mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-01-19 20:24:49 +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
|
|
@ -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 )
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue