propane 0.3.0.pre-java
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 +7 -0
- data/.gitignore +21 -0
- data/.mvn/extensions.xml +8 -0
- data/.mvn/wrapper/maven-wrapper.properties +1 -0
- data/.travis.yml +9 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +69 -0
- data/Rakefile +59 -0
- data/VERSION.txt +4 -0
- data/bin/propane +8 -0
- data/examples/complete/Rakefile +32 -0
- data/examples/complete/data/Texture01.jpg +0 -0
- data/examples/complete/data/Texture02.jpg +0 -0
- data/examples/complete/data/Univers45.vlw +0 -0
- data/examples/complete/data/displaceFrag.glsl +8 -0
- data/examples/complete/data/displaceVert.glsl +201 -0
- data/examples/complete/glsl_heightmap_noise.rb +121 -0
- data/examples/complete/kinetic_type.rb +79 -0
- data/examples/regular/Rakefile +30 -0
- data/examples/regular/arcball_box.rb +36 -0
- data/examples/regular/creating_colors.rb +57 -0
- data/examples/regular/elegant_ball.rb +159 -0
- data/examples/regular/flight_patterns.rb +63 -0
- data/examples/regular/grey_circles.rb +28 -0
- data/examples/regular/jwishy.rb +100 -0
- data/examples/regular/letters.rb +42 -0
- data/examples/regular/lib/boundary.rb +38 -0
- data/examples/regular/lib/particle.rb +77 -0
- data/examples/regular/lib/particle_system.rb +111 -0
- data/examples/regular/liquidy.rb +40 -0
- data/examples/regular/mouse_button_demo.rb +34 -0
- data/examples/regular/polyhedrons.rb +248 -0
- data/examples/regular/ribbon_doodle.rb +89 -0
- data/examples/regular/vector_math.rb +36 -0
- data/examples/regular/words.rb +41 -0
- data/lib/PROCESSING_LICENSE.txt +456 -0
- data/lib/export.txt +10 -0
- data/lib/propane.rb +12 -0
- data/lib/propane/app.rb +197 -0
- data/lib/propane/helper_methods.rb +177 -0
- data/lib/propane/helpers/numeric.rb +9 -0
- data/lib/propane/library_loader.rb +117 -0
- data/lib/propane/runner.rb +88 -0
- data/lib/propane/underscorer.rb +19 -0
- data/lib/propane/version.rb +5 -0
- data/library/boids/boids.rb +201 -0
- data/library/control_panel/control_panel.rb +172 -0
- data/pom.rb +113 -0
- data/pom.xml +198 -0
- data/propane.gemspec +28 -0
- data/src/monkstone/ColorUtil.java +67 -0
- data/src/monkstone/MathTool.java +195 -0
- data/src/monkstone/PropaneLibrary.java +47 -0
- data/src/monkstone/core/AbstractLibrary.java +102 -0
- data/src/monkstone/fastmath/Deglut.java +115 -0
- data/src/monkstone/vecmath/AppRender.java +87 -0
- data/src/monkstone/vecmath/JRender.java +56 -0
- data/src/monkstone/vecmath/ShapeRender.java +87 -0
- data/src/monkstone/vecmath/vec2/Vec2.java +670 -0
- data/src/monkstone/vecmath/vec3/Vec3.java +708 -0
- data/test/respond_to_test.rb +208 -0
- data/vendors/Rakefile +48 -0
- metadata +130 -0
@@ -0,0 +1,708 @@
|
|
1
|
+
package monkstone.vecmath.vec3;
|
2
|
+
/*
|
3
|
+
* Copyright (c) 2015-16 Martin Prout
|
4
|
+
*
|
5
|
+
* This library is free software; you can redistribute it and/or
|
6
|
+
* modify it under the terms of the GNU Lesser General Public
|
7
|
+
* License as published by the Free Software Foundation; either
|
8
|
+
* version 2.1 of the License, or (at your option) any later version.
|
9
|
+
*
|
10
|
+
* http://creativecommons.org/licenses/LGPL/2.1/
|
11
|
+
*
|
12
|
+
* This library is distributed in the hope that it will be useful,
|
13
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
15
|
+
* Lesser General Public License for more details.
|
16
|
+
*
|
17
|
+
* You should have received a copy of the GNU Lesser General Public
|
18
|
+
* License along with this library; if not, write to the Free Software
|
19
|
+
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
20
|
+
*/
|
21
|
+
|
22
|
+
import org.jruby.Ruby;
|
23
|
+
import org.jruby.RubyArray;
|
24
|
+
import org.jruby.RubyBoolean;
|
25
|
+
import org.jruby.RubyClass;
|
26
|
+
import org.jruby.RubyObject;
|
27
|
+
import org.jruby.RubySymbol;
|
28
|
+
import org.jruby.runtime.ObjectAllocator;
|
29
|
+
import org.jruby.anno.JRubyClass;
|
30
|
+
import org.jruby.anno.JRubyMethod;
|
31
|
+
import org.jruby.runtime.Arity;
|
32
|
+
import org.jruby.runtime.Block;
|
33
|
+
import org.jruby.runtime.ThreadContext;
|
34
|
+
import org.jruby.runtime.builtin.IRubyObject;
|
35
|
+
import monkstone.vecmath.JRender;
|
36
|
+
import monkstone.vecmath.vec2.Vec2;
|
37
|
+
|
38
|
+
/**
|
39
|
+
*
|
40
|
+
* @author Martin Prout
|
41
|
+
*/
|
42
|
+
@JRubyClass(name = "Vec3D")
|
43
|
+
public final class Vec3 extends RubyObject {
|
44
|
+
|
45
|
+
private static final long serialVersionUID = 4563517343762009867L;
|
46
|
+
|
47
|
+
/**
|
48
|
+
*
|
49
|
+
* @param runtime
|
50
|
+
*/
|
51
|
+
public static void createVec3(final Ruby runtime) {
|
52
|
+
RubyClass vec3Cls = runtime.defineClass("Vec3D", runtime.getObject(), new ObjectAllocator() {
|
53
|
+
@Override
|
54
|
+
public IRubyObject allocate(Ruby runtime, RubyClass rubyClass) {
|
55
|
+
return new Vec3(runtime, rubyClass);
|
56
|
+
}
|
57
|
+
});
|
58
|
+
vec3Cls.defineAnnotatedMethods(Vec3.class);
|
59
|
+
}
|
60
|
+
|
61
|
+
static final double EPSILON = 9.999999747378752e-05; // matches processing.org EPSILON
|
62
|
+
private double jx = 0;
|
63
|
+
private double jy = 0;
|
64
|
+
private double jz = 0;
|
65
|
+
|
66
|
+
/**
|
67
|
+
*
|
68
|
+
* @param context ThreadContext
|
69
|
+
* @param klazz IRubyObject
|
70
|
+
* @param args optional (no args jx = 0, jy = 0, jz = 0) (2 args jz = 0)
|
71
|
+
* @return new Vec3 object (ruby)
|
72
|
+
*/
|
73
|
+
@JRubyMethod(name = "new", meta = true, rest = true)
|
74
|
+
public final static IRubyObject rbNew(ThreadContext context, IRubyObject klazz, IRubyObject[] args) {
|
75
|
+
Vec3 vec = (Vec3) ((RubyClass) klazz).allocate();
|
76
|
+
vec.init(context, args);
|
77
|
+
return vec;
|
78
|
+
}
|
79
|
+
|
80
|
+
/**
|
81
|
+
*
|
82
|
+
* @param runtime Ruby
|
83
|
+
* @param klass RubyClass
|
84
|
+
*/
|
85
|
+
public Vec3(Ruby runtime, RubyClass klass) {
|
86
|
+
super(runtime, klass);
|
87
|
+
}
|
88
|
+
|
89
|
+
void init(ThreadContext context, IRubyObject[] args) {
|
90
|
+
int count = Arity.checkArgumentCount(context.getRuntime(), args, Arity.OPTIONAL.getValue(), 3);
|
91
|
+
if (count >= 2) {
|
92
|
+
jx = (Double) args[0].toJava(Double.class);
|
93
|
+
jy = (Double) args[1].toJava(Double.class);
|
94
|
+
}
|
95
|
+
if (count == 3) {
|
96
|
+
jz = (Double) args[2].toJava(Double.class);
|
97
|
+
}
|
98
|
+
}
|
99
|
+
|
100
|
+
/**
|
101
|
+
*
|
102
|
+
* @param context ThreadContext
|
103
|
+
* @return x IRubyObject
|
104
|
+
*/
|
105
|
+
@JRubyMethod(name = "x")
|
106
|
+
|
107
|
+
public IRubyObject getX(ThreadContext context) {
|
108
|
+
return context.getRuntime().newFloat(jx);
|
109
|
+
}
|
110
|
+
|
111
|
+
/**
|
112
|
+
*
|
113
|
+
* @param context ThreadContext
|
114
|
+
* @return y IRubyObject
|
115
|
+
*/
|
116
|
+
@JRubyMethod(name = "y")
|
117
|
+
|
118
|
+
public IRubyObject getY(ThreadContext context) {
|
119
|
+
return context.getRuntime().newFloat(jy);
|
120
|
+
}
|
121
|
+
|
122
|
+
/**
|
123
|
+
*
|
124
|
+
* @param context ThreadContext
|
125
|
+
* @return z IRubyObject
|
126
|
+
*/
|
127
|
+
@JRubyMethod(name = "z")
|
128
|
+
public IRubyObject getZ(ThreadContext context) {
|
129
|
+
return context.getRuntime().newFloat(jz);
|
130
|
+
}
|
131
|
+
|
132
|
+
/**
|
133
|
+
*
|
134
|
+
* @param context ThreadContext
|
135
|
+
* @param other IRubyObject
|
136
|
+
* @return x IRubyObject
|
137
|
+
*/
|
138
|
+
@JRubyMethod(name = "x=")
|
139
|
+
|
140
|
+
public IRubyObject setX(ThreadContext context, IRubyObject other) {
|
141
|
+
jx = (Double) other.toJava(Double.class);
|
142
|
+
return context.getRuntime().newFloat(jx);
|
143
|
+
}
|
144
|
+
|
145
|
+
/**
|
146
|
+
*
|
147
|
+
* @param context ThreadContext
|
148
|
+
* @param other IRubyObject
|
149
|
+
* @return y IRubyObject
|
150
|
+
*/
|
151
|
+
@JRubyMethod(name = "y=")
|
152
|
+
|
153
|
+
public IRubyObject setY(ThreadContext context, IRubyObject other) {
|
154
|
+
jy = (Double) other.toJava(Double.class);
|
155
|
+
return context.getRuntime().newFloat(jy);
|
156
|
+
}
|
157
|
+
|
158
|
+
/**
|
159
|
+
*
|
160
|
+
* @param context ThreadContext
|
161
|
+
* @param other IRubyObject
|
162
|
+
* @return z IRubyObject
|
163
|
+
*/
|
164
|
+
@JRubyMethod(name = "z=")
|
165
|
+
public IRubyObject setZ(ThreadContext context, IRubyObject other) {
|
166
|
+
jz = (Double) other.toJava(Double.class);
|
167
|
+
return context.getRuntime().newFloat(jz);
|
168
|
+
}
|
169
|
+
|
170
|
+
/**
|
171
|
+
*
|
172
|
+
* @param context ThreadContext
|
173
|
+
* @param key as symbol
|
174
|
+
* @return value float
|
175
|
+
*/
|
176
|
+
@JRubyMethod(name = "[]", required = 1)
|
177
|
+
|
178
|
+
public IRubyObject aref(ThreadContext context, IRubyObject key) {
|
179
|
+
Ruby runtime = context.getRuntime();
|
180
|
+
if (key instanceof RubySymbol) {
|
181
|
+
if (key == RubySymbol.newSymbol(runtime, "x")) {
|
182
|
+
return runtime.newFloat(jx);
|
183
|
+
} else if (key == RubySymbol.newSymbol(runtime, "y")) {
|
184
|
+
return runtime.newFloat(jy);
|
185
|
+
} else if (key == RubySymbol.newSymbol(runtime, "z")) {
|
186
|
+
return runtime.newFloat(jz);
|
187
|
+
} else {
|
188
|
+
throw runtime.newIndexError("invalid key");
|
189
|
+
}
|
190
|
+
} else {
|
191
|
+
throw runtime.newIndexError("invalid key");
|
192
|
+
}
|
193
|
+
}
|
194
|
+
|
195
|
+
/**
|
196
|
+
* @param context ThreadContext
|
197
|
+
* @param key as symbol
|
198
|
+
* @param value as float
|
199
|
+
* @return value float
|
200
|
+
*/
|
201
|
+
@JRubyMethod(name = "[]=")
|
202
|
+
|
203
|
+
public IRubyObject aset(ThreadContext context, IRubyObject key, IRubyObject value) {
|
204
|
+
Ruby runtime = context.getRuntime();
|
205
|
+
if (key instanceof RubySymbol) {
|
206
|
+
if (key == RubySymbol.newSymbol(runtime, "x")) {
|
207
|
+
jx = (Double) value.toJava(Double.class);
|
208
|
+
} else if (key == RubySymbol.newSymbol(runtime, "y")) {
|
209
|
+
jy = (Double) value.toJava(Double.class);
|
210
|
+
} else if (key == RubySymbol.newSymbol(runtime, "z")) {
|
211
|
+
jz = (Double) value.toJava(Double.class);
|
212
|
+
} else {
|
213
|
+
throw runtime.newIndexError("invalid key");
|
214
|
+
}
|
215
|
+
} else {
|
216
|
+
throw runtime.newIndexError("invalid key");
|
217
|
+
}
|
218
|
+
return value;
|
219
|
+
}
|
220
|
+
|
221
|
+
/**
|
222
|
+
*
|
223
|
+
* @param context ThreadContext
|
224
|
+
* @param other IRubyObject
|
225
|
+
* @return distance float
|
226
|
+
*/
|
227
|
+
@JRubyMethod(name = "dist", required = 1)
|
228
|
+
|
229
|
+
public IRubyObject dist(ThreadContext context, IRubyObject other) {
|
230
|
+
Vec3 b = null;
|
231
|
+
if (other instanceof Vec3) {
|
232
|
+
b = (Vec3) other.toJava(Vec3.class);
|
233
|
+
} else {
|
234
|
+
throw context.runtime.newTypeError("argument should be Vec3D");
|
235
|
+
}
|
236
|
+
double result = Math.sqrt((jx - b.jx) * (jx - b.jx) + (jy - b.jy) * (jy - b.jy) + (jz - b.jz) * (jz - b.jz));
|
237
|
+
return context.getRuntime().newFloat(result);
|
238
|
+
}
|
239
|
+
|
240
|
+
/**
|
241
|
+
*
|
242
|
+
* @param context ThreadContext
|
243
|
+
* @param other IRubyObject
|
244
|
+
* @return distance squared float
|
245
|
+
*/
|
246
|
+
@JRubyMethod(name = "dist_squared", required = 1)
|
247
|
+
|
248
|
+
public IRubyObject dist_squared(ThreadContext context, IRubyObject other) {
|
249
|
+
Vec3 b = null;
|
250
|
+
if (other instanceof Vec3) {
|
251
|
+
b = (Vec3) other.toJava(Vec3.class);
|
252
|
+
} else {
|
253
|
+
throw context.runtime.newTypeError("argument should be Vec3D");
|
254
|
+
}
|
255
|
+
double result = (jx - b.jx) * (jx - b.jx) + (jy - b.jy) * (jy - b.jy) + (jz - b.jz) * (jz - b.jz);
|
256
|
+
return context.getRuntime().newFloat(result);
|
257
|
+
}
|
258
|
+
|
259
|
+
/**
|
260
|
+
*
|
261
|
+
*
|
262
|
+
* @param context ThreadContext
|
263
|
+
* @param other IRubyObject
|
264
|
+
* @return cross product IRubyObject
|
265
|
+
*/
|
266
|
+
|
267
|
+
@JRubyMethod(name = "cross", required = 1)
|
268
|
+
|
269
|
+
public IRubyObject cross(ThreadContext context, IRubyObject other) {
|
270
|
+
Ruby runtime = context.getRuntime();
|
271
|
+
Vec3 vec = null;
|
272
|
+
if (other instanceof Vec3) {
|
273
|
+
vec = (Vec3) other.toJava(Vec3.class);
|
274
|
+
} else {
|
275
|
+
throw runtime.newTypeError("argument should be Vec3D");
|
276
|
+
}
|
277
|
+
return Vec3.rbNew(context, other.getMetaClass(), new IRubyObject[]{
|
278
|
+
runtime.newFloat(jy * vec.jz - jz * vec.jy),
|
279
|
+
runtime.newFloat(jz * vec.jx - jx * vec.jz),
|
280
|
+
runtime.newFloat(jx * vec.jy - jy * vec.jx)
|
281
|
+
}
|
282
|
+
);
|
283
|
+
}
|
284
|
+
|
285
|
+
/**
|
286
|
+
*
|
287
|
+
* @param context ThreadContext
|
288
|
+
* @param other IRubyObject
|
289
|
+
* @return dot product IRubyObject
|
290
|
+
*/
|
291
|
+
@JRubyMethod(name = "dot", required = 1)
|
292
|
+
|
293
|
+
public IRubyObject dot(ThreadContext context, IRubyObject other) {
|
294
|
+
Ruby runtime = context.getRuntime();
|
295
|
+
Vec3 b = null;
|
296
|
+
if (other instanceof Vec3) {
|
297
|
+
b = (Vec3) other.toJava(Vec3.class);
|
298
|
+
} else {
|
299
|
+
throw runtime.newTypeError("argument should be Vec3D");
|
300
|
+
}
|
301
|
+
return runtime.newFloat(jx * b.jx + jy * b.jy + jz * b.jz);
|
302
|
+
}
|
303
|
+
|
304
|
+
/**
|
305
|
+
*
|
306
|
+
* @param context ThreadContext
|
307
|
+
* @param other IRubyObject
|
308
|
+
* @return new Vec3 object (ruby)
|
309
|
+
*/
|
310
|
+
@JRubyMethod(name = "+", required = 1)
|
311
|
+
|
312
|
+
public IRubyObject op_add(ThreadContext context, IRubyObject other) {
|
313
|
+
Ruby runtime = context.getRuntime();
|
314
|
+
Vec3 b = (Vec3) other.toJava(Vec3.class);
|
315
|
+
return Vec3.rbNew(context, other.getMetaClass(), new IRubyObject[]{
|
316
|
+
runtime.newFloat(jx + b.jx),
|
317
|
+
runtime.newFloat(jy + b.jy),
|
318
|
+
runtime.newFloat(jz + b.jz)});
|
319
|
+
}
|
320
|
+
|
321
|
+
/**
|
322
|
+
*
|
323
|
+
* @param context ThreadContext
|
324
|
+
* @param other IRubyObject
|
325
|
+
* @return new Vec3 object (ruby)
|
326
|
+
*/
|
327
|
+
@JRubyMethod(name = "-")
|
328
|
+
|
329
|
+
public IRubyObject op_sub(ThreadContext context, IRubyObject other) {
|
330
|
+
Ruby runtime = context.getRuntime();
|
331
|
+
Vec3 b = null;
|
332
|
+
if (other instanceof Vec3) {
|
333
|
+
b = (Vec3) other.toJava(Vec3.class);
|
334
|
+
} else {
|
335
|
+
throw runtime.newTypeError("argument should be Vec3D");
|
336
|
+
}
|
337
|
+
return Vec3.rbNew(context, other.getMetaClass(), new IRubyObject[]{
|
338
|
+
runtime.newFloat(jx - b.jx),
|
339
|
+
runtime.newFloat(jy - b.jy),
|
340
|
+
runtime.newFloat(jz - b.jz)});
|
341
|
+
}
|
342
|
+
|
343
|
+
/**
|
344
|
+
*
|
345
|
+
* @param context ThreadContext
|
346
|
+
* @param other IRubyObject
|
347
|
+
* @return new Vec3 object (ruby)
|
348
|
+
*/
|
349
|
+
@JRubyMethod(name = "*", required = 1)
|
350
|
+
|
351
|
+
public IRubyObject op_mul(ThreadContext context, IRubyObject other) {
|
352
|
+
Ruby runtime = context.getRuntime();
|
353
|
+
double scalar = (Double) other.toJava(Double.class);
|
354
|
+
return Vec3.rbNew(context, this.getMetaClass(), new IRubyObject[]{
|
355
|
+
runtime.newFloat(jx * scalar),
|
356
|
+
runtime.newFloat(jy * scalar),
|
357
|
+
runtime.newFloat(jz * scalar)});
|
358
|
+
}
|
359
|
+
|
360
|
+
/**
|
361
|
+
*
|
362
|
+
* @param context ThreadContext
|
363
|
+
* @param other IRubyObject
|
364
|
+
* @return new Vec3 object (ruby)
|
365
|
+
*/
|
366
|
+
@JRubyMethod(name = "/", required = 1)
|
367
|
+
|
368
|
+
public IRubyObject op_div(ThreadContext context, IRubyObject other) {
|
369
|
+
Ruby runtime = context.getRuntime();
|
370
|
+
double scalar = (Double) other.toJava(Double.class);
|
371
|
+
if (Math.abs(scalar) < Vec3.EPSILON) {
|
372
|
+
return this;
|
373
|
+
}
|
374
|
+
return Vec3.rbNew(context, this.getMetaClass(), new IRubyObject[]{
|
375
|
+
runtime.newFloat(jx / scalar),
|
376
|
+
runtime.newFloat(jy / scalar),
|
377
|
+
runtime.newFloat(jz / scalar)});
|
378
|
+
}
|
379
|
+
|
380
|
+
/**
|
381
|
+
*
|
382
|
+
* @param context ThreadContext
|
383
|
+
* @return magnitude squared IRubyObject
|
384
|
+
*/
|
385
|
+
@JRubyMethod(name = "mag_squared")
|
386
|
+
|
387
|
+
public IRubyObject mag_squared(ThreadContext context) {
|
388
|
+
return context.getRuntime().newFloat(jx * jx + jy * jy + jz * jz);
|
389
|
+
}
|
390
|
+
|
391
|
+
/**
|
392
|
+
*
|
393
|
+
* @param context ThreadContext
|
394
|
+
* @return magnitude IRubyObject
|
395
|
+
*/
|
396
|
+
@JRubyMethod(name = "mag")
|
397
|
+
|
398
|
+
public IRubyObject mag(ThreadContext context) {
|
399
|
+
return context.getRuntime().newFloat(Math.sqrt(jx * jx + jy * jy + jz * jz));
|
400
|
+
}
|
401
|
+
|
402
|
+
/**
|
403
|
+
* Call yield if block given, do nothing if yield == false else set_mag to
|
404
|
+
* given scalar
|
405
|
+
*
|
406
|
+
* @param context ThreadContext
|
407
|
+
* @param scalar double value to set
|
408
|
+
* @param block should return a boolean (optional)
|
409
|
+
* @return magnitude IRubyObject
|
410
|
+
*/
|
411
|
+
@JRubyMethod(name = "set_mag")
|
412
|
+
|
413
|
+
public IRubyObject set_mag(ThreadContext context, IRubyObject scalar, Block block) {
|
414
|
+
if (block.isGiven()) {
|
415
|
+
if (!(boolean) block.yield(context, scalar).toJava(Boolean.class)) {
|
416
|
+
return this;
|
417
|
+
}
|
418
|
+
}
|
419
|
+
double new_mag = (Double) scalar.toJava(Double.class);
|
420
|
+
double current = Math.sqrt(jx * jx + jy * jy + jz * jz);
|
421
|
+
if (current > EPSILON) {
|
422
|
+
jx *= new_mag / current;
|
423
|
+
jy *= new_mag / current;
|
424
|
+
jz *= new_mag / current;
|
425
|
+
}
|
426
|
+
return this;
|
427
|
+
}
|
428
|
+
|
429
|
+
/**
|
430
|
+
*
|
431
|
+
* @param context ThreadContext
|
432
|
+
* @return this as a ruby object
|
433
|
+
*/
|
434
|
+
@JRubyMethod(name = "normalize!")
|
435
|
+
|
436
|
+
public IRubyObject normalize_bang(ThreadContext context) {
|
437
|
+
if (Math.abs(jx) < EPSILON && Math.abs(jy) < EPSILON && Math.abs(jz) < EPSILON) {
|
438
|
+
return this;
|
439
|
+
}
|
440
|
+
double mag = Math.sqrt(jx * jx + jy * jy + jz * jz);
|
441
|
+
jx /= mag;
|
442
|
+
jy /= mag;
|
443
|
+
jz /= mag;
|
444
|
+
return this;
|
445
|
+
}
|
446
|
+
|
447
|
+
/**
|
448
|
+
*
|
449
|
+
* @param context ThreadContext
|
450
|
+
* @return new normalized Vec3D object (ruby)
|
451
|
+
*/
|
452
|
+
@JRubyMethod(name = "normalize")
|
453
|
+
|
454
|
+
public IRubyObject normalize(ThreadContext context) {
|
455
|
+
Ruby runtime = context.getRuntime();
|
456
|
+
double mag = Math.sqrt(jx * jx + jy * jy + jz * jz);
|
457
|
+
if (mag < EPSILON) {
|
458
|
+
return Vec3.rbNew(context, this.getMetaClass(), new IRubyObject[]{
|
459
|
+
runtime.newFloat(jx),
|
460
|
+
runtime.newFloat(jy),
|
461
|
+
runtime.newFloat(jz)});
|
462
|
+
}
|
463
|
+
return Vec3.rbNew(context, this.getMetaClass(), new IRubyObject[]{
|
464
|
+
runtime.newFloat(jx / mag),
|
465
|
+
runtime.newFloat(jy / mag),
|
466
|
+
runtime.newFloat(jz / mag)});
|
467
|
+
}
|
468
|
+
|
469
|
+
/**
|
470
|
+
* Example of a regular ruby class method
|
471
|
+
*
|
472
|
+
* @param context ThreadContext
|
473
|
+
* @param klazz IRubyObject
|
474
|
+
* @return new random Vec3D object (ruby)
|
475
|
+
*/
|
476
|
+
@JRubyMethod(name = "random", meta = true)
|
477
|
+
|
478
|
+
public static IRubyObject random_direction(ThreadContext context, IRubyObject klazz) {
|
479
|
+
Ruby runtime = context.getRuntime();
|
480
|
+
double angle = Math.random() * Math.PI * 2;
|
481
|
+
double vz = Math.random() * 2 - 1;
|
482
|
+
double vx = Math.sqrt(1 - vz * vz) * Math.cos(angle);
|
483
|
+
double vy = Math.sqrt(1 - vz * vz) * Math.sin(angle);
|
484
|
+
|
485
|
+
return Vec3.rbNew(context, klazz, new IRubyObject[]{
|
486
|
+
runtime.newFloat(vx),
|
487
|
+
runtime.newFloat(vy),
|
488
|
+
runtime.newFloat(vz)});
|
489
|
+
}
|
490
|
+
|
491
|
+
/**
|
492
|
+
*
|
493
|
+
* @param context ThreadContext
|
494
|
+
* @param other IRubyObject another Vec3D
|
495
|
+
* @return angle IRubyObject in radians
|
496
|
+
*/
|
497
|
+
@JRubyMethod(name = "angle_between")
|
498
|
+
|
499
|
+
public IRubyObject angleBetween(ThreadContext context, IRubyObject other) {
|
500
|
+
Ruby runtime = context.getRuntime();
|
501
|
+
Vec3 vec = (Vec3) other.toJava(Vec3.class);
|
502
|
+
// We get NaN if we pass in a zero vector which can cause problems
|
503
|
+
// Zero seems like a reasonable angle between a (0,0,0) vector and something else
|
504
|
+
if (jx == 0 && jy == 0 && jz == 0) {
|
505
|
+
return runtime.newFloat(0.0);
|
506
|
+
}
|
507
|
+
if (vec.jx == 0 && vec.jy == 0 && vec.jz == 0) {
|
508
|
+
return runtime.newFloat(0.0);
|
509
|
+
}
|
510
|
+
|
511
|
+
double dot = jx * vec.jx + jy * vec.jy + jz * vec.jz;
|
512
|
+
double v1mag = Math.sqrt(jx * jx + jy * jy + jz * jz);
|
513
|
+
double v2mag = Math.sqrt(vec.jx * vec.jx + vec.jy * vec.jy + vec.jz * vec.jz);
|
514
|
+
// This should be a number between -1 and 1, since it's "normalized"
|
515
|
+
double amt = dot / (v1mag * v2mag);
|
516
|
+
if (amt <= -1) {
|
517
|
+
return runtime.newFloat(Math.PI);
|
518
|
+
} else if (amt >= 1) {
|
519
|
+
return runtime.newFloat(0.0);
|
520
|
+
}
|
521
|
+
return runtime.newFloat(Math.acos(amt));
|
522
|
+
}
|
523
|
+
|
524
|
+
/**
|
525
|
+
*
|
526
|
+
* @param context ThreadContext
|
527
|
+
* @return IRubyObject copy
|
528
|
+
*/
|
529
|
+
@JRubyMethod(name = {"copy", "dup"})
|
530
|
+
|
531
|
+
public IRubyObject copy(ThreadContext context) {
|
532
|
+
Ruby runtime = context.getRuntime();
|
533
|
+
return Vec3.rbNew(context, this.getMetaClass(), new IRubyObject[]{
|
534
|
+
runtime.newFloat(jx),
|
535
|
+
runtime.newFloat(jy),
|
536
|
+
runtime.newFloat(jz)});
|
537
|
+
}
|
538
|
+
|
539
|
+
/**
|
540
|
+
*
|
541
|
+
* @param context ThreadContext
|
542
|
+
* @return IRubyObject array of float
|
543
|
+
*/
|
544
|
+
@JRubyMethod(name = "to_a")
|
545
|
+
|
546
|
+
public IRubyObject toArray(ThreadContext context) {
|
547
|
+
Ruby runtime = context.getRuntime();
|
548
|
+
return RubyArray.newArray(context.runtime, new IRubyObject[]{
|
549
|
+
runtime.newFloat(jx),
|
550
|
+
runtime.newFloat(jy),
|
551
|
+
runtime.newFloat(jz)});
|
552
|
+
}
|
553
|
+
|
554
|
+
/**
|
555
|
+
* To vertex
|
556
|
+
* @param context ThreadContext
|
557
|
+
* @param object IRubyObject vertex renderer
|
558
|
+
*/
|
559
|
+
@JRubyMethod(name = "to_vertex")
|
560
|
+
|
561
|
+
public void toVertex(ThreadContext context, IRubyObject object) {
|
562
|
+
JRender renderer = (JRender) object.toJava(JRender.class);
|
563
|
+
renderer.vertex(jx, jy, jz);
|
564
|
+
}
|
565
|
+
|
566
|
+
/**
|
567
|
+
* To curve vertex
|
568
|
+
* @param context ThreadContext
|
569
|
+
* @param object IRubyObject vertex renderer
|
570
|
+
*/
|
571
|
+
@JRubyMethod(name = "to_curve_vertex")
|
572
|
+
|
573
|
+
public void toCurveVertex(ThreadContext context, IRubyObject object) {
|
574
|
+
JRender renderer = (JRender) object.toJava(JRender.class);
|
575
|
+
renderer.curveVertex(jx, jy, jz);
|
576
|
+
}
|
577
|
+
|
578
|
+
/**
|
579
|
+
* Sends this Vec3D as a processing vertex uv
|
580
|
+
* @param context ThreadContext
|
581
|
+
* @param args IRubyObject[]
|
582
|
+
*/
|
583
|
+
@JRubyMethod(name = "to_vertex_uv", rest = true)
|
584
|
+
|
585
|
+
public void toVertexUV(ThreadContext context, IRubyObject[] args) {
|
586
|
+
int count = Arity.checkArgumentCount(context.getRuntime(), args, Arity.OPTIONAL.getValue(), 3);
|
587
|
+
double u = 0;
|
588
|
+
double v = 0;
|
589
|
+
if (count == 3)
|
590
|
+
{
|
591
|
+
u = (Double) args[1].toJava(Double.class);
|
592
|
+
v = (Double) args[2].toJava(Double.class);
|
593
|
+
}
|
594
|
+
if (count == 2){
|
595
|
+
Vec2 texture = (Vec2) args[1].toJava(Vec2.class);
|
596
|
+
u = texture.javax();
|
597
|
+
v = texture.javay();
|
598
|
+
}
|
599
|
+
JRender renderer = (JRender) args[0].toJava(JRender.class);
|
600
|
+
renderer.vertex(jx, jy, jz, u, v);
|
601
|
+
}
|
602
|
+
|
603
|
+
/**
|
604
|
+
* Sends this Vec3D as a processing normal
|
605
|
+
* @param context ThreadContext
|
606
|
+
* @param object IRubyObject vertex renderer
|
607
|
+
*/
|
608
|
+
@JRubyMethod(name = "to_normal")
|
609
|
+
|
610
|
+
public void toNormal(ThreadContext context, IRubyObject object) {
|
611
|
+
JRender renderer = (JRender) object.toJava(JRender.class);
|
612
|
+
renderer.normal(jx, jy, jz);
|
613
|
+
}
|
614
|
+
|
615
|
+
/**
|
616
|
+
* For jruby-9000 we alias to inspect
|
617
|
+
*
|
618
|
+
* @param context ThreadContext
|
619
|
+
* @return IRubyObject to_s
|
620
|
+
*/
|
621
|
+
@JRubyMethod(name = {"to_s", "inspect"})
|
622
|
+
|
623
|
+
public IRubyObject to_s(ThreadContext context) {
|
624
|
+
return context.getRuntime().newString(String.format("Vec3D(x = %4.4f, y = %4.4f, z = %4.4f)", jx, jy, jz));
|
625
|
+
}
|
626
|
+
|
627
|
+
/**
|
628
|
+
* Java hash
|
629
|
+
* @return hash int
|
630
|
+
*/
|
631
|
+
@Override
|
632
|
+
public int hashCode() {
|
633
|
+
int hash = 7;
|
634
|
+
hash = 97 * hash + (int) (Double.doubleToLongBits(this.jx) ^ (Double.doubleToLongBits(this.jx) >>> 32));
|
635
|
+
hash = 97 * hash + (int) (Double.doubleToLongBits(this.jy) ^ (Double.doubleToLongBits(this.jy) >>> 32));
|
636
|
+
hash = 97 * hash + (int) (Double.doubleToLongBits(this.jz) ^ (Double.doubleToLongBits(this.jz) >>> 32));
|
637
|
+
return hash;
|
638
|
+
}
|
639
|
+
|
640
|
+
/**
|
641
|
+
* Java Equals
|
642
|
+
* @param obj Object
|
643
|
+
* @return result boolean
|
644
|
+
*/
|
645
|
+
@Override
|
646
|
+
public boolean equals(Object obj) {
|
647
|
+
if (obj instanceof Vec3) {
|
648
|
+
final Vec3 other = (Vec3) obj;
|
649
|
+
if (!((Double) this.jx).equals(other.jx)) {
|
650
|
+
return false;
|
651
|
+
}
|
652
|
+
if (!((Double) this.jy).equals(other.jy)) {
|
653
|
+
return false;
|
654
|
+
}
|
655
|
+
return ((Double) this.jz).equals(other.jz);
|
656
|
+
}
|
657
|
+
return false;
|
658
|
+
}
|
659
|
+
|
660
|
+
/**
|
661
|
+
*
|
662
|
+
* @param context ThreadContext
|
663
|
+
* @param other IRubyObject
|
664
|
+
* @return result IRubyObject as boolean
|
665
|
+
*/
|
666
|
+
@JRubyMethod(name = "eql?", required = 1)
|
667
|
+
|
668
|
+
public IRubyObject eql_p(ThreadContext context, IRubyObject other) {
|
669
|
+
if (other instanceof Vec3) {
|
670
|
+
Vec3 v = (Vec3) other.toJava(Vec3.class);
|
671
|
+
if (!((Double) this.jx).equals(v.jx)) {
|
672
|
+
return RubyBoolean.newBoolean(context.runtime, false);
|
673
|
+
}
|
674
|
+
if (!((Double) this.jy).equals(v.jy)) {
|
675
|
+
return RubyBoolean.newBoolean(context.runtime, false);
|
676
|
+
}
|
677
|
+
return RubyBoolean.newBoolean(context.runtime, ((Double) this.jz).equals(v.jz));
|
678
|
+
}
|
679
|
+
return RubyBoolean.newBoolean(context.runtime, false);
|
680
|
+
}
|
681
|
+
|
682
|
+
/**
|
683
|
+
*
|
684
|
+
* @param context ThreadContext
|
685
|
+
* @param other IRubyObject
|
686
|
+
* @return result IRubyObject as boolean
|
687
|
+
*/
|
688
|
+
@JRubyMethod(name = "==", required = 1)
|
689
|
+
|
690
|
+
@Override
|
691
|
+
public IRubyObject op_equal(ThreadContext context, IRubyObject other) {
|
692
|
+
if (other instanceof Vec3) {
|
693
|
+
Vec3 v = (Vec3) other.toJava(Vec3.class);
|
694
|
+
double diff = jx - v.jx;
|
695
|
+
if ((diff < 0 ? -diff : diff) > Vec3.EPSILON) {
|
696
|
+
return RubyBoolean.newBoolean(context.runtime, false);
|
697
|
+
}
|
698
|
+
diff = jy - v.jy;
|
699
|
+
if ((diff < 0 ? -diff : diff) > Vec3.EPSILON) {
|
700
|
+
return RubyBoolean.newBoolean(context.runtime, false);
|
701
|
+
}
|
702
|
+
diff = jz - v.jz;
|
703
|
+
boolean result = ((diff < 0 ? -diff : diff) < Vec3.EPSILON);
|
704
|
+
return RubyBoolean.newBoolean(context.runtime, result);
|
705
|
+
}
|
706
|
+
return RubyBoolean.newBoolean(context.runtime, false);
|
707
|
+
}
|
708
|
+
}
|