# Rotate Axis to surface normal

15 replies to this topic

### #1elijah

New Member

• Members
• 21 posts

Posted 01 October 2009 - 11:24 PM

Hi
I am a new to graphic programming. I manage to get the surface normal of a triangle. Now I want to rotate an axis using right hand rule. How do you go about doing this ?

God Bless
Eng Huat

### #2Reedbeta

DevMaster Staff

• 5340 posts
• LocationSanta Clara, CA

Posted 01 October 2009 - 11:44 PM

http://www.devmaster...mation_matrices
reedbeta.com - developer blog, OpenGL demos, and other projects

### #3SyntaxError

Valued Member

• Members
• 139 posts

Posted 02 October 2009 - 12:03 AM

I'm a bit confused by the question. You have a triangle normal and you also have a second vector and you want to rotate that second vector around the normal? Or something else? When you say "to" surface normal it implies to me they will be the same normal when you are done in which case there is really nothing to do so I figure you mean something else.

### #4elijah

New Member

• Members
• 21 posts

Posted 02 October 2009 - 12:13 AM

Imagine there is a slope and I need to place the tank up the slope where the top of the tank will be the z - axis.

### #5SyntaxError

Valued Member

• Members
• 139 posts

Posted 02 October 2009 - 12:46 AM

elijah said:

Imagine there is a slope and I need to place the tank up the slope where the top of the tank will be the z - axis.

Ok got you.

So if you have two unit vectors; your normal and the Z of the tank, you can get the cos of the angle between them by taking the dot product of the two vectors. So the acos of that then gives you the angle you need to rotate your tank by. Then if you take the cross product of the same two vectors and normalize the result you will get a unit vector axis that you can rotate your tank around by the aforementioned angle.

Then you can build a matrix to rotate your tank. Here is some crappy C++ code I wrote for that. Note that a) I am working left hand cooridnates b) I left off the last column of the matrix to save a bit of calculation. (I assume it to be 0,0,0,1 going down) and c) you will still have to multiply in the translation matrix to put your tank in the correct location on the hill. Read Reedbeta's link for an overview.



template<class T> void TRPG3DMatrix<T>::Set(const TRPGVector<T> &clAx, T fTheta, CRPG3DAxisRotate &clType)

{

m_pType = &clType;

T c = cos(fTheta);

T s = sin(fTheta);

T t = 1.0-c;

T fX = clAx.X();

T fY = clAx.Y();

T fZ = clAx.Z();

m_a.D[0][0]= t*fX*fX + c;           m_a.D[0][1]= t*fX*fY - s*fZ;        m_a.D[0][2]= t*fX*fZ + s*fY;

m_a.D[1][0]= t*fX*fY + s*fZ;        m_a.D[1][1]= t*fY*fY + c;           m_a.D[1][2]= t*fY*fZ - s*fX;

m_a.D[2][0]= t*fX*fZ + s*fY;        m_a.D[2][1]= t*fY*fZ + s*fX;        m_a.D[2][2]= t*fZ*fZ + c;

m_a.D[3][0]= 0;                     m_a.D[3][1]= 0;                     m_a.D[3][2]= 0;

}



Hope that helps

### #6rouncer

Senior Member

• Members
• 2755 posts

Posted 02 October 2009 - 04:54 AM

If you have a fuzzy front, then make the up the normal of the triangle, cross to get the right, normalize the right (very important) then recross to get the real front.

just point the fuzzy front flat in the direction you generally want the tank to go in.

And that should work too - just dont expect it to go straight up a horizontal(vertical i mean) cliff, because thats the weakness with this method. :)

And as I guess you know, thats a valid basis for the models orientation, which is what you wanted.
you used to be able to fit a game on a disk, then you used to be able to fit a game on a cd, then you used to be able to fit a game on a dvd, now you can barely fit one on your harddrive.

### #7elijah

New Member

• Members
• 21 posts

Posted 02 October 2009 - 06:42 AM

Hi SyntaxError,

I have tried your recommendation. It works for most cases. I did this test on a cylinder. half of the body that is facing back gives the correct axis, but the front body of the cylinder gives the wrong axis. Any ideal how I can solved this ? This cylinder is cull back design.

### #8elijah

New Member

• Members
• 21 posts

Posted 02 October 2009 - 06:45 AM

Hi roucer,

I'm sorry What is fuzzy front. I'm new in graphics.

### #9rouncer

Senior Member

• Members
• 2755 posts

Posted 02 October 2009 - 07:01 AM

I invented it sorry :). I mean point on the xz plane where you want the tank to "point" as if it was on flat ground.

then if you double cross and normalize like that youll "tilt" the tank onto a slanted ground but itll still have its turret pointing in the direction you want it.
you used to be able to fit a game on a disk, then you used to be able to fit a game on a cd, then you used to be able to fit a game on a dvd, now you can barely fit one on your harddrive.

### #10elijah

New Member

• Members
• 21 posts

Posted 02 October 2009 - 07:14 AM

Any tips on how to solve my problem. Perth is a nice place. I was there 2 years ago

### #11SyntaxError

Valued Member

• Members
• 139 posts

Posted 02 October 2009 - 12:53 PM

elijah said:

Hi SyntaxError,

I have tried your recommendation. It works for most cases. I did this test on a cylinder. half of the body that is facing back gives the correct axis, but the front body of the cylinder gives the wrong axis. Any ideal how I can solved this ? This cylinder is cull back design.

Now I'm confused again. You are using your cylinder as your tank or the cylinder as your terrain? You should be transforming your entire tank by the same matrix so if it's wrong the whole thing should be wrong.

In any case if you are using a cylinder as your terrain, you need to make sure you are getting the correct surface normals. I'm not sure how you are storing your data but in a mesh edges can't all be directed in one winding. If you draw out a mesh on a piece of paper you will notice you can't make your triangles all one winding. Therefore you need to be able to somehow get the correct winding so you can get the correct normals. Perhaps that's your problem. What mesh format are you using? Is it your own?

The other thing is there are special cases where your tank is already aligned with the terrain or exactly opposite the terrain. In those cases you can't use cross product because it won't give you an axis vector. Just add in a couple special cases for that.

Finally you still need to point your tank in the right direction. You can do that rotating around Z before you transform you tank to the terrain.

### #12elijah

New Member

• Members
• 21 posts

Posted 02 October 2009 - 01:16 PM

Actually I'm using the cylinder as a test case. When I press on the face of the triangle that made up the cylinder, the Z - Axis will point to the normal of the triangle.

The normal is calculate from the 3 points in the triangle. The code is below

public static Vector3f getTriangleNormal(Point3f p1, Point3f p2, Point3f p3) {
Vector3f Normal, AB, AC;

AB = new Vector3f(p1);
AB.sub(p2);

AC = new Vector3f(p1);
AC.sub(p3);

Normal = AB.cross(AB, AC);
Normal.normalize();

if (Normal.getX() == -0.0f) { Normal.setX(0.0f); }
if (Normal.getY() == -0.0f) { Normal.setY(0.0f); }
if (Normal.getZ() == -0.0f) { Normal.setZ(0.0f); }

return Normal;

}

public Transform3D getTransform3D(){
Vector3f INVERSE_NORMAL = NORMAL.clone();

TRANSFORM_3D_AXIS = new Transform3D();

float Angle_Value = gcMaths.VectorDotProduct( INVERSE_NORMAL, Vector3f.POSITIVE_Z_AXIS );

float angle = FastMath.acos( Angle_Value );

//AXIS_VECTOR = gcMaths.VectorCrossProduct( INVERSE_NORMAL , Vector3f.POSITIVE_Z_AXIS );

AXIS_VECTOR = gcMaths.VectorCrossProduct( Vector3f.POSITIVE_Z_AXIS , INVERSE_NORMAL );

AXIS_VECTOR.normalize();

AXIS_ANGLE = new AxisAngle3f( AXIS_VECTOR, angle );

matrix = new Matrix4f();
matrix.set( AXIS_ANGLE );
TRANSFORM_3D_AXIS.set( matrix );

NAN_CASE = CheckNAN.checkTransform3D( TRANSFORM_3D_AXIS );

TRANSFORM_3D_AXIS = NegativeZeroCleanup.cleanTransform3D( TRANSFORM_3D_AXIS.getCopy() );

TRANSFORM_3D_AXIS = NANCleanup.cleanTransform3D( TRANSFORM_3D_AXIS.getCopy() );

return TRANSFORM_3D_AXIS;
}

Just think like a 3D cad drawing. Clicking on the surface of the object, the axis will point towards the normal of the face.

Hope you can help me on this.

### #13SyntaxError

Valued Member

• Members
• 139 posts

Posted 02 October 2009 - 02:41 PM

elijah said:

public static Vector3f getTriangleNormal(Point3f p1, Point3f p2, Point3f p3)

I'm not entirely familiar with the package you are using however one thing I would like to point out is the ordering of your points is important for normal calculation. This is called winding. For instance is p1, p2 p3 clockwise looking from the front of your triangle or counterclockwise? If you can't guarantee it's always the same your normals will be inverted sometimes.

elijah said:

Just think like a 3D cad drawing. Clicking on the surface of the object, the axis will point towards the normal of the face.

Great...however CAD programs work in a particular winding. You need to choose one and enforce it. I use clockwise myself but it's up to you.

### #14elijah

New Member

• Members
• 21 posts

Posted 07 October 2009 - 05:49 AM

Thanks you very much for helping me. I have a new post on Vector intersecting a traingle. Can anybody help me on this ?

### #15rouncer

Senior Member

• Members
• 2755 posts

Posted 07 October 2009 - 10:29 AM

Do you want to orientate a model apon a triangle??? what i said is it!!!
you used to be able to fit a game on a disk, then you used to be able to fit a game on a cd, then you used to be able to fit a game on a dvd, now you can barely fit one on your harddrive.

### #16elijah

New Member

• Members
• 21 posts

Posted 09 October 2009 - 08:37 AM

Actually I what to revolve a outline of the shape around an axis but the winding rules get mix up. You are correct on the winding rule. So now I'm thinking of using the calculate Normal to check it will intersect the plane.

#### 1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users