mirror of
https://github.com/luanti-org/luanti.git
synced 2025-06-27 16:36:03 +00:00
stuff
This commit is contained in:
parent
769c472ceb
commit
abc2e54c07
16 changed files with 137 additions and 224 deletions
|
@ -135,7 +135,7 @@ public:
|
||||||
|
|
||||||
//! animates the joints in the mesh based on the current frame.
|
//! animates the joints in the mesh based on the current frame.
|
||||||
/** Also takes in to account transitions. */
|
/** Also takes in to account transitions. */
|
||||||
virtual void animateJoints(bool CalculateAbsolutePositions = true) = 0;
|
virtual void animateJoints() = 0;
|
||||||
|
|
||||||
//! render mesh ignoring its transformation.
|
//! render mesh ignoring its transformation.
|
||||||
/** Culling is unaffected. */
|
/** Culling is unaffected. */
|
||||||
|
|
|
@ -28,15 +28,9 @@ public:
|
||||||
//! Returns the relative transformation of the scene node.
|
//! Returns the relative transformation of the scene node.
|
||||||
// virtual core::matrix4 getRelativeTransformation() const = 0;
|
// virtual core::matrix4 getRelativeTransformation() const = 0;
|
||||||
|
|
||||||
//! The animation method.
|
|
||||||
void OnAnimate(u32 timeMs) override = 0;
|
|
||||||
|
|
||||||
//! The render method.
|
//! The render method.
|
||||||
/** Does nothing as bones are not visible. */
|
/** Does nothing as bones are not visible. */
|
||||||
void render() override {}
|
void render() override {}
|
||||||
|
|
||||||
//! Updates the absolute position based on the relative and the parents position
|
|
||||||
virtual void updateAbsolutePositionOfAllChildren() = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end namespace scene
|
} // end namespace scene
|
||||||
|
|
|
@ -94,16 +94,12 @@ public:
|
||||||
\param timeMs Current time in milliseconds. */
|
\param timeMs Current time in milliseconds. */
|
||||||
virtual void OnAnimate(u32 timeMs)
|
virtual void OnAnimate(u32 timeMs)
|
||||||
{
|
{
|
||||||
if (IsVisible) {
|
if (!IsVisible && Children.empty())
|
||||||
// update absolute position
|
return;
|
||||||
updateAbsolutePosition();
|
|
||||||
|
|
||||||
// perform the post render process on all children
|
updateAbsolutePosition();
|
||||||
|
for (auto *child : Children)
|
||||||
ISceneNodeList::iterator it = Children.begin();
|
child->OnAnimate(timeMs);
|
||||||
for (; it != Children.end(); ++it)
|
|
||||||
(*it)->OnAnimate(timeMs);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Renders the node.
|
//! Renders the node.
|
||||||
|
|
|
@ -8,11 +8,14 @@
|
||||||
#include "ISceneManager.h"
|
#include "ISceneManager.h"
|
||||||
#include "SMeshBuffer.h"
|
#include "SMeshBuffer.h"
|
||||||
#include "SSkinMeshBuffer.h"
|
#include "SSkinMeshBuffer.h"
|
||||||
|
#include "irrMath.h"
|
||||||
|
#include "matrix4.h"
|
||||||
#include "quaternion.h"
|
#include "quaternion.h"
|
||||||
#include "vector3d.h"
|
#include "vector3d.h"
|
||||||
|
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <variant>
|
||||||
|
|
||||||
namespace irr
|
namespace irr
|
||||||
{
|
{
|
||||||
|
@ -314,8 +317,56 @@ public:
|
||||||
//! The name of this joint
|
//! The name of this joint
|
||||||
std::optional<std::string> Name;
|
std::optional<std::string> Name;
|
||||||
|
|
||||||
//! Local matrix of this joint
|
struct Transform {
|
||||||
core::matrix4 LocalMatrix;
|
core::vector3df translation;
|
||||||
|
core::quaternion rotation;
|
||||||
|
core::vector3df scale{1};
|
||||||
|
|
||||||
|
core::matrix4 buildMatrix() const {
|
||||||
|
core::matrix4 T;
|
||||||
|
T.setTranslation(translation);
|
||||||
|
core::matrix4 R;
|
||||||
|
rotation.getMatrix_transposed(R);
|
||||||
|
core::matrix4 S;
|
||||||
|
S.setScale(scale);
|
||||||
|
return T * R * S;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//! Local transformation to be set by loaders. Mutated by animation.
|
||||||
|
//! If a matrix is used, this joint **must not** be animated,
|
||||||
|
//! because then the unique decomposition into translation, rotation and scale need not exist!
|
||||||
|
std::variant<core::matrix4, Transform> transform = Transform{};
|
||||||
|
|
||||||
|
Transform &getAnimatableTransform() {
|
||||||
|
if (std::holds_alternative<Transform>(transform))
|
||||||
|
return std::get<Transform>(transform);
|
||||||
|
const auto &mat = std::get<core::matrix4>(transform);
|
||||||
|
Transform trs;
|
||||||
|
trs.translation = mat.getTranslation();
|
||||||
|
trs.scale = mat.getScale();
|
||||||
|
trs.rotation = core::quaternion(
|
||||||
|
mat.getRotationDegrees(trs.scale) * core::DEGTORAD);
|
||||||
|
transform = trs;
|
||||||
|
// TODO raise a warning if the recomposed matrix does not equal the decomposed.
|
||||||
|
return std::get<Transform>(transform);
|
||||||
|
}
|
||||||
|
|
||||||
|
void animate(f32 frame) {
|
||||||
|
if (keys.empty())
|
||||||
|
return;
|
||||||
|
auto &transform = getAnimatableTransform();
|
||||||
|
keys.updateTransform(frame,
|
||||||
|
transform.translation,
|
||||||
|
transform.rotation,
|
||||||
|
transform.scale);
|
||||||
|
}
|
||||||
|
|
||||||
|
core::matrix4 buildLocalMatrix() const {
|
||||||
|
if (std::holds_alternative<core::matrix4>(transform))
|
||||||
|
return std::get<core::matrix4>(transform);
|
||||||
|
return std::get<Transform>(transform).buildMatrix();
|
||||||
|
}
|
||||||
|
|
||||||
//! List of child joints
|
//! List of child joints
|
||||||
std::vector<SJoint *> Children;
|
std::vector<SJoint *> Children;
|
||||||
|
@ -334,11 +385,6 @@ public:
|
||||||
core::matrix4 GlobalAnimatedMatrix;
|
core::matrix4 GlobalAnimatedMatrix;
|
||||||
core::matrix4 LocalAnimatedMatrix;
|
core::matrix4 LocalAnimatedMatrix;
|
||||||
|
|
||||||
//! These should be set by loaders.
|
|
||||||
core::vector3df Animatedposition;
|
|
||||||
core::vector3df Animatedscale;
|
|
||||||
core::quaternion Animatedrotation;
|
|
||||||
|
|
||||||
// The .x and .gltf formats pre-calculate this
|
// The .x and .gltf formats pre-calculate this
|
||||||
std::optional<core::matrix4> GlobalInversedMatrix;
|
std::optional<core::matrix4> GlobalInversedMatrix;
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -170,7 +170,11 @@ IMesh *CAnimatedMeshSceneNode::getMeshForCurrentFrame()
|
||||||
// Update the skinned mesh for the current joint transforms.
|
// Update the skinned mesh for the current joint transforms.
|
||||||
skinnedMesh->skinMesh();
|
skinnedMesh->skinMesh();
|
||||||
|
|
||||||
skinnedMesh->updateBoundingBox();
|
skinnedMesh->updateBoundingBox();
|
||||||
|
|
||||||
|
Box = skinnedMesh->getBoundingBox();
|
||||||
|
|
||||||
|
setAutomaticCulling(EAC_OFF);
|
||||||
|
|
||||||
return skinnedMesh;
|
return skinnedMesh;
|
||||||
}
|
}
|
||||||
|
@ -187,6 +191,10 @@ void CAnimatedMeshSceneNode::OnAnimate(u32 timeMs)
|
||||||
buildFrameNr(timeMs - LastTimeMs);
|
buildFrameNr(timeMs - LastTimeMs);
|
||||||
LastTimeMs = timeMs;
|
LastTimeMs = timeMs;
|
||||||
|
|
||||||
|
// This needs to be done on animate, which is called recursively *before*
|
||||||
|
// anything is rendered so that the transformations of children are up to date
|
||||||
|
animateJoints();
|
||||||
|
|
||||||
IAnimatedMeshSceneNode::OnAnimate(timeMs);
|
IAnimatedMeshSceneNode::OnAnimate(timeMs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -204,15 +212,8 @@ void CAnimatedMeshSceneNode::render()
|
||||||
++PassCount;
|
++PassCount;
|
||||||
|
|
||||||
scene::IMesh *m = getMeshForCurrentFrame();
|
scene::IMesh *m = getMeshForCurrentFrame();
|
||||||
|
_IRR_DEBUG_BREAK_IF(!m);
|
||||||
if (m) {
|
Box = m->getBoundingBox(); // HACK
|
||||||
Box = m->getBoundingBox();
|
|
||||||
} else {
|
|
||||||
#ifdef _DEBUG
|
|
||||||
os::Printer::log("Animated Mesh returned no mesh to render.", ELL_WARNING);
|
|
||||||
#endif
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
|
driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
|
||||||
|
|
||||||
|
@ -237,6 +238,7 @@ void CAnimatedMeshSceneNode::render()
|
||||||
driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
|
driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
|
||||||
|
|
||||||
// for debug purposes only:
|
// for debug purposes only:
|
||||||
|
// DebugDataVisible = ~0;
|
||||||
if (DebugDataVisible && PassCount == 1) {
|
if (DebugDataVisible && PassCount == 1) {
|
||||||
video::SMaterial debug_mat;
|
video::SMaterial debug_mat;
|
||||||
debug_mat.AntiAliasing = video::EAAM_OFF;
|
debug_mat.AntiAliasing = video::EAAM_OFF;
|
||||||
|
@ -559,7 +561,7 @@ void CAnimatedMeshSceneNode::setRenderFromIdentity(bool enable)
|
||||||
}
|
}
|
||||||
|
|
||||||
//! updates the joint positions of this mesh
|
//! updates the joint positions of this mesh
|
||||||
void CAnimatedMeshSceneNode::animateJoints(bool CalculateAbsolutePositions)
|
void CAnimatedMeshSceneNode::animateJoints()
|
||||||
{
|
{
|
||||||
if (Mesh && Mesh->getMeshType() == EAMT_SKINNED) {
|
if (Mesh && Mesh->getMeshType() == EAMT_SKINNED) {
|
||||||
checkJoints();
|
checkJoints();
|
||||||
|
@ -614,15 +616,6 @@ void CAnimatedMeshSceneNode::animateJoints(bool CalculateAbsolutePositions)
|
||||||
// TransitingBlend));
|
// TransitingBlend));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CalculateAbsolutePositions) {
|
|
||||||
//---slow---
|
|
||||||
for (u32 n = 0; n < JointChildSceneNodes.size(); ++n) {
|
|
||||||
if (JointChildSceneNodes[n]->getParent() == this) {
|
|
||||||
JointChildSceneNodes[n]->updateAbsolutePositionOfAllChildren(); // temp, should be an option
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -117,12 +117,12 @@ public:
|
||||||
//! updates the absolute position based on the relative and the parents position
|
//! updates the absolute position based on the relative and the parents position
|
||||||
void updateAbsolutePosition() override;
|
void updateAbsolutePosition() override;
|
||||||
|
|
||||||
//! Sets the transition time in seconds (note: This needs to enable joints, and setJointmode maybe set to 2)
|
//! Sets the transition time in seconds (note: This needs to enable joints)
|
||||||
//! you must call animateJoints(), or the mesh will not animate
|
//! you must call animateJoints(), or the mesh will not animate
|
||||||
void setTransitionTime(f32 Time) override;
|
void setTransitionTime(f32 Time) override;
|
||||||
|
|
||||||
//! updates the joint positions of this mesh
|
//! updates the joint positions of this mesh
|
||||||
void animateJoints(bool CalculateAbsolutePositions = true) override;
|
void animateJoints() override;
|
||||||
|
|
||||||
//! render mesh ignoring its transformation. Used with ragdolls. (culling is unaffected)
|
//! render mesh ignoring its transformation. Used with ragdolls. (culling is unaffected)
|
||||||
void setRenderFromIdentity(bool On) override;
|
void setRenderFromIdentity(bool On) override;
|
||||||
|
|
|
@ -143,31 +143,25 @@ bool CB3DMeshFileLoader::readChunkNODE(SkinnedMesh::SJoint *inJoint)
|
||||||
os::Printer::log(logStr.c_str(), joint->Name.value_or("").c_str(), ELL_DEBUG);
|
os::Printer::log(logStr.c_str(), joint->Name.value_or("").c_str(), ELL_DEBUG);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
f32 position[3], scale[3], rotation[4];
|
SkinnedMesh::SJoint::Transform transform;
|
||||||
|
{
|
||||||
|
f32 t[3], s[3], r[4];
|
||||||
|
|
||||||
readFloats(position, 3);
|
readFloats(t, 3);
|
||||||
readFloats(scale, 3);
|
readFloats(s, 3);
|
||||||
readFloats(rotation, 4);
|
readFloats(r, 4);
|
||||||
|
|
||||||
joint->Animatedposition = core::vector3df(position[0], position[1], position[2]);
|
joint->transform = transform = {
|
||||||
joint->Animatedscale = core::vector3df(scale[0], scale[1], scale[2]);
|
{t[0], t[1], t[2]},
|
||||||
joint->Animatedrotation = core::quaternion(rotation[1], rotation[2], rotation[3], rotation[0]);
|
{r[1], r[2], r[3], r[0]},
|
||||||
|
{s[0], s[1], s[2]},
|
||||||
// Build LocalMatrix:
|
};
|
||||||
|
}
|
||||||
core::matrix4 positionMatrix;
|
|
||||||
positionMatrix.setTranslation(joint->Animatedposition);
|
|
||||||
core::matrix4 scaleMatrix;
|
|
||||||
scaleMatrix.setScale(joint->Animatedscale);
|
|
||||||
core::matrix4 rotationMatrix;
|
|
||||||
joint->Animatedrotation.getMatrix_transposed(rotationMatrix);
|
|
||||||
|
|
||||||
joint->LocalMatrix = positionMatrix * rotationMatrix * scaleMatrix;
|
|
||||||
|
|
||||||
if (inJoint)
|
if (inJoint)
|
||||||
joint->GlobalMatrix = inJoint->GlobalMatrix * joint->LocalMatrix;
|
joint->GlobalMatrix = inJoint->GlobalMatrix * joint->buildLocalMatrix();
|
||||||
else
|
else
|
||||||
joint->GlobalMatrix = joint->LocalMatrix;
|
joint->GlobalMatrix = joint->buildLocalMatrix();
|
||||||
|
|
||||||
while (B3dStack.getLast().startposition + B3dStack.getLast().length > B3DFile->getPos()) // this chunk repeats
|
while (B3dStack.getLast().startposition + B3dStack.getLast().length > B3DFile->getPos()) // this chunk repeats
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,43 +0,0 @@
|
||||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
|
||||||
// This file is part of the "Irrlicht Engine".
|
|
||||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
|
||||||
|
|
||||||
#include "CBoneSceneNode.h"
|
|
||||||
|
|
||||||
#include <optional>
|
|
||||||
|
|
||||||
namespace irr
|
|
||||||
{
|
|
||||||
namespace scene
|
|
||||||
{
|
|
||||||
|
|
||||||
void CBoneSceneNode::OnAnimate(u32 timeMs)
|
|
||||||
{
|
|
||||||
if (IsVisible) {
|
|
||||||
// update absolute position
|
|
||||||
// updateAbsolutePosition();
|
|
||||||
|
|
||||||
// perform the post render process on all children
|
|
||||||
ISceneNodeList::iterator it = Children.begin();
|
|
||||||
for (; it != Children.end(); ++it)
|
|
||||||
(*it)->OnAnimate(timeMs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CBoneSceneNode::helper_updateAbsolutePositionOfAllChildren(ISceneNode *Node)
|
|
||||||
{
|
|
||||||
Node->updateAbsolutePosition();
|
|
||||||
|
|
||||||
ISceneNodeList::const_iterator it = Node->getChildren().begin();
|
|
||||||
for (; it != Node->getChildren().end(); ++it) {
|
|
||||||
helper_updateAbsolutePositionOfAllChildren((*it));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CBoneSceneNode::updateAbsolutePositionOfAllChildren()
|
|
||||||
{
|
|
||||||
helper_updateAbsolutePositionOfAllChildren(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace scene
|
|
||||||
} // namespace irr
|
|
|
@ -40,13 +40,6 @@ public:
|
||||||
return Box;
|
return Box;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnAnimate(u32 timeMs) override;
|
|
||||||
|
|
||||||
void updateAbsolutePositionOfAllChildren() override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void helper_updateAbsolutePositionOfAllChildren(ISceneNode *Node);
|
|
||||||
|
|
||||||
const u32 BoneIndex;
|
const u32 BoneIndex;
|
||||||
|
|
||||||
// Bogus box; bone scene nodes are not rendered anyways.
|
// Bogus box; bone scene nodes are not rendered anyways.
|
||||||
|
|
|
@ -539,34 +539,25 @@ static core::matrix4 loadTransform(const tiniergltf::Node::Matrix &m, SkinnedMes
|
||||||
mat[i] = static_cast<f32>(m[i]);
|
mat[i] = static_cast<f32>(m[i]);
|
||||||
mat = convertHandedness(mat);
|
mat = convertHandedness(mat);
|
||||||
|
|
||||||
// Decompose the matrix into translation, scale, and rotation.
|
// Note: "When a node is targeted for animation [...],
|
||||||
joint->Animatedposition = mat.getTranslation();
|
// only TRS properties MAY be present; matrix MUST NOT be present."
|
||||||
|
// Thus we MUST NOT do any decomposition, which in general need not exist.
|
||||||
auto scale = mat.getScale();
|
joint->transform = mat;
|
||||||
joint->Animatedscale = scale;
|
|
||||||
joint->Animatedrotation = mat.getRotationRadians(scale);
|
|
||||||
// Invert the rotation because it is applied using `getMatrix_transposed`,
|
|
||||||
// which again inverts.
|
|
||||||
joint->Animatedrotation.makeInverse();
|
|
||||||
|
|
||||||
return mat;
|
return mat;
|
||||||
}
|
}
|
||||||
|
|
||||||
static core::matrix4 loadTransform(const tiniergltf::Node::TRS &trs, SkinnedMesh::SJoint *joint)
|
static core::matrix4 loadTransform(const tiniergltf::Node::TRS &trs, SkinnedMesh::SJoint *joint)
|
||||||
{
|
{
|
||||||
const auto &trans = trs.translation;
|
const auto &t = trs.translation;
|
||||||
const auto &rot = trs.rotation;
|
const auto &r = trs.rotation;
|
||||||
const auto &scale = trs.scale;
|
const auto &s = trs.scale;
|
||||||
core::matrix4 transMat;
|
SkinnedMesh::SJoint::Transform transform{
|
||||||
joint->Animatedposition = convertHandedness(core::vector3df(trans[0], trans[1], trans[2]));
|
convertHandedness(core::vector3df(t[0], t[1], t[2])),
|
||||||
transMat.setTranslation(joint->Animatedposition);
|
convertHandedness(core::quaternion(r[0], r[1], r[2], r[3])),
|
||||||
core::matrix4 rotMat;
|
core::vector3df(s[0], s[1], s[2]),
|
||||||
joint->Animatedrotation = convertHandedness(core::quaternion(rot[0], rot[1], rot[2], rot[3]));
|
};
|
||||||
core::quaternion(joint->Animatedrotation).getMatrix_transposed(rotMat);
|
joint->transform = transform;
|
||||||
joint->Animatedscale = core::vector3df(scale[0], scale[1], scale[2]);
|
return transform.buildMatrix();
|
||||||
core::matrix4 scaleMat;
|
|
||||||
scaleMat.setScale(joint->Animatedscale);
|
|
||||||
return transMat * rotMat * scaleMat;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static core::matrix4 loadTransform(std::optional<std::variant<tiniergltf::Node::Matrix, tiniergltf::Node::TRS>> transform,
|
static core::matrix4 loadTransform(std::optional<std::variant<tiniergltf::Node::Matrix, tiniergltf::Node::TRS>> transform,
|
||||||
|
@ -584,8 +575,7 @@ void SelfType::MeshExtractor::loadNode(
|
||||||
const auto &node = m_gltf_model.nodes->at(nodeIdx);
|
const auto &node = m_gltf_model.nodes->at(nodeIdx);
|
||||||
auto *joint = m_irr_model->addJoint(parent);
|
auto *joint = m_irr_model->addJoint(parent);
|
||||||
const core::matrix4 transform = loadTransform(node.transform, joint);
|
const core::matrix4 transform = loadTransform(node.transform, joint);
|
||||||
joint->LocalMatrix = transform;
|
joint->GlobalMatrix = parent ? parent->GlobalMatrix * transform : transform;
|
||||||
joint->GlobalMatrix = parent ? parent->GlobalMatrix * joint->LocalMatrix : joint->LocalMatrix;
|
|
||||||
if (node.name.has_value()) {
|
if (node.name.has_value()) {
|
||||||
joint->Name = node.name->c_str();
|
joint->Name = node.name->c_str();
|
||||||
}
|
}
|
||||||
|
|
|
@ -320,7 +320,6 @@ set(IRRMESHLOADER
|
||||||
|
|
||||||
add_library(IRRMESHOBJ OBJECT
|
add_library(IRRMESHOBJ OBJECT
|
||||||
SkinnedMesh.cpp
|
SkinnedMesh.cpp
|
||||||
CBoneSceneNode.cpp
|
|
||||||
CMeshSceneNode.cpp
|
CMeshSceneNode.cpp
|
||||||
CAnimatedMeshSceneNode.cpp
|
CAnimatedMeshSceneNode.cpp
|
||||||
${IRRMESHLOADER}
|
${IRRMESHLOADER}
|
||||||
|
|
|
@ -552,12 +552,9 @@ bool CXMeshFileLoader::parseDataObjectFrame(SkinnedMesh::SJoint *Parent)
|
||||||
if (!parseDataObjectFrame(joint))
|
if (!parseDataObjectFrame(joint))
|
||||||
return false;
|
return false;
|
||||||
} else if (objectName == "FrameTransformMatrix") {
|
} else if (objectName == "FrameTransformMatrix") {
|
||||||
if (!parseDataObjectTransformationMatrix(joint->LocalMatrix))
|
joint->transform = core::matrix4();
|
||||||
|
if (!parseDataObjectTransformationMatrix(std::get<core::matrix4>(joint->transform)))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// joint->LocalAnimatedMatrix
|
|
||||||
// joint->LocalAnimatedMatrix.makeInverse();
|
|
||||||
// joint->LocalMatrix=tmp*joint->LocalAnimatedMatrix;
|
|
||||||
} else if (objectName == "Mesh") {
|
} else if (objectName == "Mesh") {
|
||||||
/*
|
/*
|
||||||
frame.Meshes.push_back(SXMesh());
|
frame.Meshes.push_back(SXMesh());
|
||||||
|
|
|
@ -7,7 +7,11 @@
|
||||||
#include "CBoneSceneNode.h"
|
#include "CBoneSceneNode.h"
|
||||||
#include "IAnimatedMeshSceneNode.h"
|
#include "IAnimatedMeshSceneNode.h"
|
||||||
#include "SSkinMeshBuffer.h"
|
#include "SSkinMeshBuffer.h"
|
||||||
|
#include "irrMath.h"
|
||||||
|
#include "matrix4.h"
|
||||||
#include "os.h"
|
#include "os.h"
|
||||||
|
#include "vector3d.h"
|
||||||
|
#include <variant>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
|
@ -73,13 +77,8 @@ void SkinnedMesh::animateMesh(f32 frame)
|
||||||
LastAnimatedFrame = frame;
|
LastAnimatedFrame = frame;
|
||||||
SkinnedLastFrame = false;
|
SkinnedLastFrame = false;
|
||||||
|
|
||||||
for (auto *joint : AllJoints) {
|
for (auto *joint : AllJoints)
|
||||||
// The joints can be animated here with no input from their parents
|
joint->animate(frame);
|
||||||
joint->keys.updateTransform(frame,
|
|
||||||
joint->Animatedposition,
|
|
||||||
joint->Animatedrotation,
|
|
||||||
joint->Animatedscale);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Note:
|
// Note:
|
||||||
// LocalAnimatedMatrix needs to be built at some point, but this function may be called lots of times for
|
// LocalAnimatedMatrix needs to be built at some point, but this function may be called lots of times for
|
||||||
|
@ -98,56 +97,7 @@ void SkinnedMesh::buildAllLocalAnimatedMatrices()
|
||||||
{
|
{
|
||||||
for (auto *joint : AllJoints) {
|
for (auto *joint : AllJoints) {
|
||||||
// Could be faster:
|
// Could be faster:
|
||||||
|
joint->LocalAnimatedMatrix = joint->buildLocalMatrix();
|
||||||
if (!joint->keys.empty()) {
|
|
||||||
// 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() ---
|
|
||||||
f32 *m1 = joint->LocalAnimatedMatrix.pointer();
|
|
||||||
core::vector3df &Pos = joint->Animatedposition;
|
|
||||||
m1[0] += Pos.X * m1[3];
|
|
||||||
m1[1] += Pos.Y * m1[3];
|
|
||||||
m1[2] += Pos.Z * m1[3];
|
|
||||||
m1[4] += Pos.X * m1[7];
|
|
||||||
m1[5] += Pos.Y * m1[7];
|
|
||||||
m1[6] += Pos.Z * m1[7];
|
|
||||||
m1[8] += Pos.X * m1[11];
|
|
||||||
m1[9] += Pos.Y * m1[11];
|
|
||||||
m1[10] += Pos.Z * m1[11];
|
|
||||||
m1[12] += Pos.X * m1[15];
|
|
||||||
m1[13] += Pos.Y * m1[15];
|
|
||||||
m1[14] += Pos.Z * m1[15];
|
|
||||||
// -----------------------------------
|
|
||||||
|
|
||||||
if (!joint->keys.scale.empty()) {
|
|
||||||
/*
|
|
||||||
core::matrix4 scaleMatrix;
|
|
||||||
scaleMatrix.setScale(joint->Animatedscale);
|
|
||||||
joint->LocalAnimatedMatrix *= scaleMatrix;
|
|
||||||
*/
|
|
||||||
|
|
||||||
// -------- joint->LocalAnimatedMatrix *= scaleMatrix -----------------
|
|
||||||
core::matrix4 &mat = joint->LocalAnimatedMatrix;
|
|
||||||
mat[0] *= joint->Animatedscale.X;
|
|
||||||
mat[1] *= joint->Animatedscale.X;
|
|
||||||
mat[2] *= joint->Animatedscale.X;
|
|
||||||
mat[3] *= joint->Animatedscale.X;
|
|
||||||
mat[4] *= joint->Animatedscale.Y;
|
|
||||||
mat[5] *= joint->Animatedscale.Y;
|
|
||||||
mat[6] *= joint->Animatedscale.Y;
|
|
||||||
mat[7] *= joint->Animatedscale.Y;
|
|
||||||
mat[8] *= joint->Animatedscale.Z;
|
|
||||||
mat[9] *= joint->Animatedscale.Z;
|
|
||||||
mat[10] *= joint->Animatedscale.Z;
|
|
||||||
mat[11] *= joint->Animatedscale.Z;
|
|
||||||
// -----------------------------------
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
joint->LocalAnimatedMatrix = joint->LocalMatrix;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
SkinnedLastFrame = false;
|
SkinnedLastFrame = false;
|
||||||
}
|
}
|
||||||
|
@ -396,12 +346,13 @@ void SkinnedMesh::calculateGlobalMatrices(SJoint *joint, SJoint *parentJoint)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const auto local_matrix = joint->buildLocalMatrix();
|
||||||
if (!parentJoint)
|
if (!parentJoint)
|
||||||
joint->GlobalMatrix = joint->LocalMatrix;
|
joint->GlobalMatrix = local_matrix;
|
||||||
else
|
else
|
||||||
joint->GlobalMatrix = parentJoint->GlobalMatrix * joint->LocalMatrix;
|
joint->GlobalMatrix = parentJoint->GlobalMatrix * local_matrix;
|
||||||
|
|
||||||
joint->LocalAnimatedMatrix = joint->LocalMatrix;
|
joint->LocalAnimatedMatrix = local_matrix;
|
||||||
joint->GlobalAnimatedMatrix = joint->GlobalMatrix;
|
joint->GlobalAnimatedMatrix = joint->GlobalMatrix;
|
||||||
|
|
||||||
if (!joint->GlobalInversedMatrix.has_value()) { // might be pre calculated
|
if (!joint->GlobalInversedMatrix.has_value()) { // might be pre calculated
|
||||||
|
@ -689,7 +640,7 @@ void SkinnedMesh::recoverJointsFromMesh(std::vector<IBoneSceneNode *> &jointChil
|
||||||
node->setRotation(joint->LocalAnimatedMatrix.getRotationDegrees());
|
node->setRotation(joint->LocalAnimatedMatrix.getRotationDegrees());
|
||||||
node->setScale(joint->LocalAnimatedMatrix.getScale());
|
node->setScale(joint->LocalAnimatedMatrix.getScale());
|
||||||
|
|
||||||
node->updateAbsolutePosition();
|
node->updateAbsolutePosition(); // WTF
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -916,12 +916,7 @@ struct Node {
|
||||||
std::optional<std::size_t> skin;
|
std::optional<std::size_t> skin;
|
||||||
std::optional<std::vector<double>> weights;
|
std::optional<std::vector<double>> weights;
|
||||||
Node(const Json::Value &o)
|
Node(const Json::Value &o)
|
||||||
: transform(Matrix {
|
: transform(TRS{})
|
||||||
1, 0, 0, 0,
|
|
||||||
0, 1, 0, 0,
|
|
||||||
0, 0, 1, 0,
|
|
||||||
0, 0, 0, 1
|
|
||||||
})
|
|
||||||
{
|
{
|
||||||
check(o.isObject());
|
check(o.isObject());
|
||||||
if (o.isMember("camera")) {
|
if (o.isMember("camera")) {
|
||||||
|
|
|
@ -1401,6 +1401,8 @@ void GenericCAO::updateBones(f32 dtime)
|
||||||
if (m_bone_override.empty())
|
if (m_bone_override.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// FIXME these need to be applied at a different point in time
|
||||||
|
// in order to be relative to the animated bone positions of the current frame
|
||||||
for (auto &it : m_bone_override) {
|
for (auto &it : m_bone_override) {
|
||||||
std::string bone_name = it.first;
|
std::string bone_name = it.first;
|
||||||
scene::IBoneSceneNode* bone = m_animated_meshnode->getJointNode(bone_name.c_str());
|
scene::IBoneSceneNode* bone = m_animated_meshnode->getJointNode(bone_name.c_str());
|
||||||
|
|
|
@ -413,17 +413,23 @@ SECTION("simple skin")
|
||||||
|
|
||||||
SECTION("transformations are correct")
|
SECTION("transformations are correct")
|
||||||
{
|
{
|
||||||
CHECK(parent->Animatedposition == v3f(0, 0, 0));
|
{
|
||||||
CHECK(parent->Animatedrotation == irr::core::quaternion());
|
const auto &transform = std::get<SkinnedMesh::SJoint::Transform>(parent->transform);
|
||||||
CHECK(parent->Animatedscale == v3f(1, 1, 1));
|
CHECK(transform.translation == v3f(0, 0, 0));
|
||||||
CHECK(parent->GlobalInversedMatrix == irr::core::matrix4());
|
CHECK(transform.rotation == irr::core::quaternion());
|
||||||
const v3f childTranslation(0, 1, 0);
|
CHECK(transform.scale == v3f(1, 1, 1));
|
||||||
CHECK(child->Animatedposition == childTranslation);
|
CHECK(parent->GlobalInversedMatrix == irr::core::matrix4());
|
||||||
CHECK(child->Animatedrotation == irr::core::quaternion());
|
}
|
||||||
CHECK(child->Animatedscale == v3f(1, 1, 1));
|
{
|
||||||
irr::core::matrix4 inverseBindMatrix;
|
const auto &transform = std::get<SkinnedMesh::SJoint::Transform>(child->transform);
|
||||||
inverseBindMatrix.setTranslation(-childTranslation);
|
const v3f translation(0, 1, 0);
|
||||||
CHECK(child->GlobalInversedMatrix == inverseBindMatrix);
|
CHECK(transform.translation == translation);
|
||||||
|
CHECK(transform.rotation == irr::core::quaternion());
|
||||||
|
CHECK(transform.scale == v3f(1, 1, 1));
|
||||||
|
irr::core::matrix4 inverseBindMatrix;
|
||||||
|
inverseBindMatrix.setTranslation(-translation);
|
||||||
|
CHECK(child->GlobalInversedMatrix == inverseBindMatrix);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("weights are correct")
|
SECTION("weights are correct")
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue