From c571b92dd7b770e3bdbe7a219f682be255c5f308 Mon Sep 17 00:00:00 2001 From: Paul Holland Date: Thu, 28 Jan 2016 08:06:52 -0800 Subject: [PATCH 001/119] bug fix --- .../openddlparser/include/openddlparser/OpenDDLParserUtils.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/openddlparser/include/openddlparser/OpenDDLParserUtils.h b/contrib/openddlparser/include/openddlparser/OpenDDLParserUtils.h index 635dfd8f7..8245f15b6 100644 --- a/contrib/openddlparser/include/openddlparser/OpenDDLParserUtils.h +++ b/contrib/openddlparser/include/openddlparser/OpenDDLParserUtils.h @@ -243,7 +243,7 @@ bool isComment( T *in, T *end ) { if ( in+1!=end ) { if ( *( in+1 )=='/' ) { char *drive( ( in+2 ) ); - if ( isUpperCase( *drive )||isLowerCase( *drive )&&*( drive+1 )=='/' ) { + if ( (isUpperCase( *drive )||isLowerCase( *drive ))&&*( drive+1 )=='/' ) { return false; } else { return true; From f20a5afcf06a467b5a5a884d4bcfd38dc9c6bb32 Mon Sep 17 00:00:00 2001 From: Paul Holland Date: Thu, 18 Feb 2016 12:17:47 -0800 Subject: [PATCH 002/119] can't add integer to string pointer --- code/ColladaParser.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/ColladaParser.cpp b/code/ColladaParser.cpp index f52ec677a..f620f7acb 100644 --- a/code/ColladaParser.cpp +++ b/code/ColladaParser.cpp @@ -297,7 +297,7 @@ void ColladaParser::ReadAnimationClipLibrary() else if (indexID >= 0) animName = mReader->getAttributeValue(indexID); else - animName = "animation_" + mAnimationClipLibrary.size(); + animName = std::string("animation_") + std::to_string(mAnimationClipLibrary.size()); std::pair > clip; From 2496e8a0a385e6d3c92a53601d1e9106ba06e9a2 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sun, 28 Feb 2016 17:30:11 +0100 Subject: [PATCH 003/119] Lib: reduce number of header files included. --- code/ASEParser.h | 6 ++--- code/BlenderModifier.h | 5 ++-- code/BlenderScene.h | 2 +- code/BlenderSceneGen.h | 3 +-- code/BlenderTessellator.h | 2 +- code/FBXConverter.h | 2 +- code/FBXDocument.h | 54 +++++++++++++++------------------------ code/FBXParser.h | 7 ----- code/FBXProperties.h | 1 - 9 files changed, 31 insertions(+), 51 deletions(-) diff --git a/code/ASEParser.h b/code/ASEParser.h index 6a3e56e71..b4eab6e86 100644 --- a/code/ASEParser.h +++ b/code/ASEParser.h @@ -44,9 +44,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define AI_ASEFILEHELPER_H_INC // STL/CRT headers -#include -#include -#include +//#include +//#include +//#include // public ASSIMP headers #include "../include/assimp/types.h" diff --git a/code/BlenderModifier.h b/code/BlenderModifier.h index c9b62692b..1d176756e 100644 --- a/code/BlenderModifier.h +++ b/code/BlenderModifier.h @@ -46,8 +46,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "BlenderIntermediate.h" #include "TinyFormatter.h" + namespace Assimp { - namespace Blender { +namespace Blender { // ------------------------------------------------------------------------------------------- /** Dummy base class for all blender modifiers. Modifiers are reused between imports, so @@ -56,8 +57,8 @@ namespace Assimp { class BlenderModifier { public: - virtual ~BlenderModifier() { + // empty } public: diff --git a/code/BlenderScene.h b/code/BlenderScene.h index 0af1f3912..c7d5f7eb7 100644 --- a/code/BlenderScene.h +++ b/code/BlenderScene.h @@ -47,7 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "BlenderDNA.h" namespace Assimp { - namespace Blender { +namespace Blender { // Minor parts of this file are extracts from blender data structures, // declared in the ./source/blender/makesdna directory. diff --git a/code/BlenderSceneGen.h b/code/BlenderSceneGen.h index fd7aeed0b..73eb1f927 100644 --- a/code/BlenderSceneGen.h +++ b/code/BlenderSceneGen.h @@ -48,8 +48,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "BlenderScene.h" namespace Assimp { - namespace Blender { - +namespace Blender { template <> void Structure :: Convert ( Object& dest, diff --git a/code/BlenderTessellator.h b/code/BlenderTessellator.h index d3e675e99..530bd2c3e 100644 --- a/code/BlenderTessellator.h +++ b/code/BlenderTessellator.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2013, assimp team +Copyright (c) 2006-2016, assimp team All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/FBXConverter.h b/code/FBXConverter.h index 2e38c3a8a..a69c05e41 100644 --- a/code/FBXConverter.h +++ b/code/FBXConverter.h @@ -49,7 +49,7 @@ struct aiScene; namespace Assimp { namespace FBX { - class Document; +class Document; /** Convert a FBX #Document to #aiScene diff --git a/code/FBXDocument.h b/code/FBXDocument.h index 994797d74..f8e959648 100644 --- a/code/FBXDocument.h +++ b/code/FBXDocument.h @@ -44,16 +44,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef INCLUDED_AI_FBX_DOCUMENT_H #define INCLUDED_AI_FBX_DOCUMENT_H -#include -#include -#include -#include #include -#include -#include "../include/assimp/ai_assert.h" -#include "../include/assimp/vector3.h" -#include "../include/assimp/vector2.h" -#include "../include/assimp/color4.h" #include "../include/assimp/mesh.h" #include "FBXProperties.h" #include "FBXParser.h" @@ -179,7 +170,7 @@ class NodeAttribute : public Object public: NodeAttribute(uint64_t id, const Element& element, const Document& doc, const std::string& name); - ~NodeAttribute(); + virtual ~NodeAttribute(); public: @@ -200,7 +191,7 @@ class CameraSwitcher : public NodeAttribute public: CameraSwitcher(uint64_t id, const Element& element, const Document& doc, const std::string& name); - ~CameraSwitcher(); + virtual ~CameraSwitcher(); public: @@ -251,7 +242,7 @@ class Camera : public NodeAttribute public: Camera(uint64_t id, const Element& element, const Document& doc, const std::string& name); - ~Camera(); + virtual ~Camera(); public: @@ -280,7 +271,7 @@ class Null : public NodeAttribute public: Null(uint64_t id, const Element& element, const Document& doc, const std::string& name); - ~Null(); + virtual ~Null(); }; @@ -290,7 +281,7 @@ class LimbNode : public NodeAttribute public: LimbNode(uint64_t id, const Element& element, const Document& doc, const std::string& name); - ~LimbNode(); + virtual ~LimbNode(); }; @@ -298,9 +289,8 @@ public: class Light : public NodeAttribute { public: - Light(uint64_t id, const Element& element, const Document& doc, const std::string& name); - ~Light(); + virtual ~Light(); public: @@ -370,7 +360,7 @@ class Model : public Object public: Model(uint64_t id, const Element& element, const Document& doc, const std::string& name); - ~Model(); + virtual ~Model(); public: @@ -535,7 +525,7 @@ class Texture : public Object public: Texture(uint64_t id, const Element& element, const Document& doc, const std::string& name); - ~Texture(); + virtual ~Texture(); public: @@ -599,7 +589,7 @@ class LayeredTexture : public Object public: LayeredTexture(uint64_t id, const Element& element, const Document& doc, const std::string& name); - ~LayeredTexture(); + virtual ~LayeredTexture(); //Can only be called after construction of the layered texture object due to construction flag. void fillTexture(const Document& doc); @@ -668,7 +658,7 @@ class Video : public Object public: Video(uint64_t id, const Element& element, const Document& doc, const std::string& name); - ~Video(); + virtual ~Video(); public: @@ -721,7 +711,7 @@ class Material : public Object public: Material(uint64_t id, const Element& element, const Document& doc, const std::string& name); - ~Material(); + virtual ~Material(); public: @@ -763,7 +753,7 @@ class Geometry : public Object public: Geometry(uint64_t id, const Element& element, const std::string& name, const Document& doc); - ~Geometry(); + virtual ~Geometry(); public: @@ -788,7 +778,7 @@ class MeshGeometry : public Geometry public: MeshGeometry(uint64_t id, const Element& element, const std::string& name, const Document& doc); - ~MeshGeometry(); + virtual ~MeshGeometry(); public: @@ -891,8 +881,6 @@ public: return static_cast(std::distance(facesVertexStartIndices.begin(), it - 1)); } -public: - private: void ReadLayer(const Scope& layer); @@ -952,7 +940,7 @@ class AnimationCurve : public Object public: AnimationCurve(uint64_t id, const Element& element, const std::string& name, const Document& doc); - ~AnimationCurve(); + virtual ~AnimationCurve(); public: @@ -995,13 +983,13 @@ class AnimationCurveNode : public Object { public: - /* the optional whitelist specifies a list of property names for which the caller + /* the optional white list specifies a list of property names for which the caller wants animations for. If the curve node does not match one of these, std::range_error will be thrown. */ AnimationCurveNode(uint64_t id, const Element& element, const std::string& name, const Document& doc, const char* const * target_prop_whitelist = NULL, size_t whitelist_size = 0); - ~AnimationCurveNode(); + virtual ~AnimationCurveNode(); public: @@ -1053,7 +1041,7 @@ public: AnimationLayer(uint64_t id, const Element& element, const std::string& name, const Document& doc); - ~AnimationLayer(); + virtual ~AnimationLayer(); public: @@ -1062,7 +1050,7 @@ public: return *props.get(); } - /* the optional whitelist specifies a list of property names for which the caller + /* the optional white list specifies a list of property names for which the caller wants animations for. Curves not matching this list will not be added to the animation layer. */ AnimationCurveNodeList Nodes(const char* const * target_prop_whitelist = NULL, size_t whitelist_size = 0) const; @@ -1083,7 +1071,7 @@ class AnimationStack : public Object public: AnimationStack(uint64_t id, const Element& element, const std::string& name, const Document& doc); - ~AnimationStack(); + virtual ~AnimationStack(); public: @@ -1117,7 +1105,7 @@ class Deformer : public Object public: Deformer(uint64_t id, const Element& element, const Document& doc, const std::string& name); - ~Deformer(); + virtual ~Deformer(); public: @@ -1191,7 +1179,7 @@ class Skin : public Deformer public: Skin(uint64_t id, const Element& element, const Document& doc, const std::string& name); - ~Skin(); + virtual ~Skin(); public: diff --git a/code/FBXParser.h b/code/FBXParser.h index e72a92611..f0f0db9b6 100644 --- a/code/FBXParser.h +++ b/code/FBXParser.h @@ -44,13 +44,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef INCLUDED_AI_FBX_PARSER_H #define INCLUDED_AI_FBX_PARSER_H -#include -#include -#include -#include -#include - -#include #include #include "LogAux.h" diff --git a/code/FBXProperties.h b/code/FBXProperties.h index 0346e9b31..fbaa229a1 100644 --- a/code/FBXProperties.h +++ b/code/FBXProperties.h @@ -45,7 +45,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define INCLUDED_AI_FBX_PROPERTIES_H #include -#include #include "FBXCompileConfig.h" #include From 28d327b7eaaa0864861301d939bde93db1ed8bb6 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sun, 28 Feb 2016 20:27:31 +0100 Subject: [PATCH 004/119] FBXImporter: fix build. --- code/ASEParser.h | 5 ----- code/FBXDocument.h | 1 + code/FBXParser.h | 1 + 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/code/ASEParser.h b/code/ASEParser.h index b4eab6e86..e962ea15e 100644 --- a/code/ASEParser.h +++ b/code/ASEParser.h @@ -43,11 +43,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef AI_ASEFILEHELPER_H_INC #define AI_ASEFILEHELPER_H_INC -// STL/CRT headers -//#include -//#include -//#include - // public ASSIMP headers #include "../include/assimp/types.h" #include "../include/assimp/mesh.h" diff --git a/code/FBXDocument.h b/code/FBXDocument.h index f8e959648..126a96820 100644 --- a/code/FBXDocument.h +++ b/code/FBXDocument.h @@ -45,6 +45,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define INCLUDED_AI_FBX_DOCUMENT_H #include +#include #include "../include/assimp/mesh.h" #include "FBXProperties.h" #include "FBXParser.h" diff --git a/code/FBXParser.h b/code/FBXParser.h index f0f0db9b6..0a39bd24d 100644 --- a/code/FBXParser.h +++ b/code/FBXParser.h @@ -44,6 +44,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef INCLUDED_AI_FBX_PARSER_H #define INCLUDED_AI_FBX_PARSER_H +#include #include #include "LogAux.h" From e9f47b08c59096e3da133f03a1c7a51a9234c005 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sun, 28 Feb 2016 20:56:11 +0100 Subject: [PATCH 005/119] FBXImporter: fx build. --- code/FBXParser.h | 1 + 1 file changed, 1 insertion(+) diff --git a/code/FBXParser.h b/code/FBXParser.h index 0a39bd24d..4f165c13f 100644 --- a/code/FBXParser.h +++ b/code/FBXParser.h @@ -45,6 +45,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define INCLUDED_AI_FBX_PARSER_H #include +#include #include #include "LogAux.h" From 3079b90622b87cb7061562a85799025eead4bcb6 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Mon, 29 Feb 2016 15:57:47 +0100 Subject: [PATCH 006/119] Importer: when the right importer was found log this info. --- code/FBXImporter.cpp | 2 +- code/Importer.cpp | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/code/FBXImporter.cpp b/code/FBXImporter.cpp index a8ebc3e61..48fd854ea 100644 --- a/code/FBXImporter.cpp +++ b/code/FBXImporter.cpp @@ -12,7 +12,7 @@ following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - +r * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other diff --git a/code/Importer.cpp b/code/Importer.cpp index b0325570f..b7a4cb555 100644 --- a/code/Importer.cpp +++ b/code/Importer.cpp @@ -658,7 +658,12 @@ const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags) } // Dispatch the reading to the worker class for this format - DefaultLogger::get()->info("Found a matching importer for this file format"); + const aiImporterDesc *desc( imp->GetInfo() ); + std::string ext( "unknown" ); + if ( NULL != desc ) { + ext = desc->mName; + } + DefaultLogger::get()->info("Found a matching importer for this file format: " + ext + "." ); pimpl->mProgressHandler->UpdateFileRead( 0, fileSize ); if (profiler) { From 17f0e09bd1bc54444c901fc40b128fbb18a567d7 Mon Sep 17 00:00:00 2001 From: Thiago Goulart Date: Wed, 2 Mar 2016 00:07:17 -0800 Subject: [PATCH 007/119] Fix warning when compiling using -Wswitch-enum --- include/assimp/metadata.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/assimp/metadata.h b/include/assimp/metadata.h index 47a8392a0..814d89272 100644 --- a/include/assimp/metadata.h +++ b/include/assimp/metadata.h @@ -177,6 +177,9 @@ struct aiMetadata case AI_AIVECTOR3D: delete static_cast(data); break; +#ifndef SWIG + case FORCE_32BIT: +#endif default: assert(false); break; From 2b09199f4a34b2fa9137e161e174e519656d3ceb Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Thu, 3 Mar 2016 15:19:38 +0100 Subject: [PATCH 008/119] FBXImporter: move MeshGeometry declaration into its own header --- code/CMakeLists.txt | 1 + code/FBXConverter.cpp | 17 +- code/FBXDocument.cpp | 17 +- code/FBXDocument.h | 341 ++++----------------------------------- code/FBXImporter.h | 21 +-- code/FBXMeshGeometry.cpp | 89 +++++++++- code/FBXMeshGeometry.h | 180 +++++++++++++++++++++ code/FBXModel.cpp | 1 + code/FBXParser.cpp | 25 ++- code/FBXParser.h | 18 +-- 10 files changed, 352 insertions(+), 358 deletions(-) create mode 100644 code/FBXMeshGeometry.h diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index 5088d5433..30aa19772 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -446,6 +446,7 @@ ADD_ASSIMP_IMPORTER(FBX FBXDocument.cpp FBXProperties.h FBXProperties.cpp + FBXMeshGeometry.h FBXMeshGeometry.cpp FBXMaterial.cpp FBXModel.cpp diff --git a/code/FBXConverter.cpp b/code/FBXConverter.cpp index c1a816dd8..289a84ac6 100644 --- a/code/FBXConverter.cpp +++ b/code/FBXConverter.cpp @@ -44,18 +44,20 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef ASSIMP_BUILD_NO_FBX_IMPORTER -#include -#include -#include -#include -#include "FBXParser.h" #include "FBXConverter.h" +#include "FBXParser.h" +#include "FBXMeshGeometry.h" #include "FBXDocument.h" #include "FBXUtil.h" #include "FBXProperties.h" #include "FBXImporter.h" #include "StringComparison.h" + #include "../include/assimp/scene.h" +#include +#include +#include +#include #include #include @@ -63,7 +65,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. namespace Assimp { namespace FBX { - using namespace Util; +using namespace Util; #define MAGIC_NODE_TAG "_$AssimpFbx$" @@ -154,7 +156,6 @@ public: private: - // ------------------------------------------------------------------------------------------------ // find scene root and trigger recursive scene conversion void ConvertRootNode() @@ -385,6 +386,7 @@ private: out_camera->mAspect = cam.AspectWidth() / cam.AspectHeight(); out_camera->mPosition = cam.Position(); + out_camera->mUp = cam.UpVector(); out_camera->mLookAt = cam.InterestPosition() - out_camera->mPosition; out_camera->mHorizontalFOV = AI_DEG_TO_RAD(cam.FieldOfView()); } @@ -426,6 +428,7 @@ private: case TransformationComp_GeometricTranslation: return "GeometricTranslation"; case TransformationComp_MAXIMUM: // this is to silence compiler warnings + default: break; } diff --git a/code/FBXDocument.cpp b/code/FBXDocument.cpp index b59527611..1e9ea6f3c 100644 --- a/code/FBXDocument.cpp +++ b/code/FBXDocument.cpp @@ -44,17 +44,19 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef ASSIMP_BUILD_NO_FBX_IMPORTER -#include - -#include "FBXParser.h" #include "FBXDocument.h" +#include "FBXMeshGeometry.h" +#include "FBXParser.h" #include "FBXUtil.h" #include "FBXImporter.h" #include "FBXImportSettings.h" #include "FBXDocumentUtil.h" #include "FBXProperties.h" + #include #include +#include + namespace Assimp { namespace FBX { @@ -135,6 +137,8 @@ const Object* LazyObject::Get(bool dieOnError) // so avoid constructing strings all the time. const char* obtype = key.begin(); const size_t length = static_cast(key.end()-key.begin()); + DefaultLogger::get()->debug( "obtype: " + std::string(obtype )); + DefaultLogger::get()->debug( "Classtag: " + classtag ); if (!strncmp(obtype,"Geometry",length)) { if (!strcmp(classtag.c_str(),"Mesh")) { object.reset(new MeshGeometry(id,element,name,doc)); @@ -165,10 +169,10 @@ const Object* LazyObject::Get(bool dieOnError) object.reset(new Skin(id,element,doc,name)); } } - else if (!strncmp(obtype,"Model",length)) { + else if ( !strncmp( obtype, "Model", length ) ) { // FK and IK effectors are not supported - if (strcmp(classtag.c_str(),"IKEffector") && strcmp(classtag.c_str(),"FKEffector")) { - object.reset(new Model(id,element,doc,name)); + if ( strcmp( classtag.c_str(), "IKEffector" ) && strcmp( classtag.c_str(), "FKEffector" ) ) { + object.reset( new Model( id, element, doc, name ) ); } } else if (!strncmp(obtype,"Material",length)) { @@ -408,7 +412,6 @@ void Document::ReadObjects() } } - // ------------------------------------------------------------------------------------------------ void Document::ReadPropertyTemplates() { diff --git a/code/FBXDocument.h b/code/FBXDocument.h index 126a96820..f74348ab5 100644 --- a/code/FBXDocument.h +++ b/code/FBXDocument.h @@ -56,24 +56,24 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. namespace Assimp { namespace FBX { - class Parser; - class Object; - struct ImportSettings; +class Parser; +class Object; +struct ImportSettings; - class PropertyTable; - class Document; - class Material; - class Geometry; +class PropertyTable; +class Document; +class Material; +class Geometry; - class Video; +class Video; - class AnimationCurve; - class AnimationCurveNode; - class AnimationLayer; - class AnimationStack; +class AnimationCurve; +class AnimationCurveNode; +class AnimationLayer; +class AnimationStack; - class Skin; - class Cluster; +class Skin; +class Cluster; /** Represents a delay-parsed FBX objects. Many objects in the scene @@ -82,7 +82,6 @@ namespace FBX { class LazyObject { public: - LazyObject(uint64_t id, const Element& element, const Document& doc); ~LazyObject(); @@ -117,7 +116,6 @@ public: } private: - const Document& doc; const Element& element; boost::scoped_ptr object; @@ -138,11 +136,9 @@ private: class Object { public: - Object(uint64_t id, const Element& element, const std::string& name); - virtual ~Object(); -public: + virtual ~Object(); const Element& SourceElement() const { return element; @@ -169,19 +165,15 @@ protected: class NodeAttribute : public Object { public: - NodeAttribute(uint64_t id, const Element& element, const Document& doc, const std::string& name); virtual ~NodeAttribute(); -public: - const PropertyTable& Props() const { ai_assert(props.get()); return *props.get(); } private: - boost::shared_ptr props; }; @@ -190,12 +182,9 @@ private: class CameraSwitcher : public NodeAttribute { public: - CameraSwitcher(uint64_t id, const Element& element, const Document& doc, const std::string& name); virtual ~CameraSwitcher(); -public: - int CameraID() const { return cameraId; } @@ -204,13 +193,11 @@ public: return cameraName; } - const std::string& CameraIndexName() const { return cameraIndexName; } private: - int cameraId; std::string cameraName; std::string cameraIndexName; @@ -236,17 +223,14 @@ private: } - /** DOM base class for FBX cameras attached to a node */ class Camera : public NodeAttribute { public: - Camera(uint64_t id, const Element& element, const Document& doc, const std::string& name); virtual ~Camera(); public: - fbx_simple_property(Position, aiVector3D, aiVector3D(0,0,0)) fbx_simple_property(UpVector, aiVector3D, aiVector3D(0,1,0)) fbx_simple_property(InterestPosition, aiVector3D, aiVector3D(0,0,0)) @@ -261,8 +245,6 @@ public: fbx_simple_property(FieldOfView, float, 1.0f) fbx_simple_property(FocalLength, float, 1.0f) - -private: }; @@ -270,7 +252,6 @@ private: class Null : public NodeAttribute { public: - Null(uint64_t id, const Element& element, const Document& doc, const std::string& name); virtual ~Null(); }; @@ -280,7 +261,6 @@ public: class LimbNode : public NodeAttribute { public: - LimbNode(uint64_t id, const Element& element, const Document& doc, const std::string& name); virtual ~LimbNode(); }; @@ -294,7 +274,6 @@ public: virtual ~Light(); public: - enum Type { Type_Point, @@ -317,7 +296,6 @@ public: }; public: - fbx_simple_property(Color, aiVector3D, aiVector3D(1,1,1)) fbx_simple_enum_property(LightType, Type, 0) fbx_simple_property(CastLightOnObject, bool, false) @@ -349,9 +327,6 @@ public: fbx_simple_property(TopBarnDoor, float, 20.0f) fbx_simple_property(BottomBarnDoor, float, 20.0f) fbx_simple_property(EnableBarnDoor, bool, true) - - -private: }; @@ -359,12 +334,10 @@ private: class Model : public Object { public: - Model(uint64_t id, const Element& element, const Document& doc, const std::string& name); virtual ~Model(); public: - enum RotOrder { RotOrder_EulerXYZ = 0, @@ -390,7 +363,6 @@ public: }; public: - fbx_simple_property(QuaternionInterpolate, int, 0) fbx_simple_property(RotationOffset, aiVector3D, aiVector3D()) @@ -468,7 +440,6 @@ public: fbx_simple_property(Freeze, bool, false) public: - const std::string& Shading() const { return shading; } @@ -499,18 +470,14 @@ public: return attributes; } -public: - /** convenience method to check if the node has a Null node marker */ bool IsNull() const; private: - void ResolveLinks(const Element& element, const Document& doc); private: - std::vector materials; std::vector geometry; std::vector attributes; @@ -524,12 +491,10 @@ private: class Texture : public Object { public: - Texture(uint64_t id, const Element& element, const Document& doc, const std::string& name); virtual ~Texture(); public: - const std::string& Type() const { return type; } @@ -569,7 +534,6 @@ public: } private: - aiVector2D uvTrans; aiVector2D uvScaling; @@ -588,7 +552,6 @@ private: class LayeredTexture : public Object { public: - LayeredTexture(uint64_t id, const Element& element, const Document& doc, const std::string& name); virtual ~LayeredTexture(); @@ -635,14 +598,17 @@ public: { return texture; } + BlendMode GetBlendMode() { return blendMode; } + float Alpha() { return alpha; } + private: const Texture* texture; BlendMode blendMode; @@ -657,12 +623,10 @@ typedef std::fbx_unordered_map LayeredTextur class Video : public Object { public: - Video(uint64_t id, const Element& element, const Document& doc, const std::string& name); virtual ~Video(); public: - const std::string& Type() const { return type; } @@ -696,7 +660,6 @@ public: } private: - std::string type; std::string relativeFileName; std::string fileName; @@ -710,12 +673,9 @@ private: class Material : public Object { public: - Material(uint64_t id, const Element& element, const Document& doc, const std::string& name); virtual ~Material(); -public: - const std::string& GetShadingModel() const { return shading; } @@ -738,7 +698,6 @@ public: } private: - std::string shading; bool multilayer; boost::shared_ptr props; @@ -747,191 +706,6 @@ private: LayeredTextureMap layeredTextures; }; - -/** DOM base class for all kinds of FBX geometry */ -class Geometry : public Object -{ -public: - - Geometry(uint64_t id, const Element& element, const std::string& name, const Document& doc); - virtual ~Geometry(); - -public: - - /** Get the Skin attached to this geometry or NULL */ - const Skin* DeformerSkin() const { - return skin; - } - -private: - - const Skin* skin; -}; - - -typedef std::vector MatIndexArray; - - -/** DOM class for FBX geometry of type "Mesh"*/ -class MeshGeometry : public Geometry -{ - -public: - - MeshGeometry(uint64_t id, const Element& element, const std::string& name, const Document& doc); - virtual ~MeshGeometry(); - -public: - - /** Get a list of all vertex points, non-unique*/ - const std::vector& GetVertices() const { - return vertices; - } - - /** Get a list of all vertex normals or an empty array if - * no normals are specified. */ - const std::vector& GetNormals() const { - return normals; - } - - /** Get a list of all vertex tangents or an empty array - * if no tangents are specified */ - const std::vector& GetTangents() const { - return tangents; - } - - /** Get a list of all vertex binormals or an empty array - * if no binormals are specified */ - const std::vector& GetBinormals() const { - return binormals; - } - - /** Return list of faces - each entry denotes a face and specifies - * how many vertices it has. Vertices are taken from the - * vertex data arrays in sequential order. */ - const std::vector& GetFaceIndexCounts() const { - return faces; - } - - /** Get a UV coordinate slot, returns an empty array if - * the requested slot does not exist. */ - const std::vector& GetTextureCoords(unsigned int index) const { - static const std::vector empty; - return index >= AI_MAX_NUMBER_OF_TEXTURECOORDS ? empty : uvs[index]; - } - - - /** Get a UV coordinate slot, returns an empty array if - * the requested slot does not exist. */ - std::string GetTextureCoordChannelName(unsigned int index) const { - return index >= AI_MAX_NUMBER_OF_TEXTURECOORDS ? "" : uvNames[index]; - } - - /** Get a vertex color coordinate slot, returns an empty array if - * the requested slot does not exist. */ - const std::vector& GetVertexColors(unsigned int index) const { - static const std::vector empty; - return index >= AI_MAX_NUMBER_OF_COLOR_SETS ? empty : colors[index]; - } - - - /** Get per-face-vertex material assignments */ - const MatIndexArray& GetMaterialIndices() const { - return materials; - } - - - /** Convert from a fbx file vertex index (for example from a #Cluster weight) or NULL - * if the vertex index is not valid. */ - const unsigned int* ToOutputVertexIndex(unsigned int in_index, unsigned int& count) const { - if(in_index >= mapping_counts.size()) { - return NULL; - } - - ai_assert(mapping_counts.size() == mapping_offsets.size()); - count = mapping_counts[in_index]; - - ai_assert(count != 0); - ai_assert(mapping_offsets[in_index] + count <= mappings.size()); - - return &mappings[mapping_offsets[in_index]]; - } - - - /** Determine the face to which a particular output vertex index belongs. - * This mapping is always unique. */ - unsigned int FaceForVertexIndex(unsigned int in_index) const { - ai_assert(in_index < vertices.size()); - - // in the current conversion pattern this will only be needed if - // weights are present, so no need to always pre-compute this table - if (facesVertexStartIndices.empty()) { - facesVertexStartIndices.resize(faces.size() + 1, 0); - - std::partial_sum(faces.begin(), faces.end(), facesVertexStartIndices.begin() + 1); - facesVertexStartIndices.pop_back(); - } - - ai_assert(facesVertexStartIndices.size() == faces.size()); - const std::vector::iterator it = std::upper_bound( - facesVertexStartIndices.begin(), - facesVertexStartIndices.end(), - in_index - ); - - return static_cast(std::distance(facesVertexStartIndices.begin(), it - 1)); - } - -private: - - void ReadLayer(const Scope& layer); - void ReadLayerElement(const Scope& layerElement); - void ReadVertexData(const std::string& type, int index, const Scope& source); - - void ReadVertexDataUV(std::vector& uv_out, const Scope& source, - const std::string& MappingInformationType, - const std::string& ReferenceInformationType); - - void ReadVertexDataNormals(std::vector& normals_out, const Scope& source, - const std::string& MappingInformationType, - const std::string& ReferenceInformationType); - - void ReadVertexDataColors(std::vector& colors_out, const Scope& source, - const std::string& MappingInformationType, - const std::string& ReferenceInformationType); - - void ReadVertexDataTangents(std::vector& tangents_out, const Scope& source, - const std::string& MappingInformationType, - const std::string& ReferenceInformationType); - - void ReadVertexDataBinormals(std::vector& binormals_out, const Scope& source, - const std::string& MappingInformationType, - const std::string& ReferenceInformationType); - - void ReadVertexDataMaterials(MatIndexArray& materials_out, const Scope& source, - const std::string& MappingInformationType, - const std::string& ReferenceInformationType); - -private: - - // cached data arrays - MatIndexArray materials; - std::vector vertices; - std::vector faces; - mutable std::vector facesVertexStartIndices; - std::vector tangents; - std::vector binormals; - std::vector normals; - - std::string uvNames[AI_MAX_NUMBER_OF_TEXTURECOORDS]; - std::vector uvs[AI_MAX_NUMBER_OF_TEXTURECOORDS]; - std::vector colors[AI_MAX_NUMBER_OF_COLOR_SETS]; - - std::vector mapping_counts; - std::vector mapping_offsets; - std::vector mappings; -}; - typedef std::vector KeyTimeList; typedef std::vector KeyValueList; @@ -939,12 +713,9 @@ typedef std::vector KeyValueList; class AnimationCurve : public Object { public: - AnimationCurve(uint64_t id, const Element& element, const std::string& name, const Document& doc); virtual ~AnimationCurve(); -public: - /** get list of keyframe positions (time). * Invariant: |GetKeys()| > 0 */ const KeyTimeList& GetKeys() const { @@ -968,7 +739,6 @@ public: } private: - KeyTimeList keys; KeyValueList values; std::vector attributes; @@ -983,7 +753,6 @@ typedef std::map AnimationCurveMap; class AnimationCurveNode : public Object { public: - /* the optional white list specifies a list of property names for which the caller wants animations for. If the curve node does not match one of these, std::range_error will be thrown. */ @@ -992,8 +761,6 @@ public: virtual ~AnimationCurveNode(); -public: - const PropertyTable& Props() const { ai_assert(props.get()); return *props.get(); @@ -1023,7 +790,6 @@ public: } private: - const Object* target; boost::shared_ptr props; mutable AnimationCurveMap curves; @@ -1039,13 +805,9 @@ typedef std::vector AnimationCurveNodeList; class AnimationLayer : public Object { public: - - AnimationLayer(uint64_t id, const Element& element, const std::string& name, const Document& doc); virtual ~AnimationLayer(); -public: - const PropertyTable& Props() const { ai_assert(props.get()); return *props.get(); @@ -1057,7 +819,6 @@ public: AnimationCurveNodeList Nodes(const char* const * target_prop_whitelist = NULL, size_t whitelist_size = 0) const; private: - boost::shared_ptr props; const Document& doc; }; @@ -1070,31 +831,25 @@ typedef std::vector AnimationLayerList; class AnimationStack : public Object { public: - AnimationStack(uint64_t id, const Element& element, const std::string& name, const Document& doc); virtual ~AnimationStack(); public: - fbx_simple_property(LocalStart, int64_t, 0L) fbx_simple_property(LocalStop, int64_t, 0L) fbx_simple_property(ReferenceStart, int64_t, 0L) fbx_simple_property(ReferenceStop, int64_t, 0L) - - const PropertyTable& Props() const { ai_assert(props.get()); return *props.get(); } - const AnimationLayerList& Layers() const { return layers; } private: - boost::shared_ptr props; AnimationLayerList layers; }; @@ -1104,19 +859,15 @@ private: class Deformer : public Object { public: - Deformer(uint64_t id, const Element& element, const Document& doc, const std::string& name); virtual ~Deformer(); -public: - const PropertyTable& Props() const { ai_assert(props.get()); return *props.get(); } private: - boost::shared_ptr props; }; @@ -1128,11 +879,8 @@ typedef std::vector WeightIndexArray; class Cluster : public Deformer { public: - Cluster(uint64_t id, const Element& element, const Document& doc, const std::string& name); - ~Cluster(); - -public: + virtual ~Cluster(); /** get the list of deformer weights associated with this cluster. * Use #GetIndices() to get the associated vertices. Both arrays @@ -1162,7 +910,6 @@ public: } private: - WeightArray weights; WeightIndexArray indices; @@ -1178,34 +925,26 @@ private: class Skin : public Deformer { public: - Skin(uint64_t id, const Element& element, const Document& doc, const std::string& name); virtual ~Skin(); -public: - float DeformAccuracy() const { return accuracy; } - const std::vector& Clusters() const { return clusters; } private: - float accuracy; std::vector clusters; }; - - /** Represents a link between two FBX objects. */ class Connection { public: - Connection(uint64_t insertionOrder, uint64_t src, uint64_t dest, const std::string& prop, const Document& doc); ~Connection(); @@ -1231,6 +970,8 @@ public: } int CompareTo(const Connection* c) const { + ai_assert( NULL != c ); + // note: can't subtract because this would overflow uint64_t if(InsertionOrder() > c->InsertionOrder()) { return 1; @@ -1242,11 +983,12 @@ public: } bool Compare(const Connection* c) const { + ai_assert( NULL != c ); + return InsertionOrder() < c->InsertionOrder(); } public: - uint64_t insertionOrder; const std::string prop; @@ -1254,17 +996,16 @@ public: const Document& doc; }; - - // XXX again, unique_ptr would be useful. shared_ptr is too - // bloated since the objects have a well-defined single owner - // during their entire lifetime (Document). FBX files have - // up to many thousands of objects (most of which we never use), - // so the memory overhead for them should be kept at a minimum. - typedef std::map ObjectMap; - typedef std::fbx_unordered_map > PropertyTemplateMap; +// XXX again, unique_ptr would be useful. shared_ptr is too +// bloated since the objects have a well-defined single owner +// during their entire lifetime (Document). FBX files have +// up to many thousands of objects (most of which we never use), +// so the memory overhead for them should be kept at a minimum. +typedef std::map ObjectMap; +typedef std::fbx_unordered_map > PropertyTemplateMap; - typedef std::multimap ConnectionMap; +typedef std::multimap ConnectionMap; /** DOM class for global document settings, a single instance per document can @@ -1272,12 +1013,9 @@ public: class FileGlobalSettings { public: - FileGlobalSettings(const Document& doc, boost::shared_ptr props); ~FileGlobalSettings(); -public: - const PropertyTable& Props() const { ai_assert(props.get()); return *props.get(); @@ -1287,7 +1025,6 @@ public: return doc; } - fbx_simple_property(UpAxis, int, 1) fbx_simple_property(UpAxisSign, int, 1) fbx_simple_property(FrontAxis, int, 2) @@ -1327,9 +1064,7 @@ public: fbx_simple_property(TimeSpanStop, uint64_t, 0L) fbx_simple_property(CustomFrameRate, float, -1.0f) - private: - boost::shared_ptr props; const Document& doc; }; @@ -1341,12 +1076,9 @@ private: class Document { public: - Document(const Parser& parser, const ImportSettings& settings); ~Document(); -public: - LazyObject* GetObject(uint64_t id) const; bool IsBinary() const { @@ -1361,7 +1093,7 @@ public: return creator; } - // elements (in this order): Uear, Month, Day, Hour, Second, Millisecond + // elements (in this order): Year, Month, Day, Hour, Second, Millisecond const unsigned int* CreationTimeStamp() const { return creationTimeStamp; } @@ -1412,7 +1144,6 @@ public: const std::vector& AnimationStacks() const; private: - std::vector GetConnectionsSequenced(uint64_t id, const ConnectionMap&) const; std::vector GetConnectionsSequenced(uint64_t id, bool is_src, const ConnectionMap&, @@ -1420,7 +1151,6 @@ private: size_t count) const; private: - void ReadHeader(); void ReadObjects(); void ReadPropertyTemplates(); @@ -1428,7 +1158,6 @@ private: void ReadGlobalSettings(); private: - const ImportSettings& settings; ObjectMap objects; @@ -1448,7 +1177,7 @@ private: boost::scoped_ptr globals; }; -} -} +} // Namespace FBX +} // Namespace Assimp -#endif +#endif // INCLUDED_AI_FBX_DOCUMENT_H diff --git a/code/FBXImporter.h b/code/FBXImporter.h index 0c50709fc..350ecfb67 100644 --- a/code/FBXImporter.h +++ b/code/FBXImporter.h @@ -51,12 +51,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. namespace Assimp { - // TinyFormatter.h - namespace Formatter { - template class basic_formatter; - typedef class basic_formatter< char, std::char_traits, std::allocator > format; - } - +// TinyFormatter.h +namespace Formatter { + template class basic_formatter; + typedef class basic_formatter< char, std::char_traits, std::allocator > format; +} // ------------------------------------------------------------------------------------------- /** Load the Autodesk FBX file format. @@ -68,10 +67,7 @@ class FBXImporter : public BaseImporter, public LogFunctions { public: FBXImporter(); - ~FBXImporter(); - - -public: + virtual ~FBXImporter(); // -------------------- bool CanRead( const std::string& pFile, @@ -94,12 +90,7 @@ protected: ); private: - - -private: - FBX::ImportSettings settings; - }; // !class FBXImporter } // end of namespace Assimp diff --git a/code/FBXMeshGeometry.cpp b/code/FBXMeshGeometry.cpp index 28ce924cb..49bdca92a 100644 --- a/code/FBXMeshGeometry.cpp +++ b/code/FBXMeshGeometry.cpp @@ -46,7 +46,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include -#include "FBXParser.h" +#include "FBXMeshGeometry.h" #include "FBXDocument.h" #include "FBXImporter.h" #include "FBXImportSettings.h" @@ -57,8 +57,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. namespace Assimp { namespace FBX { - using namespace Util; - +using namespace Util; // ------------------------------------------------------------------------------------------------ Geometry::Geometry(uint64_t id, const Element& element, const std::string& name, const Document& doc) @@ -82,6 +81,9 @@ Geometry::~Geometry() } +const Skin* Geometry::DeformerSkin() const { + return skin; +} // ------------------------------------------------------------------------------------------------ @@ -182,14 +184,93 @@ MeshGeometry::MeshGeometry(uint64_t id, const Element& element, const std::strin } } - // ------------------------------------------------------------------------------------------------ MeshGeometry::~MeshGeometry() { } +// ------------------------------------------------------------------------------------------------ +const std::vector& MeshGeometry::GetVertices() const { + return vertices; +} +// ------------------------------------------------------------------------------------------------ +const std::vector& MeshGeometry::GetNormals() const { + return normals; +} + +// ------------------------------------------------------------------------------------------------ +const std::vector& MeshGeometry::GetTangents() const { + return tangents; +} + +// ------------------------------------------------------------------------------------------------ +const std::vector& MeshGeometry::GetBinormals() const { + return binormals; +} + +// ------------------------------------------------------------------------------------------------ +const std::vector& MeshGeometry::GetFaceIndexCounts() const { + return faces; +} + +// ------------------------------------------------------------------------------------------------ +const std::vector& MeshGeometry::GetTextureCoords( unsigned int index ) const { + static const std::vector empty; + return index >= AI_MAX_NUMBER_OF_TEXTURECOORDS ? empty : uvs[ index ]; +} + +std::string MeshGeometry::GetTextureCoordChannelName( unsigned int index ) const { + return index >= AI_MAX_NUMBER_OF_TEXTURECOORDS ? "" : uvNames[ index ]; +} + +const std::vector& MeshGeometry::GetVertexColors( unsigned int index ) const { + static const std::vector empty; + return index >= AI_MAX_NUMBER_OF_COLOR_SETS ? empty : colors[ index ]; +} + +const MatIndexArray& MeshGeometry::GetMaterialIndices() const { + return materials; +} + +// ------------------------------------------------------------------------------------------------ +const unsigned int* MeshGeometry::ToOutputVertexIndex( unsigned int in_index, unsigned int& count ) const { + if ( in_index >= mapping_counts.size() ) { + return NULL; + } + + ai_assert( mapping_counts.size() == mapping_offsets.size() ); + count = mapping_counts[ in_index ]; + + ai_assert( count != 0 ); + ai_assert( mapping_offsets[ in_index ] + count <= mappings.size() ); + + return &mappings[ mapping_offsets[ in_index ] ]; +} + +// ------------------------------------------------------------------------------------------------ +unsigned int MeshGeometry::FaceForVertexIndex( unsigned int in_index ) const { + ai_assert( in_index < vertices.size() ); + + // in the current conversion pattern this will only be needed if + // weights are present, so no need to always pre-compute this table + if ( facesVertexStartIndices.empty() ) { + facesVertexStartIndices.resize( faces.size() + 1, 0 ); + + std::partial_sum( faces.begin(), faces.end(), facesVertexStartIndices.begin() + 1 ); + facesVertexStartIndices.pop_back(); + } + + ai_assert( facesVertexStartIndices.size() == faces.size() ); + const std::vector::iterator it = std::upper_bound( + facesVertexStartIndices.begin(), + facesVertexStartIndices.end(), + in_index + ); + + return static_cast< unsigned int >( std::distance( facesVertexStartIndices.begin(), it - 1 ) ); +} // ------------------------------------------------------------------------------------------------ void MeshGeometry::ReadLayer(const Scope& layer) diff --git a/code/FBXMeshGeometry.h b/code/FBXMeshGeometry.h new file mode 100644 index 000000000..48ac550c1 --- /dev/null +++ b/code/FBXMeshGeometry.h @@ -0,0 +1,180 @@ +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2016, assimp team +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ + +/** @file FBXImporter.h +* @brief Declaration of the FBX main importer class +*/ +#ifndef INCLUDED_AI_FBX_MESHGEOMETRY_H +#define INCLUDED_AI_FBX_MESHGEOMETRY_H + +#include "FBXParser.h" +#include "FBXDocument.h" + +namespace Assimp { +namespace FBX { + +/** + * DOM base class for all kinds of FBX geometry + */ +class Geometry : public Object +{ +public: + Geometry( uint64_t id, const Element& element, const std::string& name, const Document& doc ); + virtual ~Geometry(); + + /** Get the Skin attached to this geometry or NULL */ + const Skin* DeformerSkin() const; + +private: + const Skin* skin; +}; + + +typedef std::vector MatIndexArray; + + +/** + * DOM class for FBX geometry of type "Mesh" + */ +class MeshGeometry : public Geometry +{ +public: + /** The class constructor */ + MeshGeometry( uint64_t id, const Element& element, const std::string& name, const Document& doc ); + + /** The class destructor */ + virtual ~MeshGeometry(); + + /** Get a list of all vertex points, non-unique*/ + const std::vector& GetVertices() const; + + /** Get a list of all vertex normals or an empty array if + * no normals are specified. */ + const std::vector& GetNormals() const; + + /** Get a list of all vertex tangents or an empty array + * if no tangents are specified */ + const std::vector& GetTangents() const; + + /** Get a list of all vertex binormals or an empty array + * if no binormals are specified */ + const std::vector& GetBinormals() const; + + /** Return list of faces - each entry denotes a face and specifies + * how many vertices it has. Vertices are taken from the + * vertex data arrays in sequential order. */ + const std::vector& GetFaceIndexCounts() const; + + /** Get a UV coordinate slot, returns an empty array if + * the requested slot does not exist. */ + const std::vector& GetTextureCoords( unsigned int index ) const; + + /** Get a UV coordinate slot, returns an empty array if + * the requested slot does not exist. */ + std::string GetTextureCoordChannelName( unsigned int index ) const; + + /** Get a vertex color coordinate slot, returns an empty array if + * the requested slot does not exist. */ + const std::vector& GetVertexColors( unsigned int index ) const; + + /** Get per-face-vertex material assignments */ + const MatIndexArray& GetMaterialIndices() const; + + /** Convert from a fbx file vertex index (for example from a #Cluster weight) or NULL + * if the vertex index is not valid. */ + const unsigned int* ToOutputVertexIndex( unsigned int in_index, unsigned int& count ) const; + + /** Determine the face to which a particular output vertex index belongs. + * This mapping is always unique. */ + unsigned int FaceForVertexIndex( unsigned int in_index ) const; + +private: + void ReadLayer( const Scope& layer ); + void ReadLayerElement( const Scope& layerElement ); + void ReadVertexData( const std::string& type, int index, const Scope& source ); + + void ReadVertexDataUV( std::vector& uv_out, const Scope& source, + const std::string& MappingInformationType, + const std::string& ReferenceInformationType ); + + void ReadVertexDataNormals( std::vector& normals_out, const Scope& source, + const std::string& MappingInformationType, + const std::string& ReferenceInformationType ); + + void ReadVertexDataColors( std::vector& colors_out, const Scope& source, + const std::string& MappingInformationType, + const std::string& ReferenceInformationType ); + + void ReadVertexDataTangents( std::vector& tangents_out, const Scope& source, + const std::string& MappingInformationType, + const std::string& ReferenceInformationType ); + + void ReadVertexDataBinormals( std::vector& binormals_out, const Scope& source, + const std::string& MappingInformationType, + const std::string& ReferenceInformationType ); + + void ReadVertexDataMaterials( MatIndexArray& materials_out, const Scope& source, + const std::string& MappingInformationType, + const std::string& ReferenceInformationType ); + +private: + // cached data arrays + MatIndexArray materials; + std::vector vertices; + std::vector faces; + mutable std::vector facesVertexStartIndices; + std::vector tangents; + std::vector binormals; + std::vector normals; + + std::string uvNames[ AI_MAX_NUMBER_OF_TEXTURECOORDS ]; + std::vector uvs[ AI_MAX_NUMBER_OF_TEXTURECOORDS ]; + std::vector colors[ AI_MAX_NUMBER_OF_COLOR_SETS ]; + + std::vector mapping_counts; + std::vector mapping_offsets; + std::vector mappings; +}; + +} +} + +#endif // INCLUDED_AI_FBX_MESHGEOMETRY_H + diff --git a/code/FBXModel.cpp b/code/FBXModel.cpp index c16439724..c3018e4af 100644 --- a/code/FBXModel.cpp +++ b/code/FBXModel.cpp @@ -45,6 +45,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef ASSIMP_BUILD_NO_FBX_IMPORTER #include "FBXParser.h" +#include "FBXMeshGeometry.h" #include "FBXDocument.h" #include "FBXImporter.h" #include "FBXImportSettings.h" diff --git a/code/FBXParser.cpp b/code/FBXParser.cpp index 09a18b6e0..3f982c64a 100644 --- a/code/FBXParser.cpp +++ b/code/FBXParser.cpp @@ -61,6 +61,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include "ByteSwapper.h" +#include + using namespace Assimp; using namespace Assimp::FBX; @@ -611,7 +613,7 @@ void ReadBinaryDataArray(char type, uint32_t count, const char*& data, const cha // read an array of float3 tuples void ParseVectorDataArray(std::vector& out, const Element& el) { - out.clear(); + out.resize( 0 ); const TokenList& tok = el.Tokens(); if(tok.empty()) { @@ -653,6 +655,13 @@ void ParseVectorDataArray(std::vector& out, const Element& el) static_cast(d[1]), static_cast(d[2]))); } + + for ( size_t i = 0; i < out.size(); i++ ) { + aiVector3D vec3( out[ i ] ); + std::stringstream stream; + stream << " vec3.x = " << vec3.x << " vec3.y = " << vec3.y << " vec3.z = " << vec3.z << std::endl; + DefaultLogger::get()->info( stream.str() ); + } } else if (type == 'f') { const float* f = reinterpret_cast(&buff[0]); @@ -692,7 +701,7 @@ void ParseVectorDataArray(std::vector& out, const Element& el) // read an array of color4 tuples void ParseVectorDataArray(std::vector& out, const Element& el) { - out.clear(); + out.resize( 0 ); const TokenList& tok = el.Tokens(); if(tok.empty()) { ParseError("unexpected empty element",&el); @@ -771,7 +780,7 @@ void ParseVectorDataArray(std::vector& out, const Element& el) // read an array of float2 tuples void ParseVectorDataArray(std::vector& out, const Element& el) { - out.clear(); + out.resize( 0 ); const TokenList& tok = el.Tokens(); if(tok.empty()) { ParseError("unexpected empty element",&el); @@ -847,7 +856,7 @@ void ParseVectorDataArray(std::vector& out, const Element& el) // read an array of ints void ParseVectorDataArray(std::vector& out, const Element& el) { - out.clear(); + out.resize( 0 ); const TokenList& tok = el.Tokens(); if(tok.empty()) { ParseError("unexpected empty element",&el); @@ -905,7 +914,7 @@ void ParseVectorDataArray(std::vector& out, const Element& el) // read an array of floats void ParseVectorDataArray(std::vector& out, const Element& el) { - out.clear(); + out.resize( 0 ); const TokenList& tok = el.Tokens(); if(tok.empty()) { ParseError("unexpected empty element",&el); @@ -967,7 +976,7 @@ void ParseVectorDataArray(std::vector& out, const Element& el) // read an array of uints void ParseVectorDataArray(std::vector& out, const Element& el) { - out.clear(); + out.resize( 0 ); const TokenList& tok = el.Tokens(); if(tok.empty()) { ParseError("unexpected empty element",&el); @@ -1032,7 +1041,7 @@ void ParseVectorDataArray(std::vector& out, const Element& el) // read an array of uint64_ts void ParseVectorDataArray(std::vector& out, const Element& el) { - out.clear(); + out.resize( 0 ); const TokenList& tok = el.Tokens(); if(tok.empty()) { ParseError("unexpected empty element",&el); @@ -1090,7 +1099,7 @@ void ParseVectorDataArray(std::vector& out, const Element& el) // read an array of int64_ts void ParseVectorDataArray(std::vector& out, const Element& el) { - out.clear(); + out.resize( 0 ); const TokenList& tok = el.Tokens(); if (tok.empty()) { ParseError("unexpected empty element", &el); diff --git a/code/FBXParser.h b/code/FBXParser.h index 4f165c13f..fb4ec99fe 100644 --- a/code/FBXParser.h +++ b/code/FBXParser.h @@ -55,15 +55,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. namespace Assimp { namespace FBX { - class Scope; - class Parser; - class Element; +class Scope; +class Parser; +class Element; - // XXX should use C++11's unique_ptr - but assimp's need to keep working with 03 - typedef std::vector< Scope* > ScopeList; - typedef std::fbx_unordered_multimap< std::string, Element* > ElementMap; +// XXX should use C++11's unique_ptr - but assimp's need to keep working with 03 +typedef std::vector< Scope* > ScopeList; +typedef std::fbx_unordered_multimap< std::string, Element* > ElementMap; - typedef std::pair ElementCollection; +typedef std::pair ElementCollection; # define new_Scope new Scope # define new_Element new Element @@ -162,7 +162,6 @@ public: ~Parser(); public: - const Scope& GetRootScope() const { return *root.get(); } @@ -173,7 +172,6 @@ public: } private: - friend class Scope; friend class Element; @@ -183,9 +181,7 @@ private: TokenPtr CurrentToken() const; - private: - const TokenList& tokens; TokenPtr last, current; From 53370d0d31832a5e4bc5bb1dfe6c7bc6fd20eff1 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Thu, 3 Mar 2016 18:38:50 +0100 Subject: [PATCH 009/119] FBXImporter: some refactorings to increase readability. --- code/FBXConverter.cpp | 25 ++++++++++++++----------- code/FBXConverter.h | 11 +++++------ code/FBXImporter.cpp | 5 +++-- code/FBXModel.cpp | 2 +- code/FBXNodeAttribute.cpp | 3 ++- code/FBXProperties.h | 15 ++++----------- 6 files changed, 29 insertions(+), 32 deletions(-) diff --git a/code/FBXConverter.cpp b/code/FBXConverter.cpp index 289a84ac6..200853a92 100644 --- a/code/FBXConverter.cpp +++ b/code/FBXConverter.cpp @@ -54,13 +54,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "StringComparison.h" #include "../include/assimp/scene.h" -#include -#include #include -#include #include #include +#include +#include +#include namespace Assimp { namespace FBX { @@ -79,8 +79,9 @@ using namespace Util; class Converter { public: - - /** the different parts that make up the final local transformation of a fbx node */ + /** + * The different parts that make up the final local transformation of a fbx-node + */ enum TransformationComp { TransformationComp_Translation = 0, @@ -102,7 +103,6 @@ public: }; public: - Converter(aiScene* out, const Document& doc) : defaultMaterialIndex() , out(out) @@ -858,7 +858,7 @@ private: } } - // faster codepath, just copy the data + // faster code-path, just copy the data temp.push_back(ConvertMeshSingleMaterial(mesh, model, node_global_transform)); return temp; } @@ -961,7 +961,8 @@ private: } if(binormals) { - ai_assert(tangents.size() == vertices.size() && binormals->size() == vertices.size()); + 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); @@ -1216,10 +1217,12 @@ private: // ------------------------------------------------------------------------------------------------ - /** - if materialIndex == NO_MATERIAL_SEPARATION, materials are not taken into - * account when determining which weights to include. + /** + * - if materialIndex == NO_MATERIAL_SEPARATION, materials are not taken into + * account when determining which weights to include. * - outputVertStartIndices is only used when a material index is specified, it gives for - * each output vertex the DOM index it maps to. */ + * each output vertex the DOM index it maps to. + */ void ConvertWeights(aiMesh* out, const Model& model, const MeshGeometry& geo, const aiMatrix4x4& node_global_transform = aiMatrix4x4(), unsigned int materialIndex = NO_MATERIAL_SEPARATION, diff --git a/code/FBXConverter.h b/code/FBXConverter.h index a69c05e41..ddbbbbf25 100644 --- a/code/FBXConverter.h +++ b/code/FBXConverter.h @@ -51,15 +51,14 @@ namespace FBX { class Document; - -/** Convert a FBX #Document to #aiScene +/** + * Convert a FBX #Document to #aiScene * @param out Empty scene to be populated - * @param doc Parsed FBX document */ + * @param doc Parsed FBX document + */ void ConvertToAssimpScene(aiScene* out, const Document& doc); - } } - -#endif +#endif // INCLUDED_AI_FBX_CONVERTER_H diff --git a/code/FBXImporter.cpp b/code/FBXImporter.cpp index 48fd854ea..83b670125 100644 --- a/code/FBXImporter.cpp +++ b/code/FBXImporter.cpp @@ -86,7 +86,8 @@ static const aiImporterDesc desc = { // ------------------------------------------------------------------------------------------------ // Constructor to be privately used by #Importer FBXImporter::FBXImporter() -{} +{ +} // ------------------------------------------------------------------------------------------------ // Destructor, private as well @@ -104,7 +105,7 @@ bool FBXImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool } else if ((!extension.length() || checkSig) && pIOHandler) { - // at least ascii FBX files usually have a 'FBX' somewhere in their head + // at least ASCII-FBX files usually have a 'FBX' somewhere in their head const char* tokens[] = {"fbx"}; return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1); } diff --git a/code/FBXModel.cpp b/code/FBXModel.cpp index c3018e4af..776334e78 100644 --- a/code/FBXModel.cpp +++ b/code/FBXModel.cpp @@ -56,7 +56,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. namespace Assimp { namespace FBX { - using namespace Util; +using namespace Util; // ------------------------------------------------------------------------------------------------ Model::Model(uint64_t id, const Element& element, const Document& doc, const std::string& name) diff --git a/code/FBXNodeAttribute.cpp b/code/FBXNodeAttribute.cpp index 2bb00248b..405ce7206 100644 --- a/code/FBXNodeAttribute.cpp +++ b/code/FBXNodeAttribute.cpp @@ -58,7 +58,8 @@ namespace FBX { // ------------------------------------------------------------------------------------------------ NodeAttribute::NodeAttribute(uint64_t id, const Element& element, const Document& doc, const std::string& name) - : Object(id,element,name) +: Object(id,element,name) +, props() { const Scope& sc = GetRequiredScope(element); diff --git a/code/FBXProperties.h b/code/FBXProperties.h index fbaa229a1..b9951db8b 100644 --- a/code/FBXProperties.h +++ b/code/FBXProperties.h @@ -65,15 +65,12 @@ namespace FBX { class Property { protected: - Property(); public: - virtual ~Property(); public: - template const T* As() const { return dynamic_cast(this); @@ -85,14 +82,12 @@ template class TypedProperty : public Property { public: - explicit TypedProperty(const T& value) : value(value) { } public: - const T& Value() const { return value; } @@ -106,19 +101,18 @@ typedef std::fbx_unordered_map > DirectP typedef std::fbx_unordered_map PropertyMap; typedef std::fbx_unordered_map LazyPropertyMap; -/** Represents a property table as can be found in the newer FBX files (Properties60, Properties70)*/ +/** + * Represents a property table as can be found in the newer FBX files (Properties60, Properties70) + */ class PropertyTable { public: - // in-memory property table with no source element PropertyTable(); - PropertyTable(const Element& element, boost::shared_ptr templateProps); ~PropertyTable(); public: - const Property* Get(const std::string& name) const; // PropertyTable's need not be coupled with FBX elements so this can be NULL @@ -133,7 +127,6 @@ public: DirectPropertyMap GetUnparsedProperties() const; private: - LazyPropertyMap lazyProps; mutable PropertyMap props; const boost::shared_ptr templateProps; @@ -187,4 +180,4 @@ inline T PropertyGet(const PropertyTable& in, const std::string& name, } //! FBX } //! Assimp -#endif // +#endif // INCLUDED_AI_FBX_PROPERTIES_H From f51f5f8291ef1928ce659b8a3ae3f791135b0903 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Fri, 4 Mar 2016 11:12:11 +0100 Subject: [PATCH 010/119] Update Readme.md README: Add link to donate page. --- Readme.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Readme.md b/Readme.md index 0564e4eda..39d5df5e9 100644 --- a/Readme.md +++ b/Readme.md @@ -116,6 +116,9 @@ For development discussions, there is also a (very low-volume) mailing list, _as And we also have an IRC-channel at freenode: #assetimporterlib . You can easily join us via: [KiwiIRC/freenote](https://kiwiirc.com/client/irc.freenode.net), choose your nickname and type > /join #assetimporterlib +And if you like assimp, consider buying us a beer (or two): +[Donate](http://sourceforge.net/donate/index.php?group_id=226462") + ### Contributing ### Contributions to assimp are highly appreciated. The easiest way to get involved is to submit a pull request with your changes against the main repository's `master` branch. From 072e38403ed44817fa978aaa511826cd69f32676 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Fri, 4 Mar 2016 11:13:07 +0100 Subject: [PATCH 011/119] Update Readme.md README: move donate to a special chapter. --- Readme.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Readme.md b/Readme.md index 39d5df5e9..ad6954f12 100644 --- a/Readme.md +++ b/Readme.md @@ -116,13 +116,14 @@ For development discussions, there is also a (very low-volume) mailing list, _as And we also have an IRC-channel at freenode: #assetimporterlib . You can easily join us via: [KiwiIRC/freenote](https://kiwiirc.com/client/irc.freenode.net), choose your nickname and type > /join #assetimporterlib -And if you like assimp, consider buying us a beer (or two): -[Donate](http://sourceforge.net/donate/index.php?group_id=226462") - ### Contributing ### Contributions to assimp are highly appreciated. The easiest way to get involved is to submit a pull request with your changes against the main repository's `master` branch. +### Donate ### +If you like assimp, consider buying us a beer (or two): +[Donate](http://sourceforge.net/donate/index.php?group_id=226462") + ### License ### Our license is based on the modified, __3-clause BSD__-License. From 1e5632b3b86e6ae037871590ffdd699b3a127d78 Mon Sep 17 00:00:00 2001 From: Thiago Goulart Date: Fri, 4 Mar 2016 03:35:11 -0800 Subject: [PATCH 012/119] Add missing files (and required includes) so that xcode6 project builds succesfully. --- .../xcode6/Assimp.xcodeproj/project.pbxproj | 58 +++++++++++++++++-- 1 file changed, 54 insertions(+), 4 deletions(-) diff --git a/workspaces/xcode6/Assimp.xcodeproj/project.pbxproj b/workspaces/xcode6/Assimp.xcodeproj/project.pbxproj index 14c4598bd..dfac6e4be 100644 --- a/workspaces/xcode6/Assimp.xcodeproj/project.pbxproj +++ b/workspaces/xcode6/Assimp.xcodeproj/project.pbxproj @@ -167,6 +167,11 @@ 7FBE9FEA1B65AC1200D2115E /* OpenGEXExporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7FBE9FE51B65AC1200D2115E /* OpenGEXExporter.cpp */; }; 7FBE9FEB1B65AC1200D2115E /* OpenGEXImporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7FBE9FE71B65AC1200D2115E /* OpenGEXImporter.cpp */; }; 7FBEA0121B65B11800D2115E /* Version.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7FBEA0111B65B11800D2115E /* Version.cpp */; }; + AFB7F8521C882F1A00D7B6E9 /* OpenDDLCommon.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AFB7F8501C882F1A00D7B6E9 /* OpenDDLCommon.cpp */; }; + AFB7F8531C882F1A00D7B6E9 /* OpenDDLExport.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AFB7F8511C882F1A00D7B6E9 /* OpenDDLExport.cpp */; }; + AFB7F85D1C882F8200D7B6E9 /* glTFExporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AFB7F8591C882F8200D7B6E9 /* glTFExporter.cpp */; }; + AFB7F85E1C882F8200D7B6E9 /* glTFImporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AFB7F85B1C882F8200D7B6E9 /* glTFImporter.cpp */; }; + AFB7F8631C88302500D7B6E9 /* SIBImporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AFB7F8611C88302500D7B6E9 /* SIBImporter.cpp */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -467,6 +472,18 @@ AE1C2E2C9C424B3684AD9D4A /* texture.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = texture.h; path = include/assimp/texture.h; sourceTree = SOURCE_ROOT; }; AF75E6049338489BB256D295 /* ioapi.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.c; fileEncoding = 4; name = ioapi.c; path = contrib/unzip/ioapi.c; sourceTree = SOURCE_ROOT; }; AFA8B6DE5B3A4E52A85041C9 /* LWOFileData.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = LWOFileData.h; path = code/LWOFileData.h; sourceTree = SOURCE_ROOT; }; + AFB7F8501C882F1A00D7B6E9 /* OpenDDLCommon.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OpenDDLCommon.cpp; path = contrib/openddlparser/code/OpenDDLCommon.cpp; sourceTree = ""; }; + AFB7F8511C882F1A00D7B6E9 /* OpenDDLExport.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OpenDDLExport.cpp; path = contrib/openddlparser/code/OpenDDLExport.cpp; sourceTree = ""; }; + AFB7F8551C882F8200D7B6E9 /* glTFAsset.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = glTFAsset.h; path = code/glTFAsset.h; sourceTree = ""; }; + AFB7F8561C882F8200D7B6E9 /* glTFAsset.inl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = glTFAsset.inl; path = code/glTFAsset.inl; sourceTree = ""; }; + AFB7F8571C882F8200D7B6E9 /* glTFAssetWriter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = glTFAssetWriter.h; path = code/glTFAssetWriter.h; sourceTree = ""; }; + AFB7F8581C882F8200D7B6E9 /* glTFAssetWriter.inl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = glTFAssetWriter.inl; path = code/glTFAssetWriter.inl; sourceTree = ""; }; + AFB7F8591C882F8200D7B6E9 /* glTFExporter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = glTFExporter.cpp; path = code/glTFExporter.cpp; sourceTree = ""; }; + AFB7F85A1C882F8200D7B6E9 /* glTFExporter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = glTFExporter.h; path = code/glTFExporter.h; sourceTree = ""; }; + AFB7F85B1C882F8200D7B6E9 /* glTFImporter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = glTFImporter.cpp; path = code/glTFImporter.cpp; sourceTree = ""; }; + AFB7F85C1C882F8200D7B6E9 /* glTFImporter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = glTFImporter.h; path = code/glTFImporter.h; sourceTree = ""; }; + AFB7F8611C88302500D7B6E9 /* SIBImporter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SIBImporter.cpp; path = code/SIBImporter.cpp; sourceTree = ""; }; + AFB7F8621C88302500D7B6E9 /* SIBImporter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SIBImporter.h; path = code/SIBImporter.h; sourceTree = ""; }; AFF41974881F466A9561BE4B /* LWSLoader.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = LWSLoader.cpp; path = code/LWSLoader.cpp; sourceTree = SOURCE_ROOT; }; B04FE3598E344EC09B59CA2F /* IRRShared.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = IRRShared.h; path = code/IRRShared.h; sourceTree = SOURCE_ROOT; }; B05DC38593F04180B322360B /* camera.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = camera.h; path = include/assimp/camera.h; sourceTree = SOURCE_ROOT; }; @@ -733,6 +750,7 @@ 09D1759329AB410E92DC273A /* Collada */, 5F3147F7FF1044D49A824DBC /* DXF */, DD5B35196B184EFB820D1FBB /* CSM */, + AFB7F8541C882F6E00D7B6E9 /* glTF */, 723B9CB1C871444FBB302576 /* HMP */, 6CB3C1AECE8A4745861D913D /* Irr */, 873AA0EB80814B0A9461BB7E /* LWO */, @@ -752,6 +770,7 @@ F0273EDFDBD34EDAA6678613 /* Q3D */, C3D412701D614559B698CED1 /* Q3BSP */, 9A8E68D1ECFC49B9BB435F1C /* Raw */, + AFB7F8601C88301600D7B6E9 /* SIB */, 8C2B1B7516DD4C4798F5048F /* SMD */, 2E29D94CA6DA405EB4AF90E0 /* STL */, 3A5EB041B5CD4F98802B2540 /* Terragen */, @@ -1079,6 +1098,8 @@ 7FBEA0051B65AF8900D2115E /* openddlparser */ = { isa = PBXGroup; children = ( + AFB7F8501C882F1A00D7B6E9 /* OpenDDLCommon.cpp */, + AFB7F8511C882F1A00D7B6E9 /* OpenDDLExport.cpp */, 7FBEA0081B65AF9200D2115E /* OpenDDLCommon.h */, 7FBEA00B1B65AF9200D2115E /* OpenDDLParserUtils.h */, 7FBEA0071B65AF9200D2115E /* DDLNode.h */, @@ -1252,6 +1273,30 @@ name = Products; sourceTree = ""; }; + AFB7F8541C882F6E00D7B6E9 /* glTF */ = { + isa = PBXGroup; + children = ( + AFB7F8551C882F8200D7B6E9 /* glTFAsset.h */, + AFB7F8561C882F8200D7B6E9 /* glTFAsset.inl */, + AFB7F8571C882F8200D7B6E9 /* glTFAssetWriter.h */, + AFB7F8581C882F8200D7B6E9 /* glTFAssetWriter.inl */, + AFB7F8591C882F8200D7B6E9 /* glTFExporter.cpp */, + AFB7F85A1C882F8200D7B6E9 /* glTFExporter.h */, + AFB7F85B1C882F8200D7B6E9 /* glTFImporter.cpp */, + AFB7F85C1C882F8200D7B6E9 /* glTFImporter.h */, + ); + name = glTF; + sourceTree = ""; + }; + AFB7F8601C88301600D7B6E9 /* SIB */ = { + isa = PBXGroup; + children = ( + AFB7F8611C88302500D7B6E9 /* SIBImporter.cpp */, + AFB7F8621C88302500D7B6E9 /* SIBImporter.h */, + ); + name = SIB; + sourceTree = ""; + }; BCC52F1D5AF74E54A2D69524 = { isa = PBXGroup; children = ( @@ -1577,6 +1622,7 @@ 7F79243B1AB43E20005A8E5D /* BlenderBMesh.cpp in Sources */, 7F79243C1AB43E20005A8E5D /* BlenderDNA.cpp in Sources */, 7F79243D1AB43E20005A8E5D /* BlenderLoader.cpp in Sources */, + AFB7F85D1C882F8200D7B6E9 /* glTFExporter.cpp in Sources */, 7F79243E1AB43E20005A8E5D /* BlenderModifier.cpp in Sources */, 7F79243F1AB43E20005A8E5D /* BlenderScene.cpp in Sources */, 7F7924401AB43E20005A8E5D /* BlenderTessellator.cpp in Sources */, @@ -1612,6 +1658,7 @@ 7F79245D1AB43E20005A8E5D /* FBXUtil.cpp in Sources */, 7F7A93A91B65D0110094C4DA /* OpenDDLParser.cpp in Sources */, 7F79245E1AB43E20005A8E5D /* FindDegenerates.cpp in Sources */, + AFB7F8531C882F1A00D7B6E9 /* OpenDDLExport.cpp in Sources */, 7F79245F1AB43E20005A8E5D /* FindInstancesProcess.cpp in Sources */, 7F7924601AB43E20005A8E5D /* FindInvalidDataProcess.cpp in Sources */, 7F7924611AB43E20005A8E5D /* FixNormalsStep.cpp in Sources */, @@ -1620,6 +1667,7 @@ 7F7924641AB43E20005A8E5D /* HMPLoader.cpp in Sources */, 7F7924651AB43E20005A8E5D /* IFCBoolean.cpp in Sources */, 7F7924661AB43E20005A8E5D /* IFCCurve.cpp in Sources */, + AFB7F85E1C882F8200D7B6E9 /* glTFImporter.cpp in Sources */, 7F7924671AB43E20005A8E5D /* IFCGeometry.cpp in Sources */, 7F7924681AB43E20005A8E5D /* IFCLoader.cpp in Sources */, 7F7924691AB43E20005A8E5D /* IFCMaterial.cpp in Sources */, @@ -1640,6 +1688,7 @@ 7F7924771AB43E20005A8E5D /* LWOLoader.cpp in Sources */, 7F7924781AB43E20005A8E5D /* LWOMaterial.cpp in Sources */, 7F7924791AB43E20005A8E5D /* LWSLoader.cpp in Sources */, + AFB7F8521C882F1A00D7B6E9 /* OpenDDLCommon.cpp in Sources */, 7F79247A1AB43E20005A8E5D /* LimitBoneWeightsProcess.cpp in Sources */, 7F79247B1AB43E20005A8E5D /* MD2Loader.cpp in Sources */, 7F79247C1AB43E20005A8E5D /* MD3Loader.cpp in Sources */, @@ -1695,6 +1744,7 @@ 7F7924AB1AB43E20005A8E5D /* SpatialSort.cpp in Sources */, 7F7924AC1AB43E20005A8E5D /* SplitByBoneCountProcess.cpp in Sources */, 7F7924AD1AB43E20005A8E5D /* SplitLargeMeshes.cpp in Sources */, + AFB7F8631C88302500D7B6E9 /* SIBImporter.cpp in Sources */, 7F7924AE1AB43E20005A8E5D /* StandardShapes.cpp in Sources */, 7F7924AF1AB43E20005A8E5D /* Subdivision.cpp in Sources */, 7F7924B01AB43E20005A8E5D /* TargetAnimation.cpp in Sources */, @@ -1777,7 +1827,7 @@ OTHER_LDFLAGS = "-ObjC"; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; - USER_HEADER_SEARCH_PATHS = "code code/BoostWorkaround contrib/openddlparser/include include $(inherited)"; + USER_HEADER_SEARCH_PATHS = "code code/BoostWorkaround contrib/openddlparser/include contrib/rapidjson/include include $(inherited)"; }; name = Debug; }; @@ -1823,7 +1873,7 @@ OTHER_LDFLAGS = "-ObjC"; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; - USER_HEADER_SEARCH_PATHS = "code code/BoostWorkaround contrib/openddlparser/include include $(inherited)"; + USER_HEADER_SEARCH_PATHS = "code code/BoostWorkaround contrib/openddlparser/include contrib/rapidjson/include include $(inherited)"; VALIDATE_PRODUCT = YES; }; name = Release; @@ -1869,7 +1919,7 @@ OTHER_LDFLAGS = "-ObjC"; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; - USER_HEADER_SEARCH_PATHS = "code code/BoostWorkaround contrib/openddlparser/include include $(inherited)"; + USER_HEADER_SEARCH_PATHS = "code code/BoostWorkaround contrib/openddlparser/include contrib/rapidjson/include include $(inherited)"; VALIDATE_PRODUCT = YES; }; name = MinSizeRel; @@ -1915,7 +1965,7 @@ OTHER_LDFLAGS = "-ObjC"; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; - USER_HEADER_SEARCH_PATHS = "code code/BoostWorkaround contrib/openddlparser/include include $(inherited)"; + USER_HEADER_SEARCH_PATHS = "code code/BoostWorkaround contrib/openddlparser/include contrib/rapidjson/include include $(inherited)"; VALIDATE_PRODUCT = YES; }; name = RelWithDebInfo; From 3c9e57fd73db479d66fc654fe4a7171dd6432fd8 Mon Sep 17 00:00:00 2001 From: Thiago Goulart Date: Fri, 4 Mar 2016 03:33:45 -0800 Subject: [PATCH 013/119] Fix memory leak in OBJ loader when a mesh has no faces. --- code/ObjFileImporter.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/code/ObjFileImporter.cpp b/code/ObjFileImporter.cpp index c812baf23..f5c727ec9 100644 --- a/code/ObjFileImporter.cpp +++ b/code/ObjFileImporter.cpp @@ -308,7 +308,11 @@ aiMesh *ObjFileImporter::createTopology( const ObjFile::Model* pModel, const Obj if( !pObjMesh ) { return NULL; } - ai_assert( NULL != pObjMesh ); + + if( pObjMesh->m_Faces.empty() ) { + return NULL; + } + aiMesh* pMesh = new aiMesh; if( !pObjMesh->m_name.empty() ) { pMesh->mName.Set( pObjMesh->m_name ); From 98ba2d23103546ad5770e706fb5993a183eaefa5 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Fri, 4 Mar 2016 16:45:40 +0100 Subject: [PATCH 014/119] Update Readme.md Readme: fix typo --- Readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Readme.md b/Readme.md index ad6954f12..cafcf4921 100644 --- a/Readme.md +++ b/Readme.md @@ -122,7 +122,7 @@ a pull request with your changes against the main repository's `master` branch. ### Donate ### If you like assimp, consider buying us a beer (or two): -[Donate](http://sourceforge.net/donate/index.php?group_id=226462") +[Donate](http://sourceforge.net/donate/index.php?group_id=226462) ### License ### Our license is based on the modified, __3-clause BSD__-License. From 93be0f69dacaeb0fe377290e8920feb93afd7666 Mon Sep 17 00:00:00 2001 From: emvivre Date: Thu, 10 Mar 2016 17:47:07 +0100 Subject: [PATCH 015/119] PlyParser: fix invalid loading when comment is empty. --- code/PlyParser.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/code/PlyParser.cpp b/code/PlyParser.cpp index df7d6883b..5b6a35e5f 100644 --- a/code/PlyParser.cpp +++ b/code/PlyParser.cpp @@ -420,7 +420,10 @@ bool PLY::DOM::SkipComments (const char* pCur, if (TokenMatch(pCur,"comment",7)) { - SkipLine(pCur,&pCur); + if ( !IsLineEnd(pCur[-1]) ) + { + SkipLine(pCur,&pCur); + } SkipComments(pCur,&pCur); *pCurOut = pCur; return true; From b4b303ab5592bb5f17ac49fed9a75afe57a7410b Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sat, 12 Mar 2016 13:22:09 +0100 Subject: [PATCH 016/119] OpenGEX: fix alloc for texture coordinates. --- code/OpenGEXImporter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/OpenGEXImporter.cpp b/code/OpenGEXImporter.cpp index 0a6d510fc..05273d539 100644 --- a/code/OpenGEXImporter.cpp +++ b/code/OpenGEXImporter.cpp @@ -706,7 +706,7 @@ void OpenGEXImporter::handleIndexArrayNode( ODDLParser::DDLNode *node, aiScene * m_currentMesh->mVertices = new aiVector3D[ m_currentMesh->mNumVertices ]; m_currentMesh->mNormals = new aiVector3D[ m_currentMesh->mNumVertices ]; m_currentMesh->mNumUVComponents[ 0 ] = numItems * 3; - m_currentMesh->mTextureCoords[ 0 ] = new aiVector3D[ m_currentMesh->mNumUVComponents[ 0 ] ]; + m_currentMesh->mTextureCoords[ 0 ] = new aiVector3D[ m_currentMesh->mNumVertices ]; unsigned int index( 0 ); for( size_t i = 0; i < m_currentMesh->mNumFaces; i++ ) { From 6ee5fdf567aabd8993b00d7e26f85b6697472101 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sat, 12 Mar 2016 20:55:11 +0100 Subject: [PATCH 017/119] OpenGEX: fix review finding. --- code/OpenGEXImporter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/OpenGEXImporter.cpp b/code/OpenGEXImporter.cpp index 05273d539..a5a7b2db6 100644 --- a/code/OpenGEXImporter.cpp +++ b/code/OpenGEXImporter.cpp @@ -705,7 +705,7 @@ void OpenGEXImporter::handleIndexArrayNode( ODDLParser::DDLNode *node, aiScene * m_currentMesh->mNumVertices = numItems * 3; m_currentMesh->mVertices = new aiVector3D[ m_currentMesh->mNumVertices ]; m_currentMesh->mNormals = new aiVector3D[ m_currentMesh->mNumVertices ]; - m_currentMesh->mNumUVComponents[ 0 ] = numItems * 3; + m_currentMesh->mNumUVComponents[ 0 ] = m_currentMesh->mNumVertices; m_currentMesh->mTextureCoords[ 0 ] = new aiVector3D[ m_currentMesh->mNumVertices ]; unsigned int index( 0 ); From e2361bf209caa72d347c1b92a36133ca4844fea3 Mon Sep 17 00:00:00 2001 From: Turo Lamminen Date: Sat, 12 Mar 2016 21:23:22 +0200 Subject: [PATCH 018/119] MDL: Fix read past end of buffer on malformed input --- code/MDLLoader.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/code/MDLLoader.cpp b/code/MDLLoader.cpp index 957aa1be2..50373f401 100644 --- a/code/MDLLoader.cpp +++ b/code/MDLLoader.cpp @@ -576,9 +576,13 @@ void MDLImporter::InternReadFile_3DGS_MDL345( ) // current cursor position in the file 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) { + if (szCurrent >= szEnd) { + throw DeadlyImportError( "Texture data past end of file."); + } BE_NCONST MDL::Skin* pcSkin; pcSkin = (BE_NCONST MDL::Skin*)szCurrent; AI_SWAP4( pcSkin->group); From 8d2af995de379e6125f25189e6de152ec165bdce Mon Sep 17 00:00:00 2001 From: Turo Lamminen Date: Sat, 12 Mar 2016 23:48:05 +0200 Subject: [PATCH 019/119] MD2: Fix integer overflows on malformed input --- code/MD2Loader.cpp | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/code/MD2Loader.cpp b/code/MD2Loader.cpp index 4b7bbe67a..5e73d89fa 100644 --- a/code/MD2Loader.cpp +++ b/code/MD2Loader.cpp @@ -169,6 +169,26 @@ void MD2Importer::ValidateHeader( ) if (m_pcHeader->offsetEnd > (uint32_t)fileSize) throw DeadlyImportError( "Invalid md2 file: File is too small"); + if (m_pcHeader->numSkins > AI_MAX_ALLOC(MD2::Skin)) { + throw DeadlyImportError("Invalid MD2 header: too many skins, would overflow"); + } + + if (m_pcHeader->numVertices > AI_MAX_ALLOC(MD2::Vertex)) { + throw DeadlyImportError("Invalid MD2 header: too many vertices, would overflow"); + } + + if (m_pcHeader->numTexCoords > AI_MAX_ALLOC(MD2::TexCoord)) { + throw DeadlyImportError("Invalid MD2 header: too many texcoords, would overflow"); + } + + if (m_pcHeader->numTriangles > AI_MAX_ALLOC(MD2::Triangle)) { + throw DeadlyImportError("Invalid MD2 header: too many triangles, would overflow"); + } + + if (m_pcHeader->numFrames > AI_MAX_ALLOC(MD2::Frame)) { + throw DeadlyImportError("Invalid MD2 header: too many frames, would overflow"); + } + if (m_pcHeader->offsetSkins + m_pcHeader->numSkins * sizeof (MD2::Skin) >= fileSize || m_pcHeader->offsetTexCoords + m_pcHeader->numTexCoords * sizeof (MD2::TexCoord) >= fileSize || m_pcHeader->offsetTriangles + m_pcHeader->numTriangles * sizeof (MD2::Triangle) >= fileSize || From b0f453dba881d542e10dd67f4cadb74faf491263 Mon Sep 17 00:00:00 2001 From: Turo Lamminen Date: Sun, 13 Mar 2016 00:41:39 +0200 Subject: [PATCH 020/119] MD2: Check file is big enough to contain all the advertised frames --- code/MD2Loader.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/code/MD2Loader.cpp b/code/MD2Loader.cpp index 5e73d89fa..74af02467 100644 --- a/code/MD2Loader.cpp +++ b/code/MD2Loader.cpp @@ -189,10 +189,13 @@ void MD2Importer::ValidateHeader( ) throw DeadlyImportError("Invalid MD2 header: too many frames, would overflow"); } + // -1 because Frame already contains one + unsigned int frameSize = sizeof (MD2::Frame) + (m_pcHeader->numVertices - 1) * sizeof(MD2::Vertex); + if (m_pcHeader->offsetSkins + m_pcHeader->numSkins * sizeof (MD2::Skin) >= fileSize || m_pcHeader->offsetTexCoords + m_pcHeader->numTexCoords * sizeof (MD2::TexCoord) >= fileSize || m_pcHeader->offsetTriangles + m_pcHeader->numTriangles * sizeof (MD2::Triangle) >= fileSize || - m_pcHeader->offsetFrames + m_pcHeader->numFrames * sizeof (MD2::Frame) >= fileSize || + m_pcHeader->offsetFrames + m_pcHeader->numFrames * frameSize >= fileSize || m_pcHeader->offsetEnd > fileSize) { throw DeadlyImportError("Invalid MD2 header: some offsets are outside the file"); From da0b18090170be34f07421b0f5a579b675ce307c Mon Sep 17 00:00:00 2001 From: Turo Lamminen Date: Sat, 12 Mar 2016 21:50:34 +0200 Subject: [PATCH 021/119] MD3: Fix crash on invalid vertex index --- code/MD3Loader.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/code/MD3Loader.cpp b/code/MD3Loader.cpp index 93ccc4ad1..53e890590 100644 --- a/code/MD3Loader.cpp +++ b/code/MD3Loader.cpp @@ -1000,9 +1000,13 @@ void MD3Importer::InternReadFile( const std::string& pFile, // Read vertices aiVector3D& vec = pcMesh->mVertices[iCurrent]; - vec.x = pcVertices[ pcTriangles->INDEXES[c]].X*AI_MD3_XYZ_SCALE; - vec.y = pcVertices[ pcTriangles->INDEXES[c]].Y*AI_MD3_XYZ_SCALE; - vec.z = pcVertices[ pcTriangles->INDEXES[c]].Z*AI_MD3_XYZ_SCALE; + uint32_t index = pcTriangles->INDEXES[c]; + if (index >= pcSurfaces->NUM_VERTICES) { + throw DeadlyImportError( "MD3: Invalid vertex index"); + } + vec.x = pcVertices[index].X*AI_MD3_XYZ_SCALE; + vec.y = pcVertices[index].Y*AI_MD3_XYZ_SCALE; + vec.z = pcVertices[index].Z*AI_MD3_XYZ_SCALE; // Convert the normal vector to uncompressed float3 format aiVector3D& nor = pcMesh->mNormals[iCurrent]; From 555f5337779e2e792845284e417d11eb1b778bc4 Mon Sep 17 00:00:00 2001 From: Turo Lamminen Date: Sun, 13 Mar 2016 00:54:23 +0200 Subject: [PATCH 022/119] MD3: Check file is big enough to contain all the advertised surfaces --- code/MD3Loader.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/code/MD3Loader.cpp b/code/MD3Loader.cpp index 53e890590..c8b58f593 100644 --- a/code/MD3Loader.cpp +++ b/code/MD3Loader.cpp @@ -407,6 +407,14 @@ void MD3Importer::ValidateHeaderOffsets() throw DeadlyImportError("Invalid MD3 header: some offsets are outside the file"); } + if (pcHeader->NUM_SURFACES > AI_MAX_ALLOC(MD3::Surface)) { + throw DeadlyImportError("Invalid MD3 header: too many surfaces, would overflow"); + } + + if (pcHeader->OFS_SURFACES + pcHeader->NUM_SURFACES * sizeof(MD3::Surface) >= fileSize) { + throw DeadlyImportError("Invalid MD3 header: some surfaces are outside the file"); + } + if (pcHeader->NUM_FRAMES <= configFrameID ) throw DeadlyImportError("The requested frame is not existing the file"); } From 7e9fe2d6543e269848a2780ebc090cd749e21f89 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sun, 13 Mar 2016 20:22:36 +0100 Subject: [PATCH 023/119] OpenGEX: use correct number of uv-coordinates for texture coordinates. --- code/OpenGEXImporter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/OpenGEXImporter.cpp b/code/OpenGEXImporter.cpp index a5a7b2db6..2ddc401a4 100644 --- a/code/OpenGEXImporter.cpp +++ b/code/OpenGEXImporter.cpp @@ -705,7 +705,7 @@ void OpenGEXImporter::handleIndexArrayNode( ODDLParser::DDLNode *node, aiScene * m_currentMesh->mNumVertices = numItems * 3; m_currentMesh->mVertices = new aiVector3D[ m_currentMesh->mNumVertices ]; m_currentMesh->mNormals = new aiVector3D[ m_currentMesh->mNumVertices ]; - m_currentMesh->mNumUVComponents[ 0 ] = m_currentMesh->mNumVertices; + m_currentMesh->mNumUVComponents[ 0 ] = 3; m_currentMesh->mTextureCoords[ 0 ] = new aiVector3D[ m_currentMesh->mNumVertices ]; unsigned int index( 0 ); From 3a7c3a5698dcff7f24ecfffef3aa52611091f1b0 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Mon, 14 Mar 2016 21:00:08 +0100 Subject: [PATCH 024/119] Test for issue-731: possible overflow. --- code/ColladaLoader.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/ColladaLoader.cpp b/code/ColladaLoader.cpp index e6dd3ecad..d423fbd2e 100644 --- a/code/ColladaLoader.cpp +++ b/code/ColladaLoader.cpp @@ -1174,7 +1174,7 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars // https://github.com/assimp/assimp/issues/458 // Sub-sample axis-angle channels if the delta between two consecutive // key-frame angles is >= 180 degrees. - if (transforms[e.mTransformIndex].mType == Collada::TF_ROTATE && e.mSubElement == 3 && pos > 0 && pos < e.mTimeAccessor->mCount) { + /*if (transforms[e.mTransformIndex].mType == Collada::TF_ROTATE && e.mSubElement == 3 && pos > 0 && pos < e.mTimeAccessor->mCount) { float cur_key_angle = ReadFloat(*e.mValueAccessor, *e.mValueData, pos, 0); float last_key_angle = ReadFloat(*e.mValueAccessor, *e.mValueData, pos - 1, 0); float cur_key_time = ReadFloat(*e.mTimeAccessor, *e.mTimeData, pos, 0); @@ -1188,7 +1188,7 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars nextTime = std::min(nextTime, nextSampleTime); } } - } + }*/ } // no more keys on any channel after the current time -> we're done From 8314a20c56632a023ef0542a3b4ca11cc0b0481e Mon Sep 17 00:00:00 2001 From: Wietse Date: Mon, 14 Mar 2016 23:14:31 +0100 Subject: [PATCH 025/119] Update CMakeLists.txt Changed "add_definitions" to "add_compile_options" to fix building with NMake. Using "add_definitions" adds "/MP" to the resource compiler options which results in a fatal error when run with NMake. --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8434e4628..538d2665b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -72,7 +72,7 @@ if((CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX) AND NOT CMAKE_COMPILER_ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden -Wall" ) elseif(MSVC) # enable multi-core compilation with MSVC - add_definitions(/MP) + add_compile_options(/MP) endif() INCLUDE (FindPkgConfig) @@ -367,4 +367,4 @@ if(WIN32) add_custom_command(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/Debug/assimp-${ASSIMP_MSVC_VERSION}-mtd.lib ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.lib VERBATIM) add_custom_command(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/Debug/assimp-${ASSIMP_MSVC_VERSION}-mtd.pdb ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.pdb VERBATIM) endif(MSVC12 OR MSVC14) -endif (WIN32) \ No newline at end of file +endif (WIN32) From e3d7ca264c79f689878ce469c35f23a00e3bdf63 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 15 Mar 2016 19:28:57 +0100 Subject: [PATCH 026/119] Collada: reset workaround. --- code/ColladaLoader.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/ColladaLoader.cpp b/code/ColladaLoader.cpp index d423fbd2e..e6dd3ecad 100644 --- a/code/ColladaLoader.cpp +++ b/code/ColladaLoader.cpp @@ -1174,7 +1174,7 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars // https://github.com/assimp/assimp/issues/458 // Sub-sample axis-angle channels if the delta between two consecutive // key-frame angles is >= 180 degrees. - /*if (transforms[e.mTransformIndex].mType == Collada::TF_ROTATE && e.mSubElement == 3 && pos > 0 && pos < e.mTimeAccessor->mCount) { + if (transforms[e.mTransformIndex].mType == Collada::TF_ROTATE && e.mSubElement == 3 && pos > 0 && pos < e.mTimeAccessor->mCount) { float cur_key_angle = ReadFloat(*e.mValueAccessor, *e.mValueData, pos, 0); float last_key_angle = ReadFloat(*e.mValueAccessor, *e.mValueData, pos - 1, 0); float cur_key_time = ReadFloat(*e.mTimeAccessor, *e.mTimeData, pos, 0); @@ -1188,7 +1188,7 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars nextTime = std::min(nextTime, nextSampleTime); } } - }*/ + } } // no more keys on any channel after the current time -> we're done From d89e7943ad454635cf930307da7ee90dac2e2ddb Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 15 Mar 2016 21:16:47 +0100 Subject: [PATCH 027/119] FBX Close issue-806: support version 7400. --- code/FBXDocument.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/code/FBXDocument.cpp b/code/FBXDocument.cpp index 1e9ea6f3c..0252d0eb1 100644 --- a/code/FBXDocument.cpp +++ b/code/FBXDocument.cpp @@ -292,8 +292,10 @@ Document::~Document() // |dest_connections| contain the same Connection objects as the |src_connections| } - // ------------------------------------------------------------------------------------------------ +static const int LowerSupportedVersion = 7100; +static const int UpperSupportedVersion = 7400; + void Document::ReadHeader() { // Read ID objects from "Objects" section @@ -308,10 +310,10 @@ void Document::ReadHeader() // While we maye have some success with newer files, we don't support // the older 6.n fbx format - if(fbxVersion < 7100) { + if(fbxVersion < LowerSupportedVersion ) { DOMError("unsupported, old format version, supported are only FBX 2011, FBX 2012 and FBX 2013"); } - if(fbxVersion > 7300) { + if(fbxVersion > UpperSupportedVersion ) { if(Settings().strictMode) { DOMError("unsupported, newer format version, supported are only FBX 2011, FBX 2012 and FBX 2013" " (turn off strict mode to try anyhow) "); From 644d6a9a677d0704c8135df33c3eb8bf242725b3 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 15 Mar 2016 21:17:38 +0100 Subject: [PATCH 028/119] Collada: refactorings. --- code/ColladaLoader.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/code/ColladaLoader.cpp b/code/ColladaLoader.cpp index e6dd3ecad..b10a5a248 100644 --- a/code/ColladaLoader.cpp +++ b/code/ColladaLoader.cpp @@ -1156,13 +1156,13 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars float nextTime = 1e20f; for( std::vector::iterator it = entries.begin(); it != entries.end(); ++it) { - Collada::ChannelEntry& e = *it; + Collada::ChannelEntry& channelElement = *it; // find the next time value larger than the current size_t pos = 0; - while( pos < e.mTimeAccessor->mCount) + while( pos < channelElement.mTimeAccessor->mCount) { - float t = ReadFloat( *e.mTimeAccessor, *e.mTimeData, pos, 0); + const float t = ReadFloat( *channelElement.mTimeAccessor, *channelElement.mTimeData, pos, 0); if( t > time) { nextTime = std::min( nextTime, t); @@ -1174,17 +1174,17 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars // https://github.com/assimp/assimp/issues/458 // Sub-sample axis-angle channels if the delta between two consecutive // key-frame angles is >= 180 degrees. - if (transforms[e.mTransformIndex].mType == Collada::TF_ROTATE && e.mSubElement == 3 && pos > 0 && pos < e.mTimeAccessor->mCount) { - float cur_key_angle = ReadFloat(*e.mValueAccessor, *e.mValueData, pos, 0); - float last_key_angle = ReadFloat(*e.mValueAccessor, *e.mValueData, pos - 1, 0); - float cur_key_time = ReadFloat(*e.mTimeAccessor, *e.mTimeData, pos, 0); - float last_key_time = ReadFloat(*e.mTimeAccessor, *e.mTimeData, pos - 1, 0); - float last_eval_angle = last_key_angle + (cur_key_angle - last_key_angle) * (time - last_key_time) / (cur_key_time - last_key_time); - float delta = std::fabs(cur_key_angle - last_eval_angle); + if (transforms[channelElement.mTransformIndex].mType == Collada::TF_ROTATE && channelElement.mSubElement == 3 && pos > 0 && pos < channelElement.mTimeAccessor->mCount) { + const float cur_key_angle = ReadFloat(*channelElement.mValueAccessor, *channelElement.mValueData, pos, 0); + const float last_key_angle = ReadFloat(*channelElement.mValueAccessor, *channelElement.mValueData, pos - 1, 0); + const float cur_key_time = ReadFloat(*channelElement.mTimeAccessor, *channelElement.mTimeData, pos, 0); + const float last_key_time = ReadFloat(*channelElement.mTimeAccessor, *channelElement.mTimeData, pos - 1, 0); + const float last_eval_angle = last_key_angle + (cur_key_angle - last_key_angle) * (time - last_key_time) / (cur_key_time - last_key_time); + const float delta = std::fabs(cur_key_angle - last_eval_angle); if (delta >= 180.0f) { - int subSampleCount = static_cast(floorf(delta / 90.0f)); + const int subSampleCount = static_cast(floorf(delta / 90.0f)); if (cur_key_time != time) { - float nextSampleTime = time + (cur_key_time - time) / subSampleCount; + const float nextSampleTime = time + (cur_key_time - time) / subSampleCount; nextTime = std::min(nextTime, nextSampleTime); } } From 76e4e82ecb451abacb365e943caee8696fba00cd Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Wed, 16 Mar 2016 20:26:33 +0100 Subject: [PATCH 029/119] FBX: fix https://github.com/assimp/assimp/issues/782 --- code/FBXConverter.cpp | 5692 +++++++++++++++++++++-------------------- 1 file changed, 2940 insertions(+), 2752 deletions(-) diff --git a/code/FBXConverter.cpp b/code/FBXConverter.cpp index 200853a92..383ac65f0 100644 --- a/code/FBXConverter.cpp +++ b/code/FBXConverter.cpp @@ -103,1115 +103,90 @@ public: }; public: - Converter(aiScene* out, const Document& doc) - : defaultMaterialIndex() - , 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(); - ConvertRootNode(); - - if(doc.Settings().readAllMaterials) { - // unfortunately this means we have to evaluate all objects - BOOST_FOREACH(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); - } - } - } - } - - TransferDataToScene(); - - // 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; - } - } - - - ~Converter() - { - 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()); - } - + Converter( aiScene* out, const Document& doc ); + ~Converter(); private: // ------------------------------------------------------------------------------------------------ // find scene root and trigger recursive scene conversion - void ConvertRootNode() - { - out->mRootNode = new aiNode(); - out->mRootNode->mName.Set("RootNode"); - - // root has ID 0 - ConvertNodes(0L, *out->mRootNode); - } - + void ConvertRootNode(); // ------------------------------------------------------------------------------------------------ // collect and assign child nodes - void ConvertNodes(uint64_t id, aiNode& parent, const aiMatrix4x4& parent_transform = aiMatrix4x4()) - { - const std::vector& conns = doc.GetConnectionsByDestinationSequenced(id, "Model"); - - std::vector nodes; - nodes.reserve(conns.size()); - - std::vector nodes_chain; - - try { - BOOST_FOREACH(const Connection* con, conns) { - - // ignore object-property links - if(con->PropertyName().length()) { - continue; - } - - const Object* const object = con->SourceObject(); - if(!object) { - FBXImporter::LogWarn("failed to convert source object for Model link"); - continue; - } - - const Model* const model = dynamic_cast(object); - - if(model) { - nodes_chain.clear(); - - aiMatrix4x4 new_abs_transform = parent_transform; - - // 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. - GenerateTransformationNodeChain(*model,nodes_chain); - - ai_assert(nodes_chain.size()); - - const std::string& original_name = FixNodeName(model->Name()); - - // check if any of the nodes in the chain has the name the fbx node - // is supposed to have. If there is none, add another node to - // preserve the name - people might have scripts etc. that rely - // on specific node names. - aiNode* name_carrier = NULL; - BOOST_FOREACH(aiNode* prenode, nodes_chain) { - if ( !strcmp(prenode->mName.C_Str(), original_name.c_str()) ) { - name_carrier = prenode; - break; - } - } - - if(!name_carrier) { - nodes_chain.push_back(new aiNode(original_name)); - name_carrier = nodes_chain.back(); - } - - //setup metadata on newest node - SetupNodeMetadata(*model, *nodes_chain.back()); - - // link all nodes in a row - aiNode* last_parent = &parent; - BOOST_FOREACH(aiNode* prenode, nodes_chain) { - ai_assert(prenode); - - if(last_parent != &parent) { - last_parent->mNumChildren = 1; - last_parent->mChildren = new aiNode*[1]; - last_parent->mChildren[0] = prenode; - } - - prenode->mParent = last_parent; - last_parent = prenode; - - new_abs_transform *= prenode->mTransformation; - } - - // attach geometry - ConvertModel(*model, *nodes_chain.back(), new_abs_transform); - - // attach sub-nodes - ConvertNodes(model->ID(), *nodes_chain.back(), new_abs_transform); - - if(doc.Settings().readLights) { - ConvertLights(*model); - } - - if(doc.Settings().readCameras) { - ConvertCameras(*model); - } - - 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); - } - } - 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); - } - } + void ConvertNodes( uint64_t id, aiNode& parent, const aiMatrix4x4& parent_transform = aiMatrix4x4() ); // ------------------------------------------------------------------------------------------------ - void ConvertLights(const Model& model) - { - const std::vector& node_attrs = model.GetAttributes(); - BOOST_FOREACH(const NodeAttribute* attr, node_attrs) { - const Light* const light = dynamic_cast(attr); - if(light) { - ConvertLight(model, *light); - } - } - } + void ConvertLights( const Model& model ); // ------------------------------------------------------------------------------------------------ - void ConvertCameras(const Model& model) - { - const std::vector& node_attrs = model.GetAttributes(); - BOOST_FOREACH(const NodeAttribute* attr, node_attrs) { - const Camera* const cam = dynamic_cast(attr); - if(cam) { - ConvertCamera(model, *cam); - } - } - } - + void ConvertCameras( const Model& model ); // ------------------------------------------------------------------------------------------------ - void ConvertLight(const Model& model, const Light& light) - { - lights.push_back(new aiLight()); - aiLight* const out_light = lights.back(); - - out_light->mName.Set(FixNodeName(model.Name())); - - const float intensity = light.Intensity(); - 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; - - 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); - } - - // XXX: how to best convert the near and far decay ranges? - switch(light.DecayType()) - { - case Light::Decay_None: - out_light->mAttenuationConstant = 1.0f; - break; - case Light::Decay_Linear: - out_light->mAttenuationLinear = 1.0f; - break; - case Light::Decay_Quadratic: - out_light->mAttenuationQuadratic = 1.0f; - break; - case Light::Decay_Cubic: - FBXImporter::LogWarn("cannot represent cubic attenuation, set to Quadratic"); - out_light->mAttenuationQuadratic = 1.0f; - break; - default: - ai_assert(false); - } - } - + void ConvertLight( const Model& model, const Light& light ); // ------------------------------------------------------------------------------------------------ - void ConvertCamera(const Model& model, const Camera& cam) - { - cameras.push_back(new aiCamera()); - aiCamera* const out_camera = cameras.back(); - - out_camera->mName.Set(FixNodeName(model.Name())); - - out_camera->mAspect = cam.AspectWidth() / cam.AspectHeight(); - out_camera->mPosition = cam.Position(); - out_camera->mUp = cam.UpVector(); - out_camera->mLookAt = cam.InterestPosition() - out_camera->mPosition; - out_camera->mHorizontalFOV = AI_DEG_TO_RAD(cam.FieldOfView()); - } - + void ConvertCamera( const Model& model, const Camera& cam ); // ------------------------------------------------------------------------------------------------ // this returns unified names usable within assimp identifiers (i.e. no space characters - // while these would be allowed, they are a potential trouble spot so better not use them). - const char* 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_MAXIMUM: // this is to silence compiler warnings - default: - break; - } - - ai_assert(false); - return NULL; - } - + const char* NameTransformationComp( TransformationComp comp ); // ------------------------------------------------------------------------------------------------ // note: this returns the REAL fbx property names - const char* 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_MAXIMUM: // this is to silence compiler warnings - break; - } - - ai_assert(false); - return NULL; - } - + const char* NameTransformationCompProperty( TransformationComp comp ); // ------------------------------------------------------------------------------------------------ - aiVector3D 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(); - } - + aiVector3D TransformationCompDefaultValue( TransformationComp comp ); // ------------------------------------------------------------------------------------------------ - void 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 = 1e-6f; - - 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); - } - - ai_assert((order[0] >= 0) && (order[0] <= 2)); - ai_assert((order[1] >= 0) && (order[1] <= 2)); - ai_assert((order[2] >= 0) && (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]]; - } - } - - + void GetRotationMatrix( Model::RotOrder mode, const aiVector3D& rotation, aiMatrix4x4& out ); // ------------------------------------------------------------------------------------------------ - /** checks if a node has more than just scaling, rotation and translation components */ - bool NeedsComplexTransformationChain(const Model& model) - { - const PropertyTable& props = model.Props(); - bool ok; - - const float zero_epsilon = 1e-6f; - 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 || - comp == TransformationComp_GeometricScaling || comp == TransformationComp_GeometricRotation || comp == TransformationComp_GeometricTranslation ) { - continue; - } - - const aiVector3D& v = PropertyGet(props,NameTransformationCompProperty(comp),ok); - if(ok && v.SquareLength() > zero_epsilon) { - return true; - } - } - - return false; - } - + /** + * checks if a node has more than just scaling, rotation and translation components + */ + bool NeedsComplexTransformationChain( const Model& model ); // ------------------------------------------------------------------------------------------------ // note: name must be a FixNodeName() result - std::string NameTransformationChainNode(const std::string& name, TransformationComp comp) - { - return name + std::string(MAGIC_NODE_TAG) + "_" + NameTransformationComp(comp); - } - + std::string NameTransformationChainNode( const std::string& name, TransformationComp comp ); // ------------------------------------------------------------------------------------------------ - /** note: memory for output_nodes will be managed by the caller */ - void GenerateTransformationNodeChain(const Model& model, - std::vector& output_nodes) - { - const PropertyTable& props = model.Props(); - const Model::RotOrder rot = model.RotationOrder(); - - bool ok; - - aiMatrix4x4 chain[TransformationComp_MAXIMUM]; - std::fill_n(chain, static_cast(TransformationComp_MAXIMUM), aiMatrix4x4()); - - // generate transformation matrices for all the different transformation components - const float zero_epsilon = 1e-6f; - bool is_complex = false; - - const aiVector3D& PreRotation = PropertyGet(props,"PreRotation",ok); - if(ok && PreRotation.SquareLength() > zero_epsilon) { - is_complex = true; - - GetRotationMatrix(rot, PreRotation, chain[TransformationComp_PreRotation]); - } - - const aiVector3D& PostRotation = PropertyGet(props,"PostRotation",ok); - if(ok && PostRotation.SquareLength() > zero_epsilon) { - is_complex = true; - - GetRotationMatrix(rot, PostRotation, chain[TransformationComp_PostRotation]); - } - - const aiVector3D& RotationPivot = PropertyGet(props,"RotationPivot",ok); - if(ok && RotationPivot.SquareLength() > zero_epsilon) { - is_complex = true; - - 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) { - is_complex = true; - - aiMatrix4x4::Translation(RotationOffset,chain[TransformationComp_RotationOffset]); - } - - const aiVector3D& ScalingOffset = PropertyGet(props,"ScalingOffset",ok); - if(ok && ScalingOffset.SquareLength() > zero_epsilon) { - is_complex = true; - - aiMatrix4x4::Translation(ScalingOffset,chain[TransformationComp_ScalingOffset]); - } - - const aiVector3D& ScalingPivot = PropertyGet(props,"ScalingPivot",ok); - if(ok && ScalingPivot.SquareLength() > zero_epsilon) { - is_complex = true; - - 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) { - aiMatrix4x4::Translation(Translation,chain[TransformationComp_Translation]); - } - - const aiVector3D& Scaling = PropertyGet(props,"Lcl Scaling",ok); - if(ok && std::fabs(Scaling.SquareLength()-1.0f) > zero_epsilon) { - aiMatrix4x4::Scaling(Scaling,chain[TransformationComp_Scaling]); - } - - const aiVector3D& Rotation = PropertyGet(props,"Lcl Rotation",ok); - if(ok && Rotation.SquareLength() > zero_epsilon) { - GetRotationMatrix(rot, Rotation, chain[TransformationComp_Rotation]); - } - - const aiVector3D& GeometricScaling = PropertyGet(props, "GeometricScaling", ok); - if (ok && std::fabs(GeometricScaling.SquareLength() - 1.0f) > zero_epsilon) { - aiMatrix4x4::Scaling(GeometricScaling, chain[TransformationComp_GeometricScaling]); - } - - const aiVector3D& GeometricRotation = PropertyGet(props, "GeometricRotation", ok); - if (ok && GeometricRotation.SquareLength() > zero_epsilon) { - GetRotationMatrix(rot, GeometricRotation, chain[TransformationComp_GeometricRotation]); - } - - const aiVector3D& GeometricTranslation = PropertyGet(props, "GeometricTranslation", ok); - if (ok && GeometricTranslation.SquareLength() > zero_epsilon){ - aiMatrix4x4::Translation(GeometricTranslation, chain[TransformationComp_GeometricTranslation]); - } - - // 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) == is_complex); - - const std::string& name = FixNodeName(model.Name()); - - // 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(is_complex && 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 (chain[i].IsIdentity() && (anim_chain_bitmask & bit) == 0) { - continue; - } - - aiNode* nd = new aiNode(); - output_nodes.push_back(nd); - - nd->mName.Set(NameTransformationChainNode(name, comp)); - nd->mTransformation = chain[i]; - } - - ai_assert(output_nodes.size()); - return; - } - - // else, we can just multiply the matrices together - aiNode* nd = new aiNode(); - output_nodes.push_back(nd); - - nd->mName.Set(name); - - for (size_t i = 0; i < TransformationComp_MAXIMUM; ++i) { - nd->mTransformation = nd->mTransformation * chain[i]; - } - } + /** + * note: memory for output_nodes will be managed by the caller + */ + void GenerateTransformationNodeChain( const Model& model, std::vector& output_nodes ); // ------------------------------------------------------------------------------------------------ - - void SetupNodeMetadata(const Model& model, aiNode& nd) - { - const PropertyTable& props = model.Props(); - DirectPropertyMap unparsedProperties = props.GetUnparsedProperties(); - - // create metadata on node - std::size_t numStaticMetaData = 2; - aiMetadata* data = new aiMetadata(); - data->mNumProperties = unparsedProperties.size() + numStaticMetaData; - data->mKeys = new aiString[data->mNumProperties](); - data->mValues = new aiMetadataEntry[data->mNumProperties](); - 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 - BOOST_FOREACH(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 - assert(false); - } - } + void SetupNodeMetadata( const Model& model, aiNode& nd ); // ------------------------------------------------------------------------------------------------ - void ConvertModel(const Model& model, aiNode& nd, const aiMatrix4x4& node_global_transform) - { - const std::vector& geos = model.GetGeometry(); - - std::vector meshes; - meshes.reserve(geos.size()); - - BOOST_FOREACH(const Geometry* geo, geos) { - - const MeshGeometry* const mesh = dynamic_cast(geo); - if(mesh) { - const std::vector& indices = ConvertMesh(*mesh, model, node_global_transform); - std::copy(indices.begin(),indices.end(),std::back_inserter(meshes) ); - } - else { - FBXImporter::LogWarn("ignoring unrecognized geometry: " + geo->Name()); - } - } - - if(meshes.size()) { - nd.mMeshes = new unsigned int[meshes.size()](); - nd.mNumMeshes = static_cast(meshes.size()); - - std::swap_ranges(meshes.begin(),meshes.end(),nd.mMeshes); - } - } - + void ConvertModel( const Model& model, aiNode& nd, const aiMatrix4x4& node_global_transform ); // ------------------------------------------------------------------------------------------------ // MeshGeometry -> aiMesh, return mesh index + 1 or 0 if the conversion failed - std::vector ConvertMesh(const MeshGeometry& mesh,const Model& model, - const aiMatrix4x4& node_global_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]; - BOOST_FOREACH(MatIndexArray::value_type index, mindices) { - if(index != base) { - return ConvertMeshMultiMaterial(mesh, model, node_global_transform); - } - } - } - - // faster code-path, just copy the data - temp.push_back(ConvertMeshSingleMaterial(mesh, model, node_global_transform)); - return temp; - } - + std::vector ConvertMesh( const MeshGeometry& mesh, const Model& model, + const aiMatrix4x4& node_global_transform ); // ------------------------------------------------------------------------------------------------ - aiMesh* SetupEmptyMesh(const MeshGeometry& mesh) - { - 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); - } - - return out_mesh; - } - + aiMesh* SetupEmptyMesh( const MeshGeometry& mesh ); // ------------------------------------------------------------------------------------------------ - unsigned int ConvertMeshSingleMaterial(const MeshGeometry& mesh, const Model& model, - const aiMatrix4x4& node_global_transform) - { - const MatIndexArray& mindices = mesh.GetMaterialIndices(); - aiMesh* const out_mesh = SetupEmptyMesh(mesh); - - 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; - BOOST_FOREACH(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 = NULL; - } - } - - 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()]; - BOOST_FOREACH(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() != NULL) { - ConvertWeights(out_mesh, model, mesh, node_global_transform, NO_MATERIAL_SEPARATION); - } - - return static_cast(meshes.size() - 1); - } - + unsigned int ConvertMeshSingleMaterial( const MeshGeometry& mesh, const Model& model, + const aiMatrix4x4& node_global_transform ); // ------------------------------------------------------------------------------------------------ - std::vector ConvertMeshMultiMaterial(const MeshGeometry& mesh, const Model& model, - const aiMatrix4x4& node_global_transform) - { - const MatIndexArray& mindices = mesh.GetMaterialIndices(); - ai_assert(mindices.size()); - - std::set had; - std::vector indices; - - BOOST_FOREACH(MatIndexArray::value_type index, mindices) { - if(had.find(index) == had.end()) { - - indices.push_back(ConvertMeshMultiMaterial(mesh, model, index, node_global_transform)); - had.insert(index); - } - } - - return indices; - } - + std::vector ConvertMeshMultiMaterial( const MeshGeometry& mesh, const Model& model, + const aiMatrix4x4& node_global_transform ); // ------------------------------------------------------------------------------------------------ - unsigned int ConvertMeshMultiMaterial(const MeshGeometry& mesh, const Model& model, + unsigned int ConvertMeshMultiMaterial( const MeshGeometry& mesh, const Model& model, MatIndexArray::value_type index, - const aiMatrix4x4& node_global_transform) - { - aiMesh* const out_mesh = SetupEmptyMesh(mesh); - - 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() != NULL; - - 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 - std::vector reverseMapping; - - if (process_weights) { - 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(); - - if(tangents.size()) { - std::vector tempBinormals; - 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 = NULL; - } - } - - 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; - } - - 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 i = 0; i < num_uvs; ++i) { - const std::vector& uvs = mesh.GetTextureCoords(i); - out_mesh->mTextureCoords[i][cursor] = aiVector3D(uvs[in_cursor].x,uvs[in_cursor].y, 0.0f); - } - - for (unsigned int i = 0; i < num_vcs; ++i) { - const std::vector& cols = mesh.GetVertexColors(i); - out_mesh->mColors[i][cursor] = cols[in_cursor]; - } - } - } - - ConvertMaterialForMesh(out_mesh,model,mesh,index); - - if(process_weights) { - ConvertWeights(out_mesh, model, mesh, node_global_transform, index, &reverseMapping); - } - - return static_cast(meshes.size() - 1); - } + const aiMatrix4x4& node_global_transform ); + // ------------------------------------------------------------------------------------------------ static const unsigned int NO_MATERIAL_SEPARATION = /* std::numeric_limits::max() */ static_cast(-1); @@ -1223,707 +198,64 @@ private: * - outputVertStartIndices is only used when a material index is specified, it gives for * each output vertex the DOM index it maps to. */ - void ConvertWeights(aiMesh* out, const Model& model, const MeshGeometry& geo, + void ConvertWeights( aiMesh* out, const Model& model, const MeshGeometry& geo, const aiMatrix4x4& node_global_transform = aiMatrix4x4(), unsigned int materialIndex = NO_MATERIAL_SEPARATION, - std::vector* outputVertStartIndices = NULL) - { - 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; - bones.reserve(sk.Clusters().size()); - - const bool no_mat_check = materialIndex == NO_MATERIAL_SEPARATION; - ai_assert(no_mat_check || outputVertStartIndices); - - try { - - BOOST_FOREACH(const Cluster* cluster, sk.Clusters()) { - ai_assert(cluster); - - const WeightIndexArray& indices = cluster->GetIndices(); - - if(indices.empty()) { - continue; - } - - const MatIndexArray& mats = geo.GetMaterialIndices(); - - bool ok = false; - - 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. - BOOST_FOREACH(WeightIndexArray::value_type index, indices) { - - unsigned int count = 0; - const unsigned int* const out_idx = geo.ToOutputVertexIndex(index, count); - // ToOutputVertexIndex only returns NULL if index is out of bounds - // which should never happen - ai_assert(out_idx != NULL); - - 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(); - ok = true; - } - } - } - - // 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. - if (ok) { - ConvertCluster(bones, model, *cluster, out_indices, index_out_indices, - count_out_indices, node_global_transform); - } - } - } - catch (std::exception&) { - std::for_each(bones.begin(),bones.end(),Util::delete_fun()); - throw; - } - - if(bones.empty()) { - return; - } - - out->mBones = new aiBone*[bones.size()](); - out->mNumBones = static_cast(bones.size()); - - std::swap_ranges(bones.begin(),bones.end(),out->mBones); - } - - + std::vector* outputVertStartIndices = NULL ); // ------------------------------------------------------------------------------------------------ - void ConvertCluster(std::vector& bones, const Model& /*model*/, const Cluster& cl, + void ConvertCluster( std::vector& bones, const Model& /*model*/, const Cluster& cl, std::vector& out_indices, std::vector& index_out_indices, std::vector& count_out_indices, - const aiMatrix4x4& node_global_transform) - { - - aiBone* const bone = new aiBone(); - bones.push_back(bone); - - bone->mName = FixNodeName(cl.TargetNode()->Name()); - - bone->mOffsetMatrix = cl.TransformLink(); - bone->mOffsetMatrix.Inverse(); - - bone->mOffsetMatrix = bone->mOffsetMatrix * node_global_transform; - - bone->mNumWeights = static_cast(out_indices.size()); - aiVertexWeight* 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) { - aiVertexWeight& out_weight = *cursor++; - - out_weight.mVertexId = static_cast(out_indices[index_index + j]); - out_weight.mWeight = weights[i]; - } - } - } - + const aiMatrix4x4& node_global_transform ); // ------------------------------------------------------------------------------------------------ - void 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; - } - + void ConvertMaterialForMesh( aiMesh* out, const Model& model, const MeshGeometry& geo, + MatIndexArray::value_type materialIndex ); // ------------------------------------------------------------------------------------------------ - unsigned int 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 GetDefaultMaterial(); // ------------------------------------------------------------------------------------------------ // Material -> aiMaterial - unsigned int 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; - - // stip 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); - } - - // shading stuff and colors - SetShadingPropertiesCommon(out_mat,props); - - // texture assignments - SetTextureProperties(out_mat,material.Textures(), mesh); - SetTextureProperties(out_mat,material.LayeredTextures(), mesh); - - return static_cast(materials.size() - 1); - } + unsigned int ConvertMaterial( const Material& material, const MeshGeometry* const mesh ); // ------------------------------------------------------------------------------------------------ // Video -> aiTexture - unsigned int 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.FileName().empty() ? video.RelativeFilename() : video.FileName(); - std::string ext = BaseImporter::GetExtension(filename); - - if(ext == "jpeg") { - ext = "jpg"; - } - - if(ext.size() <= 3) { - memcpy(out_tex->achFormatHint, ext.c_str(), ext.size()); - } - - return static_cast(textures.size() - 1); - } - + unsigned int ConvertVideo( const Video& video ); // ------------------------------------------------------------------------------------------------ - void TrySetTextureProperties(aiMaterial* out_mat, const TextureMap& textures, + void 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; - path.Set(tex->RelativeFilename()); - - const Video* media = tex->Media(); - if(media != 0 && media->ContentLength() > 0) { - unsigned int index; - - VideoMap::const_iterator it = textures_converted.find(media); - if(it != textures_converted.end()) { - index = (*it).second; - } - else { - index = ConvertVideo(*media); - textures_converted[media] = index; - } - - // setup texture reference string (copied from ColladaLoader::FindFilenameForEffectTexture) - path.data[0] = '*'; - path.length = 1 + ASSIMP_itoa10(path.data + 1, MAXLEN - 1, index); - } - - 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) - { - BOOST_FOREACH(const MeshMap::value_type& v,meshes_converted) { - const MeshGeometry* const mesh = dynamic_cast (v.first); - if(!mesh) { - continue; - } - - const MatIndexArray& mats = mesh->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(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"); - 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); - } - } + aiTextureType target, const MeshGeometry* const mesh ); // ------------------------------------------------------------------------------------------------ - void TrySetTextureProperties(aiMaterial* out_mat, const LayeredTextureMap& layeredTextures, + void 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; - } - - const Texture* const tex = (*it).second->getTexture(); - - aiString path; - path.Set(tex->RelativeFilename()); - - 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) - { - BOOST_FOREACH(const MeshMap::value_type& v,meshes_converted) { - const MeshGeometry* const mesh = dynamic_cast (v.first); - if(!mesh) { - continue; - } - - const MatIndexArray& mats = mesh->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(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"); - 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); - } + aiTextureType target, const MeshGeometry* const mesh ); // ------------------------------------------------------------------------------------------------ - void 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, "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); - } + void SetTextureProperties( aiMaterial* out_mat, const TextureMap& textures, const MeshGeometry* const mesh ); // ------------------------------------------------------------------------------------------------ - void 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, "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); - } - + void SetTextureProperties( aiMaterial* out_mat, const LayeredTextureMap& layeredTextures, const MeshGeometry* const mesh ); // ------------------------------------------------------------------------------------------------ - aiColor3D GetColorPropertyFromMaterial(const PropertyTable& props, const std::string& baseName, - bool& result) - { - result = true; - - bool ok; - const aiVector3D& Diffuse = PropertyGet(props,baseName,ok); - if(ok) { - return aiColor3D(Diffuse.x,Diffuse.y,Diffuse.z); - } - else { - aiVector3D DiffuseColor = PropertyGet(props,baseName + "Color",ok); - if(ok) { - float DiffuseFactor = PropertyGet(props,baseName + "Factor",ok); - if(ok) { - DiffuseColor *= DiffuseFactor; - } - - return aiColor3D(DiffuseColor.x,DiffuseColor.y,DiffuseColor.z); - } - } - result = false; - return aiColor3D(0.0f,0.0f,0.0f); - } - + aiColor3D GetColorPropertyFromMaterial( const PropertyTable& props, const std::string& baseName, + bool& result ); // ------------------------------------------------------------------------------------------------ - void SetShadingPropertiesCommon(aiMaterial* out_mat, const PropertyTable& props) - { - // set shading properties. There are various, redundant ways in which FBX materials - // specify their shading settings (depending on shading models, prop - // template etc.). No idea which one is right in a particular context. - // Just try to make sense of it - there's no spec to verify this against, - // so why should we. - 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); - } - - const aiColor3D& Specular = GetColorPropertyFromMaterial(props,"Specular",ok); - if(ok) { - out_mat->AddProperty(&Specular,1,AI_MATKEY_COLOR_SPECULAR); - } - - const float Opacity = PropertyGet(props,"Opacity",ok); - if(ok) { - out_mat->AddProperty(&Opacity,1,AI_MATKEY_OPACITY); - } - - const float Reflectivity = PropertyGet(props,"Reflectivity",ok); - if(ok) { - out_mat->AddProperty(&Reflectivity,1,AI_MATKEY_REFLECTIVITY); - } - - const float Shininess = PropertyGet(props,"Shininess",ok); - if(ok) { - out_mat->AddProperty(&Shininess,1,AI_MATKEY_SHININESS_STRENGTH); - } - - const float ShininessExponent = PropertyGet(props,"ShininessExponent",ok); - if(ok) { - out_mat->AddProperty(&ShininessExponent,1,AI_MATKEY_SHININESS); - } - } - + void SetShadingPropertiesCommon( aiMaterial* out_mat, const PropertyTable& props ); // ------------------------------------------------------------------------------------------------ // get the number of fps for a FrameRate enumerated value - static double FrameRateToDouble(FileGlobalSettings::FrameRate fp, double customFPSVal = -1.0) - { - switch(fp) { - case FileGlobalSettings::FrameRate_DEFAULT: - return 1.0; - - case FileGlobalSettings::FrameRate_120: - return 120.0; - - case FileGlobalSettings::FrameRate_100: - return 100.0; - - case FileGlobalSettings::FrameRate_60: - return 60.0; - - case FileGlobalSettings::FrameRate_50: - return 50.0; - - case FileGlobalSettings::FrameRate_48: - return 48.0; - - case FileGlobalSettings::FrameRate_30: - case FileGlobalSettings::FrameRate_30_DROP: - return 30.0; - - case FileGlobalSettings::FrameRate_NTSC_DROP_FRAME: - case FileGlobalSettings::FrameRate_NTSC_FULL_FRAME: - return 29.9700262; - - case FileGlobalSettings::FrameRate_PAL: - return 25.0; - - case FileGlobalSettings::FrameRate_CINEMA: - return 24.0; - - case FileGlobalSettings::FrameRate_1000: - return 1000.0; - - case FileGlobalSettings::FrameRate_CINEMA_ND: - return 23.976; - - case FileGlobalSettings::FrameRate_CUSTOM: - return customFPSVal; - - case FileGlobalSettings::FrameRate_MAX: // this is to silence compiler warnings - break; - } - - ai_assert(false); - return -1.0f; - } - + static double FrameRateToDouble( FileGlobalSettings::FrameRate fp, double customFPSVal = -1.0 ); // ------------------------------------------------------------------------------------------------ // convert animation data to aiAnimation et al - void ConvertAnimations() - { - // first of all determine framerate - const FileGlobalSettings::FrameRate fps = doc.GlobalSettings().TimeMode(); - const float custom = doc.GlobalSettings().CustomFrameRate(); - anim_fps = FrameRateToDouble(fps, custom); - - const std::vector& animations = doc.AnimationStacks(); - BOOST_FOREACH(const AnimationStack* stack, animations) { - ConvertAnimationStack(*stack); - } - } - + void ConvertAnimations(); // ------------------------------------------------------------------------------------------------ // rename a node already partially converted. fixed_name is a string previously returned by @@ -1935,78 +267,13 @@ private: // NOTE: the caller is responsible for ensuring that the new name is unique and does // not collide with any other identifiers. The best way to ensure this is to only // append to the old name, which is guaranteed to match these requirements. - void RenameNode(const std::string& fixed_name, const std::string& new_name) - { - ai_assert(node_names.find(fixed_name) != node_names.end()); - ai_assert(node_names.find(new_name) == node_names.end()); - - renamed_nodes[fixed_name] = new_name; - - const aiString fn(fixed_name); - - BOOST_FOREACH(aiCamera* cam, cameras) { - if (cam->mName == fn) { - cam->mName.Set(new_name); - break; - } - } - - BOOST_FOREACH(aiLight* light, lights) { - if (light->mName == fn) { - light->mName.Set(new_name); - break; - } - } - - BOOST_FOREACH(aiAnimation* anim, animations) { - for (unsigned int i = 0; i < anim->mNumChannels; ++i) { - aiNodeAnim* const na = anim->mChannels[i]; - if (na->mNodeName == fn) { - na->mNodeName.Set(new_name); - break; - } - } - } - } - + void RenameNode( const std::string& fixed_name, const std::string& new_name ); // ------------------------------------------------------------------------------------------------ // takes a fbx node name and returns the identifier to be used in the assimp output scene. // the function is guaranteed to provide consistent results over multiple invocations // UNLESS RenameNode() is called for a particular node name. - std::string FixNodeName(const std::string& name) - { - // strip Model:: prefix, avoiding ambiguities (i.e. don't strip if - // this causes ambiguities, well possible between empty identifiers, - // such as "Model::" and ""). Make sure the behaviour is consistent - // across multiple calls to FixNodeName(). - if(name.substr(0,7) == "Model::") { - std::string temp = name.substr(7); - - const NodeNameMap::const_iterator it = node_names.find(temp); - if (it != node_names.end()) { - if (!(*it).second) { - return FixNodeName(name + "_"); - } - } - node_names[temp] = true; - - const NameNameMap::const_iterator rit = renamed_nodes.find(temp); - return rit == renamed_nodes.end() ? temp : (*rit).second; - } - - const NodeNameMap::const_iterator it = node_names.find(name); - if (it != node_names.end()) { - if ((*it).second) { - return FixNodeName(name + "_"); - } - } - node_names[name] = false; - - const NameNameMap::const_iterator rit = renamed_nodes.find(name); - return rit == renamed_nodes.end() ? name : (*rit).second; - } - + std::string FixNodeName( const std::string& name ); typedef std::map LayerMap; @@ -2015,661 +282,61 @@ private: // ------------------------------------------------------------------------------------------------ - void ConvertAnimationStack(const AnimationStack& st) - { - const AnimationLayerList& layers = st.Layers(); - if(layers.empty()) { - return; - } - - aiAnimation* const anim = new aiAnimation(); - animations.push_back(anim); - - // strip AnimationStack:: prefix - std::string name = st.Name(); - if (name.substr(0, 16) == "AnimationStack::") { - name = name.substr(16); - } - else if (name.substr(0, 11) == "AnimStack::") { - name = name.substr(11); - } - - anim->mName.Set(name); - - // need to find all nodes for which we need to generate node animations - - // it may happen that we need to merge multiple layers, though. - NodeMap node_map; - - // reverse mapping from curves to layers, much faster than querying - // the FBX DOM for it. - LayerMap layer_map; - - const char* prop_whitelist[] = { - "Lcl Scaling", - "Lcl Rotation", - "Lcl Translation" - }; - - BOOST_FOREACH(const AnimationLayer* layer, layers) { - ai_assert(layer); - - const AnimationCurveNodeList& nodes = layer->Nodes(prop_whitelist, 3); - BOOST_FOREACH(const AnimationCurveNode* node, nodes) { - ai_assert(node); - - const Model* const model = dynamic_cast(node->Target()); - // this can happen - it could also be a NodeAttribute (i.e. for camera animations) - if(!model) { - continue; - } - - const std::string& name = FixNodeName(model->Name()); - node_map[name].push_back(node); - - layer_map[node] = layer; - } - } - - // generate node animations - std::vector node_anims; - - double min_time = 1e10; - double max_time = -1e10; - - int64_t start_time = st.LocalStart(); - int64_t stop_time = st.LocalStop(); - double start_timeF = CONVERT_FBX_TIME(start_time); - double stop_timeF = CONVERT_FBX_TIME(stop_time); - - try { - BOOST_FOREACH(const NodeMap::value_type& kv, node_map) { - GenerateNodeAnimations(node_anims, - kv.first, - kv.second, - layer_map, - start_time, stop_time, - max_time, - min_time); - } - } - catch(std::exception&) { - std::for_each(node_anims.begin(), node_anims.end(), Util::delete_fun()); - throw; - } - - if(node_anims.size()) { - anim->mChannels = new aiNodeAnim*[node_anims.size()](); - anim->mNumChannels = static_cast(node_anims.size()); - - std::swap_ranges(node_anims.begin(),node_anims.end(),anim->mChannels); - } - else { - // empty animations would fail validation, so drop them - delete anim; - animations.pop_back(); - FBXImporter::LogInfo("ignoring empty AnimationStack (using IK?): " + name); - return; - } - - //adjust relative timing for animation - { - double start_fps = start_timeF * anim_fps; - - for (unsigned int c = 0; c < anim->mNumChannels; c++) - { - aiNodeAnim* channel = anim->mChannels[c]; - for (uint32_t i = 0; i < channel->mNumPositionKeys; i++) - channel->mPositionKeys[i].mTime -= start_fps; - for (uint32_t i = 0; i < channel->mNumRotationKeys; i++) - channel->mRotationKeys[i].mTime -= start_fps; - for (uint32_t i = 0; i < channel->mNumScalingKeys; i++) - channel->mScalingKeys[i].mTime -= start_fps; - } - - max_time -= min_time; - } - - // for some mysterious reason, mDuration is simply the maximum key -- the - // validator always assumes animations to start at zero. - anim->mDuration = (stop_timeF - start_timeF) * anim_fps; - anim->mTicksPerSecond = anim_fps; - } - + void ConvertAnimationStack( const AnimationStack& st ); // ------------------------------------------------------------------------------------------------ - void GenerateNodeAnimations(std::vector& node_anims, + void GenerateNodeAnimations( std::vector& node_anims, const std::string& fixed_name, const std::vector& curves, const LayerMap& layer_map, int64_t start, int64_t stop, double& max_time, - double& min_time) - { - - NodeMap node_property_map; - ai_assert(curves.size()); - - // sanity check whether the input is ok -#ifdef ASSIMP_BUILD_DEBUG - { const Object* target = NULL; - BOOST_FOREACH(const AnimationCurveNode* node, curves) { - if(!target) { - target = node->Target(); - } - ai_assert(node->Target() == target); - }} -#endif - - const AnimationCurveNode* curve_node = NULL; - BOOST_FOREACH(const AnimationCurveNode* node, curves) { - ai_assert(node); - - if (node->TargetProperty().empty()) { - FBXImporter::LogWarn("target property for animation curve not set: " + node->Name()); - continue; - } - - curve_node = node; - if (node->Curves().empty()) { - FBXImporter::LogWarn("no animation curves assigned to AnimationCurveNode: " + node->Name()); - continue; - } - - node_property_map[node->TargetProperty()].push_back(node); - } - - ai_assert(curve_node); - ai_assert(curve_node->TargetAsModel()); - - const Model& target = *curve_node->TargetAsModel(); - - // check for all possible transformation components - NodeMap::const_iterator chain[TransformationComp_MAXIMUM]; - - bool has_any = false; - bool has_complex = false; - - for (size_t i = 0; i < TransformationComp_MAXIMUM; ++i) { - const TransformationComp comp = static_cast(i); - - // inverse pivots don't exist in the input, we just generate them - if (comp == TransformationComp_RotationPivotInverse || comp == TransformationComp_ScalingPivotInverse) { - chain[i] = node_property_map.end(); - continue; - } - - chain[i] = node_property_map.find(NameTransformationCompProperty(comp)); - if (chain[i] != node_property_map.end()) { - - // check if this curves contains redundant information by looking - // up the corresponding node's transformation chain. - if (doc.Settings().optimizeEmptyAnimationCurves && - IsRedundantAnimationData(target, comp, (*chain[i]).second)) { - - FBXImporter::LogDebug("dropping redundant animation channel for node " + target.Name()); - continue; - } - - has_any = true; - - if (comp != TransformationComp_Rotation && comp != TransformationComp_Scaling && comp != TransformationComp_Translation && - comp != TransformationComp_GeometricScaling && comp != TransformationComp_GeometricRotation && comp != TransformationComp_GeometricTranslation ) - { - has_complex = true; - } - } - } - - if (!has_any) { - FBXImporter::LogWarn("ignoring node animation, did not find any transformation key frames"); - return; - } - - // this needs to play nicely with GenerateTransformationNodeChain() which will - // be invoked _later_ (animations come first). If this node has only rotation, - // scaling and translation _and_ there are no animated other components either, - // we can use a single node and also a single node animation channel. - if (!has_complex && !NeedsComplexTransformationChain(target)) { - - aiNodeAnim* const nd = GenerateSimpleNodeAnim(fixed_name, target, chain, - node_property_map.end(), - layer_map, - start, stop, - max_time, - min_time, - true // input is TRS order, assimp is SRT - ); - - ai_assert(nd); - if (nd->mNumPositionKeys == 0 && nd->mNumRotationKeys == 0 && nd->mNumScalingKeys == 0) { - delete nd; - } - else { - node_anims.push_back(nd); - } - return; - } - - // otherwise, things get gruesome and we need separate animation channels - // for each part of the transformation chain. Remember which channels - // we generated and pass this information to the node conversion - // code to avoid nodes that have identity transform, but non-identity - // animations, being dropped. - unsigned int flags = 0, bit = 0x1; - for (size_t i = 0; i < TransformationComp_MAXIMUM; ++i, bit <<= 1) { - const TransformationComp comp = static_cast(i); - - if (chain[i] != node_property_map.end()) { - flags |= bit; - - ai_assert(comp != TransformationComp_RotationPivotInverse); - ai_assert(comp != TransformationComp_ScalingPivotInverse); - - const std::string& chain_name = NameTransformationChainNode(fixed_name, comp); - - aiNodeAnim* na; - switch(comp) - { - case TransformationComp_Rotation: - case TransformationComp_PreRotation: - case TransformationComp_PostRotation: - case TransformationComp_GeometricRotation: - na = GenerateRotationNodeAnim(chain_name, - target, - (*chain[i]).second, - layer_map, - start, stop, - max_time, - min_time); - - break; - - case TransformationComp_RotationOffset: - case TransformationComp_RotationPivot: - case TransformationComp_ScalingOffset: - case TransformationComp_ScalingPivot: - case TransformationComp_Translation: - case TransformationComp_GeometricTranslation: - na = GenerateTranslationNodeAnim(chain_name, - target, - (*chain[i]).second, - layer_map, - start, stop, - max_time, - min_time); - - // pivoting requires us to generate an implicit inverse channel to undo the pivot translation - if (comp == TransformationComp_RotationPivot) { - const std::string& invName = NameTransformationChainNode(fixed_name, - TransformationComp_RotationPivotInverse); - - aiNodeAnim* const inv = GenerateTranslationNodeAnim(invName, - target, - (*chain[i]).second, - layer_map, - start, stop, - max_time, - min_time, - true); - - ai_assert(inv); - if (inv->mNumPositionKeys == 0 && inv->mNumRotationKeys == 0 && inv->mNumScalingKeys == 0) { - delete inv; - } - else { - node_anims.push_back(inv); - } - - ai_assert(TransformationComp_RotationPivotInverse > i); - flags |= bit << (TransformationComp_RotationPivotInverse - i); - } - else if (comp == TransformationComp_ScalingPivot) { - const std::string& invName = NameTransformationChainNode(fixed_name, - TransformationComp_ScalingPivotInverse); - - aiNodeAnim* const inv = GenerateTranslationNodeAnim(invName, - target, - (*chain[i]).second, - layer_map, - start, stop, - max_time, - min_time, - true); - - ai_assert(inv); - if (inv->mNumPositionKeys == 0 && inv->mNumRotationKeys == 0 && inv->mNumScalingKeys == 0) { - delete inv; - } - else { - node_anims.push_back(inv); - } - - ai_assert(TransformationComp_RotationPivotInverse > i); - flags |= bit << (TransformationComp_RotationPivotInverse - i); - } - - break; - - case TransformationComp_Scaling: - case TransformationComp_GeometricScaling: - na = GenerateScalingNodeAnim(chain_name, - target, - (*chain[i]).second, - layer_map, - start, stop, - max_time, - min_time); - - break; - - default: - ai_assert(false); - } - - ai_assert(na); - if (na->mNumPositionKeys == 0 && na->mNumRotationKeys == 0 && na->mNumScalingKeys == 0) { - delete na; - } - else { - node_anims.push_back(na); - } - continue; - } - } - - node_anim_chain_bits[fixed_name] = flags; - } - + double& min_time ); // ------------------------------------------------------------------------------------------------ - bool IsRedundantAnimationData(const Model& target, + bool IsRedundantAnimationData( const Model& target, TransformationComp comp, - const std::vector& curves) - { - ai_assert(curves.size()); - - // look for animation nodes with - // * sub channels for all relevant components set - // * one key/value pair per component - // * combined values match up the corresponding value in the bind pose node transformation - // only such nodes are 'redundant' for this function. - - if (curves.size() > 1) { - return false; - } - - const AnimationCurveNode& nd = *curves.front(); - const AnimationCurveMap& sub_curves = nd.Curves(); - - const AnimationCurveMap::const_iterator dx = sub_curves.find("d|X"); - const AnimationCurveMap::const_iterator dy = sub_curves.find("d|Y"); - const AnimationCurveMap::const_iterator dz = sub_curves.find("d|Z"); - - if (dx == sub_curves.end() || dy == sub_curves.end() || dz == sub_curves.end()) { - return false; - } - - const KeyValueList& vx = (*dx).second->GetValues(); - const KeyValueList& vy = (*dy).second->GetValues(); - const KeyValueList& vz = (*dz).second->GetValues(); - - if(vx.size() != 1 || vy.size() != 1 || vz.size() != 1) { - return false; - } - - const aiVector3D dyn_val = aiVector3D(vx[0], vy[0], vz[0]); - const aiVector3D& static_val = PropertyGet(target.Props(), - NameTransformationCompProperty(comp), - TransformationCompDefaultValue(comp) - ); - - const float epsilon = 1e-6f; - return (dyn_val - static_val).SquareLength() < epsilon; - } - + const std::vector& curves ); // ------------------------------------------------------------------------------------------------ - aiNodeAnim* GenerateRotationNodeAnim(const std::string& name, + aiNodeAnim* GenerateRotationNodeAnim( const std::string& name, const Model& target, const std::vector& curves, const LayerMap& layer_map, int64_t start, int64_t stop, double& max_time, - double& min_time) - { - ScopeGuard na(new aiNodeAnim()); - na->mNodeName.Set(name); - - ConvertRotationKeys(na, curves, layer_map, start, stop, max_time, min_time, target.RotationOrder()); - - // dummy scaling key - na->mScalingKeys = new aiVectorKey[1]; - na->mNumScalingKeys = 1; - - na->mScalingKeys[0].mTime = 0.; - na->mScalingKeys[0].mValue = aiVector3D(1.0f,1.0f,1.0f); - - // dummy position key - na->mPositionKeys = new aiVectorKey[1]; - na->mNumPositionKeys = 1; - - na->mPositionKeys[0].mTime = 0.; - na->mPositionKeys[0].mValue = aiVector3D(); - - return na.dismiss(); - } - + double& min_time ); // ------------------------------------------------------------------------------------------------ - aiNodeAnim* GenerateScalingNodeAnim(const std::string& name, + aiNodeAnim* GenerateScalingNodeAnim( const std::string& name, const Model& /*target*/, const std::vector& curves, const LayerMap& layer_map, int64_t start, int64_t stop, double& max_time, - double& min_time) - { - ScopeGuard na(new aiNodeAnim()); - na->mNodeName.Set(name); - - ConvertScaleKeys(na, curves, layer_map, start, stop, max_time, min_time); - - // dummy rotation key - na->mRotationKeys = new aiQuatKey[1]; - na->mNumRotationKeys = 1; - - na->mRotationKeys[0].mTime = 0.; - na->mRotationKeys[0].mValue = aiQuaternion(); - - // dummy position key - na->mPositionKeys = new aiVectorKey[1]; - na->mNumPositionKeys = 1; - - na->mPositionKeys[0].mTime = 0.; - na->mPositionKeys[0].mValue = aiVector3D(); - - return na.dismiss(); - } - + double& min_time ); // ------------------------------------------------------------------------------------------------ - aiNodeAnim* GenerateTranslationNodeAnim(const std::string& name, + aiNodeAnim* GenerateTranslationNodeAnim( const std::string& name, const Model& /*target*/, const std::vector& curves, const LayerMap& layer_map, int64_t start, int64_t stop, double& max_time, double& min_time, - bool inverse = false) - { - ScopeGuard na(new aiNodeAnim()); - na->mNodeName.Set(name); - - ConvertTranslationKeys(na, curves, layer_map, start, stop, max_time, min_time); - - if (inverse) { - for (unsigned int i = 0; i < na->mNumPositionKeys; ++i) { - na->mPositionKeys[i].mValue *= -1.0f; - } - } - - // dummy scaling key - na->mScalingKeys = new aiVectorKey[1]; - na->mNumScalingKeys = 1; - - na->mScalingKeys[0].mTime = 0.; - na->mScalingKeys[0].mValue = aiVector3D(1.0f,1.0f,1.0f); - - // dummy rotation key - na->mRotationKeys = new aiQuatKey[1]; - na->mNumRotationKeys = 1; - - na->mRotationKeys[0].mTime = 0.; - na->mRotationKeys[0].mValue = aiQuaternion(); - - return na.dismiss(); - } - + bool inverse = false ); // ------------------------------------------------------------------------------------------------ // generate node anim, extracting only Rotation, Scaling and Translation from the given chain - aiNodeAnim* GenerateSimpleNodeAnim(const std::string& name, + aiNodeAnim* GenerateSimpleNodeAnim( const std::string& name, const Model& target, - NodeMap::const_iterator chain[TransformationComp_MAXIMUM], + NodeMap::const_iterator chain[ TransformationComp_MAXIMUM ], NodeMap::const_iterator iter_end, const LayerMap& layer_map, int64_t start, int64_t stop, double& max_time, double& min_time, - bool reverse_order = false) - - { - ScopeGuard na(new aiNodeAnim()); - na->mNodeName.Set(name); - - const PropertyTable& props = target.Props(); - - // need to convert from TRS order to SRT? - if(reverse_order) { - - aiVector3D def_scale = PropertyGet(props,"Lcl Scaling",aiVector3D(1.f,1.f,1.f)); - aiVector3D def_translate = PropertyGet(props,"Lcl Translation",aiVector3D(0.f,0.f,0.f)); - aiVector3D def_rot = PropertyGet(props,"Lcl Rotation",aiVector3D(0.f,0.f,0.f)); - - KeyFrameListList scaling; - KeyFrameListList translation; - KeyFrameListList rotation; - - if(chain[TransformationComp_Scaling] != iter_end) { - scaling = GetKeyframeList((*chain[TransformationComp_Scaling]).second, start, stop); - } - - if(chain[TransformationComp_Translation] != iter_end) { - translation = GetKeyframeList((*chain[TransformationComp_Translation]).second, start, stop); - } - - if(chain[TransformationComp_Rotation] != iter_end) { - rotation = GetKeyframeList((*chain[TransformationComp_Rotation]).second, start, stop); - } - - KeyFrameListList joined; - joined.insert(joined.end(), scaling.begin(), scaling.end()); - joined.insert(joined.end(), translation.begin(), translation.end()); - joined.insert(joined.end(), rotation.begin(), rotation.end()); - - const KeyTimeList& times = GetKeyTimeList(joined); - - aiQuatKey* out_quat = new aiQuatKey[times.size()]; - aiVectorKey* out_scale = new aiVectorKey[times.size()]; - aiVectorKey* out_translation = new aiVectorKey[times.size()]; - - if (times.size()) - { - ConvertTransformOrder_TRStoSRT(out_quat, out_scale, out_translation, - scaling, - translation, - rotation, - times, - max_time, - min_time, - target.RotationOrder(), - def_scale, - def_translate, - def_rot); - } - - // XXX remove duplicates / redundant keys which this operation did - // likely produce if not all three channels were equally dense. - - na->mNumScalingKeys = static_cast(times.size()); - na->mNumRotationKeys = na->mNumScalingKeys; - na->mNumPositionKeys = na->mNumScalingKeys; - - na->mScalingKeys = out_scale; - na->mRotationKeys = out_quat; - na->mPositionKeys = out_translation; - } - else { - - // if a particular transformation is not given, grab it from - // the corresponding node to meet the semantics of aiNodeAnim, - // which requires all of rotation, scaling and translation - // to be set. - if(chain[TransformationComp_Scaling] != iter_end) { - ConvertScaleKeys(na, (*chain[TransformationComp_Scaling]).second, - layer_map, - start, stop, - max_time, - min_time); - } - else { - na->mScalingKeys = new aiVectorKey[1]; - na->mNumScalingKeys = 1; - - na->mScalingKeys[0].mTime = 0.; - na->mScalingKeys[0].mValue = PropertyGet(props,"Lcl Scaling", - aiVector3D(1.f,1.f,1.f)); - } - - if(chain[TransformationComp_Rotation] != iter_end) { - ConvertRotationKeys(na, (*chain[TransformationComp_Rotation]).second, - layer_map, - start, stop, - max_time, - min_time, - target.RotationOrder()); - } - else { - na->mRotationKeys = new aiQuatKey[1]; - na->mNumRotationKeys = 1; - - na->mRotationKeys[0].mTime = 0.; - na->mRotationKeys[0].mValue = EulerToQuaternion( - PropertyGet(props,"Lcl Rotation",aiVector3D(0.f,0.f,0.f)), - target.RotationOrder()); - } - - if(chain[TransformationComp_Translation] != iter_end) { - ConvertTranslationKeys(na, (*chain[TransformationComp_Translation]).second, - layer_map, - start, stop, - max_time, - min_time); - } - else { - na->mPositionKeys = new aiVectorKey[1]; - na->mNumPositionKeys = 1; - - na->mPositionKeys[0].mTime = 0.; - na->mPositionKeys[0].mValue = PropertyGet(props,"Lcl Translation", - aiVector3D(0.f,0.f,0.f)); - } - - } - return na.dismiss(); - } - - + bool reverse_order = false ); // key (time), value, mapto (component index) typedef boost::tuple, boost::shared_ptr, unsigned int > KeyFrameList; @@ -2678,215 +345,26 @@ private: // ------------------------------------------------------------------------------------------------ - KeyFrameListList GetKeyframeList(const std::vector& nodes, int64_t start, int64_t stop) - { - KeyFrameListList inputs; - inputs.reserve(nodes.size()*3); - - //give some breathing room for rounding errors - int64_t adj_start = start - 10000; - int64_t adj_stop = stop + 10000; - - BOOST_FOREACH(const AnimationCurveNode* node, nodes) { - ai_assert(node); - - const AnimationCurveMap& curves = node->Curves(); - BOOST_FOREACH(const AnimationCurveMap::value_type& kv, curves) { - - unsigned int mapto; - if (kv.first == "d|X") { - mapto = 0; - } - else if (kv.first == "d|Y") { - mapto = 1; - } - else if (kv.first == "d|Z") { - mapto = 2; - } - else { - FBXImporter::LogWarn("ignoring scale animation curve, did not recognize target component"); - continue; - } - - const AnimationCurve* const curve = kv.second; - ai_assert(curve->GetKeys().size() == curve->GetValues().size() && curve->GetKeys().size()); - - //get values within the start/stop time window - boost::shared_ptr Keys(new KeyTimeList()); - boost::shared_ptr Values(new KeyValueList()); - const int count = curve->GetKeys().size(); - Keys->reserve(count); - Values->reserve(count); - for (int n = 0; n < count; n++) - { - int64_t k = curve->GetKeys().at(n); - if (k >= adj_start && k <= adj_stop) - { - Keys->push_back(k); - Values->push_back(curve->GetValues().at(n)); - } - } - - inputs.push_back(boost::make_tuple(Keys, Values, mapto)); - } - } - return inputs; // pray for NRVO :-) - } - + KeyFrameListList GetKeyframeList( const std::vector& nodes, int64_t start, int64_t stop ); // ------------------------------------------------------------------------------------------------ - KeyTimeList GetKeyTimeList(const KeyFrameListList& inputs) - { - ai_assert(inputs.size()); - - // reserve some space upfront - it is likely that the keyframe lists - // have matching time values, so max(of all keyframe lists) should - // be a good estimate. - KeyTimeList keys; - - size_t estimate = 0; - BOOST_FOREACH(const KeyFrameList& kfl, inputs) { - estimate = std::max(estimate, kfl.get<0>()->size()); - } - - keys.reserve(estimate); - - std::vector next_pos; - next_pos.resize(inputs.size(),0); - - const size_t count = inputs.size(); - while(true) { - - int64_t min_tick = std::numeric_limits::max(); - for (size_t i = 0; i < count; ++i) { - const KeyFrameList& kfl = inputs[i]; - - if (kfl.get<0>()->size() > next_pos[i] && kfl.get<0>()->at(next_pos[i]) < min_tick) { - min_tick = kfl.get<0>()->at(next_pos[i]); - } - } - - if (min_tick == std::numeric_limits::max()) { - break; - } - keys.push_back(min_tick); - - for (size_t i = 0; i < count; ++i) { - const KeyFrameList& kfl = inputs[i]; - - - while(kfl.get<0>()->size() > next_pos[i] && kfl.get<0>()->at(next_pos[i]) == min_tick) { - ++next_pos[i]; - } - } - } - - return keys; - } - + KeyTimeList GetKeyTimeList( const KeyFrameListList& inputs ); // ------------------------------------------------------------------------------------------------ - void InterpolateKeys(aiVectorKey* valOut,const KeyTimeList& keys, const KeyFrameListList& inputs, + void InterpolateKeys( aiVectorKey* valOut, const KeyTimeList& keys, const KeyFrameListList& inputs, const aiVector3D& def_value, double& max_time, - double& min_time) - - { - ai_assert(keys.size()); - ai_assert(valOut); - - std::vector next_pos; - const size_t count = inputs.size(); - - next_pos.resize(inputs.size(),0); - - BOOST_FOREACH(KeyTimeList::value_type time, keys) { - float result[3] = {def_value.x, def_value.y, def_value.z}; - - for (size_t i = 0; i < count; ++i) { - const KeyFrameList& kfl = inputs[i]; - - const size_t ksize = kfl.get<0>()->size(); - if (ksize > next_pos[i] && kfl.get<0>()->at(next_pos[i]) == time) { - ++next_pos[i]; - } - - const size_t id0 = next_pos[i]>0 ? next_pos[i]-1 : 0; - const size_t id1 = next_pos[i]==ksize ? ksize-1 : next_pos[i]; - - // use lerp for interpolation - const KeyValueList::value_type valueA = kfl.get<1>()->at(id0); - const KeyValueList::value_type valueB = kfl.get<1>()->at(id1); - - const KeyTimeList::value_type timeA = kfl.get<0>()->at(id0); - const KeyTimeList::value_type timeB = kfl.get<0>()->at(id1); - - // do the actual interpolation in double-precision arithmetics - // because it is a bit sensitive to rounding errors. - const double factor = timeB == timeA ? 0. : static_cast((time - timeA) / (timeB - timeA)); - const float interpValue = static_cast(valueA + (valueB - valueA) * factor); - - result[kfl.get<2>()] = interpValue; - } - - // magic value to convert fbx times to seconds - valOut->mTime = CONVERT_FBX_TIME(time) * anim_fps; - - min_time = std::min(min_time, valOut->mTime); - max_time = std::max(max_time, valOut->mTime); - - valOut->mValue.x = result[0]; - valOut->mValue.y = result[1]; - valOut->mValue.z = result[2]; - - ++valOut; - } - } - + double& min_time ); // ------------------------------------------------------------------------------------------------ - void InterpolateKeys(aiQuatKey* valOut,const KeyTimeList& keys, const KeyFrameListList& inputs, + void InterpolateKeys( aiQuatKey* valOut, const KeyTimeList& keys, const KeyFrameListList& inputs, const aiVector3D& def_value, double& maxTime, double& minTime, - Model::RotOrder order) - { - ai_assert(keys.size()); - ai_assert(valOut); - - boost::scoped_array temp(new aiVectorKey[keys.size()]); - InterpolateKeys(temp.get(), keys, inputs, def_value, maxTime, minTime); - - aiMatrix4x4 m; - - aiQuaternion lastq; - - for (size_t i = 0, c = keys.size(); i < c; ++i) { - - valOut[i].mTime = temp[i].mTime; - - - GetRotationMatrix(order, temp[i].mValue, m); - aiQuaternion quat = aiQuaternion(aiMatrix3x3(m)); - - // take shortest path by checking the inner product - // http://www.3dkingdoms.com/weekly/weekly.php?a=36 - if (quat.x * lastq.x + quat.y * lastq.y + quat.z * lastq.z + quat.w * lastq.w < 0) - { - quat.x = -quat.x; - quat.y = -quat.y; - quat.z = -quat.z; - quat.w = -quat.w; - } - lastq = quat; - - valOut[i].mValue = quat; - } - } - + Model::RotOrder order ); // ------------------------------------------------------------------------------------------------ - void ConvertTransformOrder_TRStoSRT(aiQuatKey* out_quat, aiVectorKey* out_scale, + void ConvertTransformOrder_TRStoSRT( aiQuatKey* out_quat, aiVectorKey* out_scale, aiVectorKey* out_translation, const KeyFrameListList& scaling, const KeyFrameListList& translation, @@ -2897,181 +375,36 @@ private: Model::RotOrder order, const aiVector3D& def_scale, const aiVector3D& def_translate, - const aiVector3D& def_rotation) - { - if (rotation.size()) { - InterpolateKeys(out_quat, times, rotation, def_rotation, maxTime, minTime, order); - } - else { - for (size_t i = 0; i < times.size(); ++i) { - out_quat[i].mTime = CONVERT_FBX_TIME(times[i]) * anim_fps; - out_quat[i].mValue = EulerToQuaternion(def_rotation, order); - } - } - - if (scaling.size()) { - InterpolateKeys(out_scale, times, scaling, def_scale, maxTime, minTime); - } - else { - for (size_t i = 0; i < times.size(); ++i) { - out_scale[i].mTime = CONVERT_FBX_TIME(times[i]) * anim_fps; - out_scale[i].mValue = def_scale; - } - } - - if (translation.size()) { - InterpolateKeys(out_translation, times, translation, def_translate, maxTime, minTime); - } - else { - for (size_t i = 0; i < times.size(); ++i) { - out_translation[i].mTime = CONVERT_FBX_TIME(times[i]) * anim_fps; - out_translation[i].mValue = def_translate; - } - } - - const size_t count = times.size(); - for (size_t i = 0; i < count; ++i) { - aiQuaternion& r = out_quat[i].mValue; - aiVector3D& s = out_scale[i].mValue; - aiVector3D& t = out_translation[i].mValue; - - aiMatrix4x4 mat, temp; - aiMatrix4x4::Translation(t, mat); - mat *= aiMatrix4x4( r.GetMatrix() ); - mat *= aiMatrix4x4::Scaling(s, temp); - - mat.Decompose(s, r, t); - } - } - + const aiVector3D& def_rotation ); // ------------------------------------------------------------------------------------------------ // euler xyz -> quat - aiQuaternion EulerToQuaternion(const aiVector3D& rot, Model::RotOrder order) - { - aiMatrix4x4 m; - GetRotationMatrix(order, rot, m); - - return aiQuaternion(aiMatrix3x3(m)); - } - + aiQuaternion EulerToQuaternion( const aiVector3D& rot, Model::RotOrder order ); // ------------------------------------------------------------------------------------------------ - void ConvertScaleKeys(aiNodeAnim* na, const std::vector& nodes, const LayerMap& /*layers*/, + void ConvertScaleKeys( aiNodeAnim* na, const std::vector& nodes, const LayerMap& /*layers*/, int64_t start, int64_t stop, double& maxTime, - double& minTime) - { - ai_assert(nodes.size()); - - // XXX for now, assume scale should be blended geometrically (i.e. two - // layers should be multiplied with each other). There is a FBX - // property in the layer to specify the behaviour, though. - - const KeyFrameListList& inputs = GetKeyframeList(nodes, start, stop); - const KeyTimeList& keys = GetKeyTimeList(inputs); - - na->mNumScalingKeys = static_cast(keys.size()); - na->mScalingKeys = new aiVectorKey[keys.size()]; - if (keys.size() > 0) - InterpolateKeys(na->mScalingKeys, keys, inputs, aiVector3D(1.0f, 1.0f, 1.0f), maxTime, minTime); - } - + double& minTime ); // ------------------------------------------------------------------------------------------------ - void ConvertTranslationKeys(aiNodeAnim* na, const std::vector& nodes, + void ConvertTranslationKeys( aiNodeAnim* na, const std::vector& nodes, const LayerMap& /*layers*/, int64_t start, int64_t stop, double& maxTime, - double& minTime) - { - ai_assert(nodes.size()); - - // XXX see notes in ConvertScaleKeys() - const KeyFrameListList& inputs = GetKeyframeList(nodes, start, stop); - const KeyTimeList& keys = GetKeyTimeList(inputs); - - na->mNumPositionKeys = static_cast(keys.size()); - na->mPositionKeys = new aiVectorKey[keys.size()]; - if (keys.size() > 0) - InterpolateKeys(na->mPositionKeys, keys, inputs, aiVector3D(0.0f, 0.0f, 0.0f), maxTime, minTime); - } - + double& minTime ); // ------------------------------------------------------------------------------------------------ - void ConvertRotationKeys(aiNodeAnim* na, const std::vector& nodes, + void ConvertRotationKeys( aiNodeAnim* na, const std::vector& nodes, const LayerMap& /*layers*/, int64_t start, int64_t stop, double& maxTime, double& minTime, - Model::RotOrder order) - { - ai_assert(nodes.size()); - - // XXX see notes in ConvertScaleKeys() - const std::vector< KeyFrameList >& inputs = GetKeyframeList(nodes, start, stop); - const KeyTimeList& keys = GetKeyTimeList(inputs); - - na->mNumRotationKeys = static_cast(keys.size()); - na->mRotationKeys = new aiQuatKey[keys.size()]; - if (keys.size() > 0) - InterpolateKeys(na->mRotationKeys, keys, inputs, aiVector3D(0.0f, 0.0f, 0.0f), maxTime, minTime, order); - } - + Model::RotOrder order ); // ------------------------------------------------------------------------------------------------ // copy generated meshes, animations, lights, cameras and textures to the output scene - void TransferDataToScene() - { - ai_assert(!out->mMeshes && !out->mNumMeshes); - - // note: the trailing () ensures initialization with NULL - not - // many C++ users seem to know this, so pointing it out to avoid - // confusion why this code works. - - if(meshes.size()) { - out->mMeshes = new aiMesh*[meshes.size()](); - out->mNumMeshes = static_cast(meshes.size()); - - std::swap_ranges(meshes.begin(),meshes.end(),out->mMeshes); - } - - if(materials.size()) { - out->mMaterials = new aiMaterial*[materials.size()](); - out->mNumMaterials = static_cast(materials.size()); - - std::swap_ranges(materials.begin(),materials.end(),out->mMaterials); - } - - if(animations.size()) { - out->mAnimations = new aiAnimation*[animations.size()](); - out->mNumAnimations = static_cast(animations.size()); - - std::swap_ranges(animations.begin(),animations.end(),out->mAnimations); - } - - if(lights.size()) { - out->mLights = new aiLight*[lights.size()](); - out->mNumLights = static_cast(lights.size()); - - std::swap_ranges(lights.begin(),lights.end(),out->mLights); - } - - if(cameras.size()) { - out->mCameras = new aiCamera*[cameras.size()](); - out->mNumCameras = static_cast(cameras.size()); - - std::swap_ranges(cameras.begin(),cameras.end(),out->mCameras); - } - - if(textures.size()) { - out->mTextures = new aiTexture*[textures.size()](); - out->mNumTextures = static_cast(textures.size()); - - std::swap_ranges(textures.begin(),textures.end(),out->mTextures); - } - } - + void TransferDataToScene(); private: @@ -3111,6 +444,2861 @@ private: const FBX::Document& doc; }; +Converter::Converter( aiScene* out, const Document& doc ) + : defaultMaterialIndex() + , 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(); + ConvertRootNode(); + + if ( doc.Settings().readAllMaterials ) { + // unfortunately this means we have to evaluate all objects + BOOST_FOREACH( 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 ); + } + } + } + } + + TransferDataToScene(); + + // 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; + } +} + + +Converter::~Converter() +{ + 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 Converter::ConvertRootNode() +{ + out->mRootNode = new aiNode(); + out->mRootNode->mName.Set( "RootNode" ); + + // root has ID 0 + ConvertNodes( 0L, *out->mRootNode ); +} + + +void Converter::ConvertNodes( uint64_t id, aiNode& parent, const aiMatrix4x4& parent_transform ) +{ + const std::vector& conns = doc.GetConnectionsByDestinationSequenced( id, "Model" ); + + std::vector nodes; + nodes.reserve( conns.size() ); + + std::vector nodes_chain; + + try { + BOOST_FOREACH( const Connection* con, conns ) { + + // ignore object-property links + if ( con->PropertyName().length() ) { + continue; + } + + const Object* const object = con->SourceObject(); + if ( !object ) { + FBXImporter::LogWarn( "failed to convert source object for Model link" ); + continue; + } + + const Model* const model = dynamic_cast( object ); + + if ( model ) { + nodes_chain.clear(); + + aiMatrix4x4 new_abs_transform = parent_transform; + + // 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. + GenerateTransformationNodeChain( *model, nodes_chain ); + + ai_assert( nodes_chain.size() ); + + const std::string& original_name = FixNodeName( model->Name() ); + + // check if any of the nodes in the chain has the name the fbx node + // is supposed to have. If there is none, add another node to + // preserve the name - people might have scripts etc. that rely + // on specific node names. + aiNode* name_carrier = NULL; + BOOST_FOREACH( aiNode* prenode, nodes_chain ) { + if ( !strcmp( prenode->mName.C_Str(), original_name.c_str() ) ) { + name_carrier = prenode; + break; + } + } + + if ( !name_carrier ) { + nodes_chain.push_back( new aiNode( original_name ) ); + name_carrier = nodes_chain.back(); + } + + //setup metadata on newest node + SetupNodeMetadata( *model, *nodes_chain.back() ); + + // link all nodes in a row + aiNode* last_parent = &parent; + BOOST_FOREACH( aiNode* prenode, nodes_chain ) { + ai_assert( prenode ); + + if ( last_parent != &parent ) { + last_parent->mNumChildren = 1; + last_parent->mChildren = new aiNode*[ 1 ]; + last_parent->mChildren[ 0 ] = prenode; + } + + prenode->mParent = last_parent; + last_parent = prenode; + + new_abs_transform *= prenode->mTransformation; + } + + // attach geometry + ConvertModel( *model, *nodes_chain.back(), new_abs_transform ); + + // attach sub-nodes + ConvertNodes( model->ID(), *nodes_chain.back(), new_abs_transform ); + + if ( doc.Settings().readLights ) { + ConvertLights( *model ); + } + + if ( doc.Settings().readCameras ) { + ConvertCameras( *model ); + } + + 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 ); + } + } + 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 ); + } +} + + +void Converter::ConvertLights( const Model& model ) +{ + const std::vector& node_attrs = model.GetAttributes(); + BOOST_FOREACH( const NodeAttribute* attr, node_attrs ) { + const Light* const light = dynamic_cast( attr ); + if ( light ) { + ConvertLight( model, *light ); + } + } +} + +void Converter::ConvertCameras( const Model& model ) +{ + const std::vector& node_attrs = model.GetAttributes(); + BOOST_FOREACH( const NodeAttribute* attr, node_attrs ) { + const Camera* const cam = dynamic_cast( attr ); + if ( cam ) { + ConvertCamera( model, *cam ); + } + } +} + + +void Converter::ConvertLight( const Model& model, const Light& light ) +{ + lights.push_back( new aiLight() ); + aiLight* const out_light = lights.back(); + + out_light->mName.Set( FixNodeName( model.Name() ) ); + + const float intensity = light.Intensity(); + 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; + + 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 ); + } + + // XXX: how to best convert the near and far decay ranges? + switch ( light.DecayType() ) + { + case Light::Decay_None: + out_light->mAttenuationConstant = 1.0f; + break; + case Light::Decay_Linear: + out_light->mAttenuationLinear = 1.0f; + break; + case Light::Decay_Quadratic: + out_light->mAttenuationQuadratic = 1.0f; + break; + case Light::Decay_Cubic: + FBXImporter::LogWarn( "cannot represent cubic attenuation, set to Quadratic" ); + out_light->mAttenuationQuadratic = 1.0f; + break; + default: + ai_assert( false ); + } +} + +void Converter::ConvertCamera( const Model& model, const Camera& cam ) +{ + cameras.push_back( new aiCamera() ); + aiCamera* const out_camera = cameras.back(); + + out_camera->mName.Set( FixNodeName( model.Name() ) ); + + out_camera->mAspect = cam.AspectWidth() / cam.AspectHeight(); + out_camera->mPosition = cam.Position(); + out_camera->mUp = cam.UpVector(); + out_camera->mLookAt = cam.InterestPosition() - out_camera->mPosition; + out_camera->mHorizontalFOV = AI_DEG_TO_RAD( cam.FieldOfView() ); +} + + +const char* Converter::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_MAXIMUM: // this is to silence compiler warnings + default: + break; + } + + ai_assert( false ); + return NULL; +} + + +const char* Converter::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_MAXIMUM: // this is to silence compiler warnings + break; + } + + ai_assert( false ); + return NULL; +} + +aiVector3D Converter::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 Converter::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 = 1e-6f; + + 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 ); + } + + ai_assert( ( order[ 0 ] >= 0 ) && ( order[ 0 ] <= 2 ) ); + ai_assert( ( order[ 1 ] >= 0 ) && ( order[ 1 ] <= 2 ) ); + ai_assert( ( order[ 2 ] >= 0 ) && ( 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 Converter::NeedsComplexTransformationChain( const Model& model ) +{ + const PropertyTable& props = model.Props(); + bool ok; + + const float zero_epsilon = 1e-6f; + 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 ) { + continue; + } + + const aiVector3D& v = PropertyGet( props, NameTransformationCompProperty( comp ), ok ); + if ( ok && v.SquareLength() > zero_epsilon ) { + return true; + } + } + + return false; +} + + +std::string Converter::NameTransformationChainNode( const std::string& name, TransformationComp comp ) +{ + return name + std::string( MAGIC_NODE_TAG ) + "_" + NameTransformationComp( comp ); +} + +void Converter::GenerateTransformationNodeChain( const Model& model, + std::vector& output_nodes ) +{ + const PropertyTable& props = model.Props(); + const Model::RotOrder rot = model.RotationOrder(); + + bool ok; + + aiMatrix4x4 chain[ TransformationComp_MAXIMUM ]; + std::fill_n( chain, static_cast( TransformationComp_MAXIMUM ), aiMatrix4x4() ); + + // generate transformation matrices for all the different transformation components + const float zero_epsilon = 1e-6f; + bool is_complex = false; + + const aiVector3D& PreRotation = PropertyGet( props, "PreRotation", ok ); + if ( ok && PreRotation.SquareLength() > zero_epsilon ) { + is_complex = true; + + GetRotationMatrix( rot, PreRotation, chain[ TransformationComp_PreRotation ] ); + } + + const aiVector3D& PostRotation = PropertyGet( props, "PostRotation", ok ); + if ( ok && PostRotation.SquareLength() > zero_epsilon ) { + is_complex = true; + + GetRotationMatrix( rot, PostRotation, chain[ TransformationComp_PostRotation ] ); + } + + const aiVector3D& RotationPivot = PropertyGet( props, "RotationPivot", ok ); + if ( ok && RotationPivot.SquareLength() > zero_epsilon ) { + is_complex = true; + + 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 ) { + is_complex = true; + + aiMatrix4x4::Translation( RotationOffset, chain[ TransformationComp_RotationOffset ] ); + } + + const aiVector3D& ScalingOffset = PropertyGet( props, "ScalingOffset", ok ); + if ( ok && ScalingOffset.SquareLength() > zero_epsilon ) { + is_complex = true; + + aiMatrix4x4::Translation( ScalingOffset, chain[ TransformationComp_ScalingOffset ] ); + } + + const aiVector3D& ScalingPivot = PropertyGet( props, "ScalingPivot", ok ); + if ( ok && ScalingPivot.SquareLength() > zero_epsilon ) { + is_complex = true; + + 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 ) { + aiMatrix4x4::Translation( Translation, chain[ TransformationComp_Translation ] ); + } + + const aiVector3D& Scaling = PropertyGet( props, "Lcl Scaling", ok ); + if ( ok && std::fabs( Scaling.SquareLength() - 1.0f ) > zero_epsilon ) { + aiMatrix4x4::Scaling( Scaling, chain[ TransformationComp_Scaling ] ); + } + + const aiVector3D& Rotation = PropertyGet( props, "Lcl Rotation", ok ); + if ( ok && Rotation.SquareLength() > zero_epsilon ) { + GetRotationMatrix( rot, Rotation, chain[ TransformationComp_Rotation ] ); + } + + const aiVector3D& GeometricScaling = PropertyGet( props, "GeometricScaling", ok ); + if ( ok && std::fabs( GeometricScaling.SquareLength() - 1.0f ) > zero_epsilon ) { + aiMatrix4x4::Scaling( GeometricScaling, chain[ TransformationComp_GeometricScaling ] ); + } + + const aiVector3D& GeometricRotation = PropertyGet( props, "GeometricRotation", ok ); + if ( ok && GeometricRotation.SquareLength() > zero_epsilon ) { + GetRotationMatrix( rot, GeometricRotation, chain[ TransformationComp_GeometricRotation ] ); + } + + const aiVector3D& GeometricTranslation = PropertyGet( props, "GeometricTranslation", ok ); + if ( ok && GeometricTranslation.SquareLength() > zero_epsilon ) { + aiMatrix4x4::Translation( GeometricTranslation, chain[ TransformationComp_GeometricTranslation ] ); + } + + // 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 ) == is_complex ); + + const std::string& name = FixNodeName( model.Name() ); + + // 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 ( is_complex && 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 ( chain[ i ].IsIdentity() && ( anim_chain_bitmask & bit ) == 0 ) { + continue; + } + + aiNode* nd = new aiNode(); + output_nodes.push_back( nd ); + + nd->mName.Set( NameTransformationChainNode( name, comp ) ); + nd->mTransformation = chain[ i ]; + } + + ai_assert( output_nodes.size() ); + return; + } + + // else, we can just multiply the matrices together + aiNode* nd = new aiNode(); + output_nodes.push_back( nd ); + + nd->mName.Set( name ); + + for ( size_t i = 0; i < TransformationComp_MAXIMUM; ++i ) { + nd->mTransformation = nd->mTransformation * chain[ i ]; + } +} + + +void Converter::SetupNodeMetadata( const Model& model, aiNode& nd ) +{ + const PropertyTable& props = model.Props(); + DirectPropertyMap unparsedProperties = props.GetUnparsedProperties(); + + // create metadata on node + std::size_t numStaticMetaData = 2; + aiMetadata* data = new aiMetadata(); + data->mNumProperties = unparsedProperties.size() + numStaticMetaData; + data->mKeys = new aiString[ data->mNumProperties ](); + data->mValues = new aiMetadataEntry[ data->mNumProperties ](); + 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 + BOOST_FOREACH( 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 + assert( false ); + } +} + +void Converter::ConvertModel( const Model& model, aiNode& nd, const aiMatrix4x4& node_global_transform ) +{ + const std::vector& geos = model.GetGeometry(); + + std::vector meshes; + meshes.reserve( geos.size() ); + + BOOST_FOREACH( const Geometry* geo, geos ) { + + const MeshGeometry* const mesh = dynamic_cast< const MeshGeometry* >( geo ); + if ( mesh ) { + const std::vector& indices = ConvertMesh( *mesh, model, node_global_transform ); + std::copy( indices.begin(), indices.end(), std::back_inserter( meshes ) ); + } + else { + FBXImporter::LogWarn( "ignoring unrecognized geometry: " + geo->Name() ); + } + } + + if ( meshes.size() ) { + nd.mMeshes = new unsigned int[ meshes.size() ](); + nd.mNumMeshes = static_cast< unsigned int >( meshes.size() ); + + std::swap_ranges( meshes.begin(), meshes.end(), nd.mMeshes ); + } +} + + +std::vector Converter::ConvertMesh( const MeshGeometry& mesh, const Model& model, + const aiMatrix4x4& node_global_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 ]; + BOOST_FOREACH( MatIndexArray::value_type index, mindices ) { + if ( index != base ) { + return ConvertMeshMultiMaterial( mesh, model, node_global_transform ); + } + } + } + + // faster code-path, just copy the data + temp.push_back( ConvertMeshSingleMaterial( mesh, model, node_global_transform ) ); + return temp; +} + + +aiMesh* Converter::SetupEmptyMesh( const MeshGeometry& mesh ) +{ + 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 ); + } + + return out_mesh; +} + + +unsigned int Converter::ConvertMeshSingleMaterial( const MeshGeometry& mesh, const Model& model, + const aiMatrix4x4& node_global_transform ) +{ + const MatIndexArray& mindices = mesh.GetMaterialIndices(); + aiMesh* const out_mesh = SetupEmptyMesh( mesh ); + + 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; + BOOST_FOREACH( 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 = NULL; + } + } + + 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() ]; + BOOST_FOREACH( 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() != NULL ) { + ConvertWeights( out_mesh, model, mesh, node_global_transform, NO_MATERIAL_SEPARATION ); + } + + return static_cast( meshes.size() - 1 ); +} + +std::vector Converter::ConvertMeshMultiMaterial( const MeshGeometry& mesh, const Model& model, + const aiMatrix4x4& node_global_transform ) +{ + const MatIndexArray& mindices = mesh.GetMaterialIndices(); + ai_assert( mindices.size() ); + + std::set had; + std::vector indices; + + BOOST_FOREACH( MatIndexArray::value_type index, mindices ) { + if ( had.find( index ) == had.end() ) { + + indices.push_back( ConvertMeshMultiMaterial( mesh, model, index, node_global_transform ) ); + had.insert( index ); + } + } + + return indices; +} + +unsigned int Converter::ConvertMeshMultiMaterial( const MeshGeometry& mesh, const Model& model, + MatIndexArray::value_type index, + const aiMatrix4x4& node_global_transform ) +{ + aiMesh* const out_mesh = SetupEmptyMesh( mesh ); + + 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() != NULL; + + 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 + std::vector reverseMapping; + + if ( process_weights ) { + 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(); + + if ( tangents.size() ) { + std::vector tempBinormals; + 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 = NULL; + } + } + + 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; + } + + 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 i = 0; i < num_uvs; ++i ) { + const std::vector& uvs = mesh.GetTextureCoords( i ); + out_mesh->mTextureCoords[ i ][ cursor ] = aiVector3D( uvs[ in_cursor ].x, uvs[ in_cursor ].y, 0.0f ); + } + + for ( unsigned int i = 0; i < num_vcs; ++i ) { + const std::vector& cols = mesh.GetVertexColors( i ); + out_mesh->mColors[ i ][ cursor ] = cols[ in_cursor ]; + } + } + } + + ConvertMaterialForMesh( out_mesh, model, mesh, index ); + + if ( process_weights ) { + ConvertWeights( out_mesh, model, mesh, node_global_transform, index, &reverseMapping ); + } + + return static_cast( meshes.size() - 1 ); +} + + +void Converter::ConvertWeights( aiMesh* out, const Model& model, const MeshGeometry& geo, + const aiMatrix4x4& node_global_transform , + 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; + bones.reserve( sk.Clusters().size() ); + + const bool no_mat_check = materialIndex == NO_MATERIAL_SEPARATION; + ai_assert( no_mat_check || outputVertStartIndices ); + + try { + + BOOST_FOREACH( const Cluster* cluster, sk.Clusters() ) { + ai_assert( cluster ); + + const WeightIndexArray& indices = cluster->GetIndices(); + + if ( indices.empty() ) { + continue; + } + + const MatIndexArray& mats = geo.GetMaterialIndices(); + + bool ok = false; + + 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. + BOOST_FOREACH( WeightIndexArray::value_type index, indices ) { + + unsigned int count = 0; + const unsigned int* const out_idx = geo.ToOutputVertexIndex( index, count ); + // ToOutputVertexIndex only returns NULL if index is out of bounds + // which should never happen + ai_assert( out_idx != NULL ); + + 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(); + ok = true; + } + } + } + + // 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. + if ( ok ) { + ConvertCluster( bones, model, *cluster, out_indices, index_out_indices, + count_out_indices, node_global_transform ); + } + } + } + catch ( std::exception& ) { + std::for_each( bones.begin(), bones.end(), Util::delete_fun() ); + throw; + } + + if ( bones.empty() ) { + return; + } + + out->mBones = new aiBone*[ bones.size() ](); + out->mNumBones = static_cast( bones.size() ); + + std::swap_ranges( bones.begin(), bones.end(), out->mBones ); +} + +void Converter::ConvertCluster( std::vector& bones, const Model& /*model*/, const Cluster& cl, + std::vector& out_indices, + std::vector& index_out_indices, + std::vector& count_out_indices, + const aiMatrix4x4& node_global_transform ) +{ + + aiBone* const bone = new aiBone(); + bones.push_back( bone ); + + bone->mName = FixNodeName( cl.TargetNode()->Name() ); + + bone->mOffsetMatrix = cl.TransformLink(); + bone->mOffsetMatrix.Inverse(); + + bone->mOffsetMatrix = bone->mOffsetMatrix * node_global_transform; + + bone->mNumWeights = static_cast( out_indices.size() ); + aiVertexWeight* 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 ) { + aiVertexWeight& out_weight = *cursor++; + + out_weight.mVertexId = static_cast( out_indices[ index_index + j ] ); + out_weight.mWeight = weights[ i ]; + } + } +} + + +void Converter::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 Converter::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< unsigned int >( materials.size() ); + return defaultMaterialIndex - 1; +} + + +unsigned int Converter::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; + + // stip 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 ); + } + + // shading stuff and colors + SetShadingPropertiesCommon( out_mat, props ); + + // texture assignments + SetTextureProperties( out_mat, material.Textures(), mesh ); + SetTextureProperties( out_mat, material.LayeredTextures(), mesh ); + + return static_cast( materials.size() - 1 ); +} + +unsigned int Converter::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.FileName().empty() ? video.RelativeFilename() : video.FileName(); + std::string ext = BaseImporter::GetExtension( filename ); + + if ( ext == "jpeg" ) { + ext = "jpg"; + } + + if ( ext.size() <= 3 ) { + memcpy( out_tex->achFormatHint, ext.c_str(), ext.size() ); + } + + return static_cast( textures.size() - 1 ); +} + +void Converter::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; + path.Set( tex->RelativeFilename() ); + + const Video* media = tex->Media(); + if ( media != 0 && media->ContentLength() > 0 ) { + unsigned int index; + + VideoMap::const_iterator it = textures_converted.find( media ); + if ( it != textures_converted.end() ) { + index = ( *it ).second; + } + else { + index = ConvertVideo( *media ); + textures_converted[ media ] = index; + } + + // setup texture reference string (copied from ColladaLoader::FindFilenameForEffectTexture) + path.data[ 0 ] = '*'; + path.length = 1 + ASSIMP_itoa10( path.data + 1, MAXLEN - 1, index ); + } + + 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 ) + { + BOOST_FOREACH( const MeshMap::value_type& v, meshes_converted ) { + const MeshGeometry* const mesh = dynamic_cast ( v.first ); + if ( !mesh ) { + continue; + } + + const MatIndexArray& mats = mesh->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 ( 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" ); + 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 Converter::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; + } + + const Texture* const tex = ( *it ).second->getTexture(); + + aiString path; + path.Set( tex->RelativeFilename() ); + + 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 ) + { + BOOST_FOREACH( const MeshMap::value_type& v, meshes_converted ) { + const MeshGeometry* const mesh = dynamic_cast ( v.first ); + if ( !mesh ) { + continue; + } + + const MatIndexArray& mats = mesh->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 ( 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" ); + 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 Converter::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, "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 ); +} + +void Converter::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, "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 ); +} + +aiColor3D Converter::GetColorPropertyFromMaterial( const PropertyTable& props, const std::string& baseName, + bool& result ) +{ + result = true; + + bool ok; + const aiVector3D& Diffuse = PropertyGet( props, baseName, ok ); + if ( ok ) { + return aiColor3D( Diffuse.x, Diffuse.y, Diffuse.z ); + } + else { + aiVector3D DiffuseColor = PropertyGet( props, baseName + "Color", ok ); + if ( ok ) { + float DiffuseFactor = PropertyGet( props, baseName + "Factor", ok ); + if ( ok ) { + DiffuseColor *= DiffuseFactor; + } + + return aiColor3D( DiffuseColor.x, DiffuseColor.y, DiffuseColor.z ); + } + } + result = false; + return aiColor3D( 0.0f, 0.0f, 0.0f ); +} + + +void Converter::SetShadingPropertiesCommon( aiMaterial* out_mat, const PropertyTable& props ) +{ + // set shading properties. There are various, redundant ways in which FBX materials + // specify their shading settings (depending on shading models, prop + // template etc.). No idea which one is right in a particular context. + // Just try to make sense of it - there's no spec to verify this against, + // so why should we. + 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 ); + } + + const aiColor3D& Specular = GetColorPropertyFromMaterial( props, "Specular", ok ); + if ( ok ) { + out_mat->AddProperty( &Specular, 1, AI_MATKEY_COLOR_SPECULAR ); + } + + const float Opacity = PropertyGet( props, "Opacity", ok ); + if ( ok ) { + out_mat->AddProperty( &Opacity, 1, AI_MATKEY_OPACITY ); + } + + const float Reflectivity = PropertyGet( props, "Reflectivity", ok ); + if ( ok ) { + out_mat->AddProperty( &Reflectivity, 1, AI_MATKEY_REFLECTIVITY ); + } + + const float Shininess = PropertyGet( props, "Shininess", ok ); + if ( ok ) { + out_mat->AddProperty( &Shininess, 1, AI_MATKEY_SHININESS_STRENGTH ); + } + + const float ShininessExponent = PropertyGet( props, "ShininessExponent", ok ); + if ( ok ) { + out_mat->AddProperty( &ShininessExponent, 1, AI_MATKEY_SHININESS ); + } +} + + +double Converter::FrameRateToDouble( FileGlobalSettings::FrameRate fp, double customFPSVal ) +{ + switch ( fp ) { + case FileGlobalSettings::FrameRate_DEFAULT: + return 1.0; + + case FileGlobalSettings::FrameRate_120: + return 120.0; + + case FileGlobalSettings::FrameRate_100: + return 100.0; + + case FileGlobalSettings::FrameRate_60: + return 60.0; + + case FileGlobalSettings::FrameRate_50: + return 50.0; + + case FileGlobalSettings::FrameRate_48: + return 48.0; + + case FileGlobalSettings::FrameRate_30: + case FileGlobalSettings::FrameRate_30_DROP: + return 30.0; + + case FileGlobalSettings::FrameRate_NTSC_DROP_FRAME: + case FileGlobalSettings::FrameRate_NTSC_FULL_FRAME: + return 29.9700262; + + case FileGlobalSettings::FrameRate_PAL: + return 25.0; + + case FileGlobalSettings::FrameRate_CINEMA: + return 24.0; + + case FileGlobalSettings::FrameRate_1000: + return 1000.0; + + case FileGlobalSettings::FrameRate_CINEMA_ND: + return 23.976; + + case FileGlobalSettings::FrameRate_CUSTOM: + return customFPSVal; + + case FileGlobalSettings::FrameRate_MAX: // this is to silence compiler warnings + break; + } + + ai_assert( false ); + return -1.0f; +} + + +void Converter::ConvertAnimations() +{ + // first of all determine framerate + const FileGlobalSettings::FrameRate fps = doc.GlobalSettings().TimeMode(); + const float custom = doc.GlobalSettings().CustomFrameRate(); + anim_fps = FrameRateToDouble( fps, custom ); + + const std::vector& animations = doc.AnimationStacks(); + BOOST_FOREACH( const AnimationStack* stack, animations ) { + ConvertAnimationStack( *stack ); + } +} + + +void Converter::RenameNode( const std::string& fixed_name, const std::string& new_name ) +{ + ai_assert( node_names.find( fixed_name ) != node_names.end() ); + ai_assert( node_names.find( new_name ) == node_names.end() ); + + renamed_nodes[ fixed_name ] = new_name; + + const aiString fn( fixed_name ); + + BOOST_FOREACH( aiCamera* cam, cameras ) { + if ( cam->mName == fn ) { + cam->mName.Set( new_name ); + break; + } + } + + BOOST_FOREACH( aiLight* light, lights ) { + if ( light->mName == fn ) { + light->mName.Set( new_name ); + break; + } + } + + BOOST_FOREACH( aiAnimation* anim, animations ) { + for ( unsigned int i = 0; i < anim->mNumChannels; ++i ) { + aiNodeAnim* const na = anim->mChannels[ i ]; + if ( na->mNodeName == fn ) { + na->mNodeName.Set( new_name ); + break; + } + } + } +} + + +std::string Converter::FixNodeName( const std::string& name ) +{ + // strip Model:: prefix, avoiding ambiguities (i.e. don't strip if + // this causes ambiguities, well possible between empty identifiers, + // such as "Model::" and ""). Make sure the behaviour is consistent + // across multiple calls to FixNodeName(). + if ( name.substr( 0, 7 ) == "Model::" ) { + std::string temp = name.substr( 7 ); + + const NodeNameMap::const_iterator it = node_names.find( temp ); + if ( it != node_names.end() ) { + if ( !( *it ).second ) { + return FixNodeName( name + "_" ); + } + } + node_names[ temp ] = true; + + const NameNameMap::const_iterator rit = renamed_nodes.find( temp ); + return rit == renamed_nodes.end() ? temp : ( *rit ).second; + } + + const NodeNameMap::const_iterator it = node_names.find( name ); + if ( it != node_names.end() ) { + if ( ( *it ).second ) { + return FixNodeName( name + "_" ); + } + } + node_names[ name ] = false; + + const NameNameMap::const_iterator rit = renamed_nodes.find( name ); + return rit == renamed_nodes.end() ? name : ( *rit ).second; +} + +void Converter::ConvertAnimationStack( const AnimationStack& st ) +{ + const AnimationLayerList& layers = st.Layers(); + if ( layers.empty() ) { + return; + } + + aiAnimation* const anim = new aiAnimation(); + animations.push_back( anim ); + + // strip AnimationStack:: prefix + std::string name = st.Name(); + if ( name.substr( 0, 16 ) == "AnimationStack::" ) { + name = name.substr( 16 ); + } + else if ( name.substr( 0, 11 ) == "AnimStack::" ) { + name = name.substr( 11 ); + } + + anim->mName.Set( name ); + + // need to find all nodes for which we need to generate node animations - + // it may happen that we need to merge multiple layers, though. + NodeMap node_map; + + // reverse mapping from curves to layers, much faster than querying + // the FBX DOM for it. + LayerMap layer_map; + + const char* prop_whitelist[] = { + "Lcl Scaling", + "Lcl Rotation", + "Lcl Translation" + }; + + BOOST_FOREACH( const AnimationLayer* layer, layers ) { + ai_assert( layer ); + + const AnimationCurveNodeList& nodes = layer->Nodes( prop_whitelist, 3 ); + BOOST_FOREACH( const AnimationCurveNode* node, nodes ) { + ai_assert( node ); + + const Model* const model = dynamic_cast( node->Target() ); + // this can happen - it could also be a NodeAttribute (i.e. for camera animations) + if ( !model ) { + continue; + } + + const std::string& name = FixNodeName( model->Name() ); + node_map[ name ].push_back( node ); + + layer_map[ node ] = layer; + } + } + + // generate node animations + std::vector node_anims; + + double min_time = 1e10; + double max_time = -1e10; + + int64_t start_time = st.LocalStart(); + int64_t stop_time = st.LocalStop(); + double start_timeF = CONVERT_FBX_TIME( start_time ); + double stop_timeF = CONVERT_FBX_TIME( stop_time ); + + try { + BOOST_FOREACH( const NodeMap::value_type& kv, node_map ) { + GenerateNodeAnimations( node_anims, + kv.first, + kv.second, + layer_map, + start_time, stop_time, + max_time, + min_time ); + } + } + catch ( std::exception& ) { + std::for_each( node_anims.begin(), node_anims.end(), Util::delete_fun() ); + throw; + } + + if ( node_anims.size() ) { + anim->mChannels = new aiNodeAnim*[ node_anims.size() ](); + anim->mNumChannels = static_cast( node_anims.size() ); + + std::swap_ranges( node_anims.begin(), node_anims.end(), anim->mChannels ); + } + else { + // empty animations would fail validation, so drop them + delete anim; + animations.pop_back(); + FBXImporter::LogInfo( "ignoring empty AnimationStack (using IK?): " + name ); + return; + } + + //adjust relative timing for animation + { + double start_fps = start_timeF * anim_fps; + + for ( unsigned int c = 0; c < anim->mNumChannels; c++ ) + { + aiNodeAnim* channel = anim->mChannels[ c ]; + for ( uint32_t i = 0; i < channel->mNumPositionKeys; i++ ) + channel->mPositionKeys[ i ].mTime -= start_fps; + for ( uint32_t i = 0; i < channel->mNumRotationKeys; i++ ) + channel->mRotationKeys[ i ].mTime -= start_fps; + for ( uint32_t i = 0; i < channel->mNumScalingKeys; i++ ) + channel->mScalingKeys[ i ].mTime -= start_fps; + } + + max_time -= min_time; + } + + // for some mysterious reason, mDuration is simply the maximum key -- the + // validator always assumes animations to start at zero. + anim->mDuration = ( stop_timeF - start_timeF ) * anim_fps; + anim->mTicksPerSecond = anim_fps; +} + +// ------------------------------------------------------------------------------------------------ +// sanity check whether the input is ok +static void validateAnimCurveNodes( const std::vector& curves, + bool strictMode ) { + const Object* target( NULL ); + BOOST_FOREACH( const AnimationCurveNode* node, curves ) { + if ( !target ) { + target = node->Target(); + } + if ( node->Target() != target ) { + FBXImporter::LogWarn( "Node target is nullptr type." ); + } + if ( strictMode ) { + ai_assert( node->Target() == target ); + } + } +} + +// ------------------------------------------------------------------------------------------------ +void Converter::GenerateNodeAnimations( std::vector& node_anims, + const std::string& fixed_name, + const std::vector& curves, + const LayerMap& layer_map, + int64_t start, int64_t stop, + double& max_time, + double& min_time ) +{ + + NodeMap node_property_map; + ai_assert( curves.size() ); + +#ifdef ASSIMP_BUILD_DEBUG + validateAnimCurveNodes( curves, doc.Settings().strictMode ); +#endif + const AnimationCurveNode* curve_node = NULL; + BOOST_FOREACH( const AnimationCurveNode* node, curves ) { + ai_assert( node ); + + if ( node->TargetProperty().empty() ) { + FBXImporter::LogWarn( "target property for animation curve not set: " + node->Name() ); + continue; + } + + curve_node = node; + if ( node->Curves().empty() ) { + FBXImporter::LogWarn( "no animation curves assigned to AnimationCurveNode: " + node->Name() ); + continue; + } + + node_property_map[ node->TargetProperty() ].push_back( node ); + } + + ai_assert( curve_node ); + ai_assert( curve_node->TargetAsModel() ); + + const Model& target = *curve_node->TargetAsModel(); + + // check for all possible transformation components + NodeMap::const_iterator chain[ TransformationComp_MAXIMUM ]; + + bool has_any = false; + bool has_complex = false; + + for ( size_t i = 0; i < TransformationComp_MAXIMUM; ++i ) { + const TransformationComp comp = static_cast( i ); + + // inverse pivots don't exist in the input, we just generate them + if ( comp == TransformationComp_RotationPivotInverse || comp == TransformationComp_ScalingPivotInverse ) { + chain[ i ] = node_property_map.end(); + continue; + } + + chain[ i ] = node_property_map.find( NameTransformationCompProperty( comp ) ); + if ( chain[ i ] != node_property_map.end() ) { + + // check if this curves contains redundant information by looking + // up the corresponding node's transformation chain. + if ( doc.Settings().optimizeEmptyAnimationCurves && + IsRedundantAnimationData( target, comp, ( *chain[ i ] ).second ) ) { + + FBXImporter::LogDebug( "dropping redundant animation channel for node " + target.Name() ); + continue; + } + + has_any = true; + + if ( comp != TransformationComp_Rotation && comp != TransformationComp_Scaling && comp != TransformationComp_Translation && + comp != TransformationComp_GeometricScaling && comp != TransformationComp_GeometricRotation && comp != TransformationComp_GeometricTranslation ) + { + has_complex = true; + } + } + } + + if ( !has_any ) { + FBXImporter::LogWarn( "ignoring node animation, did not find any transformation key frames" ); + return; + } + + // this needs to play nicely with GenerateTransformationNodeChain() which will + // be invoked _later_ (animations come first). If this node has only rotation, + // scaling and translation _and_ there are no animated other components either, + // we can use a single node and also a single node animation channel. + if ( !has_complex && !NeedsComplexTransformationChain( target ) ) { + + aiNodeAnim* const nd = GenerateSimpleNodeAnim( fixed_name, target, chain, + node_property_map.end(), + layer_map, + start, stop, + max_time, + min_time, + true // input is TRS order, assimp is SRT + ); + + ai_assert( nd ); + if ( nd->mNumPositionKeys == 0 && nd->mNumRotationKeys == 0 && nd->mNumScalingKeys == 0 ) { + delete nd; + } + else { + node_anims.push_back( nd ); + } + return; + } + + // otherwise, things get gruesome and we need separate animation channels + // for each part of the transformation chain. Remember which channels + // we generated and pass this information to the node conversion + // code to avoid nodes that have identity transform, but non-identity + // animations, being dropped. + unsigned int flags = 0, bit = 0x1; + for ( size_t i = 0; i < TransformationComp_MAXIMUM; ++i, bit <<= 1 ) { + const TransformationComp comp = static_cast( i ); + + if ( chain[ i ] != node_property_map.end() ) { + flags |= bit; + + ai_assert( comp != TransformationComp_RotationPivotInverse ); + ai_assert( comp != TransformationComp_ScalingPivotInverse ); + + const std::string& chain_name = NameTransformationChainNode( fixed_name, comp ); + + aiNodeAnim* na; + switch ( comp ) + { + case TransformationComp_Rotation: + case TransformationComp_PreRotation: + case TransformationComp_PostRotation: + case TransformationComp_GeometricRotation: + na = GenerateRotationNodeAnim( chain_name, + target, + ( *chain[ i ] ).second, + layer_map, + start, stop, + max_time, + min_time ); + + break; + + case TransformationComp_RotationOffset: + case TransformationComp_RotationPivot: + case TransformationComp_ScalingOffset: + case TransformationComp_ScalingPivot: + case TransformationComp_Translation: + case TransformationComp_GeometricTranslation: + na = GenerateTranslationNodeAnim( chain_name, + target, + ( *chain[ i ] ).second, + layer_map, + start, stop, + max_time, + min_time ); + + // pivoting requires us to generate an implicit inverse channel to undo the pivot translation + if ( comp == TransformationComp_RotationPivot ) { + const std::string& invName = NameTransformationChainNode( fixed_name, + TransformationComp_RotationPivotInverse ); + + aiNodeAnim* const inv = GenerateTranslationNodeAnim( invName, + target, + ( *chain[ i ] ).second, + layer_map, + start, stop, + max_time, + min_time, + true ); + + ai_assert( inv ); + if ( inv->mNumPositionKeys == 0 && inv->mNumRotationKeys == 0 && inv->mNumScalingKeys == 0 ) { + delete inv; + } + else { + node_anims.push_back( inv ); + } + + ai_assert( TransformationComp_RotationPivotInverse > i ); + flags |= bit << ( TransformationComp_RotationPivotInverse - i ); + } + else if ( comp == TransformationComp_ScalingPivot ) { + const std::string& invName = NameTransformationChainNode( fixed_name, + TransformationComp_ScalingPivotInverse ); + + aiNodeAnim* const inv = GenerateTranslationNodeAnim( invName, + target, + ( *chain[ i ] ).second, + layer_map, + start, stop, + max_time, + min_time, + true ); + + ai_assert( inv ); + if ( inv->mNumPositionKeys == 0 && inv->mNumRotationKeys == 0 && inv->mNumScalingKeys == 0 ) { + delete inv; + } + else { + node_anims.push_back( inv ); + } + + ai_assert( TransformationComp_RotationPivotInverse > i ); + flags |= bit << ( TransformationComp_RotationPivotInverse - i ); + } + + break; + + case TransformationComp_Scaling: + case TransformationComp_GeometricScaling: + na = GenerateScalingNodeAnim( chain_name, + target, + ( *chain[ i ] ).second, + layer_map, + start, stop, + max_time, + min_time ); + + break; + + default: + ai_assert( false ); + } + + ai_assert( na ); + if ( na->mNumPositionKeys == 0 && na->mNumRotationKeys == 0 && na->mNumScalingKeys == 0 ) { + delete na; + } + else { + node_anims.push_back( na ); + } + continue; + } + } + + node_anim_chain_bits[ fixed_name ] = flags; +} + +bool Converter::IsRedundantAnimationData( const Model& target, + TransformationComp comp, + const std::vector& curves ) +{ + ai_assert( curves.size() ); + + // look for animation nodes with + // * sub channels for all relevant components set + // * one key/value pair per component + // * combined values match up the corresponding value in the bind pose node transformation + // only such nodes are 'redundant' for this function. + + if ( curves.size() > 1 ) { + return false; + } + + const AnimationCurveNode& nd = *curves.front(); + const AnimationCurveMap& sub_curves = nd.Curves(); + + const AnimationCurveMap::const_iterator dx = sub_curves.find( "d|X" ); + const AnimationCurveMap::const_iterator dy = sub_curves.find( "d|Y" ); + const AnimationCurveMap::const_iterator dz = sub_curves.find( "d|Z" ); + + if ( dx == sub_curves.end() || dy == sub_curves.end() || dz == sub_curves.end() ) { + return false; + } + + const KeyValueList& vx = ( *dx ).second->GetValues(); + const KeyValueList& vy = ( *dy ).second->GetValues(); + const KeyValueList& vz = ( *dz ).second->GetValues(); + + if ( vx.size() != 1 || vy.size() != 1 || vz.size() != 1 ) { + return false; + } + + const aiVector3D dyn_val = aiVector3D( vx[ 0 ], vy[ 0 ], vz[ 0 ] ); + const aiVector3D& static_val = PropertyGet( target.Props(), + NameTransformationCompProperty( comp ), + TransformationCompDefaultValue( comp ) + ); + + const float epsilon = 1e-6f; + return ( dyn_val - static_val ).SquareLength() < epsilon; +} + + +aiNodeAnim* Converter::GenerateRotationNodeAnim( const std::string& name, + const Model& target, + const std::vector& curves, + const LayerMap& layer_map, + int64_t start, int64_t stop, + double& max_time, + double& min_time ) +{ + ScopeGuard na( new aiNodeAnim() ); + na->mNodeName.Set( name ); + + ConvertRotationKeys( na, curves, layer_map, start, stop, max_time, min_time, target.RotationOrder() ); + + // dummy scaling key + na->mScalingKeys = new aiVectorKey[ 1 ]; + na->mNumScalingKeys = 1; + + na->mScalingKeys[ 0 ].mTime = 0.; + na->mScalingKeys[ 0 ].mValue = aiVector3D( 1.0f, 1.0f, 1.0f ); + + // dummy position key + na->mPositionKeys = new aiVectorKey[ 1 ]; + na->mNumPositionKeys = 1; + + na->mPositionKeys[ 0 ].mTime = 0.; + na->mPositionKeys[ 0 ].mValue = aiVector3D(); + + return na.dismiss(); +} + +aiNodeAnim* Converter::GenerateScalingNodeAnim( const std::string& name, + const Model& /*target*/, + const std::vector& curves, + const LayerMap& layer_map, + int64_t start, int64_t stop, + double& max_time, + double& min_time ) +{ + ScopeGuard na( new aiNodeAnim() ); + na->mNodeName.Set( name ); + + ConvertScaleKeys( na, curves, layer_map, start, stop, max_time, min_time ); + + // dummy rotation key + na->mRotationKeys = new aiQuatKey[ 1 ]; + na->mNumRotationKeys = 1; + + na->mRotationKeys[ 0 ].mTime = 0.; + na->mRotationKeys[ 0 ].mValue = aiQuaternion(); + + // dummy position key + na->mPositionKeys = new aiVectorKey[ 1 ]; + na->mNumPositionKeys = 1; + + na->mPositionKeys[ 0 ].mTime = 0.; + na->mPositionKeys[ 0 ].mValue = aiVector3D(); + + return na.dismiss(); +} + + +aiNodeAnim* Converter::GenerateTranslationNodeAnim( const std::string& name, + const Model& /*target*/, + const std::vector& curves, + const LayerMap& layer_map, + int64_t start, int64_t stop, + double& max_time, + double& min_time, + bool inverse ) +{ + ScopeGuard na( new aiNodeAnim() ); + na->mNodeName.Set( name ); + + ConvertTranslationKeys( na, curves, layer_map, start, stop, max_time, min_time ); + + if ( inverse ) { + for ( unsigned int i = 0; i < na->mNumPositionKeys; ++i ) { + na->mPositionKeys[ i ].mValue *= -1.0f; + } + } + + // dummy scaling key + na->mScalingKeys = new aiVectorKey[ 1 ]; + na->mNumScalingKeys = 1; + + na->mScalingKeys[ 0 ].mTime = 0.; + na->mScalingKeys[ 0 ].mValue = aiVector3D( 1.0f, 1.0f, 1.0f ); + + // dummy rotation key + na->mRotationKeys = new aiQuatKey[ 1 ]; + na->mNumRotationKeys = 1; + + na->mRotationKeys[ 0 ].mTime = 0.; + na->mRotationKeys[ 0 ].mValue = aiQuaternion(); + + return na.dismiss(); +} + +aiNodeAnim* Converter::GenerateSimpleNodeAnim( const std::string& name, + const Model& target, + NodeMap::const_iterator chain[ TransformationComp_MAXIMUM ], + NodeMap::const_iterator iter_end, + const LayerMap& layer_map, + int64_t start, int64_t stop, + double& max_time, + double& min_time, + bool reverse_order ) + +{ + ScopeGuard na( new aiNodeAnim() ); + na->mNodeName.Set( name ); + + const PropertyTable& props = target.Props(); + + // need to convert from TRS order to SRT? + if ( reverse_order ) { + + aiVector3D def_scale = PropertyGet( props, "Lcl Scaling", aiVector3D( 1.f, 1.f, 1.f ) ); + aiVector3D def_translate = PropertyGet( props, "Lcl Translation", aiVector3D( 0.f, 0.f, 0.f ) ); + aiVector3D def_rot = PropertyGet( props, "Lcl Rotation", aiVector3D( 0.f, 0.f, 0.f ) ); + + KeyFrameListList scaling; + KeyFrameListList translation; + KeyFrameListList rotation; + + if ( chain[ TransformationComp_Scaling ] != iter_end ) { + scaling = GetKeyframeList( ( *chain[ TransformationComp_Scaling ] ).second, start, stop ); + } + + if ( chain[ TransformationComp_Translation ] != iter_end ) { + translation = GetKeyframeList( ( *chain[ TransformationComp_Translation ] ).second, start, stop ); + } + + if ( chain[ TransformationComp_Rotation ] != iter_end ) { + rotation = GetKeyframeList( ( *chain[ TransformationComp_Rotation ] ).second, start, stop ); + } + + KeyFrameListList joined; + joined.insert( joined.end(), scaling.begin(), scaling.end() ); + joined.insert( joined.end(), translation.begin(), translation.end() ); + joined.insert( joined.end(), rotation.begin(), rotation.end() ); + + const KeyTimeList& times = GetKeyTimeList( joined ); + + aiQuatKey* out_quat = new aiQuatKey[ times.size() ]; + aiVectorKey* out_scale = new aiVectorKey[ times.size() ]; + aiVectorKey* out_translation = new aiVectorKey[ times.size() ]; + + if ( times.size() ) + { + ConvertTransformOrder_TRStoSRT( out_quat, out_scale, out_translation, + scaling, + translation, + rotation, + times, + max_time, + min_time, + target.RotationOrder(), + def_scale, + def_translate, + def_rot ); + } + + // XXX remove duplicates / redundant keys which this operation did + // likely produce if not all three channels were equally dense. + + na->mNumScalingKeys = static_cast( times.size() ); + na->mNumRotationKeys = na->mNumScalingKeys; + na->mNumPositionKeys = na->mNumScalingKeys; + + na->mScalingKeys = out_scale; + na->mRotationKeys = out_quat; + na->mPositionKeys = out_translation; + } + else { + + // if a particular transformation is not given, grab it from + // the corresponding node to meet the semantics of aiNodeAnim, + // which requires all of rotation, scaling and translation + // to be set. + if ( chain[ TransformationComp_Scaling ] != iter_end ) { + ConvertScaleKeys( na, ( *chain[ TransformationComp_Scaling ] ).second, + layer_map, + start, stop, + max_time, + min_time ); + } + else { + na->mScalingKeys = new aiVectorKey[ 1 ]; + na->mNumScalingKeys = 1; + + na->mScalingKeys[ 0 ].mTime = 0.; + na->mScalingKeys[ 0 ].mValue = PropertyGet( props, "Lcl Scaling", + aiVector3D( 1.f, 1.f, 1.f ) ); + } + + if ( chain[ TransformationComp_Rotation ] != iter_end ) { + ConvertRotationKeys( na, ( *chain[ TransformationComp_Rotation ] ).second, + layer_map, + start, stop, + max_time, + min_time, + target.RotationOrder() ); + } + else { + na->mRotationKeys = new aiQuatKey[ 1 ]; + na->mNumRotationKeys = 1; + + na->mRotationKeys[ 0 ].mTime = 0.; + na->mRotationKeys[ 0 ].mValue = EulerToQuaternion( + PropertyGet( props, "Lcl Rotation", aiVector3D( 0.f, 0.f, 0.f ) ), + target.RotationOrder() ); + } + + if ( chain[ TransformationComp_Translation ] != iter_end ) { + ConvertTranslationKeys( na, ( *chain[ TransformationComp_Translation ] ).second, + layer_map, + start, stop, + max_time, + min_time ); + } + else { + na->mPositionKeys = new aiVectorKey[ 1 ]; + na->mNumPositionKeys = 1; + + na->mPositionKeys[ 0 ].mTime = 0.; + na->mPositionKeys[ 0 ].mValue = PropertyGet( props, "Lcl Translation", + aiVector3D( 0.f, 0.f, 0.f ) ); + } + + } + return na.dismiss(); +} + +Converter::KeyFrameListList Converter::GetKeyframeList( const std::vector& nodes, int64_t start, int64_t stop ) +{ + KeyFrameListList inputs; + inputs.reserve( nodes.size() * 3 ); + + //give some breathing room for rounding errors + int64_t adj_start = start - 10000; + int64_t adj_stop = stop + 10000; + + BOOST_FOREACH( const AnimationCurveNode* node, nodes ) { + ai_assert( node ); + + const AnimationCurveMap& curves = node->Curves(); + BOOST_FOREACH( const AnimationCurveMap::value_type& kv, curves ) { + + unsigned int mapto; + if ( kv.first == "d|X" ) { + mapto = 0; + } + else if ( kv.first == "d|Y" ) { + mapto = 1; + } + else if ( kv.first == "d|Z" ) { + mapto = 2; + } + else { + FBXImporter::LogWarn( "ignoring scale animation curve, did not recognize target component" ); + continue; + } + + const AnimationCurve* const curve = kv.second; + ai_assert( curve->GetKeys().size() == curve->GetValues().size() && curve->GetKeys().size() ); + + //get values within the start/stop time window + boost::shared_ptr Keys( new KeyTimeList() ); + boost::shared_ptr Values( new KeyValueList() ); + const int count = curve->GetKeys().size(); + Keys->reserve( count ); + Values->reserve( count ); + for ( int n = 0; n < count; n++ ) + { + int64_t k = curve->GetKeys().at( n ); + if ( k >= adj_start && k <= adj_stop ) + { + Keys->push_back( k ); + Values->push_back( curve->GetValues().at( n ) ); + } + } + + inputs.push_back( boost::make_tuple( Keys, Values, mapto ) ); + } + } + return inputs; // pray for NRVO :-) +} + + +KeyTimeList Converter::GetKeyTimeList( const KeyFrameListList& inputs ) +{ + ai_assert( inputs.size() ); + + // reserve some space upfront - it is likely that the keyframe lists + // have matching time values, so max(of all keyframe lists) should + // be a good estimate. + KeyTimeList keys; + + size_t estimate = 0; + BOOST_FOREACH( const KeyFrameList& kfl, inputs ) { + estimate = std::max( estimate, kfl.get<0>()->size() ); + } + + keys.reserve( estimate ); + + std::vector next_pos; + next_pos.resize( inputs.size(), 0 ); + + const size_t count = inputs.size(); + while ( true ) { + + int64_t min_tick = std::numeric_limits::max(); + for ( size_t i = 0; i < count; ++i ) { + const KeyFrameList& kfl = inputs[ i ]; + + if ( kfl.get<0>()->size() > next_pos[ i ] && kfl.get<0>()->at( next_pos[ i ] ) < min_tick ) { + min_tick = kfl.get<0>()->at( next_pos[ i ] ); + } + } + + if ( min_tick == std::numeric_limits::max() ) { + break; + } + keys.push_back( min_tick ); + + for ( size_t i = 0; i < count; ++i ) { + const KeyFrameList& kfl = inputs[ i ]; + + + while ( kfl.get<0>()->size() > next_pos[ i ] && kfl.get<0>()->at( next_pos[ i ] ) == min_tick ) { + ++next_pos[ i ]; + } + } + } + + return keys; +} + +void Converter::InterpolateKeys( aiVectorKey* valOut, const KeyTimeList& keys, const KeyFrameListList& inputs, + const aiVector3D& def_value, + double& max_time, + double& min_time ) + +{ + ai_assert( keys.size() ); + ai_assert( valOut ); + + std::vector next_pos; + const size_t count = inputs.size(); + + next_pos.resize( inputs.size(), 0 ); + + BOOST_FOREACH( KeyTimeList::value_type time, keys ) { + float result[ 3 ] = { def_value.x, def_value.y, def_value.z }; + + for ( size_t i = 0; i < count; ++i ) { + const KeyFrameList& kfl = inputs[ i ]; + + const size_t ksize = kfl.get<0>()->size(); + if ( ksize > next_pos[ i ] && kfl.get<0>()->at( next_pos[ i ] ) == time ) { + ++next_pos[ i ]; + } + + const size_t id0 = next_pos[ i ]>0 ? next_pos[ i ] - 1 : 0; + const size_t id1 = next_pos[ i ] == ksize ? ksize - 1 : next_pos[ i ]; + + // use lerp for interpolation + const KeyValueList::value_type valueA = kfl.get<1>()->at( id0 ); + const KeyValueList::value_type valueB = kfl.get<1>()->at( id1 ); + + const KeyTimeList::value_type timeA = kfl.get<0>()->at( id0 ); + const KeyTimeList::value_type timeB = kfl.get<0>()->at( id1 ); + + // do the actual interpolation in double-precision arithmetics + // because it is a bit sensitive to rounding errors. + const double factor = timeB == timeA ? 0. : static_cast( ( time - timeA ) / ( timeB - timeA ) ); + const float interpValue = static_cast( valueA + ( valueB - valueA ) * factor ); + + result[ kfl.get<2>() ] = interpValue; + } + + // magic value to convert fbx times to seconds + valOut->mTime = CONVERT_FBX_TIME( time ) * anim_fps; + + min_time = std::min( min_time, valOut->mTime ); + max_time = std::max( max_time, valOut->mTime ); + + valOut->mValue.x = result[ 0 ]; + valOut->mValue.y = result[ 1 ]; + valOut->mValue.z = result[ 2 ]; + + ++valOut; + } +} + + +void Converter::InterpolateKeys( aiQuatKey* valOut, const KeyTimeList& keys, const KeyFrameListList& inputs, + const aiVector3D& def_value, + double& maxTime, + double& minTime, + Model::RotOrder order ) +{ + ai_assert( keys.size() ); + ai_assert( valOut ); + + boost::scoped_array temp( new aiVectorKey[ keys.size() ] ); + InterpolateKeys( temp.get(), keys, inputs, def_value, maxTime, minTime ); + + aiMatrix4x4 m; + + aiQuaternion lastq; + + for ( size_t i = 0, c = keys.size(); i < c; ++i ) { + + valOut[ i ].mTime = temp[ i ].mTime; + + + GetRotationMatrix( order, temp[ i ].mValue, m ); + aiQuaternion quat = aiQuaternion( aiMatrix3x3( m ) ); + + // take shortest path by checking the inner product + // http://www.3dkingdoms.com/weekly/weekly.php?a=36 + if ( quat.x * lastq.x + quat.y * lastq.y + quat.z * lastq.z + quat.w * lastq.w < 0 ) + { + quat.x = -quat.x; + quat.y = -quat.y; + quat.z = -quat.z; + quat.w = -quat.w; + } + lastq = quat; + + valOut[ i ].mValue = quat; + } +} + + +void Converter::ConvertTransformOrder_TRStoSRT( aiQuatKey* out_quat, aiVectorKey* out_scale, + aiVectorKey* out_translation, + const KeyFrameListList& scaling, + const KeyFrameListList& translation, + const KeyFrameListList& rotation, + const KeyTimeList& times, + double& maxTime, + double& minTime, + Model::RotOrder order, + const aiVector3D& def_scale, + const aiVector3D& def_translate, + const aiVector3D& def_rotation ) +{ + if ( rotation.size() ) { + InterpolateKeys( out_quat, times, rotation, def_rotation, maxTime, minTime, order ); + } + else { + for ( size_t i = 0; i < times.size(); ++i ) { + out_quat[ i ].mTime = CONVERT_FBX_TIME( times[ i ] ) * anim_fps; + out_quat[ i ].mValue = EulerToQuaternion( def_rotation, order ); + } + } + + if ( scaling.size() ) { + InterpolateKeys( out_scale, times, scaling, def_scale, maxTime, minTime ); + } + else { + for ( size_t i = 0; i < times.size(); ++i ) { + out_scale[ i ].mTime = CONVERT_FBX_TIME( times[ i ] ) * anim_fps; + out_scale[ i ].mValue = def_scale; + } + } + + if ( translation.size() ) { + InterpolateKeys( out_translation, times, translation, def_translate, maxTime, minTime ); + } + else { + for ( size_t i = 0; i < times.size(); ++i ) { + out_translation[ i ].mTime = CONVERT_FBX_TIME( times[ i ] ) * anim_fps; + out_translation[ i ].mValue = def_translate; + } + } + + const size_t count = times.size(); + for ( size_t i = 0; i < count; ++i ) { + aiQuaternion& r = out_quat[ i ].mValue; + aiVector3D& s = out_scale[ i ].mValue; + aiVector3D& t = out_translation[ i ].mValue; + + aiMatrix4x4 mat, temp; + aiMatrix4x4::Translation( t, mat ); + mat *= aiMatrix4x4( r.GetMatrix() ); + mat *= aiMatrix4x4::Scaling( s, temp ); + + mat.Decompose( s, r, t ); + } +} + + +aiQuaternion Converter::EulerToQuaternion( const aiVector3D& rot, Model::RotOrder order ) +{ + aiMatrix4x4 m; + GetRotationMatrix( order, rot, m ); + + return aiQuaternion( aiMatrix3x3( m ) ); +} + + +void Converter::ConvertScaleKeys( aiNodeAnim* na, const std::vector& nodes, const LayerMap& /*layers*/, + int64_t start, int64_t stop, + double& maxTime, + double& minTime ) +{ + ai_assert( nodes.size() ); + + // XXX for now, assume scale should be blended geometrically (i.e. two + // layers should be multiplied with each other). There is a FBX + // property in the layer to specify the behaviour, though. + + const KeyFrameListList& inputs = GetKeyframeList( nodes, start, stop ); + const KeyTimeList& keys = GetKeyTimeList( inputs ); + + na->mNumScalingKeys = static_cast( keys.size() ); + na->mScalingKeys = new aiVectorKey[ keys.size() ]; + if ( keys.size() > 0 ) + InterpolateKeys( na->mScalingKeys, keys, inputs, aiVector3D( 1.0f, 1.0f, 1.0f ), maxTime, minTime ); +} + + +void Converter::ConvertTranslationKeys( aiNodeAnim* na, const std::vector& nodes, + const LayerMap& /*layers*/, + int64_t start, int64_t stop, + double& maxTime, + double& minTime ) +{ + ai_assert( nodes.size() ); + + // XXX see notes in ConvertScaleKeys() + const KeyFrameListList& inputs = GetKeyframeList( nodes, start, stop ); + const KeyTimeList& keys = GetKeyTimeList( inputs ); + + na->mNumPositionKeys = static_cast( keys.size() ); + na->mPositionKeys = new aiVectorKey[ keys.size() ]; + if ( keys.size() > 0 ) + InterpolateKeys( na->mPositionKeys, keys, inputs, aiVector3D( 0.0f, 0.0f, 0.0f ), maxTime, minTime ); +} + + +void Converter::ConvertRotationKeys( aiNodeAnim* na, const std::vector& nodes, + const LayerMap& /*layers*/, + int64_t start, int64_t stop, + double& maxTime, + double& minTime, + Model::RotOrder order ) +{ + ai_assert( nodes.size() ); + + // XXX see notes in ConvertScaleKeys() + const std::vector< KeyFrameList >& inputs = GetKeyframeList( nodes, start, stop ); + const KeyTimeList& keys = GetKeyTimeList( inputs ); + + na->mNumRotationKeys = static_cast( keys.size() ); + na->mRotationKeys = new aiQuatKey[ keys.size() ]; + if ( keys.size() > 0 ) + InterpolateKeys( na->mRotationKeys, keys, inputs, aiVector3D( 0.0f, 0.0f, 0.0f ), maxTime, minTime, order ); +} + +void Converter::TransferDataToScene() +{ + ai_assert( !out->mMeshes && !out->mNumMeshes ); + + // note: the trailing () ensures initialization with NULL - not + // many C++ users seem to know this, so pointing it out to avoid + // confusion why this code works. + + if ( meshes.size() ) { + out->mMeshes = new aiMesh*[ meshes.size() ](); + out->mNumMeshes = static_cast( meshes.size() ); + + std::swap_ranges( meshes.begin(), meshes.end(), out->mMeshes ); + } + + if ( materials.size() ) { + out->mMaterials = new aiMaterial*[ materials.size() ](); + out->mNumMaterials = static_cast( materials.size() ); + + std::swap_ranges( materials.begin(), materials.end(), out->mMaterials ); + } + + if ( animations.size() ) { + out->mAnimations = new aiAnimation*[ animations.size() ](); + out->mNumAnimations = static_cast( animations.size() ); + + std::swap_ranges( animations.begin(), animations.end(), out->mAnimations ); + } + + if ( lights.size() ) { + out->mLights = new aiLight*[ lights.size() ](); + out->mNumLights = static_cast( lights.size() ); + + std::swap_ranges( lights.begin(), lights.end(), out->mLights ); + } + + if ( cameras.size() ) { + out->mCameras = new aiCamera*[ cameras.size() ](); + out->mNumCameras = static_cast( cameras.size() ); + + std::swap_ranges( cameras.begin(), cameras.end(), out->mCameras ); + } + + if ( textures.size() ) { + out->mTextures = new aiTexture*[ textures.size() ](); + out->mNumTextures = static_cast( textures.size() ); + + std::swap_ranges( textures.begin(), textures.end(), out->mTextures ); + } +} + //} // !anon // ------------------------------------------------------------------------------------------------ From 397fa374a35000c1babb2307b1c491455365d8ee Mon Sep 17 00:00:00 2001 From: Sherief Farouk Date: Fri, 18 Mar 2016 17:02:39 -0700 Subject: [PATCH 030/119] Removed usage of Boost static assert. --- code/AssbinExporter.cpp | 11 +++++------ code/AssbinLoader.cpp | 3 +-- code/DefaultIOStream.cpp | 6 +++--- code/JoinVerticesProcess.cpp | 7 +++---- code/LWOMaterial.cpp | 3 +-- code/STEPFile.h | 3 +-- code/SpatialSort.cpp | 5 ++--- tools/assimp_cmd/WriteDumb.cpp | 9 ++++----- 8 files changed, 20 insertions(+), 27 deletions(-) diff --git a/code/AssbinExporter.cpp b/code/AssbinExporter.cpp index 9a70d7166..7df58cd2d 100644 --- a/code/AssbinExporter.cpp +++ b/code/AssbinExporter.cpp @@ -47,7 +47,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../include/assimp/Exporter.hpp" #include "ProcessHelper.h" #include "Exceptional.h" -#include #ifdef ASSIMP_BUILD_NO_OWN_ZLIB # include @@ -103,7 +102,7 @@ inline size_t Write(IOStream * stream, const unsigned int& w) template <> inline size_t Write(IOStream * stream, const uint16_t& w) { - BOOST_STATIC_ASSERT(sizeof(uint16_t)==2); + static_assert(sizeof(uint16_t)==2, "sizeof(uint16_t)==2"); stream->Write(&w,2,1); return 2; } @@ -113,7 +112,7 @@ inline size_t Write(IOStream * stream, const uint16_t& w) template <> inline size_t Write(IOStream * stream, const float& f) { - BOOST_STATIC_ASSERT(sizeof(float)==4); + static_assert(sizeof(float)==4, "sizeof(float)==4"); stream->Write(&f,4,1); return 4; } @@ -123,7 +122,7 @@ inline size_t Write(IOStream * stream, const float& f) template <> inline size_t Write(IOStream * stream, const double& f) { - BOOST_STATIC_ASSERT(sizeof(double)==8); + static_assert(sizeof(double)==8, "sizeof(double)==8"); stream->Write(&f,8,1); return 8; } @@ -472,7 +471,7 @@ inline size_t WriteArray(IOStream * stream, const T* in, unsigned int size) uint32_t tmp = f.mNumIndices; hash = SuperFastHash(reinterpret_cast(&tmp),sizeof tmp,hash); for (unsigned int i = 0; i < f.mNumIndices; ++i) { - BOOST_STATIC_ASSERT(AI_MAX_VERTICES <= 0xffffffff); + static_assert(AI_MAX_VERTICES <= 0xffffffff, "AI_MAX_VERTICES <= 0xffffffff"); tmp = static_cast( f.mIndices[i] ); hash = SuperFastHash(reinterpret_cast(&tmp),sizeof tmp,hash); } @@ -486,7 +485,7 @@ inline size_t WriteArray(IOStream * stream, const T* in, unsigned int size) for (unsigned int i = 0; i < mesh->mNumFaces;++i) { const aiFace& f = mesh->mFaces[i]; - BOOST_STATIC_ASSERT(AI_MAX_FACE_INDICES <= 0xffff); + static_assert(AI_MAX_FACE_INDICES <= 0xffff, "AI_MAX_FACE_INDICES <= 0xffff"); Write(&chunk,f.mNumIndices); for (unsigned int a = 0; a < f.mNumIndices;++a) { diff --git a/code/AssbinLoader.cpp b/code/AssbinLoader.cpp index 509741277..2e8e06f8a 100644 --- a/code/AssbinLoader.cpp +++ b/code/AssbinLoader.cpp @@ -54,7 +54,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../include/assimp/mesh.h" #include "../include/assimp/anim.h" #include "../include/assimp/scene.h" -#include #ifdef ASSIMP_BUILD_NO_OWN_ZLIB # include @@ -351,7 +350,7 @@ void AssbinImporter::ReadBinaryMesh( IOStream * stream, aiMesh* mesh ) for (unsigned int i = 0; i < mesh->mNumFaces;++i) { aiFace& f = mesh->mFaces[i]; - BOOST_STATIC_ASSERT(AI_MAX_FACE_INDICES <= 0xffff); + static_assert(AI_MAX_FACE_INDICES <= 0xffff, "AI_MAX_FACE_INDICES <= 0xffff"); f.mNumIndices = Read(stream); f.mIndices = new unsigned int[f.mNumIndices]; diff --git a/code/DefaultIOStream.cpp b/code/DefaultIOStream.cpp index a6ca86484..31116e697 100644 --- a/code/DefaultIOStream.cpp +++ b/code/DefaultIOStream.cpp @@ -45,7 +45,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../include/assimp/ai_assert.h" #include "DefaultIOStream.h" -#include #include #include @@ -86,8 +85,9 @@ aiReturn DefaultIOStream::Seek(size_t pOffset, } // Just to check whether our enum maps one to one with the CRT constants - BOOST_STATIC_ASSERT(aiOrigin_CUR == SEEK_CUR && - aiOrigin_END == SEEK_END && aiOrigin_SET == SEEK_SET); + static_assert(aiOrigin_CUR == SEEK_CUR && + aiOrigin_END == SEEK_END && aiOrigin_SET == SEEK_SET, "aiOrigin_CUR == SEEK_CUR && \ + aiOrigin_END == SEEK_END && aiOrigin_SET == SEEK_SET"); // do the seek return (0 == ::fseek(mFile, (long)pOffset,(int)pOrigin) ? AI_SUCCESS : AI_FAILURE); diff --git a/code/JoinVerticesProcess.cpp b/code/JoinVerticesProcess.cpp index 7874d97e7..b822b527c 100644 --- a/code/JoinVerticesProcess.cpp +++ b/code/JoinVerticesProcess.cpp @@ -51,7 +51,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "Vertex.h" #include "TinyFormatter.h" #include -#include using namespace Assimp; // ------------------------------------------------------------------------------------------------ @@ -117,8 +116,8 @@ void JoinVerticesProcess::Execute( aiScene* pScene) // Unites identical vertices in the given mesh int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex) { - BOOST_STATIC_ASSERT( AI_MAX_NUMBER_OF_COLOR_SETS == 8); - BOOST_STATIC_ASSERT( AI_MAX_NUMBER_OF_TEXTURECOORDS == 8); + static_assert( AI_MAX_NUMBER_OF_COLOR_SETS == 8, "AI_MAX_NUMBER_OF_COLOR_SETS == 8"); + static_assert( AI_MAX_NUMBER_OF_TEXTURECOORDS == 8, "AI_MAX_NUMBER_OF_TEXTURECOORDS == 8"); // Return early if we don't have any positions if (!pMesh->HasPositions() || !pMesh->HasFaces()) { @@ -134,7 +133,7 @@ int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex) // whether a new vertex was created for the index (true) or if it was replaced by an existing // unique vertex (false). This saves an additional std::vector and greatly enhances // branching performance. - BOOST_STATIC_ASSERT(AI_MAX_VERTICES == 0x7fffffff); + static_assert(AI_MAX_VERTICES == 0x7fffffff, "AI_MAX_VERTICES == 0x7fffffff"); std::vector replaceIndex( pMesh->mNumVertices, 0xffffffff); // A little helper to find locally close vertices faster. diff --git a/code/LWOMaterial.cpp b/code/LWOMaterial.cpp index 7513032ee..b80dae1e8 100644 --- a/code/LWOMaterial.cpp +++ b/code/LWOMaterial.cpp @@ -48,7 +48,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // internal headers #include "LWOLoader.h" #include "ByteSwapper.h" -#include using namespace Assimp; @@ -160,7 +159,7 @@ bool LWOImporter::HandleTextures(aiMaterial* pcMat, const TextureList& in, aiTex trafo.mScaling.x = (*it).wrapAmountW; trafo.mScaling.y = (*it).wrapAmountH; - BOOST_STATIC_ASSERT(sizeof(aiUVTransform)/sizeof(float) == 5); + static_assert(sizeof(aiUVTransform)/sizeof(float) == 5, "sizeof(aiUVTransform)/sizeof(float) == 5"); pcMat->AddProperty(&trafo,1,AI_MATKEY_UVTRANSFORM(type,cur)); } DefaultLogger::get()->debug("LWO2: Setting up non-UV mapping"); diff --git a/code/STEPFile.h b/code/STEPFile.h index d688fc9fd..a0f936889 100644 --- a/code/STEPFile.h +++ b/code/STEPFile.h @@ -42,7 +42,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define INCLUDED_AI_STEPFILE_H #include -#include #include #include #include @@ -722,7 +721,7 @@ namespace STEP { ListOf() { - BOOST_STATIC_ASSERT(min_cnt <= max_cnt || !max_cnt); + static_assert(min_cnt <= max_cnt || !max_cnt, "min_cnt <= max_cnt || !max_cnt"); } }; diff --git a/code/SpatialSort.cpp b/code/SpatialSort.cpp index 3420983f0..2cf179a92 100644 --- a/code/SpatialSort.cpp +++ b/code/SpatialSort.cpp @@ -42,7 +42,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /** @file Implementation of the helper class to quickly find vertices close to a given position */ #include "SpatialSort.h" -#include #include "../include/assimp/ai_assert.h" using namespace Assimp; @@ -192,14 +191,14 @@ namespace { // If this assertion fails, signed int is not big enough to store a float on your platform. // Please correct the declaration of BinFloat a few lines above - but do it in a portable, // #ifdef'd manner! - BOOST_STATIC_ASSERT( sizeof(BinFloat) >= sizeof(float)); + static_assert( sizeof(BinFloat) >= sizeof(float), "sizeof(BinFloat) >= sizeof(float)"); #if defined( _MSC_VER) // If this assertion fails, Visual C++ has finally moved to ILP64. This means that this // code has just become legacy code! Find out the current value of _MSC_VER and modify // the #if above so it evaluates false on the current and all upcoming VC versions (or // on the current platform, if LP64 or LLP64 are still used on other platforms). - BOOST_STATIC_ASSERT( sizeof(BinFloat) == sizeof(float)); + static_assert( sizeof(BinFloat) == sizeof(float), "sizeof(BinFloat) == sizeof(float)"); // This works best on Visual C++, but other compilers have their problems with it. const BinFloat binValue = reinterpret_cast(pValue); diff --git a/tools/assimp_cmd/WriteDumb.cpp b/tools/assimp_cmd/WriteDumb.cpp index 6a8ea3007..12f5bd25a 100644 --- a/tools/assimp_cmd/WriteDumb.cpp +++ b/tools/assimp_cmd/WriteDumb.cpp @@ -58,7 +58,6 @@ const char* AICMD_MSG_DUMP_HELP = ; #include "../../code/assbin_chunks.h" -#include FILE* out = NULL; bool shortened = false; @@ -151,7 +150,7 @@ inline uint32_t Write(const uint16_t& w) template <> inline uint32_t Write(const float& f) { - BOOST_STATIC_ASSERT(sizeof(float)==4); + static_assert(sizeof(float)==4, "sizeof(float)==4"); fwrite(&f,4,1,out); return 4; } @@ -161,7 +160,7 @@ inline uint32_t Write(const float& f) template <> inline uint32_t Write(const double& f) { - BOOST_STATIC_ASSERT(sizeof(double)==8); + static_assert(sizeof(double)==8, "sizeof(double)==8"); fwrite(&f,8,1,out); return 8; } @@ -424,7 +423,7 @@ uint32_t WriteBinaryMesh(const aiMesh* mesh) uint32_t tmp = f.mNumIndices; hash = SuperFastHash(reinterpret_cast(&tmp),sizeof tmp,hash); for (unsigned int i = 0; i < f.mNumIndices; ++i) { - BOOST_STATIC_ASSERT(AI_MAX_VERTICES <= 0xffffffff); + static_assert(AI_MAX_VERTICES <= 0xffffffff, "AI_MAX_VERTICES <= 0xffffffff"); tmp = static_cast( f.mIndices[i] ); hash = SuperFastHash(reinterpret_cast(&tmp),sizeof tmp,hash); } @@ -438,7 +437,7 @@ uint32_t WriteBinaryMesh(const aiMesh* mesh) for (unsigned int i = 0; i < mesh->mNumFaces;++i) { const aiFace& f = mesh->mFaces[i]; - BOOST_STATIC_ASSERT(AI_MAX_FACE_INDICES <= 0xffff); + static_assert(AI_MAX_FACE_INDICES <= 0xffff, "AI_MAX_FACE_INDICES <= 0xffff"); len += Write(f.mNumIndices); for (unsigned int a = 0; a < f.mNumIndices;++a) { From abb3e6b8544a5a9ff1f410e0719909fd9f5a36ce Mon Sep 17 00:00:00 2001 From: Robert Liebo Date: Tue, 22 Mar 2016 18:38:28 +0100 Subject: [PATCH 031/119] [VCS-1030] fallback for non-found .mtl file: try file name of original obj with just the file extension replaced by "mtl" --- code/ObjFileImporter.cpp | 2 +- code/ObjFileParser.cpp | 16 +++++++++++----- code/ObjFileParser.h | 4 +++- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/code/ObjFileImporter.cpp b/code/ObjFileImporter.cpp index f5c727ec9..9bc2fc506 100644 --- a/code/ObjFileImporter.cpp +++ b/code/ObjFileImporter.cpp @@ -177,7 +177,7 @@ void ObjFileImporter::InternReadFile( const std::string &file, aiScene* pScene, m_progress->UpdateFileRead(1, 3); // parse the file into a temporary representation - ObjFileParser parser(m_Buffer, modelName, pIOHandler, m_progress); + ObjFileParser parser(m_Buffer, modelName, pIOHandler, m_progress, file); // And create the proper return structures out of it CreateDataFromImport(parser.GetModel(), pScene); diff --git a/code/ObjFileParser.cpp b/code/ObjFileParser.cpp index f23cea879..4ef544f28 100644 --- a/code/ObjFileParser.cpp +++ b/code/ObjFileParser.cpp @@ -61,13 +61,14 @@ const std::string ObjFileParser::DEFAULT_MATERIAL = AI_DEFAULT_MATERIAL_NAME; // ------------------------------------------------------------------- // Constructor with loaded data and directories. -ObjFileParser::ObjFileParser(std::vector &data,const std::string &modelName, IOSystem *io, ProgressHandler* progress ) : +ObjFileParser::ObjFileParser(std::vector &data, const std::string &modelName, IOSystem *io, ProgressHandler* progress, const std::string &originalObjFileName) : m_DataIt(data.begin()), m_DataItEnd(data.end()), m_pModel(NULL), m_uiLine(0), m_pIO( io ), - m_progress(progress) + m_progress(progress), + m_originalObjFileName(originalObjFileName) { std::fill_n(m_buffer,Buffersize,0); @@ -573,9 +574,14 @@ void ObjFileParser::getMaterialLib() IOStream *pFile = m_pIO->Open( absName ); if (!pFile ) { - DefaultLogger::get()->error( "OBJ: Unable to locate material file " + strMatName ); - m_DataIt = skipLine( m_DataIt, m_DataItEnd, m_uiLine ); - return; + DefaultLogger::get()->error("OBJ: Unable to locate material file " + strMatName); + std::string strMatFallbackName = m_originalObjFileName.substr(0, m_originalObjFileName.length() - 3) + "mtl"; + pFile = m_pIO->Open(strMatFallbackName); + if (!pFile) { + DefaultLogger::get()->error("OBJ: Unable to locate material fallback file " + strMatName); + m_DataIt = skipLine(m_DataIt, m_DataItEnd, m_uiLine); + return; + } } // Import material library data from file. diff --git a/code/ObjFileParser.h b/code/ObjFileParser.h index e16de49a8..7170f0d50 100644 --- a/code/ObjFileParser.h +++ b/code/ObjFileParser.h @@ -72,7 +72,7 @@ public: public: /// \brief Constructor with data array. - ObjFileParser(std::vector &Data,const std::string &strModelName, IOSystem* io, ProgressHandler* progress); + ObjFileParser(std::vector &Data, const std::string &strModelName, IOSystem* io, ProgressHandler* progress, const std::string &originalObjFileName); /// \brief Destructor ~ObjFileParser(); /// \brief Model getter. @@ -143,6 +143,8 @@ private: //! Pointer to progress handler ProgressHandler* m_progress; /// Path to the current model + // name of the obj file where the buffer comes from + const std::string& m_originalObjFileName; }; } // Namespace Assimp From 124fc9ae27a8e2d0d60f39b005a3cce8f73fab46 Mon Sep 17 00:00:00 2001 From: Robert Liebo Date: Tue, 22 Mar 2016 18:39:52 +0100 Subject: [PATCH 032/119] [VCS-1030] add log info about .mtl fallback --- code/ObjFileParser.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/code/ObjFileParser.cpp b/code/ObjFileParser.cpp index 4ef544f28..a6f515aba 100644 --- a/code/ObjFileParser.cpp +++ b/code/ObjFileParser.cpp @@ -576,9 +576,10 @@ void ObjFileParser::getMaterialLib() if (!pFile ) { DefaultLogger::get()->error("OBJ: Unable to locate material file " + strMatName); std::string strMatFallbackName = m_originalObjFileName.substr(0, m_originalObjFileName.length() - 3) + "mtl"; + DefaultLogger::get()->info("OBJ: Opening fallback material file " + strMatFallbackName); pFile = m_pIO->Open(strMatFallbackName); if (!pFile) { - DefaultLogger::get()->error("OBJ: Unable to locate material fallback file " + strMatName); + DefaultLogger::get()->error("OBJ: Unable to locate fallback material file " + strMatName); m_DataIt = skipLine(m_DataIt, m_DataItEnd, m_uiLine); return; } From ca0fa2ba69c11d9999e007fe0e7486bb7ae9d13f Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 22 Mar 2016 20:25:29 +0100 Subject: [PATCH 033/119] FBX-Importer: put debug printf into comments. --- code/FBXParser.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/code/FBXParser.cpp b/code/FBXParser.cpp index 3f982c64a..0c3290151 100644 --- a/code/FBXParser.cpp +++ b/code/FBXParser.cpp @@ -655,13 +655,13 @@ void ParseVectorDataArray(std::vector& out, const Element& el) static_cast(d[1]), static_cast(d[2]))); } - - for ( size_t i = 0; i < out.size(); i++ ) { + // for debugging + /*for ( size_t i = 0; i < out.size(); i++ ) { aiVector3D vec3( out[ i ] ); std::stringstream stream; stream << " vec3.x = " << vec3.x << " vec3.y = " << vec3.y << " vec3.z = " << vec3.z << std::endl; DefaultLogger::get()->info( stream.str() ); - } + }*/ } else if (type == 'f') { const float* f = reinterpret_cast(&buff[0]); From 23892a6deddc4fa367a09b278a78345112eb62ee Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 22 Mar 2016 20:30:25 +0100 Subject: [PATCH 034/119] FBX: add debugging tool to log class type + info. --- code/FBXDocument.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/code/FBXDocument.cpp b/code/FBXDocument.cpp index 0252d0eb1..e2c38aa85 100644 --- a/code/FBXDocument.cpp +++ b/code/FBXDocument.cpp @@ -79,6 +79,12 @@ LazyObject::~LazyObject() } +// ------------------------------------------------------------------------------------------------ +static void dumpObjectClassInfo( const char* obtype, const std::string &classtag ) { + DefaultLogger::get()->debug( "obtype: " + std::string(obtype )); + DefaultLogger::get()->debug( "Classtag: " + classtag ); +} + // ------------------------------------------------------------------------------------------------ const Object* LazyObject::Get(bool dieOnError) { @@ -137,8 +143,10 @@ const Object* LazyObject::Get(bool dieOnError) // so avoid constructing strings all the time. const char* obtype = key.begin(); const size_t length = static_cast(key.end()-key.begin()); - DefaultLogger::get()->debug( "obtype: " + std::string(obtype )); - DefaultLogger::get()->debug( "Classtag: " + classtag ); + + // For debugging + //dumpObjectClassInfo( objtype, classtag ); + if (!strncmp(obtype,"Geometry",length)) { if (!strcmp(classtag.c_str(),"Mesh")) { object.reset(new MeshGeometry(id,element,name,doc)); From 7c71f0b7a9e1c8b5cbbf788f2d1482b0e81b7f79 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Thu, 24 Mar 2016 19:53:15 +0100 Subject: [PATCH 035/119] PLYLoader: improve readability by refactorings. --- code/PlyLoader.cpp | 78 +++++++++++++++++++++++++++------------------- 1 file changed, 46 insertions(+), 32 deletions(-) diff --git a/code/PlyLoader.cpp b/code/PlyLoader.cpp index 1378d1ebb..15e20b2c4 100644 --- a/code/PlyLoader.cpp +++ b/code/PlyLoader.cpp @@ -122,6 +122,24 @@ const aiImporterDesc* PLYImporter::GetInfo () const return &desc; } +// ------------------------------------------------------------------------------------------------ +static bool isBigEndian( char* szMe ) { + // binary_little_endian + // binary_big_endian + bool isBigEndian( false ); +#if (defined AI_BUILD_BIG_ENDIAN) + if ( 'l' == *szMe || 'L' == *szMe ) { + isBigEndian = true; +} +#else + if ( 'b' == *szMe || 'B' == *szMe ) { + isBigEndian = true; + } +#endif // ! AI_BUILD_BIG_ENDIAN + + return isBigEndian; +} + // ------------------------------------------------------------------------------------------------ // Imports the given file into the given scene structure. void PLYImporter::InternReadFile( const std::string& pFile, @@ -151,33 +169,24 @@ void PLYImporter::InternReadFile( const std::string& pFile, // determine the format of the file data PLY::DOM sPlyDom; - if (TokenMatch(szMe,"format",6)) - { - if (TokenMatch(szMe,"ascii",5)) - { + if (TokenMatch(szMe,"format",6)) { + if (TokenMatch(szMe,"ascii",5)) { SkipLine(szMe,(const char**)&szMe); if(!PLY::DOM::ParseInstance(szMe,&sPlyDom)) throw DeadlyImportError( "Invalid .ply file: Unable to build DOM (#1)"); - } - else if (!::strncmp(szMe,"binary_",7)) + } else if (!::strncmp(szMe,"binary_",7)) { - bool bIsBE = false; - szMe+=7; - - // binary_little_endian - // binary_big_endian -#if (defined AI_BUILD_BIG_ENDIAN) - if ('l' == *szMe || 'L' == *szMe)bIsBE = true; -#else - if ('b' == *szMe || 'B' == *szMe)bIsBE = true; -#endif // ! AI_BUILD_BIG_ENDIAN + szMe += 7; + const bool bIsBE( isBigEndian( szMe ) ); // skip the line, parse the rest of the header and build the DOM SkipLine(szMe,(const char**)&szMe); - if(!PLY::DOM::ParseInstanceBinary(szMe,&sPlyDom,bIsBE)) - throw DeadlyImportError( "Invalid .ply file: Unable to build DOM (#2)"); + if ( !PLY::DOM::ParseInstanceBinary( szMe, &sPlyDom, bIsBE ) ) { + throw DeadlyImportError( "Invalid .ply file: Unable to build DOM (#2)" ); + } + } else { + throw DeadlyImportError( "Invalid .ply file: Unknown file format" ); } - else throw DeadlyImportError( "Invalid .ply file: Unknown file format"); } else { @@ -186,13 +195,14 @@ void PLYImporter::InternReadFile( const std::string& pFile, } this->pcDOM = &sPlyDom; - // now load a list of vertices. This must be sucessfull in order to procede + // now load a list of vertices. This must be successfully in order to procedure std::vector avPositions; this->LoadVertices(&avPositions,false); - if (avPositions.empty()) + if ( avPositions.empty() ) { throw DeadlyImportError( "Invalid .ply file: No vertices found. " - "Unable to parse the data format of the PLY file."); + "Unable to parse the data format of the PLY file." ); + } // now load a list of normals. std::vector avNormals; @@ -246,28 +256,32 @@ void PLYImporter::InternReadFile( const std::string& pFile, ConvertMeshes(&avFaces,&avPositions,&avNormals, &avColors,&avTexCoords,&avMaterials,&avMeshes); - if (avMeshes.empty()) - throw DeadlyImportError( "Invalid .ply file: Unable to extract mesh data "); + if ( avMeshes.empty() ) { + throw DeadlyImportError( "Invalid .ply file: Unable to extract mesh data " ); + } // now generate the output scene object. Fill the material list pScene->mNumMaterials = (unsigned int)avMaterials.size(); pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials]; - for (unsigned int i = 0; i < pScene->mNumMaterials;++i) - pScene->mMaterials[i] = avMaterials[i]; + for ( unsigned int i = 0; i < pScene->mNumMaterials; ++i ) { + pScene->mMaterials[ i ] = avMaterials[ i ]; + } // fill the mesh list pScene->mNumMeshes = (unsigned int)avMeshes.size(); pScene->mMeshes = new aiMesh*[pScene->mNumMeshes]; - for (unsigned int i = 0; i < pScene->mNumMeshes;++i) - pScene->mMeshes[i] = avMeshes[i]; + for ( unsigned int i = 0; i < pScene->mNumMeshes; ++i ) { + pScene->mMeshes[ i ] = avMeshes[ i ]; + } // generate a simple node structure pScene->mRootNode = new aiNode(); pScene->mRootNode->mNumMeshes = pScene->mNumMeshes; pScene->mRootNode->mMeshes = new unsigned int[pScene->mNumMeshes]; - for (unsigned int i = 0; i < pScene->mRootNode->mNumMeshes;++i) - pScene->mRootNode->mMeshes[i] = i; + for ( unsigned int i = 0; i < pScene->mRootNode->mNumMeshes; ++i ) { + pScene->mRootNode->mMeshes[ i ] = i; + } } // ------------------------------------------------------------------------------------------------ @@ -291,7 +305,7 @@ void PLYImporter::ConvertMeshes(std::vector* avFaces, for (std::vector::const_iterator i = avFaces->begin();i != avFaces->end();++i,++iNum) aiSplit[(*i).iMaterialIndex].push_back(iNum); - // now generate submeshes + // now generate sub-meshes for (unsigned int p = 0; p < avMaterials->size();++p) { if (aiSplit[p].size() != 0) @@ -491,7 +505,7 @@ void PLYImporter::LoadVertices(std::vector* pvOut, bool p_bNormals) PLY::ElementInstanceList* pcList = NULL; unsigned int cnt = 0; - // serach in the DOM for a vertex entry + // search in the DOM for a vertex entry unsigned int _i = 0; for (std::vector::const_iterator i = pcDOM->alElements.begin(); i != pcDOM->alElements.end();++i,++_i) From 1592a182106df9bda08cedf5f66c5740acaeb0fa Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Fri, 25 Mar 2016 00:09:56 +0100 Subject: [PATCH 036/119] PLYLoader: fix review comments. --- code/PlyLoader.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/code/PlyLoader.cpp b/code/PlyLoader.cpp index 15e20b2c4..4e6ea8137 100644 --- a/code/PlyLoader.cpp +++ b/code/PlyLoader.cpp @@ -123,7 +123,9 @@ const aiImporterDesc* PLYImporter::GetInfo () const } // ------------------------------------------------------------------------------------------------ -static bool isBigEndian( char* szMe ) { +static bool isBigEndian( const char* szMe ) { + ai_assert( NULL != szMe ); + // binary_little_endian // binary_big_endian bool isBigEndian( false ); From 2c3bbe041a9f1df4c68d534e8af27e251f7fc172 Mon Sep 17 00:00:00 2001 From: Steven Thompson Date: Sun, 27 Mar 2016 20:12:22 +0100 Subject: [PATCH 037/119] Set xrange to range for Python 3.0 and above --- port/PyAssimp/pyassimp/core.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/port/PyAssimp/pyassimp/core.py b/port/PyAssimp/pyassimp/core.py index f035b35e5..a183dc79c 100644 --- a/port/PyAssimp/pyassimp/core.py +++ b/port/PyAssimp/pyassimp/core.py @@ -8,6 +8,11 @@ import sys if sys.version_info < (2,6): raise 'pyassimp: need python 2.6 or newer' +# xrange was renamed range in Python 3 and the original range from Python 2 was removed. +# To keep compatibility with both Python 2 and 3, xrange is set to range for version 3.0 and up. +if sys.version_info >= (3,0): + xrange = range + import ctypes import os From 0d444793999885666c609b6d5abc37e45f1be491 Mon Sep 17 00:00:00 2001 From: boxdot Date: Tue, 29 Mar 2016 21:10:15 +0200 Subject: [PATCH 038/119] Import reflectance factor from Blender. --- code/BlenderLoader.cpp | 6 ++++++ code/BlenderScene.cpp | 2 ++ code/BlenderScene.h | 4 ++++ 3 files changed, 12 insertions(+) diff --git a/code/BlenderLoader.cpp b/code/BlenderLoader.cpp index abf6bb9c0..8df2f50fb 100644 --- a/code/BlenderLoader.cpp +++ b/code/BlenderLoader.cpp @@ -631,6 +631,12 @@ void BlenderImporter::BuildMaterials(ConversionData& conv_data) col = aiColor3D(mat->ambr,mat->ambg,mat->ambb); mout->AddProperty(&col,1,AI_MATKEY_COLOR_AMBIENT); + // is mirror enabled? + if( mat->mode & MA_RAYMIRROR ) { + const float ray_mirror = mat->ray_mirror; + mout->AddProperty(&ray_mirror,1,AI_MATKEY_REFLECTIVITY); + } + col = aiColor3D(mat->mirr,mat->mirg,mat->mirb); mout->AddProperty(&col,1,AI_MATKEY_COLOR_REFLECTIVE); diff --git a/code/BlenderScene.cpp b/code/BlenderScene.cpp index 1273de81e..2ebc13f21 100644 --- a/code/BlenderScene.cpp +++ b/code/BlenderScene.cpp @@ -313,9 +313,11 @@ template <> void Structure :: Convert ( ReadField(dest.mirg,"mirg",db); ReadField(dest.mirb,"mirb",db); ReadField(dest.emit,"emit",db); + ReadField(dest.ray_mirror,"ray_mirror",db); ReadField(dest.alpha,"alpha",db); ReadField(dest.ref,"ref",db); ReadField(dest.translucency,"translucency",db); + ReadField(dest.mode,"mode",db); ReadField(dest.roughness,"roughness",db); ReadField(dest.darkness,"darkness",db); ReadField(dest.refrac,"refrac",db); diff --git a/code/BlenderScene.h b/code/BlenderScene.h index c7d5f7eb7..768435f98 100644 --- a/code/BlenderScene.h +++ b/code/BlenderScene.h @@ -239,6 +239,8 @@ struct MDeformVert : ElemBase { }; // ------------------------------------------------------------------------------- +#define MA_RAYMIRROR 0x40000 + struct Material : ElemBase { ID id FAIL; @@ -248,9 +250,11 @@ struct Material : ElemBase { float ambr,ambg,ambb WARN; float mirr,mirg,mirb; float emit WARN; + float ray_mirror; float alpha WARN; float ref; float translucency; + int mode; float roughness; float darkness; float refrac; From c53903ff0b41955ef253c2ab6ae8503acec54432 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Thu, 31 Mar 2016 11:11:55 +0200 Subject: [PATCH 039/119] Update CMakeLists.txt Enable c++11 support for this branch. --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 538d2665b..160a1340a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,6 +20,7 @@ set(ASSIMP_PACKAGE_VERSION "0" CACHE STRING "the package-specific version used f # Needed for openddl_parser config, no use of c++11 at this moment add_definitions( -DOPENDDL_NO_USE_CPP11 ) +set_property( GLOBAL PROPERTY CXX_STANDARD 11 ) # Get the current working branch execute_process( From b573676a1b69f8cc16bd644b269134cc754edede Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Thu, 31 Mar 2016 11:26:38 +0200 Subject: [PATCH 040/119] Update CMakeLists.txt Enable c++11 support manually by using the compiler flags. --- CMakeLists.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 160a1340a..1b2f12612 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -70,10 +70,12 @@ if((CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX) AND NOT CMAKE_COMPILER_ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") endif() # hide all not-exported symbols - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden -Wall" ) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden -Wall -std=c++0x" ) elseif(MSVC) # enable multi-core compilation with MSVC add_compile_options(/MP) +elseif ( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" ) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden -Wall -Wno-long-long -pedantic -std=c++11" ) endif() INCLUDE (FindPkgConfig) From 87e7cf00a29632125a610619819158e33e64eff1 Mon Sep 17 00:00:00 2001 From: Eric Engestrom Date: Sun, 3 Apr 2016 01:38:00 +0100 Subject: [PATCH 041/119] Fix spelling mistakes --- CREDITS | 4 ++-- Readme.md | 2 +- assimp-config.cmake.in | 2 +- code/3DSLoader.cpp | 2 +- code/ACLoader.cpp | 2 +- code/ASEParser.h | 2 +- code/BVHLoader.cpp | 2 +- code/BaseImporter.cpp | 6 +++--- code/BaseImporter.h | 4 ++-- code/CSMLoader.cpp | 6 +++--- code/ColladaExporter.cpp | 4 ++-- code/ColladaLoader.cpp | 6 +++--- code/ColladaParser.cpp | 10 +++++----- code/DXFLoader.cpp | 2 +- code/FBXBinaryTokenizer.cpp | 2 +- code/FBXMeshGeometry.cpp | 2 +- code/FBXUtil.h | 4 ++-- code/FileSystemFilter.h | 2 +- code/Importer.cpp | 4 ++-- code/Importer.h | 2 +- code/JoinVerticesProcess.cpp | 6 +++--- code/LWOBLoader.cpp | 6 +++--- code/LWOLoader.cpp | 2 +- code/LimitBoneWeightsProcess.h | 2 +- code/MD3FileData.h | 2 +- code/MD3Loader.cpp | 6 +++--- code/MD5Parser.cpp | 2 +- code/MD5Parser.h | 4 ++-- code/MDLLoader.cpp | 2 +- code/MDLMaterialLoader.cpp | 6 +++--- code/NDOLoader.cpp | 2 +- code/PlyParser.cpp | 14 +++++++------- code/SMDLoader.h | 2 +- code/STLLoader.cpp | 2 +- code/SceneCombiner.h | 4 ++-- code/SpatialSort.cpp | 2 +- code/SpatialSort.h | 2 +- code/StandardShapes.h | 2 +- code/StreamReader.h | 10 +++++----- code/StreamWriter.h | 8 ++++---- code/TerragenLoader.cpp | 2 +- code/TextureTransform.cpp | 2 +- code/XFileImporter.cpp | 2 +- code/XFileParser.cpp | 4 ++-- doc/dox.h | 18 +++++++++--------- include/assimp/Compiler/pstdint.h | 2 +- include/assimp/Importer.hpp | 2 +- include/assimp/anim.h | 2 +- include/assimp/material.h | 2 +- include/assimp/mesh.h | 2 +- .../port/AndroidJNI/AndroidJNIIOSystem.h | 2 +- port/PyAssimp/pyassimp/errors.py | 2 +- port/PyAssimp/pyassimp/structs.py | 2 +- port/dAssimp/assimp/api.d | 2 +- port/dAssimp/assimp/material.d | 2 +- port/dAssimp/assimp/math.d | 4 ++-- port/dAssimp/assimp/mesh.d | 6 +++--- .../jassimp/src/jassimp/AiTextureMapMode.java | 2 +- port/swig/interface/assimp.i | 2 +- samples/DevIL/ChangeLog | 6 +++--- samples/DevIL/include/IL/config.h | 2 +- samples/DevIL/include/IL/config.h.win | 2 +- samples/DevIL/include/IL/ilut_config.h | 2 +- samples/SimpleAssimpViewX/MyDocument.mm | 2 +- .../SimpleTexturedOpenGL/src/model_loading.cpp | 6 +++--- samples/glut/README-win32.txt | 6 +++--- test/models/LWO/LWO2/concrete.source.txt | 2 +- test/regression/README.txt | 2 +- tools/assimp_view/Display.cpp | 4 ++-- tools/assimp_view/Material.cpp | 2 +- tools/assimp_view/assimp_view.h | 2 +- workspaces/Android-NDK/jni/Android.mk | 2 +- 72 files changed, 129 insertions(+), 129 deletions(-) diff --git a/CREDITS b/CREDITS index 774bed5f8..9186c092e 100644 --- a/CREDITS +++ b/CREDITS @@ -30,7 +30,7 @@ Ogre Loader, VC2010 fixes and CMake fixes. - Sebastian Hempel, PyAssimp (first version) -Compile-Bugfixes for mingw, add enviroment for static library support in make. +Compile-Bugfixes for mingw, add environment for static library support in make. - Jonathan Pokrass Supplied a bugfix concerning the scaling in the md3 loader. @@ -114,7 +114,7 @@ Contributes a fix for the configure script environment. Contributed AssimpDelphi (/port/AssimpDelphi). - rdb -Contributes a bundle of fixes and improvments for the bsp-importer. +Contributes a bundle of fixes and improvements for the bsp-importer. - Mick P For contributing the De-bone postprocessing step and filing various bug reports. diff --git a/Readme.md b/Readme.md index cafcf4921..0d69023ff 100644 --- a/Readme.md +++ b/Readme.md @@ -100,7 +100,7 @@ Open Asset Import Library is implemented in C++. The directory structure is: /tools Tools (old assimp viewer, command line `assimp`) /samples A small number of samples to illustrate possible use cases for Assimp - /workspaces Build enviroments for vc,xcode,... (deprecated, + /workspaces Build environments for vc,xcode,... (deprecated, CMake has superseeded all legacy build options!) diff --git a/assimp-config.cmake.in b/assimp-config.cmake.in index 7e57d79d3..e06cc10ee 100644 --- a/assimp-config.cmake.in +++ b/assimp-config.cmake.in @@ -64,7 +64,7 @@ set( ASSIMP_LIBRARIES ${ASSIMP_LIBRARIES}@CMAKE_DEBUG_POSTFIX@) # the boost version assimp was compiled with set( ASSIMP_Boost_VERSION "@Boost_MAJOR_VERSION@.@Boost_MINOR_VERSION@") -# for compatibility wiht pkg-config +# for compatibility with pkg-config set(ASSIMP_CFLAGS_OTHER "${ASSIMP_CXX_FLAGS}") set(ASSIMP_LDFLAGS_OTHER "${ASSIMP_LINK_FLAGS}") diff --git a/code/3DSLoader.cpp b/code/3DSLoader.cpp index 2c55ba977..f6ade56a3 100644 --- a/code/3DSLoader.cpp +++ b/code/3DSLoader.cpp @@ -197,7 +197,7 @@ void Discreet3DSImporter::InternReadFile( const std::string& pFile, ComputeNormalsWithSmoothingsGroups(*i); } - // Replace all occurences of the default material with a + // Replace all occurrences of the default material with a // valid material. Generate it if no material containing // DEFAULT in its name has been found in the file ReplaceDefaultMaterial(); diff --git a/code/ACLoader.cpp b/code/ACLoader.cpp index f84027501..4607d3536 100644 --- a/code/ACLoader.cpp +++ b/code/ACLoader.cpp @@ -884,7 +884,7 @@ void AC3DImporter::InternReadFile( const std::string& pFile, // copy meshes if (meshes.empty()) { - throw DeadlyImportError("An unknown error occured during converting"); + throw DeadlyImportError("An unknown error occurred during converting"); } pScene->mNumMeshes = (unsigned int)meshes.size(); pScene->mMeshes = new aiMesh*[pScene->mNumMeshes]; diff --git a/code/ASEParser.h b/code/ASEParser.h index e962ea15e..0a8931472 100644 --- a/code/ASEParser.h +++ b/code/ASEParser.h @@ -604,7 +604,7 @@ private: //! \param out Output string //! \param szName Name of the enclosing element -> used in error //! messages. - //! \return false if an error occured + //! \return false if an error occurred bool ParseString(std::string& out,const char* szName); public: diff --git a/code/BVHLoader.cpp b/code/BVHLoader.cpp index 1f4bc2e71..682ad2a9d 100644 --- a/code/BVHLoader.cpp +++ b/code/BVHLoader.cpp @@ -368,7 +368,7 @@ void BVHLoader::ReadMotion( aiScene* /*pScene*/) // Retrieves the next token std::string BVHLoader::GetNextToken() { - // skip any preceeding whitespace + // skip any preceding whitespace while( mReader != mBuffer.end()) { if( !isspace( *mReader)) diff --git a/code/BaseImporter.cpp b/code/BaseImporter.cpp index d58c30b2f..daed1c4ca 100644 --- a/code/BaseImporter.cpp +++ b/code/BaseImporter.cpp @@ -336,7 +336,7 @@ void BaseImporter::ConvertToUTF8(std::vector& data) // UTF 32 BE with BOM if(*((uint32_t*)&data.front()) == 0xFFFE0000) { - // swap the endianess .. + // swap the endianness .. for(uint32_t* p = (uint32_t*)&data.front(), *end = (uint32_t*)&data.back(); p <= end; ++p) { AI_SWAP4P(p); } @@ -367,7 +367,7 @@ void BaseImporter::ConvertToUTF8(std::vector& data) // UTF 16 BE with BOM if(*((uint16_t*)&data.front()) == 0xFFFE) { - // swap the endianess .. + // swap the endianness .. for(uint16_t* p = (uint16_t*)&data.front(), *end = (uint16_t*)&data.back(); p <= end; ++p) { ByteSwap::Swap2(p); } @@ -534,7 +534,7 @@ BatchLoader::~BatchLoader() delete (*it).scene; } - data->pImporter->SetIOHandler(NULL); /* get pointer back into our posession */ + data->pImporter->SetIOHandler(NULL); /* get pointer back into our possession */ delete data->pImporter; delete data; } diff --git a/code/BaseImporter.h b/code/BaseImporter.h index 75e1fdb00..2d47508f5 100644 --- a/code/BaseImporter.h +++ b/code/BaseImporter.h @@ -176,8 +176,8 @@ public: ); // ------------------------------------------------------------------- - /** Returns the error description of the last error that occured. - * @return A description of the last error that occured. An empty + /** Returns the error description of the last error that occurred. + * @return A description of the last error that occurred. An empty * string if there was no error. */ const std::string& GetErrorText() const { diff --git a/code/CSMLoader.cpp b/code/CSMLoader.cpp index 064c82dd2..34beeec09 100644 --- a/code/CSMLoader.cpp +++ b/code/CSMLoader.cpp @@ -227,7 +227,7 @@ void CSMImporter::InternReadFile( const std::string& pFile, // read x,y,z if(!SkipSpacesAndLineEnd(&buffer)) - throw DeadlyImportError("CSM: Unexpected EOF occured reading sample x coord"); + throw DeadlyImportError("CSM: Unexpected EOF occurred reading sample x coord"); if (TokenMatchI(buffer, "DROPOUT", 7)) { // seems this is invalid marker data; at least the doc says it's possible @@ -239,11 +239,11 @@ void CSMImporter::InternReadFile( const std::string& pFile, buffer = fast_atoreal_move(buffer, (float&)sub->mValue.x); if(!SkipSpacesAndLineEnd(&buffer)) - throw DeadlyImportError("CSM: Unexpected EOF occured reading sample y coord"); + throw DeadlyImportError("CSM: Unexpected EOF occurred reading sample y coord"); buffer = fast_atoreal_move(buffer, (float&)sub->mValue.y); if(!SkipSpacesAndLineEnd(&buffer)) - throw DeadlyImportError("CSM: Unexpected EOF occured reading sample z coord"); + throw DeadlyImportError("CSM: Unexpected EOF occurred reading sample z coord"); buffer = fast_atoreal_move(buffer, (float&)sub->mValue.z); ++s->mNumPositionKeys; diff --git a/code/ColladaExporter.cpp b/code/ColladaExporter.cpp index dcf82a564..c743606c7 100644 --- a/code/ColladaExporter.cpp +++ b/code/ColladaExporter.cpp @@ -872,7 +872,7 @@ void ColladaExporter::WriteGeometry( size_t pIndex) mOutput << startstr << "" << endstr; } - // triangle - dont use it, because compatibility problems + // triangle - don't use it, because compatibility problems // polygons if (countPoly) @@ -1041,7 +1041,7 @@ void ColladaExporter::WriteNode(aiNode* pNode) PushTag(); // write transformation - we can directly put the matrix there - // TODO: (thom) decompose into scale - rot - quad to allow adressing it by animations afterwards + // TODO: (thom) decompose into scale - rot - quad to allow addressing it by animations afterwards const aiMatrix4x4& mat = pNode->mTransformation; mOutput << startstr << ""; mOutput << mat.a1 << " " << mat.a2 << " " << mat.a3 << " " << mat.a4 << " "; diff --git a/code/ColladaLoader.cpp b/code/ColladaLoader.cpp index b10a5a248..e3a697929 100644 --- a/code/ColladaLoader.cpp +++ b/code/ColladaLoader.cpp @@ -663,7 +663,7 @@ aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada:: // joint vertex_weight name list - should refer to the same list as the joint names above. If not, report and reconsider const Collada::Accessor& weightNamesAcc = pParser.ResolveLibraryReference( pParser.mAccessorLibrary, pSrcController->mWeightInputJoints.mAccessor); if( &weightNamesAcc != &jointNamesAcc) - throw DeadlyImportError( "Temporary implementational lazyness. If you read this, please report to the author."); + throw DeadlyImportError( "Temporary implementational laziness. If you read this, please report to the author."); // vertex weights const Collada::Accessor& weightsAcc = pParser.ResolveLibraryReference( pParser.mAccessorLibrary, pSrcController->mWeightInputWeights.mAccessor); const Collada::Data& weights = pParser.ResolveLibraryReference( pParser.mDataLibrary, weightsAcc.mSource); @@ -1148,7 +1148,7 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars // Calculate resulting transformation aiMatrix4x4 mat = pParser.CalculateResultTransform( transforms); - // out of lazyness: we store the time in matrix.d4 + // out of laziness: we store the time in matrix.d4 mat.d4 = time; resultTrafos.push_back( mat); @@ -1294,7 +1294,7 @@ void ColladaLoader::AddTexture ( aiMaterial& mat, const ColladaParser& pParser, _AI_MATKEY_TEXBLEND_BASE, type, idx); // UV source index ... if we didn't resolve the mapping, it is actually just - // a guess but it works in most cases. We search for the frst occurence of a + // a guess but it works in most cases. We search for the frst occurrence of a // number in the channel name. We assume it is the zero-based index into the // UV channel array of all corresponding meshes. It could also be one-based // for some exporters, but we won't care of it unless someone complains about. diff --git a/code/ColladaParser.cpp b/code/ColladaParser.cpp index f620f7acb..bccac5f79 100644 --- a/code/ColladaParser.cpp +++ b/code/ColladaParser.cpp @@ -616,7 +616,7 @@ void ColladaParser::ReadControllerLibrary() { if( IsElement( "controller")) { - // read ID. Ask the spec if it's neccessary or optional... you might be surprised. + // read ID. Ask the spec if it's necessary or optional... you might be surprised. int attrID = GetAttribute( "id"); std::string id = mReader->getAttributeValue( attrID); @@ -2282,7 +2282,7 @@ size_t ColladaParser::ReadPrimitives( Mesh* pMesh, std::vector& pP if( expectedPointCount > 0) indices.reserve( expectedPointCount * numOffsets); - if (pNumPrimitives > 0) // It is possible to not contain any indicies + if (pNumPrimitives > 0) // It is possible to not contain any indices { const char* content = GetTextContent(); while( *content != 0) @@ -2317,7 +2317,7 @@ size_t ColladaParser::ReadPrimitives( Mesh* pMesh, std::vector& pP // find accessor input.mResolved = &ResolveLibraryReference( mAccessorLibrary, input.mAccessor); - // resolve accessor's data pointer as well, if neccessary + // resolve accessor's data pointer as well, if necessary const Accessor* acc = input.mResolved; if( !acc->mData) acc->mData = &ResolveLibraryReference( mDataLibrary, acc->mSource); @@ -2340,7 +2340,7 @@ size_t ColladaParser::ReadPrimitives( Mesh* pMesh, std::vector& pP // find accessor input.mResolved = &ResolveLibraryReference( mAccessorLibrary, input.mAccessor); - // resolve accessor's data pointer as well, if neccessary + // resolve accessor's data pointer as well, if necessary const Accessor* acc = input.mResolved; if( !acc->mData) acc->mData = &ResolveLibraryReference( mDataLibrary, acc->mSource); @@ -2876,7 +2876,7 @@ void ColladaParser::ReadScene() if( mReader->getNodeType() == irr::io::EXN_ELEMENT) { if( IsElement( "instance_visual_scene")) { - // should be the first and only occurence + // should be the first and only occurrence if( mRootNode) ThrowException( "Invalid scene containing multiple root nodes in element"); diff --git a/code/DXFLoader.cpp b/code/DXFLoader.cpp index 2f0f944e8..f21ea15fb 100644 --- a/code/DXFLoader.cpp +++ b/code/DXFLoader.cpp @@ -175,7 +175,7 @@ void DXFImporter::InternReadFile( const std::string& pFile, } // skip unneeded sections entirely to avoid any problems with them - // alltogether. + // altogether. else if (reader.Is(2,"CLASSES") || reader.Is(2,"TABLES")) { SkipSection(reader); continue; diff --git a/code/FBXBinaryTokenizer.cpp b/code/FBXBinaryTokenizer.cpp index fdb5c28df..aaa63d4aa 100644 --- a/code/FBXBinaryTokenizer.cpp +++ b/code/FBXBinaryTokenizer.cpp @@ -191,7 +191,7 @@ void ReadData(const char*& sbegin_out, const char*& send_out, const char* input, // 32 bit int case 'I': - // <- fall thru + // <- fall through // float case 'F': diff --git a/code/FBXMeshGeometry.cpp b/code/FBXMeshGeometry.cpp index 49bdca92a..5b60e4623 100644 --- a/code/FBXMeshGeometry.cpp +++ b/code/FBXMeshGeometry.cpp @@ -354,7 +354,7 @@ void MeshGeometry::ReadVertexData(const std::string& type, int index, const Scop // sometimes, there will be only negative entries. Drop the material // layer in such a case (I guess it means a default material should // be used). This is what the converter would do anyway, and it - // avoids loosing the material if there are more material layers + // avoids losing the material if there are more material layers // coming of which at least one contains actual data (did observe // that with one test file). const size_t count_neg = std::count_if(temp_materials.begin(),temp_materials.end(),std::bind2nd(std::less(),0)); diff --git a/code/FBXUtil.h b/code/FBXUtil.h index 331a769ff..bd41834b0 100644 --- a/code/FBXUtil.h +++ b/code/FBXUtil.h @@ -74,7 +74,7 @@ const char* TokenTypeString(TokenType t); * @param prefix Message prefix to be preprended to the location info. * @param text Message text * @param line Line index, 1-based - * @param column Colum index, 1-based + * @param column Column index, 1-based * @return A string of the following format: {prefix} (offset 0x{offset}) {text}*/ std::string AddOffset(const std::string& prefix, const std::string& text, unsigned int offset); @@ -84,7 +84,7 @@ std::string AddOffset(const std::string& prefix, const std::string& text, unsign * @param prefix Message prefix to be preprended to the location info. * @param text Message text * @param line Line index, 1-based - * @param column Colum index, 1-based + * @param column Column index, 1-based * @return A string of the following format: {prefix} (line {line}, col {column}) {text}*/ std::string AddLineAndColumn(const std::string& prefix, const std::string& text, unsigned int line, unsigned int column); diff --git a/code/FileSystemFilter.h b/code/FileSystemFilter.h index fecdaab82..3370589d6 100644 --- a/code/FileSystemFilter.h +++ b/code/FileSystemFilter.h @@ -40,7 +40,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /** @file FileSystemFilter.h * Implements a filter system to filter calls to Exists() and Open() - * in order to improve the sucess rate of file opening ... + * in order to improve the success rate of file opening ... */ #ifndef AI_FILESYSTEMFILTER_H_INC #define AI_FILESYSTEMFILTER_H_INC diff --git a/code/Importer.cpp b/code/Importer.cpp index b7a4cb555..faf0924a0 100644 --- a/code/Importer.cpp +++ b/code/Importer.cpp @@ -604,7 +604,7 @@ const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags) FreeScene(); } - // First check if the file is accessable at all + // First check if the file is accessible at all if( !pimpl->mIOHandler->Exists( pFile)) { pimpl->mErrorString = "Unable to open file \"" + pFile + "\"."; @@ -723,7 +723,7 @@ const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags) catch (std::exception &e) { #if (defined _MSC_VER) && (defined _CPPRTTI) - // if we have RTTI get the full name of the exception that occured + // if we have RTTI get the full name of the exception that occurred pimpl->mErrorString = std::string(typeid( e ).name()) + ": " + e.what(); #else pimpl->mErrorString = std::string("std::exception: ") + e.what(); diff --git a/code/Importer.h b/code/Importer.h index 7e21327ce..bb1050c56 100644 --- a/code/Importer.h +++ b/code/Importer.h @@ -166,7 +166,7 @@ public: // ------------------------------------------------------------------- /** Construct a batch loader from a given IO system to be used - * to acess external files */ + * to access external files */ explicit BatchLoader(IOSystem* pIO); ~BatchLoader(); diff --git a/code/JoinVerticesProcess.cpp b/code/JoinVerticesProcess.cpp index b822b527c..9cd34e1d0 100644 --- a/code/JoinVerticesProcess.cpp +++ b/code/JoinVerticesProcess.cpp @@ -192,8 +192,8 @@ int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex) // Position mismatch is impossible - the vertex finder already discarded all non-matching positions // We just test the other attributes even if they're not present in the mesh. - // In this case they're initialized to 0 so the comparision succeeds. - // By this method the non-present attributes are effectively ignored in the comparision. + // In this case they're initialized to 0 so the comparison succeeds. + // By this method the non-present attributes are effectively ignored in the comparison. if( (uv.normal - v.normal).SquareLength() > squareEpsilon) continue; if( (uv.texcoords[0] - v.texcoords[0]).SquareLength() > squareEpsilon) @@ -265,7 +265,7 @@ int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex) } else { - // no unique vertex matches it upto now -> so add it + // no unique vertex matches it up to now -> so add it replaceIndex[a] = (unsigned int)uniqueVertices.size(); uniqueVertices.push_back( v); } diff --git a/code/LWOBLoader.cpp b/code/LWOBLoader.cpp index 5f2519d8d..639675294 100644 --- a/code/LWOBLoader.cpp +++ b/code/LWOBLoader.cpp @@ -112,7 +112,7 @@ void LWOImporter::LoadLWOBPolygons(unsigned int length) LE_NCONST uint16_t* const end = (LE_NCONST uint16_t*)(mFileBuffer+length); LE_NCONST uint16_t* cursor = (LE_NCONST uint16_t*)mFileBuffer; - // perform endianess conversions + // perform endianness conversions #ifndef AI_BUILD_BIG_ENDIAN while (cursor < end)ByteSwap::Swap2(cursor++); cursor = (LE_NCONST uint16_t*)mFileBuffer; @@ -256,8 +256,8 @@ void LWOImporter::LoadLWOBSurface(unsigned int size) LWO::Texture* pTex = NULL; GetS0(surf.mName,size); - bool runnning = true; - while (runnning) { + bool running = true; + while (running) { if (mFileBuffer + 6 >= end) break; diff --git a/code/LWOLoader.cpp b/code/LWOLoader.cpp index 86846cf62..53b6b14fb 100644 --- a/code/LWOLoader.cpp +++ b/code/LWOLoader.cpp @@ -765,7 +765,7 @@ void LWOImporter::LoadLWOPoints(unsigned int length) } else mCurLayer->mTempPoints.resize( regularSize ); - // perform endianess conversions + // perform endianness conversions #ifndef AI_BUILD_BIG_ENDIAN for (unsigned int i = 0; i < length>>2;++i) ByteSwap::Swap4( mFileBuffer + (i << 2)); diff --git a/code/LimitBoneWeightsProcess.h b/code/LimitBoneWeightsProcess.h index 2f07bfeba..f6907cf26 100644 --- a/code/LimitBoneWeightsProcess.h +++ b/code/LimitBoneWeightsProcess.h @@ -125,7 +125,7 @@ public: mWeight = pWeight; } - /** Comparision operator to sort bone weights by descending weight */ + /** Comparison operator to sort bone weights by descending weight */ bool operator < (const Weight& pWeight) const { return mWeight > pWeight.mWeight; diff --git a/code/MD3FileData.h b/code/MD3FileData.h index 97043bc11..57dbf990b 100644 --- a/code/MD3FileData.h +++ b/code/MD3FileData.h @@ -305,7 +305,7 @@ inline void Vec3NormalToLatLng( const aiVector3D& p_vIn, uint16_t& p_iOut ) b &= 0xff; ((unsigned char*)&p_iOut)[0] = b; // longitude - ((unsigned char*)&p_iOut)[1] = a; // lattitude + ((unsigned char*)&p_iOut)[1] = a; // latitude } } diff --git a/code/MD3Loader.cpp b/code/MD3Loader.cpp index c8b58f593..7f1b32577 100644 --- a/code/MD3Loader.cpp +++ b/code/MD3Loader.cpp @@ -763,7 +763,7 @@ void MD3Importer::InternReadFile( const std::string& pFile, pcHeader = (BE_NCONST MD3::Header*)mBuffer; - // Ensure correct endianess + // Ensure correct endianness #ifdef AI_BUILD_BIG_ENDIAN AI_SWAP4(pcHeader->VERSION); @@ -832,7 +832,7 @@ void MD3Importer::InternReadFile( const std::string& pFile, unsigned int iNumMaterials = 0; while (iNum-- > 0) { - // Ensure correct endianess + // Ensure correct endianness #ifdef AI_BUILD_BIG_ENDIAN AI_SWAP4(pcSurfaces->FLAGS); @@ -965,7 +965,7 @@ void MD3Importer::InternReadFile( const std::string& pFile, pScene->mMaterials[iNumMaterials] = (aiMaterial*)pcHelper; pcMesh->mMaterialIndex = iNumMaterials++; - // Ensure correct endianess + // Ensure correct endianness #ifdef AI_BUILD_BIG_ENDIAN for (uint32_t i = 0; i < pcSurfaces->NUM_VERTICES;++i) { diff --git a/code/MD5Parser.cpp b/code/MD5Parser.cpp index 101c52d1d..cf8d5a9f5 100644 --- a/code/MD5Parser.cpp +++ b/code/MD5Parser.cpp @@ -406,7 +406,7 @@ MD5AnimParser::MD5AnimParser(SectionList& mSections) desc.mValues.reserve(mNumAnimatedComponents); } - // now read all elements (continous list of floats) + // now read all elements (continuous list of floats) for (ElementList::const_iterator eit = (*iter).mElements.begin(), eitEnd = (*iter).mElements.end(); eit != eitEnd; ++eit){ const char* sz = (*eit).szStart; while (SkipSpacesAndLineEnd(&sz)) { diff --git a/code/MD5Parser.h b/code/MD5Parser.h index bbc844d57..5d5e608bb 100644 --- a/code/MD5Parser.h +++ b/code/MD5Parser.h @@ -370,14 +370,14 @@ public: // ------------------------------------------------------------------- /** Report a specific error message and throw an exception * @param error Error message to be reported - * @param line Index of the line where the error occured + * @param line Index of the line where the error occurred */ AI_WONT_RETURN static void ReportError (const char* error, unsigned int line) AI_WONT_RETURN_SUFFIX; // ------------------------------------------------------------------- /** Report a specific warning * @param warn Warn message to be reported - * @param line Index of the line where the error occured + * @param line Index of the line where the error occurred */ static void ReportWarning (const char* warn, unsigned int line); diff --git a/code/MDLLoader.cpp b/code/MDLLoader.cpp index 50373f401..079731043 100644 --- a/code/MDLLoader.cpp +++ b/code/MDLLoader.cpp @@ -1290,7 +1290,7 @@ void MDLImporter::SortByMaterials_3DGS_MDL7( iMatIndex2 = iNumMaterials-1; } - // do a slow seach in the list ... + // do a slow search in the list ... iNum = 0; bool bFound = false; for (std::vector::iterator i = avMats.begin();i != avMats.end();++i,++iNum){ diff --git a/code/MDLMaterialLoader.cpp b/code/MDLMaterialLoader.cpp index 455f1e6d0..2499eae64 100644 --- a/code/MDLMaterialLoader.cpp +++ b/code/MDLMaterialLoader.cpp @@ -60,7 +60,7 @@ using namespace Assimp; static aiTexel* const bad_texel = reinterpret_cast(SIZE_MAX); // ------------------------------------------------------------------------------------------------ -// Find a suitable pallette file or take teh default one +// Find a suitable pallette file or take the default one void MDLImporter::SearchPalette(const unsigned char** pszColorMap) { // now try to find the color map in the current directory @@ -129,7 +129,7 @@ aiColor4D MDLImporter::ReplaceTextureWithColor(const aiTexture* pcTexture) // Read a texture from a MDL3 file void MDLImporter::CreateTextureARGB8_3DGS_MDL3(const unsigned char* szData) { - const MDL::Header *pcHeader = (const MDL::Header*)mBuffer; //the endianess is allready corrected in the InternReadFile_3DGS_MDL345 function + const MDL::Header *pcHeader = (const MDL::Header*)mBuffer; //the endianness is already corrected in the InternReadFile_3DGS_MDL345 function VALIDATE_FILE_SIZE(szData + pcHeader->skinwidth * pcHeader->skinheight); @@ -178,7 +178,7 @@ void MDLImporter::CreateTexture_3DGS_MDL4(const unsigned char* szData, { ai_assert(NULL != piSkip); - const MDL::Header *pcHeader = (const MDL::Header*)mBuffer; //the endianess is allready corrected in the InternReadFile_3DGS_MDL345 function + const MDL::Header *pcHeader = (const MDL::Header*)mBuffer; //the endianness is already corrected in the InternReadFile_3DGS_MDL345 function if (iType == 1 || iType > 3) { diff --git a/code/NDOLoader.cpp b/code/NDOLoader.cpp index 36cc2323b..08a151717 100644 --- a/code/NDOLoader.cpp +++ b/code/NDOLoader.cpp @@ -262,7 +262,7 @@ void NDOImporter::InternReadFile( const std::string& pFile, aiFace* faces = mesh->mFaces = new aiFace[mesh->mNumFaces=face_table.size()]; vertices.clear(); - vertices.reserve(4 * face_table.size()); // arbitrarily choosen + vertices.reserve(4 * face_table.size()); // arbitrarily chosen for_each(FaceTable::value_type& v, face_table) { indices.clear(); diff --git a/code/PlyParser.cpp b/code/PlyParser.cpp index 5b6a35e5f..9ea727915 100644 --- a/code/PlyParser.cpp +++ b/code/PlyParser.cpp @@ -388,7 +388,7 @@ bool PLY::Element::ParseElement (const char* pCur, if (!SkipSpaces(&pCur))return false; - //parse the number of occurences of this element + //parse the number of occurrences of this element pOut->NumOccur = strtoul10(pCur,&pCur); // go to the next line @@ -854,7 +854,7 @@ bool PLY::PropertyInstance::ParseValueBinary( out->iUInt = (uint32_t)*((uint32_t*)pCur); pCur += 4; - // Swap endianess + // Swap endianness if (p_bBE)ByteSwap::Swap((int32_t*)&out->iUInt); break; @@ -862,7 +862,7 @@ bool PLY::PropertyInstance::ParseValueBinary( { uint16_t i = *((uint16_t*)pCur); - // Swap endianess + // Swap endianness if (p_bBE)ByteSwap::Swap(&i); out->iUInt = (uint32_t)i; pCur += 2; @@ -880,7 +880,7 @@ bool PLY::PropertyInstance::ParseValueBinary( out->iInt = *((int32_t*)pCur); pCur += 4; - // Swap endianess + // Swap endianness if (p_bBE)ByteSwap::Swap(&out->iInt); break; @@ -888,7 +888,7 @@ bool PLY::PropertyInstance::ParseValueBinary( { int16_t i = *((int16_t*)pCur); - // Swap endianess + // Swap endianness if (p_bBE)ByteSwap::Swap(&i); out->iInt = (int32_t)i; pCur += 2; @@ -904,7 +904,7 @@ bool PLY::PropertyInstance::ParseValueBinary( { out->fFloat = *((float*)pCur); - // Swap endianess + // Swap endianness if (p_bBE)ByteSwap::Swap((int32_t*)&out->fFloat); pCur += 4; break; @@ -913,7 +913,7 @@ bool PLY::PropertyInstance::ParseValueBinary( { out->fDouble = *((double*)pCur); - // Swap endianess + // Swap endianness if (p_bBE)ByteSwap::Swap((int64_t*)&out->fDouble); pCur += 8; break; diff --git a/code/SMDLoader.h b/code/SMDLoader.h index 14155674a..ab6ab3d9a 100644 --- a/code/SMDLoader.h +++ b/code/SMDLoader.h @@ -39,7 +39,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** @file SMDLoader.h - * @brief Defintion of the Valve SMD file format + * @brief Definition of the Valve SMD file format */ #ifndef AI_SMDLOADER_H_INCLUDED diff --git a/code/STLLoader.cpp b/code/STLLoader.cpp index 8c8dbfc2e..28645ac58 100644 --- a/code/STLLoader.cpp +++ b/code/STLLoader.cpp @@ -406,7 +406,7 @@ bool STLImporter::LoadBinaryFile() } bool bIsMaterialise = false; - // search for an occurence of "COLOR=" in the header + // search for an occurrence of "COLOR=" in the header const unsigned char* sz2 = (const unsigned char*)mBuffer; const unsigned char* const szEnd = sz2+80; while (sz2 < szEnd) { diff --git a/code/SceneCombiner.h b/code/SceneCombiner.h index fe73ad4f5..ddb4e8f7d 100644 --- a/code/SceneCombiner.h +++ b/code/SceneCombiner.h @@ -273,7 +273,7 @@ public: /** Merges two or more materials * * The materials should be complementary as much as possible. In case - * of a property present in different materials, the first occurence + * of a property present in different materials, the first occurrence * is used. * * @param dest Destination material. Must be empty. @@ -323,7 +323,7 @@ public: * the master graph), a scene is attached to the root of the master * graph (as an additional child node) * @duplicates List of duplicates. If elem[n] == n the scene is not - * a duplicate. Otherwise elem[n] links scene n to its first occurence. + * a duplicate. Otherwise elem[n] links scene n to its first occurrence. */ static void AttachToGraph ( aiScene* master, std::vector& srcList); diff --git a/code/SpatialSort.cpp b/code/SpatialSort.cpp index 2cf179a92..c536af1b5 100644 --- a/code/SpatialSort.cpp +++ b/code/SpatialSort.cpp @@ -234,7 +234,7 @@ namespace { } // namespace // ------------------------------------------------------------------------------------------------ -// Fills an array with indices of all positions indentical to the given position. In opposite to +// Fills an array with indices of all positions identical to the given position. In opposite to // FindPositions(), not an epsilon is used but a (very low) tolerance of four floating-point units. void SpatialSort::FindIdenticalPositions( const aiVector3D& pPosition, std::vector& poResults) const diff --git a/code/SpatialSort.h b/code/SpatialSort.h index e4fb4a0c3..983a26c4b 100644 --- a/code/SpatialSort.h +++ b/code/SpatialSort.h @@ -121,7 +121,7 @@ public: std::vector& poResults) const; // ------------------------------------------------------------------------------------ - /** Fills an array with indices of all positions indentical to the given position. In + /** Fills an array with indices of all positions identical to the given position. In * opposite to FindPositions(), not an epsilon is used but a (very low) tolerance of * four floating-point units. * @param pPosition The position to look for vertices. diff --git a/code/StandardShapes.h b/code/StandardShapes.h index 211422c5d..e310bfd5e 100644 --- a/code/StandardShapes.h +++ b/code/StandardShapes.h @@ -182,7 +182,7 @@ public: // ---------------------------------------------------------------- /** @brief Generates a flat circle * - * The circle is constructed in the planed formed by the x,z + * The circle is constructed in the planned formed by the x,z * axes of the cartesian coordinate system. * * @param radius Radius of the circle diff --git a/code/StreamReader.h b/code/StreamReader.h index c7acf0af8..0d411e884 100644 --- a/code/StreamReader.h +++ b/code/StreamReader.h @@ -40,7 +40,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** @file Defines the StreamReader class which reads data from - * a binary stream with a well-defined endianess. */ + * a binary stream with a well-defined endianness. */ #ifndef AI_STREAMREADER_H_INCLUDED #define AI_STREAMREADER_H_INCLUDED @@ -57,9 +57,9 @@ namespace Assimp { /** Wrapper class around IOStream to allow for consistent reading of binary data in both * little and big endian format. Don't attempt to instance the template directly. Use * StreamReaderLE to read from a little-endian stream and StreamReaderBE to read from a - * BE stream. The class expects that the endianess of any input data is known at + * BE stream. The class expects that the endianness of any input data is known at * compile-time, which should usually be true (#BaseImporter::ConvertToUTF8 implements - * runtime endianess conversions for text files). + * runtime endianness conversions for text files). * * XXX switch from unsigned int for size types to size_t? or ptrdiff_t?*/ // -------------------------------------------------------------------------------------------- @@ -79,7 +79,7 @@ public: // --------------------------------------------------------------------- - /** Construction from a given stream with a well-defined endianess. + /** Construction from a given stream with a well-defined endianness. * * The StreamReader holds a permanent strong reference to the * stream, which is released upon destruction. @@ -88,7 +88,7 @@ public: * reads from the current position to the end of the stream. * @param le If @c RuntimeSwitch is true: specifies whether the * stream is in little endian byte order. Otherwise the - * endianess information is contained in the @c SwapEndianess + * endianness information is contained in the @c SwapEndianess * template parameter and this parameter is meaningless. */ StreamReader(boost::shared_ptr stream, bool le = false) : stream(stream) diff --git a/code/StreamWriter.h b/code/StreamWriter.h index f25736171..9f5c09cec 100644 --- a/code/StreamWriter.h +++ b/code/StreamWriter.h @@ -40,7 +40,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** @file Defines the StreamWriter class which writes data to - * a binary stream with a well-defined endianess. */ + * a binary stream with a well-defined endianness. */ #ifndef AI_STREAMWRITER_H_INCLUDED #define AI_STREAMWRITER_H_INCLUDED @@ -57,7 +57,7 @@ namespace Assimp { /** Wrapper class around IOStream to allow for consistent writing of binary data in both * little and big endian format. Don't attempt to instance the template directly. Use * StreamWriterLE to read from a little-endian stream and StreamWriterBE to read from a - * BE stream. Alternatively, there is StreamWriterAny if the endianess of the output + * BE stream. Alternatively, there is StreamWriterAny if the endianness of the output * stream is to be determined at runtime. */ // -------------------------------------------------------------------------------------------- @@ -71,7 +71,7 @@ class StreamWriter public: // --------------------------------------------------------------------- - /** Construction from a given stream with a well-defined endianess. + /** Construction from a given stream with a well-defined endianness. * * The StreamReader holds a permanent strong reference to the * stream, which is released upon destruction. @@ -79,7 +79,7 @@ public: continues at the current position of the stream cursor. * @param le If @c RuntimeSwitch is true: specifies whether the * stream is in little endian byte order. Otherwise the - * endianess information is defined by the @c SwapEndianess + * endianness information is defined by the @c SwapEndianess * template parameter and this parameter is meaningless. */ StreamWriter(boost::shared_ptr stream, bool le = false) : stream(stream) diff --git a/code/TerragenLoader.cpp b/code/TerragenLoader.cpp index 4e711fc5e..b0e450d41 100644 --- a/code/TerragenLoader.cpp +++ b/code/TerragenLoader.cpp @@ -126,7 +126,7 @@ void TerragenImporter::InternReadFile( const std::string& pFile, if( file == NULL) throw DeadlyImportError( "Failed to open TERRAGEN TERRAIN file " + pFile + "."); - // Construct a stream reader to read all data in the correct endianess + // Construct a stream reader to read all data in the correct endianness StreamReaderLE reader(file); if(reader.GetRemainingSize() < 16) throw DeadlyImportError( "TER: file is too small" ); diff --git a/code/TextureTransform.cpp b/code/TextureTransform.cpp index 9436c773a..948ec013b 100644 --- a/code/TextureTransform.cpp +++ b/code/TextureTransform.cpp @@ -554,7 +554,7 @@ void TextureTransformStep::Execute( aiScene* pScene) } } - // Print some detailled statistics into the log + // Print some detailed statistics into the log if (!DefaultLogger::isNullLogger()) { if (transformedChannels) { diff --git a/code/XFileImporter.cpp b/code/XFileImporter.cpp index b63ac4a1d..e39ea658c 100644 --- a/code/XFileImporter.cpp +++ b/code/XFileImporter.cpp @@ -668,7 +668,7 @@ void XFileImporter::ConvertMaterials( aiScene* pScene, std::vectormChildren.size() == 1 && pNode->mMeshes.empty() ) { diff --git a/doc/dox.h b/doc/dox.h index cd9214453..1e36749bb 100644 --- a/doc/dox.h +++ b/doc/dox.h @@ -98,7 +98,7 @@ more work. Both ways are described at the @link install Installation page. @endl When you're done integrating the library into your IDE / project, you can now start using it. There are two separate interfaces by which you can access the library: a C++ interface and a C interface using flat functions. While the former -is easier to handle, the latter also forms a point where other programming languages can connect to. Upto the moment, though, +is easier to handle, the latter also forms a point where other programming languages can connect to. Up to the moment, though, there are no bindings for any other language provided. Have a look at the @link usage Usage page @endlink for a detailed explanation and code examples. @section main_data Data Structures @@ -137,7 +137,7 @@ If you develop at Visual Studio 2005 or 2008, you can simply use the pre-built l Extract all files to a place of your choice. A directory called "assimp" will be created there. Add the assimp/include path to your include paths (Menu->Extras->Options->Projects and Solutions->VC++ Directories->Include files) and the assimp/lib/<Compiler> path to your linker paths (Menu->Extras->Options->Projects and Solutions->VC++ Directories->Library files). -This is neccessary only once to setup all paths inside you IDE. +This is necessary only once to setup all paths inside you IDE. To use the library in your C++ project you have to include either <assimp/Importer.hpp> or <assimp/cimport.h> plus some others starting with <types.h>. If you set up your IDE correctly the compiler should be able to find the files. Then you have to add the linker library to your @@ -310,7 +310,7 @@ bool DoTheImportThing( const std::string& pFile) @endcode What exactly is read from the files and how you interpret it is described at the @ref data page. @endlink The post processing steps that the assimp library can apply to the -imported data are listed at #aiPostProcessSteps. See the @ref pp Post proccessing page for more details. +imported data are listed at #aiPostProcessSteps. See the @ref pp Post processing page for more details. Note that the aiScene data structure returned is declared 'const'. Yes, you can get rid of these 5 letters with a simple cast. Yes, you may do that. No, it's not recommended (and it's @@ -660,7 +660,7 @@ an index into this array. An aiMesh is defined by a series of data channels. The presence of these data channels is defined by the contents of the imported file: by default there are only those data channels present in the mesh -that were also found in the file. The only channels guarenteed to be always present are aiMesh::mVertices +that were also found in the file. The only channels guaranteed to be always present are aiMesh::mVertices and aiMesh::mFaces. You can test for the presence of other data by testing the pointers against NULL or use the helper functions provided by aiMesh. You may also specify several post processing flags at Importer::ReadFile() to let assimp calculate or recalculate additional data channels for you. @@ -753,7 +753,7 @@ both Direct3D and OpenGL (swizzling the order of the color components might be n RGBA8888 has been chosen because it is well-known, easy to use and natively supported by nearly all graphics APIs.
-2) This applies if aiTexture::mHeight == 0 is fullfilled. Then, texture is stored in a +2) This applies if aiTexture::mHeight == 0 is fulfilled. Then, texture is stored in a "compressed" format such as DDS or PNG. The term "compressed" does not mean that the texture data must actually be compressed, however the texture was found in the model file as if it was stored in a separate file on the harddisk. Appropriate @@ -780,7 +780,7 @@ presence of certain properties in a material and retrieve their values. @section mat_tex Textures -Textures are organized in stacks, each stack being evaluated independently. The final color value from a particular texture stack is used in the shading equation. For example, the computed color value of the diffuse texture stack (aiTextureType_DIFFUSE) is multipled with the amount of incoming diffuse light to obtain the final diffuse color of a pixel. +Textures are organized in stacks, each stack being evaluated independently. The final color value from a particular texture stack is used in the shading equation. For example, the computed color value of the diffuse texture stack (aiTextureType_DIFFUSE) is multiplied with the amount of incoming diffuse light to obtain the final diffuse color of a pixel. @code @@ -938,7 +938,7 @@ All material key constants start with 'AI_MATKEY' (it's an ugly macro for histor TEXBLEND(t,n) float n/a - Defines the strength the n'th texture on the stack 't'. All color components (rgb) are multipled with this factor *before* any further processing is done. + Defines the strength the n'th texture on the stack 't'. All color components (rgb) are multiplied with this factor *before* any further processing is done. - @@ -1466,7 +1466,7 @@ The skeleton file must have the same name as the mesh file, e.g. fish.mesh.xml a The material file can have the same name as the mesh file (if the file is model.mesh or model.mesh.xml the loader will try to load model.material), or you can use Importer::Importer::SetPropertyString(AI_CONFIG_IMPORT_OGRE_MATERIAL_FILE, "materiafile.material") -to specify the name of the material file. This is especially usefull if multiply materials a stored in a single file. +to specify the name of the material file. This is especially useful if multiply materials a stored in a single file. The importer will first try to load the material with the same name as the mesh and only if this can't be open try to load the alternate material file. The default material filename is "Scene.material". @@ -1574,7 +1574,7 @@ But the general rule of thumb is be strict in what you write and tolerant in
  • -Take care of endianess issues! Assimp importers mostly support big-endian platforms, which define the AI_BUILD_BIG_ENDIAN constant. +Take care of endianness issues! Assimp importers mostly support big-endian platforms, which define the AI_BUILD_BIG_ENDIAN constant. See the next section for a list of utilities to simplify this task.
  • diff --git a/include/assimp/Compiler/pstdint.h b/include/assimp/Compiler/pstdint.h index 3692a8aef..22b6c235e 100644 --- a/include/assimp/Compiler/pstdint.h +++ b/include/assimp/Compiler/pstdint.h @@ -73,7 +73,7 @@ * include stdint.h. The hope is that one or the other can be * used with no real difference. * - * 5) In the current verison, if your platform can't represent + * 5) In the current version, if your platform can't represent * int32_t, int16_t and int8_t, it just dumps out with a compiler * error. * diff --git a/include/assimp/Importer.hpp b/include/assimp/Importer.hpp index 10c62e55d..4c01367ed 100644 --- a/include/assimp/Importer.hpp +++ b/include/assimp/Importer.hpp @@ -464,7 +464,7 @@ public: /** @brief Reads the given file and returns its contents if successful. * * This function is provided for backward compatibility. - * See the const char* version for detailled docs. + * See the const char* version for detailed docs. * @see ReadFile(const char*, pFlags) */ const aiScene* ReadFile( const std::string& pFile, diff --git a/include/assimp/anim.h b/include/assimp/anim.h index 0acb84532..af5941755 100644 --- a/include/assimp/anim.h +++ b/include/assimp/anim.h @@ -409,7 +409,7 @@ namespace Assimp { // --------------------------------------------------------------------------- /** @brief CPP-API: Utility class to simplify interpolations of various data types. * - * The type of interpolation is choosen automatically depending on the + * The type of interpolation is chosen automatically depending on the * types of the arguments. */ template struct Interpolator diff --git a/include/assimp/material.h b/include/assimp/material.h index 6c222a040..87d27c569 100644 --- a/include/assimp/material.h +++ b/include/assimp/material.h @@ -103,7 +103,7 @@ enum aiTextureOp // --------------------------------------------------------------------------- /** @brief Defines how UV coordinates outside the [0...1] range are handled. * - * Commonly refered to as 'wrapping mode'. + * Commonly referred to as 'wrapping mode'. */ enum aiTextureMapMode { diff --git a/include/assimp/mesh.h b/include/assimp/mesh.h index f112bea0f..a76a2d72b 100644 --- a/include/assimp/mesh.h +++ b/include/assimp/mesh.h @@ -522,7 +522,7 @@ struct aiMesh * mixed primitive types (i.e. lines and triangles) may have * normals, but the normals for vertices that are only referenced by * point or line primitives are undefined and set to qNaN. See - * the #mNormals member for a detailled discussion of qNaNs. + * the #mNormals member for a detailed discussion of qNaNs. * @note If the mesh contains tangents, it automatically also * contains bitangents. */ diff --git a/include/assimp/port/AndroidJNI/AndroidJNIIOSystem.h b/include/assimp/port/AndroidJNI/AndroidJNIIOSystem.h index 727aaa7c6..6f806f922 100644 --- a/include/assimp/port/AndroidJNI/AndroidJNIIOSystem.h +++ b/include/assimp/port/AndroidJNI/AndroidJNIIOSystem.h @@ -39,7 +39,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** @file Android implementation of IOSystem using the standard C file functions. - * Aimed to ease the acces to android assets */ + * Aimed to ease the access to android assets */ #if __ANDROID__ and __ANDROID_API__ > 9 and defined(AI_CONFIG_ANDROID_JNI_ASSIMP_MANAGER_SUPPORT) #ifndef AI_ANDROIDJNIIOSYSTEM_H_INC diff --git a/port/PyAssimp/pyassimp/errors.py b/port/PyAssimp/pyassimp/errors.py index 37db3c08a..9d776860f 100644 --- a/port/PyAssimp/pyassimp/errors.py +++ b/port/PyAssimp/pyassimp/errors.py @@ -6,6 +6,6 @@ All possible errors. class AssimpError(BaseException): """ - If an internal error occures. + If an internal error occurs. """ pass \ No newline at end of file diff --git a/port/PyAssimp/pyassimp/structs.py b/port/PyAssimp/pyassimp/structs.py index 39ed8267a..84fcfb7a0 100644 --- a/port/PyAssimp/pyassimp/structs.py +++ b/port/PyAssimp/pyassimp/structs.py @@ -568,7 +568,7 @@ class Mesh(Structure): # normals, but the normals for vertices that are only referenced by # point or line primitives are undefined and set to qNaN. See # the - #mNormals member for a detailled discussion of qNaNs. + #mNormals member for a detailed discussion of qNaNs. # @note If the mesh contains tangents, it automatically also # contains bitangents (the bitangent is just the cross product of # tangent and normal vectors). diff --git a/port/dAssimp/assimp/api.d b/port/dAssimp/assimp/api.d index fcdec1d29..9399b7f9d 100644 --- a/port/dAssimp/assimp/api.d +++ b/port/dAssimp/assimp/api.d @@ -607,7 +607,7 @@ extern ( C ) { * aiGetMaterialTextureCount() can be used to determine * the number of textures in a particular texture stack. * path = Receives the output path. null is not a valid value. - * mapping = Recieves the texture mapping mode to be used. + * mapping = Receives the texture mapping mode to be used. * Pass null if you are not interested in this information. * uvindex = For UV-mapped textures: receives the index of the UV source * channel. Unmodified otherwise. Pass null if you are not interested diff --git a/port/dAssimp/assimp/material.d b/port/dAssimp/assimp/material.d index b5af27eae..e0c480b24 100644 --- a/port/dAssimp/assimp/material.d +++ b/port/dAssimp/assimp/material.d @@ -110,7 +110,7 @@ extern ( C ) { * Defines how UV coordinates outside the [0..1] range are * handled. * - * Commonly refered to as 'wrapping mode'. + * Commonly referred to as 'wrapping mode'. */ enum aiTextureMapMode : uint { /** diff --git a/port/dAssimp/assimp/math.d b/port/dAssimp/assimp/math.d index f63d8e23a..f3cff743f 100644 --- a/port/dAssimp/assimp/math.d +++ b/port/dAssimp/assimp/math.d @@ -71,7 +71,7 @@ extern( C ) { /** * Represents a row-major 3x3 matrix * - * There is much confusion about matrix layouts (colum vs. row order). This + * There is much confusion about matrix layouts (column vs. row order). This * is always a row-major matrix, even when using the * ConvertToLeftHanded post processing step. */ @@ -84,7 +84,7 @@ extern( C ) { /** * Represents a row-major 3x3 matrix * - * There is much confusion about matrix layouts (colum vs. row order). This + * There is much confusion about matrix layouts (column vs. row order). This * is always a row-major matrix, even when using the * ConvertToLeftHanded post processing step. */ diff --git a/port/dAssimp/assimp/mesh.d b/port/dAssimp/assimp/mesh.d index 1618f31fc..9f20c9a66 100644 --- a/port/dAssimp/assimp/mesh.d +++ b/port/dAssimp/assimp/mesh.d @@ -115,7 +115,7 @@ extern ( C ) { uint mNumIndices; /** - * Array of the indicies defining the face. + * Array of the indices defining the face. * * The size is given in mNumIndices. */ @@ -205,7 +205,7 @@ extern ( C ) { * * A triangle is a polygon, but in this context, polygon means * "all polygons that are not triangles". The Triangulate - * post processing step is provided for your convinience, it splits all + * post processing step is provided for your convenience, it splits all * polygons in triangles (which are much easier to handle). */ POLYGON = 0x8 @@ -403,7 +403,7 @@ extern ( C ) { /** * The faces the mesh is contstructed from. * - * Each face referrs to a number of vertices by their indices. + * Each face refers to a number of vertices by their indices. * This array is always present in a mesh, its size is given * in mNumFaces. If the * AI_SCENE_FLAGS_NON_VERBOSE_FORMAT is not set, diff --git a/port/jassimp/jassimp/src/jassimp/AiTextureMapMode.java b/port/jassimp/jassimp/src/jassimp/AiTextureMapMode.java index f9e86dfc6..df75c58c2 100644 --- a/port/jassimp/jassimp/src/jassimp/AiTextureMapMode.java +++ b/port/jassimp/jassimp/src/jassimp/AiTextureMapMode.java @@ -44,7 +44,7 @@ package jassimp; /** * Defines how UV coordinates outside the [0...1] range are handled.

    * - * Commonly refered to as 'wrapping mode'. + * Commonly referred to as 'wrapping mode'. */ public enum AiTextureMapMode { /** diff --git a/port/swig/interface/assimp.i b/port/swig/interface/assimp.i index 8caf13dfb..a1b1404a0 100644 --- a/port/swig/interface/assimp.i +++ b/port/swig/interface/assimp.i @@ -10,7 +10,7 @@ namespace Assimp { %ignore Importer::GetExtensionList(std::string& szOut); %ignore Importer::IsExtensionSupported(const std::string& szExtension); -// These are only neccessary for extending Assimp with custom importers or post +// These are only necessary for extending Assimp with custom importers or post // processing steps, which would require wrapping the internal BaseImporter and // BaseProcess classes. %ignore Importer::RegisterLoader(BaseImporter* pImp); diff --git a/samples/DevIL/ChangeLog b/samples/DevIL/ChangeLog index aeae00053..eabed1920 100644 --- a/samples/DevIL/ChangeLog +++ b/samples/DevIL/ChangeLog @@ -384,7 +384,7 @@ * il_jpeg.c:53: Added check for IL_USE_IJL. * il_exr.cpp:319,329: Changed to write functions instead of read. * il_files.c: Added iSetOutputFake. - * il_files.c (iSetOutputLump): Added check for NULL to accomodate ilDetermineSize function. + * il_files.c (iSetOutputLump): Added check for NULL to accommodate ilDetermineSize function. * il_hdr.c:457: Changed from char* to ILbyte*. * il_icns.h:24,30: Changed from ILbyte to char. * il_size.c: Added #ifdefs for when user has declared IL_NO_XXX. Changed error to ENUM instead of PARAM. @@ -410,7 +410,7 @@ * il_pic.c (readScanline):294-295: Added check for alpha channel. * il_pic.c: Added ilSetError calls throughout. * il_sgi.c (iLoadSgiInternal): Fixed bug #1060946 - Removed IL_LUMINANCE_ALPHA filetype. - * WindowsTest.cpp:52,53: Changed border size to accomodate Windows Vista/7. + * WindowsTest.cpp:52,53: Changed border size to accommodate Windows Vista/7. * il_endian.h:20: Changed to give __BIG_ENDIAN__ a value of 1. The Google cached page of http://74.125.47.132/search?q=cache:YfSl36C2pAQJ:patch-tracking.debian.net/patch/series/view/devil/1.7.2-1/00_endian_and_ILvoid_fixes.diff+devil+big+endian&hl=en&ct=clnk&cd=11&gl=us&lr=lang_en has this patch (Nov. 24, 2008 cache). @@ -597,7 +597,7 @@ Up to 2009-01-02 (since 1.7.5 release) Denton Woods * Fixed bug in iRegisterLoad (https://sourceforge.net/forum/message.php?msg_id=5973761). * Changed seek functions in il_files.c to return ILint. * Added rpcsal.h and sal.h #includes to ilut.h for DX10. - * Added IL_MAX_QUANT_INDICES to use instead of IL_MAX_QUANT_INDEXS (mispelled). + * Added IL_MAX_QUANT_INDICES to use instead of IL_MAX_QUANT_INDEXS (misspelled). * Added WBMP support (loading and saving). * EXR files can now be loaded as file streams and lumps. * Changed iNeuQuant to take number of colors in palette. diff --git a/samples/DevIL/include/IL/config.h b/samples/DevIL/include/IL/config.h index b9fe5dc0a..933759038 100644 --- a/samples/DevIL/include/IL/config.h +++ b/samples/DevIL/include/IL/config.h @@ -57,7 +57,7 @@ // // sorry just -// cant get this one to work under windows +// can't get this one to work under windows // have disabled for the now // // will look at it some more later diff --git a/samples/DevIL/include/IL/config.h.win b/samples/DevIL/include/IL/config.h.win index 659f4ca0e..0090b9b51 100644 --- a/samples/DevIL/include/IL/config.h.win +++ b/samples/DevIL/include/IL/config.h.win @@ -59,7 +59,7 @@ // // sorry just -// cant get this one to work under windows +// can't get this one to work under windows // have disabled for the now // // will look at it some more later diff --git a/samples/DevIL/include/IL/ilut_config.h b/samples/DevIL/include/IL/ilut_config.h index 2b3625b86..bd9cbc694 100644 --- a/samples/DevIL/include/IL/ilut_config.h +++ b/samples/DevIL/include/IL/ilut_config.h @@ -7,7 +7,7 @@ // // sorry just -// cant get this one to work under windows +// can't get this one to work under windows // have disabled for the now // // will look at it some more later diff --git a/samples/SimpleAssimpViewX/MyDocument.mm b/samples/SimpleAssimpViewX/MyDocument.mm index f074126ca..be688a6be 100644 --- a/samples/SimpleAssimpViewX/MyDocument.mm +++ b/samples/SimpleAssimpViewX/MyDocument.mm @@ -486,7 +486,7 @@ static CVReturn MyDisplayLinkCallback(CVDisplayLinkRef displayLink,const CVTimeS for (unsigned int a = 0; a < nidx; ++a) { // if(mesh->mFaces[x].mNumIndices != 3) - // NSLog(@"whoa dont have 3 indices..."); + // NSLog(@"whoa don't have 3 indices..."); *indices++ = mesh->mFaces[x].mIndices[a]; } diff --git a/samples/SimpleTexturedOpenGL/SimpleTexturedOpenGL/src/model_loading.cpp b/samples/SimpleTexturedOpenGL/SimpleTexturedOpenGL/src/model_loading.cpp index bac800152..98ed43915 100644 --- a/samples/SimpleTexturedOpenGL/SimpleTexturedOpenGL/src/model_loading.cpp +++ b/samples/SimpleTexturedOpenGL/SimpleTexturedOpenGL/src/model_loading.cpp @@ -234,14 +234,14 @@ int LoadGLTextures(const aiScene* scene) std::string fileloc = basepath + filename; /* Loading of image */ success = ilLoadImage(fileloc.c_str()); - if (success) /* If no error occured: */ + if (success) /* If no error occurred: */ { // Convert every colour component into unsigned byte.If your image contains // alpha channel you can replace IL_RGB with IL_RGBA success = ilConvertImage(IL_RGB, IL_UNSIGNED_BYTE); if (!success) { - /* Error occured */ + /* Error occurred */ abortGLInit("Couldn't convert image"); return -1; } @@ -264,7 +264,7 @@ int LoadGLTextures(const aiScene* scene) } else { - /* Error occured */ + /* Error occurred */ MessageBox(NULL, ("Couldn't load Image: " + fileloc).c_str() , "ERROR", MB_OK | MB_ICONEXCLAMATION); } } diff --git a/samples/glut/README-win32.txt b/samples/glut/README-win32.txt index f3c1cbaa5..59bd9504e 100644 --- a/samples/glut/README-win32.txt +++ b/samples/glut/README-win32.txt @@ -230,7 +230,7 @@ CHANGES/FIXES: (Oct 3, '01) x Fixed bug in getVisualInfoFromString(): visuals not reloaded on display mode change. Reload visuals each time they are queried. - This fixes a problem with Win32 because the list of availabe Visuals + This fixes a problem with Win32 because the list of available Visuals (Pixelformats) changes after a change in displaymode. The problem occurs when switching to gamemode and back. Thanks to Michael Wimmer for pointing this out & providing the fix. @@ -435,7 +435,7 @@ CHANGES/FIXES: by the structure that I used in the previous port of GLUT. Therefore I decided that it would be best to "get back to the roots". I re-implemented most of glut trying to stick - with the structure layed out by Mark. The result is a much + with the structure laid out by Mark. The result is a much more stable version that passes ALL (!) (except overlay) the tests provided by Mark. In addition, this new structure will allow future enhancements by Mark to be @@ -492,7 +492,7 @@ CHANGES/FIXES: x I don't know if this is avoidable. If you have a tight rendering loop, it may be that the processor time is going to be sucked up no matter what. You can add a sleep() to the end of your render - loop if you would like to yeild to other processes and you don't + loop if you would like to yield to other processes and you don't care too much about the speed of your rendering loop. If you have Hardware that supports OpenGL (like a 3Dpro card, or GLint card) then this should be less of a problem, since it won't be rendering diff --git a/test/models/LWO/LWO2/concrete.source.txt b/test/models/LWO/LWO2/concrete.source.txt index 792fd1f89..2904ae998 100644 --- a/test/models/LWO/LWO2/concrete.source.txt +++ b/test/models/LWO/LWO2/concrete.source.txt @@ -1,2 +1,2 @@ -cgtextures.com - free, even for commercial use. See the licensing conditions and the FAQ the site for mroe details. +cgtextures.com - free, even for commercial use. See the licensing conditions and the FAQ the site for more details. Great source for free textures, btw! \ No newline at end of file diff --git a/test/regression/README.txt b/test/regression/README.txt index aab4c1104..3e90a143b 100644 --- a/test/regression/README.txt +++ b/test/regression/README.txt @@ -72,7 +72,7 @@ makes it reasonably easy to locate the offending field. --------------------------------------------------------------------------------- As mentioned above, floating-point inaccuracies between differently optimized builds are not considered regressions and all float comparisons done by the test -suite involve an epsilon to accomodate. However compiler settings that allow +suite involve an epsilon to accommodate. However compiler settings that allow compilers to perform non-IEEE754 compliant optimizations can cause arbitrary failures in the test suite. Even if the compiler is configured to be IEE754 comformant, there is lots of code in assimp that leaves the compiler a choice diff --git a/tools/assimp_view/Display.cpp b/tools/assimp_view/Display.cpp index 28c1550f3..91ea9573b 100644 --- a/tools/assimp_view/Display.cpp +++ b/tools/assimp_view/Display.cpp @@ -1104,7 +1104,7 @@ int CDisplay::OnSetup(HTREEITEM p_hTreeItem) return OnSetupTextureView(pcNew); } - // seach the node list + // search the node list for (std::vector::iterator i = m_asNodes.begin(); i != m_asNodes.end();++i){ if (p_hTreeItem == (*i).hTreeItem) { pcNew2 = &(*i); @@ -1115,7 +1115,7 @@ int CDisplay::OnSetup(HTREEITEM p_hTreeItem) return OnSetupNodeView(pcNew2); } - // seach the material list + // search the material list for (std::vector::iterator i = m_asMaterials.begin();i != m_asMaterials.end();++i){ if (p_hTreeItem == (*i).hTreeItem){ pcNew3 = &(*i); diff --git a/tools/assimp_view/Material.cpp b/tools/assimp_view/Material.cpp index 81e342c86..14f5f7447 100644 --- a/tools/assimp_view/Material.cpp +++ b/tools/assimp_view/Material.cpp @@ -605,7 +605,7 @@ void CMaterialManager::HMtoNMIfNecessary( *piTextureOut = piTexture; // Lock the input texture and try to determine its type. - // Criterias: + // Criteria: // - If r,g,b channel are identical it MUST be a height map // - If one of the rgb channels is used and the others are empty it // must be a height map, too. diff --git a/tools/assimp_view/assimp_view.h b/tools/assimp_view/assimp_view.h index 26bde344a..bfcc5f12c 100644 --- a/tools/assimp_view/assimp_view.h +++ b/tools/assimp_view/assimp_view.h @@ -194,7 +194,7 @@ enum EClickPos { // The click was inside the inner circle (x,y axis) EClickPos_Circle, - // The click was inside one of tghe vertical snap-ins + // The click was inside one of the vertical snap-ins EClickPos_CircleVert, // The click was inside onf of the horizontal snap-ins EClickPos_CircleHor, diff --git a/workspaces/Android-NDK/jni/Android.mk b/workspaces/Android-NDK/jni/Android.mk index 0d9f4981d..b4d1da7ef 100755 --- a/workspaces/Android-NDK/jni/Android.mk +++ b/workspaces/Android-NDK/jni/Android.mk @@ -21,7 +21,7 @@ LOCAL_CPP_FEATURES := exceptions # but next breaks blender and other importer # LOCAL_CFLAGS += -std=c++11 -# cant be disabled? rudamentary function? +# can't be disabled? rudamentary function? # -DASSIMP_BUILD_NO_FLIPWINDING_PROCESS \ # DontBuildProcess = \ From 06e262f8924b22e27e66129073dfa27ef2492ca1 Mon Sep 17 00:00:00 2001 From: Steven Thompson Date: Sun, 3 Apr 2016 13:03:16 +0100 Subject: [PATCH 042/119] Added ability to export scenes with PyAssimp --- port/PyAssimp/README.md | 3 +-- port/PyAssimp/pyassimp/core.py | 29 ++++++++++++++++++++++++++++- port/PyAssimp/pyassimp/helper.py | 7 +++++-- 3 files changed, 34 insertions(+), 5 deletions(-) diff --git a/port/PyAssimp/README.md b/port/PyAssimp/README.md index 77db57fae..201d3ed7d 100644 --- a/port/PyAssimp/README.md +++ b/port/PyAssimp/README.md @@ -6,8 +6,7 @@ Requires Python >= 2.6. Python 3 support is mostly here, but not well tested. -Note that pyassimp is not complete. Many ASSIMP features are missing. In -particular, only loading of models is currently supported (no export). +Note that pyassimp is not complete. Many ASSIMP features are missing. USAGE ----- diff --git a/port/PyAssimp/pyassimp/core.py b/port/PyAssimp/pyassimp/core.py index a183dc79c..27ec44c97 100644 --- a/port/PyAssimp/pyassimp/core.py +++ b/port/PyAssimp/pyassimp/core.py @@ -35,7 +35,7 @@ class AssimpLib(object): """ Assimp-Singleton """ - load, load_mem, release, dll = helper.search_library() + load, load_mem, export, release, dll = helper.search_library() _assimp_lib = AssimpLib() def make_tuple(ai_obj, type = None): @@ -316,6 +316,33 @@ def load(filename, recur_pythonize(scene.rootnode, scene) return scene +def export(scene, + filename, + file_type = None, + processing = postprocess.aiProcess_Triangulate): + ''' + Export a scene. On failure throws AssimpError. + + Arguments + --------- + scene: scene to export. + filename: Filename that the scene should be exported to. + file_type: string of file exporter to use. For example "collada". + processing: assimp postprocessing parameters. Verbose keywords are imported + from postprocessing, and the parameters can be combined bitwise to + generate the final processing value. Note that the default value will + triangulate quad faces. Example of generating other possible values: + processing = (pyassimp.postprocess.aiProcess_Triangulate | + pyassimp.postprocess.aiProcess_OptimizeMeshes) + + ''' + + from ctypes import pointer + exportStatus = _assimp_lib.export(pointer(scene), file_type.encode("ascii"), filename.encode("ascii"), processing) + + if exportStatus != 0: + raise AssimpError('Could not export scene!') + def release(scene): from ctypes import pointer _assimp_lib.release(pointer(scene)) diff --git a/port/PyAssimp/pyassimp/helper.py b/port/PyAssimp/pyassimp/helper.py index ad38e3b71..5113e895a 100644 --- a/port/PyAssimp/pyassimp/helper.py +++ b/port/PyAssimp/pyassimp/helper.py @@ -161,7 +161,8 @@ def try_load_functions(library_path, dll): If successful: Tuple containing (library_path, load from filename function, - load from memory function + load from memory function, + export to filename function, release function, ctypes handle to assimp library) ''' @@ -170,6 +171,7 @@ def try_load_functions(library_path, dll): load = dll.aiImportFile release = dll.aiReleaseImport load_mem = dll.aiImportFileFromMemory + export = dll.aiExportScene except AttributeError: #OK, this is a library, but it doesn't have the functions we need return None @@ -178,7 +180,7 @@ def try_load_functions(library_path, dll): from .structs import Scene load.restype = POINTER(Scene) load_mem.restype = POINTER(Scene) - return (library_path, load, load_mem, release, dll) + return (library_path, load, load_mem, export, release, dll) def search_library(): ''' @@ -187,6 +189,7 @@ def search_library(): Returns: tuple, (load from filename function, load from memory function, + export to filename function, release function, dll) ''' From f2d5921252187966af977c2822362f1c7667c753 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Mon, 4 Apr 2016 12:48:53 +0200 Subject: [PATCH 043/119] Update FBXConverter.cpp FBXConverter: initialize aiNodeAnim with nullptr. --- code/FBXConverter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/FBXConverter.cpp b/code/FBXConverter.cpp index 383ac65f0..6c22f0792 100644 --- a/code/FBXConverter.cpp +++ b/code/FBXConverter.cpp @@ -2525,7 +2525,7 @@ void Converter::GenerateNodeAnimations( std::vector& node_anims, const std::string& chain_name = NameTransformationChainNode( fixed_name, comp ); - aiNodeAnim* na; + aiNodeAnim* na = nullptr; switch ( comp ) { case TransformationComp_Rotation: From a2d9cbef7e1ed1b5655262edb7daabeabc00a43a Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Mon, 4 Apr 2016 12:52:22 +0200 Subject: [PATCH 044/119] Update STEPFileReader.cpp StepFileReadder: initialize var with nullptr. --- code/STEPFileReader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/STEPFileReader.cpp b/code/STEPFileReader.cpp index 3b415ddb9..424653193 100644 --- a/code/STEPFileReader.cpp +++ b/code/STEPFileReader.cpp @@ -126,7 +126,7 @@ STEP::DB* STEP::ReadFileHeader(boost::shared_ptr stream) if (list->GetSize() > 1) { DefaultLogger::get()->warn(AddLineNumber("multiple schemas currently not supported",line)); } - const EXPRESS::STRING* string; + const EXPRESS::STRING* string( nullptr ); if (!list->GetSize() || !(string=dynamic_cast( (*list)[0].get() ))) { throw STEP::SyntaxError("expected FILE_SCHEMA to contain a single string literal",line); } From 8a3b6523f2252f53c50de85e01e09b8e83f2a8b8 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 5 Apr 2016 16:30:56 +0200 Subject: [PATCH 045/119] Update CMakeLists.txt CMake for debian package: fix home url of asset importer lib. --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1b2f12612..b3dc78d84 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -299,7 +299,7 @@ if(CMAKE_CPACK_COMMAND AND UNIX AND ASSIMP_OPT_BUILD_PACKAGES) # Packing information set(CPACK_PACKAGE_NAME "assimp{ASSIMP_VERSION_MAJOR}") set(CPACK_PACKAGE_CONTACT "" CACHE STRING "Package maintainer and PGP signer.") - set(CPACK_PACKAGE_VENDOR "http://assimp.sourceforge.net/") + set(CPACK_PACKAGE_VENDOR "https://github.com/assimp") set(CPACK_PACKAGE_DISPLAY_NAME "Assimp ${ASSIMP_VERSION}") set(CPACK_PACKAGE_DESCRIPTION_SUMMARY " - Open Asset Import Library ${ASSIMP_VERSION}") set(CPACK_PACKAGE_VERSION "${ASSIMP_VERSION}.${ASSIMP_PACKAGE_VERSION}" ) From 20630e950a05886bd0b8c5947c96972fc8924710 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 5 Apr 2016 22:02:02 +0200 Subject: [PATCH 046/119] Regression test suite: add ui for simpler text execution. --- code/CalcTangentsProcess.cpp | 2 +- test/regression/ai_regression_ui.py | 96 +++++++++++++++++++++++++++++ test/regression/result_checker.py | 2 +- test/regression/run.py | 19 +++++- 4 files changed, 116 insertions(+), 3 deletions(-) create mode 100644 test/regression/ai_regression_ui.py diff --git a/code/CalcTangentsProcess.cpp b/code/CalcTangentsProcess.cpp index 09302cc3e..dbba1bed3 100644 --- a/code/CalcTangentsProcess.cpp +++ b/code/CalcTangentsProcess.cpp @@ -108,7 +108,7 @@ void CalcTangentsProcess::Execute( aiScene* pScene) } // ------------------------------------------------------------------------------------------------ -// Calculates tangents and bitangents for the given mesh +// Calculates tangents and bi-tangents for the given mesh bool CalcTangentsProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex) { // we assume that the mesh is still in the verbose vertex format where each face has its own set diff --git a/test/regression/ai_regression_ui.py b/test/regression/ai_regression_ui.py new file mode 100644 index 000000000..fb68833de --- /dev/null +++ b/test/regression/ai_regression_ui.py @@ -0,0 +1,96 @@ +#!/usr/bin/env python3 +# -*- Coding: UTF-8 -*- + +# --------------------------------------------------------------------------- +# Open Asset Import Library (ASSIMP) +# --------------------------------------------------------------------------- +# +# Copyright (c) 2006-2016, ASSIMP Development Team +# +# All rights reserved. +# +# Redistribution and use of this software in source and binary forms, +# with or without modification, are permitted provided that the following +# conditions are met: +# +# * Redistributions of source code must retain the above +# copyright notice, this list of conditions and the +# following disclaimer. +# +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the +# following disclaimer in the documentation and/or other +# materials provided with the distribution. +# +# * Neither the name of the ASSIMP team, nor the names of its +# contributors may be used to endorse or promote products +# derived from this software without specific prior +# written permission of the ASSIMP Development Team. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# --------------------------------------------------------------------------- +from Tkinter import * +import sys +import run +import result_checker as rc + +class RegDialog( object ): + def __init__(self, bin_path ): + self.assimp_bin_path = bin_path + self.b_run_ = None + self.b_update_ = None + self.b_res_checker_ = None + self.b_quit_ = None + + + def run_reg(self): + print "run_reg" + run.setEnvVar( "assimp_path", self.assimp_bin_path ) + run.run_test() + rc.run() + self.b_update_.config( state=ACTIVE ) + return 0 + + def reg_update(self): + print "ToDo!" + return 0 + + def quit(self): + print "quit" + sys.exit( 0 ) + + def initUi(self): + root = Tk() + root.title( "Assimp-Regression") + self.b_run_ = Button( root, text="Run regression ", command=self.run_reg, width = 50 ) + self.b_update_ = Button( root, text="Update database", command=self.reg_update, width = 50 ) + self.b_quit_ = Button( root, text="Quit ", command=self.quit, width = 50 ) + self.b_run_.grid( row = 0, column = 0, sticky = W+E) + self.b_update_.grid( row = 1, column = 0, sticky = W+E) + self.b_quit_.grid( row = 2, column = 0, sticky = W+E) + self.b_run_.pack() + self.b_update_.pack() + self.b_quit_.pack() + self.b_update_.config( state=DISABLED ) + root.mainloop() + +if __name__ == "__main__": + if len(sys.argv) > 1: + assimp_bin_path = sys.argv[1] + else: + assimp_bin_path = '..\\..\\bin\\debug\\assimpd.exe' + print( 'Using assimp binary: ' + assimp_bin_path ) + dlg = RegDialog(assimp_bin_path) + dlg.initUi() + +# vim: ai ts=4 sts=4 et sw=4 \ No newline at end of file diff --git a/test/regression/result_checker.py b/test/regression/result_checker.py index 5e5ab81d1..0155660bc 100644 --- a/test/regression/result_checker.py +++ b/test/regression/result_checker.py @@ -5,7 +5,7 @@ # Open Asset Import Library (ASSIMP) # --------------------------------------------------------------------------- # -# Copyright (c) 2006-2015, ASSIMP Development Team +# Copyright (c) 2006-2016, ASSIMP Development Team # # All rights reserved. # diff --git a/test/regression/run.py b/test/regression/run.py index 12f0fc94d..9e732b646 100755 --- a/test/regression/run.py +++ b/test/regression/run.py @@ -96,6 +96,8 @@ messages = collections.defaultdict(lambda: " lock(loggerMutex); #endif if (m_pLogger && !isNullLogger() ) @@ -210,7 +210,7 @@ void DefaultLogger::set( Logger *logger ) { // enter the mutex here to avoid concurrency problems #ifndef ASSIMP_BUILD_SINGLETHREADED - boost::mutex::scoped_lock lock(loggerMutex); + std::lock_guard lock(loggerMutex); #endif if (!logger)logger = &s_pNullLogger; @@ -237,7 +237,7 @@ void DefaultLogger::kill() { // enter the mutex here to avoid concurrency problems #ifndef ASSIMP_BUILD_SINGLETHREADED - boost::mutex::scoped_lock lock(loggerMutex); + std::lock_guard lock(loggerMutex); #endif if ( m_pLogger == &s_pNullLogger ) { @@ -413,7 +413,8 @@ void DefaultLogger::WriteToStreams(const char *message, ErrorSeverity ErrorSev ) // Returns thread id, if not supported only a zero will be returned. unsigned int DefaultLogger::GetThreadID() { - // fixme: we can get this value via boost::threads + // fixme: we can get this value via std::threads + // std::this_thread::get_id().hash() returns a (big) size_t, not sure if this is useful in this case. #ifdef WIN32 return (unsigned int)::GetCurrentThreadId(); #else diff --git a/include/assimp/defs.h b/include/assimp/defs.h index e90be4a99..c607a18c4 100644 --- a/include/assimp/defs.h +++ b/include/assimp/defs.h @@ -212,31 +212,16 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // "W8059 Packgr��e der Struktur ge�ndert" #endif - ////////////////////////////////////////////////////////////////////////// - /* Define 'ASSIMP_BUILD_BOOST_WORKAROUND' to compile assimp - * without boost. This is done by using a few workaround - * classes and brings some limitations (e.g. some logging won't be done, - * the library won't utilize threads or be threadsafe at all). - * This implies the 'ASSIMP_BUILD_SINGLETHREADED' setting. */ - ////////////////////////////////////////////////////////////////////////// -#ifdef ASSIMP_BUILD_BOOST_WORKAROUND - // threading support requires boost -#ifndef ASSIMP_BUILD_SINGLETHREADED -# define ASSIMP_BUILD_SINGLETHREADED -#endif - -#endif // !! ASSIMP_BUILD_BOOST_WORKAROUND ////////////////////////////////////////////////////////////////////////// /* Define ASSIMP_BUILD_SINGLETHREADED to compile assimp * without threading support. The library doesn't utilize - * threads then and is itself not threadsafe. - * If this flag is specified boost::threads is *not* required. */ + * threads then and is itself not threadsafe. */ ////////////////////////////////////////////////////////////////////////// -#ifndef ASSIMP_BUILD_SINGLETHREADED -# define ASSIMP_BUILD_SINGLETHREADED -#endif +// #ifndef ASSIMP_BUILD_SINGLETHREADED +// # define ASSIMP_BUILD_SINGLETHREADED +// #endif #if defined(_DEBUG) || ! defined(NDEBUG) # define ASSIMP_BUILD_DEBUG From 18843fe5e1e94f10c38d1b4e0bc899d543892240 Mon Sep 17 00:00:00 2001 From: mensinda Date: Tue, 5 Apr 2016 22:53:54 +0200 Subject: [PATCH 048/119] Replaced BOOST_FOREACH with c++11 ranged for loops --- code/BlenderDNA.cpp | 12 +++--- code/BlenderIntermediate.h | 5 +-- code/BlenderLoader.cpp | 10 ++--- code/BlobIOSystem.h | 7 ++-- code/C4DImporter.cpp | 4 +- code/COBLoader.cpp | 33 ++++++++--------- code/ColladaLoader.cpp | 9 ++--- code/ColladaParser.cpp | 19 +++++----- code/DXFLoader.cpp | 23 ++++++------ code/Exporter.cpp | 2 +- code/FBXAnimation.cpp | 9 ++--- code/FBXConverter.cpp | 75 +++++++++++++++++++------------------- code/FBXDeformer.cpp | 5 +-- code/FBXDocument.cpp | 11 +++--- code/FBXMaterial.cpp | 5 +-- code/FBXMeshGeometry.cpp | 9 ++--- code/FBXModel.cpp | 5 +-- code/FBXParser.cpp | 3 +- code/FBXProperties.cpp | 7 ++-- code/IFCBoolean.cpp | 2 +- code/IFCCurve.cpp | 14 +++---- code/IFCGeometry.cpp | 20 +++++----- code/IFCLoader.cpp | 30 +++++++-------- code/IFCMaterial.cpp | 6 +-- code/IFCOpenings.cpp | 72 ++++++++++++++++++------------------ code/IFCProfile.cpp | 2 +- code/IFCUtil.cpp | 6 +-- code/NDOLoader.cpp | 8 ++-- code/ObjExporter.cpp | 13 +++---- code/STEPFile.h | 5 +-- code/XGLLoader.cpp | 4 +- code/XGLLoader.h | 5 +-- code/glTFExporter.cpp | 5 +-- 33 files changed, 209 insertions(+), 236 deletions(-) diff --git a/code/BlenderDNA.cpp b/code/BlenderDNA.cpp index 5fb14c052..a91c9f33d 100644 --- a/code/BlenderDNA.cpp +++ b/code/BlenderDNA.cpp @@ -48,13 +48,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "BlenderDNA.h" #include "StreamReader.h" #include "fast_atof.h" -#include using namespace Assimp; using namespace Assimp::Blender; using namespace Assimp::Formatter; -#define for_each BOOST_FOREACH bool match4(StreamReaderAny& stream, const char* string) { char tmp[] = { (stream).GetI1(), @@ -86,7 +84,7 @@ void DNAParser :: Parse () } std::vector names (stream.GetI4()); - for_each(std::string& s, names) { + for(std::string& s : names) { while (char c = stream.GetI1()) { s += c; } @@ -99,7 +97,7 @@ void DNAParser :: Parse () } std::vector types (stream.GetI4()); - for_each(Type& s, types) { + for(Type& s : types) { while (char c = stream.GetI1()) { s.name += c; } @@ -111,7 +109,7 @@ void DNAParser :: Parse () throw DeadlyImportError("BlenderDNA: Expected TLEN field"); } - for_each(Type& s, types) { + for(Type& s : types) { s.size = stream.GetI2(); } @@ -238,9 +236,9 @@ void DNA :: DumpToFile() f << "Field format: type name offset size" << "\n"; f << "Structure format: name size" << "\n"; - for_each(const Structure& s, structures) { + for(const Structure& s : structures) { f << s.name << " " << s.size << "\n\n"; - for_each(const Field& ff, s.fields) { + for(const Field& ff : s.fields) { f << "\t" << ff.type << " " << ff.name << " " << ff.offset << " " << ff.size << std::endl; } f << std::endl; diff --git a/code/BlenderIntermediate.h b/code/BlenderIntermediate.h index bf332516e..960a64e3d 100644 --- a/code/BlenderIntermediate.h +++ b/code/BlenderIntermediate.h @@ -49,14 +49,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "BlenderDNA.h" #include "BlenderScene.h" #include "BlenderSceneGen.h" -#include #include #include "./../include/assimp/material.h" struct aiTexture; -#define for_each(x,y) BOOST_FOREACH(x,y) - namespace Assimp { namespace Blender { @@ -71,7 +68,7 @@ namespace Blender { } ~TempArray () { - for_each(T* elem, arr) { + for(T* elem : arr) { delete elem; } } diff --git a/code/BlenderLoader.cpp b/code/BlenderLoader.cpp index 8df2f50fb..c9956249f 100644 --- a/code/BlenderLoader.cpp +++ b/code/BlenderLoader.cpp @@ -305,7 +305,7 @@ void BlenderImporter::ExtractScene(Scene& out, const FileDatabase& file) const Structure& ss = file.dna.structures[(*it).second]; // we need a scene somewhere to start with. - for_each(const FileBlockHead& bl,file.entries) { + for(const FileBlockHead& bl :file.entries) { // Fix: using the DNA index is more reliable to locate scenes //if (bl.id == "SC") { @@ -560,7 +560,7 @@ void BlenderImporter::BuildMaterials(ConversionData& conv_data) // add a default material if necessary unsigned int index = static_cast( -1 ); - for_each( aiMesh* mesh, conv_data.meshes.get() ) { + for( aiMesh* mesh : conv_data.meshes.get() ) { if (mesh->mMaterialIndex == static_cast( -1 )) { if (index == static_cast( -1 )) { @@ -589,7 +589,7 @@ void BlenderImporter::BuildMaterials(ConversionData& conv_data) } } - for_each(boost::shared_ptr mat, conv_data.materials_raw) { + for(boost::shared_ptr mat : conv_data.materials_raw) { // reset per material global counters for (size_t i = 0; i < sizeof(conv_data.next_texture)/sizeof(conv_data.next_texture[0]);++i) { @@ -722,7 +722,7 @@ void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, co temp->reserve(temp->size() + per_mat.size()); std::map mat_num_to_mesh_idx; - for_each(MyPair& it, per_mat) { + for(MyPair& it : per_mat) { mat_num_to_mesh_idx[it.first] = temp->size(); temp->push_back(new aiMesh()); @@ -1157,7 +1157,7 @@ aiNode* BlenderImporter::ConvertNode(const Scene& in, const Object* obj, Convers if (children.size()) { node->mNumChildren = static_cast(children.size()); aiNode** nd = node->mChildren = new aiNode*[node->mNumChildren](); - for_each (const Object* nobj,children) { + for (const Object* nobj :children) { *nd = ConvertNode(in,nobj,conv_data,node->mTransformation * parentTransform); (*nd++)->mParent = node; } diff --git a/code/BlobIOSystem.h b/code/BlobIOSystem.h index e157bb433..6cd014254 100644 --- a/code/BlobIOSystem.h +++ b/code/BlobIOSystem.h @@ -49,7 +49,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "./../include/assimp/cexport.h" #include "./../include/assimp/IOSystem.hpp" #include "./../include/assimp/DefaultLogger.hpp" -#include #include #include #include @@ -224,7 +223,7 @@ public: virtual ~BlobIOSystem() { - BOOST_FOREACH(BlobEntry& blobby, blobs) { + for(BlobEntry& blobby : blobs) { delete blobby.second; } } @@ -243,7 +242,7 @@ public: { // one must be the master aiExportDataBlob* master = NULL, *cur; - BOOST_FOREACH(const BlobEntry& blobby, blobs) { + for(const BlobEntry& blobby : blobs) { if (blobby.first == AI_BLOBIO_MAGIC) { master = blobby.second; break; @@ -257,7 +256,7 @@ public: master->name.Set(""); cur = master; - BOOST_FOREACH(const BlobEntry& blobby, blobs) { + for(const BlobEntry& blobby : blobs) { if (blobby.second == master) { continue; } diff --git a/code/C4DImporter.cpp b/code/C4DImporter.cpp index bfb82f93c..ae2cc8edf 100644 --- a/code/C4DImporter.cpp +++ b/code/C4DImporter.cpp @@ -161,7 +161,7 @@ void C4DImporter::InternReadFile( const std::string& pFile, RecurseHierarchy(doc->GetFirstObject(), pScene->mRootNode); } catch(...) { - BOOST_FOREACH(aiMesh* mesh, meshes) { + for(aiMesh* mesh : meshes) { delete mesh; } BaseDocument::Free(doc); @@ -176,7 +176,7 @@ void C4DImporter::InternReadFile( const std::string& pFile, // copy materials over, adding a default material if necessary unsigned int mat_count = static_cast(materials.size()); - BOOST_FOREACH(aiMesh* mesh, meshes) { + for(aiMesh* mesh : meshes) { ai_assert(mesh->mMaterialIndex <= mat_count); if(mesh->mMaterialIndex >= mat_count) { ++mat_count; diff --git a/code/COBLoader.cpp b/code/COBLoader.cpp index 210913e19..f4560f944 100644 --- a/code/COBLoader.cpp +++ b/code/COBLoader.cpp @@ -54,7 +54,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "LineSplitter.h" #include "TinyFormatter.h" #include -#include #include "../include/assimp/IOSystem.hpp" #include "../include/assimp/DefaultLogger.hpp" #include "../include/assimp/scene.h" @@ -64,8 +63,6 @@ using namespace Assimp; using namespace Assimp::COB; using namespace Assimp::Formatter; -#define for_each BOOST_FOREACH - static const float units[] = { 1000.f, @@ -170,17 +167,17 @@ void COBImporter::InternReadFile( const std::string& pFile, } // sort faces by material indices - for_each(boost::shared_ptr< Node >& n,scene.nodes) { + for(boost::shared_ptr< Node >& n : scene.nodes) { if (n->type == Node::TYPE_MESH) { Mesh& mesh = (Mesh&)(*n.get()); - for_each(Face& f,mesh.faces) { + for(Face& f : mesh.faces) { mesh.temp_map[f.material].push_back(&f); } } } // count meshes - for_each(boost::shared_ptr< Node >& n,scene.nodes) { + for(boost::shared_ptr< Node >& n : scene.nodes) { if (n->type == Node::TYPE_MESH) { Mesh& mesh = (Mesh&)(*n.get()); if (mesh.vertex_positions.size() && mesh.texture_coords.size()) { @@ -193,7 +190,7 @@ void COBImporter::InternReadFile( const std::string& pFile, pScene->mNumMeshes = 0; // count lights and cameras - for_each(boost::shared_ptr< Node >& n,scene.nodes) { + for(boost::shared_ptr< Node >& n : scene.nodes) { if (n->type == Node::TYPE_LIGHT) { ++pScene->mNumLights; } @@ -251,10 +248,10 @@ aiNode* COBImporter::BuildNodes(const Node& root,const Scene& scin,aiScene* fill if (ndmesh.vertex_positions.size() && ndmesh.texture_coords.size()) { typedef std::pair Entry; - for_each(const Entry& reflist,ndmesh.temp_map) { + for(const Entry& reflist : ndmesh.temp_map) { { // create mesh size_t n = 0; - for_each(Face* f, reflist.second) { + for(Face* f : reflist.second) { n += f->indices.size(); } if (!n) { @@ -267,7 +264,7 @@ aiNode* COBImporter::BuildNodes(const Node& root,const Scene& scin,aiScene* fill outmesh->mTextureCoords[0] = new aiVector3D[n]; outmesh->mFaces = new aiFace[reflist.second.size()](); - for_each(Face* f, reflist.second) { + for(Face* f : reflist.second) { if (f->indices.empty()) { continue; } @@ -275,7 +272,7 @@ aiNode* COBImporter::BuildNodes(const Node& root,const Scene& scin,aiScene* fill aiFace& fout = outmesh->mFaces[outmesh->mNumFaces++]; fout.mIndices = new unsigned int[f->indices.size()]; - for_each(VertexIndex& v, f->indices) { + for(VertexIndex& v : f->indices) { if (v.pos_idx >= ndmesh.vertex_positions.size()) { ThrowException("Position index out of range"); } @@ -295,7 +292,7 @@ aiNode* COBImporter::BuildNodes(const Node& root,const Scene& scin,aiScene* fill outmesh->mMaterialIndex = fill->mNumMaterials; }{ // create material const Material* min = NULL; - for_each(const Material& m, scin.materials) { + for(const Material& m : scin.materials) { if (m.parent_id == ndmesh.id && m.matnum == reflist.first) { min = &m; break; @@ -396,7 +393,7 @@ aiNode* COBImporter::BuildNodes(const Node& root,const Scene& scin,aiScene* fill // add children recursively nd->mChildren = new aiNode*[root.temp_children.size()](); - for_each(const Node* n, root.temp_children) { + for(const Node* n : root.temp_children) { (nd->mChildren[nd->mNumChildren++] = BuildNodes(*n,scin,fill))->mParent = nd; } @@ -647,7 +644,7 @@ void COBImporter::ReadUnit_Ascii(Scene& out, LineSplitter& splitter, const Chunk // parent chunks preceede their childs, so we should have the // corresponding chunk already. - for_each(boost::shared_ptr< Node >& nd, out.nodes) { + for(boost::shared_ptr< Node >& nd : out.nodes) { if (nd->id == nfo.parent_id) { const unsigned int t=strtoul10(splitter[1]); @@ -903,7 +900,7 @@ void COBImporter::ReadBitM_Ascii(Scene& /*out*/, LineSplitter& splitter, const C void COBImporter::ReadString_Binary(std::string& out, StreamReaderLE& reader) { out.resize( reader.GetI2()); - for_each(char& c,out) { + for(char& c : out) { c = reader.GetI1(); } } @@ -1043,14 +1040,14 @@ void COBImporter::ReadPolH_Binary(COB::Scene& out, StreamReaderLE& reader, const ReadBasicNodeInfo_Binary(msh,reader,nfo); msh.vertex_positions.resize(reader.GetI4()); - for_each(aiVector3D& v,msh.vertex_positions) { + for(aiVector3D& v : msh.vertex_positions) { v.x = reader.GetF4(); v.y = reader.GetF4(); v.z = reader.GetF4(); } msh.texture_coords.resize(reader.GetI4()); - for_each(aiVector2D& v,msh.texture_coords) { + for(aiVector2D& v : msh.texture_coords) { v.x = reader.GetF4(); v.y = reader.GetF4(); } @@ -1283,7 +1280,7 @@ void COBImporter::ReadUnit_Binary(COB::Scene& out, StreamReaderLE& reader, const // parent chunks preceede their childs, so we should have the // corresponding chunk already. - for_each(boost::shared_ptr< Node >& nd, out.nodes) { + for(boost::shared_ptr< Node >& nd : out.nodes) { if (nd->id == nfo.parent_id) { const unsigned int t=reader.GetI2(); nd->unit_scale = t>=sizeof(units)/sizeof(units[0])?( diff --git a/code/ColladaLoader.cpp b/code/ColladaLoader.cpp index e3a697929..74139bf56 100644 --- a/code/ColladaLoader.cpp +++ b/code/ColladaLoader.cpp @@ -56,7 +56,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "time.h" #include "math.h" -#include #include "../include/assimp/DefaultLogger.hpp" #include "../include/assimp/Importer.hpp" #include @@ -317,7 +316,7 @@ void ColladaLoader::ApplyVertexToEffectSemanticMapping(Collada::Sampler& sampler // Builds lights for the given node and references them void ColladaLoader::BuildLightsForNode( const ColladaParser& pParser, const Collada::Node* pNode, aiNode* pTarget) { - BOOST_FOREACH( const Collada::LightInstance& lid, pNode->mLights) + for( const Collada::LightInstance& lid : pNode->mLights) { // find the referred light ColladaParser::LightLibrary::const_iterator srcLightIt = pParser.mLightLibrary.find( lid.mLight); @@ -385,7 +384,7 @@ void ColladaLoader::BuildLightsForNode( const ColladaParser& pParser, const Coll // Builds cameras for the given node and references them void ColladaLoader::BuildCamerasForNode( const ColladaParser& pParser, const Collada::Node* pNode, aiNode* pTarget) { - BOOST_FOREACH( const Collada::CameraInstance& cid, pNode->mCameras) + for( const Collada::CameraInstance& cid : pNode->mCameras) { // find the referred light ColladaParser::CameraLibrary::const_iterator srcCameraIt = pParser.mCameraLibrary.find( cid.mCamera); @@ -447,7 +446,7 @@ void ColladaLoader::BuildMeshesForNode( const ColladaParser& pParser, const Coll newMeshRefs.reserve(pNode->mMeshes.size()); // add a mesh for each subgroup in each collada mesh - BOOST_FOREACH( const Collada::MeshInstance& mid, pNode->mMeshes) + for( const Collada::MeshInstance& mid : pNode->mMeshes) { const Collada::Mesh* srcMesh = NULL; const Collada::Controller* srcController = NULL; @@ -1170,7 +1169,7 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars } ++pos; } - + // https://github.com/assimp/assimp/issues/458 // Sub-sample axis-angle channels if the delta between two consecutive // key-frame angles is >= 180 degrees. diff --git a/code/ColladaParser.cpp b/code/ColladaParser.cpp index bccac5f79..e1304c65f 100644 --- a/code/ColladaParser.cpp +++ b/code/ColladaParser.cpp @@ -52,7 +52,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "fast_atof.h" #include "ParsingUtils.h" #include -#include #include "../include/assimp/DefaultLogger.hpp" #include "../include/assimp/IOSystem.hpp" #include "../include/assimp/light.h" @@ -529,10 +528,10 @@ void ColladaParser::ReadAnimation( Collada::Animation* pParent) // it turned out to have channels - add them if( !channels.empty()) { - // FIXME: Is this essentially doing the same as "single-anim-node" codepath in + // FIXME: Is this essentially doing the same as "single-anim-node" codepath in // ColladaLoader::StoreAnimations? For now, this has been deferred to after - // all animations and all clips have been read. Due to handling of - // this cannot be done here, as the channel owner + // all animations and all clips have been read. Due to handling of + // this cannot be done here, as the channel owner // is lost, and some exporters make up animations by referring to multiple // single-channel animations from an . /* @@ -1404,7 +1403,7 @@ void ColladaParser::ReadEffectProfileCommon( Collada::Effect& pEffect) pEffect.mHasTransparency = true; const char* opaque = mReader->getAttributeValueSafe("opaque"); - + if(::strcmp(opaque, "RGB_ZERO") == 0 || ::strcmp(opaque, "RGB_ONE") == 0) { pEffect.mRGBTransparency = true; } @@ -2249,7 +2248,7 @@ size_t ColladaParser::ReadPrimitives( Mesh* pMesh, std::vector& pP // find the offset index for all per-vertex channels size_t numOffsets = 1; size_t perVertexOffset = SIZE_MAX; // invalid value - BOOST_FOREACH( const InputChannel& channel, pPerIndexChannels) + for( const InputChannel& channel : pPerIndexChannels) { numOffsets = std::max( numOffsets, channel.mOffset+1); if( channel.mType == IT_Vertex) @@ -2262,7 +2261,7 @@ size_t ColladaParser::ReadPrimitives( Mesh* pMesh, std::vector& pP { case Prim_Polylist: { - BOOST_FOREACH( size_t i, pVCount) + for( size_t i : pVCount) expectedPointCount += i; break; } @@ -2910,14 +2909,14 @@ AI_WONT_RETURN void ColladaParser::ThrowException( const std::string& pError) co void ColladaParser::ReportWarning(const char* msg,...) { ai_assert(NULL != msg); - + va_list args; va_start(args,msg); - + char szBuffer[3000]; const int iLen = vsprintf(szBuffer,msg,args); ai_assert(iLen > 0); - + va_end(args); DefaultLogger::get()->warn("Validation warning: " + std::string(szBuffer,iLen)); } diff --git a/code/DXFLoader.cpp b/code/DXFLoader.cpp index f21ea15fb..7f861a992 100644 --- a/code/DXFLoader.cpp +++ b/code/DXFLoader.cpp @@ -54,7 +54,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "DXFHelper.h" #include "../include/assimp/IOSystem.hpp" #include "../include/assimp/scene.h" -#include #include using namespace Assimp; @@ -222,8 +221,8 @@ void DXFImporter::ConvertMeshes(aiScene* pScene, DXF::FileData& output) if (!DefaultLogger::isNullLogger()) { unsigned int vcount = 0, icount = 0; - BOOST_FOREACH (const DXF::Block& bl, output.blocks) { - BOOST_FOREACH (boost::shared_ptr pl, bl.lines) { + for (const DXF::Block& bl : output.blocks) { + for (boost::shared_ptr pl : bl.lines) { vcount += pl->positions.size(); icount += pl->counts.size(); } @@ -242,7 +241,7 @@ void DXFImporter::ConvertMeshes(aiScene* pScene, DXF::FileData& output) // index blocks by name DXF::BlockMap blocks_by_name; - BOOST_FOREACH (DXF::Block& bl, output.blocks) { + for (DXF::Block& bl : output.blocks) { blocks_by_name[bl.name] = &bl; if ( !entities && bl.name == AI_DXF_ENTITIES_MAGIC_BLOCK ) { entities = &bl; @@ -263,7 +262,7 @@ void DXFImporter::ConvertMeshes(aiScene* pScene, DXF::FileData& output) ExpandBlockReferences(*entities,blocks_by_name); unsigned int cur = 0; - BOOST_FOREACH (boost::shared_ptr pl, entities->lines) { + for (boost::shared_ptr pl : entities->lines) { if (pl->positions.size()) { std::map::iterator it = layers.find(pl->layer); @@ -289,12 +288,12 @@ void DXFImporter::ConvertMeshes(aiScene* pScene, DXF::FileData& output) pScene->mMeshes = new aiMesh*[ pScene->mNumMeshes ] (); - BOOST_FOREACH(const LayerMap::value_type& elem, layers){ + for(const LayerMap::value_type& elem : layers){ aiMesh* const mesh = pScene->mMeshes[elem.second] = new aiMesh(); mesh->mName.Set(elem.first); unsigned int cvert = 0,cface = 0; - BOOST_FOREACH(const DXF::PolyLine* pl, corr[elem.second]){ + for(const DXF::PolyLine* pl : corr[elem.second]){ // sum over all faces since we need to 'verbosify' them. cvert += std::accumulate(pl->counts.begin(),pl->counts.end(),0); cface += pl->counts.size(); @@ -309,10 +308,10 @@ void DXFImporter::ConvertMeshes(aiScene* pScene, DXF::FileData& output) unsigned int prims = 0; unsigned int overall_indices = 0; - BOOST_FOREACH(const DXF::PolyLine* pl, corr[elem.second]){ + for(const DXF::PolyLine* pl : corr[elem.second]){ std::vector::const_iterator it = pl->indices.begin(); - BOOST_FOREACH(unsigned int facenumv,pl->counts) { + for(unsigned int facenumv : pl->counts) { aiFace& face = *faces++; face.mIndices = new unsigned int[face.mNumIndices = facenumv]; @@ -358,7 +357,7 @@ void DXFImporter::ConvertMeshes(aiScene* pScene, DXF::FileData& output) // ------------------------------------------------------------------------------------------------ void DXFImporter::ExpandBlockReferences(DXF::Block& bl,const DXF::BlockMap& blocks_by_name) { - BOOST_FOREACH (const DXF::InsertBlock& insert, bl.insertions) { + for (const DXF::InsertBlock& insert : bl.insertions) { // first check if the referenced blocks exists ... const DXF::BlockMap::const_iterator it = blocks_by_name.find(insert.name); @@ -372,7 +371,7 @@ void DXFImporter::ExpandBlockReferences(DXF::Block& bl,const DXF::BlockMap& bloc // XXX this would be the place to implement recursive expansion if needed. const DXF::Block& bl_src = *(*it).second; - BOOST_FOREACH (boost::shared_ptr pl_in, bl_src.lines) { + for (boost::shared_ptr pl_in : bl_src.lines) { boost::shared_ptr pl_out = boost::shared_ptr(new DXF::PolyLine(*pl_in)); if (bl_src.base.Length() || insert.scale.x!=1.f || insert.scale.y!=1.f || insert.scale.z!=1.f || insert.angle || insert.pos.Length()) { @@ -388,7 +387,7 @@ void DXFImporter::ExpandBlockReferences(DXF::Block& bl,const DXF::BlockMap& bloc DefaultLogger::get()->warn("DXF: BLOCK rotation not currently implemented"); } - BOOST_FOREACH (aiVector3D& v, pl_out->positions) { + for (aiVector3D& v : pl_out->positions) { v *= trafo; } } diff --git a/code/Exporter.cpp b/code/Exporter.cpp index 888a65bd0..873fa1612 100644 --- a/code/Exporter.cpp +++ b/code/Exporter.cpp @@ -491,7 +491,7 @@ const aiExportFormatDesc* Exporter :: GetExportFormatDescription( size_t pIndex // ------------------------------------------------------------------------------------------------ aiReturn Exporter :: RegisterExporter(const ExportFormatEntry& desc) { - BOOST_FOREACH(const ExportFormatEntry& e, pimpl->mExporters) { + for(const ExportFormatEntry& e : pimpl->mExporters) { if (!strcmp(e.mDescription.id,desc.mDescription.id)) { return aiReturn_FAILURE; } diff --git a/code/FBXAnimation.cpp b/code/FBXAnimation.cpp index dc5550ec9..0758d4db7 100644 --- a/code/FBXAnimation.cpp +++ b/code/FBXAnimation.cpp @@ -51,7 +51,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "FBXImportSettings.h" #include "FBXDocumentUtil.h" #include "FBXProperties.h" -#include namespace Assimp { namespace FBX { @@ -110,7 +109,7 @@ AnimationCurveNode::AnimationCurveNode(uint64_t id, const Element& element, cons const char* whitelist[] = {"Model","NodeAttribute"}; const std::vector& conns = doc.GetConnectionsBySourceSequenced(ID(),whitelist,2); - BOOST_FOREACH(const Connection* con, conns) { + for(const Connection* con : conns) { // link should go for a property if (!con->PropertyName().length()) { @@ -171,7 +170,7 @@ const AnimationCurveMap& AnimationCurveNode::Curves() const // resolve attached animation curves const std::vector& conns = doc.GetConnectionsByDestinationSequenced(ID(),"AnimationCurve"); - BOOST_FOREACH(const Connection* con, conns) { + for(const Connection* con : conns) { // link should go for a property if (!con->PropertyName().length()) { @@ -227,7 +226,7 @@ AnimationCurveNodeList AnimationLayer::Nodes(const char* const * target_prop_whi const std::vector& conns = doc.GetConnectionsByDestinationSequenced(ID(),"AnimationCurveNode"); nodes.reserve(conns.size()); - BOOST_FOREACH(const Connection* con, conns) { + for(const Connection* con : conns) { // link should not go to a property if (con->PropertyName().length()) { @@ -278,7 +277,7 @@ AnimationStack::AnimationStack(uint64_t id, const Element& element, const std::s const std::vector& conns = doc.GetConnectionsByDestinationSequenced(ID(),"AnimationLayer"); layers.reserve(conns.size()); - BOOST_FOREACH(const Connection* con, conns) { + for(const Connection* con : conns) { // link should not go to a property if (con->PropertyName().length()) { diff --git a/code/FBXConverter.cpp b/code/FBXConverter.cpp index 6c22f0792..4ff44b86d 100644 --- a/code/FBXConverter.cpp +++ b/code/FBXConverter.cpp @@ -55,7 +55,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../include/assimp/scene.h" #include -#include #include #include @@ -79,8 +78,8 @@ using namespace Util; class Converter { public: - /** - * The different parts that make up the final local transformation of a fbx-node + /** + * The different parts that make up the final local transformation of a fbx-node */ enum TransformationComp { @@ -144,8 +143,8 @@ private: // ------------------------------------------------------------------------------------------------ void GetRotationMatrix( Model::RotOrder mode, const aiVector3D& rotation, aiMatrix4x4& out ); // ------------------------------------------------------------------------------------------------ - /** - * checks if a node has more than just scaling, rotation and translation components + /** + * checks if a node has more than just scaling, rotation and translation components */ bool NeedsComplexTransformationChain( const Model& model ); @@ -154,8 +153,8 @@ private: std::string NameTransformationChainNode( const std::string& name, TransformationComp comp ); // ------------------------------------------------------------------------------------------------ - /** - * note: memory for output_nodes will be managed by the caller + /** + * note: memory for output_nodes will be managed by the caller */ void GenerateTransformationNodeChain( const Model& model, std::vector& output_nodes ); @@ -192,11 +191,11 @@ private: // ------------------------------------------------------------------------------------------------ - /** + /** * - if materialIndex == NO_MATERIAL_SEPARATION, materials are not taken into * account when determining which weights to include. * - outputVertStartIndices is only used when a material index is specified, it gives for - * each output vertex the DOM index it maps to. + * each output vertex the DOM index it maps to. */ void ConvertWeights( aiMesh* out, const Model& model, const MeshGeometry& geo, const aiMatrix4x4& node_global_transform = aiMatrix4x4(), @@ -457,7 +456,7 @@ Converter::Converter( aiScene* out, const Document& doc ) if ( doc.Settings().readAllMaterials ) { // unfortunately this means we have to evaluate all objects - BOOST_FOREACH( const ObjectMap::value_type& v, doc.Objects() ) { + for( const ObjectMap::value_type& v : doc.Objects() ) { const Object* ob = v.second->Get(); if ( !ob ) { @@ -515,7 +514,7 @@ void Converter::ConvertNodes( uint64_t id, aiNode& parent, const aiMatrix4x4& pa std::vector nodes_chain; try { - BOOST_FOREACH( const Connection* con, conns ) { + for( const Connection* con : conns ) { // ignore object-property links if ( con->PropertyName().length() ) { @@ -550,7 +549,7 @@ void Converter::ConvertNodes( uint64_t id, aiNode& parent, const aiMatrix4x4& pa // preserve the name - people might have scripts etc. that rely // on specific node names. aiNode* name_carrier = NULL; - BOOST_FOREACH( aiNode* prenode, nodes_chain ) { + for( aiNode* prenode : nodes_chain ) { if ( !strcmp( prenode->mName.C_Str(), original_name.c_str() ) ) { name_carrier = prenode; break; @@ -567,7 +566,7 @@ void Converter::ConvertNodes( uint64_t id, aiNode& parent, const aiMatrix4x4& pa // link all nodes in a row aiNode* last_parent = &parent; - BOOST_FOREACH( aiNode* prenode, nodes_chain ) { + for( aiNode* prenode : nodes_chain ) { ai_assert( prenode ); if ( last_parent != &parent ) { @@ -619,7 +618,7 @@ void Converter::ConvertNodes( uint64_t id, aiNode& parent, const aiMatrix4x4& pa void Converter::ConvertLights( const Model& model ) { const std::vector& node_attrs = model.GetAttributes(); - BOOST_FOREACH( const NodeAttribute* attr, node_attrs ) { + for( const NodeAttribute* attr : node_attrs ) { const Light* const light = dynamic_cast( attr ); if ( light ) { ConvertLight( model, *light ); @@ -630,7 +629,7 @@ void Converter::ConvertLights( const Model& model ) void Converter::ConvertCameras( const Model& model ) { const std::vector& node_attrs = model.GetAttributes(); - BOOST_FOREACH( const NodeAttribute* attr, node_attrs ) { + for( const NodeAttribute* attr : node_attrs ) { const Camera* const cam = dynamic_cast( attr ); if ( cam ) { ConvertCamera( model, *cam ); @@ -1089,7 +1088,7 @@ void Converter::SetupNodeMetadata( const Model& model, aiNode& nd ) data->Set( index++, "IsNull", model.IsNull() ? true : false ); // add unparsed properties to the node's metadata - BOOST_FOREACH( const DirectPropertyMap::value_type& prop, unparsedProperties ) { + for( const DirectPropertyMap::value_type& prop : unparsedProperties ) { // Interpret the property as a concrete type if ( const TypedProperty* interpreted = prop.second->As >() ) @@ -1116,7 +1115,7 @@ void Converter::ConvertModel( const Model& model, aiNode& nd, const aiMatrix4x4& std::vector meshes; meshes.reserve( geos.size() ); - BOOST_FOREACH( const Geometry* geo, geos ) { + for( const Geometry* geo : geos ) { const MeshGeometry* const mesh = dynamic_cast< const MeshGeometry* >( geo ); if ( mesh ) { @@ -1160,7 +1159,7 @@ std::vector Converter::ConvertMesh( const MeshGeometry& mesh, cons const MatIndexArray& mindices = mesh.GetMaterialIndices(); if ( doc.Settings().readMaterials && !mindices.empty() ) { const MatIndexArray::value_type base = mindices[ 0 ]; - BOOST_FOREACH( MatIndexArray::value_type index, mindices ) { + for( MatIndexArray::value_type index : mindices ) { if ( index != base ) { return ConvertMeshMultiMaterial( mesh, model, node_global_transform ); } @@ -1212,7 +1211,7 @@ unsigned int Converter::ConvertMeshSingleMaterial( const MeshGeometry& mesh, con aiFace* fac = out_mesh->mFaces = new aiFace[ faces.size() ](); unsigned int cursor = 0; - BOOST_FOREACH( unsigned int pcount, faces ) { + for( unsigned int pcount : faces ) { aiFace& f = *fac++; f.mNumIndices = pcount; f.mIndices = new unsigned int[ pcount ]; @@ -1287,7 +1286,7 @@ unsigned int Converter::ConvertMeshSingleMaterial( const MeshGeometry& mesh, con } aiVector3D* out_uv = out_mesh->mTextureCoords[ i ] = new aiVector3D[ vertices.size() ]; - BOOST_FOREACH( const aiVector2D& v, uvs ) { + for( const aiVector2D& v : uvs ) { *out_uv++ = aiVector3D( v.x, v.y, 0.0f ); } @@ -1329,7 +1328,7 @@ std::vector Converter::ConvertMeshMultiMaterial( const MeshGeometr std::set had; std::vector indices; - BOOST_FOREACH( MatIndexArray::value_type index, mindices ) { + for( MatIndexArray::value_type index : mindices ) { if ( had.find( index ) == had.end() ) { indices.push_back( ConvertMeshMultiMaterial( mesh, model, index, node_global_transform ) ); @@ -1537,7 +1536,7 @@ void Converter::ConvertWeights( aiMesh* out, const Model& model, const MeshGeome try { - BOOST_FOREACH( const Cluster* cluster, sk.Clusters() ) { + for( const Cluster* cluster : sk.Clusters() ) { ai_assert( cluster ); const WeightIndexArray& indices = cluster->GetIndices(); @@ -1558,7 +1557,7 @@ void Converter::ConvertWeights( aiMesh* out, const Model& model, const MeshGeome // now check if *any* of these weights is contained in the output mesh, // taking notes so we don't need to do it twice. - BOOST_FOREACH( WeightIndexArray::value_type index, indices ) { + for( WeightIndexArray::value_type index : indices ) { unsigned int count = 0; const unsigned int* const out_idx = geo.ToOutputVertexIndex( index, count ); @@ -1839,7 +1838,7 @@ void Converter::TrySetTextureProperties( aiMaterial* out_mat, const TextureMap& uvIndex = -1; if ( !mesh ) { - BOOST_FOREACH( const MeshMap::value_type& v, meshes_converted ) { + for( const MeshMap::value_type& v : meshes_converted ) { const MeshGeometry* const mesh = dynamic_cast ( v.first ); if ( !mesh ) { continue; @@ -1957,7 +1956,7 @@ void Converter::TrySetTextureProperties( aiMaterial* out_mat, const LayeredTextu uvIndex = -1; if ( !mesh ) { - BOOST_FOREACH( const MeshMap::value_type& v, meshes_converted ) { + for( const MeshMap::value_type& v : meshes_converted ) { const MeshGeometry* const mesh = dynamic_cast ( v.first ); if ( !mesh ) { continue; @@ -2190,7 +2189,7 @@ void Converter::ConvertAnimations() anim_fps = FrameRateToDouble( fps, custom ); const std::vector& animations = doc.AnimationStacks(); - BOOST_FOREACH( const AnimationStack* stack, animations ) { + for( const AnimationStack* stack : animations ) { ConvertAnimationStack( *stack ); } } @@ -2205,21 +2204,21 @@ void Converter::RenameNode( const std::string& fixed_name, const std::string& ne const aiString fn( fixed_name ); - BOOST_FOREACH( aiCamera* cam, cameras ) { + for( aiCamera* cam : cameras ) { if ( cam->mName == fn ) { cam->mName.Set( new_name ); break; } } - BOOST_FOREACH( aiLight* light, lights ) { + for( aiLight* light : lights ) { if ( light->mName == fn ) { light->mName.Set( new_name ); break; } } - BOOST_FOREACH( aiAnimation* anim, animations ) { + for( aiAnimation* anim : animations ) { for ( unsigned int i = 0; i < anim->mNumChannels; ++i ) { aiNodeAnim* const na = anim->mChannels[ i ]; if ( na->mNodeName == fn ) { @@ -2299,11 +2298,11 @@ void Converter::ConvertAnimationStack( const AnimationStack& st ) "Lcl Translation" }; - BOOST_FOREACH( const AnimationLayer* layer, layers ) { + for( const AnimationLayer* layer : layers ) { ai_assert( layer ); const AnimationCurveNodeList& nodes = layer->Nodes( prop_whitelist, 3 ); - BOOST_FOREACH( const AnimationCurveNode* node, nodes ) { + for( const AnimationCurveNode* node : nodes ) { ai_assert( node ); const Model* const model = dynamic_cast( node->Target() ); @@ -2331,7 +2330,7 @@ void Converter::ConvertAnimationStack( const AnimationStack& st ) double stop_timeF = CONVERT_FBX_TIME( stop_time ); try { - BOOST_FOREACH( const NodeMap::value_type& kv, node_map ) { + for( const NodeMap::value_type& kv : node_map ) { GenerateNodeAnimations( node_anims, kv.first, kv.second, @@ -2389,7 +2388,7 @@ void Converter::ConvertAnimationStack( const AnimationStack& st ) static void validateAnimCurveNodes( const std::vector& curves, bool strictMode ) { const Object* target( NULL ); - BOOST_FOREACH( const AnimationCurveNode* node, curves ) { + for( const AnimationCurveNode* node : curves ) { if ( !target ) { target = node->Target(); } @@ -2419,7 +2418,7 @@ void Converter::GenerateNodeAnimations( std::vector& node_anims, validateAnimCurveNodes( curves, doc.Settings().strictMode ); #endif const AnimationCurveNode* curve_node = NULL; - BOOST_FOREACH( const AnimationCurveNode* node, curves ) { + for( const AnimationCurveNode* node : curves ) { ai_assert( node ); if ( node->TargetProperty().empty() ) { @@ -2927,11 +2926,11 @@ Converter::KeyFrameListList Converter::GetKeyframeList( const std::vectorCurves(); - BOOST_FOREACH( const AnimationCurveMap::value_type& kv, curves ) { + for( const AnimationCurveMap::value_type& kv : curves ) { unsigned int mapto; if ( kv.first == "d|X" ) { @@ -2984,7 +2983,7 @@ KeyTimeList Converter::GetKeyTimeList( const KeyFrameListList& inputs ) KeyTimeList keys; size_t estimate = 0; - BOOST_FOREACH( const KeyFrameList& kfl, inputs ) { + for( const KeyFrameList& kfl : inputs ) { estimate = std::max( estimate, kfl.get<0>()->size() ); } @@ -3037,7 +3036,7 @@ void Converter::InterpolateKeys( aiVectorKey* valOut, const KeyTimeList& keys, c next_pos.resize( inputs.size(), 0 ); - BOOST_FOREACH( KeyTimeList::value_type time, keys ) { + for( KeyTimeList::value_type time : keys ) { float result[ 3 ] = { def_value.x, def_value.y, def_value.z }; for ( size_t i = 0; i < count; ++i ) { diff --git a/code/FBXDeformer.cpp b/code/FBXDeformer.cpp index 4df8d97b1..47db96563 100644 --- a/code/FBXDeformer.cpp +++ b/code/FBXDeformer.cpp @@ -50,7 +50,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "FBXImportSettings.h" #include "FBXDocumentUtil.h" #include "FBXProperties.h" -#include namespace Assimp { namespace FBX { @@ -107,7 +106,7 @@ Cluster::Cluster(uint64_t id, const Element& element, const Document& doc, const // read assigned node const std::vector& conns = doc.GetConnectionsByDestinationSequenced(ID(),"Model"); - BOOST_FOREACH(const Connection* con, conns) { + for(const Connection* con : conns) { const Model* const mod = ProcessSimpleConnection(*con, false, "Model -> Cluster", element); if(mod) { node = mod; @@ -143,7 +142,7 @@ Skin::Skin(uint64_t id, const Element& element, const Document& doc, const std:: const std::vector& conns = doc.GetConnectionsByDestinationSequenced(ID(),"Deformer"); clusters.reserve(conns.size()); - BOOST_FOREACH(const Connection* con, conns) { + for(const Connection* con : conns) { const Cluster* const cluster = ProcessSimpleConnection(*con, false, "Cluster -> Skin", element); if(cluster) { diff --git a/code/FBXDocument.cpp b/code/FBXDocument.cpp index e2c38aa85..674d9e17d 100644 --- a/code/FBXDocument.cpp +++ b/code/FBXDocument.cpp @@ -53,7 +53,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "FBXDocumentUtil.h" #include "FBXProperties.h" -#include #include #include @@ -146,7 +145,7 @@ const Object* LazyObject::Get(bool dieOnError) // For debugging //dumpObjectClassInfo( objtype, classtag ); - + if (!strncmp(obtype,"Geometry",length)) { if (!strcmp(classtag.c_str(),"Mesh")) { object.reset(new MeshGeometry(id,element,name,doc)); @@ -290,11 +289,11 @@ Document::Document(const Parser& parser, const ImportSettings& settings) // ------------------------------------------------------------------------------------------------ Document::~Document() { - BOOST_FOREACH(ObjectMap::value_type& v, objects) { + for(ObjectMap::value_type& v : objects) { delete v.second; } - BOOST_FOREACH(ConnectionMap::value_type& v, src_connections) { + for(ConnectionMap::value_type& v : src_connections) { delete v.second; } // |dest_connections| contain the same Connection objects as the |src_connections| @@ -388,7 +387,7 @@ void Document::ReadObjects() objects[0] = new LazyObject(0L, *eobjects, *this); const Scope& sobjects = *eobjects->Compound(); - BOOST_FOREACH(const ElementMap::value_type& el, sobjects.Elements()) { + for(const ElementMap::value_type& el : sobjects.Elements()) { // extract ID const TokenList& tok = el.second->Tokens(); @@ -538,7 +537,7 @@ const std::vector& Document::AnimationStacks() const } animationStacksResolved.reserve(animationStacks.size()); - BOOST_FOREACH(uint64_t id, animationStacks) { + for(uint64_t id : animationStacks) { LazyObject* const lazy = GetObject(id); const AnimationStack* stack; if(!lazy || !(stack = lazy->Get())) { diff --git a/code/FBXMaterial.cpp b/code/FBXMaterial.cpp index c14140319..43e501d67 100644 --- a/code/FBXMaterial.cpp +++ b/code/FBXMaterial.cpp @@ -51,7 +51,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "FBXDocumentUtil.h" #include "FBXProperties.h" #include "ByteSwapper.h" -#include namespace Assimp { namespace FBX { @@ -96,7 +95,7 @@ Material::Material(uint64_t id, const Element& element, const Document& doc, con // resolve texture links const std::vector& conns = doc.GetConnectionsByDestinationSequenced(ID()); - BOOST_FOREACH(const Connection* con, conns) { + for(const Connection* con : conns) { // texture link to properties, not objects if (!con->PropertyName().length()) { @@ -205,7 +204,7 @@ Texture::Texture(uint64_t id, const Element& element, const Document& doc, const // resolve video links if(doc.Settings().readTextures) { const std::vector& conns = doc.GetConnectionsByDestinationSequenced(ID()); - BOOST_FOREACH(const Connection* con, conns) { + for(const Connection* con : conns) { const Object* const ob = con->SourceObject(); if(!ob) { DOMWarning("failed to read source object for texture link, ignoring",&element); diff --git a/code/FBXMeshGeometry.cpp b/code/FBXMeshGeometry.cpp index 5b60e4623..e9d83911b 100644 --- a/code/FBXMeshGeometry.cpp +++ b/code/FBXMeshGeometry.cpp @@ -51,7 +51,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "FBXImporter.h" #include "FBXImportSettings.h" #include "FBXDocumentUtil.h" -#include namespace Assimp { @@ -65,7 +64,7 @@ Geometry::Geometry(uint64_t id, const Element& element, const std::string& name, , skin() { const std::vector& conns = doc.GetConnectionsByDestinationSequenced(ID(),"Deformer"); - BOOST_FOREACH(const Connection* con, conns) { + for(const Connection* con : conns) { const Skin* const sk = ProcessSimpleConnection(*con, false, "Skin -> Geometry", element); if(sk) { skin = sk; @@ -130,7 +129,7 @@ MeshGeometry::MeshGeometry(uint64_t id, const Element& element, const std::strin // generate output vertices, computing an adjacency table to // preserve the mapping from fbx indices to *this* indexing. unsigned int count = 0; - BOOST_FOREACH(int index, tempFaces) { + for(int index : tempFaces) { const int absi = index < 0 ? (-index - 1) : index; if(static_cast(absi) >= vertex_count) { DOMError("polygon vertex index out of range",&PolygonVertexIndex); @@ -156,7 +155,7 @@ MeshGeometry::MeshGeometry(uint64_t id, const Element& element, const std::strin } cursor = 0; - BOOST_FOREACH(int index, tempFaces) { + for(int index : tempFaces) { const int absi = index < 0 ? (-index - 1) : index; mappings[mapping_offsets[absi] + mapping_counts[absi]++] = cursor++; } @@ -494,7 +493,7 @@ void ResolveVertexDataArray(std::vector& data_out, const Scope& source, } unsigned int next = 0; - BOOST_FOREACH(int i, uvIndices) { + for(int i : uvIndices) { if (static_cast(i) >= tempData.size()) { DOMError("index out of range",&GetRequiredElement(source,indexDataElementName)); } diff --git a/code/FBXModel.cpp b/code/FBXModel.cpp index 776334e78..bbeb14bfb 100644 --- a/code/FBXModel.cpp +++ b/code/FBXModel.cpp @@ -51,7 +51,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "FBXImportSettings.h" #include "FBXDocumentUtil.h" #include "FBXProperties.h" -#include namespace Assimp { namespace FBX { @@ -98,7 +97,7 @@ void Model::ResolveLinks(const Element& element, const Document& doc) materials.reserve(conns.size()); geometry.reserve(conns.size()); attributes.reserve(conns.size()); - BOOST_FOREACH(const Connection* con, conns) { + for(const Connection* con : conns) { // material and geometry links should be Object-Object connections if (con->PropertyName().length()) { @@ -139,7 +138,7 @@ void Model::ResolveLinks(const Element& element, const Document& doc) bool Model::IsNull() const { const std::vector& attrs = GetAttributes(); - BOOST_FOREACH(const NodeAttribute* att, attrs) { + for(const NodeAttribute* att : attrs) { const Null* null_tag = dynamic_cast(att); if(null_tag) { diff --git a/code/FBXParser.cpp b/code/FBXParser.cpp index 0c3290151..beca20b14 100644 --- a/code/FBXParser.cpp +++ b/code/FBXParser.cpp @@ -58,7 +58,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "ParsingUtils.h" #include "fast_atof.h" -#include #include "ByteSwapper.h" #include @@ -208,7 +207,7 @@ Scope::Scope(Parser& parser,bool topLevel) // ------------------------------------------------------------------------------------------------ Scope::~Scope() { - BOOST_FOREACH(ElementMap::value_type& v, elements) { + for(ElementMap::value_type& v : elements) { delete v.second; } } diff --git a/code/FBXProperties.cpp b/code/FBXProperties.cpp index 053cd530f..16d2df789 100644 --- a/code/FBXProperties.cpp +++ b/code/FBXProperties.cpp @@ -49,7 +49,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "FBXDocument.h" #include "FBXDocumentUtil.h" #include "FBXProperties.h" -#include namespace Assimp { namespace FBX { @@ -145,7 +144,7 @@ PropertyTable::PropertyTable(const Element& element, boost::shared_ptr::const_iterator vit = first_operand.verts.begin(); - BOOST_FOREACH(unsigned int pcount, first_operand.vertcnt) { + for(unsigned int pcount : first_operand.vertcnt) { temp.Clear(); temp.verts.insert(temp.verts.end(), vit, vit + pcount); diff --git a/code/IFCCurve.cpp b/code/IFCCurve.cpp index 5b1a939b9..7554da5e2 100644 --- a/code/IFCCurve.cpp +++ b/code/IFCCurve.cpp @@ -239,7 +239,7 @@ public: , total() { curves.reserve(entity.Segments.size()); - BOOST_FOREACH(const IfcCompositeCurveSegment& curveSegment,entity.Segments) { + for(const IfcCompositeCurveSegment& curveSegment :entity.Segments) { // according to the specification, this must be a bounded curve boost::shared_ptr< Curve > cv(Curve::Convert(curveSegment.ParentCurve,conv)); boost::shared_ptr< BoundedCurve > bc = boost::dynamic_pointer_cast(cv); @@ -271,7 +271,7 @@ public: } IfcFloat acc = 0; - BOOST_FOREACH(const CurveEntry& entry, curves) { + for(const CurveEntry& entry : curves) { const ParamRange& range = entry.first->GetParametricRange(); const IfcFloat delta = std::abs(range.second-range.first); if (u < acc+delta) { @@ -290,7 +290,7 @@ public: size_t cnt = 0; IfcFloat acc = 0; - BOOST_FOREACH(const CurveEntry& entry, curves) { + for(const CurveEntry& entry : curves) { const ParamRange& range = entry.first->GetParametricRange(); const IfcFloat delta = std::abs(range.second-range.first); if (a <= acc+delta && b >= acc) { @@ -312,7 +312,7 @@ public: const size_t cnt = EstimateSampleCount(a,b); out.verts.reserve(out.verts.size() + cnt); - BOOST_FOREACH(const CurveEntry& entry, curves) { + for(const CurveEntry& entry : curves) { const size_t cnt = out.verts.size(); entry.first->SampleDiscrete(out); @@ -357,7 +357,7 @@ public: // oh well. bool have_param = false, have_point = false; IfcVector3 point; - BOOST_FOREACH(const Entry sel,entity.Trim1) { + for(const Entry sel :entity.Trim1) { if (const EXPRESS::REAL* const r = sel->ToPtr()) { range.first = *r; have_param = true; @@ -374,7 +374,7 @@ public: } } have_param = false, have_point = false; - BOOST_FOREACH(const Entry sel,entity.Trim2) { + for(const Entry sel :entity.Trim2) { if (const EXPRESS::REAL* const r = sel->ToPtr()) { range.second = *r; have_param = true; @@ -465,7 +465,7 @@ public: points.reserve(entity.Points.size()); IfcVector3 t; - BOOST_FOREACH(const IfcCartesianPoint& cp, entity.Points) { + for(const IfcCartesianPoint& cp : entity.Points) { ConvertCartesianPoint(t,cp); points.push_back(t); } diff --git a/code/IFCGeometry.cpp b/code/IFCGeometry.cpp index d62c23644..38e1f0f66 100644 --- a/code/IFCGeometry.cpp +++ b/code/IFCGeometry.cpp @@ -62,7 +62,7 @@ namespace Assimp { bool ProcessPolyloop(const IfcPolyLoop& loop, TempMesh& meshout, ConversionData& /*conv*/) { size_t cnt = 0; - BOOST_FOREACH(const IfcCartesianPoint& c, loop.Polygon) { + for(const IfcCartesianPoint& c : loop.Polygon) { IfcVector3 tmp; ConvertCartesianPoint(tmp,c); @@ -191,10 +191,10 @@ void ProcessPolygonBoundaries(TempMesh& result, const TempMesh& inmesh, size_t m // ------------------------------------------------------------------------------------------------ void ProcessConnectedFaceSet(const IfcConnectedFaceSet& fset, TempMesh& result, ConversionData& conv) { - BOOST_FOREACH(const IfcFace& face, fset.CfsFaces) { + for(const IfcFace& face : fset.CfsFaces) { // size_t ob = -1, cnt = 0; TempMesh meshout; - BOOST_FOREACH(const IfcFaceBound& bound, face.Bounds) { + for(const IfcFaceBound& bound : face.Bounds) { if(const IfcPolyLoop* const polyloop = bound.Bound->ToPtr()) { if(ProcessPolyloop(*polyloop, meshout,conv)) { @@ -219,7 +219,7 @@ void ProcessConnectedFaceSet(const IfcConnectedFaceSet& fset, TempMesh& result, /*if(!IsTrue(bound.Orientation)) { size_t c = 0; - BOOST_FOREACH(unsigned int& c, meshout.vertcnt) { + for(unsigned int& c : meshout.vertcnt) { std::reverse(result.verts.begin() + cnt,result.verts.begin() + cnt + c); cnt += c; } @@ -547,7 +547,7 @@ void ProcessExtrudedArea(const IfcExtrudedAreaSolid& solid, const TempMesh& curv IfcVector3 vmin, vmax; MinMaxChooser()(vmin, vmax); - BOOST_FOREACH(IfcVector3& v, in) { + for(IfcVector3& v : in) { v *= trafo; vmin = std::min(vmin, v); @@ -579,7 +579,7 @@ void ProcessExtrudedArea(const IfcExtrudedAreaSolid& solid, const TempMesh& curv } nors.reserve(conv.apply_openings->size()); - BOOST_FOREACH(TempOpening& t, *conv.apply_openings) { + for(TempOpening& t : *conv.apply_openings) { TempMesh& bounds = *t.profileMesh.get(); if( bounds.verts.size() <= 2 ) { @@ -617,7 +617,7 @@ void ProcessExtrudedArea(const IfcExtrudedAreaSolid& solid, const TempMesh& curv } if( openings ) { - BOOST_FOREACH(TempOpening& opening, *conv.apply_openings) { + for(TempOpening& opening : *conv.apply_openings) { if( !opening.wallPoints.empty() ) { IFCImporter::LogError("failed to generate all window caps"); } @@ -697,7 +697,7 @@ void ProcessExtrudedAreaSolid(const IfcExtrudedAreaSolid& solid, TempMesh& resul std::vector* oldCollectOpenings = conv.collect_openings; conv.collect_openings = &fisherPriceMyFirstOpenings; - BOOST_FOREACH(const IfcCurve* curve, cprofile->InnerCurves) { + for(const IfcCurve* curve : cprofile->InnerCurves) { TempMesh curveMesh, tempMesh; ProcessCurve(*curve, curveMesh, conv); ProcessExtrudedArea(solid, curveMesh, dir, tempMesh, conv, true); @@ -734,7 +734,7 @@ bool ProcessGeometricItem(const IfcRepresentationItem& geo, unsigned int matid, bool fix_orientation = false; boost::shared_ptr< TempMesh > meshtmp = boost::make_shared(); if(const IfcShellBasedSurfaceModel* shellmod = geo.ToPtr()) { - BOOST_FOREACH(boost::shared_ptr shell,shellmod->SbsmBoundary) { + for(boost::shared_ptr shell :shellmod->SbsmBoundary) { try { const EXPRESS::ENTITY& e = shell->To(); const IfcConnectedFaceSet& fs = conv.db.MustGetObject(e).To(); @@ -762,7 +762,7 @@ bool ProcessGeometricItem(const IfcRepresentationItem& geo, unsigned int matid, fix_orientation = true; } else if(const IfcFaceBasedSurfaceModel* surf = geo.ToPtr()) { - BOOST_FOREACH(const IfcConnectedFaceSet& fc, surf->FbsmFaces) { + for(const IfcConnectedFaceSet& fc : surf->FbsmFaces) { ProcessConnectedFaceSet(fc,*meshtmp.get(),conv); } fix_orientation = true; diff --git a/code/IFCLoader.cpp b/code/IFCLoader.cpp index 3cd8c7338..4366fa04e 100644 --- a/code/IFCLoader.cpp +++ b/code/IFCLoader.cpp @@ -383,7 +383,7 @@ void SetUnits(ConversionData& conv) void SetCoordinateSpace(ConversionData& conv) { const IfcRepresentationContext* fav = NULL; - BOOST_FOREACH(const IfcRepresentationContext& v, conv.proj.RepresentationContexts) { + for(const 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") { @@ -440,7 +440,7 @@ bool ProcessMappedItem(const IfcMappedItem& mapped, aiNode* nd_src, std::vector< if (conv.apply_openings) { IfcMatrix4 minv = msrc; minv.Inverse(); - BOOST_FOREACH(TempOpening& open,*conv.apply_openings){ + for(TempOpening& open :*conv.apply_openings){ open.Transform(minv); } } @@ -449,7 +449,7 @@ bool ProcessMappedItem(const IfcMappedItem& mapped, aiNode* nd_src, std::vector< const IfcRepresentation& repr = mapped.MappingSource->MappedRepresentation; bool got = false; - BOOST_FOREACH(const IfcRepresentationItem& item, repr.Items) { + for(const IfcRepresentationItem& item : repr.Items) { if(!ProcessRepresentationItem(item,localmatid,meshes,conv)) { IFCImporter::LogWarn("skipping mapped entity of type " + item.GetClassName() + ", no representations could be generated"); } @@ -564,9 +564,9 @@ void ProcessProductRepresentation(const IfcProduct& el, aiNode* nd, std::vector< std::vector repr_ordered(src.size()); std::copy(src.begin(),src.end(),repr_ordered.begin()); std::sort(repr_ordered.begin(),repr_ordered.end(),RateRepresentationPredicate()); - BOOST_FOREACH(const IfcRepresentation* repr, repr_ordered) { + for(const IfcRepresentation* repr : repr_ordered) { bool res = false; - BOOST_FOREACH(const IfcRepresentationItem& item, repr->Items) { + for(const IfcRepresentationItem& item : repr->Items) { if(const IfcMappedItem* const geo = item.ToPtr()) { res = ProcessMappedItem(*geo,nd,subnodes,matid,conv) || res; } @@ -589,7 +589,7 @@ void ProcessMetadata(const ListOf< Lazy< IfcProperty >, 1, 0 >& set, ConversionD const std::string& prefix = "", unsigned int nest = 0) { - BOOST_FOREACH(const IfcProperty& property, set) { + for(const IfcProperty& property : set) { const std::string& key = prefix.length() > 0 ? (prefix + "." + property.Name) : property.Name; if (const IfcPropertySingleValue* const singleValue = property.ToPtr()) { if (singleValue->NominalValue) { @@ -615,7 +615,7 @@ void ProcessMetadata(const ListOf< Lazy< IfcProperty >, 1, 0 >& set, ConversionD std::stringstream ss; ss << "["; unsigned index=0; - BOOST_FOREACH(const IfcValue::Out& v, listValue->ListValues) { + for(const IfcValue::Out& v : listValue->ListValues) { if (!v) continue; if (const EXPRESS::STRING* str = v->ToPtr()) { std::string value = static_cast(*str); @@ -713,7 +713,7 @@ aiNode* ProcessSpatialStructure(aiNode* parent, const IfcProduct& el, Conversion data->mValues = new aiMetadataEntry[data->mNumProperties](); unsigned int index = 0; - BOOST_FOREACH(const Metadata::value_type& kv, properties) + for(const Metadata::value_type& kv : properties) data->Set(index++, kv.first, aiString(kv.second)); nd->mMetaData = data; @@ -751,7 +751,7 @@ aiNode* ProcessSpatialStructure(aiNode* parent, const IfcProduct& el, Conversion if(cont->RelatingStructure->GetID() != el.GetID()) { continue; } - BOOST_FOREACH(const IfcProduct& pro, cont->RelatedElements) { + for(const 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, @@ -794,7 +794,7 @@ aiNode* ProcessSpatialStructure(aiNode* parent, const IfcProduct& el, Conversion } // we need all openings to be in the local space of *this* node, so transform them - BOOST_FOREACH(TempOpening& op,openings_local) { + for(TempOpening& op :openings_local) { op.Transform( myInv*nd_aggr->mChildren[0]->mTransformation); openings.push_back(op); } @@ -823,7 +823,7 @@ aiNode* ProcessSpatialStructure(aiNode* parent, const IfcProduct& el, Conversion nd_aggr->mTransformation = nd->mTransformation; nd_aggr->mChildren = new aiNode*[aggr->RelatedObjects.size()](); - BOOST_FOREACH(const IfcObjectDefinition& def, aggr->RelatedObjects) { + for(const IfcObjectDefinition& def : aggr->RelatedObjects) { if(const IfcProduct* const prod = def.ToPtr()) { aiNode* const ndnew = ProcessSpatialStructure(nd_aggr.get(),*prod,conv,NULL); @@ -849,7 +849,7 @@ aiNode* ProcessSpatialStructure(aiNode* parent, const IfcProduct& el, Conversion if (subnodes.size()) { nd->mChildren = new aiNode*[subnodes.size()](); - BOOST_FOREACH(aiNode* nd2, subnodes) { + for(aiNode* nd2 : subnodes) { nd->mChildren[nd->mNumChildren++] = nd2; nd2->mParent = nd.get(); } @@ -889,7 +889,7 @@ void ProcessSpatialStructures(ConversionData& conv) } - BOOST_FOREACH(const STEP::LazyObject* lz, *range) { + for(const STEP::LazyObject* lz : *range) { const IfcSpatialStructureElement* const prod = lz->ToPtr(); if(!prod) { continue; @@ -902,7 +902,7 @@ void ProcessSpatialStructures(ConversionData& conv) for(;range.first != range.second; ++range.first) { if(const IfcRelAggregates* const aggr = conv.db.GetObject((*range.first).second)->ToPtr()) { - BOOST_FOREACH(const IfcObjectDefinition& def, aggr->RelatedObjects) { + for(const 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()) { @@ -919,7 +919,7 @@ void ProcessSpatialStructures(ConversionData& conv) IFCImporter::LogWarn("failed to determine primary site element, taking the first IfcSite"); - BOOST_FOREACH(const STEP::LazyObject* lz, *range) { + for(const STEP::LazyObject* lz : *range) { const IfcSpatialStructureElement* const prod = lz->ToPtr(); if(!prod) { continue; diff --git a/code/IFCMaterial.cpp b/code/IFCMaterial.cpp index d1954a88c..be0015bab 100644 --- a/code/IFCMaterial.cpp +++ b/code/IFCMaterial.cpp @@ -76,7 +76,7 @@ void FillMaterial(aiMaterial* mat,const IFC::IfcSurfaceStyle* surf,ConversionDat mat->AddProperty(&name,AI_MATKEY_NAME); // now see which kinds of surface information are present - BOOST_FOREACH(boost::shared_ptr< const IFC::IfcSurfaceStyleElementSelect > sel2, surf->Styles) { + for(boost::shared_ptr< const IFC::IfcSurfaceStyleElementSelect > sel2 : surf->Styles) { if (const IFC::IfcSurfaceStyleShading* shade = sel2->ResolveSelectPtr(conv.db)) { aiColor4D col_base,col; @@ -139,8 +139,8 @@ unsigned int ProcessMaterials(uint64_t id, unsigned int prevMatId, ConversionDat STEP::DB::RefMapRange range = conv.db.GetRefs().equal_range(id); for(;range.first != range.second; ++range.first) { if(const IFC::IfcStyledItem* const styled = conv.db.GetObject((*range.first).second)->ToPtr()) { - BOOST_FOREACH(const IFC::IfcPresentationStyleAssignment& as, styled->Styles) { - BOOST_FOREACH(boost::shared_ptr sel, as.Styles) { + for(const IFC::IfcPresentationStyleAssignment& as : styled->Styles) { + for(boost::shared_ptr sel : as.Styles) { if( const IFC::IfcSurfaceStyle* const surf = sel->ResolveSelectPtr(conv.db) ) { // try to satisfy from cache diff --git a/code/IFCOpenings.cpp b/code/IFCOpenings.cpp index d1dd9f50c..51ea14314 100644 --- a/code/IFCOpenings.cpp +++ b/code/IFCOpenings.cpp @@ -213,7 +213,7 @@ bool BoundingBoxesOverlapping( const BoundingBox &ibb, const BoundingBox &bb ) bool IsDuplicateVertex(const IfcVector2& vv, const std::vector& temp_contour) { // sanity check for duplicate vertices - BOOST_FOREACH(const IfcVector2& cp, temp_contour) { + for(const IfcVector2& cp : temp_contour) { if ((cp-vv).SquareLength() < 1e-5f) { return true; } @@ -226,7 +226,7 @@ void ExtractVerticesFromClipper(const ClipperLib::Polygon& poly, std::vector()(newbb_min, newbb_max); - BOOST_FOREACH(const ClipperLib::IntPoint& point, poly) { + for(const ClipperLib::IntPoint& point : poly) { IfcVector2 vv = IfcVector2( from_int64(point.X), from_int64(point.Y)); // sanity rounding @@ -391,7 +391,7 @@ void MergeWindowContours (const std::vector& a, ClipperLib::Clipper clipper; ClipperLib::Polygon clip; - BOOST_FOREACH(const IfcVector2& pip, a) { + for(const IfcVector2& pip : a) { clip.push_back(ClipperLib::IntPoint( to_int64(pip.x), to_int64(pip.y) )); } @@ -402,7 +402,7 @@ void MergeWindowContours (const std::vector& a, clipper.AddPolygon(clip, ClipperLib::ptSubject); clip.clear(); - BOOST_FOREACH(const IfcVector2& pip, b) { + for(const IfcVector2& pip : b) { clip.push_back(ClipperLib::IntPoint( to_int64(pip.x), to_int64(pip.y) )); } @@ -425,7 +425,7 @@ void MakeDisjunctWindowContours (const std::vector& a, ClipperLib::Clipper clipper; ClipperLib::Polygon clip; - BOOST_FOREACH(const IfcVector2& pip, a) { + for(const IfcVector2& pip : a) { clip.push_back(ClipperLib::IntPoint( to_int64(pip.x), to_int64(pip.y) )); } @@ -436,7 +436,7 @@ void MakeDisjunctWindowContours (const std::vector& a, clipper.AddPolygon(clip, ClipperLib::ptClip); clip.clear(); - BOOST_FOREACH(const IfcVector2& pip, b) { + for(const IfcVector2& pip : b) { clip.push_back(ClipperLib::IntPoint( to_int64(pip.x), to_int64(pip.y) )); } @@ -458,7 +458,7 @@ void CleanupWindowContour(ProjectedWindowContour& window) ClipperLib::Clipper clipper; ClipperLib::ExPolygons clipped; - BOOST_FOREACH(const IfcVector2& pip, contour) { + for(const IfcVector2& pip : contour) { subject.push_back(ClipperLib::IntPoint( to_int64(pip.x), to_int64(pip.y) )); } @@ -488,7 +488,7 @@ void CleanupWindowContours(ContourVector& contours) { // Use PolyClipper to clean up window contours try { - BOOST_FOREACH(ProjectedWindowContour& window, contours) { + for(ProjectedWindowContour& window : contours) { CleanupWindowContour(window); } } @@ -516,7 +516,7 @@ void CleanupOuterContour(const std::vector& contour_flat, TempMesh& ClipperLib::Polygon clip; clip.reserve(contour_flat.size()); - BOOST_FOREACH(const IfcVector2& pip, contour_flat) { + for(const IfcVector2& pip : contour_flat) { clip.push_back(ClipperLib::IntPoint( to_int64(pip.x), to_int64(pip.y) )); } @@ -530,7 +530,7 @@ void CleanupOuterContour(const std::vector& contour_flat, TempMesh& subject.reserve(4); size_t index = 0; size_t countdown = 0; - BOOST_FOREACH(const IfcVector3& pip, curmesh.verts) { + for(const IfcVector3& pip : curmesh.verts) { if (!countdown) { countdown = curmesh.vertcnt[index++]; if (!countdown) { @@ -548,9 +548,9 @@ void CleanupOuterContour(const std::vector& contour_flat, TempMesh& clipper.Execute(ClipperLib::ctIntersection,clipped,ClipperLib::pftNonZero,ClipperLib::pftNonZero); - BOOST_FOREACH(const ClipperLib::ExPolygon& ex, clipped) { + for(const ClipperLib::ExPolygon& ex : clipped) { iold.push_back(ex.outer.size()); - BOOST_FOREACH(const ClipperLib::IntPoint& point, ex.outer) { + for(const ClipperLib::IntPoint& point : ex.outer) { vold.push_back(IfcVector3( from_int64(point.X), from_int64(point.Y), @@ -866,7 +866,7 @@ size_t CloseWindows(ContourVector& contours, OpeningRefs& refs = contours_to_openings[std::distance(contours.begin(), it)]; bool has_other_side = false; - BOOST_FOREACH(const TempOpening* opening, refs) { + for(const TempOpening* opening : refs) { if(!opening->wallPoints.empty()) { has_other_side = true; break; @@ -929,8 +929,8 @@ size_t CloseWindows(ContourVector& contours, const IfcVector3 world_point = minv * IfcVector3(proj_point.x,proj_point.y,0.0f); - BOOST_FOREACH(const TempOpening* opening, refs) { - BOOST_FOREACH(const IfcVector3& other, opening->wallPoints) { + for(const TempOpening* opening : refs) { + for(const IfcVector3& other : opening->wallPoints) { const IfcFloat sqdist = (world_point - other).SquareLength(); if (sqdist < best) { @@ -987,7 +987,7 @@ size_t CloseWindows(ContourVector& contours, else { const Contour::const_iterator cbegin = (*it).contour.begin(), cend = (*it).contour.end(); - BOOST_FOREACH(TempOpening* opening, refs) { + for(TempOpening* opening : refs) { ai_assert(opening->wallPoints.empty()); opening->wallPoints.reserve(opening->wallPoints.capacity() + (*it).contour.size()); for (Contour::const_iterator cit = cbegin; cit != cend; ++cit) { @@ -1023,7 +1023,7 @@ void Quadrify(const std::vector< BoundingBox >& bbs, TempMesh& curmesh) curmesh.vertcnt.resize(quads.size()/4,4); curmesh.verts.reserve(quads.size()); - BOOST_FOREACH(const IfcVector2& v2, quads) { + for(const IfcVector2& v2 : quads) { curmesh.verts.push_back(IfcVector3(v2.x, v2.y, static_cast(0.0))); } } @@ -1034,7 +1034,7 @@ void Quadrify(const ContourVector& contours, TempMesh& curmesh) std::vector bbs; bbs.reserve(contours.size()); - BOOST_FOREACH(const ContourVector::value_type& val, contours) { + for(const ContourVector::value_type& val : contours) { bbs.push_back(val.bb); } @@ -1065,7 +1065,7 @@ IfcMatrix4 ProjectOntoPlane(std::vector& out_contour, const TempMesh MinMaxChooser()(vmin, vmax); // Project all points into the new coordinate system, collect min/max verts on the way - BOOST_FOREACH(const IfcVector3& x, in_verts) { + for(const IfcVector3& x : in_verts) { const IfcVector3 vv = m * x; // keep Z offset in the plane coordinate system. Ignoring precision issues // (which are present, of course), this should be the same value for @@ -1089,7 +1089,7 @@ IfcMatrix4 ProjectOntoPlane(std::vector& out_contour, const TempMesh // [0,1] range. This gives us a consistent data range so all epsilons // used below can be constants. vmax -= vmin; - BOOST_FOREACH(IfcVector2& vv, out_contour) { + for(IfcVector2& vv : out_contour) { vv.x = (vv.x - vmin.x) / vmax.x; vv.y = (vv.y - vmin.y) / vmax.y; @@ -1110,7 +1110,7 @@ IfcMatrix4 ProjectOntoPlane(std::vector& out_contour, const TempMesh // debug code to verify correctness #ifdef ASSIMP_BUILD_DEBUG std::vector out_contour2; - BOOST_FOREACH(const IfcVector3& x, in_verts) { + for(const IfcVector3& x : in_verts) { const IfcVector3& vv = m * x; out_contour2.push_back(IfcVector2(vv.x,vv.y)); @@ -1161,7 +1161,7 @@ bool GenerateOpenings(std::vector& openings, IfcVector3 wall_extrusion_axis_norm = wall_extrusion_axis; wall_extrusion_axis_norm.Normalize(); - BOOST_FOREACH(TempOpening& opening,openings) { + for(TempOpening& opening :openings) { // extrusionDir may be 0,0,0 on case where the opening mesh is not an // IfcExtrudedAreaSolid but something else (i.e. a brep) @@ -1413,7 +1413,7 @@ bool GenerateOpenings(std::vector& openings, CleanupOuterContour(contour_flat, curmesh); // Undo the projection and get back to world (or local object) space - BOOST_FOREACH(IfcVector3& v3, curmesh.verts) { + for(IfcVector3& v3 : curmesh.verts) { v3 = minv * v3; } @@ -1455,7 +1455,7 @@ bool TryAddOpenings_Poly2Tri(const std::vector& openings,const std: MinMaxChooser()(vmin, vmax); // Move all points into the new coordinate system, collecting min/max verts on the way - BOOST_FOREACH(IfcVector3& x, out) { + for(IfcVector3& x : out) { const IfcVector3 vv = m * x; // keep Z offset in the plane coordinate system. Ignoring precision issues @@ -1498,7 +1498,7 @@ bool TryAddOpenings_Poly2Tri(const std::vector& openings,const std: ClipperLib::Clipper clipper_holes; size_t c = 0; - BOOST_FOREACH(const TempOpening& t,openings) { + for(const TempOpening& t :openings) { const IfcVector3& outernor = nors[c++]; const IfcFloat dot = nor * outernor; if (std::fabs(dot)<1.f-1e-6f) { @@ -1512,7 +1512,7 @@ bool TryAddOpenings_Poly2Tri(const std::vector& openings,const std: std::vector contour; - BOOST_FOREACH(const IfcVector3& xx, t.profileMesh->verts) { + for(const IfcVector3& xx : t.profileMesh->verts) { IfcVector3 vv = m * xx, vv_extr = m * (xx + t.extrusionDir); const bool is_extruded_side = std::fabs(vv.z - coord) > std::fabs(vv_extr.z - coord); @@ -1533,7 +1533,7 @@ bool TryAddOpenings_Poly2Tri(const std::vector& openings,const std: } ClipperLib::Polygon hole; - BOOST_FOREACH(IfcVector2& pip, contour) { + for(IfcVector2& pip : contour) { pip.x = (pip.x - vmin.x) / vmax.x; pip.y = (pip.y - vmin.y) / vmax.y; @@ -1566,7 +1566,7 @@ bool TryAddOpenings_Poly2Tri(const std::vector& openings,const std: // to obtain the final polygon to feed into the triangulator. { ClipperLib::Polygon poly; - BOOST_FOREACH(IfcVector2& pip, contour_flat) { + for(IfcVector2& pip : contour_flat) { pip.x = (pip.x - vmin.x) / vmax.x; pip.y = (pip.y - vmin.y) / vmax.y; @@ -1606,13 +1606,13 @@ bool TryAddOpenings_Poly2Tri(const std::vector& openings,const std: if (false && do_connections) { std::vector tmpvec; - BOOST_FOREACH(ClipperLib::Polygon& opening, holes_union) { + for(ClipperLib::Polygon& opening : holes_union) { assert(ClipperLib::Orientation(opening)); tmpvec.clear(); - BOOST_FOREACH(ClipperLib::IntPoint& point, opening) { + for(ClipperLib::IntPoint& point : opening) { tmpvec.push_back( minv * IfcVector3( vmin.x + from_int64(point.X) * vmax.x, @@ -1638,13 +1638,13 @@ bool TryAddOpenings_Poly2Tri(const std::vector& openings,const std: } std::vector< std::vector > contours; - BOOST_FOREACH(ClipperLib::ExPolygon& clip, clipped) { + for(ClipperLib::ExPolygon& clip : clipped) { contours.clear(); // Build the outer polygon contour line for feeding into poly2tri std::vector contour_points; - BOOST_FOREACH(ClipperLib::IntPoint& point, clip.outer) { + for(ClipperLib::IntPoint& point : clip.outer) { contour_points.push_back( new p2t::Point(from_int64(point.X), from_int64(point.Y)) ); } @@ -1664,12 +1664,12 @@ bool TryAddOpenings_Poly2Tri(const std::vector& openings,const std: // Build the poly2tri inner contours for all holes we got from ClipperLib - BOOST_FOREACH(ClipperLib::Polygon& opening, clip.holes) { + for(ClipperLib::Polygon& opening : clip.holes) { contours.push_back(std::vector()); std::vector& contour = contours.back(); - BOOST_FOREACH(ClipperLib::IntPoint& point, opening) { + for(ClipperLib::IntPoint& point : opening) { contour.push_back( new p2t::Point(from_int64(point.X), from_int64(point.Y)) ); } @@ -1689,7 +1689,7 @@ bool TryAddOpenings_Poly2Tri(const std::vector& openings,const std: const std::vector tris = cdt->GetTriangles(); // Collect the triangles we just produced - BOOST_FOREACH(p2t::Triangle* tri, tris) { + for(p2t::Triangle* tri : tris) { for(int i = 0; i < 3; ++i) { const IfcVector2 v = IfcVector2( diff --git a/code/IFCProfile.cpp b/code/IFCProfile.cpp index c2bf91c56..04e0b39cc 100644 --- a/code/IFCProfile.cpp +++ b/code/IFCProfile.cpp @@ -55,7 +55,7 @@ void ProcessPolyLine(const IfcPolyline& def, TempMesh& meshout, ConversionData& { // this won't produce a valid mesh, it just spits out a list of vertices IfcVector3 t; - BOOST_FOREACH(const IfcCartesianPoint& cp, def.Points) { + for(const IfcCartesianPoint& cp : def.Points) { ConvertCartesianPoint(t,cp); meshout.verts.push_back(t); } diff --git a/code/IFCUtil.cpp b/code/IFCUtil.cpp index 233d52d0b..7a47fb02d 100644 --- a/code/IFCUtil.cpp +++ b/code/IFCUtil.cpp @@ -115,7 +115,7 @@ void TempMesh::Clear() // ------------------------------------------------------------------------------------------------ void TempMesh::Transform(const IfcMatrix4& mat) { - BOOST_FOREACH(IfcVector3& v, verts) { + for(IfcVector3& v : verts) { v *= mat; } } @@ -222,7 +222,7 @@ void TempMesh::ComputePolygonNormals(std::vector& normals, } if(normalize) { - BOOST_FOREACH(IfcVector3& n, normals) { + for(IfcVector3& n : normals) { n.Normalize(); } } @@ -383,7 +383,7 @@ void TempMesh::RemoveAdjacentDuplicates() bool drop = false; std::vector::iterator base = verts.begin(); - BOOST_FOREACH(unsigned int& cnt, vertcnt) { + for(unsigned int& cnt : vertcnt) { if (cnt < 2){ base += cnt; continue; diff --git a/code/NDOLoader.cpp b/code/NDOLoader.cpp index 08a151717..699e97051 100644 --- a/code/NDOLoader.cpp +++ b/code/NDOLoader.cpp @@ -50,10 +50,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../include/assimp/IOSystem.hpp" #include "../include/assimp/scene.h" #include "StreamReader.h" -#include using namespace Assimp; -#define for_each BOOST_FOREACH static const aiImporterDesc desc = { "Nendo Mesh Importer", @@ -241,7 +239,7 @@ void NDOImporter::InternReadFile( const std::string& pFile, std::vector vertices; std::vector indices; - for_each(const Object& obj,objects) { + for(const Object& obj : objects) { aiNode* nd = *cc++ = new aiNode(obj.name); nd->mParent = root; @@ -250,7 +248,7 @@ void NDOImporter::InternReadFile( const std::string& pFile, FaceTable face_table; unsigned int n = 0; - for_each(const Edge& edge, obj.edges) { + for(const Edge& edge : obj.edges) { face_table[edge.edge[2]] = n; face_table[edge.edge[3]] = n; @@ -263,7 +261,7 @@ void NDOImporter::InternReadFile( const std::string& pFile, vertices.clear(); vertices.reserve(4 * face_table.size()); // arbitrarily chosen - for_each(FaceTable::value_type& v, face_table) { + for(FaceTable::value_type& v : face_table) { indices.clear(); aiFace& f = *faces++; diff --git a/code/ObjExporter.cpp b/code/ObjExporter.cpp index 4cfdb37e5..254786968 100644 --- a/code/ObjExporter.cpp +++ b/code/ObjExporter.cpp @@ -51,7 +51,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include -#include #include @@ -217,7 +216,7 @@ void ObjExporter :: WriteGeometryFile() // write vertex positions vpMap.getVectors(vp); mOutput << "# " << vp.size() << " vertex positions" << endl; - BOOST_FOREACH(const aiVector3D& v, vp) { + for(const aiVector3D& v : vp) { mOutput << "v " << v.x << " " << v.y << " " << v.z << endl; } mOutput << endl; @@ -225,7 +224,7 @@ void ObjExporter :: WriteGeometryFile() // write uv coordinates vtMap.getVectors(vt); mOutput << "# " << vt.size() << " UV coordinates" << endl; - BOOST_FOREACH(const aiVector3D& v, vt) { + for(const aiVector3D& v : vt) { mOutput << "vt " << v.x << " " << v.y << " " << v.z << endl; } mOutput << endl; @@ -233,22 +232,22 @@ void ObjExporter :: WriteGeometryFile() // write vertex normals vnMap.getVectors(vn); mOutput << "# " << vn.size() << " vertex normals" << endl; - BOOST_FOREACH(const aiVector3D& v, vn) { + for(const aiVector3D& v : vn) { mOutput << "vn " << v.x << " " << v.y << " " << v.z << endl; } mOutput << endl; // now write all mesh instances - BOOST_FOREACH(const MeshInstance& m, meshes) { + for(const MeshInstance& m : meshes) { mOutput << "# Mesh \'" << m.name << "\' with " << m.faces.size() << " faces" << endl; if (!m.name.empty()) { mOutput << "g " << m.name << endl; } mOutput << "usemtl " << m.matname << endl; - BOOST_FOREACH(const Face& f, m.faces) { + for(const Face& f : m.faces) { mOutput << f.kind << ' '; - BOOST_FOREACH(const FaceVertex& fv, f.indices) { + for(const FaceVertex& fv : f.indices) { mOutput << ' ' << fv.vp; if (f.kind != 'p') { diff --git a/code/STEPFile.h b/code/STEPFile.h index a0f936889..050e76b24 100644 --- a/code/STEPFile.h +++ b/code/STEPFile.h @@ -42,7 +42,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define INCLUDED_AI_STEPFILE_H #include -#include #include #include #include @@ -868,7 +867,7 @@ namespace STEP { public: ~DB() { - BOOST_FOREACH(ObjectMap::value_type& o, objects) { + for(ObjectMap::value_type& o : objects) { delete o.second; } } @@ -950,7 +949,7 @@ namespace STEP { // evaluate *all* entities in the file. this is a power test for the loader void EvaluateAll() { - BOOST_FOREACH(ObjectMap::value_type& e,objects) { + for(ObjectMap::value_type& e :objects) { **e.second; } ai_assert(evaluated_count == objects.size()); diff --git a/code/XGLLoader.cpp b/code/XGLLoader.cpp index 1d1a8d6c9..0c4f3cb3f 100644 --- a/code/XGLLoader.cpp +++ b/code/XGLLoader.cpp @@ -431,7 +431,7 @@ aiNode* XGLImporter::ReadObject(TempScope& scope, bool skipFirst, const char* cl } } catch(...) { - BOOST_FOREACH(aiNode* ch, children) { + for(aiNode* ch : children) { delete ch; } throw; @@ -691,7 +691,7 @@ bool XGLImporter::ReadMesh(TempScope& scope) // finally extract output meshes and add them to the scope typedef std::pair pairt; - BOOST_FOREACH(const pairt& p, bymat) { + for(const pairt& p : bymat) { aiMesh* const m = ToOutputMesh(p.second); scope.meshes_linear.push_back(m); diff --git a/code/XGLLoader.h b/code/XGLLoader.h index 582c07429..a27b817f5 100644 --- a/code/XGLLoader.h +++ b/code/XGLLoader.h @@ -47,7 +47,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "BaseImporter.h" #include "irrXMLWrapper.h" #include "LogAux.h" -#include #include "../include/assimp/material.h" #include "../include/assimp/Importer.hpp" #include "../include/assimp/mesh.h" @@ -102,11 +101,11 @@ private: ~TempScope() { - BOOST_FOREACH(aiMesh* m, meshes_linear) { + for(aiMesh* m : meshes_linear) { delete m; } - BOOST_FOREACH(aiMaterial* m, materials_linear) { + for(aiMaterial* m : materials_linear) { delete m; } diff --git a/code/glTFExporter.cpp b/code/glTFExporter.cpp index 41cdaf084..d40ea695f 100644 --- a/code/glTFExporter.cpp +++ b/code/glTFExporter.cpp @@ -54,7 +54,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -#include #include #include @@ -130,7 +129,7 @@ glTFExporter::glTFExporter(const char* filename, IOSystem* pIOSystem, const aiSc static void CopyValue(const aiMatrix4x4& v, glTF::mat4& o) -{ +{ o[ 0] = v.a1; o[ 1] = v.b1; o[ 2] = v.c1; o[ 3] = v.d1; o[ 4] = v.a2; o[ 5] = v.b2; o[ 6] = v.c2; o[ 7] = v.d2; o[ 8] = v.a3; o[ 9] = v.b3; o[10] = v.c3; o[11] = v.d3; @@ -233,7 +232,7 @@ void glTFExporter::ExportMaterials() for (unsigned int i = 0; i < mScene->mNumMaterials; ++i) { const aiMaterial* mat = mScene->mMaterials[i]; - + std::string name; if (mat->Get(AI_MATKEY_NAME, aiName) == AI_SUCCESS) { name = aiName.C_Str(); From cff5b0d1a00dde0f229945e19d5f1ee85474d8bd Mon Sep 17 00:00:00 2001 From: mensinda Date: Tue, 5 Apr 2016 22:56:11 +0200 Subject: [PATCH 049/119] Replaced depreacated std::auto_ptr with std::unique_ptr --- code/3DSExporter.cpp | 2 +- code/Exporter.cpp | 2 +- code/IFCLoader.cpp | 8 ++++---- code/IFCMaterial.cpp | 4 ++-- code/IFCUtil.cpp | 2 +- code/STEPFile.h | 2 +- code/STEPFileReader.cpp | 2 +- 7 files changed, 11 insertions(+), 11 deletions(-) diff --git a/code/3DSExporter.cpp b/code/3DSExporter.cpp index f33799fef..16e1e8a01 100644 --- a/code/3DSExporter.cpp +++ b/code/3DSExporter.cpp @@ -164,7 +164,7 @@ void ExportScene3DS(const char* pFile, IOSystem* pIOSystem, const aiScene* pScen // in |Exporter::ExportFormatEntry|. aiScene* scenecopy_tmp; SceneCombiner::CopyScene(&scenecopy_tmp,pScene); - std::auto_ptr scenecopy(scenecopy_tmp); + std::unique_ptr scenecopy(scenecopy_tmp); SplitLargeMeshesProcess_Triangle tri_splitter; tri_splitter.SetLimit(0xffff); diff --git a/code/Exporter.cpp b/code/Exporter.cpp index 873fa1612..72aae1acc 100644 --- a/code/Exporter.cpp +++ b/code/Exporter.cpp @@ -324,7 +324,7 @@ aiReturn Exporter :: Export( const aiScene* pScene, const char* pFormatId, const aiScene* scenecopy_tmp; SceneCombiner::CopyScene(&scenecopy_tmp,pScene); - std::auto_ptr scenecopy(scenecopy_tmp); + std::unique_ptr scenecopy(scenecopy_tmp); const ScenePrivateData* const priv = ScenePriv(pScene); // steps that are not idempotent, i.e. we might need to run them again, usually to get back to the diff --git a/code/IFCLoader.cpp b/code/IFCLoader.cpp index 4366fa04e..de4384082 100644 --- a/code/IFCLoader.cpp +++ b/code/IFCLoader.cpp @@ -423,7 +423,7 @@ void ResolveObjectPlacement(aiMatrix4x4& m, const IfcObjectPlacement& place, Con bool ProcessMappedItem(const IfcMappedItem& mapped, aiNode* nd_src, std::vector< aiNode* >& subnodes_src, unsigned int matid, ConversionData& conv) { // insert a custom node here, the cartesian transform operator is simply a conventional transformation matrix - std::auto_ptr nd(new aiNode()); + std::unique_ptr nd(new aiNode()); nd->mName.Set("IfcMappedItem"); // handle the Cartesian operator @@ -684,7 +684,7 @@ aiNode* ProcessSpatialStructure(aiNode* parent, const IfcProduct& el, Conversion } // add an output node for this spatial structure - std::auto_ptr nd(new aiNode()); + std::unique_ptr nd(new aiNode()); nd->mName.Set(el.GetClassName()+"_"+(el.Name?el.Name.Get():"Unnamed")+"_"+el.GlobalId); nd->mParent = parent; @@ -771,7 +771,7 @@ aiNode* ProcessSpatialStructure(aiNode* parent, const IfcProduct& el, Conversion const IfcFeatureElementSubtraction& open = fills->RelatedOpeningElement; // move opening elements to a separate node since they are semantically different than elements that are just 'contained' - std::auto_ptr nd_aggr(new aiNode()); + std::unique_ptr nd_aggr(new aiNode()); nd_aggr->mName.Set("$RelVoidsElement"); nd_aggr->mParent = nd.get(); @@ -816,7 +816,7 @@ aiNode* ProcessSpatialStructure(aiNode* parent, const IfcProduct& el, Conversion } // move aggregate elements to a separate node since they are semantically different than elements that are just 'contained' - std::auto_ptr nd_aggr(new aiNode()); + std::unique_ptr nd_aggr(new aiNode()); nd_aggr->mName.Set("$RelAggregates"); nd_aggr->mParent = nd.get(); diff --git a/code/IFCMaterial.cpp b/code/IFCMaterial.cpp index be0015bab..25686b83f 100644 --- a/code/IFCMaterial.cpp +++ b/code/IFCMaterial.cpp @@ -154,7 +154,7 @@ unsigned int ProcessMaterials(uint64_t id, unsigned int prevMatId, ConversionDat IFCImporter::LogWarn("ignoring surface side marker on IFC::IfcSurfaceStyle: " + side); } - std::auto_ptr mat(new aiMaterial()); + std::unique_ptr mat(new aiMaterial()); FillMaterial(mat.get(), surf, conv); @@ -190,7 +190,7 @@ unsigned int ProcessMaterials(uint64_t id, unsigned int prevMatId, ConversionDat } // we're here, yet - no default material with suitable color available. Generate one - std::auto_ptr mat(new aiMaterial()); + std::unique_ptr mat(new aiMaterial()); mat->AddProperty(&name,AI_MATKEY_NAME); const aiColor4D col = aiColor4D( 0.6f, 0.6f, 0.6f, 1.0f); // aiColor4D( color.r, color.g, color.b, 1.0f); diff --git a/code/IFCUtil.cpp b/code/IFCUtil.cpp index 7a47fb02d..89a6c78c5 100644 --- a/code/IFCUtil.cpp +++ b/code/IFCUtil.cpp @@ -75,7 +75,7 @@ aiMesh* TempMesh::ToMesh() return NULL; } - std::auto_ptr mesh(new aiMesh()); + std::unique_ptr mesh(new aiMesh()); // copy vertices mesh->mNumVertices = static_cast(verts.size()); diff --git a/code/STEPFile.h b/code/STEPFile.h index 050e76b24..63a1c2239 100644 --- a/code/STEPFile.h +++ b/code/STEPFile.h @@ -509,7 +509,7 @@ namespace STEP { static Object* Construct(const STEP::DB& db, const EXPRESS::LIST& params) { // make sure we don't leak if Fill() throws an exception - std::auto_ptr impl(new TDerived()); + 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); diff --git a/code/STEPFileReader.cpp b/code/STEPFileReader.cpp index 424653193..70217b1c6 100644 --- a/code/STEPFileReader.cpp +++ b/code/STEPFileReader.cpp @@ -88,7 +88,7 @@ STEP::TypeError::TypeError (const std::string& s,uint64_t entity /* = ENTITY_NOT STEP::DB* STEP::ReadFileHeader(boost::shared_ptr stream) { boost::shared_ptr reader = boost::shared_ptr(new StreamReaderLE(stream)); - std::auto_ptr db = std::auto_ptr(new STEP::DB(reader)); + std::unique_ptr db = std::unique_ptr(new STEP::DB(reader)); LineSplitter& splitter = db->GetSplitter(); if (!splitter || *splitter != "ISO-10303-21;") { From 5dacda0a085632b554206448cd22dd1ad018b8a9 Mon Sep 17 00:00:00 2001 From: mensinda Date: Tue, 5 Apr 2016 23:23:53 +0200 Subject: [PATCH 050/119] replaced boost smart pointers with c++11 smart pointers --- code/3DSConverter.cpp | 4 +- code/3DSExporter.cpp | 4 +- code/3DSExporter.h | 4 +- code/ACLoader.cpp | 6 +- code/ASELoader.cpp | 4 +- code/B3DImporter.cpp | 44 +-- code/BVHLoader.cpp | 4 +- code/BaseImporter.cpp | 9 +- code/BlenderDNA.cpp | 6 +- code/BlenderDNA.h | 34 +- code/BlenderDNA.inl | 110 +++---- code/BlenderIntermediate.h | 2 +- code/BlenderLoader.cpp | 20 +- code/BlenderLoader.h | 4 +- code/BlenderModifier.cpp | 14 +- code/BlenderScene.cpp | 4 +- code/BlenderScene.h | 58 ++-- code/BoostWorkaround/boost/scoped_ptr.hpp | 2 +- code/BoostWorkaround/boost/shared_ptr.hpp | 2 +- code/C4DImporter.cpp | 2 +- code/COBLoader.cpp | 38 +-- code/COBScene.h | 6 +- code/CSMLoader.cpp | 4 +- code/ColladaExporter.cpp | 6 +- code/ColladaParser.cpp | 6 +- code/ColladaParser.h | 178 +++++------ code/DXFHelper.h | 2 +- code/DXFLoader.cpp | 14 +- code/Exporter.cpp | 8 +- code/FBXConverter.cpp | 10 +- code/FBXDocument.cpp | 12 +- code/FBXDocument.h | 28 +- code/FBXDocumentUtil.cpp | 10 +- code/FBXDocumentUtil.h | 4 +- code/FBXImporter.cpp | 2 +- code/FBXParser.h | 6 +- code/FBXProperties.cpp | 4 +- code/FBXProperties.h | 8 +- code/FBXTokenizer.h | 2 +- code/FindInstancesProcess.cpp | 10 +- code/HMPLoader.cpp | 4 +- code/IFCBoolean.cpp | 6 +- code/IFCCurve.cpp | 12 +- code/IFCGeometry.cpp | 14 +- code/IFCLoader.cpp | 4 +- code/IFCMaterial.cpp | 4 +- code/IFCProfile.cpp | 2 +- code/IFCReaderGen.cpp | 360 +++++++++++----------- code/IFCUtil.h | 8 +- code/IRRLoader.cpp | 4 +- code/IRRMeshLoader.cpp | 4 +- code/Importer.cpp | 12 +- code/LWOLoader.cpp | 4 +- code/LWSLoader.cpp | 4 +- code/MD2Loader.cpp | 4 +- code/MD3Loader.cpp | 8 +- code/MD5Loader.cpp | 8 +- code/MDCLoader.cpp | 4 +- code/MDLLoader.cpp | 4 +- code/NFFLoader.cpp | 6 +- code/OFFLoader.cpp | 4 +- code/ObjExporter.cpp | 6 +- code/ObjFileImporter.cpp | 4 +- code/OgreBinarySerializer.h | 2 +- code/OgreImporter.cpp | 12 +- code/OgreMaterial.cpp | 4 +- code/OgreStructs.h | 4 +- code/OgreXmlSerializer.cpp | 6 +- code/OgreXmlSerializer.h | 2 +- code/PlyExporter.cpp | 6 +- code/PlyLoader.cpp | 4 +- code/RawLoader.cpp | 4 +- code/SMDLoader.cpp | 4 +- code/STEPFile.h | 38 +-- code/STEPFileEncoding.cpp | 10 +- code/STEPFileReader.cpp | 32 +- code/STEPFileReader.h | 2 +- code/STLExporter.cpp | 6 +- code/STLLoader.cpp | 4 +- code/StepExporter.cpp | 4 +- code/StreamReader.h | 8 +- code/StreamWriter.h | 8 +- code/TriangulateProcess.cpp | 6 +- code/UnrealLoader.cpp | 4 +- code/ValidateDataStructure.cpp | 4 +- code/XFileExporter.cpp | 4 +- code/XFileImporter.cpp | 4 +- code/XGLLoader.cpp | 8 +- code/glTFAsset.h | 14 +- code/glTFAssetWriter.inl | 2 +- code/glTFExporter.cpp | 6 +- code/glTFExporter.h | 2 +- code/glTFImporter.cpp | 16 +- code/irrXMLWrapper.h | 4 +- doc/dox.h | 2 +- 95 files changed, 709 insertions(+), 712 deletions(-) diff --git a/code/3DSConverter.cpp b/code/3DSConverter.cpp index cea255380..419b71b29 100644 --- a/code/3DSConverter.cpp +++ b/code/3DSConverter.cpp @@ -50,7 +50,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../include/assimp/scene.h" #include "../include/assimp/DefaultLogger.hpp" #include "StringComparison.h" -#include +#include #include using namespace Assimp; @@ -359,7 +359,7 @@ void Discreet3DSImporter::ConvertMeshes(aiScene* pcOut) // we need to split all meshes by their materials for (std::vector::iterator i = mScene->mMeshes.begin(); i != mScene->mMeshes.end();++i) { - boost::scoped_array< std::vector > aiSplit(new std::vector[mScene->mMaterials.size()]); + std::unique_ptr< std::vector[] > aiSplit(new std::vector[mScene->mMaterials.size()]); name.length = ASSIMP_itoa10(name.data,num++); diff --git a/code/3DSExporter.cpp b/code/3DSExporter.cpp index 16e1e8a01..5450c1baf 100644 --- a/code/3DSExporter.cpp +++ b/code/3DSExporter.cpp @@ -150,7 +150,7 @@ namespace { // Worker function for exporting a scene to 3DS. Prototyped and registered in Exporter.cpp void ExportScene3DS(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties) { - boost::shared_ptr outfile (pIOSystem->Open(pFile, "wb")); + std::shared_ptr outfile (pIOSystem->Open(pFile, "wb")); if(!outfile) { throw DeadlyExportError("Could not open output .3ds file: " + std::string(pFile)); } @@ -181,7 +181,7 @@ void ExportScene3DS(const char* pFile, IOSystem* pIOSystem, const aiScene* pScen } // end of namespace Assimp // ------------------------------------------------------------------------------------------------ -Discreet3DSExporter:: Discreet3DSExporter(boost::shared_ptr outfile, const aiScene* scene) +Discreet3DSExporter:: Discreet3DSExporter(std::shared_ptr outfile, const aiScene* scene) : scene(scene) , writer(outfile) { diff --git a/code/3DSExporter.h b/code/3DSExporter.h index ce9a02f78..321539cff 100644 --- a/code/3DSExporter.h +++ b/code/3DSExporter.h @@ -45,7 +45,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define AI_3DSEXPORTER_H_INC #include -#include +#include #include "StreamWriter.h" #include "./../include/assimp/material.h" @@ -64,7 +64,7 @@ namespace Assimp class Discreet3DSExporter { public: - Discreet3DSExporter(boost::shared_ptr outfile, const aiScene* pScene); + Discreet3DSExporter(std::shared_ptr outfile, const aiScene* pScene); private: diff --git a/code/ACLoader.cpp b/code/ACLoader.cpp index 4607d3536..fbe8cb009 100644 --- a/code/ACLoader.cpp +++ b/code/ACLoader.cpp @@ -60,7 +60,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../include/assimp/scene.h" #include "../include/assimp/config.h" #include "../include/assimp/IOSystem.hpp" -#include +#include using namespace Assimp; @@ -708,7 +708,7 @@ aiNode* AC3DImporter::ConvertObjectSection(Object& object, // collect all meshes using the same material group. if (object.subDiv) { if (configEvalSubdivision) { - boost::scoped_ptr div(Subdivider::Create(Subdivider::CATMULL_CLARKE)); + std::unique_ptr div(Subdivider::Create(Subdivider::CATMULL_CLARKE)); DefaultLogger::get()->info("AC3D: Evaluating subdivision surface: "+object.name); std::vector cpy(meshes.size()-oldm,NULL); @@ -787,7 +787,7 @@ void AC3DImporter::SetupProperties(const Importer* pImp) void AC3DImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) { - boost::scoped_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) diff --git a/code/ASELoader.cpp b/code/ASELoader.cpp index 514b6b66c..6f6610786 100644 --- a/code/ASELoader.cpp +++ b/code/ASELoader.cpp @@ -51,7 +51,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "SkeletonMeshBuilder.h" #include "TargetAnimation.h" #include "../include/assimp/Importer.hpp" -#include +#include #include "../include/assimp/IOSystem.hpp" #include "../include/assimp/DefaultLogger.hpp" #include "../include/assimp/scene.h" @@ -130,7 +130,7 @@ void ASEImporter::SetupProperties(const Importer* pImp) void ASEImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) { - boost::scoped_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) { diff --git a/code/B3DImporter.cpp b/code/B3DImporter.cpp index 05109cacb..a8214814d 100644 --- a/code/B3DImporter.cpp +++ b/code/B3DImporter.cpp @@ -7,8 +7,8 @@ Copyright (c) 2006-2016, assimp team All rights reserved. -Redistribution and use of this software in source and binary forms, -with or without modification, are permitted provided that the following +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above @@ -25,16 +25,16 @@ conditions are met: derived from this software without specific prior written permission of the assimp team. -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --------------------------------------------------------------------------- */ @@ -51,7 +51,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "TextureTransform.h" #include "ConvertToLHProcess.h" #include "StringUtils.h" -#include +#include #include "../include/assimp/IOSystem.hpp" #include "../include/assimp/anim.h" #include "../include/assimp/scene.h" @@ -71,11 +71,11 @@ static const aiImporterDesc desc = { 0, 0, 0, - "b3d" + "b3d" }; // (fixme, Aramis) quick workaround to get rid of all those signed to unsigned warnings -#ifdef _MSC_VER +#ifdef _MSC_VER # pragma warning (disable: 4018) #endif @@ -114,7 +114,7 @@ void B3DImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS cout<<"Hello world from the B3DImporter!"< file( pIOHandler->Open( pFile)); + std::unique_ptr file( pIOHandler->Open( pFile)); // Check whether we can read from the file if( file.get() == NULL) @@ -280,12 +280,12 @@ void B3DImporter::ReadBRUS(){ aiMaterial *mat=new aiMaterial; _materials.push_back( mat ); - + // Name aiString ainame( name ); mat->AddProperty( &ainame,AI_MATKEY_NAME ); - - // Diffuse color + + // Diffuse color mat->AddProperty( &color,1,AI_MATKEY_COLOR_DIFFUSE ); // Opacity @@ -294,16 +294,16 @@ void B3DImporter::ReadBRUS(){ // Specular color aiColor3D speccolor( shiny,shiny,shiny ); mat->AddProperty( &speccolor,1,AI_MATKEY_COLOR_SPECULAR ); - + // Specular power float specpow=shiny*128; mat->AddProperty( &specpow,1,AI_MATKEY_SHININESS ); - + // Double sided if( fx & 0x10 ){ - int i=1; + int i=1; mat->AddProperty( &i,1,AI_MATKEY_TWOSIDED ); - } + } //Textures for( int i=0;imNumMaterials=_materials.size(); scene->mMaterials=to_array( _materials ); - + //meshes scene->mNumMeshes=_meshes.size(); scene->mMeshes=to_array( _meshes ); diff --git a/code/BVHLoader.cpp b/code/BVHLoader.cpp index 682ad2a9d..670379f00 100644 --- a/code/BVHLoader.cpp +++ b/code/BVHLoader.cpp @@ -47,7 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "fast_atof.h" #include "SkeletonMeshBuilder.h" #include "../include/assimp/Importer.hpp" -#include +#include #include #include "../include/assimp/IOSystem.hpp" #include "../include/assimp/scene.h" @@ -118,7 +118,7 @@ void BVHLoader::InternReadFile( const std::string& pFile, aiScene* pScene, IOSys mFileName = pFile; // read file into memory - boost::scoped_ptr file( pIOHandler->Open( pFile)); + std::unique_ptr file( pIOHandler->Open( pFile)); if( file.get() == NULL) throw DeadlyImportError( "Failed to open file " + pFile + "."); diff --git a/code/BaseImporter.cpp b/code/BaseImporter.cpp index daed1c4ca..a7e134c54 100644 --- a/code/BaseImporter.cpp +++ b/code/BaseImporter.cpp @@ -52,8 +52,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../include/assimp/postprocess.h" #include #include -#include -#include +#include #include #include @@ -149,10 +148,10 @@ void BaseImporter::GetExtensionList(std::set& extensions) if (!pIOHandler) return false; - boost::scoped_ptr pStream (pIOHandler->Open(pFile)); + std::unique_ptr pStream (pIOHandler->Open(pFile)); if (pStream.get() ) { // read 200 characters from the file - boost::scoped_array _buffer (new char[searchBytes+1 /* for the '\0' */]); + std::unique_ptr _buffer (new char[searchBytes+1 /* for the '\0' */]); char* buffer = _buffer.get(); if( NULL == buffer ) { return false; @@ -256,7 +255,7 @@ void BaseImporter::GetExtensionList(std::set& extensions) const uint32_t* magic_u32; }; magic = reinterpret_cast(_magic); - boost::scoped_ptr pStream (pIOHandler->Open(pFile)); + std::unique_ptr pStream (pIOHandler->Open(pFile)); if (pStream.get() ) { // skip to offset diff --git a/code/BlenderDNA.cpp b/code/BlenderDNA.cpp index a91c9f33d..4a0cb7753 100644 --- a/code/BlenderDNA.cpp +++ b/code/BlenderDNA.cpp @@ -268,17 +268,17 @@ void DNA :: DumpToFile() } // ------------------------------------------------------------------------------------------------ -boost::shared_ptr< ElemBase > DNA :: ConvertBlobToStructure( +std::shared_ptr< ElemBase > DNA :: ConvertBlobToStructure( const Structure& structure, const FileDatabase& db ) const { std::map::const_iterator it = converters.find(structure.name); if (it == converters.end()) { - return boost::shared_ptr< ElemBase >(); + return std::shared_ptr< ElemBase >(); } - boost::shared_ptr< ElemBase > ret = (structure.*((*it).second.first))(); + std::shared_ptr< ElemBase > ret = (structure.*((*it).second.first))(); (structure.*((*it).second.second))(ret,db); return ret; diff --git a/code/BlenderDNA.h b/code/BlenderDNA.h index 98095391b..c5d85e43c 100644 --- a/code/BlenderDNA.h +++ b/code/BlenderDNA.h @@ -50,7 +50,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "StreamReader.h" #include "../include/assimp/DefaultLogger.hpp" #include -#include +#include // enable verbose log output. really verbose, so be careful. @@ -97,7 +97,7 @@ struct ElemBase * string points is the `c_str` of the `name` attribute of the * corresponding `Structure`, that is, it is only valid as long * as the DNA is not modified. The dna_type is only set if the - * data type is not static, i.e. a boost::shared_ptr + * data type is not static, i.e. a std::shared_ptr * in the scene description would have its type resolved * at runtime, so this member is always set. */ const char* dna_type; @@ -127,7 +127,7 @@ struct FileOffset // ------------------------------------------------------------------------------- /** Dummy derivate of std::vector to be able to use it in templates simultaenously - * with boost::shared_ptr, which takes only one template argument + * with std::shared_ptr, which takes only one template argument * while std::vector takes three. Also we need to provide some special member * functions of shared_ptr */ // ------------------------------------------------------------------------------- @@ -260,11 +260,11 @@ public: // -------------------------------------------------------- // generic converter template - void Convert(boost::shared_ptr in,const FileDatabase& db) const; + void Convert(std::shared_ptr in,const FileDatabase& db) const; // -------------------------------------------------------- // generic allocator - template boost::shared_ptr Allocate() const; + template std::shared_ptr Allocate() const; @@ -282,7 +282,7 @@ public: // -------------------------------------------------------- // field parsing for pointer or dynamic array types - // (boost::shared_ptr or boost::shared_array) + // (std::shared_ptr) // The return value indicates whether the data was already cached. template class TOUT, typename T> bool ReadFieldPtr(TOUT& out, const char* name, @@ -291,7 +291,7 @@ public: // -------------------------------------------------------- // field parsing for static arrays of pointer or dynamic - // array types (boost::shared_ptr[] or boost::shared_array[]) + // array types (std::shared_ptr[]) // The return value indicates whether the data was already cached. template class TOUT, typename T, size_t N> bool ReadFieldPtr(TOUT (&out)[N], const char* name, @@ -318,7 +318,7 @@ private: const FileDatabase& db, const Field& f, bool) const; // -------------------------------------------------------- - bool ResolvePointer( boost::shared_ptr< FileOffset >& out, const Pointer & ptrval, + bool ResolvePointer( std::shared_ptr< FileOffset >& out, const Pointer & ptrval, const FileDatabase& db, const Field& f, bool) const; // -------------------------------------------------------- @@ -329,8 +329,8 @@ private: private: // ------------------------------------------------------------------------------ - template T* _allocate(boost::shared_ptr& out, size_t& s) const { - out = boost::shared_ptr(new T()); + template T* _allocate(std::shared_ptr& out, size_t& s) const { + out = std::shared_ptr(new T()); s = 1; return out.get(); } @@ -394,7 +394,7 @@ template <> struct Structure :: _defaultInitializer { }; // ------------------------------------------------------------------------------------------------------- -template <> inline bool Structure :: ResolvePointer(boost::shared_ptr& out, +template <> inline bool Structure :: ResolvePointer(std::shared_ptr& out, const Pointer & ptrval, const FileDatabase& db, const Field& f, @@ -413,11 +413,11 @@ class DNA public: typedef void (Structure::*ConvertProcPtr) ( - boost::shared_ptr in, + std::shared_ptr in, const FileDatabase& ) const; - typedef boost::shared_ptr ( + typedef std::shared_ptr ( Structure::*AllocProcPtr) () const; typedef std::pair< AllocProcPtr, ConvertProcPtr > FactoryPair; @@ -464,7 +464,7 @@ public: * @param structure Destination structure definition * @param db File database. * @return A null pointer if no appropriate converter is available.*/ - boost::shared_ptr< ElemBase > ConvertBlobToStructure( + std::shared_ptr< ElemBase > ConvertBlobToStructure( const Structure& structure, const FileDatabase& db ) const; @@ -724,7 +724,7 @@ public: bool little; DNA dna; - boost::shared_ptr< StreamReaderAny > reader; + std::shared_ptr< StreamReaderAny > reader; vector< FileBlockHead > entries; public: @@ -738,7 +738,7 @@ public: // arrays of objects are never cached because we can't easily // ensure their proper destruction. template - ObjectCache& cache(boost::shared_ptr& /*in*/) const { + ObjectCache& cache(std::shared_ptr& /*in*/) const { return _cache; } @@ -755,7 +755,7 @@ private: #endif mutable ObjectCache _cacheArrays; - mutable ObjectCache _cache; + mutable ObjectCache _cache; mutable size_t next_cache_idx; }; diff --git a/code/BlenderDNA.inl b/code/BlenderDNA.inl index f23d723ee..0b3f2fd02 100644 --- a/code/BlenderDNA.inl +++ b/code/BlenderDNA.inl @@ -5,8 +5,8 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2016, assimp team All rights reserved. -Redistribution and use of this software in source and binary forms, -with or without modification, are permitted provided that the +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above @@ -23,29 +23,29 @@ following conditions are met: derived from this software without specific prior written permission of the assimp team. -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ---------------------------------------------------------------------- */ /** @file BlenderDNA.inl - * @brief Blender `DNA` (file format specification embedded in + * @brief Blender `DNA` (file format specification embedded in * blend file itself) loader. */ #ifndef INCLUDED_AI_BLEND_DNA_INL #define INCLUDED_AI_BLEND_DNA_INL -#include +#include namespace Assimp { namespace Blender { @@ -71,7 +71,7 @@ const Field* Structure :: Get (const std::string& ss) const } //-------------------------------------------------------------------------------- -const Field& Structure :: operator [] (const size_t i) const +const Field& Structure :: operator [] (const size_t i) const { if (i >= fields.size()) { throw Error((Formatter::format(), @@ -83,15 +83,15 @@ const Field& Structure :: operator [] (const size_t i) const } //-------------------------------------------------------------------------------- -template boost::shared_ptr Structure :: Allocate() const +template std::shared_ptr Structure :: Allocate() const { - return boost::shared_ptr(new T()); + return std::shared_ptr(new T()); } //-------------------------------------------------------------------------------- template void Structure :: Convert( - boost::shared_ptr in, - const FileDatabase& db) const + std::shared_ptr in, + const FileDatabase& db) const { Convert (*static_cast ( in.get() ),db); } @@ -226,7 +226,7 @@ bool Structure :: ReadFieldPtr(TOUT& out, const char* name, const FileDatabas //-------------------------------------------------------------------------------- template class TOUT, typename T, size_t N> -bool Structure :: ReadFieldPtr(TOUT (&out)[N], const char* name, +bool Structure :: ReadFieldPtr(TOUT (&out)[N], const char* name, const FileDatabase& db) const { // XXX see if we can reduce this to call to the 'normal' ReadFieldPtr @@ -306,12 +306,12 @@ void Structure :: ReadField(T& out, const char* name, const FileDatabase& db) co //-------------------------------------------------------------------------------- template