gKit2 light
mat.cpp
1 
2 #include <cassert>
3 #include <cstdio>
4 #include <cmath>
5 #include <algorithm>
6 
7 //#define _USE_MATH_DEFINES
8 #include "mat.h"
9 
10 
11 float radians( const float deg )
12 {
13  const float pi = 3.1415926535f;
14  return (pi / 180.f) * deg;
15 }
16 
17 float degrees( const float rad )
18 {
19  const float pi = 3.1415926535f;
20  return (180.f / pi) * rad;
21 }
22 
24  const float t00, const float t01, const float t02, const float t03,
25  const float t10, const float t11, const float t12, const float t13,
26  const float t20, const float t21, const float t22, const float t23,
27  const float t30, const float t31, const float t32, const float t33 )
28 {
29  m[0][0]= t00; m[0][1]= t01; m[0][2]= t02; m[0][3]= t03;
30  m[1][0]= t10; m[1][1]= t11; m[1][2]= t12; m[1][3]= t13;
31  m[2][0]= t20; m[2][1]= t21; m[2][2]= t22; m[2][3]= t23;
32  m[3][0]= t30; m[3][1]= t31; m[3][2]= t32; m[3][3]= t33;
33 }
34 
37 {
38  float x= p.x;
39  float y= p.y;
40  float z= p.z;
41 
42  float xt= m[0][0] * x + m[0][1] * y + m[0][2] * z + m[0][3]; // dot(vec4(m[0]), vec4(p, 1))
43  float yt= m[1][0] * x + m[1][1] * y + m[1][2] * z + m[1][3]; // dot(vec4(m[1]), vec4(p, 1))
44  float zt= m[2][0] * x + m[2][1] * y + m[2][2] * z + m[2][3]; // dot(vec4(m[2]), vec4(p, 1))
45  float wt= m[3][0] * x + m[3][1] * y + m[3][2] * z + m[3][3]; // dot(vec4(m[3]), vec4(p, 1))
46 
47  assert(wt != 0);
48  float w= 1.f / wt;
49  if(wt == 1.f)
50  return Point(xt, yt, zt);
51  else
52  return Point(xt*w, yt*w, zt*w);
53 }
54 
57 {
58  float x= v.x;
59  float y= v.y;
60  float z= v.z;
61 
62  float xt= m[0][0] * x + m[0][1] * y + m[0][2] * z; // dot(vec4(m[0]), vec4(v, 0))
63  float yt= m[1][0] * x + m[1][1] * y + m[1][2] * z; // dot(vec4(m[1]), vec4(v, 0))
64  float zt= m[2][0] * x + m[2][1] * y + m[2][2] * z; // dot(vec4(m[2]), vec4(v, 0))
65  // dot(vec4(m[3]), vec4(v, 0)) == dot(vec4(0, 0, 0, 1), vec4(v, 0)) == 0 par definition
66 
67  return Vector(xt, yt, zt);
68 }
69 
71 vec4 Transform::operator() ( const vec4& v ) const
72 {
73  float x= v.x;
74  float y= v.y;
75  float z= v.z;
76  float w= v.w;
77 
78  float xt= m[0][0] * x + m[0][1] * y + m[0][2] * z + m[0][3] * w; // dot(vec4(m[0]), v)
79  float yt= m[1][0] * x + m[1][1] * y + m[1][2] * z + m[1][3] * w; // dot(vec4(m[1]), v)
80  float zt= m[2][0] * x + m[2][1] * y + m[2][2] * z + m[2][3] * w; // dot(vec4(m[2]), v)
81  float wt= m[3][0] * x + m[3][1] * y + m[3][2] * z + m[3][3] * w; // dot(vec4(m[3]), v)
82 
83  return vec4(xt, yt, zt, wt);
84 }
85 
88 {
89  return Transform(
90  m[0][0], m[1][0], m[2][0], m[3][0],
91  m[0][1], m[1][1], m[2][1], m[3][1],
92  m[0][2], m[1][2], m[2][2], m[3][2],
93  m[0][3], m[1][3], m[2][3], m[3][3]);
94 }
95 
98 {
99  return inverse().transpose();
100 }
101 
102 
104 {
105  return Transform();
106 }
107 
109 {
110  return m.transpose();
111 }
112 
114 {
115  return m.inverse();
116 }
117 
119 {
120  return m.normal();
121 }
122 
123 Transform Scale( const float x, const float y, const float z )
124 {
125  return Transform(
126  x, 0, 0, 0,
127  0, y, 0, 0,
128  0, 0, z, 0,
129  0, 0, 0, 1);
130 }
131 
133 {
134  return Transform(
135  1, 0, 0, v.x,
136  0, 1, 0, v.y,
137  0, 0, 1, v.z,
138  0, 0, 0, 1);
139 }
140 
141 Transform Translation( const float x, const float y, const float z )
142 {
143  return Translation( Vector(x, y, z) );
144 }
145 
146 Transform RotationX( const float a )
147 {
148  float sin_t= sinf(radians(a));
149  float cos_t= cosf(radians(a));
150 
151  return Transform(
152  1, 0, 0, 0,
153  0, cos_t, -sin_t, 0,
154  0, sin_t, cos_t, 0,
155  0, 0, 0, 1 );
156 }
157 
158 Transform RotationY( const float a )
159 {
160  float sin_t= sinf(radians(a));
161  float cos_t= cosf(radians(a));
162 
163  return Transform(
164  cos_t, 0, sin_t, 0,
165  0, 1, 0, 0,
166  -sin_t, 0, cos_t, 0,
167  0, 0, 0, 1 );
168 }
169 
170 Transform RotationZ( const float a )
171 {
172  float sin_t= sinf(radians(a));
173  float cos_t= cosf(radians(a));
174 
175  return Transform(
176  cos_t, -sin_t, 0, 0,
177  sin_t, cos_t, 0, 0,
178  0, 0, 1, 0,
179  0, 0, 0, 1 );
180 }
181 
182 Transform Rotation( const Vector& axis, const float angle )
183 {
184  Vector a= normalize(axis);
185  float s= sinf(radians(angle));
186  float c= cosf(radians(angle));
187 
188  return Transform(
189  a.x * a.x + (1 - a.x * a.x ) * c,
190  a.x * a.y * (1 - c ) - a.z * s,
191  a.x * a.z * (1 - c ) + a.y * s,
192  0,
193 
194  a.x * a.y * (1 - c ) + a.z * s,
195  a.y * a.y + (1 - a.y * a.y ) * c,
196  a.y * a.z * (1 - c ) - a.x * s,
197  0,
198 
199  a.x * a.z * (1 - c ) - a.y * s,
200  a.y * a.z * (1 - c ) + a.x * s,
201  a.z * a.z + (1 - a.z * a.z ) * c,
202  0,
203 
204  0, 0, 0, 1);
205 }
206 
207 
208 Transform Perspective( const float fov, const float aspect, const float znear, const float zfar )
209 {
210  // perspective, openGL version
211  float itan= 1 / tanf(radians(fov) * 0.5f);
212  float id= 1 / (znear - zfar);
213 
214  return Transform(
215  itan/aspect, 0, 0, 0,
216  0, itan, 0, 0,
217  0, 0, (zfar+znear)*id, 2.f*zfar*znear*id,
218  0, 0, -1, 0);
219 }
220 
221 Transform Viewport( const float width, const float height )
222 {
223  float w= width / 2.f;
224  float h= height / 2.f;
225 
226  return Transform(
227  w, 0, 0, w,
228  0, h, 0, h,
229  0, 0, .5f, .5f,
230  0, 0, 0, 1);
231 }
232 
233 Transform Lookat( const Point& from, const Point& to, const Vector& up )
234 {
235  Vector dir= normalize( Vector(from, to) );
236  Vector right= normalize( cross(dir, normalize(up)) );
237  Vector newUp= normalize( cross(right, dir) );
238 
239  Transform m(
240  right.x, newUp.x, -dir.x, from.x,
241  right.y, newUp.y, -dir.y, from.y,
242  right.z, newUp.z, -dir.z, from.z,
243  0, 0, 0, 1);
244 
245  return m.inverse();
246 }
247 
249 {
250  Transform m;
251  for(int i = 0; i < 4; i++)
252  for(int j = 0; j < 4; j++)
253  m.m[i][j]= a.m[i][0] * b.m[0][j] + a.m[i][1] * b.m[1][j] + a.m[i][2] * b.m[2][j] + a.m[i][3] * b.m[3][j];
254 
255  return m;
256 }
257 
259 {
260  return compose_transform(a, b);
261 }
262 
264 {
265  Transform minv= *this;
266 
267  int indxc[4], indxr[4];
268  int ipiv[4] = { 0, 0, 0, 0 };
269 
270  for (int i = 0; i < 4; i++) {
271  int irow = -1, icol = -1;
272  float big = 0.f;
273 
274  // Choose pivot
275  for (int j = 0; j < 4; j++) {
276  if (ipiv[j] != 1) {
277  for (int k = 0; k < 4; k++) {
278  if (ipiv[k] == 0) {
279  if (fabsf(minv.m[j][k]) >= big) {
280  big = std::abs(minv.m[j][k]);
281  irow = j;
282  icol = k;
283  }
284  }
285  else if (ipiv[k] > 1)
286  printf("singular matrix in make_inverse()\n");
287  }
288  }
289  }
290 
291  assert(irow >= 0 && irow < 4);
292  assert(icol >= 0 && icol < 4);
293 
294  ++ipiv[icol];
295  // Swap rows _irow_ and _icol_ for pivot
296  if (irow != icol) {
297  for (int k = 0; k < 4; ++k)
298  std::swap(minv.m[irow][k], minv.m[icol][k]);
299  }
300 
301  indxr[i] = irow;
302  indxc[i] = icol;
303  if (minv.m[icol][icol] == 0.)
304  printf("singular matrix in make_inverse()\n");
305 
306  // Set $m[icol][icol]$ to one by scaling row _icol_ appropriately
307  float pivinv = 1.f / minv.m[icol][icol];
308  minv.m[icol][icol] = 1.f;
309  for (int j = 0; j < 4; j++)
310  minv.m[icol][j] *= pivinv;
311 
312  // Subtract this row from others to zero out their columns
313  for (int j = 0; j < 4; j++) {
314  if (j != icol) {
315  float save = minv.m[j][icol];
316  minv.m[j][icol] = 0;
317  for (int k = 0; k < 4; k++)
318  minv.m[j][k] -= minv.m[icol][k]*save;
319  }
320  }
321  }
322 
323  // Swap columns to reflect permutation
324  for (int j = 3; j >= 0; j--) {
325  if (indxr[j] != indxc[j]) {
326  for (int k = 0; k < 4; k++)
327  std::swap(minv.m[k][indxr[j]], minv.m[k][indxc[j]]);
328  }
329  }
330 
331  return minv;
332 }
float degrees(const float rad)
conversion en degres.
Definition: mat.cpp:17
Transform(const float t00=1.f, const float t01=0.f, const float t02=0.f, const float t03=0.f, const float t10=0.f, const float t11=1.f, const float t12=0.f, const float t13=0.f, const float t20=0.f, const float t21=0.f, const float t22=1.f, const float t23=0.f, const float t30=0.f, const float t31=0.f, const float t32=0.f, const float t33=1.f)
constructeur.
Definition: mat.cpp:23
Vector normalize(const Vector &v)
renvoie un vecteur unitaire / longueur == 1.
Definition: vec.cpp:79
Transform inverse() const
renvoie l'inverse de la matrice.
Definition: mat.cpp:263
Transform Transpose(const Transform &m)
renvoie la transposee de la matrice.
Definition: mat.cpp:108
Transform normal() const
renvoie la transformation a appliquer aux normales d'un objet transforme par la matrice m...
Definition: mat.cpp:97
Transform operator*(const Transform &a, const Transform &b)
renvoie la composition des transformations a et b, t = a * b.
Definition: mat.cpp:258
Point operator()(const Point &p) const
renvoie le point transforme.
Definition: mat.cpp:36
Transform Identity()
construit la transformation identite.
Definition: mat.cpp:103
Transform Viewport(const float width, const float height)
renvoie la matrice representant une transformation viewport.
Definition: mat.cpp:221
vecteur generique 4d, ou 3d homogene, utilitaire.
Definition: vec.h:121
float radians(const float deg)
conversion en radians.
Definition: mat.cpp:11
Transform Normal(const Transform &m)
renvoie la transformation a appliquer aux normales d'un objet transforme par la matrice m...
Definition: mat.cpp:118
Transform Inverse(const Transform &m)
renvoie l'inverse de la matrice.
Definition: mat.cpp:113
representation d'un vecteur 3d.
Definition: vec.h:42
Transform transpose() const
renvoie la transposee de la matrice.
Definition: mat.cpp:87
Transform RotationX(const float a)
renvoie la matrice representation une rotation de angle degree autour de l'axe X. ...
Definition: mat.cpp:146
Transform Lookat(const Point &from, const Point &to, const Vector &up)
renvoie la matrice representant le placement et l'orientation d'une camera pour observer le point to...
Definition: mat.cpp:233
Transform Rotation(const Vector &axis, const float angle)
renvoie la matrice representation une rotation de angle degree autour de l'axe axis.
Definition: mat.cpp:182
Transform compose_transform(const Transform &a, const Transform &b)
renvoie la composition des transformations a et b, t= a * b.
Definition: mat.cpp:248
Transform Scale(const float x, const float y, const float z)
renvoie la matrice representant une mise a l'echelle / etirement.
Definition: mat.cpp:123
Transform Translation(const Vector &v)
renvoie la matrice representant une translation par un vecteur.
Definition: mat.cpp:132
Transform RotationZ(const float a)
renvoie la matrice representation une rotation de angle degree autour de l'axe Z. ...
Definition: mat.cpp:170
void printf(Text &text, const int px, const int py, const char *format,...)
affiche un texte a la position x, y. meme utilisation que printf().
Definition: text.cpp:140
Transform Perspective(const float fov, const float aspect, const float znear, const float zfar)
renvoie la matrice representant une transformation projection perspective.
Definition: mat.cpp:208
representation d'une transformation, une matrice 4x4, organisee par ligne / row major.
Definition: mat.h:20
representation d'un point 3d.
Definition: vec.h:19
Vector cross(const Vector &u, const Vector &v)
renvoie le produit vectoriel de 2 vecteurs.
Definition: vec.cpp:85
Transform RotationY(const float a)
renvoie la matrice representation une rotation de a degree autour de l'axe Y.
Definition: mat.cpp:158