|
| 1 | + |
| 2 | +# |
| 3 | +# <p>NoiseSurface demo showing how to utilize the IsoSurface class to efficiently |
| 4 | +# visualise volumetric data, in this case using 3D SimplexNoise. The demo also |
| 5 | +# shows how to save the generated mesh as binary STL file (or alternatively in |
| 6 | +# OBJ format) for later use in other 3D tools/digital fabrication.</p> |
| 7 | +# |
| 8 | +# <p>Further classes for the toxi.volume package are planned to easier draw |
| 9 | +# and manipulate volumetric data.</p> |
| 10 | +# |
| 11 | +# <p>Key controls:</p> |
| 12 | +# <ul> |
| 13 | +# <li>w : toggle rendering style between shaded/wireframe</li> |
| 14 | +# <li>s : save model as STL & quit</li> |
| 15 | +# <li>1-9 : adjust brush density</li> |
| 16 | +# <li>a-z : adjust density threshold for calculating surface</li> |
| 17 | +# <li>-/= : adjust zoom</li> |
| 18 | +# </ul> |
| 19 | +# |
| 20 | +# Copyright (c) 2009 Karsten Schmidt |
| 21 | +# |
| 22 | +# This demo & library is free software you can redistribute it and/or |
| 23 | +# modify it under the terms of the GNU Lesser General Public |
| 24 | +# License as published by the Free Software Foundation either |
| 25 | +# version 2.1 of the License, or (at your option) any later version. |
| 26 | +# |
| 27 | +# http:#creativecommons.org/licenses/LGPL/2.1/ |
| 28 | +# |
| 29 | +# This library is distributed in the hope that it will be useful, |
| 30 | +# but WITHOUT ANY WARRANTY without even the implied warranty of |
| 31 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 32 | +# Lesser General Public License for more details. |
| 33 | +# |
| 34 | +# You should have received a copy of the GNU Lesser General Public |
| 35 | +# License along with this library if not, write to the Free Software |
| 36 | +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
| 37 | +# |
| 38 | +require 'toxiclibs' |
| 39 | +include_package 'toxi.math.waves' # for SineWave |
| 40 | + |
| 41 | +DIMX = 96 |
| 42 | +DIMY = 96 |
| 43 | +DIMZ = 128 |
| 44 | +NS = 0.03 |
| 45 | +SCALE = TVec3D.new(256, 256, 384) |
| 46 | +Z_STEP = 0.005 |
| 47 | + |
| 48 | +attr_reader :gfx, :do_save, :mesh, :isurface, :volume, :brush, :brush_size |
| 49 | +attr_reader :iso_threshold, :curr_scale, :density, :spin, :curr_z |
| 50 | + |
| 51 | +def settings |
| 52 | + size(1024, 768, P3D) |
| 53 | +end |
| 54 | + |
| 55 | +def setup |
| 56 | + sketch_title 'Volumetric Cup' |
| 57 | + @isWireframe = false |
| 58 | + @do_save = false |
| 59 | + @gfx = Gfx::ToxiclibsSupport.new(self) |
| 60 | + stroke_weight(0.5) |
| 61 | + @volume = VolumetricSpaceArray.new(SCALE, DIMX, DIMY, DIMZ) |
| 62 | + @brush = RoundBrush.new(volume, SCALE.x / 2) |
| 63 | + @brush_size = SineWave.new( |
| 64 | + -HALF_PI, |
| 65 | + 2 * TWO_PI * Z_STEP, |
| 66 | + SCALE.x * 0.03, |
| 67 | + SCALE.x * 0.06 |
| 68 | + ) |
| 69 | + @isurface = ArrayIsoSurface.new(volume) |
| 70 | + @mesh = TriangleMesh.new |
| 71 | + @iso_threshold = 0.1 |
| 72 | + @curr_scale = 1 |
| 73 | + @density = 0.5 |
| 74 | + @spin = 8 |
| 75 | + @curr_z = 0 |
| 76 | +end |
| 77 | + |
| 78 | +def draw |
| 79 | + brush.setSize(brush_size.update) |
| 80 | + offsetZ = -SCALE.z + curr_z * SCALE.z * 2.6666 |
| 81 | + curr_radius = SCALE.x * 0.4 * sin(curr_z * PI) |
| 82 | + (0..TWO_PI).step(PI / 2) do |t| |
| 83 | + brush.drawAtAbsolutePos( |
| 84 | + TVec3D.new( |
| 85 | + curr_radius * cos(t + curr_z * spin), |
| 86 | + curr_radius * sin(t + curr_z * spin), |
| 87 | + offsetZ |
| 88 | + ), |
| 89 | + density |
| 90 | + ) |
| 91 | + brush.drawAtAbsolutePos( |
| 92 | + TVec3D.new( |
| 93 | + curr_radius * cos(t - curr_z * spin), |
| 94 | + curr_radius * sin(t - curr_z * spin), |
| 95 | + offsetZ |
| 96 | + ), |
| 97 | + density |
| 98 | + ) |
| 99 | + end |
| 100 | + @curr_z += Z_STEP |
| 101 | + volume.close_sides |
| 102 | + isurface.reset |
| 103 | + isurface.computeSurfaceMesh(mesh, iso_threshold) |
| 104 | + if do_save |
| 105 | + # save mesh as STL or OBJ file |
| 106 | + mesh.saveAsSTL(data_path(format('cup%d.stl', millis / 1_000 ))) |
| 107 | + @do_save = false |
| 108 | + exit |
| 109 | + end |
| 110 | + background(128) |
| 111 | + translate(width / 2, height / 2, 0) |
| 112 | + light_specular(230, 230, 230) |
| 113 | + directional_light(255, 255, 255, 1, 1, -1) |
| 114 | + shininess(1.0) |
| 115 | + rotate_x(-0.4) |
| 116 | + rotate_y(frame_count*0.05) |
| 117 | + scale(curr_scale) |
| 118 | + no_stroke |
| 119 | + gfx.mesh(mesh) |
| 120 | +end |
| 121 | + |
| 122 | +def key_pressed |
| 123 | + case key |
| 124 | + when '-' |
| 125 | + @curr_scale = max([curr_scale - 0.1, 0.5]) |
| 126 | + when '=' |
| 127 | + @curr_scale = min([curr_scale + 0.1, 10]) |
| 128 | + when 's' |
| 129 | + @do_save = true |
| 130 | + when '1'..'9' |
| 131 | + density = -0.5 + (key.to_i) * 0.1 |
| 132 | + puts density |
| 133 | + when '0' |
| 134 | + @density = 0.5 |
| 135 | + when 'a'..'z' |
| 136 | + @iso_threshold = (key.ord - 'a'.ord) * 0.019 + 0.01 |
| 137 | + end |
| 138 | +end |
0 commit comments