snow-math 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/ext/extconf.rb +17 -0
- data/ext/snow-math/mat4.c +739 -0
- data/ext/snow-math/maths.c +2 -0
- data/ext/snow-math/maths_local.h +257 -0
- data/ext/snow-math/quat.c +187 -0
- data/ext/snow-math/snow-math.c +2117 -0
- data/ext/snow-math/vec3.c +144 -0
- data/ext/snow-math/vec4.c +145 -0
- data/lib/snow-math.rb +14 -0
- data/lib/snow-math/inspect.rb +20 -0
- data/lib/snow-math/line.rb +0 -0
- data/lib/snow-math/mat3.rb +0 -0
- data/lib/snow-math/mat4.rb +80 -0
- data/lib/snow-math/plane.rb +0 -0
- data/lib/snow-math/ptr.rb +25 -0
- data/lib/snow-math/quat.rb +114 -0
- data/lib/snow-math/swizzle.rb +57 -0
- data/lib/snow-math/to_a.rb +51 -0
- data/lib/snow-math/vec2.rb +0 -0
- data/lib/snow-math/vec3.rb +111 -0
- data/lib/snow-math/vec4.rb +113 -0
- metadata +71 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 19a3f42ccb51ce6b8f3ce302da01828ccf1b9456
|
4
|
+
data.tar.gz: cd4fea9cddf77d8e9d3b3656eb428101aff96786
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 937dc344b4c8c9925b014faf86fd6edccd93e010dbbf344c83e2c302f310baa1c97a7aa73f02f34ee97497a75a80d78e4932064083c685d124861169d9ef003a
|
7
|
+
data.tar.gz: d3113bcfacd41fe382c6f89c3fbd4e320344d60b7eb26c64bceab5d551986677217f9a284457098789377afef9817bc62ffa787d793c58179ad4afd89ba74453
|
data/ext/extconf.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
#! /usr/bin/env ruby -w
|
2
|
+
# This file is part of ruby-snowmath.
|
3
|
+
# Copyright (c) 2013 Noel Raymond Cower. All rights reserved.
|
4
|
+
# See COPYING for license details.
|
5
|
+
|
6
|
+
require 'mkmf'
|
7
|
+
|
8
|
+
if ARGV.include?("--use-float") || ARGV.include?("-F")
|
9
|
+
$CFLAGS += " -DUSE_FLOAT"
|
10
|
+
puts "Using float as base type"
|
11
|
+
else
|
12
|
+
puts "Using double as base type"
|
13
|
+
end
|
14
|
+
|
15
|
+
have_library('m', 'cos')
|
16
|
+
|
17
|
+
create_makefile('snow-math/bindings', 'snow-math/')
|
@@ -0,0 +1,739 @@
|
|
1
|
+
/*
|
2
|
+
Transformation matrix
|
3
|
+
Written by Noel Cower
|
4
|
+
|
5
|
+
See COPYING for license information
|
6
|
+
*/
|
7
|
+
|
8
|
+
#define __SNOW__MAT4_C__
|
9
|
+
|
10
|
+
#include "maths_local.h"
|
11
|
+
|
12
|
+
#if defined(__cplusplus)
|
13
|
+
extern "C"
|
14
|
+
{
|
15
|
+
#endif /* __cplusplus */
|
16
|
+
|
17
|
+
/* reference:
|
18
|
+
x y z w
|
19
|
+
0 1 2 3
|
20
|
+
4 5 6 7
|
21
|
+
8 9 10 11
|
22
|
+
12 13 14 15
|
23
|
+
*/
|
24
|
+
|
25
|
+
const mat4_t g_mat4_identity = {
|
26
|
+
1.0, 0.0, 0.0, 0.0,
|
27
|
+
0.0, 1.0, 0.0, 0.0,
|
28
|
+
0.0, 0.0, 1.0, 0.0,
|
29
|
+
0.0, 0.0, 0.0, 1.0
|
30
|
+
};
|
31
|
+
|
32
|
+
static inline s_float_t mat4_cofactor(const mat4_t m, int r0, int r1, int r2, int c0, int c1, int c2);
|
33
|
+
|
34
|
+
void mat4_identity(mat4_t out)
|
35
|
+
{
|
36
|
+
out[0] = out[5] = out[10] = out[15] = 1.0;
|
37
|
+
out[1] = out[2] = out[3] =
|
38
|
+
out[4] = out[6] = out[7] =
|
39
|
+
out[8] = out[9] = out[11] =
|
40
|
+
out[12] = out[13] = out[14] = 0.0;
|
41
|
+
}
|
42
|
+
|
43
|
+
void mat4_copy(const mat4_t in, mat4_t out)
|
44
|
+
{
|
45
|
+
if (in != out) {
|
46
|
+
int index = 0;
|
47
|
+
for (; index < 16; ++index) out[index] = in[index];
|
48
|
+
}
|
49
|
+
}
|
50
|
+
|
51
|
+
void mat4_set(
|
52
|
+
s_float_t m00, s_float_t m01, s_float_t m02, s_float_t m03,
|
53
|
+
s_float_t m04, s_float_t m05, s_float_t m06, s_float_t m07,
|
54
|
+
s_float_t m08, s_float_t m09, s_float_t m10, s_float_t m11,
|
55
|
+
s_float_t m12, s_float_t m13, s_float_t m14, s_float_t m15,
|
56
|
+
mat4_t out)
|
57
|
+
{
|
58
|
+
out[0 ] = m00;
|
59
|
+
out[1 ] = m01;
|
60
|
+
out[2 ] = m02;
|
61
|
+
out[3 ] = m03;
|
62
|
+
out[4 ] = m04;
|
63
|
+
out[5 ] = m05;
|
64
|
+
out[6 ] = m06;
|
65
|
+
out[7 ] = m07;
|
66
|
+
out[8 ] = m08;
|
67
|
+
out[9 ] = m09;
|
68
|
+
out[10] = m10;
|
69
|
+
out[11] = m11;
|
70
|
+
out[12] = m12;
|
71
|
+
out[13] = m13;
|
72
|
+
out[14] = m14;
|
73
|
+
out[15] = m15;
|
74
|
+
}
|
75
|
+
|
76
|
+
void mat4_set_axes3(const vec3_t x, const vec3_t y, const vec3_t z, const vec3_t w, mat4_t out)
|
77
|
+
{
|
78
|
+
out[0] = x[0];
|
79
|
+
out[4] = x[1];
|
80
|
+
out[8] = x[2];
|
81
|
+
|
82
|
+
out[1] = y[0];
|
83
|
+
out[5] = y[1];
|
84
|
+
out[9] = y[2];
|
85
|
+
|
86
|
+
out[2] = z[0];
|
87
|
+
out[6] = z[1];
|
88
|
+
out[10] = z[2];
|
89
|
+
|
90
|
+
out[3] = w[0];
|
91
|
+
out[7] = w[1];
|
92
|
+
out[11] = w[2];
|
93
|
+
|
94
|
+
out[12] = out[13] = out[14] = 0.0;
|
95
|
+
out[15] = 1.0;
|
96
|
+
}
|
97
|
+
|
98
|
+
void mat4_get_axes3(const mat4_t m, vec3_t x, vec3_t y, vec3_t z, vec3_t w)
|
99
|
+
{
|
100
|
+
if (x) {
|
101
|
+
x[0] = m[0];
|
102
|
+
x[1] = m[4];
|
103
|
+
x[2] = m[8];
|
104
|
+
}
|
105
|
+
|
106
|
+
if (y) {
|
107
|
+
y[0] = m[1];
|
108
|
+
y[1] = m[5];
|
109
|
+
y[2] = m[9];
|
110
|
+
}
|
111
|
+
|
112
|
+
if (z) {
|
113
|
+
z[0] = m[2];
|
114
|
+
z[1] = m[6];
|
115
|
+
z[2] = m[10];
|
116
|
+
}
|
117
|
+
|
118
|
+
if (w) {
|
119
|
+
w[0] = m[3];
|
120
|
+
w[1] = m[7];
|
121
|
+
w[2] = m[11];
|
122
|
+
}
|
123
|
+
}
|
124
|
+
|
125
|
+
void mat4_set_axes4(const vec4_t x, const vec4_t y, const vec4_t z, const vec4_t w, mat4_t out)
|
126
|
+
{
|
127
|
+
out[0] = x[0];
|
128
|
+
out[4] = x[1];
|
129
|
+
out[8] = x[2];
|
130
|
+
out[12] = x[3];
|
131
|
+
|
132
|
+
out[1] = y[0];
|
133
|
+
out[5] = y[1];
|
134
|
+
out[9] = y[2];
|
135
|
+
out[13] = y[3];
|
136
|
+
|
137
|
+
out[2] = z[0];
|
138
|
+
out[6] = z[1];
|
139
|
+
out[10] = z[2];
|
140
|
+
out[14] = z[3];
|
141
|
+
|
142
|
+
out[3] = w[0];
|
143
|
+
out[7] = w[1];
|
144
|
+
out[11] = w[2];
|
145
|
+
out[15] = w[3];
|
146
|
+
}
|
147
|
+
|
148
|
+
void mat4_get_axes4(const mat4_t m, vec4_t x, vec4_t y, vec4_t z, vec4_t w)
|
149
|
+
{
|
150
|
+
if (x) {
|
151
|
+
x[0] = m[0];
|
152
|
+
x[1] = m[4];
|
153
|
+
x[2] = m[8];
|
154
|
+
x[3] = m[12];
|
155
|
+
}
|
156
|
+
|
157
|
+
if (y) {
|
158
|
+
y[0] = m[1];
|
159
|
+
y[1] = m[5];
|
160
|
+
y[2] = m[9];
|
161
|
+
y[3] = m[13];
|
162
|
+
}
|
163
|
+
|
164
|
+
if (z) {
|
165
|
+
z[0] = m[2];
|
166
|
+
z[1] = m[6];
|
167
|
+
z[2] = m[10];
|
168
|
+
z[3] = m[14];
|
169
|
+
}
|
170
|
+
|
171
|
+
if (w) {
|
172
|
+
w[0] = m[3];
|
173
|
+
w[1] = m[7];
|
174
|
+
w[2] = m[11];
|
175
|
+
w[3] = m[15];
|
176
|
+
}
|
177
|
+
}
|
178
|
+
|
179
|
+
|
180
|
+
/*! Builds a rotation matrix with the given angle and axis. */
|
181
|
+
void mat4_rotation(s_float_t angle, s_float_t x, s_float_t y, s_float_t z, mat4_t out)
|
182
|
+
{
|
183
|
+
const s_float_t angle_rad = angle * S_DEG2RAD;
|
184
|
+
const s_float_t c = s_cos(angle_rad);
|
185
|
+
const s_float_t s = s_sin(angle_rad);
|
186
|
+
const s_float_t ic = 1.0 - c;
|
187
|
+
const s_float_t xy = x * y * ic;
|
188
|
+
const s_float_t yz = y * z * ic;
|
189
|
+
const s_float_t xz = x * z * ic;
|
190
|
+
const s_float_t xs = s * x;
|
191
|
+
const s_float_t ys = s * y;
|
192
|
+
const s_float_t zs = s * z;
|
193
|
+
|
194
|
+
out[0] = ((x * x) * ic) + c;
|
195
|
+
out[1] = xy + zs;
|
196
|
+
out[2] = xz - ys;
|
197
|
+
out[4] = xy - zs;
|
198
|
+
out[5] = ((y * y) * ic) + c;
|
199
|
+
out[6] = yz + xs;
|
200
|
+
out[8] = xz + ys;
|
201
|
+
out[9] = yz - xs;
|
202
|
+
out[10] = ((z * z) * ic) + c;
|
203
|
+
out[3] = out[7] = out[11] =
|
204
|
+
out[12] = out[13] = out[14] = 0.0;
|
205
|
+
out[15] = 1.0;
|
206
|
+
}
|
207
|
+
|
208
|
+
void mat4_frustum(s_float_t left, s_float_t right, s_float_t bottom, s_float_t top, s_float_t near, s_float_t far, mat4_t out)
|
209
|
+
{
|
210
|
+
const s_float_t xdelta = right - left;
|
211
|
+
const s_float_t ydelta = top - bottom;
|
212
|
+
const s_float_t zdelta = far - near;
|
213
|
+
const s_float_t neardouble = 2.0 * near;
|
214
|
+
|
215
|
+
out[0] = neardouble / xdelta;
|
216
|
+
out[2] = (right + left) / xdelta;
|
217
|
+
out[5] = neardouble / ydelta;
|
218
|
+
out[6] = (top + bottom) / ydelta;
|
219
|
+
out[10] = -((far + near) / zdelta);
|
220
|
+
out[11] = -1.0;
|
221
|
+
out[14] = -((neardouble * far) / zdelta);
|
222
|
+
out[1] = out[3] = out[4] =
|
223
|
+
out[7] = out[8] = out[9] =
|
224
|
+
out[12] = out[13] = out[15] = 0.0;
|
225
|
+
}
|
226
|
+
|
227
|
+
void mat4_orthographic(s_float_t left, s_float_t right, s_float_t bottom, s_float_t top, s_float_t near, s_float_t far, mat4_t out)
|
228
|
+
{
|
229
|
+
const s_float_t xdelta = right - left;
|
230
|
+
const s_float_t ydelta = top - bottom;
|
231
|
+
const s_float_t zdelta = far - near;
|
232
|
+
|
233
|
+
out[0] = 2.0 / xdelta;
|
234
|
+
out[5] = 2.0 / ydelta;
|
235
|
+
out[10] = -2.0 / zdelta;
|
236
|
+
out[12] = -((right + left) / xdelta);
|
237
|
+
out[13] = -((top + bottom) / ydelta);
|
238
|
+
out[14] = -((far + near) / zdelta);
|
239
|
+
out[15] = 1.0;
|
240
|
+
out[1] = out[2] = out[3] =
|
241
|
+
out[4] = out[6] = out[7] =
|
242
|
+
out[8] = out[9] = out[11] = 0.0;
|
243
|
+
}
|
244
|
+
|
245
|
+
void mat4_perspective(s_float_t fov_y, s_float_t aspect, s_float_t near, s_float_t far, mat4_t out)
|
246
|
+
{
|
247
|
+
const s_float_t r = s_tan(fov_y * 0.5 * S_DEG2RAD);
|
248
|
+
const s_float_t left = -r * aspect;
|
249
|
+
const s_float_t right = r * aspect;
|
250
|
+
const s_float_t bottom = -r;
|
251
|
+
const s_float_t top = r;
|
252
|
+
const s_float_t two_near = 2 * near;
|
253
|
+
const s_float_t zdelta = 1.0 / (near - far);
|
254
|
+
|
255
|
+
out[0] = two_near * (right - left);
|
256
|
+
out[5] = two_near / (top - bottom);
|
257
|
+
out[10] = (far + near) * zdelta;
|
258
|
+
out[11] = -1.0;
|
259
|
+
out[14] = (two_near * far) * zdelta;
|
260
|
+
out[1] = out[2] = out[3] =
|
261
|
+
out[4] = out[6] = out[7] =
|
262
|
+
out[8] = out[9] = out[12] =
|
263
|
+
out[13] = out[15] = 0.0;
|
264
|
+
}
|
265
|
+
|
266
|
+
void mat4_look_at(const vec3_t eye, const vec3_t center, const vec3_t up, mat4_t out)
|
267
|
+
{
|
268
|
+
mat4_t r;
|
269
|
+
vec3_t facing_norm, up_norm, s;
|
270
|
+
/* facing_norm */
|
271
|
+
vec3_subtract(center, eye, facing_norm);
|
272
|
+
vec3_normalize(facing_norm, facing_norm);
|
273
|
+
/* up_norm */
|
274
|
+
vec3_normalize(up, up_norm);
|
275
|
+
/* s */
|
276
|
+
vec3_cross_product(facing_norm, up_norm, s);
|
277
|
+
vec3_normalize(s, s);
|
278
|
+
/* up_norm rejigged */
|
279
|
+
vec3_cross_product(s, facing_norm, up_norm);
|
280
|
+
up_norm[1] = -up_norm[1];
|
281
|
+
facing_norm[0] = -facing_norm[0];
|
282
|
+
facing_norm[1] = -facing_norm[1];
|
283
|
+
facing_norm[2] = -facing_norm[2];
|
284
|
+
|
285
|
+
mat4_set_axes3(s, up_norm, facing_norm, g_vec3_zero, r);
|
286
|
+
mat4_translate(-eye[0], -eye[1], -eye[2], r, out);
|
287
|
+
}
|
288
|
+
|
289
|
+
void mat4_from_quat(const quat_t quat, mat4_t out)
|
290
|
+
{
|
291
|
+
s_float_t tx, ty, tz, xx, xy, xz, yy, yz, zz, wx, wy, wz;
|
292
|
+
|
293
|
+
tx = 2.0 * quat[0];
|
294
|
+
ty = 2.0 * quat[1];
|
295
|
+
tz = 2.0 * quat[2];
|
296
|
+
|
297
|
+
xx = tx * quat[0];
|
298
|
+
xy = tx * quat[1];
|
299
|
+
xz = tx * quat[2];
|
300
|
+
|
301
|
+
yy = ty * quat[1];
|
302
|
+
yz = tz * quat[1];
|
303
|
+
|
304
|
+
zz = tz * quat[3];
|
305
|
+
|
306
|
+
wx = tx * quat[3];
|
307
|
+
wy = ty * quat[3];
|
308
|
+
wz = tz * quat[3];
|
309
|
+
|
310
|
+
out[0 ] = 1.0 - (yy + zz);
|
311
|
+
out[1 ] = xy - wz;
|
312
|
+
out[2 ] = xz + wy;
|
313
|
+
out[4 ] = xy + wz;
|
314
|
+
out[5 ] = 1.0 - (xx + zz);
|
315
|
+
out[6 ] = yz - wx;
|
316
|
+
out[8 ] = xz - wy;
|
317
|
+
out[9 ] = yz + wx;
|
318
|
+
out[10] = 1.0 - (xx + yy);
|
319
|
+
|
320
|
+
out[7 ] = 0.0;
|
321
|
+
out[3 ] = 0.0;
|
322
|
+
out[11] = 0.0;
|
323
|
+
out[12] = 0.0;
|
324
|
+
out[13] = 0.0;
|
325
|
+
out[14] = 0.0;
|
326
|
+
|
327
|
+
out[15] = 1.0;
|
328
|
+
}
|
329
|
+
|
330
|
+
void mat4_get_row4(const mat4_t in, int row, vec4_t out)
|
331
|
+
{
|
332
|
+
if (0 <= row && row < 4) {
|
333
|
+
const s_float_t *rowvec = in + (row * 4);
|
334
|
+
out[0] = rowvec[0];
|
335
|
+
out[1] = rowvec[1];
|
336
|
+
out[2] = rowvec[2];
|
337
|
+
out[3] = rowvec[3];
|
338
|
+
}
|
339
|
+
}
|
340
|
+
|
341
|
+
void mat4_get_row3(const mat4_t in, int row, vec3_t out)
|
342
|
+
{
|
343
|
+
if (0 <= row && row < 4) {
|
344
|
+
const s_float_t *rowvec = in + (row * 4);
|
345
|
+
out[0] = rowvec[0];
|
346
|
+
out[1] = rowvec[1];
|
347
|
+
out[2] = rowvec[2];
|
348
|
+
}
|
349
|
+
}
|
350
|
+
|
351
|
+
void mat4_get_column4(const mat4_t in, int column, vec4_t out)
|
352
|
+
{
|
353
|
+
if (0 <= column && column < 4) {
|
354
|
+
const s_float_t *colvec = in + column;
|
355
|
+
out[0] = colvec[0];
|
356
|
+
out[1] = colvec[4];
|
357
|
+
out[2] = colvec[8];
|
358
|
+
out[3] = colvec[12];
|
359
|
+
}
|
360
|
+
}
|
361
|
+
|
362
|
+
void mat4_get_column3(const mat4_t in, int column, vec3_t out)
|
363
|
+
{
|
364
|
+
if (0 <= column && column < 4) {
|
365
|
+
const s_float_t *colvec = in + column;
|
366
|
+
out[0] = colvec[0];
|
367
|
+
out[1] = colvec[4];
|
368
|
+
out[2] = colvec[8];
|
369
|
+
}
|
370
|
+
}
|
371
|
+
|
372
|
+
void mat4_set_row4(int row, const vec4_t value, mat4_t inout)
|
373
|
+
{
|
374
|
+
if (0 <= row && row < 4) {
|
375
|
+
s_float_t *rowvec = inout + (row * 4);
|
376
|
+
rowvec[0] = value[0];
|
377
|
+
rowvec[1] = value[1];
|
378
|
+
rowvec[2] = value[2];
|
379
|
+
rowvec[3] = value[3];
|
380
|
+
}
|
381
|
+
}
|
382
|
+
|
383
|
+
void mat4_set_row3(int row, const vec3_t value, mat4_t inout)
|
384
|
+
{
|
385
|
+
if (0 <= row && row < 4) {
|
386
|
+
s_float_t *rowvec = inout + (row * 4);
|
387
|
+
rowvec[0] = value[0];
|
388
|
+
rowvec[1] = value[1];
|
389
|
+
rowvec[2] = value[2];
|
390
|
+
}
|
391
|
+
}
|
392
|
+
|
393
|
+
void mat4_set_column4(int column, const vec4_t value, mat4_t inout)
|
394
|
+
{
|
395
|
+
if (0 <= column && column < 4) {
|
396
|
+
s_float_t *colvec = inout + column;
|
397
|
+
colvec[0] = value[0];
|
398
|
+
colvec[4] = value[1];
|
399
|
+
colvec[8] = value[2];
|
400
|
+
colvec[12] = value[3];
|
401
|
+
}
|
402
|
+
}
|
403
|
+
|
404
|
+
void mat4_set_column3(int column, const vec3_t value, mat4_t inout)
|
405
|
+
{
|
406
|
+
if (0 <= column && column < 4) {
|
407
|
+
s_float_t *colvec = inout + column;
|
408
|
+
colvec[0] = value[0];
|
409
|
+
colvec[4] = value[1];
|
410
|
+
colvec[8] = value[2];
|
411
|
+
}
|
412
|
+
}
|
413
|
+
|
414
|
+
int mat4_equals(const mat4_t left, const mat4_t right)
|
415
|
+
{
|
416
|
+
/*
|
417
|
+
compare the XYZ components of all axes first, since they are the most likely
|
418
|
+
to vary between checks
|
419
|
+
*/
|
420
|
+
return (
|
421
|
+
s_fabs(left[0] - right[0]) < S_FLOAT_EPSILON &&
|
422
|
+
s_fabs(left[1] - right[1]) < S_FLOAT_EPSILON &&
|
423
|
+
s_fabs(left[2] - right[2]) < S_FLOAT_EPSILON &&
|
424
|
+
|
425
|
+
s_fabs(left[4] - right[4]) < S_FLOAT_EPSILON &&
|
426
|
+
s_fabs(left[5] - right[5]) < S_FLOAT_EPSILON &&
|
427
|
+
s_fabs(left[6] - right[6]) < S_FLOAT_EPSILON &&
|
428
|
+
|
429
|
+
s_fabs(left[8] - right[8]) < S_FLOAT_EPSILON &&
|
430
|
+
s_fabs(left[9] - right[9]) < S_FLOAT_EPSILON &&
|
431
|
+
s_fabs(left[10] - right[10]) < S_FLOAT_EPSILON &&
|
432
|
+
|
433
|
+
s_fabs(left[12] - right[12]) < S_FLOAT_EPSILON &&
|
434
|
+
s_fabs(left[13] - right[13]) < S_FLOAT_EPSILON &&
|
435
|
+
s_fabs(left[14] - right[14]) < S_FLOAT_EPSILON &&
|
436
|
+
|
437
|
+
s_fabs(left[3] - right[3]) < S_FLOAT_EPSILON &&
|
438
|
+
s_fabs(left[7] - right[7]) < S_FLOAT_EPSILON &&
|
439
|
+
s_fabs(left[11] - right[11]) < S_FLOAT_EPSILON &&
|
440
|
+
s_fabs(left[15] - right[15]) < S_FLOAT_EPSILON
|
441
|
+
);
|
442
|
+
}
|
443
|
+
|
444
|
+
void mat4_transpose(const mat4_t in, mat4_t out)
|
445
|
+
{
|
446
|
+
s_float_t temp;
|
447
|
+
#define swap_elem(X, Y) temp = in[(X)]; out[(X)] = in[(Y)]; out[(Y)] = temp
|
448
|
+
swap_elem(1, 4);
|
449
|
+
swap_elem(8, 2);
|
450
|
+
swap_elem(9, 6);
|
451
|
+
swap_elem(12, 3);
|
452
|
+
swap_elem(13, 7);
|
453
|
+
swap_elem(14, 11);
|
454
|
+
out[0] = in[0];
|
455
|
+
out[5] = in[5];
|
456
|
+
out[10] = in[10];
|
457
|
+
out[15] = in[15];
|
458
|
+
}
|
459
|
+
|
460
|
+
void mat4_inverse_orthogonal(const mat4_t in, mat4_t out)
|
461
|
+
{
|
462
|
+
const s_float_t m12 = in[12];
|
463
|
+
const s_float_t m13 = in[13];
|
464
|
+
const s_float_t m14 = in[14];
|
465
|
+
mat4_t temp = {
|
466
|
+
in[0],
|
467
|
+
in[4],
|
468
|
+
in[8],
|
469
|
+
0.0,
|
470
|
+
in[1],
|
471
|
+
in[5],
|
472
|
+
in[9],
|
473
|
+
0.0,
|
474
|
+
in[2],
|
475
|
+
in[6],
|
476
|
+
in[10],
|
477
|
+
0.0
|
478
|
+
};
|
479
|
+
|
480
|
+
temp[12] = -((m12 * temp[0]) + (m13 * temp[4]) + (m14 * temp[8]));
|
481
|
+
temp[13] = -((m12 * temp[1]) + (m13 * temp[5]) + (m14 * temp[9]));
|
482
|
+
temp[14] = -((m12 * temp[2]) + (m13 * temp[6]) + (m14 * temp[10]));
|
483
|
+
temp[15] = 1.0;
|
484
|
+
|
485
|
+
mat4_copy(temp, out);
|
486
|
+
}
|
487
|
+
|
488
|
+
/*!
|
489
|
+
* Writes the inverse affine of the input matrix to the output matrix.
|
490
|
+
* \returns Non-zero if an inverse affine matrix can be created, otherwise
|
491
|
+
* zero if not. If zero, the output matrix is the identity matrix.
|
492
|
+
*/
|
493
|
+
int mat4_inverse_affine(const mat4_t in, mat4_t out)
|
494
|
+
{
|
495
|
+
mat4_t temp;
|
496
|
+
s_float_t det;
|
497
|
+
s_float_t m12, m13, m14;
|
498
|
+
|
499
|
+
temp[0 ] = (in[5 ] * in[10]) - (in[6 ] * in[9 ]);
|
500
|
+
temp[1 ] = (in[2 ] * in[9 ]) - (in[1 ] * in[10]);
|
501
|
+
temp[2 ] = (in[1 ] * in[6 ]) - (in[2 ] * in[5 ]);
|
502
|
+
|
503
|
+
temp[4 ] = (in[6 ] * in[ 8]) - (in[4 ] * in[10]);
|
504
|
+
temp[5 ] = (in[0 ] * in[10]) - (in[2 ] * in[ 8]);
|
505
|
+
temp[6 ] = (in[2 ] * in[ 4]) - (in[0 ] * in[ 6]);
|
506
|
+
|
507
|
+
temp[8 ] = (in[4 ] * in[ 9]) - (in[5 ] * in[ 8]);
|
508
|
+
temp[9 ] = (in[1 ] * in[ 8]) - (in[0 ] * in[ 9]);
|
509
|
+
temp[10] = (in[0 ] * in[ 5]) - (in[1 ] * in[ 4]);
|
510
|
+
|
511
|
+
det = (in[0] * temp[0]) + (in[1] * temp[4]) + (in[2] * temp[8]);
|
512
|
+
if (s_fabs(det) < S_FLOAT_EPSILON) {
|
513
|
+
mat4_identity(out);
|
514
|
+
return 0;
|
515
|
+
}
|
516
|
+
|
517
|
+
det = 1.0 / det;
|
518
|
+
|
519
|
+
out[0] = temp[0] * det;
|
520
|
+
out[1] = temp[1] * det;
|
521
|
+
out[2] = temp[2] * det;
|
522
|
+
out[4] = temp[4] * det;
|
523
|
+
out[5] = temp[5] * det;
|
524
|
+
out[6] = temp[6] * det;
|
525
|
+
out[8 ] = temp[8 ] * det;
|
526
|
+
out[9 ] = temp[9 ] * det;
|
527
|
+
out[10] = temp[10] * det;
|
528
|
+
|
529
|
+
m12 = in[12];
|
530
|
+
m13 = in[13];
|
531
|
+
m14 = in[14];
|
532
|
+
|
533
|
+
out[12] = -((m12 * temp[0]) + (m13 * temp[4]) + (m14 * temp[8 ]));
|
534
|
+
out[13] = -((m12 * temp[1]) + (m13 * temp[5]) + (m14 * temp[9 ]));
|
535
|
+
out[14] = -((m12 * temp[2]) + (m13 * temp[6]) + (m14 * temp[10]));
|
536
|
+
|
537
|
+
out[3] = out[7] = out[11] = 0.0;
|
538
|
+
out[15] = 1.0;
|
539
|
+
|
540
|
+
return 1;
|
541
|
+
}
|
542
|
+
|
543
|
+
inline s_float_t mat4_cofactor(const mat4_t m, int r0, int r1, int r2, int c0, int c1, int c2)
|
544
|
+
{
|
545
|
+
#define cofactor_addr(l, r) (m[l*4+r])
|
546
|
+
return (
|
547
|
+
(cofactor_addr(r0,c0) * ((cofactor_addr(r1, c1) * cofactor_addr(r2, c2)) - (cofactor_addr(r2, c1) * cofactor_addr(r1, c2)))) -
|
548
|
+
(cofactor_addr(r0,c1) * ((cofactor_addr(r1, c0) * cofactor_addr(r2, c2)) - (cofactor_addr(r2, c0) * cofactor_addr(r1, c2)))) +
|
549
|
+
(cofactor_addr(r0,c2) * ((cofactor_addr(r1, c0) * cofactor_addr(r2, c1)) - (cofactor_addr(r2, c0) * cofactor_addr(r1, c1))))
|
550
|
+
);
|
551
|
+
#undef cofactor_addr
|
552
|
+
}
|
553
|
+
|
554
|
+
void mat4_adjoint(const mat4_t in, mat4_t out)
|
555
|
+
{
|
556
|
+
if (in == out) {
|
557
|
+
mat4_t temp = {
|
558
|
+
mat4_cofactor(in, 1, 2, 3, 1, 2, 3),
|
559
|
+
-mat4_cofactor(in, 0, 2, 3, 1, 2, 3),
|
560
|
+
mat4_cofactor(in, 0, 1, 3, 1, 2, 3),
|
561
|
+
-mat4_cofactor(in, 0, 1, 2, 1, 2, 3),
|
562
|
+
|
563
|
+
-mat4_cofactor(in, 1, 2, 3, 0, 2, 3),
|
564
|
+
mat4_cofactor(in, 0, 2, 3, 0, 2, 3),
|
565
|
+
-mat4_cofactor(in, 0, 1, 3, 0, 2, 3),
|
566
|
+
mat4_cofactor(in, 0, 1, 2, 0, 2, 3),
|
567
|
+
|
568
|
+
mat4_cofactor(in, 1, 2, 3, 0, 1, 3),
|
569
|
+
-mat4_cofactor(in, 0, 2, 3, 0, 1, 3),
|
570
|
+
mat4_cofactor(in, 0, 1, 3, 0, 1, 3),
|
571
|
+
-mat4_cofactor(in, 0, 1, 2, 0, 1, 3),
|
572
|
+
|
573
|
+
-mat4_cofactor(in, 1, 2, 3, 0, 1, 2),
|
574
|
+
mat4_cofactor(in, 0, 2, 3, 0, 1, 2),
|
575
|
+
-mat4_cofactor(in, 0, 1, 3, 0, 1, 2),
|
576
|
+
mat4_cofactor(in, 0, 1, 2, 0, 1, 2)
|
577
|
+
};
|
578
|
+
mat4_copy(temp, out);
|
579
|
+
} else {
|
580
|
+
out[0 ] = mat4_cofactor(in, 1, 2, 3, 1, 2, 3);
|
581
|
+
out[1 ] = -mat4_cofactor(in, 0, 2, 3, 1, 2, 3);
|
582
|
+
out[2 ] = mat4_cofactor(in, 0, 1, 3, 1, 2, 3);
|
583
|
+
out[3 ] = -mat4_cofactor(in, 0, 1, 2, 1, 2, 3);
|
584
|
+
|
585
|
+
out[4 ] = -mat4_cofactor(in, 1, 2, 3, 0, 2, 3);
|
586
|
+
out[5 ] = mat4_cofactor(in, 0, 2, 3, 0, 2, 3);
|
587
|
+
out[6 ] = -mat4_cofactor(in, 0, 1, 3, 0, 2, 3);
|
588
|
+
out[7 ] = mat4_cofactor(in, 0, 1, 2, 0, 2, 3);
|
589
|
+
|
590
|
+
out[8 ] = mat4_cofactor(in, 1, 2, 3, 0, 1, 3);
|
591
|
+
out[9 ] = -mat4_cofactor(in, 0, 2, 3, 0, 1, 3);
|
592
|
+
out[10] = mat4_cofactor(in, 0, 1, 3, 0, 1, 3);
|
593
|
+
out[11] = -mat4_cofactor(in, 0, 1, 2, 0, 1, 3);
|
594
|
+
|
595
|
+
out[12] = -mat4_cofactor(in, 1, 2, 3, 0, 1, 2);
|
596
|
+
out[13] = mat4_cofactor(in, 0, 2, 3, 0, 1, 2);
|
597
|
+
out[14] = -mat4_cofactor(in, 0, 1, 3, 0, 1, 2);
|
598
|
+
out[15] = mat4_cofactor(in, 0, 1, 2, 0, 1, 2);
|
599
|
+
}
|
600
|
+
}
|
601
|
+
|
602
|
+
s_float_t mat4_determinant(const mat4_t m)
|
603
|
+
{
|
604
|
+
return (
|
605
|
+
(m[0] * mat4_cofactor(m, 1, 2, 3, 1, 2, 3)) -
|
606
|
+
(m[1] * mat4_cofactor(m, 1, 2, 3, 0, 2, 3)) +
|
607
|
+
(m[2] * mat4_cofactor(m, 1, 2, 3, 0, 1, 3)) -
|
608
|
+
(m[3] * mat4_cofactor(m, 1, 2, 3, 0, 1, 2))
|
609
|
+
);
|
610
|
+
}
|
611
|
+
|
612
|
+
int mat4_inverse_general(const mat4_t in, mat4_t out)
|
613
|
+
{
|
614
|
+
int index;
|
615
|
+
s_float_t det = mat4_determinant(in);
|
616
|
+
|
617
|
+
if (s_fabs(det) < S_FLOAT_EPSILON) {
|
618
|
+
return 0;
|
619
|
+
}
|
620
|
+
|
621
|
+
mat4_adjoint(in, out);
|
622
|
+
det = 1.0 / det;
|
623
|
+
for (index = 0; index < 16; ++index) {
|
624
|
+
out[index] *= det;
|
625
|
+
}
|
626
|
+
|
627
|
+
return 1;
|
628
|
+
}
|
629
|
+
|
630
|
+
/*! Translates the given matrix by <X, Y, Z>. */
|
631
|
+
void mat4_translate(s_float_t x, s_float_t y, s_float_t z, const mat4_t in, mat4_t out)
|
632
|
+
{
|
633
|
+
s_float_t m12 = in[12] + ((x * in[0]) + (y * in[4]) + (z * in[8]));
|
634
|
+
s_float_t m13 = in[13] + ((x * in[1]) + (y * in[5]) + (z * in[9]));
|
635
|
+
s_float_t m14 = in[14] + ((x * in[2]) + (y * in[6]) + (z * in[10]));
|
636
|
+
s_float_t m15 = in[15] + ((x * in[3]) + (y * in[7]) + (z * in[11]));
|
637
|
+
|
638
|
+
if (in != out)
|
639
|
+
mat4_copy(in, out);
|
640
|
+
|
641
|
+
out[12] = m12;
|
642
|
+
out[13] = m13;
|
643
|
+
out[14] = m14;
|
644
|
+
out[15] = m15;
|
645
|
+
}
|
646
|
+
|
647
|
+
void mat4_translation(s_float_t x, s_float_t y, s_float_t z, mat4_t out) {
|
648
|
+
s_float_t m12 = x;
|
649
|
+
s_float_t m13 = y;
|
650
|
+
s_float_t m14 = z;
|
651
|
+
s_float_t m15 = 1;
|
652
|
+
|
653
|
+
mat4_copy(g_mat4_identity, out);
|
654
|
+
|
655
|
+
out[12] = m12;
|
656
|
+
out[13] = m13;
|
657
|
+
out[14] = m14;
|
658
|
+
out[15] = m15;
|
659
|
+
}
|
660
|
+
|
661
|
+
void mat4_multiply(const mat4_t left, const mat4_t right, mat4_t out)
|
662
|
+
{
|
663
|
+
mat4_t temp;
|
664
|
+
int index;
|
665
|
+
|
666
|
+
// Transpose the left matrix so we can be a little more cache-friendly.
|
667
|
+
mat4_transpose(left, temp);
|
668
|
+
|
669
|
+
for (index = 0; index < 4; ++index) {
|
670
|
+
const int inner_index = index * 4;
|
671
|
+
s_float_t cx, cy, cz, cw;
|
672
|
+
|
673
|
+
cx = temp[inner_index];
|
674
|
+
cy = temp[inner_index + 1];
|
675
|
+
cz = temp[inner_index + 2];
|
676
|
+
cw = temp[inner_index + 3];
|
677
|
+
|
678
|
+
temp[inner_index] = (cx * right[0 ]) + (cy * right[1 ]) + (cz * right[2 ]) + (cw * right[3 ]);
|
679
|
+
temp[inner_index + 1] = (cx * right[4 ]) + (cy * right[5 ]) + (cz * right[6 ]) + (cw * right[7 ]);
|
680
|
+
temp[inner_index + 2] = (cx * right[8 ]) + (cy * right[9 ]) + (cz * right[10]) + (cw * right[11]);
|
681
|
+
temp[inner_index + 3] = (cx * right[12]) + (cy * right[13]) + (cz * right[14]) + (cw * right[15]);
|
682
|
+
}
|
683
|
+
|
684
|
+
mat4_transpose(temp, out);
|
685
|
+
}
|
686
|
+
|
687
|
+
void mat4_multiply_vec4(const mat4_t left, const vec4_t right, vec4_t out)
|
688
|
+
{
|
689
|
+
const s_float_t x = right[0], y = right[1], z = right[2], w = right[3];
|
690
|
+
out[0] = (x * left[0]) + (y * left[4]) + (z * left[8 ]) + (w * left[12]);
|
691
|
+
out[1] = (x * left[1]) + (y * left[5]) + (z * left[9 ]) + (w * left[13]);
|
692
|
+
out[2] = (x * left[2]) + (y * left[6]) + (z * left[10]) + (w * left[14]);
|
693
|
+
out[3] = (x * left[3]) + (y * left[7]) + (z * left[11]) + (w * left[15]);
|
694
|
+
}
|
695
|
+
|
696
|
+
void mat4_transform_vec3(const mat4_t left, const vec3_t right, vec3_t out)
|
697
|
+
{
|
698
|
+
const s_float_t x = right[0], y = right[1], z = right[2];
|
699
|
+
out[0] = (x * left[0]) + (y * left[4]) + (z * left[8 ]) + left[12];
|
700
|
+
out[1] = (x * left[1]) + (y * left[5]) + (z * left[9 ]) + left[13];
|
701
|
+
out[2] = (x * left[2]) + (y * left[6]) + (z * left[10]) + left[14];
|
702
|
+
}
|
703
|
+
|
704
|
+
void mat4_rotate_vec3(const mat4_t left, const vec3_t right, vec3_t out)
|
705
|
+
{
|
706
|
+
const s_float_t x = right[0], y = right[1], z = right[2];
|
707
|
+
out[0] = (x * left[0]) + (y * left[4]) + (z * left[8 ]);
|
708
|
+
out[1] = (x * left[1]) + (y * left[5]) + (z * left[9 ]);
|
709
|
+
out[2] = (x * left[2]) + (y * left[6]) + (z * left[10]);
|
710
|
+
}
|
711
|
+
|
712
|
+
void mat4_inv_rotate_vec3(const mat4_t left, const vec3_t right, vec3_t out)
|
713
|
+
{
|
714
|
+
const s_float_t x = right[0], y = right[1], z = right[2];
|
715
|
+
out[0] = (x * left[0]) + (y * left[1]) + (z * left[2 ]);
|
716
|
+
out[1] = (x * left[4]) + (y * left[5]) + (z * left[6 ]);
|
717
|
+
out[2] = (x * left[8]) + (y * left[9]) + (z * left[10]);
|
718
|
+
}
|
719
|
+
|
720
|
+
void mat4_scale(const mat4_t in, s_float_t x, s_float_t y, s_float_t z, mat4_t out)
|
721
|
+
{
|
722
|
+
mat4_copy(in, out);
|
723
|
+
out[0] *= x;
|
724
|
+
out[4] *= x;
|
725
|
+
out[8] *= x;
|
726
|
+
|
727
|
+
out[1] *= y;
|
728
|
+
out[5] *= y;
|
729
|
+
out[9] *= y;
|
730
|
+
|
731
|
+
out[2 ] *= z;
|
732
|
+
out[6 ] *= z;
|
733
|
+
out[10] *= z;
|
734
|
+
}
|
735
|
+
|
736
|
+
#if defined(__cplusplus)
|
737
|
+
}
|
738
|
+
#endif /* __cplusplus */
|
739
|
+
|