Blame view

rts/rtsMatrix4x4.h 5.55 KB
ebb721c7   David Mayerich   new repository fo...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
  #include <iostream>
  #include <iomanip>
  #include <stdio.h>
  #include <string.h>
  
  #include "rtsVector3d.h"
  #include "rtsPoint3d.h"
  
  using namespace std;
  #ifndef RTSMATRIX4X4_H
  #define RTSMATRIX4X4_H
  
  #define RTS_PI	3.14159
  
  ///This class represents a 4x4 matrix, which is often used to represent affine transformations on 3D points and vectors.
  
  ///
  ///This class is designed to work with point3d<T> and vector3d<T>.  Data is stored internally in a column-major form which is compatible with OpenGL.
  ///
  
  template <class T>
  class matrix4x4
  {
  	/*stored as:
  	| 0  4  8  12 |
      |             |
      | 1  5  9  13 |
      |             |
      | 2  6  10 14 |
      |             |
      | 3  7  11 15 |
  	*/
  public:
  	T m_matrix[16];
  
  	//constructors
  	matrix4x4();								///<Constructor initializes all values to zero.
  	matrix4x4(T c0r0, T c0r1, T c0r2, T c0r3, 
  			  T c1r0, T c1r1, T c1r2, T c1r3, 
  			  T c2r0, T c2r1, T c2r2, T c2r3, 
  			  T c3r0, T c3r1, T c3r2, T c3r3);	///<Constructor initializes all values to those specified as parameters. c=column, r=row
  	
  	//overloaded operators
  	T& operator()(int row, int column){return m_matrix[column*4 + row];}	///<Returns the value at the specified position.  This function can be used as both m(0, 0) = x and x = m(0, 0)
  	vector3D<T> operator*(vector3D<T> rhs);		///<Overloaded arithmetic operator.  This function multiplies a vector by the current matrix, returning the transformed vector3D.
  	point3D<T> operator*(point3D<T> rhs);		///<Overloaded arithmetic operator.  This function multiplies a point by the current matrix, returning the transformed point3D.
  	matrix4x4<T> operator*(matrix4x4<T> rhs);	///<Overloaded arithmetic operator.  Computes the result of a matrix x matrix multiplication.
  
  	//methods
  	void SetIdentity();							///<Sets the current matrix to the identity matrix.
  	void SetRotation(T angle, T x, T y, T z);	///<Creates a matrix that represents a rotation of "angle" degrees around the axis given by (x, y, z).
  	void SetTranslation(T x, T y, T z);			///<Creates a matrix that represents a translation specified by the vector (x, y, z).
  	void SetScale(T x, T y, T z);				///<Creates a matrix that represents a scale along each axis given by the scalars x, y, and z.
  
  	//output
  	void Print(int width = 7, int precision = 2);///<Sends the current matrix to the standard output.
  
  };
  
  
  template <class T>
  matrix4x4<T>::matrix4x4()
  {
  	memset(m_matrix, 0, sizeof(T)*16);
  }
  
  template <class T>
  matrix4x4<T>::matrix4x4(T c0r0, T c0r1, T c0r2, T c0r3, 
  						T c1r0, T c1r1, T c1r2, T c1r3, 
  						T c2r0, T c2r1, T c2r2, T c2r3, 
  						T c3r0, T c3r1, T c3r2, T c3r3)
  {
  
  	T new_matrix[16] = {c0r0,c0r1,c0r2,c0r3,c1r0,c1r1,c1r2,c1r3,c2r0,c2r1,c2r2,c2r3,c3r0,c3r1,c3r2,c3r3};
  	memcpy(m_matrix, new_matrix, 16*sizeof(T));
  }
  
  template <class T>
  vector3D<T> matrix4x4<T>::operator*(vector3D<T> rhs)
  {
  	vector3D<T> result;
  	result.x = m_matrix[0] * rhs.x + m_matrix[4] * rhs.y + m_matrix[8] * rhs.z;
  	result.y = m_matrix[1] * rhs.x + m_matrix[5] * rhs.y + m_matrix[9] * rhs.z;
  	result.z = m_matrix[2] * rhs.x + m_matrix[6] * rhs.y + m_matrix[10] * rhs.z;
  	return result;
  }
  
  template <class T>
  point3D<T> matrix4x4<T>::operator *(point3D<T> rhs)
  {
  	point3D<T> result;
  	result.x = m_matrix[0] * rhs.x + m_matrix[4] * rhs.y + m_matrix[8] * rhs.z + m_matrix[12];
  	result.y = m_matrix[1] * rhs.x + m_matrix[5] * rhs.y + m_matrix[9] * rhs.z + m_matrix[13];
  	result.z = m_matrix[2] * rhs.x + m_matrix[6] * rhs.y + m_matrix[10] * rhs.z + m_matrix[14];
  	T w = m_matrix[3] + m_matrix[7] + m_matrix[11] + m_matrix[15];
  	result.x/=w;
  	result.y/=w;
  	result.z/=w;
  	return result;
  }
  
  template <class T>
  matrix4x4<T> matrix4x4<T>::operator *(matrix4x4<T> rhs)
  {
  	matrix4x4<T> result;
  	int i,j,r;
  	for(i = 0; i<4; i++)
  		for(j = 0; j<4; j++)
  			for(r=0; r<4; r++)
  				result(i, j) += (*this)(i, r) * rhs(r, j);
  
  	return result;
  }
  
  
  
  
  template <class T>
  void matrix4x4<T>::SetIdentity()
  {
  	T new_matrix[16] = {1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1};
  	memcpy(m_matrix, new_matrix, 16*sizeof(T));
  }
  
  template <class T>
  void matrix4x4<T>::SetTranslation(T x, T y, T z)
  {
  	T new_matrix[16] = {1,0,0,0,0,1,0,0,0,0,1,0,x,y,z,1};
  	memcpy(m_matrix, new_matrix, 16*sizeof(T));
  }
  
  template <class T>
  void matrix4x4<T>::SetScale(T x, T y, T z)
  {
  	T new_matrix[16] = {x,0,0,0,0,y,0,0,0,0,z,0,0,0,0,1};
  	memcpy(m_matrix, new_matrix, 16*sizeof(T));
  }
  
  template <class T>
  void matrix4x4<T>::SetRotation(T angle, T x, T y, T z)
  {
  	//create the axis of rotation
  	vector3D<T> axis(x, y, z);
  	T length = axis.Length();	//make sure that it is normalized
  	if(length != 1)
  		axis.Normalize();
  
  	T c = cos(angle*RTS_PI/180.0);			//compute the sine and cosine of angle
  	T s = sin(angle*RTS_PI/180.0);
  
  	//create the matrix
  	m_matrix[0] = x*x*(1-c) + c;
  	m_matrix[1] = y*x*(1-c) + z*s;
  	m_matrix[2] = x*z*(1-c) - y*s;
  	m_matrix[4] = x*y*(1-c) - z*s;
  	m_matrix[5] = y*y*(1-c) + c;
  	m_matrix[6] = y*z*(1-c) + x*s;
  	m_matrix[8] = x*z*(1-c) + y*s;
  	m_matrix[9] = y*z*(1-c) - x*s;
  	m_matrix[10]= z*z*(1-c) + c;
  	m_matrix[15]= 1;
  }
  
  
  template <class T>
  void matrix4x4<T>::Print(int width, int precision)
  {
  	cout<<setiosflags(ios::fixed);
  	cout<<setprecision(precision);
  	cout<<setw(width)<<m_matrix[0]
  		<<setw(width)<<m_matrix[4]
  		<<setw(width)<<m_matrix[8]
  		<<setw(width)<<m_matrix[12]<<endl
  		<<setw(width)<<m_matrix[1]
  		<<setw(width)<<m_matrix[5]
  		<<setw(width)<<m_matrix[9]
  		<<setw(width)<<m_matrix[13]<<endl
  		<<setw(width)<<m_matrix[2]
  		<<setw(width)<<m_matrix[6]
  		<<setw(width)<<m_matrix[10]
  		<<setw(width)<<m_matrix[14]<<endl
  		<<setw(width)<<m_matrix[3]
  		<<setw(width)<<m_matrix[7]
  		<<setw(width)<<m_matrix[11]
  		<<setw(width)<<m_matrix[15]<<endl;
  }
  
  	
  	
  
  
  
  
  
  
  #endif