diff options
Diffstat (limited to 'libs/assimp/code/AssetLib/X')
-rw-r--r-- | libs/assimp/code/AssetLib/X/XFileExporter.cpp | 541 | ||||
-rw-r--r-- | libs/assimp/code/AssetLib/X/XFileExporter.h | 140 | ||||
-rw-r--r-- | libs/assimp/code/AssetLib/X/XFileHelper.h | 234 | ||||
-rw-r--r-- | libs/assimp/code/AssetLib/X/XFileImporter.cpp | 691 | ||||
-rw-r--r-- | libs/assimp/code/AssetLib/X/XFileImporter.h | 148 | ||||
-rw-r--r-- | libs/assimp/code/AssetLib/X/XFileParser.cpp | 1360 | ||||
-rw-r--r-- | libs/assimp/code/AssetLib/X/XFileParser.h | 158 |
7 files changed, 0 insertions, 3272 deletions
diff --git a/libs/assimp/code/AssetLib/X/XFileExporter.cpp b/libs/assimp/code/AssetLib/X/XFileExporter.cpp deleted file mode 100644 index f0b1608..0000000 --- a/libs/assimp/code/AssetLib/X/XFileExporter.cpp +++ /dev/null @@ -1,541 +0,0 @@ -/* -Open Asset Import Library (assimp) ----------------------------------------------------------------------- - -Copyright (c) 2006-2022, assimp team - - -All rights reserved. - -Redistribution and use of this software in source and binary forms, -with or without modification, are permitted provided that the -following conditions are met: - -* Redistributions of source code must retain the above - copyright notice, this list of conditions and the - following disclaimer. - -* Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the - following disclaimer in the documentation and/or other - materials provided with the distribution. - -* Neither the name of the assimp team, nor the names of its - contributors may be used to endorse or promote products - derived from this software without specific prior - written permission of the assimp team. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -@author: Richard Steffen, 2014 ----------------------------------------------------------------------- -*/ - - -#ifndef ASSIMP_BUILD_NO_EXPORT -#ifndef ASSIMP_BUILD_NO_X_EXPORTER - -#include "AssetLib/X/XFileExporter.h" -#include "PostProcessing/ConvertToLHProcess.h" - -#include <assimp/Bitmap.h> -#include <assimp/BaseImporter.h> -#include <assimp/fast_atof.h> -#include <assimp/SceneCombiner.h> -#include <assimp/DefaultIOSystem.h> -#include <assimp/Exceptional.h> -#include <assimp/IOSystem.hpp> -#include <assimp/scene.h> -#include <assimp/light.h> - -#include <ctime> -#include <set> -#include <memory> - -using namespace Assimp; - -namespace Assimp -{ - -// ------------------------------------------------------------------------------------------------ -// Worker function for exporting a scene to Collada. Prototyped and registered in Exporter.cpp -void ExportSceneXFile(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties) -{ - std::string path = DefaultIOSystem::absolutePath(std::string(pFile)); - std::string file = DefaultIOSystem::completeBaseName(std::string(pFile)); - - // create/copy Properties - ExportProperties props(*pProperties); - - // set standard properties if not set - if (!props.HasPropertyBool(AI_CONFIG_EXPORT_XFILE_64BIT)) props.SetPropertyBool(AI_CONFIG_EXPORT_XFILE_64BIT, false); - - // invoke the exporter - XFileExporter iDoTheExportThing( pScene, pIOSystem, path, file, &props); - - if (iDoTheExportThing.mOutput.fail()) { - throw DeadlyExportError("output data creation failed. Most likely the file became too large: " + std::string(pFile)); - } - - // we're still here - export successfully completed. Write result to the given IOSYstem - std::unique_ptr<IOStream> outfile (pIOSystem->Open(pFile,"wt")); - if (outfile == nullptr) { - throw DeadlyExportError("could not open output .x file: " + std::string(pFile)); - } - - // XXX maybe use a small wrapper around IOStream that behaves like std::stringstream in order to avoid the extra copy. - outfile->Write( iDoTheExportThing.mOutput.str().c_str(), static_cast<size_t>(iDoTheExportThing.mOutput.tellp()),1); -} - -} // end of namespace Assimp - - -// ------------------------------------------------------------------------------------------------ -// Constructor for a specific scene to export -XFileExporter::XFileExporter(const aiScene* pScene, IOSystem* pIOSystem, const std::string& path, const std::string& file, const ExportProperties* pProperties) - : mProperties(pProperties), - mIOSystem(pIOSystem), - mPath(path), - mFile(file), - mScene(pScene), - mSceneOwned(false), - endstr("\n") -{ - // make sure that all formatting happens using the standard, C locale and not the user's current locale - mOutput.imbue( std::locale("C") ); - mOutput.precision(ASSIMP_AI_REAL_TEXT_PRECISION); - - // start writing - WriteFile(); -} - -// ------------------------------------------------------------------------------------------------ -// Destructor -XFileExporter::~XFileExporter() -{ - if(mSceneOwned) { - delete mScene; - } -} - -// ------------------------------------------------------------------------------------------------ -// Starts writing the contents -void XFileExporter::WriteFile() -{ - // note, that all realnumber values must be comma separated in x files - mOutput.setf(std::ios::fixed); - mOutput.precision(ASSIMP_AI_REAL_TEXT_PRECISION); // precision for ai_real - - // entry of writing the file - WriteHeader(); - - mOutput << startstr << "Frame DXCC_ROOT {" << endstr; - PushTag(); - - aiMatrix4x4 I; // identity - WriteFrameTransform(I); - - WriteNode(mScene->mRootNode); - PopTag(); - - mOutput << startstr << "}" << endstr; - -} - -// ------------------------------------------------------------------------------------------------ -// Writes the asset header -void XFileExporter::WriteHeader() -{ - if (mProperties->GetPropertyBool(AI_CONFIG_EXPORT_XFILE_64BIT) == true) - mOutput << startstr << "xof 0303txt 0064" << endstr; - else - mOutput << startstr << "xof 0303txt 0032" << endstr; - mOutput << endstr; - mOutput << startstr << "template Frame {" << endstr; - PushTag(); - mOutput << startstr << "<3d82ab46-62da-11cf-ab39-0020af71e433>" << endstr; - mOutput << startstr << "[...]" << endstr; - PopTag(); - mOutput << startstr << "}" << endstr; - mOutput << endstr; - mOutput << startstr << "template Matrix4x4 {" << endstr; - PushTag(); - mOutput << startstr << "<f6f23f45-7686-11cf-8f52-0040333594a3>" << endstr; - mOutput << startstr << "array FLOAT matrix[16];" << endstr; - PopTag(); - mOutput << startstr << "}" << endstr; - mOutput << endstr; - mOutput << startstr << "template FrameTransformMatrix {" << endstr; - PushTag(); - mOutput << startstr << "<f6f23f41-7686-11cf-8f52-0040333594a3>" << endstr; - mOutput << startstr << "Matrix4x4 frameMatrix;" << endstr; - PopTag(); - mOutput << startstr << "}" << endstr; - mOutput << endstr; - mOutput << startstr << "template Vector {" << endstr; - PushTag(); - mOutput << startstr << "<3d82ab5e-62da-11cf-ab39-0020af71e433>" << endstr; - mOutput << startstr << "FLOAT x;" << endstr; - mOutput << startstr << "FLOAT y;" << endstr; - mOutput << startstr << "FLOAT z;" << endstr; - PopTag(); - mOutput << startstr << "}" << endstr; - mOutput << endstr; - mOutput << startstr << "template MeshFace {" << endstr; - PushTag(); - mOutput << startstr << "<3d82ab5f-62da-11cf-ab39-0020af71e433>" << endstr; - mOutput << startstr << "DWORD nFaceVertexIndices;" << endstr; - mOutput << startstr << "array DWORD faceVertexIndices[nFaceVertexIndices];" << endstr; - PopTag(); - mOutput << startstr << "}" << endstr; - mOutput << endstr; - mOutput << startstr << "template Mesh {" << endstr; - PushTag(); - mOutput << startstr << "<3d82ab44-62da-11cf-ab39-0020af71e433>" << endstr; - mOutput << startstr << "DWORD nVertices;" << endstr; - mOutput << startstr << "array Vector vertices[nVertices];" << endstr; - mOutput << startstr << "DWORD nFaces;" << endstr; - mOutput << startstr << "array MeshFace faces[nFaces];" << endstr; - mOutput << startstr << "[...]" << endstr; - PopTag(); - mOutput << startstr << "}" << endstr; - mOutput << endstr; - mOutput << startstr << "template MeshNormals {" << endstr; - PushTag(); - mOutput << startstr << "<f6f23f43-7686-11cf-8f52-0040333594a3>" << endstr; - mOutput << startstr << "DWORD nNormals;" << endstr; - mOutput << startstr << "array Vector normals[nNormals];" << endstr; - mOutput << startstr << "DWORD nFaceNormals;" << endstr; - mOutput << startstr << "array MeshFace faceNormals[nFaceNormals];" << endstr; - PopTag(); - mOutput << startstr << "}" << endstr; - mOutput << endstr; - mOutput << startstr << "template Coords2d {" << endstr; - PushTag(); - mOutput << startstr << "<f6f23f44-7686-11cf-8f52-0040333594a3>" << endstr; - mOutput << startstr << "FLOAT u;" << endstr; - mOutput << startstr << "FLOAT v;" << endstr; - PopTag(); - mOutput << startstr << "}" << endstr; - mOutput << endstr; - mOutput << startstr << "template MeshTextureCoords {" << endstr; - PushTag(); - mOutput << startstr << "<f6f23f40-7686-11cf-8f52-0040333594a3>" << endstr; - mOutput << startstr << "DWORD nTextureCoords;" << endstr; - mOutput << startstr << "array Coords2d textureCoords[nTextureCoords];" << endstr; - PopTag(); - mOutput << startstr << "}" << endstr; - mOutput << endstr; - mOutput << startstr << "template ColorRGBA {" << endstr; - PushTag(); - mOutput << startstr << "<35ff44e0-6c7c-11cf-8f52-0040333594a3>" << endstr; - mOutput << startstr << "FLOAT red;" << endstr; - mOutput << startstr << "FLOAT green;" << endstr; - mOutput << startstr << "FLOAT blue;" << endstr; - mOutput << startstr << "FLOAT alpha;" << endstr; - PopTag(); - mOutput << startstr << "}" << endstr; - mOutput << endstr; - mOutput << startstr << "template IndexedColor {" << endstr; - PushTag(); - mOutput << startstr << "<1630b820-7842-11cf-8f52-0040333594a3>" << endstr; - mOutput << startstr << "DWORD index;" << endstr; - mOutput << startstr << "ColorRGBA indexColor;" << endstr; - PopTag(); - mOutput << startstr << "}" << endstr; - mOutput << endstr; - mOutput << startstr << "template MeshVertexColors {" << endstr; - PushTag(); - mOutput << startstr << "<1630b821-7842-11cf-8f52-0040333594a3>" << endstr; - mOutput << startstr << "DWORD nVertexColors;" << endstr; - mOutput << startstr << "array IndexedColor vertexColors[nVertexColors];" << endstr; - PopTag(); - mOutput << startstr << "}" << endstr; - mOutput << endstr; - mOutput << startstr << "template VertexElement {" << endstr; - PushTag(); - mOutput << startstr << "<f752461c-1e23-48f6-b9f8-8350850f336f>" << endstr; - mOutput << startstr << "DWORD Type;" << endstr; - mOutput << startstr << "DWORD Method;" << endstr; - mOutput << startstr << "DWORD Usage;" << endstr; - mOutput << startstr << "DWORD UsageIndex;" << endstr; - PopTag(); - mOutput << startstr << "}" << endstr; - mOutput << endstr; - mOutput << startstr << "template DeclData {" << endstr; - PushTag(); - mOutput << startstr << "<bf22e553-292c-4781-9fea-62bd554bdd93>" << endstr; - mOutput << startstr << "DWORD nElements;" << endstr; - mOutput << startstr << "array VertexElement Elements[nElements];" << endstr; - mOutput << startstr << "DWORD nDWords;" << endstr; - mOutput << startstr << "array DWORD data[nDWords];" << endstr; - PopTag(); - mOutput << startstr << "}" << endstr; - mOutput << endstr; -} - - -// Writes the material setup -void XFileExporter::WriteFrameTransform(aiMatrix4x4& m) -{ - mOutput << startstr << "FrameTransformMatrix {" << endstr << " "; - PushTag(); - mOutput << startstr << m.a1 << ", " << m.b1 << ", " << m.c1 << ", " << m.d1 << "," << endstr; - mOutput << startstr << m.a2 << ", " << m.b2 << ", " << m.c2 << ", " << m.d2 << "," << endstr; - mOutput << startstr << m.a3 << ", " << m.b3 << ", " << m.c3 << ", " << m.d3 << "," << endstr; - mOutput << startstr << m.a4 << ", " << m.b4 << ", " << m.c4 << ", " << m.d4 << ";;" << endstr; - PopTag(); - mOutput << startstr << "}" << endstr << endstr; -} - - -// ------------------------------------------------------------------------------------------------ -// Recursively writes the given node -void XFileExporter::WriteNode( aiNode* pNode) -{ - if (pNode->mName.length==0) - { - std::stringstream ss; - ss << "Node_" << pNode; - pNode->mName.Set(ss.str()); - } - mOutput << startstr << "Frame " << toXFileString(pNode->mName) << " {" << endstr; - - PushTag(); - - aiMatrix4x4 m = pNode->mTransformation; - - WriteFrameTransform(m); - - for (size_t i = 0; i < pNode->mNumMeshes; ++i) - WriteMesh(mScene->mMeshes[pNode->mMeshes[i]]); - - // recursive call the Nodes - for (size_t i = 0; i < pNode->mNumChildren; ++i) - WriteNode(pNode->mChildren[i]); - - PopTag(); - - mOutput << startstr << "}" << endstr << endstr; -} - -void XFileExporter::WriteMesh(aiMesh* mesh) -{ - mOutput << startstr << "Mesh " << toXFileString(mesh->mName) << "_mShape" << " {" << endstr; - - PushTag(); - - // write all the vertices - mOutput << startstr << mesh->mNumVertices << ";" << endstr; - for (size_t a = 0; a < mesh->mNumVertices; a++) - { - aiVector3D &v = mesh->mVertices[a]; - mOutput << startstr << v[0] << ";"<< v[1] << ";" << v[2] << ";"; - if (a < mesh->mNumVertices - 1) - mOutput << "," << endstr; - else - mOutput << ";" << endstr; - } - - // write all the faces - mOutput << startstr << mesh->mNumFaces << ";" << endstr; - for( size_t a = 0; a < mesh->mNumFaces; ++a ) - { - const aiFace& face = mesh->mFaces[a]; - mOutput << startstr << face.mNumIndices << ";"; - // must be counter clockwise triangle - //for(int b = face.mNumIndices - 1; b >= 0 ; --b) - for(size_t b = 0; b < face.mNumIndices ; ++b) - { - mOutput << face.mIndices[b]; - //if (b > 0) - if (b<face.mNumIndices-1) - mOutput << ","; - else - mOutput << ";"; - } - - if (a < mesh->mNumFaces - 1) - mOutput << "," << endstr; - else - mOutput << ";" << endstr; - } - - mOutput << endstr; - - if (mesh->HasTextureCoords(0)) - { - const aiMaterial* mat = mScene->mMaterials[mesh->mMaterialIndex]; - aiString relpath; - mat->Get(_AI_MATKEY_TEXTURE_BASE, aiTextureType_DIFFUSE, 0, relpath); - - mOutput << startstr << "MeshMaterialList {" << endstr; - PushTag(); - mOutput << startstr << "1;" << endstr; // number of materials - mOutput << startstr << mesh->mNumFaces << ";" << endstr; // number of faces - mOutput << startstr; - for( size_t a = 0; a < mesh->mNumFaces; ++a ) - { - mOutput << "0"; // the material index - if (a < mesh->mNumFaces - 1) - mOutput << ", "; - else - mOutput << ";" << endstr; - } - mOutput << startstr << "Material {" << endstr; - PushTag(); - mOutput << startstr << "1.0; 1.0; 1.0; 1.000000;;" << endstr; - mOutput << startstr << "1.000000;" << endstr; // power - mOutput << startstr << "0.000000; 0.000000; 0.000000;;" << endstr; // specularity - mOutput << startstr << "0.000000; 0.000000; 0.000000;;" << endstr; // emission - mOutput << startstr << "TextureFilename { \""; - - writePath(relpath); - - mOutput << "\"; }" << endstr; - PopTag(); - mOutput << startstr << "}" << endstr; - PopTag(); - mOutput << startstr << "}" << endstr; - } - - // write normals (every vertex has one) - if (mesh->HasNormals()) - { - mOutput << endstr << startstr << "MeshNormals {" << endstr; - mOutput << startstr << mesh->mNumVertices << ";" << endstr; - for (size_t a = 0; a < mesh->mNumVertices; a++) - { - aiVector3D &v = mesh->mNormals[a]; - // because we have a LHS and also changed wth winding, we need to invert the normals again - mOutput << startstr << -v[0] << ";"<< -v[1] << ";" << -v[2] << ";"; - if (a < mesh->mNumVertices - 1) - mOutput << "," << endstr; - else - mOutput << ";" << endstr; - } - - mOutput << startstr << mesh->mNumFaces << ";" << endstr; - for (size_t a = 0; a < mesh->mNumFaces; a++) - { - const aiFace& face = mesh->mFaces[a]; - mOutput << startstr << face.mNumIndices << ";"; - - //for(int b = face.mNumIndices-1; b >= 0 ; --b) - for(size_t b = 0; b < face.mNumIndices ; ++b) - { - mOutput << face.mIndices[b]; - //if (b > 0) - if (b<face.mNumIndices-1) - mOutput << ","; - else - mOutput << ";"; - } - - if (a < mesh->mNumFaces-1) - mOutput << "," << endstr; - else - mOutput << ";" << endstr; - } - mOutput << startstr << "}" << endstr; - } - - // write texture UVs if available - if (mesh->HasTextureCoords(0)) - { - mOutput << endstr << startstr << "MeshTextureCoords {" << endstr; - mOutput << startstr << mesh->mNumVertices << ";" << endstr; - for (size_t a = 0; a < mesh->mNumVertices; a++) - //for (int a = (int)mesh->mNumVertices-1; a >=0 ; a--) - { - aiVector3D& uv = mesh->mTextureCoords[0][a]; // uv of first uv layer for the vertex - mOutput << startstr << uv.x << ";" << uv.y; - if (a < mesh->mNumVertices-1) - //if (a >0 ) - mOutput << ";," << endstr; - else - mOutput << ";;" << endstr; - } - mOutput << startstr << "}" << endstr; - } - - // write color channel if available - if (mesh->HasVertexColors(0)) - { - mOutput << endstr << startstr << "MeshVertexColors {" << endstr; - mOutput << startstr << mesh->mNumVertices << ";" << endstr; - for (size_t a = 0; a < mesh->mNumVertices; a++) - { - aiColor4D& mColors = mesh->mColors[0][a]; // color of first vertex color set for the vertex - mOutput << startstr << a << ";" << mColors.r << ";" << mColors.g << ";" << mColors.b << ";" << mColors.a << ";;"; - if (a < mesh->mNumVertices-1) - mOutput << "," << endstr; - else - mOutput << ";" << endstr; - } - mOutput << startstr << "}" << endstr; - } - /* - else - { - mOutput << endstr << startstr << "MeshVertexColors {" << endstr; - mOutput << startstr << mesh->mNumVertices << ";" << endstr; - for (size_t a = 0; a < mesh->mNumVertices; a++) - { - aiColor4D* mColors = mesh->mColors[a]; - mOutput << startstr << a << ";0.500000;0.000000;0.000000;0.500000;;"; - if (a < mesh->mNumVertices-1) - mOutput << "," << endstr; - else - mOutput << ";" << endstr; - } - mOutput << startstr << "}" << endstr; - } - */ - PopTag(); - mOutput << startstr << "}" << endstr << endstr; - -} - -std::string XFileExporter::toXFileString(aiString &name) -{ - std::string pref = ""; // node name prefix to prevent unexpected start of string - std::string str = pref + std::string(name.C_Str()); - for (int i=0; i < (int) str.length(); ++i) - { - if ((str[i] >= '0' && str[i] <= '9') || // 0-9 - (str[i] >= 'A' && str[i] <= 'Z') || // A-Z - (str[i] >= 'a' && str[i] <= 'z')) // a-z - continue; - str[i] = '_'; - } - return str; -} - -void XFileExporter::writePath(const aiString &path) -{ - std::string str = std::string(path.C_Str()); - BaseImporter::ConvertUTF8toISO8859_1(str); - - while( str.find( "\\\\") != std::string::npos) - str.replace( str.find( "\\\\"), 2, "\\"); - - while (str.find('\\') != std::string::npos) - str.replace(str.find('\\'), 1, "/"); - - mOutput << str; - -} - -#endif -#endif diff --git a/libs/assimp/code/AssetLib/X/XFileExporter.h b/libs/assimp/code/AssetLib/X/XFileExporter.h deleted file mode 100644 index 1d9a5ae..0000000 --- a/libs/assimp/code/AssetLib/X/XFileExporter.h +++ /dev/null @@ -1,140 +0,0 @@ -/* -Open Asset Import Library (assimp) ----------------------------------------------------------------------- - -Copyright (c) 2006-2022, assimp team - - -All rights reserved. - -Redistribution and use of this software in source and binary forms, -with or without modification, are permitted provided that the -following conditions are met: - -* Redistributions of source code must retain the above - copyright notice, this list of conditions and the - following disclaimer. - -* Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the - following disclaimer in the documentation and/or other - materials provided with the distribution. - -* Neither the name of the assimp team, nor the names of its - contributors may be used to endorse or promote products - derived from this software without specific prior - written permission of the assimp team. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -@author: Richard Steffen, 2014 - ----------------------------------------------------------------------- -*/ - -/** @file XFileExporter.h - * Declares the exporter class to write a scene to a Collada file - */ -#ifndef AI_XFILEEXPORTER_H_INC -#define AI_XFILEEXPORTER_H_INC - -#include <assimp/ai_assert.h> -#include <assimp/matrix4x4.h> -#include <assimp/Exporter.hpp> -#include <sstream> - -struct aiScene; -struct aiNode; -struct aiMesh; -struct aiString; - -namespace Assimp { - -class IOSystem; - - -/// Helper class to export a given scene to a X-file. -/// Note: an xFile uses a left hand system. Assimp used a right hand system (OpenGL), therefore we have to transform everything -class XFileExporter -{ -public: - /// Constructor for a specific scene to export - XFileExporter(const aiScene* pScene, IOSystem* pIOSystem, const std::string& path, const std::string& file, const ExportProperties* pProperties); - - /// Destructor - virtual ~XFileExporter(); - -protected: - /// Starts writing the contents - void WriteFile(); - - /// Writes the asset header - void WriteHeader(); - - /// write a frame transform - void WriteFrameTransform(aiMatrix4x4& m); - - /// Recursively writes the given node - void WriteNode( aiNode* pNode ); - - /// write a mesh entry of the scene - void WriteMesh( aiMesh* mesh); - - /// Enters a new xml element, which increases the indentation - void PushTag() { startstr.append( " "); } - - /// Leaves an element, decreasing the indentation - void PopTag() { - ai_assert( startstr.length() > 1); - startstr.erase( startstr.length() - 2); - } - -public: - /// Stringstream to write all output into - std::stringstream mOutput; - -protected: - - /// normalize the name to be accepted by xfile readers - std::string toXFileString(aiString &name); - - /// hold the properties pointer - const ExportProperties* mProperties; - - /// write a path - void writePath(const aiString &path); - - /// The IOSystem for output - IOSystem* mIOSystem; - - /// Path of the directory where the scene will be exported - const std::string mPath; - - /// Name of the file (without extension) where the scene will be exported - const std::string mFile; - - /// The scene to be written - const aiScene* mScene; - bool mSceneOwned; - - /// current line start string, contains the current indentation for simple stream insertion - std::string startstr; - - /// current line end string for simple stream insertion - std::string endstr; - -}; - -} - -#endif // !! AI_XFILEEXPORTER_H_INC diff --git a/libs/assimp/code/AssetLib/X/XFileHelper.h b/libs/assimp/code/AssetLib/X/XFileHelper.h deleted file mode 100644 index 3830eb4..0000000 --- a/libs/assimp/code/AssetLib/X/XFileHelper.h +++ /dev/null @@ -1,234 +0,0 @@ -/* -Open Asset Import Library (assimp) ----------------------------------------------------------------------- - -Copyright (c) 2006-2022, assimp team - - -All rights reserved. - -Redistribution and use of this software in source and binary forms, -with or without modification, are permitted provided that the -following conditions are met: - -* Redistributions of source code must retain the above - copyright notice, this list of conditions and the - following disclaimer. - -* Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the - following disclaimer in the documentation and/or other - materials provided with the distribution. - -* Neither the name of the assimp team, nor the names of its - contributors may be used to endorse or promote products - derived from this software without specific prior - written permission of the assimp team. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ----------------------------------------------------------------------- -*/ - -/** @file Defines the helper data structures for importing XFiles */ -#ifndef AI_XFILEHELPER_H_INC -#define AI_XFILEHELPER_H_INC - -#include <cstdint> -#include <string> -#include <vector> - -#include <assimp/anim.h> -#include <assimp/mesh.h> -#include <assimp/quaternion.h> -#include <assimp/types.h> - -namespace Assimp { -namespace XFile { - -/** Helper structure representing a XFile mesh face */ -struct Face { - std::vector<unsigned int> mIndices; -}; - -/** Helper structure representing a texture filename inside a material and its potential source */ -struct TexEntry { - std::string mName; - bool mIsNormalMap; // true if the texname was specified in a NormalmapFilename tag - - TexEntry() AI_NO_EXCEPT : - mName(), - mIsNormalMap(false) { - // empty - } - TexEntry(const std::string &pName, bool pIsNormalMap = false) : - mName(pName), mIsNormalMap(pIsNormalMap) { - // empty - } -}; - -/** Helper structure representing a XFile material */ -struct Material { - std::string mName; - bool mIsReference; // if true, mName holds a name by which the actual material can be found in the material list - aiColor4D mDiffuse; - ai_real mSpecularExponent; - aiColor3D mSpecular; - aiColor3D mEmissive; - std::vector<TexEntry> mTextures; - size_t sceneIndex; ///< the index under which it was stored in the scene's material list - - Material() AI_NO_EXCEPT : - mIsReference(false), - mSpecularExponent(), - sceneIndex(SIZE_MAX) { - // empty - } -}; - -/** Helper structure to represent a bone weight */ -struct BoneWeight { - unsigned int mVertex; - ai_real mWeight; -}; - -/** Helper structure to represent a bone in a mesh */ -struct Bone { - std::string mName; - std::vector<BoneWeight> mWeights; - aiMatrix4x4 mOffsetMatrix; -}; - -/** Helper structure to represent an XFile mesh */ -struct Mesh { - std::string mName; - std::vector<aiVector3D> mPositions; - std::vector<Face> mPosFaces; - std::vector<aiVector3D> mNormals; - std::vector<Face> mNormFaces; - unsigned int mNumTextures; - std::vector<aiVector2D> mTexCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS]; - unsigned int mNumColorSets; - std::vector<aiColor4D> mColors[AI_MAX_NUMBER_OF_COLOR_SETS]; - - std::vector<unsigned int> mFaceMaterials; - std::vector<Material> mMaterials; - - std::vector<Bone> mBones; - - explicit Mesh(const std::string &pName = std::string()) AI_NO_EXCEPT - : mName(pName), - mPositions(), - mPosFaces(), - mNormals(), - mNormFaces(), - mNumTextures(0), - mTexCoords{}, - mNumColorSets(0), - mColors{}, - mFaceMaterials(), - mMaterials(), - mBones() { - // empty - } -}; - -/** Helper structure to represent a XFile frame */ -struct Node { - std::string mName; - aiMatrix4x4 mTrafoMatrix; - Node *mParent; - std::vector<Node *> mChildren; - std::vector<Mesh *> mMeshes; - - Node() AI_NO_EXCEPT - : mName(), - mTrafoMatrix(), - mParent(nullptr), - mChildren(), - mMeshes() { - // empty - } - explicit Node(Node *pParent) : - mName(), mTrafoMatrix(), mParent(pParent), mChildren(), mMeshes() { - // empty - } - - ~Node() { - for (unsigned int a = 0; a < mChildren.size(); ++a) { - delete mChildren[a]; - } - for (unsigned int a = 0; a < mMeshes.size(); ++a) { - delete mMeshes[a]; - } - } -}; - -struct MatrixKey { - double mTime; - aiMatrix4x4 mMatrix; -}; - -/** Helper structure representing a single animated bone in a XFile */ -struct AnimBone { - std::string mBoneName; - std::vector<aiVectorKey> mPosKeys; // either three separate key sequences for position, rotation, scaling - std::vector<aiQuatKey> mRotKeys; - std::vector<aiVectorKey> mScaleKeys; - std::vector<MatrixKey> mTrafoKeys; // or a combined key sequence of transformation matrices. -}; - -/** Helper structure to represent an animation set in a XFile */ -struct Animation { - std::string mName; - std::vector<AnimBone *> mAnims; - - ~Animation() { - for (unsigned int a = 0; a < mAnims.size(); a++) - delete mAnims[a]; - } -}; - -/** Helper structure analogue to aiScene */ -struct Scene { - Node *mRootNode; - - std::vector<Mesh *> mGlobalMeshes; // global meshes found outside of any frames - std::vector<Material> mGlobalMaterials; // global materials found outside of any meshes. - - std::vector<Animation *> mAnims; - unsigned int mAnimTicksPerSecond; - - Scene() AI_NO_EXCEPT - : mRootNode(nullptr), - mGlobalMeshes(), - mGlobalMaterials(), - mAnimTicksPerSecond(0) { - // empty - } - ~Scene() { - delete mRootNode; - mRootNode = nullptr; - for (unsigned int a = 0; a < mGlobalMeshes.size(); ++a) { - delete mGlobalMeshes[a]; - } - for (unsigned int a = 0; a < mAnims.size(); ++a) { - delete mAnims[a]; - } - } -}; - -} // end of namespace XFile -} // end of namespace Assimp - -#endif // AI_XFILEHELPER_H_INC diff --git a/libs/assimp/code/AssetLib/X/XFileImporter.cpp b/libs/assimp/code/AssetLib/X/XFileImporter.cpp deleted file mode 100644 index d23eb57..0000000 --- a/libs/assimp/code/AssetLib/X/XFileImporter.cpp +++ /dev/null @@ -1,691 +0,0 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (assimp) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2022, assimp team - -All rights reserved. - -Redistribution and use of this software in source and binary forms, -with or without modification, are permitted provided that the following -conditions are met: - -* Redistributions of source code must retain the above -copyright notice, this list of conditions and the -following disclaimer. - -* Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the -following disclaimer in the documentation and/or other -materials provided with the distribution. - -* Neither the name of the assimp team, nor the names of its -contributors may be used to endorse or promote products -derived from this software without specific prior -written permission of the assimp team. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ---------------------------------------------------------------------------- -*/ -/** @file XFileImporter.cpp - * @brief Implementation of the XFile importer class - */ - -#ifndef ASSIMP_BUILD_NO_X_IMPORTER - -#include "AssetLib/X/XFileImporter.h" -#include "AssetLib/X/XFileParser.h" -#include "PostProcessing/ConvertToLHProcess.h" - -#include <assimp/TinyFormatter.h> -#include <assimp/IOSystem.hpp> -#include <assimp/scene.h> -#include <assimp/DefaultLogger.hpp> -#include <assimp/importerdesc.h> - -#include <cctype> -#include <memory> - -using namespace Assimp; -using namespace Assimp::Formatter; - -static const aiImporterDesc desc = { - "Direct3D XFile Importer", - "", - "", - "", - aiImporterFlags_SupportTextFlavour | aiImporterFlags_SupportBinaryFlavour | aiImporterFlags_SupportCompressedFlavour, - 1, - 3, - 1, - 5, - "x" -}; - -// ------------------------------------------------------------------------------------------------ -// Constructor to be privately used by Importer -XFileImporter::XFileImporter() -: mBuffer() { - // empty -} - -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -XFileImporter::~XFileImporter() { - // empty -} - -// ------------------------------------------------------------------------------------------------ -// Returns whether the class can handle the format of the given file. -bool XFileImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool /*checkSig*/) const { - static const uint32_t token[] = { AI_MAKE_MAGIC("xof ") }; - return CheckMagicToken(pIOHandler,pFile,token,AI_COUNT_OF(token)); -} - -// ------------------------------------------------------------------------------------------------ -// Get file extension list -const aiImporterDesc* XFileImporter::GetInfo () const { - return &desc; -} - -// ------------------------------------------------------------------------------------------------ -// Imports the given file into the given scene structure. -void XFileImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) { - // read file into memory - std::unique_ptr<IOStream> file( pIOHandler->Open( pFile)); - if ( file.get() == nullptr ) { - throw DeadlyImportError( "Failed to open file ", pFile, "." ); - } - - static const size_t MinSize = 16; - size_t fileSize = file->FileSize(); - if ( fileSize < MinSize ) { - throw DeadlyImportError( "XFile is too small." ); - } - - // in the hope that binary files will never start with a BOM ... - mBuffer.resize( fileSize + 1); - file->Read( &mBuffer.front(), 1, fileSize); - ConvertToUTF8(mBuffer); - - // parse the file into a temporary representation - XFileParser parser( mBuffer); - - // and create the proper return structures out of it - CreateDataRepresentationFromImport( pScene, parser.GetImportedData()); - - // if nothing came from it, report it as error - if ( !pScene->mRootNode ) { - throw DeadlyImportError( "XFile is ill-formatted - no content imported." ); - } -} - -// ------------------------------------------------------------------------------------------------ -// Constructs the return data structure out of the imported data. -void XFileImporter::CreateDataRepresentationFromImport( aiScene* pScene, XFile::Scene* pData) -{ - // Read the global materials first so that meshes referring to them can find them later - ConvertMaterials( pScene, pData->mGlobalMaterials); - - // copy nodes, extracting meshes and materials on the way - pScene->mRootNode = CreateNodes( pScene, nullptr, pData->mRootNode); - - // extract animations - CreateAnimations( pScene, pData); - - // read the global meshes that were stored outside of any node - if( !pData->mGlobalMeshes.empty() ) { - // create a root node to hold them if there isn't any, yet - if( pScene->mRootNode == nullptr ) { - pScene->mRootNode = new aiNode; - pScene->mRootNode->mName.Set( "$dummy_node"); - } - - // convert all global meshes and store them in the root node. - // If there was one before, the global meshes now suddenly have its transformation matrix... - // Don't know what to do there, I don't want to insert another node under the present root node - // just to avoid this. - CreateMeshes( pScene, pScene->mRootNode, pData->mGlobalMeshes); - } - - if (!pScene->mRootNode) { - throw DeadlyImportError( "No root node" ); - } - - // Convert everything to OpenGL space... it's the same operation as the conversion back, so we can reuse the step directly - MakeLeftHandedProcess convertProcess; - convertProcess.Execute( pScene); - - FlipWindingOrderProcess flipper; - flipper.Execute(pScene); - - // finally: create a dummy material if not material was imported - if( pScene->mNumMaterials == 0) { - pScene->mNumMaterials = 1; - // create the Material - aiMaterial* mat = new aiMaterial; - int shadeMode = (int) aiShadingMode_Gouraud; - mat->AddProperty<int>( &shadeMode, 1, AI_MATKEY_SHADING_MODEL); - // material colours - int specExp = 1; - - aiColor3D clr = aiColor3D( 0, 0, 0); - mat->AddProperty( &clr, 1, AI_MATKEY_COLOR_EMISSIVE); - mat->AddProperty( &clr, 1, AI_MATKEY_COLOR_SPECULAR); - - clr = aiColor3D( 0.5f, 0.5f, 0.5f); - mat->AddProperty( &clr, 1, AI_MATKEY_COLOR_DIFFUSE); - mat->AddProperty( &specExp, 1, AI_MATKEY_SHININESS); - - pScene->mMaterials = new aiMaterial*[1]; - pScene->mMaterials[0] = mat; - } -} - -// ------------------------------------------------------------------------------------------------ -// Recursively creates scene nodes from the imported hierarchy. -aiNode* XFileImporter::CreateNodes( aiScene* pScene, aiNode* pParent, const XFile::Node* pNode) { - if ( !pNode ) { - return nullptr; - } - - // create node - aiNode* node = new aiNode; - node->mName.length = (ai_uint32)pNode->mName.length(); - node->mParent = pParent; - memcpy( node->mName.data, pNode->mName.c_str(), pNode->mName.length()); - node->mName.data[node->mName.length] = 0; - node->mTransformation = pNode->mTrafoMatrix; - - // convert meshes from the source node - CreateMeshes( pScene, node, pNode->mMeshes); - - // handle children - if( !pNode->mChildren.empty() ) { - node->mNumChildren = (unsigned int)pNode->mChildren.size(); - node->mChildren = new aiNode* [node->mNumChildren]; - - for ( unsigned int a = 0; a < pNode->mChildren.size(); ++a ) { - node->mChildren[ a ] = CreateNodes( pScene, node, pNode->mChildren[ a ] ); - } - } - - return node; -} - -// ------------------------------------------------------------------------------------------------ -// Creates the meshes for the given node. -void XFileImporter::CreateMeshes( aiScene* pScene, aiNode* pNode, const std::vector<XFile::Mesh*>& pMeshes) { - if (pMeshes.empty()) { - return; - } - - // create a mesh for each mesh-material combination in the source node - std::vector<aiMesh*> meshes; - for( unsigned int a = 0; a < pMeshes.size(); ++a ) { - XFile::Mesh* sourceMesh = pMeshes[a]; - if ( nullptr == sourceMesh ) { - continue; - } - - // first convert its materials so that we can find them with their index afterwards - ConvertMaterials( pScene, sourceMesh->mMaterials); - - unsigned int numMaterials = std::max( (unsigned int)sourceMesh->mMaterials.size(), 1u); - for( unsigned int b = 0; b < numMaterials; ++b ) { - // collect the faces belonging to this material - std::vector<unsigned int> faces; - unsigned int numVertices = 0; - if( !sourceMesh->mFaceMaterials.empty() ) { - // if there is a per-face material defined, select the faces with the corresponding material - for( unsigned int c = 0; c < sourceMesh->mFaceMaterials.size(); ++c ) { - if( sourceMesh->mFaceMaterials[c] == b) { - faces.push_back( c); - numVertices += (unsigned int)sourceMesh->mPosFaces[c].mIndices.size(); - } - } - } else { - // if there is no per-face material, place everything into one mesh - for( unsigned int c = 0; c < sourceMesh->mPosFaces.size(); ++c ) { - faces.push_back( c); - numVertices += (unsigned int)sourceMesh->mPosFaces[c].mIndices.size(); - } - } - - // no faces/vertices using this material? strange... - if ( numVertices == 0 ) { - continue; - } - - // create a submesh using this material - aiMesh* mesh = new aiMesh; - meshes.push_back( mesh); - - // find the material in the scene's material list. Either own material - // or referenced material, it should already have a valid index - if( !sourceMesh->mFaceMaterials.empty() ) { - mesh->mMaterialIndex = static_cast<unsigned int>(sourceMesh->mMaterials[b].sceneIndex); - } else { - mesh->mMaterialIndex = 0; - } - - // Create properly sized data arrays in the mesh. We store unique vertices per face, - // as specified - mesh->mNumVertices = numVertices; - mesh->mVertices = new aiVector3D[numVertices]; - mesh->mNumFaces = (unsigned int)faces.size(); - mesh->mFaces = new aiFace[mesh->mNumFaces]; - - // name - mesh->mName.Set(sourceMesh->mName); - - // normals? - if ( sourceMesh->mNormals.size() > 0 ) { - mesh->mNormals = new aiVector3D[ numVertices ]; - } - // texture coords - for( unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++c ) { - if ( !sourceMesh->mTexCoords[ c ].empty() ) { - mesh->mTextureCoords[ c ] = new aiVector3D[ numVertices ]; - } - } - // vertex colors - for( unsigned int c = 0; c < AI_MAX_NUMBER_OF_COLOR_SETS; ++c ) { - if ( !sourceMesh->mColors[ c ].empty() ) { - mesh->mColors[ c ] = new aiColor4D[ numVertices ]; - } - } - - // now collect the vertex data of all data streams present in the imported mesh - unsigned int newIndex( 0 ); - std::vector<unsigned int> orgPoints; // from which original point each new vertex stems - orgPoints.resize( numVertices, 0); - - for( unsigned int c = 0; c < faces.size(); ++c ) { - unsigned int f = faces[c]; // index of the source face - const XFile::Face& pf = sourceMesh->mPosFaces[f]; // position source face - - // create face. either triangle or triangle fan depending on the index count - aiFace& df = mesh->mFaces[c]; // destination face - df.mNumIndices = (unsigned int)pf.mIndices.size(); - df.mIndices = new unsigned int[ df.mNumIndices]; - - // collect vertex data for indices of this face - for( unsigned int d = 0; d < df.mNumIndices; ++d ) { - df.mIndices[ d ] = newIndex; - const unsigned int newIdx( pf.mIndices[ d ] ); - if ( newIdx > sourceMesh->mPositions.size() ) { - continue; - } - - orgPoints[newIndex] = pf.mIndices[d]; - - // Position - mesh->mVertices[newIndex] = sourceMesh->mPositions[pf.mIndices[d]]; - // Normal, if present - if ( mesh->HasNormals() ) { - if ( sourceMesh->mNormFaces[ f ].mIndices.size() > d ) { - const size_t idx( sourceMesh->mNormFaces[ f ].mIndices[ d ] ); - mesh->mNormals[ newIndex ] = sourceMesh->mNormals[ idx ]; - } - } - - // texture coord sets - for( unsigned int e = 0; e < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++e ) { - if( mesh->HasTextureCoords( e)) { - aiVector2D tex = sourceMesh->mTexCoords[e][pf.mIndices[d]]; - mesh->mTextureCoords[e][newIndex] = aiVector3D( tex.x, 1.0f - tex.y, 0.0f); - } - } - // vertex color sets - for ( unsigned int e = 0; e < AI_MAX_NUMBER_OF_COLOR_SETS; ++e ) { - if ( mesh->HasVertexColors( e ) ) { - mesh->mColors[ e ][ newIndex ] = sourceMesh->mColors[ e ][ pf.mIndices[ d ] ]; - } - } - - newIndex++; - } - } - - // there should be as much new vertices as we calculated before - ai_assert( newIndex == numVertices); - - // convert all bones of the source mesh which influence vertices in this newly created mesh - const std::vector<XFile::Bone>& bones = sourceMesh->mBones; - std::vector<aiBone*> newBones; - for( unsigned int c = 0; c < bones.size(); ++c ) { - const XFile::Bone& obone = bones[c]; - // set up a vertex-linear array of the weights for quick searching if a bone influences a vertex - std::vector<ai_real> oldWeights( sourceMesh->mPositions.size(), 0.0); - for ( unsigned int d = 0; d < obone.mWeights.size(); ++d ) { - oldWeights[ obone.mWeights[ d ].mVertex ] = obone.mWeights[ d ].mWeight; - } - - // collect all vertex weights that influence a vertex in the new mesh - std::vector<aiVertexWeight> newWeights; - newWeights.reserve( numVertices); - for( unsigned int d = 0; d < orgPoints.size(); ++d ) { - // does the new vertex stem from an old vertex which was influenced by this bone? - ai_real w = oldWeights[orgPoints[d]]; - if ( w > 0.0 ) { - newWeights.push_back( aiVertexWeight( d, w ) ); - } - } - - // if the bone has no weights in the newly created mesh, ignore it - if ( newWeights.empty() ) { - continue; - } - - // create - aiBone* nbone = new aiBone; - newBones.push_back( nbone); - // copy name and matrix - nbone->mName.Set( obone.mName); - nbone->mOffsetMatrix = obone.mOffsetMatrix; - nbone->mNumWeights = (unsigned int)newWeights.size(); - nbone->mWeights = new aiVertexWeight[nbone->mNumWeights]; - for ( unsigned int d = 0; d < newWeights.size(); ++d ) { - nbone->mWeights[ d ] = newWeights[ d ]; - } - } - - // store the bones in the mesh - mesh->mNumBones = (unsigned int)newBones.size(); - if( !newBones.empty()) { - mesh->mBones = new aiBone*[mesh->mNumBones]; - std::copy( newBones.begin(), newBones.end(), mesh->mBones); - } - } - } - - // reallocate scene mesh array to be large enough - aiMesh** prevArray = pScene->mMeshes; - pScene->mMeshes = new aiMesh*[pScene->mNumMeshes + meshes.size()]; - if( prevArray) { - memcpy( pScene->mMeshes, prevArray, pScene->mNumMeshes * sizeof( aiMesh*)); - delete [] prevArray; - } - - // allocate mesh index array in the node - pNode->mNumMeshes = (unsigned int)meshes.size(); - pNode->mMeshes = new unsigned int[pNode->mNumMeshes]; - - // store all meshes in the mesh library of the scene and store their indices in the node - for( unsigned int a = 0; a < meshes.size(); a++) { - pScene->mMeshes[pScene->mNumMeshes] = meshes[a]; - pNode->mMeshes[a] = pScene->mNumMeshes; - pScene->mNumMeshes++; - } -} - -// ------------------------------------------------------------------------------------------------ -// Converts the animations from the given imported data and creates them in the scene. -void XFileImporter::CreateAnimations( aiScene* pScene, const XFile::Scene* pData) { - std::vector<aiAnimation*> newAnims; - - for( unsigned int a = 0; a < pData->mAnims.size(); ++a ) { - const XFile::Animation* anim = pData->mAnims[a]; - // some exporters mock me with empty animation tags. - if ( anim->mAnims.empty() ) { - continue; - } - - // create a new animation to hold the data - aiAnimation* nanim = new aiAnimation; - newAnims.push_back( nanim); - nanim->mName.Set( anim->mName); - // duration will be determined by the maximum length - nanim->mDuration = 0; - nanim->mTicksPerSecond = pData->mAnimTicksPerSecond; - nanim->mNumChannels = (unsigned int)anim->mAnims.size(); - nanim->mChannels = new aiNodeAnim*[nanim->mNumChannels]; - - for( unsigned int b = 0; b < anim->mAnims.size(); ++b ) { - const XFile::AnimBone* bone = anim->mAnims[b]; - aiNodeAnim* nbone = new aiNodeAnim; - nbone->mNodeName.Set( bone->mBoneName); - nanim->mChannels[b] = nbone; - - // key-frames are given as combined transformation matrix keys - if( !bone->mTrafoKeys.empty() ) - { - nbone->mNumPositionKeys = (unsigned int)bone->mTrafoKeys.size(); - nbone->mPositionKeys = new aiVectorKey[nbone->mNumPositionKeys]; - nbone->mNumRotationKeys = (unsigned int)bone->mTrafoKeys.size(); - nbone->mRotationKeys = new aiQuatKey[nbone->mNumRotationKeys]; - nbone->mNumScalingKeys = (unsigned int)bone->mTrafoKeys.size(); - nbone->mScalingKeys = new aiVectorKey[nbone->mNumScalingKeys]; - - for( unsigned int c = 0; c < bone->mTrafoKeys.size(); ++c) { - // deconstruct each matrix into separate position, rotation and scaling - double time = bone->mTrafoKeys[c].mTime; - aiMatrix4x4 trafo = bone->mTrafoKeys[c].mMatrix; - - // extract position - aiVector3D pos( trafo.a4, trafo.b4, trafo.c4); - - nbone->mPositionKeys[c].mTime = time; - nbone->mPositionKeys[c].mValue = pos; - - // extract scaling - aiVector3D scale; - scale.x = aiVector3D( trafo.a1, trafo.b1, trafo.c1).Length(); - scale.y = aiVector3D( trafo.a2, trafo.b2, trafo.c2).Length(); - scale.z = aiVector3D( trafo.a3, trafo.b3, trafo.c3).Length(); - nbone->mScalingKeys[c].mTime = time; - nbone->mScalingKeys[c].mValue = scale; - - // reconstruct rotation matrix without scaling - aiMatrix3x3 rotmat( - trafo.a1 / scale.x, trafo.a2 / scale.y, trafo.a3 / scale.z, - trafo.b1 / scale.x, trafo.b2 / scale.y, trafo.b3 / scale.z, - trafo.c1 / scale.x, trafo.c2 / scale.y, trafo.c3 / scale.z); - - // and convert it into a quaternion - nbone->mRotationKeys[c].mTime = time; - nbone->mRotationKeys[c].mValue = aiQuaternion( rotmat); - } - - // longest lasting key sequence determines duration - nanim->mDuration = std::max( nanim->mDuration, bone->mTrafoKeys.back().mTime); - } else { - // separate key sequences for position, rotation, scaling - nbone->mNumPositionKeys = (unsigned int)bone->mPosKeys.size(); - if (nbone->mNumPositionKeys != 0) { - nbone->mPositionKeys = new aiVectorKey[nbone->mNumPositionKeys]; - for( unsigned int c = 0; c < nbone->mNumPositionKeys; ++c ) { - aiVector3D pos = bone->mPosKeys[c].mValue; - - nbone->mPositionKeys[c].mTime = bone->mPosKeys[c].mTime; - nbone->mPositionKeys[c].mValue = pos; - } - } - - // rotation - nbone->mNumRotationKeys = (unsigned int)bone->mRotKeys.size(); - if (nbone->mNumRotationKeys != 0) { - nbone->mRotationKeys = new aiQuatKey[nbone->mNumRotationKeys]; - for( unsigned int c = 0; c < nbone->mNumRotationKeys; ++c ) { - aiMatrix3x3 rotmat = bone->mRotKeys[c].mValue.GetMatrix(); - - nbone->mRotationKeys[c].mTime = bone->mRotKeys[c].mTime; - nbone->mRotationKeys[c].mValue = aiQuaternion( rotmat); - nbone->mRotationKeys[c].mValue.w *= -1.0f; // needs quat inversion - } - } - - // scaling - nbone->mNumScalingKeys = (unsigned int)bone->mScaleKeys.size(); - if (nbone->mNumScalingKeys != 0) { - nbone->mScalingKeys = new aiVectorKey[nbone->mNumScalingKeys]; - for( unsigned int c = 0; c < nbone->mNumScalingKeys; c++) - nbone->mScalingKeys[c] = bone->mScaleKeys[c]; - } - - // longest lasting key sequence determines duration - if( bone->mPosKeys.size() > 0) - nanim->mDuration = std::max( nanim->mDuration, bone->mPosKeys.back().mTime); - if( bone->mRotKeys.size() > 0) - nanim->mDuration = std::max( nanim->mDuration, bone->mRotKeys.back().mTime); - if( bone->mScaleKeys.size() > 0) - nanim->mDuration = std::max( nanim->mDuration, bone->mScaleKeys.back().mTime); - } - } - } - - // store all converted animations in the scene - if( newAnims.size() > 0) - { - pScene->mNumAnimations = (unsigned int)newAnims.size(); - pScene->mAnimations = new aiAnimation* [pScene->mNumAnimations]; - for( unsigned int a = 0; a < newAnims.size(); a++) - pScene->mAnimations[a] = newAnims[a]; - } -} - -// ------------------------------------------------------------------------------------------------ -// Converts all materials in the given array and stores them in the scene's material list. -void XFileImporter::ConvertMaterials( aiScene* pScene, std::vector<XFile::Material>& pMaterials) -{ - // count the non-referrer materials in the array - unsigned int numNewMaterials( 0 ); - for ( unsigned int a = 0; a < pMaterials.size(); ++a ) { - if ( !pMaterials[ a ].mIsReference ) { - ++numNewMaterials; - } - } - - // resize the scene's material list to offer enough space for the new materials - if( numNewMaterials > 0 ) { - aiMaterial** prevMats = pScene->mMaterials; - pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials + numNewMaterials]; - if( nullptr != prevMats) { - ::memcpy( pScene->mMaterials, prevMats, pScene->mNumMaterials * sizeof( aiMaterial*)); - delete [] prevMats; - } - } - - // convert all the materials given in the array - for( unsigned int a = 0; a < pMaterials.size(); ++a ) { - XFile::Material& oldMat = pMaterials[a]; - if( oldMat.mIsReference) { - // find the material it refers to by name, and store its index - for( size_t b = 0; b < pScene->mNumMaterials; ++b ) { - aiString name; - pScene->mMaterials[b]->Get( AI_MATKEY_NAME, name); - if( strcmp( name.C_Str(), oldMat.mName.data()) == 0 ) { - oldMat.sceneIndex = a; - break; - } - } - - if( oldMat.sceneIndex == SIZE_MAX ) { - ASSIMP_LOG_WARN( "Could not resolve global material reference \"", oldMat.mName, "\"" ); - oldMat.sceneIndex = 0; - } - - continue; - } - - aiMaterial* mat = new aiMaterial; - aiString name; - name.Set( oldMat.mName); - mat->AddProperty( &name, AI_MATKEY_NAME); - - // Shading model: hard-coded to PHONG, there is no such information in an XFile - // FIX (aramis): If the specular exponent is 0, use gouraud shading. This is a bugfix - // for some models in the SDK (e.g. good old tiny.x) - int shadeMode = (int)oldMat.mSpecularExponent == 0.0f - ? aiShadingMode_Gouraud : aiShadingMode_Phong; - - mat->AddProperty<int>( &shadeMode, 1, AI_MATKEY_SHADING_MODEL); - // material colours - // Unclear: there's no ambient colour, but emissive. What to put for ambient? - // Probably nothing at all, let the user select a suitable default. - mat->AddProperty( &oldMat.mEmissive, 1, AI_MATKEY_COLOR_EMISSIVE); - mat->AddProperty( &oldMat.mDiffuse, 1, AI_MATKEY_COLOR_DIFFUSE); - mat->AddProperty( &oldMat.mSpecular, 1, AI_MATKEY_COLOR_SPECULAR); - mat->AddProperty( &oldMat.mSpecularExponent, 1, AI_MATKEY_SHININESS); - - - // texture, if there is one - if (1 == oldMat.mTextures.size() ) { - const XFile::TexEntry& otex = oldMat.mTextures.back(); - if (otex.mName.length()) { - // if there is only one texture assume it contains the diffuse color - aiString tex( otex.mName); - if ( otex.mIsNormalMap ) { - mat->AddProperty( &tex, AI_MATKEY_TEXTURE_NORMALS( 0 ) ); - } else { - mat->AddProperty( &tex, AI_MATKEY_TEXTURE_DIFFUSE( 0 ) ); - } - } - } else { - // Otherwise ... try to search for typical strings in the - // texture's file name like 'bump' or 'diffuse' - unsigned int iHM = 0,iNM = 0,iDM = 0,iSM = 0,iAM = 0,iEM = 0; - for( unsigned int b = 0; b < oldMat.mTextures.size(); ++b ) { - const XFile::TexEntry& otex = oldMat.mTextures[b]; - std::string sz = otex.mName; - if ( !sz.length() ) { - continue; - } - - // find the file name - std::string::size_type s = sz.find_last_of("\\/"); - if ( std::string::npos == s ) { - s = 0; - } - - // cut off the file extension - std::string::size_type sExt = sz.find_last_of('.'); - if (std::string::npos != sExt){ - sz[sExt] = '\0'; - } - - // convert to lower case for easier comparison - for ( unsigned int c = 0; c < sz.length(); ++c ) { - sz[ c ] = (char) tolower( (unsigned char) sz[ c ] ); - } - - // Place texture filename property under the corresponding name - aiString tex( oldMat.mTextures[b].mName); - - // bump map - if (std::string::npos != sz.find("bump", s) || std::string::npos != sz.find("height", s)) { - mat->AddProperty( &tex, AI_MATKEY_TEXTURE_HEIGHT(iHM++)); - } else if (otex.mIsNormalMap || std::string::npos != sz.find( "normal", s) || std::string::npos != sz.find("nm", s)) { - mat->AddProperty( &tex, AI_MATKEY_TEXTURE_NORMALS(iNM++)); - } else if (std::string::npos != sz.find( "spec", s) || std::string::npos != sz.find( "glanz", s)) { - mat->AddProperty( &tex, AI_MATKEY_TEXTURE_SPECULAR(iSM++)); - } else if (std::string::npos != sz.find( "ambi", s) || std::string::npos != sz.find( "env", s)) { - mat->AddProperty( &tex, AI_MATKEY_TEXTURE_AMBIENT(iAM++)); - } else if (std::string::npos != sz.find( "emissive", s) || std::string::npos != sz.find( "self", s)) { - mat->AddProperty( &tex, AI_MATKEY_TEXTURE_EMISSIVE(iEM++)); - } else { - // Assume it is a diffuse texture - mat->AddProperty( &tex, AI_MATKEY_TEXTURE_DIFFUSE(iDM++)); - } - } - } - - pScene->mMaterials[pScene->mNumMaterials] = mat; - oldMat.sceneIndex = pScene->mNumMaterials; - pScene->mNumMaterials++; - } -} - -#endif // !! ASSIMP_BUILD_NO_X_IMPORTER diff --git a/libs/assimp/code/AssetLib/X/XFileImporter.h b/libs/assimp/code/AssetLib/X/XFileImporter.h deleted file mode 100644 index 6481390..0000000 --- a/libs/assimp/code/AssetLib/X/XFileImporter.h +++ /dev/null @@ -1,148 +0,0 @@ -/* -Open Asset Import Library (assimp) ----------------------------------------------------------------------- - -Copyright (c) 2006-2022, assimp team - -All rights reserved. - -Redistribution and use of this software in source and binary forms, -with or without modification, are permitted provided that the -following conditions are met: - -* Redistributions of source code must retain the above - copyright notice, this list of conditions and the - following disclaimer. - -* Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the - following disclaimer in the documentation and/or other - materials provided with the distribution. - -* Neither the name of the assimp team, nor the names of its - contributors may be used to endorse or promote products - derived from this software without specific prior - written permission of the assimp team. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ----------------------------------------------------------------------- -*/ - -/** @file XFileImporter.h - * @brief Definition of the XFile importer class. - */ -#pragma once -#ifndef AI_XFILEIMPORTER_H_INC -#define AI_XFILEIMPORTER_H_INC - -#include <map> - -#include "XFileHelper.h" -#include <assimp/BaseImporter.h> - -#include <assimp/types.h> - -struct aiNode; - -namespace Assimp { - -namespace XFile { - struct Scene; - struct Node; -} - -// --------------------------------------------------------------------------- -/** The XFileImporter is a worker class capable of importing a scene from a - * DirectX file .x - */ -class XFileImporter : public BaseImporter { -public: - XFileImporter(); - ~XFileImporter() override; - - // ------------------------------------------------------------------- - /** Returns whether the class can handle the format of the given file. - * See BaseImporter::CanRead() for details. */ - bool CanRead( const std::string& pFile, IOSystem* pIOHandler, - bool CheckSig) const override; - -protected: - // ------------------------------------------------------------------- - /** Return importer meta information. - * See #BaseImporter::GetInfo for the details - */ - const aiImporterDesc* GetInfo () const override; - - // ------------------------------------------------------------------- - /** Imports the given file into the given scene structure. - * See BaseImporter::InternReadFile() for details - */ - void InternReadFile( const std::string& pFile, aiScene* pScene, - IOSystem* pIOHandler) override; - - // ------------------------------------------------------------------- - /** Constructs the return data structure out of the imported data. - * @param pScene The scene to construct the return data in. - * @param pData The imported data in the internal temporary - * representation. - */ - void CreateDataRepresentationFromImport( aiScene* pScene, XFile::Scene* pData); - - // ------------------------------------------------------------------- - /** Recursively creates scene nodes from the imported hierarchy. - * The meshes and materials of the nodes will be extracted on the way. - * @param pScene The scene to construct the return data in. - * @param pParent The parent node where to create new child nodes - * @param pNode The temporary node to copy. - * @return The created node - */ - aiNode* CreateNodes( aiScene* pScene, aiNode* pParent, - const XFile::Node* pNode); - - // ------------------------------------------------------------------- - /** Converts all meshes in the given mesh array. Each mesh is split - * up per material, the indices of the generated meshes are stored in - * the node structure. - * @param pScene The scene to construct the return data in. - * @param pNode The target node structure that references the - * constructed meshes. - * @param pMeshes The array of meshes to convert - */ - void CreateMeshes( aiScene* pScene, aiNode* pNode, - const std::vector<XFile::Mesh*>& pMeshes); - - // ------------------------------------------------------------------- - /** Converts the animations from the given imported data and creates - * them in the scene. - * @param pScene The scene to hold to converted animations - * @param pData The data to read the animations from - */ - void CreateAnimations( aiScene* pScene, const XFile::Scene* pData); - - // ------------------------------------------------------------------- - /** Converts all materials in the given array and stores them in the - * scene's material list. - * @param pScene The scene to hold the converted materials. - * @param pMaterials The material array to convert. - */ - void ConvertMaterials( aiScene* pScene, std::vector<XFile::Material>& pMaterials); - -protected: - /// Buffer to hold the loaded file - std::vector<char> mBuffer; -}; - -} // end of namespace Assimp - -#endif // AI_BASEIMPORTER_H_INC diff --git a/libs/assimp/code/AssetLib/X/XFileParser.cpp b/libs/assimp/code/AssetLib/X/XFileParser.cpp deleted file mode 100644 index 558b979..0000000 --- a/libs/assimp/code/AssetLib/X/XFileParser.cpp +++ /dev/null @@ -1,1360 +0,0 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (assimp) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2022, assimp team - -All rights reserved. - -Redistribution and use of this software in source and binary forms, -with or without modification, are permitted provided that the following -conditions are met: - -* Redistributions of source code must retain the above - copyright notice, this list of conditions and the - following disclaimer. - -* Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the - following disclaimer in the documentation and/or other - materials provided with the distribution. - -* Neither the name of the assimp team, nor the names of its - contributors may be used to endorse or promote products - derived from this software without specific prior - written permission of the assimp team. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ---------------------------------------------------------------------------- -*/ - -/** @file Implementation of the XFile parser helper class */ - -#ifndef ASSIMP_BUILD_NO_X_IMPORTER - -#include "XFileParser.h" -#include "XFileHelper.h" -#include <assimp/ByteSwapper.h> -#include <assimp/Exceptional.h> -#include <assimp/StringUtils.h> -#include <assimp/TinyFormatter.h> -#include <assimp/fast_atof.h> -#include <assimp/DefaultLogger.hpp> - -using namespace Assimp; -using namespace Assimp::XFile; -using namespace Assimp::Formatter; - -#ifndef ASSIMP_BUILD_NO_COMPRESSED_X - -#include "Common/Compression.h" - -// Magic identifier for MSZIP compressed data -constexpr unsigned int MSZIP_MAGIC = 0x4B43; -constexpr size_t MSZIP_BLOCK = 32786l; - -#endif // !! ASSIMP_BUILD_NO_COMPRESSED_X - -// ------------------------------------------------------------------------------------------------ -// Throws an exception with a line number and the given text. -template<typename... T> -AI_WONT_RETURN void XFileParser::ThrowException(T&&... args) { - if (mIsBinaryFormat) { - throw DeadlyImportError(args...); - } else { - throw DeadlyImportError("Line ", mLineNumber, ": ", args...); - } -} - -// ------------------------------------------------------------------------------------------------ -// Constructor. Creates a data structure out of the XFile given in the memory block. -XFileParser::XFileParser(const std::vector<char> &pBuffer) : - mMajorVersion(0), mMinorVersion(0), mIsBinaryFormat(false), mBinaryNumCount(0), mP(nullptr), mEnd(nullptr), mLineNumber(0), mScene(nullptr) { - // vector to store uncompressed file for INFLATE'd X files - std::vector<char> uncompressed; - - // set up memory pointers - mP = &pBuffer.front(); - mEnd = mP + pBuffer.size() - 1; - - // check header - if (0 != strncmp(mP, "xof ", 4)) { - throw DeadlyImportError("Header mismatch, file is not an XFile."); - } - - // read version. It comes in a four byte format such as "0302" - mMajorVersion = (unsigned int)(mP[4] - 48) * 10 + (unsigned int)(mP[5] - 48); - mMinorVersion = (unsigned int)(mP[6] - 48) * 10 + (unsigned int)(mP[7] - 48); - - bool compressed = false; - - // txt - pure ASCII text format - if (strncmp(mP + 8, "txt ", 4) == 0) - mIsBinaryFormat = false; - - // bin - Binary format - else if (strncmp(mP + 8, "bin ", 4) == 0) - mIsBinaryFormat = true; - - // tzip - Inflate compressed text format - else if (strncmp(mP + 8, "tzip", 4) == 0) { - mIsBinaryFormat = false; - compressed = true; - } - // bzip - Inflate compressed binary format - else if (strncmp(mP + 8, "bzip", 4) == 0) { - mIsBinaryFormat = true; - compressed = true; - } else - ThrowException("Unsupported x-file format '", mP[8], mP[9], mP[10], mP[11], "'"); - - // float size - mBinaryFloatSize = (unsigned int)(mP[12] - 48) * 1000 + (unsigned int)(mP[13] - 48) * 100 + (unsigned int)(mP[14] - 48) * 10 + (unsigned int)(mP[15] - 48); - - if (mBinaryFloatSize != 32 && mBinaryFloatSize != 64) - ThrowException("Unknown float size ", mBinaryFloatSize, " specified in x-file header."); - - // The x format specifies size in bits, but we work in bytes - mBinaryFloatSize /= 8; - - mP += 16; - - // If this is a compressed X file, apply the inflate algorithm to it - if (compressed) { -#ifdef ASSIMP_BUILD_NO_COMPRESSED_X - throw DeadlyImportError("Assimp was built without compressed X support"); -#else - /* /////////////////////////////////////////////////////////////////////// - * COMPRESSED X FILE FORMAT - * /////////////////////////////////////////////////////////////////////// - * [xhead] - * 2 major - * 2 minor - * 4 type // bzip,tzip - * [mszip_master_head] - * 4 unkn // checksum? - * 2 unkn // flags? (seems to be constant) - * [mszip_head] - * 2 ofs // offset to next section - * 2 magic // 'CK' - * ... ofs bytes of data - * ... next mszip_head - * - * http://www.kdedevelopers.org/node/3181 has been very helpful. - * /////////////////////////////////////////////////////////////////////// - */ - - // skip unknown data (checksum, flags?) - mP += 6; - - // First find out how much storage we'll need. Count sections. - const char *P1 = mP; - unsigned int est_out = 0; - - while (P1 + 3 < mEnd) { - // read next offset - uint16_t ofs = *((uint16_t *)P1); - AI_SWAP2(ofs); - P1 += 2; - - if (ofs >= MSZIP_BLOCK) - throw DeadlyImportError("X: Invalid offset to next MSZIP compressed block"); - - // check magic word - uint16_t magic = *((uint16_t *)P1); - AI_SWAP2(magic); - P1 += 2; - - if (magic != MSZIP_MAGIC) - throw DeadlyImportError("X: Unsupported compressed format, expected MSZIP header"); - - // and advance to the next offset - P1 += ofs; - est_out += MSZIP_BLOCK; // one decompressed block is 327861 in size - } - - // Allocate storage and terminating zero and do the actual uncompressing - Compression compression; - uncompressed.resize(est_out + 1); - char *out = &uncompressed.front(); - if (compression.open(mIsBinaryFormat ? Compression::Format::Binary : Compression::Format::ASCII, - Compression::FlushMode::SyncFlush, -Compression::MaxWBits)) { - while (mP + 3 < mEnd) { - uint16_t ofs = *((uint16_t *)mP); - AI_SWAP2(ofs); - mP += 4; - - if (mP + ofs > mEnd + 2) { - throw DeadlyImportError("X: Unexpected EOF in compressed chunk"); - } - out += compression.decompressBlock(mP, ofs, out, MSZIP_BLOCK); - mP += ofs; - } - compression.close(); - } - - // ok, update pointers to point to the uncompressed file data - mP = &uncompressed[0]; - mEnd = out; - - // FIXME: we don't need the compressed data anymore, could release - // it already for better memory usage. Consider breaking const-co. - ASSIMP_LOG_INFO("Successfully decompressed MSZIP-compressed file"); -#endif // !! ASSIMP_BUILD_NO_COMPRESSED_X - } else { - // start reading here - ReadUntilEndOfLine(); - } - - mScene = new Scene; - ParseFile(); - - // filter the imported hierarchy for some degenerated cases - if (mScene->mRootNode) { - FilterHierarchy(mScene->mRootNode); - } -} - -// ------------------------------------------------------------------------------------------------ -// Destructor. Destroys all imported data along with it -XFileParser::~XFileParser() { - // kill everything we created - delete mScene; -} - -// ------------------------------------------------------------------------------------------------ -void XFileParser::ParseFile() { - bool running = true; - while (running) { - // read name of next object - std::string objectName = GetNextToken(); - if (objectName.length() == 0) { - break; - } - - // parse specific object - if (objectName == "template") { - ParseDataObjectTemplate(); - } else if (objectName == "Frame") { - ParseDataObjectFrame(nullptr); - } else if (objectName == "Mesh") { - // some meshes have no frames at all - Mesh *mesh = new Mesh; - ParseDataObjectMesh(mesh); - mScene->mGlobalMeshes.push_back(mesh); - } else if (objectName == "AnimTicksPerSecond") - ParseDataObjectAnimTicksPerSecond(); - else if (objectName == "AnimationSet") - ParseDataObjectAnimationSet(); - else if (objectName == "Material") { - // Material outside of a mesh or node - Material material; - ParseDataObjectMaterial(&material); - mScene->mGlobalMaterials.push_back(material); - } else if (objectName == "}") { - // whatever? - ASSIMP_LOG_WARN("} found in dataObject"); - } else { - // unknown format - ASSIMP_LOG_WARN("Unknown data object in animation of .x file"); - ParseUnknownDataObject(); - } - } -} - -// ------------------------------------------------------------------------------------------------ -void XFileParser::ParseDataObjectTemplate() { - // parse a template data object. Currently not stored. - std::string name; - readHeadOfDataObject(&name); - - // read GUID - std::string guid = GetNextToken(); - - // read and ignore data members - bool running = true; - while (running) { - std::string s = GetNextToken(); - - if (s == "}") { - break; - } - - if (s.length() == 0) { - ThrowException("Unexpected end of file reached while parsing template definition"); - } - } -} - -// ------------------------------------------------------------------------------------------------ -void XFileParser::ParseDataObjectFrame(Node *pParent) { - // 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. - std::string name; - readHeadOfDataObject(&name); - - // create a named node and place it at its parent, if given - Node *node = new Node(pParent); - node->mName = name; - if (pParent) { - pParent->mChildren.push_back(node); - } else { - // there might be multiple root nodes - if (mScene->mRootNode != nullptr) { - // place a dummy root if not there - if (mScene->mRootNode->mName != "$dummy_root") { - Node *exroot = mScene->mRootNode; - mScene->mRootNode = new Node(nullptr); - mScene->mRootNode->mName = "$dummy_root"; - mScene->mRootNode->mChildren.push_back(exroot); - exroot->mParent = mScene->mRootNode; - } - // put the new node as its child instead - mScene->mRootNode->mChildren.push_back(node); - node->mParent = mScene->mRootNode; - } else { - // it's the first node imported. place it as root - mScene->mRootNode = node; - } - } - - // Now inside a frame. - // read tokens until closing brace is reached. - bool running = true; - while (running) { - std::string objectName = GetNextToken(); - if (objectName.size() == 0) - ThrowException("Unexpected end of file reached while parsing frame"); - - if (objectName == "}") - break; // frame finished - else if (objectName == "Frame") - ParseDataObjectFrame(node); // child frame - else if (objectName == "FrameTransformMatrix") - ParseDataObjectTransformationMatrix(node->mTrafoMatrix); - else if (objectName == "Mesh") { - Mesh *mesh = new Mesh(name); - node->mMeshes.push_back(mesh); - ParseDataObjectMesh(mesh); - } else { - ASSIMP_LOG_WARN("Unknown data object in frame in x file"); - ParseUnknownDataObject(); - } - } -} - -// ------------------------------------------------------------------------------------------------ -void XFileParser::ParseDataObjectTransformationMatrix(aiMatrix4x4 &pMatrix) { - // read header, we're not interested if it has a name - readHeadOfDataObject(); - - // read its components - pMatrix.a1 = ReadFloat(); - pMatrix.b1 = ReadFloat(); - pMatrix.c1 = ReadFloat(); - pMatrix.d1 = ReadFloat(); - pMatrix.a2 = ReadFloat(); - pMatrix.b2 = ReadFloat(); - pMatrix.c2 = ReadFloat(); - pMatrix.d2 = ReadFloat(); - pMatrix.a3 = ReadFloat(); - pMatrix.b3 = ReadFloat(); - pMatrix.c3 = ReadFloat(); - pMatrix.d3 = ReadFloat(); - pMatrix.a4 = ReadFloat(); - pMatrix.b4 = ReadFloat(); - pMatrix.c4 = ReadFloat(); - pMatrix.d4 = ReadFloat(); - - // trailing symbols - CheckForSemicolon(); - CheckForClosingBrace(); -} - -// ------------------------------------------------------------------------------------------------ -void XFileParser::ParseDataObjectMesh(Mesh *pMesh) { - std::string name; - readHeadOfDataObject(&name); - - // read vertex count - unsigned int numVertices = ReadInt(); - pMesh->mPositions.resize(numVertices); - - // read vertices - for (unsigned int a = 0; a < numVertices; a++) - pMesh->mPositions[a] = ReadVector3(); - - // read position faces - unsigned int numPosFaces = ReadInt(); - pMesh->mPosFaces.resize(numPosFaces); - for (unsigned int a = 0; a < numPosFaces; ++a) { - // read indices - unsigned int numIndices = ReadInt(); - Face &face = pMesh->mPosFaces[a]; - for (unsigned int b = 0; b < numIndices; ++b) { - const int idx(ReadInt()); - if (static_cast<unsigned int>(idx) <= numVertices) { - face.mIndices.push_back(idx); - } - } - TestForSeparator(); - } - - // here, other data objects may follow - bool running = true; - while (running) { - std::string objectName = GetNextToken(); - - if (objectName.empty()) - ThrowException("Unexpected end of file while parsing mesh structure"); - else if (objectName == "}") - break; // mesh finished - else if (objectName == "MeshNormals") - ParseDataObjectMeshNormals(pMesh); - else if (objectName == "MeshTextureCoords") - ParseDataObjectMeshTextureCoords(pMesh); - else if (objectName == "MeshVertexColors") - ParseDataObjectMeshVertexColors(pMesh); - else if (objectName == "MeshMaterialList") - ParseDataObjectMeshMaterialList(pMesh); - else if (objectName == "VertexDuplicationIndices") - ParseUnknownDataObject(); // we'll ignore vertex duplication indices - else if (objectName == "XSkinMeshHeader") - ParseDataObjectSkinMeshHeader(pMesh); - else if (objectName == "SkinWeights") - ParseDataObjectSkinWeights(pMesh); - else { - ASSIMP_LOG_WARN("Unknown data object in mesh in x file"); - ParseUnknownDataObject(); - } - } -} - -// ------------------------------------------------------------------------------------------------ -void XFileParser::ParseDataObjectSkinWeights(Mesh *pMesh) { - if (nullptr == pMesh) { - return; - } - readHeadOfDataObject(); - - std::string transformNodeName; - GetNextTokenAsString(transformNodeName); - - pMesh->mBones.push_back(Bone()); - Bone &bone = pMesh->mBones.back(); - bone.mName = transformNodeName; - - // read vertex weights - unsigned int numWeights = ReadInt(); - bone.mWeights.reserve(numWeights); - - for (unsigned int a = 0; a < numWeights; a++) { - BoneWeight weight = {}; - weight.mVertex = ReadInt(); - bone.mWeights.push_back(weight); - } - - // read vertex weights - for (unsigned int a = 0; a < numWeights; a++) - bone.mWeights[a].mWeight = ReadFloat(); - - // read matrix offset - bone.mOffsetMatrix.a1 = ReadFloat(); - bone.mOffsetMatrix.b1 = ReadFloat(); - bone.mOffsetMatrix.c1 = ReadFloat(); - bone.mOffsetMatrix.d1 = ReadFloat(); - bone.mOffsetMatrix.a2 = ReadFloat(); - bone.mOffsetMatrix.b2 = ReadFloat(); - bone.mOffsetMatrix.c2 = ReadFloat(); - bone.mOffsetMatrix.d2 = ReadFloat(); - bone.mOffsetMatrix.a3 = ReadFloat(); - bone.mOffsetMatrix.b3 = ReadFloat(); - bone.mOffsetMatrix.c3 = ReadFloat(); - bone.mOffsetMatrix.d3 = ReadFloat(); - bone.mOffsetMatrix.a4 = ReadFloat(); - bone.mOffsetMatrix.b4 = ReadFloat(); - bone.mOffsetMatrix.c4 = ReadFloat(); - bone.mOffsetMatrix.d4 = ReadFloat(); - - CheckForSemicolon(); - CheckForClosingBrace(); -} - -// ------------------------------------------------------------------------------------------------ -void XFileParser::ParseDataObjectSkinMeshHeader(Mesh * /*pMesh*/) { - readHeadOfDataObject(); - - /*unsigned int maxSkinWeightsPerVertex =*/ReadInt(); - /*unsigned int maxSkinWeightsPerFace =*/ReadInt(); - /*unsigned int numBonesInMesh = */ ReadInt(); - - CheckForClosingBrace(); -} - -// ------------------------------------------------------------------------------------------------ -void XFileParser::ParseDataObjectMeshNormals(Mesh *pMesh) { - readHeadOfDataObject(); - - // read count - unsigned int numNormals = ReadInt(); - pMesh->mNormals.resize(numNormals); - - // read normal vectors - for (unsigned int a = 0; a < numNormals; ++a) { - pMesh->mNormals[a] = ReadVector3(); - } - - // read normal indices - unsigned int numFaces = ReadInt(); - if (numFaces != pMesh->mPosFaces.size()) { - ThrowException("Normal face count does not match vertex face count."); - } - - // do not crah when no face definitions are there - if (numFaces > 0) { - // normal face creation - pMesh->mNormFaces.resize(numFaces); - for (unsigned int a = 0; a < numFaces; ++a) { - unsigned int numIndices = ReadInt(); - pMesh->mNormFaces[a] = Face(); - Face &face = pMesh->mNormFaces[a]; - for (unsigned int b = 0; b < numIndices; ++b) { - face.mIndices.push_back(ReadInt()); - } - - TestForSeparator(); - } - } - - CheckForClosingBrace(); -} - -// ------------------------------------------------------------------------------------------------ -void XFileParser::ParseDataObjectMeshTextureCoords(Mesh *pMesh) { - readHeadOfDataObject(); - if (pMesh->mNumTextures + 1 > AI_MAX_NUMBER_OF_TEXTURECOORDS) - ThrowException("Too many sets of texture coordinates"); - - std::vector<aiVector2D> &coords = pMesh->mTexCoords[pMesh->mNumTextures++]; - - unsigned int numCoords = ReadInt(); - if (numCoords != pMesh->mPositions.size()) - ThrowException("Texture coord count does not match vertex count"); - - coords.resize(numCoords); - for (unsigned int a = 0; a < numCoords; a++) - coords[a] = ReadVector2(); - - CheckForClosingBrace(); -} - -// ------------------------------------------------------------------------------------------------ -void XFileParser::ParseDataObjectMeshVertexColors(Mesh *pMesh) { - readHeadOfDataObject(); - if (pMesh->mNumColorSets + 1 > AI_MAX_NUMBER_OF_COLOR_SETS) - ThrowException("Too many colorsets"); - std::vector<aiColor4D> &colors = pMesh->mColors[pMesh->mNumColorSets++]; - - unsigned int numColors = ReadInt(); - if (numColors != pMesh->mPositions.size()) - ThrowException("Vertex color count does not match vertex count"); - - colors.resize(numColors, aiColor4D(0, 0, 0, 1)); - for (unsigned int a = 0; a < numColors; a++) { - unsigned int index = ReadInt(); - if (index >= pMesh->mPositions.size()) - ThrowException("Vertex color index out of bounds"); - - colors[index] = ReadRGBA(); - // HACK: (thom) Maxon Cinema XPort plugin puts a third separator here, kwxPort puts a comma. - // Ignore gracefully. - if (!mIsBinaryFormat) { - FindNextNoneWhiteSpace(); - if (*mP == ';' || *mP == ',') - mP++; - } - } - - CheckForClosingBrace(); -} - -// ------------------------------------------------------------------------------------------------ -void XFileParser::ParseDataObjectMeshMaterialList(Mesh *pMesh) { - readHeadOfDataObject(); - - // read material count - /*unsigned int numMaterials =*/ReadInt(); - // read non triangulated face material index count - unsigned int numMatIndices = ReadInt(); - - // some models have a material index count of 1... to be able to read them we - // replicate this single material index on every face - if (numMatIndices != pMesh->mPosFaces.size() && numMatIndices != 1) - ThrowException("Per-Face material index count does not match face count."); - - // read per-face material indices - for (unsigned int a = 0; a < numMatIndices; a++) - pMesh->mFaceMaterials.push_back(ReadInt()); - - // in version 03.02, the face indices end with two semicolons. - // commented out version check, as version 03.03 exported from blender also has 2 semicolons - if (!mIsBinaryFormat) // && MajorVersion == 3 && MinorVersion <= 2) - { - if (mP < mEnd && *mP == ';') - ++mP; - } - - // if there was only a single material index, replicate it on all faces - while (pMesh->mFaceMaterials.size() < pMesh->mPosFaces.size()) - pMesh->mFaceMaterials.push_back(pMesh->mFaceMaterials.front()); - - // read following data objects - bool running = true; - while (running) { - std::string objectName = GetNextToken(); - if (objectName.size() == 0) - ThrowException("Unexpected end of file while parsing mesh material list."); - else if (objectName == "}") - break; // material list finished - else if (objectName == "{") { - // template materials - std::string matName = GetNextToken(); - Material material; - material.mIsReference = true; - material.mName = matName; - pMesh->mMaterials.push_back(material); - - CheckForClosingBrace(); // skip } - } else if (objectName == "Material") { - pMesh->mMaterials.push_back(Material()); - ParseDataObjectMaterial(&pMesh->mMaterials.back()); - } else if (objectName == ";") { - // ignore - } else { - ASSIMP_LOG_WARN("Unknown data object in material list in x file"); - ParseUnknownDataObject(); - } - } -} - -// ------------------------------------------------------------------------------------------------ -void XFileParser::ParseDataObjectMaterial(Material *pMaterial) { - std::string matName; - readHeadOfDataObject(&matName); - if (matName.empty()) - matName = std::string("material") + ai_to_string(mLineNumber); - pMaterial->mName = matName; - pMaterial->mIsReference = false; - - // read material values - pMaterial->mDiffuse = ReadRGBA(); - pMaterial->mSpecularExponent = ReadFloat(); - pMaterial->mSpecular = ReadRGB(); - pMaterial->mEmissive = ReadRGB(); - - // read other data objects - bool running = true; - while (running) { - std::string objectName = GetNextToken(); - if (objectName.size() == 0) - ThrowException("Unexpected end of file while parsing mesh material"); - else if (objectName == "}") - break; // material finished - else if (objectName == "TextureFilename" || objectName == "TextureFileName") { - // some exporters write "TextureFileName" instead. - std::string texname; - ParseDataObjectTextureFilename(texname); - pMaterial->mTextures.push_back(TexEntry(texname)); - } else if (objectName == "NormalmapFilename" || objectName == "NormalmapFileName") { - // one exporter writes out the normal map in a separate filename tag - std::string texname; - ParseDataObjectTextureFilename(texname); - pMaterial->mTextures.push_back(TexEntry(texname, true)); - } else { - ASSIMP_LOG_WARN("Unknown data object in material in x file"); - ParseUnknownDataObject(); - } - } -} - -// ------------------------------------------------------------------------------------------------ -void XFileParser::ParseDataObjectAnimTicksPerSecond() { - readHeadOfDataObject(); - mScene->mAnimTicksPerSecond = ReadInt(); - CheckForClosingBrace(); -} - -// ------------------------------------------------------------------------------------------------ -void XFileParser::ParseDataObjectAnimationSet() { - std::string animName; - readHeadOfDataObject(&animName); - - Animation *anim = new Animation; - mScene->mAnims.push_back(anim); - anim->mName = animName; - - bool running = true; - while (running) { - std::string objectName = GetNextToken(); - if (objectName.length() == 0) - ThrowException("Unexpected end of file while parsing animation set."); - else if (objectName == "}") - break; // animation set finished - else if (objectName == "Animation") - ParseDataObjectAnimation(anim); - else { - ASSIMP_LOG_WARN("Unknown data object in animation set in x file"); - ParseUnknownDataObject(); - } - } -} - -// ------------------------------------------------------------------------------------------------ -void XFileParser::ParseDataObjectAnimation(Animation *pAnim) { - readHeadOfDataObject(); - AnimBone *banim = new AnimBone; - pAnim->mAnims.push_back(banim); - - bool running = true; - while (running) { - std::string objectName = GetNextToken(); - - if (objectName.length() == 0) - ThrowException("Unexpected end of file while parsing animation."); - else if (objectName == "}") - break; // animation finished - else if (objectName == "AnimationKey") - ParseDataObjectAnimationKey(banim); - else if (objectName == "AnimationOptions") - ParseUnknownDataObject(); // not interested - else if (objectName == "{") { - // read frame name - banim->mBoneName = GetNextToken(); - CheckForClosingBrace(); - } else { - ASSIMP_LOG_WARN("Unknown data object in animation in x file"); - ParseUnknownDataObject(); - } - } -} - -// ------------------------------------------------------------------------------------------------ -void XFileParser::ParseDataObjectAnimationKey(AnimBone *pAnimBone) { - readHeadOfDataObject(); - - // read key type - unsigned int keyType = ReadInt(); - - // read number of keys - unsigned int numKeys = ReadInt(); - - for (unsigned int a = 0; a < numKeys; a++) { - // read time - unsigned int time = ReadInt(); - - // read keys - switch (keyType) { - case 0: // rotation quaternion - { - // read count - if (ReadInt() != 4) - ThrowException("Invalid number of arguments for quaternion key in animation"); - - aiQuatKey key; - key.mTime = double(time); - key.mValue.w = ReadFloat(); - key.mValue.x = ReadFloat(); - key.mValue.y = ReadFloat(); - key.mValue.z = ReadFloat(); - pAnimBone->mRotKeys.push_back(key); - - CheckForSemicolon(); - break; - } - - case 1: // scale vector - case 2: // position vector - { - // read count - if (ReadInt() != 3) - ThrowException("Invalid number of arguments for vector key in animation"); - - aiVectorKey key; - key.mTime = double(time); - key.mValue = ReadVector3(); - - if (keyType == 2) - pAnimBone->mPosKeys.push_back(key); - else - pAnimBone->mScaleKeys.push_back(key); - - break; - } - - case 3: // combined transformation matrix - case 4: // denoted both as 3 or as 4 - { - // read count - if (ReadInt() != 16) - ThrowException("Invalid number of arguments for matrix key in animation"); - - // read matrix - MatrixKey key; - key.mTime = double(time); - key.mMatrix.a1 = ReadFloat(); - key.mMatrix.b1 = ReadFloat(); - key.mMatrix.c1 = ReadFloat(); - key.mMatrix.d1 = ReadFloat(); - key.mMatrix.a2 = ReadFloat(); - key.mMatrix.b2 = ReadFloat(); - key.mMatrix.c2 = ReadFloat(); - key.mMatrix.d2 = ReadFloat(); - key.mMatrix.a3 = ReadFloat(); - key.mMatrix.b3 = ReadFloat(); - key.mMatrix.c3 = ReadFloat(); - key.mMatrix.d3 = ReadFloat(); - key.mMatrix.a4 = ReadFloat(); - key.mMatrix.b4 = ReadFloat(); - key.mMatrix.c4 = ReadFloat(); - key.mMatrix.d4 = ReadFloat(); - pAnimBone->mTrafoKeys.push_back(key); - - CheckForSemicolon(); - break; - } - - default: - ThrowException("Unknown key type ", keyType, " in animation."); - break; - } // end switch - - // key separator - CheckForSeparator(); - } - - CheckForClosingBrace(); -} - -// ------------------------------------------------------------------------------------------------ -void XFileParser::ParseDataObjectTextureFilename(std::string &pName) { - readHeadOfDataObject(); - GetNextTokenAsString(pName); - CheckForClosingBrace(); - - // FIX: some files (e.g. AnimationTest.x) have "" as texture file name - if (!pName.length()) { - ASSIMP_LOG_WARN("Length of texture file name is zero. Skipping this texture."); - } - - // some exporters write double backslash paths out. We simply replace them if we find them - while (pName.find("\\\\") != std::string::npos) - pName.replace(pName.find("\\\\"), 2, "\\"); -} - -// ------------------------------------------------------------------------------------------------ -void XFileParser::ParseUnknownDataObject() { - // find opening delimiter - bool running = true; - while (running) { - std::string t = GetNextToken(); - if (t.length() == 0) - ThrowException("Unexpected end of file while parsing unknown segment."); - - if (t == "{") - break; - } - - unsigned int counter = 1; - - // parse until closing delimiter - while (counter > 0) { - std::string t = GetNextToken(); - - if (t.length() == 0) - ThrowException("Unexpected end of file while parsing unknown segment."); - - if (t == "{") - ++counter; - else if (t == "}") - --counter; - } -} - -// ------------------------------------------------------------------------------------------------ -//! checks for closing curly brace -void XFileParser::CheckForClosingBrace() { - if (GetNextToken() != "}") - ThrowException("Closing brace expected."); -} - -// ------------------------------------------------------------------------------------------------ -//! checks for one following semicolon -void XFileParser::CheckForSemicolon() { - if (mIsBinaryFormat) - return; - - if (GetNextToken() != ";") - ThrowException("Semicolon expected."); -} - -// ------------------------------------------------------------------------------------------------ -//! checks for a separator char, either a ',' or a ';' -void XFileParser::CheckForSeparator() { - if (mIsBinaryFormat) - return; - - std::string token = GetNextToken(); - if (token != "," && token != ";") - ThrowException("Separator character (';' or ',') expected."); -} - -// ------------------------------------------------------------------------------------------------ -// tests and possibly consumes a separator char, but does nothing if there was no separator -void XFileParser::TestForSeparator() { - if (mIsBinaryFormat) - return; - - FindNextNoneWhiteSpace(); - if (mP >= mEnd) - return; - - // test and skip - if (*mP == ';' || *mP == ',') - mP++; -} - -// ------------------------------------------------------------------------------------------------ -void XFileParser::readHeadOfDataObject(std::string *poName) { - std::string nameOrBrace = GetNextToken(); - if (nameOrBrace != "{") { - if (poName) - *poName = nameOrBrace; - - if (GetNextToken() != "{") { - delete mScene; - ThrowException("Opening brace expected."); - } - } -} - -// ------------------------------------------------------------------------------------------------ -std::string XFileParser::GetNextToken() { - std::string s; - - // process binary-formatted file - if (mIsBinaryFormat) { - // in binary mode it will only return NAME and STRING token - // and (correctly) skip over other tokens. - if (mEnd - mP < 2) { - return s; - } - unsigned int tok = ReadBinWord(); - unsigned int len; - - // standalone tokens - switch (tok) { - case 1: { - // name token - if (mEnd - mP < 4) { - return s; - } - len = ReadBinDWord(); - const int bounds = int(mEnd - mP); - const int iLen = int(len); - if (iLen < 0) { - return s; - } - if (bounds < iLen) { - return s; - } - s = std::string(mP, len); - mP += len; - } - return s; - - case 2: - // string token - if (mEnd - mP < 4) return s; - len = ReadBinDWord(); - if (mEnd - mP < int(len)) return s; - s = std::string(mP, len); - mP += (len + 2); - return s; - case 3: - // integer token - mP += 4; - return "<integer>"; - case 5: - // GUID token - mP += 16; - return "<guid>"; - case 6: - if (mEnd - mP < 4) return s; - len = ReadBinDWord(); - mP += (len * 4); - return "<int_list>"; - case 7: - if (mEnd - mP < 4) return s; - len = ReadBinDWord(); - mP += (len * mBinaryFloatSize); - return "<flt_list>"; - 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 (mP >= mEnd) - return s; - - while ((mP < mEnd) && !isspace((unsigned char)*mP)) { - // either keep token delimiters when already holding a token, or return if first valid char - if (*mP == ';' || *mP == '}' || *mP == '{' || *mP == ',') { - if (!s.size()) - s.append(mP++, 1); - break; // stop for delimiter - } - s.append(mP++, 1); - } - } - return s; -} - -// ------------------------------------------------------------------------------------------------ -void XFileParser::FindNextNoneWhiteSpace() { - if (mIsBinaryFormat) - return; - - bool running = true; - while (running) { - while (mP < mEnd && isspace((unsigned char)*mP)) { - if (*mP == '\n') - mLineNumber++; - ++mP; - } - - if (mP >= mEnd) - return; - - // check if this is a comment - if ((mP[0] == '/' && mP[1] == '/') || mP[0] == '#') - ReadUntilEndOfLine(); - else - break; - } -} - -// ------------------------------------------------------------------------------------------------ -void XFileParser::GetNextTokenAsString(std::string &poString) { - if (mIsBinaryFormat) { - poString = GetNextToken(); - return; - } - - FindNextNoneWhiteSpace(); - if (mP >= mEnd) { - delete mScene; - ThrowException("Unexpected end of file while parsing string"); - } - - if (*mP != '"') { - delete mScene; - ThrowException("Expected quotation mark."); - } - ++mP; - - while (mP < mEnd && *mP != '"') - poString.append(mP++, 1); - - if (mP >= mEnd - 1) { - delete mScene; - ThrowException("Unexpected end of file while parsing string"); - } - - if (mP[1] != ';' || mP[0] != '"') { - delete mScene; - ThrowException("Expected quotation mark and semicolon at the end of a string."); - } - mP += 2; -} - -// ------------------------------------------------------------------------------------------------ -void XFileParser::ReadUntilEndOfLine() { - if (mIsBinaryFormat) - return; - - while (mP < mEnd) { - if (*mP == '\n' || *mP == '\r') { - ++mP; - mLineNumber++; - return; - } - - ++mP; - } -} - -// ------------------------------------------------------------------------------------------------ -unsigned short XFileParser::ReadBinWord() { - ai_assert(mEnd - mP >= 2); - const unsigned char *q = (const unsigned char *)mP; - unsigned short tmp = q[0] | (q[1] << 8); - mP += 2; - return tmp; -} - -// ------------------------------------------------------------------------------------------------ -unsigned int XFileParser::ReadBinDWord() { - ai_assert(mEnd - mP >= 4); - - const unsigned char *q = (const unsigned char *)mP; - unsigned int tmp = q[0] | (q[1] << 8) | (q[2] << 16) | (q[3] << 24); - mP += 4; - return tmp; -} - -// ------------------------------------------------------------------------------------------------ -unsigned int XFileParser::ReadInt() { - if (mIsBinaryFormat) { - if (mBinaryNumCount == 0 && mEnd - mP >= 2) { - unsigned short tmp = ReadBinWord(); // 0x06 or 0x03 - if (tmp == 0x06 && mEnd - mP >= 4) // array of ints follows - mBinaryNumCount = ReadBinDWord(); - else // single int follows - mBinaryNumCount = 1; - } - - --mBinaryNumCount; - const size_t len(mEnd - mP); - if (len >= 4) { - return ReadBinDWord(); - } else { - mP = mEnd; - return 0; - } - } else { - FindNextNoneWhiteSpace(); - - // TODO: consider using strtol10 instead??? - - // check preceding minus sign - bool isNegative = false; - if (*mP == '-') { - isNegative = true; - mP++; - } - - // at least one digit expected - if (!isdigit((unsigned char)*mP)) - ThrowException("Number expected."); - - // read digits - unsigned int number = 0; - while (mP < mEnd) { - if (!isdigit((unsigned char)*mP)) - break; - number = number * 10 + (*mP - 48); - mP++; - } - - CheckForSeparator(); - - return isNegative ? ((unsigned int)-int(number)) : number; - } -} - -// ------------------------------------------------------------------------------------------------ -ai_real XFileParser::ReadFloat() { - if (mIsBinaryFormat) { - if (mBinaryNumCount == 0 && mEnd - mP >= 2) { - unsigned short tmp = ReadBinWord(); // 0x07 or 0x42 - if (tmp == 0x07 && mEnd - mP >= 4) // array of floats following - mBinaryNumCount = ReadBinDWord(); - else // single float following - mBinaryNumCount = 1; - } - - --mBinaryNumCount; - if (mBinaryFloatSize == 8) { - if (mEnd - mP >= 8) { - double res; - ::memcpy(&res, mP, 8); - mP += 8; - const ai_real result(static_cast<ai_real>(res)); - return result; - } else { - mP = mEnd; - return 0; - } - } else { - if (mEnd - mP >= 4) { - ai_real result; - ::memcpy(&result, mP, 4); - mP += 4; - return result; - } else { - mP = mEnd; - return 0; - } - } - } - - // text version - FindNextNoneWhiteSpace(); - // check for various special strings to allow reading files from faulty exporters - // I mean you, Blender! - // Reading is safe because of the terminating zero - if (strncmp(mP, "-1.#IND00", 9) == 0 || strncmp(mP, "1.#IND00", 8) == 0) { - mP += 9; - CheckForSeparator(); - return 0.0; - } else if (strncmp(mP, "1.#QNAN0", 8) == 0) { - mP += 8; - CheckForSeparator(); - return 0.0; - } - - ai_real result = 0.0; - mP = fast_atoreal_move<ai_real>(mP, result); - - CheckForSeparator(); - - return result; -} - -// ------------------------------------------------------------------------------------------------ -aiVector2D XFileParser::ReadVector2() { - aiVector2D vector; - vector.x = ReadFloat(); - vector.y = ReadFloat(); - TestForSeparator(); - - return vector; -} - -// ------------------------------------------------------------------------------------------------ -aiVector3D XFileParser::ReadVector3() { - aiVector3D vector; - vector.x = ReadFloat(); - vector.y = ReadFloat(); - vector.z = ReadFloat(); - TestForSeparator(); - - return vector; -} - -// ------------------------------------------------------------------------------------------------ -aiColor4D XFileParser::ReadRGBA() { - aiColor4D color; - color.r = ReadFloat(); - color.g = ReadFloat(); - color.b = ReadFloat(); - color.a = ReadFloat(); - TestForSeparator(); - - return color; -} - -// ------------------------------------------------------------------------------------------------ -aiColor3D XFileParser::ReadRGB() { - aiColor3D color; - color.r = ReadFloat(); - color.g = ReadFloat(); - color.b = ReadFloat(); - TestForSeparator(); - - return color; -} - -// ------------------------------------------------------------------------------------------------ -// Filters the imported hierarchy for some degenerated cases that some exporters produce. -void XFileParser::FilterHierarchy(XFile::Node *pNode) { - // if the node has just a single unnamed child containing a mesh, remove - // the anonymous node between. The 3DSMax kwXport plugin seems to produce this - // mess in some cases - if (pNode->mChildren.size() == 1 && pNode->mMeshes.empty()) { - XFile::Node *child = pNode->mChildren.front(); - if (child->mName.length() == 0 && child->mMeshes.size() > 0) { - // transfer its meshes to us - for (unsigned int a = 0; a < child->mMeshes.size(); a++) - pNode->mMeshes.push_back(child->mMeshes[a]); - child->mMeshes.clear(); - - // transfer the transform as well - pNode->mTrafoMatrix = pNode->mTrafoMatrix * child->mTrafoMatrix; - - // then kill it - delete child; - pNode->mChildren.clear(); - } - } - - // recurse - for (unsigned int a = 0; a < pNode->mChildren.size(); a++) - FilterHierarchy(pNode->mChildren[a]); -} - -#endif // !! ASSIMP_BUILD_NO_X_IMPORTER diff --git a/libs/assimp/code/AssetLib/X/XFileParser.h b/libs/assimp/code/AssetLib/X/XFileParser.h deleted file mode 100644 index 36eac2a..0000000 --- a/libs/assimp/code/AssetLib/X/XFileParser.h +++ /dev/null @@ -1,158 +0,0 @@ -/* -Open Asset Import Library (assimp) ----------------------------------------------------------------------- - -Copyright (c) 2006-2022, assimp team - - -All rights reserved. - -Redistribution and use of this software in source and binary forms, -with or without modification, are permitted provided that the -following conditions are met: - -* Redistributions of source code must retain the above - copyright notice, this list of conditions and the - following disclaimer. - -* Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the - following disclaimer in the documentation and/or other - materials provided with the distribution. - -* Neither the name of the assimp team, nor the names of its - contributors may be used to endorse or promote products - derived from this software without specific prior - written permission of the assimp team. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ----------------------------------------------------------------------- -*/ - -/** @file Helper class to parse a XFile into a temporary structure */ -#ifndef AI_XFILEPARSER_H_INC -#define AI_XFILEPARSER_H_INC - -#include <string> -#include <vector> - -#include <assimp/types.h> - -namespace Assimp { - namespace XFile { - struct Node; - struct Mesh; - struct Scene; - struct Material; - struct Animation; - struct AnimBone; - } - -/** - * @brief The XFileParser reads a XFile either in text or binary form and builds a temporary - * data structure out of it. - */ -class XFileParser { -public: - /// Constructor. Creates a data structure out of the XFile given in the memory block. - /// @param pBuffer Null-terminated memory buffer containing the XFile - explicit XFileParser( const std::vector<char>& pBuffer); - - /// Destructor. Destroys all imported data along with it - ~XFileParser(); - - /// Returns the temporary representation of the imported data. - XFile::Scene* GetImportedData() const { return mScene; } - -protected: - void ParseFile(); - void ParseDataObjectTemplate(); - void ParseDataObjectFrame( XFile::Node *pParent); - void ParseDataObjectTransformationMatrix( aiMatrix4x4& pMatrix); - void ParseDataObjectMesh( XFile::Mesh* pMesh); - void ParseDataObjectSkinWeights( XFile::Mesh* pMesh); - void ParseDataObjectSkinMeshHeader( XFile::Mesh* pMesh); - void ParseDataObjectMeshNormals( XFile::Mesh* pMesh); - void ParseDataObjectMeshTextureCoords( XFile::Mesh* pMesh); - void ParseDataObjectMeshVertexColors( XFile::Mesh* pMesh); - void ParseDataObjectMeshMaterialList( XFile::Mesh* pMesh); - void ParseDataObjectMaterial( XFile::Material* pMaterial); - void ParseDataObjectAnimTicksPerSecond(); - void ParseDataObjectAnimationSet(); - void ParseDataObjectAnimation( XFile::Animation* pAnim); - void ParseDataObjectAnimationKey( XFile::AnimBone *pAnimBone); - void ParseDataObjectTextureFilename( std::string& pName); - void ParseUnknownDataObject(); - - //! places pointer to next begin of a token, and ignores comments - void FindNextNoneWhiteSpace(); - - //! returns next valid token. Returns empty string if no token there - std::string GetNextToken(); - - //! reads header of data object including the opening brace. - //! returns false if error happened, and writes name of object - //! if there is one - void readHeadOfDataObject(std::string *poName = nullptr); - - //! checks for closing curly brace, throws exception if not there - void CheckForClosingBrace(); - - //! checks for one following semicolon, throws exception if not there - void CheckForSemicolon(); - - //! checks for a separator char, either a ',' or a ';' - void CheckForSeparator(); - - /// tests and possibly consumes a separator char, but does nothing if there was no separator - void TestForSeparator(); - - //! reads a x file style string - void GetNextTokenAsString( std::string& poString); - - void ReadUntilEndOfLine(); - - unsigned short ReadBinWord(); - unsigned int ReadBinDWord(); - unsigned int ReadInt(); - ai_real ReadFloat(); - aiVector2D ReadVector2(); - aiVector3D ReadVector3(); - aiColor3D ReadRGB(); - aiColor4D ReadRGBA(); - - /** Throws an exception with a line number and the given text. */ - template<typename... T> - AI_WONT_RETURN void ThrowException(T&&... args) AI_WONT_RETURN_SUFFIX; - - /** - * @brief Filters the imported hierarchy for some degenerated cases that some exporters produce. - * @param pData The sub-hierarchy to filter - */ - void FilterHierarchy( XFile::Node* pNode); - -protected: - unsigned int mMajorVersion, mMinorVersion; ///< version numbers - bool mIsBinaryFormat; ///< true if the file is in binary, false if it's in text form - unsigned int mBinaryFloatSize; ///< float size in bytes, either 4 or 8 - unsigned int mBinaryNumCount; /// < counter for number arrays in binary format - const char* mP; - const char* mEnd; - unsigned int mLineNumber; ///< Line number when reading in text format - XFile::Scene* mScene; ///< Imported data -}; - -} //! ns Assimp - -#endif // AI_XFILEPARSER_H_INC |