Object rotation Euler-Quaternion conversion problem

Please don't post Bullet support questions here, use the above forums instead.
nano
Posts: 6
Joined: Sun Oct 28, 2007 2:45 am

Object rotation Euler-Quaternion conversion problem

Post by nano »

Hi there guys,

I'm using Bullet for collision detection in a project i'm working on (in the Irrlicht engine) and i've run into a problem. It seems that whenever we set/get rotation of one of our objects it's giving a bizarre vector result. I'm assuming there's something wrong with the way the conversions are happening, but i really just don't have any experience with this sort of thing to know what i'm doing wrong, so i was hoping one of you would be able to point it out to me :)

These are the main functions involved with what i'm doing:

Code: Select all

#ifndef GRAD_PI 
#define GRAD_PI 57.29577951f
#endif
#ifndef GRAD_PI2
#define GRAD_PI2 0.174532925f
#endif

//sets the rotation of the rigidBody to the input vector
void SSPhysicsObject::SetRotation(const vector3df &v)
{
	if (!m_pRigidBody) return; 
	btTransform t=m_pRigidBody->getWorldTransform();
	btQuaternion btq;
	EulerXYZToQuaternion(btVector3(v.X * GRAD_PI2, v.Y * GRAD_PI2, v.Z * GRAD_PI2), btq);
	t.setRotation(btq);
	m_pRigidBody->setWorldTransform(t);
}

//outputs the rotation of the rigidBody as a vector
vector3df SSPhysicsObject::GetRotation()
{
	if (!m_pRigidBody) return vector3df(0,0,0);
	btVector3 btv;
	btQuaternion btq=m_pRigidBody->getOrientation();
	QuaternionToEulerXYZ(btq, btv);
 	vector3df v(btv.getX(), btv.getY(), btv.getZ());
	v *= GRAD_PI;
	return v;
}
Those use these functions:

Code: Select all

void SSPhysicsObject::QuaternionToEulerXYZ(const btQuaternion &quat,btVector3 &euler)
{
	f32 w=quat.getW();	f32 x=quat.getX();	f32 y=quat.getY();	f32 z=quat.getZ();
	double sqw = w*w; double sqx = x*x; double sqy = y*y; double sqz = z*z; 
	euler.setZ((atan2(2.0 * (x*y + z*w),(sqx - sqy - sqz + sqw))));
	euler.setX((atan2(2.0 * (y*z + x*w),(-sqx - sqy + sqz + sqw))));
	euler.setY((asin(-2.0 * (x*z - y*w))));
}
void SSPhysicsObject::EulerXYZToQuaternion(btVector3 &euler, btQuaternion &quat)
{	
	btMatrix3x3 mat;
	mat.setIdentity();
	mat.setEulerZYX(euler.getX(), euler.getY(), euler.getZ());
	mat.getRotation(quat);

	//equivalent?
	//btQuaternion q(euler.getX(), euler.getY(), euler.getZ());
	//btQuaternion q1(q.getY(), q.getX(), q.getZ(), q.getW());
	//quat = q1;
}
I think those are the only functions used in the conversions and i believe the only Irrlicht data types/functions there is vector3df which is fairly self explanatory. If i've missed out something that would be important or if you can actually see something that would be giving me odd errors, please let me know!

Thanks,
Luke

Edit: I figured it'd be rather helpful if i actually included an example of what's going wrong.

If i perform the following test function:

Code: Select all

pObj->SetRotation(vector3df(5.0,10.0,15.0));
vector3df check = pObj->GetRotation();
printf("Object: GET AFTER SET (5,10,15) X: %lf, Y - %lf, Z - %lf\n", check.X, check.Y, check.Z);
I get this as the output:
Object: GET AFTER SET (5,10,15) X: -130.000031, Y: 79.999992, Z: -30.000021
nano
Posts: 6
Joined: Sun Oct 28, 2007 2:45 am

Re: Object rotation Euler-Quaternion conversion problem

Post by nano »

Okay, after about four days worth of immense frustration (last night when i posted this being me at my most confused) i figured out that the #define nomad (the person who wrote the Irrlicht-Bullet framework) had written for PI/180 is set as 0.174532925f instead of 0.0174532925f which obviously caused some extremely wrong calculations!

Everything seems to be working now with the proper value :)
cyberpunkpor
Posts: 4
Joined: Wed Dec 19, 2007 10:53 am

Re: Object rotation Euler-Quaternion conversion problem

Post by cyberpunkpor »

hello.

i am facing the same problem as you but i am using this sample as a bullet framework to Irrlicht:

http://irrlicht.sourceforge.net/phpBB2/ ... etanimator


My source code is:

playerAnimator->setRotation(vector3df(0.0,1.0,1.0));


vector3df check = playerAnimator->getRotation();

printf("Object: GET AFTER SET (0,1,1) X: %lf, Y - %lf, Z - %lf\n", check.X, check.Y, check.Z);


The debug ouput is:

Object: GET AFTER SET (0,1,1) X: -0.000025, Y - 229.183121, Z - 229.183090


I already check the constant and it is returning the correct value: 0.17.....

Can you please send me some feedback on what is wrong with the rotation? Maybe the conversion to Euler?

Thanks