Browse Source

Merge pull request #3487 from inhosens/master

Prevent to generate redundant morph targets for glTF2
Kim Kulling 4 years ago
parent
commit
11b4153949
3 changed files with 59 additions and 31 deletions
  1. 26 12
      code/AssetLib/glTF2/glTF2Importer.cpp
  2. 21 17
      code/Common/CreateAnimMesh.cpp
  3. 12 2
      include/assimp/CreateAnimMesh.h

+ 26 - 12
code/AssetLib/glTF2/glTF2Importer.cpp

@@ -453,11 +453,16 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) {
                 aim->mNumAnimMeshes = (unsigned int)targets.size();
                 aim->mAnimMeshes = new aiAnimMesh *[aim->mNumAnimMeshes];
                 for (size_t i = 0; i < targets.size(); i++) {
-                    aim->mAnimMeshes[i] = aiCreateAnimMesh(aim);
+                    bool needPositions = targets[i].position.size() > 0;
+                    bool needNormals = targets[i].normal.size() > 0;
+                    bool needTangents = targets[i].tangent.size() > 0;
+                    // GLTF morph does not support colors and texCoords
+                    aim->mAnimMeshes[i] = aiCreateAnimMesh(aim,
+                            needPositions, needNormals, needTangents, false, false);
                     aiAnimMesh &aiAnimMesh = *(aim->mAnimMeshes[i]);
                     Mesh::Primitive::Target &target = targets[i];
 
-                    if (target.position.size() > 0) {
+                    if (needPositions) {
                         aiVector3D *positionDiff = nullptr;
                         target.position[0]->ExtractData(positionDiff);
                         for (unsigned int vertexId = 0; vertexId < aim->mNumVertices; vertexId++) {
@@ -465,7 +470,7 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) {
                         }
                         delete[] positionDiff;
                     }
-                    if (target.normal.size() > 0) {
+                    if (needNormals) {
                         aiVector3D *normalDiff = nullptr;
                         target.normal[0]->ExtractData(normalDiff);
                         for (unsigned int vertexId = 0; vertexId < aim->mNumVertices; vertexId++) {
@@ -473,7 +478,7 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) {
                         }
                         delete[] normalDiff;
                     }
-                    if (target.tangent.size() > 0) {
+                    if (needTangents) {
                         Tangent *tangent = nullptr;
                         attr.tangent[0]->ExtractData(tangent);
 
@@ -1069,9 +1074,11 @@ aiNodeAnim *CreateNodeAnim(glTF2::Asset&, Node &node, AnimationSamplers &sampler
         samplers.translation->output->ExtractData(values);
         anim->mNumPositionKeys = static_cast<uint32_t>(samplers.translation->input->count);
         anim->mPositionKeys = new aiVectorKey[anim->mNumPositionKeys];
+        unsigned int ii = (samplers.translation->interpolation == Interpolation_CUBICSPLINE) ? 1 : 0;
         for (unsigned int i = 0; i < anim->mNumPositionKeys; ++i) {
             anim->mPositionKeys[i].mTime = times[i] * kMillisecondsFromSeconds;
-            anim->mPositionKeys[i].mValue = values[i];
+            anim->mPositionKeys[i].mValue = values[ii];
+            ii += (samplers.translation->interpolation == Interpolation_CUBICSPLINE) ? 3 : 1;
         }
         delete[] times;
         delete[] values;
@@ -1091,12 +1098,14 @@ aiNodeAnim *CreateNodeAnim(glTF2::Asset&, Node &node, AnimationSamplers &sampler
         samplers.rotation->output->ExtractData(values);
         anim->mNumRotationKeys = static_cast<uint32_t>(samplers.rotation->input->count);
         anim->mRotationKeys = new aiQuatKey[anim->mNumRotationKeys];
+        unsigned int ii = (samplers.rotation->interpolation == Interpolation_CUBICSPLINE) ? 1 : 0;
         for (unsigned int i = 0; i < anim->mNumRotationKeys; ++i) {
             anim->mRotationKeys[i].mTime = times[i] * kMillisecondsFromSeconds;
-            anim->mRotationKeys[i].mValue.x = values[i].w;
-            anim->mRotationKeys[i].mValue.y = values[i].x;
-            anim->mRotationKeys[i].mValue.z = values[i].y;
-            anim->mRotationKeys[i].mValue.w = values[i].z;
+            anim->mRotationKeys[i].mValue.x = values[ii].w;
+            anim->mRotationKeys[i].mValue.y = values[ii].x;
+            anim->mRotationKeys[i].mValue.z = values[ii].y;
+            anim->mRotationKeys[i].mValue.w = values[ii].z;
+            ii += (samplers.rotation->interpolation == Interpolation_CUBICSPLINE) ? 3 : 1;
         }
         delete[] times;
         delete[] values;
@@ -1117,9 +1126,11 @@ aiNodeAnim *CreateNodeAnim(glTF2::Asset&, Node &node, AnimationSamplers &sampler
         samplers.scale->output->ExtractData(values);
         anim->mNumScalingKeys = static_cast<uint32_t>(samplers.scale->input->count);
         anim->mScalingKeys = new aiVectorKey[anim->mNumScalingKeys];
+        unsigned int ii = (samplers.scale->interpolation == Interpolation_CUBICSPLINE) ? 1 : 0;
         for (unsigned int i = 0; i < anim->mNumScalingKeys; ++i) {
             anim->mScalingKeys[i].mTime = times[i] * kMillisecondsFromSeconds;
-            anim->mScalingKeys[i].mValue = values[i];
+            anim->mScalingKeys[i].mValue = values[ii];
+            ii += (samplers.scale->interpolation == Interpolation_CUBICSPLINE) ? 3 : 1;
         }
         delete[] times;
         delete[] values;
@@ -1148,11 +1159,14 @@ aiMeshMorphAnim *CreateMeshMorphAnim(glTF2::Asset&, Node &node, AnimationSampler
         samplers.weight->output->ExtractData(values);
         anim->mNumKeys = static_cast<uint32_t>(samplers.weight->input->count);
 
-        const unsigned int numMorphs = (unsigned int)samplers.weight->output->count / anim->mNumKeys;
+        // for Interpolation_CUBICSPLINE can have more outputs
+        const unsigned int weightStride = (unsigned int)samplers.weight->output->count / anim->mNumKeys;
+        const unsigned int numMorphs = (samplers.weight->interpolation == Interpolation_CUBICSPLINE) ? weightStride - 2 : weightStride;
 
         anim->mKeys = new aiMeshMorphKey[anim->mNumKeys];
-        unsigned int k = 0u;
+        unsigned int ii = (samplers.weight->interpolation == Interpolation_CUBICSPLINE) ? 1 : 0;
         for (unsigned int i = 0u; i < anim->mNumKeys; ++i) {
+            unsigned int k = weightStride * i + ii;
             anim->mKeys[i].mTime = times[i] * kMillisecondsFromSeconds;
             anim->mKeys[i].mNumValuesAndWeights = numMorphs;
             anim->mKeys[i].mValues = new unsigned int[numMorphs];

+ 21 - 17
code/Common/CreateAnimMesh.cpp

@@ -44,42 +44,46 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 namespace Assimp    {
 
-aiAnimMesh *aiCreateAnimMesh(const aiMesh *mesh)
+aiAnimMesh *aiCreateAnimMesh(const aiMesh *mesh, bool needPositions, bool needNormals, bool needTangents, bool needColors, bool needTexCoords)
 {
     aiAnimMesh *animesh = new aiAnimMesh;
     animesh->mNumVertices = mesh->mNumVertices;
-    if (mesh->mVertices) {
+    if (needPositions && mesh->mVertices) {
         animesh->mVertices = new aiVector3D[animesh->mNumVertices];
         std::memcpy(animesh->mVertices, mesh->mVertices, mesh->mNumVertices * sizeof(aiVector3D));
     }
-    if (mesh->mNormals) {
+    if (needNormals && mesh->mNormals) {
         animesh->mNormals = new aiVector3D[animesh->mNumVertices];
         std::memcpy(animesh->mNormals, mesh->mNormals, mesh->mNumVertices * sizeof(aiVector3D));
     }
-    if (mesh->mTangents) {
+    if (needTangents && mesh->mTangents) {
         animesh->mTangents = new aiVector3D[animesh->mNumVertices];
         std::memcpy(animesh->mTangents, mesh->mTangents, mesh->mNumVertices * sizeof(aiVector3D));
     }
-    if (mesh->mBitangents) {
+    if (needTangents && mesh->mBitangents) {
         animesh->mBitangents = new aiVector3D[animesh->mNumVertices];
         std::memcpy(animesh->mBitangents, mesh->mBitangents, mesh->mNumVertices * sizeof(aiVector3D));
     }
 
-    for (int i = 0; i < AI_MAX_NUMBER_OF_COLOR_SETS; ++i) {
-        if (mesh->mColors[i]) {
-            animesh->mColors[i] = new aiColor4D[animesh->mNumVertices];
-            std::memcpy(animesh->mColors[i], mesh->mColors[i], mesh->mNumVertices * sizeof(aiColor4D));
-        } else {
-            animesh->mColors[i] = nullptr;
+    if (needColors) {
+        for (int i = 0; i < AI_MAX_NUMBER_OF_COLOR_SETS; ++i) {
+            if (mesh->mColors[i]) {
+                animesh->mColors[i] = new aiColor4D[animesh->mNumVertices];
+                std::memcpy(animesh->mColors[i], mesh->mColors[i], mesh->mNumVertices * sizeof(aiColor4D));
+            } else {
+                animesh->mColors[i] = nullptr;
+            }
         }
     }
 
-    for (int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) {
-        if (mesh->mTextureCoords[i]) {
-            animesh->mTextureCoords[i] = new aiVector3D[animesh->mNumVertices];
-            std::memcpy(animesh->mTextureCoords[i], mesh->mTextureCoords[i], mesh->mNumVertices * sizeof(aiVector3D));
-        } else {
-            animesh->mTextureCoords[i] = nullptr;
+    if (needTexCoords) {
+        for (int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) {
+            if (mesh->mTextureCoords[i]) {
+                animesh->mTextureCoords[i] = new aiVector3D[animesh->mNumVertices];
+                std::memcpy(animesh->mTextureCoords[i], mesh->mTextureCoords[i], mesh->mNumVertices * sizeof(aiVector3D));
+            } else {
+                animesh->mTextureCoords[i] = nullptr;
+            }
         }
     }
     return animesh;

+ 12 - 2
include/assimp/CreateAnimMesh.h

@@ -57,10 +57,20 @@ namespace Assimp {
 
 /**
  *  Create aiAnimMesh from aiMesh.
- *  @param  mesh    The input mesh to create an animated mesh from.
+ *  @param  mesh            The input mesh to create an animated mesh from.
+ *  @param  needPositions   If true, positions will be copied from.
+ *  @param  needNormals     If true, normals will be copied from.
+ *  @param  needTangents    If true, tangents and bitangents will be copied from.
+ *  @param  needColors      If true, colors will be copied from.
+ *  @param  needTexCoords   If true, texCoords will be copied from.
  *  @return The new created animated mesh.
  */
-ASSIMP_API aiAnimMesh *aiCreateAnimMesh(const aiMesh *mesh);
+ASSIMP_API aiAnimMesh *aiCreateAnimMesh(const aiMesh *mesh,
+                                        bool needPositions = true,
+                                        bool needNormals = true,
+                                        bool needTangents = true,
+                                        bool needColors = true,
+                                        bool needTexCoords = true);
 
 } // end of namespace Assimp