0
101 Feb 06, 2006 at 11:50

in 3D, if i have normal vector, how can i get x,y and z angles that represents same rotation?
What im trying to do is, i have plane, then i want to construct matrix that when applied on object, object is projected onto plane.

#### 17 Replies

0
101 Feb 06, 2006 at 12:13

That totally depends on your system of transformations. An X,Y,Z order of transformations yields a totally different matrix than a Y,X,Z order, for example. YXZ is most commonly used.

Plus the fact that you can’t convert a single vector into euler angles, as a single vector isn’t a full orientation yet (you don’t know the rotation about the normal itself), so you can only get two angles.

(Hmm deja vu. Please use the search before opening a topic :unsure:)

0
101 Feb 06, 2006 at 12:42

maybe im explaining it wrong by talking about angles.
i want something what D3DXMatrixShadow function does, its documentation says:

Builds a matrix that flattens geometry into a plane

but i want to project object onto plane and have it facing same or opposite direction as plane normal, i dont want to flattern geometry.
i know how to get translation vector from plane normal and distance, but i dont know how to make it facing same direction as plane normal, bcos to build that matrix, i need translation plus either angles or quaternion

0
101 Feb 06, 2006 at 14:33

Right, I skipped over the second line in your startpost, sorry about that. In fact, what you’re trying to do has nothing to do with euler angles. What you need is a scale in an arbitrary direction. You can google for such a matrix setup, but I find it more interesting to investigate what you need to do, and devise a matrix out of that.

If you want to scale an arbitrary point p in direction n with scale s, where n is a unit vector, you need to form a new vector that is the projection of p onto the plane with normal n, and add to that the difference of the original vector and the new vector, multiplied by s.

In other words:

p’ = p + (s-1)*dot(p, n)*n

<=>

p’.x = p.x + (s - 1) * (p.x * n.x + p.y * n.y + p.z * n.z) * n.x
p’.y = p.y + (s - 1) * (p.x * n.x + p.y * n.y + p.z * n.z) * n.y
p’.z = p.z + (s - 1) * (p.x * n.x + p.y * n.y + p.z * n.z) * n.z

Since for a matrix you need the form p’.x = a*p.x + b*p.y + c*p.z + d (a linear system of equations), you’ll need to rewrite the above equations to get the values you put in your matrix.

p’.x = (n.x * n.x * (s-1) + 1)*p.x + (n.x * n.y * (s-1))*p.y + (n.x * n.z * (s-1))*p.z
p’.y = (n.y * n.x * (s-1))*p.x + (n.y * n.y * (s-1) + 1)*p.y + (n.y * n.z * (s-1))*p.z
p’.z = (n.z * n.x * (s-1))*p.x + (n.z * n.y * (s-1))*p.y + (n.z * n.z * (s-1) + 1)*p.z

Assuming D3D’s system where vectors are row-matrices, you’ll need to put the value (n.x * n.x * (s-1) + 1) at location (1, 1) (meaning row 1, column 1), (n.x * n.y * (s-1)) at (2, 1), etc..

To get what you need, simply take n as the normal of the plane you want it to be projected upon, and s=0 as you want to scale to zero in that direction. You might need a translation as well if your plane doesn’t touch the origin.

0
101 Feb 06, 2006 at 16:42

x = cos(u)sin(v)
y = sin(u)sin(v)
z = cos(v)

0
101 Feb 06, 2006 at 21:04

huh, looks like alot of calculations, this may be too dificult for me to implement.
is there any chance i can do this using matrix equations?
also, im not sure but, you’re also applying scale to result.
sorry, i need it only without scaling.

x = cos(u)sin(v)
y = sin(u)sin(v)
z = cos(v)

what is u and v ?

0
101 Feb 06, 2006 at 23:34

huh, looks like alot of calculations, this may be too dificult for me to implement.

I think you’re staring too much at the equations and not at what I’m really trying to say. Do you know what a matrix basically does? I guess not because the answer is right in front of you, I’m explaining how to build a matrix so you can use that in your calculations. In the 4x4 matrix you need to put 16 values, and I’m showing how you can calculate each of them.

Do you know how to build a rotation-matrix, for example? Or are you simply using a predefined function for that? And what API are you using, OpenGL or Direct3D?

0
167 Feb 07, 2006 at 04:52

There’s no need for trigonometry in this problem. It’s simple linear algebra, as .oisyn points out. I’m a little confused by your terminology though; you say you want to “project” an object onto a plane, but ‘project’ usually means flattening it. Do you want to rotate the object so that it faces the same direction as the plane’s normal?

0
101 Feb 07, 2006 at 11:17

im using Direct3D. basically i know the idea how values are stored in 4x4 matrix, i’ve tried to built some rotation matrix but without success, so im only using predefined functions now. because everytime im trying to do some trigonometry manually it simply doesnt work.

Do you want to rotate the object so that it faces the same direction as the plane’s normal?

yes, this is exactly what im trying to do. sorry for confusing you.
if i could put that rotation into matrix i could use that matrix in further calculations.

0
101 Feb 07, 2006 at 11:42

Alright, so it has nothing to do with projection onto a plane.

Well, do you have a function to form a rotationmatrix out of an axis and angle pair? It isn’t that hard. The axis is the crossproduct between the natural plane normal (when no rotation should be applied; I guess you want this to be ‘up’) and the rotated plane normal. The angle is the inverse sine of the length of the crossproduct. Be sure to normalize the axis before passing it to the aprropriate function.

0
101 Feb 08, 2006 at 17:25

im trying to calculate this angles by taking angle for each world axe then im placing this anles into matrices. i have this code:

    // vNormal is plane normal, input
// get 3 rotation angles around 3 world axes
FLOAT fXAngle = D3DXVec3Dot( &vNormal, &D3DXVECTOR3( 1,0,0 ) ) ;
FLOAT fYAngle = D3DXVec3Dot( &vNormal, &D3DXVECTOR3( 0,1,0 ) ) ;
FLOAT fZAngle = D3DXVec3Dot( &vNormal, &D3DXVECTOR3( 0,0,1 ) ) ;
// get rotation axes
D3DXVECTOR3 vnA, vnB, vnC;
D3DXVec3Cross( &vnA, &vNormal, &D3DXVECTOR3( 1,0,0 ) );
D3DXVec3Cross( &vnB, &vNormal, &D3DXVECTOR3( 0,1,0 ) );
D3DXVec3Cross( &vnC, &vNormal, &D3DXVECTOR3( 0,0,1 ) );
// create rotation matrices
D3DXMATRIX mrY, mrX, mrZ;
D3DXMatrixRotationAxis( &mrX, &vnA, fXAngle );
D3DXMatrixRotationAxis( &mrY, &vnB, fYAngle );
D3DXMatrixRotationAxis( &mrZ, &vnC, fZAngle );
// put into single matrix
mat = mrX * mrY * mrZ;


but it doesnt work, what may be wrong?
rotation is done at world origin so, i think, x-y-z order is not important.

0
101 Feb 08, 2006 at 17:45

I have no idea what you’re doing with all the axes, but you should do something like this:

Vector3 axis = Cross(plane.normal, Vector3(0, 1, 0));  // cross with the 'up' direction
float len = Length(axis);
if (len == 0)
// no rotation, return an identity matrix
else
{
float angle = asin(len);
axis *= 1/len;
// return axis/angle rotation matrix using 'axis' and 'angle'
}

0
167 Feb 08, 2006 at 18:31

ikk,

A dot product is not an angle. You seem to be confused on this point. D3DXMatrixRotationAxis expects an angle, which is the arc-cosine of the value returned by the dot product (when the two vectors being dotted are unit length). However, there is no need to find rotation angles about the three world axes. .oisyn has posted a solution that works for everything except a 180° rotation. You should think carefully about what the code he posted is doing, i.e. the geometric meaning of the cross product in relation to the plane’s normal vector.

0
101 Feb 10, 2006 at 15:24

ok, thanx for all help

0
101 Feb 13, 2006 at 11:32

Hi ikk

I’m also intersted in this topic. I’m also facing same problem for angle using normal . If u found any solution please let me know.

alex

0
101 Feb 13, 2006 at 14:09

i’ve converted .oisyns code from post #12 to direct3d version:

//vNormal is an input
D3DXVECTOR3 vAxis;
D3DXVec3Cross( &vAxis, &vNormal, &D3DXVECTOR3( 0,1,0 ) );
FLOAT fLen = D3DXVec3Length( &vAxis );
if( fLen == 0 ){
// no rotation, return an identity matrix
D3DXMatrixIdentity( &mat );
}else{
FLOAT fAngle = asinf( fLen );
// return axis/angle rotation matrix using 'axis' and 'angle'
D3DXMatrixRotationAxis( &mat, &vAxis, fAngle );
}
// result is in mat


but later i’ve found out that using only normal vector in my task isnt enough, so im using quaternion plus position instead

0
101 Feb 14, 2006 at 08:44

Dear ikk

is ur code working perfect ? please send me quaternion code . i would like to see it.

alex

0
101 Feb 14, 2006 at 11:51

code is working, but not perfectly. i dont understand what it returns when angle betwen input normal and up vector (0,1,0) is less than 90 degrees, angle isnt what it should be in those cases.
i’m sending you quaternion code, but it doesnt use normals to compute axis-angle then matrix; it computes output matrix from quaternion and position immidiatelly.