Y-Rotation of object parallel to cameraView

Post Reply
mathew11
Posts: 4
Joined: Tue Jun 16, 2015 5:09 pm

Y-Rotation of object parallel to cameraView

Post by mathew11 »

Hi,

I'm struggling with a problem, where I want to rotate my character object in the Y-Direction. I have a horizontal angle from the camera and I want to get the Y-rotation of the object parallel to the Y-rotation of the camera.

Firstly, I obtain the quaternion from the object with:

Code: Select all

btTransform tr;
body->getMotionState()->getWorldTransform(tr);
btQuaternion quat = tr.getRotation();
Then, I'm reading out the Euler angles, so it could be easier for me because of the horziontal angle from the camera.

Code: Select all

btVector3 euler;
QuaternionToEulerXYZ(quat, euler);
The function QuaternionToEulerXYZ does work, because when I would use:

Code: Select all

btQuaternion quat2;
quat2.setEulerZYX(euler.getZ(), euler.getY(), euler.getX());
tr.setRotation(quat3);
body->setWorldTransform(tr);
The rotation is correct.


But, I need something like this: (I'm passing the horizontalAngle of the camera, instead of the old Y-value)

Code: Select all

quat2.setEulerZYX(euler.getZ(), horizontalAngle, euler.getX());
Edit: I tried this, and the rotation along Y works now, but the X and Z rotation are dismissed. But why does the rotation now works without any flipping?

Code: Select all

quat2.setEulerZYX(0, horizontalAngle, 0);

The problem is, that when the horziontal angle is between 90° and 270° it start's to flip. So if the horziontal angle is 180° the object is rotating every draw call by 180°.

How can I solve this problem? I think I'm misunderstanding something with the Euler degrees. When I'm reading out the degrees, they are always between 0° - 90°.

My basic assumption is, that I just pass the horizontalAngle of the camera to my object, so it always stays parallel.

Best regards,

mathew
User avatar
drleviathan
Posts: 849
Joined: Tue Sep 30, 2014 6:03 pm
Location: San Francisco

Re: Y-Rotation of object parallel to cameraView

Post by drleviathan »

My advice would be to avoid Euler angles and just compute the new rotation directly:

Suppose you know both forward axes of your character projected onto the horizontal plane and normalized: oldCharacterForward (where it is now) and newCharacterForward (where you want it to be). You can compute the newRotation like so:

Code: Select all

btQuaternion newRotation = oldRotation;

// NOTE: assuming axes forwards lie on horizontal plane: axis points either +yAxis or -yAxis
btVector3 axis = oldCharacterForward.cross(newCharacterForward); 

// forward axes MUST be normalized
btScalar axisLength = axis.length();
assert(axisLength <= 1.0); 

// if the length of the cross product is too small then the axes are either parallel or anti-parallel
if (axisLength > 0.0001) {
    // the axes are not parallel so we may proceed
    btScalar angle = asinf(axisLength);
    axis /= axisLength;
    btQuaternion deltaQ(axis, angle);
    newRotation = deltaQ * oldRotation;
} else if (oldCharacterForward.dot(newCharacterForward) < 0.0) {
    // the axes are anti-parallel, so rotate about yAxis by PI radians
    newRotation = btQuaternion(btVector3(0.0, 1.0, 0.0), PI) * oldRotation;
}

// stuff newRotation into a btTransform and update the RigigBody below ...
// ...
mathew11
Posts: 4
Joined: Tue Jun 16, 2015 5:09 pm

Re: Y-Rotation of object parallel to cameraView

Post by mathew11 »

Thank you for your answer.

Actually, I tried something similiar what you've posted. But the problem is, that it always calculates the difference to get it parallel. Unfortunately, it does not ensure that the camera and the object always have the same Y-angle.

But anyway, now I did the following:
1) I saved the initial rotation at the initialisation of the character object. (That's the rotation which came from the modelMatrix)
2) Then, I always take that rotation and just add the Y-angle of the camera.
mathew11
Posts: 4
Joined: Tue Jun 16, 2015 5:09 pm

Re: Y-Rotation of object parallel to cameraView

Post by mathew11 »

So, finally my last approach just worked "sometimes", because there was a performance isse (don't know why it appeared).

Actually, my character has a linearVelocity which can changed by the ASDW keys for the correspondent direction. I thought, that I could mix the linearVelocity with setting a new Rotation every update, but this just made the character or whole bullet very unstable. (I really don't know why).

But then, I followed this idea: http://gamedev.stackexchange.com/a/81387

And finally I did:

Code: Select all

btTransform tr;
body->getMotionState()->getWorldTransform(tr);
btQuaternion quatOld = tr.getRotation();
btQuaternion quatNew = btQuaternion(newAngle, 0, 0) * initRotation;

btQuaternion delta = quatNew * quatOld.inverse();

btVector3 euler;
QuaternionToEulerXYZ(delta, euler);

// 10 is just a constant, it increases the speed
body->setAngularVelocity(btVector3(0, euler.getY()*10, 0));
It works great.
Post Reply