From 625357685cdf78295a281a0dba6a6a3f1468d64a Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Thu, 9 Jan 2020 22:04:46 +0100 Subject: [PATCH 001/330] Update EmbedTexturesProcess.cpp closes https://github.com/assimp/assimp/issues/2874 : fix leaked texture buffer. --- code/PostProcessing/EmbedTexturesProcess.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/code/PostProcessing/EmbedTexturesProcess.cpp b/code/PostProcessing/EmbedTexturesProcess.cpp index 739382a05..c83738563 100644 --- a/code/PostProcessing/EmbedTexturesProcess.cpp +++ b/code/PostProcessing/EmbedTexturesProcess.cpp @@ -128,7 +128,8 @@ bool EmbedTexturesProcess::addTexture(aiScene* pScene, std::string path) const { auto oldTextures = pScene->mTextures; pScene->mTextures = new aiTexture*[pScene->mNumTextures]; ::memmove(pScene->mTextures, oldTextures, sizeof(aiTexture*) * (pScene->mNumTextures - 1u)); - + delete [] oldTextures; + // Add the new texture auto pTexture = new aiTexture; pTexture->mHeight = 0; // Means that this is still compressed From d1abe68b93e7b64851dfd0f56770dde46f94194b Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 14 Jan 2020 21:44:45 +0100 Subject: [PATCH 002/330] Testcoverage improvements. --- code/Assxml/AssxmlExporter.cpp | 1 - test/CMakeLists.txt | 2 + test/unit/Common/uiScene.cpp | 93 +++++++++++++++++++ .../Assxml/utAssxmlImportExport.cpp | 76 +++++++++++++++ 4 files changed, 171 insertions(+), 1 deletion(-) create mode 100644 test/unit/Common/uiScene.cpp create mode 100644 test/unit/ImportExport/Assxml/utAssxmlImportExport.cpp diff --git a/code/Assxml/AssxmlExporter.cpp b/code/Assxml/AssxmlExporter.cpp index afdecbaf6..e28a75896 100644 --- a/code/Assxml/AssxmlExporter.cpp +++ b/code/Assxml/AssxmlExporter.cpp @@ -161,7 +161,6 @@ static void WriteNode(const aiNode* node, IOStream * io, unsigned int depth) { ioprintf(io,"%s\n",prefix); } - // ----------------------------------------------------------------------------------- // Some chuncks of text will need to be encoded for XML // http://stackoverflow.com/questions/5665231/most-efficient-way-to-escape-xml-html-in-c-string#5665377 diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 2429ab25d..780b03c2a 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -76,10 +76,12 @@ SET( COMMON unit/utProfiler.cpp unit/utSharedPPData.cpp unit/utStringUtils.cpp + unit/Common/uiScene.cpp unit/Common/utLineSplitter.cpp ) SET( IMPORTERS + unit/ImportExport/Assxml/utAssxmlImportExport.cpp unit/utLWSImportExport.cpp unit/utLWOImportExport.cpp unit/utSMDImportExport.cpp diff --git a/test/unit/Common/uiScene.cpp b/test/unit/Common/uiScene.cpp new file mode 100644 index 000000000..d5b123b48 --- /dev/null +++ b/test/unit/Common/uiScene.cpp @@ -0,0 +1,93 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2020, 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. +--------------------------------------------------------------------------- +*/ + +#include "UnitTestPCH.h" + +#include + + +using namespace Assimp; + +class utScene : public ::testing::Test { +protected: + aiScene *scene; + + void SetUp() override { + scene = new aiScene; + } + + void TearDown() override { + delete scene; + scene = nullptr; + } +}; + +TEST_F(utScene, findNodeTest) { + scene->mRootNode = new aiNode(); + scene->mRootNode->mName.Set("test"); + aiNode *child = new aiNode; + child->mName.Set("child"); + scene->mRootNode->addChildren(1, &child); + aiNode *found = scene->mRootNode->FindNode("child"); + EXPECT_EQ(child, found); +} + +TEST_F(utScene, sceneHasContentTest) { + EXPECT_FALSE(scene->HasAnimations()); + EXPECT_FALSE(scene->HasMaterials()); + EXPECT_FALSE(scene->HasMeshes()); + EXPECT_FALSE(scene->HasCameras()); + EXPECT_FALSE(scene->HasLights()); + EXPECT_FALSE(scene->HasTextures()); +} + +TEST_F(utScene, getShortFilenameTest) { + std::string long_filename1 = "foo_bar/name"; + const char *name1 = scene->GetShortFilename(long_filename1.c_str()); + EXPECT_NE(nullptr, name1); + + std::string long_filename2 = "foo_bar\\name"; + const char *name2 = scene->GetShortFilename(long_filename2.c_str()); + EXPECT_NE(nullptr, name2); +} + +TEST_F(utScene, getEmbeddedTextureTest) { +} diff --git a/test/unit/ImportExport/Assxml/utAssxmlImportExport.cpp b/test/unit/ImportExport/Assxml/utAssxmlImportExport.cpp new file mode 100644 index 000000000..c10d91b41 --- /dev/null +++ b/test/unit/ImportExport/Assxml/utAssxmlImportExport.cpp @@ -0,0 +1,76 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2019, 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. +--------------------------------------------------------------------------- +*/ + +#include "AbstractImportExportBase.h" +#include "SceneDiffer.h" +#include "UnitTestPCH.h" + +#include +#include +#include + +using namespace Assimp; + +class utAssxmlImportExport : public AbstractImportExportBase { +public: + bool importerTest() override { + return true; + } + +#ifndef ASSIMP_BUILD_NO_EXPORT + bool exporterTest() override { + Assimp::Importer importer; + const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/OBJ/spider.obj", aiProcess_ValidateDataStructure); + EXPECT_NE(scene, nullptr ); + + ::Assimp::Exporter exporter; + return AI_SUCCESS == exporter.Export(scene, "assxml", ASSIMP_TEST_MODELS_DIR "/OBJ/spider_out.assxml"); + } +#endif +}; + +#ifndef ASSIMP_BUILD_NO_EXPORT + +TEST_F(utAssxmlImportExport, exportAssxmlTest) { + EXPECT_TRUE(exporterTest()); +} + +#endif From 10ff2d94f77afcbbee182a7ea80dc6013d1c5108 Mon Sep 17 00:00:00 2001 From: kimkulling Date: Wed, 15 Jan 2020 13:59:17 +0100 Subject: [PATCH 003/330] more tests. --- test/CMakeLists.txt | 2 + .../ImportExport/IRR/utIrrImportExport.cpp | 66 +++++++++++++++++++ .../ImportExport/RAW/utRAWImportExport.cpp | 64 ++++++++++++++++++ test/unit/utM3DImportExport.cpp | 23 ++++++- 4 files changed, 152 insertions(+), 3 deletions(-) create mode 100644 test/unit/ImportExport/IRR/utIrrImportExport.cpp create mode 100644 test/unit/ImportExport/RAW/utRAWImportExport.cpp diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 780b03c2a..517462a94 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -135,6 +135,8 @@ SET( IMPORTERS unit/ImportExport/MDL/utMDLImporter_HL1_ImportSettings.cpp unit/ImportExport/MDL/utMDLImporter_HL1_Materials.cpp unit/ImportExport/MDL/utMDLImporter_HL1_Nodes.cpp + unit/ImportExport/IRR/utIrrImportExport.cpp + unit/ImportExport/RAW/utRAWImportExport.cpp ) SET( MATERIAL diff --git a/test/unit/ImportExport/IRR/utIrrImportExport.cpp b/test/unit/ImportExport/IRR/utIrrImportExport.cpp new file mode 100644 index 000000000..eaa4c8f4c --- /dev/null +++ b/test/unit/ImportExport/IRR/utIrrImportExport.cpp @@ -0,0 +1,66 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2020, 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. +--------------------------------------------------------------------------- +*/ +#include "AbstractImportExportBase.h" +#include "UnitTestPCH.h" +#include +#include +#include + +using namespace Assimp; + +class utIrrImportExport : public AbstractImportExportBase { +public: + virtual bool importerTest() { + Assimp::Importer importer; + const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/IRR/box.irr", aiProcess_ValidateDataStructure); + return nullptr != scene; + } +}; + +TEST_F(utIrrImportExport, importSimpleIrrTest) { + EXPECT_TRUE(importerTest()); +} + +TEST_F(utIrrImportExport, importSGIrrTest) { + Assimp::Importer importer; + const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/IRR/dawfInCellar_SameHierarchy.irr", aiProcess_ValidateDataStructure); + EXPECT_NE( nullptr,scene); +} diff --git a/test/unit/ImportExport/RAW/utRAWImportExport.cpp b/test/unit/ImportExport/RAW/utRAWImportExport.cpp new file mode 100644 index 000000000..6812ef302 --- /dev/null +++ b/test/unit/ImportExport/RAW/utRAWImportExport.cpp @@ -0,0 +1,64 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2020, 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. +--------------------------------------------------------------------------- +*/ +#include "AbstractImportExportBase.h" +#include "UnitTestPCH.h" +#include +#include +#include + +using namespace Assimp; + +class utRAWImportExport : public AbstractImportExportBase { +public: + virtual bool importerTest() { + Assimp::Importer importer; + const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/RAW/Wuson.raw", aiProcess_ValidateDataStructure); +#ifndef ASSIMP_BUILD_NO_RAW_IMPORTER + return nullptr != scene; +#else + return nullptr == scene; +#endif + } +}; + +TEST_F(utRAWImportExport, importSimpleRAWTest) { + EXPECT_TRUE(importerTest()); +} diff --git a/test/unit/utM3DImportExport.cpp b/test/unit/utM3DImportExport.cpp index 31028235d..ab1ef1942 100644 --- a/test/unit/utM3DImportExport.cpp +++ b/test/unit/utM3DImportExport.cpp @@ -46,23 +46,40 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "AbstractImportExportBase.h" #include +#include #include using namespace Assimp; class utM3DImportExport : public AbstractImportExportBase { public: - virtual bool importerTest() { + bool importerTest() override { Assimp::Importer importer; - const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/M3D/cube_normals.m3d", aiProcess_ValidateDataStructure ); + const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/M3D/cube_normals.m3d", aiProcess_ValidateDataStructure); #ifndef ASSIMP_BUILD_NO_M3D_IMPORTER - return nullptr != scene; + return nullptr != scene; #else return nullptr == scene; #endif // ASSIMP_BUILD_NO_M3D_IMPORTER } + +#ifndef ASSIMP_BUILD_NO_EXPORT + bool exporterTest() override { + Assimp::Importer importer; + const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/M3D/cube_normals.m3d", aiProcess_ValidateDataStructure); + Exporter exporter; + aiReturn ret = exporter.Export(scene, "m3d", ASSIMP_TEST_MODELS_DIR "/M3D/cube_normals_out.m3d"); + return ret == AI_SUCCESS; + } +#endif }; TEST_F( utM3DImportExport, importM3DFromFileTest ) { EXPECT_TRUE( importerTest() ); } + +#ifndef ASSIMP_BUILD_NO_EXPORT +TEST_F(utM3DImportExport, exportM3DFromFileTest) { + EXPECT_TRUE(exporterTest()); +} +#endif // ASSIMP_BUILD_NO_EXPORT From 40d882af4f1f9633de336ae225dd6d368da05ff2 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Thu, 16 Jan 2020 20:25:47 +0100 Subject: [PATCH 004/330] fix irrreader leak. --- code/3DS/3DSConverter.cpp | 2 - code/3DS/3DSHelper.h | 4 +- code/3DS/3DSLoader.cpp | 16 ++--- code/3DS/3DSLoader.h | 6 +- code/Assjson/cencode.c | 4 ++ code/CSM/CSMLoader.cpp | 2 +- code/FBX/FBXConverter.cpp | 4 +- code/Irr/IRRLoader.cpp | 1 + code/Material/MaterialSystem.cpp | 2 +- code/Q3BSP/Q3BSPFileImporter.cpp | 2 +- code/SMD/SMDLoader.cpp | 2 +- code/Unreal/UnrealLoader.cpp | 98 +++++++++++++++++++++++++-- code/Unreal/UnrealLoader.h | 110 ++----------------------------- contrib/zip/src/miniz.h | 2 +- tools/assimp_view/Display.cpp | 2 +- tools/assimp_view/Material.cpp | 16 ++--- 16 files changed, 126 insertions(+), 147 deletions(-) diff --git a/code/3DS/3DSConverter.cpp b/code/3DS/3DSConverter.cpp index 3c3da36a3..e1bb16c27 100644 --- a/code/3DS/3DSConverter.cpp +++ b/code/3DS/3DSConverter.cpp @@ -5,8 +5,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2019, assimp team - - All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/3DS/3DSHelper.h b/code/3DS/3DSHelper.h index 8eb4cd97c..bdb8615a4 100644 --- a/code/3DS/3DSHelper.h +++ b/code/3DS/3DSHelper.h @@ -55,8 +55,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include //sprintf -namespace Assimp { -namespace D3DS { +namespace Assimp { +namespace D3DS { #include diff --git a/code/3DS/3DSLoader.cpp b/code/3DS/3DSLoader.cpp index 3c659d0b0..ed3ab8bc3 100644 --- a/code/3DS/3DSLoader.cpp +++ b/code/3DS/3DSLoader.cpp @@ -72,7 +72,6 @@ static const aiImporterDesc desc = { "3ds prj" }; - // ------------------------------------------------------------------------------------------------ // Begins a new parsing block // - Reads the current chunk and validates it @@ -141,23 +140,19 @@ bool Discreet3DSImporter::CanRead( const std::string& pFile, IOSystem* pIOHandle // ------------------------------------------------------------------------------------------------ // Loader registry entry -const aiImporterDesc* Discreet3DSImporter::GetInfo () const -{ +const aiImporterDesc* Discreet3DSImporter::GetInfo () const { return &desc; } // ------------------------------------------------------------------------------------------------ // Setup configuration properties -void Discreet3DSImporter::SetupProperties(const Importer* /*pImp*/) -{ +void Discreet3DSImporter::SetupProperties(const Importer* /*pImp*/) { // nothing to be done for the moment } // ------------------------------------------------------------------------------------------------ // Imports the given file into the given scene structure. -void Discreet3DSImporter::InternReadFile( const std::string& pFile, - aiScene* pScene, IOSystem* pIOHandler) -{ +void Discreet3DSImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) { StreamReaderLE stream(pIOHandler->Open(pFile,"rb")); // We should have at least one chunk @@ -200,7 +195,7 @@ void Discreet3DSImporter::InternReadFile( const std::string& pFile, ComputeNormalsWithSmoothingsGroups(mesh); } - // Replace all occurences of the default material with a + // Replace all occurrences of the default material with a // valid material. Generate it if no material containing // DEFAULT in its name has been found in the file ReplaceDefaultMaterial(); @@ -227,8 +222,7 @@ void Discreet3DSImporter::InternReadFile( const std::string& pFile, // ------------------------------------------------------------------------------------------------ // Applies a master-scaling factor to the imported scene -void Discreet3DSImporter::ApplyMasterScale(aiScene* pScene) -{ +void Discreet3DSImporter::ApplyMasterScale(aiScene* pScene) { // There are some 3DS files with a zero scaling factor if (!mMasterScale)mMasterScale = 1.0f; else mMasterScale = 1.0f / mMasterScale; diff --git a/code/3DS/3DSLoader.h b/code/3DS/3DSLoader.h index f57e6a8e3..99e6d549b 100644 --- a/code/3DS/3DSLoader.h +++ b/code/3DS/3DSLoader.h @@ -65,15 +65,11 @@ using namespace D3DS; // --------------------------------------------------------------------------------- /** Importer class for 3D Studio r3 and r4 3DS files */ -class Discreet3DSImporter : public BaseImporter -{ +class Discreet3DSImporter : public BaseImporter { public: - Discreet3DSImporter(); ~Discreet3DSImporter(); -public: - // ------------------------------------------------------------------- /** Returns whether the class can handle the format of the given file. * See BaseImporter::CanRead() for details. diff --git a/code/Assjson/cencode.c b/code/Assjson/cencode.c index db99e7efa..707d31624 100644 --- a/code/Assjson/cencode.c +++ b/code/Assjson/cencode.c @@ -9,6 +9,9 @@ For details, see http://sourceforge.net/projects/libb64 const int CHARS_PER_LINE = 72; +#pragma warning(push) +#pragma warning(disable : 4244) + void base64_init_encodestate(base64_encodestate* state_in) { state_in->step = step_A; @@ -107,3 +110,4 @@ int base64_encode_blockend(char* code_out, base64_encodestate* state_in) return codechar - code_out; } +#pragma warning(pop) diff --git a/code/CSM/CSMLoader.cpp b/code/CSM/CSMLoader.cpp index 9dbb38467..b91ef096a 100644 --- a/code/CSM/CSMLoader.cpp +++ b/code/CSM/CSMLoader.cpp @@ -178,7 +178,7 @@ void CSMImporter::InternReadFile( const std::string& pFile, *ot++ = *buffer++; *ot = '\0'; - nda->mNodeName.length = (size_t)(ot-nda->mNodeName.data); + nda->mNodeName.length = static_cast(ot-nda->mNodeName.data); } anim->mNumChannels = static_cast(anims_temp.size()); diff --git a/code/FBX/FBXConverter.cpp b/code/FBX/FBXConverter.cpp index 5b34868ba..965b12d1d 100644 --- a/code/FBX/FBXConverter.cpp +++ b/code/FBX/FBXConverter.cpp @@ -1564,8 +1564,10 @@ namespace Assimp { bone_map.clear(); } - catch (std::exception&e) { + catch (std::exception &e) { + FBXImporter::LogError(e.what()); std::for_each(bones.begin(), bones.end(), Util::delete_fun()); + throw; } diff --git a/code/Irr/IRRLoader.cpp b/code/Irr/IRRLoader.cpp index e94fd85a4..f17ce6958 100644 --- a/code/Irr/IRRLoader.cpp +++ b/code/Irr/IRRLoader.cpp @@ -1483,6 +1483,7 @@ void IRRImporter::InternReadFile( const std::string& pFile, */ delete root; + delete reader; } #endif // !! ASSIMP_BUILD_NO_IRR_IMPORTER diff --git a/code/Material/MaterialSystem.cpp b/code/Material/MaterialSystem.cpp index aa3df9ac2..479e8c297 100644 --- a/code/Material/MaterialSystem.cpp +++ b/code/Material/MaterialSystem.cpp @@ -504,7 +504,7 @@ aiReturn aiMaterial::AddBinaryProperty (const void* pInput, pcNew->mData = new char[pSizeInBytes]; memcpy (pcNew->mData,pInput,pSizeInBytes); - pcNew->mKey.length = ::strlen(pKey); + pcNew->mKey.length = static_cast( ::strlen(pKey) ); ai_assert ( MAXLEN > pcNew->mKey.length); strcpy( pcNew->mKey.data, pKey ); diff --git a/code/Q3BSP/Q3BSPFileImporter.cpp b/code/Q3BSP/Q3BSPFileImporter.cpp index 4add00a07..ba08fe62c 100644 --- a/code/Q3BSP/Q3BSPFileImporter.cpp +++ b/code/Q3BSP/Q3BSPFileImporter.cpp @@ -616,7 +616,7 @@ bool Q3BSPFileImporter::importTextureFromArchive( const Q3BSP::Q3BSPModel *model // We'll leave it up to the user to figure out which extension the file has. aiString name; strncpy( name.data, pTexture->strName, sizeof name.data ); - name.length = strlen( name.data ); + name.length = static_cast(strlen( name.data )); pMatHelper->AddProperty( &name, AI_MATKEY_TEXTURE_DIFFUSE( 0 ) ); } } diff --git a/code/SMD/SMDLoader.cpp b/code/SMD/SMDLoader.cpp index 7eb6b18d1..4ca72345f 100644 --- a/code/SMD/SMDLoader.cpp +++ b/code/SMD/SMDLoader.cpp @@ -616,7 +616,7 @@ void SMDImporter::CreateOutputMaterials() { if (aszTextures[iMat].length()) { ::strncpy(szName.data, aszTextures[iMat].c_str(),MAXLEN-1); - szName.length = aszTextures[iMat].length(); + szName.length = static_cast( aszTextures[iMat].length() ); pcMat->AddProperty(&szName,AI_MATKEY_TEXTURE_DIFFUSE(0)); } } diff --git a/code/Unreal/UnrealLoader.cpp b/code/Unreal/UnrealLoader.cpp index 0bd4650d0..31bfb480b 100644 --- a/code/Unreal/UnrealLoader.cpp +++ b/code/Unreal/UnrealLoader.cpp @@ -3,9 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2019, assimp team - - +Copyright (c) 2006-2020, assimp team All rights reserved. @@ -48,8 +46,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * http://local.wasp.uwa.edu.au/~pbourke/dataformats/unreal/ */ - - #ifndef ASSIMP_BUILD_NO_3D_IMPORTER #include "Unreal/UnrealLoader.h" @@ -65,9 +61,99 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include +#include using namespace Assimp; +namespace Unreal { + + /* + 0 = Normal one-sided + 1 = Normal two-sided + 2 = Translucent two-sided + 3 = Masked two-sided + 4 = Modulation blended two-sided + 8 = Placeholder triangle for weapon positioning (invisible) + */ +enum MeshFlags { + MF_NORMAL_OS = 0, + MF_NORMAL_TS = 1, + MF_NORMAL_TRANS_TS = 2, + MF_NORMAL_MASKED_TS = 3, + MF_NORMAL_MOD_TS = 4, + MF_WEAPON_PLACEHOLDER = 8 +}; + +// a single triangle +struct Triangle { + uint16_t mVertex[3]; // Vertex indices + char mType; // James' Mesh Type + char mColor; // Color for flat and Gourand Shaded + unsigned char mTex[3][2]; // Texture UV coordinates + unsigned char mTextureNum; // Source texture offset + char mFlags; // Unreal Mesh Flags (unused) + + unsigned int matIndex; +}; + +// temporary representation for a material +struct TempMat { + TempMat() : + type(), tex(), numFaces(0) {} + + explicit TempMat(const Triangle &in) : + type((Unreal::MeshFlags)in.mType), tex(in.mTextureNum), numFaces(0) {} + + // type of mesh + Unreal::MeshFlags type; + + // index of texture + unsigned int tex; + + // number of faces using us + unsigned int numFaces; + + // for std::find + bool operator==(const TempMat &o) { + return (tex == o.tex && type == o.type); + } +}; + +struct Vertex { + int32_t X : 11; + int32_t Y : 11; + int32_t Z : 10; +}; + +// UNREAL vertex compression +inline void CompressVertex(const aiVector3D &v, uint32_t &out) { + union { + Vertex n; + int32_t t; + }; + n.X = (int32_t)v.x; + n.Y = (int32_t)v.y; + n.Z = (int32_t)v.z; + ::memcpy(&out, &t, sizeof(int32_t)); + //out = t; +} + +// UNREAL vertex decompression +inline void DecompressVertex(aiVector3D &v, int32_t in) { + union { + Vertex n; + int32_t i; + }; + i = in; + + v.x = (float)n.X; + v.y = (float)n.Y; + v.z = (float)n.Z; +} + +} // end namespace Unreal + + static const aiImporterDesc desc = { "Unreal Mesh Importer", "", @@ -403,7 +489,7 @@ void UnrealImporter::InternReadFile( const std::string& pFile, // set color and name mat->AddProperty(&color,1,AI_MATKEY_COLOR_DIFFUSE); - s.length = ::strlen(s.data); + s.length = static_cast(::strlen(s.data)); mat->AddProperty(&s,AI_MATKEY_NAME); // set texture, if any diff --git a/code/Unreal/UnrealLoader.h b/code/Unreal/UnrealLoader.h index 678aaa76b..e758e815a 100644 --- a/code/Unreal/UnrealLoader.h +++ b/code/Unreal/UnrealLoader.h @@ -2,8 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2019, assimp team - +Copyright (c) 2006-2020, assimp team All rights reserved. @@ -47,118 +46,17 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define INCLUDED_AI_3D_LOADER_H #include -#include -namespace Assimp { -namespace Unreal { - - /* - 0 = Normal one-sided - 1 = Normal two-sided - 2 = Translucent two-sided - 3 = Masked two-sided - 4 = Modulation blended two-sided - 8 = Placeholder triangle for weapon positioning (invisible) - */ -enum MeshFlags { - MF_NORMAL_OS = 0, - MF_NORMAL_TS = 1, - MF_NORMAL_TRANS_TS = 2, - MF_NORMAL_MASKED_TS = 3, - MF_NORMAL_MOD_TS = 4, - MF_WEAPON_PLACEHOLDER = 8 -}; - - // a single triangle -struct Triangle { - uint16_t mVertex[3]; // Vertex indices - char mType; // James' Mesh Type - char mColor; // Color for flat and Gourand Shaded - unsigned char mTex[3][2]; // Texture UV coordinates - unsigned char mTextureNum; // Source texture offset - char mFlags; // Unreal Mesh Flags (unused) - - unsigned int matIndex; -}; - -// temporary representation for a material -struct TempMat { - TempMat() - : type() - , tex() - , numFaces (0) - {} - - explicit TempMat(const Triangle& in) - : type ((Unreal::MeshFlags)in.mType) - , tex (in.mTextureNum) - , numFaces (0) - {} - - // type of mesh - Unreal::MeshFlags type; - - // index of texture - unsigned int tex; - - // number of faces using us - unsigned int numFaces; - - // for std::find - bool operator == (const TempMat& o ) { - return (tex == o.tex && type == o.type); - } -}; - -struct Vertex -{ - int32_t X : 11; - int32_t Y : 11; - int32_t Z : 10; -}; - - // UNREAL vertex compression -inline void CompressVertex(const aiVector3D& v, uint32_t& out) -{ - union { - Vertex n; - int32_t t; - }; - n.X = (int32_t)v.x; - n.Y = (int32_t)v.y; - n.Z = (int32_t)v.z; - ::memcpy( &out, &t, sizeof(int32_t)); - //out = t; -} - - // UNREAL vertex decompression -inline void DecompressVertex(aiVector3D& v, int32_t in) -{ - union { - Vertex n; - int32_t i; - }; - i = in; - - v.x = (float)n.X; - v.y = (float)n.Y; - v.z = (float)n.Z; -} - -} // end namespace Unreal +namespace Assimp { // --------------------------------------------------------------------------- /** @brief Importer class to load UNREAL files (*.3d) */ -class UnrealImporter : public BaseImporter -{ +class UnrealImporter : public BaseImporter { public: UnrealImporter(); ~UnrealImporter(); - -public: - // ------------------------------------------------------------------- /** @brief Returns whether we can handle the format of the given file * @@ -184,7 +82,6 @@ protected: */ void SetupProperties(const Importer* pImp); - // ------------------------------------------------------------------- /** @brief Imports the given file into the given scene structure. * @@ -204,4 +101,5 @@ private: }; // !class UnrealImporter } // end of namespace Assimp + #endif // AI_UNREALIMPORTER_H_INC diff --git a/contrib/zip/src/miniz.h b/contrib/zip/src/miniz.h index c4fcfb83e..07f7b2de2 100644 --- a/contrib/zip/src/miniz.h +++ b/contrib/zip/src/miniz.h @@ -6085,7 +6085,7 @@ mz_zip_writer_compute_padding_needed_for_file_alignment(mz_zip_archive *pZip) { if (!pZip->m_file_offset_alignment) return 0; n = (mz_uint32)(pZip->m_archive_size & (pZip->m_file_offset_alignment - 1)); - return (pZip->m_file_offset_alignment - n) & + return (mz_uint)(pZip->m_file_offset_alignment - n) & (pZip->m_file_offset_alignment - 1); } diff --git a/tools/assimp_view/Display.cpp b/tools/assimp_view/Display.cpp index ab29c1d3e..9105cf97a 100644 --- a/tools/assimp_view/Display.cpp +++ b/tools/assimp_view/Display.cpp @@ -275,7 +275,7 @@ int CDisplay::ReplaceCurrentTexture(const char* szPath) IDirect3DTexture9* piTexture = NULL; aiString szString; strcpy(szString.data,szPath); - szString.length = strlen(szPath); + szString.length = static_cast(strlen(szPath)); CMaterialManager::Instance().LoadTexture(&piTexture,&szString); if (!piTexture) { diff --git a/tools/assimp_view/Material.cpp b/tools/assimp_view/Material.cpp index 2c5316d81..ef32691d4 100644 --- a/tools/assimp_view/Material.cpp +++ b/tools/assimp_view/Material.cpp @@ -287,7 +287,7 @@ bool CMaterialManager::TryLongerPath(char* szTemp,aiString* p_szString) size_t iLen2 = iLen+1; iLen2 = iLen2 > MAXLEN ? MAXLEN : iLen2; memcpy(p_szString->data,szTempB,iLen2); - p_szString->length = iLen; + p_szString->length = static_cast(iLen); return true; } } @@ -301,7 +301,7 @@ bool CMaterialManager::TryLongerPath(char* szTemp,aiString* p_szString) size_t iLen2 = iLen+1; iLen2 = iLen2 > MAXLEN ? MAXLEN : iLen2; memcpy(p_szString->data,szTempB,iLen2); - p_szString->length = iLen; + p_szString->length = static_cast(iLen); return true; } } @@ -392,7 +392,7 @@ int CMaterialManager::FindValidPath(aiString* p_szString) if((pFile=fopen( tmp2,"r" ))){ fclose( pFile ); strcpy(p_szString->data,tmp2); - p_szString->length = strlen(tmp2); + p_szString->length = static_cast(strlen(tmp2)); return 1; } } @@ -403,11 +403,11 @@ int CMaterialManager::FindValidPath(aiString* p_szString) fclose(pFile); // copy the result string back to the aiString - const size_t iLen = strlen(szTemp); - size_t iLen2 = iLen+1; - iLen2 = iLen2 > MAXLEN ? MAXLEN : iLen2; - memcpy(p_szString->data,szTemp,iLen2); - p_szString->length = iLen; + const size_t len = strlen(szTemp); + size_t len2 = len+1; + len2 = len2 > MAXLEN ? MAXLEN : len2; + memcpy(p_szString->data, szTemp, len2); + p_szString->length = static_cast(len); } return 1; From f51b9378b126c58790638d2cd1bd0e573c55b586 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Fri, 17 Jan 2020 19:26:58 +0100 Subject: [PATCH 005/330] updating irrXml. --- contrib/irrXML/CXMLReaderImpl.h | 34 ++------ contrib/irrXML/fast_atof.h | 139 ++++++++++++++++++++++++++++++++ contrib/irrXML/irrArray.h | 7 +- contrib/irrXML/irrString.h | 12 +-- contrib/irrXML/irrTypes.h | 15 +--- contrib/irrXML/irrXML.cpp | 8 +- contrib/irrXML/irrXML.h | 28 +++---- 7 files changed, 172 insertions(+), 71 deletions(-) create mode 100644 contrib/irrXML/fast_atof.h diff --git a/contrib/irrXML/CXMLReaderImpl.h b/contrib/irrXML/CXMLReaderImpl.h index a125312a1..ad477ca51 100644 --- a/contrib/irrXML/CXMLReaderImpl.h +++ b/contrib/irrXML/CXMLReaderImpl.h @@ -8,16 +8,7 @@ #include "irrXML.h" #include "irrString.h" #include "irrArray.h" - -#include -#include -#include -#include -//using namespace Assimp; - -// For locale independent number conversion -#include -#include +#include "fast_atof.h" #ifdef _DEBUG #define IRR_DEBUGPRINT(x) printf((x)); @@ -40,7 +31,7 @@ public: //! Constructor CXMLReaderImpl(IFileReadCallBack* callback, bool deleteCallBack = true) - : TextData(0), P(0), TextBegin(0), TextSize(0), CurrentNodeType(EXN_NONE), + : TextData(0), P(0), TextSize(0), TextBegin(0), CurrentNodeType(EXN_NONE), SourceFormat(ETF_ASCII), TargetFormat(ETF_ASCII) { if (!callback) @@ -168,8 +159,7 @@ public: return 0; core::stringc c = attr->Value.c_str(); - return static_cast(atof(c.c_str())); - //return fast_atof(c.c_str()); + return core::fast_atof(c.c_str()); } @@ -181,11 +171,7 @@ public: return 0; core::stringc c = attrvalue; - std::istringstream sstr(c.c_str()); - sstr.imbue(std::locale("C")); // Locale free number convert - float fNum; - sstr >> fNum; - return fNum; + return core::fast_atof(c.c_str()); } @@ -228,7 +214,7 @@ private: { char_type* start = P; - // move forward until '<' found + // more forward until '<' found while(*P != L'<' && *P) ++P; @@ -438,10 +424,6 @@ private: while(*P != L'>') ++P; - // remove trailing whitespace, if any - while( std::isspace( P[-1])) - --P; - NodeName = core::string(pBeginClose, (int)(P - pBeginClose)); ++P; } @@ -676,12 +658,8 @@ private: TextData = new char_type[sizeWithoutHeader]; - // MSVC debugger complains here about loss of data ... - size_t numShift = sizeof( char_type) * 8; - assert(numShift < 64); - const src_char_type cc = (src_char_type)(((uint64_t(1u) << numShift) - 1)); for (int i=0; i +#include + +namespace irr +{ +namespace core +{ + +const float fast_atof_table[] = { + 0.f, + 0.1f, + 0.01f, + 0.001f, + 0.0001f, + 0.00001f, + 0.000001f, + 0.0000001f, + 0.00000001f, + 0.000000001f, + 0.0000000001f, + 0.00000000001f, + 0.000000000001f, + 0.0000000000001f, + 0.00000000000001f, + 0.000000000000001f + }; + +//! Provides a fast function for converting a string into a float, +//! about 6 times faster than atof in win32. +// If you find any bugs, please send them to me, niko (at) irrlicht3d.org. +inline char* fast_atof_move(char* c, float& out) +{ + bool inv = false; + char *t; + float f; + + if (*c=='-') + { + c++; + inv = true; + } + + f = (float)strtol(c, &t, 10); + + c = t; + + if (*c == '.') + { + c++; + + float pl = (float)strtol(c, &t, 10); + pl *= fast_atof_table[t-c]; + + f += pl; + + c = t; + + if (*c == 'e') + { + ++c; + float exp = (float)strtol(c, &t, 10); + f *= (float)pow(10.0f, exp); + c = t; + } + } + + if (inv) + f *= -1.0f; + + out = f; + return c; +} + +//! Provides a fast function for converting a string into a float, +//! about 6 times faster than atof in win32. +// If you find any bugs, please send them to me, niko (at) irrlicht3d.org. +inline const char* fast_atof_move_const(const char* c, float& out) +{ + bool inv = false; + char *t; + float f; + + if (*c=='-') + { + c++; + inv = true; + } + + f = (float)strtol(c, &t, 10); + + c = t; + + if (*c == '.') + { + c++; + + float pl = (float)strtol(c, &t, 10); + pl *= fast_atof_table[t-c]; + + f += pl; + + c = t; + + if (*c == 'e') + { + ++c; + f32 exp = (f32)strtol(c, &t, 10); + f *= (f32)powf(10.0f, exp); + c = t; + } + } + + if (inv) + f *= -1.0f; + + out = f; + return c; +} + + +inline float fast_atof(const char* c) +{ + float ret; + fast_atof_move_const(c, ret); + return ret; +} + +} // end namespace core +}// end namespace irr + +#endif + diff --git a/contrib/irrXML/irrArray.h b/contrib/irrXML/irrArray.h index 51302680e..f7b710b80 100644 --- a/contrib/irrXML/irrArray.h +++ b/contrib/irrXML/irrArray.h @@ -21,8 +21,9 @@ class array { public: - array() - : data(0), allocated(0), used(0), + + array() + : data(0), used(0), allocated(0), free_when_destroyed(true), is_sorted(true) { } @@ -30,7 +31,7 @@ public: //! Constructs a array and allocates an initial chunk of memory. //! \param start_count: Amount of elements to allocate. array(u32 start_count) - : data(0), allocated(0), used(0), + : data(0), used(0), allocated(0), free_when_destroyed(true), is_sorted(true) { reallocate(start_count); diff --git a/contrib/irrXML/irrString.h b/contrib/irrXML/irrString.h index ff0097b71..1b32ee5ea 100644 --- a/contrib/irrXML/irrString.h +++ b/contrib/irrXML/irrString.h @@ -19,7 +19,7 @@ so you can assign unicode to string and ascii to string Note that the conversation between both is not done using an encoding. Known bugs: -Special characters like 'Ä', 'Ü' and 'Ö' are ignored in the +Special characters like '', '' and '' are ignored in the methods make_upper, make_lower and equals_ignore_case. */ template @@ -29,7 +29,7 @@ public: //! Default constructor string() - : array(0), allocated(1), used(1) + : allocated(1), used(1), array(0) { array = new T[1]; array[0] = 0x0; @@ -39,7 +39,7 @@ public: //! Constructor string(const string& other) - : array(0), allocated(0), used(0) + : allocated(0), used(0), array(0) { *this = other; } @@ -47,7 +47,7 @@ public: //! Constructs a string from an int string(int number) - : array(0), allocated(0), used(0) + : allocated(0), used(0), array(0) { // store if negative and make positive @@ -98,7 +98,7 @@ public: //! Constructor for copying a string from a pointer with a given lenght template string(const B* c, s32 lenght) - : array(0), allocated(0), used(0) + : allocated(0), used(0), array(0) { if (!c) return; @@ -117,7 +117,7 @@ public: //! Constructor for unicode and ascii strings template string(const B* c) - : array(0),allocated(0), used(0) + : allocated(0), used(0), array(0) { *this = c; } diff --git a/contrib/irrXML/irrTypes.h b/contrib/irrXML/irrTypes.h index a7f12ec75..107f6649e 100644 --- a/contrib/irrXML/irrTypes.h +++ b/contrib/irrXML/irrTypes.h @@ -79,13 +79,8 @@ typedef unsigned short wchar_t; #endif // microsoft compiler //! define a break macro for debugging only in Win32 mode. -// WORKAROUND (assimp): remove __asm -#if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) -#if defined(_M_IX86) -#define _IRR_DEBUG_BREAK_IF( _CONDITION_ ) /*if (_CONDITION_) {_asm int 3}*/ -#else -#define _IRR_DEBUG_BREAK_IF( _CONDITION_ ) -#endif +#if !defined(_WIN64) && defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) +#define _IRR_DEBUG_BREAK_IF( _CONDITION_ ) if (_CONDITION_) {_asm int 3} #else #define _IRR_DEBUG_BREAK_IF( _CONDITION_ ) #endif @@ -96,10 +91,8 @@ When you call unmanaged code that returns a bool type value of false from manage the return value may appear as true. See http://support.microsoft.com/default.aspx?kbid=823071 for details. Compiler version defines: VC6.0 : 1200, VC7.0 : 1300, VC7.1 : 1310, VC8.0 : 1400*/ - -// WORKAROUND (assimp): remove __asm -#if defined(WIN32) && defined(_MSC_VER) && (_MSC_VER > 1299) && (_MSC_VER < 1400) -#define _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX /*__asm mov eax,100*/ +#if !defined(_WIN64) && defined(WIN32) && defined(_MSC_VER) && (_MSC_VER > 1299) && (_MSC_VER < 1400) +#define _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX __asm mov eax,100 #else #define _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX #endif // _IRR_MANAGED_MARSHALLING_BUGFIX diff --git a/contrib/irrXML/irrXML.cpp b/contrib/irrXML/irrXML.cpp index 5a4b04507..3fd510302 100644 --- a/contrib/irrXML/irrXML.cpp +++ b/contrib/irrXML/irrXML.cpp @@ -2,14 +2,10 @@ // This file is part of the "Irrlicht Engine" and the "irrXML" project. // For conditions of distribution and use, see copyright notice in irrlicht.h and/or irrXML.h -// Need to include Assimp, too. We're using Assimp's version of fast_atof -// so we need stdint.h. But no PCH. - - #include "irrXML.h" #include "irrString.h" #include "irrArray.h" -//#include +#include "fast_atof.h" #include "CXMLReaderImpl.h" namespace irr @@ -18,7 +14,7 @@ namespace io { //! Implementation of the file read callback for ordinary files -class IRRXML_API CFileReadCallBack : public IFileReadCallBack +class CFileReadCallBack : public IFileReadCallBack { public: diff --git a/contrib/irrXML/irrXML.h b/contrib/irrXML/irrXML.h index d724b3162..30b56c7b9 100644 --- a/contrib/irrXML/irrXML.h +++ b/contrib/irrXML/irrXML.h @@ -7,12 +7,6 @@ #include -#ifdef _WIN32 -# define IRRXML_API __declspec(dllexport) -#else -# define IRRXML_API __attribute__ ((visibility("default"))) -#endif // _WIN32 - /** \mainpage irrXML 1.2 API documentation
@@ -178,7 +172,7 @@ namespace io ETF_UTF32_BE, //! UTF-32 format, little endian - ETF_UTF32_LE + ETF_UTF32_LE, }; @@ -215,7 +209,7 @@ namespace io two methods to read your data and give a pointer to an instance of your implementation when calling createIrrXMLReader(), createIrrXMLReaderUTF16() or createIrrXMLReaderUTF32() */ - class IRRXML_API IFileReadCallBack + class IFileReadCallBack { public: @@ -415,7 +409,7 @@ namespace io \return Returns a pointer to the created xml parser. This pointer should be deleted using 'delete' after no longer needed. Returns 0 if an error occured and the file could not be opened. */ - IRRXML_API IrrXMLReader* createIrrXMLReader(const char* filename); + IrrXMLReader* createIrrXMLReader(const char* filename); //! Creates an instance of an UFT-8 or ASCII character xml parser. /** This means that all character data will be returned in 8 bit ASCII or UTF-8. The file to read can @@ -427,7 +421,7 @@ namespace io \return Returns a pointer to the created xml parser. This pointer should be deleted using 'delete' after no longer needed. Returns 0 if an error occured and the file could not be opened. */ - IRRXML_API IrrXMLReader* createIrrXMLReader(FILE* file); + IrrXMLReader* createIrrXMLReader(FILE* file); //! Creates an instance of an UFT-8 or ASCII character xml parser. /** This means that all character data will be returned in 8 bit ASCII or UTF-8. The file to read can @@ -440,7 +434,7 @@ namespace io \return Returns a pointer to the created xml parser. This pointer should be deleted using 'delete' after no longer needed. Returns 0 if an error occured and the file could not be opened. */ - IRRXML_API IrrXMLReader* createIrrXMLReader(IFileReadCallBack* callback); + IrrXMLReader* createIrrXMLReader(IFileReadCallBack* callback); //! Creates an instance of an UFT-16 xml parser. /** This means that @@ -452,7 +446,7 @@ namespace io \return Returns a pointer to the created xml parser. This pointer should be deleted using 'delete' after no longer needed. Returns 0 if an error occured and the file could not be opened. */ - IRRXML_API IrrXMLReaderUTF16* createIrrXMLReaderUTF16(const char* filename); + IrrXMLReaderUTF16* createIrrXMLReaderUTF16(const char* filename); //! Creates an instance of an UFT-16 xml parser. /** This means that all character data will be returned in UTF-16. The file to read can @@ -464,7 +458,7 @@ namespace io \return Returns a pointer to the created xml parser. This pointer should be deleted using 'delete' after no longer needed. Returns 0 if an error occured and the file could not be opened. */ - IRRXML_API IrrXMLReaderUTF16* createIrrXMLReaderUTF16(FILE* file); + IrrXMLReaderUTF16* createIrrXMLReaderUTF16(FILE* file); //! Creates an instance of an UFT-16 xml parser. /** This means that all character data will be returned in UTF-16. The file to read can @@ -477,7 +471,7 @@ namespace io \return Returns a pointer to the created xml parser. This pointer should be deleted using 'delete' after no longer needed. Returns 0 if an error occured and the file could not be opened. */ - IRRXML_API IrrXMLReaderUTF16* createIrrXMLReaderUTF16(IFileReadCallBack* callback); + IrrXMLReaderUTF16* createIrrXMLReaderUTF16(IFileReadCallBack* callback); //! Creates an instance of an UFT-32 xml parser. @@ -489,7 +483,7 @@ namespace io \return Returns a pointer to the created xml parser. This pointer should be deleted using 'delete' after no longer needed. Returns 0 if an error occured and the file could not be opened. */ - IRRXML_API IrrXMLReaderUTF32* createIrrXMLReaderUTF32(const char* filename); + IrrXMLReaderUTF32* createIrrXMLReaderUTF32(const char* filename); //! Creates an instance of an UFT-32 xml parser. /** This means that all character data will be returned in UTF-32. The file to read can @@ -501,7 +495,7 @@ namespace io \return Returns a pointer to the created xml parser. This pointer should be deleted using 'delete' after no longer needed. Returns 0 if an error occured and the file could not be opened. */ - IRRXML_API IrrXMLReaderUTF32* createIrrXMLReaderUTF32(FILE* file); + IrrXMLReaderUTF32* createIrrXMLReaderUTF32(FILE* file); //! Creates an instance of an UFT-32 xml parser. /** This means that @@ -515,7 +509,7 @@ namespace io \return Returns a pointer to the created xml parser. This pointer should be deleted using 'delete' after no longer needed. Returns 0 if an error occured and the file could not be opened. */ - IRRXML_API IrrXMLReaderUTF32* createIrrXMLReaderUTF32(IFileReadCallBack* callback); + IrrXMLReaderUTF32* createIrrXMLReaderUTF32(IFileReadCallBack* callback); /*! \file irrxml.h From 783430667b2072c9d8fd1cdee263c296405777d7 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Fri, 17 Jan 2020 20:21:53 +0100 Subject: [PATCH 006/330] fix initializer ordering for irrXml. --- contrib/irrXML/CXMLReaderImpl.h | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/contrib/irrXML/CXMLReaderImpl.h b/contrib/irrXML/CXMLReaderImpl.h index ad477ca51..63349b0cc 100644 --- a/contrib/irrXML/CXMLReaderImpl.h +++ b/contrib/irrXML/CXMLReaderImpl.h @@ -28,14 +28,23 @@ template class CXMLReaderImpl : public IIrrXMLReader { public: - //! Constructor - CXMLReaderImpl(IFileReadCallBack* callback, bool deleteCallBack = true) - : TextData(0), P(0), TextSize(0), TextBegin(0), CurrentNodeType(EXN_NONE), - SourceFormat(ETF_ASCII), TargetFormat(ETF_ASCII) - { - if (!callback) + CXMLReaderImpl(IFileReadCallBack* callback, bool deleteCallBack = true) + : TextData(0) + , P(0) + , TextBegin(0) + , TextSize(0) + , CurrentNodeType(EXN_NONE) + , SourceFormat(ETF_ASCII) + , TargetFormat(ETF_ASCII) + , NodeName () + , EmptyString() + , IsEmptyElement(false) + , SpecialCharacters() + , Attributes() { + if (!callback) { return; + } storeTargetFormat(); From 2ebafe06938b9e06bae67f793c8ca36fc0f80457 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc?= Date: Wed, 22 Jan 2020 12:40:57 +0100 Subject: [PATCH 007/330] Fix version revision formatting in glTF metadata --- code/glTF/glTFExporter.cpp | 2 +- code/glTF2/glTF2Exporter.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/code/glTF/glTFExporter.cpp b/code/glTF/glTFExporter.cpp index 4772c7dc6..cf891203a 100644 --- a/code/glTF/glTFExporter.cpp +++ b/code/glTF/glTFExporter.cpp @@ -869,7 +869,7 @@ void glTFExporter::ExportMetadata() asset.version = "1.0"; char buffer[256]; - ai_snprintf(buffer, 256, "Open Asset Import Library (assimp v%d.%d.%d)", + ai_snprintf(buffer, 256, "Open Asset Import Library (assimp v%d.%d.%x)", aiGetVersionMajor(), aiGetVersionMinor(), aiGetVersionRevision()); asset.generator = buffer; diff --git a/code/glTF2/glTF2Exporter.cpp b/code/glTF2/glTF2Exporter.cpp index ee40694f9..16ba69b9f 100644 --- a/code/glTF2/glTF2Exporter.cpp +++ b/code/glTF2/glTF2Exporter.cpp @@ -991,7 +991,7 @@ void glTF2Exporter::ExportMetadata() asset.version = "2.0"; char buffer[256]; - ai_snprintf(buffer, 256, "Open Asset Import Library (assimp v%d.%d.%d)", + ai_snprintf(buffer, 256, "Open Asset Import Library (assimp v%d.%d.%x)", aiGetVersionMajor(), aiGetVersionMinor(), aiGetVersionRevision()); asset.generator = buffer; From ff8a924ffbde41c2cc8054fc030aacaed92b4eac Mon Sep 17 00:00:00 2001 From: Marc-Antoine Lortie Date: Wed, 22 Jan 2020 09:09:39 -0500 Subject: [PATCH 008/330] [HL1 MDL] Removed downscale for textures with dimensions greater than 256. --- code/MDL/HalfLife/HL1MDLLoader.cpp | 60 ++++++------------------------ 1 file changed, 11 insertions(+), 49 deletions(-) diff --git a/code/MDL/HalfLife/HL1MDLLoader.cpp b/code/MDL/HalfLife/HL1MDLLoader.cpp index 90a1479a3..eff5b80b7 100644 --- a/code/MDL/HalfLife/HL1MDLLoader.cpp +++ b/code/MDL/HalfLife/HL1MDLLoader.cpp @@ -316,36 +316,14 @@ void HL1MDLLoader::load_sequence_groups_files() { } // ------------------------------------------------------------------------------------------------ -/** @brief Read an MDL texture. -* -* @note This method is taken from HL1 source code. -* source: file: studio_utils.c -* function(s): UploadTexture -*/ +// Read an MDL texture. void HL1MDLLoader::read_texture(const Texture_HL1 *ptexture, uint8_t *data, uint8_t *pal, aiTexture *pResult, aiColor3D &last_palette_color) { - int outwidth, outheight; - int i, j; - int row1[256], row2[256], col1[256], col2[256]; - unsigned char *pix1, *pix2, *pix3, *pix4; - - // convert texture to power of 2 - for (outwidth = 1; outwidth < ptexture->width; outwidth <<= 1) - ; - - if (outwidth > 256) - outwidth = 256; - - for (outheight = 1; outheight < ptexture->height; outheight <<= 1) - ; - - if (outheight > 256) - outheight = 256; pResult->mFilename = ptexture->name; - pResult->mWidth = outwidth; - pResult->mHeight = outheight; + pResult->mWidth = static_cast(ptexture->width); + pResult->mHeight = static_cast(ptexture->height); pResult->achFormatHint[0] = 'b'; pResult->achFormatHint[1] = 'g'; pResult->achFormatHint[2] = 'r'; @@ -356,31 +334,15 @@ void HL1MDLLoader::read_texture(const Texture_HL1 *ptexture, pResult->achFormatHint[7] = '8'; pResult->achFormatHint[8] = '\0'; - aiTexel *out = pResult->pcData = new aiTexel[outwidth * outheight]; + const size_t num_pixels = pResult->mWidth * pResult->mHeight; + aiTexel *out = pResult->pcData = new aiTexel[num_pixels]; - for (i = 0; i < outwidth; i++) { - col1[i] = (int)((i + 0.25) * (ptexture->width / (float)outwidth)); - col2[i] = (int)((i + 0.75) * (ptexture->width / (float)outwidth)); - } - - for (i = 0; i < outheight; i++) { - row1[i] = (int)((i + 0.25) * (ptexture->height / (float)outheight)) * ptexture->width; - row2[i] = (int)((i + 0.75) * (ptexture->height / (float)outheight)) * ptexture->width; - } - - // scale down and convert to 32bit RGB - for (i = 0; i < outheight; i++) { - for (j = 0; j < outwidth; j++, out++) { - pix1 = &pal[data[row1[i] + col1[j]] * 3]; - pix2 = &pal[data[row1[i] + col2[j]] * 3]; - pix3 = &pal[data[row2[i] + col1[j]] * 3]; - pix4 = &pal[data[row2[i] + col2[j]] * 3]; - - out->r = (pix1[0] + pix2[0] + pix3[0] + pix4[0]) >> 2; - out->g = (pix1[1] + pix2[1] + pix3[1] + pix4[1]) >> 2; - out->b = (pix1[2] + pix2[2] + pix3[2] + pix4[2]) >> 2; - out->a = 0xFF; - } + // Convert indexed 8 bit to 32 bit RGBA. + for (size_t i = 0; i < num_pixels; ++i, ++out) { + out->r = pal[data[i] * 3]; + out->g = pal[data[i] * 3 + 1]; + out->b = pal[data[i] * 3 + 2]; + out->a = 255; } // Get the last palette color. From 20388d6a4f3fe1d510c454265eeb7a28b6ce4265 Mon Sep 17 00:00:00 2001 From: Marc-Antoine Lortie Date: Tue, 28 Jan 2020 09:55:05 -0500 Subject: [PATCH 009/330] Refactored Assbin exporter and assimp_cmd binary serialization functions. - Renamed AssimpExport to AssimpFileWriter. - Moved AssimpFileWriter to it's own file. - Added a try catch in WriteBinaryDump to fix a case with memory leak. - Replaced calls to WriteBinaryDump with AssimpFileWriter. - Added new AssimpFileWriter files to CMakeLists.txt. --- code/Assbin/AssbinExporter.cpp | 790 +--------------------------- code/Assbin/AssbinFileWriter.cpp | 858 +++++++++++++++++++++++++++++++ code/Assbin/AssbinFileWriter.h | 65 +++ code/CMakeLists.txt | 2 + tools/assimp_cmd/Main.h | 1 + tools/assimp_cmd/WriteDumb.cpp | 705 +------------------------ 6 files changed, 952 insertions(+), 1469 deletions(-) create mode 100644 code/Assbin/AssbinFileWriter.cpp create mode 100644 code/Assbin/AssbinFileWriter.h diff --git a/code/Assbin/AssbinExporter.cpp b/code/Assbin/AssbinExporter.cpp index 86a42c400..c748624a7 100644 --- a/code/Assbin/AssbinExporter.cpp +++ b/code/Assbin/AssbinExporter.cpp @@ -46,800 +46,16 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef ASSIMP_BUILD_NO_EXPORT #ifndef ASSIMP_BUILD_NO_ASSBIN_EXPORTER -#include "Common/assbin_chunks.h" -#include "PostProcessing/ProcessHelper.h" +#include "AssbinFileWriter.h" -#include -#include +#include #include #include -#include - -#ifdef ASSIMP_BUILD_NO_OWN_ZLIB -# include -#else -# include "../contrib/zlib/zlib.h" -#endif - -#include namespace Assimp { -template -size_t Write(IOStream * stream, const T& v) { - return stream->Write( &v, sizeof(T), 1 ); -} - -// ----------------------------------------------------------------------------------- -// Serialize an aiString -template <> -inline -size_t Write(IOStream * stream, const aiString& s) { - const size_t s2 = (uint32_t)s.length; - stream->Write(&s,4,1); - stream->Write(s.data,s2,1); - - return s2+4; -} - -// ----------------------------------------------------------------------------------- -// Serialize an unsigned int as uint32_t -template <> -inline -size_t Write(IOStream * stream, const unsigned int& w) { - const uint32_t t = (uint32_t)w; - if (w > t) { - // this shouldn't happen, integers in Assimp data structures never exceed 2^32 - throw DeadlyExportError("loss of data due to 64 -> 32 bit integer conversion"); - } - - stream->Write(&t,4,1); - - return 4; -} - -// ----------------------------------------------------------------------------------- -// Serialize an unsigned int as uint16_t -template <> -inline -size_t Write(IOStream * stream, const uint16_t& w) { - static_assert(sizeof(uint16_t)==2, "sizeof(uint16_t)==2"); - stream->Write(&w,2,1); - - return 2; -} - -// ----------------------------------------------------------------------------------- -// Serialize a float -template <> -inline -size_t Write(IOStream * stream, const float& f) { - static_assert(sizeof(float)==4, "sizeof(float)==4"); - stream->Write(&f,4,1); - - return 4; -} - -// ----------------------------------------------------------------------------------- -// Serialize a double -template <> -inline -size_t Write(IOStream * stream, const double& f) { - static_assert(sizeof(double)==8, "sizeof(double)==8"); - stream->Write(&f,8,1); - - return 8; -} - -// ----------------------------------------------------------------------------------- -// Serialize a vec3 -template <> -inline -size_t Write(IOStream * stream, const aiVector3D& v) { - size_t t = Write(stream,v.x); - t += Write(stream,v.y); - t += Write(stream,v.z); - - return t; -} - -// ----------------------------------------------------------------------------------- -// Serialize a color value -template <> -inline -size_t Write(IOStream * stream, const aiColor3D& v) { - size_t t = Write(stream,v.r); - t += Write(stream,v.g); - t += Write(stream,v.b); - - return t; -} - -// ----------------------------------------------------------------------------------- -// Serialize a color value -template <> -inline -size_t Write(IOStream * stream, const aiColor4D& v) { - size_t t = Write(stream,v.r); - t += Write(stream,v.g); - t += Write(stream,v.b); - t += Write(stream,v.a); - - return t; -} - -// ----------------------------------------------------------------------------------- -// Serialize a quaternion -template <> -inline -size_t Write(IOStream * stream, const aiQuaternion& v) { - size_t t = Write(stream,v.w); - t += Write(stream,v.x); - t += Write(stream,v.y); - t += Write(stream,v.z); - ai_assert(t == 16); - - return 16; -} - -// ----------------------------------------------------------------------------------- -// Serialize a vertex weight -template <> -inline -size_t Write(IOStream * stream, const aiVertexWeight& v) { - size_t t = Write(stream,v.mVertexId); - - return t+Write(stream,v.mWeight); -} - -// ----------------------------------------------------------------------------------- -// Serialize a mat4x4 -template <> -inline -size_t Write(IOStream * stream, const aiMatrix4x4& m) { - for (unsigned int i = 0; i < 4;++i) { - for (unsigned int i2 = 0; i2 < 4;++i2) { - Write(stream,m[i][i2]); - } - } - - return 64; -} - -// ----------------------------------------------------------------------------------- -// Serialize an aiVectorKey -template <> -inline -size_t Write(IOStream * stream, const aiVectorKey& v) { - const size_t t = Write(stream,v.mTime); - return t + Write(stream,v.mValue); -} - -// ----------------------------------------------------------------------------------- -// Serialize an aiQuatKey -template <> -inline -size_t Write(IOStream * stream, const aiQuatKey& v) { - const size_t t = Write(stream,v.mTime); - return t + Write(stream,v.mValue); -} - -template -inline -size_t WriteBounds(IOStream * stream, const T* in, unsigned int size) { - T minc, maxc; - ArrayBounds(in,size,minc,maxc); - - const size_t t = Write(stream,minc); - return t + Write(stream,maxc); -} - -// We use this to write out non-byte arrays so that we write using the specializations. -// This way we avoid writing out extra bytes that potentially come from struct alignment. -template -inline -size_t WriteArray(IOStream * stream, const T* in, unsigned int size) { - size_t n = 0; - for (unsigned int i=0; i(stream,in[i]); - - return n; -} - -// ---------------------------------------------------------------------------------- -/** @class AssbinChunkWriter - * @brief Chunk writer mechanism for the .assbin file structure - * - * This is a standard in-memory IOStream (most of the code is based on BlobIOStream), - * the difference being that this takes another IOStream as a "container" in the - * constructor, and when it is destroyed, it appends the magic number, the chunk size, - * and the chunk contents to the container stream. This allows relatively easy chunk - * chunk construction, even recursively. - */ -class AssbinChunkWriter : public IOStream -{ -private: - - uint8_t* buffer; - uint32_t magic; - IOStream * container; - size_t cur_size, cursor, initial; - -private: - // ------------------------------------------------------------------- - void Grow(size_t need = 0) - { - size_t new_size = std::max(initial, std::max( need, cur_size+(cur_size>>1) )); - - const uint8_t* const old = buffer; - buffer = new uint8_t[new_size]; - - if (old) { - memcpy(buffer,old,cur_size); - delete[] old; - } - - cur_size = new_size; - } - -public: - - AssbinChunkWriter( IOStream * container, uint32_t magic, size_t initial = 4096) - : buffer(NULL), magic(magic), container(container), cur_size(0), cursor(0), initial(initial) - { - } - - virtual ~AssbinChunkWriter() - { - if (container) { - container->Write( &magic, sizeof(uint32_t), 1 ); - container->Write( &cursor, sizeof(uint32_t), 1 ); - container->Write( buffer, 1, cursor ); - } - if (buffer) delete[] buffer; - } - - void * GetBufferPointer() { return buffer; } - - // ------------------------------------------------------------------- - virtual size_t Read(void* /*pvBuffer*/, size_t /*pSize*/, size_t /*pCount*/) { - return 0; - } - virtual aiReturn Seek(size_t /*pOffset*/, aiOrigin /*pOrigin*/) { - return aiReturn_FAILURE; - } - virtual size_t Tell() const { - return cursor; - } - virtual void Flush() { - // not implemented - } - - virtual size_t FileSize() const { - return cursor; - } - - // ------------------------------------------------------------------- - virtual size_t Write(const void* pvBuffer, size_t pSize, size_t pCount) { - pSize *= pCount; - if (cursor + pSize > cur_size) { - Grow(cursor + pSize); - } - - memcpy(buffer+cursor, pvBuffer, pSize); - cursor += pSize; - - return pCount; - } - -}; - -// ---------------------------------------------------------------------------------- -/** @class AssbinExport - * @brief Assbin exporter class - * - * This class performs the .assbin exporting, and is responsible for the file layout. - */ -class AssbinExport -{ -private: - bool shortened; - bool compressed; - -protected: - // ----------------------------------------------------------------------------------- - void WriteBinaryNode( IOStream * container, const aiNode* node) - { - AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AINODE ); - - unsigned int nb_metadata = (node->mMetaData != NULL ? node->mMetaData->mNumProperties : 0); - - Write(&chunk,node->mName); - Write(&chunk,node->mTransformation); - Write(&chunk,node->mNumChildren); - Write(&chunk,node->mNumMeshes); - Write(&chunk,nb_metadata); - - for (unsigned int i = 0; i < node->mNumMeshes;++i) { - Write(&chunk,node->mMeshes[i]); - } - - for (unsigned int i = 0; i < node->mNumChildren;++i) { - WriteBinaryNode( &chunk, node->mChildren[i] ); - } - - for (unsigned int i = 0; i < nb_metadata; ++i) { - const aiString& key = node->mMetaData->mKeys[i]; - aiMetadataType type = node->mMetaData->mValues[i].mType; - void* value = node->mMetaData->mValues[i].mData; - - Write(&chunk, key); - Write(&chunk, type); - - switch (type) { - case AI_BOOL: - Write(&chunk, *((bool*) value)); - break; - case AI_INT32: - Write(&chunk, *((int32_t*) value)); - break; - case AI_UINT64: - Write(&chunk, *((uint64_t*) value)); - break; - case AI_FLOAT: - Write(&chunk, *((float*) value)); - break; - case AI_DOUBLE: - Write(&chunk, *((double*) value)); - break; - case AI_AISTRING: - Write(&chunk, *((aiString*) value)); - break; - case AI_AIVECTOR3D: - Write(&chunk, *((aiVector3D*) value)); - break; -#ifdef SWIG - case FORCE_32BIT: -#endif // SWIG - default: - break; - } - } - } - - // ----------------------------------------------------------------------------------- - void WriteBinaryTexture(IOStream * container, const aiTexture* tex) - { - AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AITEXTURE ); - - Write(&chunk,tex->mWidth); - Write(&chunk,tex->mHeight); - // Write the texture format, but don't include the null terminator. - chunk.Write( tex->achFormatHint, sizeof(char), HINTMAXTEXTURELEN - 1 ); - - if(!shortened) { - if (!tex->mHeight) { - chunk.Write(tex->pcData,1,tex->mWidth); - } - else { - chunk.Write(tex->pcData,1,tex->mWidth*tex->mHeight*4); - } - } - - } - - // ----------------------------------------------------------------------------------- - void WriteBinaryBone(IOStream * container, const aiBone* b) - { - AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AIBONE ); - - Write(&chunk,b->mName); - Write(&chunk,b->mNumWeights); - Write(&chunk,b->mOffsetMatrix); - - // for the moment we write dumb min/max values for the bones, too. - // maybe I'll add a better, hash-like solution later - if (shortened) { - WriteBounds(&chunk,b->mWeights,b->mNumWeights); - } // else write as usual - else WriteArray(&chunk,b->mWeights,b->mNumWeights); - } - - // ----------------------------------------------------------------------------------- - void WriteBinaryMesh(IOStream * container, const aiMesh* mesh) - { - AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AIMESH ); - - Write(&chunk,mesh->mPrimitiveTypes); - Write(&chunk,mesh->mNumVertices); - Write(&chunk,mesh->mNumFaces); - Write(&chunk,mesh->mNumBones); - Write(&chunk,mesh->mMaterialIndex); - - // first of all, write bits for all existent vertex components - unsigned int c = 0; - if (mesh->mVertices) { - c |= ASSBIN_MESH_HAS_POSITIONS; - } - if (mesh->mNormals) { - c |= ASSBIN_MESH_HAS_NORMALS; - } - if (mesh->mTangents && mesh->mBitangents) { - c |= ASSBIN_MESH_HAS_TANGENTS_AND_BITANGENTS; - } - for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_TEXTURECOORDS;++n) { - if (!mesh->mTextureCoords[n]) { - break; - } - c |= ASSBIN_MESH_HAS_TEXCOORD(n); - } - for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_COLOR_SETS;++n) { - if (!mesh->mColors[n]) { - break; - } - c |= ASSBIN_MESH_HAS_COLOR(n); - } - Write(&chunk,c); - - aiVector3D minVec, maxVec; - if (mesh->mVertices) { - if (shortened) { - WriteBounds(&chunk,mesh->mVertices,mesh->mNumVertices); - } // else write as usual - else WriteArray(&chunk,mesh->mVertices,mesh->mNumVertices); - } - if (mesh->mNormals) { - if (shortened) { - WriteBounds(&chunk,mesh->mNormals,mesh->mNumVertices); - } // else write as usual - else WriteArray(&chunk,mesh->mNormals,mesh->mNumVertices); - } - if (mesh->mTangents && mesh->mBitangents) { - if (shortened) { - WriteBounds(&chunk,mesh->mTangents,mesh->mNumVertices); - WriteBounds(&chunk,mesh->mBitangents,mesh->mNumVertices); - } // else write as usual - else { - WriteArray(&chunk,mesh->mTangents,mesh->mNumVertices); - WriteArray(&chunk,mesh->mBitangents,mesh->mNumVertices); - } - } - for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_COLOR_SETS;++n) { - if (!mesh->mColors[n]) - break; - - if (shortened) { - WriteBounds(&chunk,mesh->mColors[n],mesh->mNumVertices); - } // else write as usual - else WriteArray(&chunk,mesh->mColors[n],mesh->mNumVertices); - } - for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_TEXTURECOORDS;++n) { - if (!mesh->mTextureCoords[n]) - break; - - // write number of UV components - Write(&chunk,mesh->mNumUVComponents[n]); - - if (shortened) { - WriteBounds(&chunk,mesh->mTextureCoords[n],mesh->mNumVertices); - } // else write as usual - else WriteArray(&chunk,mesh->mTextureCoords[n],mesh->mNumVertices); - } - - // write faces. There are no floating-point calculations involved - // in these, so we can write a simple hash over the face data - // to the dump file. We generate a single 32 Bit hash for 512 faces - // using Assimp's standard hashing function. - if (shortened) { - unsigned int processed = 0; - for (unsigned int job;(job = std::min(mesh->mNumFaces-processed,512u));processed += job) { - - uint32_t hash = 0; - for (unsigned int a = 0; a < job;++a) { - - const aiFace& f = mesh->mFaces[processed+a]; - uint32_t tmp = f.mNumIndices; - hash = SuperFastHash(reinterpret_cast(&tmp),sizeof tmp,hash); - for (unsigned int i = 0; i < f.mNumIndices; ++i) { - static_assert(AI_MAX_VERTICES <= 0xffffffff, "AI_MAX_VERTICES <= 0xffffffff"); - tmp = static_cast( f.mIndices[i] ); - hash = SuperFastHash(reinterpret_cast(&tmp),sizeof tmp,hash); - } - } - Write(&chunk,hash); - } - } - else // else write as usual - { - // if there are less than 2^16 vertices, we can simply use 16 bit integers ... - for (unsigned int i = 0; i < mesh->mNumFaces;++i) { - const aiFace& f = mesh->mFaces[i]; - - static_assert(AI_MAX_FACE_INDICES <= 0xffff, "AI_MAX_FACE_INDICES <= 0xffff"); - Write(&chunk,f.mNumIndices); - - for (unsigned int a = 0; a < f.mNumIndices;++a) { - if (mesh->mNumVertices < (1u<<16)) { - Write(&chunk,f.mIndices[a]); - } - else Write(&chunk,f.mIndices[a]); - } - } - } - - // write bones - if (mesh->mNumBones) { - for (unsigned int a = 0; a < mesh->mNumBones;++a) { - const aiBone* b = mesh->mBones[a]; - WriteBinaryBone(&chunk,b); - } - } - } - - // ----------------------------------------------------------------------------------- - void WriteBinaryMaterialProperty(IOStream * container, const aiMaterialProperty* prop) - { - AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AIMATERIALPROPERTY ); - - Write(&chunk,prop->mKey); - Write(&chunk,prop->mSemantic); - Write(&chunk,prop->mIndex); - - Write(&chunk,prop->mDataLength); - Write(&chunk,(unsigned int)prop->mType); - chunk.Write(prop->mData,1,prop->mDataLength); - } - - // ----------------------------------------------------------------------------------- - void WriteBinaryMaterial(IOStream * container, const aiMaterial* mat) - { - AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AIMATERIAL); - - Write(&chunk,mat->mNumProperties); - for (unsigned int i = 0; i < mat->mNumProperties;++i) { - WriteBinaryMaterialProperty( &chunk, mat->mProperties[i]); - } - } - - // ----------------------------------------------------------------------------------- - void WriteBinaryNodeAnim(IOStream * container, const aiNodeAnim* nd) - { - AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AINODEANIM ); - - Write(&chunk,nd->mNodeName); - Write(&chunk,nd->mNumPositionKeys); - Write(&chunk,nd->mNumRotationKeys); - Write(&chunk,nd->mNumScalingKeys); - Write(&chunk,nd->mPreState); - Write(&chunk,nd->mPostState); - - if (nd->mPositionKeys) { - if (shortened) { - WriteBounds(&chunk,nd->mPositionKeys,nd->mNumPositionKeys); - - } // else write as usual - else WriteArray(&chunk,nd->mPositionKeys,nd->mNumPositionKeys); - } - if (nd->mRotationKeys) { - if (shortened) { - WriteBounds(&chunk,nd->mRotationKeys,nd->mNumRotationKeys); - - } // else write as usual - else WriteArray(&chunk,nd->mRotationKeys,nd->mNumRotationKeys); - } - if (nd->mScalingKeys) { - if (shortened) { - WriteBounds(&chunk,nd->mScalingKeys,nd->mNumScalingKeys); - - } // else write as usual - else WriteArray(&chunk,nd->mScalingKeys,nd->mNumScalingKeys); - } - } - - - // ----------------------------------------------------------------------------------- - void WriteBinaryAnim( IOStream * container, const aiAnimation* anim ) - { - AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AIANIMATION ); - - Write(&chunk,anim->mName); - Write(&chunk,anim->mDuration); - Write(&chunk,anim->mTicksPerSecond); - Write(&chunk,anim->mNumChannels); - - for (unsigned int a = 0; a < anim->mNumChannels;++a) { - const aiNodeAnim* nd = anim->mChannels[a]; - WriteBinaryNodeAnim(&chunk,nd); - } - } - - // ----------------------------------------------------------------------------------- - void WriteBinaryLight( IOStream * container, const aiLight* l ) - { - AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AILIGHT ); - - Write(&chunk,l->mName); - Write(&chunk,l->mType); - - if (l->mType != aiLightSource_DIRECTIONAL) { - Write(&chunk,l->mAttenuationConstant); - Write(&chunk,l->mAttenuationLinear); - Write(&chunk,l->mAttenuationQuadratic); - } - - Write(&chunk,l->mColorDiffuse); - Write(&chunk,l->mColorSpecular); - Write(&chunk,l->mColorAmbient); - - if (l->mType == aiLightSource_SPOT) { - Write(&chunk,l->mAngleInnerCone); - Write(&chunk,l->mAngleOuterCone); - } - - } - - // ----------------------------------------------------------------------------------- - void WriteBinaryCamera( IOStream * container, const aiCamera* cam ) - { - AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AICAMERA ); - - Write(&chunk,cam->mName); - Write(&chunk,cam->mPosition); - Write(&chunk,cam->mLookAt); - Write(&chunk,cam->mUp); - Write(&chunk,cam->mHorizontalFOV); - Write(&chunk,cam->mClipPlaneNear); - Write(&chunk,cam->mClipPlaneFar); - Write(&chunk,cam->mAspect); - } - - // ----------------------------------------------------------------------------------- - void WriteBinaryScene( IOStream * container, const aiScene* scene) - { - AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AISCENE ); - - // basic scene information - Write(&chunk,scene->mFlags); - Write(&chunk,scene->mNumMeshes); - Write(&chunk,scene->mNumMaterials); - Write(&chunk,scene->mNumAnimations); - Write(&chunk,scene->mNumTextures); - Write(&chunk,scene->mNumLights); - Write(&chunk,scene->mNumCameras); - - // write node graph - WriteBinaryNode( &chunk, scene->mRootNode ); - - // write all meshes - for (unsigned int i = 0; i < scene->mNumMeshes;++i) { - const aiMesh* mesh = scene->mMeshes[i]; - WriteBinaryMesh( &chunk,mesh); - } - - // write materials - for (unsigned int i = 0; i< scene->mNumMaterials; ++i) { - const aiMaterial* mat = scene->mMaterials[i]; - WriteBinaryMaterial(&chunk,mat); - } - - // write all animations - for (unsigned int i = 0; i < scene->mNumAnimations;++i) { - const aiAnimation* anim = scene->mAnimations[i]; - WriteBinaryAnim(&chunk,anim); - } - - - // write all textures - for (unsigned int i = 0; i < scene->mNumTextures;++i) { - const aiTexture* mesh = scene->mTextures[i]; - WriteBinaryTexture(&chunk,mesh); - } - - // write lights - for (unsigned int i = 0; i < scene->mNumLights;++i) { - const aiLight* l = scene->mLights[i]; - WriteBinaryLight(&chunk,l); - } - - // write cameras - for (unsigned int i = 0; i < scene->mNumCameras;++i) { - const aiCamera* cam = scene->mCameras[i]; - WriteBinaryCamera(&chunk,cam); - } - - } - -public: - AssbinExport() - : shortened(false), compressed(false) // temporary settings until properties are introduced for exporters - { - } - - // ----------------------------------------------------------------------------------- - // Write a binary model dump - void WriteBinaryDump(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene) - { - IOStream * out = pIOSystem->Open( pFile, "wb" ); - if (!out) return; - - time_t tt = time(NULL); -#if _WIN32 - tm* p = gmtime(&tt); -#else - struct tm now; - tm* p = gmtime_r(&tt, &now); -#endif - - // header - char s[64]; - memset( s, 0, 64 ); -#if _MSC_VER >= 1400 - sprintf_s(s,"ASSIMP.binary-dump.%s",asctime(p)); -#else - ai_snprintf(s,64,"ASSIMP.binary-dump.%s",asctime(p)); -#endif - out->Write( s, 44, 1 ); - // == 44 bytes - - Write( out, ASSBIN_VERSION_MAJOR ); - Write( out, ASSBIN_VERSION_MINOR ); - Write( out, aiGetVersionRevision() ); - Write( out, aiGetCompileFlags() ); - Write( out, shortened ); - Write( out, compressed ); - // == 20 bytes - - char buff[256]; - strncpy(buff,pFile,256); - out->Write(buff,sizeof(char),256); - - char cmd[] = "\0"; - strncpy(buff,cmd,128); - out->Write(buff,sizeof(char),128); - - // leave 64 bytes free for future extensions - memset(buff,0xcd,64); - out->Write(buff,sizeof(char),64); - // == 435 bytes - - // ==== total header size: 512 bytes - ai_assert( out->Tell() == ASSBIN_HEADER_LENGTH ); - - // Up to here the data is uncompressed. For compressed files, the rest - // is compressed using standard DEFLATE from zlib. - if (compressed) - { - AssbinChunkWriter uncompressedStream( NULL, 0 ); - WriteBinaryScene( &uncompressedStream, pScene ); - - uLongf uncompressedSize = static_cast(uncompressedStream.Tell()); - uLongf compressedSize = (uLongf)compressBound(uncompressedSize); - uint8_t* compressedBuffer = new uint8_t[ compressedSize ]; - - int res = compress2( compressedBuffer, &compressedSize, (const Bytef*)uncompressedStream.GetBufferPointer(), uncompressedSize, 9 ); - if(res != Z_OK) - { - delete [] compressedBuffer; - pIOSystem->Close(out); - throw DeadlyExportError("Compression failed."); - } - - out->Write( &uncompressedSize, sizeof(uint32_t), 1 ); - out->Write( compressedBuffer, sizeof(char), compressedSize ); - - delete[] compressedBuffer; - } - else - { - WriteBinaryScene( out, pScene ); - } - - pIOSystem->Close( out ); - } -}; - void ExportSceneAssbin(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* /*pProperties*/) { - AssbinExport exporter; - exporter.WriteBinaryDump( pFile, pIOSystem, pScene ); + DumpSceneToAssbin(pFile, pIOSystem, pScene, false, false); } } // end of namespace Assimp diff --git a/code/Assbin/AssbinFileWriter.cpp b/code/Assbin/AssbinFileWriter.cpp new file mode 100644 index 000000000..041bea748 --- /dev/null +++ b/code/Assbin/AssbinFileWriter.cpp @@ -0,0 +1,858 @@ +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2020, 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 AssbinFileWriter.cpp + * @brief Implementation of Assbin file writer. + */ + +#include "AssbinFileWriter.h" + +#include "Common/assbin_chunks.h" +#include "PostProcessing/ProcessHelper.h" + +#include +#include +#include +#include + +#ifdef ASSIMP_BUILD_NO_OWN_ZLIB +# include +#else +# include "../contrib/zlib/zlib.h" +#endif + +#include + +namespace Assimp { + +template +size_t Write(IOStream * stream, const T& v) { + return stream->Write( &v, sizeof(T), 1 ); +} + +// ----------------------------------------------------------------------------------- +// Serialize an aiString +template <> +inline +size_t Write(IOStream * stream, const aiString& s) { + const size_t s2 = (uint32_t)s.length; + stream->Write(&s,4,1); + stream->Write(s.data,s2,1); + + return s2+4; +} + +// ----------------------------------------------------------------------------------- +// Serialize an unsigned int as uint32_t +template <> +inline +size_t Write(IOStream * stream, const unsigned int& w) { + const uint32_t t = (uint32_t)w; + if (w > t) { + // this shouldn't happen, integers in Assimp data structures never exceed 2^32 + throw DeadlyExportError("loss of data due to 64 -> 32 bit integer conversion"); + } + + stream->Write(&t,4,1); + + return 4; +} + +// ----------------------------------------------------------------------------------- +// Serialize an unsigned int as uint16_t +template <> +inline +size_t Write(IOStream * stream, const uint16_t& w) { + static_assert(sizeof(uint16_t)==2, "sizeof(uint16_t)==2"); + stream->Write(&w,2,1); + + return 2; +} + +// ----------------------------------------------------------------------------------- +// Serialize a float +template <> +inline +size_t Write(IOStream * stream, const float& f) { + static_assert(sizeof(float)==4, "sizeof(float)==4"); + stream->Write(&f,4,1); + + return 4; +} + +// ----------------------------------------------------------------------------------- +// Serialize a double +template <> +inline +size_t Write(IOStream * stream, const double& f) { + static_assert(sizeof(double)==8, "sizeof(double)==8"); + stream->Write(&f,8,1); + + return 8; +} + +// ----------------------------------------------------------------------------------- +// Serialize a vec3 +template <> +inline +size_t Write(IOStream * stream, const aiVector3D& v) { + size_t t = Write(stream,v.x); + t += Write(stream,v.y); + t += Write(stream,v.z); + + return t; +} + +// ----------------------------------------------------------------------------------- +// Serialize a color value +template <> +inline +size_t Write(IOStream * stream, const aiColor3D& v) { + size_t t = Write(stream,v.r); + t += Write(stream,v.g); + t += Write(stream,v.b); + + return t; +} + +// ----------------------------------------------------------------------------------- +// Serialize a color value +template <> +inline +size_t Write(IOStream * stream, const aiColor4D& v) { + size_t t = Write(stream,v.r); + t += Write(stream,v.g); + t += Write(stream,v.b); + t += Write(stream,v.a); + + return t; +} + +// ----------------------------------------------------------------------------------- +// Serialize a quaternion +template <> +inline +size_t Write(IOStream * stream, const aiQuaternion& v) { + size_t t = Write(stream,v.w); + t += Write(stream,v.x); + t += Write(stream,v.y); + t += Write(stream,v.z); + ai_assert(t == 16); + + return 16; +} + +// ----------------------------------------------------------------------------------- +// Serialize a vertex weight +template <> +inline +size_t Write(IOStream * stream, const aiVertexWeight& v) { + size_t t = Write(stream,v.mVertexId); + + return t+Write(stream,v.mWeight); +} + +// ----------------------------------------------------------------------------------- +// Serialize a mat4x4 +template <> +inline +size_t Write(IOStream * stream, const aiMatrix4x4& m) { + for (unsigned int i = 0; i < 4;++i) { + for (unsigned int i2 = 0; i2 < 4;++i2) { + Write(stream,m[i][i2]); + } + } + + return 64; +} + +// ----------------------------------------------------------------------------------- +// Serialize an aiVectorKey +template <> +inline +size_t Write(IOStream * stream, const aiVectorKey& v) { + const size_t t = Write(stream,v.mTime); + return t + Write(stream,v.mValue); +} + +// ----------------------------------------------------------------------------------- +// Serialize an aiQuatKey +template <> +inline +size_t Write(IOStream * stream, const aiQuatKey& v) { + const size_t t = Write(stream,v.mTime); + return t + Write(stream,v.mValue); +} + +template +inline +size_t WriteBounds(IOStream * stream, const T* in, unsigned int size) { + T minc, maxc; + ArrayBounds(in,size,minc,maxc); + + const size_t t = Write(stream,minc); + return t + Write(stream,maxc); +} + +// We use this to write out non-byte arrays so that we write using the specializations. +// This way we avoid writing out extra bytes that potentially come from struct alignment. +template +inline +size_t WriteArray(IOStream * stream, const T* in, unsigned int size) { + size_t n = 0; + for (unsigned int i=0; i(stream,in[i]); + + return n; +} + +// ---------------------------------------------------------------------------------- +/** @class AssbinChunkWriter + * @brief Chunk writer mechanism for the .assbin file structure + * + * This is a standard in-memory IOStream (most of the code is based on BlobIOStream), + * the difference being that this takes another IOStream as a "container" in the + * constructor, and when it is destroyed, it appends the magic number, the chunk size, + * and the chunk contents to the container stream. This allows relatively easy chunk + * chunk construction, even recursively. + */ +class AssbinChunkWriter : public IOStream +{ +private: + + uint8_t* buffer; + uint32_t magic; + IOStream * container; + size_t cur_size, cursor, initial; + +private: + // ------------------------------------------------------------------- + void Grow(size_t need = 0) + { + size_t new_size = std::max(initial, std::max( need, cur_size+(cur_size>>1) )); + + const uint8_t* const old = buffer; + buffer = new uint8_t[new_size]; + + if (old) { + memcpy(buffer,old,cur_size); + delete[] old; + } + + cur_size = new_size; + } + +public: + + AssbinChunkWriter( IOStream * container, uint32_t magic, size_t initial = 4096) + : buffer(NULL), magic(magic), container(container), cur_size(0), cursor(0), initial(initial) + { + } + + virtual ~AssbinChunkWriter() + { + if (container) { + container->Write( &magic, sizeof(uint32_t), 1 ); + container->Write( &cursor, sizeof(uint32_t), 1 ); + container->Write( buffer, 1, cursor ); + } + if (buffer) delete[] buffer; + } + + void * GetBufferPointer() { return buffer; } + + // ------------------------------------------------------------------- + virtual size_t Read(void* /*pvBuffer*/, size_t /*pSize*/, size_t /*pCount*/) { + return 0; + } + virtual aiReturn Seek(size_t /*pOffset*/, aiOrigin /*pOrigin*/) { + return aiReturn_FAILURE; + } + virtual size_t Tell() const { + return cursor; + } + virtual void Flush() { + // not implemented + } + + virtual size_t FileSize() const { + return cursor; + } + + // ------------------------------------------------------------------- + virtual size_t Write(const void* pvBuffer, size_t pSize, size_t pCount) { + pSize *= pCount; + if (cursor + pSize > cur_size) { + Grow(cursor + pSize); + } + + memcpy(buffer+cursor, pvBuffer, pSize); + cursor += pSize; + + return pCount; + } + +}; + +// ---------------------------------------------------------------------------------- +/** @class AssbinFileWriter + * @brief Assbin file writer class + * + * This class writes an .assbin file, and is responsible for the file layout. + */ +class AssbinFileWriter +{ +private: + bool shortened; + bool compressed; + +protected: + // ----------------------------------------------------------------------------------- + void WriteBinaryNode( IOStream * container, const aiNode* node) + { + AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AINODE ); + + unsigned int nb_metadata = (node->mMetaData != NULL ? node->mMetaData->mNumProperties : 0); + + Write(&chunk,node->mName); + Write(&chunk,node->mTransformation); + Write(&chunk,node->mNumChildren); + Write(&chunk,node->mNumMeshes); + Write(&chunk,nb_metadata); + + for (unsigned int i = 0; i < node->mNumMeshes;++i) { + Write(&chunk,node->mMeshes[i]); + } + + for (unsigned int i = 0; i < node->mNumChildren;++i) { + WriteBinaryNode( &chunk, node->mChildren[i] ); + } + + for (unsigned int i = 0; i < nb_metadata; ++i) { + const aiString& key = node->mMetaData->mKeys[i]; + aiMetadataType type = node->mMetaData->mValues[i].mType; + void* value = node->mMetaData->mValues[i].mData; + + Write(&chunk, key); + Write(&chunk, type); + + switch (type) { + case AI_BOOL: + Write(&chunk, *((bool*) value)); + break; + case AI_INT32: + Write(&chunk, *((int32_t*) value)); + break; + case AI_UINT64: + Write(&chunk, *((uint64_t*) value)); + break; + case AI_FLOAT: + Write(&chunk, *((float*) value)); + break; + case AI_DOUBLE: + Write(&chunk, *((double*) value)); + break; + case AI_AISTRING: + Write(&chunk, *((aiString*) value)); + break; + case AI_AIVECTOR3D: + Write(&chunk, *((aiVector3D*) value)); + break; +#ifdef SWIG + case FORCE_32BIT: +#endif // SWIG + default: + break; + } + } + } + + // ----------------------------------------------------------------------------------- + void WriteBinaryTexture(IOStream * container, const aiTexture* tex) + { + AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AITEXTURE ); + + Write(&chunk,tex->mWidth); + Write(&chunk,tex->mHeight); + // Write the texture format, but don't include the null terminator. + chunk.Write( tex->achFormatHint, sizeof(char), HINTMAXTEXTURELEN - 1 ); + + if(!shortened) { + if (!tex->mHeight) { + chunk.Write(tex->pcData,1,tex->mWidth); + } + else { + chunk.Write(tex->pcData,1,tex->mWidth*tex->mHeight*4); + } + } + + } + + // ----------------------------------------------------------------------------------- + void WriteBinaryBone(IOStream * container, const aiBone* b) + { + AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AIBONE ); + + Write(&chunk,b->mName); + Write(&chunk,b->mNumWeights); + Write(&chunk,b->mOffsetMatrix); + + // for the moment we write dumb min/max values for the bones, too. + // maybe I'll add a better, hash-like solution later + if (shortened) { + WriteBounds(&chunk,b->mWeights,b->mNumWeights); + } // else write as usual + else WriteArray(&chunk,b->mWeights,b->mNumWeights); + } + + // ----------------------------------------------------------------------------------- + void WriteBinaryMesh(IOStream * container, const aiMesh* mesh) + { + AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AIMESH ); + + Write(&chunk,mesh->mPrimitiveTypes); + Write(&chunk,mesh->mNumVertices); + Write(&chunk,mesh->mNumFaces); + Write(&chunk,mesh->mNumBones); + Write(&chunk,mesh->mMaterialIndex); + + // first of all, write bits for all existent vertex components + unsigned int c = 0; + if (mesh->mVertices) { + c |= ASSBIN_MESH_HAS_POSITIONS; + } + if (mesh->mNormals) { + c |= ASSBIN_MESH_HAS_NORMALS; + } + if (mesh->mTangents && mesh->mBitangents) { + c |= ASSBIN_MESH_HAS_TANGENTS_AND_BITANGENTS; + } + for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_TEXTURECOORDS;++n) { + if (!mesh->mTextureCoords[n]) { + break; + } + c |= ASSBIN_MESH_HAS_TEXCOORD(n); + } + for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_COLOR_SETS;++n) { + if (!mesh->mColors[n]) { + break; + } + c |= ASSBIN_MESH_HAS_COLOR(n); + } + Write(&chunk,c); + + aiVector3D minVec, maxVec; + if (mesh->mVertices) { + if (shortened) { + WriteBounds(&chunk,mesh->mVertices,mesh->mNumVertices); + } // else write as usual + else WriteArray(&chunk,mesh->mVertices,mesh->mNumVertices); + } + if (mesh->mNormals) { + if (shortened) { + WriteBounds(&chunk,mesh->mNormals,mesh->mNumVertices); + } // else write as usual + else WriteArray(&chunk,mesh->mNormals,mesh->mNumVertices); + } + if (mesh->mTangents && mesh->mBitangents) { + if (shortened) { + WriteBounds(&chunk,mesh->mTangents,mesh->mNumVertices); + WriteBounds(&chunk,mesh->mBitangents,mesh->mNumVertices); + } // else write as usual + else { + WriteArray(&chunk,mesh->mTangents,mesh->mNumVertices); + WriteArray(&chunk,mesh->mBitangents,mesh->mNumVertices); + } + } + for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_COLOR_SETS;++n) { + if (!mesh->mColors[n]) + break; + + if (shortened) { + WriteBounds(&chunk,mesh->mColors[n],mesh->mNumVertices); + } // else write as usual + else WriteArray(&chunk,mesh->mColors[n],mesh->mNumVertices); + } + for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_TEXTURECOORDS;++n) { + if (!mesh->mTextureCoords[n]) + break; + + // write number of UV components + Write(&chunk,mesh->mNumUVComponents[n]); + + if (shortened) { + WriteBounds(&chunk,mesh->mTextureCoords[n],mesh->mNumVertices); + } // else write as usual + else WriteArray(&chunk,mesh->mTextureCoords[n],mesh->mNumVertices); + } + + // write faces. There are no floating-point calculations involved + // in these, so we can write a simple hash over the face data + // to the dump file. We generate a single 32 Bit hash for 512 faces + // using Assimp's standard hashing function. + if (shortened) { + unsigned int processed = 0; + for (unsigned int job;(job = std::min(mesh->mNumFaces-processed,512u));processed += job) { + + uint32_t hash = 0; + for (unsigned int a = 0; a < job;++a) { + + const aiFace& f = mesh->mFaces[processed+a]; + uint32_t tmp = f.mNumIndices; + hash = SuperFastHash(reinterpret_cast(&tmp),sizeof tmp,hash); + for (unsigned int i = 0; i < f.mNumIndices; ++i) { + static_assert(AI_MAX_VERTICES <= 0xffffffff, "AI_MAX_VERTICES <= 0xffffffff"); + tmp = static_cast( f.mIndices[i] ); + hash = SuperFastHash(reinterpret_cast(&tmp),sizeof tmp,hash); + } + } + Write(&chunk,hash); + } + } + else // else write as usual + { + // if there are less than 2^16 vertices, we can simply use 16 bit integers ... + for (unsigned int i = 0; i < mesh->mNumFaces;++i) { + const aiFace& f = mesh->mFaces[i]; + + static_assert(AI_MAX_FACE_INDICES <= 0xffff, "AI_MAX_FACE_INDICES <= 0xffff"); + Write(&chunk,f.mNumIndices); + + for (unsigned int a = 0; a < f.mNumIndices;++a) { + if (mesh->mNumVertices < (1u<<16)) { + Write(&chunk,f.mIndices[a]); + } + else Write(&chunk,f.mIndices[a]); + } + } + } + + // write bones + if (mesh->mNumBones) { + for (unsigned int a = 0; a < mesh->mNumBones;++a) { + const aiBone* b = mesh->mBones[a]; + WriteBinaryBone(&chunk,b); + } + } + } + + // ----------------------------------------------------------------------------------- + void WriteBinaryMaterialProperty(IOStream * container, const aiMaterialProperty* prop) + { + AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AIMATERIALPROPERTY ); + + Write(&chunk,prop->mKey); + Write(&chunk,prop->mSemantic); + Write(&chunk,prop->mIndex); + + Write(&chunk,prop->mDataLength); + Write(&chunk,(unsigned int)prop->mType); + chunk.Write(prop->mData,1,prop->mDataLength); + } + + // ----------------------------------------------------------------------------------- + void WriteBinaryMaterial(IOStream * container, const aiMaterial* mat) + { + AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AIMATERIAL); + + Write(&chunk,mat->mNumProperties); + for (unsigned int i = 0; i < mat->mNumProperties;++i) { + WriteBinaryMaterialProperty( &chunk, mat->mProperties[i]); + } + } + + // ----------------------------------------------------------------------------------- + void WriteBinaryNodeAnim(IOStream * container, const aiNodeAnim* nd) + { + AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AINODEANIM ); + + Write(&chunk,nd->mNodeName); + Write(&chunk,nd->mNumPositionKeys); + Write(&chunk,nd->mNumRotationKeys); + Write(&chunk,nd->mNumScalingKeys); + Write(&chunk,nd->mPreState); + Write(&chunk,nd->mPostState); + + if (nd->mPositionKeys) { + if (shortened) { + WriteBounds(&chunk,nd->mPositionKeys,nd->mNumPositionKeys); + + } // else write as usual + else WriteArray(&chunk,nd->mPositionKeys,nd->mNumPositionKeys); + } + if (nd->mRotationKeys) { + if (shortened) { + WriteBounds(&chunk,nd->mRotationKeys,nd->mNumRotationKeys); + + } // else write as usual + else WriteArray(&chunk,nd->mRotationKeys,nd->mNumRotationKeys); + } + if (nd->mScalingKeys) { + if (shortened) { + WriteBounds(&chunk,nd->mScalingKeys,nd->mNumScalingKeys); + + } // else write as usual + else WriteArray(&chunk,nd->mScalingKeys,nd->mNumScalingKeys); + } + } + + + // ----------------------------------------------------------------------------------- + void WriteBinaryAnim( IOStream * container, const aiAnimation* anim ) + { + AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AIANIMATION ); + + Write(&chunk,anim->mName); + Write(&chunk,anim->mDuration); + Write(&chunk,anim->mTicksPerSecond); + Write(&chunk,anim->mNumChannels); + + for (unsigned int a = 0; a < anim->mNumChannels;++a) { + const aiNodeAnim* nd = anim->mChannels[a]; + WriteBinaryNodeAnim(&chunk,nd); + } + } + + // ----------------------------------------------------------------------------------- + void WriteBinaryLight( IOStream * container, const aiLight* l ) + { + AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AILIGHT ); + + Write(&chunk,l->mName); + Write(&chunk,l->mType); + + if (l->mType != aiLightSource_DIRECTIONAL) { + Write(&chunk,l->mAttenuationConstant); + Write(&chunk,l->mAttenuationLinear); + Write(&chunk,l->mAttenuationQuadratic); + } + + Write(&chunk,l->mColorDiffuse); + Write(&chunk,l->mColorSpecular); + Write(&chunk,l->mColorAmbient); + + if (l->mType == aiLightSource_SPOT) { + Write(&chunk,l->mAngleInnerCone); + Write(&chunk,l->mAngleOuterCone); + } + + } + + // ----------------------------------------------------------------------------------- + void WriteBinaryCamera( IOStream * container, const aiCamera* cam ) + { + AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AICAMERA ); + + Write(&chunk,cam->mName); + Write(&chunk,cam->mPosition); + Write(&chunk,cam->mLookAt); + Write(&chunk,cam->mUp); + Write(&chunk,cam->mHorizontalFOV); + Write(&chunk,cam->mClipPlaneNear); + Write(&chunk,cam->mClipPlaneFar); + Write(&chunk,cam->mAspect); + } + + // ----------------------------------------------------------------------------------- + void WriteBinaryScene( IOStream * container, const aiScene* scene) + { + AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AISCENE ); + + // basic scene information + Write(&chunk,scene->mFlags); + Write(&chunk,scene->mNumMeshes); + Write(&chunk,scene->mNumMaterials); + Write(&chunk,scene->mNumAnimations); + Write(&chunk,scene->mNumTextures); + Write(&chunk,scene->mNumLights); + Write(&chunk,scene->mNumCameras); + + // write node graph + WriteBinaryNode( &chunk, scene->mRootNode ); + + // write all meshes + for (unsigned int i = 0; i < scene->mNumMeshes;++i) { + const aiMesh* mesh = scene->mMeshes[i]; + WriteBinaryMesh( &chunk,mesh); + } + + // write materials + for (unsigned int i = 0; i< scene->mNumMaterials; ++i) { + const aiMaterial* mat = scene->mMaterials[i]; + WriteBinaryMaterial(&chunk,mat); + } + + // write all animations + for (unsigned int i = 0; i < scene->mNumAnimations;++i) { + const aiAnimation* anim = scene->mAnimations[i]; + WriteBinaryAnim(&chunk,anim); + } + + + // write all textures + for (unsigned int i = 0; i < scene->mNumTextures;++i) { + const aiTexture* mesh = scene->mTextures[i]; + WriteBinaryTexture(&chunk,mesh); + } + + // write lights + for (unsigned int i = 0; i < scene->mNumLights;++i) { + const aiLight* l = scene->mLights[i]; + WriteBinaryLight(&chunk,l); + } + + // write cameras + for (unsigned int i = 0; i < scene->mNumCameras;++i) { + const aiCamera* cam = scene->mCameras[i]; + WriteBinaryCamera(&chunk,cam); + } + + } + +public: + AssbinFileWriter(bool shortened, bool compressed) + : shortened(shortened), compressed(compressed) + { + } + + // ----------------------------------------------------------------------------------- + // Write a binary model dump + void WriteBinaryDump(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene) + { + IOStream * out = pIOSystem->Open( pFile, "wb" ); + if (!out) + throw std::runtime_error("Unable to open output file " + std::string(pFile) + '\n'); + + auto CloseIOStream = [&]() { + if (out) { + pIOSystem->Close(out); + out = nullptr; // Ensure this is only done once. + } + }; + + try { + time_t tt = time(NULL); +#if _WIN32 + tm* p = gmtime(&tt); +#else + struct tm now; + tm* p = gmtime_r(&tt, &now); +#endif + + // header + char s[64]; + memset(s, 0, 64); +#if _MSC_VER >= 1400 + sprintf_s(s, "ASSIMP.binary-dump.%s", asctime(p)); +#else + ai_snprintf(s, 64, "ASSIMP.binary-dump.%s", asctime(p)); +#endif + out->Write(s, 44, 1); + // == 44 bytes + + Write(out, ASSBIN_VERSION_MAJOR); + Write(out, ASSBIN_VERSION_MINOR); + Write(out, aiGetVersionRevision()); + Write(out, aiGetCompileFlags()); + Write(out, shortened); + Write(out, compressed); + // == 20 bytes + + char buff[256]; + strncpy(buff, pFile, 256); + out->Write(buff, sizeof(char), 256); + + char cmd[] = "\0"; + strncpy(buff, cmd, 128); + out->Write(buff, sizeof(char), 128); + + // leave 64 bytes free for future extensions + memset(buff, 0xcd, 64); + out->Write(buff, sizeof(char), 64); + // == 435 bytes + + // ==== total header size: 512 bytes + ai_assert(out->Tell() == ASSBIN_HEADER_LENGTH); + + // Up to here the data is uncompressed. For compressed files, the rest + // is compressed using standard DEFLATE from zlib. + if (compressed) + { + AssbinChunkWriter uncompressedStream(NULL, 0); + WriteBinaryScene(&uncompressedStream, pScene); + + uLongf uncompressedSize = static_cast(uncompressedStream.Tell()); + uLongf compressedSize = (uLongf)compressBound(uncompressedSize); + uint8_t* compressedBuffer = new uint8_t[compressedSize]; + + int res = compress2(compressedBuffer, &compressedSize, (const Bytef*)uncompressedStream.GetBufferPointer(), uncompressedSize, 9); + if (res != Z_OK) + { + delete[] compressedBuffer; + throw DeadlyExportError("Compression failed."); + } + + out->Write(&uncompressedSize, sizeof(uint32_t), 1); + out->Write(compressedBuffer, sizeof(char), compressedSize); + + delete[] compressedBuffer; + } + else + { + WriteBinaryScene(out, pScene); + } + + CloseIOStream(); + } + catch (...) { + CloseIOStream(); + throw; + } + } +}; + +void DumpSceneToAssbin( + const char* pFile, IOSystem* pIOSystem, + const aiScene* pScene, bool shortened, bool compressed) { + AssbinFileWriter fileWriter(shortened, compressed); + fileWriter.WriteBinaryDump(pFile, pIOSystem, pScene); +} + +} // end of namespace Assimp diff --git a/code/Assbin/AssbinFileWriter.h b/code/Assbin/AssbinFileWriter.h new file mode 100644 index 000000000..1b151af7d --- /dev/null +++ b/code/Assbin/AssbinFileWriter.h @@ -0,0 +1,65 @@ +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2020, 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 AssbinFileWriter.h + * @brief Declaration of Assbin file writer. + */ + +#ifndef AI_ASSBINFILEWRITER_H_INC +#define AI_ASSBINFILEWRITER_H_INC + +#include +#include +#include + +namespace Assimp { + +void ASSIMP_API DumpSceneToAssbin( + const char* pFile, + IOSystem* pIOSystem, + const aiScene* pScene, + bool shortened, + bool compressed); + +} + +#endif // AI_ASSBINFILEWRITER_H_INC diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index 9144b4644..650d5f455 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -331,6 +331,8 @@ ADD_ASSIMP_IMPORTER( ASSBIN ADD_ASSIMP_EXPORTER( ASSBIN Assbin/AssbinExporter.h Assbin/AssbinExporter.cpp + Assbin/AssbinFileWriter.h + Assbin/AssbinFileWriter.cpp ) ADD_ASSIMP_EXPORTER( ASSXML diff --git a/tools/assimp_cmd/Main.h b/tools/assimp_cmd/Main.h index bd070102c..7a6ac942d 100644 --- a/tools/assimp_cmd/Main.h +++ b/tools/assimp_cmd/Main.h @@ -126,6 +126,7 @@ enum AssimpCmdError { UnknownFileFormat, NoFileExtensionSpecified, UnknownFileExtension, + ExceptionWasRaised, // Add new error codes here... diff --git a/tools/assimp_cmd/WriteDumb.cpp b/tools/assimp_cmd/WriteDumb.cpp index f019cfd6e..6990b5b14 100644 --- a/tools/assimp_cmd/WriteDumb.cpp +++ b/tools/assimp_cmd/WriteDumb.cpp @@ -60,679 +60,12 @@ const char* AICMD_MSG_DUMP_HELP = ; #include "Common/assbin_chunks.h" +#include +#include FILE* out = NULL; bool shortened = false; -// ----------------------------------------------------------------------------------- -// Compress a binary dump file (beginning at offset head_size) -void CompressBinaryDump(const char* file, unsigned int head_size) -{ - // for simplicity ... copy the file into memory again and compress it there - FILE* p = fopen(file,"r"); - fseek(p,0,SEEK_END); - const uint32_t size = ftell(p); - fseek(p,0,SEEK_SET); - - if (size uint32_t Write(const T&); - -// ----------------------------------------------------------------------------------- -// Serialize an aiString -template <> -inline uint32_t Write(const aiString& s) -{ - const uint32_t s2 = (uint32_t)s.length; - fwrite(&s,4,1,out); - fwrite(s.data,s2,1,out); - return s2+4; -} - -// ----------------------------------------------------------------------------------- -// Serialize an unsigned int as uint32_t -template <> -inline uint32_t Write(const unsigned int& w) -{ - const uint32_t t = (uint32_t)w; - if (w > t) { - // this shouldn't happen, integers in Assimp data structures never exceed 2^32 - printf("loss of data due to 64 -> 32 bit integer conversion"); - } - - fwrite(&t,4,1,out); - return 4; -} - -// ----------------------------------------------------------------------------------- -// Serialize an unsigned int as uint16_t -template <> -inline uint32_t Write(const uint16_t& w) -{ - fwrite(&w,2,1,out); - return 2; -} - -// ----------------------------------------------------------------------------------- -// Serialize a float -template <> -inline uint32_t Write(const float& f) -{ - static_assert(sizeof(float)==4, "sizeof(float)==4"); - fwrite(&f,4,1,out); - return 4; -} - -// ----------------------------------------------------------------------------------- -// Serialize a double -template <> -inline uint32_t Write(const double& f) -{ - static_assert(sizeof(double)==8, "sizeof(double)==8"); - fwrite(&f,8,1,out); - return 8; -} - -// ----------------------------------------------------------------------------------- -// Serialize a vec3 -template <> -inline uint32_t Write(const aiVector3D& v) -{ - uint32_t t = Write(v.x); - t += Write(v.y); - t += Write(v.z); - return t; -} - -// ----------------------------------------------------------------------------------- -// Serialize a color value -template <> -inline uint32_t Write(const aiColor3D& v) -{ - uint32_t t = Write(v.r); - t += Write(v.g); - t += Write(v.b); - return t; -} - -// ----------------------------------------------------------------------------------- -// Serialize a color value -template <> -inline uint32_t Write(const aiColor4D& v) -{ - uint32_t t = Write(v.r); - t += Write(v.g); - t += Write(v.b); - t += Write(v.a); - return t; -} - -// ----------------------------------------------------------------------------------- -// Serialize a quaternion -template <> -inline uint32_t Write(const aiQuaternion& v) -{ - uint32_t t = Write(v.w); - t += Write(v.x); - t += Write(v.y); - t += Write(v.z); - ai_assert(t == 16); - return 16; -} - - -// ----------------------------------------------------------------------------------- -// Serialize a vertex weight -template <> -inline uint32_t Write(const aiVertexWeight& v) -{ - uint32_t t = Write(v.mVertexId); - return t+Write(v.mWeight); -} - -// ----------------------------------------------------------------------------------- -// Serialize a mat4x4 -template <> -inline uint32_t Write(const aiMatrix4x4& m) -{ - for (unsigned int i = 0; i < 4;++i) { - for (unsigned int i2 = 0; i2 < 4;++i2) { - Write(m[i][i2]); - } - } - return 64; -} - -// ----------------------------------------------------------------------------------- -// Serialize an aiVectorKey -template <> -inline uint32_t Write(const aiVectorKey& v) -{ - const uint32_t t = Write(v.mTime); - return t + Write(v.mValue); -} - -// ----------------------------------------------------------------------------------- -// Serialize an aiQuatKey -template <> -inline uint32_t Write(const aiQuatKey& v) -{ - const uint32_t t = Write(v.mTime); - return t + Write(v.mValue); -} - -// ----------------------------------------------------------------------------------- -// Write the min/max values of an array of Ts to the file -template -inline uint32_t WriteBounds(const T* in, unsigned int size) -{ - T minc,maxc; - Assimp::ArrayBounds(in,size,minc,maxc); - - const uint32_t t = Write(minc); - return t + Write(maxc); -} - - - -// ----------------------------------------------------------------------------------- -void ChangeInteger(uint32_t ofs,uint32_t n) -{ - const uint32_t cur = ftell(out); - int retCode; - retCode = fseek(out, ofs, SEEK_SET); - ai_assert(0 == retCode); - fwrite(&n, 4, 1, out); - retCode = fseek(out, cur, SEEK_SET); - ai_assert(0 == retCode); -} - -// ----------------------------------------------------------------------------------- -uint32_t WriteBinaryNode(const aiNode* node) -{ - uint32_t len = 0, old = WriteMagic(ASSBIN_CHUNK_AINODE); - len += Write(node->mName); - len += Write(node->mTransformation); - len += Write(node->mNumChildren); - len += Write(node->mNumMeshes); - - for (unsigned int i = 0; i < node->mNumMeshes;++i) { - len += Write(node->mMeshes[i]); - } - - for (unsigned int i = 0; i < node->mNumChildren;++i) { - len += WriteBinaryNode(node->mChildren[i])+8; - } - - ChangeInteger(old,len); - return len; -} - -// ----------------------------------------------------------------------------------- -uint32_t WriteBinaryTexture(const aiTexture* tex) -{ - uint32_t len = 0, old = WriteMagic(ASSBIN_CHUNK_AITEXTURE); - - len += Write(tex->mWidth); - len += Write(tex->mHeight); - // Write the texture format, but don't include the null terminator. - len += static_cast(fwrite(tex->achFormatHint,sizeof(char),HINTMAXTEXTURELEN - 1,out)); - - if(!shortened) { - if (!tex->mHeight) { - len += static_cast(fwrite(tex->pcData,1,tex->mWidth,out)); - } - else { - len += static_cast(fwrite(tex->pcData,1,tex->mWidth*tex->mHeight*4,out)); - } - } - - ChangeInteger(old,len); - return len; -} - -// ----------------------------------------------------------------------------------- -uint32_t WriteBinaryBone(const aiBone* b) -{ - uint32_t len = 0, old = WriteMagic(ASSBIN_CHUNK_AIBONE); - - len += Write(b->mName); - len += Write(b->mNumWeights); - len += Write(b->mOffsetMatrix); - - // for the moment we write dumb min/max values for the bones, too. - // maybe I'll add a better, hash-like solution later - if (shortened) { - len += WriteBounds(b->mWeights,b->mNumWeights); - } // else write as usual - else len += static_cast(fwrite(b->mWeights,1,b->mNumWeights*sizeof(aiVertexWeight),out)); - - ChangeInteger(old,len); - return len; -} - -// ----------------------------------------------------------------------------------- -uint32_t WriteBinaryMesh(const aiMesh* mesh) -{ - uint32_t len = 0, old = WriteMagic(ASSBIN_CHUNK_AIMESH); - - len += Write(mesh->mPrimitiveTypes); - len += Write(mesh->mNumVertices); - len += Write(mesh->mNumFaces); - len += Write(mesh->mNumBones); - len += Write(mesh->mMaterialIndex); - - // first of all, write bits for all existent vertex components - unsigned int c = 0; - if (mesh->mVertices) { - c |= ASSBIN_MESH_HAS_POSITIONS; - } - if (mesh->mNormals) { - c |= ASSBIN_MESH_HAS_NORMALS; - } - if (mesh->mTangents && mesh->mBitangents) { - c |= ASSBIN_MESH_HAS_TANGENTS_AND_BITANGENTS; - } - for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_TEXTURECOORDS;++n) { - if (!mesh->mTextureCoords[n]) { - break; - } - c |= ASSBIN_MESH_HAS_TEXCOORD(n); - } - for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_COLOR_SETS;++n) { - if (!mesh->mColors[n]) { - break; - } - c |= ASSBIN_MESH_HAS_COLOR(n); - } - len += Write(c); - - aiVector3D minVec, maxVec; - if (mesh->mVertices) { - if (shortened) { - len += WriteBounds(mesh->mVertices,mesh->mNumVertices); - } // else write as usual - else len += static_cast(fwrite(mesh->mVertices,1,12*mesh->mNumVertices,out)); - } - if (mesh->mNormals) { - if (shortened) { - len += WriteBounds(mesh->mNormals,mesh->mNumVertices); - } // else write as usual - else len += static_cast(fwrite(mesh->mNormals,1,12*mesh->mNumVertices,out)); - } - if (mesh->mTangents && mesh->mBitangents) { - if (shortened) { - len += WriteBounds(mesh->mTangents,mesh->mNumVertices); - len += WriteBounds(mesh->mBitangents,mesh->mNumVertices); - } // else write as usual - else { - len += static_cast(fwrite(mesh->mTangents,1,12*mesh->mNumVertices,out)); - len += static_cast(fwrite(mesh->mBitangents,1,12*mesh->mNumVertices,out)); - } - } - for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_COLOR_SETS;++n) { - if (!mesh->mColors[n]) - break; - - if (shortened) { - len += WriteBounds(mesh->mColors[n],mesh->mNumVertices); - } // else write as usual - else len += static_cast(fwrite(mesh->mColors[n],16*mesh->mNumVertices,1,out)); - } - for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_TEXTURECOORDS;++n) { - if (!mesh->mTextureCoords[n]) - break; - - // write number of UV components - len += Write(mesh->mNumUVComponents[n]); - - if (shortened) { - len += WriteBounds(mesh->mTextureCoords[n],mesh->mNumVertices); - } // else write as usual - else len += static_cast(fwrite(mesh->mTextureCoords[n],12*mesh->mNumVertices,1,out)); - } - - // write faces. There are no floating-point calculations involved - // in these, so we can write a simple hash over the face data - // to the dump file. We generate a single 32 Bit hash for 512 faces - // using Assimp's standard hashing function. - if (shortened) { - unsigned int processed = 0; - for (unsigned int job;(job = std::min(mesh->mNumFaces-processed,512u));processed += job) { - - uint32_t hash = 0; - for (unsigned int a = 0; a < job;++a) { - - const aiFace& f = mesh->mFaces[processed+a]; - uint32_t tmp = f.mNumIndices; - hash = SuperFastHash(reinterpret_cast(&tmp),sizeof tmp,hash); - for (unsigned int i = 0; i < f.mNumIndices; ++i) { - static_assert(AI_MAX_VERTICES <= 0xffffffff, "AI_MAX_VERTICES <= 0xffffffff"); - tmp = static_cast( f.mIndices[i] ); - hash = SuperFastHash(reinterpret_cast(&tmp),sizeof tmp,hash); - } - } - len += Write(hash); - } - } - else // else write as usual - { - // if there are less than 2^16 vertices, we can simply use 16 bit integers ... - for (unsigned int i = 0; i < mesh->mNumFaces;++i) { - const aiFace& f = mesh->mFaces[i]; - - static_assert(AI_MAX_FACE_INDICES <= 0xffff, "AI_MAX_FACE_INDICES <= 0xffff"); - len += Write(f.mNumIndices); - - for (unsigned int a = 0; a < f.mNumIndices;++a) { - if (mesh->mNumVertices < (1u<<16)) { - len += Write(f.mIndices[a]); - } - else len += Write(f.mIndices[a]); - } - } - } - - // write bones - if (mesh->mNumBones) { - for (unsigned int a = 0; a < mesh->mNumBones;++a) { - const aiBone* b = mesh->mBones[a]; - len += WriteBinaryBone(b)+8; - } - } - - ChangeInteger(old,len); - return len; -} - -// ----------------------------------------------------------------------------------- -uint32_t WriteBinaryMaterialProperty(const aiMaterialProperty* prop) -{ - uint32_t len = 0, old = WriteMagic(ASSBIN_CHUNK_AIMATERIALPROPERTY); - - len += Write(prop->mKey); - len += Write(prop->mSemantic); - len += Write(prop->mIndex); - - len += Write(prop->mDataLength); - len += Write((unsigned int)prop->mType); - len += static_cast(fwrite(prop->mData,1,prop->mDataLength,out)); - - ChangeInteger(old,len); - return len; -} - -// ----------------------------------------------------------------------------------- -uint32_t WriteBinaryMaterial(const aiMaterial* mat) -{ - uint32_t len = 0, old = WriteMagic(ASSBIN_CHUNK_AIMATERIAL); - - len += Write(mat->mNumProperties); - for (unsigned int i = 0; i < mat->mNumProperties;++i) { - len += WriteBinaryMaterialProperty(mat->mProperties[i])+8; - } - - ChangeInteger(old,len); - return len; -} - -// ----------------------------------------------------------------------------------- -uint32_t WriteBinaryNodeAnim(const aiNodeAnim* nd) -{ - uint32_t len = 0, old = WriteMagic(ASSBIN_CHUNK_AINODEANIM); - - len += Write(nd->mNodeName); - len += Write(nd->mNumPositionKeys); - len += Write(nd->mNumRotationKeys); - len += Write(nd->mNumScalingKeys); - len += Write(nd->mPreState); - len += Write(nd->mPostState); - - if (nd->mPositionKeys) { - if (shortened) { - len += WriteBounds(nd->mPositionKeys,nd->mNumPositionKeys); - - } // else write as usual - else len += static_cast(fwrite(nd->mPositionKeys,1,nd->mNumPositionKeys*sizeof(aiVectorKey),out)); - } - if (nd->mRotationKeys) { - if (shortened) { - len += WriteBounds(nd->mRotationKeys,nd->mNumRotationKeys); - - } // else write as usual - else len += static_cast(fwrite(nd->mRotationKeys,1,nd->mNumRotationKeys*sizeof(aiQuatKey),out)); - } - if (nd->mScalingKeys) { - if (shortened) { - len += WriteBounds(nd->mScalingKeys,nd->mNumScalingKeys); - - } // else write as usual - else len += static_cast(fwrite(nd->mScalingKeys,1,nd->mNumScalingKeys*sizeof(aiVectorKey),out)); - } - - ChangeInteger(old,len); - return len; -} - - -// ----------------------------------------------------------------------------------- -uint32_t WriteBinaryAnim(const aiAnimation* anim) -{ - uint32_t len = 0, old = WriteMagic(ASSBIN_CHUNK_AIANIMATION); - - len += Write (anim->mName); - len += Write (anim->mDuration); - len += Write (anim->mTicksPerSecond); - len += Write(anim->mNumChannels); - - for (unsigned int a = 0; a < anim->mNumChannels;++a) { - const aiNodeAnim* nd = anim->mChannels[a]; - len += WriteBinaryNodeAnim(nd)+8; - } - - ChangeInteger(old,len); - return len; -} - -// ----------------------------------------------------------------------------------- -uint32_t WriteBinaryLight(const aiLight* l) -{ - uint32_t len = 0, old = WriteMagic(ASSBIN_CHUNK_AILIGHT); - - len += Write(l->mName); - len += Write(l->mType); - - if (l->mType != aiLightSource_DIRECTIONAL) { - len += Write(l->mAttenuationConstant); - len += Write(l->mAttenuationLinear); - len += Write(l->mAttenuationQuadratic); - } - - len += Write(l->mColorDiffuse); - len += Write(l->mColorSpecular); - len += Write(l->mColorAmbient); - - if (l->mType == aiLightSource_SPOT) { - len += Write(l->mAngleInnerCone); - len += Write(l->mAngleOuterCone); - } - - ChangeInteger(old,len); - return len; -} - -// ----------------------------------------------------------------------------------- -uint32_t WriteBinaryCamera(const aiCamera* cam) -{ - uint32_t len = 0, old = WriteMagic(ASSBIN_CHUNK_AICAMERA); - - len += Write(cam->mName); - len += Write(cam->mPosition); - len += Write(cam->mLookAt); - len += Write(cam->mUp); - len += Write(cam->mHorizontalFOV); - len += Write(cam->mClipPlaneNear); - len += Write(cam->mClipPlaneFar); - len += Write(cam->mAspect); - - ChangeInteger(old,len); - return len; -} - -// ----------------------------------------------------------------------------------- -uint32_t WriteBinaryScene(const aiScene* scene) -{ - uint32_t len = 0, old = WriteMagic(ASSBIN_CHUNK_AISCENE); - - // basic scene information - len += Write(scene->mFlags); - len += Write(scene->mNumMeshes); - len += Write(scene->mNumMaterials); - len += Write(scene->mNumAnimations); - len += Write(scene->mNumTextures); - len += Write(scene->mNumLights); - len += Write(scene->mNumCameras); - - // write node graph - len += WriteBinaryNode(scene->mRootNode)+8; - - // write all meshes - for (unsigned int i = 0; i < scene->mNumMeshes;++i) { - const aiMesh* mesh = scene->mMeshes[i]; - len += WriteBinaryMesh(mesh)+8; - } - - // write materials - for (unsigned int i = 0; i< scene->mNumMaterials; ++i) { - const aiMaterial* mat = scene->mMaterials[i]; - len += WriteBinaryMaterial(mat)+8; - } - - // write all animations - for (unsigned int i = 0; i < scene->mNumAnimations;++i) { - const aiAnimation* anim = scene->mAnimations[i]; - len += WriteBinaryAnim(anim)+8; - } - - - // write all textures - for (unsigned int i = 0; i < scene->mNumTextures;++i) { - const aiTexture* mesh = scene->mTextures[i]; - len += WriteBinaryTexture(mesh)+8; - } - - // write lights - for (unsigned int i = 0; i < scene->mNumLights;++i) { - const aiLight* l = scene->mLights[i]; - len += WriteBinaryLight(l)+8; - } - - // write cameras - for (unsigned int i = 0; i < scene->mNumCameras;++i) { - const aiCamera* cam = scene->mCameras[i]; - len += WriteBinaryCamera(cam)+8; - } - - ChangeInteger(old,len); - return len; -} - -// ----------------------------------------------------------------------------------- -// Write a binary model dump -void WriteBinaryDump(const aiScene* scene, FILE* _out, const char* src, const char* cmd, - bool _shortened, bool compressed, ImportData& /*imp*/) -{ - out = _out; - shortened = _shortened; - - time_t tt = time(NULL); -#if _WIN32 - tm* p = gmtime(&tt); -#else - struct tm now; - tm* p = gmtime_r(&tt, &now); -#endif - ai_assert(nullptr != p); - - // header - fprintf(out,"ASSIMP.binary-dump.%s",asctime(p)); - // == 44 bytes - - Write(ASSBIN_VERSION_MAJOR); - Write(ASSBIN_VERSION_MINOR); - Write(aiGetVersionRevision()); - Write(aiGetCompileFlags()); - Write(shortened); - Write(compressed); - // == 20 bytes - - { - char buff[256] = { 0 }; - strncpy(buff,src,256); - buff[255] = 0; - fwrite(buff,256,1,out); - } - - { - char buff[128] = { 0 }; - strncpy(buff,cmd,128); - buff[127] = 0; - fwrite(buff,128,1,out); - } - - // leave 64 bytes free for future extensions - { - char buff[64]; - memset(buff,0xcd,64); - fwrite(buff,64,1,out); - } - // == 435 bytes - - // ==== total header size: 512 bytes - ai_assert(ftell(out)==ASSBIN_HEADER_LENGTH); - - // Up to here the data is uncompressed. For compressed files, the rest - // is compressed using standard DEFLATE from zlib. - WriteBinaryScene(scene); -} - // ----------------------------------------------------------------------------------- // Convert a name to standard XML format void ConvertName(aiString& out, const aiString& in) @@ -1408,21 +741,29 @@ int Assimp_Dump (const char* const* params, unsigned int num) return AssimpCmdError::FailedToLoadInputFile; } - // open the output file and build the dump - FILE* o = ::fopen(out.c_str(),(binary ? "wb" : "wt")); - if (!o) { - printf("assimp dump: Unable to open output file %s\n",out.c_str()); - return AssimpCmdError::FailedToOpenOutputFile; - } - if (binary) { - WriteBinaryDump (scene,o,in.c_str(),cmd.c_str(),shortened,compressed,import); + try { + std::unique_ptr pIOSystem(new DefaultIOSystem()); + DumpSceneToAssbin(out.c_str(), pIOSystem.get(), + scene, shortened, compressed); + } + catch (const std::exception& e) { + printf(("assimp dump: " + std::string(e.what())).c_str()); + return AssimpCmdError::ExceptionWasRaised; + } + catch (...) { + printf("assimp dump: An unknown exception occured.\n"); + return AssimpCmdError::ExceptionWasRaised; + } } - else WriteDump (scene,o,in.c_str(),cmd.c_str(),shortened); - fclose(o); - - if (compressed && binary) { - CompressBinaryDump(out.c_str(),ASSBIN_HEADER_LENGTH); + else { + FILE* o = ::fopen(out.c_str(), "wt"); + if (!o) { + printf("assimp dump: Unable to open output file %s\n",out.c_str()); + return AssimpCmdError::FailedToOpenOutputFile; + } + WriteDump (scene,o,in.c_str(),cmd.c_str(),shortened); + fclose(o); } printf("assimp dump: Wrote output dump %s\n",out.c_str()); From 21edb13ff809194d0cb1ee47489f99dacb219759 Mon Sep 17 00:00:00 2001 From: Marc-Antoine Lortie Date: Tue, 28 Jan 2020 10:55:22 -0500 Subject: [PATCH 010/330] Added missing header for unique_ptr. --- tools/assimp_cmd/WriteDumb.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/assimp_cmd/WriteDumb.cpp b/tools/assimp_cmd/WriteDumb.cpp index 6990b5b14..494efd9b2 100644 --- a/tools/assimp_cmd/WriteDumb.cpp +++ b/tools/assimp_cmd/WriteDumb.cpp @@ -63,6 +63,8 @@ const char* AICMD_MSG_DUMP_HELP = #include #include +#include + FILE* out = NULL; bool shortened = false; From a328c18286aba201bbd66898304c5b4c945cc151 Mon Sep 17 00:00:00 2001 From: Marc-Antoine Lortie Date: Tue, 28 Jan 2020 11:06:17 -0500 Subject: [PATCH 011/330] Fixed "printf format not a literal error" in build. --- tools/assimp_cmd/WriteDumb.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/assimp_cmd/WriteDumb.cpp b/tools/assimp_cmd/WriteDumb.cpp index 494efd9b2..787356c57 100644 --- a/tools/assimp_cmd/WriteDumb.cpp +++ b/tools/assimp_cmd/WriteDumb.cpp @@ -750,7 +750,7 @@ int Assimp_Dump (const char* const* params, unsigned int num) scene, shortened, compressed); } catch (const std::exception& e) { - printf(("assimp dump: " + std::string(e.what())).c_str()); + printf("%s", ("assimp dump: " + std::string(e.what())).c_str()); return AssimpCmdError::ExceptionWasRaised; } catch (...) { From 5f30d4c0f8b551f87c41b2b300ecfa6111b51fc5 Mon Sep 17 00:00:00 2001 From: Marc-Antoine Lortie Date: Tue, 28 Jan 2020 12:30:09 -0500 Subject: [PATCH 012/330] Added missing cmd writting. --- code/Assbin/AssbinExporter.cpp | 8 +++++++- code/Assbin/AssbinFileWriter.cpp | 7 +++---- code/Assbin/AssbinFileWriter.h | 1 + tools/assimp_cmd/WriteDumb.cpp | 2 +- 4 files changed, 12 insertions(+), 6 deletions(-) diff --git a/code/Assbin/AssbinExporter.cpp b/code/Assbin/AssbinExporter.cpp index c748624a7..496b39d49 100644 --- a/code/Assbin/AssbinExporter.cpp +++ b/code/Assbin/AssbinExporter.cpp @@ -55,7 +55,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. namespace Assimp { void ExportSceneAssbin(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* /*pProperties*/) { - DumpSceneToAssbin(pFile, pIOSystem, pScene, false, false); + DumpSceneToAssbin( + pFile, + "\0", // no command(s). + pIOSystem, + pScene, + false, // shortened? + false); // compressed? } } // end of namespace Assimp diff --git a/code/Assbin/AssbinFileWriter.cpp b/code/Assbin/AssbinFileWriter.cpp index 041bea748..daa748f6d 100644 --- a/code/Assbin/AssbinFileWriter.cpp +++ b/code/Assbin/AssbinFileWriter.cpp @@ -754,7 +754,7 @@ public: // ----------------------------------------------------------------------------------- // Write a binary model dump - void WriteBinaryDump(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene) + void WriteBinaryDump(const char* pFile, const char* cmd, IOSystem* pIOSystem, const aiScene* pScene) { IOStream * out = pIOSystem->Open( pFile, "wb" ); if (!out) @@ -799,7 +799,6 @@ public: strncpy(buff, pFile, 256); out->Write(buff, sizeof(char), 256); - char cmd[] = "\0"; strncpy(buff, cmd, 128); out->Write(buff, sizeof(char), 128); @@ -849,10 +848,10 @@ public: }; void DumpSceneToAssbin( - const char* pFile, IOSystem* pIOSystem, + const char* pFile, const char* cmd, IOSystem* pIOSystem, const aiScene* pScene, bool shortened, bool compressed) { AssbinFileWriter fileWriter(shortened, compressed); - fileWriter.WriteBinaryDump(pFile, pIOSystem, pScene); + fileWriter.WriteBinaryDump(pFile, cmd, pIOSystem, pScene); } } // end of namespace Assimp diff --git a/code/Assbin/AssbinFileWriter.h b/code/Assbin/AssbinFileWriter.h index 1b151af7d..25db6db2d 100644 --- a/code/Assbin/AssbinFileWriter.h +++ b/code/Assbin/AssbinFileWriter.h @@ -55,6 +55,7 @@ namespace Assimp { void ASSIMP_API DumpSceneToAssbin( const char* pFile, + const char* cmd, IOSystem* pIOSystem, const aiScene* pScene, bool shortened, diff --git a/tools/assimp_cmd/WriteDumb.cpp b/tools/assimp_cmd/WriteDumb.cpp index 787356c57..1e97b54f2 100644 --- a/tools/assimp_cmd/WriteDumb.cpp +++ b/tools/assimp_cmd/WriteDumb.cpp @@ -746,7 +746,7 @@ int Assimp_Dump (const char* const* params, unsigned int num) if (binary) { try { std::unique_ptr pIOSystem(new DefaultIOSystem()); - DumpSceneToAssbin(out.c_str(), pIOSystem.get(), + DumpSceneToAssbin(out.c_str(), cmd.c_str(), pIOSystem.get(), scene, shortened, compressed); } catch (const std::exception& e) { From dd1a11b58533af01d843edaa73036ad9bde39a8e Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 28 Jan 2020 19:37:38 +0100 Subject: [PATCH 013/330] closes https://github.com/assimp/assimp/issues/1592: make install optional, default enabled. --- CMakeLists.txt | 96 +++++++++++++++++++++++++++----------------------- 1 file changed, 52 insertions(+), 44 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 580ce8ea2..fd3f1b802 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -100,6 +100,10 @@ OPTION ( ASSIMP_COVERALLS "Enable this to measure test coverage." OFF ) +OPTION( ASSIMP_INSTALL + "DIsable this if you want to use assimp as a submodule." + ON +) OPTION ( ASSIMP_ERROR_MAX "Enable all warnings." OFF @@ -601,55 +605,59 @@ ENDIF ( ASSIMP_BUILD_TESTS ) # Generate a pkg-config .pc for the Assimp library. CONFIGURE_FILE( "${PROJECT_SOURCE_DIR}/assimp.pc.in" "${PROJECT_BINARY_DIR}/assimp.pc" @ONLY ) -INSTALL( FILES "${PROJECT_BINARY_DIR}/assimp.pc" DESTINATION ${ASSIMP_LIB_INSTALL_DIR}/pkgconfig/ COMPONENT ${LIBASSIMP-DEV_COMPONENT}) +IF ( ASSIMP_INSTALL ) + INSTALL( FILES "${PROJECT_BINARY_DIR}/assimp.pc" DESTINATION ${ASSIMP_LIB_INSTALL_DIR}/pkgconfig/ COMPONENT ${LIBASSIMP-DEV_COMPONENT}) +ENDIF( ASSIMP_INSTALL ) -IF(CMAKE_CPACK_COMMAND AND UNIX AND ASSIMP_OPT_BUILD_PACKAGES) - # Packing information - SET(CPACK_PACKAGE_NAME "assimp{ASSIMP_VERSION_MAJOR}.{ASSIMP_VERSION_MINOR}") - SET(CPACK_PACKAGE_CONTACT "" CACHE STRING "Package maintainer and PGP signer.") - SET(CPACK_PACKAGE_VENDOR "https://github.com/assimp") - SET(CPACK_PACKAGE_DISPLAY_NAME "Assimp ${ASSIMP_VERSION}") - SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY " - Open Asset Import Library ${ASSIMP_VERSION}") - SET(CPACK_PACKAGE_VERSION "${ASSIMP_VERSION}.${ASSIMP_PACKAGE_VERSION}" ) - SET(CPACK_PACKAGE_VERSION_MAJOR "${ASSIMP_VERSION_MAJOR}") - SET(CPACK_PACKAGE_VERSION_MINOR "${ASSIMP_VERSION_MINOR}") - SET(CPACK_PACKAGE_VERSION_PATCH "${ASSIMP_VERSION_PATCH}") - SET(CPACK_PACKAGE_INSTALL_DIRECTORY "assimp${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}") - SET(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE") +IF ( ASSIMP_INSTALL ) + IF(CMAKE_CPACK_COMMAND AND UNIX AND ASSIMP_OPT_BUILD_PACKAGES) + # Packing information + SET(CPACK_PACKAGE_NAME "assimp{ASSIMP_VERSION_MAJOR}.{ASSIMP_VERSION_MINOR}") + SET(CPACK_PACKAGE_CONTACT "" CACHE STRING "Package maintainer and PGP signer.") + SET(CPACK_PACKAGE_VENDOR "https://github.com/assimp") + SET(CPACK_PACKAGE_DISPLAY_NAME "Assimp ${ASSIMP_VERSION}") + SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY " - Open Asset Import Library ${ASSIMP_VERSION}") + SET(CPACK_PACKAGE_VERSION "${ASSIMP_VERSION}.${ASSIMP_PACKAGE_VERSION}" ) + SET(CPACK_PACKAGE_VERSION_MAJOR "${ASSIMP_VERSION_MAJOR}") + SET(CPACK_PACKAGE_VERSION_MINOR "${ASSIMP_VERSION_MINOR}") + SET(CPACK_PACKAGE_VERSION_PATCH "${ASSIMP_VERSION_PATCH}") + SET(CPACK_PACKAGE_INSTALL_DIRECTORY "assimp${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}") + SET(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE") - STRING(TOUPPER ${LIBASSIMP_COMPONENT} "LIBASSIMP_COMPONENT_UPPER") - STRING(TOUPPER ${LIBASSIMP-DEV_COMPONENT} "LIBASSIMP-DEV_COMPONENT_UPPER") + STRING(TOUPPER ${LIBASSIMP_COMPONENT} "LIBASSIMP_COMPONENT_UPPER") + STRING(TOUPPER ${LIBASSIMP-DEV_COMPONENT} "LIBASSIMP-DEV_COMPONENT_UPPER") - SET(CPACK_COMPONENT_ASSIMP-BIN_DISPLAY_NAME "tools") - SET(CPACK_COMPONENT_ASSIMP-BIN_DEPENDS "${LIBASSIMP_COMPONENT}" ) - SET(CPACK_COMPONENT_${LIBASSIMP_COMPONENT_UPPER}_DISPLAY_NAME "libraries") - SET(CPACK_COMPONENT_${LIBASSIMP-DEV_COMPONENT_UPPER}_DISPLAY_NAME "common headers and installs") - SET(CPACK_COMPONENT_${LIBASSIMP-DEV_COMPONENT_UPPER}_DEPENDS $ "{LIBASSIMP_COMPONENT}" ) - SET(CPACK_COMPONENT_ASSIMP-DEV_DISPLAY_NAME "${CPACK_COMPONENT_${LIBASSIMP-DEV_COMPONENT}_DISPLAY_NAME}" ) - SET(CPACK_COMPONENT_ASSIMP-DEV_DEPENDS "${LIBASSIMP-DEV_COMPONENT}" ) - SET(CPACK_DEBIAN_BUILD_DEPENDS debhelper cmake zlib1g-dev pkg-config) + SET(CPACK_COMPONENT_ASSIMP-BIN_DISPLAY_NAME "tools") + SET(CPACK_COMPONENT_ASSIMP-BIN_DEPENDS "${LIBASSIMP_COMPONENT}" ) + SET(CPACK_COMPONENT_${LIBASSIMP_COMPONENT_UPPER}_DISPLAY_NAME "libraries") + SET(CPACK_COMPONENT_${LIBASSIMP-DEV_COMPONENT_UPPER}_DISPLAY_NAME "common headers and installs") + SET(CPACK_COMPONENT_${LIBASSIMP-DEV_COMPONENT_UPPER}_DEPENDS $ "{LIBASSIMP_COMPONENT}" ) + SET(CPACK_COMPONENT_ASSIMP-DEV_DISPLAY_NAME "${CPACK_COMPONENT_${LIBASSIMP-DEV_COMPONENT}_DISPLAY_NAME}" ) + SET(CPACK_COMPONENT_ASSIMP-DEV_DEPENDS "${LIBASSIMP-DEV_COMPONENT}" ) + SET(CPACK_DEBIAN_BUILD_DEPENDS debhelper cmake zlib1g-dev pkg-config) - # debian - SET(CPACK_DEBIAN_PACKAGE_PRIORITY "optional") - SET(CPACK_DEBIAN_CMAKE_OPTIONS "-DBUILD_ASSIMP_SAMPLES:BOOL=${ASSIMP_BUILD_SAMPLES}") - SET(CPACK_DEBIAN_PACKAGE_SECTION "libs" ) - SET(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_COMPONENTS_ALL}") - SET(CPACK_DEBIAN_PACKAGE_SUGGESTS) - set(cPACK_DEBIAN_PACKAGE_NAME "assimp") - SET(CPACK_DEBIAN_PACKAGE_REMOVE_SOURCE_FILES contrib/gtest contrib/zlib workspaces test doc obj samples packaging) - SET(CPACK_DEBIAN_PACKAGE_SOURCE_COPY svn export --force) - SET(CPACK_DEBIAN_CHANGELOG) - execute_process(COMMAND lsb_release -is - OUTPUT_VARIABLE _lsb_distribution OUTPUT_STRIP_TRAILING_WHITESPACE - RESULT_VARIABLE _lsb_release_failed) - SET(CPACK_DEBIAN_DISTRIBUTION_NAME ${_lsb_distribution} CACHE STRING "Name of the distrubiton") - STRING(TOLOWER ${CPACK_DEBIAN_DISTRIBUTION_NAME} CPACK_DEBIAN_DISTRIBUTION_NAME) - IF( ${CPACK_DEBIAN_DISTRIBUTION_NAME} STREQUAL "ubuntu" ) - SET(CPACK_DEBIAN_DISTRIBUTION_RELEASES lucid maverick natty oneiric precise CACHE STRING "Release code-names of the distrubiton release") + # debian + SET(CPACK_DEBIAN_PACKAGE_PRIORITY "optional") + SET(CPACK_DEBIAN_CMAKE_OPTIONS "-DBUILD_ASSIMP_SAMPLES:BOOL=${ASSIMP_BUILD_SAMPLES}") + SET(CPACK_DEBIAN_PACKAGE_SECTION "libs" ) + SET(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_COMPONENTS_ALL}") + SET(CPACK_DEBIAN_PACKAGE_SUGGESTS) + SET(cPACK_DEBIAN_PACKAGE_NAME "assimp") + SET(CPACK_DEBIAN_PACKAGE_REMOVE_SOURCE_FILES contrib/gtest contrib/zlib workspaces test doc obj samples packaging) + SET(CPACK_DEBIAN_PACKAGE_SOURCE_COPY svn export --force) + SET(CPACK_DEBIAN_CHANGELOG) + execute_process(COMMAND lsb_release -is + OUTPUT_VARIABLE _lsb_distribution OUTPUT_STRIP_TRAILING_WHITESPACE + RESULT_VARIABLE _lsb_release_failed) + SET(CPACK_DEBIAN_DISTRIBUTION_NAME ${_lsb_distribution} CACHE STRING "Name of the distrubiton") + STRING(TOLOWER ${CPACK_DEBIAN_DISTRIBUTION_NAME} CPACK_DEBIAN_DISTRIBUTION_NAME) + IF( ${CPACK_DEBIAN_DISTRIBUTION_NAME} STREQUAL "ubuntu" ) + SET(CPACK_DEBIAN_DISTRIBUTION_RELEASES lucid maverick natty oneiric precise CACHE STRING "Release code-names of the distrubiton release") + ENDIF() + SET(DPUT_HOST "" CACHE STRING "PPA repository to upload the debian sources") + INCLUDE(CPack) + INCLUDE(DebSourcePPA) ENDIF() - SET(DPUT_HOST "" CACHE STRING "PPA repository to upload the debian sources") - INCLUDE(CPack) - INCLUDE(DebSourcePPA) ENDIF() if(WIN32) From 81bc7825d112fdb37461be9414dcb6b1547cf547 Mon Sep 17 00:00:00 2001 From: Marc-Antoine Lortie Date: Tue, 28 Jan 2020 14:02:09 -0500 Subject: [PATCH 014/330] Potentially fixed strncpy warning by Coverity. --- code/Assbin/AssbinFileWriter.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/code/Assbin/AssbinFileWriter.cpp b/code/Assbin/AssbinFileWriter.cpp index daa748f6d..4bc8f7cac 100644 --- a/code/Assbin/AssbinFileWriter.cpp +++ b/code/Assbin/AssbinFileWriter.cpp @@ -795,13 +795,14 @@ public: Write(out, compressed); // == 20 bytes - char buff[256]; - strncpy(buff, pFile, 256); + char buff[256] = {0}; + ai_snprintf(buff, 256, "%s", pFile); out->Write(buff, sizeof(char), 256); - strncpy(buff, cmd, 128); + memset(buff, 0, sizeof(buff)); + ai_snprintf(buff, 128, "%s", cmd); out->Write(buff, sizeof(char), 128); - + // leave 64 bytes free for future extensions memset(buff, 0xcd, 64); out->Write(buff, sizeof(char), 64); From 5860d63efcebdf650aef13757a6ac9b948ed8a8b Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 28 Jan 2020 22:02:29 +0100 Subject: [PATCH 015/330] Update appveyor.yml Disable compilers to improve appveyor build performance --- appveyor.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 299f42df6..4fb79dd69 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -17,10 +17,10 @@ matrix: image: - Visual Studio 2013 - - Visual Studio 2015 - - Visual Studio 2017 + #- Visual Studio 2015 + #- Visual Studio 2017 - Visual Studio 2019 - - MinGW + #- MinGW platform: - Win32 From 194d31002d62aca910687bfda5bc9301203c948b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc?= Date: Wed, 29 Jan 2020 14:04:41 +0100 Subject: [PATCH 016/330] Import/export of embedded texture names for the glTF/glTF2 format --- code/glTF/glTFExporter.cpp | 2 ++ code/glTF/glTFImporter.cpp | 1 + code/glTF2/glTF2Exporter.cpp | 2 ++ code/glTF2/glTF2Importer.cpp | 1 + 4 files changed, 6 insertions(+) diff --git a/code/glTF/glTFExporter.cpp b/code/glTF/glTFExporter.cpp index 3caea7de9..4ebe53c00 100644 --- a/code/glTF/glTFExporter.cpp +++ b/code/glTF/glTFExporter.cpp @@ -352,6 +352,8 @@ void glTFExporter::GetMatColorOrTex(const aiMaterial* mat, glTF::TexProperty& pr if (path[0] == '*') { // embedded aiTexture* tex = mScene->mTextures[atoi(&path[1])]; + + prop.texture->source->name = tex->mFilename.C_Str(); uint8_t* data = reinterpret_cast(tex->pcData); prop.texture->source->SetData(data, tex->mWidth, *mAsset); diff --git a/code/glTF/glTFImporter.cpp b/code/glTF/glTFImporter.cpp index 45c0e42a9..bba48dc30 100644 --- a/code/glTF/glTFImporter.cpp +++ b/code/glTF/glTFImporter.cpp @@ -680,6 +680,7 @@ void glTFImporter::ImportEmbeddedTextures(glTF::Asset& r) size_t length = img.GetDataLength(); void* data = img.StealData(); + tex->mFilename = img.name; tex->mWidth = static_cast(length); tex->mHeight = 0; tex->pcData = reinterpret_cast(data); diff --git a/code/glTF2/glTF2Exporter.cpp b/code/glTF2/glTF2Exporter.cpp index 7a7d581cb..b240a5ea9 100644 --- a/code/glTF2/glTF2Exporter.cpp +++ b/code/glTF2/glTF2Exporter.cpp @@ -351,6 +351,8 @@ void glTF2Exporter::GetMatTex(const aiMaterial* mat, Ref& texture, aiTe if (path[0] == '*') { // embedded aiTexture* tex = mScene->mTextures[atoi(&path[1])]; + + texture->source->name = tex->mFilename.C_Str(); // The asset has its own buffer, see Image::SetData texture->source->SetData(reinterpret_cast (tex->pcData), tex->mWidth, *mAsset); diff --git a/code/glTF2/glTF2Importer.cpp b/code/glTF2/glTF2Importer.cpp index e5052d4d6..af98076a7 100644 --- a/code/glTF2/glTF2Importer.cpp +++ b/code/glTF2/glTF2Importer.cpp @@ -1248,6 +1248,7 @@ void glTF2Importer::ImportEmbeddedTextures(glTF2::Asset &r) { size_t length = img.GetDataLength(); void *data = img.StealData(); + tex->mFilename = img.name; tex->mWidth = static_cast(length); tex->mHeight = 0; tex->pcData = reinterpret_cast(data); From 0d672efa905412ecc5beda33dad2124bd8890480 Mon Sep 17 00:00:00 2001 From: Max Vollmer Date: Wed, 29 Jan 2020 15:04:26 +0000 Subject: [PATCH 017/330] Check input token length before copy --- code/FBX/FBXParser.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/code/FBX/FBXParser.cpp b/code/FBX/FBXParser.cpp index 215ff7484..5486fdcc6 100644 --- a/code/FBX/FBXParser.cpp +++ b/code/FBX/FBXParser.cpp @@ -367,9 +367,12 @@ float ParseTokenAsFloat(const Token& t, const char*& err_out) // first - next in the fbx token stream comes ',', // which fast_atof could interpret as decimal point. #define MAX_FLOAT_LENGTH 31 - char temp[MAX_FLOAT_LENGTH + 1]; const size_t length = static_cast(t.end()-t.begin()); - std::copy(t.begin(),t.end(),temp); + if (length > MAX_FLOAT_LENGTH) + return 0.f; + + char temp[MAX_FLOAT_LENGTH + 1]; + std::copy(t.begin(), t.end(), temp); temp[std::min(static_cast(MAX_FLOAT_LENGTH),length)] = '\0'; return fast_atof(temp); From 9e46fca9a911db010a6be87780073336785efccb Mon Sep 17 00:00:00 2001 From: Max Vollmer Date: Wed, 29 Jan 2020 15:06:48 +0000 Subject: [PATCH 018/330] Added missing checks for tempData and uvIndices sizes in all cases --- code/FBX/FBXMeshGeometry.cpp | 38 ++++++++++++++++++++++++++++++------ 1 file changed, 32 insertions(+), 6 deletions(-) diff --git a/code/FBX/FBXMeshGeometry.cpp b/code/FBX/FBXMeshGeometry.cpp index 70e35ccb3..003f0870c 100644 --- a/code/FBX/FBXMeshGeometry.cpp +++ b/code/FBX/FBXMeshGeometry.cpp @@ -448,6 +448,12 @@ void ResolveVertexDataArray(std::vector& data_out, const Scope& source, std::vector tempData; ParseVectorDataArray(tempData, GetRequiredElement(source, dataElementName)); + if (tempData.size() != vertex_count) { + FBXImporter::LogError(Formatter::format("length of input data unexpected for ByVertice mapping: ") + << tempData.size() << ", expected " << vertex_count); + return; + } + data_out.resize(vertex_count); for (size_t i = 0, e = tempData.size(); i < e; ++i) { @@ -461,10 +467,23 @@ void ResolveVertexDataArray(std::vector& data_out, const Scope& source, std::vector tempData; ParseVectorDataArray(tempData, GetRequiredElement(source, dataElementName)); - data_out.resize(vertex_count); + if (tempData.size() != vertex_count) { + FBXImporter::LogError(Formatter::format("length of input data unexpected for ByVertice mapping: ") + << tempData.size() << ", expected " << vertex_count); + return; + } std::vector uvIndices; ParseVectorDataArray(uvIndices,GetRequiredElement(source,indexDataElementName)); + + if (uvIndices.size() != vertex_count) { + FBXImporter::LogError(Formatter::format("length of input data unexpected for ByVertice mapping: ") + << uvIndices.size() << ", expected " << vertex_count); + return; + } + + data_out.resize(vertex_count); + for (size_t i = 0, e = uvIndices.size(); i < e; ++i) { const unsigned int istart = mapping_offsets[i], iend = istart + mapping_counts[i]; @@ -493,15 +512,22 @@ void ResolveVertexDataArray(std::vector& data_out, const Scope& source, std::vector tempData; ParseVectorDataArray(tempData, GetRequiredElement(source, dataElementName)); - data_out.resize(vertex_count); + if (tempData.size() != vertex_count) { + FBXImporter::LogError(Formatter::format("length of input data unexpected for ByPolygonVertex mapping: ") + << tempData.size() << ", expected " << vertex_count); + return; + } std::vector uvIndices; ParseVectorDataArray(uvIndices,GetRequiredElement(source,indexDataElementName)); - if (uvIndices.size() != vertex_count) { - FBXImporter::LogError("length of input data unexpected for ByPolygonVertex mapping"); - return; - } + if (uvIndices.size() != vertex_count) { + FBXImporter::LogError(Formatter::format("length of input data unexpected for ByPolygonVertex mapping: ") + << uvIndices.size() << ", expected " << vertex_count); + return; + } + + data_out.resize(vertex_count); const T empty; unsigned int next = 0; From ff168d7bc09f14d56e17ec037e3a10ccb49bf7ba Mon Sep 17 00:00:00 2001 From: Marc-Antoine Lortie Date: Wed, 29 Jan 2020 13:44:51 -0500 Subject: [PATCH 019/330] Refactored Assxml exporter and dump xml writer. - Moved AssxmlExporter serialization code in a new file AssxmlFileWriter.cpp/h - Added new files to CMakeLists.txt - Replaced string format specifiers %i by %u to match argument type. - Made a few changes in WriteDumb.cpp to call the new DumpSceneToAssxml function. --- code/Assxml/AssxmlExporter.cpp | 601 +--------------------------- code/Assxml/AssxmlFileWriter.cpp | 664 +++++++++++++++++++++++++++++++ code/Assxml/AssxmlFileWriter.h | 65 +++ code/CMakeLists.txt | 2 + tools/assimp_cmd/WriteDumb.cpp | 594 +-------------------------- 5 files changed, 753 insertions(+), 1173 deletions(-) create mode 100644 code/Assxml/AssxmlFileWriter.cpp create mode 100644 code/Assxml/AssxmlFileWriter.h diff --git a/code/Assxml/AssxmlExporter.cpp b/code/Assxml/AssxmlExporter.cpp index 6ebff3582..720fd5b40 100644 --- a/code/Assxml/AssxmlExporter.cpp +++ b/code/Assxml/AssxmlExporter.cpp @@ -46,607 +46,20 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef ASSIMP_BUILD_NO_EXPORT #ifndef ASSIMP_BUILD_NO_ASSXML_EXPORTER -#include "PostProcessing/ProcessHelper.h" - -#include -#include +#include "AssxmlFileWriter.h" #include #include -#include - -#ifdef ASSIMP_BUILD_NO_OWN_ZLIB -# include -#else -# include -#endif - -#include -#include - -using namespace Assimp; - namespace Assimp { -namespace AssxmlExport { - -// ----------------------------------------------------------------------------------- -static int ioprintf( IOStream * io, const char *format, ... ) { - using namespace std; - if ( nullptr == io ) { - return -1; - } - - static const int Size = 4096; - char sz[ Size ]; - ::memset( sz, '\0', Size ); - va_list va; - va_start( va, format ); - const unsigned int nSize = vsnprintf( sz, Size-1, format, va ); - ai_assert( nSize < Size ); - va_end( va ); - - io->Write( sz, sizeof(char), nSize ); - - return nSize; -} - -// ----------------------------------------------------------------------------------- -// Convert a name to standard XML format -static void ConvertName(aiString& out, const aiString& in) { - out.length = 0; - for (unsigned int i = 0; i < in.length; ++i) { - switch (in.data[i]) { - case '<': - out.Append("<");break; - case '>': - out.Append(">");break; - case '&': - out.Append("&");break; - case '\"': - out.Append(""");break; - case '\'': - out.Append("'");break; - default: - out.data[out.length++] = in.data[i]; - } - } - out.data[out.length] = 0; -} - -// ----------------------------------------------------------------------------------- -// Write a single node as text dump -static void WriteNode(const aiNode* node, IOStream * io, unsigned int depth) { - char prefix[512]; - for (unsigned int i = 0; i < depth;++i) - prefix[i] = '\t'; - prefix[depth] = '\0'; - - const aiMatrix4x4& m = node->mTransformation; - - aiString name; - ConvertName(name,node->mName); - ioprintf(io,"%s \n" - "%s\t \n" - "%s\t\t%0 6f %0 6f %0 6f %0 6f\n" - "%s\t\t%0 6f %0 6f %0 6f %0 6f\n" - "%s\t\t%0 6f %0 6f %0 6f %0 6f\n" - "%s\t\t%0 6f %0 6f %0 6f %0 6f\n" - "%s\t \n", - prefix,name.data,prefix, - prefix,m.a1,m.a2,m.a3,m.a4, - prefix,m.b1,m.b2,m.b3,m.b4, - prefix,m.c1,m.c2,m.c3,m.c4, - prefix,m.d1,m.d2,m.d3,m.d4,prefix); - - if (node->mNumMeshes) { - ioprintf(io, "%s\t\n%s\t", - prefix,node->mNumMeshes,prefix); - - for (unsigned int i = 0; i < node->mNumMeshes;++i) { - ioprintf(io,"%i ",node->mMeshes[i]); - } - ioprintf(io,"\n%s\t\n",prefix); - } - - if (node->mNumChildren) { - ioprintf(io,"%s\t\n", - prefix,node->mNumChildren); - - for (unsigned int i = 0; i < node->mNumChildren;++i) { - WriteNode(node->mChildren[i],io,depth+2); - } - ioprintf(io,"%s\t\n",prefix); - } - ioprintf(io,"%s\n",prefix); -} - - -// ----------------------------------------------------------------------------------- -// Some chuncks of text will need to be encoded for XML -// http://stackoverflow.com/questions/5665231/most-efficient-way-to-escape-xml-html-in-c-string#5665377 -static std::string encodeXML(const std::string& data) { - std::string buffer; - buffer.reserve(data.size()); - for(size_t pos = 0; pos != data.size(); ++pos) { - switch(data[pos]) { - case '&': buffer.append("&"); break; - case '\"': buffer.append("""); break; - case '\'': buffer.append("'"); break; - case '<': buffer.append("<"); break; - case '>': buffer.append(">"); break; - default: buffer.append(&data[pos], 1); break; - } - } - return buffer; -} - -// ----------------------------------------------------------------------------------- -// Write a text model dump -static -void WriteDump(const aiScene* scene, IOStream* io, bool shortened) { - time_t tt = ::time( NULL ); -#if _WIN32 - tm* p = gmtime(&tt); -#else - struct tm now; - tm* p = gmtime_r(&tt, &now); -#endif - ai_assert(nullptr != p); - - // write header - std::string header( - "\n" - "\n\n" - "" - " \n\n" - "\n" - ); - - const unsigned int majorVersion( aiGetVersionMajor() ); - const unsigned int minorVersion( aiGetVersionMinor() ); - const unsigned int rev( aiGetVersionRevision() ); - const char *curtime( asctime( p ) ); - ioprintf( io, header.c_str(), majorVersion, minorVersion, rev, curtime, scene->mFlags, 0 ); - - // write the node graph - WriteNode(scene->mRootNode, io, 0); - -#if 0 - // write cameras - for (unsigned int i = 0; i < scene->mNumCameras;++i) { - aiCamera* cam = scene->mCameras[i]; - ConvertName(name,cam->mName); - - // camera header - ioprintf(io,"\t\n" - "\t\t %0 8f %0 8f %0 8f \n" - "\t\t %0 8f %0 8f %0 8f \n" - "\t\t %0 8f %0 8f %0 8f \n" - "\t\t %f \n" - "\t\t %f \n" - "\t\t %f \n" - "\t\t %f \n" - "\t\n", - name.data, - cam->mUp.x,cam->mUp.y,cam->mUp.z, - cam->mLookAt.x,cam->mLookAt.y,cam->mLookAt.z, - cam->mPosition.x,cam->mPosition.y,cam->mPosition.z, - cam->mHorizontalFOV,cam->mAspect,cam->mClipPlaneNear,cam->mClipPlaneFar,i); - } - - // write lights - for (unsigned int i = 0; i < scene->mNumLights;++i) { - aiLight* l = scene->mLights[i]; - ConvertName(name,l->mName); - - // light header - ioprintf(io,"\t type=\"%s\"\n" - "\t\t %0 8f %0 8f %0 8f \n" - "\t\t %0 8f %0 8f %0 8f \n" - "\t\t %0 8f %0 8f %0 8f \n", - name.data, - (l->mType == aiLightSource_DIRECTIONAL ? "directional" : - (l->mType == aiLightSource_POINT ? "point" : "spot" )), - l->mColorDiffuse.r, l->mColorDiffuse.g, l->mColorDiffuse.b, - l->mColorSpecular.r,l->mColorSpecular.g,l->mColorSpecular.b, - l->mColorAmbient.r, l->mColorAmbient.g, l->mColorAmbient.b); - - if (l->mType != aiLightSource_DIRECTIONAL) { - ioprintf(io, - "\t\t %0 8f %0 8f %0 8f \n" - "\t\t %f \n" - "\t\t %f \n" - "\t\t %f \n", - l->mPosition.x,l->mPosition.y,l->mPosition.z, - l->mAttenuationConstant,l->mAttenuationLinear,l->mAttenuationQuadratic); - } - - if (l->mType != aiLightSource_POINT) { - ioprintf(io, - "\t\t %0 8f %0 8f %0 8f \n", - l->mDirection.x,l->mDirection.y,l->mDirection.z); - } - - if (l->mType == aiLightSource_SPOT) { - ioprintf(io, - "\t\t %f \n" - "\t\t %f \n", - l->mAngleOuterCone,l->mAngleInnerCone); - } - ioprintf(io,"\t\n"); - } -#endif - aiString name; - - // write textures - if (scene->mNumTextures) { - ioprintf(io,"\n",scene->mNumTextures); - for (unsigned int i = 0; i < scene->mNumTextures;++i) { - aiTexture* tex = scene->mTextures[i]; - bool compressed = (tex->mHeight == 0); - - // mesh header - ioprintf(io,"\t \n", - (compressed ? -1 : tex->mWidth),(compressed ? -1 : tex->mHeight), - (compressed ? "true" : "false")); - - if (compressed) { - ioprintf(io,"\t\t \n",tex->mWidth); - - if (!shortened) { - for (unsigned int n = 0; n < tex->mWidth;++n) { - ioprintf(io,"\t\t\t%2x",reinterpret_cast(tex->pcData)[n]); - if (n && !(n % 50)) { - ioprintf(io,"\n"); - } - } - } - } - else if (!shortened){ - ioprintf(io,"\t\t \n",tex->mWidth*tex->mHeight*4); - - // const unsigned int width = (unsigned int)std::log10((double)std::max(tex->mHeight,tex->mWidth))+1; - for (unsigned int y = 0; y < tex->mHeight;++y) { - for (unsigned int x = 0; x < tex->mWidth;++x) { - aiTexel* tx = tex->pcData + y*tex->mWidth+x; - unsigned int r = tx->r,g=tx->g,b=tx->b,a=tx->a; - ioprintf(io,"\t\t\t%2x %2x %2x %2x",r,g,b,a); - - // group by four for readability - if ( 0 == ( x + y*tex->mWidth ) % 4 ) { - ioprintf( io, "\n" ); - } - } - } - } - ioprintf(io,"\t\t\n\t\n"); - } - ioprintf(io,"\n"); - } - - // write materials - if (scene->mNumMaterials) { - ioprintf(io,"\n",scene->mNumMaterials); - for (unsigned int i = 0; i< scene->mNumMaterials; ++i) { - const aiMaterial* mat = scene->mMaterials[i]; - - ioprintf(io,"\t\n"); - ioprintf(io,"\t\t\n",mat->mNumProperties); - for (unsigned int n = 0; n < mat->mNumProperties;++n) { - - const aiMaterialProperty* prop = mat->mProperties[n]; - const char* sz = ""; - if (prop->mType == aiPTI_Float) { - sz = "float"; - } - else if (prop->mType == aiPTI_Integer) { - sz = "integer"; - } - else if (prop->mType == aiPTI_String) { - sz = "string"; - } - else if (prop->mType == aiPTI_Buffer) { - sz = "binary_buffer"; - } - - ioprintf(io,"\t\t\tmKey.data, sz, - ::TextureTypeToString((aiTextureType)prop->mSemantic),prop->mIndex); - - if (prop->mType == aiPTI_Float) { - ioprintf(io," size=\"%i\">\n\t\t\t\t", - static_cast(prop->mDataLength/sizeof(float))); - - for (unsigned int p = 0; p < prop->mDataLength/sizeof(float);++p) { - ioprintf(io,"%f ",*((float*)(prop->mData+p*sizeof(float)))); - } - } - else if (prop->mType == aiPTI_Integer) { - ioprintf(io," size=\"%i\">\n\t\t\t\t", - static_cast(prop->mDataLength/sizeof(int))); - - for (unsigned int p = 0; p < prop->mDataLength/sizeof(int);++p) { - ioprintf(io,"%i ",*((int*)(prop->mData+p*sizeof(int)))); - } - } - else if (prop->mType == aiPTI_Buffer) { - ioprintf(io," size=\"%i\">\n\t\t\t\t", - static_cast(prop->mDataLength)); - - for (unsigned int p = 0; p < prop->mDataLength;++p) { - ioprintf(io,"%2x ",prop->mData[p]); - if (p && 0 == p%30) { - ioprintf(io,"\n\t\t\t\t"); - } - } - } - else if (prop->mType == aiPTI_String) { - ioprintf(io,">\n\t\t\t\t\"%s\"",encodeXML(prop->mData+4).c_str() /* skip length */); - } - ioprintf(io,"\n\t\t\t\n"); - } - ioprintf(io,"\t\t\n"); - ioprintf(io,"\t\n"); - } - ioprintf(io,"\n"); - } - - // write animations - if (scene->mNumAnimations) { - ioprintf(io,"\n",scene->mNumAnimations); - for (unsigned int i = 0; i < scene->mNumAnimations;++i) { - aiAnimation* anim = scene->mAnimations[i]; - - // anim header - ConvertName(name,anim->mName); - ioprintf(io,"\t\n", - name.data, anim->mDuration, anim->mTicksPerSecond); - - // write bone animation channels - if (anim->mNumChannels) { - ioprintf(io,"\t\t\n",anim->mNumChannels); - for (unsigned int n = 0; n < anim->mNumChannels;++n) { - aiNodeAnim* nd = anim->mChannels[n]; - - // node anim header - ConvertName(name,nd->mNodeName); - ioprintf(io,"\t\t\t\n",name.data); - - if (!shortened) { - // write position keys - if (nd->mNumPositionKeys) { - ioprintf(io,"\t\t\t\t\n",nd->mNumPositionKeys); - for (unsigned int a = 0; a < nd->mNumPositionKeys;++a) { - aiVectorKey* vc = nd->mPositionKeys+a; - ioprintf(io,"\t\t\t\t\t\n" - "\t\t\t\t\t\t%0 8f %0 8f %0 8f\n\t\t\t\t\t\n", - vc->mTime,vc->mValue.x,vc->mValue.y,vc->mValue.z); - } - ioprintf(io,"\t\t\t\t\n"); - } - - // write scaling keys - if (nd->mNumScalingKeys) { - ioprintf(io,"\t\t\t\t\n",nd->mNumScalingKeys); - for (unsigned int a = 0; a < nd->mNumScalingKeys;++a) { - aiVectorKey* vc = nd->mScalingKeys+a; - ioprintf(io,"\t\t\t\t\t\n" - "\t\t\t\t\t\t%0 8f %0 8f %0 8f\n\t\t\t\t\t\n", - vc->mTime,vc->mValue.x,vc->mValue.y,vc->mValue.z); - } - ioprintf(io,"\t\t\t\t\n"); - } - - // write rotation keys - if (nd->mNumRotationKeys) { - ioprintf(io,"\t\t\t\t\n",nd->mNumRotationKeys); - for (unsigned int a = 0; a < nd->mNumRotationKeys;++a) { - aiQuatKey* vc = nd->mRotationKeys+a; - ioprintf(io,"\t\t\t\t\t\n" - "\t\t\t\t\t\t%0 8f %0 8f %0 8f %0 8f\n\t\t\t\t\t\n", - vc->mTime,vc->mValue.x,vc->mValue.y,vc->mValue.z,vc->mValue.w); - } - ioprintf(io,"\t\t\t\t\n"); - } - } - ioprintf(io,"\t\t\t\n"); - } - ioprintf(io,"\t\t\n"); - } - ioprintf(io,"\t\n"); - } - ioprintf(io,"\n"); - } - - // write meshes - if (scene->mNumMeshes) { - ioprintf(io,"\n",scene->mNumMeshes); - for (unsigned int i = 0; i < scene->mNumMeshes;++i) { - aiMesh* mesh = scene->mMeshes[i]; - // const unsigned int width = (unsigned int)std::log10((double)mesh->mNumVertices)+1; - - // mesh header - ioprintf(io,"\t\n", - (mesh->mPrimitiveTypes & aiPrimitiveType_POINT ? "points" : ""), - (mesh->mPrimitiveTypes & aiPrimitiveType_LINE ? "lines" : ""), - (mesh->mPrimitiveTypes & aiPrimitiveType_TRIANGLE ? "triangles" : ""), - (mesh->mPrimitiveTypes & aiPrimitiveType_POLYGON ? "polygons" : ""), - mesh->mMaterialIndex); - - // bones - if (mesh->mNumBones) { - ioprintf(io,"\t\t\n",mesh->mNumBones); - - for (unsigned int n = 0; n < mesh->mNumBones;++n) { - aiBone* bone = mesh->mBones[n]; - - ConvertName(name,bone->mName); - // bone header - ioprintf(io,"\t\t\t\n" - "\t\t\t\t \n" - "\t\t\t\t\t%0 6f %0 6f %0 6f %0 6f\n" - "\t\t\t\t\t%0 6f %0 6f %0 6f %0 6f\n" - "\t\t\t\t\t%0 6f %0 6f %0 6f %0 6f\n" - "\t\t\t\t\t%0 6f %0 6f %0 6f %0 6f\n" - "\t\t\t\t \n", - name.data, - bone->mOffsetMatrix.a1,bone->mOffsetMatrix.a2,bone->mOffsetMatrix.a3,bone->mOffsetMatrix.a4, - bone->mOffsetMatrix.b1,bone->mOffsetMatrix.b2,bone->mOffsetMatrix.b3,bone->mOffsetMatrix.b4, - bone->mOffsetMatrix.c1,bone->mOffsetMatrix.c2,bone->mOffsetMatrix.c3,bone->mOffsetMatrix.c4, - bone->mOffsetMatrix.d1,bone->mOffsetMatrix.d2,bone->mOffsetMatrix.d3,bone->mOffsetMatrix.d4); - - if (!shortened && bone->mNumWeights) { - ioprintf(io,"\t\t\t\t\n",bone->mNumWeights); - - // bone weights - for (unsigned int a = 0; a < bone->mNumWeights;++a) { - aiVertexWeight* wght = bone->mWeights+a; - - ioprintf(io,"\t\t\t\t\t\n\t\t\t\t\t\t%f\n\t\t\t\t\t\n", - wght->mVertexId,wght->mWeight); - } - ioprintf(io,"\t\t\t\t\n"); - } - ioprintf(io,"\t\t\t\n"); - } - ioprintf(io,"\t\t\n"); - } - - // faces - if (!shortened && mesh->mNumFaces) { - ioprintf(io,"\t\t\n",mesh->mNumFaces); - for (unsigned int n = 0; n < mesh->mNumFaces; ++n) { - aiFace& f = mesh->mFaces[n]; - ioprintf(io,"\t\t\t\n" - "\t\t\t\t",f.mNumIndices); - - for (unsigned int j = 0; j < f.mNumIndices;++j) - ioprintf(io,"%i ",f.mIndices[j]); - - ioprintf(io,"\n\t\t\t\n"); - } - ioprintf(io,"\t\t\n"); - } - - // vertex positions - if (mesh->HasPositions()) { - ioprintf(io,"\t\t \n",mesh->mNumVertices); - if (!shortened) { - for (unsigned int n = 0; n < mesh->mNumVertices; ++n) { - ioprintf(io,"\t\t%0 8f %0 8f %0 8f\n", - mesh->mVertices[n].x, - mesh->mVertices[n].y, - mesh->mVertices[n].z); - } - } - ioprintf(io,"\t\t\n"); - } - - // vertex normals - if (mesh->HasNormals()) { - ioprintf(io,"\t\t \n",mesh->mNumVertices); - if (!shortened) { - for (unsigned int n = 0; n < mesh->mNumVertices; ++n) { - ioprintf(io,"\t\t%0 8f %0 8f %0 8f\n", - mesh->mNormals[n].x, - mesh->mNormals[n].y, - mesh->mNormals[n].z); - } - } - ioprintf(io,"\t\t\n"); - } - - // vertex tangents and bitangents - if (mesh->HasTangentsAndBitangents()) { - ioprintf(io,"\t\t \n",mesh->mNumVertices); - if (!shortened) { - for (unsigned int n = 0; n < mesh->mNumVertices; ++n) { - ioprintf(io,"\t\t%0 8f %0 8f %0 8f\n", - mesh->mTangents[n].x, - mesh->mTangents[n].y, - mesh->mTangents[n].z); - } - } - ioprintf(io,"\t\t\n"); - - ioprintf(io,"\t\t \n",mesh->mNumVertices); - if (!shortened) { - for (unsigned int n = 0; n < mesh->mNumVertices; ++n) { - ioprintf(io,"\t\t%0 8f %0 8f %0 8f\n", - mesh->mBitangents[n].x, - mesh->mBitangents[n].y, - mesh->mBitangents[n].z); - } - } - ioprintf(io,"\t\t\n"); - } - - // texture coordinates - for (unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a) { - if (!mesh->mTextureCoords[a]) - break; - - ioprintf(io,"\t\t \n",mesh->mNumVertices, - a,mesh->mNumUVComponents[a]); - - if (!shortened) { - if (mesh->mNumUVComponents[a] == 3) { - for (unsigned int n = 0; n < mesh->mNumVertices; ++n) { - ioprintf(io,"\t\t%0 8f %0 8f %0 8f\n", - mesh->mTextureCoords[a][n].x, - mesh->mTextureCoords[a][n].y, - mesh->mTextureCoords[a][n].z); - } - } - else { - for (unsigned int n = 0; n < mesh->mNumVertices; ++n) { - ioprintf(io,"\t\t%0 8f %0 8f\n", - mesh->mTextureCoords[a][n].x, - mesh->mTextureCoords[a][n].y); - } - } - } - ioprintf(io,"\t\t\n"); - } - - // vertex colors - for (unsigned int a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; ++a) { - if (!mesh->mColors[a]) - break; - ioprintf(io,"\t\t \n",mesh->mNumVertices,a); - if (!shortened) { - for (unsigned int n = 0; n < mesh->mNumVertices; ++n) { - ioprintf(io,"\t\t%0 8f %0 8f %0 8f %0 8f\n", - mesh->mColors[a][n].r, - mesh->mColors[a][n].g, - mesh->mColors[a][n].b, - mesh->mColors[a][n].a); - } - } - ioprintf(io,"\t\t\n"); - } - ioprintf(io,"\t\n"); - } - ioprintf(io,"\n"); - } - ioprintf(io,"\n"); -} - -} // end of namespace AssxmlExport - void ExportSceneAssxml(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* /*pProperties*/) { - IOStream * out = pIOSystem->Open( pFile, "wt" ); - if (!out) return; - - bool shortened = false; - AssxmlExport::WriteDump( pScene, out, shortened ); - - pIOSystem->Close( out ); + DumpSceneToAssxml( + pFile, + "\0", // command(s) + pIOSystem, + pScene, + false); // shortened? } } // end of namespace Assimp diff --git a/code/Assxml/AssxmlFileWriter.cpp b/code/Assxml/AssxmlFileWriter.cpp new file mode 100644 index 000000000..0ed59e509 --- /dev/null +++ b/code/Assxml/AssxmlFileWriter.cpp @@ -0,0 +1,664 @@ +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2020, 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 AssxmlFileWriter.cpp + * @brief Implementation of Assxml file writer. + */ + +#include "AssxmlFileWriter.h" + +#include "PostProcessing/ProcessHelper.h" + +#include +#include +#include +#include + +#include + +#ifdef ASSIMP_BUILD_NO_OWN_ZLIB +# include +#else +# include +#endif + +#include +#include +#include + +using namespace Assimp; + +namespace Assimp { + +namespace AssxmlFileWriter { + +// ----------------------------------------------------------------------------------- +static int ioprintf( IOStream * io, const char *format, ... ) { + using namespace std; + if ( nullptr == io ) { + return -1; + } + + static const int Size = 4096; + char sz[ Size ]; + ::memset( sz, '\0', Size ); + va_list va; + va_start( va, format ); + const unsigned int nSize = vsnprintf( sz, Size-1, format, va ); + ai_assert( nSize < Size ); + va_end( va ); + + io->Write( sz, sizeof(char), nSize ); + + return nSize; +} + +// ----------------------------------------------------------------------------------- +// Convert a name to standard XML format +static void ConvertName(aiString& out, const aiString& in) { + out.length = 0; + for (unsigned int i = 0; i < in.length; ++i) { + switch (in.data[i]) { + case '<': + out.Append("<");break; + case '>': + out.Append(">");break; + case '&': + out.Append("&");break; + case '\"': + out.Append(""");break; + case '\'': + out.Append("'");break; + default: + out.data[out.length++] = in.data[i]; + } + } + out.data[out.length] = 0; +} + +// ----------------------------------------------------------------------------------- +// Write a single node as text dump +static void WriteNode(const aiNode* node, IOStream * io, unsigned int depth) { + char prefix[512]; + for (unsigned int i = 0; i < depth;++i) + prefix[i] = '\t'; + prefix[depth] = '\0'; + + const aiMatrix4x4& m = node->mTransformation; + + aiString name; + ConvertName(name,node->mName); + ioprintf(io,"%s \n" + "%s\t \n" + "%s\t\t%0 6f %0 6f %0 6f %0 6f\n" + "%s\t\t%0 6f %0 6f %0 6f %0 6f\n" + "%s\t\t%0 6f %0 6f %0 6f %0 6f\n" + "%s\t\t%0 6f %0 6f %0 6f %0 6f\n" + "%s\t \n", + prefix,name.data,prefix, + prefix,m.a1,m.a2,m.a3,m.a4, + prefix,m.b1,m.b2,m.b3,m.b4, + prefix,m.c1,m.c2,m.c3,m.c4, + prefix,m.d1,m.d2,m.d3,m.d4,prefix); + + if (node->mNumMeshes) { + ioprintf(io, "%s\t\n%s\t", + prefix,node->mNumMeshes,prefix); + + for (unsigned int i = 0; i < node->mNumMeshes;++i) { + ioprintf(io,"%u ",node->mMeshes[i]); + } + ioprintf(io,"\n%s\t\n",prefix); + } + + if (node->mNumChildren) { + ioprintf(io,"%s\t\n", + prefix,node->mNumChildren); + + for (unsigned int i = 0; i < node->mNumChildren;++i) { + WriteNode(node->mChildren[i],io,depth+2); + } + ioprintf(io,"%s\t\n",prefix); + } + ioprintf(io,"%s\n",prefix); +} + + +// ----------------------------------------------------------------------------------- +// Some chuncks of text will need to be encoded for XML +// http://stackoverflow.com/questions/5665231/most-efficient-way-to-escape-xml-html-in-c-string#5665377 +static std::string encodeXML(const std::string& data) { + std::string buffer; + buffer.reserve(data.size()); + for(size_t pos = 0; pos != data.size(); ++pos) { + switch(data[pos]) { + case '&': buffer.append("&"); break; + case '\"': buffer.append("""); break; + case '\'': buffer.append("'"); break; + case '<': buffer.append("<"); break; + case '>': buffer.append(">"); break; + default: buffer.append(&data[pos], 1); break; + } + } + return buffer; +} + +// ----------------------------------------------------------------------------------- +// Write a text model dump +static +void WriteDump(const char* pFile, const char* cmd, const aiScene* scene, IOStream* io, bool shortened) { + time_t tt = ::time( NULL ); +#if _WIN32 + tm* p = gmtime(&tt); +#else + struct tm now; + tm* p = gmtime_r(&tt, &now); +#endif + ai_assert(nullptr != p); + + std::string c = cmd; + std::string::size_type s; + + // https://sourceforge.net/tracker/?func=detail&aid=3167364&group_id=226462&atid=1067632 + // -- not allowed in XML comments + while((s = c.find("--")) != std::string::npos) { + c[s] = '?'; + } + + // write header + std::string header( + "\n" + "\n\n" + "" + " \n\n" + "\n" + ); + + const unsigned int majorVersion( aiGetVersionMajor() ); + const unsigned int minorVersion( aiGetVersionMinor() ); + const unsigned int rev( aiGetVersionRevision() ); + const char *curtime( asctime( p ) ); + ioprintf( io, header.c_str(), majorVersion, minorVersion, rev, pFile, c.c_str(), curtime, scene->mFlags, 0u ); + + // write the node graph + WriteNode(scene->mRootNode, io, 0); + +#if 0 + // write cameras + for (unsigned int i = 0; i < scene->mNumCameras;++i) { + aiCamera* cam = scene->mCameras[i]; + ConvertName(name,cam->mName); + + // camera header + ioprintf(io,"\t\n" + "\t\t %0 8f %0 8f %0 8f \n" + "\t\t %0 8f %0 8f %0 8f \n" + "\t\t %0 8f %0 8f %0 8f \n" + "\t\t %f \n" + "\t\t %f \n" + "\t\t %f \n" + "\t\t %f \n" + "\t\n", + name.data, + cam->mUp.x,cam->mUp.y,cam->mUp.z, + cam->mLookAt.x,cam->mLookAt.y,cam->mLookAt.z, + cam->mPosition.x,cam->mPosition.y,cam->mPosition.z, + cam->mHorizontalFOV,cam->mAspect,cam->mClipPlaneNear,cam->mClipPlaneFar,i); + } + + // write lights + for (unsigned int i = 0; i < scene->mNumLights;++i) { + aiLight* l = scene->mLights[i]; + ConvertName(name,l->mName); + + // light header + ioprintf(io,"\t type=\"%s\"\n" + "\t\t %0 8f %0 8f %0 8f \n" + "\t\t %0 8f %0 8f %0 8f \n" + "\t\t %0 8f %0 8f %0 8f \n", + name.data, + (l->mType == aiLightSource_DIRECTIONAL ? "directional" : + (l->mType == aiLightSource_POINT ? "point" : "spot" )), + l->mColorDiffuse.r, l->mColorDiffuse.g, l->mColorDiffuse.b, + l->mColorSpecular.r,l->mColorSpecular.g,l->mColorSpecular.b, + l->mColorAmbient.r, l->mColorAmbient.g, l->mColorAmbient.b); + + if (l->mType != aiLightSource_DIRECTIONAL) { + ioprintf(io, + "\t\t %0 8f %0 8f %0 8f \n" + "\t\t %f \n" + "\t\t %f \n" + "\t\t %f \n", + l->mPosition.x,l->mPosition.y,l->mPosition.z, + l->mAttenuationConstant,l->mAttenuationLinear,l->mAttenuationQuadratic); + } + + if (l->mType != aiLightSource_POINT) { + ioprintf(io, + "\t\t %0 8f %0 8f %0 8f \n", + l->mDirection.x,l->mDirection.y,l->mDirection.z); + } + + if (l->mType == aiLightSource_SPOT) { + ioprintf(io, + "\t\t %f \n" + "\t\t %f \n", + l->mAngleOuterCone,l->mAngleInnerCone); + } + ioprintf(io,"\t\n"); + } +#endif + aiString name; + + // write textures + if (scene->mNumTextures) { + ioprintf(io,"\n",scene->mNumTextures); + for (unsigned int i = 0; i < scene->mNumTextures;++i) { + aiTexture* tex = scene->mTextures[i]; + bool compressed = (tex->mHeight == 0); + + // mesh header + ioprintf(io,"\t \n", + (compressed ? -1 : tex->mWidth),(compressed ? -1 : tex->mHeight), + (compressed ? "true" : "false")); + + if (compressed) { + ioprintf(io,"\t\t \n",tex->mWidth); + + if (!shortened) { + for (unsigned int n = 0; n < tex->mWidth;++n) { + ioprintf(io,"\t\t\t%2x",reinterpret_cast(tex->pcData)[n]); + if (n && !(n % 50)) { + ioprintf(io,"\n"); + } + } + } + } + else if (!shortened){ + ioprintf(io,"\t\t \n",tex->mWidth*tex->mHeight*4); + + // const unsigned int width = (unsigned int)std::log10((double)std::max(tex->mHeight,tex->mWidth))+1; + for (unsigned int y = 0; y < tex->mHeight;++y) { + for (unsigned int x = 0; x < tex->mWidth;++x) { + aiTexel* tx = tex->pcData + y*tex->mWidth+x; + unsigned int r = tx->r,g=tx->g,b=tx->b,a=tx->a; + ioprintf(io,"\t\t\t%2x %2x %2x %2x",r,g,b,a); + + // group by four for readability + if ( 0 == ( x + y*tex->mWidth ) % 4 ) { + ioprintf( io, "\n" ); + } + } + } + } + ioprintf(io,"\t\t\n\t\n"); + } + ioprintf(io,"\n"); + } + + // write materials + if (scene->mNumMaterials) { + ioprintf(io,"\n",scene->mNumMaterials); + for (unsigned int i = 0; i< scene->mNumMaterials; ++i) { + const aiMaterial* mat = scene->mMaterials[i]; + + ioprintf(io,"\t\n"); + ioprintf(io,"\t\t\n",mat->mNumProperties); + for (unsigned int n = 0; n < mat->mNumProperties;++n) { + + const aiMaterialProperty* prop = mat->mProperties[n]; + const char* sz = ""; + if (prop->mType == aiPTI_Float) { + sz = "float"; + } + else if (prop->mType == aiPTI_Integer) { + sz = "integer"; + } + else if (prop->mType == aiPTI_String) { + sz = "string"; + } + else if (prop->mType == aiPTI_Buffer) { + sz = "binary_buffer"; + } + + ioprintf(io,"\t\t\tmKey.data, sz, + ::TextureTypeToString((aiTextureType)prop->mSemantic),prop->mIndex); + + if (prop->mType == aiPTI_Float) { + ioprintf(io," size=\"%i\">\n\t\t\t\t", + static_cast(prop->mDataLength/sizeof(float))); + + for (unsigned int p = 0; p < prop->mDataLength/sizeof(float);++p) { + ioprintf(io,"%f ",*((float*)(prop->mData+p*sizeof(float)))); + } + } + else if (prop->mType == aiPTI_Integer) { + ioprintf(io," size=\"%i\">\n\t\t\t\t", + static_cast(prop->mDataLength/sizeof(int))); + + for (unsigned int p = 0; p < prop->mDataLength/sizeof(int);++p) { + ioprintf(io,"%i ",*((int*)(prop->mData+p*sizeof(int)))); + } + } + else if (prop->mType == aiPTI_Buffer) { + ioprintf(io," size=\"%i\">\n\t\t\t\t", + static_cast(prop->mDataLength)); + + for (unsigned int p = 0; p < prop->mDataLength;++p) { + ioprintf(io,"%2x ",prop->mData[p]); + if (p && 0 == p%30) { + ioprintf(io,"\n\t\t\t\t"); + } + } + } + else if (prop->mType == aiPTI_String) { + ioprintf(io,">\n\t\t\t\t\"%s\"",encodeXML(prop->mData+4).c_str() /* skip length */); + } + ioprintf(io,"\n\t\t\t\n"); + } + ioprintf(io,"\t\t\n"); + ioprintf(io,"\t\n"); + } + ioprintf(io,"\n"); + } + + // write animations + if (scene->mNumAnimations) { + ioprintf(io,"\n",scene->mNumAnimations); + for (unsigned int i = 0; i < scene->mNumAnimations;++i) { + aiAnimation* anim = scene->mAnimations[i]; + + // anim header + ConvertName(name,anim->mName); + ioprintf(io,"\t\n", + name.data, anim->mDuration, anim->mTicksPerSecond); + + // write bone animation channels + if (anim->mNumChannels) { + ioprintf(io,"\t\t\n",anim->mNumChannels); + for (unsigned int n = 0; n < anim->mNumChannels;++n) { + aiNodeAnim* nd = anim->mChannels[n]; + + // node anim header + ConvertName(name,nd->mNodeName); + ioprintf(io,"\t\t\t\n",name.data); + + if (!shortened) { + // write position keys + if (nd->mNumPositionKeys) { + ioprintf(io,"\t\t\t\t\n",nd->mNumPositionKeys); + for (unsigned int a = 0; a < nd->mNumPositionKeys;++a) { + aiVectorKey* vc = nd->mPositionKeys+a; + ioprintf(io,"\t\t\t\t\t\n" + "\t\t\t\t\t\t%0 8f %0 8f %0 8f\n\t\t\t\t\t\n", + vc->mTime,vc->mValue.x,vc->mValue.y,vc->mValue.z); + } + ioprintf(io,"\t\t\t\t\n"); + } + + // write scaling keys + if (nd->mNumScalingKeys) { + ioprintf(io,"\t\t\t\t\n",nd->mNumScalingKeys); + for (unsigned int a = 0; a < nd->mNumScalingKeys;++a) { + aiVectorKey* vc = nd->mScalingKeys+a; + ioprintf(io,"\t\t\t\t\t\n" + "\t\t\t\t\t\t%0 8f %0 8f %0 8f\n\t\t\t\t\t\n", + vc->mTime,vc->mValue.x,vc->mValue.y,vc->mValue.z); + } + ioprintf(io,"\t\t\t\t\n"); + } + + // write rotation keys + if (nd->mNumRotationKeys) { + ioprintf(io,"\t\t\t\t\n",nd->mNumRotationKeys); + for (unsigned int a = 0; a < nd->mNumRotationKeys;++a) { + aiQuatKey* vc = nd->mRotationKeys+a; + ioprintf(io,"\t\t\t\t\t\n" + "\t\t\t\t\t\t%0 8f %0 8f %0 8f %0 8f\n\t\t\t\t\t\n", + vc->mTime,vc->mValue.x,vc->mValue.y,vc->mValue.z,vc->mValue.w); + } + ioprintf(io,"\t\t\t\t\n"); + } + } + ioprintf(io,"\t\t\t\n"); + } + ioprintf(io,"\t\t\n"); + } + ioprintf(io,"\t\n"); + } + ioprintf(io,"\n"); + } + + // write meshes + if (scene->mNumMeshes) { + ioprintf(io,"\n",scene->mNumMeshes); + for (unsigned int i = 0; i < scene->mNumMeshes;++i) { + aiMesh* mesh = scene->mMeshes[i]; + // const unsigned int width = (unsigned int)std::log10((double)mesh->mNumVertices)+1; + + // mesh header + ioprintf(io,"\t\n", + (mesh->mPrimitiveTypes & aiPrimitiveType_POINT ? "points" : ""), + (mesh->mPrimitiveTypes & aiPrimitiveType_LINE ? "lines" : ""), + (mesh->mPrimitiveTypes & aiPrimitiveType_TRIANGLE ? "triangles" : ""), + (mesh->mPrimitiveTypes & aiPrimitiveType_POLYGON ? "polygons" : ""), + mesh->mMaterialIndex); + + // bones + if (mesh->mNumBones) { + ioprintf(io,"\t\t\n",mesh->mNumBones); + + for (unsigned int n = 0; n < mesh->mNumBones;++n) { + aiBone* bone = mesh->mBones[n]; + + ConvertName(name,bone->mName); + // bone header + ioprintf(io,"\t\t\t\n" + "\t\t\t\t \n" + "\t\t\t\t\t%0 6f %0 6f %0 6f %0 6f\n" + "\t\t\t\t\t%0 6f %0 6f %0 6f %0 6f\n" + "\t\t\t\t\t%0 6f %0 6f %0 6f %0 6f\n" + "\t\t\t\t\t%0 6f %0 6f %0 6f %0 6f\n" + "\t\t\t\t \n", + name.data, + bone->mOffsetMatrix.a1,bone->mOffsetMatrix.a2,bone->mOffsetMatrix.a3,bone->mOffsetMatrix.a4, + bone->mOffsetMatrix.b1,bone->mOffsetMatrix.b2,bone->mOffsetMatrix.b3,bone->mOffsetMatrix.b4, + bone->mOffsetMatrix.c1,bone->mOffsetMatrix.c2,bone->mOffsetMatrix.c3,bone->mOffsetMatrix.c4, + bone->mOffsetMatrix.d1,bone->mOffsetMatrix.d2,bone->mOffsetMatrix.d3,bone->mOffsetMatrix.d4); + + if (!shortened && bone->mNumWeights) { + ioprintf(io,"\t\t\t\t\n",bone->mNumWeights); + + // bone weights + for (unsigned int a = 0; a < bone->mNumWeights;++a) { + aiVertexWeight* wght = bone->mWeights+a; + + ioprintf(io,"\t\t\t\t\t\n\t\t\t\t\t\t%f\n\t\t\t\t\t\n", + wght->mVertexId,wght->mWeight); + } + ioprintf(io,"\t\t\t\t\n"); + } + ioprintf(io,"\t\t\t\n"); + } + ioprintf(io,"\t\t\n"); + } + + // faces + if (!shortened && mesh->mNumFaces) { + ioprintf(io,"\t\t\n",mesh->mNumFaces); + for (unsigned int n = 0; n < mesh->mNumFaces; ++n) { + aiFace& f = mesh->mFaces[n]; + ioprintf(io,"\t\t\t\n" + "\t\t\t\t",f.mNumIndices); + + for (unsigned int j = 0; j < f.mNumIndices;++j) + ioprintf(io,"%u ",f.mIndices[j]); + + ioprintf(io,"\n\t\t\t\n"); + } + ioprintf(io,"\t\t\n"); + } + + // vertex positions + if (mesh->HasPositions()) { + ioprintf(io,"\t\t \n",mesh->mNumVertices); + if (!shortened) { + for (unsigned int n = 0; n < mesh->mNumVertices; ++n) { + ioprintf(io,"\t\t%0 8f %0 8f %0 8f\n", + mesh->mVertices[n].x, + mesh->mVertices[n].y, + mesh->mVertices[n].z); + } + } + ioprintf(io,"\t\t\n"); + } + + // vertex normals + if (mesh->HasNormals()) { + ioprintf(io,"\t\t \n",mesh->mNumVertices); + if (!shortened) { + for (unsigned int n = 0; n < mesh->mNumVertices; ++n) { + ioprintf(io,"\t\t%0 8f %0 8f %0 8f\n", + mesh->mNormals[n].x, + mesh->mNormals[n].y, + mesh->mNormals[n].z); + } + } + ioprintf(io,"\t\t\n"); + } + + // vertex tangents and bitangents + if (mesh->HasTangentsAndBitangents()) { + ioprintf(io,"\t\t \n",mesh->mNumVertices); + if (!shortened) { + for (unsigned int n = 0; n < mesh->mNumVertices; ++n) { + ioprintf(io,"\t\t%0 8f %0 8f %0 8f\n", + mesh->mTangents[n].x, + mesh->mTangents[n].y, + mesh->mTangents[n].z); + } + } + ioprintf(io,"\t\t\n"); + + ioprintf(io,"\t\t \n",mesh->mNumVertices); + if (!shortened) { + for (unsigned int n = 0; n < mesh->mNumVertices; ++n) { + ioprintf(io,"\t\t%0 8f %0 8f %0 8f\n", + mesh->mBitangents[n].x, + mesh->mBitangents[n].y, + mesh->mBitangents[n].z); + } + } + ioprintf(io,"\t\t\n"); + } + + // texture coordinates + for (unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a) { + if (!mesh->mTextureCoords[a]) + break; + + ioprintf(io,"\t\t \n",mesh->mNumVertices, + a,mesh->mNumUVComponents[a]); + + if (!shortened) { + if (mesh->mNumUVComponents[a] == 3) { + for (unsigned int n = 0; n < mesh->mNumVertices; ++n) { + ioprintf(io,"\t\t%0 8f %0 8f %0 8f\n", + mesh->mTextureCoords[a][n].x, + mesh->mTextureCoords[a][n].y, + mesh->mTextureCoords[a][n].z); + } + } + else { + for (unsigned int n = 0; n < mesh->mNumVertices; ++n) { + ioprintf(io,"\t\t%0 8f %0 8f\n", + mesh->mTextureCoords[a][n].x, + mesh->mTextureCoords[a][n].y); + } + } + } + ioprintf(io,"\t\t\n"); + } + + // vertex colors + for (unsigned int a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; ++a) { + if (!mesh->mColors[a]) + break; + ioprintf(io,"\t\t \n",mesh->mNumVertices,a); + if (!shortened) { + for (unsigned int n = 0; n < mesh->mNumVertices; ++n) { + ioprintf(io,"\t\t%0 8f %0 8f %0 8f %0 8f\n", + mesh->mColors[a][n].r, + mesh->mColors[a][n].g, + mesh->mColors[a][n].b, + mesh->mColors[a][n].a); + } + } + ioprintf(io,"\t\t\n"); + } + ioprintf(io,"\t\n"); + } + ioprintf(io,"\n"); + } + ioprintf(io,"\n"); +} + +} // end of namespace AssxmlFileWriter + +void DumpSceneToAssxml( + const char* pFile, const char* cmd, IOSystem* pIOSystem, + const aiScene* pScene, bool shortened) { + std::unique_ptr file(pIOSystem->Open(pFile, "wt")); + if (!file.get()) { + throw std::runtime_error("Unable to open output file " + std::string(pFile) + '\n'); + } + + AssxmlFileWriter::WriteDump(pFile, cmd, pScene, file.get(), shortened); +} + +} // end of namespace Assimp diff --git a/code/Assxml/AssxmlFileWriter.h b/code/Assxml/AssxmlFileWriter.h new file mode 100644 index 000000000..c10a8a5aa --- /dev/null +++ b/code/Assxml/AssxmlFileWriter.h @@ -0,0 +1,65 @@ +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2020, 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 AssxmlFileWriter.h + * @brief Declaration of Assxml file writer. + */ + +#ifndef AI_ASSXMLFILEWRITER_H_INC +#define AI_ASSXMLFILEWRITER_H_INC + +#include +#include +#include + +namespace Assimp { + +void ASSIMP_API DumpSceneToAssxml( + const char* pFile, + const char* cmd, + IOSystem* pIOSystem, + const aiScene* pScene, + bool shortened); + +} + +#endif // AI_ASSXMLFILEWRITER_H_INC diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index 650d5f455..5278509e8 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -338,6 +338,8 @@ ADD_ASSIMP_EXPORTER( ASSBIN ADD_ASSIMP_EXPORTER( ASSXML Assxml/AssxmlExporter.h Assxml/AssxmlExporter.cpp + Assxml/AssxmlFileWriter.h + Assxml/AssxmlFileWriter.cpp ) ADD_ASSIMP_IMPORTER( B3D diff --git a/tools/assimp_cmd/WriteDumb.cpp b/tools/assimp_cmd/WriteDumb.cpp index 1e97b54f2..0403f3966 100644 --- a/tools/assimp_cmd/WriteDumb.cpp +++ b/tools/assimp_cmd/WriteDumb.cpp @@ -62,85 +62,13 @@ const char* AICMD_MSG_DUMP_HELP = #include "Common/assbin_chunks.h" #include #include +#include #include FILE* out = NULL; bool shortened = false; -// ----------------------------------------------------------------------------------- -// Convert a name to standard XML format -void ConvertName(aiString& out, const aiString& in) -{ - out.length = 0; - for (unsigned int i = 0; i < in.length; ++i) { - switch (in.data[i]) { - case '<': - out.Append("<");break; - case '>': - out.Append(">");break; - case '&': - out.Append("&");break; - case '\"': - out.Append(""");break; - case '\'': - out.Append("'");break; - default: - out.data[out.length++] = in.data[i]; - } - } - out.data[out.length] = 0; -} - -// ----------------------------------------------------------------------------------- -// Write a single node as text dump -void WriteNode(const aiNode* node, FILE* out, unsigned int depth) -{ - char prefix[512]; - for (unsigned int i = 0; i < depth;++i) - prefix[i] = '\t'; - prefix[depth] = '\0'; - - const aiMatrix4x4& m = node->mTransformation; - - aiString name; - ConvertName(name,node->mName); - fprintf(out,"%s \n" - "%s\t \n" - "%s\t\t%0 6f %0 6f %0 6f %0 6f\n" - "%s\t\t%0 6f %0 6f %0 6f %0 6f\n" - "%s\t\t%0 6f %0 6f %0 6f %0 6f\n" - "%s\t\t%0 6f %0 6f %0 6f %0 6f\n" - "%s\t \n", - prefix,name.data,prefix, - prefix,m.a1,m.a2,m.a3,m.a4, - prefix,m.b1,m.b2,m.b3,m.b4, - prefix,m.c1,m.c2,m.c3,m.c4, - prefix,m.d1,m.d2,m.d3,m.d4,prefix); - - if (node->mNumMeshes) { - fprintf(out, "%s\t\n%s\t", - prefix,node->mNumMeshes,prefix); - - for (unsigned int i = 0; i < node->mNumMeshes;++i) { - fprintf(out,"%u ",node->mMeshes[i]); - } - fprintf(out,"\n%s\t\n",prefix); - } - - if (node->mNumChildren) { - fprintf(out,"%s\t\n", - prefix,node->mNumChildren); - - for (unsigned int i = 0; i < node->mNumChildren;++i) { - WriteNode(node->mChildren[i],out,depth+2); - } - fprintf(out,"%s\t\n",prefix); - } - fprintf(out,"%s\n",prefix); -} - - // ------------------------------------------------------------------------------- const char* TextureTypeToString(aiTextureType in) { @@ -179,494 +107,6 @@ const char* TextureTypeToString(aiTextureType in) return "BUG"; } - -// ----------------------------------------------------------------------------------- -// Some chuncks of text will need to be encoded for XML -// http://stackoverflow.com/questions/5665231/most-efficient-way-to-escape-xml-html-in-c-string#5665377 -static std::string encodeXML(const std::string& data) { - std::string buffer; - buffer.reserve(data.size()); - for(size_t pos = 0; pos != data.size(); ++pos) { - switch(data[pos]) { - case '&': buffer.append("&"); break; - case '\"': buffer.append("""); break; - case '\'': buffer.append("'"); break; - case '<': buffer.append("<"); break; - case '>': buffer.append(">"); break; - default: buffer.append(&data[pos], 1); break; - } - } - return buffer; -} - - - -// ----------------------------------------------------------------------------------- -// Write a text model dump -void WriteDump(const aiScene* scene, FILE* out, const char* src, const char* cmd, bool shortened) -{ - time_t tt = ::time(NULL); -#if _WIN32 - tm* p = gmtime(&tt); -#else - struct tm now; - tm* p = gmtime_r(&tt, &now); -#endif - ai_assert(nullptr != p); - - std::string c = cmd; - std::string::size_type s; - - // https://sourceforge.net/tracker/?func=detail&aid=3167364&group_id=226462&atid=1067632 - // -- not allowed in XML comments - while((s = c.find("--")) != std::string::npos) { - c[s] = '?'; - } - aiString name; - - // write header - fprintf(out, - "\n" - "\n\n" - - "" - " \n\n" - "\n", - - aiGetVersionMajor(),aiGetVersionMinor(),aiGetVersionRevision(),src,c.c_str(),asctime(p), - scene->mFlags, - 0 /*globalImporter->GetEffectivePostProcessing()*/); - - // write the node graph - WriteNode(scene->mRootNode, out, 0); - -#if 0 - // write cameras - for (unsigned int i = 0; i < scene->mNumCameras;++i) { - aiCamera* cam = scene->mCameras[i]; - ConvertName(name,cam->mName); - - // camera header - fprintf(out,"\t\n" - "\t\t %0 8f %0 8f %0 8f \n" - "\t\t %0 8f %0 8f %0 8f \n" - "\t\t %0 8f %0 8f %0 8f \n" - "\t\t %f \n" - "\t\t %f \n" - "\t\t %f \n" - "\t\t %f \n" - "\t\n", - name.data, - cam->mUp.x,cam->mUp.y,cam->mUp.z, - cam->mLookAt.x,cam->mLookAt.y,cam->mLookAt.z, - cam->mPosition.x,cam->mPosition.y,cam->mPosition.z, - cam->mHorizontalFOV,cam->mAspect,cam->mClipPlaneNear,cam->mClipPlaneFar,i); - } - - // write lights - for (unsigned int i = 0; i < scene->mNumLights;++i) { - aiLight* l = scene->mLights[i]; - ConvertName(name,l->mName); - - // light header - fprintf(out,"\t type=\"%s\"\n" - "\t\t %0 8f %0 8f %0 8f \n" - "\t\t %0 8f %0 8f %0 8f \n" - "\t\t %0 8f %0 8f %0 8f \n", - name.data, - (l->mType == aiLightSource_DIRECTIONAL ? "directional" : - (l->mType == aiLightSource_POINT ? "point" : "spot" )), - l->mColorDiffuse.r, l->mColorDiffuse.g, l->mColorDiffuse.b, - l->mColorSpecular.r,l->mColorSpecular.g,l->mColorSpecular.b, - l->mColorAmbient.r, l->mColorAmbient.g, l->mColorAmbient.b); - - if (l->mType != aiLightSource_DIRECTIONAL) { - fprintf(out, - "\t\t %0 8f %0 8f %0 8f \n" - "\t\t %f \n" - "\t\t %f \n" - "\t\t %f \n", - l->mPosition.x,l->mPosition.y,l->mPosition.z, - l->mAttenuationConstant,l->mAttenuationLinear,l->mAttenuationQuadratic); - } - - if (l->mType != aiLightSource_POINT) { - fprintf(out, - "\t\t %0 8f %0 8f %0 8f \n", - l->mDirection.x,l->mDirection.y,l->mDirection.z); - } - - if (l->mType == aiLightSource_SPOT) { - fprintf(out, - "\t\t %f \n" - "\t\t %f \n", - l->mAngleOuterCone,l->mAngleInnerCone); - } - fprintf(out,"\t\n"); - } -#endif - - // write textures - if (scene->mNumTextures) { - fprintf(out,"\n",scene->mNumTextures); - for (unsigned int i = 0; i < scene->mNumTextures;++i) { - aiTexture* tex = scene->mTextures[i]; - bool compressed = (tex->mHeight == 0); - - // mesh header - fprintf(out,"\t \n", - (compressed ? -1 : tex->mWidth),(compressed ? -1 : tex->mHeight), - (compressed ? "true" : "false")); - - if (compressed) { - fprintf(out,"\t\t \n",tex->mWidth); - - if (!shortened) { - for (unsigned int n = 0; n < tex->mWidth;++n) { - fprintf(out,"\t\t\t%2x",reinterpret_cast(tex->pcData)[n]); - if (n && !(n % 50)) { - fprintf(out,"\n"); - } - } - } - } - else if (!shortened){ - fprintf(out,"\t\t \n",tex->mWidth*tex->mHeight*4); - - // const unsigned int width = (unsigned int)log10((double)std::max(tex->mHeight,tex->mWidth))+1; - for (unsigned int y = 0; y < tex->mHeight;++y) { - for (unsigned int x = 0; x < tex->mWidth;++x) { - aiTexel* tx = tex->pcData + y*tex->mWidth+x; - unsigned int r = tx->r,g=tx->g,b=tx->b,a=tx->a; - fprintf(out,"\t\t\t%2x %2x %2x %2x",r,g,b,a); - - // group by four for readibility - if (0 == (x+y*tex->mWidth) % 4) - fprintf(out,"\n"); - } - } - } - fprintf(out,"\t\t\n\t\n"); - } - fprintf(out,"\n"); - } - - // write materials - if (scene->mNumMaterials) { - fprintf(out,"\n",scene->mNumMaterials); - for (unsigned int i = 0; i< scene->mNumMaterials; ++i) { - const aiMaterial* mat = scene->mMaterials[i]; - - fprintf(out,"\t\n"); - fprintf(out,"\t\t\n",mat->mNumProperties); - for (unsigned int n = 0; n < mat->mNumProperties;++n) { - - const aiMaterialProperty* prop = mat->mProperties[n]; - const char* sz = ""; - if (prop->mType == aiPTI_Float) { - sz = "float"; - } - else if (prop->mType == aiPTI_Integer) { - sz = "integer"; - } - else if (prop->mType == aiPTI_String) { - sz = "string"; - } - else if (prop->mType == aiPTI_Buffer) { - sz = "binary_buffer"; - } - - fprintf(out,"\t\t\tmKey.data, sz, - ::TextureTypeToString((aiTextureType)prop->mSemantic),prop->mIndex); - - if (prop->mType == aiPTI_Float) { - fprintf(out," size=\"%i\">\n\t\t\t\t", - static_cast(prop->mDataLength/sizeof(float))); - - for (unsigned int p = 0; p < prop->mDataLength/sizeof(float);++p) { - fprintf(out,"%f ",*((float*)(prop->mData+p*sizeof(float)))); - } - } - else if (prop->mType == aiPTI_Integer) { - fprintf(out," size=\"%i\">\n\t\t\t\t", - static_cast(prop->mDataLength/sizeof(int))); - - for (unsigned int p = 0; p < prop->mDataLength/sizeof(int);++p) { - fprintf(out,"%i ",*((int*)(prop->mData+p*sizeof(int)))); - } - } - else if (prop->mType == aiPTI_Buffer) { - fprintf(out," size=\"%i\">\n\t\t\t\t", - static_cast(prop->mDataLength)); - - for (unsigned int p = 0; p < prop->mDataLength;++p) { - fprintf(out,"%2x ",prop->mData[p]); - if (p && 0 == p%30) { - fprintf(out,"\n\t\t\t\t"); - } - } - } - else if (prop->mType == aiPTI_String) { - fprintf(out,">\n\t\t\t\t\"%s\"",encodeXML(prop->mData+4).c_str() /* skip length */); - } - fprintf(out,"\n\t\t\t\n"); - } - fprintf(out,"\t\t\n"); - fprintf(out,"\t\n"); - } - fprintf(out,"\n"); - } - - // write animations - if (scene->mNumAnimations) { - fprintf(out,"\n",scene->mNumAnimations); - for (unsigned int i = 0; i < scene->mNumAnimations;++i) { - aiAnimation* anim = scene->mAnimations[i]; - - // anim header - ConvertName(name,anim->mName); - fprintf(out,"\t\n", - name.data, anim->mDuration, anim->mTicksPerSecond); - - // write bone animation channels - if (anim->mNumChannels) { - fprintf(out,"\t\t\n",anim->mNumChannels); - for (unsigned int n = 0; n < anim->mNumChannels;++n) { - aiNodeAnim* nd = anim->mChannels[n]; - - // node anim header - ConvertName(name,nd->mNodeName); - fprintf(out,"\t\t\t\n",name.data); - - if (!shortened) { - // write position keys - if (nd->mNumPositionKeys) { - fprintf(out,"\t\t\t\t\n",nd->mNumPositionKeys); - for (unsigned int a = 0; a < nd->mNumPositionKeys;++a) { - aiVectorKey* vc = nd->mPositionKeys+a; - fprintf(out,"\t\t\t\t\t\n" - "\t\t\t\t\t\t%0 8f %0 8f %0 8f\n\t\t\t\t\t\n", - vc->mTime,vc->mValue.x,vc->mValue.y,vc->mValue.z); - } - fprintf(out,"\t\t\t\t\n"); - } - - // write scaling keys - if (nd->mNumScalingKeys) { - fprintf(out,"\t\t\t\t\n",nd->mNumScalingKeys); - for (unsigned int a = 0; a < nd->mNumScalingKeys;++a) { - aiVectorKey* vc = nd->mScalingKeys+a; - fprintf(out,"\t\t\t\t\t\n" - "\t\t\t\t\t\t%0 8f %0 8f %0 8f\n\t\t\t\t\t\n", - vc->mTime,vc->mValue.x,vc->mValue.y,vc->mValue.z); - } - fprintf(out,"\t\t\t\t\n"); - } - - // write rotation keys - if (nd->mNumRotationKeys) { - fprintf(out,"\t\t\t\t\n",nd->mNumRotationKeys); - for (unsigned int a = 0; a < nd->mNumRotationKeys;++a) { - aiQuatKey* vc = nd->mRotationKeys+a; - fprintf(out,"\t\t\t\t\t\n" - "\t\t\t\t\t\t%0 8f %0 8f %0 8f %0 8f\n\t\t\t\t\t\n", - vc->mTime,vc->mValue.x,vc->mValue.y,vc->mValue.z,vc->mValue.w); - } - fprintf(out,"\t\t\t\t\n"); - } - } - fprintf(out,"\t\t\t\n"); - } - fprintf(out,"\t\t\n"); - } - fprintf(out,"\t\n"); - } - fprintf(out,"\n"); - } - - // write meshes - if (scene->mNumMeshes) { - fprintf(out,"\n",scene->mNumMeshes); - for (unsigned int i = 0; i < scene->mNumMeshes;++i) { - aiMesh* mesh = scene->mMeshes[i]; - // const unsigned int width = (unsigned int)log10((double)mesh->mNumVertices)+1; - - // mesh header - fprintf(out,"\t\n", - (mesh->mPrimitiveTypes & aiPrimitiveType_POINT ? "points" : ""), - (mesh->mPrimitiveTypes & aiPrimitiveType_LINE ? "lines" : ""), - (mesh->mPrimitiveTypes & aiPrimitiveType_TRIANGLE ? "triangles" : ""), - (mesh->mPrimitiveTypes & aiPrimitiveType_POLYGON ? "polygons" : ""), - mesh->mMaterialIndex); - - // bones - if (mesh->mNumBones) { - fprintf(out,"\t\t\n",mesh->mNumBones); - - for (unsigned int n = 0; n < mesh->mNumBones;++n) { - aiBone* bone = mesh->mBones[n]; - - ConvertName(name,bone->mName); - // bone header - fprintf(out,"\t\t\t\n" - "\t\t\t\t \n" - "\t\t\t\t\t%0 6f %0 6f %0 6f %0 6f\n" - "\t\t\t\t\t%0 6f %0 6f %0 6f %0 6f\n" - "\t\t\t\t\t%0 6f %0 6f %0 6f %0 6f\n" - "\t\t\t\t\t%0 6f %0 6f %0 6f %0 6f\n" - "\t\t\t\t \n", - name.data, - bone->mOffsetMatrix.a1,bone->mOffsetMatrix.a2,bone->mOffsetMatrix.a3,bone->mOffsetMatrix.a4, - bone->mOffsetMatrix.b1,bone->mOffsetMatrix.b2,bone->mOffsetMatrix.b3,bone->mOffsetMatrix.b4, - bone->mOffsetMatrix.c1,bone->mOffsetMatrix.c2,bone->mOffsetMatrix.c3,bone->mOffsetMatrix.c4, - bone->mOffsetMatrix.d1,bone->mOffsetMatrix.d2,bone->mOffsetMatrix.d3,bone->mOffsetMatrix.d4); - - if (!shortened && bone->mNumWeights) { - fprintf(out,"\t\t\t\t\n",bone->mNumWeights); - - // bone weights - for (unsigned int a = 0; a < bone->mNumWeights;++a) { - aiVertexWeight* wght = bone->mWeights+a; - - fprintf(out,"\t\t\t\t\t\n\t\t\t\t\t\t%f\n\t\t\t\t\t\n", - wght->mVertexId,wght->mWeight); - } - fprintf(out,"\t\t\t\t\n"); - } - fprintf(out,"\t\t\t\n"); - } - fprintf(out,"\t\t\n"); - } - - // faces - if (!shortened && mesh->mNumFaces) { - fprintf(out,"\t\t\n",mesh->mNumFaces); - for (unsigned int n = 0; n < mesh->mNumFaces; ++n) { - aiFace& f = mesh->mFaces[n]; - fprintf(out,"\t\t\t\n" - "\t\t\t\t",f.mNumIndices); - - for (unsigned int j = 0; j < f.mNumIndices;++j) - fprintf(out,"%u ",f.mIndices[j]); - - fprintf(out,"\n\t\t\t\n"); - } - fprintf(out,"\t\t\n"); - } - - // vertex positions - if (mesh->HasPositions()) { - fprintf(out,"\t\t \n",mesh->mNumVertices); - if (!shortened) { - for (unsigned int n = 0; n < mesh->mNumVertices; ++n) { - fprintf(out,"\t\t%0 8f %0 8f %0 8f\n", - mesh->mVertices[n].x, - mesh->mVertices[n].y, - mesh->mVertices[n].z); - } - } - fprintf(out,"\t\t\n"); - } - - // vertex normals - if (mesh->HasNormals()) { - fprintf(out,"\t\t \n",mesh->mNumVertices); - if (!shortened) { - for (unsigned int n = 0; n < mesh->mNumVertices; ++n) { - fprintf(out,"\t\t%0 8f %0 8f %0 8f\n", - mesh->mNormals[n].x, - mesh->mNormals[n].y, - mesh->mNormals[n].z); - } - } - else { - } - fprintf(out,"\t\t\n"); - } - - // vertex tangents and bitangents - if (mesh->HasTangentsAndBitangents()) { - fprintf(out,"\t\t \n",mesh->mNumVertices); - if (!shortened) { - for (unsigned int n = 0; n < mesh->mNumVertices; ++n) { - fprintf(out,"\t\t%0 8f %0 8f %0 8f\n", - mesh->mTangents[n].x, - mesh->mTangents[n].y, - mesh->mTangents[n].z); - } - } - fprintf(out,"\t\t\n"); - - fprintf(out,"\t\t \n",mesh->mNumVertices); - if (!shortened) { - for (unsigned int n = 0; n < mesh->mNumVertices; ++n) { - fprintf(out,"\t\t%0 8f %0 8f %0 8f\n", - mesh->mBitangents[n].x, - mesh->mBitangents[n].y, - mesh->mBitangents[n].z); - } - } - fprintf(out,"\t\t\n"); - } - - // texture coordinates - for (unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a) { - if (!mesh->mTextureCoords[a]) - break; - - fprintf(out,"\t\t \n",mesh->mNumVertices, - a,mesh->mNumUVComponents[a]); - - if (!shortened) { - if (mesh->mNumUVComponents[a] == 3) { - for (unsigned int n = 0; n < mesh->mNumVertices; ++n) { - fprintf(out,"\t\t%0 8f %0 8f %0 8f\n", - mesh->mTextureCoords[a][n].x, - mesh->mTextureCoords[a][n].y, - mesh->mTextureCoords[a][n].z); - } - } - else { - for (unsigned int n = 0; n < mesh->mNumVertices; ++n) { - fprintf(out,"\t\t%0 8f %0 8f\n", - mesh->mTextureCoords[a][n].x, - mesh->mTextureCoords[a][n].y); - } - } - } - fprintf(out,"\t\t\n"); - } - - // vertex colors - for (unsigned int a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; ++a) { - if (!mesh->mColors[a]) - break; - fprintf(out,"\t\t \n",mesh->mNumVertices,a); - if (!shortened) { - for (unsigned int n = 0; n < mesh->mNumVertices; ++n) { - fprintf(out,"\t\t%0 8f %0 8f %0 8f %0 8f\n", - mesh->mColors[a][n].r, - mesh->mColors[a][n].g, - mesh->mColors[a][n].b, - mesh->mColors[a][n].a); - } - } - fprintf(out,"\t\t\n"); - } - fprintf(out,"\t\n"); - } - fprintf(out,"\n"); - } - fprintf(out,"\n"); -} - - // ----------------------------------------------------------------------------------- int Assimp_Dump (const char* const* params, unsigned int num) { @@ -743,29 +183,25 @@ int Assimp_Dump (const char* const* params, unsigned int num) return AssimpCmdError::FailedToLoadInputFile; } - if (binary) { - try { - std::unique_ptr pIOSystem(new DefaultIOSystem()); + try { + // Dump the main model, using the appropriate method. + std::unique_ptr pIOSystem(new DefaultIOSystem()); + if (binary) { DumpSceneToAssbin(out.c_str(), cmd.c_str(), pIOSystem.get(), scene, shortened, compressed); } - catch (const std::exception& e) { - printf("%s", ("assimp dump: " + std::string(e.what())).c_str()); - return AssimpCmdError::ExceptionWasRaised; - } - catch (...) { - printf("assimp dump: An unknown exception occured.\n"); - return AssimpCmdError::ExceptionWasRaised; + else { + DumpSceneToAssxml(out.c_str(), cmd.c_str(), pIOSystem.get(), + scene, shortened); } } - else { - FILE* o = ::fopen(out.c_str(), "wt"); - if (!o) { - printf("assimp dump: Unable to open output file %s\n",out.c_str()); - return AssimpCmdError::FailedToOpenOutputFile; - } - WriteDump (scene,o,in.c_str(),cmd.c_str(),shortened); - fclose(o); + catch (const std::exception& e) { + printf("%s", ("assimp dump: " + std::string(e.what())).c_str()); + return AssimpCmdError::ExceptionWasRaised; + } + catch (...) { + printf("assimp dump: An unknown exception occured.\n"); + return AssimpCmdError::ExceptionWasRaised; } printf("assimp dump: Wrote output dump %s\n",out.c_str()); From 398a8f757e401bfac5569940e56f82659c7f9e74 Mon Sep 17 00:00:00 2001 From: bzt Date: Wed, 29 Jan 2020 22:08:34 +0100 Subject: [PATCH 020/330] Additional checks on invalid input --- code/M3D/M3DImporter.cpp | 46 +++++++++++++++++++++++++++------------- 1 file changed, 31 insertions(+), 15 deletions(-) diff --git a/code/M3D/M3DImporter.cpp b/code/M3D/M3DImporter.cpp index a77e75a27..b0759542b 100644 --- a/code/M3D/M3DImporter.cpp +++ b/code/M3D/M3DImporter.cpp @@ -225,7 +225,7 @@ void M3DImporter::InternReadFile(const std::string &file, aiScene *pScene, IOSys // ------------------------------------------------------------------------------------------------ // convert materials. properties are converted using a static table in M3DMaterials.h -void M3DImporter::importMaterials(const M3DWrapper &m3d_wrap) { +void M3DImporter::importMaterials(const M3DWrapper &m3d) { unsigned int i, j, k, l, n; m3dm_t *m; aiString name = aiString(AI_DEFAULT_MATERIAL_NAME); @@ -233,9 +233,9 @@ void M3DImporter::importMaterials(const M3DWrapper &m3d_wrap) { ai_real f; ai_assert(mScene != nullptr); - ai_assert(m3d_wrap); + ai_assert(m3d); - mScene->mNumMaterials = m3d_wrap->nummaterial + 1; + mScene->mNumMaterials = m3d->nummaterial + 1; mScene->mMaterials = new aiMaterial *[mScene->mNumMaterials]; ASSIMP_LOG_DEBUG_F("M3D: importMaterials ", mScene->mNumMaterials); @@ -248,8 +248,11 @@ void M3DImporter::importMaterials(const M3DWrapper &m3d_wrap) { mat->AddProperty(&c, 1, AI_MATKEY_COLOR_DIFFUSE); mScene->mMaterials[0] = mat; - for (i = 0; i < m3d_wrap->nummaterial; i++) { - m = &m3d_wrap->material[i]; + if (!m3d->nummaterial || !m3d->material) + return; + + for (i = 0; i < m3d->nummaterial; i++) { + m = &m3d->material[i]; aiMaterial *mat = new aiMaterial; name.Set(std::string(m->name)); mat->AddProperty(&name, AI_MATKEY_NAME); @@ -294,9 +297,9 @@ void M3DImporter::importMaterials(const M3DWrapper &m3d_wrap) { // texture map properties if (m->prop[j].type >= 128 && aiTxProps[k].pKey && // extra check, should never happen, do we have the refered texture? - m->prop[j].value.textureid < m3d_wrap->numtexture && - m3d_wrap->texture[m->prop[j].value.textureid].name) { - name.Set(std::string(std::string(m3d_wrap->texture[m->prop[j].value.textureid].name) + ".png")); + m->prop[j].value.textureid < m3d->numtexture && + m3d->texture[m->prop[j].value.textureid].name) { + name.Set(std::string(std::string(m3d->texture[m->prop[j].value.textureid].name) + ".png")); mat->AddProperty(&name, aiTxProps[k].pKey, aiTxProps[k].type, aiTxProps[k].index); n = 0; mat->AddProperty(&n, 1, _AI_MATKEY_UVWSRC_BASE, aiProps[k].type, aiProps[k].index); @@ -319,7 +322,7 @@ void M3DImporter::importTextures(const M3DWrapper &m3d) { mScene->mNumTextures = m3d->numtexture; ASSIMP_LOG_DEBUG_F("M3D: importTextures ", mScene->mNumTextures); - if (!m3d->numtexture) + if (!m3d->numtexture || !m3d->texture) return; mScene->mTextures = new aiTexture *[m3d->numtexture]; @@ -387,6 +390,9 @@ void M3DImporter::importMeshes(const M3DWrapper &m3d) { ASSIMP_LOG_DEBUG_F("M3D: importMeshes ", m3d->numface); + if (!m3d->numface || !m3d->face || !m3d->numvertex || !m3d->vertex) + return; + for (i = 0; i < m3d->numface; i++) { // we must switch mesh if material changes if (lastMat != m3d->face[i].materialid) { @@ -420,6 +426,7 @@ void M3DImporter::importMeshes(const M3DWrapper &m3d) { k = static_cast(vertices->size()); pFace->mIndices[j] = k; l = m3d->face[i].vertex[j]; + if(l >= m3d->numvertex) continue; pos.x = m3d->vertex[l].x; pos.y = m3d->vertex[l].y; pos.z = m3d->vertex[l].z; @@ -432,14 +439,14 @@ void M3DImporter::importMeshes(const M3DWrapper &m3d) { vertexids->push_back(l); } l = m3d->face[i].texcoord[j]; - if (l != M3D_UNDEF) { + if (l != M3D_UNDEF && l < m3d->numtmap) { uv.x = m3d->tmap[l].u; uv.y = m3d->tmap[l].v; uv.z = 0.0; texcoords->push_back(uv); } l = m3d->face[i].normal[j]; - if (l != M3D_UNDEF) { + if (l != M3D_UNDEF && l < m3d->numvertex) { norm.x = m3d->vertex[l].x; norm.y = m3d->vertex[l].y; norm.z = m3d->vertex[l].z; @@ -487,6 +494,9 @@ void M3DImporter::importBones(const M3DWrapper &m3d, unsigned int parentid, aiNo ASSIMP_LOG_DEBUG_F("M3D: importBones ", m3d->numbone, " parentid ", (int)parentid); + if (!m3d->numbone || !m3d->bone) + return; + for (n = 0, i = parentid + 1; i < m3d->numbone; i++) if (m3d->bone[i].parent == parentid) n++; pParent->mChildren = new aiNode *[n]; @@ -521,7 +531,7 @@ void M3DImporter::importAnimations(const M3DWrapper &m3d) { ASSIMP_LOG_DEBUG_F("M3D: importAnimations ", mScene->mNumAnimations); - if (!m3d->numaction || !m3d->numbone) + if (!m3d->numaction || !m3d->action || !m3d->numbone || !m3d->bone || !m3d->vertex) return; mScene->mAnimations = new aiAnimation *[m3d->numaction]; @@ -552,6 +562,7 @@ void M3DImporter::importAnimations(const M3DWrapper &m3d) { ori = a->frame[j].transform[k].ori; } } + if(pos >= m3d->numvertex || ori >= m3d->numvertex) continue; m3dv_t *v = &m3d->vertex[pos]; m3dv_t *q = &m3d->vertex[ori]; pAnim->mChannels[l]->mPositionKeys[j].mTime = t; @@ -587,6 +598,8 @@ void M3DImporter::convertPose(const M3DWrapper &m3d, aiMatrix4x4 *m, unsigned in ai_assert(m3d); ai_assert(posid != M3D_UNDEF && posid < m3d->numvertex); ai_assert(orientid != M3D_UNDEF && orientid < m3d->numvertex); + if (!m3d->numvertex || !m3d->vertex) + return; m3dv_t *p = &m3d->vertex[posid]; m3dv_t *q = &m3d->vertex[orientid]; @@ -701,7 +714,7 @@ void M3DImporter::populateMesh(const M3DWrapper &m3d, aiMesh *pMesh, std::vector // vertex but assimp uses lists of local vertex id/weight pairs per local bone list pMesh->mNumBones = m3d->numbone; /* we need aiBone with mOffsetMatrix for bones without weights as well */ - if (pMesh->mNumBones) { + if (pMesh->mNumBones && m3d->numbone && m3d->bone) { pMesh->mBones = new aiBone *[pMesh->mNumBones]; for (unsigned int i = 0; i < m3d->numbone; i++) { aiNode *pNode; @@ -715,10 +728,11 @@ void M3DImporter::populateMesh(const M3DWrapper &m3d, aiMesh *pMesh, std::vector } else pMesh->mBones[i]->mOffsetMatrix = aiMatrix4x4(); } - if (vertexids->size()) { + if (vertexids->size() && m3d->numvertex && m3d->vertex && m3d->numskin && m3d->skin) { unsigned int i, j; // first count how many vertices we have per bone for (i = 0; i < vertexids->size(); i++) { + if(vertexids->at(i) >= m3d->numvertex) continue; unsigned int s = m3d->vertex[vertexids->at(i)].skinid; if (s != M3D_UNDEF && s != M3D_INDEXMAX) { for (unsigned int k = 0; k < M3D_NUMBONE && m3d->skin[s].weight[k] > 0.0; k++) { @@ -742,9 +756,11 @@ void M3DImporter::populateMesh(const M3DWrapper &m3d, aiMesh *pMesh, std::vector } // fill up with data for (i = 0; i < vertexids->size(); i++) { + if(vertexids->at(i) >= m3d->numvertex) continue; unsigned int s = m3d->vertex[vertexids->at(i)].skinid; - if (s != M3D_UNDEF && s != M3D_INDEXMAX) { + if (s != M3D_UNDEF && s != M3D_INDEXMAX && s < m3d->numskin) { for (unsigned int k = 0; k < M3D_NUMBONE && m3d->skin[s].weight[k] > 0.0; k++) { + if(m3d->skin[s].boneid[k] >= m3d->numbone) continue; aiString name = aiString(std::string(m3d->bone[m3d->skin[s].boneid[k]].name)); for (j = 0; j < pMesh->mNumBones; j++) { if (pMesh->mBones[j]->mName == name) { From 605336832ff0aa6fc8a2b9cde1e1a944dc9e9dc3 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Thu, 30 Jan 2020 09:47:39 +0100 Subject: [PATCH 021/330] Update M3DImporter.cpp Add missing brackets --- code/M3D/M3DImporter.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/code/M3D/M3DImporter.cpp b/code/M3D/M3DImporter.cpp index 4373672a4..1a5d1866d 100644 --- a/code/M3D/M3DImporter.cpp +++ b/code/M3D/M3DImporter.cpp @@ -248,8 +248,9 @@ void M3DImporter::importMaterials(const M3DWrapper &m3d) { mat->AddProperty(&c, 1, AI_MATKEY_COLOR_DIFFUSE); mScene->mMaterials[0] = mat; - if (!m3d->nummaterial || !m3d->material) + if (!m3d->nummaterial || !m3d->material) { return; + } for (i = 0; i < m3d->nummaterial; i++) { m = &m3d->material[i]; From a2ef0b5bd5e2695d65f29f46cad84eecec1800e1 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Thu, 30 Jan 2020 10:00:43 +0100 Subject: [PATCH 022/330] Update M3DImporter.cpp Fix some review finding: - Add missing brackets to make code more readable - fix scope of variables --- code/M3D/M3DImporter.cpp | 135 ++++++++++++++++++++++----------------- 1 file changed, 75 insertions(+), 60 deletions(-) diff --git a/code/M3D/M3DImporter.cpp b/code/M3D/M3DImporter.cpp index 1a5d1866d..20b9b9e44 100644 --- a/code/M3D/M3DImporter.cpp +++ b/code/M3D/M3DImporter.cpp @@ -109,7 +109,9 @@ using namespace std; // ------------------------------------------------------------------------------------------------ // Default constructor M3DImporter::M3DImporter() : - mScene(nullptr) {} + mScene(nullptr) { + // empty +} // ------------------------------------------------------------------------------------------------ // Returns true, if file is a binary or ASCII Model 3D file. @@ -126,14 +128,8 @@ bool M3DImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool c if (!pIOHandler) { return true; } - /* - * don't use CheckMagicToken because that checks with swapped bytes too, leading to false - * positives. This magic is not uint32_t, but char[4], so memcmp is the best way - const char* tokens[] = {"3DMO", "3dmo"}; - return CheckMagicToken(pIOHandler,pFile,tokens,2,0,4); - */ - std::unique_ptr pStream(pIOHandler->Open(pFile, "rb")); + std::unique_ptr pStream(pIOHandler->Open(pFile, "rb")); unsigned char data[4]; if (4 != pStream->Read(data, 1, 4)) { return false; @@ -144,7 +140,8 @@ bool M3DImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool c #endif ; } - return false; + + return false; } // ------------------------------------------------------------------------------------------------ @@ -257,43 +254,46 @@ void M3DImporter::importMaterials(const M3DWrapper &m3d) { aiMaterial *mat = new aiMaterial; name.Set(std::string(m->name)); mat->AddProperty(&name, AI_MATKEY_NAME); - for (j = 0; j < m->numprop; j++) { + for (j = 0; j < m->numprop; ++j) { // look up property type // 0 - 127 scalar values, // 128 - 255 the same properties but for texture maps k = 256; - for (l = 0; l < sizeof(m3d_propertytypes) / sizeof(m3d_propertytypes[0]); l++) + for (l = 0; l < sizeof(m3d_propertytypes) / sizeof(m3d_propertytypes[0]); ++l) { if (m->prop[j].type == m3d_propertytypes[l].id || m->prop[j].type == m3d_propertytypes[l].id + 128) { k = l; break; } - // should never happen, but be safe than sorry - if (k == 256) continue; + // should never happen, but be safe than sorry + if (k == 256) { + continue; + } - // scalar properties - if (m->prop[j].type < 128 && aiProps[k].pKey) { - switch (m3d_propertytypes[k].format) { - case m3dpf_color: - c = mkColor(m->prop[j].value.color); - mat->AddProperty(&c, 1, aiProps[k].pKey, aiProps[k].type, aiProps[k].index); - break; - case m3dpf_float: - f = m->prop[j].value.fnum; - mat->AddProperty(&f, 1, aiProps[k].pKey, aiProps[k].type, aiProps[k].index); - break; - default: - n = m->prop[j].value.num; - if (m->prop[j].type == m3dp_il) { - switch (n) { - case 0: n = aiShadingMode_NoShading; break; - case 2: n = aiShadingMode_Phong; break; - default: n = aiShadingMode_Gouraud; break; - } - } - mat->AddProperty(&n, 1, aiProps[k].pKey, aiProps[k].type, aiProps[k].index); - break; - } + // scalar properties + if (m->prop[j].type < 128 && aiProps[k].pKey) { + switch (m3d_propertytypes[k].format) { + case m3dpf_color: + c = mkColor(m->prop[j].value.color); + mat->AddProperty(&c, 1, aiProps[k].pKey, aiProps[k].type, aiProps[k].index); + break; + case m3dpf_float: + f = m->prop[j].value.fnum; + mat->AddProperty(&f, 1, aiProps[k].pKey, aiProps[k].type, aiProps[k].index); + break; + default: + n = m->prop[j].value.num; + if (m->prop[j].type == m3dp_il) { + switch (n) { + case 0: n = aiShadingMode_NoShading; break; + case 2: n = aiShadingMode_Phong; break; + default: n = aiShadingMode_Gouraud; break; + } + } + mat->AddProperty(&n, 1, aiProps[k].pKey, aiProps[k].type, aiProps[k].index); + break; + } + } } // texture map properties if (m->prop[j].type >= 128 && aiTxProps[k].pKey && @@ -314,7 +314,11 @@ void M3DImporter::importMaterials(const M3DWrapper &m3d) { // import textures, this is the simplest of all void M3DImporter::importTextures(const M3DWrapper &m3d) { unsigned int i; - const char *formatHint[] = { "rgba0800", "rgba0808", "rgba8880", "rgba8888" }; + static const char *formatHint[] = { + "rgba0800", + "rgba0808", + "rgba8880", + "rgba8888" }; m3dtx_t *t; ai_assert(mScene != nullptr); @@ -323,8 +327,9 @@ void M3DImporter::importTextures(const M3DWrapper &m3d) { mScene->mNumTextures = m3d->numtexture; ASSIMP_LOG_DEBUG_F("M3D: importTextures ", mScene->mNumTextures); - if (!m3d->numtexture || !m3d->texture) + if (!m3d->numtexture || !m3d->texture) { return; + } mScene->mTextures = new aiTexture *[m3d->numtexture]; for (i = 0; i < m3d->numtexture; i++) { @@ -391,8 +396,9 @@ void M3DImporter::importMeshes(const M3DWrapper &m3d) { ASSIMP_LOG_DEBUG_F("M3D: importMeshes ", m3d->numface); - if (!m3d->numface || !m3d->face || !m3d->numvertex || !m3d->vertex) + if (!m3d->numface || !m3d->face || !m3d->numvertex || !m3d->vertex) { return; + } for (i = 0; i < m3d->numface; i++) { // we must switch mesh if material changes @@ -476,12 +482,12 @@ void M3DImporter::importMeshes(const M3DWrapper &m3d) { } delete meshes; - if (faces) delete faces; - if (vertices) delete vertices; - if (normals) delete normals; - if (texcoords) delete texcoords; - if (colors) delete colors; - if (vertexids) delete vertexids; + delete faces; + delete vertices; + delete normals; + delete texcoords; + delete colors; + delete vertexids; } // ------------------------------------------------------------------------------------------------ @@ -495,11 +501,15 @@ void M3DImporter::importBones(const M3DWrapper &m3d, unsigned int parentid, aiNo ASSIMP_LOG_DEBUG_F("M3D: importBones ", m3d->numbone, " parentid ", (int)parentid); - if (!m3d->numbone || !m3d->bone) + if (!m3d->numbone || !m3d->bone) { return; + } - for (n = 0, i = parentid + 1; i < m3d->numbone; i++) - if (m3d->bone[i].parent == parentid) n++; + for (n = 0, i = parentid + 1; i < m3d->numbone; i++) { + if (m3d->bone[i].parent == parentid) { + n++; + } + } pParent->mChildren = new aiNode *[n]; for (i = parentid + 1; i < m3d->numbone; i++) { @@ -532,8 +542,9 @@ void M3DImporter::importAnimations(const M3DWrapper &m3d) { ASSIMP_LOG_DEBUG_F("M3D: importAnimations ", mScene->mNumAnimations); - if (!m3d->numaction || !m3d->action || !m3d->numbone || !m3d->bone || !m3d->vertex) + if (!m3d->numaction || !m3d->action || !m3d->numbone || !m3d->bone || !m3d->vertex) { return; + } mScene->mAnimations = new aiAnimation *[m3d->numaction]; for (i = 0; i < m3d->numaction; i++) { @@ -643,16 +654,17 @@ void M3DImporter::convertPose(const M3DWrapper &m3d, aiMatrix4x4 *m, unsigned in // ------------------------------------------------------------------------------------------------ // find a node by name aiNode *M3DImporter::findNode(aiNode *pNode, aiString name) { - unsigned int i; - ai_assert(pNode != nullptr); ai_assert(mScene != nullptr); - if (pNode->mName == name) + if (pNode->mName == name) { return pNode; - for (i = 0; i < pNode->mNumChildren; i++) { + } + for ( unsigned int i = 0; i < pNode->mNumChildren; i++) { aiNode *pChild = findNode(pNode->mChildren[i], name); - if (pChild) return pChild; + if (pChild) { + return pChild; + } } return nullptr; } @@ -714,7 +726,8 @@ void M3DImporter::populateMesh(const M3DWrapper &m3d, aiMesh *pMesh, std::vector // this is complicated, because M3D stores a list of bone id / weight pairs per // vertex but assimp uses lists of local vertex id/weight pairs per local bone list pMesh->mNumBones = m3d->numbone; - /* we need aiBone with mOffsetMatrix for bones without weights as well */ + + // we need aiBone with mOffsetMatrix for bones without weights as well if (pMesh->mNumBones && m3d->numbone && m3d->bone) { pMesh->mBones = new aiBone *[pMesh->mNumBones]; for (unsigned int i = 0; i < m3d->numbone; i++) { @@ -730,15 +743,16 @@ void M3DImporter::populateMesh(const M3DWrapper &m3d, aiMesh *pMesh, std::vector pMesh->mBones[i]->mOffsetMatrix = aiMatrix4x4(); } if (vertexids->size() && m3d->numvertex && m3d->vertex && m3d->numskin && m3d->skin) { - unsigned int i, j; // first count how many vertices we have per bone - for (i = 0; i < vertexids->size(); i++) { - if(vertexids->at(i) >= m3d->numvertex) continue; + for (unsigned int i = 0; i < vertexids->size(); i++) { + if (vertexids->at(i) >= m3d->numvertex) { + continue; + } unsigned int s = m3d->vertex[vertexids->at(i)].skinid; if (s != M3D_UNDEF && s != M3D_INDEXMAX) { for (unsigned int k = 0; k < M3D_NUMBONE && m3d->skin[s].weight[k] > 0.0; k++) { aiString name = aiString(std::string(m3d->bone[m3d->skin[s].boneid[k]].name)); - for (j = 0; j < pMesh->mNumBones; j++) { + for (unsigned int j = 0; j < pMesh->mNumBones; j++) { if (pMesh->mBones[j]->mName == name) { pMesh->mBones[j]->mNumWeights++; break; @@ -747,7 +761,8 @@ void M3DImporter::populateMesh(const M3DWrapper &m3d, aiMesh *pMesh, std::vector } } } - // allocate mWeights + + // allocate mWeights for (j = 0; j < pMesh->mNumBones; j++) { aiBone *pBone = pMesh->mBones[j]; if (pBone->mNumWeights) { From 2c1c1d846e4584990e2397f195fb3225ec6a8668 Mon Sep 17 00:00:00 2001 From: Marc-Antoine Lortie Date: Thu, 30 Jan 2020 16:40:34 -0500 Subject: [PATCH 023/330] Renamed WriteDumb.cpp to WriteDump.cpp This includes as well changes to places referencing WriteDumb.cpp. --- code/Common/assbin_chunks.h | 2 +- tools/assimp_cmd/CMakeLists.txt | 2 +- tools/assimp_cmd/Main.h | 2 +- tools/assimp_cmd/{WriteDumb.cpp => WriteDump.cpp} | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) rename tools/assimp_cmd/{WriteDumb.cpp => WriteDump.cpp} (99%) diff --git a/code/Common/assbin_chunks.h b/code/Common/assbin_chunks.h index 15e4af5e7..822df5198 100644 --- a/code/Common/assbin_chunks.h +++ b/code/Common/assbin_chunks.h @@ -37,7 +37,7 @@ The ASSBIN file format is composed of chunks to represent the hierarchical aiSce This makes the format extensible and allows backward-compatibility with future data structure versions. The <root>/code/assbin_chunks.h header contains some magic constants for use by stand-alone ASSBIN loaders. Also, Assimp's own file writer can be found -in <root>/tools/assimp_cmd/WriteDumb.cpp (yes, the 'b' is no typo ...). +in <root>/tools/assimp_cmd/WriteDump.cpp (yes, the 'b' is no typo ...). @verbatim diff --git a/tools/assimp_cmd/CMakeLists.txt b/tools/assimp_cmd/CMakeLists.txt index ef7b7f054..fcf36c356 100644 --- a/tools/assimp_cmd/CMakeLists.txt +++ b/tools/assimp_cmd/CMakeLists.txt @@ -54,7 +54,7 @@ ADD_EXECUTABLE( assimp_cmd Main.cpp Main.h resource.h - WriteDumb.cpp + WriteDump.cpp Info.cpp Export.cpp ) diff --git a/tools/assimp_cmd/Main.h b/tools/assimp_cmd/Main.h index 7a6ac942d..ecc65345d 100644 --- a/tools/assimp_cmd/Main.h +++ b/tools/assimp_cmd/Main.h @@ -168,7 +168,7 @@ bool ExportModel(const aiScene* pOut, // ------------------------------------------------------------------------------ /** assimp_dump utility - * @param params Command line parameters to 'assimp dumb' + * @param params Command line parameters to 'assimp dump' * @param Number of params * @return An #AssimpCmdError value.*/ int Assimp_Dump ( diff --git a/tools/assimp_cmd/WriteDumb.cpp b/tools/assimp_cmd/WriteDump.cpp similarity index 99% rename from tools/assimp_cmd/WriteDumb.cpp rename to tools/assimp_cmd/WriteDump.cpp index 0403f3966..67d1a0e76 100644 --- a/tools/assimp_cmd/WriteDumb.cpp +++ b/tools/assimp_cmd/WriteDump.cpp @@ -41,7 +41,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --------------------------------------------------------------------------- */ -/** @file WriteTextDumb.cpp +/** @file WriteDump.cpp * @brief Implementation of the 'assimp dump' utility */ From bbe6f7f213b5e2ee689146df5c068dc1a55ea919 Mon Sep 17 00:00:00 2001 From: Hanif Bin Ariffin Date: Thu, 30 Jan 2020 18:42:30 -0500 Subject: [PATCH 024/330] Fixed a bunch of clang warnings 1. Fix misleading indentation warnings. 2. Fix creating a temporary const copy when iterating over a map (thanks to range analysis warnings) 3. Fix creating a copy when iterating over a range without reference qualifier (also thanks to range analysis warnings) --- code/COB/COBLoader.cpp | 2 +- code/Importer/IFC/IFCCurve.cpp | 4 ++-- code/MDL/MDLLoader.cpp | 2 +- code/XGL/XGLLoader.cpp | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/code/COB/COBLoader.cpp b/code/COB/COBLoader.cpp index 7b82ab662..8e7c81192 100644 --- a/code/COB/COBLoader.cpp +++ b/code/COB/COBLoader.cpp @@ -250,7 +250,7 @@ aiNode* COBImporter::BuildNodes(const Node& root,const Scene& scin,aiScene* fill const Mesh& ndmesh = (const Mesh&)(root); if (ndmesh.vertex_positions.size() && ndmesh.texture_coords.size()) { - typedef std::pair Entry; + typedef std::pair Entry; for(const Entry& reflist : ndmesh.temp_map) { { // create mesh size_t n = 0; diff --git a/code/Importer/IFC/IFCCurve.cpp b/code/Importer/IFC/IFCCurve.cpp index 6ff330052..b16df9c5c 100644 --- a/code/Importer/IFC/IFCCurve.cpp +++ b/code/Importer/IFC/IFCCurve.cpp @@ -323,7 +323,7 @@ public: // oh well. bool have_param = false, have_point = false; IfcVector3 point; - for(const Entry sel :entity.Trim1) { + for(const Entry& sel :entity.Trim1) { if (const ::Assimp::STEP::EXPRESS::REAL* const r = sel->ToPtr<::Assimp::STEP::EXPRESS::REAL>()) { range.first = *r; have_param = true; @@ -340,7 +340,7 @@ public: } } have_param = false, have_point = false; - for(const Entry sel :entity.Trim2) { + for(const Entry& sel :entity.Trim2) { if (const ::Assimp::STEP::EXPRESS::REAL* const r = sel->ToPtr<::Assimp::STEP::EXPRESS::REAL>()) { range.second = *r; have_param = true; diff --git a/code/MDL/MDLLoader.cpp b/code/MDL/MDLLoader.cpp index 21a6bc29b..8894f46ec 100644 --- a/code/MDL/MDLLoader.cpp +++ b/code/MDL/MDLLoader.cpp @@ -1421,7 +1421,7 @@ void MDLImporter::InternReadFile_3DGS_MDL7( ) avOutList[i].reserve(3); // buffer to held the names of all groups in the file - const size_t buffersize( AI_MDL7_MAX_GROUPNAMESIZE*pcHeader->groups_num ); + const size_t buffersize(AI_MDL7_MAX_GROUPNAMESIZE*pcHeader->groups_num); char* aszGroupNameBuffer = new char[ buffersize ]; // read all groups diff --git a/code/XGL/XGLLoader.cpp b/code/XGL/XGLLoader.cpp index 24ed5d57c..403205e03 100644 --- a/code/XGL/XGLLoader.cpp +++ b/code/XGL/XGLLoader.cpp @@ -685,7 +685,7 @@ bool XGLImporter::ReadMesh(TempScope& scope) } // finally extract output meshes and add them to the scope - typedef std::pair pairt; + typedef std::pair pairt; for(const pairt& p : bymat) { aiMesh* const m = ToOutputMesh(p.second); scope.meshes_linear.push_back(m); From e434c63c31d474c506b7cb573762aa7ac307e37a Mon Sep 17 00:00:00 2001 From: bzt Date: Fri, 31 Jan 2020 14:20:23 +0100 Subject: [PATCH 025/330] Fixed what kimkulling broke --- code/M3D/M3DImporter.cpp | 137 ++++++++++++++++++++------------------- 1 file changed, 70 insertions(+), 67 deletions(-) diff --git a/code/M3D/M3DImporter.cpp b/code/M3D/M3DImporter.cpp index 20b9b9e44..1c6cea766 100644 --- a/code/M3D/M3DImporter.cpp +++ b/code/M3D/M3DImporter.cpp @@ -110,8 +110,8 @@ using namespace std; // Default constructor M3DImporter::M3DImporter() : mScene(nullptr) { - // empty -} + // empty + } // ------------------------------------------------------------------------------------------------ // Returns true, if file is a binary or ASCII Model 3D file. @@ -128,8 +128,14 @@ bool M3DImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool c if (!pIOHandler) { return true; } + /* + * don't use CheckMagicToken because that checks with swapped bytes too, leading to false + * positives. This magic is not uint32_t, but char[4], so memcmp is the best way - std::unique_ptr pStream(pIOHandler->Open(pFile, "rb")); + const char* tokens[] = {"3DMO", "3dmo"}; + return CheckMagicToken(pIOHandler,pFile,tokens,2,0,4); + */ + std::unique_ptr pStream(pIOHandler->Open(pFile, "rb")); unsigned char data[4]; if (4 != pStream->Read(data, 1, 4)) { return false; @@ -140,8 +146,7 @@ bool M3DImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool c #endif ; } - - return false; + return false; } // ------------------------------------------------------------------------------------------------ @@ -247,53 +252,50 @@ void M3DImporter::importMaterials(const M3DWrapper &m3d) { if (!m3d->nummaterial || !m3d->material) { return; - } + } for (i = 0; i < m3d->nummaterial; i++) { m = &m3d->material[i]; aiMaterial *mat = new aiMaterial; name.Set(std::string(m->name)); mat->AddProperty(&name, AI_MATKEY_NAME); - for (j = 0; j < m->numprop; ++j) { + for (j = 0; j < m->numprop; j++) { // look up property type // 0 - 127 scalar values, // 128 - 255 the same properties but for texture maps k = 256; - for (l = 0; l < sizeof(m3d_propertytypes) / sizeof(m3d_propertytypes[0]); ++l) { + for (l = 0; l < sizeof(m3d_propertytypes) / sizeof(m3d_propertytypes[0]); l++) if (m->prop[j].type == m3d_propertytypes[l].id || m->prop[j].type == m3d_propertytypes[l].id + 128) { k = l; break; } - // should never happen, but be safe than sorry - if (k == 256) { - continue; - } + // should never happen, but be safe than sorry + if (k == 256) continue; - // scalar properties - if (m->prop[j].type < 128 && aiProps[k].pKey) { - switch (m3d_propertytypes[k].format) { - case m3dpf_color: - c = mkColor(m->prop[j].value.color); - mat->AddProperty(&c, 1, aiProps[k].pKey, aiProps[k].type, aiProps[k].index); - break; - case m3dpf_float: - f = m->prop[j].value.fnum; - mat->AddProperty(&f, 1, aiProps[k].pKey, aiProps[k].type, aiProps[k].index); - break; - default: - n = m->prop[j].value.num; - if (m->prop[j].type == m3dp_il) { - switch (n) { - case 0: n = aiShadingMode_NoShading; break; - case 2: n = aiShadingMode_Phong; break; - default: n = aiShadingMode_Gouraud; break; - } - } - mat->AddProperty(&n, 1, aiProps[k].pKey, aiProps[k].type, aiProps[k].index); - break; - } - } + // scalar properties + if (m->prop[j].type < 128 && aiProps[k].pKey) { + switch (m3d_propertytypes[k].format) { + case m3dpf_color: + c = mkColor(m->prop[j].value.color); + mat->AddProperty(&c, 1, aiProps[k].pKey, aiProps[k].type, aiProps[k].index); + break; + case m3dpf_float: + f = m->prop[j].value.fnum; + mat->AddProperty(&f, 1, aiProps[k].pKey, aiProps[k].type, aiProps[k].index); + break; + default: + n = m->prop[j].value.num; + if (m->prop[j].type == m3dp_il) { + switch (n) { + case 0: n = aiShadingMode_NoShading; break; + case 2: n = aiShadingMode_Phong; break; + default: n = aiShadingMode_Gouraud; break; + } + } + mat->AddProperty(&n, 1, aiProps[k].pKey, aiProps[k].type, aiProps[k].index); + break; + } } // texture map properties if (m->prop[j].type >= 128 && aiTxProps[k].pKey && @@ -314,11 +316,12 @@ void M3DImporter::importMaterials(const M3DWrapper &m3d) { // import textures, this is the simplest of all void M3DImporter::importTextures(const M3DWrapper &m3d) { unsigned int i; - static const char *formatHint[] = { - "rgba0800", - "rgba0808", - "rgba8880", - "rgba8888" }; + const char *formatHint[] = { + "rgba0800", + "rgba0808", + "rgba8880", + "rgba8888" + }; m3dtx_t *t; ai_assert(mScene != nullptr); @@ -329,7 +332,7 @@ void M3DImporter::importTextures(const M3DWrapper &m3d) { if (!m3d->numtexture || !m3d->texture) { return; - } + } mScene->mTextures = new aiTexture *[m3d->numtexture]; for (i = 0; i < m3d->numtexture; i++) { @@ -398,7 +401,7 @@ void M3DImporter::importMeshes(const M3DWrapper &m3d) { if (!m3d->numface || !m3d->face || !m3d->numvertex || !m3d->vertex) { return; - } + } for (i = 0; i < m3d->numface; i++) { // we must switch mesh if material changes @@ -482,12 +485,12 @@ void M3DImporter::importMeshes(const M3DWrapper &m3d) { } delete meshes; - delete faces; - delete vertices; - delete normals; - delete texcoords; - delete colors; - delete vertexids; + if (faces) delete faces; + if (vertices) delete vertices; + if (normals) delete normals; + if (texcoords) delete texcoords; + if (colors) delete colors; + if (vertexids) delete vertexids; } // ------------------------------------------------------------------------------------------------ @@ -503,13 +506,13 @@ void M3DImporter::importBones(const M3DWrapper &m3d, unsigned int parentid, aiNo if (!m3d->numbone || !m3d->bone) { return; - } + } for (n = 0, i = parentid + 1; i < m3d->numbone; i++) { if (m3d->bone[i].parent == parentid) { - n++; - } - } + n++; + } + } pParent->mChildren = new aiNode *[n]; for (i = parentid + 1; i < m3d->numbone; i++) { @@ -544,7 +547,7 @@ void M3DImporter::importAnimations(const M3DWrapper &m3d) { if (!m3d->numaction || !m3d->action || !m3d->numbone || !m3d->bone || !m3d->vertex) { return; - } + } mScene->mAnimations = new aiAnimation *[m3d->numaction]; for (i = 0; i < m3d->numaction; i++) { @@ -659,12 +662,13 @@ aiNode *M3DImporter::findNode(aiNode *pNode, aiString name) { if (pNode->mName == name) { return pNode; - } - for ( unsigned int i = 0; i < pNode->mNumChildren; i++) { + } + + for (unsigned int i = 0; i < pNode->mNumChildren; i++) { aiNode *pChild = findNode(pNode->mChildren[i], name); if (pChild) { - return pChild; - } + return pChild; + } } return nullptr; } @@ -726,8 +730,7 @@ void M3DImporter::populateMesh(const M3DWrapper &m3d, aiMesh *pMesh, std::vector // this is complicated, because M3D stores a list of bone id / weight pairs per // vertex but assimp uses lists of local vertex id/weight pairs per local bone list pMesh->mNumBones = m3d->numbone; - - // we need aiBone with mOffsetMatrix for bones without weights as well + // we need aiBone with mOffsetMatrix for bones without weights as well if (pMesh->mNumBones && m3d->numbone && m3d->bone) { pMesh->mBones = new aiBone *[pMesh->mNumBones]; for (unsigned int i = 0; i < m3d->numbone; i++) { @@ -743,16 +746,17 @@ void M3DImporter::populateMesh(const M3DWrapper &m3d, aiMesh *pMesh, std::vector pMesh->mBones[i]->mOffsetMatrix = aiMatrix4x4(); } if (vertexids->size() && m3d->numvertex && m3d->vertex && m3d->numskin && m3d->skin) { + unsigned int i, j; // first count how many vertices we have per bone - for (unsigned int i = 0; i < vertexids->size(); i++) { - if (vertexids->at(i) >= m3d->numvertex) { - continue; - } + for (i = 0; i < vertexids->size(); i++) { + if(vertexids->at(i) >= m3d->numvertex) { + continue; + } unsigned int s = m3d->vertex[vertexids->at(i)].skinid; if (s != M3D_UNDEF && s != M3D_INDEXMAX) { for (unsigned int k = 0; k < M3D_NUMBONE && m3d->skin[s].weight[k] > 0.0; k++) { aiString name = aiString(std::string(m3d->bone[m3d->skin[s].boneid[k]].name)); - for (unsigned int j = 0; j < pMesh->mNumBones; j++) { + for (j = 0; j < pMesh->mNumBones; j++) { if (pMesh->mBones[j]->mName == name) { pMesh->mBones[j]->mNumWeights++; break; @@ -761,8 +765,7 @@ void M3DImporter::populateMesh(const M3DWrapper &m3d, aiMesh *pMesh, std::vector } } } - - // allocate mWeights + // allocate mWeights for (j = 0; j < pMesh->mNumBones; j++) { aiBone *pBone = pMesh->mBones[j]; if (pBone->mNumWeights) { From 0af44fb3e8597b812db47f69e59a31cfb640620a Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Fri, 31 Jan 2020 19:06:56 +0100 Subject: [PATCH 026/330] Update glTFExporter.cpp Replacing tabs by spaces. --- code/glTF/glTFExporter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/glTF/glTFExporter.cpp b/code/glTF/glTFExporter.cpp index 4ebe53c00..072234891 100644 --- a/code/glTF/glTFExporter.cpp +++ b/code/glTF/glTFExporter.cpp @@ -353,7 +353,7 @@ void glTFExporter::GetMatColorOrTex(const aiMaterial* mat, glTF::TexProperty& pr if (path[0] == '*') { // embedded aiTexture* tex = mScene->mTextures[atoi(&path[1])]; - prop.texture->source->name = tex->mFilename.C_Str(); + prop.texture->source->name = tex->mFilename.C_Str(); uint8_t* data = reinterpret_cast(tex->pcData); prop.texture->source->SetData(data, tex->mWidth, *mAsset); From 187b74355bd7ee18b02da9c84d44e6dc186b0c9e Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Fri, 31 Jan 2020 19:08:04 +0100 Subject: [PATCH 027/330] Update glTFImporter.cpp Replace tabs by spaces. --- code/glTF/glTFImporter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/glTF/glTFImporter.cpp b/code/glTF/glTFImporter.cpp index bba48dc30..16addc977 100644 --- a/code/glTF/glTFImporter.cpp +++ b/code/glTF/glTFImporter.cpp @@ -680,7 +680,7 @@ void glTFImporter::ImportEmbeddedTextures(glTF::Asset& r) size_t length = img.GetDataLength(); void* data = img.StealData(); - tex->mFilename = img.name; + tex->mFilename = img.name; tex->mWidth = static_cast(length); tex->mHeight = 0; tex->pcData = reinterpret_cast(data); From 026900088433e46ee5e35162e062d733c547a121 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Fri, 31 Jan 2020 19:11:36 +0100 Subject: [PATCH 028/330] Update glTF2Exporter.cpp Replacing tabs by spaces. --- code/glTF2/glTF2Exporter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/glTF2/glTF2Exporter.cpp b/code/glTF2/glTF2Exporter.cpp index b240a5ea9..1bfee4491 100644 --- a/code/glTF2/glTF2Exporter.cpp +++ b/code/glTF2/glTF2Exporter.cpp @@ -352,7 +352,7 @@ void glTF2Exporter::GetMatTex(const aiMaterial* mat, Ref& texture, aiTe if (path[0] == '*') { // embedded aiTexture* tex = mScene->mTextures[atoi(&path[1])]; - texture->source->name = tex->mFilename.C_Str(); + texture->source->name = tex->mFilename.C_Str(); // The asset has its own buffer, see Image::SetData texture->source->SetData(reinterpret_cast (tex->pcData), tex->mWidth, *mAsset); From ede860173eeb232db58fb768d9c097ed14edf2b4 Mon Sep 17 00:00:00 2001 From: Marc-Antoine Lortie Date: Fri, 31 Jan 2020 16:43:20 -0500 Subject: [PATCH 029/330] Fixed mValues allocated twice. mValues is already allocated in aiMetadata::Alloc(). --- code/Common/SceneCombiner.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/code/Common/SceneCombiner.cpp b/code/Common/SceneCombiner.cpp index 9471907de..29b6082a8 100644 --- a/code/Common/SceneCombiner.cpp +++ b/code/Common/SceneCombiner.cpp @@ -1312,7 +1312,6 @@ void SceneCombiner::Copy(aiMetadata** _dest, const aiMetadata* src) { aiMetadata* dest = *_dest = aiMetadata::Alloc( src->mNumProperties ); std::copy(src->mKeys, src->mKeys + src->mNumProperties, dest->mKeys); - dest->mValues = new aiMetadataEntry[src->mNumProperties]; for (unsigned int i = 0; i < src->mNumProperties; ++i) { aiMetadataEntry& in = src->mValues[i]; aiMetadataEntry& out = dest->mValues[i]; From d6567e606e6acb472f2b64f700834f8fc1ef41ff Mon Sep 17 00:00:00 2001 From: Marc-Antoine Lortie Date: Fri, 31 Jan 2020 18:14:26 -0500 Subject: [PATCH 030/330] Fixed wrong changes applied during merge. --- code/MDL/HalfLife/HL1MDLLoader.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/MDL/HalfLife/HL1MDLLoader.cpp b/code/MDL/HalfLife/HL1MDLLoader.cpp index 6d5f283af..c18528e59 100644 --- a/code/MDL/HalfLife/HL1MDLLoader.cpp +++ b/code/MDL/HalfLife/HL1MDLLoader.cpp @@ -345,8 +345,8 @@ void HL1MDLLoader::read_texture(const Texture_HL1 *ptexture, uint8_t *data, uint8_t *pal, aiTexture *pResult, aiColor3D &last_palette_color) { pResult->mFilename = ptexture->name; - pResult->mWidth = outwidth; - pResult->mHeight = outheight; + pResult->mWidth = static_cast(ptexture->width); + pResult->mHeight = static_cast(ptexture->height); pResult->achFormatHint[0] = 'r'; pResult->achFormatHint[1] = 'g'; pResult->achFormatHint[2] = 'b'; From 8e009c3d0cd11bcabf7a66952d33e3fa55b9ae12 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Mon, 3 Feb 2020 19:06:36 +0100 Subject: [PATCH 031/330] Update MDLLoader.cpp fix a tab. --- code/MDL/MDLLoader.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/MDL/MDLLoader.cpp b/code/MDL/MDLLoader.cpp index 8894f46ec..11c6e3ecb 100644 --- a/code/MDL/MDLLoader.cpp +++ b/code/MDL/MDLLoader.cpp @@ -1422,10 +1422,10 @@ void MDLImporter::InternReadFile_3DGS_MDL7( ) // buffer to held the names of all groups in the file const size_t buffersize(AI_MDL7_MAX_GROUPNAMESIZE*pcHeader->groups_num); - char* aszGroupNameBuffer = new char[ buffersize ]; + char* aszGroupNameBuffer = new char[ buffersize ]; // read all groups - for (unsigned int iGroup = 0; iGroup < (unsigned int)pcHeader->groups_num;++iGroup) { + for (unsigned int iGroup = 0; iGroup < (unsigned int)pcHeader->groups_num; ++iGroup) { MDL::IntGroupInfo_MDL7 groupInfo((BE_NCONST MDL::Group_MDL7*)szCurrent,iGroup); szCurrent = (const unsigned char*)(groupInfo.pcGroup+1); From cb55e2658db85558104b828d17b3455d0a24c6f0 Mon Sep 17 00:00:00 2001 From: Max Vollmer Date: Wed, 5 Feb 2020 11:07:39 +0000 Subject: [PATCH 032/330] Removed unnecessary checks that may result in false positives rejecting valid models --- code/FBX/FBXMeshGeometry.cpp | 46 +++++++++++++----------------------- 1 file changed, 17 insertions(+), 29 deletions(-) diff --git a/code/FBX/FBXMeshGeometry.cpp b/code/FBX/FBXMeshGeometry.cpp index 003f0870c..2f2782182 100644 --- a/code/FBX/FBXMeshGeometry.cpp +++ b/code/FBX/FBXMeshGeometry.cpp @@ -448,11 +448,11 @@ void ResolveVertexDataArray(std::vector& data_out, const Scope& source, std::vector tempData; ParseVectorDataArray(tempData, GetRequiredElement(source, dataElementName)); - if (tempData.size() != vertex_count) { - FBXImporter::LogError(Formatter::format("length of input data unexpected for ByVertice mapping: ") - << tempData.size() << ", expected " << vertex_count); - return; - } + if (tempData.size() != vertex_count) { + FBXImporter::LogError(Formatter::format("length of input data unexpected for ByVertice mapping: ") + << tempData.size() << ", expected " << vertex_count); + return; + } data_out.resize(vertex_count); for (size_t i = 0, e = tempData.size(); i < e; ++i) { @@ -467,22 +467,16 @@ void ResolveVertexDataArray(std::vector& data_out, const Scope& source, std::vector tempData; ParseVectorDataArray(tempData, GetRequiredElement(source, dataElementName)); - if (tempData.size() != vertex_count) { - FBXImporter::LogError(Formatter::format("length of input data unexpected for ByVertice mapping: ") - << tempData.size() << ", expected " << vertex_count); - return; - } - std::vector uvIndices; ParseVectorDataArray(uvIndices,GetRequiredElement(source,indexDataElementName)); - if (uvIndices.size() != vertex_count) { - FBXImporter::LogError(Formatter::format("length of input data unexpected for ByVertice mapping: ") - << uvIndices.size() << ", expected " << vertex_count); - return; - } + if (uvIndices.size() != vertex_count) { + FBXImporter::LogError(Formatter::format("length of input data unexpected for ByVertice mapping: ") + << uvIndices.size() << ", expected " << vertex_count); + return; + } - data_out.resize(vertex_count); + data_out.resize(vertex_count); for (size_t i = 0, e = uvIndices.size(); i < e; ++i) { @@ -512,22 +506,16 @@ void ResolveVertexDataArray(std::vector& data_out, const Scope& source, std::vector tempData; ParseVectorDataArray(tempData, GetRequiredElement(source, dataElementName)); - if (tempData.size() != vertex_count) { - FBXImporter::LogError(Formatter::format("length of input data unexpected for ByPolygonVertex mapping: ") - << tempData.size() << ", expected " << vertex_count); - return; - } - std::vector uvIndices; ParseVectorDataArray(uvIndices,GetRequiredElement(source,indexDataElementName)); - if (uvIndices.size() != vertex_count) { - FBXImporter::LogError(Formatter::format("length of input data unexpected for ByPolygonVertex mapping: ") - << uvIndices.size() << ", expected " << vertex_count); - return; - } + if (uvIndices.size() != vertex_count) { + FBXImporter::LogError(Formatter::format("length of input data unexpected for ByPolygonVertex mapping: ") + << uvIndices.size() << ", expected " << vertex_count); + return; + } - data_out.resize(vertex_count); + data_out.resize(vertex_count); const T empty; unsigned int next = 0; From 8af0229e0d257f7443b8f254fe2c75339680da57 Mon Sep 17 00:00:00 2001 From: Max Vollmer Date: Wed, 5 Feb 2020 14:40:35 +0000 Subject: [PATCH 033/330] In "ByVertice" case tempData.size() needs to be mapping_offsets.size(), not vertex_count --- code/FBX/FBXMeshGeometry.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/code/FBX/FBXMeshGeometry.cpp b/code/FBX/FBXMeshGeometry.cpp index 2f2782182..4a3de9f99 100644 --- a/code/FBX/FBXMeshGeometry.cpp +++ b/code/FBX/FBXMeshGeometry.cpp @@ -446,20 +446,19 @@ void ResolveVertexDataArray(std::vector& data_out, const Scope& source, return; } std::vector tempData; - ParseVectorDataArray(tempData, GetRequiredElement(source, dataElementName)); + ParseVectorDataArray(tempData, GetRequiredElement(source, dataElementName)); - if (tempData.size() != vertex_count) { + if (tempData.size() != mapping_offsets.size()) { FBXImporter::LogError(Formatter::format("length of input data unexpected for ByVertice mapping: ") - << tempData.size() << ", expected " << vertex_count); + << tempData.size() << ", expected " << mapping_offsets.size()); return; } data_out.resize(vertex_count); - for (size_t i = 0, e = tempData.size(); i < e; ++i) { - + for (size_t i = 0, e = tempData.size(); i < e; ++i) { const unsigned int istart = mapping_offsets[i], iend = istart + mapping_counts[i]; for (unsigned int j = istart; j < iend; ++j) { - data_out[mappings[j]] = tempData[i]; + data_out[mappings[j]] = tempData[i]; } } } From 18c01a023cd876ba328478a5cd4c6ff389904789 Mon Sep 17 00:00:00 2001 From: Luke Lau Date: Wed, 5 Feb 2020 21:24:54 +0000 Subject: [PATCH 034/330] Use the translation matrix in gltf2 cameras for aiCamera.mPosition --- code/glTF2/glTF2Importer.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/code/glTF2/glTF2Importer.cpp b/code/glTF2/glTF2Importer.cpp index e5052d4d6..154fef313 100644 --- a/code/glTF2/glTF2Importer.cpp +++ b/code/glTF2/glTF2Importer.cpp @@ -925,6 +925,11 @@ aiNode *ImportNode(aiScene *pScene, glTF2::Asset &r, std::vector & if (node.camera) { pScene->mCameras[node.camera.GetIndex()]->mName = ainode->mName; + if (node.translation.isPresent) { + aiVector3D trans; + CopyValue(node.translation.value, trans); + pScene->mCameras[node.camera.GetIndex()]->mPosition = trans; + } } if (node.light) { From 29603128f434e23cb93398955fe9fe22e101ed6e Mon Sep 17 00:00:00 2001 From: Frooxius Date: Thu, 6 Feb 2020 10:28:38 +0100 Subject: [PATCH 035/330] Fixed invalid armature node population when there's mesh on a node with the same name as the bone --- code/PostProcessing/ArmaturePopulate.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/code/PostProcessing/ArmaturePopulate.cpp b/code/PostProcessing/ArmaturePopulate.cpp index c339bebe0..1514e14f2 100644 --- a/code/PostProcessing/ArmaturePopulate.cpp +++ b/code/PostProcessing/ArmaturePopulate.cpp @@ -150,7 +150,8 @@ void ArmaturePopulate::BuildNodeList(const aiNode *current_node, aiNode *child = current_node->mChildren[nodeId]; ai_assert(child); - nodes.push_back(child); + if (child->mNumMeshes == 0) + nodes.push_back(child); BuildNodeList(child, nodes); } From 8c09cd2ef3d72ba150b7a8faf67ea7fcd913984b Mon Sep 17 00:00:00 2001 From: Marc-Antoine Lortie Date: Thu, 6 Feb 2020 13:19:01 -0500 Subject: [PATCH 036/330] Fixed TextureTypeToString defined multiple times. - Moved TextureTypeToString to it's own file. - Added new file to CMakeLists.txt. - Added 6 missing values in TextureTypeToString. - Added 6 missing aiTextureType enum values in assimp_cmd/Info.cpp. --- code/CMakeLists.txt | 1 + code/Common/material.cpp | 97 +++++++++++++++++++++++++++ code/PostProcessing/ProcessHelper.cpp | 40 ----------- code/PostProcessing/ProcessHelper.h | 6 -- include/assimp/material.h | 4 ++ tools/assimp_cmd/Info.cpp | 6 ++ tools/assimp_cmd/WriteDump.cpp | 38 ----------- 7 files changed, 108 insertions(+), 84 deletions(-) create mode 100644 code/Common/material.cpp diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index 5278509e8..91f099c02 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -198,6 +198,7 @@ SET( Common_SRCS Common/CreateAnimMesh.cpp Common/simd.h Common/simd.cpp + Common/material.cpp ) SOURCE_GROUP(Common FILES ${Common_SRCS}) diff --git a/code/Common/material.cpp b/code/Common/material.cpp new file mode 100644 index 000000000..f4a29dacf --- /dev/null +++ b/code/Common/material.cpp @@ -0,0 +1,97 @@ +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2020, 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 material.cpp +/** Implement common material related functions. */ + +#include +#include + +// ------------------------------------------------------------------------------- +const char* TextureTypeToString(aiTextureType in) +{ + switch (in) + { + case aiTextureType_NONE: + return "n/a"; + case aiTextureType_DIFFUSE: + return "Diffuse"; + case aiTextureType_SPECULAR: + return "Specular"; + case aiTextureType_AMBIENT: + return "Ambient"; + case aiTextureType_EMISSIVE: + return "Emissive"; + case aiTextureType_OPACITY: + return "Opacity"; + case aiTextureType_NORMALS: + return "Normals"; + case aiTextureType_HEIGHT: + return "Height"; + case aiTextureType_SHININESS: + return "Shininess"; + case aiTextureType_DISPLACEMENT: + return "Displacement"; + case aiTextureType_LIGHTMAP: + return "Lightmap"; + case aiTextureType_REFLECTION: + return "Reflection"; + case aiTextureType_BASE_COLOR: + return "BaseColor"; + case aiTextureType_NORMAL_CAMERA: + return "NormalCamera"; + case aiTextureType_EMISSION_COLOR: + return "EmissionColor"; + case aiTextureType_METALNESS: + return "Metalness"; + case aiTextureType_DIFFUSE_ROUGHNESS: + return "DiffuseRoughness"; + case aiTextureType_AMBIENT_OCCLUSION: + return "AmbientOcclusion"; + case aiTextureType_UNKNOWN: + return "Unknown"; + default: + break; + } + ai_assert(false); + return "BUG"; +} diff --git a/code/PostProcessing/ProcessHelper.cpp b/code/PostProcessing/ProcessHelper.cpp index 41444afd8..123986438 100644 --- a/code/PostProcessing/ProcessHelper.cpp +++ b/code/PostProcessing/ProcessHelper.cpp @@ -230,46 +230,6 @@ VertexWeightTable* ComputeVertexBoneWeightTable(const aiMesh* pMesh) return avPerVertexWeights; } - -// ------------------------------------------------------------------------------- -const char* TextureTypeToString(aiTextureType in) -{ - switch (in) - { - case aiTextureType_NONE: - return "n/a"; - case aiTextureType_DIFFUSE: - return "Diffuse"; - case aiTextureType_SPECULAR: - return "Specular"; - case aiTextureType_AMBIENT: - return "Ambient"; - case aiTextureType_EMISSIVE: - return "Emissive"; - case aiTextureType_OPACITY: - return "Opacity"; - case aiTextureType_NORMALS: - return "Normals"; - case aiTextureType_HEIGHT: - return "Height"; - case aiTextureType_SHININESS: - return "Shininess"; - case aiTextureType_DISPLACEMENT: - return "Displacement"; - case aiTextureType_LIGHTMAP: - return "Lightmap"; - case aiTextureType_REFLECTION: - return "Reflection"; - case aiTextureType_UNKNOWN: - return "Unknown"; - default: - break; - } - - ai_assert(false); - return "BUG"; -} - // ------------------------------------------------------------------------------- const char* MappingTypeToString(aiTextureMapping in) { diff --git a/code/PostProcessing/ProcessHelper.h b/code/PostProcessing/ProcessHelper.h index 7ff3a9c5f..5762fbb35 100644 --- a/code/PostProcessing/ProcessHelper.h +++ b/code/PostProcessing/ProcessHelper.h @@ -316,12 +316,6 @@ typedef std::vector VertexWeightTable; // Compute a per-vertex bone weight table VertexWeightTable* ComputeVertexBoneWeightTable(const aiMesh* pMesh); - -// ------------------------------------------------------------------------------- -// Get a string for a given aiTextureType -const char* TextureTypeToString(aiTextureType in); - - // ------------------------------------------------------------------------------- // Get a string for a given aiTextureMapping const char* MappingTypeToString(aiTextureMapping in); diff --git a/include/assimp/material.h b/include/assimp/material.h index 6c864e3d4..75695e50b 100644 --- a/include/assimp/material.h +++ b/include/assimp/material.h @@ -312,6 +312,10 @@ enum aiTextureType #define AI_TEXTURE_TYPE_MAX aiTextureType_UNKNOWN +// ------------------------------------------------------------------------------- +// Get a string for a given aiTextureType +ASSIMP_API const char* TextureTypeToString(enum aiTextureType in); + // --------------------------------------------------------------------------- /** @brief Defines all shading models supported by the library * diff --git a/tools/assimp_cmd/Info.cpp b/tools/assimp_cmd/Info.cpp index 1594235f9..52b9edb92 100644 --- a/tools/assimp_cmd/Info.cpp +++ b/tools/assimp_cmd/Info.cpp @@ -444,6 +444,12 @@ int Assimp_Info (const char* const* params, unsigned int num) { aiTextureType_DISPLACEMENT, aiTextureType_LIGHTMAP, aiTextureType_REFLECTION, + aiTextureType_BASE_COLOR, + aiTextureType_NORMAL_CAMERA, + aiTextureType_EMISSION_COLOR, + aiTextureType_METALNESS, + aiTextureType_DIFFUSE_ROUGHNESS, + aiTextureType_AMBIENT_OCCLUSION, aiTextureType_UNKNOWN }; for(unsigned int type = 0; type < sizeof(types)/sizeof(types[0]); ++type) { diff --git a/tools/assimp_cmd/WriteDump.cpp b/tools/assimp_cmd/WriteDump.cpp index 67d1a0e76..86542ed2e 100644 --- a/tools/assimp_cmd/WriteDump.cpp +++ b/tools/assimp_cmd/WriteDump.cpp @@ -69,44 +69,6 @@ const char* AICMD_MSG_DUMP_HELP = FILE* out = NULL; bool shortened = false; -// ------------------------------------------------------------------------------- -const char* TextureTypeToString(aiTextureType in) -{ - switch (in) - { - case aiTextureType_NONE: - return "n/a"; - case aiTextureType_DIFFUSE: - return "Diffuse"; - case aiTextureType_SPECULAR: - return "Specular"; - case aiTextureType_AMBIENT: - return "Ambient"; - case aiTextureType_EMISSIVE: - return "Emissive"; - case aiTextureType_OPACITY: - return "Opacity"; - case aiTextureType_NORMALS: - return "Normals"; - case aiTextureType_HEIGHT: - return "Height"; - case aiTextureType_SHININESS: - return "Shininess"; - case aiTextureType_DISPLACEMENT: - return "Displacement"; - case aiTextureType_LIGHTMAP: - return "Lightmap"; - case aiTextureType_REFLECTION: - return "Reflection"; - case aiTextureType_UNKNOWN: - return "Unknown"; - default: - break; - } - ai_assert(false); - return "BUG"; -} - // ----------------------------------------------------------------------------------- int Assimp_Dump (const char* const* params, unsigned int num) { From d3a70c73c445c01b03495fe2d0c8513bf16e5fb7 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Fri, 7 Feb 2020 10:58:56 +0100 Subject: [PATCH 037/330] Update FUNDING.yml Add paypal sponsoring --- .github/FUNDING.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index e750822ab..a932e5377 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -1,2 +1,2 @@ patreon: assimp -ko_fi: kimkulling +Paypal: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=4JRJVPXC4QJM4 From 8fd053315ce535fca5f103c13c2d1800d4a092ab Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sun, 9 Feb 2020 11:14:42 +0100 Subject: [PATCH 038/330] Update ArmaturePopulate.cpp - Introduce tabs width of 4. - Add missing brackets - Use c++ comment blocks --- code/PostProcessing/ArmaturePopulate.cpp | 283 +++++++++++------------ 1 file changed, 138 insertions(+), 145 deletions(-) diff --git a/code/PostProcessing/ArmaturePopulate.cpp b/code/PostProcessing/ArmaturePopulate.cpp index 1514e14f2..31c99ae94 100644 --- a/code/PostProcessing/ArmaturePopulate.cpp +++ b/code/PostProcessing/ArmaturePopulate.cpp @@ -4,7 +4,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2020, assimp team - All rights reserved. Redistribution and use of this software in source and binary forms, @@ -36,7 +35,6 @@ 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. - ---------------------------------------------------------------------- */ #include "ArmaturePopulate.h" @@ -50,220 +48,215 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. namespace Assimp { /// The default class constructor. -ArmaturePopulate::ArmaturePopulate() : BaseProcess() -{} +ArmaturePopulate::ArmaturePopulate() : + BaseProcess() { + // do nothing +} /// The class destructor. -ArmaturePopulate::~ArmaturePopulate() -{} +ArmaturePopulate::~ArmaturePopulate() { + // do nothing +} bool ArmaturePopulate::IsActive(unsigned int pFlags) const { - return (pFlags & aiProcess_PopulateArmatureData) != 0; + return (pFlags & aiProcess_PopulateArmatureData) != 0; } void ArmaturePopulate::SetupProperties(const Importer *pImp) { - // do nothing + // do nothing } void ArmaturePopulate::Execute(aiScene *out) { - // Now convert all bone positions to the correct mOffsetMatrix - std::vector bones; - std::vector nodes; - std::map bone_stack; - BuildBoneList(out->mRootNode, out->mRootNode, out, bones); - BuildNodeList(out->mRootNode, nodes); + // Now convert all bone positions to the correct mOffsetMatrix + std::vector bones; + std::vector nodes; + std::map bone_stack; + BuildBoneList(out->mRootNode, out->mRootNode, out, bones); + BuildNodeList(out->mRootNode, nodes); - BuildBoneStack(out->mRootNode, out->mRootNode, out, bones, bone_stack, nodes); + BuildBoneStack(out->mRootNode, out->mRootNode, out, bones, bone_stack, nodes); - ASSIMP_LOG_DEBUG_F("Bone stack size: ", bone_stack.size()); + ASSIMP_LOG_DEBUG_F("Bone stack size: ", bone_stack.size()); - for (std::pair kvp : bone_stack) { - aiBone *bone = kvp.first; - aiNode *bone_node = kvp.second; - ASSIMP_LOG_DEBUG_F("active node lookup: ", bone->mName.C_Str()); - // lcl transform grab - done in generate_nodes :) + for (std::pair kvp : bone_stack) { + aiBone *bone = kvp.first; + aiNode *bone_node = kvp.second; + ASSIMP_LOG_DEBUG_F("active node lookup: ", bone->mName.C_Str()); + // lcl transform grab - done in generate_nodes :) - // bone->mOffsetMatrix = bone_node->mTransformation; - aiNode *armature = GetArmatureRoot(bone_node, bones); + // bone->mOffsetMatrix = bone_node->mTransformation; + aiNode *armature = GetArmatureRoot(bone_node, bones); - ai_assert(armature); + ai_assert(armature); - // set up bone armature id - bone->mArmature = armature; + // set up bone armature id + bone->mArmature = armature; - // set this bone node to be referenced properly - ai_assert(bone_node); - bone->mNode = bone_node; - } + // set this bone node to be referenced properly + ai_assert(bone_node); + bone->mNode = bone_node; + } } -/* Reprocess all nodes to calculate bone transforms properly based on the REAL - * mOffsetMatrix not the local. */ -/* Before this would use mesh transforms which is wrong for bone transforms */ -/* Before this would work for simple character skeletons but not complex meshes - * with multiple origins */ -/* Source: sketch fab log cutter fbx */ +// Reprocess all nodes to calculate bone transforms properly based on the REAL +// mOffsetMatrix not the local. +// Before this would use mesh transforms which is wrong for bone transforms +// Before this would work for simple character skeletons but not complex meshes +// with multiple origins +// Source: sketch fab log cutter fbx void ArmaturePopulate::BuildBoneList(aiNode *current_node, const aiNode *root_node, const aiScene *scene, std::vector &bones) { - ai_assert(scene); - for (unsigned int nodeId = 0; nodeId < current_node->mNumChildren; ++nodeId) { - aiNode *child = current_node->mChildren[nodeId]; - ai_assert(child); + ai_assert(scene); + for (unsigned int nodeId = 0; nodeId < current_node->mNumChildren; ++nodeId) { + aiNode *child = current_node->mChildren[nodeId]; + ai_assert(child); - // check for bones - for (unsigned int meshId = 0; meshId < child->mNumMeshes; ++meshId) { - ai_assert(child->mMeshes); - unsigned int mesh_index = child->mMeshes[meshId]; - aiMesh *mesh = scene->mMeshes[mesh_index]; - ai_assert(mesh); + // check for bones + for (unsigned int meshId = 0; meshId < child->mNumMeshes; ++meshId) { + ai_assert(child->mMeshes); + unsigned int mesh_index = child->mMeshes[meshId]; + aiMesh *mesh = scene->mMeshes[mesh_index]; + ai_assert(mesh); - for (unsigned int boneId = 0; boneId < mesh->mNumBones; ++boneId) { - aiBone *bone = mesh->mBones[boneId]; - ai_assert(bone); + for (unsigned int boneId = 0; boneId < mesh->mNumBones; ++boneId) { + aiBone *bone = mesh->mBones[boneId]; + ai_assert(bone); - // duplicate meshes exist with the same bones sometimes :) - // so this must be detected - if (std::find(bones.begin(), bones.end(), bone) == bones.end()) { - // add the element once - bones.push_back(bone); + // duplicate mehes exist with the same bones sometimes :) + // so this must be detected + if (std::find(bones.begin(), bones.end(), bone) == bones.end()) { + // add the element once + bones.push_back(bone); + } + } + + // find mesh and get bones + // then do recursive lookup for bones in root node hierarchy } - } - // find mesh and get bones - // then do recursive lookup for bones in root node hierarchy + BuildBoneList(child, root_node, scene, bones); } - - BuildBoneList(child, root_node, scene, bones); - } } -/* Prepare flat node list which can be used for non recursive lookups later */ +// Prepare flat node list which can be used for non recursive lookups later void ArmaturePopulate::BuildNodeList(const aiNode *current_node, std::vector &nodes) { - ai_assert(current_node); + ai_assert(current_node); - for (unsigned int nodeId = 0; nodeId < current_node->mNumChildren; ++nodeId) { - aiNode *child = current_node->mChildren[nodeId]; - ai_assert(child); + for (unsigned int nodeId = 0; nodeId < current_node->mNumChildren; ++nodeId) { + aiNode *child = current_node->mChildren[nodeId]; + ai_assert(child); - if (child->mNumMeshes == 0) - nodes.push_back(child); + if (child->mNumMeshes == 0) { + nodes.push_back(child); + } - BuildNodeList(child, nodes); + BuildNodeList(child, nodes); } } -/* A bone stack allows us to have multiple armatures, with the same bone names - * A bone stack allows us also to retrieve bones true transform even with - * duplicate names :) - */ +// A bone stack allows us to have multiple armatures, with the same bone names +// A bone stack allows us also to retrieve bones true transform even with +// duplicate names :) void ArmaturePopulate::BuildBoneStack(aiNode *current_node, const aiNode *root_node, const aiScene *scene, const std::vector &bones, std::map &bone_stack, - std::vector &node_stack) { - ai_assert(scene); - ai_assert(root_node); - ai_assert(!node_stack.empty()); + std::vector &node_stack) { + ai_assert(scene); + ai_assert(root_node); + ai_assert(!node_stack.empty()); - for (aiBone *bone : bones) { - ai_assert(bone); - aiNode *node = GetNodeFromStack(bone->mName, node_stack); - if (node == nullptr) { - node_stack.clear(); - BuildNodeList(root_node, node_stack); - ASSIMP_LOG_DEBUG_F("Resetting bone stack: nullptr element ", bone->mName.C_Str()); + for (aiBone *bone : bones) { + ai_assert(bone); + aiNode *node = GetNodeFromStack(bone->mName, node_stack); + if (node == nullptr) { + node_stack.clear(); + BuildNodeList(root_node, node_stack); + ASSIMP_LOG_DEBUG_F("Resetting bone stack: nullptr element ", bone->mName.C_Str()); - node = GetNodeFromStack(bone->mName, node_stack); + node = GetNodeFromStack(bone->mName, node_stack); - if (!node) { - ASSIMP_LOG_ERROR("serious import issue node for bone was not detected"); - continue; - } + if (!node) { + ASSIMP_LOG_ERROR("serious import issue node for bone was not detected"); + continue; + } + } + + ASSIMP_LOG_DEBUG_F("Successfully added bone[", bone->mName.C_Str(), "] to stack and bone node is: ", node->mName.C_Str()); + + bone_stack.insert(std::pair(bone, node)); } - - ASSIMP_LOG_DEBUG_F("Successfully added bone[", bone->mName.C_Str(), "] to stack and bone node is: ", node->mName.C_Str()); - - bone_stack.insert(std::pair(bone, node)); - } } - -/* Returns the armature root node */ -/* This is required to be detected for a bone initially, it will recurse up - * until it cannot find another bone and return the node No known failure - * points. (yet) - */ +// Returns the armature root node +// This is required to be detected for a bone initially, it will recurse up +// until it cannot find another bone and return the node No known failure +// points. (yet) aiNode *ArmaturePopulate::GetArmatureRoot(aiNode *bone_node, std::vector &bone_list) { - while (bone_node) { - if (!IsBoneNode(bone_node->mName, bone_list)) { - ASSIMP_LOG_DEBUG_F("GetArmatureRoot() Found valid armature: ", bone_node->mName.C_Str()); - return bone_node; + while (bone_node) { + if (!IsBoneNode(bone_node->mName, bone_list)) { + ASSIMP_LOG_DEBUG_F("GetArmatureRoot() Found valid armature: ", bone_node->mName.C_Str()); + return bone_node; + } + + bone_node = bone_node->mParent; } - bone_node = bone_node->mParent; - } - - ASSIMP_LOG_ERROR("GetArmatureRoot() can't find armature!"); - - return nullptr; + ASSIMP_LOG_ERROR("GetArmatureRoot() can't find armature!"); + + return nullptr; } - - -/* Simple IsBoneNode check if this could be a bone */ +// Simple IsBoneNode check if this could be a bone bool ArmaturePopulate::IsBoneNode(const aiString &bone_name, std::vector &bones) { - for (aiBone *bone : bones) { - if (bone->mName == bone_name) { - return true; + for (aiBone *bone : bones) { + if (bone->mName == bone_name) { + return true; + } } - } - return false; + return false; } -/* Pop this node by name from the stack if found */ -/* Used in multiple armature situations with duplicate node / bone names */ -/* Known flaw: cannot have nodes with bone names, will be fixed in later release - */ -/* (serious to be fixed) Known flaw: nodes which have more than one bone could - * be prematurely dropped from stack */ +// Pop this node by name from the stack if found +// Used in multiple armature situations with duplicate node / bone names +// Known flaw: cannot have nodes with bone names, will be fixed in later release +// (serious to be fixed) Known flaw: nodes which have more than one bone could +// be prematurely dropped from stack aiNode *ArmaturePopulate::GetNodeFromStack(const aiString &node_name, std::vector &nodes) { - std::vector::iterator iter; - aiNode *found = nullptr; - for (iter = nodes.begin(); iter < nodes.end(); ++iter) { - aiNode *element = *iter; - ai_assert(element); - // node valid and node name matches - if (element->mName == node_name) { - found = element; - break; + std::vector::iterator iter; + aiNode *found = nullptr; + for (iter = nodes.begin(); iter < nodes.end(); ++iter) { + aiNode *element = *iter; + ai_assert(element); + // node valid and node name matches + if (element->mName == node_name) { + found = element; + break; + } } - } - if (found != nullptr) { - ASSIMP_LOG_INFO_F("Removed node from stack: ", found->mName.C_Str()); - // now pop the element from the node list - nodes.erase(iter); + if (found != nullptr) { + ASSIMP_LOG_INFO_F("Removed node from stack: ", found->mName.C_Str()); + // now pop the element from the node list + nodes.erase(iter); - return found; - } + return found; + } - // unique names can cause this problem - ASSIMP_LOG_ERROR("[Serious] GetNodeFromStack() can't find node from stack!"); + // unique names can cause this problem + ASSIMP_LOG_ERROR("[Serious] GetNodeFromStack() can't find node from stack!"); - return nullptr; + return nullptr; } - - - } // Namespace Assimp From ca08cbcb0cfb3e966480fdaaf603cb8c8d367819 Mon Sep 17 00:00:00 2001 From: iamAdrianIusca Date: Sun, 9 Feb 2020 20:31:06 +0200 Subject: [PATCH 039/330] - don't include HunterGate.cmake if you don't enable HUNTER package manager - don't check for DirectX if you don't build the assimp tools or samples --- CMakeLists.txt | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index fd3f1b802..38ebf3480 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -41,13 +41,13 @@ CMAKE_MINIMUM_REQUIRED( VERSION 3.0 ) # Toggles the use of the hunter package manager option(HUNTER_ENABLED "Enable Hunter package manager support" OFF) -include("cmake/HunterGate.cmake") -HunterGate( +IF(HUNTER_ENABLED) + include("cmake/HunterGate.cmake") + HunterGate( URL "https://github.com/ruslo/hunter/archive/v0.23.176.tar.gz" SHA1 "2e9ae973d028660b735ac4c6142725ca36a0048a" -) + ) -IF(HUNTER_ENABLED) add_definitions(-DASSIMP_USE_HUNTER) ENDIF(HUNTER_ENABLED) @@ -437,7 +437,9 @@ ELSE(HUNTER_ENABLED) DESTINATION "${ASSIMP_LIB_INSTALL_DIR}/cmake/assimp-${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}" COMPONENT ${LIBASSIMP-DEV_COMPONENT}) ENDIF(HUNTER_ENABLED) -FIND_PACKAGE( DirectX ) +if (ASSIMP_BUILD_SAMPLES OR ASSIMP_BUILD_SAMPLES) + FIND_PACKAGE(DirectX) +endif(ASSIMP_BUILD_SAMPLES OR ASSIMP_BUILD_SAMPLES) IF( BUILD_DOCS ) ADD_SUBDIRECTORY(doc) From 58990d4e3ff84906b459164c211ce379fe63751c Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Mon, 10 Feb 2020 23:59:52 +0100 Subject: [PATCH 040/330] Update FBXParser.cpp add missing brackets. --- code/FBX/FBXParser.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/code/FBX/FBXParser.cpp b/code/FBX/FBXParser.cpp index 5486fdcc6..aef59d60c 100644 --- a/code/FBX/FBXParser.cpp +++ b/code/FBX/FBXParser.cpp @@ -368,8 +368,9 @@ float ParseTokenAsFloat(const Token& t, const char*& err_out) // which fast_atof could interpret as decimal point. #define MAX_FLOAT_LENGTH 31 const size_t length = static_cast(t.end()-t.begin()); - if (length > MAX_FLOAT_LENGTH) + if (length > MAX_FLOAT_LENGTH) { return 0.f; + } char temp[MAX_FLOAT_LENGTH + 1]; std::copy(t.begin(), t.end(), temp); From 50334086cfb693f720d18d1664d177e63d200f0d Mon Sep 17 00:00:00 2001 From: Marc-Antoine Lortie Date: Tue, 11 Feb 2020 11:42:13 -0500 Subject: [PATCH 041/330] Added missing texture types when searching for invalid textures. --- code/PostProcessing/ValidateDataStructure.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/code/PostProcessing/ValidateDataStructure.cpp b/code/PostProcessing/ValidateDataStructure.cpp index a812efb0b..6212bfb69 100644 --- a/code/PostProcessing/ValidateDataStructure.cpp +++ b/code/PostProcessing/ValidateDataStructure.cpp @@ -777,6 +777,12 @@ void ValidateDSProcess::Validate( const aiMaterial* pMaterial) SearchForInvalidTextures(pMaterial,aiTextureType_DISPLACEMENT); SearchForInvalidTextures(pMaterial,aiTextureType_LIGHTMAP); SearchForInvalidTextures(pMaterial,aiTextureType_REFLECTION); + SearchForInvalidTextures(pMaterial,aiTextureType_BASE_COLOR); + SearchForInvalidTextures(pMaterial,aiTextureType_NORMAL_CAMERA); + SearchForInvalidTextures(pMaterial,aiTextureType_EMISSION_COLOR); + SearchForInvalidTextures(pMaterial,aiTextureType_METALNESS); + SearchForInvalidTextures(pMaterial,aiTextureType_DIFFUSE_ROUGHNESS); + SearchForInvalidTextures(pMaterial,aiTextureType_AMBIENT_OCCLUSION); } // ------------------------------------------------------------------------------------------------ From 47fc3f262751c1f15e0912358dedc33abe8cd5ca Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Wed, 12 Feb 2020 14:54:00 +0100 Subject: [PATCH 042/330] Update M3DImporter.cpp Fix a memoryleak. --- code/M3D/M3DImporter.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/code/M3D/M3DImporter.cpp b/code/M3D/M3DImporter.cpp index 1c6cea766..9aee14f75 100644 --- a/code/M3D/M3DImporter.cpp +++ b/code/M3D/M3DImporter.cpp @@ -383,7 +383,13 @@ void M3DImporter::importTextures(const M3DWrapper &m3d) { // individually. In assimp there're per mesh vertex and UV lists, and they must be // indexed simultaneously. void M3DImporter::importMeshes(const M3DWrapper &m3d) { - unsigned int i, j, k, l, numpoly = 3, lastMat = M3D_INDEXMAX; + ASSIMP_LOG_DEBUG_F("M3D: importMeshes ", m3d->numface); + + if (!m3d->numface || !m3d->face || !m3d->numvertex || !m3d->vertex) { + return; + } + + unsigned int i, j, k, l, numpoly = 3, lastMat = M3D_INDEXMAX; std::vector *meshes = new std::vector(); std::vector *faces = nullptr; std::vector *vertices = nullptr; @@ -397,11 +403,6 @@ void M3DImporter::importMeshes(const M3DWrapper &m3d) { ai_assert(m3d); ai_assert(mScene->mRootNode != nullptr); - ASSIMP_LOG_DEBUG_F("M3D: importMeshes ", m3d->numface); - - if (!m3d->numface || !m3d->face || !m3d->numvertex || !m3d->vertex) { - return; - } for (i = 0; i < m3d->numface; i++) { // we must switch mesh if material changes From fc4dd6455a87fc01a9ef734d64718945207b09f2 Mon Sep 17 00:00:00 2001 From: iamAdrianIusca Date: Thu, 13 Feb 2020 00:10:07 +0200 Subject: [PATCH 043/330] minor code improvements for the obj code - make use of range for loops - make use of empty() method for the std::vector - removed unnecessary std::string initialization - use ' ' instead of " " for the find methods (should be "faster") - simplified some function - make use of emplace_back instead of push_back (should be "faster") - other small changes --- code/Obj/ObjFileImporter.cpp | 49 +++++++++++++++------------------ code/Obj/ObjFileMtlImporter.cpp | 4 +-- code/Obj/ObjFileParser.cpp | 36 ++++++++++-------------- code/Obj/ObjFileParser.h | 2 +- 4 files changed, 39 insertions(+), 52 deletions(-) diff --git a/code/Obj/ObjFileImporter.cpp b/code/Obj/ObjFileImporter.cpp index 7e2df0fc5..d73cc5b32 100644 --- a/code/Obj/ObjFileImporter.cpp +++ b/code/Obj/ObjFileImporter.cpp @@ -175,15 +175,15 @@ void ObjFileImporter::CreateDataFromImport(const ObjFile::Model* pModel, aiScene ai_assert(false); } - if (pModel->m_Objects.size() > 0) { + if (!pModel->m_Objects.empty()) { unsigned int meshCount = 0; unsigned int childCount = 0; - for(size_t index = 0; index < pModel->m_Objects.size(); ++index) { - if(pModel->m_Objects[index]) { + for (auto object : pModel->m_Objects) { + if(object) { ++childCount; - meshCount += (unsigned int)pModel->m_Objects[index]->m_Meshes.size(); + meshCount += (unsigned int)object->m_Meshes.size(); } } @@ -365,8 +365,8 @@ aiMesh *ObjFileImporter::createTopology( const ObjFile::Model* pModel, const Obj unsigned int outIndex( 0 ); // Copy all data from all stored meshes - for (size_t index = 0; index < pObjMesh->m_Faces.size(); index++) { - ObjFile::Face* const inp = pObjMesh->m_Faces[ index ]; + for (auto& face : pObjMesh->m_Faces) { + ObjFile::Face* const inp = face; if (inp->m_PrimitiveType == aiPrimitiveType_LINE) { for(size_t i = 0; i < inp->m_vertices.size() - 1; ++i) { aiFace& f = pMesh->mFaces[ outIndex++ ]; @@ -385,7 +385,7 @@ aiMesh *ObjFileImporter::createTopology( const ObjFile::Model* pModel, const Obj } aiFace *pFace = &pMesh->mFaces[ outIndex++ ]; - const unsigned int uiNumIndices = (unsigned int) pObjMesh->m_Faces[ index ]->m_vertices.size(); + const unsigned int uiNumIndices = (unsigned int) face->m_vertices.size(); uiIdxCount += pFace->mNumIndices = (unsigned int) uiNumIndices; if (pFace->mNumIndices > 0) { pFace->mIndices = new unsigned int[ uiNumIndices ]; @@ -446,13 +446,10 @@ void ObjFileImporter::createVertexArray(const ObjFile::Model* pModel, // Copy vertices, normals and textures into aiMesh instance bool normalsok = true, uvok = true; unsigned int newIndex = 0, outIndex = 0; - for ( size_t index=0; index < pObjMesh->m_Faces.size(); index++ ) { - // Get source face - ObjFile::Face *pSourceFace = pObjMesh->m_Faces[ index ]; - + for (auto sourceFace : pObjMesh->m_Faces) { // Copy all index arrays - for ( size_t vertexIndex = 0, outVertexIndex = 0; vertexIndex < pSourceFace->m_vertices.size(); vertexIndex++ ) { - const unsigned int vertex = pSourceFace->m_vertices.at( vertexIndex ); + for (size_t vertexIndex = 0, outVertexIndex = 0; vertexIndex < sourceFace->m_vertices.size(); vertexIndex++ ) { + const unsigned int vertex = sourceFace->m_vertices.at(vertexIndex ); if ( vertex >= pModel->m_Vertices.size() ) { throw DeadlyImportError( "OBJ: vertex index out of range" ); } @@ -464,8 +461,8 @@ void ObjFileImporter::createVertexArray(const ObjFile::Model* pModel, pMesh->mVertices[ newIndex ] = pModel->m_Vertices[ vertex ]; // Copy all normals - if ( normalsok && !pModel->m_Normals.empty() && vertexIndex < pSourceFace->m_normals.size()) { - const unsigned int normal = pSourceFace->m_normals.at( vertexIndex ); + if ( normalsok && !pModel->m_Normals.empty() && vertexIndex < sourceFace->m_normals.size()) { + const unsigned int normal = sourceFace->m_normals.at(vertexIndex ); if ( normal >= pModel->m_Normals.size() ) { normalsok = false; @@ -484,9 +481,9 @@ void ObjFileImporter::createVertexArray(const ObjFile::Model* pModel, } // Copy all texture coordinates - if ( uvok && !pModel->m_TextureCoord.empty() && vertexIndex < pSourceFace->m_texturCoords.size()) + if ( uvok && !pModel->m_TextureCoord.empty() && vertexIndex < sourceFace->m_texturCoords.size()) { - const unsigned int tex = pSourceFace->m_texturCoords.at( vertexIndex ); + const unsigned int tex = sourceFace->m_texturCoords.at(vertexIndex ); if ( tex >= pModel->m_TextureCoord.size() ) { @@ -502,16 +499,16 @@ void ObjFileImporter::createVertexArray(const ObjFile::Model* pModel, // Get destination face aiFace *pDestFace = &pMesh->mFaces[ outIndex ]; - const bool last = ( vertexIndex == pSourceFace->m_vertices.size() - 1 ); - if (pSourceFace->m_PrimitiveType != aiPrimitiveType_LINE || !last) { + const bool last = (vertexIndex == sourceFace->m_vertices.size() - 1 ); + if (sourceFace->m_PrimitiveType != aiPrimitiveType_LINE || !last) { pDestFace->mIndices[ outVertexIndex ] = newIndex; outVertexIndex++; } - if (pSourceFace->m_PrimitiveType == aiPrimitiveType_POINT) { + if (sourceFace->m_PrimitiveType == aiPrimitiveType_POINT) { outIndex++; outVertexIndex = 0; - } else if (pSourceFace->m_PrimitiveType == aiPrimitiveType_LINE) { + } else if (sourceFace->m_PrimitiveType == aiPrimitiveType_LINE) { outVertexIndex = 0; if(!last) @@ -520,7 +517,7 @@ void ObjFileImporter::createVertexArray(const ObjFile::Model* pModel, if (vertexIndex) { if(!last) { pMesh->mVertices[ newIndex+1 ] = pMesh->mVertices[ newIndex ]; - if ( !pSourceFace->m_normals.empty() && !pModel->m_Normals.empty()) { + if (!sourceFace->m_normals.empty() && !pModel->m_Normals.empty()) { pMesh->mNormals[ newIndex+1 ] = pMesh->mNormals[newIndex ]; } if ( !pModel->m_TextureCoord.empty() ) { @@ -563,13 +560,11 @@ void ObjFileImporter::countObjects(const std::vector &rObjects return; iNumMeshes += static_cast( rObjects.size() ); - for (std::vector::const_iterator it = rObjects.begin(); - it != rObjects.end(); - ++it) + for (auto object: rObjects) { - if (!(*it)->m_SubObjects.empty()) + if (!object->m_SubObjects.empty()) { - countObjects((*it)->m_SubObjects, iNumMeshes); + countObjects(object->m_SubObjects, iNumMeshes); } } } diff --git a/code/Obj/ObjFileMtlImporter.cpp b/code/Obj/ObjFileMtlImporter.cpp index cdd60f03c..90c70cda3 100644 --- a/code/Obj/ObjFileMtlImporter.cpp +++ b/code/Obj/ObjFileMtlImporter.cpp @@ -274,7 +274,7 @@ void ObjFileMtlImporter::getFloatValue( ai_real &value ) // Creates a material from loaded data. void ObjFileMtlImporter::createMaterial() { - std::string line( "" ); + std::string line; while( !IsLineEnd( *m_DataIt ) ) { line += *m_DataIt; ++m_DataIt; @@ -282,7 +282,7 @@ void ObjFileMtlImporter::createMaterial() std::vector token; const unsigned int numToken = tokenize( line, token, " \t" ); - std::string name( "" ); + std::string name; if ( numToken == 1 ) { name = AI_DEFAULT_MATERIAL_NAME; } else { diff --git a/code/Obj/ObjFileParser.cpp b/code/Obj/ObjFileParser.cpp index 7e3b11b23..9e1e28ae6 100644 --- a/code/Obj/ObjFileParser.cpp +++ b/code/Obj/ObjFileParser.cpp @@ -96,9 +96,6 @@ ObjFileParser::ObjFileParser( IOStreamBuffer &streamBuffer, const std::str parseFile( streamBuffer ); } -ObjFileParser::~ObjFileParser() { -} - void ObjFileParser::setBuffer( std::vector &buffer ) { m_DataIt = buffer.begin(); m_DataItEnd = buffer.end(); @@ -182,7 +179,7 @@ void ObjFileParser::parseFile( IOStreamBuffer &streamBuffer ) { getNameNoSpace(m_DataIt, m_DataItEnd, name); - size_t nextSpace = name.find(" "); + size_t nextSpace = name.find(' '); if (nextSpace != std::string::npos) name = name.substr(0, nextSpace); @@ -199,7 +196,7 @@ void ObjFileParser::parseFile( IOStreamBuffer &streamBuffer ) { getNameNoSpace(m_DataIt, m_DataItEnd, name); - size_t nextSpace = name.find(" "); + size_t nextSpace = name.find(' '); if (nextSpace != std::string::npos) name = name.substr(0, nextSpace); @@ -274,13 +271,8 @@ static bool isDataDefinitionEnd( const char *tmp ) { static bool isNanOrInf(const char * in) { // Look for "nan" or "inf", case insensitive - if ((in[0] == 'N' || in[0] == 'n') && ASSIMP_strincmp(in, "nan", 3) == 0) { - return true; - } - else if ((in[0] == 'I' || in[0] == 'i') && ASSIMP_strincmp(in, "inf", 3) == 0) { - return true; - } - return false; + return ((in[0] == 'N' || in[0] == 'n') && ASSIMP_strincmp(in, "nan", 3) == 0) || + ((in[0] == 'I' || in[0] == 'i') && ASSIMP_strincmp(in, "inf", 3) == 0); } size_t ObjFileParser::getNumComponentsInDataDefinition() { @@ -341,7 +333,7 @@ size_t ObjFileParser::getTexCoordVector( std::vector &point3d_array if (!std::isfinite(z)) z = 0; - point3d_array.push_back( aiVector3D( x, y, z ) ); + point3d_array.emplace_back( x, y, z ); m_DataIt = skipLine( m_DataIt, m_DataItEnd, m_uiLine ); return numComponents; } @@ -357,7 +349,7 @@ void ObjFileParser::getVector3( std::vector &point3d_array ) { copyNextWord( m_buffer, Buffersize ); z = ( ai_real ) fast_atof( m_buffer ); - point3d_array.push_back( aiVector3D( x, y, z ) ); + point3d_array.emplace_back( x, y, z ); m_DataIt = skipLine( m_DataIt, m_DataItEnd, m_uiLine ); } @@ -378,7 +370,7 @@ void ObjFileParser::getHomogeneousVector3( std::vector &point3d_arra if (w == 0) throw DeadlyImportError("OBJ: Invalid component in homogeneous vector (Division by zero)"); - point3d_array.push_back( aiVector3D( x/w, y/w, z/w ) ); + point3d_array.emplace_back( x/w, y/w, z/w ); m_DataIt = skipLine( m_DataIt, m_DataItEnd, m_uiLine ); } @@ -393,7 +385,7 @@ void ObjFileParser::getTwoVectors3( std::vector &point3d_array_a, st copyNextWord( m_buffer, Buffersize ); z = ( ai_real ) fast_atof( m_buffer ); - point3d_array_a.push_back( aiVector3D( x, y, z ) ); + point3d_array_a.emplace_back( x, y, z ); copyNextWord(m_buffer, Buffersize); x = (ai_real) fast_atof(m_buffer); @@ -404,7 +396,7 @@ void ObjFileParser::getTwoVectors3( std::vector &point3d_array_a, st copyNextWord( m_buffer, Buffersize ); z = ( ai_real ) fast_atof( m_buffer ); - point3d_array_b.push_back( aiVector3D( x, y, z ) ); + point3d_array_b.emplace_back( x, y, z ); m_DataIt = skipLine( m_DataIt, m_DataItEnd, m_uiLine ); } @@ -417,7 +409,7 @@ void ObjFileParser::getVector2( std::vector &point2d_array ) { copyNextWord(m_buffer, Buffersize); y = (ai_real) fast_atof(m_buffer); - point2d_array.push_back(aiVector2D(x, y)); + point2d_array.emplace_back(x, y); m_DataIt = skipLine( m_DataIt, m_DataItEnd, m_uiLine ); } @@ -439,7 +431,7 @@ void ObjFileParser::getFace( aiPrimitiveType type ) { const bool vt = (!m_pModel->m_TextureCoord.empty()); const bool vn = (!m_pModel->m_Normals.empty()); - int iStep = 0, iPos = 0; + int iStep, iPos = 0; while ( m_DataIt != m_DataItEnd ) { iStep = 1; @@ -845,18 +837,18 @@ void ObjFileParser::createMesh( const std::string &meshName ) bool ObjFileParser::needsNewMesh( const std::string &materialName ) { // If no mesh data yet - if(m_pModel->m_pCurrentMesh == 0) + if (m_pModel->m_pCurrentMesh == nullptr) { return true; } bool newMat = false; int matIdx = getMaterialIndex( materialName ); - int curMatIdx = m_pModel->m_pCurrentMesh->m_uiMaterialIndex; + unsigned int curMatIdx = m_pModel->m_pCurrentMesh->m_uiMaterialIndex; if ( curMatIdx != int(ObjFile::Mesh::NoMaterial) && curMatIdx != matIdx // no need create a new mesh if no faces in current // lets say 'usemtl' goes straight after 'g' - && m_pModel->m_pCurrentMesh->m_Faces.size() > 0 ) + && !m_pModel->m_pCurrentMesh->m_Faces.empty() ) { // New material -> only one material per mesh, so we need to create a new // material diff --git a/code/Obj/ObjFileParser.h b/code/Obj/ObjFileParser.h index 124527413..05704c981 100644 --- a/code/Obj/ObjFileParser.h +++ b/code/Obj/ObjFileParser.h @@ -80,7 +80,7 @@ public: /// @brief Constructor with data array. ObjFileParser( IOStreamBuffer &streamBuffer, const std::string &modelName, IOSystem* io, ProgressHandler* progress, const std::string &originalObjFileName); /// @brief Destructor - ~ObjFileParser(); + ~ObjFileParser() = default; /// @brief If you want to load in-core data. void setBuffer( std::vector &buffer ); /// @brief Model getter. From 24cdb1f22184adaabb9155ac303c888843e0a7b7 Mon Sep 17 00:00:00 2001 From: iamAdrianIusca Date: Thu, 13 Feb 2020 00:21:04 +0200 Subject: [PATCH 044/330] revert small change --- code/Obj/ObjFileParser.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/Obj/ObjFileParser.cpp b/code/Obj/ObjFileParser.cpp index 9e1e28ae6..e33d2e028 100644 --- a/code/Obj/ObjFileParser.cpp +++ b/code/Obj/ObjFileParser.cpp @@ -843,7 +843,7 @@ bool ObjFileParser::needsNewMesh( const std::string &materialName ) } bool newMat = false; int matIdx = getMaterialIndex( materialName ); - unsigned int curMatIdx = m_pModel->m_pCurrentMesh->m_uiMaterialIndex; + int curMatIdx = m_pModel->m_pCurrentMesh->m_uiMaterialIndex; if ( curMatIdx != int(ObjFile::Mesh::NoMaterial) && curMatIdx != matIdx // no need create a new mesh if no faces in current From 6f1870681bf5a37ac21a8fd8fb47d753431e2677 Mon Sep 17 00:00:00 2001 From: iamAdrianIusca Date: Thu, 13 Feb 2020 00:27:30 +0200 Subject: [PATCH 045/330] reduced the scope of iStep variable --- code/Obj/ObjFileParser.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/Obj/ObjFileParser.cpp b/code/Obj/ObjFileParser.cpp index e33d2e028..500325993 100644 --- a/code/Obj/ObjFileParser.cpp +++ b/code/Obj/ObjFileParser.cpp @@ -431,9 +431,9 @@ void ObjFileParser::getFace( aiPrimitiveType type ) { const bool vt = (!m_pModel->m_TextureCoord.empty()); const bool vn = (!m_pModel->m_Normals.empty()); - int iStep, iPos = 0; + int iPos = 0; while ( m_DataIt != m_DataItEnd ) { - iStep = 1; + int iStep = 1; if ( IsLineEnd( *m_DataIt ) ) { break; From 25feb77982aefd895769dc0b79a3b50e0f05dae2 Mon Sep 17 00:00:00 2001 From: iamAdrianIusca Date: Thu, 13 Feb 2020 00:38:56 +0200 Subject: [PATCH 046/330] more minor changes --- code/Obj/ObjFileParser.cpp | 3 +++ code/Obj/ObjFileParser.h | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/code/Obj/ObjFileParser.cpp b/code/Obj/ObjFileParser.cpp index 500325993..48129c02c 100644 --- a/code/Obj/ObjFileParser.cpp +++ b/code/Obj/ObjFileParser.cpp @@ -96,6 +96,9 @@ ObjFileParser::ObjFileParser( IOStreamBuffer &streamBuffer, const std::str parseFile( streamBuffer ); } +ObjFileParser::~ObjFileParser() { +} + void ObjFileParser::setBuffer( std::vector &buffer ) { m_DataIt = buffer.begin(); m_DataItEnd = buffer.end(); diff --git a/code/Obj/ObjFileParser.h b/code/Obj/ObjFileParser.h index 05704c981..124527413 100644 --- a/code/Obj/ObjFileParser.h +++ b/code/Obj/ObjFileParser.h @@ -80,7 +80,7 @@ public: /// @brief Constructor with data array. ObjFileParser( IOStreamBuffer &streamBuffer, const std::string &modelName, IOSystem* io, ProgressHandler* progress, const std::string &originalObjFileName); /// @brief Destructor - ~ObjFileParser() = default; + ~ObjFileParser(); /// @brief If you want to load in-core data. void setBuffer( std::vector &buffer ); /// @brief Model getter. From b62bd38c71293f0425a1ac5f163c746ecb7c6c5b Mon Sep 17 00:00:00 2001 From: "Hui.Du" Date: Mon, 10 Feb 2020 02:03:26 +0000 Subject: [PATCH 047/330] Fix: GLTF animation works on RTS not matrix; fix matrix related bug. --- code/glTF/glTFAsset.h | 1 + code/glTF/glTFAssetWriter.inl | 4 +++- code/glTF/glTFExporter.cpp | 20 +++++++--------- code/glTF2/glTF2Asset.h | 1 + code/glTF2/glTF2AssetWriter.inl | 8 +++---- code/glTF2/glTF2Exporter.cpp | 42 +++++++++++++++++++++++---------- 6 files changed, 46 insertions(+), 30 deletions(-) diff --git a/code/glTF/glTFAsset.h b/code/glTF/glTFAsset.h index d0b72703e..b918d456b 100644 --- a/code/glTF/glTFAsset.h +++ b/code/glTF/glTFAsset.h @@ -191,6 +191,7 @@ namespace glTF //! Values for the BufferView::target field enum BufferViewTarget { + BufferViewTarget_NONE = 0, BufferViewTarget_ARRAY_BUFFER = 34962, BufferViewTarget_ELEMENT_ARRAY_BUFFER = 34963 }; diff --git a/code/glTF/glTFAssetWriter.inl b/code/glTF/glTFAssetWriter.inl index 784264488..6abe7e078 100644 --- a/code/glTF/glTFAssetWriter.inl +++ b/code/glTF/glTFAssetWriter.inl @@ -203,7 +203,9 @@ namespace glTF { obj.AddMember("buffer", Value(bv.buffer->id, w.mAl).Move(), w.mAl); obj.AddMember("byteOffset", static_cast(bv.byteOffset), w.mAl); obj.AddMember("byteLength", static_cast(bv.byteLength), w.mAl); - obj.AddMember("target", int(bv.target), w.mAl); + if (bv.target != BufferViewTarget_NONE) { + obj.AddMember("target", int(bv.target), w.mAl); + } } inline void Write(Value& /*obj*/, Camera& /*c*/, AssetWriter& /*w*/) diff --git a/code/glTF/glTFExporter.cpp b/code/glTF/glTFExporter.cpp index 072234891..7c21b738b 100644 --- a/code/glTF/glTFExporter.cpp +++ b/code/glTF/glTFExporter.cpp @@ -160,10 +160,7 @@ static void CopyValue(const aiMatrix4x4& v, glTF::mat4& o) static void CopyValue(const aiMatrix4x4& v, aiMatrix4x4& o) { - o.a1 = v.a1; o.a2 = v.a2; o.a3 = v.a3; o.a4 = v.a4; - o.b1 = v.b1; o.b2 = v.b2; o.b3 = v.b3; o.b4 = v.b4; - o.c1 = v.c1; o.c2 = v.c2; o.c3 = v.c3; o.c4 = v.c4; - o.d1 = v.d1; o.d2 = v.d2; o.d3 = v.d3; o.d4 = v.d4; + memcpy(&o, &v, sizeof(aiMatrix4x4)); } static void IdentityMatrix4(glTF::mat4& o) @@ -230,9 +227,8 @@ inline void SetAccessorRange(ComponentType compType, Ref acc, void* da } } -inline Ref ExportData(Asset& a, std::string& meshName, Ref& buffer, - unsigned int count, void* data, AttribType::Value typeIn, AttribType::Value typeOut, ComponentType compType, bool isIndices = false) -{ +inline Ref ExportData(Asset &a, std::string &meshName, Ref &buffer, + unsigned int count, void *data, AttribType::Value typeIn, AttribType::Value typeOut, ComponentType compType, BufferViewTarget target = BufferViewTarget_NONE) { if (!count || !data) return Ref(); unsigned int numCompsIn = AttribType::GetNumComponents(typeIn); @@ -251,7 +247,7 @@ inline Ref ExportData(Asset& a, std::string& meshName, Ref& bu bv->buffer = buffer; bv->byteOffset = unsigned(offset); bv->byteLength = length; //! The target that the WebGL buffer should be bound to. - bv->target = isIndices ? BufferViewTarget_ELEMENT_ARRAY_BUFFER : BufferViewTarget_ARRAY_BUFFER; + bv->target = target; // accessor Ref acc = a.accessors.Create(a.FindUniqueID(meshName, "accessor")); @@ -616,13 +612,13 @@ void glTFExporter::ExportMeshes() // If compression is used then you need parameters of uncompressed region: begin and size. At this step "begin" is stored. if(comp_allow) idx_srcdata_begin = b->byteLength; - Ref v = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mVertices, AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT); + Ref v = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mVertices, AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT, BufferViewTarget_ARRAY_BUFFER); if (v) p.attributes.position.push_back(v); /******************** Normals ********************/ if(comp_allow && (aim->mNormals != 0)) idx_srcdata_normal = b->byteLength;// Store index of normals array. - Ref n = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mNormals, AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT); + Ref n = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mNormals, AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT, BufferViewTarget_ARRAY_BUFFER); if (n) p.attributes.normal.push_back(n); /************** Texture coordinates **************/ @@ -639,7 +635,7 @@ void glTFExporter::ExportMeshes() if(comp_allow) idx_srcdata_tc.push_back(b->byteLength);// Store index of texture coordinates array. - Ref tc = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mTextureCoords[i], AttribType::VEC3, type, ComponentType_FLOAT, false); + Ref tc = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mTextureCoords[i], AttribType::VEC3, type, ComponentType_FLOAT, BufferViewTarget_ARRAY_BUFFER); if (tc) p.attributes.texcoord.push_back(tc); } } @@ -657,7 +653,7 @@ void glTFExporter::ExportMeshes() } } - p.indices = ExportData(*mAsset, meshId, b, unsigned(indices.size()), &indices[0], AttribType::SCALAR, AttribType::SCALAR, ComponentType_UNSIGNED_SHORT, true); + p.indices = ExportData(*mAsset, meshId, b, unsigned(indices.size()), &indices[0], AttribType::SCALAR, AttribType::SCALAR, ComponentType_UNSIGNED_SHORT, BufferViewTarget_ELEMENT_ARRAY_BUFFER); } switch (aim->mPrimitiveTypes) { diff --git a/code/glTF2/glTF2Asset.h b/code/glTF2/glTF2Asset.h index 53774de7a..d3c1654d0 100644 --- a/code/glTF2/glTF2Asset.h +++ b/code/glTF2/glTF2Asset.h @@ -198,6 +198,7 @@ namespace glTF2 //! Values for the BufferView::target field enum BufferViewTarget { + BufferViewTarget_NONE = 0, BufferViewTarget_ARRAY_BUFFER = 34962, BufferViewTarget_ELEMENT_ARRAY_BUFFER = 34963 }; diff --git a/code/glTF2/glTF2AssetWriter.inl b/code/glTF2/glTF2AssetWriter.inl index 02c14980d..8adc20404 100644 --- a/code/glTF2/glTF2AssetWriter.inl +++ b/code/glTF2/glTF2AssetWriter.inl @@ -176,13 +176,13 @@ namespace glTF2 { valSampler.AddMember("input", s.input->index, w.mAl); switch (s.interpolation) { case Interpolation_LINEAR: - valSampler.AddMember("path", "LINEAR", w.mAl); + valSampler.AddMember("interpolation", "LINEAR", w.mAl); break; case Interpolation_STEP: - valSampler.AddMember("path", "STEP", w.mAl); + valSampler.AddMember("interpolation", "STEP", w.mAl); break; case Interpolation_CUBICSPLINE: - valSampler.AddMember("path", "CUBICSPLINE", w.mAl); + valSampler.AddMember("interpolation", "CUBICSPLINE", w.mAl); break; } valSampler.AddMember("output", s.output->index, w.mAl); @@ -209,7 +209,7 @@ namespace glTF2 { if (bv.byteStride != 0) { obj.AddMember("byteStride", bv.byteStride, w.mAl); } - if (bv.target != 0) { + if (bv.target != BufferViewTarget_NONE) { obj.AddMember("target", int(bv.target), w.mAl); } } diff --git a/code/glTF2/glTF2Exporter.cpp b/code/glTF2/glTF2Exporter.cpp index 1bfee4491..35dac57e6 100644 --- a/code/glTF2/glTF2Exporter.cpp +++ b/code/glTF2/glTF2Exporter.cpp @@ -141,10 +141,7 @@ static void CopyValue(const aiMatrix4x4& v, mat4& o) { } static void CopyValue(const aiMatrix4x4& v, aiMatrix4x4& o) { - o.a1 = v.a1; o.a2 = v.a2; o.a3 = v.a3; o.a4 = v.a4; - o.b1 = v.b1; o.b2 = v.b2; o.b3 = v.b3; o.b4 = v.b4; - o.c1 = v.c1; o.c2 = v.c2; o.c3 = v.c3; o.c4 = v.c4; - o.d1 = v.d1; o.d2 = v.d2; o.d3 = v.d3; o.d4 = v.d4; + memcpy(&o, &v, sizeof(aiMatrix4x4)); } static void IdentityMatrix4(mat4& o) { @@ -211,7 +208,7 @@ inline void SetAccessorRange(ComponentType compType, Ref acc, void* da } inline Ref ExportData(Asset& a, std::string& meshName, Ref& buffer, - size_t count, void* data, AttribType::Value typeIn, AttribType::Value typeOut, ComponentType compType, bool isIndices = false) + size_t count, void* data, AttribType::Value typeIn, AttribType::Value typeOut, ComponentType compType, BufferViewTarget target = BufferViewTarget_NONE) { if (!count || !data) { return Ref(); @@ -234,7 +231,7 @@ inline Ref ExportData(Asset& a, std::string& meshName, Ref& bu bv->byteOffset = offset; bv->byteLength = length; //! The target that the WebGL buffer should be bound to. bv->byteStride = 0; - bv->target = isIndices ? BufferViewTarget_ELEMENT_ARRAY_BUFFER : BufferViewTarget_ARRAY_BUFFER; + bv->target = target; // accessor Ref acc = a.accessors.Create(a.FindUniqueID(meshName, "accessor")); @@ -747,7 +744,7 @@ void glTF2Exporter::ExportMeshes() p.material = mAsset->materials.Get(aim->mMaterialIndex); /******************* Vertices ********************/ - Ref v = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mVertices, AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT); + Ref v = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mVertices, AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT, BufferViewTarget_ARRAY_BUFFER); if (v) p.attributes.position.push_back(v); /******************** Normals ********************/ @@ -758,7 +755,7 @@ void glTF2Exporter::ExportMeshes() } } - Ref n = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mNormals, AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT); + Ref n = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mNormals, AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT, BufferViewTarget_ARRAY_BUFFER); if (n) p.attributes.normal.push_back(n); /************** Texture coordinates **************/ @@ -776,14 +773,14 @@ void glTF2Exporter::ExportMeshes() if (aim->mNumUVComponents[i] > 0) { AttribType::Value type = (aim->mNumUVComponents[i] == 2) ? AttribType::VEC2 : AttribType::VEC3; - Ref tc = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mTextureCoords[i], AttribType::VEC3, type, ComponentType_FLOAT, false); + Ref tc = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mTextureCoords[i], AttribType::VEC3, type, ComponentType_FLOAT, BufferViewTarget_ARRAY_BUFFER); if (tc) p.attributes.texcoord.push_back(tc); } } /*************** Vertex colors ****************/ for (unsigned int indexColorChannel = 0; indexColorChannel < aim->GetNumColorChannels(); ++indexColorChannel) { - Ref c = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mColors[indexColorChannel], AttribType::VEC4, AttribType::VEC4, ComponentType_FLOAT, false); + Ref c = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mColors[indexColorChannel], AttribType::VEC4, AttribType::VEC4, ComponentType_FLOAT, BufferViewTarget_ARRAY_BUFFER); if (c) p.attributes.color.push_back(c); } @@ -799,7 +796,7 @@ void glTF2Exporter::ExportMeshes() } } - p.indices = ExportData(*mAsset, meshId, b, indices.size(), &indices[0], AttribType::SCALAR, AttribType::SCALAR, ComponentType_UNSIGNED_INT, true); + p.indices = ExportData(*mAsset, meshId, b, indices.size(), &indices[0], AttribType::SCALAR, AttribType::SCALAR, ComponentType_UNSIGNED_INT, BufferViewTarget_ELEMENT_ARRAY_BUFFER); } switch (aim->mPrimitiveTypes) { @@ -956,8 +953,27 @@ unsigned int glTF2Exporter::ExportNode(const aiNode* n, Ref& parent) node->name = name; if (!n->mTransformation.IsIdentity()) { - node->matrix.isPresent = true; - CopyValue(n->mTransformation, node->matrix.value); + if (mScene->mNumAnimations > 0) { + aiQuaternion quaternion; + n->mTransformation.Decompose(*reinterpret_cast(&node->scale.value), quaternion, *reinterpret_cast(&node->translation.value)); + + aiVector3D vector(static_cast(1.0f), static_cast(1.0f), static_cast(1.0f)); + if (!reinterpret_cast(&node->scale.value)->Equal(vector)) { + node->scale.isPresent = true; + } + if (!reinterpret_cast(&node->translation.value)->Equal(vector)) { + node->translation.isPresent = true; + } + node->rotation.isPresent = true; + node->rotation.value[0] = quaternion.x; + node->rotation.value[1] = quaternion.y; + node->rotation.value[2] = quaternion.z; + node->rotation.value[3] = quaternion.w; + node->matrix.isPresent = false; + } else { + node->matrix.isPresent = true; + CopyValue(n->mTransformation, node->matrix.value); + } } for (unsigned int i = 0; i < n->mNumMeshes; ++i) { From d04df3e7c52e5566c30875236567a1656b365d9f Mon Sep 17 00:00:00 2001 From: Inho Lee Date: Fri, 14 Feb 2020 08:41:55 +0100 Subject: [PATCH 048/330] A bug when importing multiple gltf files meshOffsets are not cleared when importing multiple gltf files --- code/glTF/glTFImporter.cpp | 1 + code/glTF2/glTF2Importer.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/code/glTF/glTFImporter.cpp b/code/glTF/glTFImporter.cpp index 16addc977..b410e1002 100644 --- a/code/glTF/glTFImporter.cpp +++ b/code/glTF/glTFImporter.cpp @@ -222,6 +222,7 @@ void glTFImporter::ImportMeshes(glTF::Asset& r) std::vector meshes; unsigned int k = 0; + meshOffsets.clear(); for (unsigned int m = 0; m < r.meshes.Size(); ++m) { Mesh& mesh = r.meshes[m]; diff --git a/code/glTF2/glTF2Importer.cpp b/code/glTF2/glTF2Importer.cpp index af98076a7..7a0a92d7c 100644 --- a/code/glTF2/glTF2Importer.cpp +++ b/code/glTF2/glTF2Importer.cpp @@ -335,6 +335,7 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) { std::vector meshes; unsigned int k = 0; + meshOffsets.clear(); for (unsigned int m = 0; m < r.meshes.Size(); ++m) { Mesh &mesh = r.meshes[m]; From 1e828cb8bb18218735a8a5fa00f18ba2c544f7bd Mon Sep 17 00:00:00 2001 From: Justin Carpentier Date: Fri, 14 Feb 2020 15:57:06 +0100 Subject: [PATCH 049/330] pkg-config: fix include path --- assimp.pc.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assimp.pc.in b/assimp.pc.in index c659e19f2..02cf59dc4 100644 --- a/assimp.pc.in +++ b/assimp.pc.in @@ -1,7 +1,7 @@ prefix=@CMAKE_INSTALL_PREFIX@ exec_prefix=@CMAKE_INSTALL_PREFIX@/ libdir=@CMAKE_INSTALL_PREFIX@/@ASSIMP_LIB_INSTALL_DIR@ -includedir=@CMAKE_INSTALL_PREFIX@/../include/@ASSIMP_INCLUDE_INSTALL_DIR@ +includedir=@CMAKE_INSTALL_PREFIX@/@ASSIMP_INCLUDE_INSTALL_DIR@ Name: @CMAKE_PROJECT_NAME@ Description: Import various well-known 3D model formats in an uniform manner. From 693aa5c1d60a25efa1550fe4d2a34ac22b233bd9 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Fri, 14 Feb 2020 20:50:17 +0100 Subject: [PATCH 050/330] Enable all warnings for Visual Studio. --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 38ebf3480..a1bce5c92 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -255,8 +255,8 @@ IF ((CMAKE_C_COMPILER_ID MATCHES "GNU") AND NOT CMAKE_COMPILER_IS_MINGW) SET(LIBSTDC++_LIBRARIES -lstdc++) ELSEIF(MSVC) # enable multi-core compilation with MSVC - ADD_COMPILE_OPTIONS(/MP) - ADD_COMPILE_OPTIONS( /bigobj ) + ADD_COMPILE_OPTIONS(/MP /bigobj /W4 /WX ) + ADD_COMPILE_OPTIONS( ) # disable "elements of array '' will be default initialized" warning on MSVC2013 IF(MSVC12) ADD_COMPILE_OPTIONS(/wd4351) From b072614fad0f4dffd90934808b12fb06d0fc72d5 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sat, 15 Feb 2020 11:40:26 +0100 Subject: [PATCH 051/330] disable warnings for zib. --- contrib/zlib/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/contrib/zlib/CMakeLists.txt b/contrib/zlib/CMakeLists.txt index 9d1fcc943..c90996c0b 100644 --- a/contrib/zlib/CMakeLists.txt +++ b/contrib/zlib/CMakeLists.txt @@ -72,6 +72,7 @@ endif() check_include_file(unistd.h Z_HAVE_UNISTD_H) if(MSVC) + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /wd4131 /wd4127 /wd4244") set(CMAKE_DEBUG_POSTFIX "d") add_definitions(-D_CRT_SECURE_NO_DEPRECATE) add_definitions(-D_CRT_NONSTDC_NO_DEPRECATE) From 4a3ecbea14f009ac9a9cf8fca102f145b701706f Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sat, 15 Feb 2020 11:43:35 +0100 Subject: [PATCH 052/330] disable arning for irrXml. --- contrib/irrXML/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/contrib/irrXML/CMakeLists.txt b/contrib/irrXML/CMakeLists.txt index 7f58af3d8..48eec8328 100644 --- a/contrib/irrXML/CMakeLists.txt +++ b/contrib/irrXML/CMakeLists.txt @@ -9,6 +9,7 @@ set( IrrXML_SRCS ) if ( MSVC ) + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4127") ADD_DEFINITIONS( -D_SCL_SECURE_NO_WARNINGS ) ADD_DEFINITIONS( -D_CRT_SECURE_NO_WARNINGS ) endif ( MSVC ) From be4fe131d5fee47c6e407e76f46b12edf29edba9 Mon Sep 17 00:00:00 2001 From: Marc-Antoine Lortie Date: Sat, 15 Feb 2020 13:10:11 -0500 Subject: [PATCH 053/330] Made changes to write compiled binaries to a common directory. The following changes were tested with the following projects: - assimp DLL - unit tests - tools/assimp_cmd - tools/assimp viewer - samples/SimpleOpenGL - samples/SimpleTexturedDirectx11 - samples/SimpleTexturedOpenGL For each program listed above, the results were tested when (CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR) is true and false. Also, the "lib" in SET (CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_HOME_DIRECTORY}/lib") was changed to "bin" to allow DLLs to be written to executables/launchables programs directory. --- CMakeLists.txt | 6 +++++- test/CMakeLists.txt | 7 ------- tools/assimp_cmd/CMakeLists.txt | 7 ------- tools/assimp_view/CMakeLists.txt | 7 ------- 4 files changed, 5 insertions(+), 22 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 38ebf3480..08a1f3010 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -342,9 +342,13 @@ INCLUDE (PrecompiledHeader) # source tree. During an out-of-source build, however, do not litter this # directory, since that is probably what the user wanted to avoid. IF ( CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR ) - SET( CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_HOME_DIRECTORY}/lib" ) + SET( CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_HOME_DIRECTORY}/bin" ) SET( CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_HOME_DIRECTORY}/lib" ) SET( CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_HOME_DIRECTORY}/bin" ) +ELSE() + SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/lib") + SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin") + SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin") ENDIF ( CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR ) # Cache these to allow the user to override them manually. diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 8624a065f..b1d918a86 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -205,13 +205,6 @@ ELSE( WIN32 ) SET( platform_libs pthread ) ENDIF( WIN32 ) -IF( WIN32 ) - ADD_CUSTOM_COMMAND(TARGET unit - PRE_BUILD - COMMAND ${CMAKE_COMMAND} -E copy_if_different $ $ - MAIN_DEPENDENCY assimp) -ENDIF( WIN32 ) - IF(MSVC) add_definitions(-D_CRT_SECURE_NO_WARNINGS) ENDIF(MSVC) diff --git a/tools/assimp_cmd/CMakeLists.txt b/tools/assimp_cmd/CMakeLists.txt index fcf36c356..848b8f81c 100644 --- a/tools/assimp_cmd/CMakeLists.txt +++ b/tools/assimp_cmd/CMakeLists.txt @@ -61,13 +61,6 @@ ADD_EXECUTABLE( assimp_cmd SET_PROPERTY(TARGET assimp_cmd PROPERTY DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX}) -IF( WIN32 ) - ADD_CUSTOM_COMMAND(TARGET assimp_cmd - PRE_BUILD - COMMAND ${CMAKE_COMMAND} -E copy_if_different $ $ - MAIN_DEPENDENCY assimp) -ENDIF( WIN32 ) - TARGET_LINK_LIBRARIES( assimp_cmd assimp ${ZLIB_LIBRARIES} ) SET_TARGET_PROPERTIES( assimp_cmd PROPERTIES OUTPUT_NAME assimp diff --git a/tools/assimp_view/CMakeLists.txt b/tools/assimp_view/CMakeLists.txt index 001444e0e..dc1cee0d2 100644 --- a/tools/assimp_view/CMakeLists.txt +++ b/tools/assimp_view/CMakeLists.txt @@ -92,13 +92,6 @@ IF ( MSVC ) REMOVE_DEFINITIONS( -DUNICODE -D_UNICODE ) ENDIF ( MSVC ) - -# -ADD_CUSTOM_COMMAND(TARGET assimp_viewer - PRE_BUILD - COMMAND ${CMAKE_COMMAND} -E copy_if_different $ $ - MAIN_DEPENDENCY assimp) - # Link the executable to the assimp + dx libs. TARGET_LINK_LIBRARIES ( assimp_viewer assimp ${DirectX_LIBRARY} ${DirectX_D3DX9_LIBRARY} comctl32.lib winmm.lib ) From 5c99d6a864f9e2fc43960eb3113f212f32c7cb21 Mon Sep 17 00:00:00 2001 From: iamAdrianIusca Date: Sat, 15 Feb 2020 23:29:04 +0200 Subject: [PATCH 054/330] very small changes - FIND_PACKAGE(DirectX) is already used in the samples and assimp tool cmake files - so is not needed in the main cmake fil - other small changes --- CMakeLists.txt | 4 ---- code/Obj/ObjFileParser.cpp | 17 ++++++++--------- code/Obj/ObjFileParser.h | 4 ++-- 3 files changed, 10 insertions(+), 15 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 38ebf3480..7be4f6d5f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -437,10 +437,6 @@ ELSE(HUNTER_ENABLED) DESTINATION "${ASSIMP_LIB_INSTALL_DIR}/cmake/assimp-${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}" COMPONENT ${LIBASSIMP-DEV_COMPONENT}) ENDIF(HUNTER_ENABLED) -if (ASSIMP_BUILD_SAMPLES OR ASSIMP_BUILD_SAMPLES) - FIND_PACKAGE(DirectX) -endif(ASSIMP_BUILD_SAMPLES OR ASSIMP_BUILD_SAMPLES) - IF( BUILD_DOCS ) ADD_SUBDIRECTORY(doc) ENDIF( BUILD_DOCS ) diff --git a/code/Obj/ObjFileParser.cpp b/code/Obj/ObjFileParser.cpp index 48129c02c..8b1572067 100644 --- a/code/Obj/ObjFileParser.cpp +++ b/code/Obj/ObjFileParser.cpp @@ -53,6 +53,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include +#include namespace Assimp { @@ -71,19 +73,19 @@ ObjFileParser::ObjFileParser() ObjFileParser::ObjFileParser( IOStreamBuffer &streamBuffer, const std::string &modelName, IOSystem *io, ProgressHandler* progress, - const std::string &originalObjFileName) : + std::string originalObjFileName) : m_DataIt(), m_DataItEnd(), m_pModel(nullptr), m_uiLine(0), - m_pIO( io ), + m_pIO(io), m_progress(progress), - m_originalObjFileName(originalObjFileName) + m_originalObjFileName(std::move(originalObjFileName)) { - std::fill_n(m_buffer,Buffersize,0); + std::fill_n(m_buffer, Buffersize,0); // Create the model instance to store all the data - m_pModel.reset(new ObjFile::Model()); + m_pModel = std::make_unique(); m_pModel->m_ModelName = modelName; // create default material and store it @@ -96,9 +98,6 @@ ObjFileParser::ObjFileParser( IOStreamBuffer &streamBuffer, const std::str parseFile( streamBuffer ); } -ObjFileParser::~ObjFileParser() { -} - void ObjFileParser::setBuffer( std::vector &buffer ) { m_DataIt = buffer.begin(); m_DataItEnd = buffer.end(); @@ -128,7 +127,7 @@ void ObjFileParser::parseFile( IOStreamBuffer &streamBuffer ) { processed = static_cast(filePos); lastFilePos = filePos; progressCounter++; - m_progress->UpdateFileRead( processed, progressTotal ); + m_progress->UpdateFileRead(processed, progressTotal); } // parse line diff --git a/code/Obj/ObjFileParser.h b/code/Obj/ObjFileParser.h index 124527413..9bbee66dd 100644 --- a/code/Obj/ObjFileParser.h +++ b/code/Obj/ObjFileParser.h @@ -78,9 +78,9 @@ public: /// @brief The default constructor. ObjFileParser(); /// @brief Constructor with data array. - ObjFileParser( IOStreamBuffer &streamBuffer, const std::string &modelName, IOSystem* io, ProgressHandler* progress, const std::string &originalObjFileName); + ObjFileParser(IOStreamBuffer &streamBuffer, const std::string &modelName, IOSystem* io, ProgressHandler* progress, std::string originalObjFileName); /// @brief Destructor - ~ObjFileParser(); + ~ObjFileParser() = default; /// @brief If you want to load in-core data. void setBuffer( std::vector &buffer ); /// @brief Model getter. From d9042e46098a903de391e74ac1f5f12340c3cfee Mon Sep 17 00:00:00 2001 From: Marc-Antoine Lortie Date: Sat, 15 Feb 2020 18:02:12 -0500 Subject: [PATCH 055/330] Fixed SimpleTexturedOpenGL sample. Several places in the sample's code were calling Unicode versions of Win32 functions with "multibyte" strings. A few changes were required to fix it. I added a class "UTFConverter", which handles calls to unicode/multibyte string conversions. This should help minimize the impacts on code change in case C++'s codecvt_utf8 ever changes. In addition, seveal memory leaks have been found, but these fixes will come in another PR because it goes beyond the scope of this PR. DevIL.lib was removed in CMakeFiles.txt, as it is unused in the sample. Here is a list of the changes: - Fixed MB string calls to Unicode functions. - Added class UTFConverter to handle string conversions. - Removed reference to DevIL.lib. - Fixed compile warnings. --- samples/SimpleTexturedOpenGL/CMakeLists.txt | 2 +- .../src/model_loading.cpp | 74 +++++++++++++------ 2 files changed, 54 insertions(+), 22 deletions(-) diff --git a/samples/SimpleTexturedOpenGL/CMakeLists.txt b/samples/SimpleTexturedOpenGL/CMakeLists.txt index 40138c49b..941e18cea 100644 --- a/samples/SimpleTexturedOpenGL/CMakeLists.txt +++ b/samples/SimpleTexturedOpenGL/CMakeLists.txt @@ -35,7 +35,7 @@ ADD_EXECUTABLE( assimp_simpletexturedogl WIN32 SET_PROPERTY(TARGET assimp_simpletexturedogl PROPERTY DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX}) -TARGET_LINK_LIBRARIES( assimp_simpletexturedogl assimp ${OPENGL_LIBRARIES} ${GLUT_LIBRARIES} DevIL.lib ) +TARGET_LINK_LIBRARIES( assimp_simpletexturedogl assimp ${OPENGL_LIBRARIES} ${GLUT_LIBRARIES} ) SET_TARGET_PROPERTIES( assimp_simpletexturedogl PROPERTIES OUTPUT_NAME assimp_simpletexturedogl diff --git a/samples/SimpleTexturedOpenGL/SimpleTexturedOpenGL/src/model_loading.cpp b/samples/SimpleTexturedOpenGL/SimpleTexturedOpenGL/src/model_loading.cpp index 8d25aaaed..8428248d1 100644 --- a/samples/SimpleTexturedOpenGL/SimpleTexturedOpenGL/src/model_loading.cpp +++ b/samples/SimpleTexturedOpenGL/SimpleTexturedOpenGL/src/model_loading.cpp @@ -21,6 +21,8 @@ #define STB_IMAGE_IMPLEMENTATION #include "contrib/stb_image/stb_image.h" +#include +#include #include //to map image filenames to textureIds @@ -75,6 +77,36 @@ GLuint* textureIds; // pointer to texture Array // Create an instance of the Importer class Assimp::Importer importer; +// Used to convert between multibyte and unicode strings. +class UTFConverter { + using UTFConverterImpl = std::wstring_convert, wchar_t>; +public: + UTFConverter(const char* s) : + s_(s), + ws_(impl_.from_bytes(s)) { + } + UTFConverter(const std::string& s) : + s_(s), + ws_(impl_.from_bytes(s)) { + } + UTFConverter(const std::wstring& s) : + s_(impl_.to_bytes(s)), + ws_(s) { + } + inline const std::string& str() const { + return s_; + } + inline const wchar_t* c_wstr() const { + return ws_.c_str(); + } +private: + static UTFConverterImpl impl_; + std::string s_; + std::wstring ws_; +}; + +typename UTFConverter::UTFConverterImpl UTFConverter::impl_; + void createAILogger() { // Change this line to normal if you not want to analyse the import process @@ -120,7 +152,7 @@ bool Import3DFromFile( const std::string& pFile) } else { - MessageBox(NULL, ("Couldn't open file: " + pFile).c_str() , "ERROR", MB_OK | MB_ICONEXCLAMATION); + MessageBox(NULL, UTFConverter("Couldn't open file: " + pFile).c_wstr() , TEXT("ERROR"), MB_OK | MB_ICONEXCLAMATION); logInfo( importer.GetErrorString()); return false; } @@ -205,7 +237,7 @@ int LoadGLTextures(const aiScene* scene) } } - int numTextures = textureIdMap.size(); + const size_t numTextures = textureIdMap.size(); /* array with DevIL image IDs */ @@ -217,13 +249,13 @@ int LoadGLTextures(const aiScene* scene) /* create and fill array with GL texture ids */ textureIds = new GLuint[numTextures]; - glGenTextures(numTextures, textureIds); /* Texture name generation */ + glGenTextures(static_cast(numTextures), textureIds); /* Texture name generation */ /* get iterator */ std::map::iterator itr = textureIdMap.begin(); std::string basepath = getBasePath(modelpath); - for (int i=0; i 1) { std::wstring modelpathW(argv[1]); - modelpath = std::string(modelpathW.begin(), modelpathW.end()); + modelpath = UTFConverter(modelpathW).str(); } if (!Import3DFromFile(modelpath)) return 0; logInfo("=============== Post Import ===================="); - if (MessageBox(NULL, "Would You Like To Run In Fullscreen Mode?", "Start Fullscreen?", MB_YESNO|MB_ICONEXCLAMATION)==IDNO) + if (MessageBox(NULL, TEXT("Would You Like To Run In Fullscreen Mode?"), TEXT("Start Fullscreen?"), MB_YESNO|MB_ICONEXCLAMATION)==IDNO) { fullscreen=FALSE; } @@ -881,5 +913,5 @@ int WINAPI WinMain( HINSTANCE hInstance, // The instance destroyAILogger(); KillGLWindow(); - return (msg.wParam); + return static_cast(msg.wParam); } From eb8abfa02cc76f41ce93f3832972fb490f3b9321 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sun, 16 Feb 2020 12:37:46 +0100 Subject: [PATCH 056/330] Update .clang-format Disable tabs. --- .clang-format | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.clang-format b/.clang-format index eba6d586f..70e0945fe 100644 --- a/.clang-format +++ b/.clang-format @@ -108,7 +108,7 @@ IndentWidth: 4 # SpacesInParentheses: false # SpacesInSquareBrackets: false TabWidth: 4 -UseTab: Always +UseTab: Never --- ### C++ specific config ### Language: Cpp From b3d894ee739afc1abd7e84b4cef3f083526a67d6 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sun, 16 Feb 2020 13:06:38 +0100 Subject: [PATCH 057/330] Update CMakeLists.txt temporary disable iiXml test until xml-parser migration is ready. --- test/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 6cfa16c93..084d7fd77 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -137,7 +137,7 @@ SET( IMPORTERS unit/ImportExport/MDL/utMDLImporter_HL1_ImportSettings.cpp unit/ImportExport/MDL/utMDLImporter_HL1_Materials.cpp unit/ImportExport/MDL/utMDLImporter_HL1_Nodes.cpp - unit/ImportExport/IRR/utIrrImportExport.cpp + #unit/ImportExport/IRR/utIrrImportExport.cpp unit/ImportExport/RAW/utRAWImportExport.cpp ) From ec3a5620d0992d652fa03a2b7355c02d390f66f2 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sun, 16 Feb 2020 15:04:18 +0100 Subject: [PATCH 058/330] Update AssxmlExporter.cpp Fix the build. --- code/Assxml/AssxmlExporter.cpp | 568 --------------------------------- 1 file changed, 568 deletions(-) diff --git a/code/Assxml/AssxmlExporter.cpp b/code/Assxml/AssxmlExporter.cpp index d40f6ed57..ac2a433dd 100644 --- a/code/Assxml/AssxmlExporter.cpp +++ b/code/Assxml/AssxmlExporter.cpp @@ -51,574 +51,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include namespace Assimp { -namespace AssxmlExport { - -// ----------------------------------------------------------------------------------- -static int ioprintf( IOStream * io, const char *format, ... ) { - using namespace std; - if ( nullptr == io ) { - return -1; - } - - static const int Size = 4096; - char sz[ Size ]; - ::memset( sz, '\0', Size ); - va_list va; - va_start( va, format ); - const unsigned int nSize = vsnprintf( sz, Size-1, format, va ); - ai_assert( nSize < Size ); - va_end( va ); - - io->Write( sz, sizeof(char), nSize ); - - return nSize; -} - -// ----------------------------------------------------------------------------------- -// Convert a name to standard XML format -static void ConvertName(aiString& out, const aiString& in) { - out.length = 0; - for (unsigned int i = 0; i < in.length; ++i) { - switch (in.data[i]) { - case '<': - out.Append("<");break; - case '>': - out.Append(">");break; - case '&': - out.Append("&");break; - case '\"': - out.Append(""");break; - case '\'': - out.Append("'");break; - default: - out.data[out.length++] = in.data[i]; - } - } - out.data[out.length] = 0; -} - -// ----------------------------------------------------------------------------------- -// Write a single node as text dump -static void WriteNode(const aiNode* node, IOStream * io, unsigned int depth) { - char prefix[512]; - for (unsigned int i = 0; i < depth;++i) - prefix[i] = '\t'; - prefix[depth] = '\0'; - - const aiMatrix4x4& m = node->mTransformation; - - aiString name; - ConvertName(name,node->mName); - ioprintf(io,"%s \n" - "%s\t \n" - "%s\t\t%0 6f %0 6f %0 6f %0 6f\n" - "%s\t\t%0 6f %0 6f %0 6f %0 6f\n" - "%s\t\t%0 6f %0 6f %0 6f %0 6f\n" - "%s\t\t%0 6f %0 6f %0 6f %0 6f\n" - "%s\t \n", - prefix,name.data,prefix, - prefix,m.a1,m.a2,m.a3,m.a4, - prefix,m.b1,m.b2,m.b3,m.b4, - prefix,m.c1,m.c2,m.c3,m.c4, - prefix,m.d1,m.d2,m.d3,m.d4,prefix); - - if (node->mNumMeshes) { - ioprintf(io, "%s\t\n%s\t", - prefix,node->mNumMeshes,prefix); - - for (unsigned int i = 0; i < node->mNumMeshes;++i) { - ioprintf(io,"%i ",node->mMeshes[i]); - } - ioprintf(io,"\n%s\t\n",prefix); - } - - if (node->mNumChildren) { - ioprintf(io,"%s\t\n", - prefix,node->mNumChildren); - - for (unsigned int i = 0; i < node->mNumChildren;++i) { - WriteNode(node->mChildren[i],io,depth+2); - } - ioprintf(io,"%s\t\n",prefix); - } - ioprintf(io,"%s\n",prefix); -} - -// ----------------------------------------------------------------------------------- -// Some chuncks of text will need to be encoded for XML -// http://stackoverflow.com/questions/5665231/most-efficient-way-to-escape-xml-html-in-c-string#5665377 -static std::string encodeXML(const std::string& data) { - std::string buffer; - buffer.reserve(data.size()); - for(size_t pos = 0; pos != data.size(); ++pos) { - switch(data[pos]) { - case '&': buffer.append("&"); break; - case '\"': buffer.append("""); break; - case '\'': buffer.append("'"); break; - case '<': buffer.append("<"); break; - case '>': buffer.append(">"); break; - default: buffer.append(&data[pos], 1); break; - } - } - return buffer; -} - -// ----------------------------------------------------------------------------------- -// Write a text model dump -static -void WriteDump(const aiScene* scene, IOStream* io, bool shortened) { - time_t tt = ::time( NULL ); -#if _WIN32 - tm* p = gmtime(&tt); -#else - struct tm now; - tm* p = gmtime_r(&tt, &now); -#endif - ai_assert(nullptr != p); - - // write header - std::string header( - "\n" - "\n\n" - "" - " \n\n" - "\n" - ); - - const unsigned int majorVersion( aiGetVersionMajor() ); - const unsigned int minorVersion( aiGetVersionMinor() ); - const unsigned int rev( aiGetVersionRevision() ); - const char *curtime( asctime( p ) ); - ioprintf( io, header.c_str(), majorVersion, minorVersion, rev, curtime, scene->mFlags, 0 ); - - // write the node graph - WriteNode(scene->mRootNode, io, 0); - -#if 0 - // write cameras - for (unsigned int i = 0; i < scene->mNumCameras;++i) { - aiCamera* cam = scene->mCameras[i]; - ConvertName(name,cam->mName); - - // camera header - ioprintf(io,"\t\n" - "\t\t %0 8f %0 8f %0 8f \n" - "\t\t %0 8f %0 8f %0 8f \n" - "\t\t %0 8f %0 8f %0 8f \n" - "\t\t %f \n" - "\t\t %f \n" - "\t\t %f \n" - "\t\t %f \n" - "\t\n", - name.data, - cam->mUp.x,cam->mUp.y,cam->mUp.z, - cam->mLookAt.x,cam->mLookAt.y,cam->mLookAt.z, - cam->mPosition.x,cam->mPosition.y,cam->mPosition.z, - cam->mHorizontalFOV,cam->mAspect,cam->mClipPlaneNear,cam->mClipPlaneFar,i); - } - - // write lights - for (unsigned int i = 0; i < scene->mNumLights;++i) { - aiLight* l = scene->mLights[i]; - ConvertName(name,l->mName); - - // light header - ioprintf(io,"\t type=\"%s\"\n" - "\t\t %0 8f %0 8f %0 8f \n" - "\t\t %0 8f %0 8f %0 8f \n" - "\t\t %0 8f %0 8f %0 8f \n", - name.data, - (l->mType == aiLightSource_DIRECTIONAL ? "directional" : - (l->mType == aiLightSource_POINT ? "point" : "spot" )), - l->mColorDiffuse.r, l->mColorDiffuse.g, l->mColorDiffuse.b, - l->mColorSpecular.r,l->mColorSpecular.g,l->mColorSpecular.b, - l->mColorAmbient.r, l->mColorAmbient.g, l->mColorAmbient.b); - - if (l->mType != aiLightSource_DIRECTIONAL) { - ioprintf(io, - "\t\t %0 8f %0 8f %0 8f \n" - "\t\t %f \n" - "\t\t %f \n" - "\t\t %f \n", - l->mPosition.x,l->mPosition.y,l->mPosition.z, - l->mAttenuationConstant,l->mAttenuationLinear,l->mAttenuationQuadratic); - } - - if (l->mType != aiLightSource_POINT) { - ioprintf(io, - "\t\t %0 8f %0 8f %0 8f \n", - l->mDirection.x,l->mDirection.y,l->mDirection.z); - } - - if (l->mType == aiLightSource_SPOT) { - ioprintf(io, - "\t\t %f \n" - "\t\t %f \n", - l->mAngleOuterCone,l->mAngleInnerCone); - } - ioprintf(io,"\t\n"); - } -#endif - aiString name; - - // write textures - if (scene->mNumTextures) { - ioprintf(io,"\n",scene->mNumTextures); - for (unsigned int i = 0; i < scene->mNumTextures;++i) { - aiTexture* tex = scene->mTextures[i]; - bool compressed = (tex->mHeight == 0); - - // mesh header - ioprintf(io,"\t \n", - (compressed ? -1 : tex->mWidth),(compressed ? -1 : tex->mHeight), - (compressed ? "true" : "false")); - - if (compressed) { - ioprintf(io,"\t\t \n",tex->mWidth); - - if (!shortened) { - for (unsigned int n = 0; n < tex->mWidth;++n) { - ioprintf(io,"\t\t\t%2x",reinterpret_cast(tex->pcData)[n]); - if (n && !(n % 50)) { - ioprintf(io,"\n"); - } - } - } - } - else if (!shortened){ - ioprintf(io,"\t\t \n",tex->mWidth*tex->mHeight*4); - - // const unsigned int width = (unsigned int)std::log10((double)std::max(tex->mHeight,tex->mWidth))+1; - for (unsigned int y = 0; y < tex->mHeight;++y) { - for (unsigned int x = 0; x < tex->mWidth;++x) { - aiTexel* tx = tex->pcData + y*tex->mWidth+x; - unsigned int r = tx->r,g=tx->g,b=tx->b,a=tx->a; - ioprintf(io,"\t\t\t%2x %2x %2x %2x",r,g,b,a); - - // group by four for readability - if ( 0 == ( x + y*tex->mWidth ) % 4 ) { - ioprintf( io, "\n" ); - } - } - } - } - ioprintf(io,"\t\t\n\t\n"); - } - ioprintf(io,"\n"); - } - - // write materials - if (scene->mNumMaterials) { - ioprintf(io,"\n",scene->mNumMaterials); - for (unsigned int i = 0; i< scene->mNumMaterials; ++i) { - const aiMaterial* mat = scene->mMaterials[i]; - - ioprintf(io,"\t\n"); - ioprintf(io,"\t\t\n",mat->mNumProperties); - for (unsigned int n = 0; n < mat->mNumProperties;++n) { - - const aiMaterialProperty* prop = mat->mProperties[n]; - const char* sz = ""; - if (prop->mType == aiPTI_Float) { - sz = "float"; - } - else if (prop->mType == aiPTI_Integer) { - sz = "integer"; - } - else if (prop->mType == aiPTI_String) { - sz = "string"; - } - else if (prop->mType == aiPTI_Buffer) { - sz = "binary_buffer"; - } - - ioprintf(io,"\t\t\tmKey.data, sz, - ::TextureTypeToString((aiTextureType)prop->mSemantic),prop->mIndex); - - if (prop->mType == aiPTI_Float) { - ioprintf(io," size=\"%i\">\n\t\t\t\t", - static_cast(prop->mDataLength/sizeof(float))); - - for (unsigned int p = 0; p < prop->mDataLength/sizeof(float);++p) { - ioprintf(io,"%f ",*((float*)(prop->mData+p*sizeof(float)))); - } - } - else if (prop->mType == aiPTI_Integer) { - ioprintf(io," size=\"%i\">\n\t\t\t\t", - static_cast(prop->mDataLength/sizeof(int))); - - for (unsigned int p = 0; p < prop->mDataLength/sizeof(int);++p) { - ioprintf(io,"%i ",*((int*)(prop->mData+p*sizeof(int)))); - } - } - else if (prop->mType == aiPTI_Buffer) { - ioprintf(io," size=\"%i\">\n\t\t\t\t", - static_cast(prop->mDataLength)); - - for (unsigned int p = 0; p < prop->mDataLength;++p) { - ioprintf(io,"%2x ",prop->mData[p]); - if (p && 0 == p%30) { - ioprintf(io,"\n\t\t\t\t"); - } - } - } - else if (prop->mType == aiPTI_String) { - ioprintf(io,">\n\t\t\t\t\"%s\"",encodeXML(prop->mData+4).c_str() /* skip length */); - } - ioprintf(io,"\n\t\t\t\n"); - } - ioprintf(io,"\t\t\n"); - ioprintf(io,"\t\n"); - } - ioprintf(io,"\n"); - } - - // write animations - if (scene->mNumAnimations) { - ioprintf(io,"\n",scene->mNumAnimations); - for (unsigned int i = 0; i < scene->mNumAnimations;++i) { - aiAnimation* anim = scene->mAnimations[i]; - - // anim header - ConvertName(name,anim->mName); - ioprintf(io,"\t\n", - name.data, anim->mDuration, anim->mTicksPerSecond); - - // write bone animation channels - if (anim->mNumChannels) { - ioprintf(io,"\t\t\n",anim->mNumChannels); - for (unsigned int n = 0; n < anim->mNumChannels;++n) { - aiNodeAnim* nd = anim->mChannels[n]; - - // node anim header - ConvertName(name,nd->mNodeName); - ioprintf(io,"\t\t\t\n",name.data); - - if (!shortened) { - // write position keys - if (nd->mNumPositionKeys) { - ioprintf(io,"\t\t\t\t\n",nd->mNumPositionKeys); - for (unsigned int a = 0; a < nd->mNumPositionKeys;++a) { - aiVectorKey* vc = nd->mPositionKeys+a; - ioprintf(io,"\t\t\t\t\t\n" - "\t\t\t\t\t\t%0 8f %0 8f %0 8f\n\t\t\t\t\t\n", - vc->mTime,vc->mValue.x,vc->mValue.y,vc->mValue.z); - } - ioprintf(io,"\t\t\t\t\n"); - } - - // write scaling keys - if (nd->mNumScalingKeys) { - ioprintf(io,"\t\t\t\t\n",nd->mNumScalingKeys); - for (unsigned int a = 0; a < nd->mNumScalingKeys;++a) { - aiVectorKey* vc = nd->mScalingKeys+a; - ioprintf(io,"\t\t\t\t\t\n" - "\t\t\t\t\t\t%0 8f %0 8f %0 8f\n\t\t\t\t\t\n", - vc->mTime,vc->mValue.x,vc->mValue.y,vc->mValue.z); - } - ioprintf(io,"\t\t\t\t\n"); - } - - // write rotation keys - if (nd->mNumRotationKeys) { - ioprintf(io,"\t\t\t\t\n",nd->mNumRotationKeys); - for (unsigned int a = 0; a < nd->mNumRotationKeys;++a) { - aiQuatKey* vc = nd->mRotationKeys+a; - ioprintf(io,"\t\t\t\t\t\n" - "\t\t\t\t\t\t%0 8f %0 8f %0 8f %0 8f\n\t\t\t\t\t\n", - vc->mTime,vc->mValue.x,vc->mValue.y,vc->mValue.z,vc->mValue.w); - } - ioprintf(io,"\t\t\t\t\n"); - } - } - ioprintf(io,"\t\t\t\n"); - } - ioprintf(io,"\t\t\n"); - } - ioprintf(io,"\t\n"); - } - ioprintf(io,"\n"); - } - - // write meshes - if (scene->mNumMeshes) { - ioprintf(io,"\n",scene->mNumMeshes); - for (unsigned int i = 0; i < scene->mNumMeshes;++i) { - aiMesh* mesh = scene->mMeshes[i]; - // const unsigned int width = (unsigned int)std::log10((double)mesh->mNumVertices)+1; - - // mesh header - ioprintf(io,"\t\n", - (mesh->mPrimitiveTypes & aiPrimitiveType_POINT ? "points" : ""), - (mesh->mPrimitiveTypes & aiPrimitiveType_LINE ? "lines" : ""), - (mesh->mPrimitiveTypes & aiPrimitiveType_TRIANGLE ? "triangles" : ""), - (mesh->mPrimitiveTypes & aiPrimitiveType_POLYGON ? "polygons" : ""), - mesh->mMaterialIndex); - - // bones - if (mesh->mNumBones) { - ioprintf(io,"\t\t\n",mesh->mNumBones); - - for (unsigned int n = 0; n < mesh->mNumBones;++n) { - aiBone* bone = mesh->mBones[n]; - - ConvertName(name,bone->mName); - // bone header - ioprintf(io,"\t\t\t\n" - "\t\t\t\t \n" - "\t\t\t\t\t%0 6f %0 6f %0 6f %0 6f\n" - "\t\t\t\t\t%0 6f %0 6f %0 6f %0 6f\n" - "\t\t\t\t\t%0 6f %0 6f %0 6f %0 6f\n" - "\t\t\t\t\t%0 6f %0 6f %0 6f %0 6f\n" - "\t\t\t\t \n", - name.data, - bone->mOffsetMatrix.a1,bone->mOffsetMatrix.a2,bone->mOffsetMatrix.a3,bone->mOffsetMatrix.a4, - bone->mOffsetMatrix.b1,bone->mOffsetMatrix.b2,bone->mOffsetMatrix.b3,bone->mOffsetMatrix.b4, - bone->mOffsetMatrix.c1,bone->mOffsetMatrix.c2,bone->mOffsetMatrix.c3,bone->mOffsetMatrix.c4, - bone->mOffsetMatrix.d1,bone->mOffsetMatrix.d2,bone->mOffsetMatrix.d3,bone->mOffsetMatrix.d4); - - if (!shortened && bone->mNumWeights) { - ioprintf(io,"\t\t\t\t\n",bone->mNumWeights); - - // bone weights - for (unsigned int a = 0; a < bone->mNumWeights;++a) { - aiVertexWeight* wght = bone->mWeights+a; - - ioprintf(io,"\t\t\t\t\t\n\t\t\t\t\t\t%f\n\t\t\t\t\t\n", - wght->mVertexId,wght->mWeight); - } - ioprintf(io,"\t\t\t\t\n"); - } - ioprintf(io,"\t\t\t\n"); - } - ioprintf(io,"\t\t\n"); - } - - // faces - if (!shortened && mesh->mNumFaces) { - ioprintf(io,"\t\t\n",mesh->mNumFaces); - for (unsigned int n = 0; n < mesh->mNumFaces; ++n) { - aiFace& f = mesh->mFaces[n]; - ioprintf(io,"\t\t\t\n" - "\t\t\t\t",f.mNumIndices); - - for (unsigned int j = 0; j < f.mNumIndices;++j) - ioprintf(io,"%i ",f.mIndices[j]); - - ioprintf(io,"\n\t\t\t\n"); - } - ioprintf(io,"\t\t\n"); - } - - // vertex positions - if (mesh->HasPositions()) { - ioprintf(io,"\t\t \n",mesh->mNumVertices); - if (!shortened) { - for (unsigned int n = 0; n < mesh->mNumVertices; ++n) { - ioprintf(io,"\t\t%0 8f %0 8f %0 8f\n", - mesh->mVertices[n].x, - mesh->mVertices[n].y, - mesh->mVertices[n].z); - } - } - ioprintf(io,"\t\t\n"); - } - - // vertex normals - if (mesh->HasNormals()) { - ioprintf(io,"\t\t \n",mesh->mNumVertices); - if (!shortened) { - for (unsigned int n = 0; n < mesh->mNumVertices; ++n) { - ioprintf(io,"\t\t%0 8f %0 8f %0 8f\n", - mesh->mNormals[n].x, - mesh->mNormals[n].y, - mesh->mNormals[n].z); - } - } - ioprintf(io,"\t\t\n"); - } - - // vertex tangents and bitangents - if (mesh->HasTangentsAndBitangents()) { - ioprintf(io,"\t\t \n",mesh->mNumVertices); - if (!shortened) { - for (unsigned int n = 0; n < mesh->mNumVertices; ++n) { - ioprintf(io,"\t\t%0 8f %0 8f %0 8f\n", - mesh->mTangents[n].x, - mesh->mTangents[n].y, - mesh->mTangents[n].z); - } - } - ioprintf(io,"\t\t\n"); - - ioprintf(io,"\t\t \n",mesh->mNumVertices); - if (!shortened) { - for (unsigned int n = 0; n < mesh->mNumVertices; ++n) { - ioprintf(io,"\t\t%0 8f %0 8f %0 8f\n", - mesh->mBitangents[n].x, - mesh->mBitangents[n].y, - mesh->mBitangents[n].z); - } - } - ioprintf(io,"\t\t\n"); - } - - // texture coordinates - for (unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a) { - if (!mesh->mTextureCoords[a]) - break; - - ioprintf(io,"\t\t \n",mesh->mNumVertices, - a,mesh->mNumUVComponents[a]); - - if (!shortened) { - if (mesh->mNumUVComponents[a] == 3) { - for (unsigned int n = 0; n < mesh->mNumVertices; ++n) { - ioprintf(io,"\t\t%0 8f %0 8f %0 8f\n", - mesh->mTextureCoords[a][n].x, - mesh->mTextureCoords[a][n].y, - mesh->mTextureCoords[a][n].z); - } - } - else { - for (unsigned int n = 0; n < mesh->mNumVertices; ++n) { - ioprintf(io,"\t\t%0 8f %0 8f\n", - mesh->mTextureCoords[a][n].x, - mesh->mTextureCoords[a][n].y); - } - } - } - ioprintf(io,"\t\t\n"); - } - - // vertex colors - for (unsigned int a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; ++a) { - if (!mesh->mColors[a]) - break; - ioprintf(io,"\t\t \n",mesh->mNumVertices,a); - if (!shortened) { - for (unsigned int n = 0; n < mesh->mNumVertices; ++n) { - ioprintf(io,"\t\t%0 8f %0 8f %0 8f %0 8f\n", - mesh->mColors[a][n].r, - mesh->mColors[a][n].g, - mesh->mColors[a][n].b, - mesh->mColors[a][n].a); - } - } - ioprintf(io,"\t\t\n"); - } - ioprintf(io,"\t\n"); - } - ioprintf(io,"\n"); - } - ioprintf(io,"\n"); -} - -} // end of namespace AssxmlExport void ExportSceneAssxml(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* /*pProperties*/) { From d75f46280dc6e23b8834e769016e4415ac96d4ac Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sun, 16 Feb 2020 15:32:29 +0100 Subject: [PATCH 059/330] Update irrString.h fiix ordering of initializiation --- contrib/irrXML/irrString.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/contrib/irrXML/irrString.h b/contrib/irrXML/irrString.h index 1b32ee5ea..1abf22b78 100644 --- a/contrib/irrXML/irrString.h +++ b/contrib/irrXML/irrString.h @@ -19,7 +19,7 @@ so you can assign unicode to string and ascii to string Note that the conversation between both is not done using an encoding. Known bugs: -Special characters like '', '' and '' are ignored in the +Special characters like 'Ä', 'Ü' and 'Ö' are ignored in the methods make_upper, make_lower and equals_ignore_case. */ template @@ -29,7 +29,7 @@ public: //! Default constructor string() - : allocated(1), used(1), array(0) + : array(0), allocated(1), used(1) { array = new T[1]; array[0] = 0x0; @@ -39,7 +39,7 @@ public: //! Constructor string(const string& other) - : allocated(0), used(0), array(0) + : array(0), allocated(0), used(0) { *this = other; } @@ -47,7 +47,7 @@ public: //! Constructs a string from an int string(int number) - : allocated(0), used(0), array(0) + : array(0), allocated(0), used(0) { // store if negative and make positive @@ -98,7 +98,7 @@ public: //! Constructor for copying a string from a pointer with a given lenght template string(const B* c, s32 lenght) - : allocated(0), used(0), array(0) + : array(0), allocated(0), used(0) { if (!c) return; @@ -117,7 +117,7 @@ public: //! Constructor for unicode and ascii strings template string(const B* c) - : allocated(0), used(0), array(0) + : array(0), allocated(0), used(0) { *this = c; } From c2bfbdacf4d9f4560fd769af8a8c2beffc4820ec Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sun, 16 Feb 2020 15:37:20 +0100 Subject: [PATCH 060/330] fix more warnings. --- code/3DS/3DSHelper.h | 14 ++ code/Assbin/AssbinFileWriter.cpp | 11 +- code/B3D/B3DImporter.cpp | 130 +++++++++--------- code/B3D/B3DImporter.h | 6 +- code/Common/BaseImporter.cpp | 2 +- code/Common/SpatialSort.cpp | 2 + code/Material/MaterialSystem.cpp | 3 +- code/PostProcessing/ArmaturePopulate.cpp | 4 +- code/PostProcessing/CalcTangentsProcess.cpp | 2 +- .../PostProcessing/FindInvalidDataProcess.cpp | 13 +- code/PostProcessing/MakeVerboseFormat.cpp | 24 ++-- code/PostProcessing/OptimizeGraph.cpp | 4 +- code/PostProcessing/SortByPTypeProcess.cpp | 22 +-- code/PostProcessing/TriangulateProcess.cpp | 4 +- code/PostProcessing/ValidateDataStructure.cpp | 2 +- 15 files changed, 133 insertions(+), 110 deletions(-) diff --git a/code/3DS/3DSHelper.h b/code/3DS/3DSHelper.h index e483f1a25..00b439e56 100644 --- a/code/3DS/3DSHelper.h +++ b/code/3DS/3DSHelper.h @@ -342,6 +342,20 @@ struct Texture { mTextureBlend = get_qnan(); } + Texture(Texture &&other) AI_NO_EXCEPT : + mTextureBlend(std::move(other.mTextureBlend)), + mMapName(std::move(mMapName)), + mOffsetU(std::move(mOffsetU)), + mOffsetV(std::move(mOffsetV)), + mScaleU(std::move(mScaleU)), + mScaleV(std::move(mScaleV)), + mRotation(std::move(mRotation)), + mMapMode(std::move(mMapMode)), + bPrivate(std::move(bPrivate)), + iUVSrc(std::move(iUVSrc)) { + + } + //! Specifies the blend factor for the texture ai_real mTextureBlend; diff --git a/code/Assbin/AssbinFileWriter.cpp b/code/Assbin/AssbinFileWriter.cpp index 4bc8f7cac..5e5a78d7c 100644 --- a/code/Assbin/AssbinFileWriter.cpp +++ b/code/Assbin/AssbinFileWriter.cpp @@ -371,7 +371,7 @@ protected: void* value = node->mMetaData->mValues[i].mData; Write(&chunk, key); - Write(&chunk, type); + Write(&chunk, (uint16_t) type); switch (type) { case AI_BOOL: @@ -553,13 +553,14 @@ protected: const aiFace& f = mesh->mFaces[i]; static_assert(AI_MAX_FACE_INDICES <= 0xffff, "AI_MAX_FACE_INDICES <= 0xffff"); - Write(&chunk,f.mNumIndices); + Write(&chunk,f.mNumIndices); for (unsigned int a = 0; a < f.mNumIndices;++a) { if (mesh->mNumVertices < (1u<<16)) { - Write(&chunk,f.mIndices[a]); - } - else Write(&chunk,f.mIndices[a]); + Write(&chunk,f.mIndices[a]); + } else { + Write(&chunk, f.mIndices[a]); + } } } } diff --git a/code/B3D/B3DImporter.cpp b/code/B3D/B3DImporter.cpp index 07336df65..80da4c814 100644 --- a/code/B3D/B3DImporter.cpp +++ b/code/B3D/B3DImporter.cpp @@ -155,36 +155,37 @@ AI_WONT_RETURN void B3DImporter::Fail( string str ){ // ------------------------------------------------------------------------------------------------ int B3DImporter::ReadByte(){ - if( _pos<_buf.size() ) { - return _buf[_pos++]; - } - - Fail( "EOF" ); - return 0; + if (_pos > _buf.size()) { + Fail("EOF"); + } + + return _buf[_pos++]; } // ------------------------------------------------------------------------------------------------ int B3DImporter::ReadInt(){ - if( _pos+4<=_buf.size() ){ - int n; - memcpy(&n, &_buf[_pos], 4); - _pos+=4; - return n; + if (_pos + 4 > _buf.size()) { + Fail("EOF"); } - Fail( "EOF" ); - return 0; + + int n; + memcpy(&n, &_buf[_pos], 4); + _pos+=4; + + return n; } // ------------------------------------------------------------------------------------------------ -float B3DImporter::ReadFloat(){ - if( _pos+4<=_buf.size() ){ - float n; - memcpy(&n, &_buf[_pos], 4); - _pos+=4; - return n; - } - Fail( "EOF" ); - return 0.0f; +float B3DImporter::ReadFloat() { + if (_pos + 4 > _buf.size()) { + Fail("EOF"); + } + + float n; + memcpy(&n, &_buf[_pos], 4); + _pos+=4; + + return n; } // ------------------------------------------------------------------------------------------------ @@ -214,6 +215,9 @@ aiQuaternion B3DImporter::ReadQuat(){ // ------------------------------------------------------------------------------------------------ string B3DImporter::ReadString(){ + if (_pos > _buf.size()) { + Fail("EOF"); + } string str; while( _pos<_buf.size() ){ char c=(char)ReadByte(); @@ -222,7 +226,6 @@ string B3DImporter::ReadString(){ } str+=c; } - Fail( "EOF" ); return string(); } @@ -247,7 +250,7 @@ void B3DImporter::ExitChunk(){ } // ------------------------------------------------------------------------------------------------ -unsigned B3DImporter::ChunkSize(){ +size_t B3DImporter::ChunkSize(){ return _stack.back()-_pos; } // ------------------------------------------------------------------------------------------------ @@ -355,8 +358,8 @@ void B3DImporter::ReadVRTS(){ Fail( "Bad texcoord data" ); } - int sz=12+(_vflags&1?12:0)+(_vflags&2?16:0)+(_tcsets*_tcsize*4); - int n_verts=ChunkSize()/sz; + int sz = 12+(_vflags&1?12:0)+(_vflags&2?16:0)+(_tcsets*_tcsize*4); + size_t n_verts = ChunkSize()/sz; int v0=static_cast(_vertices.size()); _vertices.resize( v0+n_verts ); @@ -377,14 +380,14 @@ void B3DImporter::ReadVRTS(){ ReadQuat(); //skip v 4bytes... } - for( int i=0;i<_tcsets;++i ){ + for( int j=0;j<_tcsets;++j ){ float t[4]={0,0,0,0}; - for( int j=0;j<_tcsize;++j ){ - t[j]=ReadFloat(); + for( int k=0;k<_tcsize;++k ){ + t[k]=ReadFloat(); } - t[1]=1-t[1]; - if( !i ) { - v.texcoords=aiVector3D( t[0],t[1],t[2] ); + t[1] = 1 - t[1]; + if( !j ) { + v.texcoords = aiVector3D( t[0],t[1],t[2] ); } } } @@ -408,7 +411,7 @@ void B3DImporter::ReadTRIS(int v0) { mesh->mNumFaces = 0; mesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE; - int n_tris = ChunkSize() / 12; + size_t n_tris = ChunkSize() / 12; aiFace *face = mesh->mFaces = new aiFace[n_tris]; for (int i = 0; i < n_tris; ++i) { @@ -463,7 +466,7 @@ void B3DImporter::ReadBONE(int id) { Vertex &v = _vertices[vertex]; for (int i = 0; i < 4; ++i) { if (!v.weights[i]) { - v.bones[i] = id; + v.bones[i] = static_cast(id); v.weights[i] = weight; break; } @@ -547,24 +550,24 @@ aiNode *B3DImporter::ReadNODE( aiNode *parent ){ vector children; while( ChunkSize() ){ - string t=ReadChunk(); - if( t=="MESH" ){ + const string chunk = ReadChunk(); + if (chunk == "MESH") { unsigned int n= static_cast(_meshes.size()); ReadMESH(); for( unsigned int i=n;i(_meshes.size());++i ){ meshes.push_back( i ); } - }else if( t=="BONE" ){ + } else if (chunk == "BONE") { ReadBONE( nodeid ); - }else if( t=="ANIM" ){ + } else if (chunk == "ANIM") { ReadANIM(); - }else if( t=="KEYS" ){ + } else if (chunk == "KEYS") { if( !nodeAnim ){ nodeAnim.reset(new aiNodeAnim); nodeAnim->mNodeName=node->mName; } ReadKEYS( nodeAnim.get() ); - }else if( t=="NODE" ){ + } else if (chunk == "NODE") { aiNode *child=ReadNODE( node ); children.push_back( child ); } @@ -613,12 +616,12 @@ void B3DImporter::ReadBB3D( aiScene *scene ){ } while( ChunkSize() ){ - string t=ReadChunk(); - if( t=="TEXS" ){ + const string chunk = ReadChunk(); + if (chunk == "TEXS") { ReadTEXS(); - }else if( t=="BRUS" ){ + } else if (chunk == "BRUS") { ReadBRUS(); - }else if( t=="NODE" ){ + } else if (chunk == "NODE") { ReadNODE( 0 ); } ExitChunk(); @@ -656,48 +659,51 @@ void B3DImporter::ReadBB3D( aiScene *scene ){ vector< vector > vweights( _nodes.size() ); - for( int i=0;imIndices[j]]; + for (int vertIdx = 0; vertIdx < n_verts; vertIdx += 3) { + for (int faceIndex = 0; faceIndex < 3; ++faceIndex) { + Vertex &v = _vertices[face->mIndices[faceIndex]]; *mv++=v.vertex; if( mn ) *mn++=v.normal; if( mc ) *mc++=v.texcoords; - face->mIndices[j]=i+j; + face->mIndices[faceIndex] = vertIdx + faceIndex; for( int k=0;k<4;++k ){ - if( !v.weights[k] ) break; + if( !v.weights[k] ) + break; - int bone=v.bones[k]; - float weight=v.weights[k]; + int bone = v.bones[k]; + float weight = v.weights[k]; - vweights[bone].push_back( aiVertexWeight(i+j,weight) ); + vweights[bone].push_back(aiVertexWeight(vertIdx + faceIndex, weight)); } } ++face; } vector bones; - for(size_t i=0;i &weights=vweights[i]; - if( !weights.size() ) continue; + for (size_t weightIndx = 0; weightIndx < vweights.size(); ++weightIndx) { + vector &weights = vweights[weightIndx]; + if (!weights.size()) { + continue; + } - aiBone *bone=new aiBone; + aiBone *bone = new aiBone; bones.push_back( bone ); - aiNode *bnode=_nodes[i]; + aiNode *bnode = _nodes[weightIndx]; - bone->mName=bnode->mName; - bone->mNumWeights= static_cast(weights.size()); - bone->mWeights=to_array( weights ); + bone->mName = bnode->mName; + bone->mNumWeights = static_cast(weights.size()); + bone->mWeights = to_array( weights ); - aiMatrix4x4 mat=bnode->mTransformation; + aiMatrix4x4 mat = bnode->mTransformation; while( bnode->mParent ){ bnode=bnode->mParent; mat=bnode->mTransformation * mat; } - bone->mOffsetMatrix=mat.Inverse(); + bone->mOffsetMatrix = mat.Inverse(); } mesh->mNumBones= static_cast(bones.size()); mesh->mBones=to_array( bones ); diff --git a/code/B3D/B3DImporter.h b/code/B3D/B3DImporter.h index f0568dd16..17f15963d 100644 --- a/code/B3D/B3DImporter.h +++ b/code/B3D/B3DImporter.h @@ -82,7 +82,7 @@ private: std::string ReadString(); std::string ReadChunk(); void ExitChunk(); - unsigned ChunkSize(); + size_t ChunkSize(); template T *to_array( const std::vector &v ); @@ -112,10 +112,10 @@ private: void ReadBB3D( aiScene *scene ); - unsigned _pos; + size_t _pos; // unsigned _size; std::vector _buf; - std::vector _stack; + std::vector _stack; std::vector _textures; std::vector > _materials; diff --git a/code/Common/BaseImporter.cpp b/code/Common/BaseImporter.cpp index 660a6a965..13d4fb724 100644 --- a/code/Common/BaseImporter.cpp +++ b/code/Common/BaseImporter.cpp @@ -146,7 +146,7 @@ aiScene* BaseImporter::ReadFile(Importer* pImp, const std::string& pFile, IOSyst } // ------------------------------------------------------------------------------------------------ -void BaseImporter::SetupProperties(const Importer* pImp) +void BaseImporter::SetupProperties(const Importer* ) { // the default implementation does nothing } diff --git a/code/Common/SpatialSort.cpp b/code/Common/SpatialSort.cpp index 604b086b7..6d1a0133f 100644 --- a/code/Common/SpatialSort.cpp +++ b/code/Common/SpatialSort.cpp @@ -53,6 +53,8 @@ using namespace Assimp; # define CHAR_BIT 8 #endif +#pragma warning(disable : 4127) + // ------------------------------------------------------------------------------------------------ // Constructs a spatially sorted representation from the given position array. SpatialSort::SpatialSort( const aiVector3D* pPositions, unsigned int pNumPositions, diff --git a/code/Material/MaterialSystem.cpp b/code/Material/MaterialSystem.cpp index 1c034e55f..63fad4268 100644 --- a/code/Material/MaterialSystem.cpp +++ b/code/Material/MaterialSystem.cpp @@ -332,8 +332,7 @@ unsigned int aiGetMaterialTextureCount(const C_STRUCT aiMaterial* pMat, aiMaterialProperty* prop = pMat->mProperties[i]; if ( prop /* just a sanity check ... */ - && 0 == strcmp( prop->mKey.data, _AI_MATKEY_TEXTURE_BASE ) - && prop->mSemantic == type) { + && 0 == strcmp(prop->mKey.data, _AI_MATKEY_TEXTURE_BASE) && static_cast < aiTextureType>(prop->mSemantic) == type) { max = std::max(max,prop->mIndex+1); } diff --git a/code/PostProcessing/ArmaturePopulate.cpp b/code/PostProcessing/ArmaturePopulate.cpp index 31c99ae94..ce1401d39 100644 --- a/code/PostProcessing/ArmaturePopulate.cpp +++ b/code/PostProcessing/ArmaturePopulate.cpp @@ -62,7 +62,7 @@ bool ArmaturePopulate::IsActive(unsigned int pFlags) const { return (pFlags & aiProcess_PopulateArmatureData) != 0; } -void ArmaturePopulate::SetupProperties(const Importer *pImp) { +void ArmaturePopulate::SetupProperties(const Importer *) { // do nothing } @@ -162,7 +162,7 @@ void ArmaturePopulate::BuildNodeList(const aiNode *current_node, // A bone stack allows us to have multiple armatures, with the same bone names // A bone stack allows us also to retrieve bones true transform even with // duplicate names :) -void ArmaturePopulate::BuildBoneStack(aiNode *current_node, +void ArmaturePopulate::BuildBoneStack(aiNode *, const aiNode *root_node, const aiScene *scene, const std::vector &bones, diff --git a/code/PostProcessing/CalcTangentsProcess.cpp b/code/PostProcessing/CalcTangentsProcess.cpp index 4af335d2f..291205bd8 100644 --- a/code/PostProcessing/CalcTangentsProcess.cpp +++ b/code/PostProcessing/CalcTangentsProcess.cpp @@ -238,7 +238,7 @@ bool CalcTangentsProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex) // FIX: check whether we can reuse the SpatialSort of a previous step SpatialSort* vertexFinder = NULL; SpatialSort _vertexFinder; - float posEpsilon; + float posEpsilon = 10e-6f; if (shared) { std::vector >* avf; diff --git a/code/PostProcessing/FindInvalidDataProcess.cpp b/code/PostProcessing/FindInvalidDataProcess.cpp index c557d7f70..36975fcfe 100644 --- a/code/PostProcessing/FindInvalidDataProcess.cpp +++ b/code/PostProcessing/FindInvalidDataProcess.cpp @@ -99,8 +99,8 @@ void UpdateMeshReferences(aiNode* node, const std::vector& meshMap } // just let the members that are unused, that's much cheaper // than a full array realloc'n'copy party ... - if(!(node->mNumMeshes = out)) { - + node->mNumMeshes = out; + if ( 0 == out ) { delete[] node->mMeshes; node->mMeshes = NULL; } @@ -122,9 +122,8 @@ void FindInvalidDataProcess::Execute( aiScene* pScene) { // Process meshes for( unsigned int a = 0; a < pScene->mNumMeshes; a++) { - - int result; - if ((result = ProcessMesh( pScene->mMeshes[a]))) { + int result = ProcessMesh(pScene->mMeshes[a]); + if (0 == result ) { out = true; if (2 == result) { @@ -141,8 +140,8 @@ void FindInvalidDataProcess::Execute( aiScene* pScene) { } // Process animations - for (unsigned int a = 0; a < pScene->mNumAnimations;++a) { - ProcessAnimation( pScene->mAnimations[a]); + for (unsigned int animIdx = 0; animIdx < pScene->mNumAnimations; ++animIdx) { + ProcessAnimation(pScene->mAnimations[animIdx]); } diff --git a/code/PostProcessing/MakeVerboseFormat.cpp b/code/PostProcessing/MakeVerboseFormat.cpp index 88bdb3124..3928a5b27 100644 --- a/code/PostProcessing/MakeVerboseFormat.cpp +++ b/code/PostProcessing/MakeVerboseFormat.cpp @@ -132,11 +132,9 @@ bool MakeVerboseFormatProcess::MakeVerboseFormat(aiMesh* pcMesh) // need to build a clean list of bones, too for (unsigned int i = 0;i < pcMesh->mNumBones;++i) { - for (unsigned int a = 0; a < pcMesh->mBones[i]->mNumWeights;a++) - { - const aiVertexWeight& w = pcMesh->mBones[i]->mWeights[a]; - if(pcFace->mIndices[q] == w.mVertexId) - { + for (unsigned int boneIdx = 0; boneIdx < pcMesh->mBones[i]->mNumWeights; ++boneIdx) { + const aiVertexWeight &w = pcMesh->mBones[i]->mWeights[boneIdx]; + if(pcFace->mIndices[q] == w.mVertexId) { aiVertexWeight wNew; wNew.mVertexId = iIndex; wNew.mWeight = w.mWeight; @@ -157,17 +155,17 @@ bool MakeVerboseFormatProcess::MakeVerboseFormat(aiMesh* pcMesh) pvBitangents[iIndex] = pcMesh->mBitangents[pcFace->mIndices[q]]; } - unsigned int p = 0; - while (pcMesh->HasTextureCoords(p)) + unsigned int pp = 0; + while (pcMesh->HasTextureCoords(pp)) { - apvTextureCoords[p][iIndex] = pcMesh->mTextureCoords[p][pcFace->mIndices[q]]; - ++p; + apvTextureCoords[pp][iIndex] = pcMesh->mTextureCoords[pp][pcFace->mIndices[q]]; + ++pp; } - p = 0; - while (pcMesh->HasVertexColors(p)) + pp = 0; + while (pcMesh->HasVertexColors(pp)) { - apvColorSets[p][iIndex] = pcMesh->mColors[p][pcFace->mIndices[q]]; - ++p; + apvColorSets[pp][iIndex] = pcMesh->mColors[pp][pcFace->mIndices[q]]; + ++pp; } pcFace->mIndices[q] = iIndex; } diff --git a/code/PostProcessing/OptimizeGraph.cpp b/code/PostProcessing/OptimizeGraph.cpp index f3996c275..482ab916a 100644 --- a/code/PostProcessing/OptimizeGraph.cpp +++ b/code/PostProcessing/OptimizeGraph.cpp @@ -179,7 +179,7 @@ void OptimizeGraphProcess::CollectNewChildren(aiNode *nd, std::list &n // copy all mesh references in one array if (out_meshes) { - unsigned int *meshes = new unsigned int[out_meshes + join_master->mNumMeshes], *tmp = meshes; + unsigned int *meshIdxs = new unsigned int[out_meshes + join_master->mNumMeshes], *tmp = meshIdxs; for (unsigned int n = 0; n < join_master->mNumMeshes; ++n) { *tmp++ = join_master->mMeshes[n]; } @@ -217,7 +217,7 @@ void OptimizeGraphProcess::CollectNewChildren(aiNode *nd, std::list &n delete join_node; // bye, node } delete[] join_master->mMeshes; - join_master->mMeshes = meshes; + join_master->mMeshes = meshIdxs; join_master->mNumMeshes += out_meshes; } } diff --git a/code/PostProcessing/SortByPTypeProcess.cpp b/code/PostProcessing/SortByPTypeProcess.cpp index c1b08c5a7..87d34c162 100644 --- a/code/PostProcessing/SortByPTypeProcess.cpp +++ b/code/PostProcessing/SortByPTypeProcess.cpp @@ -330,19 +330,23 @@ void SortByPTypeProcess::Execute( aiScene* pScene) { ai_assert(outFaces == out->mFaces + out->mNumFaces); // now generate output bones - for (unsigned int q = 0; q < mesh->mNumBones;++q) - if (!tempBones[q].empty())++out->mNumBones; + for (unsigned int q = 0; q < mesh->mNumBones; ++q) { + if (!tempBones[q].empty()) { + ++out->mNumBones; + } + } - if (out->mNumBones) - { + if (out->mNumBones) { out->mBones = new aiBone*[out->mNumBones]; - for (unsigned int q = 0, real = 0; q < mesh->mNumBones;++q) + for (unsigned int q = 0, boneIdx = 0; q < mesh->mNumBones;++q) { TempBoneInfo& in = tempBones[q]; - if (in.empty())continue; + if (in.empty()) { + continue; + } aiBone* srcBone = mesh->mBones[q]; - aiBone* bone = out->mBones[real] = new aiBone(); + aiBone *bone = out->mBones[boneIdx] = new aiBone(); bone->mName = srcBone->mName; bone->mOffsetMatrix = srcBone->mOffsetMatrix; @@ -352,7 +356,7 @@ void SortByPTypeProcess::Execute( aiScene* pScene) { ::memcpy(bone->mWeights,&in[0],bone->mNumWeights*sizeof(aiVertexWeight)); - ++real; + ++boneIdx; } } } @@ -364,7 +368,7 @@ void SortByPTypeProcess::Execute( aiScene* pScene) { delete mesh; // avoid invalid pointer - pScene->mMeshes[i] = NULL; + pScene->mMeshes[i] = nullptr; } if (outMeshes.empty()) diff --git a/code/PostProcessing/TriangulateProcess.cpp b/code/PostProcessing/TriangulateProcess.cpp index 64cc63bbd..3fd7eea21 100644 --- a/code/PostProcessing/TriangulateProcess.cpp +++ b/code/PostProcessing/TriangulateProcess.cpp @@ -419,7 +419,7 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh) num = 0; break; - curOut -= (max-num); /* undo all previous work */ + /*curOut -= (max-num); // undo all previous work for (tmp = 0; tmp < max-2; ++tmp) { aiFace& nface = *curOut++; @@ -433,7 +433,7 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh) } num = 0; - break; + break;*/ } aiFace& nface = *curOut++; diff --git a/code/PostProcessing/ValidateDataStructure.cpp b/code/PostProcessing/ValidateDataStructure.cpp index a812efb0b..3c2d10cfb 100644 --- a/code/PostProcessing/ValidateDataStructure.cpp +++ b/code/PostProcessing/ValidateDataStructure.cpp @@ -612,7 +612,7 @@ void ValidateDSProcess::SearchForInvalidTextures(const aiMaterial* pMaterial, bool bNoSpecified = true; for (unsigned int i = 0; i < pMaterial->mNumProperties;++i) { aiMaterialProperty* prop = pMaterial->mProperties[i]; - if (prop->mSemantic != type) { + if (static_cast(prop->mSemantic) != type) { continue; } From 92da00329fc645db2148fdee5ee8af11695845ec Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sun, 16 Feb 2020 18:10:52 +0100 Subject: [PATCH 061/330] Update irrArray.h fix init ordering. --- contrib/irrXML/irrArray.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contrib/irrXML/irrArray.h b/contrib/irrXML/irrArray.h index f7b710b80..40c822590 100644 --- a/contrib/irrXML/irrArray.h +++ b/contrib/irrXML/irrArray.h @@ -23,7 +23,7 @@ class array public: array() - : data(0), used(0), allocated(0), + : data(0), allocated(0), used(0), free_when_destroyed(true), is_sorted(true) { } @@ -31,7 +31,7 @@ public: //! Constructs a array and allocates an initial chunk of memory. //! \param start_count: Amount of elements to allocate. array(u32 start_count) - : data(0), used(0), allocated(0), + : data(0), allocated(0), used(0), free_when_destroyed(true), is_sorted(true) { reallocate(start_count); From 6e13381bdb7029d263b480d70dacdf1c92a43317 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 18 Feb 2020 14:41:19 +0100 Subject: [PATCH 062/330] next warnings. --- code/3DS/3DSHelper.h | 471 +++++---- code/3DS/3DSLoader.cpp | 25 +- code/AC/ACLoader.cpp | 678 ++++++------- code/AC/ACLoader.h | 2 +- code/AMF/AMFImporter_Postprocess.cpp | 2 +- code/HMP/HMPLoader.cpp | 6 +- code/LWO/LWOAnimation.cpp | 8 +- code/MDL/MDLLoader.cpp | 1182 +++++++++++----------- code/MDL/MDLLoader.h | 4 +- code/Material/MaterialSystem.cpp | 3 +- code/PostProcessing/SplitLargeMeshes.cpp | 5 +- code/PostProcessing/TextureTransform.cpp | 6 +- 12 files changed, 1110 insertions(+), 1282 deletions(-) diff --git a/code/3DS/3DSHelper.h b/code/3DS/3DSHelper.h index 00b439e56..3ef9b8604 100644 --- a/code/3DS/3DSHelper.h +++ b/code/3DS/3DSHelper.h @@ -45,18 +45,18 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef AI_3DSFILEHELPER_H_INC #define AI_3DSFILEHELPER_H_INC -#include #include +#include #include -#include -#include +#include #include #include -#include +#include +#include #include //sprintf -namespace Assimp { -namespace D3DS { +namespace Assimp { +namespace D3DS { #include @@ -77,15 +77,13 @@ private: public: //! data structure for a single chunk in a .3ds file struct Chunk { - uint16_t Flag; - uint32_t Size; + uint16_t Flag; + uint32_t Size; } PACK_STRUCT; - //! Used for shading field in material3ds structure //! From AutoDesk 3ds SDK - typedef enum - { + typedef enum { // translated to gouraud shading with wireframe active Wire = 0x0, @@ -109,59 +107,57 @@ public: } shadetype3ds; // Flags for animated keys - enum - { - KEY_USE_TENS = 0x1, - KEY_USE_CONT = 0x2, - KEY_USE_BIAS = 0x4, - KEY_USE_EASE_TO = 0x8, - KEY_USE_EASE_FROM = 0x10 - } ; + enum { + KEY_USE_TENS = 0x1, + KEY_USE_CONT = 0x2, + KEY_USE_BIAS = 0x4, + KEY_USE_EASE_TO = 0x8, + KEY_USE_EASE_FROM = 0x10 + }; - enum - { + enum { // ******************************************************************** // Basic chunks which can be found everywhere in the file - CHUNK_VERSION = 0x0002, - CHUNK_RGBF = 0x0010, // float4 R; float4 G; float4 B - CHUNK_RGBB = 0x0011, // int1 R; int1 G; int B + CHUNK_VERSION = 0x0002, + CHUNK_RGBF = 0x0010, // float4 R; float4 G; float4 B + CHUNK_RGBB = 0x0011, // int1 R; int1 G; int B // Linear color values (gamma = 2.2?) - CHUNK_LINRGBF = 0x0013, // float4 R; float4 G; float4 B - CHUNK_LINRGBB = 0x0012, // int1 R; int1 G; int B + CHUNK_LINRGBF = 0x0013, // float4 R; float4 G; float4 B + CHUNK_LINRGBB = 0x0012, // int1 R; int1 G; int B - CHUNK_PERCENTW = 0x0030, // int2 percentage - CHUNK_PERCENTF = 0x0031, // float4 percentage - CHUNK_PERCENTD = 0x0032, // float8 percentage + CHUNK_PERCENTW = 0x0030, // int2 percentage + CHUNK_PERCENTF = 0x0031, // float4 percentage + CHUNK_PERCENTD = 0x0032, // float8 percentage // ******************************************************************** // Prj master chunk - CHUNK_PRJ = 0xC23D, + CHUNK_PRJ = 0xC23D, // MDLI master chunk - CHUNK_MLI = 0x3DAA, + CHUNK_MLI = 0x3DAA, // Primary main chunk of the .3ds file - CHUNK_MAIN = 0x4D4D, + CHUNK_MAIN = 0x4D4D, // Mesh main chunk - CHUNK_OBJMESH = 0x3D3D, + CHUNK_OBJMESH = 0x3D3D, // Specifies the background color of the .3ds file // This is passed through the material system for // viewing purposes. - CHUNK_BKGCOLOR = 0x1200, + CHUNK_BKGCOLOR = 0x1200, // Specifies the ambient base color of the scene. // This is added to all materials in the file - CHUNK_AMBCOLOR = 0x2100, + CHUNK_AMBCOLOR = 0x2100, // Specifies the background image for the whole scene // This value is passed through the material system // to the viewer - CHUNK_BIT_MAP = 0x1100, - CHUNK_BIT_MAP_EXISTS = 0x1101, + CHUNK_BIT_MAP = 0x1100, + CHUNK_BIT_MAP_EXISTS = 0x1101, // ******************************************************************** // Viewport related stuff. Ignored @@ -177,183 +173,204 @@ public: // ******************************************************************** // Mesh chunks - CHUNK_OBJBLOCK = 0x4000, - CHUNK_TRIMESH = 0x4100, - CHUNK_VERTLIST = 0x4110, + CHUNK_OBJBLOCK = 0x4000, + CHUNK_TRIMESH = 0x4100, + CHUNK_VERTLIST = 0x4110, CHUNK_VERTFLAGS = 0x4111, - CHUNK_FACELIST = 0x4120, - CHUNK_FACEMAT = 0x4130, - CHUNK_MAPLIST = 0x4140, - CHUNK_SMOOLIST = 0x4150, - CHUNK_TRMATRIX = 0x4160, + CHUNK_FACELIST = 0x4120, + CHUNK_FACEMAT = 0x4130, + CHUNK_MAPLIST = 0x4140, + CHUNK_SMOOLIST = 0x4150, + CHUNK_TRMATRIX = 0x4160, CHUNK_MESHCOLOR = 0x4165, - CHUNK_TXTINFO = 0x4170, - CHUNK_LIGHT = 0x4600, - CHUNK_CAMERA = 0x4700, + CHUNK_TXTINFO = 0x4170, + CHUNK_LIGHT = 0x4600, + CHUNK_CAMERA = 0x4700, CHUNK_HIERARCHY = 0x4F00, // Specifies the global scaling factor. This is applied // to the root node's transformation matrix - CHUNK_MASTER_SCALE = 0x0100, + CHUNK_MASTER_SCALE = 0x0100, // ******************************************************************** // Material chunks - CHUNK_MAT_MATERIAL = 0xAFFF, + CHUNK_MAT_MATERIAL = 0xAFFF, - // asciiz containing the name of the material - CHUNK_MAT_MATNAME = 0xA000, - CHUNK_MAT_AMBIENT = 0xA010, // followed by color chunk - CHUNK_MAT_DIFFUSE = 0xA020, // followed by color chunk - CHUNK_MAT_SPECULAR = 0xA030, // followed by color chunk + // asciiz containing the name of the material + CHUNK_MAT_MATNAME = 0xA000, + CHUNK_MAT_AMBIENT = 0xA010, // followed by color chunk + CHUNK_MAT_DIFFUSE = 0xA020, // followed by color chunk + CHUNK_MAT_SPECULAR = 0xA030, // followed by color chunk - // Specifies the shininess of the material - // followed by percentage chunk - CHUNK_MAT_SHININESS = 0xA040, - CHUNK_MAT_SHININESS_PERCENT = 0xA041 , + // Specifies the shininess of the material + // followed by percentage chunk + CHUNK_MAT_SHININESS = 0xA040, + CHUNK_MAT_SHININESS_PERCENT = 0xA041, - // Specifies the shading mode to be used - // followed by a short - CHUNK_MAT_SHADING = 0xA100, + // Specifies the shading mode to be used + // followed by a short + CHUNK_MAT_SHADING = 0xA100, - // NOTE: Emissive color (self illumination) seems not - // to be a color but a single value, type is unknown. - // Make the parser accept both of them. - // followed by percentage chunk (?) - CHUNK_MAT_SELF_ILLUM = 0xA080, + // NOTE: Emissive color (self illumination) seems not + // to be a color but a single value, type is unknown. + // Make the parser accept both of them. + // followed by percentage chunk (?) + CHUNK_MAT_SELF_ILLUM = 0xA080, - // Always followed by percentage chunk (?) - CHUNK_MAT_SELF_ILPCT = 0xA084, + // Always followed by percentage chunk (?) + CHUNK_MAT_SELF_ILPCT = 0xA084, - // Always followed by percentage chunk - CHUNK_MAT_TRANSPARENCY = 0xA050, + // Always followed by percentage chunk + CHUNK_MAT_TRANSPARENCY = 0xA050, - // Diffuse texture channel 0 - CHUNK_MAT_TEXTURE = 0xA200, + // Diffuse texture channel 0 + CHUNK_MAT_TEXTURE = 0xA200, - // Contains opacity information for each texel - CHUNK_MAT_OPACMAP = 0xA210, + // Contains opacity information for each texel + CHUNK_MAT_OPACMAP = 0xA210, - // Contains a reflection map to be used to reflect - // the environment. This is partially supported. - CHUNK_MAT_REFLMAP = 0xA220, + // Contains a reflection map to be used to reflect + // the environment. This is partially supported. + CHUNK_MAT_REFLMAP = 0xA220, - // Self Illumination map (emissive colors) - CHUNK_MAT_SELFIMAP = 0xA33d, + // Self Illumination map (emissive colors) + CHUNK_MAT_SELFIMAP = 0xA33d, - // Bumpmap. Not specified whether it is a heightmap - // or a normal map. Assme it is a heightmap since - // artist normally prefer this format. - CHUNK_MAT_BUMPMAP = 0xA230, + // Bumpmap. Not specified whether it is a heightmap + // or a normal map. Assme it is a heightmap since + // artist normally prefer this format. + CHUNK_MAT_BUMPMAP = 0xA230, - // Specular map. Seems to influence the specular color - CHUNK_MAT_SPECMAP = 0xA204, + // Specular map. Seems to influence the specular color + CHUNK_MAT_SPECMAP = 0xA204, - // Holds shininess data. - CHUNK_MAT_MAT_SHINMAP = 0xA33C, + // Holds shininess data. + CHUNK_MAT_MAT_SHINMAP = 0xA33C, - // Scaling in U/V direction. - // (need to gen separate UV coordinate set - // and do this by hand) - CHUNK_MAT_MAP_USCALE = 0xA354, - CHUNK_MAT_MAP_VSCALE = 0xA356, + // Scaling in U/V direction. + // (need to gen separate UV coordinate set + // and do this by hand) + CHUNK_MAT_MAP_USCALE = 0xA354, + CHUNK_MAT_MAP_VSCALE = 0xA356, - // Translation in U/V direction. - // (need to gen separate UV coordinate set - // and do this by hand) - CHUNK_MAT_MAP_UOFFSET = 0xA358, - CHUNK_MAT_MAP_VOFFSET = 0xA35a, + // Translation in U/V direction. + // (need to gen separate UV coordinate set + // and do this by hand) + CHUNK_MAT_MAP_UOFFSET = 0xA358, + CHUNK_MAT_MAP_VOFFSET = 0xA35a, - // UV-coordinates rotation around the z-axis - // Assumed to be in radians. - CHUNK_MAT_MAP_ANG = 0xA35C, + // UV-coordinates rotation around the z-axis + // Assumed to be in radians. + CHUNK_MAT_MAP_ANG = 0xA35C, - // Tiling flags for 3DS files - CHUNK_MAT_MAP_TILING = 0xa351, + // Tiling flags for 3DS files + CHUNK_MAT_MAP_TILING = 0xa351, - // Specifies the file name of a texture - CHUNK_MAPFILE = 0xA300, + // Specifies the file name of a texture + CHUNK_MAPFILE = 0xA300, - // Specifies whether a materail requires two-sided rendering - CHUNK_MAT_TWO_SIDE = 0xA081, + // Specifies whether a materail requires two-sided rendering + CHUNK_MAT_TWO_SIDE = 0xA081, // ******************************************************************** // Main keyframer chunk. Contains translation/rotation/scaling data - CHUNK_KEYFRAMER = 0xB000, + CHUNK_KEYFRAMER = 0xB000, // Supported sub chunks - CHUNK_TRACKINFO = 0xB002, - CHUNK_TRACKOBJNAME = 0xB010, - CHUNK_TRACKDUMMYOBJNAME = 0xB011, - CHUNK_TRACKPIVOT = 0xB013, - CHUNK_TRACKPOS = 0xB020, - CHUNK_TRACKROTATE = 0xB021, - CHUNK_TRACKSCALE = 0xB022, + CHUNK_TRACKINFO = 0xB002, + CHUNK_TRACKOBJNAME = 0xB010, + CHUNK_TRACKDUMMYOBJNAME = 0xB011, + CHUNK_TRACKPIVOT = 0xB013, + CHUNK_TRACKPOS = 0xB020, + CHUNK_TRACKROTATE = 0xB021, + CHUNK_TRACKSCALE = 0xB022, // ******************************************************************** // Keyframes for various other stuff in the file // Partially ignored - CHUNK_AMBIENTKEY = 0xB001, - CHUNK_TRACKMORPH = 0xB026, - CHUNK_TRACKHIDE = 0xB029, - CHUNK_OBJNUMBER = 0xB030, - CHUNK_TRACKCAMERA = 0xB003, - CHUNK_TRACKFOV = 0xB023, - CHUNK_TRACKROLL = 0xB024, - CHUNK_TRACKCAMTGT = 0xB004, - CHUNK_TRACKLIGHT = 0xB005, - CHUNK_TRACKLIGTGT = 0xB006, - CHUNK_TRACKSPOTL = 0xB007, - CHUNK_FRAMES = 0xB008, + CHUNK_AMBIENTKEY = 0xB001, + CHUNK_TRACKMORPH = 0xB026, + CHUNK_TRACKHIDE = 0xB029, + CHUNK_OBJNUMBER = 0xB030, + CHUNK_TRACKCAMERA = 0xB003, + CHUNK_TRACKFOV = 0xB023, + CHUNK_TRACKROLL = 0xB024, + CHUNK_TRACKCAMTGT = 0xB004, + CHUNK_TRACKLIGHT = 0xB005, + CHUNK_TRACKLIGTGT = 0xB006, + CHUNK_TRACKSPOTL = 0xB007, + CHUNK_FRAMES = 0xB008, // ******************************************************************** // light sub-chunks - CHUNK_DL_OFF = 0x4620, - CHUNK_DL_OUTER_RANGE = 0x465A, - CHUNK_DL_INNER_RANGE = 0x4659, - CHUNK_DL_MULTIPLIER = 0x465B, - CHUNK_DL_EXCLUDE = 0x4654, - CHUNK_DL_ATTENUATE = 0x4625, - CHUNK_DL_SPOTLIGHT = 0x4610, + CHUNK_DL_OFF = 0x4620, + CHUNK_DL_OUTER_RANGE = 0x465A, + CHUNK_DL_INNER_RANGE = 0x4659, + CHUNK_DL_MULTIPLIER = 0x465B, + CHUNK_DL_EXCLUDE = 0x4654, + CHUNK_DL_ATTENUATE = 0x4625, + CHUNK_DL_SPOTLIGHT = 0x4610, // camera sub-chunks - CHUNK_CAM_RANGES = 0x4720 + CHUNK_CAM_RANGES = 0x4720 }; }; // --------------------------------------------------------------------------- /** Helper structure representing a 3ds mesh face */ -struct Face : public FaceWithSmoothingGroup -{ +struct Face : public FaceWithSmoothingGroup { }; +#pragma warning(disable : 4315 ) + // --------------------------------------------------------------------------- /** Helper structure representing a texture */ struct Texture { //! Default constructor Texture() AI_NO_EXCEPT - : mOffsetU (0.0) - , mOffsetV (0.0) - , mScaleU (1.0) - , mScaleV (1.0) - , mRotation (0.0) - , mMapMode (aiTextureMapMode_Wrap) - , bPrivate() - , iUVSrc (0) { + : mTextureBlend(0.0f), + mMapName(), + mOffsetU(0.0), + mOffsetV(0.0), + mScaleU(1.0), + mScaleV(1.0), + mRotation(0.0), + mMapMode(aiTextureMapMode_Wrap), + bPrivate(), + iUVSrc(0) { mTextureBlend = get_qnan(); } - Texture(Texture &&other) AI_NO_EXCEPT : - mTextureBlend(std::move(other.mTextureBlend)), - mMapName(std::move(mMapName)), - mOffsetU(std::move(mOffsetU)), - mOffsetV(std::move(mOffsetV)), - mScaleU(std::move(mScaleU)), - mScaleV(std::move(mScaleV)), - mRotation(std::move(mRotation)), - mMapMode(std::move(mMapMode)), - bPrivate(std::move(bPrivate)), - iUVSrc(std::move(iUVSrc)) { + Texture(Texture &&other) AI_NO_EXCEPT : mTextureBlend(std::move(other.mTextureBlend)), + mMapName(std::move(mMapName)), + mOffsetU(std::move(mOffsetU)), + mOffsetV(std::move(mOffsetV)), + mScaleU(std::move(mScaleU)), + mScaleV(std::move(mScaleV)), + mRotation(std::move(mRotation)), + mMapMode(std::move(mMapMode)), + bPrivate(std::move(bPrivate)), + iUVSrc(std::move(iUVSrc)) { + // empty + } + Texture &operator=(Texture &&other) AI_NO_EXCEPT { + if (this == &other) { + return *this; + } + + mTextureBlend = std::move(other.mTextureBlend); + mMapName = std::move(other.mMapName); + mOffsetU = std::move(other.mOffsetU); + mOffsetV = std::move(other.mOffsetV); + mScaleU = std::move(other.mScaleU); + mScaleV = std::move(other.mScaleV); + mRotation = std::move(other.mRotation); + mMapMode = std::move(other.mMapMode); + bPrivate = std::move(other.bPrivate); + iUVSrc = std::move(other.iUVSrc); + + return *this; } //! Specifies the blend factor for the texture @@ -381,55 +398,48 @@ struct Texture { // --------------------------------------------------------------------------- /** Helper structure representing a 3ds material */ -struct Material -{ +struct Material { //! Default constructor has been deleted Material() = delete; - //! Constructor with explicit name - explicit Material(const std::string &name) - : mName(name) - , mDiffuse ( ai_real( 0.6 ), ai_real( 0.6 ), ai_real( 0.6 ) ) // FIX ... we won't want object to be black - , mSpecularExponent ( ai_real( 0.0 ) ) - , mShininessStrength ( ai_real( 1.0 ) ) - , mShading(Discreet3DS::Gouraud) - , mTransparency ( ai_real( 1.0 ) ) - , mBumpHeight ( ai_real( 1.0 ) ) - , mTwoSided (false) - { + explicit Material(const std::string &name) : + mName(name), mDiffuse(ai_real(0.6), ai_real(0.6), ai_real(0.6)) // FIX ... we won't want object to be black + , + mSpecularExponent(ai_real(0.0)), + mShininessStrength(ai_real(1.0)), + mShading(Discreet3DS::Gouraud), + mTransparency(ai_real(1.0)), + mBumpHeight(ai_real(1.0)), + mTwoSided(false) { } - - Material(const Material &other) = default; + Material(const Material &other) = default; Material &operator=(const Material &other) = default; - //! Move constructor. This is explicitly written because MSVC doesn't support defaulting it Material(Material &&other) AI_NO_EXCEPT - : mName(std::move(other.mName)) - , mDiffuse(std::move(other.mDiffuse)) - , mSpecularExponent(std::move(other.mSpecularExponent)) - , mShininessStrength(std::move(other.mShininessStrength)) - , mSpecular(std::move(other.mSpecular)) - , mAmbient(std::move(other.mAmbient)) - , mShading(std::move(other.mShading)) - , mTransparency(std::move(other.mTransparency)) - , sTexDiffuse(std::move(other.sTexDiffuse)) - , sTexOpacity(std::move(other.sTexOpacity)) - , sTexSpecular(std::move(other.sTexSpecular)) - , sTexReflective(std::move(other.sTexReflective)) - , sTexBump(std::move(other.sTexBump)) - , sTexEmissive(std::move(other.sTexEmissive)) - , sTexShininess(std::move(other.sTexShininess)) - , mBumpHeight(std::move(other.mBumpHeight)) - , mEmissive(std::move(other.mEmissive)) - , sTexAmbient(std::move(other.sTexAmbient)) - , mTwoSided(std::move(other.mTwoSided)) - { + : mName(std::move(other.mName)), + mDiffuse(std::move(other.mDiffuse)), + mSpecularExponent(std::move(other.mSpecularExponent)), + mShininessStrength(std::move(other.mShininessStrength)), + mSpecular(std::move(other.mSpecular)), + mAmbient(std::move(other.mAmbient)), + mShading(std::move(other.mShading)), + mTransparency(std::move(other.mTransparency)), + sTexDiffuse(std::move(other.sTexDiffuse)), + sTexOpacity(std::move(other.sTexOpacity)), + sTexSpecular(std::move(other.sTexSpecular)), + sTexReflective(std::move(other.sTexReflective)), + sTexBump(std::move(other.sTexBump)), + sTexEmissive(std::move(other.sTexEmissive)), + sTexShininess(std::move(other.sTexShininess)), + mBumpHeight(std::move(other.mBumpHeight)), + mEmissive(std::move(other.mEmissive)), + sTexAmbient(std::move(other.sTexAmbient)), + mTwoSided(std::move(other.mTwoSided)) { } - Material &operator=(Material &&other) AI_NO_EXCEPT { if (this == &other) { return *this; @@ -458,10 +468,8 @@ struct Material return *this; } - virtual ~Material() {} - //! Name of the material std::string mName; //! Diffuse color of the material @@ -505,18 +513,15 @@ struct Material // --------------------------------------------------------------------------- /** Helper structure to represent a 3ds file mesh */ -struct Mesh : public MeshWithSmoothingGroups -{ +struct Mesh : public MeshWithSmoothingGroups { //! Default constructor has been deleted Mesh() = delete; //! Constructor with explicit name - explicit Mesh(const std::string &name) - : mName(name) - { + explicit Mesh(const std::string &name) : + mName(name) { } - //! Name of the mesh std::string mName; @@ -533,62 +538,48 @@ struct Mesh : public MeshWithSmoothingGroups // --------------------------------------------------------------------------- /** Float key - quite similar to aiVectorKey and aiQuatKey. Both are in the C-API, so it would be difficult to make them a template. */ -struct aiFloatKey -{ - double mTime; ///< The time of this key - ai_real mValue; ///< The value of this key +struct aiFloatKey { + double mTime; ///< The time of this key + ai_real mValue; ///< The value of this key #ifdef __cplusplus // time is not compared - bool operator == (const aiFloatKey& o) const - {return o.mValue == this->mValue;} + bool operator==(const aiFloatKey &o) const { return o.mValue == this->mValue; } - bool operator != (const aiFloatKey& o) const - {return o.mValue != this->mValue;} + bool operator!=(const aiFloatKey &o) const { return o.mValue != this->mValue; } // Only time is compared. This operator is defined // for use with std::sort - bool operator < (const aiFloatKey& o) const - {return mTime < o.mTime;} + bool operator<(const aiFloatKey &o) const { return mTime < o.mTime; } - bool operator > (const aiFloatKey& o) const - {return mTime > o.mTime;} + bool operator>(const aiFloatKey &o) const { return mTime > o.mTime; } #endif }; // --------------------------------------------------------------------------- /** Helper structure to represent a 3ds file node */ -struct Node -{ +struct Node { Node() = delete; - explicit Node(const std::string &name) - : mParent(NULL) - , mName(name) - , mInstanceNumber(0) - , mHierarchyPos (0) - , mHierarchyIndex (0) - , mInstanceCount (1) - { - aRotationKeys.reserve (20); - aPositionKeys.reserve (20); - aScalingKeys.reserve (20); + explicit Node(const std::string &name) : + mParent(NULL), mName(name), mInstanceNumber(0), mHierarchyPos(0), mHierarchyIndex(0), mInstanceCount(1) { + aRotationKeys.reserve(20); + aPositionKeys.reserve(20); + aScalingKeys.reserve(20); } - - ~Node() - { - for (unsigned int i = 0; i < mChildren.size();++i) + ~Node() { + for (unsigned int i = 0; i < mChildren.size(); ++i) delete mChildren[i]; } //! Pointer to the parent node - Node* mParent; + Node *mParent; //! Holds all child nodes - std::vector mChildren; + std::vector mChildren; //! Name of the node std::string mName; @@ -614,13 +605,12 @@ struct Node //! Scaling keys loaded from the file std::vector aScalingKeys; - // For target lights (spot lights and directional lights): // The position of the target - std::vector< aiVectorKey > aTargetPositionKeys; + std::vector aTargetPositionKeys; // For cameras: the camera roll angle - std::vector< aiFloatKey > aCameraRollKeys; + std::vector aCameraRollKeys; //! Pivot position loaded from the file aiVector3D vPivot; @@ -630,8 +620,7 @@ struct Node //! Add a child node, setup the right parent node for it //! \param pc Node to be 'adopted' - inline Node& push_back(Node* pc) - { + inline Node &push_back(Node *pc) { mChildren.push_back(pc); pc->mParent = this; return *this; @@ -639,8 +628,7 @@ struct Node }; // --------------------------------------------------------------------------- /** Helper structure analogue to aiScene */ -struct Scene -{ +struct Scene { //! List of all materials loaded //! NOTE: 3ds references materials globally std::vector mMaterials; @@ -649,17 +637,16 @@ struct Scene std::vector mMeshes; //! List of all cameras loaded - std::vector mCameras; + std::vector mCameras; //! List of all lights loaded - std::vector mLights; + std::vector mLights; //! Pointer to the root node of the scene // --- moved to main class // Node* pcRootNode; }; - } // end of namespace D3DS } // end of namespace Assimp diff --git a/code/3DS/3DSLoader.cpp b/code/3DS/3DSLoader.cpp index 3e8e08967..0b4a93a2b 100644 --- a/code/3DS/3DSLoader.cpp +++ b/code/3DS/3DSLoader.cpp @@ -158,13 +158,13 @@ void Discreet3DSImporter::SetupProperties(const Importer* /*pImp*/) void Discreet3DSImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) { - StreamReaderLE stream(pIOHandler->Open(pFile,"rb")); + StreamReaderLE theStream(pIOHandler->Open(pFile,"rb")); // We should have at least one chunk - if (stream.GetRemainingSize() < 16) { + if (theStream.GetRemainingSize() < 16) { throw DeadlyImportError("3DS file is either empty or corrupt: " + pFile); } - this->stream = &stream; + this->stream = &theStream; // Allocate our temporary 3DS representation D3DS::Scene _scene; @@ -599,16 +599,19 @@ void Discreet3DSImporter::InverseNodeSearch(D3DS::Node* pcNode,D3DS::Node* pcCur // ------------------------------------------------------------------------------------------------ // Find a node with a specific name in the import hierarchy -D3DS::Node* FindNode(D3DS::Node* root, const std::string& name) -{ - if (root->mName == name) +D3DS::Node* FindNode(D3DS::Node* root, const std::string& name) { + if (root->mName == name) { return root; - for (std::vector::iterator it = root->mChildren.begin();it != root->mChildren.end(); ++it) { - D3DS::Node* nd; - if (( nd = FindNode(*it,name))) - return nd; } - return NULL; + + for (std::vector::iterator it = root->mChildren.begin();it != root->mChildren.end(); ++it) { + D3DS::Node *nd = FindNode(*it, name); + if (nullptr != nd) { + return nd; + } + } + + return nullptr; } // ------------------------------------------------------------------------------------------------ diff --git a/code/AC/ACLoader.cpp b/code/AC/ACLoader.cpp index ea533743f..196f26253 100644 --- a/code/AC/ACLoader.cpp +++ b/code/AC/ACLoader.cpp @@ -44,25 +44,23 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /** @file Implementation of the AC3D importer class */ - - #ifndef ASSIMP_BUILD_NO_AC_IMPORTER // internal headers #include "ACLoader.h" -#include -#include -#include #include "Common/Importer.h" #include -#include +#include +#include +#include +#include +#include #include -#include #include #include -#include +#include #include -#include +#include #include using namespace Assimp; @@ -82,116 +80,102 @@ static const aiImporterDesc desc = { // ------------------------------------------------------------------------------------------------ // skip to the next token -#define AI_AC_SKIP_TO_NEXT_TOKEN() \ - if (!SkipSpaces(&buffer)) \ - { \ +#define AI_AC_SKIP_TO_NEXT_TOKEN() \ + if (!SkipSpaces(&buffer)) { \ ASSIMP_LOG_ERROR("AC3D: Unexpected EOF/EOL"); \ - continue; \ + continue; \ } // ------------------------------------------------------------------------------------------------ // read a string (may be enclosed in double quotation marks). buffer must point to " -#define AI_AC_GET_STRING(out) \ - if (*buffer == '\0') { \ - throw DeadlyImportError("AC3D: Unexpected EOF in string"); \ - } \ - ++buffer; \ - const char* sz = buffer; \ - while ('\"' != *buffer) \ - { \ - if (IsLineEnd( *buffer )) \ - { \ +#define AI_AC_GET_STRING(out) \ + if (*buffer == '\0') { \ + throw DeadlyImportError("AC3D: Unexpected EOF in string"); \ + } \ + ++buffer; \ + const char *sz = buffer; \ + while ('\"' != *buffer) { \ + if (IsLineEnd(*buffer)) { \ ASSIMP_LOG_ERROR("AC3D: Unexpected EOF/EOL in string"); \ - out = "ERROR"; \ - break; \ - } \ - ++buffer; \ - } \ - if (IsLineEnd( *buffer ))continue; \ - out = std::string(sz,(unsigned int)(buffer-sz)); \ + out = "ERROR"; \ + break; \ + } \ + ++buffer; \ + } \ + if (IsLineEnd(*buffer)) continue; \ + out = std::string(sz, (unsigned int)(buffer - sz)); \ ++buffer; - // ------------------------------------------------------------------------------------------------ // read 1 to n floats prefixed with an optional predefined identifier -#define AI_AC_CHECKED_LOAD_FLOAT_ARRAY(name,name_length,num,out) \ - AI_AC_SKIP_TO_NEXT_TOKEN(); \ - if (name_length) \ - { \ - if (strncmp(buffer,name,name_length) || !IsSpace(buffer[name_length])) \ - { \ - ASSIMP_LOG_ERROR("AC3D: Unexpexted token. " name " was expected."); \ - continue; \ - } \ - buffer += name_length+1; \ - } \ - for (unsigned int i = 0; i < num;++i) \ - { \ - AI_AC_SKIP_TO_NEXT_TOKEN(); \ - buffer = fast_atoreal_move(buffer,((float*)out)[i]); \ +#define AI_AC_CHECKED_LOAD_FLOAT_ARRAY(name, name_length, num, out) \ + AI_AC_SKIP_TO_NEXT_TOKEN(); \ + if (name_length) { \ + if (strncmp(buffer, name, name_length) || !IsSpace(buffer[name_length])) { \ + ASSIMP_LOG_ERROR("AC3D: Unexpexted token. " name " was expected."); \ + continue; \ + } \ + buffer += name_length + 1; \ + } \ + for (unsigned int _i = 0; _i < num; ++_i) { \ + AI_AC_SKIP_TO_NEXT_TOKEN(); \ + buffer = fast_atoreal_move(buffer, ((float *)out)[_i]); \ } - // ------------------------------------------------------------------------------------------------ // Constructor to be privately used by Importer -AC3DImporter::AC3DImporter() - : buffer(), - configSplitBFCull(), - configEvalSubdivision(), - mNumMeshes(), - mLights(), - lights(), - groups(), - polys(), - worlds() -{ +AC3DImporter::AC3DImporter() : + buffer(), + configSplitBFCull(), + configEvalSubdivision(), + mNumMeshes(), + mLights(), + mLightsCounter(0), + mGroupsCounter(0), + mPolysCounter(0), + mWorldsCounter(0) { // nothing to be done here } // ------------------------------------------------------------------------------------------------ // Destructor, private as well -AC3DImporter::~AC3DImporter() -{ +AC3DImporter::~AC3DImporter() { // nothing to be done here } // ------------------------------------------------------------------------------------------------ // Returns whether the class can handle the format of the given file. -bool AC3DImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const -{ +bool AC3DImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const { std::string extension = GetExtension(pFile); // fixme: are acc and ac3d *really* used? Some sources say they are - if(extension == "ac" || extension == "ac3d" || extension == "acc") { + if (extension == "ac" || extension == "ac3d" || extension == "acc") { return true; } if (!extension.length() || checkSig) { uint32_t token = AI_MAKE_MAGIC("AC3D"); - return CheckMagicToken(pIOHandler,pFile,&token,1,0); + return CheckMagicToken(pIOHandler, pFile, &token, 1, 0); } return false; } // ------------------------------------------------------------------------------------------------ // Loader meta information -const aiImporterDesc* AC3DImporter::GetInfo () const -{ +const aiImporterDesc *AC3DImporter::GetInfo() const { return &desc; } // ------------------------------------------------------------------------------------------------ // Get a pointer to the next line from the file -bool AC3DImporter::GetNextLine( ) -{ +bool AC3DImporter::GetNextLine() { SkipLine(&buffer); return SkipSpaces(&buffer); } // ------------------------------------------------------------------------------------------------ // Parse an object section in an AC file -void AC3DImporter::LoadObjectSection(std::vector& objects) -{ - if (!TokenMatch(buffer,"OBJECT",6)) +void AC3DImporter::LoadObjectSection(std::vector &objects) { + if (!TokenMatch(buffer, "OBJECT", 6)) return; SkipSpaces(&buffer); @@ -199,145 +183,109 @@ void AC3DImporter::LoadObjectSection(std::vector& objects) ++mNumMeshes; objects.push_back(Object()); - Object& obj = objects.back(); + Object &obj = objects.back(); - aiLight* light = NULL; - if (!ASSIMP_strincmp(buffer,"light",5)) - { + aiLight *light = NULL; + if (!ASSIMP_strincmp(buffer, "light", 5)) { // This is a light source. Add it to the list mLights->push_back(light = new aiLight()); // Return a point light with no attenuation light->mType = aiLightSource_POINT; - light->mColorDiffuse = light->mColorSpecular = aiColor3D(1.f,1.f,1.f); + light->mColorDiffuse = light->mColorSpecular = aiColor3D(1.f, 1.f, 1.f); light->mAttenuationConstant = 1.f; // Generate a default name for both the light source and the node // FIXME - what's the right way to print a size_t? Is 'zu' universally available? stick with the safe version. - light->mName.length = ::ai_snprintf(light->mName.data, MAXLEN, "ACLight_%i",static_cast(mLights->size())-1); - obj.name = std::string( light->mName.data ); + light->mName.length = ::ai_snprintf(light->mName.data, MAXLEN, "ACLight_%i", static_cast(mLights->size()) - 1); + obj.name = std::string(light->mName.data); ASSIMP_LOG_DEBUG("AC3D: Light source encountered"); obj.type = Object::Light; - } - else if (!ASSIMP_strincmp(buffer,"group",5)) - { + } else if (!ASSIMP_strincmp(buffer, "group", 5)) { obj.type = Object::Group; - } - else if (!ASSIMP_strincmp(buffer,"world",5)) - { + } else if (!ASSIMP_strincmp(buffer, "world", 5)) { obj.type = Object::World; - } - else obj.type = Object::Poly; - while (GetNextLine()) - { - if (TokenMatch(buffer,"kids",4)) - { + } else + obj.type = Object::Poly; + while (GetNextLine()) { + if (TokenMatch(buffer, "kids", 4)) { SkipSpaces(&buffer); - unsigned int num = strtoul10(buffer,&buffer); + unsigned int num = strtoul10(buffer, &buffer); GetNextLine(); - if (num) - { + if (num) { // load the children of this object recursively obj.children.reserve(num); for (unsigned int i = 0; i < num; ++i) LoadObjectSection(obj.children); } return; - } - else if (TokenMatch(buffer,"name",4)) - { + } else if (TokenMatch(buffer, "name", 4)) { SkipSpaces(&buffer); AI_AC_GET_STRING(obj.name); // If this is a light source, we'll also need to store // the name of the node in it. - if (light) - { + if (light) { light->mName.Set(obj.name); } - } - else if (TokenMatch(buffer,"texture",7)) - { + } else if (TokenMatch(buffer, "texture", 7)) { SkipSpaces(&buffer); AI_AC_GET_STRING(obj.texture); - } - else if (TokenMatch(buffer,"texrep",6)) - { + } else if (TokenMatch(buffer, "texrep", 6)) { SkipSpaces(&buffer); - AI_AC_CHECKED_LOAD_FLOAT_ARRAY("",0,2,&obj.texRepeat); + AI_AC_CHECKED_LOAD_FLOAT_ARRAY("", 0, 2, &obj.texRepeat); if (!obj.texRepeat.x || !obj.texRepeat.y) - obj.texRepeat = aiVector2D (1.f,1.f); - } - else if (TokenMatch(buffer,"texoff",6)) - { + obj.texRepeat = aiVector2D(1.f, 1.f); + } else if (TokenMatch(buffer, "texoff", 6)) { SkipSpaces(&buffer); - AI_AC_CHECKED_LOAD_FLOAT_ARRAY("",0,2,&obj.texOffset); - } - else if (TokenMatch(buffer,"rot",3)) - { + AI_AC_CHECKED_LOAD_FLOAT_ARRAY("", 0, 2, &obj.texOffset); + } else if (TokenMatch(buffer, "rot", 3)) { SkipSpaces(&buffer); - AI_AC_CHECKED_LOAD_FLOAT_ARRAY("",0,9,&obj.rotation); - } - else if (TokenMatch(buffer,"loc",3)) - { + AI_AC_CHECKED_LOAD_FLOAT_ARRAY("", 0, 9, &obj.rotation); + } else if (TokenMatch(buffer, "loc", 3)) { SkipSpaces(&buffer); - AI_AC_CHECKED_LOAD_FLOAT_ARRAY("",0,3,&obj.translation); - } - else if (TokenMatch(buffer,"subdiv",6)) - { + AI_AC_CHECKED_LOAD_FLOAT_ARRAY("", 0, 3, &obj.translation); + } else if (TokenMatch(buffer, "subdiv", 6)) { SkipSpaces(&buffer); - obj.subDiv = strtoul10(buffer,&buffer); - } - else if (TokenMatch(buffer,"crease",6)) - { + obj.subDiv = strtoul10(buffer, &buffer); + } else if (TokenMatch(buffer, "crease", 6)) { SkipSpaces(&buffer); obj.crease = fast_atof(buffer); - } - else if (TokenMatch(buffer,"numvert",7)) - { + } else if (TokenMatch(buffer, "numvert", 7)) { SkipSpaces(&buffer); - unsigned int t = strtoul10(buffer,&buffer); + unsigned int t = strtoul10(buffer, &buffer); if (t >= AI_MAX_ALLOC(aiVector3D)) { throw DeadlyImportError("AC3D: Too many vertices, would run out of memory"); } obj.vertices.reserve(t); - for (unsigned int i = 0; i < t;++i) - { - if (!GetNextLine()) - { + for (unsigned int i = 0; i < t; ++i) { + if (!GetNextLine()) { ASSIMP_LOG_ERROR("AC3D: Unexpected EOF: not all vertices have been parsed yet"); break; - } - else if (!IsNumeric(*buffer)) - { + } else if (!IsNumeric(*buffer)) { ASSIMP_LOG_ERROR("AC3D: Unexpected token: not all vertices have been parsed yet"); --buffer; // make sure the line is processed a second time break; } obj.vertices.push_back(aiVector3D()); - aiVector3D& v = obj.vertices.back(); - AI_AC_CHECKED_LOAD_FLOAT_ARRAY("",0,3,&v.x); + aiVector3D &v = obj.vertices.back(); + AI_AC_CHECKED_LOAD_FLOAT_ARRAY("", 0, 3, &v.x); } - } - else if (TokenMatch(buffer,"numsurf",7)) - { + } else if (TokenMatch(buffer, "numsurf", 7)) { SkipSpaces(&buffer); bool Q3DWorkAround = false; - const unsigned int t = strtoul10(buffer,&buffer); + const unsigned int t = strtoul10(buffer, &buffer); obj.surfaces.reserve(t); - for (unsigned int i = 0; i < t;++i) - { + for (unsigned int i = 0; i < t; ++i) { GetNextLine(); - if (!TokenMatch(buffer,"SURF",4)) - { + if (!TokenMatch(buffer, "SURF", 4)) { // FIX: this can occur for some files - Quick 3D for // example writes no surf chunks - if (!Q3DWorkAround) - { + if (!Q3DWorkAround) { ASSIMP_LOG_WARN("AC3D: SURF token was expected"); ASSIMP_LOG_DEBUG("Continuing with Quick3D Workaround enabled"); } @@ -348,27 +296,20 @@ void AC3DImporter::LoadObjectSection(std::vector& objects) } SkipSpaces(&buffer); obj.surfaces.push_back(Surface()); - Surface& surf = obj.surfaces.back(); + Surface &surf = obj.surfaces.back(); surf.flags = strtoul_cppstyle(buffer); - while (1) - { - if(!GetNextLine()) - { + while (1) { + if (!GetNextLine()) { throw DeadlyImportError("AC3D: Unexpected EOF: surface is incomplete"); } - if (TokenMatch(buffer,"mat",3)) - { + if (TokenMatch(buffer, "mat", 3)) { SkipSpaces(&buffer); surf.mat = strtoul10(buffer); - } - else if (TokenMatch(buffer,"refs",4)) - { + } else if (TokenMatch(buffer, "refs", 4)) { // --- see fix notes above - if (Q3DWorkAround) - { - if (!surf.entries.empty()) - { + if (Q3DWorkAround) { + if (!surf.entries.empty()) { buffer -= 6; break; } @@ -380,23 +321,19 @@ void AC3DImporter::LoadObjectSection(std::vector& objects) obj.numRefs += m; - for (unsigned int k = 0; k < m; ++k) - { - if(!GetNextLine()) - { + for (unsigned int k = 0; k < m; ++k) { + if (!GetNextLine()) { ASSIMP_LOG_ERROR("AC3D: Unexpected EOF: surface references are incomplete"); break; } surf.entries.push_back(Surface::SurfaceEntry()); - Surface::SurfaceEntry& entry = surf.entries.back(); + Surface::SurfaceEntry &entry = surf.entries.back(); - entry.first = strtoul10(buffer,&buffer); + entry.first = strtoul10(buffer, &buffer); SkipSpaces(&buffer); - AI_AC_CHECKED_LOAD_FLOAT_ARRAY("",0,2,&entry.second); + AI_AC_CHECKED_LOAD_FLOAT_ARRAY("", 0, 2, &entry.second); } - } - else - { + } else { --buffer; // make sure the line is processed a second time break; @@ -410,65 +347,57 @@ void AC3DImporter::LoadObjectSection(std::vector& objects) // ------------------------------------------------------------------------------------------------ // Convert a material from AC3DImporter::Material to aiMaterial -void AC3DImporter::ConvertMaterial(const Object& object, - const Material& matSrc, - aiMaterial& matDest) -{ +void AC3DImporter::ConvertMaterial(const Object &object, + const Material &matSrc, + aiMaterial &matDest) { aiString s; - if (matSrc.name.length()) - { + if (matSrc.name.length()) { s.Set(matSrc.name); - matDest.AddProperty(&s,AI_MATKEY_NAME); + matDest.AddProperty(&s, AI_MATKEY_NAME); } - if (object.texture.length()) - { + if (object.texture.length()) { s.Set(object.texture); - matDest.AddProperty(&s,AI_MATKEY_TEXTURE_DIFFUSE(0)); + matDest.AddProperty(&s, AI_MATKEY_TEXTURE_DIFFUSE(0)); // UV transformation if (1.f != object.texRepeat.x || 1.f != object.texRepeat.y || - object.texOffset.x || object.texOffset.y) - { + object.texOffset.x || object.texOffset.y) { aiUVTransform transform; transform.mScaling = object.texRepeat; transform.mTranslation = object.texOffset; - matDest.AddProperty(&transform,1,AI_MATKEY_UVTRANSFORM_DIFFUSE(0)); + matDest.AddProperty(&transform, 1, AI_MATKEY_UVTRANSFORM_DIFFUSE(0)); } } - matDest.AddProperty(&matSrc.rgb,1, AI_MATKEY_COLOR_DIFFUSE); - matDest.AddProperty(&matSrc.amb,1, AI_MATKEY_COLOR_AMBIENT); - matDest.AddProperty(&matSrc.emis,1,AI_MATKEY_COLOR_EMISSIVE); - matDest.AddProperty(&matSrc.spec,1,AI_MATKEY_COLOR_SPECULAR); + matDest.AddProperty(&matSrc.rgb, 1, AI_MATKEY_COLOR_DIFFUSE); + matDest.AddProperty(&matSrc.amb, 1, AI_MATKEY_COLOR_AMBIENT); + matDest.AddProperty(&matSrc.emis, 1, AI_MATKEY_COLOR_EMISSIVE); + matDest.AddProperty(&matSrc.spec, 1, AI_MATKEY_COLOR_SPECULAR); int n; - if (matSrc.shin) - { + if (matSrc.shin) { n = aiShadingMode_Phong; - matDest.AddProperty(&matSrc.shin,1,AI_MATKEY_SHININESS); - } - else n = aiShadingMode_Gouraud; - matDest.AddProperty(&n,1,AI_MATKEY_SHADING_MODEL); + matDest.AddProperty(&matSrc.shin, 1, AI_MATKEY_SHININESS); + } else + n = aiShadingMode_Gouraud; + matDest.AddProperty(&n, 1, AI_MATKEY_SHADING_MODEL); float f = 1.f - matSrc.trans; - matDest.AddProperty(&f,1,AI_MATKEY_OPACITY); + matDest.AddProperty(&f, 1, AI_MATKEY_OPACITY); } // ------------------------------------------------------------------------------------------------ // Converts the loaded data to the internal verbose representation -aiNode* AC3DImporter::ConvertObjectSection(Object& object, - std::vector& meshes, - std::vector& outMaterials, - const std::vector& materials, - aiNode* parent) -{ - aiNode* node = new aiNode(); +aiNode *AC3DImporter::ConvertObjectSection(Object &object, + std::vector &meshes, + std::vector &outMaterials, + const std::vector &materials, + aiNode *parent) { + aiNode *node = new aiNode(); node->mParent = parent; - if (object.vertices.size()) - { - if (!object.surfaces.size() || !object.numRefs) - { + if (object.vertices.size()) { + if (!object.surfaces.size() || !object.numRefs) { /* " An object with 7 vertices (no surfaces, no materials defined). This is a good way of getting point data into AC3D. The Vertex->create convex-surface/object can be used on these @@ -479,17 +408,16 @@ aiNode* AC3DImporter::ConvertObjectSection(Object& object, */ ASSIMP_LOG_INFO("AC3D: No surfaces defined in object definition, " - "a point list is returned"); + "a point list is returned"); meshes.push_back(new aiMesh()); - aiMesh* mesh = meshes.back(); + aiMesh *mesh = meshes.back(); mesh->mNumFaces = mesh->mNumVertices = (unsigned int)object.vertices.size(); - aiFace* faces = mesh->mFaces = new aiFace[mesh->mNumFaces]; - aiVector3D* verts = mesh->mVertices = new aiVector3D[mesh->mNumVertices]; + aiFace *faces = mesh->mFaces = new aiFace[mesh->mNumFaces]; + aiVector3D *verts = mesh->mVertices = new aiVector3D[mesh->mNumVertices]; - for (unsigned int i = 0; i < mesh->mNumVertices;++i,++faces,++verts) - { + for (unsigned int i = 0; i < mesh->mNumVertices; ++i, ++faces, ++verts) { *verts = object.vertices[i]; faces->mNumIndices = 1; faces->mIndices = new unsigned int[1]; @@ -502,86 +430,77 @@ aiNode* AC3DImporter::ConvertObjectSection(Object& object, mesh->mMaterialIndex = 0; outMaterials.push_back(new aiMaterial()); ConvertMaterial(object, materials[0], *outMaterials.back()); - } - else - { + } else { // need to generate one or more meshes for this object. // find out how many different materials we have - typedef std::pair< unsigned int, unsigned int > IntPair; - typedef std::vector< IntPair > MatTable; - MatTable needMat(materials.size(),IntPair(0,0)); + typedef std::pair IntPair; + typedef std::vector MatTable; + MatTable needMat(materials.size(), IntPair(0, 0)); - std::vector::iterator it,end = object.surfaces.end(); - std::vector::iterator it2,end2; + std::vector::iterator it, end = object.surfaces.end(); + std::vector::iterator it2, end2; - for (it = object.surfaces.begin(); it != end; ++it) - { + for (it = object.surfaces.begin(); it != end; ++it) { unsigned int idx = (*it).mat; - if (idx >= needMat.size()) - { + if (idx >= needMat.size()) { ASSIMP_LOG_ERROR("AC3D: material index is out of range"); idx = 0; } - if ((*it).entries.empty()) - { + if ((*it).entries.empty()) { ASSIMP_LOG_WARN("AC3D: surface her zero vertex references"); } // validate all vertex indices to make sure we won't crash here - for (it2 = (*it).entries.begin(), - end2 = (*it).entries.end(); it2 != end2; ++it2) - { - if ((*it2).first >= object.vertices.size()) - { + for (it2 = (*it).entries.begin(), + end2 = (*it).entries.end(); + it2 != end2; ++it2) { + if ((*it2).first >= object.vertices.size()) { ASSIMP_LOG_WARN("AC3D: Invalid vertex reference"); (*it2).first = 0; } } - if (!needMat[idx].first)++node->mNumMeshes; + if (!needMat[idx].first) ++node->mNumMeshes; - switch ((*it).flags & 0xf) - { - // closed line - case 0x1: + switch ((*it).flags & 0xf) { + // closed line + case 0x1: - needMat[idx].first += (unsigned int)(*it).entries.size(); - needMat[idx].second += (unsigned int)(*it).entries.size()<<1u; - break; + needMat[idx].first += (unsigned int)(*it).entries.size(); + needMat[idx].second += (unsigned int)(*it).entries.size() << 1u; + break; - // unclosed line - case 0x2: + // unclosed line + case 0x2: - needMat[idx].first += (unsigned int)(*it).entries.size()-1; - needMat[idx].second += ((unsigned int)(*it).entries.size()-1)<<1u; - break; + needMat[idx].first += (unsigned int)(*it).entries.size() - 1; + needMat[idx].second += ((unsigned int)(*it).entries.size() - 1) << 1u; + break; - // 0 == polygon, else unknown - default: + // 0 == polygon, else unknown + default: - if ((*it).flags & 0xf) - { - ASSIMP_LOG_WARN("AC3D: The type flag of a surface is unknown"); - (*it).flags &= ~(0xf); - } + if ((*it).flags & 0xf) { + ASSIMP_LOG_WARN("AC3D: The type flag of a surface is unknown"); + (*it).flags &= ~(0xf); + } - // the number of faces increments by one, the number - // of vertices by surface.numref. - needMat[idx].first++; - needMat[idx].second += (unsigned int)(*it).entries.size(); + // the number of faces increments by one, the number + // of vertices by surface.numref. + needMat[idx].first++; + needMat[idx].second += (unsigned int)(*it).entries.size(); }; } - unsigned int* pip = node->mMeshes = new unsigned int[node->mNumMeshes]; + unsigned int *pip = node->mMeshes = new unsigned int[node->mNumMeshes]; unsigned int mat = 0; const size_t oldm = meshes.size(); for (MatTable::const_iterator cit = needMat.begin(), cend = needMat.end(); - cit != cend; ++cit, ++mat) - { - if (!(*cit).first)continue; + cit != cend; ++cit, ++mat) { + if (!(*cit).first) continue; // allocate a new aiMesh object *pip++ = (unsigned int)meshes.size(); - aiMesh* mesh = new aiMesh(); + aiMesh *mesh = new aiMesh(); meshes.push_back(mesh); mesh->mMaterialIndex = (unsigned int)outMaterials.size(); @@ -595,7 +514,7 @@ aiNode* AC3DImporter::ConvertObjectSection(Object& object, } else if (mesh->mNumFaces > AI_MAX_ALLOC(aiFace)) { throw DeadlyImportError("AC3D: Too many faces, would run out of memory"); } - aiFace* faces = mesh->mFaces = new aiFace[mesh->mNumFaces]; + aiFace *faces = mesh->mFaces = new aiFace[mesh->mNumFaces]; mesh->mNumVertices = (*cit).second; if (mesh->mNumVertices == 0) { @@ -603,35 +522,29 @@ aiNode* AC3DImporter::ConvertObjectSection(Object& object, } else if (mesh->mNumVertices > AI_MAX_ALLOC(aiVector3D)) { throw DeadlyImportError("AC3D: Too many vertices, would run out of memory"); } - aiVector3D* vertices = mesh->mVertices = new aiVector3D[mesh->mNumVertices]; + aiVector3D *vertices = mesh->mVertices = new aiVector3D[mesh->mNumVertices]; unsigned int cur = 0; // allocate UV coordinates, but only if the texture name for the // surface is not empty - aiVector3D* uv = NULL; - if(object.texture.length()) - { + aiVector3D *uv = NULL; + if (object.texture.length()) { uv = mesh->mTextureCoords[0] = new aiVector3D[mesh->mNumVertices]; mesh->mNumUVComponents[0] = 2; } - for (it = object.surfaces.begin(); it != end; ++it) - { - if (mat == (*it).mat) - { - const Surface& src = *it; + for (it = object.surfaces.begin(); it != end; ++it) { + if (mat == (*it).mat) { + const Surface &src = *it; // closed polygon unsigned int type = (*it).flags & 0xf; - if (!type) - { - aiFace& face = *faces++; - if((face.mNumIndices = (unsigned int)src.entries.size())) - { + if (!type) { + aiFace &face = *faces++; + if ((face.mNumIndices = (unsigned int)src.entries.size())) { face.mIndices = new unsigned int[face.mNumIndices]; - for (unsigned int i = 0; i < face.mNumIndices;++i,++vertices) - { - const Surface::SurfaceEntry& entry = src.entries[i]; + for (unsigned int i = 0; i < face.mNumIndices; ++i, ++vertices) { + const Surface::SurfaceEntry &entry = src.entries[i]; face.mIndices[i] = cur++; // copy vertex positions @@ -640,28 +553,23 @@ aiNode* AC3DImporter::ConvertObjectSection(Object& object, } *vertices = object.vertices[entry.first] + object.translation; - // copy texture coordinates - if (uv) - { - uv->x = entry.second.x; - uv->y = entry.second.y; + if (uv) { + uv->x = entry.second.x; + uv->y = entry.second.y; ++uv; } } } - } - else - { + } else { - it2 = (*it).entries.begin(); + it2 = (*it).entries.begin(); // either a closed or an unclosed line unsigned int tmp = (unsigned int)(*it).entries.size(); - if (0x2 == type)--tmp; - for (unsigned int m = 0; m < tmp;++m) - { - aiFace& face = *faces++; + if (0x2 == type) --tmp; + for (unsigned int m = 0; m < tmp; ++m) { + aiFace &face = *faces++; face.mNumIndices = 2; face.mIndices = new unsigned int[2]; @@ -669,35 +577,31 @@ aiNode* AC3DImporter::ConvertObjectSection(Object& object, face.mIndices[1] = cur++; // copy vertex positions - if (it2 == (*it).entries.end() ) { + if (it2 == (*it).entries.end()) { throw DeadlyImportError("AC3D: Bad line"); } ai_assert((*it2).first < object.vertices.size()); *vertices++ = object.vertices[(*it2).first]; // copy texture coordinates - if (uv) - { - uv->x = (*it2).second.x; - uv->y = (*it2).second.y; + if (uv) { + uv->x = (*it2).second.x; + uv->y = (*it2).second.y; ++uv; } - - if (0x1 == type && tmp-1 == m) - { + if (0x1 == type && tmp - 1 == m) { // if this is a closed line repeat its beginning now - it2 = (*it).entries.begin(); - } - else ++it2; + it2 = (*it).entries.begin(); + } else + ++it2; // second point *vertices++ = object.vertices[(*it2).first]; - if (uv) - { - uv->x = (*it2).second.x; - uv->y = (*it2).second.y; + if (uv) { + uv->x = (*it2).second.x; + uv->y = (*it2).second.y; ++uv; } } @@ -709,20 +613,18 @@ aiNode* AC3DImporter::ConvertObjectSection(Object& object, // Now apply catmull clark subdivision if necessary. We split meshes into // materials which is not done by AC3D during smoothing, so we need to // collect all meshes using the same material group. - if (object.subDiv) { + if (object.subDiv) { if (configEvalSubdivision) { std::unique_ptr div(Subdivider::Create(Subdivider::CATMULL_CLARKE)); - ASSIMP_LOG_INFO("AC3D: Evaluating subdivision surface: "+object.name); + ASSIMP_LOG_INFO("AC3D: Evaluating subdivision surface: " + object.name); - std::vector cpy(meshes.size()-oldm,NULL); - div->Subdivide(&meshes[oldm],cpy.size(),&cpy.front(),object.subDiv,true); - std::copy(cpy.begin(),cpy.end(),meshes.begin()+oldm); + std::vector cpy(meshes.size() - oldm, NULL); + div->Subdivide(&meshes[oldm], cpy.size(), &cpy.front(), object.subDiv, true); + std::copy(cpy.begin(), cpy.end(), meshes.begin() + oldm); // previous meshes are deleted vy Subdivide(). - } - else { - ASSIMP_LOG_INFO("AC3D: Letting the subdivision surface untouched due to my configuration: " - +object.name); + } else { + ASSIMP_LOG_INFO("AC3D: Letting the subdivision surface untouched due to my configuration: " + object.name); } } } @@ -730,48 +632,42 @@ aiNode* AC3DImporter::ConvertObjectSection(Object& object, if (object.name.length()) node->mName.Set(object.name); - else - { + else { // generate a name depending on the type of the node - switch (object.type) - { - case Object::Group: - node->mName.length = ::ai_snprintf(node->mName.data, MAXLEN, "ACGroup_%i",groups++); - break; - case Object::Poly: - node->mName.length = ::ai_snprintf(node->mName.data, MAXLEN, "ACPoly_%i",polys++); - break; - case Object::Light: - node->mName.length = ::ai_snprintf(node->mName.data, MAXLEN, "ACLight_%i",lights++); - break; + switch (object.type) { + case Object::Group: + node->mName.length = ::ai_snprintf(node->mName.data, MAXLEN, "ACGroup_%i", mGroupsCounter++); + break; + case Object::Poly: + node->mName.length = ::ai_snprintf(node->mName.data, MAXLEN, "ACPoly_%i", mPolysCounter++); + break; + case Object::Light: + node->mName.length = ::ai_snprintf(node->mName.data, MAXLEN, "ACLight_%i", mLightsCounter++); + break; - // there shouldn't be more than one world, but we don't care - case Object::World: - node->mName.length = ::ai_snprintf(node->mName.data, MAXLEN, "ACWorld_%i",worlds++); - break; + // there shouldn't be more than one world, but we don't care + case Object::World: + node->mName.length = ::ai_snprintf(node->mName.data, MAXLEN, "ACWorld_%i", mWorldsCounter++); + break; } } - // setup the local transformation matrix of the object // compute the transformation offset to the parent node - node->mTransformation = aiMatrix4x4 ( object.rotation ); + node->mTransformation = aiMatrix4x4(object.rotation); - if (object.type == Object::Group || !object.numRefs) - { + if (object.type == Object::Group || !object.numRefs) { node->mTransformation.a4 = object.translation.x; node->mTransformation.b4 = object.translation.y; node->mTransformation.c4 = object.translation.z; } // add children to the object - if (object.children.size()) - { + if (object.children.size()) { node->mNumChildren = (unsigned int)object.children.size(); - node->mChildren = new aiNode*[node->mNumChildren]; - for (unsigned int i = 0; i < node->mNumChildren;++i) - { - node->mChildren[i] = ConvertObjectSection(object.children[i],meshes,outMaterials,materials,node); + node->mChildren = new aiNode *[node->mNumChildren]; + for (unsigned int i = 0; i < node->mNumChildren; ++i) { + node->mChildren[i] = ConvertObjectSection(object.children[i], meshes, outMaterials, materials, node); } } @@ -779,40 +675,38 @@ aiNode* AC3DImporter::ConvertObjectSection(Object& object, } // ------------------------------------------------------------------------------------------------ -void AC3DImporter::SetupProperties(const Importer* pImp) -{ - configSplitBFCull = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_AC_SEPARATE_BFCULL,1) ? true : false; - configEvalSubdivision = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_AC_EVAL_SUBDIVISION,1) ? true : false; +void AC3DImporter::SetupProperties(const Importer *pImp) { + configSplitBFCull = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_AC_SEPARATE_BFCULL, 1) ? true : false; + configEvalSubdivision = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_AC_EVAL_SUBDIVISION, 1) ? true : false; } // ------------------------------------------------------------------------------------------------ // Imports the given file into the given scene structure. -void AC3DImporter::InternReadFile( const std::string& pFile, - aiScene* pScene, IOSystem* pIOHandler) -{ - std::unique_ptr file( pIOHandler->Open( pFile, "rb")); +void AC3DImporter::InternReadFile(const std::string &pFile, + aiScene *pScene, IOSystem *pIOHandler) { + std::unique_ptr file(pIOHandler->Open(pFile, "rb")); // Check whether we can read from the file - if( file.get() == NULL) - throw DeadlyImportError( "Failed to open AC3D file " + pFile + "."); + if (file.get() == NULL) + throw DeadlyImportError("Failed to open AC3D file " + pFile + "."); // allocate storage and copy the contents of the file to a memory buffer std::vector mBuffer2; - TextFileToBuffer(file.get(),mBuffer2); + TextFileToBuffer(file.get(), mBuffer2); buffer = &mBuffer2[0]; mNumMeshes = 0; - lights = polys = worlds = groups = 0; + mLightsCounter = mPolysCounter = mWorldsCounter = mGroupsCounter = 0; - if (::strncmp(buffer,"AC3D",4)) { + if (::strncmp(buffer, "AC3D", 4)) { throw DeadlyImportError("AC3D: No valid AC3D file, magic sequence not found"); } // print the file format version to the console - unsigned int version = HexDigitToDecimal( buffer[4] ); + unsigned int version = HexDigitToDecimal(buffer[4]); char msg[3]; - ASSIMP_itoa10(msg,3,version); + ASSIMP_itoa10(msg, 3, version); ASSIMP_LOG_INFO_F("AC3D file format version: ", msg); std::vector materials; @@ -821,89 +715,81 @@ void AC3DImporter::InternReadFile( const std::string& pFile, std::vector rootObjects; rootObjects.reserve(5); - std::vector lights; - mLights = & lights; + std::vector lights; + mLights = &lights; - while (GetNextLine()) - { - if (TokenMatch(buffer,"MATERIAL",8)) - { + while (GetNextLine()) { + if (TokenMatch(buffer, "MATERIAL", 8)) { materials.push_back(Material()); - Material& mat = materials.back(); + Material &mat = materials.back(); // manually parse the material ... sscanf would use the buldin atof ... // Format: (name) rgb %f %f %f amb %f %f %f emis %f %f %f spec %f %f %f shi %d trans %f AI_AC_SKIP_TO_NEXT_TOKEN(); - if ('\"' == *buffer) - { + if ('\"' == *buffer) { AI_AC_GET_STRING(mat.name); AI_AC_SKIP_TO_NEXT_TOKEN(); } - AI_AC_CHECKED_LOAD_FLOAT_ARRAY("rgb",3,3,&mat.rgb); - AI_AC_CHECKED_LOAD_FLOAT_ARRAY("amb",3,3,&mat.amb); - AI_AC_CHECKED_LOAD_FLOAT_ARRAY("emis",4,3,&mat.emis); - AI_AC_CHECKED_LOAD_FLOAT_ARRAY("spec",4,3,&mat.spec); - AI_AC_CHECKED_LOAD_FLOAT_ARRAY("shi",3,1,&mat.shin); - AI_AC_CHECKED_LOAD_FLOAT_ARRAY("trans",5,1,&mat.trans); + AI_AC_CHECKED_LOAD_FLOAT_ARRAY("rgb", 3, 3, &mat.rgb); + AI_AC_CHECKED_LOAD_FLOAT_ARRAY("amb", 3, 3, &mat.amb); + AI_AC_CHECKED_LOAD_FLOAT_ARRAY("emis", 4, 3, &mat.emis); + AI_AC_CHECKED_LOAD_FLOAT_ARRAY("spec", 4, 3, &mat.spec); + AI_AC_CHECKED_LOAD_FLOAT_ARRAY("shi", 3, 1, &mat.shin); + AI_AC_CHECKED_LOAD_FLOAT_ARRAY("trans", 5, 1, &mat.trans); } LoadObjectSection(rootObjects); } - if (rootObjects.empty() || !mNumMeshes) - { + if (rootObjects.empty() || !mNumMeshes) { throw DeadlyImportError("AC3D: No meshes have been loaded"); } - if (materials.empty()) - { + if (materials.empty()) { ASSIMP_LOG_WARN("AC3D: No material has been found"); materials.push_back(Material()); } - mNumMeshes += (mNumMeshes>>2u) + 1; - std::vector meshes; + mNumMeshes += (mNumMeshes >> 2u) + 1; + std::vector meshes; meshes.reserve(mNumMeshes); - std::vector omaterials; + std::vector omaterials; materials.reserve(mNumMeshes); // generate a dummy root if there are multiple objects on the top layer - Object* root; + Object *root; if (1 == rootObjects.size()) root = &rootObjects[0]; - else - { + else { root = new Object(); } // now convert the imported stuff to our output data structure - pScene->mRootNode = ConvertObjectSection(*root,meshes,omaterials,materials); - if (1 != rootObjects.size())delete root; + pScene->mRootNode = ConvertObjectSection(*root, meshes, omaterials, materials); + if (1 != rootObjects.size()) delete root; - if (!::strncmp( pScene->mRootNode->mName.data, "Node", 4)) + if (!::strncmp(pScene->mRootNode->mName.data, "Node", 4)) pScene->mRootNode->mName.Set(""); // copy meshes - if (meshes.empty()) - { + if (meshes.empty()) { throw DeadlyImportError("An unknown error occurred during converting"); } pScene->mNumMeshes = (unsigned int)meshes.size(); - pScene->mMeshes = new aiMesh*[pScene->mNumMeshes]; - ::memcpy(pScene->mMeshes,&meshes[0],pScene->mNumMeshes*sizeof(void*)); + pScene->mMeshes = new aiMesh *[pScene->mNumMeshes]; + ::memcpy(pScene->mMeshes, &meshes[0], pScene->mNumMeshes * sizeof(void *)); // copy materials pScene->mNumMaterials = (unsigned int)omaterials.size(); - pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials]; - ::memcpy(pScene->mMaterials,&omaterials[0],pScene->mNumMaterials*sizeof(void*)); + pScene->mMaterials = new aiMaterial *[pScene->mNumMaterials]; + ::memcpy(pScene->mMaterials, &omaterials[0], pScene->mNumMaterials * sizeof(void *)); // copy lights pScene->mNumLights = (unsigned int)lights.size(); - if (lights.size()) - { - pScene->mLights = new aiLight*[lights.size()]; - ::memcpy(pScene->mLights,&lights[0],lights.size()*sizeof(void*)); + if (lights.size()) { + pScene->mLights = new aiLight *[lights.size()]; + ::memcpy(pScene->mLights, &lights[0], lights.size() * sizeof(void *)); } } diff --git a/code/AC/ACLoader.h b/code/AC/ACLoader.h index 1fc654f3c..890fb2ac2 100644 --- a/code/AC/ACLoader.h +++ b/code/AC/ACLoader.h @@ -268,7 +268,7 @@ private: std::vector* mLights; // name counters - unsigned int lights, groups, polys, worlds; + unsigned int mLightsCounter, mGroupsCounter, mPolysCounter, mWorldsCounter; }; } // end of namespace Assimp diff --git a/code/AMF/AMFImporter_Postprocess.cpp b/code/AMF/AMFImporter_Postprocess.cpp index 8496d8ded..273b8e0c4 100644 --- a/code/AMF/AMFImporter_Postprocess.cpp +++ b/code/AMF/AMFImporter_Postprocess.cpp @@ -465,7 +465,7 @@ std::list mesh_idx; { auto VertexIndex_GetMinimal = [](const std::list& pFaceList, const size_t* pBiggerThan) -> size_t { - size_t rv; + size_t rv=0; if(pBiggerThan != nullptr) { diff --git a/code/HMP/HMPLoader.cpp b/code/HMP/HMPLoader.cpp index 0d1334fdd..0dea09ee0 100644 --- a/code/HMP/HMPLoader.cpp +++ b/code/HMP/HMPLoader.cpp @@ -118,11 +118,11 @@ void HMPImporter::InternReadFile( const std::string& pFile, aiScene* _pScene, IOSystem* _pIOHandler) { pScene = _pScene; - pIOHandler = _pIOHandler; - std::unique_ptr file( pIOHandler->Open( pFile)); + mIOHandler = _pIOHandler; + std::unique_ptr file(mIOHandler->Open(pFile)); // Check whether we can read from the file - if( file.get() == NULL) + if( file.get() == nullptr) throw DeadlyImportError( "Failed to open HMP file " + pFile + "."); // Check whether the HMP file is large enough to contain diff --git a/code/LWO/LWOAnimation.cpp b/code/LWO/LWOAnimation.cpp index ae9c4c13b..c5913b7f1 100644 --- a/code/LWO/LWOAnimation.cpp +++ b/code/LWO/LWOAnimation.cpp @@ -185,9 +185,11 @@ void AnimResolver::UpdateAnimRangeSetup() for (unsigned int i = 0; i < num; ++i) { m = n+old_size*(i+1); std::copy(n,n+old_size,m); - - if ((*it).pre == LWO::PrePostBehaviour_Oscillate && (reverse = !reverse)) + const bool res = ((*it).pre == LWO::PrePostBehaviour_Oscillate); + reverse = !reverse; + if (res && reverse ) { std::reverse(m,m+old_size-1); + } } // update time values @@ -533,7 +535,7 @@ void AnimResolver::GetKeys(std::vector& out, // ------------------------------------------------------------------------------------------------ // Extract animation channel -void AnimResolver::ExtractAnimChannel(aiNodeAnim** out, unsigned int flags /*= 0*/) +void AnimResolver::ExtractAnimChannel(aiNodeAnim** out, unsigned int /*= 0*/) { *out = NULL; diff --git a/code/MDL/MDLLoader.cpp b/code/MDL/MDLLoader.cpp index 11c6e3ecb..4128b4bfe 100644 --- a/code/MDL/MDLLoader.cpp +++ b/code/MDL/MDLLoader.cpp @@ -49,17 +49,17 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef ASSIMP_BUILD_NO_MDL_IMPORTER #include "MDL/MDLLoader.h" -#include "MDL/MDLDefaultColorMap.h" #include "MD2/MD2FileData.h" #include "MDL/HalfLife/HL1MDLLoader.h" +#include "MDL/MDLDefaultColorMap.h" -#include #include -#include -#include +#include +#include #include #include -#include +#include +#include #include @@ -80,24 +80,19 @@ static const aiImporterDesc desc = { // ------------------------------------------------------------------------------------------------ // Ugly stuff ... nevermind -#define _AI_MDL7_ACCESS(_data, _index, _limit, _type) \ - (*((const _type*)(((const char*)_data) + _index * _limit))) +#define _AI_MDL7_ACCESS(_data, _index, _limit, _type) \ + (*((const _type *)(((const char *)_data) + _index * _limit))) -#define _AI_MDL7_ACCESS_PTR(_data, _index, _limit, _type) \ - ((BE_NCONST _type*)(((const char*)_data) + _index * _limit)) +#define _AI_MDL7_ACCESS_PTR(_data, _index, _limit, _type) \ + ((BE_NCONST _type *)(((const char *)_data) + _index * _limit)) -#define _AI_MDL7_ACCESS_VERT(_data, _index, _limit) \ - _AI_MDL7_ACCESS(_data,_index,_limit,MDL::Vertex_MDL7) +#define _AI_MDL7_ACCESS_VERT(_data, _index, _limit) \ + _AI_MDL7_ACCESS(_data, _index, _limit, MDL::Vertex_MDL7) // ------------------------------------------------------------------------------------------------ // Constructor to be privately used by Importer -MDLImporter::MDLImporter() -: configFrameID() -, mBuffer() -, iGSFileVersion() -, pIOHandler() -, pScene() -, iFileSize() { +MDLImporter::MDLImporter() : + configFrameID(), mBuffer(), iGSFileVersion(), mIOHandler(nullptr), pScene(), iFileSize() { // empty } @@ -109,11 +104,11 @@ MDLImporter::~MDLImporter() { // ------------------------------------------------------------------------------------------------ // Returns whether the class can handle the format of the given file. -bool MDLImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const { +bool MDLImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const { const std::string extension = GetExtension(pFile); // if check for extension is not enough, check for the magic tokens - if (extension == "mdl" || !extension.length() || checkSig) { + if (extension == "mdl" || !extension.length() || checkSig) { uint32_t tokens[8]; tokens[0] = AI_MDL_MAGIC_NUMBER_LE_HL2a; tokens[1] = AI_MDL_MAGIC_NUMBER_LE_HL2b; @@ -123,26 +118,25 @@ bool MDLImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool tokens[5] = AI_MDL_MAGIC_NUMBER_LE_GS4; tokens[6] = AI_MDL_MAGIC_NUMBER_LE_GS3; tokens[7] = AI_MDL_MAGIC_NUMBER_LE; - return CheckMagicToken(pIOHandler,pFile,tokens,8,0); + return CheckMagicToken(pIOHandler, pFile, tokens, 8, 0); } return false; } // ------------------------------------------------------------------------------------------------ // Setup configuration properties -void MDLImporter::SetupProperties(const Importer* pImp) -{ - configFrameID = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_MDL_KEYFRAME,-1); +void MDLImporter::SetupProperties(const Importer *pImp) { + configFrameID = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_MDL_KEYFRAME, -1); // The // AI_CONFIG_IMPORT_MDL_KEYFRAME option overrides the // AI_CONFIG_IMPORT_GLOBAL_KEYFRAME option. - if(static_cast(-1) == configFrameID) { - configFrameID = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_GLOBAL_KEYFRAME,0); + if (static_cast(-1) == configFrameID) { + configFrameID = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_GLOBAL_KEYFRAME, 0); } // AI_CONFIG_IMPORT_MDL_COLORMAP - palette file - configPalette = pImp->GetPropertyString(AI_CONFIG_IMPORT_MDL_COLORMAP,"colormap.lmp"); + configPalette = pImp->GetPropertyString(AI_CONFIG_IMPORT_MDL_COLORMAP, "colormap.lmp"); // Read configuration specific to MDL (Half-Life 1). mHL1ImportSettings.read_animations = pImp->GetPropertyBool(AI_CONFIG_IMPORT_MDL_HL1_READ_ANIMATIONS, true); @@ -159,121 +153,114 @@ void MDLImporter::SetupProperties(const Importer* pImp) // ------------------------------------------------------------------------------------------------ // Get a list of all supported extensions -const aiImporterDesc* MDLImporter::GetInfo () const -{ +const aiImporterDesc *MDLImporter::GetInfo() const { return &desc; } // ------------------------------------------------------------------------------------------------ // Imports the given file into the given scene structure. -void MDLImporter::InternReadFile( const std::string& pFile, - aiScene* _pScene, IOSystem* _pIOHandler) -{ - pScene = _pScene; - pIOHandler = _pIOHandler; - std::unique_ptr file( pIOHandler->Open( pFile)); +void MDLImporter::InternReadFile(const std::string &pFile, + aiScene *_pScene, IOSystem *pIOHandler) { + pScene = _pScene; + mIOHandler = pIOHandler; + std::unique_ptr file(pIOHandler->Open(pFile)); // Check whether we can read from the file - if( file.get() == NULL) { - throw DeadlyImportError( "Failed to open MDL file " + pFile + "."); + if (file.get() == nullptr) { + throw DeadlyImportError("Failed to open MDL file " + pFile + "."); } // This should work for all other types of MDL files, too ... // the HL1 sequence group header is one of the smallest, afaik iFileSize = (unsigned int)file->FileSize(); - if( iFileSize < sizeof(MDL::HalfLife::SequenceHeader_HL1)) { - throw DeadlyImportError( "MDL File is too small."); + if (iFileSize < sizeof(MDL::HalfLife::SequenceHeader_HL1)) { + throw DeadlyImportError("MDL File is too small."); } - + // delete the file buffer and cleanup. auto DeleteBufferAndCleanup = [&]() { if (mBuffer) { - delete [] mBuffer; + delete[] mBuffer; mBuffer = nullptr; } - AI_DEBUG_INVALIDATE_PTR(pIOHandler); + AI_DEBUG_INVALIDATE_PTR(mIOHandler); AI_DEBUG_INVALIDATE_PTR(pScene); }; - + try { // Allocate storage and copy the contents of the file to a memory buffer - mBuffer = new unsigned char[iFileSize+1]; - file->Read( (void*)mBuffer, 1, iFileSize); + mBuffer = new unsigned char[iFileSize + 1]; + file->Read((void *)mBuffer, 1, iFileSize); // Append a binary zero to the end of the buffer. // this is just for safety that string parsing routines // find the end of the buffer ... mBuffer[iFileSize] = '\0'; - const uint32_t iMagicWord = *((uint32_t*)mBuffer); + const uint32_t iMagicWord = *((uint32_t *)mBuffer); // Determine the file subtype and call the appropriate member function // Original Quake1 format - if (AI_MDL_MAGIC_NUMBER_BE == iMagicWord || AI_MDL_MAGIC_NUMBER_LE == iMagicWord) { + if (AI_MDL_MAGIC_NUMBER_BE == iMagicWord || AI_MDL_MAGIC_NUMBER_LE == iMagicWord) { ASSIMP_LOG_DEBUG("MDL subtype: Quake 1, magic word is IDPO"); iGSFileVersion = 0; InternReadFile_Quake1(); } // GameStudio A MDL2 format - used by some test models that come with 3DGS - else if (AI_MDL_MAGIC_NUMBER_BE_GS3 == iMagicWord || AI_MDL_MAGIC_NUMBER_LE_GS3 == iMagicWord) { + else if (AI_MDL_MAGIC_NUMBER_BE_GS3 == iMagicWord || AI_MDL_MAGIC_NUMBER_LE_GS3 == iMagicWord) { ASSIMP_LOG_DEBUG("MDL subtype: 3D GameStudio A2, magic word is MDL2"); iGSFileVersion = 2; InternReadFile_Quake1(); } // GameStudio A4 MDL3 format - else if (AI_MDL_MAGIC_NUMBER_BE_GS4 == iMagicWord || AI_MDL_MAGIC_NUMBER_LE_GS4 == iMagicWord) { + else if (AI_MDL_MAGIC_NUMBER_BE_GS4 == iMagicWord || AI_MDL_MAGIC_NUMBER_LE_GS4 == iMagicWord) { ASSIMP_LOG_DEBUG("MDL subtype: 3D GameStudio A4, magic word is MDL3"); iGSFileVersion = 3; InternReadFile_3DGS_MDL345(); } // GameStudio A5+ MDL4 format - else if (AI_MDL_MAGIC_NUMBER_BE_GS5a == iMagicWord || AI_MDL_MAGIC_NUMBER_LE_GS5a == iMagicWord) { + else if (AI_MDL_MAGIC_NUMBER_BE_GS5a == iMagicWord || AI_MDL_MAGIC_NUMBER_LE_GS5a == iMagicWord) { ASSIMP_LOG_DEBUG("MDL subtype: 3D GameStudio A4, magic word is MDL4"); iGSFileVersion = 4; InternReadFile_3DGS_MDL345(); } // GameStudio A5+ MDL5 format - else if (AI_MDL_MAGIC_NUMBER_BE_GS5b == iMagicWord || AI_MDL_MAGIC_NUMBER_LE_GS5b == iMagicWord) { + else if (AI_MDL_MAGIC_NUMBER_BE_GS5b == iMagicWord || AI_MDL_MAGIC_NUMBER_LE_GS5b == iMagicWord) { ASSIMP_LOG_DEBUG("MDL subtype: 3D GameStudio A5, magic word is MDL5"); iGSFileVersion = 5; InternReadFile_3DGS_MDL345(); } // GameStudio A7 MDL7 format - else if (AI_MDL_MAGIC_NUMBER_BE_GS7 == iMagicWord || AI_MDL_MAGIC_NUMBER_LE_GS7 == iMagicWord) { + else if (AI_MDL_MAGIC_NUMBER_BE_GS7 == iMagicWord || AI_MDL_MAGIC_NUMBER_LE_GS7 == iMagicWord) { ASSIMP_LOG_DEBUG("MDL subtype: 3D GameStudio A7, magic word is MDL7"); iGSFileVersion = 7; InternReadFile_3DGS_MDL7(); } // IDST/IDSQ Format (CS:S/HL^2, etc ...) else if (AI_MDL_MAGIC_NUMBER_BE_HL2a == iMagicWord || AI_MDL_MAGIC_NUMBER_LE_HL2a == iMagicWord || - AI_MDL_MAGIC_NUMBER_BE_HL2b == iMagicWord || AI_MDL_MAGIC_NUMBER_LE_HL2b == iMagicWord) - { + AI_MDL_MAGIC_NUMBER_BE_HL2b == iMagicWord || AI_MDL_MAGIC_NUMBER_LE_HL2b == iMagicWord) { iGSFileVersion = 0; HalfLife::HalfLifeMDLBaseHeader *pHeader = (HalfLife::HalfLifeMDLBaseHeader *)mBuffer; - if (pHeader->version == AI_MDL_HL1_VERSION) - { + if (pHeader->version == AI_MDL_HL1_VERSION) { ASSIMP_LOG_DEBUG("MDL subtype: Half-Life 1/Goldsrc Engine, magic word is IDST/IDSQ"); InternReadFile_HL1(pFile, iMagicWord); - } - else - { + } else { ASSIMP_LOG_DEBUG("MDL subtype: Source(tm) Engine, magic word is IDST/IDSQ"); InternReadFile_HL2(); } - } - else { + } else { // print the magic word to the log file - throw DeadlyImportError( "Unknown MDL subformat " + pFile + - ". Magic word (" + std::string((char*)&iMagicWord,4) + ") is not known"); + throw DeadlyImportError("Unknown MDL subformat " + pFile + + ". Magic word (" + std::string((char *)&iMagicWord, 4) + ") is not known"); } // Now rotate the whole scene 90 degrees around the x axis to convert to internal coordinate system - pScene->mRootNode->mTransformation = aiMatrix4x4(1.f,0.f,0.f,0.f, - 0.f,0.f,1.f,0.f,0.f,-1.f,0.f,0.f,0.f,0.f,0.f,1.f); + pScene->mRootNode->mTransformation = aiMatrix4x4(1.f, 0.f, 0.f, 0.f, + 0.f, 0.f, 1.f, 0.f, 0.f, -1.f, 0.f, 0.f, 0.f, 0.f, 0.f, 1.f); DeleteBufferAndCleanup(); - } catch(...) { + } catch (...) { DeleteBufferAndCleanup(); throw; } @@ -281,33 +268,34 @@ void MDLImporter::InternReadFile( const std::string& pFile, // ------------------------------------------------------------------------------------------------ // Check whether we're still inside the valid file range -void MDLImporter::SizeCheck(const void* szPos) -{ - if (!szPos || (const unsigned char*)szPos > this->mBuffer + this->iFileSize) - { +void MDLImporter::SizeCheck(const void *szPos) { + if (!szPos || (const unsigned char *)szPos > this->mBuffer + this->iFileSize) { throw DeadlyImportError("Invalid MDL file. The file is too small " - "or contains invalid data."); + "or contains invalid data."); } } // ------------------------------------------------------------------------------------------------ // Just for debugging purposes -void MDLImporter::SizeCheck(const void* szPos, const char* szFile, unsigned int iLine) -{ +void MDLImporter::SizeCheck(const void *szPos, const char *szFile, unsigned int iLine) { ai_assert(NULL != szFile); - if (!szPos || (const unsigned char*)szPos > mBuffer + iFileSize) - { + if (!szPos || (const unsigned char *)szPos > mBuffer + iFileSize) { // remove a directory if there is one - const char* szFilePtr = ::strrchr(szFile,'\\'); + const char *szFilePtr = ::strrchr(szFile, '\\'); if (!szFilePtr) { - if(!(szFilePtr = ::strrchr(szFile,'/'))) + szFilePtr = ::strrchr(szFile, '/'); + if (nullptr == szFilePtr) { szFilePtr = szFile; + } + } + if (szFilePtr) { + ++szFilePtr; } - if (szFilePtr)++szFilePtr; char szBuffer[1024]; - ::sprintf(szBuffer,"Invalid MDL file. The file is too small " - "or contains invalid data (File: %s Line: %u)",szFilePtr,iLine); + ::sprintf(szBuffer, "Invalid MDL file. The file is too small " + "or contains invalid data (File: %s Line: %u)", + szFilePtr, iLine); throw DeadlyImportError(szBuffer); } @@ -315,21 +303,19 @@ void MDLImporter::SizeCheck(const void* szPos, const char* szFile, unsigned int // ------------------------------------------------------------------------------------------------ // Validate a quake file header -void MDLImporter::ValidateHeader_Quake1(const MDL::Header* pcHeader) -{ +void MDLImporter::ValidateHeader_Quake1(const MDL::Header *pcHeader) { // some values may not be NULL if (!pcHeader->num_frames) - throw DeadlyImportError( "[Quake 1 MDL] There are no frames in the file"); + throw DeadlyImportError("[Quake 1 MDL] There are no frames in the file"); if (!pcHeader->num_verts) - throw DeadlyImportError( "[Quake 1 MDL] There are no vertices in the file"); + throw DeadlyImportError("[Quake 1 MDL] There are no vertices in the file"); if (!pcHeader->num_tris) - throw DeadlyImportError( "[Quake 1 MDL] There are no triangles in the file"); + throw DeadlyImportError("[Quake 1 MDL] There are no triangles in the file"); // check whether the maxima are exceeded ...however, this applies for Quake 1 MDLs only - if (!this->iGSFileVersion) - { + if (!this->iGSFileVersion) { if (pcHeader->num_verts > AI_MDL_MAX_VERTS) ASSIMP_LOG_WARN("Quake 1 MDL model has more than AI_MDL_MAX_VERTS vertices"); @@ -342,33 +328,31 @@ void MDLImporter::ValidateHeader_Quake1(const MDL::Header* pcHeader) // (this does not apply for 3DGS MDLs) if (!this->iGSFileVersion && pcHeader->version != AI_MDL_VERSION) ASSIMP_LOG_WARN("Quake 1 MDL model has an unknown version: AI_MDL_VERSION (=6) is " - "the expected file format version"); - if(pcHeader->num_skins && (!pcHeader->skinwidth || !pcHeader->skinheight)) + "the expected file format version"); + if (pcHeader->num_skins && (!pcHeader->skinwidth || !pcHeader->skinheight)) ASSIMP_LOG_WARN("Skin width or height are 0"); } } #ifdef AI_BUILD_BIG_ENDIAN // ------------------------------------------------------------------------------------------------ -void FlipQuakeHeader(BE_NCONST MDL::Header* pcHeader) -{ - AI_SWAP4( pcHeader->ident); - AI_SWAP4( pcHeader->version); - AI_SWAP4( pcHeader->boundingradius); - AI_SWAP4( pcHeader->flags); - AI_SWAP4( pcHeader->num_frames); - AI_SWAP4( pcHeader->num_skins); - AI_SWAP4( pcHeader->num_tris); - AI_SWAP4( pcHeader->num_verts); - for (unsigned int i = 0; i < 3;++i) - { - AI_SWAP4( pcHeader->scale[i]); - AI_SWAP4( pcHeader->translate[i]); +void FlipQuakeHeader(BE_NCONST MDL::Header *pcHeader) { + AI_SWAP4(pcHeader->ident); + AI_SWAP4(pcHeader->version); + AI_SWAP4(pcHeader->boundingradius); + AI_SWAP4(pcHeader->flags); + AI_SWAP4(pcHeader->num_frames); + AI_SWAP4(pcHeader->num_skins); + AI_SWAP4(pcHeader->num_tris); + AI_SWAP4(pcHeader->num_verts); + for (unsigned int i = 0; i < 3; ++i) { + AI_SWAP4(pcHeader->scale[i]); + AI_SWAP4(pcHeader->translate[i]); } - AI_SWAP4( pcHeader->size); - AI_SWAP4( pcHeader->skinheight); - AI_SWAP4( pcHeader->skinwidth); - AI_SWAP4( pcHeader->synctype); + AI_SWAP4(pcHeader->size); + AI_SWAP4(pcHeader->skinheight); + AI_SWAP4(pcHeader->skinwidth); + AI_SWAP4(pcHeader->synctype); } #endif @@ -377,7 +361,7 @@ void FlipQuakeHeader(BE_NCONST MDL::Header* pcHeader) void MDLImporter::InternReadFile_Quake1() { ai_assert(NULL != pScene); - BE_NCONST MDL::Header *pcHeader = (BE_NCONST MDL::Header*)this->mBuffer; + BE_NCONST MDL::Header *pcHeader = (BE_NCONST MDL::Header *)this->mBuffer; #ifdef AI_BUILD_BIG_ENDIAN FlipQuakeHeader(pcHeader); @@ -386,24 +370,24 @@ void MDLImporter::InternReadFile_Quake1() { ValidateHeader_Quake1(pcHeader); // current cursor position in the file - const unsigned char* szCurrent = (const unsigned char*)(pcHeader+1); + const unsigned char *szCurrent = (const unsigned char *)(pcHeader + 1); // need to read all textures - for ( unsigned int i = 0; i < (unsigned int)pcHeader->num_skins; ++i) { + for (unsigned int i = 0; i < (unsigned int)pcHeader->num_skins; ++i) { union { - BE_NCONST MDL::Skin* pcSkin; - BE_NCONST MDL::GroupSkin* pcGroupSkin; + BE_NCONST MDL::Skin *pcSkin; + BE_NCONST MDL::GroupSkin *pcGroupSkin; }; if (szCurrent + sizeof(MDL::Skin) > this->mBuffer + this->iFileSize) { throw DeadlyImportError("[Quake 1 MDL] Unexpected EOF"); } - pcSkin = (BE_NCONST MDL::Skin*)szCurrent; + pcSkin = (BE_NCONST MDL::Skin *)szCurrent; - AI_SWAP4( pcSkin->group ); + AI_SWAP4(pcSkin->group); // Quake 1 group-skins if (1 == pcSkin->group) { - AI_SWAP4( pcGroupSkin->nb ); + AI_SWAP4(pcGroupSkin->nb); // need to skip multiple images const unsigned int iNumImages = (unsigned int)pcGroupSkin->nb; @@ -416,53 +400,51 @@ void MDLImporter::InternReadFile_Quake1() { } // go to the end of the skin section / the beginning of the next skin szCurrent += pcHeader->skinheight * pcHeader->skinwidth + - sizeof(float) * iNumImages; + sizeof(float) * iNumImages; } } else { szCurrent += sizeof(uint32_t); unsigned int iSkip = i ? UINT_MAX : 0; - CreateTexture_3DGS_MDL4(szCurrent,pcSkin->group,&iSkip); + CreateTexture_3DGS_MDL4(szCurrent, pcSkin->group, &iSkip); szCurrent += iSkip; } } // get a pointer to the texture coordinates - BE_NCONST MDL::TexCoord* pcTexCoords = (BE_NCONST MDL::TexCoord*)szCurrent; + BE_NCONST MDL::TexCoord *pcTexCoords = (BE_NCONST MDL::TexCoord *)szCurrent; szCurrent += sizeof(MDL::TexCoord) * pcHeader->num_verts; // get a pointer to the triangles - BE_NCONST MDL::Triangle* pcTriangles = (BE_NCONST MDL::Triangle*)szCurrent; + BE_NCONST MDL::Triangle *pcTriangles = (BE_NCONST MDL::Triangle *)szCurrent; szCurrent += sizeof(MDL::Triangle) * pcHeader->num_tris; VALIDATE_FILE_SIZE(szCurrent); // now get a pointer to the first frame in the file - BE_NCONST MDL::Frame* pcFrames = (BE_NCONST MDL::Frame*)szCurrent; - MDL::SimpleFrame* pcFirstFrame; + BE_NCONST MDL::Frame *pcFrames = (BE_NCONST MDL::Frame *)szCurrent; + MDL::SimpleFrame *pcFirstFrame; if (0 == pcFrames->type) { // get address of single frame - pcFirstFrame =( MDL::SimpleFrame*) &pcFrames->frame; + pcFirstFrame = (MDL::SimpleFrame *)&pcFrames->frame; } else { // get the first frame in the group - BE_NCONST MDL::GroupFrame* pcFrames2 = (BE_NCONST MDL::GroupFrame*) pcFrames; + BE_NCONST MDL::GroupFrame *pcFrames2 = (BE_NCONST MDL::GroupFrame *)pcFrames; pcFirstFrame = &(pcFrames2->frames[0]); } - BE_NCONST MDL::Vertex* pcVertices = (BE_NCONST MDL::Vertex*) ((pcFirstFrame->name) + sizeof(pcFirstFrame->name)); - VALIDATE_FILE_SIZE((const unsigned char*)(pcVertices + pcHeader->num_verts)); + BE_NCONST MDL::Vertex *pcVertices = (BE_NCONST MDL::Vertex *)((pcFirstFrame->name) + sizeof(pcFirstFrame->name)); + VALIDATE_FILE_SIZE((const unsigned char *)(pcVertices + pcHeader->num_verts)); #ifdef AI_BUILD_BIG_ENDIAN - for (int i = 0; inum_verts;++i) - { - AI_SWAP4( pcTexCoords[i].onseam ); - AI_SWAP4( pcTexCoords[i].s ); - AI_SWAP4( pcTexCoords[i].t ); + for (int i = 0; i < pcHeader->num_verts; ++i) { + AI_SWAP4(pcTexCoords[i].onseam); + AI_SWAP4(pcTexCoords[i].s); + AI_SWAP4(pcTexCoords[i].t); } - for (int i = 0; inum_tris;++i) - { - AI_SWAP4( pcTriangles[i].facesfront); - AI_SWAP4( pcTriangles[i].vertex[0]); - AI_SWAP4( pcTriangles[i].vertex[1]); - AI_SWAP4( pcTriangles[i].vertex[2]); + for (int i = 0; i < pcHeader->num_tris; ++i) { + AI_SWAP4(pcTriangles[i].facesfront); + AI_SWAP4(pcTriangles[i].vertex[0]); + AI_SWAP4(pcTriangles[i].vertex[1]); + AI_SWAP4(pcTriangles[i].vertex[2]); } #endif @@ -470,7 +452,7 @@ void MDLImporter::InternReadFile_Quake1() { SetupMaterialProperties_3DGS_MDL5_Quake1(); // allocate enough storage to hold all vertices and triangles - aiMesh* pcMesh = new aiMesh(); + aiMesh *pcMesh = new aiMesh(); pcMesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE; pcMesh->mNumVertices = pcHeader->num_tris * 3; @@ -487,30 +469,27 @@ void MDLImporter::InternReadFile_Quake1() { pScene->mRootNode->mMeshes = new unsigned int[1]; pScene->mRootNode->mMeshes[0] = 0; pScene->mNumMeshes = 1; - pScene->mMeshes = new aiMesh*[1]; + pScene->mMeshes = new aiMesh *[1]; pScene->mMeshes[0] = pcMesh; // now iterate through all triangles unsigned int iCurrent = 0; - for (unsigned int i = 0; i < (unsigned int) pcHeader->num_tris;++i) - { + for (unsigned int i = 0; i < (unsigned int)pcHeader->num_tris; ++i) { pcMesh->mFaces[i].mIndices = new unsigned int[3]; pcMesh->mFaces[i].mNumIndices = 3; unsigned int iTemp = iCurrent; - for (unsigned int c = 0; c < 3;++c,++iCurrent) - { + for (unsigned int c = 0; c < 3; ++c, ++iCurrent) { pcMesh->mFaces[i].mIndices[c] = iCurrent; // read vertices unsigned int iIndex = pcTriangles->vertex[c]; - if (iIndex >= (unsigned int)pcHeader->num_verts) - { - iIndex = pcHeader->num_verts-1; + if (iIndex >= (unsigned int)pcHeader->num_verts) { + iIndex = pcHeader->num_verts - 1; ASSIMP_LOG_WARN("Index overflow in Q1-MDL vertex list."); } - aiVector3D& vec = pcMesh->mVertices[iCurrent]; + aiVector3D &vec = pcMesh->mVertices[iCurrent]; vec.x = (float)pcVertices[iIndex].v[0] * pcHeader->scale[0]; vec.x += pcHeader->translate[0]; @@ -522,7 +501,7 @@ void MDLImporter::InternReadFile_Quake1() { vec.z += pcHeader->translate[2]; // read the normal vector from the precalculated normal table - MD2::LookupNormalIndex(pcVertices[iIndex].normalIndex,pcMesh->mNormals[iCurrent]); + MD2::LookupNormalIndex(pcVertices[iIndex].normalIndex, pcMesh->mNormals[iCurrent]); //pcMesh->mNormals[iCurrent].y *= -1.0f; // read texture coordinates @@ -530,18 +509,17 @@ void MDLImporter::InternReadFile_Quake1() { float t = (float)pcTexCoords[iIndex].t; // translate texture coordinates - if (0 == pcTriangles->facesfront && 0 != pcTexCoords[iIndex].onseam) { + if (0 == pcTriangles->facesfront && 0 != pcTexCoords[iIndex].onseam) { s += pcHeader->skinwidth * 0.5f; } // Scale s and t to range from 0.0 to 1.0 pcMesh->mTextureCoords[0][iCurrent].x = (s + 0.5f) / pcHeader->skinwidth; - pcMesh->mTextureCoords[0][iCurrent].y = 1.0f-(t + 0.5f) / pcHeader->skinheight; - + pcMesh->mTextureCoords[0][iCurrent].y = 1.0f - (t + 0.5f) / pcHeader->skinheight; } - pcMesh->mFaces[i].mIndices[0] = iTemp+2; - pcMesh->mFaces[i].mIndices[1] = iTemp+1; - pcMesh->mFaces[i].mIndices[2] = iTemp+0; + pcMesh->mFaces[i].mIndices[0] = iTemp + 2; + pcMesh->mFaces[i].mIndices[1] = iTemp + 1; + pcMesh->mFaces[i].mIndices[2] = iTemp + 0; pcTriangles++; } return; @@ -549,22 +527,21 @@ void MDLImporter::InternReadFile_Quake1() { // ------------------------------------------------------------------------------------------------ // Setup material properties for Quake and older GameStudio files -void MDLImporter::SetupMaterialProperties_3DGS_MDL5_Quake1( ) -{ - const MDL::Header* const pcHeader = (const MDL::Header*)this->mBuffer; +void MDLImporter::SetupMaterialProperties_3DGS_MDL5_Quake1() { + const MDL::Header *const pcHeader = (const MDL::Header *)this->mBuffer; // allocate ONE material - pScene->mMaterials = new aiMaterial*[1]; + pScene->mMaterials = new aiMaterial *[1]; pScene->mMaterials[0] = new aiMaterial(); pScene->mNumMaterials = 1; // setup the material's properties const int iMode = (int)aiShadingMode_Gouraud; - aiMaterial* const pcHelper = (aiMaterial*)pScene->mMaterials[0]; + aiMaterial *const pcHelper = (aiMaterial *)pScene->mMaterials[0]; pcHelper->AddProperty(&iMode, 1, AI_MATKEY_SHADING_MODEL); aiColor4D clr; - if (0 != pcHeader->num_skins && pScene->mNumTextures) { + if (0 != pcHeader->num_skins && pScene->mNumTextures) { // can we replace the texture with a single color? clr = this->ReplaceTextureWithColor(pScene->mTextures[0]); if (is_not_qnan(clr.r)) { @@ -573,89 +550,86 @@ void MDLImporter::SetupMaterialProperties_3DGS_MDL5_Quake1( ) pScene->mTextures = NULL; pScene->mNumTextures = 0; - } - else { + } else { clr.b = clr.a = clr.g = clr.r = 1.0f; aiString szString; - ::memcpy(szString.data,AI_MAKE_EMBEDDED_TEXNAME(0),3); + ::memcpy(szString.data, AI_MAKE_EMBEDDED_TEXNAME(0), 3); szString.length = 2; - pcHelper->AddProperty(&szString,AI_MATKEY_TEXTURE_DIFFUSE(0)); + pcHelper->AddProperty(&szString, AI_MATKEY_TEXTURE_DIFFUSE(0)); } } - pcHelper->AddProperty(&clr, 1,AI_MATKEY_COLOR_DIFFUSE); - pcHelper->AddProperty(&clr, 1,AI_MATKEY_COLOR_SPECULAR); + pcHelper->AddProperty(&clr, 1, AI_MATKEY_COLOR_DIFFUSE); + pcHelper->AddProperty(&clr, 1, AI_MATKEY_COLOR_SPECULAR); - clr.r *= 0.05f;clr.g *= 0.05f; - clr.b *= 0.05f;clr.a = 1.0f; - pcHelper->AddProperty(&clr, 1,AI_MATKEY_COLOR_AMBIENT); + clr.r *= 0.05f; + clr.g *= 0.05f; + clr.b *= 0.05f; + clr.a = 1.0f; + pcHelper->AddProperty(&clr, 1, AI_MATKEY_COLOR_AMBIENT); } // ------------------------------------------------------------------------------------------------ // Read a MDL 3,4,5 file -void MDLImporter::InternReadFile_3DGS_MDL345( ) -{ +void MDLImporter::InternReadFile_3DGS_MDL345() { ai_assert(NULL != pScene); // the header of MDL 3/4/5 is nearly identical to the original Quake1 header - BE_NCONST MDL::Header *pcHeader = (BE_NCONST MDL::Header*)this->mBuffer; + BE_NCONST MDL::Header *pcHeader = (BE_NCONST MDL::Header *)this->mBuffer; #ifdef AI_BUILD_BIG_ENDIAN FlipQuakeHeader(pcHeader); #endif ValidateHeader_Quake1(pcHeader); // current cursor position in the file - const unsigned char* szCurrent = (const unsigned char*)(pcHeader+1); - const unsigned char* szEnd = mBuffer + iFileSize; + const unsigned char *szCurrent = (const unsigned char *)(pcHeader + 1); + const unsigned char *szEnd = mBuffer + iFileSize; // need to read all textures - for (unsigned int i = 0; i < (unsigned int)pcHeader->num_skins;++i) { + for (unsigned int i = 0; i < (unsigned int)pcHeader->num_skins; ++i) { if (szCurrent >= szEnd) { - throw DeadlyImportError( "Texture data past end of file."); + throw DeadlyImportError("Texture data past end of file."); } - BE_NCONST MDL::Skin* pcSkin; - pcSkin = (BE_NCONST MDL::Skin*)szCurrent; - AI_SWAP4( pcSkin->group); + BE_NCONST MDL::Skin *pcSkin; + pcSkin = (BE_NCONST MDL::Skin *)szCurrent; + AI_SWAP4(pcSkin->group); // create one output image unsigned int iSkip = i ? UINT_MAX : 0; - if (5 <= iGSFileVersion) - { + if (5 <= iGSFileVersion) { // MDL5 format could contain MIPmaps - CreateTexture_3DGS_MDL5((unsigned char*)pcSkin + sizeof(uint32_t), - pcSkin->group,&iSkip); - } - else { - CreateTexture_3DGS_MDL4((unsigned char*)pcSkin + sizeof(uint32_t), - pcSkin->group,&iSkip); + CreateTexture_3DGS_MDL5((unsigned char *)pcSkin + sizeof(uint32_t), + pcSkin->group, &iSkip); + } else { + CreateTexture_3DGS_MDL4((unsigned char *)pcSkin + sizeof(uint32_t), + pcSkin->group, &iSkip); } // need to skip one image szCurrent += iSkip + sizeof(uint32_t); - } // get a pointer to the texture coordinates - BE_NCONST MDL::TexCoord_MDL3* pcTexCoords = (BE_NCONST MDL::TexCoord_MDL3*)szCurrent; + BE_NCONST MDL::TexCoord_MDL3 *pcTexCoords = (BE_NCONST MDL::TexCoord_MDL3 *)szCurrent; szCurrent += sizeof(MDL::TexCoord_MDL3) * pcHeader->synctype; // NOTE: for MDLn formats "synctype" corresponds to the number of UV coords // get a pointer to the triangles - BE_NCONST MDL::Triangle_MDL3* pcTriangles = (BE_NCONST MDL::Triangle_MDL3*)szCurrent; + BE_NCONST MDL::Triangle_MDL3 *pcTriangles = (BE_NCONST MDL::Triangle_MDL3 *)szCurrent; szCurrent += sizeof(MDL::Triangle_MDL3) * pcHeader->num_tris; #ifdef AI_BUILD_BIG_ENDIAN - for (int i = 0; isynctype;++i) { - AI_SWAP2( pcTexCoords[i].u ); - AI_SWAP2( pcTexCoords[i].v ); + for (int i = 0; i < pcHeader->synctype; ++i) { + AI_SWAP2(pcTexCoords[i].u); + AI_SWAP2(pcTexCoords[i].v); } - for (int i = 0; inum_tris;++i) { - AI_SWAP2( pcTriangles[i].index_xyz[0]); - AI_SWAP2( pcTriangles[i].index_xyz[1]); - AI_SWAP2( pcTriangles[i].index_xyz[2]); - AI_SWAP2( pcTriangles[i].index_uv[0]); - AI_SWAP2( pcTriangles[i].index_uv[1]); - AI_SWAP2( pcTriangles[i].index_uv[2]); + for (int i = 0; i < pcHeader->num_tris; ++i) { + AI_SWAP2(pcTriangles[i].index_xyz[0]); + AI_SWAP2(pcTriangles[i].index_xyz[1]); + AI_SWAP2(pcTriangles[i].index_xyz[2]); + AI_SWAP2(pcTriangles[i].index_uv[0]); + AI_SWAP2(pcTriangles[i].index_uv[1]); + AI_SWAP2(pcTriangles[i].index_uv[2]); } #endif @@ -666,7 +640,7 @@ void MDLImporter::InternReadFile_3DGS_MDL345( ) SetupMaterialProperties_3DGS_MDL5_Quake1(); // allocate enough storage to hold all vertices and triangles - aiMesh* pcMesh = new aiMesh(); + aiMesh *pcMesh = new aiMesh(); pcMesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE; pcMesh->mNumVertices = pcHeader->num_tris * 3; @@ -679,13 +653,13 @@ void MDLImporter::InternReadFile_3DGS_MDL345( ) pScene->mRootNode->mMeshes = new unsigned int[1]; pScene->mRootNode->mMeshes[0] = 0; pScene->mNumMeshes = 1; - pScene->mMeshes = new aiMesh*[1]; + pScene->mMeshes = new aiMesh *[1]; pScene->mMeshes[0] = pcMesh; // allocate output storage - pcMesh->mNumVertices = (unsigned int)pcHeader->num_tris*3; - pcMesh->mVertices = new aiVector3D[pcMesh->mNumVertices]; - pcMesh->mNormals = new aiVector3D[pcMesh->mNumVertices]; + pcMesh->mNumVertices = (unsigned int)pcHeader->num_tris * 3; + pcMesh->mVertices = new aiVector3D[pcMesh->mNumVertices]; + pcMesh->mNormals = new aiVector3D[pcMesh->mNumVertices]; if (pcHeader->synctype) { pcMesh->mTextureCoords[0] = new aiVector3D[pcMesh->mNumVertices]; @@ -693,35 +667,35 @@ void MDLImporter::InternReadFile_3DGS_MDL345( ) } // now get a pointer to the first frame in the file - BE_NCONST MDL::Frame* pcFrames = (BE_NCONST MDL::Frame*)szCurrent; + BE_NCONST MDL::Frame *pcFrames = (BE_NCONST MDL::Frame *)szCurrent; AI_SWAP4(pcFrames->type); // byte packed vertices // FIXME: these two snippets below are almost identical ... join them? ///////////////////////////////////////////////////////////////////////////////////// - if (0 == pcFrames->type || 3 >= this->iGSFileVersion) { + if (0 == pcFrames->type || 3 >= this->iGSFileVersion) { - const MDL::SimpleFrame* pcFirstFrame = (const MDL::SimpleFrame*)(szCurrent + sizeof(uint32_t)); - const MDL::Vertex* pcVertices = (const MDL::Vertex*) ((pcFirstFrame->name) + sizeof(pcFirstFrame->name)); + const MDL::SimpleFrame *pcFirstFrame = (const MDL::SimpleFrame *)(szCurrent + sizeof(uint32_t)); + const MDL::Vertex *pcVertices = (const MDL::Vertex *)((pcFirstFrame->name) + sizeof(pcFirstFrame->name)); VALIDATE_FILE_SIZE(pcVertices + pcHeader->num_verts); // now iterate through all triangles unsigned int iCurrent = 0; - for (unsigned int i = 0; i < (unsigned int) pcHeader->num_tris;++i) { + for (unsigned int i = 0; i < (unsigned int)pcHeader->num_tris; ++i) { pcMesh->mFaces[i].mIndices = new unsigned int[3]; pcMesh->mFaces[i].mNumIndices = 3; unsigned int iTemp = iCurrent; - for (unsigned int c = 0; c < 3;++c,++iCurrent) { + for (unsigned int c = 0; c < 3; ++c, ++iCurrent) { // read vertices unsigned int iIndex = pcTriangles->index_xyz[c]; - if (iIndex >= (unsigned int)pcHeader->num_verts) { - iIndex = pcHeader->num_verts-1; + if (iIndex >= (unsigned int)pcHeader->num_verts) { + iIndex = pcHeader->num_verts - 1; ASSIMP_LOG_WARN("Index overflow in MDLn vertex list"); } - aiVector3D& vec = pcMesh->mVertices[iCurrent]; + aiVector3D &vec = pcMesh->mVertices[iCurrent]; vec.x = (float)pcVertices[iIndex].v[0] * pcHeader->scale[0]; vec.x += pcHeader->translate[0]; @@ -733,50 +707,50 @@ void MDLImporter::InternReadFile_3DGS_MDL345( ) vec.z += pcHeader->translate[2]; // read the normal vector from the precalculated normal table - MD2::LookupNormalIndex(pcVertices[iIndex].normalIndex,pcMesh->mNormals[iCurrent]); + MD2::LookupNormalIndex(pcVertices[iIndex].normalIndex, pcMesh->mNormals[iCurrent]); // pcMesh->mNormals[iCurrent].y *= -1.0f; // read texture coordinates if (pcHeader->synctype) { ImportUVCoordinate_3DGS_MDL345(pcMesh->mTextureCoords[0][iCurrent], - pcTexCoords,pcTriangles->index_uv[c]); + pcTexCoords, pcTriangles->index_uv[c]); } } - pcMesh->mFaces[i].mIndices[0] = iTemp+2; - pcMesh->mFaces[i].mIndices[1] = iTemp+1; - pcMesh->mFaces[i].mIndices[2] = iTemp+0; + pcMesh->mFaces[i].mIndices[0] = iTemp + 2; + pcMesh->mFaces[i].mIndices[1] = iTemp + 1; + pcMesh->mFaces[i].mIndices[2] = iTemp + 0; pcTriangles++; } } // short packed vertices ///////////////////////////////////////////////////////////////////////////////////// - else { + else { // now get a pointer to the first frame in the file - const MDL::SimpleFrame_MDLn_SP* pcFirstFrame = (const MDL::SimpleFrame_MDLn_SP*) (szCurrent + sizeof(uint32_t)); + const MDL::SimpleFrame_MDLn_SP *pcFirstFrame = (const MDL::SimpleFrame_MDLn_SP *)(szCurrent + sizeof(uint32_t)); // get a pointer to the vertices - const MDL::Vertex_MDL4* pcVertices = (const MDL::Vertex_MDL4*) ((pcFirstFrame->name) + - sizeof(pcFirstFrame->name)); + const MDL::Vertex_MDL4 *pcVertices = (const MDL::Vertex_MDL4 *)((pcFirstFrame->name) + + sizeof(pcFirstFrame->name)); VALIDATE_FILE_SIZE(pcVertices + pcHeader->num_verts); // now iterate through all triangles unsigned int iCurrent = 0; - for (unsigned int i = 0; i < (unsigned int) pcHeader->num_tris;++i) { + for (unsigned int i = 0; i < (unsigned int)pcHeader->num_tris; ++i) { pcMesh->mFaces[i].mIndices = new unsigned int[3]; pcMesh->mFaces[i].mNumIndices = 3; unsigned int iTemp = iCurrent; - for (unsigned int c = 0; c < 3;++c,++iCurrent) { + for (unsigned int c = 0; c < 3; ++c, ++iCurrent) { // read vertices unsigned int iIndex = pcTriangles->index_xyz[c]; - if (iIndex >= (unsigned int)pcHeader->num_verts) { - iIndex = pcHeader->num_verts-1; + if (iIndex >= (unsigned int)pcHeader->num_verts) { + iIndex = pcHeader->num_verts - 1; ASSIMP_LOG_WARN("Index overflow in MDLn vertex list"); } - aiVector3D& vec = pcMesh->mVertices[iCurrent]; + aiVector3D &vec = pcMesh->mVertices[iCurrent]; vec.x = (float)pcVertices[iIndex].v[0] * pcHeader->scale[0]; vec.x += pcHeader->translate[0]; @@ -788,18 +762,18 @@ void MDLImporter::InternReadFile_3DGS_MDL345( ) vec.z += pcHeader->translate[2]; // read the normal vector from the precalculated normal table - MD2::LookupNormalIndex(pcVertices[iIndex].normalIndex,pcMesh->mNormals[iCurrent]); + MD2::LookupNormalIndex(pcVertices[iIndex].normalIndex, pcMesh->mNormals[iCurrent]); // pcMesh->mNormals[iCurrent].y *= -1.0f; // read texture coordinates if (pcHeader->synctype) { ImportUVCoordinate_3DGS_MDL345(pcMesh->mTextureCoords[0][iCurrent], - pcTexCoords,pcTriangles->index_uv[c]); + pcTexCoords, pcTriangles->index_uv[c]); } } - pcMesh->mFaces[i].mIndices[0] = iTemp+2; - pcMesh->mFaces[i].mIndices[1] = iTemp+1; - pcMesh->mFaces[i].mIndices[2] = iTemp+0; + pcMesh->mFaces[i].mIndices[0] = iTemp + 2; + pcMesh->mFaces[i].mIndices[1] = iTemp + 1; + pcMesh->mFaces[i].mIndices[2] = iTemp + 0; pcTriangles++; } } @@ -814,16 +788,15 @@ void MDLImporter::InternReadFile_3DGS_MDL345( ) // ------------------------------------------------------------------------------------------------ // Get a single UV coordinate for Quake and older GameStudio files void MDLImporter::ImportUVCoordinate_3DGS_MDL345( - aiVector3D& vOut, - const MDL::TexCoord_MDL3* pcSrc, - unsigned int iIndex) -{ + aiVector3D &vOut, + const MDL::TexCoord_MDL3 *pcSrc, + unsigned int iIndex) { ai_assert(NULL != pcSrc); - const MDL::Header* const pcHeader = (const MDL::Header*)this->mBuffer; + const MDL::Header *const pcHeader = (const MDL::Header *)this->mBuffer; // validate UV indices - if (iIndex >= (unsigned int) pcHeader->synctype) { - iIndex = pcHeader->synctype-1; + if (iIndex >= (unsigned int)pcHeader->synctype) { + iIndex = pcHeader->synctype - 1; ASSIMP_LOG_WARN("Index overflow in MDLn UV coord list"); } @@ -831,9 +804,9 @@ void MDLImporter::ImportUVCoordinate_3DGS_MDL345( float t = (float)pcSrc[iIndex].v; // Scale s and t to range from 0.0 to 1.0 - if (0x5 != iGSFileVersion) { - s = (s + 0.5f) / pcHeader->skinwidth; - t = 1.0f-(t + 0.5f) / pcHeader->skinheight; + if (0x5 != iGSFileVersion) { + s = (s + 0.5f) / pcHeader->skinwidth; + t = 1.0f - (t + 0.5f) / pcHeader->skinheight; } vOut.x = s; @@ -843,43 +816,39 @@ void MDLImporter::ImportUVCoordinate_3DGS_MDL345( // ------------------------------------------------------------------------------------------------ // Compute UV coordinates for a MDL5 file -void MDLImporter::CalculateUVCoordinates_MDL5() -{ - const MDL::Header* const pcHeader = (const MDL::Header*)this->mBuffer; - if (pcHeader->num_skins && this->pScene->mNumTextures) { - const aiTexture* pcTex = this->pScene->mTextures[0]; +void MDLImporter::CalculateUVCoordinates_MDL5() { + const MDL::Header *const pcHeader = (const MDL::Header *)this->mBuffer; + if (pcHeader->num_skins && this->pScene->mNumTextures) { + const aiTexture *pcTex = this->pScene->mTextures[0]; // if the file is loaded in DDS format: get the size of the // texture from the header of the DDS file // skip three DWORDs and read first height, then the width unsigned int iWidth, iHeight; - if (!pcTex->mHeight) { - const uint32_t* piPtr = (uint32_t*)pcTex->pcData; + if (!pcTex->mHeight) { + const uint32_t *piPtr = (uint32_t *)pcTex->pcData; piPtr += 3; iHeight = (unsigned int)*piPtr++; - iWidth = (unsigned int)*piPtr; - if (!iHeight || !iWidth) - { + iWidth = (unsigned int)*piPtr; + if (!iHeight || !iWidth) { ASSIMP_LOG_WARN("Either the width or the height of the " - "embedded DDS texture is zero. Unable to compute final texture " - "coordinates. The texture coordinates remain in their original " - "0-x/0-y (x,y = texture size) range."); - iWidth = 1; + "embedded DDS texture is zero. Unable to compute final texture " + "coordinates. The texture coordinates remain in their original " + "0-x/0-y (x,y = texture size) range."); + iWidth = 1; iHeight = 1; } - } - else { - iWidth = pcTex->mWidth; + } else { + iWidth = pcTex->mWidth; iHeight = pcTex->mHeight; } - if (1 != iWidth || 1 != iHeight) { + if (1 != iWidth || 1 != iHeight) { const float fWidth = (float)iWidth; const float fHeight = (float)iHeight; - aiMesh* pcMesh = this->pScene->mMeshes[0]; - for (unsigned int i = 0; i < pcMesh->mNumVertices;++i) - { + aiMesh *pcMesh = this->pScene->mMeshes[0]; + for (unsigned int i = 0; i < pcMesh->mNumVertices; ++i) { pcMesh->mTextureCoords[0][i].x /= fWidth; pcMesh->mTextureCoords[0][i].y /= fHeight; pcMesh->mTextureCoords[0][i].y = 1.0f - pcMesh->mTextureCoords[0][i].y; // DX to OGL @@ -890,36 +859,34 @@ void MDLImporter::CalculateUVCoordinates_MDL5() // ------------------------------------------------------------------------------------------------ // Validate the header of a MDL7 file -void MDLImporter::ValidateHeader_3DGS_MDL7(const MDL::Header_MDL7* pcHeader) -{ +void MDLImporter::ValidateHeader_3DGS_MDL7(const MDL::Header_MDL7 *pcHeader) { ai_assert(NULL != pcHeader); // There are some fixed sizes ... - if (sizeof(MDL::ColorValue_MDL7) != pcHeader->colorvalue_stc_size) { + if (sizeof(MDL::ColorValue_MDL7) != pcHeader->colorvalue_stc_size) { throw DeadlyImportError( - "[3DGS MDL7] sizeof(MDL::ColorValue_MDL7) != pcHeader->colorvalue_stc_size"); + "[3DGS MDL7] sizeof(MDL::ColorValue_MDL7) != pcHeader->colorvalue_stc_size"); } if (sizeof(MDL::TexCoord_MDL7) != pcHeader->skinpoint_stc_size) { throw DeadlyImportError( - "[3DGS MDL7] sizeof(MDL::TexCoord_MDL7) != pcHeader->skinpoint_stc_size"); + "[3DGS MDL7] sizeof(MDL::TexCoord_MDL7) != pcHeader->skinpoint_stc_size"); } - if (sizeof(MDL::Skin_MDL7) != pcHeader->skin_stc_size) { + if (sizeof(MDL::Skin_MDL7) != pcHeader->skin_stc_size) { throw DeadlyImportError( - "sizeof(MDL::Skin_MDL7) != pcHeader->skin_stc_size"); + "sizeof(MDL::Skin_MDL7) != pcHeader->skin_stc_size"); } // if there are no groups ... how should we load such a file? - if(!pcHeader->groups_num) { - throw DeadlyImportError( "[3DGS MDL7] No frames found"); + if (!pcHeader->groups_num) { + throw DeadlyImportError("[3DGS MDL7] No frames found"); } } // ------------------------------------------------------------------------------------------------ // resolve bone animation matrices -void MDLImporter::CalcAbsBoneMatrices_3DGS_MDL7(MDL::IntBone_MDL7** apcOutBones) -{ - const MDL::Header_MDL7 *pcHeader = (const MDL::Header_MDL7*)this->mBuffer; - const MDL::Bone_MDL7* pcBones = (const MDL::Bone_MDL7*)(pcHeader+1); +void MDLImporter::CalcAbsBoneMatrices_3DGS_MDL7(MDL::IntBone_MDL7 **apcOutBones) { + const MDL::Header_MDL7 *pcHeader = (const MDL::Header_MDL7 *)this->mBuffer; + const MDL::Bone_MDL7 *pcBones = (const MDL::Bone_MDL7 *)(pcHeader + 1); ai_assert(NULL != apcOutBones); // first find the bone that has NO parent, calculate the @@ -928,16 +895,16 @@ void MDLImporter::CalcAbsBoneMatrices_3DGS_MDL7(MDL::IntBone_MDL7** apcOutBones) uint16_t iParent = 0xffff; uint32_t iIterations = 0; while (iIterations++ < pcHeader->bones_num) { - for (uint32_t iBone = 0; iBone < pcHeader->bones_num;++iBone) { - BE_NCONST MDL::Bone_MDL7* pcBone = _AI_MDL7_ACCESS_PTR(pcBones,iBone, - pcHeader->bone_stc_size,MDL::Bone_MDL7); + for (uint32_t iBone = 0; iBone < pcHeader->bones_num; ++iBone) { + BE_NCONST MDL::Bone_MDL7 *pcBone = _AI_MDL7_ACCESS_PTR(pcBones, iBone, + pcHeader->bone_stc_size, MDL::Bone_MDL7); AI_SWAP2(pcBone->parent_index); AI_SWAP4(pcBone->x); AI_SWAP4(pcBone->y); AI_SWAP4(pcBone->z); - if (iParent == pcBone->parent_index) { + if (iParent == pcBone->parent_index) { // MDL7 readme //////////////////////////////////////////////////////////////// /* @@ -958,12 +925,12 @@ void MDLImporter::CalcAbsBoneMatrices_3DGS_MDL7(MDL::IntBone_MDL7** apcOutBones) */ ///////////////////////////////////////////////////////////////// - MDL::IntBone_MDL7* const pcOutBone = apcOutBones[iBone]; + MDL::IntBone_MDL7 *const pcOutBone = apcOutBones[iBone]; // store the parent index of the bone pcOutBone->iParent = pcBone->parent_index; - if (0xffff != iParent) { - const MDL::IntBone_MDL7* pcParentBone = apcOutBones[iParent]; + if (0xffff != iParent) { + const MDL::IntBone_MDL7 *pcParentBone = apcOutBones[iParent]; pcOutBone->mOffsetMatrix.a4 = -pcParentBone->vPosition.x; pcOutBone->mOffsetMatrix.b4 = -pcParentBone->vPosition.y; pcOutBone->mOffsetMatrix.c4 = -pcParentBone->vPosition.z; @@ -978,15 +945,14 @@ void MDLImporter::CalcAbsBoneMatrices_3DGS_MDL7(MDL::IntBone_MDL7** apcOutBones) if (AI_MDL7_BONE_STRUCT_SIZE__NAME_IS_NOT_THERE == pcHeader->bone_stc_size) { // no real name for our poor bone is specified :-( pcOutBone->mName.length = ai_snprintf(pcOutBone->mName.data, MAXLEN, - "UnnamedBone_%i",iBone); - } - else { + "UnnamedBone_%i", iBone); + } else { // Make sure we won't run over the buffer's end if there is no // terminal 0 character (however the documentation says there // should be one) - uint32_t iMaxLen = pcHeader->bone_stc_size-16; - for (uint32_t qq = 0; qq < iMaxLen;++qq) { - if (!pcBone->name[qq]) { + uint32_t iMaxLen = pcHeader->bone_stc_size - 16; + for (uint32_t qq = 0; qq < iMaxLen; ++qq) { + if (!pcBone->name[qq]) { iMaxLen = qq; break; } @@ -994,7 +960,7 @@ void MDLImporter::CalcAbsBoneMatrices_3DGS_MDL7(MDL::IntBone_MDL7** apcOutBones) // store the name of the bone pcOutBone->mName.length = (size_t)iMaxLen; - ::memcpy(pcOutBone->mName.data,pcBone->name,pcOutBone->mName.length); + ::memcpy(pcOutBone->mName.data, pcBone->name, pcOutBone->mName.length); pcOutBone->mName.data[pcOutBone->mName.length] = '\0'; } } @@ -1005,21 +971,19 @@ void MDLImporter::CalcAbsBoneMatrices_3DGS_MDL7(MDL::IntBone_MDL7** apcOutBones) // ------------------------------------------------------------------------------------------------ // read bones from a MDL7 file -MDL::IntBone_MDL7** MDLImporter::LoadBones_3DGS_MDL7() -{ - const MDL::Header_MDL7 *pcHeader = (const MDL::Header_MDL7*)this->mBuffer; - if (pcHeader->bones_num) { +MDL::IntBone_MDL7 **MDLImporter::LoadBones_3DGS_MDL7() { + const MDL::Header_MDL7 *pcHeader = (const MDL::Header_MDL7 *)this->mBuffer; + if (pcHeader->bones_num) { // validate the size of the bone data structure in the file - if (AI_MDL7_BONE_STRUCT_SIZE__NAME_IS_20_CHARS != pcHeader->bone_stc_size && - AI_MDL7_BONE_STRUCT_SIZE__NAME_IS_32_CHARS != pcHeader->bone_stc_size && - AI_MDL7_BONE_STRUCT_SIZE__NAME_IS_NOT_THERE != pcHeader->bone_stc_size) - { + if (AI_MDL7_BONE_STRUCT_SIZE__NAME_IS_20_CHARS != pcHeader->bone_stc_size && + AI_MDL7_BONE_STRUCT_SIZE__NAME_IS_32_CHARS != pcHeader->bone_stc_size && + AI_MDL7_BONE_STRUCT_SIZE__NAME_IS_NOT_THERE != pcHeader->bone_stc_size) { ASSIMP_LOG_WARN("Unknown size of bone data structure"); return NULL; } - MDL::IntBone_MDL7** apcBonesOut = new MDL::IntBone_MDL7*[pcHeader->bones_num]; - for (uint32_t crank = 0; crank < pcHeader->bones_num;++crank) + MDL::IntBone_MDL7 **apcBonesOut = new MDL::IntBone_MDL7 *[pcHeader->bones_num]; + for (uint32_t crank = 0; crank < pcHeader->bones_num; ++crank) apcBonesOut[crank] = new MDL::IntBone_MDL7(); // and calculate absolute bone offset matrices ... @@ -1031,11 +995,10 @@ MDL::IntBone_MDL7** MDLImporter::LoadBones_3DGS_MDL7() // ------------------------------------------------------------------------------------------------ // read faces from a MDL7 file -void MDLImporter::ReadFaces_3DGS_MDL7(const MDL::IntGroupInfo_MDL7& groupInfo, - MDL::IntGroupData_MDL7& groupData) -{ - const MDL::Header_MDL7 *pcHeader = (const MDL::Header_MDL7*)this->mBuffer; - MDL::Triangle_MDL7* pcGroupTris = groupInfo.pcGroupTris; +void MDLImporter::ReadFaces_3DGS_MDL7(const MDL::IntGroupInfo_MDL7 &groupInfo, + MDL::IntGroupData_MDL7 &groupData) { + const MDL::Header_MDL7 *pcHeader = (const MDL::Header_MDL7 *)this->mBuffer; + MDL::Triangle_MDL7 *pcGroupTris = groupInfo.pcGroupTris; // iterate through all triangles and build valid display lists unsigned int iOutIndex = 0; @@ -1045,142 +1008,143 @@ void MDLImporter::ReadFaces_3DGS_MDL7(const MDL::IntGroupInfo_MDL7& groupInfo, AI_SWAP2(pcGroupTris->v_index[2]); // iterate through all indices of the current triangle - for (unsigned int c = 0; c < 3;++c,++iOutIndex) { + for (unsigned int c = 0; c < 3; ++c, ++iOutIndex) { // validate the vertex index unsigned int iIndex = pcGroupTris->v_index[c]; - if(iIndex > (unsigned int)groupInfo.pcGroup->numverts) { + if (iIndex > (unsigned int)groupInfo.pcGroup->numverts) { // (we might need to read this section a second time - to process frame vertices correctly) - pcGroupTris->v_index[c] = iIndex = groupInfo.pcGroup->numverts-1; + pcGroupTris->v_index[c] = (uint16_t) (iIndex = groupInfo.pcGroup->numverts - 1 ); ASSIMP_LOG_WARN("Index overflow in MDL7 vertex list"); } // write the output face index - groupData.pcFaces[iTriangle].mIndices[2-c] = iOutIndex; + groupData.pcFaces[iTriangle].mIndices[2 - c] = iOutIndex; - aiVector3D& vPosition = groupData.vPositions[ iOutIndex ]; - vPosition.x = _AI_MDL7_ACCESS_VERT(groupInfo.pcGroupVerts,iIndex, pcHeader->mainvertex_stc_size) .x; - vPosition.y = _AI_MDL7_ACCESS_VERT(groupInfo.pcGroupVerts,iIndex,pcHeader->mainvertex_stc_size) .y; - vPosition.z = _AI_MDL7_ACCESS_VERT(groupInfo.pcGroupVerts,iIndex,pcHeader->mainvertex_stc_size) .z; + aiVector3D &vPosition = groupData.vPositions[iOutIndex]; + vPosition.x = _AI_MDL7_ACCESS_VERT(groupInfo.pcGroupVerts, iIndex, pcHeader->mainvertex_stc_size).x; + vPosition.y = _AI_MDL7_ACCESS_VERT(groupInfo.pcGroupVerts, iIndex, pcHeader->mainvertex_stc_size).y; + vPosition.z = _AI_MDL7_ACCESS_VERT(groupInfo.pcGroupVerts, iIndex, pcHeader->mainvertex_stc_size).z; // if we have bones, save the index if (!groupData.aiBones.empty()) { groupData.aiBones[iOutIndex] = _AI_MDL7_ACCESS_VERT(groupInfo.pcGroupVerts, - iIndex,pcHeader->mainvertex_stc_size).vertindex; + iIndex, pcHeader->mainvertex_stc_size) + .vertindex; } // now read the normal vector if (AI_MDL7_FRAMEVERTEX030305_STCSIZE <= pcHeader->mainvertex_stc_size) { // read the full normal vector - aiVector3D& vNormal = groupData.vNormals[ iOutIndex ]; - vNormal.x = _AI_MDL7_ACCESS_VERT(groupInfo.pcGroupVerts,iIndex,pcHeader->mainvertex_stc_size) .norm[0]; + aiVector3D &vNormal = groupData.vNormals[iOutIndex]; + vNormal.x = _AI_MDL7_ACCESS_VERT(groupInfo.pcGroupVerts, iIndex, pcHeader->mainvertex_stc_size).norm[0]; AI_SWAP4(vNormal.x); - vNormal.y = _AI_MDL7_ACCESS_VERT(groupInfo.pcGroupVerts,iIndex,pcHeader->mainvertex_stc_size) .norm[1]; + vNormal.y = _AI_MDL7_ACCESS_VERT(groupInfo.pcGroupVerts, iIndex, pcHeader->mainvertex_stc_size).norm[1]; AI_SWAP4(vNormal.y); - vNormal.z = _AI_MDL7_ACCESS_VERT(groupInfo.pcGroupVerts,iIndex,pcHeader->mainvertex_stc_size) .norm[2]; + vNormal.z = _AI_MDL7_ACCESS_VERT(groupInfo.pcGroupVerts, iIndex, pcHeader->mainvertex_stc_size).norm[2]; AI_SWAP4(vNormal.z); - } - else if (AI_MDL7_FRAMEVERTEX120503_STCSIZE <= pcHeader->mainvertex_stc_size) { + } else if (AI_MDL7_FRAMEVERTEX120503_STCSIZE <= pcHeader->mainvertex_stc_size) { // read the normal vector from Quake2's smart table - aiVector3D& vNormal = groupData.vNormals[ iOutIndex ]; - MD2::LookupNormalIndex(_AI_MDL7_ACCESS_VERT(groupInfo.pcGroupVerts,iIndex, - pcHeader->mainvertex_stc_size) .norm162index,vNormal); + aiVector3D &vNormal = groupData.vNormals[iOutIndex]; + MD2::LookupNormalIndex(_AI_MDL7_ACCESS_VERT(groupInfo.pcGroupVerts, iIndex, + pcHeader->mainvertex_stc_size) + .norm162index, + vNormal); } // validate and process the first uv coordinate set - if (pcHeader->triangle_stc_size >= AI_MDL7_TRIANGLE_STD_SIZE_ONE_UV) { + if (pcHeader->triangle_stc_size >= AI_MDL7_TRIANGLE_STD_SIZE_ONE_UV) { - if (groupInfo.pcGroup->num_stpts) { + if (groupInfo.pcGroup->num_stpts) { AI_SWAP2(pcGroupTris->skinsets[0].st_index[0]); AI_SWAP2(pcGroupTris->skinsets[0].st_index[1]); AI_SWAP2(pcGroupTris->skinsets[0].st_index[2]); iIndex = pcGroupTris->skinsets[0].st_index[c]; - if(iIndex > (unsigned int)groupInfo.pcGroup->num_stpts) { - iIndex = groupInfo.pcGroup->num_stpts-1; + if (iIndex > (unsigned int)groupInfo.pcGroup->num_stpts) { + iIndex = groupInfo.pcGroup->num_stpts - 1; ASSIMP_LOG_WARN("Index overflow in MDL7 UV coordinate list (#1)"); } float u = groupInfo.pcGroupUVs[iIndex].u; - float v = 1.0f-groupInfo.pcGroupUVs[iIndex].v; // DX to OGL + float v = 1.0f - groupInfo.pcGroupUVs[iIndex].v; // DX to OGL groupData.vTextureCoords1[iOutIndex].x = u; groupData.vTextureCoords1[iOutIndex].y = v; } // assign the material index, but only if it is existing - if (pcHeader->triangle_stc_size >= AI_MDL7_TRIANGLE_STD_SIZE_ONE_UV_WITH_MATINDEX){ + if (pcHeader->triangle_stc_size >= AI_MDL7_TRIANGLE_STD_SIZE_ONE_UV_WITH_MATINDEX) { AI_SWAP4(pcGroupTris->skinsets[0].material); groupData.pcFaces[iTriangle].iMatIndex[0] = pcGroupTris->skinsets[0].material; } } // validate and process the second uv coordinate set - if (pcHeader->triangle_stc_size >= AI_MDL7_TRIANGLE_STD_SIZE_TWO_UV) { + if (pcHeader->triangle_stc_size >= AI_MDL7_TRIANGLE_STD_SIZE_TWO_UV) { - if (groupInfo.pcGroup->num_stpts) { + if (groupInfo.pcGroup->num_stpts) { AI_SWAP2(pcGroupTris->skinsets[1].st_index[0]); AI_SWAP2(pcGroupTris->skinsets[1].st_index[1]); AI_SWAP2(pcGroupTris->skinsets[1].st_index[2]); AI_SWAP4(pcGroupTris->skinsets[1].material); iIndex = pcGroupTris->skinsets[1].st_index[c]; - if(iIndex > (unsigned int)groupInfo.pcGroup->num_stpts) { - iIndex = groupInfo.pcGroup->num_stpts-1; + if (iIndex > (unsigned int)groupInfo.pcGroup->num_stpts) { + iIndex = groupInfo.pcGroup->num_stpts - 1; ASSIMP_LOG_WARN("Index overflow in MDL7 UV coordinate list (#2)"); } - float u = groupInfo.pcGroupUVs[ iIndex ].u; - float v = 1.0f-groupInfo.pcGroupUVs[ iIndex ].v; + float u = groupInfo.pcGroupUVs[iIndex].u; + float v = 1.0f - groupInfo.pcGroupUVs[iIndex].v; - groupData.vTextureCoords2[ iOutIndex ].x = u; - groupData.vTextureCoords2[ iOutIndex ].y = v; // DX to OGL + groupData.vTextureCoords2[iOutIndex].x = u; + groupData.vTextureCoords2[iOutIndex].y = v; // DX to OGL // check whether we do really need the second texture // coordinate set ... wastes memory and loading time - if (0 != iIndex && (u != groupData.vTextureCoords1[ iOutIndex ].x || - v != groupData.vTextureCoords1[ iOutIndex ].y ) ) + if (0 != iIndex && (u != groupData.vTextureCoords1[iOutIndex].x || + v != groupData.vTextureCoords1[iOutIndex].y)) groupData.bNeed2UV = true; // if the material differs, we need a second skin, too - if (pcGroupTris->skinsets[ 1 ].material != pcGroupTris->skinsets[ 0 ].material) + if (pcGroupTris->skinsets[1].material != pcGroupTris->skinsets[0].material) groupData.bNeed2UV = true; } // assign the material index - groupData.pcFaces[ iTriangle ].iMatIndex[ 1 ] = pcGroupTris->skinsets[ 1 ].material; + groupData.pcFaces[iTriangle].iMatIndex[1] = pcGroupTris->skinsets[1].material; } } // get the next triangle in the list - pcGroupTris = (MDL::Triangle_MDL7*)((const char*)pcGroupTris + pcHeader->triangle_stc_size); + pcGroupTris = (MDL::Triangle_MDL7 *)((const char *)pcGroupTris + pcHeader->triangle_stc_size); } } // ------------------------------------------------------------------------------------------------ // handle frames in a MDL7 file -bool MDLImporter::ProcessFrames_3DGS_MDL7(const MDL::IntGroupInfo_MDL7& groupInfo, - MDL::IntGroupData_MDL7& groupData, - MDL::IntSharedData_MDL7& shared, - const unsigned char* szCurrent, - const unsigned char** szCurrentOut) -{ - ai_assert( nullptr != szCurrent ); - ai_assert( nullptr != szCurrentOut); +bool MDLImporter::ProcessFrames_3DGS_MDL7(const MDL::IntGroupInfo_MDL7 &groupInfo, + MDL::IntGroupData_MDL7 &groupData, + MDL::IntSharedData_MDL7 &shared, + const unsigned char *szCurrent, + const unsigned char **szCurrentOut) { + ai_assert(nullptr != szCurrent); + ai_assert(nullptr != szCurrentOut); - const MDL::Header_MDL7 *pcHeader = (const MDL::Header_MDL7*)mBuffer; + const MDL::Header_MDL7 *pcHeader = (const MDL::Header_MDL7 *)mBuffer; // if we have no bones we can simply skip all frames, // otherwise we'll need to process them. // FIX: If we need another frame than the first we must apply frame vertex replacements ... - for(unsigned int iFrame = 0; iFrame < (unsigned int)groupInfo.pcGroup->numframes;++iFrame) { - MDL::IntFrameInfo_MDL7 frame ((BE_NCONST MDL::Frame_MDL7*)szCurrent,iFrame); + for (unsigned int iFrame = 0; iFrame < (unsigned int)groupInfo.pcGroup->numframes; ++iFrame) { + MDL::IntFrameInfo_MDL7 frame((BE_NCONST MDL::Frame_MDL7 *)szCurrent, iFrame); AI_SWAP4(frame.pcFrame->vertices_count); AI_SWAP4(frame.pcFrame->transmatrix_count); const unsigned int iAdd = pcHeader->frame_stc_size + - frame.pcFrame->vertices_count * pcHeader->framevertex_stc_size + - frame.pcFrame->transmatrix_count * pcHeader->bonetrans_stc_size; + frame.pcFrame->vertices_count * pcHeader->framevertex_stc_size + + frame.pcFrame->transmatrix_count * pcHeader->bonetrans_stc_size; - if (((const char*)szCurrent - (const char*)pcHeader) + iAdd > (unsigned int)pcHeader->data_size) { + if (((const char *)szCurrent - (const char *)pcHeader) + iAdd > (unsigned int)pcHeader->data_size) { ASSIMP_LOG_WARN("Index overflow in frame area. " - "Ignoring all frames and all further mesh groups, too."); + "Ignoring all frames and all further mesh groups, too."); // don't parse more groups if we can't even read one // FIXME: sometimes this seems to occur even for valid files ... @@ -1188,66 +1152,68 @@ bool MDLImporter::ProcessFrames_3DGS_MDL7(const MDL::IntGroupInfo_MDL7& groupInf return false; } // our output frame? - if (configFrameID == iFrame) { - BE_NCONST MDL::Vertex_MDL7* pcFrameVertices = (BE_NCONST MDL::Vertex_MDL7*)(szCurrent+pcHeader->frame_stc_size); + if (configFrameID == iFrame) { + BE_NCONST MDL::Vertex_MDL7 *pcFrameVertices = (BE_NCONST MDL::Vertex_MDL7 *)(szCurrent + pcHeader->frame_stc_size); - for (unsigned int qq = 0; qq < frame.pcFrame->vertices_count;++qq) { + for (unsigned int qq = 0; qq < frame.pcFrame->vertices_count; ++qq) { // I assume this are simple replacements for normal vertices, the bone index serving // as the index of the vertex to be replaced. - uint16_t iIndex = _AI_MDL7_ACCESS(pcFrameVertices,qq,pcHeader->framevertex_stc_size,MDL::Vertex_MDL7).vertindex; + uint16_t iIndex = _AI_MDL7_ACCESS(pcFrameVertices, qq, pcHeader->framevertex_stc_size, MDL::Vertex_MDL7).vertindex; AI_SWAP2(iIndex); - if (iIndex >= groupInfo.pcGroup->numverts) { + if (iIndex >= groupInfo.pcGroup->numverts) { ASSIMP_LOG_WARN("Invalid vertex index in frame vertex section"); continue; } - aiVector3D vPosition,vNormal; + aiVector3D vPosition, vNormal; - vPosition.x = _AI_MDL7_ACCESS_VERT(pcFrameVertices,qq,pcHeader->framevertex_stc_size) .x; + vPosition.x = _AI_MDL7_ACCESS_VERT(pcFrameVertices, qq, pcHeader->framevertex_stc_size).x; AI_SWAP4(vPosition.x); - vPosition.y = _AI_MDL7_ACCESS_VERT(pcFrameVertices,qq,pcHeader->framevertex_stc_size) .y; + vPosition.y = _AI_MDL7_ACCESS_VERT(pcFrameVertices, qq, pcHeader->framevertex_stc_size).y; AI_SWAP4(vPosition.y); - vPosition.z = _AI_MDL7_ACCESS_VERT(pcFrameVertices,qq,pcHeader->framevertex_stc_size) .z; + vPosition.z = _AI_MDL7_ACCESS_VERT(pcFrameVertices, qq, pcHeader->framevertex_stc_size).z; AI_SWAP4(vPosition.z); // now read the normal vector if (AI_MDL7_FRAMEVERTEX030305_STCSIZE <= pcHeader->mainvertex_stc_size) { // read the full normal vector - vNormal.x = _AI_MDL7_ACCESS_VERT(pcFrameVertices,qq,pcHeader->framevertex_stc_size) .norm[0]; + vNormal.x = _AI_MDL7_ACCESS_VERT(pcFrameVertices, qq, pcHeader->framevertex_stc_size).norm[0]; AI_SWAP4(vNormal.x); - vNormal.y = _AI_MDL7_ACCESS_VERT(pcFrameVertices,qq,pcHeader->framevertex_stc_size) .norm[1]; + vNormal.y = _AI_MDL7_ACCESS_VERT(pcFrameVertices, qq, pcHeader->framevertex_stc_size).norm[1]; AI_SWAP4(vNormal.y); - vNormal.z = _AI_MDL7_ACCESS_VERT(pcFrameVertices,qq,pcHeader->framevertex_stc_size) .norm[2]; + vNormal.z = _AI_MDL7_ACCESS_VERT(pcFrameVertices, qq, pcHeader->framevertex_stc_size).norm[2]; AI_SWAP4(vNormal.z); - } - else if (AI_MDL7_FRAMEVERTEX120503_STCSIZE <= pcHeader->mainvertex_stc_size) { + } else if (AI_MDL7_FRAMEVERTEX120503_STCSIZE <= pcHeader->mainvertex_stc_size) { // read the normal vector from Quake2's smart table - MD2::LookupNormalIndex(_AI_MDL7_ACCESS_VERT(pcFrameVertices,qq, - pcHeader->framevertex_stc_size) .norm162index,vNormal); + MD2::LookupNormalIndex(_AI_MDL7_ACCESS_VERT(pcFrameVertices, qq, + pcHeader->framevertex_stc_size) + .norm162index, + vNormal); } // FIXME: O(n^2) at the moment ... - BE_NCONST MDL::Triangle_MDL7* pcGroupTris = groupInfo.pcGroupTris; + BE_NCONST MDL::Triangle_MDL7 *pcGroupTris = groupInfo.pcGroupTris; unsigned int iOutIndex = 0; for (unsigned int iTriangle = 0; iTriangle < (unsigned int)groupInfo.pcGroup->numtris; ++iTriangle) { // iterate through all indices of the current triangle - for (unsigned int c = 0; c < 3;++c,++iOutIndex) { + for (unsigned int c = 0; c < 3; ++c, ++iOutIndex) { // replace the vertex with the new data const unsigned int iCurIndex = pcGroupTris->v_index[c]; - if (iCurIndex == iIndex) { + if (iCurIndex == iIndex) { groupData.vPositions[iOutIndex] = vPosition; groupData.vNormals[iOutIndex] = vNormal; } } // get the next triangle in the list - pcGroupTris = (BE_NCONST MDL::Triangle_MDL7*)((const char*) - pcGroupTris + pcHeader->triangle_stc_size); + pcGroupTris = (BE_NCONST MDL::Triangle_MDL7 *)((const char *) + pcGroupTris + + pcHeader->triangle_stc_size); } } } // parse bone trafo matrix keys (only if there are bones ...) if (shared.apcOutBones) { - ParseBoneTrafoKeys_3DGS_MDL7(groupInfo,frame,shared); + ParseBoneTrafoKeys_3DGS_MDL7(groupInfo, frame, shared); } szCurrent += iAdd; } @@ -1258,92 +1224,88 @@ bool MDLImporter::ProcessFrames_3DGS_MDL7(const MDL::IntGroupInfo_MDL7& groupInf // ------------------------------------------------------------------------------------------------ // Sort faces by material, handle multiple UVs correctly void MDLImporter::SortByMaterials_3DGS_MDL7( - const MDL::IntGroupInfo_MDL7& groupInfo, - MDL::IntGroupData_MDL7& groupData, - MDL::IntSplitGroupData_MDL7& splitGroupData) -{ + const MDL::IntGroupInfo_MDL7 &groupInfo, + MDL::IntGroupData_MDL7 &groupData, + MDL::IntSplitGroupData_MDL7 &splitGroupData) { const unsigned int iNumMaterials = (unsigned int)splitGroupData.shared.pcMats.size(); - if (!groupData.bNeed2UV) { + if (!groupData.bNeed2UV) { // if we don't need a second set of texture coordinates there is no reason to keep it in memory ... groupData.vTextureCoords2.clear(); // allocate the array - splitGroupData.aiSplit = new std::vector*[iNumMaterials]; + splitGroupData.aiSplit = new std::vector *[iNumMaterials]; - for (unsigned int m = 0; m < iNumMaterials;++m) + for (unsigned int m = 0; m < iNumMaterials; ++m) splitGroupData.aiSplit[m] = new std::vector(); // iterate through all faces and sort by material - for (unsigned int iFace = 0; iFace < (unsigned int)groupInfo.pcGroup->numtris;++iFace) { + for (unsigned int iFace = 0; iFace < (unsigned int)groupInfo.pcGroup->numtris; ++iFace) { // check range if (groupData.pcFaces[iFace].iMatIndex[0] >= iNumMaterials) { // use the last material instead - splitGroupData.aiSplit[iNumMaterials-1]->push_back(iFace); + splitGroupData.aiSplit[iNumMaterials - 1]->push_back(iFace); // sometimes MED writes -1, but normally only if there is only // one skin assigned. No warning in this case - if(0xFFFFFFFF != groupData.pcFaces[iFace].iMatIndex[0]) + if (0xFFFFFFFF != groupData.pcFaces[iFace].iMatIndex[0]) ASSIMP_LOG_WARN("Index overflow in MDL7 material list [#0]"); - } - else splitGroupData.aiSplit[groupData.pcFaces[iFace]. - iMatIndex[0]]->push_back(iFace); + } else + splitGroupData.aiSplit[groupData.pcFaces[iFace].iMatIndex[0]]->push_back(iFace); } - } - else - { + } else { // we need to build combined materials for each combination of std::vector avMats; - avMats.reserve(iNumMaterials*2); + avMats.reserve(iNumMaterials * 2); // fixme: why on the heap? - std::vector* > aiTempSplit(iNumMaterials*2); - for (unsigned int m = 0; m < iNumMaterials;++m) + std::vector *> aiTempSplit(iNumMaterials * 2); + for (unsigned int m = 0; m < iNumMaterials; ++m) aiTempSplit[m] = new std::vector(); // iterate through all faces and sort by material - for (unsigned int iFace = 0; iFace < (unsigned int)groupInfo.pcGroup->numtris;++iFace) { + for (unsigned int iFace = 0; iFace < (unsigned int)groupInfo.pcGroup->numtris; ++iFace) { // check range unsigned int iMatIndex = groupData.pcFaces[iFace].iMatIndex[0]; if (iMatIndex >= iNumMaterials) { // sometimes MED writes -1, but normally only if there is only // one skin assigned. No warning in this case - if(UINT_MAX != iMatIndex) + if (UINT_MAX != iMatIndex) ASSIMP_LOG_WARN("Index overflow in MDL7 material list [#1]"); - iMatIndex = iNumMaterials-1; + iMatIndex = iNumMaterials - 1; } unsigned int iMatIndex2 = groupData.pcFaces[iFace].iMatIndex[1]; unsigned int iNum = iMatIndex; - if (UINT_MAX != iMatIndex2 && iMatIndex != iMatIndex2) { - if (iMatIndex2 >= iNumMaterials) { + if (UINT_MAX != iMatIndex2 && iMatIndex != iMatIndex2) { + if (iMatIndex2 >= iNumMaterials) { // sometimes MED writes -1, but normally only if there is only // one skin assigned. No warning in this case ASSIMP_LOG_WARN("Index overflow in MDL7 material list [#2]"); - iMatIndex2 = iNumMaterials-1; + iMatIndex2 = iNumMaterials - 1; } // do a slow search in the list ... iNum = 0; bool bFound = false; - for (std::vector::iterator i = avMats.begin();i != avMats.end();++i,++iNum){ - if ((*i).iOldMatIndices[0] == iMatIndex && (*i).iOldMatIndices[1] == iMatIndex2) { + for (std::vector::iterator i = avMats.begin(); i != avMats.end(); ++i, ++iNum) { + if ((*i).iOldMatIndices[0] == iMatIndex && (*i).iOldMatIndices[1] == iMatIndex2) { // reuse this material bFound = true; break; } } - if (!bFound) { + if (!bFound) { // build a new material ... MDL::IntMaterial_MDL7 sHelper; sHelper.pcMat = new aiMaterial(); sHelper.iOldMatIndices[0] = iMatIndex; sHelper.iOldMatIndices[1] = iMatIndex2; JoinSkins_3DGS_MDL7(splitGroupData.shared.pcMats[iMatIndex], - splitGroupData.shared.pcMats[iMatIndex2],sHelper.pcMat); + splitGroupData.shared.pcMats[iMatIndex2], sHelper.pcMat); // and add it to the list avMats.push_back(sHelper); - iNum = (unsigned int)avMats.size()-1; + iNum = (unsigned int)avMats.size() - 1; } // adjust the size of the file array if (iNum == aiTempSplit.size()) { @@ -1354,36 +1316,34 @@ void MDLImporter::SortByMaterials_3DGS_MDL7( } // now add the newly created materials to the old list - if (0 == groupInfo.iIndex) { + if (0 == groupInfo.iIndex) { splitGroupData.shared.pcMats.resize(avMats.size()); - for (unsigned int o = 0; o < avMats.size();++o) + for (unsigned int o = 0; o < avMats.size(); ++o) splitGroupData.shared.pcMats[o] = avMats[o].pcMat; - } - else { + } else { // This might result in redundant materials ... splitGroupData.shared.pcMats.resize(iNumMaterials + avMats.size()); - for (unsigned int o = iNumMaterials; o < avMats.size();++o) + for (unsigned int o = iNumMaterials; o < avMats.size(); ++o) splitGroupData.shared.pcMats[o] = avMats[o].pcMat; } // and build the final face-to-material array - splitGroupData.aiSplit = new std::vector*[aiTempSplit.size()]; - for (unsigned int m = 0; m < iNumMaterials;++m) + splitGroupData.aiSplit = new std::vector *[aiTempSplit.size()]; + for (unsigned int m = 0; m < iNumMaterials; ++m) splitGroupData.aiSplit[m] = aiTempSplit[m]; } } // ------------------------------------------------------------------------------------------------ // Read a MDL7 file -void MDLImporter::InternReadFile_3DGS_MDL7( ) -{ +void MDLImporter::InternReadFile_3DGS_MDL7() { ai_assert(NULL != pScene); MDL::IntSharedData_MDL7 sharedData; // current cursor position in the file - BE_NCONST MDL::Header_MDL7 *pcHeader = (BE_NCONST MDL::Header_MDL7*)this->mBuffer; - const unsigned char* szCurrent = (const unsigned char*)(pcHeader+1); + BE_NCONST MDL::Header_MDL7 *pcHeader = (BE_NCONST MDL::Header_MDL7 *)this->mBuffer; + const unsigned char *szCurrent = (const unsigned char *)(pcHeader + 1); AI_SWAP4(pcHeader->version); AI_SWAP4(pcHeader->bones_num); @@ -1413,21 +1373,21 @@ void MDLImporter::InternReadFile_3DGS_MDL7( ) sharedData.apcOutBones = this->LoadBones_3DGS_MDL7(); // vector to held all created meshes - std::vector* avOutList; + std::vector *avOutList; // 3 meshes per group - that should be OK for most models - avOutList = new std::vector[pcHeader->groups_num]; - for (uint32_t i = 0; i < pcHeader->groups_num;++i) + avOutList = new std::vector[pcHeader->groups_num]; + for (uint32_t i = 0; i < pcHeader->groups_num; ++i) avOutList[i].reserve(3); // buffer to held the names of all groups in the file - const size_t buffersize(AI_MDL7_MAX_GROUPNAMESIZE*pcHeader->groups_num); - char* aszGroupNameBuffer = new char[ buffersize ]; + const size_t buffersize(AI_MDL7_MAX_GROUPNAMESIZE * pcHeader->groups_num); + char *aszGroupNameBuffer = new char[buffersize]; // read all groups for (unsigned int iGroup = 0; iGroup < (unsigned int)pcHeader->groups_num; ++iGroup) { - MDL::IntGroupInfo_MDL7 groupInfo((BE_NCONST MDL::Group_MDL7*)szCurrent,iGroup); - szCurrent = (const unsigned char*)(groupInfo.pcGroup+1); + MDL::IntGroupInfo_MDL7 groupInfo((BE_NCONST MDL::Group_MDL7 *)szCurrent, iGroup); + szCurrent = (const unsigned char *)(groupInfo.pcGroup + 1); VALIDATE_FILE_SIZE(szCurrent); @@ -1438,64 +1398,65 @@ void MDLImporter::InternReadFile_3DGS_MDL7( ) AI_SWAP4(groupInfo.pcGroup->numverts); AI_SWAP4(groupInfo.pcGroup->numframes); - if (1 != groupInfo.pcGroup->typ) { + if (1 != groupInfo.pcGroup->typ) { // Not a triangle-based mesh ASSIMP_LOG_WARN("[3DGS MDL7] Not a triangle mesh group. Continuing happily"); } // store the name of the group - const unsigned int ofs = iGroup*AI_MDL7_MAX_GROUPNAMESIZE; + const unsigned int ofs = iGroup * AI_MDL7_MAX_GROUPNAMESIZE; ::memcpy(&aszGroupNameBuffer[ofs], - groupInfo.pcGroup->name,AI_MDL7_MAX_GROUPNAMESIZE); + groupInfo.pcGroup->name, AI_MDL7_MAX_GROUPNAMESIZE); // make sure '\0' is at the end - aszGroupNameBuffer[ofs+AI_MDL7_MAX_GROUPNAMESIZE-1] = '\0'; + aszGroupNameBuffer[ofs + AI_MDL7_MAX_GROUPNAMESIZE - 1] = '\0'; // read all skins sharedData.pcMats.reserve(sharedData.pcMats.size() + groupInfo.pcGroup->numskins); sharedData.abNeedMaterials.resize(sharedData.abNeedMaterials.size() + - groupInfo.pcGroup->numskins,false); + groupInfo.pcGroup->numskins, + false); - for (unsigned int iSkin = 0; iSkin < (unsigned int)groupInfo.pcGroup->numskins;++iSkin) { - ParseSkinLump_3DGS_MDL7(szCurrent,&szCurrent,sharedData.pcMats); + for (unsigned int iSkin = 0; iSkin < (unsigned int)groupInfo.pcGroup->numskins; ++iSkin) { + ParseSkinLump_3DGS_MDL7(szCurrent, &szCurrent, sharedData.pcMats); } // if we have absolutely no skin loaded we need to generate a default material - if (sharedData.pcMats.empty()) { + if (sharedData.pcMats.empty()) { const int iMode = (int)aiShadingMode_Gouraud; sharedData.pcMats.push_back(new aiMaterial()); - aiMaterial* pcHelper = (aiMaterial*)sharedData.pcMats[0]; + aiMaterial *pcHelper = (aiMaterial *)sharedData.pcMats[0]; pcHelper->AddProperty(&iMode, 1, AI_MATKEY_SHADING_MODEL); aiColor3D clr; clr.b = clr.g = clr.r = 0.6f; - pcHelper->AddProperty(&clr, 1,AI_MATKEY_COLOR_DIFFUSE); - pcHelper->AddProperty(&clr, 1,AI_MATKEY_COLOR_SPECULAR); + pcHelper->AddProperty(&clr, 1, AI_MATKEY_COLOR_DIFFUSE); + pcHelper->AddProperty(&clr, 1, AI_MATKEY_COLOR_SPECULAR); clr.b = clr.g = clr.r = 0.05f; - pcHelper->AddProperty(&clr, 1,AI_MATKEY_COLOR_AMBIENT); + pcHelper->AddProperty(&clr, 1, AI_MATKEY_COLOR_AMBIENT); aiString szName; szName.Set(AI_DEFAULT_MATERIAL_NAME); - pcHelper->AddProperty(&szName,AI_MATKEY_NAME); + pcHelper->AddProperty(&szName, AI_MATKEY_NAME); - sharedData.abNeedMaterials.resize(1,false); + sharedData.abNeedMaterials.resize(1, false); } // now get a pointer to all texture coords in the group - groupInfo.pcGroupUVs = (BE_NCONST MDL::TexCoord_MDL7*)szCurrent; - for(int i = 0; i < groupInfo.pcGroup->num_stpts; ++i){ + groupInfo.pcGroupUVs = (BE_NCONST MDL::TexCoord_MDL7 *)szCurrent; + for (int i = 0; i < groupInfo.pcGroup->num_stpts; ++i) { AI_SWAP4(groupInfo.pcGroupUVs[i].u); AI_SWAP4(groupInfo.pcGroupUVs[i].v); } szCurrent += pcHeader->skinpoint_stc_size * groupInfo.pcGroup->num_stpts; // now get a pointer to all triangle in the group - groupInfo.pcGroupTris = (Triangle_MDL7*)szCurrent; + groupInfo.pcGroupTris = (Triangle_MDL7 *)szCurrent; szCurrent += pcHeader->triangle_stc_size * groupInfo.pcGroup->numtris; // now get a pointer to all vertices in the group - groupInfo.pcGroupVerts = (BE_NCONST MDL::Vertex_MDL7*)szCurrent; - for(int i = 0; i < groupInfo.pcGroup->numverts; ++i){ + groupInfo.pcGroupVerts = (BE_NCONST MDL::Vertex_MDL7 *)szCurrent; + for (int i = 0; i < groupInfo.pcGroup->numverts; ++i) { AI_SWAP4(groupInfo.pcGroupVerts[i].x); AI_SWAP4(groupInfo.pcGroupVerts[i].y); AI_SWAP4(groupInfo.pcGroupVerts[i].z); @@ -1506,25 +1467,24 @@ void MDLImporter::InternReadFile_3DGS_MDL7( ) szCurrent += pcHeader->mainvertex_stc_size * groupInfo.pcGroup->numverts; VALIDATE_FILE_SIZE(szCurrent); - MDL::IntSplitGroupData_MDL7 splitGroupData(sharedData,avOutList[iGroup]); + MDL::IntSplitGroupData_MDL7 splitGroupData(sharedData, avOutList[iGroup]); MDL::IntGroupData_MDL7 groupData; - if (groupInfo.pcGroup->numtris && groupInfo.pcGroup->numverts) - { + if (groupInfo.pcGroup->numtris && groupInfo.pcGroup->numverts) { // build output vectors - const unsigned int iNumVertices = groupInfo.pcGroup->numtris*3; + const unsigned int iNumVertices = groupInfo.pcGroup->numtris * 3; groupData.vPositions.resize(iNumVertices); groupData.vNormals.resize(iNumVertices); - if (sharedData.apcOutBones)groupData.aiBones.resize(iNumVertices,UINT_MAX); + if (sharedData.apcOutBones) groupData.aiBones.resize(iNumVertices, UINT_MAX); // it is also possible that there are 0 UV coordinate sets - if (groupInfo.pcGroup->num_stpts){ - groupData.vTextureCoords1.resize(iNumVertices,aiVector3D()); + if (groupInfo.pcGroup->num_stpts) { + groupData.vTextureCoords1.resize(iNumVertices, aiVector3D()); // check whether the triangle data structure is large enough // to contain a second UV coordinate set - if (pcHeader->triangle_stc_size >= AI_MDL7_TRIANGLE_STD_SIZE_TWO_UV) { - groupData.vTextureCoords2.resize(iNumVertices,aiVector3D()); + if (pcHeader->triangle_stc_size >= AI_MDL7_TRIANGLE_STD_SIZE_TWO_UV) { + groupData.vTextureCoords2.resize(iNumVertices, aiVector3D()); groupData.bNeed2UV = true; } } @@ -1535,73 +1495,74 @@ void MDLImporter::InternReadFile_3DGS_MDL7( ) // sort by materials SortByMaterials_3DGS_MDL7(groupInfo, groupData, - splitGroupData); + splitGroupData); - for (unsigned int qq = 0; qq < sharedData.pcMats.size();++qq) { + for (unsigned int qq = 0; qq < sharedData.pcMats.size(); ++qq) { if (!splitGroupData.aiSplit[qq]->empty()) sharedData.abNeedMaterials[qq] = true; } - } - else ASSIMP_LOG_WARN("[3DGS MDL7] Mesh group consists of 0 " - "vertices or faces. It will be skipped."); + } else + ASSIMP_LOG_WARN("[3DGS MDL7] Mesh group consists of 0 " + "vertices or faces. It will be skipped."); // process all frames and generate output meshes - ProcessFrames_3DGS_MDL7(groupInfo,groupData, sharedData,szCurrent,&szCurrent); - GenerateOutputMeshes_3DGS_MDL7(groupData,splitGroupData); + ProcessFrames_3DGS_MDL7(groupInfo, groupData, sharedData, szCurrent, &szCurrent); + GenerateOutputMeshes_3DGS_MDL7(groupData, splitGroupData); } // generate a nodegraph and subnodes for each group pScene->mRootNode = new aiNode(); // now we need to build a final mesh list - for (uint32_t i = 0; i < pcHeader->groups_num;++i) + for (uint32_t i = 0; i < pcHeader->groups_num; ++i) pScene->mNumMeshes += (unsigned int)avOutList[i].size(); - pScene->mMeshes = new aiMesh*[pScene->mNumMeshes]; { - unsigned int p = 0,q = 0; - for (uint32_t i = 0; i < pcHeader->groups_num;++i) { - for (unsigned int a = 0; a < avOutList[i].size();++a) { + pScene->mMeshes = new aiMesh *[pScene->mNumMeshes]; + { + unsigned int p = 0, q = 0; + for (uint32_t i = 0; i < pcHeader->groups_num; ++i) { + for (unsigned int a = 0; a < avOutList[i].size(); ++a) { pScene->mMeshes[p++] = avOutList[i][a]; } - if (!avOutList[i].empty())++pScene->mRootNode->mNumChildren; + if (!avOutList[i].empty()) ++pScene->mRootNode->mNumChildren; } // we will later need an extra node to serve as parent for all bones - if (sharedData.apcOutBones)++pScene->mRootNode->mNumChildren; - this->pScene->mRootNode->mChildren = new aiNode*[pScene->mRootNode->mNumChildren]; + if (sharedData.apcOutBones) ++pScene->mRootNode->mNumChildren; + this->pScene->mRootNode->mChildren = new aiNode *[pScene->mRootNode->mNumChildren]; p = 0; - for (uint32_t i = 0; i < pcHeader->groups_num;++i) { - if (avOutList[i].empty())continue; + for (uint32_t i = 0; i < pcHeader->groups_num; ++i) { + if (avOutList[i].empty()) continue; - aiNode* const pcNode = pScene->mRootNode->mChildren[p] = new aiNode(); + aiNode *const pcNode = pScene->mRootNode->mChildren[p] = new aiNode(); pcNode->mNumMeshes = (unsigned int)avOutList[i].size(); pcNode->mMeshes = new unsigned int[pcNode->mNumMeshes]; pcNode->mParent = this->pScene->mRootNode; - for (unsigned int a = 0; a < pcNode->mNumMeshes;++a) + for (unsigned int a = 0; a < pcNode->mNumMeshes; ++a) pcNode->mMeshes[a] = q + a; q += (unsigned int)avOutList[i].size(); // setup the name of the node - char* const szBuffer = &aszGroupNameBuffer[i*AI_MDL7_MAX_GROUPNAMESIZE]; - if ('\0' == *szBuffer) { - const size_t maxSize(buffersize - (i*AI_MDL7_MAX_GROUPNAMESIZE)); - pcNode->mName.length = ai_snprintf(szBuffer, maxSize, "Group_%u", p); - } else { - pcNode->mName.length = (ai_uint32)::strlen(szBuffer); - } - ::strncpy(pcNode->mName.data,szBuffer,MAXLEN-1); + char *const szBuffer = &aszGroupNameBuffer[i * AI_MDL7_MAX_GROUPNAMESIZE]; + if ('\0' == *szBuffer) { + const size_t maxSize(buffersize - (i * AI_MDL7_MAX_GROUPNAMESIZE)); + pcNode->mName.length = ai_snprintf(szBuffer, maxSize, "Group_%u", p); + } else { + pcNode->mName.length = (ai_uint32)::strlen(szBuffer); + } + ::strncpy(pcNode->mName.data, szBuffer, MAXLEN - 1); ++p; } } // if there is only one root node with a single child we can optimize it a bit ... - if (1 == pScene->mRootNode->mNumChildren && !sharedData.apcOutBones) { - aiNode* pcOldRoot = this->pScene->mRootNode; + if (1 == pScene->mRootNode->mNumChildren && !sharedData.apcOutBones) { + aiNode *pcOldRoot = this->pScene->mRootNode; pScene->mRootNode = pcOldRoot->mChildren[0]; pcOldRoot->mChildren[0] = NULL; delete pcOldRoot; pScene->mRootNode->mParent = NULL; - } - else pScene->mRootNode->mName.Set(""); + } else + pScene->mRootNode->mName.Set(""); delete[] avOutList; delete[] aszGroupNameBuffer; @@ -1616,53 +1577,51 @@ void MDLImporter::InternReadFile_3DGS_MDL7( ) if (sharedData.apcOutBones) { // this step adds empty dummy bones to the nodegraph // insert another dummy node to avoid name conflicts - aiNode* const pc = pScene->mRootNode->mChildren[pScene->mRootNode->mNumChildren-1] = new aiNode(); + aiNode *const pc = pScene->mRootNode->mChildren[pScene->mRootNode->mNumChildren - 1] = new aiNode(); pc->mName.Set(""); // add bones to the nodegraph AddBonesToNodeGraph_3DGS_MDL7((const Assimp::MDL::IntBone_MDL7 **) - sharedData.apcOutBones,pc,0xffff); + sharedData.apcOutBones, + pc, 0xffff); // this steps build a valid output animation BuildOutputAnims_3DGS_MDL7((const Assimp::MDL::IntBone_MDL7 **) - sharedData.apcOutBones); + sharedData.apcOutBones); } } // ------------------------------------------------------------------------------------------------ // Copy materials -void MDLImporter::CopyMaterials_3DGS_MDL7(MDL::IntSharedData_MDL7 &shared) -{ +void MDLImporter::CopyMaterials_3DGS_MDL7(MDL::IntSharedData_MDL7 &shared) { pScene->mNumMaterials = (unsigned int)shared.pcMats.size(); - pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials]; - for (unsigned int i = 0; i < pScene->mNumMaterials;++i) + pScene->mMaterials = new aiMaterial *[pScene->mNumMaterials]; + for (unsigned int i = 0; i < pScene->mNumMaterials; ++i) pScene->mMaterials[i] = shared.pcMats[i]; } - // ------------------------------------------------------------------------------------------------ // Process material references -void MDLImporter::HandleMaterialReferences_3DGS_MDL7() -{ +void MDLImporter::HandleMaterialReferences_3DGS_MDL7() { // search for referrer materials - for (unsigned int i = 0; i < pScene->mNumMaterials;++i) { + for (unsigned int i = 0; i < pScene->mNumMaterials; ++i) { int iIndex = 0; - if (AI_SUCCESS == aiGetMaterialInteger(pScene->mMaterials[i],AI_MDL7_REFERRER_MATERIAL, &iIndex) ) { - for (unsigned int a = 0; a < pScene->mNumMeshes;++a) { - aiMesh* const pcMesh = pScene->mMeshes[a]; + if (AI_SUCCESS == aiGetMaterialInteger(pScene->mMaterials[i], AI_MDL7_REFERRER_MATERIAL, &iIndex)) { + for (unsigned int a = 0; a < pScene->mNumMeshes; ++a) { + aiMesh *const pcMesh = pScene->mMeshes[a]; if (i == pcMesh->mMaterialIndex) { pcMesh->mMaterialIndex = iIndex; } } // collapse the rest of the array delete pScene->mMaterials[i]; - for (unsigned int pp = i; pp < pScene->mNumMaterials-1;++pp) { + for (unsigned int pp = i; pp < pScene->mNumMaterials - 1; ++pp) { - pScene->mMaterials[pp] = pScene->mMaterials[pp+1]; - for (unsigned int a = 0; a < pScene->mNumMeshes;++a) { - aiMesh* const pcMesh = pScene->mMeshes[a]; - if (pcMesh->mMaterialIndex > i)--pcMesh->mMaterialIndex; + pScene->mMaterials[pp] = pScene->mMaterials[pp + 1]; + for (unsigned int a = 0; a < pScene->mNumMeshes; ++a) { + aiMesh *const pcMesh = pScene->mMeshes[a]; + if (pcMesh->mMaterialIndex > i) --pcMesh->mMaterialIndex; } } --pScene->mNumMaterials; @@ -1673,35 +1632,30 @@ void MDLImporter::HandleMaterialReferences_3DGS_MDL7() // ------------------------------------------------------------------------------------------------ // Read bone transformation keys void MDLImporter::ParseBoneTrafoKeys_3DGS_MDL7( - const MDL::IntGroupInfo_MDL7& groupInfo, - IntFrameInfo_MDL7& frame, - MDL::IntSharedData_MDL7& shared) -{ - const MDL::Header_MDL7* const pcHeader = (const MDL::Header_MDL7*)this->mBuffer; + const MDL::IntGroupInfo_MDL7 &groupInfo, + IntFrameInfo_MDL7 &frame, + MDL::IntSharedData_MDL7 &shared) { + const MDL::Header_MDL7 *const pcHeader = (const MDL::Header_MDL7 *)this->mBuffer; // only the first group contains bone animation keys - if (frame.pcFrame->transmatrix_count) { - if (!groupInfo.iIndex) { + if (frame.pcFrame->transmatrix_count) { + if (!groupInfo.iIndex) { // skip all frames vertices. We can't support them - const MDL::BoneTransform_MDL7* pcBoneTransforms = (const MDL::BoneTransform_MDL7*) - (((const char*)frame.pcFrame) + pcHeader->frame_stc_size + - frame.pcFrame->vertices_count * pcHeader->framevertex_stc_size); + const MDL::BoneTransform_MDL7 *pcBoneTransforms = (const MDL::BoneTransform_MDL7 *)(((const char *)frame.pcFrame) + pcHeader->frame_stc_size + + frame.pcFrame->vertices_count * pcHeader->framevertex_stc_size); // read all transformation matrices - for (unsigned int iTrafo = 0; iTrafo < frame.pcFrame->transmatrix_count;++iTrafo) { - if(pcBoneTransforms->bone_index >= pcHeader->bones_num) { + for (unsigned int iTrafo = 0; iTrafo < frame.pcFrame->transmatrix_count; ++iTrafo) { + if (pcBoneTransforms->bone_index >= pcHeader->bones_num) { ASSIMP_LOG_WARN("Index overflow in frame area. " - "Unable to parse this bone transformation"); - } - else { + "Unable to parse this bone transformation"); + } else { AddAnimationBoneTrafoKey_3DGS_MDL7(frame.iIndex, - pcBoneTransforms,shared.apcOutBones); + pcBoneTransforms, shared.apcOutBones); } - pcBoneTransforms = (const MDL::BoneTransform_MDL7*)( - (const char*)pcBoneTransforms + pcHeader->bonetrans_stc_size); + pcBoneTransforms = (const MDL::BoneTransform_MDL7 *)((const char *)pcBoneTransforms + pcHeader->bonetrans_stc_size); } - } - else { + } else { ASSIMP_LOG_WARN("Ignoring animation keyframes in groups != 0"); } } @@ -1709,79 +1663,79 @@ void MDLImporter::ParseBoneTrafoKeys_3DGS_MDL7( // ------------------------------------------------------------------------------------------------ // Attach bones to the output nodegraph -void MDLImporter::AddBonesToNodeGraph_3DGS_MDL7(const MDL::IntBone_MDL7** apcBones, - aiNode* pcParent,uint16_t iParentIndex) -{ +void MDLImporter::AddBonesToNodeGraph_3DGS_MDL7(const MDL::IntBone_MDL7 **apcBones, + aiNode *pcParent, uint16_t iParentIndex) { ai_assert(NULL != apcBones && NULL != pcParent); // get a pointer to the header ... - const MDL::Header_MDL7* const pcHeader = (const MDL::Header_MDL7*)this->mBuffer; + const MDL::Header_MDL7 *const pcHeader = (const MDL::Header_MDL7 *)this->mBuffer; - const MDL::IntBone_MDL7** apcBones2 = apcBones; - for (uint32_t i = 0; i < pcHeader->bones_num;++i) { + const MDL::IntBone_MDL7 **apcBones2 = apcBones; + for (uint32_t i = 0; i < pcHeader->bones_num; ++i) { - const MDL::IntBone_MDL7* const pcBone = *apcBones2++; + const MDL::IntBone_MDL7 *const pcBone = *apcBones2++; if (pcBone->iParent == iParentIndex) { ++pcParent->mNumChildren; } } - pcParent->mChildren = new aiNode*[pcParent->mNumChildren]; + pcParent->mChildren = new aiNode *[pcParent->mNumChildren]; unsigned int qq = 0; - for (uint32_t i = 0; i < pcHeader->bones_num;++i) { + for (uint32_t i = 0; i < pcHeader->bones_num; ++i) { - const MDL::IntBone_MDL7* const pcBone = *apcBones++; - if (pcBone->iParent != iParentIndex)continue; + const MDL::IntBone_MDL7 *const pcBone = *apcBones++; + if (pcBone->iParent != iParentIndex) continue; - aiNode* pcNode = pcParent->mChildren[qq++] = new aiNode(); - pcNode->mName = aiString( pcBone->mName ); + aiNode *pcNode = pcParent->mChildren[qq++] = new aiNode(); + pcNode->mName = aiString(pcBone->mName); - AddBonesToNodeGraph_3DGS_MDL7(apcBones,pcNode,(uint16_t)i); + AddBonesToNodeGraph_3DGS_MDL7(apcBones, pcNode, (uint16_t)i); } } // ------------------------------------------------------------------------------------------------ // Build output animations void MDLImporter::BuildOutputAnims_3DGS_MDL7( - const MDL::IntBone_MDL7** apcBonesOut) -{ + const MDL::IntBone_MDL7 **apcBonesOut) { ai_assert(NULL != apcBonesOut); - const MDL::Header_MDL7* const pcHeader = (const MDL::Header_MDL7*)mBuffer; + const MDL::Header_MDL7 *const pcHeader = (const MDL::Header_MDL7 *)mBuffer; // one animation ... - aiAnimation* pcAnim = new aiAnimation(); - for (uint32_t i = 0; i < pcHeader->bones_num;++i) { + aiAnimation *pcAnim = new aiAnimation(); + for (uint32_t i = 0; i < pcHeader->bones_num; ++i) { if (!apcBonesOut[i]->pkeyPositions.empty()) { // get the last frame ... (needn't be equal to pcHeader->frames_num) - for (size_t qq = 0; qq < apcBonesOut[i]->pkeyPositions.size();++qq) { + for (size_t qq = 0; qq < apcBonesOut[i]->pkeyPositions.size(); ++qq) { pcAnim->mDuration = std::max(pcAnim->mDuration, (double) - apcBonesOut[i]->pkeyPositions[qq].mTime); + apcBonesOut[i] + ->pkeyPositions[qq] + .mTime); } ++pcAnim->mNumChannels; } } - if (pcAnim->mDuration) { - pcAnim->mChannels = new aiNodeAnim*[pcAnim->mNumChannels]; + if (pcAnim->mDuration) { + pcAnim->mChannels = new aiNodeAnim *[pcAnim->mNumChannels]; unsigned int iCnt = 0; - for (uint32_t i = 0; i < pcHeader->bones_num;++i) { + for (uint32_t i = 0; i < pcHeader->bones_num; ++i) { if (!apcBonesOut[i]->pkeyPositions.empty()) { - const MDL::IntBone_MDL7* const intBone = apcBonesOut[i]; + const MDL::IntBone_MDL7 *const intBone = apcBonesOut[i]; - aiNodeAnim* const pcNodeAnim = pcAnim->mChannels[iCnt++] = new aiNodeAnim(); - pcNodeAnim->mNodeName = aiString( intBone->mName ); + aiNodeAnim *const pcNodeAnim = pcAnim->mChannels[iCnt++] = new aiNodeAnim(); + pcNodeAnim->mNodeName = aiString(intBone->mName); // allocate enough storage for all keys pcNodeAnim->mNumPositionKeys = (unsigned int)intBone->pkeyPositions.size(); - pcNodeAnim->mNumScalingKeys = (unsigned int)intBone->pkeyPositions.size(); + pcNodeAnim->mNumScalingKeys = (unsigned int)intBone->pkeyPositions.size(); pcNodeAnim->mNumRotationKeys = (unsigned int)intBone->pkeyPositions.size(); pcNodeAnim->mPositionKeys = new aiVectorKey[pcNodeAnim->mNumPositionKeys]; - pcNodeAnim->mScalingKeys = new aiVectorKey[pcNodeAnim->mNumPositionKeys]; + pcNodeAnim->mScalingKeys = new aiVectorKey[pcNodeAnim->mNumPositionKeys]; pcNodeAnim->mRotationKeys = new aiQuatKey[pcNodeAnim->mNumPositionKeys]; // copy all keys - for (unsigned int qq = 0; qq < pcNodeAnim->mNumPositionKeys;++qq) { + for (unsigned int qq = 0; qq < pcNodeAnim->mNumPositionKeys; ++qq) { pcNodeAnim->mPositionKeys[qq] = intBone->pkeyPositions[qq]; pcNodeAnim->mScalingKeys[qq] = intBone->pkeyScalings[qq]; pcNodeAnim->mRotationKeys[qq] = intBone->pkeyRotations[qq]; @@ -1791,17 +1745,16 @@ void MDLImporter::BuildOutputAnims_3DGS_MDL7( // store the output animation pScene->mNumAnimations = 1; - pScene->mAnimations = new aiAnimation*[1]; + pScene->mAnimations = new aiAnimation *[1]; pScene->mAnimations[0] = pcAnim; - } - else delete pcAnim; + } else + delete pcAnim; } // ------------------------------------------------------------------------------------------------ void MDLImporter::AddAnimationBoneTrafoKey_3DGS_MDL7(unsigned int iTrafo, - const MDL::BoneTransform_MDL7* pcBoneTransforms, - MDL::IntBone_MDL7** apcBonesOut) -{ + const MDL::BoneTransform_MDL7 *pcBoneTransforms, + MDL::IntBone_MDL7 **apcBonesOut) { ai_assert(NULL != pcBoneTransforms); ai_assert(NULL != apcBonesOut); @@ -1824,39 +1777,38 @@ void MDLImporter::AddAnimationBoneTrafoKey_3DGS_MDL7(unsigned int iTrafo, // now decompose the transformation matrix into separate // scaling, rotation and translation - aiVectorKey vScaling,vPosition; + aiVectorKey vScaling, vPosition; aiQuatKey qRotation; // FIXME: Decompose will assert in debug builds if the matrix is invalid ... - mTransform.Decompose(vScaling.mValue,qRotation.mValue,vPosition.mValue); + mTransform.Decompose(vScaling.mValue, qRotation.mValue, vPosition.mValue); // now generate keys vScaling.mTime = qRotation.mTime = vPosition.mTime = (double)iTrafo; // add the keys to the bone - MDL::IntBone_MDL7* const pcBoneOut = apcBonesOut[pcBoneTransforms->bone_index]; - pcBoneOut->pkeyPositions.push_back ( vPosition ); - pcBoneOut->pkeyScalings.push_back ( vScaling ); - pcBoneOut->pkeyRotations.push_back ( qRotation ); + MDL::IntBone_MDL7 *const pcBoneOut = apcBonesOut[pcBoneTransforms->bone_index]; + pcBoneOut->pkeyPositions.push_back(vPosition); + pcBoneOut->pkeyScalings.push_back(vScaling); + pcBoneOut->pkeyRotations.push_back(qRotation); } // ------------------------------------------------------------------------------------------------ // Construct output meshes void MDLImporter::GenerateOutputMeshes_3DGS_MDL7( - MDL::IntGroupData_MDL7& groupData, - MDL::IntSplitGroupData_MDL7& splitGroupData) -{ - const MDL::IntSharedData_MDL7& shared = splitGroupData.shared; + MDL::IntGroupData_MDL7 &groupData, + MDL::IntSplitGroupData_MDL7 &splitGroupData) { + const MDL::IntSharedData_MDL7 &shared = splitGroupData.shared; // get a pointer to the header ... - const MDL::Header_MDL7* const pcHeader = (const MDL::Header_MDL7*)this->mBuffer; + const MDL::Header_MDL7 *const pcHeader = (const MDL::Header_MDL7 *)this->mBuffer; const unsigned int iNumOutBones = pcHeader->bones_num; - for (std::vector::size_type i = 0; i < shared.pcMats.size();++i) { - if (!splitGroupData.aiSplit[i]->empty()) { + for (std::vector::size_type i = 0; i < shared.pcMats.size(); ++i) { + if (!splitGroupData.aiSplit[i]->empty()) { // allocate the output mesh - aiMesh* pcMesh = new aiMesh(); + aiMesh *pcMesh = new aiMesh(); pcMesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE; pcMesh->mMaterialIndex = (unsigned int)i; @@ -1865,7 +1817,7 @@ void MDLImporter::GenerateOutputMeshes_3DGS_MDL7( pcMesh->mNumFaces = (unsigned int)splitGroupData.aiSplit[i]->size(); pcMesh->mFaces = new aiFace[pcMesh->mNumFaces]; - pcMesh->mNumVertices = pcMesh->mNumFaces*3; + pcMesh->mNumVertices = pcMesh->mNumFaces * 3; pcMesh->mVertices = new aiVector3D[pcMesh->mNumVertices]; pcMesh->mNormals = new aiVector3D[pcMesh->mNumVertices]; @@ -1880,15 +1832,15 @@ void MDLImporter::GenerateOutputMeshes_3DGS_MDL7( // iterate through all faces and build an unique set of vertices unsigned int iCurrent = 0; - for (unsigned int iFace = 0; iFace < pcMesh->mNumFaces;++iFace) { + for (unsigned int iFace = 0; iFace < pcMesh->mNumFaces; ++iFace) { pcMesh->mFaces[iFace].mNumIndices = 3; pcMesh->mFaces[iFace].mIndices = new unsigned int[3]; unsigned int iSrcFace = splitGroupData.aiSplit[i]->operator[](iFace); - const MDL::IntFace_MDL7& oldFace = groupData.pcFaces[iSrcFace]; + const MDL::IntFace_MDL7 &oldFace = groupData.pcFaces[iSrcFace]; // iterate through all face indices - for (unsigned int c = 0; c < 3;++c) { + for (unsigned int c = 0; c < 3; ++c) { const uint32_t iIndex = oldFace.mIndices[c]; pcMesh->mVertices[iCurrent] = groupData.vPositions[iIndex]; pcMesh->mNormals[iCurrent] = groupData.vNormals[iIndex]; @@ -1907,51 +1859,50 @@ void MDLImporter::GenerateOutputMeshes_3DGS_MDL7( // if we have bones in the mesh we'll need to generate // proper vertex weights for them if (!groupData.aiBones.empty()) { - std::vector > aaiVWeightList; + std::vector> aaiVWeightList; aaiVWeightList.resize(iNumOutBones); - int iCurrent = 0; - for (unsigned int iFace = 0; iFace < pcMesh->mNumFaces;++iFace) { + int iCurrentWeight = 0; + for (unsigned int iFace = 0; iFace < pcMesh->mNumFaces; ++iFace) { unsigned int iSrcFace = splitGroupData.aiSplit[i]->operator[](iFace); - const MDL::IntFace_MDL7& oldFace = groupData.pcFaces[iSrcFace]; + const MDL::IntFace_MDL7 &oldFace = groupData.pcFaces[iSrcFace]; // iterate through all face indices - for (unsigned int c = 0; c < 3;++c) { - unsigned int iBone = groupData.aiBones[ oldFace.mIndices[c] ]; - if (UINT_MAX != iBone) { - if (iBone >= iNumOutBones) { + for (unsigned int c = 0; c < 3; ++c) { + unsigned int iBone = groupData.aiBones[oldFace.mIndices[c]]; + if (UINT_MAX != iBone) { + if (iBone >= iNumOutBones) { ASSIMP_LOG_ERROR("Bone index overflow. " - "The bone index of a vertex exceeds the allowed range. "); - iBone = iNumOutBones-1; + "The bone index of a vertex exceeds the allowed range. "); + iBone = iNumOutBones - 1; } - aaiVWeightList[ iBone ].push_back ( iCurrent ); + aaiVWeightList[iBone].push_back(iCurrentWeight); } - ++iCurrent; + ++iCurrentWeight; } } // now check which bones are required ... - for (std::vector >::const_iterator k = aaiVWeightList.begin();k != aaiVWeightList.end();++k) { + for (std::vector>::const_iterator k = aaiVWeightList.begin(); k != aaiVWeightList.end(); ++k) { if (!(*k).empty()) { ++pcMesh->mNumBones; } } - pcMesh->mBones = new aiBone*[pcMesh->mNumBones]; + pcMesh->mBones = new aiBone *[pcMesh->mNumBones]; iCurrent = 0; - for (std::vector >::const_iterator k = aaiVWeightList.begin();k!= aaiVWeightList.end();++k,++iCurrent) - { + for (std::vector>::const_iterator k = aaiVWeightList.begin(); k != aaiVWeightList.end(); ++k, ++iCurrent) { if ((*k).empty()) continue; // seems we'll need this node - aiBone* pcBone = pcMesh->mBones[ iCurrent ] = new aiBone(); - pcBone->mName = aiString(shared.apcOutBones[ iCurrent ]->mName); - pcBone->mOffsetMatrix = shared.apcOutBones[ iCurrent ]->mOffsetMatrix; + aiBone *pcBone = pcMesh->mBones[iCurrent] = new aiBone(); + pcBone->mName = aiString(shared.apcOutBones[iCurrent]->mName); + pcBone->mOffsetMatrix = shared.apcOutBones[iCurrent]->mOffsetMatrix; // setup vertex weights pcBone->mNumWeights = (unsigned int)(*k).size(); pcBone->mWeights = new aiVertexWeight[pcBone->mNumWeights]; - for (unsigned int weight = 0; weight < pcBone->mNumWeights;++weight) { + for (unsigned int weight = 0; weight < pcBone->mNumWeights; ++weight) { pcBone->mWeights[weight].mVertexId = (*k)[weight]; pcBone->mWeights[weight].mWeight = 1.0f; } @@ -1966,50 +1917,47 @@ void MDLImporter::GenerateOutputMeshes_3DGS_MDL7( // ------------------------------------------------------------------------------------------------ // Join to materials void MDLImporter::JoinSkins_3DGS_MDL7( - aiMaterial* pcMat1, - aiMaterial* pcMat2, - aiMaterial* pcMatOut) -{ + aiMaterial *pcMat1, + aiMaterial *pcMat2, + aiMaterial *pcMatOut) { ai_assert(NULL != pcMat1 && NULL != pcMat2 && NULL != pcMatOut); // first create a full copy of the first skin property set // and assign it to the output material - aiMaterial::CopyPropertyList(pcMatOut,pcMat1); + aiMaterial::CopyPropertyList(pcMatOut, pcMat1); int iVal = 0; - pcMatOut->AddProperty(&iVal,1,AI_MATKEY_UVWSRC_DIFFUSE(0)); + pcMatOut->AddProperty(&iVal, 1, AI_MATKEY_UVWSRC_DIFFUSE(0)); // then extract the diffuse texture from the second skin, // setup 1 as UV source and we have it aiString sString; - if(AI_SUCCESS == aiGetMaterialString ( pcMat2, AI_MATKEY_TEXTURE_DIFFUSE(0),&sString )) { + if (AI_SUCCESS == aiGetMaterialString(pcMat2, AI_MATKEY_TEXTURE_DIFFUSE(0), &sString)) { iVal = 1; - pcMatOut->AddProperty(&iVal,1,AI_MATKEY_UVWSRC_DIFFUSE(1)); - pcMatOut->AddProperty(&sString,AI_MATKEY_TEXTURE_DIFFUSE(1)); + pcMatOut->AddProperty(&iVal, 1, AI_MATKEY_UVWSRC_DIFFUSE(1)); + pcMatOut->AddProperty(&sString, AI_MATKEY_TEXTURE_DIFFUSE(1)); } } // ------------------------------------------------------------------------------------------------ // Read a Half-life 1 MDL -void MDLImporter::InternReadFile_HL1(const std::string& pFile, const uint32_t iMagicWord) -{ +void MDLImporter::InternReadFile_HL1(const std::string &pFile, const uint32_t iMagicWord) { // We can't correctly load an MDL from a MDL "sequence" file. if (iMagicWord == AI_MDL_MAGIC_NUMBER_BE_HL2b || iMagicWord == AI_MDL_MAGIC_NUMBER_LE_HL2b) throw DeadlyImportError("Impossible to properly load a model from an MDL sequence file."); // Read the MDL file. HalfLife::HL1MDLLoader loader( - pScene, - pIOHandler, - mBuffer, - pFile, - mHL1ImportSettings); + pScene, + mIOHandler, + mBuffer, + pFile, + mHL1ImportSettings); } // ------------------------------------------------------------------------------------------------ // Read a half-life 2 MDL -void MDLImporter::InternReadFile_HL2( ) -{ +void MDLImporter::InternReadFile_HL2() { //const MDL::Header_HL2* pcHeader = (const MDL::Header_HL2*)this->mBuffer; throw DeadlyImportError("HL2 MDLs are not implemented"); } diff --git a/code/MDL/MDLLoader.h b/code/MDL/MDLLoader.h index 0bb78a2b1..635b84316 100644 --- a/code/MDL/MDLLoader.h +++ b/code/MDL/MDLLoader.h @@ -4,7 +4,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2020, assimp team - All rights reserved. Redistribution and use of this software in source and binary forms, @@ -58,7 +57,6 @@ struct aiTexture; namespace Assimp { - using namespace MDL; // -------------------------------------------------------------------------------------- @@ -436,7 +434,7 @@ protected: unsigned int iGSFileVersion; /** Output I/O handler. used to load external lmp files */ - IOSystem* pIOHandler; + IOSystem* mIOHandler; /** Output scene to be filled */ aiScene* pScene; diff --git a/code/Material/MaterialSystem.cpp b/code/Material/MaterialSystem.cpp index 63fad4268..0435f029e 100644 --- a/code/Material/MaterialSystem.cpp +++ b/code/Material/MaterialSystem.cpp @@ -561,7 +561,8 @@ uint32_t Assimp::ComputeMaterialHash(const aiMaterial* mat, bool includeMatName // Exclude all properties whose first character is '?' from the hash // See doc for aiMaterialProperty. - if ((prop = mat->mProperties[i]) && (includeMatName || prop->mKey.data[0] != '?')) { + prop = mat->mProperties[ i ]; + if ( nullptr != prop && (includeMatName || prop->mKey.data[0] != '?')) { hash = SuperFastHash(prop->mKey.data,(unsigned int)prop->mKey.length,hash); hash = SuperFastHash(prop->mData,prop->mDataLength,hash); diff --git a/code/PostProcessing/SplitLargeMeshes.cpp b/code/PostProcessing/SplitLargeMeshes.cpp index 70960f4a8..d74a335ad 100644 --- a/code/PostProcessing/SplitLargeMeshes.cpp +++ b/code/PostProcessing/SplitLargeMeshes.cpp @@ -575,8 +575,9 @@ void SplitLargeMeshesProcess_Vertex::SplitMesh( for (unsigned int k = 0; k < pMesh->mNumBones;++k) { // check whether the bone is existing BoneWeightList* pcWeightList; - if ((pcWeightList = (BoneWeightList*)pcMesh->mBones[k])) { - aiBone* pcOldBone = pMesh->mBones[k]; + pcWeightList = (BoneWeightList *)pcMesh->mBones[k]; + if (nullptr != pcWeightList) { + aiBone *pcOldBone = pMesh->mBones[k]; aiBone* pcOut( nullptr ); *ppCurrent++ = pcOut = new aiBone(); pcOut->mName = aiString(pcOldBone->mName); diff --git a/code/PostProcessing/TextureTransform.cpp b/code/PostProcessing/TextureTransform.cpp index cebbd8042..f979f0f4d 100644 --- a/code/PostProcessing/TextureTransform.cpp +++ b/code/PostProcessing/TextureTransform.cpp @@ -125,7 +125,8 @@ void TextureTransformStep::PreProcessUVTransform(STransformVecInfo& info) * type (e.g. if mirroring is active there IS a difference between * offset 2 and 3) */ - if ((rounded = (int)info.mTranslation.x)) { + rounded = (int)info.mTranslation.x; + if (rounded) { float out = 0.0f; szTemp[0] = 0; if (aiTextureMapMode_Wrap == info.mapU) { @@ -158,7 +159,8 @@ void TextureTransformStep::PreProcessUVTransform(STransformVecInfo& info) * type (e.g. if mirroring is active there IS a difference between * offset 2 and 3) */ - if ((rounded = (int)info.mTranslation.y)) { + rounded = (int)info.mTranslation.y; + if (rounded) { float out = 0.0f; szTemp[0] = 0; if (aiTextureMapMode_Wrap == info.mapV) { From a65bac27e9ee0dca6c4178f5134b1bb10ce7ef91 Mon Sep 17 00:00:00 2001 From: iamAdrianIusca Date: Tue, 18 Feb 2020 18:01:53 +0200 Subject: [PATCH 063/330] fixed the make_unique --- code/Obj/ObjFileParser.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/Obj/ObjFileParser.cpp b/code/Obj/ObjFileParser.cpp index 8b1572067..bfddb8461 100644 --- a/code/Obj/ObjFileParser.cpp +++ b/code/Obj/ObjFileParser.cpp @@ -85,7 +85,7 @@ ObjFileParser::ObjFileParser( IOStreamBuffer &streamBuffer, const std::str std::fill_n(m_buffer, Buffersize,0); // Create the model instance to store all the data - m_pModel = std::make_unique(); + m_pModel.reset(new ObjFile::Model()); m_pModel->m_ModelName = modelName; // create default material and store it From d0922230a93c2a9bac8676cf7f2f7d96f8aa6deb Mon Sep 17 00:00:00 2001 From: iamAdrianIusca Date: Tue, 18 Feb 2020 18:24:52 +0200 Subject: [PATCH 064/330] fixed the = default on the destructor --- code/Obj/ObjFileParser.cpp | 4 ++++ code/Obj/ObjFileParser.h | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/code/Obj/ObjFileParser.cpp b/code/Obj/ObjFileParser.cpp index bfddb8461..7ba2216ae 100644 --- a/code/Obj/ObjFileParser.cpp +++ b/code/Obj/ObjFileParser.cpp @@ -98,6 +98,10 @@ ObjFileParser::ObjFileParser( IOStreamBuffer &streamBuffer, const std::str parseFile( streamBuffer ); } +ObjFileParser::~ObjFileParser() +{ +} + void ObjFileParser::setBuffer( std::vector &buffer ) { m_DataIt = buffer.begin(); m_DataItEnd = buffer.end(); diff --git a/code/Obj/ObjFileParser.h b/code/Obj/ObjFileParser.h index 9bbee66dd..f0f5a2dc1 100644 --- a/code/Obj/ObjFileParser.h +++ b/code/Obj/ObjFileParser.h @@ -80,7 +80,7 @@ public: /// @brief Constructor with data array. ObjFileParser(IOStreamBuffer &streamBuffer, const std::string &modelName, IOSystem* io, ProgressHandler* progress, std::string originalObjFileName); /// @brief Destructor - ~ObjFileParser() = default; + ~ObjFileParser(); /// @brief If you want to load in-core data. void setBuffer( std::vector &buffer ); /// @brief Model getter. From 016c0a866557b7a22e6d47c9c89cc13939f121ce Mon Sep 17 00:00:00 2001 From: iamAdrianIusca Date: Tue, 18 Feb 2020 18:42:59 +0200 Subject: [PATCH 065/330] small changes --- code/Common/BaseImporter.cpp | 7 +++---- code/Common/Importer.cpp | 8 ++++---- include/assimp/Importer.hpp | 4 ++-- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/code/Common/BaseImporter.cpp b/code/Common/BaseImporter.cpp index 660a6a965..8d7b029ba 100644 --- a/code/Common/BaseImporter.cpp +++ b/code/Common/BaseImporter.cpp @@ -191,7 +191,7 @@ void BaseImporter::GetExtensionList(std::set& extensions) { } std::unique_ptr pStream (pIOHandler->Open(pFile)); - if (pStream.get() ) { + if (pStream) { // read 200 characters from the file std::unique_ptr _buffer (new char[searchBytes+1 /* for the '\0' */]); char *buffer( _buffer.get() ); @@ -283,7 +283,6 @@ std::string BaseImporter::GetExtension( const std::string& file ) { return ""; } - // thanks to Andy Maloney for the hint std::string ret = file.substr( pos + 1 ); std::transform( ret.begin(), ret.end(), ret.begin(), ToLower); @@ -309,7 +308,7 @@ std::string BaseImporter::GetExtension( const std::string& file ) { }; magic = reinterpret_cast(_magic); std::unique_ptr pStream (pIOHandler->Open(pFile)); - if (pStream.get() ) { + if (pStream) { // skip to offset pStream->Seek(offset,aiOrigin_SET); @@ -603,7 +602,7 @@ unsigned int BatchLoader::AddLoadRequest(const std::string& file, } // no, we don't have it. So add it to the queue ... - m_data->requests.push_back(LoadRequest(file,steps,map, m_data->next_id)); + m_data->requests.emplace_back(file, steps, map, m_data->next_id); return m_data->next_id++; } diff --git a/code/Common/Importer.cpp b/code/Common/Importer.cpp index 5601298f1..a59ec9812 100644 --- a/code/Common/Importer.cpp +++ b/code/Common/Importer.cpp @@ -1071,7 +1071,7 @@ ai_real Importer::GetPropertyFloat(const char* szName, ai_real iErrorReturn /*= // ------------------------------------------------------------------------------------------------ // Get a configuration property -const std::string Importer::GetPropertyString(const char* szName, const std::string& iErrorReturn /*= ""*/) const { +std::string Importer::GetPropertyString(const char* szName, const std::string& iErrorReturn /*= ""*/) const { ai_assert(nullptr != pimpl); return GetGenericProperty(pimpl->mStringProperties,szName,iErrorReturn); @@ -1079,7 +1079,7 @@ const std::string Importer::GetPropertyString(const char* szName, const std::str // ------------------------------------------------------------------------------------------------ // Get a configuration property -const aiMatrix4x4 Importer::GetPropertyMatrix(const char* szName, const aiMatrix4x4& iErrorReturn /*= aiMatrix4x4()*/) const { +aiMatrix4x4 Importer::GetPropertyMatrix(const char* szName, const aiMatrix4x4& iErrorReturn /*= aiMatrix4x4()*/) const { ai_assert(nullptr != pimpl); return GetGenericProperty(pimpl->mMatrixProperties,szName,iErrorReturn); @@ -1110,10 +1110,9 @@ void Importer::GetMemoryRequirements(aiMemoryInfo& in) const { aiScene* mScene = pimpl->mScene; // return if we have no scene loaded - if (!pimpl->mScene) + if (!mScene) return; - in.total = sizeof(aiScene); // add all meshes @@ -1202,5 +1201,6 @@ void Importer::GetMemoryRequirements(aiMemoryInfo& in) const { in.materials += pc->mProperties[a]->mDataLength; } } + in.total += in.materials; } diff --git a/include/assimp/Importer.hpp b/include/assimp/Importer.hpp index 7ec4f519c..df52471a9 100644 --- a/include/assimp/Importer.hpp +++ b/include/assimp/Importer.hpp @@ -285,7 +285,7 @@ public: * The return value remains valid until the property is modified. * @see GetPropertyInteger() */ - const std::string GetPropertyString(const char* szName, + std::string GetPropertyString(const char* szName, const std::string& sErrorReturn = "") const; // ------------------------------------------------------------------- @@ -294,7 +294,7 @@ public: * The return value remains valid until the property is modified. * @see GetPropertyInteger() */ - const aiMatrix4x4 GetPropertyMatrix(const char* szName, + aiMatrix4x4 GetPropertyMatrix(const char* szName, const aiMatrix4x4& sErrorReturn = aiMatrix4x4()) const; // ------------------------------------------------------------------- From bf85fc1386fa06c184be5874d0a54cb11828347e Mon Sep 17 00:00:00 2001 From: iamAdrianIusca Date: Tue, 18 Feb 2020 18:50:48 +0200 Subject: [PATCH 066/330] small changes --- code/Obj/ObjFileData.h | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/code/Obj/ObjFileData.h b/code/Obj/ObjFileData.h index 985a49a42..d0ea8d507 100644 --- a/code/Obj/ObjFileData.h +++ b/code/Obj/ObjFileData.h @@ -110,10 +110,7 @@ struct Object { std::vector m_Meshes; //! \brief Default constructor - Object() - : m_strObjName("") { - // empty - } + Object() = default; //! \brief Destructor ~Object() { @@ -191,16 +188,12 @@ struct Material { , illumination_model (1) , ior ( ai_real( 1.0 ) ) , transparent( ai_real( 1.0), ai_real (1.0), ai_real(1.0)) { - // empty - for (size_t i = 0; i < TextureTypeCount; ++i) { - clamp[ i ] = false; - } + + std::fill_n(clamp, TextureTypeCount,false); } // Destructor - ~Material() { - // empty - } + ~Material() = default; }; // ------------------------------------------------------------------------------------------------ From ad52c5c5f6ac771124c3bd3585f24daa61fbbdbd Mon Sep 17 00:00:00 2001 From: iamAdrianIusca Date: Tue, 18 Feb 2020 18:56:09 +0200 Subject: [PATCH 067/330] .clear in destructor is redundant --- code/Common/ZipArchiveIOSystem.cpp | 2 -- code/Obj/ObjFileData.h | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/code/Common/ZipArchiveIOSystem.cpp b/code/Common/ZipArchiveIOSystem.cpp index e83d3e50d..8d00da912 100644 --- a/code/Common/ZipArchiveIOSystem.cpp +++ b/code/Common/ZipArchiveIOSystem.cpp @@ -343,8 +343,6 @@ namespace Assimp { } ZipArchiveIOSystem::Implement::~Implement() { - m_ArchiveMap.clear(); - if (m_ZipFileHandle != nullptr) { unzClose(m_ZipFileHandle); m_ZipFileHandle = nullptr; diff --git a/code/Obj/ObjFileData.h b/code/Obj/ObjFileData.h index d0ea8d507..33184ce82 100644 --- a/code/Obj/ObjFileData.h +++ b/code/Obj/ObjFileData.h @@ -189,7 +189,7 @@ struct Material { , ior ( ai_real( 1.0 ) ) , transparent( ai_real( 1.0), ai_real (1.0), ai_real(1.0)) { - std::fill_n(clamp, TextureTypeCount,false); + std::fill_n(clamp, TextureTypeCount, false); } // Destructor From a5524ffcd9befe3f008e27d65b6de620b897c49c Mon Sep 17 00:00:00 2001 From: iamAdrianIusca Date: Tue, 18 Feb 2020 19:02:14 +0200 Subject: [PATCH 068/330] more changes --- code/PostProcessing/TextureTransform.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/code/PostProcessing/TextureTransform.cpp b/code/PostProcessing/TextureTransform.cpp index cebbd8042..bf60e2970 100644 --- a/code/PostProcessing/TextureTransform.cpp +++ b/code/PostProcessing/TextureTransform.cpp @@ -92,9 +92,8 @@ void TextureTransformStep::PreProcessUVTransform(STransformVecInfo& info) * are applied is - as always - scaling, rotation, translation. */ - char szTemp[512]; - int rounded = 0; - + int rounded; + char szTemp[512]; /* Optimize the rotation angle. That's slightly difficult as * we have an inprecise floating-point number (when comparing @@ -185,7 +184,6 @@ void TextureTransformStep::PreProcessUVTransform(STransformVecInfo& info) info.mTranslation.y = out; } } - return; } // ------------------------------------------------------------------------------------------------ @@ -428,7 +426,7 @@ void TextureTransformStep::Execute( aiScene* pScene) // at the end of the list bool ref[AI_MAX_NUMBER_OF_TEXTURECOORDS]; for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_TEXTURECOORDS;++n) - ref[n] = (!mesh->mTextureCoords[n] ? true : false); + ref[n] = !mesh->mTextureCoords[n]; for (it = trafo.begin();it != trafo.end(); ++it) ref[(*it).uvIndex] = true; From 4de0237167dd8019838cb28a5622bba522f74842 Mon Sep 17 00:00:00 2001 From: iamAdrianIusca Date: Tue, 18 Feb 2020 21:55:35 +0200 Subject: [PATCH 069/330] small fix --- code/Obj/ObjFileData.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/Obj/ObjFileData.h b/code/Obj/ObjFileData.h index 33184ce82..298d1e1b7 100644 --- a/code/Obj/ObjFileData.h +++ b/code/Obj/ObjFileData.h @@ -189,7 +189,7 @@ struct Material { , ior ( ai_real( 1.0 ) ) , transparent( ai_real( 1.0), ai_real (1.0), ai_real(1.0)) { - std::fill_n(clamp, TextureTypeCount, false); + std::fill_n(clamp, static_cast(TextureTypeCount), false); } // Destructor From 8d6d8e2e3820c89fc6a2ff9758795c00e9aa0f77 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Wed, 19 Feb 2020 10:42:30 +0100 Subject: [PATCH 070/330] Update .clang-format Update clang.format to keep formatting of hashes in include file to optimize readabilaty. --- .clang-format | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.clang-format b/.clang-format index 70e0945fe..c8b8ab856 100644 --- a/.clang-format +++ b/.clang-format @@ -71,7 +71,7 @@ IncludeCategories: Priority: 3 # IncludeIsMainRegex: '(Test)?$' IndentCaseLabels: true -# IndentPPDirectives: None +IndentPPDirectives: AfterHash IndentWidth: 4 # IndentWrappedFunctionNames: false # JavaScriptQuotes: Leave From 4d27fccd0bec68a5d2525a740b1ab1eb34d0be1a Mon Sep 17 00:00:00 2001 From: Marc-Antoine Lortie Date: Wed, 19 Feb 2020 13:17:45 -0500 Subject: [PATCH 071/330] Fixed memory leaks in SimpleTexturedOpenGL sample. - Added function "cleanup" to centralize release of resources. - Added function "freeTextureIds" to free textureIds memory. - Added call to freeTextureIds in LoadGLTextures to free memory before it is allocated again. - Made several changes in KillGLWindow to prevent certain Win32 handle/resources from being released more than once. --- .../src/model_loading.cpp | 64 ++++++++++++------- 1 file changed, 42 insertions(+), 22 deletions(-) diff --git a/samples/SimpleTexturedOpenGL/SimpleTexturedOpenGL/src/model_loading.cpp b/samples/SimpleTexturedOpenGL/SimpleTexturedOpenGL/src/model_loading.cpp index 8428248d1..8c2a08b2e 100644 --- a/samples/SimpleTexturedOpenGL/SimpleTexturedOpenGL/src/model_loading.cpp +++ b/samples/SimpleTexturedOpenGL/SimpleTexturedOpenGL/src/model_loading.cpp @@ -202,8 +202,21 @@ std::string getBasePath(const std::string& path) return (std::string::npos == pos) ? "" : path.substr(0, pos + 1); } +void freeTextureIds() +{ + textureIdMap.clear(); //no need to delete pointers in it manually here. (Pointers point to textureIds deleted in next step) + + if (textureIds) + { + delete[] textureIds; + textureIds = NULL; + } +} + int LoadGLTextures(const aiScene* scene) { + freeTextureIds(); + //ILboolean success; /* Before calling ilInit() version should be checked. */ @@ -576,21 +589,24 @@ void KillGLWindow() // Properly Kill The Window hRC = NULL; } - if (hDC && !ReleaseDC(hWnd, hDC)) // Are We able to Release The DC? + if (hDC) { - MessageBox(NULL, TEXT("Release Device Context Failed."), TEXT("SHUTDOWN ERROR"), MB_OK | MB_ICONINFORMATION); - hDC=NULL; + if (!ReleaseDC(hWnd, hDC)) // Are We able to Release The DC? + MessageBox(NULL, TEXT("Release Device Context Failed."), TEXT("SHUTDOWN ERROR"), MB_OK | MB_ICONINFORMATION); + hDC = NULL; } - if (hWnd && !DestroyWindow(hWnd)) // Are We Able To Destroy The Window + if (hWnd) { - MessageBox(NULL, TEXT("Could Not Release hWnd."), TEXT("SHUTDOWN ERROR"), MB_OK | MB_ICONINFORMATION); + if (!DestroyWindow(hWnd)) // Are We Able To Destroy The Window + MessageBox(NULL, TEXT("Could Not Release hWnd."), TEXT("SHUTDOWN ERROR"), MB_OK | MB_ICONINFORMATION); hWnd = NULL; - } + } - if (!UnregisterClass(TEXT("OpenGL"), hInstance)) // Are We Able To Unregister Class + if (hInstance) { - MessageBox(NULL, TEXT("Could Not Unregister Class."), TEXT("SHUTDOWN ERROR"), MB_OK | MB_ICONINFORMATION); + if (!UnregisterClass(TEXT("OpenGL"), hInstance)) // Are We Able To Unregister Class + MessageBox(NULL, TEXT("Could Not Unregister Class."), TEXT("SHUTDOWN ERROR"), MB_OK | MB_ICONINFORMATION); hInstance = NULL; } } @@ -761,6 +777,16 @@ BOOL CreateGLWindow(const char* title, int width, int height, int bits, bool ful return TRUE; } +void cleanup() +{ + freeTextureIds(); + + destroyAILogger(); + + if (hWnd) + KillGLWindow(); +}; + LRESULT CALLBACK WndProc(HWND hWnd, // Handles for this Window UINT uMsg, // Message for this Window WPARAM wParam, // additional message Info @@ -842,7 +868,11 @@ int WINAPI WinMain( HINSTANCE hInstance, // The instance modelpath = UTFConverter(modelpathW).str(); } - if (!Import3DFromFile(modelpath)) return 0; + if (!Import3DFromFile(modelpath)) + { + cleanup(); + return 0; + } logInfo("=============== Post Import ===================="); @@ -853,6 +883,7 @@ int WINAPI WinMain( HINSTANCE hInstance, // The instance if (!CreateGLWindow(windowTitle, 640, 480, 16, fullscreen)) { + cleanup(); return 0; } @@ -893,6 +924,7 @@ int WINAPI WinMain( HINSTANCE hInstance, // The instance fullscreen=!fullscreen; if (!CreateGLWindow(windowTitle, 640, 480, 16, fullscreen)) { + cleanup(); return 0; } } @@ -900,18 +932,6 @@ int WINAPI WinMain( HINSTANCE hInstance, // The instance } // *** cleanup *** - - textureIdMap.clear(); //no need to delete pointers in it manually here. (Pointers point to textureIds deleted in next step) - - if (textureIds) - { - delete[] textureIds; - textureIds = NULL; - } - - // *** cleanup end *** - - destroyAILogger(); - KillGLWindow(); + cleanup(); return static_cast(msg.wParam); } From f28b087d163e0f027e027e6d634d4e42d55b727d Mon Sep 17 00:00:00 2001 From: iamAdrianIusca Date: Fri, 21 Feb 2020 20:17:38 +0200 Subject: [PATCH 072/330] small improvements in the CMakeLists.txt file If ASSIMP_NO_EXPORT is not defined: - don't add the macro for the exporters - don't include the files for all the exporter - don't display any messages about what exporters are enabled or not --- code/CMakeLists.txt | 232 +++++++++++++++++++++----------------------- 1 file changed, 113 insertions(+), 119 deletions(-) diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index 91f099c02..1d4586494 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -252,35 +252,39 @@ MACRO(ADD_ASSIMP_IMPORTER name) ENDIF() ENDMACRO() -# if this variable is set to TRUE, the user can manually disable exporters by setting -# ASSIMP_BUILD_XXX_EXPORTER to FALSE for each exporter -# if this variable is set to FALSE, the user can manually enable exporters by setting -# ASSIMP_BUILD_XXX_EXPORTER to TRUE for each exporter -OPTION(ASSIMP_BUILD_ALL_EXPORTERS_BY_DEFAULT "default value of all ASSIMP_BUILD_XXX_EXPORTER values" TRUE) +if (NOT ASSIMP_NO_EXPORT) -# macro to add the CMake Option ADD_ASSIMP_IMPORTER_ which enables compile of loader -# this way selective loaders can be compiled (reduces filesize + compile time) -MACRO(ADD_ASSIMP_EXPORTER name) - IF (ASSIMP_NO_EXPORT) - set(ASSIMP_EXPORTER_ENABLED FALSE) - ELSEIF (ASSIMP_BUILD_ALL_EXPORTERS_BY_DEFAULT) - set(ASSIMP_EXPORTER_ENABLED TRUE) - IF (DEFINED ASSIMP_BUILD_${name}_EXPORTER AND NOT ASSIMP_BUILD_${name}_EXPORTER) + # if this variable is set to TRUE, the user can manually disable exporters by setting + # ASSIMP_BUILD_XXX_EXPORTER to FALSE for each exporter + # if this variable is set to FALSE, the user can manually enable exporters by setting + # ASSIMP_BUILD_XXX_EXPORTER to TRUE for each exporter + OPTION(ASSIMP_BUILD_ALL_EXPORTERS_BY_DEFAULT "default value of all ASSIMP_BUILD_XXX_EXPORTER values" TRUE) + + # macro to add the CMake Option ADD_ASSIMP_IMPORTER_ which enables compile of loader + # this way selective loaders can be compiled (reduces filesize + compile time) + MACRO(ADD_ASSIMP_EXPORTER name) + IF (ASSIMP_NO_EXPORT) set(ASSIMP_EXPORTER_ENABLED FALSE) + ELSEIF (ASSIMP_BUILD_ALL_EXPORTERS_BY_DEFAULT) + set(ASSIMP_EXPORTER_ENABLED TRUE) + IF (DEFINED ASSIMP_BUILD_${name}_EXPORTER AND NOT ASSIMP_BUILD_${name}_EXPORTER) + set(ASSIMP_EXPORTER_ENABLED FALSE) + ENDIF () + ELSE () + set(ASSIMP_EXPORTER_ENABLED ${ASSIMP_BUILD_${name}_EXPORTER}) ENDIF () - ELSE () - set(ASSIMP_EXPORTER_ENABLED ${ASSIMP_BUILD_${name}_EXPORTER}) - ENDIF () - IF (ASSIMP_EXPORTER_ENABLED) - SET(ASSIMP_EXPORTERS_ENABLED "${ASSIMP_EXPORTERS_ENABLED} ${name}") - LIST(APPEND ASSIMP_EXPORTER_SRCS ${ARGN}) - SOURCE_GROUP(${name}_EXPORTER FILES ${ARGN}) - ELSE() - SET(ASSIMP_EXPORTERS_DISABLED "${ASSIMP_EXPORTERS_DISABLED} ${name}") - add_definitions(-DASSIMP_BUILD_NO_${name}_EXPORTER) - ENDIF() -ENDMACRO() + IF (ASSIMP_EXPORTER_ENABLED) + SET(ASSIMP_EXPORTERS_ENABLED "${ASSIMP_EXPORTERS_ENABLED} ${name}") + LIST(APPEND ASSIMP_EXPORTER_SRCS ${ARGN}) + SOURCE_GROUP(${name}_EXPORTER FILES ${ARGN}) + ELSE() + SET(ASSIMP_EXPORTERS_DISABLED "${ASSIMP_EXPORTERS_DISABLED} ${name}") + add_definitions(-DASSIMP_BUILD_NO_${name}_EXPORTER) + ENDIF() + ENDMACRO() + +endif() SET(ASSIMP_LOADER_SRCS "") SET(ASSIMP_IMPORTERS_ENABLED "") # list of enabled importers @@ -307,11 +311,6 @@ ADD_ASSIMP_IMPORTER( 3DS 3DS/3DSLoader.h ) -ADD_ASSIMP_EXPORTER( 3DS - 3DS/3DSExporter.h - 3DS/3DSExporter.cpp -) - ADD_ASSIMP_IMPORTER( AC AC/ACLoader.cpp AC/ACLoader.h @@ -329,20 +328,6 @@ ADD_ASSIMP_IMPORTER( ASSBIN Assbin/AssbinLoader.cpp ) -ADD_ASSIMP_EXPORTER( ASSBIN - Assbin/AssbinExporter.h - Assbin/AssbinExporter.cpp - Assbin/AssbinFileWriter.h - Assbin/AssbinFileWriter.cpp -) - -ADD_ASSIMP_EXPORTER( ASSXML - Assxml/AssxmlExporter.h - Assxml/AssxmlExporter.cpp - Assxml/AssxmlFileWriter.h - Assxml/AssxmlFileWriter.cpp -) - ADD_ASSIMP_IMPORTER( B3D B3D/B3DImporter.cpp B3D/B3DImporter.h @@ -362,11 +347,6 @@ ADD_ASSIMP_IMPORTER( COLLADA Collada/ColladaParser.h ) -ADD_ASSIMP_EXPORTER( COLLADA - Collada/ColladaExporter.h - Collada/ColladaExporter.cpp -) - ADD_ASSIMP_IMPORTER( DXF DXF/DXFLoader.cpp DXF/DXFLoader.h @@ -423,11 +403,6 @@ ADD_ASSIMP_IMPORTER( M3D M3D/m3d.h ) -ADD_ASSIMP_EXPORTER( M3D - M3D/M3DExporter.h - M3D/M3DExporter.cpp -) - ADD_ASSIMP_IMPORTER( MD2 MD2/MD2FileData.h MD2/MD2Loader.cpp @@ -505,11 +480,6 @@ ADD_ASSIMP_IMPORTER( OBJ Obj/ObjTools.h ) -ADD_ASSIMP_EXPORTER( OBJ - Obj/ObjExporter.h - Obj/ObjExporter.cpp -) - ADD_ASSIMP_IMPORTER( OGRE Ogre/OgreImporter.h Ogre/OgreStructs.h @@ -529,11 +499,6 @@ ADD_ASSIMP_IMPORTER( OPENGEX OpenGEX/OpenGEXStructs.h ) -ADD_ASSIMP_EXPORTER( OPENGEX - OpenGEX/OpenGEXExporter.cpp - OpenGEX/OpenGEXExporter.h -) - ADD_ASSIMP_IMPORTER( PLY Ply/PlyLoader.cpp Ply/PlyLoader.h @@ -541,11 +506,6 @@ ADD_ASSIMP_IMPORTER( PLY Ply/PlyParser.h ) -ADD_ASSIMP_EXPORTER( PLY - Ply/PlyExporter.cpp - Ply/PlyExporter.h -) - ADD_ASSIMP_IMPORTER( MS3D MS3D/MS3DLoader.cpp MS3D/MS3DLoader.h @@ -635,14 +595,86 @@ ADD_ASSIMP_IMPORTER( FBX FBX/FBXCommon.h ) -ADD_ASSIMP_EXPORTER( FBX - FBX/FBXExporter.h - FBX/FBXExporter.cpp - FBX/FBXExportNode.h - FBX/FBXExportNode.cpp - FBX/FBXExportProperty.h - FBX/FBXExportProperty.cpp -) +if (NOT ASSIMP_NO_EXPORT) + + ADD_ASSIMP_EXPORTER( OBJ + Obj/ObjExporter.h + Obj/ObjExporter.cpp) + + ADD_ASSIMP_EXPORTER( OPENGEX + OpenGEX/OpenGEXExporter.cpp + OpenGEX/OpenGEXExporter.h) + + ADD_ASSIMP_EXPORTER( PLY + Ply/PlyExporter.cpp + Ply/PlyExporter.h) + + ADD_ASSIMP_EXPORTER( 3DS + 3DS/3DSExporter.h + 3DS/3DSExporter.cpp) + + ADD_ASSIMP_EXPORTER( ASSBIN + Assbin/AssbinExporter.h + Assbin/AssbinExporter.cpp + Assbin/AssbinFileWriter.h + Assbin/AssbinFileWriter.cpp) + + ADD_ASSIMP_EXPORTER( ASSXML + Assxml/AssxmlExporter.h + Assxml/AssxmlExporter.cpp + Assxml/AssxmlFileWriter.h + Assxml/AssxmlFileWriter.cpp) + + ADD_ASSIMP_EXPORTER(M3D + M3D/M3DExporter.h + M3D/M3DExporter.cpp) + + ADD_ASSIMP_EXPORTER(COLLADA + Collada/ColladaExporter.h + Collada/ColladaExporter.cpp) + + ADD_ASSIMP_EXPORTER( FBX + FBX/FBXExporter.h + FBX/FBXExporter.cpp + FBX/FBXExportNode.h + FBX/FBXExportNode.cpp + FBX/FBXExportProperty.h + FBX/FBXExportProperty.cpp) + + ADD_ASSIMP_EXPORTER( STL + STL/STLExporter.h + STL/STLExporter.cpp) + + ADD_ASSIMP_EXPORTER( X + X/XFileExporter.h + X/XFileExporter.cpp) + + ADD_ASSIMP_EXPORTER( X3D + X3D/X3DExporter.cpp + X3D/X3DExporter.hpp) + + ADD_ASSIMP_EXPORTER( GLTF + glTF/glTFExporter.h + glTF/glTFExporter.cpp + glTF2/glTF2Exporter.h + glTF2/glTF2Exporter.cpp) + + ADD_ASSIMP_EXPORTER( 3MF + 3MF/D3MFExporter.h + 3MF/D3MFExporter.cpp) + + ADD_ASSIMP_EXPORTER( ASSJSON + Assjson/cencode.c + Assjson/cencode.h + Assjson/json_exporter.cpp + Assjson/mesh_splitter.cpp + Assjson/mesh_splitter.h) + + ADD_ASSIMP_EXPORTER( STEP + Step/StepExporter.h + Step/StepExporter.cpp) + +endif() SET( PostProcessing_SRCS PostProcessing/CalcTangentsProcess.cpp @@ -744,11 +776,6 @@ ADD_ASSIMP_IMPORTER( STL STL/STLLoader.h ) -ADD_ASSIMP_EXPORTER( STL - STL/STLExporter.h - STL/STLExporter.cpp -) - ADD_ASSIMP_IMPORTER( TERRAGEN Terragen/TerragenLoader.cpp Terragen/TerragenLoader.h @@ -767,11 +794,6 @@ ADD_ASSIMP_IMPORTER( X X/XFileParser.h ) -ADD_ASSIMP_EXPORTER( X - X/XFileExporter.h - X/XFileExporter.cpp -) - ADD_ASSIMP_IMPORTER( X3D X3D/X3DImporter.cpp X3D/X3DImporter.hpp @@ -792,11 +814,6 @@ ADD_ASSIMP_IMPORTER( X3D X3D/X3DVocabulary.cpp ) -ADD_ASSIMP_EXPORTER( X3D - X3D/X3DExporter.cpp - X3D/X3DExporter.hpp -) - ADD_ASSIMP_IMPORTER( GLTF glTF/glTFCommon.h glTF/glTFCommon.cpp @@ -814,13 +831,6 @@ ADD_ASSIMP_IMPORTER( GLTF glTF2/glTF2Importer.h ) -ADD_ASSIMP_EXPORTER( GLTF - glTF/glTFExporter.h - glTF/glTFExporter.cpp - glTF2/glTF2Exporter.h - glTF2/glTF2Exporter.cpp -) - ADD_ASSIMP_IMPORTER( 3MF 3MF/D3MFImporter.h 3MF/D3MFImporter.cpp @@ -829,11 +839,6 @@ ADD_ASSIMP_IMPORTER( 3MF 3MF/3MFXmlTags.h ) -ADD_ASSIMP_EXPORTER( 3MF - 3MF/D3MFExporter.h - 3MF/D3MFExporter.cpp -) - ADD_ASSIMP_IMPORTER( MMD MMD/MMDCpp14.h MMD/MMDImporter.cpp @@ -844,14 +849,6 @@ ADD_ASSIMP_IMPORTER( MMD MMD/MMDVmdParser.h ) -ADD_ASSIMP_EXPORTER( ASSJSON - Assjson/cencode.c - Assjson/cencode.h - Assjson/json_exporter.cpp - Assjson/mesh_splitter.cpp - Assjson/mesh_splitter.h -) - # Workaround for issue #2406 - force problematic large file to be optimized to prevent string table overflow error # Used -Os instead of -O2 as previous issues had mentioned, since -Os is roughly speaking -O2, excluding any # optimizations that take up extra space. Given that the issue is a string table overflowing, -Os seemed appropriate @@ -874,11 +871,6 @@ ADD_ASSIMP_IMPORTER( STEP Importer/StepFile/StepReaderGen.h ) -ADD_ASSIMP_EXPORTER( STEP - Step/StepExporter.h - Step/StepExporter.cpp -) - if ((NOT ASSIMP_NO_EXPORT) OR (NOT ASSIMP_EXPORTERS_ENABLED STREQUAL "")) SET( Exporter_SRCS Common/Exporter.cpp @@ -1088,8 +1080,10 @@ ENDIF(NOT HUNTER_ENABLED) MESSAGE(STATUS "Enabled importer formats:${ASSIMP_IMPORTERS_ENABLED}") MESSAGE(STATUS "Disabled importer formats:${ASSIMP_IMPORTERS_DISABLED}") -MESSAGE(STATUS "Enabled exporter formats:${ASSIMP_EXPORTERS_ENABLED}") -MESSAGE(STATUS "Disabled exporter formats:${ASSIMP_EXPORTERS_DISABLED}") +if (NOT ASSIMP_NO_EXPORT) + MESSAGE(STATUS "Enabled exporter formats:${ASSIMP_EXPORTERS_ENABLED}") + MESSAGE(STATUS "Disabled exporter formats:${ASSIMP_EXPORTERS_DISABLED}") +endif() SOURCE_GROUP( include\\assimp FILES ${PUBLIC_HEADERS} ) From edfaaed56fb656a3923807cac1c875cc8ff2f4ba Mon Sep 17 00:00:00 2001 From: Marc-Antoine Lortie Date: Sun, 23 Feb 2020 07:09:35 -0500 Subject: [PATCH 073/330] Removed uneeded expression in else() and endif() constructs. The following changes were tested against building with a master copy. For a more detailed report, please read the followings below: The flags that were checked were the ones checked by default + the following: ASSIMP_BUILD_ASSIMP_VIEW ASSIMP_BUILD_SAMPLES The list of compilable projects in Visual Studio were the following: - assimp - assimp_cmd - assimp_simpleogl - assimp_simpletextureddirectx11 - assimp_simpletexturedogl - assimp_viewer - INSTALL - IrrXML - uninstall - unit - UpdateAssimpLibsDebugSymbolsAndDLLs - ZERO_CHECK - zlib - zlibstatic The solution that was generated with the new changes comprised the same number of projects as the one from the master, unmodified. All projects except UpdateAssimpLibsDebugSymbolsAndDLLs were built without any error. All tests were run. UpdateAssimpLibsDebugSymbolsAndDLLs could not be built because of the reasons explained in issue #3004. --- CMakeLists.txt | 88 +++++++++---------- code/CMakeLists.txt | 86 +++++++++--------- contrib/CMakeLists.txt | 2 +- doc/CMakeLists.txt | 4 +- samples/SimpleOpenGL/CMakeLists.txt | 12 +-- .../SimpleTexturedDirectx11/CMakeLists.txt | 4 +- samples/SimpleTexturedOpenGL/CMakeLists.txt | 8 +- test/CMakeLists.txt | 6 +- test/headercheck/CMakeLists.txt | 2 +- tools/assimp_view/CMakeLists.txt | 2 +- 10 files changed, 107 insertions(+), 107 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b98d1f78a..59b79d1c6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -49,7 +49,7 @@ IF(HUNTER_ENABLED) ) add_definitions(-DASSIMP_USE_HUNTER) -ENDIF(HUNTER_ENABLED) +ENDIF() PROJECT( Assimp VERSION 5.0.1 ) @@ -141,9 +141,9 @@ OPTION ( IGNORE_GIT_HASH IF (IOS AND NOT HUNTER_ENABLED) IF (NOT CMAKE_BUILD_TYPE) SET(CMAKE_BUILD_TYPE "Release") - ENDIF (NOT CMAKE_BUILD_TYPE) + ENDIF () ADD_DEFINITIONS(-DENABLE_BITCODE) -ENDIF (IOS AND NOT HUNTER_ENABLED) +ENDIF () # Use subset of Windows.h if (WIN32) @@ -159,19 +159,19 @@ IF(MSVC) # Multibyte character set is deprecated since at least MSVC2015 (possibly earlier) ADD_DEFINITIONS( -DUNICODE -D_UNICODE ) ENDIF() -ENDIF(MSVC) +ENDIF() IF (BUILD_FRAMEWORK) SET (BUILD_SHARED_LIBS ON) MESSAGE(STATUS "Framework bundle building enabled") -ENDIF(BUILD_FRAMEWORK) +ENDIF() IF(NOT BUILD_SHARED_LIBS) MESSAGE(STATUS "Shared libraries disabled") SET(LINK_SEARCH_START_STATIC TRUE) ELSE() MESSAGE(STATUS "Shared libraries enabled") -ENDIF(NOT BUILD_SHARED_LIBS) +ENDIF() # Define here the needed parameters SET (ASSIMP_VERSION_MAJOR ${PROJECT_VERSION_MAJOR}) @@ -208,11 +208,11 @@ ENDIF() IF(NOT GIT_COMMIT_HASH) SET(GIT_COMMIT_HASH 0) -ENDIF(NOT GIT_COMMIT_HASH) +ENDIF() IF(ASSIMP_DOUBLE_PRECISION) ADD_DEFINITIONS(-DASSIMP_DOUBLE_PRECISION) -ENDIF(ASSIMP_DOUBLE_PRECISION) +ENDIF() CONFIGURE_FILE( ${CMAKE_CURRENT_LIST_DIR}/revision.h.in @@ -241,7 +241,7 @@ SET(ASSIMP_LIBRARY_SUFFIX "" CACHE STRING "Suffix to append to library names") IF( UNIX ) # Use GNUInstallDirs for Unix predefined directories INCLUDE(GNUInstallDirs) -ENDIF( UNIX ) +ENDIF() # Grouped compiler settings IF ((CMAKE_C_COMPILER_ID MATCHES "GNU") AND NOT CMAKE_COMPILER_IS_MINGW) @@ -293,7 +293,7 @@ IF ( IOS AND NOT HUNTER_ENABLED) SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fembed-bitcode -O3") # Experimental for pdb generation ENDIF() -ENDIF( IOS AND NOT HUNTER_ENABLED) +ENDIF() IF (ASSIMP_COVERALLS) MESSAGE(STATUS "Coveralls enabled") @@ -349,7 +349,7 @@ ELSE() SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/lib") SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin") SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin") -ENDIF ( CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR ) +ENDIF () # Cache these to allow the user to override them manually. SET( ASSIMP_LIB_INSTALL_DIR "lib" CACHE STRING @@ -411,7 +411,7 @@ IF(HUNTER_ENABLED) NAMESPACE "${NAMESPACE}" DESTINATION "${CONFIG_INSTALL_DIR}" ) -ELSE(HUNTER_ENABLED) +ELSE() # cmake configuration files if(${BUILD_SHARED_LIBS}) set(BUILD_LIB_TYPE SHARED) @@ -439,16 +439,16 @@ ELSE(HUNTER_ENABLED) "${CMAKE_CURRENT_BINARY_DIR}/assimpTargets.cmake" ${PACKAGE_TARGETS_FILE} DESTINATION "${ASSIMP_LIB_INSTALL_DIR}/cmake/assimp-${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}" COMPONENT ${LIBASSIMP-DEV_COMPONENT}) -ENDIF(HUNTER_ENABLED) +ENDIF() IF( BUILD_DOCS ) ADD_SUBDIRECTORY(doc) -ENDIF( BUILD_DOCS ) +ENDIF() # Look for system installed irrXML IF ( SYSTEM_IRRXML ) FIND_PACKAGE( IrrXML REQUIRED ) -ENDIF( SYSTEM_IRRXML ) +ENDIF() # Search for external dependencies, and build them from source if not found # Search for zlib @@ -460,10 +460,10 @@ IF(HUNTER_ENABLED) set(ZLIB_FOUND TRUE) set(ZLIB_LIBRARIES ZLIB::zlib) set(ASSIMP_BUILD_MINIZIP TRUE) -ELSE(HUNTER_ENABLED) +ELSE() IF ( NOT ASSIMP_BUILD_ZLIB ) FIND_PACKAGE(ZLIB) - ENDIF( NOT ASSIMP_BUILD_ZLIB ) + ENDIF() IF( NOT ZLIB_FOUND ) MESSAGE(STATUS "compiling zlib from sources") @@ -486,46 +486,46 @@ ELSE(HUNTER_ENABLED) SET(ZLIB_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/contrib/zlib ${CMAKE_CURRENT_BINARY_DIR}/contrib/zlib) # need to ensure we don't link with system zlib or minizip as well. SET(ASSIMP_BUILD_MINIZIP 1) - ELSE(NOT ZLIB_FOUND) + ELSE() ADD_DEFINITIONS(-DASSIMP_BUILD_NO_OWN_ZLIB) SET(ZLIB_LIBRARIES_LINKED -lz) - ENDIF(NOT ZLIB_FOUND) + ENDIF() INCLUDE_DIRECTORIES(${ZLIB_INCLUDE_DIR}) -ENDIF(HUNTER_ENABLED) +ENDIF() IF( NOT IOS ) IF( NOT ASSIMP_BUILD_MINIZIP ) use_pkgconfig(UNZIP minizip) - ENDIF( NOT ASSIMP_BUILD_MINIZIP ) -ELSE ( NOT IOS ) + ENDIF() +ELSE () IF( NOT BUILD_SHARED_LIBS ) IF( NOT ASSIMP_BUILD_MINIZIP ) use_pkgconfig(UNZIP minizip) - ENDIF( NOT ASSIMP_BUILD_MINIZIP ) - ENDIF ( NOT BUILD_SHARED_LIBS ) -ENDIF ( NOT IOS ) + ENDIF() + ENDIF () +ENDIF () IF ( ASSIMP_NO_EXPORT ) ADD_DEFINITIONS( -DASSIMP_BUILD_NO_EXPORT) MESSAGE( STATUS "Build an import-only version of Assimp." ) -ENDIF( ASSIMP_NO_EXPORT ) +ENDIF() SET ( ASSIMP_BUILD_ARCHITECTURE "" CACHE STRING "describe the current architecture." ) IF ( ASSIMP_BUILD_ARCHITECTURE STREQUAL "") -ELSE ( ASSIMP_BUILD_ARCHITECTURE STREQUAL "") +ELSE () ADD_DEFINITIONS ( -D'ASSIMP_BUILD_ARCHITECTURE="${ASSIMP_BUILD_ARCHITECTURE}"' ) -ENDIF ( ASSIMP_BUILD_ARCHITECTURE STREQUAL "") +ENDIF () # ${CMAKE_GENERATOR} SET ( ASSIMP_BUILD_COMPILER "" CACHE STRING "describe the current compiler." ) IF ( ASSIMP_BUILD_COMPILER STREQUAL "") -ELSE ( ASSIMP_BUILD_COMPILER STREQUAL "") +ELSE () ADD_DEFINITIONS ( -D'ASSIMP_BUILD_COMPILER="${ASSIMP_BUILD_COMPILER}"' ) -ENDIF ( ASSIMP_BUILD_COMPILER STREQUAL "") +ENDIF () MARK_AS_ADVANCED ( ASSIMP_BUILD_ARCHITECTURE ASSIMP_BUILD_COMPILER ) @@ -571,14 +571,14 @@ IF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER) MESSAGE( FATAL_ERROR "C4D is currently only available on Windows with melange SDK installed in contrib/Melange" ) - ENDIF ( MSVC ) -ELSE (ASSIMP_BUILD_NONFREE_C4D_IMPORTER) + ENDIF () +ELSE () ADD_DEFINITIONS( -DASSIMP_BUILD_NO_C4D_IMPORTER ) -ENDIF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER) +ENDIF () IF(NOT HUNTER_ENABLED) ADD_SUBDIRECTORY(contrib) -ENDIF(NOT HUNTER_ENABLED) +ENDIF() ADD_SUBDIRECTORY( code/ ) IF ( ASSIMP_BUILD_ASSIMP_TOOLS ) @@ -587,29 +587,29 @@ IF ( ASSIMP_BUILD_ASSIMP_TOOLS ) OPTION ( ASSIMP_BUILD_ASSIMP_VIEW "If the Assimp view tool is built. (requires DirectX)" ${DirectX_FOUND} ) IF ( ASSIMP_BUILD_ASSIMP_VIEW ) ADD_SUBDIRECTORY( tools/assimp_view/ ) - ENDIF ( ASSIMP_BUILD_ASSIMP_VIEW ) - ENDIF ( WIN32 AND DirectX_D3DX9_LIBRARY ) + ENDIF () + ENDIF () # Te command line tool ADD_SUBDIRECTORY( tools/assimp_cmd/ ) -ENDIF ( ASSIMP_BUILD_ASSIMP_TOOLS ) +ENDIF () IF ( ASSIMP_BUILD_SAMPLES) IF ( WIN32 ) ADD_SUBDIRECTORY( samples/SimpleTexturedOpenGL/ ) ADD_SUBDIRECTORY( samples/SimpleTexturedDirectx11 ) - ENDIF ( WIN32 ) + ENDIF () ADD_SUBDIRECTORY( samples/SimpleOpenGL/ ) -ENDIF ( ASSIMP_BUILD_SAMPLES ) +ENDIF () IF ( ASSIMP_BUILD_TESTS ) ADD_SUBDIRECTORY( test/ ) -ENDIF ( ASSIMP_BUILD_TESTS ) +ENDIF () # Generate a pkg-config .pc for the Assimp library. CONFIGURE_FILE( "${PROJECT_SOURCE_DIR}/assimp.pc.in" "${PROJECT_BINARY_DIR}/assimp.pc" @ONLY ) IF ( ASSIMP_INSTALL ) INSTALL( FILES "${PROJECT_BINARY_DIR}/assimp.pc" DESTINATION ${ASSIMP_LIB_INSTALL_DIR}/pkgconfig/ COMPONENT ${LIBASSIMP-DEV_COMPONENT}) -ENDIF( ASSIMP_INSTALL ) +ENDIF() IF ( ASSIMP_INSTALL ) IF(CMAKE_CPACK_COMMAND AND UNIX AND ASSIMP_OPT_BUILD_PACKAGES) @@ -680,7 +680,7 @@ if(WIN32) SET(ASSIMP_MSVC_VERSION "vc140") ELSEIF(MSVC15) SET(ASSIMP_MSVC_VERSION "vc141") - ENDIF(MSVC12) + ENDIF() ENDIF() IF(MSVC12 OR MSVC14 OR MSVC15 ) @@ -705,5 +705,5 @@ if(WIN32) ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/assimp-${ASSIMP_MSVC_VERSION}-mtd.pdb ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.pdb VERBATIM) ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/assimp-${ASSIMP_MSVC_VERSION}-mtd.pdb ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.pdb VERBATIM) ENDIF() - ENDIF(MSVC12 OR MSVC14 OR MSVC15 ) -ENDIF (WIN32) + ENDIF() +ENDIF () diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index 91f099c02..0cef480f2 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -49,7 +49,7 @@ SET( HEADER_PATH ../include/assimp ) if(NOT ANDROID AND ASSIMP_ANDROID_JNIIOSYSTEM) message(WARNING "Requesting Android JNI I/O-System in non-Android toolchain. Resetting ASSIMP_ANDROID_JNIIOSYSTEM to OFF.") set(ASSIMP_ANDROID_JNIIOSYSTEM OFF) -endif(NOT ANDROID AND ASSIMP_ANDROID_JNIIOSYSTEM) +endif() SET( COMPILER_HEADERS ${HEADER_PATH}/Compiler/pushpack1.h @@ -148,7 +148,7 @@ SET( Core_SRCS IF(MSVC) list(APPEND Core_SRCS "res/assimp.rc") -ENDIF(MSVC) +ENDIF() SET( Logging_SRCS ${HEADER_PATH}/DefaultLogger.hpp @@ -222,7 +222,7 @@ IF ( ASSIMP_BUILD_NONFREE_C4D_IMPORTER ) C4D/C4DImporter.h ) SOURCE_GROUP( C4D FILES ${C4D_SRCS}) -ENDIF ( ASSIMP_BUILD_NONFREE_C4D_IMPORTER ) +ENDIF () # if this variable is set to TRUE, the user can manually disable importers by setting # ASSIMP_BUILD_XXX_IMPORTER to FALSE for each importer @@ -599,7 +599,7 @@ if (ASSIMP_BUILD_IFC_IMPORTER) elseif(CMAKE_COMPILER_IS_MINGW) set_source_files_properties(Importer/IFC/IFCReaderGen1_2x3.cpp Importer/IFC/IFCReaderGen2_2x3.cpp PROPERTIES COMPILE_FLAGS "-O2 -Wa,-mbig-obj") endif() -endif (ASSIMP_BUILD_IFC_IMPORTER) +endif () ADD_ASSIMP_IMPORTER( XGL XGL/XGLLoader.cpp @@ -897,35 +897,35 @@ SOURCE_GROUP( Extra FILES ${Extra_SRCS}) IF(HUNTER_ENABLED) hunter_add_package(irrXML) find_package(irrXML CONFIG REQUIRED) -ELSE(HUNTER_ENABLED) +ELSE() # irrXML already included in contrib directory by parent CMakeLists.txt. -ENDIF(HUNTER_ENABLED) +ENDIF() # utf8 IF(HUNTER_ENABLED) hunter_add_package(utf8) find_package(utf8 CONFIG REQUIRED) -ELSE(HUNTER_ENABLED) +ELSE() # utf8 is header-only, so Assimp doesn't need to do anything. -ENDIF(HUNTER_ENABLED) +ENDIF() # polyclipping IF(HUNTER_ENABLED) hunter_add_package(polyclipping) find_package(polyclipping CONFIG REQUIRED) -ELSE(HUNTER_ENABLED) +ELSE() SET( Clipper_SRCS ../contrib/clipper/clipper.hpp ../contrib/clipper/clipper.cpp ) SOURCE_GROUP( Contrib\\Clipper FILES ${Clipper_SRCS}) -ENDIF(HUNTER_ENABLED) +ENDIF() # poly2tri IF(HUNTER_ENABLED) hunter_add_package(poly2tri) find_package(poly2tri CONFIG REQUIRED) -ELSE(HUNTER_ENABLED) +ELSE() SET( Poly2Tri_SRCS ../contrib/poly2tri/poly2tri/common/shapes.cc ../contrib/poly2tri/poly2tri/common/shapes.h @@ -940,13 +940,13 @@ ELSE(HUNTER_ENABLED) ../contrib/poly2tri/poly2tri/sweep/sweep_context.h ) SOURCE_GROUP( Contrib\\Poly2Tri FILES ${Poly2Tri_SRCS}) -ENDIF(HUNTER_ENABLED) +ENDIF() # minizip/unzip IF(HUNTER_ENABLED) hunter_add_package(minizip) find_package(minizip CONFIG REQUIRED) -ELSE(HUNTER_ENABLED) +ELSE() SET( unzip_SRCS ../contrib/unzip/crypt.h ../contrib/unzip/ioapi.c @@ -955,13 +955,13 @@ ELSE(HUNTER_ENABLED) ../contrib/unzip/unzip.h ) SOURCE_GROUP(Contrib\\unzip FILES ${unzip_SRCS}) -ENDIF(HUNTER_ENABLED) +ENDIF() # zip (https://github.com/kuba--/zip) IF(HUNTER_ENABLED) hunter_add_package(zip) find_package(zip CONFIG REQUIRED) -ELSE(HUNTER_ENABLED) +ELSE() SET( ziplib_SRCS ../contrib/zip/src/miniz.h ../contrib/zip/src/zip.c @@ -976,13 +976,13 @@ ELSE(HUNTER_ENABLED) endif() SOURCE_GROUP( ziplib FILES ${ziplib_SRCS} ) -ENDIF(HUNTER_ENABLED) +ENDIF() # openddlparser IF(HUNTER_ENABLED) hunter_add_package(openddlparser) find_package(openddlparser CONFIG REQUIRED) -ELSE(HUNTER_ENABLED) +ELSE() SET ( openddl_parser_SRCS ../contrib/openddlparser/code/OpenDDLParser.cpp ../contrib/openddlparser/code/DDLNode.cpp @@ -999,12 +999,12 @@ ELSE(HUNTER_ENABLED) ../contrib/openddlparser/include/openddlparser/Value.h ) SOURCE_GROUP( Contrib\\openddl_parser FILES ${openddl_parser_SRCS}) -ENDIF(HUNTER_ENABLED) +ENDIF() # Open3DGC IF(HUNTER_ENABLED) # Nothing to do, not available in Hunter yet. -ELSE(HUNTER_ENABLED) +ELSE() SET ( open3dgc_SRCS ../contrib/Open3DGC/o3dgcAdjacencyInfo.h ../contrib/Open3DGC/o3dgcArithmeticCodec.cpp @@ -1037,7 +1037,7 @@ ELSE(HUNTER_ENABLED) ../contrib/Open3DGC/o3dgcVector.inl ) SOURCE_GROUP( Contrib\\open3dgc FILES ${open3dgc_SRCS}) -ENDIF(HUNTER_ENABLED) +ENDIF() # Check dependencies for glTF importer with Open3DGC-compression. # RT-extensions is used in "contrib/Open3DGC/o3dgcTimer.h" for collecting statistics. Pointed file @@ -1056,34 +1056,34 @@ ENDIF () IF(HUNTER_ENABLED) hunter_add_package(RapidJSON) find_package(RapidJSON CONFIG REQUIRED) -ELSE(HUNTER_ENABLED) +ELSE() INCLUDE_DIRECTORIES( "../contrib/rapidjson/include" ) INCLUDE_DIRECTORIES( "../contrib" ) -ENDIF(HUNTER_ENABLED) +ENDIF() # VC2010 fixes if(MSVC10) option( VC10_STDINT_FIX "Fix for VC10 Compiler regarding pstdint.h redefinition errors" OFF ) if( VC10_STDINT_FIX ) ADD_DEFINITIONS( -D_STDINT ) - endif( VC10_STDINT_FIX ) -endif(MSVC10) + endif() +endif() ADD_DEFINITIONS( -DASSIMP_BUILD_DLL_EXPORT ) if ( MSVC ) ADD_DEFINITIONS( -D_SCL_SECURE_NO_WARNINGS ) ADD_DEFINITIONS( -D_CRT_SECURE_NO_WARNINGS ) -endif ( MSVC ) +endif () IF(NOT HUNTER_ENABLED) if (UNZIP_FOUND) SET (unzip_compile_SRCS "") - else (UNZIP_FOUND) + else () SET (unzip_compile_SRCS ${unzip_SRCS}) INCLUDE_DIRECTORIES( "../contrib/unzip/" ) - endif (UNZIP_FOUND) -ENDIF(NOT HUNTER_ENABLED) + endif () +ENDIF() MESSAGE(STATUS "Enabled importer formats:${ASSIMP_IMPORTERS_ENABLED}") MESSAGE(STATUS "Disabled importer formats:${ASSIMP_IMPORTERS_DISABLED}") @@ -1129,12 +1129,12 @@ IF(NOT HUNTER_ENABLED) ${IRRXML_INCLUDE_DIR} ../contrib/openddlparser/include ) -ENDIF(NOT HUNTER_ENABLED) +ENDIF() IF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER) SET( assimp_src ${assimp_src} ${C4D_SRCS}) INCLUDE_DIRECTORIES(${C4D_INCLUDES}) -ENDIF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER) +ENDIF () ADD_LIBRARY( assimp ${assimp_src} ) ADD_LIBRARY(assimp::assimp ALIAS assimp) @@ -1158,21 +1158,21 @@ IF(HUNTER_ENABLED) utf8::utf8 zip::zip ) -ELSE(HUNTER_ENABLED) +ELSE() TARGET_LINK_LIBRARIES(assimp ${ZLIB_LIBRARIES} ${OPENDDL_PARSER_LIBRARIES} ${IRRXML_LIBRARY} ) -ENDIF(HUNTER_ENABLED) +ENDIF() if(ASSIMP_ANDROID_JNIIOSYSTEM) set(ASSIMP_ANDROID_JNIIOSYSTEM_PATH port/AndroidJNI) add_subdirectory(../${ASSIMP_ANDROID_JNIIOSYSTEM_PATH}/ ../${ASSIMP_ANDROID_JNIIOSYSTEM_PATH}/) target_link_libraries(assimp android_jniiosystem) -endif(ASSIMP_ANDROID_JNIIOSYSTEM) +endif() IF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER) TARGET_LINK_LIBRARIES(assimp optimized ${C4D_RELEASE_LIBRARIES}) TARGET_LINK_LIBRARIES(assimp debug ${C4D_DEBUG_LIBRARIES}) TARGET_LINK_LIBRARIES(assimp ${C4D_EXTRA_LIBRARIES}) -ENDIF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER) +ENDIF () if( MSVC ) # in order to prevent DLL hell, each of the DLLs have to be suffixed with the major version and msvc prefix @@ -1233,8 +1233,8 @@ if (APPLE) "../${HEADER_PATH}/Compiler" assimp.framework/Headers/Compiler COMMENT "Copying public ./Compiler/ header files to framework bundle's Headers/Compiler/") - ENDIF(BUILD_FRAMEWORK) -ENDIF(APPLE) + ENDIF() +ENDIF() # Build against external unzip, or add ../contrib/unzip so # assimp can #include "unzip.h" @@ -1242,15 +1242,15 @@ IF(NOT HUNTER_ENABLED) if (UNZIP_FOUND) INCLUDE_DIRECTORIES(${UNZIP_INCLUDE_DIRS}) TARGET_LINK_LIBRARIES(assimp ${UNZIP_LIBRARIES}) - else (UNZIP_FOUND) + else () INCLUDE_DIRECTORIES("../") - endif (UNZIP_FOUND) -ENDIF(NOT HUNTER_ENABLED) + endif () +ENDIF() # Add RT-extension library for glTF importer with Open3DGC-compression. IF (RT_FOUND AND ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC) TARGET_LINK_LIBRARIES(assimp ${RT_LIBRARY}) -ENDIF (RT_FOUND AND ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC) +ENDIF () IF(HUNTER_ENABLED) INSTALL( TARGETS assimp @@ -1261,14 +1261,14 @@ IF(HUNTER_ENABLED) FRAMEWORK DESTINATION ${ASSIMP_LIB_INSTALL_DIR} COMPONENT ${LIBASSIMP_COMPONENT} INCLUDES DESTINATION "include") -ELSE(HUNTER_ENABLED) +ELSE() INSTALL( TARGETS assimp LIBRARY DESTINATION ${ASSIMP_LIB_INSTALL_DIR} ARCHIVE DESTINATION ${ASSIMP_LIB_INSTALL_DIR} RUNTIME DESTINATION ${ASSIMP_BIN_INSTALL_DIR} FRAMEWORK DESTINATION ${ASSIMP_LIB_INSTALL_DIR} COMPONENT ${LIBASSIMP_COMPONENT}) -ENDIF(HUNTER_ENABLED) +ENDIF() INSTALL( FILES ${PUBLIC_HEADERS} DESTINATION ${ASSIMP_INCLUDE_INSTALL_DIR}/assimp COMPONENT assimp-dev) INSTALL( FILES ${COMPILER_HEADERS} DESTINATION ${ASSIMP_INCLUDE_INSTALL_DIR}/assimp/Compiler COMPONENT assimp-dev) @@ -1276,7 +1276,7 @@ if (ASSIMP_ANDROID_JNIIOSYSTEM) INSTALL(FILES ${HEADER_PATH}/${ASSIMP_ANDROID_JNIIOSYSTEM_PATH}/AndroidJNIIOSystem.h DESTINATION ${ASSIMP_INCLUDE_INSTALL_DIR} COMPONENT assimp-dev) -ENDIF(ASSIMP_ANDROID_JNIIOSYSTEM) +ENDIF() if(MSVC AND ASSIMP_INSTALL_PDB) # When only the static library is built, these properties must diff --git a/contrib/CMakeLists.txt b/contrib/CMakeLists.txt index 362f1653d..8394ad703 100644 --- a/contrib/CMakeLists.txt +++ b/contrib/CMakeLists.txt @@ -1,4 +1,4 @@ # Compile internal irrXML only if system is not requested if( NOT SYSTEM_IRRXML ) add_subdirectory(irrXML) -endif( NOT SYSTEM_IRRXML ) +endif() diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt index f7ce7b726..b510d8c37 100644 --- a/doc/CMakeLists.txt +++ b/doc/CMakeLists.txt @@ -6,7 +6,7 @@ set( HTML_OUTPUT "AssimpDoc_Html" CACHE STRING "Output directory for generated H set( MICROSOFT_HELP_WORKSHOP "NO") if( MSVC ) set( MICROSOFT_HELP_WORKSHOP "YES" ) -endif( MSVC ) +endif() configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in @@ -38,5 +38,5 @@ if( DEFINED CMAKE_INSTALL_DOCDIR ) ${CMAKE_CURRENT_SOURCE_DIR}/AssimpDoc_Html/dragonsplash.png DESTINATION ${CMAKE_INSTALL_DOCDIR}/${HTML_OUTPUT} ) -endif( DEFINED CMAKE_INSTALL_DOCDIR ) +endif() diff --git a/samples/SimpleOpenGL/CMakeLists.txt b/samples/SimpleOpenGL/CMakeLists.txt index 93f389741..39593fdb9 100644 --- a/samples/SimpleOpenGL/CMakeLists.txt +++ b/samples/SimpleOpenGL/CMakeLists.txt @@ -2,24 +2,24 @@ FIND_PACKAGE(OpenGL) FIND_PACKAGE(GLUT) IF ( MSVC ) SET(M_LIB) -ELSE ( MSVC ) +ELSE () find_library(M_LIB m) -ENDIF ( MSVC ) +ENDIF () IF ( NOT GLUT_FOUND ) IF ( MSVC ) SET ( GLUT_FOUND 1 ) SET ( GLUT_INCLUDE_DIR ${Assimp_SOURCE_DIR}/samples/freeglut/ ) SET ( GLUT_LIBRARIES ${Assimp_SOURCE_DIR}/samples/freeglut/lib/freeglut.lib ) - ELSE ( MSVC ) + ELSE () MESSAGE( WARNING "Please install glut." ) - ENDIF ( MSVC ) -ENDIF ( NOT GLUT_FOUND ) + ENDIF () +ENDIF () if ( MSVC ) ADD_DEFINITIONS( -D_SCL_SECURE_NO_WARNINGS ) ADD_DEFINITIONS( -D_CRT_SECURE_NO_WARNINGS ) -endif ( MSVC ) +endif () INCLUDE_DIRECTORIES( ${Assimp_SOURCE_DIR}/include diff --git a/samples/SimpleTexturedDirectx11/CMakeLists.txt b/samples/SimpleTexturedDirectx11/CMakeLists.txt index 373b5a9db..b1882500e 100644 --- a/samples/SimpleTexturedDirectx11/CMakeLists.txt +++ b/samples/SimpleTexturedDirectx11/CMakeLists.txt @@ -2,13 +2,13 @@ FIND_PACKAGE(DirectX) IF ( MSVC ) SET(M_LIB) -ENDIF ( MSVC ) +ENDIF () if ( MSVC ) ADD_DEFINITIONS( -D_SCL_SECURE_NO_WARNINGS ) ADD_DEFINITIONS( -D_CRT_SECURE_NO_WARNINGS ) REMOVE_DEFINITIONS( -DUNICODE -D_UNICODE ) -endif ( MSVC ) +endif () INCLUDE_DIRECTORIES( ${Assimp_SOURCE_DIR}/include diff --git a/samples/SimpleTexturedOpenGL/CMakeLists.txt b/samples/SimpleTexturedOpenGL/CMakeLists.txt index 941e18cea..adcf882a8 100644 --- a/samples/SimpleTexturedOpenGL/CMakeLists.txt +++ b/samples/SimpleTexturedOpenGL/CMakeLists.txt @@ -6,15 +6,15 @@ IF ( NOT GLUT_FOUND ) SET ( GLUT_FOUND 1 ) SET ( GLUT_INCLUDE_DIR ${Assimp_SOURCE_DIR}/samples/freeglut/ ) SET ( GLUT_LIBRARIES ${Assimp_SOURCE_DIR}/samples/freeglut/lib/freeglut.lib ) - ELSE ( MSVC ) + ELSE () MESSAGE( WARNING "Please install glut." ) - ENDIF ( MSVC ) -ENDIF ( NOT GLUT_FOUND ) + ENDIF () +ENDIF () if ( MSVC ) ADD_DEFINITIONS( -D_SCL_SECURE_NO_WARNINGS ) ADD_DEFINITIONS( -D_CRT_SECURE_NO_WARNINGS ) -endif ( MSVC ) +endif () INCLUDE_DIRECTORIES( ${Assimp_SOURCE_DIR}/include diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index b1d918a86..c5c414639 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -201,13 +201,13 @@ SET_PROPERTY( TARGET assimp PROPERTY DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX} ) IF( WIN32 ) SET( platform_libs ) -ELSE( WIN32 ) +ELSE() SET( platform_libs pthread ) -ENDIF( WIN32 ) +ENDIF() IF(MSVC) add_definitions(-D_CRT_SECURE_NO_WARNINGS) -ENDIF(MSVC) +ENDIF() target_link_libraries( unit assimp ${platform_libs} ) diff --git a/test/headercheck/CMakeLists.txt b/test/headercheck/CMakeLists.txt index fa6b35c66..b77e023a8 100644 --- a/test/headercheck/CMakeLists.txt +++ b/test/headercheck/CMakeLists.txt @@ -30,7 +30,7 @@ FOREACH( HEADER ${headers} ) # add library add_library( ${TEST_NAME} EXCLUDE_FROM_ALL ${TEST_FILE} ) list(APPEND headerchecklibs ${TEST_NAME}) -ENDFOREACH( HEADER ) +ENDFOREACH() add_custom_target(headercheck DEPENDS ${headerchecklibs}) diff --git a/tools/assimp_view/CMakeLists.txt b/tools/assimp_view/CMakeLists.txt index dc1cee0d2..a77f13041 100644 --- a/tools/assimp_view/CMakeLists.txt +++ b/tools/assimp_view/CMakeLists.txt @@ -90,7 +90,7 @@ IF ( MSVC ) ADD_DEFINITIONS( -D_CRT_SECURE_NO_WARNINGS ) # assimp_viewer is ANSI (MBCS) throughout REMOVE_DEFINITIONS( -DUNICODE -D_UNICODE ) -ENDIF ( MSVC ) +ENDIF () # Link the executable to the assimp + dx libs. TARGET_LINK_LIBRARIES ( assimp_viewer assimp ${DirectX_LIBRARY} ${DirectX_D3DX9_LIBRARY} comctl32.lib winmm.lib ) From fb5b01958a448e1c3dea9b6b2796b8bf9f98a5a7 Mon Sep 17 00:00:00 2001 From: Paul Arden Date: Tue, 25 Feb 2020 11:03:07 +1100 Subject: [PATCH 074/330] Fix to read orthographic camera data. Manual merge for this branch. Fixes #3028 --- code/glTF2/glTF2Asset.inl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/code/glTF2/glTF2Asset.inl b/code/glTF2/glTF2Asset.inl index 4259022e9..184ad7419 100644 --- a/code/glTF2/glTF2Asset.inl +++ b/code/glTF2/glTF2Asset.inl @@ -1087,10 +1087,10 @@ inline void Camera::Read(Value& obj, Asset& /*r*/) cameraProperties.perspective.znear = MemberOrDefault(*it, "znear", 0.01f); } else { - cameraProperties.ortographic.xmag = MemberOrDefault(obj, "xmag", 1.f); - cameraProperties.ortographic.ymag = MemberOrDefault(obj, "ymag", 1.f); - cameraProperties.ortographic.zfar = MemberOrDefault(obj, "zfar", 100.f); - cameraProperties.ortographic.znear = MemberOrDefault(obj, "znear", 0.01f); + cameraProperties.ortographic.xmag = MemberOrDefault(*it, "xmag", 1.f); + cameraProperties.ortographic.ymag = MemberOrDefault(*it, "ymag", 1.f); + cameraProperties.ortographic.zfar = MemberOrDefault(*it, "zfar", 100.f); + cameraProperties.ortographic.znear = MemberOrDefault(*it, "znear", 0.01f); } } From ae50c4ebdf23c7f6f61300dede5bf32e0d306eb2 Mon Sep 17 00:00:00 2001 From: Paul Arden Date: Tue, 25 Feb 2020 14:45:00 +1100 Subject: [PATCH 075/330] Add support for orthographic camera information and use in glTF2 importer. Fixes #3030. --- code/glTF2/glTF2Importer.cpp | 1 + include/assimp/camera.h | 23 +++++++++++++++++------ 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/code/glTF2/glTF2Importer.cpp b/code/glTF2/glTF2Importer.cpp index dd80aeba9..cd67e69b7 100644 --- a/code/glTF2/glTF2Importer.cpp +++ b/code/glTF2/glTF2Importer.cpp @@ -715,6 +715,7 @@ void glTF2Importer::ImportCameras(glTF2::Asset &r) { aicam->mClipPlaneFar = cam.cameraProperties.ortographic.zfar; aicam->mClipPlaneNear = cam.cameraProperties.ortographic.znear; aicam->mHorizontalFOV = 0.0; + aicam->mOrthographicWidth = cam.cameraProperties.ortographic.xmag; aicam->mAspect = 1.0f; if (0.f != cam.cameraProperties.ortographic.ymag) { aicam->mAspect = cam.cameraProperties.ortographic.xmag / cam.cameraProperties.ortographic.ymag; diff --git a/include/assimp/camera.h b/include/assimp/camera.h index adb749ff5..ef52fce71 100644 --- a/include/assimp/camera.h +++ b/include/assimp/camera.h @@ -171,15 +171,26 @@ struct aiCamera */ float mAspect; + /** Half horizontal orthographic width, in scene units. + * + * The orthographic width specifies the half width of the + * orthographic view box. If non-zero the camera is + * orthographic and the mAspect should define to the + * ratio between the orthographic width and height + * and mHorizontalFOV should be set to 0. + * The default value is 0 (not orthographic). + */ + float mOrthographicWidth; #ifdef __cplusplus aiCamera() AI_NO_EXCEPT - : mUp (0.f,1.f,0.f) - , mLookAt (0.f,0.f,1.f) - , mHorizontalFOV (0.25f * (float)AI_MATH_PI) - , mClipPlaneNear (0.1f) - , mClipPlaneFar (1000.f) - , mAspect (0.f) + : mUp (0.f,1.f,0.f) + , mLookAt (0.f,0.f,1.f) + , mHorizontalFOV (0.25f * (float)AI_MATH_PI) + , mClipPlaneNear (0.1f) + , mClipPlaneFar (1000.f) + , mAspect (0.f) + , mOrthographicWidth (0.f) {} /** @brief Get a *right-handed* camera matrix from me From e56def7585804f39ee4889d11afe2508207308d9 Mon Sep 17 00:00:00 2001 From: Paul Arden Date: Tue, 25 Feb 2020 14:52:59 +1100 Subject: [PATCH 076/330] Fix indentation. --- include/assimp/camera.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/assimp/camera.h b/include/assimp/camera.h index ef52fce71..e266119fe 100644 --- a/include/assimp/camera.h +++ b/include/assimp/camera.h @@ -180,7 +180,7 @@ struct aiCamera * and mHorizontalFOV should be set to 0. * The default value is 0 (not orthographic). */ - float mOrthographicWidth; + float mOrthographicWidth; #ifdef __cplusplus aiCamera() AI_NO_EXCEPT @@ -190,7 +190,7 @@ struct aiCamera , mClipPlaneNear (0.1f) , mClipPlaneFar (1000.f) , mAspect (0.f) - , mOrthographicWidth (0.f) + , mOrthographicWidth (0.f) {} /** @brief Get a *right-handed* camera matrix from me From 957abaa15adfccda8c1b78a41c062e1cd4750320 Mon Sep 17 00:00:00 2001 From: Marc-Antoine Lortie Date: Wed, 26 Feb 2020 08:00:49 -0500 Subject: [PATCH 077/330] Raised minimum CMake version to 3.0 for assimp_cmd and assimp_view. This is a follow-up to PR #3024, in which I explained that I would then change the version of CMake to 3.0 in several files to match the changes that were originally made by OP in PR #3008. The minimum CMake version have been raised to 3.0 in both assimp_cmd and assimp_view projects. The same CMake configuration as in PR #3024 was used. All projects from PR #3024 are found in the solution with the current changes. All projects built. All tests were run. --- tools/assimp_cmd/CMakeLists.txt | 2 +- tools/assimp_view/CMakeLists.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/assimp_cmd/CMakeLists.txt b/tools/assimp_cmd/CMakeLists.txt index 848b8f81c..d46d09c2b 100644 --- a/tools/assimp_cmd/CMakeLists.txt +++ b/tools/assimp_cmd/CMakeLists.txt @@ -37,7 +37,7 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # #---------------------------------------------------------------------- -cmake_minimum_required( VERSION 2.6 ) +cmake_minimum_required( VERSION 3.0 ) INCLUDE_DIRECTORIES( ${Assimp_SOURCE_DIR}/include diff --git a/tools/assimp_view/CMakeLists.txt b/tools/assimp_view/CMakeLists.txt index a77f13041..96b21db40 100644 --- a/tools/assimp_view/CMakeLists.txt +++ b/tools/assimp_view/CMakeLists.txt @@ -37,7 +37,7 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # #---------------------------------------------------------------------- -cmake_minimum_required( VERSION 2.6 ) +cmake_minimum_required( VERSION 3.0 ) FIND_PACKAGE(DirectX REQUIRED) From 4182d6fb60ee205c4f784c7e252e553687e85f27 Mon Sep 17 00:00:00 2001 From: Nikita Shubin Date: Wed, 26 Feb 2020 16:24:34 +0300 Subject: [PATCH 078/330] cmake: double quotes around the see https://cmake.org/cmake/help/latest/command/file.html#to-native-path --- assimpTargets-debug.cmake.in | 2 +- assimpTargets-release.cmake.in | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/assimpTargets-debug.cmake.in b/assimpTargets-debug.cmake.in index e4ccbfba9..4cb917fd8 100644 --- a/assimpTargets-debug.cmake.in +++ b/assimpTargets-debug.cmake.in @@ -35,7 +35,7 @@ if(MSVC) endif() set(ASSIMP_LIBRARY_SUFFIX "@ASSIMP_LIBRARY_SUFFIX@-${MSVC_PREFIX}-mt" CACHE STRING "the suffix for the assimp windows library" ) - file(TO_NATIVE_PATH ${_IMPORT_PREFIX} _IMPORT_PREFIX) + file(TO_NATIVE_PATH "${_IMPORT_PREFIX}" _IMPORT_PREFIX) if(ASSIMP_BUILD_SHARED_LIBS) set(sharedLibraryName "assimp${ASSIMP_LIBRARY_SUFFIX}@CMAKE_DEBUG_POSTFIX@@CMAKE_SHARED_LIBRARY_SUFFIX@") diff --git a/assimpTargets-release.cmake.in b/assimpTargets-release.cmake.in index 79b643a9a..702109305 100644 --- a/assimpTargets-release.cmake.in +++ b/assimpTargets-release.cmake.in @@ -35,7 +35,7 @@ if(MSVC) endif() set(ASSIMP_LIBRARY_SUFFIX "@ASSIMP_LIBRARY_SUFFIX@-${MSVC_PREFIX}-mt" CACHE STRING "the suffix for the assimp windows library" ) - file(TO_NATIVE_PATH ${_IMPORT_PREFIX} _IMPORT_PREFIX) + file(TO_NATIVE_PATH "${_IMPORT_PREFIX}" _IMPORT_PREFIX) if(ASSIMP_BUILD_SHARED_LIBS) set(sharedLibraryName "assimp${ASSIMP_LIBRARY_SUFFIX}@CMAKE_SHARED_LIBRARY_SUFFIX@") From 3c081f5f709392849384c6bf8efba6fb0ff205cd Mon Sep 17 00:00:00 2001 From: Nikita Shubin Date: Wed, 26 Feb 2020 17:06:22 +0300 Subject: [PATCH 079/330] [RFC] cmake: targets: check lib or lib64 path Linkage against lib or lib64 should be taken into assumption. Without it we get: The imported target "assimp::assimp" references the file "/usr/lib/libassimp.so.5" When compiling against x86_64 target. The library of couse exits in /usr/lib64. see: https://cmake.org/cmake/help/v3.17/prop_gbl/FIND_LIBRARY_USE_LIB64_PATHS.html As i am not a master of cmake this should be double checked if it doesn't break anything. Signed-off-by: Nikita Shubin --- assimpTargets-debug.cmake.in | 16 ++++++++++++---- assimpTargets-release.cmake.in | 16 ++++++++++++---- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/assimpTargets-debug.cmake.in b/assimpTargets-debug.cmake.in index e4ccbfba9..cefdd038a 100644 --- a/assimpTargets-debug.cmake.in +++ b/assimpTargets-debug.cmake.in @@ -7,6 +7,14 @@ set(CMAKE_IMPORT_FILE_VERSION 1) set(ASSIMP_BUILD_SHARED_LIBS @BUILD_SHARED_LIBS@) +get_property(LIB64 GLOBAL PROPERTY FIND_LIBRARY_USE_LIB64_PATHS) + +if ("${LIB64}" STREQUAL "TRUE") + set(LIBSUFFIX 64) +else() + set(LIBSUFFIX "") +endif() + if(MSVC) if(MSVC_TOOLSET_VERSION) set(MSVC_PREFIX "vc${MSVC_TOOLSET_VERSION}") @@ -75,17 +83,17 @@ else() endif() set_target_properties(assimp::assimp PROPERTIES IMPORTED_SONAME_DEBUG "${sharedLibraryName}" - IMPORTED_LOCATION_DEBUG "${_IMPORT_PREFIX}/lib/${sharedLibraryName}" + IMPORTED_LOCATION_DEBUG "${_IMPORT_PREFIX}/lib${LIBSUFFIX}/${sharedLibraryName}" ) list(APPEND _IMPORT_CHECK_TARGETS assimp::assimp ) - list(APPEND _IMPORT_CHECK_FILES_FOR_assimp::assimp "${_IMPORT_PREFIX}/lib/${sharedLibraryName}" ) + list(APPEND _IMPORT_CHECK_FILES_FOR_assimp::assimp "${_IMPORT_PREFIX}/lib${LIBSUFFIX}/${sharedLibraryName}" ) else() set(staticLibraryName "libassimp${ASSIMP_LIBRARY_SUFFIX}@CMAKE_DEBUG_POSTFIX@@CMAKE_STATIC_LIBRARY_SUFFIX@") set_target_properties(assimp::assimp PROPERTIES - IMPORTED_LOCATION_DEBUG "${_IMPORT_PREFIX}/lib/${staticLibraryName}" + IMPORTED_LOCATION_DEBUG "${_IMPORT_PREFIX}/lib${LIBSUFFIX}/${staticLibraryName}" ) list(APPEND _IMPORT_CHECK_TARGETS assimp::assimp ) - list(APPEND _IMPORT_CHECK_FILES_FOR_assimp::assimp "${_IMPORT_PREFIX}/lib/${staticLibraryName}" ) + list(APPEND _IMPORT_CHECK_FILES_FOR_assimp::assimp "${_IMPORT_PREFIX}/lib${LIBSUFFIX}/${staticLibraryName}" ) endif() endif() diff --git a/assimpTargets-release.cmake.in b/assimpTargets-release.cmake.in index 79b643a9a..ec2daf1ba 100644 --- a/assimpTargets-release.cmake.in +++ b/assimpTargets-release.cmake.in @@ -7,6 +7,14 @@ set(CMAKE_IMPORT_FILE_VERSION 1) set(ASSIMP_BUILD_SHARED_LIBS @BUILD_SHARED_LIBS@) +get_property(LIB64 GLOBAL PROPERTY FIND_LIBRARY_USE_LIB64_PATHS) + +if ("${LIB64}" STREQUAL "TRUE") + set(LIBSUFFIX 64) +else() + set(LIBSUFFIX "") +endif() + if(MSVC) if(MSVC_TOOLSET_VERSION) set(MSVC_PREFIX "vc${MSVC_TOOLSET_VERSION}") @@ -76,17 +84,17 @@ else() set_target_properties(assimp::assimp PROPERTIES IMPORTED_SONAME_RELEASE "${sharedLibraryName}" - IMPORTED_LOCATION_RELEASE "${_IMPORT_PREFIX}/lib/${sharedLibraryName}" + IMPORTED_LOCATION_RELEASE "${_IMPORT_PREFIX}/lib${LIBSUFFIX}/${sharedLibraryName}" ) list(APPEND _IMPORT_CHECK_TARGETS assimp::assimp ) - list(APPEND _IMPORT_CHECK_FILES_FOR_assimp::assimp "${_IMPORT_PREFIX}/lib/${sharedLibraryName}" ) + list(APPEND _IMPORT_CHECK_FILES_FOR_assimp::assimp "${_IMPORT_PREFIX}/lib${LIBSUFFIX}/${sharedLibraryName}" ) else() set(staticLibraryName "libassimp${ASSIMP_LIBRARY_SUFFIX}@CMAKE_STATIC_LIBRARY_SUFFIX@") set_target_properties(assimp::assimp PROPERTIES - IMPORTED_LOCATION_RELEASE "${_IMPORT_PREFIX}/lib/${staticLibraryName}" + IMPORTED_LOCATION_RELEASE "${_IMPORT_PREFIX}/lib${LIBSUFFIX}/${staticLibraryName}" ) list(APPEND _IMPORT_CHECK_TARGETS assimp::assimp ) - list(APPEND _IMPORT_CHECK_FILES_FOR_assimp::assimp "${_IMPORT_PREFIX}/lib/${staticLibraryName}" ) + list(APPEND _IMPORT_CHECK_FILES_FOR_assimp::assimp "${_IMPORT_PREFIX}/lib${LIBSUFFIX}/${staticLibraryName}" ) endif() endif() From ed5aab94958b629c9b0857c1717b884f1f030310 Mon Sep 17 00:00:00 2001 From: Marc-Antoine Lortie Date: Wed, 26 Feb 2020 12:19:06 -0500 Subject: [PATCH 080/330] Fixed and changed a few things. - Removed references to test models with relative path. - Fixed a compile warning. - Added usage message. --- samples/SimpleOpenGL/CMakeLists.txt | 18 +++-- samples/SimpleOpenGL/Sample_SimpleOpenGL.c | 79 +++++++++++++++++++--- 2 files changed, 81 insertions(+), 16 deletions(-) diff --git a/samples/SimpleOpenGL/CMakeLists.txt b/samples/SimpleOpenGL/CMakeLists.txt index 39593fdb9..6bc8e37e6 100644 --- a/samples/SimpleOpenGL/CMakeLists.txt +++ b/samples/SimpleOpenGL/CMakeLists.txt @@ -1,3 +1,5 @@ +SET(SAMPLE_PROJECT_NAME assimp_simpleogl) + FIND_PACKAGE(OpenGL) FIND_PACKAGE(GLUT) IF ( MSVC ) @@ -16,6 +18,10 @@ IF ( NOT GLUT_FOUND ) ENDIF () ENDIF () +# Used for usage and error messages in the program. +ADD_COMPILE_DEFINITIONS(ASSIMP_VERSION="${ASSIMP_VERSION}") +ADD_COMPILE_DEFINITIONS(PROJECT_NAME="${SAMPLE_PROJECT_NAME}") + if ( MSVC ) ADD_DEFINITIONS( -D_SCL_SECURE_NO_WARNINGS ) ADD_DEFINITIONS( -D_CRT_SECURE_NO_WARNINGS ) @@ -34,17 +40,17 @@ LINK_DIRECTORIES( ${Assimp_BINARY_DIR}/lib ) -ADD_EXECUTABLE( assimp_simpleogl +ADD_EXECUTABLE( ${SAMPLE_PROJECT_NAME} Sample_SimpleOpenGL.c ) -SET_PROPERTY(TARGET assimp_simpleogl PROPERTY DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX}) +SET_PROPERTY(TARGET ${SAMPLE_PROJECT_NAME} PROPERTY DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX}) -TARGET_LINK_LIBRARIES( assimp_simpleogl assimp ${OPENGL_LIBRARIES} ${GLUT_LIBRARIES} ${M_LIB} ) -SET_TARGET_PROPERTIES( assimp_simpleogl PROPERTIES - OUTPUT_NAME assimp_simpleogl +TARGET_LINK_LIBRARIES( ${SAMPLE_PROJECT_NAME} assimp ${OPENGL_LIBRARIES} ${GLUT_LIBRARIES} ${M_LIB} ) +SET_TARGET_PROPERTIES( ${SAMPLE_PROJECT_NAME} PROPERTIES + OUTPUT_NAME ${SAMPLE_PROJECT_NAME} ) -INSTALL( TARGETS assimp_simpleogl +INSTALL( TARGETS ${SAMPLE_PROJECT_NAME} DESTINATION "${ASSIMP_BIN_INSTALL_DIR}" COMPONENT assimp-dev ) diff --git a/samples/SimpleOpenGL/Sample_SimpleOpenGL.c b/samples/SimpleOpenGL/Sample_SimpleOpenGL.c index a8a3532cf..ac31d6f3e 100644 --- a/samples/SimpleOpenGL/Sample_SimpleOpenGL.c +++ b/samples/SimpleOpenGL/Sample_SimpleOpenGL.c @@ -25,6 +25,39 @@ #include #include +#define COMMAND_USAGE "--usage" + +/* ---------------------------------------------------------------------------- */ +inline static void print_run_command(const char* command_name) { + printf("Run '%s %s' for more information.\n", + PROJECT_NAME, command_name); +} + +/* ---------------------------------------------------------------------------- */ +inline static void print_error(const char* msg) { + printf("ERROR: %s\n", msg); +} + +#define NEW_LINE "\n" +#define DOUBLE_NEW_LINE NEW_LINE NEW_LINE + +/* ---------------------------------------------------------------------------- */ +inline static void print_usage() { + static const char* usage_format = + "Usage: " + PROJECT_NAME + " " DOUBLE_NEW_LINE + "where:" DOUBLE_NEW_LINE + " %-10s %s" DOUBLE_NEW_LINE + "options:" DOUBLE_NEW_LINE + " %-10s %s" DOUBLE_NEW_LINE; + printf(usage_format, + // where + "file", "The input model file to load.", + // options + COMMAND_USAGE, "Display usage."); +} + /* the global Assimp scene object */ const C_STRUCT aiScene* scene = NULL; GLuint scene_list = 0; @@ -245,7 +278,7 @@ void do_motion (void) static int frames = 0; int time = glutGet(GLUT_ELAPSED_TIME); - angle += (time-prev_time)*0.01; + angle += (float)((time-prev_time)*0.01); prev_time = time; frames += 1; @@ -324,8 +357,37 @@ int loadasset (const char* path) /* ---------------------------------------------------------------------------- */ int main(int argc, char **argv) { + const char* model_file = NULL; C_STRUCT aiLogStream stream; + if (argc < 2) { + print_error("No input model file specifed."); + print_run_command(COMMAND_USAGE); + return EXIT_FAILURE; + } + + // Find and execute available commands entered by the user. + for (int i = 1; i < argc; ++i) { + if (!strncmp(argv[i], COMMAND_USAGE, strlen(COMMAND_USAGE))) { + print_usage(); + return EXIT_SUCCESS; + } + } + + // Check and validate the specified model file extension. + model_file = argv[1]; + const char* extension = strchr(model_file, '.'); + if (!extension) { + print_error("Please provide a file with a valid extension."); + return EXIT_FAILURE; + } + + if (AI_FALSE == aiIsExtensionSupported(extension)) { + print_error("The specified model file extension is currently " + "unsupported in Assimp " ASSIMP_VERSION "."); + return EXIT_FAILURE; + } + glutInitWindowSize(900,600); glutInitWindowPosition(100,100); glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH); @@ -346,14 +408,11 @@ int main(int argc, char **argv) stream = aiGetPredefinedLogStream(aiDefaultLogStream_FILE,"assimp_log.txt"); aiAttachLogStream(&stream); - /* the model name can be specified on the command line. If none - is specified, we try to locate one of the more expressive test - models from the repository (/models-nonbsd may be missing in - some distributions so we need a fallback from /models!). */ - if( 0 != loadasset( argc >= 2 ? argv[1] : "../../test/models-nonbsd/X/dwarf.x")) { - if( argc != 1 || (0 != loadasset( "../../../../test/models-nonbsd/X/dwarf.x") && 0 != loadasset( "../../test/models/X/Testwuson.X"))) { - return -1; - } + // Load the model file. + if(0 != loadasset(model_file)) { + print_error("Failed to load model. Please ensure that the specified file exists."); + aiDetachAllLogStreams(); + return EXIT_FAILURE; } glClearColor(0.1f,0.1f,0.1f,1.f); @@ -384,5 +443,5 @@ int main(int argc, char **argv) again. This will definitely release the last resources allocated by Assimp.*/ aiDetachAllLogStreams(); - return 0; + return EXIT_SUCCESS; } From 22311883ce2aca0477f764bb300541f02834645f Mon Sep 17 00:00:00 2001 From: Sebastian Matusik Date: Fri, 28 Feb 2020 18:39:40 -0800 Subject: [PATCH 081/330] Fix for #3037 [FATAL] SplitByBoneCountProcess::SplitMesh goes into infinite loop --- code/Common/SplitByBoneCountProcess.cpp | 40 +++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/code/Common/SplitByBoneCountProcess.cpp b/code/Common/SplitByBoneCountProcess.cpp index b472cb359..e8e216478 100644 --- a/code/Common/SplitByBoneCountProcess.cpp +++ b/code/Common/SplitByBoneCountProcess.cpp @@ -51,6 +51,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include +#include using namespace Assimp; using namespace Assimp::Formatter; @@ -94,7 +95,10 @@ void SplitByBoneCountProcess::Execute( aiScene* pScene) bool isNecessary = false; for( unsigned int a = 0; a < pScene->mNumMeshes; ++a) if( pScene->mMeshes[a]->mNumBones > mMaxBoneCount ) + { isNecessary = true; + break; + } if( !isNecessary ) { @@ -155,7 +159,9 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vectormNumBones <= mMaxBoneCount ) + { return; + } // necessary optimisation: build a list of all affecting bones for each vertex // TODO: (thom) maybe add a custom allocator here to avoid allocating tens of thousands of small arrays @@ -165,7 +171,9 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vectormBones[a]; for( unsigned int b = 0; b < bone->mNumWeights; ++b) + { vertexBones[ bone->mWeights[b].mVertexId ].push_back( BoneWeight( a, bone->mWeights[b].mWeight)); + } } unsigned int numFacesHandled = 0; @@ -189,7 +197,9 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vectormFaces[a]; // check every vertex if its bones would still fit into the current submesh @@ -201,17 +211,27 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vector mMaxBoneCount) + { + throw DeadlyImportError("SplitByBoneCountProcess: Single face requires more bones than specified max bone count!"); + } // leave out the face if the new bones required for this face don't fit the bone count limit anymore if( numBones + newBonesAtCurrentFace.size() > mMaxBoneCount ) + { continue; + } // mark all new bones as necessary while( !newBonesAtCurrentFace.empty() ) @@ -219,7 +239,9 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vectormName.length > 0 ) + { newMesh->mName.Set( format() << pMesh->mName.data << "_sub" << poNewMeshes.size()); + } newMesh->mMaterialIndex = pMesh->mMaterialIndex; newMesh->mPrimitiveTypes = pMesh->mPrimitiveTypes; poNewMeshes.push_back( newMesh); @@ -247,7 +271,9 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vectormNumFaces = static_cast(subMeshFaces.size()); newMesh->mVertices = new aiVector3D[newMesh->mNumVertices]; if( pMesh->HasNormals() ) + { newMesh->mNormals = new aiVector3D[newMesh->mNumVertices]; + } if( pMesh->HasTangentsAndBitangents() ) { newMesh->mTangents = new aiVector3D[newMesh->mNumVertices]; @@ -256,13 +282,17 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vectorHasTextureCoords( a) ) + { newMesh->mTextureCoords[a] = new aiVector3D[newMesh->mNumVertices]; + } newMesh->mNumUVComponents[a] = pMesh->mNumUVComponents[a]; } for( unsigned int a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; ++a ) { if( pMesh->HasVertexColors( a) ) + { newMesh->mColors[a] = new aiColor4D[newMesh->mNumVertices]; + } } // and copy over the data, generating faces with linear indices along the way @@ -285,7 +315,9 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vectormVertices[nvi] = pMesh->mVertices[srcIndex]; if( pMesh->HasNormals() ) + { newMesh->mNormals[nvi] = pMesh->mNormals[srcIndex]; + } if( pMesh->HasTangentsAndBitangents() ) { newMesh->mTangents[nvi] = pMesh->mTangents[srcIndex]; @@ -294,12 +326,16 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vectorHasTextureCoords( c) ) + { newMesh->mTextureCoords[c][nvi] = pMesh->mTextureCoords[c][srcIndex]; + } } for( unsigned int c = 0; c < AI_MAX_NUMBER_OF_COLOR_SETS; ++c ) { if( pMesh->HasVertexColors( c) ) + { newMesh->mColors[c][nvi] = pMesh->mColors[c][srcIndex]; + } } nvi++; @@ -316,7 +352,9 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vectormNumBones; ++a ) { if( !isBoneUsed[a] ) + { continue; + } // create the new bone const aiBone* srcBone = pMesh->mBones[a]; @@ -340,7 +378,9 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vector::max() ) + { newMesh->mBones[newBoneIndex]->mNumWeights++; + } } } From 5f35d62d612fbc4af6a4dd48653192b08c0a26ad Mon Sep 17 00:00:00 2001 From: Sebastian Matusik Date: Fri, 28 Feb 2020 18:41:29 -0800 Subject: [PATCH 082/330] Fix for #3037 cause glTF2Importer creating bunch of bones with 0 for vertex with index 0 --- code/glTF2/glTF2Importer.cpp | 77 ++++++++++++++++++++---------------- 1 file changed, 42 insertions(+), 35 deletions(-) diff --git a/code/glTF2/glTF2Importer.cpp b/code/glTF2/glTF2Importer.cpp index 5e137ed79..34591a461 100644 --- a/code/glTF2/glTF2Importer.cpp +++ b/code/glTF2/glTF2Importer.cpp @@ -111,8 +111,9 @@ const aiImporterDesc *glTF2Importer::GetInfo() const { bool glTF2Importer::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /* checkSig */) const { const std::string &extension = GetExtension(pFile); - if (extension != "gltf" && extension != "glb") + if (extension != "gltf" && extension != "glb") { return false; + } if (pIOHandler) { glTF2::Asset asset(pIOHandler); @@ -323,8 +324,9 @@ static inline bool CheckValidFacesIndices(aiFace *faces, unsigned nFaces, unsign for (unsigned i = 0; i < nFaces; ++i) { for (unsigned j = 0; j < faces[i].mNumIndices; ++j) { unsigned idx = faces[i].mIndices[j]; - if (idx >= nVerts) + if (idx >= nVerts) { return false; + } } } return true; @@ -861,7 +863,19 @@ aiNode *ImportNode(aiScene *pScene, glTF2::Asset &r, std::vector & if (node.skin) { for (int primitiveNo = 0; primitiveNo < count; ++primitiveNo) { aiMesh *mesh = pScene->mMeshes[meshOffsets[mesh_idx] + primitiveNo]; - mesh->mNumBones = static_cast(node.skin->jointNames.size()); + unsigned int numBones =static_cast(node.skin->jointNames.size()); + + std::vector> weighting(numBones); + BuildVertexWeightMapping(node.meshes[0]->primitives[primitiveNo], weighting); + + unsigned int realNumBones = 0; + for (uint32_t i = 0; i < numBones; ++i) { + if (weighting[i].size() > 0) { + realNumBones++; + } + } + + mesh->mNumBones = static_cast(realNumBones); mesh->mBones = new aiBone *[mesh->mNumBones]; // GLTF and Assimp choose to store bone weights differently. @@ -873,43 +887,33 @@ aiNode *ImportNode(aiScene *pScene, glTF2::Asset &r, std::vector & // both because it's somewhat slow and because, for many applications, // we then need to reconvert the data back into the vertex-to-bone // mapping which makes things doubly-slow. - std::vector> weighting(mesh->mNumBones); - BuildVertexWeightMapping(node.meshes[0]->primitives[primitiveNo], weighting); mat4 *pbindMatrices = nullptr; node.skin->inverseBindMatrices->ExtractData(pbindMatrices); + + int cb = 0; + for (uint32_t i = 0; i < numBones; ++i) { + const std::vector &weights = weighting[i]; + if (weights.size() > 0) { + aiBone *bone = new aiBone(); - for (uint32_t i = 0; i < mesh->mNumBones; ++i) { - aiBone *bone = new aiBone(); - - Ref joint = node.skin->jointNames[i]; - if (!joint->name.empty()) { - bone->mName = joint->name; - } else { - // Assimp expects each bone to have a unique name. - static const std::string kDefaultName = "bone_"; - char postfix[10] = { 0 }; - ASSIMP_itoa10(postfix, i); - bone->mName = (kDefaultName + postfix); - } - GetNodeTransform(bone->mOffsetMatrix, *joint); - - CopyValue(pbindMatrices[i], bone->mOffsetMatrix); - - std::vector &weights = weighting[i]; - - bone->mNumWeights = static_cast(weights.size()); - if (bone->mNumWeights > 0) { + Ref joint = node.skin->jointNames[i]; + if (!joint->name.empty()) { + bone->mName = joint->name; + } else { + // Assimp expects each bone to have a unique name. + static const std::string kDefaultName = "bone_"; + char postfix[10] = { 0 }; + ASSIMP_itoa10(postfix, i); + bone->mName = (kDefaultName + postfix); + } + GetNodeTransform(bone->mOffsetMatrix, *joint); + CopyValue(pbindMatrices[i], bone->mOffsetMatrix); + bone->mNumWeights = static_cast(weights.size()); bone->mWeights = new aiVertexWeight[bone->mNumWeights]; memcpy(bone->mWeights, weights.data(), bone->mNumWeights * sizeof(aiVertexWeight)); - } else { - // Assimp expects all bones to have at least 1 weight. - bone->mWeights = new aiVertexWeight[1]; - bone->mNumWeights = 1; - bone->mWeights->mVertexId = 0; - bone->mWeights->mWeight = 0.f; + mesh->mBones[cb++] = bone; } - mesh->mBones[i] = bone; } if (pbindMatrices) { @@ -1232,8 +1236,9 @@ void glTF2Importer::ImportEmbeddedTextures(glTF2::Asset &r) { int numEmbeddedTexs = 0; for (size_t i = 0; i < r.images.Size(); ++i) { - if (r.images[i].HasData()) + if (r.images[i].HasData()) { numEmbeddedTexs += 1; + } } if (numEmbeddedTexs == 0) @@ -1244,7 +1249,9 @@ void glTF2Importer::ImportEmbeddedTextures(glTF2::Asset &r) { // Add the embedded textures for (size_t i = 0; i < r.images.Size(); ++i) { Image &img = r.images[i]; - if (!img.HasData()) continue; + if (!img.HasData()) { + continue; + } int idx = mScene->mNumTextures++; embeddedTexIdxs[i] = idx; From 496fcd35c19b8ae4521487ad6d498d5476f69cfa Mon Sep 17 00:00:00 2001 From: Sebastian Matusik Date: Fri, 28 Feb 2020 19:17:53 -0800 Subject: [PATCH 083/330] Trimmed trailing whitespaces --- code/Common/SplitByBoneCountProcess.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/Common/SplitByBoneCountProcess.cpp b/code/Common/SplitByBoneCountProcess.cpp index e8e216478..ab7a1fe00 100644 --- a/code/Common/SplitByBoneCountProcess.cpp +++ b/code/Common/SplitByBoneCountProcess.cpp @@ -224,7 +224,7 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vector mMaxBoneCount) - { + { throw DeadlyImportError("SplitByBoneCountProcess: Single face requires more bones than specified max bone count!"); } // leave out the face if the new bones required for this face don't fit the bone count limit anymore From 710dbba52dee0f4ac2f1e59a1f495ed287d88372 Mon Sep 17 00:00:00 2001 From: Sebastian Matusik Date: Fri, 28 Feb 2020 19:19:10 -0800 Subject: [PATCH 084/330] Trimmed trailing whitespaces --- code/glTF2/glTF2Importer.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/code/glTF2/glTF2Importer.cpp b/code/glTF2/glTF2Importer.cpp index 34591a461..8c33674e1 100644 --- a/code/glTF2/glTF2Importer.cpp +++ b/code/glTF2/glTF2Importer.cpp @@ -864,17 +864,17 @@ aiNode *ImportNode(aiScene *pScene, glTF2::Asset &r, std::vector & for (int primitiveNo = 0; primitiveNo < count; ++primitiveNo) { aiMesh *mesh = pScene->mMeshes[meshOffsets[mesh_idx] + primitiveNo]; unsigned int numBones =static_cast(node.skin->jointNames.size()); - + std::vector> weighting(numBones); BuildVertexWeightMapping(node.meshes[0]->primitives[primitiveNo], weighting); - + unsigned int realNumBones = 0; for (uint32_t i = 0; i < numBones; ++i) { if (weighting[i].size() > 0) { realNumBones++; } } - + mesh->mNumBones = static_cast(realNumBones); mesh->mBones = new aiBone *[mesh->mNumBones]; @@ -890,7 +890,7 @@ aiNode *ImportNode(aiScene *pScene, glTF2::Asset &r, std::vector & mat4 *pbindMatrices = nullptr; node.skin->inverseBindMatrices->ExtractData(pbindMatrices); - + int cb = 0; for (uint32_t i = 0; i < numBones; ++i) { const std::vector &weights = weighting[i]; From 920535165da40288f5603dded29404018f09d90c Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sun, 1 Mar 2020 13:15:45 +0100 Subject: [PATCH 085/330] next fixed warnings --- code/3DS/3DSHelper.h | 43 +- code/AC/ACLoader.cpp | 122 +- code/AC/ACLoader.h | 4 - code/Blender/BlenderLoader.cpp | 33 +- code/Blender/BlenderModifier.cpp | 188 +-- code/COB/COBLoader.cpp | 4 +- code/COB/COBScene.h | 4 +- code/Collada/ColladaParser.cpp | 11 +- code/FBX/FBXDocument.cpp | 26 +- code/Importer/IFC/IFCLoader.cpp | 588 +++---- code/Importer/IFC/IFCUtil.cpp | 5 +- code/Importer/STEPParser/STEPFileReader.cpp | 11 +- code/LWO/LWOLoader.cpp | 1093 ++++++------- code/LWO/LWOLoader.h | 10 +- code/LWO/LWOMaterial.cpp | 646 ++++---- code/LWS/LWSLoader.cpp | 424 +++-- code/M3D/M3DImporter.cpp | 1144 ++++++------- code/M3D/M3DWrapper.cpp | 4 + code/M3D/m3d.h | 11 +- code/MD5/MD5Loader.cpp | 406 +++-- code/MD5/MD5Loader.h | 55 +- code/MDL/HalfLife/HL1MDLLoader.cpp | 30 +- code/MDL/HalfLife/HL1MeshTrivert.h | 30 +- code/MDL/MDLMaterialLoader.cpp | 11 +- code/MS3D/MS3DLoader.cpp | 46 +- code/NFF/NFFLoader.cpp | 950 +++++------ code/NFF/NFFLoader.h | 4 +- code/Obj/ObjFileParser.cpp | 2 +- code/Ogre/OgreBinarySerializer.cpp | 4 +- code/Ogre/OgreImporter.cpp | 1 - code/Ogre/OgreMaterial.cpp | 12 +- code/Ogre/OgreParsingUtils.h | 42 +- code/Ogre/OgreXmlSerializer.cpp | 585 +++---- code/OpenGEX/OpenGEXImporter.cpp | 8 +- code/Ply/PlyLoader.cpp | 600 ++++--- code/PostProcessing/EmbedTexturesProcess.cpp | 2 +- code/PostProcessing/TextureTransform.cpp | 3 +- code/Q3D/Q3DLoader.cpp | 19 +- code/Step/STEPFile.h | 1537 +++++++++--------- code/XGL/XGLLoader.cpp | 23 +- include/assimp/ParsingUtils.h | 1 - 41 files changed, 4124 insertions(+), 4618 deletions(-) diff --git a/code/3DS/3DSHelper.h b/code/3DS/3DSHelper.h index 3ef9b8604..1448fe609 100644 --- a/code/3DS/3DSHelper.h +++ b/code/3DS/3DSHelper.h @@ -321,7 +321,7 @@ public: struct Face : public FaceWithSmoothingGroup { }; -#pragma warning(disable : 4315 ) +#pragma warning(disable : 4315) // --------------------------------------------------------------------------- /** Helper structure representing a texture */ @@ -341,6 +341,20 @@ struct Texture { mTextureBlend = get_qnan(); } + Texture(const Texture &other) : + mTextureBlend(other.mTextureBlend), + mMapName(other.mMapName), + mOffsetU(other.mOffsetU), + mOffsetV(other.mOffsetV), + mScaleU(other.mScaleU), + mScaleV(other.mScaleV), + mRotation(other.mRotation), + mMapMode(other.mMapMode), + bPrivate(other.bPrivate), + iUVSrc(other.iUVSrc) { + // empty + } + Texture(Texture &&other) AI_NO_EXCEPT : mTextureBlend(std::move(other.mTextureBlend)), mMapName(std::move(mMapName)), mOffsetU(std::move(mOffsetU)), @@ -400,18 +414,29 @@ struct Texture { /** Helper structure representing a 3ds material */ struct Material { //! Default constructor has been deleted - Material() = delete; - - //! Constructor with explicit name - explicit Material(const std::string &name) : - mName(name), mDiffuse(ai_real(0.6), ai_real(0.6), ai_real(0.6)) // FIX ... we won't want object to be black - , + Material() : + mName(), + mDiffuse(ai_real(0.6), ai_real(0.6), ai_real(0.6)), mSpecularExponent(ai_real(0.0)), mShininessStrength(ai_real(1.0)), mShading(Discreet3DS::Gouraud), mTransparency(ai_real(1.0)), mBumpHeight(ai_real(1.0)), mTwoSided(false) { + // empty + } + + //! Constructor with explicit name + explicit Material(const std::string &name) : + mName(name), + mDiffuse(ai_real(0.6), ai_real(0.6), ai_real(0.6)), + mSpecularExponent(ai_real(0.0)), + mShininessStrength(ai_real(1.0)), + mShading(Discreet3DS::Gouraud), + mTransparency(ai_real(1.0)), + mBumpHeight(ai_real(1.0)), + mTwoSided(false) { + // empty } Material(const Material &other) = default; @@ -468,7 +493,9 @@ struct Material { return *this; } - virtual ~Material() {} + virtual ~Material() { + // empty + } //! Name of the material std::string mName; diff --git a/code/AC/ACLoader.cpp b/code/AC/ACLoader.cpp index 196f26253..5a1ab5e7b 100644 --- a/code/AC/ACLoader.cpp +++ b/code/AC/ACLoader.cpp @@ -1,4 +1,3 @@ - /* --------------------------------------------------------------------------- Open Asset Import Library (assimp) @@ -6,8 +5,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2020, assimp team - - All rights reserved. Redistribution and use of this software in source and binary forms, @@ -80,47 +77,60 @@ static const aiImporterDesc desc = { // ------------------------------------------------------------------------------------------------ // skip to the next token -#define AI_AC_SKIP_TO_NEXT_TOKEN() \ - if (!SkipSpaces(&buffer)) { \ - ASSIMP_LOG_ERROR("AC3D: Unexpected EOF/EOL"); \ - continue; \ +inline +const char *AcSkipToNextToken( const char *buffer ) { + if (!SkipSpaces( &buffer )) { + ASSIMP_LOG_ERROR("AC3D: Unexpected EOF/EOL"); } + return buffer; +} // ------------------------------------------------------------------------------------------------ // read a string (may be enclosed in double quotation marks). buffer must point to " -#define AI_AC_GET_STRING(out) \ - if (*buffer == '\0') { \ - throw DeadlyImportError("AC3D: Unexpected EOF in string"); \ - } \ - ++buffer; \ - const char *sz = buffer; \ - while ('\"' != *buffer) { \ - if (IsLineEnd(*buffer)) { \ - ASSIMP_LOG_ERROR("AC3D: Unexpected EOF/EOL in string"); \ - out = "ERROR"; \ - break; \ - } \ - ++buffer; \ - } \ - if (IsLineEnd(*buffer)) continue; \ - out = std::string(sz, (unsigned int)(buffer - sz)); \ +inline +const char *AcGetString(const char *buffer, std::string &out) { + if (*buffer == '\0') { + throw DeadlyImportError("AC3D: Unexpected EOF in string"); + } ++buffer; + const char *sz = buffer; + while ('\"' != *buffer) { + if (IsLineEnd(*buffer)) { + ASSIMP_LOG_ERROR("AC3D: Unexpected EOF/EOL in string"); + out = "ERROR"; + break; + } + ++buffer; + } + if (IsLineEnd(*buffer)) { + return buffer; + } + out = std::string(sz, (unsigned int)(buffer - sz)); + ++buffer; + + return buffer; +} // ------------------------------------------------------------------------------------------------ // read 1 to n floats prefixed with an optional predefined identifier -#define AI_AC_CHECKED_LOAD_FLOAT_ARRAY(name, name_length, num, out) \ - AI_AC_SKIP_TO_NEXT_TOKEN(); \ - if (name_length) { \ - if (strncmp(buffer, name, name_length) || !IsSpace(buffer[name_length])) { \ - ASSIMP_LOG_ERROR("AC3D: Unexpexted token. " name " was expected."); \ - continue; \ - } \ - buffer += name_length + 1; \ - } \ - for (unsigned int _i = 0; _i < num; ++_i) { \ - AI_AC_SKIP_TO_NEXT_TOKEN(); \ - buffer = fast_atoreal_move(buffer, ((float *)out)[_i]); \ +template +inline +const char *TAcCheckedLoadFloatArray(const char *buffer, const char *name, size_t name_length, size_t num, T *out) { + AcSkipToNextToken(buffer); + if (0 != name_length) { + if (0 != strncmp(buffer, name, name_length) || !IsSpace(buffer[name_length])) { + ASSIMP_LOG_ERROR("AC3D: Unexpexted token. " + std::string( name ) + " was expected."); + return buffer; + } + buffer += name_length + 1; } + for (unsigned int _i = 0; _i < num; ++_i) { + AcSkipToNextToken(buffer); + buffer = fast_atoreal_move(buffer, ((float *)out)[_i]); + } + + return buffer; +} // ------------------------------------------------------------------------------------------------ // Constructor to be privately used by Importer @@ -222,7 +232,7 @@ void AC3DImporter::LoadObjectSection(std::vector &objects) { return; } else if (TokenMatch(buffer, "name", 4)) { SkipSpaces(&buffer); - AI_AC_GET_STRING(obj.name); + buffer = AcGetString(buffer, obj.name); // If this is a light source, we'll also need to store // the name of the node in it. @@ -231,21 +241,21 @@ void AC3DImporter::LoadObjectSection(std::vector &objects) { } } else if (TokenMatch(buffer, "texture", 7)) { SkipSpaces(&buffer); - AI_AC_GET_STRING(obj.texture); + buffer = AcGetString(buffer, obj.texture); } else if (TokenMatch(buffer, "texrep", 6)) { SkipSpaces(&buffer); - AI_AC_CHECKED_LOAD_FLOAT_ARRAY("", 0, 2, &obj.texRepeat); + buffer = TAcCheckedLoadFloatArray(buffer, "", 0, 2, &obj.texRepeat); if (!obj.texRepeat.x || !obj.texRepeat.y) obj.texRepeat = aiVector2D(1.f, 1.f); } else if (TokenMatch(buffer, "texoff", 6)) { SkipSpaces(&buffer); - AI_AC_CHECKED_LOAD_FLOAT_ARRAY("", 0, 2, &obj.texOffset); + buffer = TAcCheckedLoadFloatArray(buffer, "", 0, 2, &obj.texOffset); } else if (TokenMatch(buffer, "rot", 3)) { SkipSpaces(&buffer); - AI_AC_CHECKED_LOAD_FLOAT_ARRAY("", 0, 9, &obj.rotation); + buffer = TAcCheckedLoadFloatArray(buffer, "", 0, 9, &obj.rotation); } else if (TokenMatch(buffer, "loc", 3)) { SkipSpaces(&buffer); - AI_AC_CHECKED_LOAD_FLOAT_ARRAY("", 0, 3, &obj.translation); + buffer = TAcCheckedLoadFloatArray(buffer, "", 0, 3, &obj.translation); } else if (TokenMatch(buffer, "subdiv", 6)) { SkipSpaces(&buffer); obj.subDiv = strtoul10(buffer, &buffer); @@ -271,7 +281,7 @@ void AC3DImporter::LoadObjectSection(std::vector &objects) { } obj.vertices.push_back(aiVector3D()); aiVector3D &v = obj.vertices.back(); - AI_AC_CHECKED_LOAD_FLOAT_ARRAY("", 0, 3, &v.x); + buffer = TAcCheckedLoadFloatArray(buffer, "", 0, 3, &v.x); } } else if (TokenMatch(buffer, "numsurf", 7)) { SkipSpaces(&buffer); @@ -331,10 +341,9 @@ void AC3DImporter::LoadObjectSection(std::vector &objects) { entry.first = strtoul10(buffer, &buffer); SkipSpaces(&buffer); - AI_AC_CHECKED_LOAD_FLOAT_ARRAY("", 0, 2, &entry.second); + buffer = TAcCheckedLoadFloatArray(buffer, "", 0, 2, &entry.second); } } else { - --buffer; // make sure the line is processed a second time break; } @@ -496,7 +505,9 @@ aiNode *AC3DImporter::ConvertObjectSection(Object &object, const size_t oldm = meshes.size(); for (MatTable::const_iterator cit = needMat.begin(), cend = needMat.end(); cit != cend; ++cit, ++mat) { - if (!(*cit).first) continue; + if (!(*cit).first) { + continue; + } // allocate a new aiMesh object *pip++ = (unsigned int)meshes.size(); @@ -541,7 +552,8 @@ aiNode *AC3DImporter::ConvertObjectSection(Object &object, unsigned int type = (*it).flags & 0xf; if (!type) { aiFace &face = *faces++; - if ((face.mNumIndices = (unsigned int)src.entries.size())) { + face.mNumIndices = (unsigned int)src.entries.size(); + if (0 != face.mNumIndices) { face.mIndices = new unsigned int[face.mNumIndices]; for (unsigned int i = 0; i < face.mNumIndices; ++i, ++vertices) { const Surface::SurfaceEntry &entry = src.entries[i]; @@ -726,18 +738,18 @@ void AC3DImporter::InternReadFile(const std::string &pFile, // manually parse the material ... sscanf would use the buldin atof ... // Format: (name) rgb %f %f %f amb %f %f %f emis %f %f %f spec %f %f %f shi %d trans %f - AI_AC_SKIP_TO_NEXT_TOKEN(); + buffer = AcSkipToNextToken(buffer); if ('\"' == *buffer) { - AI_AC_GET_STRING(mat.name); - AI_AC_SKIP_TO_NEXT_TOKEN(); + buffer = AcGetString(buffer, mat.name); + buffer = AcSkipToNextToken(buffer); } - AI_AC_CHECKED_LOAD_FLOAT_ARRAY("rgb", 3, 3, &mat.rgb); - AI_AC_CHECKED_LOAD_FLOAT_ARRAY("amb", 3, 3, &mat.amb); - AI_AC_CHECKED_LOAD_FLOAT_ARRAY("emis", 4, 3, &mat.emis); - AI_AC_CHECKED_LOAD_FLOAT_ARRAY("spec", 4, 3, &mat.spec); - AI_AC_CHECKED_LOAD_FLOAT_ARRAY("shi", 3, 1, &mat.shin); - AI_AC_CHECKED_LOAD_FLOAT_ARRAY("trans", 5, 1, &mat.trans); + buffer = TAcCheckedLoadFloatArray(buffer, "rgb", 3, 3, &mat.rgb); + buffer = TAcCheckedLoadFloatArray(buffer, "amb", 3, 3, &mat.amb); + buffer = TAcCheckedLoadFloatArray(buffer, "emis", 4, 3, &mat.emis); + buffer = TAcCheckedLoadFloatArray(buffer, "spec", 4, 3, &mat.spec); + buffer = TAcCheckedLoadFloatArray(buffer, "shi", 3, 1, &mat.shin); + buffer = TAcCheckedLoadFloatArray(buffer, "trans", 5, 1, &mat.trans); } LoadObjectSection(rootObjects); } diff --git a/code/AC/ACLoader.h b/code/AC/ACLoader.h index 890fb2ac2..b32cc7ee3 100644 --- a/code/AC/ACLoader.h +++ b/code/AC/ACLoader.h @@ -68,8 +68,6 @@ public: AC3DImporter(); ~AC3DImporter(); - - // Represents an AC3D material struct Material { @@ -245,8 +243,6 @@ private: aiMaterial& matDest); private: - - // points to the next data line const char* buffer; diff --git a/code/Blender/BlenderLoader.cpp b/code/Blender/BlenderLoader.cpp index 93e6d1589..b4e07617a 100644 --- a/code/Blender/BlenderLoader.cpp +++ b/code/Blender/BlenderLoader.cpp @@ -429,7 +429,7 @@ void BlenderImporter::ResolveImage(aiMaterial* out, const Material* mat, const M name.length = 1+ ASSIMP_itoa10(name.data+1,static_cast(MAXLEN-1), static_cast(conv_data.textures->size())); conv_data.textures->push_back(new aiTexture()); - aiTexture* tex = conv_data.textures->back(); + aiTexture* curTex = conv_data.textures->back(); // usually 'img->name' will be the original file name of the embedded textures, // so we can extract the file extension from it. @@ -439,19 +439,19 @@ void BlenderImporter::ResolveImage(aiMaterial* out, const Material* mat, const M --s; } - tex->achFormatHint[0] = s+1>e ? '\0' : ::tolower( s[1] ); - tex->achFormatHint[1] = s+2>e ? '\0' : ::tolower( s[2] ); - tex->achFormatHint[2] = s+3>e ? '\0' : ::tolower( s[3] ); - tex->achFormatHint[3] = '\0'; + curTex->achFormatHint[0] = s + 1 > e ? '\0' : (char)::tolower(s[1]); + curTex->achFormatHint[1] = s + 2 > e ? '\0' : (char)::tolower(s[2]); + curTex->achFormatHint[2] = s + 3 > e ? '\0' : (char)::tolower(s[3]); + curTex->achFormatHint[3] = '\0'; // tex->mHeight = 0; - tex->mWidth = img->packedfile->size; - uint8_t* ch = new uint8_t[tex->mWidth]; + curTex->mWidth = img->packedfile->size; + uint8_t *ch = new uint8_t[curTex->mWidth]; conv_data.db.reader->SetCurrentPos(static_cast( img->packedfile->data->val)); - conv_data.db.reader->CopyAndAdvance(ch,tex->mWidth); + conv_data.db.reader->CopyAndAdvance(ch, curTex->mWidth); - tex->pcData = reinterpret_cast(ch); + curTex->pcData = reinterpret_cast(ch); LogInfo("Reading embedded texture, original file was "+std::string(img->name)); } else { @@ -1078,9 +1078,9 @@ void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, co const aiFace& f = out->mFaces[out->mNumFaces++]; aiVector3D* vo = &out->mTextureCoords[0][out->mNumVertices]; - for (unsigned int i = 0; i < f.mNumIndices; ++i,++vo,++out->mNumVertices) { - vo->x = v->uv[i][0]; - vo->y = v->uv[i][1]; + for (unsigned int j = 0; j < f.mNumIndices; ++j,++vo,++out->mNumVertices) { + vo->x = v->uv[j][0]; + vo->y = v->uv[j][1]; } } @@ -1098,8 +1098,7 @@ void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, co vo->x = uv.uv[0]; vo->y = uv.uv[1]; } - } - else { + } else { // create textureCoords for every mapped tex for (uint32_t m = 0; m < itMatTexUvMapping->second.size(); ++m) { const MLoopUV *tm = itMatTexUvMapping->second[m]; @@ -1139,9 +1138,9 @@ void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, co const aiFace& f = out->mFaces[out->mNumFaces++]; aiVector3D* vo = &out->mTextureCoords[0][out->mNumVertices]; - for (unsigned int i = 0; i < f.mNumIndices; ++i,++vo,++out->mNumVertices) { - vo->x = v->uv[i][0]; - vo->y = v->uv[i][1]; + for (unsigned int j = 0; j < f.mNumIndices; ++j,++vo,++out->mNumVertices) { + vo->x = v->uv[j][0]; + vo->y = v->uv[j][1]; } } } diff --git a/code/Blender/BlenderModifier.cpp b/code/Blender/BlenderModifier.cpp index 6f8a5d7ee..2d99fbbc9 100644 --- a/code/Blender/BlenderModifier.cpp +++ b/code/Blender/BlenderModifier.cpp @@ -57,52 +57,51 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. using namespace Assimp; using namespace Assimp::Blender; -template BlenderModifier* god() { +template +BlenderModifier *god() { return new T(); } // add all available modifiers here -typedef BlenderModifier* (*fpCreateModifier)(); +typedef BlenderModifier *(*fpCreateModifier)(); static const fpCreateModifier creators[] = { - &god, - &god, + &god, + &god, - NULL // sentinel + NULL // sentinel }; // ------------------------------------------------------------------------------------------------ -struct SharedModifierData : ElemBase -{ +struct SharedModifierData : ElemBase { ModifierData modifier; }; // ------------------------------------------------------------------------------------------------ -void BlenderModifierShowcase::ApplyModifiers(aiNode& out, ConversionData& conv_data, const Scene& in, const Object& orig_object ) -{ +void BlenderModifierShowcase::ApplyModifiers(aiNode &out, ConversionData &conv_data, const Scene &in, const Object &orig_object) { size_t cnt = 0u, ful = 0u; // NOTE: this cast is potentially unsafe by design, so we need to perform type checks before // we're allowed to dereference the pointers without risking to crash. We might still be // invoking UB btw - we're assuming that the ModifierData member of the respective modifier // structures is at offset sizeof(vftable) with no padding. - const SharedModifierData* cur = static_cast ( orig_object.modifiers.first.get() ); - for (; cur; cur = static_cast ( cur->modifier.next.get() ), ++ful) { + const SharedModifierData *cur = static_cast(orig_object.modifiers.first.get()); + for (; cur; cur = static_cast(cur->modifier.next.get()), ++ful) { ai_assert(cur->dna_type); - const Structure* s = conv_data.db.dna.Get( cur->dna_type ); + const Structure *s = conv_data.db.dna.Get(cur->dna_type); if (!s) { - ASSIMP_LOG_WARN_F("BlendModifier: could not resolve DNA name: ",cur->dna_type); + ASSIMP_LOG_WARN_F("BlendModifier: could not resolve DNA name: ", cur->dna_type); continue; } // this is a common trait of all XXXMirrorData structures in BlenderDNA - const Field* f = s->Get("modifier"); + const Field *f = s->Get("modifier"); if (!f || f->offset != 0) { ASSIMP_LOG_WARN("BlendModifier: expected a `modifier` member at offset 0"); continue; } - s = conv_data.db.dna.Get( f->type ); + s = conv_data.db.dna.Get(f->type); if (!s || s->name != "ModifierData") { ASSIMP_LOG_WARN("BlendModifier: expected a ModifierData structure as first member"); continue; @@ -110,22 +109,22 @@ void BlenderModifierShowcase::ApplyModifiers(aiNode& out, ConversionData& conv_d // now, we can be sure that we should be fine to dereference *cur* as // ModifierData (with the above note). - const ModifierData& dat = cur->modifier; + const ModifierData &dat = cur->modifier; - const fpCreateModifier* curgod = creators; - std::vector< BlenderModifier* >::iterator curmod = cached_modifiers->begin(), endmod = cached_modifiers->end(); + const fpCreateModifier *curgod = creators; + std::vector::iterator curmod = cached_modifiers->begin(), endmod = cached_modifiers->end(); - for (;*curgod;++curgod,++curmod) { // allocate modifiers on the fly + for (; *curgod; ++curgod, ++curmod) { // allocate modifiers on the fly if (curmod == endmod) { cached_modifiers->push_back((*curgod)()); endmod = cached_modifiers->end(); - curmod = endmod-1; + curmod = endmod - 1; } - BlenderModifier* const modifier = *curmod; - if(modifier->IsActive(dat)) { - modifier->DoIt(out,conv_data,*static_cast(cur),in,orig_object); + BlenderModifier *const modifier = *curmod; + if (modifier->IsActive(dat)) { + modifier->DoIt(out, conv_data, *static_cast(cur), in, orig_object); cnt++; curgod = NULL; @@ -133,7 +132,7 @@ void BlenderModifierShowcase::ApplyModifiers(aiNode& out, ConversionData& conv_d } } if (curgod) { - ASSIMP_LOG_WARN_F("Couldn't find a handler for modifier: ",dat.name); + ASSIMP_LOG_WARN_F("Couldn't find a handler for modifier: ", dat.name); } } @@ -141,26 +140,22 @@ void BlenderModifierShowcase::ApplyModifiers(aiNode& out, ConversionData& conv_d // object, we still can't say whether our modifier implementations were // able to fully do their job. if (ful) { - ASSIMP_LOG_DEBUG_F("BlendModifier: found handlers for ",cnt," of ",ful," modifiers on `",orig_object.id.name, - "`, check log messages above for errors"); + ASSIMP_LOG_DEBUG_F("BlendModifier: found handlers for ", cnt, " of ", ful, " modifiers on `", orig_object.id.name, + "`, check log messages above for errors"); } } - - // ------------------------------------------------------------------------------------------------ -bool BlenderModifier_Mirror :: IsActive (const ModifierData& modin) -{ +bool BlenderModifier_Mirror ::IsActive(const ModifierData &modin) { return modin.type == ModifierData::eModifierType_Mirror; } // ------------------------------------------------------------------------------------------------ -void BlenderModifier_Mirror :: DoIt(aiNode& out, ConversionData& conv_data, const ElemBase& orig_modifier, - const Scene& /*in*/, - const Object& orig_object ) -{ +void BlenderModifier_Mirror ::DoIt(aiNode &out, ConversionData &conv_data, const ElemBase &orig_modifier, + const Scene & /*in*/, + const Object &orig_object) { // hijacking the ABI, see the big note in BlenderModifierShowcase::ApplyModifiers() - const MirrorModifierData& mir = static_cast(orig_modifier); + const MirrorModifierData &mir = static_cast(orig_modifier); ai_assert(mir.modifier.type == ModifierData::eModifierType_Mirror); conv_data.meshes->reserve(conv_data.meshes->size() + out.mNumMeshes); @@ -169,48 +164,55 @@ void BlenderModifier_Mirror :: DoIt(aiNode& out, ConversionData& conv_data, co // take all input meshes and clone them for (unsigned int i = 0; i < out.mNumMeshes; ++i) { - aiMesh* mesh; - SceneCombiner::Copy(&mesh,conv_data.meshes[out.mMeshes[i]]); + aiMesh *mesh; + SceneCombiner::Copy(&mesh, conv_data.meshes[out.mMeshes[i]]); const float xs = mir.flag & MirrorModifierData::Flags_AXIS_X ? -1.f : 1.f; const float ys = mir.flag & MirrorModifierData::Flags_AXIS_Y ? -1.f : 1.f; const float zs = mir.flag & MirrorModifierData::Flags_AXIS_Z ? -1.f : 1.f; if (mir.mirror_ob) { - const aiVector3D center( mir.mirror_ob->obmat[3][0],mir.mirror_ob->obmat[3][1],mir.mirror_ob->obmat[3][2] ); - for (unsigned int i = 0; i < mesh->mNumVertices; ++i) { - aiVector3D& v = mesh->mVertices[i]; + const aiVector3D center(mir.mirror_ob->obmat[3][0], mir.mirror_ob->obmat[3][1], mir.mirror_ob->obmat[3][2]); + for (unsigned int j = 0; j < mesh->mNumVertices; ++j) { + aiVector3D &v = mesh->mVertices[j]; - v.x = center.x + xs*(center.x - v.x); - v.y = center.y + ys*(center.y - v.y); - v.z = center.z + zs*(center.z - v.z); + v.x = center.x + xs * (center.x - v.x); + v.y = center.y + ys * (center.y - v.y); + v.z = center.z + zs * (center.z - v.z); } - } - else { - for (unsigned int i = 0; i < mesh->mNumVertices; ++i) { - aiVector3D& v = mesh->mVertices[i]; - v.x *= xs;v.y *= ys;v.z *= zs; + } else { + for (unsigned int j = 0; j < mesh->mNumVertices; ++j) { + aiVector3D &v = mesh->mVertices[j]; + v.x *= xs; + v.y *= ys; + v.z *= zs; } } if (mesh->mNormals) { - for (unsigned int i = 0; i < mesh->mNumVertices; ++i) { - aiVector3D& v = mesh->mNormals[i]; - v.x *= xs;v.y *= ys;v.z *= zs; + for (unsigned int j = 0; j < mesh->mNumVertices; ++j) { + aiVector3D &v = mesh->mNormals[j]; + v.x *= xs; + v.y *= ys; + v.z *= zs; } } if (mesh->mTangents) { - for (unsigned int i = 0; i < mesh->mNumVertices; ++i) { - aiVector3D& v = mesh->mTangents[i]; - v.x *= xs;v.y *= ys;v.z *= zs; + for (unsigned int j = 0; j < mesh->mNumVertices; ++j) { + aiVector3D &v = mesh->mTangents[j]; + v.x *= xs; + v.y *= ys; + v.z *= zs; } } if (mesh->mBitangents) { - for (unsigned int i = 0; i < mesh->mNumVertices; ++i) { - aiVector3D& v = mesh->mBitangents[i]; - v.x *= xs;v.y *= ys;v.z *= zs; + for (unsigned int j = 0; j < mesh->mNumVertices; ++j) { + aiVector3D &v = mesh->mBitangents[j]; + v.x *= xs; + v.y *= ys; + v.z *= zs; } } @@ -218,82 +220,80 @@ void BlenderModifier_Mirror :: DoIt(aiNode& out, ConversionData& conv_data, co const float vs = mir.flag & MirrorModifierData::Flags_MIRROR_V ? -1.f : 1.f; for (unsigned int n = 0; mesh->HasTextureCoords(n); ++n) { - for (unsigned int i = 0; i < mesh->mNumVertices; ++i) { - aiVector3D& v = mesh->mTextureCoords[n][i]; - v.x *= us;v.y *= vs; + for (unsigned int j = 0; j < mesh->mNumVertices; ++j) { + aiVector3D &v = mesh->mTextureCoords[n][j]; + v.x *= us; + v.y *= vs; } } // Only reverse the winding order if an odd number of axes were mirrored. if (xs * ys * zs < 0) { - for( unsigned int i = 0; i < mesh->mNumFaces; i++) { - aiFace& face = mesh->mFaces[i]; - for( unsigned int fi = 0; fi < face.mNumIndices / 2; ++fi) - std::swap( face.mIndices[fi], face.mIndices[face.mNumIndices - 1 - fi]); + for (unsigned int j = 0; j < mesh->mNumFaces; ++j ) { + aiFace &face = mesh->mFaces[j]; + for (unsigned int fi = 0; fi < face.mNumIndices / 2; ++fi) + std::swap(face.mIndices[fi], face.mIndices[face.mNumIndices - 1 - fi]); } } conv_data.meshes->push_back(mesh); } - unsigned int* nind = new unsigned int[out.mNumMeshes*2]; + unsigned int *nind = new unsigned int[out.mNumMeshes * 2]; - std::copy(out.mMeshes,out.mMeshes+out.mNumMeshes,nind); - std::transform(out.mMeshes,out.mMeshes+out.mNumMeshes,nind+out.mNumMeshes, - [&out](unsigned int n) { return out.mNumMeshes + n; }); + std::copy(out.mMeshes, out.mMeshes + out.mNumMeshes, nind); + std::transform(out.mMeshes, out.mMeshes + out.mNumMeshes, nind + out.mNumMeshes, + [&out](unsigned int n) { return out.mNumMeshes + n; }); delete[] out.mMeshes; out.mMeshes = nind; out.mNumMeshes *= 2; ASSIMP_LOG_INFO_F("BlendModifier: Applied the `Mirror` modifier to `", - orig_object.id.name,"`"); + orig_object.id.name, "`"); } // ------------------------------------------------------------------------------------------------ -bool BlenderModifier_Subdivision :: IsActive (const ModifierData& modin) -{ +bool BlenderModifier_Subdivision ::IsActive(const ModifierData &modin) { return modin.type == ModifierData::eModifierType_Subsurf; } // ------------------------------------------------------------------------------------------------ -void BlenderModifier_Subdivision :: DoIt(aiNode& out, ConversionData& conv_data, const ElemBase& orig_modifier, - const Scene& /*in*/, - const Object& orig_object ) -{ +void BlenderModifier_Subdivision ::DoIt(aiNode &out, ConversionData &conv_data, const ElemBase &orig_modifier, + const Scene & /*in*/, + const Object &orig_object) { // hijacking the ABI, see the big note in BlenderModifierShowcase::ApplyModifiers() - const SubsurfModifierData& mir = static_cast(orig_modifier); + const SubsurfModifierData &mir = static_cast(orig_modifier); ai_assert(mir.modifier.type == ModifierData::eModifierType_Subsurf); Subdivider::Algorithm algo; - switch (mir.subdivType) - { - case SubsurfModifierData::TYPE_CatmullClarke: - algo = Subdivider::CATMULL_CLARKE; - break; + switch (mir.subdivType) { + case SubsurfModifierData::TYPE_CatmullClarke: + algo = Subdivider::CATMULL_CLARKE; + break; - case SubsurfModifierData::TYPE_Simple: - ASSIMP_LOG_WARN("BlendModifier: The `SIMPLE` subdivision algorithm is not currently implemented, using Catmull-Clarke"); - algo = Subdivider::CATMULL_CLARKE; - break; + case SubsurfModifierData::TYPE_Simple: + ASSIMP_LOG_WARN("BlendModifier: The `SIMPLE` subdivision algorithm is not currently implemented, using Catmull-Clarke"); + algo = Subdivider::CATMULL_CLARKE; + break; - default: - ASSIMP_LOG_WARN_F("BlendModifier: Unrecognized subdivision algorithm: ",mir.subdivType); - return; + default: + ASSIMP_LOG_WARN_F("BlendModifier: Unrecognized subdivision algorithm: ", mir.subdivType); + return; }; std::unique_ptr subd(Subdivider::Create(algo)); ai_assert(subd); - if ( conv_data.meshes->empty() ) { + if (conv_data.meshes->empty()) { return; } - aiMesh** const meshes = &conv_data.meshes[conv_data.meshes->size() - out.mNumMeshes]; - std::unique_ptr tempmeshes(new aiMesh*[out.mNumMeshes]()); + aiMesh **const meshes = &conv_data.meshes[conv_data.meshes->size() - out.mNumMeshes]; + std::unique_ptr tempmeshes(new aiMesh *[out.mNumMeshes]()); - subd->Subdivide(meshes,out.mNumMeshes,tempmeshes.get(),std::max( mir.renderLevels, mir.levels ),true); - std::copy(tempmeshes.get(),tempmeshes.get()+out.mNumMeshes,meshes); + subd->Subdivide(meshes, out.mNumMeshes, tempmeshes.get(), std::max(mir.renderLevels, mir.levels), true); + std::copy(tempmeshes.get(), tempmeshes.get() + out.mNumMeshes, meshes); ASSIMP_LOG_INFO_F("BlendModifier: Applied the `Subdivision` modifier to `", - orig_object.id.name,"`"); + orig_object.id.name, "`"); } #endif // ASSIMP_BUILD_NO_BLEND_IMPORTER diff --git a/code/COB/COBLoader.cpp b/code/COB/COBLoader.cpp index 8e7c81192..b9ea8aff5 100644 --- a/code/COB/COBLoader.cpp +++ b/code/COB/COBLoader.cpp @@ -1015,8 +1015,8 @@ void COBImporter::ReadPolH_Binary(COB::Scene& out, StreamReaderLE& reader, const // XXX backface culling flag is 0x10 in flags // hole? - bool hole; - if ((hole = (reader.GetI1() & 0x08) != 0)) { + bool hole = (reader.GetI1() & 0x08) != 0; + if ( hole ) { // XXX Basically this should just work fine - then triangulator // should output properly triangulated data even for polygons // with holes. Test data specific to COB is needed to confirm it. diff --git a/code/COB/COBScene.h b/code/COB/COBScene.h index 87f4f4570..ef2f6dc1a 100644 --- a/code/COB/COBScene.h +++ b/code/COB/COBScene.h @@ -75,10 +75,10 @@ struct Face // ------------------ /** COB chunk header information */ +const unsigned int NO_SIZE = UINT_MAX; + struct ChunkInfo { - enum {NO_SIZE=UINT_MAX}; - ChunkInfo () : id (0) , parent_id (0) diff --git a/code/Collada/ColladaParser.cpp b/code/Collada/ColladaParser.cpp index d0f71d95a..25ee2bc3c 100644 --- a/code/Collada/ColladaParser.cpp +++ b/code/Collada/ColladaParser.cpp @@ -714,8 +714,8 @@ void ColladaParser::ReadAnimation(Collada::Animation* pParent) else if (IsElement("sampler")) { // read the ID to assign the corresponding collada channel afterwards. - int indexID = GetAttribute("id"); - std::string id = mReader->getAttributeValue(indexID); + int indexId = GetAttribute("id"); + std::string id = mReader->getAttributeValue(indexId); ChannelMap::iterator newChannel = channels.insert(std::make_pair(id, AnimationChannel())).first; // have it read into a channel @@ -3339,13 +3339,12 @@ void ColladaParser::TestClosing(const char* pName) { // Returns the index of the named attribute or -1 if not found. Does not throw, therefore useful for optional attributes int ColladaParser::GetAttribute(const char* pAttr) const { int index = TestAttribute(pAttr); - if (index != -1) { - return index; + if (index == -1) { + ThrowException(format() << "Expected attribute \"" << pAttr << "\" for element <" << mReader->getNodeName() << ">."); } // attribute not found -> throw an exception - ThrowException(format() << "Expected attribute \"" << pAttr << "\" for element <" << mReader->getNodeName() << ">."); - return -1; + return index; } // ------------------------------------------------------------------------------------------------ diff --git a/code/FBX/FBXDocument.cpp b/code/FBX/FBXDocument.cpp index ddb971b3f..5940f3cfa 100644 --- a/code/FBX/FBXDocument.cpp +++ b/code/FBX/FBXDocument.cpp @@ -428,8 +428,8 @@ void Document::ReadPropertyTemplates() const ElementCollection otypes = sdefs.GetCollection("ObjectType"); for(ElementMap::const_iterator it = otypes.first; it != otypes.second; ++it) { const Element& el = *(*it).second; - const Scope* sc = el.Compound(); - if(!sc) { + const Scope* curSc = el.Compound(); + if (!curSc) { DOMWarning("expected nested scope in ObjectType, ignoring",&el); continue; } @@ -442,24 +442,24 @@ void Document::ReadPropertyTemplates() const std::string& oname = ParseTokenAsString(*tok[0]); - const ElementCollection templs = sc->GetCollection("PropertyTemplate"); - for(ElementMap::const_iterator it = templs.first; it != templs.second; ++it) { - const Element& el = *(*it).second; - const Scope* sc = el.Compound(); - if(!sc) { + const ElementCollection templs = curSc->GetCollection("PropertyTemplate"); + for (ElementMap::const_iterator elemIt = templs.first; elemIt != templs.second; ++elemIt) { + const Element &innerEl = *(*elemIt).second; + const Scope *innerSc = innerEl.Compound(); + if (!innerSc) { DOMWarning("expected nested scope in PropertyTemplate, ignoring",&el); continue; } - const TokenList& tok = el.Tokens(); - if(tok.empty()) { + const TokenList &curTok = innerEl.Tokens(); + if (curTok.empty()) { DOMWarning("expected name for PropertyTemplate element, ignoring",&el); continue; } - const std::string& pname = ParseTokenAsString(*tok[0]); + const std::string &pname = ParseTokenAsString(*curTok[0]); - const Element* Properties70 = (*sc)["Properties70"]; + const Element *Properties70 = (*innerSc)["Properties70"]; if(Properties70) { std::shared_ptr props = std::make_shared( *Properties70,std::shared_ptr(static_cast(NULL)) @@ -529,8 +529,8 @@ const std::vector& Document::AnimationStacks() const animationStacksResolved.reserve(animationStacks.size()); for(uint64_t id : animationStacks) { LazyObject* const lazy = GetObject(id); - const AnimationStack* stack; - if(!lazy || !(stack = lazy->Get())) { + const AnimationStack *stack = lazy->Get(); + if(!lazy || nullptr == stack ) { DOMWarning("failed to read AnimationStack object"); continue; } diff --git a/code/Importer/IFC/IFCLoader.cpp b/code/Importer/IFC/IFCLoader.cpp index 5dd19f320..b96733c68 100644 --- a/code/Importer/IFC/IFCLoader.cpp +++ b/code/Importer/IFC/IFCLoader.cpp @@ -44,7 +44,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * @brief Implementation of the Industry Foundation Classes loader. */ - #ifndef ASSIMP_BUILD_NO_IFC_IMPORTER #include @@ -52,31 +51,30 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #ifndef ASSIMP_BUILD_NO_COMPRESSED_IFC -# ifdef ASSIMP_USE_HUNTER -# include -# else -# include -# endif +#ifdef ASSIMP_USE_HUNTER +#include +#else +#include +#endif #endif -#include "IFCLoader.h" #include "../STEPParser/STEPFileReader.h" +#include "IFCLoader.h" #include "IFCUtil.h" #include +#include #include #include -#include - namespace Assimp { - template<> const char* LogFunctions::Prefix() - { - static auto prefix = "IFC: "; - return prefix; - } +template <> +const char *LogFunctions::Prefix() { + static auto prefix = "IFC: "; + return prefix; } +} // namespace Assimp using namespace Assimp; using namespace Assimp::Formatter; @@ -98,15 +96,14 @@ using namespace Assimp::IFC; namespace { - // forward declarations -void SetUnits(ConversionData& conv); -void SetCoordinateSpace(ConversionData& conv); -void ProcessSpatialStructures(ConversionData& conv); -void MakeTreeRelative(ConversionData& conv); -void ConvertUnit(const ::Assimp::STEP::EXPRESS::DataType& dt,ConversionData& conv); +void SetUnits(ConversionData &conv); +void SetCoordinateSpace(ConversionData &conv); +void ProcessSpatialStructures(ConversionData &conv); +void MakeTreeRelative(ConversionData &conv); +void ConvertUnit(const ::Assimp::STEP::EXPRESS::DataType &dt, ConversionData &conv); -} // anon +} // namespace static const aiImporterDesc desc = { "Industry Foundation Classes (IFC) Importer", @@ -121,31 +118,27 @@ static const aiImporterDesc desc = { "ifc ifczip stp" }; - // ------------------------------------------------------------------------------------------------ // Constructor to be privately used by Importer -IFCImporter::IFCImporter() -{} +IFCImporter::IFCImporter() {} // ------------------------------------------------------------------------------------------------ // Destructor, private as well -IFCImporter::~IFCImporter() -{ +IFCImporter::~IFCImporter() { } // ------------------------------------------------------------------------------------------------ // Returns whether the class can handle the format of the given file. -bool IFCImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const -{ - const std::string& extension = GetExtension(pFile); - if (extension == "ifc" || extension == "ifczip" ) { +bool IFCImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const { + const std::string &extension = GetExtension(pFile); + if (extension == "ifc" || extension == "ifczip") { return true; - } else if ((!extension.length() || checkSig) && pIOHandler) { + } else if ((!extension.length() || checkSig) && pIOHandler) { // note: this is the common identification for STEP-encoded files, so // it is only unambiguous as long as we don't support any further // file formats with STEP as their encoding. - const char* tokens[] = {"ISO-10303-21"}; - const bool found( SearchFileHeaderForToken( pIOHandler, pFile, tokens, 1 ) ); + const char *tokens[] = { "ISO-10303-21" }; + const bool found(SearchFileHeaderForToken(pIOHandler, pFile, tokens, 1)); return found; } return false; @@ -153,94 +146,86 @@ bool IFCImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool // ------------------------------------------------------------------------------------------------ // List all extensions handled by this loader -const aiImporterDesc* IFCImporter::GetInfo () const -{ +const aiImporterDesc *IFCImporter::GetInfo() const { return &desc; } // ------------------------------------------------------------------------------------------------ // Setup configuration properties for the loader -void IFCImporter::SetupProperties(const Importer* pImp) -{ - settings.skipSpaceRepresentations = pImp->GetPropertyBool(AI_CONFIG_IMPORT_IFC_SKIP_SPACE_REPRESENTATIONS,true); - settings.useCustomTriangulation = pImp->GetPropertyBool(AI_CONFIG_IMPORT_IFC_CUSTOM_TRIANGULATION,true); - settings.conicSamplingAngle = std::min(std::max((float) pImp->GetPropertyFloat(AI_CONFIG_IMPORT_IFC_SMOOTHING_ANGLE, AI_IMPORT_IFC_DEFAULT_SMOOTHING_ANGLE), 5.0f), 120.0f); - settings.cylindricalTessellation = std::min(std::max(pImp->GetPropertyInteger(AI_CONFIG_IMPORT_IFC_CYLINDRICAL_TESSELLATION, AI_IMPORT_IFC_DEFAULT_CYLINDRICAL_TESSELLATION), 3), 180); - settings.skipAnnotations = true; +void IFCImporter::SetupProperties(const Importer *pImp) { + settings.skipSpaceRepresentations = pImp->GetPropertyBool(AI_CONFIG_IMPORT_IFC_SKIP_SPACE_REPRESENTATIONS, true); + settings.useCustomTriangulation = pImp->GetPropertyBool(AI_CONFIG_IMPORT_IFC_CUSTOM_TRIANGULATION, true); + settings.conicSamplingAngle = std::min(std::max((float)pImp->GetPropertyFloat(AI_CONFIG_IMPORT_IFC_SMOOTHING_ANGLE, AI_IMPORT_IFC_DEFAULT_SMOOTHING_ANGLE), 5.0f), 120.0f); + settings.cylindricalTessellation = std::min(std::max(pImp->GetPropertyInteger(AI_CONFIG_IMPORT_IFC_CYLINDRICAL_TESSELLATION, AI_IMPORT_IFC_DEFAULT_CYLINDRICAL_TESSELLATION), 3), 180); + settings.skipAnnotations = true; } - // ------------------------------------------------------------------------------------------------ // Imports the given file into the given scene structure. -void IFCImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) -{ +void IFCImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) { std::shared_ptr stream(pIOHandler->Open(pFile)); if (!stream) { ThrowException("Could not open file for reading"); } - // if this is a ifczip file, decompress its contents first - if(GetExtension(pFile) == "ifczip") { + if (GetExtension(pFile) == "ifczip") { #ifndef ASSIMP_BUILD_NO_COMPRESSED_IFC - unzFile zip = unzOpen( pFile.c_str() ); - if(zip == NULL) { + unzFile zip = unzOpen(pFile.c_str()); + if (zip == NULL) { ThrowException("Could not open ifczip file for reading, unzip failed"); } // chop 'zip' postfix - std::string fileName = pFile.substr(0,pFile.length() - 3); + std::string fileName = pFile.substr(0, pFile.length() - 3); std::string::size_type s = pFile.find_last_of('\\'); - if(s == std::string::npos) { + if (s == std::string::npos) { s = pFile.find_last_of('/'); } - if(s != std::string::npos) { - fileName = fileName.substr(s+1); + if (s != std::string::npos) { + fileName = fileName.substr(s + 1); } // search file (same name as the IFCZIP except for the file extension) and place file pointer there - if(UNZ_OK == unzGoToFirstFile(zip)) { + if (UNZ_OK == unzGoToFirstFile(zip)) { do { // get file size, etc. unz_file_info fileInfo; char filename[256]; - unzGetCurrentFileInfo( zip , &fileInfo, filename, sizeof(filename), 0, 0, 0, 0 ); + unzGetCurrentFileInfo(zip, &fileInfo, filename, sizeof(filename), 0, 0, 0, 0); if (GetExtension(filename) != "ifc") { continue; } - uint8_t* buff = new uint8_t[fileInfo.uncompressed_size]; + uint8_t *buff = new uint8_t[fileInfo.uncompressed_size]; LogInfo("Decompressing IFCZIP file"); unzOpenCurrentFile(zip); size_t total = 0; int read = 0; do { int bufferSize = fileInfo.uncompressed_size < INT16_MAX ? fileInfo.uncompressed_size : INT16_MAX; - void* buffer = malloc(bufferSize); + void *buffer = malloc(bufferSize); read = unzReadCurrentFile(zip, buffer, bufferSize); if (read > 0) { - memcpy((char*)buff + total, buffer, read); + memcpy((char *)buff + total, buffer, read); total += read; } free(buffer); } while (read > 0); size_t filesize = fileInfo.uncompressed_size; - if (total == 0 || size_t(total) != filesize) - { + if (total == 0 || size_t(total) != filesize) { delete[] buff; ThrowException("Failed to decompress IFC ZIP file"); } - unzCloseCurrentFile( zip ); - stream.reset(new MemoryIOStream(buff,fileInfo.uncompressed_size,true)); - break; - + unzCloseCurrentFile(zip); + stream.reset(new MemoryIOStream(buff, fileInfo.uncompressed_size, true)); if (unzGoToNextFile(zip) == UNZ_END_OF_LIST_OF_FILE) { ThrowException("Found no IFC file member in IFCZIP file (1)"); } + break; - } while(true); - } - else { + } while (true); + } else { ThrowException("Found no IFC file member in IFCZIP file (2)"); } @@ -251,9 +236,9 @@ void IFCImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS } std::unique_ptr db(STEP::ReadFileHeader(stream)); - const STEP::HeaderInfo& head = static_cast(*db).GetHeader(); + const STEP::HeaderInfo &head = static_cast(*db).GetHeader(); - if(!head.fileSchema.size() || head.fileSchema.substr(0,3) != "IFC") { + if (!head.fileSchema.size() || head.fileSchema.substr(0, 3) != "IFC") { ThrowException("Unrecognized file schema: " + head.fileSchema); } @@ -263,7 +248,7 @@ void IFCImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS LogDebug("Timestamp \'" + head.timestamp + '\''); } if (head.app.length()) { - LogDebug("Application/Exporter identline is \'" + head.app + '\''); + LogDebug("Application/Exporter identline is \'" + head.app + '\''); } } @@ -272,41 +257,41 @@ void IFCImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS Schema_2x3::GetSchema(schema); // tell the reader which entity types to track with special care - static const char* const types_to_track[] = { + static const char *const types_to_track[] = { "ifcsite", "ifcbuilding", "ifcproject" }; // tell the reader for which types we need to simulate STEPs reverse indices - static const char* const inverse_indices_to_track[] = { + static const char *const inverse_indices_to_track[] = { "ifcrelcontainedinspatialstructure", "ifcrelaggregates", "ifcrelvoidselement", "ifcreldefinesbyproperties", "ifcpropertyset", "ifcstyleditem" }; // feed the IFC schema into the reader and pre-parse all lines STEP::ReadFile(*db, schema, types_to_track, inverse_indices_to_track); - const STEP::LazyObject* proj = db->GetObject("ifcproject"); + const STEP::LazyObject *proj = db->GetObject("ifcproject"); if (!proj) { ThrowException("missing IfcProject entity"); } - ConversionData conv(*db,proj->To(),pScene,settings); + ConversionData conv(*db, proj->To(), pScene, settings); SetUnits(conv); SetCoordinateSpace(conv); ProcessSpatialStructures(conv); MakeTreeRelative(conv); - // NOTE - this is a stress test for the importer, but it works only - // in a build with no entities disabled. See - // scripts/IFCImporter/CPPGenerator.py - // for more information. - #ifdef ASSIMP_IFC_TEST - db->EvaluateAll(); - #endif +// NOTE - this is a stress test for the importer, but it works only +// in a build with no entities disabled. See +// scripts/IFCImporter/CPPGenerator.py +// for more information. +#ifdef ASSIMP_IFC_TEST + db->EvaluateAll(); +#endif // do final data copying if (conv.meshes.size()) { pScene->mNumMeshes = static_cast(conv.meshes.size()); - pScene->mMeshes = new aiMesh*[pScene->mNumMeshes](); - std::copy(conv.meshes.begin(),conv.meshes.end(),pScene->mMeshes); + pScene->mMeshes = new aiMesh *[pScene->mNumMeshes](); + std::copy(conv.meshes.begin(), conv.meshes.end(), pScene->mMeshes); // needed to keep the d'tor from burning us conv.meshes.clear(); @@ -314,8 +299,8 @@ void IFCImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS if (conv.materials.size()) { pScene->mNumMaterials = static_cast(conv.materials.size()); - pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials](); - std::copy(conv.materials.begin(),conv.materials.end(),pScene->mMaterials); + pScene->mMaterials = new aiMaterial *[pScene->mNumMaterials](); + std::copy(conv.materials.begin(), conv.materials.end(), pScene->mMaterials); // needed to keep the d'tor from burning us conv.materials.clear(); @@ -323,42 +308,38 @@ void IFCImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS // apply world coordinate system (which includes the scaling to convert to meters and a -90 degrees rotation around x) aiMatrix4x4 scale, rot; - aiMatrix4x4::Scaling(static_cast(IfcVector3(conv.len_scale)),scale); - aiMatrix4x4::RotationX(-AI_MATH_HALF_PI_F,rot); + aiMatrix4x4::Scaling(static_cast(IfcVector3(conv.len_scale)), scale); + aiMatrix4x4::RotationX(-AI_MATH_HALF_PI_F, rot); pScene->mRootNode->mTransformation = rot * scale * conv.wcs * pScene->mRootNode->mTransformation; // this must be last because objects are evaluated lazily as we process them - if ( !DefaultLogger::isNullLogger() ){ - LogDebug((Formatter::format(),"STEP: evaluated ",db->GetEvaluatedObjectCount()," object records")); + if (!DefaultLogger::isNullLogger()) { + LogDebug((Formatter::format(), "STEP: evaluated ", db->GetEvaluatedObjectCount(), " object records")); } } namespace { - // ------------------------------------------------------------------------------------------------ -void ConvertUnit(const Schema_2x3::IfcNamedUnit& unit,ConversionData& conv) -{ - if(const Schema_2x3::IfcSIUnit* const si = unit.ToPtr()) { - if(si->UnitType == "LENGTHUNIT") { +void ConvertUnit(const Schema_2x3::IfcNamedUnit &unit, ConversionData &conv) { + if (const Schema_2x3::IfcSIUnit *const si = unit.ToPtr()) { + if (si->UnitType == "LENGTHUNIT") { conv.len_scale = si->Prefix ? ConvertSIPrefix(si->Prefix) : 1.f; IFCImporter::LogDebug("got units used for lengths"); } - if(si->UnitType == "PLANEANGLEUNIT") { + if (si->UnitType == "PLANEANGLEUNIT") { if (si->Name != "RADIAN") { IFCImporter::LogWarn("expected base unit for angles to be radian"); } } - } - else if(const Schema_2x3::IfcConversionBasedUnit* const convu = unit.ToPtr()) { - if(convu->UnitType == "PLANEANGLEUNIT") { + } else if (const Schema_2x3::IfcConversionBasedUnit *const convu = unit.ToPtr()) { + if (convu->UnitType == "PLANEANGLEUNIT") { try { conv.angle_scale = convu->ConversionFactor->ValueComponent->To<::Assimp::STEP::EXPRESS::REAL>(); - ConvertUnit(*convu->ConversionFactor->UnitComponent,conv); + ConvertUnit(*convu->ConversionFactor->UnitComponent, conv); IFCImporter::LogDebug("got units used for angles"); - } - catch(std::bad_cast&) { + } catch (std::bad_cast &) { IFCImporter::LogError("skipping unknown IfcConversionBasedUnit.ValueComponent entry - expected REAL"); } } @@ -366,39 +347,34 @@ void ConvertUnit(const Schema_2x3::IfcNamedUnit& unit,ConversionData& conv) } // ------------------------------------------------------------------------------------------------ -void ConvertUnit(const ::Assimp::STEP::EXPRESS::DataType& dt,ConversionData& conv) -{ +void ConvertUnit(const ::Assimp::STEP::EXPRESS::DataType &dt, ConversionData &conv) { try { - const ::Assimp::STEP::EXPRESS::ENTITY& e = dt.To<::Assimp::STEP::EXPRESS::ENTITY>(); + const ::Assimp::STEP::EXPRESS::ENTITY &e = dt.To<::Assimp::STEP::EXPRESS::ENTITY>(); - const Schema_2x3::IfcNamedUnit& unit = e.ResolveSelect(conv.db); - if(unit.UnitType != "LENGTHUNIT" && unit.UnitType != "PLANEANGLEUNIT") { + const Schema_2x3::IfcNamedUnit &unit = e.ResolveSelect(conv.db); + if (unit.UnitType != "LENGTHUNIT" && unit.UnitType != "PLANEANGLEUNIT") { return; } - ConvertUnit(unit,conv); - } - catch(std::bad_cast&) { + ConvertUnit(unit, conv); + } catch (std::bad_cast &) { // not entity, somehow IFCImporter::LogError("skipping unknown IfcUnit entry - expected entity"); } } // ------------------------------------------------------------------------------------------------ -void SetUnits(ConversionData& conv) -{ +void SetUnits(ConversionData &conv) { // see if we can determine the coordinate space used to express. - for(size_t i = 0; i < conv.proj.UnitsInContext->Units.size(); ++i ) { - ConvertUnit(*conv.proj.UnitsInContext->Units[i],conv); + for (size_t i = 0; i < conv.proj.UnitsInContext->Units.size(); ++i) { + ConvertUnit(*conv.proj.UnitsInContext->Units[i], conv); } } - // ------------------------------------------------------------------------------------------------ -void SetCoordinateSpace(ConversionData& conv) -{ - const Schema_2x3::IfcRepresentationContext* fav = NULL; - for(const Schema_2x3::IfcRepresentationContext& v : conv.proj.RepresentationContexts) { +void SetCoordinateSpace(ConversionData &conv) { + const Schema_2x3::IfcRepresentationContext *fav = NULL; + for (const Schema_2x3::IfcRepresentationContext &v : conv.proj.RepresentationContexts) { fav = &v; // Model should be the most suitable type of context, hence ignore the others if (v.ContextType && v.ContextType.Get() == "Model") { @@ -406,37 +382,33 @@ void SetCoordinateSpace(ConversionData& conv) } } if (fav) { - if(const Schema_2x3::IfcGeometricRepresentationContext* const geo = fav->ToPtr()) { + if (const Schema_2x3::IfcGeometricRepresentationContext *const geo = fav->ToPtr()) { ConvertAxisPlacement(conv.wcs, *geo->WorldCoordinateSystem, conv); IFCImporter::LogDebug("got world coordinate system"); } } } - // ------------------------------------------------------------------------------------------------ -void ResolveObjectPlacement(aiMatrix4x4& m, const Schema_2x3::IfcObjectPlacement& place, ConversionData& conv) -{ - if (const Schema_2x3::IfcLocalPlacement* const local = place.ToPtr()){ +void ResolveObjectPlacement(aiMatrix4x4 &m, const Schema_2x3::IfcObjectPlacement &place, ConversionData &conv) { + if (const Schema_2x3::IfcLocalPlacement *const local = place.ToPtr()) { IfcMatrix4 tmp; ConvertAxisPlacement(tmp, *local->RelativePlacement, conv); m = static_cast(tmp); if (local->PlacementRelTo) { - aiMatrix4x4 tmp; - ResolveObjectPlacement(tmp,local->PlacementRelTo.Get(),conv); - m = tmp * m; + aiMatrix4x4 tmpM; + ResolveObjectPlacement(tmpM, local->PlacementRelTo.Get(), conv); + m = tmpM * m; } - } - else { + } else { IFCImporter::LogWarn("skipping unknown IfcObjectPlacement entity, type is " + place.GetClassName()); } } // ------------------------------------------------------------------------------------------------ -bool ProcessMappedItem(const Schema_2x3::IfcMappedItem& mapped, aiNode* nd_src, std::vector< aiNode* >& subnodes_src, unsigned int matid, ConversionData& conv) -{ +bool ProcessMappedItem(const Schema_2x3::IfcMappedItem &mapped, aiNode *nd_src, std::vector &subnodes_src, unsigned int matid, ConversionData &conv) { // insert a custom node here, the carthesian transform operator is simply a conventional transformation matrix std::unique_ptr nd(new aiNode()); nd->mName.Set("IfcMappedItem"); @@ -446,49 +418,49 @@ bool ProcessMappedItem(const Schema_2x3::IfcMappedItem& mapped, aiNode* nd_src, ConvertTransformOperator(m, *mapped.MappingTarget); IfcMatrix4 msrc; - ConvertAxisPlacement(msrc,*mapped.MappingSource->MappingOrigin,conv); + ConvertAxisPlacement(msrc, *mapped.MappingSource->MappingOrigin, conv); - msrc = m*msrc; + msrc = m * msrc; std::set meshes; const size_t old_openings = conv.collect_openings ? conv.collect_openings->size() : 0; if (conv.apply_openings) { IfcMatrix4 minv = msrc; minv.Inverse(); - for(TempOpening& open :*conv.apply_openings){ + for (TempOpening &open : *conv.apply_openings) { open.Transform(minv); } } - unsigned int localmatid = ProcessMaterials(mapped.GetID(),matid,conv,false); - const Schema_2x3::IfcRepresentation& repr = mapped.MappingSource->MappedRepresentation; + unsigned int localmatid = ProcessMaterials(mapped.GetID(), matid, conv, false); + const Schema_2x3::IfcRepresentation &repr = mapped.MappingSource->MappedRepresentation; bool got = false; - for(const Schema_2x3::IfcRepresentationItem& item : repr.Items) { - if(!ProcessRepresentationItem(item,localmatid,meshes,conv)) { + for (const Schema_2x3::IfcRepresentationItem &item : repr.Items) { + if (!ProcessRepresentationItem(item, localmatid, meshes, conv)) { IFCImporter::LogWarn("skipping mapped entity of type " + item.GetClassName() + ", no representations could be generated"); - } - else got = true; + } else + got = true; } if (!got) { return false; } - AssignAddedMeshes(meshes,nd.get(),conv); + AssignAddedMeshes(meshes, nd.get(), conv); if (conv.collect_openings) { // if this pass serves us only to collect opening geometry, // make sure we transform the TempMesh's which we need to // preserve as well. - if(const size_t diff = conv.collect_openings->size() - old_openings) { - for(size_t i = 0; i < diff; ++i) { - (*conv.collect_openings)[old_openings+i].Transform(msrc); + if (const size_t diff = conv.collect_openings->size() - old_openings) { + for (size_t i = 0; i < diff; ++i) { + (*conv.collect_openings)[old_openings + i].Transform(msrc); } } } - nd->mTransformation = nd_src->mTransformation * static_cast( msrc ); + nd->mTransformation = nd_src->mTransformation * static_cast(msrc); subnodes_src.push_back(nd.release()); return true; @@ -496,20 +468,19 @@ bool ProcessMappedItem(const Schema_2x3::IfcMappedItem& mapped, aiNode* nd_src, // ------------------------------------------------------------------------------------------------ struct RateRepresentationPredicate { - int Rate(const Schema_2x3::IfcRepresentation* r) const { + int Rate(const Schema_2x3::IfcRepresentation *r) const { // the smaller, the better - if (! r->RepresentationIdentifier) { + if (!r->RepresentationIdentifier) { // neutral choice if no extra information is specified return 0; } - - const std::string& name = r->RepresentationIdentifier.Get(); + const std::string &name = r->RepresentationIdentifier.Get(); if (name == "MappedRepresentation") { if (!r->Items.empty()) { // take the first item and base our choice on it - const Schema_2x3::IfcMappedItem* const m = r->Items.front()->ToPtr(); + const Schema_2x3::IfcMappedItem *const m = r->Items.front()->ToPtr(); if (m) { return Rate(m->MappingSource->MappedRepresentation); } @@ -520,7 +491,7 @@ struct RateRepresentationPredicate { return Rate(name); } - int Rate(const std::string& r) const { + int Rate(const std::string &r) const { if (r == "SolidModel") { return -3; } @@ -551,20 +522,19 @@ struct RateRepresentationPredicate { return 0; } - bool operator() (const Schema_2x3::IfcRepresentation* a, const Schema_2x3::IfcRepresentation* b) const { + bool operator()(const Schema_2x3::IfcRepresentation *a, const Schema_2x3::IfcRepresentation *b) const { return Rate(a) < Rate(b); } }; // ------------------------------------------------------------------------------------------------ -void ProcessProductRepresentation(const Schema_2x3::IfcProduct& el, aiNode* nd, std::vector< aiNode* >& subnodes, ConversionData& conv) -{ - if(!el.Representation) { +void ProcessProductRepresentation(const Schema_2x3::IfcProduct &el, aiNode *nd, std::vector &subnodes, ConversionData &conv) { + if (!el.Representation) { return; } // extract Color from metadata, if present - unsigned int matid = ProcessMaterials( el.GetID(), std::numeric_limits::max(), conv, false); + unsigned int matid = ProcessMaterials(el.GetID(), std::numeric_limits::max(), conv, false); std::set meshes; // we want only one representation type, so bring them in a suitable order (i.e try those @@ -572,162 +542,151 @@ void ProcessProductRepresentation(const Schema_2x3::IfcProduct& el, aiNode* nd, // representation is relatively generic and allows the concrete implementations // for the different representation types to make some sensible choices what // to load and what not to load. - const STEP::ListOf< STEP::Lazy< Schema_2x3::IfcRepresentation >, 1, 0 >& src = el.Representation.Get()->Representations; - std::vector repr_ordered(src.size()); - std::copy(src.begin(),src.end(),repr_ordered.begin()); - std::sort(repr_ordered.begin(),repr_ordered.end(),RateRepresentationPredicate()); - for(const Schema_2x3::IfcRepresentation* repr : repr_ordered) { + const STEP::ListOf, 1, 0> &src = el.Representation.Get()->Representations; + std::vector repr_ordered(src.size()); + std::copy(src.begin(), src.end(), repr_ordered.begin()); + std::sort(repr_ordered.begin(), repr_ordered.end(), RateRepresentationPredicate()); + for (const Schema_2x3::IfcRepresentation *repr : repr_ordered) { bool res = false; - for(const Schema_2x3::IfcRepresentationItem& item : repr->Items) { - if(const Schema_2x3::IfcMappedItem* const geo = item.ToPtr()) { - res = ProcessMappedItem(*geo,nd,subnodes,matid,conv) || res; - } - else { - res = ProcessRepresentationItem(item,matid,meshes,conv) || res; + for (const Schema_2x3::IfcRepresentationItem &item : repr->Items) { + if (const Schema_2x3::IfcMappedItem *const geo = item.ToPtr()) { + res = ProcessMappedItem(*geo, nd, subnodes, matid, conv) || res; + } else { + res = ProcessRepresentationItem(item, matid, meshes, conv) || res; } } // if we got something meaningful at this point, skip any further representations - if(res) { + if (res) { break; } } - AssignAddedMeshes(meshes,nd,conv); + AssignAddedMeshes(meshes, nd, conv); } typedef std::map Metadata; // ------------------------------------------------------------------------------------------------ -void ProcessMetadata(const Schema_2x3::ListOf< Schema_2x3::Lazy< Schema_2x3::IfcProperty >, 1, 0 >& set, ConversionData& conv, Metadata& properties, - const std::string& prefix = "", +void ProcessMetadata(const Schema_2x3::ListOf, 1, 0> &set, ConversionData &conv, Metadata &properties, + const std::string &prefix = "", unsigned int nest = 0) { - for(const Schema_2x3::IfcProperty& property : set) { - const std::string& key = prefix.length() > 0 ? (prefix + "." + property.Name) : property.Name; - if (const Schema_2x3::IfcPropertySingleValue* const singleValue = property.ToPtr()) { + for (const Schema_2x3::IfcProperty &property : set) { + const std::string &key = prefix.length() > 0 ? (prefix + "." + property.Name) : property.Name; + if (const Schema_2x3::IfcPropertySingleValue *const singleValue = property.ToPtr()) { if (singleValue->NominalValue) { - if (const ::Assimp::STEP::EXPRESS::STRING* str = singleValue->NominalValue.Get()->ToPtr<::Assimp::STEP::EXPRESS::STRING>()) { + if (const ::Assimp::STEP::EXPRESS::STRING *str = singleValue->NominalValue.Get()->ToPtr<::Assimp::STEP::EXPRESS::STRING>()) { std::string value = static_cast(*str); - properties[key]=value; - } - else if (const ::Assimp::STEP::EXPRESS::REAL* val = singleValue->NominalValue.Get()->ToPtr<::Assimp::STEP::EXPRESS::REAL>()) { - float value = static_cast(*val); + properties[key] = value; + } else if (const ::Assimp::STEP::EXPRESS::REAL *val1 = singleValue->NominalValue.Get()->ToPtr<::Assimp::STEP::EXPRESS::REAL>()) { + float value = static_cast(*val1); std::stringstream s; s << value; - properties[key]=s.str(); - } - else if (const ::Assimp::STEP::EXPRESS::INTEGER* val = singleValue->NominalValue.Get()->ToPtr<::Assimp::STEP::EXPRESS::INTEGER>()) { - int64_t value = static_cast(*val); + properties[key] = s.str(); + } else if (const ::Assimp::STEP::EXPRESS::INTEGER *val2 = singleValue->NominalValue.Get()->ToPtr<::Assimp::STEP::EXPRESS::INTEGER>()) { + int64_t curValue = static_cast(*val2); std::stringstream s; - s << value; - properties[key]=s.str(); + s << curValue; + properties[key] = s.str(); } } - } - else if (const Schema_2x3::IfcPropertyListValue* const listValue = property.ToPtr()) { + } else if (const Schema_2x3::IfcPropertyListValue *const listValue = property.ToPtr()) { std::stringstream ss; ss << "["; - unsigned index=0; - for(const Schema_2x3::IfcValue::Out& v : listValue->ListValues) { + unsigned index = 0; + for (const Schema_2x3::IfcValue::Out &v : listValue->ListValues) { if (!v) continue; - if (const ::Assimp::STEP::EXPRESS::STRING* str = v->ToPtr<::Assimp::STEP::EXPRESS::STRING>()) { + if (const ::Assimp::STEP::EXPRESS::STRING *str = v->ToPtr<::Assimp::STEP::EXPRESS::STRING>()) { std::string value = static_cast(*str); ss << "'" << value << "'"; - } - else if (const ::Assimp::STEP::EXPRESS::REAL* val = v->ToPtr<::Assimp::STEP::EXPRESS::REAL>()) { - float value = static_cast(*val); + } else if (const ::Assimp::STEP::EXPRESS::REAL *val1 = v->ToPtr<::Assimp::STEP::EXPRESS::REAL>()) { + float value = static_cast(*val1); + ss << value; + } else if (const ::Assimp::STEP::EXPRESS::INTEGER *val2 = v->ToPtr<::Assimp::STEP::EXPRESS::INTEGER>()) { + int64_t value = static_cast(*val2); ss << value; } - else if (const ::Assimp::STEP::EXPRESS::INTEGER* val = v->ToPtr<::Assimp::STEP::EXPRESS::INTEGER>()) { - int64_t value = static_cast(*val); - ss << value; - } - if (index+1ListValues.size()) { + if (index + 1 < listValue->ListValues.size()) { ss << ","; } index++; } ss << "]"; - properties[key]=ss.str(); - } - else if (const Schema_2x3::IfcComplexProperty* const complexProp = property.ToPtr()) { - if(nest > 2) { // mostly arbitrary limit to prevent stack overflow vulnerabilities + properties[key] = ss.str(); + } else if (const Schema_2x3::IfcComplexProperty *const complexProp = property.ToPtr()) { + if (nest > 2) { // mostly arbitrary limit to prevent stack overflow vulnerabilities IFCImporter::LogError("maximum nesting level for IfcComplexProperty reached, skipping this property."); - } - else { + } else { ProcessMetadata(complexProp->HasProperties, conv, properties, key, nest + 1); } - } - else { - properties[key]=""; + } else { + properties[key] = ""; } } } - // ------------------------------------------------------------------------------------------------ -void ProcessMetadata(uint64_t relDefinesByPropertiesID, ConversionData& conv, Metadata& properties) -{ - if (const Schema_2x3::IfcRelDefinesByProperties* const pset = conv.db.GetObject(relDefinesByPropertiesID)->ToPtr()) { - if (const Schema_2x3::IfcPropertySet* const set = conv.db.GetObject(pset->RelatingPropertyDefinition->GetID())->ToPtr()) { +void ProcessMetadata(uint64_t relDefinesByPropertiesID, ConversionData &conv, Metadata &properties) { + if (const Schema_2x3::IfcRelDefinesByProperties *const pset = conv.db.GetObject(relDefinesByPropertiesID)->ToPtr()) { + if (const Schema_2x3::IfcPropertySet *const set = conv.db.GetObject(pset->RelatingPropertyDefinition->GetID())->ToPtr()) { ProcessMetadata(set->HasProperties, conv, properties); } } } // ------------------------------------------------------------------------------------------------ -aiNode* ProcessSpatialStructure(aiNode* parent, const Schema_2x3::IfcProduct& el, ConversionData& conv, - std::vector* collect_openings = nullptr ) { - const STEP::DB::RefMap& refs = conv.db.GetRefs(); +aiNode *ProcessSpatialStructure(aiNode *parent, const Schema_2x3::IfcProduct &el, ConversionData &conv, + std::vector *collect_openings = nullptr) { + const STEP::DB::RefMap &refs = conv.db.GetRefs(); // skip over space and annotation nodes - usually, these have no meaning in Assimp's context bool skipGeometry = false; - if(conv.settings.skipSpaceRepresentations) { - if(el.ToPtr()) { + if (conv.settings.skipSpaceRepresentations) { + if (el.ToPtr()) { IFCImporter::LogDebug("skipping IfcSpace entity due to importer settings"); skipGeometry = true; } } - if(conv.settings.skipAnnotations) { - if(el.ToPtr()) { + if (conv.settings.skipAnnotations) { + if (el.ToPtr()) { IFCImporter::LogDebug("skipping IfcAnnotation entity due to importer settings"); return nullptr; } } // add an output node for this spatial structure - aiNode *nd(new aiNode ); - nd->mName.Set(el.GetClassName()+"_"+(el.Name?el.Name.Get():"Unnamed")+"_"+el.GlobalId); + aiNode *nd(new aiNode); + nd->mName.Set(el.GetClassName() + "_" + (el.Name ? el.Name.Get() : "Unnamed") + "_" + el.GlobalId); nd->mParent = parent; conv.already_processed.insert(el.GetID()); // check for node metadata STEP::DB::RefMapRange children = refs.equal_range(el.GetID()); - if (children.first!=refs.end()) { + if (children.first != refs.end()) { Metadata properties; - if (children.first==children.second) { + if (children.first == children.second) { // handles single property set ProcessMetadata((*children.first).second, conv, properties); } else { // handles multiple property sets (currently all property sets are merged, // which may not be the best solution in the long run) - for (STEP::DB::RefMap::const_iterator it=children.first; it!=children.second; ++it) { + for (STEP::DB::RefMap::const_iterator it = children.first; it != children.second; ++it) { ProcessMetadata((*it).second, conv, properties); } } if (!properties.empty()) { - aiMetadata* data = aiMetadata::Alloc( static_cast(properties.size()) ); - unsigned int index( 0 ); - for ( const Metadata::value_type& kv : properties ) { - data->Set( index++, kv.first, aiString( kv.second ) ); + aiMetadata *data = aiMetadata::Alloc(static_cast(properties.size())); + unsigned int index(0); + for (const Metadata::value_type &kv : properties) { + data->Set(index++, kv.first, aiString(kv.second)); } nd->mMetaData = data; } } - if(el.ObjectPlacement) { - ResolveObjectPlacement(nd->mTransformation,el.ObjectPlacement.Get(),conv); + if (el.ObjectPlacement) { + ResolveObjectPlacement(nd->mTransformation, el.ObjectPlacement.Get(), conv); } std::vector openings; @@ -737,44 +696,44 @@ aiNode* ProcessSpatialStructure(aiNode* parent, const Schema_2x3::IfcProduct& el // convert everything contained directly within this structure, // this may result in more nodes. - std::vector< aiNode* > subnodes; + std::vector subnodes; try { // locate aggregates and 'contained-in-here'-elements of this spatial structure and add them in recursively // on our way, collect openings in *this* element STEP::DB::RefMapRange range = refs.equal_range(el.GetID()); - for(STEP::DB::RefMapRange range2 = range; range2.first != range.second; ++range2.first) { + for (STEP::DB::RefMapRange range2 = range; range2.first != range.second; ++range2.first) { // skip over meshes that have already been processed before. This is strictly necessary // because the reverse indices also include references contained in argument lists and // therefore every element has a back-reference hold by its parent. if (conv.already_processed.find((*range2.first).second) != conv.already_processed.end()) { continue; } - const STEP::LazyObject& obj = conv.db.MustGetObject((*range2.first).second); + const STEP::LazyObject &obj = conv.db.MustGetObject((*range2.first).second); // handle regularly-contained elements - if(const Schema_2x3::IfcRelContainedInSpatialStructure* const cont = obj->ToPtr()) { - if(cont->RelatingStructure->GetID() != el.GetID()) { + if (const Schema_2x3::IfcRelContainedInSpatialStructure *const cont = obj->ToPtr()) { + if (cont->RelatingStructure->GetID() != el.GetID()) { continue; } - for(const Schema_2x3::IfcProduct& pro : cont->RelatedElements) { - if(pro.ToPtr()) { + for (const Schema_2x3::IfcProduct &pro : cont->RelatedElements) { + if (pro.ToPtr()) { // IfcOpeningElement is handled below. Sadly we can't use it here as is: // The docs say that opening elements are USUALLY attached to building storey, // but we want them for the building elements to which they belong. continue; } - aiNode* const ndnew = ProcessSpatialStructure(nd,pro,conv,nullptr); - if(ndnew) { - subnodes.push_back( ndnew ); + aiNode *const ndnew = ProcessSpatialStructure(nd, pro, conv, nullptr); + if (ndnew) { + subnodes.push_back(ndnew); } } } // handle openings, which we collect in a list rather than adding them to the node graph - else if(const Schema_2x3::IfcRelVoidsElement* const fills = obj->ToPtr()) { - if(fills->RelatingBuildingElement->GetID() == el.GetID()) { - const Schema_2x3::IfcFeatureElementSubtraction& open = fills->RelatedOpeningElement; + else if (const Schema_2x3::IfcRelVoidsElement *const fills = obj->ToPtr()) { + if (fills->RelatingBuildingElement->GetID() == el.GetID()) { + const Schema_2x3::IfcFeatureElementSubtraction &open = fills->RelatedOpeningElement; // move opening elements to a separate node since they are semantically different than elements that are just 'contained' std::unique_ptr nd_aggr(new aiNode()); @@ -784,40 +743,39 @@ aiNode* ProcessSpatialStructure(aiNode* parent, const Schema_2x3::IfcProduct& el nd_aggr->mTransformation = nd->mTransformation; std::vector openings_local; - aiNode* const ndnew = ProcessSpatialStructure( nd_aggr.get(),open, conv,&openings_local); + aiNode *const ndnew = ProcessSpatialStructure(nd_aggr.get(), open, conv, &openings_local); if (ndnew) { nd_aggr->mNumChildren = 1; - nd_aggr->mChildren = new aiNode*[1](); - + nd_aggr->mChildren = new aiNode *[1](); nd_aggr->mChildren[0] = ndnew; - if(openings_local.size()) { + if (openings_local.size()) { if (!didinv) { - myInv = aiMatrix4x4(nd->mTransformation ).Inverse(); + myInv = aiMatrix4x4(nd->mTransformation).Inverse(); didinv = true; } // we need all openings to be in the local space of *this* node, so transform them - for(TempOpening& op :openings_local) { - op.Transform( myInv*nd_aggr->mChildren[0]->mTransformation); + for (TempOpening &op : openings_local) { + op.Transform(myInv * nd_aggr->mChildren[0]->mTransformation); openings.push_back(op); } } - subnodes.push_back( nd_aggr.release() ); + subnodes.push_back(nd_aggr.release()); } } } } - for(;range.first != range.second; ++range.first) { + for (; range.first != range.second; ++range.first) { // see note in loop above if (conv.already_processed.find((*range.first).second) != conv.already_processed.end()) { continue; } - if(const Schema_2x3::IfcRelAggregates* const aggr = conv.db.GetObject((*range.first).second)->ToPtr()) { - if(aggr->RelatingObject->GetID() != el.GetID()) { + if (const Schema_2x3::IfcRelAggregates *const aggr = conv.db.GetObject((*range.first).second)->ToPtr()) { + if (aggr->RelatingObject->GetID() != el.GetID()) { continue; } @@ -828,41 +786,41 @@ aiNode* ProcessSpatialStructure(aiNode* parent, const Schema_2x3::IfcProduct& el nd_aggr->mTransformation = nd->mTransformation; - nd_aggr->mChildren = new aiNode*[aggr->RelatedObjects.size()](); - for(const Schema_2x3::IfcObjectDefinition& def : aggr->RelatedObjects) { - if(const Schema_2x3::IfcProduct* const prod = def.ToPtr()) { + nd_aggr->mChildren = new aiNode *[aggr->RelatedObjects.size()](); + for (const Schema_2x3::IfcObjectDefinition &def : aggr->RelatedObjects) { + if (const Schema_2x3::IfcProduct *const prod = def.ToPtr()) { - aiNode* const ndnew = ProcessSpatialStructure(nd_aggr.get(),*prod,conv,NULL); - if(ndnew) { + aiNode *const ndnew = ProcessSpatialStructure(nd_aggr.get(), *prod, conv, NULL); + if (ndnew) { nd_aggr->mChildren[nd_aggr->mNumChildren++] = ndnew; } } } - subnodes.push_back( nd_aggr.release() ); + subnodes.push_back(nd_aggr.release()); } } conv.collect_openings = collect_openings; - if(!conv.collect_openings) { + if (!conv.collect_openings) { conv.apply_openings = &openings; } if (!skipGeometry) { - ProcessProductRepresentation(el, nd, subnodes, conv); - conv.apply_openings = conv.collect_openings = nullptr; + ProcessProductRepresentation(el, nd, subnodes, conv); + conv.apply_openings = conv.collect_openings = nullptr; } if (subnodes.size()) { - nd->mChildren = new aiNode*[subnodes.size()](); - for(aiNode* nd2 : subnodes) { + nd->mChildren = new aiNode *[subnodes.size()](); + for (aiNode *nd2 : subnodes) { nd->mChildren[nd->mNumChildren++] = nd2; nd2->mParent = nd; } } - } catch(...) { + } catch (...) { // it hurts, but I don't want to pull boost::ptr_vector into -noboost only for these few spots here - std::for_each(subnodes.begin(),subnodes.end(),delete_fun()); + std::for_each(subnodes.begin(), subnodes.end(), delete_fun()); throw; } @@ -872,17 +830,15 @@ aiNode* ProcessSpatialStructure(aiNode* parent, const Schema_2x3::IfcProduct& el } // ------------------------------------------------------------------------------------------------ -void ProcessSpatialStructures(ConversionData& conv) -{ +void ProcessSpatialStructures(ConversionData &conv) { // XXX add support for multiple sites (i.e. IfcSpatialStructureElements with composition == COMPLEX) - // process all products in the file. it is reasonable to assume that a // file that is relevant for us contains at least a site or a building. - const STEP::DB::ObjectMapByType& map = conv.db.GetObjectsByType(); + const STEP::DB::ObjectMapByType &map = conv.db.GetObjectsByType(); ai_assert(map.find("ifcsite") != map.end()); - const STEP::DB::ObjectSet* range = &map.find("ifcsite")->second; + const STEP::DB::ObjectSet *range = &map.find("ifcsite")->second; if (range->empty()) { ai_assert(map.find("ifcbuilding") != map.end()); @@ -893,75 +849,72 @@ void ProcessSpatialStructures(ConversionData& conv) } } - std::vector nodes; + std::vector nodes; - for(const STEP::LazyObject* lz : *range) { - const Schema_2x3::IfcSpatialStructureElement* const prod = lz->ToPtr(); - if(!prod) { + for (const STEP::LazyObject *lz : *range) { + const Schema_2x3::IfcSpatialStructureElement *const prod = lz->ToPtr(); + if (!prod) { continue; } - IFCImporter::LogDebug("looking at spatial structure `" + (prod->Name ? prod->Name.Get() : "unnamed") + "`" + (prod->ObjectType? " which is of type " + prod->ObjectType.Get():"")); + IFCImporter::LogDebug("looking at spatial structure `" + (prod->Name ? prod->Name.Get() : "unnamed") + "`" + (prod->ObjectType ? " which is of type " + prod->ObjectType.Get() : "")); // the primary sites are referenced by an IFCRELAGGREGATES element which assigns them to the IFCPRODUCT - const STEP::DB::RefMap& refs = conv.db.GetRefs(); + const STEP::DB::RefMap &refs = conv.db.GetRefs(); STEP::DB::RefMapRange ref_range = refs.equal_range(conv.proj.GetID()); - for(; ref_range.first != ref_range.second; ++ref_range.first) { - if(const Schema_2x3::IfcRelAggregates* const aggr = conv.db.GetObject((*ref_range.first).second)->ToPtr()) { + for (; ref_range.first != ref_range.second; ++ref_range.first) { + if (const Schema_2x3::IfcRelAggregates *const aggr = conv.db.GetObject((*ref_range.first).second)->ToPtr()) { - for(const Schema_2x3::IfcObjectDefinition& def : aggr->RelatedObjects) { + for (const Schema_2x3::IfcObjectDefinition &def : aggr->RelatedObjects) { // comparing pointer values is not sufficient, we would need to cast them to the same type first // as there is multiple inheritance in the game. if (def.GetID() == prod->GetID()) { IFCImporter::LogDebug("selecting this spatial structure as root structure"); // got it, this is one primary site. - nodes.push_back(ProcessSpatialStructure(NULL, *prod, conv, NULL)); + nodes.push_back(ProcessSpatialStructure(NULL, *prod, conv, NULL)); } } } } } - size_t nb_nodes = nodes.size(); + size_t nb_nodes = nodes.size(); - if (nb_nodes == 0) { - IFCImporter::LogWarn("failed to determine primary site element, taking all the IfcSite"); - for (const STEP::LazyObject* lz : *range) { - const Schema_2x3::IfcSpatialStructureElement* const prod = lz->ToPtr(); - if (!prod) { - continue; - } + if (nb_nodes == 0) { + IFCImporter::LogWarn("failed to determine primary site element, taking all the IfcSite"); + for (const STEP::LazyObject *lz : *range) { + const Schema_2x3::IfcSpatialStructureElement *const prod = lz->ToPtr(); + if (!prod) { + continue; + } - nodes.push_back(ProcessSpatialStructure(NULL, *prod, conv, NULL)); - } + nodes.push_back(ProcessSpatialStructure(NULL, *prod, conv, NULL)); + } - nb_nodes = nodes.size(); - } + nb_nodes = nodes.size(); + } - if (nb_nodes == 1) { - conv.out->mRootNode = nodes[0]; - } - else if (nb_nodes > 1) { - conv.out->mRootNode = new aiNode("Root"); - conv.out->mRootNode->mParent = NULL; - conv.out->mRootNode->mNumChildren = static_cast(nb_nodes); - conv.out->mRootNode->mChildren = new aiNode*[conv.out->mRootNode->mNumChildren]; + if (nb_nodes == 1) { + conv.out->mRootNode = nodes[0]; + } else if (nb_nodes > 1) { + conv.out->mRootNode = new aiNode("Root"); + conv.out->mRootNode->mParent = NULL; + conv.out->mRootNode->mNumChildren = static_cast(nb_nodes); + conv.out->mRootNode->mChildren = new aiNode *[conv.out->mRootNode->mNumChildren]; - for (size_t i = 0; i < nb_nodes; ++i) { - aiNode* node = nodes[i]; + for (size_t i = 0; i < nb_nodes; ++i) { + aiNode *node = nodes[i]; - node->mParent = conv.out->mRootNode; + node->mParent = conv.out->mRootNode; - conv.out->mRootNode->mChildren[i] = node; - } - } - else { - IFCImporter::ThrowException("failed to determine primary site element"); - } + conv.out->mRootNode->mChildren[i] = node; + } + } else { + IFCImporter::ThrowException("failed to determine primary site element"); + } } // ------------------------------------------------------------------------------------------------ -void MakeTreeRelative(aiNode* start, const aiMatrix4x4& combined) -{ +void MakeTreeRelative(aiNode *start, const aiMatrix4x4 &combined) { // combined is the parent's absolute transformation matrix const aiMatrix4x4 old = start->mTransformation; @@ -971,18 +924,15 @@ void MakeTreeRelative(aiNode* start, const aiMatrix4x4& combined) // All nodes store absolute transformations right now, so we need to make them relative for (unsigned int i = 0; i < start->mNumChildren; ++i) { - MakeTreeRelative(start->mChildren[i],old); + MakeTreeRelative(start->mChildren[i], old); } } // ------------------------------------------------------------------------------------------------ -void MakeTreeRelative(ConversionData& conv) -{ - MakeTreeRelative(conv.out->mRootNode,IfcMatrix4()); +void MakeTreeRelative(ConversionData &conv) { + MakeTreeRelative(conv.out->mRootNode, IfcMatrix4()); } -} // !anon - - +} // namespace #endif diff --git a/code/Importer/IFC/IFCUtil.cpp b/code/Importer/IFC/IFCUtil.cpp index 3557b4baa..5e1612bf1 100644 --- a/code/Importer/IFC/IFCUtil.cpp +++ b/code/Importer/IFC/IFCUtil.cpp @@ -362,8 +362,9 @@ void TempMesh::FixupFaceOrientation() { std::reverse(mVerts.begin() + nbvsi, mVerts.begin() + nbvsi + nbvc); std::reverse(neighbour.begin() + nbvsi, neighbour.begin() + nbvsi + nbvc); - for( size_t a = 0; a < nbvc - 1; ++a ) - std::swap(neighbour[nbvsi + a], neighbour[nbvsi + a + 1]); + for (size_t aa = 0; aa < nbvc - 1; ++aa) { + std::swap(neighbour[nbvsi + aa], neighbour[nbvsi + aa + 1]); + } } // either way we're done with the neighbour. Mark it as done and continue checking from there recursively diff --git a/code/Importer/STEPParser/STEPFileReader.cpp b/code/Importer/STEPParser/STEPFileReader.cpp index 72f882d6e..84c5c463a 100644 --- a/code/Importer/STEPParser/STEPFileReader.cpp +++ b/code/Importer/STEPParser/STEPFileReader.cpp @@ -50,12 +50,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include - +#include using namespace Assimp; -namespace EXPRESS = STEP::EXPRESS; -#include +namespace EXPRESS = STEP::EXPRESS; // ------------------------------------------------------------------------------------------------ std::string AddLineNumber(const std::string& s,uint64_t line /*= LINE_NOT_SPECIFIED*/, const std::string& prefix = "") @@ -127,8 +126,8 @@ STEP::DB* STEP::ReadFileHeader(std::shared_ptr stream) { if (list->GetSize() > 1) { ASSIMP_LOG_WARN(AddLineNumber("multiple schemas currently not supported",line)); } - const EXPRESS::STRING* string( nullptr ); - if (!list->GetSize() || !(string=dynamic_cast( (*list)[0].get() ))) { + const EXPRESS::STRING *string = dynamic_cast((*list)[0].get()); + if (!list->GetSize() || nullptr == string ) { throw STEP::SyntaxError("expected FILE_SCHEMA to contain a single string literal",line); } head.fileSchema = *string; @@ -539,7 +538,7 @@ void STEP::LazyObject::LazyInit() const { } const char* acopy = args; - std::shared_ptr conv_args = EXPRESS::LIST::Parse(acopy,STEP::SyntaxError::LINE_NOT_SPECIFIED,&db.GetSchema()); + std::shared_ptr conv_args = EXPRESS::LIST::Parse(acopy,(uint64_t)STEP::SyntaxError::LINE_NOT_SPECIFIED,&db.GetSchema()); delete[] args; args = NULL; diff --git a/code/LWO/LWOLoader.cpp b/code/LWO/LWOLoader.cpp index cb581f7f5..8a1d6195f 100644 --- a/code/LWO/LWOLoader.cpp +++ b/code/LWO/LWOLoader.cpp @@ -45,24 +45,23 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * @brief Implementation of the LWO importer class */ - #ifndef ASSIMP_BUILD_NO_LWO_IMPORTER // internal headers #include "LWO/LWOLoader.h" -#include "PostProcessing/ProcessHelper.h" #include "PostProcessing/ConvertToLHProcess.h" +#include "PostProcessing/ProcessHelper.h" -#include -#include #include -#include +#include +#include #include +#include -#include -#include #include #include +#include +#include using namespace Assimp; @@ -81,32 +80,33 @@ static const aiImporterDesc desc = { // ------------------------------------------------------------------------------------------------ // Constructor to be privately used by Importer -LWOImporter::LWOImporter() - : mIsLWO2(), - mIsLXOB(), - mLayers(), - mCurLayer(), - mTags(), - mMapping(), - mSurfaces(), - mFileBuffer(), - fileSize(), - pScene(), - configSpeedFlag(), - configLayerIndex(), - hasNamedLayer() -{} +LWOImporter::LWOImporter() : + mIsLWO2(), + mIsLXOB(), + mLayers(), + mCurLayer(), + mTags(), + mMapping(), + mSurfaces(), + mFileBuffer(), + fileSize(), + mScene(nullptr), + configSpeedFlag(), + configLayerIndex(), + hasNamedLayer() { + // empty +} // ------------------------------------------------------------------------------------------------ // Destructor, private as well -LWOImporter::~LWOImporter() -{} +LWOImporter::~LWOImporter() { + // empty +} // ------------------------------------------------------------------------------------------------ // Returns whether the class can handle the format of the given file. -bool LWOImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const -{ - const std::string extension = GetExtension(pFile); +bool LWOImporter::CanRead(const std::string &file, IOSystem *pIOHandler, bool checkSig) const { + const std::string extension = GetExtension(file); if (extension == "lwo" || extension == "lxo") { return true; } @@ -117,76 +117,75 @@ bool LWOImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool tokens[0] = AI_LWO_FOURCC_LWOB; tokens[1] = AI_LWO_FOURCC_LWO2; tokens[2] = AI_LWO_FOURCC_LXOB; - return CheckMagicToken(pIOHandler,pFile,tokens,3,8); + return CheckMagicToken(pIOHandler, file, tokens, 3, 8); } return false; } // ------------------------------------------------------------------------------------------------ // Setup configuration properties -void LWOImporter::SetupProperties(const Importer* pImp) -{ - configSpeedFlag = ( 0 != pImp->GetPropertyInteger(AI_CONFIG_FAVOUR_SPEED,0) ? true : false); - configLayerIndex = pImp->GetPropertyInteger (AI_CONFIG_IMPORT_LWO_ONE_LAYER_ONLY,UINT_MAX); - configLayerName = pImp->GetPropertyString (AI_CONFIG_IMPORT_LWO_ONE_LAYER_ONLY,""); +void LWOImporter::SetupProperties(const Importer *pImp) { + configSpeedFlag = (0 != pImp->GetPropertyInteger(AI_CONFIG_FAVOUR_SPEED, 0) ? true : false); + configLayerIndex = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_LWO_ONE_LAYER_ONLY, UINT_MAX); + configLayerName = pImp->GetPropertyString(AI_CONFIG_IMPORT_LWO_ONE_LAYER_ONLY, ""); } // ------------------------------------------------------------------------------------------------ // Get list of file extensions -const aiImporterDesc* LWOImporter::GetInfo () const -{ +const aiImporterDesc *LWOImporter::GetInfo() const { return &desc; } // ------------------------------------------------------------------------------------------------ // Imports the given file into the given scene structure. -void LWOImporter::InternReadFile( const std::string& pFile, - aiScene* pScene, - IOSystem* pIOHandler) -{ - std::unique_ptr file( pIOHandler->Open( pFile, "rb")); +void LWOImporter::InternReadFile(const std::string &pFile, + aiScene *pScene, + IOSystem *pIOHandler) { + std::unique_ptr file(pIOHandler->Open(pFile, "rb")); // Check whether we can read from the file - if( file.get() == NULL) - throw DeadlyImportError( "Failed to open LWO file " + pFile + "."); + if (file.get() == nullptr) { + throw DeadlyImportError("Failed to open LWO file " + pFile + "."); + } - if((this->fileSize = (unsigned int)file->FileSize()) < 12) + if ((this->fileSize = (unsigned int)file->FileSize()) < 12) { throw DeadlyImportError("LWO: The file is too small to contain the IFF header"); + } // Allocate storage and copy the contents of the file to a memory buffer - std::vector< uint8_t > mBuffer(fileSize); - file->Read( &mBuffer[0], 1, fileSize); - this->pScene = pScene; + std::vector mBuffer(fileSize); + file->Read(&mBuffer[0], 1, fileSize); + this->mScene = pScene; // Determine the type of the file uint32_t fileType; - const char* sz = IFF::ReadHeader(&mBuffer[0],fileType); - if (sz)throw DeadlyImportError(sz); + const char *sz = IFF::ReadHeader(&mBuffer[0], fileType); + if (sz) throw DeadlyImportError(sz); mFileBuffer = &mBuffer[0] + 12; fileSize -= 12; // Initialize some members with their default values - hasNamedLayer = false; + hasNamedLayer = false; // Create temporary storage on the stack but store pointers to it in the class // instance. Therefore everything will be destructed properly if an exception // is thrown and we needn't take care of that. - LayerList _mLayers; - SurfaceList _mSurfaces; - TagList _mTags; + LayerList _mLayers; + SurfaceList _mSurfaces; + TagList _mTags; TagMappingTable _mMapping; - mLayers = &_mLayers; - mTags = &_mTags; - mMapping = &_mMapping; - mSurfaces = &_mSurfaces; + mLayers = &_mLayers; + mTags = &_mTags; + mMapping = &_mMapping; + mSurfaces = &_mSurfaces; // Allocate a default layer (layer indices are 1-based from now) mLayers->push_back(Layer()); mCurLayer = &mLayers->back(); mCurLayer->mName = ""; - mCurLayer->mIndex = -1; + mCurLayer->mIndex = (uint16_t) -1; // old lightwave file format (prior to v6) if (AI_LWO_FOURCC_LWOB == fileType) { @@ -197,18 +196,17 @@ void LWOImporter::InternReadFile( const std::string& pFile, LoadLWOBFile(); } // New lightwave format - else if (AI_LWO_FOURCC_LWO2 == fileType) { + else if (AI_LWO_FOURCC_LWO2 == fileType) { mIsLXOB = false; ASSIMP_LOG_INFO("LWO file format: LWO2 (>= LightWave 6)"); } // MODO file format - else if (AI_LWO_FOURCC_LXOB == fileType) { + else if (AI_LWO_FOURCC_LXOB == fileType) { mIsLXOB = true; ASSIMP_LOG_INFO("LWO file format: LXOB (Modo)"); } // we don't know this format - else - { + else { char szBuff[5]; szBuff[0] = (char)(fileType >> 24u); szBuff[1] = (char)(fileType >> 16u); @@ -227,16 +225,15 @@ void LWOImporter::InternReadFile( const std::string& pFile, // we need to check now whether the requested layer has been found. if (UINT_MAX != configLayerIndex) { unsigned int layerCount = 0; - for(std::list::iterator itLayers=mLayers->begin(); itLayers!=mLayers->end(); ++itLayers) + for (std::list::iterator itLayers = mLayers->begin(); itLayers != mLayers->end(); ++itLayers) if (!itLayers->skip) layerCount++; - if (layerCount!=2) + if (layerCount != 2) throw DeadlyImportError("LWO2: The requested layer was not found"); } if (configLayerName.length() && !hasNamedLayer) { - throw DeadlyImportError("LWO2: Unable to find the requested layer: " - + configLayerName); + throw DeadlyImportError("LWO2: Unable to find the requested layer: " + configLayerName); } } @@ -245,42 +242,41 @@ void LWOImporter::InternReadFile( const std::string& pFile, ResolveClips(); // now process all layers and build meshes and nodes - std::vector apcMeshes; - std::map apcNodes; + std::vector apcMeshes; + std::map apcNodes; - apcMeshes.reserve(mLayers->size()*std::min(((unsigned int)mSurfaces->size()/2u), 1u)); + apcMeshes.reserve(mLayers->size() * std::min(((unsigned int)mSurfaces->size() / 2u), 1u)); unsigned int iDefaultSurface = UINT_MAX; // index of the default surface - for (LWO::Layer &layer : *mLayers) { + for (LWO::Layer &layer : *mLayers) { if (layer.skip) continue; // I don't know whether there could be dummy layers, but it would be possible const unsigned int meshStart = (unsigned int)apcMeshes.size(); - if (!layer.mFaces.empty() && !layer.mTempPoints.empty()) { + if (!layer.mFaces.empty() && !layer.mTempPoints.empty()) { // now sort all faces by the surfaces assigned to them - std::vector pSorted(mSurfaces->size()+1); + std::vector pSorted(mSurfaces->size() + 1); unsigned int i = 0; - for (FaceList::iterator it = layer.mFaces.begin(), end = layer.mFaces.end();it != end;++it,++i) { + for (FaceList::iterator it = layer.mFaces.begin(), end = layer.mFaces.end(); it != end; ++it, ++i) { // Check whether we support this face's type if ((*it).type != AI_LWO_FACE && (*it).type != AI_LWO_PTCH && - (*it).type != AI_LWO_BONE && (*it).type != AI_LWO_SUBD) { + (*it).type != AI_LWO_BONE && (*it).type != AI_LWO_SUBD) { continue; } unsigned int idx = (*it).surfaceIndex; - if (idx >= mTags->size()) - { + if (idx >= mTags->size()) { ASSIMP_LOG_WARN("LWO: Invalid face surface index"); idx = UINT_MAX; } - if(UINT_MAX == idx || UINT_MAX == (idx = _mMapping[idx])) { - if (UINT_MAX == iDefaultSurface) { + if (UINT_MAX == idx || UINT_MAX == (idx = _mMapping[idx])) { + if (UINT_MAX == iDefaultSurface) { iDefaultSurface = (unsigned int)mSurfaces->size(); mSurfaces->push_back(LWO::Surface()); - LWO::Surface& surf = mSurfaces->back(); + LWO::Surface &surf = mSurfaces->back(); surf.mColor.r = surf.mColor.g = surf.mColor.b = 0.6f; surf.mName = "LWODefaultSurface"; } @@ -289,27 +285,27 @@ void LWOImporter::InternReadFile( const std::string& pFile, pSorted[idx].push_back(i); } if (UINT_MAX == iDefaultSurface) { - pSorted.erase(pSorted.end()-1); + pSorted.erase(pSorted.end() - 1); } - for (unsigned int p = 0,i = 0;i < mSurfaces->size();++i) { - SortedRep& sorted = pSorted[i]; + for (unsigned int p = 0, j = 0; j < mSurfaces->size(); ++j) { + SortedRep &sorted = pSorted[j]; if (sorted.empty()) continue; // generate the mesh - aiMesh* mesh = new aiMesh(); + aiMesh *mesh = new aiMesh(); apcMeshes.push_back(mesh); mesh->mNumFaces = (unsigned int)sorted.size(); // count the number of vertices SortedRep::const_iterator it = sorted.begin(), end = sorted.end(); - for (;it != end;++it) { + for (; it != end; ++it) { mesh->mNumVertices += layer.mFaces[*it].mNumIndices; } - aiVector3D *nrm = NULL, * pv = mesh->mVertices = new aiVector3D[mesh->mNumVertices]; - aiFace* pf = mesh->mFaces = new aiFace[mesh->mNumFaces]; - mesh->mMaterialIndex = i; + aiVector3D *nrm = nullptr, *pv = mesh->mVertices = new aiVector3D[mesh->mNumVertices]; + aiFace *pf = mesh->mFaces = new aiFace[mesh->mNumFaces]; + mesh->mMaterialIndex = j; // find out which vertex color channels and which texture coordinate // channels are really required by the material attached to this mesh @@ -317,20 +313,20 @@ void LWOImporter::InternReadFile( const std::string& pFile, unsigned int vVColorIndices[AI_MAX_NUMBER_OF_COLOR_SETS]; #ifdef ASSIMP_BUILD_DEBUG - for (unsigned int mui = 0; mui < AI_MAX_NUMBER_OF_TEXTURECOORDS;++mui ) { + for (unsigned int mui = 0; mui < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++mui) { vUVChannelIndices[mui] = UINT_MAX; } - for (unsigned int mui = 0; mui < AI_MAX_NUMBER_OF_COLOR_SETS;++mui ) { + for (unsigned int mui = 0; mui < AI_MAX_NUMBER_OF_COLOR_SETS; ++mui) { vVColorIndices[mui] = UINT_MAX; } #endif - FindUVChannels(_mSurfaces[i],sorted,layer,vUVChannelIndices); - FindVCChannels(_mSurfaces[i],sorted,layer,vVColorIndices); + FindUVChannels(_mSurfaces[j], sorted, layer, vUVChannelIndices); + FindVCChannels(_mSurfaces[j], sorted, layer, vVColorIndices); // allocate storage for UV and CV channels - aiVector3D* pvUV[AI_MAX_NUMBER_OF_TEXTURECOORDS]; - for (unsigned int mui = 0; mui < AI_MAX_NUMBER_OF_TEXTURECOORDS;++mui ) { + aiVector3D *pvUV[AI_MAX_NUMBER_OF_TEXTURECOORDS]; + for (unsigned int mui = 0; mui < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++mui) { if (UINT_MAX == vUVChannelIndices[mui]) { break; } @@ -341,11 +337,12 @@ void LWOImporter::InternReadFile( const std::string& pFile, mesh->mNumUVComponents[0] = 2; } - if (layer.mNormals.name.length()) + if (layer.mNormals.name.length()) { nrm = mesh->mNormals = new aiVector3D[mesh->mNumVertices]; + } - aiColor4D* pvVC[AI_MAX_NUMBER_OF_COLOR_SETS]; - for (unsigned int mui = 0; mui < AI_MAX_NUMBER_OF_COLOR_SETS;++mui) { + aiColor4D *pvVC[AI_MAX_NUMBER_OF_COLOR_SETS]; + for (unsigned int mui = 0; mui < AI_MAX_NUMBER_OF_COLOR_SETS; ++mui) { if (UINT_MAX == vVColorIndices[mui]) { break; } @@ -353,51 +350,51 @@ void LWOImporter::InternReadFile( const std::string& pFile, } // we would not need this extra array, but the code is much cleaner if we use it - std::vector& smoothingGroups = layer.mPointReferrers; - smoothingGroups.erase (smoothingGroups.begin(),smoothingGroups.end()); - smoothingGroups.resize(mesh->mNumFaces,0); + std::vector &smoothingGroups = layer.mPointReferrers; + smoothingGroups.erase(smoothingGroups.begin(), smoothingGroups.end()); + smoothingGroups.resize(mesh->mNumFaces, 0); // now convert all faces unsigned int vert = 0; std::vector::iterator outIt = smoothingGroups.begin(); - for (it = sorted.begin(); it != end;++it,++outIt) { - const LWO::Face& face = layer.mFaces[*it]; + for (it = sorted.begin(); it != end; ++it, ++outIt) { + const LWO::Face &face = layer.mFaces[*it]; *outIt = face.smoothGroup; // copy all vertices - for (unsigned int q = 0; q < face.mNumIndices;++q,++vert) { + for (unsigned int q = 0; q < face.mNumIndices; ++q, ++vert) { unsigned int idx = face.mIndices[q]; *pv++ = layer.mTempPoints[idx] /*- layer.mPivot*/; // process UV coordinates - for (unsigned int w = 0; w < AI_MAX_NUMBER_OF_TEXTURECOORDS;++w) { + for (unsigned int w = 0; w < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++w) { if (UINT_MAX == vUVChannelIndices[w]) { break; } - aiVector3D*& pp = pvUV[w]; - const aiVector2D& src = ((aiVector2D*)&layer.mUVChannels[vUVChannelIndices[w]].rawData[0])[idx]; + aiVector3D *&pp = pvUV[w]; + const aiVector2D &src = ((aiVector2D *)&layer.mUVChannels[vUVChannelIndices[w]].rawData[0])[idx]; pp->x = src.x; pp->y = src.y; pp++; } // process normals (MODO extension) - if (nrm) { - *nrm = ((aiVector3D*)&layer.mNormals.rawData[0])[idx]; + if (nrm) { + *nrm = ((aiVector3D *)&layer.mNormals.rawData[0])[idx]; nrm->z *= -1.f; ++nrm; } // process vertex colors - for (unsigned int w = 0; w < AI_MAX_NUMBER_OF_COLOR_SETS;++w) { + for (unsigned int w = 0; w < AI_MAX_NUMBER_OF_COLOR_SETS; ++w) { if (UINT_MAX == vVColorIndices[w]) { break; } - *pvVC[w] = ((aiColor4D*)&layer.mVColorChannels[vVColorIndices[w]].rawData[0])[idx]; + *pvVC[w] = ((aiColor4D *)&layer.mVColorChannels[vVColorIndices[w]].rawData[0])[idx]; // If a RGB color map is explicitly requested delete the // alpha channel - it could theoretically be != 1. - if(_mSurfaces[i].mVCMapType == AI_LWO_RGB) + if (_mSurfaces[i].mVCMapType == AI_LWO_RGB) pvVC[w]->a = 1.f; pvVC[w]++; @@ -415,17 +412,17 @@ void LWOImporter::InternReadFile( const std::string& pFile, } pf->mIndices = face.mIndices; pf->mNumIndices = face.mNumIndices; - unsigned int** p = (unsigned int**)&face.mIndices;*p = NULL; // HACK: make sure it won't be deleted + unsigned int **facePtr = (unsigned int **)&face.mIndices; + *facePtr = nullptr; // HACK: make sure it won't be deleted pf++; } - if (!mesh->mNormals) { + if (!mesh->mNormals) { // Compute normal vectors for the mesh - we can't use our GenSmoothNormal- // Step here since it wouldn't handle smoothing groups correctly for LWO. // So we use a separate implementation. - ComputeNormals(mesh,smoothingGroups,_mSurfaces[i]); - } - else { + ComputeNormals(mesh, smoothingGroups, _mSurfaces[i]); + } else { ASSIMP_LOG_DEBUG("LWO2: No need to compute normals, they're already there"); } ++p; @@ -435,14 +432,14 @@ void LWOImporter::InternReadFile( const std::string& pFile, // Generate nodes to render the mesh. Store the source layer in the mParent member of the nodes unsigned int num = static_cast(apcMeshes.size() - meshStart); if (layer.mName != "" || num > 0) { - aiNode* pcNode = new aiNode(); + aiNode *pcNode = new aiNode(); pcNode->mName.Set(layer.mName); - pcNode->mParent = (aiNode*)&layer; + pcNode->mParent = (aiNode *)&layer; pcNode->mNumMeshes = num; if (pcNode->mNumMeshes) { pcNode->mMeshes = new unsigned int[pcNode->mNumMeshes]; - for (unsigned int p = 0; p < pcNode->mNumMeshes;++p) + for (unsigned int p = 0; p < pcNode->mNumMeshes; ++p) pcNode->mMeshes[p] = p + meshStart; } apcNodes[layer.mIndex] = pcNode; @@ -453,70 +450,67 @@ void LWOImporter::InternReadFile( const std::string& pFile, throw DeadlyImportError("LWO: No meshes loaded"); // The RemoveRedundantMaterials step will clean this up later - pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials = (unsigned int)mSurfaces->size()]; - for (unsigned int mat = 0; mat < pScene->mNumMaterials;++mat) { - aiMaterial* pcMat = new aiMaterial(); + pScene->mMaterials = new aiMaterial *[pScene->mNumMaterials = (unsigned int)mSurfaces->size()]; + for (unsigned int mat = 0; mat < pScene->mNumMaterials; ++mat) { + aiMaterial *pcMat = new aiMaterial(); pScene->mMaterials[mat] = pcMat; - ConvertMaterial((*mSurfaces)[mat],pcMat); + ConvertMaterial((*mSurfaces)[mat], pcMat); } // copy the meshes to the output structure - pScene->mMeshes = new aiMesh*[ pScene->mNumMeshes = (unsigned int)apcMeshes.size() ]; - ::memcpy(pScene->mMeshes,&apcMeshes[0],pScene->mNumMeshes*sizeof(void*)); + pScene->mMeshes = new aiMesh *[pScene->mNumMeshes = (unsigned int)apcMeshes.size()]; + ::memcpy(pScene->mMeshes, &apcMeshes[0], pScene->mNumMeshes * sizeof(void *)); // generate the final node graph GenerateNodeGraph(apcNodes); } // ------------------------------------------------------------------------------------------------ -void LWOImporter::ComputeNormals(aiMesh* mesh, const std::vector& smoothingGroups, - const LWO::Surface& surface) -{ +void LWOImporter::ComputeNormals(aiMesh *mesh, const std::vector &smoothingGroups, + const LWO::Surface &surface) { // Allocate output storage mesh->mNormals = new aiVector3D[mesh->mNumVertices]; // First generate per-face normals - aiVector3D* out; + aiVector3D *out; std::vector faceNormals; // ... in some cases that's already enough if (!surface.mMaximumSmoothAngle) out = mesh->mNormals; - else { + else { faceNormals.resize(mesh->mNumVertices); out = &faceNormals[0]; } - aiFace* begin = mesh->mFaces, *const end = mesh->mFaces+mesh->mNumFaces; - for (; begin != end; ++begin) { - aiFace& face = *begin; + aiFace *begin = mesh->mFaces, *const end = mesh->mFaces + mesh->mNumFaces; + for (; begin != end; ++begin) { + aiFace &face = *begin; - if(face.mNumIndices < 3) { + if (face.mNumIndices < 3) { continue; } // LWO doc: "the normal is defined as the cross product of the first and last edges" - aiVector3D* pV1 = mesh->mVertices + face.mIndices[0]; - aiVector3D* pV2 = mesh->mVertices + face.mIndices[1]; - aiVector3D* pV3 = mesh->mVertices + face.mIndices[face.mNumIndices-1]; + aiVector3D *pV1 = mesh->mVertices + face.mIndices[0]; + aiVector3D *pV2 = mesh->mVertices + face.mIndices[1]; + aiVector3D *pV3 = mesh->mVertices + face.mIndices[face.mNumIndices - 1]; - aiVector3D vNor = ((*pV2 - *pV1) ^(*pV3 - *pV1)).Normalize(); - for (unsigned int i = 0; i < face.mNumIndices;++i) + aiVector3D vNor = ((*pV2 - *pV1) ^ (*pV3 - *pV1)).Normalize(); + for (unsigned int i = 0; i < face.mNumIndices; ++i) out[face.mIndices[i]] = vNor; } - if (!surface.mMaximumSmoothAngle)return; + if (!surface.mMaximumSmoothAngle) return; const float posEpsilon = ComputePositionEpsilon(mesh); // Now generate the spatial sort tree SGSpatialSort sSort; std::vector::const_iterator it = smoothingGroups.begin(); - for( begin = mesh->mFaces; begin != end; ++begin, ++it) - { - aiFace& face = *begin; - for (unsigned int i = 0; i < face.mNumIndices;++i) - { + for (begin = mesh->mFaces; begin != end; ++begin, ++it) { + aiFace &face = *begin; + for (unsigned int i = 0; i < face.mNumIndices; ++i) { unsigned int tt = face.mIndices[i]; - sSort.Add(mesh->mVertices[tt],tt,*it); + sSort.Add(mesh->mVertices[tt], tt, *it); } } // Sort everything - this takes O(nlogn) time @@ -526,21 +520,19 @@ void LWOImporter::ComputeNormals(aiMesh* mesh, const std::vector& // Generate vertex normals. We have O(logn) for the binary lookup, which we need // for n elements, thus the EXPECTED complexity is O(nlogn) - if (surface.mMaximumSmoothAngle < 3.f && !configSpeedFlag) { + if (surface.mMaximumSmoothAngle < 3.f && !configSpeedFlag) { const float fLimit = std::cos(surface.mMaximumSmoothAngle); - for( begin = mesh->mFaces, it = smoothingGroups.begin(); begin != end; ++begin, ++it) { - const aiFace& face = *begin; - unsigned int* beginIdx = face.mIndices, *const endIdx = face.mIndices+face.mNumIndices; - for (; beginIdx != endIdx; ++beginIdx) - { + for (begin = mesh->mFaces, it = smoothingGroups.begin(); begin != end; ++begin, ++it) { + const aiFace &face = *begin; + unsigned int *beginIdx = face.mIndices, *const endIdx = face.mIndices + face.mNumIndices; + for (; beginIdx != endIdx; ++beginIdx) { unsigned int idx = *beginIdx; - sSort.FindPositions(mesh->mVertices[idx],*it,posEpsilon,poResult,true); - std::vector::const_iterator a, end = poResult.end(); + sSort.FindPositions(mesh->mVertices[idx], *it, posEpsilon, poResult, true); aiVector3D vNormals; - for (a = poResult.begin();a != end;++a) { - const aiVector3D& v = faceNormals[*a]; + for (std::vector::const_iterator a = poResult.begin(); a != poResult.end(); ++a) { + const aiVector3D &v = faceNormals[*a]; if (v * faceNormals[idx] < fLimit) continue; vNormals += v; @@ -549,27 +541,25 @@ void LWOImporter::ComputeNormals(aiMesh* mesh, const std::vector& } } } - // faster code path in case there is no smooth angle - else { - std::vector vertexDone(mesh->mNumVertices,false); - for( begin = mesh->mFaces, it = smoothingGroups.begin(); begin != end; ++begin, ++it) { - const aiFace& face = *begin; - unsigned int* beginIdx = face.mIndices, *const endIdx = face.mIndices+face.mNumIndices; - for (; beginIdx != endIdx; ++beginIdx) - { + // faster code path in case there is no smooth angle + else { + std::vector vertexDone(mesh->mNumVertices, false); + for (begin = mesh->mFaces, it = smoothingGroups.begin(); begin != end; ++begin, ++it) { + const aiFace &face = *begin; + unsigned int *beginIdx = face.mIndices, *const endIdx = face.mIndices + face.mNumIndices; + for (; beginIdx != endIdx; ++beginIdx) { unsigned int idx = *beginIdx; if (vertexDone[idx]) continue; - sSort.FindPositions(mesh->mVertices[idx],*it,posEpsilon,poResult,true); - std::vector::const_iterator a, end = poResult.end(); + sSort.FindPositions(mesh->mVertices[idx], *it, posEpsilon, poResult, true); aiVector3D vNormals; - for (a = poResult.begin();a != end;++a) { - const aiVector3D& v = faceNormals[*a]; + for (std::vector::const_iterator a = poResult.begin(); a != poResult.end(); ++a) { + const aiVector3D &v = faceNormals[*a]; vNormals += v; } vNormals.Normalize(); - for (a = poResult.begin();a != end;++a) { + for (std::vector::const_iterator a = poResult.begin(); a != poResult.end(); ++a) { mesh->mNormals[*a] = vNormals; vertexDone[*a] = true; } @@ -579,23 +569,22 @@ void LWOImporter::ComputeNormals(aiMesh* mesh, const std::vector& } // ------------------------------------------------------------------------------------------------ -void LWOImporter::GenerateNodeGraph(std::map& apcNodes) -{ +void LWOImporter::GenerateNodeGraph(std::map &apcNodes) { // now generate the final nodegraph - generate a root node and attach children - aiNode* root = pScene->mRootNode = new aiNode(); + aiNode *root = mScene->mRootNode = new aiNode(); root->mName.Set(""); //Set parent of all children, inserting pivots - std::map mapPivot; + std::map mapPivot; for (auto itapcNodes = apcNodes.begin(); itapcNodes != apcNodes.end(); ++itapcNodes) { //Get the parent index - LWO::Layer* nodeLayer = (LWO::Layer*)(itapcNodes->second->mParent); + LWO::Layer *nodeLayer = (LWO::Layer *)(itapcNodes->second->mParent); uint16_t parentIndex = nodeLayer->mParent; //Create pivot node, store it into the pivot map, and set the parent as the pivot - aiNode* pivotNode = new aiNode(); - pivotNode->mName.Set("Pivot-"+std::string(itapcNodes->second->mName.data)); + aiNode *pivotNode = new aiNode(); + pivotNode->mName.Set("Pivot-" + std::string(itapcNodes->second->mName.data)); itapcNodes->second->mParent = pivotNode; //Look for the parent node to attach the pivot to @@ -613,7 +602,7 @@ void LWOImporter::GenerateNodeGraph(std::map& apcNodes) pivotNode->mTransformation.a4 = nodeLayer->mPivot.x; pivotNode->mTransformation.b4 = nodeLayer->mPivot.y; pivotNode->mTransformation.c4 = nodeLayer->mPivot.z; - mapPivot[-(itapcNodes->first+2)] = pivotNode; + mapPivot[-(itapcNodes->first + 2)] = pivotNode; } //Merge pivot map into node map @@ -622,7 +611,7 @@ void LWOImporter::GenerateNodeGraph(std::map& apcNodes) } //Set children of all parents - apcNodes[-1] = root; + apcNodes[(uint16_t)-1] = root; for (auto itMapParentNodes = apcNodes.begin(); itMapParentNodes != apcNodes.end(); ++itMapParentNodes) { for (auto itMapChildNodes = apcNodes.begin(); itMapChildNodes != apcNodes.end(); ++itMapChildNodes) { if ((itMapParentNodes->first != itMapChildNodes->first) && (itMapParentNodes->second == itMapChildNodes->second->mParent)) { @@ -630,7 +619,7 @@ void LWOImporter::GenerateNodeGraph(std::map& apcNodes) } } if (itMapParentNodes->second->mNumChildren) { - itMapParentNodes->second->mChildren = new aiNode* [ itMapParentNodes->second->mNumChildren ]; + itMapParentNodes->second->mChildren = new aiNode *[itMapParentNodes->second->mNumChildren]; uint16_t p = 0; for (auto itMapChildNodes = apcNodes.begin(); itMapChildNodes != apcNodes.end(); ++itMapChildNodes) { if ((itMapParentNodes->first != itMapChildNodes->first) && (itMapParentNodes->second == itMapChildNodes->second->mParent)) { @@ -640,37 +629,36 @@ void LWOImporter::GenerateNodeGraph(std::map& apcNodes) } } - if (!pScene->mRootNode->mNumChildren) + if (!mScene->mRootNode->mNumChildren) throw DeadlyImportError("LWO: Unable to build a valid node graph"); // Remove a single root node with no meshes assigned to it ... - if (1 == pScene->mRootNode->mNumChildren) { - aiNode* pc = pScene->mRootNode->mChildren[0]; - pc->mParent = pScene->mRootNode->mChildren[0] = NULL; - delete pScene->mRootNode; - pScene->mRootNode = pc; + if (1 == mScene->mRootNode->mNumChildren) { + aiNode *pc = mScene->mRootNode->mChildren[0]; + pc->mParent = mScene->mRootNode->mChildren[0] = nullptr; + delete mScene->mRootNode; + mScene->mRootNode = pc; } // convert the whole stuff to RH with CCW winding MakeLeftHandedProcess maker; - maker.Execute(pScene); + maker.Execute(mScene); FlipWindingOrderProcess flipper; - flipper.Execute(pScene); + flipper.Execute(mScene); } // ------------------------------------------------------------------------------------------------ -void LWOImporter::ResolveTags() -{ +void LWOImporter::ResolveTags() { // --- this function is used for both LWO2 and LWOB mMapping->resize(mTags->size(), UINT_MAX); - for (unsigned int a = 0; a < mTags->size();++a) { + for (unsigned int a = 0; a < mTags->size(); ++a) { - const std::string& c = (*mTags)[a]; - for (unsigned int i = 0; i < mSurfaces->size();++i) { + const std::string &c = (*mTags)[a]; + for (unsigned int i = 0; i < mSurfaces->size(); ++i) { - const std::string& d = (*mSurfaces)[i].mName; - if (!ASSIMP_stricmp(c,d)) { + const std::string &d = (*mSurfaces)[i].mName; + if (!ASSIMP_stricmp(c, d)) { (*mMapping)[a] = i; break; @@ -680,25 +668,24 @@ void LWOImporter::ResolveTags() } // ------------------------------------------------------------------------------------------------ -void LWOImporter::ResolveClips() -{ - for( unsigned int i = 0; i < mClips.size();++i) { +void LWOImporter::ResolveClips() { + for (unsigned int i = 0; i < mClips.size(); ++i) { - Clip& clip = mClips[i]; + Clip &clip = mClips[i]; if (Clip::REF == clip.type) { - if (clip.clipRef >= mClips.size()) { + if (clip.clipRef >= mClips.size()) { ASSIMP_LOG_ERROR("LWO2: Clip referrer index is out of range"); clip.clipRef = 0; } - Clip& dest = mClips[clip.clipRef]; + Clip &dest = mClips[clip.clipRef]; if (Clip::REF == dest.type) { ASSIMP_LOG_ERROR("LWO2: Clip references another clip reference"); clip.type = Clip::UNSUPPORTED; } - else { + else { clip.path = dest.path; clip.type = dest.type; } @@ -707,39 +694,35 @@ void LWOImporter::ResolveClips() } // ------------------------------------------------------------------------------------------------ -void LWOImporter::AdjustTexturePath(std::string& out) -{ +void LWOImporter::AdjustTexturePath(std::string &out) { // --- this function is used for both LWO2 and LWOB - if (!mIsLWO2 && ::strstr(out.c_str(), "(sequence)")) { + if (!mIsLWO2 && ::strstr(out.c_str(), "(sequence)")) { // remove the (sequence) and append 000 ASSIMP_LOG_INFO("LWOB: Sequence of animated texture found. It will be ignored"); - out = out.substr(0,out.length()-10) + "000"; + out = out.substr(0, out.length() - 10) + "000"; } // format: drive:path/file - we just need to insert a slash after the drive std::string::size_type n = out.find_first_of(':'); if (std::string::npos != n) { - out.insert(n+1,"/"); + out.insert(n + 1, "/"); } } // ------------------------------------------------------------------------------------------------ -void LWOImporter::LoadLWOTags(unsigned int size) -{ +void LWOImporter::LoadLWOTags(unsigned int size) { // --- this function is used for both LWO2 and LWOB - const char* szCur = (const char*)mFileBuffer, *szLast = szCur; - const char* const szEnd = szLast+size; - while (szCur < szEnd) - { - if (!(*szCur)) - { - const size_t len = (size_t)(szCur-szLast); + const char *szCur = (const char *)mFileBuffer, *szLast = szCur; + const char *const szEnd = szLast + size; + while (szCur < szEnd) { + if (!(*szCur)) { + const size_t len = (size_t)(szCur - szLast); // FIX: skip empty-sized tags if (len) - mTags->push_back(std::string(szLast,len)); - szCur += (len&0x1 ? 1 : 2); + mTags->push_back(std::string(szLast, len)); + szCur += (len & 0x1 ? 1 : 2); szLast = szCur; } szCur++; @@ -747,89 +730,82 @@ void LWOImporter::LoadLWOTags(unsigned int size) } // ------------------------------------------------------------------------------------------------ -void LWOImporter::LoadLWOPoints(unsigned int length) -{ +void LWOImporter::LoadLWOPoints(unsigned int length) { // --- this function is used for both LWO2 and LWOB but for // LWO2 we need to allocate 25% more storage - it could be we'll // need to duplicate some points later. const size_t vertexLen = 12; - if ((length % vertexLen) != 0) - { - throw DeadlyImportError( "LWO2: Points chunk length is not multiple of vertexLen (12)"); + if ((length % vertexLen) != 0) { + throw DeadlyImportError("LWO2: Points chunk length is not multiple of vertexLen (12)"); } unsigned int regularSize = (unsigned int)mCurLayer->mTempPoints.size() + length / 12; - if (mIsLWO2) - { - mCurLayer->mTempPoints.reserve ( regularSize + (regularSize>>2u) ); - mCurLayer->mTempPoints.resize ( regularSize ); + if (mIsLWO2) { + mCurLayer->mTempPoints.reserve(regularSize + (regularSize >> 2u)); + mCurLayer->mTempPoints.resize(regularSize); // initialize all point referrers with the default values - mCurLayer->mPointReferrers.reserve ( regularSize + (regularSize>>2u) ); - mCurLayer->mPointReferrers.resize ( regularSize, UINT_MAX ); - } - else mCurLayer->mTempPoints.resize( regularSize ); + mCurLayer->mPointReferrers.reserve(regularSize + (regularSize >> 2u)); + mCurLayer->mPointReferrers.resize(regularSize, UINT_MAX); + } else + mCurLayer->mTempPoints.resize(regularSize); - // perform endianness conversions + // perform endianness conversions #ifndef AI_BUILD_BIG_ENDIAN - for (unsigned int i = 0; i < length>>2;++i) - ByteSwap::Swap4( mFileBuffer + (i << 2)); + for (unsigned int i = 0; i> 2; ++i) + ByteSwap::Swap4(mFileBuffer + (i << 2)); #endif - ::memcpy(&mCurLayer->mTempPoints[0],mFileBuffer,length); + ::memcpy(&mCurLayer->mTempPoints[0], mFileBuffer, length); } // ------------------------------------------------------------------------------------------------ -void LWOImporter::LoadLWO2Polygons(unsigned int length) -{ - LE_NCONST uint16_t* const end = (LE_NCONST uint16_t*)(mFileBuffer+length); +void LWOImporter::LoadLWO2Polygons(unsigned int length) { + LE_NCONST uint16_t *const end = (LE_NCONST uint16_t *)(mFileBuffer + length); const uint32_t type = GetU4(); // Determine the type of the polygons - switch (type) - { - // read unsupported stuff too (although we won't process it) - case AI_LWO_MBAL: - ASSIMP_LOG_WARN("LWO2: Encountered unsupported primitive chunk (METABALL)"); - break; - case AI_LWO_CURV: - ASSIMP_LOG_WARN("LWO2: Encountered unsupported primitive chunk (SPLINE)");; - break; + switch (type) { + // read unsupported stuff too (although we won't process it) + case AI_LWO_MBAL: + ASSIMP_LOG_WARN("LWO2: Encountered unsupported primitive chunk (METABALL)"); + break; + case AI_LWO_CURV: + ASSIMP_LOG_WARN("LWO2: Encountered unsupported primitive chunk (SPLINE)"); + ; + break; - // These are ok with no restrictions - case AI_LWO_PTCH: - case AI_LWO_FACE: - case AI_LWO_BONE: - case AI_LWO_SUBD: - break; - default: + // These are ok with no restrictions + case AI_LWO_PTCH: + case AI_LWO_FACE: + case AI_LWO_BONE: + case AI_LWO_SUBD: + break; + default: - // hm!? wtf is this? ok ... - ASSIMP_LOG_ERROR("LWO2: Ignoring unknown polygon type."); - break; + // hm!? wtf is this? ok ... + ASSIMP_LOG_ERROR("LWO2: Ignoring unknown polygon type."); + break; } // first find out how many faces and vertices we'll finally need - uint16_t* cursor= (uint16_t*)mFileBuffer; + uint16_t *cursor = (uint16_t *)mFileBuffer; - unsigned int iNumFaces = 0,iNumVertices = 0; - CountVertsAndFacesLWO2(iNumVertices,iNumFaces,cursor,end); + unsigned int iNumFaces = 0, iNumVertices = 0; + CountVertsAndFacesLWO2(iNumVertices, iNumFaces, cursor, end); // allocate the output array and copy face indices - if (iNumFaces) - { - cursor = (uint16_t*)mFileBuffer; + if (iNumFaces) { + cursor = (uint16_t *)mFileBuffer; - mCurLayer->mFaces.resize(iNumFaces,LWO::Face(type)); + mCurLayer->mFaces.resize(iNumFaces, LWO::Face(type)); FaceList::iterator it = mCurLayer->mFaces.begin(); - CopyFaceIndicesLWO2(it,cursor,end); + CopyFaceIndicesLWO2(it, cursor, end); } } // ------------------------------------------------------------------------------------------------ -void LWOImporter::CountVertsAndFacesLWO2(unsigned int& verts, unsigned int& faces, - uint16_t*& cursor, const uint16_t* const end, unsigned int max) -{ - while (cursor < end && max--) - { +void LWOImporter::CountVertsAndFacesLWO2(unsigned int &verts, unsigned int &faces, + uint16_t *&cursor, const uint16_t *const end, unsigned int max) { + while (cursor < end && max--) { uint16_t numIndices; ::memcpy(&numIndices, cursor++, 2); AI_LSWAP2(numIndices); @@ -838,272 +814,252 @@ void LWOImporter::CountVertsAndFacesLWO2(unsigned int& verts, unsigned int& face verts += numIndices; ++faces; - for(uint16_t i = 0; i < numIndices; i++) - { - ReadVSizedIntLWO2((uint8_t*&)cursor); + for (uint16_t i = 0; i < numIndices; i++) { + ReadVSizedIntLWO2((uint8_t *&)cursor); } } } // ------------------------------------------------------------------------------------------------ -void LWOImporter::CopyFaceIndicesLWO2(FaceList::iterator& it, - uint16_t*& cursor, - const uint16_t* const end) -{ - while (cursor < end) - { - LWO::Face& face = *it++; +void LWOImporter::CopyFaceIndicesLWO2(FaceList::iterator &it, + uint16_t *&cursor, + const uint16_t *const end) { + while (cursor < end) { + LWO::Face &face = *it++; uint16_t numIndices; ::memcpy(&numIndices, cursor++, 2); AI_LSWAP2(numIndices); face.mNumIndices = numIndices & 0x03FF; - if(face.mNumIndices) /* byte swapping has already been done */ + if (face.mNumIndices) /* byte swapping has already been done */ { face.mIndices = new unsigned int[face.mNumIndices]; - for(unsigned int i = 0; i < face.mNumIndices; i++) - { - face.mIndices[i] = ReadVSizedIntLWO2((uint8_t*&)cursor) + mCurLayer->mPointIDXOfs; - if(face.mIndices[i] > mCurLayer->mTempPoints.size()) - { + for (unsigned int i = 0; i < face.mNumIndices; i++) { + face.mIndices[i] = ReadVSizedIntLWO2((uint8_t *&)cursor) + mCurLayer->mPointIDXOfs; + if (face.mIndices[i] > mCurLayer->mTempPoints.size()) { ASSIMP_LOG_WARN("LWO2: Failure evaluating face record, index is out of range"); - face.mIndices[i] = (unsigned int)mCurLayer->mTempPoints.size()-1; + face.mIndices[i] = (unsigned int)mCurLayer->mTempPoints.size() - 1; } } - } - else throw DeadlyImportError("LWO2: Encountered invalid face record with zero indices"); + } else + throw DeadlyImportError("LWO2: Encountered invalid face record with zero indices"); } } - // ------------------------------------------------------------------------------------------------ -void LWOImporter::LoadLWO2PolygonTags(unsigned int length) -{ - LE_NCONST uint8_t* const end = mFileBuffer+length; +void LWOImporter::LoadLWO2PolygonTags(unsigned int length) { + LE_NCONST uint8_t *const end = mFileBuffer + length; - AI_LWO_VALIDATE_CHUNK_LENGTH(length,PTAG,4); + AI_LWO_VALIDATE_CHUNK_LENGTH(length, PTAG, 4); uint32_t type = GetU4(); if (type != AI_LWO_SURF && type != AI_LWO_SMGP) return; - while (mFileBuffer < end) - { + while (mFileBuffer < end) { unsigned int i = ReadVSizedIntLWO2(mFileBuffer) + mCurLayer->mFaceIDXOfs; unsigned int j = GetU2(); - if (i >= mCurLayer->mFaces.size()) { + if (i >= mCurLayer->mFaces.size()) { ASSIMP_LOG_WARN("LWO2: face index in PTAG is out of range"); continue; } - switch (type) { + switch (type) { - case AI_LWO_SURF: - mCurLayer->mFaces[i].surfaceIndex = j; - break; - case AI_LWO_SMGP: /* is that really used? */ - mCurLayer->mFaces[i].smoothGroup = j; - break; + case AI_LWO_SURF: + mCurLayer->mFaces[i].surfaceIndex = j; + break; + case AI_LWO_SMGP: /* is that really used? */ + mCurLayer->mFaces[i].smoothGroup = j; + break; }; } } // ------------------------------------------------------------------------------------------------ template -VMapEntry* FindEntry(std::vector< T >& list,const std::string& name, bool perPoly) -{ - for (auto & elem : list) { +VMapEntry *FindEntry(std::vector &list, const std::string &name, bool perPoly) { + for (auto &elem : list) { if (elem.name == name) { - if (!perPoly) { + if (!perPoly) { ASSIMP_LOG_WARN("LWO2: Found two VMAP sections with equal names"); } return &elem; } } - list.push_back( T() ); - VMapEntry* p = &list.back(); + list.push_back(T()); + VMapEntry *p = &list.back(); p->name = name; return p; } // ------------------------------------------------------------------------------------------------ template -inline void CreateNewEntry(T& chan, unsigned int srcIdx) -{ +inline void CreateNewEntry(T &chan, unsigned int srcIdx) { if (!chan.name.length()) return; chan.abAssigned[srcIdx] = true; - chan.abAssigned.resize(chan.abAssigned.size()+1,false); + chan.abAssigned.resize(chan.abAssigned.size() + 1, false); - for (unsigned int a = 0; a < chan.dims;++a) - chan.rawData.push_back(chan.rawData[srcIdx*chan.dims+a]); + for (unsigned int a = 0; a < chan.dims; ++a) + chan.rawData.push_back(chan.rawData[srcIdx * chan.dims + a]); } // ------------------------------------------------------------------------------------------------ template -inline void CreateNewEntry(std::vector< T >& list, unsigned int srcIdx) -{ - for (auto &elem : list) { - CreateNewEntry( elem, srcIdx ); +inline void CreateNewEntry(std::vector &list, unsigned int srcIdx) { + for (auto &elem : list) { + CreateNewEntry(elem, srcIdx); } } // ------------------------------------------------------------------------------------------------ -inline void LWOImporter::DoRecursiveVMAPAssignment(VMapEntry* base, unsigned int numRead, - unsigned int idx, float* data) -{ +inline void LWOImporter::DoRecursiveVMAPAssignment(VMapEntry *base, unsigned int numRead, + unsigned int idx, float *data) { ai_assert(NULL != data); - LWO::ReferrerList& refList = mCurLayer->mPointReferrers; + LWO::ReferrerList &refList = mCurLayer->mPointReferrers; unsigned int i; if (idx >= base->abAssigned.size()) { throw DeadlyImportError("Bad index"); } base->abAssigned[idx] = true; - for (i = 0; i < numRead;++i) { - base->rawData[idx*base->dims+i]= data[i]; + for (i = 0; i < numRead; ++i) { + base->rawData[idx * base->dims + i] = data[i]; } if (UINT_MAX != (i = refList[idx])) { - DoRecursiveVMAPAssignment(base,numRead,i,data); + DoRecursiveVMAPAssignment(base, numRead, i, data); } } // ------------------------------------------------------------------------------------------------ -inline void AddToSingleLinkedList(ReferrerList& refList, unsigned int srcIdx, unsigned int destIdx) -{ - if(UINT_MAX == refList[srcIdx]) { +inline void AddToSingleLinkedList(ReferrerList &refList, unsigned int srcIdx, unsigned int destIdx) { + if (UINT_MAX == refList[srcIdx]) { refList[srcIdx] = destIdx; return; } - AddToSingleLinkedList(refList,refList[srcIdx],destIdx); + AddToSingleLinkedList(refList, refList[srcIdx], destIdx); } // ------------------------------------------------------------------------------------------------ // Load LWO2 vertex map -void LWOImporter::LoadLWO2VertexMap(unsigned int length, bool perPoly) -{ - LE_NCONST uint8_t* const end = mFileBuffer+length; +void LWOImporter::LoadLWO2VertexMap(unsigned int length, bool perPoly) { + LE_NCONST uint8_t *const end = mFileBuffer + length; - AI_LWO_VALIDATE_CHUNK_LENGTH(length,VMAP,6); + AI_LWO_VALIDATE_CHUNK_LENGTH(length, VMAP, 6); unsigned int type = GetU4(); unsigned int dims = GetU2(); - VMapEntry* base; + VMapEntry *base; // read the name of the vertex map std::string name; - GetS0(name,length); + GetS0(name, length); - switch (type) - { - case AI_LWO_TXUV: - if (dims != 2) { - ASSIMP_LOG_WARN("LWO2: Skipping UV channel \'" - + name + "\' with !2 components"); - return; - } - base = FindEntry(mCurLayer->mUVChannels,name,perPoly); - break; - case AI_LWO_WGHT: - case AI_LWO_MNVW: - if (dims != 1) { - ASSIMP_LOG_WARN("LWO2: Skipping Weight Channel \'" - + name + "\' with !1 components"); - return; - } - base = FindEntry((type == AI_LWO_WGHT ? mCurLayer->mWeightChannels - : mCurLayer->mSWeightChannels),name,perPoly); - break; - case AI_LWO_RGB: - case AI_LWO_RGBA: - if (dims != 3 && dims != 4) { - ASSIMP_LOG_WARN("LWO2: Skipping Color Map \'" - + name + "\' with a dimension > 4 or < 3"); - return; - } - base = FindEntry(mCurLayer->mVColorChannels,name,perPoly); - break; + switch (type) { + case AI_LWO_TXUV: + if (dims != 2) { + ASSIMP_LOG_WARN("LWO2: Skipping UV channel \'" + name + "\' with !2 components"); + return; + } + base = FindEntry(mCurLayer->mUVChannels, name, perPoly); + break; + case AI_LWO_WGHT: + case AI_LWO_MNVW: + if (dims != 1) { + ASSIMP_LOG_WARN("LWO2: Skipping Weight Channel \'" + name + "\' with !1 components"); + return; + } + base = FindEntry((type == AI_LWO_WGHT ? mCurLayer->mWeightChannels : mCurLayer->mSWeightChannels), name, perPoly); + break; + case AI_LWO_RGB: + case AI_LWO_RGBA: + if (dims != 3 && dims != 4) { + ASSIMP_LOG_WARN("LWO2: Skipping Color Map \'" + name + "\' with a dimension > 4 or < 3"); + return; + } + base = FindEntry(mCurLayer->mVColorChannels, name, perPoly); + break; - case AI_LWO_MODO_NORM: - /* This is a non-standard extension chunk used by Luxology's MODO. + case AI_LWO_MODO_NORM: + /* This is a non-standard extension chunk used by Luxology's MODO. * It stores per-vertex normals. This VMAP exists just once, has * 3 dimensions and is btw extremely beautiful. */ - if (name != "vert_normals" || dims != 3 || mCurLayer->mNormals.name.length()) + if (name != "vert_normals" || dims != 3 || mCurLayer->mNormals.name.length()) + return; + + ASSIMP_LOG_INFO("Processing non-standard extension: MODO VMAP.NORM.vert_normals"); + + mCurLayer->mNormals.name = name; + base = &mCurLayer->mNormals; + break; + + case AI_LWO_PICK: /* these VMAPs are just silently dropped */ + case AI_LWO_MORF: + case AI_LWO_SPOT: return; - ASSIMP_LOG_INFO("Processing non-standard extension: MODO VMAP.NORM.vert_normals"); - - mCurLayer->mNormals.name = name; - base = & mCurLayer->mNormals; - break; - - case AI_LWO_PICK: /* these VMAPs are just silently dropped */ - case AI_LWO_MORF: - case AI_LWO_SPOT: - return; - - default: - if (name == "APS.Level") { - // XXX handle this (seems to be subdivision-related). - } - ASSIMP_LOG_WARN_F("LWO2: Skipping unknown VMAP/VMAD channel \'", name, "\'"); - return; + default: + if (name == "APS.Level") { + // XXX handle this (seems to be subdivision-related). + } + ASSIMP_LOG_WARN_F("LWO2: Skipping unknown VMAP/VMAD channel \'", name, "\'"); + return; }; base->Allocate((unsigned int)mCurLayer->mTempPoints.size()); // now read all entries in the map - type = std::min(dims,base->dims); - const unsigned int diff = (dims - type)<<2u; + type = std::min(dims, base->dims); + const unsigned int diff = (dims - type) << 2u; - LWO::FaceList& list = mCurLayer->mFaces; - LWO::PointList& pointList = mCurLayer->mTempPoints; - LWO::ReferrerList& refList = mCurLayer->mPointReferrers; + LWO::FaceList &list = mCurLayer->mFaces; + LWO::PointList &pointList = mCurLayer->mTempPoints; + LWO::ReferrerList &refList = mCurLayer->mPointReferrers; const unsigned int numPoints = (unsigned int)pointList.size(); - const unsigned int numFaces = (unsigned int)list.size(); + const unsigned int numFaces = (unsigned int)list.size(); - while (mFileBuffer < end) { + while (mFileBuffer < end) { unsigned int idx = ReadVSizedIntLWO2(mFileBuffer) + mCurLayer->mPointIDXOfs; - if (idx >= numPoints) { + if (idx >= numPoints) { ASSIMP_LOG_WARN_F("LWO2: Failure evaluating VMAP/VMAD entry \'", name, "\', vertex index is out of range"); - mFileBuffer += base->dims<<2u; + mFileBuffer += base->dims << 2u; continue; } - if (perPoly) { + if (perPoly) { unsigned int polyIdx = ReadVSizedIntLWO2(mFileBuffer) + mCurLayer->mFaceIDXOfs; - if (base->abAssigned[idx]) { + if (base->abAssigned[idx]) { // we have already a VMAP entry for this vertex - thus // we need to duplicate the corresponding polygon. - if (polyIdx >= numFaces) { + if (polyIdx >= numFaces) { ASSIMP_LOG_WARN_F("LWO2: Failure evaluating VMAD entry \'", name, "\', polygon index is out of range"); - mFileBuffer += base->dims<<2u; + mFileBuffer += base->dims << 2u; continue; } - LWO::Face& src = list[polyIdx]; + LWO::Face &src = list[polyIdx]; // generate a new unique vertex for the corresponding index - but only // if we can find the index in the face bool had = false; - for (unsigned int i = 0; i < src.mNumIndices;++i) { + for (unsigned int i = 0; i < src.mNumIndices; ++i) { unsigned int srcIdx = src.mIndices[i], tmp = idx; do { if (tmp == srcIdx) break; - } - while ((tmp = refList[tmp]) != UINT_MAX); + } while ((tmp = refList[tmp]) != UINT_MAX); if (tmp == UINT_MAX) { continue; } had = true; - refList.resize(refList.size()+1, UINT_MAX); + refList.resize(refList.size() + 1, UINT_MAX); idx = (unsigned int)pointList.size(); src.mIndices[i] = (unsigned int)pointList.size(); @@ -1111,14 +1067,14 @@ void LWOImporter::LoadLWO2VertexMap(unsigned int length, bool perPoly) // store the index of the new vertex in the old vertex // so we get a single linked list we can traverse in // only one direction - AddToSingleLinkedList(refList,srcIdx,src.mIndices[i]); + AddToSingleLinkedList(refList, srcIdx, src.mIndices[i]); pointList.push_back(pointList[srcIdx]); - CreateNewEntry(mCurLayer->mVColorChannels, srcIdx ); - CreateNewEntry(mCurLayer->mUVChannels, srcIdx ); - CreateNewEntry(mCurLayer->mWeightChannels, srcIdx ); - CreateNewEntry(mCurLayer->mSWeightChannels, srcIdx ); - CreateNewEntry(mCurLayer->mNormals, srcIdx ); + CreateNewEntry(mCurLayer->mVColorChannels, srcIdx); + CreateNewEntry(mCurLayer->mUVChannels, srcIdx); + CreateNewEntry(mCurLayer->mWeightChannels, srcIdx); + CreateNewEntry(mCurLayer->mSWeightChannels, srcIdx); + CreateNewEntry(mCurLayer->mNormals, srcIdx); } if (!had) { ASSIMP_LOG_WARN_F("LWO2: Failure evaluating VMAD entry \'", name, "\', vertex index wasn't found in that polygon"); @@ -1128,94 +1084,94 @@ void LWOImporter::LoadLWO2VertexMap(unsigned int length, bool perPoly) } std::unique_ptr temp(new float[type]); - for (unsigned int l = 0; l < type;++l) + for (unsigned int l = 0; l < type; ++l) temp[l] = GetF4(); - DoRecursiveVMAPAssignment(base,type,idx, temp.get()); + DoRecursiveVMAPAssignment(base, type, idx, temp.get()); mFileBuffer += diff; } } // ------------------------------------------------------------------------------------------------ // Load LWO2 clip -void LWOImporter::LoadLWO2Clip(unsigned int length) -{ - AI_LWO_VALIDATE_CHUNK_LENGTH(length,CLIP,10); +void LWOImporter::LoadLWO2Clip(unsigned int length) { + AI_LWO_VALIDATE_CHUNK_LENGTH(length, CLIP, 10); mClips.push_back(LWO::Clip()); - LWO::Clip& clip = mClips.back(); + LWO::Clip &clip = mClips.back(); // first - get the index of the clip clip.idx = GetU4(); IFF::SubChunkHeader head = IFF::LoadSubChunk(mFileBuffer); - switch (head.type) - { - case AI_LWO_STIL: - AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,STIL,1); + switch (head.type) { + case AI_LWO_STIL: + AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, STIL, 1); - // "Normal" texture - GetS0(clip.path,head.length); - clip.type = Clip::STILL; - break; + // "Normal" texture + GetS0(clip.path, head.length); + clip.type = Clip::STILL; + break; - case AI_LWO_ISEQ: - AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,ISEQ,16); - // Image sequence. We'll later take the first. - { - uint8_t digits = GetU1(); mFileBuffer++; - int16_t offset = GetU2(); mFileBuffer+=4; - int16_t start = GetU2(); mFileBuffer+=4; + case AI_LWO_ISEQ: + AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, ISEQ, 16); + // Image sequence. We'll later take the first. + { + uint8_t digits = GetU1(); + mFileBuffer++; + int16_t offset = GetU2(); + mFileBuffer += 4; + int16_t start = GetU2(); + mFileBuffer += 4; - std::string s; - std::ostringstream ss; - GetS0(s,head.length); + std::string s; + std::ostringstream ss; + GetS0(s, head.length); - head.length -= (uint16_t)s.length()+1; - ss << s; - ss << std::setw(digits) << offset + start; - GetS0(s,head.length); - ss << s; - clip.path = ss.str(); - clip.type = Clip::SEQ; - } - break; + head.length -= (uint16_t)s.length() + 1; + ss << s; + ss << std::setw(digits) << offset + start; + GetS0(s, head.length); + ss << s; + clip.path = ss.str(); + clip.type = Clip::SEQ; + } + break; - case AI_LWO_STCC: - ASSIMP_LOG_WARN("LWO2: Color shifted images are not supported"); - break; + case AI_LWO_STCC: + ASSIMP_LOG_WARN("LWO2: Color shifted images are not supported"); + break; - case AI_LWO_ANIM: - ASSIMP_LOG_WARN("LWO2: Animated textures are not supported"); - break; + case AI_LWO_ANIM: + ASSIMP_LOG_WARN("LWO2: Animated textures are not supported"); + break; - case AI_LWO_XREF: - AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,XREF,4); + case AI_LWO_XREF: + AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, XREF, 4); - // Just a cross-reference to another CLIp - clip.type = Clip::REF; - clip.clipRef = GetU4(); - break; + // Just a cross-reference to another CLIp + clip.type = Clip::REF; + clip.clipRef = GetU4(); + break; - case AI_LWO_NEGA: - AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,NEGA,2); - clip.negate = (0 != GetU2()); - break; + case AI_LWO_NEGA: + AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, NEGA, 2); + clip.negate = (0 != GetU2()); + break; - default: - ASSIMP_LOG_WARN("LWO2: Encountered unknown CLIP sub-chunk"); + default: + ASSIMP_LOG_WARN("LWO2: Encountered unknown CLIP sub-chunk"); } } // ------------------------------------------------------------------------------------------------ // Load envelope description -void LWOImporter::LoadLWO2Envelope(unsigned int length) -{ - LE_NCONST uint8_t* const end = mFileBuffer + length; - AI_LWO_VALIDATE_CHUNK_LENGTH(length,ENVL,4); +void LWOImporter::LoadLWO2Envelope(unsigned int length) { + LE_NCONST uint8_t *const end = mFileBuffer + length; + AI_LWO_VALIDATE_CHUNK_LENGTH(length, ENVL, 4); mEnvelopes.push_back(LWO::Envelope()); - LWO::Envelope& envelope = mEnvelopes.back(); + LWO::Envelope &envelope = mEnvelopes.back(); // Get the index of the envelope envelope.index = ReadVSizedIntLWO2(mFileBuffer); @@ -1223,84 +1179,83 @@ void LWOImporter::LoadLWO2Envelope(unsigned int length) // It looks like there might be an extra U4 right after the index, // at least in modo (LXOB) files: we'll ignore it if it's zero, // otherwise it represents the start of a subchunk, so we backtrack. - if (mIsLXOB) - { + if (mIsLXOB) { uint32_t extra = GetU4(); - if (extra) - { + if (extra) { mFileBuffer -= 4; } } // ... and read all subchunks - while (true) - { - if (mFileBuffer + 6 >= end)break; + while (true) { + if (mFileBuffer + 6 >= end) break; LE_NCONST IFF::SubChunkHeader head = IFF::LoadSubChunk(mFileBuffer); if (mFileBuffer + head.length > end) throw DeadlyImportError("LWO2: Invalid envelope chunk length"); - uint8_t* const next = mFileBuffer+head.length; - switch (head.type) - { - // Type & representation of the envelope - case AI_LWO_TYPE: - AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,TYPE,2); - mFileBuffer++; // skip user format + uint8_t *const next = mFileBuffer + head.length; + switch (head.type) { + // Type & representation of the envelope + case AI_LWO_TYPE: + AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, TYPE, 2); + mFileBuffer++; // skip user format - // Determine type of envelope - envelope.type = (LWO::EnvelopeType)*mFileBuffer; - ++mFileBuffer; - break; + // Determine type of envelope + envelope.type = (LWO::EnvelopeType)*mFileBuffer; + ++mFileBuffer; + break; - // precondition - case AI_LWO_PRE: - AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,PRE,2); - envelope.pre = (LWO::PrePostBehaviour)GetU2(); - break; + // precondition + case AI_LWO_PRE: + AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, PRE, 2); + envelope.pre = (LWO::PrePostBehaviour)GetU2(); + break; - // postcondition - case AI_LWO_POST: - AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,POST,2); - envelope.post = (LWO::PrePostBehaviour)GetU2(); - break; + // postcondition + case AI_LWO_POST: + AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, POST, 2); + envelope.post = (LWO::PrePostBehaviour)GetU2(); + break; - // keyframe - case AI_LWO_KEY: - { - AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,KEY,8); + // keyframe + case AI_LWO_KEY: { + AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, KEY, 8); - envelope.keys.push_back(LWO::Key()); - LWO::Key& key = envelope.keys.back(); + envelope.keys.push_back(LWO::Key()); + LWO::Key &key = envelope.keys.back(); - key.time = GetF4(); - key.value = GetF4(); - break; + key.time = GetF4(); + key.value = GetF4(); + break; } - // interval interpolation - case AI_LWO_SPAN: - { - AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,SPAN,4); - if (envelope.keys.size()<2) + // interval interpolation + case AI_LWO_SPAN: { + AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, SPAN, 4); + if (envelope.keys.size() < 2) ASSIMP_LOG_WARN("LWO2: Unexpected SPAN chunk"); else { - LWO::Key& key = envelope.keys.back(); - switch (GetU4()) - { + LWO::Key &key = envelope.keys.back(); + switch (GetU4()) { case AI_LWO_STEP: - key.inter = LWO::IT_STEP;break; + key.inter = LWO::IT_STEP; + break; case AI_LWO_LINE: - key.inter = LWO::IT_LINE;break; + key.inter = LWO::IT_LINE; + break; case AI_LWO_TCB: - key.inter = LWO::IT_TCB;break; + key.inter = LWO::IT_TCB; + break; case AI_LWO_HERM: - key.inter = LWO::IT_HERM;break; + key.inter = LWO::IT_HERM; + break; case AI_LWO_BEZI: - key.inter = LWO::IT_BEZI;break; + key.inter = LWO::IT_BEZI; + break; case AI_LWO_BEZ2: - key.inter = LWO::IT_BEZ2;break; + key.inter = LWO::IT_BEZ2; + break; default: ASSIMP_LOG_WARN("LWO2: Unknown interval interpolation mode"); }; @@ -1310,9 +1265,9 @@ void LWOImporter::LoadLWO2Envelope(unsigned int length) break; } - default: - ASSIMP_LOG_WARN("LWO2: Encountered unknown ENVL subchunk"); - break; + default: + ASSIMP_LOG_WARN("LWO2: Encountered unknown ENVL subchunk"); + break; } // regardless how much we did actually read, go to the next chunk mFileBuffer = next; @@ -1321,59 +1276,54 @@ void LWOImporter::LoadLWO2Envelope(unsigned int length) // ------------------------------------------------------------------------------------------------ // Load file - master function -void LWOImporter::LoadLWO2File() -{ +void LWOImporter::LoadLWO2File() { bool skip = false; - LE_NCONST uint8_t* const end = mFileBuffer + fileSize; + LE_NCONST uint8_t *const end = mFileBuffer + fileSize; unsigned int iUnnamed = 0; - while (true) - { - if (mFileBuffer + sizeof(IFF::ChunkHeader) > end)break; + while (true) { + if (mFileBuffer + sizeof(IFF::ChunkHeader) > end) break; const IFF::ChunkHeader head = IFF::LoadChunk(mFileBuffer); - if (mFileBuffer + head.length > end) - { + if (mFileBuffer + head.length > end) { throw DeadlyImportError("LWO2: Chunk length points behind the file"); break; } - uint8_t* const next = mFileBuffer+head.length; + uint8_t *const next = mFileBuffer + head.length; - if(!head.length) { + if (!head.length) { mFileBuffer = next; continue; } - switch (head.type) - { - // new layer - case AI_LWO_LAYR: - { + switch (head.type) { + // new layer + case AI_LWO_LAYR: { // add a new layer to the list .... - mLayers->push_back ( LWO::Layer() ); - LWO::Layer& layer = mLayers->back(); + mLayers->push_back(LWO::Layer()); + LWO::Layer &layer = mLayers->back(); mCurLayer = &layer; - AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,LAYR,16); + AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, LAYR, 16); // layer index. layer.mIndex = GetU2(); // Continue loading this layer or ignore it? Check the layer index property - if (UINT_MAX != configLayerIndex && (configLayerIndex-1) != layer.mIndex) { + if (UINT_MAX != configLayerIndex && (configLayerIndex - 1) != layer.mIndex) { skip = true; - } - else skip = false; + } else + skip = false; // pivot point mFileBuffer += 2; /* unknown */ mCurLayer->mPivot.x = GetF4(); mCurLayer->mPivot.y = GetF4(); mCurLayer->mPivot.z = GetF4(); - GetS0(layer.mName,head.length-16); + GetS0(layer.mName, head.length - 16); // if the name is empty, generate a default name - if (layer.mName.empty()) { + if (layer.mName.empty()) { char buffer[128]; // should be sufficiently large ::ai_snprintf(buffer, 128, "Layer_%i", iUnnamed++); layer.mName = buffer; @@ -1382,13 +1332,14 @@ void LWOImporter::LoadLWO2File() // load this layer or ignore it? Check the layer name property if (configLayerName.length() && configLayerName != layer.mName) { skip = true; - } - else hasNamedLayer = true; + } else + hasNamedLayer = true; // optional: parent of this layer if (mFileBuffer + 2 <= next) layer.mParent = GetU2(); - else layer.mParent = -1; + else + layer.mParent = (uint16_t) -1; // Set layer skip parameter layer.skip = skip; @@ -1396,9 +1347,8 @@ void LWOImporter::LoadLWO2File() break; } - // vertex list - case AI_LWO_PNTS: - { + // vertex list + case AI_LWO_PNTS: { if (skip) break; @@ -1407,27 +1357,25 @@ void LWOImporter::LoadLWO2File() mCurLayer->mPointIDXOfs = old; break; } - // vertex tags - case AI_LWO_VMAD: - if (mCurLayer->mFaces.empty()) - { - ASSIMP_LOG_WARN("LWO2: Unexpected VMAD chunk"); - break; - } - // --- intentionally no break here - case AI_LWO_VMAP: - { + // vertex tags + case AI_LWO_VMAD: + if (mCurLayer->mFaces.empty()) { + ASSIMP_LOG_WARN("LWO2: Unexpected VMAD chunk"); + break; + } + // --- intentionally no break here + case AI_LWO_VMAP: { if (skip) break; if (mCurLayer->mTempPoints.empty()) ASSIMP_LOG_WARN("LWO2: Unexpected VMAP chunk"); - else LoadLWO2VertexMap(head.length,head.type == AI_LWO_VMAD); + else + LoadLWO2VertexMap(head.length, head.type == AI_LWO_VMAD); break; } - // face list - case AI_LWO_POLS: - { + // face list + case AI_LWO_POLS: { if (skip) break; @@ -1436,9 +1384,8 @@ void LWOImporter::LoadLWO2File() mCurLayer->mFaceIDXOfs = old; break; } - // polygon tags - case AI_LWO_PTAG: - { + // polygon tags + case AI_LWO_PTAG: { if (skip) break; @@ -1449,34 +1396,30 @@ void LWOImporter::LoadLWO2File() } break; } - // list of tags - case AI_LWO_TAGS: - { + // list of tags + case AI_LWO_TAGS: { if (!mTags->empty()) { ASSIMP_LOG_WARN("LWO2: SRFS chunk encountered twice"); - } else { + } else { LoadLWOTags(head.length); } break; } - // surface chunk - case AI_LWO_SURF: - { + // surface chunk + case AI_LWO_SURF: { LoadLWO2Surface(head.length); break; } - // clip chunk - case AI_LWO_CLIP: - { + // clip chunk + case AI_LWO_CLIP: { LoadLWO2Clip(head.length); break; } - // envelope chunk - case AI_LWO_ENVL: - { + // envelope chunk + case AI_LWO_ENVL: { LoadLWO2Envelope(head.length); break; } diff --git a/code/LWO/LWOLoader.h b/code/LWO/LWOLoader.h index 680f82923..e9eb7ff1c 100644 --- a/code/LWO/LWOLoader.h +++ b/code/LWO/LWOLoader.h @@ -76,9 +76,6 @@ public: LWOImporter(); ~LWOImporter(); - -public: - // ------------------------------------------------------------------- /** Returns whether the class can handle the format of the given file. * See BaseImporter::CanRead() for details. @@ -86,7 +83,6 @@ public: bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const; - // ------------------------------------------------------------------- /** Called prior to ReadFile(). * The function is a request to the importer to update its configuration @@ -389,7 +385,7 @@ protected: unsigned int fileSize; /** Output scene */ - aiScene* pScene; + aiScene* mScene; /** Configuration option: speed flag set? */ bool configSpeedFlag; @@ -406,8 +402,8 @@ protected: // ------------------------------------------------------------------------------------------------ -inline float LWOImporter::GetF4() -{ +inline +float LWOImporter::GetF4() { float f; ::memcpy(&f, mFileBuffer, 4); mFileBuffer += 4; diff --git a/code/LWO/LWOMaterial.cpp b/code/LWO/LWOMaterial.cpp index b2304a6be..65fcebddb 100644 --- a/code/LWO/LWOMaterial.cpp +++ b/code/LWO/LWOMaterial.cpp @@ -43,30 +43,24 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /** @file Implementation of the material oart of the LWO importer class */ - - #ifndef ASSIMP_BUILD_NO_LWO_IMPORTER // internal headers #include "LWOLoader.h" #include - using namespace Assimp; // ------------------------------------------------------------------------------------------------ template -T lerp(const T& one, const T& two, float val) -{ - return one + (two-one)*val; +T lerp(const T &one, const T &two, float val) { + return one + (two - one) * val; } // ------------------------------------------------------------------------------------------------ // Convert a lightwave mapping mode to our's -inline aiTextureMapMode GetMapMode(LWO::Texture::Wrap in) -{ - switch (in) - { +inline aiTextureMapMode GetMapMode(LWO::Texture::Wrap in) { + switch (in) { case LWO::Texture::REPEAT: return aiTextureMapMode_Wrap; @@ -84,15 +78,14 @@ inline aiTextureMapMode GetMapMode(LWO::Texture::Wrap in) } // ------------------------------------------------------------------------------------------------ -bool LWOImporter::HandleTextures(aiMaterial* pcMat, const TextureList& in, aiTextureType type) -{ +bool LWOImporter::HandleTextures(aiMaterial *pcMat, const TextureList &in, aiTextureType type) { ai_assert(NULL != pcMat); unsigned int cur = 0, temp = 0; aiString s; bool ret = false; - for (const auto &texture : in) { + for (const auto &texture : in) { if (!texture.enabled || !texture.bCanUse) continue; ret = true; @@ -101,9 +94,8 @@ bool LWOImporter::HandleTextures(aiMaterial* pcMat, const TextureList& in, aiTex // as they are, the GenUVcoords step will compute UV // channels if they're not there. - aiTextureMapping mapping; - switch (texture.mapMode) - { + aiTextureMapping mapping = aiTextureMapping_OTHER; + switch (texture.mapMode) { case LWO::Texture::Planar: mapping = aiTextureMapping_PLANE; break; @@ -120,20 +112,18 @@ bool LWOImporter::HandleTextures(aiMaterial* pcMat, const TextureList& in, aiTex ASSIMP_LOG_ERROR("LWO2: Unsupported texture mapping: FrontProjection"); mapping = aiTextureMapping_OTHER; break; - case LWO::Texture::UV: - { - if( UINT_MAX == texture.mRealUVIndex ) { - // We have no UV index for this texture, so we can't display it - continue; - } - - // add the UV source index - temp = texture.mRealUVIndex; - pcMat->AddProperty((int*)&temp,1,AI_MATKEY_UVWSRC(type,cur)); - - mapping = aiTextureMapping_UV; + case LWO::Texture::UV: { + if (UINT_MAX == texture.mRealUVIndex) { + // We have no UV index for this texture, so we can't display it + continue; } - break; + + // add the UV source index + temp = texture.mRealUVIndex; + pcMat->AddProperty((int *)&temp, 1, AI_MATKEY_UVWSRC(type, cur)); + + mapping = aiTextureMapping_UV; + } break; default: ai_assert(false); }; @@ -143,17 +133,17 @@ bool LWOImporter::HandleTextures(aiMaterial* pcMat, const TextureList& in, aiTex aiVector3D v; switch (texture.majorAxis) { case Texture::AXIS_X: - v = aiVector3D(1.0,0.0,0.0); + v = aiVector3D(1.0, 0.0, 0.0); break; case Texture::AXIS_Y: - v = aiVector3D(0.0,1.0,0.0); + v = aiVector3D(0.0, 1.0, 0.0); break; default: // case Texture::AXIS_Z: - v = aiVector3D(0.0,0.0,1.0); + v = aiVector3D(0.0, 0.0, 1.0); break; } - pcMat->AddProperty(&v,1,AI_MATKEY_TEXMAP_AXIS(type,cur)); + pcMat->AddProperty(&v, 1, AI_MATKEY_TEXMAP_AXIS(type, cur)); // Setup UV scalings for cylindric and spherical projections if (mapping == aiTextureMapping_CYLINDER || mapping == aiTextureMapping_SPHERE) { @@ -161,15 +151,15 @@ bool LWOImporter::HandleTextures(aiMaterial* pcMat, const TextureList& in, aiTex trafo.mScaling.x = texture.wrapAmountW; trafo.mScaling.y = texture.wrapAmountH; - static_assert(sizeof(aiUVTransform)/sizeof(ai_real) == 5, "sizeof(aiUVTransform)/sizeof(ai_real) == 5"); - pcMat->AddProperty(&trafo,1,AI_MATKEY_UVTRANSFORM(type,cur)); + static_assert(sizeof(aiUVTransform) / sizeof(ai_real) == 5, "sizeof(aiUVTransform)/sizeof(ai_real) == 5"); + pcMat->AddProperty(&trafo, 1, AI_MATKEY_UVTRANSFORM(type, cur)); } ASSIMP_LOG_DEBUG("LWO2: Setting up non-UV mapping"); } // The older LWOB format does not use indirect references to clips. // The file name of a texture is directly specified in the tex chunk. - if (mIsLWO2) { + if (mIsLWO2) { // find the corresponding clip (take the last one if multiple // share the same index) ClipList::iterator end = mClips.end(), candidate = end; @@ -178,9 +168,8 @@ bool LWOImporter::HandleTextures(aiMaterial* pcMat, const TextureList& in, aiTex if ((*clip).idx == temp) { candidate = clip; } - } - if (candidate == end) { + if (candidate == end) { ASSIMP_LOG_ERROR("LWO2: Clip index is out of bounds"); temp = 0; @@ -191,8 +180,7 @@ bool LWOImporter::HandleTextures(aiMaterial* pcMat, const TextureList& in, aiTex s.Set("$texture.png"); //continue; - } - else { + } else { if (Clip::UNSUPPORTED == (*candidate).type) { ASSIMP_LOG_ERROR("LWO2: Clip type is not supported"); continue; @@ -205,11 +193,9 @@ bool LWOImporter::HandleTextures(aiMaterial* pcMat, const TextureList& in, aiTex if ((*candidate).negate) { flags |= aiTextureFlags_Invert; } - pcMat->AddProperty(&flags,1,AI_MATKEY_TEXFLAGS(type,cur)); + pcMat->AddProperty(&flags, 1, AI_MATKEY_TEXFLAGS(type, cur)); } - } - else - { + } else { std::string ss = texture.mFileName; if (!ss.length()) { ASSIMP_LOG_WARN("LWOB: Empty file name"); @@ -218,14 +204,13 @@ bool LWOImporter::HandleTextures(aiMaterial* pcMat, const TextureList& in, aiTex AdjustTexturePath(ss); s.Set(ss); } - pcMat->AddProperty(&s,AI_MATKEY_TEXTURE(type,cur)); + pcMat->AddProperty(&s, AI_MATKEY_TEXTURE(type, cur)); // add the blend factor - pcMat->AddProperty(&texture.mStrength,1,AI_MATKEY_TEXBLEND(type,cur)); + pcMat->AddProperty(&texture.mStrength, 1, AI_MATKEY_TEXBLEND(type, cur)); // add the blend operation - switch (texture.blendType) - { + switch (texture.blendType) { case LWO::Texture::Normal: case LWO::Texture::Multiply: temp = (unsigned int)aiTextureOp_Multiply; @@ -247,10 +232,9 @@ bool LWOImporter::HandleTextures(aiMaterial* pcMat, const TextureList& in, aiTex default: temp = (unsigned int)aiTextureOp_Multiply; ASSIMP_LOG_WARN("LWO2: Unsupported texture blend mode: alpha or displacement"); - } // Setup texture operation - pcMat->AddProperty((int*)&temp,1,AI_MATKEY_TEXOP(type,cur)); + pcMat->AddProperty((int *)&temp, 1, AI_MATKEY_TEXOP(type, cur)); // setup the mapping mode int mapping_ = static_cast(mapping); @@ -258,11 +242,11 @@ bool LWOImporter::HandleTextures(aiMaterial* pcMat, const TextureList& in, aiTex // add the u-wrapping temp = (unsigned int)GetMapMode(texture.wrapModeWidth); - pcMat->AddProperty((int*)&temp,1,AI_MATKEY_MAPPINGMODE_U(type,cur)); + pcMat->AddProperty((int *)&temp, 1, AI_MATKEY_MAPPINGMODE_U(type, cur)); // add the v-wrapping temp = (unsigned int)GetMapMode(texture.wrapModeHeight); - pcMat->AddProperty((int*)&temp,1,AI_MATKEY_MAPPINGMODE_V(type,cur)); + pcMat->AddProperty((int *)&temp, 1, AI_MATKEY_MAPPINGMODE_V(type, cur)); ++cur; } @@ -270,94 +254,87 @@ bool LWOImporter::HandleTextures(aiMaterial* pcMat, const TextureList& in, aiTex } // ------------------------------------------------------------------------------------------------ -void LWOImporter::ConvertMaterial(const LWO::Surface& surf,aiMaterial* pcMat) -{ +void LWOImporter::ConvertMaterial(const LWO::Surface &surf, aiMaterial *pcMat) { // copy the name of the surface aiString st; st.Set(surf.mName); - pcMat->AddProperty(&st,AI_MATKEY_NAME); + pcMat->AddProperty(&st, AI_MATKEY_NAME); const int i = surf.bDoubleSided ? 1 : 0; - pcMat->AddProperty(&i,1,AI_MATKEY_TWOSIDED); + pcMat->AddProperty(&i, 1, AI_MATKEY_TWOSIDED); // add the refraction index and the bump intensity - pcMat->AddProperty(&surf.mIOR,1,AI_MATKEY_REFRACTI); - pcMat->AddProperty(&surf.mBumpIntensity,1,AI_MATKEY_BUMPSCALING); + pcMat->AddProperty(&surf.mIOR, 1, AI_MATKEY_REFRACTI); + pcMat->AddProperty(&surf.mBumpIntensity, 1, AI_MATKEY_BUMPSCALING); aiShadingMode m; - if (surf.mSpecularValue && surf.mGlossiness) - { + if (surf.mSpecularValue && surf.mGlossiness) { float fGloss; - if (mIsLWO2) { - fGloss = std::pow( surf.mGlossiness*ai_real( 10.0 )+ ai_real( 2.0 ), ai_real( 2.0 ) ); - } - else - { + if (mIsLWO2) { + fGloss = std::pow(surf.mGlossiness * ai_real(10.0) + ai_real(2.0), ai_real(2.0)); + } else { if (16.0 >= surf.mGlossiness) fGloss = 6.0; else if (64.0 >= surf.mGlossiness) fGloss = 20.0; else if (256.0 >= surf.mGlossiness) fGloss = 50.0; - else fGloss = 80.0; + else + fGloss = 80.0; } - pcMat->AddProperty(&surf.mSpecularValue,1,AI_MATKEY_SHININESS_STRENGTH); - pcMat->AddProperty(&fGloss,1,AI_MATKEY_SHININESS); + pcMat->AddProperty(&surf.mSpecularValue, 1, AI_MATKEY_SHININESS_STRENGTH); + pcMat->AddProperty(&fGloss, 1, AI_MATKEY_SHININESS); m = aiShadingMode_Phong; - } - else m = aiShadingMode_Gouraud; + } else + m = aiShadingMode_Gouraud; // specular color - aiColor3D clr = lerp( aiColor3D(1.0,1.0,1.0), surf.mColor, surf.mColorHighlights ); - pcMat->AddProperty(&clr,1,AI_MATKEY_COLOR_SPECULAR); - pcMat->AddProperty(&surf.mSpecularValue,1,AI_MATKEY_SHININESS_STRENGTH); + aiColor3D clr = lerp(aiColor3D(1.0, 1.0, 1.0), surf.mColor, surf.mColorHighlights); + pcMat->AddProperty(&clr, 1, AI_MATKEY_COLOR_SPECULAR); + pcMat->AddProperty(&surf.mSpecularValue, 1, AI_MATKEY_SHININESS_STRENGTH); // emissive color // luminosity is not really the same but it affects the surface in a similar way. Some scaling looks good. - clr.g = clr.b = clr.r = surf.mLuminosity*ai_real( 0.8 ); - pcMat->AddProperty(&clr,1,AI_MATKEY_COLOR_EMISSIVE); + clr.g = clr.b = clr.r = surf.mLuminosity * ai_real(0.8); + pcMat->AddProperty(&clr, 1, AI_MATKEY_COLOR_EMISSIVE); // opacity ... either additive or default-blended, please - if (0.0 != surf.mAdditiveTransparency) { + if (0.0 != surf.mAdditiveTransparency) { const int add = aiBlendMode_Additive; - pcMat->AddProperty(&surf.mAdditiveTransparency,1,AI_MATKEY_OPACITY); - pcMat->AddProperty(&add,1,AI_MATKEY_BLEND_FUNC); - } else if (10e10f != surf.mTransparency) { + pcMat->AddProperty(&surf.mAdditiveTransparency, 1, AI_MATKEY_OPACITY); + pcMat->AddProperty(&add, 1, AI_MATKEY_BLEND_FUNC); + } else if (10e10f != surf.mTransparency) { const int def = aiBlendMode_Default; - const float f = 1.0f-surf.mTransparency; - pcMat->AddProperty(&f,1,AI_MATKEY_OPACITY); - pcMat->AddProperty(&def,1,AI_MATKEY_BLEND_FUNC); + const float f = 1.0f - surf.mTransparency; + pcMat->AddProperty(&f, 1, AI_MATKEY_OPACITY); + pcMat->AddProperty(&def, 1, AI_MATKEY_BLEND_FUNC); } - // ADD TEXTURES to the material // TODO: find out how we can handle COLOR textures correctly... - bool b = HandleTextures(pcMat,surf.mColorTextures,aiTextureType_DIFFUSE); - b = (b || HandleTextures(pcMat,surf.mDiffuseTextures,aiTextureType_DIFFUSE)); - HandleTextures(pcMat,surf.mSpecularTextures,aiTextureType_SPECULAR); - HandleTextures(pcMat,surf.mGlossinessTextures,aiTextureType_SHININESS); - HandleTextures(pcMat,surf.mBumpTextures,aiTextureType_HEIGHT); - HandleTextures(pcMat,surf.mOpacityTextures,aiTextureType_OPACITY); - HandleTextures(pcMat,surf.mReflectionTextures,aiTextureType_REFLECTION); + bool b = HandleTextures(pcMat, surf.mColorTextures, aiTextureType_DIFFUSE); + b = (b || HandleTextures(pcMat, surf.mDiffuseTextures, aiTextureType_DIFFUSE)); + HandleTextures(pcMat, surf.mSpecularTextures, aiTextureType_SPECULAR); + HandleTextures(pcMat, surf.mGlossinessTextures, aiTextureType_SHININESS); + HandleTextures(pcMat, surf.mBumpTextures, aiTextureType_HEIGHT); + HandleTextures(pcMat, surf.mOpacityTextures, aiTextureType_OPACITY); + HandleTextures(pcMat, surf.mReflectionTextures, aiTextureType_REFLECTION); // Now we need to know which shader to use .. iterate through the shader list of // the surface and search for a name which we know ... - for (const auto &shader : surf.mShaders) { - if (shader.functionName == "LW_SuperCelShader" || shader.functionName == "AH_CelShader") { + for (const auto &shader : surf.mShaders) { + if (shader.functionName == "LW_SuperCelShader" || shader.functionName == "AH_CelShader") { ASSIMP_LOG_INFO("LWO2: Mapping LW_SuperCelShader/AH_CelShader to aiShadingMode_Toon"); m = aiShadingMode_Toon; break; - } - else if (shader.functionName == "LW_RealFresnel" || shader.functionName == "LW_FastFresnel") { + } else if (shader.functionName == "LW_RealFresnel" || shader.functionName == "LW_FastFresnel") { ASSIMP_LOG_INFO("LWO2: Mapping LW_RealFresnel/LW_FastFresnel to aiShadingMode_Fresnel"); m = aiShadingMode_Fresnel; break; - } - else - { + } else { ASSIMP_LOG_WARN_F("LWO2: Unknown surface shader: ", shader.functionName); } } @@ -368,22 +345,21 @@ void LWOImporter::ConvertMaterial(const LWO::Surface& surf,aiMaterial* pcMat) // (the diffuse value is just a scaling factor) // If a diffuse texture is set, we set this value to 1.0 - clr = (b && false ? aiColor3D(1.0,1.0,1.0) : surf.mColor); + clr = (b && false ? aiColor3D(1.0, 1.0, 1.0) : surf.mColor); clr.r *= surf.mDiffuseValue; clr.g *= surf.mDiffuseValue; clr.b *= surf.mDiffuseValue; - pcMat->AddProperty(&clr,1,AI_MATKEY_COLOR_DIFFUSE); + pcMat->AddProperty(&clr, 1, AI_MATKEY_COLOR_DIFFUSE); } // ------------------------------------------------------------------------------------------------ -char LWOImporter::FindUVChannels(LWO::TextureList& list, - LWO::Layer& /*layer*/,LWO::UVChannel& uv, unsigned int next) -{ +char LWOImporter::FindUVChannels(LWO::TextureList &list, + LWO::Layer & /*layer*/, LWO::UVChannel &uv, unsigned int next) { char ret = 0; - for (auto &texture : list) { + for (auto &texture : list) { // Ignore textures with non-UV mappings for the moment. - if (!texture.enabled || !texture.bCanUse || texture.mapMode != LWO::Texture::UV) { + if (!texture.enabled || !texture.bCanUse || texture.mapMode != LWO::Texture::UV) { continue; } @@ -391,11 +367,9 @@ char LWOImporter::FindUVChannels(LWO::TextureList& list, ret = 1; // got it. - if (texture.mRealUVIndex == UINT_MAX || texture.mRealUVIndex == next) - { + if (texture.mRealUVIndex == UINT_MAX || texture.mRealUVIndex == next) { texture.mRealUVIndex = next; - } - else { + } else { // channel mismatch. need to duplicate the material. ASSIMP_LOG_WARN("LWO: Channel mismatch, would need to duplicate surface [design bug]"); @@ -407,49 +381,48 @@ char LWOImporter::FindUVChannels(LWO::TextureList& list, } // ------------------------------------------------------------------------------------------------ -void LWOImporter::FindUVChannels(LWO::Surface& surf, - LWO::SortedRep& sorted,LWO::Layer& layer, - unsigned int out[AI_MAX_NUMBER_OF_TEXTURECOORDS]) -{ +void LWOImporter::FindUVChannels(LWO::Surface &surf, + LWO::SortedRep &sorted, LWO::Layer &layer, + unsigned int out[AI_MAX_NUMBER_OF_TEXTURECOORDS]) { unsigned int next = 0, extra = 0, num_extra = 0; // Check whether we have an UV entry != 0 for one of the faces in 'sorted' - for (unsigned int i = 0; i < layer.mUVChannels.size();++i) { - LWO::UVChannel& uv = layer.mUVChannels[i]; + for (unsigned int i = 0; i < layer.mUVChannels.size(); ++i) { + LWO::UVChannel &uv = layer.mUVChannels[i]; - for (LWO::SortedRep::const_iterator it = sorted.begin(); it != sorted.end(); ++it) { + for (LWO::SortedRep::const_iterator it = sorted.begin(); it != sorted.end(); ++it) { - LWO::Face& face = layer.mFaces[*it]; + LWO::Face &face = layer.mFaces[*it]; for (unsigned int n = 0; n < face.mNumIndices; ++n) { unsigned int idx = face.mIndices[n]; - if (uv.abAssigned[idx] && ((aiVector2D*)&uv.rawData[0])[idx] != aiVector2D()) { + if (uv.abAssigned[idx] && ((aiVector2D *)&uv.rawData[0])[idx] != aiVector2D()) { if (extra >= AI_MAX_NUMBER_OF_TEXTURECOORDS) { ASSIMP_LOG_ERROR("LWO: Maximum number of UV channels for " - "this mesh reached. Skipping channel \'" + uv.name + "\'"); + "this mesh reached. Skipping channel \'" + + uv.name + "\'"); - } - else { + } else { // Search through all textures assigned to 'surf' and look for this UV channel char had = 0; - had |= FindUVChannels(surf.mColorTextures,layer,uv,next); - had |= FindUVChannels(surf.mDiffuseTextures,layer,uv,next); - had |= FindUVChannels(surf.mSpecularTextures,layer,uv,next); - had |= FindUVChannels(surf.mGlossinessTextures,layer,uv,next); - had |= FindUVChannels(surf.mOpacityTextures,layer,uv,next); - had |= FindUVChannels(surf.mBumpTextures,layer,uv,next); - had |= FindUVChannels(surf.mReflectionTextures,layer,uv,next); + had |= FindUVChannels(surf.mColorTextures, layer, uv, next); + had |= FindUVChannels(surf.mDiffuseTextures, layer, uv, next); + had |= FindUVChannels(surf.mSpecularTextures, layer, uv, next); + had |= FindUVChannels(surf.mGlossinessTextures, layer, uv, next); + had |= FindUVChannels(surf.mOpacityTextures, layer, uv, next); + had |= FindUVChannels(surf.mBumpTextures, layer, uv, next); + had |= FindUVChannels(surf.mReflectionTextures, layer, uv, next); // We have a texture referencing this UV channel so we have to take special care // and are willing to drop unreferenced channels in favour of it. if (had != 0) { if (num_extra) { - for (unsigned int a = next; a < std::min( extra, AI_MAX_NUMBER_OF_TEXTURECOORDS-1u ); ++a) { - out[a+1] = out[a]; + for (unsigned int a = next; a < std::min(extra, AI_MAX_NUMBER_OF_TEXTURECOORDS - 1u); ++a) { + out[a + 1] = out[a]; } } ++extra; @@ -461,7 +434,7 @@ void LWOImporter::FindUVChannels(LWO::Surface& surf, ++num_extra; } } - it = sorted.end()-1; + it = sorted.end() - 1; break; } } @@ -473,42 +446,40 @@ void LWOImporter::FindUVChannels(LWO::Surface& surf, } // ------------------------------------------------------------------------------------------------ -void LWOImporter::FindVCChannels(const LWO::Surface& surf, LWO::SortedRep& sorted, const LWO::Layer& layer, - unsigned int out[AI_MAX_NUMBER_OF_COLOR_SETS]) -{ +void LWOImporter::FindVCChannels(const LWO::Surface &surf, LWO::SortedRep &sorted, const LWO::Layer &layer, + unsigned int out[AI_MAX_NUMBER_OF_COLOR_SETS]) { unsigned int next = 0; // Check whether we have an vc entry != 0 for one of the faces in 'sorted' - for (unsigned int i = 0; i < layer.mVColorChannels.size();++i) { - const LWO::VColorChannel& vc = layer.mVColorChannels[i]; + for (unsigned int i = 0; i < layer.mVColorChannels.size(); ++i) { + const LWO::VColorChannel &vc = layer.mVColorChannels[i]; if (surf.mVCMap == vc.name) { // The vertex color map is explicitly requested by the surface so we need to take special care of it - for (unsigned int a = 0; a < std::min(next,AI_MAX_NUMBER_OF_COLOR_SETS-1u); ++a) { - out[a+1] = out[a]; + for (unsigned int a = 0; a < std::min(next, AI_MAX_NUMBER_OF_COLOR_SETS - 1u); ++a) { + out[a + 1] = out[a]; } out[0] = i; ++next; - } - else { + } else { - for (LWO::SortedRep::iterator it = sorted.begin(); it != sorted.end(); ++it) { - const LWO::Face& face = layer.mFaces[*it]; + for (LWO::SortedRep::iterator it = sorted.begin(); it != sorted.end(); ++it) { + const LWO::Face &face = layer.mFaces[*it]; for (unsigned int n = 0; n < face.mNumIndices; ++n) { unsigned int idx = face.mIndices[n]; - if (vc.abAssigned[idx] && ((aiColor4D*)&vc.rawData[0])[idx] != aiColor4D(0.0,0.0,0.0,1.0)) { + if (vc.abAssigned[idx] && ((aiColor4D *)&vc.rawData[0])[idx] != aiColor4D(0.0, 0.0, 0.0, 1.0)) { if (next >= AI_MAX_NUMBER_OF_COLOR_SETS) { ASSIMP_LOG_ERROR("LWO: Maximum number of vertex color channels for " - "this mesh reached. Skipping channel \'" + vc.name + "\'"); + "this mesh reached. Skipping channel \'" + + vc.name + "\'"); - } - else { + } else { out[next++] = i; } - it = sorted.end()-1; + it = sorted.end() - 1; break; } } @@ -521,154 +492,149 @@ void LWOImporter::FindVCChannels(const LWO::Surface& surf, LWO::SortedRep& sorte } // ------------------------------------------------------------------------------------------------ -void LWOImporter::LoadLWO2ImageMap(unsigned int size, LWO::Texture& tex ) -{ - LE_NCONST uint8_t* const end = mFileBuffer + size; - while (true) - { - if (mFileBuffer + 6 >= end)break; +void LWOImporter::LoadLWO2ImageMap(unsigned int size, LWO::Texture &tex) { + LE_NCONST uint8_t *const end = mFileBuffer + size; + while (true) { + if (mFileBuffer + 6 >= end) break; LE_NCONST IFF::SubChunkHeader head = IFF::LoadSubChunk(mFileBuffer); if (mFileBuffer + head.length > end) throw DeadlyImportError("LWO2: Invalid SURF.BLOCK chunk length"); - uint8_t* const next = mFileBuffer+head.length; - switch (head.type) - { - case AI_LWO_PROJ: - tex.mapMode = (Texture::MappingMode)GetU2(); - break; - case AI_LWO_WRAP: - tex.wrapModeWidth = (Texture::Wrap)GetU2(); - tex.wrapModeHeight = (Texture::Wrap)GetU2(); - break; - case AI_LWO_AXIS: - tex.majorAxis = (Texture::Axes)GetU2(); - break; - case AI_LWO_IMAG: - tex.mClipIdx = GetU2(); - break; - case AI_LWO_VMAP: - GetS0(tex.mUVChannelIndex,head.length); - break; - case AI_LWO_WRPH: - tex.wrapAmountH = GetF4(); - break; - case AI_LWO_WRPW: - tex.wrapAmountW = GetF4(); - break; + uint8_t *const next = mFileBuffer + head.length; + switch (head.type) { + case AI_LWO_PROJ: + tex.mapMode = (Texture::MappingMode)GetU2(); + break; + case AI_LWO_WRAP: + tex.wrapModeWidth = (Texture::Wrap)GetU2(); + tex.wrapModeHeight = (Texture::Wrap)GetU2(); + break; + case AI_LWO_AXIS: + tex.majorAxis = (Texture::Axes)GetU2(); + break; + case AI_LWO_IMAG: + tex.mClipIdx = GetU2(); + break; + case AI_LWO_VMAP: + GetS0(tex.mUVChannelIndex, head.length); + break; + case AI_LWO_WRPH: + tex.wrapAmountH = GetF4(); + break; + case AI_LWO_WRPW: + tex.wrapAmountW = GetF4(); + break; } mFileBuffer = next; } } // ------------------------------------------------------------------------------------------------ -void LWOImporter::LoadLWO2Procedural(unsigned int /*size*/, LWO::Texture& tex ) -{ +void LWOImporter::LoadLWO2Procedural(unsigned int /*size*/, LWO::Texture &tex) { // --- not supported at the moment ASSIMP_LOG_ERROR("LWO2: Found procedural texture, this is not supported"); tex.bCanUse = false; } // ------------------------------------------------------------------------------------------------ -void LWOImporter::LoadLWO2Gradient(unsigned int /*size*/, LWO::Texture& tex ) -{ +void LWOImporter::LoadLWO2Gradient(unsigned int /*size*/, LWO::Texture &tex) { // --- not supported at the moment ASSIMP_LOG_ERROR("LWO2: Found gradient texture, this is not supported"); tex.bCanUse = false; } // ------------------------------------------------------------------------------------------------ -void LWOImporter::LoadLWO2TextureHeader(unsigned int size, LWO::Texture& tex ) -{ - LE_NCONST uint8_t* const end = mFileBuffer + size; +void LWOImporter::LoadLWO2TextureHeader(unsigned int size, LWO::Texture &tex) { + LE_NCONST uint8_t *const end = mFileBuffer + size; // get the ordinal string - GetS0( tex.ordinal, size); + GetS0(tex.ordinal, size); // we could crash later if this is an empty string ... - if (!tex.ordinal.length()) - { + if (!tex.ordinal.length()) { ASSIMP_LOG_ERROR("LWO2: Ill-formed SURF.BLOK ordinal string"); tex.ordinal = "\x00"; } - while (true) - { - if (mFileBuffer + 6 >= end)break; + while (true) { + if (mFileBuffer + 6 >= end) break; const IFF::SubChunkHeader head = IFF::LoadSubChunk(mFileBuffer); if (mFileBuffer + head.length > end) throw DeadlyImportError("LWO2: Invalid texture header chunk length"); - uint8_t* const next = mFileBuffer+head.length; - switch (head.type) - { - case AI_LWO_CHAN: - tex.type = GetU4(); - break; - case AI_LWO_ENAB: - tex.enabled = GetU2() ? true : false; - break; - case AI_LWO_OPAC: - tex.blendType = (Texture::BlendType)GetU2(); - tex.mStrength = GetF4(); - break; + uint8_t *const next = mFileBuffer + head.length; + switch (head.type) { + case AI_LWO_CHAN: + tex.type = GetU4(); + break; + case AI_LWO_ENAB: + tex.enabled = GetU2() ? true : false; + break; + case AI_LWO_OPAC: + tex.blendType = (Texture::BlendType)GetU2(); + tex.mStrength = GetF4(); + break; } mFileBuffer = next; } } // ------------------------------------------------------------------------------------------------ -void LWOImporter::LoadLWO2TextureBlock(LE_NCONST IFF::SubChunkHeader* head, unsigned int size ) -{ +void LWOImporter::LoadLWO2TextureBlock(LE_NCONST IFF::SubChunkHeader *head, unsigned int size) { ai_assert(!mSurfaces->empty()); - LWO::Surface& surf = mSurfaces->back(); + LWO::Surface &surf = mSurfaces->back(); LWO::Texture tex; // load the texture header - LoadLWO2TextureHeader(head->length,tex); + LoadLWO2TextureHeader(head->length, tex); size -= head->length + 6; // now get the exact type of the texture - switch (head->type) - { - case AI_LWO_PROC: - LoadLWO2Procedural(size,tex); - break; - case AI_LWO_GRAD: - LoadLWO2Gradient(size,tex); - break; - case AI_LWO_IMAP: - LoadLWO2ImageMap(size,tex); + switch (head->type) { + case AI_LWO_PROC: + LoadLWO2Procedural(size, tex); + break; + case AI_LWO_GRAD: + LoadLWO2Gradient(size, tex); + break; + case AI_LWO_IMAP: + LoadLWO2ImageMap(size, tex); } // get the destination channel - TextureList* listRef = NULL; - switch (tex.type) - { - case AI_LWO_COLR: - listRef = &surf.mColorTextures;break; - case AI_LWO_DIFF: - listRef = &surf.mDiffuseTextures;break; - case AI_LWO_SPEC: - listRef = &surf.mSpecularTextures;break; - case AI_LWO_GLOS: - listRef = &surf.mGlossinessTextures;break; - case AI_LWO_BUMP: - listRef = &surf.mBumpTextures;break; - case AI_LWO_TRAN: - listRef = &surf.mOpacityTextures;break; - case AI_LWO_REFL: - listRef = &surf.mReflectionTextures;break; - default: - ASSIMP_LOG_WARN("LWO2: Encountered unknown texture type"); - return; + TextureList *listRef = NULL; + switch (tex.type) { + case AI_LWO_COLR: + listRef = &surf.mColorTextures; + break; + case AI_LWO_DIFF: + listRef = &surf.mDiffuseTextures; + break; + case AI_LWO_SPEC: + listRef = &surf.mSpecularTextures; + break; + case AI_LWO_GLOS: + listRef = &surf.mGlossinessTextures; + break; + case AI_LWO_BUMP: + listRef = &surf.mBumpTextures; + break; + case AI_LWO_TRAN: + listRef = &surf.mOpacityTextures; + break; + case AI_LWO_REFL: + listRef = &surf.mReflectionTextures; + break; + default: + ASSIMP_LOG_WARN("LWO2: Encountered unknown texture type"); + return; } // now attach the texture to the parent surface - sort by ordinal string - for (TextureList::iterator it = listRef->begin();it != listRef->end(); ++it) { - if (::strcmp(tex.ordinal.c_str(),(*it).ordinal.c_str()) < 0) { - listRef->insert(it,tex); + for (TextureList::iterator it = listRef->begin(); it != listRef->end(); ++it) { + if (::strcmp(tex.ordinal.c_str(), (*it).ordinal.c_str()) < 0) { + listRef->insert(it, tex); return; } } @@ -676,50 +642,46 @@ void LWOImporter::LoadLWO2TextureBlock(LE_NCONST IFF::SubChunkHeader* head, unsi } // ------------------------------------------------------------------------------------------------ -void LWOImporter::LoadLWO2ShaderBlock(LE_NCONST IFF::SubChunkHeader* /*head*/, unsigned int size ) -{ - LE_NCONST uint8_t* const end = mFileBuffer + size; +void LWOImporter::LoadLWO2ShaderBlock(LE_NCONST IFF::SubChunkHeader * /*head*/, unsigned int size) { + LE_NCONST uint8_t *const end = mFileBuffer + size; ai_assert(!mSurfaces->empty()); - LWO::Surface& surf = mSurfaces->back(); + LWO::Surface &surf = mSurfaces->back(); LWO::Shader shader; // get the ordinal string - GetS0( shader.ordinal, size); + GetS0(shader.ordinal, size); // we could crash later if this is an empty string ... - if (!shader.ordinal.length()) - { + if (!shader.ordinal.length()) { ASSIMP_LOG_ERROR("LWO2: Ill-formed SURF.BLOK ordinal string"); shader.ordinal = "\x00"; } // read the header - while (true) - { - if (mFileBuffer + 6 >= end)break; + while (true) { + if (mFileBuffer + 6 >= end) break; const IFF::SubChunkHeader head = IFF::LoadSubChunk(mFileBuffer); if (mFileBuffer + head.length > end) throw DeadlyImportError("LWO2: Invalid shader header chunk length"); - uint8_t* const next = mFileBuffer+head.length; - switch (head.type) - { - case AI_LWO_ENAB: - shader.enabled = GetU2() ? true : false; - break; + uint8_t *const next = mFileBuffer + head.length; + switch (head.type) { + case AI_LWO_ENAB: + shader.enabled = GetU2() ? true : false; + break; - case AI_LWO_FUNC: - GetS0( shader.functionName, head.length ); + case AI_LWO_FUNC: + GetS0(shader.functionName, head.length); } mFileBuffer = next; } // now attach the shader to the parent surface - sort by ordinal string - for (ShaderList::iterator it = surf.mShaders.begin();it != surf.mShaders.end(); ++it) { - if (::strcmp(shader.ordinal.c_str(),(*it).ordinal.c_str()) < 0) { - surf.mShaders.insert(it,shader); + for (ShaderList::iterator it = surf.mShaders.begin(); it != surf.mShaders.end(); ++it) { + if (::strcmp(shader.ordinal.c_str(), (*it).ordinal.c_str()) < 0) { + surf.mShaders.insert(it, shader); return; } } @@ -727,33 +689,33 @@ void LWOImporter::LoadLWO2ShaderBlock(LE_NCONST IFF::SubChunkHeader* /*head*/, u } // ------------------------------------------------------------------------------------------------ -void LWOImporter::LoadLWO2Surface(unsigned int size) -{ - LE_NCONST uint8_t* const end = mFileBuffer + size; +void LWOImporter::LoadLWO2Surface(unsigned int size) { + LE_NCONST uint8_t *const end = mFileBuffer + size; - mSurfaces->push_back( LWO::Surface () ); - LWO::Surface& surf = mSurfaces->back(); + mSurfaces->push_back(LWO::Surface()); + LWO::Surface &surf = mSurfaces->back(); - GetS0(surf.mName,size); + GetS0(surf.mName, size); // check whether this surface was derived from any other surface std::string derived; - GetS0(derived,(unsigned int)(end - mFileBuffer)); - if (derived.length()) { + GetS0(derived, (unsigned int)(end - mFileBuffer)); + if (derived.length()) { // yes, find this surface - for (SurfaceList::iterator it = mSurfaces->begin(), end = mSurfaces->end()-1; it != end; ++it) { + for (SurfaceList::iterator it = mSurfaces->begin(), itEnd = mSurfaces->end() - 1; it != itEnd; ++it) { if ((*it).mName == derived) { // we have it ... surf = *it; - derived.clear();break; + derived.clear(); + break; } } - if (derived.size()) + if (derived.size()) { ASSIMP_LOG_WARN("LWO2: Unable to find source surface: " + derived); + } } - while (true) - { + while (true) { if (mFileBuffer + 6 >= end) break; const IFF::SubChunkHeader head = IFF::LoadSubChunk(mFileBuffer); @@ -761,131 +723,115 @@ void LWOImporter::LoadLWO2Surface(unsigned int size) if (mFileBuffer + head.length > end) throw DeadlyImportError("LWO2: Invalid surface chunk length"); - uint8_t* const next = mFileBuffer+head.length; - switch (head.type) - { - // diffuse color - case AI_LWO_COLR: - { - AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,COLR,12); + uint8_t *const next = mFileBuffer + head.length; + switch (head.type) { + // diffuse color + case AI_LWO_COLR: { + AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, COLR, 12); surf.mColor.r = GetF4(); surf.mColor.g = GetF4(); surf.mColor.b = GetF4(); break; } - // diffuse strength ... hopefully - case AI_LWO_DIFF: - { - AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,DIFF,4); + // diffuse strength ... hopefully + case AI_LWO_DIFF: { + AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, DIFF, 4); surf.mDiffuseValue = GetF4(); break; } - // specular strength ... hopefully - case AI_LWO_SPEC: - { - AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,SPEC,4); + // specular strength ... hopefully + case AI_LWO_SPEC: { + AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, SPEC, 4); surf.mSpecularValue = GetF4(); break; } - // transparency - case AI_LWO_TRAN: - { + // transparency + case AI_LWO_TRAN: { // transparency explicitly disabled? if (surf.mTransparency == 10e10f) break; - AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,TRAN,4); + AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, TRAN, 4); surf.mTransparency = GetF4(); break; } - // additive transparency - case AI_LWO_ADTR: - { - AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,ADTR,4); + // additive transparency + case AI_LWO_ADTR: { + AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, ADTR, 4); surf.mAdditiveTransparency = GetF4(); break; } - // wireframe mode - case AI_LWO_LINE: - { - AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,LINE,2); + // wireframe mode + case AI_LWO_LINE: { + AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, LINE, 2); if (GetU2() & 0x1) surf.mWireframe = true; break; } - // glossiness - case AI_LWO_GLOS: - { - AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,GLOS,4); + // glossiness + case AI_LWO_GLOS: { + AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, GLOS, 4); surf.mGlossiness = GetF4(); break; } - // bump intensity - case AI_LWO_BUMP: - { - AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,BUMP,4); + // bump intensity + case AI_LWO_BUMP: { + AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, BUMP, 4); surf.mBumpIntensity = GetF4(); break; } - // color highlights - case AI_LWO_CLRH: - { - AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,CLRH,4); + // color highlights + case AI_LWO_CLRH: { + AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, CLRH, 4); surf.mColorHighlights = GetF4(); break; } - // index of refraction - case AI_LWO_RIND: - { - AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,RIND,4); + // index of refraction + case AI_LWO_RIND: { + AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, RIND, 4); surf.mIOR = GetF4(); break; } - // polygon sidedness - case AI_LWO_SIDE: - { - AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,SIDE,2); + // polygon sidedness + case AI_LWO_SIDE: { + AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, SIDE, 2); surf.bDoubleSided = (3 == GetU2()); break; } - // maximum smoothing angle - case AI_LWO_SMAN: - { - AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,SMAN,4); - surf.mMaximumSmoothAngle = std::fabs( GetF4() ); + // maximum smoothing angle + case AI_LWO_SMAN: { + AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, SMAN, 4); + surf.mMaximumSmoothAngle = std::fabs(GetF4()); break; } - // vertex color channel to be applied to the surface - case AI_LWO_VCOL: - { - AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,VCOL,12); - surf.mDiffuseValue *= GetF4(); // strength - ReadVSizedIntLWO2(mFileBuffer); // skip envelope - surf.mVCMapType = GetU4(); // type of the channel + // vertex color channel to be applied to the surface + case AI_LWO_VCOL: { + AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, VCOL, 12); + surf.mDiffuseValue *= GetF4(); // strength + ReadVSizedIntLWO2(mFileBuffer); // skip envelope + surf.mVCMapType = GetU4(); // type of the channel // name of the channel - GetS0(surf.mVCMap, (unsigned int) (next - mFileBuffer )); + GetS0(surf.mVCMap, (unsigned int)(next - mFileBuffer)); break; } - // surface bock entry - case AI_LWO_BLOK: - { - AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,BLOK,4); + // surface bock entry + case AI_LWO_BLOK: { + AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, BLOK, 4); IFF::SubChunkHeader head2 = IFF::LoadSubChunk(mFileBuffer); - switch (head2.type) - { - case AI_LWO_PROC: - case AI_LWO_GRAD: - case AI_LWO_IMAP: - LoadLWO2TextureBlock(&head2, head.length); - break; - case AI_LWO_SHDR: - LoadLWO2ShaderBlock(&head2, head.length); - break; + switch (head2.type) { + case AI_LWO_PROC: + case AI_LWO_GRAD: + case AI_LWO_IMAP: + LoadLWO2TextureBlock(&head2, head.length); + break; + case AI_LWO_SHDR: + LoadLWO2ShaderBlock(&head2, head.length); + break; - default: - ASSIMP_LOG_WARN("LWO2: Found an unsupported surface BLOK"); + default: + ASSIMP_LOG_WARN("LWO2: Found an unsupported surface BLOK"); }; break; diff --git a/code/LWS/LWSLoader.cpp b/code/LWS/LWSLoader.cpp index 4a9cec4ec..952c3ccbc 100644 --- a/code/LWS/LWSLoader.cpp +++ b/code/LWS/LWSLoader.cpp @@ -45,22 +45,21 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * @brief Implementation of the LWS importer class */ - #ifndef ASSIMP_BUILD_NO_LWS_IMPORTER #include "LWS/LWSLoader.h" -#include "PostProcessing/ConvertToLHProcess.h" #include "Common/Importer.h" +#include "PostProcessing/ConvertToLHProcess.h" -#include -#include -#include #include +#include +#include #include -#include -#include -#include +#include #include +#include +#include +#include #include @@ -81,9 +80,8 @@ static const aiImporterDesc desc = { // ------------------------------------------------------------------------------------------------ // Recursive parsing of LWS files -void LWS::Element::Parse (const char*& buffer) -{ - for (;SkipSpacesAndLineEnd(&buffer);SkipLine(&buffer)) { +void LWS::Element::Parse(const char *&buffer) { + for (; SkipSpacesAndLineEnd(&buffer); SkipLine(&buffer)) { // begin of a new element with children bool sub = false; @@ -91,27 +89,26 @@ void LWS::Element::Parse (const char*& buffer) ++buffer; SkipSpaces(&buffer); sub = true; - } - else if (*buffer == '}') + } else if (*buffer == '}') return; children.push_back(Element()); // copy data line - read token per token - const char* cur = buffer; - while (!IsSpaceOrNewLine(*buffer)) ++buffer; - children.back().tokens[0] = std::string(cur,(size_t) (buffer-cur)); + const char *cur = buffer; + while (!IsSpaceOrNewLine(*buffer)) + ++buffer; + children.back().tokens[0] = std::string(cur, (size_t)(buffer - cur)); SkipSpaces(&buffer); - if (children.back().tokens[0] == "Plugin") - { + if (children.back().tokens[0] == "Plugin") { ASSIMP_LOG_DEBUG("LWS: Skipping over plugin-specific data"); // strange stuff inside Plugin/Endplugin blocks. Needn't // follow LWS syntax, so we skip over it - for (;SkipSpacesAndLineEnd(&buffer);SkipLine(&buffer)) { - if (!::strncmp(buffer,"EndPlugin",9)) { + for (; SkipSpacesAndLineEnd(&buffer); SkipLine(&buffer)) { + if (!::strncmp(buffer, "EndPlugin", 9)) { //SkipLine(&buffer); break; } @@ -120,8 +117,9 @@ void LWS::Element::Parse (const char*& buffer) } cur = buffer; - while (!IsLineEnd(*buffer)) ++buffer; - children.back().tokens[1] = std::string(cur,(size_t) (buffer-cur)); + while (!IsLineEnd(*buffer)) + ++buffer; + children.back().tokens[1] = std::string(cur, (size_t)(buffer - cur)); // parse more elements recursively if (sub) @@ -131,28 +129,25 @@ void LWS::Element::Parse (const char*& buffer) // ------------------------------------------------------------------------------------------------ // Constructor to be privately used by Importer -LWSImporter::LWSImporter() - : configSpeedFlag(), - io(), - first(), - last(), - fps(), - noSkeletonMesh() -{ +LWSImporter::LWSImporter() : + configSpeedFlag(), + io(), + first(), + last(), + fps(), + noSkeletonMesh() { // nothing to do here } // ------------------------------------------------------------------------------------------------ // Destructor, private as well -LWSImporter::~LWSImporter() -{ +LWSImporter::~LWSImporter() { // nothing to do here } // ------------------------------------------------------------------------------------------------ // Returns whether the class can handle the format of the given file. -bool LWSImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler,bool checkSig) const -{ +bool LWSImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const { const std::string extension = GetExtension(pFile); if (extension == "lws" || extension == "mot") return true; @@ -162,69 +157,67 @@ bool LWSImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler,bool c uint32_t tokens[2]; tokens[0] = AI_MAKE_MAGIC("LWSC"); tokens[1] = AI_MAKE_MAGIC("LWMO"); - return CheckMagicToken(pIOHandler,pFile,tokens,2); + return CheckMagicToken(pIOHandler, pFile, tokens, 2); } return false; } // ------------------------------------------------------------------------------------------------ // Get list of file extensions -const aiImporterDesc* LWSImporter::GetInfo () const -{ +const aiImporterDesc *LWSImporter::GetInfo() const { return &desc; } // ------------------------------------------------------------------------------------------------ // Setup configuration properties -void LWSImporter::SetupProperties(const Importer* pImp) -{ +void LWSImporter::SetupProperties(const Importer *pImp) { // AI_CONFIG_FAVOUR_SPEED - configSpeedFlag = (0 != pImp->GetPropertyInteger(AI_CONFIG_FAVOUR_SPEED,0)); + configSpeedFlag = (0 != pImp->GetPropertyInteger(AI_CONFIG_FAVOUR_SPEED, 0)); // AI_CONFIG_IMPORT_LWS_ANIM_START first = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_LWS_ANIM_START, - 150392 /* magic hack */); + 150392 /* magic hack */); // AI_CONFIG_IMPORT_LWS_ANIM_END last = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_LWS_ANIM_END, - 150392 /* magic hack */); + 150392 /* magic hack */); if (last < first) { - std::swap(last,first); + std::swap(last, first); } - noSkeletonMesh = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_NO_SKELETON_MESHES,0) != 0; + noSkeletonMesh = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_NO_SKELETON_MESHES, 0) != 0; } // ------------------------------------------------------------------------------------------------ // Read an envelope description -void LWSImporter::ReadEnvelope(const LWS::Element& dad, LWO::Envelope& fill ) -{ +void LWSImporter::ReadEnvelope(const LWS::Element &dad, LWO::Envelope &fill) { if (dad.children.empty()) { ASSIMP_LOG_ERROR("LWS: Envelope descriptions must not be empty"); return; } // reserve enough storage - std::list< LWS::Element >::const_iterator it = dad.children.begin();; + std::list::const_iterator it = dad.children.begin(); + ; fill.keys.reserve(strtoul10(it->tokens[1].c_str())); for (++it; it != dad.children.end(); ++it) { - const char* c = (*it).tokens[1].c_str(); + const char *c = (*it).tokens[1].c_str(); if ((*it).tokens[0] == "Key") { fill.keys.push_back(LWO::Key()); - LWO::Key& key = fill.keys.back(); + LWO::Key &key = fill.keys.back(); float f; SkipSpaces(&c); - c = fast_atoreal_move(c,key.value); + c = fast_atoreal_move(c, key.value); SkipSpaces(&c); - c = fast_atoreal_move(c,f); + c = fast_atoreal_move(c, f); key.time = f; - unsigned int span = strtoul10(c,&c), num = 0; + unsigned int span = strtoul10(c, &c), num = 0; switch (span) { case 0: @@ -251,16 +244,15 @@ void LWSImporter::ReadEnvelope(const LWS::Element& dad, LWO::Envelope& fill ) default: ASSIMP_LOG_ERROR("LWS: Unknown span type"); } - for (unsigned int i = 0; i < num;++i) { + for (unsigned int i = 0; i < num; ++i) { SkipSpaces(&c); - c = fast_atoreal_move(c,key.params[i]); + c = fast_atoreal_move(c, key.params[i]); } - } - else if ((*it).tokens[0] == "Behaviors") { + } else if ((*it).tokens[0] == "Behaviors") { SkipSpaces(&c); - fill.pre = (LWO::PrePostBehaviour) strtoul10(c,&c); + fill.pre = (LWO::PrePostBehaviour)strtoul10(c, &c); SkipSpaces(&c); - fill.post = (LWO::PrePostBehaviour) strtoul10(c,&c); + fill.post = (LWO::PrePostBehaviour)strtoul10(c, &c); } } } @@ -268,36 +260,35 @@ void LWSImporter::ReadEnvelope(const LWS::Element& dad, LWO::Envelope& fill ) // ------------------------------------------------------------------------------------------------ // Read animation channels in the old LightWave animation format void LWSImporter::ReadEnvelope_Old( - std::list< LWS::Element >::const_iterator& it, - const std::list< LWS::Element >::const_iterator& end, - LWS::NodeDesc& nodes, - unsigned int /*version*/) -{ - unsigned int num,sub_num; - if (++it == end)goto unexpected_end; + std::list::const_iterator &it, + const std::list::const_iterator &end, + LWS::NodeDesc &nodes, + unsigned int /*version*/) { + unsigned int num, sub_num; + if (++it == end) goto unexpected_end; num = strtoul10((*it).tokens[0].c_str()); for (unsigned int i = 0; i < num; ++i) { nodes.channels.push_back(LWO::Envelope()); - LWO::Envelope& envl = nodes.channels.back(); + LWO::Envelope &envl = nodes.channels.back(); envl.index = i; - envl.type = (LWO::EnvelopeType)(i+1); + envl.type = (LWO::EnvelopeType)(i + 1); - if (++it == end)goto unexpected_end; + if (++it == end) goto unexpected_end; sub_num = strtoul10((*it).tokens[0].c_str()); - for (unsigned int n = 0; n < sub_num;++n) { + for (unsigned int n = 0; n < sub_num; ++n) { - if (++it == end)goto unexpected_end; + if (++it == end) goto unexpected_end; // parse value and time, skip the rest for the moment. LWO::Key key; - const char* c = fast_atoreal_move((*it).tokens[0].c_str(),key.value); + const char *c = fast_atoreal_move((*it).tokens[0].c_str(), key.value); SkipSpaces(&c); float f; - fast_atoreal_move((*it).tokens[0].c_str(),f); + fast_atoreal_move((*it).tokens[0].c_str(), f); key.time = f; envl.keys.push_back(key); @@ -311,51 +302,49 @@ unexpected_end: // ------------------------------------------------------------------------------------------------ // Setup a nice name for a node -void LWSImporter::SetupNodeName(aiNode* nd, LWS::NodeDesc& src) -{ +void LWSImporter::SetupNodeName(aiNode *nd, LWS::NodeDesc &src) { const unsigned int combined = src.number | ((unsigned int)src.type) << 28u; // the name depends on the type. We break LWS's strange naming convention // and return human-readable, but still machine-parsable and unique, strings. - if (src.type == LWS::NodeDesc::OBJECT) { + if (src.type == LWS::NodeDesc::OBJECT) { if (src.path.length()) { std::string::size_type s = src.path.find_last_of("\\/"); if (s == std::string::npos) s = 0; - else ++s; + else + ++s; std::string::size_type t = src.path.substr(s).find_last_of("."); - nd->mName.length = ::ai_snprintf(nd->mName.data, MAXLEN, "%s_(%08X)",src.path.substr(s).substr(0,t).c_str(),combined); + nd->mName.length = ::ai_snprintf(nd->mName.data, MAXLEN, "%s_(%08X)", src.path.substr(s).substr(0, t).c_str(), combined); return; } } - nd->mName.length = ::ai_snprintf(nd->mName.data, MAXLEN, "%s_(%08X)",src.name,combined); + nd->mName.length = ::ai_snprintf(nd->mName.data, MAXLEN, "%s_(%08X)", src.name, combined); } // ------------------------------------------------------------------------------------------------ // Recursively build the scenegraph -void LWSImporter::BuildGraph(aiNode* nd, LWS::NodeDesc& src, std::vector& attach, - BatchLoader& batch, - aiCamera**& camOut, - aiLight**& lightOut, - std::vector& animOut) -{ +void LWSImporter::BuildGraph(aiNode *nd, LWS::NodeDesc &src, std::vector &attach, + BatchLoader &batch, + aiCamera **&camOut, + aiLight **&lightOut, + std::vector &animOut) { // Setup a very cryptic name for the node, we want the user to be happy - SetupNodeName(nd,src); - aiNode* ndAnim = nd; + SetupNodeName(nd, src); + aiNode *ndAnim = nd; // If the node is an object if (src.type == LWS::NodeDesc::OBJECT) { // If the object is from an external file, get it - aiScene* obj = NULL; - if (src.path.length() ) { + aiScene *obj = NULL; + if (src.path.length()) { obj = batch.GetImport(src.id); if (!obj) { ASSIMP_LOG_ERROR("LWS: Failed to read external file " + src.path); - } - else { + } else { if (obj->mRootNode->mNumChildren == 1) { //If the pivot is not set for this layer, get it from the external object @@ -366,7 +355,7 @@ void LWSImporter::BuildGraph(aiNode* nd, LWS::NodeDesc& src, std::vectormRootNode->mChildren[0]; + aiNode *newRootNode = obj->mRootNode->mChildren[0]; obj->mRootNode->mChildren[0] = NULL; delete obj->mRootNode; @@ -384,7 +373,7 @@ void LWSImporter::BuildGraph(aiNode* nd, LWS::NodeDesc& src, std::vectormNumChildren = 1; - nd->mChildren = new aiNode*[1]; + nd->mChildren = new aiNode *[1]; nd->mChildren[0] = new aiNode(); nd->mChildren[0]->mParent = nd; nd->mChildren[0]->mTransformation.a4 = -src.pivotPos.x; @@ -397,16 +386,16 @@ void LWSImporter::BuildGraph(aiNode* nd, LWS::NodeDesc& src, std::vectormColorDiffuse = lit->mColorSpecular = src.lightColor*src.lightIntensity; + lit->mColorDiffuse = lit->mColorSpecular = src.lightColor * src.lightIntensity; // name to attach light to node -> unique due to LWs indexing system lit->mName = nd->mName; @@ -415,14 +404,13 @@ void LWSImporter::BuildGraph(aiNode* nd, LWS::NodeDesc& src, std::vectormType = aiLightSource_SPOT; - lit->mAngleInnerCone = (float)AI_DEG_TO_RAD( src.lightConeAngle ); - lit->mAngleOuterCone = lit->mAngleInnerCone+(float)AI_DEG_TO_RAD( src.lightEdgeAngle ); + lit->mAngleInnerCone = (float)AI_DEG_TO_RAD(src.lightConeAngle); + lit->mAngleOuterCone = lit->mAngleInnerCone + (float)AI_DEG_TO_RAD(src.lightEdgeAngle); - } - else if (src.lightType == 1) { /* directional light source */ + } else if (src.lightType == 1) { /* directional light source */ lit->mType = aiLightSource_DIRECTIONAL; - } - else lit->mType = aiLightSource_POINT; + } else + lit->mType = aiLightSource_POINT; // fixme: no proper handling of light falloffs yet if (src.lightFalloffType == 1) @@ -435,22 +423,22 @@ void LWSImporter::BuildGraph(aiNode* nd, LWS::NodeDesc& src, std::vector unique due to LWs indexing system cam->mName = nd->mName; } // Get the node transformation from the LWO key - LWO::AnimResolver resolver(src.channels,fps); + LWO::AnimResolver resolver(src.channels, fps); resolver.ExtractBindPose(ndAnim->mTransformation); // .. and construct animation channels - aiNodeAnim* anim = NULL; + aiNodeAnim *anim = NULL; if (first != last) { - resolver.SetAnimationRange(first,last); - resolver.ExtractAnimChannel(&anim,AI_LWO_ANIM_FLAG_SAMPLE_ANIMS|AI_LWO_ANIM_FLAG_START_AT_ZERO); + resolver.SetAnimationRange(first, last); + resolver.ExtractAnimChannel(&anim, AI_LWO_ANIM_FLAG_SAMPLE_ANIMS | AI_LWO_ANIM_FLAG_START_AT_ZERO); if (anim) { anim->mNodeName = ndAnim->mName; animOut.push_back(anim); @@ -459,27 +447,25 @@ void LWSImporter::BuildGraph(aiNode* nd, LWS::NodeDesc& src, std::vectormChildren = new aiNode*[src.children.size()]; - for (std::list::iterator it = src.children.begin(); it != src.children.end(); ++it) { - aiNode* ndd = nd->mChildren[nd->mNumChildren++] = new aiNode(); + nd->mChildren = new aiNode *[src.children.size()]; + for (std::list::iterator it = src.children.begin(); it != src.children.end(); ++it) { + aiNode *ndd = nd->mChildren[nd->mNumChildren++] = new aiNode(); ndd->mParent = nd; - BuildGraph(ndd,**it,attach,batch,camOut,lightOut,animOut); + BuildGraph(ndd, **it, attach, batch, camOut, lightOut, animOut); } } } // ------------------------------------------------------------------------------------------------ // Determine the exact location of a LWO file -std::string LWSImporter::FindLWOFile(const std::string& in) -{ +std::string LWSImporter::FindLWOFile(const std::string &in) { // insert missing directory separator if necessary std::string tmp; - if (in.length() > 3 && in[1] == ':'&& in[2] != '\\' && in[2] != '/') - { + if (in.length() > 3 && in[1] == ':' && in[2] != '\\' && in[2] != '/') { tmp = in[0] + (std::string(":\\") + in.substr(2)); - } - else tmp = in; + } else + tmp = in; if (io->Exists(tmp)) { return in; @@ -503,35 +489,34 @@ std::string LWSImporter::FindLWOFile(const std::string& in) return test; } - // return original path, maybe the IOsystem knows better return tmp; } // ------------------------------------------------------------------------------------------------ // Read file into given scene data structure -void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene, - IOSystem* pIOHandler) -{ +void LWSImporter::InternReadFile(const std::string &pFile, aiScene *pScene, + IOSystem *pIOHandler) { io = pIOHandler; - std::unique_ptr file( pIOHandler->Open( pFile, "rb")); + std::unique_ptr file(pIOHandler->Open(pFile, "rb")); // Check whether we can read from the file - if( file.get() == NULL) { - throw DeadlyImportError( "Failed to open LWS file " + pFile + "."); + if (file.get() == NULL) { + throw DeadlyImportError("Failed to open LWS file " + pFile + "."); } // Allocate storage and copy the contents of the file to a memory buffer - std::vector< char > mBuffer; - TextFileToBuffer(file.get(),mBuffer); + std::vector mBuffer; + TextFileToBuffer(file.get(), mBuffer); // Parse the file structure - LWS::Element root; const char* dummy = &mBuffer[0]; + LWS::Element root; + const char *dummy = &mBuffer[0]; root.Parse(dummy); // Construct a Batchimporter to read more files recursively BatchLoader batch(pIOHandler); -// batch.SetBasePath(pFile); + // batch.SetBasePath(pFile); // Construct an array to receive the flat output graph std::list nodes; @@ -541,7 +526,7 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene, // check magic identifier, 'LWSC' bool motion_file = false; - std::list< LWS::Element >::const_iterator it = root.children.begin(); + std::list::const_iterator it = root.children.begin(); if ((*it).tokens[0] == "LWMO") motion_file = true; @@ -554,54 +539,54 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene, unsigned int version = strtoul10((*it).tokens[0].c_str()); ASSIMP_LOG_INFO("LWS file format version is " + (*it).tokens[0]); first = 0.; - last = 60.; - fps = 25.; /* seems to be a good default frame rate */ + last = 60.; + fps = 25.; /* seems to be a good default frame rate */ // Now read all elements in a very straghtforward manner for (; it != root.children.end(); ++it) { - const char* c = (*it).tokens[1].c_str(); + const char *c = (*it).tokens[1].c_str(); // 'FirstFrame': begin of animation slice if ((*it).tokens[0] == "FirstFrame") { - if (150392. != first /* see SetupProperties() */) - first = strtoul10(c,&c)-1.; /* we're zero-based */ + if (150392. != first /* see SetupProperties() */) + first = strtoul10(c, &c) - 1.; /* we're zero-based */ } // 'LastFrame': end of animation slice else if ((*it).tokens[0] == "LastFrame") { - if (150392. != last /* see SetupProperties() */) - last = strtoul10(c,&c)-1.; /* we're zero-based */ + if (150392. != last /* see SetupProperties() */) + last = strtoul10(c, &c) - 1.; /* we're zero-based */ } // 'FramesPerSecond': frames per second else if ((*it).tokens[0] == "FramesPerSecond") { - fps = strtoul10(c,&c); + fps = strtoul10(c, &c); } // 'LoadObjectLayer': load a layer of a specific LWO file else if ((*it).tokens[0] == "LoadObjectLayer") { // get layer index - const int layer = strtoul10(c,&c); + const int layer = strtoul10(c, &c); // setup the layer to be loaded BatchLoader::PropertyMap props; - SetGenericProperty(props.ints,AI_CONFIG_IMPORT_LWO_ONE_LAYER_ONLY,layer); + SetGenericProperty(props.ints, AI_CONFIG_IMPORT_LWO_ONE_LAYER_ONLY, layer); // add node to list LWS::NodeDesc d; d.type = LWS::NodeDesc::OBJECT; if (version >= 4) { // handle LWSC 4 explicit ID SkipSpaces(&c); - d.number = strtoul16(c,&c) & AI_LWS_MASK; - } - else d.number = cur_object++; + d.number = strtoul16(c, &c) & AI_LWS_MASK; + } else + d.number = cur_object++; // and add the file to the import list SkipSpaces(&c); - std::string path = FindLWOFile( c ); + std::string path = FindLWOFile(c); d.path = path; - d.id = batch.AddLoadRequest(path,0,&props); + d.id = batch.AddLoadRequest(path, 0, &props); nodes.push_back(d); num_object++; @@ -614,12 +599,12 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene, d.type = LWS::NodeDesc::OBJECT; if (version >= 4) { // handle LWSC 4 explicit ID - d.number = strtoul16(c,&c) & AI_LWS_MASK; + d.number = strtoul16(c, &c) & AI_LWS_MASK; SkipSpaces(&c); - } - else d.number = cur_object++; - std::string path = FindLWOFile( c ); - d.id = batch.AddLoadRequest(path,0,NULL); + } else + d.number = cur_object++; + std::string path = FindLWOFile(c); + d.id = batch.AddLoadRequest(path, 0, NULL); d.path = path; nodes.push_back(d); @@ -632,10 +617,10 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene, LWS::NodeDesc d; d.type = LWS::NodeDesc::OBJECT; if (version >= 4) { // handle LWSC 4 explicit ID - d.number = strtoul16(c,&c) & AI_LWS_MASK; + d.number = strtoul16(c, &c) & AI_LWS_MASK; SkipSpaces(&c); - } - else d.number = cur_object++; + } else + d.number = cur_object++; d.name = c; nodes.push_back(d); @@ -662,13 +647,13 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene, // important: index of channel nodes.back().channels.push_back(LWO::Envelope()); - LWO::Envelope& env = nodes.back().channels.back(); + LWO::Envelope &env = nodes.back().channels.back(); env.index = strtoul10(c); // currently we can just interpret the standard channels 0...9 // (hack) assume that index-i yields the binary channel type from LWO - env.type = (LWO::EnvelopeType)(env.index+1); + env.type = (LWO::EnvelopeType)(env.index + 1); } // 'Envelope': a single animation channel @@ -676,18 +661,18 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene, if (nodes.empty() || nodes.back().channels.empty()) ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'Envelope\'"); else { - ReadEnvelope((*it),nodes.back().channels.back()); + ReadEnvelope((*it), nodes.back().channels.back()); } } // 'ObjectMotion': animation information for older lightwave formats - else if (version < 3 && ((*it).tokens[0] == "ObjectMotion" || - (*it).tokens[0] == "CameraMotion" || - (*it).tokens[0] == "LightMotion")) { + else if (version < 3 && ((*it).tokens[0] == "ObjectMotion" || + (*it).tokens[0] == "CameraMotion" || + (*it).tokens[0] == "LightMotion")) { if (nodes.empty()) ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'Motion\'"); else { - ReadEnvelope_Old(it,root.children.end(),nodes.back(),version); + ReadEnvelope_Old(it, root.children.end(), nodes.back(), version); } } // 'Pre/PostBehavior': pre/post animation behaviour for LWSC 2 @@ -695,11 +680,13 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene, if (nodes.empty()) ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'Pre/PostBehavior'"); else { - for (std::list::iterator it = nodes.back().channels.begin(); it != nodes.back().channels.end(); ++it) { + for (std::list::iterator envelopeIt = nodes.back().channels.begin(); envelopeIt != nodes.back().channels.end(); ++envelopeIt) { // two ints per envelope - LWO::Envelope& env = *it; - env.pre = (LWO::PrePostBehaviour) strtoul10(c,&c); SkipSpaces(&c); - env.post = (LWO::PrePostBehaviour) strtoul10(c,&c); SkipSpaces(&c); + LWO::Envelope &env = *envelopeIt; + env.pre = (LWO::PrePostBehaviour)strtoul10(c, &c); + SkipSpaces(&c); + env.post = (LWO::PrePostBehaviour)strtoul10(c, &c); + SkipSpaces(&c); } } } @@ -708,7 +695,8 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene, if (nodes.empty()) ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'ParentItem\'"); - else nodes.back().parent = strtoul16(c,&c); + else + nodes.back().parent = strtoul16(c, &c); } // 'ParentObject': deprecated one for older formats else if (version < 3 && (*it).tokens[0] == "ParentObject") { @@ -716,7 +704,7 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene, ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'ParentObject\'"); else { - nodes.back().parent = strtoul10(c,&c) | (1u << 28u); + nodes.back().parent = strtoul10(c, &c) | (1u << 28u); } } // 'AddCamera': add a camera to the scenegraph @@ -727,9 +715,9 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene, d.type = LWS::NodeDesc::CAMERA; if (version >= 4) { // handle LWSC 4 explicit ID - d.number = strtoul16(c,&c) & AI_LWS_MASK; - } - else d.number = cur_camera++; + d.number = strtoul16(c, &c) & AI_LWS_MASK; + } else + d.number = cur_camera++; nodes.push_back(d); num_camera++; @@ -739,7 +727,8 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene, if (nodes.empty() || nodes.back().type != LWS::NodeDesc::CAMERA) ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'CameraName\'"); - else nodes.back().name = c; + else + nodes.back().name = c; } // 'AddLight': add a light to the scenegraph else if ((*it).tokens[0] == "AddLight") { @@ -749,9 +738,9 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene, d.type = LWS::NodeDesc::LIGHT; if (version >= 4) { // handle LWSC 4 explicit ID - d.number = strtoul16(c,&c) & AI_LWS_MASK; - } - else d.number = cur_light++; + d.number = strtoul16(c, &c) & AI_LWS_MASK; + } else + d.number = cur_light++; nodes.push_back(d); num_light++; @@ -761,14 +750,16 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene, if (nodes.empty() || nodes.back().type != LWS::NodeDesc::LIGHT) ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'LightName\'"); - else nodes.back().name = c; + else + nodes.back().name = c; } // 'LightIntensity': set intensity of currently active light - else if ((*it).tokens[0] == "LightIntensity" || (*it).tokens[0] == "LgtIntensity" ) { + else if ((*it).tokens[0] == "LightIntensity" || (*it).tokens[0] == "LgtIntensity") { if (nodes.empty() || nodes.back().type != LWS::NodeDesc::LIGHT) ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'LightIntensity\'"); - else fast_atoreal_move(c, nodes.back().lightIntensity ); + else + fast_atoreal_move(c, nodes.back().lightIntensity); } // 'LightType': set type of currently active light @@ -776,7 +767,8 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene, if (nodes.empty() || nodes.back().type != LWS::NodeDesc::LIGHT) ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'LightType\'"); - else nodes.back().lightType = strtoul10(c); + else + nodes.back().lightType = strtoul10(c); } // 'LightFalloffType': set falloff type of currently active light @@ -784,7 +776,8 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene, if (nodes.empty() || nodes.back().type != LWS::NodeDesc::LIGHT) ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'LightFalloffType\'"); - else nodes.back().lightFalloffType = strtoul10(c); + else + nodes.back().lightFalloffType = strtoul10(c); } // 'LightConeAngle': set cone angle of currently active light @@ -792,7 +785,8 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene, if (nodes.empty() || nodes.back().type != LWS::NodeDesc::LIGHT) ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'LightConeAngle\'"); - else nodes.back().lightConeAngle = fast_atof(c); + else + nodes.back().lightConeAngle = fast_atof(c); } // 'LightEdgeAngle': set area where we're smoothing from min to max intensity @@ -800,7 +794,8 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene, if (nodes.empty() || nodes.back().type != LWS::NodeDesc::LIGHT) ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'LightEdgeAngle\'"); - else nodes.back().lightEdgeAngle = fast_atof(c); + else + nodes.back().lightEdgeAngle = fast_atof(c); } // 'LightColor': set color of currently active light @@ -809,11 +804,11 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene, ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'LightColor\'"); else { - c = fast_atoreal_move(c, (float&) nodes.back().lightColor.r ); + c = fast_atoreal_move(c, (float &)nodes.back().lightColor.r); SkipSpaces(&c); - c = fast_atoreal_move(c, (float&) nodes.back().lightColor.g ); + c = fast_atoreal_move(c, (float &)nodes.back().lightColor.g); SkipSpaces(&c); - c = fast_atoreal_move(c, (float&) nodes.back().lightColor.b ); + c = fast_atoreal_move(c, (float &)nodes.back().lightColor.b); } } @@ -822,11 +817,11 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene, if (nodes.empty()) ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'PivotPosition\'"); else { - c = fast_atoreal_move(c, (float&) nodes.back().pivotPos.x ); + c = fast_atoreal_move(c, (float &)nodes.back().pivotPos.x); SkipSpaces(&c); - c = fast_atoreal_move(c, (float&) nodes.back().pivotPos.y ); + c = fast_atoreal_move(c, (float &)nodes.back().pivotPos.y); SkipSpaces(&c); - c = fast_atoreal_move(c, (float&) nodes.back().pivotPos.z ); + c = fast_atoreal_move(c, (float &)nodes.back().pivotPos.z); // Mark pivotPos as set nodes.back().isPivotSet = true; } @@ -834,79 +829,80 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene, } // resolve parenting - for (std::list::iterator it = nodes.begin(); it != nodes.end(); ++it) { + for (std::list::iterator ndIt = nodes.begin(); ndIt != nodes.end(); ++ndIt) { // check whether there is another node which calls us a parent for (std::list::iterator dit = nodes.begin(); dit != nodes.end(); ++dit) { - if (dit != it && *it == (*dit).parent) { + if (dit != ndIt && *ndIt == (*dit).parent) { if ((*dit).parent_resolved) { // fixme: it's still possible to produce an overflow due to cross references .. ASSIMP_LOG_ERROR("LWS: Found cross reference in scene-graph"); continue; } - (*it).children.push_back(&*dit); - (*dit).parent_resolved = &*it; + ndIt->children.push_back(&*dit); + (*dit).parent_resolved = &*ndIt; } } } // find out how many nodes have no parent yet unsigned int no_parent = 0; - for (std::list::iterator it = nodes.begin(); it != nodes.end(); ++it) { - if (!(*it).parent_resolved) - ++ no_parent; + for (std::list::iterator ndIt = nodes.begin(); ndIt != nodes.end(); ++ndIt) { + if (!ndIt->parent_resolved) { + ++no_parent; + } } - if (!no_parent) + if (!no_parent) { throw DeadlyImportError("LWS: Unable to find scene root node"); - + } // Load all subsequent files batch.LoadAll(); // and build the final output graph by attaching the loaded external // files to ourselves. first build a master graph - aiScene* master = new aiScene(); - aiNode* nd = master->mRootNode = new aiNode(); + aiScene *master = new aiScene(); + aiNode *nd = master->mRootNode = new aiNode(); // allocate storage for cameras&lights if (num_camera) { - master->mCameras = new aiCamera*[master->mNumCameras = num_camera]; + master->mCameras = new aiCamera *[master->mNumCameras = num_camera]; } - aiCamera** cams = master->mCameras; + aiCamera **cams = master->mCameras; if (num_light) { - master->mLights = new aiLight*[master->mNumLights = num_light]; + master->mLights = new aiLight *[master->mNumLights = num_light]; } - aiLight** lights = master->mLights; + aiLight **lights = master->mLights; std::vector attach; - std::vector anims; + std::vector anims; nd->mName.Set(""); - nd->mChildren = new aiNode*[no_parent]; - for (std::list::iterator it = nodes.begin(); it != nodes.end(); ++it) { - if (!(*it).parent_resolved) { - aiNode* ro = nd->mChildren[ nd->mNumChildren++ ] = new aiNode(); + nd->mChildren = new aiNode *[no_parent]; + for (std::list::iterator ndIt = nodes.begin(); ndIt != nodes.end(); ++ndIt) { + if (!ndIt->parent_resolved) { + aiNode *ro = nd->mChildren[nd->mNumChildren++] = new aiNode(); ro->mParent = nd; // ... and build the scene graph. If we encounter object nodes, // add then to our attachment table. - BuildGraph(ro,*it, attach, batch, cams, lights, anims); + BuildGraph(ro, *ndIt, attach, batch, cams, lights, anims); } } // create a master animation channel for us if (anims.size()) { - master->mAnimations = new aiAnimation*[master->mNumAnimations = 1]; - aiAnimation* anim = master->mAnimations[0] = new aiAnimation(); + master->mAnimations = new aiAnimation *[master->mNumAnimations = 1]; + aiAnimation *anim = master->mAnimations[0] = new aiAnimation(); anim->mName.Set("LWSMasterAnim"); // LWS uses seconds as time units, but we convert to frames anim->mTicksPerSecond = fps; - anim->mDuration = last-(first-1); /* fixme ... zero or one-based?*/ + anim->mDuration = last - (first - 1); /* fixme ... zero or one-based?*/ - anim->mChannels = new aiNodeAnim*[anim->mNumChannels = static_cast(anims.size())]; - std::copy(anims.begin(),anims.end(),anim->mChannels); + anim->mChannels = new aiNodeAnim *[anim->mNumChannels = static_cast(anims.size())]; + std::copy(anims.begin(), anims.end(), anim->mChannels); } // convert the master scene to RH @@ -918,9 +914,10 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene, flipper.Execute(master); // OK ... finally build the output graph - SceneCombiner::MergeScenes(&pScene,master,attach, - AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES | (!configSpeedFlag ? ( - AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES_IF_NECESSARY | AI_INT_MERGE_SCENE_GEN_UNIQUE_MATNAMES) : 0)); + SceneCombiner::MergeScenes(&pScene, master, attach, + AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES | (!configSpeedFlag ? ( + AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES_IF_NECESSARY | AI_INT_MERGE_SCENE_GEN_UNIQUE_MATNAMES) : + 0)); // Check flags if (!pScene->mNumMeshes || !pScene->mNumMaterials) { @@ -931,7 +928,6 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene, SkeletonMeshBuilder builder(pScene); } } - } #endif // !! ASSIMP_BUILD_NO_LWS_IMPORTER diff --git a/code/M3D/M3DImporter.cpp b/code/M3D/M3DImporter.cpp index 9aee14f75..c69783c30 100644 --- a/code/M3D/M3DImporter.cpp +++ b/code/M3D/M3DImporter.cpp @@ -56,9 +56,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -#include "M3DWrapper.h" #include "M3DImporter.h" #include "M3DMaterials.h" +#include "M3DWrapper.h" // RESOURCES: // https://gitlab.com/bztsrc/model3d/blob/master/docs/m3d_format.md @@ -86,19 +86,19 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ static const aiImporterDesc desc = { - "Model 3D Importer", - "", - "", - "", - aiImporterFlags_SupportTextFlavour | aiImporterFlags_SupportBinaryFlavour, - 0, - 0, - 0, - 0, + "Model 3D Importer", + "", + "", + "", + aiImporterFlags_SupportTextFlavour | aiImporterFlags_SupportBinaryFlavour, + 0, + 0, + 0, + 0, #ifdef M3D_ASCII - "m3d a3d" + "m3d a3d" #else - "m3d" + "m3d" #endif }; @@ -109,273 +109,280 @@ using namespace std; // ------------------------------------------------------------------------------------------------ // Default constructor M3DImporter::M3DImporter() : - mScene(nullptr) { - // empty - } + mScene(nullptr) { + // empty +} // ------------------------------------------------------------------------------------------------ // Returns true, if file is a binary or ASCII Model 3D file. bool M3DImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const { - const std::string extension = GetExtension(pFile); + const std::string extension = GetExtension(pFile); - if (extension == "m3d" + if (extension == "m3d" #ifdef M3D_ASCII - || extension == "a3d" + || extension == "a3d" #endif - ) - return true; - else if (!extension.length() || checkSig) { - if (!pIOHandler) { - return true; - } - /* + ) + return true; + else if (!extension.length() || checkSig) { + if (!pIOHandler) { + return true; + } + /* * don't use CheckMagicToken because that checks with swapped bytes too, leading to false * positives. This magic is not uint32_t, but char[4], so memcmp is the best way const char* tokens[] = {"3DMO", "3dmo"}; return CheckMagicToken(pIOHandler,pFile,tokens,2,0,4); */ - std::unique_ptr pStream(pIOHandler->Open(pFile, "rb")); - unsigned char data[4]; - if (4 != pStream->Read(data, 1, 4)) { - return false; - } - return !memcmp(data, "3DMO", 4) /* bin */ + std::unique_ptr pStream(pIOHandler->Open(pFile, "rb")); + unsigned char data[4]; + if (4 != pStream->Read(data, 1, 4)) { + return false; + } + return !memcmp(data, "3DMO", 4) /* bin */ #ifdef M3D_ASCII - || !memcmp(data, "3dmo", 4) /* ASCII */ + || !memcmp(data, "3dmo", 4) /* ASCII */ #endif - ; - } - return false; + ; + } + return false; } // ------------------------------------------------------------------------------------------------ const aiImporterDesc *M3DImporter::GetInfo() const { - return &desc; + return &desc; } // ------------------------------------------------------------------------------------------------ // Model 3D import implementation void M3DImporter::InternReadFile(const std::string &file, aiScene *pScene, IOSystem *pIOHandler) { - // Read file into memory - std::unique_ptr pStream(pIOHandler->Open(file, "rb")); - if (!pStream.get()) { - throw DeadlyImportError("Failed to open file " + file + "."); - } + // Read file into memory + std::unique_ptr pStream(pIOHandler->Open(file, "rb")); + if (!pStream.get()) { + throw DeadlyImportError("Failed to open file " + file + "."); + } - // Get the file-size and validate it, throwing an exception when fails - size_t fileSize = pStream->FileSize(); - if (fileSize < 8) { - throw DeadlyImportError("M3D-file " + file + " is too small."); - } - std::vector buffer(fileSize); - if (fileSize != pStream->Read(buffer.data(), 1, fileSize)) { - throw DeadlyImportError("Failed to read the file " + file + "."); - } - // extra check for binary format's first 8 bytes. Not done for the ASCII variant - if(!memcmp(buffer.data(), "3DMO", 4) && memcmp(buffer.data() + 4, &fileSize, 4)) { - throw DeadlyImportError("Bad binary header in file " + file + "."); - } + // Get the file-size and validate it, throwing an exception when fails + size_t fileSize = pStream->FileSize(); + if (fileSize < 8) { + throw DeadlyImportError("M3D-file " + file + " is too small."); + } + std::vector buffer(fileSize); + if (fileSize != pStream->Read(buffer.data(), 1, fileSize)) { + throw DeadlyImportError("Failed to read the file " + file + "."); + } + // extra check for binary format's first 8 bytes. Not done for the ASCII variant + if (!memcmp(buffer.data(), "3DMO", 4) && memcmp(buffer.data() + 4, &fileSize, 4)) { + throw DeadlyImportError("Bad binary header in file " + file + "."); + } #ifdef M3D_ASCII - // make sure there's a terminator zero character, as input must be ASCIIZ - if(!memcmp(buffer.data(), "3dmo", 4)) { - buffer.push_back(0); - } + // make sure there's a terminator zero character, as input must be ASCIIZ + if (!memcmp(buffer.data(), "3dmo", 4)) { + buffer.push_back(0); + } #endif - // Get the path for external assets - std::string folderName("./"); - std::string::size_type pos = file.find_last_of("\\/"); - if (pos != std::string::npos) { - folderName = file.substr(0, pos); - if (!folderName.empty()) { - pIOHandler->PushDirectory(folderName); - } - } + // Get the path for external assets + std::string folderName("./"); + std::string::size_type pos = file.find_last_of("\\/"); + if (pos != std::string::npos) { + folderName = file.substr(0, pos); + if (!folderName.empty()) { + pIOHandler->PushDirectory(folderName); + } + } //DefaultLogger::create("/dev/stderr", Logger::VERBOSE); - ASSIMP_LOG_DEBUG_F("M3D: loading ", file); + ASSIMP_LOG_DEBUG_F("M3D: loading ", file); - // let the C SDK do the hard work for us - M3DWrapper m3d(pIOHandler, buffer); + // let the C SDK do the hard work for us + M3DWrapper m3d(pIOHandler, buffer); - if (!m3d) { - throw DeadlyImportError("Unable to parse " + file + " as M3D."); - } + if (!m3d) { + throw DeadlyImportError("Unable to parse " + file + " as M3D."); + } - // create the root node - pScene->mRootNode = new aiNode; - pScene->mRootNode->mName = aiString(m3d.Name()); - pScene->mRootNode->mTransformation = aiMatrix4x4(); - pScene->mRootNode->mNumChildren = 0; - mScene = pScene; + // create the root node + pScene->mRootNode = new aiNode; + pScene->mRootNode->mName = aiString(m3d.Name()); + pScene->mRootNode->mTransformation = aiMatrix4x4(); + pScene->mRootNode->mNumChildren = 0; + mScene = pScene; - ASSIMP_LOG_DEBUG("M3D: root node " + m3d.Name()); + ASSIMP_LOG_DEBUG("M3D: root node " + m3d.Name()); - // now we just have to fill up the Assimp structures in pScene - importMaterials(m3d); + // now we just have to fill up the Assimp structures in pScene + importMaterials(m3d); importTextures(m3d); - importBones(m3d, M3D_NOTDEFINED, pScene->mRootNode); - importMeshes(m3d); - importAnimations(m3d); + importBones(m3d, M3D_NOTDEFINED, pScene->mRootNode); + importMeshes(m3d); + importAnimations(m3d); - // Pop directory stack - if (pIOHandler->StackSize() > 0) { - pIOHandler->PopDirectory(); - } + // Pop directory stack + if (pIOHandler->StackSize() > 0) { + pIOHandler->PopDirectory(); + } } // ------------------------------------------------------------------------------------------------ // convert materials. properties are converted using a static table in M3DMaterials.h void M3DImporter::importMaterials(const M3DWrapper &m3d) { - unsigned int i, j, k, l, n; - m3dm_t *m; - aiString name = aiString(AI_DEFAULT_MATERIAL_NAME); - aiColor4D c; - ai_real f; + unsigned int i, j, k, l, n; + m3dm_t *m; + aiString name = aiString(AI_DEFAULT_MATERIAL_NAME); + aiColor4D c; + ai_real f; - ai_assert(mScene != nullptr); - ai_assert(m3d); + ai_assert(mScene != nullptr); + ai_assert(m3d); - mScene->mNumMaterials = m3d->nummaterial + 1; - mScene->mMaterials = new aiMaterial *[mScene->mNumMaterials]; + mScene->mNumMaterials = m3d->nummaterial + 1; + mScene->mMaterials = new aiMaterial *[mScene->mNumMaterials]; - ASSIMP_LOG_DEBUG_F("M3D: importMaterials ", mScene->mNumMaterials); + ASSIMP_LOG_DEBUG_F("M3D: importMaterials ", mScene->mNumMaterials); - // add a default material as first - aiMaterial *mat = new aiMaterial; - mat->AddProperty(&name, AI_MATKEY_NAME); - c.a = 1.0f; - c.b = c.g = c.r = 0.6f; - mat->AddProperty(&c, 1, AI_MATKEY_COLOR_DIFFUSE); - mScene->mMaterials[0] = mat; + // add a default material as first + aiMaterial *mat = new aiMaterial; + mat->AddProperty(&name, AI_MATKEY_NAME); + c.a = 1.0f; + c.b = c.g = c.r = 0.6f; + mat->AddProperty(&c, 1, AI_MATKEY_COLOR_DIFFUSE); + mScene->mMaterials[0] = mat; - if (!m3d->nummaterial || !m3d->material) { - return; - } + if (!m3d->nummaterial || !m3d->material) { + return; + } - for (i = 0; i < m3d->nummaterial; i++) { - m = &m3d->material[i]; - aiMaterial *mat = new aiMaterial; - name.Set(std::string(m->name)); - mat->AddProperty(&name, AI_MATKEY_NAME); - for (j = 0; j < m->numprop; j++) { - // look up property type - // 0 - 127 scalar values, - // 128 - 255 the same properties but for texture maps - k = 256; - for (l = 0; l < sizeof(m3d_propertytypes) / sizeof(m3d_propertytypes[0]); l++) - if (m->prop[j].type == m3d_propertytypes[l].id || - m->prop[j].type == m3d_propertytypes[l].id + 128) { - k = l; - break; - } - // should never happen, but be safe than sorry - if (k == 256) continue; + for (i = 0; i < m3d->nummaterial; i++) { + m = &m3d->material[i]; + aiMaterial *newMat = new aiMaterial; + name.Set(std::string(m->name)); + newMat->AddProperty(&name, AI_MATKEY_NAME); + for (j = 0; j < m->numprop; j++) { + // look up property type + // 0 - 127 scalar values, + // 128 - 255 the same properties but for texture maps + k = 256; + for (l = 0; l < sizeof(m3d_propertytypes) / sizeof(m3d_propertytypes[0]); l++) + if (m->prop[j].type == m3d_propertytypes[l].id || + m->prop[j].type == m3d_propertytypes[l].id + 128) { + k = l; + break; + } + // should never happen, but be safe than sorry + if (k == 256) + continue; - // scalar properties - if (m->prop[j].type < 128 && aiProps[k].pKey) { - switch (m3d_propertytypes[k].format) { - case m3dpf_color: - c = mkColor(m->prop[j].value.color); - mat->AddProperty(&c, 1, aiProps[k].pKey, aiProps[k].type, aiProps[k].index); - break; - case m3dpf_float: - f = m->prop[j].value.fnum; - mat->AddProperty(&f, 1, aiProps[k].pKey, aiProps[k].type, aiProps[k].index); - break; - default: - n = m->prop[j].value.num; - if (m->prop[j].type == m3dp_il) { - switch (n) { - case 0: n = aiShadingMode_NoShading; break; - case 2: n = aiShadingMode_Phong; break; - default: n = aiShadingMode_Gouraud; break; - } - } - mat->AddProperty(&n, 1, aiProps[k].pKey, aiProps[k].type, aiProps[k].index); - break; - } - } - // texture map properties - if (m->prop[j].type >= 128 && aiTxProps[k].pKey && - // extra check, should never happen, do we have the refered texture? - m->prop[j].value.textureid < m3d->numtexture && - m3d->texture[m->prop[j].value.textureid].name) { - name.Set(std::string(std::string(m3d->texture[m->prop[j].value.textureid].name) + ".png")); - mat->AddProperty(&name, aiTxProps[k].pKey, aiTxProps[k].type, aiTxProps[k].index); - n = 0; - mat->AddProperty(&n, 1, _AI_MATKEY_UVWSRC_BASE, aiProps[k].type, aiProps[k].index); - } - } - mScene->mMaterials[i + 1] = mat; - } + // scalar properties + if (m->prop[j].type < 128 && aiProps[k].pKey) { + switch (m3d_propertytypes[k].format) { + case m3dpf_color: + c = mkColor(m->prop[j].value.color); + newMat->AddProperty(&c, 1, aiProps[k].pKey, aiProps[k].type, aiProps[k].index); + break; + case m3dpf_float: + f = m->prop[j].value.fnum; + newMat->AddProperty(&f, 1, aiProps[k].pKey, aiProps[k].type, aiProps[k].index); + break; + default: + n = m->prop[j].value.num; + if (m->prop[j].type == m3dp_il) { + switch (n) { + case 0: + n = aiShadingMode_NoShading; + break; + case 2: + n = aiShadingMode_Phong; + break; + default: + n = aiShadingMode_Gouraud; + break; + } + } + newMat->AddProperty(&n, 1, aiProps[k].pKey, aiProps[k].type, aiProps[k].index); + break; + } + } + // texture map properties + if (m->prop[j].type >= 128 && aiTxProps[k].pKey && + // extra check, should never happen, do we have the refered texture? + m->prop[j].value.textureid < m3d->numtexture && + m3d->texture[m->prop[j].value.textureid].name) { + name.Set(std::string(std::string(m3d->texture[m->prop[j].value.textureid].name) + ".png")); + mat->AddProperty(&name, aiTxProps[k].pKey, aiTxProps[k].type, aiTxProps[k].index); + n = 0; + mat->AddProperty(&n, 1, _AI_MATKEY_UVWSRC_BASE, aiProps[k].type, aiProps[k].index); + } + } + mScene->mMaterials[i + 1] = mat; + } } // ------------------------------------------------------------------------------------------------ // import textures, this is the simplest of all void M3DImporter::importTextures(const M3DWrapper &m3d) { - unsigned int i; - const char *formatHint[] = { - "rgba0800", - "rgba0808", - "rgba8880", - "rgba8888" - }; - m3dtx_t *t; + unsigned int i; + const char *formatHint[] = { + "rgba0800", + "rgba0808", + "rgba8880", + "rgba8888" + }; + m3dtx_t *t; - ai_assert(mScene != nullptr); - ai_assert(m3d); + ai_assert(mScene != nullptr); + ai_assert(m3d); - mScene->mNumTextures = m3d->numtexture; - ASSIMP_LOG_DEBUG_F("M3D: importTextures ", mScene->mNumTextures); + mScene->mNumTextures = m3d->numtexture; + ASSIMP_LOG_DEBUG_F("M3D: importTextures ", mScene->mNumTextures); - if (!m3d->numtexture || !m3d->texture) { - return; - } + if (!m3d->numtexture || !m3d->texture) { + return; + } - mScene->mTextures = new aiTexture *[m3d->numtexture]; - for (i = 0; i < m3d->numtexture; i++) { - unsigned int j, k; - t = &m3d->texture[i]; - aiTexture *tx = new aiTexture; - tx->mFilename = aiString(std::string(t->name) + ".png"); - if (!t->w || !t->h || !t->f || !t->d) { - /* without ASSIMP_USE_M3D_READFILECB, we only have the filename, but no texture data ever */ - tx->mWidth = 0; - tx->mHeight = 0; - memcpy(tx->achFormatHint, "png\000", 4); - tx->pcData = nullptr; - } else { - /* if we have the texture loaded, set format hint and pcData too */ - tx->mWidth = t->w; - tx->mHeight = t->h; - strcpy(tx->achFormatHint, formatHint[t->f - 1]); - tx->pcData = new aiTexel[tx->mWidth * tx->mHeight]; - for (j = k = 0; j < tx->mWidth * tx->mHeight; j++) { - switch (t->f) { - case 1: tx->pcData[j].g = t->d[k++]; break; - case 2: - tx->pcData[j].g = t->d[k++]; - tx->pcData[j].a = t->d[k++]; - break; - case 3: - tx->pcData[j].r = t->d[k++]; - tx->pcData[j].g = t->d[k++]; - tx->pcData[j].b = t->d[k++]; - tx->pcData[j].a = 255; - break; - case 4: - tx->pcData[j].r = t->d[k++]; - tx->pcData[j].g = t->d[k++]; - tx->pcData[j].b = t->d[k++]; - tx->pcData[j].a = t->d[k++]; - break; - } - } - } - mScene->mTextures[i] = tx; - } + mScene->mTextures = new aiTexture *[m3d->numtexture]; + for (i = 0; i < m3d->numtexture; i++) { + unsigned int j, k; + t = &m3d->texture[i]; + aiTexture *tx = new aiTexture; + tx->mFilename = aiString(std::string(t->name) + ".png"); + if (!t->w || !t->h || !t->f || !t->d) { + /* without ASSIMP_USE_M3D_READFILECB, we only have the filename, but no texture data ever */ + tx->mWidth = 0; + tx->mHeight = 0; + memcpy(tx->achFormatHint, "png\000", 4); + tx->pcData = nullptr; + } else { + /* if we have the texture loaded, set format hint and pcData too */ + tx->mWidth = t->w; + tx->mHeight = t->h; + strcpy(tx->achFormatHint, formatHint[t->f - 1]); + tx->pcData = new aiTexel[tx->mWidth * tx->mHeight]; + for (j = k = 0; j < tx->mWidth * tx->mHeight; j++) { + switch (t->f) { + case 1: tx->pcData[j].g = t->d[k++]; break; + case 2: + tx->pcData[j].g = t->d[k++]; + tx->pcData[j].a = t->d[k++]; + break; + case 3: + tx->pcData[j].r = t->d[k++]; + tx->pcData[j].g = t->d[k++]; + tx->pcData[j].b = t->d[k++]; + tx->pcData[j].a = 255; + break; + case 4: + tx->pcData[j].r = t->d[k++]; + tx->pcData[j].g = t->d[k++]; + tx->pcData[j].b = t->d[k++]; + tx->pcData[j].a = t->d[k++]; + break; + } + } + } + mScene->mTextures[i] = tx; + } } // ------------------------------------------------------------------------------------------------ @@ -383,151 +390,150 @@ void M3DImporter::importTextures(const M3DWrapper &m3d) { // individually. In assimp there're per mesh vertex and UV lists, and they must be // indexed simultaneously. void M3DImporter::importMeshes(const M3DWrapper &m3d) { - ASSIMP_LOG_DEBUG_F("M3D: importMeshes ", m3d->numface); + ASSIMP_LOG_DEBUG_F("M3D: importMeshes ", m3d->numface); - if (!m3d->numface || !m3d->face || !m3d->numvertex || !m3d->vertex) { - return; - } + if (!m3d->numface || !m3d->face || !m3d->numvertex || !m3d->vertex) { + return; + } unsigned int i, j, k, l, numpoly = 3, lastMat = M3D_INDEXMAX; - std::vector *meshes = new std::vector(); - std::vector *faces = nullptr; - std::vector *vertices = nullptr; - std::vector *normals = nullptr; - std::vector *texcoords = nullptr; - std::vector *colors = nullptr; - std::vector *vertexids = nullptr; - aiMesh *pMesh = nullptr; + std::vector *meshes = new std::vector(); + std::vector *faces = nullptr; + std::vector *vertices = nullptr; + std::vector *normals = nullptr; + std::vector *texcoords = nullptr; + std::vector *colors = nullptr; + std::vector *vertexids = nullptr; + aiMesh *pMesh = nullptr; - ai_assert(mScene != nullptr); - ai_assert(m3d); - ai_assert(mScene->mRootNode != nullptr); + ai_assert(mScene != nullptr); + ai_assert(m3d); + ai_assert(mScene->mRootNode != nullptr); + for (i = 0; i < m3d->numface; i++) { + // we must switch mesh if material changes + if (lastMat != m3d->face[i].materialid) { + lastMat = m3d->face[i].materialid; + if (pMesh && vertices && vertices->size() && faces && faces->size()) { + populateMesh(m3d, pMesh, faces, vertices, normals, texcoords, colors, vertexids); + meshes->push_back(pMesh); + delete faces; + delete vertices; + delete normals; + delete texcoords; + delete colors; + delete vertexids; // this is not stored in pMesh, just to collect bone vertices + } + pMesh = new aiMesh; + pMesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE; + pMesh->mMaterialIndex = lastMat + 1; + faces = new std::vector(); + vertices = new std::vector(); + normals = new std::vector(); + texcoords = new std::vector(); + colors = new std::vector(); + vertexids = new std::vector(); + } + // add a face to temporary vector + aiFace *pFace = new aiFace; + pFace->mNumIndices = numpoly; + pFace->mIndices = new unsigned int[numpoly]; + for (j = 0; j < numpoly; j++) { + aiVector3D pos, uv, norm; + k = static_cast(vertices->size()); + pFace->mIndices[j] = k; + l = m3d->face[i].vertex[j]; + if (l >= m3d->numvertex) continue; + pos.x = m3d->vertex[l].x; + pos.y = m3d->vertex[l].y; + pos.z = m3d->vertex[l].z; + vertices->push_back(pos); + colors->push_back(mkColor(m3d->vertex[l].color)); + // add a bone to temporary vector + if (m3d->vertex[l].skinid != M3D_UNDEF && m3d->vertex[l].skinid != M3D_INDEXMAX && m3d->skin && m3d->bone) { + // this is complicated, because M3D stores a list of bone id / weight pairs per + // vertex but assimp uses lists of local vertex id/weight pairs per local bone list + vertexids->push_back(l); + } + l = m3d->face[i].texcoord[j]; + if (l != M3D_UNDEF && l < m3d->numtmap) { + uv.x = m3d->tmap[l].u; + uv.y = m3d->tmap[l].v; + uv.z = 0.0; + texcoords->push_back(uv); + } + l = m3d->face[i].normal[j]; + if (l != M3D_UNDEF && l < m3d->numvertex) { + norm.x = m3d->vertex[l].x; + norm.y = m3d->vertex[l].y; + norm.z = m3d->vertex[l].z; + normals->push_back(norm); + } + } + faces->push_back(*pFace); + delete pFace; + } + // if there's data left in the temporary vectors, flush them + if (pMesh && vertices->size() && faces->size()) { + populateMesh(m3d, pMesh, faces, vertices, normals, texcoords, colors, vertexids); + meshes->push_back(pMesh); + } - for (i = 0; i < m3d->numface; i++) { - // we must switch mesh if material changes - if (lastMat != m3d->face[i].materialid) { - lastMat = m3d->face[i].materialid; - if (pMesh && vertices && vertices->size() && faces && faces->size()) { - populateMesh(m3d, pMesh, faces, vertices, normals, texcoords, colors, vertexids); - meshes->push_back(pMesh); - delete faces; - delete vertices; - delete normals; - delete texcoords; - delete colors; - delete vertexids; // this is not stored in pMesh, just to collect bone vertices - } - pMesh = new aiMesh; - pMesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE; - pMesh->mMaterialIndex = lastMat + 1; - faces = new std::vector(); - vertices = new std::vector(); - normals = new std::vector(); - texcoords = new std::vector(); - colors = new std::vector(); - vertexids = new std::vector(); - } - // add a face to temporary vector - aiFace *pFace = new aiFace; - pFace->mNumIndices = numpoly; - pFace->mIndices = new unsigned int[numpoly]; - for (j = 0; j < numpoly; j++) { - aiVector3D pos, uv, norm; - k = static_cast(vertices->size()); - pFace->mIndices[j] = k; - l = m3d->face[i].vertex[j]; - if(l >= m3d->numvertex) continue; - pos.x = m3d->vertex[l].x; - pos.y = m3d->vertex[l].y; - pos.z = m3d->vertex[l].z; - vertices->push_back(pos); - colors->push_back(mkColor(m3d->vertex[l].color)); - // add a bone to temporary vector - if (m3d->vertex[l].skinid != M3D_UNDEF && m3d->vertex[l].skinid != M3D_INDEXMAX && m3d->skin && m3d->bone) { - // this is complicated, because M3D stores a list of bone id / weight pairs per - // vertex but assimp uses lists of local vertex id/weight pairs per local bone list - vertexids->push_back(l); - } - l = m3d->face[i].texcoord[j]; - if (l != M3D_UNDEF && l < m3d->numtmap) { - uv.x = m3d->tmap[l].u; - uv.y = m3d->tmap[l].v; - uv.z = 0.0; - texcoords->push_back(uv); - } - l = m3d->face[i].normal[j]; - if (l != M3D_UNDEF && l < m3d->numvertex) { - norm.x = m3d->vertex[l].x; - norm.y = m3d->vertex[l].y; - norm.z = m3d->vertex[l].z; - normals->push_back(norm); - } - } - faces->push_back(*pFace); - delete pFace; - } - // if there's data left in the temporary vectors, flush them - if (pMesh && vertices->size() && faces->size()) { - populateMesh(m3d, pMesh, faces, vertices, normals, texcoords, colors, vertexids); - meshes->push_back(pMesh); - } + // create global mesh list in scene + mScene->mNumMeshes = static_cast(meshes->size()); + mScene->mMeshes = new aiMesh *[mScene->mNumMeshes]; + std::copy(meshes->begin(), meshes->end(), mScene->mMeshes); - // create global mesh list in scene - mScene->mNumMeshes = static_cast(meshes->size()); - mScene->mMeshes = new aiMesh *[mScene->mNumMeshes]; - std::copy(meshes->begin(), meshes->end(), mScene->mMeshes); + // create mesh indeces in root node + mScene->mRootNode->mNumMeshes = static_cast(meshes->size()); + mScene->mRootNode->mMeshes = new unsigned int[meshes->size()]; + for (i = 0; i < meshes->size(); i++) { + mScene->mRootNode->mMeshes[i] = i; + } - // create mesh indeces in root node - mScene->mRootNode->mNumMeshes = static_cast(meshes->size()); - mScene->mRootNode->mMeshes = new unsigned int[meshes->size()]; - for (i = 0; i < meshes->size(); i++) { - mScene->mRootNode->mMeshes[i] = i; - } - - delete meshes; - if (faces) delete faces; - if (vertices) delete vertices; - if (normals) delete normals; - if (texcoords) delete texcoords; - if (colors) delete colors; - if (vertexids) delete vertexids; + delete meshes; + if (faces) delete faces; + if (vertices) delete vertices; + if (normals) delete normals; + if (texcoords) delete texcoords; + if (colors) delete colors; + if (vertexids) delete vertexids; } // ------------------------------------------------------------------------------------------------ // a reentrant node parser. Otherwise this is simple void M3DImporter::importBones(const M3DWrapper &m3d, unsigned int parentid, aiNode *pParent) { - unsigned int i, n; + unsigned int i, n; - ai_assert(pParent != nullptr); - ai_assert(mScene != nullptr); - ai_assert(m3d); + ai_assert(pParent != nullptr); + ai_assert(mScene != nullptr); + ai_assert(m3d); - ASSIMP_LOG_DEBUG_F("M3D: importBones ", m3d->numbone, " parentid ", (int)parentid); + ASSIMP_LOG_DEBUG_F("M3D: importBones ", m3d->numbone, " parentid ", (int)parentid); - if (!m3d->numbone || !m3d->bone) { - return; - } + if (!m3d->numbone || !m3d->bone) { + return; + } - for (n = 0, i = parentid + 1; i < m3d->numbone; i++) { - if (m3d->bone[i].parent == parentid) { - n++; - } - } - pParent->mChildren = new aiNode *[n]; + for (n = 0, i = parentid + 1; i < m3d->numbone; i++) { + if (m3d->bone[i].parent == parentid) { + n++; + } + } + pParent->mChildren = new aiNode *[n]; - for (i = parentid + 1; i < m3d->numbone; i++) { - if (m3d->bone[i].parent == parentid) { - aiNode *pChild = new aiNode; - pChild->mParent = pParent; - pChild->mName = aiString(std::string(m3d->bone[i].name)); - convertPose(m3d, &pChild->mTransformation, m3d->bone[i].pos, m3d->bone[i].ori); - pChild->mNumChildren = 0; - pParent->mChildren[pParent->mNumChildren] = pChild; - pParent->mNumChildren++; - importBones(m3d, i, pChild); - } - } + for (i = parentid + 1; i < m3d->numbone; i++) { + if (m3d->bone[i].parent == parentid) { + aiNode *pChild = new aiNode; + pChild->mParent = pParent; + pChild->mName = aiString(std::string(m3d->bone[i].name)); + convertPose(m3d, &pChild->mTransformation, m3d->bone[i].pos, m3d->bone[i].ori); + pChild->mNumChildren = 0; + pParent->mChildren[pParent->mNumChildren] = pChild; + pParent->mNumChildren++; + importBones(m3d, i, pChild); + } + } } // ------------------------------------------------------------------------------------------------ @@ -535,157 +541,157 @@ void M3DImporter::importBones(const M3DWrapper &m3d, unsigned int parentid, aiNo // a timestamp per frame, but assimp needs timestamp and lists of position, orientation lists per // bone, so we have to convert between the two conceptually different representation forms void M3DImporter::importAnimations(const M3DWrapper &m3d) { - unsigned int i, j, k, l, pos, ori; - double t; - m3da_t *a; + unsigned int i, j, k, l, pos, ori; + double t; + m3da_t *a; - ai_assert(mScene != nullptr); - ai_assert(m3d); + ai_assert(mScene != nullptr); + ai_assert(m3d); - mScene->mNumAnimations = m3d->numaction; + mScene->mNumAnimations = m3d->numaction; - ASSIMP_LOG_DEBUG_F("M3D: importAnimations ", mScene->mNumAnimations); + ASSIMP_LOG_DEBUG_F("M3D: importAnimations ", mScene->mNumAnimations); - if (!m3d->numaction || !m3d->action || !m3d->numbone || !m3d->bone || !m3d->vertex) { - return; - } + if (!m3d->numaction || !m3d->action || !m3d->numbone || !m3d->bone || !m3d->vertex) { + return; + } - mScene->mAnimations = new aiAnimation *[m3d->numaction]; - for (i = 0; i < m3d->numaction; i++) { - a = &m3d->action[i]; - aiAnimation *pAnim = new aiAnimation; - pAnim->mName = aiString(std::string(a->name)); - pAnim->mDuration = ((double)a->durationmsec) / 10; - pAnim->mTicksPerSecond = 100; - // now we know how many bones are referenced in this animation - pAnim->mNumChannels = m3d->numbone; - pAnim->mChannels = new aiNodeAnim *[pAnim->mNumChannels]; - for (l = 0; l < m3d->numbone; l++) { - unsigned int n; - pAnim->mChannels[l] = new aiNodeAnim; - pAnim->mChannels[l]->mNodeName = aiString(std::string(m3d->bone[l].name)); - // now n is the size of positions / orientations arrays - pAnim->mChannels[l]->mNumPositionKeys = pAnim->mChannels[l]->mNumRotationKeys = a->numframe; - pAnim->mChannels[l]->mPositionKeys = new aiVectorKey[a->numframe]; - pAnim->mChannels[l]->mRotationKeys = new aiQuatKey[a->numframe]; - pos = m3d->bone[l].pos; - ori = m3d->bone[l].ori; - for (j = n = 0; j < a->numframe; j++) { - t = ((double)a->frame[j].msec) / 10; - for (k = 0; k < a->frame[j].numtransform; k++) { - if (a->frame[j].transform[k].boneid == l) { - pos = a->frame[j].transform[k].pos; - ori = a->frame[j].transform[k].ori; - } - } - if(pos >= m3d->numvertex || ori >= m3d->numvertex) continue; - m3dv_t *v = &m3d->vertex[pos]; - m3dv_t *q = &m3d->vertex[ori]; - pAnim->mChannels[l]->mPositionKeys[j].mTime = t; - pAnim->mChannels[l]->mPositionKeys[j].mValue.x = v->x; - pAnim->mChannels[l]->mPositionKeys[j].mValue.y = v->y; - pAnim->mChannels[l]->mPositionKeys[j].mValue.z = v->z; - pAnim->mChannels[l]->mRotationKeys[j].mTime = t; - pAnim->mChannels[l]->mRotationKeys[j].mValue.w = q->w; - pAnim->mChannels[l]->mRotationKeys[j].mValue.x = q->x; - pAnim->mChannels[l]->mRotationKeys[j].mValue.y = q->y; - pAnim->mChannels[l]->mRotationKeys[j].mValue.z = q->z; - } // foreach frame - } // foreach bones - mScene->mAnimations[i] = pAnim; - } + mScene->mAnimations = new aiAnimation *[m3d->numaction]; + for (i = 0; i < m3d->numaction; i++) { + a = &m3d->action[i]; + aiAnimation *pAnim = new aiAnimation; + pAnim->mName = aiString(std::string(a->name)); + pAnim->mDuration = ((double)a->durationmsec) / 10; + pAnim->mTicksPerSecond = 100; + // now we know how many bones are referenced in this animation + pAnim->mNumChannels = m3d->numbone; + pAnim->mChannels = new aiNodeAnim *[pAnim->mNumChannels]; + for (l = 0; l < m3d->numbone; l++) { + unsigned int n; + pAnim->mChannels[l] = new aiNodeAnim; + pAnim->mChannels[l]->mNodeName = aiString(std::string(m3d->bone[l].name)); + // now n is the size of positions / orientations arrays + pAnim->mChannels[l]->mNumPositionKeys = pAnim->mChannels[l]->mNumRotationKeys = a->numframe; + pAnim->mChannels[l]->mPositionKeys = new aiVectorKey[a->numframe]; + pAnim->mChannels[l]->mRotationKeys = new aiQuatKey[a->numframe]; + pos = m3d->bone[l].pos; + ori = m3d->bone[l].ori; + for (j = n = 0; j < a->numframe; j++) { + t = ((double)a->frame[j].msec) / 10; + for (k = 0; k < a->frame[j].numtransform; k++) { + if (a->frame[j].transform[k].boneid == l) { + pos = a->frame[j].transform[k].pos; + ori = a->frame[j].transform[k].ori; + } + } + if (pos >= m3d->numvertex || ori >= m3d->numvertex) continue; + m3dv_t *v = &m3d->vertex[pos]; + m3dv_t *q = &m3d->vertex[ori]; + pAnim->mChannels[l]->mPositionKeys[j].mTime = t; + pAnim->mChannels[l]->mPositionKeys[j].mValue.x = v->x; + pAnim->mChannels[l]->mPositionKeys[j].mValue.y = v->y; + pAnim->mChannels[l]->mPositionKeys[j].mValue.z = v->z; + pAnim->mChannels[l]->mRotationKeys[j].mTime = t; + pAnim->mChannels[l]->mRotationKeys[j].mValue.w = q->w; + pAnim->mChannels[l]->mRotationKeys[j].mValue.x = q->x; + pAnim->mChannels[l]->mRotationKeys[j].mValue.y = q->y; + pAnim->mChannels[l]->mRotationKeys[j].mValue.z = q->z; + } // foreach frame + } // foreach bones + mScene->mAnimations[i] = pAnim; + } } // ------------------------------------------------------------------------------------------------ // convert uint32_t into aiColor4D aiColor4D M3DImporter::mkColor(uint32_t c) { - aiColor4D color; - color.a = ((float)((c >> 24) & 0xff)) / 255; - color.b = ((float)((c >> 16) & 0xff)) / 255; - color.g = ((float)((c >> 8) & 0xff)) / 255; - color.r = ((float)((c >> 0) & 0xff)) / 255; - return color; + aiColor4D color; + color.a = ((float)((c >> 24) & 0xff)) / 255; + color.b = ((float)((c >> 16) & 0xff)) / 255; + color.g = ((float)((c >> 8) & 0xff)) / 255; + color.r = ((float)((c >> 0) & 0xff)) / 255; + return color; } // ------------------------------------------------------------------------------------------------ // convert a position id and orientation id into a 4 x 4 transformation matrix void M3DImporter::convertPose(const M3DWrapper &m3d, aiMatrix4x4 *m, unsigned int posid, unsigned int orientid) { - ai_assert(m != nullptr); - ai_assert(m3d); - ai_assert(posid != M3D_UNDEF && posid < m3d->numvertex); - ai_assert(orientid != M3D_UNDEF && orientid < m3d->numvertex); - if (!m3d->numvertex || !m3d->vertex) - return; - m3dv_t *p = &m3d->vertex[posid]; - m3dv_t *q = &m3d->vertex[orientid]; + ai_assert(m != nullptr); + ai_assert(m3d); + ai_assert(posid != M3D_UNDEF && posid < m3d->numvertex); + ai_assert(orientid != M3D_UNDEF && orientid < m3d->numvertex); + if (!m3d->numvertex || !m3d->vertex) + return; + m3dv_t *p = &m3d->vertex[posid]; + m3dv_t *q = &m3d->vertex[orientid]; - /* quaternion to matrix. Do NOT use aiQuaternion to aiMatrix3x3, gives bad results */ - if (q->x == 0.0 && q->y == 0.0 && q->z >= 0.7071065 && q->z <= 0.7071075 && q->w == 0.0) { - m->a2 = m->a3 = m->b1 = m->b3 = m->c1 = m->c2 = 0.0; - m->a1 = m->b2 = m->c3 = -1.0; - } else { - m->a1 = 1 - 2 * (q->y * q->y + q->z * q->z); - if (m->a1 > -M3D_EPSILON && m->a1 < M3D_EPSILON) m->a1 = 0.0; - m->a2 = 2 * (q->x * q->y - q->z * q->w); - if (m->a2 > -M3D_EPSILON && m->a2 < M3D_EPSILON) m->a2 = 0.0; - m->a3 = 2 * (q->x * q->z + q->y * q->w); - if (m->a3 > -M3D_EPSILON && m->a3 < M3D_EPSILON) m->a3 = 0.0; - m->b1 = 2 * (q->x * q->y + q->z * q->w); - if (m->b1 > -M3D_EPSILON && m->b1 < M3D_EPSILON) m->b1 = 0.0; - m->b2 = 1 - 2 * (q->x * q->x + q->z * q->z); - if (m->b2 > -M3D_EPSILON && m->b2 < M3D_EPSILON) m->b2 = 0.0; - m->b3 = 2 * (q->y * q->z - q->x * q->w); - if (m->b3 > -M3D_EPSILON && m->b3 < M3D_EPSILON) m->b3 = 0.0; - m->c1 = 2 * (q->x * q->z - q->y * q->w); - if (m->c1 > -M3D_EPSILON && m->c1 < M3D_EPSILON) m->c1 = 0.0; - m->c2 = 2 * (q->y * q->z + q->x * q->w); - if (m->c2 > -M3D_EPSILON && m->c2 < M3D_EPSILON) m->c2 = 0.0; - m->c3 = 1 - 2 * (q->x * q->x + q->y * q->y); - if (m->c3 > -M3D_EPSILON && m->c3 < M3D_EPSILON) m->c3 = 0.0; - } + /* quaternion to matrix. Do NOT use aiQuaternion to aiMatrix3x3, gives bad results */ + if (q->x == 0.0 && q->y == 0.0 && q->z >= 0.7071065 && q->z <= 0.7071075 && q->w == 0.0) { + m->a2 = m->a3 = m->b1 = m->b3 = m->c1 = m->c2 = 0.0; + m->a1 = m->b2 = m->c3 = -1.0; + } else { + m->a1 = 1 - 2 * (q->y * q->y + q->z * q->z); + if (m->a1 > -M3D_EPSILON && m->a1 < M3D_EPSILON) m->a1 = 0.0; + m->a2 = 2 * (q->x * q->y - q->z * q->w); + if (m->a2 > -M3D_EPSILON && m->a2 < M3D_EPSILON) m->a2 = 0.0; + m->a3 = 2 * (q->x * q->z + q->y * q->w); + if (m->a3 > -M3D_EPSILON && m->a3 < M3D_EPSILON) m->a3 = 0.0; + m->b1 = 2 * (q->x * q->y + q->z * q->w); + if (m->b1 > -M3D_EPSILON && m->b1 < M3D_EPSILON) m->b1 = 0.0; + m->b2 = 1 - 2 * (q->x * q->x + q->z * q->z); + if (m->b2 > -M3D_EPSILON && m->b2 < M3D_EPSILON) m->b2 = 0.0; + m->b3 = 2 * (q->y * q->z - q->x * q->w); + if (m->b3 > -M3D_EPSILON && m->b3 < M3D_EPSILON) m->b3 = 0.0; + m->c1 = 2 * (q->x * q->z - q->y * q->w); + if (m->c1 > -M3D_EPSILON && m->c1 < M3D_EPSILON) m->c1 = 0.0; + m->c2 = 2 * (q->y * q->z + q->x * q->w); + if (m->c2 > -M3D_EPSILON && m->c2 < M3D_EPSILON) m->c2 = 0.0; + m->c3 = 1 - 2 * (q->x * q->x + q->y * q->y); + if (m->c3 > -M3D_EPSILON && m->c3 < M3D_EPSILON) m->c3 = 0.0; + } - /* set translation */ - m->a4 = p->x; - m->b4 = p->y; - m->c4 = p->z; + /* set translation */ + m->a4 = p->x; + m->b4 = p->y; + m->c4 = p->z; - m->d1 = 0; - m->d2 = 0; - m->d3 = 0; - m->d4 = 1; + m->d1 = 0; + m->d2 = 0; + m->d3 = 0; + m->d4 = 1; } // ------------------------------------------------------------------------------------------------ // find a node by name aiNode *M3DImporter::findNode(aiNode *pNode, aiString name) { - ai_assert(pNode != nullptr); - ai_assert(mScene != nullptr); + ai_assert(pNode != nullptr); + ai_assert(mScene != nullptr); - if (pNode->mName == name) { - return pNode; - } + if (pNode->mName == name) { + return pNode; + } - for (unsigned int i = 0; i < pNode->mNumChildren; i++) { - aiNode *pChild = findNode(pNode->mChildren[i], name); - if (pChild) { - return pChild; - } - } - return nullptr; + for (unsigned int i = 0; i < pNode->mNumChildren; i++) { + aiNode *pChild = findNode(pNode->mChildren[i], name); + if (pChild) { + return pChild; + } + } + return nullptr; } // ------------------------------------------------------------------------------------------------ // fills up offsetmatrix in mBones void M3DImporter::calculateOffsetMatrix(aiNode *pNode, aiMatrix4x4 *m) { - ai_assert(pNode != nullptr); - ai_assert(mScene != nullptr); + ai_assert(pNode != nullptr); + ai_assert(mScene != nullptr); - if (pNode->mParent) { - calculateOffsetMatrix(pNode->mParent, m); - *m *= pNode->mTransformation; - } else { - *m = pNode->mTransformation; - } + if (pNode->mParent) { + calculateOffsetMatrix(pNode->mParent, m); + *m *= pNode->mTransformation; + } else { + *m = pNode->mTransformation; + } } // ------------------------------------------------------------------------------------------------ @@ -693,110 +699,110 @@ void M3DImporter::calculateOffsetMatrix(aiNode *pNode, aiMatrix4x4 *m) { // temporary lists to collect data for an aiMesh, which requires local arrays and local indeces // this function fills up an aiMesh with those temporary lists void M3DImporter::populateMesh(const M3DWrapper &m3d, aiMesh *pMesh, std::vector *faces, std::vector *vertices, - std::vector *normals, std::vector *texcoords, std::vector *colors, - std::vector *vertexids) { + std::vector *normals, std::vector *texcoords, std::vector *colors, + std::vector *vertexids) { - ai_assert(pMesh != nullptr); - ai_assert(faces != nullptr); - ai_assert(vertices != nullptr); - ai_assert(normals != nullptr); - ai_assert(texcoords != nullptr); - ai_assert(colors != nullptr); - ai_assert(vertexids != nullptr); - ai_assert(m3d); + ai_assert(pMesh != nullptr); + ai_assert(faces != nullptr); + ai_assert(vertices != nullptr); + ai_assert(normals != nullptr); + ai_assert(texcoords != nullptr); + ai_assert(colors != nullptr); + ai_assert(vertexids != nullptr); + ai_assert(m3d); - ASSIMP_LOG_DEBUG_F("M3D: populateMesh numvertices ", vertices->size(), " numfaces ", faces->size(), - " numnormals ", normals->size(), " numtexcoord ", texcoords->size(), " numbones ", m3d->numbone); + ASSIMP_LOG_DEBUG_F("M3D: populateMesh numvertices ", vertices->size(), " numfaces ", faces->size(), + " numnormals ", normals->size(), " numtexcoord ", texcoords->size(), " numbones ", m3d->numbone); - if (vertices->size() && faces->size()) { - pMesh->mNumFaces = static_cast(faces->size()); - pMesh->mFaces = new aiFace[pMesh->mNumFaces]; - std::copy(faces->begin(), faces->end(), pMesh->mFaces); - pMesh->mNumVertices = static_cast(vertices->size()); - pMesh->mVertices = new aiVector3D[pMesh->mNumVertices]; - std::copy(vertices->begin(), vertices->end(), pMesh->mVertices); - if (normals->size() == vertices->size()) { - pMesh->mNormals = new aiVector3D[pMesh->mNumVertices]; - std::copy(normals->begin(), normals->end(), pMesh->mNormals); - } - if (texcoords->size() == vertices->size()) { - pMesh->mTextureCoords[0] = new aiVector3D[pMesh->mNumVertices]; - std::copy(texcoords->begin(), texcoords->end(), pMesh->mTextureCoords[0]); - pMesh->mNumUVComponents[0] = 2; - } - if (colors->size() == vertices->size()) { - pMesh->mColors[0] = new aiColor4D[pMesh->mNumVertices]; - std::copy(colors->begin(), colors->end(), pMesh->mColors[0]); - } - // this is complicated, because M3D stores a list of bone id / weight pairs per - // vertex but assimp uses lists of local vertex id/weight pairs per local bone list - pMesh->mNumBones = m3d->numbone; - // we need aiBone with mOffsetMatrix for bones without weights as well - if (pMesh->mNumBones && m3d->numbone && m3d->bone) { - pMesh->mBones = new aiBone *[pMesh->mNumBones]; - for (unsigned int i = 0; i < m3d->numbone; i++) { - aiNode *pNode; - pMesh->mBones[i] = new aiBone; - pMesh->mBones[i]->mName = aiString(std::string(m3d->bone[i].name)); - pMesh->mBones[i]->mNumWeights = 0; - pNode = findNode(mScene->mRootNode, pMesh->mBones[i]->mName); - if (pNode) { - calculateOffsetMatrix(pNode, &pMesh->mBones[i]->mOffsetMatrix); - pMesh->mBones[i]->mOffsetMatrix.Inverse(); - } else - pMesh->mBones[i]->mOffsetMatrix = aiMatrix4x4(); - } - if (vertexids->size() && m3d->numvertex && m3d->vertex && m3d->numskin && m3d->skin) { - unsigned int i, j; - // first count how many vertices we have per bone - for (i = 0; i < vertexids->size(); i++) { - if(vertexids->at(i) >= m3d->numvertex) { - continue; - } - unsigned int s = m3d->vertex[vertexids->at(i)].skinid; - if (s != M3D_UNDEF && s != M3D_INDEXMAX) { - for (unsigned int k = 0; k < M3D_NUMBONE && m3d->skin[s].weight[k] > 0.0; k++) { - aiString name = aiString(std::string(m3d->bone[m3d->skin[s].boneid[k]].name)); - for (j = 0; j < pMesh->mNumBones; j++) { - if (pMesh->mBones[j]->mName == name) { - pMesh->mBones[j]->mNumWeights++; - break; - } - } - } - } - } - // allocate mWeights - for (j = 0; j < pMesh->mNumBones; j++) { - aiBone *pBone = pMesh->mBones[j]; - if (pBone->mNumWeights) { - pBone->mWeights = new aiVertexWeight[pBone->mNumWeights]; - pBone->mNumWeights = 0; - } - } - // fill up with data - for (i = 0; i < vertexids->size(); i++) { - if(vertexids->at(i) >= m3d->numvertex) continue; - unsigned int s = m3d->vertex[vertexids->at(i)].skinid; - if (s != M3D_UNDEF && s != M3D_INDEXMAX && s < m3d->numskin) { - for (unsigned int k = 0; k < M3D_NUMBONE && m3d->skin[s].weight[k] > 0.0; k++) { - if(m3d->skin[s].boneid[k] >= m3d->numbone) continue; - aiString name = aiString(std::string(m3d->bone[m3d->skin[s].boneid[k]].name)); - for (j = 0; j < pMesh->mNumBones; j++) { - if (pMesh->mBones[j]->mName == name) { - aiBone *pBone = pMesh->mBones[j]; - pBone->mWeights[pBone->mNumWeights].mVertexId = i; - pBone->mWeights[pBone->mNumWeights].mWeight = m3d->skin[s].weight[k]; - pBone->mNumWeights++; - break; - } - } - } // foreach skin - } - } // foreach vertexids - } - } - } + if (vertices->size() && faces->size()) { + pMesh->mNumFaces = static_cast(faces->size()); + pMesh->mFaces = new aiFace[pMesh->mNumFaces]; + std::copy(faces->begin(), faces->end(), pMesh->mFaces); + pMesh->mNumVertices = static_cast(vertices->size()); + pMesh->mVertices = new aiVector3D[pMesh->mNumVertices]; + std::copy(vertices->begin(), vertices->end(), pMesh->mVertices); + if (normals->size() == vertices->size()) { + pMesh->mNormals = new aiVector3D[pMesh->mNumVertices]; + std::copy(normals->begin(), normals->end(), pMesh->mNormals); + } + if (texcoords->size() == vertices->size()) { + pMesh->mTextureCoords[0] = new aiVector3D[pMesh->mNumVertices]; + std::copy(texcoords->begin(), texcoords->end(), pMesh->mTextureCoords[0]); + pMesh->mNumUVComponents[0] = 2; + } + if (colors->size() == vertices->size()) { + pMesh->mColors[0] = new aiColor4D[pMesh->mNumVertices]; + std::copy(colors->begin(), colors->end(), pMesh->mColors[0]); + } + // this is complicated, because M3D stores a list of bone id / weight pairs per + // vertex but assimp uses lists of local vertex id/weight pairs per local bone list + pMesh->mNumBones = m3d->numbone; + // we need aiBone with mOffsetMatrix for bones without weights as well + if (pMesh->mNumBones && m3d->numbone && m3d->bone) { + pMesh->mBones = new aiBone *[pMesh->mNumBones]; + for (unsigned int i = 0; i < m3d->numbone; i++) { + aiNode *pNode; + pMesh->mBones[i] = new aiBone; + pMesh->mBones[i]->mName = aiString(std::string(m3d->bone[i].name)); + pMesh->mBones[i]->mNumWeights = 0; + pNode = findNode(mScene->mRootNode, pMesh->mBones[i]->mName); + if (pNode) { + calculateOffsetMatrix(pNode, &pMesh->mBones[i]->mOffsetMatrix); + pMesh->mBones[i]->mOffsetMatrix.Inverse(); + } else + pMesh->mBones[i]->mOffsetMatrix = aiMatrix4x4(); + } + if (vertexids->size() && m3d->numvertex && m3d->vertex && m3d->numskin && m3d->skin) { + unsigned int i, j; + // first count how many vertices we have per bone + for (i = 0; i < vertexids->size(); i++) { + if (vertexids->at(i) >= m3d->numvertex) { + continue; + } + unsigned int s = m3d->vertex[vertexids->at(i)].skinid; + if (s != M3D_UNDEF && s != M3D_INDEXMAX) { + for (unsigned int k = 0; k < M3D_NUMBONE && m3d->skin[s].weight[k] > 0.0; k++) { + aiString name = aiString(std::string(m3d->bone[m3d->skin[s].boneid[k]].name)); + for (j = 0; j < pMesh->mNumBones; j++) { + if (pMesh->mBones[j]->mName == name) { + pMesh->mBones[j]->mNumWeights++; + break; + } + } + } + } + } + // allocate mWeights + for (j = 0; j < pMesh->mNumBones; j++) { + aiBone *pBone = pMesh->mBones[j]; + if (pBone->mNumWeights) { + pBone->mWeights = new aiVertexWeight[pBone->mNumWeights]; + pBone->mNumWeights = 0; + } + } + // fill up with data + for (i = 0; i < vertexids->size(); i++) { + if (vertexids->at(i) >= m3d->numvertex) continue; + unsigned int s = m3d->vertex[vertexids->at(i)].skinid; + if (s != M3D_UNDEF && s != M3D_INDEXMAX && s < m3d->numskin) { + for (unsigned int k = 0; k < M3D_NUMBONE && m3d->skin[s].weight[k] > 0.0; k++) { + if (m3d->skin[s].boneid[k] >= m3d->numbone) continue; + aiString name = aiString(std::string(m3d->bone[m3d->skin[s].boneid[k]].name)); + for (j = 0; j < pMesh->mNumBones; j++) { + if (pMesh->mBones[j]->mName == name) { + aiBone *pBone = pMesh->mBones[j]; + pBone->mWeights[pBone->mNumWeights].mVertexId = i; + pBone->mWeights[pBone->mNumWeights].mWeight = m3d->skin[s].weight[k]; + pBone->mNumWeights++; + break; + } + } + } // foreach skin + } + } // foreach vertexids + } + } + } } // ------------------------------------------------------------------------------------------------ diff --git a/code/M3D/M3DWrapper.cpp b/code/M3D/M3DWrapper.cpp index 6ab59b2f0..eca8af75f 100644 --- a/code/M3D/M3DWrapper.cpp +++ b/code/M3D/M3DWrapper.cpp @@ -100,6 +100,10 @@ M3DWrapper::M3DWrapper() { } M3DWrapper::M3DWrapper(IOSystem *pIOHandler, const std::vector &buffer) { + if (nullptr == pIOHandler) { + ai_assert(nullptr != pIOHandler); + } + #ifdef ASSIMP_USE_M3D_READFILECB // pass this IOHandler to the C callback in a thread-local pointer m3dimporter_pIOHandler = pIOHandler; diff --git a/code/M3D/m3d.h b/code/M3D/m3d.h index d09348497..a1981a440 100644 --- a/code/M3D/m3d.h +++ b/code/M3D/m3d.h @@ -99,6 +99,10 @@ typedef uint16_t M3D_INDEX; #define _register #endif +#pragma warning(push) +#pragma warning(disable : 4127 ) +#pragma warning(disable : 4505 ) + /*** File format structures ***/ /** @@ -2162,8 +2166,8 @@ M3D_INDEX _m3d_gettx(m3d_t *model, m3dread_t readfilecb, m3dfree_t freecb, char w = h = len = 0; ri.bits_per_channel = 8; model->texture[i].d = (uint8_t*)stbi__png_load(&s, (int*)&w, (int*)&h, (int*)&len, 0, &ri); - model->texture[i].w = w; - model->texture[i].h = h; + model->texture[i].w = (uint16_t) w; + model->texture[i].h = (uint16_t) h; model->texture[i].f = (uint8_t)len; #endif } else { @@ -5605,6 +5609,9 @@ namespace M3D { #endif /* impl */ } + +#pragma warning(pop<) + #endif #endif /* __cplusplus */ diff --git a/code/MD5/MD5Loader.cpp b/code/MD5/MD5Loader.cpp index 8c41794e7..d428873df 100644 --- a/code/MD5/MD5Loader.cpp +++ b/code/MD5/MD5Loader.cpp @@ -45,21 +45,20 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * @brief Implementation of the MD5 importer class */ - #ifndef ASSIMP_BUILD_NO_MD5_IMPORTER // internal headers -#include #include "MD5Loader.h" +#include +#include +#include #include #include -#include -#include -#include -#include -#include -#include #include +#include +#include +#include +#include #include using namespace Assimp; @@ -67,7 +66,6 @@ using namespace Assimp; // Minimum weight value. Weights inside [-n ... n] are ignored #define AI_MD5_WEIGHT_EPSILON Math::getEpsilon() - static const aiImporterDesc desc = { "Doom 3 / MD5 Mesh Importer", "", @@ -83,93 +81,78 @@ static const aiImporterDesc desc = { // ------------------------------------------------------------------------------------------------ // Constructor to be privately used by Importer -MD5Importer::MD5Importer() - : mIOHandler() - , mBuffer() - , fileSize() - , iLineNumber() - , pScene() - , pIOHandler() - , bHadMD5Mesh() - , bHadMD5Anim() - , bHadMD5Camera() - , configNoAutoLoad (false) -{} +MD5Importer::MD5Importer() : + mIOHandler(nullptr), mBuffer(), fileSize(), iLineNumber(), pScene(), bHadMD5Mesh(), bHadMD5Anim(), bHadMD5Camera(), configNoAutoLoad(false) { + // empty +} // ------------------------------------------------------------------------------------------------ // Destructor, private as well -MD5Importer::~MD5Importer() -{} +MD5Importer::~MD5Importer() { + // empty +} // ------------------------------------------------------------------------------------------------ // Returns whether the class can handle the format of the given file. -bool MD5Importer::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const -{ +bool MD5Importer::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const { const std::string extension = GetExtension(pFile); if (extension == "md5anim" || extension == "md5mesh" || extension == "md5camera") return true; - else if (!extension.length() || checkSig) { + else if (!extension.length() || checkSig) { if (!pIOHandler) { return true; } - const char* tokens[] = {"MD5Version"}; - return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1); + const char *tokens[] = { "MD5Version" }; + return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 1); } return false; } // ------------------------------------------------------------------------------------------------ // Get list of all supported extensions -const aiImporterDesc* MD5Importer::GetInfo () const -{ +const aiImporterDesc *MD5Importer::GetInfo() const { return &desc; } // ------------------------------------------------------------------------------------------------ // Setup import properties -void MD5Importer::SetupProperties(const Importer* pImp) -{ +void MD5Importer::SetupProperties(const Importer *pImp) { // AI_CONFIG_IMPORT_MD5_NO_ANIM_AUTOLOAD - configNoAutoLoad = (0 != pImp->GetPropertyInteger(AI_CONFIG_IMPORT_MD5_NO_ANIM_AUTOLOAD,0)); + configNoAutoLoad = (0 != pImp->GetPropertyInteger(AI_CONFIG_IMPORT_MD5_NO_ANIM_AUTOLOAD, 0)); } // ------------------------------------------------------------------------------------------------ // Imports the given file into the given scene structure. -void MD5Importer::InternReadFile( const std::string& pFile, - aiScene* _pScene, IOSystem* _pIOHandler) -{ - pIOHandler = _pIOHandler; - pScene = _pScene; +void MD5Importer::InternReadFile(const std::string &pFile, + aiScene *_pScene, IOSystem *pIOHandler) { + mIOHandler = pIOHandler; + pScene = _pScene; bHadMD5Mesh = bHadMD5Anim = bHadMD5Camera = false; // remove the file extension const std::string::size_type pos = pFile.find_last_of('.'); - mFile = (std::string::npos == pos ? pFile : pFile.substr(0,pos+1)); + mFile = (std::string::npos == pos ? pFile : pFile.substr(0, pos + 1)); const std::string extension = GetExtension(pFile); try { if (extension == "md5camera") { LoadMD5CameraFile(); - } - else if (configNoAutoLoad || extension == "md5anim") { + } else if (configNoAutoLoad || extension == "md5anim") { // determine file extension and process just *one* file if (extension.length() == 0) { throw DeadlyImportError("Failure, need file extension to determine MD5 part type"); } if (extension == "md5anim") { LoadMD5AnimFile(); - } - else if (extension == "md5mesh") { + } else if (extension == "md5mesh") { LoadMD5MeshFile(); } - } - else { + } else { LoadMD5MeshFile(); LoadMD5AnimFile(); } - } - catch ( ... ) { // std::exception, Assimp::DeadlyImportError + } catch (...) { // std::exception, Assimp::DeadlyImportError UnloadFileFromMemory(); throw; } @@ -180,8 +163,8 @@ void MD5Importer::InternReadFile( const std::string& pFile, } // Now rotate the whole scene 90 degrees around the x axis to match our internal coordinate system - pScene->mRootNode->mTransformation = aiMatrix4x4(1.f,0.f,0.f,0.f, - 0.f,0.f,1.f,0.f,0.f,-1.f,0.f,0.f,0.f,0.f,0.f,1.f); + pScene->mRootNode->mTransformation = aiMatrix4x4(1.f, 0.f, 0.f, 0.f, + 0.f, 0.f, 1.f, 0.f, 0.f, -1.f, 0.f, 0.f, 0.f, 0.f, 0.f, 1.f); // the output scene wouldn't pass the validation without this flag if (!bHadMD5Mesh) { @@ -194,8 +177,7 @@ void MD5Importer::InternReadFile( const std::string& pFile, // ------------------------------------------------------------------------------------------------ // Load a file into a memory buffer -void MD5Importer::LoadFileIntoMemory (IOStream* file) -{ +void MD5Importer::LoadFileIntoMemory(IOStream *file) { // unload the previous buffer, if any UnloadFileFromMemory(); @@ -204,21 +186,20 @@ void MD5Importer::LoadFileIntoMemory (IOStream* file) ai_assert(fileSize); // allocate storage and copy the contents of the file to a memory buffer - mBuffer = new char[fileSize+1]; - file->Read( (void*)mBuffer, 1, fileSize); + mBuffer = new char[fileSize + 1]; + file->Read((void *)mBuffer, 1, fileSize); iLineNumber = 1; // append a terminal 0 mBuffer[fileSize] = '\0'; // now remove all line comments from the file - CommentRemover::RemoveLineComments("//",mBuffer,' '); + CommentRemover::RemoveLineComments("//", mBuffer, ' '); } // ------------------------------------------------------------------------------------------------ // Unload the current memory buffer -void MD5Importer::UnloadFileFromMemory () -{ +void MD5Importer::UnloadFileFromMemory() { // delete the file buffer delete[] mBuffer; mBuffer = NULL; @@ -227,57 +208,55 @@ void MD5Importer::UnloadFileFromMemory () // ------------------------------------------------------------------------------------------------ // Build unique vertices -void MD5Importer::MakeDataUnique (MD5::MeshDesc& meshSrc) -{ - std::vector abHad(meshSrc.mVertices.size(),false); +void MD5Importer::MakeDataUnique(MD5::MeshDesc &meshSrc) { + std::vector abHad(meshSrc.mVertices.size(), false); // allocate enough storage to keep the output structures - const unsigned int iNewNum = static_cast(meshSrc.mFaces.size()*3); + const unsigned int iNewNum = static_cast(meshSrc.mFaces.size() * 3); unsigned int iNewIndex = static_cast(meshSrc.mVertices.size()); meshSrc.mVertices.resize(iNewNum); // try to guess how much storage we'll need for new weights const float fWeightsPerVert = meshSrc.mWeights.size() / (float)iNewIndex; - const unsigned int guess = (unsigned int)(fWeightsPerVert*iNewNum); + const unsigned int guess = (unsigned int)(fWeightsPerVert * iNewNum); meshSrc.mWeights.reserve(guess + (guess >> 3)); // + 12.5% as buffer - for (FaceList::const_iterator iter = meshSrc.mFaces.begin(),iterEnd = meshSrc.mFaces.end();iter != iterEnd;++iter){ - const aiFace& face = *iter; - for (unsigned int i = 0; i < 3;++i) { + for (FaceList::const_iterator iter = meshSrc.mFaces.begin(), iterEnd = meshSrc.mFaces.end(); iter != iterEnd; ++iter) { + const aiFace &face = *iter; + for (unsigned int i = 0; i < 3; ++i) { if (face.mIndices[0] >= meshSrc.mVertices.size()) { throw DeadlyImportError("MD5MESH: Invalid vertex index"); } - if (abHad[face.mIndices[i]]) { + if (abHad[face.mIndices[i]]) { // generate a new vertex meshSrc.mVertices[iNewIndex] = meshSrc.mVertices[face.mIndices[i]]; face.mIndices[i] = iNewIndex++; - } - else abHad[face.mIndices[i]] = true; + } else + abHad[face.mIndices[i]] = true; } // swap face order - std::swap(face.mIndices[0],face.mIndices[2]); + std::swap(face.mIndices[0], face.mIndices[2]); } } // ------------------------------------------------------------------------------------------------ // Recursive node graph construction from a MD5MESH -void MD5Importer::AttachChilds_Mesh(int iParentID,aiNode* piParent, BoneList& bones) -{ +void MD5Importer::AttachChilds_Mesh(int iParentID, aiNode *piParent, BoneList &bones) { ai_assert(NULL != piParent && !piParent->mNumChildren); // First find out how many children we'll have - for (int i = 0; i < (int)bones.size();++i) { - if (iParentID != i && bones[i].mParentIndex == iParentID) { + for (int i = 0; i < (int)bones.size(); ++i) { + if (iParentID != i && bones[i].mParentIndex == iParentID) { ++piParent->mNumChildren; } } if (piParent->mNumChildren) { - piParent->mChildren = new aiNode*[piParent->mNumChildren]; - for (int i = 0; i < (int)bones.size();++i) { + piParent->mChildren = new aiNode *[piParent->mNumChildren]; + for (int i = 0; i < (int)bones.size(); ++i) { // (avoid infinite recursion) - if (iParentID != i && bones[i].mParentIndex == iParentID) { - aiNode* pc; + if (iParentID != i && bones[i].mParentIndex == iParentID) { + aiNode *pc; // setup a new node *piParent->mChildren++ = pc = new aiNode(); pc->mName = aiString(bones[i].mName); @@ -285,9 +264,9 @@ void MD5Importer::AttachChilds_Mesh(int iParentID,aiNode* piParent, BoneList& bo // get the transformation matrix from rotation and translational components aiQuaternion quat; - MD5::ConvertQuaternion ( bones[i].mRotationQuat, quat ); + MD5::ConvertQuaternion(bones[i].mRotationQuat, quat); - bones[i].mTransform = aiMatrix4x4 ( quat.GetMatrix()); + bones[i].mTransform = aiMatrix4x4(quat.GetMatrix()); bones[i].mTransform.a4 = bones[i].mPositionXYZ.x; bones[i].mTransform.b4 = bones[i].mPositionXYZ.y; bones[i].mTransform.c4 = bones[i].mPositionXYZ.z; @@ -298,12 +277,12 @@ void MD5Importer::AttachChilds_Mesh(int iParentID,aiNode* piParent, BoneList& bo // the transformations for each bone are absolute, so we need to multiply them // with the inverse of the absolute matrix of the parent joint - if (-1 != iParentID) { + if (-1 != iParentID) { pc->mTransformation = bones[iParentID].mInvTransform * pc->mTransformation; } // add children to this node, too - AttachChilds_Mesh( i, pc, bones); + AttachChilds_Mesh(i, pc, bones); } } // undo offset computations @@ -313,37 +292,36 @@ void MD5Importer::AttachChilds_Mesh(int iParentID,aiNode* piParent, BoneList& bo // ------------------------------------------------------------------------------------------------ // Recursive node graph construction from a MD5ANIM -void MD5Importer::AttachChilds_Anim(int iParentID,aiNode* piParent, AnimBoneList& bones,const aiNodeAnim** node_anims) -{ +void MD5Importer::AttachChilds_Anim(int iParentID, aiNode *piParent, AnimBoneList &bones, const aiNodeAnim **node_anims) { ai_assert(NULL != piParent && !piParent->mNumChildren); // First find out how many children we'll have - for (int i = 0; i < (int)bones.size();++i) { - if (iParentID != i && bones[i].mParentIndex == iParentID) { + for (int i = 0; i < (int)bones.size(); ++i) { + if (iParentID != i && bones[i].mParentIndex == iParentID) { ++piParent->mNumChildren; } } if (piParent->mNumChildren) { - piParent->mChildren = new aiNode*[piParent->mNumChildren]; - for (int i = 0; i < (int)bones.size();++i) { + piParent->mChildren = new aiNode *[piParent->mNumChildren]; + for (int i = 0; i < (int)bones.size(); ++i) { // (avoid infinite recursion) - if (iParentID != i && bones[i].mParentIndex == iParentID) - { - aiNode* pc; + if (iParentID != i && bones[i].mParentIndex == iParentID) { + aiNode *pc; // setup a new node *piParent->mChildren++ = pc = new aiNode(); pc->mName = aiString(bones[i].mName); pc->mParent = piParent; // get the corresponding animation channel and its first frame - const aiNodeAnim** cur = node_anims; - while ((**cur).mNodeName != pc->mName)++cur; + const aiNodeAnim **cur = node_anims; + while ((**cur).mNodeName != pc->mName) + ++cur; - aiMatrix4x4::Translation((**cur).mPositionKeys[0].mValue,pc->mTransformation); - pc->mTransformation = pc->mTransformation * aiMatrix4x4((**cur).mRotationKeys[0].mValue.GetMatrix()) ; + aiMatrix4x4::Translation((**cur).mPositionKeys[0].mValue, pc->mTransformation); + pc->mTransformation = pc->mTransformation * aiMatrix4x4((**cur).mRotationKeys[0].mValue.GetMatrix()); // add children to this node, too - AttachChilds_Anim( i, pc, bones,node_anims); + AttachChilds_Anim(i, pc, bones, node_anims); } } // undo offset computations @@ -353,13 +331,12 @@ void MD5Importer::AttachChilds_Anim(int iParentID,aiNode* piParent, AnimBoneList // ------------------------------------------------------------------------------------------------ // Load a MD5MESH file -void MD5Importer::LoadMD5MeshFile () -{ +void MD5Importer::LoadMD5MeshFile() { std::string pFile = mFile + "md5mesh"; - std::unique_ptr file( pIOHandler->Open( pFile, "rb")); + std::unique_ptr file(mIOHandler->Open(pFile, "rb")); // Check whether we can read from the file - if( file.get() == NULL || !file->FileSize()) { + if (file.get() == nullptr || !file->FileSize()) { ASSIMP_LOG_WARN("Failed to access MD5MESH file: " + pFile); return; } @@ -367,7 +344,7 @@ void MD5Importer::LoadMD5MeshFile () LoadFileIntoMemory(file.get()); // now construct a parser and parse the file - MD5::MD5Parser parser(mBuffer,fileSize); + MD5::MD5Parser parser(mBuffer, fileSize); // load the mesh information from it MD5::MD5MeshParser meshParser(parser.mSections); @@ -375,13 +352,13 @@ void MD5Importer::LoadMD5MeshFile () // create the bone hierarchy - first the root node and dummy nodes for all meshes pScene->mRootNode = new aiNode(""); pScene->mRootNode->mNumChildren = 2; - pScene->mRootNode->mChildren = new aiNode*[2]; + pScene->mRootNode->mChildren = new aiNode *[2]; // build the hierarchy from the MD5MESH file - aiNode* pcNode = pScene->mRootNode->mChildren[1] = new aiNode(); + aiNode *pcNode = pScene->mRootNode->mChildren[1] = new aiNode(); pcNode->mName.Set(""); pcNode->mParent = pScene->mRootNode; - AttachChilds_Mesh(-1,pcNode,meshParser.mJoints); + AttachChilds_Mesh(-1, pcNode, meshParser.mJoints); pcNode = pScene->mRootNode->mChildren[0] = new aiNode(); pcNode->mName.Set(""); @@ -393,96 +370,94 @@ void MD5Importer::LoadMD5MeshFile () #else // FIX: MD5 files exported from Blender can have empty meshes - for (std::vector::const_iterator it = meshParser.mMeshes.begin(),end = meshParser.mMeshes.end(); it != end;++it) { + for (std::vector::const_iterator it = meshParser.mMeshes.begin(), end = meshParser.mMeshes.end(); it != end; ++it) { if (!(*it).mFaces.empty() && !(*it).mVertices.empty()) ++pScene->mNumMaterials; } // generate all meshes pScene->mNumMeshes = pScene->mNumMaterials; - pScene->mMeshes = new aiMesh*[pScene->mNumMeshes]; - pScene->mMaterials = new aiMaterial*[pScene->mNumMeshes]; + pScene->mMeshes = new aiMesh *[pScene->mNumMeshes]; + pScene->mMaterials = new aiMaterial *[pScene->mNumMeshes]; // storage for node mesh indices pcNode->mNumMeshes = pScene->mNumMeshes; pcNode->mMeshes = new unsigned int[pcNode->mNumMeshes]; - for (unsigned int m = 0; m < pcNode->mNumMeshes;++m) + for (unsigned int m = 0; m < pcNode->mNumMeshes; ++m) pcNode->mMeshes[m] = m; unsigned int n = 0; - for (std::vector::iterator it = meshParser.mMeshes.begin(),end = meshParser.mMeshes.end(); it != end;++it) { - MD5::MeshDesc& meshSrc = *it; + for (std::vector::iterator it = meshParser.mMeshes.begin(), end = meshParser.mMeshes.end(); it != end; ++it) { + MD5::MeshDesc &meshSrc = *it; if (meshSrc.mFaces.empty() || meshSrc.mVertices.empty()) continue; - aiMesh* mesh = pScene->mMeshes[n] = new aiMesh(); + aiMesh *mesh = pScene->mMeshes[n] = new aiMesh(); mesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE; // generate unique vertices in our internal verbose format MakeDataUnique(meshSrc); - std::string name( meshSrc.mShader.C_Str() ); + std::string name(meshSrc.mShader.C_Str()); name += ".msh"; mesh->mName = name; - mesh->mNumVertices = (unsigned int) meshSrc.mVertices.size(); + mesh->mNumVertices = (unsigned int)meshSrc.mVertices.size(); mesh->mVertices = new aiVector3D[mesh->mNumVertices]; mesh->mTextureCoords[0] = new aiVector3D[mesh->mNumVertices]; mesh->mNumUVComponents[0] = 2; // copy texture coordinates - aiVector3D* pv = mesh->mTextureCoords[0]; - for (MD5::VertexList::const_iterator iter = meshSrc.mVertices.begin();iter != meshSrc.mVertices.end();++iter,++pv) { + aiVector3D *pv = mesh->mTextureCoords[0]; + for (MD5::VertexList::const_iterator iter = meshSrc.mVertices.begin(); iter != meshSrc.mVertices.end(); ++iter, ++pv) { pv->x = (*iter).mUV.x; - pv->y = 1.0f-(*iter).mUV.y; // D3D to OpenGL + pv->y = 1.0f - (*iter).mUV.y; // D3D to OpenGL pv->z = 0.0f; } // sort all bone weights - per bone - unsigned int* piCount = new unsigned int[meshParser.mJoints.size()]; - ::memset(piCount,0,sizeof(unsigned int)*meshParser.mJoints.size()); + unsigned int *piCount = new unsigned int[meshParser.mJoints.size()]; + ::memset(piCount, 0, sizeof(unsigned int) * meshParser.mJoints.size()); - for (MD5::VertexList::const_iterator iter = meshSrc.mVertices.begin();iter != meshSrc.mVertices.end();++iter,++pv) { - for (unsigned int jub = (*iter).mFirstWeight, w = jub; w < jub + (*iter).mNumWeights;++w) - { - MD5::WeightDesc& weightDesc = meshSrc.mWeights[w]; + for (MD5::VertexList::const_iterator iter = meshSrc.mVertices.begin(); iter != meshSrc.mVertices.end(); ++iter, ++pv) { + for (unsigned int jub = (*iter).mFirstWeight, w = jub; w < jub + (*iter).mNumWeights; ++w) { + MD5::WeightDesc &weightDesc = meshSrc.mWeights[w]; /* FIX for some invalid exporters */ - if (!(weightDesc.mWeight < AI_MD5_WEIGHT_EPSILON && weightDesc.mWeight >= -AI_MD5_WEIGHT_EPSILON )) + if (!(weightDesc.mWeight < AI_MD5_WEIGHT_EPSILON && weightDesc.mWeight >= -AI_MD5_WEIGHT_EPSILON)) ++piCount[weightDesc.mBone]; } } // check how many we will need - for (unsigned int p = 0; p < meshParser.mJoints.size();++p) - if (piCount[p])mesh->mNumBones++; + for (unsigned int p = 0; p < meshParser.mJoints.size(); ++p) + if (piCount[p]) mesh->mNumBones++; if (mesh->mNumBones) // just for safety { - mesh->mBones = new aiBone*[mesh->mNumBones]; - for (unsigned int q = 0,h = 0; q < meshParser.mJoints.size();++q) - { - if (!piCount[q])continue; - aiBone* p = mesh->mBones[h] = new aiBone(); + mesh->mBones = new aiBone *[mesh->mNumBones]; + for (unsigned int q = 0, h = 0; q < meshParser.mJoints.size(); ++q) { + if (!piCount[q]) continue; + aiBone *p = mesh->mBones[h] = new aiBone(); p->mNumWeights = piCount[q]; p->mWeights = new aiVertexWeight[p->mNumWeights]; p->mName = aiString(meshParser.mJoints[q].mName); p->mOffsetMatrix = meshParser.mJoints[q].mInvTransform; // store the index for later use - MD5::BoneDesc& boneSrc = meshParser.mJoints[q]; + MD5::BoneDesc &boneSrc = meshParser.mJoints[q]; boneSrc.mMap = h++; // compute w-component of quaternion - MD5::ConvertQuaternion( boneSrc.mRotationQuat, boneSrc.mRotationQuatConverted ); + MD5::ConvertQuaternion(boneSrc.mRotationQuat, boneSrc.mRotationQuatConverted); } pv = mesh->mVertices; - for (MD5::VertexList::const_iterator iter = meshSrc.mVertices.begin();iter != meshSrc.mVertices.end();++iter,++pv) { + for (MD5::VertexList::const_iterator iter = meshSrc.mVertices.begin(); iter != meshSrc.mVertices.end(); ++iter, ++pv) { // compute the final vertex position from all single weights *pv = aiVector3D(); // there are models which have weights which don't sum to 1 ... ai_real fSum = 0.0; - for (unsigned int jub = (*iter).mFirstWeight, w = jub; w < jub + (*iter).mNumWeights;++w) + for (unsigned int jub = (*iter).mFirstWeight, w = jub; w < jub + (*iter).mNumWeights; ++w) fSum += meshSrc.mWeights[w].mWeight; if (!fSum) { ASSIMP_LOG_ERROR("MD5MESH: The sum of all vertex bone weights is 0"); @@ -490,32 +465,32 @@ void MD5Importer::LoadMD5MeshFile () } // process bone weights - for (unsigned int jub = (*iter).mFirstWeight, w = jub; w < jub + (*iter).mNumWeights;++w) { + for (unsigned int jub = (*iter).mFirstWeight, w = jub; w < jub + (*iter).mNumWeights; ++w) { if (w >= meshSrc.mWeights.size()) throw DeadlyImportError("MD5MESH: Invalid weight index"); - MD5::WeightDesc& weightDesc = meshSrc.mWeights[w]; - if ( weightDesc.mWeight < AI_MD5_WEIGHT_EPSILON && weightDesc.mWeight >= -AI_MD5_WEIGHT_EPSILON) { + MD5::WeightDesc &weightDesc = meshSrc.mWeights[w]; + if (weightDesc.mWeight < AI_MD5_WEIGHT_EPSILON && weightDesc.mWeight >= -AI_MD5_WEIGHT_EPSILON) { continue; } const ai_real fNewWeight = weightDesc.mWeight / fSum; // transform the local position into worldspace - MD5::BoneDesc& boneSrc = meshParser.mJoints[weightDesc.mBone]; - const aiVector3D v = boneSrc.mRotationQuatConverted.Rotate (weightDesc.vOffsetPosition); + MD5::BoneDesc &boneSrc = meshParser.mJoints[weightDesc.mBone]; + const aiVector3D v = boneSrc.mRotationQuatConverted.Rotate(weightDesc.vOffsetPosition); // use the original weight to compute the vertex position // (some MD5s seem to depend on the invalid weight values ...) - *pv += ((boneSrc.mPositionXYZ+v)* (ai_real)weightDesc.mWeight); + *pv += ((boneSrc.mPositionXYZ + v) * (ai_real)weightDesc.mWeight); - aiBone* bone = mesh->mBones[boneSrc.mMap]; - *bone->mWeights++ = aiVertexWeight((unsigned int)(pv-mesh->mVertices),fNewWeight); + aiBone *bone = mesh->mBones[boneSrc.mMap]; + *bone->mWeights++ = aiVertexWeight((unsigned int)(pv - mesh->mVertices), fNewWeight); } } // undo our nice offset tricks ... - for (unsigned int p = 0; p < mesh->mNumBones;++p) { + for (unsigned int p = 0; p < mesh->mNumBones; ++p) { mesh->mBones[p]->mWeights -= mesh->mBones[p]->mNumWeights; } } @@ -526,14 +501,14 @@ void MD5Importer::LoadMD5MeshFile () // (however, take care that the aiFace destructor doesn't delete the mIndices array) mesh->mNumFaces = (unsigned int)meshSrc.mFaces.size(); mesh->mFaces = new aiFace[mesh->mNumFaces]; - for (unsigned int c = 0; c < mesh->mNumFaces;++c) { + for (unsigned int c = 0; c < mesh->mNumFaces; ++c) { mesh->mFaces[c].mNumIndices = 3; mesh->mFaces[c].mIndices = meshSrc.mFaces[c].mIndices; meshSrc.mFaces[c].mIndices = NULL; } // generate a material for the mesh - aiMaterial* mat = new aiMaterial(); + aiMaterial *mat = new aiMaterial(); pScene->mMaterials[n] = mat; // insert the typical doom3 textures: @@ -541,28 +516,27 @@ void MD5Importer::LoadMD5MeshFile () // nnn_h.tga - height map // nnn_s.tga - specular map // nnn_d.tga - diffuse map - if (meshSrc.mShader.length && !strchr(meshSrc.mShader.data,'.')) { + if (meshSrc.mShader.length && !strchr(meshSrc.mShader.data, '.')) { aiString temp(meshSrc.mShader); temp.Append("_local.tga"); - mat->AddProperty(&temp,AI_MATKEY_TEXTURE_NORMALS(0)); + mat->AddProperty(&temp, AI_MATKEY_TEXTURE_NORMALS(0)); - temp = aiString(meshSrc.mShader); + temp = aiString(meshSrc.mShader); temp.Append("_s.tga"); - mat->AddProperty(&temp,AI_MATKEY_TEXTURE_SPECULAR(0)); + mat->AddProperty(&temp, AI_MATKEY_TEXTURE_SPECULAR(0)); - temp = aiString(meshSrc.mShader); + temp = aiString(meshSrc.mShader); temp.Append("_d.tga"); - mat->AddProperty(&temp,AI_MATKEY_TEXTURE_DIFFUSE(0)); + mat->AddProperty(&temp, AI_MATKEY_TEXTURE_DIFFUSE(0)); - temp = aiString(meshSrc.mShader); + temp = aiString(meshSrc.mShader); temp.Append("_h.tga"); - mat->AddProperty(&temp,AI_MATKEY_TEXTURE_HEIGHT(0)); + mat->AddProperty(&temp, AI_MATKEY_TEXTURE_HEIGHT(0)); // set this also as material name - mat->AddProperty(&meshSrc.mShader,AI_MATKEY_NAME); - } - else { + mat->AddProperty(&meshSrc.mShader, AI_MATKEY_NAME); + } else { mat->AddProperty(&meshSrc.mShader, AI_MATKEY_TEXTURE_DIFFUSE(0)); } mesh->mMaterialIndex = n++; @@ -572,39 +546,37 @@ void MD5Importer::LoadMD5MeshFile () // ------------------------------------------------------------------------------------------------ // Load an MD5ANIM file -void MD5Importer::LoadMD5AnimFile () -{ +void MD5Importer::LoadMD5AnimFile() { std::string pFile = mFile + "md5anim"; - std::unique_ptr file( pIOHandler->Open( pFile, "rb")); + std::unique_ptr file(mIOHandler->Open(pFile, "rb")); // Check whether we can read from the file - if( !file.get() || !file->FileSize()) { + if (!file.get() || !file->FileSize()) { ASSIMP_LOG_WARN("Failed to read MD5ANIM file: " + pFile); return; } LoadFileIntoMemory(file.get()); // parse the basic file structure - MD5::MD5Parser parser(mBuffer,fileSize); + MD5::MD5Parser parser(mBuffer, fileSize); // load the animation information from the parse tree MD5::MD5AnimParser animParser(parser.mSections); // generate and fill the output animation if (animParser.mAnimatedBones.empty() || animParser.mFrames.empty() || - animParser.mBaseFrames.size() != animParser.mAnimatedBones.size()) { + animParser.mBaseFrames.size() != animParser.mAnimatedBones.size()) { ASSIMP_LOG_ERROR("MD5ANIM: No frames or animated bones loaded"); - } - else { + } else { bHadMD5Anim = true; - pScene->mAnimations = new aiAnimation*[pScene->mNumAnimations = 1]; - aiAnimation* anim = pScene->mAnimations[0] = new aiAnimation(); + pScene->mAnimations = new aiAnimation *[pScene->mNumAnimations = 1]; + aiAnimation *anim = pScene->mAnimations[0] = new aiAnimation(); anim->mNumChannels = (unsigned int)animParser.mAnimatedBones.size(); - anim->mChannels = new aiNodeAnim*[anim->mNumChannels]; - for (unsigned int i = 0; i < anim->mNumChannels;++i) { - aiNodeAnim* node = anim->mChannels[i] = new aiNodeAnim(); - node->mNodeName = aiString( animParser.mAnimatedBones[i].mName ); + anim->mChannels = new aiNodeAnim *[anim->mNumChannels]; + for (unsigned int i = 0; i < anim->mNumChannels; ++i) { + aiNodeAnim *node = anim->mChannels[i] = new aiNodeAnim(); + node->mNodeName = aiString(animParser.mAnimatedBones[i].mName); // allocate storage for the keyframes node->mPositionKeys = new aiVectorKey[animParser.mFrames.size()]; @@ -614,46 +586,44 @@ void MD5Importer::LoadMD5AnimFile () // 1 tick == 1 frame anim->mTicksPerSecond = animParser.fFrameRate; - for (FrameList::const_iterator iter = animParser.mFrames.begin(), iterEnd = animParser.mFrames.end();iter != iterEnd;++iter){ + for (FrameList::const_iterator iter = animParser.mFrames.begin(), iterEnd = animParser.mFrames.end(); iter != iterEnd; ++iter) { double dTime = (double)(*iter).iIndex; - aiNodeAnim** pcAnimNode = anim->mChannels; + aiNodeAnim **pcAnimNode = anim->mChannels; if (!(*iter).mValues.empty() || iter == animParser.mFrames.begin()) /* be sure we have at least one frame */ { // now process all values in there ... read all joints - MD5::BaseFrameDesc* pcBaseFrame = &animParser.mBaseFrames[0]; - for (AnimBoneList::const_iterator iter2 = animParser.mAnimatedBones.begin(); iter2 != animParser.mAnimatedBones.end();++iter2, - ++pcAnimNode,++pcBaseFrame) - { - if((*iter2).iFirstKeyIndex >= (*iter).mValues.size()) { + MD5::BaseFrameDesc *pcBaseFrame = &animParser.mBaseFrames[0]; + for (AnimBoneList::const_iterator iter2 = animParser.mAnimatedBones.begin(); iter2 != animParser.mAnimatedBones.end(); ++iter2, + ++pcAnimNode, ++pcBaseFrame) { + if ((*iter2).iFirstKeyIndex >= (*iter).mValues.size()) { // Allow for empty frames if ((*iter2).iFlags != 0) { throw DeadlyImportError("MD5: Keyframe index is out of range"); - } continue; } - const float* fpCur = &(*iter).mValues[(*iter2).iFirstKeyIndex]; - aiNodeAnim* pcCurAnimBone = *pcAnimNode; + const float *fpCur = &(*iter).mValues[(*iter2).iFirstKeyIndex]; + aiNodeAnim *pcCurAnimBone = *pcAnimNode; - aiVectorKey* vKey = &pcCurAnimBone->mPositionKeys[pcCurAnimBone->mNumPositionKeys++]; - aiQuatKey* qKey = &pcCurAnimBone->mRotationKeys [pcCurAnimBone->mNumRotationKeys++]; + aiVectorKey *vKey = &pcCurAnimBone->mPositionKeys[pcCurAnimBone->mNumPositionKeys++]; + aiQuatKey *qKey = &pcCurAnimBone->mRotationKeys[pcCurAnimBone->mNumRotationKeys++]; aiVector3D vTemp; // translational component for (unsigned int i = 0; i < 3; ++i) { if ((*iter2).iFlags & (1u << i)) { - vKey->mValue[i] = *fpCur++; - } - else vKey->mValue[i] = pcBaseFrame->vPositionXYZ[i]; + vKey->mValue[i] = *fpCur++; + } else + vKey->mValue[i] = pcBaseFrame->vPositionXYZ[i]; } // orientation component for (unsigned int i = 0; i < 3; ++i) { if ((*iter2).iFlags & (8u << i)) { - vTemp[i] = *fpCur++; - } - else vTemp[i] = pcBaseFrame->vRotationQuat[i]; + vTemp[i] = *fpCur++; + } else + vTemp[i] = pcBaseFrame->vRotationQuat[i]; } MD5::ConvertQuaternion(vTemp, qKey->mValue); @@ -662,7 +632,7 @@ void MD5Importer::LoadMD5AnimFile () } // compute the duration of the animation - anim->mDuration = std::max(dTime,anim->mDuration); + anim->mDuration = std::max(dTime, anim->mDuration); } // If we didn't build the hierarchy yet (== we didn't load a MD5MESH), @@ -671,11 +641,11 @@ void MD5Importer::LoadMD5AnimFile () pScene->mRootNode = new aiNode(); pScene->mRootNode->mName.Set(""); - AttachChilds_Anim(-1,pScene->mRootNode,animParser.mAnimatedBones,(const aiNodeAnim**)anim->mChannels); + AttachChilds_Anim(-1, pScene->mRootNode, animParser.mAnimatedBones, (const aiNodeAnim **)anim->mChannels); // Call SkeletonMeshBuilder to construct a mesh to represent the shape if (pScene->mRootNode->mNumChildren) { - SkeletonMeshBuilder skeleton_maker(pScene,pScene->mRootNode->mChildren[0]); + SkeletonMeshBuilder skeleton_maker(pScene, pScene->mRootNode->mChildren[0]); } } } @@ -683,20 +653,19 @@ void MD5Importer::LoadMD5AnimFile () // ------------------------------------------------------------------------------------------------ // Load an MD5CAMERA file -void MD5Importer::LoadMD5CameraFile () -{ +void MD5Importer::LoadMD5CameraFile() { std::string pFile = mFile + "md5camera"; - std::unique_ptr file( pIOHandler->Open( pFile, "rb")); + std::unique_ptr file(mIOHandler->Open(pFile, "rb")); // Check whether we can read from the file - if( !file.get() || !file->FileSize()) { + if (!file.get() || !file->FileSize()) { throw DeadlyImportError("Failed to read MD5CAMERA file: " + pFile); } bHadMD5Camera = true; LoadFileIntoMemory(file.get()); // parse the basic file structure - MD5::MD5Parser parser(mBuffer,fileSize); + MD5::MD5Parser parser(mBuffer, fileSize); // load the camera animation data from the parse tree MD5::MD5CameraParser cameraParser(parser.mSections); @@ -705,56 +674,55 @@ void MD5Importer::LoadMD5CameraFile () throw DeadlyImportError("MD5CAMERA: No frames parsed"); } - std::vector& cuts = cameraParser.cuts; - std::vector& frames = cameraParser.frames; + std::vector &cuts = cameraParser.cuts; + std::vector &frames = cameraParser.frames; // Construct output graph - a simple root with a dummy child. // The root node performs the coordinate system conversion - aiNode* root = pScene->mRootNode = new aiNode(""); - root->mChildren = new aiNode*[root->mNumChildren = 1]; + aiNode *root = pScene->mRootNode = new aiNode(""); + root->mChildren = new aiNode *[root->mNumChildren = 1]; root->mChildren[0] = new aiNode(""); root->mChildren[0]->mParent = root; // ... but with one camera assigned to it - pScene->mCameras = new aiCamera*[pScene->mNumCameras = 1]; - aiCamera* cam = pScene->mCameras[0] = new aiCamera(); + pScene->mCameras = new aiCamera *[pScene->mNumCameras = 1]; + aiCamera *cam = pScene->mCameras[0] = new aiCamera(); cam->mName = ""; // FIXME: Fov is currently set to the first frame's value - cam->mHorizontalFOV = AI_DEG_TO_RAD( frames.front().fFOV ); + cam->mHorizontalFOV = AI_DEG_TO_RAD(frames.front().fFOV); // every cut is written to a separate aiAnimation if (!cuts.size()) { cuts.push_back(0); - cuts.push_back(static_cast(frames.size()-1)); - } - else { - cuts.insert(cuts.begin(),0); + cuts.push_back(static_cast(frames.size() - 1)); + } else { + cuts.insert(cuts.begin(), 0); - if (cuts.back() < frames.size()-1) - cuts.push_back(static_cast(frames.size()-1)); + if (cuts.back() < frames.size() - 1) + cuts.push_back(static_cast(frames.size() - 1)); } - pScene->mNumAnimations = static_cast(cuts.size()-1); - aiAnimation** tmp = pScene->mAnimations = new aiAnimation*[pScene->mNumAnimations]; - for (std::vector::const_iterator it = cuts.begin(); it != cuts.end()-1; ++it) { + pScene->mNumAnimations = static_cast(cuts.size() - 1); + aiAnimation **tmp = pScene->mAnimations = new aiAnimation *[pScene->mNumAnimations]; + for (std::vector::const_iterator it = cuts.begin(); it != cuts.end() - 1; ++it) { - aiAnimation* anim = *tmp++ = new aiAnimation(); - anim->mName.length = ::ai_snprintf(anim->mName.data, MAXLEN, "anim%u_from_%u_to_%u",(unsigned int)(it-cuts.begin()),(*it),*(it+1)); + aiAnimation *anim = *tmp++ = new aiAnimation(); + anim->mName.length = ::ai_snprintf(anim->mName.data, MAXLEN, "anim%u_from_%u_to_%u", (unsigned int)(it - cuts.begin()), (*it), *(it + 1)); anim->mTicksPerSecond = cameraParser.fFrameRate; - anim->mChannels = new aiNodeAnim*[anim->mNumChannels = 1]; - aiNodeAnim* nd = anim->mChannels[0] = new aiNodeAnim(); + anim->mChannels = new aiNodeAnim *[anim->mNumChannels = 1]; + aiNodeAnim *nd = anim->mChannels[0] = new aiNodeAnim(); nd->mNodeName.Set(""); - nd->mNumPositionKeys = nd->mNumRotationKeys = *(it+1) - (*it); + nd->mNumPositionKeys = nd->mNumRotationKeys = *(it + 1) - (*it); nd->mPositionKeys = new aiVectorKey[nd->mNumPositionKeys]; - nd->mRotationKeys = new aiQuatKey [nd->mNumRotationKeys]; + nd->mRotationKeys = new aiQuatKey[nd->mNumRotationKeys]; for (unsigned int i = 0; i < nd->mNumPositionKeys; ++i) { - nd->mPositionKeys[i].mValue = frames[*it+i].vPositionXYZ; - MD5::ConvertQuaternion(frames[*it+i].vRotationQuat,nd->mRotationKeys[i].mValue); - nd->mRotationKeys[i].mTime = nd->mPositionKeys[i].mTime = *it+i; + nd->mPositionKeys[i].mValue = frames[*it + i].vPositionXYZ; + MD5::ConvertQuaternion(frames[*it + i].vRotationQuat, nd->mRotationKeys[i].mValue); + nd->mRotationKeys[i].mTime = nd->mPositionKeys[i].mTime = *it + i; } } } diff --git a/code/MD5/MD5Loader.h b/code/MD5/MD5Loader.h index 196ffb69a..cfdd9ed0e 100644 --- a/code/MD5/MD5Loader.h +++ b/code/MD5/MD5Loader.h @@ -40,7 +40,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ---------------------------------------------------------------------- */ - /** @file MD5Loader.h * @brief Definition of the .MD5 importer class. * http://www.modwiki.net/wiki/MD5_(file_format) @@ -48,15 +47,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef AI_MD5LOADER_H_INCLUDED #define AI_MD5LOADER_H_INCLUDED -#include #include "MD5Parser.h" +#include #include struct aiNode; struct aiNodeAnim; -namespace Assimp { +namespace Assimp { class IOStream; using namespace Assimp::MD5; @@ -64,61 +63,53 @@ using namespace Assimp::MD5; // --------------------------------------------------------------------------- /** Importer class for the MD5 file format */ -class MD5Importer : public BaseImporter -{ +class MD5Importer : public BaseImporter { public: MD5Importer(); ~MD5Importer(); - -public: - // ------------------------------------------------------------------- /** 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; + bool CanRead(const std::string &pFile, IOSystem *pIOHandler, + bool checkSig) const; protected: - // ------------------------------------------------------------------- /** Return importer meta information. * See #BaseImporter::GetInfo for the details */ - const aiImporterDesc* GetInfo () const; + const aiImporterDesc *GetInfo() const; // ------------------------------------------------------------------- /** Called prior to ReadFile(). * The function is a request to the importer to update its configuration * basing on the Importer's configuration property list. */ - void SetupProperties(const Importer* pImp); + void SetupProperties(const Importer *pImp); // ------------------------------------------------------------------- /** Imports the given file into the given scene structure. * See BaseImporter::InternReadFile() for details */ - void InternReadFile( const std::string& pFile, aiScene* pScene, - IOSystem* pIOHandler); - -protected: - + void InternReadFile(const std::string &pFile, aiScene *pScene, + IOSystem *pIOHandler); // ------------------------------------------------------------------- /** Load a *.MD5MESH file. */ - void LoadMD5MeshFile (); + void LoadMD5MeshFile(); // ------------------------------------------------------------------- /** Load a *.MD5ANIM file. */ - void LoadMD5AnimFile (); + void LoadMD5AnimFile(); // ------------------------------------------------------------------- /** Load a *.MD5CAMERA file. */ - void LoadMD5CameraFile (); + void LoadMD5CameraFile(); // ------------------------------------------------------------------- /** Construct node hierarchy from a given MD5ANIM @@ -127,8 +118,8 @@ protected: * @param bones Input bones * @param node_anims Generated node animations */ - void AttachChilds_Anim(int iParentID,aiNode* piParent, - AnimBoneList& bones,const aiNodeAnim** node_anims); + void AttachChilds_Anim(int iParentID, aiNode *piParent, + AnimBoneList &bones, const aiNodeAnim **node_anims); // ------------------------------------------------------------------- /** Construct node hierarchy from a given MD5MESH @@ -136,13 +127,13 @@ protected: * @param piParent Parent node to attach to * @param bones Input bones */ - void AttachChilds_Mesh(int iParentID,aiNode* piParent,BoneList& bones); + void AttachChilds_Mesh(int iParentID, aiNode *piParent, BoneList &bones); // ------------------------------------------------------------------- /** Build unique vertex buffers from a given MD5ANIM * @param meshSrc Input data */ - void MakeDataUnique (MD5::MeshDesc& meshSrc); + void MakeDataUnique(MD5::MeshDesc &meshSrc); // ------------------------------------------------------------------- /** Load the contents of a specific file into memory and @@ -151,19 +142,18 @@ protected: * mBuffer is modified to point to this buffer. * @param pFile File stream to be read */ - void LoadFileIntoMemory (IOStream* pFile); - void UnloadFileFromMemory (); - + void LoadFileIntoMemory(IOStream *pFile); + void UnloadFileFromMemory(); /** IOSystem to be used to access files */ - IOSystem* mIOHandler; + IOSystem *mIOHandler; /** Path to the file, excluding the file extension but with the dot */ std::string mFile; /** Buffer to hold the loaded file */ - char* mBuffer; + char *mBuffer; /** Size of the file */ unsigned int fileSize; @@ -172,10 +162,7 @@ protected: unsigned int iLineNumber; /** Scene to be filled */ - aiScene* pScene; - - /** (Custom) I/O handler implementation */ - IOSystem* pIOHandler; + aiScene *pScene; /** true if a MD5MESH file has already been parsed */ bool bHadMD5Mesh; diff --git a/code/MDL/HalfLife/HL1MDLLoader.cpp b/code/MDL/HalfLife/HL1MDLLoader.cpp index c18528e59..82bf8fb0c 100644 --- a/code/MDL/HalfLife/HL1MDLLoader.cpp +++ b/code/MDL/HalfLife/HL1MDLLoader.cpp @@ -817,20 +817,20 @@ void HL1MDLLoader::read_meshes() { mesh_faces.reserve(num_faces); if (is_triangle_fan) { - for (int i = 0; i < num_faces; ++i) { + for (int faceIdx = 0; faceIdx < num_faces; ++faceIdx) { mesh_faces.push_back(HL1MeshFace{ tricmds[0], - tricmds[i + 1], - tricmds[i + 2] }); + tricmds[faceIdx + 1], + tricmds[faceIdx + 2] }); } } else { - for (int i = 0; i < num_faces; ++i) { + for (int faceIdx = 0; faceIdx < num_faces; ++faceIdx) { if (i & 1) { // Preserve winding order. mesh_faces.push_back(HL1MeshFace{ - tricmds[i + 1], - tricmds[i], - tricmds[i + 2] }); + tricmds[faceIdx + 1], + tricmds[faceIdx], + tricmds[faceIdx + 2] }); } else { mesh_faces.push_back(HL1MeshFace{ tricmds[i], @@ -1122,10 +1122,10 @@ void HL1MDLLoader::read_sequence_infos() { aiNode *blend_controller_node = blend_controllers_node->mChildren[j] = new aiNode(); blend_controller_node->mParent = blend_controllers_node; - aiMetadata *md = blend_controller_node->mMetaData = aiMetadata::Alloc(3); - md->Set(0, "Start", pseqdesc->blendstart[j]); - md->Set(1, "End", pseqdesc->blendend[j]); - md->Set(2, "MotionFlags", pseqdesc->blendtype[j]); + aiMetadata *metaData = blend_controller_node->mMetaData = aiMetadata::Alloc(3); + metaData->Set(0, "Start", pseqdesc->blendstart[j]); + metaData->Set(1, "End", pseqdesc->blendend[j]); + metaData->Set(2, "MotionFlags", pseqdesc->blendtype[j]); } } } @@ -1151,10 +1151,10 @@ void HL1MDLLoader::read_sequence_infos() { aiNode *pEvent = pEventsNode->mChildren[j] = new aiNode(); pEvent->mParent = pEventsNode; - aiMetadata *md = pEvent->mMetaData = aiMetadata::Alloc(3); - md->Set(0, "Frame", pevent->frame); - md->Set(1, "ScriptEvent", pevent->event); - md->Set(2, "Options", aiString(pevent->options)); + aiMetadata *metaData = pEvent->mMetaData = aiMetadata::Alloc(3); + metaData->Set(0, "Frame", pevent->frame); + metaData->Set(1, "ScriptEvent", pevent->event); + metaData->Set(2, "Options", aiString(pevent->options)); } } diff --git a/code/MDL/HalfLife/HL1MeshTrivert.h b/code/MDL/HalfLife/HL1MeshTrivert.h index b61765663..9e7c01504 100644 --- a/code/MDL/HalfLife/HL1MeshTrivert.h +++ b/code/MDL/HalfLife/HL1MeshTrivert.h @@ -56,27 +56,27 @@ namespace HalfLife { /* A class to help map model triverts to mesh triverts. */ struct HL1MeshTrivert { HL1MeshTrivert() : - vertindex(-1), - normindex(-1), - s(0), - t(0), - localindex(-1) { + vertindex(-1), + normindex(-1), + s(0), + t(0), + localindex(-1) { } HL1MeshTrivert(short vertindex, short normindex, short s, short t, short localindex) : - vertindex(vertindex), - normindex(normindex), - s(s), - t(t), - localindex() { + vertindex(vertindex), + normindex(normindex), + s(s), + t(t), + localindex(localindex) { } HL1MeshTrivert(const Trivert &a) : - vertindex(a.vertindex), - normindex(a.normindex), - s(a.s), - t(a.t), - localindex(-1) { + vertindex(a.vertindex), + normindex(a.normindex), + s(a.s), + t(a.t), + localindex(-1) { } inline bool operator==(const Trivert &a) const { diff --git a/code/MDL/MDLMaterialLoader.cpp b/code/MDL/MDLMaterialLoader.cpp index 38ff5bbb1..f6ff13d9b 100644 --- a/code/MDL/MDLMaterialLoader.cpp +++ b/code/MDL/MDLMaterialLoader.cpp @@ -68,7 +68,7 @@ static aiTexel* const bad_texel = reinterpret_cast(SIZE_MAX); void MDLImporter::SearchPalette(const unsigned char** pszColorMap) { // now try to find the color map in the current directory - IOStream* pcStream = pIOHandler->Open(configPalette,"rb"); + IOStream* pcStream = mIOHandler->Open(configPalette,"rb"); const unsigned char* szColorMap = (const unsigned char*)::g_aclrDefaultColorMap; if(pcStream) @@ -702,14 +702,13 @@ void MDLImporter::ParseSkinLump_3DGS_MDL7( // data structures in the aiScene instance if (pcNew && pScene->mNumTextures <= 999) { - // place this as diffuse texture - char szCurrent[5]; - ai_snprintf(szCurrent,5,"*%i",this->pScene->mNumTextures); + char current[5]; + ai_snprintf(current, 5, "*%i", this->pScene->mNumTextures); aiString szFile; - const size_t iLen = strlen((const char*)szCurrent); - ::memcpy(szFile.data,(const char*)szCurrent,iLen+1); + const size_t iLen = strlen((const char *)current); + ::memcpy(szFile.data, (const char *)current, iLen + 1); szFile.length = (ai_uint32)iLen; pcMatOut->AddProperty(&szFile,AI_MATKEY_TEXTURE_DIFFUSE(0)); diff --git a/code/MS3D/MS3DLoader.cpp b/code/MS3D/MS3DLoader.cpp index 5a29df2ee..9f0149c2b 100644 --- a/code/MS3D/MS3DLoader.cpp +++ b/code/MS3D/MS3DLoader.cpp @@ -261,19 +261,19 @@ void MS3DImporter::InternReadFile( const std::string& pFile, TempTriangle& t = triangles[i]; stream.IncPtr(2); - for (unsigned int i = 0; i < 3; ++i) { - t.indices[i] = stream.GetI2(); + for (unsigned int j = 0; j < 3; ++j) { + t.indices[j] = stream.GetI2(); } - for (unsigned int i = 0; i < 3; ++i) { - ReadVector(stream,t.normals[i]); + for (unsigned int j = 0; j < 3; ++j) { + ReadVector(stream,t.normals[j]); } - for (unsigned int i = 0; i < 3; ++i) { - stream >> (float&)(t.uv[i].x); // see note in ReadColor() + for (unsigned int j = 0; j < 3; ++j) { + stream >> (float&)(t.uv[j].x); // see note in ReadColor() } - for (unsigned int i = 0; i < 3; ++i) { - stream >> (float&)(t.uv[i].y); + for (unsigned int j = 0; j < 3; ++j) { + stream >> (float&)(t.uv[j].y); } t.sg = stream.GetI1(); @@ -296,8 +296,8 @@ void MS3DImporter::InternReadFile( const std::string& pFile, stream >> num; t.triangles.resize(num); - for (unsigned int i = 0; i < num; ++i) { - t.triangles[i] = stream.GetI2(); + for (unsigned int j = 0; j < num; ++j) { + t.triangles[j] = stream.GetI2(); } t.mat = stream.GetI1(); if (t.mat == UINT_MAX) { @@ -309,8 +309,8 @@ void MS3DImporter::InternReadFile( const std::string& pFile, stream >> mat; std::vector materials(mat); - for (unsigned int i = 0;i < mat; ++i) { - TempMaterial& t = materials[i]; + for (unsigned int j = 0;j < mat; ++j) { + TempMaterial& t = materials[j]; stream.CopyAndAdvance(t.name,32); t.name[32] = '\0'; @@ -338,8 +338,8 @@ void MS3DImporter::InternReadFile( const std::string& pFile, stream >> joint; std::vector joints(joint); - for(unsigned int i = 0; i < joint; ++i) { - TempJoint& j = joints[i]; + for(unsigned int ii = 0; ii < joint; ++ii) { + TempJoint& j = joints[ii]; stream.IncPtr(1); stream.CopyAndAdvance(j.name,32); @@ -494,17 +494,17 @@ void MS3DImporter::InternReadFile( const std::string& pFile, typedef std::map BoneSet; BoneSet mybones; - for (unsigned int i = 0,n = 0; i < m->mNumFaces; ++i) { - aiFace& f = m->mFaces[i]; - if (g.triangles[i]>triangles.size()) { + for (unsigned int j = 0,n = 0; j < m->mNumFaces; ++j) { + aiFace& f = m->mFaces[j]; + if (g.triangles[j]>triangles.size()) { throw DeadlyImportError("MS3D: Encountered invalid triangle index, file is malformed"); } TempTriangle& t = triangles[g.triangles[i]]; f.mIndices = new unsigned int[f.mNumIndices=3]; - for (unsigned int i = 0; i < 3; ++i,++n) { - if (t.indices[i]>vertices.size()) { + for (unsigned int k = 0; k < 3; ++k,++n) { + if (t.indices[k]>vertices.size()) { throw DeadlyImportError("MS3D: Encountered invalid vertex index, file is malformed"); } @@ -545,11 +545,11 @@ void MS3DImporter::InternReadFile( const std::string& pFile, } // .. and collect bone weights - for (unsigned int i = 0,n = 0; i < m->mNumFaces; ++i) { - TempTriangle& t = triangles[g.triangles[i]]; + for (unsigned int j = 0,n = 0; j < m->mNumFaces; ++j) { + TempTriangle& t = triangles[g.triangles[j]]; - for (unsigned int i = 0; i < 3; ++i,++n) { - const TempVertex& v = vertices[t.indices[i]]; + for (unsigned int k = 0; k < 3; ++k,++n) { + const TempVertex& v = vertices[t.indices[k]]; for(unsigned int a = 0; a < 4; ++a) { const unsigned int bone = v.bone_id[a]; if(bone==UINT_MAX){ diff --git a/code/NFF/NFFLoader.cpp b/code/NFF/NFFLoader.cpp index ca10f7a03..edb64a34f 100644 --- a/code/NFF/NFFLoader.cpp +++ b/code/NFF/NFFLoader.cpp @@ -43,23 +43,21 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /** @file Implementation of the STL importer class */ - #ifndef ASSIMP_BUILD_NO_NFF_IMPORTER // internal headers #include "NFFLoader.h" #include -#include -#include -#include #include -#include -#include -#include +#include +#include #include +#include +#include +#include +#include #include - using namespace Assimp; static const aiImporterDesc desc = { @@ -77,69 +75,63 @@ static const aiImporterDesc desc = { // ------------------------------------------------------------------------------------------------ // Constructor to be privately used by Importer -NFFImporter::NFFImporter() -{} +NFFImporter::NFFImporter() {} // ------------------------------------------------------------------------------------------------ // Destructor, private as well -NFFImporter::~NFFImporter() -{} +NFFImporter::~NFFImporter() {} // ------------------------------------------------------------------------------------------------ // Returns whether the class can handle the format of the given file. -bool NFFImporter::CanRead( const std::string& pFile, IOSystem* /*pIOHandler*/, bool /*checkSig*/) const -{ - return SimpleExtensionCheck(pFile,"nff","enff"); +bool NFFImporter::CanRead(const std::string &pFile, IOSystem * /*pIOHandler*/, bool /*checkSig*/) const { + return SimpleExtensionCheck(pFile, "nff", "enff"); } // ------------------------------------------------------------------------------------------------ // Get the list of all supported file extensions -const aiImporterDesc* NFFImporter::GetInfo () const -{ +const aiImporterDesc *NFFImporter::GetInfo() const { return &desc; } // ------------------------------------------------------------------------------------------------ #define AI_NFF_PARSE_FLOAT(f) \ - SkipSpaces(&sz); \ - if (!::IsLineEnd(*sz))sz = fast_atoreal_move(sz, (float&)f); + SkipSpaces(&sz); \ + if (!::IsLineEnd(*sz)) sz = fast_atoreal_move(sz, (float &)f); // ------------------------------------------------------------------------------------------------ #define AI_NFF_PARSE_TRIPLE(v) \ - AI_NFF_PARSE_FLOAT(v[0]) \ - AI_NFF_PARSE_FLOAT(v[1]) \ + AI_NFF_PARSE_FLOAT(v[0]) \ + AI_NFF_PARSE_FLOAT(v[1]) \ AI_NFF_PARSE_FLOAT(v[2]) // ------------------------------------------------------------------------------------------------ -#define AI_NFF_PARSE_SHAPE_INFORMATION() \ - aiVector3D center, radius(1.0f,get_qnan(),get_qnan()); \ - AI_NFF_PARSE_TRIPLE(center); \ - AI_NFF_PARSE_TRIPLE(radius); \ - if (is_qnan(radius.z))radius.z = radius.x; \ - if (is_qnan(radius.y))radius.y = radius.x; \ - currentMesh.radius = radius; \ - currentMesh.center = center; +#define AI_NFF_PARSE_SHAPE_INFORMATION() \ + aiVector3D center, radius(1.0f, get_qnan(), get_qnan()); \ + AI_NFF_PARSE_TRIPLE(center); \ + AI_NFF_PARSE_TRIPLE(radius); \ + if (is_qnan(radius.z)) radius.z = radius.x; \ + if (is_qnan(radius.y)) radius.y = radius.x; \ + curMesh.radius = radius; \ + curMesh.center = center; // ------------------------------------------------------------------------------------------------ -#define AI_NFF2_GET_NEXT_TOKEN() \ - do \ - { \ - if (!GetNextLine(buffer,line)) \ - {ASSIMP_LOG_WARN("NFF2: Unexpected EOF, can't read next token");break;} \ - SkipSpaces(line,&sz); \ - } \ - while(IsLineEnd(*sz)) - +#define AI_NFF2_GET_NEXT_TOKEN() \ + do { \ + if (!GetNextLine(buffer, line)) { \ + ASSIMP_LOG_WARN("NFF2: Unexpected EOF, can't read next token"); \ + break; \ + } \ + SkipSpaces(line, &sz); \ + } while (IsLineEnd(*sz)) // ------------------------------------------------------------------------------------------------ // Loads the material table for the NFF2 file format from an external file -void NFFImporter::LoadNFF2MaterialTable(std::vector& output, - const std::string& path, IOSystem* pIOHandler) -{ - std::unique_ptr file( pIOHandler->Open( path, "rb")); +void NFFImporter::LoadNFF2MaterialTable(std::vector &output, + const std::string &path, IOSystem *pIOHandler) { + std::unique_ptr file(pIOHandler->Open(path, "rb")); // Check whether we can read from the file - if( !file.get()) { + if (!file.get()) { ASSIMP_LOG_ERROR("NFF2: Unable to open material library " + path + "."); return; } @@ -149,83 +141,65 @@ void NFFImporter::LoadNFF2MaterialTable(std::vector& output, // allocate storage and copy the contents of the file to a memory buffer // (terminate it with zero) - std::vector mBuffer2(m+1); - TextFileToBuffer(file.get(),mBuffer2); - const char* buffer = &mBuffer2[0]; + std::vector mBuffer2(m + 1); + TextFileToBuffer(file.get(), mBuffer2); + const char *buffer = &mBuffer2[0]; // First of all: remove all comments from the file - CommentRemover::RemoveLineComments("//",&mBuffer2[0]); + CommentRemover::RemoveLineComments("//", &mBuffer2[0]); // The file should start with the magic sequence "mat" - if (!TokenMatch(buffer,"mat",3)) { + if (!TokenMatch(buffer, "mat", 3)) { ASSIMP_LOG_ERROR_F("NFF2: Not a valid material library ", path, "."); return; } - ShadingInfo* curShader = NULL; + ShadingInfo *curShader = NULL; // No read the file line per line char line[4096]; - const char* sz; - while (GetNextLine(buffer,line)) - { - SkipSpaces(line,&sz); + const char *sz; + while (GetNextLine(buffer, line)) { + SkipSpaces(line, &sz); // 'version' defines the version of the file format - if (TokenMatch(sz,"version",7)) - { + if (TokenMatch(sz, "version", 7)) { ASSIMP_LOG_INFO_F("NFF (Sense8) material library file format: ", std::string(sz)); } // 'matdef' starts a new material in the file - else if (TokenMatch(sz,"matdef",6)) - { + else if (TokenMatch(sz, "matdef", 6)) { // add a new material to the list - output.push_back( ShadingInfo() ); - curShader = & output.back(); + output.push_back(ShadingInfo()); + curShader = &output.back(); // parse the name of the material - } - else if (!TokenMatch(sz,"valid",5)) - { + } else if (!TokenMatch(sz, "valid", 5)) { // check whether we have an active material at the moment - if (!IsLineEnd(*sz)) - { - if (!curShader) - { + if (!IsLineEnd(*sz)) { + if (!curShader) { ASSIMP_LOG_ERROR_F("NFF2 material library: Found element ", sz, "but there is no active material"); continue; } - } - else continue; + } else + continue; // now read the material property and determine its type aiColor3D c; - if (TokenMatch(sz,"ambient",7)) - { + if (TokenMatch(sz, "ambient", 7)) { AI_NFF_PARSE_TRIPLE(c); curShader->ambient = c; - } - else if (TokenMatch(sz,"diffuse",7) || TokenMatch(sz,"ambientdiffuse",14) /* correct? */) - { + } else if (TokenMatch(sz, "diffuse", 7) || TokenMatch(sz, "ambientdiffuse", 14) /* correct? */) { AI_NFF_PARSE_TRIPLE(c); curShader->diffuse = curShader->ambient = c; - } - else if (TokenMatch(sz,"specular",8)) - { + } else if (TokenMatch(sz, "specular", 8)) { AI_NFF_PARSE_TRIPLE(c); curShader->specular = c; - } - else if (TokenMatch(sz,"emission",8)) - { + } else if (TokenMatch(sz, "emission", 8)) { AI_NFF_PARSE_TRIPLE(c); curShader->emissive = c; - } - else if (TokenMatch(sz,"shininess",9)) - { + } else if (TokenMatch(sz, "shininess", 9)) { AI_NFF_PARSE_FLOAT(curShader->shininess); - } - else if (TokenMatch(sz,"opacity",7)) - { + } else if (TokenMatch(sz, "opacity", 7)) { AI_NFF_PARSE_FLOAT(curShader->opacity); } } @@ -234,20 +208,19 @@ void NFFImporter::LoadNFF2MaterialTable(std::vector& output, // ------------------------------------------------------------------------------------------------ // Imports the given file into the given scene structure. -void NFFImporter::InternReadFile( const std::string& pFile, - aiScene* pScene, IOSystem* pIOHandler) -{ - std::unique_ptr file( pIOHandler->Open( pFile, "rb")); +void NFFImporter::InternReadFile(const std::string &pFile, + aiScene *pScene, IOSystem *pIOHandler) { + std::unique_ptr file(pIOHandler->Open(pFile, "rb")); // Check whether we can read from the file - if( !file.get()) - throw DeadlyImportError( "Failed to open NFF file " + pFile + "."); + if (!file.get()) + throw DeadlyImportError("Failed to open NFF file " + pFile + "."); // allocate storage and copy the contents of the file to a memory buffer // (terminate it with zero) std::vector mBuffer2; - TextFileToBuffer(file.get(),mBuffer2); - const char* buffer = &mBuffer2[0]; + TextFileToBuffer(file.get(), mBuffer2); + const char *buffer = &mBuffer2[0]; // mesh arrays - separate here to make the handling of the pointers below easier. std::vector meshes; @@ -256,18 +229,18 @@ void NFFImporter::InternReadFile( const std::string& pFile, std::vector meshesLocked; char line[4096]; - const char* sz; + const char *sz; // camera parameters - aiVector3D camPos, camUp(0.f,1.f,0.f), camLookAt(0.f,0.f,1.f); + aiVector3D camPos, camUp(0.f, 1.f, 0.f), camLookAt(0.f, 0.f, 1.f); float angle = 45.f; aiVector2D resolution; bool hasCam = false; - MeshInfo* currentMeshWithNormals = NULL; - MeshInfo* currentMesh = NULL; - MeshInfo* currentMeshWithUVCoords = NULL; + MeshInfo *currentMeshWithNormals = NULL; + MeshInfo *currentMesh = NULL; + MeshInfo *currentMeshWithUVCoords = NULL; ShadingInfo s; // current material info @@ -275,24 +248,23 @@ void NFFImporter::InternReadFile( const std::string& pFile, unsigned int iTesselation = 4; // some temporary variables we need to parse the file - unsigned int sphere = 0, - cylinder = 0, - cone = 0, - numNamed = 0, - dodecahedron = 0, - octahedron = 0, - tetrahedron = 0, - hexahedron = 0; + unsigned int sphere = 0, + cylinder = 0, + cone = 0, + numNamed = 0, + dodecahedron = 0, + octahedron = 0, + tetrahedron = 0, + hexahedron = 0; // lights imported from the file std::vector lights; // check whether this is the NFF2 file format - if (TokenMatch(buffer,"nff",3)) - { + if (TokenMatch(buffer, "nff", 3)) { const float qnan = get_qnan(); - const aiColor4D cQNAN = aiColor4D (qnan,0.f,0.f,1.f); - const aiVector3D vQNAN = aiVector3D(qnan,0.f,0.f); + const aiColor4D cQNAN = aiColor4D(qnan, 0.f, 0.f, 1.f); + const aiVector3D vQNAN = aiVector3D(qnan, 0.f, 0.f); // another NFF file format ... just a raw parser has been implemented // no support for further details, I don't think it is worth the effort @@ -300,132 +272,119 @@ void NFFImporter::InternReadFile( const std::string& pFile, // http://www.netghost.narod.ru/gff/graphics/summary/sense8.htm // First of all: remove all comments from the file - CommentRemover::RemoveLineComments("//",&mBuffer2[0]); + CommentRemover::RemoveLineComments("//", &mBuffer2[0]); - while (GetNextLine(buffer,line)) - { - SkipSpaces(line,&sz); - if (TokenMatch(sz,"version",7)) - { - ASSIMP_LOG_INFO_F("NFF (Sense8) file format: ", sz ); - } - else if (TokenMatch(sz,"viewpos",7)) - { + while (GetNextLine(buffer, line)) { + SkipSpaces(line, &sz); + if (TokenMatch(sz, "version", 7)) { + ASSIMP_LOG_INFO_F("NFF (Sense8) file format: ", sz); + } else if (TokenMatch(sz, "viewpos", 7)) { AI_NFF_PARSE_TRIPLE(camPos); hasCam = true; - } - else if (TokenMatch(sz,"viewdir",7)) - { + } else if (TokenMatch(sz, "viewdir", 7)) { AI_NFF_PARSE_TRIPLE(camLookAt); hasCam = true; } // This starts a new object section - else if (!IsSpaceOrNewLine(*sz)) - { + else if (!IsSpaceOrNewLine(*sz)) { unsigned int subMeshIdx = 0; // read the name of the object, skip all spaces // at the end of it. - const char* sz3 = sz; - while (!IsSpaceOrNewLine(*sz))++sz; - std::string objectName = std::string(sz3,(unsigned int)(sz-sz3)); + const char *sz3 = sz; + while (!IsSpaceOrNewLine(*sz)) + ++sz; + std::string objectName = std::string(sz3, (unsigned int)(sz - sz3)); const unsigned int objStart = (unsigned int)meshes.size(); // There could be a material table in a separate file std::vector materialTable; - while (true) - { + while (true) { AI_NFF2_GET_NEXT_TOKEN(); // material table - an external file - if (TokenMatch(sz,"mtable",6)) - { + if (TokenMatch(sz, "mtable", 6)) { SkipSpaces(&sz); sz3 = sz; - while (!IsSpaceOrNewLine(*sz))++sz; - const unsigned int diff = (unsigned int)(sz-sz3); - if (!diff)ASSIMP_LOG_WARN("NFF2: Found empty mtable token"); - else - { + while (!IsSpaceOrNewLine(*sz)) + ++sz; + const unsigned int diff = (unsigned int)(sz - sz3); + if (!diff) + ASSIMP_LOG_WARN("NFF2: Found empty mtable token"); + else { // The material table has the file extension .mat. // If it is not there, we need to append it - std::string path = std::string(sz3,diff); - if(std::string::npos == path.find_last_of(".mat")) - { + std::string path = std::string(sz3, diff); + if (std::string::npos == path.find_last_of(".mat")) { path.append(".mat"); } // Now extract the working directory from the path to // this file and append the material library filename // to it. - std::string::size_type s; - if ((std::string::npos == (s = path.find_last_of('\\')) || !s) && - (std::string::npos == (s = path.find_last_of('/')) || !s) ) - { - s = pFile.find_last_of('\\'); - if (std::string::npos == s)s = pFile.find_last_of('/'); - if (std::string::npos != s) - { - path = pFile.substr(0,s+1) + path; + std::string::size_type sepPos; + if ((std::string::npos == (sepPos = path.find_last_of('\\')) || !sepPos) && + (std::string::npos == (sepPos = path.find_last_of('/')) || !sepPos)) { + sepPos = pFile.find_last_of('\\'); + if (std::string::npos == sepPos) { + sepPos = pFile.find_last_of('/'); + } + if (std::string::npos != sepPos) { + path = pFile.substr(0, sepPos + 1) + path; } } - LoadNFF2MaterialTable(materialTable,path,pIOHandler); + LoadNFF2MaterialTable(materialTable, path, pIOHandler); } - } - else break; + } else + break; } // read the numbr of vertices - unsigned int num = ::strtoul10(sz,&sz); + unsigned int num = ::strtoul10(sz, &sz); // temporary storage - std::vector tempColors; - std::vector tempPositions,tempTextureCoords,tempNormals; + std::vector tempColors; + std::vector tempPositions, tempTextureCoords, tempNormals; - bool hasNormals = false,hasUVs = false,hasColor = false; + bool hasNormals = false, hasUVs = false, hasColor = false; - tempPositions.reserve (num); - tempColors.reserve (num); - tempNormals.reserve (num); - tempTextureCoords.reserve (num); - for (unsigned int i = 0; i < num; ++i) - { + tempPositions.reserve(num); + tempColors.reserve(num); + tempNormals.reserve(num); + tempTextureCoords.reserve(num); + for (unsigned int i = 0; i < num; ++i) { AI_NFF2_GET_NEXT_TOKEN(); aiVector3D v; AI_NFF_PARSE_TRIPLE(v); tempPositions.push_back(v); // parse all other attributes in the line - while (true) - { + while (true) { SkipSpaces(&sz); - if (IsLineEnd(*sz))break; + if (IsLineEnd(*sz)) break; // color definition - if (TokenMatch(sz,"0x",2)) - { + if (TokenMatch(sz, "0x", 2)) { hasColor = true; - unsigned int numIdx = ::strtoul16(sz,&sz); + unsigned int numIdx = ::strtoul16(sz, &sz); aiColor4D clr; clr.a = 1.f; // 0xRRGGBB clr.r = ((numIdx >> 16u) & 0xff) / 255.f; - clr.g = ((numIdx >> 8u) & 0xff) / 255.f; - clr.b = ((numIdx) & 0xff) / 255.f; + clr.g = ((numIdx >> 8u) & 0xff) / 255.f; + clr.b = ((numIdx)&0xff) / 255.f; tempColors.push_back(clr); } // normal vector - else if (TokenMatch(sz,"norm",4)) - { + else if (TokenMatch(sz, "norm", 4)) { hasNormals = true; AI_NFF_PARSE_TRIPLE(v); tempNormals.push_back(v); } // UV coordinate - else if (TokenMatch(sz,"uv",2)) - { + else if (TokenMatch(sz, "uv", 2)) { hasUVs = true; AI_NFF_PARSE_FLOAT(v.x); AI_NFF_PARSE_FLOAT(v.y); @@ -446,32 +405,28 @@ void NFFImporter::InternReadFile( const std::string& pFile, } AI_NFF2_GET_NEXT_TOKEN(); - if (!num)throw DeadlyImportError("NFF2: There are zero vertices"); - num = ::strtoul10(sz,&sz); + if (!num) throw DeadlyImportError("NFF2: There are zero vertices"); + num = ::strtoul10(sz, &sz); std::vector tempIdx; tempIdx.reserve(10); - for (unsigned int i = 0; i < num; ++i) - { + for (unsigned int i = 0; i < num; ++i) { AI_NFF2_GET_NEXT_TOKEN(); - SkipSpaces(line,&sz); - unsigned int numIdx = ::strtoul10(sz,&sz); + SkipSpaces(line, &sz); + unsigned int numIdx = ::strtoul10(sz, &sz); // read all faces indices - if (numIdx) - { + if (numIdx) { // mesh.faces.push_back(numIdx); // tempIdx.erase(tempIdx.begin(),tempIdx.end()); tempIdx.resize(numIdx); - for (unsigned int a = 0; a < numIdx;++a) - { - SkipSpaces(sz,&sz); - unsigned int m = ::strtoul10(sz,&sz); - if (m >= (unsigned int)tempPositions.size()) - { + for (unsigned int a = 0; a < numIdx; ++a) { + SkipSpaces(sz, &sz); + unsigned int m = ::strtoul10(sz, &sz); + if (m >= (unsigned int)tempPositions.size()) { ASSIMP_LOG_ERROR("NFF2: Vertex index overflow"); - m= 0; + m = 0; } // mesh.vertices.push_back (tempPositions[idx]); tempIdx[a] = m; @@ -483,34 +438,30 @@ void NFFImporter::InternReadFile( const std::string& pFile, unsigned int matIdx = 0; // white material color - we have vertex colors - shader.color = aiColor3D(1.f,1.f,1.f); - aiColor4D c = aiColor4D(1.f,1.f,1.f,1.f); - while (true) - { - SkipSpaces(sz,&sz); - if(IsLineEnd(*sz))break; + shader.color = aiColor3D(1.f, 1.f, 1.f); + aiColor4D c = aiColor4D(1.f, 1.f, 1.f, 1.f); + while (true) { + SkipSpaces(sz, &sz); + if (IsLineEnd(*sz)) break; // per-polygon colors - if (TokenMatch(sz,"0x",2)) - { + if (TokenMatch(sz, "0x", 2)) { hasColor = true; - const char* sz2 = sz; - numIdx = ::strtoul16(sz,&sz); - const unsigned int diff = (unsigned int)(sz-sz2); + const char *sz2 = sz; + numIdx = ::strtoul16(sz, &sz); + const unsigned int diff = (unsigned int)(sz - sz2); // 0xRRGGBB - if (diff > 3) - { + if (diff > 3) { c.r = ((numIdx >> 16u) & 0xff) / 255.f; - c.g = ((numIdx >> 8u) & 0xff) / 255.f; - c.b = ((numIdx) & 0xff) / 255.f; + c.g = ((numIdx >> 8u) & 0xff) / 255.f; + c.b = ((numIdx)&0xff) / 255.f; } // 0xRGB - else - { + else { c.r = ((numIdx >> 8u) & 0xf) / 16.f; c.g = ((numIdx >> 4u) & 0xf) / 16.f; - c.b = ((numIdx) & 0xf) / 16.f; + c.b = ((numIdx)&0xf) / 16.f; } } // TODO - implement texture mapping here @@ -534,81 +485,73 @@ void NFFImporter::InternReadFile( const std::string& pFile, #endif // texture file name for this polygon + mapping information - else if ('_' == sz[0]) - { + else if ('_' == sz[0]) { // get mapping information - switch (sz[1]) - { - case 'v': - case 'V': + switch (sz[1]) { + case 'v': + case 'V': - shader.shaded = false; - break; + shader.shaded = false; + break; - case 't': - case 'T': - case 'u': - case 'U': + case 't': + case 'T': + case 'u': + case 'U': - ASSIMP_LOG_WARN("Unsupported NFF2 texture attribute: trans"); + ASSIMP_LOG_WARN("Unsupported NFF2 texture attribute: trans"); }; - if (!sz[1] || '_' != sz[2]) - { + if (!sz[1] || '_' != sz[2]) { ASSIMP_LOG_WARN("NFF2: Expected underscore after texture attributes"); continue; } - const char* sz2 = sz+3; - while (!IsSpaceOrNewLine( *sz ))++sz; - const unsigned int diff = (unsigned int)(sz-sz2); - if (diff)shader.texFile = std::string(sz2,diff); + const char *sz2 = sz + 3; + while (!IsSpaceOrNewLine(*sz)) + ++sz; + const unsigned int diff = (unsigned int)(sz - sz2); + if (diff) shader.texFile = std::string(sz2, diff); } // Two-sided material? - else if (TokenMatch(sz,"both",4)) - { + else if (TokenMatch(sz, "both", 4)) { shader.twoSided = true; } // Material ID? - else if (!materialTable.empty() && TokenMatch(sz,"matid",5)) - { + else if (!materialTable.empty() && TokenMatch(sz, "matid", 5)) { SkipSpaces(&sz); - matIdx = ::strtoul10(sz,&sz); - if (matIdx >= materialTable.size()) - { + matIdx = ::strtoul10(sz, &sz); + if (matIdx >= materialTable.size()) { ASSIMP_LOG_ERROR("NFF2: Material index overflow."); matIdx = 0; } // now combine our current shader with the shader we // read from the material table. - ShadingInfo& mat = materialTable[matIdx]; - shader.ambient = mat.ambient; - shader.diffuse = mat.diffuse; - shader.emissive = mat.emissive; - shader.opacity = mat.opacity; - shader.specular = mat.specular; + ShadingInfo &mat = materialTable[matIdx]; + shader.ambient = mat.ambient; + shader.diffuse = mat.diffuse; + shader.emissive = mat.emissive; + shader.opacity = mat.opacity; + shader.specular = mat.specular; shader.shininess = mat.shininess; - } - else SkipToken(sz); + } else + SkipToken(sz); } // search the list of all shaders we have for this object whether // there is an identical one. In this case, we append our mesh // data to it. - MeshInfo* mesh = NULL; + MeshInfo *mesh = NULL; for (std::vector::iterator it = meshes.begin() + objStart, end = meshes.end(); - it != end; ++it) - { - if ((*it).shader == shader && (*it).matIndex == matIdx) - { + it != end; ++it) { + if ((*it).shader == shader && (*it).matIndex == matIdx) { // we have one, we can append our data to it mesh = &(*it); } } - if (!mesh) - { - meshes.push_back(MeshInfo(PatchType_Simple,false)); + if (!mesh) { + meshes.push_back(MeshInfo(PatchType_Simple, false)); mesh = &meshes.back(); mesh->matIndex = matIdx; @@ -616,10 +559,9 @@ void NFFImporter::InternReadFile( const std::string& pFile, // an unique name to it to make sure the scene will // pass the validation step for the moment. // TODO: fix naming of objects in the scenegraph later - if (objectName.length()) - { - ::strcpy(mesh->name,objectName.c_str()); - ASSIMP_itoa10(&mesh->name[objectName.length()],30,subMeshIdx++); + if (objectName.length()) { + ::strcpy(mesh->name, objectName.c_str()); + ASSIMP_itoa10(&mesh->name[objectName.length()], 30, subMeshIdx++); } // copy the shader to the mesh. @@ -627,63 +569,53 @@ void NFFImporter::InternReadFile( const std::string& pFile, } // fill the mesh with data - if (!tempIdx.empty()) - { + if (!tempIdx.empty()) { mesh->faces.push_back((unsigned int)tempIdx.size()); for (std::vector::const_iterator it = tempIdx.begin(), end = tempIdx.end(); - it != end;++it) - { + it != end; ++it) { unsigned int m = *it; // copy colors -vertex color specifications override polygon color specifications - if (hasColor) - { - const aiColor4D& clr = tempColors[m]; - mesh->colors.push_back((is_qnan( clr.r ) ? c : clr)); + if (hasColor) { + const aiColor4D &clr = tempColors[m]; + mesh->colors.push_back((is_qnan(clr.r) ? c : clr)); } // positions should always be there - mesh->vertices.push_back (tempPositions[m]); + mesh->vertices.push_back(tempPositions[m]); // copy normal vectors if (hasNormals) - mesh->normals.push_back (tempNormals[m]); + mesh->normals.push_back(tempNormals[m]); // copy texture coordinates if (hasUVs) - mesh->uvs.push_back (tempTextureCoords[m]); + mesh->uvs.push_back(tempTextureCoords[m]); } } } - if (!num)throw DeadlyImportError("NFF2: There are zero faces"); + if (!num) throw DeadlyImportError("NFF2: There are zero faces"); } } camLookAt = camLookAt + camPos; - } - else // "Normal" Neutral file format that is quite more common + } else // "Normal" Neutral file format that is quite more common { - while (GetNextLine(buffer,line)) - { + while (GetNextLine(buffer, line)) { sz = line; - if ('p' == line[0] || TokenMatch(sz,"tpp",3)) - { - MeshInfo* out = NULL; + if ('p' == line[0] || TokenMatch(sz, "tpp", 3)) { + MeshInfo *out = NULL; // 'tpp' - texture polygon patch primitive - if ('t' == line[0]) - { + if ('t' == line[0]) { currentMeshWithUVCoords = NULL; - for (auto &mesh : meshesWithUVCoords) - { - if (mesh.shader == s) - { + for (auto &mesh : meshesWithUVCoords) { + if (mesh.shader == s) { currentMeshWithUVCoords = &mesh; break; } } - if (!currentMeshWithUVCoords) - { + if (!currentMeshWithUVCoords) { meshesWithUVCoords.push_back(MeshInfo(PatchType_UVAndNormals)); currentMeshWithUVCoords = &meshesWithUVCoords.back(); currentMeshWithUVCoords->shader = s; @@ -691,103 +623,89 @@ void NFFImporter::InternReadFile( const std::string& pFile, out = currentMeshWithUVCoords; } // 'pp' - polygon patch primitive - else if ('p' == line[1]) - { + else if ('p' == line[1]) { currentMeshWithNormals = NULL; - for (auto &mesh : meshesWithNormals) - { - if (mesh.shader == s) - { + for (auto &mesh : meshesWithNormals) { + if (mesh.shader == s) { currentMeshWithNormals = &mesh; break; } } - if (!currentMeshWithNormals) - { + if (!currentMeshWithNormals) { meshesWithNormals.push_back(MeshInfo(PatchType_Normals)); currentMeshWithNormals = &meshesWithNormals.back(); currentMeshWithNormals->shader = s; } - sz = &line[2];out = currentMeshWithNormals; + sz = &line[2]; + out = currentMeshWithNormals; } // 'p' - polygon primitive - else - { + else { currentMesh = NULL; - for (auto &mesh : meshes) - { - if (mesh.shader == s) - { + for (auto &mesh : meshes) { + if (mesh.shader == s) { currentMesh = &mesh; break; } } - if (!currentMesh) - { + if (!currentMesh) { meshes.push_back(MeshInfo(PatchType_Simple)); currentMesh = &meshes.back(); currentMesh->shader = s; } - sz = &line[1];out = currentMesh; + sz = &line[1]; + out = currentMesh; } - SkipSpaces(sz,&sz); + SkipSpaces(sz, &sz); unsigned int m = strtoul10(sz); // ---- flip the face order - out->vertices.resize(out->vertices.size()+m); - if (out != currentMesh) - { + out->vertices.resize(out->vertices.size() + m); + if (out != currentMesh) { out->normals.resize(out->vertices.size()); } - if (out == currentMeshWithUVCoords) - { + if (out == currentMeshWithUVCoords) { out->uvs.resize(out->vertices.size()); } - for (unsigned int n = 0; n < m;++n) - { - if(!GetNextLine(buffer,line)) - { + for (unsigned int n = 0; n < m; ++n) { + if (!GetNextLine(buffer, line)) { ASSIMP_LOG_ERROR("NFF: Unexpected EOF was encountered. Patch definition incomplete"); continue; } - aiVector3D v; sz = &line[0]; + aiVector3D v; + sz = &line[0]; AI_NFF_PARSE_TRIPLE(v); - out->vertices[out->vertices.size()-n-1] = v; + out->vertices[out->vertices.size() - n - 1] = v; - if (out != currentMesh) - { + if (out != currentMesh) { AI_NFF_PARSE_TRIPLE(v); - out->normals[out->vertices.size()-n-1] = v; + out->normals[out->vertices.size() - n - 1] = v; } - if (out == currentMeshWithUVCoords) - { + if (out == currentMeshWithUVCoords) { // FIX: in one test file this wraps over multiple lines SkipSpaces(&sz); - if (IsLineEnd(*sz)) - { - GetNextLine(buffer,line); + if (IsLineEnd(*sz)) { + GetNextLine(buffer, line); sz = line; } AI_NFF_PARSE_FLOAT(v.x); SkipSpaces(&sz); - if (IsLineEnd(*sz)) - { - GetNextLine(buffer,line); + if (IsLineEnd(*sz)) { + GetNextLine(buffer, line); sz = line; } AI_NFF_PARSE_FLOAT(v.y); v.y = 1.f - v.y; - out->uvs[out->vertices.size()-n-1] = v; + out->uvs[out->vertices.size() - n - 1] = v; } } out->faces.push_back(m); } // 'f' - shading information block - else if (TokenMatch(sz,"f",1)) - { + else if (TokenMatch(sz, "f", 1)) { float d; // read the RGB colors @@ -802,158 +720,147 @@ void NFFImporter::InternReadFile( const std::string& pFile, // NFF2 uses full colors here so we need to use them too // although NFF uses simple scaling factors - s.diffuse.g = s.diffuse.b = s.diffuse.r; + s.diffuse.g = s.diffuse.b = s.diffuse.r; s.specular.g = s.specular.b = s.specular.r; // if the next one is NOT a number we assume it is a texture file name // this feature is used by some NFF files on the internet and it has // been implemented as it can be really useful SkipSpaces(&sz); - if (!IsNumeric(*sz)) - { + if (!IsNumeric(*sz)) { // TODO: Support full file names with spaces and quotation marks ... - const char* p = sz; - while (!IsSpaceOrNewLine( *sz ))++sz; + const char *p = sz; + while (!IsSpaceOrNewLine(*sz)) + ++sz; - unsigned int diff = (unsigned int)(sz-p); - if (diff) - { - s.texFile = std::string(p,diff); + unsigned int diff = (unsigned int)(sz - p); + if (diff) { + s.texFile = std::string(p, diff); } - } - else - { + } else { AI_NFF_PARSE_FLOAT(s.ambient); // optional } } // 'shader' - other way to specify a texture - else if (TokenMatch(sz,"shader",6)) - { + else if (TokenMatch(sz, "shader", 6)) { SkipSpaces(&sz); - const char* old = sz; - while (!IsSpaceOrNewLine(*sz))++sz; + const char *old = sz; + while (!IsSpaceOrNewLine(*sz)) + ++sz; s.texFile = std::string(old, (uintptr_t)sz - (uintptr_t)old); } // 'l' - light source - else if (TokenMatch(sz,"l",1)) - { + else if (TokenMatch(sz, "l", 1)) { lights.push_back(Light()); - Light& light = lights.back(); + Light &light = lights.back(); AI_NFF_PARSE_TRIPLE(light.position); - AI_NFF_PARSE_FLOAT (light.intensity); + AI_NFF_PARSE_FLOAT(light.intensity); AI_NFF_PARSE_TRIPLE(light.color); } // 's' - sphere - else if (TokenMatch(sz,"s",1)) - { - meshesLocked.push_back(MeshInfo(PatchType_Simple,true)); - MeshInfo& currentMesh = meshesLocked.back(); - currentMesh.shader = s; - currentMesh.shader.mapping = aiTextureMapping_SPHERE; + else if (TokenMatch(sz, "s", 1)) { + meshesLocked.push_back(MeshInfo(PatchType_Simple, true)); + MeshInfo &curMesh = meshesLocked.back(); + curMesh.shader = s; + curMesh.shader.mapping = aiTextureMapping_SPHERE; AI_NFF_PARSE_SHAPE_INFORMATION(); // we don't need scaling or translation here - we do it in the node's transform - StandardShapes::MakeSphere(iTesselation, currentMesh.vertices); - currentMesh.faces.resize(currentMesh.vertices.size()/3,3); + StandardShapes::MakeSphere(iTesselation, curMesh.vertices); + curMesh.faces.resize(curMesh.vertices.size() / 3, 3); // generate a name for the mesh - ::ai_snprintf(currentMesh.name,128,"sphere_%i",sphere++); + ::ai_snprintf(curMesh.name, MeshInfo::MaxNameLen, "sphere_%i", sphere++); } // 'dod' - dodecahedron - else if (TokenMatch(sz,"dod",3)) - { - meshesLocked.push_back(MeshInfo(PatchType_Simple,true)); - MeshInfo& currentMesh = meshesLocked.back(); - currentMesh.shader = s; - currentMesh.shader.mapping = aiTextureMapping_SPHERE; + else if (TokenMatch(sz, "dod", 3)) { + meshesLocked.push_back(MeshInfo(PatchType_Simple, true)); + MeshInfo &curMesh = meshesLocked.back(); + curMesh.shader = s; + curMesh.shader.mapping = aiTextureMapping_SPHERE; AI_NFF_PARSE_SHAPE_INFORMATION(); // we don't need scaling or translation here - we do it in the node's transform - StandardShapes::MakeDodecahedron(currentMesh.vertices); - currentMesh.faces.resize(currentMesh.vertices.size()/3,3); + StandardShapes::MakeDodecahedron(curMesh.vertices); + curMesh.faces.resize(curMesh.vertices.size() / 3, 3); // generate a name for the mesh - ::ai_snprintf(currentMesh.name,128,"dodecahedron_%i",dodecahedron++); + ::ai_snprintf(curMesh.name, 128, "dodecahedron_%i", dodecahedron++); } // 'oct' - octahedron - else if (TokenMatch(sz,"oct",3)) - { - meshesLocked.push_back(MeshInfo(PatchType_Simple,true)); - MeshInfo& currentMesh = meshesLocked.back(); - currentMesh.shader = s; - currentMesh.shader.mapping = aiTextureMapping_SPHERE; + else if (TokenMatch(sz, "oct", 3)) { + meshesLocked.push_back(MeshInfo(PatchType_Simple, true)); + MeshInfo &curMesh = meshesLocked.back(); + curMesh.shader = s; + curMesh.shader.mapping = aiTextureMapping_SPHERE; AI_NFF_PARSE_SHAPE_INFORMATION(); // we don't need scaling or translation here - we do it in the node's transform - StandardShapes::MakeOctahedron(currentMesh.vertices); - currentMesh.faces.resize(currentMesh.vertices.size()/3,3); + StandardShapes::MakeOctahedron(curMesh.vertices); + curMesh.faces.resize(curMesh.vertices.size() / 3, 3); // generate a name for the mesh - ::ai_snprintf(currentMesh.name,128,"octahedron_%i",octahedron++); + ::ai_snprintf(curMesh.name, MeshInfo::MaxNameLen, "octahedron_%i", octahedron++); } // 'tet' - tetrahedron - else if (TokenMatch(sz,"tet",3)) - { - meshesLocked.push_back(MeshInfo(PatchType_Simple,true)); - MeshInfo& currentMesh = meshesLocked.back(); - currentMesh.shader = s; - currentMesh.shader.mapping = aiTextureMapping_SPHERE; + else if (TokenMatch(sz, "tet", 3)) { + meshesLocked.push_back(MeshInfo(PatchType_Simple, true)); + MeshInfo &curMesh = meshesLocked.back(); + curMesh.shader = s; + curMesh.shader.mapping = aiTextureMapping_SPHERE; AI_NFF_PARSE_SHAPE_INFORMATION(); // we don't need scaling or translation here - we do it in the node's transform - StandardShapes::MakeTetrahedron(currentMesh.vertices); - currentMesh.faces.resize(currentMesh.vertices.size()/3,3); + StandardShapes::MakeTetrahedron(curMesh.vertices); + curMesh.faces.resize(curMesh.vertices.size() / 3, 3); // generate a name for the mesh - ::ai_snprintf(currentMesh.name,128,"tetrahedron_%i",tetrahedron++); + ::ai_snprintf(curMesh.name, MeshInfo::MaxNameLen, "tetrahedron_%i", tetrahedron++); } // 'hex' - hexahedron - else if (TokenMatch(sz,"hex",3)) - { - meshesLocked.push_back(MeshInfo(PatchType_Simple,true)); - MeshInfo& currentMesh = meshesLocked.back(); - currentMesh.shader = s; - currentMesh.shader.mapping = aiTextureMapping_BOX; + else if (TokenMatch(sz, "hex", 3)) { + meshesLocked.push_back(MeshInfo(PatchType_Simple, true)); + MeshInfo &curMesh = meshesLocked.back(); + curMesh.shader = s; + curMesh.shader.mapping = aiTextureMapping_BOX; AI_NFF_PARSE_SHAPE_INFORMATION(); // we don't need scaling or translation here - we do it in the node's transform - StandardShapes::MakeHexahedron(currentMesh.vertices); - currentMesh.faces.resize(currentMesh.vertices.size()/3,3); + StandardShapes::MakeHexahedron(curMesh.vertices); + curMesh.faces.resize(curMesh.vertices.size() / 3, 3); // generate a name for the mesh - ::ai_snprintf(currentMesh.name,128,"hexahedron_%i",hexahedron++); + ::ai_snprintf(curMesh.name, MeshInfo::MaxNameLen, "hexahedron_%i", hexahedron++); } // 'c' - cone - else if (TokenMatch(sz,"c",1)) - { - meshesLocked.push_back(MeshInfo(PatchType_Simple,true)); - MeshInfo& currentMesh = meshesLocked.back(); - currentMesh.shader = s; - currentMesh.shader.mapping = aiTextureMapping_CYLINDER; + else if (TokenMatch(sz, "c", 1)) { + meshesLocked.push_back(MeshInfo(PatchType_Simple, true)); + MeshInfo &curMesh = meshesLocked.back(); + curMesh.shader = s; + curMesh.shader.mapping = aiTextureMapping_CYLINDER; - if(!GetNextLine(buffer,line)) - { + if (!GetNextLine(buffer, line)) { ASSIMP_LOG_ERROR("NFF: Unexpected end of file (cone definition not complete)"); break; } sz = line; // read the two center points and the respective radii - aiVector3D center1, center2; float radius1, radius2; + aiVector3D center1, center2; + float radius1 = 0.f, radius2 = 0.f; AI_NFF_PARSE_TRIPLE(center1); AI_NFF_PARSE_FLOAT(radius1); - if(!GetNextLine(buffer,line)) - { + if (!GetNextLine(buffer, line)) { ASSIMP_LOG_ERROR("NFF: Unexpected end of file (cone definition not complete)"); break; } @@ -964,164 +871,152 @@ void NFFImporter::InternReadFile( const std::string& pFile, // compute the center point of the cone/cylinder - // it is its local transformation origin - currentMesh.dir = center2-center1; - currentMesh.center = center1+currentMesh.dir/(ai_real)2.0; + curMesh.dir = center2 - center1; + curMesh.center = center1 + curMesh.dir / (ai_real)2.0; float f; - if (( f = currentMesh.dir.Length()) < 10e-3f ) - { + if ((f = curMesh.dir.Length()) < 10e-3f) { ASSIMP_LOG_ERROR("NFF: Cone height is close to zero"); continue; } - currentMesh.dir /= f; // normalize + curMesh.dir /= f; // normalize // generate the cone - it consists of simple triangles StandardShapes::MakeCone(f, radius1, radius2, - integer_pow(4, iTesselation), currentMesh.vertices); + integer_pow(4, iTesselation), curMesh.vertices); // MakeCone() returns tris - currentMesh.faces.resize(currentMesh.vertices.size()/3,3); + curMesh.faces.resize(curMesh.vertices.size() / 3, 3); // generate a name for the mesh. 'cone' if it a cone, // 'cylinder' if it is a cylinder. Funny, isn't it? - if (radius1 != radius2) - ::ai_snprintf(currentMesh.name,128,"cone_%i",cone++); - else ::ai_snprintf(currentMesh.name,128,"cylinder_%i",cylinder++); + if (radius1 != radius2) { + ::ai_snprintf(curMesh.name, MeshInfo::MaxNameLen, "cone_%i", cone++); + } else { + ::ai_snprintf(curMesh.name, MeshInfo::MaxNameLen, "cylinder_%i", cylinder++); + } } // 'tess' - tessellation - else if (TokenMatch(sz,"tess",4)) - { + else if (TokenMatch(sz, "tess", 4)) { SkipSpaces(&sz); iTesselation = strtoul10(sz); } // 'from' - camera position - else if (TokenMatch(sz,"from",4)) - { + else if (TokenMatch(sz, "from", 4)) { AI_NFF_PARSE_TRIPLE(camPos); hasCam = true; } // 'at' - camera look-at vector - else if (TokenMatch(sz,"at",2)) - { + else if (TokenMatch(sz, "at", 2)) { AI_NFF_PARSE_TRIPLE(camLookAt); hasCam = true; } // 'up' - camera up vector - else if (TokenMatch(sz,"up",2)) - { + else if (TokenMatch(sz, "up", 2)) { AI_NFF_PARSE_TRIPLE(camUp); hasCam = true; } // 'angle' - (half?) camera field of view - else if (TokenMatch(sz,"angle",5)) - { + else if (TokenMatch(sz, "angle", 5)) { AI_NFF_PARSE_FLOAT(angle); hasCam = true; } // 'resolution' - used to compute the screen aspect - else if (TokenMatch(sz,"resolution",10)) - { + else if (TokenMatch(sz, "resolution", 10)) { AI_NFF_PARSE_FLOAT(resolution.x); AI_NFF_PARSE_FLOAT(resolution.y); hasCam = true; } // 'pb' - bezier patch. Not supported yet - else if (TokenMatch(sz,"pb",2)) - { + else if (TokenMatch(sz, "pb", 2)) { ASSIMP_LOG_ERROR("NFF: Encountered unsupported ID: bezier patch"); } // 'pn' - NURBS. Not supported yet - else if (TokenMatch(sz,"pn",2) || TokenMatch(sz,"pnn",3)) - { + else if (TokenMatch(sz, "pn", 2) || TokenMatch(sz, "pnn", 3)) { ASSIMP_LOG_ERROR("NFF: Encountered unsupported ID: NURBS"); } // '' - comment - else if ('#' == line[0]) - { - const char* sz;SkipSpaces(&line[1],&sz); - if (!IsLineEnd(*sz)) { - ASSIMP_LOG_INFO(sz); + else if ('#' == line[0]) { + const char *space; + SkipSpaces(&line[1], &space); + if (!IsLineEnd(*space)) { + ASSIMP_LOG_INFO(space); } } } } // copy all arrays into one large - meshes.reserve (meshes.size()+meshesLocked.size()+meshesWithNormals.size()+meshesWithUVCoords.size()); - meshes.insert (meshes.end(),meshesLocked.begin(),meshesLocked.end()); - meshes.insert (meshes.end(),meshesWithNormals.begin(),meshesWithNormals.end()); - meshes.insert (meshes.end(),meshesWithUVCoords.begin(),meshesWithUVCoords.end()); + meshes.reserve(meshes.size() + meshesLocked.size() + meshesWithNormals.size() + meshesWithUVCoords.size()); + meshes.insert(meshes.end(), meshesLocked.begin(), meshesLocked.end()); + meshes.insert(meshes.end(), meshesWithNormals.begin(), meshesWithNormals.end()); + meshes.insert(meshes.end(), meshesWithUVCoords.begin(), meshesWithUVCoords.end()); // now generate output meshes. first find out how many meshes we'll need std::vector::const_iterator it = meshes.begin(), end = meshes.end(); - for (;it != end;++it) - { - if (!(*it).faces.empty()) - { + for (; it != end; ++it) { + if (!(*it).faces.empty()) { ++pScene->mNumMeshes; - if ((*it).name[0])++numNamed; + if ((*it).name[0]) ++numNamed; } } // generate a dummy root node - assign all unnamed elements such // as polygons and polygon patches to the root node and generate // sub nodes for named objects such as spheres and cones. - aiNode* const root = new aiNode(); + aiNode *const root = new aiNode(); root->mName.Set(""); - root->mNumChildren = numNamed + (hasCam ? 1 : 0) + (unsigned int) lights.size(); - root->mNumMeshes = pScene->mNumMeshes-numNamed; + root->mNumChildren = numNamed + (hasCam ? 1 : 0) + (unsigned int)lights.size(); + root->mNumMeshes = pScene->mNumMeshes - numNamed; - aiNode** ppcChildren = NULL; - unsigned int* pMeshes = NULL; + aiNode **ppcChildren = NULL; + unsigned int *pMeshes = NULL; if (root->mNumMeshes) pMeshes = root->mMeshes = new unsigned int[root->mNumMeshes]; if (root->mNumChildren) - ppcChildren = root->mChildren = new aiNode*[root->mNumChildren]; + ppcChildren = root->mChildren = new aiNode *[root->mNumChildren]; // generate the camera - if (hasCam) - { + if (hasCam) { ai_assert(ppcChildren); - aiNode* nd = new aiNode(); + aiNode *nd = new aiNode(); *ppcChildren = nd; nd->mName.Set(""); nd->mParent = root; // allocate the camera in the scene pScene->mNumCameras = 1; - pScene->mCameras = new aiCamera*[1]; - aiCamera* c = pScene->mCameras[0] = new aiCamera; + pScene->mCameras = new aiCamera *[1]; + aiCamera *c = pScene->mCameras[0] = new aiCamera; c->mName = nd->mName; // make sure the names are identical - c->mHorizontalFOV = AI_DEG_TO_RAD( angle ); - c->mLookAt = camLookAt - camPos; - c->mPosition = camPos; - c->mUp = camUp; + c->mHorizontalFOV = AI_DEG_TO_RAD(angle); + c->mLookAt = camLookAt - camPos; + c->mPosition = camPos; + c->mUp = camUp; // If the resolution is not specified in the file, we // need to set 1.0 as aspect. - c->mAspect = (!resolution.y ? 0.f : resolution.x / resolution.y); + c->mAspect = (!resolution.y ? 0.f : resolution.x / resolution.y); ++ppcChildren; } // generate light sources - if (!lights.empty()) - { + if (!lights.empty()) { ai_assert(ppcChildren); pScene->mNumLights = (unsigned int)lights.size(); - pScene->mLights = new aiLight*[pScene->mNumLights]; - for (unsigned int i = 0; i < pScene->mNumLights;++i,++ppcChildren) - { - const Light& l = lights[i]; + pScene->mLights = new aiLight *[pScene->mNumLights]; + for (unsigned int i = 0; i < pScene->mNumLights; ++i, ++ppcChildren) { + const Light &l = lights[i]; - aiNode* nd = new aiNode(); + aiNode *nd = new aiNode(); *ppcChildren = nd; nd->mParent = root; - nd->mName.length = ::ai_snprintf(nd->mName.data,1024,"",i); + nd->mName.length = ::ai_snprintf(nd->mName.data, 1024, "", i); // allocate the light in the scene data structure - aiLight* out = pScene->mLights[i] = new aiLight(); + aiLight *out = pScene->mLights[i] = new aiLight(); out->mName = nd->mName; // make sure the names are identical out->mType = aiLightSource_POINT; out->mColorDiffuse = out->mColorSpecular = l.color * l.intensity; @@ -1129,22 +1024,21 @@ void NFFImporter::InternReadFile( const std::string& pFile, } } - if (!pScene->mNumMeshes)throw DeadlyImportError("NFF: No meshes loaded"); - pScene->mMeshes = new aiMesh*[pScene->mNumMeshes]; - pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials = pScene->mNumMeshes]; + if (!pScene->mNumMeshes) throw DeadlyImportError("NFF: No meshes loaded"); + pScene->mMeshes = new aiMesh *[pScene->mNumMeshes]; + pScene->mMaterials = new aiMaterial *[pScene->mNumMaterials = pScene->mNumMeshes]; unsigned int m = 0; - for (it = meshes.begin(); it != end;++it) - { - if ((*it).faces.empty())continue; + for (it = meshes.begin(); it != end; ++it) { + if ((*it).faces.empty()) continue; - const MeshInfo& src = *it; - aiMesh* const mesh = pScene->mMeshes[m] = new aiMesh(); + const MeshInfo &src = *it; + aiMesh *const mesh = pScene->mMeshes[m] = new aiMesh(); mesh->mNumVertices = (unsigned int)src.vertices.size(); mesh->mNumFaces = (unsigned int)src.faces.size(); // Generate sub nodes for named meshes - if ( src.name[ 0 ] && NULL != ppcChildren ) { - aiNode* const node = *ppcChildren = new aiNode(); + if (src.name[0] && NULL != ppcChildren) { + aiNode *const node = *ppcChildren = new aiNode(); node->mParent = root; node->mNumMeshes = 1; node->mMeshes = new unsigned int[1]; @@ -1152,13 +1046,19 @@ void NFFImporter::InternReadFile( const std::string& pFile, node->mName.Set(src.name); // setup the transformation matrix of the node - aiMatrix4x4::FromToMatrix(aiVector3D(0.f,1.f,0.f), - src.dir,node->mTransformation); + aiMatrix4x4::FromToMatrix(aiVector3D(0.f, 1.f, 0.f), + src.dir, node->mTransformation); - aiMatrix4x4& mat = node->mTransformation; - mat.a1 *= src.radius.x; mat.b1 *= src.radius.x; mat.c1 *= src.radius.x; - mat.a2 *= src.radius.y; mat.b2 *= src.radius.y; mat.c2 *= src.radius.y; - mat.a3 *= src.radius.z; mat.b3 *= src.radius.z; mat.c3 *= src.radius.z; + aiMatrix4x4 &mat = node->mTransformation; + mat.a1 *= src.radius.x; + mat.b1 *= src.radius.x; + mat.c1 *= src.radius.x; + mat.a2 *= src.radius.y; + mat.b2 *= src.radius.y; + mat.c2 *= src.radius.y; + mat.a3 *= src.radius.z; + mat.b3 *= src.radius.z; + mat.c3 *= src.radius.z; mat.a4 = src.center.x; mat.b4 = src.center.y; mat.c4 = src.center.z; @@ -1170,107 +1070,99 @@ void NFFImporter::InternReadFile( const std::string& pFile, // copy vertex positions mesh->mVertices = new aiVector3D[mesh->mNumVertices]; - ::memcpy(mesh->mVertices,&src.vertices[0], - sizeof(aiVector3D)*mesh->mNumVertices); + ::memcpy(mesh->mVertices, &src.vertices[0], + sizeof(aiVector3D) * mesh->mNumVertices); // NFF2: there could be vertex colors - if (!src.colors.empty()) - { + if (!src.colors.empty()) { ai_assert(src.colors.size() == src.vertices.size()); // copy vertex colors mesh->mColors[0] = new aiColor4D[mesh->mNumVertices]; - ::memcpy(mesh->mColors[0],&src.colors[0], - sizeof(aiColor4D)*mesh->mNumVertices); + ::memcpy(mesh->mColors[0], &src.colors[0], + sizeof(aiColor4D) * mesh->mNumVertices); } - if (!src.normals.empty()) - { + if (!src.normals.empty()) { ai_assert(src.normals.size() == src.vertices.size()); // copy normal vectors mesh->mNormals = new aiVector3D[mesh->mNumVertices]; - ::memcpy(mesh->mNormals,&src.normals[0], - sizeof(aiVector3D)*mesh->mNumVertices); + ::memcpy(mesh->mNormals, &src.normals[0], + sizeof(aiVector3D) * mesh->mNumVertices); } - if (!src.uvs.empty()) - { + if (!src.uvs.empty()) { ai_assert(src.uvs.size() == src.vertices.size()); // copy texture coordinates mesh->mTextureCoords[0] = new aiVector3D[mesh->mNumVertices]; - ::memcpy(mesh->mTextureCoords[0],&src.uvs[0], - sizeof(aiVector3D)*mesh->mNumVertices); + ::memcpy(mesh->mTextureCoords[0], &src.uvs[0], + sizeof(aiVector3D) * mesh->mNumVertices); } // generate faces unsigned int p = 0; - aiFace* pFace = mesh->mFaces = new aiFace[mesh->mNumFaces]; + aiFace *pFace = mesh->mFaces = new aiFace[mesh->mNumFaces]; for (std::vector::const_iterator it2 = src.faces.begin(), - end2 = src.faces.end(); - it2 != end2;++it2,++pFace) - { - pFace->mIndices = new unsigned int [ pFace->mNumIndices = *it2 ]; - for (unsigned int o = 0; o < pFace->mNumIndices;++o) + end2 = src.faces.end(); + it2 != end2; ++it2, ++pFace) { + pFace->mIndices = new unsigned int[pFace->mNumIndices = *it2]; + for (unsigned int o = 0; o < pFace->mNumIndices; ++o) pFace->mIndices[o] = p++; } // generate a material for the mesh - aiMaterial* pcMat = (aiMaterial*)(pScene->mMaterials[m] = new aiMaterial()); + aiMaterial *pcMat = (aiMaterial *)(pScene->mMaterials[m] = new aiMaterial()); mesh->mMaterialIndex = m++; - aiString s; - s.Set(AI_DEFAULT_MATERIAL_NAME); - pcMat->AddProperty(&s, AI_MATKEY_NAME); + aiString matName; + matName.Set(AI_DEFAULT_MATERIAL_NAME); + pcMat->AddProperty(&matName, AI_MATKEY_NAME); // FIX: Ignore diffuse == 0 - aiColor3D c = src.shader.color * (src.shader.diffuse.r ? src.shader.diffuse : aiColor3D(1.f,1.f,1.f)); - pcMat->AddProperty(&c,1,AI_MATKEY_COLOR_DIFFUSE); + aiColor3D c = src.shader.color * (src.shader.diffuse.r ? src.shader.diffuse : aiColor3D(1.f, 1.f, 1.f)); + pcMat->AddProperty(&c, 1, AI_MATKEY_COLOR_DIFFUSE); c = src.shader.color * src.shader.specular; - pcMat->AddProperty(&c,1,AI_MATKEY_COLOR_SPECULAR); + pcMat->AddProperty(&c, 1, AI_MATKEY_COLOR_SPECULAR); // NFF2 - default values for NFF - pcMat->AddProperty(&src.shader.ambient, 1,AI_MATKEY_COLOR_AMBIENT); - pcMat->AddProperty(&src.shader.emissive,1,AI_MATKEY_COLOR_EMISSIVE); - pcMat->AddProperty(&src.shader.opacity, 1,AI_MATKEY_OPACITY); + pcMat->AddProperty(&src.shader.ambient, 1, AI_MATKEY_COLOR_AMBIENT); + pcMat->AddProperty(&src.shader.emissive, 1, AI_MATKEY_COLOR_EMISSIVE); + pcMat->AddProperty(&src.shader.opacity, 1, AI_MATKEY_OPACITY); // setup the first texture layer, if existing - if (src.shader.texFile.length()) - { - s.Set(src.shader.texFile); - pcMat->AddProperty(&s,AI_MATKEY_TEXTURE_DIFFUSE(0)); + if (src.shader.texFile.length()) { + matName.Set(src.shader.texFile); + pcMat->AddProperty(&matName, AI_MATKEY_TEXTURE_DIFFUSE(0)); if (aiTextureMapping_UV != src.shader.mapping) { - aiVector3D v(0.f,-1.f,0.f); - pcMat->AddProperty(&v, 1,AI_MATKEY_TEXMAP_AXIS_DIFFUSE(0)); - pcMat->AddProperty((int*)&src.shader.mapping, 1,AI_MATKEY_MAPPING_DIFFUSE(0)); + aiVector3D v(0.f, -1.f, 0.f); + pcMat->AddProperty(&v, 1, AI_MATKEY_TEXMAP_AXIS_DIFFUSE(0)); + pcMat->AddProperty((int *)&src.shader.mapping, 1, AI_MATKEY_MAPPING_DIFFUSE(0)); } } // setup the name of the material - if (src.shader.name.length()) - { - s.Set(src.shader.texFile); - pcMat->AddProperty(&s,AI_MATKEY_NAME); + if (src.shader.name.length()) { + matName.Set(src.shader.texFile); + pcMat->AddProperty(&matName, AI_MATKEY_NAME); } // setup some more material properties that are specific to NFF2 int i; - if (src.shader.twoSided) - { + if (src.shader.twoSided) { i = 1; - pcMat->AddProperty(&i,1,AI_MATKEY_TWOSIDED); + pcMat->AddProperty(&i, 1, AI_MATKEY_TWOSIDED); } i = (src.shader.shaded ? aiShadingMode_Gouraud : aiShadingMode_NoShading); - if (src.shader.shininess) - { + if (src.shader.shininess) { i = aiShadingMode_Phong; - pcMat->AddProperty(&src.shader.shininess,1,AI_MATKEY_SHININESS); + pcMat->AddProperty(&src.shader.shininess, 1, AI_MATKEY_SHININESS); } - pcMat->AddProperty(&i,1,AI_MATKEY_SHADING_MODEL); + pcMat->AddProperty(&i, 1, AI_MATKEY_SHADING_MODEL); } pScene->mRootNode = root; } diff --git a/code/NFF/NFFLoader.h b/code/NFF/NFFLoader.h index 02f0f82d5..524310b0e 100644 --- a/code/NFF/NFFLoader.h +++ b/code/NFF/NFFLoader.h @@ -185,8 +185,8 @@ private: // for spheres, cones and cylinders: center point of the object aiVector3D center, radius, dir; - - char name[128]; + static const size_t MaxNameLen = 128; + char name[MaxNameLen]; std::vector vertices, normals, uvs; std::vector faces; diff --git a/code/Obj/ObjFileParser.cpp b/code/Obj/ObjFileParser.cpp index 48129c02c..a23b8a997 100644 --- a/code/Obj/ObjFileParser.cpp +++ b/code/Obj/ObjFileParser.cpp @@ -80,7 +80,7 @@ ObjFileParser::ObjFileParser( IOStreamBuffer &streamBuffer, const std::str m_progress(progress), m_originalObjFileName(originalObjFileName) { - std::fill_n(m_buffer,Buffersize,0); + std::fill_n(m_buffer,Buffersize,'\0'); // Create the model instance to store all the data m_pModel.reset(new ObjFile::Model()); diff --git a/code/Ogre/OgreBinarySerializer.cpp b/code/Ogre/OgreBinarySerializer.cpp index c7b7e0b5e..9259208f5 100644 --- a/code/Ogre/OgreBinarySerializer.cpp +++ b/code/Ogre/OgreBinarySerializer.cpp @@ -668,8 +668,8 @@ void OgreBinarySerializer::ReadEdgeList(Mesh * /*mesh*/) for (size_t i=0; iIncPtr(sizeof(uint32_t) * 3); diff --git a/code/Ogre/OgreImporter.cpp b/code/Ogre/OgreImporter.cpp index 6ef9aa462..9d85a0a96 100644 --- a/code/Ogre/OgreImporter.cpp +++ b/code/Ogre/OgreImporter.cpp @@ -4,7 +4,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2020, assimp team - All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/Ogre/OgreMaterial.cpp b/code/Ogre/OgreMaterial.cpp index 6f2e62958..f79206406 100644 --- a/code/Ogre/OgreMaterial.cpp +++ b/code/Ogre/OgreMaterial.cpp @@ -206,8 +206,8 @@ aiMaterial* OgreImporter::ReadMaterial(const std::string &pFile, Assimp::IOSyste aiMaterial *material = new aiMaterial(); m_textures.clear(); - aiString ts(materialName); - material->AddProperty(&ts, AI_MATKEY_NAME); + aiString matName(materialName); + material->AddProperty(&matName, AI_MATKEY_NAME); // The stringstream will push words from a line until newline. // It will also trim whitespace from line start and between words. @@ -279,14 +279,14 @@ aiMaterial* OgreImporter::ReadMaterial(const std::string &pFile, Assimp::IOSyste else if (linePart=="$colormap") { ss >> linePart; - aiString ts(linePart); - material->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE, 0)); + aiString cm(linePart); + material->AddProperty(&cm, AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE, 0)); } else if (linePart=="$normalmap") { ss >> linePart; - aiString ts(linePart); - material->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_NORMALS, 0)); + aiString nm(linePart); + material->AddProperty(&nm, AI_MATKEY_TEXTURE(aiTextureType_NORMALS, 0)); } else if (linePart=="$shininess_strength") { diff --git a/code/Ogre/OgreParsingUtils.h b/code/Ogre/OgreParsingUtils.h index 3fbfd5c31..872906e48 100644 --- a/code/Ogre/OgreParsingUtils.h +++ b/code/Ogre/OgreParsingUtils.h @@ -46,26 +46,25 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef ASSIMP_BUILD_NO_OGRE_IMPORTER #include -#include -#include #include -#include +#include #include +#include +#include namespace Assimp { namespace Ogre { /// Returns a lower cased copy of @s. -static AI_FORCE_INLINE -std::string ToLower(std::string s) -{ - std::transform(s.begin(), s.end(), s.begin(), ::tolower); - return s; +static AI_FORCE_INLINE std::string ToLower(const std::string &s) { + std::string lower(s); + std::transform(lower.begin(), lower.end(), lower.begin(), Assimp::ToLower); + + return lower; } /// Returns if @c s ends with @c suffix. If @c caseSensitive is false, both strings will be lower cased before matching. -static AI_FORCE_INLINE -bool EndsWith(const std::string &s, const std::string &suffix, bool caseSensitive = true) { +static AI_FORCE_INLINE bool EndsWith( const std::string &s, const std::string &suffix, bool caseSensitive = true) { if (s.empty() || suffix.empty()) { return false; } else if (s.length() < suffix.length()) { @@ -77,7 +76,7 @@ bool EndsWith(const std::string &s, const std::string &suffix, bool caseSensitiv } size_t len = suffix.length(); - std::string sSuffix = s.substr(s.length()-len, len); + std::string sSuffix = s.substr(s.length() - len, len); return (ASSIMP_stricmp(sSuffix, suffix) == 0); } @@ -86,7 +85,8 @@ bool EndsWith(const std::string &s, const std::string &suffix, bool caseSensitiv /// Trim from start static AI_FORCE_INLINE -std::string &TrimLeft(std::string &s, bool newlines = true) { + std::string & + TrimLeft(std::string &s, bool newlines = true) { if (!newlines) { s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](char c) { return !Assimp::IsSpace(c); })); } else { @@ -97,9 +97,10 @@ std::string &TrimLeft(std::string &s, bool newlines = true) { /// Trim from end static AI_FORCE_INLINE -std::string &TrimRight(std::string &s, bool newlines = true) { + std::string & + TrimRight(std::string &s, bool newlines = true) { if (!newlines) { - s.erase(std::find_if(s.rbegin(), s.rend(), [](char c) { return !Assimp::IsSpace(c); }).base(),s.end()); + s.erase(std::find_if(s.rbegin(), s.rend(), [](char c) { return !Assimp::IsSpace(c); }).base(), s.end()); } else { s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](char c) { return !Assimp::IsSpaceOrNewLine(c); })); } @@ -108,13 +109,15 @@ std::string &TrimRight(std::string &s, bool newlines = true) { /// Trim from both ends static AI_FORCE_INLINE -std::string &Trim(std::string &s, bool newlines = true) { + std::string & + Trim(std::string &s, bool newlines = true) { return TrimLeft(TrimRight(s, newlines), newlines); } /// Skips a line from current @ss position until a newline. Returns the skipped part. static AI_FORCE_INLINE -std::string SkipLine(std::stringstream &ss) { + std::string + SkipLine(std::stringstream &ss) { std::string skipped; getline(ss, skipped); return skipped; @@ -123,14 +126,15 @@ std::string SkipLine(std::stringstream &ss) { /// Skips a line and reads next element from @c ss to @c nextElement. /** @return Skipped line content until newline. */ static AI_FORCE_INLINE -std::string NextAfterNewLine(std::stringstream &ss, std::string &nextElement) { + std::string + NextAfterNewLine(std::stringstream &ss, std::string &nextElement) { std::string skipped = SkipLine(ss); ss >> nextElement; return skipped; } -} // Ogre -} // Assimp +} // namespace Ogre +} // namespace Assimp #endif // ASSIMP_BUILD_NO_OGRE_IMPORTER #endif // AI_OGREPARSINGUTILS_H_INC diff --git a/code/Ogre/OgreXmlSerializer.cpp b/code/Ogre/OgreXmlSerializer.cpp index a93f1b207..406220a9d 100644 --- a/code/Ogre/OgreXmlSerializer.cpp +++ b/code/Ogre/OgreXmlSerializer.cpp @@ -53,140 +53,94 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Define as 1 to get verbose logging. #define OGRE_XML_SERIALIZER_DEBUG 0 -namespace Assimp -{ -namespace Ogre -{ +namespace Assimp { +namespace Ogre { -AI_WONT_RETURN void ThrowAttibuteError(const XmlReader* reader, const std::string &name, const std::string &error = "") AI_WONT_RETURN_SUFFIX; -AI_WONT_RETURN void ThrowAttibuteError(const XmlReader* reader, const std::string &name, const std::string &error) -{ - if (!error.empty()) - { +AI_WONT_RETURN void ThrowAttibuteError(const XmlReader *reader, const std::string &name, const std::string &error = "") AI_WONT_RETURN_SUFFIX; +AI_WONT_RETURN void ThrowAttibuteError(const XmlReader *reader, const std::string &name, const std::string &error) { + if (!error.empty()) { throw DeadlyImportError(error + " in node '" + std::string(reader->getNodeName()) + "' and attribute '" + name + "'"); - } - else - { + } else { throw DeadlyImportError("Attribute '" + name + "' does not exist in node '" + std::string(reader->getNodeName()) + "'"); } } -template<> -int32_t OgreXmlSerializer::ReadAttribute(const char *name) const -{ - if (HasAttribute(name)) - { - return static_cast(m_reader->getAttributeValueAsInt(name)); - } - else - { - ThrowAttibuteError(m_reader, name); - return 0; - } -} - -template<> -uint32_t OgreXmlSerializer::ReadAttribute(const char *name) const -{ - if (HasAttribute(name)) - { - /** @note This is hackish. But we are never expecting unsigned values that go outside the - int32_t range. Just monitor for negative numbers and kill the import. */ - int32_t temp = ReadAttribute(name); - if (temp >= 0) - { - return static_cast(temp); - } - else - { - ThrowAttibuteError(m_reader, name, "Found a negative number value where expecting a uint32_t value"); - } - } - else - { +template <> +int32_t OgreXmlSerializer::ReadAttribute(const char *name) const { + if (!HasAttribute(name)) { ThrowAttibuteError(m_reader, name); } - return 0; + + return static_cast(m_reader->getAttributeValueAsInt(name)); } -template<> -uint16_t OgreXmlSerializer::ReadAttribute(const char *name) const -{ - if (HasAttribute(name)) - { - return static_cast(ReadAttribute(name)); - } - else - { +template <> +uint32_t OgreXmlSerializer::ReadAttribute(const char *name) const { + if (!HasAttribute(name)) { ThrowAttibuteError(m_reader, name); } - return 0; + // @note This is hackish. But we are never expecting unsigned values that go outside the + // int32_t range. Just monitor for negative numbers and kill the import. + int32_t temp = ReadAttribute(name); + if (temp < 0) { + ThrowAttibuteError(m_reader, name, "Found a negative number value where expecting a uint32_t value"); + } + + return static_cast(temp); } -template<> -float OgreXmlSerializer::ReadAttribute(const char *name) const -{ - if (HasAttribute(name)) - { - return m_reader->getAttributeValueAsFloat(name); - } - else - { +template <> +uint16_t OgreXmlSerializer::ReadAttribute(const char *name) const { + if (!HasAttribute(name)) { ThrowAttibuteError(m_reader, name); - return 0; } + + return static_cast(ReadAttribute(name)); } -template<> -std::string OgreXmlSerializer::ReadAttribute(const char *name) const -{ - const char* value = m_reader->getAttributeValue(name); - if (value) - { - return std::string(value); - } - else - { +template <> +float OgreXmlSerializer::ReadAttribute(const char *name) const { + if (!HasAttribute(name)) { ThrowAttibuteError(m_reader, name); - return ""; } + + return m_reader->getAttributeValueAsFloat(name); } -template<> -bool OgreXmlSerializer::ReadAttribute(const char *name) const -{ +template <> +std::string OgreXmlSerializer::ReadAttribute(const char *name) const { + const char *value = m_reader->getAttributeValue(name); + if (nullptr == value) { + ThrowAttibuteError(m_reader, name); + } + + return std::string(value); +} + +template <> +bool OgreXmlSerializer::ReadAttribute(const char *name) const { std::string value = Ogre::ToLower(ReadAttribute(name)); - if (ASSIMP_stricmp(value, "true") == 0) - { + if (ASSIMP_stricmp(value, "true") == 0) { return true; - } - else if (ASSIMP_stricmp(value, "false") == 0) - { + } else if (ASSIMP_stricmp(value, "false") == 0) { return false; - } - else - { + } else { ThrowAttibuteError(m_reader, name, "Boolean value is expected to be 'true' or 'false', encountered '" + value + "'"); return false; } } -bool OgreXmlSerializer::HasAttribute(const char *name) const -{ +bool OgreXmlSerializer::HasAttribute(const char *name) const { return (m_reader->getAttributeValue(name) != 0); } -std::string &OgreXmlSerializer::NextNode() -{ - do - { - if (!m_reader->read()) - { +std::string &OgreXmlSerializer::NextNode() { + do { + if (!m_reader->read()) { m_currentNodeName = ""; return m_currentNodeName; } - } - while(m_reader->getNodeType() != irr::io::EXN_ELEMENT); + } while (m_reader->getNodeType() != irr::io::EXN_ELEMENT); CurrentNodeName(true); #if (OGRE_XML_SERIALIZER_DEBUG == 1) @@ -195,32 +149,29 @@ std::string &OgreXmlSerializer::NextNode() return m_currentNodeName; } -bool OgreXmlSerializer::CurrentNodeNameEquals(const std::string &name) const -{ +bool OgreXmlSerializer::CurrentNodeNameEquals(const std::string &name) const { return (ASSIMP_stricmp(m_currentNodeName, name) == 0); } -std::string OgreXmlSerializer::CurrentNodeName(bool forceRead) -{ +std::string OgreXmlSerializer::CurrentNodeName(bool forceRead) { if (forceRead) m_currentNodeName = std::string(m_reader->getNodeName()); return m_currentNodeName; } -std::string &OgreXmlSerializer::SkipCurrentNode() -{ +std::string &OgreXmlSerializer::SkipCurrentNode() { #if (OGRE_XML_SERIALIZER_DEBUG == 1) ASSIMP_LOG_DEBUG("Skipping node <" + m_currentNodeName + ">"); #endif - for(;;) { + for (;;) { if (!m_reader->read()) { m_currentNodeName = ""; return m_currentNodeName; } - if ( m_reader->getNodeType() != irr::io::EXN_ELEMENT_END ) { + if (m_reader->getNodeType() != irr::io::EXN_ELEMENT_END) { continue; - } else if ( std::string( m_reader->getNodeName() ) == m_currentNodeName ) { + } else if (std::string(m_reader->getNodeName()) == m_currentNodeName) { break; } } @@ -231,38 +182,38 @@ std::string &OgreXmlSerializer::SkipCurrentNode() // Mesh XML constants // -static const char *nnMesh = "mesh"; -static const char *nnSharedGeometry = "sharedgeometry"; -static const char *nnSubMeshes = "submeshes"; -static const char *nnSubMesh = "submesh"; -static const char *nnSubMeshNames = "submeshnames"; -static const char *nnSkeletonLink = "skeletonlink"; -static const char *nnLOD = "levelofdetail"; -static const char *nnExtremes = "extremes"; -static const char *nnPoses = "poses"; -static const char *nnAnimations = "animations"; +static const char *nnMesh = "mesh"; +static const char *nnSharedGeometry = "sharedgeometry"; +static const char *nnSubMeshes = "submeshes"; +static const char *nnSubMesh = "submesh"; +static const char *nnSubMeshNames = "submeshnames"; +static const char *nnSkeletonLink = "skeletonlink"; +static const char *nnLOD = "levelofdetail"; +static const char *nnExtremes = "extremes"; +static const char *nnPoses = "poses"; +static const char *nnAnimations = "animations"; // -static const char *nnFaces = "faces"; -static const char *nnFace = "face"; -static const char *nnGeometry = "geometry"; -static const char *nnTextures = "textures"; +static const char *nnFaces = "faces"; +static const char *nnFace = "face"; +static const char *nnGeometry = "geometry"; +static const char *nnTextures = "textures"; // -static const char *nnBoneAssignments = "boneassignments"; +static const char *nnBoneAssignments = "boneassignments"; // -static const char *nnVertexBuffer = "vertexbuffer"; +static const char *nnVertexBuffer = "vertexbuffer"; // -static const char *nnVertex = "vertex"; -static const char *nnPosition = "position"; -static const char *nnNormal = "normal"; -static const char *nnTangent = "tangent"; -static const char *nnBinormal = "binormal"; -static const char *nnTexCoord = "texcoord"; -static const char *nnColorDiffuse = "colour_diffuse"; -static const char *nnColorSpecular = "colour_specular"; +static const char *nnVertex = "vertex"; +static const char *nnPosition = "position"; +static const char *nnNormal = "normal"; +static const char *nnTangent = "tangent"; +static const char *nnBinormal = "binormal"; +static const char *nnTexCoord = "texcoord"; +static const char *nnColorDiffuse = "colour_diffuse"; +static const char *nnColorSpecular = "colour_specular"; // static const char *nnVertexBoneAssignment = "vertexboneassignment"; @@ -270,30 +221,30 @@ static const char *nnVertexBoneAssignment = "vertexboneassignment"; // Skeleton XML constants // -static const char *nnSkeleton = "skeleton"; -static const char *nnBones = "bones"; -static const char *nnBoneHierarchy = "bonehierarchy"; -static const char *nnAnimationLinks = "animationlinks"; +static const char *nnSkeleton = "skeleton"; +static const char *nnBones = "bones"; +static const char *nnBoneHierarchy = "bonehierarchy"; +static const char *nnAnimationLinks = "animationlinks"; // -static const char *nnBone = "bone"; -static const char *nnRotation = "rotation"; -static const char *nnAxis = "axis"; -static const char *nnScale = "scale"; +static const char *nnBone = "bone"; +static const char *nnRotation = "rotation"; +static const char *nnAxis = "axis"; +static const char *nnScale = "scale"; // -static const char *nnBoneParent = "boneparent"; +static const char *nnBoneParent = "boneparent"; // -static const char *nnAnimation = "animation"; -static const char *nnTracks = "tracks"; +static const char *nnAnimation = "animation"; +static const char *nnTracks = "tracks"; // -static const char *nnTrack = "track"; -static const char *nnKeyFrames = "keyframes"; -static const char *nnKeyFrame = "keyframe"; -static const char *nnTranslate = "translate"; -static const char *nnRotate = "rotate"; +static const char *nnTrack = "track"; +static const char *nnKeyFrames = "keyframes"; +static const char *nnKeyFrame = "keyframe"; +static const char *nnTranslate = "translate"; +static const char *nnRotate = "rotate"; // Common XML constants @@ -322,34 +273,26 @@ void OgreXmlSerializer::ReadMesh(MeshXml *mesh) { NextNode(); // Root level nodes - while(m_currentNodeName == nnSharedGeometry || - m_currentNodeName == nnSubMeshes || - m_currentNodeName == nnSkeletonLink || - m_currentNodeName == nnBoneAssignments || - m_currentNodeName == nnLOD || - m_currentNodeName == nnSubMeshNames || - m_currentNodeName == nnExtremes || - m_currentNodeName == nnPoses || - m_currentNodeName == nnAnimations) - { - if (m_currentNodeName == nnSharedGeometry) - { + while (m_currentNodeName == nnSharedGeometry || + m_currentNodeName == nnSubMeshes || + m_currentNodeName == nnSkeletonLink || + m_currentNodeName == nnBoneAssignments || + m_currentNodeName == nnLOD || + m_currentNodeName == nnSubMeshNames || + m_currentNodeName == nnExtremes || + m_currentNodeName == nnPoses || + m_currentNodeName == nnAnimations) { + if (m_currentNodeName == nnSharedGeometry) { mesh->sharedVertexData = new VertexDataXml(); ReadGeometry(mesh->sharedVertexData); - } - else if (m_currentNodeName == nnSubMeshes) - { + } else if (m_currentNodeName == nnSubMeshes) { NextNode(); - while(m_currentNodeName == nnSubMesh) { + while (m_currentNodeName == nnSubMesh) { ReadSubMesh(mesh); } - } - else if (m_currentNodeName == nnBoneAssignments) - { + } else if (m_currentNodeName == nnBoneAssignments) { ReadBoneAssignments(mesh->sharedVertexData); - } - else if (m_currentNodeName == nnSkeletonLink) - { + } else if (m_currentNodeName == nnSkeletonLink) { mesh->skeletonRef = ReadAttribute("name"); ASSIMP_LOG_DEBUG_F("Read skeleton link ", mesh->skeletonRef); NextNode(); @@ -360,49 +303,43 @@ void OgreXmlSerializer::ReadMesh(MeshXml *mesh) { } } -void OgreXmlSerializer::ReadGeometry(VertexDataXml *dest) -{ +void OgreXmlSerializer::ReadGeometry(VertexDataXml *dest) { dest->count = ReadAttribute("vertexcount"); - ASSIMP_LOG_DEBUG_F( " - Reading geometry of ", dest->count, " vertices"); + ASSIMP_LOG_DEBUG_F(" - Reading geometry of ", dest->count, " vertices"); NextNode(); - while(m_currentNodeName == nnVertexBuffer) { + while (m_currentNodeName == nnVertexBuffer) { ReadGeometryVertexBuffer(dest); } } -void OgreXmlSerializer::ReadGeometryVertexBuffer(VertexDataXml *dest) -{ +void OgreXmlSerializer::ReadGeometryVertexBuffer(VertexDataXml *dest) { bool positions = (HasAttribute("positions") && ReadAttribute("positions")); - bool normals = (HasAttribute("normals") && ReadAttribute("normals")); - bool tangents = (HasAttribute("tangents") && ReadAttribute("tangents")); - uint32_t uvs = (HasAttribute("texture_coords") ? ReadAttribute("texture_coords") : 0); + bool normals = (HasAttribute("normals") && ReadAttribute("normals")); + bool tangents = (HasAttribute("tangents") && ReadAttribute("tangents")); + uint32_t uvs = (HasAttribute("texture_coords") ? ReadAttribute("texture_coords") : 0); // Not having positions is a error only if a previous vertex buffer did not have them. if (!positions && !dest->HasPositions()) { throw DeadlyImportError("Vertex buffer does not contain positions!"); } - if (positions) - { + if (positions) { ASSIMP_LOG_DEBUG(" - Contains positions"); dest->positions.reserve(dest->count); } - if (normals) - { + if (normals) { ASSIMP_LOG_DEBUG(" - Contains normals"); dest->normals.reserve(dest->count); } - if (tangents) - { + if (tangents) { ASSIMP_LOG_DEBUG(" - Contains tangents"); dest->tangents.reserve(dest->count); } - if (uvs > 0) - { - ASSIMP_LOG_DEBUG_F( " - Contains ", uvs, " texture coords"); + if (uvs > 0) { + ASSIMP_LOG_DEBUG_F(" - Contains ", uvs, " texture coords"); dest->uvs.resize(uvs); - for(size_t i=0, len=dest->uvs.size(); iuvs.size(); i < len; ++i) { dest->uvs[i].reserve(dest->count); } } @@ -413,49 +350,40 @@ void OgreXmlSerializer::ReadGeometryVertexBuffer(VertexDataXml *dest) NextNode(); - while(m_currentNodeName == nnVertex || - m_currentNodeName == nnPosition || - m_currentNodeName == nnNormal || - m_currentNodeName == nnTangent || - m_currentNodeName == nnBinormal || - m_currentNodeName == nnTexCoord || - m_currentNodeName == nnColorDiffuse || - m_currentNodeName == nnColorSpecular) - { + while (m_currentNodeName == nnVertex || + m_currentNodeName == nnPosition || + m_currentNodeName == nnNormal || + m_currentNodeName == nnTangent || + m_currentNodeName == nnBinormal || + m_currentNodeName == nnTexCoord || + m_currentNodeName == nnColorDiffuse || + m_currentNodeName == nnColorSpecular) { if (m_currentNodeName == nnVertex) { NextNode(); } /// @todo Implement nnBinormal, nnColorDiffuse and nnColorSpecular - if (positions && m_currentNodeName == nnPosition) - { + if (positions && m_currentNodeName == nnPosition) { aiVector3D pos; pos.x = ReadAttribute(anX); pos.y = ReadAttribute(anY); pos.z = ReadAttribute(anZ); dest->positions.push_back(pos); - } - else if (normals && m_currentNodeName == nnNormal) - { + } else if (normals && m_currentNodeName == nnNormal) { aiVector3D normal; normal.x = ReadAttribute(anX); normal.y = ReadAttribute(anY); normal.z = ReadAttribute(anZ); dest->normals.push_back(normal); - } - else if (tangents && m_currentNodeName == nnTangent) - { + } else if (tangents && m_currentNodeName == nnTangent) { aiVector3D tangent; tangent.x = ReadAttribute(anX); tangent.y = ReadAttribute(anY); tangent.z = ReadAttribute(anZ); dest->tangents.push_back(tangent); - } - else if (uvs > 0 && m_currentNodeName == nnTexCoord) - { - for(auto &uvs : dest->uvs) - { + } else if (uvs > 0 && m_currentNodeName == nnTexCoord) { + for (auto &curUvs : dest->uvs) { if (m_currentNodeName != nnTexCoord) { throw DeadlyImportError("Vertex buffer declared more UVs than can be found in a vertex"); } @@ -463,47 +391,31 @@ void OgreXmlSerializer::ReadGeometryVertexBuffer(VertexDataXml *dest) aiVector3D uv; uv.x = ReadAttribute("u"); uv.y = (ReadAttribute("v") * -1) + 1; // Flip UV from Ogre to Assimp form - uvs.push_back(uv); + curUvs.push_back(uv); NextNode(); } // Continue main loop as above already read next node continue; - } - else - { + } else { /// @todo Remove this stuff once implemented. We only want to log warnings once per element. bool warn = true; - if (m_currentNodeName == nnBinormal) - { - if (warnBinormal) - { + if (m_currentNodeName == nnBinormal) { + if (warnBinormal) { warnBinormal = false; - } - else - { + } else { warn = false; } - } - else if (m_currentNodeName == nnColorDiffuse) - { - if (warnColorDiffuse) - { + } else if (m_currentNodeName == nnColorDiffuse) { + if (warnColorDiffuse) { warnColorDiffuse = false; - } - else - { + } else { warn = false; } - } - else if (m_currentNodeName == nnColorSpecular) - { - if (warnColorSpecular) - { + } else if (m_currentNodeName == nnColorSpecular) { + if (warnColorSpecular) { warnColorSpecular = false; - } - else - { + } else { warn = false; } } @@ -518,7 +430,7 @@ void OgreXmlSerializer::ReadGeometryVertexBuffer(VertexDataXml *dest) // Sanity checks if (dest->positions.size() != dest->count) { - throw DeadlyImportError(Formatter::format() << "Read only " << dest->positions.size() << " positions when should have read " << dest->count); + throw DeadlyImportError(Formatter::format() << "Read only " << dest->positions.size() << " positions when should have read " << dest->count); } if (normals && dest->normals.size() != dest->count) { throw DeadlyImportError(Formatter::format() << "Read only " << dest->normals.size() << " normals when should have read " << dest->count); @@ -526,26 +438,24 @@ void OgreXmlSerializer::ReadGeometryVertexBuffer(VertexDataXml *dest) if (tangents && dest->tangents.size() != dest->count) { throw DeadlyImportError(Formatter::format() << "Read only " << dest->tangents.size() << " tangents when should have read " << dest->count); } - for(unsigned int i=0; iuvs.size(); ++i) - { + for (unsigned int i = 0; i < dest->uvs.size(); ++i) { if (dest->uvs[i].size() != dest->count) { throw DeadlyImportError(Formatter::format() << "Read only " << dest->uvs[i].size() - << " uvs for uv index " << i << " when should have read " << dest->count); + << " uvs for uv index " << i << " when should have read " << dest->count); } } } -void OgreXmlSerializer::ReadSubMesh(MeshXml *mesh) -{ - static const char *anMaterial = "material"; +void OgreXmlSerializer::ReadSubMesh(MeshXml *mesh) { + static const char *anMaterial = "material"; static const char *anUseSharedVertices = "usesharedvertices"; - static const char *anCount = "count"; - static const char *anV1 = "v1"; - static const char *anV2 = "v2"; - static const char *anV3 = "v3"; - static const char *anV4 = "v4"; + static const char *anCount = "count"; + static const char *anV1 = "v1"; + static const char *anV2 = "v2"; + static const char *anV3 = "v3"; + static const char *anV4 = "v4"; - SubMeshXml* submesh = new SubMeshXml(); + SubMeshXml *submesh = new SubMeshXml(); if (HasAttribute(anMaterial)) { submesh->materialRef = ReadAttribute(anMaterial); @@ -554,9 +464,9 @@ void OgreXmlSerializer::ReadSubMesh(MeshXml *mesh) submesh->usesSharedVertexData = ReadAttribute(anUseSharedVertices); } - ASSIMP_LOG_DEBUG_F( "Reading SubMesh ", mesh->subMeshes.size()); - ASSIMP_LOG_DEBUG_F( " - Material: '", submesh->materialRef, "'"); - ASSIMP_LOG_DEBUG_F( " - Uses shared geometry: ", (submesh->usesSharedVertexData ? "true" : "false")); + ASSIMP_LOG_DEBUG_F("Reading SubMesh ", mesh->subMeshes.size()); + ASSIMP_LOG_DEBUG_F(" - Material: '", submesh->materialRef, "'"); + ASSIMP_LOG_DEBUG_F(" - Uses shared geometry: ", (submesh->usesSharedVertexData ? "true" : "false")); // TODO: maybe we have always just 1 faces and 1 geometry and always in this order. this loop will only work correct, when the order // of faces and geometry changed, and not if we have more than one of one @@ -565,19 +475,16 @@ void OgreXmlSerializer::ReadSubMesh(MeshXml *mesh) bool quadWarned = false; NextNode(); - while(m_currentNodeName == nnFaces || - m_currentNodeName == nnGeometry || - m_currentNodeName == nnTextures || - m_currentNodeName == nnBoneAssignments) - { - if (m_currentNodeName == nnFaces) - { + while (m_currentNodeName == nnFaces || + m_currentNodeName == nnGeometry || + m_currentNodeName == nnTextures || + m_currentNodeName == nnBoneAssignments) { + if (m_currentNodeName == nnFaces) { submesh->indexData->faceCount = ReadAttribute(anCount); submesh->indexData->faces.reserve(submesh->indexData->faceCount); NextNode(); - while(m_currentNodeName == nnFace) - { + while (m_currentNodeName == nnFace) { aiFace face; face.mNumIndices = 3; face.mIndices = new unsigned int[3]; @@ -598,7 +505,7 @@ void OgreXmlSerializer::ReadSubMesh(MeshXml *mesh) } if (submesh->indexData->faces.size() == submesh->indexData->faceCount) { - ASSIMP_LOG_DEBUG_F( " - Faces ", submesh->indexData->faceCount); + ASSIMP_LOG_DEBUG_F(" - Faces ", submesh->indexData->faceCount); } else { throw DeadlyImportError(Formatter::format() << "Read only " << submesh->indexData->faces.size() << " faces when should have read " << submesh->indexData->faceCount); } @@ -622,21 +529,19 @@ void OgreXmlSerializer::ReadSubMesh(MeshXml *mesh) mesh->subMeshes.push_back(submesh); } -void OgreXmlSerializer::ReadBoneAssignments(VertexDataXml *dest) -{ +void OgreXmlSerializer::ReadBoneAssignments(VertexDataXml *dest) { if (!dest) { throw DeadlyImportError("Cannot read bone assignments, vertex data is null."); } static const char *anVertexIndex = "vertexindex"; - static const char *anBoneIndex = "boneindex"; - static const char *anWeight = "weight"; + static const char *anBoneIndex = "boneindex"; + static const char *anWeight = "weight"; std::set influencedVertices; NextNode(); - while(m_currentNodeName == nnVertexBoneAssignment) - { + while (m_currentNodeName == nnVertexBoneAssignment) { VertexBoneAssignment ba; ba.vertexIndex = ReadAttribute(anVertexIndex); ba.boneIndex = ReadAttribute(anBoneIndex); @@ -652,38 +557,32 @@ void OgreXmlSerializer::ReadBoneAssignments(VertexDataXml *dest) Some exporters won't care if the sum of all bone weights for a single vertex equals 1 or not, so validate here. */ const float epsilon = 0.05f; - for (const uint32_t vertexIndex : influencedVertices) - { + for (const uint32_t vertexIndex : influencedVertices) { float sum = 0.0f; - for (VertexBoneAssignmentList::const_iterator baIter=dest->boneAssignments.begin(), baEnd=dest->boneAssignments.end(); baIter != baEnd; ++baIter) - { + for (VertexBoneAssignmentList::const_iterator baIter = dest->boneAssignments.begin(), baEnd = dest->boneAssignments.end(); baIter != baEnd; ++baIter) { if (baIter->vertexIndex == vertexIndex) sum += baIter->weight; } - if ((sum < (1.0f - epsilon)) || (sum > (1.0f + epsilon))) - { - for (auto &boneAssign : dest->boneAssignments) - { + if ((sum < (1.0f - epsilon)) || (sum > (1.0f + epsilon))) { + for (auto &boneAssign : dest->boneAssignments) { if (boneAssign.vertexIndex == vertexIndex) boneAssign.weight /= sum; } } } - ASSIMP_LOG_DEBUG_F( " - ", dest->boneAssignments.size(), " bone assignments"); + ASSIMP_LOG_DEBUG_F(" - ", dest->boneAssignments.size(), " bone assignments"); } // Skeleton -bool OgreXmlSerializer::ImportSkeleton(Assimp::IOSystem *pIOHandler, MeshXml *mesh) -{ +bool OgreXmlSerializer::ImportSkeleton(Assimp::IOSystem *pIOHandler, MeshXml *mesh) { if (!mesh || mesh->skeletonRef.empty()) return false; // Highly unusual to see in read world cases but support // XML mesh referencing a binary skeleton file. - if (EndsWith(mesh->skeletonRef, ".skeleton", false)) - { + if (EndsWith(mesh->skeletonRef, ".skeleton", false)) { if (OgreBinarySerializer::ImportSkeleton(pIOHandler, mesh)) return true; @@ -705,8 +604,7 @@ bool OgreXmlSerializer::ImportSkeleton(Assimp::IOSystem *pIOHandler, MeshXml *me return true; } -bool OgreXmlSerializer::ImportSkeleton(Assimp::IOSystem *pIOHandler, Mesh *mesh) -{ +bool OgreXmlSerializer::ImportSkeleton(Assimp::IOSystem *pIOHandler, Mesh *mesh) { if (!mesh || mesh->skeletonRef.empty()) return false; @@ -721,16 +619,13 @@ bool OgreXmlSerializer::ImportSkeleton(Assimp::IOSystem *pIOHandler, Mesh *mesh) return true; } -XmlReaderPtr OgreXmlSerializer::OpenReader(Assimp::IOSystem *pIOHandler, const std::string &filename) -{ - if (!EndsWith(filename, ".skeleton.xml", false)) - { +XmlReaderPtr OgreXmlSerializer::OpenReader(Assimp::IOSystem *pIOHandler, const std::string &filename) { + if (!EndsWith(filename, ".skeleton.xml", false)) { ASSIMP_LOG_ERROR_F("Imported Mesh is referencing to unsupported '", filename, "' skeleton file."); return XmlReaderPtr(); } - if (!pIOHandler->Exists(filename)) - { + if (!pIOHandler->Exists(filename)) { ASSIMP_LOG_ERROR_F("Failed to find skeleton file '", filename, "' that is referenced by imported Mesh."); return XmlReaderPtr(); } @@ -748,8 +643,7 @@ XmlReaderPtr OgreXmlSerializer::OpenReader(Assimp::IOSystem *pIOHandler, const s return reader; } -void OgreXmlSerializer::ReadSkeleton(Skeleton *skeleton) -{ +void OgreXmlSerializer::ReadSkeleton(Skeleton *skeleton) { if (NextNode() != nnSkeleton) { throw DeadlyImportError("Root node is <" + m_currentNodeName + "> expecting "); } @@ -758,18 +652,16 @@ void OgreXmlSerializer::ReadSkeleton(Skeleton *skeleton) // Optional blend mode from root node if (HasAttribute("blendmode")) { - skeleton->blendMode = (ToLower(ReadAttribute("blendmode")) == "cumulative" - ? Skeleton::ANIMBLEND_CUMULATIVE : Skeleton::ANIMBLEND_AVERAGE); + skeleton->blendMode = (ToLower(ReadAttribute("blendmode")) == "cumulative" ? Skeleton::ANIMBLEND_CUMULATIVE : Skeleton::ANIMBLEND_AVERAGE); } NextNode(); // Root level nodes - while(m_currentNodeName == nnBones || - m_currentNodeName == nnBoneHierarchy || - m_currentNodeName == nnAnimations || - m_currentNodeName == nnAnimationLinks) - { + while (m_currentNodeName == nnBones || + m_currentNodeName == nnBoneHierarchy || + m_currentNodeName == nnAnimations || + m_currentNodeName == nnAnimationLinks) { if (m_currentNodeName == nnBones) ReadBones(skeleton); else if (m_currentNodeName == nnBoneHierarchy) @@ -781,8 +673,7 @@ void OgreXmlSerializer::ReadSkeleton(Skeleton *skeleton) } } -void OgreXmlSerializer::ReadAnimations(Skeleton *skeleton) -{ +void OgreXmlSerializer::ReadAnimations(Skeleton *skeleton) { if (skeleton->bones.empty()) { throw DeadlyImportError("Cannot read for a Skeleton without bones"); } @@ -790,8 +681,7 @@ void OgreXmlSerializer::ReadAnimations(Skeleton *skeleton) ASSIMP_LOG_DEBUG(" - Animations"); NextNode(); - while(m_currentNodeName == nnAnimation) - { + while (m_currentNodeName == nnAnimation) { Animation *anim = new Animation(skeleton); anim->name = ReadAttribute("name"); anim->length = ReadAttribute("length"); @@ -803,15 +693,13 @@ void OgreXmlSerializer::ReadAnimations(Skeleton *skeleton) ReadAnimationTracks(anim); skeleton->animations.push_back(anim); - ASSIMP_LOG_DEBUG_F( " ", anim->name, " (", anim->length, " sec, ", anim->tracks.size(), " tracks)"); + ASSIMP_LOG_DEBUG_F(" ", anim->name, " (", anim->length, " sec, ", anim->tracks.size(), " tracks)"); } } -void OgreXmlSerializer::ReadAnimationTracks(Animation *dest) -{ +void OgreXmlSerializer::ReadAnimationTracks(Animation *dest) { NextNode(); - while(m_currentNodeName == nnTrack) - { + while (m_currentNodeName == nnTrack) { VertexAnimationTrack track; track.type = VertexAnimationTrack::VAT_TRANSFORM; track.boneName = ReadAttribute("bone"); @@ -826,27 +714,21 @@ void OgreXmlSerializer::ReadAnimationTracks(Animation *dest) } } -void OgreXmlSerializer::ReadAnimationKeyFrames(Animation *anim, VertexAnimationTrack *dest) -{ +void OgreXmlSerializer::ReadAnimationKeyFrames(Animation *anim, VertexAnimationTrack *dest) { const aiVector3D zeroVec(0.f, 0.f, 0.f); NextNode(); - while(m_currentNodeName == nnKeyFrame) - { + while (m_currentNodeName == nnKeyFrame) { TransformKeyFrame keyframe; keyframe.timePos = ReadAttribute("time"); NextNode(); - while(m_currentNodeName == nnTranslate || m_currentNodeName == nnRotate || m_currentNodeName == nnScale) - { - if (m_currentNodeName == nnTranslate) - { + while (m_currentNodeName == nnTranslate || m_currentNodeName == nnRotate || m_currentNodeName == nnScale) { + if (m_currentNodeName == nnTranslate) { keyframe.position.x = ReadAttribute(anX); keyframe.position.y = ReadAttribute(anY); keyframe.position.z = ReadAttribute(anZ); - } - else if (m_currentNodeName == nnRotate) - { + } else if (m_currentNodeName == nnRotate) { float angle = ReadAttribute("angle"); if (NextNode() != nnAxis) { @@ -857,17 +739,14 @@ void OgreXmlSerializer::ReadAnimationKeyFrames(Animation *anim, VertexAnimationT axis.x = ReadAttribute(anX); axis.y = ReadAttribute(anY); axis.z = ReadAttribute(anZ); - if (axis.Equal(zeroVec)) - { + if (axis.Equal(zeroVec)) { axis.x = 1.0f; if (angle != 0) { ASSIMP_LOG_WARN_F("Found invalid a key frame with a zero rotation axis in animation: ", anim->name); } } keyframe.rotation = aiQuaternion(axis, angle); - } - else if (m_currentNodeName == nnScale) - { + } else if (m_currentNodeName == nnScale) { keyframe.scale.x = ReadAttribute(anX); keyframe.scale.y = ReadAttribute(anY); keyframe.scale.z = ReadAttribute(anZ); @@ -880,14 +759,12 @@ void OgreXmlSerializer::ReadAnimationKeyFrames(Animation *anim, VertexAnimationT } } -void OgreXmlSerializer::ReadBoneHierarchy(Skeleton *skeleton) -{ +void OgreXmlSerializer::ReadBoneHierarchy(Skeleton *skeleton) { if (skeleton->bones.empty()) { throw DeadlyImportError("Cannot read for a Skeleton without bones"); } - while(NextNode() == nnBoneParent) - { + while (NextNode() == nnBoneParent) { const std::string name = ReadAttribute("bone"); const std::string parentName = ReadAttribute("parent"); @@ -901,46 +778,38 @@ void OgreXmlSerializer::ReadBoneHierarchy(Skeleton *skeleton) } // Calculate bone matrices for root bones. Recursively calculates their children. - for (size_t i=0, len=skeleton->bones.size(); ibones.size(); i < len; ++i) { Bone *bone = skeleton->bones[i]; if (!bone->IsParented()) bone->CalculateWorldMatrixAndDefaultPose(skeleton); } } -static bool BoneCompare(Bone *a, Bone *b) -{ - ai_assert( nullptr != a ); - ai_assert( nullptr != b ); - +static bool BoneCompare(Bone *a, Bone *b) { + ai_assert(nullptr != a); + ai_assert(nullptr != b); + return (a->id < b->id); } -void OgreXmlSerializer::ReadBones(Skeleton *skeleton) -{ +void OgreXmlSerializer::ReadBones(Skeleton *skeleton) { ASSIMP_LOG_DEBUG(" - Bones"); NextNode(); - while(m_currentNodeName == nnBone) - { + while (m_currentNodeName == nnBone) { Bone *bone = new Bone(); bone->id = ReadAttribute("id"); bone->name = ReadAttribute("name"); NextNode(); - while(m_currentNodeName == nnPosition || - m_currentNodeName == nnRotation || - m_currentNodeName == nnScale) - { - if (m_currentNodeName == nnPosition) - { + while (m_currentNodeName == nnPosition || + m_currentNodeName == nnRotation || + m_currentNodeName == nnScale) { + if (m_currentNodeName == nnPosition) { bone->position.x = ReadAttribute(anX); bone->position.y = ReadAttribute(anY); bone->position.z = ReadAttribute(anZ); - } - else if (m_currentNodeName == nnRotation) - { + } else if (m_currentNodeName == nnRotation) { float angle = ReadAttribute("angle"); if (NextNode() != nnAxis) { @@ -953,17 +822,12 @@ void OgreXmlSerializer::ReadBones(Skeleton *skeleton) axis.z = ReadAttribute(anZ); bone->rotation = aiQuaternion(axis, angle); - } - else if (m_currentNodeName == nnScale) - { + } else if (m_currentNodeName == nnScale) { /// @todo Implement taking scale into account in matrix/pose calculations! - if (HasAttribute("factor")) - { + if (HasAttribute("factor")) { float factor = ReadAttribute("factor"); bone->scale.Set(factor, factor, factor); - } - else - { + } else { if (HasAttribute(anX)) bone->scale.x = ReadAttribute(anX); if (HasAttribute(anY)) @@ -985,10 +849,9 @@ void OgreXmlSerializer::ReadBones(Skeleton *skeleton) // Validate that bone indexes are not skipped. /** @note Left this from original authors code, but not sure if this is strictly necessary as per the Ogre skeleton spec. It might be more that other (later) code in this imported does not break. */ - for (size_t i=0, len=skeleton->bones.size(); ibones.size(); i < len; ++i) { Bone *b = skeleton->bones[i]; - ASSIMP_LOG_DEBUG_F( " ", b->id, " ", b->name); + ASSIMP_LOG_DEBUG_F(" ", b->id, " ", b->name); if (b->id != static_cast(i)) { throw DeadlyImportError(Formatter::format() << "Bone ids are not in sequence starting from 0. Missing index " << i); @@ -996,7 +859,7 @@ void OgreXmlSerializer::ReadBones(Skeleton *skeleton) } } -} // Ogre -} // Assimp +} // namespace Ogre +} // namespace Assimp #endif // ASSIMP_BUILD_NO_OGRE_IMPORTER diff --git a/code/OpenGEX/OpenGEXImporter.cpp b/code/OpenGEX/OpenGEXImporter.cpp index 4ee746716..bfdf144aa 100644 --- a/code/OpenGEX/OpenGEXImporter.cpp +++ b/code/OpenGEX/OpenGEXImporter.cpp @@ -1212,8 +1212,8 @@ void OpenGEXImporter::resolveReferences() { if( RefInfo::MeshRef == currentRefInfo->m_type ) { for( size_t i = 0; i < currentRefInfo->m_Names.size(); ++i ) { const std::string &name( currentRefInfo->m_Names[ i ] ); - ReferenceMap::const_iterator it( m_mesh2refMap.find( name ) ); - if( m_mesh2refMap.end() != it ) { + ReferenceMap::const_iterator curIt( m_mesh2refMap.find( name ) ); + if (m_mesh2refMap.end() != curIt) { unsigned int meshIdx = static_cast(m_mesh2refMap[ name ]); node->mMeshes[ i ] = meshIdx; } @@ -1221,8 +1221,8 @@ void OpenGEXImporter::resolveReferences() { } else if( RefInfo::MaterialRef == currentRefInfo->m_type ) { for ( size_t i = 0; i < currentRefInfo->m_Names.size(); ++i ) { const std::string name( currentRefInfo->m_Names[ i ] ); - ReferenceMap::const_iterator it( m_material2refMap.find( name ) ); - if ( m_material2refMap.end() != it ) { + ReferenceMap::const_iterator curIt(m_material2refMap.find(name)); + if (m_material2refMap.end() != curIt) { if ( nullptr != m_currentMesh ) { unsigned int matIdx = static_cast< unsigned int >( m_material2refMap[ name ] ); if ( m_currentMesh->mMaterialIndex != 0 ) { diff --git a/code/Ply/PlyLoader.cpp b/code/Ply/PlyLoader.cpp index cd52b74f2..02c7c2caa 100644 --- a/code/Ply/PlyLoader.cpp +++ b/code/Ply/PlyLoader.cpp @@ -49,10 +49,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // internal headers #include "PlyLoader.h" #include -#include -#include -#include #include +#include +#include +#include using namespace ::Assimp; @@ -69,29 +69,25 @@ static const aiImporterDesc desc = { "ply" }; - // ------------------------------------------------------------------------------------------------ // Internal stuff namespace { - // ------------------------------------------------------------------------------------------------ - // Checks that property index is within range - template - inline - const T &GetProperty(const std::vector &props, int idx) { - if (static_cast(idx) >= props.size()) { - throw DeadlyImportError("Invalid .ply file: Property index is out of range."); - } - - return props[idx]; +// ------------------------------------------------------------------------------------------------ +// Checks that property index is within range +template +inline const T &GetProperty(const std::vector &props, int idx) { + if (static_cast(idx) >= props.size()) { + throw DeadlyImportError("Invalid .ply file: Property index is out of range."); } + + return props[idx]; } +} // namespace // ------------------------------------------------------------------------------------------------ // Constructor to be privately used by Importer -PLYImporter::PLYImporter() -: mBuffer(nullptr) -, pcDOM(nullptr) -, mGeneratedMesh(nullptr) { +PLYImporter::PLYImporter() : + mBuffer(nullptr), pcDOM(nullptr), mGeneratedMesh(nullptr) { // empty } @@ -103,16 +99,16 @@ PLYImporter::~PLYImporter() { // ------------------------------------------------------------------------------------------------ // Returns whether the class can handle the format of the given file. -bool PLYImporter::CanRead(const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const { +bool PLYImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const { const std::string extension = GetExtension(pFile); - if ( extension == "ply" ) { + if (extension == "ply") { return true; } else if (!extension.length() || checkSig) { - if ( !pIOHandler ) { + if (!pIOHandler) { return true; } - static const char* tokens[] = { "ply" }; + static const char *tokens[] = { "ply" }; return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 1); } @@ -120,19 +116,19 @@ bool PLYImporter::CanRead(const std::string& pFile, IOSystem* pIOHandler, bool c } // ------------------------------------------------------------------------------------------------ -const aiImporterDesc* PLYImporter::GetInfo() const { +const aiImporterDesc *PLYImporter::GetInfo() const { return &desc; } // ------------------------------------------------------------------------------------------------ -static bool isBigEndian(const char* szMe) { +static bool isBigEndian(const char *szMe) { ai_assert(nullptr != szMe); // binary_little_endian // binary_big_endian bool isBigEndian(false); #if (defined AI_BUILD_BIG_ENDIAN) - if ( 'l' == *szMe || 'L' == *szMe ) { + if ('l' == *szMe || 'L' == *szMe) { isBigEndian = true; } #else @@ -146,7 +142,7 @@ static bool isBigEndian(const char* szMe) { // ------------------------------------------------------------------------------------------------ // Imports the given file into the given scene structure. -void PLYImporter::InternReadFile(const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) { +void PLYImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) { const std::string mode = "rb"; std::unique_ptr fileStream(pIOHandler->Open(pFile, mode)); if (!fileStream.get()) { @@ -154,8 +150,8 @@ void PLYImporter::InternReadFile(const std::string& pFile, aiScene* pScene, IOSy } // Get the file-size - const size_t fileSize( fileStream->FileSize() ); - if ( 0 == fileSize ) { + const size_t fileSize(fileStream->FileSize()); + if (0 == fileSize) { throw DeadlyImportError("File " + pFile + " is empty."); } @@ -169,28 +165,28 @@ void PLYImporter::InternReadFile(const std::string& pFile, aiScene* pScene, IOSy if ((headerCheck.size() < 3) || (headerCheck[0] != 'P' && headerCheck[0] != 'p') || (headerCheck[1] != 'L' && headerCheck[1] != 'l') || - (headerCheck[2] != 'Y' && headerCheck[2] != 'y') ) { + (headerCheck[2] != 'Y' && headerCheck[2] != 'y')) { streamedBuffer.close(); throw DeadlyImportError("Invalid .ply file: Magic number \'ply\' is no there"); } std::vector mBuffer2; streamedBuffer.getNextLine(mBuffer2); - mBuffer = (unsigned char*)&mBuffer2[0]; + mBuffer = (unsigned char *)&mBuffer2[0]; - char* szMe = (char*)&this->mBuffer[0]; - SkipSpacesAndLineEnd(szMe, (const char**)&szMe); + char *szMe = (char *)&this->mBuffer[0]; + SkipSpacesAndLineEnd(szMe, (const char **)&szMe); // determine the format of the file data and construct the aiMesh - PLY::DOM sPlyDom; + PLY::DOM sPlyDom; this->pcDOM = &sPlyDom; if (TokenMatch(szMe, "format", 6)) { if (TokenMatch(szMe, "ascii", 5)) { - SkipLine(szMe, (const char**)&szMe); + SkipLine(szMe, (const char **)&szMe); if (!PLY::DOM::ParseInstance(streamedBuffer, &sPlyDom, this)) { if (mGeneratedMesh != nullptr) { - delete(mGeneratedMesh); + delete (mGeneratedMesh); mGeneratedMesh = nullptr; } @@ -204,7 +200,7 @@ void PLYImporter::InternReadFile(const std::string& pFile, aiScene* pScene, IOSy // skip the line, parse the rest of the header and build the DOM if (!PLY::DOM::ParseInstanceBinary(streamedBuffer, &sPlyDom, this, bIsBE)) { if (mGeneratedMesh != nullptr) { - delete(mGeneratedMesh); + delete (mGeneratedMesh); mGeneratedMesh = nullptr; } @@ -213,7 +209,7 @@ void PLYImporter::InternReadFile(const std::string& pFile, aiScene* pScene, IOSy } } else { if (mGeneratedMesh != nullptr) { - delete(mGeneratedMesh); + delete (mGeneratedMesh); mGeneratedMesh = nullptr; } @@ -223,7 +219,7 @@ void PLYImporter::InternReadFile(const std::string& pFile, aiScene* pScene, IOSy } else { AI_DEBUG_INVALIDATE_PTR(this->mBuffer); if (mGeneratedMesh != nullptr) { - delete(mGeneratedMesh); + delete (mGeneratedMesh); mGeneratedMesh = nullptr; } @@ -242,24 +238,24 @@ void PLYImporter::InternReadFile(const std::string& pFile, aiScene* pScene, IOSy // list is containing a list of points bool pointsOnly = mGeneratedMesh->mFaces == nullptr ? true : false; if (pointsOnly) { - mGeneratedMesh->mPrimitiveTypes = aiPrimitiveType::aiPrimitiveType_POINT; + mGeneratedMesh->mPrimitiveTypes = aiPrimitiveType::aiPrimitiveType_POINT; } // now load a list of all materials - std::vector avMaterials; + std::vector avMaterials; std::string defaultTexture; LoadMaterial(&avMaterials, defaultTexture, pointsOnly); // now generate the output scene object. Fill the material list pScene->mNumMaterials = (unsigned int)avMaterials.size(); - pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials]; + pScene->mMaterials = new aiMaterial *[pScene->mNumMaterials]; for (unsigned int i = 0; i < pScene->mNumMaterials; ++i) { pScene->mMaterials[i] = avMaterials[i]; } // fill the mesh list pScene->mNumMeshes = 1; - pScene->mMeshes = new aiMesh*[pScene->mNumMeshes]; + pScene->mMeshes = new aiMesh *[pScene->mNumMeshes]; pScene->mMeshes[0] = mGeneratedMesh; mGeneratedMesh = nullptr; @@ -273,7 +269,7 @@ void PLYImporter::InternReadFile(const std::string& pFile, aiScene* pScene, IOSy } } -void PLYImporter::LoadVertex(const PLY::Element* pcElement, const PLY::ElementInstance* instElement, unsigned int pos) { +void PLYImporter::LoadVertex(const PLY::Element *pcElement, const PLY::ElementInstance *instElement, unsigned int pos) { ai_assert(nullptr != pcElement); ai_assert(nullptr != instElement); @@ -290,8 +286,8 @@ void PLYImporter::LoadVertex(const PLY::Element* pcElement, const PLY::ElementIn PLY::EDataType aiTexcoordTypes[2] = { EDT_Char, EDT_Char }; // now check whether which normal components are available - unsigned int _a( 0 ), cnt( 0 ); - for ( std::vector::const_iterator a = pcElement->alProperties.begin(); + unsigned int _a(0), cnt(0); + for (std::vector::const_iterator a = pcElement->alProperties.begin(); a != pcElement->alProperties.end(); ++a, ++_a) { if ((*a).bIsList) { continue; @@ -358,17 +354,17 @@ void PLYImporter::LoadVertex(const PLY::Element* pcElement, const PLY::ElementIn aiVector3D vOut; if (0xFFFFFFFF != aiPositions[0]) { vOut.x = PLY::PropertyInstance::ConvertTo( - GetProperty(instElement->alProperties, aiPositions[0]).avList.front(), aiTypes[0]); + GetProperty(instElement->alProperties, aiPositions[0]).avList.front(), aiTypes[0]); } if (0xFFFFFFFF != aiPositions[1]) { vOut.y = PLY::PropertyInstance::ConvertTo( - GetProperty(instElement->alProperties, aiPositions[1]).avList.front(), aiTypes[1]); + GetProperty(instElement->alProperties, aiPositions[1]).avList.front(), aiTypes[1]); } if (0xFFFFFFFF != aiPositions[2]) { vOut.z = PLY::PropertyInstance::ConvertTo( - GetProperty(instElement->alProperties, aiPositions[2]).avList.front(), aiTypes[2]); + GetProperty(instElement->alProperties, aiPositions[2]).avList.front(), aiTypes[2]); } // Normals @@ -376,19 +372,19 @@ void PLYImporter::LoadVertex(const PLY::Element* pcElement, const PLY::ElementIn bool haveNormal = false; if (0xFFFFFFFF != aiNormal[0]) { nOut.x = PLY::PropertyInstance::ConvertTo( - GetProperty(instElement->alProperties, aiNormal[0]).avList.front(), aiNormalTypes[0]); + GetProperty(instElement->alProperties, aiNormal[0]).avList.front(), aiNormalTypes[0]); haveNormal = true; } if (0xFFFFFFFF != aiNormal[1]) { nOut.y = PLY::PropertyInstance::ConvertTo( - GetProperty(instElement->alProperties, aiNormal[1]).avList.front(), aiNormalTypes[1]); + GetProperty(instElement->alProperties, aiNormal[1]).avList.front(), aiNormalTypes[1]); haveNormal = true; } if (0xFFFFFFFF != aiNormal[2]) { nOut.z = PLY::PropertyInstance::ConvertTo( - GetProperty(instElement->alProperties, aiNormal[2]).avList.front(), aiNormalTypes[2]); + GetProperty(instElement->alProperties, aiNormal[2]).avList.front(), aiNormalTypes[2]); haveNormal = true; } @@ -397,19 +393,25 @@ void PLYImporter::LoadVertex(const PLY::Element* pcElement, const PLY::ElementIn bool haveColor = false; if (0xFFFFFFFF != aiColors[0]) { cOut.r = NormalizeColorValue(GetProperty(instElement->alProperties, - aiColors[0]).avList.front(), aiColorsTypes[0]); + aiColors[0]) + .avList.front(), + aiColorsTypes[0]); haveColor = true; } if (0xFFFFFFFF != aiColors[1]) { cOut.g = NormalizeColorValue(GetProperty(instElement->alProperties, - aiColors[1]).avList.front(), aiColorsTypes[1]); + aiColors[1]) + .avList.front(), + aiColorsTypes[1]); haveColor = true; } if (0xFFFFFFFF != aiColors[2]) { cOut.b = NormalizeColorValue(GetProperty(instElement->alProperties, - aiColors[2]).avList.front(), aiColorsTypes[2]); + aiColors[2]) + .avList.front(), + aiColorsTypes[2]); haveColor = true; } @@ -418,7 +420,9 @@ void PLYImporter::LoadVertex(const PLY::Element* pcElement, const PLY::ElementIn cOut.a = 1.0; } else { cOut.a = NormalizeColorValue(GetProperty(instElement->alProperties, - aiColors[3]).avList.front(), aiColorsTypes[3]); + aiColors[3]) + .avList.front(), + aiColorsTypes[3]); haveColor = true; } @@ -429,18 +433,18 @@ void PLYImporter::LoadVertex(const PLY::Element* pcElement, const PLY::ElementIn bool haveTextureCoords = false; if (0xFFFFFFFF != aiTexcoord[0]) { tOut.x = PLY::PropertyInstance::ConvertTo( - GetProperty(instElement->alProperties, aiTexcoord[0]).avList.front(), aiTexcoordTypes[0]); + GetProperty(instElement->alProperties, aiTexcoord[0]).avList.front(), aiTexcoordTypes[0]); haveTextureCoords = true; } if (0xFFFFFFFF != aiTexcoord[1]) { tOut.y = PLY::PropertyInstance::ConvertTo( - GetProperty(instElement->alProperties, aiTexcoord[1]).avList.front(), aiTexcoordTypes[1]); + GetProperty(instElement->alProperties, aiTexcoord[1]).avList.front(), aiTexcoordTypes[1]); haveTextureCoords = true; } //create aiMesh if needed - if ( nullptr == mGeneratedMesh ) { + if (nullptr == mGeneratedMesh) { mGeneratedMesh = new aiMesh(); mGeneratedMesh->mMaterialIndex = 0; } @@ -474,7 +478,6 @@ void PLYImporter::LoadVertex(const PLY::Element* pcElement, const PLY::ElementIn } } - // ------------------------------------------------------------------------------------------------ // Convert a color component to [0...1] ai_real PLYImporter::NormalizeColorValue(PLY::PropertyInstance::ValueUnion val, PLY::EDataType eType) { @@ -504,7 +507,7 @@ ai_real PLYImporter::NormalizeColorValue(PLY::PropertyInstance::ValueUnion val, // ------------------------------------------------------------------------------------------------ // Try to extract proper faces from the PLY DOM -void PLYImporter::LoadFace(const PLY::Element* pcElement, const PLY::ElementInstance* instElement, +void PLYImporter::LoadFace(const PLY::Element *pcElement, const PLY::ElementInstance *instElement, unsigned int pos) { ai_assert(nullptr != pcElement); ai_assert(nullptr != instElement); @@ -586,16 +589,16 @@ void PLYImporter::LoadFace(const PLY::Element* pcElement, const PLY::ElementInst mGeneratedMesh->mFaces[pos].mIndices = new unsigned int[iNum]; std::vector::const_iterator p = - GetProperty(instElement->alProperties, iProperty).avList.begin(); + GetProperty(instElement->alProperties, iProperty).avList.begin(); for (unsigned int a = 0; a < iNum; ++a, ++p) { mGeneratedMesh->mFaces[pos].mIndices[a] = PLY::PropertyInstance::ConvertTo(*p, eType); } } - // parse the material index - // cannot be handled without processing the whole file first - /*if (0xFFFFFFFF != iMaterialIndex) + // parse the material index + // cannot be handled without processing the whole file first + /*if (0xFFFFFFFF != iMaterialIndex) { mGeneratedMesh->mFaces[pos]. = PLY::PropertyInstance::ConvertTo( GetProperty(instElement->alProperties, iMaterialIndex).avList.front(), eType2); @@ -606,14 +609,14 @@ void PLYImporter::LoadFace(const PLY::Element* pcElement, const PLY::ElementInst //should be 6 coords std::vector::const_iterator p = - GetProperty(instElement->alProperties, iTextureCoord).avList.begin(); + GetProperty(instElement->alProperties, iTextureCoord).avList.begin(); if ((iNum / 3) == 2) // X Y coord { for (unsigned int a = 0; a < iNum; ++a, ++p) { unsigned int vindex = mGeneratedMesh->mFaces[pos].mIndices[a / 2]; if (vindex < mGeneratedMesh->mNumVertices) { - if (mGeneratedMesh->mTextureCoords[0] == nullptr ) { + if (mGeneratedMesh->mTextureCoords[0] == nullptr) { mGeneratedMesh->mNumUVComponents[0] = 2; mGeneratedMesh->mTextureCoords[0] = new aiVector3D[mGeneratedMesh->mNumVertices]; } @@ -633,11 +636,11 @@ void PLYImporter::LoadFace(const PLY::Element* pcElement, const PLY::ElementInst // normally we have only one triangle strip instance where // a value of -1 indicates a restart of the strip bool flip = false; - const std::vector& quak = GetProperty(instElement->alProperties, iProperty).avList; + const std::vector &quak = GetProperty(instElement->alProperties, iProperty).avList; //pvOut->reserve(pvOut->size() + quak.size() + (quak.size()>>2u)); //Limits memory consumption int aiTable[2] = { -1, -1 }; - for (std::vector::const_iterator a = quak.begin(); a != quak.end(); ++a) { + for (std::vector::const_iterator a = quak.begin(); a != quak.end(); ++a) { const int p = PLY::PropertyInstance::ConvertTo(*a, eType); if (-1 == p) { @@ -668,7 +671,7 @@ void PLYImporter::LoadFace(const PLY::Element* pcElement, const PLY::ElementInst // every second pass swap the indices. flip = !flip; - if ( flip ) { + if (flip) { std::swap(mGeneratedMesh->mFaces[pos].mIndices[0], mGeneratedMesh->mFaces[pos].mIndices[1]); } @@ -681,285 +684,254 @@ void PLYImporter::LoadFace(const PLY::Element* pcElement, const PLY::ElementInst // ------------------------------------------------------------------------------------------------ // Get a RGBA color in [0...1] range -void PLYImporter::GetMaterialColor(const std::vector& avList, - unsigned int aiPositions[4], - PLY::EDataType aiTypes[4], - aiColor4D* clrOut) -{ - ai_assert(NULL != clrOut); +void PLYImporter::GetMaterialColor(const std::vector &avList, + unsigned int aiPositions[4], + PLY::EDataType aiTypes[4], + aiColor4D *clrOut) { + ai_assert(NULL != clrOut); - if (0xFFFFFFFF == aiPositions[0])clrOut->r = 0.0f; - else - { - clrOut->r = NormalizeColorValue(GetProperty(avList, - aiPositions[0]).avList.front(), aiTypes[0]); - } + if (0xFFFFFFFF == aiPositions[0]) + clrOut->r = 0.0f; + else { + clrOut->r = NormalizeColorValue(GetProperty(avList, + aiPositions[0]) + .avList.front(), + aiTypes[0]); + } - if (0xFFFFFFFF == aiPositions[1])clrOut->g = 0.0f; - else - { - clrOut->g = NormalizeColorValue(GetProperty(avList, - aiPositions[1]).avList.front(), aiTypes[1]); - } + if (0xFFFFFFFF == aiPositions[1]) + clrOut->g = 0.0f; + else { + clrOut->g = NormalizeColorValue(GetProperty(avList, + aiPositions[1]) + .avList.front(), + aiTypes[1]); + } - if (0xFFFFFFFF == aiPositions[2])clrOut->b = 0.0f; - else - { - clrOut->b = NormalizeColorValue(GetProperty(avList, - aiPositions[2]).avList.front(), aiTypes[2]); - } + if (0xFFFFFFFF == aiPositions[2]) + clrOut->b = 0.0f; + else { + clrOut->b = NormalizeColorValue(GetProperty(avList, + aiPositions[2]) + .avList.front(), + aiTypes[2]); + } - // assume 1.0 for the alpha channel ifit is not set - if (0xFFFFFFFF == aiPositions[3])clrOut->a = 1.0f; - else - { - clrOut->a = NormalizeColorValue(GetProperty(avList, - aiPositions[3]).avList.front(), aiTypes[3]); - } + // assume 1.0 for the alpha channel ifit is not set + if (0xFFFFFFFF == aiPositions[3]) + clrOut->a = 1.0f; + else { + clrOut->a = NormalizeColorValue(GetProperty(avList, + aiPositions[3]) + .avList.front(), + aiTypes[3]); + } } // ------------------------------------------------------------------------------------------------ // Extract a material from the PLY DOM -void PLYImporter::LoadMaterial(std::vector* pvOut, std::string &defaultTexture, const bool pointsOnly) -{ - ai_assert(NULL != pvOut); +void PLYImporter::LoadMaterial(std::vector *pvOut, std::string &defaultTexture, const bool pointsOnly) { + ai_assert(NULL != pvOut); - // diffuse[4], specular[4], ambient[4] - // rgba order - unsigned int aaiPositions[3][4] = { + // diffuse[4], specular[4], ambient[4] + // rgba order + unsigned int aaiPositions[3][4] = { - { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF }, - { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF }, - { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF }, - }; + { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF }, + { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF }, + { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF }, + }; - PLY::EDataType aaiTypes[3][4] = { - { EDT_Char, EDT_Char, EDT_Char, EDT_Char }, - { EDT_Char, EDT_Char, EDT_Char, EDT_Char }, - { EDT_Char, EDT_Char, EDT_Char, EDT_Char } - }; - PLY::ElementInstanceList* pcList = NULL; + PLY::EDataType aaiTypes[3][4] = { + { EDT_Char, EDT_Char, EDT_Char, EDT_Char }, + { EDT_Char, EDT_Char, EDT_Char, EDT_Char }, + { EDT_Char, EDT_Char, EDT_Char, EDT_Char } + }; + PLY::ElementInstanceList *pcList = NULL; - unsigned int iPhong = 0xFFFFFFFF; - PLY::EDataType ePhong = EDT_Char; + unsigned int iPhong = 0xFFFFFFFF; + PLY::EDataType ePhong = EDT_Char; - unsigned int iOpacity = 0xFFFFFFFF; - PLY::EDataType eOpacity = EDT_Char; + unsigned int iOpacity = 0xFFFFFFFF; + PLY::EDataType eOpacity = EDT_Char; - // search in the DOM for a vertex entry - unsigned int _i = 0; - for (std::vector::const_iterator i = this->pcDOM->alElements.begin(); - i != this->pcDOM->alElements.end(); ++i, ++_i) - { - if (PLY::EEST_Material == (*i).eSemantic) - { - pcList = &this->pcDOM->alElementData[_i]; + // search in the DOM for a vertex entry + unsigned int _i = 0; + for (std::vector::const_iterator i = this->pcDOM->alElements.begin(); + i != this->pcDOM->alElements.end(); ++i, ++_i) { + if (PLY::EEST_Material == (*i).eSemantic) { + pcList = &this->pcDOM->alElementData[_i]; - // now check whether which coordinate sets are available - unsigned int _a = 0; - for (std::vector::const_iterator - a = (*i).alProperties.begin(); - a != (*i).alProperties.end(); ++a, ++_a) - { - if ((*a).bIsList)continue; + // now check whether which coordinate sets are available + unsigned int _a = 0; + for (std::vector::const_iterator + a = (*i).alProperties.begin(); + a != (*i).alProperties.end(); ++a, ++_a) { + if ((*a).bIsList) continue; - // pohng specularity ----------------------------------- - if (PLY::EST_PhongPower == (*a).Semantic) - { - iPhong = _a; - ePhong = (*a).eType; - } + // pohng specularity ----------------------------------- + if (PLY::EST_PhongPower == (*a).Semantic) { + iPhong = _a; + ePhong = (*a).eType; + } - // general opacity ----------------------------------- - if (PLY::EST_Opacity == (*a).Semantic) - { - iOpacity = _a; - eOpacity = (*a).eType; - } + // general opacity ----------------------------------- + if (PLY::EST_Opacity == (*a).Semantic) { + iOpacity = _a; + eOpacity = (*a).eType; + } - // diffuse color channels ----------------------------------- - if (PLY::EST_DiffuseRed == (*a).Semantic) - { - aaiPositions[0][0] = _a; - aaiTypes[0][0] = (*a).eType; + // diffuse color channels ----------------------------------- + if (PLY::EST_DiffuseRed == (*a).Semantic) { + aaiPositions[0][0] = _a; + aaiTypes[0][0] = (*a).eType; + } else if (PLY::EST_DiffuseGreen == (*a).Semantic) { + aaiPositions[0][1] = _a; + aaiTypes[0][1] = (*a).eType; + } else if (PLY::EST_DiffuseBlue == (*a).Semantic) { + aaiPositions[0][2] = _a; + aaiTypes[0][2] = (*a).eType; + } else if (PLY::EST_DiffuseAlpha == (*a).Semantic) { + aaiPositions[0][3] = _a; + aaiTypes[0][3] = (*a).eType; + } + // specular color channels ----------------------------------- + else if (PLY::EST_SpecularRed == (*a).Semantic) { + aaiPositions[1][0] = _a; + aaiTypes[1][0] = (*a).eType; + } else if (PLY::EST_SpecularGreen == (*a).Semantic) { + aaiPositions[1][1] = _a; + aaiTypes[1][1] = (*a).eType; + } else if (PLY::EST_SpecularBlue == (*a).Semantic) { + aaiPositions[1][2] = _a; + aaiTypes[1][2] = (*a).eType; + } else if (PLY::EST_SpecularAlpha == (*a).Semantic) { + aaiPositions[1][3] = _a; + aaiTypes[1][3] = (*a).eType; + } + // ambient color channels ----------------------------------- + else if (PLY::EST_AmbientRed == (*a).Semantic) { + aaiPositions[2][0] = _a; + aaiTypes[2][0] = (*a).eType; + } else if (PLY::EST_AmbientGreen == (*a).Semantic) { + aaiPositions[2][1] = _a; + aaiTypes[2][1] = (*a).eType; + } else if (PLY::EST_AmbientBlue == (*a).Semantic) { + aaiPositions[2][2] = _a; + aaiTypes[2][2] = (*a).eType; + } else if (PLY::EST_AmbientAlpha == (*a).Semantic) { + aaiPositions[2][3] = _a; + aaiTypes[2][3] = (*a).eType; + } + } + break; + } else if (PLY::EEST_TextureFile == (*i).eSemantic) { + defaultTexture = (*i).szName; } - else if (PLY::EST_DiffuseGreen == (*a).Semantic) - { - aaiPositions[0][1] = _a; - aaiTypes[0][1] = (*a).eType; - } - else if (PLY::EST_DiffuseBlue == (*a).Semantic) - { - aaiPositions[0][2] = _a; - aaiTypes[0][2] = (*a).eType; - } - else if (PLY::EST_DiffuseAlpha == (*a).Semantic) - { - aaiPositions[0][3] = _a; - aaiTypes[0][3] = (*a).eType; - } - // specular color channels ----------------------------------- - else if (PLY::EST_SpecularRed == (*a).Semantic) - { - aaiPositions[1][0] = _a; - aaiTypes[1][0] = (*a).eType; - } - else if (PLY::EST_SpecularGreen == (*a).Semantic) - { - aaiPositions[1][1] = _a; - aaiTypes[1][1] = (*a).eType; - } - else if (PLY::EST_SpecularBlue == (*a).Semantic) - { - aaiPositions[1][2] = _a; - aaiTypes[1][2] = (*a).eType; - } - else if (PLY::EST_SpecularAlpha == (*a).Semantic) - { - aaiPositions[1][3] = _a; - aaiTypes[1][3] = (*a).eType; - } - // ambient color channels ----------------------------------- - else if (PLY::EST_AmbientRed == (*a).Semantic) - { - aaiPositions[2][0] = _a; - aaiTypes[2][0] = (*a).eType; - } - else if (PLY::EST_AmbientGreen == (*a).Semantic) - { - aaiPositions[2][1] = _a; - aaiTypes[2][1] = (*a).eType; - } - else if (PLY::EST_AmbientBlue == (*a).Semantic) - { - aaiPositions[2][2] = _a; - aaiTypes[2][2] = (*a).eType; - } - else if (PLY::EST_AmbientAlpha == (*a).Semantic) - { - aaiPositions[2][3] = _a; - aaiTypes[2][3] = (*a).eType; - } - } - break; } - else if (PLY::EEST_TextureFile == (*i).eSemantic) - { - defaultTexture = (*i).szName; - } - } - // check whether we have a valid source for the material data - if (NULL != pcList) { - for (std::vector::const_iterator i = pcList->alInstances.begin(); i != pcList->alInstances.end(); ++i) { - aiColor4D clrOut; - aiMaterial* pcHelper = new aiMaterial(); + // check whether we have a valid source for the material data + if (NULL != pcList) { + for (std::vector::const_iterator i = pcList->alInstances.begin(); i != pcList->alInstances.end(); ++i) { + aiColor4D clrOut; + aiMaterial *pcHelper = new aiMaterial(); - // build the diffuse material color - GetMaterialColor((*i).alProperties, aaiPositions[0], aaiTypes[0], &clrOut); - pcHelper->AddProperty(&clrOut, 1, AI_MATKEY_COLOR_DIFFUSE); + // build the diffuse material color + GetMaterialColor((*i).alProperties, aaiPositions[0], aaiTypes[0], &clrOut); + pcHelper->AddProperty(&clrOut, 1, AI_MATKEY_COLOR_DIFFUSE); - // build the specular material color - GetMaterialColor((*i).alProperties, aaiPositions[1], aaiTypes[1], &clrOut); - pcHelper->AddProperty(&clrOut, 1, AI_MATKEY_COLOR_SPECULAR); + // build the specular material color + GetMaterialColor((*i).alProperties, aaiPositions[1], aaiTypes[1], &clrOut); + pcHelper->AddProperty(&clrOut, 1, AI_MATKEY_COLOR_SPECULAR); - // build the ambient material color - GetMaterialColor((*i).alProperties, aaiPositions[2], aaiTypes[2], &clrOut); - pcHelper->AddProperty(&clrOut, 1, AI_MATKEY_COLOR_AMBIENT); + // build the ambient material color + GetMaterialColor((*i).alProperties, aaiPositions[2], aaiTypes[2], &clrOut); + pcHelper->AddProperty(&clrOut, 1, AI_MATKEY_COLOR_AMBIENT); - // handle phong power and shading mode - int iMode = (int)aiShadingMode_Gouraud; - if (0xFFFFFFFF != iPhong) { - ai_real fSpec = PLY::PropertyInstance::ConvertTo(GetProperty((*i).alProperties, iPhong).avList.front(), ePhong); + // handle phong power and shading mode + int iMode = (int)aiShadingMode_Gouraud; + if (0xFFFFFFFF != iPhong) { + ai_real fSpec = PLY::PropertyInstance::ConvertTo(GetProperty((*i).alProperties, iPhong).avList.front(), ePhong); - // if shininess is 0 (and the pow() calculation would therefore always - // become 1, not depending on the angle), use gouraud lighting - if (fSpec) { - // scale this with 15 ... hopefully this is correct - fSpec *= 15; - pcHelper->AddProperty(&fSpec, 1, AI_MATKEY_SHININESS); + // if shininess is 0 (and the pow() calculation would therefore always + // become 1, not depending on the angle), use gouraud lighting + if (fSpec) { + // scale this with 15 ... hopefully this is correct + fSpec *= 15; + pcHelper->AddProperty(&fSpec, 1, AI_MATKEY_SHININESS); - iMode = (int)aiShadingMode_Phong; + iMode = (int)aiShadingMode_Phong; + } + } + pcHelper->AddProperty(&iMode, 1, AI_MATKEY_SHADING_MODEL); + + // handle opacity + if (0xFFFFFFFF != iOpacity) { + ai_real fOpacity = PLY::PropertyInstance::ConvertTo(GetProperty((*i).alProperties, iPhong).avList.front(), eOpacity); + pcHelper->AddProperty(&fOpacity, 1, AI_MATKEY_OPACITY); + } + + // The face order is absolutely undefined for PLY, so we have to + // use two-sided rendering to be sure it's ok. + const int two_sided = 1; + pcHelper->AddProperty(&two_sided, 1, AI_MATKEY_TWOSIDED); + + //default texture + if (!defaultTexture.empty()) { + const aiString name(defaultTexture.c_str()); + pcHelper->AddProperty(&name, _AI_MATKEY_TEXTURE_BASE, aiTextureType_DIFFUSE, 0); + } + + if (!pointsOnly) { + pcHelper->AddProperty(&two_sided, 1, AI_MATKEY_TWOSIDED); + } + + //set to wireframe, so when using this material info we can switch to points rendering + if (pointsOnly) { + const int wireframe = 1; + pcHelper->AddProperty(&wireframe, 1, AI_MATKEY_ENABLE_WIREFRAME); + } + + // add the newly created material instance to the list + pvOut->push_back(pcHelper); } - } - pcHelper->AddProperty(&iMode, 1, AI_MATKEY_SHADING_MODEL); + } else { + // generate a default material + aiMaterial *pcHelper = new aiMaterial(); - // handle opacity - if (0xFFFFFFFF != iOpacity) { - ai_real fOpacity = PLY::PropertyInstance::ConvertTo(GetProperty((*i).alProperties, iPhong).avList.front(), eOpacity); - pcHelper->AddProperty(&fOpacity, 1, AI_MATKEY_OPACITY); - } + // fill in a default material + int iMode = (int)aiShadingMode_Gouraud; + pcHelper->AddProperty(&iMode, 1, AI_MATKEY_SHADING_MODEL); - // The face order is absolutely undefined for PLY, so we have to - // use two-sided rendering to be sure it's ok. - const int two_sided = 1; - pcHelper->AddProperty(&two_sided, 1, AI_MATKEY_TWOSIDED); + //generate white material most 3D engine just multiply ambient / diffuse color with actual ambient / light color + aiColor3D clr; + clr.b = clr.g = clr.r = 1.0f; + pcHelper->AddProperty(&clr, 1, AI_MATKEY_COLOR_DIFFUSE); + pcHelper->AddProperty(&clr, 1, AI_MATKEY_COLOR_SPECULAR); - //default texture - if (!defaultTexture.empty()) - { - const aiString name(defaultTexture.c_str()); - pcHelper->AddProperty(&name, _AI_MATKEY_TEXTURE_BASE, aiTextureType_DIFFUSE, 0); - } + clr.b = clr.g = clr.r = 1.0f; + pcHelper->AddProperty(&clr, 1, AI_MATKEY_COLOR_AMBIENT); - if (!pointsOnly) - { - const int two_sided = 1; - pcHelper->AddProperty(&two_sided, 1, AI_MATKEY_TWOSIDED); - } + // The face order is absolutely undefined for PLY, so we have to + // use two-sided rendering to be sure it's ok. + if (!pointsOnly) { + const int two_sided = 1; + pcHelper->AddProperty(&two_sided, 1, AI_MATKEY_TWOSIDED); + } - //set to wireframe, so when using this material info we can switch to points rendering - if (pointsOnly) - { - const int wireframe = 1; - pcHelper->AddProperty(&wireframe, 1, AI_MATKEY_ENABLE_WIREFRAME); - } + //default texture + if (!defaultTexture.empty()) { + const aiString name(defaultTexture.c_str()); + pcHelper->AddProperty(&name, _AI_MATKEY_TEXTURE_BASE, aiTextureType_DIFFUSE, 0); + } - // add the newly created material instance to the list - pvOut->push_back(pcHelper); + //set to wireframe, so when using this material info we can switch to points rendering + if (pointsOnly) { + const int wireframe = 1; + pcHelper->AddProperty(&wireframe, 1, AI_MATKEY_ENABLE_WIREFRAME); + } + + pvOut->push_back(pcHelper); } - } - else - { - // generate a default material - aiMaterial* pcHelper = new aiMaterial(); - - // fill in a default material - int iMode = (int)aiShadingMode_Gouraud; - pcHelper->AddProperty(&iMode, 1, AI_MATKEY_SHADING_MODEL); - - //generate white material most 3D engine just multiply ambient / diffuse color with actual ambient / light color - aiColor3D clr; - clr.b = clr.g = clr.r = 1.0f; - pcHelper->AddProperty(&clr, 1, AI_MATKEY_COLOR_DIFFUSE); - pcHelper->AddProperty(&clr, 1, AI_MATKEY_COLOR_SPECULAR); - - clr.b = clr.g = clr.r = 1.0f; - pcHelper->AddProperty(&clr, 1, AI_MATKEY_COLOR_AMBIENT); - - // The face order is absolutely undefined for PLY, so we have to - // use two-sided rendering to be sure it's ok. - if (!pointsOnly) - { - const int two_sided = 1; - pcHelper->AddProperty(&two_sided, 1, AI_MATKEY_TWOSIDED); - } - - //default texture - if (!defaultTexture.empty()) - { - const aiString name(defaultTexture.c_str()); - pcHelper->AddProperty(&name, _AI_MATKEY_TEXTURE_BASE, aiTextureType_DIFFUSE, 0); - } - - //set to wireframe, so when using this material info we can switch to points rendering - if (pointsOnly) - { - const int wireframe = 1; - pcHelper->AddProperty(&wireframe, 1, AI_MATKEY_ENABLE_WIREFRAME); - } - - pvOut->push_back(pcHelper); - } } #endif // !! ASSIMP_BUILD_NO_PLY_IMPORTER diff --git a/code/PostProcessing/EmbedTexturesProcess.cpp b/code/PostProcessing/EmbedTexturesProcess.cpp index b187acf53..13906ab5f 100644 --- a/code/PostProcessing/EmbedTexturesProcess.cpp +++ b/code/PostProcessing/EmbedTexturesProcess.cpp @@ -137,7 +137,7 @@ bool EmbedTexturesProcess::addTexture(aiScene* pScene, std::string path) const { pTexture->pcData = imageContent; auto extension = path.substr(path.find_last_of('.') + 1u); - std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower); + std::transform(extension.begin(), extension.end(), extension.begin(), ToLower ); if (extension == "jpeg") { extension = "jpg"; } diff --git a/code/PostProcessing/TextureTransform.cpp b/code/PostProcessing/TextureTransform.cpp index f979f0f4d..b9d20fdbc 100644 --- a/code/PostProcessing/TextureTransform.cpp +++ b/code/PostProcessing/TextureTransform.cpp @@ -105,7 +105,8 @@ void TextureTransformStep::PreProcessUVTransform(STransformVecInfo& info) if (info.mRotation) { float out = info.mRotation; - if ((rounded = static_cast((info.mRotation / static_cast(AI_MATH_TWO_PI))))) + rounded = static_cast((info.mRotation / static_cast(AI_MATH_TWO_PI))); + if (rounded) { out -= rounded * static_cast(AI_MATH_PI); ASSIMP_LOG_INFO_F("Texture coordinate rotation ", info.mRotation, " can be simplified to ", out); diff --git a/code/Q3D/Q3DLoader.cpp b/code/Q3D/Q3DLoader.cpp index f68d2ac32..06894bfe2 100644 --- a/code/Q3D/Q3DLoader.cpp +++ b/code/Q3D/Q3DLoader.cpp @@ -517,8 +517,8 @@ outer: for (FaceIdxArray::const_iterator it = fidx[i].begin(),end = fidx[i].end(); it != end; ++it, ++faces) { - Mesh& m = meshes[(*it).first]; - Face& face = m.faces[(*it).second]; + Mesh& curMesh = meshes[(*it).first]; + Face &face = curMesh.faces[(*it).second]; faces->mNumIndices = (unsigned int)face.indices.size(); faces->mIndices = new unsigned int [faces->mNumIndices]; @@ -528,29 +528,30 @@ outer: for (unsigned int n = 0; n < faces->mNumIndices;++n, ++cnt, ++norms, ++verts) { - if (face.indices[n] >= m.verts.size()) + if (face.indices[n] >= curMesh.verts.size()) { ASSIMP_LOG_WARN("Quick3D: Vertex index overflow"); face.indices[n] = 0; } // copy vertices - *verts = m.verts[ face.indices[n] ]; + *verts = curMesh.verts[face.indices[n]]; - if (face.indices[n] >= m.normals.size() && faces->mNumIndices >= 3) + if (face.indices[n] >= curMesh.normals.size() && faces->mNumIndices >= 3) { // we have no normal here - assign the face normal if (!fnOK) { - const aiVector3D& pV1 = m.verts[ face.indices[0] ]; - const aiVector3D& pV2 = m.verts[ face.indices[1] ]; - const aiVector3D& pV3 = m.verts[ face.indices.size() - 1 ]; + const aiVector3D &pV1 = curMesh.verts[face.indices[0]]; + const aiVector3D &pV2 = curMesh.verts[face.indices[1]]; + const aiVector3D &pV3 = curMesh.verts[face.indices.size() - 1]; faceNormal = (pV2 - pV1) ^ (pV3 - pV1).Normalize(); fnOK = true; } *norms = faceNormal; + } else { + *norms = curMesh.normals[face.indices[n]]; } - else *norms = m.normals[ face.indices[n] ]; // copy texture coordinates if (uv && m.uv.size()) diff --git a/code/Step/STEPFile.h b/code/Step/STEPFile.h index 040a4fa21..6ab7d1035 100644 --- a/code/Step/STEPFile.h +++ b/code/Step/STEPFile.h @@ -44,33 +44,36 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define INCLUDED_AI_STEPFILE_H #include +#include #include +#include #include #include -#include -#include #include "FBX/FBXDocument.h" //ObjectMap::value_type #include +#pragma warning( push ) +#pragma warning( disable : 4456 ) +#pragma warning(disable : 4245) // #if _MSC_VER > 1500 || (defined __GNUC___) -# define ASSIMP_STEP_USE_UNORDERED_MULTIMAP +#define ASSIMP_STEP_USE_UNORDERED_MULTIMAP #else -# define step_unordered_map map -# define step_unordered_multimap multimap +#define step_unordered_map map +#define step_unordered_multimap multimap #endif #ifdef ASSIMP_STEP_USE_UNORDERED_MULTIMAP -# include -# if _MSC_VER > 1600 -# define step_unordered_map unordered_map -# define step_unordered_multimap unordered_multimap -# else -# define step_unordered_map tr1::unordered_map -# define step_unordered_multimap tr1::unordered_multimap -# endif +#include +#if _MSC_VER > 1600 +#define step_unordered_map unordered_map +#define step_unordered_multimap unordered_multimap +#else +#define step_unordered_map tr1::unordered_map +#define step_unordered_multimap tr1::unordered_multimap +#endif #endif #include @@ -86,931 +89,873 @@ namespace Assimp { // ******************************************************************************** // before things get complicated, this is the basic outline: - namespace STEP { - namespace EXPRESS { +namespace EXPRESS { - // base data types known by EXPRESS schemata - any custom data types will derive one of those - class DataType; - class UNSET; /*: public DataType */ - class ISDERIVED; /*: public DataType */ - // class REAL; /*: public DataType */ - class ENUM; /*: public DataType */ - // class STRING; /*: public DataType */ - // class INTEGER; /*: public DataType */ - class ENTITY; /*: public DataType */ - class LIST; /*: public DataType */ - // class SELECT; /*: public DataType */ +// base data types known by EXPRESS schemata - any custom data types will derive one of those +class DataType; +class UNSET; /*: public DataType */ +class ISDERIVED; /*: public DataType */ +// class REAL; /*: public DataType */ +class ENUM; /*: public DataType */ +// class STRING; /*: public DataType */ +// class INTEGER; /*: public DataType */ +class ENTITY; /*: public DataType */ +class LIST; /*: public DataType */ +// class SELECT; /*: public DataType */ - // a conversion schema is not exactly an EXPRESS schema, rather it - // is a list of pointers to conversion functions to build up the - // object tree from an input file. - class ConversionSchema; - } +// a conversion schema is not exactly an EXPRESS schema, rather it +// is a list of pointers to conversion functions to build up the +// object tree from an input file. +class ConversionSchema; +} // namespace EXPRESS - struct HeaderInfo; - class Object; - class LazyObject; - class DB; +struct HeaderInfo; +class Object; +class LazyObject; +class DB; - - typedef Object* (*ConvertObjectProc)(const DB& db, const EXPRESS::LIST& params); -} +typedef Object *(*ConvertObjectProc)(const DB &db, const EXPRESS::LIST ¶ms); +} // namespace STEP // ******************************************************************************** namespace STEP { - // ------------------------------------------------------------------------------- - /** Exception class used by the STEP loading & parsing code. It is typically +// ------------------------------------------------------------------------------- +/** Exception class used by the STEP loading & parsing code. It is typically * coupled with a line number. */ - // ------------------------------------------------------------------------------- - struct SyntaxError : DeadlyImportError { - enum { - LINE_NOT_SPECIFIED = 0xffffffffffffffffLL - }; - - SyntaxError (const std::string& s,uint64_t line = LINE_NOT_SPECIFIED); +// ------------------------------------------------------------------------------- +struct SyntaxError : DeadlyImportError { + enum { + LINE_NOT_SPECIFIED = 0xffffffffffffffffLL }; + SyntaxError(const std::string &s, uint64_t line = LINE_NOT_SPECIFIED); +}; - // ------------------------------------------------------------------------------- - /** Exception class used by the STEP loading & parsing code when a type +// ------------------------------------------------------------------------------- +/** Exception class used by the STEP loading & parsing code when a type * error (i.e. an entity expects a string but receives a bool) occurs. * It is typically coupled with both an entity id and a line number.*/ - // ------------------------------------------------------------------------------- - struct TypeError : DeadlyImportError { - enum { - ENTITY_NOT_SPECIFIED = 0xffffffffffffffffLL, - ENTITY_NOT_SPECIFIED_32 = 0x00000000ffffffff - }; - - TypeError (const std::string& s,uint64_t entity = ENTITY_NOT_SPECIFIED, uint64_t line = SyntaxError::LINE_NOT_SPECIFIED); +// ------------------------------------------------------------------------------- +struct TypeError : DeadlyImportError { + enum { + ENTITY_NOT_SPECIFIED = 0xffffffffffffffffLL, + ENTITY_NOT_SPECIFIED_32 = 0x00000000ffffffff }; + TypeError(const std::string &s, uint64_t entity = ENTITY_NOT_SPECIFIED, uint64_t line = SyntaxError::LINE_NOT_SPECIFIED); +}; - // hack to make a given member template-dependent - template - T2& Couple(T2& in) { - return in; +// hack to make a given member template-dependent +template +T2 &Couple(T2 &in) { + return in; +} + +namespace EXPRESS { + +// ------------------------------------------------------------------------------- +//** Base class for all STEP data types */ +// ------------------------------------------------------------------------------- +class DataType { +public: + typedef std::shared_ptr Out; + +public: + virtual ~DataType() { } +public: + template + const T &To() const { + return dynamic_cast(*this); + } - namespace EXPRESS { + template + T &To() { + return dynamic_cast(*this); + } - // ------------------------------------------------------------------------------- - //** Base class for all STEP data types */ - // ------------------------------------------------------------------------------- - class DataType - { - public: - typedef std::shared_ptr Out; + template + const T *ToPtr() const { + return dynamic_cast(this); + } - public: + template + T *ToPtr() { + return dynamic_cast(this); + } - virtual ~DataType() { - } + // utilities to deal with SELECT entities, which currently lack automatic + // conversion support. + template + const T &ResolveSelect(const DB &db) const { + return Couple(db).MustGetObject(To())->template To(); + } - public: + template + const T *ResolveSelectPtr(const DB &db) const { + const EXPRESS::ENTITY *e = ToPtr(); + return e ? Couple(db).MustGetObject(*e)->template ToPtr() : (const T *)0; + } - template - const T& To() const { - return dynamic_cast(*this); - } - - template - T& To() { - return dynamic_cast(*this); - } - - - template - const T* ToPtr() const { - return dynamic_cast(this); - } - - template - T* ToPtr() { - return dynamic_cast(this); - } - - // utilities to deal with SELECT entities, which currently lack automatic - // conversion support. - template - const T& ResolveSelect(const DB& db) const { - return Couple(db).MustGetObject(To())->template To(); - } - - template - const T* ResolveSelectPtr(const DB& db) const { - const EXPRESS::ENTITY* e = ToPtr(); - return e?Couple(db).MustGetObject(*e)->template ToPtr():(const T*)0; - } - - public: - - /** parse a variable from a string and set 'inout' to the character +public: + /** parse a variable from a string and set 'inout' to the character * behind the last consumed character. An optional schema enables, * if specified, automatic conversion of custom data types. * * @throw SyntaxError */ - static std::shared_ptr Parse(const char*& inout, - uint64_t line = SyntaxError::LINE_NOT_SPECIFIED, - const EXPRESS::ConversionSchema* schema = NULL); + static std::shared_ptr Parse(const char *&inout, + uint64_t line = SyntaxError::LINE_NOT_SPECIFIED, + const EXPRESS::ConversionSchema *schema = NULL); - public: - }; +public: +}; - typedef DataType SELECT; - typedef DataType LOGICAL; +typedef DataType SELECT; +typedef DataType LOGICAL; - // ------------------------------------------------------------------------------- - /** Sentinel class to represent explicitly unset (optional) fields ($) */ - // ------------------------------------------------------------------------------- - class UNSET : public DataType - { - public: - private: - }; +// ------------------------------------------------------------------------------- +/** Sentinel class to represent explicitly unset (optional) fields ($) */ +// ------------------------------------------------------------------------------- +class UNSET : public DataType { +public: +private: +}; - // ------------------------------------------------------------------------------- - /** Sentinel class to represent explicitly derived fields (*) */ - // ------------------------------------------------------------------------------- - class ISDERIVED : public DataType - { - public: - private: - }; +// ------------------------------------------------------------------------------- +/** Sentinel class to represent explicitly derived fields (*) */ +// ------------------------------------------------------------------------------- +class ISDERIVED : public DataType { +public: +private: +}; - // ------------------------------------------------------------------------------- - /** Shared implementation for some of the primitive data type, i.e. int, float */ - // ------------------------------------------------------------------------------- - template - class PrimitiveDataType : public DataType - { - public: +// ------------------------------------------------------------------------------- +/** Shared implementation for some of the primitive data type, i.e. int, float */ +// ------------------------------------------------------------------------------- +template +class PrimitiveDataType : public DataType { +public: + // This is the type that will cd ultimatively be used to + // expose this data type to the user. + typedef T Out; - // This is the type that will cd ultimatively be used to - // expose this data type to the user. - typedef T Out; + PrimitiveDataType() {} + PrimitiveDataType(const T &val) : + val(val) {} - public: + PrimitiveDataType(const PrimitiveDataType &o) { + (*this) = o; + } - PrimitiveDataType() {} - PrimitiveDataType(const T& val) - : val(val) - {} + operator const T &() const { + return val; + } - PrimitiveDataType(const PrimitiveDataType& o) { - (*this) = o; - } + PrimitiveDataType &operator=(const PrimitiveDataType &o) { + val = o.val; + return *this; + } +protected: + T val; +}; - public: +typedef PrimitiveDataType INTEGER; +typedef PrimitiveDataType REAL; +typedef PrimitiveDataType NUMBER; +typedef PrimitiveDataType STRING; - operator const T& () const { - return val; - } +// ------------------------------------------------------------------------------- +/** Generic base class for all enumerated types */ +// ------------------------------------------------------------------------------- +class ENUMERATION : public STRING { +public: + ENUMERATION(const std::string &val) : + STRING(val) {} - PrimitiveDataType& operator=(const PrimitiveDataType& o) { - val = o.val; - return *this; - } +private: +}; - protected: - T val; +typedef ENUMERATION BOOLEAN; - }; +// ------------------------------------------------------------------------------- +/** This is just a reference to an entity/object somewhere else */ +// ------------------------------------------------------------------------------- +class ENTITY : public PrimitiveDataType { +public: + ENTITY(uint64_t val) : + PrimitiveDataType(val) { + ai_assert(val != 0); + } - typedef PrimitiveDataType INTEGER; - typedef PrimitiveDataType REAL; - typedef PrimitiveDataType NUMBER; - typedef PrimitiveDataType STRING; + ENTITY() : + PrimitiveDataType(TypeError::ENTITY_NOT_SPECIFIED) { + // empty + } +private: +}; +// ------------------------------------------------------------------------------- +/** Wrap any STEP aggregate: LIST, SET, ... */ +// ------------------------------------------------------------------------------- +class LIST : public DataType { +public: + // access a particular list index, throw std::range_error for wrong indices + std::shared_ptr operator[](size_t index) const { + return members[index]; + } - // ------------------------------------------------------------------------------- - /** Generic base class for all enumerated types */ - // ------------------------------------------------------------------------------- - class ENUMERATION : public STRING - { - public: + size_t GetSize() const { + return members.size(); + } - ENUMERATION (const std::string& val) - : STRING(val) - {} +public: + /** @see DaraType::Parse */ + static std::shared_ptr Parse(const char *&inout, + uint64_t line = SyntaxError::LINE_NOT_SPECIFIED, + const EXPRESS::ConversionSchema *schema = NULL); - private: - }; +private: + typedef std::vector> MemberList; + MemberList members; +}; - typedef ENUMERATION BOOLEAN; +class BINARY : public PrimitiveDataType { +public: + BINARY(uint32_t val) : + PrimitiveDataType(val) { + // empty + } - // ------------------------------------------------------------------------------- - /** This is just a reference to an entity/object somewhere else */ - // ------------------------------------------------------------------------------- - class ENTITY : public PrimitiveDataType - { - public: + BINARY() : + PrimitiveDataType(TypeError::ENTITY_NOT_SPECIFIED_32) { + // empty + } +}; - ENTITY(uint64_t val) - : PrimitiveDataType(val) - { - ai_assert(val!=0); - } - - ENTITY() - : PrimitiveDataType(TypeError::ENTITY_NOT_SPECIFIED) - { - } - - private: - }; - - // ------------------------------------------------------------------------------- - /** Wrap any STEP aggregate: LIST, SET, ... */ - // ------------------------------------------------------------------------------- - class LIST : public DataType - { - public: - - // access a particular list index, throw std::range_error for wrong indices - std::shared_ptr operator[] (size_t index) const { - return members[index]; - } - - size_t GetSize() const { - return members.size(); - } - - public: - - /** @see DaraType::Parse */ - static std::shared_ptr Parse(const char*& inout, - uint64_t line = SyntaxError::LINE_NOT_SPECIFIED, - const EXPRESS::ConversionSchema* schema = NULL); - - - private: - typedef std::vector< std::shared_ptr > MemberList; - MemberList members; - }; - - class BINARY : public PrimitiveDataType { - public: - BINARY(uint32_t val) - : PrimitiveDataType(val) { - // empty - } - - BINARY() - : PrimitiveDataType(TypeError::ENTITY_NOT_SPECIFIED_32) { - // empty - } - }; - - // ------------------------------------------------------------------------------- - /* Not exactly a full EXPRESS schema but rather a list of conversion functions +// ------------------------------------------------------------------------------- +/* Not exactly a full EXPRESS schema but rather a list of conversion functions * to extract valid C++ objects out of a STEP file. Those conversion functions * may, however, perform further schema validations. */ - // ------------------------------------------------------------------------------- - class ConversionSchema { - public: - struct SchemaEntry { - SchemaEntry( const char *name, ConvertObjectProc func ) - : mName( name ) - , mFunc(func) { - // empty - } +// ------------------------------------------------------------------------------- +class ConversionSchema { +public: + struct SchemaEntry { + SchemaEntry(const char *name, ConvertObjectProc func) : + mName(name), mFunc(func) { + // empty + } - const char* mName; - ConvertObjectProc mFunc; - }; + const char *mName; + ConvertObjectProc mFunc; + }; - typedef std::map ConverterMap; + typedef std::map ConverterMap; - template - explicit ConversionSchema( const SchemaEntry (& schemas)[N]) { - *this = schemas; - } - - ConversionSchema() { - - } - - ConvertObjectProc GetConverterProc(const std::string& name) const { - ConverterMap::const_iterator it = converters.find(name); - return it == converters.end() ? nullptr : (*it).second; - } - - bool IsKnownToken(const std::string& name) const { - return converters.find(name) != converters.end(); - } - - const char* GetStaticStringForToken(const std::string& token) const { - ConverterMap::const_iterator it = converters.find(token); - return it == converters.end() ? nullptr : (*it).first.c_str(); - } - - - template - const ConversionSchema& operator=( const SchemaEntry (& schemas)[N]) { - for(size_t i = 0; i < N; ++i ) { - const SchemaEntry& schema = schemas[i]; - converters[schema.mName] = schema.mFunc; - } - return *this; - } - - private: - ConverterMap converters; - }; + template + explicit ConversionSchema(const SchemaEntry (&schemas)[N]) { + *this = schemas; } + ConversionSchema() { + } + ConvertObjectProc GetConverterProc(const std::string &name) const { + ConverterMap::const_iterator it = converters.find(name); + return it == converters.end() ? nullptr : (*it).second; + } - // ------------------------------------------------------------------------------ - /** Bundle all the relevant info from a STEP header, parts of which may later + bool IsKnownToken(const std::string &name) const { + return converters.find(name) != converters.end(); + } + + const char *GetStaticStringForToken(const std::string &token) const { + ConverterMap::const_iterator it = converters.find(token); + return it == converters.end() ? nullptr : (*it).first.c_str(); + } + + template + const ConversionSchema &operator=(const SchemaEntry (&schemas)[N]) { + for (size_t i = 0; i < N; ++i) { + const SchemaEntry &schema = schemas[i]; + converters[schema.mName] = schema.mFunc; + } + return *this; + } + +private: + ConverterMap converters; +}; +} // namespace EXPRESS + +// ------------------------------------------------------------------------------ +/** Bundle all the relevant info from a STEP header, parts of which may later * be plainly dumped to the logfile, whereas others may help the caller pick an * appropriate loading strategy.*/ - // ------------------------------------------------------------------------------ - struct HeaderInfo - { - std::string timestamp; - std::string app; - std::string fileSchema; - }; +// ------------------------------------------------------------------------------ +struct HeaderInfo { + std::string timestamp; + std::string app; + std::string fileSchema; +}; +// ------------------------------------------------------------------------------ +/** Base class for all concrete object instances */ +// ------------------------------------------------------------------------------ +class Object { +public: + Object(const char *classname = "unknown") : + id(0), classname(classname) { + // empty + } - // ------------------------------------------------------------------------------ - /** Base class for all concrete object instances */ - // ------------------------------------------------------------------------------ - class Object { - public: - Object(const char* classname = "unknown") - : id( 0 ) - , classname(classname) { - // empty - } + virtual ~Object() { + // empty + } - virtual ~Object() { - // empty - } - - // utilities to simplify casting to concrete types - template - const T& To() const { - return dynamic_cast(*this); - } - - template - T& To() { - return dynamic_cast(*this); - } - - template - const T* ToPtr() const { - return dynamic_cast(this); - } - - template - T* ToPtr() { - return dynamic_cast(this); - } - - uint64_t GetID() const { - return id; - } - - std::string GetClassName() const { - return classname; - } - - void SetID(uint64_t newval) { - id = newval; - } - - private: - uint64_t id; - const char* const classname; - }; + // utilities to simplify casting to concrete types + template + const T &To() const { + return dynamic_cast(*this); + } template - size_t GenericFill(const STEP::DB& db, const EXPRESS::LIST& params, T* in); - // (intentionally undefined) + T &To() { + return dynamic_cast(*this); + } - - // ------------------------------------------------------------------------------ - /** CRTP shared base class for use by concrete entity implementation classes */ - // ------------------------------------------------------------------------------ - template - struct ObjectHelper : virtual Object { - ObjectHelper() - : aux_is_derived(0) { - // empty - } - - static Object* Construct(const STEP::DB& db, const EXPRESS::LIST& params) { - // make sure we don't leak if Fill() throws an exception - std::unique_ptr impl(new TDerived()); - - // GenericFill is undefined so we need to have a specialization - const size_t num_args = GenericFill(db,params,&*impl); - (void)num_args; - - // the following check is commented because it will always trigger if - // parts of the entities are generated with dummy wrapper code. - // This is currently done to reduce the size of the loader - // code. - //if (num_args != params.GetSize() && impl->GetClassName() != "NotImplemented") { - // DefaultLogger::get()->debug("STEP: not all parameters consumed"); - //} - return impl.release(); - } - - // note that this member always exists multiple times within the hierarchy - // of an individual object, so any access to it must be disambiguated. - std::bitset aux_is_derived; - }; - - // ------------------------------------------------------------------------------ - /** Class template used to represent OPTIONAL data members in the converted schema */ - // ------------------------------------------------------------------------------ template - struct Maybe { - Maybe() - : have() { - // empty - } + const T *ToPtr() const { + return dynamic_cast(this); + } - explicit Maybe(const T& ptr) - : ptr(ptr) - , have(true) { - // empty - } + template + T *ToPtr() { + return dynamic_cast(this); + } + uint64_t GetID() const { + return id; + } - void flag_invalid() { - have = false; - } + std::string GetClassName() const { + return classname; + } - void flag_valid() { - have = true; - } + void SetID(uint64_t newval) { + id = newval; + } +private: + uint64_t id; + const char *const classname; +}; - bool operator! () const { - return !have; - } +template +size_t GenericFill(const STEP::DB &db, const EXPRESS::LIST ¶ms, T *in); +// (intentionally undefined) - operator bool() const { - return have; - } +// ------------------------------------------------------------------------------ +/** CRTP shared base class for use by concrete entity implementation classes */ +// ------------------------------------------------------------------------------ +template +struct ObjectHelper : virtual Object { + ObjectHelper() : + aux_is_derived(0) { + // empty + } - operator const T&() const { - return Get(); - } + static Object *Construct(const STEP::DB &db, const EXPRESS::LIST ¶ms) { + // make sure we don't leak if Fill() throws an exception + std::unique_ptr impl(new TDerived()); - const T& Get() const { - ai_assert(have); - return ptr; - } + // GenericFill is undefined so we need to have a specialization + const size_t num_args = GenericFill(db, params, &*impl); + (void)num_args; - Maybe& operator=(const T& _ptr) { - ptr = _ptr; - have = true; - return *this; - } + // the following check is commented because it will always trigger if + // parts of the entities are generated with dummy wrapper code. + // This is currently done to reduce the size of the loader + // code. + //if (num_args != params.GetSize() && impl->GetClassName() != "NotImplemented") { + // DefaultLogger::get()->debug("STEP: not all parameters consumed"); + //} + return impl.release(); + } - private: - template friend struct InternGenericConvert; + // note that this member always exists multiple times within the hierarchy + // of an individual object, so any access to it must be disambiguated. + std::bitset aux_is_derived; +}; - operator T&() { - return ptr; - } +// ------------------------------------------------------------------------------ +/** Class template used to represent OPTIONAL data members in the converted schema */ +// ------------------------------------------------------------------------------ +template +struct Maybe { + Maybe() : + have() { + // empty + } - T ptr; - bool have; - }; + explicit Maybe(const T &ptr) : + ptr(ptr), have(true) { + // empty + } - // ------------------------------------------------------------------------------ - /** A LazyObject is created when needed. Before this happens, we just keep + void flag_invalid() { + have = false; + } + + void flag_valid() { + have = true; + } + + bool operator!() const { + return !have; + } + + operator bool() const { + return have; + } + + operator const T &() const { + return Get(); + } + + const T &Get() const { + ai_assert(have); + return ptr; + } + + Maybe &operator=(const T &_ptr) { + ptr = _ptr; + have = true; + return *this; + } + +private: + template + friend struct InternGenericConvert; + + operator T &() { + return ptr; + } + + T ptr; + bool have; +}; + +// ------------------------------------------------------------------------------ +/** A LazyObject is created when needed. Before this happens, we just keep the text line that contains the object definition. */ - // ------------------------------------------------------------------------------- - class LazyObject { - friend class DB; +// ------------------------------------------------------------------------------- +class LazyObject { + friend class DB; - public: - LazyObject(DB& db, uint64_t id, uint64_t line, const char* type,const char* args); - ~LazyObject(); +public: + LazyObject(DB &db, uint64_t id, uint64_t line, const char *type, const char *args); + ~LazyObject(); - Object& operator * () { - if (!obj) { - LazyInit(); - ai_assert(obj); - } - return *obj; + Object &operator*() { + if (!obj) { + LazyInit(); + ai_assert(obj); } + return *obj; + } - const Object& operator * () const { - if (!obj) { - LazyInit(); - ai_assert(obj); - } - return *obj; + const Object &operator*() const { + if (!obj) { + LazyInit(); + ai_assert(obj); } - - template - const T& To() const { - return dynamic_cast( **this ); - } - - template - T& To() { - return dynamic_cast( **this ); - } - - template - const T* ToPtr() const { - return dynamic_cast( &**this ); - } - - template - T* ToPtr() { - return dynamic_cast( &**this ); - } - - Object* operator -> () { - return &**this; - } - - const Object* operator -> () const { - return &**this; - } - - bool operator== (const std::string& atype) const { - return type == atype; - } - - bool operator!= (const std::string& atype) const { - return type != atype; - } - - uint64_t GetID() const { - return id; - } - - private: - void LazyInit() const; - - private: - mutable uint64_t id; - const char* const type; - DB& db; - mutable const char* args; - mutable Object* obj; - }; - - template - inline - bool operator==( std::shared_ptr lo, T whatever ) { - return *lo == whatever; // XXX use std::forward if we have 0x + return *obj; } template - inline - bool operator==( const std::pair >& lo, T whatever ) { - return *(lo.second) == whatever; // XXX use std::forward if we have 0x + const T &To() const { + return dynamic_cast(**this); } - // ------------------------------------------------------------------------------ - /** Class template used to represent lazily evaluated object references in the converted schema */ - // ------------------------------------------------------------------------------ template - struct Lazy { - typedef Lazy Out; - Lazy(const LazyObject* obj = nullptr) - : obj(obj) { - // empty - } - - operator const T*() const { - return obj->ToPtr(); - } - - operator const T&() const { - return obj->To(); - } - - const T& operator * () const { - return obj->To(); - } - - const T* operator -> () const { - return &obj->To(); - } - - const LazyObject* obj; - }; - - // ------------------------------------------------------------------------------ - /** Class template used to represent LIST and SET data members in the converted schema */ - // ------------------------------------------------------------------------------ - template - struct ListOf : public std::vector { - typedef typename T::Out OutScalar; - typedef ListOf Out; - - ListOf() { - static_assert(min_cnt <= max_cnt || !max_cnt, "min_cnt <= max_cnt || !max_cnt"); - } - }; - - // ------------------------------------------------------------------------------ - template - struct PickBaseType { - typedef EXPRESS::PrimitiveDataType Type; - }; - - template - struct PickBaseType< Lazy > { - typedef EXPRESS::ENTITY Type; - }; - - template<> - struct PickBaseType< std::shared_ptr< const EXPRESS::DataType > >; - - // ------------------------------------------------------------------------------ - template - struct InternGenericConvert { - void operator()(T& out, const std::shared_ptr< const EXPRESS::DataType >& in, const STEP::DB& /*db*/) { - try{ - out = dynamic_cast< const typename PickBaseType::Type& > ( *in ); - } catch(std::bad_cast&) { - throw TypeError("type error reading literal field"); - } - } - }; - - template <> - struct InternGenericConvert< std::shared_ptr< const EXPRESS::DataType > > { - void operator()(std::shared_ptr< const EXPRESS::DataType >& out, const std::shared_ptr< const EXPRESS::DataType >& in, const STEP::DB& /*db*/) { - out = in; - } - }; - - template - struct InternGenericConvert< Maybe > { - void operator()(Maybe& out, const std::shared_ptr< const EXPRESS::DataType >& in, const STEP::DB& db) { - GenericConvert((T&)out,in,db); - out.flag_valid(); - } - }; - - template - struct InternGenericConvertList { - void operator()(ListOf& out, const std::shared_ptr< const EXPRESS::DataType >& inp_base, const STEP::DB& db) { - - const EXPRESS::LIST* inp = dynamic_cast(inp_base.get()); - if (!inp) { - throw TypeError("type error reading aggregate"); - } - - // XXX is this really how the EXPRESS notation ([?:3],[1:3]) is intended? - if (max_cnt && inp->GetSize() > max_cnt) { - ASSIMP_LOG_WARN("too many aggregate elements"); - } - else if (inp->GetSize() < min_cnt) { - ASSIMP_LOG_WARN("too few aggregate elements"); - } - - out.reserve(inp->GetSize()); - for(size_t i = 0; i < inp->GetSize(); ++i) { - - out.push_back( typename ListOf::OutScalar() ); - try{ - GenericConvert(out.back(),(*inp)[i], db); - } - catch(const TypeError& t) { - throw TypeError(t.what() +std::string(" of aggregate")); - } - } - } - }; - - template - struct InternGenericConvert< Lazy > { - void operator()(Lazy& out, const std::shared_ptr< const EXPRESS::DataType >& in_base, const STEP::DB& db) { - const EXPRESS::ENTITY* in = dynamic_cast(in_base.get()); - if (!in) { - throw TypeError("type error reading entity"); - } - out = Couple(db).GetObject(*in); - } - }; - - template - inline void GenericConvert(T1& a, const std::shared_ptr< const EXPRESS::DataType >& b, const STEP::DB& db) { - return InternGenericConvert()(a,b,db); + T &To() { + return dynamic_cast(**this); } - template - inline void GenericConvert(ListOf& a, const std::shared_ptr< const EXPRESS::DataType >& b, const STEP::DB& db) { - return InternGenericConvertList()(a,b,db); + template + const T *ToPtr() const { + return dynamic_cast(&**this); } - // ------------------------------------------------------------------------------ - /** Lightweight manager class that holds the map of all objects in a + template + T *ToPtr() { + return dynamic_cast(&**this); + } + + Object *operator->() { + return &**this; + } + + const Object *operator->() const { + return &**this; + } + + bool operator==(const std::string &atype) const { + return type == atype; + } + + bool operator!=(const std::string &atype) const { + return type != atype; + } + + uint64_t GetID() const { + return id; + } + +private: + void LazyInit() const; + +private: + mutable uint64_t id; + const char *const type; + DB &db; + mutable const char *args; + mutable Object *obj; +}; + +template +inline bool operator==(std::shared_ptr lo, T whatever) { + return *lo == whatever; // XXX use std::forward if we have 0x +} + +template +inline bool operator==(const std::pair> &lo, T whatever) { + return *(lo.second) == whatever; // XXX use std::forward if we have 0x +} + +// ------------------------------------------------------------------------------ +/** Class template used to represent lazily evaluated object references in the converted schema */ +// ------------------------------------------------------------------------------ +template +struct Lazy { + typedef Lazy Out; + Lazy(const LazyObject *obj = nullptr) : + obj(obj) { + // empty + } + + operator const T *() const { + return obj->ToPtr(); + } + + operator const T &() const { + return obj->To(); + } + + const T &operator*() const { + return obj->To(); + } + + const T *operator->() const { + return &obj->To(); + } + + const LazyObject *obj; +}; + +// ------------------------------------------------------------------------------ +/** Class template used to represent LIST and SET data members in the converted schema */ +// ------------------------------------------------------------------------------ +template +struct ListOf : public std::vector { + typedef typename T::Out OutScalar; + typedef ListOf Out; + + ListOf() { + static_assert(min_cnt <= max_cnt || !max_cnt, "min_cnt <= max_cnt || !max_cnt"); + } +}; + +// ------------------------------------------------------------------------------ +template +struct PickBaseType { + typedef EXPRESS::PrimitiveDataType Type; +}; + +template +struct PickBaseType> { + typedef EXPRESS::ENTITY Type; +}; + +template <> +struct PickBaseType>; + +// ------------------------------------------------------------------------------ +template +struct InternGenericConvert { + void operator()(T &out, const std::shared_ptr &in, const STEP::DB & /*db*/) { + try { + out = dynamic_cast::Type &>(*in); + } catch (std::bad_cast &) { + throw TypeError("type error reading literal field"); + } + } +}; + +template <> +struct InternGenericConvert> { + void operator()(std::shared_ptr &out, const std::shared_ptr &in, const STEP::DB & /*db*/) { + out = in; + } +}; + +template +struct InternGenericConvert> { + void operator()(Maybe &out, const std::shared_ptr &in, const STEP::DB &db) { + GenericConvert((T &)out, in, db); + out.flag_valid(); + } +}; + +template +struct InternGenericConvertList { + void operator()(ListOf &out, const std::shared_ptr &inp_base, const STEP::DB &db) { + + const EXPRESS::LIST *inp = dynamic_cast(inp_base.get()); + if (!inp) { + throw TypeError("type error reading aggregate"); + } + + // XXX is this really how the EXPRESS notation ([?:3],[1:3]) is intended? + if (max_cnt && inp->GetSize() > max_cnt) { + ASSIMP_LOG_WARN("too many aggregate elements"); + } else if (inp->GetSize() < min_cnt) { + ASSIMP_LOG_WARN("too few aggregate elements"); + } + + out.reserve(inp->GetSize()); + for (size_t i = 0; i < inp->GetSize(); ++i) { + + out.push_back(typename ListOf::OutScalar()); + try { + GenericConvert(out.back(), (*inp)[i], db); + } catch (const TypeError &t) { + throw TypeError(t.what() + std::string(" of aggregate")); + } + } + } +}; + +template +struct InternGenericConvert> { + void operator()(Lazy &out, const std::shared_ptr &in_base, const STEP::DB &db) { + const EXPRESS::ENTITY *in = dynamic_cast(in_base.get()); + if (!in) { + throw TypeError("type error reading entity"); + } + out = Couple(db).GetObject(*in); + } +}; + +template +inline void GenericConvert(T1 &a, const std::shared_ptr &b, const STEP::DB &db) { + return InternGenericConvert()(a, b, db); +} + +template +inline void GenericConvert(ListOf &a, const std::shared_ptr &b, const STEP::DB &db) { + return InternGenericConvertList()(a, b, db); +} + +// ------------------------------------------------------------------------------ +/** Lightweight manager class that holds the map of all objects in a * STEP file. DB's are exclusively maintained by the functions in * STEPFileReader.h*/ - // ------------------------------------------------------------------------------- - class DB - { - friend DB* ReadFileHeader(std::shared_ptr stream); - friend void ReadFile(DB& db,const EXPRESS::ConversionSchema& scheme, - const char* const* types_to_track, size_t len, - const char* const* inverse_indices_to_track, size_t len2 - ); +// ------------------------------------------------------------------------------- +class DB { + friend DB *ReadFileHeader(std::shared_ptr stream); + friend void ReadFile(DB &db, const EXPRESS::ConversionSchema &scheme, + const char *const *types_to_track, size_t len, + const char *const *inverse_indices_to_track, size_t len2); - friend class LazyObject; + friend class LazyObject; - public: - // objects indexed by ID - this can grow pretty large (i.e some hundred million - // entries), so use raw pointers to avoid *any* overhead. - typedef std::map ObjectMap; +public: + // objects indexed by ID - this can grow pretty large (i.e some hundred million + // entries), so use raw pointers to avoid *any* overhead. + typedef std::map ObjectMap; - // objects indexed by their declarative type, but only for those that we truly want - typedef std::set< const LazyObject*> ObjectSet; - typedef std::map ObjectMapByType; + // objects indexed by their declarative type, but only for those that we truly want + typedef std::set ObjectSet; + typedef std::map ObjectMapByType; - // list of types for which to keep inverse indices for all references - // that the respective objects keep. - // the list keeps pointers to strings in static storage - typedef std::set InverseWhitelist; + // list of types for which to keep inverse indices for all references + // that the respective objects keep. + // the list keeps pointers to strings in static storage + typedef std::set InverseWhitelist; - // references - for each object id the ids of all objects which reference it - // this is used to simulate STEP inverse indices for selected types. - typedef std::step_unordered_multimap RefMap; - typedef std::pair RefMapRange; + // references - for each object id the ids of all objects which reference it + // this is used to simulate STEP inverse indices for selected types. + typedef std::step_unordered_multimap RefMap; + typedef std::pair RefMapRange; - private: +private: + DB(std::shared_ptr reader) : + reader(reader), splitter(*reader, true, true), evaluated_count(), schema(nullptr) {} - DB(std::shared_ptr reader) - : reader(reader) - , splitter(*reader,true,true) - , evaluated_count() - , schema( nullptr ) - {} - - public: - ~DB() { - for(ObjectMap::value_type& o : objects) { - delete o.second; - } +public: + ~DB() { + for (ObjectMap::value_type &o : objects) { + delete o.second; } + } - uint64_t GetObjectCount() const { - return objects.size(); + uint64_t GetObjectCount() const { + return objects.size(); + } + + uint64_t GetEvaluatedObjectCount() const { + return evaluated_count; + } + + const HeaderInfo &GetHeader() const { + return header; + } + + const EXPRESS::ConversionSchema &GetSchema() const { + return *schema; + } + + const ObjectMap &GetObjects() const { + return objects; + } + + const ObjectMapByType &GetObjectsByType() const { + return objects_bytype; + } + + const RefMap &GetRefs() const { + return refs; + } + + bool KeepInverseIndicesForType(const char *const type) const { + return inv_whitelist.find(type) != inv_whitelist.end(); + } + + // get the yet unevaluated object record with a given id + const LazyObject *GetObject(uint64_t id) const { + const ObjectMap::const_iterator it = objects.find(id); + if (it != objects.end()) { + return (*it).second; } + return nullptr; + } - uint64_t GetEvaluatedObjectCount() const { - return evaluated_count; + // get an arbitrary object out of the soup with the only restriction being its type. + const LazyObject *GetObject(const std::string &type) const { + const ObjectMapByType::const_iterator it = objects_bytype.find(type); + if (it != objects_bytype.end() && (*it).second.size()) { + return *(*it).second.begin(); } + return NULL; + } - const HeaderInfo& GetHeader() const { - return header; + // same, but raise an exception if the object doesn't exist and return a reference + const LazyObject &MustGetObject(uint64_t id) const { + const LazyObject *o = GetObject(id); + if (!o) { + throw TypeError("requested entity is not present", id); } + return *o; + } - const EXPRESS::ConversionSchema& GetSchema() const { - return *schema; + const LazyObject &MustGetObject(const std::string &type) const { + const LazyObject *o = GetObject(type); + if (!o) { + throw TypeError("requested entity of type " + type + "is not present"); } - - const ObjectMap& GetObjects() const { - return objects; - } - - const ObjectMapByType& GetObjectsByType() const { - return objects_bytype; - } - - const RefMap& GetRefs() const { - return refs; - } - - bool KeepInverseIndicesForType(const char* const type) const { - return inv_whitelist.find(type) != inv_whitelist.end(); - } - - - // get the yet unevaluated object record with a given id - const LazyObject* GetObject(uint64_t id) const { - const ObjectMap::const_iterator it = objects.find(id); - if (it != objects.end()) { - return (*it).second; - } - return nullptr; - } - - - // get an arbitrary object out of the soup with the only restriction being its type. - const LazyObject* GetObject(const std::string& type) const { - const ObjectMapByType::const_iterator it = objects_bytype.find(type); - if (it != objects_bytype.end() && (*it).second.size()) { - return *(*it).second.begin(); - } - return NULL; - } - - // same, but raise an exception if the object doesn't exist and return a reference - const LazyObject& MustGetObject(uint64_t id) const { - const LazyObject* o = GetObject(id); - if (!o) { - throw TypeError("requested entity is not present",id); - } - return *o; - } - - const LazyObject& MustGetObject(const std::string& type) const { - const LazyObject* o = GetObject(type); - if (!o) { - throw TypeError("requested entity of type "+type+"is not present"); - } - return *o; - } - + return *o; + } #ifdef ASSIMP_IFC_TEST - // evaluate *all* entities in the file. this is a power test for the loader - void EvaluateAll() { - for(ObjectMap::value_type& e :objects) { - **e.second; - } - ai_assert(evaluated_count == objects.size()); + // evaluate *all* entities in the file. this is a power test for the loader + void EvaluateAll() { + for (ObjectMap::value_type &e : objects) { + **e.second; } + ai_assert(evaluated_count == objects.size()); + } #endif - private: +private: + // full access only offered to close friends - they should + // use the provided getters rather than messing around with + // the members directly. + LineSplitter &GetSplitter() { + return splitter; + } - // full access only offered to close friends - they should - // use the provided getters rather than messing around with - // the members directly. - LineSplitter& GetSplitter() { - return splitter; + void InternInsert(const LazyObject *lz) { + objects[lz->GetID()] = lz; + + const ObjectMapByType::iterator it = objects_bytype.find(lz->type); + if (it != objects_bytype.end()) { + (*it).second.insert(lz); } + } - void InternInsert(const LazyObject* lz) { - objects[lz->GetID()] = lz; + void SetSchema(const EXPRESS::ConversionSchema &_schema) { + schema = &_schema; + } - const ObjectMapByType::iterator it = objects_bytype.find( lz->type ); - if (it != objects_bytype.end()) { - (*it).second.insert(lz); - } + void SetTypesToTrack(const char *const *types, size_t N) { + for (size_t i = 0; i < N; ++i) { + objects_bytype[types[i]] = ObjectSet(); } + } - void SetSchema(const EXPRESS::ConversionSchema& _schema) { - schema = &_schema; + void SetInverseIndicesToTrack(const char *const *types, size_t N) { + for (size_t i = 0; i < N; ++i) { + const char *const sz = schema->GetStaticStringForToken(types[i]); + ai_assert(sz); + inv_whitelist.insert(sz); } + } + HeaderInfo &GetHeader() { + return header; + } - void SetTypesToTrack(const char* const* types, size_t N) { - for(size_t i = 0; i < N;++i) { - objects_bytype[types[i]] = ObjectSet(); - } - } + void MarkRef(uint64_t who, uint64_t by_whom) { + refs.insert(std::make_pair(who, by_whom)); + } - void SetInverseIndicesToTrack( const char* const* types, size_t N ) { - for(size_t i = 0; i < N;++i) { - const char* const sz = schema->GetStaticStringForToken(types[i]); - ai_assert(sz); - inv_whitelist.insert(sz); - } - } +private: + HeaderInfo header; + ObjectMap objects; + ObjectMapByType objects_bytype; + RefMap refs; + InverseWhitelist inv_whitelist; + std::shared_ptr reader; + LineSplitter splitter; + uint64_t evaluated_count; + const EXPRESS::ConversionSchema *schema; +}; - HeaderInfo& GetHeader() { - return header; - } +#pragma warning( pop ) - void MarkRef(uint64_t who, uint64_t by_whom) { - refs.insert(std::make_pair(who,by_whom)); - } +} // namespace STEP - private: - HeaderInfo header; - ObjectMap objects; - ObjectMapByType objects_bytype; - RefMap refs; - InverseWhitelist inv_whitelist; - std::shared_ptr reader; - LineSplitter splitter; - uint64_t evaluated_count; - const EXPRESS::ConversionSchema* schema; - }; - -} - -} // end Assimp +} // namespace Assimp #endif // INCLUDED_AI_STEPFILE_H diff --git a/code/XGL/XGLLoader.cpp b/code/XGL/XGLLoader.cpp index 403205e03..415d8173e 100644 --- a/code/XGL/XGLLoader.cpp +++ b/code/XGL/XGLLoader.cpp @@ -297,8 +297,7 @@ std::string XGLImporter::GetElementName() std::string ret; ret.resize(len); - - std::transform(s,s+len,ret.begin(),::tolower); + std::transform(s, s + len, ret.begin(), ::ToLower); return ret; } @@ -618,26 +617,22 @@ bool XGLImporter::ReadMesh(TempScope& scope) bool has[3] = {0}; while (ReadElementUpToClosing(s.c_str())) { - const std::string& s = GetElementName(); - if (s == "fv1" || s == "lv1" || s == "pv1") { + const std::string& elemName = GetElementName(); + if (elemName == "fv1" || elemName == "lv1" || elemName == "pv1") { ReadFaceVertex(t,tf[0]); has[0] = true; - } - else if (s == "fv2" || s == "lv2") { - ReadFaceVertex(t,tf[1]); + } else if (elemName == "fv2" || elemName == "lv2") { + ReadFaceVertex(t, tf[1]); has[1] = true; - } - else if (s == "fv3") { - ReadFaceVertex(t,tf[2]); + } else if (elemName == "fv3") { + ReadFaceVertex(t, tf[2]); has[2] = true; - } - else if (s == "mat") { + } else if (elemName == "mat") { if (mid != ~0u) { LogWarn("only one material tag allowed per "); } mid = ResolveMaterialRef(scope); - } - else if (s == "matref") { + } else if (elemName == "matref") { if (mid != ~0u) { LogWarn("only one material tag allowed per "); } diff --git a/include/assimp/ParsingUtils.h b/include/assimp/ParsingUtils.h index 736952e26..69dc95da2 100644 --- a/include/assimp/ParsingUtils.h +++ b/include/assimp/ParsingUtils.h @@ -4,7 +4,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2020, assimp team - All rights reserved. Redistribution and use of this software in source and binary forms, From bb62249f0c76124a7fd44398b90a76009182476c Mon Sep 17 00:00:00 2001 From: Yingying Wang Date: Wed, 4 Mar 2020 14:52:26 -0800 Subject: [PATCH 086/330] fix gltf2 exporter memory crash --- code/glTF2/glTF2Asset.inl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/glTF2/glTF2Asset.inl b/code/glTF2/glTF2Asset.inl index 35ecfa62d..2535207c4 100644 --- a/code/glTF2/glTF2Asset.inl +++ b/code/glTF2/glTF2Asset.inl @@ -535,7 +535,7 @@ inline void Buffer::Grow(size_t amount) // Shift operation is standard way to divide integer by 2, it doesn't cast it to float back and forth, also works for odd numbers, // originally it would look like: static_cast(capacity * 1.5f) - capacity = std::max(capacity + (capacity >> 1), byteLength + amount); + capacity = byteLength + amount; //wangyi fix crash std::max(capacity + (capacity >> 1), byteLength + amount); uint8_t* b = new uint8_t[capacity]; if (mData) memcpy(b, mData.get(), byteLength); From 8b9abc58e72ea714070ca67016b127a96572ea4b Mon Sep 17 00:00:00 2001 From: Sebastian Matusik Date: Wed, 4 Mar 2020 17:15:09 -0800 Subject: [PATCH 087/330] ifdef the exporters as specifying harsher linker flags than what's in default CMake causes linking issues. --- code/Common/Exporter.cpp | 35 ++++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/code/Common/Exporter.cpp b/code/Common/Exporter.cpp index 9f9a33b58..403ba4ebb 100644 --- a/code/Common/Exporter.cpp +++ b/code/Common/Exporter.cpp @@ -80,32 +80,61 @@ namespace Assimp { void GetPostProcessingStepInstanceList(std::vector< BaseProcess* >& out); // ------------------------------------------------------------------------------------------------ -// Exporter worker function prototypes. Should not be necessary to #ifndef them, it's just a prototype -// do not use const, because some exporter need to convert the scene temporary +// Exporter worker function prototypes. Do not use const, because some exporter need to convert +// the scene temporary +#ifndef ASSIMP_BUILD_NO_COLLADA_EXPORTER void ExportSceneCollada(const char*,IOSystem*, const aiScene*, const ExportProperties*); +#endif +#ifndef ASSIMP_BUILD_NO_X_EXPORTER void ExportSceneXFile(const char*,IOSystem*, const aiScene*, const ExportProperties*); +#endif +#ifndef ASSIMP_BUILD_NO_STEP_EXPORTER void ExportSceneStep(const char*,IOSystem*, const aiScene*, const ExportProperties*); +#endif +#ifndef ASSIMP_BUILD_NO_OBJ_EXPORTER void ExportSceneObj(const char*,IOSystem*, const aiScene*, const ExportProperties*); void ExportSceneObjNoMtl(const char*,IOSystem*, const aiScene*, const ExportProperties*); +#endif +#ifdef ASSIMP_BUILD_NO_STL_EXPORTER void ExportSceneSTL(const char*,IOSystem*, const aiScene*, const ExportProperties*); void ExportSceneSTLBinary(const char*,IOSystem*, const aiScene*, const ExportProperties*); +#endif +#ifndef ASSIMP_BUILD_NO_PLY_EXPORTER void ExportScenePly(const char*,IOSystem*, const aiScene*, const ExportProperties*); void ExportScenePlyBinary(const char*, IOSystem*, const aiScene*, const ExportProperties*); +#endif +#ifndef ASSIMP_BUILD_NO_3DS_EXPORTER void ExportScene3DS(const char*, IOSystem*, const aiScene*, const ExportProperties*); +#endif +#ifndef ASSIMP_BUILD_NO_GLTF_EXPORTER void ExportSceneGLTF(const char*, IOSystem*, const aiScene*, const ExportProperties*); void ExportSceneGLB(const char*, IOSystem*, const aiScene*, const ExportProperties*); void ExportSceneGLTF2(const char*, IOSystem*, const aiScene*, const ExportProperties*); void ExportSceneGLB2(const char*, IOSystem*, const aiScene*, const ExportProperties*); +#endif +#ifndef ASSIMP_BUILD_NO_ASSBIN_EXPORTER void ExportSceneAssbin(const char*, IOSystem*, const aiScene*, const ExportProperties*); +#endif +#ifndef ASSIMP_BUILD_NO_ASSXML_EXPORTER void ExportSceneAssxml(const char*, IOSystem*, const aiScene*, const ExportProperties*); +#endif +#ifndef ASSIMP_BUILD_NO_X3D_EXPORTER void ExportSceneX3D(const char*, IOSystem*, const aiScene*, const ExportProperties*); +#endif +#ifndef ASSIMP_BUILD_NO_FBX_EXPORTER void ExportSceneFBX(const char*, IOSystem*, const aiScene*, const ExportProperties*); void ExportSceneFBXA(const char*, IOSystem*, const aiScene*, const ExportProperties*); +#endif +#ifndef ASSIMP_BUILD_NO_3MF_EXPORTER void ExportScene3MF( const char*, IOSystem*, const aiScene*, const ExportProperties* ); +#endif +#ifndef ASSIMP_BUILD_NO_M3D_EXPORTER void ExportSceneM3D(const char*, IOSystem*, const aiScene*, const ExportProperties*); void ExportSceneM3DA(const char*, IOSystem*, const aiScene*, const ExportProperties*); +#endif +#ifndef ASSIMP_BUILD_NO_ASSJSON_EXPORTER void ExportAssimp2Json(const char* , IOSystem*, const aiScene* , const Assimp::ExportProperties*); - +#endif static void setupExporterArray(std::vector &exporters) { #ifndef ASSIMP_BUILD_NO_COLLADA_EXPORTER From aa8a6122cefb8286817a1250d87528105be1de34 Mon Sep 17 00:00:00 2001 From: Marc-Antoine Lortie Date: Fri, 6 Mar 2020 10:26:51 -0500 Subject: [PATCH 088/330] Fixed SimpleTexturedDirectX11 sample. - Removed OpenGL/Glut references in SimpleTexturedDirectX11 CMakeFile - Moved UTFConverter from SimpleTexturedOpenGL to its own file to be able to reuse it. - Added compile definition SHADER_PATH to allow to locate the shader files in CMakeFile - Fixed compile warnings - Made global pointers null to help prevent dangling references. - Added missing members initialization in class constructors. - Removed references to missing model "Models/mymodel.fbx" - Fixed error when extracting model file directory - Added missing device context assignment in ModelLoader Load method - Fixed memory leak caused by variable 'ourModel' not deleted. - Removed call to dev->Release() in ModelLoader.cpp - Adjusted Release() calls in reverse order when cleaning up D3D - Made Throwanerror implementation throw an error instead of displaying a message box - Fixed leaking D3D resources - Added a pointer to an ID3D11Debug to dump live objects. --- CMakeLists.txt | 2 + samples/SharedCode/UTFConverter.cpp | 52 +++++ samples/SharedCode/UTFConverter.h | 92 +++++++++ .../SimpleTexturedDirectx11/CMakeLists.txt | 9 +- .../SimpleTexturedDirectx11/Mesh.h | 47 +++-- .../SimpleTexturedDirectx11/ModelLoader.cpp | 16 +- .../SimpleTexturedDirectx11/SafeRelease.hpp | 57 ++++++ .../SimpleTexturedDirectx11/main.cpp | 183 +++++++++++++----- samples/SimpleTexturedOpenGL/CMakeLists.txt | 3 + .../src/model_loading.cpp | 34 +--- 10 files changed, 386 insertions(+), 109 deletions(-) create mode 100644 samples/SharedCode/UTFConverter.cpp create mode 100644 samples/SharedCode/UTFConverter.h create mode 100644 samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/SafeRelease.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 59b79d1c6..0a7f8eeae 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -594,6 +594,8 @@ IF ( ASSIMP_BUILD_ASSIMP_TOOLS ) ENDIF () IF ( ASSIMP_BUILD_SAMPLES) + SET( SAMPLES_DIR ${CMAKE_CURRENT_SOURCE_DIR}/samples ) + SET( SAMPLES_SHARED_CODE_DIR ${SAMPLES_DIR}/SharedCode ) IF ( WIN32 ) ADD_SUBDIRECTORY( samples/SimpleTexturedOpenGL/ ) ADD_SUBDIRECTORY( samples/SimpleTexturedDirectx11 ) diff --git a/samples/SharedCode/UTFConverter.cpp b/samples/SharedCode/UTFConverter.cpp new file mode 100644 index 000000000..a1bff7e4b --- /dev/null +++ b/samples/SharedCode/UTFConverter.cpp @@ -0,0 +1,52 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2020, 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. +--------------------------------------------------------------------------- +*/ + +#include "UTFConverter.h" + +namespace AssimpSamples { +namespace SharedCode { + +typename UTFConverter::UTFConverterImpl UTFConverter::impl_; + +} +} diff --git a/samples/SharedCode/UTFConverter.h b/samples/SharedCode/UTFConverter.h new file mode 100644 index 000000000..17e89ee4d --- /dev/null +++ b/samples/SharedCode/UTFConverter.h @@ -0,0 +1,92 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2020, 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. +--------------------------------------------------------------------------- +*/ + +#ifndef ASSIMP_SAMPLES_SHARED_CODE_UTFCONVERTER_H +#define ASSIMP_SAMPLES_SHARED_CODE_UTFCONVERTER_H + +#include +#include +#include + +namespace AssimpSamples { +namespace SharedCode { + +// Used to convert between multibyte and unicode strings. +class UTFConverter { + using UTFConverterImpl = std::wstring_convert, wchar_t>; +public: + UTFConverter(const char* s) : + s_(s), + ws_(impl_.from_bytes(s)) { + } + UTFConverter(const wchar_t* s) : + s_(impl_.to_bytes(s)), + ws_(s) { + } + UTFConverter(const std::string& s) : + s_(s), + ws_(impl_.from_bytes(s)) { + } + UTFConverter(const std::wstring& s) : + s_(impl_.to_bytes(s)), + ws_(s) { + } + inline const char* c_str() const { + return s_.c_str(); + } + inline const std::string& str() const { + return s_; + } + inline const wchar_t* c_wstr() const { + return ws_.c_str(); + } +private: + static UTFConverterImpl impl_; + std::string s_; + std::wstring ws_; +}; + +} +} + +#endif // ASSIMP_SAMPLES_SHARED_CODE_UTFCONVERTER_H diff --git a/samples/SimpleTexturedDirectx11/CMakeLists.txt b/samples/SimpleTexturedDirectx11/CMakeLists.txt index b1882500e..9016b8869 100644 --- a/samples/SimpleTexturedDirectx11/CMakeLists.txt +++ b/samples/SimpleTexturedDirectx11/CMakeLists.txt @@ -10,12 +10,12 @@ if ( MSVC ) REMOVE_DEFINITIONS( -DUNICODE -D_UNICODE ) endif () +ADD_COMPILE_DEFINITIONS(SHADER_PATH="${CMAKE_CURRENT_SOURCE_DIR}/SimpleTexturedDirectx11/") + INCLUDE_DIRECTORIES( ${Assimp_SOURCE_DIR}/include ${Assimp_SOURCE_DIR}/code - ${OPENGL_INCLUDE_DIR} - ${GLUT_INCLUDE_DIR} - ${Assimp_SOURCE_DIR}/samples/freeglut/include + ${SAMPLES_SHARED_CODE_DIR} ) LINK_DIRECTORIES( @@ -32,6 +32,9 @@ ADD_EXECUTABLE( assimp_simpletextureddirectx11 WIN32 SimpleTexturedDirectx11/TextureLoader.h #SimpleTexturedDirectx11/VertexShader.hlsl SimpleTexturedDirectx11/main.cpp + SimpleTexturedDirectx11/SafeRelease.hpp + ${SAMPLES_SHARED_CODE_DIR}/UTFConverter.cpp + ${SAMPLES_SHARED_CODE_DIR}/UTFConverter.h ) SET_PROPERTY(TARGET assimp_simpletextureddirectx11 PROPERTY DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX}) diff --git a/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/Mesh.h b/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/Mesh.h index 87433219f..3a2875a1f 100644 --- a/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/Mesh.h +++ b/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/Mesh.h @@ -6,6 +6,7 @@ #include #include #include +#include using namespace std; #include @@ -13,6 +14,8 @@ using namespace std; #include using namespace DirectX; +#include "SafeRelease.hpp" + struct VERTEX { FLOAT X, Y, Z; XMFLOAT2 texcoord; @@ -22,6 +25,10 @@ struct Texture { string type; string path; ID3D11ShaderResourceView *texture; + + inline void Release() { + SafeRelease(texture); + } }; class Mesh { @@ -31,15 +38,15 @@ public: vector textures; ID3D11Device *dev; - Mesh(ID3D11Device *dev, vector vertices, vector indices, vector textures) + Mesh(ID3D11Device *dev, const vector& vertices, const vector& indices, const vector& textures) : + vertices(vertices), + indices(indices), + textures(textures), + dev(dev), + VertexBuffer(nullptr), + IndexBuffer(nullptr) { - this->vertices = vertices; - this->indices = indices; - this->textures = textures; - - this->dev = dev; - - this->setupMesh(dev); + this->setupMesh(this->dev); } void Draw(ID3D11DeviceContext *devcon) @@ -52,13 +59,13 @@ public: devcon->PSSetShaderResources(0, 1, &textures[0].texture); - devcon->DrawIndexed(indices.size(), 0, 0); + devcon->DrawIndexed(static_cast(indices.size()), 0, 0); } void Close() { - VertexBuffer->Release(); - IndexBuffer->Release(); + SafeRelease(VertexBuffer); + SafeRelease(IndexBuffer); } private: /* Render data */ @@ -66,13 +73,13 @@ private: /* Functions */ // Initializes all the buffer objects/arrays - bool setupMesh(ID3D11Device *dev) + void setupMesh(ID3D11Device *dev) { HRESULT hr; D3D11_BUFFER_DESC vbd; vbd.Usage = D3D11_USAGE_IMMUTABLE; - vbd.ByteWidth = sizeof(VERTEX) * vertices.size(); + vbd.ByteWidth = static_cast(sizeof(VERTEX) * vertices.size()); vbd.BindFlags = D3D11_BIND_VERTEX_BUFFER; vbd.CPUAccessFlags = 0; vbd.MiscFlags = 0; @@ -81,12 +88,14 @@ private: initData.pSysMem = &vertices[0]; hr = dev->CreateBuffer(&vbd, &initData, &VertexBuffer); - if (FAILED(hr)) - return false; + if (FAILED(hr)) { + Close(); + throw std::runtime_error("Failed to create vertex buffer."); + } D3D11_BUFFER_DESC ibd; ibd.Usage = D3D11_USAGE_IMMUTABLE; - ibd.ByteWidth = sizeof(UINT) * indices.size(); + ibd.ByteWidth = static_cast(sizeof(UINT) * indices.size()); ibd.BindFlags = D3D11_BIND_INDEX_BUFFER; ibd.CPUAccessFlags = 0; ibd.MiscFlags = 0; @@ -94,8 +103,10 @@ private: initData.pSysMem = &indices[0]; hr = dev->CreateBuffer(&ibd, &initData, &IndexBuffer); - if (FAILED(hr)) - return false; + if (FAILED(hr)) { + Close(); + throw std::runtime_error("Failed to create index buffer."); + } } }; diff --git a/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/ModelLoader.cpp b/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/ModelLoader.cpp index 10ba07a98..b0f086a5d 100644 --- a/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/ModelLoader.cpp +++ b/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/ModelLoader.cpp @@ -1,6 +1,12 @@ #include "ModelLoader.h" -ModelLoader::ModelLoader() +ModelLoader::ModelLoader() : + dev(nullptr), + devcon(nullptr), + meshes(), + directory(), + textures_loaded(), + hwnd(nullptr) { } @@ -20,9 +26,10 @@ bool ModelLoader::Load(HWND hwnd, ID3D11Device * dev, ID3D11DeviceContext * devc if (pScene == NULL) return false; - this->directory = filename.substr(0, filename.find_last_of('/')); + this->directory = filename.substr(0, filename.find_last_of("/\\")); this->dev = dev; + this->devcon = devcon; this->hwnd = hwnd; processNode(pScene->mRootNode, pScene); @@ -138,12 +145,13 @@ vector ModelLoader::loadMaterialTextures(aiMaterial * mat, aiTextureTyp void ModelLoader::Close() { + for (auto& t : textures_loaded) + t.Release(); + for (int i = 0; i < meshes.size(); i++) { meshes[i].Close(); } - - dev->Release(); } void ModelLoader::processNode(aiNode * node, const aiScene * scene) diff --git a/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/SafeRelease.hpp b/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/SafeRelease.hpp new file mode 100644 index 000000000..2fd80db6c --- /dev/null +++ b/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/SafeRelease.hpp @@ -0,0 +1,57 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2020, 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. +--------------------------------------------------------------------------- +*/ + +#ifdef _MSC_VER +#pragma once +#endif + +/* Used to reduce to reduce the number of lines when calling Release() + on a D3D interface. Implemented as a template instead of a 'SAFE_RELEASE' + MACRO to ease debugging. */ +template +inline void SafeRelease(T*& x) { + if (x) { + x->Release(); + x = nullptr; + } +} diff --git a/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/main.cpp b/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/main.cpp index 2d847095a..781fe89e5 100644 --- a/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/main.cpp +++ b/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/main.cpp @@ -14,12 +14,16 @@ // --------------------------------------------------------------------------- #include +#include +#include #include #include #include #include #include #include "ModelLoader.h" +#include "UTFConverter.h" +#include "SafeRelease.hpp" #pragma comment (lib, "d3d11.lib") #pragma comment (lib, "Dxgi.lib") @@ -27,6 +31,10 @@ #pragma comment (lib, "dxguid.lib") using namespace DirectX; +using namespace AssimpSamples::SharedCode; + +#define VERTEX_SHADER_FILE L"VertexShader.hlsl" +#define PIXEL_SHADER_FILE L"PixelShader.hlsl" // ------------------------------------------------------------ // Structs @@ -45,29 +53,32 @@ struct ConstantBuffer { const char g_szClassName[] = "directxWindowClass"; +static std::string g_ModelPath; UINT width, height; -HWND hwnd; +HWND hwnd = nullptr; // ------------------------------------------------------------ // DirectX Variables // ------------------------------------------------------------ D3D_DRIVER_TYPE g_driverType = D3D_DRIVER_TYPE_NULL; D3D_FEATURE_LEVEL g_featureLevel = D3D_FEATURE_LEVEL_11_0; -ID3D11Device *dev; -ID3D11Device1 *dev1; -ID3D11DeviceContext *devcon; -ID3D11DeviceContext1 *devcon1; -IDXGISwapChain *swapchain; -IDXGISwapChain1 *swapchain1; -ID3D11RenderTargetView *backbuffer; -ID3D11VertexShader *pVS; -ID3D11PixelShader *pPS; -ID3D11InputLayout *pLayout; -ID3D11Buffer *pConstantBuffer; -ID3D11Texture2D *g_pDepthStencil; -ID3D11DepthStencilView *g_pDepthStencilView; -ID3D11SamplerState *TexSamplerState; +ID3D11Device *dev = nullptr; +ID3D11Device1 *dev1 = nullptr; +ID3D11DeviceContext *devcon = nullptr; +ID3D11DeviceContext1 *devcon1 = nullptr; +IDXGISwapChain *swapchain = nullptr; +IDXGISwapChain1 *swapchain1 = nullptr; +ID3D11RenderTargetView *backbuffer = nullptr; +ID3D11VertexShader *pVS = nullptr; +ID3D11PixelShader *pPS = nullptr; +ID3D11InputLayout *pLayout = nullptr; +ID3D11Buffer *pConstantBuffer = nullptr; +ID3D11Texture2D *g_pDepthStencil = nullptr; +ID3D11DepthStencilView *g_pDepthStencilView = nullptr; +ID3D11SamplerState *TexSamplerState = nullptr; +ID3D11RasterizerState *rasterstate = nullptr; +ID3D11Debug* d3d11debug = nullptr; XMMATRIX m_World; XMMATRIX m_View; @@ -91,7 +102,7 @@ void Throwanerror(LPCSTR errormessage); // Our Model // ------------------------------------------------------------ -ModelLoader *ourModel; +ModelLoader *ourModel = nullptr; LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { @@ -109,9 +120,42 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) return 0; } -int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, - LPSTR lpCmdLine, int nCmdShow) +int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, + LPWSTR lpCmdLine, int nCmdShow) { + int argc; + LPWSTR* argv = CommandLineToArgvW(GetCommandLineW(), &argc); + if (!argv) { + MessageBox(NULL, + TEXT("An error occured while reading command line arguments."), + TEXT("Error!"), + MB_ICONERROR | MB_OK); + return EXIT_FAILURE; + } + + // Free memory allocated from CommandLineToArgvW. + auto free_command_line_allocated_memory = [&argv]() { + if (argv) { + LocalFree(argv); + argv = nullptr; + } + }; + + // Ensure that a model file has been specified. + if (argc < 2) { + MessageBox(NULL, + TEXT("No model file specified. The program will now close."), + TEXT("Error!"), + MB_ICONERROR | MB_OK); + free_command_line_allocated_memory(); + return EXIT_FAILURE; + } + + // Retrieve the model file path. + g_ModelPath = UTFConverter(argv[1]).str(); + + free_command_line_allocated_memory(); + WNDCLASSEX wc; MSG msg; @@ -160,26 +204,35 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, width = wr.right - wr.left; height = wr.bottom - wr.top; - InitD3D(hInstance, hwnd); + try { + InitD3D(hInstance, hwnd); - while (true) - { - - if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) + while (true) { - TranslateMessage(&msg); - DispatchMessage(&msg); - if (msg.message == WM_QUIT) - break; + if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + + if (msg.message == WM_QUIT) + break; + } + + RenderFrame(); } - RenderFrame(); + CleanD3D(); + return static_cast(msg.wParam); + } catch (const std::exception& e) { + MessageBox(hwnd, e.what(), TEXT("Error!"), MB_ICONERROR | MB_OK); + CleanD3D(); + return EXIT_FAILURE; + } catch (...) { + MessageBox(hwnd, TEXT("Caught an unknown exception."), TEXT("Error!"), MB_ICONERROR | MB_OK); + CleanD3D(); + return EXIT_FAILURE; } - - CleanD3D(); - - return msg.wParam; } void InitD3D(HINSTANCE hinstance, HWND hWnd) @@ -227,6 +280,12 @@ void InitD3D(HINSTANCE hinstance, HWND hWnd) if (FAILED(hr)) Throwanerror("Directx Device Creation Failed!"); +#if _DEBUG + hr = dev->QueryInterface(IID_PPV_ARGS(&d3d11debug)); + if (FAILED(hr)) + OutputDebugString(TEXT("Failed to retrieve DirectX 11 debug interface.\n")); +#endif + UINT m4xMsaaQuality; dev->CheckMultisampleQualityLevels( DXGI_FORMAT_R8G8B8A8_UNORM, 4, &m4xMsaaQuality); @@ -348,7 +407,6 @@ void InitD3D(HINSTANCE hinstance, HWND hWnd) devcon->OMSetRenderTargets(1, &backbuffer, g_pDepthStencilView); D3D11_RASTERIZER_DESC rasterDesc; - ID3D11RasterizerState *rasterState; rasterDesc.AntialiasedLineEnable = false; rasterDesc.CullMode = D3D11_CULL_BACK; rasterDesc.DepthBias = 0; @@ -360,8 +418,8 @@ void InitD3D(HINSTANCE hinstance, HWND hWnd) rasterDesc.ScissorEnable = false; rasterDesc.SlopeScaledDepthBias = 0.0f; - dev->CreateRasterizerState(&rasterDesc, &rasterState); - devcon->RSSetState(rasterState); + dev->CreateRasterizerState(&rasterDesc, &rasterstate); + devcon->RSSetState(rasterstate); D3D11_VIEWPORT viewport; ZeroMemory(&viewport, sizeof(D3D11_VIEWPORT)); @@ -381,19 +439,38 @@ void InitD3D(HINSTANCE hinstance, HWND hWnd) void CleanD3D(void) { - swapchain->SetFullscreenState(FALSE, NULL); + if (swapchain) + swapchain->SetFullscreenState(FALSE, NULL); - ourModel->Close(); - g_pDepthStencil->Release(); - g_pDepthStencilView->Release(); - pLayout->Release(); - pVS->Release(); - pPS->Release(); - pConstantBuffer->Release(); - swapchain->Release(); - backbuffer->Release(); - dev->Release(); - devcon->Release(); + if (ourModel) { + ourModel->Close(); + delete ourModel; + ourModel = nullptr; + } + SafeRelease(TexSamplerState); + SafeRelease(pConstantBuffer); + SafeRelease(pLayout); + SafeRelease(pVS); + SafeRelease(pPS); + SafeRelease(rasterstate); + SafeRelease(g_pDepthStencilView); + SafeRelease(g_pDepthStencil); + SafeRelease(backbuffer); + SafeRelease(swapchain); + SafeRelease(swapchain1); + SafeRelease(devcon1); + SafeRelease(dev1); + SafeRelease(devcon); +#if _DEBUG + if (d3d11debug) { + OutputDebugString(TEXT("Dumping DirectX 11 live objects.\n")); + d3d11debug->ReportLiveDeviceObjects(D3D11_RLDO_DETAIL); + SafeRelease(d3d11debug); + } else { + OutputDebugString(TEXT("Unable to dump live objects: no DirectX 11 debug interface available.\n")); + } +#endif + SafeRelease(dev); } void RenderFrame(void) @@ -431,8 +508,10 @@ void RenderFrame(void) void InitPipeline() { ID3DBlob *VS, *PS; - CompileShaderFromFile(L"VertexShader.hlsl", 0, "main", "vs_4_0", &VS); - CompileShaderFromFile(L"PixelShader.hlsl", 0, "main", "ps_4_0", &PS); + if(FAILED(CompileShaderFromFile(SHADER_PATH VERTEX_SHADER_FILE, 0, "main", "vs_4_0", &VS))) + Throwanerror(UTFConverter(L"Failed to compile shader from file " VERTEX_SHADER_FILE).c_str()); + if(FAILED(CompileShaderFromFile(SHADER_PATH PIXEL_SHADER_FILE, 0, "main", "ps_4_0", &PS))) + Throwanerror(UTFConverter(L"Failed to compile shader from file " PIXEL_SHADER_FILE).c_str()); dev->CreateVertexShader(VS->GetBufferPointer(), VS->GetBufferSize(), NULL, &pVS); dev->CreatePixelShader(PS->GetBufferPointer(), PS->GetBufferSize(), NULL, &pPS); @@ -485,7 +564,7 @@ void InitGraphics() m_View = XMMatrixLookAtLH(Eye, At, Up); ourModel = new ModelLoader; - if (!ourModel->Load(hwnd, dev, devcon, "Models/myModel.fbx")) + if (!ourModel->Load(hwnd, dev, devcon, g_ModelPath)) Throwanerror("Model couldn't be loaded"); } @@ -514,5 +593,5 @@ HRESULT CompileShaderFromFile(LPCWSTR pFileName, const D3D_SHADER_MACRO* pDefine void Throwanerror(LPCSTR errormessage) { - MessageBox(hwnd, errormessage, "Error!", MB_ICONERROR | MB_OK); -} \ No newline at end of file + throw std::runtime_error(errormessage); +} diff --git a/samples/SimpleTexturedOpenGL/CMakeLists.txt b/samples/SimpleTexturedOpenGL/CMakeLists.txt index adcf882a8..e40c40f29 100644 --- a/samples/SimpleTexturedOpenGL/CMakeLists.txt +++ b/samples/SimpleTexturedOpenGL/CMakeLists.txt @@ -21,6 +21,7 @@ INCLUDE_DIRECTORIES( ${Assimp_SOURCE_DIR}/code ${OPENGL_INCLUDE_DIR} ${GLUT_INCLUDE_DIR} + ${SAMPLES_SHARED_CODE_DIR} ) LINK_DIRECTORIES( @@ -31,6 +32,8 @@ LINK_DIRECTORIES( ADD_EXECUTABLE( assimp_simpletexturedogl WIN32 SimpleTexturedOpenGL/include/boost_includes.h SimpleTexturedOpenGL/src/model_loading.cpp + ${SAMPLES_SHARED_CODE_DIR}/UTFConverter.cpp + ${SAMPLES_SHARED_CODE_DIR}/UTFConverter.h ) SET_PROPERTY(TARGET assimp_simpletexturedogl PROPERTY DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX}) diff --git a/samples/SimpleTexturedOpenGL/SimpleTexturedOpenGL/src/model_loading.cpp b/samples/SimpleTexturedOpenGL/SimpleTexturedOpenGL/src/model_loading.cpp index 8c2a08b2e..452c0715c 100644 --- a/samples/SimpleTexturedOpenGL/SimpleTexturedOpenGL/src/model_loading.cpp +++ b/samples/SimpleTexturedOpenGL/SimpleTexturedOpenGL/src/model_loading.cpp @@ -21,8 +21,6 @@ #define STB_IMAGE_IMPLEMENTATION #include "contrib/stb_image/stb_image.h" -#include -#include #include //to map image filenames to textureIds @@ -35,7 +33,7 @@ #include #include #include - +#include "UTFConverter.h" // The default hard-coded path. Can be overridden by supplying a path through the command line. static std::string modelpath = "../../test/models/OBJ/spider.obj"; @@ -77,35 +75,7 @@ GLuint* textureIds; // pointer to texture Array // Create an instance of the Importer class Assimp::Importer importer; -// Used to convert between multibyte and unicode strings. -class UTFConverter { - using UTFConverterImpl = std::wstring_convert, wchar_t>; -public: - UTFConverter(const char* s) : - s_(s), - ws_(impl_.from_bytes(s)) { - } - UTFConverter(const std::string& s) : - s_(s), - ws_(impl_.from_bytes(s)) { - } - UTFConverter(const std::wstring& s) : - s_(impl_.to_bytes(s)), - ws_(s) { - } - inline const std::string& str() const { - return s_; - } - inline const wchar_t* c_wstr() const { - return ws_.c_str(); - } -private: - static UTFConverterImpl impl_; - std::string s_; - std::wstring ws_; -}; - -typename UTFConverter::UTFConverterImpl UTFConverter::impl_; +using namespace AssimpSamples::SharedCode; void createAILogger() { From c620e9a2ac7db28c6b94a5b6388825783aee2e2b Mon Sep 17 00:00:00 2001 From: Marc-Antoine Lortie Date: Fri, 6 Mar 2020 13:28:05 -0500 Subject: [PATCH 089/330] Fixed memory leak caused by glutMainLoop() not returning. Fixed memory leak by allowing glutMainLoop() to return to allow for the scene and streams to be released. --- samples/SimpleOpenGL/Sample_SimpleOpenGL.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/samples/SimpleOpenGL/Sample_SimpleOpenGL.c b/samples/SimpleOpenGL/Sample_SimpleOpenGL.c index ac31d6f3e..f59ab92e5 100644 --- a/samples/SimpleOpenGL/Sample_SimpleOpenGL.c +++ b/samples/SimpleOpenGL/Sample_SimpleOpenGL.c @@ -15,9 +15,9 @@ #include #ifdef __APPLE__ -#include +#include #else -#include +#include #endif /* assimp include files. These three are usually needed. */ @@ -392,6 +392,7 @@ int main(int argc, char **argv) glutInitWindowPosition(100,100); glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH); glutInit(&argc, argv); + glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_GLUTMAINLOOP_RETURNS); glutCreateWindow("Assimp - Very simple OpenGL sample"); glutDisplayFunc(display); From 31c6f0db928add0e4ff22877bd4c91b5418aa2e4 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sat, 7 Mar 2020 12:19:55 +0100 Subject: [PATCH 090/330] Update Mesh.h Apply code style. --- .../SimpleTexturedDirectx11/Mesh.h | 124 +++++++++--------- 1 file changed, 59 insertions(+), 65 deletions(-) diff --git a/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/Mesh.h b/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/Mesh.h index 3a2875a1f..fb2f7f7db 100644 --- a/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/Mesh.h +++ b/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/Mesh.h @@ -7,11 +7,9 @@ #include #include #include -using namespace std; - -#include #include #include + using namespace DirectX; #include "SafeRelease.hpp" @@ -26,88 +24,84 @@ struct Texture { string path; ID3D11ShaderResourceView *texture; - inline void Release() { + void Release() { SafeRelease(texture); } }; class Mesh { public: - vector vertices; - vector indices; - vector textures; - ID3D11Device *dev; + std::vector vertices; + std::vector indices; + std::vector textures; + ID3D11Device *dev; - Mesh(ID3D11Device *dev, const vector& vertices, const vector& indices, const vector& textures) : - vertices(vertices), - indices(indices), - textures(textures), - dev(dev), - VertexBuffer(nullptr), - IndexBuffer(nullptr) - { - this->setupMesh(this->dev); - } + Mesh(ID3D11Device *dev, const vector& vertices, const vector& indices, const vector& textures) : + vertices(vertices), + indices(indices), + textures(textures), + dev(dev), + VertexBuffer(nullptr), + IndexBuffer(nullptr) { + this->setupMesh(this->dev); + } - void Draw(ID3D11DeviceContext *devcon) - { - UINT stride = sizeof(VERTEX); - UINT offset = 0; + void Draw(ID3D11DeviceContext *devcon) { + UINT stride = sizeof(VERTEX); + UINT offset = 0; - devcon->IASetVertexBuffers(0, 1, &VertexBuffer, &stride, &offset); - devcon->IASetIndexBuffer(IndexBuffer, DXGI_FORMAT_R32_UINT, 0); + devcon->IASetVertexBuffers(0, 1, &VertexBuffer, &stride, &offset); + devcon->IASetIndexBuffer(IndexBuffer, DXGI_FORMAT_R32_UINT, 0); - devcon->PSSetShaderResources(0, 1, &textures[0].texture); + devcon->PSSetShaderResources(0, 1, &textures[0].texture); - devcon->DrawIndexed(static_cast(indices.size()), 0, 0); - } + devcon->DrawIndexed(static_cast(indices.size()), 0, 0); + } - void Close() - { - SafeRelease(VertexBuffer); - SafeRelease(IndexBuffer); - } + void Close() { + SafeRelease(VertexBuffer); + SafeRelease(IndexBuffer); + } private: - /* Render data */ - ID3D11Buffer *VertexBuffer, *IndexBuffer; + // Render data + ID3D11Buffer *VertexBuffer, *IndexBuffer; - /* Functions */ - // Initializes all the buffer objects/arrays - void setupMesh(ID3D11Device *dev) - { - HRESULT hr; + // Functions + // Initializes all the buffer objects/arrays + void setupMesh(ID3D11Device *dev) { + HRESULT hr; - D3D11_BUFFER_DESC vbd; - vbd.Usage = D3D11_USAGE_IMMUTABLE; - vbd.ByteWidth = static_cast(sizeof(VERTEX) * vertices.size()); - vbd.BindFlags = D3D11_BIND_VERTEX_BUFFER; - vbd.CPUAccessFlags = 0; - vbd.MiscFlags = 0; + D3D11_BUFFER_DESC vbd; + vbd.Usage = D3D11_USAGE_IMMUTABLE; + vbd.ByteWidth = static_cast(sizeof(VERTEX) * vertices.size()); + vbd.BindFlags = D3D11_BIND_VERTEX_BUFFER; + vbd.CPUAccessFlags = 0; + vbd.MiscFlags = 0; - D3D11_SUBRESOURCE_DATA initData; - initData.pSysMem = &vertices[0]; + D3D11_SUBRESOURCE_DATA initData; + initData.pSysMem = &vertices[0]; - hr = dev->CreateBuffer(&vbd, &initData, &VertexBuffer); - if (FAILED(hr)) { - Close(); - throw std::runtime_error("Failed to create vertex buffer."); - } + hr = dev->CreateBuffer(&vbd, &initData, &VertexBuffer); + if (FAILED(hr)) { + Close(); + throw std::runtime_error("Failed to create vertex buffer."); + } - D3D11_BUFFER_DESC ibd; - ibd.Usage = D3D11_USAGE_IMMUTABLE; - ibd.ByteWidth = static_cast(sizeof(UINT) * indices.size()); - ibd.BindFlags = D3D11_BIND_INDEX_BUFFER; - ibd.CPUAccessFlags = 0; - ibd.MiscFlags = 0; + D3D11_BUFFER_DESC ibd; + ibd.Usage = D3D11_USAGE_IMMUTABLE; + ibd.ByteWidth = static_cast(sizeof(UINT) * indices.size()); + ibd.BindFlags = D3D11_BIND_INDEX_BUFFER; + ibd.CPUAccessFlags = 0; + ibd.MiscFlags = 0; - initData.pSysMem = &indices[0]; + initData.pSysMem = &indices[0]; - hr = dev->CreateBuffer(&ibd, &initData, &IndexBuffer); - if (FAILED(hr)) { - Close(); - throw std::runtime_error("Failed to create index buffer."); - } - } + hr = dev->CreateBuffer(&ibd, &initData, &IndexBuffer); + if (FAILED(hr)) { + Close(); + throw std::runtime_error("Failed to create index buffer."); + } + } }; #endif From b5d65bf94e2cedd5dd60443d66de92d61f3ccf6d Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sat, 7 Mar 2020 12:22:57 +0100 Subject: [PATCH 091/330] Update ModelLoader.cpp Apply asimp-code-style. --- .../SimpleTexturedDirectx11/ModelLoader.cpp | 108 +++++++----------- 1 file changed, 40 insertions(+), 68 deletions(-) diff --git a/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/ModelLoader.cpp b/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/ModelLoader.cpp index b0f086a5d..1ab5b61fb 100644 --- a/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/ModelLoader.cpp +++ b/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/ModelLoader.cpp @@ -1,22 +1,21 @@ #include "ModelLoader.h" ModelLoader::ModelLoader() : - dev(nullptr), - devcon(nullptr), - meshes(), - directory(), - textures_loaded(), - hwnd(nullptr) -{ + dev(nullptr), + devcon(nullptr), + meshes(), + directory(), + textures_loaded(), + hwnd(nullptr) { + // empty } -ModelLoader::~ModelLoader() -{ +ModelLoader::~ModelLoader() { + // empty } -bool ModelLoader::Load(HWND hwnd, ID3D11Device * dev, ID3D11DeviceContext * devcon, std::string filename) -{ +bool ModelLoader::Load(HWND hwnd, ID3D11Device * dev, ID3D11DeviceContext * devcon, std::string filename) { Assimp::Importer importer; const aiScene* pScene = importer.ReadFile(filename, @@ -37,41 +36,37 @@ bool ModelLoader::Load(HWND hwnd, ID3D11Device * dev, ID3D11DeviceContext * devc return true; } -void ModelLoader::Draw(ID3D11DeviceContext * devcon) -{ - for (int i = 0; i < meshes.size(); i++) - { +void ModelLoader::Draw(ID3D11DeviceContext * devcon) { + for (int i = 0; i < meshes.size(); ++i ) { meshes[i].Draw(devcon); } } string textype; -Mesh ModelLoader::processMesh(aiMesh * mesh, const aiScene * scene) -{ +Mesh ModelLoader::processMesh(aiMesh * mesh, const aiScene * scene) { // Data to fill vector vertices; vector indices; vector textures; - if (mesh->mMaterialIndex >= 0) - { + if (mesh->mMaterialIndex >= 0) { aiMaterial* mat = scene->mMaterials[mesh->mMaterialIndex]; - if (textype.empty()) textype = determineTextureType(scene, mat); + if (textype.empty()) { + textype = determineTextureType(scene, mat); + } } // Walk through each of the mesh's vertices - for (UINT i = 0; i < mesh->mNumVertices; i++) - { + for (UINT i = 0; i < mesh->mNumVertices; i++) { VERTEX vertex; vertex.X = mesh->mVertices[i].x; vertex.Y = mesh->mVertices[i].y; vertex.Z = mesh->mVertices[i].z; - if (mesh->mTextureCoords[0]) - { + if (mesh->mTextureCoords[0]) { vertex.texcoord.x = (float)mesh->mTextureCoords[0][i].x; vertex.texcoord.y = (float)mesh->mTextureCoords[0][i].y; } @@ -79,16 +74,14 @@ Mesh ModelLoader::processMesh(aiMesh * mesh, const aiScene * scene) vertices.push_back(vertex); } - for (UINT i = 0; i < mesh->mNumFaces; i++) - { + for (UINT i = 0; i < mesh->mNumFaces; i++) { aiFace face = mesh->mFaces[i]; for (UINT j = 0; j < face.mNumIndices; j++) indices.push_back(face.mIndices[j]); } - if (mesh->mMaterialIndex >= 0) - { + if (mesh->mMaterialIndex >= 0) { aiMaterial* material = scene->mMaterials[mesh->mMaterialIndex]; vector diffuseMaps = this->loadMaterialTextures(material, aiTextureType_DIFFUSE, "texture_diffuse", scene); @@ -98,35 +91,27 @@ Mesh ModelLoader::processMesh(aiMesh * mesh, const aiScene * scene) return Mesh(dev, vertices, indices, textures); } -vector ModelLoader::loadMaterialTextures(aiMaterial * mat, aiTextureType type, string typeName, const aiScene * scene) -{ +vector ModelLoader::loadMaterialTextures(aiMaterial * mat, aiTextureType type, string typeName, const aiScene * scene) { vector textures; - for (UINT i = 0; i < mat->GetTextureCount(type); i++) - { + for (UINT i = 0; i < mat->GetTextureCount(type); i++) { aiString str; mat->GetTexture(type, i, &str); // Check if texture was loaded before and if so, continue to next iteration: skip loading a new texture bool skip = false; - for (UINT j = 0; j < textures_loaded.size(); j++) - { - if (std::strcmp(textures_loaded[j].path.c_str(), str.C_Str()) == 0) - { + for (UINT j = 0; j < textures_loaded.size(); j++) { + if (std::strcmp(textures_loaded[j].path.c_str(), str.C_Str()) == 0) { textures.push_back(textures_loaded[j]); skip = true; // A texture with the same filepath has already been loaded, continue to next one. (optimization) break; } } - if (!skip) - { // If texture hasn't been loaded already, load it + if (!skip) { // If texture hasn't been loaded already, load it HRESULT hr; Texture texture; - if (textype == "embedded compressed texture") - { + if (textype == "embedded compressed texture") { int textureindex = getTextureIndex(&str); texture.texture = getTextureFromModel(scene, textureindex); - } - else - { + } else { string filename = string(str.C_Str()); filename = directory + '/' + filename; wstring filenamews = wstring(filename.begin(), filename.end()); @@ -143,65 +128,52 @@ vector ModelLoader::loadMaterialTextures(aiMaterial * mat, aiTextureTyp return textures; } -void ModelLoader::Close() -{ +void ModelLoader::Close() { for (auto& t : textures_loaded) t.Release(); - for (int i = 0; i < meshes.size(); i++) - { + for (int i = 0; i < meshes.size(); i++) { meshes[i].Close(); } } -void ModelLoader::processNode(aiNode * node, const aiScene * scene) -{ - for (UINT i = 0; i < node->mNumMeshes; i++) - { +void ModelLoader::processNode(aiNode * node, const aiScene * scene) { + for (UINT i = 0; i < node->mNumMeshes; i++) { aiMesh* mesh = scene->mMeshes[node->mMeshes[i]]; meshes.push_back(this->processMesh(mesh, scene)); } - for (UINT i = 0; i < node->mNumChildren; i++) - { + for (UINT i = 0; i < node->mNumChildren; i++) { this->processNode(node->mChildren[i], scene); } } -string ModelLoader::determineTextureType(const aiScene * scene, aiMaterial * mat) -{ +string ModelLoader::determineTextureType(const aiScene * scene, aiMaterial * mat) { aiString textypeStr; mat->GetTexture(aiTextureType_DIFFUSE, 0, &textypeStr); string textypeteststr = textypeStr.C_Str(); - if (textypeteststr == "*0" || textypeteststr == "*1" || textypeteststr == "*2" || textypeteststr == "*3" || textypeteststr == "*4" || textypeteststr == "*5") - { - if (scene->mTextures[0]->mHeight == 0) - { + if (textypeteststr == "*0" || textypeteststr == "*1" || textypeteststr == "*2" || textypeteststr == "*3" || textypeteststr == "*4" || textypeteststr == "*5") { + if (scene->mTextures[0]->mHeight == 0) { return "embedded compressed texture"; - } - else - { + } else { return "embedded non-compressed texture"; } } - if (textypeteststr.find('.') != string::npos) - { + if (textypeteststr.find('.') != string::npos) { return "textures are on disk"; } return "."; } -int ModelLoader::getTextureIndex(aiString * str) -{ +int ModelLoader::getTextureIndex(aiString * str) { string tistr; tistr = str->C_Str(); tistr = tistr.substr(1); return stoi(tistr); } -ID3D11ShaderResourceView * ModelLoader::getTextureFromModel(const aiScene * scene, int textureindex) -{ +ID3D11ShaderResourceView * ModelLoader::getTextureFromModel(const aiScene * scene, int textureindex) { HRESULT hr; ID3D11ShaderResourceView *texture; From dda083fa7bd7034f8fb31bf8ffc0a4d2bccf80fd Mon Sep 17 00:00:00 2001 From: Marc-Antoine Lortie Date: Sun, 8 Mar 2020 10:50:18 -0400 Subject: [PATCH 092/330] Added missing std namespace prefix to std types. --- .../SimpleTexturedDirectx11/Mesh.h | 6 ++--- .../SimpleTexturedDirectx11/ModelLoader.cpp | 26 +++++++++---------- .../SimpleTexturedDirectx11/ModelLoader.h | 8 +++--- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/Mesh.h b/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/Mesh.h index fb2f7f7db..125b3e585 100644 --- a/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/Mesh.h +++ b/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/Mesh.h @@ -20,8 +20,8 @@ struct VERTEX { }; struct Texture { - string type; - string path; + std::string type; + std::string path; ID3D11ShaderResourceView *texture; void Release() { @@ -36,7 +36,7 @@ public: std::vector textures; ID3D11Device *dev; - Mesh(ID3D11Device *dev, const vector& vertices, const vector& indices, const vector& textures) : + Mesh(ID3D11Device *dev, const std::vector& vertices, const std::vector& indices, const std::vector& textures) : vertices(vertices), indices(indices), textures(textures), diff --git a/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/ModelLoader.cpp b/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/ModelLoader.cpp index 1ab5b61fb..806320144 100644 --- a/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/ModelLoader.cpp +++ b/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/ModelLoader.cpp @@ -42,13 +42,13 @@ void ModelLoader::Draw(ID3D11DeviceContext * devcon) { } } -string textype; +std::string textype; Mesh ModelLoader::processMesh(aiMesh * mesh, const aiScene * scene) { // Data to fill - vector vertices; - vector indices; - vector textures; + std::vector vertices; + std::vector indices; + std::vector textures; if (mesh->mMaterialIndex >= 0) { aiMaterial* mat = scene->mMaterials[mesh->mMaterialIndex]; @@ -84,15 +84,15 @@ Mesh ModelLoader::processMesh(aiMesh * mesh, const aiScene * scene) { if (mesh->mMaterialIndex >= 0) { aiMaterial* material = scene->mMaterials[mesh->mMaterialIndex]; - vector diffuseMaps = this->loadMaterialTextures(material, aiTextureType_DIFFUSE, "texture_diffuse", scene); + std::vector diffuseMaps = this->loadMaterialTextures(material, aiTextureType_DIFFUSE, "texture_diffuse", scene); textures.insert(textures.end(), diffuseMaps.begin(), diffuseMaps.end()); } return Mesh(dev, vertices, indices, textures); } -vector ModelLoader::loadMaterialTextures(aiMaterial * mat, aiTextureType type, string typeName, const aiScene * scene) { - vector textures; +std::vector ModelLoader::loadMaterialTextures(aiMaterial * mat, aiTextureType type, std::string typeName, const aiScene * scene) { + std::vector textures; for (UINT i = 0; i < mat->GetTextureCount(type); i++) { aiString str; mat->GetTexture(type, i, &str); @@ -112,9 +112,9 @@ vector ModelLoader::loadMaterialTextures(aiMaterial * mat, aiTextureTyp int textureindex = getTextureIndex(&str); texture.texture = getTextureFromModel(scene, textureindex); } else { - string filename = string(str.C_Str()); + std::string filename = std::string(str.C_Str()); filename = directory + '/' + filename; - wstring filenamews = wstring(filename.begin(), filename.end()); + std::wstring filenamews = std::wstring(filename.begin(), filename.end()); hr = CreateWICTextureFromFile(dev, devcon, filenamews.c_str(), nullptr, &texture.texture); if (FAILED(hr)) MessageBox(hwnd, "Texture couldn't be loaded", "Error!", MB_ICONERROR | MB_OK); @@ -148,10 +148,10 @@ void ModelLoader::processNode(aiNode * node, const aiScene * scene) { } } -string ModelLoader::determineTextureType(const aiScene * scene, aiMaterial * mat) { +std::string ModelLoader::determineTextureType(const aiScene * scene, aiMaterial * mat) { aiString textypeStr; mat->GetTexture(aiTextureType_DIFFUSE, 0, &textypeStr); - string textypeteststr = textypeStr.C_Str(); + std::string textypeteststr = textypeStr.C_Str(); if (textypeteststr == "*0" || textypeteststr == "*1" || textypeteststr == "*2" || textypeteststr == "*3" || textypeteststr == "*4" || textypeteststr == "*5") { if (scene->mTextures[0]->mHeight == 0) { return "embedded compressed texture"; @@ -159,7 +159,7 @@ string ModelLoader::determineTextureType(const aiScene * scene, aiMaterial * mat return "embedded non-compressed texture"; } } - if (textypeteststr.find('.') != string::npos) { + if (textypeteststr.find('.') != std::string::npos) { return "textures are on disk"; } @@ -167,7 +167,7 @@ string ModelLoader::determineTextureType(const aiScene * scene, aiMaterial * mat } int ModelLoader::getTextureIndex(aiString * str) { - string tistr; + std::string tistr; tistr = str->C_Str(); tistr = tistr.substr(1); return stoi(tistr); diff --git a/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/ModelLoader.h b/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/ModelLoader.h index 9b4a53c27..18ad03fa0 100644 --- a/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/ModelLoader.h +++ b/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/ModelLoader.h @@ -28,14 +28,14 @@ private: ID3D11Device *dev; ID3D11DeviceContext *devcon; std::vector meshes; - string directory; - vector textures_loaded; + std::string directory; + std::vector textures_loaded; HWND hwnd; void processNode(aiNode* node, const aiScene* scene); Mesh processMesh(aiMesh* mesh, const aiScene* scene); - vector loadMaterialTextures(aiMaterial* mat, aiTextureType type, string typeName, const aiScene* scene); - string determineTextureType(const aiScene* scene, aiMaterial* mat); + std::vector loadMaterialTextures(aiMaterial* mat, aiTextureType type, std::string typeName, const aiScene* scene); + std::string determineTextureType(const aiScene* scene, aiMaterial* mat); int getTextureIndex(aiString* str); ID3D11ShaderResourceView* getTextureFromModel(const aiScene* scene, int textureindex); }; From 424f5e939f2c8f87116d757efe4f937583780028 Mon Sep 17 00:00:00 2001 From: Marc-Antoine Lortie Date: Sun, 8 Mar 2020 12:18:09 -0400 Subject: [PATCH 093/330] Fixed wrong matrix type used in comparaison operators. --- include/assimp/matrix3x3.h | 6 +++--- include/assimp/matrix3x3.inl | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/assimp/matrix3x3.h b/include/assimp/matrix3x3.h index f9880ab9e..9f11b6b83 100644 --- a/include/assimp/matrix3x3.h +++ b/include/assimp/matrix3x3.h @@ -93,10 +93,10 @@ public: const TReal* operator[] (unsigned int p_iIndex) const; // comparison operators - bool operator== (const aiMatrix4x4t& m) const; - bool operator!= (const aiMatrix4x4t& m) const; + bool operator== (const aiMatrix3x3t& m) const; + bool operator!= (const aiMatrix3x3t& m) const; - bool Equal(const aiMatrix4x4t& m, TReal epsilon = 1e-6) const; + bool Equal(const aiMatrix3x3t& m, TReal epsilon = 1e-6) const; template operator aiMatrix3x3t () const; diff --git a/include/assimp/matrix3x3.inl b/include/assimp/matrix3x3.inl index b11e036b1..0b9565604 100644 --- a/include/assimp/matrix3x3.inl +++ b/include/assimp/matrix3x3.inl @@ -141,7 +141,7 @@ const TReal* aiMatrix3x3t::operator[] (unsigned int p_iIndex) const { // ------------------------------------------------------------------------------------------------ template AI_FORCE_INLINE -bool aiMatrix3x3t::operator== (const aiMatrix4x4t& m) const { +bool aiMatrix3x3t::operator== (const aiMatrix3x3t& m) const { return a1 == m.a1 && a2 == m.a2 && a3 == m.a3 && b1 == m.b1 && b2 == m.b2 && b3 == m.b3 && c1 == m.c1 && c2 == m.c2 && c3 == m.c3; @@ -150,14 +150,14 @@ bool aiMatrix3x3t::operator== (const aiMatrix4x4t& m) const { // ------------------------------------------------------------------------------------------------ template AI_FORCE_INLINE -bool aiMatrix3x3t::operator!= (const aiMatrix4x4t& m) const { +bool aiMatrix3x3t::operator!= (const aiMatrix3x3t& m) const { return !(*this == m); } // --------------------------------------------------------------------------- template AI_FORCE_INLINE -bool aiMatrix3x3t::Equal(const aiMatrix4x4t& m, TReal epsilon) const { +bool aiMatrix3x3t::Equal(const aiMatrix3x3t& m, TReal epsilon) const { return std::abs(a1 - m.a1) <= epsilon && std::abs(a2 - m.a2) <= epsilon && From e8d2b840178b2b22336eb02b2535f32f3d5cc37b Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sun, 8 Mar 2020 21:24:01 +0100 Subject: [PATCH 094/330] clean all warnings for vs-2019 --- code/3DS/3DSExporter.cpp | 48 +- code/3MF/D3MFExporter.cpp | 8 +- code/Assbin/AssbinFileWriter.cpp | 5 +- code/Assjson/json_exporter.cpp | 20 +- code/Assxml/AssxmlFileWriter.cpp | 14 +- code/Collada/ColladaExporter.cpp | 38 +- code/FBX/FBXCommon.h | 58 +- code/FBX/FBXConverter.cpp | 6708 ++++++++--------- code/FBX/FBXConverter.h | 19 +- code/FBX/FBXExportNode.cpp | 53 +- code/FBX/FBXExporter.cpp | 33 +- code/FBX/FBXMaterial.cpp | 4 +- code/FBX/FBXModel.cpp | 77 +- code/FBX/FBXParser.h | 4 +- code/FBX/FBXProperties.cpp | 14 +- code/Importer/IFC/IFCCurve.cpp | 14 +- code/Importer/IFC/IFCGeometry.cpp | 4 +- code/Importer/IFC/IFCOpenings.cpp | 4 +- code/Importer/StepFile/StepFileGen1.cpp | 12 +- code/Importer/StepFile/StepFileGen2.cpp | 47 +- code/Importer/StepFile/StepFileGen3.cpp | 188 +- code/Importer/StepFile/StepFileImporter.cpp | 2 +- code/M3D/M3DExporter.cpp | 553 +- code/M3D/m3d.h | 6626 ++++++++-------- code/MMD/MMDVmdParser.h | 6 +- code/Obj/ObjExporter.cpp | 2 +- code/Ogre/OgreBinarySerializer.cpp | 520 +- code/Q3BSP/Q3BSPFileImporter.cpp | 31 +- code/Q3D/Q3DLoader.cpp | 15 +- code/SMD/SMDLoader.cpp | 18 +- code/STL/STLLoader.cpp | 353 +- code/STL/STLLoader.h | 7 +- code/Step/STEPFile.h | 9 +- code/Terragen/TerragenLoader.cpp | 7 +- code/Unreal/UnrealLoader.cpp | 5 +- code/X/XFileImporter.cpp | 6 +- code/X3D/FIReader.cpp | 11 +- code/glTF/glTFAsset.h | 2 +- code/glTF/glTFAsset.inl | 1274 ++-- code/glTF/glTFAssetWriter.inl | 8 +- code/glTF/glTFExporter.cpp | 17 +- code/glTF2/glTF2Asset.inl | 1196 ++- code/glTF2/glTF2AssetWriter.inl | 15 +- code/glTF2/glTF2Exporter.cpp | 18 +- code/glTF2/glTF2Importer.cpp | 4 +- contrib/Open3DGC/o3dgcSC3DMCDecoder.inl | 14 +- contrib/Open3DGC/o3dgcSC3DMCEncoder.inl | 15 +- contrib/Open3DGC/o3dgcTriangleListEncoder.inl | 4 +- contrib/poly2tri/poly2tri/sweep/sweep.cc | 9 +- contrib/unzip/crypt.h | 3 +- contrib/unzip/ioapi.c | 5 + contrib/unzip/unzip.c | 4 + contrib/zip/src/miniz.h | 2 +- contrib/zip/src/zip.c | 9 +- include/assimp/StringUtils.h | 2 +- 55 files changed, 9135 insertions(+), 9009 deletions(-) diff --git a/code/3DS/3DSExporter.cpp b/code/3DS/3DSExporter.cpp index 14810cbff..403ca20a2 100644 --- a/code/3DS/3DSExporter.cpp +++ b/code/3DS/3DSExporter.cpp @@ -80,7 +80,7 @@ namespace { { chunk_start_pos = writer.GetCurrentPos(); writer.PutU2(chunk_type); - writer.PutU4(CHUNK_SIZE_NOT_SET); + writer.PutU4((uint32_t)CHUNK_SIZE_NOT_SET); } ~ChunkWriter() { @@ -193,21 +193,21 @@ Discreet3DSExporter:: Discreet3DSExporter(std::shared_ptr &outfile, co CollectTrafos(scene->mRootNode, trafos); CollectMeshes(scene->mRootNode, meshes); - ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAIN); + ChunkWriter curRootChunk(writer, Discreet3DS::CHUNK_MAIN); { - ChunkWriter chunk(writer, Discreet3DS::CHUNK_OBJMESH); + ChunkWriter curChunk(writer, Discreet3DS::CHUNK_OBJMESH); WriteMaterials(); WriteMeshes(); { - ChunkWriter chunk(writer, Discreet3DS::CHUNK_MASTER_SCALE); + ChunkWriter curChunk1(writer, Discreet3DS::CHUNK_MASTER_SCALE); writer.PutF4(1.0f); } } { - ChunkWriter chunk(writer, Discreet3DS::CHUNK_KEYFRAMER); + ChunkWriter curChunk(writer, Discreet3DS::CHUNK_KEYFRAMER); WriteHierarchy(*scene->mRootNode, -1, -1); } } @@ -223,9 +223,9 @@ int Discreet3DSExporter::WriteHierarchy(const aiNode& node, int seq, int sibling { // 3DS scene hierarchy is serialized as in http://www.martinreddy.net/gfx/3d/3DS.spec { - ChunkWriter chunk(writer, Discreet3DS::CHUNK_TRACKINFO); + ChunkWriter curRootChunk(writer, Discreet3DS::CHUNK_TRACKINFO); { - ChunkWriter chunk(writer, Discreet3DS::CHUNK_TRACKOBJNAME); + ChunkWriter curChunk(writer, Discreet3DS::CHUNK_TRACKOBJNAME); // Assimp node names are unique and distinct from all mesh-node // names we generate; thus we can use them as-is @@ -237,7 +237,7 @@ int Discreet3DSExporter::WriteHierarchy(const aiNode& node, int seq, int sibling int16_t hierarchy_pos = static_cast(seq); if (sibling_level != -1) { - hierarchy_pos = sibling_level; + hierarchy_pos =(uint16_t) sibling_level; } // Write the hierarchy position @@ -262,7 +262,7 @@ int Discreet3DSExporter::WriteHierarchy(const aiNode& node, int seq, int sibling const unsigned int mesh_idx = node.mMeshes[i]; const aiMesh& mesh = *scene->mMeshes[mesh_idx]; - ChunkWriter chunk(writer, Discreet3DS::CHUNK_TRACKINFO); + ChunkWriter curChunk(writer, Discreet3DS::CHUNK_TRACKINFO); { ChunkWriter chunk(writer, Discreet3DS::CHUNK_TRACKOBJNAME); WriteString(GetMeshName(mesh, mesh_idx, node)); @@ -279,7 +279,7 @@ int Discreet3DSExporter::WriteHierarchy(const aiNode& node, int seq, int sibling void Discreet3DSExporter::WriteMaterials() { for (unsigned int i = 0; i < scene->mNumMaterials; ++i) { - ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_MATERIAL); + ChunkWriter curRootChunk(writer, Discreet3DS::CHUNK_MAT_MATERIAL); const aiMaterial& mat = *scene->mMaterials[i]; { @@ -290,22 +290,22 @@ void Discreet3DSExporter::WriteMaterials() aiColor3D color; if (mat.Get(AI_MATKEY_COLOR_DIFFUSE, color) == AI_SUCCESS) { - ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_DIFFUSE); + ChunkWriter curChunk(writer, Discreet3DS::CHUNK_MAT_DIFFUSE); WriteColor(color); } if (mat.Get(AI_MATKEY_COLOR_SPECULAR, color) == AI_SUCCESS) { - ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_SPECULAR); + ChunkWriter curChunk(writer, Discreet3DS::CHUNK_MAT_SPECULAR); WriteColor(color); } if (mat.Get(AI_MATKEY_COLOR_AMBIENT, color) == AI_SUCCESS) { - ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_AMBIENT); + ChunkWriter curChunk(writer, Discreet3DS::CHUNK_MAT_AMBIENT); WriteColor(color); } if (mat.Get(AI_MATKEY_COLOR_EMISSIVE, color) == AI_SUCCESS) { - ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_SELF_ILLUM); + ChunkWriter curChunk(writer, Discreet3DS::CHUNK_MAT_SELF_ILLUM); WriteColor(color); } @@ -389,14 +389,14 @@ void Discreet3DSExporter::WriteTexture(const aiMaterial& mat, aiTextureType type ChunkWriter chunk(writer, chunk_flags); { - ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAPFILE); + ChunkWriter curChunk(writer, Discreet3DS::CHUNK_MAPFILE); WriteString(path); } WritePercentChunk(blend); { - ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_MAP_TILING); + ChunkWriter curChunk(writer, Discreet3DS::CHUNK_MAT_MAP_TILING); uint16_t val = 0; // WRAP if (map_mode[0] == aiTextureMapMode_Mirror) { val = 0x2; @@ -447,7 +447,7 @@ void Discreet3DSExporter::WriteMeshes() // Vertices in world space { - ChunkWriter chunk(writer, Discreet3DS::CHUNK_VERTLIST); + ChunkWriter curChunk(writer, Discreet3DS::CHUNK_VERTLIST); const uint16_t count = static_cast(mesh.mNumVertices); writer.PutU2(count); @@ -461,7 +461,7 @@ void Discreet3DSExporter::WriteMeshes() // UV coordinates if (mesh.HasTextureCoords(0)) { - ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAPLIST); + ChunkWriter curChunk(writer, Discreet3DS::CHUNK_MAPLIST); const uint16_t count = static_cast(mesh.mNumVertices); writer.PutU2(count); @@ -474,7 +474,7 @@ void Discreet3DSExporter::WriteMeshes() // Faces (indices) { - ChunkWriter chunk(writer, Discreet3DS::CHUNK_FACELIST); + ChunkWriter curChunk(writer, Discreet3DS::CHUNK_FACELIST); ai_assert(mesh.mNumFaces <= 0xffff); @@ -513,7 +513,7 @@ void Discreet3DSExporter::WriteMeshes() // Transformation matrix by which the mesh vertices have been pre-transformed with. { - ChunkWriter chunk(writer, Discreet3DS::CHUNK_TRMATRIX); + ChunkWriter curChunk(writer, Discreet3DS::CHUNK_TRMATRIX); for (unsigned int r = 0; r < 4; ++r) { for (unsigned int c = 0; c < 3; ++c) { writer.PutF4(trafo[r][c]); @@ -526,7 +526,7 @@ void Discreet3DSExporter::WriteMeshes() // ------------------------------------------------------------------------------------------------ void Discreet3DSExporter::WriteFaceMaterialChunk(const aiMesh& mesh) { - ChunkWriter chunk(writer, Discreet3DS::CHUNK_FACEMAT); + ChunkWriter curChunk(writer, Discreet3DS::CHUNK_FACEMAT); const std::string& name = GetMaterialName(*scene->mMaterials[mesh.mMaterialIndex], mesh.mMaterialIndex); WriteString(name); @@ -559,7 +559,7 @@ void Discreet3DSExporter::WriteString(const aiString& s) { // ------------------------------------------------------------------------------------------------ void Discreet3DSExporter::WriteColor(const aiColor3D& color) { - ChunkWriter chunk(writer, Discreet3DS::CHUNK_RGBF); + ChunkWriter curChunk(writer, Discreet3DS::CHUNK_RGBF); writer.PutF4(color.r); writer.PutF4(color.g); writer.PutF4(color.b); @@ -567,13 +567,13 @@ void Discreet3DSExporter::WriteColor(const aiColor3D& color) { // ------------------------------------------------------------------------------------------------ void Discreet3DSExporter::WritePercentChunk(float f) { - ChunkWriter chunk(writer, Discreet3DS::CHUNK_PERCENTF); + ChunkWriter curChunk(writer, Discreet3DS::CHUNK_PERCENTF); writer.PutF4(f); } // ------------------------------------------------------------------------------------------------ void Discreet3DSExporter::WritePercentChunk(double f) { - ChunkWriter chunk(writer, Discreet3DS::CHUNK_PERCENTD); + ChunkWriter ccurChunkhunk(writer, Discreet3DS::CHUNK_PERCENTD); writer.PutF8(f); } diff --git a/code/3MF/D3MFExporter.cpp b/code/3MF/D3MFExporter.cpp index 9d71a54f2..092b947e9 100644 --- a/code/3MF/D3MFExporter.cpp +++ b/code/3MF/D3MFExporter.cpp @@ -256,13 +256,13 @@ void D3MFExporter::writeBaseMaterials() { tmp.clear(); hexDiffuseColor = "#"; - tmp = DecimalToHexa( color.r ); + tmp = DecimalToHexa( (ai_real) color.r ); hexDiffuseColor += tmp; - tmp = DecimalToHexa( color.g ); + tmp = DecimalToHexa((ai_real)color.g); hexDiffuseColor += tmp; - tmp = DecimalToHexa( color.b ); + tmp = DecimalToHexa((ai_real)color.b); hexDiffuseColor += tmp; - tmp = DecimalToHexa( color.a ); + tmp = DecimalToHexa((ai_real)color.a); hexDiffuseColor += tmp; } else { hexDiffuseColor = "#FFFFFFFF"; diff --git a/code/Assbin/AssbinFileWriter.cpp b/code/Assbin/AssbinFileWriter.cpp index 5e5a78d7c..b756adfa0 100644 --- a/code/Assbin/AssbinFileWriter.cpp +++ b/code/Assbin/AssbinFileWriter.cpp @@ -61,6 +61,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include +#pragma warning(push) +#pragma warning(disable : 4706) + namespace Assimp { template @@ -530,7 +533,6 @@ protected: if (shortened) { unsigned int processed = 0; for (unsigned int job;(job = std::min(mesh->mNumFaces-processed,512u));processed += job) { - uint32_t hash = 0; for (unsigned int a = 0; a < job;++a) { @@ -855,5 +857,6 @@ void DumpSceneToAssbin( AssbinFileWriter fileWriter(shortened, compressed); fileWriter.WriteBinaryDump(pFile, cmd, pIOSystem, pScene); } +#pragma warning(pop) } // end of namespace Assimp diff --git a/code/Assjson/json_exporter.cpp b/code/Assjson/json_exporter.cpp index e9fa72496..4a8e4599e 100644 --- a/code/Assjson/json_exporter.cpp +++ b/code/Assjson/json_exporter.cpp @@ -91,20 +91,20 @@ public: base64_encodestate s; base64_init_encodestate(&s); - char* const out = new char[std::max(len * 2, static_cast(16u))]; - const int n = base64_encode_block(reinterpret_cast(buffer), static_cast(len), out, &s); - out[n + base64_encode_blockend(out + n, &s)] = '\0'; + char* const cur_out = new char[std::max(len * 2, static_cast(16u))]; + const int n = base64_encode_block(reinterpret_cast(buffer), static_cast(len), cur_out, &s); + cur_out[n + base64_encode_blockend(cur_out + n, &s)] = '\0'; // base64 encoding may add newlines, but JSON strings may not contain 'real' newlines // (only escaped ones). Remove any newlines in out. - for (char* cur = out; *cur; ++cur) { + for (char *cur = cur_out; *cur; ++cur) { if (*cur == '\n') { *cur = ' '; } } - buff << '\"' << out << "\"\n"; - delete[] out; + buff << '\"' << cur_out << "\"\n"; + delete[] cur_out; } void StartObj(bool is_element = false) { @@ -464,8 +464,8 @@ void Write(JSONWriter& out, const aiMaterial& ai, bool is_elem = true) { case aiPTI_Float: if (prop->mDataLength / sizeof(float) > 1) { out.StartArray(); - for (unsigned int i = 0; i < prop->mDataLength / sizeof(float); ++i) { - out.Element(reinterpret_cast(prop->mData)[i]); + for (unsigned int ii = 0; ii < prop->mDataLength / sizeof(float); ++ii) { + out.Element(reinterpret_cast(prop->mData)[ii]); } out.EndArray(); } @@ -477,8 +477,8 @@ void Write(JSONWriter& out, const aiMaterial& ai, bool is_elem = true) { case aiPTI_Integer: if (prop->mDataLength / sizeof(int) > 1) { out.StartArray(); - for (unsigned int i = 0; i < prop->mDataLength / sizeof(int); ++i) { - out.Element(reinterpret_cast(prop->mData)[i]); + for (unsigned int ii = 0; ii < prop->mDataLength / sizeof(int); ++ii) { + out.Element(reinterpret_cast(prop->mData)[ii]); } out.EndArray(); } else { diff --git a/code/Assxml/AssxmlFileWriter.cpp b/code/Assxml/AssxmlFileWriter.cpp index 0ed59e509..3a88d5052 100644 --- a/code/Assxml/AssxmlFileWriter.cpp +++ b/code/Assxml/AssxmlFileWriter.cpp @@ -373,25 +373,25 @@ void WriteDump(const char* pFile, const char* cmd, const aiScene* scene, IOStrea ioprintf(io," size=\"%i\">\n\t\t\t\t", static_cast(prop->mDataLength/sizeof(float))); - for (unsigned int p = 0; p < prop->mDataLength/sizeof(float);++p) { - ioprintf(io,"%f ",*((float*)(prop->mData+p*sizeof(float)))); + for (unsigned int pp = 0; pp < prop->mDataLength/sizeof(float);++pp) { + ioprintf(io,"%f ",*((float*)(prop->mData+pp*sizeof(float)))); } } else if (prop->mType == aiPTI_Integer) { ioprintf(io," size=\"%i\">\n\t\t\t\t", static_cast(prop->mDataLength/sizeof(int))); - for (unsigned int p = 0; p < prop->mDataLength/sizeof(int);++p) { - ioprintf(io,"%i ",*((int*)(prop->mData+p*sizeof(int)))); + for (unsigned int pp = 0; pp < prop->mDataLength/sizeof(int);++pp) { + ioprintf(io,"%i ",*((int*)(prop->mData+pp*sizeof(int)))); } } else if (prop->mType == aiPTI_Buffer) { ioprintf(io," size=\"%i\">\n\t\t\t\t", static_cast(prop->mDataLength)); - for (unsigned int p = 0; p < prop->mDataLength;++p) { - ioprintf(io,"%2x ",prop->mData[p]); - if (p && 0 == p%30) { + for (unsigned int pp = 0; pp< prop->mDataLength;++pp) { + ioprintf(io,"%2x ",prop->mData[pp]); + if (pp && 0 == pp%30) { ioprintf(io,"\n\t\t\t\t"); } } diff --git a/code/Collada/ColladaExporter.cpp b/code/Collada/ColladaExporter.cpp index 99cdc097b..e27e7aa90 100644 --- a/code/Collada/ColladaExporter.cpp +++ b/code/Collada/ColladaExporter.cpp @@ -1335,32 +1335,34 @@ void ColladaExporter::WriteAnimationLibrary(size_t pIndex) mOutput << startstr << "" << endstr; PushTag(); - std::string node_idstr; + std::string cur_node_idstr; for (size_t a = 0; a < anim->mNumChannels; ++a) { const aiNodeAnim * nodeAnim = anim->mChannels[a]; // sanity check - if ( nodeAnim->mNumPositionKeys != nodeAnim->mNumScalingKeys || nodeAnim->mNumPositionKeys != nodeAnim->mNumRotationKeys ) continue; + if (nodeAnim->mNumPositionKeys != nodeAnim->mNumScalingKeys || nodeAnim->mNumPositionKeys != nodeAnim->mNumRotationKeys) { + continue; + } { - node_idstr.clear(); - node_idstr += nodeAnim->mNodeName.data; - node_idstr += std::string( "_matrix-input" ); + cur_node_idstr.clear(); + cur_node_idstr += nodeAnim->mNodeName.data; + cur_node_idstr += std::string("_matrix-input"); std::vector frames; for( size_t i = 0; i < nodeAnim->mNumPositionKeys; ++i) { frames.push_back(static_cast(nodeAnim->mPositionKeys[i].mTime)); } - WriteFloatArray( node_idstr , FloatType_Time, (const ai_real*) frames.data(), frames.size()); + WriteFloatArray(cur_node_idstr, FloatType_Time, (const ai_real *)frames.data(), frames.size()); frames.clear(); } { - node_idstr.clear(); + cur_node_idstr.clear(); - node_idstr += nodeAnim->mNodeName.data; - node_idstr += std::string("_matrix-output"); + cur_node_idstr += nodeAnim->mNodeName.data; + cur_node_idstr += std::string("_matrix-output"); std::vector keyframes; keyframes.reserve(nodeAnim->mNumPositionKeys * 16); @@ -1385,7 +1387,7 @@ void ColladaExporter::WriteAnimationLibrary(size_t pIndex) } } - WriteFloatArray( node_idstr, FloatType_Mat4x4, (const ai_real*) keyframes.data(), keyframes.size() / 16); + WriteFloatArray(cur_node_idstr, FloatType_Mat4x4, (const ai_real *)keyframes.data(), keyframes.size() / 16); } { @@ -1401,16 +1403,16 @@ void ColladaExporter::WriteAnimationLibrary(size_t pIndex) } } - const std::string node_idstr = nodeAnim->mNodeName.data + std::string("_matrix-interpolation"); - std::string arrayId = XMLIDEncode(node_idstr) + "-array"; + const std::string cur_node_idstr2 = nodeAnim->mNodeName.data + std::string("_matrix-interpolation"); + std::string arrayId = XMLIDEncode(cur_node_idstr2) + "-array"; - mOutput << startstr << "" << endstr; + mOutput << startstr << "" << endstr; PushTag(); // source array mOutput << startstr << " "; - for( size_t a = 0; a < names.size(); ++a ) { - mOutput << names[a] << " "; + for( size_t aa = 0; aa < names.size(); ++aa ) { + mOutput << names[aa] << " "; } mOutput << "" << endstr; @@ -1672,13 +1674,13 @@ void ColladaExporter::WriteNode( const aiScene* pScene, aiNode* pNode) PushTag(); mOutput << startstr << "mMaterialIndex].name) << "\">" << endstr; PushTag(); - for( size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a ) + for( size_t aa = 0; aa < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++aa ) { - if( mesh->HasTextureCoords( static_cast(a) ) ) + if( mesh->HasTextureCoords( static_cast(aa) ) ) // semantic as in // input_semantic as in // input_set as in - mOutput << startstr << "" << endstr; + mOutput << startstr << "" << endstr; } PopTag(); mOutput << startstr << "" << endstr; diff --git a/code/FBX/FBXCommon.h b/code/FBX/FBXCommon.h index 7f70eb784..7d015a134 100644 --- a/code/FBX/FBXCommon.h +++ b/code/FBX/FBXCommon.h @@ -48,40 +48,40 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef ASSIMP_BUILD_NO_FBX_EXPORTER namespace Assimp { -namespace FBX -{ - const std::string NULL_RECORD = { // 25 null bytes in 64-bit and 13 null bytes in 32-bit - '\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0', - '\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0' - }; // who knows why, it looks like two integers 32/64 bit (compressed and uncompressed sizes?) + 1 byte (might be compression type?) - const std::string SEPARATOR = {'\x00', '\x01'}; // for use inside strings - const std::string MAGIC_NODE_TAG = "_$AssimpFbx$"; // from import - const int64_t SECOND = 46186158000; // FBX's kTime unit +namespace FBX { - // rotation order. We'll probably use EulerXYZ for everything - enum RotOrder { - RotOrder_EulerXYZ = 0, - RotOrder_EulerXZY, - RotOrder_EulerYZX, - RotOrder_EulerYXZ, - RotOrder_EulerZXY, - RotOrder_EulerZYX, +const std::string NULL_RECORD = { // 25 null bytes in 64-bit and 13 null bytes in 32-bit + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0' +}; // who knows why, it looks like two integers 32/64 bit (compressed and uncompressed sizes?) + 1 byte (might be compression type?) +const std::string SEPARATOR = { '\x00', '\x01' }; // for use inside strings +const std::string MAGIC_NODE_TAG = "_$AssimpFbx$"; // from import +const int64_t SECOND = 46186158000; // FBX's kTime unit - RotOrder_SphericXYZ, +// rotation order. We'll probably use EulerXYZ for everything +enum RotOrder { + RotOrder_EulerXYZ = 0, + RotOrder_EulerXZY, + RotOrder_EulerYZX, + RotOrder_EulerYXZ, + RotOrder_EulerZXY, + RotOrder_EulerZYX, - RotOrder_MAX // end-of-enum sentinel - }; + RotOrder_SphericXYZ, - // transformation inheritance method. Most of the time RSrs - enum TransformInheritance { - TransformInheritance_RrSs = 0, - TransformInheritance_RSrs, - TransformInheritance_Rrs, + RotOrder_MAX // end-of-enum sentinel +}; - TransformInheritance_MAX // end-of-enum sentinel - }; -} -} +// transformation inheritance method. Most of the time RSrs +enum TransformInheritance { + TransformInheritance_RrSs = 0, + TransformInheritance_RSrs, + TransformInheritance_Rrs, + + TransformInheritance_MAX // end-of-enum sentinel +}; +} // namespace FBX +} // namespace Assimp #endif // ASSIMP_BUILD_NO_FBX_EXPORTER #endif // AI_FBXCOMMON_H_INC diff --git a/code/FBX/FBXConverter.cpp b/code/FBX/FBXConverter.cpp index 22616a480..42444e339 100644 --- a/code/FBX/FBXConverter.cpp +++ b/code/FBX/FBXConverter.cpp @@ -4,7 +4,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2020, assimp team - All rights reserved. Redistribution and use of this software in source and binary forms, @@ -47,2286 +46,2185 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef ASSIMP_BUILD_NO_FBX_IMPORTER #include "FBXConverter.h" -#include "FBXParser.h" -#include "FBXMeshGeometry.h" #include "FBXDocument.h" -#include "FBXUtil.h" -#include "FBXProperties.h" #include "FBXImporter.h" +#include "FBXMeshGeometry.h" +#include "FBXParser.h" +#include "FBXProperties.h" +#include "FBXUtil.h" -#include #include +#include #include #include -#include #include +#include -#include -#include -#include -#include -#include -#include -#include -#include #include +#include +#include +#include +#include +#include +#include +#include +#include namespace Assimp { - namespace FBX { +namespace FBX { - using namespace Util; +using namespace Util; #define MAGIC_NODE_TAG "_$AssimpFbx$" #define CONVERT_FBX_TIME(time) static_cast(time) / 46186158000LL - FBXConverter::FBXConverter(aiScene* out, const Document& doc, bool removeEmptyBones ) - : defaultMaterialIndex() - , lights() - , cameras() - , textures() - , materials_converted() - , textures_converted() - , meshes_converted() - , node_anim_chain_bits() - , mNodeNames() - , anim_fps() - , out(out) - , doc(doc) { - // animations need to be converted first since this will - // populate the node_anim_chain_bits map, which is needed - // to determine which nodes need to be generated. - ConvertAnimations(); - // Embedded textures in FBX could be connected to nothing but to itself, - // for instance Texture -> Video connection only but not to the main graph, - // The idea here is to traverse all objects to find these Textures and convert them, - // so later during material conversion it will find converted texture in the textures_converted array. - if (doc.Settings().readTextures) - { - ConvertOrphantEmbeddedTextures(); - } - ConvertRootNode(); +FBXConverter::FBXConverter(aiScene *out, const Document &doc, bool removeEmptyBones) : + defaultMaterialIndex(), + mMeshes(), + lights(), + cameras(), + textures(), + materials_converted(), + textures_converted(), + meshes_converted(), + node_anim_chain_bits(), + mNodeNames(), + anim_fps(), + mSceneOut(out), + doc(doc), + mRemoveEmptyBones(removeEmptyBones) { + // animations need to be converted first since this will + // populate the node_anim_chain_bits map, which is needed + // to determine which nodes need to be generated. + ConvertAnimations(); + // Embedded textures in FBX could be connected to nothing but to itself, + // for instance Texture -> Video connection only but not to the main graph, + // The idea here is to traverse all objects to find these Textures and convert them, + // so later during material conversion it will find converted texture in the textures_converted array. + if (doc.Settings().readTextures) { + ConvertOrphantEmbeddedTextures(); + } + ConvertRootNode(); - if (doc.Settings().readAllMaterials) { - // unfortunately this means we have to evaluate all objects - for (const ObjectMap::value_type& v : doc.Objects()) { + if (doc.Settings().readAllMaterials) { + // unfortunately this means we have to evaluate all objects + for (const ObjectMap::value_type &v : doc.Objects()) { - const Object* ob = v.second->Get(); - if (!ob) { - continue; - } - - const Material* mat = dynamic_cast(ob); - if (mat) { - - if (materials_converted.find(mat) == materials_converted.end()) { - ConvertMaterial(*mat, 0); - } - } - } + const Object *ob = v.second->Get(); + if (!ob) { + continue; } - ConvertGlobalSettings(); - TransferDataToScene(); + const Material *mat = dynamic_cast(ob); + if (mat) { - // if we didn't read any meshes set the AI_SCENE_FLAGS_INCOMPLETE - // to make sure the scene passes assimp's validation. FBX files - // need not contain geometry (i.e. camera animations, raw armatures). - if (out->mNumMeshes == 0) { - out->mFlags |= AI_SCENE_FLAGS_INCOMPLETE; - } - } - - - FBXConverter::~FBXConverter() { - std::for_each(meshes.begin(), meshes.end(), Util::delete_fun()); - std::for_each(materials.begin(), materials.end(), Util::delete_fun()); - std::for_each(animations.begin(), animations.end(), Util::delete_fun()); - std::for_each(lights.begin(), lights.end(), Util::delete_fun()); - std::for_each(cameras.begin(), cameras.end(), Util::delete_fun()); - std::for_each(textures.begin(), textures.end(), Util::delete_fun()); - } - - void FBXConverter::ConvertRootNode() { - out->mRootNode = new aiNode(); - std::string unique_name; - GetUniqueName("RootNode", unique_name); - out->mRootNode->mName.Set(unique_name); - - // root has ID 0 - ConvertNodes(0L, out->mRootNode, out->mRootNode); - } - - static std::string getAncestorBaseName(const aiNode* node) - { - const char* nodeName = nullptr; - size_t length = 0; - while (node && (!nodeName || length == 0)) - { - nodeName = node->mName.C_Str(); - length = node->mName.length; - node = node->mParent; - } - - if (!nodeName || length == 0) - { - return {}; - } - // could be std::string_view if c++17 available - return std::string(nodeName, length); - } - - // Make unique name - std::string FBXConverter::MakeUniqueNodeName(const Model* const model, const aiNode& parent) - { - std::string original_name = FixNodeName(model->Name()); - if (original_name.empty()) - { - original_name = getAncestorBaseName(&parent); - } - std::string unique_name; - GetUniqueName(original_name, unique_name); - return unique_name; - } - /// todo: pre-build node hierarchy - /// todo: get bone from stack - /// todo: make map of aiBone* to aiNode* - /// then update convert clusters to the new format - void FBXConverter::ConvertNodes(uint64_t id, aiNode *parent, aiNode *root_node) { - const std::vector& conns = doc.GetConnectionsByDestinationSequenced(id, "Model"); - - std::vector nodes; - nodes.reserve(conns.size()); - - std::vector nodes_chain; - std::vector post_nodes_chain; - - try { - for (const Connection* con : conns) { - // ignore object-property links - if (con->PropertyName().length()) { - // really important we document why this is ignored. - FBXImporter::LogInfo("ignoring property link - no docs on why this is ignored"); - continue; //? - } - - // convert connection source object into Object base class - const Object* const object = con->SourceObject(); - if (nullptr == object) { - FBXImporter::LogError("failed to convert source object for Model link"); - continue; - } - - // FBX Model::Cube, Model::Bone001, etc elements - // This detects if we can cast the object into this model structure. - const Model* const model = dynamic_cast(object); - - if (nullptr != model) { - nodes_chain.clear(); - post_nodes_chain.clear(); - - aiMatrix4x4 new_abs_transform = parent->mTransformation; - std::string node_name = FixNodeName(model->Name()); - // even though there is only a single input node, the design of - // assimp (or rather: the complicated transformation chain that - // is employed by fbx) means that we may need multiple aiNode's - // to represent a fbx node's transformation. - - - // generate node transforms - this includes pivot data - // if need_additional_node is true then you t - const bool need_additional_node = GenerateTransformationNodeChain(*model, node_name, nodes_chain, post_nodes_chain); - - // assert that for the current node we must have at least a single transform - ai_assert(nodes_chain.size()); - - if (need_additional_node) { - nodes_chain.push_back(new aiNode(node_name)); - } - - //setup metadata on newest node - SetupNodeMetadata(*model, *nodes_chain.back()); - - // link all nodes in a row - aiNode* last_parent = parent; - for (aiNode* child : nodes_chain) { - ai_assert(child); - - if (last_parent != parent) { - last_parent->mNumChildren = 1; - last_parent->mChildren = new aiNode*[1]; - last_parent->mChildren[0] = child; - } - - child->mParent = last_parent; - last_parent = child; - - new_abs_transform *= child->mTransformation; - } - - // attach geometry - ConvertModel(*model, nodes_chain.back(), root_node, new_abs_transform); - - // check if there will be any child nodes - const std::vector& child_conns - = doc.GetConnectionsByDestinationSequenced(model->ID(), "Model"); - - // if so, link the geometric transform inverse nodes - // before we attach any child nodes - if (child_conns.size()) { - for (aiNode* postnode : post_nodes_chain) { - ai_assert(postnode); - - if (last_parent != parent) { - last_parent->mNumChildren = 1; - last_parent->mChildren = new aiNode*[1]; - last_parent->mChildren[0] = postnode; - } - - postnode->mParent = last_parent; - last_parent = postnode; - - new_abs_transform *= postnode->mTransformation; - } - } - else { - // free the nodes we allocated as we don't need them - Util::delete_fun deleter; - std::for_each( - post_nodes_chain.begin(), - post_nodes_chain.end(), - deleter - ); - } - - // recursion call - child nodes - ConvertNodes(model->ID(), last_parent, root_node); - - if (doc.Settings().readLights) { - ConvertLights(*model, node_name); - } - - if (doc.Settings().readCameras) { - ConvertCameras(*model, node_name); - } - - nodes.push_back(nodes_chain.front()); - nodes_chain.clear(); - } - } - - if (nodes.size()) { - parent->mChildren = new aiNode*[nodes.size()](); - parent->mNumChildren = static_cast(nodes.size()); - - std::swap_ranges(nodes.begin(), nodes.end(), parent->mChildren); - } - else - { - parent->mNumChildren = 0; - parent->mChildren = nullptr; - } - - } - catch (std::exception&) { - Util::delete_fun deleter; - std::for_each(nodes.begin(), nodes.end(), deleter); - std::for_each(nodes_chain.begin(), nodes_chain.end(), deleter); - std::for_each(post_nodes_chain.begin(), post_nodes_chain.end(), deleter); - } - } - - - void FBXConverter::ConvertLights(const Model& model, const std::string &orig_name) { - const std::vector& node_attrs = model.GetAttributes(); - for (const NodeAttribute* attr : node_attrs) { - const Light* const light = dynamic_cast(attr); - if (light) { - ConvertLight(*light, orig_name); + if (materials_converted.find(mat) == materials_converted.end()) { + ConvertMaterial(*mat, 0); } } } + } - void FBXConverter::ConvertCameras(const Model& model, const std::string &orig_name) { - const std::vector& node_attrs = model.GetAttributes(); - for (const NodeAttribute* attr : node_attrs) { - const Camera* const cam = dynamic_cast(attr); - if (cam) { - ConvertCamera(*cam, orig_name); - } - } - } + ConvertGlobalSettings(); + TransferDataToScene(); - void FBXConverter::ConvertLight(const Light& light, const std::string &orig_name) { - lights.push_back(new aiLight()); - aiLight* const out_light = lights.back(); - - out_light->mName.Set(orig_name); - - const float intensity = light.Intensity() / 100.0f; - const aiVector3D& col = light.Color(); - - out_light->mColorDiffuse = aiColor3D(col.x, col.y, col.z); - out_light->mColorDiffuse.r *= intensity; - out_light->mColorDiffuse.g *= intensity; - out_light->mColorDiffuse.b *= intensity; - - out_light->mColorSpecular = out_light->mColorDiffuse; - - //lights are defined along negative y direction - out_light->mPosition = aiVector3D(0.0f); - out_light->mDirection = aiVector3D(0.0f, -1.0f, 0.0f); - out_light->mUp = aiVector3D(0.0f, 0.0f, -1.0f); - - switch (light.LightType()) - { - case Light::Type_Point: - out_light->mType = aiLightSource_POINT; - break; - - case Light::Type_Directional: - out_light->mType = aiLightSource_DIRECTIONAL; - break; - - case Light::Type_Spot: - out_light->mType = aiLightSource_SPOT; - out_light->mAngleOuterCone = AI_DEG_TO_RAD(light.OuterAngle()); - out_light->mAngleInnerCone = AI_DEG_TO_RAD(light.InnerAngle()); - break; - - case Light::Type_Area: - FBXImporter::LogWarn("cannot represent area light, set to UNDEFINED"); - out_light->mType = aiLightSource_UNDEFINED; - break; - - case Light::Type_Volume: - FBXImporter::LogWarn("cannot represent volume light, set to UNDEFINED"); - out_light->mType = aiLightSource_UNDEFINED; - break; - default: - ai_assert(false); - } - - float decay = light.DecayStart(); - switch (light.DecayType()) - { - case Light::Decay_None: - out_light->mAttenuationConstant = decay; - out_light->mAttenuationLinear = 0.0f; - out_light->mAttenuationQuadratic = 0.0f; - break; - case Light::Decay_Linear: - out_light->mAttenuationConstant = 0.0f; - out_light->mAttenuationLinear = 2.0f / decay; - out_light->mAttenuationQuadratic = 0.0f; - break; - case Light::Decay_Quadratic: - out_light->mAttenuationConstant = 0.0f; - out_light->mAttenuationLinear = 0.0f; - out_light->mAttenuationQuadratic = 2.0f / (decay * decay); - break; - case Light::Decay_Cubic: - FBXImporter::LogWarn("cannot represent cubic attenuation, set to Quadratic"); - out_light->mAttenuationQuadratic = 1.0f; - break; - default: - ai_assert(false); - break; - } - } - - void FBXConverter::ConvertCamera(const Camera& cam, const std::string &orig_name) - { - cameras.push_back(new aiCamera()); - aiCamera* const out_camera = cameras.back(); - - out_camera->mName.Set(orig_name); - - out_camera->mAspect = cam.AspectWidth() / cam.AspectHeight(); - - out_camera->mPosition = aiVector3D(0.0f); - out_camera->mLookAt = aiVector3D(1.0f, 0.0f, 0.0f); - out_camera->mUp = aiVector3D(0.0f, 1.0f, 0.0f); - - out_camera->mHorizontalFOV = AI_DEG_TO_RAD(cam.FieldOfView()); - - out_camera->mClipPlaneNear = cam.NearPlane(); - out_camera->mClipPlaneFar = cam.FarPlane(); - - out_camera->mHorizontalFOV = AI_DEG_TO_RAD(cam.FieldOfView()); - out_camera->mClipPlaneNear = cam.NearPlane(); - out_camera->mClipPlaneFar = cam.FarPlane(); - } - - void FBXConverter::GetUniqueName(const std::string &name, std::string &uniqueName) - { - uniqueName = name; - auto it_pair = mNodeNames.insert({ name, 0 }); // duplicate node name instance count - unsigned int& i = it_pair.first->second; - while (!it_pair.second) - { - i++; - std::ostringstream ext; - ext << name << std::setfill('0') << std::setw(3) << i; - uniqueName = ext.str(); - it_pair = mNodeNames.insert({ uniqueName, 0 }); - } - } - - const char* FBXConverter::NameTransformationComp(TransformationComp comp) { - switch (comp) { - case TransformationComp_Translation: - return "Translation"; - case TransformationComp_RotationOffset: - return "RotationOffset"; - case TransformationComp_RotationPivot: - return "RotationPivot"; - case TransformationComp_PreRotation: - return "PreRotation"; - case TransformationComp_Rotation: - return "Rotation"; - case TransformationComp_PostRotation: - return "PostRotation"; - case TransformationComp_RotationPivotInverse: - return "RotationPivotInverse"; - case TransformationComp_ScalingOffset: - return "ScalingOffset"; - case TransformationComp_ScalingPivot: - return "ScalingPivot"; - case TransformationComp_Scaling: - return "Scaling"; - case TransformationComp_ScalingPivotInverse: - return "ScalingPivotInverse"; - case TransformationComp_GeometricScaling: - return "GeometricScaling"; - case TransformationComp_GeometricRotation: - return "GeometricRotation"; - case TransformationComp_GeometricTranslation: - return "GeometricTranslation"; - case TransformationComp_GeometricScalingInverse: - return "GeometricScalingInverse"; - case TransformationComp_GeometricRotationInverse: - return "GeometricRotationInverse"; - case TransformationComp_GeometricTranslationInverse: - return "GeometricTranslationInverse"; - case TransformationComp_MAXIMUM: // this is to silence compiler warnings - default: - break; - } - - ai_assert(false); - - return nullptr; - } - - const char* FBXConverter::NameTransformationCompProperty(TransformationComp comp) { - switch (comp) { - case TransformationComp_Translation: - return "Lcl Translation"; - case TransformationComp_RotationOffset: - return "RotationOffset"; - case TransformationComp_RotationPivot: - return "RotationPivot"; - case TransformationComp_PreRotation: - return "PreRotation"; - case TransformationComp_Rotation: - return "Lcl Rotation"; - case TransformationComp_PostRotation: - return "PostRotation"; - case TransformationComp_RotationPivotInverse: - return "RotationPivotInverse"; - case TransformationComp_ScalingOffset: - return "ScalingOffset"; - case TransformationComp_ScalingPivot: - return "ScalingPivot"; - case TransformationComp_Scaling: - return "Lcl Scaling"; - case TransformationComp_ScalingPivotInverse: - return "ScalingPivotInverse"; - case TransformationComp_GeometricScaling: - return "GeometricScaling"; - case TransformationComp_GeometricRotation: - return "GeometricRotation"; - case TransformationComp_GeometricTranslation: - return "GeometricTranslation"; - case TransformationComp_GeometricScalingInverse: - return "GeometricScalingInverse"; - case TransformationComp_GeometricRotationInverse: - return "GeometricRotationInverse"; - case TransformationComp_GeometricTranslationInverse: - return "GeometricTranslationInverse"; - case TransformationComp_MAXIMUM: // this is to silence compiler warnings - break; - } - - ai_assert(false); - - return nullptr; - } - - aiVector3D FBXConverter::TransformationCompDefaultValue(TransformationComp comp) - { - // XXX a neat way to solve the never-ending special cases for scaling - // would be to do everything in log space! - return comp == TransformationComp_Scaling ? aiVector3D(1.f, 1.f, 1.f) : aiVector3D(); - } - - void FBXConverter::GetRotationMatrix(Model::RotOrder mode, const aiVector3D& rotation, aiMatrix4x4& out) - { - if (mode == Model::RotOrder_SphericXYZ) { - FBXImporter::LogError("Unsupported RotationMode: SphericXYZ"); - out = aiMatrix4x4(); - return; - } - - const float angle_epsilon = Math::getEpsilon(); - - out = aiMatrix4x4(); - - bool is_id[3] = { true, true, true }; - - aiMatrix4x4 temp[3]; - if (std::fabs(rotation.z) > angle_epsilon) { - aiMatrix4x4::RotationZ(AI_DEG_TO_RAD(rotation.z), temp[2]); - is_id[2] = false; - } - if (std::fabs(rotation.y) > angle_epsilon) { - aiMatrix4x4::RotationY(AI_DEG_TO_RAD(rotation.y), temp[1]); - is_id[1] = false; - } - if (std::fabs(rotation.x) > angle_epsilon) { - aiMatrix4x4::RotationX(AI_DEG_TO_RAD(rotation.x), temp[0]); - is_id[0] = false; - } - - int order[3] = { -1, -1, -1 }; - - // note: rotation order is inverted since we're left multiplying as is usual in assimp - switch (mode) - { - case Model::RotOrder_EulerXYZ: - order[0] = 2; - order[1] = 1; - order[2] = 0; - break; - - case Model::RotOrder_EulerXZY: - order[0] = 1; - order[1] = 2; - order[2] = 0; - break; - - case Model::RotOrder_EulerYZX: - order[0] = 0; - order[1] = 2; - order[2] = 1; - break; - - case Model::RotOrder_EulerYXZ: - order[0] = 2; - order[1] = 0; - order[2] = 1; - break; - - case Model::RotOrder_EulerZXY: - order[0] = 1; - order[1] = 0; - order[2] = 2; - break; - - case Model::RotOrder_EulerZYX: - order[0] = 0; - order[1] = 1; - order[2] = 2; - break; - - default: - ai_assert(false); - break; - } - - ai_assert(order[0] >= 0); - ai_assert(order[0] <= 2); - ai_assert(order[1] >= 0); - ai_assert(order[1] <= 2); - ai_assert(order[2] >= 0); - ai_assert(order[2] <= 2); - - if (!is_id[order[0]]) { - out = temp[order[0]]; - } - - if (!is_id[order[1]]) { - out = out * temp[order[1]]; - } - - if (!is_id[order[2]]) { - out = out * temp[order[2]]; - } - } - - bool FBXConverter::NeedsComplexTransformationChain(const Model& model) - { - const PropertyTable& props = model.Props(); - bool ok; - - const float zero_epsilon = 1e-6f; - const aiVector3D all_ones(1.0f, 1.0f, 1.0f); - for (size_t i = 0; i < TransformationComp_MAXIMUM; ++i) { - const TransformationComp comp = static_cast(i); - - if (comp == TransformationComp_Rotation || comp == TransformationComp_Scaling || comp == TransformationComp_Translation) { - continue; - } - - bool scale_compare = (comp == TransformationComp_GeometricScaling || comp == TransformationComp_Scaling); - - const aiVector3D& v = PropertyGet(props, NameTransformationCompProperty(comp), ok); - if (ok && scale_compare) { - if ((v - all_ones).SquareLength() > zero_epsilon) { - return true; - } - } else if (ok) { - if (v.SquareLength() > zero_epsilon) { - return true; - } - } - } - - return false; - } - - std::string FBXConverter::NameTransformationChainNode(const std::string& name, TransformationComp comp) - { - return name + std::string(MAGIC_NODE_TAG) + "_" + NameTransformationComp(comp); - } - - bool FBXConverter::GenerateTransformationNodeChain(const Model& model, const std::string& name, std::vector& output_nodes, - std::vector& post_output_nodes) { - const PropertyTable& props = model.Props(); - const Model::RotOrder rot = model.RotationOrder(); - - bool ok; - - aiMatrix4x4 chain[TransformationComp_MAXIMUM]; - - ai_assert(TransformationComp_MAXIMUM < 32); - std::uint32_t chainBits = 0; - // A node won't need a node chain if it only has these. - const std::uint32_t chainMaskSimple = (1 << TransformationComp_Translation) + (1 << TransformationComp_Scaling) + (1 << TransformationComp_Rotation); - // A node will need a node chain if it has any of these. - const std::uint32_t chainMaskComplex = ((1 << (TransformationComp_MAXIMUM)) - 1) - chainMaskSimple; - - std::fill_n(chain, static_cast(TransformationComp_MAXIMUM), aiMatrix4x4()); - - // generate transformation matrices for all the different transformation components - const float zero_epsilon = Math::getEpsilon(); - const aiVector3D all_ones(1.0f, 1.0f, 1.0f); - - const aiVector3D& PreRotation = PropertyGet(props, "PreRotation", ok); - if (ok && PreRotation.SquareLength() > zero_epsilon) { - chainBits = chainBits | (1 << TransformationComp_PreRotation); - - GetRotationMatrix(Model::RotOrder::RotOrder_EulerXYZ, PreRotation, chain[TransformationComp_PreRotation]); - } - - const aiVector3D& PostRotation = PropertyGet(props, "PostRotation", ok); - if (ok && PostRotation.SquareLength() > zero_epsilon) { - chainBits = chainBits | (1 << TransformationComp_PostRotation); - - GetRotationMatrix(Model::RotOrder::RotOrder_EulerXYZ, PostRotation, chain[TransformationComp_PostRotation]); - } - - const aiVector3D& RotationPivot = PropertyGet(props, "RotationPivot", ok); - if (ok && RotationPivot.SquareLength() > zero_epsilon) { - chainBits = chainBits | (1 << TransformationComp_RotationPivot) | (1 << TransformationComp_RotationPivotInverse); - - aiMatrix4x4::Translation(RotationPivot, chain[TransformationComp_RotationPivot]); - aiMatrix4x4::Translation(-RotationPivot, chain[TransformationComp_RotationPivotInverse]); - } - - const aiVector3D& RotationOffset = PropertyGet(props, "RotationOffset", ok); - if (ok && RotationOffset.SquareLength() > zero_epsilon) { - chainBits = chainBits | (1 << TransformationComp_RotationOffset); - - aiMatrix4x4::Translation(RotationOffset, chain[TransformationComp_RotationOffset]); - } - - const aiVector3D& ScalingOffset = PropertyGet(props, "ScalingOffset", ok); - if (ok && ScalingOffset.SquareLength() > zero_epsilon) { - chainBits = chainBits | (1 << TransformationComp_ScalingOffset); - - aiMatrix4x4::Translation(ScalingOffset, chain[TransformationComp_ScalingOffset]); - } - - const aiVector3D& ScalingPivot = PropertyGet(props, "ScalingPivot", ok); - if (ok && ScalingPivot.SquareLength() > zero_epsilon) { - chainBits = chainBits | (1 << TransformationComp_ScalingPivot) | (1 << TransformationComp_ScalingPivotInverse); - - aiMatrix4x4::Translation(ScalingPivot, chain[TransformationComp_ScalingPivot]); - aiMatrix4x4::Translation(-ScalingPivot, chain[TransformationComp_ScalingPivotInverse]); - } - - const aiVector3D& Translation = PropertyGet(props, "Lcl Translation", ok); - if (ok && Translation.SquareLength() > zero_epsilon) { - chainBits = chainBits | (1 << TransformationComp_Translation); - - aiMatrix4x4::Translation(Translation, chain[TransformationComp_Translation]); - } - - const aiVector3D& Scaling = PropertyGet(props, "Lcl Scaling", ok); - if (ok && (Scaling - all_ones).SquareLength() > zero_epsilon) { - chainBits = chainBits | (1 << TransformationComp_Scaling); - - aiMatrix4x4::Scaling(Scaling, chain[TransformationComp_Scaling]); - } - - const aiVector3D& Rotation = PropertyGet(props, "Lcl Rotation", ok); - if (ok && Rotation.SquareLength() > zero_epsilon) { - chainBits = chainBits | (1 << TransformationComp_Rotation); - - GetRotationMatrix(rot, Rotation, chain[TransformationComp_Rotation]); - } - - const aiVector3D& GeometricScaling = PropertyGet(props, "GeometricScaling", ok); - if (ok && (GeometricScaling - all_ones).SquareLength() > zero_epsilon) { - chainBits = chainBits | (1 << TransformationComp_GeometricScaling); - aiMatrix4x4::Scaling(GeometricScaling, chain[TransformationComp_GeometricScaling]); - aiVector3D GeometricScalingInverse = GeometricScaling; - bool canscale = true; - for (unsigned int i = 0; i < 3; ++i) { - if (std::fabs(GeometricScalingInverse[i]) > zero_epsilon) { - GeometricScalingInverse[i] = 1.0f / GeometricScaling[i]; - } - else { - FBXImporter::LogError("cannot invert geometric scaling matrix with a 0.0 scale component"); - canscale = false; - break; - } - } - if (canscale) { - chainBits = chainBits | (1 << TransformationComp_GeometricScalingInverse); - aiMatrix4x4::Scaling(GeometricScalingInverse, chain[TransformationComp_GeometricScalingInverse]); - } - } - - const aiVector3D& GeometricRotation = PropertyGet(props, "GeometricRotation", ok); - if (ok && GeometricRotation.SquareLength() > zero_epsilon) { - chainBits = chainBits | (1 << TransformationComp_GeometricRotation) | (1 << TransformationComp_GeometricRotationInverse); - GetRotationMatrix(rot, GeometricRotation, chain[TransformationComp_GeometricRotation]); - GetRotationMatrix(rot, GeometricRotation, chain[TransformationComp_GeometricRotationInverse]); - chain[TransformationComp_GeometricRotationInverse].Inverse(); - } - - const aiVector3D& GeometricTranslation = PropertyGet(props, "GeometricTranslation", ok); - if (ok && GeometricTranslation.SquareLength() > zero_epsilon) { - chainBits = chainBits | (1 << TransformationComp_GeometricTranslation) | (1 << TransformationComp_GeometricTranslationInverse); - aiMatrix4x4::Translation(GeometricTranslation, chain[TransformationComp_GeometricTranslation]); - aiMatrix4x4::Translation(-GeometricTranslation, chain[TransformationComp_GeometricTranslationInverse]); - } - - // is_complex needs to be consistent with NeedsComplexTransformationChain() - // or the interplay between this code and the animation converter would - // not be guaranteed. - //ai_assert(NeedsComplexTransformationChain(model) == ((chainBits & chainMaskComplex) != 0)); - - // now, if we have more than just Translation, Scaling and Rotation, - // we need to generate a full node chain to accommodate for assimp's - // lack to express pivots and offsets. - if ((chainBits & chainMaskComplex) && doc.Settings().preservePivots) { - FBXImporter::LogInfo("generating full transformation chain for node: " + name); - - // query the anim_chain_bits dictionary to find out which chain elements - // have associated node animation channels. These can not be dropped - // even if they have identity transform in bind pose. - NodeAnimBitMap::const_iterator it = node_anim_chain_bits.find(name); - const unsigned int anim_chain_bitmask = (it == node_anim_chain_bits.end() ? 0 : (*it).second); - - unsigned int bit = 0x1; - for (size_t i = 0; i < TransformationComp_MAXIMUM; ++i, bit <<= 1) { - const TransformationComp comp = static_cast(i); - - if ((chainBits & bit) == 0 && (anim_chain_bitmask & bit) == 0) { - continue; - } - - if (comp == TransformationComp_PostRotation) { - chain[i] = chain[i].Inverse(); - } - - aiNode* nd = new aiNode(); - nd->mName.Set(NameTransformationChainNode(name, comp)); - nd->mTransformation = chain[i]; - - // geometric inverses go in a post-node chain - if (comp == TransformationComp_GeometricScalingInverse || - comp == TransformationComp_GeometricRotationInverse || - comp == TransformationComp_GeometricTranslationInverse - ) { - post_output_nodes.push_back(nd); - } - else { - output_nodes.push_back(nd); - } - } - - ai_assert(output_nodes.size()); - return true; - } - - // else, we can just multiply the matrices together - aiNode* nd = new aiNode(); - output_nodes.push_back(nd); - - // name passed to the method is already unique - nd->mName.Set(name); - - for (const auto &transform : chain) { - nd->mTransformation = nd->mTransformation * transform; - } - return false; - } - - void FBXConverter::SetupNodeMetadata(const Model& model, aiNode& nd) - { - const PropertyTable& props = model.Props(); - DirectPropertyMap unparsedProperties = props.GetUnparsedProperties(); - - // create metadata on node - const std::size_t numStaticMetaData = 2; - aiMetadata* data = aiMetadata::Alloc(static_cast(unparsedProperties.size() + numStaticMetaData)); - nd.mMetaData = data; - int index = 0; - - // find user defined properties (3ds Max) - data->Set(index++, "UserProperties", aiString(PropertyGet(props, "UDP3DSMAX", ""))); - // preserve the info that a node was marked as Null node in the original file. - data->Set(index++, "IsNull", model.IsNull() ? true : false); - - // add unparsed properties to the node's metadata - for (const DirectPropertyMap::value_type& prop : unparsedProperties) { - // Interpret the property as a concrete type - if (const TypedProperty* interpreted = prop.second->As >()) { - data->Set(index++, prop.first, interpreted->Value()); - } - else if (const TypedProperty* interpreted = prop.second->As >()) { - data->Set(index++, prop.first, interpreted->Value()); - } - else if (const TypedProperty* interpreted = prop.second->As >()) { - data->Set(index++, prop.first, interpreted->Value()); - } - else if (const TypedProperty* interpreted = prop.second->As >()) { - data->Set(index++, prop.first, interpreted->Value()); - } - else if (const TypedProperty* interpreted = prop.second->As >()) { - data->Set(index++, prop.first, aiString(interpreted->Value())); - } - else if (const TypedProperty* interpreted = prop.second->As >()) { - data->Set(index++, prop.first, interpreted->Value()); - } - else { - ai_assert(false); - } - } - } - - void FBXConverter::ConvertModel(const Model &model, aiNode *parent, aiNode *root_node, - const aiMatrix4x4 &absolute_transform) - { - const std::vector& geos = model.GetGeometry(); - - std::vector meshes; - meshes.reserve(geos.size()); - - for (const Geometry* geo : geos) { - - const MeshGeometry* const mesh = dynamic_cast(geo); - const LineGeometry* const line = dynamic_cast(geo); - if (mesh) { - const std::vector& indices = ConvertMesh(*mesh, model, parent, root_node, - absolute_transform); - std::copy(indices.begin(), indices.end(), std::back_inserter(meshes)); - } - else if (line) { - const std::vector& indices = ConvertLine(*line, model, parent, root_node); - std::copy(indices.begin(), indices.end(), std::back_inserter(meshes)); - } - else { - FBXImporter::LogWarn("ignoring unrecognized geometry: " + geo->Name()); - } - } - - if (meshes.size()) { - parent->mMeshes = new unsigned int[meshes.size()](); - parent->mNumMeshes = static_cast(meshes.size()); - - std::swap_ranges(meshes.begin(), meshes.end(), parent->mMeshes); - } - } - - std::vector - FBXConverter::ConvertMesh(const MeshGeometry &mesh, const Model &model, aiNode *parent, aiNode *root_node, - const aiMatrix4x4 &absolute_transform) - { - std::vector temp; - - MeshMap::const_iterator it = meshes_converted.find(&mesh); - if (it != meshes_converted.end()) { - std::copy((*it).second.begin(), (*it).second.end(), std::back_inserter(temp)); - return temp; - } - - const std::vector& vertices = mesh.GetVertices(); - const std::vector& faces = mesh.GetFaceIndexCounts(); - if (vertices.empty() || faces.empty()) { - FBXImporter::LogWarn("ignoring empty geometry: " + mesh.Name()); - return temp; - } - - // one material per mesh maps easily to aiMesh. Multiple material - // meshes need to be split. - const MatIndexArray& mindices = mesh.GetMaterialIndices(); - if (doc.Settings().readMaterials && !mindices.empty()) { - const MatIndexArray::value_type base = mindices[0]; - for (MatIndexArray::value_type index : mindices) { - if (index != base) { - return ConvertMeshMultiMaterial(mesh, model, parent, root_node, absolute_transform); - } - } - } - - // faster code-path, just copy the data - temp.push_back(ConvertMeshSingleMaterial(mesh, model, absolute_transform, parent, root_node)); - return temp; - } - - std::vector FBXConverter::ConvertLine(const LineGeometry& line, const Model& model, - aiNode *parent, aiNode *root_node) - { - std::vector temp; - - const std::vector& vertices = line.GetVertices(); - const std::vector& indices = line.GetIndices(); - if (vertices.empty() || indices.empty()) { - FBXImporter::LogWarn("ignoring empty line: " + line.Name()); - return temp; - } - - aiMesh* const out_mesh = SetupEmptyMesh(line, root_node); - out_mesh->mPrimitiveTypes |= aiPrimitiveType_LINE; - - // copy vertices - out_mesh->mNumVertices = static_cast(vertices.size()); - out_mesh->mVertices = new aiVector3D[out_mesh->mNumVertices]; - std::copy(vertices.begin(), vertices.end(), out_mesh->mVertices); - - //Number of line segments (faces) is "Number of Points - Number of Endpoints" - //N.B.: Endpoints in FbxLine are denoted by negative indices. - //If such an Index is encountered, add 1 and multiply by -1 to get the real index. - unsigned int epcount = 0; - for (unsigned i = 0; i < indices.size(); i++) - { - if (indices[i] < 0) { - epcount++; - } - } - unsigned int pcount = static_cast( indices.size() ); - unsigned int scount = out_mesh->mNumFaces = pcount - epcount; - - aiFace* fac = out_mesh->mFaces = new aiFace[scount](); - for (unsigned int i = 0; i < pcount; ++i) { - if (indices[i] < 0) continue; - aiFace& f = *fac++; - f.mNumIndices = 2; //2 == aiPrimitiveType_LINE - f.mIndices = new unsigned int[2]; - f.mIndices[0] = indices[i]; - int segid = indices[(i + 1 == pcount ? 0 : i + 1)]; //If we have reached he last point, wrap around - f.mIndices[1] = (segid < 0 ? (segid + 1)*-1 : segid); //Convert EndPoint Index to normal Index - } - temp.push_back(static_cast(meshes.size() - 1)); - return temp; - } - - aiMesh* FBXConverter::SetupEmptyMesh(const Geometry& mesh, aiNode *parent) - { - aiMesh* const out_mesh = new aiMesh(); - meshes.push_back(out_mesh); - meshes_converted[&mesh].push_back(static_cast(meshes.size() - 1)); - - // set name - std::string name = mesh.Name(); - if (name.substr(0, 10) == "Geometry::") { - name = name.substr(10); - } - - if (name.length()) { - out_mesh->mName.Set(name); - } - else - { - out_mesh->mName = parent->mName; - } - - return out_mesh; - } - - unsigned int FBXConverter::ConvertMeshSingleMaterial(const MeshGeometry &mesh, const Model &model, - const aiMatrix4x4 &absolute_transform, aiNode *parent, - aiNode *root_node) - { - const MatIndexArray& mindices = mesh.GetMaterialIndices(); - aiMesh* const out_mesh = SetupEmptyMesh(mesh, parent); - - const std::vector& vertices = mesh.GetVertices(); - const std::vector& faces = mesh.GetFaceIndexCounts(); - - // copy vertices - out_mesh->mNumVertices = static_cast(vertices.size()); - out_mesh->mVertices = new aiVector3D[vertices.size()]; - - std::copy(vertices.begin(), vertices.end(), out_mesh->mVertices); - - // generate dummy faces - out_mesh->mNumFaces = static_cast(faces.size()); - aiFace* fac = out_mesh->mFaces = new aiFace[faces.size()](); - - unsigned int cursor = 0; - for (unsigned int pcount : faces) { - aiFace& f = *fac++; - f.mNumIndices = pcount; - f.mIndices = new unsigned int[pcount]; - switch (pcount) - { - case 1: - out_mesh->mPrimitiveTypes |= aiPrimitiveType_POINT; - break; - case 2: - out_mesh->mPrimitiveTypes |= aiPrimitiveType_LINE; - break; - case 3: - out_mesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE; - break; - default: - out_mesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON; - break; - } - for (unsigned int i = 0; i < pcount; ++i) { - f.mIndices[i] = cursor++; - } - } - - // copy normals - const std::vector& normals = mesh.GetNormals(); - if (normals.size()) { - ai_assert(normals.size() == vertices.size()); - - out_mesh->mNormals = new aiVector3D[vertices.size()]; - std::copy(normals.begin(), normals.end(), out_mesh->mNormals); - } - - // copy tangents - assimp requires both tangents and bitangents (binormals) - // to be present, or neither of them. Compute binormals from normals - // and tangents if needed. - const std::vector& tangents = mesh.GetTangents(); - const std::vector* binormals = &mesh.GetBinormals(); - - if (tangents.size()) { - std::vector tempBinormals; - if (!binormals->size()) { - if (normals.size()) { - tempBinormals.resize(normals.size()); - for (unsigned int i = 0; i < tangents.size(); ++i) { - tempBinormals[i] = normals[i] ^ tangents[i]; - } - - binormals = &tempBinormals; - } - else { - binormals = nullptr; - } - } - - if (binormals) { - ai_assert(tangents.size() == vertices.size()); - ai_assert(binormals->size() == vertices.size()); - - out_mesh->mTangents = new aiVector3D[vertices.size()]; - std::copy(tangents.begin(), tangents.end(), out_mesh->mTangents); - - out_mesh->mBitangents = new aiVector3D[vertices.size()]; - std::copy(binormals->begin(), binormals->end(), out_mesh->mBitangents); - } - } - - // copy texture coords - for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) { - const std::vector& uvs = mesh.GetTextureCoords(i); - if (uvs.empty()) { - break; - } - - aiVector3D* out_uv = out_mesh->mTextureCoords[i] = new aiVector3D[vertices.size()]; - for (const aiVector2D& v : uvs) { - *out_uv++ = aiVector3D(v.x, v.y, 0.0f); - } - - out_mesh->mNumUVComponents[i] = 2; - } - - // copy vertex colors - for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_COLOR_SETS; ++i) { - const std::vector& colors = mesh.GetVertexColors(i); - if (colors.empty()) { - break; - } - - out_mesh->mColors[i] = new aiColor4D[vertices.size()]; - std::copy(colors.begin(), colors.end(), out_mesh->mColors[i]); - } - - if (!doc.Settings().readMaterials || mindices.empty()) { - FBXImporter::LogError("no material assigned to mesh, setting default material"); - out_mesh->mMaterialIndex = GetDefaultMaterial(); - } - else { - ConvertMaterialForMesh(out_mesh, model, mesh, mindices[0]); - } - - if (doc.Settings().readWeights && mesh.DeformerSkin() != nullptr) { - ConvertWeights(out_mesh, model, mesh, absolute_transform, parent, root_node, NO_MATERIAL_SEPARATION, - nullptr); - } - - std::vector animMeshes; - for (const BlendShape* blendShape : mesh.GetBlendShapes()) { - for (const BlendShapeChannel* blendShapeChannel : blendShape->BlendShapeChannels()) { - const std::vector& shapeGeometries = blendShapeChannel->GetShapeGeometries(); - for (size_t i = 0; i < shapeGeometries.size(); i++) { - aiAnimMesh *animMesh = aiCreateAnimMesh(out_mesh); - const ShapeGeometry* shapeGeometry = shapeGeometries.at(i); - const std::vector& vertices = shapeGeometry->GetVertices(); - const std::vector& normals = shapeGeometry->GetNormals(); - const std::vector& indices = shapeGeometry->GetIndices(); - animMesh->mName.Set(FixAnimMeshName(shapeGeometry->Name())); - for (size_t j = 0; j < indices.size(); j++) { - unsigned int index = indices.at(j); - aiVector3D vertex = vertices.at(j); - aiVector3D normal = normals.at(j); - unsigned int count = 0; - const unsigned int* outIndices = mesh.ToOutputVertexIndex(index, count); - for (unsigned int k = 0; k < count; k++) { - unsigned int index = outIndices[k]; - animMesh->mVertices[index] += vertex; - if (animMesh->mNormals != nullptr) { - animMesh->mNormals[index] += normal; - animMesh->mNormals[index].NormalizeSafe(); - } - } - } - animMesh->mWeight = shapeGeometries.size() > 1 ? blendShapeChannel->DeformPercent() / 100.0f : 1.0f; - animMeshes.push_back(animMesh); - } - } - } - const size_t numAnimMeshes = animMeshes.size(); - if (numAnimMeshes > 0) { - out_mesh->mNumAnimMeshes = static_cast(numAnimMeshes); - out_mesh->mAnimMeshes = new aiAnimMesh*[numAnimMeshes]; - for (size_t i = 0; i < numAnimMeshes; i++) { - out_mesh->mAnimMeshes[i] = animMeshes.at(i); - } - } - return static_cast(meshes.size() - 1); - } - - std::vector - FBXConverter::ConvertMeshMultiMaterial(const MeshGeometry &mesh, const Model &model, aiNode *parent, - aiNode *root_node, - const aiMatrix4x4 &absolute_transform) - { - const MatIndexArray& mindices = mesh.GetMaterialIndices(); - ai_assert(mindices.size()); - - std::set had; - std::vector indices; - - for (MatIndexArray::value_type index : mindices) { - if (had.find(index) == had.end()) { - - indices.push_back(ConvertMeshMultiMaterial(mesh, model, index, parent, root_node, absolute_transform)); - had.insert(index); - } - } - - return indices; - } - - unsigned int FBXConverter::ConvertMeshMultiMaterial(const MeshGeometry &mesh, const Model &model, - MatIndexArray::value_type index, - aiNode *parent, aiNode *root_node, - const aiMatrix4x4 &absolute_transform) - { - aiMesh* const out_mesh = SetupEmptyMesh(mesh, parent); - - const MatIndexArray& mindices = mesh.GetMaterialIndices(); - const std::vector& vertices = mesh.GetVertices(); - const std::vector& faces = mesh.GetFaceIndexCounts(); - - const bool process_weights = doc.Settings().readWeights && mesh.DeformerSkin() != nullptr; - - unsigned int count_faces = 0; - unsigned int count_vertices = 0; - - // count faces - std::vector::const_iterator itf = faces.begin(); - for (MatIndexArray::const_iterator it = mindices.begin(), - end = mindices.end(); it != end; ++it, ++itf) - { - if ((*it) != index) { - continue; - } - ++count_faces; - count_vertices += *itf; - } - - ai_assert(count_faces); - ai_assert(count_vertices); - - // mapping from output indices to DOM indexing, needed to resolve weights or blendshapes - std::vector reverseMapping; - std::map translateIndexMap; - if (process_weights || mesh.GetBlendShapes().size() > 0) { - reverseMapping.resize(count_vertices); - } - - // allocate output data arrays, but don't fill them yet - out_mesh->mNumVertices = count_vertices; - out_mesh->mVertices = new aiVector3D[count_vertices]; - - out_mesh->mNumFaces = count_faces; - aiFace* fac = out_mesh->mFaces = new aiFace[count_faces](); - - - // allocate normals - const std::vector& normals = mesh.GetNormals(); - if (normals.size()) { - ai_assert(normals.size() == vertices.size()); - out_mesh->mNormals = new aiVector3D[vertices.size()]; - } - - // allocate tangents, binormals. - const std::vector& tangents = mesh.GetTangents(); - const std::vector* binormals = &mesh.GetBinormals(); - std::vector tempBinormals; - - if (tangents.size()) { - if (!binormals->size()) { - if (normals.size()) { - // XXX this computes the binormals for the entire mesh, not only - // the part for which we need them. - tempBinormals.resize(normals.size()); - for (unsigned int i = 0; i < tangents.size(); ++i) { - tempBinormals[i] = normals[i] ^ tangents[i]; - } - - binormals = &tempBinormals; - } - else { - binormals = nullptr; - } - } - - if (binormals) { - ai_assert(tangents.size() == vertices.size() && binormals->size() == vertices.size()); - - out_mesh->mTangents = new aiVector3D[vertices.size()]; - out_mesh->mBitangents = new aiVector3D[vertices.size()]; - } - } - - // allocate texture coords - unsigned int num_uvs = 0; - for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i, ++num_uvs) { - const std::vector& uvs = mesh.GetTextureCoords(i); - if (uvs.empty()) { - break; - } - - out_mesh->mTextureCoords[i] = new aiVector3D[vertices.size()]; - out_mesh->mNumUVComponents[i] = 2; - } - - // allocate vertex colors - unsigned int num_vcs = 0; - for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_COLOR_SETS; ++i, ++num_vcs) { - const std::vector& colors = mesh.GetVertexColors(i); - if (colors.empty()) { - break; - } - - out_mesh->mColors[i] = new aiColor4D[vertices.size()]; - } - - unsigned int cursor = 0, in_cursor = 0; - - itf = faces.begin(); - for (MatIndexArray::const_iterator it = mindices.begin(), end = mindices.end(); it != end; ++it, ++itf) - { - const unsigned int pcount = *itf; - if ((*it) != index) { - in_cursor += pcount; - continue; - } - - aiFace& f = *fac++; - - f.mNumIndices = pcount; - f.mIndices = new unsigned int[pcount]; - switch (pcount) - { - case 1: - out_mesh->mPrimitiveTypes |= aiPrimitiveType_POINT; - break; - case 2: - out_mesh->mPrimitiveTypes |= aiPrimitiveType_LINE; - break; - case 3: - out_mesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE; - break; - default: - out_mesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON; - break; - } - for (unsigned int i = 0; i < pcount; ++i, ++cursor, ++in_cursor) { - f.mIndices[i] = cursor; - - if (reverseMapping.size()) { - reverseMapping[cursor] = in_cursor; - translateIndexMap[in_cursor] = cursor; - } - - out_mesh->mVertices[cursor] = vertices[in_cursor]; - - if (out_mesh->mNormals) { - out_mesh->mNormals[cursor] = normals[in_cursor]; - } - - if (out_mesh->mTangents) { - out_mesh->mTangents[cursor] = tangents[in_cursor]; - out_mesh->mBitangents[cursor] = (*binormals)[in_cursor]; - } - - for (unsigned int j = 0; j < num_uvs; ++j) { - const std::vector& uvs = mesh.GetTextureCoords(j); - out_mesh->mTextureCoords[j][cursor] = aiVector3D(uvs[in_cursor].x, uvs[in_cursor].y, 0.0f); - } - - for (unsigned int j = 0; j < num_vcs; ++j) { - const std::vector& cols = mesh.GetVertexColors(j); - out_mesh->mColors[j][cursor] = cols[in_cursor]; - } - } - } - - ConvertMaterialForMesh(out_mesh, model, mesh, index); - - if (process_weights) { - ConvertWeights(out_mesh, model, mesh, absolute_transform, parent, root_node, index, &reverseMapping); - } - - std::vector animMeshes; - for (const BlendShape* blendShape : mesh.GetBlendShapes()) { - for (const BlendShapeChannel* blendShapeChannel : blendShape->BlendShapeChannels()) { - const std::vector& shapeGeometries = blendShapeChannel->GetShapeGeometries(); - for (size_t i = 0; i < shapeGeometries.size(); i++) { - aiAnimMesh* animMesh = aiCreateAnimMesh(out_mesh); - const ShapeGeometry* shapeGeometry = shapeGeometries.at(i); - const std::vector& vertices = shapeGeometry->GetVertices(); - const std::vector& normals = shapeGeometry->GetNormals(); - const std::vector& indices = shapeGeometry->GetIndices(); - animMesh->mName.Set(FixAnimMeshName(shapeGeometry->Name())); - for (size_t j = 0; j < indices.size(); j++) { - unsigned int index = indices.at(j); - aiVector3D vertex = vertices.at(j); - aiVector3D normal = normals.at(j); - unsigned int count = 0; - const unsigned int* outIndices = mesh.ToOutputVertexIndex(index, count); - for (unsigned int k = 0; k < count; k++) { - unsigned int outIndex = outIndices[k]; - if (translateIndexMap.find(outIndex) == translateIndexMap.end()) - continue; - unsigned int index = translateIndexMap[outIndex]; - animMesh->mVertices[index] += vertex; - if (animMesh->mNormals != nullptr) { - animMesh->mNormals[index] += normal; - animMesh->mNormals[index].NormalizeSafe(); - } - } - } - animMesh->mWeight = shapeGeometries.size() > 1 ? blendShapeChannel->DeformPercent() / 100.0f : 1.0f; - animMeshes.push_back(animMesh); - } - } - } - - const size_t numAnimMeshes = animMeshes.size(); - if (numAnimMeshes > 0) { - out_mesh->mNumAnimMeshes = static_cast(numAnimMeshes); - out_mesh->mAnimMeshes = new aiAnimMesh*[numAnimMeshes]; - for (size_t i = 0; i < numAnimMeshes; i++) { - out_mesh->mAnimMeshes[i] = animMeshes.at(i); - } - } - - return static_cast(meshes.size() - 1); - } - - void FBXConverter::ConvertWeights(aiMesh *out, const Model &model, const MeshGeometry &geo, - const aiMatrix4x4 &absolute_transform, - aiNode *parent, aiNode *root_node, unsigned int materialIndex, - std::vector *outputVertStartIndices) - { - ai_assert(geo.DeformerSkin()); - - std::vector out_indices; - std::vector index_out_indices; - std::vector count_out_indices; - - const Skin& sk = *geo.DeformerSkin(); - - std::vector bones; - - const bool no_mat_check = materialIndex == NO_MATERIAL_SEPARATION; - ai_assert(no_mat_check || outputVertStartIndices); - - try { - // iterate over the sub deformers - for (const Cluster* cluster : sk.Clusters()) { - ai_assert(cluster); - - const WeightIndexArray& indices = cluster->GetIndices(); - - const MatIndexArray& mats = geo.GetMaterialIndices(); - - const size_t no_index_sentinel = std::numeric_limits::max(); - - count_out_indices.clear(); - index_out_indices.clear(); - out_indices.clear(); - - - // now check if *any* of these weights is contained in the output mesh, - // taking notes so we don't need to do it twice. - for (WeightIndexArray::value_type index : indices) { - - unsigned int count = 0; - const unsigned int* const out_idx = geo.ToOutputVertexIndex(index, count); - // ToOutputVertexIndex only returns nullptr if index is out of bounds - // which should never happen - ai_assert(out_idx != nullptr); - - index_out_indices.push_back(no_index_sentinel); - count_out_indices.push_back(0); - - for (unsigned int i = 0; i < count; ++i) { - if (no_mat_check || static_cast(mats[geo.FaceForVertexIndex(out_idx[i])]) == materialIndex) { - - if (index_out_indices.back() == no_index_sentinel) { - index_out_indices.back() = out_indices.size(); - } - - if (no_mat_check) { - out_indices.push_back(out_idx[i]); - } else { - // this extra lookup is in O(logn), so the entire algorithm becomes O(nlogn) - const std::vector::iterator it = std::lower_bound( - outputVertStartIndices->begin(), - outputVertStartIndices->end(), - out_idx[i] - ); - - out_indices.push_back(std::distance(outputVertStartIndices->begin(), it)); - } - - ++count_out_indices.back(); - } - } - } - - // if we found at least one, generate the output bones - // XXX this could be heavily simplified by collecting the bone - // data in a single step. - ConvertCluster(bones, cluster, out_indices, index_out_indices, - count_out_indices, absolute_transform, parent, root_node); - } - - bone_map.clear(); - } - catch (std::exception&) { - std::for_each(bones.begin(), bones.end(), Util::delete_fun()); - throw; - } - - if (bones.empty()) { - out->mBones = nullptr; - out->mNumBones = 0; - return; - } else { - out->mBones = new aiBone *[bones.size()](); - out->mNumBones = static_cast(bones.size()); - - std::swap_ranges(bones.begin(), bones.end(), out->mBones); - } - } - - const aiNode* FBXConverter::GetNodeByName( const aiString& name, aiNode *current_node ) - { - aiNode * iter = current_node; - //printf("Child count: %d", iter->mNumChildren); - return iter; - } - - void FBXConverter::ConvertCluster(std::vector &local_mesh_bones, const Cluster *cl, - std::vector &out_indices, std::vector &index_out_indices, - std::vector &count_out_indices, const aiMatrix4x4 &absolute_transform, - aiNode *parent, aiNode *root_node) { - ai_assert(cl); // make sure cluster valid - std::string deformer_name = cl->TargetNode()->Name(); - aiString bone_name = aiString(FixNodeName(deformer_name)); - - aiBone *bone = nullptr; - - if (bone_map.count(deformer_name)) { - ASSIMP_LOG_DEBUG_F("retrieved bone from lookup ", bone_name.C_Str(), ". Deformer:", deformer_name); - bone = bone_map[deformer_name]; - } else { - ASSIMP_LOG_DEBUG_F("created new bone ", bone_name.C_Str(), ". Deformer: ", deformer_name); - bone = new aiBone(); - bone->mName = bone_name; - - // store local transform link for post processing - bone->mOffsetMatrix = cl->TransformLink(); - bone->mOffsetMatrix.Inverse(); - - aiMatrix4x4 matrix = (aiMatrix4x4)absolute_transform; - - bone->mOffsetMatrix = bone->mOffsetMatrix * matrix; // * mesh_offset - - - // - // Now calculate the aiVertexWeights - // - - aiVertexWeight *cursor = nullptr; - - bone->mNumWeights = static_cast(out_indices.size()); - cursor = bone->mWeights = new aiVertexWeight[out_indices.size()]; - - const size_t no_index_sentinel = std::numeric_limits::max(); - const WeightArray& weights = cl->GetWeights(); - - const size_t c = index_out_indices.size(); - for (size_t i = 0; i < c; ++i) { - const size_t index_index = index_out_indices[i]; - - if (index_index == no_index_sentinel) { - continue; - } - - const size_t cc = count_out_indices[i]; - for (size_t j = 0; j < cc; ++j) { - // cursor runs from first element relative to the start - // or relative to the start of the next indexes. - aiVertexWeight& out_weight = *cursor++; - - out_weight.mVertexId = static_cast(out_indices[index_index + j]); - out_weight.mWeight = weights[i]; - } - } - - bone_map.insert(std::pair(deformer_name, bone)); - } - - ASSIMP_LOG_DEBUG_F("bone research: Indicies size: ", out_indices.size()); - - // lookup must be populated in case something goes wrong - // this also allocates bones to mesh instance outside - local_mesh_bones.push_back(bone); - } - - void FBXConverter::ConvertMaterialForMesh(aiMesh* out, const Model& model, const MeshGeometry& geo, - MatIndexArray::value_type materialIndex) - { - // locate source materials for this mesh - const std::vector& mats = model.GetMaterials(); - if (static_cast(materialIndex) >= mats.size() || materialIndex < 0) { - FBXImporter::LogError("material index out of bounds, setting default material"); - out->mMaterialIndex = GetDefaultMaterial(); - return; - } - - const Material* const mat = mats[materialIndex]; - MaterialMap::const_iterator it = materials_converted.find(mat); - if (it != materials_converted.end()) { - out->mMaterialIndex = (*it).second; - return; - } - - out->mMaterialIndex = ConvertMaterial(*mat, &geo); - materials_converted[mat] = out->mMaterialIndex; - } - - unsigned int FBXConverter::GetDefaultMaterial() - { - if (defaultMaterialIndex) { - return defaultMaterialIndex - 1; - } - - aiMaterial* out_mat = new aiMaterial(); - materials.push_back(out_mat); - - const aiColor3D diffuse = aiColor3D(0.8f, 0.8f, 0.8f); - out_mat->AddProperty(&diffuse, 1, AI_MATKEY_COLOR_DIFFUSE); - - aiString s; - s.Set(AI_DEFAULT_MATERIAL_NAME); - - out_mat->AddProperty(&s, AI_MATKEY_NAME); - - defaultMaterialIndex = static_cast(materials.size()); - return defaultMaterialIndex - 1; - } - - - unsigned int FBXConverter::ConvertMaterial(const Material& material, const MeshGeometry* const mesh) - { - const PropertyTable& props = material.Props(); - - // generate empty output material - aiMaterial* out_mat = new aiMaterial(); - materials_converted[&material] = static_cast(materials.size()); - - materials.push_back(out_mat); - - aiString str; - - // strip Material:: prefix - std::string name = material.Name(); - if (name.substr(0, 10) == "Material::") { - name = name.substr(10); - } - - // set material name if not empty - this could happen - // and there should be no key for it in this case. - if (name.length()) { - str.Set(name); - out_mat->AddProperty(&str, AI_MATKEY_NAME); - } - - // Set the shading mode as best we can: The FBX specification only mentions Lambert and Phong, and only Phong is mentioned in Assimp's aiShadingMode enum. - if (material.GetShadingModel() == "phong") - { - aiShadingMode shadingMode = aiShadingMode_Phong; - out_mat->AddProperty(&shadingMode, 1, AI_MATKEY_SHADING_MODEL); - } - - // shading stuff and colors - SetShadingPropertiesCommon(out_mat, props); - SetShadingPropertiesRaw( out_mat, props, material.Textures(), mesh ); - - // texture assignments - SetTextureProperties(out_mat, material.Textures(), mesh); - SetTextureProperties(out_mat, material.LayeredTextures(), mesh); - - return static_cast(materials.size() - 1); - } - - unsigned int FBXConverter::ConvertVideo(const Video& video) - { - // generate empty output texture - aiTexture* out_tex = new aiTexture(); - textures.push_back(out_tex); - - // assuming the texture is compressed - out_tex->mWidth = static_cast(video.ContentLength()); // total data size - out_tex->mHeight = 0; // fixed to 0 - - // steal the data from the Video to avoid an additional copy - out_tex->pcData = reinterpret_cast(const_cast(video).RelinquishContent()); - - // try to extract a hint from the file extension - const std::string& filename = video.RelativeFilename().empty() ? video.FileName() : video.RelativeFilename(); - std::string ext = BaseImporter::GetExtension(filename); - - if (ext == "jpeg") { - ext = "jpg"; - } - - if (ext.size() <= 3) { - memcpy(out_tex->achFormatHint, ext.c_str(), ext.size()); - } - - out_tex->mFilename.Set(filename.c_str()); - - return static_cast(textures.size() - 1); - } - - aiString FBXConverter::GetTexturePath(const Texture* tex) - { - aiString path; - path.Set(tex->RelativeFilename()); - - const Video* media = tex->Media(); - if (media != nullptr) { - bool textureReady = false; //tells if our texture is ready (if it was loaded or if it was found) - unsigned int index; - - VideoMap::const_iterator it = textures_converted.find(*media); - if (it != textures_converted.end()) { - index = (*it).second; - textureReady = true; - } - else { - if (media->ContentLength() > 0) { - index = ConvertVideo(*media); - textures_converted[*media] = index; - textureReady = true; - } - } - - // setup texture reference string (copied from ColladaLoader::FindFilenameForEffectTexture), if the texture is ready - if (doc.Settings().useLegacyEmbeddedTextureNaming) { - if (textureReady) { - // TODO: check the possibility of using the flag "AI_CONFIG_IMPORT_FBX_EMBEDDED_TEXTURES_LEGACY_NAMING" - // In FBX files textures are now stored internally by Assimp with their filename included - // Now Assimp can lookup through the loaded textures after all data is processed - // We need to load all textures before referencing them, as FBX file format order may reference a texture before loading it - // This may occur on this case too, it has to be studied - path.data[0] = '*'; - path.length = 1 + ASSIMP_itoa10(path.data + 1, MAXLEN - 1, index); - } - } - } - - return path; - } - - void FBXConverter::TrySetTextureProperties(aiMaterial* out_mat, const TextureMap& textures, - const std::string& propName, - aiTextureType target, const MeshGeometry* const mesh) { - TextureMap::const_iterator it = textures.find(propName); - if (it == textures.end()) { - return; - } - - const Texture* const tex = (*it).second; - if (tex != 0) - { - aiString path = GetTexturePath(tex); - out_mat->AddProperty(&path, _AI_MATKEY_TEXTURE_BASE, target, 0); - - aiUVTransform uvTrafo; - // XXX handle all kinds of UV transformations - uvTrafo.mScaling = tex->UVScaling(); - uvTrafo.mTranslation = tex->UVTranslation(); - out_mat->AddProperty(&uvTrafo, 1, _AI_MATKEY_UVTRANSFORM_BASE, target, 0); - - const PropertyTable& props = tex->Props(); - - int uvIndex = 0; - - bool ok; - const std::string& uvSet = PropertyGet(props, "UVSet", ok); - if (ok) { - // "default" is the name which usually appears in the FbxFileTexture template - if (uvSet != "default" && uvSet.length()) { - // this is a bit awkward - we need to find a mesh that uses this - // material and scan its UV channels for the given UV name because - // assimp references UV channels by index, not by name. - - // XXX: the case that UV channels may appear in different orders - // in meshes is unhandled. A possible solution would be to sort - // the UV channels alphabetically, but this would have the side - // effect that the primary (first) UV channel would sometimes - // be moved, causing trouble when users read only the first - // UV channel and ignore UV channel assignments altogether. - - const unsigned int matIndex = static_cast(std::distance(materials.begin(), - std::find(materials.begin(), materials.end(), out_mat) - )); - - - uvIndex = -1; - if (!mesh) - { - for (const MeshMap::value_type& v : meshes_converted) { - const MeshGeometry* const meshGeom = dynamic_cast (v.first); - if (!meshGeom) { - continue; - } - - const MatIndexArray& mats = meshGeom->GetMaterialIndices(); - if (std::find(mats.begin(), mats.end(), matIndex) == mats.end()) { - continue; - } - - int index = -1; - for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) { - if (meshGeom->GetTextureCoords(i).empty()) { - break; - } - const std::string& name = meshGeom->GetTextureCoordChannelName(i); - if (name == uvSet) { - index = static_cast(i); - break; - } - } - if (index == -1) { - FBXImporter::LogWarn("did not find UV channel named " + uvSet + " in a mesh using this material"); - continue; - } - - if (uvIndex == -1) { - uvIndex = index; - } - else { - FBXImporter::LogWarn("the UV channel named " + uvSet + - " appears at different positions in meshes, results will be wrong"); - } - } - } - else - { - int index = -1; - for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) { - if (mesh->GetTextureCoords(i).empty()) { - break; - } - const std::string& name = mesh->GetTextureCoordChannelName(i); - if (name == uvSet) { - index = static_cast(i); - break; - } - } - if (index == -1) { - FBXImporter::LogWarn("did not find UV channel named " + uvSet + " in a mesh using this material"); - } - - if (uvIndex == -1) { - uvIndex = index; - } - } - - if (uvIndex == -1) { - FBXImporter::LogWarn("failed to resolve UV channel " + uvSet + ", using first UV channel"); - uvIndex = 0; - } - } - } - - out_mat->AddProperty(&uvIndex, 1, _AI_MATKEY_UVWSRC_BASE, target, 0); - } - } - - void FBXConverter::TrySetTextureProperties(aiMaterial* out_mat, const LayeredTextureMap& layeredTextures, - const std::string& propName, - aiTextureType target, const MeshGeometry* const mesh) { - LayeredTextureMap::const_iterator it = layeredTextures.find(propName); - if (it == layeredTextures.end()) { - return; - } - - int texCount = (*it).second->textureCount(); - - // Set the blend mode for layered textures - int blendmode = (*it).second->GetBlendMode(); - out_mat->AddProperty(&blendmode, 1, _AI_MATKEY_TEXOP_BASE, target, 0); - - for (int texIndex = 0; texIndex < texCount; texIndex++) { - - const Texture* const tex = (*it).second->getTexture(texIndex); - - aiString path = GetTexturePath(tex); - out_mat->AddProperty(&path, _AI_MATKEY_TEXTURE_BASE, target, texIndex); - - aiUVTransform uvTrafo; - // XXX handle all kinds of UV transformations - uvTrafo.mScaling = tex->UVScaling(); - uvTrafo.mTranslation = tex->UVTranslation(); - out_mat->AddProperty(&uvTrafo, 1, _AI_MATKEY_UVTRANSFORM_BASE, target, texIndex); - - const PropertyTable& props = tex->Props(); - - int uvIndex = 0; - - bool ok; - const std::string& uvSet = PropertyGet(props, "UVSet", ok); - if (ok) { - // "default" is the name which usually appears in the FbxFileTexture template - if (uvSet != "default" && uvSet.length()) { - // this is a bit awkward - we need to find a mesh that uses this - // material and scan its UV channels for the given UV name because - // assimp references UV channels by index, not by name. - - // XXX: the case that UV channels may appear in different orders - // in meshes is unhandled. A possible solution would be to sort - // the UV channels alphabetically, but this would have the side - // effect that the primary (first) UV channel would sometimes - // be moved, causing trouble when users read only the first - // UV channel and ignore UV channel assignments altogether. - - const unsigned int matIndex = static_cast(std::distance(materials.begin(), - std::find(materials.begin(), materials.end(), out_mat) - )); - - uvIndex = -1; - if (!mesh) - { - for (const MeshMap::value_type& v : meshes_converted) { - const MeshGeometry* const meshGeom = dynamic_cast (v.first); - if (!meshGeom) { - continue; - } - - const MatIndexArray& mats = meshGeom->GetMaterialIndices(); - if (std::find(mats.begin(), mats.end(), matIndex) == mats.end()) { - continue; - } - - int index = -1; - for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) { - if (meshGeom->GetTextureCoords(i).empty()) { - break; - } - const std::string& name = meshGeom->GetTextureCoordChannelName(i); - if (name == uvSet) { - index = static_cast(i); - break; - } - } - if (index == -1) { - FBXImporter::LogWarn("did not find UV channel named " + uvSet + " in a mesh using this material"); - continue; - } - - if (uvIndex == -1) { - uvIndex = index; - } - else { - FBXImporter::LogWarn("the UV channel named " + uvSet + - " appears at different positions in meshes, results will be wrong"); - } - } - } - else - { - int index = -1; - for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) { - if (mesh->GetTextureCoords(i).empty()) { - break; - } - const std::string& name = mesh->GetTextureCoordChannelName(i); - if (name == uvSet) { - index = static_cast(i); - break; - } - } - if (index == -1) { - FBXImporter::LogWarn("did not find UV channel named " + uvSet + " in a mesh using this material"); - } - - if (uvIndex == -1) { - uvIndex = index; - } - } - - if (uvIndex == -1) { - FBXImporter::LogWarn("failed to resolve UV channel " + uvSet + ", using first UV channel"); - uvIndex = 0; - } - } - } - - out_mat->AddProperty(&uvIndex, 1, _AI_MATKEY_UVWSRC_BASE, target, texIndex); - } - } - - void FBXConverter::SetTextureProperties(aiMaterial* out_mat, const TextureMap& textures, const MeshGeometry* const mesh) - { - TrySetTextureProperties(out_mat, textures, "DiffuseColor", aiTextureType_DIFFUSE, mesh); - TrySetTextureProperties(out_mat, textures, "AmbientColor", aiTextureType_AMBIENT, mesh); - TrySetTextureProperties(out_mat, textures, "EmissiveColor", aiTextureType_EMISSIVE, mesh); - TrySetTextureProperties(out_mat, textures, "SpecularColor", aiTextureType_SPECULAR, mesh); - TrySetTextureProperties(out_mat, textures, "SpecularFactor", aiTextureType_SPECULAR, mesh); - TrySetTextureProperties(out_mat, textures, "TransparentColor", aiTextureType_OPACITY, mesh); - TrySetTextureProperties(out_mat, textures, "ReflectionColor", aiTextureType_REFLECTION, mesh); - TrySetTextureProperties(out_mat, textures, "DisplacementColor", aiTextureType_DISPLACEMENT, mesh); - TrySetTextureProperties(out_mat, textures, "NormalMap", aiTextureType_NORMALS, mesh); - TrySetTextureProperties(out_mat, textures, "Bump", aiTextureType_HEIGHT, mesh); - TrySetTextureProperties(out_mat, textures, "ShininessExponent", aiTextureType_SHININESS, mesh); - TrySetTextureProperties( out_mat, textures, "TransparencyFactor", aiTextureType_OPACITY, mesh ); - TrySetTextureProperties( out_mat, textures, "EmissiveFactor", aiTextureType_EMISSIVE, mesh ); - //Maya counterparts - TrySetTextureProperties(out_mat, textures, "Maya|DiffuseTexture", aiTextureType_DIFFUSE, mesh); - TrySetTextureProperties(out_mat, textures, "Maya|NormalTexture", aiTextureType_NORMALS, mesh); - TrySetTextureProperties(out_mat, textures, "Maya|SpecularTexture", aiTextureType_SPECULAR, mesh); - TrySetTextureProperties(out_mat, textures, "Maya|FalloffTexture", aiTextureType_OPACITY, mesh); - TrySetTextureProperties(out_mat, textures, "Maya|ReflectionMapTexture", aiTextureType_REFLECTION, mesh); - - // Maya PBR - TrySetTextureProperties(out_mat, textures, "Maya|baseColor|file", aiTextureType_BASE_COLOR, mesh); - TrySetTextureProperties(out_mat, textures, "Maya|normalCamera|file", aiTextureType_NORMAL_CAMERA, mesh); - TrySetTextureProperties(out_mat, textures, "Maya|emissionColor|file", aiTextureType_EMISSION_COLOR, mesh); - TrySetTextureProperties(out_mat, textures, "Maya|metalness|file", aiTextureType_METALNESS, mesh); - TrySetTextureProperties(out_mat, textures, "Maya|diffuseRoughness|file", aiTextureType_DIFFUSE_ROUGHNESS, mesh); - - // Maya stingray - TrySetTextureProperties(out_mat, textures, "Maya|TEX_color_map|file", aiTextureType_BASE_COLOR, mesh); - TrySetTextureProperties(out_mat, textures, "Maya|TEX_normal_map|file", aiTextureType_NORMAL_CAMERA, mesh); - TrySetTextureProperties(out_mat, textures, "Maya|TEX_emissive_map|file", aiTextureType_EMISSION_COLOR, mesh); - TrySetTextureProperties(out_mat, textures, "Maya|TEX_metallic_map|file", aiTextureType_METALNESS, mesh); - TrySetTextureProperties(out_mat, textures, "Maya|TEX_roughness_map|file", aiTextureType_DIFFUSE_ROUGHNESS, mesh); - TrySetTextureProperties(out_mat, textures, "Maya|TEX_ao_map|file", aiTextureType_AMBIENT_OCCLUSION, mesh); - - // 3DSMax PBR - TrySetTextureProperties(out_mat, textures, "3dsMax|Parameters|base_color_map", aiTextureType_BASE_COLOR, mesh); - TrySetTextureProperties(out_mat, textures, "3dsMax|Parameters|bump_map", aiTextureType_NORMAL_CAMERA, mesh); - TrySetTextureProperties(out_mat, textures, "3dsMax|Parameters|emission_map", aiTextureType_EMISSION_COLOR, mesh); - TrySetTextureProperties(out_mat, textures, "3dsMax|Parameters|metalness_map", aiTextureType_METALNESS, mesh); - TrySetTextureProperties(out_mat, textures, "3dsMax|Parameters|roughness_map", aiTextureType_DIFFUSE_ROUGHNESS, mesh); - } - - void FBXConverter::SetTextureProperties(aiMaterial* out_mat, const LayeredTextureMap& layeredTextures, const MeshGeometry* const mesh) - { - TrySetTextureProperties(out_mat, layeredTextures, "DiffuseColor", aiTextureType_DIFFUSE, mesh); - TrySetTextureProperties(out_mat, layeredTextures, "AmbientColor", aiTextureType_AMBIENT, mesh); - TrySetTextureProperties(out_mat, layeredTextures, "EmissiveColor", aiTextureType_EMISSIVE, mesh); - TrySetTextureProperties(out_mat, layeredTextures, "SpecularColor", aiTextureType_SPECULAR, mesh); - TrySetTextureProperties(out_mat, layeredTextures, "SpecularFactor", aiTextureType_SPECULAR, mesh); - TrySetTextureProperties(out_mat, layeredTextures, "TransparentColor", aiTextureType_OPACITY, mesh); - TrySetTextureProperties(out_mat, layeredTextures, "ReflectionColor", aiTextureType_REFLECTION, mesh); - TrySetTextureProperties(out_mat, layeredTextures, "DisplacementColor", aiTextureType_DISPLACEMENT, mesh); - TrySetTextureProperties(out_mat, layeredTextures, "NormalMap", aiTextureType_NORMALS, mesh); - TrySetTextureProperties(out_mat, layeredTextures, "Bump", aiTextureType_HEIGHT, mesh); - TrySetTextureProperties(out_mat, layeredTextures, "ShininessExponent", aiTextureType_SHININESS, mesh); - TrySetTextureProperties( out_mat, layeredTextures, "EmissiveFactor", aiTextureType_EMISSIVE, mesh ); - TrySetTextureProperties( out_mat, layeredTextures, "TransparencyFactor", aiTextureType_OPACITY, mesh ); - } - - aiColor3D FBXConverter::GetColorPropertyFactored(const PropertyTable& props, const std::string& colorName, - const std::string& factorName, bool& result, bool useTemplate) - { - result = true; - - bool ok; - aiVector3D BaseColor = PropertyGet(props, colorName, ok, useTemplate); - if (!ok) { - result = false; - return aiColor3D(0.0f, 0.0f, 0.0f); - } - - // if no factor name, return the colour as is - if (factorName.empty()) { - return aiColor3D(BaseColor.x, BaseColor.y, BaseColor.z); - } - - // otherwise it should be multiplied by the factor, if found. - float factor = PropertyGet(props, factorName, ok, useTemplate); - if (ok) { - BaseColor *= factor; - } - return aiColor3D(BaseColor.x, BaseColor.y, BaseColor.z); - } - - aiColor3D FBXConverter::GetColorPropertyFromMaterial(const PropertyTable& props, const std::string& baseName, - bool& result) - { - return GetColorPropertyFactored(props, baseName + "Color", baseName + "Factor", result, true); - } - - aiColor3D FBXConverter::GetColorProperty(const PropertyTable& props, const std::string& colorName, - bool& result, bool useTemplate) - { - result = true; - bool ok; - const aiVector3D& ColorVec = PropertyGet(props, colorName, ok, useTemplate); - if (!ok) { - result = false; - return aiColor3D(0.0f, 0.0f, 0.0f); - } - return aiColor3D(ColorVec.x, ColorVec.y, ColorVec.z); - } - - void FBXConverter::SetShadingPropertiesCommon(aiMaterial* out_mat, const PropertyTable& props) - { - // Set shading properties. - // Modern FBX Files have two separate systems for defining these, - // with only the more comprehensive one described in the property template. - // Likely the other values are a legacy system, - // which is still always exported by the official FBX SDK. - // - // Blender's FBX import and export mostly ignore this legacy system, - // and as we only support recent versions of FBX anyway, we can do the same. - bool ok; - - const aiColor3D& Diffuse = GetColorPropertyFromMaterial(props, "Diffuse", ok); - if (ok) { - out_mat->AddProperty(&Diffuse, 1, AI_MATKEY_COLOR_DIFFUSE); - } - - const aiColor3D& Emissive = GetColorPropertyFromMaterial(props, "Emissive", ok); - if (ok) { - out_mat->AddProperty(&Emissive, 1, AI_MATKEY_COLOR_EMISSIVE); - } - - const aiColor3D& Ambient = GetColorPropertyFromMaterial(props, "Ambient", ok); - if (ok) { - out_mat->AddProperty(&Ambient, 1, AI_MATKEY_COLOR_AMBIENT); - } - - // we store specular factor as SHININESS_STRENGTH, so just get the color - const aiColor3D& Specular = GetColorProperty(props, "SpecularColor", ok, true); - if (ok) { - out_mat->AddProperty(&Specular, 1, AI_MATKEY_COLOR_SPECULAR); - } - - // and also try to get SHININESS_STRENGTH - const float SpecularFactor = PropertyGet(props, "SpecularFactor", ok, true); - if (ok) { - out_mat->AddProperty(&SpecularFactor, 1, AI_MATKEY_SHININESS_STRENGTH); - } - - // and the specular exponent - const float ShininessExponent = PropertyGet(props, "ShininessExponent", ok); - if (ok) { - out_mat->AddProperty(&ShininessExponent, 1, AI_MATKEY_SHININESS); - } - - // TransparentColor / TransparencyFactor... gee thanks FBX :rolleyes: - const aiColor3D& Transparent = GetColorPropertyFactored(props, "TransparentColor", "TransparencyFactor", ok); - float CalculatedOpacity = 1.0f; - if (ok) { - out_mat->AddProperty(&Transparent, 1, AI_MATKEY_COLOR_TRANSPARENT); - // as calculated by FBX SDK 2017: - CalculatedOpacity = 1.0f - ((Transparent.r + Transparent.g + Transparent.b) / 3.0f); - } - - // try to get the transparency factor - const float TransparencyFactor = PropertyGet(props, "TransparencyFactor", ok); - if (ok) { - out_mat->AddProperty(&TransparencyFactor, 1, AI_MATKEY_TRANSPARENCYFACTOR); - } - - // use of TransparencyFactor is inconsistent. - // Maya always stores it as 1.0, - // so we can't use it to set AI_MATKEY_OPACITY. - // Blender is more sensible and stores it as the alpha value. - // However both the FBX SDK and Blender always write an additional - // legacy "Opacity" field, so we can try to use that. - // - // If we can't find it, - // we can fall back to the value which the FBX SDK calculates - // from transparency colour (RGB) and factor (F) as - // 1.0 - F*((R+G+B)/3). - // - // There's no consistent way to interpret this opacity value, - // so it's up to clients to do the correct thing. - const float Opacity = PropertyGet(props, "Opacity", ok); - if (ok) { - out_mat->AddProperty(&Opacity, 1, AI_MATKEY_OPACITY); - } - else if (CalculatedOpacity != 1.0) { - out_mat->AddProperty(&CalculatedOpacity, 1, AI_MATKEY_OPACITY); - } - - // reflection color and factor are stored separately - const aiColor3D& Reflection = GetColorProperty(props, "ReflectionColor", ok, true); - if (ok) { - out_mat->AddProperty(&Reflection, 1, AI_MATKEY_COLOR_REFLECTIVE); - } - - float ReflectionFactor = PropertyGet(props, "ReflectionFactor", ok, true); - if (ok) { - out_mat->AddProperty(&ReflectionFactor, 1, AI_MATKEY_REFLECTIVITY); - } - - const float BumpFactor = PropertyGet(props, "BumpFactor", ok); - if (ok) { - out_mat->AddProperty(&BumpFactor, 1, AI_MATKEY_BUMPSCALING); - } - - const float DispFactor = PropertyGet(props, "DisplacementFactor", ok); - if (ok) { - out_mat->AddProperty(&DispFactor, 1, "$mat.displacementscaling", 0, 0); + // if we didn't read any meshes set the AI_SCENE_FLAGS_INCOMPLETE + // to make sure the scene passes assimp's validation. FBX files + // need not contain geometry (i.e. camera animations, raw armatures). + if (out->mNumMeshes == 0) { + out->mFlags |= AI_SCENE_FLAGS_INCOMPLETE; } } +FBXConverter::~FBXConverter() { + std::for_each(mMeshes.begin(), mMeshes.end(), Util::delete_fun()); + std::for_each(materials.begin(), materials.end(), Util::delete_fun()); + std::for_each(animations.begin(), animations.end(), Util::delete_fun()); + std::for_each(lights.begin(), lights.end(), Util::delete_fun()); + std::for_each(cameras.begin(), cameras.end(), Util::delete_fun()); + std::for_each(textures.begin(), textures.end(), Util::delete_fun()); +} -void FBXConverter::SetShadingPropertiesRaw(aiMaterial* out_mat, const PropertyTable& props, const TextureMap& textures, const MeshGeometry* const mesh) -{ +void FBXConverter::ConvertRootNode() { + mSceneOut->mRootNode = new aiNode(); + std::string unique_name; + GetUniqueName("RootNode", unique_name); + mSceneOut->mRootNode->mName.Set(unique_name); + + // root has ID 0 + ConvertNodes(0L, mSceneOut->mRootNode, mSceneOut->mRootNode); +} + +static std::string getAncestorBaseName(const aiNode *node) { + const char *nodeName = nullptr; + size_t length = 0; + while (node && (!nodeName || length == 0)) { + nodeName = node->mName.C_Str(); + length = node->mName.length; + node = node->mParent; + } + + if (!nodeName || length == 0) { + return {}; + } + // could be std::string_view if c++17 available + return std::string(nodeName, length); +} + +// Make unique name +std::string FBXConverter::MakeUniqueNodeName(const Model *const model, const aiNode &parent) { + std::string original_name = FixNodeName(model->Name()); + if (original_name.empty()) { + original_name = getAncestorBaseName(&parent); + } + std::string unique_name; + GetUniqueName(original_name, unique_name); + return unique_name; +} + +/// todo: pre-build node hierarchy +/// todo: get bone from stack +/// todo: make map of aiBone* to aiNode* +/// then update convert clusters to the new format +void FBXConverter::ConvertNodes(uint64_t id, aiNode *parent, aiNode *root_node) { + const std::vector &conns = doc.GetConnectionsByDestinationSequenced(id, "Model"); + + std::vector nodes; + nodes.reserve(conns.size()); + + std::vector nodes_chain; + std::vector post_nodes_chain; + + try { + for (const Connection *con : conns) { + // ignore object-property links + if (con->PropertyName().length()) { + // really important we document why this is ignored. + FBXImporter::LogInfo("ignoring property link - no docs on why this is ignored"); + continue; //? + } + + // convert connection source object into Object base class + const Object *const object = con->SourceObject(); + if (nullptr == object) { + FBXImporter::LogError("failed to convert source object for Model link"); + continue; + } + + // FBX Model::Cube, Model::Bone001, etc elements + // This detects if we can cast the object into this model structure. + const Model *const model = dynamic_cast(object); + + if (nullptr != model) { + nodes_chain.clear(); + post_nodes_chain.clear(); + + aiMatrix4x4 new_abs_transform = parent->mTransformation; + std::string node_name = FixNodeName(model->Name()); + // even though there is only a single input node, the design of + // assimp (or rather: the complicated transformation chain that + // is employed by fbx) means that we may need multiple aiNode's + // to represent a fbx node's transformation. + + // generate node transforms - this includes pivot data + // if need_additional_node is true then you t + const bool need_additional_node = GenerateTransformationNodeChain(*model, node_name, nodes_chain, post_nodes_chain); + + // assert that for the current node we must have at least a single transform + ai_assert(nodes_chain.size()); + + if (need_additional_node) { + nodes_chain.push_back(new aiNode(node_name)); + } + + //setup metadata on newest node + SetupNodeMetadata(*model, *nodes_chain.back()); + + // link all nodes in a row + aiNode *last_parent = parent; + for (aiNode *child : nodes_chain) { + ai_assert(child); + + if (last_parent != parent) { + last_parent->mNumChildren = 1; + last_parent->mChildren = new aiNode *[1]; + last_parent->mChildren[0] = child; + } + + child->mParent = last_parent; + last_parent = child; + + new_abs_transform *= child->mTransformation; + } + + // attach geometry + ConvertModel(*model, nodes_chain.back(), root_node, new_abs_transform); + + // check if there will be any child nodes + const std::vector &child_conns = doc.GetConnectionsByDestinationSequenced(model->ID(), "Model"); + + // if so, link the geometric transform inverse nodes + // before we attach any child nodes + if (child_conns.size()) { + for (aiNode *postnode : post_nodes_chain) { + ai_assert(postnode); + + if (last_parent != parent) { + last_parent->mNumChildren = 1; + last_parent->mChildren = new aiNode *[1]; + last_parent->mChildren[0] = postnode; + } + + postnode->mParent = last_parent; + last_parent = postnode; + + new_abs_transform *= postnode->mTransformation; + } + } else { + // free the nodes we allocated as we don't need them + Util::delete_fun deleter; + std::for_each( + post_nodes_chain.begin(), + post_nodes_chain.end(), + deleter); + } + + // recursion call - child nodes + ConvertNodes(model->ID(), last_parent, root_node); + + if (doc.Settings().readLights) { + ConvertLights(*model, node_name); + } + + if (doc.Settings().readCameras) { + ConvertCameras(*model, node_name); + } + + nodes.push_back(nodes_chain.front()); + nodes_chain.clear(); + } + } + + if (nodes.size()) { + parent->mChildren = new aiNode *[nodes.size()](); + parent->mNumChildren = static_cast(nodes.size()); + + std::swap_ranges(nodes.begin(), nodes.end(), parent->mChildren); + } else { + parent->mNumChildren = 0; + parent->mChildren = nullptr; + } + + } catch (std::exception &) { + Util::delete_fun deleter; + std::for_each(nodes.begin(), nodes.end(), deleter); + std::for_each(nodes_chain.begin(), nodes_chain.end(), deleter); + std::for_each(post_nodes_chain.begin(), post_nodes_chain.end(), deleter); + } +} + +void FBXConverter::ConvertLights(const Model &model, const std::string &orig_name) { + const std::vector &node_attrs = model.GetAttributes(); + for (const NodeAttribute *attr : node_attrs) { + const Light *const light = dynamic_cast(attr); + if (light) { + ConvertLight(*light, orig_name); + } + } +} + +void FBXConverter::ConvertCameras(const Model &model, const std::string &orig_name) { + const std::vector &node_attrs = model.GetAttributes(); + for (const NodeAttribute *attr : node_attrs) { + const Camera *const cam = dynamic_cast(attr); + if (cam) { + ConvertCamera(*cam, orig_name); + } + } +} + +void FBXConverter::ConvertLight(const Light &light, const std::string &orig_name) { + lights.push_back(new aiLight()); + aiLight *const out_light = lights.back(); + + out_light->mName.Set(orig_name); + + const float intensity = light.Intensity() / 100.0f; + const aiVector3D &col = light.Color(); + + out_light->mColorDiffuse = aiColor3D(col.x, col.y, col.z); + out_light->mColorDiffuse.r *= intensity; + out_light->mColorDiffuse.g *= intensity; + out_light->mColorDiffuse.b *= intensity; + + out_light->mColorSpecular = out_light->mColorDiffuse; + + //lights are defined along negative y direction + out_light->mPosition = aiVector3D(0.0f); + out_light->mDirection = aiVector3D(0.0f, -1.0f, 0.0f); + out_light->mUp = aiVector3D(0.0f, 0.0f, -1.0f); + + switch (light.LightType()) { + case Light::Type_Point: + out_light->mType = aiLightSource_POINT; + break; + + case Light::Type_Directional: + out_light->mType = aiLightSource_DIRECTIONAL; + break; + + case Light::Type_Spot: + out_light->mType = aiLightSource_SPOT; + out_light->mAngleOuterCone = AI_DEG_TO_RAD(light.OuterAngle()); + out_light->mAngleInnerCone = AI_DEG_TO_RAD(light.InnerAngle()); + break; + + case Light::Type_Area: + FBXImporter::LogWarn("cannot represent area light, set to UNDEFINED"); + out_light->mType = aiLightSource_UNDEFINED; + break; + + case Light::Type_Volume: + FBXImporter::LogWarn("cannot represent volume light, set to UNDEFINED"); + out_light->mType = aiLightSource_UNDEFINED; + break; + default: + ai_assert(false); + } + + float decay = light.DecayStart(); + switch (light.DecayType()) { + case Light::Decay_None: + out_light->mAttenuationConstant = decay; + out_light->mAttenuationLinear = 0.0f; + out_light->mAttenuationQuadratic = 0.0f; + break; + case Light::Decay_Linear: + out_light->mAttenuationConstant = 0.0f; + out_light->mAttenuationLinear = 2.0f / decay; + out_light->mAttenuationQuadratic = 0.0f; + break; + case Light::Decay_Quadratic: + out_light->mAttenuationConstant = 0.0f; + out_light->mAttenuationLinear = 0.0f; + out_light->mAttenuationQuadratic = 2.0f / (decay * decay); + break; + case Light::Decay_Cubic: + FBXImporter::LogWarn("cannot represent cubic attenuation, set to Quadratic"); + out_light->mAttenuationQuadratic = 1.0f; + break; + default: + ai_assert(false); + break; + } +} + +void FBXConverter::ConvertCamera(const Camera &cam, const std::string &orig_name) { + cameras.push_back(new aiCamera()); + aiCamera *const out_camera = cameras.back(); + + out_camera->mName.Set(orig_name); + + out_camera->mAspect = cam.AspectWidth() / cam.AspectHeight(); + + out_camera->mPosition = aiVector3D(0.0f); + out_camera->mLookAt = aiVector3D(1.0f, 0.0f, 0.0f); + out_camera->mUp = aiVector3D(0.0f, 1.0f, 0.0f); + + out_camera->mHorizontalFOV = AI_DEG_TO_RAD(cam.FieldOfView()); + + out_camera->mClipPlaneNear = cam.NearPlane(); + out_camera->mClipPlaneFar = cam.FarPlane(); + + out_camera->mHorizontalFOV = AI_DEG_TO_RAD(cam.FieldOfView()); + out_camera->mClipPlaneNear = cam.NearPlane(); + out_camera->mClipPlaneFar = cam.FarPlane(); +} + +void FBXConverter::GetUniqueName(const std::string &name, std::string &uniqueName) { + uniqueName = name; + auto it_pair = mNodeNames.insert({ name, 0 }); // duplicate node name instance count + unsigned int &i = it_pair.first->second; + while (!it_pair.second) { + i++; + std::ostringstream ext; + ext << name << std::setfill('0') << std::setw(3) << i; + uniqueName = ext.str(); + it_pair = mNodeNames.insert({ uniqueName, 0 }); + } +} + +const char *FBXConverter::NameTransformationComp(TransformationComp comp) { + switch (comp) { + case TransformationComp_Translation: + return "Translation"; + case TransformationComp_RotationOffset: + return "RotationOffset"; + case TransformationComp_RotationPivot: + return "RotationPivot"; + case TransformationComp_PreRotation: + return "PreRotation"; + case TransformationComp_Rotation: + return "Rotation"; + case TransformationComp_PostRotation: + return "PostRotation"; + case TransformationComp_RotationPivotInverse: + return "RotationPivotInverse"; + case TransformationComp_ScalingOffset: + return "ScalingOffset"; + case TransformationComp_ScalingPivot: + return "ScalingPivot"; + case TransformationComp_Scaling: + return "Scaling"; + case TransformationComp_ScalingPivotInverse: + return "ScalingPivotInverse"; + case TransformationComp_GeometricScaling: + return "GeometricScaling"; + case TransformationComp_GeometricRotation: + return "GeometricRotation"; + case TransformationComp_GeometricTranslation: + return "GeometricTranslation"; + case TransformationComp_GeometricScalingInverse: + return "GeometricScalingInverse"; + case TransformationComp_GeometricRotationInverse: + return "GeometricRotationInverse"; + case TransformationComp_GeometricTranslationInverse: + return "GeometricTranslationInverse"; + case TransformationComp_MAXIMUM: // this is to silence compiler warnings + default: + break; + } + + ai_assert(false); + + return nullptr; +} + +const char *FBXConverter::NameTransformationCompProperty(TransformationComp comp) { + switch (comp) { + case TransformationComp_Translation: + return "Lcl Translation"; + case TransformationComp_RotationOffset: + return "RotationOffset"; + case TransformationComp_RotationPivot: + return "RotationPivot"; + case TransformationComp_PreRotation: + return "PreRotation"; + case TransformationComp_Rotation: + return "Lcl Rotation"; + case TransformationComp_PostRotation: + return "PostRotation"; + case TransformationComp_RotationPivotInverse: + return "RotationPivotInverse"; + case TransformationComp_ScalingOffset: + return "ScalingOffset"; + case TransformationComp_ScalingPivot: + return "ScalingPivot"; + case TransformationComp_Scaling: + return "Lcl Scaling"; + case TransformationComp_ScalingPivotInverse: + return "ScalingPivotInverse"; + case TransformationComp_GeometricScaling: + return "GeometricScaling"; + case TransformationComp_GeometricRotation: + return "GeometricRotation"; + case TransformationComp_GeometricTranslation: + return "GeometricTranslation"; + case TransformationComp_GeometricScalingInverse: + return "GeometricScalingInverse"; + case TransformationComp_GeometricRotationInverse: + return "GeometricRotationInverse"; + case TransformationComp_GeometricTranslationInverse: + return "GeometricTranslationInverse"; + case TransformationComp_MAXIMUM: // this is to silence compiler warnings + break; + } + + ai_assert(false); + + return nullptr; +} + +aiVector3D FBXConverter::TransformationCompDefaultValue(TransformationComp comp) { + // XXX a neat way to solve the never-ending special cases for scaling + // would be to do everything in log space! + return comp == TransformationComp_Scaling ? aiVector3D(1.f, 1.f, 1.f) : aiVector3D(); +} + +void FBXConverter::GetRotationMatrix(Model::RotOrder mode, const aiVector3D &rotation, aiMatrix4x4 &out) { + if (mode == Model::RotOrder_SphericXYZ) { + FBXImporter::LogError("Unsupported RotationMode: SphericXYZ"); + out = aiMatrix4x4(); + return; + } + + const float angle_epsilon = Math::getEpsilon(); + + out = aiMatrix4x4(); + + bool is_id[3] = { true, true, true }; + + aiMatrix4x4 temp[3]; + if (std::fabs(rotation.z) > angle_epsilon) { + aiMatrix4x4::RotationZ(AI_DEG_TO_RAD(rotation.z), temp[2]); + is_id[2] = false; + } + if (std::fabs(rotation.y) > angle_epsilon) { + aiMatrix4x4::RotationY(AI_DEG_TO_RAD(rotation.y), temp[1]); + is_id[1] = false; + } + if (std::fabs(rotation.x) > angle_epsilon) { + aiMatrix4x4::RotationX(AI_DEG_TO_RAD(rotation.x), temp[0]); + is_id[0] = false; + } + + int order[3] = { -1, -1, -1 }; + + // note: rotation order is inverted since we're left multiplying as is usual in assimp + switch (mode) { + case Model::RotOrder_EulerXYZ: + order[0] = 2; + order[1] = 1; + order[2] = 0; + break; + + case Model::RotOrder_EulerXZY: + order[0] = 1; + order[1] = 2; + order[2] = 0; + break; + + case Model::RotOrder_EulerYZX: + order[0] = 0; + order[1] = 2; + order[2] = 1; + break; + + case Model::RotOrder_EulerYXZ: + order[0] = 2; + order[1] = 0; + order[2] = 1; + break; + + case Model::RotOrder_EulerZXY: + order[0] = 1; + order[1] = 0; + order[2] = 2; + break; + + case Model::RotOrder_EulerZYX: + order[0] = 0; + order[1] = 1; + order[2] = 2; + break; + + default: + ai_assert(false); + break; + } + + ai_assert(order[0] >= 0); + ai_assert(order[0] <= 2); + ai_assert(order[1] >= 0); + ai_assert(order[1] <= 2); + ai_assert(order[2] >= 0); + ai_assert(order[2] <= 2); + + if (!is_id[order[0]]) { + out = temp[order[0]]; + } + + if (!is_id[order[1]]) { + out = out * temp[order[1]]; + } + + if (!is_id[order[2]]) { + out = out * temp[order[2]]; + } +} + +bool FBXConverter::NeedsComplexTransformationChain(const Model &model) { + const PropertyTable &props = model.Props(); + bool ok; + + const float zero_epsilon = 1e-6f; + const aiVector3D all_ones(1.0f, 1.0f, 1.0f); + for (size_t i = 0; i < TransformationComp_MAXIMUM; ++i) { + const TransformationComp comp = static_cast(i); + + if (comp == TransformationComp_Rotation || comp == TransformationComp_Scaling || comp == TransformationComp_Translation) { + continue; + } + + bool scale_compare = (comp == TransformationComp_GeometricScaling || comp == TransformationComp_Scaling); + + const aiVector3D &v = PropertyGet(props, NameTransformationCompProperty(comp), ok); + if (ok && scale_compare) { + if ((v - all_ones).SquareLength() > zero_epsilon) { + return true; + } + } else if (ok) { + if (v.SquareLength() > zero_epsilon) { + return true; + } + } + } + + return false; +} + +std::string FBXConverter::NameTransformationChainNode(const std::string &name, TransformationComp comp) { + return name + std::string(MAGIC_NODE_TAG) + "_" + NameTransformationComp(comp); +} + +bool FBXConverter::GenerateTransformationNodeChain(const Model &model, const std::string &name, std::vector &output_nodes, + std::vector &post_output_nodes) { + const PropertyTable &props = model.Props(); + const Model::RotOrder rot = model.RotationOrder(); + + bool ok; + + aiMatrix4x4 chain[TransformationComp_MAXIMUM]; + + ai_assert(TransformationComp_MAXIMUM < 32); + std::uint32_t chainBits = 0; + // A node won't need a node chain if it only has these. + const std::uint32_t chainMaskSimple = (1 << TransformationComp_Translation) + (1 << TransformationComp_Scaling) + (1 << TransformationComp_Rotation); + // A node will need a node chain if it has any of these. + const std::uint32_t chainMaskComplex = ((1 << (TransformationComp_MAXIMUM)) - 1) - chainMaskSimple; + + std::fill_n(chain, static_cast(TransformationComp_MAXIMUM), aiMatrix4x4()); + + // generate transformation matrices for all the different transformation components + const float zero_epsilon = Math::getEpsilon(); + const aiVector3D all_ones(1.0f, 1.0f, 1.0f); + + const aiVector3D &PreRotation = PropertyGet(props, "PreRotation", ok); + if (ok && PreRotation.SquareLength() > zero_epsilon) { + chainBits = chainBits | (1 << TransformationComp_PreRotation); + + GetRotationMatrix(Model::RotOrder::RotOrder_EulerXYZ, PreRotation, chain[TransformationComp_PreRotation]); + } + + const aiVector3D &PostRotation = PropertyGet(props, "PostRotation", ok); + if (ok && PostRotation.SquareLength() > zero_epsilon) { + chainBits = chainBits | (1 << TransformationComp_PostRotation); + + GetRotationMatrix(Model::RotOrder::RotOrder_EulerXYZ, PostRotation, chain[TransformationComp_PostRotation]); + } + + const aiVector3D &RotationPivot = PropertyGet(props, "RotationPivot", ok); + if (ok && RotationPivot.SquareLength() > zero_epsilon) { + chainBits = chainBits | (1 << TransformationComp_RotationPivot) | (1 << TransformationComp_RotationPivotInverse); + + aiMatrix4x4::Translation(RotationPivot, chain[TransformationComp_RotationPivot]); + aiMatrix4x4::Translation(-RotationPivot, chain[TransformationComp_RotationPivotInverse]); + } + + const aiVector3D &RotationOffset = PropertyGet(props, "RotationOffset", ok); + if (ok && RotationOffset.SquareLength() > zero_epsilon) { + chainBits = chainBits | (1 << TransformationComp_RotationOffset); + + aiMatrix4x4::Translation(RotationOffset, chain[TransformationComp_RotationOffset]); + } + + const aiVector3D &ScalingOffset = PropertyGet(props, "ScalingOffset", ok); + if (ok && ScalingOffset.SquareLength() > zero_epsilon) { + chainBits = chainBits | (1 << TransformationComp_ScalingOffset); + + aiMatrix4x4::Translation(ScalingOffset, chain[TransformationComp_ScalingOffset]); + } + + const aiVector3D &ScalingPivot = PropertyGet(props, "ScalingPivot", ok); + if (ok && ScalingPivot.SquareLength() > zero_epsilon) { + chainBits = chainBits | (1 << TransformationComp_ScalingPivot) | (1 << TransformationComp_ScalingPivotInverse); + + aiMatrix4x4::Translation(ScalingPivot, chain[TransformationComp_ScalingPivot]); + aiMatrix4x4::Translation(-ScalingPivot, chain[TransformationComp_ScalingPivotInverse]); + } + + const aiVector3D &Translation = PropertyGet(props, "Lcl Translation", ok); + if (ok && Translation.SquareLength() > zero_epsilon) { + chainBits = chainBits | (1 << TransformationComp_Translation); + + aiMatrix4x4::Translation(Translation, chain[TransformationComp_Translation]); + } + + const aiVector3D &Scaling = PropertyGet(props, "Lcl Scaling", ok); + if (ok && (Scaling - all_ones).SquareLength() > zero_epsilon) { + chainBits = chainBits | (1 << TransformationComp_Scaling); + + aiMatrix4x4::Scaling(Scaling, chain[TransformationComp_Scaling]); + } + + const aiVector3D &Rotation = PropertyGet(props, "Lcl Rotation", ok); + if (ok && Rotation.SquareLength() > zero_epsilon) { + chainBits = chainBits | (1 << TransformationComp_Rotation); + + GetRotationMatrix(rot, Rotation, chain[TransformationComp_Rotation]); + } + + const aiVector3D &GeometricScaling = PropertyGet(props, "GeometricScaling", ok); + if (ok && (GeometricScaling - all_ones).SquareLength() > zero_epsilon) { + chainBits = chainBits | (1 << TransformationComp_GeometricScaling); + aiMatrix4x4::Scaling(GeometricScaling, chain[TransformationComp_GeometricScaling]); + aiVector3D GeometricScalingInverse = GeometricScaling; + bool canscale = true; + for (unsigned int i = 0; i < 3; ++i) { + if (std::fabs(GeometricScalingInverse[i]) > zero_epsilon) { + GeometricScalingInverse[i] = 1.0f / GeometricScaling[i]; + } else { + FBXImporter::LogError("cannot invert geometric scaling matrix with a 0.0 scale component"); + canscale = false; + break; + } + } + if (canscale) { + chainBits = chainBits | (1 << TransformationComp_GeometricScalingInverse); + aiMatrix4x4::Scaling(GeometricScalingInverse, chain[TransformationComp_GeometricScalingInverse]); + } + } + + const aiVector3D &GeometricRotation = PropertyGet(props, "GeometricRotation", ok); + if (ok && GeometricRotation.SquareLength() > zero_epsilon) { + chainBits = chainBits | (1 << TransformationComp_GeometricRotation) | (1 << TransformationComp_GeometricRotationInverse); + GetRotationMatrix(rot, GeometricRotation, chain[TransformationComp_GeometricRotation]); + GetRotationMatrix(rot, GeometricRotation, chain[TransformationComp_GeometricRotationInverse]); + chain[TransformationComp_GeometricRotationInverse].Inverse(); + } + + const aiVector3D &GeometricTranslation = PropertyGet(props, "GeometricTranslation", ok); + if (ok && GeometricTranslation.SquareLength() > zero_epsilon) { + chainBits = chainBits | (1 << TransformationComp_GeometricTranslation) | (1 << TransformationComp_GeometricTranslationInverse); + aiMatrix4x4::Translation(GeometricTranslation, chain[TransformationComp_GeometricTranslation]); + aiMatrix4x4::Translation(-GeometricTranslation, chain[TransformationComp_GeometricTranslationInverse]); + } + + // is_complex needs to be consistent with NeedsComplexTransformationChain() + // or the interplay between this code and the animation converter would + // not be guaranteed. + //ai_assert(NeedsComplexTransformationChain(model) == ((chainBits & chainMaskComplex) != 0)); + + // now, if we have more than just Translation, Scaling and Rotation, + // we need to generate a full node chain to accommodate for assimp's + // lack to express pivots and offsets. + if ((chainBits & chainMaskComplex) && doc.Settings().preservePivots) { + FBXImporter::LogInfo("generating full transformation chain for node: " + name); + + // query the anim_chain_bits dictionary to find out which chain elements + // have associated node animation channels. These can not be dropped + // even if they have identity transform in bind pose. + NodeAnimBitMap::const_iterator it = node_anim_chain_bits.find(name); + const unsigned int anim_chain_bitmask = (it == node_anim_chain_bits.end() ? 0 : (*it).second); + + unsigned int bit = 0x1; + for (size_t i = 0; i < TransformationComp_MAXIMUM; ++i, bit <<= 1) { + const TransformationComp comp = static_cast(i); + + if ((chainBits & bit) == 0 && (anim_chain_bitmask & bit) == 0) { + continue; + } + + if (comp == TransformationComp_PostRotation) { + chain[i] = chain[i].Inverse(); + } + + aiNode *nd = new aiNode(); + nd->mName.Set(NameTransformationChainNode(name, comp)); + nd->mTransformation = chain[i]; + + // geometric inverses go in a post-node chain + if (comp == TransformationComp_GeometricScalingInverse || + comp == TransformationComp_GeometricRotationInverse || + comp == TransformationComp_GeometricTranslationInverse) { + post_output_nodes.push_back(nd); + } else { + output_nodes.push_back(nd); + } + } + + ai_assert(output_nodes.size()); + return true; + } + + // else, we can just multiply the matrices together + aiNode *nd = new aiNode(); + output_nodes.push_back(nd); + + // name passed to the method is already unique + nd->mName.Set(name); + + for (const auto &transform : chain) { + nd->mTransformation = nd->mTransformation * transform; + } + return false; +} + +void FBXConverter::SetupNodeMetadata(const Model &model, aiNode &nd) { + const PropertyTable &props = model.Props(); + DirectPropertyMap unparsedProperties = props.GetUnparsedProperties(); + + // create metadata on node + const std::size_t numStaticMetaData = 2; + aiMetadata *data = aiMetadata::Alloc(static_cast(unparsedProperties.size() + numStaticMetaData)); + nd.mMetaData = data; + int index = 0; + + // find user defined properties (3ds Max) + data->Set(index++, "UserProperties", aiString(PropertyGet(props, "UDP3DSMAX", ""))); + // preserve the info that a node was marked as Null node in the original file. + data->Set(index++, "IsNull", model.IsNull() ? true : false); + + // add unparsed properties to the node's metadata + for (const DirectPropertyMap::value_type &prop : unparsedProperties) { + // Interpret the property as a concrete type + if (const TypedProperty *interpretedBool = prop.second->As>()) { + data->Set(index++, prop.first, interpretedBool->Value()); + } else if (const TypedProperty *interpretedInt = prop.second->As>()) { + data->Set(index++, prop.first, interpretedInt->Value()); + } else if (const TypedProperty *interpretedUint64 = prop.second->As>()) { + data->Set(index++, prop.first, interpretedUint64->Value()); + } else if (const TypedProperty *interpretedFloat = prop.second->As>()) { + data->Set(index++, prop.first, interpretedFloat->Value()); + } else if (const TypedProperty *interpretedString = prop.second->As>()) { + data->Set(index++, prop.first, aiString(interpretedString->Value())); + } else if (const TypedProperty *interpretedVec3 = prop.second->As>()) { + data->Set(index++, prop.first, interpretedVec3->Value()); + } else { + ai_assert(false); + } + } +} + +void FBXConverter::ConvertModel(const Model &model, aiNode *parent, aiNode *root_node, + const aiMatrix4x4 &absolute_transform) { + const std::vector &geos = model.GetGeometry(); + + std::vector meshes; + meshes.reserve(geos.size()); + + for (const Geometry *geo : geos) { + + const MeshGeometry *const mesh = dynamic_cast(geo); + const LineGeometry *const line = dynamic_cast(geo); + if (mesh) { + const std::vector &indices = ConvertMesh(*mesh, model, parent, root_node, + absolute_transform); + std::copy(indices.begin(), indices.end(), std::back_inserter(meshes)); + } else if (line) { + const std::vector &indices = ConvertLine(*line, root_node); + std::copy(indices.begin(), indices.end(), std::back_inserter(meshes)); + } else { + FBXImporter::LogWarn("ignoring unrecognized geometry: " + geo->Name()); + } + } + + if (meshes.size()) { + parent->mMeshes = new unsigned int[meshes.size()](); + parent->mNumMeshes = static_cast(meshes.size()); + + std::swap_ranges(meshes.begin(), meshes.end(), parent->mMeshes); + } +} + +std::vector +FBXConverter::ConvertMesh(const MeshGeometry &mesh, const Model &model, aiNode *parent, aiNode *root_node, + const aiMatrix4x4 &absolute_transform) { + std::vector temp; + + MeshMap::const_iterator it = meshes_converted.find(&mesh); + if (it != meshes_converted.end()) { + std::copy((*it).second.begin(), (*it).second.end(), std::back_inserter(temp)); + return temp; + } + + const std::vector &vertices = mesh.GetVertices(); + const std::vector &faces = mesh.GetFaceIndexCounts(); + if (vertices.empty() || faces.empty()) { + FBXImporter::LogWarn("ignoring empty geometry: " + mesh.Name()); + return temp; + } + + // one material per mesh maps easily to aiMesh. Multiple material + // meshes need to be split. + const MatIndexArray &mindices = mesh.GetMaterialIndices(); + if (doc.Settings().readMaterials && !mindices.empty()) { + const MatIndexArray::value_type base = mindices[0]; + for (MatIndexArray::value_type index : mindices) { + if (index != base) { + return ConvertMeshMultiMaterial(mesh, model, parent, root_node, absolute_transform); + } + } + } + + // faster code-path, just copy the data + temp.push_back(ConvertMeshSingleMaterial(mesh, model, absolute_transform, parent, root_node)); + return temp; +} + +std::vector FBXConverter::ConvertLine(const LineGeometry &line, aiNode *root_node) { + std::vector temp; + + const std::vector &vertices = line.GetVertices(); + const std::vector &indices = line.GetIndices(); + if (vertices.empty() || indices.empty()) { + FBXImporter::LogWarn("ignoring empty line: " + line.Name()); + return temp; + } + + aiMesh *const out_mesh = SetupEmptyMesh(line, root_node); + out_mesh->mPrimitiveTypes |= aiPrimitiveType_LINE; + + // copy vertices + out_mesh->mNumVertices = static_cast(vertices.size()); + out_mesh->mVertices = new aiVector3D[out_mesh->mNumVertices]; + std::copy(vertices.begin(), vertices.end(), out_mesh->mVertices); + + //Number of line segments (faces) is "Number of Points - Number of Endpoints" + //N.B.: Endpoints in FbxLine are denoted by negative indices. + //If such an Index is encountered, add 1 and multiply by -1 to get the real index. + unsigned int epcount = 0; + for (unsigned i = 0; i < indices.size(); i++) { + if (indices[i] < 0) { + epcount++; + } + } + unsigned int pcount = static_cast(indices.size()); + unsigned int scount = out_mesh->mNumFaces = pcount - epcount; + + aiFace *fac = out_mesh->mFaces = new aiFace[scount](); + for (unsigned int i = 0; i < pcount; ++i) { + if (indices[i] < 0) continue; + aiFace &f = *fac++; + f.mNumIndices = 2; //2 == aiPrimitiveType_LINE + f.mIndices = new unsigned int[2]; + f.mIndices[0] = indices[i]; + int segid = indices[(i + 1 == pcount ? 0 : i + 1)]; //If we have reached he last point, wrap around + f.mIndices[1] = (segid < 0 ? (segid + 1) * -1 : segid); //Convert EndPoint Index to normal Index + } + temp.push_back(static_cast(mMeshes.size() - 1)); + return temp; +} + +aiMesh *FBXConverter::SetupEmptyMesh(const Geometry &mesh, aiNode *parent) { + aiMesh *const out_mesh = new aiMesh(); + mMeshes.push_back(out_mesh); + meshes_converted[&mesh].push_back(static_cast(mMeshes.size() - 1)); + + // set name + std::string name = mesh.Name(); + if (name.substr(0, 10) == "Geometry::") { + name = name.substr(10); + } + + if (name.length()) { + out_mesh->mName.Set(name); + } else { + out_mesh->mName = parent->mName; + } + + return out_mesh; +} + +unsigned int FBXConverter::ConvertMeshSingleMaterial(const MeshGeometry &mesh, const Model &model, + const aiMatrix4x4 &absolute_transform, aiNode *parent, + aiNode *) { + const MatIndexArray &mindices = mesh.GetMaterialIndices(); + aiMesh *const out_mesh = SetupEmptyMesh(mesh, parent); + + const std::vector &vertices = mesh.GetVertices(); + const std::vector &faces = mesh.GetFaceIndexCounts(); + + // copy vertices + out_mesh->mNumVertices = static_cast(vertices.size()); + out_mesh->mVertices = new aiVector3D[vertices.size()]; + + std::copy(vertices.begin(), vertices.end(), out_mesh->mVertices); + + // generate dummy faces + out_mesh->mNumFaces = static_cast(faces.size()); + aiFace *fac = out_mesh->mFaces = new aiFace[faces.size()](); + + unsigned int cursor = 0; + for (unsigned int pcount : faces) { + aiFace &f = *fac++; + f.mNumIndices = pcount; + f.mIndices = new unsigned int[pcount]; + switch (pcount) { + case 1: + out_mesh->mPrimitiveTypes |= aiPrimitiveType_POINT; + break; + case 2: + out_mesh->mPrimitiveTypes |= aiPrimitiveType_LINE; + break; + case 3: + out_mesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE; + break; + default: + out_mesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON; + break; + } + for (unsigned int i = 0; i < pcount; ++i) { + f.mIndices[i] = cursor++; + } + } + + // copy normals + const std::vector &normals = mesh.GetNormals(); + if (normals.size()) { + ai_assert(normals.size() == vertices.size()); + + out_mesh->mNormals = new aiVector3D[vertices.size()]; + std::copy(normals.begin(), normals.end(), out_mesh->mNormals); + } + + // copy tangents - assimp requires both tangents and bitangents (binormals) + // to be present, or neither of them. Compute binormals from normals + // and tangents if needed. + const std::vector &tangents = mesh.GetTangents(); + const std::vector *binormals = &mesh.GetBinormals(); + + if (tangents.size()) { + std::vector tempBinormals; + if (!binormals->size()) { + if (normals.size()) { + tempBinormals.resize(normals.size()); + for (unsigned int i = 0; i < tangents.size(); ++i) { + tempBinormals[i] = normals[i] ^ tangents[i]; + } + + binormals = &tempBinormals; + } else { + binormals = nullptr; + } + } + + if (binormals) { + ai_assert(tangents.size() == vertices.size()); + ai_assert(binormals->size() == vertices.size()); + + out_mesh->mTangents = new aiVector3D[vertices.size()]; + std::copy(tangents.begin(), tangents.end(), out_mesh->mTangents); + + out_mesh->mBitangents = new aiVector3D[vertices.size()]; + std::copy(binormals->begin(), binormals->end(), out_mesh->mBitangents); + } + } + + // copy texture coords + for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) { + const std::vector &uvs = mesh.GetTextureCoords(i); + if (uvs.empty()) { + break; + } + + aiVector3D *out_uv = out_mesh->mTextureCoords[i] = new aiVector3D[vertices.size()]; + for (const aiVector2D &v : uvs) { + *out_uv++ = aiVector3D(v.x, v.y, 0.0f); + } + + out_mesh->mNumUVComponents[i] = 2; + } + + // copy vertex colors + for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_COLOR_SETS; ++i) { + const std::vector &colors = mesh.GetVertexColors(i); + if (colors.empty()) { + break; + } + + out_mesh->mColors[i] = new aiColor4D[vertices.size()]; + std::copy(colors.begin(), colors.end(), out_mesh->mColors[i]); + } + + if (!doc.Settings().readMaterials || mindices.empty()) { + FBXImporter::LogError("no material assigned to mesh, setting default material"); + out_mesh->mMaterialIndex = GetDefaultMaterial(); + } else { + ConvertMaterialForMesh(out_mesh, model, mesh, mindices[0]); + } + + if (doc.Settings().readWeights && mesh.DeformerSkin() != nullptr) { + ConvertWeights(out_mesh, mesh, absolute_transform, parent, NO_MATERIAL_SEPARATION, nullptr); + } + + std::vector animMeshes; + for (const BlendShape *blendShape : mesh.GetBlendShapes()) { + for (const BlendShapeChannel *blendShapeChannel : blendShape->BlendShapeChannels()) { + const std::vector &shapeGeometries = blendShapeChannel->GetShapeGeometries(); + for (size_t i = 0; i < shapeGeometries.size(); i++) { + aiAnimMesh *animMesh = aiCreateAnimMesh(out_mesh); + const ShapeGeometry *shapeGeometry = shapeGeometries.at(i); + const std::vector &curVertices = shapeGeometry->GetVertices(); + const std::vector &curNormals = shapeGeometry->GetNormals(); + const std::vector &curIndices = shapeGeometry->GetIndices(); + animMesh->mName.Set(FixAnimMeshName(shapeGeometry->Name())); + for (size_t j = 0; j < curIndices.size(); j++) { + const unsigned int curIndex = curIndices.at(j); + aiVector3D vertex = curVertices.at(j); + aiVector3D normal = curNormals.at(j); + unsigned int count = 0; + const unsigned int *outIndices = mesh.ToOutputVertexIndex(curIndex, count); + for (unsigned int k = 0; k < count; k++) { + unsigned int index = outIndices[k]; + animMesh->mVertices[index] += vertex; + if (animMesh->mNormals != nullptr) { + animMesh->mNormals[index] += normal; + animMesh->mNormals[index].NormalizeSafe(); + } + } + } + animMesh->mWeight = shapeGeometries.size() > 1 ? blendShapeChannel->DeformPercent() / 100.0f : 1.0f; + animMeshes.push_back(animMesh); + } + } + } + const size_t numAnimMeshes = animMeshes.size(); + if (numAnimMeshes > 0) { + out_mesh->mNumAnimMeshes = static_cast(numAnimMeshes); + out_mesh->mAnimMeshes = new aiAnimMesh *[numAnimMeshes]; + for (size_t i = 0; i < numAnimMeshes; i++) { + out_mesh->mAnimMeshes[i] = animMeshes.at(i); + } + } + return static_cast(mMeshes.size() - 1); +} + +std::vector +FBXConverter::ConvertMeshMultiMaterial(const MeshGeometry &mesh, const Model &model, aiNode *parent, + aiNode *root_node, + const aiMatrix4x4 &absolute_transform) { + const MatIndexArray &mindices = mesh.GetMaterialIndices(); + ai_assert(mindices.size()); + + std::set had; + std::vector indices; + + for (MatIndexArray::value_type index : mindices) { + if (had.find(index) == had.end()) { + + indices.push_back(ConvertMeshMultiMaterial(mesh, model, index, parent, root_node, absolute_transform)); + had.insert(index); + } + } + + return indices; +} + +unsigned int FBXConverter::ConvertMeshMultiMaterial(const MeshGeometry &mesh, const Model &model, + MatIndexArray::value_type index, + aiNode *parent, aiNode *, + const aiMatrix4x4 &absolute_transform) { + aiMesh *const out_mesh = SetupEmptyMesh(mesh, parent); + + const MatIndexArray &mindices = mesh.GetMaterialIndices(); + const std::vector &vertices = mesh.GetVertices(); + const std::vector &faces = mesh.GetFaceIndexCounts(); + + const bool process_weights = doc.Settings().readWeights && mesh.DeformerSkin() != nullptr; + + unsigned int count_faces = 0; + unsigned int count_vertices = 0; + + // count faces + std::vector::const_iterator itf = faces.begin(); + for (MatIndexArray::const_iterator it = mindices.begin(), + end = mindices.end(); + it != end; ++it, ++itf) { + if ((*it) != index) { + continue; + } + ++count_faces; + count_vertices += *itf; + } + + ai_assert(count_faces); + ai_assert(count_vertices); + + // mapping from output indices to DOM indexing, needed to resolve weights or blendshapes + std::vector reverseMapping; + std::map translateIndexMap; + if (process_weights || mesh.GetBlendShapes().size() > 0) { + reverseMapping.resize(count_vertices); + } + + // allocate output data arrays, but don't fill them yet + out_mesh->mNumVertices = count_vertices; + out_mesh->mVertices = new aiVector3D[count_vertices]; + + out_mesh->mNumFaces = count_faces; + aiFace *fac = out_mesh->mFaces = new aiFace[count_faces](); + + // allocate normals + const std::vector &normals = mesh.GetNormals(); + if (normals.size()) { + ai_assert(normals.size() == vertices.size()); + out_mesh->mNormals = new aiVector3D[vertices.size()]; + } + + // allocate tangents, binormals. + const std::vector &tangents = mesh.GetTangents(); + const std::vector *binormals = &mesh.GetBinormals(); + std::vector tempBinormals; + + if (tangents.size()) { + if (!binormals->size()) { + if (normals.size()) { + // XXX this computes the binormals for the entire mesh, not only + // the part for which we need them. + tempBinormals.resize(normals.size()); + for (unsigned int i = 0; i < tangents.size(); ++i) { + tempBinormals[i] = normals[i] ^ tangents[i]; + } + + binormals = &tempBinormals; + } else { + binormals = nullptr; + } + } + + if (binormals) { + ai_assert(tangents.size() == vertices.size() && binormals->size() == vertices.size()); + + out_mesh->mTangents = new aiVector3D[vertices.size()]; + out_mesh->mBitangents = new aiVector3D[vertices.size()]; + } + } + + // allocate texture coords + unsigned int num_uvs = 0; + for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i, ++num_uvs) { + const std::vector &uvs = mesh.GetTextureCoords(i); + if (uvs.empty()) { + break; + } + + out_mesh->mTextureCoords[i] = new aiVector3D[vertices.size()]; + out_mesh->mNumUVComponents[i] = 2; + } + + // allocate vertex colors + unsigned int num_vcs = 0; + for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_COLOR_SETS; ++i, ++num_vcs) { + const std::vector &colors = mesh.GetVertexColors(i); + if (colors.empty()) { + break; + } + + out_mesh->mColors[i] = new aiColor4D[vertices.size()]; + } + + unsigned int cursor = 0, in_cursor = 0; + + itf = faces.begin(); + for (MatIndexArray::const_iterator it = mindices.begin(), end = mindices.end(); it != end; ++it, ++itf) { + const unsigned int pcount = *itf; + if ((*it) != index) { + in_cursor += pcount; + continue; + } + + aiFace &f = *fac++; + + f.mNumIndices = pcount; + f.mIndices = new unsigned int[pcount]; + switch (pcount) { + case 1: + out_mesh->mPrimitiveTypes |= aiPrimitiveType_POINT; + break; + case 2: + out_mesh->mPrimitiveTypes |= aiPrimitiveType_LINE; + break; + case 3: + out_mesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE; + break; + default: + out_mesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON; + break; + } + for (unsigned int i = 0; i < pcount; ++i, ++cursor, ++in_cursor) { + f.mIndices[i] = cursor; + + if (reverseMapping.size()) { + reverseMapping[cursor] = in_cursor; + translateIndexMap[in_cursor] = cursor; + } + + out_mesh->mVertices[cursor] = vertices[in_cursor]; + + if (out_mesh->mNormals) { + out_mesh->mNormals[cursor] = normals[in_cursor]; + } + + if (out_mesh->mTangents) { + out_mesh->mTangents[cursor] = tangents[in_cursor]; + out_mesh->mBitangents[cursor] = (*binormals)[in_cursor]; + } + + for (unsigned int j = 0; j < num_uvs; ++j) { + const std::vector &uvs = mesh.GetTextureCoords(j); + out_mesh->mTextureCoords[j][cursor] = aiVector3D(uvs[in_cursor].x, uvs[in_cursor].y, 0.0f); + } + + for (unsigned int j = 0; j < num_vcs; ++j) { + const std::vector &cols = mesh.GetVertexColors(j); + out_mesh->mColors[j][cursor] = cols[in_cursor]; + } + } + } + + ConvertMaterialForMesh(out_mesh, model, mesh, index); + + if (process_weights) { + ConvertWeights(out_mesh, mesh, absolute_transform, parent, index, &reverseMapping); + } + + std::vector animMeshes; + for (const BlendShape *blendShape : mesh.GetBlendShapes()) { + for (const BlendShapeChannel *blendShapeChannel : blendShape->BlendShapeChannels()) { + const std::vector &shapeGeometries = blendShapeChannel->GetShapeGeometries(); + for (size_t i = 0; i < shapeGeometries.size(); i++) { + aiAnimMesh *animMesh = aiCreateAnimMesh(out_mesh); + const ShapeGeometry *shapeGeometry = shapeGeometries.at(i); + const std::vector &curVertices = shapeGeometry->GetVertices(); + const std::vector &curNormals = shapeGeometry->GetNormals(); + const std::vector &curIndices = shapeGeometry->GetIndices(); + animMesh->mName.Set(FixAnimMeshName(shapeGeometry->Name())); + for (size_t j = 0; j < curIndices.size(); j++) { + unsigned int curIndex = curIndices.at(j); + aiVector3D vertex = curVertices.at(j); + aiVector3D normal = curNormals.at(j); + unsigned int count = 0; + const unsigned int *outIndices = mesh.ToOutputVertexIndex(curIndex, count); + for (unsigned int k = 0; k < count; k++) { + unsigned int outIndex = outIndices[k]; + if (translateIndexMap.find(outIndex) == translateIndexMap.end()) + continue; + unsigned int transIndex = translateIndexMap[outIndex]; + animMesh->mVertices[transIndex] += vertex; + if (animMesh->mNormals != nullptr) { + animMesh->mNormals[transIndex] += normal; + animMesh->mNormals[transIndex].NormalizeSafe(); + } + } + } + animMesh->mWeight = shapeGeometries.size() > 1 ? blendShapeChannel->DeformPercent() / 100.0f : 1.0f; + animMeshes.push_back(animMesh); + } + } + } + + const size_t numAnimMeshes = animMeshes.size(); + if (numAnimMeshes > 0) { + out_mesh->mNumAnimMeshes = static_cast(numAnimMeshes); + out_mesh->mAnimMeshes = new aiAnimMesh *[numAnimMeshes]; + for (size_t i = 0; i < numAnimMeshes; i++) { + out_mesh->mAnimMeshes[i] = animMeshes.at(i); + } + } + + return static_cast(mMeshes.size() - 1); +} + +void FBXConverter::ConvertWeights(aiMesh *out, const MeshGeometry &geo, + const aiMatrix4x4 &absolute_transform, + aiNode *parent, unsigned int materialIndex, + std::vector *outputVertStartIndices) { + ai_assert(geo.DeformerSkin()); + + std::vector out_indices; + std::vector index_out_indices; + std::vector count_out_indices; + + const Skin &sk = *geo.DeformerSkin(); + + std::vector bones; + + const bool no_mat_check = materialIndex == NO_MATERIAL_SEPARATION; + ai_assert(no_mat_check || outputVertStartIndices); + + try { + // iterate over the sub deformers + for (const Cluster *cluster : sk.Clusters()) { + ai_assert(cluster); + + const WeightIndexArray &indices = cluster->GetIndices(); + + const MatIndexArray &mats = geo.GetMaterialIndices(); + + const size_t no_index_sentinel = std::numeric_limits::max(); + + count_out_indices.clear(); + index_out_indices.clear(); + out_indices.clear(); + + // now check if *any* of these weights is contained in the output mesh, + // taking notes so we don't need to do it twice. + for (WeightIndexArray::value_type index : indices) { + + unsigned int count = 0; + const unsigned int *const out_idx = geo.ToOutputVertexIndex(index, count); + // ToOutputVertexIndex only returns nullptr if index is out of bounds + // which should never happen + ai_assert(out_idx != nullptr); + + index_out_indices.push_back(no_index_sentinel); + count_out_indices.push_back(0); + + for (unsigned int i = 0; i < count; ++i) { + if (no_mat_check || static_cast(mats[geo.FaceForVertexIndex(out_idx[i])]) == materialIndex) { + + if (index_out_indices.back() == no_index_sentinel) { + index_out_indices.back() = out_indices.size(); + } + + if (no_mat_check) { + out_indices.push_back(out_idx[i]); + } else { + // this extra lookup is in O(logn), so the entire algorithm becomes O(nlogn) + const std::vector::iterator it = std::lower_bound( + outputVertStartIndices->begin(), + outputVertStartIndices->end(), + out_idx[i]); + + out_indices.push_back(std::distance(outputVertStartIndices->begin(), it)); + } + + ++count_out_indices.back(); + } + } + } + + // if we found at least one, generate the output bones + // XXX this could be heavily simplified by collecting the bone + // data in a single step. + ConvertCluster(bones, cluster, out_indices, index_out_indices, + count_out_indices, absolute_transform, parent); + } + + bone_map.clear(); + } catch (std::exception &) { + std::for_each(bones.begin(), bones.end(), Util::delete_fun()); + throw; + } + + if (bones.empty()) { + out->mBones = nullptr; + out->mNumBones = 0; + return; + } else { + out->mBones = new aiBone *[bones.size()](); + out->mNumBones = static_cast(bones.size()); + + std::swap_ranges(bones.begin(), bones.end(), out->mBones); + } +} + +const aiNode *GetNodeByName(aiNode *current_node) { + aiNode *iter = current_node; + //printf("Child count: %d", iter->mNumChildren); + return iter; +} + +void FBXConverter::ConvertCluster(std::vector &local_mesh_bones, const Cluster *cl, + std::vector &out_indices, std::vector &index_out_indices, + std::vector &count_out_indices, const aiMatrix4x4 &absolute_transform, + aiNode *) { + ai_assert(cl); // make sure cluster valid + std::string deformer_name = cl->TargetNode()->Name(); + aiString bone_name = aiString(FixNodeName(deformer_name)); + + aiBone *bone = nullptr; + + if (bone_map.count(deformer_name)) { + ASSIMP_LOG_DEBUG_F("retrieved bone from lookup ", bone_name.C_Str(), ". Deformer:", deformer_name); + bone = bone_map[deformer_name]; + } else { + ASSIMP_LOG_DEBUG_F("created new bone ", bone_name.C_Str(), ". Deformer: ", deformer_name); + bone = new aiBone(); + bone->mName = bone_name; + + // store local transform link for post processing + bone->mOffsetMatrix = cl->TransformLink(); + bone->mOffsetMatrix.Inverse(); + + aiMatrix4x4 matrix = (aiMatrix4x4)absolute_transform; + + bone->mOffsetMatrix = bone->mOffsetMatrix * matrix; // * mesh_offset + + // + // Now calculate the aiVertexWeights + // + + aiVertexWeight *cursor = nullptr; + + bone->mNumWeights = static_cast(out_indices.size()); + cursor = bone->mWeights = new aiVertexWeight[out_indices.size()]; + + const size_t no_index_sentinel = std::numeric_limits::max(); + const WeightArray &weights = cl->GetWeights(); + + const size_t c = index_out_indices.size(); + for (size_t i = 0; i < c; ++i) { + const size_t index_index = index_out_indices[i]; + + if (index_index == no_index_sentinel) { + continue; + } + + const size_t cc = count_out_indices[i]; + for (size_t j = 0; j < cc; ++j) { + // cursor runs from first element relative to the start + // or relative to the start of the next indexes. + aiVertexWeight &out_weight = *cursor++; + + out_weight.mVertexId = static_cast(out_indices[index_index + j]); + out_weight.mWeight = weights[i]; + } + } + + bone_map.insert(std::pair(deformer_name, bone)); + } + + ASSIMP_LOG_DEBUG_F("bone research: Indicies size: ", out_indices.size()); + + // lookup must be populated in case something goes wrong + // this also allocates bones to mesh instance outside + local_mesh_bones.push_back(bone); +} + +void FBXConverter::ConvertMaterialForMesh(aiMesh *out, const Model &model, const MeshGeometry &geo, + MatIndexArray::value_type materialIndex) { + // locate source materials for this mesh + const std::vector &mats = model.GetMaterials(); + if (static_cast(materialIndex) >= mats.size() || materialIndex < 0) { + FBXImporter::LogError("material index out of bounds, setting default material"); + out->mMaterialIndex = GetDefaultMaterial(); + return; + } + + const Material *const mat = mats[materialIndex]; + MaterialMap::const_iterator it = materials_converted.find(mat); + if (it != materials_converted.end()) { + out->mMaterialIndex = (*it).second; + return; + } + + out->mMaterialIndex = ConvertMaterial(*mat, &geo); + materials_converted[mat] = out->mMaterialIndex; +} + +unsigned int FBXConverter::GetDefaultMaterial() { + if (defaultMaterialIndex) { + return defaultMaterialIndex - 1; + } + + aiMaterial *out_mat = new aiMaterial(); + materials.push_back(out_mat); + + const aiColor3D diffuse = aiColor3D(0.8f, 0.8f, 0.8f); + out_mat->AddProperty(&diffuse, 1, AI_MATKEY_COLOR_DIFFUSE); + + aiString s; + s.Set(AI_DEFAULT_MATERIAL_NAME); + + out_mat->AddProperty(&s, AI_MATKEY_NAME); + + defaultMaterialIndex = static_cast(materials.size()); + return defaultMaterialIndex - 1; +} + +unsigned int FBXConverter::ConvertMaterial(const Material &material, const MeshGeometry *const mesh) { + const PropertyTable &props = material.Props(); + + // generate empty output material + aiMaterial *out_mat = new aiMaterial(); + materials_converted[&material] = static_cast(materials.size()); + + materials.push_back(out_mat); + + aiString str; + + // strip Material:: prefix + std::string name = material.Name(); + if (name.substr(0, 10) == "Material::") { + name = name.substr(10); + } + + // set material name if not empty - this could happen + // and there should be no key for it in this case. + if (name.length()) { + str.Set(name); + out_mat->AddProperty(&str, AI_MATKEY_NAME); + } + + // Set the shading mode as best we can: The FBX specification only mentions Lambert and Phong, and only Phong is mentioned in Assimp's aiShadingMode enum. + if (material.GetShadingModel() == "phong") { + aiShadingMode shadingMode = aiShadingMode_Phong; + out_mat->AddProperty(&shadingMode, 1, AI_MATKEY_SHADING_MODEL); + } + + // shading stuff and colors + SetShadingPropertiesCommon(out_mat, props); + SetShadingPropertiesRaw(out_mat, props, material.Textures(), mesh); + + // texture assignments + SetTextureProperties(out_mat, material.Textures(), mesh); + SetTextureProperties(out_mat, material.LayeredTextures(), mesh); + + return static_cast(materials.size() - 1); +} + +unsigned int FBXConverter::ConvertVideo(const Video &video) { + // generate empty output texture + aiTexture *out_tex = new aiTexture(); + textures.push_back(out_tex); + + // assuming the texture is compressed + out_tex->mWidth = static_cast(video.ContentLength()); // total data size + out_tex->mHeight = 0; // fixed to 0 + + // steal the data from the Video to avoid an additional copy + out_tex->pcData = reinterpret_cast(const_cast