naev 0.12.6
mat4.c
Go to the documentation of this file.
1/*
2 * See Licensing and Copyright notice in naev.h
3 */
10#include "naev.h"
12
13#include <stdio.h>
14
15#include "mat4.h"
16#include "nstring.h"
17
18void mat4_tostr( const mat4 *m, char *buf, size_t len )
19{
20 int l = 0;
21 for ( int i = 0; i < 4; i++ ) {
22 for ( int j = 0; j < 4; j++ )
23 l += scnprintf( &buf[l], len - l, "%7.g ", m->m[j][i] );
24 l += scnprintf( &buf[l], len - l, "\n" );
25 }
26}
27
28void mat4_print( const mat4 *m )
29{
30 for ( int i = 0; i < 4; i++ ) {
31 for ( int j = 0; j < 4; j++ )
32 printf( "%7.g ", m->m[j][i] );
33 printf( "\n" );
34 }
35}
36
46void mat4_mul( mat4 *out, const mat4 *m1, const mat4 *m2 )
47{
48 for ( int i = 0; i < 4; i++ ) {
49 for ( int j = 0; j < 4; j++ ) {
50 GLfloat v = 0.;
51 for ( int k = 0; k < 4; k++ )
52 v += m1->m[i][k] * m2->m[k][j];
53 out->m[i][j] = v;
54 }
55 }
56}
57
67void mat4_mul_vec( vec3 *out, const mat4 *m, const vec3 *v )
68{
69 for ( int i = 0; i < 3; i++ ) {
70 GLfloat a = m->m[3][i];
71 for ( int j = 0; j < 3; j++ )
72 a += m->m[j][i] * v->v[j];
73 out->v[i] = a;
74 }
75}
76
84void mat4_apply( mat4 *lhs, const mat4 *rhs )
85{
86 /* Process by rows. */
87 for ( int i = 0; i < 4; i++ ) {
88 float l0 = lhs->m[i][0];
89 float l1 = lhs->m[i][1];
90 float l2 = lhs->m[i][2];
91
92 float r0 = l0 * rhs->m[0][0] + l1 * rhs->m[1][0] + l2 * rhs->m[2][0];
93 float r1 = l0 * rhs->m[0][1] + l1 * rhs->m[1][1] + l2 * rhs->m[2][1];
94 float r2 = l0 * rhs->m[0][2] + l1 * rhs->m[1][2] + l2 * rhs->m[2][2];
95
96 lhs->m[i][0] = r0;
97 lhs->m[i][1] = r1;
98 lhs->m[i][2] = r2;
99 }
100 lhs->m[3][0] += rhs->m[3][0];
101 lhs->m[3][1] += rhs->m[3][1];
102 lhs->m[3][2] += rhs->m[3][2];
103}
104
113void mat4_scale( mat4 *m, double x, double y, double z )
114{
115 for ( int i = 0; i < 4; i++ ) {
116 m->m[0][i] *= x;
117 m->m[1][i] *= y;
118 m->m[2][i] *= z;
119 }
120}
121void mat4_scale_xy( mat4 *m, double x, double y )
122{
123 for ( int i = 0; i < 4; i++ ) {
124 m->m[0][i] *= x;
125 m->m[1][i] *= y;
126 }
127}
128
137void mat4_translate( mat4 *m, double x, double y, double z )
138{
139 for ( int i = 0; i < 4; i++ )
140 m->m[3][i] += m->m[0][i] * x + m->m[1][i] * y + m->m[2][i] * z;
141}
142void mat4_translate_x( mat4 *m, double x )
143{
144 for ( int i = 0; i < 4; i++ )
145 m->m[3][i] += m->m[0][i] * x;
146}
147void mat4_translate_xy( mat4 *m, double x, double y )
148{
149 for ( int i = 0; i < 4; i++ )
150 m->m[3][i] += m->m[0][i] * x + m->m[1][i] * y;
151}
152void mat4_translate_scale_xy( mat4 *m, double x, double y, double w, double h )
153{
154 for ( int i = 0; i < 4; i++ ) {
155 m->m[3][i] += m->m[0][i] * x + m->m[1][i] * y;
156 m->m[0][i] *= w;
157 m->m[1][i] *= h;
158 }
159}
160
167void mat4_rotate2d( mat4 *m, double angle )
168{
169 double c, s, x, y;
170
171 c = cos( angle );
172 s = sin( angle );
173 x = m->m[0][0];
174 y = m->m[1][0];
175 m->m[0][0] = c * x + s * y;
176 m->m[1][0] = -s * x + c * y;
177
178 x = m->m[0][1];
179 y = m->m[1][1];
180 m->m[0][1] = c * x + s * y;
181 m->m[1][1] = -s * x + c * y;
182}
183
191void mat4_rotate2dv( mat4 *m, double c, double s )
192{
193 double x, y;
194
195 x = m->m[0][0];
196 y = m->m[1][0];
197 m->m[0][0] = c * x + s * y;
198 m->m[1][0] = -s * x + c * y;
199
200 x = m->m[0][1];
201 y = m->m[1][1];
202 m->m[0][1] = c * x + s * y;
203 m->m[1][1] = -s * x + c * y;
204}
205
216void mat4_rotate( mat4 *m, double angle, double x, double y, double z )
217{
218 double norm, c, s;
219 mat4 R;
220
221 norm = sqrt( pow2( x ) + pow2( y ) + pow2( z ) );
222 c = cos( angle );
223 s = sin( angle );
224 x /= norm;
225 y /= norm;
226 z /= norm;
227 R.m[0][0] = x * x * ( 1. - c ) + c;
228 R.m[0][1] = y * x * ( 1. - c ) + z * s;
229 R.m[0][2] = x * z * ( 1. - c ) - y * s;
230 R.m[0][3] = 0.;
231 R.m[1][0] = x * y * ( 1. - c ) - z * s;
232 R.m[1][1] = y * y * ( 1. - c ) + c;
233 R.m[1][2] = y * z * ( 1. - c ) + x * s;
234 R.m[1][3] = 0.;
235 R.m[2][0] = x * z * ( 1. - c ) + y * s;
236 R.m[2][1] = y * z * ( 1. - c ) - x * s;
237 R.m[2][2] = z * z * ( 1. - c ) + c;
238 R.m[2][3] = 0.;
239 R.m[3][0] = 0.;
240 R.m[3][1] = 0.;
241 R.m[3][2] = 0.;
242 R.m[3][3] = 1.;
243
244 mat4_apply( m, &R );
245}
246
253void mat4_rotate_quaternion( mat4 *m, const quat *q )
254{
255 mat4 R;
256
257 GLfloat qx, qy, qz, qw;
258 qx = q->q[0];
259 qy = q->q[1];
260 qz = q->q[2];
261 qw = q->q[3];
262
263 R.ptr[0] = ( 1. - 2. * qy * qy - 2. * qz * qz );
264 R.ptr[1] = ( 2. * qx * qy + 2. * qz * qw );
265 R.ptr[2] = ( 2. * qx * qz - 2. * qy * qw );
266 R.ptr[3] = 0.;
267
268 R.ptr[4] = ( 2. * qx * qy - 2. * qz * qw );
269 R.ptr[5] = ( 1. - 2. * qx * qx - 2. * qz * qz );
270 R.ptr[6] = ( 2. * qy * qz + 2. * qx * qw );
271 R.ptr[7] = 0.;
272
273 R.ptr[8] = ( 2. * qx * qz + 2. * qy * qw );
274 R.ptr[9] = ( 2. * qy * qz - 2. * qx * qw );
275 R.ptr[10] = ( 1. - 2. * qx * qx - 2. * qy * qy );
276 R.ptr[11] = 0.;
277
278 R.ptr[12] = 0.;
279 R.ptr[13] = 0.;
280 R.ptr[14] = 0.;
281 R.ptr[15] = 1.;
282
283 mat4_apply( m, &R );
284}
285
290void mat4_trs( mat4 *m, const vec3 *t, const quat *r, const vec3 *s )
291{
292 GLfloat tx, ty, tz;
293 GLfloat qx, qy, qz, qw;
294 GLfloat sx, sy, sz;
295
296 tx = t->v[0];
297 ty = t->v[1];
298 tz = t->v[2];
299
300 qx = r->q[0];
301 qy = r->q[1];
302 qz = r->q[2];
303 qw = r->q[3];
304
305 sx = s->v[0];
306 sy = s->v[1];
307 sz = s->v[2];
308
309 m->ptr[0] = ( 1 - 2 * qy * qy - 2 * qz * qz ) * sx;
310 m->ptr[1] = ( 2 * qx * qy + 2 * qz * qw ) * sx;
311 m->ptr[2] = ( 2 * qx * qz - 2 * qy * qw ) * sx;
312 m->ptr[3] = 0.f;
313
314 m->ptr[4] = ( 2 * qx * qy - 2 * qz * qw ) * sy;
315 m->ptr[5] = ( 1 - 2 * qx * qx - 2 * qz * qz ) * sy;
316 m->ptr[6] = ( 2 * qy * qz + 2 * qx * qw ) * sy;
317 m->ptr[7] = 0.f;
318
319 m->ptr[8] = ( 2 * qx * qz + 2 * qy * qw ) * sz;
320 m->ptr[9] = ( 2 * qy * qz - 2 * qx * qw ) * sz;
321 m->ptr[10] = ( 1 - 2 * qx * qx - 2 * qy * qy ) * sz;
322 m->ptr[11] = 0.f;
323
324 m->ptr[12] = tx;
325 m->ptr[13] = ty;
326 m->ptr[14] = tz;
327 m->ptr[15] = 1.f;
328}
329
336{
337 const mat4 m = { .m = { { 1., 0., 0., 0. },
338 { 0., 1., 0., 0. },
339 { 0., 0., 1., 0. },
340 { 0., 0., 0., 1. } } };
341 return m;
342}
343
347mat4 mat4_ortho( double left, double right, double bottom, double top,
348 double nearVal, double farVal )
349{
350 mat4 mat = { { { { 0 } } } };
351 double tx, ty, tz;
352
353 /* https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glOrtho.xml
354 */
355 tx = -( right + left ) / ( right - left );
356 ty = -( top + bottom ) / ( top - bottom );
357 tz = -( farVal + nearVal ) / ( farVal - nearVal );
358
359 mat.m[0][0] = 2. / ( right - left );
360 mat.m[1][1] = 2. / ( top - bottom );
361 mat.m[2][2] = -2. / ( farVal - nearVal );
362 mat.m[3][3] = 1.;
363 mat.m[3][0] = tx;
364 mat.m[3][1] = ty;
365 mat.m[3][2] = tz;
366
367 return mat;
368}
369
382mat4 mat4_lookat( const vec3 *eye, const vec3 *center, const vec3 *up )
383{
384 vec3 forward, side, upc;
385 mat4 H;
386
387 vec3_sub( &forward, center, eye );
388 vec3_normalize( &forward ); /* Points towards the center from the eye. */
389
390 /* side = forward x up */
391 vec3_cross( &side, &forward, up );
392 vec3_normalize( &side ); /* Points to the side. */
393
394 /* upc = side x forward */
395 vec3_cross( &upc, &side, &forward );
396 /* No need to normalize since forward and side and unitary. */
397
398 /* First column. */
399 H.m[0][0] = side.v[0];
400 H.m[1][0] = side.v[1];
401 H.m[2][0] = side.v[2];
402 H.m[3][0] = 0.;
403 /* Second column. */
404 H.m[0][1] = upc.v[0];
405 H.m[1][1] = upc.v[1];
406 H.m[2][1] = upc.v[2];
407 H.m[3][1] = 0.;
408 /* Third column. */
409 H.m[0][2] = -forward.v[0];
410 H.m[1][2] = -forward.v[1];
411 H.m[2][2] = -forward.v[2];
412 H.m[3][2] = 0.;
413 /* Fourth column. */
414 H.m[0][3] = 0.; //-eye->v[0];
415 H.m[1][3] = 0.; //-eye->v[1];
416 H.m[2][3] = 0.; //-eye->v[2];
417 H.m[3][3] = 1.;
418
419 mat4_translate( &H, -eye->v[0], -eye->v[1], -eye->v[2] );
420
421 return H;
422}
423
433mat4 mat4_perspective( double fov, double aspect, double near, double far )
434{
435 mat4 H;
436 double c = 1. / tan( fov * 0.5 );
437 double d = far - near;
438
439 /* First column. */
440 H.m[0][0] = c / aspect;
441 H.m[0][1] = 0.;
442 H.m[0][2] = 0.;
443 H.m[0][3] = 0.;
444 /* Second column. */
445 H.m[1][0] = 0.;
446 H.m[1][1] = c;
447 H.m[1][2] = 0.;
448 H.m[1][3] = 0.;
449 /* Third column. */
450 H.m[2][0] = 0.;
451 H.m[2][1] = 0.;
452 H.m[2][2] = -( far + near ) / d;
453 H.m[2][3] = -1.;
454 /* Fourth column. */
455 H.m[3][0] = 0.;
456 H.m[3][1] = 0.;
457 H.m[3][2] = -2. * far * near / d;
458 H.m[3][3] = 0.;
459
460 return H;
461}
462
463void quat_normalize( quat *q )
464{
465 GLfloat d = sqrtf( pow2( q->q[0] ) + pow2( q->q[1] ) + pow2( q->q[2] ) +
466 pow2( q->q[3] ) );
467 for ( int i = 0; i < 4; i++ )
468 q->q[i] /= d;
469}
470
471void quat_slerp( GLfloat qm[4], const GLfloat qa[4], const GLfloat qb[4],
472 GLfloat t )
473{
474 // Calculate angle between them.
475 double cosHalfTheta =
476 qa[3] * qb[3] + qa[0] * qb[0] + qa[1] * qb[1] + qa[2] * qb[2];
477 // if qa=qb or qa=-qb then theta = 0 and we can return qa
478 if ( fabs( cosHalfTheta ) >= 1.0 ) {
479 qm[3] = qa[3];
480 qm[0] = qa[0];
481 qm[1] = qa[1];
482 qm[2] = qa[2];
483 return;
484 }
485 // Calculate temporary values.
486 double halfTheta = acos( cosHalfTheta );
487 double sinHalfTheta = sqrt( 1.0 - cosHalfTheta * cosHalfTheta );
488 // if theta = 180 degrees then result is not fully defined
489 // we could rotate around any axis normal to qa or qb
490 if ( fabs( sinHalfTheta ) < 0.001 ) { // fabs is floating point absolute
491 qm[3] = ( qa[3] * 0.5 + qb[3] * 0.5 );
492 qm[0] = ( qa[0] * 0.5 + qb[0] * 0.5 );
493 qm[1] = ( qa[1] * 0.5 + qb[1] * 0.5 );
494 qm[2] = ( qa[2] * 0.5 + qb[2] * 0.5 );
495 return;
496 }
497 double ratioA = sin( ( 1 - t ) * halfTheta ) / sinHalfTheta;
498 double ratioB = sin( t * halfTheta ) / sinHalfTheta;
499 // calculate Quaternion.
500 qm[3] = ( qa[3] * ratioA + qb[3] * ratioB );
501 qm[0] = ( qa[0] * ratioA + qb[0] * ratioB );
502 qm[1] = ( qa[1] * ratioA + qb[1] * ratioB );
503 qm[2] = ( qa[2] * ratioA + qb[2] * ratioB );
504}
void mat4_translate(mat4 *m, double x, double y, double z)
Translates a homogenous transformation matrix.
Definition mat4.c:137
void mat4_apply(mat4 *lhs, const mat4 *rhs)
Applies a transformation to another, storing the result in the left hand side.
Definition mat4.c:84
mat4 mat4_lookat(const vec3 *eye, const vec3 *center, const vec3 *up)
Creates a matrix with a transformation to look at a center point from an eye with an up vector.
Definition mat4.c:382
mat4 mat4_identity(void)
Creates an identity matrix.
Definition mat4.c:335
mat4 mat4_perspective(double fov, double aspect, double near, double far)
Creates a matrix with a perspective transformation.
Definition mat4.c:433
void mat4_rotate(mat4 *m, double angle, double x, double y, double z)
Multiplies the given matrix by a rotation. (Follows the right-hand rule.)
Definition mat4.c:216
void mat4_mul_vec(vec3 *out, const mat4 *m, const vec3 *v)
Multiplies a matrix with a vector (out = m * v);.
Definition mat4.c:67
void mat4_scale(mat4 *m, double x, double y, double z)
Scales a homogeneous transformation matrix.
Definition mat4.c:113
void mat4_mul(mat4 *out, const mat4 *m1, const mat4 *m2)
Multiplies two matrices (out = m1 * m2).
Definition mat4.c:46
void mat4_rotate_quaternion(mat4 *m, const quat *q)
Applies a quaternion transformation.
Definition mat4.c:253
void mat4_trs(mat4 *m, const vec3 *t, const quat *r, const vec3 *s)
Creates a homogeneous transform matrix from a translation, rotation, and scaling. Uses T*R*S order.
Definition mat4.c:290
mat4 mat4_ortho(double left, double right, double bottom, double top, double nearVal, double farVal)
Creates an orthographic projection matrix.
Definition mat4.c:347
void mat4_rotate2d(mat4 *m, double angle)
Rotates an angle, in radians, around the z axis.
Definition mat4.c:167
void mat4_rotate2dv(mat4 *m, double c, double s)
Rotates the +x axis to the given vector.
Definition mat4.c:191
Header file with generic functions and naev-specifics.
#define pow2(x)
Definition naev.h:53
int scnprintf(char *text, size_t maxlen, const char *fmt,...)
Like snprintf(), but returns the number of characters ACTUALLY "printed" into the buffer....
Definition nstring.c:102
static const double c[]
Definition rng.c:256
static const double d[]
Definition rng.c:263
Definition mat4.h:12
Definition mat4.h:20
Definition vec3.h:6