Class: Snow::Vec4

Inherits:
Data
  • Object
show all
Includes:
ArraySupport, BaseMarshalSupport, FiddlePointerSupport, InspectSupport, SwizzleSupport
Defined in:
lib/snow-math/vec4.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 4-component vector class.

Constant Summary collapse

POS_X =
self.new(1, 0, 0, 1).freeze
POS_Y =
self.new(0, 1, 0, 1).freeze
POS_Z =
self.new(0, 0, 1, 1).freeze
NEG_X =
self.new(-1, 0, 0, 1).freeze
NEG_Y =
self.new(0, -1, 0, 1).freeze
NEG_Z =
self.new(0, 0, -1, 1).freeze
ONE =
self.new(1, 1, 1, 1).freeze
ZERO =
self.new(0, 0, 0, 0).freeze
IDENTITY =
self.new(0, 0, 0, 1).freeze
@@SWIZZLE_CHARS =
/^[xyzw]{2,4}$/
@@SWIZZLE_MAPPING =
{ 2 => ::Snow::Vec2, 3 => ::Snow::Vec3, 4 => self, 'x' => 0, 'y' => 1, 'z' => 2, 'w' => 3 }

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 Vec4’s components.

call-seq:

set(x, y, z, w = 1) -> new vec4 with components [x, y, z, w]
set([x, y, z, w])   -> new vec4 with components [x, y, z, w]
set(vec3)           -> vec4 with components [vec3.xyz, 1]
set(vec2)           -> vec4 with components [vec2.xy, 0, 1]
set(vec4)           -> copy of vec4
set(quat)           -> copy of quat as vec4


3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
# File 'ext/snow-math/snow-math.c', line 3660

static VALUE sm_vec4_init(int argc, VALUE *argv, VALUE sm_self)
{
  vec4_t *self = sm_unwrap_vec4(sm_self, NULL);
  size_t arr_index = 0;

  rb_check_frozen(sm_self);

  switch(argc) {

  /* Default value */
  case 0: { break; }

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

    if (SM_IS_A(argv[0], vec3)) {
      sm_unwrap_vec3(argv[0], *self);
      self[0][3] = s_float_lit(1.0);
      break;
    }

    if (SM_IS_A(argv[0], vec2)) {
      sm_unwrap_vec2(argv[0], *self);
      self[0][2] = s_float_lit(0.0);
      self[0][3] = s_float_lit(1.0);
      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 + 4;
      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 Vec4");
    break;
  }

  /* W */
  case 4: {
    self[0][3] = (s_float_t)rb_num2dbl(argv[3]);
    case 3: /* X, Y, Z */
    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 initialize/set");
    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 new Vec4.

call-seq:

new()               -> new vec4 with components [0, 0, 0, 1]
new(x, y, z, w = 1) -> new vec4 with components [x, y, z, w]
new([x, y, z, w])   -> new vec4 with components [x, y, z, w]
new(vec4)           -> copy of vec4
new(vec3)           -> copy of vec3 with w component of 1
new(quat)           -> copy of quat as vec4


3640
3641
3642
3643
3644
3645
# File 'ext/snow-math/snow-math.c', line 3640

static VALUE sm_vec4_new(int argc, VALUE *argv, VALUE self)
{
  VALUE sm_vec = sm_wrap_vec4(g_vec4_identity, self);
  rb_obj_call_init(sm_vec, argc, argv);
  return sm_vec;
}

Instance Method Details

#==(sm_other) ⇒ Object

Tests this Vec4 or Quat and another Vec4 or Quat for equivalency.

call-seq:

quat == other_quat -> bool
vec4 == other_vec4 -> bool
quat == vec4       -> bool
vec4 == quat       -> bool


3855
3856
3857
3858
3859
3860
3861
3862
# File 'ext/snow-math/snow-math.c', line 3855

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

  return vec4_equals(*sm_unwrap_vec4(sm_self, NULL), *sm_unwrap_vec4(sm_other, NULL)) ? Qtrue : Qfalse;
}

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

Adds this and another vector or quaternion’s components together and returns the result. The result type is that of the receiver.

call-seq:

add(vec4, output = nil) -> output or new vec4 or quat


3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
# File 'ext/snow-math/snow-math.c', line 3511

static VALUE sm_vec4_add(int argc, VALUE *argv, VALUE sm_self)
{
  VALUE sm_rhs;
  VALUE sm_out;
  vec4_t *self;
  vec4_t *rhs;
  rb_scan_args(argc, argv, "11", &sm_rhs, &sm_out);
  self = sm_unwrap_vec4(sm_self, NULL);
  if (!SM_IS_A(sm_rhs, vec4) && !SM_IS_A(sm_rhs, quat)) {
    rb_raise(rb_eTypeError,
      kSM_WANT_FOUR_FORMAT_LIT,
      rb_obj_classname(sm_rhs));
    return Qnil;
  }
  rhs = sm_unwrap_vec4(sm_rhs, NULL);
  if (argc == 2) {
    if (!RTEST(sm_out)) {
      goto SM_LABEL(skip_output);
    }{
    vec4_t *output;
    if (!SM_IS_A(sm_rhs, vec4) && !SM_IS_A(sm_rhs, quat)) {
      rb_raise(rb_eTypeError,
        kSM_WANT_FOUR_FORMAT_LIT,
        rb_obj_classname(sm_rhs));
      return Qnil;
    }
    rb_check_frozen(sm_out);
    output = sm_unwrap_vec4(sm_out, NULL);
    vec4_add(*self, *rhs, *output);
  }} else if (argc == 1) {
SM_LABEL(skip_output): {
    vec4_t output;
    vec4_add(*self, *rhs, output);
    sm_out = sm_wrap_vec4(output, rb_obj_class(sm_self));
    rb_obj_call_init(sm_out, 0, 0);
  }} else {
    rb_raise(rb_eArgError, "Invalid number of arguments to add");
  }
  return sm_out;
}

#add!(rhs) ⇒ Object

Calls #add(rhs, self)

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



171
172
173
# File 'lib/snow-math/vec4.rb', line 171

def add!(rhs)
  add rhs, self
end

#addressObject

Returns the memory address of the object.

call-seq: address -> fixnum



6894
6895
6896
6897
6898
6899
# File 'ext/snow-math/snow-math.c', line 6894

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 vec4 / quat


3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
# File 'ext/snow-math/snow-math.c', line 3201

static VALUE sm_vec4_copy(int argc, VALUE *argv, VALUE sm_self)
{
  VALUE sm_out;
  vec4_t *self;
  rb_scan_args(argc, argv, "01", &sm_out);
  self = sm_unwrap_vec4(sm_self, NULL);
  if (argc == 1) {
    if (!RTEST(sm_out)) {
      goto SM_LABEL(skip_output);
    }{
    vec4_t *output;
    if (!SM_IS_A(sm_out, vec4) && !SM_IS_A(sm_out, quat)) {
      rb_raise(rb_eTypeError,
        kSM_WANT_FOUR_FORMAT_LIT,
        rb_obj_classname(sm_out));
      return Qnil;
    }
    rb_check_frozen(sm_out);
    output = sm_unwrap_vec4(sm_out, NULL);
    vec4_copy (*self, *output);
  }} else if (argc == 0) {
SM_LABEL(skip_output): {
    vec4_t output;
    vec4_copy (*self, output);
    sm_out = sm_wrap_vec4(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;
}

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

Divides this vector or quaternion’s components by a scalar value and returns the result. The return type is that of the receiver.

call-seq:

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


3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
# File 'ext/snow-math/snow-math.c', line 3821

static VALUE sm_vec4_divide(int argc, VALUE *argv, VALUE sm_self)
{
  VALUE sm_out;
  VALUE sm_scalar;
  s_float_t scalar;
  vec4_t *self = sm_unwrap_vec4(sm_self, NULL);

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

  if ((SM_IS_A(sm_out, vec4) || SM_IS_A(sm_out, quat))) {
    rb_check_frozen(sm_out);
    vec4_divide(*self, scalar, *sm_unwrap_vec4(sm_out, NULL));
  } else {
    vec4_t out;
    vec4_divide(*self, scalar, out);
    sm_out = sm_wrap_vec4(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



192
193
194
# File 'lib/snow-math/vec4.rb', line 192

def divide!(rhs)
  divide rhs, self
end

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

Returns the dot product of self and another Vec4 or Quat.

call-seq:

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


3612
3613
3614
3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
# File 'ext/snow-math/snow-math.c', line 3612

static VALUE sm_vec4_dot_product(VALUE sm_self, VALUE sm_other)
{
  if (!SM_IS_A(sm_other, vec4) &&
      !SM_IS_A(sm_other, quat)) {
    rb_raise(rb_eArgError,
      kSM_WANT_FOUR_FORMAT_LIT,
      rb_obj_classname(sm_other));
    return Qnil;
  }
  return rb_float_new(
    vec4_dot_product(
      *sm_unwrap_vec4(sm_self, NULL),
      *sm_unwrap_vec4(sm_other, NULL)));
}

#fetchObject Also known as: []

Gets the component of the Vec4 at the given index.

call-seq: fetch(index) -> float



3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
# File 'ext/snow-math/snow-math.c', line 3134

static VALUE sm_vec4_fetch (VALUE sm_self, VALUE sm_index)
{
  static const int max_index = sizeof(vec4_t) / sizeof(s_float_t);
  const vec4_t *self = sm_unwrap_vec4(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 vec4


3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
# File 'ext/snow-math/snow-math.c', line 3282

static VALUE sm_vec4_inverse(int argc, VALUE *argv, VALUE sm_self)
{
  VALUE sm_out;
  vec4_t *self;
  rb_scan_args(argc, argv, "01", &sm_out);
  self = sm_unwrap_vec4(sm_self, NULL);
  if (argc == 1) {
    if (!RTEST(sm_out)) {
      goto SM_LABEL(skip_output);
    }{
    vec4_t *output;
    if (!SM_IS_A(sm_out, vec4) && !SM_IS_A(sm_out, quat)) {
      rb_raise(rb_eTypeError,
        kSM_WANT_FOUR_FORMAT_LIT,
        rb_obj_classname(sm_out));
      return Qnil;
    }
    rb_check_frozen(sm_out);
    output = sm_unwrap_vec4(sm_out, NULL);
    vec4_inverse (*self, *output);
  }} else if (argc == 0) {
SM_LABEL(skip_output): {
    vec4_t output;
    vec4_inverse (*self, output);
    sm_out = sm_wrap_vec4(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



130
131
132
# File 'lib/snow-math/vec4.rb', line 130

def inverse!
  inverse self
end

#lengthObject

Returns the length of the Vec4 in components. Result is always 4.

call-seq: length -> fixnum



3188
3189
3190
3191
# File 'ext/snow-math/snow-math.c', line 3188

static VALUE sm_vec4_length (VALUE self)
{
  return SIZET2NUM(sizeof(vec4_t) / sizeof(s_float_t));
}

#magnitudeObject

Returns the magnitude of self.

call-seq:

magnitude -> float


3775
3776
3777
3778
# File 'ext/snow-math/snow-math.c', line 3775

static VALUE sm_vec4_magnitude(VALUE sm_self)
{
  return rb_float_new(vec4_length(*sm_unwrap_vec4(sm_self, NULL)));
}

#magnitude_squaredObject

Returns the squared magnitude of self.

call-seq:

magnitude_squared -> float


3762
3763
3764
3765
# File 'ext/snow-math/snow-math.c', line 3762

static VALUE sm_vec4_magnitude_squared(VALUE sm_self)
{
  return rb_float_new(vec4_length_squared(*sm_unwrap_vec4(sm_self, NULL)));
}

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

Calls #multiply_vec4 and #scale, respectively.

call-seq:

multiply(vec4, output = nil) -> output or new vec4
multiply(scalar, output = nil) -> output or new vec4


153
154
155
156
157
158
159
# File 'lib/snow-math/vec4.rb', line 153

def multiply(rhs, output = nil)
  case rhs
  when ::Snow::Vec4, ::Snow::Quat then multiply_vec4(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



164
165
166
# File 'lib/snow-math/vec4.rb', line 164

def multiply!(rhs)
  multiply rhs, self
end

#multiply_vec4(*args) ⇒ Object

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

call-seq:

multiply_vec4(vec4, output = nil) -> output or new vec4


3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
# File 'ext/snow-math/snow-math.c', line 3461

static VALUE sm_vec4_multiply(int argc, VALUE *argv, VALUE sm_self)
{
  VALUE sm_rhs;
  VALUE sm_out;
  vec4_t *self;
  vec4_t *rhs;
  rb_scan_args(argc, argv, "11", &sm_rhs, &sm_out);
  self = sm_unwrap_vec4(sm_self, NULL);
  if (!SM_IS_A(sm_rhs, vec4) && !SM_IS_A(sm_rhs, quat)) {
    rb_raise(rb_eTypeError,
      kSM_WANT_FOUR_FORMAT_LIT,
      rb_obj_classname(sm_rhs));
    return Qnil;
  }
  rhs = sm_unwrap_vec4(sm_rhs, NULL);
  if (argc == 2) {
    if (!RTEST(sm_out)) {
      goto SM_LABEL(skip_output);
    }{
    vec4_t *output;
    if (!SM_IS_A(sm_out, vec4) && !SM_IS_A(sm_out, quat)) {
      rb_raise(rb_eTypeError,
        kSM_WANT_FOUR_FORMAT_LIT,
        rb_obj_classname(sm_out));
      return Qnil;
    }
    rb_check_frozen(sm_out);
    output = sm_unwrap_vec4(sm_out, NULL);
    vec4_multiply(*self, *rhs, *output);
  }} else if (argc == 1) {
SM_LABEL(skip_output): {
    vec4_t output;
    vec4_multiply(*self, *rhs, output);
    sm_out = sm_wrap_vec4(output, rb_obj_class(sm_self));
    rb_obj_call_init(sm_out, 0, 0);
  }} else {
    rb_raise(rb_eArgError, "Invalid number of arguments to multiply_vec4");
  }
  return sm_out;
}

#multiply_vec4!(rhs) ⇒ Object

Calls #multiply_vec4(rhs, self)

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



144
145
146
# File 'lib/snow-math/vec4.rb', line 144

def multiply_vec4!(rhs)
  multiply_vec4 rhs, self
end

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

Negates this vector or quaternions’s components and returns the result.

call-seq:

negate(output = nil) -> output or new vec4 or quat


3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
# File 'ext/snow-math/snow-math.c', line 3322

static VALUE sm_vec4_negate(int argc, VALUE *argv, VALUE sm_self)
{
  VALUE sm_out;
  vec4_t *self;
  rb_scan_args(argc, argv, "01", &sm_out);
  self = sm_unwrap_vec4(sm_self, NULL);
  if (argc == 1) {
    if (!RTEST(sm_out)) {
      goto SM_LABEL(skip_output);
    }{
    vec4_t *output;
    if (!SM_IS_A(sm_out, vec4) && !SM_IS_A(sm_out, quat)) {
      rb_raise(rb_eTypeError,
        kSM_WANT_FOUR_FORMAT_LIT,
        rb_obj_classname(sm_out));
      return Qnil;
    }
    rb_check_frozen(sm_out);
    output = sm_unwrap_vec4(sm_out, NULL);
    vec4_negate (*self, *output);
  }} else if (argc == 0) {
SM_LABEL(skip_output): {
    vec4_t output;
    vec4_negate (*self, output);
    sm_out = sm_wrap_vec4(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



137
138
139
# File 'lib/snow-math/vec4.rb', line 137

def negate!
  negate self
end

#normalize(*args) ⇒ Object

Returns a normalized Vec4 or Quat, depending on the type of the receiver and output.

call-seq:

normalize(output = nil) -> output or new vec4 / quat


3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
# File 'ext/snow-math/snow-math.c', line 3242

static VALUE sm_vec4_normalize(int argc, VALUE *argv, VALUE sm_self)
{
  VALUE sm_out;
  vec4_t *self;
  rb_scan_args(argc, argv, "01", &sm_out);
  self = sm_unwrap_vec4(sm_self, NULL);
  if (argc == 1) {
    if (!RTEST(sm_out)) {
      goto SM_LABEL(skip_output);
    }{
    vec4_t *output;
    if (!SM_IS_A(sm_out, vec4) && !SM_IS_A(sm_out, quat)) {
     rb_raise(rb_eTypeError,
       kSM_WANT_FOUR_FORMAT_LIT,
       rb_obj_classname(sm_out));
    }
    rb_check_frozen(sm_out);
    output = sm_unwrap_vec4(sm_out, NULL);
    vec4_normalize (*self, *output);
  }} else if (argc == 0) {
SM_LABEL(skip_output): {
    vec4_t output;
    vec4_normalize (*self, output);
    sm_out = sm_wrap_vec4(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



123
124
125
# File 'lib/snow-math/vec4.rb', line 123

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 vec4


3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
# File 'ext/snow-math/snow-math.c', line 3362

static VALUE sm_vec4_project(int argc, VALUE *argv, VALUE sm_self)
{
  VALUE sm_rhs;
  VALUE sm_out;
  vec4_t *self;
  vec4_t *rhs;
  rb_scan_args(argc, argv, "11", &sm_rhs, &sm_out);
  self = sm_unwrap_vec4(sm_self, NULL);
  if (!SM_IS_A(sm_rhs, vec4) && !SM_IS_A(sm_rhs, quat)) {
    rb_raise(rb_eTypeError,
      kSM_WANT_FOUR_FORMAT_LIT,
      rb_obj_classname(sm_rhs));
    return Qnil;
  }
  rhs = sm_unwrap_vec4(sm_rhs, NULL);
  if (argc == 2) {
    if (!RTEST(sm_out)) {
      goto SM_LABEL(skip_output);
    }{
    vec4_t *output;
    if (!SM_IS_A(sm_out, vec4) && !SM_IS_A(sm_out, quat)) {
      rb_raise(rb_eTypeError,
        kSM_WANT_FOUR_FORMAT_LIT,
        rb_obj_classname(sm_out));
      return Qnil;
    }
    rb_check_frozen(sm_out);
    output = sm_unwrap_vec4(sm_out, NULL);
    vec4_project(*self, *rhs, *output);
  }} else if (argc == 1) {
SM_LABEL(skip_output): {
    vec4_t output;
    vec4_project(*self, *rhs, output);
    sm_out = sm_wrap_vec4(output, rb_obj_class(sm_self));
    rb_obj_call_init(sm_out, 0, 0);
  }} else {
    rb_raise(rb_eArgError, "Invalid number of arguments to project");
  }
  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 vec4


3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
# File 'ext/snow-math/snow-math.c', line 3411

static VALUE sm_vec4_reflect(int argc, VALUE *argv, VALUE sm_self)
{
  VALUE sm_rhs;
  VALUE sm_out;
  vec4_t *self;
  vec4_t *rhs;
  rb_scan_args(argc, argv, "11", &sm_rhs, &sm_out);
  self = sm_unwrap_vec4(sm_self, NULL);
  if (!SM_IS_A(sm_rhs, vec4) && !SM_IS_A(sm_rhs, quat)) {
    rb_raise(rb_eTypeError,
      kSM_WANT_FOUR_FORMAT_LIT,
      rb_obj_classname(sm_rhs));
    return Qnil;
  }
  rhs = sm_unwrap_vec4(sm_rhs, NULL);
  if (argc == 2) {
    if (!RTEST(sm_out)) {
      goto SM_LABEL(skip_output);
    }{
    vec4_t *output;
    if (!SM_IS_A(sm_out, vec4) && !SM_IS_A(sm_out, quat)) {
      rb_raise(rb_eTypeError,
        kSM_WANT_FOUR_FORMAT_LIT,
        rb_obj_classname(sm_out));
      return Qnil;
    }
    rb_check_frozen(sm_out);
    output = sm_unwrap_vec4(sm_out, NULL);
    vec4_reflect(*self, *rhs, *output);
  }} else if (argc == 1) {
SM_LABEL(skip_output): {
    vec4_t output;
    vec4_reflect(*self, *rhs, output);
    sm_out = sm_wrap_vec4(output, rb_obj_class(sm_self));
    rb_obj_call_init(sm_out, 0, 0);
  }} else {
    rb_raise(rb_eArgError, "Invalid number of arguments to reflect");
  }
  return sm_out;
}

#scale(*args) ⇒ Object

Scales this vector or quaternion’s components by a scalar value and returns the result. The return type is that of the receiver.

call-seq:

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


3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
# File 'ext/snow-math/snow-math.c', line 3789

static VALUE sm_vec4_scale(int argc, VALUE *argv, VALUE sm_self)
{
  VALUE sm_out;
  VALUE sm_scalar;
  s_float_t scalar;
  vec4_t *self = sm_unwrap_vec4(sm_self, NULL);

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

  if ((SM_IS_A(sm_out, vec4) || SM_IS_A(sm_out, quat))) {
    rb_check_frozen(sm_out);
    vec4_scale(*self, scalar, *sm_unwrap_vec4(sm_out, NULL));
  } else {
    vec4_t out;
    vec4_scale(*self, scalar, out);
    sm_out = sm_wrap_vec4(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



185
186
187
# File 'lib/snow-math/vec4.rb', line 185

def scale!(rhs)
  scale rhs, self
end

#set(*args) ⇒ Object

Sets the Vec4’s components.

call-seq:

set(x, y, z, w = 1) -> new vec4 with components [x, y, z, w]
set([x, y, z, w])   -> new vec4 with components [x, y, z, w]
set(vec3)           -> vec4 with components [vec3.xyz, 1]
set(vec2)           -> vec4 with components [vec2.xy, 0, 1]
set(vec4)           -> copy of vec4
set(quat)           -> copy of quat as vec4


3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
# File 'ext/snow-math/snow-math.c', line 3660

static VALUE sm_vec4_init(int argc, VALUE *argv, VALUE sm_self)
{
  vec4_t *self = sm_unwrap_vec4(sm_self, NULL);
  size_t arr_index = 0;

  rb_check_frozen(sm_self);

  switch(argc) {

  /* Default value */
  case 0: { break; }

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

    if (SM_IS_A(argv[0], vec3)) {
      sm_unwrap_vec3(argv[0], *self);
      self[0][3] = s_float_lit(1.0);
      break;
    }

    if (SM_IS_A(argv[0], vec2)) {
      sm_unwrap_vec2(argv[0], *self);
      self[0][2] = s_float_lit(0.0);
      self[0][3] = s_float_lit(1.0);
      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 + 4;
      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 Vec4");
    break;
  }

  /* W */
  case 4: {
    self[0][3] = (s_float_t)rb_num2dbl(argv[3]);
    case 3: /* X, Y, Z */
    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 initialize/set");
    break;
  }
  } /* switch (argc) */

  return sm_self;
}

#sizeObject

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

call-seq: size -> fixnum



3176
3177
3178
3179
# File 'ext/snow-math/snow-math.c', line 3176

static VALUE sm_vec4_size (VALUE self)
{
  return SIZET2NUM(sizeof(vec4_t));
}

#storeObject Also known as: []=

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

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



3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
# File 'ext/snow-math/snow-math.c', line 3153

static VALUE sm_vec4_store (VALUE sm_self, VALUE sm_index, VALUE sm_value)
{
  static const int max_index = sizeof(vec4_t) / sizeof(s_float_t);
  vec4_t *self = sm_unwrap_vec4(sm_self, NULL);
  int index = NUM2INT(sm_index);
  rb_check_frozen(sm_self);
  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 or quaternion’s components from this vector’s and returns the result. The return type is that of the receiver.

call-seq:

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


3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
# File 'ext/snow-math/snow-math.c', line 3561

static VALUE sm_vec4_subtract(int argc, VALUE *argv, VALUE sm_self)
{
  VALUE sm_rhs;
  VALUE sm_out;
  vec4_t *self;
  vec4_t *rhs;
  rb_scan_args(argc, argv, "11", &sm_rhs, &sm_out);
  self = sm_unwrap_vec4(sm_self, NULL);
  if (!SM_IS_A(sm_rhs, vec4) && !SM_IS_A(sm_rhs, quat)) {
    rb_raise(rb_eTypeError,
      kSM_WANT_FOUR_FORMAT_LIT,
      rb_obj_classname(sm_rhs));
    return Qnil;
  }
  rhs = sm_unwrap_vec4(sm_rhs, NULL);
  if (argc == 2) {
    if (!RTEST(sm_out)) {
      goto SM_LABEL(skip_output);
    }{
    vec4_t *output;
    if (!SM_IS_A(sm_rhs, vec4) && !SM_IS_A(sm_rhs, quat)) {
      rb_raise(rb_eTypeError,
        kSM_WANT_FOUR_FORMAT_LIT,
        rb_obj_classname(sm_rhs));
      return Qnil;
    }
    rb_check_frozen(sm_out);
    output = sm_unwrap_vec4(sm_out, NULL);
    vec4_subtract(*self, *rhs, *output);
  }} else if (argc == 1) {
SM_LABEL(skip_output): {
    vec4_t output;
    vec4_subtract(*self, *rhs, output);
    sm_out = sm_wrap_vec4(output, rb_obj_class(sm_self));
    rb_obj_call_init(sm_out, 0, 0);
  }} else {
    rb_raise(rb_eArgError, "Invalid number of arguments to subtract");
  }
  return sm_out;
}

#subtract!(rhs) ⇒ Object

Calls #subtract(rhs, self)

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



178
179
180
# File 'lib/snow-math/vec4.rb', line 178

def subtract!(rhs)
  subtract rhs, self
end

#to_quatObject



60
61
62
# File 'lib/snow-math/vec4.rb', line 60

def to_quat
  Quat.new(self)
end

#to_sObject

Returns a string representation of self.

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

call-seq:

to_s -> string


3743
3744
3745
3746
3747
3748
3749
3750
3751
3752
# File 'ext/snow-math/snow-math.c', line 3743

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

#to_vec2Object



48
49
50
# File 'lib/snow-math/vec4.rb', line 48

def to_vec2
  Vec2.new(self)
end

#to_vec3Object



52
53
54
# File 'lib/snow-math/vec4.rb', line 52

def to_vec3
  Vec3.new(self)
end

#to_vec4Object



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

def to_vec4
  Vec4.new(self)
end

#wObject

Returns the W component of the vector.

call-seq: w -> float



109
110
111
# File 'lib/snow-math/vec4.rb', line 109

def w
  self[3]
end

#w=(value) ⇒ Object

Sets the W component of the vector.

call-seq: w = value -> value



116
117
118
# File 'lib/snow-math/vec4.rb', line 116

def w=(value)
  self[3] = value
end

#xObject

Returns the X component of the vector.

call-seq: x -> float



67
68
69
# File 'lib/snow-math/vec4.rb', line 67

def x
  self[0]
end

#x=(value) ⇒ Object

Sets the X component of the vector.

call-seq: x = value -> value



74
75
76
# File 'lib/snow-math/vec4.rb', line 74

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

#yObject

Returns the Y component of the vector.

call-seq: y -> float



81
82
83
# File 'lib/snow-math/vec4.rb', line 81

def y
  self[1]
end

#y=(value) ⇒ Object

Sets the Y component of the vector.

call-seq: y = value -> value



88
89
90
# File 'lib/snow-math/vec4.rb', line 88

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

#zObject

Returns the Z component of the vector.

call-seq: z -> float



95
96
97
# File 'lib/snow-math/vec4.rb', line 95

def z
  self[2]
end

#z=(value) ⇒ Object

Sets the Z component of the vector.

call-seq: z = value -> value



102
103
104
# File 'lib/snow-math/vec4.rb', line 102

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