larb 0.1.0 → 1.0.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/README.md +14 -1
- data/ext/larb/color.c +446 -0
- data/ext/larb/color.h +35 -0
- data/ext/larb/extconf.rb +11 -0
- data/ext/larb/larb.c +27 -0
- data/ext/larb/larb.h +8 -0
- data/ext/larb/mat2.c +300 -0
- data/ext/larb/mat2.h +30 -0
- data/ext/larb/mat2d.c +380 -0
- data/ext/larb/mat2d.h +35 -0
- data/ext/larb/mat3.c +469 -0
- data/ext/larb/mat3.h +33 -0
- data/ext/larb/mat4.c +671 -0
- data/ext/larb/mat4.h +31 -0
- data/ext/larb/quat.c +523 -0
- data/ext/larb/quat.h +39 -0
- data/ext/larb/quat2.c +473 -0
- data/ext/larb/quat2.h +39 -0
- data/ext/larb/vec2.c +342 -0
- data/ext/larb/vec2.h +43 -0
- data/ext/larb/vec3.c +503 -0
- data/ext/larb/vec3.h +52 -0
- data/ext/larb/vec4.c +340 -0
- data/ext/larb/vec4.h +38 -0
- data/lib/larb/version.rb +5 -0
- data/lib/larb.rb +2 -14
- data/test/larb/color_test.rb +278 -0
- data/test/larb/mat2_test.rb +144 -0
- data/test/larb/mat2d_test.rb +172 -0
- data/test/larb/mat3_test.rb +147 -0
- data/test/larb/mat4_test.rb +270 -0
- data/test/larb/quat2_test.rb +161 -0
- data/test/larb/quat_test.rb +224 -0
- data/test/larb/vec2_test.rb +251 -0
- data/test/larb/vec3_test.rb +310 -0
- data/test/larb/vec4_test.rb +189 -0
- data/test/test_helper.rb +4 -0
- metadata +53 -14
- data/Rakefile +0 -11
- data/lib/larb/color.rb +0 -148
- data/lib/larb/mat2.rb +0 -119
- data/lib/larb/mat2d.rb +0 -180
- data/lib/larb/mat3.rb +0 -238
- data/lib/larb/mat4.rb +0 -329
- data/lib/larb/quat.rb +0 -238
- data/lib/larb/quat2.rb +0 -193
- data/lib/larb/vec2.rb +0 -150
- data/lib/larb/vec3.rb +0 -218
- data/lib/larb/vec4.rb +0 -125
data/ext/larb/vec3.c
ADDED
|
@@ -0,0 +1,503 @@
|
|
|
1
|
+
#include "vec3.h"
|
|
2
|
+
|
|
3
|
+
#include <math.h>
|
|
4
|
+
|
|
5
|
+
static void vec3_free(void *ptr) {
|
|
6
|
+
xfree(ptr);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
static size_t vec3_memsize(const void *ptr) {
|
|
10
|
+
return sizeof(Vec3Data);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
static const rb_data_type_t vec3_type = {
|
|
14
|
+
"Vec3",
|
|
15
|
+
{0, vec3_free, vec3_memsize},
|
|
16
|
+
0,
|
|
17
|
+
0,
|
|
18
|
+
RUBY_TYPED_FREE_IMMEDIATELY,
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
static VALUE cVec3 = Qnil;
|
|
22
|
+
|
|
23
|
+
static double value_to_double(VALUE value) {
|
|
24
|
+
VALUE coerced = rb_funcall(value, rb_intern("to_f"), 0);
|
|
25
|
+
return NUM2DBL(coerced);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
static Vec3Data *vec3_get(VALUE obj) {
|
|
29
|
+
Vec3Data *data = NULL;
|
|
30
|
+
TypedData_Get_Struct(obj, Vec3Data, &vec3_type, data);
|
|
31
|
+
return data;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
static VALUE vec3_build(VALUE klass, double x, double y, double z) {
|
|
35
|
+
VALUE obj = vec3_alloc(klass);
|
|
36
|
+
Vec3Data *data = vec3_get(obj);
|
|
37
|
+
data->x = x;
|
|
38
|
+
data->y = y;
|
|
39
|
+
data->z = z;
|
|
40
|
+
return obj;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
static double clamp_double(double value, double min, double max) {
|
|
44
|
+
if (value < min) {
|
|
45
|
+
return min;
|
|
46
|
+
}
|
|
47
|
+
if (value > max) {
|
|
48
|
+
return max;
|
|
49
|
+
}
|
|
50
|
+
return value;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
VALUE vec3_alloc(VALUE klass) {
|
|
54
|
+
Vec3Data *data = ALLOC(Vec3Data);
|
|
55
|
+
data->x = 0.0;
|
|
56
|
+
data->y = 0.0;
|
|
57
|
+
data->z = 0.0;
|
|
58
|
+
return TypedData_Wrap_Struct(klass, &vec3_type, data);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
VALUE vec3_initialize(int argc, VALUE *argv, VALUE self) {
|
|
62
|
+
VALUE vx = Qnil;
|
|
63
|
+
VALUE vy = Qnil;
|
|
64
|
+
VALUE vz = Qnil;
|
|
65
|
+
Vec3Data *data = vec3_get(self);
|
|
66
|
+
|
|
67
|
+
rb_scan_args(argc, argv, "03", &vx, &vy, &vz);
|
|
68
|
+
data->x = NIL_P(vx) ? 0.0 : value_to_double(vx);
|
|
69
|
+
data->y = NIL_P(vy) ? 0.0 : value_to_double(vy);
|
|
70
|
+
data->z = NIL_P(vz) ? 0.0 : value_to_double(vz);
|
|
71
|
+
|
|
72
|
+
return self;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
static VALUE vec3_class_bracket(VALUE klass, VALUE x, VALUE y, VALUE z) {
|
|
76
|
+
return vec3_build(klass, value_to_double(x), value_to_double(y),
|
|
77
|
+
value_to_double(z));
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
static VALUE vec3_class_zero(VALUE klass) {
|
|
81
|
+
return vec3_build(klass, 0.0, 0.0, 0.0);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
static VALUE vec3_class_one(VALUE klass) {
|
|
85
|
+
return vec3_build(klass, 1.0, 1.0, 1.0);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
static VALUE vec3_class_up(VALUE klass) {
|
|
89
|
+
return vec3_build(klass, 0.0, 1.0, 0.0);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
static VALUE vec3_class_down(VALUE klass) {
|
|
93
|
+
return vec3_build(klass, 0.0, -1.0, 0.0);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
static VALUE vec3_class_forward(VALUE klass) {
|
|
97
|
+
return vec3_build(klass, 0.0, 0.0, -1.0);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
static VALUE vec3_class_back(VALUE klass) {
|
|
101
|
+
return vec3_build(klass, 0.0, 0.0, 1.0);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
static VALUE vec3_class_right(VALUE klass) {
|
|
105
|
+
return vec3_build(klass, 1.0, 0.0, 0.0);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
static VALUE vec3_class_left(VALUE klass) {
|
|
109
|
+
return vec3_build(klass, -1.0, 0.0, 0.0);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
static VALUE vec3_get_x(VALUE self) {
|
|
113
|
+
Vec3Data *data = vec3_get(self);
|
|
114
|
+
return DBL2NUM(data->x);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
static VALUE vec3_set_x(VALUE self, VALUE value) {
|
|
118
|
+
Vec3Data *data = vec3_get(self);
|
|
119
|
+
data->x = value_to_double(value);
|
|
120
|
+
return value;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
static VALUE vec3_get_y(VALUE self) {
|
|
124
|
+
Vec3Data *data = vec3_get(self);
|
|
125
|
+
return DBL2NUM(data->y);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
static VALUE vec3_set_y(VALUE self, VALUE value) {
|
|
129
|
+
Vec3Data *data = vec3_get(self);
|
|
130
|
+
data->y = value_to_double(value);
|
|
131
|
+
return value;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
static VALUE vec3_get_z(VALUE self) {
|
|
135
|
+
Vec3Data *data = vec3_get(self);
|
|
136
|
+
return DBL2NUM(data->z);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
static VALUE vec3_set_z(VALUE self, VALUE value) {
|
|
140
|
+
Vec3Data *data = vec3_get(self);
|
|
141
|
+
data->z = value_to_double(value);
|
|
142
|
+
return value;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
VALUE vec3_add(VALUE self, VALUE other) {
|
|
146
|
+
Vec3Data *a = vec3_get(self);
|
|
147
|
+
Vec3Data *b = vec3_get(other);
|
|
148
|
+
return vec3_build(rb_obj_class(self), a->x + b->x, a->y + b->y,
|
|
149
|
+
a->z + b->z);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
VALUE vec3_sub(VALUE self, VALUE other) {
|
|
153
|
+
Vec3Data *a = vec3_get(self);
|
|
154
|
+
Vec3Data *b = vec3_get(other);
|
|
155
|
+
return vec3_build(rb_obj_class(self), a->x - b->x, a->y - b->y,
|
|
156
|
+
a->z - b->z);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
VALUE vec3_mul(VALUE self, VALUE scalar) {
|
|
160
|
+
Vec3Data *a = vec3_get(self);
|
|
161
|
+
|
|
162
|
+
if (rb_obj_is_kind_of(scalar, cVec3)) {
|
|
163
|
+
Vec3Data *b = vec3_get(scalar);
|
|
164
|
+
return vec3_build(rb_obj_class(self), a->x * b->x, a->y * b->y,
|
|
165
|
+
a->z * b->z);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
double s = value_to_double(scalar);
|
|
169
|
+
return vec3_build(rb_obj_class(self), a->x * s, a->y * s, a->z * s);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
VALUE vec3_div(VALUE self, VALUE scalar) {
|
|
173
|
+
Vec3Data *a = vec3_get(self);
|
|
174
|
+
double s = value_to_double(scalar);
|
|
175
|
+
return vec3_build(rb_obj_class(self), a->x / s, a->y / s, a->z / s);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
VALUE vec3_negate(VALUE self) {
|
|
179
|
+
Vec3Data *a = vec3_get(self);
|
|
180
|
+
return vec3_build(rb_obj_class(self), -a->x, -a->y, -a->z);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
VALUE vec3_dot(VALUE self, VALUE other) {
|
|
184
|
+
Vec3Data *a = vec3_get(self);
|
|
185
|
+
Vec3Data *b = vec3_get(other);
|
|
186
|
+
return DBL2NUM(a->x * b->x + a->y * b->y + a->z * b->z);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
VALUE vec3_cross(VALUE self, VALUE other) {
|
|
190
|
+
Vec3Data *a = vec3_get(self);
|
|
191
|
+
Vec3Data *b = vec3_get(other);
|
|
192
|
+
return vec3_build(rb_obj_class(self), a->y * b->z - a->z * b->y,
|
|
193
|
+
a->z * b->x - a->x * b->z,
|
|
194
|
+
a->x * b->y - a->y * b->x);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
VALUE vec3_length(VALUE self) {
|
|
198
|
+
Vec3Data *a = vec3_get(self);
|
|
199
|
+
return DBL2NUM(sqrt(a->x * a->x + a->y * a->y + a->z * a->z));
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
VALUE vec3_length_squared(VALUE self) {
|
|
203
|
+
Vec3Data *a = vec3_get(self);
|
|
204
|
+
return DBL2NUM(a->x * a->x + a->y * a->y + a->z * a->z);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
VALUE vec3_normalize(VALUE self) {
|
|
208
|
+
Vec3Data *a = vec3_get(self);
|
|
209
|
+
double len = sqrt(a->x * a->x + a->y * a->y + a->z * a->z);
|
|
210
|
+
return vec3_build(rb_obj_class(self), a->x / len, a->y / len, a->z / len);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
VALUE vec3_reflect(VALUE self, VALUE normal) {
|
|
214
|
+
Vec3Data *a = vec3_get(self);
|
|
215
|
+
Vec3Data *n = vec3_get(normal);
|
|
216
|
+
double dot = a->x * n->x + a->y * n->y + a->z * n->z;
|
|
217
|
+
return vec3_build(rb_obj_class(self), a->x - n->x * (2.0 * dot),
|
|
218
|
+
a->y - n->y * (2.0 * dot), a->z - n->z * (2.0 * dot));
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
VALUE vec3_xy(VALUE self) {
|
|
222
|
+
Vec3Data *a = vec3_get(self);
|
|
223
|
+
VALUE vec2_class = rb_const_get(mLarb, rb_intern("Vec2"));
|
|
224
|
+
return rb_funcall(vec2_class, rb_intern("new"), 2, DBL2NUM(a->x),
|
|
225
|
+
DBL2NUM(a->y));
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
VALUE vec3_xz(VALUE self) {
|
|
229
|
+
Vec3Data *a = vec3_get(self);
|
|
230
|
+
VALUE vec2_class = rb_const_get(mLarb, rb_intern("Vec2"));
|
|
231
|
+
return rb_funcall(vec2_class, rb_intern("new"), 2, DBL2NUM(a->x),
|
|
232
|
+
DBL2NUM(a->z));
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
VALUE vec3_yz(VALUE self) {
|
|
236
|
+
Vec3Data *a = vec3_get(self);
|
|
237
|
+
VALUE vec2_class = rb_const_get(mLarb, rb_intern("Vec2"));
|
|
238
|
+
return rb_funcall(vec2_class, rb_intern("new"), 2, DBL2NUM(a->y),
|
|
239
|
+
DBL2NUM(a->z));
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
VALUE vec3_lerp(VALUE self, VALUE other, VALUE t) {
|
|
243
|
+
Vec3Data *a = vec3_get(self);
|
|
244
|
+
Vec3Data *b = vec3_get(other);
|
|
245
|
+
double s = value_to_double(t);
|
|
246
|
+
return vec3_build(rb_obj_class(self), a->x + (b->x - a->x) * s,
|
|
247
|
+
a->y + (b->y - a->y) * s,
|
|
248
|
+
a->z + (b->z - a->z) * s);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
VALUE vec3_to_a(VALUE self) {
|
|
252
|
+
Vec3Data *a = vec3_get(self);
|
|
253
|
+
VALUE ary = rb_ary_new_capa(3);
|
|
254
|
+
rb_ary_push(ary, DBL2NUM(a->x));
|
|
255
|
+
rb_ary_push(ary, DBL2NUM(a->y));
|
|
256
|
+
rb_ary_push(ary, DBL2NUM(a->z));
|
|
257
|
+
return ary;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
VALUE vec3_to_vec4(int argc, VALUE *argv, VALUE self) {
|
|
261
|
+
VALUE vw = Qnil;
|
|
262
|
+
Vec3Data *a = vec3_get(self);
|
|
263
|
+
|
|
264
|
+
rb_scan_args(argc, argv, "01", &vw);
|
|
265
|
+
VALUE vec4_class = rb_const_get(mLarb, rb_intern("Vec4"));
|
|
266
|
+
return rb_funcall(vec4_class, rb_intern("new"), 4, DBL2NUM(a->x),
|
|
267
|
+
DBL2NUM(a->y), DBL2NUM(a->z),
|
|
268
|
+
NIL_P(vw) ? DBL2NUM(1.0) : vw);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
VALUE vec3_aref(VALUE self, VALUE index) {
|
|
272
|
+
VALUE ary = vec3_to_a(self);
|
|
273
|
+
return rb_ary_entry(ary, NUM2LONG(index));
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
VALUE vec3_equal(VALUE self, VALUE other) {
|
|
277
|
+
if (!rb_obj_is_kind_of(other, cVec3)) {
|
|
278
|
+
return Qfalse;
|
|
279
|
+
}
|
|
280
|
+
Vec3Data *a = vec3_get(self);
|
|
281
|
+
Vec3Data *b = vec3_get(other);
|
|
282
|
+
return (a->x == b->x && a->y == b->y && a->z == b->z) ? Qtrue : Qfalse;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
VALUE vec3_near(int argc, VALUE *argv, VALUE self) {
|
|
286
|
+
VALUE other = Qnil;
|
|
287
|
+
VALUE epsilon = Qnil;
|
|
288
|
+
|
|
289
|
+
rb_scan_args(argc, argv, "11", &other, &epsilon);
|
|
290
|
+
Vec3Data *a = vec3_get(self);
|
|
291
|
+
Vec3Data *b = vec3_get(other);
|
|
292
|
+
double eps = NIL_P(epsilon) ? 1e-6 : value_to_double(epsilon);
|
|
293
|
+
|
|
294
|
+
if (fabs(a->x - b->x) < eps && fabs(a->y - b->y) < eps &&
|
|
295
|
+
fabs(a->z - b->z) < eps) {
|
|
296
|
+
return Qtrue;
|
|
297
|
+
}
|
|
298
|
+
return Qfalse;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
VALUE vec3_distance(VALUE self, VALUE other) {
|
|
302
|
+
Vec3Data *a = vec3_get(self);
|
|
303
|
+
Vec3Data *b = vec3_get(other);
|
|
304
|
+
double dx = a->x - b->x;
|
|
305
|
+
double dy = a->y - b->y;
|
|
306
|
+
double dz = a->z - b->z;
|
|
307
|
+
return DBL2NUM(sqrt(dx * dx + dy * dy + dz * dz));
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
VALUE vec3_distance_squared(VALUE self, VALUE other) {
|
|
311
|
+
Vec3Data *a = vec3_get(self);
|
|
312
|
+
Vec3Data *b = vec3_get(other);
|
|
313
|
+
double dx = a->x - b->x;
|
|
314
|
+
double dy = a->y - b->y;
|
|
315
|
+
double dz = a->z - b->z;
|
|
316
|
+
return DBL2NUM(dx * dx + dy * dy + dz * dz);
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
VALUE vec3_angle_between(VALUE self, VALUE other) {
|
|
320
|
+
Vec3Data *a = vec3_get(self);
|
|
321
|
+
Vec3Data *b = vec3_get(other);
|
|
322
|
+
double len = sqrt(a->x * a->x + a->y * a->y + a->z * a->z);
|
|
323
|
+
double other_len = sqrt(b->x * b->x + b->y * b->y + b->z * b->z);
|
|
324
|
+
double dot = a->x * b->x + a->y * b->y + a->z * b->z;
|
|
325
|
+
double d = dot / (len * other_len);
|
|
326
|
+
return DBL2NUM(acos(clamp_double(d, -1.0, 1.0)));
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
VALUE vec3_project(VALUE self, VALUE onto) {
|
|
330
|
+
Vec3Data *a = vec3_get(self);
|
|
331
|
+
Vec3Data *b = vec3_get(onto);
|
|
332
|
+
double denom = b->x * b->x + b->y * b->y + b->z * b->z;
|
|
333
|
+
double scale = (a->x * b->x + a->y * b->y + a->z * b->z) / denom;
|
|
334
|
+
return vec3_build(rb_obj_class(self), b->x * scale, b->y * scale,
|
|
335
|
+
b->z * scale);
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
VALUE vec3_reject(VALUE self, VALUE from) {
|
|
339
|
+
Vec3Data *a = vec3_get(self);
|
|
340
|
+
Vec3Data *b = vec3_get(from);
|
|
341
|
+
double denom = b->x * b->x + b->y * b->y + b->z * b->z;
|
|
342
|
+
double scale = (a->x * b->x + a->y * b->y + a->z * b->z) / denom;
|
|
343
|
+
double px = b->x * scale;
|
|
344
|
+
double py = b->y * scale;
|
|
345
|
+
double pz = b->z * scale;
|
|
346
|
+
return vec3_build(rb_obj_class(self), a->x - px, a->y - py, a->z - pz);
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
VALUE vec3_slerp(VALUE self, VALUE other, VALUE t) {
|
|
350
|
+
Vec3Data *a = vec3_get(self);
|
|
351
|
+
Vec3Data *b = vec3_get(other);
|
|
352
|
+
double s = value_to_double(t);
|
|
353
|
+
|
|
354
|
+
double len = sqrt(a->x * a->x + a->y * a->y + a->z * a->z);
|
|
355
|
+
double other_len = sqrt(b->x * b->x + b->y * b->y + b->z * b->z);
|
|
356
|
+
double dot = (a->x * b->x + a->y * b->y + a->z * b->z) / (len * other_len);
|
|
357
|
+
dot = clamp_double(dot, -1.0, 1.0);
|
|
358
|
+
|
|
359
|
+
double theta = acos(dot) * s;
|
|
360
|
+
double rx = b->x - a->x * dot;
|
|
361
|
+
double ry = b->y - a->y * dot;
|
|
362
|
+
double rz = b->z - a->z * dot;
|
|
363
|
+
double rlen = sqrt(rx * rx + ry * ry + rz * rz);
|
|
364
|
+
rx /= rlen;
|
|
365
|
+
ry /= rlen;
|
|
366
|
+
rz /= rlen;
|
|
367
|
+
|
|
368
|
+
return vec3_build(rb_obj_class(self), a->x * cos(theta) + rx * sin(theta),
|
|
369
|
+
a->y * cos(theta) + ry * sin(theta),
|
|
370
|
+
a->z * cos(theta) + rz * sin(theta));
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
VALUE vec3_clamp_length(VALUE self, VALUE max_length) {
|
|
374
|
+
Vec3Data *a = vec3_get(self);
|
|
375
|
+
double max_len = value_to_double(max_length);
|
|
376
|
+
double len_sq = a->x * a->x + a->y * a->y + a->z * a->z;
|
|
377
|
+
if (len_sq <= max_len * max_len) {
|
|
378
|
+
return self;
|
|
379
|
+
}
|
|
380
|
+
double scale = max_len / sqrt(len_sq);
|
|
381
|
+
return vec3_build(rb_obj_class(self), a->x * scale, a->y * scale,
|
|
382
|
+
a->z * scale);
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
VALUE vec3_normalize_bang(VALUE self) {
|
|
386
|
+
Vec3Data *a = vec3_get(self);
|
|
387
|
+
double len = sqrt(a->x * a->x + a->y * a->y + a->z * a->z);
|
|
388
|
+
a->x /= len;
|
|
389
|
+
a->y /= len;
|
|
390
|
+
a->z /= len;
|
|
391
|
+
return self;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
VALUE vec3_min(VALUE self, VALUE other) {
|
|
395
|
+
Vec3Data *a = vec3_get(self);
|
|
396
|
+
Vec3Data *b = vec3_get(other);
|
|
397
|
+
return vec3_build(rb_obj_class(self), fmin(a->x, b->x), fmin(a->y, b->y),
|
|
398
|
+
fmin(a->z, b->z));
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
VALUE vec3_max(VALUE self, VALUE other) {
|
|
402
|
+
Vec3Data *a = vec3_get(self);
|
|
403
|
+
Vec3Data *b = vec3_get(other);
|
|
404
|
+
return vec3_build(rb_obj_class(self), fmax(a->x, b->x), fmax(a->y, b->y),
|
|
405
|
+
fmax(a->z, b->z));
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
VALUE vec3_abs(VALUE self) {
|
|
409
|
+
Vec3Data *a = vec3_get(self);
|
|
410
|
+
return vec3_build(rb_obj_class(self), fabs(a->x), fabs(a->y), fabs(a->z));
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
VALUE vec3_floor(VALUE self) {
|
|
414
|
+
Vec3Data *a = vec3_get(self);
|
|
415
|
+
return vec3_build(rb_obj_class(self), floor(a->x), floor(a->y), floor(a->z));
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
VALUE vec3_ceil(VALUE self) {
|
|
419
|
+
Vec3Data *a = vec3_get(self);
|
|
420
|
+
return vec3_build(rb_obj_class(self), ceil(a->x), ceil(a->y), ceil(a->z));
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
VALUE vec3_round(VALUE self) {
|
|
424
|
+
Vec3Data *a = vec3_get(self);
|
|
425
|
+
return vec3_build(rb_obj_class(self), round(a->x), round(a->y), round(a->z));
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
VALUE vec3_inspect(VALUE self) {
|
|
429
|
+
Vec3Data *a = vec3_get(self);
|
|
430
|
+
VALUE sx = rb_funcall(DBL2NUM(a->x), rb_intern("to_s"), 0);
|
|
431
|
+
VALUE sy = rb_funcall(DBL2NUM(a->y), rb_intern("to_s"), 0);
|
|
432
|
+
VALUE sz = rb_funcall(DBL2NUM(a->z), rb_intern("to_s"), 0);
|
|
433
|
+
VALUE str = rb_str_new_cstr("Vec3[");
|
|
434
|
+
rb_str_concat(str, sx);
|
|
435
|
+
rb_str_cat_cstr(str, ", ");
|
|
436
|
+
rb_str_concat(str, sy);
|
|
437
|
+
rb_str_cat_cstr(str, ", ");
|
|
438
|
+
rb_str_concat(str, sz);
|
|
439
|
+
rb_str_cat_cstr(str, "]");
|
|
440
|
+
return str;
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
void Init_vec3(VALUE module) {
|
|
444
|
+
cVec3 = rb_define_class_under(module, "Vec3", rb_cObject);
|
|
445
|
+
|
|
446
|
+
rb_define_alloc_func(cVec3, vec3_alloc);
|
|
447
|
+
rb_define_method(cVec3, "initialize", vec3_initialize, -1);
|
|
448
|
+
|
|
449
|
+
rb_define_singleton_method(cVec3, "[]", vec3_class_bracket, 3);
|
|
450
|
+
rb_define_singleton_method(cVec3, "zero", vec3_class_zero, 0);
|
|
451
|
+
rb_define_singleton_method(cVec3, "one", vec3_class_one, 0);
|
|
452
|
+
rb_define_singleton_method(cVec3, "up", vec3_class_up, 0);
|
|
453
|
+
rb_define_singleton_method(cVec3, "down", vec3_class_down, 0);
|
|
454
|
+
rb_define_singleton_method(cVec3, "forward", vec3_class_forward, 0);
|
|
455
|
+
rb_define_singleton_method(cVec3, "back", vec3_class_back, 0);
|
|
456
|
+
rb_define_singleton_method(cVec3, "right", vec3_class_right, 0);
|
|
457
|
+
rb_define_singleton_method(cVec3, "left", vec3_class_left, 0);
|
|
458
|
+
|
|
459
|
+
rb_define_method(cVec3, "x", vec3_get_x, 0);
|
|
460
|
+
rb_define_method(cVec3, "x=", vec3_set_x, 1);
|
|
461
|
+
rb_define_method(cVec3, "y", vec3_get_y, 0);
|
|
462
|
+
rb_define_method(cVec3, "y=", vec3_set_y, 1);
|
|
463
|
+
rb_define_method(cVec3, "z", vec3_get_z, 0);
|
|
464
|
+
rb_define_method(cVec3, "z=", vec3_set_z, 1);
|
|
465
|
+
|
|
466
|
+
rb_define_method(cVec3, "+", vec3_add, 1);
|
|
467
|
+
rb_define_method(cVec3, "-", vec3_sub, 1);
|
|
468
|
+
rb_define_method(cVec3, "*", vec3_mul, 1);
|
|
469
|
+
rb_define_method(cVec3, "/", vec3_div, 1);
|
|
470
|
+
rb_define_method(cVec3, "-@", vec3_negate, 0);
|
|
471
|
+
|
|
472
|
+
rb_define_method(cVec3, "dot", vec3_dot, 1);
|
|
473
|
+
rb_define_method(cVec3, "cross", vec3_cross, 1);
|
|
474
|
+
rb_define_method(cVec3, "length", vec3_length, 0);
|
|
475
|
+
rb_define_method(cVec3, "length_squared", vec3_length_squared, 0);
|
|
476
|
+
rb_define_method(cVec3, "normalize", vec3_normalize, 0);
|
|
477
|
+
rb_define_method(cVec3, "reflect", vec3_reflect, 1);
|
|
478
|
+
rb_define_method(cVec3, "xy", vec3_xy, 0);
|
|
479
|
+
rb_define_method(cVec3, "xz", vec3_xz, 0);
|
|
480
|
+
rb_define_method(cVec3, "yz", vec3_yz, 0);
|
|
481
|
+
rb_define_method(cVec3, "lerp", vec3_lerp, 2);
|
|
482
|
+
rb_define_method(cVec3, "to_a", vec3_to_a, 0);
|
|
483
|
+
rb_define_method(cVec3, "to_vec4", vec3_to_vec4, -1);
|
|
484
|
+
rb_define_method(cVec3, "[]", vec3_aref, 1);
|
|
485
|
+
rb_define_method(cVec3, "==", vec3_equal, 1);
|
|
486
|
+
rb_define_method(cVec3, "near?", vec3_near, -1);
|
|
487
|
+
rb_define_method(cVec3, "distance", vec3_distance, 1);
|
|
488
|
+
rb_define_method(cVec3, "distance_squared", vec3_distance_squared, 1);
|
|
489
|
+
rb_define_method(cVec3, "angle_between", vec3_angle_between, 1);
|
|
490
|
+
rb_define_method(cVec3, "project", vec3_project, 1);
|
|
491
|
+
rb_define_method(cVec3, "reject", vec3_reject, 1);
|
|
492
|
+
rb_define_method(cVec3, "slerp", vec3_slerp, 2);
|
|
493
|
+
rb_define_method(cVec3, "clamp_length", vec3_clamp_length, 1);
|
|
494
|
+
rb_define_method(cVec3, "normalize!", vec3_normalize_bang, 0);
|
|
495
|
+
rb_define_method(cVec3, "min", vec3_min, 1);
|
|
496
|
+
rb_define_method(cVec3, "max", vec3_max, 1);
|
|
497
|
+
rb_define_method(cVec3, "abs", vec3_abs, 0);
|
|
498
|
+
rb_define_method(cVec3, "floor", vec3_floor, 0);
|
|
499
|
+
rb_define_method(cVec3, "ceil", vec3_ceil, 0);
|
|
500
|
+
rb_define_method(cVec3, "round", vec3_round, 0);
|
|
501
|
+
rb_define_method(cVec3, "inspect", vec3_inspect, 0);
|
|
502
|
+
rb_define_alias(cVec3, "to_s", "inspect");
|
|
503
|
+
}
|
data/ext/larb/vec3.h
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
#ifndef VEC3_H
|
|
2
|
+
#define VEC3_H
|
|
3
|
+
|
|
4
|
+
#include "larb.h"
|
|
5
|
+
|
|
6
|
+
typedef struct {
|
|
7
|
+
double x;
|
|
8
|
+
double y;
|
|
9
|
+
double z;
|
|
10
|
+
} Vec3Data;
|
|
11
|
+
|
|
12
|
+
void Init_vec3(VALUE module);
|
|
13
|
+
VALUE vec3_alloc(VALUE klass);
|
|
14
|
+
VALUE vec3_initialize(int argc, VALUE *argv, VALUE self);
|
|
15
|
+
|
|
16
|
+
VALUE vec3_add(VALUE self, VALUE other);
|
|
17
|
+
VALUE vec3_sub(VALUE self, VALUE other);
|
|
18
|
+
VALUE vec3_mul(VALUE self, VALUE scalar);
|
|
19
|
+
VALUE vec3_div(VALUE self, VALUE scalar);
|
|
20
|
+
VALUE vec3_negate(VALUE self);
|
|
21
|
+
VALUE vec3_dot(VALUE self, VALUE other);
|
|
22
|
+
VALUE vec3_cross(VALUE self, VALUE other);
|
|
23
|
+
VALUE vec3_length(VALUE self);
|
|
24
|
+
VALUE vec3_length_squared(VALUE self);
|
|
25
|
+
VALUE vec3_normalize(VALUE self);
|
|
26
|
+
VALUE vec3_reflect(VALUE self, VALUE normal);
|
|
27
|
+
VALUE vec3_xy(VALUE self);
|
|
28
|
+
VALUE vec3_xz(VALUE self);
|
|
29
|
+
VALUE vec3_yz(VALUE self);
|
|
30
|
+
VALUE vec3_lerp(VALUE self, VALUE other, VALUE t);
|
|
31
|
+
VALUE vec3_to_a(VALUE self);
|
|
32
|
+
VALUE vec3_to_vec4(int argc, VALUE *argv, VALUE self);
|
|
33
|
+
VALUE vec3_aref(VALUE self, VALUE index);
|
|
34
|
+
VALUE vec3_equal(VALUE self, VALUE other);
|
|
35
|
+
VALUE vec3_near(int argc, VALUE *argv, VALUE self);
|
|
36
|
+
VALUE vec3_distance(VALUE self, VALUE other);
|
|
37
|
+
VALUE vec3_distance_squared(VALUE self, VALUE other);
|
|
38
|
+
VALUE vec3_angle_between(VALUE self, VALUE other);
|
|
39
|
+
VALUE vec3_project(VALUE self, VALUE onto);
|
|
40
|
+
VALUE vec3_reject(VALUE self, VALUE from);
|
|
41
|
+
VALUE vec3_slerp(VALUE self, VALUE other, VALUE t);
|
|
42
|
+
VALUE vec3_clamp_length(VALUE self, VALUE max_length);
|
|
43
|
+
VALUE vec3_normalize_bang(VALUE self);
|
|
44
|
+
VALUE vec3_min(VALUE self, VALUE other);
|
|
45
|
+
VALUE vec3_max(VALUE self, VALUE other);
|
|
46
|
+
VALUE vec3_abs(VALUE self);
|
|
47
|
+
VALUE vec3_floor(VALUE self);
|
|
48
|
+
VALUE vec3_ceil(VALUE self);
|
|
49
|
+
VALUE vec3_round(VALUE self);
|
|
50
|
+
VALUE vec3_inspect(VALUE self);
|
|
51
|
+
|
|
52
|
+
#endif
|