Horde3D
http://horde3d.org/forums/

H3DUT Proposal: h3dutGetNodeWorldTransform
http://horde3d.org/forums/viewtopic.php?f=8&t=1264
Page 1 of 1

Author:  Orm [ 29.09.2010, 21:44 ]
Post subject:  H3DUT Proposal: h3dutGetNodeWorldTransform

I recently found myself in need of a function that retrieved the absolute world transform of a particular node and was a bit disappointed when I found that the h3dGetNodeTransform function only retrieved the transform relative to a nodes parent. I needed to retrieve the world coordinates of a node within a scenegraph to integrate collision volumes with the nodes. So I propose that a new function be added to help with that.

Code:
// The implementation I am using uses references and nixes the scale value, but the theory is the same.
void h3dutGetNodeWorldTransform(H3DNode node, float* tx,float* ty,float* tz,float* rx,float* ry,float* rz,float*,float* sx, float* sy, float* sz)
{
    H3DNode parent;
   
    float tra_x,tra_y,tra_z;
    float rot_x,rot_y,rot_z;
    float sca_x,sca_y,sca_z;
   
    do
    {
        parent = h3dGetNodeParent(node);
        h3dGetNodeTransform(node,&tra_x,&tra_y,&tra_z,&rot_x,&rot_y,&rot_z,&sca_x,&sca_y,&sca_z);
       
        *tx+=tra_x;*ty+=tra_y;*tz+=tra_z;
        *rx+=rot_x;*ry+=rot_y;*rz+=rot_z;
        *sx+=sca_x;*sy+=sca_y;*sz+=sca_z;
       
    }while(parent!=H3DRootNode);
}


By the way, if I am doing this wrong, please let me know. That was my other reason for this post. :?

Author:  phoenix64 [ 29.09.2010, 22:34 ]
Post subject:  Re: H3DUT Proposal: h3dutGetNodeWorldTransform

Hm. Is this really correct? Just summing up the positions and scale doesn't look good to me, can you explain why that works? Because I would have multiplied the matrices of the different transforms there and then decomposed the result into position/scale/vector. After a rotation around 180 degrees, translation suddenly goes into the opposite direction, however you are still just adding it?

Author:  Rauy [ 29.09.2010, 22:51 ]
Post subject:  Re: H3DUT Proposal: h3dutGetNodeWorldTransform

This function does not work, but there is already a Horde3D function for the absolute (and relative) matrix: h3dGetNodeTransMats.

Author:  Orm [ 29.09.2010, 23:25 ]
Post subject:  Re: H3DUT Proposal: h3dutGetNodeWorldTransform

Rauy wrote:
This function does not work, but there is already a Horde3D function for the absolute (and relative) matrix: h3dGetNodeTransMats.


Right, and this is about the solution I came up with. In the prop class I have btCollisionObjects hashed to H3DNodes for easy syncronization:

Code:
// assume the following
typedef boost::unordered_map<H3DNode, boost::shared_ptr<btCollisionObject> > NodeCollisionMap;
typedef std::pair<H3DNode, boost::shared_ptr<btCollisionObject> > CollisionMapPair;

void Prop::Update(float time)
{
    // Set the orientation of the props root node
    btQuaternion orientation((btScalar)rotX,(btScalar)rotY,(btScalar)rotZ);
    btTransform trans(orientation,btVector3(x,y,z));
    collision_object->setWorldTransform(trans);

    // explicit transforms stored by the prop object and are set when a rigid body is attached.
    h3dSetNodeTransform(node,x,y,z,rotX,rotY,rotZ,scalX,scalY,scalZ);

    BOOST_FOREACH(CollisionMapPair pair, collision_map)
    {
        float mat[4][4];
        h3dGetNodeTransMats(pair.first,NULL,mat);

        float X = mat[3][0];float Y = mat[3][1];float Z = mat[3][2];
       
        // Still need to decompose the matrix to aquire the rotation of the node.
        btQuaternion orientation((btScalar)rx,(btScalar)ry,(btScalar)rz);
        btTransform trans2(orientation,btVector3(X,Y,Z));
        pair.second->setWorldTransform(trans2);
    }
}

Author:  Volker [ 30.09.2010, 08:32 ]
Post subject:  Re: H3DUT Proposal: h3dutGetNodeWorldTransform

I wonder why you have to decompose the matrix to set it in bullet? Is it only to avoid scaling? Maybe you should then change the vertex positions instead of apply scaling to the modelnode, this way you have the same matrix within Horde and bullet, which may reduce errors, since the decomposition of the rotation from the matrix normally suffers from singularities. If you still want to decompose the matrix you can also have a look at the decompose function of Matrix4f. But as already mentioned, their are problems in certain rotation cases.

Author:  Orm [ 30.09.2010, 17:23 ]
Post subject:  Re: H3DUT Proposal: h3dutGetNodeWorldTransform

Here is the code as I currently have it (untested)

Code:
void Actor::Update(float time)
{
    BOOST_FOREACH(CollisionMapPair pair, collision_map)
    {
        const float** mat;
        float* trans;
        float* rot;
        float* scal;
        h3dGetNodeTransMats(pair.first,NULL,mat);

        decompose(mat,trans,rot,scal);

        btQuaternion orientation((btScalar)rot[0],(btScalar)rot[1],(btScalar)rot[2]);
        btTransform btrans(orientation,btVector3(trans[0],trans[1],trans[2]));
        pair.second->setWorldTransform(btrans);
    }
    // if it has a core object defined
    if(core_object && asUpdate > 0)
    {
        int r;
        Stage::I()->getContext()->Prepare(asUpdate);
        Stage::I()->getContext()->SetArgFloat(0,time);
        r = Stage::I()->getContext()->Execute();
        if(r != asEXECUTION_FINISHED)
        {
            if(r == asEXECUTION_EXCEPTION)
            {
                LOG("An exception '"+string(Stage::I()->getContext()->GetExceptionString())+
                    "' occurred. Please correct the code and try again.",FATAL);
                Engine::I()->Kill();
            }
        }
    }
}

Page 1 of 1 All times are UTC + 1 hour
Powered by phpBB® Forum Software © phpBB Group
https://www.phpbb.com/