propane 0.3.0.pre-java
Sign up to get free protection for your applications and to get access to all the features.
- 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,63 @@
|
|
1
|
+
# Description:
|
2
|
+
# Flight Patterns is that ol' Euruko 2008 demo.
|
3
|
+
# Reworked version for Propane
|
4
|
+
# Usage:
|
5
|
+
# Drag mouse to steer 'invisible' flock attractor, use 'f' key to toggle flee
|
6
|
+
# Mouse 'click' to toggle 'sphere' or 'circle' display
|
7
|
+
require 'propane'
|
8
|
+
|
9
|
+
class FlightPatterns < Propane::App
|
10
|
+
load_library :boids
|
11
|
+
|
12
|
+
attr_reader :flee, :radius
|
13
|
+
|
14
|
+
def setup
|
15
|
+
size 1024, 768, P3D
|
16
|
+
sphere_detail 8
|
17
|
+
color_mode RGB, 1.0
|
18
|
+
no_stroke
|
19
|
+
shininess 1.0
|
20
|
+
specular 0.3, 0.1, 0.1
|
21
|
+
emissive 0.03, 0.03, 0.1
|
22
|
+
@radius = 0.02 * height
|
23
|
+
@click = false
|
24
|
+
@flee = false
|
25
|
+
@flocks = (0..3).map { Boids.flock(n: 20, x: 0, y: 0, w: width, h: height) }
|
26
|
+
end
|
27
|
+
|
28
|
+
def mouse_pressed
|
29
|
+
@click = !@click
|
30
|
+
end
|
31
|
+
|
32
|
+
def key_pressed
|
33
|
+
return unless key == 'f'
|
34
|
+
@flee = !@flee
|
35
|
+
end
|
36
|
+
|
37
|
+
def draw
|
38
|
+
background 0.05
|
39
|
+
ambient_light 0.01, 0.01, 0.01
|
40
|
+
light_specular 0.4, 0.2, 0.2
|
41
|
+
point_light 1.0, 1.0, 1.0, mouse_x, mouse_y, 190
|
42
|
+
@flocks.each_with_index do |flock, i|
|
43
|
+
flock.goal(target: Vec3D.new(mouse_x, mouse_y, 0), flee: @flee)
|
44
|
+
flock.update(goal: 185, limit: 13.5)
|
45
|
+
flock.each do |boid|
|
46
|
+
r = (0.15 * boid.pos.z) + radius
|
47
|
+
case i
|
48
|
+
when 0 then fill 0.85, 0.65, 0.65
|
49
|
+
when 1 then fill 0.65, 0.85, 0.65
|
50
|
+
when 2 then fill 0.65, 0.65, 0.85
|
51
|
+
end
|
52
|
+
push_matrix
|
53
|
+
point_array = (boid.pos.to_a).map { |p| p - (r / 2.0) }
|
54
|
+
translate(*point_array)
|
55
|
+
@click ? sphere(r / 2) : ellipse(0, 0, r, r)
|
56
|
+
@click ? hint(ENABLE_DEPTH_TEST) : hint(DISABLE_DEPTH_TEST)
|
57
|
+
pop_matrix
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
FlightPatterns.new title: 'Flight Patterns'
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
# grey circles : borrowed from https://github.com/quil/quil
|
4
|
+
require 'propane'
|
5
|
+
|
6
|
+
class GreyCircles < Propane::App
|
7
|
+
|
8
|
+
def setup
|
9
|
+
size(323, 200)
|
10
|
+
smooth
|
11
|
+
frame_rate(1)
|
12
|
+
background(200)
|
13
|
+
end
|
14
|
+
|
15
|
+
def draw
|
16
|
+
stroke_setup
|
17
|
+
diameter = rand(100)
|
18
|
+
ellipse(rand(width), rand(height), diameter, diameter)
|
19
|
+
end
|
20
|
+
|
21
|
+
def stroke_setup
|
22
|
+
[:stroke, :stroke_weight, :fill].each do |method|
|
23
|
+
send(method, rand(255))
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
GreyCircles.new title: 'Oh so many circles'
|
@@ -0,0 +1,100 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
require 'propane'
|
4
|
+
# Iconic ruby-processing example for Propane
|
5
|
+
class JWishy < Propane::App
|
6
|
+
load_library :control_panel
|
7
|
+
|
8
|
+
attr_reader :alpha, :back_color, :bluish, :hide, :magnitude, :panel
|
9
|
+
attr_reader :x_wiggle, :y_wiggle
|
10
|
+
|
11
|
+
def setup
|
12
|
+
size 600, 600
|
13
|
+
control_panel do |c|
|
14
|
+
c.title = 'Control Panel'
|
15
|
+
c.look_feel 'Nimbus'
|
16
|
+
c.slider :bluish, 0.0..1.0, 0.5
|
17
|
+
c.slider :alpha, 0.0..1.0, 0.5
|
18
|
+
c.checkbox :go_big
|
19
|
+
c.button :reset
|
20
|
+
c.menu :shape, %w(oval square triangle)
|
21
|
+
@panel = c
|
22
|
+
end
|
23
|
+
@hide = false
|
24
|
+
@shape = 'oval'
|
25
|
+
@x_wiggle, @y_wiggle = 10.0, 0
|
26
|
+
@magnitude = 8.15
|
27
|
+
@back_color = [0.06, 0.03, 0.18]
|
28
|
+
color_mode RGB, 1
|
29
|
+
ellipse_mode CORNER
|
30
|
+
smooth
|
31
|
+
end
|
32
|
+
|
33
|
+
def draw_background
|
34
|
+
back_color[3] = alpha
|
35
|
+
fill(*back_color.to_java(:float))
|
36
|
+
rect 0, 0, width, height
|
37
|
+
end
|
38
|
+
|
39
|
+
def reset
|
40
|
+
@y_wiggle = 0
|
41
|
+
end
|
42
|
+
|
43
|
+
def draw
|
44
|
+
# only make control_panel visible once, or again when hide is false
|
45
|
+
unless hide
|
46
|
+
@hide = true
|
47
|
+
panel.set_visible(hide)
|
48
|
+
end
|
49
|
+
draw_background
|
50
|
+
# Seed the random numbers for consistent placement from frame to frame
|
51
|
+
srand(0)
|
52
|
+
horiz, vert, mag = x_wiggle, y_wiggle, magnitude
|
53
|
+
if @go_big
|
54
|
+
mag *= 2
|
55
|
+
vert /= 2
|
56
|
+
end
|
57
|
+
blu = bluish
|
58
|
+
x, y = (width / 2), -27
|
59
|
+
c = 0.0
|
60
|
+
64.times do
|
61
|
+
x += cos(horiz) * mag
|
62
|
+
y += log10(vert) * mag + sin(vert) * 2
|
63
|
+
fill(sin(y_wiggle + c), rand * 0.2, rand * blu, 0.5)
|
64
|
+
s = 42 + cos(vert) * 17
|
65
|
+
args = [@shape, x - s / 2, y - s / 2, s, s]
|
66
|
+
draw_shape(args)
|
67
|
+
vert += rand * 0.25
|
68
|
+
horiz += rand * 0.25
|
69
|
+
c += 0.1
|
70
|
+
end
|
71
|
+
@x_wiggle += 0.05
|
72
|
+
@y_wiggle += 0.1
|
73
|
+
end
|
74
|
+
|
75
|
+
def mouse_pressed
|
76
|
+
return unless hide
|
77
|
+
@hide = false
|
78
|
+
end
|
79
|
+
|
80
|
+
def draw_shape(args)
|
81
|
+
case args[0]
|
82
|
+
when 'triangle'
|
83
|
+
draw_triangle(args)
|
84
|
+
when 'square'
|
85
|
+
rect(args[1], args[2], args[3], args[4])
|
86
|
+
else
|
87
|
+
ellipse(args[1], args[2], args[3], args[4]) # oval for Shoes
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def draw_triangle(args)
|
92
|
+
x2 = args[1] + (args[3] * 0.6)
|
93
|
+
y0 = args[2] + (args[4] * 0.396)
|
94
|
+
y1 = args[2] - (args[4] * 0.792)
|
95
|
+
y2 = args[2] + (args[4] * 0.396)
|
96
|
+
triangle(args[1] - (args[3] * 0.6), y0, args[1], y1, x2, y2)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
JWishy.new title: 'Wishy Worm'
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
# Letters.
|
4
|
+
#
|
5
|
+
require 'propane'
|
6
|
+
|
7
|
+
LETTERS = ('A'..'Z').to_a + ('0'..'9').to_a + ('a'..'z').to_a
|
8
|
+
|
9
|
+
# Draws letters to the screen. This requires loading a font,
|
10
|
+
# setting the font, and then drawing the letters.
|
11
|
+
class Letters < Propane::App
|
12
|
+
def setup
|
13
|
+
size 640, 360
|
14
|
+
@font = create_font 'Georgia', 24
|
15
|
+
text_font @font
|
16
|
+
text_align CENTER, CENTER
|
17
|
+
end
|
18
|
+
|
19
|
+
def draw
|
20
|
+
background 0
|
21
|
+
translate 24, 32
|
22
|
+
x, y = 0.0, 0.0
|
23
|
+
gap = 30
|
24
|
+
# ranges -> arrays -> joined!
|
25
|
+
LETTERS.each do |letter|
|
26
|
+
fill 255
|
27
|
+
fill 204, 204, 0 if letter =~ /[AEIOU]/
|
28
|
+
fill 0, 204, 204 if letter =~ /[aeiou]/
|
29
|
+
fill 153 if letter =~ /[0-9]/
|
30
|
+
fill 255, 100, 0 if key_pressed? && (letter.downcase.eql? key)
|
31
|
+
fill 0, 100, 255 if key_pressed? && (letter.upcase.eql? key)
|
32
|
+
text letter, x, y
|
33
|
+
x += gap
|
34
|
+
if x > width - 30
|
35
|
+
x = 0
|
36
|
+
y += gap
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
Letters.new title: 'Letters'
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# Re-usable Boundary class
|
2
|
+
class Boundary
|
3
|
+
include Propane::Proxy
|
4
|
+
attr_reader :box2d, :b, :pos, :size, :a
|
5
|
+
|
6
|
+
def initialize(b2d, pos, sz, a = 0)
|
7
|
+
@box2d, @pos, @size, @a = b2d, pos, sz, a
|
8
|
+
# Define the polygon
|
9
|
+
sd = PolygonShape.new
|
10
|
+
# Figure out the box2d coordinates
|
11
|
+
box2d_w = box2d.scale_to_world(size.x / 2)
|
12
|
+
box2d_h = box2d.scale_to_world(size.y / 2)
|
13
|
+
# We're just a box
|
14
|
+
sd.set_as_box(box2d_w, box2d_h)
|
15
|
+
# Create the body
|
16
|
+
bd = BodyDef.new
|
17
|
+
bd.type = BodyType::STATIC
|
18
|
+
bd.angle = a
|
19
|
+
bd.position.set(box2d.processing_to_world(pos.x, pos.y))
|
20
|
+
@b = box2d.create_body(bd)
|
21
|
+
# Attached the shape to the body using a Fixture
|
22
|
+
b.create_fixture(sd, 1)
|
23
|
+
end
|
24
|
+
|
25
|
+
# Draw the boundary, it doesn't move so we don't ask for location
|
26
|
+
def display
|
27
|
+
fill(0)
|
28
|
+
stroke(0)
|
29
|
+
stroke_weight(1)
|
30
|
+
rect_mode(PConstants::CENTER)
|
31
|
+
a = b.get_angle
|
32
|
+
push_matrix
|
33
|
+
translate(pos.x, pos.y)
|
34
|
+
rotate(-a)
|
35
|
+
rect(0, 0, size.x, size.y)
|
36
|
+
pop_matrix
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
# Note the particle class change method is use to change color to red
|
2
|
+
# when two particles collide (no change just hitting boundary)
|
3
|
+
class Particle
|
4
|
+
extend Forwardable
|
5
|
+
def_delegators(:@app, :box2d, :begin_shape, :color, :end_shape, :line,
|
6
|
+
:pop_matrix, :ellipse, :translate, :rotate, :stroke,
|
7
|
+
:push_matrix, :fill, :no_fill, :stroke_weight)
|
8
|
+
attr_accessor :body
|
9
|
+
attr_reader :radius, :col
|
10
|
+
|
11
|
+
def initialize(app, x, y, r)
|
12
|
+
@app, @x, @y, @radius = app, x, y, r
|
13
|
+
# This function puts the particle in the Box2d world
|
14
|
+
make_body(x, y, radius)
|
15
|
+
@col = color('#c0c0c0') # silvergrey
|
16
|
+
body.setUserData(self)
|
17
|
+
end
|
18
|
+
|
19
|
+
# This function removes the particle from the box2d world
|
20
|
+
def kill_body
|
21
|
+
box2d.destroy_body(body)
|
22
|
+
end
|
23
|
+
|
24
|
+
# Change color when hit
|
25
|
+
def change
|
26
|
+
@col = color('#cc0000') # red
|
27
|
+
end
|
28
|
+
|
29
|
+
# Is the particle ready for deletion?
|
30
|
+
def done
|
31
|
+
# Let's find the screen position of the particle
|
32
|
+
pos = box2d.body_coord(body)
|
33
|
+
# Is it off the bottom of the screen?
|
34
|
+
return false unless pos.y > (box2d.height + radius * 2)
|
35
|
+
kill_body
|
36
|
+
true
|
37
|
+
end
|
38
|
+
|
39
|
+
def display
|
40
|
+
# We look at each body and get its screen position
|
41
|
+
pos = box2d.body_coord(body)
|
42
|
+
# Get its angle of rotation
|
43
|
+
a = body.get_angle
|
44
|
+
push_matrix
|
45
|
+
translate(pos.x, pos.y)
|
46
|
+
rotate(a)
|
47
|
+
fill(col)
|
48
|
+
stroke(0)
|
49
|
+
stroke_weight(1)
|
50
|
+
ellipse(0, 0, radius * 2, radius * 2)
|
51
|
+
# Let's add a line so we can see the rotation
|
52
|
+
line(0, 0, radius, 0)
|
53
|
+
pop_matrix
|
54
|
+
end
|
55
|
+
|
56
|
+
# Here's our function that adds the particle to the Box2D world
|
57
|
+
def make_body(x, y, r)
|
58
|
+
# Define a body
|
59
|
+
bd = BodyDef.new
|
60
|
+
# Set its position
|
61
|
+
bd.position = box2d.processing_to_world(x, y)
|
62
|
+
bd.type = BodyType::DYNAMIC
|
63
|
+
@body = box2d.create_body(bd)
|
64
|
+
# Make the body's shape a circle
|
65
|
+
cs = CircleShape.new
|
66
|
+
cs.m_radius = box2d.scale_to_world(r)
|
67
|
+
fd = FixtureDef.new
|
68
|
+
fd.shape = cs
|
69
|
+
# Parameters that affect physics
|
70
|
+
fd.density = 1
|
71
|
+
fd.friction = 0.01
|
72
|
+
fd.restitution = 0.3
|
73
|
+
# Attach fixture to body
|
74
|
+
body.create_fixture(fd)
|
75
|
+
body.set_angular_velocity(rand(-10.0..10))
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
|
3
|
+
module Runnable
|
4
|
+
def run
|
5
|
+
reject!(&:done)
|
6
|
+
each(&:display)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
# Not be confused with the jbox2d ParticleSystem
|
11
|
+
class ParticleSystem
|
12
|
+
include Enumerable, Runnable
|
13
|
+
extend Forwardable
|
14
|
+
def_delegators(:@particles, :each, :reject!, :<<, :empty?)
|
15
|
+
def_delegator(:@particles, :empty?, :dead?)
|
16
|
+
|
17
|
+
attr_reader :x, :y
|
18
|
+
|
19
|
+
def initialize(bd, num, x, y)
|
20
|
+
@particles = [] # Initialize the Array
|
21
|
+
@x, @y = x, y # Store the origin point
|
22
|
+
num.times do
|
23
|
+
self << Particle.new(bd, x, y)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def add_particles(bd, n)
|
28
|
+
n.times do
|
29
|
+
self << Particle.new(bd, x, y)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# A Particle
|
35
|
+
require 'pbox2d'
|
36
|
+
|
37
|
+
class Particle
|
38
|
+
include Propane::Proxy
|
39
|
+
TRAIL_SIZE = 6
|
40
|
+
# We need to keep track of a Body
|
41
|
+
|
42
|
+
attr_reader :trail, :body, :box2d
|
43
|
+
|
44
|
+
# Constructor
|
45
|
+
def initialize(b2d, x, y)
|
46
|
+
@box2d = b2d
|
47
|
+
@trail = Array.new(TRAIL_SIZE, [x, y])
|
48
|
+
# Add the box to the box2d world
|
49
|
+
# Here's a little trick, let's make a tiny tiny radius
|
50
|
+
# This way we have collisions, but they don't overwhelm the system
|
51
|
+
make_body(x, y, 0.2)
|
52
|
+
end
|
53
|
+
|
54
|
+
# This function removes the particle from the box2d world
|
55
|
+
def kill_body
|
56
|
+
box2d.destroy_body(body)
|
57
|
+
end
|
58
|
+
|
59
|
+
# Is the particle ready for deletion?
|
60
|
+
def done
|
61
|
+
# Let's find the screen position of the particle
|
62
|
+
pos = box2d.body_coord(body)
|
63
|
+
# Is it off the bottom of the screen?
|
64
|
+
return false unless pos.y > box2d.height + 20
|
65
|
+
kill_body
|
66
|
+
true
|
67
|
+
end
|
68
|
+
|
69
|
+
# Drawing the box
|
70
|
+
def display
|
71
|
+
# We look at each body and get its screen position
|
72
|
+
pos = box2d.body_coord(body)
|
73
|
+
# Keep track of a history of screen positions in an array
|
74
|
+
(TRAIL_SIZE - 1).times do |i|
|
75
|
+
trail[i] = trail[i + 1]
|
76
|
+
end
|
77
|
+
trail[TRAIL_SIZE - 1] = [pos.x, pos.y]
|
78
|
+
# Draw particle as a trail
|
79
|
+
begin_shape
|
80
|
+
no_fill
|
81
|
+
stroke_weight(2)
|
82
|
+
stroke(0, 150)
|
83
|
+
trail.each do |v|
|
84
|
+
vertex(v[0], v[1])
|
85
|
+
end
|
86
|
+
end_shape
|
87
|
+
end
|
88
|
+
|
89
|
+
# This function adds the rectangle to the box2d world
|
90
|
+
def make_body(x, y, r)
|
91
|
+
# Define and create the body
|
92
|
+
bd = BodyDef.new
|
93
|
+
bd.type = BodyType::DYNAMIC
|
94
|
+
bd.position.set(box2d.processing_to_world(x, y))
|
95
|
+
@body = box2d.create_body(bd)
|
96
|
+
# Give it some initial random velocity
|
97
|
+
body.set_linear_velocity(Vec2.new(rand(-1.0..1), rand(-1.0..1)))
|
98
|
+
# Make the body's shape a circle
|
99
|
+
cs = CircleShape.new
|
100
|
+
cs.m_radius = box2d.scale_to_world(r)
|
101
|
+
fd = FixtureDef.new
|
102
|
+
fd.shape = cs
|
103
|
+
fd.density = 1
|
104
|
+
fd.friction = 0 # Slippery when wet!
|
105
|
+
fd.restitution = 0.5
|
106
|
+
# We could use this if we want to turn collisions off
|
107
|
+
# cd.filter.groupIndex = -10
|
108
|
+
# Attach fixture to body
|
109
|
+
body.create_fixture(fd)
|
110
|
+
end
|
111
|
+
end
|