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 +4 -4
- data/COPYING +26 -0
- data/README.md +613 -0
- data/ext/extconf.rb +8 -0
- data/ext/snow-math/snow-math.c +25 -15
- data/lib/snow-math/array_cache.rb +16 -0
- metadata +7 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 46e87b537dadcdf09df7d18126a3fdd43bae0269
|
4
|
+
data.tar.gz: 48ac51001b1c24bf65e0916a2d8253745bf61680
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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"
|
data/ext/snow-math/snow-math.c
CHANGED
@@ -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
|
287
|
+
static VALUE sm_##ELEM_TYPE##_array_new(VALUE sm_self, VALUE sm_length_or_copy) \
|
287
288
|
{ \
|
288
|
-
|
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(
|
293
|
-
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 =
|
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(
|
304
|
+
Data_Get_Struct(sm_length_or_copy, ELEM_TYPE##_t, source); \
|
304
305
|
MEMCPY(arr, source, ELEM_TYPE##_t, length); \
|
305
|
-
|
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,
|
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
|
-
|
317
|
-
|
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 %
|
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
|
-
|
335
|
-
|
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 %
|
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
|
-
|
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.
|
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
|