snow-math 1.3.0pre0 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -8,6 +8,9 @@ See COPYING for license information
8
8
  #include "maths_local.h"
9
9
  #include "ruby.h"
10
10
 
11
+ #define kSM_WANT_THREE_OR_FOUR_FORMAT_LIT ("Expected a Vec3, Vec4, or Quat, got %s")
12
+ #define kSM_WANT_FOUR_FORMAT_LIT ("Expected a Vec4 or Quat, got %s")
13
+
11
14
  /*
12
15
  Generates a label within the current function with the given name. Should be
13
16
  as unique as anyone needs.
@@ -289,10 +292,9 @@ static VALUE sm_vec3_array_store(VALUE sm_self, VALUE sm_index, VALUE sm_value)
289
292
  rb_raise(rb_eRangeError,
290
293
  "Index %zu out of bounds for array with length %zu",
291
294
  index, length);
292
- } else if (!SM_IS_A(sm_value, vec3)) {
295
+ } else if (!SM_IS_A(sm_value, vec3) && !SM_IS_A(sm_value, vec4) && !SM_IS_A(sm_value, quat)) {
293
296
  rb_raise(rb_eTypeError,
294
- "Invalid value to store: expected %s, got %s",
295
- rb_class2name(s_sm_vec3_klass),
297
+ "Invalid value to store: expected Vec3, Vec4, or Quat, got %s",
296
298
  rb_obj_classname(sm_value));
297
299
  }
298
300
 
@@ -480,10 +482,9 @@ static VALUE sm_vec4_array_store(VALUE sm_self, VALUE sm_index, VALUE sm_value)
480
482
  rb_raise(rb_eRangeError,
481
483
  "Index %zu out of bounds for array with length %zu",
482
484
  index, length);
483
- } else if (!SM_IS_A(sm_value, vec4)) {
485
+ } else if (!SM_IS_A(sm_value, vec4) || !(SM_IS_A(sm_value, quat))) {
484
486
  rb_raise(rb_eTypeError,
485
- "Invalid value to store: expected %s, got %s",
486
- rb_class2name(s_sm_vec4_klass),
487
+ "Invalid value to store: expected Quat or Vec4, got %s",
487
488
  rb_obj_classname(sm_value));
488
489
  }
489
490
 
@@ -671,10 +672,9 @@ static VALUE sm_quat_array_store(VALUE sm_self, VALUE sm_index, VALUE sm_value)
671
672
  rb_raise(rb_eRangeError,
672
673
  "Index %zu out of bounds for array with length %zu",
673
674
  index, length);
674
- } else if (!SM_IS_A(sm_value, quat)) {
675
+ } else if (!SM_IS_A(sm_value, vec4) || !(SM_IS_A(sm_value, quat))) {
675
676
  rb_raise(rb_eTypeError,
676
- "Invalid value to store: expected %s, got %s",
677
- rb_class2name(s_sm_quat_klass),
677
+ "Invalid value to store: expected Quat or Vec4, got %s",
678
678
  rb_obj_classname(sm_value));
679
679
  }
680
680
 
@@ -849,35 +849,40 @@ static VALUE sm_mat3_array_fetch(VALUE sm_self, VALUE sm_index)
849
849
  * array and stored at the index, then no copy is done, otherwise the Mat3 is
850
850
  * copied to the array.
851
851
  *
852
+ * If the value stored is a Mat4, it will be converted to a Mat3 for storage,
853
+ * though this will not modify the value directly.
854
+ *
852
855
  * call-seq: store(index, value) -> value
853
856
  */
854
857
  static VALUE sm_mat3_array_store(VALUE sm_self, VALUE sm_index, VALUE sm_value)
855
858
  {
856
859
  mat3_t *arr;
857
- mat3_t *value;
858
860
  size_t length = NUM2SIZET(sm_mathtype_array_length(sm_self));
859
861
  size_t index = NUM2SIZET(sm_index);
862
+ int is_mat3 = 0;
860
863
 
861
864
  if (index >= length) {
862
865
  rb_raise(rb_eRangeError,
863
866
  "Index %zu out of bounds for array with length %zu",
864
867
  index, length);
865
- } else if (!SM_IS_A(sm_value, mat3)) {
868
+ } else if (!(is_mat3 = SM_IS_A(sm_value, mat3)) && !SM_IS_A(sm_value, mat4)) {
866
869
  rb_raise(rb_eTypeError,
867
- "Invalid value to store: expected %s, got %s",
868
- rb_class2name(s_sm_mat3_klass),
870
+ "Invalid value to store: expected Mat3 or Mat4, got %s",
869
871
  rb_obj_classname(sm_value));
870
872
  }
871
873
 
872
874
  Data_Get_Struct(sm_self, mat3_t, arr);
873
- value = sm_unwrap_mat3(sm_value, NULL);
874
875
 
875
- if (value == &arr[index]) {
876
- /* The object's part of the array, don't bother copying */
877
- return sm_value;
876
+ if (is_mat3) {
877
+ mat3_t *value = sm_unwrap_mat3(sm_value, NULL);
878
+ if (value == &arr[index]) {
879
+ /* The object's part of the array, don't bother copying */
880
+ return sm_value;
881
+ }
882
+ mat3_copy(*value, arr[index]);
883
+ } else {
884
+ mat4_to_mat3(*sm_unwrap_mat4(sm_value, NULL), arr[index]);
878
885
  }
879
-
880
- mat3_copy(*value, arr[index]);
881
886
  return sm_value;
882
887
  }
883
888
 
@@ -1040,35 +1045,40 @@ static VALUE sm_mat4_array_fetch(VALUE sm_self, VALUE sm_index)
1040
1045
  * array and stored at the index, then no copy is done, otherwise the Mat4 is
1041
1046
  * copied to the array.
1042
1047
  *
1048
+ * If the value stored is a Mat3, it will be converted to a Mat4 for storage,
1049
+ * though this will not modify the value directly.
1050
+ *
1043
1051
  * call-seq: store(index, value) -> value
1044
1052
  */
1045
1053
  static VALUE sm_mat4_array_store(VALUE sm_self, VALUE sm_index, VALUE sm_value)
1046
1054
  {
1047
1055
  mat4_t *arr;
1048
- mat4_t *value;
1049
1056
  size_t length = NUM2SIZET(sm_mathtype_array_length(sm_self));
1050
1057
  size_t index = NUM2SIZET(sm_index);
1058
+ int is_mat4 = 0;
1051
1059
 
1052
1060
  if (index >= length) {
1053
1061
  rb_raise(rb_eRangeError,
1054
1062
  "Index %zu out of bounds for array with length %zu",
1055
1063
  index, length);
1056
- } else if (!SM_IS_A(sm_value, mat4)) {
1064
+ } else if (!(is_mat4 = SM_IS_A(sm_value, mat4)) && !SM_IS_A(sm_value, mat3)) {
1057
1065
  rb_raise(rb_eTypeError,
1058
- "Invalid value to store: expected %s, got %s",
1059
- rb_class2name(s_sm_mat4_klass),
1066
+ "Invalid value to store: expected Mat3 or Mat4, got %s",
1060
1067
  rb_obj_classname(sm_value));
1061
1068
  }
1062
1069
 
1063
1070
  Data_Get_Struct(sm_self, mat4_t, arr);
1064
- value = sm_unwrap_mat4(sm_value, NULL);
1065
1071
 
1066
- if (value == &arr[index]) {
1067
- /* The object's part of the array, don't bother copying */
1068
- return sm_value;
1072
+ if (is_mat4) {
1073
+ mat4_t *value = sm_unwrap_mat4(sm_value, NULL);
1074
+ if (value == &arr[index]) {
1075
+ /* The object's part of the array, don't bother copying */
1076
+ return sm_value;
1077
+ }
1078
+ mat4_copy(*value, arr[index]);
1079
+ } else {
1080
+ mat3_to_mat4(*sm_unwrap_mat3(sm_value, NULL), arr[index]);
1069
1081
  }
1070
-
1071
- mat4_copy(*value, arr[index]);
1072
1082
  return sm_value;
1073
1083
  }
1074
1084
 
@@ -1203,7 +1213,12 @@ static VALUE sm_vec3_length (VALUE self)
1203
1213
  if (!RTEST(sm_out)) {
1204
1214
  goto SM_LABEL(skip_output);
1205
1215
  }{
1206
- SM_RAISE_IF_NOT_TYPE(sm_out, vec3);
1216
+ if (!SM_IS_A(sm_out, vec3) && !SM_IS_A(sm_out, vec4) && !SM_IS_A(sm_out, quat)) {
1217
+ rb_raise(rb_eTypeError,
1218
+ kSM_WANT_THREE_OR_FOUR_FORMAT_LIT,
1219
+ rb_obj_classname(sm_out));
1220
+ return Qnil;
1221
+ }
1207
1222
  vec3_t *output = sm_unwrap_vec3(sm_out, NULL);
1208
1223
  vec3_copy (*self, *output);
1209
1224
  }} else if (argc == 0) {
@@ -1237,7 +1252,12 @@ static VALUE sm_vec3_length (VALUE self)
1237
1252
  if (!RTEST(sm_out)) {
1238
1253
  goto SM_LABEL(skip_output);
1239
1254
  }{
1240
- SM_RAISE_IF_NOT_TYPE(sm_out, vec3);
1255
+ if (!SM_IS_A(sm_out, vec3) && !SM_IS_A(sm_out, vec4) && !SM_IS_A(sm_out, quat)) {
1256
+ rb_raise(rb_eTypeError,
1257
+ kSM_WANT_THREE_OR_FOUR_FORMAT_LIT,
1258
+ rb_obj_classname(sm_out));
1259
+ return Qnil;
1260
+ }
1241
1261
  vec3_t *output = sm_unwrap_vec3(sm_out, NULL);
1242
1262
  vec3_normalize (*self, *output);
1243
1263
  }} else if (argc == 0) {
@@ -1271,7 +1291,12 @@ static VALUE sm_vec3_length (VALUE self)
1271
1291
  if (!RTEST(sm_out)) {
1272
1292
  goto SM_LABEL(skip_output);
1273
1293
  }{
1274
- SM_RAISE_IF_NOT_TYPE(sm_out, vec3);
1294
+ if (!SM_IS_A(sm_out, vec3) && !SM_IS_A(sm_out, vec4) && !SM_IS_A(sm_out, quat)) {
1295
+ rb_raise(rb_eTypeError,
1296
+ kSM_WANT_THREE_OR_FOUR_FORMAT_LIT,
1297
+ rb_obj_classname(sm_out));
1298
+ return Qnil;
1299
+ }
1275
1300
  vec3_t *output = sm_unwrap_vec3(sm_out, NULL);
1276
1301
  vec3_inverse (*self, *output);
1277
1302
  }} else if (argc == 0) {
@@ -1304,7 +1329,12 @@ static VALUE sm_vec3_length (VALUE self)
1304
1329
  if (!RTEST(sm_out)) {
1305
1330
  goto SM_LABEL(skip_output);
1306
1331
  }{
1307
- SM_RAISE_IF_NOT_TYPE(sm_out, vec3);
1332
+ if (!SM_IS_A(sm_out, vec3) && !SM_IS_A(sm_out, vec4) && !SM_IS_A(sm_out, quat)) {
1333
+ rb_raise(rb_eTypeError,
1334
+ kSM_WANT_THREE_OR_FOUR_FORMAT_LIT,
1335
+ rb_obj_classname(sm_out));
1336
+ return Qnil;
1337
+ }
1308
1338
  vec3_t *output = sm_unwrap_vec3(sm_out, NULL);
1309
1339
  vec3_negate (*self, *output);
1310
1340
  }} else if (argc == 0) {
@@ -1335,13 +1365,23 @@ static VALUE sm_vec3_project(int argc, VALUE *argv, VALUE sm_self)
1335
1365
  vec3_t *rhs;
1336
1366
  rb_scan_args(argc, argv, "11", &sm_rhs, &sm_out);
1337
1367
  self = sm_unwrap_vec3(sm_self, NULL);
1338
- SM_RAISE_IF_NOT_TYPE(sm_rhs, vec3);
1368
+ if (!SM_IS_A(sm_rhs, vec3) && !SM_IS_A(sm_rhs, vec4) && !SM_IS_A(sm_rhs, quat)) {
1369
+ rb_raise(rb_eTypeError,
1370
+ kSM_WANT_THREE_OR_FOUR_FORMAT_LIT,
1371
+ rb_obj_classname(sm_rhs));
1372
+ return Qnil;
1373
+ }
1339
1374
  rhs = sm_unwrap_vec3(sm_rhs, NULL);
1340
1375
  if (argc == 2) {
1341
1376
  if (!RTEST(sm_out)) {
1342
1377
  goto SM_LABEL(skip_output);
1343
1378
  }{
1344
- SM_RAISE_IF_NOT_TYPE(sm_out, vec3);
1379
+ if (!SM_IS_A(sm_out, vec3) && !SM_IS_A(sm_out, vec4) && !SM_IS_A(sm_out, quat)) {
1380
+ rb_raise(rb_eTypeError,
1381
+ kSM_WANT_THREE_OR_FOUR_FORMAT_LIT,
1382
+ rb_obj_classname(sm_out));
1383
+ return Qnil;
1384
+ }
1345
1385
  vec3_t *output = sm_unwrap_vec3(sm_out, NULL);
1346
1386
  vec3_project(*self, *rhs, *output);
1347
1387
  }} else if (argc == 1) {
@@ -1372,13 +1412,23 @@ static VALUE sm_vec3_reflect(int argc, VALUE *argv, VALUE sm_self)
1372
1412
  vec3_t *rhs;
1373
1413
  rb_scan_args(argc, argv, "11", &sm_rhs, &sm_out);
1374
1414
  self = sm_unwrap_vec3(sm_self, NULL);
1375
- SM_RAISE_IF_NOT_TYPE(sm_rhs, vec3);
1415
+ if (!SM_IS_A(sm_rhs, vec3) && !SM_IS_A(sm_rhs, vec4) && !SM_IS_A(sm_rhs, quat)) {
1416
+ rb_raise(rb_eTypeError,
1417
+ kSM_WANT_THREE_OR_FOUR_FORMAT_LIT,
1418
+ rb_obj_classname(sm_rhs));
1419
+ return Qnil;
1420
+ }
1376
1421
  rhs = sm_unwrap_vec3(sm_rhs, NULL);
1377
1422
  if (argc == 2) {
1378
1423
  if (!RTEST(sm_out)) {
1379
1424
  goto SM_LABEL(skip_output);
1380
1425
  }{
1381
- SM_RAISE_IF_NOT_TYPE(sm_out, vec3);
1426
+ if (!SM_IS_A(sm_out, vec3) && !SM_IS_A(sm_out, vec4) && !SM_IS_A(sm_out, quat)) {
1427
+ rb_raise(rb_eTypeError,
1428
+ kSM_WANT_THREE_OR_FOUR_FORMAT_LIT,
1429
+ rb_obj_classname(sm_out));
1430
+ return Qnil;
1431
+ }
1382
1432
  vec3_t *output = sm_unwrap_vec3(sm_out, NULL);
1383
1433
  vec3_reflect(*self, *rhs, *output);
1384
1434
  }} else if (argc == 1) {
@@ -1409,13 +1459,23 @@ static VALUE sm_vec3_cross_product(int argc, VALUE *argv, VALUE sm_self)
1409
1459
  vec3_t *rhs;
1410
1460
  rb_scan_args(argc, argv, "11", &sm_rhs, &sm_out);
1411
1461
  self = sm_unwrap_vec3(sm_self, NULL);
1412
- SM_RAISE_IF_NOT_TYPE(sm_rhs, vec3);
1462
+ if (!SM_IS_A(sm_rhs, vec3) && !SM_IS_A(sm_rhs, vec4) && !SM_IS_A(sm_rhs, quat)) {
1463
+ rb_raise(rb_eTypeError,
1464
+ kSM_WANT_THREE_OR_FOUR_FORMAT_LIT,
1465
+ rb_obj_classname(sm_rhs));
1466
+ return Qnil;
1467
+ }
1413
1468
  rhs = sm_unwrap_vec3(sm_rhs, NULL);
1414
1469
  if (argc == 2) {
1415
1470
  if (!RTEST(sm_out)) {
1416
1471
  goto SM_LABEL(skip_output);
1417
1472
  }{
1418
- SM_RAISE_IF_NOT_TYPE(sm_out, vec3);
1473
+ if (!SM_IS_A(sm_out, vec3) && !SM_IS_A(sm_out, vec4) && !SM_IS_A(sm_out, quat)) {
1474
+ rb_raise(rb_eTypeError,
1475
+ kSM_WANT_THREE_OR_FOUR_FORMAT_LIT,
1476
+ rb_obj_classname(sm_out));
1477
+ return Qnil;
1478
+ }
1419
1479
  vec3_t *output = sm_unwrap_vec3(sm_out, NULL);
1420
1480
  vec3_cross_product(*self, *rhs, *output);
1421
1481
  }} else if (argc == 1) {
@@ -1447,13 +1507,23 @@ static VALUE sm_vec3_multiply(int argc, VALUE *argv, VALUE sm_self)
1447
1507
  vec3_t *rhs;
1448
1508
  rb_scan_args(argc, argv, "11", &sm_rhs, &sm_out);
1449
1509
  self = sm_unwrap_vec3(sm_self, NULL);
1450
- SM_RAISE_IF_NOT_TYPE(sm_rhs, vec3);
1510
+ if (!SM_IS_A(sm_rhs, vec3) && !SM_IS_A(sm_rhs, vec4) && !SM_IS_A(sm_rhs, quat)) {
1511
+ rb_raise(rb_eTypeError,
1512
+ kSM_WANT_THREE_OR_FOUR_FORMAT_LIT,
1513
+ rb_obj_classname(sm_rhs));
1514
+ return Qnil;
1515
+ }
1451
1516
  rhs = sm_unwrap_vec3(sm_rhs, NULL);
1452
1517
  if (argc == 2) {
1453
1518
  if (!RTEST(sm_out)) {
1454
1519
  goto SM_LABEL(skip_output);
1455
1520
  }{
1456
- SM_RAISE_IF_NOT_TYPE(sm_out, vec3);
1521
+ if (!SM_IS_A(sm_out, vec3) && !SM_IS_A(sm_out, vec4) && !SM_IS_A(sm_out, quat)) {
1522
+ rb_raise(rb_eTypeError,
1523
+ kSM_WANT_THREE_OR_FOUR_FORMAT_LIT,
1524
+ rb_obj_classname(sm_out));
1525
+ return Qnil;
1526
+ }
1457
1527
  vec3_t *output = sm_unwrap_vec3(sm_out, NULL);
1458
1528
  vec3_multiply(*self, *rhs, *output);
1459
1529
  }} else if (argc == 1) {
@@ -1484,13 +1554,23 @@ static VALUE sm_vec3_add(int argc, VALUE *argv, VALUE sm_self)
1484
1554
  vec3_t *rhs;
1485
1555
  rb_scan_args(argc, argv, "11", &sm_rhs, &sm_out);
1486
1556
  self = sm_unwrap_vec3(sm_self, NULL);
1487
- SM_RAISE_IF_NOT_TYPE(sm_rhs, vec3);
1557
+ if (!SM_IS_A(sm_rhs, vec3) && !SM_IS_A(sm_rhs, vec4) && !SM_IS_A(sm_rhs, quat)) {
1558
+ rb_raise(rb_eTypeError,
1559
+ kSM_WANT_THREE_OR_FOUR_FORMAT_LIT,
1560
+ rb_obj_classname(sm_rhs));
1561
+ return Qnil;
1562
+ }
1488
1563
  rhs = sm_unwrap_vec3(sm_rhs, NULL);
1489
1564
  if (argc == 2) {
1490
1565
  if (!RTEST(sm_out)) {
1491
1566
  goto SM_LABEL(skip_output);
1492
1567
  }{
1493
- SM_RAISE_IF_NOT_TYPE(sm_out, vec3);
1568
+ if (!SM_IS_A(sm_out, vec3) && !SM_IS_A(sm_out, vec4) && !SM_IS_A(sm_out, quat)) {
1569
+ rb_raise(rb_eTypeError,
1570
+ kSM_WANT_THREE_OR_FOUR_FORMAT_LIT,
1571
+ rb_obj_classname(sm_out));
1572
+ return Qnil;
1573
+ }
1494
1574
  vec3_t *output = sm_unwrap_vec3(sm_out, NULL);
1495
1575
  vec3_add(*self, *rhs, *output);
1496
1576
  }} else if (argc == 1) {
@@ -1522,13 +1602,23 @@ static VALUE sm_vec3_subtract(int argc, VALUE *argv, VALUE sm_self)
1522
1602
  vec3_t *rhs;
1523
1603
  rb_scan_args(argc, argv, "11", &sm_rhs, &sm_out);
1524
1604
  self = sm_unwrap_vec3(sm_self, NULL);
1525
- SM_RAISE_IF_NOT_TYPE(sm_rhs, vec3);
1605
+ if (!SM_IS_A(sm_rhs, vec3) && !SM_IS_A(sm_rhs, vec4) && !SM_IS_A(sm_rhs, quat)) {
1606
+ rb_raise(rb_eTypeError,
1607
+ kSM_WANT_THREE_OR_FOUR_FORMAT_LIT,
1608
+ rb_obj_classname(sm_rhs));
1609
+ return Qnil;
1610
+ }
1526
1611
  rhs = sm_unwrap_vec3(sm_rhs, NULL);
1527
1612
  if (argc == 2) {
1528
1613
  if (!RTEST(sm_out)) {
1529
1614
  goto SM_LABEL(skip_output);
1530
1615
  }{
1531
- SM_RAISE_IF_NOT_TYPE(sm_out, vec3);
1616
+ if (!SM_IS_A(sm_out, vec3) && !SM_IS_A(sm_out, vec4) && !SM_IS_A(sm_out, quat)) {
1617
+ rb_raise(rb_eTypeError,
1618
+ kSM_WANT_THREE_OR_FOUR_FORMAT_LIT,
1619
+ rb_obj_classname(sm_out));
1620
+ return Qnil;
1621
+ }
1532
1622
  vec3_t *output = sm_unwrap_vec3(sm_out, NULL);
1533
1623
  vec3_subtract(*self, *rhs, *output);
1534
1624
  }} else if (argc == 1) {
@@ -1890,7 +1980,7 @@ static VALUE sm_vec4_length (VALUE self)
1890
1980
  * Returns a copy of self.
1891
1981
  *
1892
1982
  * call-seq:
1893
- * copy(output = nil) -> output or new vec4
1983
+ * copy(output = nil) -> output or new vec4 / quat
1894
1984
  */
1895
1985
  static VALUE sm_vec4_copy(int argc, VALUE *argv, VALUE sm_self)
1896
1986
  {
@@ -1902,7 +1992,12 @@ static VALUE sm_vec4_length (VALUE self)
1902
1992
  if (!RTEST(sm_out)) {
1903
1993
  goto SM_LABEL(skip_output);
1904
1994
  }{
1905
- SM_RAISE_IF_NOT_TYPE(sm_out, vec4);
1995
+ if (!SM_IS_A(sm_out, vec4) && !SM_IS_A(sm_out, quat)) {
1996
+ rb_raise(rb_eTypeError,
1997
+ kSM_WANT_FOUR_FORMAT_LIT,
1998
+ rb_obj_classname(sm_out));
1999
+ return Qnil;
2000
+ }
1906
2001
  vec4_t *output = sm_unwrap_vec4(sm_out, NULL);
1907
2002
  vec4_copy (*self, *output);
1908
2003
  }} else if (argc == 0) {
@@ -1920,10 +2015,11 @@ static VALUE sm_vec4_length (VALUE self)
1920
2015
 
1921
2016
 
1922
2017
  /*
1923
- * Returns a normalized vector.
2018
+ * Returns a normalized Vec4 or Quat, depending on the type of the receiver and
2019
+ * output.
1924
2020
  *
1925
2021
  * call-seq:
1926
- * normalize(output = nil) -> output or new vec4
2022
+ * normalize(output = nil) -> output or new vec4 / quat
1927
2023
  */
1928
2024
  static VALUE sm_vec4_normalize(int argc, VALUE *argv, VALUE sm_self)
1929
2025
  {
@@ -1935,7 +2031,11 @@ static VALUE sm_vec4_length (VALUE self)
1935
2031
  if (!RTEST(sm_out)) {
1936
2032
  goto SM_LABEL(skip_output);
1937
2033
  }{
1938
- SM_RAISE_IF_NOT_TYPE(sm_out, vec4);
2034
+ if (!SM_IS_A(sm_out, vec4) && !SM_IS_A(sm_out, quat)) {
2035
+ rb_raise(rb_eTypeError,
2036
+ kSM_WANT_FOUR_FORMAT_LIT,
2037
+ rb_obj_classname(sm_out));
2038
+ }
1939
2039
  vec4_t *output = sm_unwrap_vec4(sm_out, NULL);
1940
2040
  vec4_normalize (*self, *output);
1941
2041
  }} else if (argc == 0) {
@@ -1969,7 +2069,12 @@ static VALUE sm_vec4_length (VALUE self)
1969
2069
  if (!RTEST(sm_out)) {
1970
2070
  goto SM_LABEL(skip_output);
1971
2071
  }{
1972
- SM_RAISE_IF_NOT_TYPE(sm_out, vec4);
2072
+ if (!SM_IS_A(sm_out, vec4) && !SM_IS_A(sm_out, quat)) {
2073
+ rb_raise(rb_eTypeError,
2074
+ kSM_WANT_FOUR_FORMAT_LIT,
2075
+ rb_obj_classname(sm_out));
2076
+ return Qnil;
2077
+ }
1973
2078
  vec4_t *output = sm_unwrap_vec4(sm_out, NULL);
1974
2079
  vec4_inverse (*self, *output);
1975
2080
  }} else if (argc == 0) {
@@ -1987,10 +2092,10 @@ static VALUE sm_vec4_length (VALUE self)
1987
2092
 
1988
2093
 
1989
2094
  /*
1990
- * Negates this vector's components and returns the result.
2095
+ * Negates this vector or quaternions's components and returns the result.
1991
2096
  *
1992
2097
  * call-seq:
1993
- * negate(output = nil) -> output or new vec4
2098
+ * negate(output = nil) -> output or new vec4 or quat
1994
2099
  */
1995
2100
  static VALUE sm_vec4_negate(int argc, VALUE *argv, VALUE sm_self)
1996
2101
  {
@@ -2002,7 +2107,12 @@ static VALUE sm_vec4_length (VALUE self)
2002
2107
  if (!RTEST(sm_out)) {
2003
2108
  goto SM_LABEL(skip_output);
2004
2109
  }{
2005
- SM_RAISE_IF_NOT_TYPE(sm_out, vec4);
2110
+ if (!SM_IS_A(sm_out, vec4) && !SM_IS_A(sm_out, quat)) {
2111
+ rb_raise(rb_eTypeError,
2112
+ kSM_WANT_FOUR_FORMAT_LIT,
2113
+ rb_obj_classname(sm_out));
2114
+ return Qnil;
2115
+ }
2006
2116
  vec4_t *output = sm_unwrap_vec4(sm_out, NULL);
2007
2117
  vec4_negate (*self, *output);
2008
2118
  }} else if (argc == 0) {
@@ -2033,13 +2143,23 @@ static VALUE sm_vec4_project(int argc, VALUE *argv, VALUE sm_self)
2033
2143
  vec4_t *rhs;
2034
2144
  rb_scan_args(argc, argv, "11", &sm_rhs, &sm_out);
2035
2145
  self = sm_unwrap_vec4(sm_self, NULL);
2036
- SM_RAISE_IF_NOT_TYPE(sm_rhs, vec4);
2146
+ if (!SM_IS_A(sm_rhs, vec4) && !SM_IS_A(sm_rhs, quat)) {
2147
+ rb_raise(rb_eTypeError,
2148
+ kSM_WANT_FOUR_FORMAT_LIT,
2149
+ rb_obj_classname(sm_rhs));
2150
+ return Qnil;
2151
+ }
2037
2152
  rhs = sm_unwrap_vec4(sm_rhs, NULL);
2038
2153
  if (argc == 2) {
2039
2154
  if (!RTEST(sm_out)) {
2040
2155
  goto SM_LABEL(skip_output);
2041
2156
  }{
2042
- SM_RAISE_IF_NOT_TYPE(sm_out, vec4);
2157
+ if (!SM_IS_A(sm_out, vec4) && !SM_IS_A(sm_out, quat)) {
2158
+ rb_raise(rb_eTypeError,
2159
+ kSM_WANT_FOUR_FORMAT_LIT,
2160
+ rb_obj_classname(sm_out));
2161
+ return Qnil;
2162
+ }
2043
2163
  vec4_t *output = sm_unwrap_vec4(sm_out, NULL);
2044
2164
  vec4_project(*self, *rhs, *output);
2045
2165
  }} else if (argc == 1) {
@@ -2070,13 +2190,23 @@ static VALUE sm_vec4_reflect(int argc, VALUE *argv, VALUE sm_self)
2070
2190
  vec4_t *rhs;
2071
2191
  rb_scan_args(argc, argv, "11", &sm_rhs, &sm_out);
2072
2192
  self = sm_unwrap_vec4(sm_self, NULL);
2073
- SM_RAISE_IF_NOT_TYPE(sm_rhs, vec4);
2193
+ if (!SM_IS_A(sm_rhs, vec4) && !SM_IS_A(sm_rhs, quat)) {
2194
+ rb_raise(rb_eTypeError,
2195
+ kSM_WANT_FOUR_FORMAT_LIT,
2196
+ rb_obj_classname(sm_rhs));
2197
+ return Qnil;
2198
+ }
2074
2199
  rhs = sm_unwrap_vec4(sm_rhs, NULL);
2075
2200
  if (argc == 2) {
2076
2201
  if (!RTEST(sm_out)) {
2077
2202
  goto SM_LABEL(skip_output);
2078
2203
  }{
2079
- SM_RAISE_IF_NOT_TYPE(sm_out, vec4);
2204
+ if (!SM_IS_A(sm_out, vec4) && !SM_IS_A(sm_out, quat)) {
2205
+ rb_raise(rb_eTypeError,
2206
+ kSM_WANT_FOUR_FORMAT_LIT,
2207
+ rb_obj_classname(sm_out));
2208
+ return Qnil;
2209
+ }
2080
2210
  vec4_t *output = sm_unwrap_vec4(sm_out, NULL);
2081
2211
  vec4_reflect(*self, *rhs, *output);
2082
2212
  }} else if (argc == 1) {
@@ -2108,13 +2238,23 @@ static VALUE sm_vec4_multiply(int argc, VALUE *argv, VALUE sm_self)
2108
2238
  vec4_t *rhs;
2109
2239
  rb_scan_args(argc, argv, "11", &sm_rhs, &sm_out);
2110
2240
  self = sm_unwrap_vec4(sm_self, NULL);
2111
- SM_RAISE_IF_NOT_TYPE(sm_rhs, vec4);
2241
+ if (!SM_IS_A(sm_rhs, vec4) && !SM_IS_A(sm_rhs, quat)) {
2242
+ rb_raise(rb_eTypeError,
2243
+ kSM_WANT_FOUR_FORMAT_LIT,
2244
+ rb_obj_classname(sm_rhs));
2245
+ return Qnil;
2246
+ }
2112
2247
  rhs = sm_unwrap_vec4(sm_rhs, NULL);
2113
2248
  if (argc == 2) {
2114
2249
  if (!RTEST(sm_out)) {
2115
2250
  goto SM_LABEL(skip_output);
2116
2251
  }{
2117
- SM_RAISE_IF_NOT_TYPE(sm_out, vec4);
2252
+ if (!SM_IS_A(sm_out, vec4) && !SM_IS_A(sm_out, quat)) {
2253
+ rb_raise(rb_eTypeError,
2254
+ kSM_WANT_FOUR_FORMAT_LIT,
2255
+ rb_obj_classname(sm_out));
2256
+ return Qnil;
2257
+ }
2118
2258
  vec4_t *output = sm_unwrap_vec4(sm_out, NULL);
2119
2259
  vec4_multiply(*self, *rhs, *output);
2120
2260
  }} else if (argc == 1) {
@@ -2132,10 +2272,11 @@ SM_LABEL(skip_output): {
2132
2272
 
2133
2273
 
2134
2274
  /*
2135
- * Adds this and another vector's components together and returns the result.
2275
+ * Adds this and another vector or quaternion's components together and returns
2276
+ * the result. The result type is that of the receiver.
2136
2277
  *
2137
2278
  * call-seq:
2138
- * add(vec4, output = nil) -> output or new vec4
2279
+ * add(vec4, output = nil) -> output or new vec4 or quat
2139
2280
  */
2140
2281
  static VALUE sm_vec4_add(int argc, VALUE *argv, VALUE sm_self)
2141
2282
  {
@@ -2145,13 +2286,23 @@ static VALUE sm_vec4_add(int argc, VALUE *argv, VALUE sm_self)
2145
2286
  vec4_t *rhs;
2146
2287
  rb_scan_args(argc, argv, "11", &sm_rhs, &sm_out);
2147
2288
  self = sm_unwrap_vec4(sm_self, NULL);
2148
- SM_RAISE_IF_NOT_TYPE(sm_rhs, vec4);
2289
+ if (!SM_IS_A(sm_rhs, vec4) && !SM_IS_A(sm_rhs, quat)) {
2290
+ rb_raise(rb_eTypeError,
2291
+ kSM_WANT_FOUR_FORMAT_LIT,
2292
+ rb_obj_classname(sm_rhs));
2293
+ return Qnil;
2294
+ }
2149
2295
  rhs = sm_unwrap_vec4(sm_rhs, NULL);
2150
2296
  if (argc == 2) {
2151
2297
  if (!RTEST(sm_out)) {
2152
2298
  goto SM_LABEL(skip_output);
2153
2299
  }{
2154
- SM_RAISE_IF_NOT_TYPE(sm_out, vec4);
2300
+ if (!SM_IS_A(sm_rhs, vec4) && !SM_IS_A(sm_rhs, quat)) {
2301
+ rb_raise(rb_eTypeError,
2302
+ kSM_WANT_FOUR_FORMAT_LIT,
2303
+ rb_obj_classname(sm_rhs));
2304
+ return Qnil;
2305
+ }
2155
2306
  vec4_t *output = sm_unwrap_vec4(sm_out, NULL);
2156
2307
  vec4_add(*self, *rhs, *output);
2157
2308
  }} else if (argc == 1) {
@@ -2169,8 +2320,8 @@ SM_LABEL(skip_output): {
2169
2320
 
2170
2321
 
2171
2322
  /*
2172
- * Subtracts another vector's components from this vector's and returns the
2173
- * result.
2323
+ * Subtracts another vector or quaternion's components from this vector's and
2324
+ * returns the result. The return type is that of the receiver.
2174
2325
  *
2175
2326
  * call-seq:
2176
2327
  * subtract(vec4, output = nil) -> output or new vec4
@@ -2183,13 +2334,23 @@ static VALUE sm_vec4_subtract(int argc, VALUE *argv, VALUE sm_self)
2183
2334
  vec4_t *rhs;
2184
2335
  rb_scan_args(argc, argv, "11", &sm_rhs, &sm_out);
2185
2336
  self = sm_unwrap_vec4(sm_self, NULL);
2186
- SM_RAISE_IF_NOT_TYPE(sm_rhs, vec4);
2337
+ if (!SM_IS_A(sm_rhs, vec4) && !SM_IS_A(sm_rhs, quat)) {
2338
+ rb_raise(rb_eTypeError,
2339
+ kSM_WANT_FOUR_FORMAT_LIT,
2340
+ rb_obj_classname(sm_rhs));
2341
+ return Qnil;
2342
+ }
2187
2343
  rhs = sm_unwrap_vec4(sm_rhs, NULL);
2188
2344
  if (argc == 2) {
2189
2345
  if (!RTEST(sm_out)) {
2190
2346
  goto SM_LABEL(skip_output);
2191
2347
  }{
2192
- SM_RAISE_IF_NOT_TYPE(sm_out, vec4);
2348
+ if (!SM_IS_A(sm_rhs, vec4) && !SM_IS_A(sm_rhs, quat)) {
2349
+ rb_raise(rb_eTypeError,
2350
+ kSM_WANT_FOUR_FORMAT_LIT,
2351
+ rb_obj_classname(sm_rhs));
2352
+ return Qnil;
2353
+ }
2193
2354
  vec4_t *output = sm_unwrap_vec4(sm_out, NULL);
2194
2355
  vec4_subtract(*self, *rhs, *output);
2195
2356
  }} else if (argc == 1) {
@@ -2219,7 +2380,7 @@ static VALUE sm_vec4_dot_product(VALUE sm_self, VALUE sm_other)
2219
2380
  if (!SM_IS_A(sm_other, vec4) &&
2220
2381
  !SM_IS_A(sm_other, quat)) {
2221
2382
  rb_raise(rb_eArgError,
2222
- "Expected a Quat or Vec4, got %s",
2383
+ kSM_WANT_FOUR_FORMAT_LIT,
2223
2384
  rb_obj_classname(sm_other));
2224
2385
  return Qnil;
2225
2386
  }
@@ -2374,7 +2535,8 @@ static VALUE sm_vec4_magnitude(VALUE sm_self)
2374
2535
 
2375
2536
 
2376
2537
  /*
2377
- * Scales this vector's components by a scalar value and returns the result.
2538
+ * Scales this vector or quaternion's components by a scalar value and returns
2539
+ * the result. The return type is that of the receiver.
2378
2540
  *
2379
2541
  * call-seq:
2380
2542
  * scale(scalar, output = nil) -> output or new vec4
@@ -2404,7 +2566,8 @@ static VALUE sm_vec4_scale(int argc, VALUE *argv, VALUE sm_self)
2404
2566
 
2405
2567
 
2406
2568
  /*
2407
- * Divides this vector's components by a scalar value and returns the result.
2569
+ * Divides this vector or quaternion's components by a scalar value and returns
2570
+ * the result. The return type is that of the receiver.
2408
2571
  *
2409
2572
  * call-seq:
2410
2573
  * divide(scalar, output = nil) -> output or new vec4
@@ -2550,39 +2713,6 @@ static VALUE sm_quat_length (VALUE self)
2550
2713
 
2551
2714
 
2552
2715
 
2553
- /*
2554
- * Returns a copy of self.
2555
- *
2556
- * call-seq:
2557
- * copy(output = nil) -> output or new quat
2558
- */
2559
- static VALUE sm_quat_copy(int argc, VALUE *argv, VALUE sm_self)
2560
- {
2561
- VALUE sm_out;
2562
- quat_t *self;
2563
- rb_scan_args(argc, argv, "01", &sm_out);
2564
- self = sm_unwrap_quat(sm_self, NULL);
2565
- if (argc == 1) {
2566
- if (!RTEST(sm_out)) {
2567
- goto SM_LABEL(skip_output);
2568
- }{
2569
- SM_RAISE_IF_NOT_TYPE(sm_out, quat);
2570
- quat_t *output = sm_unwrap_quat(sm_out, NULL);
2571
- quat_copy (*self, *output);
2572
- }} else if (argc == 0) {
2573
- SM_LABEL(skip_output): {
2574
- quat_t output;
2575
- quat_copy (*self, output);
2576
- sm_out = sm_wrap_quat(output, rb_obj_class(sm_self));
2577
- rb_obj_call_init(sm_out, 0, 0);
2578
- }} else {
2579
- rb_raise(rb_eArgError, "Invalid number of arguments to copy");
2580
- }
2581
- return sm_out;
2582
- }
2583
-
2584
-
2585
-
2586
2716
  /*
2587
2717
  * Returns the inverse of this Quat. Note that this is not the same as the
2588
2718
  * inverse of, for example, a Vec4.
@@ -2600,7 +2730,12 @@ static VALUE sm_quat_length (VALUE self)
2600
2730
  if (!RTEST(sm_out)) {
2601
2731
  goto SM_LABEL(skip_output);
2602
2732
  }{
2603
- SM_RAISE_IF_NOT_TYPE(sm_out, quat);
2733
+ if (!SM_IS_A(sm_out, vec4) && !SM_IS_A(sm_out, quat)) {
2734
+ rb_raise(rb_eTypeError,
2735
+ kSM_WANT_FOUR_FORMAT_LIT,
2736
+ rb_obj_classname(sm_out));
2737
+ return Qnil;
2738
+ }
2604
2739
  quat_t *output = sm_unwrap_quat(sm_out, NULL);
2605
2740
  quat_inverse (*self, *output);
2606
2741
  }} else if (argc == 0) {
@@ -2617,39 +2752,6 @@ static VALUE sm_quat_length (VALUE self)
2617
2752
 
2618
2753
 
2619
2754
 
2620
- /*
2621
- * Negates all components of this quaternion and returns the result.
2622
- *
2623
- * call-seq:
2624
- * negate(output = nil) -> output or new quat
2625
- */
2626
- static VALUE sm_quat_negate(int argc, VALUE *argv, VALUE sm_self)
2627
- {
2628
- VALUE sm_out;
2629
- quat_t *self;
2630
- rb_scan_args(argc, argv, "01", &sm_out);
2631
- self = sm_unwrap_quat(sm_self, NULL);
2632
- if (argc == 1) {
2633
- if (!RTEST(sm_out)) {
2634
- goto SM_LABEL(skip_output);
2635
- }{
2636
- SM_RAISE_IF_NOT_TYPE(sm_out, quat);
2637
- quat_t *output = sm_unwrap_quat(sm_out, NULL);
2638
- quat_negate (*self, *output);
2639
- }} else if (argc == 0) {
2640
- SM_LABEL(skip_output): {
2641
- quat_t output;
2642
- quat_negate (*self, output);
2643
- sm_out = sm_wrap_quat(output, rb_obj_class(sm_self));
2644
- rb_obj_call_init(sm_out, 0, 0);
2645
- }} else {
2646
- rb_raise(rb_eArgError, "Invalid number of arguments to negate");
2647
- }
2648
- return sm_out;
2649
- }
2650
-
2651
-
2652
-
2653
2755
  /*
2654
2756
  * Concatenates this quaternion and another and returns the result.
2655
2757
  *
@@ -2664,13 +2766,23 @@ static VALUE sm_quat_multiply(int argc, VALUE *argv, VALUE sm_self)
2664
2766
  quat_t *rhs;
2665
2767
  rb_scan_args(argc, argv, "11", &sm_rhs, &sm_out);
2666
2768
  self = sm_unwrap_quat(sm_self, NULL);
2667
- SM_RAISE_IF_NOT_TYPE(sm_rhs, quat);
2769
+ if (!!SM_IS_A(sm_rhs, vec4) && !SM_IS_A(sm_rhs, quat)) {
2770
+ rb_raise(rb_eTypeError,
2771
+ kSM_WANT_FOUR_FORMAT_LIT,
2772
+ rb_obj_classname(sm_rhs));
2773
+ return Qnil;
2774
+ }
2668
2775
  rhs = sm_unwrap_quat(sm_rhs, NULL);
2669
2776
  if (argc == 2) {
2670
2777
  if (!RTEST(sm_out)) {
2671
2778
  goto SM_LABEL(skip_output);
2672
2779
  }{
2673
- SM_RAISE_IF_NOT_TYPE(sm_out, quat);
2780
+ if (!!SM_IS_A(sm_out, vec4) && !SM_IS_A(sm_out, quat)) {
2781
+ rb_raise(rb_eTypeError,
2782
+ kSM_WANT_FOUR_FORMAT_LIT,
2783
+ rb_obj_classname(sm_out));
2784
+ return Qnil;
2785
+ }
2674
2786
  quat_t *output = sm_unwrap_quat(sm_out, NULL);
2675
2787
  quat_multiply(*self, *rhs, *output);
2676
2788
  }} else if (argc == 1) {
@@ -2698,23 +2810,33 @@ static VALUE sm_quat_multiply_vec3(int argc, VALUE *argv, VALUE sm_self)
2698
2810
  VALUE sm_rhs;
2699
2811
  VALUE sm_out;
2700
2812
  quat_t *self;
2701
- quat_t *rhs;
2813
+ vec3_t *rhs;
2702
2814
  rb_scan_args(argc, argv, "11", &sm_rhs, &sm_out);
2703
2815
  self = sm_unwrap_quat(sm_self, NULL);
2704
- SM_RAISE_IF_NOT_TYPE(sm_rhs, quat);
2705
- rhs = sm_unwrap_quat(sm_rhs, NULL);
2816
+ if (!SM_IS_A(sm_rhs, vec3) && !SM_IS_A(sm_rhs, vec4) && !SM_IS_A(sm_rhs, quat)) {
2817
+ rb_raise(rb_eTypeError,
2818
+ kSM_WANT_THREE_OR_FOUR_FORMAT_LIT,
2819
+ rb_obj_classname(sm_rhs));
2820
+ return Qnil;
2821
+ }
2822
+ rhs = sm_unwrap_vec3(sm_rhs, NULL);
2706
2823
  if (argc == 2) {
2707
2824
  if (!RTEST(sm_out)) {
2708
2825
  goto SM_LABEL(skip_output);
2709
2826
  }{
2710
- SM_RAISE_IF_NOT_TYPE(sm_out, quat);
2711
- quat_t *output = sm_unwrap_quat(sm_out, NULL);
2827
+ if (!SM_IS_A(sm_out, vec3) && !SM_IS_A(sm_out, vec4) && !SM_IS_A(sm_out, quat)) {
2828
+ rb_raise(rb_eTypeError,
2829
+ kSM_WANT_THREE_OR_FOUR_FORMAT_LIT,
2830
+ rb_obj_classname(sm_out));
2831
+ return Qnil;
2832
+ }
2833
+ vec3_t *output = sm_unwrap_vec3(sm_out, NULL);
2712
2834
  quat_multiply_vec3(*self, *rhs, *output);
2713
2835
  }} else if (argc == 1) {
2714
2836
  SM_LABEL(skip_output): {
2715
- quat_t output;
2837
+ vec3_t output;
2716
2838
  quat_multiply_vec3(*self, *rhs, output);
2717
- sm_out = sm_wrap_quat(output, rb_obj_class(sm_self));
2839
+ sm_out = sm_wrap_vec3(output, rb_obj_class(sm_rhs));
2718
2840
  rb_obj_call_init(sm_out, 0, 0);
2719
2841
  }} else {
2720
2842
  rb_raise(rb_eArgError, "Invalid number of arguments to quat");
@@ -2871,7 +2993,12 @@ static VALUE sm_quat_angle_axis(int argc, VALUE *argv, VALUE self)
2871
2993
  const vec3_t *axis;
2872
2994
 
2873
2995
  rb_scan_args(argc, argv, "21", &sm_angle, &sm_axis, &sm_out);
2874
- SM_RAISE_IF_NOT_TYPE(sm_axis, vec3);
2996
+ if (!SM_IS_A(sm_axis, vec3) && !SM_IS_A(sm_axis, vec4) && !SM_IS_A(sm_axis, quat)) {
2997
+ rb_raise(rb_eTypeError,
2998
+ kSM_WANT_THREE_OR_FOUR_FORMAT_LIT,
2999
+ rb_obj_classname(sm_axis));
3000
+ return Qnil;
3001
+ }
2875
3002
 
2876
3003
  angle = (s_float_t)rb_num2dbl(sm_angle);
2877
3004
  axis = sm_unwrap_vec3(sm_axis, NULL);
@@ -2906,67 +3033,6 @@ static VALUE sm_quat_identity(VALUE sm_self)
2906
3033
 
2907
3034
 
2908
3035
 
2909
- /*
2910
- * Scales this quaternion's components by a scalar value and returns the result.
2911
- *
2912
- * call-seq:
2913
- * scale(scalar, output = nil) -> output or new quat
2914
- */
2915
- static VALUE sm_quat_scale(int argc, VALUE *argv, VALUE sm_self)
2916
- {
2917
- VALUE sm_out;
2918
- VALUE sm_scalar;
2919
- s_float_t scalar;
2920
- vec4_t *self = sm_unwrap_vec4(sm_self, NULL);
2921
-
2922
- rb_scan_args(argc, argv, "11", &sm_scalar, &sm_out);
2923
- scalar = rb_num2dbl(sm_scalar);
2924
-
2925
- if ((SM_IS_A(sm_out, vec4) || SM_IS_A(sm_out, quat))) {
2926
- vec4_scale(*self, scalar, *sm_unwrap_vec4(sm_out, NULL));
2927
- } else {
2928
- vec4_t out;
2929
- vec4_scale(*self, scalar, out);
2930
- sm_out = sm_wrap_quat(out, rb_obj_class(sm_self));
2931
- rb_obj_call_init(sm_out, 0, 0);
2932
- }
2933
-
2934
- return sm_out;
2935
- }
2936
-
2937
-
2938
-
2939
- /*
2940
- * Divides this quaternion's components by a scalar value and returns the
2941
- * result.
2942
- *
2943
- * call-seq:
2944
- * divide(scalar, output = nil) -> output or new quat
2945
- */
2946
- static VALUE sm_quat_divide(int argc, VALUE *argv, VALUE sm_self)
2947
- {
2948
- VALUE sm_out;
2949
- VALUE sm_scalar;
2950
- s_float_t scalar;
2951
- vec4_t *self = sm_unwrap_vec4(sm_self, NULL);
2952
-
2953
- rb_scan_args(argc, argv, "11", &sm_scalar, &sm_out);
2954
- scalar = rb_num2dbl(sm_scalar);
2955
-
2956
- if ((SM_IS_A(sm_out, vec4) || SM_IS_A(sm_out, quat))) {
2957
- vec4_divide(*self, scalar, *sm_unwrap_vec4(sm_out, NULL));
2958
- } else {
2959
- vec4_t out;
2960
- vec4_divide(*self, scalar, out);
2961
- sm_out = sm_wrap_quat(out, rb_obj_class(sm_self));
2962
- rb_obj_call_init(sm_out, 0, 0);
2963
- }
2964
-
2965
- return sm_out;
2966
- }
2967
-
2968
-
2969
-
2970
3036
  /*
2971
3037
  * Returns a quaternion interpolated between self and destination using
2972
3038
  * spherical linear interpolation. Alpha is the interpolation value and must be
@@ -2989,7 +3055,7 @@ static VALUE sm_quat_slerp(int argc, VALUE *argv, VALUE sm_self)
2989
3055
 
2990
3056
  if (!SM_IS_A(sm_destination, vec4) && !SM_IS_A(sm_destination, quat)) {
2991
3057
  rb_raise(rb_eTypeError,
2992
- "Expected either Vec4 or Quat, got %s",
3058
+ kSM_WANT_FOUR_FORMAT_LIT,
2993
3059
  rb_obj_classname(sm_destination));
2994
3060
  return Qnil;
2995
3061
  }
@@ -3010,108 +3076,6 @@ static VALUE sm_quat_slerp(int argc, VALUE *argv, VALUE sm_self)
3010
3076
 
3011
3077
 
3012
3078
 
3013
- /*
3014
- * Normalizes the quaternion.
3015
- *
3016
- * call-seq:
3017
- * normalize(output = nil) -> output or new qual
3018
- */
3019
- static VALUE sm_quat_normalize(int argc, VALUE *argv, VALUE sm_self)
3020
- {
3021
- VALUE sm_out;
3022
- VALUE sm_scalar;
3023
- s_float_t scalar;
3024
- vec4_t *self = sm_unwrap_vec4(sm_self, NULL);
3025
-
3026
- rb_scan_args(argc, argv, "01", &sm_scalar, &sm_out);
3027
- scalar = rb_num2dbl(sm_scalar);
3028
-
3029
- if ((SM_IS_A(sm_out, vec4) || SM_IS_A(sm_out, quat))) {
3030
- vec4_normalize(*self, *sm_unwrap_vec4(sm_out, NULL));
3031
- } else {
3032
- vec4_t out;
3033
- vec4_normalize(*self, out);
3034
- sm_out = sm_wrap_quat(out, rb_obj_class(sm_self));
3035
- rb_obj_call_init(sm_out, 0, 0);
3036
- }
3037
-
3038
- return sm_out;
3039
- }
3040
-
3041
-
3042
-
3043
- /*
3044
- * Adds the components of this and another quaternion together and returns the
3045
- * result.
3046
- *
3047
- * call-seq:
3048
- * add(quat, output = nil) -> output or new quat
3049
- */
3050
- static VALUE sm_quat_add(int argc, VALUE *argv, VALUE sm_self)
3051
- {
3052
- VALUE sm_out;
3053
- VALUE sm_left;
3054
- vec4_t *self = sm_unwrap_vec4(sm_self, NULL);
3055
-
3056
- rb_scan_args(argc, argv, "11", &sm_left, &sm_out);
3057
-
3058
- if (!SM_IS_A(sm_left, vec4) && !SM_IS_A(sm_left, quat)) {
3059
- rb_raise(rb_eTypeError,
3060
- "Expected either Vec4 or Quat, got %s",
3061
- rb_obj_classname(sm_left));
3062
- return Qnil;
3063
- }
3064
-
3065
- if ((SM_IS_A(sm_out, vec4) || SM_IS_A(sm_out, quat))) {
3066
- vec4_add(*self, *sm_unwrap_vec4(sm_left, NULL), *sm_unwrap_vec4(sm_out, NULL));
3067
- } else {
3068
- vec4_t out;
3069
- vec4_add(*self, *sm_unwrap_vec4(sm_left, NULL), out);
3070
- sm_out = sm_wrap_quat(out, rb_obj_class(sm_self));
3071
- rb_obj_call_init(sm_out, 0, 0);
3072
- }
3073
-
3074
- return sm_out;
3075
- }
3076
-
3077
-
3078
-
3079
- /*
3080
- * Subtract's another quaternion's components from this quaternion and returns
3081
- * the result.
3082
- *
3083
- * call-seq:
3084
- * subtract(quat, output = nil) -> output or new quat
3085
- */
3086
- static VALUE sm_quat_subtract(int argc, VALUE *argv, VALUE sm_self)
3087
- {
3088
- VALUE sm_out;
3089
- VALUE sm_left;
3090
- vec4_t *self = sm_unwrap_vec4(sm_self, NULL);
3091
-
3092
- rb_scan_args(argc, argv, "11", &sm_left, &sm_out);
3093
-
3094
- if (!SM_IS_A(sm_left, vec4) && !SM_IS_A(sm_left, quat)) {
3095
- rb_raise(rb_eTypeError,
3096
- "Expected either Vec4 or Quat, got %s",
3097
- rb_obj_classname(sm_left));
3098
- return Qnil;
3099
- }
3100
-
3101
- if ((SM_IS_A(sm_out, vec4) || SM_IS_A(sm_out, quat))) {
3102
- vec4_subtract(*self, *sm_unwrap_vec4(sm_left, NULL), *sm_unwrap_vec4(sm_out, NULL));
3103
- } else {
3104
- vec4_t out;
3105
- vec4_subtract(*self, *sm_unwrap_vec4(sm_left, NULL), out);
3106
- sm_out = sm_wrap_quat(out, rb_obj_class(sm_self));
3107
- rb_obj_call_init(sm_out, 0, 0);
3108
- }
3109
-
3110
- return sm_out;
3111
- }
3112
-
3113
-
3114
-
3115
3079
  /*==============================================================================
3116
3080
 
3117
3081
  mat4_t functions
@@ -3425,13 +3389,23 @@ static VALUE sm_mat4_multiply_vec4(int argc, VALUE *argv, VALUE sm_self)
3425
3389
  vec4_t *rhs;
3426
3390
  rb_scan_args(argc, argv, "11", &sm_rhs, &sm_out);
3427
3391
  self = sm_unwrap_mat4(sm_self, NULL);
3428
- SM_RAISE_IF_NOT_TYPE(sm_rhs, vec4);
3392
+ if (!SM_IS_A(sm_rhs, vec4) && !SM_IS_A(sm_rhs, quat)) {
3393
+ rb_raise(rb_eTypeError,
3394
+ kSM_WANT_FOUR_FORMAT_LIT,
3395
+ rb_obj_classname(sm_rhs));
3396
+ return Qnil;
3397
+ }
3429
3398
  rhs = sm_unwrap_vec4(sm_rhs, NULL);
3430
3399
  if (argc == 2) {
3431
3400
  if (!RTEST(sm_out)) {
3432
3401
  goto SM_LABEL(skip_output);
3433
3402
  }{
3434
- SM_RAISE_IF_NOT_TYPE(sm_out, vec4);
3403
+ if (!SM_IS_A(sm_out, vec4) && !SM_IS_A(sm_out, quat)) {
3404
+ rb_raise(rb_eTypeError,
3405
+ kSM_WANT_FOUR_FORMAT_LIT,
3406
+ rb_obj_classname(sm_out));
3407
+ return Qnil;
3408
+ }
3435
3409
  vec4_t *output = sm_unwrap_vec4(sm_out, NULL);
3436
3410
  mat4_multiply_vec4(*self, *rhs, *output);
3437
3411
  }} else if (argc == 1) {
@@ -3462,13 +3436,23 @@ static VALUE sm_mat4_transform_vec3(int argc, VALUE *argv, VALUE sm_self)
3462
3436
  vec3_t *rhs;
3463
3437
  rb_scan_args(argc, argv, "11", &sm_rhs, &sm_out);
3464
3438
  self = sm_unwrap_mat4(sm_self, NULL);
3465
- SM_RAISE_IF_NOT_TYPE(sm_rhs, vec3);
3439
+ if (!SM_IS_A(sm_rhs, vec3) && !SM_IS_A(sm_rhs, vec4) && !SM_IS_A(sm_rhs, quat)) {
3440
+ rb_raise(rb_eTypeError,
3441
+ kSM_WANT_THREE_OR_FOUR_FORMAT_LIT,
3442
+ rb_obj_classname(sm_rhs));
3443
+ return Qnil;
3444
+ }
3466
3445
  rhs = sm_unwrap_vec3(sm_rhs, NULL);
3467
3446
  if (argc == 2) {
3468
3447
  if (!RTEST(sm_out)) {
3469
3448
  goto SM_LABEL(skip_output);
3470
3449
  }{
3471
- SM_RAISE_IF_NOT_TYPE(sm_out, vec3);
3450
+ if (!SM_IS_A(sm_out, vec3) && !SM_IS_A(sm_out, vec4) && !SM_IS_A(sm_out, quat)) {
3451
+ rb_raise(rb_eTypeError,
3452
+ kSM_WANT_THREE_OR_FOUR_FORMAT_LIT,
3453
+ rb_obj_classname(sm_out));
3454
+ return Qnil;
3455
+ }
3472
3456
  vec3_t *output = sm_unwrap_vec3(sm_out, NULL);
3473
3457
  mat4_transform_vec3(*self, *rhs, *output);
3474
3458
  }} else if (argc == 1) {
@@ -3500,13 +3484,23 @@ static VALUE sm_mat4_rotate_vec3(int argc, VALUE *argv, VALUE sm_self)
3500
3484
  vec3_t *rhs;
3501
3485
  rb_scan_args(argc, argv, "11", &sm_rhs, &sm_out);
3502
3486
  self = sm_unwrap_mat4(sm_self, NULL);
3503
- SM_RAISE_IF_NOT_TYPE(sm_rhs, vec3);
3487
+ if (!SM_IS_A(sm_rhs, vec3) && !SM_IS_A(sm_rhs, vec4) && !SM_IS_A(sm_rhs, quat)) {
3488
+ rb_raise(rb_eTypeError,
3489
+ kSM_WANT_THREE_OR_FOUR_FORMAT_LIT,
3490
+ rb_obj_classname(sm_rhs));
3491
+ return Qnil;
3492
+ }
3504
3493
  rhs = sm_unwrap_vec3(sm_rhs, NULL);
3505
3494
  if (argc == 2) {
3506
3495
  if (!RTEST(sm_out)) {
3507
3496
  goto SM_LABEL(skip_output);
3508
3497
  }{
3509
- SM_RAISE_IF_NOT_TYPE(sm_out, vec3);
3498
+ if (!SM_IS_A(sm_out, vec3) && !SM_IS_A(sm_out, vec4) && !SM_IS_A(sm_out, quat)) {
3499
+ rb_raise(rb_eTypeError,
3500
+ kSM_WANT_THREE_OR_FOUR_FORMAT_LIT,
3501
+ rb_obj_classname(sm_out));
3502
+ return Qnil;
3503
+ }
3510
3504
  vec3_t *output = sm_unwrap_vec3(sm_out, NULL);
3511
3505
  mat4_rotate_vec3(*self, *rhs, *output);
3512
3506
  }} else if (argc == 1) {
@@ -3538,13 +3532,23 @@ static VALUE sm_mat4_inv_rotate_vec3(int argc, VALUE *argv, VALUE sm_self)
3538
3532
  vec3_t *rhs;
3539
3533
  rb_scan_args(argc, argv, "11", &sm_rhs, &sm_out);
3540
3534
  self = sm_unwrap_mat4(sm_self, NULL);
3541
- SM_RAISE_IF_NOT_TYPE(sm_rhs, vec3);
3535
+ if (!SM_IS_A(sm_rhs, vec3) && !SM_IS_A(sm_rhs, vec4) && !SM_IS_A(sm_rhs, quat)) {
3536
+ rb_raise(rb_eTypeError,
3537
+ kSM_WANT_THREE_OR_FOUR_FORMAT_LIT,
3538
+ rb_obj_classname(sm_rhs));
3539
+ return Qnil;
3540
+ }
3542
3541
  rhs = sm_unwrap_vec3(sm_rhs, NULL);
3543
3542
  if (argc == 2) {
3544
3543
  if (!RTEST(sm_out)) {
3545
3544
  goto SM_LABEL(skip_output);
3546
3545
  }{
3547
- SM_RAISE_IF_NOT_TYPE(sm_out, vec3);
3546
+ if (!SM_IS_A(sm_out, vec3) && !SM_IS_A(sm_out, vec4) && !SM_IS_A(sm_out, quat)) {
3547
+ rb_raise(rb_eTypeError,
3548
+ kSM_WANT_THREE_OR_FOUR_FORMAT_LIT,
3549
+ rb_obj_classname(sm_out));
3550
+ return Qnil;
3551
+ }
3548
3552
  vec3_t *output = sm_unwrap_vec3(sm_out, NULL);
3549
3553
  mat4_inv_rotate_vec3(*self, *rhs, *output);
3550
3554
  }} else if (argc == 1) {
@@ -3877,7 +3881,7 @@ static VALUE sm_mat4_init(int argc, VALUE *argv, VALUE sm_self)
3877
3881
  if (!SM_IS_A(argv[arg_index], vec4) && !SM_IS_A(argv[arg_index], quat)) {
3878
3882
  rb_raise(
3879
3883
  rb_eArgError,
3880
- "Argument %d must be a Vec4 or Quat when supplying four arguments to Mat4.initialize",
3884
+ "Argument %d must be a Vec4 or Quat when supplying four arguments to Mat4.initialize/set",
3881
3885
  (int)(arg_index + 1));
3882
3886
  }
3883
3887
 
@@ -3952,7 +3956,12 @@ static VALUE sm_mat4_angle_axis(int argc, VALUE *argv, VALUE self)
3952
3956
  const vec3_t *axis;
3953
3957
 
3954
3958
  rb_scan_args(argc, argv, "21", &sm_angle, &sm_axis, &sm_out);
3955
- SM_RAISE_IF_NOT_TYPE(sm_axis, vec3);
3959
+ if (!SM_IS_A(sm_axis, vec3) && !SM_IS_A(sm_axis, vec4) && !SM_IS_A(sm_axis, quat)) {
3960
+ rb_raise(rb_eTypeError,
3961
+ kSM_WANT_THREE_OR_FOUR_FORMAT_LIT,
3962
+ rb_obj_classname(sm_axis));
3963
+ return Qnil;
3964
+ }
3956
3965
 
3957
3966
  angle = (s_float_t)rb_num2dbl(sm_angle);
3958
3967
  axis = sm_unwrap_vec3(sm_axis, NULL);
@@ -3976,7 +3985,7 @@ static VALUE sm_mat4_angle_axis(int argc, VALUE *argv, VALUE self)
3976
3985
  * Returns a Vec3 whose components are that of the row at the given index.
3977
3986
  *
3978
3987
  * call-seq:
3979
- * get_row3(index) -> new vec3
3988
+ * get_row3(index, output = nil) -> output or new vec3
3980
3989
  */
3981
3990
  static VALUE sm_mat4_get_row3(int argc, VALUE *argv, VALUE sm_self)
3982
3991
  {
@@ -4000,7 +4009,12 @@ static VALUE sm_mat4_get_row3(int argc, VALUE *argv, VALUE sm_self)
4000
4009
  sm_out = argv[1];
4001
4010
 
4002
4011
  if (RTEST(sm_out)) {
4003
- SM_RAISE_IF_NOT_TYPE(sm_out, vec3);
4012
+ if (!SM_IS_A(sm_out, vec3) && !SM_IS_A(sm_out, vec4) && !SM_IS_A(sm_out, quat)) {
4013
+ rb_raise(rb_eTypeError,
4014
+ kSM_WANT_THREE_OR_FOUR_FORMAT_LIT,
4015
+ rb_obj_classname(sm_out));
4016
+ return Qnil;
4017
+ }
4004
4018
  } else {
4005
4019
  goto SM_LABEL(no_output);
4006
4020
  }
@@ -4034,7 +4048,7 @@ static VALUE sm_mat4_get_row3(int argc, VALUE *argv, VALUE sm_self)
4034
4048
  * Returns a Vec4 whose components are that of the row at the given index.
4035
4049
  *
4036
4050
  * call-seq:
4037
- * get_row4(index) -> new vec4
4051
+ * get_row4(index, output = nil) -> output or new vec4
4038
4052
  */
4039
4053
  static VALUE sm_mat4_get_row4(int argc, VALUE *argv, VALUE sm_self)
4040
4054
  {
@@ -4058,7 +4072,12 @@ static VALUE sm_mat4_get_row4(int argc, VALUE *argv, VALUE sm_self)
4058
4072
  sm_out = argv[1];
4059
4073
 
4060
4074
  if (RTEST(sm_out)) {
4061
- SM_RAISE_IF_NOT_TYPE(sm_out, vec4);
4075
+ if (!SM_IS_A(sm_out, vec4) && !SM_IS_A(sm_out, quat)) {
4076
+ rb_raise(rb_eTypeError,
4077
+ kSM_WANT_FOUR_FORMAT_LIT,
4078
+ rb_obj_classname(sm_out));
4079
+ return Qnil;
4080
+ }
4062
4081
  } else {
4063
4082
  goto SM_LABEL(no_output);
4064
4083
  }
@@ -4092,7 +4111,7 @@ static VALUE sm_mat4_get_row4(int argc, VALUE *argv, VALUE sm_self)
4092
4111
  * Returns a Vec3 whose components are that of the column at the given index.
4093
4112
  *
4094
4113
  * call-seq:
4095
- * get_column3(index) -> new vec3
4114
+ * get_column3(index, output = nil) -> output or new vec3
4096
4115
  */
4097
4116
  static VALUE sm_mat4_get_column3(int argc, VALUE *argv, VALUE sm_self)
4098
4117
  {
@@ -4116,7 +4135,12 @@ static VALUE sm_mat4_get_column3(int argc, VALUE *argv, VALUE sm_self)
4116
4135
  sm_out = argv[1];
4117
4136
 
4118
4137
  if (RTEST(sm_out)) {
4119
- SM_RAISE_IF_NOT_TYPE(sm_out, vec3);
4138
+ if (!SM_IS_A(sm_out, vec3) && !SM_IS_A(sm_out, vec4) && !SM_IS_A(sm_out, quat)) {
4139
+ rb_raise(rb_eTypeError,
4140
+ kSM_WANT_THREE_OR_FOUR_FORMAT_LIT,
4141
+ rb_obj_classname(sm_out));
4142
+ return Qnil;
4143
+ }
4120
4144
  } else {
4121
4145
  goto SM_LABEL(no_output);
4122
4146
  }
@@ -4150,7 +4174,7 @@ static VALUE sm_mat4_get_column3(int argc, VALUE *argv, VALUE sm_self)
4150
4174
  * Returns a Vec4 whose components are that of the column at the given index.
4151
4175
  *
4152
4176
  * call-seq:
4153
- * get_column4(index) -> new vec4
4177
+ * get_column4(index, output = nil) -> output or new vec4
4154
4178
  */
4155
4179
  static VALUE sm_mat4_get_column4(int argc, VALUE *argv, VALUE sm_self)
4156
4180
  {
@@ -4174,7 +4198,12 @@ static VALUE sm_mat4_get_column4(int argc, VALUE *argv, VALUE sm_self)
4174
4198
  sm_out = argv[1];
4175
4199
 
4176
4200
  if (RTEST(sm_out)) {
4177
- SM_RAISE_IF_NOT_TYPE(sm_out, vec4);
4201
+ if (!SM_IS_A(sm_out, vec4) && !SM_IS_A(sm_out, quat)) {
4202
+ rb_raise(rb_eTypeError,
4203
+ kSM_WANT_FOUR_FORMAT_LIT,
4204
+ rb_obj_classname(sm_out));
4205
+ return Qnil;
4206
+ }
4178
4207
  } else {
4179
4208
  goto SM_LABEL(no_output);
4180
4209
  }
@@ -4216,7 +4245,12 @@ static VALUE sm_mat4_set_row3(VALUE sm_self, VALUE sm_index, VALUE sm_value)
4216
4245
  int index;
4217
4246
  mat4_t *self;
4218
4247
 
4219
- SM_RAISE_IF_NOT_TYPE(sm_value, vec3);
4248
+ if (!SM_IS_A(sm_value, vec3) && !SM_IS_A(sm_value, vec4) && !SM_IS_A(sm_value, quat)) {
4249
+ rb_raise(rb_eTypeError,
4250
+ kSM_WANT_THREE_OR_FOUR_FORMAT_LIT,
4251
+ rb_obj_classname(sm_value));
4252
+ return Qnil;
4253
+ }
4220
4254
 
4221
4255
  self = sm_unwrap_mat4(sm_self, NULL);
4222
4256
  value = sm_unwrap_vec3(sm_value, NULL);
@@ -4246,7 +4280,12 @@ static VALUE sm_mat4_set_column3(VALUE sm_self, VALUE sm_index, VALUE sm_value)
4246
4280
  int index;
4247
4281
  mat4_t *self;
4248
4282
 
4249
- SM_RAISE_IF_NOT_TYPE(sm_value, vec3);
4283
+ if (!SM_IS_A(sm_value, vec3) && !SM_IS_A(sm_value, vec4) && !SM_IS_A(sm_value, quat)) {
4284
+ rb_raise(rb_eTypeError,
4285
+ kSM_WANT_THREE_OR_FOUR_FORMAT_LIT,
4286
+ rb_obj_classname(sm_value));
4287
+ return Qnil;
4288
+ }
4250
4289
 
4251
4290
  self = sm_unwrap_mat4(sm_self, NULL);
4252
4291
  value = sm_unwrap_vec3(sm_value, NULL);
@@ -4276,7 +4315,12 @@ static VALUE sm_mat4_set_row4(VALUE sm_self, VALUE sm_index, VALUE sm_value)
4276
4315
  int index;
4277
4316
  mat4_t *self;
4278
4317
 
4279
- SM_RAISE_IF_NOT_TYPE(sm_value, vec4);
4318
+ if (!SM_IS_A(sm_value, vec4) && !SM_IS_A(sm_value, quat)) {
4319
+ rb_raise(rb_eTypeError,
4320
+ kSM_WANT_FOUR_FORMAT_LIT,
4321
+ rb_obj_classname(sm_value));
4322
+ return Qnil;
4323
+ }
4280
4324
 
4281
4325
  self = sm_unwrap_mat4(sm_self, NULL);
4282
4326
  value = sm_unwrap_vec4(sm_value, NULL);
@@ -4306,7 +4350,12 @@ static VALUE sm_mat4_set_column4(VALUE sm_self, VALUE sm_index, VALUE sm_value)
4306
4350
  int index;
4307
4351
  mat4_t *self;
4308
4352
 
4309
- SM_RAISE_IF_NOT_TYPE(sm_value, vec4);
4353
+ if (!SM_IS_A(sm_value, vec4) && !SM_IS_A(sm_value, quat)) {
4354
+ rb_raise(rb_eTypeError,
4355
+ kSM_WANT_FOUR_FORMAT_LIT,
4356
+ rb_obj_classname(sm_value));
4357
+ return Qnil;
4358
+ }
4310
4359
 
4311
4360
  self = sm_unwrap_mat4(sm_self, NULL);
4312
4361
  value = sm_unwrap_vec4(sm_value, NULL);
@@ -4904,13 +4953,23 @@ static VALUE sm_mat3_rotate_vec3(int argc, VALUE *argv, VALUE sm_self)
4904
4953
  vec3_t *rhs;
4905
4954
  rb_scan_args(argc, argv, "11", &sm_rhs, &sm_out);
4906
4955
  self = sm_unwrap_mat3(sm_self, NULL);
4907
- SM_RAISE_IF_NOT_TYPE(sm_rhs, vec3);
4956
+ if (!SM_IS_A(sm_rhs, vec3) && !SM_IS_A(sm_rhs, vec4) && !SM_IS_A(sm_rhs, quat)) {
4957
+ rb_raise(rb_eTypeError,
4958
+ kSM_WANT_THREE_OR_FOUR_FORMAT_LIT,
4959
+ rb_obj_classname(sm_rhs));
4960
+ return Qnil;
4961
+ }
4908
4962
  rhs = sm_unwrap_vec3(sm_rhs, NULL);
4909
4963
  if (argc == 2) {
4910
4964
  if (!RTEST(sm_out)) {
4911
4965
  goto SM_LABEL(skip_output);
4912
4966
  }{
4913
- SM_RAISE_IF_NOT_TYPE(sm_out, vec3);
4967
+ if (!SM_IS_A(sm_out, vec3) && !SM_IS_A(sm_out, vec4) && !SM_IS_A(sm_out, quat)) {
4968
+ rb_raise(rb_eTypeError,
4969
+ kSM_WANT_THREE_OR_FOUR_FORMAT_LIT,
4970
+ rb_obj_classname(sm_out));
4971
+ return Qnil;
4972
+ }
4914
4973
  vec3_t *output = sm_unwrap_vec3(sm_out, NULL);
4915
4974
  mat3_rotate_vec3(*self, *rhs, *output);
4916
4975
  }} else if (argc == 1) {
@@ -4942,13 +5001,23 @@ static VALUE sm_mat3_inv_rotate_vec3(int argc, VALUE *argv, VALUE sm_self)
4942
5001
  vec3_t *rhs;
4943
5002
  rb_scan_args(argc, argv, "11", &sm_rhs, &sm_out);
4944
5003
  self = sm_unwrap_mat3(sm_self, NULL);
4945
- SM_RAISE_IF_NOT_TYPE(sm_rhs, vec3);
5004
+ if (!SM_IS_A(sm_rhs, vec3) && !SM_IS_A(sm_rhs, vec4) && !SM_IS_A(sm_rhs, quat)) {
5005
+ rb_raise(rb_eTypeError,
5006
+ kSM_WANT_THREE_OR_FOUR_FORMAT_LIT,
5007
+ rb_obj_classname(sm_rhs));
5008
+ return Qnil;
5009
+ }
4946
5010
  rhs = sm_unwrap_vec3(sm_rhs, NULL);
4947
5011
  if (argc == 2) {
4948
5012
  if (!RTEST(sm_out)) {
4949
5013
  goto SM_LABEL(skip_output);
4950
5014
  }{
4951
- SM_RAISE_IF_NOT_TYPE(sm_out, vec3);
5015
+ if (!SM_IS_A(sm_out, vec3) && !SM_IS_A(sm_out, vec4) && !SM_IS_A(sm_out, quat)) {
5016
+ rb_raise(rb_eTypeError,
5017
+ kSM_WANT_THREE_OR_FOUR_FORMAT_LIT,
5018
+ rb_obj_classname(sm_out));
5019
+ return Qnil;
5020
+ }
4952
5021
  vec3_t *output = sm_unwrap_vec3(sm_out, NULL);
4953
5022
  mat3_inv_rotate_vec3(*self, *rhs, *output);
4954
5023
  }} else if (argc == 1) {
@@ -5196,7 +5265,12 @@ static VALUE sm_mat3_angle_axis(int argc, VALUE *argv, VALUE self)
5196
5265
  const vec3_t *axis;
5197
5266
 
5198
5267
  rb_scan_args(argc, argv, "21", &sm_angle, &sm_axis, &sm_out);
5199
- SM_RAISE_IF_NOT_TYPE(sm_axis, vec3);
5268
+ if (!SM_IS_A(sm_axis, vec3) && !SM_IS_A(sm_axis, vec4) && !SM_IS_A(sm_axis, quat)) {
5269
+ rb_raise(rb_eTypeError,
5270
+ kSM_WANT_THREE_OR_FOUR_FORMAT_LIT,
5271
+ rb_obj_classname(sm_axis));
5272
+ return Qnil;
5273
+ }
5200
5274
 
5201
5275
  angle = (s_float_t)rb_num2dbl(sm_angle);
5202
5276
  axis = sm_unwrap_vec3(sm_axis, NULL);
@@ -5220,7 +5294,7 @@ static VALUE sm_mat3_angle_axis(int argc, VALUE *argv, VALUE self)
5220
5294
  * Returns a Vec3 whose components are that of the row at the given index.
5221
5295
  *
5222
5296
  * call-seq:
5223
- * get_row3(index) -> new vec3
5297
+ * get_row3(index, output = nil) -> output or new vec3
5224
5298
  */
5225
5299
  static VALUE sm_mat3_get_row3(int argc, VALUE *argv, VALUE sm_self)
5226
5300
  {
@@ -5244,7 +5318,12 @@ static VALUE sm_mat3_get_row3(int argc, VALUE *argv, VALUE sm_self)
5244
5318
  sm_out = argv[1];
5245
5319
 
5246
5320
  if (RTEST(sm_out)) {
5247
- SM_RAISE_IF_NOT_TYPE(sm_out, vec3);
5321
+ if (!SM_IS_A(sm_out, vec3) && !SM_IS_A(sm_out, vec4) && !SM_IS_A(sm_out, quat)) {
5322
+ rb_raise(rb_eTypeError,
5323
+ kSM_WANT_THREE_OR_FOUR_FORMAT_LIT,
5324
+ rb_obj_classname(sm_out));
5325
+ return Qnil;
5326
+ }
5248
5327
  } else {
5249
5328
  goto SM_LABEL(no_output);
5250
5329
  }
@@ -5278,7 +5357,7 @@ static VALUE sm_mat3_get_row3(int argc, VALUE *argv, VALUE sm_self)
5278
5357
  * Returns a Vec3 whose components are that of the column at the given index.
5279
5358
  *
5280
5359
  * call-seq:
5281
- * get_column3(index) -> new vec3
5360
+ * get_column3(index, output = nil) -> output or new vec3
5282
5361
  */
5283
5362
  static VALUE sm_mat3_get_column3(int argc, VALUE *argv, VALUE sm_self)
5284
5363
  {
@@ -5302,7 +5381,12 @@ static VALUE sm_mat3_get_column3(int argc, VALUE *argv, VALUE sm_self)
5302
5381
  sm_out = argv[1];
5303
5382
 
5304
5383
  if (RTEST(sm_out)) {
5305
- SM_RAISE_IF_NOT_TYPE(sm_out, vec3);
5384
+ if (!SM_IS_A(sm_out, vec3) && !SM_IS_A(sm_out, vec4) && !SM_IS_A(sm_out, quat)) {
5385
+ rb_raise(rb_eTypeError,
5386
+ kSM_WANT_THREE_OR_FOUR_FORMAT_LIT,
5387
+ rb_obj_classname(sm_out));
5388
+ return Qnil;
5389
+ }
5306
5390
  } else {
5307
5391
  goto SM_LABEL(no_output);
5308
5392
  }
@@ -5344,7 +5428,12 @@ static VALUE sm_mat3_set_row3(VALUE sm_self, VALUE sm_index, VALUE sm_value)
5344
5428
  int index;
5345
5429
  mat3_t *self;
5346
5430
 
5347
- SM_RAISE_IF_NOT_TYPE(sm_value, vec3);
5431
+ if (!SM_IS_A(sm_value, vec3) && !SM_IS_A(sm_value, vec4) && !SM_IS_A(sm_value, quat)) {
5432
+ rb_raise(rb_eTypeError,
5433
+ kSM_WANT_THREE_OR_FOUR_FORMAT_LIT,
5434
+ rb_obj_classname(sm_value));
5435
+ return Qnil;
5436
+ }
5348
5437
 
5349
5438
  self = sm_unwrap_mat3(sm_self, NULL);
5350
5439
  value = sm_unwrap_vec3(sm_value, NULL);
@@ -5374,7 +5463,12 @@ static VALUE sm_mat3_set_column3(VALUE sm_self, VALUE sm_index, VALUE sm_value)
5374
5463
  int index;
5375
5464
  mat3_t *self;
5376
5465
 
5377
- SM_RAISE_IF_NOT_TYPE(sm_value, vec3);
5466
+ if (!SM_IS_A(sm_value, vec3) && !SM_IS_A(sm_value, vec4) && !SM_IS_A(sm_value, quat)) {
5467
+ rb_raise(rb_eTypeError,
5468
+ kSM_WANT_THREE_OR_FOUR_FORMAT_LIT,
5469
+ rb_obj_classname(sm_value));
5470
+ return Qnil;
5471
+ }
5378
5472
 
5379
5473
  self = sm_unwrap_mat3(sm_self, NULL);
5380
5474
  value = sm_unwrap_vec3(sm_value, NULL);
@@ -5478,9 +5572,20 @@ static VALUE sm_get_address(VALUE sm_self)
5478
5572
 
5479
5573
  void Init_bindings()
5480
5574
  {
5575
+ ID kRB_CONST_SIZE, kRB_CONST_LENGTH, kRB_CONST_FLOAT_SIZE, kRB_CONST_TYPE;
5576
+
5481
5577
  kRB_IVAR_MATHARRAY_LENGTH = rb_intern("__length");
5482
5578
  kRB_IVAR_MATHARRAY_CACHE = rb_intern("__cache");
5483
5579
  kRB_IVAR_MATHARRAY_SOURCE = rb_intern("__source");
5580
+ kRB_CONST_SIZE = rb_intern("SIZE");
5581
+ kRB_CONST_LENGTH = rb_intern("LENGTH");
5582
+ kRB_CONST_FLOAT_SIZE = rb_intern("SNOW_MATH_FLOAT_SIZE");
5583
+ kRB_CONST_TYPE = rb_intern("TYPE");
5584
+
5585
+ /*
5586
+ * The size in bytes of the base snow-math floating point type. Set to 4 when
5587
+ * using float or 8 when using double.
5588
+ */
5484
5589
 
5485
5590
  s_sm_snowmath_mod = rb_define_module("Snow");
5486
5591
  s_sm_vec3_klass = rb_define_class_under(s_sm_snowmath_mod, "Vec3", rb_cObject);
@@ -5489,6 +5594,18 @@ void Init_bindings()
5489
5594
  s_sm_mat3_klass = rb_define_class_under(s_sm_snowmath_mod, "Mat3", rb_cObject);
5490
5595
  s_sm_mat4_klass = rb_define_class_under(s_sm_snowmath_mod, "Mat4", rb_cObject);
5491
5596
 
5597
+ rb_const_set(s_sm_snowmath_mod, kRB_CONST_FLOAT_SIZE, INT2FIX(sizeof(s_float_t)));
5598
+ rb_const_set(s_sm_vec3_klass, kRB_CONST_SIZE, INT2FIX(sizeof(vec3_t)));
5599
+ rb_const_set(s_sm_vec4_klass, kRB_CONST_SIZE, INT2FIX(sizeof(vec4_t)));
5600
+ rb_const_set(s_sm_quat_klass, kRB_CONST_SIZE, INT2FIX(sizeof(quat_t)));
5601
+ rb_const_set(s_sm_mat3_klass, kRB_CONST_SIZE, INT2FIX(sizeof(mat3_t)));
5602
+ rb_const_set(s_sm_mat4_klass, kRB_CONST_SIZE, INT2FIX(sizeof(mat4_t)));
5603
+ rb_const_set(s_sm_vec3_klass, kRB_CONST_LENGTH, INT2FIX(sizeof(vec3_t) / sizeof(s_float_t)));
5604
+ rb_const_set(s_sm_vec4_klass, kRB_CONST_LENGTH, INT2FIX(sizeof(vec4_t) / sizeof(s_float_t)));
5605
+ rb_const_set(s_sm_quat_klass, kRB_CONST_LENGTH, INT2FIX(sizeof(quat_t) / sizeof(s_float_t)));
5606
+ rb_const_set(s_sm_mat3_klass, kRB_CONST_LENGTH, INT2FIX(sizeof(mat3_t) / sizeof(s_float_t)));
5607
+ rb_const_set(s_sm_mat4_klass, kRB_CONST_LENGTH, INT2FIX(sizeof(mat4_t) / sizeof(s_float_t)));
5608
+
5492
5609
  rb_define_singleton_method(s_sm_vec3_klass, "new", sm_vec3_new, -1);
5493
5610
  rb_define_method(s_sm_vec3_klass, "initialize", sm_vec3_init, -1);
5494
5611
  rb_define_method(s_sm_vec3_klass, "set", sm_vec3_init, -1);
@@ -5551,18 +5668,18 @@ void Init_bindings()
5551
5668
  rb_define_method(s_sm_quat_klass, "length", sm_quat_length, 0);
5552
5669
  rb_define_method(s_sm_quat_klass, "to_s", sm_quat_to_s, 0);
5553
5670
  rb_define_method(s_sm_quat_klass, "address", sm_get_address, 0);
5554
- rb_define_method(s_sm_quat_klass, "copy", sm_quat_copy, -1);
5555
5671
  rb_define_method(s_sm_quat_klass, "inverse", sm_quat_inverse, -1);
5556
- rb_define_method(s_sm_quat_klass, "negate", sm_quat_negate, -1);
5557
5672
  rb_define_method(s_sm_quat_klass, "multiply_quat", sm_quat_multiply, -1);
5558
5673
  rb_define_method(s_sm_quat_klass, "multiply_vec3", sm_quat_multiply_vec3, -1);
5559
- rb_define_method(s_sm_quat_klass, "normalize", sm_quat_normalize, -1);
5560
- rb_define_method(s_sm_quat_klass, "scale", sm_quat_scale, -1);
5561
- rb_define_method(s_sm_quat_klass, "divide", sm_quat_divide, -1);
5562
- rb_define_method(s_sm_quat_klass, "add", sm_quat_add, -1);
5563
- rb_define_method(s_sm_quat_klass, "subtract", sm_quat_subtract, -1);
5564
5674
  rb_define_method(s_sm_quat_klass, "slerp", sm_quat_slerp, -1);
5565
5675
  // Borrow some functions from vec4
5676
+ rb_define_method(s_sm_quat_klass, "copy", sm_vec4_copy, -1);
5677
+ rb_define_method(s_sm_quat_klass, "negate", sm_vec4_negate, -1);
5678
+ rb_define_method(s_sm_quat_klass, "normalize", sm_vec4_normalize, -1);
5679
+ rb_define_method(s_sm_quat_klass, "scale", sm_vec4_scale, -1);
5680
+ rb_define_method(s_sm_quat_klass, "divide", sm_vec4_divide, -1);
5681
+ rb_define_method(s_sm_quat_klass, "add", sm_vec4_add, -1);
5682
+ rb_define_method(s_sm_quat_klass, "subtract", sm_vec4_subtract, -1);
5566
5683
  rb_define_method(s_sm_quat_klass, "dot_product", sm_vec4_dot_product, 1);
5567
5684
  rb_define_method(s_sm_quat_klass, "magnitude_squared", sm_vec4_magnitude_squared, 0);
5568
5685
  rb_define_method(s_sm_quat_klass, "magnitude", sm_vec4_magnitude, 0);
@@ -5641,6 +5758,7 @@ void Init_bindings()
5641
5758
  #if BUILD_ARRAY_TYPE
5642
5759
 
5643
5760
  s_sm_vec3_array_klass = rb_define_class_under(s_sm_snowmath_mod, "Vec3Array", rb_cObject);
5761
+ rb_const_set(s_sm_vec3_array_klass, kRB_CONST_TYPE, s_sm_vec3_klass);
5644
5762
  rb_define_singleton_method(s_sm_vec3_array_klass, "new", sm_vec3_array_new, 1);
5645
5763
  rb_define_method(s_sm_vec3_array_klass, "fetch", sm_vec3_array_fetch, 1);
5646
5764
  rb_define_method(s_sm_vec3_array_klass, "store", sm_vec3_array_store, 2);
@@ -5650,6 +5768,7 @@ void Init_bindings()
5650
5768
  rb_define_method(s_sm_vec3_array_klass, "address", sm_get_address, 0);
5651
5769
 
5652
5770
  s_sm_vec4_array_klass = rb_define_class_under(s_sm_snowmath_mod, "Vec4Array", rb_cObject);
5771
+ rb_const_set(s_sm_vec4_array_klass, kRB_CONST_TYPE, s_sm_vec4_klass);
5653
5772
  rb_define_singleton_method(s_sm_vec4_array_klass, "new", sm_vec4_array_new, 1);
5654
5773
  rb_define_method(s_sm_vec4_array_klass, "fetch", sm_vec4_array_fetch, 1);
5655
5774
  rb_define_method(s_sm_vec4_array_klass, "store", sm_vec4_array_store, 2);
@@ -5659,6 +5778,7 @@ void Init_bindings()
5659
5778
  rb_define_method(s_sm_vec4_array_klass, "address", sm_get_address, 0);
5660
5779
 
5661
5780
  s_sm_quat_array_klass = rb_define_class_under(s_sm_snowmath_mod, "QuatArray", rb_cObject);
5781
+ rb_const_set(s_sm_quat_array_klass, kRB_CONST_TYPE, s_sm_quat_klass);
5662
5782
  rb_define_singleton_method(s_sm_quat_array_klass, "new", sm_quat_array_new, 1);
5663
5783
  rb_define_method(s_sm_quat_array_klass, "fetch", sm_quat_array_fetch, 1);
5664
5784
  rb_define_method(s_sm_quat_array_klass, "store", sm_quat_array_store, 2);
@@ -5668,6 +5788,7 @@ void Init_bindings()
5668
5788
  rb_define_method(s_sm_quat_array_klass, "address", sm_get_address, 0);
5669
5789
 
5670
5790
  s_sm_mat3_array_klass = rb_define_class_under(s_sm_snowmath_mod, "Mat3Array", rb_cObject);
5791
+ rb_const_set(s_sm_mat3_array_klass, kRB_CONST_TYPE, s_sm_mat3_klass);
5671
5792
  rb_define_singleton_method(s_sm_mat3_array_klass, "new", sm_mat3_array_new, 1);
5672
5793
  rb_define_method(s_sm_mat3_array_klass, "fetch", sm_mat3_array_fetch, 1);
5673
5794
  rb_define_method(s_sm_mat3_array_klass, "store", sm_mat3_array_store, 2);
@@ -5677,6 +5798,7 @@ void Init_bindings()
5677
5798
  rb_define_method(s_sm_mat3_array_klass, "address", sm_get_address, 0);
5678
5799
 
5679
5800
  s_sm_mat4_array_klass = rb_define_class_under(s_sm_snowmath_mod, "Mat4Array", rb_cObject);
5801
+ rb_const_set(s_sm_mat4_array_klass, kRB_CONST_TYPE, s_sm_mat4_klass);
5680
5802
  rb_define_singleton_method(s_sm_mat4_array_klass, "new", sm_mat4_array_new, 1);
5681
5803
  rb_define_method(s_sm_mat4_array_klass, "fetch", sm_mat4_array_fetch, 1);
5682
5804
  rb_define_method(s_sm_mat4_array_klass, "store", sm_mat4_array_store, 2);