From f9158592e1478b2013afc7041d9ed041cf2d2f4a Mon Sep 17 00:00:00 2001 From: David Walter Seikel Date: Mon, 13 Jan 2014 19:47:58 +1000 Subject: Update Irrlicht to 1.8.1. Include actual change markers this time. lol --- .../source/Irrlicht/CXMeshFileLoader.cpp | 2419 -------------------- 1 file changed, 2419 deletions(-) delete mode 100644 libraries/irrlicht-1.8/source/Irrlicht/CXMeshFileLoader.cpp (limited to 'libraries/irrlicht-1.8/source/Irrlicht/CXMeshFileLoader.cpp') diff --git a/libraries/irrlicht-1.8/source/Irrlicht/CXMeshFileLoader.cpp b/libraries/irrlicht-1.8/source/Irrlicht/CXMeshFileLoader.cpp deleted file mode 100644 index 1c67434..0000000 --- a/libraries/irrlicht-1.8/source/Irrlicht/CXMeshFileLoader.cpp +++ /dev/null @@ -1,2419 +0,0 @@ -// Copyright (C) 2002-2012 Nikolaus Gebhardt -// This file is part of the "Irrlicht Engine". -// For conditions of distribution and use, see copyright notice in irrlicht.h - -#include "IrrCompileConfig.h" - -#ifdef _IRR_COMPILE_WITH_X_LOADER_ - -#include "CXMeshFileLoader.h" -#include "os.h" - -#include "fast_atof.h" -#include "coreutil.h" -#include "ISceneManager.h" -#include "IVideoDriver.h" -#include "IFileSystem.h" -#include "IReadFile.h" - -#ifdef _DEBUG -#define _XREADER_DEBUG -#endif -//#define BETTER_MESHBUFFER_SPLITTING_FOR_X - -namespace irr -{ -namespace scene -{ - -//! Constructor -CXMeshFileLoader::CXMeshFileLoader(scene::ISceneManager* smgr, io::IFileSystem* fs) -: SceneManager(smgr), FileSystem(fs), AllJoints(0), AnimatedMesh(0), - Buffer(0), P(0), End(0), BinaryNumCount(0), Line(0), - CurFrame(0), MajorVersion(0), MinorVersion(0), BinaryFormat(false), FloatSize(0) -{ - #ifdef _DEBUG - setDebugName("CXMeshFileLoader"); - #endif -} - - -//! returns true if the file maybe is able to be loaded by this class -//! based on the file extension (e.g. ".bsp") -bool CXMeshFileLoader::isALoadableFileExtension(const io::path& filename) const -{ - return core::hasFileExtension ( filename, "x" ); -} - - -//! creates/loads an animated mesh from the file. -//! \return Pointer to the created mesh. Returns 0 if loading failed. -//! If you no longer need the mesh, you should call IAnimatedMesh::drop(). -//! See IReferenceCounted::drop() for more information. -IAnimatedMesh* CXMeshFileLoader::createMesh(io::IReadFile* f) -{ - if (!f) - return 0; - -#ifdef _XREADER_DEBUG - u32 time = os::Timer::getRealTime(); -#endif - - AnimatedMesh = new CSkinnedMesh(); - - if (load(f)) - { - AnimatedMesh->finalize(); - } - else - { - AnimatedMesh->drop(); - AnimatedMesh = 0; - } -#ifdef _XREADER_DEBUG - time = os::Timer::getRealTime() - time; - core::stringc tmpString = "Time to load "; - tmpString += BinaryFormat ? "binary" : "ascii"; - tmpString += " X file: "; - tmpString += time; - tmpString += "ms"; - os::Printer::log(tmpString.c_str()); -#endif - //Clear up - - MajorVersion=0; - MinorVersion=0; - BinaryFormat=0; - BinaryNumCount=0; - FloatSize=0; - P=0; - End=0; - CurFrame=0; - TemplateMaterials.clear(); - - delete [] Buffer; - Buffer = 0; - - for (u32 i=0; iMaterials.size()) - { - mesh->Materials.push_back(video::SMaterial()); - mesh->Materials[0].DiffuseColor.set(0xff777777); - mesh->Materials[0].Shininess=0.f; - mesh->Materials[0].SpecularColor.set(0xff777777); - mesh->Materials[0].EmissiveColor.set(0xff000000); - } - - u32 i; - - mesh->Buffers.reallocate(mesh->Materials.size()); -#ifndef BETTER_MESHBUFFER_SPLITTING_FOR_X - const u32 bufferOffset = AnimatedMesh->getMeshBufferCount(); -#endif - for (i=0; iMaterials.size(); ++i) - { - mesh->Buffers.push_back( AnimatedMesh->addMeshBuffer() ); - mesh->Buffers.getLast()->Material = mesh->Materials[i]; - - if (!mesh->HasSkinning) - { - //Set up rigid animation - if (mesh->AttachedJointID!=-1) - { - AnimatedMesh->getAllJoints()[mesh->AttachedJointID]->AttachedMeshes.push_back( AnimatedMesh->getMeshBuffers().size()-1 ); - } - } - } - - if (!mesh->FaceMaterialIndices.size()) - { - mesh->FaceMaterialIndices.set_used(mesh->Indices.size() / 3); - for (i=0; iFaceMaterialIndices.size(); ++i) - mesh->FaceMaterialIndices[i]=0; - } - - if (!mesh->HasVertexColors) - { - for (u32 j=0;jFaceMaterialIndices.size();++j) - { - for (u32 id=j*3+0;id<=j*3+2;++id) - { - mesh->Vertices[ mesh->Indices[id] ].Color = mesh->Buffers[mesh->FaceMaterialIndices[j]]->Material.DiffuseColor; - } - } - } - - #ifdef BETTER_MESHBUFFER_SPLITTING_FOR_X - { - //the same vertex can be used in many different meshbuffers, but it's slow to work out - - core::array< core::array< u32 > > verticesLinkIndex; - verticesLinkIndex.reallocate(mesh->Vertices.size()); - core::array< core::array< u16 > > verticesLinkBuffer; - verticesLinkBuffer.reallocate(mesh->Vertices.size()); - - for (i=0;iVertices.size();++i) - { - verticesLinkIndex.push_back( core::array< u32 >() ); - verticesLinkBuffer.push_back( core::array< u16 >() ); - } - - for (i=0;iFaceMaterialIndices.size();++i) - { - for (u32 id=i*3+0;id<=i*3+2;++id) - { - core::array< u16 > &Array=verticesLinkBuffer[ mesh->Indices[id] ]; - bool found=false; - - for (u32 j=0; j < Array.size(); ++j) - { - if (Array[j]==mesh->FaceMaterialIndices[i]) - { - found=true; - break; - } - } - - if (!found) - Array.push_back( mesh->FaceMaterialIndices[i] ); - } - } - - for (i=0;iVertices.size();++i) - { - core::array< u16 > &Array = verticesLinkBuffer[i]; - verticesLinkIndex[i].reallocate(Array.size()); - for (u32 j=0; j < Array.size(); ++j) - { - scene::SSkinMeshBuffer *buffer = mesh->Buffers[ Array[j] ]; - verticesLinkIndex[i].push_back( buffer->Vertices_Standard.size() ); - buffer->Vertices_Standard.push_back( mesh->Vertices[i] ); - } - } - - for (i=0;iFaceMaterialIndices.size();++i) - { - scene::SSkinMeshBuffer *buffer=mesh->Buffers[ mesh->FaceMaterialIndices[i] ]; - - for (u32 id=i*3+0;id<=i*3+2;++id) - { - core::array< u16 > &Array=verticesLinkBuffer[ mesh->Indices[id] ]; - - for (u32 j=0;j< Array.size() ;++j) - { - if ( Array[j]== mesh->FaceMaterialIndices[i] ) - buffer->Indices.push_back( verticesLinkIndex[ mesh->Indices[id] ][j] ); - } - } - } - - for (u32 j=0;jWeightJoint.size();++j) - { - ISkinnedMesh::SJoint* joint = AnimatedMesh->getAllJoints()[mesh->WeightJoint[j]]; - ISkinnedMesh::SWeight& weight = joint->Weights[mesh->WeightNum[j]]; - - u32 id = weight.vertex_id; - - if (id>=verticesLinkIndex.size()) - { - os::Printer::log("X loader: Weight id out of range", ELL_WARNING); - id=0; - weight.strength=0.f; - } - - if (verticesLinkBuffer[id].size()==1) - { - weight.vertex_id=verticesLinkIndex[id][0]; - weight.buffer_id=verticesLinkBuffer[id][0]; - } - else if (verticesLinkBuffer[id].size() != 0) - { - for (u32 k=1; k < verticesLinkBuffer[id].size(); ++k) - { - ISkinnedMesh::SWeight* WeightClone = AnimatedMesh->addWeight(joint); - WeightClone->strength = weight.strength; - WeightClone->vertex_id = verticesLinkIndex[id][k]; - WeightClone->buffer_id = verticesLinkBuffer[id][k]; - } - } - } - } - #else - { - core::array< u32 > verticesLinkIndex; - core::array< s16 > verticesLinkBuffer; - verticesLinkBuffer.set_used(mesh->Vertices.size()); - - // init with 0 - for (i=0;iVertices.size();++i) - { - // watch out for vertices which are not part of the mesh - // they will keep the -1 and can lead to out-of-bounds access - verticesLinkBuffer[i]=-1; - } - - bool warned = false; - // store meshbuffer number per vertex - for (i=0;iFaceMaterialIndices.size();++i) - { - for (u32 id=i*3+0;id<=i*3+2;++id) - { - if ((verticesLinkBuffer[mesh->Indices[id]] != -1) && (verticesLinkBuffer[mesh->Indices[id]] != (s16)mesh->FaceMaterialIndices[i])) - { - if (!warned) - { - os::Printer::log("X loader", "Duplicated vertex, animation might be corrupted.", ELL_WARNING); - warned=true; - } - const u32 tmp = mesh->Vertices.size(); - mesh->Vertices.push_back(mesh->Vertices[ mesh->Indices[id] ]); - mesh->Indices[id] = tmp; - verticesLinkBuffer.set_used(mesh->Vertices.size()); - } - verticesLinkBuffer[ mesh->Indices[id] ] = mesh->FaceMaterialIndices[i]; - } - } - - if (mesh->FaceMaterialIndices.size() != 0) - { - // store vertices in buffers and remember relation in verticesLinkIndex - u32* vCountArray = new u32[mesh->Buffers.size()]; - memset(vCountArray, 0, mesh->Buffers.size()*sizeof(u32)); - // count vertices in each buffer and reallocate - for (i=0; iVertices.size(); ++i) - { - if (verticesLinkBuffer[i] != -1) - ++vCountArray[verticesLinkBuffer[i]]; - } - if (mesh->TCoords2.size()) - { - for (i=0; i!=mesh->Buffers.size(); ++i) - { - mesh->Buffers[i]->Vertices_2TCoords.reallocate(vCountArray[i]); - mesh->Buffers[i]->VertexType=video::EVT_2TCOORDS; - } - } - else - { - for (i=0; i!=mesh->Buffers.size(); ++i) - mesh->Buffers[i]->Vertices_Standard.reallocate(vCountArray[i]); - } - - verticesLinkIndex.set_used(mesh->Vertices.size()); - // actually store vertices - for (i=0; iVertices.size(); ++i) - { - // if a vertex is missing for some reason, just skip it - if (verticesLinkBuffer[i]==-1) - continue; - scene::SSkinMeshBuffer *buffer = mesh->Buffers[ verticesLinkBuffer[i] ]; - - if (mesh->TCoords2.size()) - { - verticesLinkIndex[i] = buffer->Vertices_2TCoords.size(); - buffer->Vertices_2TCoords.push_back( mesh->Vertices[i] ); - // We have a problem with correct tcoord2 handling here - // crash fixed for now by checking the values - buffer->Vertices_2TCoords.getLast().TCoords2=(iTCoords2.size())?mesh->TCoords2[i]:mesh->Vertices[i].TCoords; - } - else - { - verticesLinkIndex[i] = buffer->Vertices_Standard.size(); - buffer->Vertices_Standard.push_back( mesh->Vertices[i] ); - } - } - - // count indices per buffer and reallocate - memset(vCountArray, 0, mesh->Buffers.size()*sizeof(u32)); - for (i=0; iFaceMaterialIndices.size(); ++i) - ++vCountArray[ mesh->FaceMaterialIndices[i] ]; - for (i=0; i!=mesh->Buffers.size(); ++i) - mesh->Buffers[i]->Indices.reallocate(vCountArray[i]); - delete [] vCountArray; - // create indices per buffer - for (i=0; iFaceMaterialIndices.size(); ++i) - { - scene::SSkinMeshBuffer *buffer = mesh->Buffers[ mesh->FaceMaterialIndices[i] ]; - for (u32 id=i*3+0; id!=i*3+3; ++id) - { - buffer->Indices.push_back( verticesLinkIndex[ mesh->Indices[id] ] ); - } - } - } - - for (u32 j=0; jWeightJoint.size(); ++j) - { - ISkinnedMesh::SWeight& weight = (AnimatedMesh->getAllJoints()[mesh->WeightJoint[j]]->Weights[mesh->WeightNum[j]]); - - u32 id = weight.vertex_id; - - if (id>=verticesLinkIndex.size()) - { - os::Printer::log("X loader: Weight id out of range", ELL_WARNING); - id=0; - weight.strength=0.f; - } - - weight.vertex_id=verticesLinkIndex[id]; - weight.buffer_id=verticesLinkBuffer[id] + bufferOffset; - } - } - #endif - - } - - return true; -} - - -//! Reads file into memory -bool CXMeshFileLoader::readFileIntoMemory(io::IReadFile* file) -{ - const long size = file->getSize(); - if (size < 12) - { - os::Printer::log("X File is too small.", ELL_WARNING); - return false; - } - - Buffer = new c8[size]; - - //! read all into memory - if (file->read(Buffer, size) != size) - { - os::Printer::log("Could not read from x file.", ELL_WARNING); - return false; - } - - Line = 1; - End = Buffer + size; - - //! check header "xof " - if (strncmp(Buffer, "xof ", 4)!=0) - { - os::Printer::log("Not an x file, wrong header.", ELL_WARNING); - return false; - } - - //! read minor and major version, e.g. 0302 or 0303 - c8 tmp[3]; - tmp[0] = Buffer[4]; - tmp[1] = Buffer[5]; - tmp[2] = 0x0; - MajorVersion = core::strtoul10(tmp); - - tmp[0] = Buffer[6]; - tmp[1] = Buffer[7]; - MinorVersion = core::strtoul10(tmp); - - //! read format - if (strncmp(&Buffer[8], "txt ", 4) ==0) - BinaryFormat = false; - else if (strncmp(&Buffer[8], "bin ", 4) ==0) - BinaryFormat = true; - else - { - os::Printer::log("Only uncompressed x files currently supported.", ELL_WARNING); - return false; - } - BinaryNumCount=0; - - //! read float size - if (strncmp(&Buffer[12], "0032", 4) ==0) - FloatSize = 4; - else if (strncmp(&Buffer[12], "0064", 4) ==0) - FloatSize = 8; - else - { - os::Printer::log("Float size not supported.", ELL_WARNING); - return false; - } - - P = &Buffer[16]; - - readUntilEndOfLine(); - FilePath = FileSystem->getFileDir(file->getFileName()) + "/"; - - return true; -} - - -//! Parses the file -bool CXMeshFileLoader::parseFile() -{ - while(parseDataObject()) - { - // loop - } - - return true; -} - - -//! Parses the next Data object in the file -bool CXMeshFileLoader::parseDataObject() -{ - core::stringc objectName = getNextToken(); - - if (objectName.size() == 0) - return false; - - // parse specific object -#ifdef _XREADER_DEBUG - os::Printer::log("debug DataObject:", objectName.c_str(), ELL_DEBUG); -#endif - - if (objectName == "template") - return parseDataObjectTemplate(); - else - if (objectName == "Frame") - { - return parseDataObjectFrame( 0 ); - } - else - if (objectName == "Mesh") - { - // some meshes have no frames at all - //CurFrame = AnimatedMesh->addJoint(0); - - SXMesh *mesh=new SXMesh; - - //mesh->Buffer=AnimatedMesh->addMeshBuffer(); - Meshes.push_back(mesh); - - return parseDataObjectMesh(*mesh); - } - else - if (objectName == "AnimationSet") - { - return parseDataObjectAnimationSet(); - } - else - if (objectName == "Material") - { - // template materials now available thanks to joeWright - TemplateMaterials.push_back(SXTemplateMaterial()); - TemplateMaterials.getLast().Name = getNextToken(); - return parseDataObjectMaterial(TemplateMaterials.getLast().Material); - } - else - if (objectName == "}") - { - os::Printer::log("} found in dataObject", ELL_WARNING); - return true; - } - - os::Printer::log("Unknown data object in animation of .x file", objectName.c_str(), ELL_WARNING); - - return parseUnknownDataObject(); -} - - -bool CXMeshFileLoader::parseDataObjectTemplate() -{ -#ifdef _XREADER_DEBUG - os::Printer::log("CXFileReader: Reading template", ELL_DEBUG); -#endif - - // parse a template data object. Currently not stored. - core::stringc name; - - if (!readHeadOfDataObject(&name)) - { - os::Printer::log("Left delimiter in template data object missing.", - name.c_str(), ELL_WARNING); - os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); - return false; - } - - // read GUID - getNextToken(); - - // read and ignore data members - while(true) - { - core::stringc s = getNextToken(); - - if (s == "}") - break; - - if (s.size() == 0) - return false; - } - - return true; -} - - -bool CXMeshFileLoader::parseDataObjectFrame(CSkinnedMesh::SJoint *Parent) -{ -#ifdef _XREADER_DEBUG - os::Printer::log("CXFileReader: Reading frame", ELL_DEBUG); -#endif - - // A coordinate frame, or "frame of reference." The Frame template - // is open and can contain any object. The Direct3D extensions (D3DX) - // mesh-loading functions recognize Mesh, FrameTransformMatrix, and - // Frame template instances as child objects when loading a Frame - // instance. - - u32 JointID=0; - - core::stringc name; - - if (!readHeadOfDataObject(&name)) - { - os::Printer::log("No opening brace in Frame found in x file", ELL_WARNING); - os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); - return false; - } - - CSkinnedMesh::SJoint *joint=0; - - if (name.size()) - { - for (u32 n=0; n < AnimatedMesh->getAllJoints().size(); ++n) - { - if (AnimatedMesh->getAllJoints()[n]->Name==name) - { - joint=AnimatedMesh->getAllJoints()[n]; - JointID=n; - break; - } - } - } - - if (!joint) - { -#ifdef _XREADER_DEBUG - os::Printer::log("creating joint ", name.c_str(), ELL_DEBUG); -#endif - joint=AnimatedMesh->addJoint(Parent); - joint->Name=name; - JointID=AnimatedMesh->getAllJoints().size()-1; - } - else - { -#ifdef _XREADER_DEBUG - os::Printer::log("using joint ", name.c_str(), ELL_DEBUG); -#endif - if (Parent) - Parent->Children.push_back(joint); - } - - // Now inside a frame. - // read tokens until closing brace is reached. - - while(true) - { - core::stringc objectName = getNextToken(); - -#ifdef _XREADER_DEBUG - os::Printer::log("debug DataObject in frame:", objectName.c_str(), ELL_DEBUG); -#endif - - if (objectName.size() == 0) - { - os::Printer::log("Unexpected ending found in Frame in x file.", ELL_WARNING); - os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); - return false; - } - else - if (objectName == "}") - { - break; // frame finished - } - else - if (objectName == "Frame") - { - - if (!parseDataObjectFrame(joint)) - return false; - } - else - if (objectName == "FrameTransformMatrix") - { - if (!parseDataObjectTransformationMatrix(joint->LocalMatrix)) - return false; - - //joint->LocalAnimatedMatrix - //joint->LocalAnimatedMatrix.makeInverse(); - //joint->LocalMatrix=tmp*joint->LocalAnimatedMatrix; - } - else - if (objectName == "Mesh") - { - /* - frame.Meshes.push_back(SXMesh()); - if (!parseDataObjectMesh(frame.Meshes.getLast())) - return false; - */ - SXMesh *mesh=new SXMesh; - - mesh->AttachedJointID=JointID; - - Meshes.push_back(mesh); - - if (!parseDataObjectMesh(*mesh)) - return false; - } - else - { - os::Printer::log("Unknown data object in frame in x file", objectName.c_str(), ELL_WARNING); - if (!parseUnknownDataObject()) - return false; - } - } - - return true; -} - - -bool CXMeshFileLoader::parseDataObjectTransformationMatrix(core::matrix4 &mat) -{ -#ifdef _XREADER_DEBUG - os::Printer::log("CXFileReader: Reading Transformation Matrix", ELL_DEBUG); -#endif - - if (!readHeadOfDataObject()) - { - os::Printer::log("No opening brace in Transformation Matrix found in x file", ELL_WARNING); - os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); - return false; - } - - readMatrix(mat); - - if (!checkForOneFollowingSemicolons()) - { - os::Printer::log("No finishing semicolon in Transformation Matrix found in x file", ELL_WARNING); - os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); - } - - if (!checkForClosingBrace()) - { - os::Printer::log("No closing brace in Transformation Matrix found in x file", ELL_WARNING); - os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); - return false; - } - - return true; -} - - -bool CXMeshFileLoader::parseDataObjectMesh(SXMesh &mesh) -{ - core::stringc name; - - if (!readHeadOfDataObject(&name)) - { -#ifdef _XREADER_DEBUG - os::Printer::log("CXFileReader: Reading mesh", ELL_DEBUG); -#endif - os::Printer::log("No opening brace in Mesh found in x file", ELL_WARNING); - os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); - return false; - } - -#ifdef _XREADER_DEBUG - os::Printer::log("CXFileReader: Reading mesh", name.c_str(), ELL_DEBUG); -#endif - - // read vertex count - const u32 nVertices = readInt(); - - // read vertices - mesh.Vertices.set_used(nVertices); - for (u32 n=0; n polygonfaces; - u32 currentIndex = 0; - - for (u32 k=0; k>8)&0xf)*sizeof(core::vector2df); - for (u32 j=0; jgetAllJoints().size(); ++n) - { - if (AnimatedMesh->getAllJoints()[n]->Name==TransformNodeName) - { - joint=AnimatedMesh->getAllJoints()[n]; - break; - } - } - - if (!joint) - { -#ifdef _XREADER_DEBUG - os::Printer::log("creating joint for skinning ", TransformNodeName.c_str(), ELL_DEBUG); -#endif - n = AnimatedMesh->getAllJoints().size(); - joint=AnimatedMesh->addJoint(0); - joint->Name=TransformNodeName; - } - - // read vertex weights - const u32 nWeights = readInt(); - - // read vertex indices - u32 i; - - const u32 jointStart = joint->Weights.size(); - joint->Weights.reallocate(jointStart+nWeights); - - mesh.WeightJoint.reallocate( mesh.WeightJoint.size() + nWeights ); - mesh.WeightNum.reallocate( mesh.WeightNum.size() + nWeights ); - - for (i=0; iWeights.size()); - - CSkinnedMesh::SWeight *weight=AnimatedMesh->addWeight(joint); - - weight->buffer_id=0; - weight->vertex_id=readInt(); - } - - // read vertex weights - - for (i=jointStart; iWeights[i].strength = readFloat(); - - // read matrix offset - - // transforms the mesh vertices to the space of the bone - // When concatenated to the bone's transform, this provides the - // world space coordinates of the mesh as affected by the bone - core::matrix4& MatrixOffset = joint->GlobalInversedMatrix; - - readMatrix(MatrixOffset); - - if (!checkForOneFollowingSemicolons()) - { - os::Printer::log("No finishing semicolon in Skin Weights found in x file", ELL_WARNING); - os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); - } - - if (!checkForClosingBrace()) - { - os::Printer::log("No closing brace in Skin Weights found in x file", ELL_WARNING); - os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); - return false; - } - - return true; -} - - -bool CXMeshFileLoader::parseDataObjectSkinMeshHeader(SXMesh& mesh) -{ -#ifdef _XREADER_DEBUG - os::Printer::log("CXFileReader: Reading skin mesh header", ELL_DEBUG); -#endif - - if (!readHeadOfDataObject()) - { - os::Printer::log("No opening brace in Skin Mesh header found in .x file", ELL_WARNING); - os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); - return false; - } - - mesh.MaxSkinWeightsPerVertex = readInt(); - mesh.MaxSkinWeightsPerFace = readInt(); - mesh.BoneCount = readInt(); - - if (!BinaryFormat) - getNextToken(); // skip semicolon - - if (!checkForClosingBrace()) - { - os::Printer::log("No closing brace in skin mesh header in x file", ELL_WARNING); - os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); - return false; - } - - return true; -} - - -bool CXMeshFileLoader::parseDataObjectMeshNormals(SXMesh &mesh) -{ -#ifdef _XREADER_DEBUG - os::Printer::log("CXFileReader: reading mesh normals", ELL_DEBUG); -#endif - - if (!readHeadOfDataObject()) - { - os::Printer::log("No opening brace in Mesh Normals found in x file", ELL_WARNING); - os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); - return false; - } - - // read count - const u32 nNormals = readInt(); - core::array normals; - normals.set_used(nNormals); - - // read normals - for (u32 i=0; i normalIndices; - normalIndices.set_used(mesh.Indices.size()); - - // read face normal indices - const u32 nFNormals = readInt(); - - u32 normalidx = 0; - core::array polygonfaces; - for (u32 k=0; k=mesh.Vertices.size()) - { - os::Printer::log("index value in parseDataObjectMeshVertexColors out of bounds", ELL_WARNING); - os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); - return false; - } - readRGBA(mesh.Vertices[Index].Color); - checkForOneFollowingSemicolons(); - } - - if (!checkForOneFollowingSemicolons()) - { - os::Printer::log("No finishing semicolon in Mesh Vertex Colors Array found in x file", ELL_WARNING); - os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); - } - - if (!checkForClosingBrace()) - { - os::Printer::log("No closing brace in Mesh Texture Coordinates Array found in x file", ELL_WARNING); - os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); - return false; - } - - return true; -} - - -bool CXMeshFileLoader::parseDataObjectMeshMaterialList(SXMesh &mesh) -{ -#ifdef _XREADER_DEBUG - os::Printer::log("CXFileReader: Reading mesh material list", ELL_DEBUG); -#endif - - if (!readHeadOfDataObject()) - { - os::Printer::log("No opening brace in Mesh Material List found in x file", ELL_WARNING); - os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); - return false; - } - - // read material count - mesh.Materials.reallocate(readInt()); - - // read non triangulated face material index count - const u32 nFaceIndices = readInt(); - - // There seems to be a compact representation of "all faces the same material" - // being represented as 1;1;0;; which means 1 material, 1 face with first material - // all the other faces have to obey then, so check is disabled - //if (nFaceIndices != mesh.IndexCountPerFace.size()) - // os::Printer::log("Index count per face not equal to face material index count in x file.", ELL_WARNING); - - // read non triangulated face indices and create triangulated ones - mesh.FaceMaterialIndices.set_used( mesh.Indices.size() / 3); - u32 triangulatedindex = 0; - u32 ind = 0; - for (u32 tfi=0; tfiexistFile(TextureFileName)) - material.setTexture(textureLayer, SceneManager->getVideoDriver()->getTexture(TextureFileName)); - // mesh path - else - { - TextureFileName=FilePath + FileSystem->getFileBasename(TextureFileName); - if (FileSystem->existFile(TextureFileName)) - material.setTexture(textureLayer, SceneManager->getVideoDriver()->getTexture(TextureFileName)); - // working directory - else - material.setTexture(textureLayer, SceneManager->getVideoDriver()->getTexture(FileSystem->getFileBasename(TextureFileName))); - } - ++textureLayer; - if (textureLayer==2) - material.MaterialType=video::EMT_LIGHTMAP; - } - else - if (objectName.equals_ignore_case("NormalmapFilename")) - { - // some exporters write "NormalmapFileName" instead. - core::stringc TextureFileName; - if (!parseDataObjectTextureFilename(TextureFileName)) - return false; - - // original name - if (FileSystem->existFile(TextureFileName)) - material.setTexture(1, SceneManager->getVideoDriver()->getTexture(TextureFileName)); - // mesh path - else - { - TextureFileName=FilePath + FileSystem->getFileBasename(TextureFileName); - if (FileSystem->existFile(TextureFileName)) - material.setTexture(1, SceneManager->getVideoDriver()->getTexture(TextureFileName)); - // working directory - else - material.setTexture(1, SceneManager->getVideoDriver()->getTexture(FileSystem->getFileBasename(TextureFileName))); - } - if (textureLayer==1) - ++textureLayer; - } - else - { - os::Printer::log("Unknown data object in material in .x file", objectName.c_str(), ELL_WARNING); - if (!parseUnknownDataObject()) - return false; - } - } - - return true; -} - - -bool CXMeshFileLoader::parseDataObjectAnimationSet() -{ -#ifdef _XREADER_DEBUG - os::Printer::log("CXFileReader: Reading animation set", ELL_DEBUG); -#endif - - core::stringc AnimationName; - - if (!readHeadOfDataObject(&AnimationName)) - { - os::Printer::log("No opening brace in Animation Set found in x file", ELL_WARNING); - os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); - return false; - } - os::Printer::log("Reading animationset ", AnimationName, ELL_DEBUG); - - while(true) - { - core::stringc objectName = getNextToken(); - - if (objectName.size() == 0) - { - os::Printer::log("Unexpected ending found in Animation set in x file.", ELL_WARNING); - os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); - return false; - } - else - if (objectName == "}") - { - break; // animation set finished - } - else - if (objectName == "Animation") - { - if (!parseDataObjectAnimation()) - return false; - } - else - { - os::Printer::log("Unknown data object in animation set in x file", objectName.c_str(), ELL_WARNING); - if (!parseUnknownDataObject()) - return false; - } - } - return true; -} - - -bool CXMeshFileLoader::parseDataObjectAnimation() -{ -#ifdef _XREADER_DEBUG - os::Printer::log("CXFileReader: reading animation", ELL_DEBUG); -#endif - - if (!readHeadOfDataObject()) - { - os::Printer::log("No opening brace in Animation found in x file", ELL_WARNING); - os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); - return false; - } - - //anim.closed = true; - //anim.linearPositionQuality = true; - CSkinnedMesh::SJoint animationDump; - - core::stringc FrameName; - - while(true) - { - core::stringc objectName = getNextToken(); - - if (objectName.size() == 0) - { - os::Printer::log("Unexpected ending found in Animation in x file.", ELL_WARNING); - os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); - return false; - } - else - if (objectName == "}") - { - break; // animation finished - } - else - if (objectName == "AnimationKey") - { - if (!parseDataObjectAnimationKey(&animationDump)) - return false; - } - else - if (objectName == "AnimationOptions") - { - //TODO: parse options. - if (!parseUnknownDataObject()) - return false; - } - else - if (objectName == "{") - { - // read frame name - FrameName = getNextToken(); - - if (!checkForClosingBrace()) - { - os::Printer::log("Unexpected ending found in Animation in x file.", ELL_WARNING); - os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); - return false; - } - } - else - { - os::Printer::log("Unknown data object in animation in x file", objectName.c_str(), ELL_WARNING); - if (!parseUnknownDataObject()) - return false; - } - } - - if (FrameName.size() != 0) - { -#ifdef _XREADER_DEBUG - os::Printer::log("frame name", FrameName.c_str(), ELL_DEBUG); -#endif - CSkinnedMesh::SJoint *joint=0; - - u32 n; - for (n=0; n < AnimatedMesh->getAllJoints().size(); ++n) - { - if (AnimatedMesh->getAllJoints()[n]->Name==FrameName) - { - joint=AnimatedMesh->getAllJoints()[n]; - break; - } - } - - if (!joint) - { -#ifdef _XREADER_DEBUG - os::Printer::log("creating joint for animation ", FrameName.c_str(), ELL_DEBUG); -#endif - joint=AnimatedMesh->addJoint(0); - joint->Name=FrameName; - } - - joint->PositionKeys.reallocate(joint->PositionKeys.size()+animationDump.PositionKeys.size()); - for (n=0; nPositionKeys.push_back(animationDump.PositionKeys[n]); - } - - joint->ScaleKeys.reallocate(joint->ScaleKeys.size()+animationDump.ScaleKeys.size()); - for (n=0; nScaleKeys.push_back(animationDump.ScaleKeys[n]); - } - - joint->RotationKeys.reallocate(joint->RotationKeys.size()+animationDump.RotationKeys.size()); - for (n=0; nRotationKeys.push_back(animationDump.RotationKeys[n]); - } - } - else - os::Printer::log("joint name was never given", ELL_WARNING); - - return true; -} - - -bool CXMeshFileLoader::parseDataObjectAnimationKey(ISkinnedMesh::SJoint *joint) -{ -#ifdef _XREADER_DEBUG - os::Printer::log("CXFileReader: reading animation key", ELL_DEBUG); -#endif - - if (!readHeadOfDataObject()) - { - os::Printer::log("No opening brace in Animation Key found in x file", ELL_WARNING); - os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); - return false; - } - - // read key type - - const u32 keyType = readInt(); - - if (keyType > 4) - { - os::Printer::log("Unknown key type found in Animation Key in x file", ELL_WARNING); - os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); - return false; - } - - // read number of keys - const u32 numberOfKeys = readInt(); - - // eat the semicolon after the "0". if there are keys present, readInt() - // does this for us. If there aren't, we need to do it explicitly - if (numberOfKeys == 0) - checkForOneFollowingSemicolons(); - - for (u32 i=0; iaddRotationKey(joint); - key->frame=time; - key->rotation.set(X,Y,Z,W); - } - break; - case 1: //scale - case 2: //position - { - // read vectors - - // read count - if (readInt() != 3) - { - os::Printer::log("Expected 3 numbers in animation key in x file", ELL_WARNING); - os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); - return false; - } - - core::vector3df vector; - readVector3(vector); - - if (!checkForTwoFollowingSemicolons()) - { - os::Printer::log("No finishing semicolon after vector animation key in x file", ELL_WARNING); - os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); - } - - if (keyType==2) - { - ISkinnedMesh::SPositionKey *key=AnimatedMesh->addPositionKey(joint); - key->frame=time; - key->position=vector; - } - else - { - ISkinnedMesh::SScaleKey *key=AnimatedMesh->addScaleKey(joint); - key->frame=time; - key->scale=vector; - } - } - break; - case 3: - case 4: - { - // read matrix - - // read count - if (readInt() != 16) - { - os::Printer::log("Expected 16 numbers in animation key in x file", ELL_WARNING); - os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); - return false; - } - - // read matrix - core::matrix4 mat(core::matrix4::EM4CONST_NOTHING); - readMatrix(mat); - - //mat=joint->LocalMatrix*mat; - - if (!checkForOneFollowingSemicolons()) - { - os::Printer::log("No finishing semicolon after matrix animation key in x file", ELL_WARNING); - os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); - } - - //core::vector3df rotation = mat.getRotationDegrees(); - - ISkinnedMesh::SRotationKey *keyR=AnimatedMesh->addRotationKey(joint); - keyR->frame=time; - - // IRR_TEST_BROKEN_QUATERNION_USE: TODO - switched from mat to mat.getTransposed() for downward compatibility. - // Not tested so far if this was correct or wrong before quaternion fix! - keyR->rotation= core::quaternion(mat.getTransposed()); - - ISkinnedMesh::SPositionKey *keyP=AnimatedMesh->addPositionKey(joint); - keyP->frame=time; - keyP->position=mat.getTranslation(); - -/* - core::vector3df scale=mat.getScale(); - - if (scale.X==0) - scale.X=1; - if (scale.Y==0) - scale.Y=1; - if (scale.Z==0) - scale.Z=1; - ISkinnedMesh::SScaleKey *keyS=AnimatedMesh->addScaleKey(joint); - keyS->frame=time; - keyS->scale=scale; -*/ - } - break; - } // end switch - } - - if (!checkForOneFollowingSemicolons()) - --P; - - if (!checkForClosingBrace()) - { - os::Printer::log("No closing brace in animation key in x file", ELL_WARNING); - os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); - return false; - } - - return true; -} - - -bool CXMeshFileLoader::parseDataObjectTextureFilename(core::stringc& texturename) -{ -#ifdef _XREADER_DEBUG - os::Printer::log("CXFileReader: reading texture filename", ELL_DEBUG); -#endif - - if (!readHeadOfDataObject()) - { - os::Printer::log("No opening brace in Texture filename found in x file", ELL_WARNING); - os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); - return false; - } - - if (!getNextTokenAsString(texturename)) - { - os::Printer::log("Unknown syntax while reading texture filename string in x file", ELL_WARNING); - os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); - return false; - } - - if (!checkForClosingBrace()) - { - os::Printer::log("No closing brace in Texture filename found in x file", ELL_WARNING); - os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING); - return false; - } - - return true; -} - - -bool CXMeshFileLoader::parseUnknownDataObject() -{ - // find opening delimiter - while(true) - { - core::stringc t = getNextToken(); - - if (t.size() == 0) - return false; - - if (t == "{") - break; - } - - u32 counter = 1; - - // parse until closing delimiter - - while(counter) - { - core::stringc t = getNextToken(); - - if (t.size() == 0) - return false; - - if (t == "{") - ++counter; - else - if (t == "}") - --counter; - } - - return true; -} - - -//! checks for closing curly brace, returns false if not there -bool CXMeshFileLoader::checkForClosingBrace() -{ - return (getNextToken() == "}"); -} - - -//! checks for one following semicolon, returns false if not there -bool CXMeshFileLoader::checkForOneFollowingSemicolons() -{ - if (BinaryFormat) - return true; - - if (getNextToken() == ";") - return true; - else - { - --P; - return false; - } -} - - -//! checks for two following semicolons, returns false if they are not there -bool CXMeshFileLoader::checkForTwoFollowingSemicolons() -{ - if (BinaryFormat) - return true; - - for (u32 k=0; k<2; ++k) - { - if (getNextToken() != ";") - { - --P; - return false; - } - } - - return true; -} - - -//! reads header of dataobject including the opening brace. -//! returns false if error happened, and writes name of object -//! if there is one -bool CXMeshFileLoader::readHeadOfDataObject(core::stringc* outname) -{ - core::stringc nameOrBrace = getNextToken(); - if (nameOrBrace != "{") - { - if (outname) - (*outname) = nameOrBrace; - - if (getNextToken() != "{") - return false; - } - - return true; -} - - -//! returns next parseable token. Returns empty string if no token there -core::stringc CXMeshFileLoader::getNextToken() -{ - core::stringc s; - - // process binary-formatted file - if (BinaryFormat) - { - // in binary mode it will only return NAME and STRING token - // and (correctly) skip over other tokens. - - s16 tok = readBinWord(); - u32 len; - - // standalone tokens - switch (tok) { - case 1: - // name token - len = readBinDWord(); - s = core::stringc(P, len); - P += len; - return s; - case 2: - // string token - len = readBinDWord(); - s = core::stringc(P, len); - P += (len + 2); - return s; - case 3: - // integer token - P += 4; - return ""; - case 5: - // GUID token - P += 16; - return ""; - case 6: - len = readBinDWord(); - P += (len * 4); - return ""; - case 7: - len = readBinDWord(); - P += (len * FloatSize); - return ""; - case 0x0a: - return "{"; - case 0x0b: - return "}"; - case 0x0c: - return "("; - case 0x0d: - return ")"; - case 0x0e: - return "["; - case 0x0f: - return "]"; - case 0x10: - return "<"; - case 0x11: - return ">"; - case 0x12: - return "."; - case 0x13: - return ","; - case 0x14: - return ";"; - case 0x1f: - return "template"; - case 0x28: - return "WORD"; - case 0x29: - return "DWORD"; - case 0x2a: - return "FLOAT"; - case 0x2b: - return "DOUBLE"; - case 0x2c: - return "CHAR"; - case 0x2d: - return "UCHAR"; - case 0x2e: - return "SWORD"; - case 0x2f: - return "SDWORD"; - case 0x30: - return "void"; - case 0x31: - return "string"; - case 0x32: - return "unicode"; - case 0x33: - return "cstring"; - case 0x34: - return "array"; - } - } - // process text-formatted file - else - { - findNextNoneWhiteSpace(); - - if (P >= End) - return s; - - while((P < End) && !core::isspace(P[0])) - { - // either keep token delimiters when already holding a token, or return if first valid char - if (P[0]==';' || P[0]=='}' || P[0]=='{' || P[0]==',') - { - if (!s.size()) - { - s.append(P[0]); - ++P; - } - break; // stop for delimiter - } - s.append(P[0]); - ++P; - } - } - return s; -} - - -//! places pointer to next begin of a token, which must be a number, -// and ignores comments -void CXMeshFileLoader::findNextNoneWhiteSpaceNumber() -{ - if (BinaryFormat) - return; - - while((P < End) && (P[0] != '-') && (P[0] != '.') && - !( core::isdigit(P[0]))) - { - // check if this is a comment - if ((P[0] == '/' && P[1] == '/') || P[0] == '#') - readUntilEndOfLine(); - else - ++P; - } -} - - -// places pointer to next begin of a token, and ignores comments -void CXMeshFileLoader::findNextNoneWhiteSpace() -{ - if (BinaryFormat) - return; - - while(true) - { - while((P < End) && core::isspace(P[0])) - { - if (*P=='\n') - ++Line; - ++P; - } - - if (P >= End) - return; - - // check if this is a comment - if ((P[0] == '/' && P[1] == '/') || - P[0] == '#') - readUntilEndOfLine(); - else - break; - } -} - - -//! reads a x file style string -bool CXMeshFileLoader::getNextTokenAsString(core::stringc& out) -{ - if (BinaryFormat) - { - out=getNextToken(); - return true; - } - findNextNoneWhiteSpace(); - - if (P >= End) - return false; - - if (P[0] != '"') - return false; - ++P; - - while(P < End && P[0]!='"') - { - out.append(P[0]); - ++P; - } - - if ( P[1] != ';' || P[0] != '"') - return false; - P+=2; - - return true; -} - - -void CXMeshFileLoader::readUntilEndOfLine() -{ - if (BinaryFormat) - return; - - while(P < End) - { - if (P[0] == '\n' || P[0] == '\r') - { - ++P; - ++Line; - return; - } - - ++P; - } -} - - -u16 CXMeshFileLoader::readBinWord() -{ -#ifdef __BIG_ENDIAN__ - const u16 tmp = os::Byteswap::byteswap(*(u16 *)P); -#else - const u16 tmp = *(u16 *)P; -#endif - P += 2; - return tmp; -} - - -u32 CXMeshFileLoader::readBinDWord() -{ -#ifdef __BIG_ENDIAN__ - const u32 tmp = os::Byteswap::byteswap(*(u32 *)P); -#else - const u32 tmp = *(u32 *)P; -#endif - P += 4; - return tmp; -} - - -u32 CXMeshFileLoader::readInt() -{ - if (BinaryFormat) - { - if (!BinaryNumCount) - { - const u16 tmp = readBinWord(); // 0x06 or 0x03 - if (tmp == 0x06) - BinaryNumCount = readBinDWord(); - else - BinaryNumCount = 1; // single int - } - --BinaryNumCount; - return readBinDWord(); - } - else - { - findNextNoneWhiteSpaceNumber(); - return core::strtoul10(P, &P); - } -} - - -f32 CXMeshFileLoader::readFloat() -{ - if (BinaryFormat) - { - if (!BinaryNumCount) - { - const u16 tmp = readBinWord(); // 0x07 or 0x42 - if (tmp == 0x07) - BinaryNumCount = readBinDWord(); - else - BinaryNumCount = 1; // single int - } - --BinaryNumCount; - if (FloatSize == 8) - { -#ifdef __BIG_ENDIAN__ - //TODO: Check if data is properly converted here - f32 ctmp[2]; - ctmp[1] = os::Byteswap::byteswap(*(f32*)P); - ctmp[0] = os::Byteswap::byteswap(*(f32*)P+4); - const f32 tmp = (f32)(*(f64*)(void*)ctmp); -#else - const f32 tmp = (f32)(*(f64 *)P); -#endif - P += 8; - return tmp; - } - else - { -#ifdef __BIG_ENDIAN__ - const f32 tmp = os::Byteswap::byteswap(*(f32 *)P); -#else - const f32 tmp = *(f32 *)P; -#endif - P += 4; - return tmp; - } - } - findNextNoneWhiteSpaceNumber(); - f32 ftmp; - P = core::fast_atof_move(P, ftmp); - return ftmp; -} - - -// read 2-dimensional vector. Stops at semicolon after second value for text file format -bool CXMeshFileLoader::readVector2(core::vector2df& vec) -{ - vec.X = readFloat(); - vec.Y = readFloat(); - return true; -} - - -// read 3-dimensional vector. Stops at semicolon after third value for text file format -bool CXMeshFileLoader::readVector3(core::vector3df& vec) -{ - vec.X = readFloat(); - vec.Y = readFloat(); - vec.Z = readFloat(); - return true; -} - - -// read color without alpha value. Stops after second semicolon after blue value -bool CXMeshFileLoader::readRGB(video::SColor& color) -{ - video::SColorf tmpColor; - tmpColor.r = readFloat(); - tmpColor.g = readFloat(); - tmpColor.b = readFloat(); - color = tmpColor.toSColor(); - return checkForOneFollowingSemicolons(); -} - - -// read color with alpha value. Stops after second semicolon after blue value -bool CXMeshFileLoader::readRGBA(video::SColor& color) -{ - video::SColorf tmpColor; - tmpColor.r = readFloat(); - tmpColor.g = readFloat(); - tmpColor.b = readFloat(); - tmpColor.a = readFloat(); - color = tmpColor.toSColor(); - return checkForOneFollowingSemicolons(); -} - - -// read matrix from list of floats -bool CXMeshFileLoader::readMatrix(core::matrix4& mat) -{ - for (u32 i=0; i<16; ++i) - mat[i] = readFloat(); - return checkForOneFollowingSemicolons(); -} - - -} // end namespace scene -} // end namespace irr - -#endif // _IRR_COMPILE_WITH_X_LOADER_ - -- cgit v1.1