|
| 1 | +# frozen_string_literal: true |
| 2 | +require 'picrate' |
| 3 | +require 'arcball' |
| 4 | + |
| 5 | +########################## |
| 6 | +# RetainedMenger.rb |
| 7 | +# (processing-3.0) |
| 8 | +# author Martin Prout |
| 9 | +########################## |
| 10 | +class RetainedMenger < Processing::App |
| 11 | + |
| 12 | + PTS = 3 |
| 13 | + MIN_SIZE = 20 |
| 14 | + |
| 15 | + attr_reader :menger |
| 16 | + |
| 17 | + def setup |
| 18 | + sketch_title 'Retained Menger' |
| 19 | + Processing::ArcBall.init(self) |
| 20 | + @menger = create_shape(GROUP) |
| 21 | + create_menger(0, 0, 0, height * 0.8) |
| 22 | + end |
| 23 | + |
| 24 | + def draw |
| 25 | + background(20, 20, 200) |
| 26 | + no_stroke |
| 27 | + lights |
| 28 | + define_lights |
| 29 | + render |
| 30 | + end |
| 31 | + |
| 32 | + def render |
| 33 | + menger.set_fill(color(224, 223, 219)) |
| 34 | + menger.set_ambient(50) |
| 35 | + menger.set_specular(150) |
| 36 | + shape(menger) |
| 37 | + end |
| 38 | + |
| 39 | + def create_menger(xx, yy, zz, sz) |
| 40 | + u = sz / 3.0 |
| 41 | + if sz < MIN_SIZE # recursion limited by minimum cube size |
| 42 | + no_stroke |
| 43 | + menger.add_child(create_cube(xx, yy, zz, sz)) # create and add a cube |
| 44 | + else |
| 45 | + mesh_grid(PTS, PTS, PTS) do |x, y, z| |
| 46 | + i = x - 1 |
| 47 | + j = y - 1 |
| 48 | + k = z - 1 |
| 49 | + if (i.abs + j.abs + k.abs) > 1 |
| 50 | + create_menger(xx + (i * u), yy + (j * u), zz + (k * u), u) |
| 51 | + end |
| 52 | + end |
| 53 | + end |
| 54 | + end |
| 55 | + |
| 56 | + def create_cube(xx, yy, zz, sz) |
| 57 | + dim = sz / 2.0 |
| 58 | + cube = create_shape |
| 59 | + cube.begin_shape(QUADS) |
| 60 | + # Front face |
| 61 | + cube.fill(255) |
| 62 | + cube.normal(0, 0, 1) |
| 63 | + cube.vertex(-dim + xx, -dim + yy, -dim + zz) |
| 64 | + cube.vertex(+dim + xx, -dim + yy, -dim + zz) |
| 65 | + cube.vertex(+dim + xx, +dim + yy, -dim + zz) |
| 66 | + cube.vertex(-dim + xx, +dim + yy, -dim + zz) |
| 67 | + |
| 68 | + # Back face |
| 69 | + |
| 70 | + cube.normal(0, 0, -1) |
| 71 | + cube.vertex(-dim + xx, -dim + yy, +dim + zz) |
| 72 | + cube.vertex(+dim + xx, -dim + yy, +dim + zz) |
| 73 | + cube.vertex(+dim + xx, +dim + yy, +dim + zz) |
| 74 | + cube.vertex(-dim + xx, +dim + yy, +dim + zz) |
| 75 | + |
| 76 | + # Left face |
| 77 | + |
| 78 | + cube.normal(1, 0, 0) |
| 79 | + cube.vertex(-dim + xx, -dim + yy, -dim + zz) |
| 80 | + cube.vertex(-dim + xx, -dim + yy, +dim + zz) |
| 81 | + cube.vertex(-dim + xx, +dim + yy, +dim + zz) |
| 82 | + cube.vertex(-dim + xx, +dim + yy, -dim + zz) |
| 83 | + |
| 84 | + # Right face |
| 85 | + |
| 86 | + cube.normal(-1, 0, 0) |
| 87 | + cube.vertex(+dim + xx, -dim + yy, -dim + zz) |
| 88 | + cube.vertex(+dim + xx, -dim + yy, +dim + zz) |
| 89 | + cube.vertex(+dim + xx, +dim + yy, +dim + zz) |
| 90 | + cube.vertex(+dim + xx, +dim + yy, -dim + zz) |
| 91 | + |
| 92 | + # Top face |
| 93 | + |
| 94 | + cube.normal(0, 1, 0) |
| 95 | + cube.vertex(-dim + xx, -dim + yy, -dim + zz) |
| 96 | + cube.vertex(+dim + xx, -dim + yy, -dim + zz) |
| 97 | + cube.vertex(+dim + xx, -dim + yy, +dim + zz) |
| 98 | + cube.vertex(-dim + xx, -dim + yy, +dim + zz) |
| 99 | + |
| 100 | + # Bottom face |
| 101 | + |
| 102 | + cube.normal(0, -1, 0) |
| 103 | + cube.vertex(-dim + xx, +dim + yy, -dim + zz) |
| 104 | + cube.vertex(+dim + xx, +dim + yy, -dim + zz) |
| 105 | + cube.vertex(+dim + xx, +dim + yy, +dim + zz) |
| 106 | + cube.vertex(-dim + xx, +dim + yy, +dim + zz) |
| 107 | + cube.end_shape |
| 108 | + cube |
| 109 | + end |
| 110 | + |
| 111 | + def define_lights |
| 112 | + ambient_light(180, 180, 180) |
| 113 | + point_light(30, 30, 30, 200, 240, 0) |
| 114 | + directional_light(50, 50, 50, 1, 0, 0) |
| 115 | + spot_light(30, 30, 30, 0, 40, 200, 0, -0.5, -0.5, PI / 2, 2) |
| 116 | + end |
| 117 | + |
| 118 | + def settings |
| 119 | + size(640, 480, P3D) |
| 120 | + smooth(8) |
| 121 | + end |
| 122 | +end |
| 123 | + |
| 124 | +RetainedMenger.new |
0 commit comments