1
0
Fork 0
mirror of https://github.com/luanti-org/luanti.git synced 2025-06-27 16:36:03 +00:00
This commit is contained in:
Lars Mueller 2025-01-26 00:44:14 +01:00
parent 8c00f403f1
commit 4dacb66693
3 changed files with 20 additions and 14 deletions

View file

@ -75,7 +75,7 @@ public:
//! Turns the given array of local matrices into an array of global matrices //! Turns the given array of local matrices into an array of global matrices
//! by multiplying with respective parent matrices. //! by multiplying with respective parent matrices.
void calculateGlobalMatrices(std::vector<core::matrix4> &matrices); void calculateGlobalMatrices(std::vector<core::matrix4> &matrices) const;
//! Performs a software skin on this mesh based on the given joint matrices //! Performs a software skin on this mesh based on the given joint matrices
void skinMesh(const std::vector<core::matrix4> &animated_transforms); void skinMesh(const std::vector<core::matrix4> &animated_transforms);

View file

@ -514,6 +514,8 @@ bool CXMeshFileLoader::parseDataObjectFrame(SkinnedMesh::SJoint *Parent)
if (n.has_value()) { if (n.has_value()) {
JointID = *n; JointID = *n;
joint = AnimatedMesh->getAllJoints()[JointID]; joint = AnimatedMesh->getAllJoints()[JointID];
if (Parent)
joint->ParentJointID = Parent->JointID;
} }
} }

View file

@ -265,7 +265,7 @@ void SkinnedMesh::resetAnimation()
//! Turns the given array of local matrices into an array of global matrices //! Turns the given array of local matrices into an array of global matrices
//! by multiplying with respective parent matrices. //! by multiplying with respective parent matrices.
void SkinnedMesh::calculateGlobalMatrices(std::vector<core::matrix4> &matrices) void SkinnedMesh::calculateGlobalMatrices(std::vector<core::matrix4> &matrices) const
{ {
// Note that the joints are topologically sorted. // Note that the joints are topologically sorted.
for (u16 i = 0; i < AllJoints.size(); ++i) { for (u16 i = 0; i < AllJoints.size(); ++i) {
@ -409,40 +409,45 @@ void SkinnedMesh::recalculateBaseBoundingBoxes() {
calculateBufferBoundingBoxes(); calculateBufferBoundingBoxes();
} }
// TODO this can be removed: Our API guarantees topo sorting if we prevent mutation
void SkinnedMesh::topoSortJoints() void SkinnedMesh::topoSortJoints()
{ {
size_t n = AllJoints.size(); size_t n = AllJoints.size();
std::vector<u16> permutation; // new id -> old id std::vector<u16> new_to_old_id; // new id -> old id
std::vector<std::vector<u16>> children(AllJoints.size()); std::vector<std::vector<u16>> children(n);
for (u16 i = 0; i < n; ++i) { for (u16 i = 0; i < n; ++i) {
if (auto parentId = AllJoints[i]->ParentJointID) if (auto parentId = AllJoints[i]->ParentJointID)
children[*parentId].push_back(i); children[*parentId].push_back(i);
else else
permutation.push_back(i); new_to_old_id.push_back(i);
} }
// Levelorder // Levelorder
for (u16 i = 0; i < n; ++i) { for (u16 i = 0; i < n; ++i) {
permutation.insert(permutation.end(), new_to_old_id.insert(new_to_old_id.end(),
children[i].begin(), children[i].end()); children[new_to_old_id[i]].begin(),
children[new_to_old_id[i]].end());
} }
// old id -> new id // old id -> new id
std::vector<u16> inverse_permutation(n); std::vector<u16> old_to_new_id(n);
for (u16 i = 0; i < n; ++i) for (u16 i = 0; i < n; ++i)
inverse_permutation[permutation[i]] = i; old_to_new_id[new_to_old_id[i]] = i;
std::vector<SJoint *> joints(n); std::vector<SJoint *> joints(n);
for (u16 i = 0; i < n; ++i) { for (u16 i = 0; i < n; ++i) {
joints[i] = AllJoints[permutation[i]]; joints[i] = AllJoints[new_to_old_id[i]];
joints[i]->JointID = i; joints[i]->JointID = i;
if (auto parentId = joints[i]->ParentJointID) if (auto parentId = joints[i]->ParentJointID)
joints[i]->ParentJointID = inverse_permutation[*parentId]; joints[i]->ParentJointID = old_to_new_id[*parentId];
}
AllJoints = std::move(joints);
for (u16 i = 0; i < n; ++i) {
if (auto pjid = AllJoints[i]->ParentJointID)
assert(*pjid < i);
} }
AllJoints = joints;
} }
//! called by loader after populating with mesh and bone data //! called by loader after populating with mesh and bone data
@ -469,7 +474,6 @@ SkinnedMesh *SkinnedMeshBuilder::finalize()
} }
calculateGlobalMatrices(matrices); calculateGlobalMatrices(matrices);
for (size_t i = 0; i < AllJoints.size(); ++i) { for (size_t i = 0; i < AllJoints.size(); ++i) {
auto *joint = AllJoints[i]; auto *joint = AllJoints[i];
if (!joint->GlobalInversedMatrix) { if (!joint->GlobalInversedMatrix) {