]> git.lizzy.rs Git - irrlicht.git/blob - include/IColladaMeshWriter.h
Prepare GUI for IME support
[irrlicht.git] / include / IColladaMeshWriter.h
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
4 \r
5 #ifndef __IRR_I_COLLADA_MESH_WRITER_H_INCLUDED__\r
6 #define __IRR_I_COLLADA_MESH_WRITER_H_INCLUDED__\r
7 \r
8 #include "IMeshWriter.h"\r
9 #include "ISceneNode.h"\r
10 #include "IAnimatedMesh.h"\r
11 #include "SMaterial.h"\r
12 \r
13 namespace irr\r
14 {\r
15 namespace io\r
16 {\r
17         class IWriteFile;\r
18 } // end namespace io\r
19 \r
20 namespace scene\r
21 {\r
22         //! Lighting models - more or less the way Collada categorizes materials\r
23         enum E_COLLADA_TECHNIQUE_FX\r
24         {\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
27                 ECTF_BLINN,\r
28                 //! Phong shading, default in many external renderers.\r
29                 ECTF_PHONG,\r
30                 //! diffuse shaded surface that is independent of lighting.\r
31                 ECTF_LAMBERT,\r
32                 // constantly shaded surface that is independent of lighting.\r
33                 ECTF_CONSTANT\r
34         };\r
35 \r
36         //! How to interpret the opacity in collada\r
37         enum E_COLLADA_TRANSPARENT_FX\r
38         {\r
39                 //! default - only alpha channel of color or texture is used.\r
40                 ECOF_A_ONE = 0,\r
41 \r
42                 //! Alpha values for each RGB channel of color or texture are used.\r
43                 ECOF_RGB_ZERO = 1\r
44         };\r
45 \r
46         //! Color names collada uses in it's color samplers\r
47         enum E_COLLADA_COLOR_SAMPLER\r
48         {\r
49                 ECCS_DIFFUSE,\r
50                 ECCS_AMBIENT,\r
51                 ECCS_EMISSIVE,\r
52                 ECCS_SPECULAR,\r
53                 ECCS_TRANSPARENT,\r
54                 ECCS_REFLECTIVE\r
55         };\r
56 \r
57         //! Irrlicht colors which can be mapped to E_COLLADA_COLOR_SAMPLER values\r
58         enum E_COLLADA_IRR_COLOR\r
59         {\r
60                 //! Don't write this element at all\r
61                 ECIC_NONE,\r
62 \r
63                 //! Check IColladaMeshWriterProperties for custom color\r
64                 ECIC_CUSTOM,\r
65 \r
66                 //! Use SMaterial::DiffuseColor\r
67                 ECIC_DIFFUSE,\r
68 \r
69                 //! Use SMaterial::AmbientColor\r
70                 ECIC_AMBIENT,\r
71 \r
72                 //! Use SMaterial::EmissiveColor\r
73                 ECIC_EMISSIVE,\r
74 \r
75                 //! Use SMaterial::SpecularColor\r
76                 ECIC_SPECULAR\r
77         };\r
78 \r
79         //! Control when geometry elements are created\r
80         enum E_COLLADA_GEOMETRY_WRITING\r
81         {\r
82                 //! Default - write each mesh exactly once to collada. Optimal but will not work with many tools.\r
83                 ECGI_PER_MESH,\r
84 \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
89         };\r
90 \r
91         //! Callback interface for properties which can be used to influence collada writing\r
92         class IColladaMeshWriterProperties  : public virtual IReferenceCounted\r
93         {\r
94         public:\r
95                 virtual ~IColladaMeshWriterProperties () {}\r
96 \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
99 \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
105 \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
112 \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
116 \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
120 \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
125 \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
130 \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
135 \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
139 \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
144 \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
151 \r
152         };\r
153 \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
158         */\r
159         class IColladaMeshWriterNames  : public virtual IReferenceCounted\r
160         {\r
161         public:\r
162 \r
163                 virtual ~IColladaMeshWriterNames () {}\r
164 \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
174                 */\r
175                 virtual irr::core::stringc nameForMesh(const scene::IMesh* mesh, int instance) = 0;\r
176 \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
183                 */\r
184                 virtual irr::core::stringc nameForNode(const scene::ISceneNode* node) = 0;\r
185 \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
196                 */\r
197                 virtual irr::core::stringc nameForMaterial(const video::SMaterial & material, int materialId, const scene::IMesh* mesh, const scene::ISceneNode* node) = 0;\r
198         };\r
199 \r
200 \r
201         //! Interface for writing meshes\r
202         class IColladaMeshWriter : public IMeshWriter\r
203         {\r
204         public:\r
205 \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
212                 {\r
213                         ParamNamesUV[0] = "U";\r
214                         ParamNamesUV[1] = "V";\r
215                 }\r
216 \r
217                 //! Destructor\r
218                 virtual ~IColladaMeshWriter()\r
219                 {\r
220                         if ( Properties )\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
228                 }\r
229 \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
233 \r
234 \r
235                 //! Set if texture information should be written\r
236                 virtual void setWriteTextures(bool write)\r
237                 {\r
238                         WriteTextures = write;\r
239                 }\r
240 \r
241                 //! Get if texture information should be written\r
242                 virtual bool getWriteTextures() const\r
243                 {\r
244                         return WriteTextures;\r
245                 }\r
246 \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
251                 */\r
252                 virtual void setWriteDefaultScene(bool write)\r
253                 {\r
254                         WriteDefaultScene = write;\r
255                 }\r
256 \r
257                 //! Get if a default scene should be written\r
258                 virtual bool getWriteDefaultScene() const\r
259                 {\r
260                         return WriteDefaultScene;\r
261                 }\r
262 \r
263                 //! Sets ambient color of the scene to write\r
264                 virtual void setAmbientLight(const video::SColorf &ambientColor)\r
265                 {\r
266                         AmbientLight = ambientColor;\r
267                 }\r
268 \r
269                 //! Return ambient light of the scene which is written\r
270                 virtual video::SColorf getAmbientLight() const\r
271                 {\r
272                         return AmbientLight;\r
273                 }\r
274 \r
275                 //! Set the unit distances for all elements and objects\r
276                 /**\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
280                 {\r
281                         UnitMeter = meter;\r
282                         UnitName = name;\r
283                 }\r
284 \r
285                 //! Return real world meters to use per unit for all elements and objects\r
286                 virtual irr::f32 getUnitMeter() const\r
287                 {\r
288                         return UnitMeter;\r
289                 }\r
290 \r
291                 //! Return name to use for distance units. Like p.E. "meter".\r
292                 virtual irr::core::stringc getUnitName() const \r
293                 {\r
294                         return UnitName;\r
295                 }\r
296 \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
304                 */\r
305                 virtual void setGeometryWriting(E_COLLADA_GEOMETRY_WRITING writeStyle)\r
306                 {\r
307                         GeometryWriting = writeStyle;\r
308                 }\r
309 \r
310                 //! Get the current style of geometry writing.\r
311                 virtual E_COLLADA_GEOMETRY_WRITING getGeometryWriting() const\r
312                 {\r
313                         return GeometryWriting;\r
314                 }\r
315 \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
323                 */\r
324                 virtual void setExportSMaterialsOnlyOnce(bool exportOnce)\r
325                 {\r
326                         ExportSMaterialOnce = exportOnce;\r
327                 }\r
328 \r
329                 virtual bool getExportSMaterialsOnlyOnce() const\r
330                 {\r
331                         return ExportSMaterialOnce;\r
332                 }\r
333 \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
338                 {\r
339                         if ( p == Properties )\r
340                                 return;\r
341                         if ( p )\r
342                                 p->grab();\r
343                         if ( Properties )\r
344                                 Properties->drop();\r
345                         Properties = p;\r
346                 }\r
347 \r
348                 //! Get properties which are currently used.\r
349                 virtual IColladaMeshWriterProperties * getProperties() const\r
350                 {\r
351                         return Properties;\r
352                 }\r
353 \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
357                 {\r
358                         return DefaultProperties;\r
359                 }\r
360 \r
361                 //! Install a generator to create custom names on export.\r
362                 virtual void setNameGenerator(IColladaMeshWriterNames * nameGenerator)\r
363                 {\r
364                         if ( nameGenerator == NameGenerator )\r
365                                 return;\r
366                         if ( nameGenerator )\r
367                                 nameGenerator->grab();\r
368                         if ( NameGenerator )\r
369                                 NameGenerator->drop();\r
370                         NameGenerator = nameGenerator;\r
371                 }\r
372 \r
373                 //! Get currently used name generator\r
374                 virtual IColladaMeshWriterNames * getNameGenerator() const\r
375                 {\r
376                         return NameGenerator;\r
377                 }\r
378 \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
382                 {\r
383                         return DefaultNameGenerator;\r
384                 }\r
385 \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
389 \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
395 \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
402                 */\r
403                 void SetParamNamesUV(const core::stringc& u, const core::stringc& v)\r
404                 {\r
405                         ParamNamesUV[0] = u;\r
406                         ParamNamesUV[1] = v;\r
407                 }\r
408 \r
409 \r
410         protected:\r
411                 // NOTE: You usually should also call setProperties with the same parameter when using setDefaultProperties\r
412                 virtual void setDefaultProperties(IColladaMeshWriterProperties * p)\r
413                 {\r
414                         if ( p == DefaultProperties )\r
415                                 return;\r
416                         if ( p )\r
417                                 p->grab();\r
418                         if ( DefaultProperties )\r
419                                 DefaultProperties->drop();\r
420                         DefaultProperties = p;\r
421                 }\r
422 \r
423                 // NOTE: You usually should also call setNameGenerator with the same parameter when using setDefaultProperties\r
424                 virtual void setDefaultNameGenerator(IColladaMeshWriterNames * p)\r
425                 {\r
426                         if ( p == DefaultNameGenerator )\r
427                                 return;\r
428                         if ( p )\r
429                                 p->grab();\r
430                         if ( DefaultNameGenerator )\r
431                                 DefaultNameGenerator->drop();\r
432                         DefaultNameGenerator = p;\r
433                 }\r
434 \r
435         protected:\r
436                 irr::core::stringc ParamNamesUV[2];\r
437 \r
438         private:\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
450         };\r
451 \r
452 \r
453 } // end namespace\r
454 } // end namespace\r
455 \r
456 #endif\r