snow-math 1.3.0pre0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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);