diff --git a/include/ISceneManager.h b/include/ISceneManager.h
index a33deb84..576621e8 100644
--- a/include/ISceneManager.h
+++ b/include/ISceneManager.h
@@ -148,17 +148,6 @@ namespace scene
* As this format supports skeletal animations, an
* ISkinnedMesh will be returned by this importer.
*
- *
- * DirectX (.x) |
- * Platform independent importer (so not D3D-only) for
- * .x files. Most 3D packages can export these natively
- * and there are several tools for them available, e.g.
- * the Maya exporter included in the DX SDK.
- * .x files can include skeletal animations and Irrlicht
- * is able to play and display them, users can manipulate
- * the joints via the ISkinnedMesh interface. Currently,
- * Irrlicht only supports uncompressed .x files. |
- *
*
*
* To load and display a mesh quickly, just do this:
diff --git a/source/Irrlicht/CXMeshFileLoader.cpp b/source/Irrlicht/CXMeshFileLoader.cpp
deleted file mode 100644
index 24455f2a..00000000
--- a/source/Irrlicht/CXMeshFileLoader.cpp
+++ /dev/null
@@ -1,2391 +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 "CXMeshFileLoader.h"
-#include "os.h"
-
-#include "fast_atof.h"
-#include "coreutil.h"
-#include "ISceneManager.h"
-#include "IVideoDriver.h"
-#include "IReadFile.h"
-
-#ifdef _DEBUG
-#define _XREADER_DEBUG
-#endif
-//#define BETTER_MESHBUFFER_SPLITTING_FOR_X
-
-#define SET_ERR_AND_RETURN() do { ErrorState = true; return false; } while (0)
-
-namespace irr
-{
-namespace scene
-{
-
-//! Constructor
-CXMeshFileLoader::CXMeshFileLoader(scene::ISceneManager* smgr)
-: AnimatedMesh(0), Buffer(0), P(0), End(0), BinaryNumCount(0), Line(0), ErrorState(false),
- 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. ".b3d")
-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* file)
-{
- if (!file)
- return 0;
-
-#ifdef _XREADER_DEBUG
- u32 time = os::Timer::getRealTime();
-#endif
-
- AnimatedMesh = new CSkinnedMesh();
-
- if (load(file))
- {
- 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;
-
- 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+1];
- Buffer[size] = 0x0; // null-terminate
-
- //! read all into memory
- if (file->read(Buffer, size) != static_cast(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();
-
- return true;
-}
-
-
-//! Parses the file
-bool CXMeshFileLoader::parseFile()
-{
- while(parseDataObject())
- {
- // loop
- }
-
- return !ErrorState;
-}
-
-
-//! 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 == "AnimTicksPerSecond")
- {
- return parseDataObjectAnimationTicksPerSecond();
- }
- else
- if (objectName == "Material")
- {
- return parseUnknownDataObject();
- }
- 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);
- SET_ERR_AND_RETURN();
- }
-
- // 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);
- SET_ERR_AND_RETURN();
- }
-
- 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);
- SET_ERR_AND_RETURN();
- }
- 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);
- SET_ERR_AND_RETURN();
- }
-
- 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);
- SET_ERR_AND_RETURN();
- }
-
- 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);
- SET_ERR_AND_RETURN();
- }
-
-#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= mesh.Vertices.size())
- {
- os::Printer::log("Out of range index found in Mesh x file reader.", ELL_WARNING);
- SET_ERR_AND_RETURN();
- }
- }
-
- if (!checkForTwoFollowingSemicolons())
- {
- os::Printer::log("No finishing semicolon in Mesh Face Array found in x file", ELL_WARNING);
- os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING);
- }
-
- // here, other data objects may follow
-
- while(true)
- {
- core::stringc objectName = getNextToken();
-
- if (objectName.size() == 0)
- {
- os::Printer::log("Unexpected ending found in Mesh in x file.", ELL_WARNING);
- os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING);
- SET_ERR_AND_RETURN();
- }
- else
- if (objectName == "}")
- {
- break; // mesh finished
- }
-
-#ifdef _XREADER_DEBUG
- os::Printer::log("debug DataObject in mesh", objectName.c_str(), ELL_DEBUG);
-#endif
-
- if (objectName == "MeshNormals")
- {
- if (!parseDataObjectMeshNormals(mesh))
- return false;
- }
- else
- if (objectName == "MeshTextureCoords")
- {
- if (!parseDataObjectMeshTextureCoords(mesh))
- return false;
- }
- else
- if (objectName == "MeshVertexColors")
- {
- if (!parseDataObjectMeshVertexColors(mesh))
- return false;
- }
- else
- if (objectName == "MeshMaterialList")
- {
- if (!parseDataObjectMeshMaterialList(mesh))
- return false;
- }
- else
- if (objectName == "VertexDuplicationIndices")
- {
- // we'll ignore vertex duplication indices
- // TODO: read them
- if (!parseUnknownDataObject())
- return false;
- }
- else
- if (objectName == "DeclData")
- {
- if (!readHeadOfDataObject())
- {
- os::Printer::log("No starting brace in DeclData found.", ELL_WARNING);
- os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING);
- SET_ERR_AND_RETURN();
- }
- // arbitrary vertex attributes
- // first comes the number of element definitions
- // then the vertex element type definitions
- // with format type;tesselator;semantics;usageindex
- // we want to support 2;0;6;0 == tangent
- // 2;0;7;0 == binormal
- // 2;0;3;0 == normal
- // 1/2;0;5;0 == 1st uv coord
- // and 1/2;0;5;1 == 2nd uv coord
- // type==2 is 3xf32, type==1 is 2xf32
- u32 j;
- const u32 dcnt = readInt();
- u16 size = 0;
- s16 normalpos = -1;
- s16 uvpos = -1;
- s16 uv2pos = -1;
- s16 tangentpos = -1;
- s16 binormalpos = -1;
- s16 normaltype = -1;
- s16 uvtype = -1;
- s16 uv2type = -1;
- s16 tangenttype = -1;
- s16 binormaltype = -1;
-
- (void)tangentpos; // disable unused variable warnings
- (void)binormalpos; // disable unused variable warnings
- (void)tangenttype; // disable unused variable warnings
- (void)binormaltype; // disable unused variable warnings
-
- for (j=0; j>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);
- SET_ERR_AND_RETURN();
- }
-
- 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);
- SET_ERR_AND_RETURN();
- }
-
- 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);
- SET_ERR_AND_RETURN();
- }
-
- 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);
- SET_ERR_AND_RETURN();
- }
-
- // 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();
- //if (nFNormals >= mesh.IndexCountPerFace.size())
- if (0) // this condition doesn't work for some reason
- {
- os::Printer::log("Too many face normals found in x file", ELL_WARNING);
- os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING);
- SET_ERR_AND_RETURN();
- }
-
- u32 normalidx = 0;
- core::array polygonfaces;
- for (u32 k=0; k= mesh.Vertices.size())
- if (0) // this condition doesn't work for some reason
- {
- os::Printer::log("Too many texture coords found in x file", ELL_WARNING);
- os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING);
- SET_ERR_AND_RETURN();
- }
-
- for (u32 i=0; i=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);
- SET_ERR_AND_RETURN();
- }
- 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);
- SET_ERR_AND_RETURN();
- }
-
- // read material count
- const u32 nMaterials = readInt();
- mesh.Materials.reallocate(nMaterials);
-
- // 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; tfi= core::max_(nMaterials, 1U))
- {
- os::Printer::log("Out of range index found in x file", ELL_WARNING);
- os::Printer::log("Line", core::stringc(Line).c_str(), ELL_WARNING);
- SET_ERR_AND_RETURN();
- }
- const u32 fc = mesh.IndexCountPerFace[tfi]/3;
- for (u32 k=0; ksetAnimationSpeed(static_cast(ticks));
-
- 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);
- SET_ERR_AND_RETURN();
- }
-
- //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);
- SET_ERR_AND_RETURN();
- }
- 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);
- SET_ERR_AND_RETURN();
- }
- }
- else
- {
- os::Printer::log("Unknown data object in animation in x file", objectName.c_str(), ELL_WARNING);
- if (!parseUnknownDataObject())
- SET_ERR_AND_RETURN();
- }
- }
-
- 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);
- SET_ERR_AND_RETURN();
- }
-
- // 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);
- SET_ERR_AND_RETURN();
- }
-
- // 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);
- key->rotation.normalize();
- }
- 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);
- SET_ERR_AND_RETURN();
- }
-
- 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);
- SET_ERR_AND_RETURN();
- }
-
- // 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);
- SET_ERR_AND_RETURN();
- }
-
- 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);
- SET_ERR_AND_RETURN();
- }
-
- 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);
- SET_ERR_AND_RETURN();
- }
-
- 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);
- SET_ERR_AND_RETURN();
- }
-
- 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()
-{
- if (P>=End)
- return 0;
-#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()
-{
- if (P>=End)
- return 0;
-#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
diff --git a/source/Irrlicht/CXMeshFileLoader.h b/source/Irrlicht/CXMeshFileLoader.h
deleted file mode 100644
index 67e559df..00000000
--- a/source/Irrlicht/CXMeshFileLoader.h
+++ /dev/null
@@ -1,183 +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
-
-#pragma once
-
-#include "IMeshLoader.h"
-#include "irrString.h"
-#include "CSkinnedMesh.h"
-
-
-namespace irr
-{
-namespace io
-{
- class IReadFile;
-} // end namespace io
-namespace scene
-{
-class IMeshManipulator;
-
-//! Meshloader capable of loading x meshes.
-class CXMeshFileLoader : public IMeshLoader
-{
-public:
-
- //! Constructor
- CXMeshFileLoader(scene::ISceneManager* smgr);
-
- //! returns true if the file maybe is able to be loaded by this class
- //! based on the file extension (e.g. ".cob")
- bool isALoadableFileExtension(const io::path& filename) const override;
-
- //! 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* createMesh(io::IReadFile* file) override;
-
- struct SXMesh
- {
- SXMesh() : MaxSkinWeightsPerVertex(0), MaxSkinWeightsPerFace(0), BoneCount(0),AttachedJointID(-1),HasSkinning(false), HasVertexColors(false) {}
- // this mesh contains triangulated texture data.
- // because in an .x file, faces can be made of more than 3
- // vertices, the indices data structure is triangulated during the
- // loading process. The IndexCountPerFace array is filled during
- // this triangulation process and stores how much indices belong to
- // every face. This data structure can be ignored, because all data
- // in this structure is triangulated.
-
- core::stringc Name;
-
- u32 MaxSkinWeightsPerVertex;
- u32 MaxSkinWeightsPerFace;
- u32 BoneCount;
-
- core::array IndexCountPerFace; // default 3, but could be more
-
- core::array Buffers;
-
- core::array Vertices;
- core::array TCoords2;
-
- core::array Indices;
-
- core::array FaceMaterialIndices; // index of material for each face
-
- core::array Materials; // material array
-
- core::array WeightJoint;
- core::array WeightNum;
-
- s32 AttachedJointID;
-
- bool HasSkinning;
- bool HasVertexColors;
- };
-
-private:
-
- bool load(io::IReadFile* file);
-
- bool readFileIntoMemory(io::IReadFile* file);
-
- bool parseFile();
-
- bool parseDataObject();
-
- bool parseDataObjectTemplate();
-
- bool parseDataObjectFrame(CSkinnedMesh::SJoint *parent);
-
- bool parseDataObjectTransformationMatrix(core::matrix4 &mat);
-
- bool parseDataObjectMesh(SXMesh &mesh);
-
- bool parseDataObjectSkinWeights(SXMesh &mesh);
-
- bool parseDataObjectSkinMeshHeader(SXMesh &mesh);
-
- bool parseDataObjectMeshNormals(SXMesh &mesh);
-
- bool parseDataObjectMeshTextureCoords(SXMesh &mesh);
-
- bool parseDataObjectMeshVertexColors(SXMesh &mesh);
-
- bool parseDataObjectMeshMaterialList(SXMesh &mesh);
-
- bool parseDataObjectAnimationSet();
-
- bool parseDataObjectAnimationTicksPerSecond();
-
- bool parseDataObjectAnimation();
-
- bool parseDataObjectAnimationKey(ISkinnedMesh::SJoint *joint);
-
- bool parseDataObjectTextureFilename(core::stringc& texturename);
-
- bool parseUnknownDataObject();
-
- //! places pointer to next begin of a token, and ignores comments
- void findNextNoneWhiteSpace();
-
- //! places pointer to next begin of a token, which must be a number,
- // and ignores comments
- void findNextNoneWhiteSpaceNumber();
-
- //! returns next parseable token. Returns empty string if no token there
- core::stringc getNextToken();
-
- //! reads header of dataobject including the opening brace.
- //! returns false if error happened, and writes name of object
- //! if there is one
- bool readHeadOfDataObject(core::stringc* outname=0);
-
- //! checks for closing curly brace, returns false if not there
- bool checkForClosingBrace();
-
- //! checks for one following semicolons, returns false if not there
- bool checkForOneFollowingSemicolons();
-
- //! checks for two following semicolons, returns false if they are not there
- bool checkForTwoFollowingSemicolons();
-
- //! reads a x file style string
- bool getNextTokenAsString(core::stringc& out);
-
- void readUntilEndOfLine();
-
- u16 readBinWord();
- u32 readBinDWord();
- u32 readInt();
- f32 readFloat();
- bool readVector2(core::vector2df& vec);
- bool readVector3(core::vector3df& vec);
- bool readMatrix(core::matrix4& mat);
- bool readRGB(video::SColor& color);
- bool readRGBA(video::SColor& color);
-
- CSkinnedMesh* AnimatedMesh;
-
- c8* Buffer;
- const c8* P;
- c8* End;
- // counter for number arrays in binary format
- u32 BinaryNumCount;
- u32 Line;
- io::path FilePath;
-
- bool ErrorState;
-
- CSkinnedMesh::SJoint *CurFrame;
-
- core::array Meshes;
-
- u32 MajorVersion;
- u32 MinorVersion;
- bool BinaryFormat;
- c8 FloatSize;
-};
-
-} // end namespace scene
-} // end namespace irr