diff --git a/CMakeLists.txt b/CMakeLists.txt index 59b79d1c6..16b1f9620 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -589,11 +589,13 @@ IF ( ASSIMP_BUILD_ASSIMP_TOOLS ) ADD_SUBDIRECTORY( tools/assimp_view/ ) ENDIF () ENDIF () - # Te command line tool + # The command line tool ADD_SUBDIRECTORY( tools/assimp_cmd/ ) ENDIF () IF ( ASSIMP_BUILD_SAMPLES) + SET( SAMPLES_DIR ${CMAKE_CURRENT_SOURCE_DIR}/samples ) + SET( SAMPLES_SHARED_CODE_DIR ${SAMPLES_DIR}/SharedCode ) IF ( WIN32 ) ADD_SUBDIRECTORY( samples/SimpleTexturedOpenGL/ ) ADD_SUBDIRECTORY( samples/SimpleTexturedDirectx11 ) diff --git a/assimp.pc.in b/assimp.pc.in index c659e19f2..02cf59dc4 100644 --- a/assimp.pc.in +++ b/assimp.pc.in @@ -1,7 +1,7 @@ prefix=@CMAKE_INSTALL_PREFIX@ exec_prefix=@CMAKE_INSTALL_PREFIX@/ libdir=@CMAKE_INSTALL_PREFIX@/@ASSIMP_LIB_INSTALL_DIR@ -includedir=@CMAKE_INSTALL_PREFIX@/../include/@ASSIMP_INCLUDE_INSTALL_DIR@ +includedir=@CMAKE_INSTALL_PREFIX@/@ASSIMP_INCLUDE_INSTALL_DIR@ Name: @CMAKE_PROJECT_NAME@ Description: Import various well-known 3D model formats in an uniform manner. diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index 0cef480f2..0dff5d9e4 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -185,8 +185,6 @@ SET( Common_SRCS Common/ScenePreprocessor.cpp Common/ScenePreprocessor.h Common/SkeletonMeshBuilder.cpp - Common/SplitByBoneCountProcess.cpp - Common/SplitByBoneCountProcess.h Common/StandardShapes.cpp Common/TargetAnimation.cpp Common/TargetAnimation.h @@ -252,35 +250,39 @@ MACRO(ADD_ASSIMP_IMPORTER name) ENDIF() ENDMACRO() -# if this variable is set to TRUE, the user can manually disable exporters by setting -# ASSIMP_BUILD_XXX_EXPORTER to FALSE for each exporter -# if this variable is set to FALSE, the user can manually enable exporters by setting -# ASSIMP_BUILD_XXX_EXPORTER to TRUE for each exporter -OPTION(ASSIMP_BUILD_ALL_EXPORTERS_BY_DEFAULT "default value of all ASSIMP_BUILD_XXX_EXPORTER values" TRUE) +if (NOT ASSIMP_NO_EXPORT) -# macro to add the CMake Option ADD_ASSIMP_IMPORTER_ which enables compile of loader -# this way selective loaders can be compiled (reduces filesize + compile time) -MACRO(ADD_ASSIMP_EXPORTER name) - IF (ASSIMP_NO_EXPORT) - set(ASSIMP_EXPORTER_ENABLED FALSE) - ELSEIF (ASSIMP_BUILD_ALL_EXPORTERS_BY_DEFAULT) - set(ASSIMP_EXPORTER_ENABLED TRUE) - IF (DEFINED ASSIMP_BUILD_${name}_EXPORTER AND NOT ASSIMP_BUILD_${name}_EXPORTER) + # if this variable is set to TRUE, the user can manually disable exporters by setting + # ASSIMP_BUILD_XXX_EXPORTER to FALSE for each exporter + # if this variable is set to FALSE, the user can manually enable exporters by setting + # ASSIMP_BUILD_XXX_EXPORTER to TRUE for each exporter + OPTION(ASSIMP_BUILD_ALL_EXPORTERS_BY_DEFAULT "default value of all ASSIMP_BUILD_XXX_EXPORTER values" TRUE) + + # macro to add the CMake Option ADD_ASSIMP_IMPORTER_ which enables compile of loader + # this way selective loaders can be compiled (reduces filesize + compile time) + MACRO(ADD_ASSIMP_EXPORTER name) + IF (ASSIMP_NO_EXPORT) set(ASSIMP_EXPORTER_ENABLED FALSE) + ELSEIF (ASSIMP_BUILD_ALL_EXPORTERS_BY_DEFAULT) + set(ASSIMP_EXPORTER_ENABLED TRUE) + IF (DEFINED ASSIMP_BUILD_${name}_EXPORTER AND NOT ASSIMP_BUILD_${name}_EXPORTER) + set(ASSIMP_EXPORTER_ENABLED FALSE) + ENDIF () + ELSE () + set(ASSIMP_EXPORTER_ENABLED ${ASSIMP_BUILD_${name}_EXPORTER}) ENDIF () - ELSE () - set(ASSIMP_EXPORTER_ENABLED ${ASSIMP_BUILD_${name}_EXPORTER}) - ENDIF () - IF (ASSIMP_EXPORTER_ENABLED) - SET(ASSIMP_EXPORTERS_ENABLED "${ASSIMP_EXPORTERS_ENABLED} ${name}") - LIST(APPEND ASSIMP_EXPORTER_SRCS ${ARGN}) - SOURCE_GROUP(${name}_EXPORTER FILES ${ARGN}) - ELSE() - SET(ASSIMP_EXPORTERS_DISABLED "${ASSIMP_EXPORTERS_DISABLED} ${name}") - add_definitions(-DASSIMP_BUILD_NO_${name}_EXPORTER) - ENDIF() -ENDMACRO() + IF (ASSIMP_EXPORTER_ENABLED) + SET(ASSIMP_EXPORTERS_ENABLED "${ASSIMP_EXPORTERS_ENABLED} ${name}") + LIST(APPEND ASSIMP_EXPORTER_SRCS ${ARGN}) + SOURCE_GROUP(${name}_EXPORTER FILES ${ARGN}) + ELSE() + SET(ASSIMP_EXPORTERS_DISABLED "${ASSIMP_EXPORTERS_DISABLED} ${name}") + add_definitions(-DASSIMP_BUILD_NO_${name}_EXPORTER) + ENDIF() + ENDMACRO() + +endif() SET(ASSIMP_LOADER_SRCS "") SET(ASSIMP_IMPORTERS_ENABLED "") # list of enabled importers @@ -307,11 +309,6 @@ ADD_ASSIMP_IMPORTER( 3DS 3DS/3DSLoader.h ) -ADD_ASSIMP_EXPORTER( 3DS - 3DS/3DSExporter.h - 3DS/3DSExporter.cpp -) - ADD_ASSIMP_IMPORTER( AC AC/ACLoader.cpp AC/ACLoader.h @@ -329,20 +326,6 @@ ADD_ASSIMP_IMPORTER( ASSBIN Assbin/AssbinLoader.cpp ) -ADD_ASSIMP_EXPORTER( ASSBIN - Assbin/AssbinExporter.h - Assbin/AssbinExporter.cpp - Assbin/AssbinFileWriter.h - Assbin/AssbinFileWriter.cpp -) - -ADD_ASSIMP_EXPORTER( ASSXML - Assxml/AssxmlExporter.h - Assxml/AssxmlExporter.cpp - Assxml/AssxmlFileWriter.h - Assxml/AssxmlFileWriter.cpp -) - ADD_ASSIMP_IMPORTER( B3D B3D/B3DImporter.cpp B3D/B3DImporter.h @@ -362,11 +345,6 @@ ADD_ASSIMP_IMPORTER( COLLADA Collada/ColladaParser.h ) -ADD_ASSIMP_EXPORTER( COLLADA - Collada/ColladaExporter.h - Collada/ColladaExporter.cpp -) - ADD_ASSIMP_IMPORTER( DXF DXF/DXFLoader.cpp DXF/DXFLoader.h @@ -423,11 +401,6 @@ ADD_ASSIMP_IMPORTER( M3D M3D/m3d.h ) -ADD_ASSIMP_EXPORTER( M3D - M3D/M3DExporter.h - M3D/M3DExporter.cpp -) - ADD_ASSIMP_IMPORTER( MD2 MD2/MD2FileData.h MD2/MD2Loader.cpp @@ -505,11 +478,6 @@ ADD_ASSIMP_IMPORTER( OBJ Obj/ObjTools.h ) -ADD_ASSIMP_EXPORTER( OBJ - Obj/ObjExporter.h - Obj/ObjExporter.cpp -) - ADD_ASSIMP_IMPORTER( OGRE Ogre/OgreImporter.h Ogre/OgreStructs.h @@ -529,11 +497,6 @@ ADD_ASSIMP_IMPORTER( OPENGEX OpenGEX/OpenGEXStructs.h ) -ADD_ASSIMP_EXPORTER( OPENGEX - OpenGEX/OpenGEXExporter.cpp - OpenGEX/OpenGEXExporter.h -) - ADD_ASSIMP_IMPORTER( PLY Ply/PlyLoader.cpp Ply/PlyLoader.h @@ -541,11 +504,6 @@ ADD_ASSIMP_IMPORTER( PLY Ply/PlyParser.h ) -ADD_ASSIMP_EXPORTER( PLY - Ply/PlyExporter.cpp - Ply/PlyExporter.h -) - ADD_ASSIMP_IMPORTER( MS3D MS3D/MS3DLoader.cpp MS3D/MS3DLoader.h @@ -635,14 +593,86 @@ ADD_ASSIMP_IMPORTER( FBX FBX/FBXCommon.h ) -ADD_ASSIMP_EXPORTER( FBX - FBX/FBXExporter.h - FBX/FBXExporter.cpp - FBX/FBXExportNode.h - FBX/FBXExportNode.cpp - FBX/FBXExportProperty.h - FBX/FBXExportProperty.cpp -) +if (NOT ASSIMP_NO_EXPORT) + + ADD_ASSIMP_EXPORTER( OBJ + Obj/ObjExporter.h + Obj/ObjExporter.cpp) + + ADD_ASSIMP_EXPORTER( OPENGEX + OpenGEX/OpenGEXExporter.cpp + OpenGEX/OpenGEXExporter.h) + + ADD_ASSIMP_EXPORTER( PLY + Ply/PlyExporter.cpp + Ply/PlyExporter.h) + + ADD_ASSIMP_EXPORTER( 3DS + 3DS/3DSExporter.h + 3DS/3DSExporter.cpp) + + ADD_ASSIMP_EXPORTER( ASSBIN + Assbin/AssbinExporter.h + Assbin/AssbinExporter.cpp + Assbin/AssbinFileWriter.h + Assbin/AssbinFileWriter.cpp) + + ADD_ASSIMP_EXPORTER( ASSXML + Assxml/AssxmlExporter.h + Assxml/AssxmlExporter.cpp + Assxml/AssxmlFileWriter.h + Assxml/AssxmlFileWriter.cpp) + + ADD_ASSIMP_EXPORTER(M3D + M3D/M3DExporter.h + M3D/M3DExporter.cpp) + + ADD_ASSIMP_EXPORTER(COLLADA + Collada/ColladaExporter.h + Collada/ColladaExporter.cpp) + + ADD_ASSIMP_EXPORTER( FBX + FBX/FBXExporter.h + FBX/FBXExporter.cpp + FBX/FBXExportNode.h + FBX/FBXExportNode.cpp + FBX/FBXExportProperty.h + FBX/FBXExportProperty.cpp) + + ADD_ASSIMP_EXPORTER( STL + STL/STLExporter.h + STL/STLExporter.cpp) + + ADD_ASSIMP_EXPORTER( X + X/XFileExporter.h + X/XFileExporter.cpp) + + ADD_ASSIMP_EXPORTER( X3D + X3D/X3DExporter.cpp + X3D/X3DExporter.hpp) + + ADD_ASSIMP_EXPORTER( GLTF + glTF/glTFExporter.h + glTF/glTFExporter.cpp + glTF2/glTF2Exporter.h + glTF2/glTF2Exporter.cpp) + + ADD_ASSIMP_EXPORTER( 3MF + 3MF/D3MFExporter.h + 3MF/D3MFExporter.cpp) + + ADD_ASSIMP_EXPORTER( ASSJSON + Assjson/cencode.c + Assjson/cencode.h + Assjson/json_exporter.cpp + Assjson/mesh_splitter.cpp + Assjson/mesh_splitter.h) + + ADD_ASSIMP_EXPORTER( STEP + Step/StepExporter.h + Step/StepExporter.cpp) + +endif() SET( PostProcessing_SRCS PostProcessing/CalcTangentsProcess.cpp @@ -705,6 +735,8 @@ SET( PostProcessing_SRCS PostProcessing/ArmaturePopulate.h PostProcessing/GenBoundingBoxesProcess.cpp PostProcessing/GenBoundingBoxesProcess.h + PostProcessing/SplitByBoneCountProcess.cpp + PostProcessing/SplitByBoneCountProcess.h ) SOURCE_GROUP( PostProcessing FILES ${PostProcessing_SRCS}) @@ -744,11 +776,6 @@ ADD_ASSIMP_IMPORTER( STL STL/STLLoader.h ) -ADD_ASSIMP_EXPORTER( STL - STL/STLExporter.h - STL/STLExporter.cpp -) - ADD_ASSIMP_IMPORTER( TERRAGEN Terragen/TerragenLoader.cpp Terragen/TerragenLoader.h @@ -767,11 +794,6 @@ ADD_ASSIMP_IMPORTER( X X/XFileParser.h ) -ADD_ASSIMP_EXPORTER( X - X/XFileExporter.h - X/XFileExporter.cpp -) - ADD_ASSIMP_IMPORTER( X3D X3D/X3DImporter.cpp X3D/X3DImporter.hpp @@ -792,11 +814,6 @@ ADD_ASSIMP_IMPORTER( X3D X3D/X3DVocabulary.cpp ) -ADD_ASSIMP_EXPORTER( X3D - X3D/X3DExporter.cpp - X3D/X3DExporter.hpp -) - ADD_ASSIMP_IMPORTER( GLTF glTF/glTFCommon.h glTF/glTFCommon.cpp @@ -814,13 +831,6 @@ ADD_ASSIMP_IMPORTER( GLTF glTF2/glTF2Importer.h ) -ADD_ASSIMP_EXPORTER( GLTF - glTF/glTFExporter.h - glTF/glTFExporter.cpp - glTF2/glTF2Exporter.h - glTF2/glTF2Exporter.cpp -) - ADD_ASSIMP_IMPORTER( 3MF 3MF/D3MFImporter.h 3MF/D3MFImporter.cpp @@ -829,11 +839,6 @@ ADD_ASSIMP_IMPORTER( 3MF 3MF/3MFXmlTags.h ) -ADD_ASSIMP_EXPORTER( 3MF - 3MF/D3MFExporter.h - 3MF/D3MFExporter.cpp -) - ADD_ASSIMP_IMPORTER( MMD MMD/MMDCpp14.h MMD/MMDImporter.cpp @@ -844,14 +849,6 @@ ADD_ASSIMP_IMPORTER( MMD MMD/MMDVmdParser.h ) -ADD_ASSIMP_EXPORTER( ASSJSON - Assjson/cencode.c - Assjson/cencode.h - Assjson/json_exporter.cpp - Assjson/mesh_splitter.cpp - Assjson/mesh_splitter.h -) - # Workaround for issue #2406 - force problematic large file to be optimized to prevent string table overflow error # Used -Os instead of -O2 as previous issues had mentioned, since -Os is roughly speaking -O2, excluding any # optimizations that take up extra space. Given that the issue is a string table overflowing, -Os seemed appropriate @@ -874,11 +871,6 @@ ADD_ASSIMP_IMPORTER( STEP Importer/StepFile/StepReaderGen.h ) -ADD_ASSIMP_EXPORTER( STEP - Step/StepExporter.h - Step/StepExporter.cpp -) - if ((NOT ASSIMP_NO_EXPORT) OR (NOT ASSIMP_EXPORTERS_ENABLED STREQUAL "")) SET( Exporter_SRCS Common/Exporter.cpp @@ -1088,8 +1080,10 @@ ENDIF() MESSAGE(STATUS "Enabled importer formats:${ASSIMP_IMPORTERS_ENABLED}") MESSAGE(STATUS "Disabled importer formats:${ASSIMP_IMPORTERS_DISABLED}") -MESSAGE(STATUS "Enabled exporter formats:${ASSIMP_EXPORTERS_ENABLED}") -MESSAGE(STATUS "Disabled exporter formats:${ASSIMP_EXPORTERS_DISABLED}") +if (NOT ASSIMP_NO_EXPORT) + MESSAGE(STATUS "Enabled exporter formats:${ASSIMP_EXPORTERS_ENABLED}") + MESSAGE(STATUS "Disabled exporter formats:${ASSIMP_EXPORTERS_DISABLED}") +endif() SOURCE_GROUP( include\\assimp FILES ${PUBLIC_HEADERS} ) diff --git a/code/Common/BaseProcess.cpp b/code/Common/BaseProcess.cpp index 974af68db..d02653cf2 100644 --- a/code/Common/BaseProcess.cpp +++ b/code/Common/BaseProcess.cpp @@ -5,8 +5,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2020, assimp team - - All rights reserved. Redistribution and use of this software in source and binary forms, @@ -43,45 +41,43 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /** @file Implementation of BaseProcess */ -#include #include "BaseProcess.h" -#include -#include #include "Importer.h" +#include +#include +#include using namespace Assimp; // ------------------------------------------------------------------------------------------------ // Constructor to be privately used by Importer BaseProcess::BaseProcess() AI_NO_EXCEPT -: shared() -, progress() -{ + : shared(), + progress() { + // empty } // ------------------------------------------------------------------------------------------------ // Destructor, private as well -BaseProcess::~BaseProcess() -{ +BaseProcess::~BaseProcess() { // nothing to do here } // ------------------------------------------------------------------------------------------------ -void BaseProcess::ExecuteOnScene( Importer* pImp) -{ - ai_assert(NULL != pImp && NULL != pImp->Pimpl()->mScene); +void BaseProcess::ExecuteOnScene(Importer *pImp) { + ai_assert( nullptr != pImp ); + ai_assert( nullptr != pImp->Pimpl()->mScene); progress = pImp->GetProgressHandler(); - ai_assert(progress); + ai_assert(nullptr != progress); - SetupProperties( pImp ); + SetupProperties(pImp); // catch exceptions thrown inside the PostProcess-Step - try - { + try { Execute(pImp->Pimpl()->mScene); - } catch( const std::exception& err ) { + } catch (const std::exception &err) { // extract error description pImp->Pimpl()->mErrorString = err.what(); @@ -94,14 +90,11 @@ void BaseProcess::ExecuteOnScene( Importer* pImp) } // ------------------------------------------------------------------------------------------------ -void BaseProcess::SetupProperties(const Importer* /*pImp*/) -{ +void BaseProcess::SetupProperties(const Importer * /*pImp*/) { // the default implementation does nothing } // ------------------------------------------------------------------------------------------------ -bool BaseProcess::RequireVerboseFormat() const -{ +bool BaseProcess::RequireVerboseFormat() const { return true; } - diff --git a/code/Common/BaseProcess.h b/code/Common/BaseProcess.h index a7e48bba3..bf1f2586f 100644 --- a/code/Common/BaseProcess.h +++ b/code/Common/BaseProcess.h @@ -4,7 +4,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2020, assimp team - All rights reserved. Redistribution and use of this software in source and binary forms, @@ -44,12 +43,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef INCLUDED_AI_BASEPROCESS_H #define INCLUDED_AI_BASEPROCESS_H -#include #include +#include + struct aiScene; -namespace Assimp { +namespace Assimp { class Importer; @@ -60,64 +60,50 @@ class Importer; * to provide additional information to other steps. This is primarily * intended for cross-step optimizations. */ -class SharedPostProcessInfo -{ +class SharedPostProcessInfo { public: - - struct Base - { - virtual ~Base() - {} + struct Base { + virtual ~Base() {} }; //! Represents data that is allocated on the heap, thus needs to be deleted template - struct THeapData : public Base - { - explicit THeapData(T* in) - : data (in) - {} + struct THeapData : public Base { + explicit THeapData(T *in) : + data(in) {} - ~THeapData() - { + ~THeapData() { delete data; } - T* data; + T *data; }; //! Represents static, by-value data not allocated on the heap template - struct TStaticData : public Base - { - explicit TStaticData(T in) - : data (in) - {} + struct TStaticData : public Base { + explicit TStaticData(T in) : + data(in) {} - ~TStaticData() - {} + ~TStaticData() {} T data; }; // some typedefs for cleaner code typedef unsigned int KeyType; - typedef std::map PropertyMap; + typedef std::map PropertyMap; public: - //! Destructor - ~SharedPostProcessInfo() - { + ~SharedPostProcessInfo() { Clean(); } //! Remove all stored properties from the table - void Clean() - { + void Clean() { // invoke the virtual destructor for all stored properties for (PropertyMap::iterator it = pmap.begin(), end = pmap.end(); - it != end; ++it) - { + it != end; ++it) { delete (*it).second; } pmap.clear(); @@ -125,24 +111,21 @@ public: //! Add a heap property to the list template - void AddProperty( const char* name, T* in ){ - AddProperty(name,(Base*)new THeapData(in)); + void AddProperty(const char *name, T *in) { + AddProperty(name, (Base *)new THeapData(in)); } //! Add a static by-value property to the list template - void AddProperty( const char* name, T in ){ - AddProperty(name,(Base*)new TStaticData(in)); + void AddProperty(const char *name, T in) { + AddProperty(name, (Base *)new TStaticData(in)); } - //! Get a heap property template - bool GetProperty( const char* name, T*& out ) const - { - THeapData* t = (THeapData*)GetPropertyInternal(name); - if(!t) - { + bool GetProperty(const char *name, T *&out) const { + THeapData *t = (THeapData *)GetPropertyInternal(name); + if (!t) { out = NULL; return false; } @@ -152,53 +135,34 @@ public: //! Get a static, by-value property template - bool GetProperty( const char* name, T& out ) const - { - TStaticData* t = (TStaticData*)GetPropertyInternal(name); - if(!t)return false; + bool GetProperty(const char *name, T &out) const { + TStaticData *t = (TStaticData *)GetPropertyInternal(name); + if ( nullptr == t) { + return false; + } out = t->data; return true; } //! Remove a property of a specific type - void RemoveProperty( const char* name) { - SetGenericPropertyPtr(pmap,name,NULL); + void RemoveProperty(const char *name) { + SetGenericPropertyPtr(pmap, name, nullptr ); } private: - - void AddProperty( const char* name, Base* data) { - SetGenericPropertyPtr(pmap,name,data); + void AddProperty(const char *name, Base *data) { + SetGenericPropertyPtr(pmap, name, data); } - Base* GetPropertyInternal( const char* name) const { - return GetGenericProperty(pmap,name,NULL); + Base *GetPropertyInternal(const char *name) const { + return GetGenericProperty(pmap, name, nullptr ); } private: - //! Map of all stored properties PropertyMap pmap; }; -#if 0 - -// --------------------------------------------------------------------------- -/** @brief Represents a dependency table for a postprocessing steps. - * - * For future use. - */ - struct PPDependencyTable - { - unsigned int execute_me_before_these; - unsigned int execute_me_after_these; - unsigned int only_if_these_are_not_specified; - unsigned int mutually_exclusive_with; - }; - -#endif - - #define AI_SPP_SPATIAL_SORT "$Spat" // --------------------------------------------------------------------------- @@ -228,7 +192,7 @@ public: * @return true if the process is present in this flag fields, * false if not. */ - virtual bool IsActive( unsigned int pFlags) const = 0; + virtual bool IsActive(unsigned int pFlags) const = 0; // ------------------------------------------------------------------- /** Check whether this step expects its input vertex data to be @@ -241,14 +205,14 @@ public: * the object pointer will be set to NULL). * @param pImp Importer instance (pImp->mScene must be valid) */ - void ExecuteOnScene( Importer* pImp); + void ExecuteOnScene(Importer *pImp); // ------------------------------------------------------------------- /** Called prior to ExecuteOnScene(). * The function is a request to the process to update its configuration * basing on the Importer's configuration property list. */ - virtual void SetupProperties(const Importer* pImp); + virtual void SetupProperties(const Importer *pImp); // ------------------------------------------------------------------- /** Executes the post processing step on the given imported data. @@ -256,35 +220,32 @@ public: * This method must be implemented by deriving classes. * @param pScene The imported data to work at. */ - virtual void Execute( aiScene* pScene) = 0; - + virtual void Execute(aiScene *pScene) = 0; // ------------------------------------------------------------------- /** Assign a new SharedPostProcessInfo to the step. This object * allows multiple postprocess steps to share data. * @param sh May be NULL */ - inline void SetSharedData(SharedPostProcessInfo* sh) { + inline void SetSharedData(SharedPostProcessInfo *sh) { shared = sh; } // ------------------------------------------------------------------- /** Get the shared data that is assigned to the step. */ - inline SharedPostProcessInfo* GetSharedData() { + inline SharedPostProcessInfo *GetSharedData() { return shared; } protected: - /** See the doc of #SharedPostProcessInfo for more details */ - SharedPostProcessInfo* shared; + SharedPostProcessInfo *shared; /** Currently active progress handler */ - ProgressHandler* progress; + ProgressHandler *progress; }; - } // end of namespace Assimp #endif // AI_BASEPROCESS_H_INC diff --git a/code/Common/PostStepRegistry.cpp b/code/Common/PostStepRegistry.cpp index 21bd2af95..19382165f 100644 --- a/code/Common/PostStepRegistry.cpp +++ b/code/Common/PostStepRegistry.cpp @@ -123,7 +123,7 @@ corresponding preprocessor flag to selectively disable steps. # include "PostProcessing/OptimizeGraph.h" #endif #ifndef ASSIMP_BUILD_NO_SPLITBYBONECOUNT_PROCESS -# include "Common/SplitByBoneCountProcess.h" +# include "PostProcessing/SplitByBoneCountProcess.h" #endif #ifndef ASSIMP_BUILD_NO_DEBONE_PROCESS # include "PostProcessing/DeboneProcess.h" diff --git a/code/Common/SplitByBoneCountProcess.cpp b/code/PostProcessing/SplitByBoneCountProcess.cpp similarity index 95% rename from code/Common/SplitByBoneCountProcess.cpp rename to code/PostProcessing/SplitByBoneCountProcess.cpp index b472cb359..ab7a1fe00 100644 --- a/code/Common/SplitByBoneCountProcess.cpp +++ b/code/PostProcessing/SplitByBoneCountProcess.cpp @@ -51,6 +51,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include +#include using namespace Assimp; using namespace Assimp::Formatter; @@ -94,7 +95,10 @@ void SplitByBoneCountProcess::Execute( aiScene* pScene) bool isNecessary = false; for( unsigned int a = 0; a < pScene->mNumMeshes; ++a) if( pScene->mMeshes[a]->mNumBones > mMaxBoneCount ) + { isNecessary = true; + break; + } if( !isNecessary ) { @@ -155,7 +159,9 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vectormNumBones <= mMaxBoneCount ) + { return; + } // necessary optimisation: build a list of all affecting bones for each vertex // TODO: (thom) maybe add a custom allocator here to avoid allocating tens of thousands of small arrays @@ -165,7 +171,9 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vectormBones[a]; for( unsigned int b = 0; b < bone->mNumWeights; ++b) + { vertexBones[ bone->mWeights[b].mVertexId ].push_back( BoneWeight( a, bone->mWeights[b].mWeight)); + } } unsigned int numFacesHandled = 0; @@ -189,7 +197,9 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vectormFaces[a]; // check every vertex if its bones would still fit into the current submesh @@ -201,17 +211,27 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vector mMaxBoneCount) + { + throw DeadlyImportError("SplitByBoneCountProcess: Single face requires more bones than specified max bone count!"); + } // leave out the face if the new bones required for this face don't fit the bone count limit anymore if( numBones + newBonesAtCurrentFace.size() > mMaxBoneCount ) + { continue; + } // mark all new bones as necessary while( !newBonesAtCurrentFace.empty() ) @@ -219,7 +239,9 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vectormName.length > 0 ) + { newMesh->mName.Set( format() << pMesh->mName.data << "_sub" << poNewMeshes.size()); + } newMesh->mMaterialIndex = pMesh->mMaterialIndex; newMesh->mPrimitiveTypes = pMesh->mPrimitiveTypes; poNewMeshes.push_back( newMesh); @@ -247,7 +271,9 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vectormNumFaces = static_cast(subMeshFaces.size()); newMesh->mVertices = new aiVector3D[newMesh->mNumVertices]; if( pMesh->HasNormals() ) + { newMesh->mNormals = new aiVector3D[newMesh->mNumVertices]; + } if( pMesh->HasTangentsAndBitangents() ) { newMesh->mTangents = new aiVector3D[newMesh->mNumVertices]; @@ -256,13 +282,17 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vectorHasTextureCoords( a) ) + { newMesh->mTextureCoords[a] = new aiVector3D[newMesh->mNumVertices]; + } newMesh->mNumUVComponents[a] = pMesh->mNumUVComponents[a]; } for( unsigned int a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; ++a ) { if( pMesh->HasVertexColors( a) ) + { newMesh->mColors[a] = new aiColor4D[newMesh->mNumVertices]; + } } // and copy over the data, generating faces with linear indices along the way @@ -285,7 +315,9 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vectormVertices[nvi] = pMesh->mVertices[srcIndex]; if( pMesh->HasNormals() ) + { newMesh->mNormals[nvi] = pMesh->mNormals[srcIndex]; + } if( pMesh->HasTangentsAndBitangents() ) { newMesh->mTangents[nvi] = pMesh->mTangents[srcIndex]; @@ -294,12 +326,16 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vectorHasTextureCoords( c) ) + { newMesh->mTextureCoords[c][nvi] = pMesh->mTextureCoords[c][srcIndex]; + } } for( unsigned int c = 0; c < AI_MAX_NUMBER_OF_COLOR_SETS; ++c ) { if( pMesh->HasVertexColors( c) ) + { newMesh->mColors[c][nvi] = pMesh->mColors[c][srcIndex]; + } } nvi++; @@ -316,7 +352,9 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vectormNumBones; ++a ) { if( !isBoneUsed[a] ) + { continue; + } // create the new bone const aiBone* srcBone = pMesh->mBones[a]; @@ -340,7 +378,9 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vector::max() ) + { newMesh->mBones[newBoneIndex]->mNumWeights++; + } } } diff --git a/code/Common/SplitByBoneCountProcess.h b/code/PostProcessing/SplitByBoneCountProcess.h similarity index 99% rename from code/Common/SplitByBoneCountProcess.h rename to code/PostProcessing/SplitByBoneCountProcess.h index 7185d0330..b99830fde 100644 --- a/code/Common/SplitByBoneCountProcess.h +++ b/code/PostProcessing/SplitByBoneCountProcess.h @@ -46,7 +46,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define AI_SPLITBYBONECOUNTPROCESS_H_INC #include -#include "BaseProcess.h" +#include "Common/BaseProcess.h" #include #include diff --git a/code/glTF2/glTF2Importer.cpp b/code/glTF2/glTF2Importer.cpp index 5e137ed79..8c33674e1 100644 --- a/code/glTF2/glTF2Importer.cpp +++ b/code/glTF2/glTF2Importer.cpp @@ -111,8 +111,9 @@ const aiImporterDesc *glTF2Importer::GetInfo() const { bool glTF2Importer::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /* checkSig */) const { const std::string &extension = GetExtension(pFile); - if (extension != "gltf" && extension != "glb") + if (extension != "gltf" && extension != "glb") { return false; + } if (pIOHandler) { glTF2::Asset asset(pIOHandler); @@ -323,8 +324,9 @@ static inline bool CheckValidFacesIndices(aiFace *faces, unsigned nFaces, unsign for (unsigned i = 0; i < nFaces; ++i) { for (unsigned j = 0; j < faces[i].mNumIndices; ++j) { unsigned idx = faces[i].mIndices[j]; - if (idx >= nVerts) + if (idx >= nVerts) { return false; + } } } return true; @@ -861,7 +863,19 @@ aiNode *ImportNode(aiScene *pScene, glTF2::Asset &r, std::vector & if (node.skin) { for (int primitiveNo = 0; primitiveNo < count; ++primitiveNo) { aiMesh *mesh = pScene->mMeshes[meshOffsets[mesh_idx] + primitiveNo]; - mesh->mNumBones = static_cast(node.skin->jointNames.size()); + unsigned int numBones =static_cast(node.skin->jointNames.size()); + + std::vector> weighting(numBones); + BuildVertexWeightMapping(node.meshes[0]->primitives[primitiveNo], weighting); + + unsigned int realNumBones = 0; + for (uint32_t i = 0; i < numBones; ++i) { + if (weighting[i].size() > 0) { + realNumBones++; + } + } + + mesh->mNumBones = static_cast(realNumBones); mesh->mBones = new aiBone *[mesh->mNumBones]; // GLTF and Assimp choose to store bone weights differently. @@ -873,43 +887,33 @@ aiNode *ImportNode(aiScene *pScene, glTF2::Asset &r, std::vector & // both because it's somewhat slow and because, for many applications, // we then need to reconvert the data back into the vertex-to-bone // mapping which makes things doubly-slow. - std::vector> weighting(mesh->mNumBones); - BuildVertexWeightMapping(node.meshes[0]->primitives[primitiveNo], weighting); mat4 *pbindMatrices = nullptr; node.skin->inverseBindMatrices->ExtractData(pbindMatrices); - for (uint32_t i = 0; i < mesh->mNumBones; ++i) { - aiBone *bone = new aiBone(); + int cb = 0; + for (uint32_t i = 0; i < numBones; ++i) { + const std::vector &weights = weighting[i]; + if (weights.size() > 0) { + aiBone *bone = new aiBone(); - Ref joint = node.skin->jointNames[i]; - if (!joint->name.empty()) { - bone->mName = joint->name; - } else { - // Assimp expects each bone to have a unique name. - static const std::string kDefaultName = "bone_"; - char postfix[10] = { 0 }; - ASSIMP_itoa10(postfix, i); - bone->mName = (kDefaultName + postfix); - } - GetNodeTransform(bone->mOffsetMatrix, *joint); - - CopyValue(pbindMatrices[i], bone->mOffsetMatrix); - - std::vector &weights = weighting[i]; - - bone->mNumWeights = static_cast(weights.size()); - if (bone->mNumWeights > 0) { + Ref joint = node.skin->jointNames[i]; + if (!joint->name.empty()) { + bone->mName = joint->name; + } else { + // Assimp expects each bone to have a unique name. + static const std::string kDefaultName = "bone_"; + char postfix[10] = { 0 }; + ASSIMP_itoa10(postfix, i); + bone->mName = (kDefaultName + postfix); + } + GetNodeTransform(bone->mOffsetMatrix, *joint); + CopyValue(pbindMatrices[i], bone->mOffsetMatrix); + bone->mNumWeights = static_cast(weights.size()); bone->mWeights = new aiVertexWeight[bone->mNumWeights]; memcpy(bone->mWeights, weights.data(), bone->mNumWeights * sizeof(aiVertexWeight)); - } else { - // Assimp expects all bones to have at least 1 weight. - bone->mWeights = new aiVertexWeight[1]; - bone->mNumWeights = 1; - bone->mWeights->mVertexId = 0; - bone->mWeights->mWeight = 0.f; + mesh->mBones[cb++] = bone; } - mesh->mBones[i] = bone; } if (pbindMatrices) { @@ -1232,8 +1236,9 @@ void glTF2Importer::ImportEmbeddedTextures(glTF2::Asset &r) { int numEmbeddedTexs = 0; for (size_t i = 0; i < r.images.Size(); ++i) { - if (r.images[i].HasData()) + if (r.images[i].HasData()) { numEmbeddedTexs += 1; + } } if (numEmbeddedTexs == 0) @@ -1244,7 +1249,9 @@ void glTF2Importer::ImportEmbeddedTextures(glTF2::Asset &r) { // Add the embedded textures for (size_t i = 0; i < r.images.Size(); ++i) { Image &img = r.images[i]; - if (!img.HasData()) continue; + if (!img.HasData()) { + continue; + } int idx = mScene->mNumTextures++; embeddedTexIdxs[i] = idx; diff --git a/contrib/zip/CMakeLists.txt b/contrib/zip/CMakeLists.txt index 77916d2e1..f194649ed 100644 --- a/contrib/zip/CMakeLists.txt +++ b/contrib/zip/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.0) project(zip LANGUAGES C - VERSION "0.1.15") + VERSION "0.1.18") set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH}) option(CMAKE_DISABLE_TESTING "Disable test creation" OFF) @@ -16,10 +16,6 @@ elseif ("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "AppleClang") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -Wall -Wextra -Werror -pedantic") - if(ENABLE_COVERAGE) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -O0 -fprofile-arcs -ftest-coverage") - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --coverage") - endif() endif (MSVC) # zip @@ -35,7 +31,7 @@ if (NOT CMAKE_DISABLE_TESTING) enable_testing() add_subdirectory(test) find_package(Sanitizers) - add_sanitizers(${PROJECT_NAME} ${test_out} ${test_miniz_out}) + add_sanitizers(${PROJECT_NAME} ${test_out}) endif() #### diff --git a/contrib/zip/README.md b/contrib/zip/README.md index 14eb9a34c..bdd0822b6 100644 --- a/contrib/zip/README.md +++ b/contrib/zip/README.md @@ -1,10 +1,8 @@ ### A portable (OSX/Linux/Windows), simple zip library written in C This is done by hacking awesome [miniz](https://code.google.com/p/miniz) library and layering functions on top of the miniz v1.15 API. -[![Windows](https://ci.appveyor.com/api/projects/status/bph8dr3jacgmjv32/branch/master?svg=true&label=windows)](https://ci.appveyor.com/project/kuba--/zip) -[![Linux](https://travis-ci.org/kuba--/zip.svg?branch=master&label=linux%2fosx)](https://travis-ci.org/kuba--/zip) +[![Build](https://github.com/kuba--/zip/workflows/build/badge.svg)](https://github.com/kuba--/zip/actions?query=workflow%3Abuild) [![Version](https://badge.fury.io/gh/kuba--%2Fzip.svg)](https://github.com/kuba--/zip/releases) -[![Codecov](https://codecov.io/gh/kuba--/zip/branch/master/graph/badge.svg)](https://codecov.io/gh/kuba--/zip) # The Idea @@ -213,6 +211,53 @@ func main() { } ``` +### Rust (ffi) +```rust +extern crate libc; +use std::ffi::CString; + +#[repr(C)] +pub struct Zip { + _private: [u8; 0], +} + +#[link(name = "zip")] +extern "C" { + fn zip_open(path: *const libc::c_char, level: libc::c_int, mode: libc::c_char) -> *mut Zip; + fn zip_close(zip: *mut Zip) -> libc::c_void; + + fn zip_entry_open(zip: *mut Zip, entryname: *const libc::c_char) -> libc::c_int; + fn zip_entry_close(zip: *mut Zip) -> libc::c_int; + fn zip_entry_write( + zip: *mut Zip, + buf: *const libc::c_void, + bufsize: libc::size_t, + ) -> libc::c_int; +} + +fn main() { + let path = CString::new("/tmp/test.zip").unwrap(); + let mode: libc::c_char = 'w' as libc::c_char; + + let entryname = CString::new("test.txt").unwrap(); + let content = "test content\0"; + + unsafe { + let zip: *mut Zip = zip_open(path.as_ptr(), 5, mode); + { + zip_entry_open(zip, entryname.as_ptr()); + { + let buf = content.as_ptr() as *const libc::c_void; + let bufsize = content.len() as libc::size_t; + zip_entry_write(zip, buf, bufsize); + } + zip_entry_close(zip); + } + zip_close(zip); + } +} +``` + ### Ruby (ffi) Install _ffi_ gem. ```shell diff --git a/contrib/zip/src/zip.c b/contrib/zip/src/zip.c index 1abcfd8fd..3b2821e6a 100644 --- a/contrib/zip/src/zip.c +++ b/contrib/zip/src/zip.c @@ -222,6 +222,20 @@ void zip_close(struct zip_t *zip) { } } +int zip_is64(struct zip_t *zip) { + if (!zip) { + // zip_t handler is not initialized + return -1; + } + + if (!zip->archive.m_pState) { + // zip state is not initialized + return -1; + } + + return (int)zip->archive.m_pState->m_zip64; +} + int zip_entry_open(struct zip_t *zip, const char *entryname) { size_t entrylen = 0; mz_zip_archive *pzip = NULL; @@ -794,7 +808,8 @@ int zip_create(const char *zipname, const char *filenames[], size_t len) { if (MZ_FILE_STAT(name, &file_stat) != 0) { // problem getting information - check errno - return -1; + status = -1; + break; } if ((file_stat.st_mode & 0200) == 0) { diff --git a/contrib/zip/src/zip.h b/contrib/zip/src/zip.h index a48d64d6d..cd3ab5cd0 100644 --- a/contrib/zip/src/zip.h +++ b/contrib/zip/src/zip.h @@ -21,7 +21,7 @@ extern "C" { #if !defined(_SSIZE_T_DEFINED) && !defined(_SSIZE_T_DEFINED_) && \ !defined(__DEFINED_ssize_t) && !defined(__ssize_t_defined) && \ - !defined(_SSIZE_T) && !defined(_SSIZE_T_) + !defined(_SSIZE_T) && !defined(_SSIZE_T_) && !defined(_SSIZE_T_DECLARED) // 64-bit Windows is the only mainstream platform // where sizeof(long) != sizeof(void*) @@ -37,6 +37,7 @@ typedef long ssize_t; /* byte count or error */ #define __ssize_t_defined #define _SSIZE_T #define _SSIZE_T_ +#define _SSIZE_T_DECLARED #endif @@ -90,6 +91,16 @@ extern struct zip_t *zip_open(const char *zipname, int level, char mode); */ extern void zip_close(struct zip_t *zip); +/** + * Determines if the archive has a zip64 end of central directory headers. + * + * @param zip zip archive handler. + * + * @return the return code - 1 (true), 0 (false), negative number (< 0) on + * error. + */ +extern int zip_is64(struct zip_t *zip); + /** * Opens an entry by name in the zip archive. * diff --git a/contrib/zip/test/CMakeLists.txt b/contrib/zip/test/CMakeLists.txt index cc060b00f..122411585 100644 --- a/contrib/zip/test/CMakeLists.txt +++ b/contrib/zip/test/CMakeLists.txt @@ -2,15 +2,10 @@ cmake_minimum_required(VERSION 2.8) # test set(test_out test.out) -set(test_miniz_out test_miniz.out) add_executable(${test_out} test.c) target_link_libraries(${test_out} zip) -add_executable(${test_miniz_out} test_miniz.c) -target_link_libraries(${test_miniz_out} zip) add_test(NAME ${test_out} COMMAND ${test_out}) -add_test(NAME ${test_miniz_out} COMMAND ${test_miniz_out}) set(test_out ${test_out} PARENT_SCOPE) -set(test_miniz_out ${test_miniz_out} PARENT_SCOPE) diff --git a/contrib/zip/test/test.c b/contrib/zip/test/test.c index a9b2ddab1..9cc2248ac 100644 --- a/contrib/zip/test/test.c +++ b/contrib/zip/test/test.c @@ -47,7 +47,7 @@ static void test_write(void) { assert(CRC32DATA1 == zip_entry_crc32(zip)); ++total_entries; assert(0 == zip_entry_close(zip)); - + assert(0 == zip_is64(zip)); zip_close(zip); } @@ -92,6 +92,7 @@ static void test_read(void) { size_t buftmp; struct zip_t *zip = zip_open(ZIPNAME, 0, 'r'); assert(zip != NULL); + assert(0 == zip_is64(zip)); assert(0 == zip_entry_open(zip, "test\\test-1.txt")); assert(strlen(TESTDATA1) == zip_entry_size(zip)); @@ -310,6 +311,7 @@ static void test_fwrite(void) { assert(0 == zip_entry_open(zip, WFILE)); assert(0 == zip_entry_fwrite(zip, WFILE)); assert(0 == zip_entry_close(zip)); + assert(0 == zip_is64(zip)); zip_close(zip); remove(WFILE); diff --git a/include/assimp/GenericProperty.h b/include/assimp/GenericProperty.h index 30f4988f9..c1891c7b6 100644 --- a/include/assimp/GenericProperty.h +++ b/include/assimp/GenericProperty.h @@ -4,7 +4,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2020, assimp team - All rights reserved. Redistribution and use of this software in source and binary forms, @@ -45,26 +44,25 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define AI_GENERIC_PROPERTY_H_INCLUDED #ifdef __GNUC__ -# pragma GCC system_header +# pragma GCC system_header #endif -#include -#include #include +#include +#include #include // ------------------------------------------------------------------------------------------------ template -inline -bool SetGenericProperty(std::map< unsigned int, T >& list, - const char* szName, const T& value) { +inline bool SetGenericProperty(std::map &list, + const char *szName, const T &value) { ai_assert(nullptr != szName); const uint32_t hash = SuperFastHash(szName); typename std::map::iterator it = list.find(hash); - if (it == list.end()) { - list.insert(std::pair( hash, value )); + if (it == list.end()) { + list.insert(std::pair(hash, value)); return false; } (*it).second = value; @@ -74,9 +72,8 @@ bool SetGenericProperty(std::map< unsigned int, T >& list, // ------------------------------------------------------------------------------------------------ template -inline -const T& GetGenericProperty(const std::map< unsigned int, T >& list, - const char* szName, const T& errorReturn) { +inline const T &GetGenericProperty(const std::map &list, + const char *szName, const T &errorReturn) { ai_assert(nullptr != szName); const uint32_t hash = SuperFastHash(szName); @@ -92,22 +89,21 @@ const T& GetGenericProperty(const std::map< unsigned int, T >& list, // Special version for pointer types - they will be deleted when replaced with another value // passing NULL removes the whole property template -inline -void SetGenericPropertyPtr(std::map< unsigned int, T* >& list, - const char* szName, T* value, bool* bWasExisting = nullptr ) { +inline void SetGenericPropertyPtr(std::map &list, + const char *szName, T *value, bool *bWasExisting = nullptr) { ai_assert(nullptr != szName); const uint32_t hash = SuperFastHash(szName); - typename std::map::iterator it = list.find(hash); - if (it == list.end()) { + typename std::map::iterator it = list.find(hash); + if (it == list.end()) { if (bWasExisting) { *bWasExisting = false; } - list.insert(std::pair( hash, value )); + list.insert(std::pair(hash, value)); return; } - if ((*it).second != value) { + if ((*it).second != value) { delete (*it).second; (*it).second = value; } @@ -121,9 +117,8 @@ void SetGenericPropertyPtr(std::map< unsigned int, T* >& list, // ------------------------------------------------------------------------------------------------ template -inline -bool HasGenericProperty(const std::map< unsigned int, T >& list, - const char* szName) { +inline bool HasGenericProperty(const std::map &list, + const char *szName) { ai_assert(nullptr != szName); const uint32_t hash = SuperFastHash(szName); diff --git a/include/assimp/matrix3x3.h b/include/assimp/matrix3x3.h index f9880ab9e..9f11b6b83 100644 --- a/include/assimp/matrix3x3.h +++ b/include/assimp/matrix3x3.h @@ -93,10 +93,10 @@ public: const TReal* operator[] (unsigned int p_iIndex) const; // comparison operators - bool operator== (const aiMatrix4x4t& m) const; - bool operator!= (const aiMatrix4x4t& m) const; + bool operator== (const aiMatrix3x3t& m) const; + bool operator!= (const aiMatrix3x3t& m) const; - bool Equal(const aiMatrix4x4t& m, TReal epsilon = 1e-6) const; + bool Equal(const aiMatrix3x3t& m, TReal epsilon = 1e-6) const; template operator aiMatrix3x3t () const; diff --git a/include/assimp/matrix3x3.inl b/include/assimp/matrix3x3.inl index b11e036b1..0b9565604 100644 --- a/include/assimp/matrix3x3.inl +++ b/include/assimp/matrix3x3.inl @@ -141,7 +141,7 @@ const TReal* aiMatrix3x3t::operator[] (unsigned int p_iIndex) const { // ------------------------------------------------------------------------------------------------ template AI_FORCE_INLINE -bool aiMatrix3x3t::operator== (const aiMatrix4x4t& m) const { +bool aiMatrix3x3t::operator== (const aiMatrix3x3t& m) const { return a1 == m.a1 && a2 == m.a2 && a3 == m.a3 && b1 == m.b1 && b2 == m.b2 && b3 == m.b3 && c1 == m.c1 && c2 == m.c2 && c3 == m.c3; @@ -150,14 +150,14 @@ bool aiMatrix3x3t::operator== (const aiMatrix4x4t& m) const { // ------------------------------------------------------------------------------------------------ template AI_FORCE_INLINE -bool aiMatrix3x3t::operator!= (const aiMatrix4x4t& m) const { +bool aiMatrix3x3t::operator!= (const aiMatrix3x3t& m) const { return !(*this == m); } // --------------------------------------------------------------------------- template AI_FORCE_INLINE -bool aiMatrix3x3t::Equal(const aiMatrix4x4t& m, TReal epsilon) const { +bool aiMatrix3x3t::Equal(const aiMatrix3x3t& m, TReal epsilon) const { return std::abs(a1 - m.a1) <= epsilon && std::abs(a2 - m.a2) <= epsilon && diff --git a/port/PyAssimp/pyassimp/core.py b/port/PyAssimp/pyassimp/core.py index c346e2652..85cfe8233 100644 --- a/port/PyAssimp/pyassimp/core.py +++ b/port/PyAssimp/pyassimp/core.py @@ -138,7 +138,7 @@ def _init(self, target = None, parent = None): logger.debug(str(self) + ": Added array " + str(getattr(target, name)) + " as self." + name.lower()) continue - if m.startswith('m'): + if m.startswith('m') and len(m) > 1 and m[1].upper() == m[1]: if name == "parent": setattr(target, name, parent) diff --git a/samples/SharedCode/UTFConverter.cpp b/samples/SharedCode/UTFConverter.cpp new file mode 100644 index 000000000..a1bff7e4b --- /dev/null +++ b/samples/SharedCode/UTFConverter.cpp @@ -0,0 +1,52 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2020, assimp team + + + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + +#include "UTFConverter.h" + +namespace AssimpSamples { +namespace SharedCode { + +typename UTFConverter::UTFConverterImpl UTFConverter::impl_; + +} +} diff --git a/samples/SharedCode/UTFConverter.h b/samples/SharedCode/UTFConverter.h new file mode 100644 index 000000000..17e89ee4d --- /dev/null +++ b/samples/SharedCode/UTFConverter.h @@ -0,0 +1,92 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2020, assimp team + + + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + +#ifndef ASSIMP_SAMPLES_SHARED_CODE_UTFCONVERTER_H +#define ASSIMP_SAMPLES_SHARED_CODE_UTFCONVERTER_H + +#include +#include +#include + +namespace AssimpSamples { +namespace SharedCode { + +// Used to convert between multibyte and unicode strings. +class UTFConverter { + using UTFConverterImpl = std::wstring_convert, wchar_t>; +public: + UTFConverter(const char* s) : + s_(s), + ws_(impl_.from_bytes(s)) { + } + UTFConverter(const wchar_t* s) : + s_(impl_.to_bytes(s)), + ws_(s) { + } + UTFConverter(const std::string& s) : + s_(s), + ws_(impl_.from_bytes(s)) { + } + UTFConverter(const std::wstring& s) : + s_(impl_.to_bytes(s)), + ws_(s) { + } + inline const char* c_str() const { + return s_.c_str(); + } + inline const std::string& str() const { + return s_; + } + inline const wchar_t* c_wstr() const { + return ws_.c_str(); + } +private: + static UTFConverterImpl impl_; + std::string s_; + std::wstring ws_; +}; + +} +} + +#endif // ASSIMP_SAMPLES_SHARED_CODE_UTFCONVERTER_H diff --git a/samples/SimpleTexturedDirectx11/CMakeLists.txt b/samples/SimpleTexturedDirectx11/CMakeLists.txt index b1882500e..9016b8869 100644 --- a/samples/SimpleTexturedDirectx11/CMakeLists.txt +++ b/samples/SimpleTexturedDirectx11/CMakeLists.txt @@ -10,12 +10,12 @@ if ( MSVC ) REMOVE_DEFINITIONS( -DUNICODE -D_UNICODE ) endif () +ADD_COMPILE_DEFINITIONS(SHADER_PATH="${CMAKE_CURRENT_SOURCE_DIR}/SimpleTexturedDirectx11/") + INCLUDE_DIRECTORIES( ${Assimp_SOURCE_DIR}/include ${Assimp_SOURCE_DIR}/code - ${OPENGL_INCLUDE_DIR} - ${GLUT_INCLUDE_DIR} - ${Assimp_SOURCE_DIR}/samples/freeglut/include + ${SAMPLES_SHARED_CODE_DIR} ) LINK_DIRECTORIES( @@ -32,6 +32,9 @@ ADD_EXECUTABLE( assimp_simpletextureddirectx11 WIN32 SimpleTexturedDirectx11/TextureLoader.h #SimpleTexturedDirectx11/VertexShader.hlsl SimpleTexturedDirectx11/main.cpp + SimpleTexturedDirectx11/SafeRelease.hpp + ${SAMPLES_SHARED_CODE_DIR}/UTFConverter.cpp + ${SAMPLES_SHARED_CODE_DIR}/UTFConverter.h ) SET_PROPERTY(TARGET assimp_simpletextureddirectx11 PROPERTY DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX}) diff --git a/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/Mesh.h b/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/Mesh.h index 87433219f..fb2f7f7db 100644 --- a/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/Mesh.h +++ b/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/Mesh.h @@ -6,13 +6,14 @@ #include #include #include -using namespace std; - -#include +#include #include #include + using namespace DirectX; +#include "SafeRelease.hpp" + struct VERTEX { FLOAT X, Y, Z; XMFLOAT2 texcoord; @@ -22,81 +23,85 @@ struct Texture { string type; string path; ID3D11ShaderResourceView *texture; + + void Release() { + SafeRelease(texture); + } }; class Mesh { public: - vector vertices; - vector indices; - vector textures; - ID3D11Device *dev; + std::vector vertices; + std::vector indices; + std::vector textures; + ID3D11Device *dev; - Mesh(ID3D11Device *dev, vector vertices, vector indices, vector textures) - { - this->vertices = vertices; - this->indices = indices; - this->textures = textures; + Mesh(ID3D11Device *dev, const vector& vertices, const vector& indices, const vector& textures) : + vertices(vertices), + indices(indices), + textures(textures), + dev(dev), + VertexBuffer(nullptr), + IndexBuffer(nullptr) { + this->setupMesh(this->dev); + } - this->dev = dev; + void Draw(ID3D11DeviceContext *devcon) { + UINT stride = sizeof(VERTEX); + UINT offset = 0; - this->setupMesh(dev); - } + devcon->IASetVertexBuffers(0, 1, &VertexBuffer, &stride, &offset); + devcon->IASetIndexBuffer(IndexBuffer, DXGI_FORMAT_R32_UINT, 0); - void Draw(ID3D11DeviceContext *devcon) - { - UINT stride = sizeof(VERTEX); - UINT offset = 0; + devcon->PSSetShaderResources(0, 1, &textures[0].texture); - devcon->IASetVertexBuffers(0, 1, &VertexBuffer, &stride, &offset); - devcon->IASetIndexBuffer(IndexBuffer, DXGI_FORMAT_R32_UINT, 0); + devcon->DrawIndexed(static_cast(indices.size()), 0, 0); + } - devcon->PSSetShaderResources(0, 1, &textures[0].texture); - - devcon->DrawIndexed(indices.size(), 0, 0); - } - - void Close() - { - VertexBuffer->Release(); - IndexBuffer->Release(); - } + void Close() { + SafeRelease(VertexBuffer); + SafeRelease(IndexBuffer); + } private: - /* Render data */ - ID3D11Buffer *VertexBuffer, *IndexBuffer; + // Render data + ID3D11Buffer *VertexBuffer, *IndexBuffer; - /* Functions */ - // Initializes all the buffer objects/arrays - bool setupMesh(ID3D11Device *dev) - { - HRESULT hr; + // Functions + // Initializes all the buffer objects/arrays + void setupMesh(ID3D11Device *dev) { + HRESULT hr; - D3D11_BUFFER_DESC vbd; - vbd.Usage = D3D11_USAGE_IMMUTABLE; - vbd.ByteWidth = sizeof(VERTEX) * vertices.size(); - vbd.BindFlags = D3D11_BIND_VERTEX_BUFFER; - vbd.CPUAccessFlags = 0; - vbd.MiscFlags = 0; + D3D11_BUFFER_DESC vbd; + vbd.Usage = D3D11_USAGE_IMMUTABLE; + vbd.ByteWidth = static_cast(sizeof(VERTEX) * vertices.size()); + vbd.BindFlags = D3D11_BIND_VERTEX_BUFFER; + vbd.CPUAccessFlags = 0; + vbd.MiscFlags = 0; - D3D11_SUBRESOURCE_DATA initData; - initData.pSysMem = &vertices[0]; + D3D11_SUBRESOURCE_DATA initData; + initData.pSysMem = &vertices[0]; - hr = dev->CreateBuffer(&vbd, &initData, &VertexBuffer); - if (FAILED(hr)) - return false; + hr = dev->CreateBuffer(&vbd, &initData, &VertexBuffer); + if (FAILED(hr)) { + Close(); + throw std::runtime_error("Failed to create vertex buffer."); + } - D3D11_BUFFER_DESC ibd; - ibd.Usage = D3D11_USAGE_IMMUTABLE; - ibd.ByteWidth = sizeof(UINT) * indices.size(); - ibd.BindFlags = D3D11_BIND_INDEX_BUFFER; - ibd.CPUAccessFlags = 0; - ibd.MiscFlags = 0; + D3D11_BUFFER_DESC ibd; + ibd.Usage = D3D11_USAGE_IMMUTABLE; + ibd.ByteWidth = static_cast(sizeof(UINT) * indices.size()); + ibd.BindFlags = D3D11_BIND_INDEX_BUFFER; + ibd.CPUAccessFlags = 0; + ibd.MiscFlags = 0; - initData.pSysMem = &indices[0]; + initData.pSysMem = &indices[0]; - hr = dev->CreateBuffer(&ibd, &initData, &IndexBuffer); - if (FAILED(hr)) - return false; - } + hr = dev->CreateBuffer(&ibd, &initData, &IndexBuffer); + if (FAILED(hr)) { + Close(); + throw std::runtime_error("Failed to create index buffer."); + } + } }; #endif diff --git a/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/ModelLoader.cpp b/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/ModelLoader.cpp index 10ba07a98..1ab5b61fb 100644 --- a/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/ModelLoader.cpp +++ b/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/ModelLoader.cpp @@ -1,16 +1,21 @@ #include "ModelLoader.h" -ModelLoader::ModelLoader() -{ +ModelLoader::ModelLoader() : + dev(nullptr), + devcon(nullptr), + meshes(), + directory(), + textures_loaded(), + hwnd(nullptr) { + // empty } -ModelLoader::~ModelLoader() -{ +ModelLoader::~ModelLoader() { + // empty } -bool ModelLoader::Load(HWND hwnd, ID3D11Device * dev, ID3D11DeviceContext * devcon, std::string filename) -{ +bool ModelLoader::Load(HWND hwnd, ID3D11Device * dev, ID3D11DeviceContext * devcon, std::string filename) { Assimp::Importer importer; const aiScene* pScene = importer.ReadFile(filename, @@ -20,9 +25,10 @@ bool ModelLoader::Load(HWND hwnd, ID3D11Device * dev, ID3D11DeviceContext * devc if (pScene == NULL) return false; - this->directory = filename.substr(0, filename.find_last_of('/')); + this->directory = filename.substr(0, filename.find_last_of("/\\")); this->dev = dev; + this->devcon = devcon; this->hwnd = hwnd; processNode(pScene->mRootNode, pScene); @@ -30,41 +36,37 @@ bool ModelLoader::Load(HWND hwnd, ID3D11Device * dev, ID3D11DeviceContext * devc return true; } -void ModelLoader::Draw(ID3D11DeviceContext * devcon) -{ - for (int i = 0; i < meshes.size(); i++) - { +void ModelLoader::Draw(ID3D11DeviceContext * devcon) { + for (int i = 0; i < meshes.size(); ++i ) { meshes[i].Draw(devcon); } } string textype; -Mesh ModelLoader::processMesh(aiMesh * mesh, const aiScene * scene) -{ +Mesh ModelLoader::processMesh(aiMesh * mesh, const aiScene * scene) { // Data to fill vector vertices; vector indices; vector textures; - if (mesh->mMaterialIndex >= 0) - { + if (mesh->mMaterialIndex >= 0) { aiMaterial* mat = scene->mMaterials[mesh->mMaterialIndex]; - if (textype.empty()) textype = determineTextureType(scene, mat); + if (textype.empty()) { + textype = determineTextureType(scene, mat); + } } // Walk through each of the mesh's vertices - for (UINT i = 0; i < mesh->mNumVertices; i++) - { + for (UINT i = 0; i < mesh->mNumVertices; i++) { VERTEX vertex; vertex.X = mesh->mVertices[i].x; vertex.Y = mesh->mVertices[i].y; vertex.Z = mesh->mVertices[i].z; - if (mesh->mTextureCoords[0]) - { + if (mesh->mTextureCoords[0]) { vertex.texcoord.x = (float)mesh->mTextureCoords[0][i].x; vertex.texcoord.y = (float)mesh->mTextureCoords[0][i].y; } @@ -72,16 +74,14 @@ Mesh ModelLoader::processMesh(aiMesh * mesh, const aiScene * scene) vertices.push_back(vertex); } - for (UINT i = 0; i < mesh->mNumFaces; i++) - { + for (UINT i = 0; i < mesh->mNumFaces; i++) { aiFace face = mesh->mFaces[i]; for (UINT j = 0; j < face.mNumIndices; j++) indices.push_back(face.mIndices[j]); } - if (mesh->mMaterialIndex >= 0) - { + if (mesh->mMaterialIndex >= 0) { aiMaterial* material = scene->mMaterials[mesh->mMaterialIndex]; vector diffuseMaps = this->loadMaterialTextures(material, aiTextureType_DIFFUSE, "texture_diffuse", scene); @@ -91,35 +91,27 @@ Mesh ModelLoader::processMesh(aiMesh * mesh, const aiScene * scene) return Mesh(dev, vertices, indices, textures); } -vector ModelLoader::loadMaterialTextures(aiMaterial * mat, aiTextureType type, string typeName, const aiScene * scene) -{ +vector ModelLoader::loadMaterialTextures(aiMaterial * mat, aiTextureType type, string typeName, const aiScene * scene) { vector textures; - for (UINT i = 0; i < mat->GetTextureCount(type); i++) - { + for (UINT i = 0; i < mat->GetTextureCount(type); i++) { aiString str; mat->GetTexture(type, i, &str); // Check if texture was loaded before and if so, continue to next iteration: skip loading a new texture bool skip = false; - for (UINT j = 0; j < textures_loaded.size(); j++) - { - if (std::strcmp(textures_loaded[j].path.c_str(), str.C_Str()) == 0) - { + for (UINT j = 0; j < textures_loaded.size(); j++) { + if (std::strcmp(textures_loaded[j].path.c_str(), str.C_Str()) == 0) { textures.push_back(textures_loaded[j]); skip = true; // A texture with the same filepath has already been loaded, continue to next one. (optimization) break; } } - if (!skip) - { // If texture hasn't been loaded already, load it + if (!skip) { // If texture hasn't been loaded already, load it HRESULT hr; Texture texture; - if (textype == "embedded compressed texture") - { + if (textype == "embedded compressed texture") { int textureindex = getTextureIndex(&str); texture.texture = getTextureFromModel(scene, textureindex); - } - else - { + } else { string filename = string(str.C_Str()); filename = directory + '/' + filename; wstring filenamews = wstring(filename.begin(), filename.end()); @@ -136,64 +128,52 @@ vector ModelLoader::loadMaterialTextures(aiMaterial * mat, aiTextureTyp return textures; } -void ModelLoader::Close() -{ - for (int i = 0; i < meshes.size(); i++) - { +void ModelLoader::Close() { + for (auto& t : textures_loaded) + t.Release(); + + for (int i = 0; i < meshes.size(); i++) { meshes[i].Close(); } - - dev->Release(); } -void ModelLoader::processNode(aiNode * node, const aiScene * scene) -{ - for (UINT i = 0; i < node->mNumMeshes; i++) - { +void ModelLoader::processNode(aiNode * node, const aiScene * scene) { + for (UINT i = 0; i < node->mNumMeshes; i++) { aiMesh* mesh = scene->mMeshes[node->mMeshes[i]]; meshes.push_back(this->processMesh(mesh, scene)); } - for (UINT i = 0; i < node->mNumChildren; i++) - { + for (UINT i = 0; i < node->mNumChildren; i++) { this->processNode(node->mChildren[i], scene); } } -string ModelLoader::determineTextureType(const aiScene * scene, aiMaterial * mat) -{ +string ModelLoader::determineTextureType(const aiScene * scene, aiMaterial * mat) { aiString textypeStr; mat->GetTexture(aiTextureType_DIFFUSE, 0, &textypeStr); string textypeteststr = textypeStr.C_Str(); - if (textypeteststr == "*0" || textypeteststr == "*1" || textypeteststr == "*2" || textypeteststr == "*3" || textypeteststr == "*4" || textypeteststr == "*5") - { - if (scene->mTextures[0]->mHeight == 0) - { + if (textypeteststr == "*0" || textypeteststr == "*1" || textypeteststr == "*2" || textypeteststr == "*3" || textypeteststr == "*4" || textypeteststr == "*5") { + if (scene->mTextures[0]->mHeight == 0) { return "embedded compressed texture"; - } - else - { + } else { return "embedded non-compressed texture"; } } - if (textypeteststr.find('.') != string::npos) - { + if (textypeteststr.find('.') != string::npos) { return "textures are on disk"; } return "."; } -int ModelLoader::getTextureIndex(aiString * str) -{ +int ModelLoader::getTextureIndex(aiString * str) { string tistr; tistr = str->C_Str(); tistr = tistr.substr(1); return stoi(tistr); } -ID3D11ShaderResourceView * ModelLoader::getTextureFromModel(const aiScene * scene, int textureindex) -{ +ID3D11ShaderResourceView * ModelLoader::getTextureFromModel(const aiScene * scene, int textureindex) { HRESULT hr; ID3D11ShaderResourceView *texture; diff --git a/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/SafeRelease.hpp b/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/SafeRelease.hpp new file mode 100644 index 000000000..2fd80db6c --- /dev/null +++ b/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/SafeRelease.hpp @@ -0,0 +1,57 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2020, assimp team + + + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + +#ifdef _MSC_VER +#pragma once +#endif + +/* Used to reduce to reduce the number of lines when calling Release() + on a D3D interface. Implemented as a template instead of a 'SAFE_RELEASE' + MACRO to ease debugging. */ +template +inline void SafeRelease(T*& x) { + if (x) { + x->Release(); + x = nullptr; + } +} diff --git a/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/main.cpp b/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/main.cpp index 2d847095a..781fe89e5 100644 --- a/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/main.cpp +++ b/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/main.cpp @@ -14,12 +14,16 @@ // --------------------------------------------------------------------------- #include +#include +#include #include #include #include #include #include #include "ModelLoader.h" +#include "UTFConverter.h" +#include "SafeRelease.hpp" #pragma comment (lib, "d3d11.lib") #pragma comment (lib, "Dxgi.lib") @@ -27,6 +31,10 @@ #pragma comment (lib, "dxguid.lib") using namespace DirectX; +using namespace AssimpSamples::SharedCode; + +#define VERTEX_SHADER_FILE L"VertexShader.hlsl" +#define PIXEL_SHADER_FILE L"PixelShader.hlsl" // ------------------------------------------------------------ // Structs @@ -45,29 +53,32 @@ struct ConstantBuffer { const char g_szClassName[] = "directxWindowClass"; +static std::string g_ModelPath; UINT width, height; -HWND hwnd; +HWND hwnd = nullptr; // ------------------------------------------------------------ // DirectX Variables // ------------------------------------------------------------ D3D_DRIVER_TYPE g_driverType = D3D_DRIVER_TYPE_NULL; D3D_FEATURE_LEVEL g_featureLevel = D3D_FEATURE_LEVEL_11_0; -ID3D11Device *dev; -ID3D11Device1 *dev1; -ID3D11DeviceContext *devcon; -ID3D11DeviceContext1 *devcon1; -IDXGISwapChain *swapchain; -IDXGISwapChain1 *swapchain1; -ID3D11RenderTargetView *backbuffer; -ID3D11VertexShader *pVS; -ID3D11PixelShader *pPS; -ID3D11InputLayout *pLayout; -ID3D11Buffer *pConstantBuffer; -ID3D11Texture2D *g_pDepthStencil; -ID3D11DepthStencilView *g_pDepthStencilView; -ID3D11SamplerState *TexSamplerState; +ID3D11Device *dev = nullptr; +ID3D11Device1 *dev1 = nullptr; +ID3D11DeviceContext *devcon = nullptr; +ID3D11DeviceContext1 *devcon1 = nullptr; +IDXGISwapChain *swapchain = nullptr; +IDXGISwapChain1 *swapchain1 = nullptr; +ID3D11RenderTargetView *backbuffer = nullptr; +ID3D11VertexShader *pVS = nullptr; +ID3D11PixelShader *pPS = nullptr; +ID3D11InputLayout *pLayout = nullptr; +ID3D11Buffer *pConstantBuffer = nullptr; +ID3D11Texture2D *g_pDepthStencil = nullptr; +ID3D11DepthStencilView *g_pDepthStencilView = nullptr; +ID3D11SamplerState *TexSamplerState = nullptr; +ID3D11RasterizerState *rasterstate = nullptr; +ID3D11Debug* d3d11debug = nullptr; XMMATRIX m_World; XMMATRIX m_View; @@ -91,7 +102,7 @@ void Throwanerror(LPCSTR errormessage); // Our Model // ------------------------------------------------------------ -ModelLoader *ourModel; +ModelLoader *ourModel = nullptr; LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { @@ -109,9 +120,42 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) return 0; } -int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, - LPSTR lpCmdLine, int nCmdShow) +int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, + LPWSTR lpCmdLine, int nCmdShow) { + int argc; + LPWSTR* argv = CommandLineToArgvW(GetCommandLineW(), &argc); + if (!argv) { + MessageBox(NULL, + TEXT("An error occured while reading command line arguments."), + TEXT("Error!"), + MB_ICONERROR | MB_OK); + return EXIT_FAILURE; + } + + // Free memory allocated from CommandLineToArgvW. + auto free_command_line_allocated_memory = [&argv]() { + if (argv) { + LocalFree(argv); + argv = nullptr; + } + }; + + // Ensure that a model file has been specified. + if (argc < 2) { + MessageBox(NULL, + TEXT("No model file specified. The program will now close."), + TEXT("Error!"), + MB_ICONERROR | MB_OK); + free_command_line_allocated_memory(); + return EXIT_FAILURE; + } + + // Retrieve the model file path. + g_ModelPath = UTFConverter(argv[1]).str(); + + free_command_line_allocated_memory(); + WNDCLASSEX wc; MSG msg; @@ -160,26 +204,35 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, width = wr.right - wr.left; height = wr.bottom - wr.top; - InitD3D(hInstance, hwnd); + try { + InitD3D(hInstance, hwnd); - while (true) - { - - if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) + while (true) { - TranslateMessage(&msg); - DispatchMessage(&msg); - if (msg.message == WM_QUIT) - break; + if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + + if (msg.message == WM_QUIT) + break; + } + + RenderFrame(); } - RenderFrame(); + CleanD3D(); + return static_cast(msg.wParam); + } catch (const std::exception& e) { + MessageBox(hwnd, e.what(), TEXT("Error!"), MB_ICONERROR | MB_OK); + CleanD3D(); + return EXIT_FAILURE; + } catch (...) { + MessageBox(hwnd, TEXT("Caught an unknown exception."), TEXT("Error!"), MB_ICONERROR | MB_OK); + CleanD3D(); + return EXIT_FAILURE; } - - CleanD3D(); - - return msg.wParam; } void InitD3D(HINSTANCE hinstance, HWND hWnd) @@ -227,6 +280,12 @@ void InitD3D(HINSTANCE hinstance, HWND hWnd) if (FAILED(hr)) Throwanerror("Directx Device Creation Failed!"); +#if _DEBUG + hr = dev->QueryInterface(IID_PPV_ARGS(&d3d11debug)); + if (FAILED(hr)) + OutputDebugString(TEXT("Failed to retrieve DirectX 11 debug interface.\n")); +#endif + UINT m4xMsaaQuality; dev->CheckMultisampleQualityLevels( DXGI_FORMAT_R8G8B8A8_UNORM, 4, &m4xMsaaQuality); @@ -348,7 +407,6 @@ void InitD3D(HINSTANCE hinstance, HWND hWnd) devcon->OMSetRenderTargets(1, &backbuffer, g_pDepthStencilView); D3D11_RASTERIZER_DESC rasterDesc; - ID3D11RasterizerState *rasterState; rasterDesc.AntialiasedLineEnable = false; rasterDesc.CullMode = D3D11_CULL_BACK; rasterDesc.DepthBias = 0; @@ -360,8 +418,8 @@ void InitD3D(HINSTANCE hinstance, HWND hWnd) rasterDesc.ScissorEnable = false; rasterDesc.SlopeScaledDepthBias = 0.0f; - dev->CreateRasterizerState(&rasterDesc, &rasterState); - devcon->RSSetState(rasterState); + dev->CreateRasterizerState(&rasterDesc, &rasterstate); + devcon->RSSetState(rasterstate); D3D11_VIEWPORT viewport; ZeroMemory(&viewport, sizeof(D3D11_VIEWPORT)); @@ -381,19 +439,38 @@ void InitD3D(HINSTANCE hinstance, HWND hWnd) void CleanD3D(void) { - swapchain->SetFullscreenState(FALSE, NULL); + if (swapchain) + swapchain->SetFullscreenState(FALSE, NULL); - ourModel->Close(); - g_pDepthStencil->Release(); - g_pDepthStencilView->Release(); - pLayout->Release(); - pVS->Release(); - pPS->Release(); - pConstantBuffer->Release(); - swapchain->Release(); - backbuffer->Release(); - dev->Release(); - devcon->Release(); + if (ourModel) { + ourModel->Close(); + delete ourModel; + ourModel = nullptr; + } + SafeRelease(TexSamplerState); + SafeRelease(pConstantBuffer); + SafeRelease(pLayout); + SafeRelease(pVS); + SafeRelease(pPS); + SafeRelease(rasterstate); + SafeRelease(g_pDepthStencilView); + SafeRelease(g_pDepthStencil); + SafeRelease(backbuffer); + SafeRelease(swapchain); + SafeRelease(swapchain1); + SafeRelease(devcon1); + SafeRelease(dev1); + SafeRelease(devcon); +#if _DEBUG + if (d3d11debug) { + OutputDebugString(TEXT("Dumping DirectX 11 live objects.\n")); + d3d11debug->ReportLiveDeviceObjects(D3D11_RLDO_DETAIL); + SafeRelease(d3d11debug); + } else { + OutputDebugString(TEXT("Unable to dump live objects: no DirectX 11 debug interface available.\n")); + } +#endif + SafeRelease(dev); } void RenderFrame(void) @@ -431,8 +508,10 @@ void RenderFrame(void) void InitPipeline() { ID3DBlob *VS, *PS; - CompileShaderFromFile(L"VertexShader.hlsl", 0, "main", "vs_4_0", &VS); - CompileShaderFromFile(L"PixelShader.hlsl", 0, "main", "ps_4_0", &PS); + if(FAILED(CompileShaderFromFile(SHADER_PATH VERTEX_SHADER_FILE, 0, "main", "vs_4_0", &VS))) + Throwanerror(UTFConverter(L"Failed to compile shader from file " VERTEX_SHADER_FILE).c_str()); + if(FAILED(CompileShaderFromFile(SHADER_PATH PIXEL_SHADER_FILE, 0, "main", "ps_4_0", &PS))) + Throwanerror(UTFConverter(L"Failed to compile shader from file " PIXEL_SHADER_FILE).c_str()); dev->CreateVertexShader(VS->GetBufferPointer(), VS->GetBufferSize(), NULL, &pVS); dev->CreatePixelShader(PS->GetBufferPointer(), PS->GetBufferSize(), NULL, &pPS); @@ -485,7 +564,7 @@ void InitGraphics() m_View = XMMatrixLookAtLH(Eye, At, Up); ourModel = new ModelLoader; - if (!ourModel->Load(hwnd, dev, devcon, "Models/myModel.fbx")) + if (!ourModel->Load(hwnd, dev, devcon, g_ModelPath)) Throwanerror("Model couldn't be loaded"); } @@ -514,5 +593,5 @@ HRESULT CompileShaderFromFile(LPCWSTR pFileName, const D3D_SHADER_MACRO* pDefine void Throwanerror(LPCSTR errormessage) { - MessageBox(hwnd, errormessage, "Error!", MB_ICONERROR | MB_OK); -} \ No newline at end of file + throw std::runtime_error(errormessage); +} diff --git a/samples/SimpleTexturedOpenGL/CMakeLists.txt b/samples/SimpleTexturedOpenGL/CMakeLists.txt index adcf882a8..e40c40f29 100644 --- a/samples/SimpleTexturedOpenGL/CMakeLists.txt +++ b/samples/SimpleTexturedOpenGL/CMakeLists.txt @@ -21,6 +21,7 @@ INCLUDE_DIRECTORIES( ${Assimp_SOURCE_DIR}/code ${OPENGL_INCLUDE_DIR} ${GLUT_INCLUDE_DIR} + ${SAMPLES_SHARED_CODE_DIR} ) LINK_DIRECTORIES( @@ -31,6 +32,8 @@ LINK_DIRECTORIES( ADD_EXECUTABLE( assimp_simpletexturedogl WIN32 SimpleTexturedOpenGL/include/boost_includes.h SimpleTexturedOpenGL/src/model_loading.cpp + ${SAMPLES_SHARED_CODE_DIR}/UTFConverter.cpp + ${SAMPLES_SHARED_CODE_DIR}/UTFConverter.h ) SET_PROPERTY(TARGET assimp_simpletexturedogl PROPERTY DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX}) diff --git a/samples/SimpleTexturedOpenGL/SimpleTexturedOpenGL/src/model_loading.cpp b/samples/SimpleTexturedOpenGL/SimpleTexturedOpenGL/src/model_loading.cpp index 8c2a08b2e..452c0715c 100644 --- a/samples/SimpleTexturedOpenGL/SimpleTexturedOpenGL/src/model_loading.cpp +++ b/samples/SimpleTexturedOpenGL/SimpleTexturedOpenGL/src/model_loading.cpp @@ -21,8 +21,6 @@ #define STB_IMAGE_IMPLEMENTATION #include "contrib/stb_image/stb_image.h" -#include -#include #include //to map image filenames to textureIds @@ -35,7 +33,7 @@ #include #include #include - +#include "UTFConverter.h" // The default hard-coded path. Can be overridden by supplying a path through the command line. static std::string modelpath = "../../test/models/OBJ/spider.obj"; @@ -77,35 +75,7 @@ GLuint* textureIds; // pointer to texture Array // Create an instance of the Importer class Assimp::Importer importer; -// Used to convert between multibyte and unicode strings. -class UTFConverter { - using UTFConverterImpl = std::wstring_convert, wchar_t>; -public: - UTFConverter(const char* s) : - s_(s), - ws_(impl_.from_bytes(s)) { - } - UTFConverter(const std::string& s) : - s_(s), - ws_(impl_.from_bytes(s)) { - } - UTFConverter(const std::wstring& s) : - s_(impl_.to_bytes(s)), - ws_(s) { - } - inline const std::string& str() const { - return s_; - } - inline const wchar_t* c_wstr() const { - return ws_.c_str(); - } -private: - static UTFConverterImpl impl_; - std::string s_; - std::wstring ws_; -}; - -typename UTFConverter::UTFConverterImpl UTFConverter::impl_; +using namespace AssimpSamples::SharedCode; void createAILogger() { diff --git a/tools/assimp_cmd/CMakeLists.txt b/tools/assimp_cmd/CMakeLists.txt index 848b8f81c..d46d09c2b 100644 --- a/tools/assimp_cmd/CMakeLists.txt +++ b/tools/assimp_cmd/CMakeLists.txt @@ -37,7 +37,7 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # #---------------------------------------------------------------------- -cmake_minimum_required( VERSION 2.6 ) +cmake_minimum_required( VERSION 3.0 ) INCLUDE_DIRECTORIES( ${Assimp_SOURCE_DIR}/include diff --git a/tools/assimp_view/CMakeLists.txt b/tools/assimp_view/CMakeLists.txt index a77f13041..96b21db40 100644 --- a/tools/assimp_view/CMakeLists.txt +++ b/tools/assimp_view/CMakeLists.txt @@ -37,7 +37,7 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # #---------------------------------------------------------------------- -cmake_minimum_required( VERSION 2.6 ) +cmake_minimum_required( VERSION 3.0 ) FIND_PACKAGE(DirectX REQUIRED)