snow-math 1.0.0 → 1.1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 06c2a2a9cd139c807ff150d18ca76fd89bee201c
4
- data.tar.gz: 8c85e6d28b419162c6ded6d66bddd2ed7aae2af7
3
+ metadata.gz: 46e87b537dadcdf09df7d18126a3fdd43bae0269
4
+ data.tar.gz: 48ac51001b1c24bf65e0916a2d8253745bf61680
5
5
  SHA512:
6
- metadata.gz: 83c7950be8b9393e58e9ddb6549e1ab34ac30cc26abdd6e91651aa6753641522edc141159e5c658f3b4e4048d96ee97537b8d4f721449a698f96dc6721886ca8
7
- data.tar.gz: 95666f511d19d35cadb78bec99051f536cb3a825c00fbbbc1437ca532a6b8fa749204173d1ccb31a1cf90db4c052a73d9e05d5b076f599f70155c5220ddbb3ac
6
+ metadata.gz: d69f5b6d5224531c115093013049b1273905fc66a9fd1628d1ecee557a24932fcdac3bf1851b9814415c60596d9be65e93265fce947cdeb3c820b1ff2bf0ea9c
7
+ data.tar.gz: be97770e8846a16d83746f28ec00334e7c472d8b19f6eaa54145ab70c181caa264ee21a96211b2c5f658813cdc443f7099d19c6078e1053a5f536bbb6798480b
data/COPYING ADDED
@@ -0,0 +1,26 @@
1
+ Copyright (c) 2013, Noel Raymond Cower <ncower@gmail.com>.
2
+ All rights reserved.
3
+
4
+ Redistribution and use in source and binary forms, with or without
5
+ modification, are permitted provided that the following conditions are met:
6
+
7
+ 1. Redistributions of source code must retain the above copyright notice, this
8
+ list of conditions and the following disclaimer.
9
+ 2. Redistributions in binary form must reproduce the above copyright notice,
10
+ this list of conditions and the following disclaimer in the documentation
11
+ and/or other materials provided with the distribution.
12
+
13
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
14
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
17
+ ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
20
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23
+
24
+ The views and conclusions contained in the software and documentation are those
25
+ of the authors and should not be interpreted as representing official policies,
26
+ either expressed or implied, of the FreeBSD Project.
data/README.md ADDED
@@ -0,0 +1,613 @@
1
+ # snow-math
2
+
3
+ $ gem install snow-math [-- [--use-float | -F]]
4
+
5
+
6
+
7
+ ## Intro
8
+
9
+ snow-math is a small, fairly simple library of 3D math routines implemented in
10
+ C with Ruby bindings. It's intended for use with OpenGL and such. Currently, it
11
+ provides four 3D math types:
12
+
13
+ - Snow::Vec3
14
+ - Snow::Vec4
15
+ - Snow::Quat
16
+ - Snow::Mat4
17
+
18
+ _Most_ of their functionality is implemented in the C bindings, particularly
19
+ anything that should be moderately performant.
20
+
21
+ By default, snow-math uses 64-bit native floats as its underlying type. So, a
22
+ Vec3 is literally a `doube[3]` (or a `vec3_t` in C). If you want it to use
23
+ 32-bit floats, simply pass the `--use-float` option to gem when installing it.
24
+ This will cause the bindings to be compiled using floats instead of doubles.
25
+ Like so:
26
+
27
+ $ gem install snow-math -- --use-float
28
+
29
+ If you prefer shorter command-line options, `-F` is a synonym for `--use-float`.
30
+
31
+
32
+ ## Usage
33
+
34
+ In your Ruby scripts, you just need to `require 'snow-math'` and all of the
35
+ library will be pulled in _with the exception of `Fiddle::Pointer` support_.
36
+ To include the Fiddle support, you'll also need to `require 'snow-math/ptr'`.
37
+ This is to avoid dragging the entirety of Fiddle into your code when you're not
38
+ using it.
39
+
40
+ Because it's difficult to produce useful documentation for these bindings, this
41
+ is a brief outline of the classes and their functions in Ruby, sans function
42
+ bodies. Where a description of the functions is missing, the functions do what
43
+ they say on the tin.
44
+
45
+ ### Notes
46
+
47
+ #### Outputs
48
+
49
+ Also, keep in mind that for any function provides an output argument, that
50
+ argument is optional. If output is non-nil, the function will must write its
51
+ the result of its operation to the output object.
52
+
53
+ When nil, the function will always return a new object. Providing an output
54
+ argument can be helpful when you want to avoid some unnecessary allocations.
55
+
56
+ Combined with the array types, you can either maintain a pool of 3D math objects
57
+ or use it to avoid cache misses (though right now the array objects are not the
58
+ most-optimized as they allocate a wrapper object per `fetch` -- something to
59
+ keep in mind).
60
+
61
+ In all cases where an output is provided, output may be the the object the
62
+ function is called on. So, for example, `vec.negate(vec)` is perfectly valid.
63
+
64
+
65
+ #### Shared by All Types
66
+
67
+ All types share the following functions. These are not included in the class
68
+ bodies below except where their behaviour is notably different.
69
+
70
+
71
+ - `fetch(index)` and `store(index, value)` - To get and set values at the given
72
+ component indices. For typed arrays, index is an array index. These do
73
+ bounds-checking. They are always aliased as `[]` and `[]=` respectively.
74
+ Typically, there are also simpler XYZW components for vectors and
75
+ quaternions. These behave a little differently for typed arrays, which you
76
+ can read about in their section below.
77
+
78
+ - `address` - Returns the memory address of the object's first component.
79
+
80
+ - `size` - Returns the size in bytes of the object in memory, not counting any
81
+ overhead introduced by Ruby. This varies depending on whether the gem was
82
+ built using floats or doubles. For typed arrays, this is the size of all
83
+ elements combined. So, a 16-length Mat4Array using doubles is 2048 bytes in
84
+ size, whereas a single Vec3 is 24 bytes.
85
+
86
+ - `length` - Returns the length in components of the object (3 for Vec3, 4 for
87
+ Vec4 and Quat, and 16 for Mat4). The result of this function should be
88
+ obvious for each type.
89
+
90
+ - `map(&block)` and `map` - In the first form, yields each component of an
91
+ object to the block and returns an object of the same type with the results.
92
+ In the second form, returns an Enumerator.
93
+
94
+ - `map!(&block)` and `map!` - Same as the above, but operates on self rather
95
+ than creating a new object.
96
+
97
+ - `each(&object)` and `each` - Does what you think it does. Second form returns
98
+ an Enumerator.
99
+
100
+ - `to_a` - Returns an array of all components in the given object.
101
+
102
+ - `to_ptr` - You have to `require 'snow-math/ptr'` for this. Returns a new
103
+ `Fiddle::Pointer` pointing to the object's address.
104
+
105
+ - `to_s` - Converts the object to a string that looks more or less like
106
+ `"{ fetch(0), fetch(1), ..., fetch(length - 1) }"`.
107
+
108
+
109
+ #### Swizzling
110
+
111
+ Vectors and quaternions generate swizzle methods on first use. So, by calling
112
+ `some_vector.zyx`, the some_vector's class, will generate a swizzle function
113
+ that returns a new Vec3 with components Z, Y, and X of the original vector, in
114
+ that order. The components you can use for swizzling on each type are fairly
115
+ obvious but are as follows:
116
+
117
+ - __Vec3__
118
+ Components: X, Y, and Z.
119
+ Swizzling three components returns a Vec3.
120
+ Swizzling four components returns a Vec4.
121
+
122
+ - __Vec4__
123
+ Components: X, Y, Z, and W.
124
+ Swizzling three components returns a Vec3.
125
+ Swizzling four components returns a Vec4.
126
+
127
+ - __Quat__
128
+ Components: X, Y, Z, and W.
129
+ Swizzling three components returns a Vec3.
130
+ Swizzling four components returns a Quat.
131
+
132
+
133
+ ### Types
134
+
135
+ #### Snow::Vec3
136
+
137
+ class Snow::Vec3
138
+
139
+ def self.new() -> Vec3[0, 0, 0]
140
+ def self.new(x, y, z) -> Vec3[x, y, z]
141
+ def self.new(other: Vec3 | Vec4 | Quat) -> Vec3[other.x, other.y, other.z]
142
+ Aliased as :[], so you can use Vec3[0, 1, 2] to call Vec3.new(0, 1, 2).
143
+
144
+ self == rhs
145
+ Compares whether two Vec3s are equivalent. rhs may also be a Quat or Vec4,
146
+ in which case the first three components of either will be compared with
147
+ self.
148
+
149
+ def set() -> self [no-op]
150
+ def set(x, y, z) -> self
151
+ def set(other) -> self
152
+ Set takes the same arguments as self.new(...) and will call the same initialize
153
+ function as new(). If no arguments are provided to set, it does nothing.
154
+
155
+ def copy(output = nil) -> new vec3 or output
156
+ If output is nil, this is equivalent to calling o.dup or o.class.new(o).
157
+ With an output, the method copies self's components to other. For the most
158
+ part, you probably only want to use this with an output.
159
+
160
+ def inverse(output = nil) -> new vec3 or output
161
+ def inverse! -> self
162
+ Returns a vector whose components are the multiplicative inverse of the
163
+ vector's components.
164
+ Aliased as :~
165
+
166
+ def negate(output = nil) -> new vec3 or output
167
+ def negate! -> self
168
+ Returns a vector whose components are the negated form of the vector's
169
+ components. Beware of -0.0 here.
170
+ Aliased as :-@
171
+
172
+ def normalize(output = nil) -> new vec3 or output
173
+ def normalize!() -> self
174
+
175
+ def cross_product(rhs, output = nil) -> new vec3 or output
176
+ def cross_product!(rhs) -> self
177
+
178
+ def multiply_vec3(rhs, output = nil) -> new vec3 or output
179
+ Multiplies both vector's components together and returns the result.
180
+
181
+ def multiply(vec3, output = nil) -> same as multiply_vec3
182
+ def multiply(scalar, output = nil) -> same as scale
183
+ def multiply!(rhs) -> same as multiply(rhs, self)
184
+ Non-mutable form aliased as :*
185
+
186
+ def add(rhs, output = nil) -> new vec3 or output
187
+ def add!(rhs)
188
+ Aliased as :+
189
+
190
+ def subtract(rhs, output = nil) -> new vec3 or output
191
+ def subtract!(rhs) -> self
192
+ Aliased as :-
193
+
194
+ def dot_product(rhs) -> Float
195
+ Aliased as :**
196
+
197
+ def magnitude_squared -> Float
198
+ def magnitude -> Float
199
+ Returns the squared magnitude and the magnitude, respectively. To give you
200
+ an idea of the difference, magnitude == Math.sqrt(magnitude_squared). So
201
+ if you don't need the exact magnitude and only want to compare the magnitude
202
+ of two things, you can skip a call to sqrt and use the squared magnitude.
203
+
204
+ def scale(scalar, output = nil) -> new vec3 or output
205
+ def divide(scalar, output = nil) -> new vec3 or output
206
+ Multiplies or divides all components of the vector by a scalar. In the case
207
+ of divide, a scalar of 0 is undefined behaviour.
208
+ divide is aliased as :/
209
+
210
+ def size -> size in bytes
211
+ def length -> length in floats
212
+ size is either 24 or 12, depending on whether the gem was built to use
213
+ floats or doubles. length is always 3.
214
+
215
+ def x
216
+ def x=(new_x)
217
+ Same as fetch(0) and store(0, new_x) respectively
218
+
219
+ def y
220
+ def y=(new_y)
221
+ Same as fetch(1) and store(1, new_y) respectively
222
+
223
+ def z
224
+ def z=(new_z)
225
+ Same as fetch(2) and store(2, new_z) respectively
226
+
227
+ end
228
+
229
+
230
+
231
+ #### Snow::Vec4
232
+
233
+ Vec4 is fundamentally the same as Vec3, except it lacks a `cross_product`
234
+ function, has four components, and provides a `w` accessor for the fourth
235
+ component. In addition, it is at times interchangeable with Quat.
236
+
237
+ class Snow::Vec4
238
+
239
+ def self.new() -> Vec4[0, 0, 0, 1]
240
+ def self.new(x, y, z, w = 1) -> Vec4[x, y, z, w]
241
+ def self.new(other: Vec3 | Vec4 | Quat) -> Vec4[other.x, other.y, other.z, other.w | 1]
242
+ Aliased as :[], so you can use Vec4[0, 1, 2, 3] to call Vec4.new(0, 1, 2, 3).
243
+ When calling Vec4.new and supplying a Vec3 to copy from, the fourth component,
244
+ w, will be set to 1.
245
+
246
+ self == rhs
247
+ Compares whether two Vec4s are equivalent. rhs may also be a Quat.
248
+
249
+ def set() -> self [no-op]
250
+ def set(x, y, z, w = 1) -> self
251
+ def set(other) -> self
252
+ Set takes the same arguments as self.new(...) and will call the same initialize
253
+ function as new(). If no arguments are provided to set, it does nothing.
254
+
255
+ def copy(output = nil) -> new vec4 or output
256
+ If output is nil, this is equivalent to calling o.dup or o.class.new(o).
257
+ With an output, the method copies self's components to other. For the most
258
+ part, you probably only want to use this with an output.
259
+
260
+ def inverse(output = nil) -> new vec4 or output
261
+ def inverse! -> self
262
+ Returns a vector whose components are the multiplicative inverse of the
263
+ vector's components.
264
+
265
+ def negate(output = nil) -> new vec4 or output
266
+ def negate! -> self
267
+ Returns a vector whose components are the negated form of the vector's
268
+ components. Beware of -0.0 here.
269
+
270
+ def normalize(output = nil) -> new vec4 or output
271
+ def normalize!() -> self
272
+
273
+ def multiply_vec4(rhs, output = nil) -> new vec4 or output
274
+ def multiply_vec4!(rhs) -> self
275
+ Multiplies both vector's components together and returns the result.
276
+
277
+ def multiply(vec4, output = nil) -> same as multiply_vec4
278
+ def multiply(numeric, output = nil) -> same as scale
279
+ def multiply!(rhs) -> same as multiply(rhs, self)
280
+ Aliased as :*
281
+
282
+ def add(rhs, output = nil) -> new vec4 or output
283
+ def add!(rhs)
284
+
285
+ def subtract(rhs, output = nil) -> new vec4 or output
286
+ def subtract!(rhs) -> self
287
+
288
+ def dot_product(rhs) -> Float
289
+
290
+ def magnitude_squared -> Float
291
+ def magnitude -> Float
292
+ Returns the squared magnitude and the magnitude, respectively. To give you
293
+ an idea of the difference, magnitude == Math.sqrt(magnitude_squared). So
294
+ if you don't need the exact magnitude and only want to compare the magnitude
295
+ of two things, you can skip a call to sqrt and use the squared magnitude.
296
+
297
+ def scale(scalar, output = nil) -> new vec4 or output
298
+ def divide(scalar, output = nil) -> new vec4 or output
299
+ Multiplies or divides all components of the vector by a scalar. In the case
300
+ of divide, a scalar of 0 is undefined behaviour.
301
+
302
+ def size -> size in bytes
303
+ def length -> length in floats
304
+ size is either 32 or 16. depending on whether the gem was built to use
305
+ floats or doubles. length is always 4.
306
+
307
+ def x
308
+ def x=(new_x)
309
+ Same as fetch(0) and store(0, new_x) respectively
310
+
311
+ def y
312
+ def y=(new_y)
313
+ Same as fetch(1) and store(1, new_y) respectively
314
+
315
+ def z
316
+ def z=(new_z)
317
+ Same as fetch(2) and store(2, new_z) respectively
318
+
319
+ def w
320
+ def w=(new_w)
321
+ Same as fetch(3) and store(3, new_w) respectively
322
+
323
+ end
324
+
325
+
326
+
327
+ #### Snow::Quat
328
+
329
+ Quat is functionally similar to Vec4, except it provides some functions specific
330
+ to quaternions. Why these aren't just part of Vec4 is a mystery for the ages
331
+ and an attempt to make code more readable.
332
+
333
+ class Snow::Quat
334
+
335
+ def self.new() -> Quat[0, 0, 0, 1]
336
+ def self.new(x, y, z, w = 1) -> Quat[x, y, z, w]
337
+ def self.new(Mat4) -> Quat from Mat4
338
+ def self.new(other: Vec3 | Quat | Quat) -> Quat[other.x, other.y, other.z, other.w | 1]
339
+ Aliased as :[], so you can use Quat[0, 1, 2, 3] to call Quat.new(0, 1, 2, 3).
340
+ When calling Quat.new and supplying a Vec3 to copy from, the fourth component,
341
+ w, will be set to 1. If provided a Mat4, it will be converted to a Quat. Without
342
+ arguments, Quat.new will return an identity quaternion.
343
+
344
+ self == rhs
345
+ Compares whether two Quats are equivalent. rhs may be either a Quat or
346
+ Vec4.
347
+
348
+ def set() -> self [no-op]
349
+ def set(x, y, z, w = 1) -> self
350
+ def set(Mat4) -> self
351
+ def set(other) -> self
352
+ This takes the same arguments as self.new and in fact just calls the Quat's
353
+ initializer with the new arguments. The only difference is that calling set()
354
+ without arguments will not set this quaternion to the identity quaternion,
355
+ because the allocator is the one responsible for that. (To do that, use
356
+ load_identity)
357
+
358
+ load_identity() -> self
359
+ Resets self to the identity quaternion.
360
+
361
+ def copy(output = nil) -> new quat or output
362
+ If output is nil, this is equivalent to calling o.dup or o.class.new(o).
363
+ With an output, the method copies self's components to other. For the most
364
+ part, you probably only want to use this with an output.
365
+
366
+ def inverse(output = nil) -> new quat or output
367
+ def inverse! -> self
368
+ Returns the inverse of this quaternion (or writes the inverse to an output
369
+ or itself). This is not the same as a vector's inverse -- keep that in mind.
370
+
371
+ def negate(output = nil) -> new quat or output
372
+ def negate! -> self
373
+ Returns a quaternion whose components are the negated form of the vector's
374
+ components. Beware of -0.0 here. This is the same as negating a vector.
375
+
376
+ def normalize(output = nil) -> new quat or output
377
+ def normalize!() -> self
378
+
379
+ def multiply_quat(rhs: Quat, output = nil) -> new quat or output
380
+ def multiply!(rhs: Quat) -> self
381
+ The first form, multiply_quat, multiplies two quaternions and returns the
382
+ resulting quaternion. The second form, multiply!, is the same as calling
383
+ multiply_quat(rhs, self).
384
+
385
+ def mutliply_vec3(rhs: Vec3, output = nil) -> new vec3 or output
386
+ Multiplies a vec3 by a quat and returns the resulting vec3.
387
+
388
+ def multiply(vec3, output = nil) -> new vec3 or output
389
+ def multiply(quat, output = nil) -> new quat or output
390
+ def multiply(numeric, output = nil) -> new quat or output
391
+ In its first form, it's the same as #multiply_vec3. In its second, it's the
392
+ same as #multiply_quat. In its third, it's the same as #scale.
393
+
394
+ def add(rhs, output = nil) -> new quat or output
395
+ def add!(rhs)
396
+ Same as Vec4#add and Vec4#add!.
397
+
398
+ def subtract(rhs, output = nil) -> new quat or output
399
+ def subtract!(rhs) -> self
400
+ Same as Vec4#subtract and Vec4#subtract!.
401
+
402
+ def dot_product(rhs) -> Float
403
+ Same as Vec4#dot_product.
404
+
405
+ def magnitude_squared -> Float
406
+ def magnitude -> Float
407
+ Returns the squared magnitude and the magnitude, respectively. To give you
408
+ an idea of the difference, magnitude == Math.sqrt(magnitude_squared). So
409
+ if you don't need the exact magnitude and only want to compare the magnitude
410
+ of two things, you can skip a call to sqrt and use the squared magnitude.
411
+
412
+ def scale(scalar, output = nil) -> new quat or output
413
+ def divide(scalar, output = nil) -> new quat or output
414
+ Multiplies or divides all components of the quaternion by a scalar. In the
415
+ case of divide, a scalar of 0 is undefined behaviour.
416
+
417
+ def size -> size in bytes
418
+ def length -> length in floats
419
+ size is either 32 or 16. depending on whether the gem was built to use
420
+ floats or doubles. length is always 4.
421
+
422
+ def x
423
+ def x=(new_x)
424
+ Same as fetch(0) and store(0, new_x) respectively
425
+
426
+ def y
427
+ def y=(new_y)
428
+ Same as fetch(1) and store(1, new_y) respectively
429
+
430
+ def z
431
+ def z=(new_z)
432
+ Same as fetch(2) and store(2, new_z) respectively
433
+
434
+ def w
435
+ def w=(new_w)
436
+ Same as fetch(3) and store(3, new_w) respectively
437
+
438
+ end
439
+
440
+
441
+
442
+ #### Snow::Mat4
443
+
444
+ class Snow::Mat4
445
+
446
+ def self.new() -> identity mat4
447
+ def self.new(m1, m2, m3, ..., m16) -> mat4 with the given components
448
+ def self.new([Vec4, Vec4, Vec4, Vec4]) -> mat4 with rows defined by the given Vec4s
449
+ def self.new(Quat) -> Mat4 from Quat
450
+ def self.new(Mat4) -> copy of the given Mat4
451
+ Aliased as `[]`, so you can use Mat4[...] to create a new Mat4.
452
+
453
+ def self.translation(x, y, z, output = nil) -> new mat4 or output
454
+ def self.translation(Vec3, output = nil) -> new mat4 or output
455
+ Returns a translation matrix.
456
+
457
+ def self.angle_axis(angle_degrees, axis: Vec3, output = nil) -> new mat4 or output
458
+ Returns a new rotation matrix for the given angle and axis. The angle is in
459
+ degrees. This might offend some people, but I assure you, your sanity will
460
+ be preserved by doing this.
461
+
462
+ def self.frustum(left, right, bottom, top, z_near, z_far, output = nil) -> new mat4 or output
463
+ def self.orthographic(left, right, bottom, top, z_near, z_far, output = nil) -> new mat4 or output
464
+ def self.perspective(fov_y, aspect, z_near, z_far, output = nil) -> new mat4 or output
465
+ Returns the given kinds of projection matrices. In the case of perspective,
466
+ fov_y is specified in degrees. Again, your sanity will thank you.
467
+
468
+ def self.look_at(eye: Vec3, center: Vec3, up: Vec3, output = nil) -> new mat4 or output
469
+ Returns a look-at matrix.
470
+
471
+ def set(...)
472
+ Same variations and arguments as self.new(...)
473
+
474
+ def load_identity() -> self
475
+ Resets self to the identity matrix.
476
+
477
+ def copy(output = nil) -> new mat4 or output
478
+ Copies self to the given output matrix.
479
+
480
+ def transpose(output = nil) -> new mat4 or output
481
+ def transpose!() -> self
482
+
483
+ def inverse_orthogonal(output = nil) -> new mat4 or output
484
+ def inverse_affine(output = nil) -> new mat4 or output on success, nil on failure
485
+ def inverse_general(output = nil) -> new mat4 or output on success, nil on failure
486
+ def inverse_orthogonal!() -> self
487
+ def inverse_affine!() -> self on success, nil on failure
488
+ def inverse_general!() -> self on success, nil on failure
489
+
490
+ def translate(x, y, z, output = nil) -> new mat4 or output
491
+ def translate(vec3, output = nil) -> new mat4 or output
492
+ def translate!(x, y, z) -> self
493
+ def translate!(vec3) -> self
494
+ Essentially multiplies this matrix by a translation matrix with the given
495
+ translation and returns it.
496
+
497
+ def multiply_mat4(rhs, output = nil) -> new mat4 or output
498
+ def multiply_mat4!(rhs) -> self
499
+ Multiplies this and the rhs matrix and returns the result.
500
+
501
+ def multiply_vec4(rhs, output = nil) -> new vec4 or output
502
+ Transforms a vec4 by the matrix and returns the result.
503
+
504
+ def multiply_vec3(rhs, output = nil) -> new vec3 or output
505
+ def rotate_vec3(rhs, output = nil) -> new vec3 or output
506
+ In the first form, transforms a vec3 by the matrix and returns the result.
507
+ In the second form, rotates a vec3 by the matrix, ignoring any translation,
508
+ and returns the result.
509
+
510
+ def inverse_rotate_vec3(vec3, output = nil) -> new vec3 or output
511
+ Essentially just a convenience function.
512
+
513
+ def multiply(mat4, output = nil) -> same as mutliply_mat4
514
+ def multiply(vec3, output = nil) -> same as mutliply_vec3
515
+ def multiply(numeric, output = nil) -> same as scale(N, N, N, output)
516
+ def multiply!(rhs) -> same as multiply(rhs, self)
517
+ The fourth form, multiply!, will fail if attempting to multiply a vec3.
518
+ Aliased as `*`
519
+
520
+ def adjoint(output = nil) -> new mat4 or output
521
+ def adjoint!() -> new mat4 or output
522
+
523
+ def determinant -> Float
524
+
525
+ def scale(x, y, z, output = nil) -> new mat4 or output
526
+ def scale!(x, y, z) -> new mat4 or output
527
+ Returns a matrix with its inner 3x3 matrix's rows scaled by the given
528
+ components.
529
+
530
+ def set_row3, set_column3, set_row4, set_column4(index, V) -> self
531
+ V is a vector with the number of components in the function name. Sets the
532
+ Mat4's row or column to the components of the given vec3 or vec4.
533
+
534
+ def get_row3, get_column3, get_row4, get_column4(index, output = nil) -> row/column
535
+ Returns a vector with the number of components as specific by the name for
536
+ the given row or column in the Mat4.
537
+
538
+ end
539
+
540
+
541
+
542
+ #### Snow::Vec3Array, Snow::Vec4Array, Snow::QuatArray, Snow::Mat4Array
543
+
544
+ All typed arrays have the same interface and differ only in the kind of object
545
+ they contain. As such, this applies to all typed arrays.
546
+
547
+ class Snow::Vec3Array, Snow::Vec4Array, Snow::QuatArray, Snow::Mat4Array
548
+
549
+ def self.new(length) -> new array
550
+ def self.new(array) -> copy of array
551
+ Aliased as `[]`, so you can create an array, for example, by writing
552
+ `Vec3Array[16]`. The length provided must be greater than zero, otherwise
553
+ the returned array is nil.
554
+
555
+ Array elements are always uninitialized on allocation, so they will often
556
+ contain garbage values. It is your responsibility to initialize them as
557
+ needed.
558
+
559
+ def fetch(index) -> object of array element type
560
+ Returns an object that references the array's internal data. Manipulating
561
+ this object manipulates the data in the array -- it is not simply a copy of
562
+ the array's data. The returned object is cached, so subsequent calls to
563
+ fetch will return the same object (unless resized, in which case the cache
564
+ is destroyed and objects previously bound to the array are invalid -- use
565
+ of those objects following a resize is considered undefined behaviour).
566
+
567
+ def store(index, value) -> value
568
+ Copies a value object's data into the array's data. If the value object is
569
+ already part of the array -- that is, it was created using the array's
570
+ fetch function, this is a no-op.
571
+
572
+ def resize!(new_length) -> self
573
+ def resize(new_length) -> new array
574
+ Resizes the array and returns the value. In the first form, the underlying
575
+ buffer for the array is resized. In the second form, a new array is
576
+ allocated and returned.
577
+
578
+ end
579
+
580
+
581
+
582
+ ## License
583
+
584
+ snow-math, like most of my gems, is licensed under a simplified BSD license.
585
+ And like most of my gems, I will say as usual that if this is a problem for
586
+ you, please contact me. The license is reproduced here:
587
+
588
+ Copyright (c) 2013, Noel Raymond Cower <ncower@gmail.com>.
589
+ All rights reserved.
590
+
591
+ Redistribution and use in source and binary forms, with or without
592
+ modification, are permitted provided that the following conditions are met:
593
+
594
+ 1. Redistributions of source code must retain the above copyright notice, this
595
+ list of conditions and the following disclaimer.
596
+ 2. Redistributions in binary form must reproduce the above copyright notice,
597
+ this list of conditions and the following disclaimer in the documentation
598
+ and/or other materials provided with the distribution.
599
+
600
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
601
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
602
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
603
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
604
+ ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
605
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
606
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
607
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
608
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
609
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
610
+
611
+ The views and conclusions contained in the software and documentation are those
612
+ of the authors and should not be interpreted as representing official policies,
613
+ either expressed or implied, of the FreeBSD Project.
data/ext/extconf.rb CHANGED
@@ -8,6 +8,14 @@ require 'mkmf'
8
8
  # Compile as C99
9
9
  $CFLAGS += " -std=c99"
10
10
 
11
+ if ARGV.include?("--debug") || ARGV.include?("-D")
12
+ $CFLAGS += " -g"
13
+ puts "Building extension source in debug mode"
14
+ else
15
+ $CFLAGS += " -O3 -fno-fast-math -fno-strict-aliasing"
16
+ puts "Building extension source in release mode"
17
+ end
18
+
11
19
  if ARGV.include?("--use-float") || ARGV.include?("-F")
12
20
  $CFLAGS += " -DUSE_FLOAT"
13
21
  puts "Using float as base type"
@@ -275,6 +275,7 @@ static VALUE sm_mathtype_array_length(VALUE sm_self)
275
275
  rb_define_singleton_method(klass_, "new", sm_##ELEM_TYPE##_array_new, 1); \
276
276
  rb_define_method(klass_, "fetch", sm_##ELEM_TYPE##_array_fetch, 1); \
277
277
  rb_define_method(klass_, "store", sm_##ELEM_TYPE##_array_store, 2); \
278
+ rb_define_method(klass_, "resize!", sm_##ELEM_TYPE##_array_resize, 1); \
278
279
  rb_define_method(klass_, "size", sm_##ELEM_TYPE##_array_size, 0); \
279
280
  rb_define_method(klass_, "length", sm_mathtype_array_length, 0); \
280
281
  rb_define_method(klass_, "address", sm_get_address, 0); \
@@ -283,16 +284,16 @@ static VALUE sm_mathtype_array_length(VALUE sm_self)
283
284
  #define DEF_SM_ARR_TYPE(ELEM_TYPE) \
284
285
  static VALUE SM_ARR_KLASS(ELEM_TYPE) = Qnil; \
285
286
  \
286
- static VALUE sm_##ELEM_TYPE##_array_new(VALUE sm_self, VALUE sm_length) \
287
+ static VALUE sm_##ELEM_TYPE##_array_new(VALUE sm_self, VALUE sm_length_or_copy) \
287
288
  { \
288
- int length = 0; \
289
+ size_t length = 0; \
289
290
  ELEM_TYPE##_t *arr; \
290
291
  VALUE sm_type_array; \
291
292
  int copy_array = 0; \
292
- if ((copy_array = SM_IS_A(sm_length, ELEM_TYPE##_array))) { \
293
- length = NUM2INT(sm_mathtype_array_length(sm_length)); \
293
+ if ((copy_array = SM_IS_A(sm_length_or_copy, ELEM_TYPE##_array))) { \
294
+ length = NUM2SIZET(sm_mathtype_array_length(sm_length_or_copy)); \
294
295
  } else { \
295
- length = NUM2INT(sm_length); \
296
+ length = NUM2SIZET(sm_length_or_copy); \
296
297
  } \
297
298
  if (length <= 0) { \
298
299
  return Qnil; \
@@ -300,25 +301,34 @@ static VALUE sm_##ELEM_TYPE##_array_new(VALUE sm_self, VALUE sm_length)
300
301
  arr = ALLOC_N(ELEM_TYPE##_t, length); \
301
302
  if (copy_array) { \
302
303
  const ELEM_TYPE##_t *source; \
303
- Data_Get_Struct(sm_length, ELEM_TYPE##_t, source); \
304
+ Data_Get_Struct(sm_length_or_copy, ELEM_TYPE##_t, source); \
304
305
  MEMCPY(arr, source, ELEM_TYPE##_t, length); \
305
- sm_length = sm_mathtype_array_length(sm_length); \
306
+ sm_length_or_copy = sm_mathtype_array_length(sm_length_or_copy); \
306
307
  } \
307
308
  sm_type_array = Data_Wrap_Struct(sm_self, 0, free, arr); \
308
- rb_ivar_set(sm_type_array, kRB_IVAR_MATHARRAY_LENGTH, sm_length); \
309
+ rb_ivar_set(sm_type_array, kRB_IVAR_MATHARRAY_LENGTH, sm_length_or_copy); \
309
310
  rb_obj_call_init(sm_type_array, 0, 0); \
310
311
  return sm_type_array; \
311
312
  } \
312
313
  \
314
+ static VALUE sm_##ELEM_TYPE##_array_resize(VALUE sm_self, VALUE sm_new_length) \
315
+ { \
316
+ size_t new_length; \
317
+ new_length = NUM2SIZET(sm_new_length); \
318
+ REALLOC_N(RDATA(sm_self)->data, ELEM_TYPE##_t, new_length); \
319
+ rb_ivar_set(sm_self, kRB_IVAR_MATHARRAY_LENGTH, sm_new_length); \
320
+ return sm_self; \
321
+ } \
322
+ \
313
323
  static VALUE sm_##ELEM_TYPE##_array_fetch(VALUE sm_self, VALUE sm_index) \
314
324
  { \
315
325
  ELEM_TYPE##_t *arr; \
316
- int length = NUM2INT(sm_mathtype_array_length(sm_self)); \
317
- int index = NUM2INT(sm_index); \
326
+ size_t length = NUM2SIZET(sm_mathtype_array_length(sm_self)); \
327
+ size_t index = NUM2SIZET(sm_index); \
318
328
  VALUE sm_inner; \
319
329
  if (index < 0 || index >= length) { \
320
330
  rb_raise(rb_eRangeError, \
321
- "Index %d out of bounds for array with length %d", \
331
+ "Index %zu out of bounds for array with length %zu", \
322
332
  index, length); \
323
333
  } \
324
334
  Data_Get_Struct(sm_self, ELEM_TYPE##_t, arr); \
@@ -331,11 +341,11 @@ static VALUE sm_##ELEM_TYPE##_array_store(VALUE sm_self, VALUE sm_index, VALUE s
331
341
  { \
332
342
  ELEM_TYPE##_t *arr; \
333
343
  ELEM_TYPE##_t *value; \
334
- int length = NUM2INT(sm_mathtype_array_length(sm_self)); \
335
- int index = NUM2INT(sm_index); \
344
+ size_t length = NUM2SIZET(sm_mathtype_array_length(sm_self)); \
345
+ size_t index = NUM2SIZET(sm_index); \
336
346
  if (index < 0 || index >= length) { \
337
347
  rb_raise(rb_eRangeError, \
338
- "Index %d out of bounds for array with length %d", \
348
+ "Index %zu out of bounds for array with length %zu", \
339
349
  index, length); \
340
350
  } else if (!SM_IS_A(sm_value, ELEM_TYPE)) { \
341
351
  rb_raise(rb_eTypeError, \
@@ -354,7 +364,7 @@ static VALUE sm_##ELEM_TYPE##_array_store(VALUE sm_self, VALUE sm_index, VALUE s
354
364
  \
355
365
  static VALUE sm_##ELEM_TYPE##_array_size(VALUE sm_self) \
356
366
  { \
357
- int length = NUM2INT(sm_mathtype_array_length(sm_self)); \
367
+ size_t length = NUM2SIZET(sm_mathtype_array_length(sm_self)); \
358
368
  return SIZET2NUM(length * sizeof(ELEM_TYPE##_t)); \
359
369
  }
360
370
 
@@ -7,6 +7,7 @@ module Snow
7
7
  if const_defined?(klass_sym)
8
8
  const_get(klass_sym).class_exec {
9
9
  alias_method :__fetch__, :fetch
10
+ alias_method :__resize__!, :resize!
10
11
  alias_method :__array_cache_initialize__, :initialize
11
12
 
12
13
  def initialize(*args)
@@ -19,6 +20,21 @@ module Snow
19
20
  end
20
21
 
21
22
  alias_method :[], :fetch
23
+
24
+ def resize!(new_length)
25
+ @__cache__ = []
26
+ __resize__!(new_length)
27
+ end
28
+
29
+ def resize(new_length)
30
+ arr = self.class.new(new_length)
31
+ self_length = self.length
32
+ (0 ... (self_length < new_length ? self_length : new_length)).each {
33
+ |index|
34
+ arr.store(index, self.fetch(index))
35
+ }
36
+ return arr
37
+ end
22
38
  }
23
39
  end
24
40
  }
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: snow-math
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Noel Raymond Cower
@@ -15,7 +15,9 @@ email: ncower@gmail.com
15
15
  executables: []
16
16
  extensions:
17
17
  - ext/extconf.rb
18
- extra_rdoc_files: []
18
+ extra_rdoc_files:
19
+ - README.md
20
+ - COPYING
19
21
  files:
20
22
  - lib/snow-math/array_cache.rb
21
23
  - lib/snow-math/inspect.rb
@@ -39,6 +41,8 @@ files:
39
41
  - ext/snow-math/vec4.c
40
42
  - ext/snow-math/maths_local.h
41
43
  - ext/extconf.rb
44
+ - COPYING
45
+ - README.md
42
46
  homepage: https://github.com/nilium/ruby-snowmath
43
47
  licenses:
44
48
  - Simplified BSD
@@ -69,4 +73,4 @@ signing_key:
69
73
  specification_version: 4
70
74
  summary: Snow Math Types
71
75
  test_files: []
72
- has_rdoc:
76
+ has_rdoc: true