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-e03cc46cb475
master
hybrid 2010-12-30 14:49:19 +00:00
parent 49fc81f564
commit 9f6d50804a
10 changed files with 336 additions and 185 deletions

View File

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

View File

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

View File

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

View File

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

55
tests/skinnedMesh.cpp Normal file
View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -343,6 +343,10 @@
RelativePath=".\serializeAttributes.cpp"
>
</File>
<File
RelativePath=".\skinnedMesh.cpp"
>
</File>
<File
RelativePath=".\softwareDevice.cpp"
>