5
\$\begingroup\$

As I hask ask here I'm working on how my objects can move over the terrain and other objects. My proposal and also an idea in the answers was to calculate the rotation from the object with the normals from other objects around (under and in front) the moving object.

My main problem for that is how I can get the normal from an object at a special position. Let's take the ramp on the road from the old example. It depends from which side my car comes. If it comes from front it can drive along the ramp but if it comes from back it moves against the wall. Of course there are other normals if I come from the other side. All my objects have these variables:

float vertices[];
float normals[];
short drawOrder[];

float[] modelMatrix;
AABBox boundingBox;

So you see I can allways get the vertices, normals and the position. I can also test if the object collides with another object with the bounding box (axis aligned) but I have no idea how I can get the normal where the collision happens but that is the important thing for the rotation of the car. Do you have any ideas or are there usual way how to do this?

\$\endgroup\$
7
+50
\$\begingroup\$

To put it simply - winding order. Winding order is the way you define which side of a triangle is the front and which side is the back. For example, OpenGL's default winding order is counter-clockwise, which means the triangle on the left is pointed out of the screen and the triangle on the right is pointed into the screen. If you had back-face culling turned on you would not be able to see the right-hand triangle.

1       1
|\      |\
| \     | \
|  \    |  \
2---3   3---2

This works together with the non-commutative property of the vector cross product

a × b = -(b × a)

to ensure that when you calculate the normal of a triangle it points in the right direction. To use the triangle example from above, if you always calculate your normal vector as follows, the normal will always point out from the front of the triangle (towards you for the left triangle, away for the right). Note that to obtain a unit normal, which is desirable for lighting and collision, you also need to normalize the vector.

n = (p2 - p1) × (p3 - p1)

Since the vector cross product is conventionally right-handed, you can verify the normal direction yourself using this method with your right hand:

  1. Point your index finger in the direction of the left-hand operand a
  2. Point your middle finger in the direction of the right-hand operand b
  3. Your thumb is now pointing in the direction of the vector obtained with the cross product a × b

Notice how if you switch the operands your thumb ends up in the opposite direction.


So how does this relate to collision detection?

To ensure that you always obtain a collision normal that will point away from the surface, only detect collisions from the front side. If, like in your example, you want to be able to collide with both sides of an object, put two collision surfaces, one flipped, on top of each other. Again, refer back to the two triangles and how the winding order defines which side is the front. If you layer the two triangles, now you have a double-sided triangle with a different normal (the exact opposite!) on each side. Since you only detect collisions with the "front" of a surface you always obtain the correct normal.

Respecting winding order is how convex hull algorithms are still able to determine which is the "outside" despite not being given that information explicitly. The Quickhull algorithm uses tetrahedra that are eventually used to build a triangle mesh, and if the winding order is maintained properly from the start all the normals will be facing in the correct direction.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.