Sfoglia il codice sorgente

Fix for importing animated skinned meshes.
Scale is negated in inverse bind matrices.
Vertex weights are normalized (glTF importer is limited to 4 weights per vert).
Fixed interpolation for animations where the first frame is not at 0.0.
Allows cached.dts version of assimp imported shapes to be loaded.

OTHGMars 6 anni fa
parent
commit
6660f253b5

+ 24 - 3
Engine/source/ts/assimp/assimpAppMesh.cpp

@@ -202,6 +202,15 @@ void AssimpAppMesh::lockMesh(F32 t, const MatrixF& objOffset)
 
       MatrixF boneTransform;
       AssimpAppNode::assimpToTorqueMat(mMeshData->mBones[b]->mOffsetMatrix, boneTransform);
+      Point3F boneScale = boneTransform.getScale();
+      if (boneScale != Point3F::One)
+      {
+         Point3F scaleMult = Point3F::One / boneScale;
+         Point3F scalePos = boneTransform.getPosition();
+         boneTransform.scale(scaleMult);
+         scalePos /= scaleMult;
+         boneTransform.setPosition(scalePos);
+      }
       initialTransforms.push_back(boneTransform);
 
       //Weights
@@ -225,20 +234,32 @@ void AssimpAppMesh::lockMesh(F32 t, const MatrixF& objOffset)
    vertexIndex.setSize(nonZeroWeights);
    boneIndex.setSize(nonZeroWeights);
 
-   // Copy the weights to our vectors in vertex order
+   // Copy the weights to our vectors in vertex order and
+   // normalize vertex weights (force weights for each vert to sum to 1)
    U32 nextWeight = 0;
-   for (U32 i = 0; i < mMeshData->mNumVertices; i++)
+   for (U32 i = 0; i < mMeshData->mNumVertices; ++i)
    {
-      for (U32 ind = 0; ind < nonZeroWeights; ind++)
+      U32 vertStart = nextWeight;
+      F32 invTotalWeight = 0;
+      for (U32 ind = 0; ind < nonZeroWeights; ++ind)
       {
          if (tmpVertexIndex[ind] == i)
          {
             weight[nextWeight] = tmpWeight[ind];
+            invTotalWeight += tmpWeight[ind];
             vertexIndex[nextWeight] = tmpVertexIndex[ind];
             boneIndex[nextWeight] = tmpBoneIndex[ind];
             nextWeight++;
          }
       }
+
+      // Now normalize the vertex weights
+      if (invTotalWeight > 0.0)
+      {
+         invTotalWeight = 1.0f / invTotalWeight;
+         for (U32 ind = vertStart; ind < nextWeight; ++ind)
+            weight[ind] *= invTotalWeight;
+      }
    }
 
    if ( noUVFound )

+ 6 - 6
Engine/source/ts/assimp/assimpAppNode.cpp

@@ -135,13 +135,13 @@ void AssimpAppNode::getAnimatedTransform(MatrixF& mat, F32 t, aiAnimation* animS
             {
                F32 curT = sTimeMultiplier * (F32)nodeAnim->mPositionKeys[key].mTime;
                curPos.set(nodeAnim->mPositionKeys[key].mValue.x, nodeAnim->mPositionKeys[key].mValue.y, nodeAnim->mPositionKeys[key].mValue.z);
-               if (curT > t)
+               if ((curT > t) && (key > 0))
                {
                   F32 factor = (t - lastT) / (curT - lastT);
                   trans.interpolate(lastPos, curPos, factor);
                   break;
                }
-               else if ((curT == t) || (key == nodeAnim->mNumPositionKeys - 1))
+               else if ((curT >= t) || (key == nodeAnim->mNumPositionKeys - 1))
                {
                   trans = curPos;
                   break;
@@ -165,13 +165,13 @@ void AssimpAppNode::getAnimatedTransform(MatrixF& mat, F32 t, aiAnimation* animS
                F32 curT = sTimeMultiplier * (F32)nodeAnim->mRotationKeys[key].mTime;
                curRot.set(nodeAnim->mRotationKeys[key].mValue.x, nodeAnim->mRotationKeys[key].mValue.y,
                   nodeAnim->mRotationKeys[key].mValue.z, nodeAnim->mRotationKeys[key].mValue.w);
-               if (curT > t)
+               if ((curT > t) && (key > 0))
                {
                   F32 factor = (t - lastT) / (curT - lastT);
                   rot.interpolate(lastRot, curRot, factor);
                   break;
                }
-               else if ((curT == t) || (key == nodeAnim->mNumRotationKeys - 1))
+               else if ((curT >= t) || (key == nodeAnim->mNumRotationKeys - 1))
                {
                   rot = curRot;
                   break;
@@ -193,13 +193,13 @@ void AssimpAppNode::getAnimatedTransform(MatrixF& mat, F32 t, aiAnimation* animS
             {
                F32 curT = sTimeMultiplier * (F32)nodeAnim->mScalingKeys[key].mTime;
                curScale.set(nodeAnim->mScalingKeys[key].mValue.x, nodeAnim->mScalingKeys[key].mValue.y, nodeAnim->mScalingKeys[key].mValue.z);
-               if (curT > t)
+               if ((curT > t) && (key > 0))
                {
                   F32 factor = (t - lastT) / (curT - lastT);
                   scale.interpolate(lastScale, curScale, factor);
                   break;
                }
-               else if ((curT == t) || (key == nodeAnim->mNumScalingKeys - 1))
+               else if ((curT >= t) || (key == nodeAnim->mNumScalingKeys - 1))
                {
                   scale = curScale;
                   break;

+ 2 - 0
Engine/source/ts/assimp/assimpAppSequence.cpp

@@ -19,6 +19,7 @@ AssimpAppSequence::AssimpAppSequence(aiAnimation *a) :
    mSequenceName = mAnim->mName.C_Str();
    if (mSequenceName.isEmpty())
       mSequenceName = "ambient";
+   Con::printf("\n[Assimp] Adding %s animation", mSequenceName.c_str());
 
    fps = (mAnim->mTicksPerSecond > 0) ? mAnim->mTicksPerSecond : 30.0f;
 
@@ -72,6 +73,7 @@ AssimpAppSequence::AssimpAppSequence(aiAnimation *a) :
       minFrameTime /= (F32)timeFactor;
       maxEndTime /= (F32)timeFactor;
       fps = (minFrameTime > 0.0f) ? 1.0f / minFrameTime : fps;
+      fps = mClamp(fpsRequest, 5 /*TSShapeLoader::MinFrameRate*/, TSShapeLoader::MaxFrameRate);
       seqEnd = maxEndTime;
       mTimeMultiplier = 1.0f / timeFactor;
    }

+ 3 - 5
Engine/source/ts/assimp/assimpShapeLoader.cpp

@@ -329,8 +329,6 @@ void AssimpShapeLoader::updateMaterialsScript(const Torque::Path &path)
 /// Check if an up-to-date cached DTS is available for this DAE file
 bool AssimpShapeLoader::canLoadCachedDTS(const Torque::Path& path)
 {
-   return false;
-
    // Generate the cached filename
    Torque::Path cachedPath(path);
    cachedPath.setExtension("cached.dts");
@@ -339,13 +337,13 @@ bool AssimpShapeLoader::canLoadCachedDTS(const Torque::Path& path)
    FileTime cachedModifyTime;
    if (Platform::getFileTimes(cachedPath.getFullPath(), NULL, &cachedModifyTime))
    {
-      bool forceLoadDAE = Con::getBoolVariable("$assimp::forceLoad", false);
+      bool forceLoad = Con::getBoolVariable("$assimp::forceLoad", false);
 
       FileTime daeModifyTime;
       if (!Platform::getFileTimes(path.getFullPath(), NULL, &daeModifyTime) ||
-         (!forceLoadDAE && (Platform::compareFileTimes(cachedModifyTime, daeModifyTime) >= 0) ))
+         (!forceLoad && (Platform::compareFileTimes(cachedModifyTime, daeModifyTime) >= 0) ))
       {
-         // DAE not found, or cached DTS is newer
+         // Original file not found, or cached DTS is newer
          return true;
       }
    }