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

@ -3,7 +3,7 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2024, assimp team
Copyright (c) 2006-2026, assimp team
All rights reserved.
@ -77,18 +77,26 @@ static constexpr aiImporterDesc desc = {
"dae xml zae"
};
static const float kMillisecondsFromSeconds = 1000.f;
static constexpr float kMillisecondsFromSeconds = 1000.f;
// Add an item of metadata to a node
// Assumes the key is not already in the list
template <typename T>
inline void AddNodeMetaData(aiNode *node, const std::string &key, const T &value) {
void AddNodeMetaData(aiNode *node, const std::string &key, const T &value) {
if (nullptr == node->mMetaData) {
node->mMetaData = new aiMetadata();
}
node->mMetaData->Add(key, value);
}
// ------------------------------------------------------------------------------------------------
// Reads a float value from an accessor and its data array.
static ai_real ReadFloat(const Accessor &pAccessor, const Data &pData, size_t pIndex, size_t pOffset) {
const size_t pos = pAccessor.mStride * pIndex + pAccessor.mOffset + pOffset;
ai_assert(pos < pData.mValues.size());
return pData.mValues[pos];
}
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
ColladaLoader::ColladaLoader() :
@ -152,7 +160,7 @@ void ColladaLoader::InternReadFile(const std::string &pFile, aiScene *pScene, IO
throw DeadlyImportError("Collada: File came out empty. Something is wrong here.");
}
// reserve some storage to avoid unnecessary reallocs
// reserve some storage to avoid unnecessary reallocates
newMats.reserve(parser.mMaterialLibrary.size() * 2u);
mMeshes.reserve(parser.mMeshLibrary.size() * 2u);
@ -176,7 +184,7 @@ void ColladaLoader::InternReadFile(const std::string &pFile, aiScene *pScene, IO
0, 0, parser.mUnitSize, 0,
0, 0, 0, 1);
}
if (!ignoreUpDirection) {
// Convert to Y_UP, if different orientation
if (parser.mUpDirection == ColladaParser::UP_X) {
@ -224,7 +232,7 @@ void ColladaLoader::InternReadFile(const std::string &pFile, aiScene *pScene, IO
// Recursively constructs a scene node for the given parser node and returns it.
aiNode *ColladaLoader::BuildHierarchy(const ColladaParser &pParser, const Collada::Node *pNode) {
// create a node for it
aiNode *node = new aiNode();
auto *node = new aiNode();
// find a name for the new node. It's more complicated than you might think
node->mName.Set(FindNameForNode(pNode));
@ -272,24 +280,24 @@ aiNode *ColladaLoader::BuildHierarchy(const ColladaParser &pParser, const Collad
// ------------------------------------------------------------------------------------------------
// Resolve node instances
void ColladaLoader::ResolveNodeInstances(const ColladaParser &pParser, const Node *pNode,
std::vector<const Node*> &resolved) {
std::vector<const Node*> &resolved) const {
// reserve enough storage
resolved.reserve(pNode->mNodeInstances.size());
// ... and iterate through all nodes to be instanced as children of pNode
for (const auto &nodeInst : pNode->mNodeInstances) {
for (const auto &[mNode] : pNode->mNodeInstances) {
// find the corresponding node in the library
const ColladaParser::NodeLibrary::const_iterator itt = pParser.mNodeLibrary.find(nodeInst.mNode);
const auto itt = pParser.mNodeLibrary.find(mNode);
const Node *nd = itt == pParser.mNodeLibrary.end() ? nullptr : (*itt).second;
// FIX for http://sourceforge.net/tracker/?func=detail&aid=3054873&group_id=226462&atid=1067632
// need to check for both name and ID to catch all. To avoid breaking valid files,
// the workaround is only enabled when the first attempt to resolve the node has failed.
if (nullptr == nd) {
nd = FindNode(pParser.mRootNode, nodeInst.mNode);
nd = FindNode(pParser.mRootNode, mNode);
}
if (nullptr == nd) {
ASSIMP_LOG_ERROR("Collada: Unable to resolve reference to instanced node ", nodeInst.mNode);
ASSIMP_LOG_ERROR("Collada: Unable to resolve reference to instanced node ", mNode);
} else {
// attach this node to the list of children
resolved.push_back(nd);
@ -299,8 +307,8 @@ void ColladaLoader::ResolveNodeInstances(const ColladaParser &pParser, const Nod
// ------------------------------------------------------------------------------------------------
// Resolve UV channels
void ColladaLoader::ApplyVertexToEffectSemanticMapping(Sampler &sampler, const SemanticMappingTable &table) {
SemanticMappingTable::InputSemanticMap::const_iterator it = table.mMap.find(sampler.mUVChannel);
static void ApplyVertexToEffectSemanticMapping(Sampler &sampler, const SemanticMappingTable &table) {
const auto it = table.mMap.find(sampler.mUVChannel);
if (it == table.mMap.end()) {
return;
}
@ -317,7 +325,7 @@ void ColladaLoader::ApplyVertexToEffectSemanticMapping(Sampler &sampler, const S
void ColladaLoader::BuildLightsForNode(const ColladaParser &pParser, const Node *pNode, aiNode *pTarget) {
for (const LightInstance &lid : pNode->mLights) {
// find the referred light
ColladaParser::LightLibrary::const_iterator srcLightIt = pParser.mLightLibrary.find(lid.mLight);
auto srcLightIt = pParser.mLightLibrary.find(lid.mLight);
if (srcLightIt == pParser.mLightLibrary.end()) {
ASSIMP_LOG_WARN("Collada: Unable to find light for ID \"", lid.mLight, "\". Skipping.");
continue;
@ -325,7 +333,7 @@ void ColladaLoader::BuildLightsForNode(const ColladaParser &pParser, const Node
const Collada::Light *srcLight = &srcLightIt->second;
// now fill our ai data structure
aiLight *out = new aiLight();
auto out = new aiLight();
out->mName = pTarget->mName;
out->mType = (aiLightSourceType)srcLight->mType;
@ -382,7 +390,7 @@ void ColladaLoader::BuildLightsForNode(const ColladaParser &pParser, const Node
void ColladaLoader::BuildCamerasForNode(const ColladaParser &pParser, const Node *pNode, aiNode *pTarget) {
for (const CameraInstance &cid : pNode->mCameras) {
// find the referred light
ColladaParser::CameraLibrary::const_iterator srcCameraIt = pParser.mCameraLibrary.find(cid.mCamera);
auto srcCameraIt = pParser.mCameraLibrary.find(cid.mCamera);
if (srcCameraIt == pParser.mCameraLibrary.end()) {
ASSIMP_LOG_WARN("Collada: Unable to find camera for ID \"", cid.mCamera, "\". Skipping.");
continue;
@ -395,7 +403,7 @@ void ColladaLoader::BuildCamerasForNode(const ColladaParser &pParser, const Node
}
// now fill our ai data structure
aiCamera *out = new aiCamera();
auto *out = new aiCamera();
out->mName = pTarget->mName;
// collada cameras point in -Z by default, rest is specified in node transform
@ -445,10 +453,10 @@ void ColladaLoader::BuildMeshesForNode(const ColladaParser &pParser, const Node
const Controller *srcController = nullptr;
// find the referred mesh
ColladaParser::MeshLibrary::const_iterator srcMeshIt = pParser.mMeshLibrary.find(mid.mMeshOrController);
auto srcMeshIt = pParser.mMeshLibrary.find(mid.mMeshOrController);
if (srcMeshIt == pParser.mMeshLibrary.end()) {
// if not found in the mesh-library, it might also be a controller referring to a mesh
ColladaParser::ControllerLibrary::const_iterator srcContrIt = pParser.mControllerLibrary.find(mid.mMeshOrController);
auto srcContrIt = pParser.mControllerLibrary.find(mid.mMeshOrController);
if (srcContrIt != pParser.mControllerLibrary.end()) {
srcController = &srcContrIt->second;
srcMeshIt = pParser.mMeshLibrary.find(srcController->mMeshId);
@ -462,7 +470,7 @@ void ColladaLoader::BuildMeshesForNode(const ColladaParser &pParser, const Node
continue;
}
} else {
// ID found in the mesh library -> direct reference to an unskinned mesh
// ID found in the mesh library -> direct reference to a not skinned mesh
srcMesh = srcMeshIt->second;
}
@ -476,7 +484,7 @@ void ColladaLoader::BuildMeshesForNode(const ColladaParser &pParser, const Node
// find material assigned to this submesh
std::string meshMaterial;
std::map<std::string, SemanticMappingTable>::const_iterator meshMatIt = mid.mMaterials.find(submesh.mMaterial);
auto meshMatIt = mid.mMaterials.find(submesh.mMaterial);
const Collada::SemanticMappingTable *table = nullptr;
if (meshMatIt != mid.mMaterials.end()) {
@ -492,30 +500,34 @@ void ColladaLoader::BuildMeshesForNode(const ColladaParser &pParser, const Node
// OK ... here the *real* fun starts ... we have the vertex-input-to-effect-semantic-table
// given. The only mapping stuff which we do actually support is the UV channel.
std::map<std::string, size_t>::const_iterator matIt = mMaterialIndexByName.find(meshMaterial);
auto matIt = mMaterialIndexByName.find(meshMaterial);
unsigned int matIdx = 0;
if (matIt != mMaterialIndexByName.end()) {
matIdx = static_cast<unsigned int>(matIt->second);
}
if (table && !table->mMap.empty()) {
std::pair<Collada::Effect *, aiMaterial *> &mat = newMats[matIdx];
if (matIdx < newMats.size()) {
std::pair<Collada::Effect *, aiMaterial *> &mat = newMats[matIdx];
// Iterate through all texture channels assigned to the effect and
// check whether we have mapping information for it.
ApplyVertexToEffectSemanticMapping(mat.first->mTexDiffuse, *table);
ApplyVertexToEffectSemanticMapping(mat.first->mTexAmbient, *table);
ApplyVertexToEffectSemanticMapping(mat.first->mTexSpecular, *table);
ApplyVertexToEffectSemanticMapping(mat.first->mTexEmissive, *table);
ApplyVertexToEffectSemanticMapping(mat.first->mTexTransparent, *table);
ApplyVertexToEffectSemanticMapping(mat.first->mTexBump, *table);
// Iterate through all texture channels assigned to the effect and
// check whether we have mapping information for it.
ApplyVertexToEffectSemanticMapping(mat.first->mTexDiffuse, *table);
ApplyVertexToEffectSemanticMapping(mat.first->mTexAmbient, *table);
ApplyVertexToEffectSemanticMapping(mat.first->mTexSpecular, *table);
ApplyVertexToEffectSemanticMapping(mat.first->mTexEmissive, *table);
ApplyVertexToEffectSemanticMapping(mat.first->mTexTransparent, *table);
ApplyVertexToEffectSemanticMapping(mat.first->mTexBump, *table);
} else {
ASSIMP_LOG_WARN("Collada: Ignoring material mapping for mesh \"", mid.mMeshOrController, "\". Material index ", matIdx, " is out of bounds (newMats.size()=", newMats.size(), ").");
}
}
// built lookup index of the Mesh-Submesh-Material combination
ColladaMeshIndex index(mid.mMeshOrController, sm, meshMaterial);
// if we already have the mesh at the library, just add its index to the node's array
std::map<ColladaMeshIndex, size_t>::const_iterator dstMeshIt = mMeshIndexByID.find(index);
auto dstMeshIt = mMeshIndexByID.find(index);
if (dstMeshIt != mMeshIndexByID.end()) {
newMeshRefs.push_back(dstMeshIt->second);
} else {
@ -530,7 +542,7 @@ void ColladaLoader::BuildMeshesForNode(const ColladaParser &pParser, const Node
faceStart += submesh.mNumFaces;
// assign the material index
std::map<std::string, size_t>::const_iterator subMatIt = mMaterialIndexByName.find(submesh.mMaterial);
auto subMatIt = mMaterialIndexByName.find(submesh.mMaterial);
if (subMatIt != mMaterialIndexByName.end()) {
dstMesh->mMaterialIndex = static_cast<unsigned int>(subMatIt->second);
} else {
@ -618,7 +630,7 @@ aiMesh *ColladaLoader::CreateMesh(const ColladaParser &pParser, const Mesh *pSrc
std::copy(pSrcMesh->mTangents.begin() + pStartVertex, pSrcMesh->mTangents.begin() + pStartVertex + numVertices, dstMesh->mTangents);
}
// bitangents, if given.
// bi-tangents, if given.
if (pSrcMesh->mBitangents.size() >= pStartVertex + numVertices) {
dstMesh->mBitangents = new aiVector3D[numVertices];
std::copy(pSrcMesh->mBitangents.begin() + pStartVertex, pSrcMesh->mBitangents.begin() + pStartVertex + numVertices, dstMesh->mBitangents);
@ -664,7 +676,7 @@ aiMesh *ColladaLoader::CreateMesh(const ColladaParser &pParser, const Mesh *pSrc
std::vector<float> targetWeights;
Collada::MorphMethod method = Normalized;
for (std::map<std::string, Controller>::const_iterator it = pParser.mControllerLibrary.begin();
for (auto it = pParser.mControllerLibrary.begin();
it != pParser.mControllerLibrary.end(); ++it) {
const Controller &c = it->second;
const Collada::Mesh *baseMesh = pParser.ResolveLibraryReference(pParser.mMeshLibrary, c.mMeshId);
@ -754,7 +766,7 @@ aiMesh *ColladaLoader::CreateMesh(const ColladaParser &pParser, const Mesh *pSrc
std::vector<IndexPairVector::const_iterator> weightStartPerVertex;
weightStartPerVertex.resize(pSrcController->mWeightCounts.size(), pSrcController->mWeights.end());
IndexPairVector::const_iterator pit = pSrcController->mWeights.begin();
auto pit = pSrcController->mWeights.begin();
for (size_t a = 0; a < pSrcController->mWeightCounts.size(); ++a) {
weightStartPerVertex[a] = pit;
pit += pSrcController->mWeightCounts[a];
@ -766,7 +778,7 @@ aiMesh *ColladaLoader::CreateMesh(const ColladaParser &pParser, const Mesh *pSrc
// the controller assigns the vertex weights
size_t orgIndex = pSrcMesh->mFacePosIndices[a];
// find the vertex weights for this vertex
IndexPairVector::const_iterator iit = weightStartPerVertex[orgIndex];
auto iit = weightStartPerVertex[orgIndex];
size_t pairCount = pSrcController->mWeightCounts[orgIndex];
for (size_t b = 0; b < pairCount; ++b, ++iit) {
@ -807,7 +819,7 @@ aiMesh *ColladaLoader::CreateMesh(const ColladaParser &pParser, const Mesh *pSrc
}
// create bone with its weights
aiBone *bone = new aiBone;
auto bone = new aiBone;
bone->mName = ReadString(jointNamesAcc, jointNames, a);
bone->mOffsetMatrix.a1 = ReadFloat(jointMatrixAcc, jointMatrices, a, 0);
bone->mOffsetMatrix.a2 = ReadFloat(jointMatrixAcc, jointMatrices, a, 1);
@ -973,7 +985,7 @@ void ColladaLoader::StoreAnimations(aiScene *pScene, const ColladaParser &pParse
// if there are other animations which fit the template anim, combine all channels into a single anim
if (!collectedAnimIndices.empty()) {
aiAnimation *combinedAnim = new aiAnimation();
auto *combinedAnim = new aiAnimation();
combinedAnim->mName = aiString(std::string("combinedAnim_") + char('0' + a));
combinedAnim->mDuration = templateAnim->mDuration;
combinedAnim->mTicksPerSecond = templateAnim->mTicksPerSecond;
@ -1040,7 +1052,7 @@ struct MorphTimeValues {
};
void insertMorphTimeValue(std::vector<MorphTimeValues> &values, float time, float weight, unsigned int value) {
MorphTimeValues::key k;
MorphTimeValues::key k{};
k.mValue = value;
k.mWeight = weight;
if (values.empty() || time < values[0].mTime) {
@ -1077,6 +1089,7 @@ static float getWeightAtKey(const std::vector<MorphTimeValues> &values, int key,
return mKey.mWeight;
}
}
// no value at key found, try to interpolate if present at other keys. if not, return zero
// TODO: interpolation
return 0.0f;
@ -1105,7 +1118,7 @@ void ColladaLoader::CreateAnimation(aiScene *pScene, const ColladaParser &pParse
// now check all channels if they affect the current node
std::string targetID, subElement;
for (std::vector<AnimationChannel>::const_iterator cit = pSrcAnim->mChannels.begin();
for (auto cit = pSrcAnim->mChannels.begin();
cit != pSrcAnim->mChannels.end(); ++cit) {
const AnimationChannel &srcChannel = *cit;
ChannelEntry entry;
@ -1348,7 +1361,7 @@ void ColladaLoader::CreateAnimation(aiScene *pScene, const ColladaParser &pParse
// build an animation channel for the given node out of these trafo keys
if (!resultTrafos.empty()) {
aiNodeAnim *dstAnim = new aiNodeAnim;
auto *dstAnim = new aiNodeAnim;
dstAnim->mNodeName = nodeName;
dstAnim->mNumPositionKeys = static_cast<unsigned int>(resultTrafos.size());
dstAnim->mNumRotationKeys = static_cast<unsigned int>(resultTrafos.size());
@ -1390,7 +1403,7 @@ void ColladaLoader::CreateAnimation(aiScene *pScene, const ColladaParser &pParse
// or 2) one channel with morph target count arrays
// assume first
aiMeshMorphAnim *morphAnim = new aiMeshMorphAnim;
auto *morphAnim = new aiMeshMorphAnim;
morphAnim->mName.Set(nodeName);
std::vector<MorphTimeValues> morphTimeValues;
@ -1433,7 +1446,7 @@ void ColladaLoader::CreateAnimation(aiScene *pScene, const ColladaParser &pParse
}
if (!anims.empty() || !morphAnims.empty()) {
aiAnimation *anim = new aiAnimation;
auto anim = new aiAnimation;
anim->mName.Set(pName);
anim->mNumChannels = static_cast<unsigned int>(anims.size());
if (anim->mNumChannels > 0) {
@ -1513,7 +1526,7 @@ void ColladaLoader::AddTexture(aiMaterial &mat,
map = sampler.mUVId;
} else {
map = -1;
for (std::string::const_iterator it = sampler.mUVChannel.begin(); it != sampler.mUVChannel.end(); ++it) {
for (auto it = sampler.mUVChannel.begin(); it != sampler.mUVChannel.end(); ++it) {
if (IsNumeric(*it)) {
map = strtoul10(&(*it));
break;
@ -1531,7 +1544,7 @@ void ColladaLoader::AddTexture(aiMaterial &mat,
// Fills materials from the collada material definitions
void ColladaLoader::FillMaterials(const ColladaParser &pParser, aiScene * /*pScene*/) {
for (auto &elem : newMats) {
aiMaterial &mat = (aiMaterial &)*elem.second;
auto &mat = (aiMaterial &)*elem.second;
Collada::Effect &effect = *elem.first;
// resolve shading mode
@ -1641,17 +1654,17 @@ void ColladaLoader::FillMaterials(const ColladaParser &pParser, aiScene * /*pSce
void ColladaLoader::BuildMaterials(ColladaParser &pParser, aiScene * /*pScene*/) {
newMats.reserve(pParser.mMaterialLibrary.size());
for (ColladaParser::MaterialLibrary::const_iterator matIt = pParser.mMaterialLibrary.begin();
for (auto matIt = pParser.mMaterialLibrary.begin();
matIt != pParser.mMaterialLibrary.end(); ++matIt) {
const Material &material = matIt->second;
// a material is only a reference to an effect
ColladaParser::EffectLibrary::iterator effIt = pParser.mEffectLibrary.find(material.mEffect);
auto effIt = pParser.mEffectLibrary.find(material.mEffect);
if (effIt == pParser.mEffectLibrary.end())
continue;
Effect &effect = effIt->second;
// create material
aiMaterial *mat = new aiMaterial;
auto *mat = new aiMaterial;
aiString name(material.mName.empty() ? matIt->first : material.mName);
mat->AddProperty(&name, AI_MATKEY_NAME);
@ -1674,7 +1687,7 @@ aiString ColladaLoader::FindFilenameForEffectTexture(const ColladaParser &pParse
std::string name = pName;
while (true) {
// the given string is a param entry. Find it
Effect::ParamLibrary::const_iterator it = pEffect.mParams.find(name);
auto it = pEffect.mParams.find(name);
// if not found, we're at the end of the recursion. The resulting string should be the image ID
if (it == pEffect.mParams.end())
break;
@ -1684,7 +1697,7 @@ aiString ColladaLoader::FindFilenameForEffectTexture(const ColladaParser &pParse
}
// find the image referred by this name in the image library of the scene
ColladaParser::ImageLibrary::const_iterator imIt = pParser.mImageLibrary.find(name);
auto imIt = pParser.mImageLibrary.find(name);
if (imIt == pParser.mImageLibrary.end()) {
ASSIMP_LOG_WARN("Collada: Unable to resolve effect texture entry \"", pName, "\", ended up at ID \"", name, "\".");
@ -1696,7 +1709,7 @@ aiString ColladaLoader::FindFilenameForEffectTexture(const ColladaParser &pParse
// if this is an embedded texture image setup an aiTexture for it
if (!imIt->second.mImageData.empty()) {
aiTexture *tex = new aiTexture();
auto *tex = new aiTexture();
// Store embedded texture name reference
tex->mFilename.Set(imIt->second.mFileName.c_str());
@ -1728,14 +1741,6 @@ aiString ColladaLoader::FindFilenameForEffectTexture(const ColladaParser &pParse
return result;
}
// ------------------------------------------------------------------------------------------------
// Reads a float value from an accessor and its data array.
ai_real ColladaLoader::ReadFloat(const Accessor &pAccessor, const Data &pData, size_t pIndex, size_t pOffset) const {
size_t pos = pAccessor.mStride * pIndex + pAccessor.mOffset + pOffset;
ai_assert(pos < pData.mValues.size());
return pData.mValues[pos];
}
// ------------------------------------------------------------------------------------------------
// Reads a string value from an accessor and its data array.
const std::string &ColladaLoader::ReadString(const Accessor &pAccessor, const Data &pData, size_t pIndex) const {
@ -1818,4 +1823,4 @@ std::string ColladaLoader::FindNameForNode(const Node *pNode) {
} // Namespace Assimp
#endif // !! ASSIMP_BUILD_NO_DAE_IMPORTER
#endif // !! ASSIMP_BUILD_NO_COLLADA_IMPORTER