Add animation support in GEVulkanAnimatedMeshSceneNode
This commit is contained in:
parent
b75dec1fbc
commit
8e1de345fb
@ -14,6 +14,7 @@ class SPMeshLoader;
|
||||
|
||||
namespace GE
|
||||
{
|
||||
struct Armature;
|
||||
class GESPMBuffer;
|
||||
class GEVulkanSceneManager;
|
||||
|
||||
@ -31,6 +32,7 @@ private:
|
||||
|
||||
unsigned m_bind_frame, m_total_joints, m_joint_using, m_frame_count;
|
||||
|
||||
std::vector<Armature> m_all_armatures;
|
||||
public:
|
||||
// ------------------------------------------------------------------------
|
||||
GESPM();
|
||||
@ -70,6 +72,17 @@ public:
|
||||
virtual E_ANIMATED_MESH_TYPE getMeshType() const { return EAMT_SPM; }
|
||||
// ------------------------------------------------------------------------
|
||||
virtual void finalize();
|
||||
// ------------------------------------------------------------------------
|
||||
std::vector<Armature>& getArmatures() { return m_all_armatures; }
|
||||
// ------------------------------------------------------------------------
|
||||
void getSkinningMatrices(f32 frame, std::vector<core::matrix4>& dest,
|
||||
float frame_interpolating = -1.0f, float rate = -1.0f);
|
||||
// ------------------------------------------------------------------------
|
||||
s32 getJointIDWithArm(const c8* name, unsigned* arm_id) const;
|
||||
// ------------------------------------------------------------------------
|
||||
bool isStatic() const { return m_all_armatures.empty(); }
|
||||
// ------------------------------------------------------------------------
|
||||
unsigned getJointCount() const { return m_joint_using; }
|
||||
|
||||
};
|
||||
|
||||
|
@ -1,6 +1,10 @@
|
||||
#include "ge_spm.hpp"
|
||||
|
||||
#include "ge_animation.hpp"
|
||||
#include "ge_spm_buffer.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace GE
|
||||
{
|
||||
GESPM::GESPM()
|
||||
@ -42,6 +46,54 @@ void GESPM::finalize()
|
||||
m_bounding_box.reset(0.0f, 0.0f, 0.0f);
|
||||
for (unsigned i = 0; i < m_buffer.size(); i++)
|
||||
m_bounding_box.addInternalBox(m_buffer[i]->getBoundingBox());
|
||||
|
||||
for (Armature& arm : getArmatures())
|
||||
{
|
||||
arm.getInterpolatedMatrices((float)m_bind_frame);
|
||||
for (auto& p : arm.m_world_matrices)
|
||||
{
|
||||
p.second = false;
|
||||
}
|
||||
for (unsigned i = 0; i < arm.m_joint_names.size(); i++)
|
||||
{
|
||||
core::matrix4 m;
|
||||
arm.getWorldMatrix(arm.m_interpolated_matrices, i).getInverse(m);
|
||||
arm.m_joint_matrices[i] = m;
|
||||
}
|
||||
}
|
||||
} // finalize
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void GESPM::getSkinningMatrices(f32 frame, std::vector<core::matrix4>& dest,
|
||||
float frame_interpolating, float rate)
|
||||
{
|
||||
unsigned accumulated_joints = 0;
|
||||
for (unsigned i = 0; i < m_all_armatures.size(); i++)
|
||||
{
|
||||
m_all_armatures[i].getPose(frame, &dest[accumulated_joints],
|
||||
frame_interpolating, rate);
|
||||
accumulated_joints += m_all_armatures[i].m_joint_used;
|
||||
}
|
||||
} // getSkinningMatrices
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
s32 GESPM::getJointIDWithArm(const c8* name, unsigned* arm_id) const
|
||||
{
|
||||
for (unsigned i = 0; i < m_all_armatures.size(); i++)
|
||||
{
|
||||
const Armature& arm = m_all_armatures[i];
|
||||
auto found = std::find(arm.m_joint_names.begin(),
|
||||
arm.m_joint_names.end(), name);
|
||||
if (found != arm.m_joint_names.end())
|
||||
{
|
||||
if (arm_id != NULL)
|
||||
{
|
||||
*arm_id = i;
|
||||
}
|
||||
return (int)(found - arm.m_joint_names.begin());
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
} // getJointIDWithArm
|
||||
|
||||
}
|
||||
|
@ -1,8 +1,11 @@
|
||||
#include "ge_vulkan_animated_mesh_scene_node.hpp"
|
||||
|
||||
#include "ge_animation.hpp"
|
||||
#include "ge_spm.hpp"
|
||||
|
||||
#include "ISceneManager.h"
|
||||
#include "../../../lib/irrlicht/source/Irrlicht/CBoneSceneNode.h"
|
||||
#include <limits>
|
||||
|
||||
namespace GE
|
||||
{
|
||||
@ -14,6 +17,7 @@ GEVulkanAnimatedMeshSceneNode::GEVulkanAnimatedMeshSceneNode(irr::scene::IAnimat
|
||||
: irr::scene::CAnimatedMeshSceneNode(mesh, parent, mgr, id, position,
|
||||
rotation, scale)
|
||||
{
|
||||
m_saved_transition_frame = -1.0f;
|
||||
} // GEVulkanAnimatedMeshSceneNode
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -31,4 +35,101 @@ void GEVulkanAnimatedMeshSceneNode::OnRegisterSceneNode()
|
||||
ISceneNode::OnRegisterSceneNode();
|
||||
} // OnRegisterSceneNode
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void GEVulkanAnimatedMeshSceneNode::setMesh(irr::scene::IAnimatedMesh* mesh)
|
||||
{
|
||||
CAnimatedMeshSceneNode::setMesh(mesh);
|
||||
cleanJoints();
|
||||
GESPM* spm = getSPM();
|
||||
if (!spm || spm->isStatic())
|
||||
return;
|
||||
|
||||
unsigned bone_idx = 0;
|
||||
m_skinning_matrices.resize(spm->getJointCount());
|
||||
for (Armature& arm : spm->getArmatures())
|
||||
{
|
||||
for (const std::string& bone_name : arm.m_joint_names)
|
||||
{
|
||||
m_joint_nodes[bone_name] = new CBoneSceneNode(this,
|
||||
SceneManager, 0, bone_idx++, bone_name.c_str());
|
||||
m_joint_nodes.at(bone_name)->drop();
|
||||
m_joint_nodes.at(bone_name)->setSkinningSpace(EBSS_GLOBAL);
|
||||
}
|
||||
}
|
||||
} // setMesh
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void GEVulkanAnimatedMeshSceneNode::OnAnimate(irr::u32 time_ms)
|
||||
{
|
||||
GESPM* spm = getSPM();
|
||||
if (!spm || spm->isStatic())
|
||||
{
|
||||
IAnimatedMeshSceneNode::OnAnimate(time_ms);
|
||||
return;
|
||||
}
|
||||
|
||||
// first frame
|
||||
if (LastTimeMs == 0)
|
||||
LastTimeMs = time_ms;
|
||||
|
||||
// set CurrentFrameNr
|
||||
buildFrameNr(time_ms - LastTimeMs);
|
||||
LastTimeMs = time_ms;
|
||||
|
||||
spm->getSkinningMatrices(getFrameNr(), m_skinning_matrices,
|
||||
m_saved_transition_frame, TransitingBlend);
|
||||
recursiveUpdateAbsolutePosition();
|
||||
|
||||
for (Armature& arm : spm->getArmatures())
|
||||
{
|
||||
for (unsigned i = 0; i < arm.m_joint_names.size(); i++)
|
||||
{
|
||||
m_joint_nodes.at(arm.m_joint_names[i])->setAbsoluteTransformation
|
||||
(AbsoluteTransformation * arm.m_world_matrices[i].first);
|
||||
}
|
||||
}
|
||||
|
||||
IAnimatedMeshSceneNode::OnAnimate(time_ms);
|
||||
} // OnAnimate
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
irr::scene::IBoneSceneNode* GEVulkanAnimatedMeshSceneNode::getJointNode(const irr::c8* joint_name)
|
||||
{
|
||||
auto ret = m_joint_nodes.find(joint_name);
|
||||
if (ret != m_joint_nodes.end())
|
||||
return ret->second;
|
||||
return NULL;
|
||||
} // getJointNode
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
irr::scene::IBoneSceneNode* GEVulkanAnimatedMeshSceneNode::getJointNode(irr::u32 joint_id)
|
||||
{
|
||||
irr::u32 idx = 0;
|
||||
for (auto& p : m_joint_nodes)
|
||||
{
|
||||
if (joint_id == idx)
|
||||
return p.second;
|
||||
idx++;
|
||||
}
|
||||
return NULL;
|
||||
} // getJointNode
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void GEVulkanAnimatedMeshSceneNode::setTransitionTime(irr::f32 Time)
|
||||
{
|
||||
if (Time == 0.0f)
|
||||
{
|
||||
TransitingBlend = TransitionTime = Transiting = 0;
|
||||
m_saved_transition_frame = -1.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
const u32 ttime = (u32)core::floor32(Time * 1000.0f);
|
||||
TransitionTime = ttime;
|
||||
Transiting = core::reciprocal((f32)TransitionTime);
|
||||
TransitingBlend = 0.0f;
|
||||
m_saved_transition_frame = getFrameNr();
|
||||
}
|
||||
} // setTransitionTime
|
||||
|
||||
}
|
||||
|
@ -3,12 +3,32 @@
|
||||
|
||||
#include "../source/Irrlicht/CAnimatedMeshSceneNode.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace GE
|
||||
{
|
||||
class GESPM;
|
||||
|
||||
class GEVulkanAnimatedMeshSceneNode : public irr::scene::CAnimatedMeshSceneNode
|
||||
{
|
||||
private:
|
||||
std::unordered_map<std::string, irr::scene::IBoneSceneNode*> m_joint_nodes;
|
||||
|
||||
float m_saved_transition_frame;
|
||||
|
||||
std::vector<irr::core::matrix4> m_skinning_matrices;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
void cleanJoints()
|
||||
{
|
||||
for (auto& p : m_joint_nodes)
|
||||
removeChild(p.second);
|
||||
m_joint_nodes.clear();
|
||||
m_skinning_matrices.clear();
|
||||
}
|
||||
public:
|
||||
// ------------------------------------------------------------------------
|
||||
GEVulkanAnimatedMeshSceneNode(irr::scene::IAnimatedMesh* mesh,
|
||||
@ -17,6 +37,20 @@ public:
|
||||
const irr::core::vector3df& rotation = irr::core::vector3df(0, 0, 0),
|
||||
const irr::core::vector3df& scale = irr::core::vector3df(1.0f, 1.0f, 1.0f));
|
||||
// ------------------------------------------------------------------------
|
||||
~GEVulkanAnimatedMeshSceneNode() { cleanJoints(); }
|
||||
// ------------------------------------------------------------------------
|
||||
virtual void setMesh(irr::scene::IAnimatedMesh* mesh);
|
||||
// ------------------------------------------------------------------------
|
||||
virtual void OnAnimate(irr::u32 time_ms);
|
||||
// ------------------------------------------------------------------------
|
||||
virtual irr::scene::IBoneSceneNode* getJointNode(const irr::c8* joint_name);
|
||||
// ------------------------------------------------------------------------
|
||||
virtual irr::scene::IBoneSceneNode* getJointNode(irr::u32 joint_id);
|
||||
// ------------------------------------------------------------------------
|
||||
virtual irr::u32 getJointCount() const { return m_joint_nodes.size(); }
|
||||
// ------------------------------------------------------------------------
|
||||
virtual void setTransitionTime(irr::f32 Time);
|
||||
// ------------------------------------------------------------------------
|
||||
GESPM* getSPM() const;
|
||||
// ------------------------------------------------------------------------
|
||||
virtual void OnRegisterSceneNode();
|
||||
|
@ -114,6 +114,11 @@ scene::IAnimatedMesh* B3DMeshLoader::createMesh(io::IReadFile* f)
|
||||
stk_material->getTexture();
|
||||
gebuf->recalculateBoundingBox();
|
||||
}
|
||||
ge_spm->m_bind_frame = spm->m_bind_frame;
|
||||
ge_spm->m_total_joints = spm->m_total_joints;
|
||||
ge_spm->m_joint_using = spm->m_joint_using;
|
||||
ge_spm->m_frame_count = spm->m_frame_count;
|
||||
std::swap(ge_spm->m_all_armatures, spm->m_all_armatures);
|
||||
ge_spm->finalize();
|
||||
ge_spm->setMinMax(min.toIrrVector(), max.toIrrVector());
|
||||
spm->drop();
|
||||
|
@ -335,6 +335,26 @@ scene::IAnimatedMesh* SPMeshLoader::createMesh(io::IReadFile* f)
|
||||
}
|
||||
spm->m_all_armatures = std::move(m_all_armatures);
|
||||
}
|
||||
#ifndef SERVER_ONLY
|
||||
else if (ge_spm)
|
||||
{
|
||||
GE::GESPM* spm = static_cast<GE::GESPM*>(m_mesh);
|
||||
spm->m_bind_frame = m_bind_frame;
|
||||
spm->m_joint_using = m_joint_count;
|
||||
// Because the last frame in spm is usable
|
||||
if (has_armature)
|
||||
{
|
||||
spm->m_frame_count = m_frame_count + 1;
|
||||
}
|
||||
for (unsigned i = 0; i < m_all_armatures.size(); i++)
|
||||
{
|
||||
// This is diffferent from m_joint_using
|
||||
spm->m_total_joints +=
|
||||
(unsigned)m_all_armatures[i].m_joint_names.size();
|
||||
}
|
||||
spm->m_all_armatures = std::move(m_all_armatures);
|
||||
}
|
||||
#endif
|
||||
m_mesh->finalize();
|
||||
scene::CSkinnedMesh* cmesh = dynamic_cast<scene::CSkinnedMesh*>(m_mesh);
|
||||
if (cmesh && !real_spm && has_armature)
|
||||
|
@ -48,6 +48,7 @@
|
||||
#include "IMeshManipulator.h"
|
||||
#include <algorithm>
|
||||
#include <ge_animation.hpp>
|
||||
#include <ge_spm.hpp>
|
||||
|
||||
#define SKELETON_DEBUG 0
|
||||
|
||||
@ -1295,11 +1296,21 @@ void KartModel::initInverseBoneMatrices()
|
||||
m_model_filename.c_str());
|
||||
striaght_frame = 0.0f;
|
||||
}
|
||||
std::vector<GE::Armature> armatures;
|
||||
|
||||
#ifndef SERVER_ONLY
|
||||
using namespace SP;
|
||||
SPMesh* spm = dynamic_cast<SPMesh*>(m_mesh);
|
||||
GE::GESPM* ge_spm = dynamic_cast<GE::GESPM*>(m_mesh);
|
||||
if (spm)
|
||||
armatures = spm->getArmatures();
|
||||
else if (ge_spm)
|
||||
armatures = ge_spm->getArmatures();
|
||||
#endif
|
||||
|
||||
if (!armatures.empty())
|
||||
{
|
||||
for (GE::Armature& arm : spm->getArmatures())
|
||||
for (GE::Armature& arm : armatures)
|
||||
{
|
||||
arm.getInterpolatedMatrices(striaght_frame);
|
||||
for (auto& p : arm.m_world_matrices)
|
||||
|
Loading…
Reference in New Issue
Block a user