diff --git a/third_party/libassimp/AssimpConfig.cmake.in b/third_party/libassimp/AssimpConfig.cmake.in deleted file mode 100644 index 5bb705a41d..0000000000 --- a/third_party/libassimp/AssimpConfig.cmake.in +++ /dev/null @@ -1,21 +0,0 @@ -# - Config file for the FooBar package -# It defines the following variables -# FOOBAR_INCLUDE_DIRS - include directories for FooBar -# FOOBAR_LIBRARIES - libraries to link against -# FOOBAR_EXECUTABLE - the bar executable - -# Compute paths -get_filename_component(FOOBAR_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) -if(EXISTS "${FOOBAR_CMAKE_DIR}/CMakeCache.txt") - # In build tree - include("${FOOBAR_CMAKE_DIR}/FooBarBuildTreeSettings.cmake") -else() - set(FOOBAR_INCLUDE_DIRS "${FOOBAR_CMAKE_DIR}/@CONF_REL_INCLUDE_DIR@") -endif() - -# Our library dependencies (contains definitions for IMPORTED targets) -include("${FOOBAR_CMAKE_DIR}/FooBarLibraryDepends.cmake") - -# These are IMPORTED targets created by FooBarLibraryDepends.cmake -set(FOOBAR_LIBRARIES foo) -set(FOOBAR_EXECUTABLE bar) diff --git a/third_party/libassimp/Build.md b/third_party/libassimp/Build.md index 418749a0f4..d5b443a791 100644 --- a/third_party/libassimp/Build.md +++ b/third_party/libassimp/Build.md @@ -1,5 +1,8 @@ # Install CMake -Asset-Importer-Lib supports a lot of different OSes and platforms. We are using cmake to generate the build environment for these via cmake. So you have to make sure that you have a working cmake-installation on your system. You can download it at https://cmake.org/ +Asset-Importer-Lib can be build for a lot of different platforms. We are using cmake to generate the build environment for these via cmake. So you have to make sure that you have a working cmake-installation on your system. You can download it at https://cmake.org/ or for linux install it via +``` +sudo apt-get install cmake +``` # Get the source Make sure you have a working git-installation. Open a command prompt and clone the Asset-Importer-Lib via: @@ -11,44 +14,45 @@ git clone https://github.com/assimp/assimp.git First you have to install Visual-Studio on your windows-system. You can get the Community-Version for free here: https://visualstudio.microsoft.com/de/downloads/ To generate the build environment for your IDE open a command prompt, navigate to your repo and type: - ``` > cmake CMakeLists.txt ``` -This will generate the project files. +This will generate the project files for the visual studio. All dependencies used to build Asset-IMporter-Lib shall be part of the repo. If you want to use you own zlib.installation this is possible as well. Check the options for it. # Build instructions for Windows with UWP See https://stackoverflow.com/questions/40803170/cmake-uwp-using-cmake-to-build-universal-windows-app # Build instrcutions for Linux / Unix -Open a terminal and got to your repository. You can generate the projectfiles and build the library via: +Open a terminal and got to your repository. You can generate the makefiles and build the library via: ``` cmake CMakeLists.txt make -j4 ``` -The option -j descripes the number of parallel processes for the build. +The option -j descripes the number of parallel processes for the build. In this case make will try to use 4 cores for the build. + +If you want to use a IDE for linux you can try QTCreator for instance. # CMake build options The cmake-build-environment provides options to configure the build. The following options can be used: -- BUILD_SHARED_LIBS ( default ON ): Generation of shared libs ( dll for windows, so for Linux ). Set this to OFF to get a static lib. -- BUILD_FRAMEWORK ( default OFF, MacOnly): Build package as Mac OS X Framework bundle -- ASSIMP_DOUBLE_PRECISION( default OFF ): All data will be stored as double values. -- ASSIMP_OPT_BUILD_PACKAGES ( default OFF): Set to ON to generate CPack configuration files and packaging targets -- ASSIMP_ANDROID_JNIIOSYSTEM ( default OFF ): Android JNI IOSystem support is active -- ASSIMP_NO_EXPORT ( default OFF ): Disable Assimp's export functionality -- ASSIMP_BUILD_ZLIB ( default OFF ): Build your own zlib -- ASSIMP_BUILD_ASSIMP_TOOLS ( default ON ): If the supplementary tools for Assimp are built in addition to the library. -- ASSIMP_BUILD_SAMPLES ( default OFF ): If the official samples are built as well (needs Glut). -- ASSIMP_BUILD_TESTS ( default ON ): If the test suite for Assimp is built in addition to the library. -- ASSIMP_COVERALLS ( default OFF ): Enable this to measure test coverage. -- ASSIMP_WERROR( default OFF ): Treat warnings as errors. -- ASSIMP_ASAN ( default OFF ): Enable AddressSanitizer. -- ASSIMP_UBSAN ( default OFF ): Enable Undefined Behavior sanitizer. -- SYSTEM_IRRXML ( default OFF ): Use system installed Irrlicht/IrrXML library. -- BUILD_DOCS ( default OFF ): Build documentation using Doxygen. -- INJECT_DEBUG_POSTFIX( default ON ): Inject debug postfix in .a/.so lib names -- IGNORE_GIT_HASH ( default OFF ): Don't call git to get the hash. -- ASSIMP_INSTALL_PDB ( default ON ): Install MSVC debug files. +- **BUILD_SHARED_LIBS ( default ON )**: Generation of shared libs ( dll for windows, so for Linux ). Set this to OFF to get a static lib. +- **BUILD_FRAMEWORK ( default OFF, MacOnly)**: Build package as Mac OS X Framework bundle +- **ASSIMP_DOUBLE_PRECISION( default OFF )**: All data will be stored as double values. +- **ASSIMP_OPT_BUILD_PACKAGES ( default OFF)**: Set to ON to generate CPack configuration files and packaging targets +- **ASSIMP_ANDROID_JNIIOSYSTEM ( default OFF )**: Android JNI IOSystem support is active +- **ASSIMP_NO_EXPORT ( default OFF )**: Disable Assimp's export functionality +- **ASSIMP_BUILD_ZLIB ( default OFF )**: Build your own zlib +- **ASSIMP_BUILD_ASSIMP_TOOLS ( default ON )**: If the supplementary tools for Assimp are built in addition to the library. +- **ASSIMP_BUILD_SAMPLES ( default OFF )**: If the official samples are built as well (needs Glut). +- **ASSIMP_BUILD_TESTS ( default ON )**: If the test suite for Assimp is built in addition to the library. +- **ASSIMP_COVERALLS ( default OFF )**: Enable this to measure test coverage. +- **ASSIMP_WERROR( default OFF )**: Treat warnings as errors. +- **ASSIMP_ASAN ( default OFF )**: Enable AddressSanitizer. +- **ASSIMP_UBSAN ( default OFF )**: Enable Undefined Behavior sanitizer. +- **SYSTEM_IRRXML ( default OFF )**: Use system installed Irrlicht/IrrXML library. +- **BUILD_DOCS ( default OFF )**: Build documentation using Doxygen. +- **INJECT_DEBUG_POSTFIX( default ON )**: Inject debug postfix in .a/.so lib names +- **IGNORE_GIT_HASH ( default OFF )**: Don't call git to get the hash. +- **ASSIMP_INSTALL_PDB ( default ON )**: Install MSVC debug files. diff --git a/third_party/libassimp/CMakeLists.txt b/third_party/libassimp/CMakeLists.txt index ade45f719e..645d92689b 100644 --- a/third_party/libassimp/CMakeLists.txt +++ b/third_party/libassimp/CMakeLists.txt @@ -170,7 +170,7 @@ IF(NOT IGNORE_GIT_HASH) # Get the latest abbreviated commit hash of the working branch EXECUTE_PROCESS( - COMMAND git log -1 --format=%h --no-show-signature + COMMAND git rev-parse --short=8 HEAD WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} OUTPUT_VARIABLE GIT_COMMIT_HASH OUTPUT_STRIP_TRAILING_WHITESPACE diff --git a/third_party/libassimp/code/3DSLoader.cpp b/third_party/libassimp/code/3DSLoader.cpp index cd79b0a6d1..34066e44b0 100644 --- a/third_party/libassimp/code/3DSLoader.cpp +++ b/third_party/libassimp/code/3DSLoader.cpp @@ -161,19 +161,21 @@ void Discreet3DSImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) { StreamReaderLE stream(pIOHandler->Open(pFile,"rb")); - this->stream = &stream; // We should have at least one chunk if (stream.GetRemainingSize() < 16) { throw DeadlyImportError("3DS file is either empty or corrupt: " + pFile); } + this->stream = &stream; // Allocate our temporary 3DS representation - mScene = new D3DS::Scene(); + D3DS::Scene _scene; + mScene = &_scene; // Initialize members + D3DS::Node _rootNode("UNNAMED"); mLastNodeIndex = -1; - mCurrentNode = new D3DS::Node("UNNAMED"); + mCurrentNode = &_rootNode; mRootNode = mCurrentNode; mRootNode->mHierarchyPos = -1; mRootNode->mHierarchyIndex = -1; @@ -193,7 +195,6 @@ void Discreet3DSImporter::InternReadFile( const std::string& pFile, // file. for (auto &mesh : mScene->mMeshes) { if (mesh.mFaces.size() > 0 && mesh.mPositions.size() == 0) { - delete mScene; throw DeadlyImportError("3DS file contains faces but no vertices: " + pFile); } CheckIndices(mesh); @@ -201,7 +202,7 @@ void Discreet3DSImporter::InternReadFile( const std::string& pFile, ComputeNormalsWithSmoothingsGroups(mesh); } - // Replace all occurrences of the default material with a + // Replace all occurences of the default material with a // valid material. Generate it if no material containing // DEFAULT in its name has been found in the file ReplaceDefaultMaterial(); @@ -218,10 +219,8 @@ void Discreet3DSImporter::InternReadFile( const std::string& pFile, // Now apply the master scaling factor to the scene ApplyMasterScale(pScene); - // Delete our internal scene representation and the root - // node, so the whole hierarchy will follow - delete mRootNode; - delete mScene; + // Our internal scene representation and the root + // node will be automatically deleted, so the whole hierarchy will follow AI_DEBUG_INVALIDATE_PTR(mRootNode); AI_DEBUG_INVALIDATE_PTR(mScene); diff --git a/third_party/libassimp/code/AssbinExporter.cpp b/third_party/libassimp/code/AssbinExporter.cpp index d64b5c1def..f49389f785 100644 --- a/third_party/libassimp/code/AssbinExporter.cpp +++ b/third_party/libassimp/code/AssbinExporter.cpp @@ -89,7 +89,7 @@ size_t Write(IOStream * stream, const unsigned int& w) { const uint32_t t = (uint32_t)w; if (w > t) { // this shouldn't happen, integers in Assimp data structures never exceed 2^32 - throw new DeadlyExportError("loss of data due to 64 -> 32 bit integer conversion"); + throw DeadlyExportError("loss of data due to 64 -> 32 bit integer conversion"); } stream->Write(&t,4,1); @@ -805,10 +805,16 @@ public: WriteBinaryScene( &uncompressedStream, pScene ); uLongf uncompressedSize = static_cast(uncompressedStream.Tell()); - uLongf compressedSize = (uLongf)(uncompressedStream.Tell() * 1.001 + 12.); + uLongf compressedSize = (uLongf)compressBound(uncompressedSize); uint8_t* compressedBuffer = new uint8_t[ compressedSize ]; - compress2( compressedBuffer, &compressedSize, (const Bytef*)uncompressedStream.GetBufferPointer(), uncompressedSize, 9 ); + int res = compress2( compressedBuffer, &compressedSize, (const Bytef*)uncompressedStream.GetBufferPointer(), uncompressedSize, 9 ); + if(res != Z_OK) + { + delete [] compressedBuffer; + pIOSystem->Close(out); + throw DeadlyExportError("Compression failed."); + } out->Write( &uncompressedSize, sizeof(uint32_t), 1 ); out->Write( compressedBuffer, sizeof(char), compressedSize ); diff --git a/third_party/libassimp/code/AssbinLoader.cpp b/third_party/libassimp/code/AssbinLoader.cpp index 81c77f3fa6..321a0cfecd 100644 --- a/third_party/libassimp/code/AssbinLoader.cpp +++ b/third_party/libassimp/code/AssbinLoader.cpp @@ -57,6 +57,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include #ifdef ASSIMP_BUILD_NO_OWN_ZLIB # include @@ -103,7 +104,9 @@ bool AssbinImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bo template T Read(IOStream * stream) { T t; - stream->Read( &t, sizeof(T), 1 ); + size_t res = stream->Read( &t, sizeof(T), 1 ); + if(res != 1) + throw DeadlyImportError("Unexpected EOF"); return t; } @@ -144,7 +147,8 @@ template <> aiString Read(IOStream * stream) { aiString s; stream->Read(&s.length,4,1); - stream->Read(s.data,s.length,1); + if(s.length) + stream->Read(s.data,s.length,1); s.data[s.length] = 0; return s; } @@ -207,46 +211,48 @@ void ReadBounds( IOStream * stream, T* /*p*/, unsigned int n ) { } // ----------------------------------------------------------------------------------- -void AssbinImporter::ReadBinaryNode( IOStream * stream, aiNode** node, aiNode* parent ) { - uint32_t chunkID = Read(stream); - (void)(chunkID); - ai_assert(chunkID == ASSBIN_CHUNK_AINODE); +void AssbinImporter::ReadBinaryNode( IOStream * stream, aiNode** onode, aiNode* parent ) { + if(Read(stream) != ASSBIN_CHUNK_AINODE) + throw DeadlyImportError("Magic chunk identifiers are wrong!"); /*uint32_t size =*/ Read(stream); - *node = new aiNode(); + std::unique_ptr node(new aiNode()); - (*node)->mName = Read(stream); - (*node)->mTransformation = Read(stream); - (*node)->mNumChildren = Read(stream); - (*node)->mNumMeshes = Read(stream); + node->mName = Read(stream); + node->mTransformation = Read(stream); + unsigned numChildren = Read(stream); + unsigned numMeshes = Read(stream); unsigned int nb_metadata = Read(stream); if(parent) { - (*node)->mParent = parent; + node->mParent = parent; } - if ((*node)->mNumMeshes) { - (*node)->mMeshes = new unsigned int[(*node)->mNumMeshes]; - for (unsigned int i = 0; i < (*node)->mNumMeshes; ++i) { - (*node)->mMeshes[i] = Read(stream); + if (numMeshes) + { + node->mMeshes = new unsigned int[numMeshes]; + for (unsigned int i = 0; i < numMeshes; ++i) { + node->mMeshes[i] = Read(stream); + node->mNumMeshes++; } } - if ((*node)->mNumChildren) { - (*node)->mChildren = new aiNode*[(*node)->mNumChildren]; - for (unsigned int i = 0; i < (*node)->mNumChildren; ++i) { - ReadBinaryNode( stream, &(*node)->mChildren[i], *node ); + if (numChildren) { + node->mChildren = new aiNode*[numChildren]; + for (unsigned int i = 0; i < numChildren; ++i) { + ReadBinaryNode( stream, &node->mChildren[i], node.get() ); + node->mNumChildren++; } } if ( nb_metadata > 0 ) { - (*node)->mMetaData = aiMetadata::Alloc(nb_metadata); + node->mMetaData = aiMetadata::Alloc(nb_metadata); for (unsigned int i = 0; i < nb_metadata; ++i) { - (*node)->mMetaData->mKeys[i] = Read(stream); - (*node)->mMetaData->mValues[i].mType = (aiMetadataType) Read(stream); - void* data( nullptr ); + node->mMetaData->mKeys[i] = Read(stream); + node->mMetaData->mValues[i].mType = (aiMetadataType) Read(stream); + void* data = nullptr; - switch ((*node)->mMetaData->mValues[i].mType) { + switch (node->mMetaData->mValues[i].mType) { case AI_BOOL: data = new bool(Read(stream)); break; @@ -275,16 +281,16 @@ void AssbinImporter::ReadBinaryNode( IOStream * stream, aiNode** node, aiNode* p break; } - (*node)->mMetaData->mValues[i].mData = data; + node->mMetaData->mValues[i].mData = data; } } + *onode = node.release(); } // ----------------------------------------------------------------------------------- void AssbinImporter::ReadBinaryBone( IOStream * stream, aiBone* b ) { - uint32_t chunkID = Read(stream); - (void)(chunkID); - ai_assert(chunkID == ASSBIN_CHUNK_AIBONE); + if(Read(stream) != ASSBIN_CHUNK_AIBONE) + throw DeadlyImportError("Magic chunk identifiers are wrong!"); /*uint32_t size =*/ Read(stream); b->mName = Read(stream); @@ -306,12 +312,10 @@ void AssbinImporter::ReadBinaryBone( IOStream * stream, aiBone* b ) { static bool fitsIntoUI16(unsigned int mNumVertices) { return ( mNumVertices < (1u<<16) ); } - // ----------------------------------------------------------------------------------- void AssbinImporter::ReadBinaryMesh( IOStream * stream, aiMesh* mesh ) { - uint32_t chunkID = Read(stream); - (void)(chunkID); - ai_assert(chunkID == ASSBIN_CHUNK_AIMESH); + if(Read(stream) != ASSBIN_CHUNK_AIMESH) + throw DeadlyImportError("Magic chunk identifiers are wrong!"); /*uint32_t size =*/ Read(stream); mesh->mPrimitiveTypes = Read(stream); @@ -423,9 +427,8 @@ void AssbinImporter::ReadBinaryMesh( IOStream * stream, aiMesh* mesh ) { // ----------------------------------------------------------------------------------- void AssbinImporter::ReadBinaryMaterialProperty(IOStream * stream, aiMaterialProperty* prop) { - uint32_t chunkID = Read(stream); - (void)(chunkID); - ai_assert(chunkID == ASSBIN_CHUNK_AIMATERIALPROPERTY); + if(Read(stream) != ASSBIN_CHUNK_AIMATERIALPROPERTY) + throw DeadlyImportError("Magic chunk identifiers are wrong!"); /*uint32_t size =*/ Read(stream); prop->mKey = Read(stream); @@ -440,9 +443,8 @@ void AssbinImporter::ReadBinaryMaterialProperty(IOStream * stream, aiMaterialPro // ----------------------------------------------------------------------------------- void AssbinImporter::ReadBinaryMaterial(IOStream * stream, aiMaterial* mat) { - uint32_t chunkID = Read(stream); - (void)(chunkID); - ai_assert(chunkID == ASSBIN_CHUNK_AIMATERIAL); + if(Read(stream) != ASSBIN_CHUNK_AIMATERIAL) + throw DeadlyImportError("Magic chunk identifiers are wrong!"); /*uint32_t size =*/ Read(stream); mat->mNumAllocated = mat->mNumProperties = Read(stream); @@ -462,9 +464,8 @@ void AssbinImporter::ReadBinaryMaterial(IOStream * stream, aiMaterial* mat) { // ----------------------------------------------------------------------------------- void AssbinImporter::ReadBinaryNodeAnim(IOStream * stream, aiNodeAnim* nd) { - uint32_t chunkID = Read(stream); - (void)(chunkID); - ai_assert(chunkID == ASSBIN_CHUNK_AINODEANIM); + if(Read(stream) != ASSBIN_CHUNK_AINODEANIM) + throw DeadlyImportError("Magic chunk identifiers are wrong!"); /*uint32_t size =*/ Read(stream); nd->mNodeName = Read(stream); @@ -508,9 +509,8 @@ void AssbinImporter::ReadBinaryNodeAnim(IOStream * stream, aiNodeAnim* nd) { // ----------------------------------------------------------------------------------- void AssbinImporter::ReadBinaryAnim( IOStream * stream, aiAnimation* anim ) { - uint32_t chunkID = Read(stream); - (void)(chunkID); - ai_assert(chunkID == ASSBIN_CHUNK_AIANIMATION); + if(Read(stream) != ASSBIN_CHUNK_AIANIMATION) + throw DeadlyImportError("Magic chunk identifiers are wrong!"); /*uint32_t size =*/ Read(stream); anim->mName = Read (stream); @@ -529,9 +529,8 @@ void AssbinImporter::ReadBinaryAnim( IOStream * stream, aiAnimation* anim ) { // ----------------------------------------------------------------------------------- void AssbinImporter::ReadBinaryTexture(IOStream * stream, aiTexture* tex) { - uint32_t chunkID = Read(stream); - (void)(chunkID); - ai_assert(chunkID == ASSBIN_CHUNK_AITEXTURE); + if(Read(stream) != ASSBIN_CHUNK_AITEXTURE) + throw DeadlyImportError("Magic chunk identifiers are wrong!"); /*uint32_t size =*/ Read(stream); tex->mWidth = Read(stream); @@ -551,9 +550,8 @@ void AssbinImporter::ReadBinaryTexture(IOStream * stream, aiTexture* tex) { // ----------------------------------------------------------------------------------- void AssbinImporter::ReadBinaryLight( IOStream * stream, aiLight* l ) { - uint32_t chunkID = Read(stream); - (void)(chunkID); - ai_assert(chunkID == ASSBIN_CHUNK_AILIGHT); + if(Read(stream) != ASSBIN_CHUNK_AILIGHT) + throw DeadlyImportError("Magic chunk identifiers are wrong!"); /*uint32_t size =*/ Read(stream); l->mName = Read(stream); @@ -577,9 +575,8 @@ void AssbinImporter::ReadBinaryLight( IOStream * stream, aiLight* l ) { // ----------------------------------------------------------------------------------- void AssbinImporter::ReadBinaryCamera( IOStream * stream, aiCamera* cam ) { - uint32_t chunkID = Read(stream); - (void)(chunkID); - ai_assert(chunkID == ASSBIN_CHUNK_AICAMERA); + if(Read(stream) != ASSBIN_CHUNK_AICAMERA) + throw DeadlyImportError("Magic chunk identifiers are wrong!"); /*uint32_t size =*/ Read(stream); cam->mName = Read(stream); @@ -594,9 +591,8 @@ void AssbinImporter::ReadBinaryCamera( IOStream * stream, aiCamera* cam ) { // ----------------------------------------------------------------------------------- void AssbinImporter::ReadBinaryScene( IOStream * stream, aiScene* scene ) { - uint32_t chunkID = Read(stream); - (void)(chunkID); - ai_assert(chunkID == ASSBIN_CHUNK_AISCENE); + if(Read(stream) != ASSBIN_CHUNK_AISCENE) + throw DeadlyImportError("Magic chunk identifiers are wrong!"); /*uint32_t size =*/ Read(stream); scene->mFlags = Read(stream); @@ -614,6 +610,7 @@ void AssbinImporter::ReadBinaryScene( IOStream * stream, aiScene* scene ) { // Read all meshes if (scene->mNumMeshes) { scene->mMeshes = new aiMesh*[scene->mNumMeshes]; + memset(scene->mMeshes, 0, scene->mNumMeshes*sizeof(aiMesh*)); for (unsigned int i = 0; i < scene->mNumMeshes;++i) { scene->mMeshes[i] = new aiMesh(); ReadBinaryMesh( stream,scene->mMeshes[i]); @@ -623,6 +620,7 @@ void AssbinImporter::ReadBinaryScene( IOStream * stream, aiScene* scene ) { // Read materials if (scene->mNumMaterials) { scene->mMaterials = new aiMaterial*[scene->mNumMaterials]; + memset(scene->mMaterials, 0, scene->mNumMaterials*sizeof(aiMaterial*)); for (unsigned int i = 0; i< scene->mNumMaterials; ++i) { scene->mMaterials[i] = new aiMaterial(); ReadBinaryMaterial(stream,scene->mMaterials[i]); @@ -632,6 +630,7 @@ void AssbinImporter::ReadBinaryScene( IOStream * stream, aiScene* scene ) { // Read all animations if (scene->mNumAnimations) { scene->mAnimations = new aiAnimation*[scene->mNumAnimations]; + memset(scene->mAnimations, 0, scene->mNumAnimations*sizeof(aiAnimation*)); for (unsigned int i = 0; i < scene->mNumAnimations;++i) { scene->mAnimations[i] = new aiAnimation(); ReadBinaryAnim(stream,scene->mAnimations[i]); @@ -641,6 +640,7 @@ void AssbinImporter::ReadBinaryScene( IOStream * stream, aiScene* scene ) { // Read all textures if (scene->mNumTextures) { scene->mTextures = new aiTexture*[scene->mNumTextures]; + memset(scene->mTextures, 0, scene->mNumTextures*sizeof(aiTexture*)); for (unsigned int i = 0; i < scene->mNumTextures;++i) { scene->mTextures[i] = new aiTexture(); ReadBinaryTexture(stream,scene->mTextures[i]); @@ -650,6 +650,7 @@ void AssbinImporter::ReadBinaryScene( IOStream * stream, aiScene* scene ) { // Read lights if (scene->mNumLights) { scene->mLights = new aiLight*[scene->mNumLights]; + memset(scene->mLights, 0, scene->mNumLights*sizeof(aiLight*)); for (unsigned int i = 0; i < scene->mNumLights;++i) { scene->mLights[i] = new aiLight(); ReadBinaryLight(stream,scene->mLights[i]); @@ -659,6 +660,7 @@ void AssbinImporter::ReadBinaryScene( IOStream * stream, aiScene* scene ) { // Read cameras if (scene->mNumCameras) { scene->mCameras = new aiCamera*[scene->mNumCameras]; + memset(scene->mCameras, 0, scene->mNumCameras*sizeof(aiCamera*)); for (unsigned int i = 0; i < scene->mNumCameras;++i) { scene->mCameras[i] = new aiCamera(); ReadBinaryCamera(stream,scene->mCameras[i]); @@ -675,7 +677,7 @@ void AssbinImporter::InternReadFile( const std::string& pFile, aiScene* pScene, } // signature - stream->Seek( 44, aiOrigin_CUR ); + stream->Seek( 44, aiOrigin_CUR ); unsigned int versionMajor = Read(stream); unsigned int versionMinor = Read(stream); @@ -701,11 +703,19 @@ void AssbinImporter::InternReadFile( const std::string& pFile, aiScene* pScene, uLongf compressedSize = static_cast(stream->FileSize() - stream->Tell()); unsigned char * compressedData = new unsigned char[ compressedSize ]; - stream->Read( compressedData, 1, compressedSize ); + size_t len = stream->Read( compressedData, 1, compressedSize ); + ai_assert(len == compressedSize); unsigned char * uncompressedData = new unsigned char[ uncompressedSize ]; - uncompress( uncompressedData, &uncompressedSize, compressedData, compressedSize ); + int res = uncompress( uncompressedData, &uncompressedSize, compressedData, len ); + if(res != Z_OK) + { + delete [] uncompressedData; + delete [] compressedData; + pIOHandler->Close(stream); + throw DeadlyImportError("Zlib decompression failed."); + } MemoryIOStream io( uncompressedData, uncompressedSize ); diff --git a/third_party/libassimp/code/CMakeLists.txt b/third_party/libassimp/code/CMakeLists.txt index 7ad49ad331..6b8d3d3227 100644 --- a/third_party/libassimp/code/CMakeLists.txt +++ b/third_party/libassimp/code/CMakeLists.txt @@ -191,6 +191,14 @@ SET( Common_SRCS ) SOURCE_GROUP(Common FILES ${Common_SRCS}) +SET( STEPParser_SRCS + Importer/STEPParser/STEPFileReader.h + Importer/STEPParser/STEPFileReader.cpp + Importer/STEPParser/STEPFileEncoding.cpp + Importer/STEPParser/STEPFileEncoding.h +) +SOURCE_GROUP(STEPParser FILES ${STEPParser_SRCS}) + IF ( ASSIMP_BUILD_NONFREE_C4D_IMPORTER ) SET( C4D_SRCS C4DImporter.cpp @@ -487,11 +495,8 @@ ADD_ASSIMP_IMPORTER( IFC Importer/IFC/IFCCurve.cpp Importer/IFC/IFCBoolean.cpp Importer/IFC/IFCOpenings.cpp - Importer/IFC/STEPFileReader.h - Importer/IFC/STEPFileReader.cpp - Importer/IFC/STEPFileEncoding.cpp - Importer/IFC/STEPFileEncoding.h ) + if (ASSIMP_BUILD_IFC_IMPORTER) if (MSVC) set_source_files_properties(Importer/IFC/IFCReaderGen1_2x3.cpp Importer/IFC/IFCReaderGen2_2x3.cpp PROPERTIES COMPILE_FLAGS "/bigobj") @@ -885,6 +890,7 @@ SET( assimp_src ${Exporter_SRCS} ${PostProcessing_SRCS} ${MaterialSystem_SRCS} + ${STEPParser_SRCS} ${Step_SRCS} # Model Support @@ -917,7 +923,7 @@ IF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER) ENDIF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER) ADD_LIBRARY( assimp ${assimp_src} ) -ADD_LIBRARY(assimp::asimp ALIAS assimp) +ADD_LIBRARY(assimp::assimp ALIAS assimp) TARGET_INCLUDE_DIRECTORIES ( assimp PUBLIC $ diff --git a/third_party/libassimp/code/D3MFImporter.cpp b/third_party/libassimp/code/D3MFImporter.cpp index bf0e6a1023..de57081491 100644 --- a/third_party/libassimp/code/D3MFImporter.cpp +++ b/third_party/libassimp/code/D3MFImporter.cpp @@ -419,8 +419,6 @@ private: } //namespace D3MF -static const std::string Extension = "3mf"; - static const aiImporterDesc desc = { "3mf Importer", "", @@ -431,7 +429,7 @@ static const aiImporterDesc desc = { 0, 0, 0, - Extension.c_str() + "3mf" }; D3MFImporter::D3MFImporter() @@ -445,7 +443,7 @@ D3MFImporter::~D3MFImporter() { bool D3MFImporter::CanRead(const std::string &filename, IOSystem *pIOHandler, bool checkSig) const { const std::string extension( GetExtension( filename ) ); - if(extension == Extension ) { + if(extension == desc.mFileExtensions ) { return true; } else if ( !extension.length() || checkSig ) { if ( nullptr == pIOHandler ) { diff --git a/third_party/libassimp/code/DXFHelper.h b/third_party/libassimp/code/DXFHelper.h index 00e66a0dbc..daf2f97e20 100644 --- a/third_party/libassimp/code/DXFHelper.h +++ b/third_party/libassimp/code/DXFHelper.h @@ -55,28 +55,21 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include namespace Assimp { - namespace DXF { - +namespace DXF { // read pairs of lines, parse group code and value and provide utilities // to convert the data to the target data type. -class LineReader -{ - +// do NOT skip empty lines. In DXF files, they count as valid data. +class LineReader { public: - LineReader(StreamReaderLE& reader) - // do NOT skip empty lines. In DXF files, they count as valid data. - : splitter(reader,false,true) - , groupcode( 0 ) - , value() - , end() - { + : splitter(reader,false,true) + , groupcode( 0 ) + , value() + , end() { + // empty } -public: - - // ----------------------------------------- bool Is(int gc, const char* what) const { return groupcode == gc && !strcmp(what,value.c_str()); @@ -102,8 +95,6 @@ public: return !((bool)*this); } -public: - // ----------------------------------------- unsigned int ValueAsUnsignedInt() const { return strtoul10(value.c_str()); @@ -119,8 +110,6 @@ public: return fast_atof(value.c_str()); } -public: - // ----------------------------------------- /** pseudo-iterator increment to advance to the next (groupcode/value) pair */ LineReader& operator++() { @@ -175,14 +164,12 @@ private: int end; }; - - // represents a POLYLINE or a LWPOLYLINE. or even a 3DFACE The data is converted as needed. -struct PolyLine -{ +struct PolyLine { PolyLine() - : flags() - {} + : flags() { + // empty + } std::vector positions; std::vector colors; @@ -194,14 +181,15 @@ struct PolyLine std::string desc; }; - // reference to a BLOCK. Specifies its own coordinate system. -struct InsertBlock -{ +struct InsertBlock { InsertBlock() - : scale(1.f,1.f,1.f) - , angle() - {} + : pos() + , scale(1.f,1.f,1.f) + , angle() + , name() { + // empty + } aiVector3D pos; aiVector3D scale; @@ -228,9 +216,7 @@ struct FileData std::vector blocks; }; +} +} // Namespace Assimp - - - -}} #endif diff --git a/third_party/libassimp/code/DXFLoader.cpp b/third_party/libassimp/code/DXFLoader.cpp index d317382dc6..6710597df0 100644 --- a/third_party/libassimp/code/DXFLoader.cpp +++ b/third_party/libassimp/code/DXFLoader.cpp @@ -63,16 +63,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. using namespace Assimp; // AutoCAD Binary DXF -#define AI_DXF_BINARY_IDENT ("AutoCAD Binary DXF\r\n\x1a\0") -#define AI_DXF_BINARY_IDENT_LEN (24) +const std::string AI_DXF_BINARY_IDENT = std::string("AutoCAD Binary DXF\r\n\x1a\0"); +const size_t AI_DXF_BINARY_IDENT_LEN = 24u; // default vertex color that all uncolored vertices will receive -#define AI_DXF_DEFAULT_COLOR aiColor4D(0.6f,0.6f,0.6f,0.6f) +const aiColor4D AI_DXF_DEFAULT_COLOR(aiColor4D(0.6f, 0.6f, 0.6f, 0.6f)); // color indices for DXF - 16 are supported, the table is // taken directly from the DXF spec. -static aiColor4D g_aclrDxfIndexColors[] = -{ +static aiColor4D g_aclrDxfIndexColors[] = { aiColor4D (0.6f, 0.6f, 0.6f, 1.0f), aiColor4D (1.0f, 0.0f, 0.0f, 1.0f), // red aiColor4D (0.0f, 1.0f, 0.0f, 1.0f), // green @@ -93,6 +92,10 @@ static aiColor4D g_aclrDxfIndexColors[] = #define AI_DXF_NUM_INDEX_COLORS (sizeof(g_aclrDxfIndexColors)/sizeof(g_aclrDxfIndexColors[0])) #define AI_DXF_ENTITIES_MAGIC_BLOCK "$ASSIMP_ENTITIES_MAGIC" +static const int GroupCode_Name = 2; +static const int GroupCode_XComp = 10; +static const int GroupCode_YComp = 20; +static const int GroupCode_ZComp = 30; static const aiImporterDesc desc = { "Drawing Interchange Format (DXF) Importer", @@ -110,24 +113,27 @@ static const aiImporterDesc desc = { // ------------------------------------------------------------------------------------------------ // Constructor to be privately used by Importer DXFImporter::DXFImporter() -{} +: BaseImporter() { + // empty +} // ------------------------------------------------------------------------------------------------ // Destructor, private as well -DXFImporter::~DXFImporter() -{} +DXFImporter::~DXFImporter() { + // empty +} // ------------------------------------------------------------------------------------------------ // Returns whether the class can handle the format of the given file. -bool DXFImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig ) const { - const std::string& extension = GetExtension( pFile ); - if ( extension == "dxf" ) { +bool DXFImporter::CanRead( const std::string& filename, IOSystem* pIOHandler, bool checkSig ) const { + const std::string& extension = GetExtension( filename ); + if ( extension == desc.mFileExtensions ) { return true; } if ( extension.empty() || checkSig ) { - static const char *pTokens[] = { "SECTION", "HEADER", "ENDSEC", "BLOCKS" }; - return BaseImporter::SearchFileHeaderForToken(pIOHandler, pFile, pTokens, 4, 32 ); + const char *pTokens[] = { "SECTION", "HEADER", "ENDSEC", "BLOCKS" }; + return BaseImporter::SearchFileHeaderForToken(pIOHandler, filename, pTokens, 4, 32 ); } return false; @@ -135,29 +141,25 @@ bool DXFImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool // ------------------------------------------------------------------------------------------------ // Get a list of all supported file extensions -const aiImporterDesc* DXFImporter::GetInfo () const -{ +const aiImporterDesc* DXFImporter::GetInfo () const { return &desc; } // ------------------------------------------------------------------------------------------------ // Imports the given file into the given scene structure. -void DXFImporter::InternReadFile( const std::string& pFile, - aiScene* pScene, - IOSystem* pIOHandler) -{ - std::shared_ptr file = std::shared_ptr( pIOHandler->Open( pFile) ); +void DXFImporter::InternReadFile( const std::string& filename, aiScene* pScene, IOSystem* pIOHandler) { + std::shared_ptr file = std::shared_ptr( pIOHandler->Open( filename) ); // Check whether we can read the file - if( file.get() == NULL) { - throw DeadlyImportError( "Failed to open DXF file " + pFile + ""); + if( file.get() == nullptr ) { + throw DeadlyImportError( "Failed to open DXF file " + filename + ""); } - // check whether this is a binaray DXF file - we can't read binary DXF files :-( + // Check whether this is a binary DXF file - we can't read binary DXF files :-( char buff[AI_DXF_BINARY_IDENT_LEN+1] = {0}; file->Read(buff,AI_DXF_BINARY_IDENT_LEN,1); - if (!strncmp(AI_DXF_BINARY_IDENT,buff,AI_DXF_BINARY_IDENT_LEN)) { + if (0 == strncmp(AI_DXF_BINARY_IDENT.c_str(),buff,AI_DXF_BINARY_IDENT_LEN)) { throw DeadlyImportError("DXF: Binary files are not supported at the moment"); } @@ -226,13 +228,11 @@ void DXFImporter::InternReadFile( const std::string& pFile, } // ------------------------------------------------------------------------------------------------ -void DXFImporter::ConvertMeshes(aiScene* pScene, DXF::FileData& output) -{ +void DXFImporter::ConvertMeshes(aiScene* pScene, DXF::FileData& output) { // the process of resolving all the INSERT statements can grow the // poly-count excessively, so log the original number. // XXX Option to import blocks as separate nodes? if (!DefaultLogger::isNullLogger()) { - unsigned int vcount = 0, icount = 0; for (const DXF::Block& bl : output.blocks) { for (std::shared_ptr pl : bl.lines) { @@ -293,7 +293,7 @@ void DXFImporter::ConvertMeshes(aiScene* pScene, DXF::FileData& output) } } - if (!pScene->mNumMeshes) { + if ( 0 == pScene->mNumMeshes) { throw DeadlyImportError("DXF: this file contains no 3d data"); } @@ -366,8 +366,7 @@ void DXFImporter::ConvertMeshes(aiScene* pScene, DXF::FileData& output) // ------------------------------------------------------------------------------------------------ -void DXFImporter::ExpandBlockReferences(DXF::Block& bl,const DXF::BlockMap& blocks_by_name) -{ +void DXFImporter::ExpandBlockReferences(DXF::Block& bl,const DXF::BlockMap& blocks_by_name) { for (const DXF::InsertBlock& insert : bl.insertions) { // first check if the referenced blocks exists ... @@ -407,8 +406,7 @@ void DXFImporter::ExpandBlockReferences(DXF::Block& bl,const DXF::BlockMap& bloc } // ------------------------------------------------------------------------------------------------ -void DXFImporter::GenerateMaterials(aiScene* pScene, DXF::FileData& /*output*/) -{ +void DXFImporter::GenerateMaterials(aiScene* pScene, DXF::FileData& /*output*/) { // generate an almost-white default material. Reason: // the default vertex color is GREY, so we are // already at Assimp's usual default color. @@ -433,8 +431,7 @@ void DXFImporter::GenerateMaterials(aiScene* pScene, DXF::FileData& /*output*/) } // ------------------------------------------------------------------------------------------------ -void DXFImporter::GenerateHierarchy(aiScene* pScene, DXF::FileData& /*output*/) -{ +void DXFImporter::GenerateHierarchy(aiScene* pScene, DXF::FileData& /*output*/) { // generate the output scene graph, which is just the root node with a single child for each layer. pScene->mRootNode = new aiNode(); pScene->mRootNode->mName.Set(""); @@ -488,17 +485,17 @@ void DXFImporter::ParseBlock(DXF::LineReader& reader, DXF::FileData& output) { while( !reader.End() && !reader.Is(0,"ENDBLK")) { switch(reader.GroupCode()) { - case 2: + case GroupCode_Name: block.name = reader.Value(); break; - case 10: + case GroupCode_XComp: block.base.x = reader.ValueAsFloat(); break; - case 20: + case GroupCode_YComp: block.base.y = reader.ValueAsFloat(); break; - case 30: + case GroupCode_ZComp: block.base.z = reader.ValueAsFloat(); break; } @@ -525,9 +522,8 @@ void DXFImporter::ParseBlock(DXF::LineReader& reader, DXF::FileData& output) { } // ------------------------------------------------------------------------------------------------ -void DXFImporter::ParseEntities(DXF::LineReader& reader, DXF::FileData& output) -{ - // push a new block onto the stack. +void DXFImporter::ParseEntities(DXF::LineReader& reader, DXF::FileData& output) { + // Push a new block onto the stack. output.blocks.push_back( DXF::Block() ); DXF::Block& block = output.blocks.back(); @@ -557,27 +553,25 @@ void DXFImporter::ParseEntities(DXF::LineReader& reader, DXF::FileData& output) " inserted blocks in ENTITIES" ); } -void DXFImporter::ParseInsertion(DXF::LineReader& reader, DXF::FileData& output) -{ +void DXFImporter::ParseInsertion(DXF::LineReader& reader, DXF::FileData& output) { output.blocks.back().insertions.push_back( DXF::InsertBlock() ); DXF::InsertBlock& bl = output.blocks.back().insertions.back(); while( !reader.End() && !reader.Is(0)) { - switch(reader.GroupCode()) - { + switch(reader.GroupCode()) { // name of referenced block - case 2: + case GroupCode_Name: bl.name = reader.Value(); break; // translation - case 10: + case GroupCode_XComp: bl.pos.x = reader.ValueAsFloat(); break; - case 20: + case GroupCode_YComp: bl.pos.y = reader.ValueAsFloat(); break; - case 30: + case GroupCode_ZComp: bl.pos.z = reader.ValueAsFloat(); break; @@ -704,8 +698,7 @@ void DXFImporter::ParsePolyLine(DXF::LineReader& reader, DXF::FileData& output) #define DXF_VERTEX_FLAG_HAS_POSITIONS 0x40 // ------------------------------------------------------------------------------------------------ -void DXFImporter::ParsePolyLineVertex(DXF::LineReader& reader, DXF::PolyLine& line) -{ +void DXFImporter::ParsePolyLineVertex(DXF::LineReader& reader, DXF::PolyLine& line) { unsigned int cnti = 0, flags = 0; unsigned int indices[4]; @@ -718,8 +711,7 @@ void DXFImporter::ParsePolyLineVertex(DXF::LineReader& reader, DXF::PolyLine& li break; } - switch (reader.GroupCode()) - { + switch (reader.GroupCode()) { case 8: // layer to which the vertex belongs to - assume that // this is always the layer the top-level poly-line @@ -734,9 +726,17 @@ void DXFImporter::ParsePolyLineVertex(DXF::LineReader& reader, DXF::PolyLine& li break; // VERTEX COORDINATES - case 10: out.x = reader.ValueAsFloat();break; - case 20: out.y = reader.ValueAsFloat();break; - case 30: out.z = reader.ValueAsFloat();break; + case GroupCode_XComp: + out.x = reader.ValueAsFloat(); + break; + + case GroupCode_YComp: + out.y = reader.ValueAsFloat(); + break; + + case GroupCode_ZComp: + out.z = reader.ValueAsFloat(); + break; // POLYFACE vertex indices case 71: @@ -770,6 +770,10 @@ void DXFImporter::ParsePolyLineVertex(DXF::LineReader& reader, DXF::PolyLine& li if (indices[i] == 0) { ASSIMP_LOG_WARN("DXF: invalid vertex index, indices are one-based."); --line.counts.back(); + // Workaround to fix issue 2229 + if (line.counts.back() == 0) { + line.counts.pop_back(); + } continue; } line.indices.push_back(indices[i]-1); @@ -808,62 +812,74 @@ void DXFImporter::Parse3DFace(DXF::LineReader& reader, DXF::FileData& output) break; // x position of the first corner - case 10: vip[0].x = reader.ValueAsFloat(); + case 10: + vip[0].x = reader.ValueAsFloat(); b[2] = true; break; // y position of the first corner - case 20: vip[0].y = reader.ValueAsFloat(); + case 20: + vip[0].y = reader.ValueAsFloat(); b[2] = true; break; // z position of the first corner - case 30: vip[0].z = reader.ValueAsFloat(); + case 30: + vip[0].z = reader.ValueAsFloat(); b[2] = true; break; // x position of the second corner - case 11: vip[1].x = reader.ValueAsFloat(); + case 11: + vip[1].x = reader.ValueAsFloat(); b[3] = true; break; // y position of the second corner - case 21: vip[1].y = reader.ValueAsFloat(); + case 21: + vip[1].y = reader.ValueAsFloat(); b[3] = true; break; // z position of the second corner - case 31: vip[1].z = reader.ValueAsFloat(); + case 31: + vip[1].z = reader.ValueAsFloat(); b[3] = true; break; // x position of the third corner - case 12: vip[2].x = reader.ValueAsFloat(); + case 12: + vip[2].x = reader.ValueAsFloat(); b[0] = true; break; // y position of the third corner - case 22: vip[2].y = reader.ValueAsFloat(); + case 22: + vip[2].y = reader.ValueAsFloat(); b[0] = true; break; // z position of the third corner - case 32: vip[2].z = reader.ValueAsFloat(); + case 32: + vip[2].z = reader.ValueAsFloat(); b[0] = true; break; // x position of the fourth corner - case 13: vip[3].x = reader.ValueAsFloat(); + case 13: + vip[3].x = reader.ValueAsFloat(); b[1] = true; break; // y position of the fourth corner - case 23: vip[3].y = reader.ValueAsFloat(); + case 23: + vip[3].y = reader.ValueAsFloat(); b[1] = true; break; // z position of the fourth corner - case 33: vip[3].z = reader.ValueAsFloat(); + case 33: + vip[3].z = reader.ValueAsFloat(); b[1] = true; break; diff --git a/third_party/libassimp/code/DXFLoader.h b/third_party/libassimp/code/DXFLoader.h index 487bb99f87..e7f534e985 100644 --- a/third_party/libassimp/code/DXFLoader.h +++ b/third_party/libassimp/code/DXFLoader.h @@ -50,32 +50,27 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include namespace Assimp { - namespace DXF { - class LineReader; - struct FileData; - struct PolyLine; - struct Block; - struct InsertBlock; - - typedef std::map BlockMap; - } +// Forward declarations +namespace DXF { + class LineReader; + struct FileData; + struct PolyLine; + struct Block; + struct InsertBlock; + typedef std::map BlockMap; +} // --------------------------------------------------------------------------- -/** DXF importer implementation. - * -*/ -class DXFImporter : public BaseImporter -{ +/** + * @brief DXF importer implementation. + */ +class DXFImporter : public BaseImporter { public: DXFImporter(); ~DXFImporter(); - - -public: - // ------------------------------------------------------------------- /** Returns whether the class can handle the format of the given file. * See BaseImporter::CanRead() for details. */ @@ -83,7 +78,6 @@ public: bool checkSig) const; protected: - // ------------------------------------------------------------------- /** Return importer meta information. * See #BaseImporter::GetInfo for the details*/ diff --git a/third_party/libassimp/code/Exporter.cpp b/third_party/libassimp/code/Exporter.cpp index 63a9340912..0acde75bf6 100644 --- a/third_party/libassimp/code/Exporter.cpp +++ b/third_party/libassimp/code/Exporter.cpp @@ -212,6 +212,7 @@ public: for( unsigned int a = 0; a < mPostProcessingSteps.size(); a++) { delete mPostProcessingSteps[a]; } + delete mProgressHandler; } public: @@ -246,10 +247,6 @@ Exporter :: Exporter() // ------------------------------------------------------------------------------------------------ Exporter::~Exporter() { FreeBlob(); - if (pimpl->mIsDefaultProgressHandler) { - delete pimpl->mProgressHandler; - pimpl->mProgressHandler = nullptr; - } delete pimpl; } diff --git a/third_party/libassimp/code/Importer/IFC/IFCLoader.cpp b/third_party/libassimp/code/Importer/IFC/IFCLoader.cpp index f1c99a0f40..4733555381 100644 --- a/third_party/libassimp/code/Importer/IFC/IFCLoader.cpp +++ b/third_party/libassimp/code/Importer/IFC/IFCLoader.cpp @@ -56,7 +56,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endif #include "IFCLoader.h" -#include "STEPFileReader.h" +#include "../STEPParser/STEPFileReader.h" #include "IFCUtil.h" diff --git a/third_party/libassimp/code/Importer/IFC/STEPFileEncoding.cpp b/third_party/libassimp/code/Importer/STEPParser/STEPFileEncoding.cpp similarity index 100% rename from third_party/libassimp/code/Importer/IFC/STEPFileEncoding.cpp rename to third_party/libassimp/code/Importer/STEPParser/STEPFileEncoding.cpp diff --git a/third_party/libassimp/code/Importer/IFC/STEPFileEncoding.h b/third_party/libassimp/code/Importer/STEPParser/STEPFileEncoding.h similarity index 100% rename from third_party/libassimp/code/Importer/IFC/STEPFileEncoding.h rename to third_party/libassimp/code/Importer/STEPParser/STEPFileEncoding.h diff --git a/third_party/libassimp/code/Importer/IFC/STEPFileReader.cpp b/third_party/libassimp/code/Importer/STEPParser/STEPFileReader.cpp similarity index 100% rename from third_party/libassimp/code/Importer/IFC/STEPFileReader.cpp rename to third_party/libassimp/code/Importer/STEPParser/STEPFileReader.cpp diff --git a/third_party/libassimp/code/Importer/IFC/STEPFileReader.h b/third_party/libassimp/code/Importer/STEPParser/STEPFileReader.h similarity index 100% rename from third_party/libassimp/code/Importer/IFC/STEPFileReader.h rename to third_party/libassimp/code/Importer/STEPParser/STEPFileReader.h diff --git a/third_party/libassimp/code/Importer/StepFile/StepFileImporter.cpp b/third_party/libassimp/code/Importer/StepFile/StepFileImporter.cpp index 9a34a84f57..9bfaf7051e 100644 --- a/third_party/libassimp/code/Importer/StepFile/StepFileImporter.cpp +++ b/third_party/libassimp/code/Importer/StepFile/StepFileImporter.cpp @@ -44,7 +44,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef ASSIMP_BUILD_NO_STEPFILE_IMPORTER #include "StepFileImporter.h" -#include "../../Importer/IFC/STEPFileReader.h" +#include "../../Importer/STEPParser/STEPFileReader.h" #include #include diff --git a/third_party/libassimp/code/MDLLoader.cpp b/third_party/libassimp/code/MDLLoader.cpp index dfe1c13119..eb067a1c94 100644 --- a/third_party/libassimp/code/MDLLoader.cpp +++ b/third_party/libassimp/code/MDLLoader.cpp @@ -413,8 +413,9 @@ void MDLImporter::InternReadFile_Quake1() { #if 1 // FIXME: the cast is wrong and cause a warning on clang 5.0 - // disable thi code for now, fix it later + // disable this code for now, fix it later ai_assert(false && "Bad pointer cast"); + pcFirstFrame = nullptr; // Workaround: msvc++ C4703 error #else BE_NCONST MDL::GroupFrame* pcFrames2 = (BE_NCONST MDL::GroupFrame*)pcFrames; pcFirstFrame = (BE_NCONST MDL::SimpleFrame*)(&pcFrames2->time + pcFrames->type); diff --git a/third_party/libassimp/code/MS3DLoader.cpp b/third_party/libassimp/code/MS3DLoader.cpp index b06bea31c9..c659d2ec7f 100644 --- a/third_party/libassimp/code/MS3DLoader.cpp +++ b/third_party/libassimp/code/MS3DLoader.cpp @@ -181,8 +181,7 @@ void MS3DImporter :: CollectChildJoints(const std::vector& joints, ch->mParent = nd; ch->mTransformation = aiMatrix4x4::Translation(joints[i].position,aiMatrix4x4()=aiMatrix4x4())* - // XXX actually, I don't *know* why we need the inverse here. Probably column vs. row order? - aiMatrix4x4().FromEulerAnglesXYZ(joints[i].rotation).Transpose(); + aiMatrix4x4().FromEulerAnglesXYZ(joints[i].rotation); const aiMatrix4x4 abs = absTrafo*ch->mTransformation; for(unsigned int a = 0; a < mScene->mNumMeshes; ++a) { @@ -639,11 +638,8 @@ void MS3DImporter::InternReadFile( const std::string& pFile, aiQuatKey& q = nd->mRotationKeys[nd->mNumRotationKeys++]; q.mTime = (*rot).time*animfps; - - // XXX it seems our matrix&quaternion code has faults in its conversion routines -- - // aiQuaternion(x,y,z) seems to besomething different as quat(matrix.fromeuler(x,y,z)). - q.mValue = aiQuaternion(aiMatrix3x3(aiMatrix4x4().FromEulerAnglesXYZ((*rot).value)* - aiMatrix4x4().FromEulerAnglesXYZ((*it).rotation)).Transpose()); + q.mValue = aiQuaternion(aiMatrix3x3(aiMatrix4x4().FromEulerAnglesXYZ((*it).rotation)* + aiMatrix4x4().FromEulerAnglesXYZ((*rot).value))); } } diff --git a/third_party/libassimp/code/OFFLoader.cpp b/third_party/libassimp/code/OFFLoader.cpp index 81f9c99166..a72e6d9d41 100644 --- a/third_party/libassimp/code/OFFLoader.cpp +++ b/third_party/libassimp/code/OFFLoader.cpp @@ -106,15 +106,23 @@ const aiImporterDesc* OFFImporter::GetInfo () const return &desc; } + +// skip blank space, lines and comments +static void NextToken(const char **car, const char* end) { + SkipSpacesAndLineEnd(car); + while (*car < end && (**car == '#' || **car == '\n' || **car == '\r')) { + SkipLine(car); + SkipSpacesAndLineEnd(car); + } +} + // ------------------------------------------------------------------------------------------------ // Imports the given file into the given scene structure. -void OFFImporter::InternReadFile( const std::string& pFile, - aiScene* pScene, IOSystem* pIOHandler) -{ +void OFFImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) { std::unique_ptr file( pIOHandler->Open( pFile, "rb")); // Check whether we can read from the file - if( file.get() == NULL) { + if( file.get() == nullptr) { throw DeadlyImportError( "Failed to open OFF file " + pFile + "."); } @@ -123,15 +131,61 @@ void OFFImporter::InternReadFile( const std::string& pFile, TextFileToBuffer(file.get(),mBuffer2); const char* buffer = &mBuffer2[0]; - char line[4096]; - GetNextLine(buffer,line); - if ('O' == line[0]) { - GetNextLine(buffer,line); // skip the 'OFF' line + // Proper OFF header parser. We only implement normal loading for now. + bool hasTexCoord = false, hasNormals = false, hasColors = false; + bool hasHomogenous = false, hasDimension = false; + unsigned int dimensions = 3; + const char* car = buffer; + const char* end = buffer + mBuffer2.size(); + NextToken(&car, end); + + if (car < end - 2 && car[0] == 'S' && car[1] == 'T') { + hasTexCoord = true; car += 2; + } + if (car < end - 1 && car[0] == 'C') { + hasColors = true; car++; + } + if (car < end- 1 && car[0] == 'N') { + hasNormals = true; car++; + } + if (car < end - 1 && car[0] == '4') { + hasHomogenous = true; car++; + } + if (car < end - 1 && car[0] == 'n') { + hasDimension = true; car++; + } + if (car < end - 3 && car[0] == 'O' && car[1] == 'F' && car[2] == 'F') { + car += 3; + NextToken(&car, end); + } else { + // in case there is no OFF header (which is allowed by the + // specification...), then we might have unintentionally read an + // additional dimension from the primitive count fields + dimensions = 3; + hasHomogenous = false; + NextToken(&car, end); + + // at this point the next token should be an integer number + if (car >= end - 1 || *car < '0' || *car > '9') { + throw DeadlyImportError("OFF: Header is invalid"); + } + } + if (hasDimension) { + dimensions = strtoul10(car, &car); + NextToken(&car, end); + } + if (dimensions > 3) { + throw DeadlyImportError + ("OFF: Number of vertex coordinates higher than 3 unsupported"); } - const char* sz = line; SkipSpaces(&sz); - const unsigned int numVertices = strtoul10(sz,&sz);SkipSpaces(&sz); - const unsigned int numFaces = strtoul10(sz,&sz); + NextToken(&car, end); + const unsigned int numVertices = strtoul10(car, &car); + NextToken(&car, end); + const unsigned int numFaces = strtoul10(car, &car); + NextToken(&car, end); + strtoul10(car, &car); // skip edge count + NextToken(&car, end); if (!numVertices) { throw DeadlyImportError("OFF: There are no valid vertices"); @@ -147,91 +201,127 @@ void OFFImporter::InternReadFile( const std::string& pFile, pScene->mMeshes[0] = mesh; mesh->mNumFaces = numFaces; - aiFace* faces = new aiFace [mesh->mNumFaces]; + aiFace* faces = new aiFace[mesh->mNumFaces]; mesh->mFaces = faces; - std::vector tempPositions(numVertices); + mesh->mNumVertices = numVertices; + mesh->mVertices = new aiVector3D[numVertices]; + mesh->mNormals = hasNormals ? new aiVector3D[numVertices] : nullptr; + mesh->mColors[0] = hasColors ? new aiColor4D[numVertices] : nullptr; + + if (hasTexCoord) { + mesh->mNumUVComponents[0] = 2; + mesh->mTextureCoords[0] = new aiVector3D[numVertices]; + } + char line[4096]; + buffer = car; + const char *sz = car; // now read all vertex lines - for (unsigned int i = 0; i< numVertices;++i) - { - if(!GetNextLine(buffer,line)) - { + for (unsigned int i = 0; i < numVertices; ++i) { + if(!GetNextLine(buffer, line)) { ASSIMP_LOG_ERROR("OFF: The number of verts in the header is incorrect"); break; } - aiVector3D& v = tempPositions[i]; + aiVector3D& v = mesh->mVertices[i]; + sz = line; - sz = line; SkipSpaces(&sz); - sz = fast_atoreal_move(sz,(ai_real&)v.x); SkipSpaces(&sz); - sz = fast_atoreal_move(sz,(ai_real&)v.y); SkipSpaces(&sz); - fast_atoreal_move(sz,(ai_real&)v.z); + // helper array to write a for loop over possible dimension values + ai_real* vec[3] = {&v.x, &v.y, &v.z}; + + // stop at dimensions: this allows loading 1D or 2D coordinate vertices + for (unsigned int dim = 0; dim < dimensions; ++dim ) { + SkipSpaces(&sz); + sz = fast_atoreal_move(sz, *vec[dim]); + } + + // if has homogenous coordinate, divide others by this one + if (hasHomogenous) { + SkipSpaces(&sz); + ai_real w = 1.; + sz = fast_atoreal_move(sz, w); + for (unsigned int dim = 0; dim < dimensions; ++dim ) { + *(vec[dim]) /= w; + } + } + + // read optional normals + if (hasNormals) { + aiVector3D& n = mesh->mNormals[i]; + SkipSpaces(&sz); + sz = fast_atoreal_move(sz,(ai_real&)n.x); + SkipSpaces(&sz); + sz = fast_atoreal_move(sz,(ai_real&)n.y); + SkipSpaces(&sz); + fast_atoreal_move(sz,(ai_real&)n.z); + } + + // reading colors is a pain because the specification says it can be + // integers or floats, and any number of them between 1 and 4 included, + // until the next comment or end of line + // in theory should be testing type ! + if (hasColors) { + aiColor4D& c = mesh->mColors[0][i]; + SkipSpaces(&sz); + sz = fast_atoreal_move(sz,(ai_real&)c.r); + if (*sz != '#' && *sz != '\n' && *sz != '\r') { + SkipSpaces(&sz); + sz = fast_atoreal_move(sz,(ai_real&)c.g); + } else { + c.g = 0.; + } + if (*sz != '#' && *sz != '\n' && *sz != '\r') { + SkipSpaces(&sz); + sz = fast_atoreal_move(sz,(ai_real&)c.b); + } else { + c.b = 0.; + } + if (*sz != '#' && *sz != '\n' && *sz != '\r') { + SkipSpaces(&sz); + sz = fast_atoreal_move(sz,(ai_real&)c.a); + } else { + c.a = 1.; + } + } + if (hasTexCoord) { + aiVector3D& t = mesh->mTextureCoords[0][i]; + SkipSpaces(&sz); + sz = fast_atoreal_move(sz,(ai_real&)t.x); + SkipSpaces(&sz); + fast_atoreal_move(sz,(ai_real&)t.y); + } } - - // First find out how many vertices we'll need - const char* old = buffer; - for (unsigned int i = 0; i< mesh->mNumFaces;++i) - { - if(!GetNextLine(buffer,line)) - { + // load faces with their indices + faces = mesh->mFaces; + for (unsigned int i = 0; i < numFaces; ) { + if(!GetNextLine(buffer,line)) { ASSIMP_LOG_ERROR("OFF: The number of faces in the header is incorrect"); break; } - sz = line;SkipSpaces(&sz); - faces->mNumIndices = strtoul10(sz,&sz); - if(!(faces->mNumIndices) || faces->mNumIndices > 9) - { - ASSIMP_LOG_ERROR("OFF: Faces with zero indices aren't allowed"); + unsigned int idx; + sz = line; SkipSpaces(&sz); + idx = strtoul10(sz,&sz); + if(!idx || idx > 9) { + ASSIMP_LOG_ERROR("OFF: Faces with zero indices aren't allowed"); --mesh->mNumFaces; continue; - } - mesh->mNumVertices += faces->mNumIndices; - ++faces; - } - - if (!mesh->mNumVertices) - throw DeadlyImportError("OFF: There are no valid faces"); - - // allocate storage for the output vertices - std::vector verts; - verts.reserve(mesh->mNumVertices); - - // second: now parse all face indices - buffer = old; - faces = mesh->mFaces; - for (unsigned int i = 0, p = 0; i< mesh->mNumFaces;) - { - if(!GetNextLine(buffer,line))break; - - unsigned int idx; - sz = line;SkipSpaces(&sz); - idx = strtoul10(sz,&sz); - if(!(idx) || idx > 9) - continue; - - faces->mIndices = new unsigned int [faces->mNumIndices]; - for (unsigned int m = 0; m < faces->mNumIndices;++m) - { + } + faces->mNumIndices = idx; + faces->mIndices = new unsigned int[faces->mNumIndices]; + for (unsigned int m = 0; m < faces->mNumIndices;++m) { SkipSpaces(&sz); idx = strtoul10(sz,&sz); - if ((idx) >= numVertices) - { + if (idx >= numVertices) { ASSIMP_LOG_ERROR("OFF: Vertex index is out of range"); - idx = numVertices-1; + idx = numVertices - 1; } - faces->mIndices[m] = p++; - verts.push_back(tempPositions[idx]); + faces->mIndices[m] = idx; } ++i; ++faces; } - - if (mesh->mNumVertices != verts.size()) { - throw DeadlyImportError("OFF: Vertex count mismatch"); - } - mesh->mVertices = new aiVector3D[verts.size()]; - memcpy(mesh->mVertices, &verts[0], verts.size() * sizeof(aiVector3D)); + // generate the output node graph pScene->mRootNode = new aiNode(); pScene->mRootNode->mName.Set(""); @@ -248,8 +338,8 @@ void OFFImporter::InternReadFile( const std::string& pFile, pcMat->AddProperty(&clr,1,AI_MATKEY_COLOR_DIFFUSE); pScene->mMaterials[0] = pcMat; - const int twosided =1; - pcMat->AddProperty(&twosided,1,AI_MATKEY_TWOSIDED); + const int twosided = 1; + pcMat->AddProperty(&twosided, 1, AI_MATKEY_TWOSIDED); } #endif // !! ASSIMP_BUILD_NO_OFF_IMPORTER diff --git a/third_party/libassimp/code/SMDLoader.cpp b/third_party/libassimp/code/SMDLoader.cpp index dc6706934b..c6ec616243 100644 --- a/third_party/libassimp/code/SMDLoader.cpp +++ b/third_party/libassimp/code/SMDLoader.cpp @@ -5,8 +5,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2018, assimp team - - All rights reserved. Redistribution and use of this software in source and binary forms, @@ -48,8 +46,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef ASSIMP_BUILD_NO_SMD_IMPORTER -// internal headers -#include "SMDLoader.h" #include #include #include @@ -58,6 +54,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include +#include + +// internal headers +#include "SMDLoader.h" + +#ifndef _WIN32 +#define strtok_s strtok_r +#endif using namespace Assimp; @@ -77,14 +82,14 @@ static const aiImporterDesc desc = { // ------------------------------------------------------------------------------------------------ // Constructor to be privately used by Importer SMDImporter::SMDImporter() -: configFrameID(), -mBuffer(), -pScene( nullptr ), -iFileSize( 0 ), -iSmallestFrame( -1 ), -dLengthOfAnim( 0.0 ), -bHasUVs(false ), -iLineNumber(-1) { +: configFrameID() +, mBuffer() +, pScene( nullptr ) +, iFileSize( 0 ) +, iSmallestFrame( INT_MAX ) +, dLengthOfAnim( 0.0 ) +, bHasUVs(false ) +, iLineNumber(-1) { // empty } @@ -96,23 +101,20 @@ SMDImporter::~SMDImporter() { // ------------------------------------------------------------------------------------------------ // Returns whether the class can handle the format of the given file. -bool SMDImporter::CanRead( const std::string& pFile, IOSystem* /*pIOHandler*/, bool) const -{ +bool SMDImporter::CanRead( const std::string& pFile, IOSystem* /*pIOHandler*/, bool) const { // fixme: auto format detection return SimpleExtensionCheck(pFile,"smd","vta"); } // ------------------------------------------------------------------------------------------------ // Get a list of all supported file extensions -const aiImporterDesc* SMDImporter::GetInfo () const -{ +const aiImporterDesc* SMDImporter::GetInfo () const { return &desc; } // ------------------------------------------------------------------------------------------------ // Setup configuration properties -void SMDImporter::SetupProperties(const Importer* pImp) -{ +void SMDImporter::SetupProperties(const Importer* pImp) { // The // AI_CONFIG_IMPORT_SMD_KEYFRAME option overrides the // AI_CONFIG_IMPORT_GLOBAL_KEYFRAME option. @@ -120,50 +122,21 @@ void SMDImporter::SetupProperties(const Importer* pImp) if(static_cast(-1) == configFrameID) { configFrameID = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_GLOBAL_KEYFRAME,0); } + + bLoadAnimationList = pImp->GetPropertyBool(AI_CONFIG_IMPORT_SMD_LOAD_ANIMATION_LIST, true); + noSkeletonMesh = pImp->GetPropertyBool(AI_CONFIG_IMPORT_NO_SKELETON_MESHES, false); } // ------------------------------------------------------------------------------------------------ // Imports the given file into the given scene structure. -void SMDImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) -{ - std::unique_ptr file( pIOHandler->Open( pFile, "rb")); - - // Check whether we can read from the file - if( file.get() == NULL) { - throw DeadlyImportError( "Failed to open SMD/VTA file " + pFile + "."); - } - - iFileSize = (unsigned int)file->FileSize(); - - // Allocate storage and copy the contents of the file to a memory buffer +void SMDImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) { this->pScene = pScene; - - mBuffer.resize( iFileSize + 1 ); - TextFileToBuffer(file.get(), mBuffer ); - - iSmallestFrame = (1 << 31); - bHasUVs = true; - iLineNumber = 1; - - // Reserve enough space for ... hm ... 10 textures - aszTextures.reserve(10); - - // Reserve enough space for ... hm ... 1000 triangles - asTriangles.reserve(1000); - - // Reserve enough space for ... hm ... 20 bones - asBones.reserve(20); - - - // parse the file ... - ParseFile(); + ReadSmd(pFile, pIOHandler); // If there are no triangles it seems to be an animation SMD, // containing only the animation skeleton. - if (asTriangles.empty()) - { - if (asBones.empty()) - { + if (asTriangles.empty()) { + if (asBones.empty()) { throw DeadlyImportError("SMD: No triangles and no bones have " "been found in the file. This file seems to be invalid."); } @@ -173,15 +146,12 @@ void SMDImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE; } - if (!asBones.empty()) - { + if (!asBones.empty()) { // Check whether all bones have been initialized for (std::vector::const_iterator - i = asBones.begin(); - i != asBones.end();++i) - { - if (!(*i).mName.length()) - { + i = asBones.begin(); + i != asBones.end();++i) { + if (!(*i).mName.length()) { ASSIMP_LOG_WARN("SMD: Not all bones have been initialized"); break; } @@ -189,64 +159,64 @@ void SMDImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS // now fix invalid time values and make sure the animation starts at frame 0 FixTimeValues(); - - // compute absolute bone transformation matrices - // ComputeAbsoluteBoneTransformations(); } - if (!(pScene->mFlags & AI_SCENE_FLAGS_INCOMPLETE)) - { + // build output nodes (bones are added as empty dummy nodes) + CreateOutputNodes(); + + if (!(pScene->mFlags & AI_SCENE_FLAGS_INCOMPLETE)) { // create output meshes CreateOutputMeshes(); // build an output material list CreateOutputMaterials(); + + // use root node that renders all meshes + pScene->mRootNode->mNumMeshes = pScene->mNumMeshes; + pScene->mRootNode->mMeshes = new unsigned int[pScene->mNumMeshes]; + for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) { + pScene->mRootNode->mMeshes[i] = i; + } } // build the output animation - CreateOutputAnimations(); + CreateOutputAnimations(pFile, pIOHandler); - // build output nodes (bones are added as empty dummy nodes) - CreateOutputNodes(); - - if (pScene->mFlags & AI_SCENE_FLAGS_INCOMPLETE) - { + if ((pScene->mFlags & AI_SCENE_FLAGS_INCOMPLETE) && !noSkeletonMesh) { SkeletonMeshBuilder skeleton(pScene); } } + // ------------------------------------------------------------------------------------------------ // Write an error message with line number to the log file -void SMDImporter::LogErrorNoThrow(const char* msg) -{ - char szTemp[1024]; - ai_snprintf(szTemp,1024,"Line %u: %s",iLineNumber,msg); +void SMDImporter::LogErrorNoThrow(const char* msg) { + const size_t BufferSize = 1024; + char szTemp[BufferSize]; + ai_snprintf(szTemp,BufferSize,"Line %u: %s",iLineNumber,msg); DefaultLogger::get()->error(szTemp); } // ------------------------------------------------------------------------------------------------ // Write a warning with line number to the log file -void SMDImporter::LogWarning(const char* msg) -{ - char szTemp[1024]; +void SMDImporter::LogWarning(const char* msg) { + const size_t BufferSize = 1024; + char szTemp[BufferSize]; ai_assert(strlen(msg) < 1000); - ai_snprintf(szTemp,1024,"Line %u: %s",iLineNumber,msg); + ai_snprintf(szTemp,BufferSize,"Line %u: %s",iLineNumber,msg); ASSIMP_LOG_WARN(szTemp); } // ------------------------------------------------------------------------------------------------ // Fix invalid time values in the file -void SMDImporter::FixTimeValues() -{ +void SMDImporter::FixTimeValues() { double dDelta = (double)iSmallestFrame; double dMax = 0.0f; for (std::vector::iterator - iBone = asBones.begin(); - iBone != asBones.end();++iBone) - { + iBone = asBones.begin(); + iBone != asBones.end();++iBone) { for (std::vector::iterator - iKey = (*iBone).sAnim.asKeys.begin(); - iKey != (*iBone).sAnim.asKeys.end();++iKey) - { + iKey = (*iBone).sAnim.asKeys.begin(); + iKey != (*iBone).sAnim.asKeys.end();++iKey) { (*iKey).dTime -= dDelta; dMax = std::max(dMax, (*iKey).dTime); } @@ -256,10 +226,10 @@ void SMDImporter::FixTimeValues() // ------------------------------------------------------------------------------------------------ // create output meshes -void SMDImporter::CreateOutputMeshes() -{ - if (aszTextures.empty()) +void SMDImporter::CreateOutputMeshes() { + if (aszTextures.empty()) { aszTextures.push_back(std::string()); + } // we need to sort all faces by their material index // in opposition to other loaders we can be sure that each @@ -273,28 +243,27 @@ void SMDImporter::CreateOutputMeshes() // approximate the space that will be required unsigned int iNum = (unsigned int)asTriangles.size() / pScene->mNumMeshes; iNum += iNum >> 1; - for (unsigned int i = 0; i < pScene->mNumMeshes;++i) + for (unsigned int i = 0; i < pScene->mNumMeshes;++i) { aaiFaces[i].reserve(iNum); - + } // collect all faces iNum = 0; for (std::vector::const_iterator - iFace = asTriangles.begin(); - iFace != asTriangles.end();++iFace,++iNum) - { - if (UINT_MAX == (*iFace).iTexture)aaiFaces[(*iFace).iTexture].push_back( 0 ); - else if ((*iFace).iTexture >= aszTextures.size()) - { + iFace = asTriangles.begin(); + iFace != asTriangles.end();++iFace,++iNum) { + if (UINT_MAX == (*iFace).iTexture) { + aaiFaces[(*iFace).iTexture].push_back( 0 ); + } else if ((*iFace).iTexture >= aszTextures.size()) { ASSIMP_LOG_INFO("[SMD/VTA] Material index overflow in face"); aaiFaces[(*iFace).iTexture].push_back((unsigned int)aszTextures.size()-1); + } else { + aaiFaces[(*iFace).iTexture].push_back(iNum); } - else aaiFaces[(*iFace).iTexture].push_back(iNum); } // now create the output meshes - for (unsigned int i = 0; i < pScene->mNumMeshes;++i) - { + for (unsigned int i = 0; i < pScene->mNumMeshes;++i) { aiMesh*& pcMesh = pScene->mMeshes[i] = new aiMesh(); ai_assert(!aaiFaces[i].empty()); // should not be empty ... @@ -310,8 +279,7 @@ void SMDImporter::CreateOutputMeshes() TempBoneWeightList* aaiBones = new TempBoneWeightList[asBones.size()](); // try to reserve enough memory without wasting too much - for (unsigned int iBone = 0; iBone < asBones.size();++iBone) - { + for (unsigned int iBone = 0; iBone < asBones.size();++iBone) { aaiBones[iBone].reserve(pcMesh->mNumVertices/asBones.size()); } @@ -320,16 +288,14 @@ void SMDImporter::CreateOutputMeshes() aiVector3D* pcNormals = pcMesh->mNormals = new aiVector3D[pcMesh->mNumVertices]; aiVector3D* pcVerts = pcMesh->mVertices = new aiVector3D[pcMesh->mNumVertices]; - aiVector3D* pcUVs = NULL; - if (bHasUVs) - { + aiVector3D* pcUVs = nullptr; + if (bHasUVs) { pcUVs = pcMesh->mTextureCoords[0] = new aiVector3D[pcMesh->mNumVertices]; pcMesh->mNumUVComponents[0] = 2; } iNum = 0; - for (unsigned int iFace = 0; iFace < pcMesh->mNumFaces;++iFace) - { + for (unsigned int iFace = 0; iFace < pcMesh->mNumFaces;++iFace) { pcMesh->mFaces[iFace].mIndices = new unsigned int[3]; pcMesh->mFaces[iFace].mNumIndices = 3; @@ -347,25 +313,20 @@ void SMDImporter::CreateOutputMeshes() *pcNormals++ = face.avVertices[2].nor; // fill the texture coordinates - if (pcUVs) - { + if (pcUVs) { *pcUVs++ = face.avVertices[0].uv; *pcUVs++ = face.avVertices[1].uv; *pcUVs++ = face.avVertices[2].uv; } - for (unsigned int iVert = 0; iVert < 3;++iVert) - { + for (unsigned int iVert = 0; iVert < 3;++iVert) { float fSum = 0.0f; - for (unsigned int iBone = 0;iBone < face.avVertices[iVert].aiBoneLinks.size();++iBone) - { + for (unsigned int iBone = 0;iBone < face.avVertices[iVert].aiBoneLinks.size();++iBone) { TempWeightListEntry& pairval = face.avVertices[iVert].aiBoneLinks[iBone]; // FIX: The second check is here just to make sure we won't // assign more than one weight to a single vertex index - if (pairval.first >= asBones.size() || - pairval.first == face.avVertices[iVert].iParentNode) - { + if (pairval.first >= asBones.size() || pairval.first == face.avVertices[iVert].iParentNode) { ASSIMP_LOG_ERROR("[SMD/VTA] Bone index overflow. " "The bone index will be ignored, the weight will be assigned " "to the vertex' parent node"); @@ -383,27 +344,23 @@ void SMDImporter::CreateOutputMeshes() // that the parent of a vertex is 0xffffffff (if the corresponding // entry in the file was unreadable) // ****************************************************************** - if (fSum < 0.975f && face.avVertices[iVert].iParentNode != UINT_MAX) - { - if (face.avVertices[iVert].iParentNode >= asBones.size()) - { + if (fSum < 0.975f && face.avVertices[iVert].iParentNode != UINT_MAX) { + if (face.avVertices[iVert].iParentNode >= asBones.size()) { ASSIMP_LOG_ERROR("[SMD/VTA] Bone index overflow. " "The index of the vertex parent bone is invalid. " "The remaining weights will be normalized to 1.0"); - if (fSum) - { + if (fSum) { fSum = 1 / fSum; - for (unsigned int iBone = 0;iBone < face.avVertices[iVert].aiBoneLinks.size();++iBone) - { + for (unsigned int iBone = 0;iBone < face.avVertices[iVert].aiBoneLinks.size();++iBone) { TempWeightListEntry& pairval = face.avVertices[iVert].aiBoneLinks[iBone]; - if (pairval.first >= asBones.size())continue; + if (pairval.first >= asBones.size()) { + continue; + } aaiBones[pairval.first].back().second *= fSum; } } - } - else - { + } else { aaiBones[face.avVertices[iVert].iParentNode].push_back( TempWeightListEntry(iNum,1.0f-fSum)); } @@ -414,17 +371,18 @@ void SMDImporter::CreateOutputMeshes() // now build all bones of the mesh iNum = 0; - for (unsigned int iBone = 0; iBone < asBones.size();++iBone) + for (unsigned int iBone = 0; iBone < asBones.size();++iBone) { if (!aaiBones[iBone].empty())++iNum; + } - if (false && iNum) - { + if (iNum) { pcMesh->mNumBones = iNum; pcMesh->mBones = new aiBone*[pcMesh->mNumBones]; iNum = 0; - for (unsigned int iBone = 0; iBone < asBones.size();++iBone) - { - if (aaiBones[iBone].empty())continue; + for (unsigned int iBone = 0; iBone < asBones.size();++iBone) { + if (aaiBones[iBone].empty()) { + continue; + } aiBone*& bone = pcMesh->mBones[iNum] = new aiBone(); bone->mNumWeights = (unsigned int)aaiBones[iBone].size(); @@ -434,8 +392,7 @@ void SMDImporter::CreateOutputMeshes() asBones[iBone].bIsUsed = true; - for (unsigned int iWeight = 0; iWeight < bone->mNumWeights;++iWeight) - { + for (unsigned int iWeight = 0; iWeight < bone->mNumWeights;++iWeight) { bone->mWeights[iWeight].mVertexId = aaiBones[iBone][iWeight].first; bone->mWeights[iWeight].mWeight = aaiBones[iBone][iWeight].second; } @@ -449,34 +406,44 @@ void SMDImporter::CreateOutputMeshes() // ------------------------------------------------------------------------------------------------ // add bone child nodes -void SMDImporter::AddBoneChildren(aiNode* pcNode, uint32_t iParent) -{ - ai_assert( NULL != pcNode ); +void SMDImporter::AddBoneChildren(aiNode* pcNode, uint32_t iParent) { + ai_assert( nullptr != pcNode ); ai_assert( 0 == pcNode->mNumChildren ); - ai_assert( NULL == pcNode->mChildren); + ai_assert( nullptr == pcNode->mChildren); // first count ... - for (unsigned int i = 0; i < asBones.size();++i) - { + for (unsigned int i = 0; i < asBones.size();++i) { SMD::Bone& bone = asBones[i]; - if (bone.iParent == iParent)++pcNode->mNumChildren; + if (bone.iParent == iParent) { + ++pcNode->mNumChildren; + } } // now allocate the output array pcNode->mChildren = new aiNode*[pcNode->mNumChildren]; // and fill all subnodes - unsigned int qq = 0; - for (unsigned int i = 0; i < asBones.size();++i) - { + unsigned int qq( 0 ); + for (unsigned int i = 0; i < asBones.size();++i) { SMD::Bone& bone = asBones[i]; - if (bone.iParent != iParent)continue; + if (bone.iParent != iParent) { + continue; + } aiNode* pc = pcNode->mChildren[qq++] = new aiNode(); pc->mName.Set(bone.mName); // store the local transformation matrix of the bind pose - pc->mTransformation = bone.sAnim.asKeys[bone.sAnim.iFirstTimeKey].matrix; + if (bone.sAnim.asKeys.size()) { + pc->mTransformation = bone.sAnim.asKeys[0].matrix; + } + + if (bone.iParent == static_cast(-1)) { + bone.mOffsetMatrix = pc->mTransformation; + } else { + bone.mOffsetMatrix = asBones[bone.iParent].mOffsetMatrix * pc->mTransformation; + } + pc->mParent = pcNode; // add children to this node, too @@ -486,31 +453,23 @@ void SMDImporter::AddBoneChildren(aiNode* pcNode, uint32_t iParent) // ------------------------------------------------------------------------------------------------ // create output nodes -void SMDImporter::CreateOutputNodes() -{ +void SMDImporter::CreateOutputNodes() { pScene->mRootNode = new aiNode(); - if (!(pScene->mFlags & AI_SCENE_FLAGS_INCOMPLETE)) - { - // create one root node that renders all meshes - pScene->mRootNode->mNumMeshes = pScene->mNumMeshes; - pScene->mRootNode->mMeshes = new unsigned int[pScene->mNumMeshes]; - for (unsigned int i = 0; i < pScene->mNumMeshes;++i) - pScene->mRootNode->mMeshes[i] = i; - } // now add all bones as dummy sub nodes to the graph - // AddBoneChildren(pScene->mRootNode,(uint32_t)-1); + AddBoneChildren(pScene->mRootNode,(uint32_t)-1); + for (auto &bone : asBones) { + bone.mOffsetMatrix.Inverse(); + } // if we have only one bone we can even remove the root node - if (pScene->mFlags & AI_SCENE_FLAGS_INCOMPLETE && - 1 == pScene->mRootNode->mNumChildren) - { + if (pScene->mFlags & AI_SCENE_FLAGS_INCOMPLETE && 1 == pScene->mRootNode->mNumChildren) { aiNode* pcOldRoot = pScene->mRootNode; pScene->mRootNode = pcOldRoot->mChildren[0]; - pcOldRoot->mChildren[0] = NULL; + pcOldRoot->mChildren[0] = nullptr; delete pcOldRoot; - pScene->mRootNode->mParent = NULL; + pScene->mRootNode->mParent = nullptr; } else { @@ -521,60 +480,63 @@ void SMDImporter::CreateOutputNodes() // ------------------------------------------------------------------------------------------------ // create output animations -void SMDImporter::CreateOutputAnimations() -{ - unsigned int iNumBones = 0; - for (std::vector::const_iterator - i = asBones.begin(); - i != asBones.end();++i) - { - if ((*i).bIsUsed)++iNumBones; - } - if (!iNumBones) - { - // just make sure this case doesn't occur ... (it could occur - // if the file was invalid) - return; - } +void SMDImporter::CreateOutputAnimations(const std::string &pFile, IOSystem* pIOHandler) { + std::vector> animFileList; + if (bLoadAnimationList) { + GetAnimationFileList(pFile, pIOHandler, animFileList); + } + int animCount = animFileList.size() + 1; pScene->mNumAnimations = 1; - pScene->mAnimations = new aiAnimation*[1]; - aiAnimation*& anim = pScene->mAnimations[0] = new aiAnimation(); + pScene->mAnimations = new aiAnimation*[animCount]; + memset(pScene->mAnimations, 0, sizeof(aiAnimation*)*animCount); + CreateOutputAnimation(0, ""); + for (auto &animFile : animFileList) { + ReadSmd(std::get<1>(animFile), pIOHandler); + if (asBones.empty()) { + continue; + } + + FixTimeValues(); + CreateOutputAnimation(pScene->mNumAnimations++, std::get<0>(animFile)); + } +} + +void SMDImporter::CreateOutputAnimation(int index, const std::string &name) { + aiAnimation*& anim = pScene->mAnimations[index] = new aiAnimation(); + + if (name.length()) { + anim->mName.Set(name.c_str()); + } anim->mDuration = dLengthOfAnim; - anim->mNumChannels = iNumBones; + anim->mNumChannels = asBones.size(); anim->mTicksPerSecond = 25.0; // FIXME: is this correct? aiNodeAnim** pp = anim->mChannels = new aiNodeAnim*[anim->mNumChannels]; // now build valid keys unsigned int a = 0; - for (std::vector::const_iterator - i = asBones.begin(); - i != asBones.end();++i) - { - if (!(*i).bIsUsed)continue; - + for (std::vector::const_iterator i = asBones.begin(); i != asBones.end(); ++i) { aiNodeAnim* p = pp[a] = new aiNodeAnim(); // copy the name of the bone - p->mNodeName.Set( i->mName); + p->mNodeName.Set(i->mName); - p->mNumRotationKeys = (unsigned int) (*i).sAnim.asKeys.size(); - if (p->mNumRotationKeys) - { + p->mNumRotationKeys = (unsigned int)(*i).sAnim.asKeys.size(); + if (p->mNumRotationKeys){ p->mNumPositionKeys = p->mNumRotationKeys; aiVectorKey* pVecKeys = p->mPositionKeys = new aiVectorKey[p->mNumRotationKeys]; aiQuatKey* pRotKeys = p->mRotationKeys = new aiQuatKey[p->mNumRotationKeys]; for (std::vector::const_iterator - qq = (*i).sAnim.asKeys.begin(); - qq != (*i).sAnim.asKeys.end(); ++qq) - { + qq = (*i).sAnim.asKeys.begin(); + qq != (*i).sAnim.asKeys.end(); ++qq) { pRotKeys->mTime = pVecKeys->mTime = (*qq).dTime; // compute the rotation quaternion from the euler angles - pRotKeys->mValue = aiQuaternion( (*qq).vRot.x, (*qq).vRot.y, (*qq).vRot.z ); + // aiQuaternion: The order of the parameters is yzx? + pRotKeys->mValue = aiQuaternion((*qq).vRot.y, (*qq).vRot.z, (*qq).vRot.x); pVecKeys->mValue = (*qq).vPos; ++pVecKeys; ++pRotKeys; @@ -586,71 +548,57 @@ void SMDImporter::CreateOutputAnimations() } } -// ------------------------------------------------------------------------------------------------ -void SMDImporter::ComputeAbsoluteBoneTransformations() -{ - // For each bone: determine the key with the lowest time value - // theoretically the SMD format should have all keyframes - // in order. However, I've seen a file where this wasn't true. - for (unsigned int i = 0; i < asBones.size();++i) - { - SMD::Bone& bone = asBones[i]; +void SMDImporter::GetAnimationFileList(const std::string &pFile, IOSystem* pIOHandler, std::vector>& outList) { + auto base = DefaultIOSystem::absolutePath(pFile); + auto name = DefaultIOSystem::completeBaseName(pFile); + auto path = base + "/" + name + "_animation.txt"; - uint32_t iIndex = 0; - double dMin = 10e10; - for (unsigned int i = 0; i < bone.sAnim.asKeys.size();++i) - { - double d = std::min(bone.sAnim.asKeys[i].dTime,dMin); - if (d < dMin) - { - dMin = d; - iIndex = i; - } - } - bone.sAnim.iFirstTimeKey = iIndex; + std::unique_ptr file(pIOHandler->Open(path.c_str(), "rb")); + if (file.get() == nullptr) { + return; } - unsigned int iParent = 0; - while (iParent < asBones.size()) - { - for (unsigned int iBone = 0; iBone < asBones.size();++iBone) - { - SMD::Bone& bone = asBones[iBone]; + // Allocate storage and copy the contents of the file to a memory buffer + std::vector buf; + size_t fileSize = file->FileSize(); + buf.resize(fileSize + 1); + TextFileToBuffer(file.get(), buf); - if (iParent == bone.iParent) - { - SMD::Bone& parentBone = asBones[iParent]; + /* + *_animation.txt format: + name path + idle idle.smd + jump anim/jump.smd + walk.smd + ... + */ + std::string animName, animPath; + char *tok1, *tok2; + char *context1, *context2; - - uint32_t iIndex = bone.sAnim.iFirstTimeKey; - const aiMatrix4x4& mat = bone.sAnim.asKeys[iIndex].matrix; - aiMatrix4x4& matOut = bone.sAnim.asKeys[iIndex].matrixAbsolute; - - // The same for the parent bone ... - iIndex = parentBone.sAnim.iFirstTimeKey; - const aiMatrix4x4& mat2 = parentBone.sAnim.asKeys[iIndex].matrixAbsolute; - - // Compute the absolute transformation matrix - matOut = mat * mat2; + tok1 = strtok_s(&buf[0], "\r\n", &context1); + while (tok1 != NULL) { + tok2 = strtok_s(tok1, " \t", &context2); + if (tok2) { + char *p = tok2; + tok2 = strtok_s(nullptr, " \t", &context2); + if (tok2) { + animPath = tok2; + animName = p; + } else { + // No name + animPath = p; + animName = DefaultIOSystem::completeBaseName(animPath); } + outList.push_back(std::make_tuple(animName, base + "/" + animPath)); } - ++iParent; - } - - // Store the inverse of the absolute transformation matrix - // of the first key as bone offset matrix - for (iParent = 0; iParent < asBones.size();++iParent) - { - SMD::Bone& bone = asBones[iParent]; - bone.mOffsetMatrix = bone.sAnim.asKeys[bone.sAnim.iFirstTimeKey].matrixAbsolute; - bone.mOffsetMatrix.Inverse(); + tok1 = strtok_s(nullptr, "\r\n", &context1); } } -\ + // ------------------------------------------------------------------------------------------------ // create output materials -void SMDImporter::CreateOutputMaterials() -{ +void SMDImporter::CreateOutputMaterials() { ai_assert( nullptr != pScene ); pScene->mNumMaterials = (unsigned int)aszTextures.size(); @@ -674,14 +622,13 @@ void SMDImporter::CreateOutputMaterials() } // create a default material if necessary - if (0 == pScene->mNumMaterials) - { + if (0 == pScene->mNumMaterials) { pScene->mNumMaterials = 1; aiMaterial* pcHelper = new aiMaterial(); pScene->mMaterials[0] = pcHelper; - int iMode = (int)aiShadingMode_Gouraud; + int iMode = static_cast(aiShadingMode_Gouraud); pcHelper->AddProperty(&iMode, 1, AI_MATKEY_SHADING_MODEL); aiColor3D clr; @@ -700,66 +647,94 @@ void SMDImporter::CreateOutputMaterials() // ------------------------------------------------------------------------------------------------ // Parse the file -void SMDImporter::ParseFile() -{ +void SMDImporter::ParseFile() { const char* szCurrent = &mBuffer[0]; // read line per line ... - for ( ;; ) - { - if(!SkipSpacesAndLineEnd(szCurrent,&szCurrent)) break; + for ( ;; ) { + if(!SkipSpacesAndLineEnd(szCurrent,&szCurrent)) { + break; + } // "version \n", should be 1 for hl and hl2 SMD files - if (TokenMatch(szCurrent,"version",7)) - { + if (TokenMatch(szCurrent,"version",7)) { if(!SkipSpaces(szCurrent,&szCurrent)) break; - if (1 != strtoul10(szCurrent,&szCurrent)) - { + if (1 != strtoul10(szCurrent,&szCurrent)) { ASSIMP_LOG_WARN("SMD.version is not 1. This " "file format is not known. Continuing happily ..."); } continue; } // "nodes\n" - Starts the node section - if (TokenMatch(szCurrent,"nodes",5)) - { + if (TokenMatch(szCurrent,"nodes",5)) { ParseNodesSection(szCurrent,&szCurrent); continue; } // "triangles\n" - Starts the triangle section - if (TokenMatch(szCurrent,"triangles",9)) - { + if (TokenMatch(szCurrent,"triangles",9)) { ParseTrianglesSection(szCurrent,&szCurrent); continue; } // "vertexanimation\n" - Starts the vertex animation section - if (TokenMatch(szCurrent,"vertexanimation",15)) - { + if (TokenMatch(szCurrent,"vertexanimation",15)) { bHasUVs = false; ParseVASection(szCurrent,&szCurrent); continue; } // "skeleton\n" - Starts the skeleton section - if (TokenMatch(szCurrent,"skeleton",8)) - { + if (TokenMatch(szCurrent,"skeleton",8)) { ParseSkeletonSection(szCurrent,&szCurrent); continue; } SkipLine(szCurrent,&szCurrent); } - return; +} + +void SMDImporter::ReadSmd(const std::string &pFile, IOSystem* pIOHandler) { + std::unique_ptr file(pIOHandler->Open(pFile, "rb")); + + // Check whether we can read from the file + if (file.get() == nullptr) { + throw DeadlyImportError("Failed to open SMD/VTA file " + pFile + "."); + } + + iFileSize = (unsigned int)file->FileSize(); + + // Allocate storage and copy the contents of the file to a memory buffer + mBuffer.resize(iFileSize + 1); + TextFileToBuffer(file.get(), mBuffer); + + iSmallestFrame = INT_MAX; + bHasUVs = true; + iLineNumber = 1; + + // Reserve enough space for ... hm ... 10 textures + aszTextures.reserve(10); + + // Reserve enough space for ... hm ... 1000 triangles + asTriangles.reserve(1000); + + // Reserve enough space for ... hm ... 20 bones + asBones.reserve(20); + + aszTextures.clear(); + asTriangles.clear(); + asBones.clear(); + + // parse the file ... + ParseFile(); } // ------------------------------------------------------------------------------------------------ -unsigned int SMDImporter::GetTextureIndex(const std::string& filename) -{ +unsigned int SMDImporter::GetTextureIndex(const std::string& filename) { unsigned int iIndex = 0; for (std::vector::const_iterator - i = aszTextures.begin(); - i != aszTextures.end();++i,++iIndex) - { + i = aszTextures.begin(); + i != aszTextures.end();++i,++iIndex) { // case-insensitive ... it's a path - if (0 == ASSIMP_stricmp ( filename.c_str(),(*i).c_str()))return iIndex; + if (0 == ASSIMP_stricmp ( filename.c_str(),(*i).c_str())) { + return iIndex; + } } iIndex = (unsigned int)aszTextures.size(); aszTextures.push_back(filename); @@ -768,15 +743,10 @@ unsigned int SMDImporter::GetTextureIndex(const std::string& filename) // ------------------------------------------------------------------------------------------------ // Parse the nodes section of the file -void SMDImporter::ParseNodesSection(const char* szCurrent, - const char** szCurrentOut) -{ - for ( ;; ) - { +void SMDImporter::ParseNodesSection(const char* szCurrent, const char** szCurrentOut) { + for ( ;; ) { // "end\n" - Ends the nodes section - if (0 == ASSIMP_strincmp(szCurrent,"end",3) && - IsSpaceOrNewLine(*(szCurrent+3))) - { + if (0 == ASSIMP_strincmp(szCurrent,"end",3) && IsSpaceOrNewLine(*(szCurrent+3))) { szCurrent += 4; break; } @@ -788,18 +758,18 @@ void SMDImporter::ParseNodesSection(const char* szCurrent, // ------------------------------------------------------------------------------------------------ // Parse the triangles section of the file -void SMDImporter::ParseTrianglesSection(const char* szCurrent, - const char** szCurrentOut) -{ +void SMDImporter::ParseTrianglesSection(const char* szCurrent, const char** szCurrentOut) { // Parse a triangle, parse another triangle, parse the next triangle ... // and so on until we reach a token that looks quite similar to "end" - for ( ;; ) - { - if(!SkipSpacesAndLineEnd(szCurrent,&szCurrent)) break; + for ( ;; ) { + if(!SkipSpacesAndLineEnd(szCurrent,&szCurrent)) { + break; + } // "end\n" - Ends the triangles section - if (TokenMatch(szCurrent,"end",3)) + if (TokenMatch(szCurrent,"end",3)) { break; + } ParseTriangle(szCurrent,&szCurrent); } SkipSpacesAndLineEnd(szCurrent,&szCurrent); @@ -807,40 +777,39 @@ void SMDImporter::ParseTrianglesSection(const char* szCurrent, } // ------------------------------------------------------------------------------------------------ // Parse the vertex animation section of the file -void SMDImporter::ParseVASection(const char* szCurrent, - const char** szCurrentOut) -{ +void SMDImporter::ParseVASection(const char* szCurrent, const char** szCurrentOut) { unsigned int iCurIndex = 0; - for ( ;; ) - { - if(!SkipSpacesAndLineEnd(szCurrent,&szCurrent)) break; + for ( ;; ) { + if (!SkipSpacesAndLineEnd(szCurrent,&szCurrent)) { + break; + } // "end\n" - Ends the "vertexanimation" section - if (TokenMatch(szCurrent,"end",3)) + if (TokenMatch(szCurrent,"end",3)) { break; + } // "time \n" - if (TokenMatch(szCurrent,"time",4)) - { + if (TokenMatch(szCurrent,"time",4)) { // NOTE: The doc says that time values COULD be negative ... // NOTE2: this is the shape key -> valve docs int iTime = 0; - if(!ParseSignedInt(szCurrent,&szCurrent,iTime) || configFrameID != (unsigned int)iTime)break; + if(!ParseSignedInt(szCurrent,&szCurrent,iTime) || configFrameID != (unsigned int)iTime) { + break; + } SkipLine(szCurrent,&szCurrent); - } - else - { - if(0 == iCurIndex) - { + } else { + if(0 == iCurIndex) { asTriangles.push_back(SMD::Face()); } - if (++iCurIndex == 3)iCurIndex = 0; + if (++iCurIndex == 3) { + iCurIndex = 0; + } ParseVertex(szCurrent,&szCurrent,asTriangles.back().avVertices[iCurIndex],true); } } - if (iCurIndex != 2 && !asTriangles.empty()) - { + if (iCurIndex != 2 && !asTriangles.empty()) { // we want to no degenerates, so throw this triangle away asTriangles.pop_back(); } @@ -848,30 +817,30 @@ void SMDImporter::ParseVASection(const char* szCurrent, SkipSpacesAndLineEnd(szCurrent,&szCurrent); *szCurrentOut = szCurrent; } + // ------------------------------------------------------------------------------------------------ // Parse the skeleton section of the file -void SMDImporter::ParseSkeletonSection(const char* szCurrent, - const char** szCurrentOut) -{ +void SMDImporter::ParseSkeletonSection(const char* szCurrent, const char** szCurrentOut) { int iTime = 0; - for ( ;; ) - { - if(!SkipSpacesAndLineEnd(szCurrent,&szCurrent)) break; + for ( ;; ) { + if (!SkipSpacesAndLineEnd(szCurrent,&szCurrent)) { + break; + } // "end\n" - Ends the skeleton section - if (TokenMatch(szCurrent,"end",3)) + if (TokenMatch(szCurrent,"end",3)) { break; - + } else if (TokenMatch(szCurrent,"time",4)) { // "time \n" - Specifies the current animation frame - else if (TokenMatch(szCurrent,"time",4)) - { - // NOTE: The doc says that time values COULD be negative ... - if(!ParseSignedInt(szCurrent,&szCurrent,iTime))break; + if(!ParseSignedInt(szCurrent,&szCurrent,iTime)) { + break; + } iSmallestFrame = std::min(iSmallestFrame,iTime); SkipLine(szCurrent,&szCurrent); + } else { + ParseSkeletonElement(szCurrent,&szCurrent,iTime); } - else ParseSkeletonElement(szCurrent,&szCurrent,iTime); } *szCurrentOut = szCurrent; } @@ -884,45 +853,38 @@ void SMDImporter::ParseSkeletonSection(const char* szCurrent, } // ------------------------------------------------------------------------------------------------ // Parse a node line -void SMDImporter::ParseNodeInfo(const char* szCurrent, - const char** szCurrentOut) -{ +void SMDImporter::ParseNodeInfo(const char* szCurrent, const char** szCurrentOut) { unsigned int iBone = 0; SkipSpacesAndLineEnd(szCurrent,&szCurrent); - if(!ParseUnsignedInt(szCurrent,&szCurrent,iBone) || !SkipSpaces(szCurrent,&szCurrent)) - { + if ( !ParseUnsignedInt(szCurrent,&szCurrent,iBone) || !SkipSpaces(szCurrent,&szCurrent)) { LogErrorNoThrow("Unexpected EOF/EOL while parsing bone index"); SMDI_PARSE_RETURN; } // add our bone to the list - if (iBone >= asBones.size())asBones.resize(iBone+1); + if (iBone >= asBones.size()) { + asBones.resize(iBone+1); + } SMD::Bone& bone = asBones[iBone]; bool bQuota = true; - if ('\"' != *szCurrent) - { + if ('\"' != *szCurrent) { LogWarning("Bone name is expcted to be enclosed in " "double quotation marks. "); bQuota = false; + } else { + ++szCurrent; } - else ++szCurrent; const char* szEnd = szCurrent; - for ( ;; ) - { - if (bQuota && '\"' == *szEnd) - { + for ( ;; ) { + if (bQuota && '\"' == *szEnd) { iBone = (unsigned int)(szEnd - szCurrent); ++szEnd; break; - } - else if (IsSpaceOrNewLine(*szEnd)) - { + } else if (!bQuota && IsSpaceOrNewLine(*szEnd)) { iBone = (unsigned int)(szEnd - szCurrent); break; - } - else if (!(*szEnd)) - { + } else if (!(*szEnd)) { LogErrorNoThrow("Unexpected EOF/EOL while parsing bone name"); SMDI_PARSE_RETURN; } @@ -932,8 +894,7 @@ void SMDImporter::ParseNodeInfo(const char* szCurrent, szCurrent = szEnd; // the only negative bone parent index that could occur is -1 AFAIK - if(!ParseSignedInt(szCurrent,&szCurrent,(int&)bone.iParent)) - { + if(!ParseSignedInt(szCurrent,&szCurrent,(int&)bone.iParent)) { LogErrorNoThrow("Unexpected EOF/EOL while parsing bone parent index. Assuming -1"); SMDI_PARSE_RETURN; } @@ -944,20 +905,16 @@ void SMDImporter::ParseNodeInfo(const char* szCurrent, // ------------------------------------------------------------------------------------------------ // Parse a skeleton element -void SMDImporter::ParseSkeletonElement(const char* szCurrent, - const char** szCurrentOut,int iTime) -{ +void SMDImporter::ParseSkeletonElement(const char* szCurrent, const char** szCurrentOut,int iTime) { aiVector3D vPos; aiVector3D vRot; unsigned int iBone = 0; - if(!ParseUnsignedInt(szCurrent,&szCurrent,iBone)) - { + if(!ParseUnsignedInt(szCurrent,&szCurrent,iBone)) { ASSIMP_LOG_ERROR("Unexpected EOF/EOL while parsing bone index"); SMDI_PARSE_RETURN; } - if (iBone >= asBones.size()) - { + if (iBone >= asBones.size()) { LogErrorNoThrow("Bone index in skeleton section is out of range"); SMDI_PARSE_RETURN; } @@ -967,60 +924,51 @@ void SMDImporter::ParseSkeletonElement(const char* szCurrent, SMD::Bone::Animation::MatrixKey& key = bone.sAnim.asKeys.back(); key.dTime = (double)iTime; - if(!ParseFloat(szCurrent,&szCurrent,(float&)vPos.x)) - { + if(!ParseFloat(szCurrent,&szCurrent,(float&)vPos.x)) { LogErrorNoThrow("Unexpected EOF/EOL while parsing bone.pos.x"); SMDI_PARSE_RETURN; } - if(!ParseFloat(szCurrent,&szCurrent,(float&)vPos.y)) - { + if(!ParseFloat(szCurrent,&szCurrent,(float&)vPos.y)) { LogErrorNoThrow("Unexpected EOF/EOL while parsing bone.pos.y"); SMDI_PARSE_RETURN; } - if(!ParseFloat(szCurrent,&szCurrent,(float&)vPos.z)) - { + if(!ParseFloat(szCurrent,&szCurrent,(float&)vPos.z)) { LogErrorNoThrow("Unexpected EOF/EOL while parsing bone.pos.z"); SMDI_PARSE_RETURN; } - if(!ParseFloat(szCurrent,&szCurrent,(float&)vRot.x)) - { + if(!ParseFloat(szCurrent,&szCurrent,(float&)vRot.x)) { LogErrorNoThrow("Unexpected EOF/EOL while parsing bone.rot.x"); SMDI_PARSE_RETURN; } - if(!ParseFloat(szCurrent,&szCurrent,(float&)vRot.y)) - { + if(!ParseFloat(szCurrent,&szCurrent,(float&)vRot.y)) { LogErrorNoThrow("Unexpected EOF/EOL while parsing bone.rot.y"); SMDI_PARSE_RETURN; } - if(!ParseFloat(szCurrent,&szCurrent,(float&)vRot.z)) - { + if(!ParseFloat(szCurrent,&szCurrent,(float&)vRot.z)) { LogErrorNoThrow("Unexpected EOF/EOL while parsing bone.rot.z"); SMDI_PARSE_RETURN; } // build the transformation matrix of the key - key.matrix.FromEulerAnglesXYZ(vRot.x,vRot.y,vRot.z); - { + key.matrix.FromEulerAnglesXYZ(vRot.x,vRot.y,vRot.z); { aiMatrix4x4 mTemp; mTemp.a4 = vPos.x; mTemp.b4 = vPos.y; mTemp.c4 = vPos.z; - key.matrix = key.matrix * mTemp; + key.matrix = mTemp * key.matrix; } - + key.vPos = vPos; + key.vRot = vRot; // go to the beginning of the next line SMDI_PARSE_RETURN; } // ------------------------------------------------------------------------------------------------ // Parse a triangle -void SMDImporter::ParseTriangle(const char* szCurrent, - const char** szCurrentOut) -{ +void SMDImporter::ParseTriangle(const char* szCurrent, const char** szCurrentOut) { asTriangles.push_back(SMD::Face()); SMD::Face& face = asTriangles.back(); - if(!SkipSpaces(szCurrent,&szCurrent)) - { + if(!SkipSpaces(szCurrent,&szCurrent)) { LogErrorNoThrow("Unexpected EOF/EOL while parsing a triangle"); return; } @@ -1035,21 +983,18 @@ void SMDImporter::ParseTriangle(const char* szCurrent, SkipSpacesAndLineEnd(szCurrent,&szCurrent); // load three vertices - for (unsigned int iVert = 0; iVert < 3;++iVert) - { - ParseVertex(szCurrent,&szCurrent, - face.avVertices[iVert]); + for (unsigned int iVert = 0; iVert < 3;++iVert) { + ParseVertex(szCurrent,&szCurrent, face.avVertices[iVert]); } *szCurrentOut = szCurrent; } // ------------------------------------------------------------------------------------------------ // Parse a float -bool SMDImporter::ParseFloat(const char* szCurrent, - const char** szCurrentOut, float& out) -{ - if(!SkipSpaces(&szCurrent)) +bool SMDImporter::ParseFloat(const char* szCurrent, const char** szCurrentOut, float& out) { + if(!SkipSpaces(&szCurrent)) { return false; + } *szCurrentOut = fast_atoreal_move(szCurrent,out); return true; @@ -1057,11 +1002,10 @@ bool SMDImporter::ParseFloat(const char* szCurrent, // ------------------------------------------------------------------------------------------------ // Parse an unsigned int -bool SMDImporter::ParseUnsignedInt(const char* szCurrent, - const char** szCurrentOut, unsigned int& out) -{ - if(!SkipSpaces(&szCurrent)) +bool SMDImporter::ParseUnsignedInt(const char* szCurrent, const char** szCurrentOut, unsigned int& out) { + if(!SkipSpaces(&szCurrent)) { return false; + } out = strtoul10(szCurrent,szCurrentOut); return true; @@ -1069,11 +1013,10 @@ bool SMDImporter::ParseUnsignedInt(const char* szCurrent, // ------------------------------------------------------------------------------------------------ // Parse a signed int -bool SMDImporter::ParseSignedInt(const char* szCurrent, - const char** szCurrentOut, int& out) -{ - if(!SkipSpaces(&szCurrent)) +bool SMDImporter::ParseSignedInt(const char* szCurrent, const char** szCurrentOut, int& out) { + if(!SkipSpaces(&szCurrent)) { return false; + } out = strtol10(szCurrent,szCurrentOut); return true; @@ -1082,59 +1025,50 @@ bool SMDImporter::ParseSignedInt(const char* szCurrent, // ------------------------------------------------------------------------------------------------ // Parse a vertex void SMDImporter::ParseVertex(const char* szCurrent, - const char** szCurrentOut, SMD::Vertex& vertex, - bool bVASection /*= false*/) -{ - if (SkipSpaces(&szCurrent) && IsLineEnd(*szCurrent)) - { + const char** szCurrentOut, SMD::Vertex& vertex, + bool bVASection /*= false*/) { + if (SkipSpaces(&szCurrent) && IsLineEnd(*szCurrent)) { SkipSpacesAndLineEnd(szCurrent,&szCurrent); return ParseVertex(szCurrent,szCurrentOut,vertex,bVASection); } - if(!ParseSignedInt(szCurrent,&szCurrent,(int&)vertex.iParentNode)) - { + if(!ParseSignedInt(szCurrent,&szCurrent,(int&)vertex.iParentNode)) { LogErrorNoThrow("Unexpected EOF/EOL while parsing vertex.parent"); SMDI_PARSE_RETURN; } - if(!ParseFloat(szCurrent,&szCurrent,(float&)vertex.pos.x)) - { + if(!ParseFloat(szCurrent,&szCurrent,(float&)vertex.pos.x)) { LogErrorNoThrow("Unexpected EOF/EOL while parsing vertex.pos.x"); SMDI_PARSE_RETURN; } - if(!ParseFloat(szCurrent,&szCurrent,(float&)vertex.pos.y)) - { + if(!ParseFloat(szCurrent,&szCurrent,(float&)vertex.pos.y)) { LogErrorNoThrow("Unexpected EOF/EOL while parsing vertex.pos.y"); SMDI_PARSE_RETURN; } - if(!ParseFloat(szCurrent,&szCurrent,(float&)vertex.pos.z)) - { + if(!ParseFloat(szCurrent,&szCurrent,(float&)vertex.pos.z)) { LogErrorNoThrow("Unexpected EOF/EOL while parsing vertex.pos.z"); SMDI_PARSE_RETURN; } - if(!ParseFloat(szCurrent,&szCurrent,(float&)vertex.nor.x)) - { + if(!ParseFloat(szCurrent,&szCurrent,(float&)vertex.nor.x)) { LogErrorNoThrow("Unexpected EOF/EOL while parsing vertex.nor.x"); SMDI_PARSE_RETURN; } - if(!ParseFloat(szCurrent,&szCurrent,(float&)vertex.nor.y)) - { + if(!ParseFloat(szCurrent,&szCurrent,(float&)vertex.nor.y)) { LogErrorNoThrow("Unexpected EOF/EOL while parsing vertex.nor.y"); SMDI_PARSE_RETURN; } - if(!ParseFloat(szCurrent,&szCurrent,(float&)vertex.nor.z)) - { + if(!ParseFloat(szCurrent,&szCurrent,(float&)vertex.nor.z)) { LogErrorNoThrow("Unexpected EOF/EOL while parsing vertex.nor.z"); SMDI_PARSE_RETURN; } - if (bVASection)SMDI_PARSE_RETURN; + if (bVASection) { + SMDI_PARSE_RETURN; + } - if(!ParseFloat(szCurrent,&szCurrent,(float&)vertex.uv.x)) - { + if(!ParseFloat(szCurrent,&szCurrent,(float&)vertex.uv.x)) { LogErrorNoThrow("Unexpected EOF/EOL while parsing vertex.uv.x"); SMDI_PARSE_RETURN; } - if(!ParseFloat(szCurrent,&szCurrent,(float&)vertex.uv.y)) - { + if(!ParseFloat(szCurrent,&szCurrent,(float&)vertex.uv.y)) { LogErrorNoThrow("Unexpected EOF/EOL while parsing vertex.uv.y"); SMDI_PARSE_RETURN; } @@ -1142,17 +1076,20 @@ void SMDImporter::ParseVertex(const char* szCurrent, // now read the number of bones affecting this vertex // all elements from now are fully optional, we don't need them unsigned int iSize = 0; - if(!ParseUnsignedInt(szCurrent,&szCurrent,iSize))SMDI_PARSE_RETURN; + if(!ParseUnsignedInt(szCurrent,&szCurrent,iSize)) { + SMDI_PARSE_RETURN; + } vertex.aiBoneLinks.resize(iSize,std::pair(0,0.0f)); for (std::vector >::iterator - i = vertex.aiBoneLinks.begin(); - i != vertex.aiBoneLinks.end();++i) - { - if(!ParseUnsignedInt(szCurrent,&szCurrent,(*i).first)) + i = vertex.aiBoneLinks.begin(); + i != vertex.aiBoneLinks.end();++i) { + if(!ParseUnsignedInt(szCurrent,&szCurrent,(*i).first)) { SMDI_PARSE_RETURN; - if(!ParseFloat(szCurrent,&szCurrent,(*i).second)) + } + if(!ParseFloat(szCurrent,&szCurrent,(*i).second)) { SMDI_PARSE_RETURN; + } } // go to the beginning of the next line diff --git a/third_party/libassimp/code/SMDLoader.h b/third_party/libassimp/code/SMDLoader.h index 40c08385fc..a791e7dde3 100644 --- a/third_party/libassimp/code/SMDLoader.h +++ b/third_party/libassimp/code/SMDLoader.h @@ -219,6 +219,7 @@ protected: /** Parse the SMD file and create the output scene */ void ParseFile(); + void ReadSmd(const std::string &pFile, IOSystem* pIOHandler); // ------------------------------------------------------------------- /** Parse the triangles section of the SMD file @@ -289,13 +290,6 @@ protected: */ unsigned int GetTextureIndex(const std::string& filename); - // ------------------------------------------------------------------- - /** Computes absolute bone transformations - * All output transformations are in worldspace. - */ - void ComputeAbsoluteBoneTransformations(); - - // ------------------------------------------------------------------- /** Parse a line in the skeleton section */ @@ -344,7 +338,9 @@ protected: */ void CreateOutputMeshes(); void CreateOutputNodes(); - void CreateOutputAnimations(); + void CreateOutputAnimations(const std::string &pFile, IOSystem* pIOHandler); + void CreateOutputAnimation(int index, const std::string &name); + void GetAnimationFileList(const std::string &pFile, IOSystem* pIOHandler, std::vector>& outList); void CreateOutputMaterials(); @@ -413,6 +409,8 @@ private: */ unsigned int iLineNumber; + bool bLoadAnimationList = true; + bool noSkeletonMesh = false; }; } // end of namespace Assimp diff --git a/third_party/libassimp/code/STEPFile.h b/third_party/libassimp/code/STEPFile.h index 6245290b65..f5b56c31f5 100644 --- a/third_party/libassimp/code/STEPFile.h +++ b/third_party/libassimp/code/STEPFile.h @@ -142,7 +142,7 @@ namespace STEP { struct TypeError : DeadlyImportError { enum { ENTITY_NOT_SPECIFIED = 0xffffffffffffffffLL, - ENTITY_NOT_SPECIFIED_32 = -1u + ENTITY_NOT_SPECIFIED_32 = 0x00000000ffffffff }; TypeError (const std::string& s,uint64_t entity = ENTITY_NOT_SPECIFIED, uint64_t line = SyntaxError::LINE_NOT_SPECIFIED); diff --git a/third_party/libassimp/code/glTF2Asset.inl b/third_party/libassimp/code/glTF2Asset.inl index 687e16ce1e..ed37937f41 100755 --- a/third_party/libassimp/code/glTF2Asset.inl +++ b/third_party/libassimp/code/glTF2Asset.inl @@ -1357,6 +1357,13 @@ inline void Asset::Load(const std::string& pFile, bool isBinary) } } + // Force reading of skins since they're not always directly referenced + if (Value* skinsArray = FindArray(doc, "skins")) { + for (unsigned int i = 0; i < skinsArray->Size(); ++i) { + skins.Retrieve(i); + } + } + if (Value* animsArray = FindArray(doc, "animations")) { for (unsigned int i = 0; i < animsArray->Size(); ++i) { animations.Retrieve(i); diff --git a/third_party/libassimp/code/glTF2Importer.cpp b/third_party/libassimp/code/glTF2Importer.cpp index e8d2a2d95c..f6a664e5ec 100755 --- a/third_party/libassimp/code/glTF2Importer.cpp +++ b/third_party/libassimp/code/glTF2Importer.cpp @@ -1022,6 +1022,32 @@ void glTF2Importer::ImportAnimations(glTF2::Asset& r) ++j; } } + + // Use the latest keyframe for the duration of the animation + double maxDuration = 0; + for (unsigned int j = 0; j < ai_anim->mNumChannels; ++j) { + auto chan = ai_anim->mChannels[j]; + if (chan->mNumPositionKeys) { + auto lastPosKey = chan->mPositionKeys[chan->mNumPositionKeys - 1]; + if (lastPosKey.mTime > maxDuration) { + maxDuration = lastPosKey.mTime; + } + } + if (chan->mNumRotationKeys) { + auto lastRotKey = chan->mRotationKeys[chan->mNumRotationKeys - 1]; + if (lastRotKey.mTime > maxDuration) { + maxDuration = lastRotKey.mTime; + } + } + if (chan->mNumScalingKeys) { + auto lastScaleKey = chan->mScalingKeys[chan->mNumScalingKeys - 1]; + if (lastScaleKey.mTime > maxDuration) { + maxDuration = lastScaleKey.mTime; + } + } + } + ai_anim->mDuration = maxDuration; + mScene->mAnimations[i] = ai_anim; } } diff --git a/third_party/libassimp/contrib/openddlparser/include/openddlparser/OpenDDLParserUtils.h b/third_party/libassimp/contrib/openddlparser/include/openddlparser/OpenDDLParserUtils.h index 64897436ed..f0762ac671 100644 --- a/third_party/libassimp/contrib/openddlparser/include/openddlparser/OpenDDLParserUtils.h +++ b/third_party/libassimp/contrib/openddlparser/include/openddlparser/OpenDDLParserUtils.h @@ -59,32 +59,10 @@ bool isSeparator( T in ) { return false; } -static const unsigned char chartype_table[ 256 ] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0-15 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16-31 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 32-47 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, // 48-63 - - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 64-79 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 80-95 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 96-111 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 112-127 - - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // > 127 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -}; - template inline bool isNumeric( const T in ) { - return ( chartype_table[ static_cast( in ) ] == 1 ); + return ( in >= '0' && in <= '9' ); } template diff --git a/third_party/libassimp/doc/dox.h b/third_party/libassimp/doc/dox.h index af9eeb6094..d63c8a806a 100644 --- a/third_party/libassimp/doc/dox.h +++ b/third_party/libassimp/doc/dox.h @@ -1486,9 +1486,8 @@ Just copy'n'paste the template from Appendix A and adapt it for your needs. with DefaultLogger::get()->[error, warn, debug, info].
  • -Make sure that your loader compiles against all build configurations on all supported platforms. This includes -noboost! To avoid problems, -see the boost section on this page for a list of all 'allowed' boost classes (again, this grew historically when we had to accept that boost -is not THAT widely spread that one could rely on it being available everywhere). +Make sure that your loader compiles against all build configurations on all supported platforms. You can use our CI-build to check several platforms +like Windows and Linux ( 32 bit and 64 bit ).
  • Provide some _free_ test models in <root>/test/models/<FormatName>/ and credit their authors. @@ -1567,22 +1566,6 @@ NewMaterial->AddProperty(&aiString(MaterialName.c_str()), AI_MATKEY_NAME);//Mate NewMaterial->AddProperty(&aiString(Texturename.c_str()), AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE, 0));//again, Texturename is a std::string @endcode -@section boost Boost - -The boost whitelist: -
      -
    • boost.scoped_ptr
    • -
    • boost.scoped_array
    • -
    • boost.format
    • -
    • boost.random
    • -
    • boost.common_factor
    • -
    • boost.foreach
    • -
    • boost.tuple
    • -
    - -(if you happen to need something else, i.e. boost::thread, make this an optional feature. -assimp_BUILD_BOOST_WORKAROUND is defined for -noboost builds) - @section appa Appendix A - Template for BaseImporter's abstract methods @code diff --git a/third_party/libassimp/include/assimp/MemoryIOWrapper.h b/third_party/libassimp/include/assimp/MemoryIOWrapper.h index bfcfff9c2c..5260cb2b2a 100644 --- a/third_party/libassimp/include/assimp/MemoryIOWrapper.h +++ b/third_party/libassimp/include/assimp/MemoryIOWrapper.h @@ -80,7 +80,9 @@ public: // ------------------------------------------------------------------- // Read from stream size_t Read(void* pvBuffer, size_t pSize, size_t pCount) { - const size_t cnt = std::min(pCount,(length-pos)/pSize),ofs = pSize*cnt; + ai_assert(pvBuffer); + ai_assert(pSize); + const size_t cnt = std::min(pCount,(length-pos)/pSize), ofs = pSize*cnt; memcpy(pvBuffer,buffer+pos,ofs); pos += ofs; diff --git a/third_party/libassimp/include/assimp/color4.h b/third_party/libassimp/include/assimp/color4.h index 570b8f44cf..fddd1b638c 100644 --- a/third_party/libassimp/include/assimp/color4.h +++ b/third_party/libassimp/include/assimp/color4.h @@ -63,8 +63,7 @@ public: aiColor4t (TReal _r, TReal _g, TReal _b, TReal _a) : r(_r), g(_g), b(_b), a(_a) {} explicit aiColor4t (TReal _r) : r(_r), g(_r), b(_r), a(_r) {} - aiColor4t (const aiColor4t& o) - : r(o.r), g(o.g), b(o.b), a(o.a) {} + aiColor4t (const aiColor4t& o) = default; public: // combined operators diff --git a/third_party/libassimp/include/assimp/config.h b/third_party/libassimp/include/assimp/config.h index da664d7367..fe8e901522 100644 --- a/third_party/libassimp/include/assimp/config.h +++ b/third_party/libassimp/include/assimp/config.h @@ -673,6 +673,12 @@ enum aiComponent #define AI_CONFIG_IMPORT_SMD_KEYFRAME "IMPORT_SMD_KEYFRAME" #define AI_CONFIG_IMPORT_UNREAL_KEYFRAME "IMPORT_UNREAL_KEYFRAME" +// --------------------------------------------------------------------------- +/** Smd load multiple animations + * + * Property type: bool. Default value: true. + */ +#define AI_CONFIG_IMPORT_SMD_LOAD_ANIMATION_LIST "IMPORT_SMD_LOAD_ANIMATION_LIST" // --------------------------------------------------------------------------- /** @brief Configures the AC loader to collect all surfaces which have the diff --git a/third_party/libassimp/include/assimp/config.h.in b/third_party/libassimp/include/assimp/config.h.in index 8de2ea43e1..fd828bc6e9 100644 --- a/third_party/libassimp/include/assimp/config.h.in +++ b/third_party/libassimp/include/assimp/config.h.in @@ -673,6 +673,12 @@ enum aiComponent #define AI_CONFIG_IMPORT_SMD_KEYFRAME "IMPORT_SMD_KEYFRAME" #define AI_CONFIG_IMPORT_UNREAL_KEYFRAME "IMPORT_UNREAL_KEYFRAME" +// --------------------------------------------------------------------------- +/** Smd load multiple animations + * + * Property type: bool. Default value: true. + */ +#define AI_CONFIG_IMPORT_SMD_LOAD_ANIMATION_LIST "IMPORT_SMD_LOAD_ANIMATION_LIST" // --------------------------------------------------------------------------- /** @brief Configures the AC loader to collect all surfaces which have the diff --git a/third_party/libassimp/include/assimp/matrix4x4.inl b/third_party/libassimp/include/assimp/matrix4x4.inl index 9920f00592..680d7666df 100644 --- a/third_party/libassimp/include/assimp/matrix4x4.inl +++ b/third_party/libassimp/include/assimp/matrix4x4.inl @@ -527,27 +527,25 @@ inline aiMatrix4x4t& aiMatrix4x4t::FromEulerAnglesXYZ(TReal x, TRe { aiMatrix4x4t& _this = *this; - TReal cr = std::cos( x ); - TReal sr = std::sin( x ); - TReal cp = std::cos( y ); - TReal sp = std::sin( y ); - TReal cy = std::cos( z ); - TReal sy = std::sin( z ); + TReal cx = std::cos(x); + TReal sx = std::sin(x); + TReal cy = std::cos(y); + TReal sy = std::sin(y); + TReal cz = std::cos(z); + TReal sz = std::sin(z); - _this.a1 = cp*cy ; - _this.a2 = cp*sy; - _this.a3 = -sp ; + // mz*my*mx + _this.a1 = cz * cy; + _this.a2 = cz * sy * sx - sz * cx; + _this.a3 = sz * sx + cz * sy * cx; - TReal srsp = sr*sp; - TReal crsp = cr*sp; + _this.b1 = sz * cy; + _this.b2 = cz * cx + sz * sy * sx; + _this.b3 = sz * sy * cx - cz * sx; - _this.b1 = srsp*cy-cr*sy ; - _this.b2 = srsp*sy+cr*cy ; - _this.b3 = sr*cp ; - - _this.c1 = crsp*cy+sr*sy ; - _this.c2 = crsp*sy-sr*cy ; - _this.c3 = cr*cp ; + _this.c1 = -sy; + _this.c2 = cy * sx; + _this.c3 = cy * cx; return *this; } diff --git a/third_party/libassimp/include/assimp/vector2.h b/third_party/libassimp/include/assimp/vector2.h index d290945c96..85ca6d0a47 100644 --- a/third_party/libassimp/include/assimp/vector2.h +++ b/third_party/libassimp/include/assimp/vector2.h @@ -53,7 +53,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # include #endif -#include "./Compiler/pushpack1.h" #include "defs.h" // ---------------------------------------------------------------------------------- @@ -62,24 +61,18 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifdef __cplusplus template -class aiVector2t -{ +class aiVector2t { public: - aiVector2t () : x(), y() {} aiVector2t (TReal _x, TReal _y) : x(_x), y(_y) {} explicit aiVector2t (TReal _xyz) : x(_xyz), y(_xyz) {} - aiVector2t (const aiVector2t& o) : x(o.x), y(o.y) {} - -public: + aiVector2t (const aiVector2t& o) = default; void Set( TReal pX, TReal pY); TReal SquareLength() const ; TReal Length() const ; aiVector2t& Normalize(); -public: - const aiVector2t& operator += (const aiVector2t& o); const aiVector2t& operator -= (const aiVector2t& o); const aiVector2t& operator *= (TReal f); @@ -111,6 +104,4 @@ struct aiVector2D { #endif // __cplusplus -#include "./Compiler/poppack1.h" - #endif // AI_VECTOR2D_H_INC diff --git a/third_party/libassimp/include/assimp/vector3.h b/third_party/libassimp/include/assimp/vector3.h index 2c610b3a99..33ae7d22f0 100644 --- a/third_party/libassimp/include/assimp/vector3.h +++ b/third_party/libassimp/include/assimp/vector3.h @@ -69,7 +69,7 @@ public: aiVector3t() AI_NO_EXCEPT : x(), y(), z() {} aiVector3t(TReal _x, TReal _y, TReal _z) : x(_x), y(_y), z(_z) {} explicit aiVector3t (TReal _xyz ) : x(_xyz), y(_xyz), z(_xyz) {} - aiVector3t( const aiVector3t& o ) : x(o.x), y(o.y), z(o.z) {} + aiVector3t( const aiVector3t& o ) = default; public: diff --git a/third_party/libassimp/revision.h b/third_party/libassimp/revision.h index 54e9f12c65..4ee64a2fbf 100644 --- a/third_party/libassimp/revision.h +++ b/third_party/libassimp/revision.h @@ -1,7 +1,7 @@ #ifndef ASSIMP_REVISION_H_INC #define ASSIMP_REVISION_H_INC -#define GitVersion 0xe6905b6a +#define GitVersion 0xd7eae5bb #define GitBranch "master" #endif // ASSIMP_REVISION_H_INC diff --git a/third_party/libassimp/tnt/CMakeLists.txt b/third_party/libassimp/tnt/CMakeLists.txt index cde111f1fb..8a83073246 100644 --- a/third_party/libassimp/tnt/CMakeLists.txt +++ b/third_party/libassimp/tnt/CMakeLists.txt @@ -127,10 +127,10 @@ set(PRIVATE_HDRS ${PRIVATE_HDR_DIR}/Importer/IFC/IFCReaderGen_2x3.h ${PRIVATE_HDR_DIR}/Importer/IFC/IFCReaderGen_4.h ${PRIVATE_HDR_DIR}/Importer/IFC/IFCUtil.h - ${PRIVATE_HDR_DIR}/Importer/IFC/STEPFileEncoding.h - ${PRIVATE_HDR_DIR}/Importer/IFC/STEPFileReader.h ${PRIVATE_HDR_DIR}/Importer/StepFile/StepFileImporter.h ${PRIVATE_HDR_DIR}/Importer/StepFile/StepReaderGen.h + ${PRIVATE_HDR_DIR}/Importer/STEPParser/STEPFileEncoding.h + ${PRIVATE_HDR_DIR}/Importer/STEPParser/STEPFileReader.h ) # sources dependencies @@ -232,12 +232,12 @@ set(SRCS ${SRC_DIR}/code/Importer/IFC/IFCReaderGen2_2x3.cpp ${SRC_DIR}/code/Importer/IFC/IFCReaderGen_4.cpp ${SRC_DIR}/code/Importer/IFC/IFCUtil.cpp - ${SRC_DIR}/code/Importer/IFC/STEPFileEncoding.cpp - ${SRC_DIR}/code/Importer/IFC/STEPFileReader.cpp ${SRC_DIR}/code/Importer/StepFile/StepFileImporter.cpp ${SRC_DIR}/code/Importer/StepFile/StepFileGen1.cpp ${SRC_DIR}/code/Importer/StepFile/StepFileGen2.cpp ${SRC_DIR}/code/Importer/StepFile/StepFileGen3.cpp + ${SRC_DIR}/code/Importer/STEPParser/STEPFileEncoding.cpp + ${SRC_DIR}/code/Importer/STEPParser/STEPFileReader.cpp ${SRC_DIR}/contrib/clipper/clipper.cpp ${SRC_DIR}/contrib/irrXML/irrXML.cpp ${SRC_DIR}/contrib/poly2tri/poly2tri/common/shapes.cc