How to rotate a vector ? RESOLVED

Hello guys,

I am programming a free direction tunnel oldschool effect with my “own” engine using a raytracing algorythm.
I followed this famous tutorial herehttp://www.programmersheaven.com/d/click.aspx?ID=F6526:
Renditions is perfect, but i am encountering a weird issue when i move the camera.

To rotate around axis X for example i use the following procedure:

[quote]private void rotateZ(Vector vector,double angle) {

	//normalize(vector); // No  need to normalize, vector is already ok...

	vector.x = (float)(vector.x * Math.cos(angle) - vector.y * Math.sin(angle));

	vector.y = (float)(vector.x * Math.sin(angle) + vector.y * Math.cos(angle)) ;

}
[/quote]
The issue is that rotate one time by PI/3 isn’t then same as rotate 10 times by PI/30 !! Result are totally different:

Rotate by PI/3

Vector before:
x=-0.5773502691896258
y=-0.5773502691896258
z=-0.5773502691896258

Vector after:
x=0.21132486540518702
y=-0.10566243270259373
z=-0.5773502691896258


Rotate 10 times by PI/30

Vector before:
x=-0.5773502691896258
y=-0.5773502691896258
z=-0.5773502691896258

Vector after:
x=0.17820429666750315
y=-0.7207237170724873
z=-0.5773502691896258

As a result after a “small” rotation, rendition is ok, but if I try to rotate by PI/2, vectors become total non-sense and the picture is totally distorded !!!
I am missing something huge, but i cannot find what…

Anybody ever ran into this issue ?

PS: I tried to use double instead of float to represent a vector with no success…

hmm. I havent done a rotate by hand in years… not since discovering the vecmath package in Java3D…

Do you have similar rotation methods for each axis? I believe you are running into the mathmatical weakness of using Euler angles to represent your rotations. When using Euler angles (a vector representing the rotation about each of the x,y, and z axis) small rotations will appear to work but include very small errors that add up. As any of the rotations approach 90 degrees, the Euler representation breaks down because of something called a gimbal lock (essentially reducing the degrees of freedom of the rotation). The accumulated error in the Euler approach has to do the trig, not the precision of the numbers.

As Jeff mentions, the vector math package provides ways to do rotation. You can use the Euler approach, axis-angle, or quaternions. For rotations in all three directions, quaternions are mathmatically the most stable. This article includes an overview including example code for implementing rotations: http://jdj.sys-con.com/read/99792.htm. See page 3, ‘Slicker than Euler’ and figure 7 (http://res.sys-con.com/story/jun05/99792/jacobs-fig7.jpg) . The vector math package is used except for the conversion between Euler angles and quaternions. There are also several references that should help too.

Good luck,
Mike

Thanks for your answers guys.

Mike thanks for this link about the “gimbal lock” and euler angles, it was quite interesting.

The bug was very stupid:

I forgot that java/c++ procedures are not “atomic”. So if i change vector.x, but i have to use it to calculate vector.y…i have to first save vector.x in a variable :wink: !
This happend because i just recopied was i found in my math book forgetting to adapt it to a procedural language such as Java…

This is the correct way to rotate a vector.


private void rotateZ(Vector vector,double angle) {

      //normalize(vector); // No  need to normalize, vector is already ok...

      Float oldX = vector.x; 

      vector.x = (float)(vector.x * Math.cos(angle) - vector.y * Math.sin(angle));

      vector.y = (float)(oldX * Math.sin(angle) + vector.y * Math.cos(angle)) ;

}

heh yup that would do it.

Ima bit emabressed I didnt spot it!

No problem Jeff !!

That is funny how the stupidest problems are often the hardest to spot !