From 693aa5c1d60a25efa1550fe4d2a34ac22b233bd9 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Fri, 14 Feb 2020 20:50:17 +0100 Subject: [PATCH 01/51] 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 02/51] 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 03/51] 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 c2bfbdacf4d9f4560fd769af8a8c2beffc4820ec Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sun, 16 Feb 2020 15:37:20 +0100 Subject: [PATCH 04/51] 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 6e13381bdb7029d263b480d70dacdf1c92a43317 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 18 Feb 2020 14:41:19 +0100 Subject: [PATCH 05/51] 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 920535165da40288f5603dded29404018f09d90c Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sun, 1 Mar 2020 13:15:45 +0100 Subject: [PATCH 06/51] 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 e8d2b840178b2b22336eb02b2535f32f3d5cc37b Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sun, 8 Mar 2020 21:24:01 +0100 Subject: [PATCH 07/51] 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