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 __C_COLLADA_MESH_FILE_LOADER_H_INCLUDED__ 6 #define __C_COLLADA_MESH_FILE_LOADER_H_INCLUDED__ 7 8 #include "IMeshLoader.h" 9 #include "IFileSystem.h" 10 #include "IVideoDriver.h" 11 #include "irrString.h" 12 #include "SMesh.h" 13 #include "SMeshBuffer.h" 14 #include "ISceneManager.h" 15 #include "irrMap.h" 16 #include "CAttributes.h" 17 18 namespace irr 19 { 20 namespace scene 21 { 22 23 #ifdef _DEBUG 24 //#define COLLADA_READER_DEBUG 25 #endif 26 27 class IColladaPrefab; 28 29 enum ECOLLADA_PARAM_NAME 30 { 31 ECPN_COLOR = 0, 32 ECPN_AMBIENT, 33 ECPN_DIFFUSE, 34 ECPN_SPECULAR, 35 ECPN_SHININESS, 36 ECPN_TRANSPARENCY, 37 ECPN_YFOV, 38 ECPN_ZNEAR, 39 ECPN_ZFAR, 40 41 ECPN_COUNT 42 }; 43 44 enum ECOLLADA_PARAM_TYPE 45 { 46 ECPT_FLOAT = 0, 47 ECPT_FLOAT2, 48 ECPT_FLOAT3, 49 ECPT_FLOAT4, 50 51 ECPT_COUNT 52 }; 53 54 //! Collada Parameter 55 struct SColladaParam 56 { SColladaParamSColladaParam57 SColladaParam() 58 : Name(ECPN_COUNT), Type(ECPT_COUNT) 59 { 60 for (int i=0; i<4; ++i) Floats[i] = 0; 61 } 62 63 ECOLLADA_PARAM_NAME Name; 64 ECOLLADA_PARAM_TYPE Type; 65 66 f32 Floats[4]; 67 }; 68 69 enum ECOLLADA_INPUT_SEMANTIC 70 { 71 ECIS_POSITION = 0, 72 ECIS_VERTEX, 73 ECIS_NORMAL, 74 ECIS_TEXCOORD, 75 ECIS_UV, 76 ECIS_TANGENT, 77 ECIS_IMAGE, 78 ECIS_TEXTURE, 79 80 ECIS_COUNT 81 }; 82 83 //! Collada Input 84 struct SColladaInput 85 { SColladaInputSColladaInput86 SColladaInput() 87 : Semantic(ECIS_COUNT), Data(0), Offset(0), Set(0), Stride(1) 88 { 89 } 90 91 ECOLLADA_INPUT_SEMANTIC Semantic; 92 core::stringc Source; 93 f32* Data; 94 u32 Offset; 95 u32 Set; 96 u32 Stride; 97 }; 98 99 //! Collada images 100 struct SColladaImage 101 { 102 core::stringc Id; 103 core::stringc Source; 104 core::dimension2du Dimension; 105 bool SourceIsFilename; 106 }; 107 108 109 //! Collada texture 110 struct SColladaTexture 111 { 112 video::ITexture* Texture; 113 core::stringc Id; 114 }; 115 116 117 //! Collada material 118 struct SColladaMaterial 119 { 120 video::SMaterial Mat; 121 core::stringc Id; 122 core::stringc InstanceEffectId; 123 f32 Transparency; 124 125 inline bool operator< (const SColladaMaterial & other) const 126 { 127 return Id < other.Id; 128 } 129 }; 130 131 //! Collada effect (materials, shaders, and programs) 132 struct SColladaEffect 133 { 134 core::stringc Id; 135 f32 Transparency; 136 core::array<core::stringc> Textures; 137 video::SMaterial Mat; 138 // TODO: Parameters looks somewhat lazy workaround, I think we should really read all parameters correct. 139 io::IAttributes * Parameters; 140 141 inline bool operator< (const SColladaEffect & other) const 142 { 143 return Id < other.Id; 144 } 145 }; 146 147 148 struct SNumberArray // for storing float and int arrays 149 { 150 core::stringc Name; 151 core::array<f32> Data; 152 }; 153 154 struct SAccessor 155 { SAccessorSAccessor156 SAccessor() 157 : Count(0), Offset(0), Stride(1) {} 158 // I don't store the source of the accessor here because I assume 159 // it to use the array of the source this accessor is located in. 160 161 int Count; 162 int Offset; 163 int Stride; 164 165 core::array<SColladaParam> Parameters; // parameters defining the accessor 166 }; 167 168 struct SSource 169 { 170 core::stringc Id; 171 SNumberArray Array; 172 core::array<SAccessor> Accessors; 173 }; 174 175 class CScenePrefab; 176 177 //! Meshloader capable of loading COLLADA meshes and scene descriptions into Irrlicht. 178 class CColladaFileLoader : public IMeshLoader 179 { 180 public: 181 182 //! Constructor 183 CColladaFileLoader(scene::ISceneManager* smgr, io::IFileSystem* fs); 184 185 //! destructor 186 virtual ~CColladaFileLoader(); 187 188 //! returns true if the file maybe is able to be loaded by this class 189 //! based on the file extension (e.g. ".cob") 190 virtual bool isALoadableFileExtension(const io::path& filename) const; 191 192 //! creates/loads an animated mesh from the file. 193 //! \return Pointer to the created mesh. Returns 0 if loading failed. 194 //! If you no longer need the mesh, you should call IAnimatedMesh::drop(). 195 //! See IReferenceCounted::drop() for more information. 196 virtual IAnimatedMesh* createMesh(io::IReadFile* file); 197 198 private: 199 200 //! skips an (unknown) section in the collada document 201 void skipSection(io::IXMLReaderUTF8* reader, bool reportSkipping); 202 203 //! reads the <COLLADA> section and its content 204 void readColladaSection(io::IXMLReaderUTF8* reader); 205 206 //! reads a <library> section and its content 207 void readLibrarySection(io::IXMLReaderUTF8* reader); 208 209 //! reads a <visual_scene> element and stores it as a prefab 210 void readVisualScene(io::IXMLReaderUTF8* reader); 211 212 //! reads a <scene> section and its content 213 void readSceneSection(io::IXMLReaderUTF8* reader); 214 215 //! reads a <asset> section and its content 216 void readAssetSection(io::IXMLReaderUTF8* reader); 217 218 //! reads a <node> section and its content 219 //! if a prefab pointer is passed the nodes are created as scene prefabs children of that prefab 220 void readNodeSection(io::IXMLReaderUTF8* reader, scene::ISceneNode* parent, CScenePrefab* p=0); 221 222 //! reads a <lookat> element and its content and creates a matrix from it 223 core::matrix4 readLookAtNode(io::IXMLReaderUTF8* reader); 224 225 //! reads a <matrix> element and its content and creates a matrix from it 226 core::matrix4 readMatrixNode(io::IXMLReaderUTF8* reader); 227 228 //! reads a <perspective> element and its content and creates a matrix from it 229 core::matrix4 readPerspectiveNode(io::IXMLReaderUTF8* reader); 230 231 //! reads a <rotate> element and its content and creates a matrix from it 232 core::matrix4 readRotateNode(io::IXMLReaderUTF8* reader); 233 234 //! reads a <skew> element and its content and creates a matrix from it 235 core::matrix4 readSkewNode(io::IXMLReaderUTF8* reader); 236 237 //! reads a <boundingbox> element and its content and stores it in bbox 238 void readBboxNode(io::IXMLReaderUTF8* reader, core::aabbox3df& bbox); 239 240 //! reads a <scale> element and its content and creates a matrix from it 241 core::matrix4 readScaleNode(io::IXMLReaderUTF8* reader); 242 243 //! reads a <translate> element and its content and creates a matrix from it 244 core::matrix4 readTranslateNode(io::IXMLReaderUTF8* reader); 245 246 //! reads a <color> element 247 video::SColorf readColorNode(io::IXMLReaderUTF8* reader); 248 249 //! reads a <float> element 250 f32 readFloatNode(io::IXMLReaderUTF8* reader); 251 252 //! reads a <instance> node 253 void readInstanceNode(io::IXMLReaderUTF8* reader, 254 scene::ISceneNode* parent, scene::ISceneNode** outNode, 255 CScenePrefab* p=0, const core::stringc& type=core::stringc()); 256 257 //! creates a scene node from Prefabs (with name given in 'url') 258 void instantiateNode(scene::ISceneNode* parent, scene::ISceneNode** outNode=0, 259 CScenePrefab* p=0, const core::stringc& url="", 260 const core::stringc& type=core::stringc()); 261 262 //! reads a <light> element and stores it as prefab 263 void readLightPrefab(io::IXMLReaderUTF8* reader); 264 265 //! reads a <camera> element and stores it as prefab 266 void readCameraPrefab(io::IXMLReaderUTF8* reader); 267 268 //! reads a <image> element and stores it in the image section 269 void readImage(io::IXMLReaderUTF8* reader); 270 271 //! reads a <texture> element and stores it in the texture section 272 void readTexture(io::IXMLReaderUTF8* reader); 273 274 //! reads a <material> element and stores it in the material section 275 void readMaterial(io::IXMLReaderUTF8* reader); 276 277 //! reads a <effect> element and stores it in the effects section 278 void readEffect(io::IXMLReaderUTF8* reader, SColladaEffect * effect = 0); 279 280 //! reads a <geometry> element and stores it as mesh if possible 281 void readGeometry(io::IXMLReaderUTF8* reader); 282 283 //! parses a float from a char pointer and moves the pointer to 284 //! the end of the parsed float 285 inline f32 readFloat(const c8** p); 286 287 //! parses an int from a char pointer and moves the pointer to 288 //! the end of the parsed float 289 inline s32 readInt(const c8** p); 290 291 //! places pointer to next begin of a token 292 void findNextNoneWhiteSpace(const c8** p); 293 294 //! reads floats from inside of xml element until end of xml element 295 void readFloatsInsideElement(io::IXMLReaderUTF8* reader, f32* floats, u32 count); 296 297 //! reads ints from inside of xml element until end of xml element 298 void readIntsInsideElement(io::IXMLReaderUTF8* reader, s32* ints, u32 count); 299 300 //! clears all loaded data 301 void clearData(); 302 303 //! parses all collada parameters inside an element and stores them in ColladaParameters 304 void readColladaParameters(io::IXMLReaderUTF8* reader, const core::stringc& parentName); 305 306 //! returns a collada parameter or none if not found 307 SColladaParam* getColladaParameter(ECOLLADA_PARAM_NAME name); 308 309 //! parses all collada inputs inside an element and stores them in Inputs. Reads 310 //! until first tag which is not an input tag or the end of the parent is reached 311 void readColladaInputs(io::IXMLReaderUTF8* reader, const core::stringc& parentName); 312 313 //! reads a collada input tag and adds it to the input parameter 314 void readColladaInput(io::IXMLReaderUTF8* reader, core::array<SColladaInput>& inputs); 315 316 //! returns a collada input or none if not found 317 SColladaInput* getColladaInput(ECOLLADA_INPUT_SEMANTIC input); 318 319 //! read Collada Id, uses id or name if id is missing 320 core::stringc readId(io::IXMLReaderUTF8* reader); 321 322 //! changes the XML URI into an internal id 323 void uriToId(core::stringc& str); 324 325 //! reads a polygons section and creates a mesh from it 326 void readPolygonSection(io::IXMLReaderUTF8* reader, 327 core::array<SSource>& sources, scene::SMesh* mesh, 328 const core::stringc& geometryId); 329 330 //! finds a material, possible instancing it 331 const SColladaMaterial * findMaterial(const core::stringc & materialName); 332 333 //! reads and bind materials as given by the symbol->target bind mapping 334 void readBindMaterialSection(io::IXMLReaderUTF8* reader, const core::stringc & id); 335 336 //! create an Irrlicht texture from the SColladaImage 337 video::ITexture* getTextureFromImage(core::stringc uri, SColladaEffect * effect); 338 339 //! read a parameter and value 340 void readParameter(io::IXMLReaderUTF8* reader, io::IAttributes* parameters); 341 342 scene::ISceneManager* SceneManager; 343 io::IFileSystem* FileSystem; 344 345 scene::IAnimatedMesh* DummyMesh; 346 core::stringc CurrentlyLoadingMesh; 347 348 scene::IAnimatedMesh* FirstLoadedMesh; 349 io::path FirstLoadedMeshName; 350 s32 LoadedMeshCount; 351 u32 Version; 352 bool FlipAxis; 353 354 core::array<IColladaPrefab*> Prefabs; 355 core::array<SColladaParam> ColladaParameters; 356 core::array<SColladaImage> Images; 357 core::array<SColladaTexture> Textures; 358 core::array<SColladaMaterial> Materials; 359 core::array<SColladaInput> Inputs; 360 core::array<SColladaEffect> Effects; 361 //! meshbuffer reference ("geomid/matname") -> index into MeshesToBind 362 core::map<core::stringc,u32> MaterialsToBind; 363 //! Array of buffers for each material binding 364 core::array< core::array<irr::scene::IMeshBuffer*> > MeshesToBind; 365 366 bool CreateInstances; 367 }; 368 369 370 371 //! following class is for holding and createing instances of library objects, 372 //! named prefabs in this loader. 373 class IColladaPrefab : public virtual IReferenceCounted 374 { 375 public: 376 //! creates an instance of this prefab 377 virtual scene::ISceneNode* addInstance(scene::ISceneNode* parent, 378 scene::ISceneManager* mgr) = 0; 379 380 //! returns id of this prefab 381 virtual const core::stringc& getId() = 0; 382 }; 383 384 385 } // end namespace scene 386 } // end namespace irr 387 388 #endif 389 390