/*
* Copyright (c) 2003-2009 jMonkeyEngine
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package automenta.spacenet.space.geom.text3d;
import automenta.spacenet.space.geom.text3d.math.ClosedPolygon;
import automenta.spacenet.space.geom.text3d.math.DoublyConnectedEdgeList;
import automenta.spacenet.space.geom.text3d.math.PlanarEdge;
import automenta.spacenet.space.geom.text3d.math.PlanarVertex;
import automenta.spacenet.space.geom.text3d.math.TriangulationVertex;
import automenta.spacenet.space.geom.text3d.math.Triangulator;
import com.ardor3d.math.Vector3;
import java.awt.geom.Rectangle2D;
import java.nio.IntBuffer;
import java.util.ArrayList;
import java.util.Vector;
/**
* This class represents a glyph of text.
*
* @author emanuel
*/
public class Glyph3D {
private static final long serialVersionUID = -8126290675830115033L;
/**
* This represents the planar subdivision of the glyph, before
* triangulation.
*/
Triangulator subdivision = new Triangulator();
Vector<PlanarEdge> outline;
Vector3 outline_normals[];
// These are the indices for the triangulation of the surface of the glyph.
IntBuffer surface;
private Rectangle2D bounds;
private Glyph3DMesh glyphmesh;
private char glyph_char;
private int childIndex = -1;
public Glyph3D(char glyph_char) {
this.glyph_char = glyph_char;
}
/**
* This method adds one closed polygon to the subdivision (it can both be
* the outer-polygon or the inner) In normal glyphs, the outer should be
* clockwise and the inner counter-clockwise. That is why we add the edges
* in the opposite order, due to the convention of
* {@link DoublyConnectedEdgeList}.
*/
public void addPolygon(ClosedPolygon poly) {
/*
* if(poly.isHole()) { logger.info("The Polygon is a hole, this might be
* alright."); }
*/
int first_vert_id = subdivision.getVertices().size();
for (Vector3 p : poly.getPoints()) {
PlanarVertex vert = subdivision.addVertex(p);
if (vert.getIndex() > first_vert_id) {
subdivision.addEdge(vert.getIndex(), vert.getIndex() - 1);
}
}
// Add the last one
subdivision.addEdge(first_vert_id, first_vert_id
+ poly.getPoints().size() - 1);
}
/**
* Triangulate the glyph, but first save the original outline.
*/
public void triangulate() {
// Save the outline and calculate normals
outline = new Vector<PlanarEdge>();
for (PlanarEdge e : subdivision.getEdges()) {
if (e.isRealEdge()) {
outline.add(e);
}
}
// Calculate outline normals
outline_normals = new Vector3[outline.size()];
for (PlanarEdge e : outline) {
TriangulationVertex vert = (TriangulationVertex) e.getDestination();
// Normal 1
Vector3 normal1 = new Vector3(vert.getOutGoingEdge()
.getDestination().getPoint())
.subtractLocal(vert.getPoint()).normalizeLocal();
// Vector3f normal1 = new
// Vector3f(vert.getOutGoingEdge().getDestination().getPoint()).subtractLocal(vert.getPoint());
// normal1.z = -normal1.x;
// normal1.x = normal1.y;
// normal1.y = normal1.z;
// normal1.z = 0;
normal1.set(normal1.getY(), normal1.getZ(), 0);
// Normal 2
Vector3 normal2 = new Vector3(vert.getPoint()).subtractLocal(
vert.getInGoingEdge().getOrigin().getPoint())
.normalizeLocal();
// Vector3f normal2 = new
// Vector3f(vert.getPoint()).subtractLocal(vert.getInGoingEdge().getOrigin().getPoint());
// normal2.z = -normal2.x;
// normal2.x = normal2.y;
// normal2.y = normal2.z;
// normal2.z = 0;
normal2.set(normal2.getY(), normal2.getZ(), 0);
normal1.addLocal(normal2).normalizeLocal();
outline_normals[vert.getIndex()] = normal1;
}
// Calculate the triangulation of the surface.
surface = subdivision.triangulate();
}
public boolean isEmpty() {
return subdivision.getVertices().size() == 0;
}
public Vector<PlanarEdge> getOutline() {
return outline;
}
public Vector3[] getOutlineNormals() {
return outline_normals;
}
public IntBuffer getSurface() {
return surface;
}
public void setBounds(Rectangle2D bounds2D) {
bounds = bounds2D;
}
public Rectangle2D getBounds() {
return bounds;
}
public ArrayList<TriangulationVertex> getVertices() {
return subdivision.getVertices();
}
/**
* Here we create the glyph-mesh from the triangulation (using
* sides/front/back according to arguments).
*
* @param drawBack
* @param drawFront
* @param drawSides
*/
public void generateMesh(boolean drawSides, boolean drawFront,
boolean drawBack) {
this.glyphmesh = new Glyph3DMesh(this, drawSides, drawFront, drawBack);
this.glyphmesh.setName("char: "+glyph_char);
}
public Glyph3DMesh getMesh() {
return glyphmesh;
}
public char getChar() {
return glyph_char;
}
public void setChildIndex(int index) {
this.childIndex = index;
}
public int getChildIndex() {
return childIndex;
}
}