Rotate Axis to surface normal
#1
Posted 01 October 2009 - 11:24 PM
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
#2
#3
Posted 02 October 2009 - 12:03 AM
#4
Posted 02 October 2009 - 12:13 AM
#5
Posted 02 October 2009 - 12:46 AM
elijah said:
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
#6
Posted 02 October 2009 - 04:54 AM
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.
#7
Posted 02 October 2009 - 06:42 AM
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.
#8
Posted 02 October 2009 - 06:45 AM
I'm sorry What is fuzzy front. I'm new in graphics.
#9
Posted 02 October 2009 - 07:01 AM
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.
#10
Posted 02 October 2009 - 07:14 AM
#11
Posted 02 October 2009 - 12:53 PM
elijah said:
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.
#12
Posted 02 October 2009 - 01:16 PM
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.
#13
Posted 02 October 2009 - 02:41 PM
elijah said:
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:
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.
#14
Posted 07 October 2009 - 05:49 AM
#15
Posted 07 October 2009 - 10:29 AM
#16
Posted 09 October 2009 - 08:37 AM
1 user(s) are reading this topic
0 members, 1 guests, 0 anonymous users












