Merge branch 'master' into kimkulling/add_windows_clang_issue-5519

kimkulling/add_windows_clang_issue-5519
Kim Kulling 2024-09-10 18:39:00 +02:00 committed by GitHub
commit b65e84d759
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
23 changed files with 424 additions and 135 deletions

View File

@ -41,6 +41,9 @@ jobs:
cc: gcc cc: gcc
steps: steps:
- name: ccache
uses: hendrikmuhs/ccache-action@v1.2
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with: with:
submodules: true submodules: true

View File

@ -71,7 +71,7 @@ IF(ASSIMP_HUNTER_ENABLED)
add_definitions(-DASSIMP_USE_HUNTER) add_definitions(-DASSIMP_USE_HUNTER)
ENDIF() ENDIF()
PROJECT(Assimp VERSION 5.4.1) PROJECT(Assimp VERSION 5.4.3)
# All supported options ############################################### # All supported options ###############################################

View File

@ -643,11 +643,17 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene *pcSOut, aiNode *pcOut,
} }
// Allocate storage for children // Allocate storage for children
pcOut->mNumChildren = (unsigned int)pcIn->mChildren.size(); const unsigned int size = static_cast<unsigned int>(pcIn->mChildren.size());
pcOut->mNumChildren = size;
if (size == 0) {
return;
}
pcOut->mChildren = new aiNode *[pcIn->mChildren.size()]; pcOut->mChildren = new aiNode *[pcIn->mChildren.size()];
// Recursively process all children // Recursively process all children
const unsigned int size = static_cast<unsigned int>(pcIn->mChildren.size());
for (unsigned int i = 0; i < size; ++i) { for (unsigned int i = 0; i < size; ++i) {
pcOut->mChildren[i] = new aiNode(); pcOut->mChildren[i] = new aiNode();
pcOut->mChildren[i]->mParent = pcOut; pcOut->mChildren[i]->mParent = pcOut;

View File

@ -372,9 +372,11 @@ aiNode *COBImporter::BuildNodes(const Node &root, const Scene &scin, aiScene *fi
} }
// add children recursively // add children recursively
nd->mChildren = new aiNode *[root.temp_children.size()](); if (!root.temp_children.empty()) {
for (const Node *n : root.temp_children) { nd->mChildren = new aiNode *[root.temp_children.size()]();
(nd->mChildren[nd->mNumChildren++] = BuildNodes(*n, scin, fill))->mParent = nd; for (const Node *n : root.temp_children) {
(nd->mChildren[nd->mNumChildren++] = BuildNodes(*n, scin, fill))->mParent = nd;
}
} }
return nd; return nd;

View File

@ -181,7 +181,9 @@ FBXConverter::FBXConverter(aiScene *out, const Document &doc, bool removeEmptyBo
if (out->mNumMeshes == 0) { if (out->mNumMeshes == 0) {
out->mFlags |= AI_SCENE_FLAGS_INCOMPLETE; out->mFlags |= AI_SCENE_FLAGS_INCOMPLETE;
} else { } else {
correctRootTransform(mSceneOut); // Apply the FBX axis metadata unless requested not to
if (!doc.Settings().ignoreUpDirection)
correctRootTransform(mSceneOut);
} }
} }
@ -357,12 +359,12 @@ void FBXConverter::ConvertNodes(uint64_t id, aiNode *parent, aiNode *root_node)
if (nodes.empty()) { if (nodes.empty()) {
parent->mNumChildren = 0; parent->mNumChildren = 0;
parent->mChildren = nullptr; parent->mChildren = nullptr;
} } else {
parent->mChildren = new aiNode *[nodes.size()]();
parent->mChildren = new aiNode *[nodes.size()](); parent->mNumChildren = static_cast<unsigned int>(nodes.size());
parent->mNumChildren = static_cast<unsigned int>(nodes.size()); for (unsigned int i = 0; i < nodes.size(); ++i) {
for (unsigned int i = 0; i < nodes.size(); ++i) { parent->mChildren[i] = nodes[i].mOwnership.release();
parent->mChildren[i] = nodes[i].mOwnership.release(); }
} }
} }

View File

@ -156,6 +156,9 @@ struct ImportSettings {
/** Set to true to perform a conversion from cm to meter after the import /** Set to true to perform a conversion from cm to meter after the import
*/ */
bool convertToMeters; bool convertToMeters;
// Set to true to ignore the axis configuration in the file
bool ignoreUpDirection = false;
}; };
} // namespace FBX } // namespace FBX

View File

@ -117,6 +117,7 @@ void FBXImporter::SetupProperties(const Importer *pImp) {
mSettings.useLegacyEmbeddedTextureNaming = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_EMBEDDED_TEXTURES_LEGACY_NAMING, false); mSettings.useLegacyEmbeddedTextureNaming = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_EMBEDDED_TEXTURES_LEGACY_NAMING, false);
mSettings.removeEmptyBones = pImp->GetPropertyBool(AI_CONFIG_IMPORT_REMOVE_EMPTY_BONES, true); mSettings.removeEmptyBones = pImp->GetPropertyBool(AI_CONFIG_IMPORT_REMOVE_EMPTY_BONES, true);
mSettings.convertToMeters = pImp->GetPropertyBool(AI_CONFIG_FBX_CONVERT_TO_M, false); mSettings.convertToMeters = pImp->GetPropertyBool(AI_CONFIG_FBX_CONVERT_TO_M, false);
mSettings.ignoreUpDirection = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_IGNORE_UP_DIRECTION, false);
mSettings.useSkeleton = pImp->GetPropertyBool(AI_CONFIG_FBX_USE_SKELETON_BONE_CONTAINER, false); mSettings.useSkeleton = pImp->GetPropertyBool(AI_CONFIG_FBX_USE_SKELETON_BONE_CONTAINER, false);
} }

View File

@ -448,6 +448,9 @@ void PLYImporter::LoadVertex(const PLY::Element *pcElement, const PLY::ElementIn
mGeneratedMesh->mNumVertices = pcElement->NumOccur; mGeneratedMesh->mNumVertices = pcElement->NumOccur;
mGeneratedMesh->mVertices = new aiVector3D[mGeneratedMesh->mNumVertices]; mGeneratedMesh->mVertices = new aiVector3D[mGeneratedMesh->mNumVertices];
} }
if (pos >= mGeneratedMesh->mNumVertices) {
throw DeadlyImportError("Invalid .ply file: Too many vertices");
}
mGeneratedMesh->mVertices[pos] = vOut; mGeneratedMesh->mVertices[pos] = vOut;

View File

@ -48,10 +48,29 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/ByteSwapper.h> #include <assimp/ByteSwapper.h>
#include <assimp/fast_atof.h> #include <assimp/fast_atof.h>
#include <assimp/DefaultLogger.hpp> #include <assimp/DefaultLogger.hpp>
#include <unordered_set>
#include <utility> #include <utility>
namespace Assimp { namespace Assimp {
std::string to_string(EElementSemantic e) {
switch (e) {
case EEST_Vertex:
return std::string{ "vertex" };
case EEST_TriStrip:
return std::string{ "tristrips" };
case EEST_Edge:
return std::string{ "edge" };
case EEST_Material:
return std::string{ "material" };
case EEST_TextureFile:
return std::string{ "TextureFile" };
default:
return std::string{ "invalid" };
}
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
PLY::EDataType PLY::Property::ParseDataType(std::vector<char> &buffer) { PLY::EDataType PLY::Property::ParseDataType(std::vector<char> &buffer) {
ai_assert(!buffer.empty()); ai_assert(!buffer.empty());
@ -281,6 +300,8 @@ bool PLY::Element::ParseElement(IOStreamBuffer<char> &streamBuffer, std::vector<
// if the exact semantic can't be determined, just store // if the exact semantic can't be determined, just store
// the original string identifier // the original string identifier
pOut->szName = std::string(&buffer[0], &buffer[0] + strlen(&buffer[0])); pOut->szName = std::string(&buffer[0], &buffer[0] + strlen(&buffer[0]));
auto pos = pOut->szName.find_last_of(' ');
pOut->szName.erase(pos, pOut->szName.size());
} }
if (!PLY::DOM::SkipSpaces(buffer)) if (!PLY::DOM::SkipSpaces(buffer))
@ -413,6 +434,7 @@ bool PLY::DOM::SkipComments(std::vector<char> buffer) {
bool PLY::DOM::ParseHeader(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer, bool isBinary) { bool PLY::DOM::ParseHeader(IOStreamBuffer<char> &streamBuffer, std::vector<char> &buffer, bool isBinary) {
ASSIMP_LOG_VERBOSE_DEBUG("PLY::DOM::ParseHeader() begin"); ASSIMP_LOG_VERBOSE_DEBUG("PLY::DOM::ParseHeader() begin");
std::unordered_set<std::string> definedAlElements;
// parse all elements // parse all elements
while (!buffer.empty()) { while (!buffer.empty()) {
// skip all comments // skip all comments
@ -421,6 +443,13 @@ bool PLY::DOM::ParseHeader(IOStreamBuffer<char> &streamBuffer, std::vector<char>
PLY::Element out; PLY::Element out;
if (PLY::Element::ParseElement(streamBuffer, buffer, &out)) { if (PLY::Element::ParseElement(streamBuffer, buffer, &out)) {
// add the element to the list of elements // add the element to the list of elements
const auto propertyName = (out.szName.empty()) ? to_string(out.eSemantic) : out.szName;
auto alreadyDefined = definedAlElements.find(propertyName);
if (alreadyDefined != definedAlElements.end()) {
throw DeadlyImportError("Property '" + propertyName + "' in header already defined ");
}
definedAlElements.insert(propertyName);
alElements.push_back(out); alElements.push_back(out);
} else if (TokenMatch(buffer, "end_header", 10)) { } else if (TokenMatch(buffer, "end_header", 10)) {
// we have reached the end of the header // we have reached the end of the header

View File

@ -400,8 +400,12 @@ void SMDImporter::AddBoneChildren(aiNode* pcNode, uint32_t iParent) {
} }
} }
// nothing to do
if (pcNode->mNumChildren == 0)
return;
// now allocate the output array // now allocate the output array
pcNode->mChildren = new aiNode*[pcNode->mNumChildren]; pcNode->mChildren = new aiNode *[pcNode->mNumChildren];
// and fill all subnodes // and fill all subnodes
unsigned int qq( 0 ); unsigned int qq( 0 );

View File

@ -1053,7 +1053,7 @@ ENDIF() # IF (ASSIMP_BUILD_USD_IMPORTER)
IF(ASSIMP_HUNTER_ENABLED) IF(ASSIMP_HUNTER_ENABLED)
hunter_add_package(pugixml) hunter_add_package(pugixml)
find_package(pugixml CONFIG REQUIRED) find_package(pugixml CONFIG REQUIRED)
ELSE() ELSEIF(NOT TARGET pugixml::pugixml)
SET( Pugixml_SRCS SET( Pugixml_SRCS
../contrib/pugixml/src/pugiconfig.hpp ../contrib/pugixml/src/pugiconfig.hpp
../contrib/pugixml/src/pugixml.hpp ../contrib/pugixml/src/pugixml.hpp
@ -1396,6 +1396,7 @@ IF (ASSIMP_WARNINGS_AS_ERRORS)
-Wno-unused-template -Wno-unused-template
-Wno-undefined-func-template -Wno-undefined-func-template
-Wno-declaration-after-statement -Wno-declaration-after-statement
-Wno-deprecated-declarations
) )
ELSE() ELSE()
TARGET_COMPILE_OPTIONS(assimp PRIVATE /W4 /WX) TARGET_COMPILE_OPTIONS(assimp PRIVATE /W4 /WX)
@ -1417,9 +1418,7 @@ TARGET_INCLUDE_DIRECTORIES ( assimp PUBLIC
IF(ASSIMP_HUNTER_ENABLED) IF(ASSIMP_HUNTER_ENABLED)
TARGET_LINK_LIBRARIES(assimp TARGET_LINK_LIBRARIES(assimp
PUBLIC PUBLIC
#polyclipping::polyclipping
openddlparser::openddl_parser openddlparser::openddl_parser
#poly2tri::poly2tri
minizip::minizip minizip::minizip
ZLIB::zlib ZLIB::zlib
RapidJSON::rapidjson RapidJSON::rapidjson
@ -1439,6 +1438,9 @@ ELSE()
if (ASSIMP_BUILD_DRACO) if (ASSIMP_BUILD_DRACO)
target_link_libraries(assimp ${draco_LIBRARIES}) target_link_libraries(assimp ${draco_LIBRARIES})
endif() endif()
if(TARGET pugixml::pugixml)
target_link_libraries(assimp pugixml::pugixml)
endif()
ENDIF() ENDIF()
if(ASSIMP_ANDROID_JNIIOSYSTEM) if(ASSIMP_ANDROID_JNIIOSYSTEM)

View File

@ -359,20 +359,25 @@ void CallbackToLogRedirector(const char *msg, char *dt) {
s->write(msg); s->write(msg);
} }
static LogStream *DefaultStream = nullptr;
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
ASSIMP_API aiLogStream aiGetPredefinedLogStream(aiDefaultLogStream pStream, const char *file) { ASSIMP_API aiLogStream aiGetPredefinedLogStream(aiDefaultLogStream pStream, const char *file) {
aiLogStream sout; aiLogStream sout;
ASSIMP_BEGIN_EXCEPTION_REGION(); ASSIMP_BEGIN_EXCEPTION_REGION();
LogStream *stream = LogStream::createDefaultStream(pStream, file); if (DefaultStream == nullptr) {
if (!stream) { DefaultStream = LogStream::createDefaultStream(pStream, file);
}
if (!DefaultStream) {
sout.callback = nullptr; sout.callback = nullptr;
sout.user = nullptr; sout.user = nullptr;
} else { } else {
sout.callback = &CallbackToLogRedirector; sout.callback = &CallbackToLogRedirector;
sout.user = (char *)stream; sout.user = (char *)DefaultStream;
} }
gPredefinedStreams.push_back(stream); gPredefinedStreams.push_back(DefaultStream);
ASSIMP_END_EXCEPTION_REGION(aiLogStream); ASSIMP_END_EXCEPTION_REGION(aiLogStream);
return sout; return sout;
} }

View File

@ -65,37 +65,47 @@ void SortByPTypeProcess::SetupProperties(const Importer *pImp) {
mConfigRemoveMeshes = pImp->GetPropertyInteger(AI_CONFIG_PP_SBP_REMOVE, 0); mConfigRemoveMeshes = pImp->GetPropertyInteger(AI_CONFIG_PP_SBP_REMOVE, 0);
} }
// ------------------------------------------------------------------------------------------------
static void clearMeshesInNode(aiNode *node) {
delete[] node->mMeshes;
node->mNumMeshes = 0;
node->mMeshes = nullptr;
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Update changed meshes in all nodes // Update changed meshes in all nodes
void UpdateNodes(const std::vector<unsigned int> &replaceMeshIndex, aiNode *node) { void UpdateNodes(const std::vector<unsigned int> &replaceMeshIndex, aiNode *node) {
ai_assert(node != nullptr);
if (node->mNumMeshes) { if (node->mNumMeshes) {
unsigned int newSize = 0; unsigned int newSize = 0;
for (unsigned int m = 0; m < node->mNumMeshes; ++m) { for (unsigned int m = 0; m < node->mNumMeshes; ++m) {
unsigned int add = node->mMeshes[m] << 2; unsigned int add = node->mMeshes[m] << 2;
for (unsigned int i = 0; i < 4; ++i) { for (unsigned int i = 0; i < 4; ++i) {
if (UINT_MAX != replaceMeshIndex[add + i]) ++newSize; if (UINT_MAX != replaceMeshIndex[add + i]) {
} ++newSize;
}
if (!newSize) {
delete[] node->mMeshes;
node->mNumMeshes = 0;
node->mMeshes = nullptr;
} else {
// Try to reuse the old array if possible
unsigned int *newMeshes = (newSize > node->mNumMeshes ? new unsigned int[newSize] : node->mMeshes);
for (unsigned int m = 0; m < node->mNumMeshes; ++m) {
unsigned int add = node->mMeshes[m] << 2;
for (unsigned int i = 0; i < 4; ++i) {
if (UINT_MAX != replaceMeshIndex[add + i])
*newMeshes++ = replaceMeshIndex[add + i];
} }
} }
if (newSize > node->mNumMeshes)
delete[] node->mMeshes;
node->mMeshes = newMeshes - (node->mNumMeshes = newSize);
} }
if (newSize == 0) {
clearMeshesInNode(node);
return;
}
// Try to reuse the old array if possible
unsigned int *newMeshes = (newSize > node->mNumMeshes ? new unsigned int[newSize] : node->mMeshes);
for (unsigned int m = 0; m < node->mNumMeshes; ++m) {
unsigned int add = node->mMeshes[m] << 2;
for (unsigned int i = 0; i < 4; ++i) {
if (UINT_MAX != replaceMeshIndex[add + i]) {
*newMeshes++ = replaceMeshIndex[add + i];
}
}
}
if (newSize > node->mNumMeshes) {
clearMeshesInNode(node);
}
node->mMeshes = newMeshes - (node->mNumMeshes = newSize);
} }
// call all subnodes recursively // call all subnodes recursively
@ -167,6 +177,10 @@ void SortByPTypeProcess::Execute(aiScene *pScene) {
// with the largest number of primitives // with the largest number of primitives
unsigned int aiNumPerPType[4] = { 0, 0, 0, 0 }; unsigned int aiNumPerPType[4] = { 0, 0, 0, 0 };
aiFace *pFirstFace = mesh->mFaces; aiFace *pFirstFace = mesh->mFaces;
if (pFirstFace == nullptr) {
continue;
}
aiFace *const pLastFace = pFirstFace + mesh->mNumFaces; aiFace *const pLastFace = pFirstFace + mesh->mNumFaces;
unsigned int numPolyVerts = 0; unsigned int numPolyVerts = 0;

View File

@ -891,6 +891,9 @@ void ValidateDSProcess::Validate(const aiNode *pNode) {
ReportError("aiNode \"%s\" child %i \"%s\" parent is someone else: \"%s\"", pNode->mName.C_Str(), i, pChild->mName.C_Str(), parentName); ReportError("aiNode \"%s\" child %i \"%s\" parent is someone else: \"%s\"", pNode->mName.C_Str(), i, pChild->mName.C_Str(), parentName);
} }
} }
} else if (pNode->mChildren) {
ReportError("aiNode::mChildren is not nullptr for empty node %s (aiNode::mNumChildren is %i)",
nodeName, pNode->mNumChildren);
} }
} }

View File

@ -47,7 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using namespace Assimp; using namespace Assimp;
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t dataSize) { extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t dataSize) {
aiLogStream stream = aiGetPredefinedLogStream(aiDefaultLogStream_STDOUT,NULL); aiLogStream stream = aiGetPredefinedLogStream(aiDefaultLogStream_STDOUT, nullptr);
aiAttachLogStream(&stream); aiAttachLogStream(&stream);
Importer importer; Importer importer;

View File

@ -676,6 +676,19 @@ enum aiComponent
#define AI_CONFIG_FBX_CONVERT_TO_M \ #define AI_CONFIG_FBX_CONVERT_TO_M \
"AI_CONFIG_FBX_CONVERT_TO_M" "AI_CONFIG_FBX_CONVERT_TO_M"
// ---------------------------------------------------------------------------
/** @brief Set whether the FBX importer shall ignore the provided axis configuration
*
* If this property is set to true, the axis directions provided in the FBX file
* will be ignored and the file will be loaded as is.
*
* Set to true for Assimp 5.3.x and earlier behavior
* Equivalent to AI_CONFIG_IMPORT_COLLADA_IGNORE_UP_DIRECTION
* Property type: Bool. Default value: false.
*/
#define AI_CONFIG_IMPORT_FBX_IGNORE_UP_DIRECTION \
"AI_CONFIG_IMPORT_FBX_IGNORE_UP_DIRECTION"
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** @brief Will enable the skeleton struct to store bone data. /** @brief Will enable the skeleton struct to store bone data.
* *

View File

@ -49,14 +49,16 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define AI_DEFINES_H_INC #define AI_DEFINES_H_INC
#ifdef __GNUC__ #ifdef __GNUC__
#pragma GCC system_header # pragma GCC system_header
#endif #endif
#include <assimp/config.h> #include <assimp/config.h>
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
/* Define ASSIMP_BUILD_NO_XX_IMPORTER to disable a specific /**
* file format loader. The loader is be excluded from the * @brief Define ASSIMP_BUILD_NO_XX_IMPORTER to disable a specific file format loader.
*
* The loader is be excluded from the
* build in this case. 'XX' stands for the most common file * build in this case. 'XX' stands for the most common file
* extension of the file format. E.g.: * extension of the file format. E.g.:
* ASSIMP_BUILD_NO_X_IMPORTER disables the X loader. * ASSIMP_BUILD_NO_X_IMPORTER disables the X loader.
@ -76,34 +78,33 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
#ifndef ASSIMP_BUILD_NO_COMPRESSED_X #ifndef ASSIMP_BUILD_NO_COMPRESSED_X
#define ASSIMP_BUILD_NEED_Z_INFLATE # define ASSIMP_BUILD_NEED_Z_INFLATE
#endif #endif
#ifndef ASSIMP_BUILD_NO_COMPRESSED_BLEND #ifndef ASSIMP_BUILD_NO_COMPRESSED_BLEND
#define ASSIMP_BUILD_NEED_Z_INFLATE # define ASSIMP_BUILD_NEED_Z_INFLATE
#endif #endif
#ifndef ASSIMP_BUILD_NO_COMPRESSED_IFC #ifndef ASSIMP_BUILD_NO_COMPRESSED_IFC
#define ASSIMP_BUILD_NEED_Z_INFLATE # define ASSIMP_BUILD_NEED_Z_INFLATE
#define ASSIMP_BUILD_NEED_UNZIP # define ASSIMP_BUILD_NEED_UNZIP
#endif #endif
#ifndef ASSIMP_BUILD_NO_Q3BSP_IMPORTER #ifndef ASSIMP_BUILD_NO_Q3BSP_IMPORTER
#define ASSIMP_BUILD_NEED_Z_INFLATE # define ASSIMP_BUILD_NEED_Z_INFLATE
#define ASSIMP_BUILD_NEED_UNZIP # define ASSIMP_BUILD_NEED_UNZIP
#endif #endif
// We need those constants, workaround for any platforms where nobody defined them yet /**
* @brief We need those constants, workaround for any platforms where nobody defined them yet.
*/
#if (!defined SIZE_MAX) #if (!defined SIZE_MAX)
#define SIZE_MAX (~((size_t)0)) # define SIZE_MAX (~((size_t)0))
#endif #endif
/*#if (!defined UINT_MAX)
#define UINT_MAX (~((unsigned int)0))
#endif*/
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
/* Define ASSIMP_BUILD_NO_XX_PROCESS to disable a specific /** @brief Define ASSIMP_BUILD_NO_XX_PROCESS to disable a specific
*
* post processing step. This is the current list of process names ('XX'): * post processing step. This is the current list of process names ('XX'):
* CALCTANGENTS * CALCTANGENTS
* JOINVERTICES * JOINVERTICES
@ -134,46 +135,50 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* OPTIMIZEGRAPH * OPTIMIZEGRAPH
* GENENTITYMESHES * GENENTITYMESHES
* FIXTEXTUREPATHS * FIXTEXTUREPATHS
* GENBOUNDINGBOXES */ * GENBOUNDINGBOXES
////////////////////////////////////////////////////////////////////////// */
//////////////////////////////////////////////////////////////////////////
/** @brief Define 'ASSIMP_BUILD_DLL_EXPORT' to build a DLL of the library
*
* Define 'ASSIMP_DLL' before including Assimp to link to ASSIMP in
* an external DLL under Windows. Default is static linkage.
*/
//////////////////////////////////////////////////////////////////////////
#ifdef _WIN32 #ifdef _WIN32
#undef ASSIMP_API # undef ASSIMP_API
////////////////////////////////////////////////////////////////////////// # ifdef ASSIMP_BUILD_DLL_EXPORT
/* Define 'ASSIMP_BUILD_DLL_EXPORT' to build a DLL of the library */ # define ASSIMP_API __declspec(dllexport)
////////////////////////////////////////////////////////////////////////// # define ASSIMP_API_WINONLY __declspec(dllexport)
#ifdef ASSIMP_BUILD_DLL_EXPORT # elif (defined ASSIMP_DLL)
#define ASSIMP_API __declspec(dllexport) # define ASSIMP_API __declspec(dllimport)
#define ASSIMP_API_WINONLY __declspec(dllexport) # define ASSIMP_API_WINONLY __declspec(dllimport)
# else
////////////////////////////////////////////////////////////////////////// # define ASSIMP_API
/* Define 'ASSIMP_DLL' before including Assimp to link to ASSIMP in # define ASSIMP_API_WINONLY
* an external DLL under Windows. Default is static linkage. */ # endif
////////////////////////////////////////////////////////////////////////// #else
#elif (defined ASSIMP_DLL) # define ASSIMP_API __attribute__((visibility("default")))
#define ASSIMP_API __declspec(dllimport) # define ASSIMP_API_WINONLY
#define ASSIMP_API_WINONLY __declspec(dllimport)
#else
#define ASSIMP_API
#define ASSIMP_API_WINONLY
#endif
#elif defined(SWIG)
/* Do nothing, the relevant defines are all in AssimpSwigPort.i */
#else
#define ASSIMP_API __attribute__((visibility("default")))
#define ASSIMP_API_WINONLY
#endif // _WIN32 #endif // _WIN32
/**
* @brief Helper macros
*
* @def AI_FORCE_INLINE
* @brief Force the compiler to inline a function, if possible
*
* @def AI_WONT_RETURN
* @brief Tells the compiler that a function never returns.
*
* Used in code analysis to skip dead paths (e.g. after an assertion evaluated to false).
*/
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(disable : 4521 4512 4714 4127 4351 4510) #pragma warning(disable : 4521 4512 4714 4127 4351 4510)
#ifdef ASSIMP_BUILD_DLL_EXPORT #ifdef ASSIMP_BUILD_DLL_EXPORT
#pragma warning(disable : 4251) #pragma warning(disable : 4251)
#endif #endif
/* Force the compiler to inline a function, if possible */
#define AI_FORCE_INLINE inline #define AI_FORCE_INLINE inline
/* Tells the compiler that a function never returns. Used in code analysis
* to skip dead paths (e.g. after an assertion evaluated to false). */
#define AI_WONT_RETURN __declspec(noreturn) #define AI_WONT_RETURN __declspec(noreturn)
#elif defined(SWIG) #elif defined(SWIG)
/* Do nothing, the relevant defines are all in AssimpSwigPort.i */ /* Do nothing, the relevant defines are all in AssimpSwigPort.i */
@ -223,29 +228,31 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* to typedef all structs/enums. */ * to typedef all structs/enums. */
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
#if (defined ASSIMP_DOXYGEN_BUILD) #if (defined ASSIMP_DOXYGEN_BUILD)
#define C_STRUCT # define C_STRUCT
#define C_ENUM # define C_ENUM
#else #else
#define C_STRUCT struct # define C_STRUCT struct
#define C_ENUM enum # define C_ENUM enum
#endif #endif
#endif #endif
#if (defined(__BORLANDC__) || defined(__BCPLUSPLUS__)) #if (defined(__BORLANDC__) || defined(__BCPLUSPLUS__))
#error Currently, Borland is unsupported. Feel free to port Assimp. # error Currently, Borland is unsupported. Feel free to port Assimp.
#endif #endif
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
/* Define ASSIMP_BUILD_SINGLETHREADED to compile assimp /**
* without threading support. The library doesn't utilize * Define ASSIMP_BUILD_SINGLETHREADED to compile assimp
* threads then and is itself not threadsafe. */ * without threading support. The library doesn't utilize
* threads then and is itself not threadsafe.
*/
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
#ifndef ASSIMP_BUILD_SINGLETHREADED #ifndef ASSIMP_BUILD_SINGLETHREADED
#define ASSIMP_BUILD_SINGLETHREADED # define ASSIMP_BUILD_SINGLETHREADED
#endif #endif
#if defined(_DEBUG) || !defined(NDEBUG) #if defined(_DEBUG) || !defined(NDEBUG)
#define ASSIMP_BUILD_DEBUG # define ASSIMP_BUILD_DEBUG
#endif #endif
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
@ -291,55 +298,74 @@ typedef unsigned int ai_uint;
#ifdef __cplusplus #ifdef __cplusplus
constexpr ai_real ai_epsilon = (ai_real) 1e-6; constexpr ai_real ai_epsilon = (ai_real) 1e-6;
#else #else
#define ai_epsilon ((ai_real)1e-6) # define ai_epsilon ((ai_real)1e-6)
#endif
/* Support for big-endian builds */
#if defined(__BYTE_ORDER__)
#if (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
#if !defined(__BIG_ENDIAN__)
#define __BIG_ENDIAN__
#endif
#else /* little endian */
#if defined(__BIG_ENDIAN__)
#undef __BIG_ENDIAN__
#endif
#endif
#endif
#if defined(__BIG_ENDIAN__)
#define AI_BUILD_BIG_ENDIAN
#endif #endif
/** /**
* To avoid running out of memory * @brief Support for big-endian builds
*
* This will check which byte ordering is used on the target architecture.
*/
#if defined(__BYTE_ORDER__)
# if (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
# if !defined(__BIG_ENDIAN__)
# define __BIG_ENDIAN__
# endif
# else /* little endian */
# if defined(__BIG_ENDIAN__)
# undef __BIG_ENDIAN__
# endif
# endif
#endif
#if defined(__BIG_ENDIAN__)
# define AI_BUILD_BIG_ENDIAN
#endif
/**
* @brief To avoid running out of memory
*
* This can be adjusted for specific use cases * This can be adjusted for specific use cases
* It's NOT a total limit, just a limit for individual allocations * It's NOT a total limit, just a limit for individual allocations
*/ */
#define AI_MAX_ALLOC(type) ((256U * 1024 * 1024) / sizeof(type)) #define AI_MAX_ALLOC(type) ((256U * 1024 * 1024) / sizeof(type))
#ifndef _MSC_VER #ifndef _MSC_VER
#if __cplusplus >= 201103L // C++11 # if __cplusplus >= 201103L // C++11
#define AI_NO_EXCEPT noexcept # define AI_NO_EXCEPT noexcept
# else
# define AI_NO_EXCEPT
# endif
#else #else
#define AI_NO_EXCEPT # if (_MSC_VER >= 1915)
#endif # define AI_NO_EXCEPT noexcept
#else # else
#if (_MSC_VER >= 1915) # define AI_NO_EXCEPT
#define AI_NO_EXCEPT noexcept # endif
#else
#define AI_NO_EXCEPT
#endif
#endif // _MSC_VER #endif // _MSC_VER
/** /**
* Helper macro to set a pointer to NULL in debug builds * @brief Helper macro to set a pointer to NULL in debug builds
*/ */
#if (defined ASSIMP_BUILD_DEBUG) #if (defined ASSIMP_BUILD_DEBUG)
#define AI_DEBUG_INVALIDATE_PTR(x) x = NULL; # define AI_DEBUG_INVALIDATE_PTR(x) x = NULL;
#else #else
#define AI_DEBUG_INVALIDATE_PTR(x) # define AI_DEBUG_INVALIDATE_PTR(x)
#endif #endif
#define AI_COUNT_OF(X) (sizeof(X) / sizeof((X)[0])) #define AI_COUNT_OF(X) (sizeof(X) / sizeof((X)[0]))
/**
* @brief Will mark functions or classes as deprecated.
*
* Deprecation means that we will remove this function, class or methods in the next m
*/
#if defined(__GNUC__) || defined(__clang__)
# define AI_DEPRECATED __attribute__((deprecated))
#elif defined(_MSC_VER)
# define AI_DEPRECATED __declspec(deprecated)
#else
# pragma message("WARNING: You need to implement DEPRECATED for this compiler")
# define AI_DEPRECATED
#endif
#endif // !! AI_DEFINES_H_INC #endif // !! AI_DEFINES_H_INC

View File

@ -100,6 +100,7 @@ SET( COMMON
unit/Common/utBase64.cpp unit/Common/utBase64.cpp
unit/Common/utHash.cpp unit/Common/utHash.cpp
unit/Common/utBaseProcess.cpp unit/Common/utBaseProcess.cpp
unit/Common/utLogger.cpp
) )
SET(Geometry SET(Geometry

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,52 @@
/*
---------------------------------------------------------------------------
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other
materials provided with the distribution.
* Neither the name of the assimp team, nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior
written permission of the assimp team.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
#include "UnitTestPCH.h"
#include <assimp/Importer.hpp>
using namespace Assimp;
class utLogger : public ::testing::Test {};
TEST_F(utLogger, aiGetPredefinedLogStream_leak_test) {
aiLogStream stream1 = aiGetPredefinedLogStream(aiDefaultLogStream_STDOUT, nullptr);
aiLogStream stream2 = aiGetPredefinedLogStream(aiDefaultLogStream_STDOUT, nullptr);
ASSERT_EQ(stream1.callback, stream2.callback);
}

View File

@ -311,6 +311,37 @@ TEST_F(utFBXImporterExporter, sceneMetadata) {
} }
} }
TEST_F(utFBXImporterExporter, importCustomAxes) {
// see https://github.com/assimp/assimp/issues/5494
Assimp::Importer importer;
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/FBX/embedded_ascii/box.FBX", aiProcess_ValidateDataStructure);
EXPECT_NE(nullptr, scene);
// The ASCII box has customised the Up and Forward axes, verify that the RootNode transform has applied it
ASSERT_FALSE(scene->mRootNode->mTransformation.IsIdentity()) << "Did not apply the custom axis transform";
aiVector3D upVec{ 0, 0, 1 }; // Up is +Z
aiVector3D forwardVec{ 0, -1, 0 }; // Forward is -Y
aiVector3D rightVec{ 1, 0, 0 }; // Right is +X
aiMatrix4x4 mat(rightVec.x, rightVec.y, rightVec.z, 0.0f,
upVec.x, upVec.y, upVec.z, 0.0f,
forwardVec.x, forwardVec.y, forwardVec.z, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f);
EXPECT_EQ(mat, scene->mRootNode->mTransformation);
}
TEST_F(utFBXImporterExporter, importIgnoreCustomAxes) {
// see https://github.com/assimp/assimp/issues/5494
Assimp::Importer importer;
importer.SetPropertyBool(AI_CONFIG_IMPORT_FBX_IGNORE_UP_DIRECTION, true);
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/FBX/embedded_ascii/box.FBX", aiProcess_ValidateDataStructure);
EXPECT_NE(nullptr, scene);
// Verify that the RootNode transform has NOT applied the custom axes
EXPECT_TRUE(scene->mRootNode->mTransformation.IsIdentity());
}
TEST_F(utFBXImporterExporter, importCubesWithOutOfRangeFloat) { TEST_F(utFBXImporterExporter, importCubesWithOutOfRangeFloat) {
Assimp::Importer importer; Assimp::Importer importer;
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/FBX/cubes_with_outofrange_float.fbx", aiProcess_ValidateDataStructure); const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/FBX/cubes_with_outofrange_float.fbx", aiProcess_ValidateDataStructure);

View File

@ -89,7 +89,7 @@ TEST_F(utPLYImportExport, exportTest_Success) {
#endif // ASSIMP_BUILD_NO_EXPORT #endif // ASSIMP_BUILD_NO_EXPORT
//Test issue 1623, crash when loading two PLY files in a row // Test issue 1623, crash when loading two PLY files in a row
TEST_F(utPLYImportExport, importerMultipleTest) { TEST_F(utPLYImportExport, importerMultipleTest) {
Assimp::Importer importer; Assimp::Importer importer;
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/PLY/cube.ply", aiProcess_ValidateDataStructure); const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/PLY/cube.ply", aiProcess_ValidateDataStructure);
@ -109,7 +109,7 @@ TEST_F(utPLYImportExport, importPLYwithUV) {
EXPECT_NE(nullptr, scene); EXPECT_NE(nullptr, scene);
EXPECT_NE(nullptr, scene->mMeshes[0]); EXPECT_NE(nullptr, scene->mMeshes[0]);
//This test model is using n-gons, so 6 faces instead of 12 tris // This test model is using n-gons, so 6 faces instead of 12 tris
EXPECT_EQ(6u, scene->mMeshes[0]->mNumFaces); EXPECT_EQ(6u, scene->mMeshes[0]->mNumFaces);
EXPECT_EQ(aiPrimitiveType_POLYGON, scene->mMeshes[0]->mPrimitiveTypes); EXPECT_EQ(aiPrimitiveType_POLYGON, scene->mMeshes[0]->mPrimitiveTypes);
EXPECT_EQ(true, scene->mMeshes[0]->HasTextureCoords(0)); EXPECT_EQ(true, scene->mMeshes[0]->HasTextureCoords(0));
@ -121,7 +121,7 @@ TEST_F(utPLYImportExport, importBinaryPLY) {
EXPECT_NE(nullptr, scene); EXPECT_NE(nullptr, scene);
EXPECT_NE(nullptr, scene->mMeshes[0]); EXPECT_NE(nullptr, scene->mMeshes[0]);
//This test model is double sided, so 12 faces instead of 6 // This test model is double sided, so 12 faces instead of 6
EXPECT_EQ(12u, scene->mMeshes[0]->mNumFaces); EXPECT_EQ(12u, scene->mMeshes[0]->mNumFaces);
} }
@ -160,7 +160,7 @@ TEST_F(utPLYImportExport, vertexColorTest) {
TEST_F(utPLYImportExport, pointcloudTest) { TEST_F(utPLYImportExport, pointcloudTest) {
Assimp::Importer importer; Assimp::Importer importer;
//Could not use aiProcess_ValidateDataStructure since it's missing faces. // Could not use aiProcess_ValidateDataStructure since it's missing faces.
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/PLY/issue623.ply", 0); const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/PLY/issue623.ply", 0);
EXPECT_NE(nullptr, scene); EXPECT_NE(nullptr, scene);
@ -192,7 +192,7 @@ static const char *test_file =
TEST_F(utPLYImportExport, parseErrorTest) { TEST_F(utPLYImportExport, parseErrorTest) {
Assimp::Importer importer; Assimp::Importer importer;
//Could not use aiProcess_ValidateDataStructure since it's missing faces. // Could not use aiProcess_ValidateDataStructure since it's missing faces.
const aiScene *scene = importer.ReadFileFromMemory(test_file, strlen(test_file), 0); const aiScene *scene = importer.ReadFileFromMemory(test_file, strlen(test_file), 0);
EXPECT_NE(nullptr, scene); EXPECT_NE(nullptr, scene);
} }
@ -203,3 +203,61 @@ TEST_F(utPLYImportExport, parseInvalid) {
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/invalid/crash-30d6d0f7c529b3b66b4131700b7a4580cd7082df.ply", 0); const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/invalid/crash-30d6d0f7c529b3b66b4131700b7a4580cd7082df.ply", 0);
EXPECT_EQ(nullptr, scene); EXPECT_EQ(nullptr, scene);
} }
TEST_F(utPLYImportExport, payload_JVN42386607) {
Assimp::Importer importer;
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/PLY/payload_JVN42386607", 0);
EXPECT_EQ(nullptr, scene);
}
// Tests Issue #5729. Test, if properties defined multiple times. Unclear what to do, better to abort than to crash entirely
TEST_F(utPLYImportExport, parseInvalidDoubleProperty) {
const char data[] = "ply\n"
"format ascii 1.0\n"
"element vertex 4\n"
"property float x\n"
"property float y\n"
"property float z\n"
"element vertex 8\n"
"property float x\n"
"property float y\n"
"property float z\n"
"end_header\n"
"0.0 0.0 0.0 0.0 0.0 0.0\n"
"0.0 0.0 1.0 0.0 0.0 1.0\n"
"0.0 1.0 0.0 0.0 1.0 0.0\n"
"0.0 0.0 1.0\n"
"0.0 1.0 0.0 0.0 0.0 1.0\n"
"0.0 1.0 1.0 0.0 1.0 1.0\n";
Assimp::Importer importer;
const aiScene *scene = importer.ReadFileFromMemory(data, sizeof(data), 0);
EXPECT_EQ(nullptr, scene);
}
// Tests Issue #5729. Test, if properties defined multiple times. Unclear what to do, better to abort than to crash entirely
TEST_F(utPLYImportExport, parseInvalidDoubleCustomProperty) {
const char data[] = "ply\n"
"format ascii 1.0\n"
"element vertex 4\n"
"property float x\n"
"property float y\n"
"property float z\n"
"element name 8\n"
"property float x\n"
"element name 5\n"
"property float x\n"
"end_header\n"
"0.0 0.0 0.0 100.0 10.0\n"
"0.0 0.0 1.0 200.0 20.0\n"
"0.0 1.0 0.0 300.0 30.0\n"
"0.0 1.0 1.0 400.0 40.0\n"
"0.0 0.0 0.0 500.0 50.0\n"
"0.0 0.0 1.0 600.0 60.0\n"
"0.0 1.0 0.0 700.0 70.0\n"
"0.0 1.0 1.0 800.0 80.0\n";
Assimp::Importer importer;
const aiScene *scene = importer.ReadFileFromMemory(data, sizeof(data), 0);
EXPECT_EQ(nullptr, scene);
}

View File

@ -61,7 +61,7 @@ TEST_F( utVersion, aiGetVersionMinorTest ) {
} }
TEST_F( utVersion, aiGetVersionPatchTest ) { TEST_F( utVersion, aiGetVersionPatchTest ) {
EXPECT_EQ(aiGetVersionPatch(), 1U ); EXPECT_EQ(aiGetVersionPatch(), 3U );
} }
TEST_F( utVersion, aiGetCompileFlagsTest ) { TEST_F( utVersion, aiGetCompileFlagsTest ) {