From 0d672efa905412ecc5beda33dad2124bd8890480 Mon Sep 17 00:00:00 2001 From: Max Vollmer Date: Wed, 29 Jan 2020 15:04:26 +0000 Subject: [PATCH 01/10] Check input token length before copy --- code/FBX/FBXParser.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/code/FBX/FBXParser.cpp b/code/FBX/FBXParser.cpp index 215ff7484..5486fdcc6 100644 --- a/code/FBX/FBXParser.cpp +++ b/code/FBX/FBXParser.cpp @@ -367,9 +367,12 @@ float ParseTokenAsFloat(const Token& t, const char*& err_out) // first - next in the fbx token stream comes ',', // which fast_atof could interpret as decimal point. #define MAX_FLOAT_LENGTH 31 - char temp[MAX_FLOAT_LENGTH + 1]; const size_t length = static_cast(t.end()-t.begin()); - std::copy(t.begin(),t.end(),temp); + if (length > MAX_FLOAT_LENGTH) + return 0.f; + + char temp[MAX_FLOAT_LENGTH + 1]; + std::copy(t.begin(), t.end(), temp); temp[std::min(static_cast(MAX_FLOAT_LENGTH),length)] = '\0'; return fast_atof(temp); From 398a8f757e401bfac5569940e56f82659c7f9e74 Mon Sep 17 00:00:00 2001 From: bzt Date: Wed, 29 Jan 2020 22:08:34 +0100 Subject: [PATCH 02/10] Additional checks on invalid input --- code/M3D/M3DImporter.cpp | 46 +++++++++++++++++++++++++++------------- 1 file changed, 31 insertions(+), 15 deletions(-) diff --git a/code/M3D/M3DImporter.cpp b/code/M3D/M3DImporter.cpp index a77e75a27..b0759542b 100644 --- a/code/M3D/M3DImporter.cpp +++ b/code/M3D/M3DImporter.cpp @@ -225,7 +225,7 @@ void M3DImporter::InternReadFile(const std::string &file, aiScene *pScene, IOSys // ------------------------------------------------------------------------------------------------ // convert materials. properties are converted using a static table in M3DMaterials.h -void M3DImporter::importMaterials(const M3DWrapper &m3d_wrap) { +void M3DImporter::importMaterials(const M3DWrapper &m3d) { unsigned int i, j, k, l, n; m3dm_t *m; aiString name = aiString(AI_DEFAULT_MATERIAL_NAME); @@ -233,9 +233,9 @@ void M3DImporter::importMaterials(const M3DWrapper &m3d_wrap) { ai_real f; ai_assert(mScene != nullptr); - ai_assert(m3d_wrap); + ai_assert(m3d); - mScene->mNumMaterials = m3d_wrap->nummaterial + 1; + mScene->mNumMaterials = m3d->nummaterial + 1; mScene->mMaterials = new aiMaterial *[mScene->mNumMaterials]; ASSIMP_LOG_DEBUG_F("M3D: importMaterials ", mScene->mNumMaterials); @@ -248,8 +248,11 @@ void M3DImporter::importMaterials(const M3DWrapper &m3d_wrap) { mat->AddProperty(&c, 1, AI_MATKEY_COLOR_DIFFUSE); mScene->mMaterials[0] = mat; - for (i = 0; i < m3d_wrap->nummaterial; i++) { - m = &m3d_wrap->material[i]; + if (!m3d->nummaterial || !m3d->material) + return; + + for (i = 0; i < m3d->nummaterial; i++) { + m = &m3d->material[i]; aiMaterial *mat = new aiMaterial; name.Set(std::string(m->name)); mat->AddProperty(&name, AI_MATKEY_NAME); @@ -294,9 +297,9 @@ void M3DImporter::importMaterials(const M3DWrapper &m3d_wrap) { // texture map properties if (m->prop[j].type >= 128 && aiTxProps[k].pKey && // extra check, should never happen, do we have the refered texture? - m->prop[j].value.textureid < m3d_wrap->numtexture && - m3d_wrap->texture[m->prop[j].value.textureid].name) { - name.Set(std::string(std::string(m3d_wrap->texture[m->prop[j].value.textureid].name) + ".png")); + m->prop[j].value.textureid < m3d->numtexture && + m3d->texture[m->prop[j].value.textureid].name) { + name.Set(std::string(std::string(m3d->texture[m->prop[j].value.textureid].name) + ".png")); mat->AddProperty(&name, aiTxProps[k].pKey, aiTxProps[k].type, aiTxProps[k].index); n = 0; mat->AddProperty(&n, 1, _AI_MATKEY_UVWSRC_BASE, aiProps[k].type, aiProps[k].index); @@ -319,7 +322,7 @@ void M3DImporter::importTextures(const M3DWrapper &m3d) { mScene->mNumTextures = m3d->numtexture; ASSIMP_LOG_DEBUG_F("M3D: importTextures ", mScene->mNumTextures); - if (!m3d->numtexture) + if (!m3d->numtexture || !m3d->texture) return; mScene->mTextures = new aiTexture *[m3d->numtexture]; @@ -387,6 +390,9 @@ void M3DImporter::importMeshes(const M3DWrapper &m3d) { ASSIMP_LOG_DEBUG_F("M3D: importMeshes ", m3d->numface); + if (!m3d->numface || !m3d->face || !m3d->numvertex || !m3d->vertex) + return; + for (i = 0; i < m3d->numface; i++) { // we must switch mesh if material changes if (lastMat != m3d->face[i].materialid) { @@ -420,6 +426,7 @@ void M3DImporter::importMeshes(const M3DWrapper &m3d) { k = static_cast(vertices->size()); pFace->mIndices[j] = k; l = m3d->face[i].vertex[j]; + if(l >= m3d->numvertex) continue; pos.x = m3d->vertex[l].x; pos.y = m3d->vertex[l].y; pos.z = m3d->vertex[l].z; @@ -432,14 +439,14 @@ void M3DImporter::importMeshes(const M3DWrapper &m3d) { vertexids->push_back(l); } l = m3d->face[i].texcoord[j]; - if (l != M3D_UNDEF) { + if (l != M3D_UNDEF && l < m3d->numtmap) { uv.x = m3d->tmap[l].u; uv.y = m3d->tmap[l].v; uv.z = 0.0; texcoords->push_back(uv); } l = m3d->face[i].normal[j]; - if (l != M3D_UNDEF) { + if (l != M3D_UNDEF && l < m3d->numvertex) { norm.x = m3d->vertex[l].x; norm.y = m3d->vertex[l].y; norm.z = m3d->vertex[l].z; @@ -487,6 +494,9 @@ void M3DImporter::importBones(const M3DWrapper &m3d, unsigned int parentid, aiNo ASSIMP_LOG_DEBUG_F("M3D: importBones ", m3d->numbone, " parentid ", (int)parentid); + if (!m3d->numbone || !m3d->bone) + return; + for (n = 0, i = parentid + 1; i < m3d->numbone; i++) if (m3d->bone[i].parent == parentid) n++; pParent->mChildren = new aiNode *[n]; @@ -521,7 +531,7 @@ void M3DImporter::importAnimations(const M3DWrapper &m3d) { ASSIMP_LOG_DEBUG_F("M3D: importAnimations ", mScene->mNumAnimations); - if (!m3d->numaction || !m3d->numbone) + if (!m3d->numaction || !m3d->action || !m3d->numbone || !m3d->bone || !m3d->vertex) return; mScene->mAnimations = new aiAnimation *[m3d->numaction]; @@ -552,6 +562,7 @@ void M3DImporter::importAnimations(const M3DWrapper &m3d) { ori = a->frame[j].transform[k].ori; } } + if(pos >= m3d->numvertex || ori >= m3d->numvertex) continue; m3dv_t *v = &m3d->vertex[pos]; m3dv_t *q = &m3d->vertex[ori]; pAnim->mChannels[l]->mPositionKeys[j].mTime = t; @@ -587,6 +598,8 @@ void M3DImporter::convertPose(const M3DWrapper &m3d, aiMatrix4x4 *m, unsigned in ai_assert(m3d); ai_assert(posid != M3D_UNDEF && posid < m3d->numvertex); ai_assert(orientid != M3D_UNDEF && orientid < m3d->numvertex); + if (!m3d->numvertex || !m3d->vertex) + return; m3dv_t *p = &m3d->vertex[posid]; m3dv_t *q = &m3d->vertex[orientid]; @@ -701,7 +714,7 @@ void M3DImporter::populateMesh(const M3DWrapper &m3d, aiMesh *pMesh, std::vector // vertex but assimp uses lists of local vertex id/weight pairs per local bone list pMesh->mNumBones = m3d->numbone; /* we need aiBone with mOffsetMatrix for bones without weights as well */ - if (pMesh->mNumBones) { + if (pMesh->mNumBones && m3d->numbone && m3d->bone) { pMesh->mBones = new aiBone *[pMesh->mNumBones]; for (unsigned int i = 0; i < m3d->numbone; i++) { aiNode *pNode; @@ -715,10 +728,11 @@ void M3DImporter::populateMesh(const M3DWrapper &m3d, aiMesh *pMesh, std::vector } else pMesh->mBones[i]->mOffsetMatrix = aiMatrix4x4(); } - if (vertexids->size()) { + if (vertexids->size() && m3d->numvertex && m3d->vertex && m3d->numskin && m3d->skin) { unsigned int i, j; // first count how many vertices we have per bone for (i = 0; i < vertexids->size(); i++) { + if(vertexids->at(i) >= m3d->numvertex) continue; unsigned int s = m3d->vertex[vertexids->at(i)].skinid; if (s != M3D_UNDEF && s != M3D_INDEXMAX) { for (unsigned int k = 0; k < M3D_NUMBONE && m3d->skin[s].weight[k] > 0.0; k++) { @@ -742,9 +756,11 @@ void M3DImporter::populateMesh(const M3DWrapper &m3d, aiMesh *pMesh, std::vector } // fill up with data for (i = 0; i < vertexids->size(); i++) { + if(vertexids->at(i) >= m3d->numvertex) continue; unsigned int s = m3d->vertex[vertexids->at(i)].skinid; - if (s != M3D_UNDEF && s != M3D_INDEXMAX) { + if (s != M3D_UNDEF && s != M3D_INDEXMAX && s < m3d->numskin) { for (unsigned int k = 0; k < M3D_NUMBONE && m3d->skin[s].weight[k] > 0.0; k++) { + if(m3d->skin[s].boneid[k] >= m3d->numbone) continue; aiString name = aiString(std::string(m3d->bone[m3d->skin[s].boneid[k]].name)); for (j = 0; j < pMesh->mNumBones; j++) { if (pMesh->mBones[j]->mName == name) { From 605336832ff0aa6fc8a2b9cde1e1a944dc9e9dc3 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Thu, 30 Jan 2020 09:47:39 +0100 Subject: [PATCH 03/10] Update M3DImporter.cpp Add missing brackets --- code/M3D/M3DImporter.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/code/M3D/M3DImporter.cpp b/code/M3D/M3DImporter.cpp index 4373672a4..1a5d1866d 100644 --- a/code/M3D/M3DImporter.cpp +++ b/code/M3D/M3DImporter.cpp @@ -248,8 +248,9 @@ void M3DImporter::importMaterials(const M3DWrapper &m3d) { mat->AddProperty(&c, 1, AI_MATKEY_COLOR_DIFFUSE); mScene->mMaterials[0] = mat; - if (!m3d->nummaterial || !m3d->material) + if (!m3d->nummaterial || !m3d->material) { return; + } for (i = 0; i < m3d->nummaterial; i++) { m = &m3d->material[i]; From a2ef0b5bd5e2695d65f29f46cad84eecec1800e1 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Thu, 30 Jan 2020 10:00:43 +0100 Subject: [PATCH 04/10] Update M3DImporter.cpp Fix some review finding: - Add missing brackets to make code more readable - fix scope of variables --- code/M3D/M3DImporter.cpp | 135 ++++++++++++++++++++++----------------- 1 file changed, 75 insertions(+), 60 deletions(-) diff --git a/code/M3D/M3DImporter.cpp b/code/M3D/M3DImporter.cpp index 1a5d1866d..20b9b9e44 100644 --- a/code/M3D/M3DImporter.cpp +++ b/code/M3D/M3DImporter.cpp @@ -109,7 +109,9 @@ using namespace std; // ------------------------------------------------------------------------------------------------ // Default constructor M3DImporter::M3DImporter() : - mScene(nullptr) {} + mScene(nullptr) { + // empty +} // ------------------------------------------------------------------------------------------------ // Returns true, if file is a binary or ASCII Model 3D file. @@ -126,14 +128,8 @@ bool M3DImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool c if (!pIOHandler) { return true; } - /* - * don't use CheckMagicToken because that checks with swapped bytes too, leading to false - * positives. This magic is not uint32_t, but char[4], so memcmp is the best way - const char* tokens[] = {"3DMO", "3dmo"}; - return CheckMagicToken(pIOHandler,pFile,tokens,2,0,4); - */ - std::unique_ptr pStream(pIOHandler->Open(pFile, "rb")); + std::unique_ptr pStream(pIOHandler->Open(pFile, "rb")); unsigned char data[4]; if (4 != pStream->Read(data, 1, 4)) { return false; @@ -144,7 +140,8 @@ bool M3DImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool c #endif ; } - return false; + + return false; } // ------------------------------------------------------------------------------------------------ @@ -257,43 +254,46 @@ void M3DImporter::importMaterials(const M3DWrapper &m3d) { aiMaterial *mat = new aiMaterial; name.Set(std::string(m->name)); mat->AddProperty(&name, AI_MATKEY_NAME); - for (j = 0; j < m->numprop; j++) { + for (j = 0; j < m->numprop; ++j) { // look up property type // 0 - 127 scalar values, // 128 - 255 the same properties but for texture maps k = 256; - for (l = 0; l < sizeof(m3d_propertytypes) / sizeof(m3d_propertytypes[0]); l++) + for (l = 0; l < sizeof(m3d_propertytypes) / sizeof(m3d_propertytypes[0]); ++l) { if (m->prop[j].type == m3d_propertytypes[l].id || m->prop[j].type == m3d_propertytypes[l].id + 128) { k = l; break; } - // should never happen, but be safe than sorry - if (k == 256) continue; + // should never happen, but be safe than sorry + if (k == 256) { + continue; + } - // scalar properties - if (m->prop[j].type < 128 && aiProps[k].pKey) { - switch (m3d_propertytypes[k].format) { - case m3dpf_color: - c = mkColor(m->prop[j].value.color); - mat->AddProperty(&c, 1, aiProps[k].pKey, aiProps[k].type, aiProps[k].index); - break; - case m3dpf_float: - f = m->prop[j].value.fnum; - mat->AddProperty(&f, 1, aiProps[k].pKey, aiProps[k].type, aiProps[k].index); - break; - default: - n = m->prop[j].value.num; - if (m->prop[j].type == m3dp_il) { - switch (n) { - case 0: n = aiShadingMode_NoShading; break; - case 2: n = aiShadingMode_Phong; break; - default: n = aiShadingMode_Gouraud; break; - } - } - mat->AddProperty(&n, 1, aiProps[k].pKey, aiProps[k].type, aiProps[k].index); - break; - } + // scalar properties + if (m->prop[j].type < 128 && aiProps[k].pKey) { + switch (m3d_propertytypes[k].format) { + case m3dpf_color: + c = mkColor(m->prop[j].value.color); + mat->AddProperty(&c, 1, aiProps[k].pKey, aiProps[k].type, aiProps[k].index); + break; + case m3dpf_float: + f = m->prop[j].value.fnum; + mat->AddProperty(&f, 1, aiProps[k].pKey, aiProps[k].type, aiProps[k].index); + break; + default: + n = m->prop[j].value.num; + if (m->prop[j].type == m3dp_il) { + switch (n) { + case 0: n = aiShadingMode_NoShading; break; + case 2: n = aiShadingMode_Phong; break; + default: n = aiShadingMode_Gouraud; break; + } + } + mat->AddProperty(&n, 1, aiProps[k].pKey, aiProps[k].type, aiProps[k].index); + break; + } + } } // texture map properties if (m->prop[j].type >= 128 && aiTxProps[k].pKey && @@ -314,7 +314,11 @@ void M3DImporter::importMaterials(const M3DWrapper &m3d) { // import textures, this is the simplest of all void M3DImporter::importTextures(const M3DWrapper &m3d) { unsigned int i; - const char *formatHint[] = { "rgba0800", "rgba0808", "rgba8880", "rgba8888" }; + static const char *formatHint[] = { + "rgba0800", + "rgba0808", + "rgba8880", + "rgba8888" }; m3dtx_t *t; ai_assert(mScene != nullptr); @@ -323,8 +327,9 @@ void M3DImporter::importTextures(const M3DWrapper &m3d) { mScene->mNumTextures = m3d->numtexture; ASSIMP_LOG_DEBUG_F("M3D: importTextures ", mScene->mNumTextures); - if (!m3d->numtexture || !m3d->texture) + if (!m3d->numtexture || !m3d->texture) { return; + } mScene->mTextures = new aiTexture *[m3d->numtexture]; for (i = 0; i < m3d->numtexture; i++) { @@ -391,8 +396,9 @@ void M3DImporter::importMeshes(const M3DWrapper &m3d) { ASSIMP_LOG_DEBUG_F("M3D: importMeshes ", m3d->numface); - if (!m3d->numface || !m3d->face || !m3d->numvertex || !m3d->vertex) + if (!m3d->numface || !m3d->face || !m3d->numvertex || !m3d->vertex) { return; + } for (i = 0; i < m3d->numface; i++) { // we must switch mesh if material changes @@ -476,12 +482,12 @@ void M3DImporter::importMeshes(const M3DWrapper &m3d) { } delete meshes; - if (faces) delete faces; - if (vertices) delete vertices; - if (normals) delete normals; - if (texcoords) delete texcoords; - if (colors) delete colors; - if (vertexids) delete vertexids; + delete faces; + delete vertices; + delete normals; + delete texcoords; + delete colors; + delete vertexids; } // ------------------------------------------------------------------------------------------------ @@ -495,11 +501,15 @@ void M3DImporter::importBones(const M3DWrapper &m3d, unsigned int parentid, aiNo ASSIMP_LOG_DEBUG_F("M3D: importBones ", m3d->numbone, " parentid ", (int)parentid); - if (!m3d->numbone || !m3d->bone) + if (!m3d->numbone || !m3d->bone) { return; + } - for (n = 0, i = parentid + 1; i < m3d->numbone; i++) - if (m3d->bone[i].parent == parentid) n++; + for (n = 0, i = parentid + 1; i < m3d->numbone; i++) { + if (m3d->bone[i].parent == parentid) { + n++; + } + } pParent->mChildren = new aiNode *[n]; for (i = parentid + 1; i < m3d->numbone; i++) { @@ -532,8 +542,9 @@ void M3DImporter::importAnimations(const M3DWrapper &m3d) { ASSIMP_LOG_DEBUG_F("M3D: importAnimations ", mScene->mNumAnimations); - if (!m3d->numaction || !m3d->action || !m3d->numbone || !m3d->bone || !m3d->vertex) + if (!m3d->numaction || !m3d->action || !m3d->numbone || !m3d->bone || !m3d->vertex) { return; + } mScene->mAnimations = new aiAnimation *[m3d->numaction]; for (i = 0; i < m3d->numaction; i++) { @@ -643,16 +654,17 @@ void M3DImporter::convertPose(const M3DWrapper &m3d, aiMatrix4x4 *m, unsigned in // ------------------------------------------------------------------------------------------------ // find a node by name aiNode *M3DImporter::findNode(aiNode *pNode, aiString name) { - unsigned int i; - ai_assert(pNode != nullptr); ai_assert(mScene != nullptr); - if (pNode->mName == name) + if (pNode->mName == name) { return pNode; - for (i = 0; i < pNode->mNumChildren; i++) { + } + for ( unsigned int i = 0; i < pNode->mNumChildren; i++) { aiNode *pChild = findNode(pNode->mChildren[i], name); - if (pChild) return pChild; + if (pChild) { + return pChild; + } } return nullptr; } @@ -714,7 +726,8 @@ void M3DImporter::populateMesh(const M3DWrapper &m3d, aiMesh *pMesh, std::vector // this is complicated, because M3D stores a list of bone id / weight pairs per // vertex but assimp uses lists of local vertex id/weight pairs per local bone list pMesh->mNumBones = m3d->numbone; - /* we need aiBone with mOffsetMatrix for bones without weights as well */ + + // we need aiBone with mOffsetMatrix for bones without weights as well if (pMesh->mNumBones && m3d->numbone && m3d->bone) { pMesh->mBones = new aiBone *[pMesh->mNumBones]; for (unsigned int i = 0; i < m3d->numbone; i++) { @@ -730,15 +743,16 @@ void M3DImporter::populateMesh(const M3DWrapper &m3d, aiMesh *pMesh, std::vector pMesh->mBones[i]->mOffsetMatrix = aiMatrix4x4(); } if (vertexids->size() && m3d->numvertex && m3d->vertex && m3d->numskin && m3d->skin) { - unsigned int i, j; // first count how many vertices we have per bone - for (i = 0; i < vertexids->size(); i++) { - if(vertexids->at(i) >= m3d->numvertex) continue; + for (unsigned int i = 0; i < vertexids->size(); i++) { + if (vertexids->at(i) >= m3d->numvertex) { + continue; + } unsigned int s = m3d->vertex[vertexids->at(i)].skinid; if (s != M3D_UNDEF && s != M3D_INDEXMAX) { for (unsigned int k = 0; k < M3D_NUMBONE && m3d->skin[s].weight[k] > 0.0; k++) { aiString name = aiString(std::string(m3d->bone[m3d->skin[s].boneid[k]].name)); - for (j = 0; j < pMesh->mNumBones; j++) { + for (unsigned int j = 0; j < pMesh->mNumBones; j++) { if (pMesh->mBones[j]->mName == name) { pMesh->mBones[j]->mNumWeights++; break; @@ -747,7 +761,8 @@ void M3DImporter::populateMesh(const M3DWrapper &m3d, aiMesh *pMesh, std::vector } } } - // allocate mWeights + + // allocate mWeights for (j = 0; j < pMesh->mNumBones; j++) { aiBone *pBone = pMesh->mBones[j]; if (pBone->mNumWeights) { From e434c63c31d474c506b7cb573762aa7ac307e37a Mon Sep 17 00:00:00 2001 From: bzt Date: Fri, 31 Jan 2020 14:20:23 +0100 Subject: [PATCH 05/10] Fixed what kimkulling broke --- code/M3D/M3DImporter.cpp | 137 ++++++++++++++++++++------------------- 1 file changed, 70 insertions(+), 67 deletions(-) diff --git a/code/M3D/M3DImporter.cpp b/code/M3D/M3DImporter.cpp index 20b9b9e44..1c6cea766 100644 --- a/code/M3D/M3DImporter.cpp +++ b/code/M3D/M3DImporter.cpp @@ -110,8 +110,8 @@ using namespace std; // Default constructor M3DImporter::M3DImporter() : mScene(nullptr) { - // empty -} + // empty + } // ------------------------------------------------------------------------------------------------ // Returns true, if file is a binary or ASCII Model 3D file. @@ -128,8 +128,14 @@ bool M3DImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool c if (!pIOHandler) { return true; } + /* + * don't use CheckMagicToken because that checks with swapped bytes too, leading to false + * positives. This magic is not uint32_t, but char[4], so memcmp is the best way - std::unique_ptr pStream(pIOHandler->Open(pFile, "rb")); + const char* tokens[] = {"3DMO", "3dmo"}; + return CheckMagicToken(pIOHandler,pFile,tokens,2,0,4); + */ + std::unique_ptr pStream(pIOHandler->Open(pFile, "rb")); unsigned char data[4]; if (4 != pStream->Read(data, 1, 4)) { return false; @@ -140,8 +146,7 @@ bool M3DImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool c #endif ; } - - return false; + return false; } // ------------------------------------------------------------------------------------------------ @@ -247,53 +252,50 @@ void M3DImporter::importMaterials(const M3DWrapper &m3d) { if (!m3d->nummaterial || !m3d->material) { return; - } + } for (i = 0; i < m3d->nummaterial; i++) { m = &m3d->material[i]; aiMaterial *mat = new aiMaterial; name.Set(std::string(m->name)); mat->AddProperty(&name, AI_MATKEY_NAME); - for (j = 0; j < m->numprop; ++j) { + for (j = 0; j < m->numprop; j++) { // look up property type // 0 - 127 scalar values, // 128 - 255 the same properties but for texture maps k = 256; - for (l = 0; l < sizeof(m3d_propertytypes) / sizeof(m3d_propertytypes[0]); ++l) { + for (l = 0; l < sizeof(m3d_propertytypes) / sizeof(m3d_propertytypes[0]); l++) if (m->prop[j].type == m3d_propertytypes[l].id || m->prop[j].type == m3d_propertytypes[l].id + 128) { k = l; break; } - // should never happen, but be safe than sorry - if (k == 256) { - continue; - } + // should never happen, but be safe than sorry + if (k == 256) continue; - // scalar properties - if (m->prop[j].type < 128 && aiProps[k].pKey) { - switch (m3d_propertytypes[k].format) { - case m3dpf_color: - c = mkColor(m->prop[j].value.color); - mat->AddProperty(&c, 1, aiProps[k].pKey, aiProps[k].type, aiProps[k].index); - break; - case m3dpf_float: - f = m->prop[j].value.fnum; - mat->AddProperty(&f, 1, aiProps[k].pKey, aiProps[k].type, aiProps[k].index); - break; - default: - n = m->prop[j].value.num; - if (m->prop[j].type == m3dp_il) { - switch (n) { - case 0: n = aiShadingMode_NoShading; break; - case 2: n = aiShadingMode_Phong; break; - default: n = aiShadingMode_Gouraud; break; - } - } - mat->AddProperty(&n, 1, aiProps[k].pKey, aiProps[k].type, aiProps[k].index); - break; - } - } + // scalar properties + if (m->prop[j].type < 128 && aiProps[k].pKey) { + switch (m3d_propertytypes[k].format) { + case m3dpf_color: + c = mkColor(m->prop[j].value.color); + mat->AddProperty(&c, 1, aiProps[k].pKey, aiProps[k].type, aiProps[k].index); + break; + case m3dpf_float: + f = m->prop[j].value.fnum; + mat->AddProperty(&f, 1, aiProps[k].pKey, aiProps[k].type, aiProps[k].index); + break; + default: + n = m->prop[j].value.num; + if (m->prop[j].type == m3dp_il) { + switch (n) { + case 0: n = aiShadingMode_NoShading; break; + case 2: n = aiShadingMode_Phong; break; + default: n = aiShadingMode_Gouraud; break; + } + } + mat->AddProperty(&n, 1, aiProps[k].pKey, aiProps[k].type, aiProps[k].index); + break; + } } // texture map properties if (m->prop[j].type >= 128 && aiTxProps[k].pKey && @@ -314,11 +316,12 @@ void M3DImporter::importMaterials(const M3DWrapper &m3d) { // import textures, this is the simplest of all void M3DImporter::importTextures(const M3DWrapper &m3d) { unsigned int i; - static const char *formatHint[] = { - "rgba0800", - "rgba0808", - "rgba8880", - "rgba8888" }; + const char *formatHint[] = { + "rgba0800", + "rgba0808", + "rgba8880", + "rgba8888" + }; m3dtx_t *t; ai_assert(mScene != nullptr); @@ -329,7 +332,7 @@ void M3DImporter::importTextures(const M3DWrapper &m3d) { if (!m3d->numtexture || !m3d->texture) { return; - } + } mScene->mTextures = new aiTexture *[m3d->numtexture]; for (i = 0; i < m3d->numtexture; i++) { @@ -398,7 +401,7 @@ void M3DImporter::importMeshes(const M3DWrapper &m3d) { if (!m3d->numface || !m3d->face || !m3d->numvertex || !m3d->vertex) { return; - } + } for (i = 0; i < m3d->numface; i++) { // we must switch mesh if material changes @@ -482,12 +485,12 @@ void M3DImporter::importMeshes(const M3DWrapper &m3d) { } delete meshes; - delete faces; - delete vertices; - delete normals; - delete texcoords; - delete colors; - delete vertexids; + if (faces) delete faces; + if (vertices) delete vertices; + if (normals) delete normals; + if (texcoords) delete texcoords; + if (colors) delete colors; + if (vertexids) delete vertexids; } // ------------------------------------------------------------------------------------------------ @@ -503,13 +506,13 @@ void M3DImporter::importBones(const M3DWrapper &m3d, unsigned int parentid, aiNo if (!m3d->numbone || !m3d->bone) { return; - } + } for (n = 0, i = parentid + 1; i < m3d->numbone; i++) { if (m3d->bone[i].parent == parentid) { - n++; - } - } + n++; + } + } pParent->mChildren = new aiNode *[n]; for (i = parentid + 1; i < m3d->numbone; i++) { @@ -544,7 +547,7 @@ void M3DImporter::importAnimations(const M3DWrapper &m3d) { if (!m3d->numaction || !m3d->action || !m3d->numbone || !m3d->bone || !m3d->vertex) { return; - } + } mScene->mAnimations = new aiAnimation *[m3d->numaction]; for (i = 0; i < m3d->numaction; i++) { @@ -659,12 +662,13 @@ aiNode *M3DImporter::findNode(aiNode *pNode, aiString name) { if (pNode->mName == name) { return pNode; - } - for ( unsigned int i = 0; i < pNode->mNumChildren; i++) { + } + + for (unsigned int i = 0; i < pNode->mNumChildren; i++) { aiNode *pChild = findNode(pNode->mChildren[i], name); if (pChild) { - return pChild; - } + return pChild; + } } return nullptr; } @@ -726,8 +730,7 @@ void M3DImporter::populateMesh(const M3DWrapper &m3d, aiMesh *pMesh, std::vector // this is complicated, because M3D stores a list of bone id / weight pairs per // vertex but assimp uses lists of local vertex id/weight pairs per local bone list pMesh->mNumBones = m3d->numbone; - - // we need aiBone with mOffsetMatrix for bones without weights as well + // we need aiBone with mOffsetMatrix for bones without weights as well if (pMesh->mNumBones && m3d->numbone && m3d->bone) { pMesh->mBones = new aiBone *[pMesh->mNumBones]; for (unsigned int i = 0; i < m3d->numbone; i++) { @@ -743,16 +746,17 @@ void M3DImporter::populateMesh(const M3DWrapper &m3d, aiMesh *pMesh, std::vector pMesh->mBones[i]->mOffsetMatrix = aiMatrix4x4(); } if (vertexids->size() && m3d->numvertex && m3d->vertex && m3d->numskin && m3d->skin) { + unsigned int i, j; // first count how many vertices we have per bone - for (unsigned int i = 0; i < vertexids->size(); i++) { - if (vertexids->at(i) >= m3d->numvertex) { - continue; - } + for (i = 0; i < vertexids->size(); i++) { + if(vertexids->at(i) >= m3d->numvertex) { + continue; + } unsigned int s = m3d->vertex[vertexids->at(i)].skinid; if (s != M3D_UNDEF && s != M3D_INDEXMAX) { for (unsigned int k = 0; k < M3D_NUMBONE && m3d->skin[s].weight[k] > 0.0; k++) { aiString name = aiString(std::string(m3d->bone[m3d->skin[s].boneid[k]].name)); - for (unsigned int j = 0; j < pMesh->mNumBones; j++) { + for (j = 0; j < pMesh->mNumBones; j++) { if (pMesh->mBones[j]->mName == name) { pMesh->mBones[j]->mNumWeights++; break; @@ -761,8 +765,7 @@ void M3DImporter::populateMesh(const M3DWrapper &m3d, aiMesh *pMesh, std::vector } } } - - // allocate mWeights + // allocate mWeights for (j = 0; j < pMesh->mNumBones; j++) { aiBone *pBone = pMesh->mBones[j]; if (pBone->mNumWeights) { From 8af0229e0d257f7443b8f254fe2c75339680da57 Mon Sep 17 00:00:00 2001 From: Max Vollmer Date: Wed, 5 Feb 2020 14:40:35 +0000 Subject: [PATCH 06/10] In "ByVertice" case tempData.size() needs to be mapping_offsets.size(), not vertex_count --- code/FBX/FBXMeshGeometry.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/code/FBX/FBXMeshGeometry.cpp b/code/FBX/FBXMeshGeometry.cpp index 2f2782182..4a3de9f99 100644 --- a/code/FBX/FBXMeshGeometry.cpp +++ b/code/FBX/FBXMeshGeometry.cpp @@ -446,20 +446,19 @@ void ResolveVertexDataArray(std::vector& data_out, const Scope& source, return; } std::vector tempData; - ParseVectorDataArray(tempData, GetRequiredElement(source, dataElementName)); + ParseVectorDataArray(tempData, GetRequiredElement(source, dataElementName)); - if (tempData.size() != vertex_count) { + if (tempData.size() != mapping_offsets.size()) { FBXImporter::LogError(Formatter::format("length of input data unexpected for ByVertice mapping: ") - << tempData.size() << ", expected " << vertex_count); + << tempData.size() << ", expected " << mapping_offsets.size()); return; } data_out.resize(vertex_count); - for (size_t i = 0, e = tempData.size(); i < e; ++i) { - + for (size_t i = 0, e = tempData.size(); i < e; ++i) { const unsigned int istart = mapping_offsets[i], iend = istart + mapping_counts[i]; for (unsigned int j = istart; j < iend; ++j) { - data_out[mappings[j]] = tempData[i]; + data_out[mappings[j]] = tempData[i]; } } } From 18c01a023cd876ba328478a5cd4c6ff389904789 Mon Sep 17 00:00:00 2001 From: Luke Lau Date: Wed, 5 Feb 2020 21:24:54 +0000 Subject: [PATCH 07/10] Use the translation matrix in gltf2 cameras for aiCamera.mPosition --- code/glTF2/glTF2Importer.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/code/glTF2/glTF2Importer.cpp b/code/glTF2/glTF2Importer.cpp index e5052d4d6..154fef313 100644 --- a/code/glTF2/glTF2Importer.cpp +++ b/code/glTF2/glTF2Importer.cpp @@ -925,6 +925,11 @@ aiNode *ImportNode(aiScene *pScene, glTF2::Asset &r, std::vector & if (node.camera) { pScene->mCameras[node.camera.GetIndex()]->mName = ainode->mName; + if (node.translation.isPresent) { + aiVector3D trans; + CopyValue(node.translation.value, trans); + pScene->mCameras[node.camera.GetIndex()]->mPosition = trans; + } } if (node.light) { From 58990d4e3ff84906b459164c211ce379fe63751c Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Mon, 10 Feb 2020 23:59:52 +0100 Subject: [PATCH 08/10] Update FBXParser.cpp add missing brackets. --- code/FBX/FBXParser.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/code/FBX/FBXParser.cpp b/code/FBX/FBXParser.cpp index 5486fdcc6..aef59d60c 100644 --- a/code/FBX/FBXParser.cpp +++ b/code/FBX/FBXParser.cpp @@ -368,8 +368,9 @@ float ParseTokenAsFloat(const Token& t, const char*& err_out) // which fast_atof could interpret as decimal point. #define MAX_FLOAT_LENGTH 31 const size_t length = static_cast(t.end()-t.begin()); - if (length > MAX_FLOAT_LENGTH) + if (length > MAX_FLOAT_LENGTH) { return 0.f; + } char temp[MAX_FLOAT_LENGTH + 1]; std::copy(t.begin(), t.end(), temp); From 47fc3f262751c1f15e0912358dedc33abe8cd5ca Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Wed, 12 Feb 2020 14:54:00 +0100 Subject: [PATCH 09/10] Update M3DImporter.cpp Fix a memoryleak. --- code/M3D/M3DImporter.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/code/M3D/M3DImporter.cpp b/code/M3D/M3DImporter.cpp index 1c6cea766..9aee14f75 100644 --- a/code/M3D/M3DImporter.cpp +++ b/code/M3D/M3DImporter.cpp @@ -383,7 +383,13 @@ void M3DImporter::importTextures(const M3DWrapper &m3d) { // individually. In assimp there're per mesh vertex and UV lists, and they must be // indexed simultaneously. void M3DImporter::importMeshes(const M3DWrapper &m3d) { - unsigned int i, j, k, l, numpoly = 3, lastMat = M3D_INDEXMAX; + ASSIMP_LOG_DEBUG_F("M3D: importMeshes ", m3d->numface); + + if (!m3d->numface || !m3d->face || !m3d->numvertex || !m3d->vertex) { + return; + } + + unsigned int i, j, k, l, numpoly = 3, lastMat = M3D_INDEXMAX; std::vector *meshes = new std::vector(); std::vector *faces = nullptr; std::vector *vertices = nullptr; @@ -397,11 +403,6 @@ void M3DImporter::importMeshes(const M3DWrapper &m3d) { ai_assert(m3d); ai_assert(mScene->mRootNode != nullptr); - ASSIMP_LOG_DEBUG_F("M3D: importMeshes ", m3d->numface); - - if (!m3d->numface || !m3d->face || !m3d->numvertex || !m3d->vertex) { - return; - } for (i = 0; i < m3d->numface; i++) { // we must switch mesh if material changes From b62bd38c71293f0425a1ac5f163c746ecb7c6c5b Mon Sep 17 00:00:00 2001 From: "Hui.Du" Date: Mon, 10 Feb 2020 02:03:26 +0000 Subject: [PATCH 10/10] Fix: GLTF animation works on RTS not matrix; fix matrix related bug. --- code/glTF/glTFAsset.h | 1 + code/glTF/glTFAssetWriter.inl | 4 +++- code/glTF/glTFExporter.cpp | 20 +++++++--------- code/glTF2/glTF2Asset.h | 1 + code/glTF2/glTF2AssetWriter.inl | 8 +++---- code/glTF2/glTF2Exporter.cpp | 42 +++++++++++++++++++++++---------- 6 files changed, 46 insertions(+), 30 deletions(-) diff --git a/code/glTF/glTFAsset.h b/code/glTF/glTFAsset.h index d0b72703e..b918d456b 100644 --- a/code/glTF/glTFAsset.h +++ b/code/glTF/glTFAsset.h @@ -191,6 +191,7 @@ namespace glTF //! Values for the BufferView::target field enum BufferViewTarget { + BufferViewTarget_NONE = 0, BufferViewTarget_ARRAY_BUFFER = 34962, BufferViewTarget_ELEMENT_ARRAY_BUFFER = 34963 }; diff --git a/code/glTF/glTFAssetWriter.inl b/code/glTF/glTFAssetWriter.inl index 784264488..6abe7e078 100644 --- a/code/glTF/glTFAssetWriter.inl +++ b/code/glTF/glTFAssetWriter.inl @@ -203,7 +203,9 @@ namespace glTF { obj.AddMember("buffer", Value(bv.buffer->id, w.mAl).Move(), w.mAl); obj.AddMember("byteOffset", static_cast(bv.byteOffset), w.mAl); obj.AddMember("byteLength", static_cast(bv.byteLength), w.mAl); - obj.AddMember("target", int(bv.target), w.mAl); + if (bv.target != BufferViewTarget_NONE) { + obj.AddMember("target", int(bv.target), w.mAl); + } } inline void Write(Value& /*obj*/, Camera& /*c*/, AssetWriter& /*w*/) diff --git a/code/glTF/glTFExporter.cpp b/code/glTF/glTFExporter.cpp index 072234891..7c21b738b 100644 --- a/code/glTF/glTFExporter.cpp +++ b/code/glTF/glTFExporter.cpp @@ -160,10 +160,7 @@ static void CopyValue(const aiMatrix4x4& v, glTF::mat4& o) static void CopyValue(const aiMatrix4x4& v, aiMatrix4x4& o) { - o.a1 = v.a1; o.a2 = v.a2; o.a3 = v.a3; o.a4 = v.a4; - o.b1 = v.b1; o.b2 = v.b2; o.b3 = v.b3; o.b4 = v.b4; - o.c1 = v.c1; o.c2 = v.c2; o.c3 = v.c3; o.c4 = v.c4; - o.d1 = v.d1; o.d2 = v.d2; o.d3 = v.d3; o.d4 = v.d4; + memcpy(&o, &v, sizeof(aiMatrix4x4)); } static void IdentityMatrix4(glTF::mat4& o) @@ -230,9 +227,8 @@ inline void SetAccessorRange(ComponentType compType, Ref acc, void* da } } -inline Ref ExportData(Asset& a, std::string& meshName, Ref& buffer, - unsigned int count, void* data, AttribType::Value typeIn, AttribType::Value typeOut, ComponentType compType, bool isIndices = false) -{ +inline Ref ExportData(Asset &a, std::string &meshName, Ref &buffer, + unsigned int count, void *data, AttribType::Value typeIn, AttribType::Value typeOut, ComponentType compType, BufferViewTarget target = BufferViewTarget_NONE) { if (!count || !data) return Ref(); unsigned int numCompsIn = AttribType::GetNumComponents(typeIn); @@ -251,7 +247,7 @@ inline Ref ExportData(Asset& a, std::string& meshName, Ref& bu bv->buffer = buffer; bv->byteOffset = unsigned(offset); bv->byteLength = length; //! The target that the WebGL buffer should be bound to. - bv->target = isIndices ? BufferViewTarget_ELEMENT_ARRAY_BUFFER : BufferViewTarget_ARRAY_BUFFER; + bv->target = target; // accessor Ref acc = a.accessors.Create(a.FindUniqueID(meshName, "accessor")); @@ -616,13 +612,13 @@ void glTFExporter::ExportMeshes() // If compression is used then you need parameters of uncompressed region: begin and size. At this step "begin" is stored. if(comp_allow) idx_srcdata_begin = b->byteLength; - Ref v = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mVertices, AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT); + Ref v = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mVertices, AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT, BufferViewTarget_ARRAY_BUFFER); if (v) p.attributes.position.push_back(v); /******************** Normals ********************/ if(comp_allow && (aim->mNormals != 0)) idx_srcdata_normal = b->byteLength;// Store index of normals array. - Ref n = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mNormals, AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT); + Ref n = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mNormals, AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT, BufferViewTarget_ARRAY_BUFFER); if (n) p.attributes.normal.push_back(n); /************** Texture coordinates **************/ @@ -639,7 +635,7 @@ void glTFExporter::ExportMeshes() if(comp_allow) idx_srcdata_tc.push_back(b->byteLength);// Store index of texture coordinates array. - Ref tc = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mTextureCoords[i], AttribType::VEC3, type, ComponentType_FLOAT, false); + Ref tc = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mTextureCoords[i], AttribType::VEC3, type, ComponentType_FLOAT, BufferViewTarget_ARRAY_BUFFER); if (tc) p.attributes.texcoord.push_back(tc); } } @@ -657,7 +653,7 @@ void glTFExporter::ExportMeshes() } } - p.indices = ExportData(*mAsset, meshId, b, unsigned(indices.size()), &indices[0], AttribType::SCALAR, AttribType::SCALAR, ComponentType_UNSIGNED_SHORT, true); + p.indices = ExportData(*mAsset, meshId, b, unsigned(indices.size()), &indices[0], AttribType::SCALAR, AttribType::SCALAR, ComponentType_UNSIGNED_SHORT, BufferViewTarget_ELEMENT_ARRAY_BUFFER); } switch (aim->mPrimitiveTypes) { diff --git a/code/glTF2/glTF2Asset.h b/code/glTF2/glTF2Asset.h index 53774de7a..d3c1654d0 100644 --- a/code/glTF2/glTF2Asset.h +++ b/code/glTF2/glTF2Asset.h @@ -198,6 +198,7 @@ namespace glTF2 //! Values for the BufferView::target field enum BufferViewTarget { + BufferViewTarget_NONE = 0, BufferViewTarget_ARRAY_BUFFER = 34962, BufferViewTarget_ELEMENT_ARRAY_BUFFER = 34963 }; diff --git a/code/glTF2/glTF2AssetWriter.inl b/code/glTF2/glTF2AssetWriter.inl index 02c14980d..8adc20404 100644 --- a/code/glTF2/glTF2AssetWriter.inl +++ b/code/glTF2/glTF2AssetWriter.inl @@ -176,13 +176,13 @@ namespace glTF2 { valSampler.AddMember("input", s.input->index, w.mAl); switch (s.interpolation) { case Interpolation_LINEAR: - valSampler.AddMember("path", "LINEAR", w.mAl); + valSampler.AddMember("interpolation", "LINEAR", w.mAl); break; case Interpolation_STEP: - valSampler.AddMember("path", "STEP", w.mAl); + valSampler.AddMember("interpolation", "STEP", w.mAl); break; case Interpolation_CUBICSPLINE: - valSampler.AddMember("path", "CUBICSPLINE", w.mAl); + valSampler.AddMember("interpolation", "CUBICSPLINE", w.mAl); break; } valSampler.AddMember("output", s.output->index, w.mAl); @@ -209,7 +209,7 @@ namespace glTF2 { if (bv.byteStride != 0) { obj.AddMember("byteStride", bv.byteStride, w.mAl); } - if (bv.target != 0) { + if (bv.target != BufferViewTarget_NONE) { obj.AddMember("target", int(bv.target), w.mAl); } } diff --git a/code/glTF2/glTF2Exporter.cpp b/code/glTF2/glTF2Exporter.cpp index 1bfee4491..35dac57e6 100644 --- a/code/glTF2/glTF2Exporter.cpp +++ b/code/glTF2/glTF2Exporter.cpp @@ -141,10 +141,7 @@ static void CopyValue(const aiMatrix4x4& v, mat4& o) { } static void CopyValue(const aiMatrix4x4& v, aiMatrix4x4& o) { - o.a1 = v.a1; o.a2 = v.a2; o.a3 = v.a3; o.a4 = v.a4; - o.b1 = v.b1; o.b2 = v.b2; o.b3 = v.b3; o.b4 = v.b4; - o.c1 = v.c1; o.c2 = v.c2; o.c3 = v.c3; o.c4 = v.c4; - o.d1 = v.d1; o.d2 = v.d2; o.d3 = v.d3; o.d4 = v.d4; + memcpy(&o, &v, sizeof(aiMatrix4x4)); } static void IdentityMatrix4(mat4& o) { @@ -211,7 +208,7 @@ inline void SetAccessorRange(ComponentType compType, Ref acc, void* da } inline Ref ExportData(Asset& a, std::string& meshName, Ref& buffer, - size_t count, void* data, AttribType::Value typeIn, AttribType::Value typeOut, ComponentType compType, bool isIndices = false) + size_t count, void* data, AttribType::Value typeIn, AttribType::Value typeOut, ComponentType compType, BufferViewTarget target = BufferViewTarget_NONE) { if (!count || !data) { return Ref(); @@ -234,7 +231,7 @@ inline Ref ExportData(Asset& a, std::string& meshName, Ref& bu bv->byteOffset = offset; bv->byteLength = length; //! The target that the WebGL buffer should be bound to. bv->byteStride = 0; - bv->target = isIndices ? BufferViewTarget_ELEMENT_ARRAY_BUFFER : BufferViewTarget_ARRAY_BUFFER; + bv->target = target; // accessor Ref acc = a.accessors.Create(a.FindUniqueID(meshName, "accessor")); @@ -747,7 +744,7 @@ void glTF2Exporter::ExportMeshes() p.material = mAsset->materials.Get(aim->mMaterialIndex); /******************* Vertices ********************/ - Ref v = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mVertices, AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT); + Ref v = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mVertices, AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT, BufferViewTarget_ARRAY_BUFFER); if (v) p.attributes.position.push_back(v); /******************** Normals ********************/ @@ -758,7 +755,7 @@ void glTF2Exporter::ExportMeshes() } } - Ref n = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mNormals, AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT); + Ref n = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mNormals, AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT, BufferViewTarget_ARRAY_BUFFER); if (n) p.attributes.normal.push_back(n); /************** Texture coordinates **************/ @@ -776,14 +773,14 @@ void glTF2Exporter::ExportMeshes() if (aim->mNumUVComponents[i] > 0) { AttribType::Value type = (aim->mNumUVComponents[i] == 2) ? AttribType::VEC2 : AttribType::VEC3; - Ref tc = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mTextureCoords[i], AttribType::VEC3, type, ComponentType_FLOAT, false); + Ref tc = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mTextureCoords[i], AttribType::VEC3, type, ComponentType_FLOAT, BufferViewTarget_ARRAY_BUFFER); if (tc) p.attributes.texcoord.push_back(tc); } } /*************** Vertex colors ****************/ for (unsigned int indexColorChannel = 0; indexColorChannel < aim->GetNumColorChannels(); ++indexColorChannel) { - Ref c = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mColors[indexColorChannel], AttribType::VEC4, AttribType::VEC4, ComponentType_FLOAT, false); + Ref c = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mColors[indexColorChannel], AttribType::VEC4, AttribType::VEC4, ComponentType_FLOAT, BufferViewTarget_ARRAY_BUFFER); if (c) p.attributes.color.push_back(c); } @@ -799,7 +796,7 @@ void glTF2Exporter::ExportMeshes() } } - p.indices = ExportData(*mAsset, meshId, b, indices.size(), &indices[0], AttribType::SCALAR, AttribType::SCALAR, ComponentType_UNSIGNED_INT, true); + p.indices = ExportData(*mAsset, meshId, b, indices.size(), &indices[0], AttribType::SCALAR, AttribType::SCALAR, ComponentType_UNSIGNED_INT, BufferViewTarget_ELEMENT_ARRAY_BUFFER); } switch (aim->mPrimitiveTypes) { @@ -956,8 +953,27 @@ unsigned int glTF2Exporter::ExportNode(const aiNode* n, Ref& parent) node->name = name; if (!n->mTransformation.IsIdentity()) { - node->matrix.isPresent = true; - CopyValue(n->mTransformation, node->matrix.value); + if (mScene->mNumAnimations > 0) { + aiQuaternion quaternion; + n->mTransformation.Decompose(*reinterpret_cast(&node->scale.value), quaternion, *reinterpret_cast(&node->translation.value)); + + aiVector3D vector(static_cast(1.0f), static_cast(1.0f), static_cast(1.0f)); + if (!reinterpret_cast(&node->scale.value)->Equal(vector)) { + node->scale.isPresent = true; + } + if (!reinterpret_cast(&node->translation.value)->Equal(vector)) { + node->translation.isPresent = true; + } + node->rotation.isPresent = true; + node->rotation.value[0] = quaternion.x; + node->rotation.value[1] = quaternion.y; + node->rotation.value[2] = quaternion.z; + node->rotation.value[3] = quaternion.w; + node->matrix.isPresent = false; + } else { + node->matrix.isPresent = true; + CopyValue(n->mTransformation, node->matrix.value); + } } for (unsigned int i = 0; i < n->mNumMeshes; ++i) {