1 // Copyright (C) 2002-2012 Nikolaus Gebhardt
\r
2 // This file is part of the "Irrlicht Engine".
\r
3 // For conditions of distribution and use, see copyright notice in irrlicht.h
\r
5 #ifndef __IRR_I_COLLADA_MESH_WRITER_H_INCLUDED__
\r
6 #define __IRR_I_COLLADA_MESH_WRITER_H_INCLUDED__
\r
8 #include "IMeshWriter.h"
\r
9 #include "ISceneNode.h"
\r
10 #include "IAnimatedMesh.h"
\r
11 #include "SMaterial.h"
\r
18 } // end namespace io
\r
22 //! Lighting models - more or less the way Collada categorizes materials
\r
23 enum E_COLLADA_TECHNIQUE_FX
\r
25 //! Blinn-phong which is default for opengl and dx fixed function pipelines.
\r
26 //! But several well-known renderers don't support it and prefer phong.
\r
28 //! Phong shading, default in many external renderers.
\r
30 //! diffuse shaded surface that is independent of lighting.
\r
32 // constantly shaded surface that is independent of lighting.
\r
36 //! How to interpret the opacity in collada
\r
37 enum E_COLLADA_TRANSPARENT_FX
\r
39 //! default - only alpha channel of color or texture is used.
\r
42 //! Alpha values for each RGB channel of color or texture are used.
\r
46 //! Color names collada uses in it's color samplers
\r
47 enum E_COLLADA_COLOR_SAMPLER
\r
57 //! Irrlicht colors which can be mapped to E_COLLADA_COLOR_SAMPLER values
\r
58 enum E_COLLADA_IRR_COLOR
\r
60 //! Don't write this element at all
\r
63 //! Check IColladaMeshWriterProperties for custom color
\r
66 //! Use SMaterial::DiffuseColor
\r
69 //! Use SMaterial::AmbientColor
\r
72 //! Use SMaterial::EmissiveColor
\r
75 //! Use SMaterial::SpecularColor
\r
79 //! Control when geometry elements are created
\r
80 enum E_COLLADA_GEOMETRY_WRITING
\r
82 //! Default - write each mesh exactly once to collada. Optimal but will not work with many tools.
\r
85 //! Write each mesh as often as it's used with different materials-names in the scene.
\r
86 //! Material names which are used here are created on export, so using the IColladaMeshWriterNames
\r
87 //! interface you have some control over how many geometries are written.
\r
88 ECGI_PER_MESH_AND_MATERIAL
\r
91 //! Callback interface for properties which can be used to influence collada writing
\r
92 class IColladaMeshWriterProperties : public virtual IReferenceCounted
\r
95 virtual ~IColladaMeshWriterProperties () {}
\r
97 //! Which lighting model should be used in the technique (FX) section when exporting effects (materials)
\r
98 virtual E_COLLADA_TECHNIQUE_FX getTechniqueFx(const video::SMaterial& material) const = 0;
\r
100 //! Which texture index should be used when writing the texture of the given sampler color.
\r
101 /** \return the index to the texture-layer or -1 if that texture should never be exported
\r
102 Note: for ECCS_TRANSPARENT by default the alpha channel is used, if you want to use RGB you have to set
\r
103 also the ECOF_RGB_ZERO flag in getTransparentFx. */
\r
104 virtual s32 getTextureIdx(const video::SMaterial & material, E_COLLADA_COLOR_SAMPLER cs) const = 0;
\r
106 //! Return which color from Irrlicht should be used for the color requested by collada
\r
107 /** Note that collada allows exporting either texture or color, not both.
\r
108 So color mapping is only checked if we have no valid texture already.
\r
109 By default we try to return best fits when possible. For example ECCS_DIFFUSE is mapped to ECIC_DIFFUSE.
\r
110 When ECIC_CUSTOM is returned then the result of getCustomColor will be used. */
\r
111 virtual E_COLLADA_IRR_COLOR getColorMapping(const video::SMaterial & material, E_COLLADA_COLOR_SAMPLER cs) const = 0;
\r
113 //! Return custom colors for certain color types requested by collada.
\r
114 /** Only used when getColorMapping returns ECIC_CUSTOM for the same parameters. */
\r
115 virtual video::SColor getCustomColor(const video::SMaterial & material, E_COLLADA_COLOR_SAMPLER cs) const = 0;
\r
117 //! Return the transparence color interpretation.
\r
118 /** Not this is only about ECCS_TRANSPARENT and does not affect getTransparency. */
\r
119 virtual E_COLLADA_TRANSPARENT_FX getTransparentFx(const video::SMaterial& material) const = 0;
\r
121 //! Transparency value for that material.
\r
122 /** This value is additional to transparent settings, if both are set they will be multiplicated.
\r
123 \return 1.0 for fully transparent, 0.0 for not transparent and not written at all when < 0.f */
\r
124 virtual f32 getTransparency(const video::SMaterial& material) const = 0;
\r
126 //! Reflectivity value for that material
\r
127 /** The amount of perfect mirror reflection to be added to the reflected light
\r
128 \return 0.0 - 1.0 for reflectivity and element is not written at all when < 0.f */
\r
129 virtual f32 getReflectivity(const video::SMaterial& material) const = 0;
\r
131 //! Return index of refraction for that material
\r
132 /** By default we don't write that.
\r
133 \return a value greater equal 0.f to write \<index_of_refraction\> when it is lesser than 0 nothing will be written */
\r
134 virtual f32 getIndexOfRefraction(const video::SMaterial& material) const = 0;
\r
136 //! Should node be used in scene export? (only needed for scene-writing, ignored in mesh-writing)
\r
137 //! By default all visible nodes are exported.
\r
138 virtual bool isExportable(const irr::scene::ISceneNode * node) const = 0;
\r
140 //! Return the mesh for the given node. If it has no mesh or shouldn't export it's mesh
\r
141 //! you can return 0 in which case only the transformation matrix of the node will be used.
\r
142 // TODO: Function is not const because there is no const getMesh() function for several Irrlicht nodes.
\r
143 virtual IMesh* getMesh(irr::scene::ISceneNode * node) = 0;
\r
145 //! Return if the node has it's own material overwriting the mesh-materials
\r
146 /** Usually true except for mesh-nodes which have isReadOnlyMaterials set.
\r
147 This is mostly important for naming (as ISceneNode::getMaterial() already returns the correct material).
\r
148 You have to override it when exporting custom scenenodes with own materials.
\r
149 \return true => The node's own material is used, false => ignore node material and use the one from the mesh */
\r
150 virtual bool useNodeMaterial(const scene::ISceneNode* node) const = 0;
\r
154 //! Callback interface to use custom names on collada writing.
\r
155 /** You can either modify names and id's written to collada or you can use
\r
156 this interface to just find out which names are used on writing.
\r
157 Names are often used later as xs:anyURI, so avoid whitespace, '#' and '%' in the names.
\r
159 class IColladaMeshWriterNames : public virtual IReferenceCounted
\r
163 virtual ~IColladaMeshWriterNames () {}
\r
165 //! Return a unique name for the given mesh
\r
166 /** Note that names really must be unique here per mesh-pointer, so
\r
167 mostly it's a good idea to return the nameForMesh from
\r
168 IColladaMeshWriter::getDefaultNameGenerator(). Also names must follow
\r
169 the xs:NCName standard to be valid, you can run them through
\r
170 IColladaMeshWriter::toNCName to ensure that.
\r
171 \param mesh Pointer to the mesh which needs a name
\r
172 \param instance When E_COLLADA_GEOMETRY_WRITING is not ECGI_PER_MESH then
\r
173 several instances of the same mesh can be written and this counts them.
\r
175 virtual irr::core::stringc nameForMesh(const scene::IMesh* mesh, int instance) = 0;
\r
177 //! Return a unique name for the given node
\r
178 /** Note that names really must be unique here per node-pointer, so
\r
179 mostly it's a good idea to return the nameForNode from
\r
180 IColladaMeshWriter::getDefaultNameGenerator(). Also names must follow
\r
181 the xs:NCName standard to be valid, you can run them through
\r
182 IColladaMeshWriter::toNCName to ensure that.
\r
184 virtual irr::core::stringc nameForNode(const scene::ISceneNode* node) = 0;
\r
186 //! Return a name for the material
\r
187 /** There is one material created in the writer for each unique name.
\r
188 So you can use this to control the number of materials which get written.
\r
189 For example Irrlicht does by default write one material for each material
\r
190 instanced by a node. So if you know that in your application material
\r
191 instances per node are identical between different nodes you can reduce
\r
192 the number of exported materials using that knowledge by using identical
\r
193 names for such shared materials.
\r
194 Names must follow the xs:NCName standard to be valid, you can run them
\r
195 through IColladaMeshWriter::toNCName to ensure that.
\r
197 virtual irr::core::stringc nameForMaterial(const video::SMaterial & material, int materialId, const scene::IMesh* mesh, const scene::ISceneNode* node) = 0;
\r
201 //! Interface for writing meshes
\r
202 class IColladaMeshWriter : public IMeshWriter
\r
206 IColladaMeshWriter()
\r
207 : Properties(0), DefaultProperties(0), NameGenerator(0), DefaultNameGenerator(0)
\r
208 , WriteTextures(true), WriteDefaultScene(true), ExportSMaterialOnce(true)
\r
209 , AmbientLight(0.f, 0.f, 0.f, 1.f)
\r
210 , UnitMeter(1.f), UnitName("meter")
\r
211 , GeometryWriting(ECGI_PER_MESH)
\r
213 ParamNamesUV[0] = "U";
\r
214 ParamNamesUV[1] = "V";
\r
218 virtual ~IColladaMeshWriter()
\r
221 Properties->drop();
\r
222 if ( DefaultProperties )
\r
223 DefaultProperties->drop();
\r
224 if ( NameGenerator )
\r
225 NameGenerator->drop();
\r
226 if ( DefaultNameGenerator )
\r
227 DefaultNameGenerator->drop();
\r
230 //! writes a scene starting with the given node
\r
231 //\param writeRoot: 0 = no, 1=yes unless root is scenemanager, 2=yes
\r
232 virtual bool writeScene(io::IWriteFile* file, scene::ISceneNode* root, int writeRoot=1) = 0;
\r
235 //! Set if texture information should be written
\r
236 virtual void setWriteTextures(bool write)
\r
238 WriteTextures = write;
\r
241 //! Get if texture information should be written
\r
242 virtual bool getWriteTextures() const
\r
244 return WriteTextures;
\r
247 //! Set if a default scene should be written when writing meshes.
\r
248 /** Many collada readers fail to read a mesh if the collada files doesn't contain a scene as well.
\r
249 The scene is doing an instantiation of the mesh.
\r
250 When using writeScene this flag is ignored (as we have scene there already)
\r
252 virtual void setWriteDefaultScene(bool write)
\r
254 WriteDefaultScene = write;
\r
257 //! Get if a default scene should be written
\r
258 virtual bool getWriteDefaultScene() const
\r
260 return WriteDefaultScene;
\r
263 //! Sets ambient color of the scene to write
\r
264 virtual void setAmbientLight(const video::SColorf &ambientColor)
\r
266 AmbientLight = ambientColor;
\r
269 //! Return ambient light of the scene which is written
\r
270 virtual video::SColorf getAmbientLight() const
\r
272 return AmbientLight;
\r
275 //! Set the unit distances for all elements and objects
\r
277 \param meter: Real-world meters to use per unit. Default 1 unit = 1 meter. For 1 unit = 1cm you would set to 0.01
\r
278 \param name: Name to use for distance unit. Default is "meter". */
\r
279 virtual void setUnit(irr::f32 meter, const irr::core::stringc& name)
\r
285 //! Return real world meters to use per unit for all elements and objects
\r
286 virtual irr::f32 getUnitMeter() const
\r
291 //! Return name to use for distance units. Like p.E. "meter".
\r
292 virtual irr::core::stringc getUnitName() const
\r
297 //! Control when and how often a mesh is written
\r
298 /** Optimally ECGI_PER_MESH would be always sufficient - writing geometry once per mesh.
\r
299 Unfortunately many tools (at the time of writing this nearly all of them) have trouble
\r
300 on import when different materials are used per node. So when you override materials
\r
301 per node and importing the resulting collada has materials problems in other tools try
\r
302 using other values here.
\r
303 \param writeStyle One of the E_COLLADA_GEOMETRY_WRITING settings.
\r
305 virtual void setGeometryWriting(E_COLLADA_GEOMETRY_WRITING writeStyle)
\r
307 GeometryWriting = writeStyle;
\r
310 //! Get the current style of geometry writing.
\r
311 virtual E_COLLADA_GEOMETRY_WRITING getGeometryWriting() const
\r
313 return GeometryWriting;
\r
316 //! Make certain there is only one collada material generated per Irrlicht material
\r
317 /** Checks before creating a collada material-name if an identical
\r
318 irr:::video::SMaterial has been exported already. If so don't export it with
\r
319 another name. This is set by default and leads to way smaller .dae files.
\r
320 Note that if you need to disable this flag for some reason you can still
\r
321 get a similar effect using the IColladaMeshWriterNames::nameForMaterial
\r
322 by returning identical names for identical materials there.
\r
324 virtual void setExportSMaterialsOnlyOnce(bool exportOnce)
\r
326 ExportSMaterialOnce = exportOnce;
\r
329 virtual bool getExportSMaterialsOnlyOnce() const
\r
331 return ExportSMaterialOnce;
\r
334 //! Set properties to use by the meshwriter instead of it's default properties.
\r
335 /** Overloading properties with an own class allows modifying the writing process in certain ways.
\r
336 By default properties are set to the DefaultProperties. */
\r
337 virtual void setProperties(IColladaMeshWriterProperties * p)
\r
339 if ( p == Properties )
\r
344 Properties->drop();
\r
348 //! Get properties which are currently used.
\r
349 virtual IColladaMeshWriterProperties * getProperties() const
\r
354 //! Return the original default properties of the writer.
\r
355 /** You can use this pointer in your own properties to access and return default values. */
\r
356 IColladaMeshWriterProperties * getDefaultProperties() const
\r
358 return DefaultProperties;
\r
361 //! Install a generator to create custom names on export.
\r
362 virtual void setNameGenerator(IColladaMeshWriterNames * nameGenerator)
\r
364 if ( nameGenerator == NameGenerator )
\r
366 if ( nameGenerator )
\r
367 nameGenerator->grab();
\r
368 if ( NameGenerator )
\r
369 NameGenerator->drop();
\r
370 NameGenerator = nameGenerator;
\r
373 //! Get currently used name generator
\r
374 virtual IColladaMeshWriterNames * getNameGenerator() const
\r
376 return NameGenerator;
\r
379 //! Return the original default name generator of the writer.
\r
380 /** You can use this pointer in your own generator to access and return default values. */
\r
381 IColladaMeshWriterNames * getDefaultNameGenerator() const
\r
383 return DefaultNameGenerator;
\r
386 //! Restrict the characters of oldString a set of allowed characters in xs:NCName and add the prefix.
\r
387 /** A tool function to help when using a custom name generator to generative valid names for collada names and id's. */
\r
388 virtual irr::core::stringc toNCName(const irr::core::stringc& oldString, const irr::core::stringc& prefix=irr::core::stringc("_NC_")) const = 0;
\r
390 //! After export you can find out which name had been used for writing the geometry for this node.
\r
391 /** The name comes from IColladaMeshWriterNames::nameForMesh, but you can't access the node there.
\r
392 \return Either a pointer to the name or NULL */
\r
393 // TODO: Function is not const because there is no const getMesh() function for several Irrlicht nodes.
\r
394 virtual const irr::core::stringc* findGeometryNameForNode(ISceneNode* node) = 0;
\r
396 //! Change param name used for UV's.
\r
397 /** Param names for UV's have a name. By default it's "U" and "V".
\r
398 Usually it doesn't matter as names are optional in Collada anyway.
\r
399 But unfortunately some tools insist on specific names.
\r
400 So if "U", "V" does not work then try to export by setting this to "S", "T".
\r
401 One tool which insists on "S", "T" is for example SketchUp.
\r
403 void SetParamNamesUV(const core::stringc& u, const core::stringc& v)
\r
405 ParamNamesUV[0] = u;
\r
406 ParamNamesUV[1] = v;
\r
411 // NOTE: You usually should also call setProperties with the same parameter when using setDefaultProperties
\r
412 virtual void setDefaultProperties(IColladaMeshWriterProperties * p)
\r
414 if ( p == DefaultProperties )
\r
418 if ( DefaultProperties )
\r
419 DefaultProperties->drop();
\r
420 DefaultProperties = p;
\r
423 // NOTE: You usually should also call setNameGenerator with the same parameter when using setDefaultProperties
\r
424 virtual void setDefaultNameGenerator(IColladaMeshWriterNames * p)
\r
426 if ( p == DefaultNameGenerator )
\r
430 if ( DefaultNameGenerator )
\r
431 DefaultNameGenerator->drop();
\r
432 DefaultNameGenerator = p;
\r
436 irr::core::stringc ParamNamesUV[2];
\r
439 IColladaMeshWriterProperties * Properties;
\r
440 IColladaMeshWriterProperties * DefaultProperties;
\r
441 IColladaMeshWriterNames * NameGenerator;
\r
442 IColladaMeshWriterNames * DefaultNameGenerator;
\r
443 bool WriteTextures;
\r
444 bool WriteDefaultScene;
\r
445 bool ExportSMaterialOnce;
\r
446 video::SColorf AmbientLight;
\r
447 irr::f32 UnitMeter;
\r
448 irr::core::stringc UnitName;
\r
449 E_COLLADA_GEOMETRY_WRITING GeometryWriting;
\r