Page 1 of 2
Using quaternions
Posted: Sat Oct 18, 2014 12:22 pm
by Derrik
I have a model loaded, but I'm having trouble rotating it correctly in 3D space.
When using Euler angles the axis change after each rotation:
Code: Select all
glRotatef(angleX, 1.0f, 0.0f, 0.0f);
glRotatef(angleY, 0.0f, 1.0f, 0.0f);
glRotatef(angleZ, 0.0f, 0.0f, 1.0f);
If I reorder them, the resultant orientation changes because the axises change during each rotation. I don't want this behavior in my rotations.
I have read that quaternions will solve this problem.
However, when trying to implement a quaternion library (
http://www.sacredsoftware.net/tutorials ... ions.xhtml) the model was translated off-screen.
Code: Select all
Quaternion q;
int main(void) {
q = Quaternion_identity();
while(1) {
m4x4 m = Quaternion_toMatrix(q);
int i;
for(i = 0; i < 4 * 4; i++) {
printf("%d %d\n", i, m.m[i]);
}
glMultMatrix4x4(&m);
}
}
I figured out that the issue was because glMultMatrix4x4 expects a matrix to the 12 bit fractional part (<< 12). I came across the same problem when using trigonometric functions.
I experimented with the fixedToFloat and floatToFixed macros. For example I discovered that the following will give you a regular sine implementation:
Code: Select all
fixedToFloat(sinLerp(degreesToAngle(angle)), 12);
However I've been battling these conversions for several hours each day and still can't get a working implementation of quaternions. I keep getting odd artifacts such as stretching of my model or just translating it off-screen completely.
Has anyone been able to get quaternions working with VideoGL? Please help!
Re: Using quaternions
Posted: Sat Oct 18, 2014 2:18 pm
by elhobbs
do you have a sample with code that you could share with people?
Re: Using quaternions
Posted: Sat Oct 18, 2014 7:08 pm
by Derrik
Here's what I've got at the moment:
http://www.321webs.com/download/80285.htm
As you can see from the code, I'm really not sure of what I should be doing.
Thanks for the help.
Re: Using quaternions
Posted: Sat Oct 18, 2014 8:50 pm
by elhobbs
I think your main issue is dealing with fixed point numbers. There is no automatic conversion to and from floats - and you have a lot of mixing of the two in your code. I have not fixed all of the code - just the bare minimum needed to get the teapot to spin around the y axis. you should be able to apply the changes to the rest of the code.
Re: Using quaternions
Posted: Sun Oct 19, 2014 8:19 pm
by Derrik
elhobbs wrote:I think your main issue is dealing with fixed point numbers. There is no automatic conversion to and from floats - and you have a lot of mixing of the two in your code. I have not fixed all of the code - just the bare minimum needed to get the teapot to spin around the y axis. you should be able to apply the changes to the rest of the code.
Thank you! This has helped me a lot! I should definitely be able to fix the rest of the code now.
Re: Using quaternions
Posted: Mon Oct 20, 2014 4:40 pm
by Derrik
I came across a problem. I need to implement a quaternion to euler function, however all of the formulas I have found online rely on atan or atan2. Unfortunately libnds does not have any inverse tan functions. Is there a work around for this?
Many thanks once again!
Re: Using quaternions
Posted: Mon Oct 20, 2014 5:43 pm
by elhobbs
you can use the version in <math.h> - you will need to add libm to your make file. add -lm to LIBS after -lnds9
you will need to do some conversion of input/outputs to/from fixed/float etc.
Re: Using quaternions
Posted: Tue Oct 21, 2014 6:19 pm
by Derrik
I've given it a go but sadly it's not as simple as:
Code: Select all
#define atanLerp(a) ((int32)(atan((double)a / (double)4096.0) * (double)4096.0))
I tried to convert the radians to degrees and then convert the degrees to a DS angle with:
Code: Select all
#define atanLerp(a) degreesToAngle(atan((double)a / (double)4096.0) * (M_PI / 180.0))
But unfortunately this doesn't work either, so I'm not really sure where to go from here.
Re: Using quaternions
Posted: Tue Oct 21, 2014 7:53 pm
by Derrik
I was able to find an atan2Lerp function here:
http://www.coranac.com/2009/02/on-arctangent/
All I need now is a function which moves the model at the angle that it is rotated at (by the quaternion).
So first of all I need a quaternion to euler function, I found one here:
http://www.euclideanspace.com/maths/geo ... /index.htm
And tried to modify it for fixed point numbers:
Code: Select all
vect3D Quaternion_toEuler(Quaternion q) {
//http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToEuler/index.htm
vect3D v;
ulong test = mulf32(q.x, q.y) + mulf32(q.z, q.w);
if(test > floatToFixed(0.499f, 12)) { // singularity at north pole
v.x = 2 * atan2(q.x, q.w);
v.y = floatToFixed(M_PI / 2.0f, 12);
v.z = 0;
return v;
}
if(test < floatToFixed(-0.499f, 12)) { // singularity at south pole
v.x = -2 * atan2(q.x, q.w);
v.y = floatToFixed(-M_PI / 2.0f, 12);
v.z = 0;
return v;
}
ulong sqx = mulf32(q.x, q.x);
ulong sqy = mulf32(q.y, q.y);
ulong sqz = mulf32(q.z, q.z);
v.x = atan2Lerp(2 * mulf32(q.y, q.w) - 2 * mulf32(q.x, q.z), (1 << 12) - 2 * sqy - 2 * sqz);
v.y = asinLerp(2 * test);
v.z = atan2Lerp(2 * mulf32(q.x, q.w) - 2 * mulf32(q.y, q.z), (1 << 12) - 2 * sqx - 2 * sqz);
return v;
}
But it isn't working. Did I miss something?
Re: Using quaternions
Posted: Wed Oct 22, 2014 1:31 am
by elhobbs
why do you have a mixture of atan2 (which is looking for doubles) and atan2Lerp(which is looking for fixed point)?