gKit2 light
mat.cpp
1 
2 #include <cassert>
3 #include <cstdio>
4 #include <cmath>
5 #include <algorithm>
6 
7 #include "mat.h"
8 
9 
10 float radians( const float deg )
11 {
12  return ((float) M_PI / 180.f) * deg;
13 }
14 
15 float degrees( const float rad )
16 {
17  return (180.f / (float) M_PI) * rad;
18 }
19 
21  const float t00, const float t01, const float t02, const float t03,
22  const float t10, const float t11, const float t12, const float t13,
23  const float t20, const float t21, const float t22, const float t23,
24  const float t30, const float t31, const float t32, const float t33 )
25 {
26  m[0][0]= t00; m[0][1]= t01; m[0][2]= t02; m[0][3]= t03;
27  m[1][0]= t10; m[1][1]= t11; m[1][2]= t12; m[1][3]= t13;
28  m[2][0]= t20; m[2][1]= t21; m[2][2]= t22; m[2][3]= t23;
29  m[3][0]= t30; m[3][1]= t31; m[3][2]= t32; m[3][3]= t33;
30 }
31 
32 Transform& Transform::column( const unsigned id, const float t0, const float t1, const float t2, const float t3 )
33 {
34  m[0][id]= t0;
35  m[1][id]= t1;
36  m[2][id]= t2;
37  m[3][id]= t3;
38  return *this;
39 }
40 
41 vec4 Transform::column( const unsigned id ) const
42 {
43  assert(id < 4);
44  return vec4(m[0][id], m[1][id], m[2][id], m[3][id]);
45 }
46 
47 vec4 Transform::column( const unsigned id )
48 {
49  assert(id < 4);
50  return vec4(m[0][id], m[1][id], m[2][id], m[3][id]);
51 }
52 
53 
54 Transform& Transform::row( const unsigned id, const float t0, const float t1, const float t2, const float t3 )
55 {
56  m[id][0]= t0;
57  m[id][1]= t1;
58  m[id][2]= t2;
59  m[id][3]= t3;
60  return *this;
61 }
62 
63 vec4 Transform::row( const unsigned id ) const
64 {
65  assert(id < 4);
66  return vec4(m[id][0], m[id][1], m[id][2], m[id][3]);
67 }
68 
69 vec4 Transform::row( const unsigned id )
70 {
71  assert(id < 4);
72  return vec4(m[id][0], m[id][1], m[id][2], m[id][3]);
73 }
74 
75 
76 Transform& Transform::column_major( const float matrix[16] )
77 {
78  for(int i= 0; i < 4; i++)
79  column(i, matrix[4*i], matrix[4*i+1], matrix[4*i+2], matrix[4*i+3]);
80  return *this;
81 }
82 
83 Transform& Transform::row_major( const float matrix[16] )
84 {
85  for(int i= 0; i < 4; i++)
86  row(i, matrix[4*i], matrix[4*i+1], matrix[4*i+2], matrix[4*i+3]);
87  return *this;
88 }
89 
90 Transform::Transform( const Vector& x, const Vector& y, const Vector& z, const Vector& w )
91 {
92  m[0][0] = x.x; m[0][1] = y.x; m[0][2] = z.x; m[0][3] = w.x;
93  m[1][0] = x.y; m[1][1] = y.y; m[1][2] = z.y; m[1][3] = w.y;
94  m[2][0] = x.z; m[2][1] = y.z; m[2][2] = z.z; m[2][3] = w.z;
95  m[3][0] = 0; m[3][1] = 0; m[3][2] = 0; m[3][3] = 1;
96 }
97 
98 Transform::Transform( const vec4& x, const vec4& y, const vec4& z, const vec4& w )
99 {
100  m[0][0] = x.x; m[0][1] = y.x; m[0][2] = z.x; m[0][3] = w.x;
101  m[1][0] = x.y; m[1][1] = y.y; m[1][2] = z.y; m[1][3] = w.y;
102  m[2][0] = x.z; m[2][1] = y.z; m[2][2] = z.z; m[2][3] = w.z;
103  m[3][0] = x.w; m[3][1] = y.w; m[3][2] = z.w; m[3][3] = w.w;
104 }
105 
106 Vector Transform::operator[] ( const unsigned c ) const
107 {
108  assert(c < 4);
109  return Vector(m[0][c], m[1][c], m[2][c]);
110 }
111 
112 
115 {
116  float x= p.x;
117  float y= p.y;
118  float z= p.z;
119 
120  float xt= m[0][0] * x + m[0][1] * y + m[0][2] * z + m[0][3]; // dot(vec4(m[0]), vec4(p, 1))
121  float yt= m[1][0] * x + m[1][1] * y + m[1][2] * z + m[1][3]; // dot(vec4(m[1]), vec4(p, 1))
122  float zt= m[2][0] * x + m[2][1] * y + m[2][2] * z + m[2][3]; // dot(vec4(m[2]), vec4(p, 1))
123  float wt= m[3][0] * x + m[3][1] * y + m[3][2] * z + m[3][3]; // dot(vec4(m[3]), vec4(p, 1))
124 
125  assert(wt != 0);
126  float w= 1.f / wt;
127  if(wt == 1.f)
128  return Point(xt, yt, zt);
129  else
130  return Point(xt*w, yt*w, zt*w);
131 }
132 
135 {
136  float x= v.x;
137  float y= v.y;
138  float z= v.z;
139 
140  float xt= m[0][0] * x + m[0][1] * y + m[0][2] * z; // dot(vec4(m[0]), vec4(v, 0))
141  float yt= m[1][0] * x + m[1][1] * y + m[1][2] * z; // dot(vec4(m[1]), vec4(v, 0))
142  float zt= m[2][0] * x + m[2][1] * y + m[2][2] * z; // dot(vec4(m[2]), vec4(v, 0))
143  // dot(vec4(m[3]), vec4(v, 0)) == dot(vec4(0, 0, 0, 1), vec4(v, 0)) == 0 par definition
144 
145  return Vector(xt, yt, zt);
146 }
147 
150 {
151  float x= v.x;
152  float y= v.y;
153  float z= v.z;
154  float w= v.w;
155 
156  float xt= m[0][0] * x + m[0][1] * y + m[0][2] * z + m[0][3] * w; // dot(vec4(m[0]), v)
157  float yt= m[1][0] * x + m[1][1] * y + m[1][2] * z + m[1][3] * w; // dot(vec4(m[1]), v)
158  float zt= m[2][0] * x + m[2][1] * y + m[2][2] * z + m[2][3] * w; // dot(vec4(m[2]), v)
159  float wt= m[3][0] * x + m[3][1] * y + m[3][2] * z + m[3][3] * w; // dot(vec4(m[3]), v)
160 
161  return vec4(xt, yt, zt, wt);
162 }
163 
166 {
167  return Transform(
168  m[0][0], m[1][0], m[2][0], m[3][0],
169  m[0][1], m[1][1], m[2][1], m[3][1],
170  m[0][2], m[1][2], m[2][2], m[3][2],
171  m[0][3], m[1][3], m[2][3], m[3][3]);
172 }
173 
174 
176 {
177  return compose_transform(*this, b);
178 }
179 
182 {
183  return inverse().transpose();
184 }
185 
186 
188 {
189  return Transform();
190 }
191 
193 {
194  return m.transpose();
195 }
196 
198 {
199  return m.inverse();
200 }
201 
203 {
204  return m.normal();
205 }
206 
207 Transform Scale( const float x, const float y, const float z )
208 {
209  return Transform(
210  x, 0, 0, 0,
211  0, y, 0, 0,
212  0, 0, z, 0,
213  0, 0, 0, 1);
214 }
215 
217 {
218  return Transform(
219  1, 0, 0, v.x,
220  0, 1, 0, v.y,
221  0, 0, 1, v.z,
222  0, 0, 0, 1);
223 }
224 
225 Transform Translation( const float x, const float y, const float z )
226 {
227  return Translation( Vector(x, y, z) );
228 }
229 
230 Transform RotationX( const float a )
231 {
232  float sin_t= sinf(radians(a));
233  float cos_t= cosf(radians(a));
234 
235  return Transform(
236  1, 0, 0, 0,
237  0, cos_t, -sin_t, 0,
238  0, sin_t, cos_t, 0,
239  0, 0, 0, 1 );
240 }
241 
242 Transform RotationY( const float a )
243 {
244  float sin_t= sinf(radians(a));
245  float cos_t= cosf(radians(a));
246 
247  return Transform(
248  cos_t, 0, sin_t, 0,
249  0, 1, 0, 0,
250  -sin_t, 0, cos_t, 0,
251  0, 0, 0, 1 );
252 }
253 
254 Transform RotationZ( const float a )
255 {
256  float sin_t= sinf(radians(a));
257  float cos_t= cosf(radians(a));
258 
259  return Transform(
260  cos_t, -sin_t, 0, 0,
261  sin_t, cos_t, 0, 0,
262  0, 0, 1, 0,
263  0, 0, 0, 1 );
264 }
265 
266 Transform Rotation( const Vector& axis, const float angle )
267 {
268  Vector a= normalize(axis);
269  float s= sinf(radians(angle));
270  float c= cosf(radians(angle));
271 
272  return Transform(
273  a.x * a.x + (1 - a.x * a.x ) * c,
274  a.x * a.y * (1 - c ) - a.z * s,
275  a.x * a.z * (1 - c ) + a.y * s,
276  0,
277 
278  a.x * a.y * (1 - c ) + a.z * s,
279  a.y * a.y + (1 - a.y * a.y ) * c,
280  a.y * a.z * (1 - c ) - a.x * s,
281  0,
282 
283  a.x * a.z * (1 - c ) - a.y * s,
284  a.y * a.z * (1 - c ) + a.x * s,
285  a.z * a.z + (1 - a.z * a.z ) * c,
286  0,
287 
288  0, 0, 0, 1);
289 }
290 
291 
292 Transform Rotation( const Vector& u, const Vector& v )
293 {
294  Vector a= normalize(u);
295  Vector b= normalize(v);
296  Vector w= cross(a, b); // rotation autour de w, un vecteur perpendiculaire a u et v
297  float s= length(w); // sin theta
298  float c= dot(a, b); // cos theta
299 
300  // si u et v sont colineaires, pas d'axe de rotation, renvoyer +1 ou -1
301  if(s < float(0.00001))
303  return Scale(std::copysign(c, 1));
304 
305  // normalise l'axe de rotation
306  w= w / s;
307 
308  // meme matrice de rotation qu'au dessus , cf Rotation(axis, angle), l'axe est le vecteur w, s et c sont le sinus et le cosinus de l'angle
309  return Transform(
310  w.x * w.x + (1 - w.x * w.x ) * c,
311  w.x * w.y * (1 - c ) - w.z * s,
312  w.x * w.z * (1 - c ) + w.y * s,
313  0,
314 
315  w.x * w.y * (1 - c ) + w.z * s,
316  w.y * w.y + (1 - w.y * w.y ) * c,
317  w.y * w.z * (1 - c ) - w.x * s,
318  0,
319 
320  w.x * w.z * (1 - c ) - w.y * s,
321  w.y * w.z * (1 - c ) + w.x * s,
322  w.z * w.z + (1 - w.z * w.z ) * c,
323  0,
324 
325  0, 0, 0, 1);
326 }
327 
328 
329 Transform Perspective( const float fov, const float aspect, const float znear, const float zfar )
330 {
331  // perspective, openGL version
332  float itan= 1 / tanf(radians(fov) * 0.5f);
333  float id= 1 / (znear - zfar);
334 
335  return Transform(
336  itan/aspect, 0, 0, 0,
337  0, itan, 0, 0,
338  0, 0, (zfar+znear)*id, 2.f*zfar*znear*id,
339  0, 0, -1, 0);
340 }
341 
342 
343 Transform Ortho( const float left, const float right, const float bottom, const float top, const float znear, const float zfar )
344 {
345  float tx= - (right + left) / (right - left);
346  float ty= - (top + bottom) / (top - bottom);
347  float tz= - (zfar + znear) / (zfar - znear);
348 
349  return Transform(
350  2.f / (right - left), 0, 0, tx,
351  0, 2.f / (top - bottom), 0, ty,
352  0, 0, -2.f / (zfar - znear), tz,
353  0, 0, 0, 1);
354 }
355 
356 
357 Transform Viewport( const float width, const float height )
358 {
359  float w= width / 2.f;
360  float h= height / 2.f;
361 
362  return Transform(
363  w, 0, 0, w,
364  0, h, 0, h,
365  0, 0, .5f, .5f,
366  0, 0, 0, 1);
367 }
368 
369 Transform Lookat( const Point& from, const Point& to, const Vector& up )
370 {
371  Vector dir= normalize( Vector(from, to) );
372  Vector right= normalize( cross(dir, normalize(up)) );
373  Vector newUp= normalize( cross(right, dir) );
374 
375  Transform m(
376  right.x, newUp.x, -dir.x, from.x,
377  right.y, newUp.y, -dir.y, from.y,
378  right.z, newUp.z, -dir.z, from.z,
379  0, 0, 0, 1);
380 
381  return m.inverse();
382 }
383 
385 {
386  Transform m;
387  for(int i = 0; i < 4; i++)
388  for(int j = 0; j < 4; j++)
389  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];
390 
391  return m;
392 }
393 
395 {
396  return compose_transform(a, b);
397 }
398 
400 {
401  Transform minv= *this;
402 
403  int indxc[4], indxr[4];
404  int ipiv[4] = { 0, 0, 0, 0 };
405 
406  for (int i = 0; i < 4; i++) {
407  int irow = -1, icol = -1;
408  float big = 0.f;
409 
410  // Choose pivot
411  for (int j = 0; j < 4; j++) {
412  if (ipiv[j] != 1) {
413  for (int k = 0; k < 4; k++) {
414  if (ipiv[k] == 0) {
415  if (fabsf(minv.m[j][k]) >= big) {
416  big = std::abs(minv.m[j][k]);
417  irow = j;
418  icol = k;
419  }
420  }
421  else if (ipiv[k] > 1)
422  printf("singular matrix in Transform::inverse()\n");
423  }
424  }
425  }
426 
427  assert(irow >= 0 && irow < 4);
428  assert(icol >= 0 && icol < 4);
429 
430  ++ipiv[icol];
431  // Swap rows _irow_ and _icol_ for pivot
432  if (irow != icol) {
433  for (int k = 0; k < 4; ++k)
434  std::swap(minv.m[irow][k], minv.m[icol][k]);
435  }
436 
437  indxr[i] = irow;
438  indxc[i] = icol;
439  if (minv.m[icol][icol] == 0.)
440  printf("singular matrix in Transform::inverse()\n");
441 
442  // Set $m[icol][icol]$ to one by scaling row _icol_ appropriately
443  float pivinv = 1.f / minv.m[icol][icol];
444  minv.m[icol][icol] = 1.f;
445  for (int j = 0; j < 4; j++)
446  minv.m[icol][j] *= pivinv;
447 
448  // Subtract this row from others to zero out their columns
449  for (int j = 0; j < 4; j++) {
450  if (j != icol) {
451  float save = minv.m[j][icol];
452  minv.m[j][icol] = 0;
453  for (int k = 0; k < 4; k++)
454  minv.m[j][k] -= minv.m[icol][k]*save;
455  }
456  }
457  }
458 
459  // Swap columns to reflect permutation
460  for (int j = 3; j >= 0; j--) {
461  if (indxr[j] != indxc[j]) {
462  for (int k = 0; k < 4; k++)
463  std::swap(minv.m[k][indxr[j]], minv.m[k][indxc[j]]);
464  }
465  }
466 
467  return minv;
468 }
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 Inverse(const Transform &m)
renvoie l'inverse de la matrice.
Definition: mat.cpp:197
Transform Transpose(const Transform &m)
renvoie la transposee de la matrice.
Definition: mat.cpp:192
Transform Normal(const Transform &m)
renvoie la transformation a appliquer aux normales d'un objet transforme par la matrice m.
Definition: mat.cpp:202
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:266
Transform Viewport(const float width, const float height)
renvoie la matrice representant une transformation viewport.
Definition: mat.cpp:357
float degrees(const float rad)
conversion en degres.
Definition: mat.cpp:15
Transform Identity()
construit la transformation identite.
Definition: mat.cpp:187
Transform RotationX(const float a)
renvoie la matrice representation une rotation de angle degree autour de l'axe X.
Definition: mat.cpp:230
Transform compose_transform(const Transform &a, const Transform &b)
renvoie la composition des transformations a et b, t= a * b.
Definition: mat.cpp:384
Transform RotationY(const float a)
renvoie la matrice representation une rotation de a degree autour de l'axe Y.
Definition: mat.cpp:242
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:329
float dot(const Vector &u, const Vector &v)
renvoie le produit scalaire de 2 vecteurs.
Definition: vec.cpp:137
Transform Ortho(const float left, const float right, const float bottom, const float top, const float znear, const float zfar)
renvoie la matrice representant une transformation orthographique, passage d'un cube []x[]x[] vers [-...
Definition: mat.cpp:343
Transform operator*(const Transform &a, const Transform &b)
renvoie la composition des transformations a et b, t = a * b.
Definition: mat.cpp:394
float radians(const float deg)
conversion en radians.
Definition: mat.cpp:10
Vector normalize(const Vector &v)
renvoie un vecteur unitaire / longueur == 1.
Definition: vec.cpp:123
Transform Translation(const Vector &v)
renvoie la matrice representant une translation par un vecteur.
Definition: mat.cpp:216
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:369
Transform RotationZ(const float a)
renvoie la matrice representation une rotation de angle degree autour de l'axe Z.
Definition: mat.cpp:254
float length(const Vector &v)
renvoie la longueur d'un vecteur.
Definition: vec.cpp:142
Vector cross(const Vector &u, const Vector &v)
renvoie le produit vectoriel de 2 vecteurs.
Definition: vec.cpp:129
Transform Scale(const float x, const float y, const float z)
renvoie la matrice representant une mise a l'echelle / etirement.
Definition: mat.cpp:207
representation d'un point 3d.
Definition: vec.h:21
representation d'une transformation, une matrice 4x4, organisee par ligne / row major.
Definition: mat.h:21
Transform & column_major(const float matrix[16])
initialise la matrice avec 16 floats organises par colonne.
Definition: mat.cpp:76
Transform & row_major(const float matrix[16])
initialise la matrice avec 16 floats organises par ligne.
Definition: mat.cpp:83
Transform(const float t00=1, const float t01=0, const float t02=0, const float t03=0, const float t10=0, const float t11=1, const float t12=0, const float t13=0, const float t20=0, const float t21=0, const float t22=1, const float t23=0, const float t30=0, const float t31=0, const float t32=0, const float t33=1)
constructeur.
Definition: mat.cpp:20
Vector operator[](const unsigned c) const
renvoie le Vector colonne c de la matrice
Definition: mat.cpp:106
Transform & column(const unsigned id, const float t0, const float t1, const float t2, const float t3)
initialise une colonne de la matrice a partir de 4 floats.
Definition: mat.cpp:32
Transform normal() const
renvoie la transformation a appliquer aux normales d'un objet transforme par la matrice m.
Definition: mat.cpp:181
Transform inverse() const
renvoie l'inverse de la matrice.
Definition: mat.cpp:399
Transform & row(const unsigned id, const float t0, const float t1, const float t2, const float t3)
initialise une ligne de la matrice.
Definition: mat.cpp:54
Point operator()(const Point &p) const
renvoie le point transforme.
Definition: mat.cpp:114
Transform transpose() const
renvoie la transposee de la matrice.
Definition: mat.cpp:165
representation d'un vecteur 3d.
Definition: vec.h:59
vecteur generique 4d, ou 3d homogene, utilitaire.
Definition: vec.h:168