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 ...@@ -19,7 +19,9 @@ namespace scene
struct SSkinMeshBuffer : public IMeshBuffer struct SSkinMeshBuffer : public IMeshBuffer
{ {
//! Default constructor //! 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 #ifdef _DEBUG
setDebugName("SSkinMeshBuffer"); setDebugName("SSkinMeshBuffer");
...@@ -131,6 +133,11 @@ struct SSkinMeshBuffer : public IMeshBuffer ...@@ -131,6 +133,11 @@ struct SSkinMeshBuffer : public IMeshBuffer
//! Recalculate bounding box //! Recalculate bounding box
virtual void recalculateBoundingBox() virtual void recalculateBoundingBox()
{ {
if(!BoundingBoxNeedsRecalculated)
return;
BoundingBoxNeedsRecalculated = false;
switch (VertexType) switch (VertexType)
{ {
case video::EVT_STANDARD: case video::EVT_STANDARD:
...@@ -359,6 +366,9 @@ struct SSkinMeshBuffer : public IMeshBuffer ...@@ -359,6 +366,9 @@ struct SSkinMeshBuffer : public IMeshBuffer
virtual u32 getChangedID_Index() const {return ChangedID_Index;} 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_Vertex;
u32 ChangedID_Index; u32 ChangedID_Index;
...@@ -376,6 +386,7 @@ struct SSkinMeshBuffer : public IMeshBuffer ...@@ -376,6 +386,7 @@ struct SSkinMeshBuffer : public IMeshBuffer
core::array<video::S3DVertex> Vertices_Standard; core::array<video::S3DVertex> Vertices_Standard;
core::array<u16> Indices; core::array<u16> Indices;
core::aabbox3d<f32> BoundingBox; core::aabbox3d<f32> BoundingBox;
bool BoundingBoxNeedsRecalculated;
}; };
......
...@@ -33,7 +33,8 @@ CAnimatedMeshSceneNode::CAnimatedMeshSceneNode(IAnimatedMesh* mesh, ISceneNode* ...@@ -33,7 +33,8 @@ CAnimatedMeshSceneNode::CAnimatedMeshSceneNode(IAnimatedMesh* mesh, ISceneNode*
CurrentFrameNr(0.f), JointMode(EJUOR_NONE), JointsUsed(false), CurrentFrameNr(0.f), JointMode(EJUOR_NONE), JointsUsed(false),
TransitionTime(0), Transiting(0.f), TransitingBlend(0.f), TransitionTime(0), Transiting(0.f), TransitingBlend(0.f),
Looping(true), ReadOnlyMaterials(false), 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 #ifdef _DEBUG
setDebugName("CAnimatedMeshSceneNode"); setDebugName("CAnimatedMeshSceneNode");
...@@ -195,43 +196,15 @@ void CAnimatedMeshSceneNode::OnRegisterSceneNode() ...@@ -195,43 +196,15 @@ void CAnimatedMeshSceneNode::OnRegisterSceneNode()
} }
} }
IMesh * CAnimatedMeshSceneNode::getMeshForCurrentFrame(void)
//! OnAnimate() is called just before rendering the whole scene.
void CAnimatedMeshSceneNode::OnAnimate(u32 timeMs)
{ {
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); MeshForCurrentFrame = Mesh->getMesh((s32)getFrameNr(), 255, StartFrame, EndFrame);
if ( m )
Box = m->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;
f32 frame = getFrameNr();
scene::IMesh* m;
if (Mesh->getMeshType() != EAMT_SKINNED)
m = Mesh->getMesh((s32)frame, 255, StartFrame, EndFrame);
else else
{ {
CSkinnedMesh* skinnedMesh = reinterpret_cast<CSkinnedMesh*>(Mesh); CSkinnedMesh* skinnedMesh = reinterpret_cast<CSkinnedMesh*>(Mesh);
...@@ -239,7 +212,7 @@ void CAnimatedMeshSceneNode::render() ...@@ -239,7 +212,7 @@ void CAnimatedMeshSceneNode::render()
if (JointMode == EJUOR_CONTROL)//write to mesh if (JointMode == EJUOR_CONTROL)//write to mesh
skinnedMesh->transferJointsToMesh(JointChildSceneNodes); skinnedMesh->transferJointsToMesh(JointChildSceneNodes);
else else
skinnedMesh->animateMesh(frame, 1.0f); skinnedMesh->animateMesh(getFrameNr(), 1.0f);
skinnedMesh->skinMesh(); skinnedMesh->skinMesh();
...@@ -255,10 +228,48 @@ void CAnimatedMeshSceneNode::render() ...@@ -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 ) if ( 0 == m )
{ {
#ifdef _DEBUG #ifdef _DEBUG
......
...@@ -161,6 +161,9 @@ namespace scene ...@@ -161,6 +161,9 @@ namespace scene
private: private:
//! Get a static mesh for the current frame of this animated mesh
IMesh * getMeshForCurrentFrame(void);
f32 buildFrameNr( u32 timeMs); f32 buildFrameNr( u32 timeMs);
void checkJoints(); void checkJoints();
void beginTransition(); void beginTransition();
...@@ -168,12 +171,14 @@ namespace scene ...@@ -168,12 +171,14 @@ namespace scene
core::array<video::SMaterial> Materials; core::array<video::SMaterial> Materials;
core::aabbox3d<f32> Box; core::aabbox3d<f32> Box;
IAnimatedMesh* Mesh; IAnimatedMesh* Mesh;
IMesh * MeshForCurrentFrame;
u32 BeginFrameTime; u32 BeginFrameTime;
s32 StartFrame; s32 StartFrame;
s32 EndFrame; s32 EndFrame;
f32 FramesPerSecond; f32 FramesPerSecond;
f32 CurrentFrameNr; f32 CurrentFrameNr;
f32 FrameWhenCurrentMeshWasGenerated;
E_JOINT_UPDATE_ON_RENDER JointMode; //0-unused, 1-get joints only, 2-set joints only, 3-move and set E_JOINT_UPDATE_ON_RENDER JointMode; //0-unused, 1-get joints only, 2-set joints only, 3-move and set
bool JointsUsed; bool JointsUsed;
......
...@@ -61,7 +61,6 @@ IMesh* CSkinnedMesh::getMesh(s32 frame, s32 detailLevel, s32 startFrameLoop, s32 ...@@ -61,7 +61,6 @@ IMesh* CSkinnedMesh::getMesh(s32 frame, s32 detailLevel, s32 startFrameLoop, s32
animateMesh((f32)frame, 1.0f); animateMesh((f32)frame, 1.0f);
buildAll_LocalAnimatedMatrices(); buildAll_LocalAnimatedMatrices();
buildAll_GlobalAnimatedMatrices();
skinMesh(); skinMesh();
return this; return this;
} }
...@@ -127,6 +126,8 @@ void CSkinnedMesh::animateMesh(f32 frame, f32 blend) ...@@ -127,6 +126,8 @@ void CSkinnedMesh::animateMesh(f32 frame, f32 blend)
buildAll_LocalAnimatedMatrices(); buildAll_LocalAnimatedMatrices();
//----------------- //-----------------
} }
updateBoundingBox();
} }
...@@ -428,7 +429,7 @@ void CSkinnedMesh::skinMesh() ...@@ -428,7 +429,7 @@ void CSkinnedMesh::skinMesh()
return; return;
//---------------- //----------------
// Temp! // This is marked as "Temp!". A shiny dubloon to whomever can tell me why.
buildAll_GlobalAnimatedMatrices(); buildAll_GlobalAnimatedMatrices();
//----------------- //-----------------
...@@ -506,6 +507,8 @@ void CSkinnedMesh::SkinJoint(SJoint *joint, SJoint *parentJoint) ...@@ -506,6 +507,8 @@ void CSkinnedMesh::SkinJoint(SJoint *joint, SJoint *parentJoint)
//*(weight._Pos) += thisVertexMove * weight.strength; //*(weight._Pos) += thisVertexMove * weight.strength;
} }
buffersUsed[weight.buffer_id]->boundingBoxNeedsRecalculated();
} }
} }
...@@ -704,6 +707,7 @@ bool CSkinnedMesh::setHardwareSkinning(bool on) ...@@ -704,6 +707,7 @@ bool CSkinnedMesh::setHardwareSkinning(bool on)
const u32 vertex_id=joint->Weights[j].vertex_id; 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)->Pos = joint->Weights[j].StaticPos;
LocalBuffers[buffer_id]->getVertex(vertex_id)->Normal = joint->Weights[j].StaticNormal; LocalBuffers[buffer_id]->getVertex(vertex_id)->Normal = joint->Weights[j].StaticNormal;
LocalBuffers[buffer_id]->boundingBoxNeedsRecalculated();
} }
} }
...@@ -1096,11 +1100,28 @@ void CSkinnedMesh::finalize() ...@@ -1096,11 +1100,28 @@ void CSkinnedMesh::finalize()
BoundingBox.addInternalBox(bb); BoundingBox.addInternalBox(bb);
} }
} }
}
void CSkinnedMesh::updateBoundingBox(void)
{
if(!SkinningBuffers)
return;
//add 5% padding to bounding box core::array<SSkinMeshBuffer*> & buffer = *SkinningBuffers;
const core::vector3df Padding = BoundingBox.getExtent()*0.05f; BoundingBox.reset(0,0,0);
BoundingBox.MinEdge -= Padding;
BoundingBox.MaxEdge += Padding; 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: ...@@ -168,6 +168,7 @@ private:
core::vector3df& vt1, core::vector3df& vt2, core::vector3df& vt3, core::vector3df& vt1, core::vector3df& vt2, core::vector3df& vt3,
core::vector2df& tc1, core::vector2df& tc2, core::vector2df& tc3); core::vector2df& tc1, core::vector2df& tc2, core::vector2df& tc3);
void updateBoundingBox(void);
core::array<SSkinMeshBuffer*> *SkinningBuffers; //Meshbuffer to skin, default is to skin localBuffers 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