added IAnimatedMeshSceneNode::getXJointNode

A forum to store posts deemed exceptionally wise and useful
Post Reply
Electron
Posts: 874
Joined: Sun Mar 14, 2004 12:05 am
Location: Massachusetts USA

added IAnimatedMeshSceneNode::getXJointNode

Post by Electron »

same as getMS3DJointNode except for .X meshes. It was very easy to add, most of it was copying and pasting the code for ms3d.

add the following:
to IAnimatedMeshSceneNode.h

Code: Select all

public:
//! Returns a pointer to a child node, wich has the same transformation as 
//! the corrsesponding joint, if the mesh in this scene node is a .X mesh.
virtual ISceneNode* getXJointNode(const c8* jointName)=0;
to CAnimatedMeshSceneNode.h

Code: Select all

public:
//! Returns a pointer to a child node, wich has the same transformation as 
//! the corrsesponding joint, if the mesh in this scene node is a .X mesh.
virtual ISceneNode* getXJointNode(const c8* jointName);

private:
core::array<IDummyTransformationSceneNode* > JointChildSceneNodesX;
to CAnimatedMeshSceneNode.cpp

Code: Select all

//! Returns a pointer to a child node, wich has the same transformation as 
//! the corrsesponding joint, if the mesh in this scene node is a .X mesh.
ISceneNode* CAnimatedMeshSceneNode::getXJointNode(const c8* jointName)
{
	if (!Mesh || Mesh->getMeshType() != EAMT_X)
		return 0;

	IAnimatedMeshX* amm = (IAnimatedMeshX*)Mesh;
	s32 jointCount = amm->getJointCount();
	s32 number = amm->getJointNumber(jointName);

	if (number == -1)
	{
		os::Printer::log("Joint with specified name not found in .X mesh.", jointName, ELL_WARNING);
		return 0;
	}

	if (JointChildSceneNodesX.empty())
	{
		// allocate joints for the first time.
		JointChildSceneNodesX.set_used(jointCount);
		for (s32 i=0; i<jointCount; ++i)
			JointChildSceneNodesX[i] = 0;
	}

	if (JointChildSceneNodesX[number] == 0)
	{
		JointChildSceneNodesX[number] = 
			SceneManager->addDummyTransformationSceneNode(this);
		JointChildSceneNodesX[number]->grab();
	}

	return JointChildSceneNodesX[number];
}
Now we have to add some code to existing functions. Anything with an
//added by JAMES is new code (James is my name)
all of these are in CAnimatedMeshSceneNode.cpp

the destructor should now look like this

Code: Select all

//! destructor
CAnimatedMeshSceneNode::~CAnimatedMeshSceneNode()
{
	if (Mesh)
		Mesh->drop();

	if (Shadow)
		Shadow->drop();

	for (s32 i=0; i<(s32)JointChildSceneNodes.size(); ++i)
		if (JointChildSceneNodes[i])
			JointChildSceneNodes[i]->drop();
	//added by JAMES
	for (s32 i=0; i<(s32)JointChildSceneNodesX.size(); ++i)
		if (JointChildSceneNodesX[i])
			JointChildSceneNodesX[i]->drop();
	//end added by JAMES
}
the pre-render function should look like this

Code: Select all

//! frame
void CAnimatedMeshSceneNode::OnPreRender()
{
	if (IsVisible)
		SceneManager->registerNodeForRendering(this);

	ISceneNode::OnPreRender();

	if (IsVisible)
	{
      for (s32 i=0; i<(s32)JointChildSceneNodes.size(); ++i){
			if (JointChildSceneNodes[i])
				JointChildSceneNodes[i]->OnPreRender();}
	  //added by JAMES
      for (s32 i=0; i<(s32)JointChildSceneNodesX.size(); ++i){
			if (JointChildSceneNodesX[i])
				JointChildSceneNodesX[i]->OnPreRender();}
	  //end added by JAMES	
   }	
}
the post-render function is where the actual transformation is done. it should look like this

Code: Select all

//! OnPostRender() is called just after rendering the whole scene.
void CAnimatedMeshSceneNode::OnPostRender(u32 timeMs)
{
	s32 frameNr = getFrameNr();

	if (IsVisible)
	{
		// animate this node with all animators

		core::list<ISceneNodeAnimator*>::Iterator ait = Animators.begin();
		for (; ait != Animators.end(); ++ait)
			(*ait)->animateNode(this, timeMs);

		// update absolute position
		updateAbsolutePosition();

		// update all dummy transformation nodes
		if (!JointChildSceneNodes.empty() && Mesh && Mesh->getMeshType() == EAMT_MS3D)
		{
			IAnimatedMeshMS3D* amm = (IAnimatedMeshMS3D*)Mesh;
			core::matrix4* mat;

			for (s32 i=0; i<(s32)JointChildSceneNodes.size(); ++i)
				if (JointChildSceneNodes[i])
				{
					mat = amm->getMatrixOfJoint(i, frameNr);
					if (mat)
						JointChildSceneNodes[i]->getRelativeTransformationMatrix() = *mat;
				}
		}
		//added by JAMES
		if (!JointChildSceneNodesX.empty() && Mesh && Mesh->getMeshType() == EAMT_X)
		{
			IAnimatedMeshX* amm = (IAnimatedMeshX*)Mesh;
			core::matrix4* mat;

			for (s32 i=0; i<(s32)JointChildSceneNodesX.size(); ++i)
				if (JointChildSceneNodesX[i])
				{
					mat = amm->getMatrixOfJoint(i, frameNr);
					if (mat)
						JointChildSceneNodesX[i]->getRelativeTransformationMatrix() = *mat;
				}
		}
		//end added by JAMES
		
		core::list<ISceneNode*>::Iterator it = Children.begin();
		for (; it != Children.end(); ++it)
			(*it)->OnPostRender(timeMs);
	}
}
lastly we need to modify the removeChild function

Code: Select all

//! Removes a child from this scene node.
//! Implemented here, to be able to remove the shadow properly, if there is one,
//! or to remove attached childs.
bool CAnimatedMeshSceneNode::removeChild(ISceneNode* child)
{
	if (child && Shadow == child)
	{
		Shadow->drop();
		Shadow = 0;
		return true;
	}

	if (ISceneNode::removeChild(child))
	{
		for (s32 i=0; i<(s32)JointChildSceneNodes.size(); ++i)
		if (JointChildSceneNodes[i] == child)
		{
			JointChildSceneNodes[i]->drop();
			JointChildSceneNodes[i] = 0;
			return true;
		}
		//added by JAMES
		for (s32 i=0; i<(s32)JointChildSceneNodesX.size(); ++i)
		if (JointChildSceneNodesX[i] == child)
		{
			JointChildSceneNodesX[i]->drop();
			JointChildSceneNodesX[i] = 0;
			return true;
		}
		//end added by JAMES

		return true;
	}

	return false;
}
I haven't tested this a great deal, so if anyone has problems please let me know. I hope people find this useful.
arras
Posts: 1622
Joined: Mon Apr 05, 2004 8:35 am
Location: Slovakia
Contact:

Post by arras »

Thanks Electron, I have no use for this right now but sure one day I will ...its definetly usefull function since its much easier to use than to deal with matrix of joints.

...As soon as I find some time I will test it.

Keep coding!! :wink:
Electron
Posts: 874
Joined: Sun Mar 14, 2004 12:05 am
Location: Massachusetts USA

Post by Electron »

Unfortunately there seems to be something wrong with it because CXAnimationPlayer::getMatrixOfJoint seems to have a bug. See thsi thread for more detailshttp://irrlicht.sourceforge.net/phpBB2/ ... ply&t=2979

Basically, this modification is useless. I will post if I find a fix
You do a lot of programming? Really? I try to get some in, but the debugging keeps me pretty busy.

Crucible of Stars
Electron
Posts: 874
Joined: Sun Mar 14, 2004 12:05 am
Location: Massachusetts USA

Post by Electron »

all better. Read the above thread to find the fix. Basically CXAnimationPlayer::getMatrixOfJoint needs to return the AnimatedMatrix instead of the CombinedAnimationMatrix
You do a lot of programming? Really? I try to get some in, but the debugging keeps me pretty busy.

Crucible of Stars
etcaptor
Posts: 871
Joined: Fri Apr 09, 2004 10:32 pm
Location: Valhalla
Contact:

Post by etcaptor »

I just wonder why this is not included in irr 7.1. for x nodes:?:

If only getMatrixOfJoint is used, we must cast current frame like parameter. Indeed is easy using of getXJointNode and set it like parent for some weapon or armor node.

I'll try this solution, thanks Electron.


I found that your solution is already included in NX.
Andi|xng
Posts: 83
Joined: Thu Mar 24, 2005 10:49 pm
Location: Schrobenhausen, Germany
Contact:

Post by Andi|xng »

Any news here?
Is the bug still there in Irrlicht 0.12? Does anybody know, when Niko will add this getXJoint-Feature to Irrlicht?
Thanks.
dhenton9000
Posts: 395
Joined: Fri Apr 08, 2005 8:46 pm

Post by dhenton9000 »

I've hit this puppy as well. Any word if this is in the pipeline?
keithwei
Posts: 10
Joined: Fri Sep 09, 2005 6:36 am

Post by keithwei »

very good
Post Reply