• 14
• 12
• 9
• 10
• 13

how to compute vector projection matrix

This topic is 4439 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

Recommended Posts

I'm trying to create a matrix that projects one vector onto another. I already know to accomplish this you do: v' = (v*n)n where v is your original vector and n is the direction you wish to project to. But after projection, I need v' to be the same length as v, which does not happen doing normal projection. I already know how to build the matrix which does the above, but how do you build a matrix that also preserves vector length after the transformation? I want to be able to orient an object on terrain so that it's y-axis points in the direction of the surface normals.

Share on other sites
Is there any particular reason you can't just normalize the vectors?

Share on other sites
You need a rotation matrix R that would rotate v such that R*v would "point" to the same direction as n.

You could construct such a matrix by creating a rotation quaternion and then converting the quaternion to rotation matrix.

Another way is to use Rodrigues' rotation formula, and construct the matrix directly:

R = I + sin(a)*[w] + (1-cos(a))*[w]2,

where:
I - Identity matrix
a - Angle between v and n ( ex: ArcCos( Dot(v, n) ) )
w - Normalize( Cross( v, n ) )
[w] - The cross matrix such that for any vector u: [w]*u = Cross( w, u ).

If both v and u are normalized, the process can be seriously optimized:

R = I + [w] + b*[w]2,

where:
w - Cross( v, n )
b - 1/(1 + Dot( v, n ))

Share on other sites
I can already construct a matrix that performs the rotation of v to n. What I need is a matrix that preserves the length of v AFTER the rotation.

Plus it does not matter if v and n are already normalized. The projection of v onto n does NOT have a length of 1.

Share on other sites
Quote:
 Original post by oconnellseanmI can already construct a matrix that performs the rotation of v to n. What I need is a matrix that preserves the length of v AFTER the rotation.
A properly constructed rotation matrix does preserve the length of the vector it operates on, so this shouldn't even be an issue. Are you sure you're building the rotation matrix correctly? If you're not sure, you could post the code for us to look at...

Share on other sites
Here's my code:

void normalize(float *n){	float mag = sqrt(n[0]*n[0] + n[1]*n[1] + n[2]*n[2]);	n[0] /= mag;	n[1] /= mag;	n[2] /= mag;}float mag(float *n){	return sqrt(n[0]*n[0] + n[1]*n[1] + n[2]*n[2]);}int _tmain(int argc, _TCHAR* argv[]){ 	float v[] = {1, 0, 0};	float n[] = {1, 1, 0};	float m[9];	normalize(n);	m[0] = n[0]*n[0];	m[1] = n[1];		m[2] = n[2];	m[3] = n[0];		m[4] = n[1]*n[1];	m[5] = n[2];	m[6] = n[0];		m[7] = n[1];		m[8] = n[2]*n[2];	float v0[3];		v0[0] = m[0]*v[0] + m[3]*v[1] + m[6]*v[2];	v0[1] = m[1]*v[0] + m[4]*v[1] + m[7]*v[2];	v0[2] = m[2]*v[0] + m[5]*v[1] + m[8]*v[2];	printf("After transform: v={%f,%f,%f}  l=%f\n", v0[0], v0[1], v0[2], mag(v0));		normalize(v0);	printf("Rescale: v={%f,%f,%f}  l=%f\n", v0[0], v0[1], v0[2], mag(v0));	return 0;}

I basically given my direction vector n I construct the rotation matrix like so:

    m = [  nx*nx    ny        nz     ]        [  nx       ny*ny     nz     ]        [  nx       ny        nz*nz  ]

Share on other sites
Okay, I figured it out. I was WAY OFF on how to calculate this correctly. Here's the actualy correct solution.

	Vector3 v(1, 0, 0);	Vector3 n(1, 1, 0);	n.normalize();	Vector3 axis = crossProduct(v, n);	axis.normalize();	float theta = angle(v, n);	Matrix4 mat;	mat.identity();	mat.setupRotate(axis, theta);	Vector3 v0 = v * mat;	printf("new v = [%f %f %f]\n", v0.x, v0.y, v0.z);

So basically what I finally realized is that you just take the cross product of your vector v and n, then find the angle between the two vectors..........then simply rotate theta radians around the cross product vector. That's it.