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
SIZE =
INT2FIX(sizeof(vec4_t))
LENGTH =
INT2FIX(sizeof(vec4_t) / sizeof(s_float_t))
@@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


3505
3506
3507
3508
3509
3510
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
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
# File 'ext/snow-math/snow-math.c', line 3505

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)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)NUM2DBL(argv[3]);
    case 3: /* X, Y, Z */
    self[0][0] = (s_float_t)NUM2DBL(argv[0]);
    self[0][1] = (s_float_t)NUM2DBL(argv[1]);
    self[0][2] = (s_float_t)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


3485
3486
3487
3488
3489
3490
# File 'ext/snow-math/snow-math.c', line 3485

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


3700
3701
3702
3703
3704
3705
3706
3707
# File 'ext/snow-math/snow-math.c', line 3700

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


3356
3357
3358
3359
3360
3361
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
# File 'ext/snow-math/snow-math.c', line 3356

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



6739
6740
6741
6742
6743
6744
# File 'ext/snow-math/snow-math.c', line 6739

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


3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
# File 'ext/snow-math/snow-math.c', line 3046

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


3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
# File 'ext/snow-math/snow-math.c', line 3666

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 = 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


3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
# File 'ext/snow-math/snow-math.c', line 3457

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 DBL2NUM(
    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



2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
# File 'ext/snow-math/snow-math.c', line 2979

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 DBL2NUM(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


3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
# File 'ext/snow-math/snow-math.c', line 3127

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



3033
3034
3035
3036
# File 'ext/snow-math/snow-math.c', line 3033

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


3620
3621
3622
3623
# File 'ext/snow-math/snow-math.c', line 3620

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

#magnitude_squaredObject

Returns the squared magnitude of self.

call-seq:

magnitude_squared -> float


3607
3608
3609
3610
# File 'ext/snow-math/snow-math.c', line 3607

static VALUE sm_vec4_magnitude_squared(VALUE sm_self)
{
  return DBL2NUM(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


3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
# File 'ext/snow-math/snow-math.c', line 3306

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


3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
# File 'ext/snow-math/snow-math.c', line 3167

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


3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
# File 'ext/snow-math/snow-math.c', line 3087

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


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
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
# File 'ext/snow-math/snow-math.c', line 3207

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


3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
# File 'ext/snow-math/snow-math.c', line 3256

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


3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
# File 'ext/snow-math/snow-math.c', line 3634

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 = 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


3505
3506
3507
3508
3509
3510
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
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
# File 'ext/snow-math/snow-math.c', line 3505

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)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)NUM2DBL(argv[3]);
    case 3: /* X, Y, Z */
    self[0][0] = (s_float_t)NUM2DBL(argv[0]);
    self[0][1] = (s_float_t)NUM2DBL(argv[1]);
    self[0][2] = (s_float_t)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



3021
3022
3023
3024
# File 'ext/snow-math/snow-math.c', line 3021

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



2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
# File 'ext/snow-math/snow-math.c', line 2998

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)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


3406
3407
3408
3409
3410
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
# File 'ext/snow-math/snow-math.c', line 3406

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


3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
# File 'ext/snow-math/snow-math.c', line 3588

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