numerix 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 +7 -0
- data/.gitignore +18 -0
- data/.travis.yml +5 -0
- data/.yardopts +5 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +6 -0
- data/LICENSE.txt +21 -0
- data/README.md +66 -0
- data/Rakefile +18 -0
- data/TODO.txt +25 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/ext/numerix/common.h +107 -0
- data/ext/numerix/extconf.rb +3 -0
- data/ext/numerix/matrix3x2.c +638 -0
- data/ext/numerix/matrix3x2.h +52 -0
- data/ext/numerix/matrix4x4.c +1807 -0
- data/ext/numerix/matrix4x4.h +90 -0
- data/ext/numerix/matrix_base.c +307 -0
- data/ext/numerix/matrix_base.h +70 -0
- data/ext/numerix/numerix.c +33 -0
- data/ext/numerix/numerix.h +19 -0
- data/ext/numerix/plane.c +311 -0
- data/ext/numerix/plane.h +34 -0
- data/ext/numerix/quaternion.c +712 -0
- data/ext/numerix/quaternion.h +53 -0
- data/ext/numerix/structure.c +154 -0
- data/ext/numerix/structure.h +24 -0
- data/ext/numerix/vector.c +326 -0
- data/ext/numerix/vector.h +57 -0
- data/ext/numerix/vector2.c +641 -0
- data/ext/numerix/vector2.h +64 -0
- data/ext/numerix/vector3.c +805 -0
- data/ext/numerix/vector3.h +68 -0
- data/ext/numerix/vector4.c +727 -0
- data/ext/numerix/vector4.h +63 -0
- data/ext/numerix/vector_base.c +94 -0
- data/ext/numerix/vector_base.h +30 -0
- data/extra/numerix128.png +0 -0
- data/extra/numerix24.png +0 -0
- data/extra/numerix32.png +0 -0
- data/extra/numerix320.png +0 -0
- data/extra/numerix48.png +0 -0
- data/extra/numerix96.png +0 -0
- data/lib/numerix/error.rb +36 -0
- data/lib/numerix/matrix3x2.rb +420 -0
- data/lib/numerix/matrix4x4.rb +676 -0
- data/lib/numerix/matrix_base.rb +14 -0
- data/lib/numerix/plane.rb +154 -0
- data/lib/numerix/quaternion.rb +355 -0
- data/lib/numerix/structure.rb +124 -0
- data/lib/numerix/vector.rb +13 -0
- data/lib/numerix/vector2.rb +534 -0
- data/lib/numerix/vector3.rb +572 -0
- data/lib/numerix/vector4.rb +551 -0
- data/lib/numerix/vector_base.rb +14 -0
- data/lib/numerix/version.rb +6 -0
- data/lib/numerix.rb +10 -0
- data/numerix.gemspec +30 -0
- metadata +167 -0
@@ -0,0 +1,638 @@
|
|
1
|
+
|
2
|
+
#include "matrix3x2.h"
|
3
|
+
|
4
|
+
void Init_matrix3x2(VALUE outer) {
|
5
|
+
rb_define_alloc_func(rb_cMatrix3x2, rb_matrix3x2_allocate);
|
6
|
+
rb_define_method(rb_cMatrix3x2, "initialize", rb_matrix3x2_initialize, -1);
|
7
|
+
|
8
|
+
// Instance
|
9
|
+
rb_define_method(rb_cMatrix3x2, "identity?", rb_matrix3x2_identity_p, 0);
|
10
|
+
rb_define_method(rb_cMatrix3x2, "translation", rb_matrix3x2_translation, 0);
|
11
|
+
rb_define_method(rb_cMatrix3x2, "translation=", rb_matrix3x2_translation_set, 1);
|
12
|
+
rb_define_method(rb_cMatrix3x2, "determinant", rb_matrix3x2_determinant, 0);
|
13
|
+
rb_define_method(rb_cMatrix3x2, "row", rb_matrix3x2_row, 1);
|
14
|
+
rb_define_method(rb_cMatrix3x2, "column", rb_matrix3x2_column, 1);
|
15
|
+
rb_define_method(rb_cMatrix3x2, "each_row", rb_matrix3x2_each_row, 0);
|
16
|
+
rb_define_method(rb_cMatrix3x2, "each_column", rb_matrix3x2_each_column, 0);
|
17
|
+
rb_define_method(rb_cMatrix3x2, "invert", rb_matrix3x2_invert, 0);
|
18
|
+
rb_define_method(rb_cMatrix3x2, "lerp", rb_matrix3x2_lerp, 2);
|
19
|
+
rb_define_method(rb_cMatrix3x2, "lerp!", rb_matrix3x2_lerp_bang, 2);
|
20
|
+
rb_define_method(rb_cMatrix3x2, "map", rb_matrix3x2_map, 0);
|
21
|
+
rb_define_method(rb_cMatrix3x2, "map!", rb_matrix3x2_map_bang, 0);
|
22
|
+
|
23
|
+
// Alias
|
24
|
+
rb_define_alias(rb_cMatrix3x2, "collect", "map");
|
25
|
+
rb_define_alias(rb_cMatrix3x2, "collect!", "map!");
|
26
|
+
|
27
|
+
// Conversion
|
28
|
+
rb_define_method(rb_cMatrix3x2, "to_s", rb_matrix3x2_to_s, 0);
|
29
|
+
rb_define_method(rb_cMatrix3x2, "to_a", rb_matrix3x2_to_a, 0);
|
30
|
+
rb_define_method(rb_cMatrix3x2, "to_h", rb_matrix3x2_to_h, 0);
|
31
|
+
|
32
|
+
// Operators
|
33
|
+
rb_define_method(rb_cMatrix3x2, "-@", rb_matrix3x2_negate, 0);
|
34
|
+
rb_define_method(rb_cMatrix3x2, "+", rb_matrix3x2_add, 1);
|
35
|
+
rb_define_method(rb_cMatrix3x2, "-", rb_matrix3x2_subtract, 1);
|
36
|
+
rb_define_method(rb_cMatrix3x2, "*", rb_matrix3x2_multiply, 1);
|
37
|
+
rb_define_method(rb_cMatrix3x2, "==", rb_matrix3x2_equal, 1);
|
38
|
+
rb_define_method(rb_cMatrix3x2, "[]", rb_matrix3x2_aref, -1);
|
39
|
+
rb_define_method(rb_cMatrix3x2, "[]=", rb_matrix3x2_aset, -1);
|
40
|
+
rb_define_method(rb_cMatrix3x2, "**", rb_matrix3x2_pow, 1);
|
41
|
+
|
42
|
+
// Class
|
43
|
+
rb_define_singleton_method(rb_cMatrix3x2, "identity", rb_matrix3x2_identity, 0);
|
44
|
+
rb_define_singleton_method(rb_cMatrix3x2, "create_translation", rb_matrix3x2_create_translation, -1);
|
45
|
+
rb_define_singleton_method(rb_cMatrix3x2, "create_scale", rb_matrix3x2_create_scale, -1);
|
46
|
+
rb_define_singleton_method(rb_cMatrix3x2, "create_skew", rb_matrix3x2_create_skew, -1);
|
47
|
+
rb_define_singleton_method(rb_cMatrix3x2, "create_rotation", rb_matrix3x2_create_rotation, -1);
|
48
|
+
rb_define_singleton_method(rb_cMatrix3x2, "lerp", rb_matrix3x2_lerp_s, 3);
|
49
|
+
}
|
50
|
+
|
51
|
+
static VALUE rb_matrix3x2_allocate(VALUE klass) {
|
52
|
+
Matrix3x2 *m = ALLOC(Matrix3x2);
|
53
|
+
memset(m, 0, sizeof(Matrix3x2));
|
54
|
+
return NUMERIX_WRAP(klass, m);
|
55
|
+
}
|
56
|
+
|
57
|
+
VALUE rb_matrix3x2_initialize(int argc, VALUE *argv, VALUE self) {
|
58
|
+
MATRIX3X2();
|
59
|
+
if (argc == 6) {
|
60
|
+
m->m11 = NUM2FLT(argv[0]);
|
61
|
+
m->m12 = NUM2FLT(argv[1]);
|
62
|
+
m->m21 = NUM2FLT(argv[2]);
|
63
|
+
m->m22 = NUM2FLT(argv[3]);
|
64
|
+
m->m31 = NUM2FLT(argv[4]);
|
65
|
+
m->m32 = NUM2FLT(argv[5]);
|
66
|
+
} else if (argc != 0)
|
67
|
+
rb_raise(rb_eArgError, "wrong number of arguments (given %d, expected 0, 6)", argc);
|
68
|
+
|
69
|
+
return Qnil;
|
70
|
+
}
|
71
|
+
|
72
|
+
VALUE rb_matrix3x2_identity_p(VALUE self) {
|
73
|
+
MATRIX3X2();
|
74
|
+
// Check diagonal element first for early out.
|
75
|
+
return m->m11 == 1.0f && m->m22 == 1.0f && m->m12 == 0.0f &&
|
76
|
+
m->m21 == 0.0f && m->m31 == 0.0f && m->m32 == 0.0f
|
77
|
+
? Qtrue
|
78
|
+
: Qfalse;
|
79
|
+
}
|
80
|
+
|
81
|
+
VALUE rb_matrix3x2_identity(VALUE klass) {
|
82
|
+
Matrix3x2 *m = ALLOC(Matrix3x2);
|
83
|
+
m->m11 = 1.0f;
|
84
|
+
m->m12 = 0.0f;
|
85
|
+
m->m21 = 0.0f;
|
86
|
+
m->m22 = 1.0f;
|
87
|
+
m->m31 = 0.0f;
|
88
|
+
m->m32 = 0.0f;
|
89
|
+
return NUMERIX_WRAP(klass, m);
|
90
|
+
}
|
91
|
+
|
92
|
+
VALUE rb_matrix3x2_translation(VALUE self) {
|
93
|
+
MATRIX3X2();
|
94
|
+
Vector2 *v = ALLOC(Vector2);
|
95
|
+
v->x = m->m31;
|
96
|
+
v->y = m->m32;
|
97
|
+
return NUMERIX_WRAP(rb_cVector2, v);
|
98
|
+
}
|
99
|
+
|
100
|
+
VALUE rb_matrix3x2_translation_set(VALUE self, VALUE value) {
|
101
|
+
MATRIX3X2();
|
102
|
+
Vector2 *v;
|
103
|
+
Data_Get_Struct(value, Vector2, v);
|
104
|
+
m->m31 = v->x;
|
105
|
+
m->m32 = v->y;
|
106
|
+
return value;
|
107
|
+
}
|
108
|
+
|
109
|
+
VALUE rb_matrix3x2_create_translation(int argc, VALUE *argv, VALUE klass) {
|
110
|
+
Matrix3x2 *result = ALLOC(Matrix3x2);
|
111
|
+
|
112
|
+
if (argc == 1) {
|
113
|
+
Vector2 *v;
|
114
|
+
Data_Get_Struct(argv[0], Vector2, v);
|
115
|
+
result->m31 = v->x;
|
116
|
+
result->m32 = v->y;
|
117
|
+
|
118
|
+
} else if (argc == 2) {
|
119
|
+
result->m31 = NUM2FLT(argv[0]);
|
120
|
+
result->m32 = NUM2FLT(argv[1]);
|
121
|
+
} else
|
122
|
+
rb_raise(rb_eArgError, "wrong number of arguments (given %d, expected 1, 2)", argc);
|
123
|
+
|
124
|
+
result->m11 = 1.0f;
|
125
|
+
result->m12 = 0.0f;
|
126
|
+
result->m21 = 0.0f;
|
127
|
+
result->m22 = 1.0f;
|
128
|
+
|
129
|
+
return NUMERIX_WRAP(klass, result);
|
130
|
+
}
|
131
|
+
|
132
|
+
VALUE rb_matrix3x2_negate(VALUE self) {
|
133
|
+
MATRIX4X4();
|
134
|
+
Matrix3x2 *result = ALLOC(Matrix3x2);
|
135
|
+
|
136
|
+
result->m11 = -m->m11;
|
137
|
+
result->m12 = -m->m12;
|
138
|
+
result->m21 = -m->m21;
|
139
|
+
result->m22 = -m->m22;
|
140
|
+
result->m31 = -m->m31;
|
141
|
+
result->m32 = -m->m32;
|
142
|
+
|
143
|
+
return NUMERIX_WRAP(CLASS_OF(self), result);
|
144
|
+
}
|
145
|
+
|
146
|
+
VALUE rb_matrix3x2_add(VALUE self, VALUE other) {
|
147
|
+
Matrix3x2 *m1, *m2, *result;
|
148
|
+
Data_Get_Struct(self, Matrix3x2, m1);
|
149
|
+
Data_Get_Struct(other, Matrix3x2, m2);
|
150
|
+
result = ALLOC(Matrix3x2);
|
151
|
+
|
152
|
+
result->m11 = m1->m11 + m2->m11;
|
153
|
+
result->m12 = m1->m12 + m2->m12;
|
154
|
+
result->m21 = m1->m21 + m2->m21;
|
155
|
+
result->m22 = m1->m22 + m2->m22;
|
156
|
+
result->m31 = m1->m31 + m2->m31;
|
157
|
+
result->m32 = m1->m32 + m2->m32;
|
158
|
+
|
159
|
+
return NUMERIX_WRAP(CLASS_OF(self), result);
|
160
|
+
}
|
161
|
+
|
162
|
+
VALUE rb_matrix3x2_subtract(VALUE self, VALUE other) {
|
163
|
+
Matrix3x2 *m1, *m2, *result;
|
164
|
+
Data_Get_Struct(self, Matrix3x2, m1);
|
165
|
+
Data_Get_Struct(other, Matrix3x2, m2);
|
166
|
+
result = ALLOC(Matrix3x2);
|
167
|
+
|
168
|
+
result->m11 = m1->m11 - m2->m11;
|
169
|
+
result->m12 = m1->m12 - m2->m12;
|
170
|
+
result->m21 = m1->m21 - m2->m21;
|
171
|
+
result->m22 = m1->m22 - m2->m22;
|
172
|
+
result->m31 = m1->m31 - m2->m31;
|
173
|
+
result->m32 = m1->m32 - m2->m32;
|
174
|
+
|
175
|
+
return NUMERIX_WRAP(CLASS_OF(self), result);
|
176
|
+
}
|
177
|
+
|
178
|
+
VALUE rb_matrix3x2_multiply(VALUE self, VALUE other) {
|
179
|
+
Matrix3x2 *m1, *result;
|
180
|
+
Data_Get_Struct(self, Matrix3x2, m1);
|
181
|
+
result = ALLOC(Matrix3x2);
|
182
|
+
VALUE klass = CLASS_OF(self);
|
183
|
+
if (NUMERIX_TYPE_P(other, klass)) {
|
184
|
+
Matrix3x2 *m2, *result;
|
185
|
+
Data_Get_Struct(other, Matrix3x2, m2);
|
186
|
+
|
187
|
+
// First row
|
188
|
+
result->m11 = m1->m11 * m2->m11 + m1->m12 * m2->m21;
|
189
|
+
result->m12 = m1->m11 * m2->m12 + m1->m12 * m2->m22;
|
190
|
+
|
191
|
+
// Second row
|
192
|
+
result->m21 = m1->m21 * m2->m11 + m1->m22 * m2->m21;
|
193
|
+
result->m22 = m1->m21 * m2->m12 + m1->m22 * m2->m22;
|
194
|
+
|
195
|
+
// Third row
|
196
|
+
result->m31 = m1->m31 * m2->m11 + m1->m32 * m2->m21 + m2->m31;
|
197
|
+
result->m32 = m1->m31 * m2->m12 + m1->m32 * m2->m22 + m2->m32;
|
198
|
+
} else {
|
199
|
+
float scalar = NUM2FLT(other);
|
200
|
+
result->m11 = m1->m11 * scalar;
|
201
|
+
result->m12 = m1->m12 * scalar;
|
202
|
+
result->m21 = m1->m21 * scalar;
|
203
|
+
result->m22 = m1->m22 * scalar;
|
204
|
+
result->m31 = m1->m31 * scalar;
|
205
|
+
result->m32 = m1->m32 * scalar;
|
206
|
+
}
|
207
|
+
|
208
|
+
return NUMERIX_WRAP(klass, result);
|
209
|
+
}
|
210
|
+
|
211
|
+
VALUE rb_matrix3x2_pow(VALUE self, VALUE exponent) {
|
212
|
+
struct RData *rdata = RDATA(self);
|
213
|
+
const int count = 6;
|
214
|
+
float *result = ruby_xmalloc(sizeof(float) * count);
|
215
|
+
float *m = (float *)rdata->data;
|
216
|
+
float e = fabsf(NUM2FLT(exponent));
|
217
|
+
for (int i = 0; i < count; i++)
|
218
|
+
result[i] = powf(fabsf(m[i]), e);
|
219
|
+
|
220
|
+
return NUMERIX_WRAP(rdata->basic.klass, result);
|
221
|
+
}
|
222
|
+
|
223
|
+
VALUE rb_matrix3x2_equal(VALUE self, VALUE other) {
|
224
|
+
if (CLASS_OF(other) != CLASS_OF(self))
|
225
|
+
return Qfalse;
|
226
|
+
Matrix3x2 *m1, *m2;
|
227
|
+
Data_Get_Struct(self, Matrix3x2, m1);
|
228
|
+
Data_Get_Struct(other, Matrix3x2, m2);
|
229
|
+
return FLT_EQUAL(m1->m11, m2->m11) && FLT_EQUAL(m1->m12, m2->m12) &&
|
230
|
+
FLT_EQUAL(m1->m21, m2->m21) && FLT_EQUAL(m1->m22, m2->m22) &&
|
231
|
+
FLT_EQUAL(m1->m31, m2->m31) && FLT_EQUAL(m1->m32, m2->m32)
|
232
|
+
? Qtrue
|
233
|
+
: Qfalse;
|
234
|
+
}
|
235
|
+
|
236
|
+
VALUE rb_matrix3x2_row(VALUE self, VALUE row) {
|
237
|
+
MATRIX3X2();
|
238
|
+
VALUE args = rb_ary_new_capa(4);
|
239
|
+
int r = NUM2INT(row);
|
240
|
+
switch (r) {
|
241
|
+
case 0: {
|
242
|
+
rb_ary_push(args, DBL2NUM(m->m11));
|
243
|
+
rb_ary_push(args, DBL2NUM(m->m12));
|
244
|
+
break;
|
245
|
+
}
|
246
|
+
case 1: {
|
247
|
+
rb_ary_push(args, DBL2NUM(m->m21));
|
248
|
+
rb_ary_push(args, DBL2NUM(m->m22));
|
249
|
+
break;
|
250
|
+
}
|
251
|
+
case 2: {
|
252
|
+
rb_ary_push(args, DBL2NUM(m->m31));
|
253
|
+
rb_ary_push(args, DBL2NUM(m->m32));
|
254
|
+
break;
|
255
|
+
}
|
256
|
+
default:
|
257
|
+
break;
|
258
|
+
}
|
259
|
+
return args;
|
260
|
+
}
|
261
|
+
|
262
|
+
VALUE rb_matrix3x2_column(VALUE self, VALUE column) {
|
263
|
+
MATRIX3X2();
|
264
|
+
VALUE args = rb_ary_new_capa(3);
|
265
|
+
int c = NUM2INT(column);
|
266
|
+
if (c == 0) {
|
267
|
+
rb_ary_push(args, DBL2NUM(m->m11));
|
268
|
+
rb_ary_push(args, DBL2NUM(m->m21));
|
269
|
+
rb_ary_push(args, DBL2NUM(m->m31));
|
270
|
+
} else if (c == 1) {
|
271
|
+
rb_ary_push(args, DBL2NUM(m->m12));
|
272
|
+
rb_ary_push(args, DBL2NUM(m->m22));
|
273
|
+
rb_ary_push(args, DBL2NUM(m->m32));
|
274
|
+
}
|
275
|
+
return args;
|
276
|
+
}
|
277
|
+
|
278
|
+
VALUE rb_matrix3x2_map(VALUE self) {
|
279
|
+
const int count = 6;
|
280
|
+
RETURN_SIZED_ENUMERATOR(self, 0, 0, count);
|
281
|
+
|
282
|
+
struct RData *rdata = RDATA(self);
|
283
|
+
float *flt = (float *)rdata->data;
|
284
|
+
float *result = (float *)ruby_xmalloc(count * sizeof(float));
|
285
|
+
|
286
|
+
for (int i = 0; i < count; i++)
|
287
|
+
result[i] = NUM2FLT(rb_yield(DBL2NUM(flt[i])));
|
288
|
+
|
289
|
+
return NUMERIX_WRAP(rdata->basic.klass, result);
|
290
|
+
}
|
291
|
+
|
292
|
+
VALUE rb_matrix3x2_map_bang(VALUE self) {
|
293
|
+
const int count = 6;
|
294
|
+
RETURN_SIZED_ENUMERATOR(self, 0, 0, count);
|
295
|
+
|
296
|
+
float *flt = (float *)RDATA(self)->data;
|
297
|
+
for (int i = 0; i < count; i++)
|
298
|
+
flt[i] = NUM2FLT(rb_yield(DBL2NUM(flt[i])));
|
299
|
+
|
300
|
+
return self;
|
301
|
+
}
|
302
|
+
|
303
|
+
VALUE rb_matrix3x2_to_s(VALUE self) {
|
304
|
+
MATRIX3X2();
|
305
|
+
return rb_sprintf("{{%f, %f}, {%f, %f}, {%f, %f}}", m->m11, m->m12, m->m21, m->m22, m->m31, m->m32);
|
306
|
+
}
|
307
|
+
|
308
|
+
VALUE rb_matrix3x2_to_a(VALUE self) {
|
309
|
+
MATRIX3X2();
|
310
|
+
VALUE array = rb_ary_new_capa(3);
|
311
|
+
// Row 1
|
312
|
+
VALUE r1 = rb_ary_new_capa(2);
|
313
|
+
rb_ary_store(r1, 0, DBL2NUM(m->m11));
|
314
|
+
rb_ary_store(r1, 1, DBL2NUM(m->m12));
|
315
|
+
rb_ary_push(array, r1);
|
316
|
+
// Row 2
|
317
|
+
VALUE r2 = rb_ary_new_capa(2);
|
318
|
+
rb_ary_store(r2, 0, DBL2NUM(m->m21));
|
319
|
+
rb_ary_store(r2, 1, DBL2NUM(m->m22));
|
320
|
+
rb_ary_push(array, r2);
|
321
|
+
// Row 3
|
322
|
+
VALUE r3 = rb_ary_new_capa(2);
|
323
|
+
rb_ary_store(r3, 0, DBL2NUM(m->m31));
|
324
|
+
rb_ary_store(r3, 1, DBL2NUM(m->m32));
|
325
|
+
rb_ary_push(array, r3);
|
326
|
+
return array;
|
327
|
+
}
|
328
|
+
|
329
|
+
VALUE rb_matrix3x2_to_h(VALUE self) {
|
330
|
+
MATRIX3X2();
|
331
|
+
VALUE hash = rb_hash_new();
|
332
|
+
rb_hash_aset(hash, ID2SYM(rb_intern("m11")), DBL2NUM(m->m11));
|
333
|
+
rb_hash_aset(hash, ID2SYM(rb_intern("m12")), DBL2NUM(m->m12));
|
334
|
+
rb_hash_aset(hash, ID2SYM(rb_intern("m21")), DBL2NUM(m->m21));
|
335
|
+
rb_hash_aset(hash, ID2SYM(rb_intern("m22")), DBL2NUM(m->m22));
|
336
|
+
rb_hash_aset(hash, ID2SYM(rb_intern("m31")), DBL2NUM(m->m31));
|
337
|
+
rb_hash_aset(hash, ID2SYM(rb_intern("m32")), DBL2NUM(m->m32));
|
338
|
+
return hash;
|
339
|
+
}
|
340
|
+
|
341
|
+
VALUE rb_matrix3x2_create_scale(int argc, VALUE *argv, VALUE klass) {
|
342
|
+
Matrix3x2 *result = ALLOC(Matrix3x2);
|
343
|
+
result->m12 = 0.0f;
|
344
|
+
result->m21 = 0.0f;
|
345
|
+
switch (argc) {
|
346
|
+
case 1: {
|
347
|
+
result->m31 = 0.0f;
|
348
|
+
result->m32 = 0.0f;
|
349
|
+
if (NUMERIX_TYPE_P(argv[0], rb_cVector2)) {
|
350
|
+
Vector2 *vscale;
|
351
|
+
Data_Get_Struct(argv[0], Vector2, vscale);
|
352
|
+
result->m11 = vscale->x;
|
353
|
+
result->m22 = vscale->y;
|
354
|
+
} else {
|
355
|
+
float scale = NUM2FLT(argv[0]);
|
356
|
+
result->m11 = scale;
|
357
|
+
result->m22 = scale;
|
358
|
+
}
|
359
|
+
}
|
360
|
+
case 2: {
|
361
|
+
if (NUMERIX_TYPE_P(argv[0], rb_cVector2)) {
|
362
|
+
Vector2 *v1, *v2;
|
363
|
+
Data_Get_Struct(argv[0], Vector2, v1);
|
364
|
+
Data_Get_Struct(argv[1], Vector2, v2);
|
365
|
+
result->m11 = v1->x;
|
366
|
+
result->m22 = v1->y;
|
367
|
+
result->m31 = v2->x * (1.0f - v1->x);
|
368
|
+
result->m32 = v2->y * (1.0f - v1->y);
|
369
|
+
} else {
|
370
|
+
if (NUMERIX_TYPE_P(argv[1], rb_cVector2)) {
|
371
|
+
float s = NUM2FLT(argv[0]);
|
372
|
+
Vector2 *cp;
|
373
|
+
Data_Get_Struct(argv[1], Vector2, cp);
|
374
|
+
result->m11 = s;
|
375
|
+
result->m22 = s;
|
376
|
+
result->m31 = cp->x * (1.0f - s);
|
377
|
+
result->m32 = cp->y * (1.0f - s);
|
378
|
+
} else {
|
379
|
+
result->m11 = NUM2FLT(argv[0]);
|
380
|
+
result->m22 = NUM2FLT(argv[1]);
|
381
|
+
result->m31 = 0.0f;
|
382
|
+
result->m32 = 0.0f;
|
383
|
+
}
|
384
|
+
}
|
385
|
+
break;
|
386
|
+
}
|
387
|
+
case 3: {
|
388
|
+
Vector2 *vec2;
|
389
|
+
Data_Get_Struct(argv[2], Vector2, vec2);
|
390
|
+
float xscale = NUM2FLT(argv[0]);
|
391
|
+
float yscale = NUM2FLT(argv[1]);
|
392
|
+
|
393
|
+
result->m11 = xscale;
|
394
|
+
result->m22 = yscale;
|
395
|
+
result->m31 = vec2->x * (1.0f - xscale);
|
396
|
+
result->m32 = vec2->y * (1.0f - yscale);
|
397
|
+
}
|
398
|
+
default:
|
399
|
+
rb_raise(rb_eArgError, "wrong number of arguments (given %d, expected 1, 2, 3)", argc);
|
400
|
+
}
|
401
|
+
|
402
|
+
return NUMERIX_WRAP(klass, result);
|
403
|
+
}
|
404
|
+
|
405
|
+
VALUE rb_matrix3x2_create_skew(int argc, VALUE *argv, VALUE klass) {
|
406
|
+
if (argc != 2 && argc != 3)
|
407
|
+
rb_raise(rb_eArgError, "wrong number of arguments (given %d, expected 2, 3)", argc);
|
408
|
+
|
409
|
+
Matrix3x2 *result = ALLOC(Matrix3x2);
|
410
|
+
|
411
|
+
float xTan = tanf(NUM2FLT(argv[0]));
|
412
|
+
float yTan = tanf(NUM2FLT(argv[1]));
|
413
|
+
|
414
|
+
result->m12 = yTan;
|
415
|
+
result->m21 = xTan;
|
416
|
+
result->m11 = 1.0f;
|
417
|
+
result->m22 = 1.0f;
|
418
|
+
|
419
|
+
if (argc == 3) {
|
420
|
+
Vector2 *cp;
|
421
|
+
Data_Get_Struct(argv[2], Vector2, cp);
|
422
|
+
result->m31 = -cp->x * xTan;
|
423
|
+
result->m32 = -cp->y * yTan;
|
424
|
+
} else {
|
425
|
+
result->m31 = 0.0f;
|
426
|
+
result->m32 = 0.0f;
|
427
|
+
}
|
428
|
+
|
429
|
+
return NUMERIX_WRAP(klass, result);
|
430
|
+
}
|
431
|
+
|
432
|
+
VALUE rb_matrix3x2_create_rotation(int argc, VALUE *argv, VALUE klass) {
|
433
|
+
if (argc != 1 && argc != 2)
|
434
|
+
rb_raise(rb_eArgError, "wrong number of arguments (given %d, expected 1, 2)", argc);
|
435
|
+
|
436
|
+
Matrix3x2 *result = ALLOC(Matrix3x2);
|
437
|
+
float radians = remainderf(NUM2FLT(argv[0]), NUMERIX_PI * 2.0f);
|
438
|
+
const float epsilon = 0.001f * NUMERIX_PI / 180.0f; // 0.1% of a degree
|
439
|
+
float c, s;
|
440
|
+
|
441
|
+
if (radians > -epsilon && radians < epsilon) {
|
442
|
+
// Exact case for zero rotation.
|
443
|
+
c = 1;
|
444
|
+
s = 0;
|
445
|
+
} else if (radians > NUMERIX_HALF_PI - epsilon && radians < NUMERIX_HALF_PI + epsilon) {
|
446
|
+
// Exact case for 90 degree rotation.
|
447
|
+
c = 0;
|
448
|
+
s = 1;
|
449
|
+
} else if (radians < -NUMERIX_PI + epsilon || radians > NUMERIX_PI - epsilon) {
|
450
|
+
// Exact case for 180 degree rotation.
|
451
|
+
c = -1;
|
452
|
+
s = 0;
|
453
|
+
} else if (radians > -NUMERIX_HALF_PI - epsilon && radians < -NUMERIX_HALF_PI + epsilon) {
|
454
|
+
// Exact case for 270 degree rotation.
|
455
|
+
c = 0;
|
456
|
+
s = -1;
|
457
|
+
} else {
|
458
|
+
// Arbitrary rotation.
|
459
|
+
c = cosf(radians);
|
460
|
+
s = sinf(radians);
|
461
|
+
}
|
462
|
+
|
463
|
+
// [ c s ]
|
464
|
+
// [ -s c ]
|
465
|
+
// [ 0 0 ]
|
466
|
+
result->m11 = c;
|
467
|
+
result->m12 = s;
|
468
|
+
result->m21 = -s;
|
469
|
+
result->m22 = c;
|
470
|
+
if (argc == 2) {
|
471
|
+
Vector2 *cp;
|
472
|
+
Data_Get_Struct(argv[1], Vector2, cp);
|
473
|
+
result->m31 = cp->x * (1.0f - c) + cp->y * s;
|
474
|
+
result->m32 = cp->y * (1.0f - c) - cp->x * s;
|
475
|
+
} else {
|
476
|
+
result->m31 = 0.0f;
|
477
|
+
result->m32 = 0.0f;
|
478
|
+
}
|
479
|
+
|
480
|
+
return NUMERIX_WRAP(klass, result);
|
481
|
+
}
|
482
|
+
|
483
|
+
VALUE rb_matrix3x2_determinant(VALUE self) {
|
484
|
+
MATRIX3X2();
|
485
|
+
// There isn't actually any such thing as a determinant for a non-square matrix,
|
486
|
+
// but this 3x2 type is really just an optimization of a 3x3 where we happen to
|
487
|
+
// know the rightmost column is always (0, 0, 1). So we expand to 3x3 format:
|
488
|
+
//
|
489
|
+
// [ M11, M12, 0 ]
|
490
|
+
// [ M21, M22, 0 ]
|
491
|
+
// [ M31, M32, 1 ]
|
492
|
+
//
|
493
|
+
// Sum the diagonal products:
|
494
|
+
// (M11 * M22 * 1) + (M12 * 0 * M31) + (0 * M21 * M32)
|
495
|
+
//
|
496
|
+
// Subtract the opposite diagonal products:
|
497
|
+
// (M31 * M22 * 0) + (M32 * 0 * M11) + (1 * M21 * M12)
|
498
|
+
//
|
499
|
+
// Collapse out the constants and oh look, this is just a 2x2 determinant!
|
500
|
+
return DBL2NUM((m->m11 * m->m22) - (m->m21 * m->m12));
|
501
|
+
}
|
502
|
+
|
503
|
+
VALUE rb_matrix3x2_each_row(VALUE self) {
|
504
|
+
MATRIX3X2();
|
505
|
+
for (int i = 0; i < 3; i++) {
|
506
|
+
VALUE index = INT2NUM(i);
|
507
|
+
rb_yield(rb_matrix3x2_row(self, index));
|
508
|
+
}
|
509
|
+
return self;
|
510
|
+
}
|
511
|
+
|
512
|
+
VALUE rb_matrix3x2_each_column(VALUE self) {
|
513
|
+
MATRIX3X2();
|
514
|
+
for (int i = 0; i < 2; i++) {
|
515
|
+
VALUE index = INT2NUM(i);
|
516
|
+
rb_yield(rb_matrix3x2_column(self, index));
|
517
|
+
}
|
518
|
+
return self;
|
519
|
+
}
|
520
|
+
|
521
|
+
VALUE rb_matrix3x2_aref(int argc, VALUE *argv, VALUE self) {
|
522
|
+
if (argc == 1) {
|
523
|
+
return rb_call_super(1, argv);
|
524
|
+
} else if (argc == 2) {
|
525
|
+
int r = NUM2INT(argv[0]);
|
526
|
+
int c = NUM2INT(argv[1]);
|
527
|
+
if (r < 0 || r > 2 || c < 0 || c > 1)
|
528
|
+
return Qnil;
|
529
|
+
VALUE arg = INT2NUM(r + (c * 4));
|
530
|
+
return rb_call_super(1, &arg);
|
531
|
+
}
|
532
|
+
rb_raise(rb_eArgError, "wrong number of arguments (given %d, expected 1, 2)", argc);
|
533
|
+
return Qnil;
|
534
|
+
}
|
535
|
+
|
536
|
+
VALUE rb_matrix3x2_aset(int argc, VALUE *argv, VALUE self) {
|
537
|
+
if (argc == 2) {
|
538
|
+
return rb_call_super(2, argv);
|
539
|
+
} else if (argc == 3) {
|
540
|
+
int r = NUM2INT(argv[0]);
|
541
|
+
int c = NUM2INT(argv[1]);
|
542
|
+
if (r < 0 || r > 2 || c < 0 || c > 1)
|
543
|
+
return Qnil;
|
544
|
+
argv[1] = INT2NUM(r + (c * 3));
|
545
|
+
return rb_call_super(2, &argv[1]);
|
546
|
+
}
|
547
|
+
rb_raise(rb_eArgError, "wrong number of arguments (%d for 2, 3)", argc);
|
548
|
+
return Qnil;
|
549
|
+
}
|
550
|
+
|
551
|
+
VALUE rb_matrix3x2_invert(VALUE self) {
|
552
|
+
Matrix3x2 *m, *result;
|
553
|
+
Data_Get_Struct(self, Matrix3x2, m);
|
554
|
+
result = ALLOC(Matrix3x2);
|
555
|
+
|
556
|
+
float det = (m->m11 * m->m22) - (m->m21 * m->m12);
|
557
|
+
|
558
|
+
if (fabsf(det) < FLT_EPSILON) {
|
559
|
+
float *ptr = (float *)result;
|
560
|
+
for (int i = 0; i < 6; i++)
|
561
|
+
ptr[i] = NAN;
|
562
|
+
} else {
|
563
|
+
float invDet = 1.0f / det;
|
564
|
+
result->m11 = m->m22 * invDet;
|
565
|
+
result->m12 = -m->m12 * invDet;
|
566
|
+
result->m21 = -m->m21 * invDet;
|
567
|
+
result->m22 = m->m11 * invDet;
|
568
|
+
result->m31 = (m->m21 * m->m32 - m->m31 * m->m22) * invDet;
|
569
|
+
result->m32 = (m->m31 * m->m12 - m->m11 * m->m32) * invDet;
|
570
|
+
}
|
571
|
+
|
572
|
+
return NUMERIX_WRAP(CLASS_OF(self), result);
|
573
|
+
}
|
574
|
+
|
575
|
+
VALUE rb_matrix3x2_lerp(VALUE self, VALUE other, VALUE amount) {
|
576
|
+
Matrix3x2 *m1, *m2, *result;
|
577
|
+
Data_Get_Struct(self, Matrix3x2, m1);
|
578
|
+
Data_Get_Struct(other, Matrix3x2, m2);
|
579
|
+
result = ALLOC(Matrix3x2);
|
580
|
+
|
581
|
+
float weight = NUMERIX_CLAMP(NUM2FLT(amount), 0.0f, 1.0f);
|
582
|
+
// First row
|
583
|
+
result->m11 = m1->m11 + (m2->m11 - m1->m11) * weight;
|
584
|
+
result->m12 = m1->m12 + (m2->m12 - m1->m12) * weight;
|
585
|
+
|
586
|
+
// Second row
|
587
|
+
result->m21 = m1->m21 + (m2->m21 - m1->m21) * weight;
|
588
|
+
result->m22 = m1->m22 + (m2->m22 - m1->m22) * weight;
|
589
|
+
|
590
|
+
// Third row
|
591
|
+
result->m31 = m1->m31 + (m2->m31 - m1->m31) * weight;
|
592
|
+
result->m32 = m1->m32 + (m2->m32 - m1->m32) * weight;
|
593
|
+
|
594
|
+
return NUMERIX_WRAP(CLASS_OF(self), result);
|
595
|
+
}
|
596
|
+
|
597
|
+
VALUE rb_matrix3x2_lerp_bang(VALUE self, VALUE other, VALUE amount) {
|
598
|
+
Matrix3x2 *m1, *m2;
|
599
|
+
Data_Get_Struct(self, Matrix3x2, m1);
|
600
|
+
Data_Get_Struct(other, Matrix3x2, m2);
|
601
|
+
|
602
|
+
float weight = NUMERIX_CLAMP(NUM2FLT(amount), 0.0f, 1.0f);
|
603
|
+
// First row
|
604
|
+
m1->m11 = m1->m11 + (m2->m11 - m1->m11) * weight;
|
605
|
+
m1->m12 = m1->m12 + (m2->m12 - m1->m12) * weight;
|
606
|
+
|
607
|
+
// Second row
|
608
|
+
m1->m21 = m1->m21 + (m2->m21 - m1->m21) * weight;
|
609
|
+
m1->m22 = m1->m22 + (m2->m22 - m1->m22) * weight;
|
610
|
+
|
611
|
+
// Third row
|
612
|
+
m1->m31 = m1->m31 + (m2->m31 - m1->m31) * weight;
|
613
|
+
m1->m32 = m1->m32 + (m2->m32 - m1->m32) * weight;
|
614
|
+
|
615
|
+
return self;
|
616
|
+
}
|
617
|
+
|
618
|
+
static inline VALUE rb_matrix3x2_lerp_s(VALUE klass, VALUE matrix1, VALUE matrix2, VALUE amount) {
|
619
|
+
Matrix3x2 *m1, *m2, *result;
|
620
|
+
Data_Get_Struct(matrix1, Matrix3x2, m1);
|
621
|
+
Data_Get_Struct(matrix2, Matrix3x2, m2);
|
622
|
+
result = ALLOC(Matrix3x2);
|
623
|
+
|
624
|
+
float weight = NUMERIX_CLAMP(NUM2FLT(amount), 0.0f, 1.0f);
|
625
|
+
// First row
|
626
|
+
result->m11 = m1->m11 + (m2->m11 - m1->m11) * weight;
|
627
|
+
result->m12 = m1->m12 + (m2->m12 - m1->m12) * weight;
|
628
|
+
|
629
|
+
// Second row
|
630
|
+
result->m21 = m1->m21 + (m2->m21 - m1->m21) * weight;
|
631
|
+
result->m22 = m1->m22 + (m2->m22 - m1->m22) * weight;
|
632
|
+
|
633
|
+
// Third row
|
634
|
+
result->m31 = m1->m31 + (m2->m31 - m1->m31) * weight;
|
635
|
+
result->m32 = m1->m32 + (m2->m32 - m1->m32) * weight;
|
636
|
+
|
637
|
+
return NUMERIX_WRAP(klass, result);
|
638
|
+
}
|
@@ -0,0 +1,52 @@
|
|
1
|
+
#ifndef NUMERIX_MATRIX3X2_H
|
2
|
+
#define NUMERIX_MATRIX3X2_H 1
|
3
|
+
|
4
|
+
#include "common.h"
|
5
|
+
#include "matrix_base.h"
|
6
|
+
|
7
|
+
#define MATRIX3X2() \
|
8
|
+
Matrix3x2 *m; \
|
9
|
+
Data_Get_Struct(self, Matrix3x2, m)
|
10
|
+
|
11
|
+
void Init_matrix3x2(VALUE outer);
|
12
|
+
static VALUE rb_matrix3x2_allocate(VALUE klass);
|
13
|
+
VALUE rb_matrix3x2_initialize(int argc, VALUE *argv, VALUE self);
|
14
|
+
|
15
|
+
// Instance
|
16
|
+
VALUE rb_matrix3x2_identity_p(VALUE self);
|
17
|
+
VALUE rb_matrix3x2_translation(VALUE self);
|
18
|
+
VALUE rb_matrix3x2_translation_set(VALUE self, VALUE value);
|
19
|
+
VALUE rb_matrix3x2_determinant(VALUE self);
|
20
|
+
VALUE rb_matrix3x2_negate(VALUE self);
|
21
|
+
VALUE rb_matrix3x2_add(VALUE self, VALUE other);
|
22
|
+
VALUE rb_matrix3x2_subtract(VALUE self, VALUE other);
|
23
|
+
VALUE rb_matrix3x2_multiply(VALUE self, VALUE other);
|
24
|
+
VALUE rb_matrix3x2_equal(VALUE self, VALUE other);
|
25
|
+
VALUE rb_matrix3x2_row(VALUE self, VALUE row);
|
26
|
+
VALUE rb_matrix3x2_column(VALUE self, VALUE column);
|
27
|
+
VALUE rb_matrix3x2_each_row(VALUE self);
|
28
|
+
VALUE rb_matrix3x2_each_column(VALUE self);
|
29
|
+
VALUE rb_matrix3x2_aref(int argc, VALUE *argv, VALUE self);
|
30
|
+
VALUE rb_matrix3x2_aset(int argc, VALUE *argv, VALUE self);
|
31
|
+
VALUE rb_matrix3x2_invert(VALUE self);
|
32
|
+
VALUE rb_matrix3x2_lerp(VALUE self, VALUE other, VALUE amount);
|
33
|
+
VALUE rb_matrix3x2_lerp_bang(VALUE self, VALUE other, VALUE amount);
|
34
|
+
VALUE rb_matrix3x2_pow(VALUE self, VALUE exponent);
|
35
|
+
VALUE rb_matrix3x2_map(VALUE self);
|
36
|
+
VALUE rb_matrix3x2_map_bang(VALUE self);
|
37
|
+
|
38
|
+
// Conversion
|
39
|
+
VALUE rb_matrix3x2_to_s(VALUE self);
|
40
|
+
VALUE rb_matrix3x2_to_a(VALUE self);
|
41
|
+
VALUE rb_matrix3x2_to_h(VALUE self);
|
42
|
+
|
43
|
+
// Class
|
44
|
+
VALUE rb_matrix3x2_identity(VALUE klass);
|
45
|
+
VALUE rb_matrix3x2_create_translation(int argc, VALUE *argv, VALUE klass);
|
46
|
+
VALUE rb_matrix3x2_create_scale(int argc, VALUE *argv, VALUE klass);
|
47
|
+
VALUE rb_matrix3x2_create_skew(int argc, VALUE *argv, VALUE klass);
|
48
|
+
VALUE rb_matrix3x2_create_rotation(int argc, VALUE *argv, VALUE klass);
|
49
|
+
|
50
|
+
static inline VALUE rb_matrix3x2_lerp_s(VALUE klass, VALUE matrix1, VALUE matrix2, VALUE amount);
|
51
|
+
|
52
|
+
#endif /* NUMERIX_MATRIX3X2_H */
|