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