1 // Copyright (C) 2002-2012 Nikolaus Gebhardt
2 // This file is part of the "Irrlicht Engine".
3 // For conditions of distribution and use, see copyright notice in irrlicht.h
4 
5 #ifndef __IRR_C_COLLADA_MESH_WRITER_H_INCLUDED__
6 #define __IRR_C_COLLADA_MESH_WRITER_H_INCLUDED__
7 
8 #include "IColladaMeshWriter.h"
9 #include "S3DVertex.h"
10 #include "irrMap.h"
11 #include "IVideoDriver.h"
12 
13 namespace irr
14 {
15 namespace io
16 {
17 	class IXMLWriter;
18 	class IFileSystem;
19 }
20 
21 namespace scene
22 {
23 	//! Callback interface for properties which can be used to influence collada writing
24 	// (Implementer note: keep namespace labels here to make it easier for users copying this one)
25 	class CColladaMeshWriterProperties  : public virtual IColladaMeshWriterProperties
26 	{
27 	public:
28 		//! Which lighting model should be used in the technique (FX) section when exporting effects (materials)
29 		virtual irr::scene::E_COLLADA_TECHNIQUE_FX getTechniqueFx(const irr::video::SMaterial& material) const;
30 
31 		//! Which texture index should be used when writing the texture of the given sampler color.
32 		virtual irr::s32 getTextureIdx(const irr::video::SMaterial & material, irr::scene::E_COLLADA_COLOR_SAMPLER cs) const;
33 
34 		//! Return which color from Irrlicht should be used for the color requested by collada
35 		virtual irr::scene::E_COLLADA_IRR_COLOR getColorMapping(const irr::video::SMaterial & material, irr::scene::E_COLLADA_COLOR_SAMPLER cs) const;
36 
37 		//! Return custom colors for certain color types requested by collada.
38 		virtual irr::video::SColor getCustomColor(const irr::video::SMaterial & material, irr::scene::E_COLLADA_COLOR_SAMPLER cs) const;
39 
40 		//! Return the settings for transparence
41 		virtual irr::scene::E_COLLADA_TRANSPARENT_FX getTransparentFx(const irr::video::SMaterial& material) const;
42 
43 		//! Transparency value for that material.
44 		virtual irr::f32 getTransparency(const irr::video::SMaterial& material) const;
45 
46 		//! Reflectivity value for that material
47 		virtual irr::f32 getReflectivity(const irr::video::SMaterial& material) const;
48 
49 		//! Return index of refraction for that material
50 		virtual irr::f32 getIndexOfRefraction(const irr::video::SMaterial& material) const;
51 
52 		//! Should node be used in scene export? By default all visible nodes are exported.
53 		virtual bool isExportable(const irr::scene::ISceneNode * node) const;
54 
55 		//! Return the mesh for the given nod. If it has no mesh or shouldn't export it's mesh return 0.
56 		virtual irr::scene::IMesh* getMesh(irr::scene::ISceneNode * node);
57 
58 		//! Return if the node has it's own material overwriting the mesh-materials
59 		virtual bool useNodeMaterial(const scene::ISceneNode* node) const;
60 	};
61 
62 	class CColladaMeshWriterNames  : public virtual IColladaMeshWriterNames
63 	{
64 	public:
65 		CColladaMeshWriterNames(IColladaMeshWriter * writer);
66 		virtual irr::core::stringw nameForMesh(const scene::IMesh* mesh, int instance);
67 		virtual irr::core::stringw nameForNode(const scene::ISceneNode* node);
68 		virtual irr::core::stringw nameForMaterial(const video::SMaterial & material, int materialId, const scene::IMesh* mesh, const scene::ISceneNode* node);
69 	protected:
70 		irr::core::stringw nameForPtr(const void* ptr) const;
71 	private:
72 		IColladaMeshWriter * ColladaMeshWriter;
73 	};
74 
75 
76 
77 //! class to write meshes, implementing a COLLADA (.dae, .xml) writer
78 /** This writer implementation has been originally developed for irrEdit and then
79 merged out to the Irrlicht Engine */
80 class CColladaMeshWriter : public IColladaMeshWriter
81 {
82 public:
83 
84 	CColladaMeshWriter(ISceneManager * smgr, video::IVideoDriver* driver, io::IFileSystem* fs);
85 	virtual ~CColladaMeshWriter();
86 
87 	//! Returns the type of the mesh writer
88 	virtual EMESH_WRITER_TYPE getType() const;
89 
90 	//! writes a scene starting with the given node
91 	virtual bool writeScene(io::IWriteFile* file, scene::ISceneNode* root);
92 
93 	//! writes a mesh
94 	virtual bool writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32 flags=EMWF_NONE);
95 
96 	// Restrict the characters of oldString a set of allowed characters in xs::NCName and add the prefix.
97 	virtual irr::core::stringw toNCName(const irr::core::stringw& oldString, const irr::core::stringw& prefix=irr::core::stringw(L"_NC_")) const;
98 
99 protected:
100 
101 	void reset();
102 	bool hasSecondTextureCoordinates(video::E_VERTEX_TYPE type) const;
103 	void writeUv(const irr::core::vector2df& vec);
104 	void writeVector(const irr::core::vector2df& vec);
105 	void writeVector(const irr::core::vector3df& vec);
106 	void writeColor(const irr::video::SColorf& colorf, bool writeAlpha=true);
107 	inline irr::core::stringw toString(const irr::video::ECOLOR_FORMAT format) const;
108 	inline irr::core::stringw toString(const irr::video::E_TEXTURE_CLAMP clamp) const;
109 	inline irr::core::stringw toString(const irr::scene::E_COLLADA_TRANSPARENT_FX opaque) const;
110 	inline irr::core::stringw toRef(const irr::core::stringw& source) const;
111 	bool isCamera(const scene::ISceneNode* node) const;
112 	irr::core::stringw nameForMesh(const scene::IMesh* mesh, int instance) const;
113 	irr::core::stringw nameForNode(const scene::ISceneNode* node) const;
114 	irr::core::stringw nameForMaterial(const video::SMaterial & material, int materialId, const scene::IMesh* mesh, const scene::ISceneNode* node);
115 	irr::core::stringw nameForMaterialSymbol(const scene::IMesh* mesh, int materialId) const;
116 	irr::core::stringw findCachedMaterialName(const irr::video::SMaterial& material) const;
117 	irr::core::stringw minTexfilterToString(bool bilinear, bool trilinear) const;
118 	irr::core::stringw magTexfilterToString(bool bilinear, bool trilinear) const;
119 	irr::core::stringw pathToURI(const irr::io::path& path) const;
120 	inline bool isXmlNameStartChar(wchar_t c) const;
121 	inline bool isXmlNameChar(wchar_t c) const;
122 	s32 getCheckedTextureIdx(const video::SMaterial & material, E_COLLADA_COLOR_SAMPLER cs);
123 	video::SColor getColorMapping(const video::SMaterial & material, E_COLLADA_COLOR_SAMPLER cs, E_COLLADA_IRR_COLOR colType);
124 	void writeAsset();
125 	void makeMeshNames(irr::scene::ISceneNode * node);
126 	void writeNodeMaterials(irr::scene::ISceneNode * node);
127 	void writeNodeEffects(irr::scene::ISceneNode * node);
128 	void writeNodeLights(irr::scene::ISceneNode * node);
129 	void writeNodeCameras(irr::scene::ISceneNode * node);
130 	void writeAllMeshGeometries();
131 	void writeSceneNode(irr::scene::ISceneNode * node);
132 	void writeMeshMaterials(scene::IMesh* mesh, irr::core::array<irr::core::stringw> * materialNamesOut=0);
133 	void writeMeshEffects(scene::IMesh* mesh);
134 	void writeMaterialEffect(const irr::core::stringw& materialname, const video::SMaterial & material);
135 	void writeMeshGeometry(const irr::core::stringw& meshname, scene::IMesh* mesh);
136 	void writeMeshInstanceGeometry(const irr::core::stringw& meshname, scene::IMesh* mesh, scene::ISceneNode* node=0);
137 	void writeMaterial(const irr::core::stringw& materialname);
138 	void writeLightInstance(const irr::core::stringw& lightName);
139 	void writeCameraInstance(const irr::core::stringw& cameraName);
140 	void writeLibraryImages();
141 	void writeColorFx(const video::SMaterial & material, const wchar_t * colorname, E_COLLADA_COLOR_SAMPLER cs, const wchar_t* attr1Name=0, const wchar_t* attr1Value=0);
142 	void writeAmbientLightElement(const video::SColorf & col);
143 	void writeColorElement(const video::SColor & col, bool writeAlpha=true);
144 	void writeColorElement(const video::SColorf & col, bool writeAlpha=true);
145 	void writeTextureSampler(s32 textureIdx);
146 	void writeFxElement(const video::SMaterial & material, E_COLLADA_TECHNIQUE_FX techFx);
147 	void writeNode(const wchar_t * nodeName, const wchar_t * content);
148 	void writeFloatElement(irr::f32 value);
149 	void writeRotateElement(const irr::core::vector3df& axis, irr::f32 angle);
150 	void writeScaleElement(const irr::core::vector3df& scale);
151 	void writeTranslateElement(const irr::core::vector3df& translate);
152 	void writeMatrixElement(const irr::core::matrix4& matrix);
153 
154 	struct SComponentGlobalStartPos
155 	{
SComponentGlobalStartPosSComponentGlobalStartPos156 		SComponentGlobalStartPos() : PosStartIndex(-1), PosLastIndex(-1),
157 				NormalStartIndex(-1), NormalLastIndex(-1),
158 				TCoord0StartIndex(-1), TCoord0LastIndex(-1),
159 				TCoord1StartIndex(-1), TCoord1LastIndex(-1)
160 		{ }
161 
162 		s32 PosStartIndex;
163 		s32 PosLastIndex;
164 
165 		s32 NormalStartIndex;
166 		s32 NormalLastIndex;
167 
168 		s32 TCoord0StartIndex;
169 		s32 TCoord0LastIndex;
170 
171 		s32 TCoord1StartIndex;
172 		s32 TCoord1LastIndex;
173 	};
174 
175 	io::IFileSystem* FileSystem;
176 	video::IVideoDriver* VideoDriver;
177 	io::IXMLWriter* Writer;
178 	core::array<video::ITexture*> LibraryImages;
179 	io::path Directory;
180 
181 	// Helper struct for creating geometry copies for the ECGI_PER_MESH_AND_MATERIAL settings.
182 	struct SGeometryMeshMaterials
183 	{
equalsSGeometryMeshMaterials184 		bool equals(const core::array<irr::core::stringw>& names) const
185 		{
186 			if ( names.size() != MaterialNames.size() )
187 				return false;
188 			for ( irr::u32 i=0; i<MaterialNames.size(); ++i )
189 				if ( names[i] != MaterialNames[i] )
190 					return false;
191 			return true;
192 		}
193 
194 		irr::core::stringw GeometryName;				// replacing the usual ColladaMesh::Name
195 		core::array<irr::core::stringw> MaterialNames;	// Material names exported for this instance
196 		core::array<const ISceneNode*> MaterialOwners;	// Nodes using this specific mesh-material combination
197 	};
198 
199 	// Check per mesh-ptr if stuff has been written for this mesh already
200 	struct SColladaMesh
201 	{
SColladaMeshSColladaMesh202 		SColladaMesh() : MaterialsWritten(false), EffectsWritten(false)
203 		{
204 		}
205 
findGeometryMeshMaterialsSColladaMesh206 		SGeometryMeshMaterials * findGeometryMeshMaterials(const irr::core::array<irr::core::stringw> materialNames)
207 		{
208 			for ( irr::u32 i=0; i<GeometryMeshMaterials.size(); ++i )
209 			{
210 				if ( GeometryMeshMaterials[i].equals(materialNames) )
211 					return &(GeometryMeshMaterials[i]);
212 			}
213 			return NULL;
214 		}
215 
findGeometryNameForNodeSColladaMesh216 		const irr::core::stringw& findGeometryNameForNode(const ISceneNode* node) const
217 		{
218 			if ( GeometryMeshMaterials.size() < 2 )
219 				return Name;
220 			for ( irr::u32 i=0; i<GeometryMeshMaterials.size(); ++i )
221 			{
222 				if ( GeometryMeshMaterials[i].MaterialOwners.linear_search(node)  >= 0 )
223 					return GeometryMeshMaterials[i].GeometryName;
224 			}
225 			return Name; // (shouldn't get here usually)
226 		}
227 
228 		irr::core::stringw Name;
229 		bool MaterialsWritten;	// just an optimization doing that here in addition to the MaterialsWritten map
230 		bool EffectsWritten;	// just an optimization doing that here in addition to the EffectsWritten map
231 
232 		core::array<SGeometryMeshMaterials> GeometryMeshMaterials;
233 	};
234 	typedef core::map<IMesh*, SColladaMesh>::Node MeshNode;
235 	core::map<IMesh*, SColladaMesh> Meshes;
236 
237 	// structure for the lights library
238 	struct SColladaLight
239 	{
SColladaLightSColladaLight240 		SColladaLight()	{}
241 		irr::core::stringw Name;
242 	};
243 	typedef core::map<ISceneNode*, SColladaLight>::Node LightNode;
244 	core::map<ISceneNode*, SColladaLight> LightNodes;
245 
246 	// structure for the camera library
247 	typedef core::map<ISceneNode*, irr::core::stringw>::Node CameraNode;
248 	core::map<ISceneNode*, irr::core::stringw> CameraNodes;
249 
250 	// Check per name if stuff has been written already
251 	// TODO: second parameter not needed, we just don't have a core::set class yet in Irrlicht
252 	core::map<irr::core::stringw, bool> MaterialsWritten;
253 	core::map<irr::core::stringw, bool> EffectsWritten;
254 
255 	// Cache material names
256 	struct MaterialName
257 	{
MaterialNameMaterialName258 		MaterialName(const irr::video::SMaterial & material, const irr::core::stringw& name)
259 			: Material(material), Name(name)
260 		{}
261 		irr::video::SMaterial Material;
262 		irr::core::stringw Name;
263 	};
264 	irr::core::array< MaterialName > MaterialNameCache;
265 };
266 
267 
268 } // end namespace
269 } // end namespace
270 
271 #endif
272