mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-07-15 00:24:40 +00:00
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.
This commit is contained in:
parent
6be2989bbc
commit
6660f253b5
4 changed files with 35 additions and 14 deletions
|
|
@ -202,6 +202,15 @@ void AssimpAppMesh::lockMesh(F32 t, const MatrixF& objOffset)
|
||||||
|
|
||||||
MatrixF boneTransform;
|
MatrixF boneTransform;
|
||||||
AssimpAppNode::assimpToTorqueMat(mMeshData->mBones[b]->mOffsetMatrix, 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);
|
initialTransforms.push_back(boneTransform);
|
||||||
|
|
||||||
//Weights
|
//Weights
|
||||||
|
|
@ -225,20 +234,32 @@ void AssimpAppMesh::lockMesh(F32 t, const MatrixF& objOffset)
|
||||||
vertexIndex.setSize(nonZeroWeights);
|
vertexIndex.setSize(nonZeroWeights);
|
||||||
boneIndex.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;
|
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)
|
if (tmpVertexIndex[ind] == i)
|
||||||
{
|
{
|
||||||
weight[nextWeight] = tmpWeight[ind];
|
weight[nextWeight] = tmpWeight[ind];
|
||||||
|
invTotalWeight += tmpWeight[ind];
|
||||||
vertexIndex[nextWeight] = tmpVertexIndex[ind];
|
vertexIndex[nextWeight] = tmpVertexIndex[ind];
|
||||||
boneIndex[nextWeight] = tmpBoneIndex[ind];
|
boneIndex[nextWeight] = tmpBoneIndex[ind];
|
||||||
nextWeight++;
|
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 )
|
if ( noUVFound )
|
||||||
|
|
|
||||||
|
|
@ -135,13 +135,13 @@ void AssimpAppNode::getAnimatedTransform(MatrixF& mat, F32 t, aiAnimation* animS
|
||||||
{
|
{
|
||||||
F32 curT = sTimeMultiplier * (F32)nodeAnim->mPositionKeys[key].mTime;
|
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);
|
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);
|
F32 factor = (t - lastT) / (curT - lastT);
|
||||||
trans.interpolate(lastPos, curPos, factor);
|
trans.interpolate(lastPos, curPos, factor);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if ((curT == t) || (key == nodeAnim->mNumPositionKeys - 1))
|
else if ((curT >= t) || (key == nodeAnim->mNumPositionKeys - 1))
|
||||||
{
|
{
|
||||||
trans = curPos;
|
trans = curPos;
|
||||||
break;
|
break;
|
||||||
|
|
@ -165,13 +165,13 @@ void AssimpAppNode::getAnimatedTransform(MatrixF& mat, F32 t, aiAnimation* animS
|
||||||
F32 curT = sTimeMultiplier * (F32)nodeAnim->mRotationKeys[key].mTime;
|
F32 curT = sTimeMultiplier * (F32)nodeAnim->mRotationKeys[key].mTime;
|
||||||
curRot.set(nodeAnim->mRotationKeys[key].mValue.x, nodeAnim->mRotationKeys[key].mValue.y,
|
curRot.set(nodeAnim->mRotationKeys[key].mValue.x, nodeAnim->mRotationKeys[key].mValue.y,
|
||||||
nodeAnim->mRotationKeys[key].mValue.z, nodeAnim->mRotationKeys[key].mValue.w);
|
nodeAnim->mRotationKeys[key].mValue.z, nodeAnim->mRotationKeys[key].mValue.w);
|
||||||
if (curT > t)
|
if ((curT > t) && (key > 0))
|
||||||
{
|
{
|
||||||
F32 factor = (t - lastT) / (curT - lastT);
|
F32 factor = (t - lastT) / (curT - lastT);
|
||||||
rot.interpolate(lastRot, curRot, factor);
|
rot.interpolate(lastRot, curRot, factor);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if ((curT == t) || (key == nodeAnim->mNumRotationKeys - 1))
|
else if ((curT >= t) || (key == nodeAnim->mNumRotationKeys - 1))
|
||||||
{
|
{
|
||||||
rot = curRot;
|
rot = curRot;
|
||||||
break;
|
break;
|
||||||
|
|
@ -193,13 +193,13 @@ void AssimpAppNode::getAnimatedTransform(MatrixF& mat, F32 t, aiAnimation* animS
|
||||||
{
|
{
|
||||||
F32 curT = sTimeMultiplier * (F32)nodeAnim->mScalingKeys[key].mTime;
|
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);
|
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);
|
F32 factor = (t - lastT) / (curT - lastT);
|
||||||
scale.interpolate(lastScale, curScale, factor);
|
scale.interpolate(lastScale, curScale, factor);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if ((curT == t) || (key == nodeAnim->mNumScalingKeys - 1))
|
else if ((curT >= t) || (key == nodeAnim->mNumScalingKeys - 1))
|
||||||
{
|
{
|
||||||
scale = curScale;
|
scale = curScale;
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ AssimpAppSequence::AssimpAppSequence(aiAnimation *a) :
|
||||||
mSequenceName = mAnim->mName.C_Str();
|
mSequenceName = mAnim->mName.C_Str();
|
||||||
if (mSequenceName.isEmpty())
|
if (mSequenceName.isEmpty())
|
||||||
mSequenceName = "ambient";
|
mSequenceName = "ambient";
|
||||||
|
Con::printf("\n[Assimp] Adding %s animation", mSequenceName.c_str());
|
||||||
|
|
||||||
fps = (mAnim->mTicksPerSecond > 0) ? mAnim->mTicksPerSecond : 30.0f;
|
fps = (mAnim->mTicksPerSecond > 0) ? mAnim->mTicksPerSecond : 30.0f;
|
||||||
|
|
||||||
|
|
@ -72,6 +73,7 @@ AssimpAppSequence::AssimpAppSequence(aiAnimation *a) :
|
||||||
minFrameTime /= (F32)timeFactor;
|
minFrameTime /= (F32)timeFactor;
|
||||||
maxEndTime /= (F32)timeFactor;
|
maxEndTime /= (F32)timeFactor;
|
||||||
fps = (minFrameTime > 0.0f) ? 1.0f / minFrameTime : fps;
|
fps = (minFrameTime > 0.0f) ? 1.0f / minFrameTime : fps;
|
||||||
|
fps = mClamp(fpsRequest, 5 /*TSShapeLoader::MinFrameRate*/, TSShapeLoader::MaxFrameRate);
|
||||||
seqEnd = maxEndTime;
|
seqEnd = maxEndTime;
|
||||||
mTimeMultiplier = 1.0f / timeFactor;
|
mTimeMultiplier = 1.0f / timeFactor;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
/// Check if an up-to-date cached DTS is available for this DAE file
|
||||||
bool AssimpShapeLoader::canLoadCachedDTS(const Torque::Path& path)
|
bool AssimpShapeLoader::canLoadCachedDTS(const Torque::Path& path)
|
||||||
{
|
{
|
||||||
return false;
|
|
||||||
|
|
||||||
// Generate the cached filename
|
// Generate the cached filename
|
||||||
Torque::Path cachedPath(path);
|
Torque::Path cachedPath(path);
|
||||||
cachedPath.setExtension("cached.dts");
|
cachedPath.setExtension("cached.dts");
|
||||||
|
|
@ -339,13 +337,13 @@ bool AssimpShapeLoader::canLoadCachedDTS(const Torque::Path& path)
|
||||||
FileTime cachedModifyTime;
|
FileTime cachedModifyTime;
|
||||||
if (Platform::getFileTimes(cachedPath.getFullPath(), NULL, &cachedModifyTime))
|
if (Platform::getFileTimes(cachedPath.getFullPath(), NULL, &cachedModifyTime))
|
||||||
{
|
{
|
||||||
bool forceLoadDAE = Con::getBoolVariable("$assimp::forceLoad", false);
|
bool forceLoad = Con::getBoolVariable("$assimp::forceLoad", false);
|
||||||
|
|
||||||
FileTime daeModifyTime;
|
FileTime daeModifyTime;
|
||||||
if (!Platform::getFileTimes(path.getFullPath(), NULL, &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;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue