Interpreting euler angles for getEulerZYX() method

Nitram
Posts: 10
Joined: Sat Feb 23, 2013 11:33 am

Interpreting euler angles for getEulerZYX() method

Post by Nitram »

I have a plane which has a bounding box with zero height, and on top of that plane I have another box, which acts as character.
Everything worked normal until I decided to add friction, so character would stop immediately but then a problem appeared. Now when I move the cube, sometimes it goes up and down a little, even though when I set linear velocity, y is always zero. Maybe I'm interpreting friction wrong? How is it measured?

I also have one other problem, the spheres, even though I made sure they have precise bounding box, are a little bit sunk on the ground plane.

This is how I add box:

Code: Select all

void WindowsPhysicsManager::addBox(Node* node) {
	Physics* pa = static_cast<Physics*>(node->getResource(Resource::PHYSICS));
	BoundingBox* bb = static_cast<BoundingBox*>(pa->getBoundingVolume());
	Vec3& box = bb->getSizes();
	btCollisionShape* groundShape = new btBoxShape(
		btVector3(box.getX() * 0.5f, box.getY() * 0.5f, box.getZ() * 0.5f));
	collisionShapes_.push_back(groundShape);
	btTransform groundTransform;
	groundTransform.setIdentity();
	Vec3& origin = bb->getCenter();
	groundTransform.setOrigin(
		btVector3(
			node->getPos().getX(),
			node->getPos().getY(),
			node->getPos().getZ()));
	btVector3 localInertia(0,0,0);
	if (pa->getMass() > GHOST_DELTA) {
		groundShape->calculateLocalInertia(pa->getMass(), localInertia);
	}
	btDefaultMotionState* myMotionState =
		new btDefaultMotionState(groundTransform);
	btRigidBody::btRigidBodyConstructionInfo rbInfo(
		pa->getMass(), myMotionState, groundShape, localInertia);
	rbInfo.m_friction = 1.0f;
	btRigidBody* body = new btRigidBody(rbInfo);
	body->setUserPointer(static_cast<void*>(node));
	dynamicsWorld_->addRigidBody(body);
}
This is how I add sphere:

Code: Select all

void WindowsPhysicsManager::addSphere(Node* node) {
	Physics* pa = static_cast<Physics*>(node->getResource(Resource::PHYSICS));
	BoundingSphere* bs = static_cast<BoundingSphere*>(pa->getBoundingVolume());
	btCollisionShape* colShape = new btSphereShape(
		btScalar(bs->getRadius()));
	collisionShapes_.push_back(colShape);
	btTransform startTransform;
	startTransform.setIdentity();
	Vec3& origin = bs->getCenter();
	startTransform.setOrigin(
		btVector3(
			node->getPos().getX(),
			node->getPos().getY(),
			node->getPos().getZ()));
	bool isDynamic = (pa->getMass() > GHOST_DELTA);
	btVector3 localInertia(0,0,0);
	if (isDynamic) {
		colShape->calculateLocalInertia(pa->getMass(), localInertia);
	}
	btDefaultMotionState* myMotionState =
		new btDefaultMotionState(startTransform);
	btRigidBody::btRigidBodyConstructionInfo rbInfo(
		pa->getMass(), myMotionState, colShape,localInertia);
	rbInfo.m_angularDamping = 1.0f;
	btRigidBody* body = new btRigidBody(rbInfo);
	body->setUserPointer(static_cast<void*>(node));
	dynamicsWorld_->addRigidBody(body);
}
This is how I move box:

Code: Select all

void WindowsPhysicsManager::move(Node* node, Vec3& pos) {
	btCollisionObjectArray arr = dynamicsWorld_->getCollisionObjectArray();
	int size = arr.size();
	for (int i = 0; i < size; i++) {
		if (arr[i]->getUserPointer() == node) {
			//btTransform tr;
			//tr.setIdentity();
			//tr.setOrigin(btVector3(pos.getX(), pos.getY(), pos.getZ()));
			btRigidBody* body = btRigidBody::upcast(arr[i]);
			body->activate();
			//body->applyCentralForce(btVector3(0.0f, 10000.0f, 0.0f));
			body->setLinearVelocity(
				btVector3(pos.getX(), pos.getY(), pos.getZ()));
			//body->setCenterOfMassTransform(tr);
		}
	}
}
I'm new here. So If I formatted my question wrong, please excuse me.
Any help would be appreciated.
You do not have the required permissions to view the files attached to this post.
Last edited by Nitram on Tue Feb 26, 2013 5:50 pm, edited 2 times in total.
Nitram
Posts: 10
Joined: Sat Feb 23, 2013 11:33 am

Re: Box friction on other box

Post by Nitram »

I might have found the first problem source. It has to do with the way I'm handling rotation. Is this the correct way to get object rotation?

Code: Select all

			btTransform trans;
			body->getMotionState()->getWorldTransform(trans);
			Node* node = static_cast<Node*>(
				body->getUserPointer());
			node->getPos().setXYZ(
				trans.getOrigin().getX(),
				trans.getOrigin().getY(),
				trans.getOrigin().getZ());
			static float yaw, pitch, roll;
			trans.getBasis().getEulerYPR(yaw, pitch, roll);
			node->getRot().setXYZ(
				pitch * -57.2957795f,
				yaw * -57.2957795f,
				roll * -57.2957795f);
I couldn't found any normal documentation about handling rotation using Euler angles, so I tried to find the correct way via trial and error. If I'm correct, returned rotations are in radians, so I had to multiply them by 180/PI, but then, all my models were rotating backwards, instead of forward, when pushed. So I inverted them. And now, rotation seems to work, sort of...
But I get this behavior, when cube just stops on its corner. Any suggestions what might be wrong?
You do not have the required permissions to view the files attached to this post.
xexuxjy
Posts: 225
Joined: Wed Jan 07, 2009 11:43 am
Location: London

Re: Box friction on other box

Post by xexuxjy »

One thing that's always useful is to enable the debug draw functionality for bullet so you can see if where it thinks objects are is where you think they are.

Also I didn't notice the general size of your objects (apologies if I missed it) , Bullet adds a margin (0.02 i think) to each one which might also be effecting things.
Nitram
Posts: 10
Joined: Sat Feb 23, 2013 11:33 am

Re: Box friction on other box

Post by Nitram »

xexuxjy wrote:One thing that's always useful is to enable the debug draw functionality for bullet so you can see if where it thinks objects are is where you think they are.

Also I didn't notice the general size of your objects (apologies if I missed it) , Bullet adds a margin (0.02 i think) to each one which might also be effecting things.
Thanks for reply, I use meters as in 1.0f = 1 meter. My spheres were ~4 meters in radius, so that probably explains why the sinking was so visible. I'll try to enable debug draw and post later.
Nitram
Posts: 10
Joined: Sat Feb 23, 2013 11:33 am

Re: Box friction on other box

Post by Nitram »

So, I'm back. Finally implemented debug draw and this is what I see... Yellow line shows that there's actually something wrong with the way I'm handling rotations. So it would be great if someone could point me to the location of some example that correctly handle euler angles, NOT queternions. Another strange thing I saw after enabling debug draw is marked red. What could that be? There is no object added there.

[EDIT]
Don't mind about red marked object, it's the center of plane, didn't knew bullet draws coordinate axes.
You do not have the required permissions to view the files attached to this post.
xexuxjy
Posts: 225
Joined: Wed Jan 07, 2009 11:43 am
Location: London

Re: Problem with euler angles

Post by xexuxjy »

the only example I can find in the demos is in the CollisionInterfaceDemo where it basically gets YPR from the object, adjusts them and sets them back on the object again (getEulerYPR/setEulerYPR) to rotate slowly over time. With your example below does it start off correct and then divert or is always wrong?
Nitram
Posts: 10
Joined: Sat Feb 23, 2013 11:33 am

Re: Problem with euler angles

Post by Nitram »

So after spending some more time on this, I found my problem, as to why my angles are so messed up.
I printed the result of getEulerXYZ() and this is what I get:
GhostEngine 2013-02-26 19-23-11-83.png
The printed angles are (after converting to degrees):
x="-127.978989f" y="-0.000014f" z="89.999977f"
White cube is mine (it's normals face inwards, so I could see it's center).
Green cube with x, y, z angles is from bullet.
Now, when I manually add printed angles to my object, I get the same result as here for white box, because this is what you would expect, assuming object starts at 0, 0, 0 rotations.
But bullet does something entirely different. As you can see, the x axis is pointing up, because cube is on it's side. And if the coordinate system always started as x pointing up/down, z pointing towards us, and y pointing right/left, then if we were to apply printed rotations for object who starts at 0, 0, 0, we would get exactly the same result, as current green bullet box (or something like that, I might be mistaking y and z axes), but I'm using opengl and I don't want to change my primary axes orientation!

How do I handle this situation?
You do not have the required permissions to view the files attached to this post.
Nitram
Posts: 10
Joined: Sat Feb 23, 2013 11:33 am

Re: Problem with euler angles

Post by Nitram »

xexuxjy wrote:the only example I can find in the demos is in the CollisionInterfaceDemo where it basically gets YPR from the object, adjusts them and sets them back on the object again (getEulerYPR/setEulerYPR) to rotate slowly over time. With your example below does it start off correct and then divert or is always wrong?
It starts correct, but after flipping object it starts to act strangely.
I looked at this example, and there it works, but my situation is different. It seems that bullet interprets axes depending on object position or something like that. I still need to understand how one would handle this.
xexuxjy
Posts: 225
Joined: Wed Jan 07, 2009 11:43 am
Location: London

Re: Interpreting euler angles for getEulerZYX() method

Post by xexuxjy »

Well the wiki has a bit on bullets coordinate system

http://bulletphysics.org/mediawiki-1.5. ... ate_system

Depending on what your coordinate system is you might have to do some conversion, but I'd be surprised if you had to negate all 3 values.
Nitram
Posts: 10
Joined: Sat Feb 23, 2013 11:33 am

Re: Interpreting euler angles for getEulerZYX() method

Post by Nitram »

xexuxjy wrote:Well the wiki has a bit on bullets coordinate system

http://bulletphysics.org/mediawiki-1.5. ... ate_system

Depending on what your coordinate system is you might have to do some conversion, but I'd be surprised if you had to negate all 3 values.
Yes, it does seem fishy about negation. Thanks, for the page, but it really lacks any helpful information (more or less, like whole bullet wiki? :D).
Code samples that come with SDK are good, but they don't cover all situations.
I fixed this now.
I just gave up on those euler methods, because they just don't work the way you would expect them to.
Since I already use OpenGL, I just retrieve whole OpenGL matrix and multiply it with my nodes scale factor:

Code: Select all

			Mat4 mat;
			trans.getOpenGLMatrix(mat);
			Mat4 scale;
			Matrix::scale(scale,
				node->getScale().getX(),
				node->getScale().getY(),
				node->getScale().getZ());
			Mat4 res;
			Matrix::multiply(mat, scale, res);
			node->setMatrix(res);
This seems to work just fine. I'll just have to figure out methods, on how to retrieve rotation and position from this matrix.
Thanks for all the help :)