1
0
Fork 0
mirror of https://github.com/luanti-org/luanti.git synced 2025-08-06 17:41:04 +00:00

Do bounding box & matrix calculation at proper point in time

This commit is contained in:
Lars Mueller 2025-01-27 18:21:43 +01:00
parent 07963f1af5
commit 455f7a4cae
2 changed files with 51 additions and 39 deletions

View file

@ -4,6 +4,7 @@
#include "CAnimatedMeshSceneNode.h" #include "CAnimatedMeshSceneNode.h"
#include "CBoneSceneNode.h" #include "CBoneSceneNode.h"
#include "EDebugSceneTypes.h"
#include "IVideoDriver.h" #include "IVideoDriver.h"
#include "ISceneManager.h" #include "ISceneManager.h"
#include "S3DVertex.h" #include "S3DVertex.h"
@ -159,17 +160,8 @@ IMesh *CAnimatedMeshSceneNode::getMeshForCurrentFrame()
auto *skinnedMesh = static_cast<SkinnedMesh *>(Mesh); auto *skinnedMesh = static_cast<SkinnedMesh *>(Mesh);
std::vector<core::matrix4> matrices; // Matrices have already been calculated in OnAnimate
matrices.reserve(JointChildSceneNodes.size()); skinnedMesh->skinMesh(PerJoint.GlobalMatrices);
for (auto *node : JointChildSceneNodes)
matrices.push_back(node->getRelativeTransformation());
skinnedMesh->calculateGlobalMatrices(matrices);
skinnedMesh->skinMesh(matrices);
// TODO this should have happened *before* the skinning in OnAnimate;
// we should thus probably store the global matrices.
Box = skinnedMesh->calculateBoundingBox(matrices);
return skinnedMesh; return skinnedMesh;
} }
@ -192,6 +184,13 @@ void CAnimatedMeshSceneNode::OnAnimate(u32 timeMs)
OnAnimateCallback(timeMs / 1000.0f); OnAnimateCallback(timeMs / 1000.0f);
IAnimatedMeshSceneNode::OnAnimate(timeMs); IAnimatedMeshSceneNode::OnAnimate(timeMs);
if (auto *skinnedMesh = dynamic_cast<SkinnedMesh*>(Mesh)) {
for (u16 i = 0; i < PerJoint.SceneNodes.size(); ++i)
PerJoint.GlobalMatrices[i] = PerJoint.SceneNodes[i]->getRelativeTransformation();
skinnedMesh->calculateGlobalMatrices(PerJoint.GlobalMatrices);
Box = skinnedMesh->calculateBoundingBox(PerJoint.GlobalMatrices);
}
} }
//! renders the node. //! renders the node.
@ -389,12 +388,12 @@ IBoneSceneNode *CAnimatedMeshSceneNode::getJointNode(const c8 *jointName)
return 0; return 0;
} }
if (JointChildSceneNodes.size() <= *number) { if (PerJoint.SceneNodes.size() <= *number) {
os::Printer::log("Joint was found in mesh, but is not loaded into node", jointName, ELL_WARNING); os::Printer::log("Joint was found in mesh, but is not loaded into node", jointName, ELL_WARNING);
return 0; return 0;
} }
return JointChildSceneNodes[*number]; return PerJoint.SceneNodes[*number];
} }
//! Returns a pointer to a child node, which has the same transformation as //! Returns a pointer to a child node, which has the same transformation as
@ -408,12 +407,12 @@ IBoneSceneNode *CAnimatedMeshSceneNode::getJointNode(u32 jointID)
checkJoints(); checkJoints();
if (JointChildSceneNodes.size() <= jointID) { if (PerJoint.SceneNodes.size() <= jointID) {
os::Printer::log("Joint not loaded into node", ELL_WARNING); os::Printer::log("Joint not loaded into node", ELL_WARNING);
return 0; return 0;
} }
return JointChildSceneNodes[jointID]; return PerJoint.SceneNodes[jointID];
} }
//! Gets joint count. //! Gets joint count.
@ -434,9 +433,9 @@ bool CAnimatedMeshSceneNode::removeChild(ISceneNode *child)
{ {
if (ISceneNode::removeChild(child)) { if (ISceneNode::removeChild(child)) {
if (JointsUsed) { // stop weird bugs caused while changing parents as the joints are being created if (JointsUsed) { // stop weird bugs caused while changing parents as the joints are being created
for (u32 i = 0; i < JointChildSceneNodes.size(); ++i) { for (u32 i = 0; i < PerJoint.SceneNodes.size(); ++i) {
if (JointChildSceneNodes[i] == child) { if (PerJoint.SceneNodes[i] == child) {
JointChildSceneNodes[i] = 0; // remove link to child PerJoint.SceneNodes[i] = 0; // remove link to child
break; break;
} }
} }
@ -538,18 +537,17 @@ void CAnimatedMeshSceneNode::setRenderFromIdentity(bool enable)
void CAnimatedMeshSceneNode::addJoints() void CAnimatedMeshSceneNode::addJoints()
{ {
const auto &joints = static_cast<SkinnedMesh*>(Mesh)->getAllJoints(); const auto &joints = static_cast<SkinnedMesh*>(Mesh)->getAllJoints();
JointChildSceneNodes.clear(); PerJoint.setN(joints.size());
JointChildSceneNodes.reserve(joints.size()); PerJoint.SceneNodes.clear();
PretransitingSave.clear(); PerJoint.SceneNodes.reserve(joints.size());
PretransitingSave.resize(JointChildSceneNodes.size());
for (size_t i = 0; i < joints.size(); ++i) { for (size_t i = 0; i < joints.size(); ++i) {
const auto *joint = joints[i]; const auto *joint = joints[i];
ISceneNode *parent = this; ISceneNode *parent = this;
if (joint->ParentJointID) if (joint->ParentJointID)
parent = JointChildSceneNodes.at(*joint->ParentJointID); // exists because of topo. order parent = PerJoint.SceneNodes.at(*joint->ParentJointID); // exists because of topo. order
assert(parent); assert(parent);
const auto *matrix = std::get_if<core::matrix4>(&joint->transform); const auto *matrix = std::get_if<core::matrix4>(&joint->transform);
JointChildSceneNodes.push_back(new CBoneSceneNode( PerJoint.SceneNodes.push_back(new CBoneSceneNode(
parent, SceneManager, 0, i, joint->Name, parent, SceneManager, 0, i, joint->Name,
matrix ? core::Transform{} : std::get<core::Transform>(joint->transform), matrix ? core::Transform{} : std::get<core::Transform>(joint->transform),
matrix ? *matrix : std::optional<core::matrix4>{})); matrix ? *matrix : std::optional<core::matrix4>{}));
@ -561,7 +559,7 @@ void CAnimatedMeshSceneNode::updateJointSceneNodes(
{ {
for (size_t i = 0; i < transforms.size(); ++i) { for (size_t i = 0; i < transforms.size(); ++i) {
const auto &transform = transforms[i]; const auto &transform = transforms[i];
auto *node = static_cast<CBoneSceneNode*>(JointChildSceneNodes[i]); auto *node = static_cast<CBoneSceneNode*>(PerJoint.SceneNodes[i]);
if (const auto *trs = std::get_if<core::Transform>(&transform)) { if (const auto *trs = std::get_if<core::Transform>(&transform)) {
node->setTransform(*trs); node->setTransform(*trs);
// .x lets animations override matrix transforms entirely. // .x lets animations override matrix transforms entirely.
@ -589,10 +587,10 @@ void CAnimatedMeshSceneNode::animateJoints()
//----------------------------------------- //-----------------------------------------
if (Transiting != 0.f) { if (Transiting != 0.f) {
for (u32 i = 0; i < JointChildSceneNodes.size(); ++i) { for (u32 i = 0; i < PerJoint.SceneNodes.size(); ++i) {
if (PretransitingSave[i]) { if (PerJoint.PreTransSaves[i]) {
JointChildSceneNodes[i]->setTransform(PretransitingSave[i]->interpolate( PerJoint.SceneNodes[i]->setTransform(PerJoint.PreTransSaves[i]->interpolate(
JointChildSceneNodes[i]->getTransform(), TransitingBlend)); PerJoint.SceneNodes[i]->getTransform(), TransitingBlend));
} }
} }
} }
@ -604,8 +602,8 @@ void CAnimatedMeshSceneNode::checkJoints()
return; return;
if (!JointsUsed) { if (!JointsUsed) {
for (u32 i = 0; i < JointChildSceneNodes.size(); ++i) for (u32 i = 0; i < PerJoint.SceneNodes.size(); ++i)
removeChild(JointChildSceneNodes[i]); removeChild(PerJoint.SceneNodes[i]);
addJoints(); addJoints();
JointsUsed = true; JointsUsed = true;
@ -619,11 +617,11 @@ void CAnimatedMeshSceneNode::beginTransition()
if (TransitionTime != 0) { if (TransitionTime != 0) {
// Copy the transforms of animated joints // Copy the transforms of animated joints
for (u32 i = 0; i < JointChildSceneNodes.size(); ++i) { for (u32 i = 0; i < PerJoint.SceneNodes.size(); ++i) {
if (!JointChildSceneNodes[i]->Matrix) { if (!PerJoint.SceneNodes[i]->Matrix) {
PretransitingSave[i] = JointChildSceneNodes[i]->getTransform(); PerJoint.PreTransSaves[i] = PerJoint.SceneNodes[i]->getTransform();
} else { } else {
PretransitingSave[i] = std::nullopt; PerJoint.PreTransSaves[i] = std::nullopt;
} }
} }
@ -664,8 +662,8 @@ ISceneNode *CAnimatedMeshSceneNode::clone(ISceneNode *newParent, ISceneManager *
newNode->Looping = Looping; newNode->Looping = Looping;
newNode->ReadOnlyMaterials = ReadOnlyMaterials; newNode->ReadOnlyMaterials = ReadOnlyMaterials;
newNode->PassCount = PassCount; newNode->PassCount = PassCount;
newNode->JointChildSceneNodes = JointChildSceneNodes; newNode->PerJoint.SceneNodes = PerJoint.SceneNodes;
newNode->PretransitingSave = PretransitingSave; newNode->PerJoint.PreTransSaves = PerJoint.PreTransSaves;
newNode->RenderFromIdentity = RenderFromIdentity; newNode->RenderFromIdentity = RenderFromIdentity;
return newNode; return newNode;

View file

@ -10,6 +10,7 @@
#include "SkinnedMesh.h" #include "SkinnedMesh.h"
#include "Transform.h" #include "Transform.h"
#include "matrix4.h"
namespace irr namespace irr
{ {
@ -172,8 +173,21 @@ private:
s32 PassCount; s32 PassCount;
std::function<void(f32)> OnAnimateCallback; std::function<void(f32)> OnAnimateCallback;
std::vector<CBoneSceneNode *> JointChildSceneNodes; struct PerJointData {
std::vector<std::optional<core::Transform>> PretransitingSave; std::vector<CBoneSceneNode *> SceneNodes;
std::vector<core::matrix4> GlobalMatrices;
std::vector<std::optional<core::Transform>> PreTransSaves;
void setN(u16 n) {
SceneNodes.clear();
SceneNodes.resize(n);
GlobalMatrices.clear();
GlobalMatrices.resize(n);
PreTransSaves.clear();
PreTransSaves.resize(n);
}
};
PerJointData PerJoint;
}; };
} // end namespace scene } // end namespace scene