/**
*
This example demonstrates the MeshVoxelizer utility to turn a given
* triangle mesh into a volumetric representation for further manipulation.
* E.g. This is useful for some digital fabrication tasks when only a shell
* with a physical wall thickness is desired rather than a completely solid/filled
* polygon model. Other use cases incl. experimentation with VolumetricBrushes
* to drill holes into models etc.
*
* The MeshVoxelizer class is currently still in ongoing development, so any
* feature requests/ideas/help is appreciated.
*
* Usage:
* - v: voxelize current mesh (see details in function comment)
* - l: apply laplacian mesh smooth
* - w: wireframe on/off
* - n: show normals on/off
* - r: reset mesh
* - -/=: adjust zoom
*
*/
/*
* Copyright (c) 2010 Karsten Schmidt
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* http://creativecommons.org/licenses/LGPL/2.1/
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
import processing.opengl.*;
import toxi.geom.*;
import toxi.geom.mesh.*;
import toxi.geom.mesh.subdiv.*;
import toxi.processing.*;
import toxi.util.*;
import toxi.volume.*;
ToxiclibsSupport gfx;
WETriangleMesh mesh;
boolean isWireframe;
float currZoom = 1.25f;
boolean showNormals;
void setup() {
size(1280, 720, OPENGL);
gfx = new ToxiclibsSupport(this);
initMesh();
}
void draw() {
background(255);
translate(width / 2, height / 2, 0);
rotateX(mouseY * 0.01f);
rotateY(mouseX * 0.01f);
scale(currZoom);
if (!isWireframe) {
fill(255);
noStroke();
lights();
}
else {
gfx.origin(new Vec3D(), 100);
noFill();
stroke(0);
}
gfx.meshNormalMapped(mesh, !isWireframe, showNormals ? 10 : 0);
}
// creates a simple cube mesh and applies displacement subdivision
// on all edges for several iterations
void initMesh() {
mesh = new WETriangleMesh();
new AABB(new Vec3D(0, 0, 0), 100).toMesh(mesh);
for(int i=0; i<5; i++) {
SubdivisionStrategy subdiv = new MidpointDisplacementSubdivision(
mesh.computeCentroid(),
i % 2 == 0 ? 0.35f : -0.2f
);
mesh.subdivide(subdiv,0);
}
mesh.computeFaceNormals();
mesh.faceOutwards();
mesh.computeVertexNormals();
}
// this function will first translate the mesh into a volumetric version
// this volumetric representation will constitute of a solid shell
// coinciding (albeit with loss of precision) with the original mesh
// the function then calculates a new mesh of an iso surface in this voxel space
// the original mesh will be discarded (overwritten)
//
// if you have enough RAM and would like less holes in the resulting surface
// try a higher voxel resolution (e.g. 128, 192) and/or increase wall thickness
void voxelizeMesh() {
MeshVoxelizer voxelizer=new MeshVoxelizer(64);
// try setting to 1 or 2 (voxels)
voxelizer.setWallThickness(0);
VolumetricSpace vol = voxelizer.voxelizeMesh(mesh);
vol.closeSides();
IsoSurface surface = new HashIsoSurface(vol);
mesh = new WETriangleMesh();
surface.computeSurfaceMesh(mesh, 0.2f);
mesh.computeVertexNormals();
}
void keyPressed() {
if (key == 'w') {
isWireframe = !isWireframe;
}
if (key == 'l') {
new LaplacianSmooth().filter(mesh, 1);
}
if (key == '-') {
currZoom -= 0.1;
}
if (key == '=') {
currZoom += 0.1;
}
if (key == 'v') {
voxelizeMesh();
}
if (key == 'n') {
showNormals = !showNormals;
}
if (key=='r') {
initMesh();
}
}