Jump to content
  • Advertisement
Sign in to follow this  
Shock

Please verify my vector/look-at matrix code

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

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello all. Im trying to create a left handed look-at matrix. Im using the way described in the dx9 sdk docs for the D3DXMatrixLookAtLH function. I did it using D3DXVECTOR3 and D3DXMATRIX manually as in the docs and it worked, however for some reason its not working with my own vector and matrix classes. I seem to be loosing precision after normalizing, D3DX vectors get 0.999947 ( something like that ) and I get 1.0. Here's how im constructing the LH look-at matrix:
/* Creates a look-at matrix */
inline void matrix4_make_lookat( vector3<T> view, vector3<T> position, vector3<T> up )
	{
		vector3<T> zaxis( view - position );
		zaxis.vector3_normalize();
		vector3<T> xaxis;
		xaxis.vector3_cross_product( up, zaxis );
		vector3<T> yaxis;
		yaxis.vector3_cross_product( zaxis, xaxis );

		_11 = xaxis.v_x;
		_12 = yaxis.v_x;
		_13 = zaxis.v_x;
		_14 = 0;
	
		_21 = xaxis.v_y;
		_22 = yaxis.v_y;
		_23 = zaxis.v_y;
		_24 = 0;

		_31 = xaxis.v_z;
		_32 =  yaxis.v_z;
		_33 =  zaxis.v_z;
		_34 = 0;

		_41 = -xaxis.vector3_dot_product( position );
		_42 = -yaxis.vector3_dot_product( position );
		_43 = -zaxis.vector3_dot_product( position );
		_44 = 1;
	}

Here's my vector templated class:
template <class T> class vector3 
	{
	public:
		/* Constructor ( default ) */
		vector3() : 
		  x(0), y(0), z(0) 
			{
			}

		/* Constructor ( overloaded ) Incoming vector values */
		vector3( T tx, T ty, T tz ) : 
			x(tx), y(ty), z(tz) 
			{
			}

		/* Constructor ( overloaded ) Incoming vector3 class instance */
		vector3( vector3 &vec3 ) : 
			x(vec3.x), y( vec3.y ), z( vec3.z ) 
			{
			}

		/* Overload assignment operator */
		inline vector3 &operator =( const vector3 &vec3 )
			{
				x = vec3.x, 
				y = vec3.y, 
				z = vec3.z;

				return *this;
			}

		/* Overload addition operator */
		inline vector3 operator +( const vector3 &vec3 ) 
			{
				return vector3( x + vec3.x, y + vec3.y, z + vec3.z );
			}

		/* Overload subtraction operator */
		inline vector3 operator -( const vector3 &vec3 )
			{
				return vector3( x - vec3.x, y - vec3.y, z - vec3.z );
			}

		/* Overload multiplication operator ( multiply by type ) */
		inline vector3 operator *( T t )
			{
				return vector3( x * t, y * t, z *t );
			}

		/* Overload add-to-self operator */
		inline vector3  &operator +=( const vector3 &vec3 )
			{
				x += vec3.x;
				y += vec3.y;
				z += vec3.z;

				return *this;
			}	

		/* Overload subtract-from-self operator */
		inline vector3 &operator -= ( const vector3 &vec3 )
			{
				x -= vec3.x;
				y -= vec3.y;
				z -= vec3.z;

				return *this;
			}

		/* Cross Product */
		inline void vector3_cross_product( vector3 &vec3_1, vector3 &vec3_2 )
			{
				x = vec3_1.y * vec3_2.z - vec3_1.z * vec3_2.y;
				y = vec3_1.z * vec3_2.x - vec3_1.x * vec3_2.z;
				z = vec3_1.x * vec3_2.y - vec3_1.y * vec3_2.x;
			}

		/* Dot Product */
		inline T vector3_dot_product( vector3 &vec3 )
			{
				return x * vec3.x + y * vec3.y + z * vec3.z ;
			}

		/* Divide by Scalar */
		inline vector3 vector3_divide_by_scalar( T scalar )
			{
				return vector3( x / scalar, y / scalar, z / scalar );
			}

		/* Vector invert */
		inline void vector3_invert( void )
			{
				x = -x,
				y = -y, 
				z = -z;
			}

		/* Get vector length */
		inline T vector3_length( void )
			{
				return sqrt( x * x + y * y + z * z ); 
			}

		/* Normalize vector */
		inline void vector3_normalize( void )
			{
				T length = vector3_length();

				x /= length; 
				y /= length;
				z /= length;
			}

		/* Set the vector's values */
		inline void vector3_set( T tx, T ty, T tz ) 
			{ 
				x = tx; 
				y = ty; 
				z = tz; 
			}

		/* 3D Vector values */
		T x, y, z;

};

Please tell me if im doing anything wrong anywhere. :( Thanks

Share this post


Link to post
Share on other sites
Advertisement
Maybe you are doing nothing wrong, 0.999947 is practically 1.0.
You get impreciseness as soon as you start calculating with floats already, so if it's 1.0 or 0.999... at the beginning doesn't matter.
But maybe I am wrong...

Constantin

Share this post


Link to post
Share on other sites
At first glance your vector class looks fine, and the lookat function looks correct as well. To me at least the error you describe seems within reasonable limits.

Share this post


Link to post
Share on other sites
Thanks for the reply.

Dude I have even tried with double's and get the same thing

[crying]

Share this post


Link to post
Share on other sites
Does the 0.000053 difference lead to a wrong calculated lookat matrix, or are your only guessing that your vector class is wrong because of the difference?

As jyk pointed out: your vector class seems fine! so if you get a wrong lookat-matrix you should search a mistake in the lookat-function.

Constantin

Share this post


Link to post
Share on other sites

Dammit, I feel so stupid! I was passing the wrong vectors when creating the look-at matrix. Position for view, and View for position.

Stupid me!

Thank you for your help though guys.

One more question though. If I was to create the look-at matrix for use in OpenGL ( uses a right hand coordinate system right? ) what would I need to do?

Im not that math savvy, hence me trying to create my own look-at matrix to get a more in depth understanding of it all.

Thank you, and I am sorry for wasting your time for my stupid ( very stupid! ) mistake.

Share this post


Link to post
Share on other sites
Quote:
One more question though. If I was to create the look-at matrix for use in OpenGL ( uses a right hand coordinate system right? ) what would I need to do?
For OpenGL there are a couple of things to take into account. Starting with the standard algorithm (which is what you have):

Vector3 z = normalize(target-pos);
Vector3 x = normalize(up.Cross(z));
Vector3 y = z.Cross(x);

float tx = -pos.Dot(x);
float ty = -pos.Dot(y);
float tz = -pos.Dot(z);

We now need to load this into an OpenGL-style (column vector) matrix:

[xx xy xz tx]
[yx yy yz ty]
[zx zy zz tz]
[0 0 0 1 ]

Remember that OpenGL is column-major, so this becomes:

m[0] = xx; m[4] = xy; m[8] = xz; m[12] = tx;
m[1] = yx; m[5] = yy; m[9] = yz; m[13] = ty;
m[2] = zx; m[6] = zy; m[10] = zz; m[14] = tz;
m[3] = 0; m[7] = 0; m[11] = 0; m[15] = 1;

This creates a camera space with +z forward. For OpenGL we need -z forward, so as a last step we apply a 180-degree rotation about the y axis. To cut to the chase, replacing the line:

Vector3 z = normalize(target-pos);

With:

Vector3 z = normalize(pos-target);

Will do exactly that.

(I can't absolutely guarantee the correctness of the above, but this is how I've implemented it in my own matrix class, and the results appear to match those of gluLookAt().)

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!