/* jCAE stand for Java Computer Aided Engineering. Features are : Small CAD
modeler, Finite element mesher, Plugin architecture.
Copyright (C) 2005, by EADS CRC
Copyright (C) 2007,2008, by EADS France
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.
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
package org.jcae.viewer3d;
import org.jcae.mesh.oemm.OEMM;
import org.jcae.mesh.amibe.ds.Mesh;
import org.jcae.mesh.amibe.ds.Triangle;
import org.jcae.mesh.amibe.ds.AbstractHalfEdge;
import org.jcae.mesh.amibe.ds.Vertex;
import java.util.Collection;
import javax.media.j3d.Appearance;
import javax.media.j3d.QuadArray;
import javax.media.j3d.Shape3D;
import javax.media.j3d.BranchGroup;
import javax.media.j3d.PolygonAttributes;
import javax.media.j3d.ColoringAttributes;
import javax.media.j3d.TriangleArray;
import javax.media.j3d.IndexedLineArray;
import javax.media.j3d.IndexedGeometryArray;
import javax.media.j3d.GeometryArray;
import javax.media.j3d.LineAttributes;
import java.util.logging.Logger;
public class OEMMViewer
{
private static Logger logger = Logger.getLogger(OEMMViewer.class.getName());
private final static float absOffsetStep = Float.parseFloat(System.getProperty("javax.media.j3d.zFactorAbs", "20.0f"));
private final static float relOffsetStep = Float.parseFloat(System.getProperty("javax.media.j3d.zFactorRel", "2.0f"));
public static BranchGroup bgOEMM(OEMM oemm, boolean onlyLeaves)
{
BranchGroup bg=new BranchGroup();
double [] coord = oemm.getCoords(onlyLeaves);
QuadArray quad = new QuadArray(coord.length/3, QuadArray.COORDINATES);
quad.setCapability(QuadArray.ALLOW_FORMAT_READ);
quad.setCapability(QuadArray.ALLOW_COUNT_READ);
quad.setCapability(QuadArray.ALLOW_COORDINATE_READ);
quad.setCoordinates(0, coord);
Appearance quadApp = new Appearance();
quadApp.setPolygonAttributes(new PolygonAttributes(PolygonAttributes.POLYGON_LINE, PolygonAttributes.CULL_NONE, 0));
quadApp.setColoringAttributes(new ColoringAttributes(0,1,0,ColoringAttributes.SHADE_GOURAUD));
Shape3D shapeQuad=new Shape3D(quad, quadApp);
shapeQuad.setCapability(Shape3D.ALLOW_GEOMETRY_READ);
bg.addChild(shapeQuad);
return bg;
}
public static BranchGroup meshOEMM(Mesh mesh)
{
// Mesh may be empty if all vertices are connected to
// external vertices
BranchGroup bg = new BranchGroup();
if (mesh.getTriangles().isEmpty())
return bg;
double [] coord = meshCoord(mesh);
if (coord.length == 0)
return bg;
TriangleArray tri = new TriangleArray(coord.length/3, TriangleArray.COORDINATES);
tri.setCapability(TriangleArray.ALLOW_COUNT_READ);
tri.setCapability(TriangleArray.ALLOW_FORMAT_READ);
tri.setCapability(TriangleArray.ALLOW_REF_DATA_READ);
tri.setCoordinates(0, coord);
Appearance blackFace = new Appearance();
PolygonAttributes pa = new PolygonAttributes(PolygonAttributes.POLYGON_FILL, PolygonAttributes.CULL_NONE, 2.0f*absOffsetStep, false, relOffsetStep);
ColoringAttributes ca = new ColoringAttributes(0,0,0,ColoringAttributes.SHADE_FLAT);
//pa.setCullFace(PolygonAttributes.CULL_BACK);
blackFace.setPolygonAttributes(pa);
blackFace.setColoringAttributes(ca);
Shape3D shapeFill = new Shape3D(tri, blackFace);
shapeFill.setCapability(Shape3D.ALLOW_GEOMETRY_READ);
bg.addChild(shapeFill);
Appearance wireFrame = new Appearance();
PolygonAttributes pa2 = new PolygonAttributes(PolygonAttributes.POLYGON_LINE, PolygonAttributes.CULL_NONE, absOffsetStep);
ColoringAttributes ca2 = new ColoringAttributes(0,0,1,ColoringAttributes.SHADE_GOURAUD);
//pa2.setCullFace(PolygonAttributes.CULL_BACK);
wireFrame.setPolygonAttributes(pa2);
wireFrame.setColoringAttributes(ca2);
Shape3D shapeLine = new Shape3D(tri, wireFrame);
shapeLine.setCapability(Shape3D.ALLOW_GEOMETRY_READ);
bg.addChild(shapeLine);
if (!mesh.hasAdjacency())
return bg;
// Free edges
int [] beams = meshFreeEdges(mesh);
if (beams.length <= 0)
return bg;
IndexedLineArray geom = new IndexedLineArray(
coord.length/3,
GeometryArray.COORDINATES|GeometryArray.BY_REFERENCE,
beams.length);
geom.setCoordinateIndices(0, beams);
geom.setCapability(GeometryArray.ALLOW_COUNT_READ);
geom.setCapability(GeometryArray.ALLOW_FORMAT_READ);
geom.setCapability(GeometryArray.ALLOW_REF_DATA_READ);
geom.setCapability(IndexedGeometryArray.ALLOW_COORDINATE_INDEX_READ);
geom.setCoordRefDouble(coord);
Appearance freeEdgeApp = new Appearance();
freeEdgeApp.setLineAttributes(new LineAttributes(1,LineAttributes.PATTERN_SOLID,false));
freeEdgeApp.setColoringAttributes(new ColoringAttributes(1.0f,0.0f,0.0f,ColoringAttributes.SHADE_FLAT));
Shape3D shapeFreeEdges = new Shape3D(geom, freeEdgeApp);
shapeFreeEdges.setCapability(Shape3D.ALLOW_GEOMETRY_READ);
bg.addChild(shapeFreeEdges);
logger.info("Number of free edges: "+(beams.length/2));
return bg;
}
private static final double [] meshCoord(Mesh mesh)
{
Collection<Triangle> triList = mesh.getTriangles();
boolean [] isViewable = new boolean[triList.size()];
int nrt = 0;
int i = 0;
for (Triangle t: triList)
{
isViewable[i] = isViewable(t);
if (isViewable[i])
nrt++;
i++;
}
double [] coord = new double[9*nrt];
nrt = 0;
i = 0;
for (Triangle t: triList)
{
if (isViewable[i])
{
for (int j = 0; j < 3; j++)
{
double [] xyz = t.vertex[j].getUV();
for (int k = 0; k < 3; k++)
coord[9*nrt+3*j+k] = xyz[k];
}
// Needed by meshFreeEdges() below
if (mesh.hasAdjacency())
{
for (int j = 0; j < 3; j++)
((Vertex) t.vertex[j]).setLabel(3*nrt+j);
}
nrt++;
}
i++;
}
return coord;
}
private static boolean isViewable(Triangle t)
{
return t.isReadable() && t.vertex[0].isReadable() && t.vertex[1].isReadable() && t.vertex[2].isReadable();
}
private static final int [] meshFreeEdges(Mesh mesh)
{
Collection<Triangle> triList = mesh.getTriangles();
int nrt = 0;
for (Triangle t: triList)
{
if (!t.isReadable())
continue;
AbstractHalfEdge e = t.getAbstractHalfEdge();
for (int j = 0; j < 3; j++)
{
e = e.next();
if (!e.origin().isWritable() && !e.destination().isWritable())
continue;
if (e.hasAttributes(AbstractHalfEdge.BOUNDARY))
nrt++;
}
}
int [] ret = new int[2*nrt];
int i = 0;
for (Triangle t: triList)
{
if (!t.isReadable())
continue;
AbstractHalfEdge e = t.getAbstractHalfEdge();
for (int j = 0; j < 3; j++)
{
e = e.next();
if (!e.origin().isWritable() && !e.destination().isWritable())
continue;
if (e.hasAttributes(AbstractHalfEdge.BOUNDARY))
{
ret[2*i] = e.origin().getLabel();
ret[2*i+1] = e.destination().getLabel();
i++;
}
}
}
return ret;
}
}