/*
* 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.PlanarEdge;
import automenta.spacenet.space.geom.text3d.math.PlanarVertex;
import automenta.spacenet.space.geom.text3d.math.TriangulationVertex;
import com.ardor3d.bounding.OrientedBoundingBox;
import com.ardor3d.math.Vector2;
import com.ardor3d.math.Vector3;
import com.ardor3d.scenegraph.Mesh;
import com.ardor3d.util.geom.BufferUtils;
import java.nio.IntBuffer;
/**
* This class holds one glyph as a trimesh. The data is stored in this order:
* sides,front and back. Hence we get the following:
*
* <h4>Vertices/Normals/Texcoords/VertexColors buffers</h4>
* <ul>
* <li><i>n</i>*2 vertices used for the sides
* <li><i>n</i> vertices used for the front
* <li><i>n</i> vertices used for the back
* </ul>
* <h4>Indice buffer</h4>
* <ul>
* <li><i>n</i>*6 indices for the sides (<i>n</i>*2 triangles)
* <li>(<i>n</i>-2)*3 indices for the front (<i>n</i>-2 triangles)
* <li>(<i>n</i>-2)*3 indices for the back (<i>n</i>-2 triangles)
* </ul>
*
* TODO: We should have a threshold on the angle of the outline, that way we
* could make smooth only where it should actually be smooth.
*
* @author emanuel
*/
public class Glyph3DMesh extends Mesh {
private static final long serialVersionUID = -2744055578491222293L;
public Glyph3DMesh(Glyph3D glyph3D, boolean drawSides, boolean drawFront, boolean drawBack) {
super("");
// Calculate how many vertices we need
int vertex_count = 0;
int triangle_count = 0;
if (drawSides) {
vertex_count += glyph3D.getOutline().size() * 2;
triangle_count += glyph3D.getOutline().size() * 2;
}
if (drawFront) {
vertex_count += glyph3D.getVertices().size();
triangle_count += glyph3D.getSurface().capacity() / 3;
}
if (drawBack) {
vertex_count += glyph3D.getVertices().size();
triangle_count += glyph3D.getSurface().capacity() / 3;
}
// Allocate what we need
Vector3 verts[] = new Vector3[vertex_count];
Vector3 norms[] = new Vector3[vertex_count];
Vector2 texcoords[] = new Vector2[vertex_count];
IntBuffer triangles = BufferUtils.createIntBuffer(triangle_count * 3);
// triangles.rewind();
int vcount = 0; // Used to pad indexes.
// Add all the vertices (either one or two layers)
int numverts = glyph3D.getVertices().size();
if (drawSides) {
for (TriangulationVertex v : glyph3D.getVertices()) {
norms[v.getIndex()] = glyph3D.getOutlineNormals()[v.getIndex()];
verts[v.getIndex()] = new Vector3(v.getPoint());
verts[v.getIndex()].addLocal(0,0,0.5);
norms[v.getIndex() + numverts] = glyph3D.getOutlineNormals()[v
.getIndex()];
verts[v.getIndex() + numverts] = new Vector3(v.getPoint());
verts[v.getIndex() + numverts].addLocal(0,0,-0.5);
}
vcount += numverts * 2;
// Add indices
for (PlanarEdge e : glyph3D.getOutline()) {
if (!e.isRealEdge())
continue;
PlanarVertex src = e.getOrigin();
PlanarVertex dst = e.getDestination();
int v1 = src.getIndex();
int v2 = dst.getIndex();
int v3 = dst.getIndex() + numverts;
int v4 = src.getIndex() + numverts;
triangles.put(new int[] { v1, v3, v2, v3, v1, v4 });
}
}
if (drawFront) {
Vector3 backnormal = new Vector3(0, 0, 1);
for (TriangulationVertex v : glyph3D.getVertices()) {
norms[vcount + v.getIndex()] = backnormal;
verts[vcount + v.getIndex()] = new Vector3(v.getPoint());
verts[vcount + v.getIndex()].addLocal(0,0,0.5);
}
glyph3D.getSurface().rewind();
while (glyph3D.getSurface().remaining() > 0) {
int tri[] = { glyph3D.getSurface().get() + vcount,
glyph3D.getSurface().get() + vcount,
glyph3D.getSurface().get() + vcount };
triangles.put(tri[2]);
triangles.put(tri[1]);
triangles.put(tri[0]);
}
vcount += numverts;
}
if (drawBack) {
Vector3 frontnormal = new Vector3(0, 0, -1);
for (TriangulationVertex v : glyph3D.getVertices()) {
norms[vcount + v.getIndex()] = frontnormal;
verts[vcount + v.getIndex()] = new Vector3(v.getPoint());
verts[vcount + v.getIndex()].addLocal(0,0,-0.5);
}
// We need to add the offset (vertcount)
glyph3D.getSurface().rewind();
while (glyph3D.getSurface().remaining() > 0) {
triangles.put(glyph3D.getSurface().get() + vcount);
}
vcount += numverts;
}
// // Set the texture coords to the vertex coords (in X/Y plane)
// for(int i = 0;i < verts.length; i++)
// {
// texcoords[i] = new Vector2(verts[i].x, verts[i].y);
//
// }
getMeshData().setVertexBuffer(BufferUtils.createFloatBuffer(verts));
getMeshData().setNormalBuffer(BufferUtils.createFloatBuffer(norms));
//getMeshData().setTextureCoords(new TexCoords(BufferUtils.createFloatBuffer(texcoords)), 0);
getMeshData().setIndexBuffer(triangles);
// logger.info("triangles:"+triangles);
}
}