Class: Snow::Vec3

Inherits:
Object
  • Object
show all
Includes:
ArraySupport, BaseMarshalSupport, FiddlePointerSupport, InspectSupport, SwizzleSupport
Defined in:
lib/snow-math/vec3.rb,
lib/snow-math/ptr.rb,
lib/snow-math/to_a.rb,
lib/snow-math/inspect.rb,
lib/snow-math/marshal.rb,
lib/snow-math/swizzle.rb,
ext/snow-math/snow-math.c

Overview

A 3-component vector class.

Constant Summary collapse

@@SWIZZLE_CHARS =
/^[xyz]{3,4}$/
@@SWIZZLE_MAPPING =
{ 3 => self, 4 => ::Snow::Vec4, 'x' => 0, 'y' => 1, 'z' => 2 }

Class Method Summary collapse

Instance Method Summary collapse

Methods included from SwizzleSupport

#__under_method_missing__, #method_missing

Methods included from BaseMarshalSupport

#_dump, included

Methods included from InspectSupport

#inspect

Methods included from ArraySupport

#each, #map, #map!, #to_a

Methods included from FiddlePointerSupport

#to_ptr

Constructor Details

#initialize(*args) ⇒ Object

Sets the Vec3’s components.

call-seq:

set(x, y, z)   -> vec3 with components [x, y, z]
set([x, y, z]) -> vec3 with components [x, y, z]
set(vec3)      -> copy of vec3
set(vec4)      -> vec3 of vec4's x, y, and z components
set(quat)      -> vec3 of quat's x, y, and z components


1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
# File 'ext/snow-math/snow-math.c', line 1695

static VALUE sm_vec3_init(int argc, VALUE *argv, VALUE sm_self)
{
  vec3_t *self = sm_unwrap_vec3(sm_self, NULL);
  size_t arr_index = 0;

  switch(argc) {

  // Default value
  case 0: { break; }

  // Copy or by-array
  case 1: {
    if (SM_IS_A(argv[0], vec3) ||
        SM_IS_A(argv[0], vec4) ||
        SM_IS_A(argv[0], quat)) {
      sm_unwrap_vec3(argv[0], *self);
      break;
    }

    // Optional offset into array provided
    if (0) {
      case 2:
      arr_index = NUM2SIZET(argv[1]);
    }

    // Array of values
    if (SM_RB_IS_A(argv[0], rb_cArray)) {
      VALUE arrdata = argv[0];
      const size_t arr_end = arr_index + 3;
      s_float_t *vec_elem = *self;
      for (; arr_index < arr_end; ++arr_index, ++vec_elem) {
        *vec_elem = (s_float_t)rb_num2dbl(rb_ary_entry(arrdata, (long)arr_index));
      }
      break;
    }

    rb_raise(rb_eArgError, "Expected either an array of Numerics or a Vec3");
    break;
  }

  // X, Y, Z
  case 3: {
    self[0][0] = (s_float_t)rb_num2dbl(argv[0]);
    self[0][1] = (s_float_t)rb_num2dbl(argv[1]);
    self[0][2] = (s_float_t)rb_num2dbl(argv[2]);
    break;
  }

  default: {
    rb_raise(rb_eArgError, "Invalid arguments to Vec3.initialize");
    break;
  }
  } // switch (argc)

  return sm_self;
}

Dynamic Method Handling

This class handles dynamic methods through the method_missing method in the class Snow::SwizzleSupport

Class Method Details

.new(*args) ⇒ Object Also known as: []

Allocates a Vec3.

call-seq:

new()          -> vec3 with components [0, 0, 0]
new(x, y, z)   -> vec3 with components [x, y, z]
new([x, y, z]) -> vec3 with components [x, y, z]
new(vec3)      -> copy of vec3
new(vec4)      -> vec3 of vec4's x, y, and z components
new(quat)      -> vec3 of quat's x, y, and z components


1676
1677
1678
1679
1680
1681
# File 'ext/snow-math/snow-math.c', line 1676

static VALUE sm_vec3_new(int argc, VALUE *argv, VALUE self)
{
  VALUE sm_vec = sm_wrap_vec3(g_vec3_zero, self);
  rb_obj_call_init(sm_vec, argc, argv);
  return sm_vec;
}

Instance Method Details

#==(sm_other) ⇒ Object

Tests whether a Vec3 is equivalent to another Vec3, a Vec4, or a Quat. When testing for equivalency against 4-component objects, only the first three components are compared.

call-seq:

vec3 == other_vec3 -> bool
vec3 == vec4       -> bool
vec3 == quat       -> bool


1871
1872
1873
1874
1875
1876
1877
1878
# File 'ext/snow-math/snow-math.c', line 1871

static VALUE sm_vec3_equals(VALUE sm_self, VALUE sm_other)
{
  if (!RTEST(sm_other) || (!SM_IS_A(sm_other, vec3) && !SM_IS_A(sm_other, vec4) && !SM_IS_A(sm_other, quat))) {
    return Qfalse;
  }

  return vec3_equals(*sm_unwrap_vec3(sm_self, NULL), *sm_unwrap_vec3(sm_other, NULL)) ? Qtrue : Qfalse;
}

#add(*args) ⇒ Object Also known as: +

Adds this and another vector’s components together and returns the result.

call-seq:

add(vec3, output = nil) -> output or new vec3


1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
# File 'ext/snow-math/snow-math.c', line 1549

static VALUE sm_vec3_add(int argc, VALUE *argv, VALUE sm_self)
{
  VALUE sm_rhs;
  VALUE sm_out;
  vec3_t *self;
  vec3_t *rhs;
  rb_scan_args(argc, argv, "11", &sm_rhs, &sm_out);
  self = sm_unwrap_vec3(sm_self, NULL);
  if (!SM_IS_A(sm_rhs, vec3) && !SM_IS_A(sm_rhs, vec4) && !SM_IS_A(sm_rhs, quat)) {
    rb_raise(rb_eTypeError,
      kSM_WANT_THREE_OR_FOUR_FORMAT_LIT,
      rb_obj_classname(sm_rhs));
    return Qnil;
  }
  rhs = sm_unwrap_vec3(sm_rhs, NULL);
  if (argc == 2) {
    if (!RTEST(sm_out)) {
      goto SM_LABEL(skip_output);
    }{
    if (!SM_IS_A(sm_out, vec3) && !SM_IS_A(sm_out, vec4) && !SM_IS_A(sm_out, quat)) {
      rb_raise(rb_eTypeError,
        kSM_WANT_THREE_OR_FOUR_FORMAT_LIT,
        rb_obj_classname(sm_out));
      return Qnil;
    }
    vec3_t *output = sm_unwrap_vec3(sm_out, NULL);
    vec3_add(*self, *rhs, *output);
  }} else if (argc == 1) {
SM_LABEL(skip_output): {
    vec3_t output;
    vec3_add(*self, *rhs, output);
    sm_out = sm_wrap_vec3(output, rb_obj_class(sm_self));
    rb_obj_call_init(sm_out, 0, 0);
  }} else {
    rb_raise(rb_eArgError, "Invalid number of arguments to vec3");
  }
  return sm_out;
}

#add!(rhs) ⇒ Object

Calls #add(rhs, self)

call-seq: add!(rhs) -> self



139
140
141
# File 'lib/snow-math/vec3.rb', line 139

def add!(rhs)
  add rhs, self
end

#addressObject

Returns the memory address of the object.

call-seq: address -> fixnum



5564
5565
5566
5567
5568
5569
# File 'ext/snow-math/snow-math.c', line 5564

static VALUE sm_get_address(VALUE sm_self)
{
  void *data_ptr = NULL;
  Data_Get_Struct(sm_self, void, data_ptr);
  return ULL2NUM((unsigned long long)data_ptr);
}

#copy(*args) ⇒ Object Also known as: dup, clone

Returns a copy of self.

call-seq:

copy(output = nil) -> output or new vec3


1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
# File 'ext/snow-math/snow-math.c', line 1206

static VALUE sm_vec3_copy(int argc, VALUE *argv, VALUE sm_self)
{
  VALUE sm_out;
  vec3_t *self;
  rb_scan_args(argc, argv, "01", &sm_out);
  self = sm_unwrap_vec3(sm_self, NULL);
  if (argc == 1) {
    if (!RTEST(sm_out)) {
      goto SM_LABEL(skip_output);
    }{
    if (!SM_IS_A(sm_out, vec3) && !SM_IS_A(sm_out, vec4) && !SM_IS_A(sm_out, quat)) {
      rb_raise(rb_eTypeError,
        kSM_WANT_THREE_OR_FOUR_FORMAT_LIT,
        rb_obj_classname(sm_out));
      return Qnil;
    }
    vec3_t *output = sm_unwrap_vec3(sm_out, NULL);
    vec3_copy (*self, *output);
  }} else if (argc == 0) {
SM_LABEL(skip_output): {
    vec3_t output;
    vec3_copy (*self, output);
    sm_out = sm_wrap_vec3(output, rb_obj_class(sm_self));
    rb_obj_call_init(sm_out, 0, 0);
  }} else {
    rb_raise(rb_eArgError, "Invalid number of arguments to copy");
  }
  return sm_out;
}

#cross_product(*args) ⇒ Object Also known as: ^

Returns the cross product of this vector and another Vec3.

call-seq:

cross_product(vec3, output = nil) -> output or new vec3


1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
# File 'ext/snow-math/snow-math.c', line 1454

static VALUE sm_vec3_cross_product(int argc, VALUE *argv, VALUE sm_self)
{
  VALUE sm_rhs;
  VALUE sm_out;
  vec3_t *self;
  vec3_t *rhs;
  rb_scan_args(argc, argv, "11", &sm_rhs, &sm_out);
  self = sm_unwrap_vec3(sm_self, NULL);
  if (!SM_IS_A(sm_rhs, vec3) && !SM_IS_A(sm_rhs, vec4) && !SM_IS_A(sm_rhs, quat)) {
    rb_raise(rb_eTypeError,
      kSM_WANT_THREE_OR_FOUR_FORMAT_LIT,
      rb_obj_classname(sm_rhs));
    return Qnil;
  }
  rhs = sm_unwrap_vec3(sm_rhs, NULL);
  if (argc == 2) {
    if (!RTEST(sm_out)) {
      goto SM_LABEL(skip_output);
    }{
    if (!SM_IS_A(sm_out, vec3) && !SM_IS_A(sm_out, vec4) && !SM_IS_A(sm_out, quat)) {
      rb_raise(rb_eTypeError,
        kSM_WANT_THREE_OR_FOUR_FORMAT_LIT,
        rb_obj_classname(sm_out));
      return Qnil;
    }
    vec3_t *output = sm_unwrap_vec3(sm_out, NULL);
    vec3_cross_product(*self, *rhs, *output);
  }} else if (argc == 1) {
SM_LABEL(skip_output): {
    vec3_t output;
    vec3_cross_product(*self, *rhs, output);
    sm_out = sm_wrap_vec3(output, rb_obj_class(sm_self));
    rb_obj_call_init(sm_out, 0, 0);
  }} else {
    rb_raise(rb_eArgError, "Invalid number of arguments to vec3");
  }
  return sm_out;
}

#cross_product!(rhs) ⇒ Object

Calls #cross_product(rhs, self)

call-seq: cross_product!(rhs) -> self



105
106
107
# File 'lib/snow-math/vec3.rb', line 105

def cross_product!(rhs)
  cross_product rhs, self
end

#divide(*args) ⇒ Object Also known as: /

Divides this vector’s components by a scalar value and returns the result.

call-seq:

divide(scalar, output = nil) -> output or new vec3


1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
# File 'ext/snow-math/snow-math.c', line 1837

static VALUE sm_vec3_divide(int argc, VALUE *argv, VALUE sm_self)
{
  VALUE sm_out;
  VALUE sm_scalar;
  s_float_t scalar;
  vec3_t *self = sm_unwrap_vec3(sm_self, NULL);

  rb_scan_args(argc, argv, "11", &sm_scalar, &sm_out);
  scalar = rb_num2dbl(sm_scalar);

  if (SM_IS_A(sm_out, vec3)) {
    vec3_divide(*self, scalar, *sm_unwrap_vec3(sm_out, NULL));
  } else {
    vec3_t out;
    vec3_divide(*self, scalar, out);
    sm_out = sm_wrap_vec3(out, rb_obj_class(sm_self));
    rb_obj_call_init(sm_out, 0, 0);
  }

  return sm_out;
}

#divide!(rhs) ⇒ Object

Calls #divide(rhs, self)

call-seq: divide!(rhs) -> self



160
161
162
# File 'lib/snow-math/vec3.rb', line 160

def divide!(rhs)
  divide rhs, self
end

#dot_product(sm_other) ⇒ Object Also known as: **

Returns the dot product of this and another Vec3 or the XYZ components of a Vec4 or Quat.

call-seq:

dot_product(vec3) -> float
dot_product(vec4) -> float
dot_product(quat) -> float


1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
# File 'ext/snow-math/snow-math.c', line 1647

static VALUE sm_vec3_dot_product(VALUE sm_self, VALUE sm_other)
{
  if (!SM_IS_A(sm_other, vec3) &&
      !SM_IS_A(sm_other, vec4) &&
      !SM_IS_A(sm_other, quat)) {
    rb_raise(rb_eArgError,
      "Expected a Quat, Vec3, or Vec4, got %s",
      rb_obj_classname(sm_other));
    return Qnil;
  }
  return rb_float_new(
    vec3_dot_product(
      *sm_unwrap_vec3(sm_self, NULL),
      *sm_unwrap_vec3(sm_other, NULL)));
}

#fetchObject Also known as: []

Gets the component of the Vec3 at the given index.

call-seq: fetch(index) -> float



1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
# File 'ext/snow-math/snow-math.c', line 1140

static VALUE sm_vec3_fetch (VALUE sm_self, VALUE sm_index)
{
  static const int max_index = sizeof(vec3_t) / sizeof(s_float_t);
  const vec3_t *self = sm_unwrap_vec3(sm_self, NULL);
  int index = NUM2INT(sm_index);
  if (index < 0 || index >= max_index) {
    rb_raise(rb_eRangeError,
      "Index %d is out of bounds, must be from 0 through %d", index, max_index - 1);
  }
  return rb_float_new(self[0][NUM2INT(sm_index)]);
}

#inverse(*args) ⇒ Object Also known as: ~

Returns a vector whose components are the multiplicative inverse of this vector’s.

call-seq:

inverse(output = nil) -> output or new vec3


1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
# File 'ext/snow-math/snow-math.c', line 1284

static VALUE sm_vec3_inverse(int argc, VALUE *argv, VALUE sm_self)
{
  VALUE sm_out;
  vec3_t *self;
  rb_scan_args(argc, argv, "01", &sm_out);
  self = sm_unwrap_vec3(sm_self, NULL);
  if (argc == 1) {
    if (!RTEST(sm_out)) {
      goto SM_LABEL(skip_output);
    }{
    if (!SM_IS_A(sm_out, vec3) && !SM_IS_A(sm_out, vec4) && !SM_IS_A(sm_out, quat)) {
      rb_raise(rb_eTypeError,
        kSM_WANT_THREE_OR_FOUR_FORMAT_LIT,
        rb_obj_classname(sm_out));
      return Qnil;
    }
    vec3_t *output = sm_unwrap_vec3(sm_out, NULL);
    vec3_inverse (*self, *output);
  }} else if (argc == 0) {
SM_LABEL(skip_output): {
    vec3_t output;
    vec3_inverse (*self, output);
    sm_out = sm_wrap_vec3(output, rb_obj_class(sm_self));
    rb_obj_call_init(sm_out, 0, 0);
  }} else {
    rb_raise(rb_eArgError, "Invalid number of arguments to inverse");
  }
  return sm_out;
}

#inverse!Object

Calls #inverse(self)

call-seq: inverse! -> self



91
92
93
# File 'lib/snow-math/vec3.rb', line 91

def inverse!
  inverse self
end

#lengthObject

Returns the length of the Vec3 in components. Result is always 3.

call-seq: length -> fixnum



1193
1194
1195
1196
# File 'ext/snow-math/snow-math.c', line 1193

static VALUE sm_vec3_length (VALUE self)
{
  return SIZET2NUM(sizeof(vec3_t) / sizeof(s_float_t));
}

#magnitudeObject

Returns the magnitude of self.

call-seq:

magnitude -> float


1794
1795
1796
1797
# File 'ext/snow-math/snow-math.c', line 1794

static VALUE sm_vec3_magnitude(VALUE sm_self)
{
  return rb_float_new(vec3_length(*sm_unwrap_vec3(sm_self, NULL)));
}

#magnitude_squaredObject

Returns the squared magnitude of self.

call-seq:

magnitude_squared -> float


1781
1782
1783
1784
# File 'ext/snow-math/snow-math.c', line 1781

static VALUE sm_vec3_magnitude_squared(VALUE sm_self)
{
  return rb_float_new(vec3_length_squared(*sm_unwrap_vec3(sm_self, NULL)));
}

#multiply(rhs, output = nil) ⇒ Object Also known as: *

Calls #multiply_vec3 and #scale, respectively.

call-seq:

multiply(vec3, output) -> output or new vec3
multiply(scalar, output) -> output or new vec3


121
122
123
124
125
126
127
# File 'lib/snow-math/vec3.rb', line 121

def multiply(rhs, output = nil)
  case rhs
  when ::Snow::Vec3 then multiply_vec3(rhs, output)
  when Numeric then scale(rhs, output)
  else raise TypeError, "Invalid type for RHS"
  end
end

#multiply!(rhs) ⇒ Object

Calls #multiply(rhs, self)

call-seq: multiply!(rhs) -> self



132
133
134
# File 'lib/snow-math/vec3.rb', line 132

def multiply!(rhs)
  multiply rhs, self
end

#multiply_vec3(*args) ⇒ Object

Multiplies this and another vector’s components together and returns the result.

call-seq:

multiply(vec3, output = nil) -> output or new vec3


1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
# File 'ext/snow-math/snow-math.c', line 1502

static VALUE sm_vec3_multiply(int argc, VALUE *argv, VALUE sm_self)
{
  VALUE sm_rhs;
  VALUE sm_out;
  vec3_t *self;
  vec3_t *rhs;
  rb_scan_args(argc, argv, "11", &sm_rhs, &sm_out);
  self = sm_unwrap_vec3(sm_self, NULL);
  if (!SM_IS_A(sm_rhs, vec3) && !SM_IS_A(sm_rhs, vec4) && !SM_IS_A(sm_rhs, quat)) {
    rb_raise(rb_eTypeError,
      kSM_WANT_THREE_OR_FOUR_FORMAT_LIT,
      rb_obj_classname(sm_rhs));
    return Qnil;
  }
  rhs = sm_unwrap_vec3(sm_rhs, NULL);
  if (argc == 2) {
    if (!RTEST(sm_out)) {
      goto SM_LABEL(skip_output);
    }{
    if (!SM_IS_A(sm_out, vec3) && !SM_IS_A(sm_out, vec4) && !SM_IS_A(sm_out, quat)) {
      rb_raise(rb_eTypeError,
        kSM_WANT_THREE_OR_FOUR_FORMAT_LIT,
        rb_obj_classname(sm_out));
      return Qnil;
    }
    vec3_t *output = sm_unwrap_vec3(sm_out, NULL);
    vec3_multiply(*self, *rhs, *output);
  }} else if (argc == 1) {
SM_LABEL(skip_output): {
    vec3_t output;
    vec3_multiply(*self, *rhs, output);
    sm_out = sm_wrap_vec3(output, rb_obj_class(sm_self));
    rb_obj_call_init(sm_out, 0, 0);
  }} else {
    rb_raise(rb_eArgError, "Invalid number of arguments to vec3");
  }
  return sm_out;
}

#multiply_vec3!(rhs) ⇒ Object

Calls #multiply_vec3(rhs, self)

call-seq: multiply_vec3!(rhs) -> self



112
113
114
# File 'lib/snow-math/vec3.rb', line 112

def multiply_vec3!(rhs)
  multiply_vec3 rhs, self
end

#negate(*args) ⇒ Object Also known as: -@

Negates this vector’s components and returns the result.

call-seq:

negate(output = nil) -> output or new vec3


1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
# File 'ext/snow-math/snow-math.c', line 1322

static VALUE sm_vec3_negate(int argc, VALUE *argv, VALUE sm_self)
{
  VALUE sm_out;
  vec3_t *self;
  rb_scan_args(argc, argv, "01", &sm_out);
  self = sm_unwrap_vec3(sm_self, NULL);
  if (argc == 1) {
    if (!RTEST(sm_out)) {
      goto SM_LABEL(skip_output);
    }{
    if (!SM_IS_A(sm_out, vec3) && !SM_IS_A(sm_out, vec4) && !SM_IS_A(sm_out, quat)) {
      rb_raise(rb_eTypeError,
        kSM_WANT_THREE_OR_FOUR_FORMAT_LIT,
        rb_obj_classname(sm_out));
      return Qnil;
    }
    vec3_t *output = sm_unwrap_vec3(sm_out, NULL);
    vec3_negate (*self, *output);
  }} else if (argc == 0) {
SM_LABEL(skip_output): {
    vec3_t output;
    vec3_negate (*self, output);
    sm_out = sm_wrap_vec3(output, rb_obj_class(sm_self));
    rb_obj_call_init(sm_out, 0, 0);
  }} else {
    rb_raise(rb_eArgError, "Invalid number of arguments to negate");
  }
  return sm_out;
}

#negate!Object

Calls #negate(self)

call-seq: negate! -> self



98
99
100
# File 'lib/snow-math/vec3.rb', line 98

def negate!
  negate self
end

#normalize(*args) ⇒ Object

Returns a vector whose components are the multiplicative inverse of this vector’s.

call-seq:

normalize(output = nil) -> output or new vec3


1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
# File 'ext/snow-math/snow-math.c', line 1245

static VALUE sm_vec3_normalize(int argc, VALUE *argv, VALUE sm_self)
{
  VALUE sm_out;
  vec3_t *self;
  rb_scan_args(argc, argv, "01", &sm_out);
  self = sm_unwrap_vec3(sm_self, NULL);
  if (argc == 1) {
    if (!RTEST(sm_out)) {
      goto SM_LABEL(skip_output);
    }{
    if (!SM_IS_A(sm_out, vec3) && !SM_IS_A(sm_out, vec4) && !SM_IS_A(sm_out, quat)) {
      rb_raise(rb_eTypeError,
        kSM_WANT_THREE_OR_FOUR_FORMAT_LIT,
        rb_obj_classname(sm_out));
      return Qnil;
    }
    vec3_t *output = sm_unwrap_vec3(sm_out, NULL);
    vec3_normalize (*self, *output);
  }} else if (argc == 0) {
SM_LABEL(skip_output): {
    vec3_t output;
    vec3_normalize (*self, output);
    sm_out = sm_wrap_vec3(output, rb_obj_class(sm_self));
    rb_obj_call_init(sm_out, 0, 0);
  }} else {
    rb_raise(rb_eArgError, "Invalid number of arguments to normalize");
  }
  return sm_out;
}

#normalize!Object

Calls #normalize(self)

call-seq: normalize! -> self



84
85
86
# File 'lib/snow-math/vec3.rb', line 84

def normalize!
  normalize self
end

#project(*args) ⇒ Object

Projects this vector onto a normal vector and returns the result.

call-seq:

project(normal, output = nil) -> output or new vec3


1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
# File 'ext/snow-math/snow-math.c', line 1360

static VALUE sm_vec3_project(int argc, VALUE *argv, VALUE sm_self)
{
  VALUE sm_rhs;
  VALUE sm_out;
  vec3_t *self;
  vec3_t *rhs;
  rb_scan_args(argc, argv, "11", &sm_rhs, &sm_out);
  self = sm_unwrap_vec3(sm_self, NULL);
  if (!SM_IS_A(sm_rhs, vec3) && !SM_IS_A(sm_rhs, vec4) && !SM_IS_A(sm_rhs, quat)) {
    rb_raise(rb_eTypeError,
      kSM_WANT_THREE_OR_FOUR_FORMAT_LIT,
      rb_obj_classname(sm_rhs));
    return Qnil;
  }
  rhs = sm_unwrap_vec3(sm_rhs, NULL);
  if (argc == 2) {
    if (!RTEST(sm_out)) {
      goto SM_LABEL(skip_output);
    }{
    if (!SM_IS_A(sm_out, vec3) && !SM_IS_A(sm_out, vec4) && !SM_IS_A(sm_out, quat)) {
      rb_raise(rb_eTypeError,
        kSM_WANT_THREE_OR_FOUR_FORMAT_LIT,
        rb_obj_classname(sm_out));
      return Qnil;
    }
    vec3_t *output = sm_unwrap_vec3(sm_out, NULL);
    vec3_project(*self, *rhs, *output);
  }} else if (argc == 1) {
SM_LABEL(skip_output): {
    vec3_t output;
    vec3_project(*self, *rhs, output);
    sm_out = sm_wrap_vec3(output, rb_obj_class(sm_self));
    rb_obj_call_init(sm_out, 0, 0);
  }} else {
    rb_raise(rb_eArgError, "Invalid number of arguments to vec3");
  }
  return sm_out;
}

#reflect(*args) ⇒ Object

Reflects this vector against a normal vector and returns the result.

call-seq:

reflect(normal, output = nil) -> output or new vec3


1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
# File 'ext/snow-math/snow-math.c', line 1407

static VALUE sm_vec3_reflect(int argc, VALUE *argv, VALUE sm_self)
{
  VALUE sm_rhs;
  VALUE sm_out;
  vec3_t *self;
  vec3_t *rhs;
  rb_scan_args(argc, argv, "11", &sm_rhs, &sm_out);
  self = sm_unwrap_vec3(sm_self, NULL);
  if (!SM_IS_A(sm_rhs, vec3) && !SM_IS_A(sm_rhs, vec4) && !SM_IS_A(sm_rhs, quat)) {
    rb_raise(rb_eTypeError,
      kSM_WANT_THREE_OR_FOUR_FORMAT_LIT,
      rb_obj_classname(sm_rhs));
    return Qnil;
  }
  rhs = sm_unwrap_vec3(sm_rhs, NULL);
  if (argc == 2) {
    if (!RTEST(sm_out)) {
      goto SM_LABEL(skip_output);
    }{
    if (!SM_IS_A(sm_out, vec3) && !SM_IS_A(sm_out, vec4) && !SM_IS_A(sm_out, quat)) {
      rb_raise(rb_eTypeError,
        kSM_WANT_THREE_OR_FOUR_FORMAT_LIT,
        rb_obj_classname(sm_out));
      return Qnil;
    }
    vec3_t *output = sm_unwrap_vec3(sm_out, NULL);
    vec3_reflect(*self, *rhs, *output);
  }} else if (argc == 1) {
SM_LABEL(skip_output): {
    vec3_t output;
    vec3_reflect(*self, *rhs, output);
    sm_out = sm_wrap_vec3(output, rb_obj_class(sm_self));
    rb_obj_call_init(sm_out, 0, 0);
  }} else {
    rb_raise(rb_eArgError, "Invalid number of arguments to vec3");
  }
  return sm_out;
}

#scale(*args) ⇒ Object

Scales this vector’s components by a scalar value and returns the result.

call-seq:

scale(scalar, output = nil) -> output or new vec3


1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
# File 'ext/snow-math/snow-math.c', line 1807

static VALUE sm_vec3_scale(int argc, VALUE *argv, VALUE sm_self)
{
  VALUE sm_out;
  VALUE sm_scalar;
  s_float_t scalar;
  vec3_t *self = sm_unwrap_vec3(sm_self, NULL);

  rb_scan_args(argc, argv, "11", &sm_scalar, &sm_out);
  scalar = rb_num2dbl(sm_scalar);

  if (SM_IS_A(sm_out, vec3)) {
    vec3_scale(*self, scalar, *sm_unwrap_vec3(sm_out, NULL));
  } else {
    vec3_t out;
    vec3_scale(*self, scalar, out);
    sm_out = sm_wrap_vec3(out, rb_obj_class(sm_self));
    rb_obj_call_init(sm_out, 0, 0);
  }

  return sm_out;
}

#scale!(rhs) ⇒ Object

Calls #scale(rhs, self)

call-seq: scale!(rhs) -> self



153
154
155
# File 'lib/snow-math/vec3.rb', line 153

def scale!(rhs)
  scale rhs, self
end

#set(*args) ⇒ Object

Sets the Vec3’s components.

call-seq:

set(x, y, z)   -> vec3 with components [x, y, z]
set([x, y, z]) -> vec3 with components [x, y, z]
set(vec3)      -> copy of vec3
set(vec4)      -> vec3 of vec4's x, y, and z components
set(quat)      -> vec3 of quat's x, y, and z components


1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
# File 'ext/snow-math/snow-math.c', line 1695

static VALUE sm_vec3_init(int argc, VALUE *argv, VALUE sm_self)
{
  vec3_t *self = sm_unwrap_vec3(sm_self, NULL);
  size_t arr_index = 0;

  switch(argc) {

  // Default value
  case 0: { break; }

  // Copy or by-array
  case 1: {
    if (SM_IS_A(argv[0], vec3) ||
        SM_IS_A(argv[0], vec4) ||
        SM_IS_A(argv[0], quat)) {
      sm_unwrap_vec3(argv[0], *self);
      break;
    }

    // Optional offset into array provided
    if (0) {
      case 2:
      arr_index = NUM2SIZET(argv[1]);
    }

    // Array of values
    if (SM_RB_IS_A(argv[0], rb_cArray)) {
      VALUE arrdata = argv[0];
      const size_t arr_end = arr_index + 3;
      s_float_t *vec_elem = *self;
      for (; arr_index < arr_end; ++arr_index, ++vec_elem) {
        *vec_elem = (s_float_t)rb_num2dbl(rb_ary_entry(arrdata, (long)arr_index));
      }
      break;
    }

    rb_raise(rb_eArgError, "Expected either an array of Numerics or a Vec3");
    break;
  }

  // X, Y, Z
  case 3: {
    self[0][0] = (s_float_t)rb_num2dbl(argv[0]);
    self[0][1] = (s_float_t)rb_num2dbl(argv[1]);
    self[0][2] = (s_float_t)rb_num2dbl(argv[2]);
    break;
  }

  default: {
    rb_raise(rb_eArgError, "Invalid arguments to Vec3.initialize");
    break;
  }
  } // switch (argc)

  return sm_self;
}

#sizeObject

Returns the length in bytes of the Vec3. When compiled to use doubles as the base type, this is always 24. Otherwise, when compiled to use floats, it’s always 12.

call-seq: size -> fixnum



1181
1182
1183
1184
# File 'ext/snow-math/snow-math.c', line 1181

static VALUE sm_vec3_size (VALUE self)
{
  return SIZET2NUM(sizeof(vec3_t));
}

#storeObject Also known as: []=

Sets the Vec3’s component at the index to the value.

call-seq: store(index, value) -> value



1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
# File 'ext/snow-math/snow-math.c', line 1159

static VALUE sm_vec3_store (VALUE sm_self, VALUE sm_index, VALUE sm_value)
{
  static const int max_index = sizeof(vec3_t) / sizeof(s_float_t);
  vec3_t *self = sm_unwrap_vec3(sm_self, NULL);
  int index = NUM2INT(sm_index);
  if (index < 0 || index >= max_index) {
    rb_raise(rb_eRangeError,
      "Index %d is out of bounds, must be from 0 through %d", index, max_index - 1);
  }
  self[0][index] = (s_float_t)rb_num2dbl(sm_value);
  return sm_value;
}

#subtract(*args) ⇒ Object Also known as: -

Subtracts another vector’s components from this vector’s and returns the result.

call-seq:

subtract(vec3, output = nil) -> output or new vec3


1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
# File 'ext/snow-math/snow-math.c', line 1597

static VALUE sm_vec3_subtract(int argc, VALUE *argv, VALUE sm_self)
{
  VALUE sm_rhs;
  VALUE sm_out;
  vec3_t *self;
  vec3_t *rhs;
  rb_scan_args(argc, argv, "11", &sm_rhs, &sm_out);
  self = sm_unwrap_vec3(sm_self, NULL);
  if (!SM_IS_A(sm_rhs, vec3) && !SM_IS_A(sm_rhs, vec4) && !SM_IS_A(sm_rhs, quat)) {
    rb_raise(rb_eTypeError,
      kSM_WANT_THREE_OR_FOUR_FORMAT_LIT,
      rb_obj_classname(sm_rhs));
    return Qnil;
  }
  rhs = sm_unwrap_vec3(sm_rhs, NULL);
  if (argc == 2) {
    if (!RTEST(sm_out)) {
      goto SM_LABEL(skip_output);
    }{
    if (!SM_IS_A(sm_out, vec3) && !SM_IS_A(sm_out, vec4) && !SM_IS_A(sm_out, quat)) {
      rb_raise(rb_eTypeError,
        kSM_WANT_THREE_OR_FOUR_FORMAT_LIT,
        rb_obj_classname(sm_out));
      return Qnil;
    }
    vec3_t *output = sm_unwrap_vec3(sm_out, NULL);
    vec3_subtract(*self, *rhs, *output);
  }} else if (argc == 1) {
SM_LABEL(skip_output): {
    vec3_t output;
    vec3_subtract(*self, *rhs, output);
    sm_out = sm_wrap_vec3(output, rb_obj_class(sm_self));
    rb_obj_call_init(sm_out, 0, 0);
  }} else {
    rb_raise(rb_eArgError, "Invalid number of arguments to vec3");
  }
  return sm_out;
}

#subtract!(rhs) ⇒ Object

Calls #subtract(rhs, self)

call-seq: subtract!(rhs) -> self



146
147
148
# File 'lib/snow-math/vec3.rb', line 146

def subtract!(rhs)
  subtract rhs, self
end

#to_sObject

Returns a string representation of self.

Vec3[].to_s     # => "{ 0.0, 0.0, 0.0 }"

call-seq:

to_s -> string


1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
# File 'ext/snow-math/snow-math.c', line 1762

static VALUE sm_vec3_to_s(VALUE self)
{
  const s_float_t *v;
  v = (const s_float_t *)*sm_unwrap_vec3(self, NULL);
  return rb_sprintf(
    "{ "
    "%f, %f, %f"
    " }",
    v[0], v[1], v[2]);
}

#xObject

Returns the X component of the vector.

call-seq: x -> float



42
43
44
# File 'lib/snow-math/vec3.rb', line 42

def x
  self[0]
end

#x=(value) ⇒ Object

Sets the X component of the vector.

call-seq: x = value -> value



49
50
51
# File 'lib/snow-math/vec3.rb', line 49

def x=(value)
  self[0] = value
end

#yObject

Returns the Y component of the vector.

call-seq: y -> float



56
57
58
# File 'lib/snow-math/vec3.rb', line 56

def y
  self[1]
end

#y=(value) ⇒ Object

Sets the Y component of the vector.

call-seq: y = value -> value



63
64
65
# File 'lib/snow-math/vec3.rb', line 63

def y=(value)
  self[1] = value
end

#zObject

Returns the Z component of the vector.

call-seq: z -> float



70
71
72
# File 'lib/snow-math/vec3.rb', line 70

def z
  self[2]
end

#z=(value) ⇒ Object

Sets the Z component of the vector.

call-seq: z = value -> value



77
78
79
# File 'lib/snow-math/vec3.rb', line 77

def z=(value)
  self[2] = value
end