snow-math 1.1.0 → 1.2.1

Sign up to get free protection for your applications and to get access to all the features.
data/ext/snow-math/mat4.c CHANGED
@@ -42,10 +42,22 @@ void mat4_identity(mat4_t out)
42
42
 
43
43
  void mat4_copy(const mat4_t in, mat4_t out)
44
44
  {
45
- if (in != out) {
46
- int index = 0;
47
- for (; index < 16; ++index) out[index] = in[index];
48
- }
45
+ out[0 ] = in[0 ];
46
+ out[1 ] = in[1 ];
47
+ out[2 ] = in[2 ];
48
+ out[3 ] = in[3 ];
49
+ out[4 ] = in[4 ];
50
+ out[5 ] = in[5 ];
51
+ out[6 ] = in[6 ];
52
+ out[7 ] = in[7 ];
53
+ out[8 ] = in[8 ];
54
+ out[9 ] = in[9 ];
55
+ out[10] = in[10];
56
+ out[11] = in[11];
57
+ out[12] = in[12];
58
+ out[13] = in[13];
59
+ out[14] = in[14];
60
+ out[15] = in[15];
49
61
  }
50
62
 
51
63
  void mat4_set(
@@ -73,6 +85,19 @@ void mat4_set(
73
85
  out[15] = m15;
74
86
  }
75
87
 
88
+ void mat4_to_mat3(const mat4_t in, mat3_t out)
89
+ {
90
+ out[0] = in[0];
91
+ out[1] = in[1];
92
+ out[2] = in[2];
93
+ out[3] = in[4];
94
+ out[4] = in[5];
95
+ out[5] = in[6];
96
+ out[6] = in[8];
97
+ out[7] = in[9];
98
+ out[8] = in[10];
99
+ }
100
+
76
101
  void mat4_set_axes3(const vec3_t x, const vec3_t y, const vec3_t z, const vec3_t w, mat4_t out)
77
102
  {
78
103
  out[0] = x[0];
@@ -418,26 +443,26 @@ int mat4_equals(const mat4_t left, const mat4_t right)
418
443
  to vary between checks
419
444
  */
420
445
  return (
421
- s_fabs(left[0] - right[0]) < S_FLOAT_EPSILON &&
422
- s_fabs(left[1] - right[1]) < S_FLOAT_EPSILON &&
423
- s_fabs(left[2] - right[2]) < S_FLOAT_EPSILON &&
424
-
425
- s_fabs(left[4] - right[4]) < S_FLOAT_EPSILON &&
426
- s_fabs(left[5] - right[5]) < S_FLOAT_EPSILON &&
427
- s_fabs(left[6] - right[6]) < S_FLOAT_EPSILON &&
428
-
429
- s_fabs(left[8] - right[8]) < S_FLOAT_EPSILON &&
430
- s_fabs(left[9] - right[9]) < S_FLOAT_EPSILON &&
431
- s_fabs(left[10] - right[10]) < S_FLOAT_EPSILON &&
432
-
433
- s_fabs(left[12] - right[12]) < S_FLOAT_EPSILON &&
434
- s_fabs(left[13] - right[13]) < S_FLOAT_EPSILON &&
435
- s_fabs(left[14] - right[14]) < S_FLOAT_EPSILON &&
436
-
437
- s_fabs(left[3] - right[3]) < S_FLOAT_EPSILON &&
438
- s_fabs(left[7] - right[7]) < S_FLOAT_EPSILON &&
439
- s_fabs(left[11] - right[11]) < S_FLOAT_EPSILON &&
440
- s_fabs(left[15] - right[15]) < S_FLOAT_EPSILON
446
+ float_equals(left[0], right[0]) &&
447
+ float_equals(left[1], right[1]) &&
448
+ float_equals(left[2], right[2]) &&
449
+
450
+ float_equals(left[4], right[4]) &&
451
+ float_equals(left[5], right[5]) &&
452
+ float_equals(left[6], right[6]) &&
453
+
454
+ float_equals(left[8], right[8]) &&
455
+ float_equals(left[9], right[9]) &&
456
+ float_equals(left[10], right[10]) &&
457
+
458
+ float_equals(left[12], right[12]) &&
459
+ float_equals(left[13], right[13]) &&
460
+ float_equals(left[14], right[14]) &&
461
+
462
+ float_equals(left[3], right[3]) &&
463
+ float_equals(left[7], right[7]) &&
464
+ float_equals(left[11], right[11]) &&
465
+ float_equals(left[15], right[15])
441
466
  );
442
467
  }
443
468
 
@@ -661,25 +686,50 @@ void mat4_translation(s_float_t x, s_float_t y, s_float_t z, mat4_t out) {
661
686
  void mat4_multiply(const mat4_t left, const mat4_t right, mat4_t out)
662
687
  {
663
688
  mat4_t temp;
664
- int index;
689
+ s_float_t cx, cy, cz, cw;
665
690
 
666
691
  // Transpose the left matrix so we can be a little more cache-friendly.
667
692
  mat4_transpose(left, temp);
668
693
 
669
- for (index = 0; index < 4; ++index) {
670
- const int inner_index = index * 4;
671
- s_float_t cx, cy, cz, cw;
672
-
673
- cx = temp[inner_index];
674
- cy = temp[inner_index + 1];
675
- cz = temp[inner_index + 2];
676
- cw = temp[inner_index + 3];
677
-
678
- temp[inner_index] = (cx * right[0 ]) + (cy * right[1 ]) + (cz * right[2 ]) + (cw * right[3 ]);
679
- temp[inner_index + 1] = (cx * right[4 ]) + (cy * right[5 ]) + (cz * right[6 ]) + (cw * right[7 ]);
680
- temp[inner_index + 2] = (cx * right[8 ]) + (cy * right[9 ]) + (cz * right[10]) + (cw * right[11]);
681
- temp[inner_index + 3] = (cx * right[12]) + (cy * right[13]) + (cz * right[14]) + (cw * right[15]);
682
- }
694
+ cx = temp[0];
695
+ cy = temp[1];
696
+ cz = temp[2];
697
+ cw = temp[3];
698
+
699
+ temp[0] = (cx * right[0 ]) + (cy * right[1 ]) + (cz * right[2 ]) + (cw * right[3 ]);
700
+ temp[1] = (cx * right[4 ]) + (cy * right[5 ]) + (cz * right[6 ]) + (cw * right[7 ]);
701
+ temp[2] = (cx * right[8 ]) + (cy * right[9 ]) + (cz * right[10]) + (cw * right[11]);
702
+ temp[3] = (cx * right[12]) + (cy * right[13]) + (cz * right[14]) + (cw * right[15]);
703
+
704
+ cx = temp[4];
705
+ cy = temp[5];
706
+ cz = temp[6];
707
+ cw = temp[7];
708
+
709
+ temp[4] = (cx * right[0 ]) + (cy * right[1 ]) + (cz * right[2 ]) + (cw * right[3 ]);
710
+ temp[5] = (cx * right[4 ]) + (cy * right[5 ]) + (cz * right[6 ]) + (cw * right[7 ]);
711
+ temp[6] = (cx * right[8 ]) + (cy * right[9 ]) + (cz * right[10]) + (cw * right[11]);
712
+ temp[7] = (cx * right[12]) + (cy * right[13]) + (cz * right[14]) + (cw * right[15]);
713
+
714
+ cx = temp[8];
715
+ cy = temp[9];
716
+ cz = temp[10];
717
+ cw = temp[11];
718
+
719
+ temp[8] = (cx * right[0 ]) + (cy * right[1 ]) + (cz * right[2 ]) + (cw * right[3 ]);
720
+ temp[9] = (cx * right[4 ]) + (cy * right[5 ]) + (cz * right[6 ]) + (cw * right[7 ]);
721
+ temp[10] = (cx * right[8 ]) + (cy * right[9 ]) + (cz * right[10]) + (cw * right[11]);
722
+ temp[11] = (cx * right[12]) + (cy * right[13]) + (cz * right[14]) + (cw * right[15]);
723
+
724
+ cx = temp[12];
725
+ cy = temp[13];
726
+ cz = temp[14];
727
+ cw = temp[15];
728
+
729
+ temp[12] = (cx * right[0 ]) + (cy * right[1 ]) + (cz * right[2 ]) + (cw * right[3 ]);
730
+ temp[13] = (cx * right[4 ]) + (cy * right[5 ]) + (cz * right[6 ]) + (cw * right[7 ]);
731
+ temp[14] = (cx * right[8 ]) + (cy * right[9 ]) + (cz * right[10]) + (cw * right[11]);
732
+ temp[15] = (cx * right[12]) + (cy * right[13]) + (cz * right[14]) + (cw * right[15]);
683
733
 
684
734
  mat4_transpose(temp, out);
685
735
  }
@@ -719,18 +769,22 @@ void mat4_inv_rotate_vec3(const mat4_t left, const vec3_t right, vec3_t out)
719
769
 
720
770
  void mat4_scale(const mat4_t in, s_float_t x, s_float_t y, s_float_t z, mat4_t out)
721
771
  {
722
- mat4_copy(in, out);
723
- out[0] *= x;
724
- out[4] *= x;
725
- out[8] *= x;
726
-
727
- out[1] *= y;
728
- out[5] *= y;
729
- out[9] *= y;
730
-
731
- out[2 ] *= z;
732
- out[6 ] *= z;
733
- out[10] *= z;
772
+ out[0] = in[0] * x;
773
+ out[1] = in[1] * y;
774
+ out[2] = in[2] * z;
775
+ out[3] = in[3];
776
+ out[4] = in[4] * x;
777
+ out[5] = in[5] * y;
778
+ out[6] = in[6] * z;
779
+ out[7] = in[7];
780
+ out[8] = in[8] * x;
781
+ out[9] = in[9] * y;
782
+ out[10] = in[10] * z;
783
+ out[11] = in[11];
784
+ out[12] = in[12];
785
+ out[13] = in[13];
786
+ out[14] = in[14];
787
+ out[15] = in[15];
734
788
  }
735
789
 
736
790
  #if defined(__cplusplus)
@@ -32,25 +32,28 @@ extern "C" {
32
32
  /* Typedefs and macros for specific floating point types */
33
33
  #ifdef USE_FLOAT
34
34
  typedef float s_float_t;
35
- #define s_cos cosf
36
- #define s_sin sinf
37
- #define s_tan tanf
38
- #define s_acos acosf
39
- #define s_asin asinf
40
- #define s_atan atanf
41
- #define s_fabs fabsf
35
+ #define s_cos(X) (cosf((X)))
36
+ #define s_sin(X) (sinf((X)))
37
+ #define s_tan(X) (tanf((X)))
38
+ #define s_acos(X) (acosf((X)))
39
+ #define s_asin(X) (asinf((X)))
40
+ #define s_atan(X) (atanf((X)))
41
+ #define s_fabs(X) (fabsf((X)))
42
+ #define s_sqrt(X) (sqrtf((X)))
42
43
  #else
43
44
  typedef double s_float_t;
44
- #define s_cos cos
45
- #define s_sin sin
46
- #define s_tan tan
47
- #define s_acos acos
48
- #define s_asin asin
49
- #define s_atan atan
50
- #define s_fabs fabs
45
+ #define s_cos(X) (cos((X)))
46
+ #define s_sin(X) (sin((X)))
47
+ #define s_tan(X) (tan((X)))
48
+ #define s_acos(X) (acos((X)))
49
+ #define s_asin(X) (asin((X)))
50
+ #define s_atan(X) (atan((X)))
51
+ #define s_fabs(X) (fabs((X)))
52
+ #define s_sqrt(X) (sqrt((X)))
51
53
  #endif
52
54
 
53
55
  typedef s_float_t mat4_t[16];
56
+ typedef s_float_t mat3_t[9];
54
57
  typedef s_float_t vec4_t[4];
55
58
  typedef s_float_t vec3_t[3];
56
59
  typedef s_float_t vec2_t[2];
@@ -114,6 +117,8 @@ void vec3_multiply(const vec3_t left, const vec3_t right, vec3_t out);
114
117
  void vec3_negate(const vec3_t v, vec3_t out);
115
118
  void vec3_inverse(const vec3_t v, vec3_t out);
116
119
 
120
+ void vec3_project(const vec3_t in, const vec3_t normal, vec3_t out);
121
+ void vec3_reflect(const vec3_t in, const vec3_t normal, vec3_t out);
117
122
  void vec3_cross_product(const vec3_t left, const vec3_t right, vec3_t out);
118
123
  s_float_t vec3_dot_product(const vec3_t left, const vec3_t right);
119
124
 
@@ -154,6 +159,8 @@ void vec4_multiply(const vec4_t left, const vec4_t right, vec4_t out);
154
159
  void vec4_negate(const vec4_t v, vec4_t out);
155
160
  void vec4_inverse(const vec4_t v, vec4_t out);
156
161
 
162
+ void vec4_project(const vec4_t in, const vec4_t normal, vec4_t out);
163
+ void vec4_reflect(const vec4_t in, const vec4_t normal, vec4_t out);
157
164
  s_float_t vec4_dot_product(const vec4_t left, const vec4_t right);
158
165
 
159
166
  void vec4_scale(const vec4_t v, s_float_t scalar, vec4_t out);
@@ -163,6 +170,40 @@ int vec4_equals(const vec4_t left, const vec4_t right);
163
170
 
164
171
 
165
172
 
173
+ /*==============================================================================
174
+
175
+ 3x3 Matrix (mat3_t)
176
+
177
+ ==============================================================================*/
178
+
179
+ extern const mat3_t g_mat3_identity;
180
+
181
+ void mat3_identity(mat3_t out);
182
+ void mat3_copy(const mat3_t in, mat3_t out);
183
+ void mat3_set(s_float_t m00, s_float_t m10, s_float_t m20,
184
+ s_float_t m01, s_float_t m11, s_float_t m21,
185
+ s_float_t m02, s_float_t m12, s_float_t m22,
186
+ mat3_t out);
187
+ void mat3_to_mat4(const mat3_t in, mat4_t out);
188
+ void mat3_rotation(s_float_t angle, s_float_t x, s_float_t y, s_float_t z, mat3_t out);
189
+ void mat3_from_quat(const quat_t in, mat3_t out);
190
+ void mat3_transpose(const mat3_t in, mat3_t out);
191
+ void mat3_scale(const mat3_t in, s_float_t x, s_float_t y, s_float_t z, mat3_t out);
192
+ void mat3_orthogonal(const mat3_t in, mat3_t out);
193
+ void mat3_multiply(const mat3_t lhs, const mat3_t rhs, mat3_t out);
194
+ void mat3_rotate_vec3(const mat3_t lhs, const vec3_t rhs, vec3_t out);
195
+ void mat3_inv_rotate_vec3(const mat3_t lhs, const vec3_t rhs, vec3_t out);
196
+ void mat3_cofactor(const mat3_t in, mat3_t out);
197
+ void mat3_adjoint(const mat3_t in, mat3_t out);
198
+ void mat3_get_row3(const mat3_t in, int row, vec3_t out);
199
+ void mat3_get_column3(const mat3_t in, int column, vec3_t out);
200
+ void mat3_set_row3(int row, const vec3_t in, mat3_t out);
201
+ void mat3_set_column3(int column, const vec3_t in, mat3_t out);
202
+ s_float_t mat3_determinant(const mat3_t in);
203
+ int mat3_equals(const mat3_t lhs, const mat3_t rhs);
204
+ int mat3_inverse(const mat3_t in, mat3_t out);
205
+
206
+
166
207
  /*==============================================================================
167
208
 
168
209
  4x4 Matrix (mat4_t)
@@ -179,6 +220,7 @@ void mat4_set(
179
220
  s_float_t m08, s_float_t m09, s_float_t m10, s_float_t m11,
180
221
  s_float_t m12, s_float_t m13, s_float_t m14, s_float_t m15,
181
222
  mat4_t out);
223
+ void mat4_to_mat3(const mat4_t in, mat3_t out);
182
224
 
183
225
  void mat4_set_axes3(const vec3_t x, const vec3_t y, const vec3_t z, const vec3_t w, mat4_t out);
184
226
  void mat4_get_axes3(const mat4_t m, vec3_t x, vec3_t y, vec3_t z, vec3_t w);
@@ -251,6 +293,7 @@ void quat_multiply_vec3(const quat_t left, const vec3_t right, vec3_t o
251
293
 
252
294
  void quat_from_angle_axis(s_float_t angle, s_float_t x, s_float_t y, s_float_t z, quat_t out);
253
295
  void quat_from_mat4(const mat4_t mat, quat_t out);
296
+ void quat_from_mat3(const mat3_t mat, quat_t out);
254
297
 
255
298
  void quat_slerp(const quat_t from, const quat_t to, s_float_t delta, quat_t out);
256
299
 
data/ext/snow-math/quat.c CHANGED
@@ -108,7 +108,7 @@ void quat_from_mat4(const mat4_t mat, quat_t out)
108
108
 
109
109
  trace = mat[0] + mat[5] + mat[10];
110
110
  if (trace > 0) {
111
- r = sqrtf(trace + 1.0);
111
+ r = s_sqrt(trace + 1.0);
112
112
  out[3] = r * 0.5;
113
113
  r = 0.5 / r;
114
114
  out[0] = (mat[9] - mat[6]) * r;
@@ -116,10 +116,13 @@ void quat_from_mat4(const mat4_t mat, quat_t out)
116
116
  out[2] = (mat[4] - mat[1]) * r;
117
117
  } else {
118
118
  index = 0;
119
- if (mat[5] > mat[0]) index = 1;
120
- if (mat[10] > mat[index * 5]) index = 2;
119
+ if (mat[10] > mat[index * 5]) {
120
+ index = 2;
121
+ } else if (mat[5] > mat[0]) {
122
+ index = 1;
123
+ }
121
124
 
122
- r = sqrtf(mat[index * 5] - (mat[((index + 1)) % 3 * 5] + mat[((index + 2) % 3) * 5]) + 1.0);
125
+ r = s_sqrt(mat[index * 5] - (mat[((index + 1)) % 3 * 5] + mat[((index + 2) % 3) * 5]) + 1.0);
123
126
  out[index] = r * 0.5;
124
127
 
125
128
  if (r) r = 0.5 / r;
@@ -147,6 +150,65 @@ void quat_from_mat4(const mat4_t mat, quat_t out)
147
150
  }
148
151
  }
149
152
 
153
+ void quat_from_mat3(const mat3_t mat, quat_t out)
154
+ {
155
+ s_float_t trace, r;
156
+ const s_float_t *m = m;
157
+ s_float_t m01 = mat[3], m02 = mat[6], m10 = mat[1],
158
+ m12 = mat[7], m20 = mat[2], m21 = mat[5];
159
+
160
+ trace = mat[0] + mat[4] + mat[8];
161
+
162
+ if (trace > 0.0) {
163
+ r = s_sqrt(trace + 1);
164
+ out[3] = r * 0.5;
165
+ r = 0.5 / r;
166
+ out[0] = (m12 - m21) * r;
167
+ out[1] = (m20 - m02) * r;
168
+ out[2] = (m01 - m10) * r;
169
+ } else {
170
+ int index = 0;
171
+ if (mat[8] > (index ? mat[4] : mat[0])) {
172
+ index = 2;
173
+ } else if (mat[4] > mat[0]) {
174
+ index = 1;
175
+ }
176
+
177
+ switch (index) {
178
+ default:
179
+ case 0:
180
+ r = out[0] = s_sqrt(mat[0] - (mat[4] + mat[8]) + 1) * 0.5;
181
+ if (r != 0.0 && r != -0.0) {
182
+ r = 0.5 / r;
183
+ }
184
+ out[1] = (m10 + m01) * r;
185
+ out[2] = (m20 + m02) * r;
186
+ out[3] = (m12 - m21) * r;
187
+ break;
188
+
189
+ case 1:
190
+ r = out[1] = s_sqrt(mat[4] - (mat[8] + mat[0]) + 1) * 0.5;
191
+ if (r != 0.0 && r != -0.0) {
192
+ r = 0.5 / r;
193
+ }
194
+ out[0] = (m10 + m01) * r;
195
+ out[2] = (m12 + m21) * r;
196
+ out[3] = (m20 - m02) * r;
197
+ break;
198
+
199
+ case 2:
200
+ r = out[2] = s_sqrt(mat[4] - (mat[0] + mat[4]) + 1) * 0.5;
201
+ if (r != 0.0 && r != -0.0) {
202
+ r = 0.5 / r;
203
+ }
204
+ out[0] = (m20 + m02) * r;
205
+ out[1] = (m21 + m12) * r;
206
+ out[3] = (m01 - m10) * r;
207
+ break;
208
+ }
209
+ }
210
+ }
211
+
150
212
  void quat_slerp(const quat_t from, const quat_t to, s_float_t delta, quat_t out)
151
213
  {
152
214
  s_float_t dot, scale0, scale1, angle, inverse_sin;
@@ -381,18 +381,21 @@ static VALUE s_sm_snowmath_mod = Qnil;
381
381
  DEF_SM_TYPE_KLASS(vec3);
382
382
  DEF_SM_TYPE_KLASS(vec4);
383
383
  DEF_SM_TYPE_KLASS(quat);
384
+ DEF_SM_TYPE_KLASS(mat3);
384
385
  DEF_SM_TYPE_KLASS(mat4);
385
386
 
386
387
  // Declare wrapping operations
387
388
  DECL_SM_UNWRAP_OP(vec3);
388
389
  DECL_SM_UNWRAP_OP(vec4);
389
390
  DECL_SM_UNWRAP_OP(quat);
391
+ DECL_SM_UNWRAP_OP(mat3);
390
392
  DECL_SM_UNWRAP_OP(mat4);
391
393
 
392
394
  // Declare unwrapping operations
393
395
  DECL_SM_WRAP_OP(vec3);
394
396
  DECL_SM_WRAP_OP(vec4);
395
397
  DECL_SM_WRAP_OP(quat);
398
+ DECL_SM_WRAP_OP(mat3);
396
399
  DECL_SM_WRAP_OP(mat4);
397
400
 
398
401
 
@@ -407,6 +410,7 @@ DECL_SM_WRAP_OP(mat4);
407
410
  DEF_SM_ARR_TYPE(vec3);
408
411
  DEF_SM_ARR_TYPE(vec4);
409
412
  DEF_SM_ARR_TYPE(quat);
413
+ DEF_SM_ARR_TYPE(mat3);
410
414
  DEF_SM_ARR_TYPE(mat4);
411
415
  #endif
412
416
 
@@ -428,6 +432,8 @@ DEF_SM_UNARY_OP(copy, vec3, vec3);
428
432
  DEF_SM_UNARY_OP(normalize, vec3, vec3);
429
433
  DEF_SM_UNARY_OP(inverse, vec3, vec3);
430
434
  DEF_SM_UNARY_OP(negate, vec3, vec3);
435
+ DEF_SM_BINARY_OP(project, vec3, vec3, vec3);
436
+ DEF_SM_BINARY_OP(reflect, vec3, vec3, vec3);
431
437
  DEF_SM_BINARY_OP(cross_product, vec3, vec3, vec3);
432
438
  DEF_SM_BINARY_OP(multiply, vec3, vec3, vec3);
433
439
  DEF_SM_BINARY_OP(add, vec3, vec3, vec3);
@@ -625,6 +631,8 @@ DEF_SM_UNARY_OP(copy, vec4, vec4);
625
631
  DEF_SM_UNARY_OP(normalize, vec4, vec4);
626
632
  DEF_SM_UNARY_OP(inverse, vec4, vec4);
627
633
  DEF_SM_UNARY_OP(negate, vec4, vec4);
634
+ DEF_SM_BINARY_OP(project, vec4, vec4, vec4);
635
+ DEF_SM_BINARY_OP(reflect, vec4, vec4, vec4);
628
636
  DEF_SM_BINARY_OP(multiply, vec4, vec4, vec4);
629
637
  DEF_SM_BINARY_OP(add, vec4, vec4, vec4);
630
638
  DEF_SM_BINARY_OP(subtract, vec4, vec4, vec4);
@@ -866,6 +874,12 @@ static VALUE sm_quat_init(int argc, VALUE *argv, VALUE sm_self)
866
874
  break;
867
875
  }
868
876
 
877
+ if (SM_IS_A(argv[0], mat3)) {
878
+ const mat3_t *mat = sm_unwrap_mat3(argv[0], NULL);
879
+ quat_from_mat3(*mat, *self);
880
+ break;
881
+ }
882
+
869
883
  // Optional offset into array provided
870
884
  if (0) {
871
885
  case 2:
@@ -921,10 +935,6 @@ static VALUE sm_quat_to_s(VALUE self)
921
935
 
922
936
 
923
937
 
924
-
925
-
926
-
927
-
928
938
  static VALUE sm_quat_angle_axis(int argc, VALUE *argv, VALUE self)
929
939
  {
930
940
  VALUE sm_angle;
@@ -1141,6 +1151,7 @@ DEF_SM_LENGTH_OP(mat4);
1141
1151
  DEF_SM_FETCH_OP(mat4);
1142
1152
  DEF_SM_STORE_OP(mat4);
1143
1153
  DEF_SM_UNARY_OP(copy, mat4, mat4);
1154
+ DEF_SM_UNARY_OP(to_mat3, mat4, mat3);
1144
1155
  DEF_SM_UNARY_OP(transpose, mat4, mat4);
1145
1156
  DEF_SM_UNARY_OP(inverse_orthogonal, mat4, mat4);
1146
1157
  DEF_SM_UNARY_OP(adjoint, mat4, mat4);
@@ -1367,6 +1378,12 @@ static VALUE sm_mat4_init(int argc, VALUE *argv, VALUE sm_self)
1367
1378
  break;
1368
1379
  }
1369
1380
 
1381
+ // Copy Mat3
1382
+ if (SM_IS_A(argv[0], mat3)) {
1383
+ mat3_to_mat4(*sm_unwrap_mat4(argv[0], NULL), *self);
1384
+ break;
1385
+ }
1386
+
1370
1387
  // Build from Quaternion
1371
1388
  if (SM_IS_A(argv[0], quat)) {
1372
1389
  mat4_from_quat(*sm_unwrap_quat(argv[0], NULL), *self);
@@ -1438,9 +1455,9 @@ static VALUE sm_mat4_to_s(VALUE self)
1438
1455
  v = (const s_float_t *)*sm_unwrap_mat4(self, NULL);
1439
1456
  return rb_sprintf(
1440
1457
  "{ "
1441
- "%f, %f, %f, %f" ", "
1442
- "%f, %f, %f, %f" ", "
1443
- "%f, %f, %f, %f" ", "
1458
+ "%f, %f, %f, %f" ",\n "
1459
+ "%f, %f, %f, %f" ",\n "
1460
+ "%f, %f, %f, %f" ",\n "
1444
1461
  "%f, %f, %f, %f"
1445
1462
  " }",
1446
1463
  v[0], v[1], v[2], v[3],
@@ -1977,6 +1994,430 @@ static VALUE sm_mat4_equals(VALUE sm_self, VALUE sm_other)
1977
1994
 
1978
1995
 
1979
1996
 
1997
+ /*==============================================================================
1998
+
1999
+ mat3_t functions
2000
+
2001
+ ==============================================================================*/
2002
+
2003
+ DEF_SM_WRAP_OP(mat3);
2004
+ DEF_SM_UNWRAP_OP(mat3);
2005
+ DEF_SM_SIZE_OP(mat3);
2006
+ DEF_SM_LENGTH_OP(mat3);
2007
+ DEF_SM_FETCH_OP(mat3);
2008
+ DEF_SM_STORE_OP(mat3);
2009
+ DEF_SM_UNARY_OP(copy, mat3, mat3);
2010
+ DEF_SM_UNARY_OP(to_mat4, mat3, mat4);
2011
+ DEF_SM_UNARY_OP(transpose, mat3, mat3);
2012
+ DEF_SM_UNARY_OP(adjoint, mat3, mat3);
2013
+ DEF_SM_UNARY_OP(orthogonal, mat3, mat3);
2014
+ DEF_SM_UNARY_OP(cofactor, mat3, mat3);
2015
+ DEF_SM_BINARY_OP(multiply, mat3, mat3, mat3);
2016
+ DEF_SM_BINARY_OP(rotate_vec3, mat3, vec3, vec3);
2017
+ DEF_SM_BINARY_OP(inv_rotate_vec3, mat3, vec3, vec3);
2018
+
2019
+
2020
+
2021
+ static VALUE sm_mat3_determinant(VALUE sm_self)
2022
+ {
2023
+ return mat3_determinant(*sm_unwrap_mat3(sm_self, NULL));
2024
+ }
2025
+
2026
+
2027
+
2028
+ static VALUE sm_mat3_inverse(int argc, VALUE *argv, VALUE sm_self)
2029
+ {
2030
+ VALUE sm_out = Qnil;
2031
+ mat3_t *self;
2032
+
2033
+ rb_scan_args(argc, argv, "01", &sm_out);
2034
+ self = sm_unwrap_mat3(sm_self, NULL);
2035
+
2036
+ if (argc == 1) {
2037
+ mat3_t *output;
2038
+
2039
+ if (!RTEST(sm_out)) {
2040
+ goto SM_LABEL(skip_output);
2041
+ }
2042
+
2043
+ if (!SM_IS_A(sm_out, mat3)) {
2044
+ rb_raise(rb_eTypeError,
2045
+ "Invalid argument to output of inverse_general: expected %s, got %s",
2046
+ rb_class2name(SM_KLASS(mat3)),
2047
+ rb_obj_classname(sm_out));
2048
+ return Qnil;
2049
+ }
2050
+
2051
+ output = sm_unwrap_mat3(sm_out, NULL);
2052
+ if (!mat3_inverse(*self, *output)) {
2053
+ return Qnil;
2054
+ }
2055
+
2056
+ } else if (argc == 0) {
2057
+ SM_LABEL(skip_output): {
2058
+ mat3_t output;
2059
+ if (!mat3_inverse(*self, output)) {
2060
+ return Qnil;
2061
+ }
2062
+
2063
+ sm_out = sm_wrap_mat3(output, rb_obj_class(sm_self));
2064
+ rb_obj_call_init(sm_out, 0, 0);
2065
+ }
2066
+ } else {
2067
+ rb_raise(rb_eArgError, "Invalid number of arguments to inverse");
2068
+ }
2069
+
2070
+ return sm_out;
2071
+ }
2072
+
2073
+
2074
+
2075
+ static VALUE sm_mat3_new(int argc, VALUE *argv, VALUE self)
2076
+ {
2077
+ VALUE sm_mat = sm_wrap_mat3(g_mat3_identity, self);
2078
+ rb_obj_call_init(sm_mat, argc, argv);
2079
+ return sm_mat;
2080
+ }
2081
+
2082
+
2083
+
2084
+ static VALUE sm_mat3_init(int argc, VALUE *argv, VALUE sm_self)
2085
+ {
2086
+ mat3_t *self = sm_unwrap_mat3(sm_self, NULL);
2087
+ size_t arr_index = 0;
2088
+
2089
+ switch (argc) {
2090
+
2091
+ case 0: {
2092
+ // Identity (handled in _new)
2093
+ break;
2094
+ }
2095
+
2096
+ // Copy Mat3 or provided [Numeric..]
2097
+ case 1: {
2098
+ // Copy Mat3
2099
+ if (SM_IS_A(argv[0], mat3)) {
2100
+ sm_unwrap_mat3(argv[0], *self);
2101
+ break;
2102
+ }
2103
+
2104
+ // Copy Mat4
2105
+ if (SM_IS_A(argv[0], mat4)) {
2106
+ mat4_to_mat3(*sm_unwrap_mat4(argv[0], NULL), *self);
2107
+ break;
2108
+ }
2109
+
2110
+ // Build from Quaternion
2111
+ if (SM_IS_A(argv[0], quat)) {
2112
+ mat3_from_quat(*sm_unwrap_quat(argv[0], NULL), *self);
2113
+ break;
2114
+ }
2115
+
2116
+ // Optional offset into array provided
2117
+ if (0) {
2118
+ case 2:
2119
+ arr_index = NUM2SIZET(argv[1]);
2120
+ }
2121
+
2122
+ // Array of values
2123
+ if (SM_RB_IS_A(argv[0], rb_cArray)) {
2124
+ VALUE arrdata = argv[0];
2125
+ const size_t arr_end = arr_index + 9;
2126
+ s_float_t *mat_elem = *self;
2127
+ for (; arr_index < arr_end; ++arr_index, ++mat_elem) {
2128
+ *mat_elem = rb_num2dbl(rb_ary_entry(arrdata, (long)arr_index));
2129
+ }
2130
+ break;
2131
+ }
2132
+
2133
+ rb_raise(rb_eArgError, "Expected either an array of Numerics or a Mat3");
2134
+ break;
2135
+ }
2136
+
2137
+ // Mat3(Vec3, Vec3, Vec3)
2138
+ case 3: {
2139
+ size_t arg_index;
2140
+ s_float_t *mat_elem = *self;
2141
+ for (arg_index = 0; arg_index < 3; ++arg_index, mat_elem += 3) {
2142
+ if (!SM_IS_A(argv[arg_index], vec3)) {
2143
+ rb_raise(
2144
+ rb_eArgError,
2145
+ "Argument %d must be a Vec3 when supplying three arguments to Mat3.initialize",
2146
+ (int)(arg_index + 1));
2147
+ }
2148
+
2149
+ sm_unwrap_vec3(argv[arg_index], mat_elem);
2150
+ }
2151
+ break;
2152
+ }
2153
+
2154
+ // Mat3(Numeric m00 .. m16)
2155
+ case 9: {
2156
+ s_float_t *mat_elem = *self;
2157
+ VALUE *argv_p = argv;
2158
+ for (; argc; --argc, ++argv_p, ++mat_elem) {
2159
+ *mat_elem = (s_float_t)rb_num2dbl(*argv_p);
2160
+ }
2161
+ break;
2162
+ }
2163
+
2164
+ default: {
2165
+ rb_raise(rb_eArgError, "Invalid arguments to Mat3.initialize");
2166
+ break;
2167
+ }
2168
+ } // swtich (argc)
2169
+
2170
+ return sm_self;
2171
+ }
2172
+
2173
+
2174
+
2175
+ static VALUE sm_mat3_to_s(VALUE self)
2176
+ {
2177
+ const s_float_t *v;
2178
+ v = (const s_float_t *)*sm_unwrap_mat3(self, NULL);
2179
+ return rb_sprintf(
2180
+ "{ "
2181
+ "%f, %f, %f" ",\n "
2182
+ "%f, %f, %f" ",\n "
2183
+ "%f, %f, %f"
2184
+ " }",
2185
+ v[0], v[1], v[2],
2186
+ v[3], v[4], v[5],
2187
+ v[6], v[7], v[8] );
2188
+ }
2189
+
2190
+
2191
+
2192
+ static VALUE sm_mat3_angle_axis(int argc, VALUE *argv, VALUE self)
2193
+ {
2194
+ VALUE sm_angle;
2195
+ VALUE sm_axis;
2196
+ VALUE sm_out;
2197
+ s_float_t angle;
2198
+ const vec3_t *axis;
2199
+
2200
+ rb_scan_args(argc, argv, "21", &sm_angle, &sm_axis, &sm_out);
2201
+ SM_RAISE_IF_NOT_TYPE(sm_axis, vec3);
2202
+
2203
+ angle = (s_float_t)rb_num2dbl(sm_angle);
2204
+ axis = sm_unwrap_vec3(sm_axis, NULL);
2205
+
2206
+ if (SM_IS_A(sm_out, mat3)) {
2207
+ mat3_t *out = sm_unwrap_mat3(sm_out, NULL);
2208
+ mat3_rotation(angle, (*axis)[0], (*axis)[1], (*axis)[2], *out);
2209
+ } else {
2210
+ mat3_t out;
2211
+ mat3_rotation(angle, (*axis)[0], (*axis)[1], (*axis)[2], out);
2212
+ sm_out = sm_wrap_mat3(out, self);
2213
+ rb_obj_call_init(sm_out, 0, 0);
2214
+ }
2215
+
2216
+ return sm_out;
2217
+ }
2218
+
2219
+
2220
+
2221
+ static VALUE sm_mat3_get_row3(int argc, VALUE *argv, VALUE sm_self)
2222
+ {
2223
+ mat3_t *self;
2224
+ int index;
2225
+ VALUE sm_out;
2226
+
2227
+ self = sm_unwrap_mat3(sm_self, NULL);
2228
+ index = NUM2INT(argv[0]);
2229
+ sm_out = Qnil;
2230
+
2231
+ if (index < 0 || index > 3) {
2232
+ rb_raise(rb_eRangeError, "Index %d is out of range, must be (0 .. 3)", index);
2233
+ return Qnil;
2234
+ }
2235
+
2236
+ switch (argc) {
2237
+ case 2: {
2238
+ vec3_t *out;
2239
+
2240
+ sm_out = argv[1];
2241
+
2242
+ if (RTEST(sm_out)) {
2243
+ SM_RAISE_IF_NOT_TYPE(sm_out, vec3);
2244
+ } else {
2245
+ goto SM_LABEL(no_output);
2246
+ }
2247
+
2248
+ out = sm_unwrap_vec3(sm_out, NULL);
2249
+ mat3_get_row3(*self, index, *out);
2250
+
2251
+ break;
2252
+ }
2253
+
2254
+ case 1: SM_LABEL(no_output): {
2255
+ vec3_t out;
2256
+ mat3_get_row3(*self, index, out);
2257
+ sm_out = sm_wrap_vec3(out, Qnil);
2258
+ rb_obj_call_init(sm_out, 0, 0);
2259
+ break;
2260
+ }
2261
+
2262
+ default: {
2263
+ rb_raise(rb_eArgError, "Invalid number of arguments to get_row3 - expected 1 or 2");
2264
+ break;
2265
+ }
2266
+ }
2267
+
2268
+ return sm_out;
2269
+ }
2270
+
2271
+
2272
+
2273
+ static VALUE sm_mat3_get_column3(int argc, VALUE *argv, VALUE sm_self)
2274
+ {
2275
+ mat3_t *self;
2276
+ int index;
2277
+ VALUE sm_out;
2278
+
2279
+ self = sm_unwrap_mat3(sm_self, NULL);
2280
+ index = NUM2INT(argv[0]);
2281
+ sm_out = Qnil;
2282
+
2283
+ if (index < 0 || index > 3) {
2284
+ rb_raise(rb_eRangeError, "Index %d is out of range, must be (0 .. 3)", index);
2285
+ return Qnil;
2286
+ }
2287
+
2288
+ switch (argc) {
2289
+ case 2: {
2290
+ vec3_t *out;
2291
+
2292
+ sm_out = argv[1];
2293
+
2294
+ if (RTEST(sm_out)) {
2295
+ SM_RAISE_IF_NOT_TYPE(sm_out, vec3);
2296
+ } else {
2297
+ goto SM_LABEL(no_output);
2298
+ }
2299
+
2300
+ out = sm_unwrap_vec3(sm_out, NULL);
2301
+ mat3_get_column3(*self, index, *out);
2302
+
2303
+ break;
2304
+ }
2305
+
2306
+ case 1: SM_LABEL(no_output): {
2307
+ vec3_t out;
2308
+ mat3_get_column3(*self, index, out);
2309
+ sm_out = sm_wrap_vec3(out, Qnil);
2310
+ rb_obj_call_init(sm_out, 0, 0);
2311
+ break;
2312
+ }
2313
+
2314
+ default: {
2315
+ rb_raise(rb_eArgError, "Invalid number of arguments to get_column3 - expected 1 or 2");
2316
+ break;
2317
+ }
2318
+ }
2319
+
2320
+ return sm_out;
2321
+ }
2322
+
2323
+
2324
+
2325
+ static VALUE sm_mat3_set_row3(VALUE sm_self, VALUE sm_index, VALUE sm_value)
2326
+ {
2327
+ const vec3_t *value;
2328
+ int index;
2329
+ mat3_t *self;
2330
+
2331
+ SM_RAISE_IF_NOT_TYPE(sm_value, vec3);
2332
+
2333
+ self = sm_unwrap_mat3(sm_self, NULL);
2334
+ value = sm_unwrap_vec3(sm_value, NULL);
2335
+ index = NUM2INT(sm_index);
2336
+
2337
+ if (index < 0 || index > 3) {
2338
+ rb_raise(rb_eRangeError, "Index %d is out of range, must be (0 .. 3)", index);
2339
+ return Qnil;
2340
+ }
2341
+
2342
+ mat3_set_row3(index, *value, *self);
2343
+
2344
+ return sm_self;
2345
+ }
2346
+
2347
+
2348
+
2349
+ static VALUE sm_mat3_set_column3(VALUE sm_self, VALUE sm_index, VALUE sm_value)
2350
+ {
2351
+ const vec3_t *value;
2352
+ int index;
2353
+ mat3_t *self;
2354
+
2355
+ SM_RAISE_IF_NOT_TYPE(sm_value, vec3);
2356
+
2357
+ self = sm_unwrap_mat3(sm_self, NULL);
2358
+ value = sm_unwrap_vec3(sm_value, NULL);
2359
+ index = NUM2INT(sm_index);
2360
+
2361
+ if (index < 0 || index > 3) {
2362
+ rb_raise(rb_eRangeError, "Index %d is out of range, must be (0 .. 3)", index);
2363
+ return Qnil;
2364
+ }
2365
+
2366
+ mat3_set_column3(index, *value, *self);
2367
+
2368
+ return sm_self;
2369
+ }
2370
+
2371
+
2372
+
2373
+ static VALUE sm_mat3_identity(VALUE sm_self)
2374
+ {
2375
+ mat3_t *self = sm_unwrap_mat3(sm_self, NULL);
2376
+ mat3_identity(*self);
2377
+ return sm_self;
2378
+ }
2379
+
2380
+
2381
+
2382
+ static VALUE sm_mat3_scale(int argc, VALUE *argv, VALUE sm_self)
2383
+ {
2384
+ VALUE sm_out;
2385
+ VALUE sm_x, sm_y, sm_z;
2386
+ s_float_t x, y, z;
2387
+ mat3_t *self = sm_unwrap_mat3(sm_self, NULL);
2388
+
2389
+ rb_scan_args(argc, argv, "31", &sm_x, &sm_y, &sm_z, &sm_out);
2390
+ x = rb_num2dbl(sm_x);
2391
+ y = rb_num2dbl(sm_y);
2392
+ z = rb_num2dbl(sm_z);
2393
+
2394
+ if (SM_IS_A(sm_out, mat3)) {
2395
+ mat3_scale(*self, x, y, z, *sm_unwrap_mat3(sm_out, NULL));
2396
+ } else {
2397
+ mat3_t out;
2398
+ mat3_scale(*self, x, y, z, out);
2399
+ sm_out = sm_wrap_mat3(out, rb_obj_class(sm_self));
2400
+ rb_obj_call_init(sm_out, 0, 0);
2401
+ }
2402
+
2403
+ return sm_out;
2404
+ }
2405
+
2406
+
2407
+
2408
+ static VALUE sm_mat3_equals(VALUE sm_self, VALUE sm_other)
2409
+ {
2410
+ if (!RTEST(sm_other)) {
2411
+ return Qfalse;
2412
+ } else {
2413
+ SM_RAISE_IF_NOT_TYPE(sm_other, mat3);
2414
+ }
2415
+
2416
+ return mat3_equals(*sm_unwrap_mat3(sm_self, NULL), *sm_unwrap_mat3(sm_other, NULL)) ? Qtrue : Qfalse;
2417
+ }
2418
+
2419
+
2420
+
1980
2421
  /*==============================================================================
1981
2422
 
1982
2423
  General-purpose functions
@@ -2001,6 +2442,7 @@ void Init_bindings()
2001
2442
  SM_KLASS(vec3) = rb_define_class_under(s_sm_snowmath_mod, "Vec3", rb_cObject);
2002
2443
  SM_KLASS(vec4) = rb_define_class_under(s_sm_snowmath_mod, "Vec4", rb_cObject);
2003
2444
  SM_KLASS(quat) = rb_define_class_under(s_sm_snowmath_mod, "Quat", rb_cObject);
2445
+ SM_KLASS(mat3) = rb_define_class_under(s_sm_snowmath_mod, "Mat3", rb_cObject);
2004
2446
  SM_KLASS(mat4) = rb_define_class_under(s_sm_snowmath_mod, "Mat4", rb_cObject);
2005
2447
 
2006
2448
  rb_define_singleton_method(SM_KLASS(vec3), "new", sm_vec3_new, -1);
@@ -2020,6 +2462,8 @@ void Init_bindings()
2020
2462
  rb_define_method(SM_KLASS(vec3), "multiply_vec3", sm_vec3_multiply, -1);
2021
2463
  rb_define_method(SM_KLASS(vec3), "add", sm_vec3_add, -1);
2022
2464
  rb_define_method(SM_KLASS(vec3), "subtract", sm_vec3_subtract, -1);
2465
+ rb_define_method(SM_KLASS(vec3), "reflect", sm_vec3_reflect, -1);
2466
+ rb_define_method(SM_KLASS(vec3), "project", sm_vec3_project, -1);
2023
2467
  rb_define_method(SM_KLASS(vec3), "dot_product", sm_vec3_dot_product, 1);
2024
2468
  rb_define_method(SM_KLASS(vec3), "magnitude_squared", sm_vec3_magnitude_squared, 0);
2025
2469
  rb_define_method(SM_KLASS(vec3), "magnitude", sm_vec3_magnitude, 0);
@@ -2043,6 +2487,8 @@ void Init_bindings()
2043
2487
  rb_define_method(SM_KLASS(vec4), "multiply_vec4", sm_vec4_multiply, -1);
2044
2488
  rb_define_method(SM_KLASS(vec4), "add", sm_vec4_add, -1);
2045
2489
  rb_define_method(SM_KLASS(vec4), "subtract", sm_vec4_subtract, -1);
2490
+ rb_define_method(SM_KLASS(vec4), "reflect", sm_vec4_reflect, -1);
2491
+ rb_define_method(SM_KLASS(vec4), "project", sm_vec4_project, -1);
2046
2492
  rb_define_method(SM_KLASS(vec4), "dot_product", sm_vec4_dot_product, 1);
2047
2493
  rb_define_method(SM_KLASS(vec4), "magnitude_squared", sm_vec4_magnitude_squared, 0);
2048
2494
  rb_define_method(SM_KLASS(vec4), "magnitude", sm_vec4_magnitude, 0);
@@ -2087,6 +2533,7 @@ void Init_bindings()
2087
2533
  rb_define_singleton_method(SM_KLASS(mat4), "look_at", sm_mat4_look_at, -1);
2088
2534
  rb_define_method(SM_KLASS(mat4), "initialize", sm_mat4_init, -1);
2089
2535
  rb_define_method(SM_KLASS(mat4), "set", sm_mat4_init, -1);
2536
+ rb_define_method(SM_KLASS(mat4), "to_mat3", sm_mat4_to_mat3, -1);
2090
2537
  rb_define_method(SM_KLASS(mat4), "load_identity", sm_mat4_identity, 0);
2091
2538
  rb_define_method(SM_KLASS(mat4), "fetch", sm_mat4_fetch, 1);
2092
2539
  rb_define_method(SM_KLASS(mat4), "store", sm_mat4_store, 2);
@@ -2118,10 +2565,40 @@ void Init_bindings()
2118
2565
  rb_define_method(SM_KLASS(mat4), "get_column4", sm_mat4_get_column4, -1);
2119
2566
  rb_define_method(SM_KLASS(mat4), "==", sm_mat4_equals, 1);
2120
2567
 
2568
+ rb_define_singleton_method(SM_KLASS(mat3), "new", sm_mat3_new, -1);
2569
+ rb_define_singleton_method(SM_KLASS(mat3), "angle_axis", sm_mat3_angle_axis, -1);
2570
+ rb_define_method(SM_KLASS(mat3), "initialize", sm_mat3_init, -1);
2571
+ rb_define_method(SM_KLASS(mat3), "set", sm_mat3_init, -1);
2572
+ rb_define_method(SM_KLASS(mat3), "to_mat4", sm_mat3_to_mat4, -1);
2573
+ rb_define_method(SM_KLASS(mat3), "load_identity", sm_mat3_identity, 0);
2574
+ rb_define_method(SM_KLASS(mat3), "fetch", sm_mat3_fetch, 1);
2575
+ rb_define_method(SM_KLASS(mat3), "store", sm_mat3_store, 2);
2576
+ rb_define_method(SM_KLASS(mat3), "size", sm_mat3_size, 0);
2577
+ rb_define_method(SM_KLASS(mat3), "length", sm_mat3_length, 0);
2578
+ rb_define_method(SM_KLASS(mat3), "to_s", sm_mat3_to_s, 0);
2579
+ rb_define_method(SM_KLASS(mat3), "address", sm_get_address, 0);
2580
+ rb_define_method(SM_KLASS(mat3), "copy", sm_mat3_copy, -1);
2581
+ rb_define_method(SM_KLASS(mat3), "transpose", sm_mat3_transpose, -1);
2582
+ rb_define_method(SM_KLASS(mat3), "adjoint", sm_mat3_adjoint, -1);
2583
+ rb_define_method(SM_KLASS(mat3), "cofactor", sm_mat3_cofactor, -1);
2584
+ rb_define_method(SM_KLASS(mat3), "orthogonal", sm_mat3_orthogonal, -1);
2585
+ rb_define_method(SM_KLASS(mat3), "scale", sm_mat3_scale, -1);
2586
+ rb_define_method(SM_KLASS(mat3), "multiply_mat3", sm_mat3_multiply, -1);
2587
+ rb_define_method(SM_KLASS(mat3), "rotate_vec3", sm_mat3_rotate_vec3, -1);
2588
+ rb_define_method(SM_KLASS(mat3), "inverse_rotate_vec3", sm_mat3_inv_rotate_vec3, -1);
2589
+ rb_define_method(SM_KLASS(mat3), "inverse", sm_mat3_inverse, -1);
2590
+ rb_define_method(SM_KLASS(mat3), "determinant", sm_mat3_determinant, 0);
2591
+ rb_define_method(SM_KLASS(mat3), "set_row3", sm_mat3_set_row3, 2);
2592
+ rb_define_method(SM_KLASS(mat3), "get_row3", sm_mat3_get_row3, -1);
2593
+ rb_define_method(SM_KLASS(mat3), "set_column3", sm_mat3_set_column3, 2);
2594
+ rb_define_method(SM_KLASS(mat3), "get_column3", sm_mat3_get_column3, -1);
2595
+ rb_define_method(SM_KLASS(mat3), "==", sm_mat3_equals, 1);
2596
+
2121
2597
  #ifdef BUILD_ARRAY_TYPE
2122
2598
  REG_SM_ARR_TYPE(vec3, "Vec3Array");
2123
2599
  REG_SM_ARR_TYPE(vec4, "Vec4Array");
2124
2600
  REG_SM_ARR_TYPE(quat, "QuatArray");
2601
+ REG_SM_ARR_TYPE(mat3, "Mat3Array");
2125
2602
  REG_SM_ARR_TYPE(mat4, "Mat4Array");
2126
2603
  #endif
2127
2604