Merge branch 'master' into cmake_fix_native_path

pull/3034/head
Kim Kulling 2020-03-10 16:29:44 +01:00 committed by GitHub
commit af59010583
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
30 changed files with 824 additions and 527 deletions

View File

@ -589,11 +589,13 @@ IF ( ASSIMP_BUILD_ASSIMP_TOOLS )
ADD_SUBDIRECTORY( tools/assimp_view/ ) ADD_SUBDIRECTORY( tools/assimp_view/ )
ENDIF () ENDIF ()
ENDIF () ENDIF ()
# Te command line tool # The command line tool
ADD_SUBDIRECTORY( tools/assimp_cmd/ ) ADD_SUBDIRECTORY( tools/assimp_cmd/ )
ENDIF () ENDIF ()
IF ( ASSIMP_BUILD_SAMPLES) IF ( ASSIMP_BUILD_SAMPLES)
SET( SAMPLES_DIR ${CMAKE_CURRENT_SOURCE_DIR}/samples )
SET( SAMPLES_SHARED_CODE_DIR ${SAMPLES_DIR}/SharedCode )
IF ( WIN32 ) IF ( WIN32 )
ADD_SUBDIRECTORY( samples/SimpleTexturedOpenGL/ ) ADD_SUBDIRECTORY( samples/SimpleTexturedOpenGL/ )
ADD_SUBDIRECTORY( samples/SimpleTexturedDirectx11 ) ADD_SUBDIRECTORY( samples/SimpleTexturedDirectx11 )

View File

@ -1,7 +1,7 @@
prefix=@CMAKE_INSTALL_PREFIX@ prefix=@CMAKE_INSTALL_PREFIX@
exec_prefix=@CMAKE_INSTALL_PREFIX@/ exec_prefix=@CMAKE_INSTALL_PREFIX@/
libdir=@CMAKE_INSTALL_PREFIX@/@ASSIMP_LIB_INSTALL_DIR@ 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@ Name: @CMAKE_PROJECT_NAME@
Description: Import various well-known 3D model formats in an uniform manner. Description: Import various well-known 3D model formats in an uniform manner.

View File

@ -185,8 +185,6 @@ SET( Common_SRCS
Common/ScenePreprocessor.cpp Common/ScenePreprocessor.cpp
Common/ScenePreprocessor.h Common/ScenePreprocessor.h
Common/SkeletonMeshBuilder.cpp Common/SkeletonMeshBuilder.cpp
Common/SplitByBoneCountProcess.cpp
Common/SplitByBoneCountProcess.h
Common/StandardShapes.cpp Common/StandardShapes.cpp
Common/TargetAnimation.cpp Common/TargetAnimation.cpp
Common/TargetAnimation.h Common/TargetAnimation.h
@ -252,35 +250,39 @@ MACRO(ADD_ASSIMP_IMPORTER name)
ENDIF() ENDIF()
ENDMACRO() ENDMACRO()
# if this variable is set to TRUE, the user can manually disable exporters by setting if (NOT ASSIMP_NO_EXPORT)
# 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_<name> which enables compile of loader # if this variable is set to TRUE, the user can manually disable exporters by setting
# this way selective loaders can be compiled (reduces filesize + compile time) # ASSIMP_BUILD_XXX_EXPORTER to FALSE for each exporter
MACRO(ADD_ASSIMP_EXPORTER name) # if this variable is set to FALSE, the user can manually enable exporters by setting
IF (ASSIMP_NO_EXPORT) # ASSIMP_BUILD_XXX_EXPORTER to TRUE for each exporter
set(ASSIMP_EXPORTER_ENABLED FALSE) OPTION(ASSIMP_BUILD_ALL_EXPORTERS_BY_DEFAULT "default value of all ASSIMP_BUILD_XXX_EXPORTER values" TRUE)
ELSEIF (ASSIMP_BUILD_ALL_EXPORTERS_BY_DEFAULT)
set(ASSIMP_EXPORTER_ENABLED TRUE) # macro to add the CMake Option ADD_ASSIMP_IMPORTER_<name> which enables compile of loader
IF (DEFINED ASSIMP_BUILD_${name}_EXPORTER AND NOT ASSIMP_BUILD_${name}_EXPORTER) # 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) 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 () ENDIF ()
ELSE ()
set(ASSIMP_EXPORTER_ENABLED ${ASSIMP_BUILD_${name}_EXPORTER})
ENDIF ()
IF (ASSIMP_EXPORTER_ENABLED) IF (ASSIMP_EXPORTER_ENABLED)
SET(ASSIMP_EXPORTERS_ENABLED "${ASSIMP_EXPORTERS_ENABLED} ${name}") SET(ASSIMP_EXPORTERS_ENABLED "${ASSIMP_EXPORTERS_ENABLED} ${name}")
LIST(APPEND ASSIMP_EXPORTER_SRCS ${ARGN}) LIST(APPEND ASSIMP_EXPORTER_SRCS ${ARGN})
SOURCE_GROUP(${name}_EXPORTER FILES ${ARGN}) SOURCE_GROUP(${name}_EXPORTER FILES ${ARGN})
ELSE() ELSE()
SET(ASSIMP_EXPORTERS_DISABLED "${ASSIMP_EXPORTERS_DISABLED} ${name}") SET(ASSIMP_EXPORTERS_DISABLED "${ASSIMP_EXPORTERS_DISABLED} ${name}")
add_definitions(-DASSIMP_BUILD_NO_${name}_EXPORTER) add_definitions(-DASSIMP_BUILD_NO_${name}_EXPORTER)
ENDIF() ENDIF()
ENDMACRO() ENDMACRO()
endif()
SET(ASSIMP_LOADER_SRCS "") SET(ASSIMP_LOADER_SRCS "")
SET(ASSIMP_IMPORTERS_ENABLED "") # list of enabled importers SET(ASSIMP_IMPORTERS_ENABLED "") # list of enabled importers
@ -307,11 +309,6 @@ ADD_ASSIMP_IMPORTER( 3DS
3DS/3DSLoader.h 3DS/3DSLoader.h
) )
ADD_ASSIMP_EXPORTER( 3DS
3DS/3DSExporter.h
3DS/3DSExporter.cpp
)
ADD_ASSIMP_IMPORTER( AC ADD_ASSIMP_IMPORTER( AC
AC/ACLoader.cpp AC/ACLoader.cpp
AC/ACLoader.h AC/ACLoader.h
@ -329,20 +326,6 @@ ADD_ASSIMP_IMPORTER( ASSBIN
Assbin/AssbinLoader.cpp 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 ADD_ASSIMP_IMPORTER( B3D
B3D/B3DImporter.cpp B3D/B3DImporter.cpp
B3D/B3DImporter.h B3D/B3DImporter.h
@ -362,11 +345,6 @@ ADD_ASSIMP_IMPORTER( COLLADA
Collada/ColladaParser.h Collada/ColladaParser.h
) )
ADD_ASSIMP_EXPORTER( COLLADA
Collada/ColladaExporter.h
Collada/ColladaExporter.cpp
)
ADD_ASSIMP_IMPORTER( DXF ADD_ASSIMP_IMPORTER( DXF
DXF/DXFLoader.cpp DXF/DXFLoader.cpp
DXF/DXFLoader.h DXF/DXFLoader.h
@ -423,11 +401,6 @@ ADD_ASSIMP_IMPORTER( M3D
M3D/m3d.h M3D/m3d.h
) )
ADD_ASSIMP_EXPORTER( M3D
M3D/M3DExporter.h
M3D/M3DExporter.cpp
)
ADD_ASSIMP_IMPORTER( MD2 ADD_ASSIMP_IMPORTER( MD2
MD2/MD2FileData.h MD2/MD2FileData.h
MD2/MD2Loader.cpp MD2/MD2Loader.cpp
@ -505,11 +478,6 @@ ADD_ASSIMP_IMPORTER( OBJ
Obj/ObjTools.h Obj/ObjTools.h
) )
ADD_ASSIMP_EXPORTER( OBJ
Obj/ObjExporter.h
Obj/ObjExporter.cpp
)
ADD_ASSIMP_IMPORTER( OGRE ADD_ASSIMP_IMPORTER( OGRE
Ogre/OgreImporter.h Ogre/OgreImporter.h
Ogre/OgreStructs.h Ogre/OgreStructs.h
@ -529,11 +497,6 @@ ADD_ASSIMP_IMPORTER( OPENGEX
OpenGEX/OpenGEXStructs.h OpenGEX/OpenGEXStructs.h
) )
ADD_ASSIMP_EXPORTER( OPENGEX
OpenGEX/OpenGEXExporter.cpp
OpenGEX/OpenGEXExporter.h
)
ADD_ASSIMP_IMPORTER( PLY ADD_ASSIMP_IMPORTER( PLY
Ply/PlyLoader.cpp Ply/PlyLoader.cpp
Ply/PlyLoader.h Ply/PlyLoader.h
@ -541,11 +504,6 @@ ADD_ASSIMP_IMPORTER( PLY
Ply/PlyParser.h Ply/PlyParser.h
) )
ADD_ASSIMP_EXPORTER( PLY
Ply/PlyExporter.cpp
Ply/PlyExporter.h
)
ADD_ASSIMP_IMPORTER( MS3D ADD_ASSIMP_IMPORTER( MS3D
MS3D/MS3DLoader.cpp MS3D/MS3DLoader.cpp
MS3D/MS3DLoader.h MS3D/MS3DLoader.h
@ -635,14 +593,86 @@ ADD_ASSIMP_IMPORTER( FBX
FBX/FBXCommon.h FBX/FBXCommon.h
) )
ADD_ASSIMP_EXPORTER( FBX if (NOT ASSIMP_NO_EXPORT)
FBX/FBXExporter.h
FBX/FBXExporter.cpp ADD_ASSIMP_EXPORTER( OBJ
FBX/FBXExportNode.h Obj/ObjExporter.h
FBX/FBXExportNode.cpp Obj/ObjExporter.cpp)
FBX/FBXExportProperty.h
FBX/FBXExportProperty.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 SET( PostProcessing_SRCS
PostProcessing/CalcTangentsProcess.cpp PostProcessing/CalcTangentsProcess.cpp
@ -705,6 +735,8 @@ SET( PostProcessing_SRCS
PostProcessing/ArmaturePopulate.h PostProcessing/ArmaturePopulate.h
PostProcessing/GenBoundingBoxesProcess.cpp PostProcessing/GenBoundingBoxesProcess.cpp
PostProcessing/GenBoundingBoxesProcess.h PostProcessing/GenBoundingBoxesProcess.h
PostProcessing/SplitByBoneCountProcess.cpp
PostProcessing/SplitByBoneCountProcess.h
) )
SOURCE_GROUP( PostProcessing FILES ${PostProcessing_SRCS}) SOURCE_GROUP( PostProcessing FILES ${PostProcessing_SRCS})
@ -744,11 +776,6 @@ ADD_ASSIMP_IMPORTER( STL
STL/STLLoader.h STL/STLLoader.h
) )
ADD_ASSIMP_EXPORTER( STL
STL/STLExporter.h
STL/STLExporter.cpp
)
ADD_ASSIMP_IMPORTER( TERRAGEN ADD_ASSIMP_IMPORTER( TERRAGEN
Terragen/TerragenLoader.cpp Terragen/TerragenLoader.cpp
Terragen/TerragenLoader.h Terragen/TerragenLoader.h
@ -767,11 +794,6 @@ ADD_ASSIMP_IMPORTER( X
X/XFileParser.h X/XFileParser.h
) )
ADD_ASSIMP_EXPORTER( X
X/XFileExporter.h
X/XFileExporter.cpp
)
ADD_ASSIMP_IMPORTER( X3D ADD_ASSIMP_IMPORTER( X3D
X3D/X3DImporter.cpp X3D/X3DImporter.cpp
X3D/X3DImporter.hpp X3D/X3DImporter.hpp
@ -792,11 +814,6 @@ ADD_ASSIMP_IMPORTER( X3D
X3D/X3DVocabulary.cpp X3D/X3DVocabulary.cpp
) )
ADD_ASSIMP_EXPORTER( X3D
X3D/X3DExporter.cpp
X3D/X3DExporter.hpp
)
ADD_ASSIMP_IMPORTER( GLTF ADD_ASSIMP_IMPORTER( GLTF
glTF/glTFCommon.h glTF/glTFCommon.h
glTF/glTFCommon.cpp glTF/glTFCommon.cpp
@ -814,13 +831,6 @@ ADD_ASSIMP_IMPORTER( GLTF
glTF2/glTF2Importer.h glTF2/glTF2Importer.h
) )
ADD_ASSIMP_EXPORTER( GLTF
glTF/glTFExporter.h
glTF/glTFExporter.cpp
glTF2/glTF2Exporter.h
glTF2/glTF2Exporter.cpp
)
ADD_ASSIMP_IMPORTER( 3MF ADD_ASSIMP_IMPORTER( 3MF
3MF/D3MFImporter.h 3MF/D3MFImporter.h
3MF/D3MFImporter.cpp 3MF/D3MFImporter.cpp
@ -829,11 +839,6 @@ ADD_ASSIMP_IMPORTER( 3MF
3MF/3MFXmlTags.h 3MF/3MFXmlTags.h
) )
ADD_ASSIMP_EXPORTER( 3MF
3MF/D3MFExporter.h
3MF/D3MFExporter.cpp
)
ADD_ASSIMP_IMPORTER( MMD ADD_ASSIMP_IMPORTER( MMD
MMD/MMDCpp14.h MMD/MMDCpp14.h
MMD/MMDImporter.cpp MMD/MMDImporter.cpp
@ -844,14 +849,6 @@ ADD_ASSIMP_IMPORTER( MMD
MMD/MMDVmdParser.h 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 # 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 # 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 # 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 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 "")) if ((NOT ASSIMP_NO_EXPORT) OR (NOT ASSIMP_EXPORTERS_ENABLED STREQUAL ""))
SET( Exporter_SRCS SET( Exporter_SRCS
Common/Exporter.cpp Common/Exporter.cpp
@ -1088,8 +1080,10 @@ ENDIF()
MESSAGE(STATUS "Enabled importer formats:${ASSIMP_IMPORTERS_ENABLED}") MESSAGE(STATUS "Enabled importer formats:${ASSIMP_IMPORTERS_ENABLED}")
MESSAGE(STATUS "Disabled importer formats:${ASSIMP_IMPORTERS_DISABLED}") MESSAGE(STATUS "Disabled importer formats:${ASSIMP_IMPORTERS_DISABLED}")
MESSAGE(STATUS "Enabled exporter formats:${ASSIMP_EXPORTERS_ENABLED}") if (NOT ASSIMP_NO_EXPORT)
MESSAGE(STATUS "Disabled exporter formats:${ASSIMP_EXPORTERS_DISABLED}") MESSAGE(STATUS "Enabled exporter formats:${ASSIMP_EXPORTERS_ENABLED}")
MESSAGE(STATUS "Disabled exporter formats:${ASSIMP_EXPORTERS_DISABLED}")
endif()
SOURCE_GROUP( include\\assimp FILES ${PUBLIC_HEADERS} ) SOURCE_GROUP( include\\assimp FILES ${PUBLIC_HEADERS} )

View File

@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2020, assimp team Copyright (c) 2006-2020, assimp team
All rights reserved. All rights reserved.
Redistribution and use of this software in source and binary forms, 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 */ /** @file Implementation of BaseProcess */
#include <assimp/BaseImporter.h>
#include "BaseProcess.h" #include "BaseProcess.h"
#include <assimp/DefaultLogger.hpp>
#include <assimp/scene.h>
#include "Importer.h" #include "Importer.h"
#include <assimp/BaseImporter.h>
#include <assimp/scene.h>
#include <assimp/DefaultLogger.hpp>
using namespace Assimp; using namespace Assimp;
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer // Constructor to be privately used by Importer
BaseProcess::BaseProcess() AI_NO_EXCEPT BaseProcess::BaseProcess() AI_NO_EXCEPT
: shared() : shared(),
, progress() progress() {
{ // empty
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Destructor, private as well // Destructor, private as well
BaseProcess::~BaseProcess() BaseProcess::~BaseProcess() {
{
// nothing to do here // nothing to do here
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BaseProcess::ExecuteOnScene( Importer* pImp) void BaseProcess::ExecuteOnScene(Importer *pImp) {
{ ai_assert( nullptr != pImp );
ai_assert(NULL != pImp && NULL != pImp->Pimpl()->mScene); ai_assert( nullptr != pImp->Pimpl()->mScene);
progress = pImp->GetProgressHandler(); progress = pImp->GetProgressHandler();
ai_assert(progress); ai_assert(nullptr != progress);
SetupProperties( pImp ); SetupProperties(pImp);
// catch exceptions thrown inside the PostProcess-Step // catch exceptions thrown inside the PostProcess-Step
try try {
{
Execute(pImp->Pimpl()->mScene); Execute(pImp->Pimpl()->mScene);
} catch( const std::exception& err ) { } catch (const std::exception &err) {
// extract error description // extract error description
pImp->Pimpl()->mErrorString = err.what(); 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 // the default implementation does nothing
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
bool BaseProcess::RequireVerboseFormat() const bool BaseProcess::RequireVerboseFormat() const {
{
return true; return true;
} }

View File

@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2020, assimp team Copyright (c) 2006-2020, assimp team
All rights reserved. All rights reserved.
Redistribution and use of this software in source and binary forms, 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 #ifndef INCLUDED_AI_BASEPROCESS_H
#define INCLUDED_AI_BASEPROCESS_H #define INCLUDED_AI_BASEPROCESS_H
#include <map>
#include <assimp/GenericProperty.h> #include <assimp/GenericProperty.h>
#include <map>
struct aiScene; struct aiScene;
namespace Assimp { namespace Assimp {
class Importer; class Importer;
@ -60,64 +60,50 @@ class Importer;
* to provide additional information to other steps. This is primarily * to provide additional information to other steps. This is primarily
* intended for cross-step optimizations. * intended for cross-step optimizations.
*/ */
class SharedPostProcessInfo class SharedPostProcessInfo {
{
public: public:
struct Base {
struct Base virtual ~Base() {}
{
virtual ~Base()
{}
}; };
//! Represents data that is allocated on the heap, thus needs to be deleted //! Represents data that is allocated on the heap, thus needs to be deleted
template <typename T> template <typename T>
struct THeapData : public Base struct THeapData : public Base {
{ explicit THeapData(T *in) :
explicit THeapData(T* in) data(in) {}
: data (in)
{}
~THeapData() ~THeapData() {
{
delete data; delete data;
} }
T* data; T *data;
}; };
//! Represents static, by-value data not allocated on the heap //! Represents static, by-value data not allocated on the heap
template <typename T> template <typename T>
struct TStaticData : public Base struct TStaticData : public Base {
{ explicit TStaticData(T in) :
explicit TStaticData(T in) data(in) {}
: data (in)
{}
~TStaticData() ~TStaticData() {}
{}
T data; T data;
}; };
// some typedefs for cleaner code // some typedefs for cleaner code
typedef unsigned int KeyType; typedef unsigned int KeyType;
typedef std::map<KeyType, Base*> PropertyMap; typedef std::map<KeyType, Base *> PropertyMap;
public: public:
//! Destructor //! Destructor
~SharedPostProcessInfo() ~SharedPostProcessInfo() {
{
Clean(); Clean();
} }
//! Remove all stored properties from the table //! Remove all stored properties from the table
void Clean() void Clean() {
{
// invoke the virtual destructor for all stored properties // invoke the virtual destructor for all stored properties
for (PropertyMap::iterator it = pmap.begin(), end = pmap.end(); for (PropertyMap::iterator it = pmap.begin(), end = pmap.end();
it != end; ++it) it != end; ++it) {
{
delete (*it).second; delete (*it).second;
} }
pmap.clear(); pmap.clear();
@ -125,24 +111,21 @@ public:
//! Add a heap property to the list //! Add a heap property to the list
template <typename T> template <typename T>
void AddProperty( const char* name, T* in ){ void AddProperty(const char *name, T *in) {
AddProperty(name,(Base*)new THeapData<T>(in)); AddProperty(name, (Base *)new THeapData<T>(in));
} }
//! Add a static by-value property to the list //! Add a static by-value property to the list
template <typename T> template <typename T>
void AddProperty( const char* name, T in ){ void AddProperty(const char *name, T in) {
AddProperty(name,(Base*)new TStaticData<T>(in)); AddProperty(name, (Base *)new TStaticData<T>(in));
} }
//! Get a heap property //! Get a heap property
template <typename T> template <typename T>
bool GetProperty( const char* name, T*& out ) const bool GetProperty(const char *name, T *&out) const {
{ THeapData<T> *t = (THeapData<T> *)GetPropertyInternal(name);
THeapData<T>* t = (THeapData<T>*)GetPropertyInternal(name); if (!t) {
if(!t)
{
out = NULL; out = NULL;
return false; return false;
} }
@ -152,53 +135,34 @@ public:
//! Get a static, by-value property //! Get a static, by-value property
template <typename T> template <typename T>
bool GetProperty( const char* name, T& out ) const bool GetProperty(const char *name, T &out) const {
{ TStaticData<T> *t = (TStaticData<T> *)GetPropertyInternal(name);
TStaticData<T>* t = (TStaticData<T>*)GetPropertyInternal(name); if ( nullptr == t) {
if(!t)return false; return false;
}
out = t->data; out = t->data;
return true; return true;
} }
//! Remove a property of a specific type //! Remove a property of a specific type
void RemoveProperty( const char* name) { void RemoveProperty(const char *name) {
SetGenericPropertyPtr<Base>(pmap,name,NULL); SetGenericPropertyPtr<Base>(pmap, name, nullptr );
} }
private: private:
void AddProperty(const char *name, Base *data) {
void AddProperty( const char* name, Base* data) { SetGenericPropertyPtr<Base>(pmap, name, data);
SetGenericPropertyPtr<Base>(pmap,name,data);
} }
Base* GetPropertyInternal( const char* name) const { Base *GetPropertyInternal(const char *name) const {
return GetGenericProperty<Base*>(pmap,name,NULL); return GetGenericProperty<Base *>(pmap, name, nullptr );
} }
private: private:
//! Map of all stored properties //! Map of all stored properties
PropertyMap pmap; 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" #define AI_SPP_SPATIAL_SORT "$Spat"
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@ -228,7 +192,7 @@ public:
* @return true if the process is present in this flag fields, * @return true if the process is present in this flag fields,
* false if not. * 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 /** Check whether this step expects its input vertex data to be
@ -241,14 +205,14 @@ public:
* the object pointer will be set to NULL). * the object pointer will be set to NULL).
* @param pImp Importer instance (pImp->mScene must be valid) * @param pImp Importer instance (pImp->mScene must be valid)
*/ */
void ExecuteOnScene( Importer* pImp); void ExecuteOnScene(Importer *pImp);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Called prior to ExecuteOnScene(). /** Called prior to ExecuteOnScene().
* The function is a request to the process to update its configuration * The function is a request to the process to update its configuration
* basing on the Importer's configuration property list. * 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. /** Executes the post processing step on the given imported data.
@ -256,35 +220,32 @@ public:
* This method must be implemented by deriving classes. * This method must be implemented by deriving classes.
* @param pScene The imported data to work at. * @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 /** Assign a new SharedPostProcessInfo to the step. This object
* allows multiple postprocess steps to share data. * allows multiple postprocess steps to share data.
* @param sh May be NULL * @param sh May be NULL
*/ */
inline void SetSharedData(SharedPostProcessInfo* sh) { inline void SetSharedData(SharedPostProcessInfo *sh) {
shared = sh; shared = sh;
} }
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Get the shared data that is assigned to the step. /** Get the shared data that is assigned to the step.
*/ */
inline SharedPostProcessInfo* GetSharedData() { inline SharedPostProcessInfo *GetSharedData() {
return shared; return shared;
} }
protected: protected:
/** See the doc of #SharedPostProcessInfo for more details */ /** See the doc of #SharedPostProcessInfo for more details */
SharedPostProcessInfo* shared; SharedPostProcessInfo *shared;
/** Currently active progress handler */ /** Currently active progress handler */
ProgressHandler* progress; ProgressHandler *progress;
}; };
} // end of namespace Assimp } // end of namespace Assimp
#endif // AI_BASEPROCESS_H_INC #endif // AI_BASEPROCESS_H_INC

View File

@ -123,7 +123,7 @@ corresponding preprocessor flag to selectively disable steps.
# include "PostProcessing/OptimizeGraph.h" # include "PostProcessing/OptimizeGraph.h"
#endif #endif
#ifndef ASSIMP_BUILD_NO_SPLITBYBONECOUNT_PROCESS #ifndef ASSIMP_BUILD_NO_SPLITBYBONECOUNT_PROCESS
# include "Common/SplitByBoneCountProcess.h" # include "PostProcessing/SplitByBoneCountProcess.h"
#endif #endif
#ifndef ASSIMP_BUILD_NO_DEBONE_PROCESS #ifndef ASSIMP_BUILD_NO_DEBONE_PROCESS
# include "PostProcessing/DeboneProcess.h" # include "PostProcessing/DeboneProcess.h"

View File

@ -51,6 +51,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <limits> #include <limits>
#include <assimp/TinyFormatter.h> #include <assimp/TinyFormatter.h>
#include <assimp/Exceptional.h>
using namespace Assimp; using namespace Assimp;
using namespace Assimp::Formatter; using namespace Assimp::Formatter;
@ -94,7 +95,10 @@ void SplitByBoneCountProcess::Execute( aiScene* pScene)
bool isNecessary = false; bool isNecessary = false;
for( unsigned int a = 0; a < pScene->mNumMeshes; ++a) for( unsigned int a = 0; a < pScene->mNumMeshes; ++a)
if( pScene->mMeshes[a]->mNumBones > mMaxBoneCount ) if( pScene->mMeshes[a]->mNumBones > mMaxBoneCount )
{
isNecessary = true; isNecessary = true;
break;
}
if( !isNecessary ) if( !isNecessary )
{ {
@ -155,7 +159,9 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vector<aiMesh
{ {
// skip if not necessary // skip if not necessary
if( pMesh->mNumBones <= mMaxBoneCount ) if( pMesh->mNumBones <= mMaxBoneCount )
{
return; return;
}
// necessary optimisation: build a list of all affecting bones for each vertex // 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 // 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::vector<aiMesh
{ {
const aiBone* bone = pMesh->mBones[a]; const aiBone* bone = pMesh->mBones[a];
for( unsigned int b = 0; b < bone->mNumWeights; ++b) for( unsigned int b = 0; b < bone->mNumWeights; ++b)
{
vertexBones[ bone->mWeights[b].mVertexId ].push_back( BoneWeight( a, bone->mWeights[b].mWeight)); vertexBones[ bone->mWeights[b].mVertexId ].push_back( BoneWeight( a, bone->mWeights[b].mWeight));
}
} }
unsigned int numFacesHandled = 0; unsigned int numFacesHandled = 0;
@ -189,7 +197,9 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vector<aiMesh
{ {
// skip if the face is already stored in a submesh // skip if the face is already stored in a submesh
if( isFaceHandled[a] ) if( isFaceHandled[a] )
{
continue; continue;
}
const aiFace& face = pMesh->mFaces[a]; const aiFace& face = pMesh->mFaces[a];
// check every vertex if its bones would still fit into the current submesh // 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<aiMesh
unsigned int boneIndex = vb[c].first; unsigned int boneIndex = vb[c].first;
// if the bone is already used in this submesh, it's ok // if the bone is already used in this submesh, it's ok
if( isBoneUsed[boneIndex] ) if( isBoneUsed[boneIndex] )
{
continue; continue;
}
// if it's not used, yet, we would need to add it. Store its bone index // if it's not used, yet, we would need to add it. Store its bone index
if( std::find( newBonesAtCurrentFace.begin(), newBonesAtCurrentFace.end(), boneIndex) == newBonesAtCurrentFace.end() ) if( std::find( newBonesAtCurrentFace.begin(), newBonesAtCurrentFace.end(), boneIndex) == newBonesAtCurrentFace.end() )
{
newBonesAtCurrentFace.push_back( boneIndex); newBonesAtCurrentFace.push_back( boneIndex);
}
} }
} }
if (newBonesAtCurrentFace.size() > 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 // 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 ) if( numBones + newBonesAtCurrentFace.size() > mMaxBoneCount )
{
continue; continue;
}
// mark all new bones as necessary // mark all new bones as necessary
while( !newBonesAtCurrentFace.empty() ) while( !newBonesAtCurrentFace.empty() )
@ -219,7 +239,9 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vector<aiMesh
unsigned int newIndex = newBonesAtCurrentFace.back(); unsigned int newIndex = newBonesAtCurrentFace.back();
newBonesAtCurrentFace.pop_back(); // this also avoids the deallocation which comes with a clear() newBonesAtCurrentFace.pop_back(); // this also avoids the deallocation which comes with a clear()
if( isBoneUsed[newIndex] ) if( isBoneUsed[newIndex] )
{
continue; continue;
}
isBoneUsed[newIndex] = true; isBoneUsed[newIndex] = true;
numBones++; numBones++;
@ -237,7 +259,9 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vector<aiMesh
// create a new mesh to hold this subset of the source mesh // create a new mesh to hold this subset of the source mesh
aiMesh* newMesh = new aiMesh; aiMesh* newMesh = new aiMesh;
if( pMesh->mName.length > 0 ) if( pMesh->mName.length > 0 )
{
newMesh->mName.Set( format() << pMesh->mName.data << "_sub" << poNewMeshes.size()); newMesh->mName.Set( format() << pMesh->mName.data << "_sub" << poNewMeshes.size());
}
newMesh->mMaterialIndex = pMesh->mMaterialIndex; newMesh->mMaterialIndex = pMesh->mMaterialIndex;
newMesh->mPrimitiveTypes = pMesh->mPrimitiveTypes; newMesh->mPrimitiveTypes = pMesh->mPrimitiveTypes;
poNewMeshes.push_back( newMesh); poNewMeshes.push_back( newMesh);
@ -247,7 +271,9 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vector<aiMesh
newMesh->mNumFaces = static_cast<unsigned int>(subMeshFaces.size()); newMesh->mNumFaces = static_cast<unsigned int>(subMeshFaces.size());
newMesh->mVertices = new aiVector3D[newMesh->mNumVertices]; newMesh->mVertices = new aiVector3D[newMesh->mNumVertices];
if( pMesh->HasNormals() ) if( pMesh->HasNormals() )
{
newMesh->mNormals = new aiVector3D[newMesh->mNumVertices]; newMesh->mNormals = new aiVector3D[newMesh->mNumVertices];
}
if( pMesh->HasTangentsAndBitangents() ) if( pMesh->HasTangentsAndBitangents() )
{ {
newMesh->mTangents = new aiVector3D[newMesh->mNumVertices]; newMesh->mTangents = new aiVector3D[newMesh->mNumVertices];
@ -256,13 +282,17 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vector<aiMesh
for( unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a ) for( unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a )
{ {
if( pMesh->HasTextureCoords( a) ) if( pMesh->HasTextureCoords( a) )
{
newMesh->mTextureCoords[a] = new aiVector3D[newMesh->mNumVertices]; newMesh->mTextureCoords[a] = new aiVector3D[newMesh->mNumVertices];
}
newMesh->mNumUVComponents[a] = pMesh->mNumUVComponents[a]; newMesh->mNumUVComponents[a] = pMesh->mNumUVComponents[a];
} }
for( unsigned int a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; ++a ) for( unsigned int a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; ++a )
{ {
if( pMesh->HasVertexColors( a) ) if( pMesh->HasVertexColors( a) )
{
newMesh->mColors[a] = new aiColor4D[newMesh->mNumVertices]; newMesh->mColors[a] = new aiColor4D[newMesh->mNumVertices];
}
} }
// and copy over the data, generating faces with linear indices along the way // and copy over the data, generating faces with linear indices along the way
@ -285,7 +315,9 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vector<aiMesh
newMesh->mVertices[nvi] = pMesh->mVertices[srcIndex]; newMesh->mVertices[nvi] = pMesh->mVertices[srcIndex];
if( pMesh->HasNormals() ) if( pMesh->HasNormals() )
{
newMesh->mNormals[nvi] = pMesh->mNormals[srcIndex]; newMesh->mNormals[nvi] = pMesh->mNormals[srcIndex];
}
if( pMesh->HasTangentsAndBitangents() ) if( pMesh->HasTangentsAndBitangents() )
{ {
newMesh->mTangents[nvi] = pMesh->mTangents[srcIndex]; newMesh->mTangents[nvi] = pMesh->mTangents[srcIndex];
@ -294,12 +326,16 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vector<aiMesh
for( unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++c ) for( unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++c )
{ {
if( pMesh->HasTextureCoords( c) ) if( pMesh->HasTextureCoords( c) )
{
newMesh->mTextureCoords[c][nvi] = pMesh->mTextureCoords[c][srcIndex]; newMesh->mTextureCoords[c][nvi] = pMesh->mTextureCoords[c][srcIndex];
}
} }
for( unsigned int c = 0; c < AI_MAX_NUMBER_OF_COLOR_SETS; ++c ) for( unsigned int c = 0; c < AI_MAX_NUMBER_OF_COLOR_SETS; ++c )
{ {
if( pMesh->HasVertexColors( c) ) if( pMesh->HasVertexColors( c) )
{
newMesh->mColors[c][nvi] = pMesh->mColors[c][srcIndex]; newMesh->mColors[c][nvi] = pMesh->mColors[c][srcIndex];
}
} }
nvi++; nvi++;
@ -316,7 +352,9 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vector<aiMesh
for( unsigned int a = 0; a < pMesh->mNumBones; ++a ) for( unsigned int a = 0; a < pMesh->mNumBones; ++a )
{ {
if( !isBoneUsed[a] ) if( !isBoneUsed[a] )
{
continue; continue;
}
// create the new bone // create the new bone
const aiBone* srcBone = pMesh->mBones[a]; const aiBone* srcBone = pMesh->mBones[a];
@ -340,7 +378,9 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vector<aiMesh
{ {
unsigned int newBoneIndex = mappedBoneIndex[ bonesOnThisVertex[b].first ]; unsigned int newBoneIndex = mappedBoneIndex[ bonesOnThisVertex[b].first ];
if( newBoneIndex != std::numeric_limits<unsigned int>::max() ) if( newBoneIndex != std::numeric_limits<unsigned int>::max() )
{
newMesh->mBones[newBoneIndex]->mNumWeights++; newMesh->mBones[newBoneIndex]->mNumWeights++;
}
} }
} }

View File

@ -46,7 +46,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define AI_SPLITBYBONECOUNTPROCESS_H_INC #define AI_SPLITBYBONECOUNTPROCESS_H_INC
#include <vector> #include <vector>
#include "BaseProcess.h" #include "Common/BaseProcess.h"
#include <assimp/mesh.h> #include <assimp/mesh.h>
#include <assimp/scene.h> #include <assimp/scene.h>

View File

@ -111,8 +111,9 @@ const aiImporterDesc *glTF2Importer::GetInfo() const {
bool glTF2Importer::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /* checkSig */) const { bool glTF2Importer::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /* checkSig */) const {
const std::string &extension = GetExtension(pFile); const std::string &extension = GetExtension(pFile);
if (extension != "gltf" && extension != "glb") if (extension != "gltf" && extension != "glb") {
return false; return false;
}
if (pIOHandler) { if (pIOHandler) {
glTF2::Asset asset(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 i = 0; i < nFaces; ++i) {
for (unsigned j = 0; j < faces[i].mNumIndices; ++j) { for (unsigned j = 0; j < faces[i].mNumIndices; ++j) {
unsigned idx = faces[i].mIndices[j]; unsigned idx = faces[i].mIndices[j];
if (idx >= nVerts) if (idx >= nVerts) {
return false; return false;
}
} }
} }
return true; return true;
@ -861,7 +863,19 @@ aiNode *ImportNode(aiScene *pScene, glTF2::Asset &r, std::vector<unsigned int> &
if (node.skin) { if (node.skin) {
for (int primitiveNo = 0; primitiveNo < count; ++primitiveNo) { for (int primitiveNo = 0; primitiveNo < count; ++primitiveNo) {
aiMesh *mesh = pScene->mMeshes[meshOffsets[mesh_idx] + primitiveNo]; aiMesh *mesh = pScene->mMeshes[meshOffsets[mesh_idx] + primitiveNo];
mesh->mNumBones = static_cast<unsigned int>(node.skin->jointNames.size()); unsigned int numBones =static_cast<unsigned int>(node.skin->jointNames.size());
std::vector<std::vector<aiVertexWeight>> 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<unsigned int>(realNumBones);
mesh->mBones = new aiBone *[mesh->mNumBones]; mesh->mBones = new aiBone *[mesh->mNumBones];
// GLTF and Assimp choose to store bone weights differently. // GLTF and Assimp choose to store bone weights differently.
@ -873,43 +887,33 @@ aiNode *ImportNode(aiScene *pScene, glTF2::Asset &r, std::vector<unsigned int> &
// both because it's somewhat slow and because, for many applications, // both because it's somewhat slow and because, for many applications,
// we then need to reconvert the data back into the vertex-to-bone // we then need to reconvert the data back into the vertex-to-bone
// mapping which makes things doubly-slow. // mapping which makes things doubly-slow.
std::vector<std::vector<aiVertexWeight>> weighting(mesh->mNumBones);
BuildVertexWeightMapping(node.meshes[0]->primitives[primitiveNo], weighting);
mat4 *pbindMatrices = nullptr; mat4 *pbindMatrices = nullptr;
node.skin->inverseBindMatrices->ExtractData(pbindMatrices); node.skin->inverseBindMatrices->ExtractData(pbindMatrices);
for (uint32_t i = 0; i < mesh->mNumBones; ++i) { int cb = 0;
aiBone *bone = new aiBone(); for (uint32_t i = 0; i < numBones; ++i) {
const std::vector<aiVertexWeight> &weights = weighting[i];
if (weights.size() > 0) {
aiBone *bone = new aiBone();
Ref<Node> joint = node.skin->jointNames[i]; Ref<Node> joint = node.skin->jointNames[i];
if (!joint->name.empty()) { if (!joint->name.empty()) {
bone->mName = joint->name; bone->mName = joint->name;
} else { } else {
// Assimp expects each bone to have a unique name. // Assimp expects each bone to have a unique name.
static const std::string kDefaultName = "bone_"; static const std::string kDefaultName = "bone_";
char postfix[10] = { 0 }; char postfix[10] = { 0 };
ASSIMP_itoa10(postfix, i); ASSIMP_itoa10(postfix, i);
bone->mName = (kDefaultName + postfix); bone->mName = (kDefaultName + postfix);
} }
GetNodeTransform(bone->mOffsetMatrix, *joint); GetNodeTransform(bone->mOffsetMatrix, *joint);
CopyValue(pbindMatrices[i], bone->mOffsetMatrix);
CopyValue(pbindMatrices[i], bone->mOffsetMatrix); bone->mNumWeights = static_cast<uint32_t>(weights.size());
std::vector<aiVertexWeight> &weights = weighting[i];
bone->mNumWeights = static_cast<uint32_t>(weights.size());
if (bone->mNumWeights > 0) {
bone->mWeights = new aiVertexWeight[bone->mNumWeights]; bone->mWeights = new aiVertexWeight[bone->mNumWeights];
memcpy(bone->mWeights, weights.data(), bone->mNumWeights * sizeof(aiVertexWeight)); memcpy(bone->mWeights, weights.data(), bone->mNumWeights * sizeof(aiVertexWeight));
} else { mesh->mBones[cb++] = bone;
// 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[i] = bone;
} }
if (pbindMatrices) { if (pbindMatrices) {
@ -1232,8 +1236,9 @@ void glTF2Importer::ImportEmbeddedTextures(glTF2::Asset &r) {
int numEmbeddedTexs = 0; int numEmbeddedTexs = 0;
for (size_t i = 0; i < r.images.Size(); ++i) { for (size_t i = 0; i < r.images.Size(); ++i) {
if (r.images[i].HasData()) if (r.images[i].HasData()) {
numEmbeddedTexs += 1; numEmbeddedTexs += 1;
}
} }
if (numEmbeddedTexs == 0) if (numEmbeddedTexs == 0)
@ -1244,7 +1249,9 @@ void glTF2Importer::ImportEmbeddedTextures(glTF2::Asset &r) {
// Add the embedded textures // Add the embedded textures
for (size_t i = 0; i < r.images.Size(); ++i) { for (size_t i = 0; i < r.images.Size(); ++i) {
Image &img = r.images[i]; Image &img = r.images[i];
if (!img.HasData()) continue; if (!img.HasData()) {
continue;
}
int idx = mScene->mNumTextures++; int idx = mScene->mNumTextures++;
embeddedTexIdxs[i] = idx; embeddedTexIdxs[i] = idx;

View File

@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.0)
project(zip project(zip
LANGUAGES C LANGUAGES C
VERSION "0.1.15") VERSION "0.1.18")
set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH}) set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH})
option(CMAKE_DISABLE_TESTING "Disable test creation" OFF) 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 "Clang" OR
"${CMAKE_C_COMPILER_ID}" STREQUAL "AppleClang") "${CMAKE_C_COMPILER_ID}" STREQUAL "AppleClang")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -Wall -Wextra -Werror -pedantic") 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) endif (MSVC)
# zip # zip
@ -35,7 +31,7 @@ if (NOT CMAKE_DISABLE_TESTING)
enable_testing() enable_testing()
add_subdirectory(test) add_subdirectory(test)
find_package(Sanitizers) find_package(Sanitizers)
add_sanitizers(${PROJECT_NAME} ${test_out} ${test_miniz_out}) add_sanitizers(${PROJECT_NAME} ${test_out})
endif() endif()
#### ####

View File

@ -1,10 +1,8 @@
### A portable (OSX/Linux/Windows), simple zip library written in C ### 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. 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) [![Build](https://github.com/kuba--/zip/workflows/build/badge.svg)](https://github.com/kuba--/zip/actions?query=workflow%3Abuild)
[![Linux](https://travis-ci.org/kuba--/zip.svg?branch=master&label=linux%2fosx)](https://travis-ci.org/kuba--/zip)
[![Version](https://badge.fury.io/gh/kuba--%2Fzip.svg)](https://github.com/kuba--/zip/releases) [![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 # 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) ### Ruby (ffi)
Install _ffi_ gem. Install _ffi_ gem.
```shell ```shell

View File

@ -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) { int zip_entry_open(struct zip_t *zip, const char *entryname) {
size_t entrylen = 0; size_t entrylen = 0;
mz_zip_archive *pzip = NULL; 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) { if (MZ_FILE_STAT(name, &file_stat) != 0) {
// problem getting information - check errno // problem getting information - check errno
return -1; status = -1;
break;
} }
if ((file_stat.st_mode & 0200) == 0) { if ((file_stat.st_mode & 0200) == 0) {

View File

@ -21,7 +21,7 @@ extern "C" {
#if !defined(_SSIZE_T_DEFINED) && !defined(_SSIZE_T_DEFINED_) && \ #if !defined(_SSIZE_T_DEFINED) && !defined(_SSIZE_T_DEFINED_) && \
!defined(__DEFINED_ssize_t) && !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 // 64-bit Windows is the only mainstream platform
// where sizeof(long) != sizeof(void*) // where sizeof(long) != sizeof(void*)
@ -37,6 +37,7 @@ typedef long ssize_t; /* byte count or error */
#define __ssize_t_defined #define __ssize_t_defined
#define _SSIZE_T #define _SSIZE_T
#define _SSIZE_T_ #define _SSIZE_T_
#define _SSIZE_T_DECLARED
#endif #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); 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. * Opens an entry by name in the zip archive.
* *

View File

@ -2,15 +2,10 @@ cmake_minimum_required(VERSION 2.8)
# test # test
set(test_out test.out) set(test_out test.out)
set(test_miniz_out test_miniz.out)
add_executable(${test_out} test.c) add_executable(${test_out} test.c)
target_link_libraries(${test_out} zip) 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_out} COMMAND ${test_out})
add_test(NAME ${test_miniz_out} COMMAND ${test_miniz_out})
set(test_out ${test_out} PARENT_SCOPE) set(test_out ${test_out} PARENT_SCOPE)
set(test_miniz_out ${test_miniz_out} PARENT_SCOPE)

View File

@ -47,7 +47,7 @@ static void test_write(void) {
assert(CRC32DATA1 == zip_entry_crc32(zip)); assert(CRC32DATA1 == zip_entry_crc32(zip));
++total_entries; ++total_entries;
assert(0 == zip_entry_close(zip)); assert(0 == zip_entry_close(zip));
assert(0 == zip_is64(zip));
zip_close(zip); zip_close(zip);
} }
@ -92,6 +92,7 @@ static void test_read(void) {
size_t buftmp; size_t buftmp;
struct zip_t *zip = zip_open(ZIPNAME, 0, 'r'); struct zip_t *zip = zip_open(ZIPNAME, 0, 'r');
assert(zip != NULL); assert(zip != NULL);
assert(0 == zip_is64(zip));
assert(0 == zip_entry_open(zip, "test\\test-1.txt")); assert(0 == zip_entry_open(zip, "test\\test-1.txt"));
assert(strlen(TESTDATA1) == zip_entry_size(zip)); 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_open(zip, WFILE));
assert(0 == zip_entry_fwrite(zip, WFILE)); assert(0 == zip_entry_fwrite(zip, WFILE));
assert(0 == zip_entry_close(zip)); assert(0 == zip_entry_close(zip));
assert(0 == zip_is64(zip));
zip_close(zip); zip_close(zip);
remove(WFILE); remove(WFILE);

View File

@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2020, assimp team Copyright (c) 2006-2020, assimp team
All rights reserved. All rights reserved.
Redistribution and use of this software in source and binary forms, 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 #define AI_GENERIC_PROPERTY_H_INCLUDED
#ifdef __GNUC__ #ifdef __GNUC__
# pragma GCC system_header # pragma GCC system_header
#endif #endif
#include <assimp/Importer.hpp>
#include <assimp/ai_assert.h>
#include <assimp/Hash.h> #include <assimp/Hash.h>
#include <assimp/ai_assert.h>
#include <assimp/Importer.hpp>
#include <map> #include <map>
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
template <class T> template <class T>
inline inline bool SetGenericProperty(std::map<unsigned int, T> &list,
bool SetGenericProperty(std::map< unsigned int, T >& list, const char *szName, const T &value) {
const char* szName, const T& value) {
ai_assert(nullptr != szName); ai_assert(nullptr != szName);
const uint32_t hash = SuperFastHash(szName); const uint32_t hash = SuperFastHash(szName);
typename std::map<unsigned int, T>::iterator it = list.find(hash); typename std::map<unsigned int, T>::iterator it = list.find(hash);
if (it == list.end()) { if (it == list.end()) {
list.insert(std::pair<unsigned int, T>( hash, value )); list.insert(std::pair<unsigned int, T>(hash, value));
return false; return false;
} }
(*it).second = value; (*it).second = value;
@ -74,9 +72,8 @@ bool SetGenericProperty(std::map< unsigned int, T >& list,
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
template <class T> template <class T>
inline inline const T &GetGenericProperty(const std::map<unsigned int, T> &list,
const T& GetGenericProperty(const std::map< unsigned int, T >& list, const char *szName, const T &errorReturn) {
const char* szName, const T& errorReturn) {
ai_assert(nullptr != szName); ai_assert(nullptr != szName);
const uint32_t hash = SuperFastHash(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 // Special version for pointer types - they will be deleted when replaced with another value
// passing NULL removes the whole property // passing NULL removes the whole property
template <class T> template <class T>
inline inline void SetGenericPropertyPtr(std::map<unsigned int, T *> &list,
void SetGenericPropertyPtr(std::map< unsigned int, T* >& list, const char *szName, T *value, bool *bWasExisting = nullptr) {
const char* szName, T* value, bool* bWasExisting = nullptr ) {
ai_assert(nullptr != szName); ai_assert(nullptr != szName);
const uint32_t hash = SuperFastHash(szName); const uint32_t hash = SuperFastHash(szName);
typename std::map<unsigned int, T*>::iterator it = list.find(hash); typename std::map<unsigned int, T *>::iterator it = list.find(hash);
if (it == list.end()) { if (it == list.end()) {
if (bWasExisting) { if (bWasExisting) {
*bWasExisting = false; *bWasExisting = false;
} }
list.insert(std::pair<unsigned int,T*>( hash, value )); list.insert(std::pair<unsigned int, T *>(hash, value));
return; return;
} }
if ((*it).second != value) { if ((*it).second != value) {
delete (*it).second; delete (*it).second;
(*it).second = value; (*it).second = value;
} }
@ -121,9 +117,8 @@ void SetGenericPropertyPtr(std::map< unsigned int, T* >& list,
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
template <class T> template <class T>
inline inline bool HasGenericProperty(const std::map<unsigned int, T> &list,
bool HasGenericProperty(const std::map< unsigned int, T >& list, const char *szName) {
const char* szName) {
ai_assert(nullptr != szName); ai_assert(nullptr != szName);
const uint32_t hash = SuperFastHash(szName); const uint32_t hash = SuperFastHash(szName);

View File

@ -93,10 +93,10 @@ public:
const TReal* operator[] (unsigned int p_iIndex) const; const TReal* operator[] (unsigned int p_iIndex) const;
// comparison operators // comparison operators
bool operator== (const aiMatrix4x4t<TReal>& m) const; bool operator== (const aiMatrix3x3t<TReal>& m) const;
bool operator!= (const aiMatrix4x4t<TReal>& m) const; bool operator!= (const aiMatrix3x3t<TReal>& m) const;
bool Equal(const aiMatrix4x4t<TReal>& m, TReal epsilon = 1e-6) const; bool Equal(const aiMatrix3x3t<TReal>& m, TReal epsilon = 1e-6) const;
template <typename TOther> template <typename TOther>
operator aiMatrix3x3t<TOther> () const; operator aiMatrix3x3t<TOther> () const;

View File

@ -141,7 +141,7 @@ const TReal* aiMatrix3x3t<TReal>::operator[] (unsigned int p_iIndex) const {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
template <typename TReal> template <typename TReal>
AI_FORCE_INLINE AI_FORCE_INLINE
bool aiMatrix3x3t<TReal>::operator== (const aiMatrix4x4t<TReal>& m) const { bool aiMatrix3x3t<TReal>::operator== (const aiMatrix3x3t<TReal>& m) const {
return a1 == m.a1 && a2 == m.a2 && a3 == m.a3 && return a1 == m.a1 && a2 == m.a2 && a3 == m.a3 &&
b1 == m.b1 && b2 == m.b2 && b3 == m.b3 && b1 == m.b1 && b2 == m.b2 && b3 == m.b3 &&
c1 == m.c1 && c2 == m.c2 && c3 == m.c3; c1 == m.c1 && c2 == m.c2 && c3 == m.c3;
@ -150,14 +150,14 @@ bool aiMatrix3x3t<TReal>::operator== (const aiMatrix4x4t<TReal>& m) const {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
template <typename TReal> template <typename TReal>
AI_FORCE_INLINE AI_FORCE_INLINE
bool aiMatrix3x3t<TReal>::operator!= (const aiMatrix4x4t<TReal>& m) const { bool aiMatrix3x3t<TReal>::operator!= (const aiMatrix3x3t<TReal>& m) const {
return !(*this == m); return !(*this == m);
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
template<typename TReal> template<typename TReal>
AI_FORCE_INLINE AI_FORCE_INLINE
bool aiMatrix3x3t<TReal>::Equal(const aiMatrix4x4t<TReal>& m, TReal epsilon) const { bool aiMatrix3x3t<TReal>::Equal(const aiMatrix3x3t<TReal>& m, TReal epsilon) const {
return return
std::abs(a1 - m.a1) <= epsilon && std::abs(a1 - m.a1) <= epsilon &&
std::abs(a2 - m.a2) <= epsilon && std::abs(a2 - m.a2) <= epsilon &&

View File

@ -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()) logger.debug(str(self) + ": Added array " + str(getattr(target, name)) + " as self." + name.lower())
continue continue
if m.startswith('m'): if m.startswith('m') and len(m) > 1 and m[1].upper() == m[1]:
if name == "parent": if name == "parent":
setattr(target, name, parent) setattr(target, name, parent)

View File

@ -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_;
}
}

View File

@ -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 <string>
#include <locale>
#include <codecvt>
namespace AssimpSamples {
namespace SharedCode {
// Used to convert between multibyte and unicode strings.
class UTFConverter {
using UTFConverterImpl = std::wstring_convert<std::codecvt_utf8<wchar_t>, 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

View File

@ -10,12 +10,12 @@ if ( MSVC )
REMOVE_DEFINITIONS( -DUNICODE -D_UNICODE ) REMOVE_DEFINITIONS( -DUNICODE -D_UNICODE )
endif () endif ()
ADD_COMPILE_DEFINITIONS(SHADER_PATH="${CMAKE_CURRENT_SOURCE_DIR}/SimpleTexturedDirectx11/")
INCLUDE_DIRECTORIES( INCLUDE_DIRECTORIES(
${Assimp_SOURCE_DIR}/include ${Assimp_SOURCE_DIR}/include
${Assimp_SOURCE_DIR}/code ${Assimp_SOURCE_DIR}/code
${OPENGL_INCLUDE_DIR} ${SAMPLES_SHARED_CODE_DIR}
${GLUT_INCLUDE_DIR}
${Assimp_SOURCE_DIR}/samples/freeglut/include
) )
LINK_DIRECTORIES( LINK_DIRECTORIES(
@ -32,6 +32,9 @@ ADD_EXECUTABLE( assimp_simpletextureddirectx11 WIN32
SimpleTexturedDirectx11/TextureLoader.h SimpleTexturedDirectx11/TextureLoader.h
#SimpleTexturedDirectx11/VertexShader.hlsl #SimpleTexturedDirectx11/VertexShader.hlsl
SimpleTexturedDirectx11/main.cpp 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}) SET_PROPERTY(TARGET assimp_simpletextureddirectx11 PROPERTY DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX})

View File

@ -6,13 +6,14 @@
#include <sstream> #include <sstream>
#include <iostream> #include <iostream>
#include <vector> #include <vector>
using namespace std; #include <stdexcept>
#include <vector>
#include <d3d11_1.h> #include <d3d11_1.h>
#include <DirectXMath.h> #include <DirectXMath.h>
using namespace DirectX; using namespace DirectX;
#include "SafeRelease.hpp"
struct VERTEX { struct VERTEX {
FLOAT X, Y, Z; FLOAT X, Y, Z;
XMFLOAT2 texcoord; XMFLOAT2 texcoord;
@ -22,81 +23,85 @@ struct Texture {
string type; string type;
string path; string path;
ID3D11ShaderResourceView *texture; ID3D11ShaderResourceView *texture;
void Release() {
SafeRelease(texture);
}
}; };
class Mesh { class Mesh {
public: public:
vector<VERTEX> vertices; std::vector<VERTEX> vertices;
vector<UINT> indices; std::vector<UINT> indices;
vector<Texture> textures; std::vector<Texture> textures;
ID3D11Device *dev; ID3D11Device *dev;
Mesh(ID3D11Device *dev, vector<VERTEX> vertices, vector<UINT> indices, vector<Texture> textures) Mesh(ID3D11Device *dev, const vector<VERTEX>& vertices, const vector<UINT>& indices, const vector<Texture>& textures) :
{ vertices(vertices),
this->vertices = vertices; indices(indices),
this->indices = indices; textures(textures),
this->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) devcon->PSSetShaderResources(0, 1, &textures[0].texture);
{
UINT stride = sizeof(VERTEX);
UINT offset = 0;
devcon->IASetVertexBuffers(0, 1, &VertexBuffer, &stride, &offset); devcon->DrawIndexed(static_cast<UINT>(indices.size()), 0, 0);
devcon->IASetIndexBuffer(IndexBuffer, DXGI_FORMAT_R32_UINT, 0); }
devcon->PSSetShaderResources(0, 1, &textures[0].texture); void Close() {
SafeRelease(VertexBuffer);
devcon->DrawIndexed(indices.size(), 0, 0); SafeRelease(IndexBuffer);
} }
void Close()
{
VertexBuffer->Release();
IndexBuffer->Release();
}
private: private:
/* Render data */ // Render data
ID3D11Buffer *VertexBuffer, *IndexBuffer; ID3D11Buffer *VertexBuffer, *IndexBuffer;
/* Functions */ // Functions
// Initializes all the buffer objects/arrays // Initializes all the buffer objects/arrays
bool setupMesh(ID3D11Device *dev) void setupMesh(ID3D11Device *dev) {
{ HRESULT hr;
HRESULT hr;
D3D11_BUFFER_DESC vbd; D3D11_BUFFER_DESC vbd;
vbd.Usage = D3D11_USAGE_IMMUTABLE; vbd.Usage = D3D11_USAGE_IMMUTABLE;
vbd.ByteWidth = sizeof(VERTEX) * vertices.size(); vbd.ByteWidth = static_cast<UINT>(sizeof(VERTEX) * vertices.size());
vbd.BindFlags = D3D11_BIND_VERTEX_BUFFER; vbd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
vbd.CPUAccessFlags = 0; vbd.CPUAccessFlags = 0;
vbd.MiscFlags = 0; vbd.MiscFlags = 0;
D3D11_SUBRESOURCE_DATA initData; D3D11_SUBRESOURCE_DATA initData;
initData.pSysMem = &vertices[0]; initData.pSysMem = &vertices[0];
hr = dev->CreateBuffer(&vbd, &initData, &VertexBuffer); hr = dev->CreateBuffer(&vbd, &initData, &VertexBuffer);
if (FAILED(hr)) if (FAILED(hr)) {
return false; Close();
throw std::runtime_error("Failed to create vertex buffer.");
}
D3D11_BUFFER_DESC ibd; D3D11_BUFFER_DESC ibd;
ibd.Usage = D3D11_USAGE_IMMUTABLE; ibd.Usage = D3D11_USAGE_IMMUTABLE;
ibd.ByteWidth = sizeof(UINT) * indices.size(); ibd.ByteWidth = static_cast<UINT>(sizeof(UINT) * indices.size());
ibd.BindFlags = D3D11_BIND_INDEX_BUFFER; ibd.BindFlags = D3D11_BIND_INDEX_BUFFER;
ibd.CPUAccessFlags = 0; ibd.CPUAccessFlags = 0;
ibd.MiscFlags = 0; ibd.MiscFlags = 0;
initData.pSysMem = &indices[0]; initData.pSysMem = &indices[0];
hr = dev->CreateBuffer(&ibd, &initData, &IndexBuffer); hr = dev->CreateBuffer(&ibd, &initData, &IndexBuffer);
if (FAILED(hr)) if (FAILED(hr)) {
return false; Close();
} throw std::runtime_error("Failed to create index buffer.");
}
}
}; };
#endif #endif

View File

@ -1,16 +1,21 @@
#include "ModelLoader.h" #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; Assimp::Importer importer;
const aiScene* pScene = importer.ReadFile(filename, const aiScene* pScene = importer.ReadFile(filename,
@ -20,9 +25,10 @@ bool ModelLoader::Load(HWND hwnd, ID3D11Device * dev, ID3D11DeviceContext * devc
if (pScene == NULL) if (pScene == NULL)
return false; return false;
this->directory = filename.substr(0, filename.find_last_of('/')); this->directory = filename.substr(0, filename.find_last_of("/\\"));
this->dev = dev; this->dev = dev;
this->devcon = devcon;
this->hwnd = hwnd; this->hwnd = hwnd;
processNode(pScene->mRootNode, pScene); processNode(pScene->mRootNode, pScene);
@ -30,41 +36,37 @@ bool ModelLoader::Load(HWND hwnd, ID3D11Device * dev, ID3D11DeviceContext * devc
return true; return true;
} }
void ModelLoader::Draw(ID3D11DeviceContext * devcon) void ModelLoader::Draw(ID3D11DeviceContext * devcon) {
{ for (int i = 0; i < meshes.size(); ++i ) {
for (int i = 0; i < meshes.size(); i++)
{
meshes[i].Draw(devcon); meshes[i].Draw(devcon);
} }
} }
string textype; string textype;
Mesh ModelLoader::processMesh(aiMesh * mesh, const aiScene * scene) Mesh ModelLoader::processMesh(aiMesh * mesh, const aiScene * scene) {
{
// Data to fill // Data to fill
vector<VERTEX> vertices; vector<VERTEX> vertices;
vector<UINT> indices; vector<UINT> indices;
vector<Texture> textures; vector<Texture> textures;
if (mesh->mMaterialIndex >= 0) if (mesh->mMaterialIndex >= 0) {
{
aiMaterial* mat = scene->mMaterials[mesh->mMaterialIndex]; 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 // 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 vertex;
vertex.X = mesh->mVertices[i].x; vertex.X = mesh->mVertices[i].x;
vertex.Y = mesh->mVertices[i].y; vertex.Y = mesh->mVertices[i].y;
vertex.Z = mesh->mVertices[i].z; 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.x = (float)mesh->mTextureCoords[0][i].x;
vertex.texcoord.y = (float)mesh->mTextureCoords[0][i].y; 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); 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]; aiFace face = mesh->mFaces[i];
for (UINT j = 0; j < face.mNumIndices; j++) for (UINT j = 0; j < face.mNumIndices; j++)
indices.push_back(face.mIndices[j]); indices.push_back(face.mIndices[j]);
} }
if (mesh->mMaterialIndex >= 0) if (mesh->mMaterialIndex >= 0) {
{
aiMaterial* material = scene->mMaterials[mesh->mMaterialIndex]; aiMaterial* material = scene->mMaterials[mesh->mMaterialIndex];
vector<Texture> diffuseMaps = this->loadMaterialTextures(material, aiTextureType_DIFFUSE, "texture_diffuse", scene); vector<Texture> 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); return Mesh(dev, vertices, indices, textures);
} }
vector<Texture> ModelLoader::loadMaterialTextures(aiMaterial * mat, aiTextureType type, string typeName, const aiScene * scene) vector<Texture> ModelLoader::loadMaterialTextures(aiMaterial * mat, aiTextureType type, string typeName, const aiScene * scene) {
{
vector<Texture> textures; vector<Texture> textures;
for (UINT i = 0; i < mat->GetTextureCount(type); i++) for (UINT i = 0; i < mat->GetTextureCount(type); i++) {
{
aiString str; aiString str;
mat->GetTexture(type, i, &str); mat->GetTexture(type, i, &str);
// Check if texture was loaded before and if so, continue to next iteration: skip loading a new texture // Check if texture was loaded before and if so, continue to next iteration: skip loading a new texture
bool skip = false; bool skip = false;
for (UINT j = 0; j < textures_loaded.size(); j++) for (UINT j = 0; j < textures_loaded.size(); j++) {
{ if (std::strcmp(textures_loaded[j].path.c_str(), str.C_Str()) == 0) {
if (std::strcmp(textures_loaded[j].path.c_str(), str.C_Str()) == 0)
{
textures.push_back(textures_loaded[j]); textures.push_back(textures_loaded[j]);
skip = true; // A texture with the same filepath has already been loaded, continue to next one. (optimization) skip = true; // A texture with the same filepath has already been loaded, continue to next one. (optimization)
break; break;
} }
} }
if (!skip) if (!skip) { // If texture hasn't been loaded already, load it
{ // If texture hasn't been loaded already, load it
HRESULT hr; HRESULT hr;
Texture texture; Texture texture;
if (textype == "embedded compressed texture") if (textype == "embedded compressed texture") {
{
int textureindex = getTextureIndex(&str); int textureindex = getTextureIndex(&str);
texture.texture = getTextureFromModel(scene, textureindex); texture.texture = getTextureFromModel(scene, textureindex);
} } else {
else
{
string filename = string(str.C_Str()); string filename = string(str.C_Str());
filename = directory + '/' + filename; filename = directory + '/' + filename;
wstring filenamews = wstring(filename.begin(), filename.end()); wstring filenamews = wstring(filename.begin(), filename.end());
@ -136,64 +128,52 @@ vector<Texture> ModelLoader::loadMaterialTextures(aiMaterial * mat, aiTextureTyp
return textures; return textures;
} }
void ModelLoader::Close() void ModelLoader::Close() {
{ for (auto& t : textures_loaded)
for (int i = 0; i < meshes.size(); i++) t.Release();
{
for (int i = 0; i < meshes.size(); i++) {
meshes[i].Close(); meshes[i].Close();
} }
dev->Release();
} }
void ModelLoader::processNode(aiNode * node, const aiScene * scene) void ModelLoader::processNode(aiNode * node, const aiScene * scene) {
{ for (UINT i = 0; i < node->mNumMeshes; i++) {
for (UINT i = 0; i < node->mNumMeshes; i++)
{
aiMesh* mesh = scene->mMeshes[node->mMeshes[i]]; aiMesh* mesh = scene->mMeshes[node->mMeshes[i]];
meshes.push_back(this->processMesh(mesh, scene)); 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); this->processNode(node->mChildren[i], scene);
} }
} }
string ModelLoader::determineTextureType(const aiScene * scene, aiMaterial * mat) string ModelLoader::determineTextureType(const aiScene * scene, aiMaterial * mat) {
{
aiString textypeStr; aiString textypeStr;
mat->GetTexture(aiTextureType_DIFFUSE, 0, &textypeStr); mat->GetTexture(aiTextureType_DIFFUSE, 0, &textypeStr);
string textypeteststr = textypeStr.C_Str(); string textypeteststr = textypeStr.C_Str();
if (textypeteststr == "*0" || textypeteststr == "*1" || textypeteststr == "*2" || textypeteststr == "*3" || textypeteststr == "*4" || textypeteststr == "*5") if (textypeteststr == "*0" || textypeteststr == "*1" || textypeteststr == "*2" || textypeteststr == "*3" || textypeteststr == "*4" || textypeteststr == "*5") {
{ if (scene->mTextures[0]->mHeight == 0) {
if (scene->mTextures[0]->mHeight == 0)
{
return "embedded compressed texture"; return "embedded compressed texture";
} } else {
else
{
return "embedded non-compressed texture"; return "embedded non-compressed texture";
} }
} }
if (textypeteststr.find('.') != string::npos) if (textypeteststr.find('.') != string::npos) {
{
return "textures are on disk"; return "textures are on disk";
} }
return "."; return ".";
} }
int ModelLoader::getTextureIndex(aiString * str) int ModelLoader::getTextureIndex(aiString * str) {
{
string tistr; string tistr;
tistr = str->C_Str(); tistr = str->C_Str();
tistr = tistr.substr(1); tistr = tistr.substr(1);
return stoi(tistr); return stoi(tistr);
} }
ID3D11ShaderResourceView * ModelLoader::getTextureFromModel(const aiScene * scene, int textureindex) ID3D11ShaderResourceView * ModelLoader::getTextureFromModel(const aiScene * scene, int textureindex) {
{
HRESULT hr; HRESULT hr;
ID3D11ShaderResourceView *texture; ID3D11ShaderResourceView *texture;

View File

@ -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<typename T>
inline void SafeRelease(T*& x) {
if (x) {
x->Release();
x = nullptr;
}
}

View File

@ -14,12 +14,16 @@
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
#include <Windows.h> #include <Windows.h>
#include <shellapi.h>
#include <stdexcept>
#include <windowsx.h> #include <windowsx.h>
#include <d3d11_1.h> #include <d3d11_1.h>
#include <dxgi1_2.h> #include <dxgi1_2.h>
#include <DirectXMath.h> #include <DirectXMath.h>
#include <d3dcompiler.h> #include <d3dcompiler.h>
#include "ModelLoader.h" #include "ModelLoader.h"
#include "UTFConverter.h"
#include "SafeRelease.hpp"
#pragma comment (lib, "d3d11.lib") #pragma comment (lib, "d3d11.lib")
#pragma comment (lib, "Dxgi.lib") #pragma comment (lib, "Dxgi.lib")
@ -27,6 +31,10 @@
#pragma comment (lib, "dxguid.lib") #pragma comment (lib, "dxguid.lib")
using namespace DirectX; using namespace DirectX;
using namespace AssimpSamples::SharedCode;
#define VERTEX_SHADER_FILE L"VertexShader.hlsl"
#define PIXEL_SHADER_FILE L"PixelShader.hlsl"
// ------------------------------------------------------------ // ------------------------------------------------------------
// Structs // Structs
@ -45,29 +53,32 @@ struct ConstantBuffer {
const char g_szClassName[] = "directxWindowClass"; const char g_szClassName[] = "directxWindowClass";
static std::string g_ModelPath;
UINT width, height; UINT width, height;
HWND hwnd; HWND hwnd = nullptr;
// ------------------------------------------------------------ // ------------------------------------------------------------
// DirectX Variables // DirectX Variables
// ------------------------------------------------------------ // ------------------------------------------------------------
D3D_DRIVER_TYPE g_driverType = D3D_DRIVER_TYPE_NULL; D3D_DRIVER_TYPE g_driverType = D3D_DRIVER_TYPE_NULL;
D3D_FEATURE_LEVEL g_featureLevel = D3D_FEATURE_LEVEL_11_0; D3D_FEATURE_LEVEL g_featureLevel = D3D_FEATURE_LEVEL_11_0;
ID3D11Device *dev; ID3D11Device *dev = nullptr;
ID3D11Device1 *dev1; ID3D11Device1 *dev1 = nullptr;
ID3D11DeviceContext *devcon; ID3D11DeviceContext *devcon = nullptr;
ID3D11DeviceContext1 *devcon1; ID3D11DeviceContext1 *devcon1 = nullptr;
IDXGISwapChain *swapchain; IDXGISwapChain *swapchain = nullptr;
IDXGISwapChain1 *swapchain1; IDXGISwapChain1 *swapchain1 = nullptr;
ID3D11RenderTargetView *backbuffer; ID3D11RenderTargetView *backbuffer = nullptr;
ID3D11VertexShader *pVS; ID3D11VertexShader *pVS = nullptr;
ID3D11PixelShader *pPS; ID3D11PixelShader *pPS = nullptr;
ID3D11InputLayout *pLayout; ID3D11InputLayout *pLayout = nullptr;
ID3D11Buffer *pConstantBuffer; ID3D11Buffer *pConstantBuffer = nullptr;
ID3D11Texture2D *g_pDepthStencil; ID3D11Texture2D *g_pDepthStencil = nullptr;
ID3D11DepthStencilView *g_pDepthStencilView; ID3D11DepthStencilView *g_pDepthStencilView = nullptr;
ID3D11SamplerState *TexSamplerState; ID3D11SamplerState *TexSamplerState = nullptr;
ID3D11RasterizerState *rasterstate = nullptr;
ID3D11Debug* d3d11debug = nullptr;
XMMATRIX m_World; XMMATRIX m_World;
XMMATRIX m_View; XMMATRIX m_View;
@ -91,7 +102,7 @@ void Throwanerror(LPCSTR errormessage);
// Our Model // Our Model
// ------------------------------------------------------------ // ------------------------------------------------------------
ModelLoader *ourModel; ModelLoader *ourModel = nullptr;
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) 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; return 0;
} }
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow) 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; WNDCLASSEX wc;
MSG msg; MSG msg;
@ -160,26 +204,35 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
width = wr.right - wr.left; width = wr.right - wr.left;
height = wr.bottom - wr.top; height = wr.bottom - wr.top;
InitD3D(hInstance, hwnd); try {
InitD3D(hInstance, hwnd);
while (true) while (true)
{
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{ {
TranslateMessage(&msg);
DispatchMessage(&msg);
if (msg.message == WM_QUIT) if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
break; {
TranslateMessage(&msg);
DispatchMessage(&msg);
if (msg.message == WM_QUIT)
break;
}
RenderFrame();
} }
RenderFrame(); CleanD3D();
return static_cast<int>(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) void InitD3D(HINSTANCE hinstance, HWND hWnd)
@ -227,6 +280,12 @@ void InitD3D(HINSTANCE hinstance, HWND hWnd)
if (FAILED(hr)) if (FAILED(hr))
Throwanerror("Directx Device Creation Failed!"); 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; UINT m4xMsaaQuality;
dev->CheckMultisampleQualityLevels( dev->CheckMultisampleQualityLevels(
DXGI_FORMAT_R8G8B8A8_UNORM, 4, &m4xMsaaQuality); DXGI_FORMAT_R8G8B8A8_UNORM, 4, &m4xMsaaQuality);
@ -348,7 +407,6 @@ void InitD3D(HINSTANCE hinstance, HWND hWnd)
devcon->OMSetRenderTargets(1, &backbuffer, g_pDepthStencilView); devcon->OMSetRenderTargets(1, &backbuffer, g_pDepthStencilView);
D3D11_RASTERIZER_DESC rasterDesc; D3D11_RASTERIZER_DESC rasterDesc;
ID3D11RasterizerState *rasterState;
rasterDesc.AntialiasedLineEnable = false; rasterDesc.AntialiasedLineEnable = false;
rasterDesc.CullMode = D3D11_CULL_BACK; rasterDesc.CullMode = D3D11_CULL_BACK;
rasterDesc.DepthBias = 0; rasterDesc.DepthBias = 0;
@ -360,8 +418,8 @@ void InitD3D(HINSTANCE hinstance, HWND hWnd)
rasterDesc.ScissorEnable = false; rasterDesc.ScissorEnable = false;
rasterDesc.SlopeScaledDepthBias = 0.0f; rasterDesc.SlopeScaledDepthBias = 0.0f;
dev->CreateRasterizerState(&rasterDesc, &rasterState); dev->CreateRasterizerState(&rasterDesc, &rasterstate);
devcon->RSSetState(rasterState); devcon->RSSetState(rasterstate);
D3D11_VIEWPORT viewport; D3D11_VIEWPORT viewport;
ZeroMemory(&viewport, sizeof(D3D11_VIEWPORT)); ZeroMemory(&viewport, sizeof(D3D11_VIEWPORT));
@ -381,19 +439,38 @@ void InitD3D(HINSTANCE hinstance, HWND hWnd)
void CleanD3D(void) void CleanD3D(void)
{ {
swapchain->SetFullscreenState(FALSE, NULL); if (swapchain)
swapchain->SetFullscreenState(FALSE, NULL);
ourModel->Close(); if (ourModel) {
g_pDepthStencil->Release(); ourModel->Close();
g_pDepthStencilView->Release(); delete ourModel;
pLayout->Release(); ourModel = nullptr;
pVS->Release(); }
pPS->Release(); SafeRelease(TexSamplerState);
pConstantBuffer->Release(); SafeRelease(pConstantBuffer);
swapchain->Release(); SafeRelease(pLayout);
backbuffer->Release(); SafeRelease(pVS);
dev->Release(); SafeRelease(pPS);
devcon->Release(); 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) void RenderFrame(void)
@ -431,8 +508,10 @@ void RenderFrame(void)
void InitPipeline() void InitPipeline()
{ {
ID3DBlob *VS, *PS; ID3DBlob *VS, *PS;
CompileShaderFromFile(L"VertexShader.hlsl", 0, "main", "vs_4_0", &VS); if(FAILED(CompileShaderFromFile(SHADER_PATH VERTEX_SHADER_FILE, 0, "main", "vs_4_0", &VS)))
CompileShaderFromFile(L"PixelShader.hlsl", 0, "main", "ps_4_0", &PS); 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->CreateVertexShader(VS->GetBufferPointer(), VS->GetBufferSize(), NULL, &pVS);
dev->CreatePixelShader(PS->GetBufferPointer(), PS->GetBufferSize(), NULL, &pPS); dev->CreatePixelShader(PS->GetBufferPointer(), PS->GetBufferSize(), NULL, &pPS);
@ -485,7 +564,7 @@ void InitGraphics()
m_View = XMMatrixLookAtLH(Eye, At, Up); m_View = XMMatrixLookAtLH(Eye, At, Up);
ourModel = new ModelLoader; 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"); Throwanerror("Model couldn't be loaded");
} }
@ -514,5 +593,5 @@ HRESULT CompileShaderFromFile(LPCWSTR pFileName, const D3D_SHADER_MACRO* pDefine
void Throwanerror(LPCSTR errormessage) void Throwanerror(LPCSTR errormessage)
{ {
MessageBox(hwnd, errormessage, "Error!", MB_ICONERROR | MB_OK); throw std::runtime_error(errormessage);
} }

View File

@ -21,6 +21,7 @@ INCLUDE_DIRECTORIES(
${Assimp_SOURCE_DIR}/code ${Assimp_SOURCE_DIR}/code
${OPENGL_INCLUDE_DIR} ${OPENGL_INCLUDE_DIR}
${GLUT_INCLUDE_DIR} ${GLUT_INCLUDE_DIR}
${SAMPLES_SHARED_CODE_DIR}
) )
LINK_DIRECTORIES( LINK_DIRECTORIES(
@ -31,6 +32,8 @@ LINK_DIRECTORIES(
ADD_EXECUTABLE( assimp_simpletexturedogl WIN32 ADD_EXECUTABLE( assimp_simpletexturedogl WIN32
SimpleTexturedOpenGL/include/boost_includes.h SimpleTexturedOpenGL/include/boost_includes.h
SimpleTexturedOpenGL/src/model_loading.cpp 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}) SET_PROPERTY(TARGET assimp_simpletexturedogl PROPERTY DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX})

View File

@ -21,8 +21,6 @@
#define STB_IMAGE_IMPLEMENTATION #define STB_IMAGE_IMPLEMENTATION
#include "contrib/stb_image/stb_image.h" #include "contrib/stb_image/stb_image.h"
#include <locale>
#include <codecvt>
#include <fstream> #include <fstream>
//to map image filenames to textureIds //to map image filenames to textureIds
@ -35,7 +33,7 @@
#include <assimp/scene.h> #include <assimp/scene.h>
#include <assimp/DefaultLogger.hpp> #include <assimp/DefaultLogger.hpp>
#include <assimp/LogStream.hpp> #include <assimp/LogStream.hpp>
#include "UTFConverter.h"
// The default hard-coded path. Can be overridden by supplying a path through the command line. // 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"; 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 // Create an instance of the Importer class
Assimp::Importer importer; Assimp::Importer importer;
// Used to convert between multibyte and unicode strings. using namespace AssimpSamples::SharedCode;
class UTFConverter {
using UTFConverterImpl = std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t>;
public:
UTFConverter(const char* s) :
s_(s),
ws_(impl_.from_bytes(s)) {
}
UTFConverter(const std::string& s) :
s_(s),
ws_(impl_.from_bytes(s)) {
}
UTFConverter(const std::wstring& s) :
s_(impl_.to_bytes(s)),
ws_(s) {
}
inline const std::string& str() const {
return s_;
}
inline const wchar_t* c_wstr() const {
return ws_.c_str();
}
private:
static UTFConverterImpl impl_;
std::string s_;
std::wstring ws_;
};
typename UTFConverter::UTFConverterImpl UTFConverter::impl_;
void createAILogger() void createAILogger()
{ {

View File

@ -37,7 +37,7 @@
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # 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( INCLUDE_DIRECTORIES(
${Assimp_SOURCE_DIR}/include ${Assimp_SOURCE_DIR}/include

View File

@ -37,7 +37,7 @@
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # 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) FIND_PACKAGE(DirectX REQUIRED)