Package toxi.volume

Source Code of toxi.volume.MeshLatticeBuilder

/*
*   __               .__       .__  ._____.          
* _/  |_  _______  __|__| ____ |  | |__\_ |__   ______
* \   __\/  _ \  \/  /  |/ ___\|  | |  || __ \ /  ___/
*  |  | (  <_> >    <|  \  \___|  |_|  || \_\ \\___ \
*  |__|  \____/__/\_ \__|\___  >____/__||___  /____  >
*                   \/       \/             \/     \/
*
* Copyright (c) 2006-2011 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
*/

package toxi.volume;

import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;

import toxi.geom.AABB;
import toxi.geom.Line3D;
import toxi.geom.Vec3D;
import toxi.geom.mesh.Mesh3D;
import toxi.geom.mesh.WETriangleMesh;
import toxi.geom.mesh.WingedEdge;
import toxi.math.ScaleMap;
import toxi.util.datatypes.FloatRange;
import toxi.util.datatypes.IntegerRange;

public class MeshLatticeBuilder {

    protected static final Logger logger = Logger
            .getLogger(MeshLatticeBuilder.class.getName());

    public static WETriangleMesh build(WETriangleMesh mesh, int res,
            float stroke) {
        return build(mesh, res, new FloatRange(stroke, stroke));
    }

    public static WETriangleMesh build(WETriangleMesh mesh, int res,
            FloatRange stroke) {
        VolumetricSpace volume = buildVolume(mesh, res, stroke);
        IsoSurface surface = new HashIsoSurface(volume);
        mesh = (WETriangleMesh) surface.computeSurfaceMesh(new WETriangleMesh(
                "iso", 300000, 900000), 0.2f);
        logger.info("created lattice mesh: " + mesh);
        return mesh;
    }

    public static VolumetricSpace buildVolume(WETriangleMesh mesh, int res,
            float stroke) {
        return buildVolume(mesh, res, new FloatRange(stroke, stroke));
    }

    public static VolumetricSpace buildVolume(WETriangleMesh mesh, int res,
            FloatRange stroke) {
        MeshLatticeBuilder builder = new MeshLatticeBuilder(mesh
                .getBoundingBox().getExtent().scale(2), res, res, res, stroke);
        return builder.buildVolume(mesh);
    }

    protected IntegerRange voxRangeX, voxRangeY, voxRangeZ;
    protected FloatRange stroke;

    private VolumetricSpace volume;

    private float drawStep = 0.5f;

    private ScaleMap bboxToVoxelX;

    private ScaleMap bboxToVoxelY;
    private ScaleMap bboxToVoxelZ;

    public MeshLatticeBuilder(Vec3D scale, int res, float stroke) {
        this(scale, res, res, res, new FloatRange(stroke, stroke));
    }

    public MeshLatticeBuilder(Vec3D scale, int resX, int resY, int resZ,
            FloatRange stroke) {
        this.stroke = stroke;
        this.voxRangeX = new IntegerRange(1, resX - 2);
        this.voxRangeY = new IntegerRange(1, resY - 2);
        this.voxRangeZ = new IntegerRange(1, resZ - 2);
        volume = new VolumetricHashMap(scale, resX, resY, resZ, 0.1f);
    }

    public WETriangleMesh buildLattice(WETriangleMesh mesh, Mesh3D targetMesh,
            float isoValue) {
        if (volume == null) {
            volume = buildVolume(mesh);
        }
        if (targetMesh == null) {
            targetMesh = new WETriangleMesh();
        }
        IsoSurface surface = new HashIsoSurface(volume);
        mesh = (WETriangleMesh) surface
                .computeSurfaceMesh(targetMesh, isoValue);
        return mesh;
    }

    public VolumetricSpace buildVolume(WETriangleMesh mesh) {
        VolumetricBrush brush = new RoundBrush(volume, 1);
        brush.setMode(VolumetricBrush.MODE_PEAK);
        return buildVolume(mesh, brush);
    }

    public VolumetricSpace buildVolume(final WETriangleMesh mesh,
            final VolumetricBrush brush) {
        logger.info("creating lattice...");
        setMesh(mesh);
        List<Float> edgeLengths = new ArrayList<Float>(mesh.edges.size());
        for (WingedEdge e : mesh.edges.values()) {
            edgeLengths.add(e.getLength());
        }
        FloatRange range = FloatRange.fromSamples(edgeLengths);
        ScaleMap brushSize = new ScaleMap(range.min, range.max, stroke.min,
                stroke.max);
        for (WingedEdge e : mesh.edges.values()) {
            brush.setSize((float) brushSize.getClippedValueFor(e.getLength()));
            createLattice(brush, e, drawStep);
        }
        volume.closeSides();
        return volume;
    }

    public void createLattice(VolumetricBrush brush, Line3D l, float drawStep) {
        List<Vec3D> points = l.splitIntoSegments(null, drawStep, true);
        for (Vec3D p : points) {
            float x = (float) bboxToVoxelX.getClippedValueFor(p.x);
            float y = (float) bboxToVoxelY.getClippedValueFor(p.y);
            float z = (float) bboxToVoxelZ.getClippedValueFor(p.z);
            brush.drawAtGridPos(x, y, z, 1);
        }
    }

    /**
     * @return the drawStep
     */
    public float getDrawStep() {
        return drawStep;
    }

    /**
     * @return the volume
     */
    public VolumetricSpace getVolume() {
        return volume;
    }

    /**
     * Sets the distance between {@link VolumetricBrush} positions when tracing
     * mesh edges.
     *
     * @param drawStep
     *            the drawStep to set
     */
    public void setDrawStepLength(float drawStep) {
        this.drawStep = drawStep;
    }

    public void setInputBounds(AABB box) {
        Vec3D bmin = box.getMin();
        Vec3D bmax = box.getMax();
        bboxToVoxelX = new ScaleMap(bmin.x, bmax.x, voxRangeX.min,
                voxRangeX.max);
        bboxToVoxelY = new ScaleMap(bmin.y, bmax.y, voxRangeY.min,
                voxRangeY.max);
        bboxToVoxelZ = new ScaleMap(bmin.z, bmax.z, voxRangeZ.min,
                voxRangeZ.max);
    }

    public void setMesh(WETriangleMesh mesh) {
        setInputBounds(mesh.getBoundingBox());
    }

    protected void setRangeMinMax(IntegerRange range, int min, int max,
            int maxRes) {
        // swap if necessary...
        if (min > max) {
            max ^= min;
            min ^= max;
            max ^= min;
        }
        if (min < 0 || min >= maxRes || max < 0 || max >= maxRes) {
            throw new IllegalArgumentException(
                    "voxel range min/max is out of bounds: " + min + "->" + max);
        }
        range.min = min;
        range.max = max;
    }

    /**
     * @param volume
     *            the volume to set
     */
    public void setVolume(VolumetricSpace volume) {
        this.volume = volume;
    }

    public MeshLatticeBuilder setVoxelRangeX(int min, int max) {
        setRangeMinMax(voxRangeX, min, max, volume.resX);
        return this;
    }

    public MeshLatticeBuilder setVoxelRangeY(int min, int max) {
        setRangeMinMax(voxRangeY, min, max, volume.resY);
        return this;
    }

    public MeshLatticeBuilder setVoxelRangeZ(int min, int max) {
        setRangeMinMax(voxRangeZ, min, max, volume.resZ);
        return this;
    }
}
TOP

Related Classes of toxi.volume.MeshLatticeBuilder

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.