Commit 1c0fab0d authored by Rogerborg's avatar Rogerborg

Update the bounding boxes of animated skinned meshes. (Attempt to) remove...

Update the bounding boxes of animated skinned meshes.  (Attempt to) remove duplication of the recalculation of frames of animated meshes in CAnimatedMeshSceneNode::OnAnimate() and CAnimatedMeshSceneNode::render().

git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@1805 dfc29bdd-3216-0410-991c-e03cc46cb475
parent def976c1
......@@ -19,7 +19,9 @@ namespace scene
struct SSkinMeshBuffer : public IMeshBuffer
{
//! Default constructor
SSkinMeshBuffer(video::E_VERTEX_TYPE vt=video::EVT_STANDARD) : ChangedID_Vertex(1),ChangedID_Index(1),MappingHint_Vertex(EHM_NEVER),MappingHint_Index(EHM_NEVER),VertexType(vt)
SSkinMeshBuffer(video::E_VERTEX_TYPE vt=video::EVT_STANDARD) :
ChangedID_Vertex(1),ChangedID_Index(1),MappingHint_Vertex(EHM_NEVER),
MappingHint_Index(EHM_NEVER),VertexType(vt),BoundingBoxNeedsRecalculated(true)
{
#ifdef _DEBUG
setDebugName("SSkinMeshBuffer");
......@@ -131,6 +133,11 @@ struct SSkinMeshBuffer : public IMeshBuffer
//! Recalculate bounding box
virtual void recalculateBoundingBox()
{
if(!BoundingBoxNeedsRecalculated)
return;
BoundingBoxNeedsRecalculated = false;
switch (VertexType)
{
case video::EVT_STANDARD:
......@@ -359,6 +366,9 @@ struct SSkinMeshBuffer : public IMeshBuffer
virtual u32 getChangedID_Index() const {return ChangedID_Index;}
//! Call this after changing the positions of any vertex.
void boundingBoxNeedsRecalculated(void) { BoundingBoxNeedsRecalculated = true; }
u32 ChangedID_Vertex;
u32 ChangedID_Index;
......@@ -376,6 +386,7 @@ struct SSkinMeshBuffer : public IMeshBuffer
core::array<video::S3DVertex> Vertices_Standard;
core::array<u16> Indices;
core::aabbox3d<f32> BoundingBox;
bool BoundingBoxNeedsRecalculated;
};
......
......@@ -33,7 +33,8 @@ CAnimatedMeshSceneNode::CAnimatedMeshSceneNode(IAnimatedMesh* mesh, ISceneNode*
CurrentFrameNr(0.f), JointMode(EJUOR_NONE), JointsUsed(false),
TransitionTime(0), Transiting(0.f), TransitingBlend(0.f),
Looping(true), ReadOnlyMaterials(false),
LoopCallBack(0), PassCount(0), Shadow(0), RenderFromIdentity(0)
LoopCallBack(0), PassCount(0), Shadow(0), RenderFromIdentity(0),
MeshForCurrentFrame(0), FrameWhenCurrentMeshWasGenerated(0.f)
{
#ifdef _DEBUG
setDebugName("CAnimatedMeshSceneNode");
......@@ -195,43 +196,15 @@ void CAnimatedMeshSceneNode::OnRegisterSceneNode()
}
}
//! OnAnimate() is called just before rendering the whole scene.
void CAnimatedMeshSceneNode::OnAnimate(u32 timeMs)
IMesh * CAnimatedMeshSceneNode::getMeshForCurrentFrame(void)
{
CurrentFrameNr = buildFrameNr ( timeMs );
if(MeshForCurrentFrame && core::equals(CurrentFrameNr, FrameWhenCurrentMeshWasGenerated))
return MeshForCurrentFrame;
if ( Mesh && (Mesh->getMeshType() != EAMT_SKINNED))
if(Mesh->getMeshType() != EAMT_SKINNED)
{
scene::IMesh *m = Mesh->getMesh((s32)CurrentFrameNr, 255, StartFrame, EndFrame);
if ( m )
Box = m->getBoundingBox();
MeshForCurrentFrame = Mesh->getMesh((s32)getFrameNr(), 255, StartFrame, EndFrame);
}
IAnimatedMeshSceneNode::OnAnimate ( timeMs );
}
//! renders the node.
void CAnimatedMeshSceneNode::render()
{
video::IVideoDriver* driver = SceneManager->getVideoDriver();
if (!Mesh || !driver)
return;
bool isTransparentPass =
SceneManager->getSceneNodeRenderPass() == scene::ESNRP_TRANSPARENT;
++PassCount;
f32 frame = getFrameNr();
scene::IMesh* m;
if (Mesh->getMeshType() != EAMT_SKINNED)
m = Mesh->getMesh((s32)frame, 255, StartFrame, EndFrame);
else
{
CSkinnedMesh* skinnedMesh = reinterpret_cast<CSkinnedMesh*>(Mesh);
......@@ -239,7 +212,7 @@ void CAnimatedMeshSceneNode::render()
if (JointMode == EJUOR_CONTROL)//write to mesh
skinnedMesh->transferJointsToMesh(JointChildSceneNodes);
else
skinnedMesh->animateMesh(frame, 1.0f);
skinnedMesh->animateMesh(getFrameNr(), 1.0f);
skinnedMesh->skinMesh();
......@@ -255,10 +228,48 @@ void CAnimatedMeshSceneNode::render()
}
}
m=skinnedMesh;
MeshForCurrentFrame = skinnedMesh;
}
FrameWhenCurrentMeshWasGenerated = CurrentFrameNr;
return MeshForCurrentFrame;
}
//! OnAnimate() is called just before rendering the whole scene.
void CAnimatedMeshSceneNode::OnAnimate(u32 timeMs)
{
CurrentFrameNr = buildFrameNr ( timeMs );
if ( Mesh )
{
scene::IMesh * mesh = getMeshForCurrentFrame();
if ( mesh )
Box = mesh->getBoundingBox();
}
IAnimatedMeshSceneNode::OnAnimate ( timeMs );
}
//! renders the node.
void CAnimatedMeshSceneNode::render()
{
video::IVideoDriver* driver = SceneManager->getVideoDriver();
if (!Mesh || !driver)
return;
bool isTransparentPass =
SceneManager->getSceneNodeRenderPass() == scene::ESNRP_TRANSPARENT;
++PassCount;
scene::IMesh* m = getMeshForCurrentFrame();
if ( 0 == m )
{
#ifdef _DEBUG
......
......@@ -161,6 +161,9 @@ namespace scene
private:
//! Get a static mesh for the current frame of this animated mesh
IMesh * getMeshForCurrentFrame(void);
f32 buildFrameNr( u32 timeMs);
void checkJoints();
void beginTransition();
......@@ -168,12 +171,14 @@ namespace scene
core::array<video::SMaterial> Materials;
core::aabbox3d<f32> Box;
IAnimatedMesh* Mesh;
IMesh * MeshForCurrentFrame;
u32 BeginFrameTime;
s32 StartFrame;
s32 EndFrame;
f32 FramesPerSecond;
f32 CurrentFrameNr;
f32 FrameWhenCurrentMeshWasGenerated;
E_JOINT_UPDATE_ON_RENDER JointMode; //0-unused, 1-get joints only, 2-set joints only, 3-move and set
bool JointsUsed;
......
......@@ -61,7 +61,6 @@ IMesh* CSkinnedMesh::getMesh(s32 frame, s32 detailLevel, s32 startFrameLoop, s32
animateMesh((f32)frame, 1.0f);
buildAll_LocalAnimatedMatrices();
buildAll_GlobalAnimatedMatrices();
skinMesh();
return this;
}
......@@ -127,6 +126,8 @@ void CSkinnedMesh::animateMesh(f32 frame, f32 blend)
buildAll_LocalAnimatedMatrices();
//-----------------
}
updateBoundingBox();
}
......@@ -428,7 +429,7 @@ void CSkinnedMesh::skinMesh()
return;
//----------------
// Temp!
// This is marked as "Temp!". A shiny dubloon to whomever can tell me why.
buildAll_GlobalAnimatedMatrices();
//-----------------
......@@ -506,6 +507,8 @@ void CSkinnedMesh::SkinJoint(SJoint *joint, SJoint *parentJoint)
//*(weight._Pos) += thisVertexMove * weight.strength;
}
buffersUsed[weight.buffer_id]->boundingBoxNeedsRecalculated();
}
}
......@@ -704,6 +707,7 @@ bool CSkinnedMesh::setHardwareSkinning(bool on)
const u32 vertex_id=joint->Weights[j].vertex_id;
LocalBuffers[buffer_id]->getVertex(vertex_id)->Pos = joint->Weights[j].StaticPos;
LocalBuffers[buffer_id]->getVertex(vertex_id)->Normal = joint->Weights[j].StaticNormal;
LocalBuffers[buffer_id]->boundingBoxNeedsRecalculated();
}
}
......@@ -1096,11 +1100,28 @@ void CSkinnedMesh::finalize()
BoundingBox.addInternalBox(bb);
}
}
}
void CSkinnedMesh::updateBoundingBox(void)
{
if(!SkinningBuffers)
return;
//add 5% padding to bounding box
const core::vector3df Padding = BoundingBox.getExtent()*0.05f;
BoundingBox.MinEdge -= Padding;
BoundingBox.MaxEdge += Padding;
core::array<SSkinMeshBuffer*> & buffer = *SkinningBuffers;
BoundingBox.reset(0,0,0);
if (!buffer.empty())
{
for (u32 j=0; j<buffer.size(); ++j)
{
buffer[j]->recalculateBoundingBox();
core::aabbox3df bb = buffer[j]->BoundingBox;
buffer[j]->Transformation.transformBoxEx(bb);
BoundingBox.addInternalBox(bb);
}
}
}
......
......@@ -168,6 +168,7 @@ private:
core::vector3df& vt1, core::vector3df& vt2, core::vector3df& vt3,
core::vector2df& tc1, core::vector2df& tc2, core::vector2df& tc3);
void updateBoundingBox(void);
core::array<SSkinMeshBuffer*> *SkinningBuffers; //Meshbuffer to skin, default is to skin localBuffers
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment