larb 0.1.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/README.md +14 -1
- data/ext/larb/color.c +446 -0
- data/ext/larb/color.h +35 -0
- data/ext/larb/extconf.rb +11 -0
- data/ext/larb/larb.c +27 -0
- data/ext/larb/larb.h +8 -0
- data/ext/larb/mat2.c +300 -0
- data/ext/larb/mat2.h +30 -0
- data/ext/larb/mat2d.c +380 -0
- data/ext/larb/mat2d.h +35 -0
- data/ext/larb/mat3.c +469 -0
- data/ext/larb/mat3.h +33 -0
- data/ext/larb/mat4.c +671 -0
- data/ext/larb/mat4.h +31 -0
- data/ext/larb/quat.c +523 -0
- data/ext/larb/quat.h +39 -0
- data/ext/larb/quat2.c +473 -0
- data/ext/larb/quat2.h +39 -0
- data/ext/larb/vec2.c +342 -0
- data/ext/larb/vec2.h +43 -0
- data/ext/larb/vec3.c +503 -0
- data/ext/larb/vec3.h +52 -0
- data/ext/larb/vec4.c +340 -0
- data/ext/larb/vec4.h +38 -0
- data/lib/larb/version.rb +5 -0
- data/lib/larb.rb +2 -14
- data/test/larb/color_test.rb +278 -0
- data/test/larb/mat2_test.rb +144 -0
- data/test/larb/mat2d_test.rb +172 -0
- data/test/larb/mat3_test.rb +147 -0
- data/test/larb/mat4_test.rb +270 -0
- data/test/larb/quat2_test.rb +161 -0
- data/test/larb/quat_test.rb +224 -0
- data/test/larb/vec2_test.rb +251 -0
- data/test/larb/vec3_test.rb +310 -0
- data/test/larb/vec4_test.rb +189 -0
- data/test/test_helper.rb +4 -0
- metadata +53 -14
- data/Rakefile +0 -11
- data/lib/larb/color.rb +0 -148
- data/lib/larb/mat2.rb +0 -119
- data/lib/larb/mat2d.rb +0 -180
- data/lib/larb/mat3.rb +0 -238
- data/lib/larb/mat4.rb +0 -329
- data/lib/larb/quat.rb +0 -238
- data/lib/larb/quat2.rb +0 -193
- data/lib/larb/vec2.rb +0 -150
- data/lib/larb/vec3.rb +0 -218
- data/lib/larb/vec4.rb +0 -125
data/ext/larb/mat4.c
ADDED
|
@@ -0,0 +1,671 @@
|
|
|
1
|
+
#include "mat4.h"
|
|
2
|
+
|
|
3
|
+
#include <math.h>
|
|
4
|
+
|
|
5
|
+
static void mat4_free(void *ptr) {
|
|
6
|
+
xfree(ptr);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
static size_t mat4_memsize(const void *ptr) {
|
|
10
|
+
return sizeof(Mat4Data);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
static const rb_data_type_t mat4_type = {
|
|
14
|
+
"Mat4",
|
|
15
|
+
{0, mat4_free, mat4_memsize},
|
|
16
|
+
0,
|
|
17
|
+
0,
|
|
18
|
+
RUBY_TYPED_FREE_IMMEDIATELY,
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
static VALUE cMat4 = Qnil;
|
|
22
|
+
static VALUE cVec3 = Qnil;
|
|
23
|
+
static VALUE cVec4 = Qnil;
|
|
24
|
+
static VALUE cQuat = Qnil;
|
|
25
|
+
|
|
26
|
+
static double value_to_double(VALUE value) {
|
|
27
|
+
VALUE coerced = rb_funcall(value, rb_intern("to_f"), 0);
|
|
28
|
+
return NUM2DBL(coerced);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
static Mat4Data *mat4_get(VALUE obj) {
|
|
32
|
+
Mat4Data *data = NULL;
|
|
33
|
+
TypedData_Get_Struct(obj, Mat4Data, &mat4_type, data);
|
|
34
|
+
return data;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
static VALUE mat4_build(VALUE klass, const double *values) {
|
|
38
|
+
VALUE obj = mat4_alloc(klass);
|
|
39
|
+
Mat4Data *data = mat4_get(obj);
|
|
40
|
+
for (int i = 0; i < 16; i++) {
|
|
41
|
+
data->data[i] = values[i];
|
|
42
|
+
}
|
|
43
|
+
return obj;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
static VALUE mat4_build16(VALUE klass, double v0, double v1, double v2,
|
|
47
|
+
double v3, double v4, double v5, double v6, double v7,
|
|
48
|
+
double v8, double v9, double v10, double v11,
|
|
49
|
+
double v12, double v13, double v14, double v15) {
|
|
50
|
+
double values[16] = {v0, v1, v2, v3, v4, v5, v6, v7,
|
|
51
|
+
v8, v9, v10, v11, v12, v13, v14, v15};
|
|
52
|
+
return mat4_build(klass, values);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
static inline void vec3_normalize(double *x, double *y, double *z) {
|
|
56
|
+
double len = sqrt((*x) * (*x) + (*y) * (*y) + (*z) * (*z));
|
|
57
|
+
*x /= len;
|
|
58
|
+
*y /= len;
|
|
59
|
+
*z /= len;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
static inline void vec3_cross(double ax, double ay, double az, double bx,
|
|
63
|
+
double by, double bz, double *rx, double *ry,
|
|
64
|
+
double *rz) {
|
|
65
|
+
*rx = ay * bz - az * by;
|
|
66
|
+
*ry = az * bx - ax * bz;
|
|
67
|
+
*rz = ax * by - ay * bx;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
VALUE mat4_alloc(VALUE klass) {
|
|
71
|
+
Mat4Data *data = ALLOC(Mat4Data);
|
|
72
|
+
for (int i = 0; i < 16; i++) {
|
|
73
|
+
data->data[i] = 0.0;
|
|
74
|
+
}
|
|
75
|
+
data->data[0] = 1.0;
|
|
76
|
+
data->data[5] = 1.0;
|
|
77
|
+
data->data[10] = 1.0;
|
|
78
|
+
data->data[15] = 1.0;
|
|
79
|
+
return TypedData_Wrap_Struct(klass, &mat4_type, data);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
VALUE mat4_initialize(int argc, VALUE *argv, VALUE self) {
|
|
83
|
+
VALUE data_arg = Qnil;
|
|
84
|
+
Mat4Data *data = mat4_get(self);
|
|
85
|
+
|
|
86
|
+
rb_scan_args(argc, argv, "01", &data_arg);
|
|
87
|
+
if (NIL_P(data_arg)) {
|
|
88
|
+
for (int i = 0; i < 16; i++) {
|
|
89
|
+
data->data[i] = 0.0;
|
|
90
|
+
}
|
|
91
|
+
data->data[0] = 1.0;
|
|
92
|
+
data->data[5] = 1.0;
|
|
93
|
+
data->data[10] = 1.0;
|
|
94
|
+
data->data[15] = 1.0;
|
|
95
|
+
return self;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
VALUE ary = rb_check_array_type(data_arg);
|
|
99
|
+
if (NIL_P(ary)) {
|
|
100
|
+
rb_raise(rb_eTypeError, "expected Array");
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
for (int i = 0; i < 16; i++) {
|
|
104
|
+
data->data[i] = value_to_double(rb_ary_entry(ary, i));
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return self;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
static VALUE mat4_class_identity(VALUE klass) {
|
|
111
|
+
return mat4_alloc(klass);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
static VALUE mat4_class_zero(VALUE klass) {
|
|
115
|
+
return mat4_build16(klass, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
|
|
116
|
+
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
static VALUE mat4_class_translation(VALUE klass, VALUE x, VALUE y, VALUE z) {
|
|
120
|
+
VALUE m = mat4_class_identity(klass);
|
|
121
|
+
mat4_aset(m, INT2NUM(12), x);
|
|
122
|
+
mat4_aset(m, INT2NUM(13), y);
|
|
123
|
+
mat4_aset(m, INT2NUM(14), z);
|
|
124
|
+
return m;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
static VALUE mat4_class_scaling(VALUE klass, VALUE x, VALUE y, VALUE z) {
|
|
128
|
+
double sx = value_to_double(x);
|
|
129
|
+
double sy = value_to_double(y);
|
|
130
|
+
double sz = value_to_double(z);
|
|
131
|
+
return mat4_build16(klass, sx, 0.0, 0.0, 0.0, 0.0, sy, 0.0, 0.0, 0.0, 0.0,
|
|
132
|
+
sz, 0.0, 0.0, 0.0, 0.0, 1.0);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
static VALUE mat4_class_rotation_x(VALUE klass, VALUE radians) {
|
|
136
|
+
double r = value_to_double(radians);
|
|
137
|
+
double c = cos(r);
|
|
138
|
+
double s = sin(r);
|
|
139
|
+
return mat4_build16(klass, 1.0, 0.0, 0.0, 0.0, 0.0, c, s, 0.0, 0.0, -s, c,
|
|
140
|
+
0.0, 0.0, 0.0, 0.0, 1.0);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
static VALUE mat4_class_rotation_y(VALUE klass, VALUE radians) {
|
|
144
|
+
double r = value_to_double(radians);
|
|
145
|
+
double c = cos(r);
|
|
146
|
+
double s = sin(r);
|
|
147
|
+
return mat4_build16(klass, c, 0.0, -s, 0.0, 0.0, 1.0, 0.0, 0.0, s, 0.0, c,
|
|
148
|
+
0.0, 0.0, 0.0, 0.0, 1.0);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
static VALUE mat4_class_rotation_z(VALUE klass, VALUE radians) {
|
|
152
|
+
double r = value_to_double(radians);
|
|
153
|
+
double c = cos(r);
|
|
154
|
+
double s = sin(r);
|
|
155
|
+
return mat4_build16(klass, c, s, 0.0, 0.0, -s, c, 0.0, 0.0, 0.0, 0.0, 1.0,
|
|
156
|
+
0.0, 0.0, 0.0, 0.0, 1.0);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
static VALUE mat4_class_rotation(VALUE klass, VALUE axis, VALUE radians) {
|
|
160
|
+
VALUE normalized = rb_funcall(axis, rb_intern("normalize"), 0);
|
|
161
|
+
double x = value_to_double(rb_funcall(normalized, rb_intern("x"), 0));
|
|
162
|
+
double y = value_to_double(rb_funcall(normalized, rb_intern("y"), 0));
|
|
163
|
+
double z = value_to_double(rb_funcall(normalized, rb_intern("z"), 0));
|
|
164
|
+
double r = value_to_double(radians);
|
|
165
|
+
double c = cos(r);
|
|
166
|
+
double s = sin(r);
|
|
167
|
+
double t = 1.0 - c;
|
|
168
|
+
|
|
169
|
+
return mat4_build16(klass, t * x * x + c, t * x * y + s * z,
|
|
170
|
+
t * x * z - s * y, 0.0, t * x * y - s * z,
|
|
171
|
+
t * y * y + c, t * y * z + s * x, 0.0,
|
|
172
|
+
t * x * z + s * y, t * y * z - s * x,
|
|
173
|
+
t * z * z + c, 0.0, 0.0, 0.0, 0.0, 1.0);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
static VALUE mat4_class_look_at(VALUE klass, VALUE eye, VALUE target,
|
|
177
|
+
VALUE up) {
|
|
178
|
+
double ex = value_to_double(rb_funcall(eye, rb_intern("x"), 0));
|
|
179
|
+
double ey = value_to_double(rb_funcall(eye, rb_intern("y"), 0));
|
|
180
|
+
double ez = value_to_double(rb_funcall(eye, rb_intern("z"), 0));
|
|
181
|
+
double tx = value_to_double(rb_funcall(target, rb_intern("x"), 0));
|
|
182
|
+
double ty = value_to_double(rb_funcall(target, rb_intern("y"), 0));
|
|
183
|
+
double tz = value_to_double(rb_funcall(target, rb_intern("z"), 0));
|
|
184
|
+
double ux = value_to_double(rb_funcall(up, rb_intern("x"), 0));
|
|
185
|
+
double uy = value_to_double(rb_funcall(up, rb_intern("y"), 0));
|
|
186
|
+
double uz = value_to_double(rb_funcall(up, rb_intern("z"), 0));
|
|
187
|
+
|
|
188
|
+
double fx = tx - ex;
|
|
189
|
+
double fy = ty - ey;
|
|
190
|
+
double fz = tz - ez;
|
|
191
|
+
vec3_normalize(&fx, &fy, &fz);
|
|
192
|
+
|
|
193
|
+
double rx, ry, rz;
|
|
194
|
+
vec3_cross(fx, fy, fz, ux, uy, uz, &rx, &ry, &rz);
|
|
195
|
+
vec3_normalize(&rx, &ry, &rz);
|
|
196
|
+
|
|
197
|
+
double ux2, uy2, uz2;
|
|
198
|
+
vec3_cross(rx, ry, rz, fx, fy, fz, &ux2, &uy2, &uz2);
|
|
199
|
+
|
|
200
|
+
return mat4_build16(klass, rx, ux2, -fx, 0.0, ry, uy2, -fy, 0.0, rz, uz2,
|
|
201
|
+
-fz, 0.0, -(rx * ex + ry * ey + rz * ez),
|
|
202
|
+
-(ux2 * ex + uy2 * ey + uz2 * ez),
|
|
203
|
+
(fx * ex + fy * ey + fz * ez), 1.0);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
static VALUE mat4_class_perspective(VALUE klass, VALUE fov_y, VALUE aspect,
|
|
207
|
+
VALUE near, VALUE far) {
|
|
208
|
+
double f = 1.0 / tan(value_to_double(fov_y) / 2.0);
|
|
209
|
+
double nf = 1.0 / (value_to_double(near) - value_to_double(far));
|
|
210
|
+
double a = value_to_double(aspect);
|
|
211
|
+
double n = value_to_double(near);
|
|
212
|
+
double fr = value_to_double(far);
|
|
213
|
+
|
|
214
|
+
return mat4_build16(klass, f / a, 0.0, 0.0, 0.0, 0.0, f, 0.0, 0.0, 0.0, 0.0,
|
|
215
|
+
(fr + n) * nf, -1.0, 0.0, 0.0, 2.0 * fr * n * nf, 0.0);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
static VALUE mat4_class_orthographic(VALUE klass, VALUE left, VALUE right,
|
|
219
|
+
VALUE bottom, VALUE top, VALUE near,
|
|
220
|
+
VALUE far) {
|
|
221
|
+
double rl = 1.0 / (value_to_double(right) - value_to_double(left));
|
|
222
|
+
double tb = 1.0 / (value_to_double(top) - value_to_double(bottom));
|
|
223
|
+
double fn = 1.0 / (value_to_double(far) - value_to_double(near));
|
|
224
|
+
double r = value_to_double(right);
|
|
225
|
+
double l = value_to_double(left);
|
|
226
|
+
double t = value_to_double(top);
|
|
227
|
+
double b = value_to_double(bottom);
|
|
228
|
+
double f = value_to_double(far);
|
|
229
|
+
double n = value_to_double(near);
|
|
230
|
+
|
|
231
|
+
return mat4_build16(klass, 2 * rl, 0.0, 0.0, 0.0, 0.0, 2 * tb, 0.0, 0.0,
|
|
232
|
+
0.0, 0.0, -2 * fn, 0.0, -(r + l) * rl, -(t + b) * tb,
|
|
233
|
+
-(f + n) * fn, 1.0);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
static VALUE mat4_class_frustum(VALUE klass, VALUE left, VALUE right,
|
|
237
|
+
VALUE bottom, VALUE top, VALUE near,
|
|
238
|
+
VALUE far) {
|
|
239
|
+
double rl = 1.0 / (value_to_double(right) - value_to_double(left));
|
|
240
|
+
double tb = 1.0 / (value_to_double(top) - value_to_double(bottom));
|
|
241
|
+
double nf = 1.0 / (value_to_double(near) - value_to_double(far));
|
|
242
|
+
double r = value_to_double(right);
|
|
243
|
+
double l = value_to_double(left);
|
|
244
|
+
double t = value_to_double(top);
|
|
245
|
+
double b = value_to_double(bottom);
|
|
246
|
+
double n = value_to_double(near);
|
|
247
|
+
double f = value_to_double(far);
|
|
248
|
+
|
|
249
|
+
return mat4_build16(klass, 2 * n * rl, 0.0, 0.0, 0.0, 0.0, 2 * n * tb, 0.0,
|
|
250
|
+
0.0, (r + l) * rl, (t + b) * tb, (f + n) * nf, -1.0, 0.0,
|
|
251
|
+
0.0, 2 * f * n * nf, 0.0);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
static VALUE mat4_class_from_quaternion(VALUE klass, VALUE quat) {
|
|
255
|
+
double x = value_to_double(rb_funcall(quat, rb_intern("x"), 0));
|
|
256
|
+
double y = value_to_double(rb_funcall(quat, rb_intern("y"), 0));
|
|
257
|
+
double z = value_to_double(rb_funcall(quat, rb_intern("z"), 0));
|
|
258
|
+
double w = value_to_double(rb_funcall(quat, rb_intern("w"), 0));
|
|
259
|
+
|
|
260
|
+
double x2 = x + x;
|
|
261
|
+
double y2 = y + y;
|
|
262
|
+
double z2 = z + z;
|
|
263
|
+
double xx = x * x2;
|
|
264
|
+
double xy = x * y2;
|
|
265
|
+
double xz = x * z2;
|
|
266
|
+
double yy = y * y2;
|
|
267
|
+
double yz = y * z2;
|
|
268
|
+
double zz = z * z2;
|
|
269
|
+
double wx = w * x2;
|
|
270
|
+
double wy = w * y2;
|
|
271
|
+
double wz = w * z2;
|
|
272
|
+
|
|
273
|
+
return mat4_build16(klass, 1 - (yy + zz), xy + wz, xz - wy, 0.0, xy - wz,
|
|
274
|
+
1 - (xx + zz), yz + wx, 0.0, xz + wy, yz - wx,
|
|
275
|
+
1 - (xx + yy), 0.0, 0.0, 0.0, 0.0, 1.0);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
static VALUE mat4_class_trs(VALUE klass, VALUE translation, VALUE rotation,
|
|
279
|
+
VALUE scale) {
|
|
280
|
+
VALUE rot = mat4_class_from_quaternion(klass, rotation);
|
|
281
|
+
double sx = value_to_double(rb_funcall(scale, rb_intern("x"), 0));
|
|
282
|
+
double sy = value_to_double(rb_funcall(scale, rb_intern("y"), 0));
|
|
283
|
+
double sz = value_to_double(rb_funcall(scale, rb_intern("z"), 0));
|
|
284
|
+
VALUE scale_m = mat4_class_scaling(klass, DBL2NUM(sx), DBL2NUM(sy), DBL2NUM(sz));
|
|
285
|
+
double tx = value_to_double(rb_funcall(translation, rb_intern("x"), 0));
|
|
286
|
+
double ty = value_to_double(rb_funcall(translation, rb_intern("y"), 0));
|
|
287
|
+
double tz = value_to_double(rb_funcall(translation, rb_intern("z"), 0));
|
|
288
|
+
VALUE trans_m =
|
|
289
|
+
mat4_class_translation(klass, DBL2NUM(tx), DBL2NUM(ty), DBL2NUM(tz));
|
|
290
|
+
VALUE tmp = mat4_mul(rot, scale_m);
|
|
291
|
+
return mat4_mul(tmp, trans_m);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
VALUE mat4_aref(VALUE self, VALUE index) {
|
|
295
|
+
Mat4Data *data = mat4_get(self);
|
|
296
|
+
long idx = NUM2LONG(index);
|
|
297
|
+
if (idx < 0 || idx > 15) {
|
|
298
|
+
return Qnil;
|
|
299
|
+
}
|
|
300
|
+
return DBL2NUM(data->data[idx]);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
VALUE mat4_aset(VALUE self, VALUE index, VALUE value) {
|
|
304
|
+
Mat4Data *data = mat4_get(self);
|
|
305
|
+
long idx = NUM2LONG(index);
|
|
306
|
+
if (idx < 0 || idx > 15) {
|
|
307
|
+
rb_raise(rb_eIndexError, "index %ld out of range", idx);
|
|
308
|
+
}
|
|
309
|
+
data->data[idx] = value_to_double(value);
|
|
310
|
+
return value;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
VALUE mat4_mul(VALUE self, VALUE other) {
|
|
314
|
+
Mat4Data *a = mat4_get(self);
|
|
315
|
+
|
|
316
|
+
if (rb_obj_is_kind_of(other, cMat4)) {
|
|
317
|
+
Mat4Data *b = mat4_get(other);
|
|
318
|
+
double result[16];
|
|
319
|
+
const double *ad = a->data;
|
|
320
|
+
const double *bd = b->data;
|
|
321
|
+
|
|
322
|
+
result[0] = ad[0] * bd[0] + ad[4] * bd[1] + ad[8] * bd[2] + ad[12] * bd[3];
|
|
323
|
+
result[1] = ad[1] * bd[0] + ad[5] * bd[1] + ad[9] * bd[2] + ad[13] * bd[3];
|
|
324
|
+
result[2] = ad[2] * bd[0] + ad[6] * bd[1] + ad[10] * bd[2] + ad[14] * bd[3];
|
|
325
|
+
result[3] = ad[3] * bd[0] + ad[7] * bd[1] + ad[11] * bd[2] + ad[15] * bd[3];
|
|
326
|
+
|
|
327
|
+
result[4] = ad[0] * bd[4] + ad[4] * bd[5] + ad[8] * bd[6] + ad[12] * bd[7];
|
|
328
|
+
result[5] = ad[1] * bd[4] + ad[5] * bd[5] + ad[9] * bd[6] + ad[13] * bd[7];
|
|
329
|
+
result[6] = ad[2] * bd[4] + ad[6] * bd[5] + ad[10] * bd[6] + ad[14] * bd[7];
|
|
330
|
+
result[7] = ad[3] * bd[4] + ad[7] * bd[5] + ad[11] * bd[6] + ad[15] * bd[7];
|
|
331
|
+
|
|
332
|
+
result[8] = ad[0] * bd[8] + ad[4] * bd[9] + ad[8] * bd[10] + ad[12] * bd[11];
|
|
333
|
+
result[9] = ad[1] * bd[8] + ad[5] * bd[9] + ad[9] * bd[10] + ad[13] * bd[11];
|
|
334
|
+
result[10] = ad[2] * bd[8] + ad[6] * bd[9] + ad[10] * bd[10] + ad[14] * bd[11];
|
|
335
|
+
result[11] = ad[3] * bd[8] + ad[7] * bd[9] + ad[11] * bd[10] + ad[15] * bd[11];
|
|
336
|
+
|
|
337
|
+
result[12] = ad[0] * bd[12] + ad[4] * bd[13] + ad[8] * bd[14] + ad[12] * bd[15];
|
|
338
|
+
result[13] = ad[1] * bd[12] + ad[5] * bd[13] + ad[9] * bd[14] + ad[13] * bd[15];
|
|
339
|
+
result[14] = ad[2] * bd[12] + ad[6] * bd[13] + ad[10] * bd[14] + ad[14] * bd[15];
|
|
340
|
+
result[15] = ad[3] * bd[12] + ad[7] * bd[13] + ad[11] * bd[14] + ad[15] * bd[15];
|
|
341
|
+
return mat4_build(rb_obj_class(self), result);
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
if (rb_obj_is_kind_of(other, cVec4)) {
|
|
345
|
+
double x = value_to_double(rb_funcall(other, rb_intern("x"), 0));
|
|
346
|
+
double y = value_to_double(rb_funcall(other, rb_intern("y"), 0));
|
|
347
|
+
double z = value_to_double(rb_funcall(other, rb_intern("z"), 0));
|
|
348
|
+
double w = value_to_double(rb_funcall(other, rb_intern("w"), 0));
|
|
349
|
+
VALUE vec4_class = rb_const_get(mLarb, rb_intern("Vec4"));
|
|
350
|
+
return rb_funcall(
|
|
351
|
+
vec4_class, rb_intern("new"), 4,
|
|
352
|
+
DBL2NUM(a->data[0] * x + a->data[4] * y + a->data[8] * z +
|
|
353
|
+
a->data[12] * w),
|
|
354
|
+
DBL2NUM(a->data[1] * x + a->data[5] * y + a->data[9] * z +
|
|
355
|
+
a->data[13] * w),
|
|
356
|
+
DBL2NUM(a->data[2] * x + a->data[6] * y + a->data[10] * z +
|
|
357
|
+
a->data[14] * w),
|
|
358
|
+
DBL2NUM(a->data[3] * x + a->data[7] * y + a->data[11] * z +
|
|
359
|
+
a->data[15] * w));
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
if (rb_obj_is_kind_of(other, cVec3)) {
|
|
363
|
+
VALUE vec4 = rb_funcall(other, rb_intern("to_vec4"), 0);
|
|
364
|
+
return mat4_mul(self, vec4);
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
return Qnil;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
VALUE mat4_transpose(VALUE self) {
|
|
371
|
+
Mat4Data *a = mat4_get(self);
|
|
372
|
+
return mat4_build16(rb_obj_class(self), a->data[0], a->data[4], a->data[8],
|
|
373
|
+
a->data[12], a->data[1], a->data[5], a->data[9],
|
|
374
|
+
a->data[13], a->data[2], a->data[6], a->data[10],
|
|
375
|
+
a->data[14], a->data[3], a->data[7], a->data[11],
|
|
376
|
+
a->data[15]);
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
VALUE mat4_inverse(VALUE self) {
|
|
380
|
+
Mat4Data *a = mat4_get(self);
|
|
381
|
+
const double *m = a->data;
|
|
382
|
+
const double m0 = m[0];
|
|
383
|
+
const double m1 = m[1];
|
|
384
|
+
const double m2 = m[2];
|
|
385
|
+
const double m3 = m[3];
|
|
386
|
+
const double m4 = m[4];
|
|
387
|
+
const double m5 = m[5];
|
|
388
|
+
const double m6 = m[6];
|
|
389
|
+
const double m7 = m[7];
|
|
390
|
+
const double m8 = m[8];
|
|
391
|
+
const double m9 = m[9];
|
|
392
|
+
const double m10 = m[10];
|
|
393
|
+
const double m11 = m[11];
|
|
394
|
+
const double m12 = m[12];
|
|
395
|
+
const double m13 = m[13];
|
|
396
|
+
const double m14 = m[14];
|
|
397
|
+
const double m15 = m[15];
|
|
398
|
+
double inv[16];
|
|
399
|
+
|
|
400
|
+
inv[0] = m5 * m10 * m15 - m5 * m11 * m14 - m9 * m6 * m15 +
|
|
401
|
+
m9 * m7 * m14 + m13 * m6 * m11 - m13 * m7 * m10;
|
|
402
|
+
inv[4] = -m4 * m10 * m15 + m4 * m11 * m14 + m8 * m6 * m15 -
|
|
403
|
+
m8 * m7 * m14 - m12 * m6 * m11 + m12 * m7 * m10;
|
|
404
|
+
inv[8] = m4 * m9 * m15 - m4 * m11 * m13 - m8 * m5 * m15 +
|
|
405
|
+
m8 * m7 * m13 + m12 * m5 * m11 - m12 * m7 * m9;
|
|
406
|
+
inv[12] = -m4 * m9 * m14 + m4 * m10 * m13 + m8 * m5 * m14 -
|
|
407
|
+
m8 * m6 * m13 - m12 * m5 * m10 + m12 * m6 * m9;
|
|
408
|
+
|
|
409
|
+
inv[1] = -m1 * m10 * m15 + m1 * m11 * m14 + m9 * m2 * m15 -
|
|
410
|
+
m9 * m3 * m14 - m13 * m2 * m11 + m13 * m3 * m10;
|
|
411
|
+
inv[5] = m0 * m10 * m15 - m0 * m11 * m14 - m8 * m2 * m15 +
|
|
412
|
+
m8 * m3 * m14 + m12 * m2 * m11 - m12 * m3 * m10;
|
|
413
|
+
inv[9] = -m0 * m9 * m15 + m0 * m11 * m13 + m8 * m1 * m15 -
|
|
414
|
+
m8 * m3 * m13 - m12 * m1 * m11 + m12 * m3 * m9;
|
|
415
|
+
inv[13] = m0 * m9 * m14 - m0 * m10 * m13 - m8 * m1 * m14 +
|
|
416
|
+
m8 * m2 * m13 + m12 * m1 * m10 - m12 * m2 * m9;
|
|
417
|
+
|
|
418
|
+
inv[2] = m1 * m6 * m15 - m1 * m7 * m14 - m5 * m2 * m15 +
|
|
419
|
+
m5 * m3 * m14 + m13 * m2 * m7 - m13 * m3 * m6;
|
|
420
|
+
inv[6] = -m0 * m6 * m15 + m0 * m7 * m14 + m4 * m2 * m15 -
|
|
421
|
+
m4 * m3 * m14 - m12 * m2 * m7 + m12 * m3 * m6;
|
|
422
|
+
inv[10] = m0 * m5 * m15 - m0 * m7 * m13 - m4 * m1 * m15 +
|
|
423
|
+
m4 * m3 * m13 + m12 * m1 * m7 - m12 * m3 * m5;
|
|
424
|
+
inv[14] = -m0 * m5 * m14 + m0 * m6 * m13 + m4 * m1 * m14 -
|
|
425
|
+
m4 * m2 * m13 - m12 * m1 * m6 + m12 * m2 * m5;
|
|
426
|
+
|
|
427
|
+
inv[3] = -m1 * m6 * m11 + m1 * m7 * m10 + m5 * m2 * m11 -
|
|
428
|
+
m5 * m3 * m10 - m9 * m2 * m7 + m9 * m3 * m6;
|
|
429
|
+
inv[7] = m0 * m6 * m11 - m0 * m7 * m10 - m4 * m2 * m11 +
|
|
430
|
+
m4 * m3 * m10 + m8 * m2 * m7 - m8 * m3 * m6;
|
|
431
|
+
inv[11] = -m0 * m5 * m11 + m0 * m7 * m9 + m4 * m1 * m11 -
|
|
432
|
+
m4 * m3 * m9 - m8 * m1 * m7 + m8 * m3 * m5;
|
|
433
|
+
inv[15] = m0 * m5 * m10 - m0 * m6 * m9 - m4 * m1 * m10 +
|
|
434
|
+
m4 * m2 * m9 + m8 * m1 * m6 - m8 * m2 * m5;
|
|
435
|
+
|
|
436
|
+
double det = m0 * inv[0] + m1 * inv[4] + m2 * inv[8] + m3 * inv[12];
|
|
437
|
+
if (fabs(det) < 1e-10) {
|
|
438
|
+
rb_raise(rb_eRuntimeError, "Matrix is not invertible");
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
det = 1.0 / det;
|
|
442
|
+
for (int i = 0; i < 16; i++) {
|
|
443
|
+
inv[i] *= det;
|
|
444
|
+
}
|
|
445
|
+
return mat4_build(rb_obj_class(self), inv);
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
VALUE mat4_to_a(VALUE self) {
|
|
449
|
+
Mat4Data *a = mat4_get(self);
|
|
450
|
+
VALUE ary = rb_ary_new_capa(16);
|
|
451
|
+
for (int i = 0; i < 16; i++) {
|
|
452
|
+
rb_ary_push(ary, DBL2NUM(a->data[i]));
|
|
453
|
+
}
|
|
454
|
+
return ary;
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
VALUE mat4_data(VALUE self) {
|
|
458
|
+
return mat4_to_a(self);
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
VALUE mat4_determinant(VALUE self) {
|
|
462
|
+
Mat4Data *a = mat4_get(self);
|
|
463
|
+
double *m = a->data;
|
|
464
|
+
double det =
|
|
465
|
+
m[0] *
|
|
466
|
+
(m[5] * (m[10] * m[15] - m[11] * m[14]) -
|
|
467
|
+
m[9] * (m[6] * m[15] - m[7] * m[14]) +
|
|
468
|
+
m[13] * (m[6] * m[11] - m[7] * m[10])) -
|
|
469
|
+
m[4] *
|
|
470
|
+
(m[1] * (m[10] * m[15] - m[11] * m[14]) -
|
|
471
|
+
m[9] * (m[2] * m[15] - m[3] * m[14]) +
|
|
472
|
+
m[13] * (m[2] * m[11] - m[3] * m[10])) +
|
|
473
|
+
m[8] *
|
|
474
|
+
(m[1] * (m[6] * m[15] - m[7] * m[14]) -
|
|
475
|
+
m[5] * (m[2] * m[15] - m[3] * m[14]) +
|
|
476
|
+
m[13] * (m[2] * m[7] - m[3] * m[6])) -
|
|
477
|
+
m[12] *
|
|
478
|
+
(m[1] * (m[6] * m[11] - m[7] * m[10]) -
|
|
479
|
+
m[5] * (m[2] * m[11] - m[3] * m[10]) +
|
|
480
|
+
m[9] * (m[2] * m[7] - m[3] * m[6]));
|
|
481
|
+
return DBL2NUM(det);
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
VALUE mat4_add(VALUE self, VALUE other) {
|
|
485
|
+
Mat4Data *a = mat4_get(self);
|
|
486
|
+
Mat4Data *b = mat4_get(other);
|
|
487
|
+
double values[16];
|
|
488
|
+
for (int i = 0; i < 16; i++) {
|
|
489
|
+
values[i] = a->data[i] + b->data[i];
|
|
490
|
+
}
|
|
491
|
+
return mat4_build(rb_obj_class(self), values);
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
VALUE mat4_sub(VALUE self, VALUE other) {
|
|
495
|
+
Mat4Data *a = mat4_get(self);
|
|
496
|
+
Mat4Data *b = mat4_get(other);
|
|
497
|
+
double values[16];
|
|
498
|
+
for (int i = 0; i < 16; i++) {
|
|
499
|
+
values[i] = a->data[i] - b->data[i];
|
|
500
|
+
}
|
|
501
|
+
return mat4_build(rb_obj_class(self), values);
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
VALUE mat4_equal(VALUE self, VALUE other) {
|
|
505
|
+
if (!rb_obj_is_kind_of(other, cMat4)) {
|
|
506
|
+
return Qfalse;
|
|
507
|
+
}
|
|
508
|
+
Mat4Data *a = mat4_get(self);
|
|
509
|
+
Mat4Data *b = mat4_get(other);
|
|
510
|
+
for (int i = 0; i < 16; i++) {
|
|
511
|
+
if (a->data[i] != b->data[i]) {
|
|
512
|
+
return Qfalse;
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
return Qtrue;
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
VALUE mat4_near(int argc, VALUE *argv, VALUE self) {
|
|
519
|
+
VALUE other = Qnil;
|
|
520
|
+
VALUE epsilon = Qnil;
|
|
521
|
+
|
|
522
|
+
rb_scan_args(argc, argv, "11", &other, &epsilon);
|
|
523
|
+
Mat4Data *a = mat4_get(self);
|
|
524
|
+
Mat4Data *b = mat4_get(other);
|
|
525
|
+
double eps = NIL_P(epsilon) ? 1e-6 : value_to_double(epsilon);
|
|
526
|
+
|
|
527
|
+
for (int i = 0; i < 16; i++) {
|
|
528
|
+
if (fabs(a->data[i] - b->data[i]) >= eps) {
|
|
529
|
+
return Qfalse;
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
return Qtrue;
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
VALUE mat4_extract_translation(VALUE self) {
|
|
536
|
+
Mat4Data *a = mat4_get(self);
|
|
537
|
+
VALUE vec3_class = rb_const_get(mLarb, rb_intern("Vec3"));
|
|
538
|
+
return rb_funcall(vec3_class, rb_intern("new"), 3, DBL2NUM(a->data[12]),
|
|
539
|
+
DBL2NUM(a->data[13]), DBL2NUM(a->data[14]));
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
VALUE mat4_extract_scale(VALUE self) {
|
|
543
|
+
Mat4Data *a = mat4_get(self);
|
|
544
|
+
double sx = sqrt(a->data[0] * a->data[0] + a->data[1] * a->data[1] +
|
|
545
|
+
a->data[2] * a->data[2]);
|
|
546
|
+
double sy = sqrt(a->data[4] * a->data[4] + a->data[5] * a->data[5] +
|
|
547
|
+
a->data[6] * a->data[6]);
|
|
548
|
+
double sz = sqrt(a->data[8] * a->data[8] + a->data[9] * a->data[9] +
|
|
549
|
+
a->data[10] * a->data[10]);
|
|
550
|
+
VALUE vec3_class = rb_const_get(mLarb, rb_intern("Vec3"));
|
|
551
|
+
return rb_funcall(vec3_class, rb_intern("new"), 3, DBL2NUM(sx), DBL2NUM(sy),
|
|
552
|
+
DBL2NUM(sz));
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
VALUE mat4_extract_rotation(VALUE self) {
|
|
556
|
+
Mat4Data *a = mat4_get(self);
|
|
557
|
+
VALUE scale = mat4_extract_scale(self);
|
|
558
|
+
double sx = value_to_double(rb_funcall(scale, rb_intern("x"), 0));
|
|
559
|
+
double sy = value_to_double(rb_funcall(scale, rb_intern("y"), 0));
|
|
560
|
+
double sz = value_to_double(rb_funcall(scale, rb_intern("z"), 0));
|
|
561
|
+
|
|
562
|
+
double m00 = a->data[0] / sx;
|
|
563
|
+
double m01 = a->data[1] / sx;
|
|
564
|
+
double m02 = a->data[2] / sx;
|
|
565
|
+
double m10 = a->data[4] / sy;
|
|
566
|
+
double m11 = a->data[5] / sy;
|
|
567
|
+
double m12 = a->data[6] / sy;
|
|
568
|
+
double m20 = a->data[8] / sz;
|
|
569
|
+
double m21 = a->data[9] / sz;
|
|
570
|
+
double m22 = a->data[10] / sz;
|
|
571
|
+
|
|
572
|
+
double trace = m00 + m11 + m22;
|
|
573
|
+
if (trace > 0.0) {
|
|
574
|
+
double s = 0.5 / sqrt(trace + 1.0);
|
|
575
|
+
return rb_funcall(cQuat, rb_intern("new"), 4,
|
|
576
|
+
DBL2NUM((m12 - m21) * s),
|
|
577
|
+
DBL2NUM((m20 - m02) * s),
|
|
578
|
+
DBL2NUM((m01 - m10) * s), DBL2NUM(0.25 / s));
|
|
579
|
+
}
|
|
580
|
+
if (m00 > m11 && m00 > m22) {
|
|
581
|
+
double s = 2.0 * sqrt(1.0 + m00 - m11 - m22);
|
|
582
|
+
return rb_funcall(cQuat, rb_intern("new"), 4, DBL2NUM(0.25 * s),
|
|
583
|
+
DBL2NUM((m10 + m01) / s),
|
|
584
|
+
DBL2NUM((m20 + m02) / s),
|
|
585
|
+
DBL2NUM((m12 - m21) / s));
|
|
586
|
+
}
|
|
587
|
+
if (m11 > m22) {
|
|
588
|
+
double s = 2.0 * sqrt(1.0 + m11 - m00 - m22);
|
|
589
|
+
return rb_funcall(cQuat, rb_intern("new"), 4,
|
|
590
|
+
DBL2NUM((m10 + m01) / s), DBL2NUM(0.25 * s),
|
|
591
|
+
DBL2NUM((m21 + m12) / s),
|
|
592
|
+
DBL2NUM((m20 - m02) / s));
|
|
593
|
+
}
|
|
594
|
+
double s = 2.0 * sqrt(1.0 + m22 - m00 - m11);
|
|
595
|
+
return rb_funcall(cQuat, rb_intern("new"), 4,
|
|
596
|
+
DBL2NUM((m20 + m02) / s),
|
|
597
|
+
DBL2NUM((m21 + m12) / s), DBL2NUM(0.25 * s),
|
|
598
|
+
DBL2NUM((m01 - m10) / s));
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
static VALUE mat4_format_value(double value) {
|
|
602
|
+
return rb_funcall(rb_mKernel, rb_intern("format"), 2,
|
|
603
|
+
rb_str_new_cstr("%8.4f"), DBL2NUM(value));
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
static VALUE mat4_row_string(const double *values, int offset) {
|
|
607
|
+
VALUE str = mat4_format_value(values[offset]);
|
|
608
|
+
for (int i = 1; i < 4; i++) {
|
|
609
|
+
rb_str_cat_cstr(str, ", ");
|
|
610
|
+
rb_str_concat(str, mat4_format_value(values[offset + i]));
|
|
611
|
+
}
|
|
612
|
+
return str;
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
VALUE mat4_inspect(VALUE self) {
|
|
616
|
+
Mat4Data *a = mat4_get(self);
|
|
617
|
+
VALUE str = rb_str_new_cstr("Mat4[\n ");
|
|
618
|
+
rb_str_concat(str, mat4_row_string(a->data, 0));
|
|
619
|
+
rb_str_cat_cstr(str, "\n ");
|
|
620
|
+
rb_str_concat(str, mat4_row_string(a->data, 4));
|
|
621
|
+
rb_str_cat_cstr(str, "\n ");
|
|
622
|
+
rb_str_concat(str, mat4_row_string(a->data, 8));
|
|
623
|
+
rb_str_cat_cstr(str, "\n ");
|
|
624
|
+
rb_str_concat(str, mat4_row_string(a->data, 12));
|
|
625
|
+
rb_str_cat_cstr(str, "\n]");
|
|
626
|
+
return str;
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
void Init_mat4(VALUE module) {
|
|
630
|
+
cMat4 = rb_define_class_under(module, "Mat4", rb_cObject);
|
|
631
|
+
cVec3 = rb_const_get(mLarb, rb_intern("Vec3"));
|
|
632
|
+
cVec4 = rb_const_get(mLarb, rb_intern("Vec4"));
|
|
633
|
+
cQuat = rb_const_get(mLarb, rb_intern("Quat"));
|
|
634
|
+
|
|
635
|
+
rb_define_alloc_func(cMat4, mat4_alloc);
|
|
636
|
+
rb_define_method(cMat4, "initialize", mat4_initialize, -1);
|
|
637
|
+
|
|
638
|
+
rb_define_singleton_method(cMat4, "identity", mat4_class_identity, 0);
|
|
639
|
+
rb_define_singleton_method(cMat4, "zero", mat4_class_zero, 0);
|
|
640
|
+
rb_define_singleton_method(cMat4, "translation", mat4_class_translation, 3);
|
|
641
|
+
rb_define_singleton_method(cMat4, "scaling", mat4_class_scaling, 3);
|
|
642
|
+
rb_define_singleton_method(cMat4, "rotation_x", mat4_class_rotation_x, 1);
|
|
643
|
+
rb_define_singleton_method(cMat4, "rotation_y", mat4_class_rotation_y, 1);
|
|
644
|
+
rb_define_singleton_method(cMat4, "rotation_z", mat4_class_rotation_z, 1);
|
|
645
|
+
rb_define_singleton_method(cMat4, "rotation", mat4_class_rotation, 2);
|
|
646
|
+
rb_define_singleton_method(cMat4, "look_at", mat4_class_look_at, 3);
|
|
647
|
+
rb_define_singleton_method(cMat4, "perspective", mat4_class_perspective, 4);
|
|
648
|
+
rb_define_singleton_method(cMat4, "orthographic", mat4_class_orthographic,
|
|
649
|
+
6);
|
|
650
|
+
rb_define_singleton_method(cMat4, "frustum", mat4_class_frustum, 6);
|
|
651
|
+
rb_define_singleton_method(cMat4, "from_quaternion",
|
|
652
|
+
mat4_class_from_quaternion, 1);
|
|
653
|
+
rb_define_singleton_method(cMat4, "trs", mat4_class_trs, 3);
|
|
654
|
+
|
|
655
|
+
rb_define_method(cMat4, "data", mat4_data, 0);
|
|
656
|
+
rb_define_method(cMat4, "[]", mat4_aref, 1);
|
|
657
|
+
rb_define_method(cMat4, "[]=", mat4_aset, 2);
|
|
658
|
+
rb_define_method(cMat4, "*", mat4_mul, 1);
|
|
659
|
+
rb_define_method(cMat4, "transpose", mat4_transpose, 0);
|
|
660
|
+
rb_define_method(cMat4, "inverse", mat4_inverse, 0);
|
|
661
|
+
rb_define_method(cMat4, "to_a", mat4_to_a, 0);
|
|
662
|
+
rb_define_method(cMat4, "determinant", mat4_determinant, 0);
|
|
663
|
+
rb_define_method(cMat4, "+", mat4_add, 1);
|
|
664
|
+
rb_define_method(cMat4, "-", mat4_sub, 1);
|
|
665
|
+
rb_define_method(cMat4, "==", mat4_equal, 1);
|
|
666
|
+
rb_define_method(cMat4, "near?", mat4_near, -1);
|
|
667
|
+
rb_define_method(cMat4, "extract_translation", mat4_extract_translation, 0);
|
|
668
|
+
rb_define_method(cMat4, "extract_scale", mat4_extract_scale, 0);
|
|
669
|
+
rb_define_method(cMat4, "extract_rotation", mat4_extract_rotation, 0);
|
|
670
|
+
rb_define_method(cMat4, "inspect", mat4_inspect, 0);
|
|
671
|
+
}
|
data/ext/larb/mat4.h
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
#ifndef MAT4_H
|
|
2
|
+
#define MAT4_H
|
|
3
|
+
|
|
4
|
+
#include "larb.h"
|
|
5
|
+
|
|
6
|
+
typedef struct {
|
|
7
|
+
double data[16];
|
|
8
|
+
} Mat4Data;
|
|
9
|
+
|
|
10
|
+
void Init_mat4(VALUE module);
|
|
11
|
+
VALUE mat4_alloc(VALUE klass);
|
|
12
|
+
VALUE mat4_initialize(int argc, VALUE *argv, VALUE self);
|
|
13
|
+
|
|
14
|
+
VALUE mat4_aref(VALUE self, VALUE index);
|
|
15
|
+
VALUE mat4_aset(VALUE self, VALUE index, VALUE value);
|
|
16
|
+
VALUE mat4_mul(VALUE self, VALUE other);
|
|
17
|
+
VALUE mat4_transpose(VALUE self);
|
|
18
|
+
VALUE mat4_inverse(VALUE self);
|
|
19
|
+
VALUE mat4_to_a(VALUE self);
|
|
20
|
+
VALUE mat4_determinant(VALUE self);
|
|
21
|
+
VALUE mat4_add(VALUE self, VALUE other);
|
|
22
|
+
VALUE mat4_sub(VALUE self, VALUE other);
|
|
23
|
+
VALUE mat4_equal(VALUE self, VALUE other);
|
|
24
|
+
VALUE mat4_near(int argc, VALUE *argv, VALUE self);
|
|
25
|
+
VALUE mat4_extract_translation(VALUE self);
|
|
26
|
+
VALUE mat4_extract_scale(VALUE self);
|
|
27
|
+
VALUE mat4_extract_rotation(VALUE self);
|
|
28
|
+
VALUE mat4_inspect(VALUE self);
|
|
29
|
+
VALUE mat4_data(VALUE self);
|
|
30
|
+
|
|
31
|
+
#endif
|