001/**
002 * TriangleListShape3D -- A Java 3D Shape3D representation of a TriangleList.
003 *
004 * Copyright (C) 2015-2016, by Joseph A. Huwaldt. All rights reserved.
005 *
006 * This library is free software; you can redistribute it and/or modify it under the terms
007 * of the GNU Lesser General Public License as published by the Free Software Foundation;
008 * either version 2.1 of the License, or (at your option) any later version.
009 *
010 * This library is distributed in the hope that it will be useful, but WITHOUT ANY
011 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
012 * PARTICULAR PURPOSE. See the GNU Library General Public License for more details.
013 *
014 * You should have received a copy of the GNU Lesser General Public License along with
015 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place -
016 * Suite 330, Boston, MA 02111-1307, USA. Or visit: http://www.gnu.org/licenses/lgpl.html
017 */
018package geomss.j3d;
019
020import com.sun.j3d.utils.geometry.GeometryInfo;
021import com.sun.j3d.utils.geometry.NormalGenerator;
022import com.sun.j3d.utils.geometry.Stripifier;
023import geomss.geom.*;
024import jahuwaldt.js.param.Parameter;
025import static java.util.Objects.requireNonNull;
026import javax.measure.unit.SI;
027import javax.media.j3d.*;
028import javax.vecmath.*;
029
030/**
031 * A Shape3D object based on a {@link geomss.geom.TriangleList TriangleList}. The default
032 * appearance of the geometry is solid filled grey with lighting enabled.
033 *
034 * <p> Modified by: Joseph A. Huwaldt </p>
035 *
036 * @author Joseph A. Huwaldt, Date: August 29, 2015
037 * @version September 9, 2016
038 */
039public class TriangleListShape3D extends GeomShape3D {
040
041    /**
042     * @param parent The GeomSS geometry element that this Shape3D is associated with.
043     */
044    private TriangleListShape3D(GeomElement parent) {
045        super(parent);
046    }
047
048    /**
049     * Construct a TriangleListShape3D object from the specified {@link TriangleList}.
050     *
051     * @param parent The GeomSS geometry element that this Shape3D is associated with.
052     * @param list   The TriangleList to be converted into a J3D Shape3D object.
053     */
054    public TriangleListShape3D(GeomElement parent, TriangleList<? extends GeomTriangle> list) {
055        super(parent);
056
057        setGeometry(createGeometry(requireNonNull(list), true));
058    }
059
060    /**
061     * Construct a TriangleListShape3D object from the specified {@link TriangleList}.
062     *
063     * @param parent     The GeomSS geometry element that this Shape3D is associated with.
064     * @param list       The TriangleList to be converted into a J3D Shape3D object.
065     * @param appearance The Appearance to use when rendering the list of triangles.
066     */
067    public TriangleListShape3D(GeomElement parent, TriangleList<? extends GeomTriangle> list, Appearance appearance) {
068        this(parent, list);
069        setAppearance(requireNonNull(appearance));
070    }
071
072    /**
073     * Construct a TriangleListShape3D object from the specified {@link TriangleList}.
074     *
075     * @param parent     The GeomSS geometry element that this Shape3D is associated with.
076     * @param list       The TriangleList to be converted into a J3D Shape3D object.
077     * @param appearance The Appearance to use when rendering the list of triangles.
078     * @param stripify   Flag indicating if the list of individual triangles should be
079     *                   converted into triangle strips for rendering or not.
080     */
081    public TriangleListShape3D(GeomElement parent, TriangleList<? extends GeomTriangle> list,
082            Appearance appearance, boolean stripify) {
083        super(parent);
084
085        setGeometry(createGeometry(requireNonNull(list), stripify));
086        setAppearance(requireNonNull(appearance));
087    }
088
089    /**
090     * Used to create a new instance of the node.
091     *
092     * @param forceDuplicate when set to <code>true</code>, causes the
093     *                       <code>duplicateOnCloneTree</code> flag to be ignored. When
094     *                       <code>false</code>, the value of each node's
095     *                       <code>duplicateOnCloneTree</code> variable determines whether
096     *                       NodeComponent data is duplicated or copied.
097     * @return A new instance of this Java3D node.
098     */
099    @Override
100    public Node cloneNode(boolean forceDuplicate) {
101        TriangleListShape3D usc = new TriangleListShape3D(this.getGeometryElement());
102        usc.duplicateNode(this, forceDuplicate);
103        return usc;
104    }
105
106    /**
107     * Convert the TriangleList, and an optional list of vertex normals, into a J3D
108     * Geometry object here.
109     */
110    private Geometry createGeometry(TriangleList<? extends GeomTriangle> triLst, boolean stripify) {
111
112        //  Extract a minimal set of vertices and indexes from the triangle list.
113        TriangleVertData triData = triLst.toVertData(Parameter.valueOf(Parameter.SQRT_EPS, triLst.getUnit()));
114        PointString<? extends GeomPoint> verts = triData.vertices;
115        int[] coordIndices = triData.tris;
116
117        // Convert the list of GeomPoint vertices into J3D points.
118        int numDims = triLst.getPhyDimension();
119        int vertexCount = verts.size();
120        Point3f[] coordinates = new Point3f[vertexCount];
121        for (int i = 0; i < vertexCount; ++i) {
122            GeomPoint point = verts.get(i);
123
124            //  Convert all geometry to meters.
125            double x = point.getValue(0, SI.METER);
126            double y = point.getValue(1, SI.METER);
127            double z = (numDims > 2 ? point.getValue(2, SI.METER) : 0);
128            coordinates[i] = new Point3f((float)x, (float)y, (float)z);
129        }
130
131        // Create a GeomInfo object for our geometry.
132        GeometryInfo geomInfo = new GeometryInfo(GeometryInfo.TRIANGLE_ARRAY);
133        geomInfo.setCoordinates(coordinates);
134        geomInfo.setCoordinateIndices(coordIndices);
135
136        // Generate vertex normals automatically.
137        NormalGenerator ng = new NormalGenerator(0);    //  Use facet normals only (no smoothing).
138        ng.generateNormals(geomInfo);
139
140        if (stripify) {
141            // Stripify the geometry for increased performance.
142            Stripifier st = new Stripifier();
143            st.stripify(geomInfo);
144        }
145
146        return geomInfo.getGeometryArray();
147    }
148}