From b28bcc365c1ca1063c5df4f906f73dfb49603477 Mon Sep 17 00:00:00 2001 From: Rohan Singh Date: Wed, 24 Jan 2018 09:45:20 -0500 Subject: [PATCH 01/22] Interpret IndexAToDirect as Direct when the index element is missing Paint3D exports FBX like this, which is wrong, but could still support it --- code/FBXMeshGeometry.cpp | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/code/FBXMeshGeometry.cpp b/code/FBXMeshGeometry.cpp index 4868b3e72..99e1b1c5f 100644 --- a/code/FBXMeshGeometry.cpp +++ b/code/FBXMeshGeometry.cpp @@ -427,16 +427,19 @@ void ResolveVertexDataArray(std::vector& data_out, const Scope& source, const std::vector& mapping_offsets, const std::vector& mappings) { + bool isDirect = ReferenceInformationType == "Direct"; + bool isIndexToDirect = ReferenceInformationType == "IndexToDirect"; + // fallback to direct data if there is no index data element + if ( isIndexToDirect && !HasElement( source, indexDataElementName ) ) { + isDirect = true; + isIndexToDirect = false; + } // handle permutations of Mapping and Reference type - it would be nice to // deal with this more elegantly and with less redundancy, but right // now it seems unavoidable. - if (MappingInformationType == "ByVertice" && ReferenceInformationType == "Direct") { - if ( !HasElement( source, indexDataElementName ) ) { - return; - } - + if (MappingInformationType == "ByVertice" && isDirect) { std::vector tempData; ParseVectorDataArray(tempData, GetRequiredElement(source, dataElementName)); @@ -449,14 +452,11 @@ void ResolveVertexDataArray(std::vector& data_out, const Scope& source, } } } - else if (MappingInformationType == "ByVertice" && ReferenceInformationType == "IndexToDirect") { + else if (MappingInformationType == "ByVertice" && isIndexToDirect) { std::vector tempData; ParseVectorDataArray(tempData, GetRequiredElement(source, dataElementName)); data_out.resize(vertex_count); - if ( !HasElement( source, indexDataElementName ) ) { - return; - } std::vector uvIndices; ParseVectorDataArray(uvIndices,GetRequiredElement(source,indexDataElementName)); @@ -471,7 +471,7 @@ void ResolveVertexDataArray(std::vector& data_out, const Scope& source, } } } - else if (MappingInformationType == "ByPolygonVertex" && ReferenceInformationType == "Direct") { + else if (MappingInformationType == "ByPolygonVertex" && isDirect) { std::vector tempData; ParseVectorDataArray(tempData, GetRequiredElement(source, dataElementName)); @@ -484,7 +484,7 @@ void ResolveVertexDataArray(std::vector& data_out, const Scope& source, data_out.swap(tempData); } - else if (MappingInformationType == "ByPolygonVertex" && ReferenceInformationType == "IndexToDirect") { + else if (MappingInformationType == "ByPolygonVertex" && isIndexToDirect) { std::vector tempData; ParseVectorDataArray(tempData, GetRequiredElement(source, dataElementName)); From 4736160b793ed86840cb07c156a469516c1c92b4 Mon Sep 17 00:00:00 2001 From: Giuseppe Barbieri Date: Tue, 6 Feb 2018 22:36:37 +0100 Subject: [PATCH 02/22] Update BlenderDNA.h --- code/BlenderDNA.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/BlenderDNA.h b/code/BlenderDNA.h index 932784e9f..43c9d2d82 100644 --- a/code/BlenderDNA.h +++ b/code/BlenderDNA.h @@ -204,7 +204,7 @@ enum ErrorPolicy { // ------------------------------------------------------------------------------- /** Represents a data structure in a BLEND file. A Structure defines n fields - * and their locatios and encodings the input stream. Usually, every + * and their locations and encodings the input stream. Usually, every * Structure instance pertains to one equally-named data structure in the * BlenderScene.h header. This class defines various utilities to map a * binary `blob` read from the file to such a structure instance with From f00d450d254d5ba56fdad4bf004127847ee6b551 Mon Sep 17 00:00:00 2001 From: Giuseppe Barbieri Date: Sun, 11 Feb 2018 17:43:49 +0100 Subject: [PATCH 03/22] Update BlenderDNA.inl --- code/BlenderDNA.inl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/BlenderDNA.inl b/code/BlenderDNA.inl index de85815cc..c6a3779b1 100644 --- a/code/BlenderDNA.inl +++ b/code/BlenderDNA.inl @@ -501,7 +501,7 @@ const FileBlockHead* Structure :: LocateFileBlockForAddress(const Pointer & ptrv { // the file blocks appear in list sorted by // with ascending base addresses so we can run a - // binary search to locate the pointee quickly. + // binary search to locate the pointer quickly. // NOTE: Blender seems to distinguish between side-by-side // data (stored in the same data block) and far pointers, From 12999050262d8a6213cf6b1f136a11fa80f57066 Mon Sep 17 00:00:00 2001 From: mbuchner Date: Mon, 12 Feb 2018 11:20:03 +0100 Subject: [PATCH 04/22] Make FileSystemFilter forward all virtual functions to wrapped IOSystem instance This makes it possible to override those functions. Previously the default implementation was always used. Fixes #1773 --- code/FileSystemFilter.h | 49 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/code/FileSystemFilter.h b/code/FileSystemFilter.h index 0fabb41dd..10b18bd78 100644 --- a/code/FileSystemFilter.h +++ b/code/FileSystemFilter.h @@ -168,6 +168,55 @@ public: return wrapped->ComparePaths (one,second); } + // ------------------------------------------------------------------- + /** Pushes a new directory onto the directory stack. */ + bool PushDirectory(const std::string &path) + { + return wrapped->PushDirectory(path); + } + + // ------------------------------------------------------------------- + /** Returns the top directory from the stack. */ + const std::string &CurrentDirectory() const + { + return wrapped->CurrentDirectory(); + } + + // ------------------------------------------------------------------- + /** Returns the number of directories stored on the stack. */ + size_t StackSize() const + { + return wrapped->StackSize(); + } + + // ------------------------------------------------------------------- + /** Pops the top directory from the stack. */ + bool PopDirectory() + { + return wrapped->PopDirectory(); + } + + // ------------------------------------------------------------------- + /** Creates an new directory at the given path. */ + bool CreateDirectory(const std::string &path) + { + return wrapped->CreateDirectory(path); + } + + // ------------------------------------------------------------------- + /** Will change the current directory to the given path. */ + bool ChangeDirectory(const std::string &path) + { + return wrapped->ChangeDirectory(path); + } + + // ------------------------------------------------------------------- + /** Delete file. */ + bool DeleteFile(const std::string &file) + { + return wrapped->DeleteFile(file); + } + private: // ------------------------------------------------------------------- From 8a4fd2f9477b6d624f9f94f2f1367c84e81e5a5d Mon Sep 17 00:00:00 2001 From: Sergio Acereda Date: Mon, 12 Feb 2018 21:51:40 +0100 Subject: [PATCH 05/22] globalScale process not registered --- code/PostStepRegistry.cpp | 9 +++++++-- code/ScaleProcess.cpp | 4 ++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/code/PostStepRegistry.cpp b/code/PostStepRegistry.cpp index 49f5d7375..2a5e211c1 100644 --- a/code/PostStepRegistry.cpp +++ b/code/PostStepRegistry.cpp @@ -125,6 +125,9 @@ corresponding preprocessor flag to selectively disable steps. #ifndef ASSIMP_BUILD_NO_DEBONE_PROCESS # include "DeboneProcess.h" #endif +#if (!defined ASSIMP_BUILD_NO_GLOBALSCALE_PROCESS) +# include "ScaleProcess.h" +#endif namespace Assimp { @@ -136,7 +139,7 @@ void GetPostProcessingStepInstanceList(std::vector< BaseProcess* >& out) // of sequence it is executed. Steps that are added here are not // validated - as RegisterPPStep() does - all dependencies must be given. // ---------------------------------------------------------------------------- - out.reserve(30); + out.reserve(31); #if (!defined ASSIMP_BUILD_NO_MAKELEFTHANDED_PROCESS) out.push_back( new MakeLeftHandedProcess()); #endif @@ -197,7 +200,9 @@ void GetPostProcessingStepInstanceList(std::vector< BaseProcess* >& out) #if (!defined ASSIMP_BUILD_NO_GENFACENORMALS_PROCESS) out.push_back( new GenFaceNormalsProcess()); #endif - +#if (!defined ASSIMP_BUILD_NO_GLOBALSCALE_PROCESS) + out.push_back( new ScaleProcess()); +#endif // ......................................................................... // DON'T change the order of these five .. // XXX this is actually a design weakness that dates back to the time diff --git a/code/ScaleProcess.cpp b/code/ScaleProcess.cpp index ef7357b68..0f60fbdb4 100644 --- a/code/ScaleProcess.cpp +++ b/code/ScaleProcess.cpp @@ -39,6 +39,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ---------------------------------------------------------------------- */ +#ifndef ASSIMP_BUILD_NO_GLOBALSCALE_PROCESS + #include "ScaleProcess.h" #include @@ -104,3 +106,5 @@ void ScaleProcess::applyScaling( aiNode *currentNode ) { } } // Namespace Assimp + +#endif // !! ASSIMP_BUILD_NO_GLOBALSCALE_PROCESS From 331e67c32d7b1e685c704d552ed08f25bb03e7ba Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Mon, 12 Feb 2018 22:07:12 +0100 Subject: [PATCH 06/22] 3mf: introduce first prototype for basematerial support. --- code/3MFXmlTags.h | 7 ++- code/D3MFImporter.cpp | 137 ++++++++++++++++++++++++++++++------------ 2 files changed, 106 insertions(+), 38 deletions(-) diff --git a/code/3MFXmlTags.h b/code/3MFXmlTags.h index 30aed0e95..20971a38f 100644 --- a/code/3MFXmlTags.h +++ b/code/3MFXmlTags.h @@ -69,6 +69,12 @@ namespace XmlTag { static const std::string objectid = "objectid"; static const std::string transform = "transform"; + // Material definitions + static const std::string basematerials = "basematerials"; + static const std::string basematerials_base = "base"; + static const std::string basematerials_name = "name"; + static const std::string basematerials_displaycolor = "displaycolor"; + static const std::string CONTENT_TYPES_ARCHIVE = "[Content_Types].xml"; static const std::string ROOT_RELATIONSHIPS_ARCHIVE = "_rels/.rels"; static const std::string SCHEMA_CONTENTTYPES = "http://schemas.openxmlformats.org/package/2006/content-types"; @@ -83,7 +89,6 @@ namespace XmlTag { static const std::string PACKAGE_TEXTURE_RELATIONSHIP_TYPE = "http://schemas.microsoft.com/3dmanufacturing/2013/01/3dtexture"; static const std::string PACKAGE_CORE_PROPERTIES_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties"; static const std::string PACKAGE_THUMBNAIL_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail"; - } } // Namespace D3MF diff --git a/code/D3MFImporter.cpp b/code/D3MFImporter.cpp index 0777a55fa..823fae74c 100644 --- a/code/D3MFImporter.cpp +++ b/code/D3MFImporter.cpp @@ -68,7 +68,9 @@ namespace D3MF { class XmlSerializer { public: XmlSerializer(XmlReader* xmlReader) - : xmlReader(xmlReader) { + : xmlReader(xmlReader) + , mMeshes() + , mMaterials() { // empty } @@ -77,6 +79,10 @@ public: } void ImportXml(aiScene* scene) { + if ( nullptr != scene ) { + return; + } + scene->mRootNode = new aiNode(); std::vector children; @@ -84,7 +90,9 @@ public: if(xmlReader->getNodeName() == D3MF::XmlTag::object) { children.push_back(ReadObject(scene)); } else if(xmlReader->getNodeName() == D3MF::XmlTag::build) { - + // + } else if ( xmlReader->getNodeName() == D3MF::XmlTag::basematerials ) { + ReadBaseMaterials(); } } @@ -92,10 +100,10 @@ public: scene->mRootNode->mName.Set( "3MF" ); } - scene->mNumMeshes = static_cast(meshes.size()); + scene->mNumMeshes = static_cast( mMeshes.size()); scene->mMeshes = new aiMesh*[scene->mNumMeshes](); - std::copy(meshes.begin(), meshes.end(), scene->mMeshes); + std::copy( mMeshes.begin(), mMeshes.end(), scene->mMeshes); scene->mRootNode->mNumChildren = static_cast(children.size()); scene->mRootNode->mChildren = new aiNode*[scene->mRootNode->mNumChildren](); @@ -104,8 +112,7 @@ public: } private: - aiNode* ReadObject(aiScene* scene) - { + aiNode* ReadObject(aiScene* scene) { std::unique_ptr node(new aiNode()); std::vector meshIds; @@ -124,19 +131,16 @@ private: node->mParent = scene->mRootNode; node->mName.Set(name); - size_t meshIdx = meshes.size(); + size_t meshIdx = mMeshes.size(); - while(ReadToEndElement(D3MF::XmlTag::object)) - { - if(xmlReader->getNodeName() == D3MF::XmlTag::mesh) - { + while(ReadToEndElement(D3MF::XmlTag::object)) { + if(xmlReader->getNodeName() == D3MF::XmlTag::mesh) { auto mesh = ReadMesh(); mesh->mName.Set(name); - meshes.push_back(mesh); + mMeshes.push_back(mesh); meshIds.push_back(static_cast(meshIdx)); - meshIdx++; - + ++meshIdx; } } @@ -147,19 +151,14 @@ private: std::copy(meshIds.begin(), meshIds.end(), node->mMeshes); return node.release(); - } aiMesh* ReadMesh() { aiMesh* mesh = new aiMesh(); - while(ReadToEndElement(D3MF::XmlTag::mesh)) - { - if(xmlReader->getNodeName() == D3MF::XmlTag::vertices) - { + while(ReadToEndElement(D3MF::XmlTag::mesh)) { + if(xmlReader->getNodeName() == D3MF::XmlTag::vertices) { ImportVertices(mesh); - } - else if(xmlReader->getNodeName() == D3MF::XmlTag::triangles) - { + } else if(xmlReader->getNodeName() == D3MF::XmlTag::triangles) { ImportTriangles(mesh); } } @@ -167,8 +166,7 @@ private: return mesh; } - void ImportVertices(aiMesh* mesh) - { + void ImportVertices(aiMesh* mesh) { std::vector vertices; while(ReadToEndElement(D3MF::XmlTag::vertices)) @@ -182,11 +180,9 @@ private: mesh->mVertices = new aiVector3D[mesh->mNumVertices]; std::copy(vertices.begin(), vertices.end(), mesh->mVertices); - } - aiVector3D ReadVertex() - { + aiVector3D ReadVertex() { aiVector3D vertex; vertex.x = ai_strtof(xmlReader->getAttributeValue(D3MF::XmlTag::x.c_str()), nullptr); @@ -196,15 +192,11 @@ private: return vertex; } - void ImportTriangles(aiMesh* mesh) - { + void ImportTriangles(aiMesh* mesh) { std::vector faces; - - while(ReadToEndElement(D3MF::XmlTag::triangles)) - { - if(xmlReader->getNodeName() == D3MF::XmlTag::triangle) - { + while(ReadToEndElement(D3MF::XmlTag::triangles)) { + if(xmlReader->getNodeName() == D3MF::XmlTag::triangle) { faces.push_back(ReadTriangle()); } } @@ -216,8 +208,7 @@ private: std::copy(faces.begin(), faces.end(), mesh->mFaces); } - aiFace ReadTriangle() - { + aiFace ReadTriangle() { aiFace face; face.mNumIndices = 3; @@ -229,6 +220,77 @@ private: return face; } + void ReadBaseMaterials() { + while ( ReadToEndElement( D3MF::XmlTag::basematerials ) ) { + mMaterials.push_back( readMaterialDef() ); + } + } + + bool parseColor( const char *color, aiColor4D &diffuse ) { + if ( nullptr == color ) { + return false; + } + + const size_t len( strlen( color ) ); + if ( 9 != len ) { + return false; + } + + const char *buf( color ); + if ( '#' != *buf ) { + return false; + } + + char comp[ 2 ] = { 0,0 }; + comp[ 0 ] = *buf; + ++buf; + comp[ 1 ] = *buf; + ++buf; + diffuse.r = static_cast( std::atoi( comp ) ); + + comp[ 0 ] = *buf; + ++buf; + comp[ 1 ] = *buf; + ++buf; + diffuse.g = static_cast( std::atoi( comp ) ); + + comp[ 0 ] = *buf; + ++buf; + comp[ 1 ] = *buf; + ++buf; + diffuse.b = static_cast( std::atoi( comp ) ); + + comp[ 0 ] = *buf; + ++buf; + comp[ 1 ] = *buf; + ++buf; + diffuse.a = static_cast( std::atoi( comp ) ); + + return true; + } + + aiMaterial *readMaterialDef() { + while ( ReadToEndElement( D3MF::XmlTag::basematerials_base ) ) { + const char *name( nullptr ); + const char *color( nullptr ); + if ( xmlReader->getNodeName() == D3MF::XmlTag::basematerials_name ) { + name = xmlReader->getAttributeValue( D3MF::XmlTag::basematerials_name.c_str() ); + + aiString matName; + matName.Set( name ); + aiMaterial *mat = new aiMaterial; + mat->AddProperty( &matName, AI_MATKEY_NAME ); + + color = xmlReader->getAttributeValue( D3MF::XmlTag::basematerials_displaycolor.c_str() ); + aiColor4D diffuse; + if ( parseColor( color, diffuse ) ) { + mat->AddProperty( &diffuse, 1, AI_MATKEY_COLOR_DIFFUSE ); + } + } + } + + } + private: bool ReadToStartElement(const std::string& startTag) { @@ -267,7 +329,8 @@ private: private: - std::vector meshes; + std::vector mMeshes; + std::vector mMaterials; XmlReader* xmlReader; }; From ccbcaa2ee8482c196e6d7cb1a86b6f75d34c8ea0 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 13 Feb 2018 20:36:22 +0100 Subject: [PATCH 07/22] fix some static-analysis findings. --- code/FindInstancesProcess.h | 14 +++++----- code/OpenGEXImporter.cpp | 27 ++++++++++-------- code/SceneCombiner.cpp | 47 ++++++++++++++++---------------- code/SpatialSort.cpp | 2 +- code/VertexTriangleAdjacency.cpp | 15 ++++------ code/VertexTriangleAdjacency.h | 29 ++++++-------------- include/assimp/IOStreamBuffer.h | 4 +-- include/assimp/SGSpatialSort.h | 2 +- 8 files changed, 65 insertions(+), 75 deletions(-) diff --git a/code/FindInstancesProcess.h b/code/FindInstancesProcess.h index 2ef6c1ca7..fb2ac6eb6 100644 --- a/code/FindInstancesProcess.h +++ b/code/FindInstancesProcess.h @@ -60,9 +60,9 @@ namespace Assimp { * @param in Input mesh * @return Hash. */ -inline uint64_t GetMeshHash(aiMesh* in) -{ - ai_assert(NULL != in); +inline +uint64_t GetMeshHash(aiMesh* in) { + ai_assert(nullptr != in); // ... get an unique value representing the vertex format of the mesh const unsigned int fhash = GetMeshVFormatUnique(in); @@ -78,14 +78,14 @@ inline uint64_t GetMeshHash(aiMesh* in) /** @brief Perform a component-wise comparison of two arrays * * @param first First array - * @param second Second aray + * @param second Second array * @param size Size of both arrays * @param e Epsilon * @return true if the arrays are identical */ -inline bool CompareArrays(const aiVector3D* first, const aiVector3D* second, - unsigned int size, float e) -{ +inline +bool CompareArrays(const aiVector3D* first, const aiVector3D* second, + unsigned int size, float e) { for (const aiVector3D* end = first+size; first != end; ++first,++second) { if ( (*first - *second).SquareLength() >= e) return false; diff --git a/code/OpenGEXImporter.cpp b/code/OpenGEXImporter.cpp index 43c92c4f5..652ba0f98 100644 --- a/code/OpenGEXImporter.cpp +++ b/code/OpenGEXImporter.cpp @@ -731,17 +731,22 @@ enum MeshAttribute { TexCoord }; +static const std::string PosToken = "position"; +static const std::string ColToken = "color"; +static const std::string NormalToken = "normal"; +static const std::string TexCoordToken = "texcoord"; + //------------------------------------------------------------------------------------------------ static MeshAttribute getAttributeByName( const char *attribName ) { ai_assert( nullptr != attribName ); - if ( 0 == strncmp( "position", attribName, strlen( "position" ) ) ) { + if ( 0 == strncmp( PosToken.c_str(), attribName, PosToken.size() ) ) { return Position; - } else if ( 0 == strncmp( "color", attribName, strlen( "color" ) ) ) { + } else if ( 0 == strncmp( ColToken.c_str(), attribName, ColToken.size() ) ) { return Color; - } else if( 0 == strncmp( "normal", attribName, strlen( "normal" ) ) ) { + } else if( 0 == strncmp( NormalToken.c_str(), attribName, NormalToken.size() ) ) { return Normal; - } else if( 0 == strncmp( "texcoord", attribName, strlen( "texcoord" ) ) ) { + } else if( 0 == strncmp( TexCoordToken.c_str(), attribName, TexCoordToken.size() ) ) { return TexCoord; } @@ -1098,14 +1103,12 @@ void OpenGEXImporter::handleParamNode( ODDLParser::DDLNode *node, aiScene * /*pS return; } const float floatVal( val->getFloat() ); - if ( prop->m_value != nullptr ) { - if ( 0 == ASSIMP_strincmp( "fov", prop->m_value->getString(), 3 ) ) { - m_currentCamera->mHorizontalFOV = floatVal; - } else if ( 0 == ASSIMP_strincmp( "near", prop->m_value->getString(), 3 ) ) { - m_currentCamera->mClipPlaneNear = floatVal; - } else if ( 0 == ASSIMP_strincmp( "far", prop->m_value->getString(), 3 ) ) { - m_currentCamera->mClipPlaneFar = floatVal; - } + if ( 0 == ASSIMP_strincmp( "fov", prop->m_value->getString(), 3 ) ) { + m_currentCamera->mHorizontalFOV = floatVal; + } else if ( 0 == ASSIMP_strincmp( "near", prop->m_value->getString(), 4 ) ) { + m_currentCamera->mClipPlaneNear = floatVal; + } else if ( 0 == ASSIMP_strincmp( "far", prop->m_value->getString(), 3 ) ) { + m_currentCamera->mClipPlaneFar = floatVal; } } } diff --git a/code/SceneCombiner.cpp b/code/SceneCombiner.cpp index 30722618f..8647bd1ba 100644 --- a/code/SceneCombiner.cpp +++ b/code/SceneCombiner.cpp @@ -1256,29 +1256,30 @@ void SceneCombiner::Copy(aiMetadata** _dest, const aiMetadata* src) { aiMetadataEntry& out = dest->mValues[i]; out.mType = in.mType; switch (dest->mValues[i].mType) { - case AI_BOOL: - out.mData = new bool(*static_cast(in.mData)); - break; - case AI_INT32: - out.mData = new int32_t(*static_cast(in.mData)); - break; - case AI_UINT64: - out.mData = new uint64_t(*static_cast(in.mData)); - break; - case AI_FLOAT: - out.mData = new float(*static_cast(in.mData)); - break; - case AI_DOUBLE: - out.mData = new double(*static_cast(in.mData)); - break; - case AI_AISTRING: - out.mData = new aiString(*static_cast(in.mData)); - break; - case AI_AIVECTOR3D: - out.mData = new aiVector3D(*static_cast(in.mData)); - break; - default: - ai_assert(false); + case AI_BOOL: + out.mData = new bool(*static_cast(in.mData)); + break; + case AI_INT32: + out.mData = new int32_t(*static_cast(in.mData)); + break; + case AI_UINT64: + out.mData = new uint64_t(*static_cast(in.mData)); + break; + case AI_FLOAT: + out.mData = new float(*static_cast(in.mData)); + break; + case AI_DOUBLE: + out.mData = new double(*static_cast(in.mData)); + break; + case AI_AISTRING: + out.mData = new aiString(*static_cast(in.mData)); + break; + case AI_AIVECTOR3D: + out.mData = new aiVector3D(*static_cast(in.mData)); + break; + default: + ai_assert(false); + break; } } } diff --git a/code/SpatialSort.cpp b/code/SpatialSort.cpp index 010cad7c1..e6ffeb260 100644 --- a/code/SpatialSort.cpp +++ b/code/SpatialSort.cpp @@ -294,7 +294,7 @@ void SpatialSort::FindIdenticalPositions( const aiVector3D& pPosition, index++; // Now start iterating from there until the first position lays outside of the distance range. - // Add all positions inside the distance range within the tolerance to the result aray + // Add all positions inside the distance range within the tolerance to the result array std::vector::const_iterator it = mPositions.begin() + index; while( ToBinary(it->mDistance) < maxDistBinary) { diff --git a/code/VertexTriangleAdjacency.cpp b/code/VertexTriangleAdjacency.cpp index 022d5d902..5886ca372 100644 --- a/code/VertexTriangleAdjacency.cpp +++ b/code/VertexTriangleAdjacency.cpp @@ -48,7 +48,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "VertexTriangleAdjacency.h" #include - using namespace Assimp; // ------------------------------------------------------------------------------------------------ @@ -60,8 +59,8 @@ VertexTriangleAdjacency::VertexTriangleAdjacency(aiFace *pcFaces, // compute the number of referenced vertices if it wasn't specified by the caller const aiFace* const pcFaceEnd = pcFaces + iNumFaces; if (!iNumVertices) { - for (aiFace* pcFace = pcFaces; pcFace != pcFaceEnd; ++pcFace) { + ai_assert( nullptr != pcFace ); ai_assert(3 == pcFace->mNumIndices); iNumVertices = std::max(iNumVertices,pcFace->mIndices[0]); iNumVertices = std::max(iNumVertices,pcFace->mIndices[1]); @@ -69,19 +68,18 @@ VertexTriangleAdjacency::VertexTriangleAdjacency(aiFace *pcFaces, } } - this->iNumVertices = iNumVertices; + mNumVertices = iNumVertices; unsigned int* pi; // allocate storage if (bComputeNumTriangles) { pi = mLiveTriangles = new unsigned int[iNumVertices+1]; - memset(mLiveTriangles,0,sizeof(unsigned int)*(iNumVertices+1)); + ::memset(mLiveTriangles,0,sizeof(unsigned int)*(iNumVertices+1)); mOffsetTable = new unsigned int[iNumVertices+2]+1; - } - else { + } else { pi = mOffsetTable = new unsigned int[iNumVertices+2]+1; - memset(mOffsetTable,0,sizeof(unsigned int)*(iNumVertices+1)); + ::memset(mOffsetTable,0,sizeof(unsigned int)*(iNumVertices+1)); mLiveTriangles = NULL; // important, otherwise the d'tor would crash } @@ -90,8 +88,7 @@ VertexTriangleAdjacency::VertexTriangleAdjacency(aiFace *pcFaces, *piEnd++ = 0u; // first pass: compute the number of faces referencing each vertex - for (aiFace* pcFace = pcFaces; pcFace != pcFaceEnd; ++pcFace) - { + for (aiFace* pcFace = pcFaces; pcFace != pcFaceEnd; ++pcFace) { pi[pcFace->mIndices[0]]++; pi[pcFace->mIndices[1]]++; pi[pcFace->mIndices[2]]++; diff --git a/code/VertexTriangleAdjacency.h b/code/VertexTriangleAdjacency.h index 566783835..23624a5be 100644 --- a/code/VertexTriangleAdjacency.h +++ b/code/VertexTriangleAdjacency.h @@ -60,10 +60,8 @@ namespace Assimp { * @note Although it is called #VertexTriangleAdjacency, the current version does also * support arbitrary polygons. */ // -------------------------------------------------------------------------------------------- -class ASSIMP_API VertexTriangleAdjacency -{ +class ASSIMP_API VertexTriangleAdjacency { public: - // ---------------------------------------------------------------------------- /** @brief Construction from an existing index buffer * @param pcFaces Index buffer @@ -77,39 +75,30 @@ public: unsigned int iNumVertices = 0, bool bComputeNumTriangles = true); - // ---------------------------------------------------------------------------- /** @brief Destructor */ ~VertexTriangleAdjacency(); - -public: - // ---------------------------------------------------------------------------- /** @brief Get all triangles adjacent to a vertex * @param iVertIndex Index of the vertex * @return A pointer to the adjacency list. */ - unsigned int* GetAdjacentTriangles(unsigned int iVertIndex) const - { - ai_assert(iVertIndex < iNumVertices); + unsigned int* GetAdjacentTriangles(unsigned int iVertIndex) const { + ai_assert(iVertIndex < mNumVertices); return &mAdjacencyTable[ mOffsetTable[iVertIndex]]; } - // ---------------------------------------------------------------------------- /** @brief Get the number of triangles that are referenced by * a vertex. This function returns a reference that can be modified * @param iVertIndex Index of the vertex * @return Number of referenced triangles */ - unsigned int& GetNumTrianglesPtr(unsigned int iVertIndex) - { - ai_assert(iVertIndex < iNumVertices && NULL != mLiveTriangles); + unsigned int& GetNumTrianglesPtr(unsigned int iVertIndex) { + ai_assert( iVertIndex < mNumVertices ); + ai_assert( nullptr != mLiveTriangles ); return mLiveTriangles[iVertIndex]; } - -public: - //! Offset table unsigned int* mOffsetTable; @@ -120,9 +109,9 @@ public: unsigned int* mLiveTriangles; //! Debug: Number of referenced vertices - unsigned int iNumVertices; - + unsigned int mNumVertices; }; -} + +} //! ns Assimp #endif // !! AI_VTADJACENCY_H_INC diff --git a/include/assimp/IOStreamBuffer.h b/include/assimp/IOStreamBuffer.h index a503b3874..fdc339062 100644 --- a/include/assimp/IOStreamBuffer.h +++ b/include/assimp/IOStreamBuffer.h @@ -248,9 +248,9 @@ bool IOStreamBuffer::getNextDataLine( std::vector &buffer, T continuationT } } - bool continuationFound( false ), endOfDataLine( false ); + bool continuationFound( false ); size_t i = 0; - while ( !endOfDataLine ) { + for( ;; ) { if ( continuationToken == m_cache[ m_cachePos ] ) { continuationFound = true; ++m_cachePos; diff --git a/include/assimp/SGSpatialSort.h b/include/assimp/SGSpatialSort.h index d8b4b418b..203e32512 100644 --- a/include/assimp/SGSpatialSort.h +++ b/include/assimp/SGSpatialSort.h @@ -123,7 +123,7 @@ protected: Entry() { /** intentionally not initialized.*/ } Entry( unsigned int pIndex, const aiVector3D& pPosition, float pDistance,uint32_t pSG) - : + : mIndex( pIndex), mPosition( pPosition), mSmoothGroups (pSG), From 58436068e7e08e496a1d415461de706a33f7832f Mon Sep 17 00:00:00 2001 From: Giuseppe Barbieri Date: Fri, 16 Feb 2018 22:16:10 +0100 Subject: [PATCH 08/22] Update BlenderScene.cpp --- code/BlenderScene.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/BlenderScene.cpp b/code/BlenderScene.cpp index 0e1dec7f3..e4373909e 100644 --- a/code/BlenderScene.cpp +++ b/code/BlenderScene.cpp @@ -116,7 +116,7 @@ template <> void Structure :: Convert ( ReadField(temp,"projy",db); dest.projy = static_cast(temp); ReadField(temp,"projz",db); - dest.projx = static_cast(temp); + dest.projz = static_cast(temp); ReadField(dest.mapping,"mapping",db); ReadFieldArray(dest.ofs,"ofs",db); ReadFieldArray(dest.size,"size",db); From 8950504cf079d60a18c56796218c722d52120db2 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sun, 18 Feb 2018 21:30:23 +0100 Subject: [PATCH 09/22] Fix import of materials. --- code/3MFXmlTags.h | 1 + code/D3MFImporter.cpp | 30 ++++++++++++++++++++++-------- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/code/3MFXmlTags.h b/code/3MFXmlTags.h index 20971a38f..00938a45e 100644 --- a/code/3MFXmlTags.h +++ b/code/3MFXmlTags.h @@ -62,6 +62,7 @@ namespace XmlTag { static const std::string v2 = "v2"; static const std::string v3 = "v3"; static const std::string id = "id"; + static const std::string pid = "pid"; static const std::string name = "name"; static const std::string type = "type"; static const std::string build = "build"; diff --git a/code/D3MFImporter.cpp b/code/D3MFImporter.cpp index 823fae74c..29e27371e 100644 --- a/code/D3MFImporter.cpp +++ b/code/D3MFImporter.cpp @@ -79,7 +79,7 @@ public: } void ImportXml(aiScene* scene) { - if ( nullptr != scene ) { + if ( nullptr == scene ) { return; } @@ -87,11 +87,12 @@ public: std::vector children; while(ReadToEndElement(D3MF::XmlTag::model)) { - if(xmlReader->getNodeName() == D3MF::XmlTag::object) { + const std::string nodeName( xmlReader->getNodeName() ); + if( nodeName == D3MF::XmlTag::object) { children.push_back(ReadObject(scene)); - } else if(xmlReader->getNodeName() == D3MF::XmlTag::build) { + } else if( nodeName == D3MF::XmlTag::build) { // - } else if ( xmlReader->getNodeName() == D3MF::XmlTag::basematerials ) { + } else if ( nodeName == D3MF::XmlTag::basematerials ) { ReadBaseMaterials(); } } @@ -105,6 +106,11 @@ public: std::copy( mMeshes.begin(), mMeshes.end(), scene->mMeshes); + scene->mNumMaterials = mMaterials.size(); + if ( 0 != scene->mNumMaterials ) { + scene->mMaterials = new aiMaterial*[ scene->mNumMaterials ]; + std::copy( mMaterials.begin(), mMaterials.end(), scene->mMaterials ); + } scene->mRootNode->mNumChildren = static_cast(children.size()); scene->mRootNode->mChildren = new aiNode*[scene->mRootNode->mNumChildren](); @@ -196,8 +202,13 @@ private: std::vector faces; while(ReadToEndElement(D3MF::XmlTag::triangles)) { + const std::string nodeName( xmlReader->getNodeName() ); if(xmlReader->getNodeName() == D3MF::XmlTag::triangle) { faces.push_back(ReadTriangle()); + } else if ( nodeName == D3MF::XmlTag::pid ) { + const std::string matId( xmlReader->getAttributeValue( nodeName.c_str() ) ); + int matIdx( std::atoi( matId.c_str() ) ); + mesh->mMaterialIndex = matIdx; } } @@ -270,15 +281,17 @@ private: } aiMaterial *readMaterialDef() { - while ( ReadToEndElement( D3MF::XmlTag::basematerials_base ) ) { + aiMaterial *mat( nullptr ); + //while ( ReadToEndElement( D3MF::XmlTag::basematerials_base ) ) { const char *name( nullptr ); const char *color( nullptr ); - if ( xmlReader->getNodeName() == D3MF::XmlTag::basematerials_name ) { + const std::string nodeName( xmlReader->getNodeName() ); + if ( nodeName == D3MF::XmlTag::basematerials_base ) { name = xmlReader->getAttributeValue( D3MF::XmlTag::basematerials_name.c_str() ); aiString matName; matName.Set( name ); - aiMaterial *mat = new aiMaterial; + mat = new aiMaterial; mat->AddProperty( &matName, AI_MATKEY_NAME ); color = xmlReader->getAttributeValue( D3MF::XmlTag::basematerials_displaycolor.c_str() ); @@ -287,8 +300,9 @@ private: mat->AddProperty( &diffuse, 1, AI_MATKEY_COLOR_DIFFUSE ); } } - } + //} + return mat; } private: From 24d452e27c40a1de917fb033c38688e090ebd83c Mon Sep 17 00:00:00 2001 From: Tommy Date: Mon, 19 Feb 2018 11:34:26 +0100 Subject: [PATCH 10/22] Fix aiBone->mOffsetMatrix documentation, which was incorrect. Also elaborated a bit on what mOffsetMatrix is, and what it is for. --- include/assimp/mesh.h | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/include/assimp/mesh.h b/include/assimp/mesh.h index b2f64195f..731053614 100644 --- a/include/assimp/mesh.h +++ b/include/assimp/mesh.h @@ -243,20 +243,31 @@ struct aiVertexWeight { * * A bone has a name by which it can be found in the frame hierarchy and by * which it can be addressed by animations. In addition it has a number of - * influences on vertices. + * influences on vertices, and a matrix relating the mesh position to the + * position of the bone at the time of binding. */ struct aiBone { //! The name of the bone. C_STRUCT aiString mName; - //! The number of vertices affected by this bone + //! The number of vertices affected by this bone. //! The maximum value for this member is #AI_MAX_BONE_WEIGHTS. unsigned int mNumWeights; - //! The vertices affected by this bone + //! The influence weights of this bone, by vertex index. C_STRUCT aiVertexWeight* mWeights; - //! Matrix that transforms from mesh space to bone space in bind pose + /** Matrix that transforms from bone space to mesh space in bind pose. + * + * This matrix describes the position of the mesh + * in the local space of this bone when the skeleton was bound. + * Thus it can be used directly to determine a desired vertex position, + * given the world-space transform of the bone when animated, + * and the position of the vertex in mesh space. + * + * It is sometimes called an inverse-bind matrix, + * or inverse bind pose matrix. + */ C_STRUCT aiMatrix4x4 mOffsetMatrix; #ifdef __cplusplus From f0ccff70a4448f5888955eb5a6215f3cd2efe3ac Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 20 Feb 2018 09:03:18 +0100 Subject: [PATCH 11/22] Update FileSystemFilter.h Fix review findings --- code/FileSystemFilter.h | 117 +++++++++++++++++++--------------------- 1 file changed, 54 insertions(+), 63 deletions(-) diff --git a/code/FileSystemFilter.h b/code/FileSystemFilter.h index 0fabb41dd..668d79625 100644 --- a/code/FileSystemFilter.h +++ b/code/FileSystemFilter.h @@ -42,13 +42,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * Implements a filter system to filter calls to Exists() and Open() * in order to improve the success rate of file opening ... */ +#pragma once #ifndef AI_FILESYSTEMFILTER_H_INC #define AI_FILESYSTEMFILTER_H_INC -#include "../include/assimp/IOSystem.hpp" -#include "../include/assimp/DefaultLogger.hpp" -#include "../include/assimp/fast_atof.h" -#include "../include/assimp/ParsingUtils.h" +#include +#include +#include +#include namespace Assimp { @@ -64,90 +65,84 @@ class FileSystemFilter : public IOSystem public: /** Constructor. */ FileSystemFilter(const std::string& file, IOSystem* old) - : wrapped (old) - , src_file (file) - , sep(wrapped->getOsSeparator()) - { - ai_assert(NULL != wrapped); + : mWrapped (old) + , mSrc_file(file) + , sep(wrapped->getOsSeparator()) { + ai_assert(nullptr != mWrapped); // Determine base directory - base = src_file; + mBase = mSrc_file; std::string::size_type ss2; - if (std::string::npos != (ss2 = base.find_last_of("\\/"))) { - base.erase(ss2,base.length()-ss2); - } - else { - base = ""; - // return; + if (std::string::npos != (ss2 = mBase.find_last_of("\\/"))) { + mBase.erase(ss2,mBase.length()-ss2); + } else { + mBase = ""; } // make sure the directory is terminated properly char s; - if (base.length() == 0) { - base = "."; - base += getOsSeparator(); - } - else if ((s = *(base.end()-1)) != '\\' && s != '/') { - base += getOsSeparator(); + if ( mBase.empty() ) { + mBase = "."; + mBase += getOsSeparator(); + } else if ((s = *(base.end()-1)) != '\\' && s != '/') { + mBase += getOsSeparator(); } - DefaultLogger::get()->info("Import root directory is \'" + base + "\'"); + DefaultLogger::get()->info("Import root directory is \'" + mBase + "\'"); } /** Destructor. */ - ~FileSystemFilter() - { - // haha + ~FileSystemFilter() { + // empty } // ------------------------------------------------------------------- /** Tests for the existence of a file at the given path. */ - bool Exists( const char* pFile) const - { + bool Exists( const char* pFile) const { + ai_assert( nullptr != mWrapped ); std::string tmp = pFile; // Currently this IOSystem is also used to open THE ONE FILE. - if (tmp != src_file) { + if (tmp != mSrc_file) { BuildPath(tmp); Cleanup(tmp); } - return wrapped->Exists(tmp); + return mWrapped->Exists(tmp); } // ------------------------------------------------------------------- /** Returns the directory separator. */ - char getOsSeparator() const - { + char getOsSeparator() const { return sep; } // ------------------------------------------------------------------- /** Open a new file with a given path. */ - IOStream* Open( const char* pFile, const char* pMode = "rb") - { - ai_assert(pFile); - ai_assert(pMode); + IOStream* Open( const char* pFile, const char* pMode = "rb") { + ai_assert( nullptr != mWrapped ); + ai_assert( nullptr != pFile ); + ai_assert( nullptr != pMode ); // First try the unchanged path - IOStream* s = wrapped->Open(pFile,pMode); + IOStream* s = mWrapped->Open(pFile,pMode); - if (!s) { + if (nullptr == s) { std::string tmp = pFile; // Try to convert between absolute and relative paths BuildPath(tmp); - s = wrapped->Open(tmp,pMode); + s = mWrapped->Open(tmp,pMode); - if (!s) { + if (nullptr == s) { // Finally, look for typical issues with paths // and try to correct them. This is our last // resort. tmp = pFile; Cleanup(tmp); BuildPath(tmp); - s = wrapped->Open(tmp,pMode); + s = mWrapped->Open(tmp,pMode); } } @@ -156,27 +151,26 @@ public: // ------------------------------------------------------------------- /** Closes the given file and releases all resources associated with it. */ - void Close( IOStream* pFile) - { - return wrapped->Close(pFile); + void Close( IOStream* pFile) { + ai_assert( nullptr != mWrapped ); + return mWrapped->Close(pFile); } // ------------------------------------------------------------------- /** Compare two paths */ - bool ComparePaths (const char* one, const char* second) const - { - return wrapped->ComparePaths (one,second); + bool ComparePaths (const char* one, const char* second) const { + ai_assert( nullptr != mWrapped ); + return mWrapped->ComparePaths (one,second); } private: - // ------------------------------------------------------------------- /** Build a valid path from a given relative or absolute path. */ - void BuildPath (std::string& in) const - { + void BuildPath (std::string& in) const { + ai_assert( nullptr != mWrapped ); // if we can already access the file, great. - if (in.length() < 3 || wrapped->Exists(in)) { + if (in.length() < 3 || mWrapped->Exists(in)) { return; } @@ -184,8 +178,8 @@ private: if (in[1] != ':') { // append base path and try - const std::string tmp = base + in; - if (wrapped->Exists(tmp)) { + const std::string tmp = mBase + in; + if (mWrapped->Exists(tmp)) { in = tmp; return; } @@ -207,7 +201,7 @@ private: std::string::size_type last_dirsep = std::string::npos; while(true) { - tmp = base; + tmp = mBase; tmp += sep; std::string::size_type dirsep = in.rfind('/', last_dirsep); @@ -223,7 +217,7 @@ private: last_dirsep = dirsep-1; tmp += in.substr(dirsep+1, in.length()-pos); - if (wrapped->Exists(tmp)) { + if (mWrapped->Exists(tmp)) { in = tmp; return; } @@ -236,15 +230,14 @@ private: // ------------------------------------------------------------------- /** Cleanup the given path */ - void Cleanup (std::string& in) const - { - char last = 0; + void Cleanup (std::string& in) const { if(in.empty()) { return; } // Remove a very common issue when we're parsing file names: spaces at the // beginning of the path. + char last = 0; std::string::iterator it = in.begin(); while (IsSpaceOrNewLine( *it ))++it; if (it != in.begin()) { @@ -274,9 +267,7 @@ private: it = in.erase(it); --it; } - } - else if (*it == '%' && in.end() - it > 2) { - + } else if (*it == '%' && in.end() - it > 2) { // Hex sequence in URIs if( IsHex((&*it)[0]) && IsHex((&*it)[1]) ) { *it = HexOctetToDecimal(&*it); @@ -290,8 +281,8 @@ private: } private: - IOSystem* wrapped; - std::string src_file, base; + IOSystem *mWrapped; + std::string mSrc_file, mBase; char sep; }; From a92dbabc2538747620316ec1548e2ed64eb58d0a Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 20 Feb 2018 16:36:55 +0100 Subject: [PATCH 12/22] Update FileSystemFilter.h Fix missing save. --- code/FileSystemFilter.h | 45 +++++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/code/FileSystemFilter.h b/code/FileSystemFilter.h index 464bb4c91..23d555eb8 100644 --- a/code/FileSystemFilter.h +++ b/code/FileSystemFilter.h @@ -67,7 +67,7 @@ public: FileSystemFilter(const std::string& file, IOSystem* old) : mWrapped (old) , mSrc_file(file) - , sep(wrapped->getOsSeparator()) { + , sep(mWrapped->getOsSeparator()) { ai_assert(nullptr != mWrapped); // Determine base directory @@ -101,6 +101,7 @@ public: /** Tests for the existence of a file at the given path. */ bool Exists( const char* pFile) const { ai_assert( nullptr != mWrapped ); + std::string tmp = pFile; // Currently this IOSystem is also used to open THE ONE FILE. @@ -165,51 +166,51 @@ public: // ------------------------------------------------------------------- /** Pushes a new directory onto the directory stack. */ - bool PushDirectory(const std::string &path) - { - return wrapped->PushDirectory(path); + bool PushDirectory(const std::string &path ) { + ai_assert( nullptr != mWrapped ); + return mWrapped->PushDirectory(path); } // ------------------------------------------------------------------- /** Returns the top directory from the stack. */ - const std::string &CurrentDirectory() const - { - return wrapped->CurrentDirectory(); + const std::string &CurrentDirectory() const { + ai_assert( nullptr != mWrapped ); + return mWrapped->CurrentDirectory(); } // ------------------------------------------------------------------- /** Returns the number of directories stored on the stack. */ - size_t StackSize() const - { - return wrapped->StackSize(); + size_t StackSize() const { + ai_assert( nullptr != mWrapped ); + return mWrapped->StackSize(); } // ------------------------------------------------------------------- /** Pops the top directory from the stack. */ - bool PopDirectory() - { - return wrapped->PopDirectory(); + bool PopDirectory() { + ai_assert( nullptr != mWrapped ); + return mWrapped->PopDirectory(); } // ------------------------------------------------------------------- /** Creates an new directory at the given path. */ - bool CreateDirectory(const std::string &path) - { - return wrapped->CreateDirectory(path); + bool CreateDirectory(const std::string &path) { + ai_assert( nullptr != mWrapped ); + return mWrapped->CreateDirectory(path); } // ------------------------------------------------------------------- /** Will change the current directory to the given path. */ - bool ChangeDirectory(const std::string &path) - { - return wrapped->ChangeDirectory(path); + bool ChangeDirectory(const std::string &path) { + ai_assert( nullptr != mWrapped ); + return mWrapped->ChangeDirectory(path); } // ------------------------------------------------------------------- /** Delete file. */ - bool DeleteFile(const std::string &file) - { - return wrapped->DeleteFile(file); + bool DeleteFile(const std::string &file) { + ai_assert( nullptr != mWrapped ); + return mWrapped->DeleteFile(file); } private: From 7cd1a66c8bc22a2c94460900f47c48d46be14bd1 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 20 Feb 2018 22:08:40 +0100 Subject: [PATCH 13/22] Use correct lookup. --- code/D3MFImporter.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/code/D3MFImporter.cpp b/code/D3MFImporter.cpp index 29e27371e..5c036bf76 100644 --- a/code/D3MFImporter.cpp +++ b/code/D3MFImporter.cpp @@ -205,10 +205,11 @@ private: const std::string nodeName( xmlReader->getNodeName() ); if(xmlReader->getNodeName() == D3MF::XmlTag::triangle) { faces.push_back(ReadTriangle()); - } else if ( nodeName == D3MF::XmlTag::pid ) { - const std::string matId( xmlReader->getAttributeValue( nodeName.c_str() ) ); - int matIdx( std::atoi( matId.c_str() ) ); - mesh->mMaterialIndex = matIdx; + const char *pidToken( xmlReader->getAttributeValue( D3MF::XmlTag::pid.c_str() ) ); + if ( nullptr != pidToken ) { + int matIdx( std::atoi( pidToken ) ); + mesh->mMaterialIndex = matIdx; + } } } @@ -234,6 +235,7 @@ private: void ReadBaseMaterials() { while ( ReadToEndElement( D3MF::XmlTag::basematerials ) ) { mMaterials.push_back( readMaterialDef() ); + xmlReader->read(); } } @@ -324,8 +326,7 @@ private: return false; } - bool ReadToEndElement(const std::string& closeTag) - { + bool ReadToEndElement(const std::string& closeTag) { while(xmlReader->read()) { if (xmlReader->getNodeType() == irr::io::EXN_ELEMENT) { From fb213e4bac445484d80bbde8888520ba83cfcf1f Mon Sep 17 00:00:00 2001 From: Tommy Date: Wed, 21 Feb 2018 12:23:28 +0100 Subject: [PATCH 14/22] FBX Importer: apply inverse of geometric transform to child nodes. --- code/FBXConverter.cpp | 66 +++++++++++++++++++++++++++++++++++++++---- code/FBXConverter.h | 7 +++-- 2 files changed, 66 insertions(+), 7 deletions(-) diff --git a/code/FBXConverter.cpp b/code/FBXConverter.cpp index 6929e5c33..7134bc2e0 100644 --- a/code/FBXConverter.cpp +++ b/code/FBXConverter.cpp @@ -142,6 +142,7 @@ void Converter::ConvertNodes( uint64_t id, aiNode& parent, const aiMatrix4x4& pa nodes.reserve( conns.size() ); std::vector nodes_chain; + std::vector post_nodes_chain; try { for( const Connection* con : conns ) { @@ -161,6 +162,7 @@ void Converter::ConvertNodes( uint64_t id, aiNode& parent, const aiMatrix4x4& pa if ( model ) { nodes_chain.clear(); + post_nodes_chain.clear(); aiMatrix4x4 new_abs_transform = parent_transform; @@ -168,7 +170,7 @@ void Converter::ConvertNodes( uint64_t id, aiNode& parent, const aiMatrix4x4& pa // 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. - GenerateTransformationNodeChain( *model, nodes_chain ); + GenerateTransformationNodeChain( *model, nodes_chain, post_nodes_chain ); ai_assert( nodes_chain.size() ); @@ -213,8 +215,25 @@ void Converter::ConvertNodes( uint64_t id, aiNode& parent, const aiMatrix4x4& pa // attach geometry ConvertModel( *model, *nodes_chain.back(), new_abs_transform ); + // now link the geometric transform inverse nodes, + // before we attach any child nodes + 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; + } + // attach sub-nodes - ConvertNodes( model->ID(), *nodes_chain.back(), new_abs_transform ); + ConvertNodes( model->ID(), *last_parent, new_abs_transform ); if ( doc.Settings().readLights ) { ConvertLights( *model ); @@ -396,6 +415,12 @@ const char* Converter::NameTransformationComp( TransformationComp comp ) 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; @@ -437,6 +462,12 @@ const char* Converter::NameTransformationCompProperty( TransformationComp comp ) 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; } @@ -570,7 +601,7 @@ std::string Converter::NameTransformationChainNode( const std::string& name, Tra return name + std::string( MAGIC_NODE_TAG ) + "_" + NameTransformationComp( comp ); } -void Converter::GenerateTransformationNodeChain( const Model& model, std::vector& output_nodes ) +void Converter::GenerateTransformationNodeChain( const Model& model, std::vector& output_nodes, std::vector& post_output_nodes ) { const PropertyTable& props = model.Props(); const Model::RotOrder rot = model.RotationOrder(); @@ -646,16 +677,33 @@ void Converter::GenerateTransformationNodeChain( const Model& model, std::vector const aiVector3D& GeometricScaling = PropertyGet( props, "GeometricScaling", ok ); if ( ok && std::fabs( GeometricScaling.SquareLength() - 1.0f ) > zero_epsilon ) { aiMatrix4x4::Scaling( GeometricScaling, chain[ TransformationComp_GeometricScaling ] ); + aiVector3D GeometricScalingInverse = GeometricScaling; + bool canscale = true; + for (size_t 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) { + aiMatrix4x4::Scaling( GeometricScalingInverse, chain[ TransformationComp_GeometricScalingInverse ] ); + } } const aiVector3D& GeometricRotation = PropertyGet( props, "GeometricRotation", ok ); if ( ok && GeometricRotation.SquareLength() > zero_epsilon ) { 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 ) { aiMatrix4x4::Translation( GeometricTranslation, chain[ TransformationComp_GeometricTranslation ] ); + aiMatrix4x4::Translation( -GeometricTranslation, chain[ TransformationComp_GeometricTranslationInverse ] ); } // is_complex needs to be consistent with NeedsComplexTransformationChain() @@ -690,10 +738,18 @@ void Converter::GenerateTransformationNodeChain( const Model& model, std::vector } aiNode* nd = new aiNode(); - output_nodes.push_back( nd ); - 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() ); diff --git a/code/FBXConverter.h b/code/FBXConverter.h index c882e9326..06a6f07a7 100644 --- a/code/FBXConverter.h +++ b/code/FBXConverter.h @@ -82,7 +82,10 @@ public: * The different parts that make up the final local transformation of a fbx-node */ enum TransformationComp { - TransformationComp_Translation = 0, + TransformationComp_GeometricScalingInverse = 0, + TransformationComp_GeometricRotationInverse, + TransformationComp_GeometricTranslationInverse, + TransformationComp_Translation, TransformationComp_RotationOffset, TransformationComp_RotationPivot, TransformationComp_PreRotation, @@ -153,7 +156,7 @@ private: /** * note: memory for output_nodes will be managed by the caller */ - void GenerateTransformationNodeChain(const Model& model, std::vector& output_nodes); + void GenerateTransformationNodeChain(const Model& model, std::vector& output_nodes, std::vector& post_output_nodes); // ------------------------------------------------------------------------------------------------ void SetupNodeMetadata(const Model& model, aiNode& nd); From a8fc22fd3f0dabc79820d074dd81f1c67d983dee Mon Sep 17 00:00:00 2001 From: Tommy Date: Wed, 21 Feb 2018 12:57:45 +0100 Subject: [PATCH 15/22] assimp_cmd: Add --verbose flag to 'info' command, to print node transforms. --- tools/assimp_cmd/Info.cpp | 49 +++++++++++++++++++++++++++++++++------ 1 file changed, 42 insertions(+), 7 deletions(-) diff --git a/tools/assimp_cmd/Info.cpp b/tools/assimp_cmd/Info.cpp index e19746db6..a9f66eb1f 100644 --- a/tools/assimp_cmd/Info.cpp +++ b/tools/assimp_cmd/Info.cpp @@ -47,9 +47,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "Main.h" const char* AICMD_MSG_INFO_HELP_E = -"assimp info [-r]\n" +"assimp info [-r] [-v]\n" "\tPrint basic structure of a 3D model\n" -"\t-r,--raw: No postprocessing, do a raw import\n"; +"\t-r,--raw: No postprocessing, do a raw import\n" +"\t-v,--verbose: Print verbose info such as node transform data\n"; // ----------------------------------------------------------------------------------- @@ -184,7 +185,7 @@ std::string FindPTypes(const aiScene* scene) // ----------------------------------------------------------------------------------- void PrintHierarchy(const aiNode* root, unsigned int maxnest, unsigned int maxline, - unsigned int cline, unsigned int cnest=0) + unsigned int cline, bool verbose, unsigned int cnest=0) { if (cline++ >= maxline || cnest >= maxnest) { return; @@ -194,8 +195,29 @@ void PrintHierarchy(const aiNode* root, unsigned int maxnest, unsigned int maxli printf("-- "); } printf("\'%s\', meshes: %u\n",root->mName.data,root->mNumMeshes); + + if (verbose) { + // print the actual transform + //printf(","); + aiVector3D s, r, t; + root->mTransformation.Decompose(s, r, t); + if (s.x != 1.0 || s.y != 1.0 || s.z != 1.0) { + for(unsigned int i = 0; i < cnest; ++i) { printf(" "); } + printf(" S:[%f %f %f]\n", s.x, s.y, s.z); + } + if (r.x || r.y || r.z) { + for(unsigned int i = 0; i < cnest; ++i) { printf(" "); } + printf(" R:[%f %f %f]\n", r.x, r.y, r.z); + } + if (t.x || t.y || t.z) { + for(unsigned int i = 0; i < cnest; ++i) { printf(" "); } + printf(" T:[%f %f %f]\n", t.x, t.y, t.z); + } + } + //printf("\n"); + for (unsigned int i = 0; i < root->mNumChildren; ++i ) { - PrintHierarchy(root->mChildren[i],maxnest,maxline,cline,cnest+1); + PrintHierarchy(root->mChildren[i],maxnest,maxline,cline,verbose,cnest+1); if(i == root->mNumChildren-1) { for(unsigned int i = 0; i < cnest; ++i) { printf(" "); @@ -230,10 +252,23 @@ int Assimp_Info (const char* const* params, unsigned int num) const std::string in = std::string(params[0]); + // get -r and -v arguments + bool raw = false; + bool verbose = false; + for(unsigned int i = 1; i < num; ++i) { + if (!strcmp(params[i],"--raw")||!strcmp(params[i],"-r")) { + raw = true; + } + if (!strcmp(params[i],"--verbose")||!strcmp(params[i],"-v")) { + verbose = true; + } + } + // do maximum post-processing unless -r was specified ImportData import; - import.ppFlags = num>1&&(!strcmp(params[1],"--raw")||!strcmp(params[1],"-r")) ? 0 - : aiProcessPreset_TargetRealtime_MaxQuality; + if (!raw) { + import.ppFlags = aiProcessPreset_TargetRealtime_MaxQuality; + } // import the main model const aiScene* scene = ImportModel(import,in); @@ -346,7 +381,7 @@ int Assimp_Info (const char* const* params, unsigned int num) printf("\nNode hierarchy:\n"); unsigned int cline=0; - PrintHierarchy(scene->mRootNode,20,1000,cline); + PrintHierarchy(scene->mRootNode,20,1000,cline,verbose); printf("\n"); return 0; From 22dbb6c2d2bb8cf0a9e6495073a46434ba28dd34 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Wed, 21 Feb 2018 13:10:51 +0100 Subject: [PATCH 16/22] Update FileSystemFilter.h - Fix typo. -test in public metod against invalid parameters --- code/FileSystemFilter.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/code/FileSystemFilter.h b/code/FileSystemFilter.h index 23d555eb8..8d43c1c27 100644 --- a/code/FileSystemFilter.h +++ b/code/FileSystemFilter.h @@ -85,7 +85,7 @@ public: if ( mBase.empty() ) { mBase = "."; mBase += getOsSeparator(); - } else if ((s = *(base.end()-1)) != '\\' && s != '/') { + } else if ((s = *(mBase.end()-1)) != '\\' && s != '/') { mBase += getOsSeparator(); } @@ -123,6 +123,10 @@ public: /** Open a new file with a given path. */ IOStream* Open( const char* pFile, const char* pMode = "rb") { ai_assert( nullptr != mWrapped ); + if ( nullptr == pFile || nullptr == pMode ) { + return nullptr; + } + ai_assert( nullptr != pFile ); ai_assert( nullptr != pMode ); From c1f353f6c7673d5056d4ea07399e1de607b3838d Mon Sep 17 00:00:00 2001 From: Tommy Date: Wed, 21 Feb 2018 14:15:03 +0100 Subject: [PATCH 17/22] FBX Export: Geometric transformations always create transformation chain. In combination with fb213e4b, this fixes #1112. --- code/FBXConverter.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/code/FBXConverter.cpp b/code/FBXConverter.cpp index 7134bc2e0..893f9f405 100644 --- a/code/FBXConverter.cpp +++ b/code/FBXConverter.cpp @@ -582,8 +582,7 @@ bool Converter::NeedsComplexTransformationChain( const Model& model ) for ( size_t i = 0; i < TransformationComp_MAXIMUM; ++i ) { const TransformationComp comp = static_cast< TransformationComp >( i ); - if ( comp == TransformationComp_Rotation || comp == TransformationComp_Scaling || comp == TransformationComp_Translation || - comp == TransformationComp_GeometricScaling || comp == TransformationComp_GeometricRotation || comp == TransformationComp_GeometricTranslation ) { + if ( comp == TransformationComp_Rotation || comp == TransformationComp_Scaling || comp == TransformationComp_Translation ) { continue; } @@ -676,6 +675,7 @@ void Converter::GenerateTransformationNodeChain( const Model& model, std::vector const aiVector3D& GeometricScaling = PropertyGet( props, "GeometricScaling", ok ); if ( ok && std::fabs( GeometricScaling.SquareLength() - 1.0f ) > zero_epsilon ) { + is_complex = true; aiMatrix4x4::Scaling( GeometricScaling, chain[ TransformationComp_GeometricScaling ] ); aiVector3D GeometricScalingInverse = GeometricScaling; bool canscale = true; @@ -695,6 +695,7 @@ void Converter::GenerateTransformationNodeChain( const Model& model, std::vector const aiVector3D& GeometricRotation = PropertyGet( props, "GeometricRotation", ok ); if ( ok && GeometricRotation.SquareLength() > zero_epsilon ) { + is_complex = true; GetRotationMatrix( rot, GeometricRotation, chain[ TransformationComp_GeometricRotation ] ); GetRotationMatrix( rot, GeometricRotation, chain[ TransformationComp_GeometricRotationInverse ] ); chain[ TransformationComp_GeometricRotationInverse ].Inverse(); @@ -702,6 +703,7 @@ void Converter::GenerateTransformationNodeChain( const Model& model, std::vector const aiVector3D& GeometricTranslation = PropertyGet( props, "GeometricTranslation", ok ); if ( ok && GeometricTranslation.SquareLength() > zero_epsilon ) { + is_complex = true; aiMatrix4x4::Translation( GeometricTranslation, chain[ TransformationComp_GeometricTranslation ] ); aiMatrix4x4::Translation( -GeometricTranslation, chain[ TransformationComp_GeometricTranslationInverse ] ); } @@ -2265,8 +2267,7 @@ void Converter::GenerateNodeAnimations( std::vector& node_anims, has_any = true; - if ( comp != TransformationComp_Rotation && comp != TransformationComp_Scaling && comp != TransformationComp_Translation && - comp != TransformationComp_GeometricScaling && comp != TransformationComp_GeometricRotation && comp != TransformationComp_GeometricTranslation ) + if ( comp != TransformationComp_Rotation && comp != TransformationComp_Scaling && comp != TransformationComp_Translation ) { has_complex = true; } From f847d4817d3dc2542c33dfb07ad0402d9985e3d5 Mon Sep 17 00:00:00 2001 From: Tommy Date: Wed, 21 Feb 2018 15:29:57 +0100 Subject: [PATCH 18/22] FBX Export: fix logic for determining if scale transformation is identity. Previously it was comparing scale.SquareLength() to 1.0. --- code/FBXConverter.cpp | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/code/FBXConverter.cpp b/code/FBXConverter.cpp index 893f9f405..746777d65 100644 --- a/code/FBXConverter.cpp +++ b/code/FBXConverter.cpp @@ -579,6 +579,7 @@ bool Converter::NeedsComplexTransformationChain( const Model& model ) 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< TransformationComp >( i ); @@ -586,9 +587,17 @@ bool Converter::NeedsComplexTransformationChain( const Model& model ) continue; } + bool scale_compare = ( comp == TransformationComp_GeometricScaling || comp == TransformationComp_Scaling ); + const aiVector3D& v = PropertyGet( props, NameTransformationCompProperty( comp ), ok ); - if ( ok && v.SquareLength() > zero_epsilon ) { - return true; + if ( ok && scale_compare ) { + if ( (v - all_ones).SquareLength() > zero_epsilon ) { + return true; + } + } else if ( ok ) { + if ( v.SquareLength() > zero_epsilon ) { + return true; + } } } @@ -612,6 +621,7 @@ void Converter::GenerateTransformationNodeChain( const Model& model, std::vector // generate transformation matrices for all the different transformation components const float zero_epsilon = 1e-6f; + const aiVector3D all_ones(1.0f, 1.0f, 1.0f); bool is_complex = false; const aiVector3D& PreRotation = PropertyGet( props, "PreRotation", ok ); @@ -664,7 +674,7 @@ void Converter::GenerateTransformationNodeChain( const Model& model, std::vector } const aiVector3D& Scaling = PropertyGet( props, "Lcl Scaling", ok ); - if ( ok && std::fabs( Scaling.SquareLength() - 1.0f ) > zero_epsilon ) { + if ( ok && (Scaling - all_ones).SquareLength() > zero_epsilon ) { aiMatrix4x4::Scaling( Scaling, chain[ TransformationComp_Scaling ] ); } @@ -674,7 +684,7 @@ void Converter::GenerateTransformationNodeChain( const Model& model, std::vector } const aiVector3D& GeometricScaling = PropertyGet( props, "GeometricScaling", ok ); - if ( ok && std::fabs( GeometricScaling.SquareLength() - 1.0f ) > zero_epsilon ) { + if ( ok && (GeometricScaling - all_ones).SquareLength() > zero_epsilon ) { is_complex = true; aiMatrix4x4::Scaling( GeometricScaling, chain[ TransformationComp_GeometricScaling ] ); aiVector3D GeometricScalingInverse = GeometricScaling; From 1d901f075c8420a18ac291ab4b721d051b250911 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Fri, 23 Feb 2018 17:49:29 +0100 Subject: [PATCH 19/22] 3mf-importer: fix parsing of base-material color. --- code/3MFXmlTags.h | 3 ++ code/D3MFImporter.cpp | 88 ++++++++++++++++------------------- include/assimp/ParsingUtils.h | 27 +++++------ include/assimp/fast_atof.h | 4 +- 4 files changed, 60 insertions(+), 62 deletions(-) diff --git a/code/3MFXmlTags.h b/code/3MFXmlTags.h index 00938a45e..c4da2970d 100644 --- a/code/3MFXmlTags.h +++ b/code/3MFXmlTags.h @@ -45,6 +45,7 @@ namespace Assimp { namespace D3MF { namespace XmlTag { + // Model-data specific tags static const std::string model = "model"; static const std::string model_unit = "unit"; static const std::string metadata = "metadata"; @@ -63,6 +64,7 @@ namespace XmlTag { static const std::string v3 = "v3"; static const std::string id = "id"; static const std::string pid = "pid"; + static const std::string p1 = "p1"; static const std::string name = "name"; static const std::string type = "type"; static const std::string build = "build"; @@ -76,6 +78,7 @@ namespace XmlTag { static const std::string basematerials_name = "name"; static const std::string basematerials_displaycolor = "displaycolor"; + // Meta info tags static const std::string CONTENT_TYPES_ARCHIVE = "[Content_Types].xml"; static const std::string ROOT_RELATIONSHIPS_ARCHIVE = "_rels/.rels"; static const std::string SCHEMA_CONTENTTYPES = "http://schemas.openxmlformats.org/package/2006/content-types"; diff --git a/code/D3MFImporter.cpp b/code/D3MFImporter.cpp index 5c036bf76..489926204 100644 --- a/code/D3MFImporter.cpp +++ b/code/D3MFImporter.cpp @@ -61,6 +61,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include "3MFXmlTags.h" +#include + +#include namespace Assimp { namespace D3MF { @@ -175,10 +178,8 @@ private: void ImportVertices(aiMesh* mesh) { std::vector vertices; - while(ReadToEndElement(D3MF::XmlTag::vertices)) - { - if(xmlReader->getNodeName() == D3MF::XmlTag::vertex) - { + while(ReadToEndElement(D3MF::XmlTag::vertices)) { + if(xmlReader->getNodeName() == D3MF::XmlTag::vertex) { vertices.push_back(ReadVertex()); } } @@ -205,7 +206,7 @@ private: const std::string nodeName( xmlReader->getNodeName() ); if(xmlReader->getNodeName() == D3MF::XmlTag::triangle) { faces.push_back(ReadTriangle()); - const char *pidToken( xmlReader->getAttributeValue( D3MF::XmlTag::pid.c_str() ) ); + const char *pidToken( xmlReader->getAttributeValue( D3MF::XmlTag::p1.c_str() ) ); if ( nullptr != pidToken ) { int matIdx( std::atoi( pidToken ) ); mesh->mMaterialIndex = matIdx; @@ -253,92 +254,85 @@ private: if ( '#' != *buf ) { return false; } - - char comp[ 2 ] = { 0,0 }; - comp[ 0 ] = *buf; ++buf; - comp[ 1 ] = *buf; - ++buf; - diffuse.r = static_cast( std::atoi( comp ) ); + char comp[ 3 ] = { 0,0,'\0' }; comp[ 0 ] = *buf; ++buf; comp[ 1 ] = *buf; ++buf; - diffuse.g = static_cast( std::atoi( comp ) ); + diffuse.r = static_cast( strtol( comp, NULL, 16 ) ); + comp[ 0 ] = *buf; ++buf; comp[ 1 ] = *buf; ++buf; - diffuse.b = static_cast( std::atoi( comp ) ); + diffuse.g = static_cast< ai_real >( strtol( comp, NULL, 16 ) ); comp[ 0 ] = *buf; ++buf; comp[ 1 ] = *buf; ++buf; - diffuse.a = static_cast( std::atoi( comp ) ); + diffuse.b = static_cast< ai_real >( strtol( comp, NULL, 16 ) ); + + comp[ 0 ] = *buf; + ++buf; + comp[ 1 ] = *buf; + ++buf; + diffuse.a = static_cast< ai_real >( strtol( comp, NULL, 16 ) ); return true; } aiMaterial *readMaterialDef() { aiMaterial *mat( nullptr ); - //while ( ReadToEndElement( D3MF::XmlTag::basematerials_base ) ) { - const char *name( nullptr ); - const char *color( nullptr ); - const std::string nodeName( xmlReader->getNodeName() ); - if ( nodeName == D3MF::XmlTag::basematerials_base ) { - name = xmlReader->getAttributeValue( D3MF::XmlTag::basematerials_name.c_str() ); + const char *name( nullptr ); + const char *color( nullptr ); + const std::string nodeName( xmlReader->getNodeName() ); + if ( nodeName == D3MF::XmlTag::basematerials_base ) { + name = xmlReader->getAttributeValue( D3MF::XmlTag::basematerials_name.c_str() ); - aiString matName; - matName.Set( name ); - mat = new aiMaterial; - mat->AddProperty( &matName, AI_MATKEY_NAME ); + aiString matName; + matName.Set( name ); + mat = new aiMaterial; + mat->AddProperty( &matName, AI_MATKEY_NAME ); - color = xmlReader->getAttributeValue( D3MF::XmlTag::basematerials_displaycolor.c_str() ); - aiColor4D diffuse; - if ( parseColor( color, diffuse ) ) { - mat->AddProperty( &diffuse, 1, AI_MATKEY_COLOR_DIFFUSE ); - } + color = xmlReader->getAttributeValue( D3MF::XmlTag::basematerials_displaycolor.c_str() ); + aiColor4D diffuse; + if ( parseColor( color, diffuse ) ) { + mat->AddProperty( &diffuse, 1, AI_MATKEY_COLOR_DIFFUSE ); } - //} + } return mat; } private: - bool ReadToStartElement(const std::string& startTag) - { - while(xmlReader->read()) - { - if (xmlReader->getNodeType() == irr::io::EXN_ELEMENT && xmlReader->getNodeName() == startTag) - { + bool ReadToStartElement(const std::string& startTag) { + while(xmlReader->read()) { + const std::string &nodeName( xmlReader->getNodeName() ); + if (xmlReader->getNodeType() == irr::io::EXN_ELEMENT && nodeName == startTag) { return true; - } - else if (xmlReader->getNodeType() == irr::io::EXN_ELEMENT_END && - xmlReader->getNodeName() == startTag) - { + } else if (xmlReader->getNodeType() == irr::io::EXN_ELEMENT_END && nodeName == startTag) { return false; } } - //DefaultLogger::get()->error("unexpected EOF, expected closing <" + closeTag + "> tag"); + return false; } bool ReadToEndElement(const std::string& closeTag) { - while(xmlReader->read()) - { + while(xmlReader->read()) { + const std::string &nodeName( xmlReader->getNodeName() ); if (xmlReader->getNodeType() == irr::io::EXN_ELEMENT) { return true; - } - else if (xmlReader->getNodeType() == irr::io::EXN_ELEMENT_END - && xmlReader->getNodeName() == closeTag) - { + } else if (xmlReader->getNodeType() == irr::io::EXN_ELEMENT_END && nodeName == closeTag) { return false; } } DefaultLogger::get()->error("unexpected EOF, expected closing <" + closeTag + "> tag"); + return false; } diff --git a/include/assimp/ParsingUtils.h b/include/assimp/ParsingUtils.h index 555b2a309..40e183a5c 100644 --- a/include/assimp/ParsingUtils.h +++ b/include/assimp/ParsingUtils.h @@ -66,49 +66,50 @@ static const unsigned int BufferSize = 4096; // --------------------------------------------------------------------------------- template -AI_FORCE_INLINE char_t ToLower( char_t in) -{ +AI_FORCE_INLINE +char_t ToLower( char_t in ) { return (in >= (char_t)'A' && in <= (char_t)'Z') ? (char_t)(in+0x20) : in; } // --------------------------------------------------------------------------------- template -AI_FORCE_INLINE char_t ToUpper( char_t in) { +AI_FORCE_INLINE +char_t ToUpper( char_t in) { return (in >= (char_t)'a' && in <= (char_t)'z') ? (char_t)(in-0x20) : in; } // --------------------------------------------------------------------------------- template -AI_FORCE_INLINE bool IsUpper( char_t in) -{ +AI_FORCE_INLINE +bool IsUpper( char_t in) { return (in >= (char_t)'A' && in <= (char_t)'Z'); } // --------------------------------------------------------------------------------- template -AI_FORCE_INLINE bool IsLower( char_t in) -{ +AI_FORCE_INLINE +bool IsLower( char_t in) { return (in >= (char_t)'a' && in <= (char_t)'z'); } // --------------------------------------------------------------------------------- template -AI_FORCE_INLINE bool IsSpace( char_t in) -{ +AI_FORCE_INLINE +bool IsSpace( char_t in) { return (in == (char_t)' ' || in == (char_t)'\t'); } // --------------------------------------------------------------------------------- template -AI_FORCE_INLINE bool IsLineEnd( char_t in) -{ +AI_FORCE_INLINE +bool IsLineEnd( char_t in) { return (in==(char_t)'\r'||in==(char_t)'\n'||in==(char_t)'\0'||in==(char_t)'\f'); } // --------------------------------------------------------------------------------- template -AI_FORCE_INLINE bool IsSpaceOrNewLine( char_t in) -{ +AI_FORCE_INLINE +bool IsSpaceOrNewLine( char_t in) { return IsSpace(in) || IsLineEnd(in); } diff --git a/include/assimp/fast_atof.h b/include/assimp/fast_atof.h index 058a7ff87..fa70abfb2 100644 --- a/include/assimp/fast_atof.h +++ b/include/assimp/fast_atof.h @@ -129,8 +129,8 @@ inline unsigned int strtoul16( const char* in, const char** out=0) // Convert just one hex digit // Return value is UINT_MAX if the input character is not a hex digit. // ------------------------------------------------------------------------------------ -inline unsigned int HexDigitToDecimal(char in) -{ +inline +unsigned int HexDigitToDecimal(char in) { unsigned int out = UINT_MAX; if (in >= '0' && in <= '9') out = in - '0'; From 9c663e9630c5c38e8b8fc64b433b7d93b2594bf5 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Fri, 23 Feb 2018 18:14:46 +0100 Subject: [PATCH 20/22] fast_a_to_f: add some brackets. --- include/assimp/fast_atof.h | 92 ++++++++++++++++++-------------------- 1 file changed, 44 insertions(+), 48 deletions(-) diff --git a/include/assimp/fast_atof.h b/include/assimp/fast_atof.h index fa70abfb2..5c25db8e1 100644 --- a/include/assimp/fast_atof.h +++ b/include/assimp/fast_atof.h @@ -14,8 +14,8 @@ // ------------------------------------------------------------------------------------ -#ifndef __FAST_A_TO_F_H_INCLUDED__ -#define __FAST_A_TO_F_H_INCLUDED__ +#ifndef FAST_A_TO_F_H_INCLUDED +#define FAST_A_TO_F_H_INCLUDED #include #include @@ -148,8 +148,8 @@ unsigned int HexDigitToDecimal(char in) { // ------------------------------------------------------------------------------------ // Convert a hex-encoded octet (2 characters, i.e. df or 1a). // ------------------------------------------------------------------------------------ -inline uint8_t HexOctetToDecimal(const char* in) -{ +inline +uint8_t HexOctetToDecimal(const char* in) { return ((uint8_t)HexDigitToDecimal(in[0])<<4)+(uint8_t)HexDigitToDecimal(in[1]); } @@ -157,8 +157,8 @@ inline uint8_t HexOctetToDecimal(const char* in) // ------------------------------------------------------------------------------------ // signed variant of strtoul10 // ------------------------------------------------------------------------------------ -inline int strtol10( const char* in, const char** out=0) -{ +inline +int strtol10( const char* in, const char** out=0) { bool inv = (*in=='-'); if (inv || *in=='+') ++in; @@ -176,10 +176,9 @@ inline int strtol10( const char* in, const char** out=0) // 0NNN - oct // NNN - dec // ------------------------------------------------------------------------------------ -inline unsigned int strtoul_cppstyle( const char* in, const char** out=0) -{ - if ('0' == in[0]) - { +inline +unsigned int strtoul_cppstyle( const char* in, const char** out=0) { + if ('0' == in[0]) { return 'x' == in[1] ? strtoul16(in+2,out) : strtoul8(in+1,out); } return strtoul10(in, out); @@ -189,19 +188,20 @@ inline unsigned int strtoul_cppstyle( const char* in, const char** out=0) // Special version of the function, providing higher accuracy and safety // It is mainly used by fast_atof to prevent ugly and unwanted integer overflows. // ------------------------------------------------------------------------------------ -inline uint64_t strtoul10_64( const char* in, const char** out=0, unsigned int* max_inout=0) -{ +inline +uint64_t strtoul10_64( const char* in, const char** out=0, unsigned int* max_inout=0) { unsigned int cur = 0; uint64_t value = 0; - if ( *in < '0' || *in > '9' ) - throw std::invalid_argument(std::string("The string \"") + in + "\" cannot be converted into a value."); + if ( *in < '0' || *in > '9' ) { + throw std::invalid_argument( std::string( "The string \"" ) + in + "\" cannot be converted into a value." ); + } bool running = true; - while ( running ) - { - if ( *in < '0' || *in > '9' ) + while ( running ) { + if ( *in < '0' || *in > '9' ) { break; + } const uint64_t new_value = ( value * 10 ) + ( *in - '0' ); @@ -210,7 +210,6 @@ inline uint64_t strtoul10_64( const char* in, const char** out=0, unsigned int* DefaultLogger::get()->warn( std::string( "Converting the string \"" ) + in + "\" into a value resulted in overflow." ); return 0; } - //throw std::overflow_error(); value = new_value; @@ -218,21 +217,23 @@ inline uint64_t strtoul10_64( const char* in, const char** out=0, unsigned int* ++cur; if (max_inout && *max_inout == cur) { - if (out) { /* skip to end */ - while (*in >= '0' && *in <= '9') + while ( *in >= '0' && *in <= '9' ) { ++in; + } *out = in; } return value; } } - if (out) + if ( out ) { *out = in; + } - if (max_inout) + if ( max_inout ) { *max_inout = cur; + } return value; } @@ -240,11 +241,12 @@ inline uint64_t strtoul10_64( const char* in, const char** out=0, unsigned int* // ------------------------------------------------------------------------------------ // signed variant of strtoul10_64 // ------------------------------------------------------------------------------------ -inline int64_t strtol10_64(const char* in, const char** out = 0, unsigned int* max_inout = 0) -{ +inline +int64_t strtol10_64(const char* in, const char** out = 0, unsigned int* max_inout = 0) { bool inv = (*in == '-'); - if (inv || *in == '+') + if ( inv || *in == '+' ) { ++in; + } int64_t value = strtoul10_64(in, out, max_inout); if (inv) { @@ -253,7 +255,6 @@ inline int64_t strtol10_64(const char* in, const char** out = 0, unsigned int* m return value; } - // Number of relevant decimals for floating-point parsing. #define AI_FAST_ATOF_RELAVANT_DECIMALS 15 @@ -263,8 +264,8 @@ inline int64_t strtol10_64(const char* in, const char** out = 0, unsigned int* m // If you find any bugs, please send them to me, niko (at) irrlicht3d.org. // ------------------------------------------------------------------------------------ template -inline const char* fast_atoreal_move(const char* c, Real& out, bool check_comma = true) -{ +inline +const char* fast_atoreal_move(const char* c, Real& out, bool check_comma = true) { Real f = 0; bool inv = (*c == '-'); @@ -272,42 +273,36 @@ inline const char* fast_atoreal_move(const char* c, Real& out, bool check_comma ++c; } - if ((c[0] == 'N' || c[0] == 'n') && ASSIMP_strincmp(c, "nan", 3) == 0) - { + if ((c[0] == 'N' || c[0] == 'n') && ASSIMP_strincmp(c, "nan", 3) == 0) { out = std::numeric_limits::quiet_NaN(); c += 3; return c; } - if ((c[0] == 'I' || c[0] == 'i') && ASSIMP_strincmp(c, "inf", 3) == 0) - { + if ((c[0] == 'I' || c[0] == 'i') && ASSIMP_strincmp(c, "inf", 3) == 0) { out = std::numeric_limits::infinity(); if (inv) { out = -out; } c += 3; - if ((c[0] == 'I' || c[0] == 'i') && ASSIMP_strincmp(c, "inity", 5) == 0) - { + if ((c[0] == 'I' || c[0] == 'i') && ASSIMP_strincmp(c, "inity", 5) == 0) { c += 5; } return c; - } + if (!(c[0] >= '0' && c[0] <= '9') && - !((c[0] == '.' || (check_comma && c[0] == ',')) && c[1] >= '0' && c[1] <= '9')) - { + !((c[0] == '.' || (check_comma && c[0] == ',')) && c[1] >= '0' && c[1] <= '9')){ throw std::invalid_argument("Cannot parse string " "as real number: does not start with digit " "or decimal point followed by digit."); } - if (*c != '.' && (! check_comma || c[0] != ',')) - { + if (*c != '.' && (! check_comma || c[0] != ',')) { f = static_cast( strtoul10_64 ( c, &c) ); } - if ((*c == '.' || (check_comma && c[0] == ',')) && c[1] >= '0' && c[1] <= '9') - { + if ((*c == '.' || (check_comma && c[0] == ',')) && c[1] >= '0' && c[1] <= '9') { ++c; // NOTE: The original implementation is highly inaccurate here. The precision of a single @@ -358,24 +353,25 @@ inline const char* fast_atoreal_move(const char* c, Real& out, bool check_comma // ------------------------------------------------------------------------------------ // The same but more human. -inline ai_real fast_atof(const char* c) -{ +inline +ai_real fast_atof(const char* c) { ai_real ret(0.0); fast_atoreal_move(c, ret); + return ret; } -inline ai_real fast_atof( const char* c, const char** cout) -{ +inline +ai_real fast_atof( const char* c, const char** cout) { ai_real ret(0.0); *cout = fast_atoreal_move(c, ret); return ret; } -inline ai_real fast_atof( const char** inout) -{ +inline +ai_real fast_atof( const char** inout) { ai_real ret(0.0); *inout = fast_atoreal_move(*inout, ret); @@ -384,4 +380,4 @@ inline ai_real fast_atof( const char** inout) } // end of namespace Assimp -#endif +#endif // FAST_A_TO_F_H_INCLUDED From d00c4a54e6ae1a00131bc00682875017d5867c04 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Fri, 23 Feb 2018 18:59:38 +0100 Subject: [PATCH 21/22] Update fast_atof.h fix typo --- include/assimp/fast_atof.h | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/include/assimp/fast_atof.h b/include/assimp/fast_atof.h index 9c40a1646..fced5307a 100644 --- a/include/assimp/fast_atof.h +++ b/include/assimp/fast_atof.h @@ -26,15 +26,13 @@ #include "StringComparison.h" #include - #ifdef _MSC_VER # include #else # include #endif -namespace Assimp -{ +namespace Assimp { const double fast_atof_table[16] = { // we write [16] here instead of [] to work around a swig bug 0.0, @@ -64,8 +62,9 @@ unsigned int strtoul10( const char* in, const char** out=0) { unsigned int value = 0; for ( ;; ) { - if ( *in < '0' || *in > '9' ) + if ( *in < '0' || *in > '9' ) { break; + } value = ( value * 10 ) + ( *in - '0' ); ++in; @@ -109,8 +108,7 @@ unsigned int strtoul16( const char* in, const char** out=0) { value = ( value << 4u ) + ( *in - 'A' ) + 10; } else if (*in >= 'a' && *in <= 'f') { value = ( value << 4u ) + ( *in - 'a' ) + 10; - } - else { + } else { break; } ++in; @@ -258,7 +256,7 @@ int64_t strtol10_64(const char* in, const char** out = 0, unsigned int* max_inou //! about 6 times faster than atof in win32. // If you find any bugs, please send them to me, niko (at) irrlicht3d.org. // ------------------------------------------------------------------------------------ -template +template inline const char* fast_atoreal_move(const char* c, Real& out, bool check_comma = true) { Real f = 0; @@ -284,10 +282,10 @@ const char* fast_atoreal_move(const char* c, Real& out, bool check_comma = true) c += 5; } return c; - + } if (!(c[0] >= '0' && c[0] <= '9') && - !((c[0] == '.' || (check_comma && c[0] == ',')) && c[1] >= '0' && c[1] <= '9')){ + !((c[0] == '.' || (check_comma && c[0] == ',')) && c[1] >= '0' && c[1] <= '9')) { throw std::invalid_argument("Cannot parse string " "as real number: does not start with digit " "or decimal point followed by digit."); @@ -322,7 +320,6 @@ const char* fast_atoreal_move(const char* c, Real& out, bool check_comma = true) // A major 'E' must be allowed. Necessary for proper reading of some DXF files. // Thanks to Zhao Lei to point out that this if() must be outside the if (*c == '.' ..) if (*c == 'e' || *c == 'E') { - ++c; const bool einv = (*c=='-'); if (einv || *c=='+') { From 375dd4c1793f9d4d0caa49d8a8b75994b6af0aa9 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Fri, 23 Feb 2018 20:34:34 +0100 Subject: [PATCH 22/22] Update D3MFImporter.cpp Fix order of init list. --- code/D3MFImporter.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/code/D3MFImporter.cpp b/code/D3MFImporter.cpp index 489926204..fe5e260a4 100644 --- a/code/D3MFImporter.cpp +++ b/code/D3MFImporter.cpp @@ -71,9 +71,9 @@ namespace D3MF { class XmlSerializer { public: XmlSerializer(XmlReader* xmlReader) - : xmlReader(xmlReader) - , mMeshes() - , mMaterials() { + : mMeshes() + , mMaterials() + , xmlReader(xmlReader){ // empty }