PDA

View Full Version : Calculating .IPL Quaternion rotations to Euler


Pottus
07/02/2013, 10:04 PM
Ok, so here is the deal I've been working on a map editor for a while now and have steadily been adding new features a couple of days ago I realized there was no way to reference San Andreas objects and delete them with RemoveBuildingForPlayer() function. That part works fine but I also realize it would now be possible to clone parts of San Andreas into it's own map or remove an object and replace it with a create object that can be re-textured. Anyways the main problem with this is calculating the Quaternion rotations in the .IPL files to Euler angles which is done by the following function.


stock QuaternionToEuler(Float:qX, Float:qY, Float:qZ, Float:qW, &Float:rX, &Float:rY, &Float:rZ)
{
new Float:sqw, Float:sqx, Float:sqy, Float:sqz;
new Float:PI = 3.14159265359;

new Float:unit;
new Float:test;

sqw = qW*qW;
sqx = qX*qX;
sqy = qY*qY;
sqz = qZ*qZ;

unit = sqx + sqy + sqz + sqw; // if normalised is one, otherwise is correction factor

test = qX*qY + qZ*qW;

if (test > 0.499 * unit) { // singularity at north pole
rX = 2 * atan2(qX,qW);
rZ = PI/2;
rY = 0;
}
else if (test < -0.499*unit) { // singularity at south pole
rX = -2 * atan2(qX,qW);
rZ = -PI/2;
rY = 0;
}
else
{
rX = atan2(2*qY*qW-2*qX*qZ , sqx - sqy - sqz + sqw);
rZ = asin(2*test/unit);
rY = atan2(2*qX*qW-2*qY*qZ , -sqx + sqy - sqz + sqw);
}
}

That seams to work fine except, things get weird in game, some calculations work some are inverted etc does anyone have any ideas of how to get this to work properly ?

Pottus
07/02/2013, 11:36 PM
Thanks a lot, I'll try using this function here and let you know how it goes!

I'm pretty sure this is what I"m looking for

QuatToEulerZXY(Float:quat_x, Float:quat_y, Float:quat_z, Float:quat_w, &Float:x, &Float:y, &Float:z)
{
x = -asin(2 * ((quat_x * quat_z) + (quat_w * quat_y)));
y = atan2(2 * ((quat_y * quat_z) + (quat_w * quat_x)), (quat_w * quat_w) - (quat_x * quat_x) - (quat_y * quat_y) + (quat_z * quat_z));
z = -atan2(2 * ((quat_x * quat_y) + (quat_w * quat_z)), (quat_w * quat_w) + (quat_x * quat_x) - (quat_y * quat_y) - (quat_z * quat_z));
return 1;
}

Edit - Ok well it works better but still fails on some objects, for instance

http://img7.imageshack.us/img7/9672/samp251ql.png (http://imageshack.us/photo/my-images/7/samp251ql.png/)

It would seem the RX and RY need to be swapped for it to work.

Pottus
08/02/2013, 04:32 AM
Further testing shows this function does not work 100 percent.