From 87fe99881c92ea499d7a65ff55a20a8ba4c333e4 Mon Sep 17 00:00:00 2001 From: hybrid Date: Wed, 8 Aug 2007 16:30:10 +0000 Subject: [PATCH] Added texture support for collada meshes. Fixed const parameters in MeshManipulator. git-svn-id: http://svn.code.sf.net/p/irrlicht/code/trunk@827 dfc29bdd-3216-0410-991c-e03cc46cb475 --- source/Irrlicht/CColladaFileLoader.cpp | 199 ++++++++++++++++++------- source/Irrlicht/CColladaFileLoader.h | 31 +++- source/Irrlicht/CMeshManipulator.cpp | 4 +- source/Irrlicht/CMeshManipulator.h | 4 +- 4 files changed, 182 insertions(+), 56 deletions(-) diff --git a/source/Irrlicht/CColladaFileLoader.cpp b/source/Irrlicht/CColladaFileLoader.cpp index df73263c..517729e1 100644 --- a/source/Irrlicht/CColladaFileLoader.cpp +++ b/source/Irrlicht/CColladaFileLoader.cpp @@ -34,6 +34,8 @@ namespace scene const core::stringc cameraPrefabName = "camera"; const core::stringc materialSectionName = "material"; const core::stringc geometrySectionName = "geometry"; + const core::stringc imageSectionName = "image"; + const core::stringc textureSectionName = "texture"; const core::stringc meshSectionName = "mesh"; const core::stringc sourceSectionName = "source"; @@ -56,7 +58,7 @@ namespace scene const core::stringc paramTagName = "param"; const char* const inputSemanticNames[] = {"POSITION", "VERTEX", "NORMAL", "TEXCOORD", - "UV", "TANGENT", 0}; + "UV", "TANGENT", "IMAGE", "TEXTURE", 0}; //! following class is for holding and creating instances of library objects, //! named prefabs in this loader. @@ -286,7 +288,7 @@ void CColladaFileLoader::skipSection(io::IXMLReaderUTF8* reader, bool reportSkip return; // read until we've reached the last element in this section - int tagCounter = 1; + u32 tagCounter = 1; while(tagCounter && reader->read()) { @@ -342,6 +344,12 @@ void CColladaFileLoader::readLibrarySection(io::IXMLReaderUTF8* reader) if (lightPrefabName == reader->getNodeName()) readLightPrefab(reader); else + if (imageSectionName == reader->getNodeName()) + readImage(reader); + else + if (textureSectionName == reader->getNodeName()) + readTexture(reader); + else if (materialSectionName == reader->getNodeName()) readMaterial(reader); else @@ -628,7 +636,7 @@ void CColladaFileLoader::readInstanceNode(io::IXMLReaderUTF8* reader, scene::ISc uriToId(url); if (CreateInstances) - for (int i=0; i<(int)Prefabs.size(); ++i) + for (u32 i=0; igetId()) { *outNode = Prefabs[i]->addInstance(parent, SceneManager); @@ -666,6 +674,46 @@ void CColladaFileLoader::readCameraPrefab(io::IXMLReaderUTF8* reader) } +//! reads a element and stores it in the image section +void CColladaFileLoader::readImage(io::IXMLReaderUTF8* reader) +{ + SColladaImage image; + image.Id = reader->getAttributeValue("id"); + image.Filename = reader->getAttributeValue("source"); + + // add image to list of loaded images. + Images.push_back(image); +} + + +//! reads a element and stores it in the texture section +void CColladaFileLoader::readTexture(io::IXMLReaderUTF8* reader) +{ + SColladaTexture texture; + texture.Id = reader->getAttributeValue("id"); + + if (!reader->isEmptyElement()) + { + readColladaInputs(reader, textureSectionName); + SColladaInput* input = getColladaInput(ECIS_IMAGE); + if (input) + { + core::stringc imageName = input->Source; + uriToId(imageName); + for (u32 i=0; igetTexture(Images[i].Filename.c_str()); + break; + } + } + } + + // add texture to list of loaded textures. + Textures.push_back(texture); +} + + //! reads a element and stores it in the material section void CColladaFileLoader::readMaterial(io::IXMLReaderUTF8* reader) { @@ -674,9 +722,39 @@ void CColladaFileLoader::readMaterial(io::IXMLReaderUTF8* reader) if (!reader->isEmptyElement()) { - // TODO: implement material parsing later. - // for now we only read and discard then all tags. + readColladaInputs(reader, materialSectionName); + SColladaInput* input = getColladaInput(ECIS_TEXTURE); + if (input) + { + core::stringc textureName = input->Source; + uriToId(textureName); + for (u32 i=0; iType == ECPT_FLOAT3) + material.Mat.AmbientColor = video::SColorf(p->Floats[0],p->Floats[1],p->Floats[2]).toSColor(); + p = getColladaParameter(ECPN_DIFFUSE); + if (p && p->Type == ECPT_FLOAT3) + material.Mat.DiffuseColor = video::SColorf(p->Floats[0],p->Floats[1],p->Floats[2]).toSColor(); + p = getColladaParameter(ECPN_SPECULAR); + if (p && p->Type == ECPT_FLOAT3) + material.Mat.DiffuseColor = video::SColorf(p->Floats[0],p->Floats[1],p->Floats[2]).toSColor(); + p = getColladaParameter(ECPN_SHININESS); + if (p && p->Type == ECPT_FLOAT) + material.Mat.Shininess = p->Floats[0]; +#endif } // add material to list of loaded materials. @@ -792,10 +870,13 @@ void CColladaFileLoader::readGeometry(io::IXMLReaderUTF8* reader) core::stringc data = reader->getNodeData(); const c8* p = &data[0]; - for (int i=0; i<(int)a.size(); ++i) + for (u32 i=0; i Indices; + core::array Indices; }; //! reads a polygons section and creates a mesh from it @@ -869,12 +950,21 @@ void CColladaFileLoader::readPolygonSection(io::IXMLReaderUTF8* reader, core::stringc vertexPositionSource, core::array& sources, scene::SMesh* mesh) { - core::stringc material = reader->getAttributeValue("material"); + core::stringc materialName = reader->getAttributeValue("material"); + uriToId(materialName); + video::SMaterial mat; + for (u32 i=0; igetAttributeValueAsInt("count"); core::array slots; core::array polygons; bool parsePolygonOK = false; - int inputSemanticCount = 0; + u32 inputSemanticCount = 0; // read all and if (!reader->isEmptyElement()) @@ -908,8 +998,8 @@ void CColladaFileLoader::readPolygonSection(io::IXMLReaderUTF8* reader, uriToId(sourceArrayURI); // find source array (we'll ignore acessors for this implementation) - int s; - for (s=0; s<(int)sources.size(); ++s) + u32 s; + for (s=0; sread() - if (inputSemanticCount == 0 || inputSemanticCount != (int)slots.size()) + if (inputSemanticCount == 0 || inputSemanticCount != slots.size()) return; // we cannot create the mesh if one of the input semantics wasn't found. if (!polygons.size()) @@ -981,12 +1072,12 @@ void CColladaFileLoader::readPolygonSection(io::IXMLReaderUTF8* reader, // analyze content of slots to create a fitting mesh buffer - int i; - int textureCoordSetCount = 0; - int normalSlotCount = 0; - int secondTexCoordSetIndex = -1; + u32 i; + u32 textureCoordSetCount = 0; + bool normalSlotCount = false; + u32 secondTexCoordSetIndex = 0xFFFFFFFF; - for (i=0; i<(int)slots.size(); ++i) + for (i=0; iMaterial=mat; buffer = mbuffer; - for (i=0; i<(int)polygons.size(); ++i) + for (i=0; iVertices.size(); - int oldVertexCount = currentVertexCount - vertexCount; - for (int face=0; faceVertices.size() - vertexCount; + for (u32 face=0; faceIndices.push_back(oldVertexCount + 0); mbuffer->Indices.push_back(oldVertexCount + 1 + face); @@ -1075,24 +1166,25 @@ void CColladaFileLoader::readPolygonSection(io::IXMLReaderUTF8* reader, // lightmap mesh buffer scene::SMeshBufferLightMap* mbuffer = new SMeshBufferLightMap(); + mbuffer->Material=mat; buffer = mbuffer; - for (i=0; i<(int)polygons.size(); ++i) + for (i=0; iVertices.size(); - int oldVertexCount = currentVertexCount - vertexCount; - for (int face=0; faceVertices.size() - vertexCount; + for (u32 face=0; faceIndices.push_back(oldVertexCount + 0); mbuffer->Indices.push_back(oldVertexCount + 1 + face); @@ -1180,7 +1271,7 @@ void CColladaFileLoader::readLightPrefab(io::IXMLReaderUTF8* reader) //! returns a collada parameter or none if not found SColladaParam* CColladaFileLoader::getColladaParameter(ECOLLADA_PARAM_NAME name) { - for (int i=0; i<(int)Parameters.size(); ++i) + for (u32 i=0; igetAttributeValue("semantic"); - for (i=0; inputSemanticNames[i]; ++i) + for (u32 i=0; inputSemanticNames[i]; ++i) if (semanticName == inputSemanticNames[i]) { p.Semantic = (ECOLLADA_INPUT_SEMANTIC)i; @@ -1221,7 +1311,7 @@ void CColladaFileLoader::readColladaInput(io::IXMLReaderUTF8* reader) Inputs.push_back(p); } -//! parses all collada inuts inside an element and stores them in Parameters +//! parses all collada inputs inside an element and stores them in Inputs void CColladaFileLoader::readColladaInputs(io::IXMLReaderUTF8* reader, const core::stringc& parentName) { Inputs.clear(); @@ -1264,7 +1354,7 @@ void CColladaFileLoader::readColladaParameters(io::IXMLReaderUTF8* reader, SColladaParam p; // get type - int i; + u32 i; core::stringc typeName = reader->getAttributeValue("type"); for (i=0; typeNames[i]; ++i) if (typeName == typeNames[i]) @@ -1342,7 +1432,7 @@ void CColladaFileLoader::findNextNoneWhiteSpace(const c8** start) //! reads floats from inside of xml element until end of xml element -void CColladaFileLoader::readFloatsInsideElement(io::IXMLReaderUTF8* reader, f32* floats, s32 count) +void CColladaFileLoader::readFloatsInsideElement(io::IXMLReaderUTF8* reader, f32* floats, u32 count) { if (reader->isEmptyElement()) return; @@ -1358,10 +1448,13 @@ void CColladaFileLoader::readFloatsInsideElement(io::IXMLReaderUTF8* reader, f32 core::stringc data = reader->getNodeData(); const c8* p = &data[0]; - for (int i=0; idrop(); Prefabs.clear(); @@ -1384,6 +1477,12 @@ void CColladaFileLoader::clearData() // clear all parameters Parameters.clear(); + // clear all materials + Images.clear(); + + // clear all materials + Textures.clear(); + // clear all materials Materials.clear(); diff --git a/source/Irrlicht/CColladaFileLoader.h b/source/Irrlicht/CColladaFileLoader.h index d6e355b0..fe8251e0 100644 --- a/source/Irrlicht/CColladaFileLoader.h +++ b/source/Irrlicht/CColladaFileLoader.h @@ -31,6 +31,7 @@ enum ECOLLADA_PARAM_NAME ECPN_DIFFUSE, ECPN_SPECULAR, ECPN_SHININESS, + ECPN_TRANSPARENCY, ECPN_YFOV, ECPN_ZNEAR, ECPN_ZFAR, @@ -71,6 +72,8 @@ enum ECOLLADA_INPUT_SEMANTIC ECIS_TEXCOORD, ECIS_UV, ECIS_TANGENT, + ECIS_IMAGE, + ECIS_TEXTURE, ECIS_COUNT }; @@ -87,6 +90,22 @@ struct SColladaInput core::stringc Source; }; +//! Collada images +struct SColladaImage +{ + core::stringc Filename; + core::stringc Id; +}; + + +//! Collada texture +struct SColladaTexture +{ + video::ITexture* Texture; + core::stringc Id; +}; + + //! Collada material struct SColladaMaterial { @@ -196,6 +215,12 @@ private: //! reads a element and stores it as prefab void readCameraPrefab(io::IXMLReaderUTF8* reader); + //! reads a element and stores it in the image section + void readImage(io::IXMLReaderUTF8* reader); + + //! reads a element and stores it in the texture section + void readTexture(io::IXMLReaderUTF8* reader); + //! reads a element and stores it in the material section void readMaterial(io::IXMLReaderUTF8* reader); @@ -214,7 +239,7 @@ private: void findNextNoneWhiteSpace(const c8** p); //! reads floats from inside of xml element until end of xml element - void readFloatsInsideElement(io::IXMLReaderUTF8* reader, f32* floats, s32 count); + void readFloatsInsideElement(io::IXMLReaderUTF8* reader, f32* floats, u32 count); //! clears all loaded data void clearData(); @@ -225,7 +250,7 @@ private: //! returns a collada parameter or none if not found SColladaParam* getColladaParameter(ECOLLADA_PARAM_NAME name); - //! parses all collada inuts inside an element and stores them in Inputs. Reads + //! parses all collada inputs inside an element and stores them in Inputs. Reads //! until first tag which is not an input tag or the end of the parent is reached void readColladaInputs(io::IXMLReaderUTF8* reader, const core::stringc& parentName); @@ -256,6 +281,8 @@ private: core::array Prefabs; core::array Parameters; + core::array Images; + core::array Textures; core::array Materials; core::array Inputs; diff --git a/source/Irrlicht/CMeshManipulator.cpp b/source/Irrlicht/CMeshManipulator.cpp index eb73e48b..bd004dce 100644 --- a/source/Irrlicht/CMeshManipulator.cpp +++ b/source/Irrlicht/CMeshManipulator.cpp @@ -803,8 +803,8 @@ void CMeshManipulator::calculateTangents( core::vector3df& normal, core::vector3df& tangent, core::vector3df& binormal, - core::vector3df& vt1, core::vector3df& vt2, core::vector3df& vt3, // vertices - core::vector2df& tc1, core::vector2df& tc2, core::vector2df& tc3) // texture coords + const core::vector3df& vt1, const core::vector3df& vt2, const core::vector3df& vt3, // vertices + const core::vector2df& tc1, const core::vector2df& tc2, const core::vector2df& tc3) // texture coords { // choose one of them: //#define USE_NVIDIA_GLH_VERSION // use version used by nvidia in glh headers diff --git a/source/Irrlicht/CMeshManipulator.h b/source/Irrlicht/CMeshManipulator.h index 03f60e67..1c3bd5ec 100644 --- a/source/Irrlicht/CMeshManipulator.h +++ b/source/Irrlicht/CMeshManipulator.h @@ -98,8 +98,8 @@ private: static void calculateTangents(core::vector3df& normal, core::vector3df& tangent, core::vector3df& binormal, - core::vector3df& vt1, core::vector3df& vt2, core::vector3df& vt3, - core::vector2df& tc1, core::vector2df& tc2, core::vector2df& tc3); + const core::vector3df& vt1, const core::vector3df& vt2, const core::vector3df& vt3, + const core::vector2df& tc1, const core::vector2df& tc2, const core::vector2df& tc3); }; } // end namespace scene