Transformation Error with Parent

You are an experienced programmer and have a problem with the engine, shaders, or advanced effects? Here you'll get answers.
No questions about C++ programming or topics which are answered in the tutorials!
Post Reply
nutpor
Posts: 31
Joined: Sun Jun 12, 2005 5:06 pm
Location: Behind You ^_^

Transformation Error with Parent

Post by nutpor »

Hi all :) ,

I moved this thread from bugs report forum.

First, let me explain the situation.
Suppose I create 3 scenenodes, named nodeA, nodeB and nodeC which all of them are child of root scenenode.
Then I add node to nodeA, nodeB
Parent Children
----------------------------------------
nodeA nodeA1
nodeA nodeA2
nodeA nodeA3

nodeB nodeB1
nodeB nodeB1
nodeB nodeB1

I want to setParent of nodeA1-3 and nodeB1-3 to nodeC but
position, rotation and scaling of children node MUST NOT change so I needed to recalculate each position, rotation and scaling to relative with new parent which is nodeC but position and scaling are mess up!

Here is my code for grouping

Code: Select all

// nodeList : list of node to be group
// refIndex : index of node that will be a reference position, rotation, scaling of other node in group
irr::scene::ISceneNode* CSceneNodeFactory::groupSceneNode(std::vector<irr::scene::ISceneNode*>& nodeList, irr::s32 refIndex, irr::scene::ISceneManager* smgr)
{
	if (nodeList.size() == 0 || refIndex < 0 || !smgr)
	{
		return 0;
	}

	// Create a new groupSceneNode for all SceneNode in nodeList.
	ISceneNode* newGroup = CSceneNodeFactory::createGroupSceneNode(0, smgr);


	// Set position for the new groupSceneNode.
	ISceneNode* currentNode = nodeList.at(refIndex);
	newGroup->setPosition(currentNode->getPosition());
	newGroup->setRotation(currentNode->getRotation());
	//newGroup->setScale(currentSceneNode->getScale());


	irr::core::list<ISceneNode*>::Iterator itr;
	irr::core::list<ISceneNode*> newList;
	irr::core::list<ISceneNode*> children;

	for (u32 i = 0; i < nodeList.size(); ++i)
	{
		currentNode = nodeList.at(i);
	
		if (currentNode->getChildren().getSize() > 0)
		{
			// has children
			itr = currentNode->getChildren().begin();
			for (; itr != currentNode->getChildren().end(); ++itr)
			{
				irr::scene::ISceneNode* node = (*itr);
				vector3df newPos;
				vector3df newRot;
				vector3df newScl;

				vector3df myScale;
				vector3df parentScale;

				matrix4 mat;
				node->updateAbsolutePosition();
				mat = node->getAbsoluteTransformation();
				CLogger::print("before", mat.getTranslation());
				CLogger::print("mat", getScale(mat));

				newPos = (node->getPosition() + currentNode->getPosition()) - newGroup->getPosition();
				newRot = (node->getRotation() + currentNode->getRotation()) - newGroup->getRotation();
				myScale = node->getScale();
				parentScale = currentNode->getScale();
				newScl.X = myScale.X * parentScale.X;
				newScl.Y = myScale.Y * parentScale.Y;
				newScl.Z = myScale.Z * parentScale.Z;

				node->setPosition(newPos);
				node->setRotation(newRot);
				//node->setScale(newScl);
				newList.push_back(node);

				node->updateAbsolutePosition();
				mat = node->getAbsoluteTransformation();

			}
			deleteSceneNode(currentNode, smgr, 1);
			currentNode = 0;
		}
		else
		{
			irr::scene::ISceneNode* node = currentNode;
			vector3df newPos;
			vector3df newRot;
			vector3df newScl;

			newPos = node->getPosition() - newGroup->getPosition();
			newRot = node->getRotation() - newGroup->getRotation();
			newScl = node->getScale();

			node->setPosition(newPos);
			node->setRotation(newRot);
			node->setScale(newScl);
			newList.push_back(node);
		}
	}


	for (itr = newList.begin(); itr != newList.end(); ++itr)
	{
		(*itr)->setParent(newGroup);
	}

	return newGroup;
}
createGroupSceneNode() is creating empty scene node that doesn't do anything more than conthainer of scene node.

Code: Select all

virtual core::matrix4 getRelativeTransformation() const
	{
		core::matrix4 mat;

		mat.setRotationDegrees(RelativeRotation);	

		if (RelativeScale != core::vector3df(1,1,1))
		{
			core::matrix4 smat;
			smat.setScale(RelativeScale);
			mat *= smat;
		}

		mat.setTranslation(RelativeTranslation);

		return mat;
	}
Any help would by greatly appreciated. :)
Acki
Posts: 3496
Joined: Tue Jun 29, 2004 12:04 am
Location: Nobody's Place (Venlo NL)
Contact:

Post by Acki »

Yes that's normal...
If a node has for example a scale of 2 and you add another as child to it, the child will become the same scale as the parent added to his own scale !!!
So if node 2 has also a scale of 2 it will become a scale of 4...

So you have to recalculate the scale, position and rotation of the child...
Well, I didn't get this really to work this way...
I did it with a 3rd node (IEmptySceneNode) that becomes the parent of both...
The empty scene node has a position and rotation of (0, 0, 0) and scale of (1, 1, 1) so it doesn't affect the other nodes...

Well, it also should work the other way...

Code: Select all

child->setRotation(parent->getRotation() - child->getRotation());
child->setPosition(parent->getPosition() - child->getPosition());
child->setScale(parent->getScale() / child->getScale());
But there is something wrong, it doesn't work...
Maybe the code isn't correct, I wrote it out of remembrance... ;)
while(!asleep) sheep++;
IrrExtensions:Image
http://abusoft.g0dsoft.com
try Stendhal a MORPG written in Java
nutpor
Posts: 31
Joined: Sun Jun 12, 2005 5:06 pm
Location: Behind You ^_^

Post by nutpor »

Suppose parent's scale is 2,2,2 and child's scale is 3,3,3.
If I create new empty node which scale is 1,1,1 and move child to this node I have to set child's scale to 6,6,6 right?
I've tried this but it still doesn't works.
Acki
Posts: 3496
Joined: Tue Jun 29, 2004 12:04 am
Location: Nobody's Place (Venlo NL)
Contact:

Post by Acki »

Yes, that's right...

For position and rotation you can also try to set the parent to rot(0,0,0) and pos(0,0,0) than add the child and set the parent back to it's position...

For scale I don't know, maybe someone else knows how to calculate the new scale for a child node ???
while(!asleep) sheep++;
IrrExtensions:Image
http://abusoft.g0dsoft.com
try Stendhal a MORPG written in Java
nutpor
Posts: 31
Joined: Sun Jun 12, 2005 5:06 pm
Location: Behind You ^_^

Post by nutpor »

For Example:
nodeA :
parent = root
position(100,100,0)
rotation(0,0,0)
sscale(2,2,2)

nodeB :
parent = nodeA
position(50,50,50)
rotation(0,0,0)
scale(1,1,1)

if I new nodeC :
parent = root
position(50,50,50)
rotation(0,0,0)
scale(1,1,1)
And setParent of nodeB to nodeC
then nodeB become :
parent = nodeC
position(100,100,0)
rotation(0,0,0)
scale(2,2,2)
to make nodeC still rendered at same position and same scale
I print debug value of each node it print right but it render wrong!
Post Reply