 # still my worst nightmare...

hi, my 2nd question for today to keep things going on i posted this question a few weeks ago, but wasnt able to solve the problem…

i have some kind of off-road terrain ( flat roads, hills, pits, …) and i drive around on it with my car…
the terrain is made up of polys. imagine an excerpt of my scene: in the middle there’s the flat road, on the left the hill, and to the right a little pit to fall into, as well as many other hills
i can simply detect where my car is with my PtInsidePolygon function… so f.e. when i detect my car is over the “hill-poly”, i need to make the car going up the hill correct, i.e. regardless how the car is moving( i could drive the hill up backwards). so what i need to do is translate/rotate the car and then draw it, so its standing perpendicular to the hill-poly, facing in any direction i want… ok, i’m able to define a normal to the hill-poly and so on, but this is just too much for me!

i guess i have to take the current angle of the car, compare it with the hill-poly angle and make some kind of magic to get it right sorry to ask the same question again, but this is making me nervous!

i could post more details on demand(didnt want to make this post too long…)

Here’s how to position a car on terrain:

1. figure out the normal.
2. rotate the car to the normal.
4. rotate the car AROUND THE NORMAL to the heading.
5. figure out the position (x,y,z)
6. translate the car to the position

Done!

If you’re viewing from inside the car, you do the exact same thing, except backwards, in reverse, to the camera.

You are actually very close!!

What you need is an Up-Vector for your car. Imagine a box around your car. the Up-vector is simply the normal to the side of the box that is at the top of the car.

Since you have the normal for the hill, the road, and the other faces in your terrain, the only thing your need to do is :

1. Find the surface on wich your car is.
2. Find the normal of that surface
3. Calculate the angles between the up-vector and surface normal.
4. transform your car first without worrying about the angles in 3. The transforms I am thinking about here are : Position of the car, steering left or right right.
5. Rotate the car again using the angles caculated in 3. This is like tilting the box around the car!

Let’s call u (ux, uy, uz), the car up-vector and n (nx, ny, nz) the terrain normal.

Any algebra books will tell you that

x-axis angle = acos( (uy*ny) / (lenght(u) * length(n)) )

y-axis angle = acos( (uz*nz) / (lenght(u) * length(n)) )

z-axis angle = acos( (ux*nx) / (length(u) * length(n)) )

This is pretty tricky to do, but it can be done. I’m going to describe just one of the ways it could be done. You say you can get the normal of the terrain at any point, that’s good you are going to need it. You also need two more vectors. Both tanget to terrain and perpendicular to one another. One of these vectors should point in the forward direction, and the other always in some other direction as determined by either the left or right hand rule. Together these three vectors (unit vectors I’m assuming btw) describe a new coordinate system. Your vehicle exists in object space correct? You need to take the coordinate system of the vehicle in object space and transform it into the new coordinate system as determined by those three vectors I spoke of above. To do these is really suprisingly easy. You simply take those three 3D unit vectors and use them as the columns or rows of a transformation matrix (which you use, columns or rows is dependent on how you represent a vector in matrix form). So first make sure the vehicles is located at the origin of its object space. I’m assuming this point would be the vehicle’s center of gravity as well since all rigid rotation goes about the center of gravity. Now transform the vertices of the vehicle by the transformation matrix just simply by mulitplying each vector by the matrix. You then need to translate those points into world space. You could actually do this at the same time as the first transformation if you first multiply the tranformation matrix by the translation matrix and use the resultant matrix to do all the transforming for the vehicle. There are some details you must be aware of before this would work right. You must be consistent in the orientation of your coordinate systems. If up in object space is along the +y axis, then the y axis of the transformed coordinate system would be in the direction of the terrain’s outward facing normal. If your vehicle’s length is along the x axis and is pointed in the +x direction, then that vector tangent to the terrain that lies in plane of motion (not necessarily direction, since going reverse doesn’t flip your object coordinate system), must be the x axis of the transformed coordinate system. Then if the +z axis in object space goes to the right, then the other vector tangent to the terrain must point to the right with respect to the other two vectors of the tranformed coordinate system. Now just doing this will work but the result will not be pleasing as the turning motion will be quite sudden and unrealistic. Instead you should transform vehicle’s coordinate system by using an interpolated matrix. An interpolation of the cuurent vehicle orientation to the desired orientation. And to do this easily, you need to use quaternions. You will need to convert the matrices (sans translation) into quaternions and you linearly interpolate those, turning the result back into a matrix, which is what you can then multiply by the translation matrix, and then transform the vehicles vertices into world space. I think someone else could probably summarize this method better. hello i’ve coded and read some math stuff as well( i am really sad about not learning this in school for free )

however, i get some strange results…

1.)i assigned normals to the poly(s)

2.)i assigned the car an up-vector, just like Gorg said

3.)i test wether the car is inside the poly(the terrain is flat and i drive into the poly,which differs from the other polys)

4.) i calculate the angles and draw the car like this:

//calc angles:
rot.x = acos((player.upvector.y*cVector.y)/(length(player.upvector)*length(cVector)) );

rot.y = acos((player.upvector.z*cVector.z)/ (length(player.upvector) * length(cVector)) );

rot.z = acos((player.upvector.x*cVector.x) / (length(player.upvector) * length(cVector)) );

//where cVector is the polys’ vector…

//car code:
glPushMatrix();
glTranslatef(car_pos.x, car_pos.y, car_pos.z);

//rotate the car:
glRotatef(rot.x,1.0f,0.0f,0.0f);
glRotatef(rot.y,0.0f,1.0f,0.0f);
glRotatef(rot.z,0.0f,0.0f,1.0f);

//rotate in the facing direction
glRotatef( (-facingDirection * 180_OVER_PI), 0.0f , 1.0f, 0.0f);

glCallList(Car);
.
.
glPopMatrix();

so,i drive into the poly(viewing the car from behind), and the following happened:

the “camera” moved some units to the left and some units forward…i could see the car a bit but it wasnt rotated correct…i WASNT ABLE anymore to make some other rotations( i built in some keys to rotate the camera for debugging and stuff…) !!!

i can remember of something called “Gimbal lock” , where everything gets f**ed up and no rotations are possible anymore…

is this a “gimbal lock” ?? would be very interested ( feeling like in a science-fiction movie )
then the only way will be to use quaternions,like DFrey said…(gotta check that out first)

cheers,
sebastian

p.s.: thanks for your patience [This message has been edited by sebastian (edited 07-04-2000).]

I must admit I am puzzled!!!

Originally posted by sebastian:

//rotate in the facing direction
glRotatef( (-facingDirection * 180_OVER_PI), 0.0f , 1.0f, 0.0f);

what is that line for?

it’s just to rotate the car in the heading it should look, as you can see …

but finally i dont wanna annoy you with my problem, think i’ll heavily learn math now…

just one quick point i want to make: calling subsquent glRotates like that will rotate in object space and not in world space.

for instance, if you apply a 90-degree rotation about the x-axis (i.e., glRotatef(90.0, 1.0, 0.0, 0.0)) then the object’s y-axis now points along the world’s z-axis. and the object’s z-axis points toward the world’s negative y.

it’s much better (or at least easier) to find the axis of rotation straight away, rather than applying piece-wise rotations. at least, they never worked for me.

Gimbal lock “normally” occurs when the rotation about the y axis is + or - 90 degrees. “Normally” because I am assuming that the sequence of rotations is xyz (you rotate about the x axis, then the y axis, then the z axis) as opposed to yxz or xyx, for example (there are 12 possible sequences you could choose). If gimbal lock is the source of your problem (given your description of what you are trying to do I would say that at some point you will have gimbal lock problems) there are three things you could do. The best solution (most robust) would be to use Euler parameters or quaternions to represent your rotations. Another solution is to resequence. For example if you are using an xyz sequence you could choose an xyx sequence if you need to rotate about the y axis by 90 degrees. For an xyx sequence the gimbal lock condition would occur at 0 and 180 degrees. Finally (maybe you will think this is the best solution) is to follow phlake’s advice and determine on the fly the axis you need to rotate about and the amount of rotation to achieve the desired orientation.
there’s a new tutorial on gamedev.net about quaternions.it comes along with some useful code… ( i’m really happy about that one    )