Skip to content

Commit 5b51f98

Browse files
committed
dyanamic color table
1 parent f7a5ed2 commit 5b51f98

File tree

1 file changed

+171
-0
lines changed

1 file changed

+171
-0
lines changed

contributed/spiky_orb.rb

Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
# spiky_orb.rb
2+
# After a vanilla processing sketch by
3+
# Ben Notorianni aka lazydog
4+
# Features dynamic creation of a colour table
5+
BALL_RADIUS = 160
6+
7+
attr_reader :colour_table, :orb_vertices, :flat, :smoothing, :sub_division_depth
8+
attr_reader :orb_radii
9+
10+
def settings
11+
size 640, 480, P3D
12+
end
13+
14+
def setup
15+
sketch_title 'Spiky Orb'
16+
@orb_vertices = []
17+
@flat = false
18+
@smoothing = 3
19+
@sub_division_depth = 4
20+
end
21+
22+
def draw
23+
background(0)
24+
lights
25+
spot_light(255, 255, 255, 400, 400, 400, -1, -1, -1, PI / 2, 2)
26+
translate(width / 2, height / 2)
27+
smooth_rotation(5.0, 6.7, 7.3)
28+
create_sphere
29+
draw_tesselated_icosahedron(orb_vertices, colour_table)
30+
end
31+
32+
def calc_color(red, green, blue)
33+
r = 127 * sin(PI * frame_count * red) + 127
34+
g = 127 * sin(PI * frame_count * green) + 127
35+
b = 127 * sin(PI * frame_count * blue) + 127
36+
color(r, g, b)
37+
end
38+
39+
def generate_colour_table(depth)
40+
c1 = calc_color(0.00400, 0.002200, 0.00300)
41+
c2 = calc_color(0.00328, 0.00328, 0.00328)
42+
c3 = calc_color(0.00496, 0.00780, 0.00450)
43+
c4 = calc_color(0.00420, 0.00520, 0.00620)
44+
colour_set = [
45+
[c1, c1, c1, c2],
46+
[c1, c1, c1, c2],
47+
[c1, c1, c1, c2],
48+
[c4, c4, c4, c3]
49+
]
50+
@colour_table = []
51+
20.times do
52+
(4**(depth - 1)).times do |j|
53+
colour_table << colour_set[(j / 16) % 4][j % 4]
54+
end
55+
end
56+
colour_table
57+
end
58+
59+
def subdivide_triangle(depth, index, pt1, pt2, pt3)
60+
if depth == 1
61+
orb_vertices[index += 1] = pt1.x
62+
orb_vertices[index += 1] = pt1.y
63+
orb_vertices[index += 1] = pt1.z
64+
orb_vertices[index += 1] = pt2.x
65+
orb_vertices[index += 1] = pt2.y
66+
orb_vertices[index += 1] = pt2.z
67+
orb_vertices[index += 1] = pt3.x
68+
orb_vertices[index += 1] = pt3.y
69+
orb_vertices[index += 1] = pt3.z
70+
else
71+
vec1 = pt1 + pt2
72+
vec2 = pt2 + pt3
73+
vec3 = pt3 + pt1
74+
if depth <= sub_division_depth - smoothing
75+
vec1 *= 0.5
76+
vec2 *= 0.5
77+
vec3 *= 0.5
78+
else
79+
r = orb_radii[depth]
80+
vec1 = vec1.normalize * r
81+
vec2 = vec2.normalize * r
82+
vec3 = vec3.normalize * r
83+
end
84+
index = subdivide_triangle(depth - 1, index, pt1, vec1, vec3)
85+
index = subdivide_triangle(depth - 1, index, vec1, pt2, vec2)
86+
index = subdivide_triangle(depth - 1, index, vec2, pt3, vec3)
87+
index = subdivide_triangle(depth - 1, index, vec1, vec2, vec3)
88+
end
89+
index
90+
end
91+
92+
def tesselate_icosahedron(radii, depth)
93+
gr = (1 + sqrt(5)) / 2.0
94+
r = radii[depth] / sqrt(1 + gr * gr)
95+
v = [
96+
Vec3D.new(0, -r, r * gr),
97+
Vec3D.new(0, -r, -r * gr),
98+
Vec3D.new(0, r, -r * gr),
99+
Vec3D.new(0, r, r * gr),
100+
Vec3D.new(r, -r * gr, 0),
101+
Vec3D.new(r, r * gr, 0),
102+
Vec3D.new(-r, r * gr, 0),
103+
Vec3D.new(-r, -r * gr, 0),
104+
Vec3D.new(-r * gr, 0, r),
105+
Vec3D.new(-r * gr, 0, -r),
106+
Vec3D.new(r * gr, 0, -r),
107+
Vec3D.new(r * gr, 0, r)
108+
]
109+
index = 0
110+
index = subdivide_triangle(depth, index, v[0], v[7], v[4])
111+
index = subdivide_triangle(depth, index, v[0], v[4], v[11])
112+
index = subdivide_triangle(depth, index, v[0], v[11], v[3])
113+
index = subdivide_triangle(depth, index, v[0], v[3], v[8])
114+
index = subdivide_triangle(depth, index, v[0], v[8], v[7])
115+
index = subdivide_triangle(depth, index, v[1], v[4], v[7])
116+
index = subdivide_triangle(depth, index, v[1], v[10], v[4])
117+
index = subdivide_triangle(depth, index, v[10], v[11], v[4])
118+
index = subdivide_triangle(depth, index, v[11], v[5], v[10])
119+
index = subdivide_triangle(depth, index, v[5], v[3], v[11])
120+
index = subdivide_triangle(depth, index, v[3], v[6], v[5])
121+
index = subdivide_triangle(depth, index, v[6], v[8], v[3])
122+
index = subdivide_triangle(depth, index, v[8], v[9], v[6])
123+
index = subdivide_triangle(depth, index, v[9], v[7], v[8])
124+
index = subdivide_triangle(depth, index, v[7], v[1], v[9])
125+
index = subdivide_triangle(depth, index, v[2], v[1], v[9])
126+
index = subdivide_triangle(depth, index, v[2], v[10], v[1])
127+
index = subdivide_triangle(depth, index, v[2], v[5], v[10])
128+
index = subdivide_triangle(depth, index, v[2], v[6], v[5])
129+
subdivide_triangle(depth, index, v[2], v[9], v[6])
130+
end
131+
132+
def smooth_rotation(ro1, ro2, ro3)
133+
mills = millis * 0.00003
134+
rotate_x 0.5 * Math.sin(mills * ro1) + 0.5
135+
rotate_y 0.5 * Math.sin(mills * ro2) + 0.5
136+
rotate_z 0.5 * Math.sin(mills * ro3) + 0.5
137+
end
138+
139+
def generate_radii(base_radius, depth)
140+
return (0..depth).map { base_radius } if flat
141+
142+
(0..depth).map do |i|
143+
r = 2 * noise(frame_count * 0.003, (i.to_f / depth) - 1.0)
144+
base_radius * (0.9 * r)
145+
end
146+
end
147+
148+
def draw_tesselated_icosahedron(verticies, colour_table)
149+
index = 0
150+
no_stroke
151+
begin_shape(TRIANGLES)
152+
colour_table.each do |col|
153+
fill(col)
154+
vertex(verticies[index += 1], verticies[index += 1], verticies[index += 1])
155+
vertex(verticies[index += 1], verticies[index += 1], verticies[index += 1])
156+
vertex(verticies[index += 1], verticies[index += 1], verticies[index += 1])
157+
end
158+
end_shape
159+
end
160+
161+
def create_sphere
162+
@orb_radii = generate_radii(BALL_RADIUS, sub_division_depth)
163+
tesselate_icosahedron(orb_radii, sub_division_depth)
164+
generate_colour_table(sub_division_depth)
165+
end
166+
167+
def key_pressed
168+
return unless key == 's'
169+
170+
@flat = !flat
171+
end

0 commit comments

Comments
 (0)