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,1807 @@
|
|
1
|
+
|
2
|
+
#include "matrix4x4.h"
|
3
|
+
|
4
|
+
void Init_matrix4x4(VALUE outer) {
|
5
|
+
rb_define_alloc_func(rb_cMatrix4x4, rb_matrix4x4_allocate);
|
6
|
+
rb_define_method(rb_cMatrix4x4, "initialize", rb_matrix4x4_initialize, -1);
|
7
|
+
|
8
|
+
// Instance
|
9
|
+
rb_define_method(rb_cMatrix4x4, "identity?", rb_matrix4x4_identity_p, 0);
|
10
|
+
rb_define_method(rb_cMatrix4x4, "translation", rb_matrix4x4_translation, 0);
|
11
|
+
rb_define_method(rb_cMatrix4x4, "translation=", rb_matrix4x4_translation_set, 1);
|
12
|
+
rb_define_method(rb_cMatrix4x4, "determinant", rb_matrix4x4_determinant, 0);
|
13
|
+
rb_define_method(rb_cMatrix4x4, "row", rb_matrix4x4_row, 1);
|
14
|
+
rb_define_method(rb_cMatrix4x4, "column", rb_matrix4x4_column, 1);
|
15
|
+
rb_define_method(rb_cMatrix4x4, "each_row", rb_matrix4x4_each_row, 0);
|
16
|
+
rb_define_method(rb_cMatrix4x4, "each_column", rb_matrix4x4_each_column, 0);
|
17
|
+
rb_define_method(rb_cMatrix4x4, "invert", rb_matrix4x4_invert, 0);
|
18
|
+
rb_define_method(rb_cMatrix4x4, "transform", rb_matrix4x4_transform, 1);
|
19
|
+
rb_define_method(rb_cMatrix4x4, "transform!", rb_matrix4x4_transform_bang, 1);
|
20
|
+
rb_define_method(rb_cMatrix4x4, "transpose", rb_matrix4x4_transpose, 0);
|
21
|
+
rb_define_method(rb_cMatrix4x4, "lerp", rb_matrix4x4_lerp, 2);
|
22
|
+
rb_define_method(rb_cMatrix4x4, "lerp!", rb_matrix4x4_lerp_bang, 2);
|
23
|
+
rb_define_method(rb_cMatrix4x4, "map", rb_matrix4x4_map, 0);
|
24
|
+
rb_define_method(rb_cMatrix4x4, "map2!", rb_matrix4x4_map_bang, 0);
|
25
|
+
|
26
|
+
// Alias
|
27
|
+
rb_define_alias(rb_cMatrix4x4, "collect", "map");
|
28
|
+
rb_define_alias(rb_cMatrix4x4, "collect2!", "map2!");
|
29
|
+
|
30
|
+
// Conversion
|
31
|
+
rb_define_method(rb_cMatrix4x4, "to_s", rb_matrix4x4_to_s, 0);
|
32
|
+
rb_define_method(rb_cMatrix4x4, "to_a", rb_matrix4x4_to_a, 0);
|
33
|
+
rb_define_method(rb_cMatrix4x4, "to_h", rb_matrix4x4_to_h, 0);
|
34
|
+
// to_mat3
|
35
|
+
|
36
|
+
// Operators
|
37
|
+
rb_define_method(rb_cMatrix4x4, "+", rb_matrix4x4_add, 1);
|
38
|
+
rb_define_method(rb_cMatrix4x4, "-", rb_matrix4x4_subtract, 1);
|
39
|
+
rb_define_method(rb_cMatrix4x4, "*", rb_matrix4x4_multiply, 1);
|
40
|
+
rb_define_method(rb_cMatrix4x4, "-@", rb_matrix4x4_negate, 0);
|
41
|
+
rb_define_method(rb_cMatrix4x4, "==", rb_matrix4x4_equal, 1);
|
42
|
+
rb_define_method(rb_cMatrix4x4, "[]", rb_matrix4x4_aref, -1);
|
43
|
+
rb_define_method(rb_cMatrix4x4, "[]=", rb_matrix4x4_aset, -1);
|
44
|
+
rb_define_method(rb_cMatrix4x4, "**", rb_matrix4x4_pow, 1);
|
45
|
+
|
46
|
+
// // Class
|
47
|
+
rb_define_singleton_method(rb_cMatrix4x4, "identity", rb_matrix4x4_identity, 0);
|
48
|
+
rb_define_singleton_method(rb_cMatrix4x4, "create_billboard", rb_matrix4x4_create_billboard, 4);
|
49
|
+
rb_define_singleton_method(rb_cMatrix4x4, "create_constrained_billboard", rb_matrix4x4_create_constrained_billboard, 5);
|
50
|
+
rb_define_singleton_method(rb_cMatrix4x4, "create_translation", rb_matrix4x4_create_translation, -1);
|
51
|
+
rb_define_singleton_method(rb_cMatrix4x4, "create_scale", rb_matrix4x4_create_scale, -1);
|
52
|
+
rb_define_singleton_method(rb_cMatrix4x4, "create_rotation_x", rb_matrix4x4_create_rotation_x, -1);
|
53
|
+
rb_define_singleton_method(rb_cMatrix4x4, "create_rotation_y", rb_matrix4x4_create_rotation_y, -1);
|
54
|
+
rb_define_singleton_method(rb_cMatrix4x4, "create_rotation_z", rb_matrix4x4_create_rotation_z, -1);
|
55
|
+
rb_define_singleton_method(rb_cMatrix4x4, "from_axis_angle", rb_matrix4x4_from_axis_angle, 2);
|
56
|
+
rb_define_singleton_method(rb_cMatrix4x4, "create_perspective_fov", rb_matrix4x4_create_perspective_fov, 4);
|
57
|
+
rb_define_singleton_method(rb_cMatrix4x4, "create_perspective", rb_matrix4x4_create_perspective_fov, 4);
|
58
|
+
rb_define_singleton_method(rb_cMatrix4x4, "create_perspective_off_center", rb_matrix4x4_create_perspective_off_center, 6);
|
59
|
+
rb_define_singleton_method(rb_cMatrix4x4, "create_orthographic", rb_matrix4x4_create_orthographic, 4);
|
60
|
+
rb_define_singleton_method(rb_cMatrix4x4, "create_orthographic_off_center", rb_matrix4x4_create_orthographic_off_center, 6);
|
61
|
+
rb_define_singleton_method(rb_cMatrix4x4, "create_look_at", rb_matrix4x4_create_look_at, 3);
|
62
|
+
rb_define_singleton_method(rb_cMatrix4x4, "create_world", rb_matrix4x4_create_world, 3);
|
63
|
+
rb_define_singleton_method(rb_cMatrix4x4, "from_quaternion", rb_matrix4x4_from_quaternion, 1);
|
64
|
+
rb_define_singleton_method(rb_cMatrix4x4, "from_yaw_pitch_roll", rb_matrix4x4_from_yaw_pitch_roll, 3);
|
65
|
+
rb_define_singleton_method(rb_cMatrix4x4, "create_shadow", rb_matrix4x4_create_shadow, 2);
|
66
|
+
rb_define_singleton_method(rb_cMatrix4x4, "create_reflection", rb_matrix4x4_create_reflection, 1);
|
67
|
+
rb_define_singleton_method(rb_cMatrix4x4, "lerp", rb_matrix4x4_lerp_s, 3);
|
68
|
+
}
|
69
|
+
|
70
|
+
static inline void numerix_cross_norm(Vector3 *v1, Vector3 *v2, Vector3 *result) {
|
71
|
+
float x = v1->y * v2->z - v1->z * v2->y;
|
72
|
+
float y = v1->z * v2->x - v1->x * v2->z;
|
73
|
+
float z = v1->x * v2->y - v1->y * v2->x;
|
74
|
+
float invLength = 1.0f / sqrtf(x * x + y * y + z * z);
|
75
|
+
result->x = x * invLength;
|
76
|
+
result->y = y * invLength;
|
77
|
+
result->z = z * invLength;
|
78
|
+
}
|
79
|
+
|
80
|
+
static inline void numerix_vec3_normalize(Vector3 *v) {
|
81
|
+
float invLength = 1.0f / sqrtf(v->x * v->x + v->y * v->y + v->z * v->z);
|
82
|
+
v->x *= invLength;
|
83
|
+
v->y *= invLength;
|
84
|
+
v->z *= invLength;
|
85
|
+
}
|
86
|
+
|
87
|
+
static inline void numerix_vec3_cross(Vector3 *v1, Vector3 *v2, Vector3 *result) {
|
88
|
+
result->x = v1->y * v2->z - v1->z * v2->y;
|
89
|
+
result->y = v1->z * v2->x - v1->x * v2->z;
|
90
|
+
result->z = v1->x * v2->y - v1->y * v2->x;
|
91
|
+
}
|
92
|
+
|
93
|
+
static inline float numerix_vec3_dot(Vector3 *v1, Vector3 *v2) {
|
94
|
+
return v1->x * v2->x + v1->y * v2->y + v1->z * v2->z;
|
95
|
+
}
|
96
|
+
|
97
|
+
static VALUE rb_matrix4x4_allocate(VALUE klass) {
|
98
|
+
Matrix4x4 *m = ALLOC(Matrix4x4);
|
99
|
+
memset(m, 0, sizeof(Matrix4x4));
|
100
|
+
return NUMERIX_WRAP(klass, m);
|
101
|
+
}
|
102
|
+
|
103
|
+
VALUE rb_matrix4x4_initialize(int argc, VALUE *argv, VALUE self) {
|
104
|
+
MATRIX4X4();
|
105
|
+
if (argc == 16) {
|
106
|
+
m->m11 = NUM2FLT(argv[0]);
|
107
|
+
m->m12 = NUM2FLT(argv[1]);
|
108
|
+
m->m13 = NUM2FLT(argv[2]);
|
109
|
+
m->m14 = NUM2FLT(argv[3]);
|
110
|
+
m->m21 = NUM2FLT(argv[4]);
|
111
|
+
m->m22 = NUM2FLT(argv[5]);
|
112
|
+
m->m23 = NUM2FLT(argv[6]);
|
113
|
+
m->m24 = NUM2FLT(argv[7]);
|
114
|
+
m->m31 = NUM2FLT(argv[8]);
|
115
|
+
m->m32 = NUM2FLT(argv[9]);
|
116
|
+
m->m33 = NUM2FLT(argv[10]);
|
117
|
+
m->m34 = NUM2FLT(argv[11]);
|
118
|
+
m->m41 = NUM2FLT(argv[12]);
|
119
|
+
m->m42 = NUM2FLT(argv[13]);
|
120
|
+
m->m43 = NUM2FLT(argv[14]);
|
121
|
+
m->m44 = NUM2FLT(argv[15]);
|
122
|
+
} else if (argc == 1) {
|
123
|
+
if (NUMERIX_TYPE_P(argv[0], rb_cMatrix3x2)) {
|
124
|
+
Matrix3x2 *value;
|
125
|
+
Data_Get_Struct(argv[0], Matrix3x2, value);
|
126
|
+
m->m11 = value->m11;
|
127
|
+
m->m12 = value->m12;
|
128
|
+
m->m13 = 0.0f;
|
129
|
+
m->m14 = 0.0f;
|
130
|
+
m->m21 = value->m21;
|
131
|
+
m->m22 = value->m22;
|
132
|
+
m->m23 = 0.0f;
|
133
|
+
m->m24 = 0.0f;
|
134
|
+
m->m31 = 0.0f;
|
135
|
+
m->m32 = 0.0f;
|
136
|
+
m->m33 = 1.0f;
|
137
|
+
m->m34 = 0.0f;
|
138
|
+
m->m41 = value->m31;
|
139
|
+
m->m42 = value->m32;
|
140
|
+
m->m43 = 0.0f;
|
141
|
+
m->m44 = 1.0f;
|
142
|
+
} else {
|
143
|
+
float value = NUM2FLT(argv[0]);
|
144
|
+
float *p = (float *)m;
|
145
|
+
for (int i = 0; i < 16; i++)
|
146
|
+
p[i] = value;
|
147
|
+
}
|
148
|
+
} else if (argc != 0)
|
149
|
+
rb_raise(rb_eArgError, "wrong number of arguments (given %d, expected 0, 16)", argc);
|
150
|
+
|
151
|
+
return Qnil;
|
152
|
+
}
|
153
|
+
|
154
|
+
VALUE rb_matrix4x4_lerp(VALUE self, VALUE other, VALUE amount) {
|
155
|
+
Matrix4x4 *m1, *m2, *result;
|
156
|
+
Data_Get_Struct(self, Matrix4x4, m1);
|
157
|
+
Data_Get_Struct(other, Matrix4x4, m2);
|
158
|
+
result = ALLOC(Matrix4x4);
|
159
|
+
float weight = NUMERIX_CLAMP(NUM2FLT(amount), 0.0f, 1.0f);
|
160
|
+
|
161
|
+
// First row
|
162
|
+
result->m11 = m1->m11 + (m2->m11 - m1->m11) * weight;
|
163
|
+
result->m12 = m1->m12 + (m2->m12 - m1->m12) * weight;
|
164
|
+
result->m13 = m1->m13 + (m2->m13 - m1->m13) * weight;
|
165
|
+
result->m14 = m1->m14 + (m2->m14 - m1->m14) * weight;
|
166
|
+
|
167
|
+
// Second row
|
168
|
+
result->m21 = m1->m21 + (m2->m21 - m1->m21) * weight;
|
169
|
+
result->m22 = m1->m22 + (m2->m22 - m1->m22) * weight;
|
170
|
+
result->m23 = m1->m23 + (m2->m23 - m1->m23) * weight;
|
171
|
+
result->m24 = m1->m24 + (m2->m24 - m1->m24) * weight;
|
172
|
+
|
173
|
+
// Third row
|
174
|
+
result->m31 = m1->m31 + (m2->m31 - m1->m31) * weight;
|
175
|
+
result->m32 = m1->m32 + (m2->m32 - m1->m32) * weight;
|
176
|
+
result->m33 = m1->m33 + (m2->m33 - m1->m33) * weight;
|
177
|
+
result->m34 = m1->m34 + (m2->m34 - m1->m34) * weight;
|
178
|
+
|
179
|
+
// Fourth row
|
180
|
+
result->m41 = m1->m41 + (m2->m41 - m1->m41) * weight;
|
181
|
+
result->m42 = m1->m42 + (m2->m42 - m1->m42) * weight;
|
182
|
+
result->m43 = m1->m43 + (m2->m43 - m1->m43) * weight;
|
183
|
+
result->m44 = m1->m44 + (m2->m44 - m1->m44) * weight;
|
184
|
+
|
185
|
+
return NUMERIX_WRAP(CLASS_OF(self), result);
|
186
|
+
}
|
187
|
+
|
188
|
+
VALUE rb_matrix4x4_lerp_bang(VALUE self, VALUE other, VALUE amount) {
|
189
|
+
Matrix4x4 *m1, *m2;
|
190
|
+
Data_Get_Struct(self, Matrix4x4, m1);
|
191
|
+
Data_Get_Struct(other, Matrix4x4, m2);
|
192
|
+
float weight = NUMERIX_CLAMP(NUM2FLT(amount), 0.0f, 1.0f);
|
193
|
+
|
194
|
+
// First row
|
195
|
+
m1->m11 = m1->m11 + (m2->m11 - m1->m11) * weight;
|
196
|
+
m1->m12 = m1->m12 + (m2->m12 - m1->m12) * weight;
|
197
|
+
m1->m13 = m1->m13 + (m2->m13 - m1->m13) * weight;
|
198
|
+
m1->m14 = m1->m14 + (m2->m14 - m1->m14) * weight;
|
199
|
+
|
200
|
+
// Second row
|
201
|
+
m1->m21 = m1->m21 + (m2->m21 - m1->m21) * weight;
|
202
|
+
m1->m22 = m1->m22 + (m2->m22 - m1->m22) * weight;
|
203
|
+
m1->m23 = m1->m23 + (m2->m23 - m1->m23) * weight;
|
204
|
+
m1->m24 = m1->m24 + (m2->m24 - m1->m24) * weight;
|
205
|
+
|
206
|
+
// Third row
|
207
|
+
m1->m31 = m1->m31 + (m2->m31 - m1->m31) * weight;
|
208
|
+
m1->m32 = m1->m32 + (m2->m32 - m1->m32) * weight;
|
209
|
+
m1->m33 = m1->m33 + (m2->m33 - m1->m33) * weight;
|
210
|
+
m1->m34 = m1->m34 + (m2->m34 - m1->m34) * weight;
|
211
|
+
|
212
|
+
// Fourth row
|
213
|
+
m1->m41 = m1->m41 + (m2->m41 - m1->m41) * weight;
|
214
|
+
m1->m42 = m1->m42 + (m2->m42 - m1->m42) * weight;
|
215
|
+
m1->m43 = m1->m43 + (m2->m43 - m1->m43) * weight;
|
216
|
+
m1->m44 = m1->m44 + (m2->m44 - m1->m44) * weight;
|
217
|
+
|
218
|
+
return self;
|
219
|
+
}
|
220
|
+
|
221
|
+
VALUE rb_matrix4x4_identity_p(VALUE self) {
|
222
|
+
MATRIX4X4();
|
223
|
+
// Check diagonal element first for early out.
|
224
|
+
return m->m11 == 1.0f && m->m22 == 1.0f && m->m33 == 1.0f && m->m44 == 1.0f &&
|
225
|
+
m->m12 == 0.0f && m->m13 == 0.0f && m->m14 == 0.0f && m->m21 == 0.0f &&
|
226
|
+
m->m23 == 0.0f && m->m24 == 0.0f && m->m31 == 0.0f && m->m32 == 0.0f &&
|
227
|
+
m->m34 == 0.0f && m->m41 == 0.0f && m->m42 == 0.0f && m->m43 == 0.0f
|
228
|
+
? Qtrue
|
229
|
+
: Qfalse;
|
230
|
+
}
|
231
|
+
|
232
|
+
VALUE rb_matrix4x4_translation(VALUE self) {
|
233
|
+
MATRIX4X4();
|
234
|
+
Vector3 *v = ALLOC(Vector3);
|
235
|
+
v->x = m->m41;
|
236
|
+
v->y = m->m42;
|
237
|
+
v->z = m->m43;
|
238
|
+
return NUMERIX_WRAP(rb_cVector3, v);
|
239
|
+
}
|
240
|
+
|
241
|
+
VALUE rb_matrix4x4_translation_set(VALUE self, VALUE value) {
|
242
|
+
MATRIX4X4();
|
243
|
+
Vector3 *v;
|
244
|
+
Data_Get_Struct(value, Vector3, v);
|
245
|
+
m->m41 = v->x;
|
246
|
+
m->m42 = v->y;
|
247
|
+
m->m43 = v->z;
|
248
|
+
return value;
|
249
|
+
}
|
250
|
+
|
251
|
+
VALUE rb_matrix4x4_determinant(VALUE self) {
|
252
|
+
Matrix4x4 *matrix;
|
253
|
+
Data_Get_Struct(self, Matrix4x4, matrix);
|
254
|
+
// | a b c d | | f g h | | e g h | | e f h | | e f g |
|
255
|
+
// | e f g h | = a | j k l | - b | i k l | + c | i j l | - d | i j k |
|
256
|
+
// | i j k l | | n o p | | m o p | | m n p | | m n o |
|
257
|
+
// | m n o p |
|
258
|
+
//
|
259
|
+
// | f g h |
|
260
|
+
// a | j k l | = a ( f ( kp - lo ) - g ( jp - ln ) + h ( jo - kn ) )
|
261
|
+
// | n o p |
|
262
|
+
//
|
263
|
+
// | e g h |
|
264
|
+
// b | i k l | = b ( e ( kp - lo ) - g ( ip - lm ) + h ( io - km ) )
|
265
|
+
// | m o p |
|
266
|
+
//
|
267
|
+
// | e f h |
|
268
|
+
// c | i j l | = c ( e ( jp - ln ) - f ( ip - lm ) + h ( in - jm ) )
|
269
|
+
// | m n p |
|
270
|
+
//
|
271
|
+
// | e f g |
|
272
|
+
// d | i j k | = d ( e ( jo - kn ) - f ( io - km ) + g ( in - jm ) )
|
273
|
+
// | m n o |
|
274
|
+
//
|
275
|
+
// Cost of operation
|
276
|
+
// 17 adds and 28 muls.
|
277
|
+
//
|
278
|
+
// add: 6 + 8 + 3 = 17
|
279
|
+
// mul: 12 + 16 = 28
|
280
|
+
|
281
|
+
float a = matrix->m11, b = matrix->m12, c = matrix->m13, d = matrix->m14;
|
282
|
+
float e = matrix->m21, f = matrix->m22, g = matrix->m23, h = matrix->m24;
|
283
|
+
float i = matrix->m31, j = matrix->m32, k = matrix->m33, l = matrix->m34;
|
284
|
+
float m = matrix->m41, n = matrix->m42, o = matrix->m43, p = matrix->m44;
|
285
|
+
|
286
|
+
float kp_lo = k * p - l * o;
|
287
|
+
float jp_ln = j * p - l * n;
|
288
|
+
float jo_kn = j * o - k * n;
|
289
|
+
float ip_lm = i * p - l * m;
|
290
|
+
float io_km = i * o - k * m;
|
291
|
+
float in_jm = i * n - j * m;
|
292
|
+
|
293
|
+
return DBL2NUM(a * (f * kp_lo - g * jp_ln + h * jo_kn) -
|
294
|
+
b * (e * kp_lo - g * ip_lm + h * io_km) +
|
295
|
+
c * (e * jp_ln - f * ip_lm + h * in_jm) -
|
296
|
+
d * (e * jo_kn - f * io_km + g * in_jm));
|
297
|
+
}
|
298
|
+
|
299
|
+
VALUE rb_matrix4x4_to_s(VALUE self) {
|
300
|
+
MATRIX4X4();
|
301
|
+
return rb_sprintf("{{%f, %f, %f, %f}, {%f, %f, %f, %f}, {%f, %f, %f, %f}, {%f, %f, %f, %f}}",
|
302
|
+
m->m11, m->m12, m->m13, m->m14, m->m21, m->m22, m->m23, m->m24,
|
303
|
+
m->m31, m->m32, m->m33, m->m34, m->m41, m->m42, m->m43, m->m44);
|
304
|
+
}
|
305
|
+
|
306
|
+
VALUE rb_matrix4x4_equal(VALUE self, VALUE other) {
|
307
|
+
if (CLASS_OF(other) != CLASS_OF(self))
|
308
|
+
return Qfalse;
|
309
|
+
Matrix4x4 *m1, *m2;
|
310
|
+
Data_Get_Struct(self, Matrix4x4, m1);
|
311
|
+
Data_Get_Struct(other, Matrix4x4, m2);
|
312
|
+
return FLT_EQUAL(m1->m11, m2->m11) && FLT_EQUAL(m1->m12, m2->m12) && FLT_EQUAL(m1->m13, m2->m13) && FLT_EQUAL(m1->m14, m2->m14) &&
|
313
|
+
FLT_EQUAL(m1->m21, m2->m21) && FLT_EQUAL(m1->m22, m2->m22) && FLT_EQUAL(m1->m23, m2->m23) && FLT_EQUAL(m1->m24, m2->m24) &&
|
314
|
+
FLT_EQUAL(m1->m31, m2->m31) && FLT_EQUAL(m1->m32, m2->m32) && FLT_EQUAL(m1->m33, m2->m33) && FLT_EQUAL(m1->m34, m2->m34) &&
|
315
|
+
FLT_EQUAL(m1->m41, m2->m41) && FLT_EQUAL(m1->m42, m2->m42) && FLT_EQUAL(m1->m43, m2->m43) && FLT_EQUAL(m1->m44, m2->m44)
|
316
|
+
? Qtrue
|
317
|
+
: Qfalse;
|
318
|
+
}
|
319
|
+
|
320
|
+
VALUE rb_matrix4x4_pow(VALUE self, VALUE exponent) {
|
321
|
+
struct RData *rdata = RDATA(self);
|
322
|
+
const int count = 16;
|
323
|
+
float *result = ruby_xmalloc(sizeof(float) * count);
|
324
|
+
float *m = (float *)rdata->data;
|
325
|
+
float e = fabsf(NUM2FLT(exponent));
|
326
|
+
for (int i = 0; i < count; i++)
|
327
|
+
result[i] = powf(fabsf(m[i]), e);
|
328
|
+
|
329
|
+
return NUMERIX_WRAP(rdata->basic.klass, result);
|
330
|
+
}
|
331
|
+
|
332
|
+
VALUE rb_matrix4x4_to_a(VALUE self) {
|
333
|
+
MATRIX4X4();
|
334
|
+
VALUE array = rb_ary_new_capa(4);
|
335
|
+
// Row 1
|
336
|
+
VALUE r1 = rb_ary_new_capa(4);
|
337
|
+
rb_ary_store(r1, 0, DBL2NUM(m->m11));
|
338
|
+
rb_ary_store(r1, 1, DBL2NUM(m->m12));
|
339
|
+
rb_ary_store(r1, 2, DBL2NUM(m->m13));
|
340
|
+
rb_ary_store(r1, 3, DBL2NUM(m->m14));
|
341
|
+
rb_ary_push(array, r1);
|
342
|
+
// Row 2
|
343
|
+
VALUE r2 = rb_ary_new_capa(4);
|
344
|
+
rb_ary_store(r2, 0, DBL2NUM(m->m21));
|
345
|
+
rb_ary_store(r2, 1, DBL2NUM(m->m22));
|
346
|
+
rb_ary_store(r2, 2, DBL2NUM(m->m23));
|
347
|
+
rb_ary_store(r2, 3, DBL2NUM(m->m24));
|
348
|
+
rb_ary_push(array, r2);
|
349
|
+
// Row 3
|
350
|
+
VALUE r3 = rb_ary_new_capa(4);
|
351
|
+
rb_ary_store(r3, 0, DBL2NUM(m->m31));
|
352
|
+
rb_ary_store(r3, 1, DBL2NUM(m->m32));
|
353
|
+
rb_ary_store(r3, 2, DBL2NUM(m->m33));
|
354
|
+
rb_ary_store(r3, 3, DBL2NUM(m->m34));
|
355
|
+
rb_ary_push(array, r3);
|
356
|
+
// Row 4
|
357
|
+
VALUE r4 = rb_ary_new_capa(4);
|
358
|
+
rb_ary_store(r4, 0, DBL2NUM(m->m41));
|
359
|
+
rb_ary_store(r4, 1, DBL2NUM(m->m42));
|
360
|
+
rb_ary_store(r4, 2, DBL2NUM(m->m43));
|
361
|
+
rb_ary_store(r4, 3, DBL2NUM(m->m44));
|
362
|
+
rb_ary_push(array, r4);
|
363
|
+
return array;
|
364
|
+
}
|
365
|
+
|
366
|
+
VALUE rb_matrix4x4_row(VALUE self, VALUE row) {
|
367
|
+
MATRIX4X4();
|
368
|
+
VALUE args = rb_ary_new_capa(4);
|
369
|
+
int r = NUM2INT(row);
|
370
|
+
switch (r) {
|
371
|
+
case 0: {
|
372
|
+
rb_ary_push(args, DBL2NUM(m->m11));
|
373
|
+
rb_ary_push(args, DBL2NUM(m->m12));
|
374
|
+
rb_ary_push(args, DBL2NUM(m->m13));
|
375
|
+
rb_ary_push(args, DBL2NUM(m->m14));
|
376
|
+
break;
|
377
|
+
}
|
378
|
+
case 1: {
|
379
|
+
rb_ary_push(args, DBL2NUM(m->m21));
|
380
|
+
rb_ary_push(args, DBL2NUM(m->m22));
|
381
|
+
rb_ary_push(args, DBL2NUM(m->m23));
|
382
|
+
rb_ary_push(args, DBL2NUM(m->m24));
|
383
|
+
break;
|
384
|
+
}
|
385
|
+
case 2: {
|
386
|
+
rb_ary_push(args, DBL2NUM(m->m31));
|
387
|
+
rb_ary_push(args, DBL2NUM(m->m32));
|
388
|
+
rb_ary_push(args, DBL2NUM(m->m33));
|
389
|
+
rb_ary_push(args, DBL2NUM(m->m34));
|
390
|
+
break;
|
391
|
+
}
|
392
|
+
case 3: {
|
393
|
+
rb_ary_push(args, DBL2NUM(m->m41));
|
394
|
+
rb_ary_push(args, DBL2NUM(m->m42));
|
395
|
+
rb_ary_push(args, DBL2NUM(m->m43));
|
396
|
+
rb_ary_push(args, DBL2NUM(m->m44));
|
397
|
+
break;
|
398
|
+
}
|
399
|
+
default:
|
400
|
+
break;
|
401
|
+
}
|
402
|
+
return args;
|
403
|
+
}
|
404
|
+
|
405
|
+
VALUE rb_matrix4x4_column(VALUE self, VALUE column) {
|
406
|
+
MATRIX4X4();
|
407
|
+
VALUE args = rb_ary_new_capa(4);
|
408
|
+
int c = NUM2INT(column);
|
409
|
+
switch (c) {
|
410
|
+
case 0: {
|
411
|
+
rb_ary_push(args, DBL2NUM(m->m11));
|
412
|
+
rb_ary_push(args, DBL2NUM(m->m21));
|
413
|
+
rb_ary_push(args, DBL2NUM(m->m31));
|
414
|
+
rb_ary_push(args, DBL2NUM(m->m41));
|
415
|
+
break;
|
416
|
+
}
|
417
|
+
case 1: {
|
418
|
+
rb_ary_push(args, DBL2NUM(m->m12));
|
419
|
+
rb_ary_push(args, DBL2NUM(m->m22));
|
420
|
+
rb_ary_push(args, DBL2NUM(m->m32));
|
421
|
+
rb_ary_push(args, DBL2NUM(m->m42));
|
422
|
+
break;
|
423
|
+
}
|
424
|
+
case 2: {
|
425
|
+
rb_ary_push(args, DBL2NUM(m->m13));
|
426
|
+
rb_ary_push(args, DBL2NUM(m->m23));
|
427
|
+
rb_ary_push(args, DBL2NUM(m->m33));
|
428
|
+
rb_ary_push(args, DBL2NUM(m->m43));
|
429
|
+
break;
|
430
|
+
}
|
431
|
+
case 3: {
|
432
|
+
rb_ary_push(args, DBL2NUM(m->m14));
|
433
|
+
rb_ary_push(args, DBL2NUM(m->m24));
|
434
|
+
rb_ary_push(args, DBL2NUM(m->m34));
|
435
|
+
rb_ary_push(args, DBL2NUM(m->m44));
|
436
|
+
break;
|
437
|
+
}
|
438
|
+
default:
|
439
|
+
break;
|
440
|
+
}
|
441
|
+
return args;
|
442
|
+
}
|
443
|
+
|
444
|
+
VALUE rb_matrix4x4_map(VALUE self) {
|
445
|
+
const int count = 16;
|
446
|
+
struct RData *rdata = RDATA(self);
|
447
|
+
float *flt = (float *)rdata->data;
|
448
|
+
float *result = (float *)ruby_xmalloc(count * sizeof(float));
|
449
|
+
|
450
|
+
for (int i = 0; i < count; i++)
|
451
|
+
result[i] = NUM2FLT(rb_yield(DBL2NUM(flt[i])));
|
452
|
+
|
453
|
+
return NUMERIX_WRAP(rdata->basic.klass, result);
|
454
|
+
}
|
455
|
+
|
456
|
+
VALUE rb_matrix4x4_map_bang(VALUE self) {
|
457
|
+
const int count = 16;
|
458
|
+
float *flt = (float *)RDATA(self)->data;
|
459
|
+
|
460
|
+
for (int i = 0; i < count; i++)
|
461
|
+
flt[i] = NUM2FLT(rb_yield(DBL2NUM(flt[i])));
|
462
|
+
|
463
|
+
return self;
|
464
|
+
}
|
465
|
+
|
466
|
+
VALUE rb_matrix4x4_to_h(VALUE self) {
|
467
|
+
MATRIX4X4();
|
468
|
+
VALUE hash = rb_hash_new();
|
469
|
+
rb_hash_aset(hash, ID2SYM(rb_intern("m11")), DBL2NUM(m->m11));
|
470
|
+
rb_hash_aset(hash, ID2SYM(rb_intern("m12")), DBL2NUM(m->m12));
|
471
|
+
rb_hash_aset(hash, ID2SYM(rb_intern("m13")), DBL2NUM(m->m13));
|
472
|
+
rb_hash_aset(hash, ID2SYM(rb_intern("m14")), DBL2NUM(m->m14));
|
473
|
+
|
474
|
+
rb_hash_aset(hash, ID2SYM(rb_intern("m21")), DBL2NUM(m->m21));
|
475
|
+
rb_hash_aset(hash, ID2SYM(rb_intern("m22")), DBL2NUM(m->m22));
|
476
|
+
rb_hash_aset(hash, ID2SYM(rb_intern("m23")), DBL2NUM(m->m23));
|
477
|
+
rb_hash_aset(hash, ID2SYM(rb_intern("m24")), DBL2NUM(m->m24));
|
478
|
+
|
479
|
+
rb_hash_aset(hash, ID2SYM(rb_intern("m31")), DBL2NUM(m->m31));
|
480
|
+
rb_hash_aset(hash, ID2SYM(rb_intern("m32")), DBL2NUM(m->m32));
|
481
|
+
rb_hash_aset(hash, ID2SYM(rb_intern("m33")), DBL2NUM(m->m33));
|
482
|
+
rb_hash_aset(hash, ID2SYM(rb_intern("m34")), DBL2NUM(m->m34));
|
483
|
+
|
484
|
+
rb_hash_aset(hash, ID2SYM(rb_intern("m41")), DBL2NUM(m->m41));
|
485
|
+
rb_hash_aset(hash, ID2SYM(rb_intern("m42")), DBL2NUM(m->m42));
|
486
|
+
rb_hash_aset(hash, ID2SYM(rb_intern("m43")), DBL2NUM(m->m43));
|
487
|
+
rb_hash_aset(hash, ID2SYM(rb_intern("m44")), DBL2NUM(m->m44));
|
488
|
+
return hash;
|
489
|
+
}
|
490
|
+
|
491
|
+
VALUE rb_matrix4x4_each_row(VALUE self) {
|
492
|
+
MATRIX4X4();
|
493
|
+
for (int i = 0; i < 4; i++) {
|
494
|
+
VALUE index = INT2NUM(i);
|
495
|
+
rb_yield(rb_matrix4x4_row(self, index));
|
496
|
+
}
|
497
|
+
return self;
|
498
|
+
}
|
499
|
+
|
500
|
+
VALUE rb_matrix4x4_each_column(VALUE self) {
|
501
|
+
MATRIX4X4();
|
502
|
+
for (int i = 0; i < 4; i++) {
|
503
|
+
VALUE index = INT2NUM(i);
|
504
|
+
rb_yield(rb_matrix4x4_column(self, index));
|
505
|
+
}
|
506
|
+
return self;
|
507
|
+
}
|
508
|
+
|
509
|
+
VALUE rb_matrix4x4_aref(int argc, VALUE *argv, VALUE self) {
|
510
|
+
if (argc == 1) {
|
511
|
+
return rb_call_super(1, argv);
|
512
|
+
} else if (argc == 2) {
|
513
|
+
int r = NUM2INT(argv[0]);
|
514
|
+
int c = NUM2INT(argv[1]);
|
515
|
+
if (r < 0 || r > 3 || c < 0 || c > 3)
|
516
|
+
return Qnil;
|
517
|
+
argv[0] = INT2NUM(r + (c * 4));
|
518
|
+
return rb_call_super(1, argv);
|
519
|
+
}
|
520
|
+
rb_raise(rb_eArgError, "wrong number of arguments (given %d, expected 1, 2)", argc);
|
521
|
+
return Qnil;
|
522
|
+
}
|
523
|
+
|
524
|
+
VALUE rb_matrix4x4_aset(int argc, VALUE *argv, VALUE self) {
|
525
|
+
if (argc == 2) {
|
526
|
+
return rb_call_super(2, argv);
|
527
|
+
} else if (argc == 3) {
|
528
|
+
int r = NUM2INT(argv[0]);
|
529
|
+
int c = NUM2INT(argv[1]);
|
530
|
+
if (r < 0 || r > 3 || c < 0 || c > 3)
|
531
|
+
return Qnil;
|
532
|
+
argv[1] = INT2NUM(r + (c * 4));
|
533
|
+
return rb_call_super(2, &argv[1]);
|
534
|
+
}
|
535
|
+
rb_raise(rb_eArgError, "wrong number of arguments (%d for 2, 3)", argc);
|
536
|
+
return Qnil;
|
537
|
+
}
|
538
|
+
|
539
|
+
VALUE rb_matrix4x4_identity(VALUE klass) {
|
540
|
+
Matrix4x4 *m = ALLOC(Matrix4x4);
|
541
|
+
m->m11 = 1.0f;
|
542
|
+
m->m12 = 0.0f;
|
543
|
+
m->m13 = 0.0f;
|
544
|
+
m->m14 = 0.0f;
|
545
|
+
m->m21 = 0.0f;
|
546
|
+
m->m22 = 1.0f;
|
547
|
+
m->m23 = 0.0f;
|
548
|
+
m->m24 = 0.0f;
|
549
|
+
m->m31 = 0.0f;
|
550
|
+
m->m32 = 0.0f;
|
551
|
+
m->m33 = 1.0f;
|
552
|
+
m->m34 = 0.0f;
|
553
|
+
m->m41 = 0.0f;
|
554
|
+
m->m42 = 0.0f;
|
555
|
+
m->m43 = 0.0f;
|
556
|
+
m->m44 = 1.0f;
|
557
|
+
return NUMERIX_WRAP(klass, m);
|
558
|
+
}
|
559
|
+
|
560
|
+
VALUE rb_matrix4x4_create_billboard(VALUE klass, VALUE position, VALUE camera, VALUE up, VALUE forward) {
|
561
|
+
const float epsilon = 1e-4f;
|
562
|
+
Vector3 *pos, *cam, *u, *f;
|
563
|
+
Data_Get_Struct(position, Vector3, pos);
|
564
|
+
Data_Get_Struct(camera, Vector3, cam);
|
565
|
+
Data_Get_Struct(up, Vector3, u);
|
566
|
+
Data_Get_Struct(forward, Vector3, f);
|
567
|
+
|
568
|
+
Vector3 *axis = xmalloc(sizeof(Vector3) * 3);
|
569
|
+
|
570
|
+
axis[2].x = pos->x - cam->x;
|
571
|
+
axis[2].y = pos->y - cam->y;
|
572
|
+
axis[2].z = pos->z - cam->z;
|
573
|
+
|
574
|
+
float norm = axis[2].x * axis[2].x + axis[2].y * axis[2].y + axis[2].z * axis[2].z;
|
575
|
+
|
576
|
+
if (norm < epsilon) {
|
577
|
+
axis[2].x = -f->x;
|
578
|
+
axis[2].y = -f->y;
|
579
|
+
axis[2].z = -f->z;
|
580
|
+
} else {
|
581
|
+
float inverseNorm = 1.0f / sqrtf(norm);
|
582
|
+
axis[2].x *= inverseNorm;
|
583
|
+
axis[2].y *= inverseNorm;
|
584
|
+
axis[2].z *= inverseNorm;
|
585
|
+
}
|
586
|
+
|
587
|
+
numerix_cross_norm(u, &axis[2], &axis[0]);
|
588
|
+
numerix_vec3_cross(&axis[2], &axis[0], &axis[1]);
|
589
|
+
|
590
|
+
Matrix4x4 *result = ALLOC(Matrix4x4);
|
591
|
+
|
592
|
+
result->m11 = axis[0].x;
|
593
|
+
result->m12 = axis[0].y;
|
594
|
+
result->m13 = axis[0].z;
|
595
|
+
result->m14 = 0.0f;
|
596
|
+
result->m21 = axis[1].x;
|
597
|
+
result->m22 = axis[1].y;
|
598
|
+
result->m23 = axis[1].z;
|
599
|
+
result->m24 = 0.0f;
|
600
|
+
result->m31 = axis[2].x;
|
601
|
+
result->m32 = axis[2].y;
|
602
|
+
result->m33 = axis[2].z;
|
603
|
+
result->m34 = 0.0f;
|
604
|
+
|
605
|
+
result->m41 = pos->x;
|
606
|
+
result->m42 = pos->y;
|
607
|
+
result->m43 = pos->z;
|
608
|
+
result->m44 = 1.0f;
|
609
|
+
|
610
|
+
xfree(axis);
|
611
|
+
|
612
|
+
return NUMERIX_WRAP(klass, result);
|
613
|
+
}
|
614
|
+
|
615
|
+
VALUE rb_matrix4x4_create_constrained_billboard(VALUE klass, VALUE position, VALUE rotate, VALUE camera, VALUE up, VALUE forward) {
|
616
|
+
const float epsilon = 1e-4f;
|
617
|
+
const float minAngle = 1.0f - (0.1f * (NUMERIX_PI / 180.0f)); // 0.1 degrees
|
618
|
+
|
619
|
+
Vector3 *pos, *cam, *r, *u, *f;
|
620
|
+
Data_Get_Struct(position, Vector3, pos);
|
621
|
+
Data_Get_Struct(camera, Vector3, cam);
|
622
|
+
Data_Get_Struct(rotate, Vector3, r);
|
623
|
+
Data_Get_Struct(up, Vector3, u);
|
624
|
+
Data_Get_Struct(forward, Vector3, f);
|
625
|
+
|
626
|
+
Vector3 *axis = xmalloc(sizeof(Vector3) * 3);
|
627
|
+
Vector3 *faceDir = xmalloc(sizeof(Vector3));
|
628
|
+
|
629
|
+
faceDir->x = pos->x - cam->x;
|
630
|
+
faceDir->y = pos->y - cam->y;
|
631
|
+
faceDir->z = pos->z - cam->z;
|
632
|
+
|
633
|
+
float norm = faceDir->x * faceDir->x + faceDir->y * faceDir->y + faceDir->z * faceDir->z;
|
634
|
+
if (norm < epsilon) {
|
635
|
+
faceDir->x = -f->x;
|
636
|
+
faceDir->y = -f->y;
|
637
|
+
faceDir->z = -f->z;
|
638
|
+
} else {
|
639
|
+
float invNorm = 1.0f / sqrtf(norm);
|
640
|
+
faceDir->x *= invNorm;
|
641
|
+
faceDir->y *= invNorm;
|
642
|
+
faceDir->z *= invNorm;
|
643
|
+
}
|
644
|
+
|
645
|
+
// Treat the case when angle between faceDir and rotateAxis is too close to 0.
|
646
|
+
float dot = numerix_vec3_dot(r, faceDir);
|
647
|
+
|
648
|
+
if (fabsf(dot) > minAngle) {
|
649
|
+
memcpy(&axis[2], f, sizeof(Vector2));
|
650
|
+
// Make sure passed values are useful for compute.
|
651
|
+
dot = numerix_vec3_dot(r, &axis[2]);
|
652
|
+
|
653
|
+
if (fabsf(dot) > minAngle) {
|
654
|
+
axis[2].y = 0.0f;
|
655
|
+
if (fabsf(r->z) > minAngle) {
|
656
|
+
axis[2].x = 1.0f;
|
657
|
+
axis[2].z = 0.0f;
|
658
|
+
} else {
|
659
|
+
axis[2].x = 0.0f;
|
660
|
+
axis[2].z = -1.0f;
|
661
|
+
}
|
662
|
+
}
|
663
|
+
numerix_cross_norm(r, &axis[2], &axis[0]);
|
664
|
+
numerix_cross_norm(&axis[0], r, &axis[2]);
|
665
|
+
} else {
|
666
|
+
numerix_cross_norm(r, faceDir, &axis[0]);
|
667
|
+
numerix_cross_norm(&axis[0], &axis[1], &axis[2]);
|
668
|
+
}
|
669
|
+
|
670
|
+
Matrix4x4 *result = ALLOC(Matrix4x4);
|
671
|
+
|
672
|
+
result->m11 = axis[0].x;
|
673
|
+
result->m12 = axis[0].y;
|
674
|
+
result->m13 = axis[0].z;
|
675
|
+
result->m14 = 0.0f;
|
676
|
+
result->m21 = axis[1].x;
|
677
|
+
result->m22 = axis[1].y;
|
678
|
+
result->m23 = axis[1].z;
|
679
|
+
result->m24 = 0.0f;
|
680
|
+
result->m31 = axis[2].x;
|
681
|
+
result->m32 = axis[2].y;
|
682
|
+
result->m33 = axis[2].z;
|
683
|
+
result->m34 = 0.0f;
|
684
|
+
|
685
|
+
result->m41 = pos->x;
|
686
|
+
result->m42 = pos->y;
|
687
|
+
result->m43 = pos->z;
|
688
|
+
result->m44 = 1.0f;
|
689
|
+
|
690
|
+
xfree(axis);
|
691
|
+
xfree(faceDir);
|
692
|
+
|
693
|
+
return NUMERIX_WRAP(klass, result);
|
694
|
+
}
|
695
|
+
|
696
|
+
VALUE rb_matrix4x4_create_translation(int argc, VALUE *argv, VALUE klass) {
|
697
|
+
float x, y, z;
|
698
|
+
if (argc == 1) {
|
699
|
+
Vector3 *v;
|
700
|
+
Data_Get_Struct(argv[0], Vector3, v);
|
701
|
+
x = v->x;
|
702
|
+
y = v->y;
|
703
|
+
z = v->z;
|
704
|
+
} else if (argc == 3) {
|
705
|
+
x = NUM2FLT(argv[0]);
|
706
|
+
y = NUM2FLT(argv[1]);
|
707
|
+
z = NUM2FLT(argv[2]);
|
708
|
+
} else
|
709
|
+
rb_raise(rb_eArgError, "wrong number of arguments (given %d, expected 1, 3)", argc);
|
710
|
+
|
711
|
+
Matrix4x4 *result = ALLOC(Matrix4x4);
|
712
|
+
result->m11 = 1.0f;
|
713
|
+
result->m12 = 0.0f;
|
714
|
+
result->m13 = 0.0f;
|
715
|
+
result->m14 = 0.0f;
|
716
|
+
result->m21 = 0.0f;
|
717
|
+
result->m22 = 1.0f;
|
718
|
+
result->m23 = 0.0f;
|
719
|
+
result->m24 = 0.0f;
|
720
|
+
result->m31 = 0.0f;
|
721
|
+
result->m32 = 0.0f;
|
722
|
+
result->m33 = 1.0f;
|
723
|
+
result->m34 = 0.0f;
|
724
|
+
|
725
|
+
result->m41 = x;
|
726
|
+
result->m42 = y;
|
727
|
+
result->m43 = z;
|
728
|
+
result->m44 = 1.0f;
|
729
|
+
|
730
|
+
return NUMERIX_WRAP(klass, result);
|
731
|
+
}
|
732
|
+
|
733
|
+
VALUE rb_matrix4x4_create_scale(int argc, VALUE *argv, VALUE klass) {
|
734
|
+
float xscale, yscale, zscale, tx = 0.0f, ty = 0.0f, tz = 0.0f;
|
735
|
+
|
736
|
+
switch (argc) {
|
737
|
+
case 1: {
|
738
|
+
if (NUMERIX_TYPE_P(argv[0], rb_cVector3)) // (vec3)
|
739
|
+
{
|
740
|
+
Vector3 *vec3;
|
741
|
+
Data_Get_Struct(argv[0], Vector3, vec3);
|
742
|
+
xscale = vec3->x;
|
743
|
+
yscale = vec3->y;
|
744
|
+
zscale = vec3->z;
|
745
|
+
} else // (float)
|
746
|
+
{
|
747
|
+
xscale = yscale = zscale = NUM2FLT(argv[0]);
|
748
|
+
}
|
749
|
+
break;
|
750
|
+
}
|
751
|
+
case 2: {
|
752
|
+
Vector3 *cp;
|
753
|
+
Data_Get_Struct(argv[1], Vector3, cp);
|
754
|
+
if (NUMERIX_TYPE_P(argv[0], rb_cVector3)) // (vec3, vec3)
|
755
|
+
{
|
756
|
+
Vector3 *v3;
|
757
|
+
Data_Get_Struct(argv[1], Vector3, v3);
|
758
|
+
xscale = v3->x;
|
759
|
+
yscale = v3->y;
|
760
|
+
zscale = v3->z;
|
761
|
+
} else // (float, vec3)
|
762
|
+
{
|
763
|
+
xscale = yscale = zscale = NUM2FLT(argv[0]);
|
764
|
+
}
|
765
|
+
tx = cp->x * (1.0f - xscale);
|
766
|
+
ty = cp->y * (1.0f - yscale);
|
767
|
+
tz = cp->z * (1.0f - zscale);
|
768
|
+
break;
|
769
|
+
}
|
770
|
+
case 3: // (float, float, float)
|
771
|
+
{
|
772
|
+
xscale = NUM2FLT(argv[0]);
|
773
|
+
yscale = NUM2FLT(argv[1]);
|
774
|
+
zscale = NUM2FLT(argv[2]);
|
775
|
+
break;
|
776
|
+
}
|
777
|
+
case 4: // (float, float, float, vec3)
|
778
|
+
{
|
779
|
+
xscale = NUM2FLT(argv[0]);
|
780
|
+
yscale = NUM2FLT(argv[1]);
|
781
|
+
zscale = NUM2FLT(argv[2]);
|
782
|
+
Vector3 *center;
|
783
|
+
Data_Get_Struct(argv[3], Vector3, center);
|
784
|
+
tx = center->x * (1.0f - xscale);
|
785
|
+
ty = center->y * (1.0f - yscale);
|
786
|
+
tz = center->z * (1.0f - zscale);
|
787
|
+
break;
|
788
|
+
}
|
789
|
+
default: {
|
790
|
+
rb_raise(rb_eArgError, "wrong number of arguments (given %d, expected 1, 2, 3, 4)", argc);
|
791
|
+
break;
|
792
|
+
}
|
793
|
+
}
|
794
|
+
Matrix4x4 *result = ALLOC(Matrix4x4);
|
795
|
+
result->m11 = xscale;
|
796
|
+
result->m12 = 0.0f;
|
797
|
+
result->m13 = 0.0f;
|
798
|
+
result->m14 = 0.0f;
|
799
|
+
result->m21 = 0.0f;
|
800
|
+
result->m22 = yscale;
|
801
|
+
result->m23 = 0.0f;
|
802
|
+
result->m24 = 0.0f;
|
803
|
+
result->m31 = 0.0f;
|
804
|
+
result->m32 = 0.0f;
|
805
|
+
result->m33 = zscale;
|
806
|
+
result->m34 = 0.0f;
|
807
|
+
result->m41 = tx;
|
808
|
+
result->m42 = ty;
|
809
|
+
result->m43 = tz;
|
810
|
+
result->m44 = 1.0f;
|
811
|
+
|
812
|
+
return NUMERIX_WRAP(klass, result);
|
813
|
+
}
|
814
|
+
|
815
|
+
VALUE rb_matrix4x4_create_rotation_x(int argc, VALUE *argv, VALUE klass) {
|
816
|
+
if (argc != 1 && argc != 2)
|
817
|
+
rb_raise(rb_eArgError, "wrong number of arguments (given %d, expected 1, 2)", argc);
|
818
|
+
|
819
|
+
float radians = NUM2FLT(argv[0]);
|
820
|
+
float c = cosf(radians);
|
821
|
+
float s = sinf(radians);
|
822
|
+
float y = 0.0f, z = 0.0f;
|
823
|
+
if (argc == 2) {
|
824
|
+
Vector3 *center;
|
825
|
+
Data_Get_Struct(argv[1], Vector3, center);
|
826
|
+
y = center->y * (1.0f - c) + center->z * s;
|
827
|
+
z = center->z * (1.0f - c) - center->y * s;
|
828
|
+
}
|
829
|
+
|
830
|
+
Matrix4x4 *result = ALLOC(Matrix4x4);
|
831
|
+
// [ 1 0 0 0 ]
|
832
|
+
// [ 0 c s 0 ]
|
833
|
+
// [ 0 -s c 0 ]
|
834
|
+
// [ 0 y z 1 ]
|
835
|
+
result->m11 = 1.0f;
|
836
|
+
result->m12 = 0.0f;
|
837
|
+
result->m13 = 0.0f;
|
838
|
+
result->m14 = 0.0f;
|
839
|
+
result->m21 = 0.0f;
|
840
|
+
result->m22 = c;
|
841
|
+
result->m23 = s;
|
842
|
+
result->m24 = 0.0f;
|
843
|
+
result->m31 = 0.0f;
|
844
|
+
result->m32 = -s;
|
845
|
+
result->m33 = c;
|
846
|
+
result->m34 = 0.0f;
|
847
|
+
result->m41 = 0.0f;
|
848
|
+
result->m42 = y;
|
849
|
+
result->m43 = z;
|
850
|
+
result->m44 = 1.0f;
|
851
|
+
|
852
|
+
return NUMERIX_WRAP(klass, result);
|
853
|
+
}
|
854
|
+
|
855
|
+
VALUE rb_matrix4x4_create_rotation_y(int argc, VALUE *argv, VALUE klass) {
|
856
|
+
if (argc != 1 && argc != 2)
|
857
|
+
rb_raise(rb_eArgError, "wrong number of arguments (given %d, expected 1, 2)", argc);
|
858
|
+
|
859
|
+
float radians = NUM2FLT(argv[0]);
|
860
|
+
float c = cosf(radians);
|
861
|
+
float s = sinf(radians);
|
862
|
+
float x = 0.0f, z = 0.0f;
|
863
|
+
if (argc == 2) {
|
864
|
+
Vector3 *center;
|
865
|
+
Data_Get_Struct(argv[1], Vector3, center);
|
866
|
+
x = center->x * (1.0f - c) - center->z * s;
|
867
|
+
z = center->z * (1.0f - c) + center->x * s;
|
868
|
+
}
|
869
|
+
|
870
|
+
Matrix4x4 *result = ALLOC(Matrix4x4);
|
871
|
+
// [ c 0 -s 0 ]
|
872
|
+
// [ 0 1 0 0 ]
|
873
|
+
// [ s 0 c 0 ]
|
874
|
+
// [ x 0 z 1 ]
|
875
|
+
result->m11 = c;
|
876
|
+
result->m12 = 0.0f;
|
877
|
+
result->m13 = -s;
|
878
|
+
result->m14 = 0.0f;
|
879
|
+
result->m21 = 0.0f;
|
880
|
+
result->m22 = 1.0f;
|
881
|
+
result->m23 = 0.0f;
|
882
|
+
result->m24 = 0.0f;
|
883
|
+
result->m31 = s;
|
884
|
+
result->m32 = 0.0f;
|
885
|
+
result->m33 = c;
|
886
|
+
result->m34 = 0.0f;
|
887
|
+
result->m41 = x;
|
888
|
+
result->m42 = 0.0f;
|
889
|
+
result->m43 = z;
|
890
|
+
result->m44 = 1.0f;
|
891
|
+
|
892
|
+
return NUMERIX_WRAP(klass, result);
|
893
|
+
}
|
894
|
+
|
895
|
+
VALUE rb_matrix4x4_create_rotation_z(int argc, VALUE *argv, VALUE klass) {
|
896
|
+
if (argc != 1 && argc != 2)
|
897
|
+
rb_raise(rb_eArgError, "wrong number of arguments (given %d, expected 1, 2)", argc);
|
898
|
+
|
899
|
+
float radians = NUM2FLT(argv[0]);
|
900
|
+
float c = cosf(radians);
|
901
|
+
float s = sinf(radians);
|
902
|
+
float x = 0.0f, y = 0.0f;
|
903
|
+
if (argc == 2) {
|
904
|
+
Vector3 *center;
|
905
|
+
Data_Get_Struct(argv[1], Vector3, center);
|
906
|
+
x = center->x * (1.0f - c) + center->y * s;
|
907
|
+
y = center->y * (1.0f - c) - center->x * s;
|
908
|
+
}
|
909
|
+
|
910
|
+
Matrix4x4 *result = ALLOC(Matrix4x4);
|
911
|
+
// [ c s 0 0 ]
|
912
|
+
// [ -s c 0 0 ]
|
913
|
+
// [ 0 0 1 0 ]
|
914
|
+
// [ x y 0 1 ]
|
915
|
+
result->m11 = c;
|
916
|
+
result->m12 = s;
|
917
|
+
result->m13 = 0.0f;
|
918
|
+
result->m14 = 0.0f;
|
919
|
+
result->m21 = -s;
|
920
|
+
result->m22 = c;
|
921
|
+
result->m23 = 0.0f;
|
922
|
+
result->m24 = 0.0f;
|
923
|
+
result->m31 = 0.0f;
|
924
|
+
result->m32 = 0.0f;
|
925
|
+
result->m33 = 1.0f;
|
926
|
+
result->m34 = 0.0f;
|
927
|
+
result->m41 = x;
|
928
|
+
result->m42 = y;
|
929
|
+
result->m43 = 0.0f;
|
930
|
+
result->m44 = 1.0f;
|
931
|
+
|
932
|
+
return NUMERIX_WRAP(klass, result);
|
933
|
+
}
|
934
|
+
|
935
|
+
VALUE rb_matrix4x4_from_axis_angle(VALUE klass, VALUE axis, VALUE angle) {
|
936
|
+
// a: angle
|
937
|
+
// x, y, z: unit vector for axis.
|
938
|
+
//
|
939
|
+
// Rotation matrix M can compute by using below equation.
|
940
|
+
//
|
941
|
+
// T T
|
942
|
+
// M = uu + (cos a)( I-uu ) + (sin a)S
|
943
|
+
//
|
944
|
+
// Where:
|
945
|
+
//
|
946
|
+
// u = ( x, y, z )
|
947
|
+
//
|
948
|
+
// [ 0 -z y ]
|
949
|
+
// S = [ z 0 -x ]
|
950
|
+
// [ -y x 0 ]
|
951
|
+
//
|
952
|
+
// [ 1 0 0 ]
|
953
|
+
// I = [ 0 1 0 ]
|
954
|
+
// [ 0 0 1 ]
|
955
|
+
//
|
956
|
+
//
|
957
|
+
// [ xx+cosa*(1-xx) yx-cosa*yx-sina*z zx-cosa*xz+sina*y ]
|
958
|
+
// M = [ xy-cosa*yx+sina*z yy+cosa(1-yy) yz-cosa*yz-sina*x ]
|
959
|
+
// [ zx-cosa*zx-sina*y zy-cosa*zy+sina*x zz+cosa*(1-zz) ]
|
960
|
+
//
|
961
|
+
|
962
|
+
float ang = NUM2FLT(angle);
|
963
|
+
Vector3 *v;
|
964
|
+
Data_Get_Struct(axis, Vector3, v);
|
965
|
+
|
966
|
+
float x = v->x, y = v->y, z = v->z;
|
967
|
+
float sa = sinf(ang), ca = cosf(ang);
|
968
|
+
float xx = x * x, yy = y * y, zz = z * z;
|
969
|
+
float xy = x * y, xz = x * z, yz = y * z;
|
970
|
+
|
971
|
+
Matrix4x4 *result = ALLOC(Matrix4x4);
|
972
|
+
|
973
|
+
result->m11 = xx + ca * (1.0f - xx);
|
974
|
+
result->m12 = xy - ca * xy + sa * z;
|
975
|
+
result->m13 = xz - ca * xz - sa * y;
|
976
|
+
result->m14 = 0.0f;
|
977
|
+
result->m21 = xy - ca * xy - sa * z;
|
978
|
+
result->m22 = yy + ca * (1.0f - yy);
|
979
|
+
result->m23 = yz - ca * yz + sa * x;
|
980
|
+
result->m24 = 0.0f;
|
981
|
+
result->m31 = xz - ca * xz + sa * y;
|
982
|
+
result->m32 = yz - ca * yz - sa * x;
|
983
|
+
result->m33 = zz + ca * (1.0f - zz);
|
984
|
+
result->m34 = 0.0f;
|
985
|
+
result->m41 = 0.0f;
|
986
|
+
result->m42 = 0.0f;
|
987
|
+
result->m43 = 0.0f;
|
988
|
+
result->m44 = 1.0f;
|
989
|
+
|
990
|
+
return NUMERIX_WRAP(klass, result);
|
991
|
+
}
|
992
|
+
|
993
|
+
VALUE rb_matrix4x4_create_perspective_fov(VALUE klass, VALUE fieldOfView, VALUE aspectRatio, VALUE nearDist, VALUE farDist) {
|
994
|
+
float n = NUM2FLT(nearDist);
|
995
|
+
float f = NUM2FLT(farDist);
|
996
|
+
if (n <= 0.0f)
|
997
|
+
rb_raise(rb_eRangeError, "near plane distance must be value greater than 0.0 (given %f)", n);
|
998
|
+
if (f <= 0.0f)
|
999
|
+
rb_raise(rb_eRangeError, "far plane distance must be value greater than 0.0 (given %f)", n);
|
1000
|
+
if (n <= 0.0f)
|
1001
|
+
rb_raise(rb_eRangeError, "near plane distance must be less than far plane distance");
|
1002
|
+
|
1003
|
+
float ratio = NUM2FLT(aspectRatio);
|
1004
|
+
float fov = NUM2FLT(fieldOfView);
|
1005
|
+
if (fov <= 0.0f || fov >= NUMERIX_PI)
|
1006
|
+
rb_raise(rb_eRangeError, "field of view must be value greater than 0.0 and less than PI (given %f)", fov);
|
1007
|
+
|
1008
|
+
Matrix4x4 *result = ALLOC(Matrix4x4);
|
1009
|
+
|
1010
|
+
float yscale = 1.0f / tanf(fov * 0.5f);
|
1011
|
+
float xscale = yscale / ratio;
|
1012
|
+
|
1013
|
+
result->m11 = xscale;
|
1014
|
+
result->m12 = result->m13 = result->m14 = 0.0f;
|
1015
|
+
|
1016
|
+
result->m22 = yscale;
|
1017
|
+
result->m21 = result->m23 = result->m24 = 0.0f;
|
1018
|
+
|
1019
|
+
result->m31 = result->m32 = 0.0f;
|
1020
|
+
result->m33 = f / (n - f);
|
1021
|
+
result->m34 = -1.0f;
|
1022
|
+
|
1023
|
+
result->m41 = result->m42 = result->m44 = 0.0f;
|
1024
|
+
result->m43 = n * f / (n - f);
|
1025
|
+
|
1026
|
+
return NUMERIX_WRAP(klass, result);
|
1027
|
+
}
|
1028
|
+
|
1029
|
+
VALUE rb_matrix4x4_create_perspective(VALUE klass, VALUE width, VALUE height, VALUE nearDist, VALUE farDist) {
|
1030
|
+
float n = NUM2FLT(nearDist);
|
1031
|
+
float f = NUM2FLT(farDist);
|
1032
|
+
if (n <= 0.0f)
|
1033
|
+
rb_raise(rb_eRangeError, "near plane distance must be value greater than 0.0 (given %f)", n);
|
1034
|
+
if (f <= 0.0f)
|
1035
|
+
rb_raise(rb_eRangeError, "far plane distance must be value greater than 0.0 (given %f)", n);
|
1036
|
+
if (n <= 0.0f)
|
1037
|
+
rb_raise(rb_eRangeError, "near plane distance must be less than far plane distance");
|
1038
|
+
|
1039
|
+
float w = NUM2FLT(width);
|
1040
|
+
float h = NUM2FLT(height);
|
1041
|
+
|
1042
|
+
Matrix4x4 *result = ALLOC(Matrix4x4);
|
1043
|
+
|
1044
|
+
result->m11 = 2.0f * n / w;
|
1045
|
+
result->m12 = result->m13 = result->m14 = 0.0f;
|
1046
|
+
|
1047
|
+
result->m22 = 2.0f * n / h;
|
1048
|
+
result->m21 = result->m23 = result->m24 = 0.0f;
|
1049
|
+
|
1050
|
+
result->m33 = f / (n - f);
|
1051
|
+
result->m31 = result->m32 = 0.0f;
|
1052
|
+
result->m34 = -1.0f;
|
1053
|
+
|
1054
|
+
result->m41 = result->m42 = result->m44 = 0.0f;
|
1055
|
+
result->m43 = n * f / (n - f);
|
1056
|
+
|
1057
|
+
return NUMERIX_WRAP(klass, result);
|
1058
|
+
}
|
1059
|
+
|
1060
|
+
VALUE rb_matrix4x4_create_perspective_off_center(VALUE klass, VALUE left, VALUE right, VALUE bottom, VALUE top, VALUE nearDist, VALUE farDist) {
|
1061
|
+
float n = NUM2FLT(nearDist);
|
1062
|
+
float f = NUM2FLT(farDist);
|
1063
|
+
if (n <= 0.0f)
|
1064
|
+
rb_raise(rb_eRangeError, "near plane distance must be value greater than 0.0 (given %f)", n);
|
1065
|
+
if (f <= 0.0f)
|
1066
|
+
rb_raise(rb_eRangeError, "far plane distance must be value greater than 0.0 (given %f)", n);
|
1067
|
+
if (n <= 0.0f)
|
1068
|
+
rb_raise(rb_eRangeError, "near plane distance must be less than far plane distance");
|
1069
|
+
|
1070
|
+
float l = NUM2FLT(left);
|
1071
|
+
float r = NUM2FLT(right);
|
1072
|
+
float t = NUM2FLT(top);
|
1073
|
+
float b = NUM2FLT(bottom);
|
1074
|
+
Matrix4x4 *result = ALLOC(Matrix4x4);
|
1075
|
+
|
1076
|
+
result->m11 = 2.0f * n / (r - l);
|
1077
|
+
result->m12 = result->m13 = result->m14 = 0.0f;
|
1078
|
+
|
1079
|
+
result->m22 = 2.0f * n / (t - b);
|
1080
|
+
result->m21 = result->m23 = result->m24 = 0.0f;
|
1081
|
+
|
1082
|
+
result->m31 = (l + r) / (r - l);
|
1083
|
+
result->m32 = (t + b) / (t - b);
|
1084
|
+
result->m33 = f / (n - f);
|
1085
|
+
result->m34 = -1.0f;
|
1086
|
+
|
1087
|
+
result->m43 = n * f / (n - f);
|
1088
|
+
result->m41 = result->m42 = result->m44 = 0.0f;
|
1089
|
+
|
1090
|
+
return NUMERIX_WRAP(klass, result);
|
1091
|
+
}
|
1092
|
+
|
1093
|
+
VALUE rb_matrix4x4_create_orthographic(VALUE klass, VALUE width, VALUE height, VALUE zNearPlane, VALUE zFarPlane) {
|
1094
|
+
float n = NUM2FLT(zNearPlane);
|
1095
|
+
float f = NUM2FLT(zFarPlane);
|
1096
|
+
|
1097
|
+
Matrix4x4 *result = ALLOC(Matrix4x4);
|
1098
|
+
|
1099
|
+
result->m11 = 2.0f / NUM2FLT(width);
|
1100
|
+
result->m12 = result->m13 = result->m14 = 0.0f;
|
1101
|
+
|
1102
|
+
result->m22 = 2.0f / NUM2FLT(height);
|
1103
|
+
result->m21 = result->m23 = result->m24 = 0.0f;
|
1104
|
+
|
1105
|
+
result->m33 = 1.0f / (n - f);
|
1106
|
+
result->m31 = result->m32 = result->m34 = 0.0f;
|
1107
|
+
|
1108
|
+
result->m41 = result->m42 = 0.0f;
|
1109
|
+
result->m43 = n / (n - f);
|
1110
|
+
result->m44 = 1.0f;
|
1111
|
+
|
1112
|
+
return NUMERIX_WRAP(klass, result);
|
1113
|
+
}
|
1114
|
+
|
1115
|
+
VALUE rb_matrix4x4_create_orthographic_off_center(VALUE klass, VALUE left, VALUE right, VALUE bottom, VALUE top, VALUE zNearPlane, VALUE zFarPlane) {
|
1116
|
+
float n = NUM2FLT(zNearPlane);
|
1117
|
+
float f = NUM2FLT(zFarPlane);
|
1118
|
+
float l = NUM2FLT(left);
|
1119
|
+
float r = NUM2FLT(right);
|
1120
|
+
float t = NUM2FLT(top);
|
1121
|
+
float b = NUM2FLT(bottom);
|
1122
|
+
Matrix4x4 *result = ALLOC(Matrix4x4);
|
1123
|
+
|
1124
|
+
result->m11 = 2.0f / (r - l);
|
1125
|
+
result->m12 = result->m13 = result->m14 = 0.0f;
|
1126
|
+
|
1127
|
+
result->m22 = 2.0f / (t - b);
|
1128
|
+
result->m21 = result->m23 = result->m24 = 0.0f;
|
1129
|
+
|
1130
|
+
result->m33 = 1.0f / (n - f);
|
1131
|
+
result->m31 = result->m32 = result->m34 = 0.0f;
|
1132
|
+
|
1133
|
+
result->m41 = (l + r) / (l - r);
|
1134
|
+
result->m42 = (t + b) / (b - t);
|
1135
|
+
result->m43 = n / (n - f);
|
1136
|
+
result->m44 = 1.0f;
|
1137
|
+
|
1138
|
+
return NUMERIX_WRAP(klass, result);
|
1139
|
+
}
|
1140
|
+
|
1141
|
+
VALUE rb_matrix4x4_create_look_at(VALUE klass, VALUE camPos, VALUE camTarget, VALUE camUp) {
|
1142
|
+
Vector3 *cam, *target, *up;
|
1143
|
+
Data_Get_Struct(camPos, Vector3, cam);
|
1144
|
+
Data_Get_Struct(camTarget, Vector3, target);
|
1145
|
+
Data_Get_Struct(camUp, Vector3, up);
|
1146
|
+
|
1147
|
+
Vector3 *axis = xmalloc(sizeof(Vector3) * 3);
|
1148
|
+
axis[2].x = cam->x - target->x;
|
1149
|
+
axis[2].y = cam->y - target->y;
|
1150
|
+
axis[2].z = cam->z - target->z;
|
1151
|
+
numerix_vec3_normalize(&axis[2]);
|
1152
|
+
|
1153
|
+
numerix_cross_norm(up, &axis[2], &axis[0]);
|
1154
|
+
numerix_cross_norm(&axis[2], &axis[0], &axis[1]);
|
1155
|
+
|
1156
|
+
Matrix4x4 *result = ALLOC(Matrix4x4);
|
1157
|
+
|
1158
|
+
result->m11 = axis[0].x;
|
1159
|
+
result->m12 = axis[1].x;
|
1160
|
+
result->m13 = axis[2].x;
|
1161
|
+
result->m14 = 0.0f;
|
1162
|
+
result->m21 = axis[0].y;
|
1163
|
+
result->m22 = axis[1].y;
|
1164
|
+
result->m23 = axis[2].y;
|
1165
|
+
result->m24 = 0.0f;
|
1166
|
+
result->m31 = axis[0].z;
|
1167
|
+
result->m32 = axis[1].z;
|
1168
|
+
result->m33 = axis[2].z;
|
1169
|
+
result->m34 = 0.0f;
|
1170
|
+
result->m41 = -(numerix_vec3_dot(&axis[0], cam));
|
1171
|
+
result->m42 = -(numerix_vec3_dot(&axis[1], cam));
|
1172
|
+
result->m43 = -(numerix_vec3_dot(&axis[2], cam));
|
1173
|
+
result->m44 = 1.0f;
|
1174
|
+
|
1175
|
+
xfree(axis);
|
1176
|
+
|
1177
|
+
return NUMERIX_WRAP(klass, result);
|
1178
|
+
}
|
1179
|
+
|
1180
|
+
VALUE rb_matrix4x4_create_world(VALUE klass, VALUE position, VALUE forward, VALUE up) {
|
1181
|
+
Vector3 *pos, *f, *u;
|
1182
|
+
Data_Get_Struct(position, Vector3, pos);
|
1183
|
+
Data_Get_Struct(forward, Vector3, f);
|
1184
|
+
Data_Get_Struct(up, Vector3, u);
|
1185
|
+
|
1186
|
+
Vector3 *axis = xmalloc(sizeof(Vector3) * 3);
|
1187
|
+
|
1188
|
+
axis[2].x = -f->x;
|
1189
|
+
axis[2].y = -f->y;
|
1190
|
+
axis[2].z = -f->z;
|
1191
|
+
numerix_vec3_normalize(&axis[2]);
|
1192
|
+
numerix_cross_norm(u, &axis[2], &axis[0]);
|
1193
|
+
numerix_vec3_cross(&axis[2], &axis[0], &axis[1]);
|
1194
|
+
|
1195
|
+
Matrix4x4 *result = ALLOC(Matrix4x4);
|
1196
|
+
|
1197
|
+
result->m11 = axis[0].x;
|
1198
|
+
result->m12 = axis[0].y;
|
1199
|
+
result->m13 = axis[0].z;
|
1200
|
+
result->m14 = 0.0f;
|
1201
|
+
result->m21 = axis[1].x;
|
1202
|
+
result->m22 = axis[1].y;
|
1203
|
+
result->m23 = axis[1].z;
|
1204
|
+
result->m24 = 0.0f;
|
1205
|
+
result->m31 = axis[2].x;
|
1206
|
+
result->m32 = axis[2].y;
|
1207
|
+
result->m33 = axis[2].z;
|
1208
|
+
result->m34 = 0.0f;
|
1209
|
+
result->m41 = pos->x;
|
1210
|
+
result->m42 = pos->y;
|
1211
|
+
result->m43 = pos->z;
|
1212
|
+
result->m44 = 1.0f;
|
1213
|
+
|
1214
|
+
xfree(axis);
|
1215
|
+
|
1216
|
+
return NUMERIX_WRAP(klass, result);
|
1217
|
+
}
|
1218
|
+
|
1219
|
+
VALUE rb_matrix4x4_from_quaternion(VALUE klass, VALUE quaternion) {
|
1220
|
+
Quaternion *q;
|
1221
|
+
Data_Get_Struct(quaternion, Quaternion, q);
|
1222
|
+
|
1223
|
+
float xx = q->x * q->x;
|
1224
|
+
float yy = q->y * q->y;
|
1225
|
+
float zz = q->z * q->z;
|
1226
|
+
|
1227
|
+
float xy = q->x * q->y;
|
1228
|
+
float wz = q->z * q->w;
|
1229
|
+
float xz = q->z * q->x;
|
1230
|
+
float wy = q->y * q->w;
|
1231
|
+
float yz = q->y * q->z;
|
1232
|
+
float wx = q->x * q->w;
|
1233
|
+
|
1234
|
+
Matrix4x4 *result = ALLOC(Matrix4x4);
|
1235
|
+
|
1236
|
+
result->m11 = 1.0f - 2.0f * (yy + zz);
|
1237
|
+
result->m12 = 2.0f * (xy + wz);
|
1238
|
+
result->m13 = 2.0f * (xz - wy);
|
1239
|
+
result->m14 = 0.0f;
|
1240
|
+
result->m21 = 2.0f * (xy - wz);
|
1241
|
+
result->m22 = 1.0f - 2.0f * (zz + xx);
|
1242
|
+
result->m23 = 2.0f * (yz + wx);
|
1243
|
+
result->m24 = 0.0f;
|
1244
|
+
result->m31 = 2.0f * (xz + wy);
|
1245
|
+
result->m32 = 2.0f * (yz - wx);
|
1246
|
+
result->m33 = 1.0f - 2.0f * (yy + xx);
|
1247
|
+
result->m34 = 0.0f;
|
1248
|
+
result->m41 = 0.0f;
|
1249
|
+
result->m42 = 0.0f;
|
1250
|
+
result->m43 = 0.0f;
|
1251
|
+
result->m44 = 1.0f;
|
1252
|
+
|
1253
|
+
return NUMERIX_WRAP(klass, result);
|
1254
|
+
}
|
1255
|
+
|
1256
|
+
VALUE rb_matrix4x4_from_yaw_pitch_roll(VALUE klass, VALUE yaw, VALUE pitch, VALUE roll) {
|
1257
|
+
VALUE q = rb_quaternion_from_yaw_pitch_roll(rb_cQuaternion, yaw, pitch, roll);
|
1258
|
+
return rb_matrix4x4_from_quaternion(klass, q);
|
1259
|
+
}
|
1260
|
+
|
1261
|
+
VALUE rb_matrix4x4_create_shadow(VALUE klass, VALUE lightDir, VALUE plane) {
|
1262
|
+
Vector3 *light;
|
1263
|
+
Data_Get_Struct(lightDir, Vector3, light);
|
1264
|
+
|
1265
|
+
VALUE normPlane = rb_plane_normalize(plane);
|
1266
|
+
Plane *p;
|
1267
|
+
Data_Get_Struct(normPlane, Plane, p);
|
1268
|
+
|
1269
|
+
float dot = p->normal.x * light->x + p->normal.y * light->y + p->normal.z * light->z;
|
1270
|
+
float a = -p->normal.x;
|
1271
|
+
float b = -p->normal.y;
|
1272
|
+
float c = -p->normal.z;
|
1273
|
+
float d = -p->distance;
|
1274
|
+
|
1275
|
+
Matrix4x4 *result = ALLOC(Matrix4x4);
|
1276
|
+
|
1277
|
+
result->m11 = a * light->x + dot;
|
1278
|
+
result->m21 = b * light->x;
|
1279
|
+
result->m31 = c * light->x;
|
1280
|
+
result->m41 = d * light->x;
|
1281
|
+
|
1282
|
+
result->m12 = a * light->y;
|
1283
|
+
result->m22 = b * light->y + dot;
|
1284
|
+
result->m32 = c * light->y;
|
1285
|
+
result->m42 = d * light->y;
|
1286
|
+
|
1287
|
+
result->m13 = a * light->z;
|
1288
|
+
result->m23 = b * light->z;
|
1289
|
+
result->m33 = c * light->z + dot;
|
1290
|
+
result->m43 = d * light->z;
|
1291
|
+
|
1292
|
+
result->m14 = 0.0f;
|
1293
|
+
result->m24 = 0.0f;
|
1294
|
+
result->m34 = 0.0f;
|
1295
|
+
result->m44 = dot;
|
1296
|
+
|
1297
|
+
return NUMERIX_WRAP(klass, result);
|
1298
|
+
}
|
1299
|
+
|
1300
|
+
VALUE rb_matrix4x4_create_reflection(VALUE klass, VALUE plane) {
|
1301
|
+
VALUE normPlane = rb_plane_normalize(plane);
|
1302
|
+
Plane *p;
|
1303
|
+
Data_Get_Struct(normPlane, Plane, p);
|
1304
|
+
|
1305
|
+
float a = p->normal.x;
|
1306
|
+
float b = p->normal.y;
|
1307
|
+
float c = p->normal.z;
|
1308
|
+
|
1309
|
+
float fa = -2.0f * a;
|
1310
|
+
float fb = -2.0f * b;
|
1311
|
+
float fc = -2.0f * c;
|
1312
|
+
|
1313
|
+
Matrix4x4 *result = ALLOC(Matrix4x4);
|
1314
|
+
|
1315
|
+
result->m11 = fa * a + 1.0f;
|
1316
|
+
result->m12 = fb * a;
|
1317
|
+
result->m13 = fc * a;
|
1318
|
+
result->m14 = 0.0f;
|
1319
|
+
|
1320
|
+
result->m21 = fa * b;
|
1321
|
+
result->m22 = fb * b + 1.0f;
|
1322
|
+
result->m23 = fc * b;
|
1323
|
+
result->m24 = 0.0f;
|
1324
|
+
|
1325
|
+
result->m31 = fa * c;
|
1326
|
+
result->m32 = fb * c;
|
1327
|
+
result->m33 = fc * c + 1.0f;
|
1328
|
+
result->m34 = 0.0f;
|
1329
|
+
|
1330
|
+
result->m41 = fa * p->distance;
|
1331
|
+
result->m42 = fb * p->distance;
|
1332
|
+
result->m43 = fc * p->distance;
|
1333
|
+
result->m44 = 1.0f;
|
1334
|
+
|
1335
|
+
return NUMERIX_WRAP(klass, result);
|
1336
|
+
}
|
1337
|
+
|
1338
|
+
VALUE rb_matrix4x4_transform(VALUE self, VALUE quaternion) {
|
1339
|
+
Matrix4x4 *m, *result;
|
1340
|
+
Quaternion *rotation;
|
1341
|
+
Data_Get_Struct(self, Matrix4x4, m);
|
1342
|
+
Data_Get_Struct(quaternion, Quaternion, rotation);
|
1343
|
+
|
1344
|
+
// Compute rotation matrix.
|
1345
|
+
float x2 = rotation->x + rotation->x;
|
1346
|
+
float y2 = rotation->y + rotation->y;
|
1347
|
+
float z2 = rotation->z + rotation->z;
|
1348
|
+
|
1349
|
+
float wx2 = rotation->w * x2;
|
1350
|
+
float wy2 = rotation->w * y2;
|
1351
|
+
float wz2 = rotation->w * z2;
|
1352
|
+
float xx2 = rotation->x * x2;
|
1353
|
+
float xy2 = rotation->x * y2;
|
1354
|
+
float xz2 = rotation->x * z2;
|
1355
|
+
float yy2 = rotation->y * y2;
|
1356
|
+
float yz2 = rotation->y * z2;
|
1357
|
+
float zz2 = rotation->z * z2;
|
1358
|
+
|
1359
|
+
float q11 = 1.0f - yy2 - zz2;
|
1360
|
+
float q21 = xy2 - wz2;
|
1361
|
+
float q31 = xz2 + wy2;
|
1362
|
+
|
1363
|
+
float q12 = xy2 + wz2;
|
1364
|
+
float q22 = 1.0f - xx2 - zz2;
|
1365
|
+
float q32 = yz2 - wx2;
|
1366
|
+
|
1367
|
+
float q13 = xz2 - wy2;
|
1368
|
+
float q23 = yz2 + wx2;
|
1369
|
+
float q33 = 1.0f - xx2 - yy2;
|
1370
|
+
|
1371
|
+
result = ALLOC(Matrix4x4);
|
1372
|
+
|
1373
|
+
// First row
|
1374
|
+
result->m11 = m->m11 * q11 + m->m12 * q21 + m->m13 * q31;
|
1375
|
+
result->m12 = m->m11 * q12 + m->m12 * q22 + m->m13 * q32;
|
1376
|
+
result->m13 = m->m11 * q13 + m->m12 * q23 + m->m13 * q33;
|
1377
|
+
result->m14 = m->m14;
|
1378
|
+
|
1379
|
+
// Second row
|
1380
|
+
result->m21 = m->m21 * q11 + m->m22 * q21 + m->m23 * q31;
|
1381
|
+
result->m22 = m->m21 * q12 + m->m22 * q22 + m->m23 * q32;
|
1382
|
+
result->m23 = m->m21 * q13 + m->m22 * q23 + m->m23 * q33;
|
1383
|
+
result->m24 = m->m24;
|
1384
|
+
|
1385
|
+
// Third row
|
1386
|
+
result->m31 = m->m31 * q11 + m->m32 * q21 + m->m33 * q31;
|
1387
|
+
result->m32 = m->m31 * q12 + m->m32 * q22 + m->m33 * q32;
|
1388
|
+
result->m33 = m->m31 * q13 + m->m32 * q23 + m->m33 * q33;
|
1389
|
+
result->m34 = m->m34;
|
1390
|
+
|
1391
|
+
// Fourth row
|
1392
|
+
result->m41 = m->m41 * q11 + m->m42 * q21 + m->m43 * q31;
|
1393
|
+
result->m42 = m->m41 * q12 + m->m42 * q22 + m->m43 * q32;
|
1394
|
+
result->m43 = m->m41 * q13 + m->m42 * q23 + m->m43 * q33;
|
1395
|
+
result->m44 = m->m44;
|
1396
|
+
|
1397
|
+
return NUMERIX_WRAP(CLASS_OF(self), result);
|
1398
|
+
}
|
1399
|
+
|
1400
|
+
VALUE rb_matrix4x4_transform_bang(VALUE self, VALUE quaternion) {
|
1401
|
+
MATRIX4X4();
|
1402
|
+
Quaternion *rotation;
|
1403
|
+
Data_Get_Struct(quaternion, Quaternion, rotation);
|
1404
|
+
|
1405
|
+
// Compute rotation matrix.
|
1406
|
+
float x2 = rotation->x + rotation->x;
|
1407
|
+
float y2 = rotation->y + rotation->y;
|
1408
|
+
float z2 = rotation->z + rotation->z;
|
1409
|
+
|
1410
|
+
float wx2 = rotation->w * x2;
|
1411
|
+
float wy2 = rotation->w * y2;
|
1412
|
+
float wz2 = rotation->w * z2;
|
1413
|
+
float xx2 = rotation->x * x2;
|
1414
|
+
float xy2 = rotation->x * y2;
|
1415
|
+
float xz2 = rotation->x * z2;
|
1416
|
+
float yy2 = rotation->y * y2;
|
1417
|
+
float yz2 = rotation->y * z2;
|
1418
|
+
float zz2 = rotation->z * z2;
|
1419
|
+
|
1420
|
+
float q11 = 1.0f - yy2 - zz2;
|
1421
|
+
float q21 = xy2 - wz2;
|
1422
|
+
float q31 = xz2 + wy2;
|
1423
|
+
|
1424
|
+
float q12 = xy2 + wz2;
|
1425
|
+
float q22 = 1.0f - xx2 - zz2;
|
1426
|
+
float q32 = yz2 - wx2;
|
1427
|
+
|
1428
|
+
float q13 = xz2 - wy2;
|
1429
|
+
float q23 = yz2 + wx2;
|
1430
|
+
float q33 = 1.0f - xx2 - yy2;
|
1431
|
+
|
1432
|
+
// First row
|
1433
|
+
m->m11 = m->m11 * q11 + m->m12 * q21 + m->m13 * q31;
|
1434
|
+
m->m12 = m->m11 * q12 + m->m12 * q22 + m->m13 * q32;
|
1435
|
+
m->m13 = m->m11 * q13 + m->m12 * q23 + m->m13 * q33;
|
1436
|
+
m->m14 = m->m14;
|
1437
|
+
|
1438
|
+
// Second row
|
1439
|
+
m->m21 = m->m21 * q11 + m->m22 * q21 + m->m23 * q31;
|
1440
|
+
m->m22 = m->m21 * q12 + m->m22 * q22 + m->m23 * q32;
|
1441
|
+
m->m23 = m->m21 * q13 + m->m22 * q23 + m->m23 * q33;
|
1442
|
+
m->m24 = m->m24;
|
1443
|
+
|
1444
|
+
// Third row
|
1445
|
+
m->m31 = m->m31 * q11 + m->m32 * q21 + m->m33 * q31;
|
1446
|
+
m->m32 = m->m31 * q12 + m->m32 * q22 + m->m33 * q32;
|
1447
|
+
m->m33 = m->m31 * q13 + m->m32 * q23 + m->m33 * q33;
|
1448
|
+
m->m34 = m->m34;
|
1449
|
+
|
1450
|
+
// Fourth row
|
1451
|
+
m->m41 = m->m41 * q11 + m->m42 * q21 + m->m43 * q31;
|
1452
|
+
m->m42 = m->m41 * q12 + m->m42 * q22 + m->m43 * q32;
|
1453
|
+
m->m43 = m->m41 * q13 + m->m42 * q23 + m->m43 * q33;
|
1454
|
+
m->m44 = m->m44;
|
1455
|
+
|
1456
|
+
return self;
|
1457
|
+
}
|
1458
|
+
|
1459
|
+
VALUE rb_matrix4x4_transpose(VALUE self) {
|
1460
|
+
MATRIX4X4();
|
1461
|
+
Matrix4x4 *result = ALLOC(Matrix4x4);
|
1462
|
+
|
1463
|
+
result->m11 = m->m11;
|
1464
|
+
result->m12 = m->m21;
|
1465
|
+
result->m13 = m->m31;
|
1466
|
+
result->m14 = m->m41;
|
1467
|
+
result->m21 = m->m12;
|
1468
|
+
result->m22 = m->m22;
|
1469
|
+
result->m23 = m->m32;
|
1470
|
+
result->m24 = m->m42;
|
1471
|
+
result->m31 = m->m13;
|
1472
|
+
result->m32 = m->m23;
|
1473
|
+
result->m33 = m->m33;
|
1474
|
+
result->m34 = m->m43;
|
1475
|
+
result->m41 = m->m14;
|
1476
|
+
result->m42 = m->m24;
|
1477
|
+
result->m43 = m->m34;
|
1478
|
+
result->m44 = m->m44;
|
1479
|
+
|
1480
|
+
return NUMERIX_WRAP(CLASS_OF(self), result);
|
1481
|
+
}
|
1482
|
+
|
1483
|
+
VALUE rb_matrix4x4_lerp_s(VALUE klass, VALUE matrix1, VALUE matrix2, VALUE amount) {
|
1484
|
+
Matrix4x4 *m1, *m2, *result;
|
1485
|
+
Data_Get_Struct(matrix1, Matrix4x4, m1);
|
1486
|
+
Data_Get_Struct(matrix2, Matrix4x4, m2);
|
1487
|
+
result = ALLOC(Matrix4x4);
|
1488
|
+
float weight = NUMERIX_CLAMP(NUM2FLT(amount), 0.0f, 1.0f);
|
1489
|
+
|
1490
|
+
// First row
|
1491
|
+
result->m11 = m1->m11 + (m2->m11 - m1->m11) * weight;
|
1492
|
+
result->m12 = m1->m12 + (m2->m12 - m1->m12) * weight;
|
1493
|
+
result->m13 = m1->m13 + (m2->m13 - m1->m13) * weight;
|
1494
|
+
result->m14 = m1->m14 + (m2->m14 - m1->m14) * weight;
|
1495
|
+
|
1496
|
+
// Second row
|
1497
|
+
result->m21 = m1->m21 + (m2->m21 - m1->m21) * weight;
|
1498
|
+
result->m22 = m1->m22 + (m2->m22 - m1->m22) * weight;
|
1499
|
+
result->m23 = m1->m23 + (m2->m23 - m1->m23) * weight;
|
1500
|
+
result->m24 = m1->m24 + (m2->m24 - m1->m24) * weight;
|
1501
|
+
|
1502
|
+
// Third row
|
1503
|
+
result->m31 = m1->m31 + (m2->m31 - m1->m31) * weight;
|
1504
|
+
result->m32 = m1->m32 + (m2->m32 - m1->m32) * weight;
|
1505
|
+
result->m33 = m1->m33 + (m2->m33 - m1->m33) * weight;
|
1506
|
+
result->m34 = m1->m34 + (m2->m34 - m1->m34) * weight;
|
1507
|
+
|
1508
|
+
// Fourth row
|
1509
|
+
result->m41 = m1->m41 + (m2->m41 - m1->m41) * weight;
|
1510
|
+
result->m42 = m1->m42 + (m2->m42 - m1->m42) * weight;
|
1511
|
+
result->m43 = m1->m43 + (m2->m43 - m1->m43) * weight;
|
1512
|
+
result->m44 = m1->m44 + (m2->m44 - m1->m44) * weight;
|
1513
|
+
|
1514
|
+
return NUMERIX_WRAP(klass, result);
|
1515
|
+
}
|
1516
|
+
|
1517
|
+
VALUE rb_matrix4x4_negate(VALUE self) {
|
1518
|
+
MATRIX4X4();
|
1519
|
+
Matrix4x4 *result = ALLOC(Matrix4x4);
|
1520
|
+
|
1521
|
+
result->m11 = -m->m11;
|
1522
|
+
result->m12 = -m->m12;
|
1523
|
+
result->m13 = -m->m13;
|
1524
|
+
result->m14 = -m->m14;
|
1525
|
+
result->m21 = -m->m21;
|
1526
|
+
result->m22 = -m->m22;
|
1527
|
+
result->m23 = -m->m23;
|
1528
|
+
result->m24 = -m->m24;
|
1529
|
+
result->m31 = -m->m31;
|
1530
|
+
result->m32 = -m->m32;
|
1531
|
+
result->m33 = -m->m33;
|
1532
|
+
result->m34 = -m->m34;
|
1533
|
+
result->m41 = -m->m41;
|
1534
|
+
result->m42 = -m->m42;
|
1535
|
+
result->m43 = -m->m43;
|
1536
|
+
result->m44 = -m->m44;
|
1537
|
+
|
1538
|
+
return NUMERIX_WRAP(CLASS_OF(self), result);
|
1539
|
+
}
|
1540
|
+
|
1541
|
+
VALUE rb_matrix4x4_add(VALUE self, VALUE other) {
|
1542
|
+
Matrix4x4 *m1, *m2, *result;
|
1543
|
+
Data_Get_Struct(self, Matrix4x4, m1);
|
1544
|
+
Data_Get_Struct(other, Matrix4x4, m2);
|
1545
|
+
result = ALLOC(Matrix4x4);
|
1546
|
+
|
1547
|
+
result->m11 = m1->m11 + m2->m11;
|
1548
|
+
result->m12 = m1->m12 + m2->m12;
|
1549
|
+
result->m13 = m1->m13 + m2->m13;
|
1550
|
+
result->m14 = m1->m14 + m2->m14;
|
1551
|
+
result->m21 = m1->m21 + m2->m21;
|
1552
|
+
result->m22 = m1->m22 + m2->m22;
|
1553
|
+
result->m23 = m1->m23 + m2->m23;
|
1554
|
+
result->m24 = m1->m24 + m2->m24;
|
1555
|
+
result->m31 = m1->m31 + m2->m31;
|
1556
|
+
result->m32 = m1->m32 + m2->m32;
|
1557
|
+
result->m33 = m1->m33 + m2->m33;
|
1558
|
+
result->m34 = m1->m34 + m2->m34;
|
1559
|
+
result->m41 = m1->m41 + m2->m41;
|
1560
|
+
result->m42 = m1->m42 + m2->m42;
|
1561
|
+
result->m43 = m1->m43 + m2->m43;
|
1562
|
+
result->m44 = m1->m44 + m2->m44;
|
1563
|
+
|
1564
|
+
return NUMERIX_WRAP(CLASS_OF(self), result);
|
1565
|
+
}
|
1566
|
+
|
1567
|
+
VALUE rb_matrix4x4_subtract(VALUE self, VALUE other) {
|
1568
|
+
Matrix4x4 *m1, *m2, *result;
|
1569
|
+
Data_Get_Struct(self, Matrix4x4, m1);
|
1570
|
+
Data_Get_Struct(other, Matrix4x4, m2);
|
1571
|
+
result = ALLOC(Matrix4x4);
|
1572
|
+
|
1573
|
+
result->m11 = m1->m11 - m2->m11;
|
1574
|
+
result->m12 = m1->m12 - m2->m12;
|
1575
|
+
result->m13 = m1->m13 - m2->m13;
|
1576
|
+
result->m14 = m1->m14 - m2->m14;
|
1577
|
+
result->m21 = m1->m21 - m2->m21;
|
1578
|
+
result->m22 = m1->m22 - m2->m22;
|
1579
|
+
result->m23 = m1->m23 - m2->m23;
|
1580
|
+
result->m24 = m1->m24 - m2->m24;
|
1581
|
+
result->m31 = m1->m31 - m2->m31;
|
1582
|
+
result->m32 = m1->m32 - m2->m32;
|
1583
|
+
result->m33 = m1->m33 - m2->m33;
|
1584
|
+
result->m34 = m1->m34 - m2->m34;
|
1585
|
+
result->m41 = m1->m41 - m2->m41;
|
1586
|
+
result->m42 = m1->m42 - m2->m42;
|
1587
|
+
result->m43 = m1->m43 - m2->m43;
|
1588
|
+
result->m44 = m1->m44 - m2->m44;
|
1589
|
+
|
1590
|
+
return NUMERIX_WRAP(CLASS_OF(self), result);
|
1591
|
+
}
|
1592
|
+
|
1593
|
+
VALUE rb_matrix4x4_multiply(VALUE self, VALUE other) {
|
1594
|
+
Matrix4x4 *m1, *result;
|
1595
|
+
Data_Get_Struct(self, Matrix4x4, m1);
|
1596
|
+
result = ALLOC(Matrix4x4);
|
1597
|
+
|
1598
|
+
if (NUMERIX_TYPE_P(other, rb_cMatrix4x4)) {
|
1599
|
+
Matrix4x4 *m2;
|
1600
|
+
Data_Get_Struct(other, Matrix4x4, m2);
|
1601
|
+
|
1602
|
+
// First row
|
1603
|
+
result->m11 = m1->m11 * m2->m11 + m1->m12 * m2->m21 + m1->m13 * m2->m31 + m1->m14 * m2->m41;
|
1604
|
+
result->m12 = m1->m11 * m2->m12 + m1->m12 * m2->m22 + m1->m13 * m2->m32 + m1->m14 * m2->m42;
|
1605
|
+
result->m13 = m1->m11 * m2->m13 + m1->m12 * m2->m23 + m1->m13 * m2->m33 + m1->m14 * m2->m43;
|
1606
|
+
result->m14 = m1->m11 * m2->m14 + m1->m12 * m2->m24 + m1->m13 * m2->m34 + m1->m14 * m2->m44;
|
1607
|
+
|
1608
|
+
// Second row
|
1609
|
+
result->m21 = m1->m21 * m2->m11 + m1->m22 * m2->m21 + m1->m23 * m2->m31 + m1->m24 * m2->m41;
|
1610
|
+
result->m22 = m1->m21 * m2->m12 + m1->m22 * m2->m22 + m1->m23 * m2->m32 + m1->m24 * m2->m42;
|
1611
|
+
result->m23 = m1->m21 * m2->m13 + m1->m22 * m2->m23 + m1->m23 * m2->m33 + m1->m24 * m2->m43;
|
1612
|
+
result->m24 = m1->m21 * m2->m14 + m1->m22 * m2->m24 + m1->m23 * m2->m34 + m1->m24 * m2->m44;
|
1613
|
+
|
1614
|
+
// Third row
|
1615
|
+
result->m31 = m1->m31 * m2->m11 + m1->m32 * m2->m21 + m1->m33 * m2->m31 + m1->m34 * m2->m41;
|
1616
|
+
result->m32 = m1->m31 * m2->m12 + m1->m32 * m2->m22 + m1->m33 * m2->m32 + m1->m34 * m2->m42;
|
1617
|
+
result->m33 = m1->m31 * m2->m13 + m1->m32 * m2->m23 + m1->m33 * m2->m33 + m1->m34 * m2->m43;
|
1618
|
+
result->m34 = m1->m31 * m2->m14 + m1->m32 * m2->m24 + m1->m33 * m2->m34 + m1->m34 * m2->m44;
|
1619
|
+
|
1620
|
+
// Fourth row
|
1621
|
+
result->m41 = m1->m41 * m2->m11 + m1->m42 * m2->m21 + m1->m43 * m2->m31 + m1->m44 * m2->m41;
|
1622
|
+
result->m42 = m1->m41 * m2->m12 + m1->m42 * m2->m22 + m1->m43 * m2->m32 + m1->m44 * m2->m42;
|
1623
|
+
result->m43 = m1->m41 * m2->m13 + m1->m42 * m2->m23 + m1->m43 * m2->m33 + m1->m44 * m2->m43;
|
1624
|
+
result->m44 = m1->m41 * m2->m14 + m1->m42 * m2->m24 + m1->m43 * m2->m34 + m1->m44 * m2->m44;
|
1625
|
+
} else {
|
1626
|
+
float scalar = NUM2FLT(other);
|
1627
|
+
result->m11 = m1->m11 * scalar;
|
1628
|
+
result->m12 = m1->m12 * scalar;
|
1629
|
+
result->m13 = m1->m13 * scalar;
|
1630
|
+
result->m14 = m1->m14 * scalar;
|
1631
|
+
result->m21 = m1->m21 * scalar;
|
1632
|
+
result->m22 = m1->m22 * scalar;
|
1633
|
+
result->m23 = m1->m23 * scalar;
|
1634
|
+
result->m24 = m1->m24 * scalar;
|
1635
|
+
result->m31 = m1->m31 * scalar;
|
1636
|
+
result->m32 = m1->m32 * scalar;
|
1637
|
+
result->m33 = m1->m33 * scalar;
|
1638
|
+
result->m34 = m1->m34 * scalar;
|
1639
|
+
result->m41 = m1->m41 * scalar;
|
1640
|
+
result->m42 = m1->m42 * scalar;
|
1641
|
+
result->m43 = m1->m43 * scalar;
|
1642
|
+
result->m44 = m1->m44 * scalar;
|
1643
|
+
}
|
1644
|
+
|
1645
|
+
return NUMERIX_WRAP(CLASS_OF(self), result);
|
1646
|
+
}
|
1647
|
+
|
1648
|
+
VALUE rb_matrix4x4_invert(VALUE self) {
|
1649
|
+
Matrix4x4 *mat, *result;
|
1650
|
+
Data_Get_Struct(self, Matrix4x4, mat);
|
1651
|
+
result = ALLOC(Matrix4x4);
|
1652
|
+
// -1
|
1653
|
+
// If you have matrix M, inverse Matrix M can compute
|
1654
|
+
//
|
1655
|
+
// -1 1
|
1656
|
+
// M = --------- A
|
1657
|
+
// det(M)
|
1658
|
+
//
|
1659
|
+
// A is adjugate (adjoint) of M, where,
|
1660
|
+
//
|
1661
|
+
// T
|
1662
|
+
// A = C
|
1663
|
+
//
|
1664
|
+
// C is Cofactor matrix of M, where,
|
1665
|
+
// i + j
|
1666
|
+
// C = (-1) * det(M )
|
1667
|
+
// ij ij
|
1668
|
+
//
|
1669
|
+
// [ a b c d ]
|
1670
|
+
// M = [ e f g h ]
|
1671
|
+
// [ i j k l ]
|
1672
|
+
// [ m n o p ]
|
1673
|
+
//
|
1674
|
+
// First Row
|
1675
|
+
// 2 | f g h |
|
1676
|
+
// C = (-1) | j k l | = + ( f ( kp - lo ) - g ( jp - ln ) + h ( jo - kn ) )
|
1677
|
+
// 11 | n o p |
|
1678
|
+
//
|
1679
|
+
// 3 | e g h |
|
1680
|
+
// C = (-1) | i k l | = - ( e ( kp - lo ) - g ( ip - lm ) + h ( io - km ) )
|
1681
|
+
// 12 | m o p |
|
1682
|
+
//
|
1683
|
+
// 4 | e f h |
|
1684
|
+
// C = (-1) | i j l | = + ( e ( jp - ln ) - f ( ip - lm ) + h ( in - jm ) )
|
1685
|
+
// 13 | m n p |
|
1686
|
+
//
|
1687
|
+
// 5 | e f g |
|
1688
|
+
// C = (-1) | i j k | = - ( e ( jo - kn ) - f ( io - km ) + g ( in - jm ) )
|
1689
|
+
// 14 | m n o |
|
1690
|
+
//
|
1691
|
+
// Second Row
|
1692
|
+
// 3 | b c d |
|
1693
|
+
// C = (-1) | j k l | = - ( b ( kp - lo ) - c ( jp - ln ) + d ( jo - kn ) )
|
1694
|
+
// 21 | n o p |
|
1695
|
+
//
|
1696
|
+
// 4 | a c d |
|
1697
|
+
// C = (-1) | i k l | = + ( a ( kp - lo ) - c ( ip - lm ) + d ( io - km ) )
|
1698
|
+
// 22 | m o p |
|
1699
|
+
//
|
1700
|
+
// 5 | a b d |
|
1701
|
+
// C = (-1) | i j l | = - ( a ( jp - ln ) - b ( ip - lm ) + d ( in - jm ) )
|
1702
|
+
// 23 | m n p |
|
1703
|
+
//
|
1704
|
+
// 6 | a b c |
|
1705
|
+
// C = (-1) | i j k | = + ( a ( jo - kn ) - b ( io - km ) + c ( in - jm ) )
|
1706
|
+
// 24 | m n o |
|
1707
|
+
//
|
1708
|
+
// Third Row
|
1709
|
+
// 4 | b c d |
|
1710
|
+
// C = (-1) | f g h | = + ( b ( gp - ho ) - c ( fp - hn ) + d ( fo - gn ) )
|
1711
|
+
// 31 | n o p |
|
1712
|
+
//
|
1713
|
+
// 5 | a c d |
|
1714
|
+
// C = (-1) | e g h | = - ( a ( gp - ho ) - c ( ep - hm ) + d ( eo - gm ) )
|
1715
|
+
// 32 | m o p |
|
1716
|
+
//
|
1717
|
+
// 6 | a b d |
|
1718
|
+
// C = (-1) | e f h | = + ( a ( fp - hn ) - b ( ep - hm ) + d ( en - fm ) )
|
1719
|
+
// 33 | m n p |
|
1720
|
+
//
|
1721
|
+
// 7 | a b c |
|
1722
|
+
// C = (-1) | e f g | = - ( a ( fo - gn ) - b ( eo - gm ) + c ( en - fm ) )
|
1723
|
+
// 34 | m n o |
|
1724
|
+
//
|
1725
|
+
// Fourth Row
|
1726
|
+
// 5 | b c d |
|
1727
|
+
// C = (-1) | f g h | = - ( b ( gl - hk ) - c ( fl - hj ) + d ( fk - gj ) )
|
1728
|
+
// 41 | j k l |
|
1729
|
+
//
|
1730
|
+
// 6 | a c d |
|
1731
|
+
// C = (-1) | e g h | = + ( a ( gl - hk ) - c ( el - hi ) + d ( ek - gi ) )
|
1732
|
+
// 42 | i k l |
|
1733
|
+
//
|
1734
|
+
// 7 | a b d |
|
1735
|
+
// C = (-1) | e f h | = - ( a ( fl - hj ) - b ( el - hi ) + d ( ej - fi ) )
|
1736
|
+
// 43 | i j l |
|
1737
|
+
//
|
1738
|
+
// 8 | a b c |
|
1739
|
+
// C = (-1) | e f g | = + ( a ( fk - gj ) - b ( ek - gi ) + c ( ej - fi ) )
|
1740
|
+
// 44 | i j k |
|
1741
|
+
//
|
1742
|
+
// Cost of operation
|
1743
|
+
// 53 adds, 104 muls, and 1 div.
|
1744
|
+
float a = mat->m11, b = mat->m12, c = mat->m13, d = mat->m14;
|
1745
|
+
float e = mat->m21, f = mat->m22, g = mat->m23, h = mat->m24;
|
1746
|
+
float i = mat->m31, j = mat->m32, k = mat->m33, l = mat->m34;
|
1747
|
+
float m = mat->m41, n = mat->m42, o = mat->m43, p = mat->m44;
|
1748
|
+
|
1749
|
+
float kp_lo = k * p - l * o;
|
1750
|
+
float jp_ln = j * p - l * n;
|
1751
|
+
float jo_kn = j * o - k * n;
|
1752
|
+
float ip_lm = i * p - l * m;
|
1753
|
+
float io_km = i * o - k * m;
|
1754
|
+
float in_jm = i * n - j * m;
|
1755
|
+
|
1756
|
+
float a11 = +(f * kp_lo - g * jp_ln + h * jo_kn);
|
1757
|
+
float a12 = -(e * kp_lo - g * ip_lm + h * io_km);
|
1758
|
+
float a13 = +(e * jp_ln - f * ip_lm + h * in_jm);
|
1759
|
+
float a14 = -(e * jo_kn - f * io_km + g * in_jm);
|
1760
|
+
|
1761
|
+
float det = a * a11 + b * a12 + c * a13 + d * a14;
|
1762
|
+
|
1763
|
+
if (fabsf(det) < FLT_EPSILON) {
|
1764
|
+
// invalid
|
1765
|
+
float *matp = (float *)mat;
|
1766
|
+
for (int i = 0; i < 16; i++)
|
1767
|
+
matp[i] = NAN;
|
1768
|
+
} else {
|
1769
|
+
float invDet = 1.0f / det;
|
1770
|
+
|
1771
|
+
result->m11 = a11 * invDet;
|
1772
|
+
result->m21 = a12 * invDet;
|
1773
|
+
result->m31 = a13 * invDet;
|
1774
|
+
result->m41 = a14 * invDet;
|
1775
|
+
|
1776
|
+
result->m12 = -(b * kp_lo - c * jp_ln + d * jo_kn) * invDet;
|
1777
|
+
result->m22 = +(a * kp_lo - c * ip_lm + d * io_km) * invDet;
|
1778
|
+
result->m32 = -(a * jp_ln - b * ip_lm + d * in_jm) * invDet;
|
1779
|
+
result->m42 = +(a * jo_kn - b * io_km + c * in_jm) * invDet;
|
1780
|
+
|
1781
|
+
float gp_ho = g * p - h * o;
|
1782
|
+
float fp_hn = f * p - h * n;
|
1783
|
+
float fo_gn = f * o - g * n;
|
1784
|
+
float ep_hm = e * p - h * m;
|
1785
|
+
float eo_gm = e * o - g * m;
|
1786
|
+
float en_fm = e * n - f * m;
|
1787
|
+
|
1788
|
+
result->m13 = +(b * gp_ho - c * fp_hn + d * fo_gn) * invDet;
|
1789
|
+
result->m23 = -(a * gp_ho - c * ep_hm + d * eo_gm) * invDet;
|
1790
|
+
result->m33 = +(a * fp_hn - b * ep_hm + d * en_fm) * invDet;
|
1791
|
+
result->m43 = -(a * fo_gn - b * eo_gm + c * en_fm) * invDet;
|
1792
|
+
|
1793
|
+
float gl_hk = g * l - h * k;
|
1794
|
+
float fl_hj = f * l - h * j;
|
1795
|
+
float fk_gj = f * k - g * j;
|
1796
|
+
float el_hi = e * l - h * i;
|
1797
|
+
float ek_gi = e * k - g * i;
|
1798
|
+
float ej_fi = e * j - f * i;
|
1799
|
+
|
1800
|
+
result->m14 = -(b * gl_hk - c * fl_hj + d * fk_gj) * invDet;
|
1801
|
+
result->m24 = +(a * gl_hk - c * el_hi + d * ek_gi) * invDet;
|
1802
|
+
result->m34 = -(a * fl_hj - b * el_hi + d * ej_fi) * invDet;
|
1803
|
+
result->m44 = +(a * fk_gj - b * ek_gi + c * ej_fi) * invDet;
|
1804
|
+
}
|
1805
|
+
|
1806
|
+
return NUMERIX_WRAP(CLASS_OF(self), result);
|
1807
|
+
}
|