update assimp to 6.0.5

This commit is contained in:
AzaezelX 2026-06-09 12:46:56 -05:00
parent 2d2eb57e2e
commit f5cf21cfeb
941 changed files with 22718 additions and 12240 deletions

View file

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -81,7 +81,7 @@ void ArmaturePopulate::Execute(aiScene *out) {
aiBone *bone = kvp.first;
aiNode *bone_node = kvp.second;
ASSIMP_LOG_VERBOSE_DEBUG("active node lookup: ", bone->mName.C_Str());
// lcl transform grab - done in generate_nodes :)
aiNode *armature = GetArmatureRoot(bone_node, bones);

View file

@ -2,8 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -66,22 +65,22 @@ namespace Assimp {
* You can contact RevoluPowered <gordon@gordonite.tech>
* For more info about this
*/
class ASSIMP_API ArmaturePopulate : public BaseProcess {
class ASSIMP_API ArmaturePopulate final : public BaseProcess {
public:
/// The default class constructor.
ArmaturePopulate() = default;
/// The class destructor.
virtual ~ArmaturePopulate() = default;
~ArmaturePopulate() override = default;
/// Overwritten, @see BaseProcess
virtual bool IsActive( unsigned int pFlags ) const;
bool IsActive( unsigned int pFlags ) const override;
/// Overwritten, @see BaseProcess
virtual void SetupProperties( const Importer* pImp );
void SetupProperties( const Importer* pImp ) override;
/// Overwritten, @see BaseProcess
virtual void Execute( aiScene* pScene );
void Execute( aiScene* pScene ) override;
static aiNode *GetArmatureRoot(aiNode *bone_node,
std::vector<aiBone *> &bone_list);

View file

@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
@ -200,7 +200,7 @@ bool CalcTangentsProcess::ProcessMesh(aiMesh *pMesh, unsigned int meshIndex) {
localBitangent.NormalizeSafe();
// reconstruct tangent/bitangent according to normal and bitangent/tangent when it's infinite or NaN.
bool invalid_tangent = is_special_float(localTangent.x) || is_special_float(localTangent.y) || is_special_float(localTangent.z)
bool invalid_tangent = is_special_float(localTangent.x) || is_special_float(localTangent.y) || is_special_float(localTangent.z)
|| (-0.5f < localTangent.x && localTangent.x < 0.5f && -0.5f < localTangent.y && localTangent.y < 0.5f && -0.5f < localTangent.z && localTangent.z < 0.5f);
bool invalid_bitangent = is_special_float(localBitangent.x) || is_special_float(localBitangent.y) || is_special_float(localBitangent.z)
|| (-0.5f < localBitangent.x && localBitangent.x < 0.5f && -0.5f < localBitangent.y && localBitangent.y < 0.5f && -0.5f < localBitangent.z && localBitangent.z < 0.5f);

View file

@ -2,8 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -59,7 +58,7 @@ namespace Assimp
* because the joining of vertices also considers tangents and bitangents for
* uniqueness.
*/
class ASSIMP_API_WINONLY CalcTangentsProcess : public BaseProcess {
class ASSIMP_API_WINONLY CalcTangentsProcess final : public BaseProcess {
public:
CalcTangentsProcess();
~CalcTangentsProcess() override = default;

View file

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.

View file

@ -2,8 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -59,7 +58,7 @@ namespace Assimp {
/** ComputeUVMappingProcess - converts special mappings, such as spherical,
* cylindrical or boxed to proper UV coordinates for rendering.
*/
class ComputeUVMappingProcess : public BaseProcess {
class ComputeUVMappingProcess final : public BaseProcess {
public:
ComputeUVMappingProcess() = default;
~ComputeUVMappingProcess() override = default;

View file

@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.

View file

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -60,7 +60,7 @@ struct aiNode;
struct aiMaterial;
struct aiCamera;
namespace Assimp {
namespace Assimp {
// -----------------------------------------------------------------------------------
/** @brief The MakeLeftHandedProcess converts all imported data to a left-handed
@ -72,7 +72,7 @@ namespace Assimp {
*
* @note RH-LH and LH-RH is the same, so this class can be used for both
*/
class MakeLeftHandedProcess : public BaseProcess {
class MakeLeftHandedProcess final : public BaseProcess {
public:
MakeLeftHandedProcess() = default;
~MakeLeftHandedProcess() override = default;
@ -147,7 +147,7 @@ public:
// ---------------------------------------------------------------------------
/** Postprocessing step to flip the UV coordinate system of the import data
*/
class FlipUVsProcess : public BaseProcess
class FlipUVsProcess final : public BaseProcess
{
friend class Importer;
@ -156,13 +156,13 @@ public:
FlipUVsProcess();
/** Destructor, private as well */
~FlipUVsProcess();
~FlipUVsProcess() override;
// -------------------------------------------------------------------
bool IsActive( unsigned int pFlags) const;
bool IsActive( unsigned int pFlags) const override;
// -------------------------------------------------------------------
void Execute( aiScene* pScene);
void Execute( aiScene* pScene) override;
protected:
void ProcessMesh( aiMesh* pMesh);

View file

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -187,7 +187,7 @@ bool DeboneProcess::ConsiderMesh(const aiMesh* pMesh) {
}
} else {
vertexBones[vid] = i;
}
}
}
if(!isBoneNecessary[i]) {

View file

@ -2,8 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -52,7 +51,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <vector>
#include <utility>
#// Forward declarations
// Forward declarations
class DeboneTest;
namespace Assimp {
@ -67,13 +66,15 @@ namespace Assimp {
* the bone are split from the mesh. The split off (new) mesh is boneless. At any
* point in time, bones without affect upon a given mesh are to be removed.
*/
class DeboneProcess : public BaseProcess {
class DeboneProcess final : public BaseProcess {
public:
DeboneProcess();
~DeboneProcess() override = default;
// -------------------------------------------------------------------
/** Returns whether the processing step is present in the given flag.
/**
* @brief Returns whether the processing step is present in the given flag.
*
* @param pFlags The processing flags the importer was called with.
* A bitwise combination of #aiPostProcessSteps.
* @return true if the process is present in this flag fields,
@ -82,7 +83,9 @@ public:
bool IsActive( unsigned int pFlags) const override;
// -------------------------------------------------------------------
/** Called prior to ExecuteOnScene().
/**
* @brief Called prior to ExecuteOnScene().
*
* The function is a request to the process to update its configuration
* basing on the Importer's configuration property list.
*/
@ -90,33 +93,41 @@ public:
protected:
// -------------------------------------------------------------------
/** Executes the post processing step on the given imported data.
* At the moment a process is not supposed to fail.
* @param pScene The imported data to work at.
*/
/**
* @brief Executes the post processing step on the given imported data.
*
* At the moment a process is not supposed to fail.
* @param pScene The imported data to work at.
*/
void Execute( aiScene* pScene) override;
// -------------------------------------------------------------------
/** Counts bones total/removable in a given mesh.
/**
* @brief Counts bones total/removable in a given mesh.
*
* @param pMesh The mesh to process.
* @return false in case of an error.
*/
bool ConsiderMesh( const aiMesh* pMesh);
/// Splits the given mesh by bone count.
/// @brief Splits the given mesh by bone count.
/// @param pMesh the Mesh to split. Is not changed at all, but might be superfluous in case it was split.
/// @param poNewMeshes Array of submeshes created in the process. Empty if splitting was not necessary.
void SplitMesh(const aiMesh* pMesh, std::vector< std::pair< aiMesh*,const aiBone* > >& poNewMeshes) const;
/// Recursively updates the node's mesh list to account for the changed mesh list
/// @brief Recursively updates the node's mesh list to account for the changed mesh list
/// @param pNode The root node to update.
void UpdateNode(aiNode* pNode) const;
// -------------------------------------------------------------------
// Apply transformation to a mesh
/// @brief Apply transformation to a mesh
/// @param mesh The mesh to apply the transformation
/// @param mat The transformation to appy
void ApplyTransform(aiMesh* mesh, const aiMatrix4x4& mat)const;
public:
/** Number of bones present in the scene. */
unsigned int mNumBones;
/// Number of bones present in the scene.
unsigned int mNumBones;
unsigned int mNumBonesCanDoWithout;
float mThreshold;

View file

@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team

View file

@ -2,8 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -53,7 +52,7 @@ namespace Assimp {
// ---------------------------------------------------------------------------
/** The DropFaceNormalsProcess computes face normals for all faces of all meshes
*/
class ASSIMP_API_WINONLY DropFaceNormalsProcess : public BaseProcess {
class ASSIMP_API_WINONLY DropFaceNormalsProcess final : public BaseProcess {
public:
DropFaceNormalsProcess() = default;
~DropFaceNormalsProcess() override = default;

View file

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -113,14 +113,14 @@ std::string EmbedTexturesProcess::tryToFindValidPath(const std::string &imagePat
}
// In unix systems, '\' is a valid file name character, but some files may use \ as a directory separator.
// Try replacing '\' by '/'.
// Try replacing '\' by '/'.
if (mIOHandler->getOsSeparator() != '\\' && imagePath.find('\\') != std::string::npos) {
ASSIMP_LOG_WARN("EmbedTexturesProcess: Cannot find image '", imagePath, "' in root folder. Will try replacing directory separators.");
testPath = imagePath;
std::replace(testPath.begin(), testPath.end(), '\\', mIOHandler->getOsSeparator());
return tryToFindValidPath(testPath);
}
ASSIMP_LOG_ERROR("EmbedTexturesProcess: Unable to embed texture: ", imagePath, ".");
return {};
}

View file

@ -2,8 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -59,7 +58,7 @@ namespace Assimp {
* it will check if a file with the same name exists at the root folder
* of the imported model. And if so, it uses that.
*/
class ASSIMP_API EmbedTexturesProcess : public BaseProcess {
class ASSIMP_API EmbedTexturesProcess final : public BaseProcess {
public:
/// The default class constructor.
EmbedTexturesProcess() = default;
@ -74,7 +73,7 @@ public:
void SetupProperties(const Importer* pImp) override;
/// Overwritten, @see BaseProcess
virtual void Execute(aiScene* pScene) override;
void Execute(aiScene* pScene) override;
private:
// Try several ways to attempt to resolve the image path

View file

@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.

View file

@ -2,8 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -50,7 +49,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/mesh.h>
class FindDegeneratesProcessTest;
namespace Assimp {
namespace Assimp {
// ---------------------------------------------------------------------------

View file

@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team

View file

@ -2,8 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.

View file

@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.

View file

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.

View file

@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team

View file

@ -2,8 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.

View file

@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.

View file

@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -19,7 +19,7 @@ conditions are met:
copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other
materials provided with the distribution.
s
* 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
@ -54,7 +54,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace Assimp {
/**
/**
* @brief Post-processing process to find axis-aligned bounding volumes for amm meshes
* used in a scene.
*/

View file

@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -39,7 +39,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
/**
/**
* @file Implementation of the post-processing step to generate face
* normals for all imported faces.
*/
@ -51,6 +51,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/scene.h>
#include <assimp/DefaultLogger.hpp>
#include <numeric>
#include <memory>
using namespace Assimp;
// ------------------------------------------------------------------------------------------------
@ -86,6 +89,64 @@ void GenFaceNormalsProcess::Execute(aiScene *pScene) {
}
}
namespace {
template<class XMesh>
void updateXMeshVertices(XMesh *pMesh, std::vector<int> &uniqueVertices) {
// replace vertex data with the unique data sets
pMesh->mNumVertices = static_cast<unsigned int>(uniqueVertices.size());
// ----------------------------------------------------------------------------
// NOTE - we're *not* calling Vertex::SortBack() because it would check for
// presence of every single vertex component once PER VERTEX. And our CPU
// dislikes branches, even if they're easily predictable.
// ----------------------------------------------------------------------------
// Position, if present (check made for aiAnimMesh)
if (pMesh->mVertices) {
std::unique_ptr<aiVector3D[]> oldVertices(pMesh->mVertices);
pMesh->mVertices = new aiVector3D[pMesh->mNumVertices];
for (unsigned int a = 0; a < pMesh->mNumVertices; a++) {
pMesh->mVertices[a] = oldVertices[uniqueVertices[a]];
}
}
// Tangents, if present
if (pMesh->mTangents) {
std::unique_ptr<aiVector3D[]> oldTangents(pMesh->mTangents);
pMesh->mTangents = new aiVector3D[pMesh->mNumVertices];
for (unsigned int a = 0; a < pMesh->mNumVertices; a++) {
pMesh->mTangents[a] = oldTangents[uniqueVertices[a]];
}
}
// Bitangents as well
if (pMesh->mBitangents) {
std::unique_ptr<aiVector3D[]> oldBitangents(pMesh->mBitangents);
pMesh->mBitangents = new aiVector3D[pMesh->mNumVertices];
for (unsigned int a = 0; a < pMesh->mNumVertices; a++) {
pMesh->mBitangents[a] = oldBitangents[uniqueVertices[a]];
}
}
// Vertex colors
for (unsigned int a = 0; pMesh->HasVertexColors(a); a++) {
std::unique_ptr<aiColor4D[]> oldColors(pMesh->mColors[a]);
pMesh->mColors[a] = new aiColor4D[pMesh->mNumVertices];
for (unsigned int b = 0; b < pMesh->mNumVertices; b++) {
pMesh->mColors[a][b] = oldColors[uniqueVertices[b]];
}
}
// Texture coords
for (unsigned int a = 0; pMesh->HasTextureCoords(a); a++) {
std::unique_ptr<aiVector3D[]> oldTextureCoords(pMesh->mTextureCoords[a]);
pMesh->mTextureCoords[a] = new aiVector3D[pMesh->mNumVertices];
for (unsigned int b = 0; b < pMesh->mNumVertices; b++) {
pMesh->mTextureCoords[a][b] = oldTextureCoords[uniqueVertices[b]];
}
}
}
} // namespace
// ------------------------------------------------------------------------------------------------
// Executes the post-processing step on the given imported data.
bool GenFaceNormalsProcess::GenMeshFaceNormals(aiMesh *pMesh) {
@ -112,17 +173,21 @@ bool GenFaceNormalsProcess::GenMeshFaceNormals(aiMesh *pMesh) {
// mask to indicate if a vertex was already referenced and needs to be duplicated
std::vector<bool> alreadyReferenced;
alreadyReferenced.resize(pMesh->mNumVertices, false);
std::vector<aiVector3D> duplicatedVertices;
std::vector<int> duplicatedVertices;
duplicatedVertices.resize(pMesh->mNumVertices);
std::iota(std::begin(duplicatedVertices), std::end(duplicatedVertices), 0);
auto storeNormalSplitVertex = [&](unsigned int index, const aiVector3D& normal) {
if (!alreadyReferenced[index]) {
normals[index] = normal;
alreadyReferenced[index] = true;
} else {
duplicatedVertices.push_back(pMesh->mVertices[index]);
normals.push_back(normal);
index = pMesh->mNumVertices + static_cast<unsigned int>(duplicatedVertices.size() - 1);
duplicatedVertices.push_back(index);
index = static_cast<unsigned int>(duplicatedVertices.size() - 1);
}
return index;
};
@ -144,7 +209,7 @@ bool GenFaceNormalsProcess::GenMeshFaceNormals(aiMesh *pMesh) {
const aiVector3D *pV3 = &pMesh->mVertices[face.mIndices[face.mNumIndices - 1]];
// Boolean XOR - if either but not both of these flags are set, then the winding order has
// changed and the cross-product to calculate the normal needs to be reversed
if (flippedWindingOrder_ != leftHanded_)
if (flippedWindingOrder_ != leftHanded_)
std::swap(pV2, pV3);
const aiVector3D vNor = ((*pV2 - *pV1) ^ (*pV3 - *pV1)).NormalizeSafe();
@ -154,16 +219,10 @@ bool GenFaceNormalsProcess::GenMeshFaceNormals(aiMesh *pMesh) {
}
// store normals (and additional vertices) back into the mesh
if (!duplicatedVertices.empty()) {
const aiVector3D * oldVertices = pMesh->mVertices;
auto oldNumVertices = pMesh->mNumVertices;
pMesh->mNumVertices += static_cast<unsigned int>(duplicatedVertices.size());
pMesh->mVertices = new aiVector3D[pMesh->mNumVertices];
memcpy(pMesh->mVertices, oldVertices, oldNumVertices * sizeof(aiVector3D));
memcpy(pMesh->mVertices + oldNumVertices, duplicatedVertices.data(), duplicatedVertices.size() * sizeof(aiVector3D));
delete[] oldVertices;
if (pMesh->mNumVertices != std::size(duplicatedVertices)) {
updateXMeshVertices(pMesh, duplicatedVertices);
}
pMesh->mNormals = new aiVector3D[pMesh->mNumVertices];
pMesh->mNormals = new aiVector3D[normals.size()];
memcpy(pMesh->mNormals, normals.data(), normals.size() * sizeof(aiVector3D));
return true;

View file

@ -2,8 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -50,7 +49,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace Assimp {
// ---------------------------------------------------------------------------
/**
/**
* @brief The GenFaceNormalsProcess computes face normals for all faces of all meshes
*/
class ASSIMP_API_WINONLY GenFaceNormalsProcess : public BaseProcess {

View file

@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.

View file

@ -2,8 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.

View file

@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -58,11 +58,55 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <stack>
namespace Assimp {
namespace {
ai_real calculateInputACMR(aiMesh *pMesh, const aiFace *const pcEnd,
unsigned int configCacheDepth, unsigned int meshNum) {
ai_real fACMR = 0.0f;
unsigned int *piFIFOStack = new unsigned int[configCacheDepth];
memset(piFIFOStack, 0xff, configCacheDepth * sizeof(unsigned int));
unsigned int *piCur = piFIFOStack;
const unsigned int *const piCurEnd = piFIFOStack + configCacheDepth;
// count the number of cache misses
unsigned int iCacheMisses = 0;
for (const aiFace *pcFace = pMesh->mFaces; pcFace != pcEnd; ++pcFace) {
for (unsigned int qq = 0; qq < 3; ++qq) {
bool bInCache = false;
for (unsigned int *pp = piFIFOStack; pp < piCurEnd; ++pp) {
if (*pp == pcFace->mIndices[qq]) {
// the vertex is in cache
bInCache = true;
break;
}
}
if (!bInCache) {
++iCacheMisses;
if (piCurEnd == piCur) {
piCur = piFIFOStack;
}
*piCur++ = pcFace->mIndices[qq];
}
}
}
delete[] piFIFOStack;
fACMR = (ai_real)iCacheMisses / pMesh->mNumFaces;
if (3.0 == fACMR) {
char szBuff[128]; // should be sufficiently large in every case
// the JoinIdenticalVertices process has not been executed on this
// mesh, otherwise this value would normally be at least minimally
// smaller than 3.0 ...
ai_snprintf(szBuff, 128, "Mesh %u: Not suitable for vcache optimization", meshNum);
ASSIMP_LOG_WARN(szBuff);
return static_cast<ai_real>(0.f);
}
return fACMR;
}
}
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
ImproveCacheLocalityProcess::ImproveCacheLocalityProcess() :
mConfigCacheDepth(PP_ICL_PTCACHE_SIZE) {
ImproveCacheLocalityProcess::ImproveCacheLocalityProcess() : mConfigCacheDepth(PP_ICL_PTCACHE_SIZE) {
// empty
}
@ -107,51 +151,6 @@ void ImproveCacheLocalityProcess::Execute(aiScene *pScene) {
}
}
// ------------------------------------------------------------------------------------------------
static ai_real calculateInputACMR(aiMesh *pMesh, const aiFace *const pcEnd,
unsigned int configCacheDepth, unsigned int meshNum) {
ai_real fACMR = 0.0f;
unsigned int *piFIFOStack = new unsigned int[configCacheDepth];
memset(piFIFOStack, 0xff, configCacheDepth * sizeof(unsigned int));
unsigned int *piCur = piFIFOStack;
const unsigned int *const piCurEnd = piFIFOStack + configCacheDepth;
// count the number of cache misses
unsigned int iCacheMisses = 0;
for (const aiFace *pcFace = pMesh->mFaces; pcFace != pcEnd; ++pcFace) {
for (unsigned int qq = 0; qq < 3; ++qq) {
bool bInCache = false;
for (unsigned int *pp = piFIFOStack; pp < piCurEnd; ++pp) {
if (*pp == pcFace->mIndices[qq]) {
// the vertex is in cache
bInCache = true;
break;
}
}
if (!bInCache) {
++iCacheMisses;
if (piCurEnd == piCur) {
piCur = piFIFOStack;
}
*piCur++ = pcFace->mIndices[qq];
}
}
}
delete[] piFIFOStack;
fACMR = (ai_real)iCacheMisses / pMesh->mNumFaces;
if (3.0 == fACMR) {
char szBuff[128]; // should be sufficiently large in every case
// the JoinIdenticalVertices process has not been executed on this
// mesh, otherwise this value would normally be at least minimally
// smaller than 3.0 ...
ai_snprintf(szBuff, 128, "Mesh %u: Not suitable for vcache optimization", meshNum);
ASSIMP_LOG_WARN(szBuff);
return static_cast<ai_real>(0.f);
}
return fACMR;
}
// ------------------------------------------------------------------------------------------------
// Improves the cache coherency of a specific mesh
ai_real ImproveCacheLocalityProcess::ProcessMesh(aiMesh *pMesh, unsigned int meshNum) {
@ -380,4 +379,3 @@ ai_real ImproveCacheLocalityProcess::ProcessMesh(aiMesh *pMesh, unsigned int mes
}
} // namespace Assimp

View file

@ -2,8 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.

View file

@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -100,6 +100,65 @@ void JoinVerticesProcess::Execute( aiScene* pScene) {
namespace {
struct CompareVerticesAlmostEqual {
bool operator () (const Vertex & a, const Vertex & b) const {
static const float epsilon = 1e-5f;
static const float squareEpsilon = epsilon * epsilon;
if ((a.position - b.position).SquareLength() > squareEpsilon) {
return false;
}
// We just test the other attributes even if they're not present in the mesh.
// In this case they're initialized to 0 so the comparison succeeds.
// By this method the non-present attributes are effectively ignored in the comparison.
if ((a.normal - b.normal).SquareLength() > squareEpsilon) {
return false;
}
if ((a.tangent - b.tangent).SquareLength() > squareEpsilon) {
return false;
}
if ((a.bitangent - b.bitangent).SquareLength() > squareEpsilon) {
return false;
}
for (uint32_t i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; i ++) {
if ((a.texcoords[i] - b.texcoords[i]).SquareLength() > squareEpsilon) {
return false;
}
}
for (uint32_t i = 0; i < AI_MAX_NUMBER_OF_COLOR_SETS; i ++) {
if (GetColorDifference(a.colors[i], b.colors[i]) > squareEpsilon) {
return false;
}
}
// If reached this point, they are ~equal
return true;
}
};
struct HashVertex {
inline void hash_combine(std::size_t& seed, const ai_real& v) const {
std::hash<ai_real> hasher;
seed ^= hasher(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
}
size_t operator () (const Vertex & v) const {
size_t hash = 0;
hash_combine(hash, v.position.x);
hash_combine(hash, v.position.y);
hash_combine(hash, v.position.z);
return hash;
}
};
template<class XMesh>
void updateXMeshVertices(XMesh *pMesh, std::vector<int> &uniqueVertices) {
// replace vertex data with the unique data sets
@ -208,7 +267,7 @@ int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex) {
}
}
// a map that maps a vertex to its new index
std::map<Vertex, int> vertex2Index = {};
std::unordered_map<Vertex, int, HashVertex, CompareVerticesAlmostEqual> vertex2Index = {};
// we can not end up with more vertices than we started with
// Now check each vertex if it brings something new to the table
int newIndex = 0;

View file

@ -2,8 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -65,7 +64,7 @@ class ASSIMP_API JoinVerticesProcess : public BaseProcess {
public:
// -------------------------------------------------------------------
/// The default class constructor / destructor.
JoinVerticesProcess() = default;
JoinVerticesProcess() = default;
~JoinVerticesProcess() override = default;
// -------------------------------------------------------------------

View file

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -68,7 +68,7 @@ bool LimitBoneWeightsProcess::IsActive( unsigned int pFlags) const {
// Executes the post processing step on the given imported data.
void LimitBoneWeightsProcess::Execute( aiScene* pScene) {
ai_assert(pScene != nullptr);
ASSIMP_LOG_DEBUG("LimitBoneWeightsProcess begin");
for (unsigned int m = 0; m < pScene->mNumMeshes; ++m) {
@ -88,7 +88,7 @@ void LimitBoneWeightsProcess::SetupProperties(const Importer* pImp) {
// ------------------------------------------------------------------------------------------------
static unsigned int removeEmptyBones(aiMesh *pMesh) {
ai_assert(pMesh != nullptr);
unsigned int writeBone = 0;
for (unsigned int readBone = 0; readBone< pMesh->mNumBones; ++readBone) {
aiBone* bone = pMesh->mBones[readBone];
@ -98,7 +98,7 @@ static unsigned int removeEmptyBones(aiMesh *pMesh) {
delete bone;
}
}
return writeBone;
}

View file

@ -2,8 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.

View file

@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team

View file

@ -2,8 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -50,7 +49,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
struct aiMesh;
namespace Assimp {
namespace Assimp {
// ---------------------------------------------------------------------------
/** MakeVerboseFormatProcess: Class to convert an asset to the verbose

View file

@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.

View file

@ -2,8 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -58,7 +57,7 @@ struct aiMesh;
class OptimizeGraphProcessTest;
namespace Assimp {
namespace Assimp {
// -----------------------------------------------------------------------------
/** @brief Postprocessing step to optimize the scenegraph

View file

@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team

View file

@ -2,8 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -56,7 +55,7 @@ struct aiMesh;
struct aiNode;
class OptimizeMeshesProcessTest;
namespace Assimp {
namespace Assimp {
// ---------------------------------------------------------------------------
/** @brief Postprocessing step to optimize mesh usage

View file

@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -348,7 +348,7 @@ void PretransformVertices::BuildWCSMeshes(std::vector<aiMesh *> &out, aiMesh **i
mesh->mBones = reinterpret_cast<aiBone **>(&node->mTransformation);
mesh->mNumBones = UINT_MAX;
continue;
}
}
// try to find us in the list of newly created meshes
for (unsigned int n = 0; n < out.size(); ++n) {

View file

@ -2,8 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.

View file

@ -2,8 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.

View file

@ -2,8 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.

View file

@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -78,7 +78,7 @@ void RemoveRedundantMatsProcess::Execute( aiScene* pScene) {
if (pScene->mNumMaterials == 0) {
return;
}
// Find out which materials are referenced by meshes
std::vector<bool> abReferenced(pScene->mNumMaterials,false);
for (unsigned int i = 0;i < pScene->mNumMeshes;++i) {

View file

@ -2,8 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -51,7 +50,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
class RemoveRedundantMatsTest;
namespace Assimp {
namespace Assimp {
// ---------------------------------------------------------------------------
/** RemoveRedundantMatsProcess: Post-processing step to remove redundant

View file

@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.

View file

@ -2,8 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -83,7 +82,7 @@ public:
* The function is a request to the process to update its configuration
* basing on the Importer's configuration property list.
*/
virtual void SetupProperties(const Importer* pImp) override;
void SetupProperties(const Importer* pImp) override;
// -------------------------------------------------------------------
/** Manually setup the configuration flags for the step

View file

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.

View file

@ -2,8 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -74,13 +73,13 @@ public:
ai_real getScale() const;
/// Overwritten, @see BaseProcess
virtual bool IsActive( unsigned int pFlags ) const override;
bool IsActive( unsigned int pFlags ) const override;
/// Overwritten, @see BaseProcess
virtual void SetupProperties( const Importer* pImp ) override;
void SetupProperties( const Importer* pImp ) override;
/// Overwritten, @see BaseProcess
virtual void Execute( aiScene* pScene ) override;
void Execute( aiScene* pScene ) override;
private:
void traverseNodes( aiNode *currentNode, unsigned int nested_node_id = 0 );

View file

@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -76,7 +76,7 @@ static void clearMeshesInNode(aiNode *node) {
// Update changed meshes in all nodes
void UpdateNodes(const std::vector<unsigned int> &replaceMeshIndex, aiNode *node) {
ai_assert(node != nullptr);
if (node->mNumMeshes) {
unsigned int newSize = 0;
for (unsigned int m = 0; m < node->mNumMeshes; ++m) {
@ -91,7 +91,7 @@ void UpdateNodes(const std::vector<unsigned int> &replaceMeshIndex, aiNode *node
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) {
@ -136,6 +136,9 @@ void SortByPTypeProcess::Execute(aiScene *pScene) {
for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
aiMesh *const mesh = pScene->mMeshes[i];
if (mesh->mPrimitiveTypes == 0) {
for (size_t idx = 0; idx < outMeshes.size(); ++idx) {
delete outMeshes[idx];
}
throw DeadlyImportError("Mesh with invalid primitive type: ", mesh->mName.C_Str());
}
@ -162,6 +165,7 @@ void SortByPTypeProcess::Execute(aiScene *pScene) {
if (!(mConfigRemoveMeshes & mesh->mPrimitiveTypes)) {
*meshIdx = static_cast<unsigned int>(outMeshes.size());
outMeshes.emplace_back(mesh);
pScene->mMeshes[i] = nullptr; // Indicate ownership transfer
} else {
delete mesh;
pScene->mMeshes[i] = nullptr;
@ -185,12 +189,15 @@ void SortByPTypeProcess::Execute(aiScene *pScene) {
unsigned int numPolyVerts = 0;
for (; pFirstFace != pLastFace; ++pFirstFace) {
if (pFirstFace->mNumIndices <= 3)
if (pFirstFace->mNumIndices >= 1 && pFirstFace->mNumIndices <= 3)
++aiNumPerPType[pFirstFace->mNumIndices - 1];
else {
++aiNumPerPType[3];
numPolyVerts += pFirstFace->mNumIndices;
}
if (pFirstFace->mNumIndices == 0) {
ASSIMP_LOG_WARN("Face with 0 indices treated as polygon");
}
}
VertexWeightTable *avw = ComputeVertexBoneWeightTable(mesh);
@ -322,7 +329,7 @@ void SortByPTypeProcess::Execute(aiScene *pScene) {
if (vert) {
*vert++ = mesh->mVertices[idx];
}
if (nor)
if (nor)
*nor++ = mesh->mNormals[idx];
if (tan) {
*tan++ = mesh->mTangents[idx];
@ -330,13 +337,13 @@ void SortByPTypeProcess::Execute(aiScene *pScene) {
}
for (unsigned int pp = 0; pp < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++pp) {
if (!uv[pp])
if (!uv[pp])
break;
*uv[pp]++ = mesh->mTextureCoords[pp][idx];
}
for (unsigned int pp = 0; pp < AI_MAX_NUMBER_OF_COLOR_SETS; ++pp) {
if (!cols[pp])
if (!cols[pp])
break;
*cols[pp]++ = mesh->mColors[pp][idx];
}

View file

@ -2,8 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -50,7 +49,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
class SortByPTypeProcessTest;
namespace Assimp {
namespace Assimp {
// ---------------------------------------------------------------------------

View file

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.

View file

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -74,7 +74,7 @@ public:
/// @brief Called prior to ExecuteOnScene().
/// The function is a request to the process to update its configuration
/// basing on the Importer's configuration property list.
virtual void SetupProperties(const Importer* pImp) override;
void SetupProperties(const Importer* pImp) override;
/// @brief Will return the maximal number of bones.
/// @return The maximal number of bones.

View file

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -102,9 +102,9 @@ void SplitLargeMeshesProcess_Triangle::SetupProperties( const Importer* pImp) {
void SplitLargeMeshesProcess_Triangle::UpdateNode(aiNode* pcNode, const std::vector<std::pair<aiMesh*, unsigned int> >& avList) {
if (pcNode == nullptr) {
ASSIMP_LOG_WARN("UpdateNode skipped, nullptr detected.");
return;
return;
}
// for every index in out list build a new entry
std::vector<unsigned int> aiEntries;
aiEntries.reserve(pcNode->mNumMeshes + 1);

View file

@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.

View file

@ -1,8 +1,7 @@
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -35,27 +34,20 @@ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
/** @file A helper class that processes texture transformations */
#include "TextureTransform.h"
#include <assimp/Importer.hpp>
#include <assimp/postprocess.h>
#include <assimp/DefaultLogger.hpp>
#include <assimp/scene.h>
#include "TextureTransform.h"
#include <assimp/StringUtils.h>
using namespace Assimp;
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
TextureTransformStep::TextureTransformStep() : configFlags() {
// nothing to do here
}
namespace Assimp {
// ------------------------------------------------------------------------------------------------
// Returns whether the processing step is present in the given flag field.
@ -202,7 +194,6 @@ inline static const char* MappingModeToChar(aiTextureMapMode map) {
void TextureTransformStep::Execute( aiScene* pScene) {
ASSIMP_LOG_DEBUG("TransformUVCoordsProcess begin");
/* We build a per-mesh list of texture transformations we'll need
* to apply. To achieve this, we iterate through all materials,
* find all textures and get their transformations and UV indices.
@ -426,7 +417,6 @@ void TextureTransformStep::Execute( aiScene* pScene) {
// it shouldn't be too worse if we remove them.
unsigned int size = (unsigned int)trafo.size();
if (size > AI_MAX_NUMBER_OF_TEXTURECOORDS) {
if (!DefaultLogger::isNullLogger()) {
ASSIMP_LOG_ERROR(static_cast<unsigned int>(trafo.size()), " UV channels required but just ",
AI_MAX_NUMBER_OF_TEXTURECOORDS, " available");
@ -434,7 +424,6 @@ void TextureTransformStep::Execute( aiScene* pScene) {
size = AI_MAX_NUMBER_OF_TEXTURECOORDS;
}
aiVector3D* old[AI_MAX_NUMBER_OF_TEXTURECOORDS];
for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_TEXTURECOORDS;++n)
old[n] = mesh->mTextureCoords[n];
@ -443,14 +432,13 @@ void TextureTransformStep::Execute( aiScene* pScene) {
// that we're not going to need later can be overridden.
it = trafo.begin();
for (unsigned int n = 0; n < trafo.size();++n,++it) {
if (n >= size) {
// Try to use an untransformed channel for all channels we threw over board
UpdateUVIndex((*it).updateList,untransformed);
continue;
}
outChannels++;
++outChannels;
// Write to the log
if (!DefaultLogger::isNullLogger()) {
@ -470,15 +458,18 @@ void TextureTransformStep::Execute( aiScene* pScene) {
// Check whether we need a new buffer here
if (mesh->mTextureCoords[n]) {
it2 = it;++it2;
it2 = it;
++it2;
for (unsigned int m = n+1; m < size;++m, ++it2) {
if ((*it2).uvIndex == n){
it2 = trafo.begin();
break;
}
}
if (it2 == trafo.begin()){
if (it2 == trafo.begin()) {
{
std::unique_ptr<aiVector3D[]> oldTextureCoords(mesh->mTextureCoords[n]);
}
mesh->mTextureCoords[n] = new aiVector3D[mesh->mNumVertices];
}
}
@ -536,13 +527,12 @@ void TextureTransformStep::Execute( aiScene* pScene) {
// Print some detailed statistics into the log
if (!DefaultLogger::isNullLogger()) {
if (transformedChannels) {
ASSIMP_LOG_INFO("TransformUVCoordsProcess end: ", outChannels, " output channels (in: ", inChannels, ", modified: ", transformedChannels,")");
} else {
ASSIMP_LOG_DEBUG("TransformUVCoordsProcess finished");
ASSIMP_LOG_INFO("TransformUVCoordsProcess finished");
}
}
}
} // namespace Assimp

View file

@ -1,9 +1,7 @@
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -44,142 +42,116 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef AI_TEXTURE_TRANSFORM_H_INCLUDED
#define AI_TEXTURE_TRANSFORM_H_INCLUDED
#include <assimp/BaseImporter.h>
#include "Common/BaseProcess.h"
#include <assimp/BaseImporter.h>
#include <assimp/material.h>
#include <list>
struct aiNode;
struct aiMaterial;
namespace Assimp {
namespace Assimp {
#define AI_TT_UV_IDX_LOCK_TBD 0xffffffff
#define AI_TT_UV_IDX_LOCK_NONE 0xeeeeeeee
#define AI_TT_ROTATION_EPSILON ((float)AI_DEG_TO_RAD(0.5))
// ---------------------------------------------------------------------------
/** Small helper structure representing a shortcut into the material list
* to be able to update some values quickly.
*/
/**
* @brief Small helper structure representing a shortcut into the material list
* to be able to update some values quickly.
*/
struct TTUpdateInfo {
TTUpdateInfo() AI_NO_EXCEPT
: directShortcut(nullptr)
, mat(nullptr)
, semantic(0)
, index(0) {
// empty
}
//! Direct shortcut, if available
unsigned int* directShortcut;
unsigned int* directShortcut = nullptr;
//! Material
aiMaterial *mat;
aiMaterial *mat = nullptr;
//! Texture type and index
unsigned int semantic, index;
//! Texture type
unsigned int semantic = 0;
//! Texture index
unsigned int index = 0;
};
// ---------------------------------------------------------------------------
/** Helper class representing texture coordinate transformations
*/
/**
* @brief Helper class representing texture coordinate transformations
*/
struct STransformVecInfo : public aiUVTransform {
STransformVecInfo() AI_NO_EXCEPT
: uvIndex(0)
, mapU(aiTextureMapMode_Wrap)
, mapV(aiTextureMapMode_Wrap)
, lockedPos(AI_TT_UV_IDX_LOCK_NONE) {
// empty
}
//! Source texture coordinate index
unsigned int uvIndex;
unsigned int uvIndex = 0;
//! Texture mapping mode in the u, v direction
aiTextureMapMode mapU,mapV;
//! Texture mapping mode in the u direction
aiTextureMapMode mapU = aiTextureMapMode_Wrap;
//! Texture mapping mode in the v direction
aiTextureMapMode mapV = aiTextureMapMode_Wrap;
//! Locked destination UV index
//! AI_TT_UV_IDX_LOCK_TBD - to be determined
//! AI_TT_UV_IDX_LOCK_NONE - none (default)
unsigned int lockedPos;
unsigned int lockedPos = AI_TT_UV_IDX_LOCK_NONE;
//! Update info - shortcuts into all materials
//! that are referencing this transform setup
std::list<TTUpdateInfo> updateList;
// -------------------------------------------------------------------
/** Compare two transform setups
*/
inline bool operator== (const STransformVecInfo& other) const
{
inline bool operator== (const STransformVecInfo& other) const {
// We use a small epsilon here
const static float epsilon = 0.05f;
if (std::fabs( mTranslation.x - other.mTranslation.x ) > epsilon ||
std::fabs( mTranslation.y - other.mTranslation.y ) > epsilon)
{
std::fabs( mTranslation.y - other.mTranslation.y ) > epsilon) {
return false;
}
if (std::fabs( mScaling.x - other.mScaling.x ) > epsilon ||
std::fabs( mScaling.y - other.mScaling.y ) > epsilon)
{
std::fabs( mScaling.y - other.mScaling.y ) > epsilon) {
return false;
}
if (std::fabs( mRotation - other.mRotation) > epsilon)
{
if (std::fabs( mRotation - other.mRotation) > epsilon) {
return false;
}
return true;
}
inline bool operator!= (const STransformVecInfo& other) const
{
inline bool operator!= (const STransformVecInfo& other) const {
return !(*this == other);
}
// -------------------------------------------------------------------
/** Returns whether this is an untransformed texture coordinate set
*/
inline bool IsUntransformed() const
{
/**
* @brief Returns whether this is an untransformed texture coordinate set
*/
inline bool IsUntransformed() const {
return (1.0f == mScaling.x && 1.f == mScaling.y &&
!mTranslation.x && !mTranslation.y &&
mRotation < AI_TT_ROTATION_EPSILON);
!mTranslation.x && !mTranslation.y && mRotation < AI_TT_ROTATION_EPSILON);
}
// -------------------------------------------------------------------
/** Build a 3x3 matrix from the transformations
*/
inline void GetMatrix(aiMatrix3x3& mOut)
{
/**
* @brief Build a 3x3 matrix from the transformations
*/
inline void GetMatrix(aiMatrix3x3& mOut) {
mOut = aiMatrix3x3();
if (1.0f != mScaling.x || 1.0f != mScaling.y)
{
if (1.0f != mScaling.x || 1.0f != mScaling.y) {
aiMatrix3x3 mScale;
mScale.a1 = mScaling.x;
mScale.b2 = mScaling.y;
mOut = mScale;
}
if (mRotation)
{
if (mRotation) {
aiMatrix3x3 mRot;
mRot.a1 = mRot.b2 = std::cos(mRotation);
mRot.a2 = mRot.b1 = std::sin(mRotation);
mRot.a2 = -mRot.a2;
mOut *= mRot;
}
if (mTranslation.x || mTranslation.y)
{
if (mTranslation.x || mTranslation.y) {
aiMatrix3x3 mTrans;
mTrans.a3 = mTranslation.x;
mTrans.b3 = mTranslation.y;
@ -188,16 +160,18 @@ struct STransformVecInfo : public aiUVTransform {
}
};
// ---------------------------------------------------------------------------
/** Helper step to compute final UV coordinate sets if there are scalings
/**
* @brief Helper step to compute final UV coordinate sets if there are scalings
* or rotations in the original data read from the file.
*/
class TextureTransformStep : public BaseProcess {
*/
class TextureTransformStep final : public BaseProcess {
public:
// -------------------------------------------------------------------
/// The default class constructor / destructor.
TextureTransformStep();
/// The default class constructor. /
TextureTransformStep() = default;
/// The default class destructor.
~TextureTransformStep() override = default;
// -------------------------------------------------------------------
@ -211,16 +185,17 @@ public:
protected:
// -------------------------------------------------------------------
/** Preprocess a specific UV transformation setup
/**
* @brief Preprocess a specific UV transformation setup
*
* @param info Transformation setup to be preprocessed.
*/
*/
void PreProcessUVTransform(STransformVecInfo& info);
private:
unsigned int configFlags;
};
} // namespace Assimp
#endif //! AI_TEXTURE_TRANSFORM_H_INCLUDED

View file

@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -62,6 +62,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "PostProcessing/TriangulateProcess.h"
#include "PostProcessing/ProcessHelper.h"
#include "Common/PolyTools.h"
#include "contrib/earcut-hpp/earcut.hpp"
#include <memory>
#include <cstdint>
@ -74,6 +75,23 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define POLY_GRID_XPAD 20
#define POLY_OUTPUT_FILE "assimp_polygons_debug.txt"
namespace mapbox::util {
template <>
struct nth<0, aiVector2D> {
inline static auto get(const aiVector2D& t) {
return t.x;
}
};
template <>
struct nth<1, aiVector2D> {
inline static auto get(const aiVector2D& t) {
return t.y;
}
};
} // namespace mapbox::util
using namespace Assimp;
namespace {
@ -216,7 +234,7 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh) {
++numOut;
} else {
numOut += face.mNumIndices-2;
max_out = std::max(max_out,face.mNumIndices);
max_out = std::max<uint32_t>(max_out,face.mNumIndices);
}
}
@ -225,7 +243,7 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh) {
ASSIMP_LOG_ERROR( "Invalidation detected in the number of indices: does not fit to the primitive type." );
return false;
}
aiVector3D *nor_out = nullptr;
// if we don't have normals yet, but expect them to be a cheap side
@ -244,7 +262,9 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh) {
aiFace* out = new aiFace[numOut](), *curOut = out;
std::vector<aiVector3D> temp_verts3d(max_out+2); /* temporary storage for vertices */
std::vector<aiVector2D> temp_verts(max_out+2);
std::vector<std::vector<aiVector2D>> temp_poly(1); /* temporary storage for earcut.hpp */
std::vector<aiVector2D>& temp_verts = temp_poly[0];
temp_verts.reserve(max_out + 2);
NGONEncoder ngonEncoder;
@ -264,13 +284,11 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh) {
const aiVector3D* verts = pMesh->mVertices;
// use std::unique_ptr to avoid slow std::vector<bool> specialiations
std::unique_ptr<bool[]> done(new bool[max_out]);
for( unsigned int a = 0; a < pMesh->mNumFaces; a++) {
aiFace& face = pMesh->mFaces[a];
unsigned int* idx = face.mIndices;
int num = (int)face.mNumIndices, ear = 0, tmp, prev = num-1, next = 0, max = num;
unsigned int num = face.mNumIndices;
// Apply vertex colors to represent the face winding?
#ifdef AI_BUILD_TRIANGULATE_COLOR_FACE_WINDING
@ -363,16 +381,16 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh) {
// We project it onto a plane to get a 2d triangle.
// Collect all vertices of of the polygon.
for (tmp = 0; tmp < max; ++tmp) {
for (unsigned int tmp = 0; tmp < num; ++tmp) {
temp_verts3d[tmp] = verts[idx[tmp]];
}
// Get newell normal of the polygon. Store it for future use if it's a polygon-only mesh
aiVector3D n;
NewellNormal<3,3,3>(n,max,&temp_verts3d.front().x,&temp_verts3d.front().y,&temp_verts3d.front().z);
NewellNormal<3, 3, 3>(n, num, &temp_verts3d.front().x, &temp_verts3d.front().y, &temp_verts3d.front().z);
if (nor_out) {
for (tmp = 0; tmp < max; ++tmp)
nor_out[idx[tmp]] = n;
for (unsigned int tmp = 0; tmp < num; ++tmp)
nor_out[idx[tmp]] = n;
}
// Select largest normal coordinate to ignore for projection
@ -398,10 +416,20 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh) {
std::swap(ac,bc);
}
for (tmp =0; tmp < max; ++tmp) {
temp_verts.resize(num);
for (unsigned int tmp = 0; tmp < num; ++tmp) {
temp_verts[tmp].x = verts[idx[tmp]][ac];
temp_verts[tmp].y = verts[idx[tmp]][bc];
done[tmp] = false;
}
auto indices = mapbox::earcut(temp_poly);
for (size_t i = 0; i < indices.size(); i += 3) {
aiFace& nface = *curOut++;
nface.mIndices = new unsigned int[3];
nface.mNumIndices = 3;
nface.mIndices[0] = indices[i];
nface.mIndices[1] = indices[i + 1];
nface.mIndices[2] = indices[i + 2];
}
#ifdef AI_BUILD_TRIANGULATE_DEBUG_POLYS
@ -431,120 +459,6 @@ bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh) {
fprintf(fout,"\ntriangulation sequence: ");
#endif
//
// FIXME: currently this is the slow O(kn) variant with a worst case
// complexity of O(n^2) (I think). Can be done in O(n).
while (num > 3) {
// Find the next ear of the polygon
int num_found = 0;
for (ear = next;;prev = ear,ear = next) {
// break after we looped two times without a positive match
for (next=ear+1;done[(next>=max?next=0:next)];++next);
if (next < ear) {
if (++num_found == 2) {
break;
}
}
const aiVector2D* pnt1 = &temp_verts[ear],
*pnt0 = &temp_verts[prev],
*pnt2 = &temp_verts[next];
// Must be a convex point. Assuming ccw winding, it must be on the right of the line between p-1 and p+1.
if (OnLeftSideOfLine2D(*pnt0,*pnt2,*pnt1) == 1) {
continue;
}
// Skip when three point is in a line
aiVector2D left = *pnt0 - *pnt1;
aiVector2D right = *pnt2 - *pnt1;
left.Normalize();
right.Normalize();
auto mul = left * right;
// if the angle is 0 or 180
if (std::abs(mul - 1.f) < ai_epsilon || std::abs(mul + 1.f) < ai_epsilon) {
// skip this ear
ASSIMP_LOG_WARN("Skip a ear, due to its angle is near 0 or 180.");
continue;
}
// and no other point may be contained in this triangle
for ( tmp = 0; tmp < max; ++tmp) {
// We need to compare the actual values because it's possible that multiple indexes in
// the polygon are referring to the same position. concave_polygon.obj is a sample
//
// FIXME: Use 'epsiloned' comparisons instead? Due to numeric inaccuracies in
// PointInTriangle() I'm guessing that it's actually possible to construct
// input data that would cause us to end up with no ears. The problem is,
// which epsilon? If we chose a too large value, we'd get wrong results
const aiVector2D& vtmp = temp_verts[tmp];
if ( vtmp != *pnt1 && vtmp != *pnt2 && vtmp != *pnt0 && PointInTriangle2D(*pnt0,*pnt1,*pnt2,vtmp)) {
break;
}
}
if (tmp != max) {
continue;
}
// this vertex is an ear
break;
}
if (num_found == 2) {
// Due to the 'two ear theorem', every simple polygon with more than three points must
// have 2 'ears'. Here's definitely something wrong ... but we don't give up yet.
//
// Instead we're continuing with the standard tri-fanning algorithm which we'd
// use if we had only convex polygons. That's life.
ASSIMP_LOG_ERROR("Failed to triangulate polygon (no ear found). Probably not a simple polygon?");
#ifdef AI_BUILD_TRIANGULATE_DEBUG_POLYS
fprintf(fout,"critical error here, no ear found! ");
#endif
num = 0;
break;
}
aiFace& nface = *curOut++;
nface.mNumIndices = 3;
if (!nface.mIndices) {
nface.mIndices = new unsigned int[3];
}
// setup indices for the new triangle ...
nface.mIndices[0] = prev;
nface.mIndices[1] = ear;
nface.mIndices[2] = next;
// exclude the ear from most further processing
done[ear] = true;
--num;
}
if (num > 0) {
// We have three indices forming the last 'ear' remaining. Collect them.
aiFace& nface = *curOut++;
nface.mNumIndices = 3;
if (!nface.mIndices) {
nface.mIndices = new unsigned int[3];
}
for (tmp = 0; done[tmp]; ++tmp);
nface.mIndices[0] = tmp;
for (++tmp; done[tmp]; ++tmp);
nface.mIndices[1] = tmp;
for (++tmp; done[tmp]; ++tmp);
nface.mIndices[2] = tmp;
}
}
#ifdef AI_BUILD_TRIANGULATE_DEBUG_POLYS

View file

@ -2,8 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.

View file

@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -134,7 +134,7 @@ inline void ValidateDSProcess::DoValidationEx(T **parray, unsigned int size,
if (size == 0) {
return;
}
if (!parray) {
ReportError("aiScene::%s is nullptr (aiScene::%s is %i)",
firstName, secondName, size);

View file

@ -2,8 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -63,7 +62,7 @@ struct aiString;
struct aiCamera;
struct aiLight;
namespace Assimp {
namespace Assimp {
// --------------------------------------------------------------------------------------
/** Validates the whole ASSIMP scene data structure for correctness.