summaryrefslogtreecommitdiffstats
path: root/src/com/jogamp/graph/curve/tess
diff options
context:
space:
mode:
authorRami Santina <[email protected]>2011-03-25 03:58:05 +0100
committerSven Gothel <[email protected]>2011-03-25 03:58:05 +0100
commit7f745c32c5734bc9549a16a98d158cdc01215bf5 (patch)
treead798e477be7ff9903a98e3ee3ee51e130453d2e /src/com/jogamp/graph/curve/tess
parent6c07da79c276abef7a7c2f51b05fb1e04f7666db (diff)
Add initial GPU based curve rendering implementation, utilizing TTF fonts and manual shapes
Diffstat (limited to 'src/com/jogamp/graph/curve/tess')
-rw-r--r--src/com/jogamp/graph/curve/tess/CDTriangulator2D.java213
1 files changed, 213 insertions, 0 deletions
diff --git a/src/com/jogamp/graph/curve/tess/CDTriangulator2D.java b/src/com/jogamp/graph/curve/tess/CDTriangulator2D.java
new file mode 100644
index 000000000..936965f0c
--- /dev/null
+++ b/src/com/jogamp/graph/curve/tess/CDTriangulator2D.java
@@ -0,0 +1,213 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``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 JogAmp Community 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.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.graph.curve.tess;
+
+import java.util.ArrayList;
+
+import jogamp.graph.curve.tess.GraphOutline;
+import jogamp.graph.curve.tess.GraphPoint;
+import jogamp.graph.curve.tess.Loop;
+import jogamp.graph.math.VectorFloatUtil;
+
+import com.jogamp.graph.geom.Outline;
+import com.jogamp.graph.geom.Triangle;
+import com.jogamp.graph.geom.PointTex;
+import jogamp.opengl.Debug;
+
+/** Constrained Delaunay Triangulation
+ * implementation of a list of Outlines that define a set of
+ * Closed Regions with optional n holes.
+ *
+ */
+public class CDTriangulator2D <T extends PointTex> {
+
+ protected static final boolean DEBUG = Debug.debug("Triangulation");
+
+ private float sharpness = 0.5f;
+ private ArrayList<Loop<T>> loops;
+ private ArrayList<T> vertices;
+
+ private ArrayList<Triangle<T>> triangles;
+ private int maxTriID = 0;
+
+
+ public CDTriangulator2D() {
+ this(0.5f);
+ }
+
+ /** Constructor for a new Delaunay triangulator
+ * @param curveSharpness the curvature around
+ * the off-curve vertices
+ */
+ public CDTriangulator2D(float curveSharpness) {
+ this.sharpness = curveSharpness;
+ reset();
+ }
+
+ /** Reset the triangulation to initial state
+ * Clearing cached data
+ */
+ public void reset() {
+ maxTriID = 0;
+ vertices = new ArrayList<T>();
+ triangles = new ArrayList<Triangle<T>>(3);
+ loops = new ArrayList<Loop<T>>();
+ }
+
+ /** Add a curve to the list of profiles provided
+ * @param polyline a bounding Outline
+ */
+ public void addCurve(Outline<T> polyline){
+ Loop<T> loop = null;
+
+ if(!loops.isEmpty()){
+ loop = getContainerLoop(polyline);
+ }
+
+ if(loop == null) {
+ GraphOutline<T> outline = new GraphOutline<T>(polyline);
+ GraphOutline<T> innerPoly = extractBoundaryTriangles(outline, false);
+ vertices.addAll(polyline.getVertices());
+ loop = new Loop<T>(innerPoly, VectorFloatUtil.CCW);
+ loops.add(loop);
+ }
+ else {
+ GraphOutline<T> outline = new GraphOutline<T>(polyline);
+ GraphOutline<T> innerPoly = extractBoundaryTriangles(outline, true);
+ vertices.addAll(innerPoly.getPoints());
+ loop.addConstraintCurve(innerPoly);
+ }
+ }
+
+ /** Generate the triangulation of the provided
+ * List of Outlines
+ */
+ public ArrayList<Triangle<T>> generateTriangulation(){
+ for(int i=0;i<loops.size();i++) {
+ Loop<T> loop = loops.get(i);
+ int numTries = 0;
+ int size = loop.computeLoopSize();
+ while(!loop.isSimplex()){
+ Triangle<T> tri = null;
+ if(numTries > size){
+ tri = loop.cut(false);
+ }
+ else{
+ tri = loop.cut(true);
+ }
+ numTries++;
+
+ if(tri != null) {
+ numTries = 0;
+ size--;
+ tri.setId(maxTriID++);
+ triangles.add(tri);
+ if(DEBUG){
+ System.err.println(tri);
+ }
+ }
+ if(numTries > size*2){
+ if(DEBUG){
+ System.err.println("Triangulation not complete!");
+ }
+ break;
+ }
+ }
+ Triangle<T> tri = loop.cut(true);
+ if(tri != null)
+ triangles.add(tri);
+ }
+ return triangles;
+ }
+
+ @SuppressWarnings("unchecked")
+ private GraphOutline<T> extractBoundaryTriangles(GraphOutline<T> outline, boolean hole){
+ GraphOutline<T> innerOutline = new GraphOutline<T>();
+ ArrayList<GraphPoint<T>> outVertices = outline.getGraphPoint();
+ int size = outVertices.size();
+ for(int i=0; i < size; i++) {
+ GraphPoint<T> currentVertex = outVertices.get(i);
+ GraphPoint<T> gv0 = outVertices.get((i+size-1)%size);
+ GraphPoint<T> gv2 = outVertices.get((i+1)%size);
+ GraphPoint<T> gv1 = currentVertex;
+
+ if(!currentVertex.getPoint().isOnCurve()) {
+ T v0 = (T) gv0.getPoint().clone();
+ T v2 = (T) gv2.getPoint().clone();
+ T v1 = (T) gv1.getPoint().clone();
+
+ gv0.setBoundaryContained(true);
+ gv1.setBoundaryContained(true);
+ gv2.setBoundaryContained(true);
+
+ Triangle<T> t= null;
+ boolean holeLike = false;
+ if(VectorFloatUtil.ccw(v0,v1,v2)){
+ t = new Triangle<T>(v0, v1, v2);
+ }
+ else {
+ holeLike = true;
+ t = new Triangle<T>(v2, v1, v0);
+ }
+ t.setId(maxTriID++);
+ triangles.add(t);
+
+ if(hole || holeLike) {
+ v0.setTexCoord(0, -0.1f);
+ v2.setTexCoord(1, -0.1f);
+ v1.setTexCoord(0.5f, -1*sharpness -0.1f);
+ innerOutline.addVertex(currentVertex);
+ }
+ else {
+ v0.setTexCoord(0, 0.1f);
+ v2.setTexCoord(1, 0.1f);
+ v1.setTexCoord(0.5f, sharpness+0.1f);
+ }
+ }
+ else {
+ if(!gv2.getPoint().isOnCurve() || !gv0.getPoint().isOnCurve()){
+ currentVertex.setBoundaryContained(true);
+ }
+ innerOutline.addVertex(currentVertex);
+ }
+ }
+ return innerOutline;
+ }
+
+ private Loop<T> getContainerLoop(Outline<T> polyline){
+ T v = polyline.getVertex(0);
+
+ for (Loop<T> loop:loops){
+ if(loop.checkInside(v)){
+ return loop;
+ }
+ }
+ return null;
+ }
+}