Fix setMesh for skinned meshes, as reported by wing64. The joints cache was not updated, and hence the node reported and returned wrong joints.
Added support for resetting the transition time to 0. Fixed some method names (correct camel case, create replaced by add, upper case fixed) in skinnedMesh.cpp git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@3526 dfc29bdd-3216-0410-991c-e03cc46cb475master
parent
49fc81f564
commit
9f6d50804a
|
@ -32,20 +32,17 @@ CAnimatedMeshSceneNode::CAnimatedMeshSceneNode(IAnimatedMesh* mesh,
|
|||
const core::vector3df& rotation,
|
||||
const core::vector3df& scale)
|
||||
: IAnimatedMeshSceneNode(parent, mgr, id, position, rotation, scale), Mesh(0),
|
||||
StartFrame(0), EndFrame(0), FramesPerSecond(0.f),
|
||||
StartFrame(0), EndFrame(0), FramesPerSecond(0.025f),
|
||||
CurrentFrameNr(0.f), LastTimeMs(0),
|
||||
TransitionTime(0), Transiting(0.f), TransitingBlend(0.f),
|
||||
JointMode(EJUOR_NONE), JointsUsed(false),
|
||||
Looping(true), ReadOnlyMaterials(false), RenderFromIdentity(0),
|
||||
LoopCallBack(0), PassCount(0), Shadow(0),
|
||||
MD3Special ( 0 )
|
||||
Looping(true), ReadOnlyMaterials(false), RenderFromIdentity(false),
|
||||
LoopCallBack(0), PassCount(0), Shadow(0), MD3Special(0)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CAnimatedMeshSceneNode");
|
||||
#endif
|
||||
|
||||
FramesPerSecond = 25.f/1000.f;
|
||||
|
||||
setMesh(mesh);
|
||||
}
|
||||
|
||||
|
@ -54,7 +51,7 @@ CAnimatedMeshSceneNode::CAnimatedMeshSceneNode(IAnimatedMesh* mesh,
|
|||
CAnimatedMeshSceneNode::~CAnimatedMeshSceneNode()
|
||||
{
|
||||
if (MD3Special)
|
||||
MD3Special->drop ();
|
||||
MD3Special->drop();
|
||||
|
||||
if (Mesh)
|
||||
Mesh->drop();
|
||||
|
@ -62,10 +59,6 @@ CAnimatedMeshSceneNode::~CAnimatedMeshSceneNode()
|
|||
if (Shadow)
|
||||
Shadow->drop();
|
||||
|
||||
//for (u32 i=0; i<JointChildSceneNodes.size(); ++i)
|
||||
// if (JointChildSceneNodes[i])
|
||||
// JointChildSceneNodes[i]->drop();
|
||||
|
||||
if (LoopCallBack)
|
||||
LoopCallBack->drop();
|
||||
}
|
||||
|
@ -604,7 +597,7 @@ IBoneSceneNode* CAnimatedMeshSceneNode::getJointNode(const c8* jointName)
|
|||
return 0;
|
||||
}
|
||||
|
||||
return getJointNode((u32)number);
|
||||
return JointChildSceneNodes[number];
|
||||
}
|
||||
|
||||
|
||||
|
@ -673,10 +666,12 @@ bool CAnimatedMeshSceneNode::removeChild(ISceneNode* child)
|
|||
if (JointsUsed) //stop weird bugs caused while changing parents as the joints are being created
|
||||
{
|
||||
for (u32 i=0; i<JointChildSceneNodes.size(); ++i)
|
||||
if (JointChildSceneNodes[i] == child)
|
||||
{
|
||||
JointChildSceneNodes[i] = 0; //remove link to child
|
||||
return true;
|
||||
if (JointChildSceneNodes[i] == child)
|
||||
{
|
||||
JointChildSceneNodes[i] = 0; //remove link to child
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
@ -836,16 +831,24 @@ void CAnimatedMeshSceneNode::setMesh(IAnimatedMesh* mesh)
|
|||
}
|
||||
}
|
||||
|
||||
// clean up joint nodes
|
||||
if (JointsUsed)
|
||||
{
|
||||
JointsUsed=false;
|
||||
checkJoints();
|
||||
}
|
||||
|
||||
// get start and begin time
|
||||
setFrameLoop ( 0, Mesh->getFrameCount() );
|
||||
// setAnimationSpeed(Mesh->getAnimationSpeed());
|
||||
setFrameLoop(0, Mesh->getFrameCount());
|
||||
}
|
||||
|
||||
|
||||
// returns the absolute transformation for a special MD3 Tag if the mesh is a md3 mesh,
|
||||
// or the absolutetransformation if it's a normal scenenode
|
||||
const SMD3QuaternionTag* CAnimatedMeshSceneNode::getMD3TagTransformation( const core::stringc & tagname)
|
||||
const SMD3QuaternionTag* CAnimatedMeshSceneNode::getMD3TagTransformation(const core::stringc& tagname)
|
||||
{
|
||||
return MD3Special ? MD3Special->AbsoluteTagList.get ( tagname ) : 0;
|
||||
return MD3Special ? MD3Special->AbsoluteTagList.get(tagname) : 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -892,10 +895,6 @@ void CAnimatedMeshSceneNode::updateAbsolutePosition()
|
|||
void CAnimatedMeshSceneNode::setJointMode(E_JOINT_UPDATE_ON_RENDER mode)
|
||||
{
|
||||
checkJoints();
|
||||
|
||||
//if (mode<0) mode=0;
|
||||
//if (mode>3) mode=3;
|
||||
|
||||
JointMode=mode;
|
||||
}
|
||||
|
||||
|
@ -904,98 +903,94 @@ void CAnimatedMeshSceneNode::setJointMode(E_JOINT_UPDATE_ON_RENDER mode)
|
|||
//! you must call animateJoints(), or the mesh will not animate
|
||||
void CAnimatedMeshSceneNode::setTransitionTime(f32 time)
|
||||
{
|
||||
if (time != 0.0f)
|
||||
{
|
||||
checkJoints();
|
||||
const u32 ttime = (u32)core::floor32(time*1000.0f);
|
||||
if (TransitionTime==ttime)
|
||||
return;
|
||||
TransitionTime = ttime;
|
||||
if (ttime != 0)
|
||||
setJointMode(EJUOR_CONTROL);
|
||||
TransitionTime = (u32)core::floor32(time*1000.0f);
|
||||
}
|
||||
else
|
||||
setJointMode(EJUOR_NONE);
|
||||
}
|
||||
|
||||
|
||||
//! render mesh ignoring its transformation. Used with ragdolls. (culling is unaffected)
|
||||
void CAnimatedMeshSceneNode::setRenderFromIdentity( bool On )
|
||||
void CAnimatedMeshSceneNode::setRenderFromIdentity(bool enable)
|
||||
{
|
||||
RenderFromIdentity=On;
|
||||
RenderFromIdentity=enable;
|
||||
}
|
||||
|
||||
|
||||
//! updates the joint positions of this mesh
|
||||
void CAnimatedMeshSceneNode::animateJoints(bool CalculateAbsolutePositions)
|
||||
{
|
||||
checkJoints();
|
||||
|
||||
if (Mesh && Mesh->getMeshType() == EAMT_SKINNED )
|
||||
{
|
||||
if (JointsUsed)
|
||||
checkJoints();
|
||||
const f32 frame = getFrameNr(); //old?
|
||||
|
||||
CSkinnedMesh* skinnedMesh=reinterpret_cast<CSkinnedMesh*>(Mesh);
|
||||
|
||||
skinnedMesh->transferOnlyJointsHintsToMesh( JointChildSceneNodes );
|
||||
skinnedMesh->animateMesh(frame, 1.0f);
|
||||
skinnedMesh->recoverJointsFromMesh( JointChildSceneNodes);
|
||||
|
||||
//-----------------------------------------
|
||||
// Transition
|
||||
//-----------------------------------------
|
||||
|
||||
if (Transiting != 0.f)
|
||||
{
|
||||
f32 frame = getFrameNr(); //old?
|
||||
|
||||
CSkinnedMesh* skinnedMesh=reinterpret_cast<CSkinnedMesh*>(Mesh);
|
||||
|
||||
skinnedMesh->transferOnlyJointsHintsToMesh( JointChildSceneNodes );
|
||||
|
||||
skinnedMesh->animateMesh(frame, 1.0f);
|
||||
|
||||
skinnedMesh->recoverJointsFromMesh( JointChildSceneNodes);
|
||||
|
||||
//-----------------------------------------
|
||||
// Transition
|
||||
//-----------------------------------------
|
||||
|
||||
if (Transiting != 0.f)
|
||||
// Init additional matrices
|
||||
if (PretransitingSave.size()<JointChildSceneNodes.size())
|
||||
{
|
||||
//Check the array is big enough (not really needed)
|
||||
if (PretransitingSave.size()<JointChildSceneNodes.size())
|
||||
{
|
||||
for(u32 n=PretransitingSave.size(); n<JointChildSceneNodes.size(); ++n)
|
||||
PretransitingSave.push_back(core::matrix4());
|
||||
}
|
||||
|
||||
for (u32 n=0; n<JointChildSceneNodes.size(); ++n)
|
||||
{
|
||||
//------Position------
|
||||
|
||||
JointChildSceneNodes[n]->setPosition(
|
||||
core::lerp(
|
||||
PretransitingSave[n].getTranslation(),
|
||||
JointChildSceneNodes[n]->getPosition(),
|
||||
TransitingBlend));
|
||||
|
||||
//------Rotation------
|
||||
|
||||
//Code is slow, needs to be fixed up
|
||||
|
||||
const core::quaternion RotationStart(PretransitingSave[n].getRotationDegrees()*core::DEGTORAD);
|
||||
const core::quaternion RotationEnd(JointChildSceneNodes[n]->getRotation()*core::DEGTORAD);
|
||||
|
||||
core::quaternion QRotation;
|
||||
QRotation.slerp(RotationStart, RotationEnd, TransitingBlend);
|
||||
|
||||
core::vector3df tmpVector;
|
||||
QRotation.toEuler(tmpVector);
|
||||
tmpVector*=core::RADTODEG; //convert from radians back to degrees
|
||||
JointChildSceneNodes[n]->setRotation( tmpVector );
|
||||
|
||||
//------Scale------
|
||||
|
||||
//JointChildSceneNodes[n]->setScale(
|
||||
// core::lerp(
|
||||
// PretransitingSave[n].getScale(),
|
||||
// JointChildSceneNodes[n]->getScale(),
|
||||
// TransitingBlend));
|
||||
}
|
||||
for(u32 n=PretransitingSave.size(); n<JointChildSceneNodes.size(); ++n)
|
||||
PretransitingSave.push_back(core::matrix4());
|
||||
}
|
||||
|
||||
if (CalculateAbsolutePositions)
|
||||
for (u32 n=0; n<JointChildSceneNodes.size(); ++n)
|
||||
{
|
||||
//---slow---
|
||||
for (u32 n=0;n<JointChildSceneNodes.size();++n)
|
||||
//------Position------
|
||||
|
||||
JointChildSceneNodes[n]->setPosition(
|
||||
core::lerp(
|
||||
PretransitingSave[n].getTranslation(),
|
||||
JointChildSceneNodes[n]->getPosition(),
|
||||
TransitingBlend));
|
||||
|
||||
//------Rotation------
|
||||
|
||||
//Code is slow, needs to be fixed up
|
||||
|
||||
const core::quaternion RotationStart(PretransitingSave[n].getRotationDegrees()*core::DEGTORAD);
|
||||
const core::quaternion RotationEnd(JointChildSceneNodes[n]->getRotation()*core::DEGTORAD);
|
||||
|
||||
core::quaternion QRotation;
|
||||
QRotation.slerp(RotationStart, RotationEnd, TransitingBlend);
|
||||
|
||||
core::vector3df tmpVector;
|
||||
QRotation.toEuler(tmpVector);
|
||||
tmpVector*=core::RADTODEG; //convert from radians back to degrees
|
||||
JointChildSceneNodes[n]->setRotation( tmpVector );
|
||||
|
||||
//------Scale------
|
||||
|
||||
//JointChildSceneNodes[n]->setScale(
|
||||
// core::lerp(
|
||||
// PretransitingSave[n].getScale(),
|
||||
// JointChildSceneNodes[n]->getScale(),
|
||||
// TransitingBlend));
|
||||
}
|
||||
}
|
||||
|
||||
if (CalculateAbsolutePositions)
|
||||
{
|
||||
//---slow---
|
||||
for (u32 n=0;n<JointChildSceneNodes.size();++n)
|
||||
{
|
||||
if (JointChildSceneNodes[n]->getParent()==this)
|
||||
{
|
||||
if (JointChildSceneNodes[n]->getParent()==this)
|
||||
{
|
||||
JointChildSceneNodes[n]->updateAbsolutePositionOfAllChildren(); //temp, should be an option
|
||||
}
|
||||
JointChildSceneNodes[n]->updateAbsolutePositionOfAllChildren(); //temp, should be an option
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1012,9 +1007,12 @@ void CAnimatedMeshSceneNode::checkJoints()
|
|||
|
||||
if (!JointsUsed)
|
||||
{
|
||||
//Create joints for SkinnedMesh
|
||||
for (u32 i=0; i<JointChildSceneNodes.size(); ++i)
|
||||
removeChild(JointChildSceneNodes[i]);
|
||||
JointChildSceneNodes.clear();
|
||||
|
||||
((CSkinnedMesh*)Mesh)->createJoints(JointChildSceneNodes, this, SceneManager);
|
||||
//Create joints for SkinnedMesh
|
||||
((CSkinnedMesh*)Mesh)->addJoints(JointChildSceneNodes, this, SceneManager);
|
||||
((CSkinnedMesh*)Mesh)->recoverJointsFromMesh(JointChildSceneNodes);
|
||||
|
||||
JointsUsed=true;
|
||||
|
@ -1039,7 +1037,6 @@ void CAnimatedMeshSceneNode::beginTransition()
|
|||
PretransitingSave.push_back(core::matrix4());
|
||||
}
|
||||
|
||||
|
||||
//Copy the position of joints
|
||||
for (u32 n=0;n<JointChildSceneNodes.size();++n)
|
||||
PretransitingSave[n]=JointChildSceneNodes[n]->getRelativeTransformation();
|
||||
|
@ -1054,14 +1051,16 @@ void CAnimatedMeshSceneNode::beginTransition()
|
|||
*/
|
||||
ISceneNode* CAnimatedMeshSceneNode::clone(ISceneNode* newParent, ISceneManager* newManager)
|
||||
{
|
||||
if (!newParent) newParent = Parent;
|
||||
if (!newManager) newManager = SceneManager;
|
||||
if (!newParent)
|
||||
newParent = Parent;
|
||||
if (!newManager)
|
||||
newManager = SceneManager;
|
||||
|
||||
CAnimatedMeshSceneNode * newNode =
|
||||
CAnimatedMeshSceneNode* newNode =
|
||||
new CAnimatedMeshSceneNode(Mesh, NULL, newManager, ID, RelativeTranslation,
|
||||
RelativeRotation, RelativeScale);
|
||||
|
||||
if ( newParent )
|
||||
if (newParent)
|
||||
{
|
||||
newNode->setParent(newParent); // not in constructor because virtual overload for updateAbsolutePosition won't be called
|
||||
newNode->drop();
|
||||
|
@ -1097,4 +1096,3 @@ ISceneNode* CAnimatedMeshSceneNode::clone(ISceneNode* newParent, ISceneManager*
|
|||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
|
||||
|
|
|
@ -18,11 +18,10 @@ namespace scene
|
|||
|
||||
//! constructor
|
||||
CSkinnedMesh::CSkinnedMesh()
|
||||
: SkinningBuffers(0), AnimationFrames(0.f),
|
||||
LastAnimatedFrame(0.f), LastSkinnedFrame(0.f),
|
||||
InterpolationMode(EIM_LINEAR),
|
||||
: SkinningBuffers(0), AnimationFrames(0.f), FramesPerSecond(25.f),
|
||||
LastAnimatedFrame(0.f), InterpolationMode(EIM_LINEAR),
|
||||
HasAnimation(false), PreparedForSkinning(false),
|
||||
BoneControlUsed(false), AnimateNormals(true), HardwareSkinning(false)
|
||||
AnimateNormals(true), HardwareSkinning(false)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CSkinnedMesh");
|
||||
|
@ -54,6 +53,23 @@ u32 CSkinnedMesh::getFrameCount() const
|
|||
}
|
||||
|
||||
|
||||
//! Gets the default animation speed of the animated mesh.
|
||||
/** \return Amount of frames per second. If the amount is 0, it is a static, non animated mesh. */
|
||||
f32 CSkinnedMesh::getAnimationSpeed() const
|
||||
{
|
||||
return FramesPerSecond;
|
||||
}
|
||||
|
||||
|
||||
//! Gets the frame count of the animated mesh.
|
||||
/** \param fps Frames per second to play the animation with. If the amount is 0, it is not animated.
|
||||
The actual speed is set in the scene node the mesh is instantiated in.*/
|
||||
void CSkinnedMesh::setAnimationSpeed(f32 fps)
|
||||
{
|
||||
FramesPerSecond=fps;
|
||||
}
|
||||
|
||||
|
||||
//! returns the animated mesh based on a detail level. 0 is the lowest, 255 the highest detail. Note, that some Meshes will ignore the detail level.
|
||||
IMesh* CSkinnedMesh::getMesh(s32 frame, s32 detailLevel, s32 startFrameLoop, s32 endFrameLoop)
|
||||
{
|
||||
|
@ -125,14 +141,14 @@ void CSkinnedMesh::animateMesh(f32 frame, f32 blend)
|
|||
|
||||
//----------------
|
||||
// Temp!
|
||||
buildAll_LocalAnimatedMatrices();
|
||||
buildAllLocalAnimatedMatrices();
|
||||
//-----------------
|
||||
|
||||
updateBoundingBox();
|
||||
}
|
||||
|
||||
|
||||
void CSkinnedMesh::buildAll_LocalAnimatedMatrices()
|
||||
void CSkinnedMesh::buildAllLocalAnimatedMatrices()
|
||||
{
|
||||
for (u32 i=0; i<AllJoints.size(); ++i)
|
||||
{
|
||||
|
@ -200,12 +216,12 @@ void CSkinnedMesh::buildAll_LocalAnimatedMatrices()
|
|||
}
|
||||
|
||||
|
||||
void CSkinnedMesh::buildAll_GlobalAnimatedMatrices(SJoint *joint, SJoint *parentJoint)
|
||||
void CSkinnedMesh::buildAllGlobalAnimatedMatrices(SJoint *joint, SJoint *parentJoint)
|
||||
{
|
||||
if (!joint)
|
||||
{
|
||||
for (u32 i=0; i<RootJoints.size(); ++i)
|
||||
buildAll_GlobalAnimatedMatrices(RootJoints[i], 0);
|
||||
buildAllGlobalAnimatedMatrices(RootJoints[i], 0);
|
||||
return;
|
||||
}
|
||||
else
|
||||
|
@ -219,7 +235,7 @@ void CSkinnedMesh::buildAll_GlobalAnimatedMatrices(SJoint *joint, SJoint *parent
|
|||
}
|
||||
|
||||
for (u32 j=0; j<joint->Children.size(); ++j)
|
||||
buildAll_GlobalAnimatedMatrices(joint->Children[j], joint);
|
||||
buildAllGlobalAnimatedMatrices(joint->Children[j], joint);
|
||||
}
|
||||
|
||||
|
||||
|
@ -426,12 +442,12 @@ void CSkinnedMesh::getFrameData(f32 frame, SJoint *joint,
|
|||
//! Preforms a software skin on this mesh based of joint positions
|
||||
void CSkinnedMesh::skinMesh()
|
||||
{
|
||||
if ( !HasAnimation)
|
||||
if (!HasAnimation)
|
||||
return;
|
||||
|
||||
//----------------
|
||||
// This is marked as "Temp!". A shiny dubloon to whomever can tell me why.
|
||||
buildAll_GlobalAnimatedMatrices();
|
||||
buildAllGlobalAnimatedMatrices();
|
||||
//-----------------
|
||||
|
||||
if (!HardwareSkinning)
|
||||
|
@ -456,7 +472,7 @@ void CSkinnedMesh::skinMesh()
|
|||
|
||||
//skin starting with the root joints
|
||||
for (i=0; i<RootJoints.size(); ++i)
|
||||
SkinJoint(RootJoints[i], 0);
|
||||
skinJoint(RootJoints[i], 0);
|
||||
|
||||
for (i=0; i<SkinningBuffers->size(); ++i)
|
||||
(*SkinningBuffers)[i]->setDirty(EBT_VERTEX);
|
||||
|
@ -465,7 +481,7 @@ void CSkinnedMesh::skinMesh()
|
|||
}
|
||||
|
||||
|
||||
void CSkinnedMesh::SkinJoint(SJoint *joint, SJoint *parentJoint)
|
||||
void CSkinnedMesh::skinJoint(SJoint *joint, SJoint *parentJoint)
|
||||
{
|
||||
if (joint->Weights.size())
|
||||
{
|
||||
|
@ -515,7 +531,7 @@ void CSkinnedMesh::SkinJoint(SJoint *joint, SJoint *parentJoint)
|
|||
|
||||
//Skin all children
|
||||
for (u32 j=0; j<joint->Children.size(); ++j)
|
||||
SkinJoint(joint->Children[j], joint);
|
||||
skinJoint(joint->Children[j], joint);
|
||||
}
|
||||
|
||||
|
||||
|
@ -694,7 +710,6 @@ bool CSkinnedMesh::setHardwareSkinning(bool on)
|
|||
{
|
||||
if (HardwareSkinning!=on)
|
||||
{
|
||||
|
||||
if (on)
|
||||
{
|
||||
|
||||
|
@ -719,7 +734,7 @@ bool CSkinnedMesh::setHardwareSkinning(bool on)
|
|||
}
|
||||
|
||||
|
||||
void CSkinnedMesh::CalculateGlobalMatrices(SJoint *joint,SJoint *parentJoint)
|
||||
void CSkinnedMesh::calculateGlobalMatrices(SJoint *joint,SJoint *parentJoint)
|
||||
{
|
||||
if (!joint && parentJoint) // bit of protection from endless loops
|
||||
return;
|
||||
|
@ -728,7 +743,7 @@ void CSkinnedMesh::CalculateGlobalMatrices(SJoint *joint,SJoint *parentJoint)
|
|||
if (!joint)
|
||||
{
|
||||
for (u32 i=0; i<RootJoints.size(); ++i)
|
||||
CalculateGlobalMatrices(RootJoints[i],0);
|
||||
calculateGlobalMatrices(RootJoints[i],0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -747,7 +762,7 @@ void CSkinnedMesh::CalculateGlobalMatrices(SJoint *joint,SJoint *parentJoint)
|
|||
}
|
||||
|
||||
for (u32 j=0; j<joint->Children.size(); ++j)
|
||||
CalculateGlobalMatrices(joint->Children[j],joint);
|
||||
calculateGlobalMatrices(joint->Children[j],joint);
|
||||
}
|
||||
|
||||
|
||||
|
@ -864,8 +879,8 @@ void CSkinnedMesh::finalize()
|
|||
{
|
||||
u32 i;
|
||||
|
||||
// Make sure we recalc the next frame
|
||||
LastAnimatedFrame=-1;
|
||||
LastSkinnedFrame=-1;
|
||||
|
||||
//calculate bounding box
|
||||
for (i=0; i<LocalBuffers.size(); ++i)
|
||||
|
@ -1066,11 +1081,11 @@ void CSkinnedMesh::finalize()
|
|||
|
||||
//Needed for animation and skinning...
|
||||
|
||||
CalculateGlobalMatrices(0,0);
|
||||
calculateGlobalMatrices(0,0);
|
||||
|
||||
//animateMesh(0, 1);
|
||||
//buildAll_LocalAnimatedMatrices();
|
||||
//buildAll_GlobalAnimatedMatrices();
|
||||
//buildAllLocalAnimatedMatrices();
|
||||
//buildAllGlobalAnimatedMatrices();
|
||||
|
||||
//rigid animation for non animated meshes
|
||||
for (i=0; i<AllJoints.size(); ++i)
|
||||
|
@ -1247,15 +1262,15 @@ void CSkinnedMesh::normalizeWeights()
|
|||
}
|
||||
|
||||
|
||||
void CSkinnedMesh::recoverJointsFromMesh(core::array<IBoneSceneNode*> &JointChildSceneNodes)
|
||||
void CSkinnedMesh::recoverJointsFromMesh(core::array<IBoneSceneNode*> &jointChildSceneNodes)
|
||||
{
|
||||
for (u32 i=0;i<AllJoints.size();++i)
|
||||
for (u32 i=0; i<AllJoints.size(); ++i)
|
||||
{
|
||||
IBoneSceneNode* node=JointChildSceneNodes[i];
|
||||
IBoneSceneNode* node=jointChildSceneNodes[i];
|
||||
SJoint *joint=AllJoints[i];
|
||||
node->setPosition( joint->LocalAnimatedMatrix.getTranslation() );
|
||||
node->setRotation( joint->LocalAnimatedMatrix.getRotationDegrees() );
|
||||
node->setScale( joint->LocalAnimatedMatrix.getScale() );
|
||||
node->setPosition(joint->LocalAnimatedMatrix.getTranslation());
|
||||
node->setRotation(joint->LocalAnimatedMatrix.getRotationDegrees());
|
||||
node->setScale(joint->LocalAnimatedMatrix.getScale());
|
||||
|
||||
node->positionHint=joint->positionHint;
|
||||
node->scaleHint=joint->scaleHint;
|
||||
|
@ -1266,11 +1281,11 @@ void CSkinnedMesh::recoverJointsFromMesh(core::array<IBoneSceneNode*> &JointChil
|
|||
}
|
||||
|
||||
|
||||
void CSkinnedMesh::transferJointsToMesh(const core::array<IBoneSceneNode*> &JointChildSceneNodes)
|
||||
void CSkinnedMesh::transferJointsToMesh(const core::array<IBoneSceneNode*> &jointChildSceneNodes)
|
||||
{
|
||||
for (u32 i=0; i<AllJoints.size(); ++i)
|
||||
{
|
||||
const IBoneSceneNode* const node=JointChildSceneNodes[i];
|
||||
const IBoneSceneNode* const node=jointChildSceneNodes[i];
|
||||
SJoint *joint=AllJoints[i];
|
||||
|
||||
joint->LocalAnimatedMatrix.setRotationDegrees(node->getRotation());
|
||||
|
@ -1283,17 +1298,16 @@ void CSkinnedMesh::transferJointsToMesh(const core::array<IBoneSceneNode*> &Join
|
|||
|
||||
joint->GlobalSkinningSpace=(node->getSkinningSpace()==EBSS_GLOBAL);
|
||||
}
|
||||
//Remove cache, temp...
|
||||
// Make sure we recalc the next frame
|
||||
LastAnimatedFrame=-1;
|
||||
LastSkinnedFrame=-1;
|
||||
}
|
||||
|
||||
|
||||
void CSkinnedMesh::transferOnlyJointsHintsToMesh(const core::array<IBoneSceneNode*> &JointChildSceneNodes)
|
||||
void CSkinnedMesh::transferOnlyJointsHintsToMesh(const core::array<IBoneSceneNode*> &jointChildSceneNodes)
|
||||
{
|
||||
for (u32 i=0;i<AllJoints.size();++i)
|
||||
for (u32 i=0; i<AllJoints.size(); ++i)
|
||||
{
|
||||
const IBoneSceneNode* const node=JointChildSceneNodes[i];
|
||||
const IBoneSceneNode* const node=jointChildSceneNodes[i];
|
||||
SJoint *joint=AllJoints[i];
|
||||
|
||||
joint->positionHint=node->positionHint;
|
||||
|
@ -1303,32 +1317,28 @@ void CSkinnedMesh::transferOnlyJointsHintsToMesh(const core::array<IBoneSceneNod
|
|||
}
|
||||
|
||||
|
||||
void CSkinnedMesh::createJoints(core::array<IBoneSceneNode*> &JointChildSceneNodes,
|
||||
IAnimatedMeshSceneNode* AnimatedMeshSceneNode,
|
||||
ISceneManager* SceneManager)
|
||||
void CSkinnedMesh::addJoints(core::array<IBoneSceneNode*> &jointChildSceneNodes,
|
||||
IAnimatedMeshSceneNode* node, ISceneManager* smgr)
|
||||
{
|
||||
u32 i;
|
||||
|
||||
//Create new joints
|
||||
for (i=0;i<AllJoints.size();++i)
|
||||
for (u32 i=0; i<AllJoints.size(); ++i)
|
||||
{
|
||||
JointChildSceneNodes.push_back(new CBoneSceneNode(0, SceneManager, 0, i, AllJoints[i]->Name.c_str()));
|
||||
jointChildSceneNodes.push_back(new CBoneSceneNode(0, smgr, 0, i, AllJoints[i]->Name.c_str()));
|
||||
}
|
||||
|
||||
//Match up parents
|
||||
for (i=0;i<JointChildSceneNodes.size();++i)
|
||||
for (u32 i=0; i<jointChildSceneNodes.size(); ++i)
|
||||
{
|
||||
IBoneSceneNode* node=JointChildSceneNodes[i];
|
||||
const SJoint* const joint=AllJoints[i]; //should be fine
|
||||
|
||||
s32 parentID=-1;
|
||||
|
||||
for (u32 j=0;j<AllJoints.size();++j)
|
||||
for (u32 j=0;(parentID==-1)&&(j<AllJoints.size());++j)
|
||||
{
|
||||
if (i!=j && parentID==-1)
|
||||
if (i!=j)
|
||||
{
|
||||
const SJoint* const parentTest=AllJoints[j];
|
||||
for (u32 n=0;n<parentTest->Children.size();++n)
|
||||
for (u32 n=0; n<parentTest->Children.size(); ++n)
|
||||
{
|
||||
if (parentTest->Children[n]==joint)
|
||||
{
|
||||
|
@ -1339,12 +1349,13 @@ void CSkinnedMesh::createJoints(core::array<IBoneSceneNode*> &JointChildSceneNod
|
|||
}
|
||||
}
|
||||
|
||||
IBoneSceneNode* bone=jointChildSceneNodes[i];
|
||||
if (parentID!=-1)
|
||||
node->setParent( JointChildSceneNodes[parentID] );
|
||||
bone->setParent(jointChildSceneNodes[parentID]);
|
||||
else
|
||||
node->setParent( AnimatedMeshSceneNode );
|
||||
bone->setParent(node);
|
||||
|
||||
node->drop();
|
||||
bone->drop();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -35,6 +35,15 @@ namespace scene
|
|||
//! returns the amount of frames. If the amount is 1, it is a static (=non animated) mesh.
|
||||
virtual u32 getFrameCount() const;
|
||||
|
||||
//! Gets the default animation speed of the animated mesh.
|
||||
/** \return Amount of frames per second. If the amount is 0, it is a static, non animated mesh. */
|
||||
virtual f32 getAnimationSpeed() const;
|
||||
|
||||
//! Gets the frame count of the animated mesh.
|
||||
/** \param fps Frames per second to play the animation with. If the amount is 0, it is not animated.
|
||||
The actual speed is set in the scene node the mesh is instantiated in.*/
|
||||
virtual void setAnimationSpeed(f32 fps);
|
||||
|
||||
//! returns the animated mesh based on a detail level (which is ignored)
|
||||
virtual IMesh* getMesh(s32 frame, s32 detailLevel=255, s32 startFrameLoop=-1, s32 endFrameLoop=-1);
|
||||
|
||||
|
@ -95,20 +104,6 @@ namespace scene
|
|||
//! Sets Interpolation Mode
|
||||
virtual void setInterpolationMode(E_INTERPOLATION_MODE mode);
|
||||
|
||||
//! Recovers the joints from the mesh
|
||||
virtual void recoverJointsFromMesh(core::array<IBoneSceneNode*> &JointChildSceneNodes);
|
||||
|
||||
//! Tranfers the joint data to the mesh
|
||||
virtual void transferJointsToMesh(const core::array<IBoneSceneNode*> &JointChildSceneNodes);
|
||||
|
||||
//! Tranfers the joint hints to the mesh
|
||||
virtual void transferOnlyJointsHintsToMesh(const core::array<IBoneSceneNode*> &JointChildSceneNodes);
|
||||
|
||||
//! Creates an array of joints from this mesh
|
||||
virtual void createJoints(core::array<IBoneSceneNode*> &JointChildSceneNodes,
|
||||
IAnimatedMeshSceneNode* AnimatedMeshSceneNode,
|
||||
ISceneManager* SceneManager);
|
||||
|
||||
//! Convertes the mesh to contain tangent information
|
||||
virtual void convertMeshToTangents();
|
||||
|
||||
|
@ -119,8 +114,7 @@ namespace scene
|
|||
virtual bool setHardwareSkinning(bool on);
|
||||
|
||||
//Interface for the mesh loaders (finalize should lock these functions, and they should have some prefix like loader_
|
||||
|
||||
//these functions will use the needed arrays, set vaules, etc to help the loaders
|
||||
//these functions will use the needed arrays, set values, etc to help the loaders
|
||||
|
||||
//! exposed for loaders to add mesh buffers
|
||||
virtual core::array<SSkinMeshBuffer*> &getMeshBuffers();
|
||||
|
@ -152,23 +146,37 @@ namespace scene
|
|||
|
||||
virtual void updateBoundingBox(void);
|
||||
|
||||
//! Recovers the joints from the mesh
|
||||
void recoverJointsFromMesh(core::array<IBoneSceneNode*> &jointChildSceneNodes);
|
||||
|
||||
//! Tranfers the joint data to the mesh
|
||||
void transferJointsToMesh(const core::array<IBoneSceneNode*> &jointChildSceneNodes);
|
||||
|
||||
//! Tranfers the joint hints to the mesh
|
||||
void transferOnlyJointsHintsToMesh(const core::array<IBoneSceneNode*> &jointChildSceneNodes);
|
||||
|
||||
//! Creates an array of joints from this mesh as children of node
|
||||
void addJoints(core::array<IBoneSceneNode*> &jointChildSceneNodes,
|
||||
IAnimatedMeshSceneNode* node,
|
||||
ISceneManager* smgr);
|
||||
|
||||
private:
|
||||
void checkForAnimation();
|
||||
|
||||
void normalizeWeights();
|
||||
|
||||
void buildAll_LocalAnimatedMatrices(); //public?
|
||||
void buildAllLocalAnimatedMatrices();
|
||||
|
||||
void buildAll_GlobalAnimatedMatrices(SJoint *Joint=0, SJoint *ParentJoint=0);
|
||||
void buildAllGlobalAnimatedMatrices(SJoint *Joint=0, SJoint *ParentJoint=0);
|
||||
|
||||
void getFrameData(f32 frame, SJoint *Node,
|
||||
core::vector3df &position, s32 &positionHint,
|
||||
core::vector3df &scale, s32 &scaleHint,
|
||||
core::quaternion &rotation, s32 &rotationHint);
|
||||
|
||||
void CalculateGlobalMatrices(SJoint *Joint,SJoint *ParentJoint);
|
||||
void calculateGlobalMatrices(SJoint *Joint,SJoint *ParentJoint);
|
||||
|
||||
void SkinJoint(SJoint *Joint, SJoint *ParentJoint);
|
||||
void skinJoint(SJoint *Joint, SJoint *ParentJoint);
|
||||
|
||||
void calculateTangents(core::vector3df& normal,
|
||||
core::vector3df& tangent, core::vector3df& binormal,
|
||||
|
@ -182,20 +190,19 @@ private:
|
|||
core::array<SJoint*> AllJoints;
|
||||
core::array<SJoint*> RootJoints;
|
||||
|
||||
core::aabbox3d<f32> BoundingBox;
|
||||
|
||||
core::array< core::array<bool> > Vertices_Moved;
|
||||
|
||||
core::aabbox3d<f32> BoundingBox;
|
||||
|
||||
f32 AnimationFrames;
|
||||
f32 FramesPerSecond;
|
||||
|
||||
f32 LastAnimatedFrame;
|
||||
f32 LastSkinnedFrame;
|
||||
|
||||
E_INTERPOLATION_MODE InterpolationMode;
|
||||
E_INTERPOLATION_MODE InterpolationMode:8;
|
||||
|
||||
bool HasAnimation;
|
||||
bool PreparedForSkinning;
|
||||
bool BoneControlUsed;
|
||||
bool AnimateNormals;
|
||||
bool HardwareSkinning;
|
||||
};
|
||||
|
|
|
@ -89,13 +89,14 @@ int main(int argumentCount, char * arguments[])
|
|||
TEST(softwareDevice);
|
||||
TEST(b3dAnimation);
|
||||
TEST(burningsVideo);
|
||||
TEST(createImage);
|
||||
TEST(cursorSetVisible);
|
||||
TEST(flyCircleAnimator);
|
||||
TEST(md2Animation);
|
||||
TEST(meshTransform);
|
||||
TEST(skinnedMesh);
|
||||
TEST(testGeometryCreator);
|
||||
TEST(writeImageToFile);
|
||||
TEST(meshTransform);
|
||||
TEST(createImage);
|
||||
// all driver checks
|
||||
TEST(videoDriver);
|
||||
TEST(drawPixel);
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
// Copyright (C) 2008-2009 Colin MacDonald
|
||||
// No rights reserved: this software is in the public domain.
|
||||
|
||||
#include "testUtils.h"
|
||||
|
||||
using namespace irr;
|
||||
using namespace core;
|
||||
using namespace scene;
|
||||
using namespace video;
|
||||
using namespace io;
|
||||
using namespace gui;
|
||||
|
||||
// Tests skinned meshes.
|
||||
bool skinnedMesh(void)
|
||||
{
|
||||
// Use EDT_BURNINGSVIDEO since it is not dependent on (e.g.) OpenGL driver versions.
|
||||
IrrlichtDevice *device = createDevice( EDT_BURNINGSVIDEO, dimension2d<u32>(160, 120), 32);
|
||||
if (!device)
|
||||
return false;
|
||||
|
||||
IVideoDriver* driver = device->getVideoDriver();
|
||||
ISceneManager * smgr = device->getSceneManager();
|
||||
|
||||
logTestString("Testing setMesh()\n");
|
||||
|
||||
ISkinnedMesh* mesh = (ISkinnedMesh*)smgr->getMesh("../media/ninja.b3d");
|
||||
if (!mesh)
|
||||
return false;
|
||||
|
||||
IAnimatedMeshSceneNode* node = smgr->addAnimatedMeshSceneNode(mesh);
|
||||
if (!node)
|
||||
return false;
|
||||
|
||||
// test if certain joint is found
|
||||
bool result = (node->getJointNode("Joint1") != 0);
|
||||
|
||||
mesh = (ISkinnedMesh*)smgr->getMesh("../media/dwarf.x");
|
||||
if (!mesh)
|
||||
return false;
|
||||
node->setMesh(mesh);
|
||||
|
||||
// make sure old joint is non-existant anymore
|
||||
logTestString("Ignore error message in log, this is intended.\n");
|
||||
result &= (node->getJointNode("Joint1")==0);
|
||||
|
||||
// and check that a new joint can be found
|
||||
// we use a late one, in order to see also inconsistencies in the joint cache
|
||||
result &= (node->getJointNode("cam") != 0);
|
||||
|
||||
device->closeDevice();
|
||||
device->run();
|
||||
device->drop();
|
||||
|
||||
return result;
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
Tests finished. 59 tests of 59 passed.
|
||||
Tests finished. 60 tests of 60 passed.
|
||||
Compiled as DEBUG
|
||||
Test suite pass at GMT Tue Dec 28 19:10:59 2010
|
||||
Test suite pass at GMT Thu Dec 30 14:45:02 2010
|
||||
|
||||
|
|
|
@ -71,6 +71,8 @@
|
|||
<Unit filename="removeCustomAnimator.cpp" />
|
||||
<Unit filename="sceneCollisionManager.cpp" />
|
||||
<Unit filename="sceneNodeAnimator.cpp" />
|
||||
<Unit filename="serializeAttributes.cpp" />
|
||||
<Unit filename="skinnedMesh.cpp" />
|
||||
<Unit filename="softwareDevice.cpp" />
|
||||
<Unit filename="terrainSceneNode.cpp" />
|
||||
<Unit filename="testDimension2d.cpp" />
|
||||
|
|
|
@ -124,6 +124,7 @@
|
|||
<ClCompile Include="sceneCollisionManager.cpp" />
|
||||
<ClCompile Include="sceneNodeAnimator.cpp" />
|
||||
<ClCompile Include="serializeAttributes.cpp" />
|
||||
<ClCompile Include="skinnedMesh.cpp" />
|
||||
<ClCompile Include="softwareDevice.cpp" />
|
||||
<ClCompile Include="stencilshadow.cpp" />
|
||||
<ClCompile Include="terrainSceneNode.cpp" />
|
||||
|
|
|
@ -196,6 +196,10 @@
|
|||
RelativePath=".\collisionResponseAnimator.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\color.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\createImage.cpp"
|
||||
>
|
||||
|
@ -208,6 +212,10 @@
|
|||
RelativePath=".\disambiguateTextures.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\draw2DImage.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\drawPixel.cpp"
|
||||
>
|
||||
|
@ -240,18 +248,42 @@
|
|||
RelativePath=".\guiDisabledMenu.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\irrArray.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\irrCoreEquals.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\irrList.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\irrMap.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\irrString.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\lightMaps.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\lights.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\line2dIntersectWith.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\loadTextures.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\main.cpp"
|
||||
>
|
||||
|
@ -280,6 +312,10 @@
|
|||
RelativePath=".\mrt.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\orthoCam.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\planeMatrix.cpp"
|
||||
>
|
||||
|
@ -292,6 +328,10 @@
|
|||
RelativePath=".\removeCustomAnimator.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\renderTargetTexture.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\sceneCollisionManager.cpp"
|
||||
>
|
||||
|
@ -300,14 +340,30 @@
|
|||
RelativePath=".\sceneNodeAnimator.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\serializeAttributes.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\skinnedMesh.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\softwareDevice.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\stencilshadow.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\terrainSceneNode.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\testaabbox.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\testDimension2d.cpp"
|
||||
>
|
||||
|
@ -316,6 +372,14 @@
|
|||
RelativePath=".\testGeometryCreator.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\testQuaternion.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\testS3DVertex.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\testUtils.cpp"
|
||||
>
|
||||
|
@ -328,10 +392,22 @@
|
|||
RelativePath=".\testVector3d.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\testXML.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\textureFeatures.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\textureRenderStates.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\timer.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\transparentMaterials.cpp"
|
||||
>
|
||||
|
@ -352,10 +428,6 @@
|
|||
RelativePath=".\writeImageToFile.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\zipReader.cpp"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
|
|
|
@ -343,6 +343,10 @@
|
|||
RelativePath=".\serializeAttributes.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\skinnedMesh.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\softwareDevice.cpp"
|
||||
>
|
||||
|
|
Loading…
Reference in New Issue