diff --git a/irr/include/ISkinnedMesh.h b/irr/include/ISkinnedMesh.h index bb611bba2..869327bcd 100644 --- a/irr/include/ISkinnedMesh.h +++ b/irr/include/ISkinnedMesh.h @@ -159,15 +159,17 @@ class ISkinnedMesh : public IAnimatedMesh core::array Weights; //! Unnecessary for loaders, will be overwritten on finalize - core::matrix4 GlobalMatrix; + core::matrix4 GlobalMatrix; // loaders may still choose to set this (temporarily) to calculate absolute vertex data. core::matrix4 GlobalAnimatedMatrix; core::matrix4 LocalAnimatedMatrix; + + //! These should be set by loaders. core::vector3df Animatedposition; core::vector3df Animatedscale; core::quaternion Animatedrotation; - core::matrix4 GlobalInversedMatrix; // the x format pre-calculates this - + // The .x and .gltf formats pre-calculate this + std::optional GlobalInversedMatrix; private: //! Internal members used by CSkinnedMesh friend class CSkinnedMesh; diff --git a/irr/src/CB3DMeshFileLoader.cpp b/irr/src/CB3DMeshFileLoader.cpp index 66ad64a6f..edce3f1d8 100644 --- a/irr/src/CB3DMeshFileLoader.cpp +++ b/irr/src/CB3DMeshFileLoader.cpp @@ -389,6 +389,7 @@ bool CB3DMeshFileLoader::readChunkVRTS(CSkinnedMesh::SJoint *inJoint) // Transform the Vertex position by nested node... inJoint->GlobalMatrix.transformVect(Vertex.Pos); inJoint->GlobalMatrix.rotateAndScaleVect(Vertex.Normal); + Vertex.Normal.normalize(); // renormalize: normal might have been skewed by scaling // Add it... BaseVertices.push_back(Vertex); diff --git a/irr/src/CSkinnedMesh.cpp b/irr/src/CSkinnedMesh.cpp index 5e1452601..9e2e399da 100644 --- a/irr/src/CSkinnedMesh.cpp +++ b/irr/src/CSkinnedMesh.cpp @@ -222,6 +222,7 @@ void CSkinnedMesh::buildAllLocalAnimatedMatrices() // IRR_TEST_BROKEN_QUATERNION_USE: TODO - switched to getMatrix_transposed instead of getMatrix for downward compatibility. // Not tested so far if this was correct or wrong before quaternion fix! + // Note that using getMatrix_transposed inverts the rotation. joint->Animatedrotation.getMatrix_transposed(joint->LocalAnimatedMatrix); // --- joint->LocalAnimatedMatrix *= joint->Animatedrotation.getMatrix() --- @@ -496,8 +497,7 @@ void CSkinnedMesh::skinJoint(SJoint *joint, SJoint *parentJoint) { if (joint->Weights.size()) { // Find this joints pull on vertices... - core::matrix4 jointVertexPull(core::matrix4::EM4CONST_NOTHING); - jointVertexPull.setbyproduct(joint->GlobalAnimatedMatrix, joint->GlobalInversedMatrix); + core::matrix4 jointVertexPull = joint->GlobalAnimatedMatrix * joint->GlobalInversedMatrix.value(); core::vector3df thisVertexMove, thisNormalMove; @@ -510,8 +510,10 @@ void CSkinnedMesh::skinJoint(SJoint *joint, SJoint *parentJoint) // Pull this vertex... jointVertexPull.transformVect(thisVertexMove, weight.StaticPos); - if (AnimateNormals) + if (AnimateNormals) { jointVertexPull.rotateAndScaleVect(thisNormalMove = weight.StaticNormal); + thisNormalMove.normalize(); // must renormalize after potentially scaling + } if (!(*(weight.Moved))) { *(weight.Moved) = true; @@ -755,9 +757,9 @@ void CSkinnedMesh::calculateGlobalMatrices(SJoint *joint, SJoint *parentJoint) joint->LocalAnimatedMatrix = joint->LocalMatrix; joint->GlobalAnimatedMatrix = joint->GlobalMatrix; - if (joint->GlobalInversedMatrix.isIdentity()) { // might be pre calculated + if (joint->GlobalInversedMatrix.has_value()) { // might be pre calculated joint->GlobalInversedMatrix = joint->GlobalMatrix; - joint->GlobalInversedMatrix.makeInverse(); // slow + joint->GlobalInversedMatrix->makeInverse(); // slow } for (u32 j = 0; j < joint->Children.size(); ++j) diff --git a/irr/src/CXMeshFileLoader.cpp b/irr/src/CXMeshFileLoader.cpp index 5978980f4..c32f01299 100644 --- a/irr/src/CXMeshFileLoader.cpp +++ b/irr/src/CXMeshFileLoader.cpp @@ -994,9 +994,9 @@ bool CXMeshFileLoader::parseDataObjectSkinWeights(SXMesh &mesh) // transforms the mesh vertices to the space of the bone // When concatenated to the bone's transform, this provides the // world space coordinates of the mesh as affected by the bone - core::matrix4 &MatrixOffset = joint->GlobalInversedMatrix; - + core::matrix4 MatrixOffset; readMatrix(MatrixOffset); + joint->GlobalInversedMatrix = MatrixOffset; if (!checkForOneFollowingSemicolons()) { os::Printer::log("No finishing semicolon in Skin Weights found in x file", ELL_WARNING);