|
7/8-2005 |
|
This paper concerns itself with the making of an ortho-normal basis matrix when you only know one basis vector. This can be extremely useful when rewriting equations containing vector operations.
If you are a skilled mathematician you will know about the Gram Schmidt method which is used to make an orthogonal matrix (not necessarily normalized) from n linearly independent vectors (in n dimensions). Our approach is that we only know one vector so the Gram Schmidt method isn’t suitable. What if you for some reason wanted to rotate all your vectors into a new space (v-space), where an important vector, say,
was represented as
This would be nice in a function of the type
where ni and nj are two arbitrary vectors, since we could represent this function in v-space as
Get the idea? But how do we make a matrix that can rotate v, ni and nj into the v-space when only knowing one basis vector - the normalized v vector itself? We will need two vectors which are perpendicular to the v vector (note that we work in 3 dimensions). To do this, we will represent the direction of the v vector in polar coordinates. That is
because we are searching for an ortho-normal basis matrix, .
Now, the algorithm is easier to express in pseudo-c++ code: v0 = normalize(v); theta = acos(v0.x); if(theta == 0) // Watch out for precision errors { // v0 must be the vector (0, 0, 1) v1 = (r, 0, 0); } else { /* NOTE Adding pi/2 to theta will rotate v1 90 degrees, which will make v1 perpendicular to v0. Note that you can not add pi/2 to phi and get the same result. */ theta1 = theta + pi/2; v1 = ( v0.x / sin(theta) * sin(theta1), v0.y / sin(theta) * sin(theta1), cos(theta1)); }We will only be needing one more basis vector, v2, which, in 3 dimensions, is very easy to calculate by using the cross product between v0 and v1: v2 = cross(v0, v1) This will generate the following right-handed ( ) matrix,
If you want a left-handed ( ) matrix simply invert the cross product:
v2 = -cross(v0, v1) = cross(v1, v0)) The matrix above will take any vector in v-space and rotate it into world space. This is the opposite of what we want, but the inverse matrix will do the right thing and is calculated because the matrix is happening to be an ortho-normal matrix, such as;
So, the matrix that rotates vectors in world space into v-space is:
q.e.d. Note that if the vectors v0, v1 and v2 were not of unit length we would have to calculate the inverse matrix, but this would also have reduced the equation further because the v vector would be presented as in v-space, .
If you want to use this method the algorithm would look like this v0 = v; r=magnitude(v); // Divide by length theta = acos(v0.x / r); if(theta == 0) // Watch out for precision errors v1 = (r, 0, 0); else { theta1 = theta + pi/2; // Note that the z component is multiplied by r v1 = ( v0.x / sin(theta) * sin(theta1), v0.y / sin(theta) * sin(theta1), r * cos(theta1)); } v2 = cross(v0, v1); M(v0,v1,v2).inverse();Jakob Gath Blacksmith Studios |
|
Return to articles overview |
|
Copyright Blacksmith Studios 2005 © |