XYZ rotation to align a plane onto a normal.

Post Reply
Crayder
Posts: 15
Joined: Mon Aug 10, 2015 10:18 pm

XYZ rotation to align a plane onto a normal.

Post by Crayder »

Basically I need a way to get a Euler X-Y-Z rotation vector from the normal of a surface. The current code works for some cases, but not all. It mostly works when casting a ray straight down. When casting rays at walls or slope the rotation returned is usually crooked and just not very helpful. The rotation is supposed to make a plane parallel to the surface the raycast hit from the normal.


Current code:

Code: Select all

int ColAndreasWorld::performRayTestAngle(const btVector3& Start, const btVector3& End, btVector3& Result, btScalar& RX, btScalar& RY, btScalar& RZ, uint16_t& model)
{
	btCollisionWorld::ClosestRayResultCallback RayCallback(Start, End);

	dynamicsWorld->rayTest(Start, End, RayCallback);

	if (RayCallback.hasHit())
	{
		btVector3 Rotation = RayCallback.m_hitNormalWorld;
		RX = -(asin(Rotation.getY())*RADIAN_TO_DEG);
		RY = asin(Rotation.getX())*RADIAN_TO_DEG;
		RZ = 0.0;
		Result = RayCallback.m_hitPointWorld;
		model = RayCallback.m_collisionObject->getUserIndex();
		return 1;
	}
	return 0;
}
That is called using:

Code: Select all

performRayTestAngle(Start, End, Result, RX, RY, RZ, model)
PS. The code is not by me, but I am a collaborator.
User avatar
drleviathan
Posts: 849
Joined: Tue Sep 30, 2014 6:03 pm
Location: San Francisco

Re: XYZ rotation to align a plane onto a normal.

Post by drleviathan »

What do you really want to do? Are you just using the RX, RY, and RZ values to define a plane? If so then the Euler angles are pnot the most useful info to harvest. A plane can be defined by any point on the plane and a normal. The result of the raycast provides these for you --> no need to do Euler stuff.
Crayder
Posts: 15
Joined: Mon Aug 10, 2015 10:18 pm

Re: XYZ rotation to align a plane onto a normal.

Post by Crayder »

No, I was saying plane as an example. I need the euler angles because they are used by the game that this is needed for. I'm not trying to define a plane. I just want the angles to be calculated correctly.

There would be many uses for these angles after it's done right, one for example would be aligning objects (none of which would be handled by bullet, which is a main reason I need this function) in the game with a surface.
User avatar
drleviathan
Posts: 849
Joined: Tue Sep 30, 2014 6:03 pm
Location: San Francisco

Re: XYZ rotation to align a plane onto a normal.

Post by drleviathan »

Given some normal vectorB there is an infinite number of rotations (and hence infinite combinations of Euler angles) that would rotate any reference vectorA to it -- there is no unique solution for the information you want. To compute a unique solution you need more information than just the normal, for example not just vectorA but also what is up, right, and forward in its frame and how that should relate to the cardinal axes in B's frame.

That said, if all you know is vectorA and vectorB then typically there is a unique rotation that brings A to B with the shortest angle of rotation. Computing the quaternion for that rotation is done like this:

Code: Select all

    btVector3 axis = (vectorA.cross(vectorB)).normalized();
    btScalar angle = btAcos(vectorA.dot(vectorB)) / (vectorA.length() * vectorB.length());
    btQuaternion Q = btQuaternion(axis, angle);
Note that there is much normalization and length measuring going on, so the algorithm could be optimized if you are sure the two vectors are normalized. Also it breaks when the two vectors are parallel or anti-parallel so you should check for that case before using it.

Personally, I'd prefer to have the quaternion rather than the Euler angles, but if you want to decompose into Euler angles then you could do:

Code: Select all

    btMatrix3x3 M = btMatrix3x3(Q);
    btScalar yaw, pitch, roll;
    M.getEulerXYZ(yaw, pitch, roll);
Note that there is more than one "definition" of Euler angles and the btMatrix3x3 class provides a few different ways to decompose. Look at the documentation to find the one you want to use.
Post Reply