Use callback function to directly upload joints without copying
This commit is contained in:
@@ -8,6 +8,8 @@
|
||||
#include "aabbox3d.h"
|
||||
#include "IMesh.h"
|
||||
|
||||
typedef void (*SkinningCallback)(const irr::core::matrix4& m, int joint, int offset);
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
|
||||
@@ -69,7 +69,7 @@ namespace scene
|
||||
virtual void animateMesh(f32 frame, f32 blend)=0;
|
||||
|
||||
//! Preforms a software skin on this mesh based of joint positions
|
||||
virtual void skinMesh(f32 strength=1.f) = 0;
|
||||
virtual void skinMesh(f32 strength=1.f, SkinningCallback sc = NULL, int offset = -1) = 0;
|
||||
|
||||
//! converts the vertex type of all meshbuffers to tangents.
|
||||
/** E.g. used for bump mapping. */
|
||||
|
||||
@@ -178,7 +178,7 @@ void CAnimatedMeshSceneNode::OnRegisterSceneNode()
|
||||
}
|
||||
}
|
||||
|
||||
IMesh * CAnimatedMeshSceneNode::getMeshForCurrentFrame()
|
||||
IMesh * CAnimatedMeshSceneNode::getMeshForCurrentFrame(SkinningCallback sc, int offset)
|
||||
{
|
||||
if(Mesh->getMeshType() != EAMT_SKINNED)
|
||||
{
|
||||
@@ -203,7 +203,7 @@ IMesh * CAnimatedMeshSceneNode::getMeshForCurrentFrame()
|
||||
skinnedMesh->animateMesh(getFrameNr(), 1.0f);
|
||||
|
||||
// Update the skinned mesh for the current joint transforms.
|
||||
skinnedMesh->skinMesh(AnimationStrength);
|
||||
skinnedMesh->skinMesh(AnimationStrength, sc, offset);
|
||||
|
||||
if (JointMode == EJUOR_READ)//read from mesh
|
||||
{
|
||||
|
||||
@@ -161,7 +161,7 @@ namespace scene
|
||||
protected:
|
||||
|
||||
//! Get a static mesh for the current frame of this animated mesh
|
||||
IMesh* getMeshForCurrentFrame();
|
||||
virtual IMesh* getMeshForCurrentFrame(SkinningCallback sc = NULL, int offset = -1);
|
||||
|
||||
void buildFrameNr(u32 timeMs);
|
||||
void checkJoints();
|
||||
|
||||
@@ -22,7 +22,8 @@ CSkinnedMesh::CSkinnedMesh()
|
||||
LastAnimatedFrame(-1), SkinnedLastFrame(false),
|
||||
InterpolationMode(EIM_LINEAR),
|
||||
HasAnimation(false), PreparedForSkinning(false),
|
||||
AnimateNormals(true), HardwareSkinning(false), m_joint_total_size(0)
|
||||
AnimateNormals(true), HardwareSkinning(false), m_total_joints(0),
|
||||
m_current_joint(0)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CSkinnedMesh");
|
||||
@@ -99,6 +100,12 @@ IMesh* CSkinnedMesh::getMesh(s32 frame, s32 detailLevel, s32 startFrameLoop, s32
|
||||
//! blend: {0-old position, 1-New position}
|
||||
void CSkinnedMesh::animateMesh(f32 frame, f32 blend)
|
||||
{
|
||||
if (HardwareSkinning && LastAnimatedFrame==frame)
|
||||
{
|
||||
SkinnedLastFrame=false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!HasAnimation || LastAnimatedFrame==frame)
|
||||
return;
|
||||
|
||||
@@ -451,7 +458,7 @@ void CSkinnedMesh::getFrameData(f32 frame, SJoint *joint,
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
//! Preforms a software skin on this mesh based of joint positions
|
||||
void CSkinnedMesh::skinMesh(f32 strength)
|
||||
void CSkinnedMesh::skinMesh(f32 strength, SkinningCallback sc, int offset)
|
||||
{
|
||||
if (!HasAnimation || SkinnedLastFrame)
|
||||
return;
|
||||
@@ -462,11 +469,11 @@ void CSkinnedMesh::skinMesh(f32 strength)
|
||||
//-----------------
|
||||
|
||||
SkinnedLastFrame=true;
|
||||
m_joint_matrixes.clear();
|
||||
m_current_joint = 0;
|
||||
if (HardwareSkinning)
|
||||
{
|
||||
for (u32 i = 0; i < RootJoints.size(); i++)
|
||||
skinJoint(RootJoints[i], 0, strength);
|
||||
skinJoint(RootJoints[i], 0, strength, sc, offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -498,7 +505,8 @@ void CSkinnedMesh::skinMesh(f32 strength)
|
||||
updateBoundingBox();
|
||||
}
|
||||
|
||||
void CSkinnedMesh::skinJoint(SJoint *joint, SJoint *parentJoint, f32 strength)
|
||||
void CSkinnedMesh::skinJoint(SJoint *joint, SJoint *parentJoint, f32 strength,
|
||||
SkinningCallback sc, int offset)
|
||||
{
|
||||
if (joint->Weights.size())
|
||||
{
|
||||
@@ -507,7 +515,8 @@ void CSkinnedMesh::skinJoint(SJoint *joint, SJoint *parentJoint, f32 strength)
|
||||
jointVertexPull.setbyproduct(joint->GlobalAnimatedMatrix, joint->GlobalInversedMatrix);
|
||||
if (HardwareSkinning)
|
||||
{
|
||||
m_joint_matrixes.push_back(jointVertexPull);
|
||||
if (sc != NULL) sc(jointVertexPull, m_current_joint, offset);
|
||||
m_current_joint++;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -562,7 +571,7 @@ void CSkinnedMesh::skinJoint(SJoint *joint, SJoint *parentJoint, f32 strength)
|
||||
|
||||
//Skin all children
|
||||
for (u32 j=0; j<joint->Children.size(); ++j)
|
||||
skinJoint(joint->Children[j], joint, strength);
|
||||
skinJoint(joint->Children[j], joint, strength, sc, offset);
|
||||
}
|
||||
|
||||
|
||||
@@ -1458,7 +1467,7 @@ void CSkinnedMesh::convertForSkinning()
|
||||
}
|
||||
SkinnedLastFrame = false;
|
||||
skinMesh();
|
||||
m_joint_total_size = m_joint_matrixes.size();
|
||||
m_total_joints = m_current_joint;
|
||||
}
|
||||
|
||||
void CSkinnedMesh::computeWeightInfluence(SJoint *joint, size_t &index, WeightInfluence& wi)
|
||||
|
||||
@@ -14,17 +14,6 @@
|
||||
#include "matrix4.h"
|
||||
#include "quaternion.h"
|
||||
|
||||
class Matrix4x4
|
||||
{
|
||||
private:
|
||||
float data[16];
|
||||
public:
|
||||
inline Matrix4x4(const irr::core::matrix4& m)
|
||||
{
|
||||
memcpy(data, m.pointer(), 16 * sizeof(float));
|
||||
}
|
||||
};
|
||||
|
||||
class JointInfluence
|
||||
{
|
||||
public:
|
||||
@@ -76,7 +65,7 @@ namespace scene
|
||||
virtual void animateMesh(f32 frame, f32 blend);
|
||||
|
||||
//! Preforms a software skin on this mesh based of joint positions
|
||||
virtual void skinMesh(f32 strength=1.f);
|
||||
virtual void skinMesh(f32 strength=1.f, SkinningCallback sc = NULL, int offset = -1);
|
||||
|
||||
//! returns amount of mesh buffers.
|
||||
virtual u32 getMeshBufferCount() const;
|
||||
@@ -188,12 +177,7 @@ namespace scene
|
||||
|
||||
void computeWeightInfluence(SJoint *joint, size_t &index, WeightInfluence& wi);
|
||||
|
||||
const void* getJointPointer() const { return m_joint_matrixes.const_pointer(); }
|
||||
|
||||
u32 getTotalJointSize() const
|
||||
{
|
||||
return m_joint_total_size;
|
||||
}
|
||||
u32 getTotalJoints() const { return m_total_joints; }
|
||||
|
||||
private:
|
||||
void checkForAnimation();
|
||||
@@ -211,7 +195,8 @@ private:
|
||||
|
||||
void calculateGlobalMatrices(SJoint *Joint,SJoint *ParentJoint);
|
||||
|
||||
void skinJoint(SJoint *Joint, SJoint *ParentJoint, f32 strength=1.f);
|
||||
void skinJoint(SJoint *Joint, SJoint *ParentJoint, f32 strength=1.f,
|
||||
SkinningCallback sc = NULL, int offset = -1);
|
||||
|
||||
void calculateTangents(core::vector3df& normal,
|
||||
core::vector3df& tangent, core::vector3df& binormal,
|
||||
@@ -241,8 +226,8 @@ private:
|
||||
bool PreparedForSkinning;
|
||||
bool AnimateNormals;
|
||||
bool HardwareSkinning;
|
||||
core::array<Matrix4x4> m_joint_matrixes;
|
||||
u32 m_joint_total_size;
|
||||
u32 m_total_joints;
|
||||
u32 m_current_joint;
|
||||
};
|
||||
|
||||
} // end namespace scene
|
||||
|
||||
@@ -899,6 +899,6 @@ int32_t DrawCalls::getSkinningOffset() const
|
||||
return std::accumulate(m_mesh_for_skinning.begin(),
|
||||
m_mesh_for_skinning.end(), 0, []
|
||||
(const size_t previous, const STKAnimatedMesh* m)
|
||||
{ return previous + m->getTotalJointSize(); });
|
||||
{ return previous + m->getTotalJoints(); });
|
||||
} // getSkinningOffset
|
||||
#endif // !SERVER_ONLY
|
||||
|
||||
@@ -222,12 +222,9 @@ void STKAnimatedMesh::updateNoGL()
|
||||
|
||||
void STKAnimatedMesh::updateGL()
|
||||
{
|
||||
|
||||
scene::IMesh* m = getMeshForCurrentFrame();
|
||||
|
||||
if (!isGLInitialized)
|
||||
{
|
||||
for (u32 i = 0; i < m->getMeshBufferCount(); ++i)
|
||||
for (u32 i = 0; i < Mesh->getMeshBufferCount(); ++i)
|
||||
{
|
||||
scene::IMeshBuffer* mb = Mesh->getMeshBuffer(i);
|
||||
if (!mb)
|
||||
@@ -275,13 +272,9 @@ void STKAnimatedMesh::updateGL()
|
||||
isGLInitialized = true;
|
||||
}
|
||||
|
||||
scene::IMesh* m = getMeshForCurrentFrame();
|
||||
if (useHardwareSkinning())
|
||||
{
|
||||
if (m_skinning_offset == -1) return;
|
||||
glBindBuffer(GL_UNIFORM_BUFFER, SharedGPUObjects::getSkinningUBO());
|
||||
glBufferSubData(GL_UNIFORM_BUFFER, m_skinning_offset,
|
||||
m_skinned_mesh->getTotalJointSize() * 16 * sizeof(float),
|
||||
m_skinned_mesh->getJointPointer());
|
||||
m_skinning_offset = -1;
|
||||
return;
|
||||
}
|
||||
@@ -329,9 +322,9 @@ void STKAnimatedMesh::render()
|
||||
updateGL();
|
||||
}
|
||||
|
||||
int STKAnimatedMesh::getTotalJointSize() const
|
||||
int STKAnimatedMesh::getTotalJoints() const
|
||||
{
|
||||
return m_skinned_mesh->getTotalJointSize();
|
||||
return m_skinned_mesh->getTotalJoints();
|
||||
}
|
||||
|
||||
void STKAnimatedMesh::resetSkinningState(scene::IAnimatedMesh* mesh)
|
||||
@@ -342,9 +335,30 @@ void STKAnimatedMesh::resetSkinningState(scene::IAnimatedMesh* mesh)
|
||||
if (m_skinned_mesh)
|
||||
{
|
||||
m_skinned_mesh->convertForSkinning();
|
||||
if (m_skinned_mesh->getTotalJointSize() == 0)
|
||||
if (m_skinned_mesh->getTotalJoints() == 0)
|
||||
m_skinned_mesh = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
scene::IMesh* STKAnimatedMesh::getMeshForCurrentFrame(SkinningCallback sc,
|
||||
int offset)
|
||||
{
|
||||
if (!useHardwareSkinning())
|
||||
return scene::CAnimatedMeshSceneNode::getMeshForCurrentFrame();
|
||||
if (m_skinning_offset == -1)
|
||||
return Mesh;
|
||||
|
||||
return scene::CAnimatedMeshSceneNode::getMeshForCurrentFrame
|
||||
(uploadJoints, m_skinning_offset);
|
||||
}
|
||||
|
||||
void STKAnimatedMesh::uploadJoints(const irr::core::matrix4& m,
|
||||
int joint, int offset)
|
||||
{
|
||||
assert(offset != -1);
|
||||
glBindBuffer(GL_UNIFORM_BUFFER, SharedGPUObjects::getSkinningUBO());
|
||||
glBufferSubData(GL_UNIFORM_BUFFER, offset + joint * 16 * sizeof(float),
|
||||
16 * sizeof(float), m.pointer());
|
||||
}
|
||||
|
||||
#endif // !SERVER_ONLY
|
||||
|
||||
@@ -54,10 +54,16 @@ public:
|
||||
virtual void render();
|
||||
virtual void setMesh(irr::scene::IAnimatedMesh* mesh);
|
||||
virtual bool glow() const { return false; }
|
||||
int getTotalJointSize() const;
|
||||
virtual irr::scene::IMesh* getMeshForCurrentFrame(SkinningCallback sc = NULL,
|
||||
int offset = -1);
|
||||
int getTotalJoints() const;
|
||||
void setSkinningOffset(int offset) { m_skinning_offset = offset; }
|
||||
bool useHardwareSkinning() const { return m_skinned_mesh != NULL; }
|
||||
void resetSkinningState(scene::IAnimatedMesh*);
|
||||
|
||||
// Callback for skinning mesh
|
||||
static void uploadJoints(const irr::core::matrix4& m,
|
||||
int joint, int offset);
|
||||
private:
|
||||
RenderInfo* m_mesh_render_info;
|
||||
bool m_all_parts_colorized;
|
||||
|
||||
Reference in New Issue
Block a user