snow-math 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
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