Use callback function to directly upload joints without copying

This commit is contained in:
Benau
2016-12-10 16:16:40 +08:00
parent 8ca0c54bdc
commit fcd1e2830e
9 changed files with 63 additions and 47 deletions

View File

@@ -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

View File

@@ -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. */

View File

@@ -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
{

View File

@@ -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();

View File

@@ -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)

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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;