Matrix

Started by
6 comments, last by Kasya 15 years, 8 months ago
Hello, i have a matrix class i don't know how to transform it into world space. my matrix class

template<class T> class _CMatrix {
	public:
		T row[16];

		//Constructors:
		_CMatrix() { memset(row, 0, sizeof(T)*16); }
		_CMatrix(T nrow[16]) { memset(row, nrow, sizeof(T)*16); }
		_CMatrix(_CMatrix &nm) { memset(row, nm.row, sizeof(T)*16); }


		//CMatrix - CMatrix Operators:
		_CMatrix &operator=(const _CMatrix &m) {

			memset(row, m.row, sizeof(T)*16);
			return *this;

		}

		_CMatrix operator*(const _CMatrix &m) {

			T temp[16];

			temp[0] = row[0] * m.row[0] + row[4] * m.row[1] + row[8] * m.row[2];
			temp[1] = row[1] * m.row[0] + row[5] * m.row[1] + row[9] * m.row[2];
			temp[2] = row[2] * m.row[0] + row[6] * m.row[1] + row[10] * m.row[2];
			temp[3] = 0;

			temp[4] = row[0] * m.row[4] + row[4] * m.row[5] + row[8] * m.row[6];
			temp[5] = row[1] * m.row[4] + row[5] * m.row[5] + row[9] * m.row[6];
			temp[6] = row[2] * m.row[4] + row[6] * m.row[5] + row[10] * m.row[6];
			temp[7] = 0;

			temp[8] = row[0] * m.row[8] + row[4] * m.row[9] + row[8] * m.row[10];
			temp[9] = row[1] * m.row[8] + row[5] * m.row[9] + row[9] * m.row[10];
			temp[10] = row[2] * m.row[8] + row[6] * m.row[9] + row[10] * m.row[10];
			temp[11] = 0;

			temp[12] = row[0] * m.row[12] + row[4] * m.row[13] + row[8] * m.row[14] + row[12];
			temp[13] = row[1] * m.row[12] + row[5] * m.row[13] + row[9] * m.row[14] + row[13];
			temp[14] = row[2] * m.row[12] + row[6] * m.row[13] + row[10] * m.row[14] + row[14];
			temp[15] = 1;

			Set(temp);
			return *this; 

		}

		//CMatrix - Scalar operators:
		_CMatrix &operator=(const T m[16]) {

			memset(row, m, sizeof(T)*16);
			return *this;

		}

		_CMatrix operator*(const T m[16]) {

			T temp[16];

			temp[0] = row[0] * m[0] + row[4] * m[1] + row[8] * m[2];
			temp[1] = row[1] * m[0] + row[5] * m[1] + row[9] * m[2];
			temp[2] = row[2] * m[0] + row[6] * m[1] + row[10] * m[2];
			temp[3] = 0;

			temp[4] = row[0] * m[4] + row[4] * m[5] + row[8] * m[6];
			temp[5] = row[1] * m[4] + row[5] * m[5] + row[9] * m[6];
			temp[6] = row[2] * m[4] + row[6] * m[5] + row[10] * m[6];
			temp[7] = 0;

			temp[8] = row[0] * m[8] + row[4] * m[9] + row[8] * m[10];
			temp[9] = row[1] * m[8] + row[5] * m[9] + row[9] * m[10];
			temp[10] = row[2] * m[8] + row[6] * m[9] + row[10] * m[10];
			temp[11] = 0;

			temp[12] = row[0] * m[12] + row[4] * m[13] + row[8] * m[14] + row[12];
			temp[13] = row[1] * m[12] + row[5] * m[13] + row[9] * m[14] + row[13];
			temp[14] = row[2] * m[12] + row[6] * m[13] + row[10] * m[14] + row[14];
			temp[15] = 1;

			Set(temp);
			return *this;

		}

		//Other Functions:
		void LoadIdentity() { 

			memset(row, 0, sizeof(T) * 16);
			row[0] = row[5] = row[10] = row[15] = 1;

		}

		void Translate(T x, T y, T z) {
		
			row[12] = x;
			row[13] = y;
			row[14] = z;

		}

		void TranslateInverse(T x, T y, T z) {
		
			row[12] = -x;
			row[13] = -y;
			row[14] = -z;

		}

		void SetRotationRadians(T x, T y, T z) {
		
			double cr = cos( x );
			double sr = sin( x );
			double cp = cos( y );
			double sp = sin( y );
			double cy = cos( z );
			double sy = sin( z );

			row[0] = ( cp*cy );
			row[1] = ( cp*sy );
			row[2] = ( -sp );
			row[3] = ( 0.0f );

			double srsp = sr*sp;
			double crsp = cr*sp;

			row[4] = ( srsp*cy-cr*sy );
			row[5] = ( srsp*sy+cr*cy );
			row[6] = ( sr*cp );

			row[8] = ( crsp*cy+sr*sy );
			row[9] = ( crsp*sy-sr*cy );
			row[10] = ( cr*cp );


		}

		void SetRotationRadiansInverse(T x, T y, T z) {
			
			double cr = cos( x );
			double sr = sin( x );
			double cp = cos( y );
			double sp = sin( y );
			double cy = cos( z );
			double sy = sin( z );	

			row[0] = ( cp*cy );
			row[4] = ( cp*sy );
			row[8] = ( -sp );

			double srsp = sr*sp;
			double crsp = cr*sp;

			row[1] = ( srsp*cy-cr*sy );
			row[5] = ( srsp*sy+cr*cy );
			row[9] = ( sr*cp );

			row[2] = ( crsp*cy+sr*sy );
			row[6] = ( crsp*sy-sr*cy );
			row[10] = ( cr*cp );

		}

		void SetRotationDegrees(T x, T y, T z) {

			_CVector3<T> angles;
			angles.x = x * 180/PI;
			angles.y = y * 180/PI;
			angles.z = z * 180/PI;
			SetRotationRadians(angles.x, angles.y, angles.z);

		}

		void SetRotationDegreesInverse(T x, T y, T z) {

			_CVector3<T> angles;
			angles.x = -x * 180/PI;
			angles.y = -y * 180/PI;
			angles.z = -z * 180/PI;
			SetRotationRadiansInverse(angles.x, angles.y, angles.z);

		}

		void RotateVector(_CVector3<T> v) {
			
			_CVector3<T> temp;

			temp.x = v.x * row[0] + v.y * row[4] + v.z * row[8];
			temp.y = v.x * row[1] + v.y * row[5] + v.z * row[9];
			temp.z = v.x * row[2] + v.y * row[6] + v.z * row[10];

			v.Set(temp);

		}

		void RotateVectorInverse(_CVector3<T> v) {
			
			_CVector3<T> temp;

			temp.x = v.x * row[0] + v.y * row[1] + v.z * row[2];
			temp.y = v.x * row[4] + v.y * row[5] + v.z * row[6];
			temp.z = v.x * row[8] + v.y * row[9] + v.z * row[10];

			v.Set(temp);

		}

		void Set(T nrow[16]) { memset(row, nrow, sizeof(T)*16);	}
		void Reset() { memset(row, 0, sizeof(T)*16); }
		


};

how can i transform it into world space? Thanks
Advertisement
Transforming a space into another means to find the matrix that maps the local co-ordinate frame in the given space to the desired space. The frame itself isn't relocated or rotated or whatever, it just gets other co-ordinates that match it in the desired space.

In the local space a 3D cartesian co-ordinate frame is located at [0,0,0] and orientated with the basis vectors [1,0,0], [0,1,0], and [0,0,1] (what is usually called the local x, y, and z vectors). Say that the frame is located at [3,4,5] in world space. This means that the local origin [0,0,0] has world space co-ordinates [3,4,5]. So the transformation from local space to world space is a translation, so that
[0,0,0] -> [3,4,5]
and hence, as a matrix,
T(3,4,5)

The same principle works for the orientation, scaling, ... However, you have of course be aware of a suitable order of transformations, since matrix multiplication is non commutative.
Quote:Original post by Kasya
Hello, i have a matrix class i don't know how to transform it into world space.
This is unrelated to your question, but I just wanted to point out a couple of things in your code:

1. IIRC, symbols that begin with an underscore followed by a capital letter are reserved by the implementation in C++. In any case, may I ask what the purpose of the underscore and 'C' prefixes is? Why not just call the class Matrix?

2. Are you sure your operator=() is implemented correctly? Did you perhaps mean to use memcpy()? (It looks likes this may apply to a couple other functions as well.)

3. I might be missing something here, but I don't think it's typical to ignore the 'homogenous' row/column of the matrix (i.e. [0, 0, 0, 1]) in matrix multiplication functions. This will probably lead to wrong results on occasion.

4. Again, I might be missing something (it's early), but it looks like your * operator overwrites the matrix on which it's called. Are you sure that's the behavior you're after? (Note: it's typical to implement binary operators as non-member functions rather than member functions.)

There are a few other things that look a bit suspicious, but I'll leave it at that for now.
Quote:Original post by jyk
Quote:Original post by Kasya
Hello, i have a matrix class i don't know how to transform it into world space.
This is unrelated to your question, but I just wanted to point out a couple of things in your code:

1. IIRC, symbols that begin with an underscore followed by a capital letter are reserved by the implementation in C++. In any case, may I ask what the purpose of the underscore and 'C' prefixes is? Why not just call the class Matrix?

2. Are you sure your operator=() is implemented correctly? Did you perhaps mean to use memcpy()? (It looks likes this may apply to a couple other functions as well.)

3. I might be missing something here, but I don't think it's typical to ignore the 'homogenous' row/column of the matrix (i.e. [0, 0, 0, 1]) in matrix multiplication functions. This will probably lead to wrong results on occasion.

4. Again, I might be missing something (it's early), but it looks like your * operator overwrites the matrix on which it's called. Are you sure that's the behavior you're after? (Note: it's typical to implement binary operators as non-member functions rather than member functions.)

There are a few other things that look a bit suspicious, but I'll leave it at that for now.



i had some bugs here i fixed all of them.

------------

Quote:
Transforming a space into another means to find the matrix that maps the local co-ordinate frame in the given space to the desired space. The frame itself isn't relocated or rotated or whatever, it just gets other co-ordinates that match it in the desired space.

In the local space a 3D cartesian co-ordinate frame is located at [0,0,0] and orientated with the basis vectors [1,0,0], [0,1,0], and [0,0,1] (what is usually called the local x, y, and z vectors). Say that the frame is located at [3,4,5] in world space. This means that the local origin [0,0,0] has world space co-ordinates [3,4,5]. So the transformation from local space to world space is a translation, so that
[0,0,0] -> [3,4,5]
and hence, as a matrix,
T(3,4,5)

The same principle works for the orientation, scaling, ... However, you have of course be aware of a suitable order of transformations, since matrix multiplication is non commutative.


For object-world transformation i need to multiply matrix or what (like in OPENGL glPopMatrix(), glPushMatrix()). And For Projection Matrix, View Matrix what i need to do?
Thanks!
Quote:3. I might be missing something here, but I don't think it's typical to ignore the 'homogenous' row/column of the matrix (i.e. [0, 0, 0, 1]) in matrix multiplication functions. This will probably lead to wrong results on occasion.


you mean i need to use T row[4][4]
if im not wrong. i have a question. Why? Arent row[16] and row[4][4] equal?
Thanks!
He means "why aren't you including index 3, 7, 11 and 15 in your multiplication?" If you don't include those, you don't have a proper multiplication routine.

Also, you might want to transpose the representation of your matrix so that it matches that of both OpenGL and Direct3D -- This is also good for SSE optimization later.

throw table_exception("(? ???)? ? ???");

Quote:Original post by Kasya
For object-world transformation i need to multiply matrix or what (like in OPENGL glPopMatrix(), glPushMatrix()). And For Projection Matrix, View Matrix what i need to do?

glPush-/-PopMatrix are a functionality of a stack of matrices, and not of the matrix itself. They furthur don't perform a multiplication. But the matrix product itself is of course functionality you have to implement. You already have approaches to that, although suffering from the problems jyk has enumerated. Moreover, you have to bear in mind that the matrix product isn't commutative, so that routines that alter the instance itself should be available as a pre- and a post-multiply versions.

Since it is questionable to implement matrix operations itself into a matrix class, it is even more questionable to implement matrix building routine like fromTranslation, fromRotation, fromPerspective directly into the matrix class. I suggest you either implement external routines that convert from a transformation to a matrix, or at least to create classes especially for transformations and projections, resp.
I understand Translate Matrix. Its working. But i cannot use Rotation Matrix. It doesn't Rotate. What can i do?
Thanks!

This topic is closed to new replies.

Advertisement