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