aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/jogl/classes/com/jogamp/graph/curve/OutlineShape.java106
-rw-r--r--src/jogl/classes/com/jogamp/graph/geom/Outline.java83
-rw-r--r--src/jogl/classes/com/jogamp/opengl/math/VectorUtil.java30
-rw-r--r--src/jogl/classes/jogamp/graph/curve/tess/CDTriangulator2D.java31
-rw-r--r--src/jogl/classes/jogamp/graph/curve/tess/GraphOutline.java8
-rw-r--r--src/jogl/classes/jogamp/graph/curve/tess/Loop.java107
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT01.java97
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/demos/GPUTextRendererListenerBase01.java21
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/demos/ui/TestObject01.java24
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/demos/ui/TestObject02.java302
-rw-r--r--src/test/com/jogamp/opengl/test/junit/graph/demos/ui/UITypeDemo01.java2
11 files changed, 654 insertions, 157 deletions
diff --git a/src/jogl/classes/com/jogamp/graph/curve/OutlineShape.java b/src/jogl/classes/com/jogamp/graph/curve/OutlineShape.java
index 1369061d3..fb0ff6a7e 100644
--- a/src/jogl/classes/com/jogamp/graph/curve/OutlineShape.java
+++ b/src/jogl/classes/com/jogamp/graph/curve/OutlineShape.java
@@ -43,19 +43,32 @@ import com.jogamp.opengl.math.FloatUtil;
import com.jogamp.opengl.math.VectorUtil;
import com.jogamp.opengl.math.geom.AABBox;
-
/**
* A Generic shape objects which is defined by a list of Outlines.
* This Shape can be transformed to triangulations.
* The list of triangles generated are render-able by a Region object.
* The triangulation produced by this Shape will define the
* closed region defined by the outlines.
- *
+ * <p>
* One or more OutlineShape Object can be associated to a region
* this is left as a high-level representation of the Objects. For
* optimizations, flexibility requirements for future features.
- *
- * <br><br>
+ * </p>
+ * <p>
+ * <a name="windingrules">
+ * Outline shape general {@link Winding} rules
+ * <ul>
+ * <li>Outer boundary shapes are required as {@link Winding#CCW}, if unsure
+ * <ul>
+ * <li>You may check {@link Winding} via {@link #getWindingOfLastOutline()} or {@link Outline#getWinding()} (optional)</li>
+ * <li>Use {@link #setWindingOfLastOutline(Winding)} before {@link #closeLastOutline(boolean)} or {@link #closePath()} } to enforce {@link Winding#CCW}, or</li>
+ * <li>use {@link Outline#setWinding(Winding)} on a specific {@link Outline} to enforce {@link Winding#CCW}.</li>
+ * <li>If e.g. the {@link Winding} has changed for an {@link Outline} by above operations, its vertices have been reversed.</li>
+ * </ul></li>
+ * <li>Inner shapes or holes are adjusted to be {@link Winding#CW}, no user consideration is required here.</li>
+ * <li>Safe path: Simply create all shapes with {@link Winding#CCW} or apply {@link Outline#setWinding(Winding)}.</li>
+ * </ul>
+ * </p>
* Example to creating an Outline Shape:
* <pre>
addVertex(...)
@@ -67,33 +80,35 @@ import com.jogamp.opengl.math.geom.AABBox;
addVertex(...)
* </pre>
*
+ * <p>
* The above will create two outlines each with three vertices. By adding these two outlines to
* the OutlineShape, we are stating that the combination of the two outlines represent the shape.
- * <br>
- *
+ * </p>
+ * <p>
* To specify that the shape is curved at a region, the on-curve flag should be set to false
* for the vertex that is in the middle of the curved region (if the curved region is defined by 3
* vertices (quadratic curve).
- * <br>
+ * </p>
+ * <p>
* In case the curved region is defined by 4 or more vertices the middle vertices should both have
* the on-curve flag set to false.
- *
- * <br>Example: <br>
+ * </p>
+ * Example:
* <pre>
addVertex(0,0, true);
addVertex(0,1, false);
addVertex(1,1, false);
addVertex(1,0, true);
* </pre>
- *
+ * <p>
* The above snippet defines a cubic nurbs curve where (0,1 and 1,1)
* do not belong to the final rendered shape.
+ * </p>
*
* <i>Implementation Notes:</i><br>
* <ul>
* <li> The first vertex of any outline belonging to the shape should be on-curve</li>
* <li> Intersections between off-curved parts of the outline is not handled</li>
- * <li> Outline shape winding shall be constructed counter clock wise ({@link Winding#CCW}).</li>
* </ul>
*
* @see Outline
@@ -226,6 +241,21 @@ public final class OutlineShape implements Comparable<OutlineShape> {
}
/**
+ * Compute the {@link Winding} of the {@link #getLastOutline()} using the {@link #area(ArrayList)} function over all of its vertices.
+ * @return {@link Winding#CCW} or {@link Winding#CW}
+ */
+ public final Winding getWindingOfLastOutline() {
+ return getLastOutline().getWinding();
+ }
+
+ /**
+ * Sets the enforced {@link Winding} of the {@link #getLastOutline()}.
+ */
+ public final void setWindingOfLastOutline(final Winding enforced) {
+ getLastOutline().setWinding(enforced);
+ }
+
+ /**
* Add a new empty {@link Outline}
* to the end of this shape's outline list.
* <p>If the {@link #getLastOutline()} is empty already, no new one will be added.</p>
@@ -358,9 +388,8 @@ public final class OutlineShape implements Comparable<OutlineShape> {
/**
* Adds a vertex to the last open outline to the shape's tail.
*
- * The constructed shape should be {@link Winding#CCW}.
- *
* @param v the vertex to be added to the OutlineShape
+ * @see <a href="#windingrules">see winding rules</a>
*/
public final void addVertex(final Vertex v) {
final Outline lo = getLastOutline();
@@ -375,10 +404,9 @@ public final class OutlineShape implements Comparable<OutlineShape> {
/**
* Adds a vertex to the last open outline to the shape at {@code position}
*
- * The constructed shape should be {@link Winding#CCW}.
- *
* @param position index within the last open outline, at which the vertex will be added
* @param v the vertex to be added to the OutlineShape
+ * @see <a href="#windingrules">see winding rules</a>
*/
public final void addVertex(final int position, final Vertex v) {
final Outline lo = getLastOutline();
@@ -393,12 +421,10 @@ public final class OutlineShape implements Comparable<OutlineShape> {
* Add a 2D {@link Vertex} to the last open outline to the shape's tail.
* The 2D vertex will be represented as Z=0.
*
- * The constructed shape should be {@link Winding#CCW}.
- *
* @param x the x coordinate
* @param y the y coordniate
- * @param onCurve flag if this vertex is on the final curve or defines a curved region
- * of the shape around this vertex.
+ * @param onCurve flag if this vertex is on the final curve or defines a curved region of the shape around this vertex.
+ * @see <a href="#windingrules">see winding rules</a>
*/
public final void addVertex(final float x, final float y, final boolean onCurve) {
addVertex(vertexFactory.create(x, y, 0f, onCurve));
@@ -408,13 +434,11 @@ public final class OutlineShape implements Comparable<OutlineShape> {
* Add a 2D {@link Vertex} to the last open outline to the shape at {@code position}.
* The 2D vertex will be represented as Z=0.
*
- * The constructed shape should be {@link Winding#CCW}.
- *
* @param position index within the last open outline, at which the vertex will be added
* @param x the x coordinate
* @param y the y coordniate
- * @param onCurve flag if this vertex is on the final curve or defines a curved region
- * of the shape around this vertex.
+ * @param onCurve flag if this vertex is on the final curve or defines a curved region of the shape around this vertex.
+ * @see <a href="#windingrules">see winding rules</a>
*/
public final void addVertex(final int position, final float x, final float y, final boolean onCurve) {
addVertex(position, vertexFactory.create(x, y, 0f, onCurve));
@@ -423,13 +447,11 @@ public final class OutlineShape implements Comparable<OutlineShape> {
/**
* Add a 3D {@link Vertex} to the last open outline to the shape's tail.
*
- * The constructed shape should be {@link Winding#CCW}.
- *
* @param x the x coordinate
* @param y the y coordinate
* @param z the z coordinate
- * @param onCurve flag if this vertex is on the final curve or defines a curved region
- * of the shape around this vertex.
+ * @param onCurve flag if this vertex is on the final curve or defines a curved region of the shape around this vertex.
+ * @see <a href="#windingrules">see winding rules</a>
*/
public final void addVertex(final float x, final float y, final float z, final boolean onCurve) {
addVertex(vertexFactory.create(x, y, z, onCurve));
@@ -438,14 +460,12 @@ public final class OutlineShape implements Comparable<OutlineShape> {
/**
* Add a 3D {@link Vertex} to the last open outline to the shape at {@code position}.
*
- * The constructed shape should be {@link Winding#CCW}.
- *
* @param position index within the last open outline, at which the vertex will be added
* @param x the x coordinate
* @param y the y coordniate
* @param z the z coordinate
- * @param onCurve flag if this vertex is on the final curve or defines a curved region
- * of the shape around this vertex.
+ * @param onCurve flag if this vertex is on the final curve or defines a curved region of the shape around this vertex.
+ * @see <a href="#windingrules">see winding rules</a>
*/
public final void addVertex(final int position, final float x, final float y, final float z, final boolean onCurve) {
addVertex(position, vertexFactory.create(x, y, z, onCurve));
@@ -454,8 +474,6 @@ public final class OutlineShape implements Comparable<OutlineShape> {
/**
* Add a vertex to the last open outline to the shape's tail.
*
- * The constructed shape should be {@link Winding#CCW}.
- *
* The vertex is passed as a float array and its offset where its attributes are located.
* The attributes should be continuous (stride = 0).
* Attributes which value are not set (when length less than 3)
@@ -463,8 +481,8 @@ public final class OutlineShape implements Comparable<OutlineShape> {
* @param coordsBuffer the coordinate array where the vertex attributes are to be picked from
* @param offset the offset in the buffer to the x coordinate
* @param length the number of attributes to pick from the buffer (maximum 3)
- * @param onCurve flag if this vertex is on the final curve or defines a curved region
- * of the shape around this vertex.
+ * @param onCurve flag if this vertex is on the final curve or defines a curved region of the shape around this vertex.
+ * @see <a href="#windingrules">see winding rules</a>
*/
public final void addVertex(final float[] coordsBuffer, final int offset, final int length, final boolean onCurve) {
addVertex(vertexFactory.create(coordsBuffer, offset, length, onCurve));
@@ -473,8 +491,6 @@ public final class OutlineShape implements Comparable<OutlineShape> {
/**
* Add a vertex to the last open outline to the shape at {@code position}.
*
- * The constructed shape should be {@link Winding#CCW}.
- *
* The vertex is passed as a float array and its offset where its attributes are located.
* The attributes should be continuous (stride = 0).
* Attributes which value are not set (when length less than 3)
@@ -483,8 +499,8 @@ public final class OutlineShape implements Comparable<OutlineShape> {
* @param coordsBuffer the coordinate array where the vertex attributes are to be picked from
* @param offset the offset in the buffer to the x coordinate
* @param length the number of attributes to pick from the buffer (maximum 3)
- * @param onCurve flag if this vertex is on the final curve or defines a curved region
- * of the shape around this vertex.
+ * @param onCurve flag if this vertex is on the final curve or defines a curved region of the shape around this vertex.
+ * @see <a href="#windingrules">see winding rules</a>
*/
public final void addVertex(final int position, final float[] coordsBuffer, final int offset, final int length, final boolean onCurve) {
addVertex(position, vertexFactory.create(coordsBuffer, offset, length, onCurve));
@@ -659,13 +675,12 @@ public final class OutlineShape implements Comparable<OutlineShape> {
/**
* Start a new position for the next line segment at given point x/y (P1).
*
- * The constructed shape should be {@link Winding#CCW}.
- *
* @param x point (P1)
* @param y point (P1)
* @param z point (P1)
* @see Path2F#moveTo(float, float)
* @see #addPath(com.jogamp.graph.geom.plane.Path2F.Iterator, boolean)
+ * @see <a href="#windingrules">see winding rules</a>
*/
public final void moveTo(final float x, final float y, final float z) {
if ( 0 == getLastOutline().getVertexCount() ) {
@@ -680,13 +695,12 @@ public final class OutlineShape implements Comparable<OutlineShape> {
/**
* Add a line segment, intersecting the last point and the given point x/y (P1).
*
- * The constructed shape should be {@link Winding#CCW}.
- *
* @param x final point (P1)
* @param y final point (P1)
* @param z final point (P1)
* @see Path2F#lineTo(float, float)
* @see #addPath(com.jogamp.graph.geom.plane.Path2F.Iterator, boolean)
+ * @see <a href="#windingrules">see winding rules</a>
*/
public final void lineTo(final float x, final float y, final float z) {
addVertex(x, y, z, true);
@@ -695,8 +709,6 @@ public final class OutlineShape implements Comparable<OutlineShape> {
/**
* Add a quadratic curve segment, intersecting the last point and the second given point x2/y2 (P2).
*
- * The constructed shape should be {@link Winding#CCW}.
- *
* @param x1 quadratic parametric control point (P1)
* @param y1 quadratic parametric control point (P1)
* @param z1 quadratic parametric control point (P1)
@@ -705,6 +717,7 @@ public final class OutlineShape implements Comparable<OutlineShape> {
* @param z2 quadratic parametric control point (P2)
* @see Path2F#quadTo(float, float, float, float)
* @see #addPath(com.jogamp.graph.geom.plane.Path2F.Iterator, boolean)
+ * @see <a href="#windingrules">see winding rules</a>
*/
public final void quadTo(final float x1, final float y1, final float z1, final float x2, final float y2, final float z2) {
addVertex(x1, y1, z1, false);
@@ -714,8 +727,6 @@ public final class OutlineShape implements Comparable<OutlineShape> {
/**
* Add a cubic Bézier curve segment, intersecting the last point and the second given point x3/y3 (P3).
*
- * The constructed shape should be {@link Winding#CCW}.
- *
* @param x1 Bézier control point (P1)
* @param y1 Bézier control point (P1)
* @param z1 Bézier control point (P1)
@@ -727,6 +738,7 @@ public final class OutlineShape implements Comparable<OutlineShape> {
* @param z3 final interpolated control point (P3)
* @see Path2F#cubicTo(float, float, float, float, float, float)
* @see #addPath(com.jogamp.graph.geom.plane.Path2F.Iterator, boolean)
+ * @see <a href="#windingrules">see winding rules</a>
*/
public final void cubicTo(final float x1, final float y1, final float z1, final float x2, final float y2, final float z2, final float x3, final float y3, final float z3) {
addVertex(x1, y1, z1, false);
diff --git a/src/jogl/classes/com/jogamp/graph/geom/Outline.java b/src/jogl/classes/com/jogamp/graph/geom/Outline.java
index b18d51849..7c9cb69c9 100644
--- a/src/jogl/classes/com/jogamp/graph/geom/Outline.java
+++ b/src/jogl/classes/com/jogamp/graph/geom/Outline.java
@@ -30,6 +30,7 @@ package com.jogamp.graph.geom;
import java.util.ArrayList;
import com.jogamp.graph.geom.plane.AffineTransform;
+import com.jogamp.graph.geom.plane.Winding;
import com.jogamp.graph.curve.OutlineShape;
import com.jogamp.graph.curve.Region;
import com.jogamp.opengl.math.FloatUtil;
@@ -54,6 +55,8 @@ public class Outline implements Comparable<Outline> {
private boolean closed;
private final AABBox bbox;
private boolean dirtyBBox;
+ private Winding winding;
+ private boolean dirtyWinding;
/**Create an outline defined by control vertices.
* An outline can contain off Curve vertices which define curved
@@ -64,14 +67,19 @@ public class Outline implements Comparable<Outline> {
closed = false;
bbox = new AABBox();
dirtyBBox = false;
+ winding = Winding.CCW;
+ dirtyWinding = false;
}
/**
* Copy ctor
*/
public Outline(final Outline src) {
- vertices = new ArrayList<Vertex>(src.vertices.size());
- for(int i=0; i<vertices.size(); i++) {
+ final int count = src.vertices.size();
+ vertices = new ArrayList<Vertex>(count);
+ winding = src.getWinding();
+ dirtyWinding = false;
+ for(int i=0; i<count; i++) {
vertices.add( src.vertices.get(i).clone() );
}
closed = src.closed;
@@ -79,6 +87,74 @@ public class Outline implements Comparable<Outline> {
dirtyBBox = src.dirtyBBox;
}
+ /**
+ * Copy ctor w/ enforced Winding
+ * <p>
+ * If the enforced {@link Winding} doesn't match the source Outline, the vertices reversed copied into this new instance.
+ * </p>
+ * @param src the source Outline
+ * @param enforce {@link Winding} to be enforced on this copy
+ */
+ public Outline(final Outline src, final Winding enforce) {
+ final int count = src.vertices.size();
+ vertices = new ArrayList<Vertex>(count);
+ final Winding had_winding = src.getWinding();;
+ winding = had_winding;
+ dirtyWinding = false;
+ if( enforce != had_winding ) {
+ for(int i=count-1; i>=0; --i) {
+ vertices.add( src.vertices.get(i).clone() );
+ }
+ winding = enforce;
+ } else {
+ for(int i=0; i<count; ++i) {
+ vertices.add( src.vertices.get(i).clone() );
+ }
+ }
+ closed = src.closed;
+ bbox = new AABBox(src.bbox);
+ dirtyBBox = src.dirtyBBox;
+ }
+
+ /**
+ * Sets {@link Winding} to this outline
+ * <p>
+ * If the enforced {@link Winding} doesn't match this Outline, the vertices are reversed.
+ * </p>
+ * @param enforce to be enforced {@link Winding}
+ */
+ public final void setWinding(final Winding enforce) {
+ final Winding had_winding = getWinding();
+ if( enforce != had_winding ) {
+ final int count = vertices.size();
+ final ArrayList<Vertex> ccw = new ArrayList<Vertex>(count);
+ for(int i=count-1; i>=0; --i) {
+ ccw.add(vertices.get(i));
+ }
+ vertices = ccw;
+ winding = enforce;
+ }
+ }
+
+ /**
+ * Compute the winding of the {@link #getLastOutline()} using the {@link #area(ArrayList)} function over all of its vertices.
+ * @return {@link Winding#CCW} or {@link Winding#CW}
+ */
+ public final Winding getWinding() {
+ if( !dirtyWinding ) {
+ return winding;
+ }
+ final int count = getVertexCount();
+ if( 3 > count ) {
+ winding = Winding.CCW;
+ } else {
+ final ArrayList<Vertex> vertices = getVertices();
+ winding = VectorUtil.getWinding(vertices);
+ }
+ dirtyWinding = false;
+ return winding;
+ }
+
public final int getVertexCount() {
return vertices.size();
}
@@ -107,6 +183,7 @@ public class Outline implements Comparable<Outline> {
if(!dirtyBBox) {
bbox.resize(vertex.getCoord());
}
+ dirtyWinding = true;
}
/** Replaces the {@link Vertex} element at the given {@code position}.
@@ -123,6 +200,7 @@ public class Outline implements Comparable<Outline> {
}
vertices.set(position, vertex);
dirtyBBox = true;
+ dirtyWinding = true;
}
public final Vertex getVertex(final int index){
@@ -141,6 +219,7 @@ public class Outline implements Comparable<Outline> {
*/
public final Vertex removeVertex(final int position) throws IndexOutOfBoundsException {
dirtyBBox = true;
+ dirtyWinding = true;
return vertices.remove(position);
}
diff --git a/src/jogl/classes/com/jogamp/opengl/math/VectorUtil.java b/src/jogl/classes/com/jogamp/opengl/math/VectorUtil.java
index 3ee504a29..d7e72e245 100644
--- a/src/jogl/classes/com/jogamp/opengl/math/VectorUtil.java
+++ b/src/jogl/classes/com/jogamp/opengl/math/VectorUtil.java
@@ -888,25 +888,35 @@ public final class VectorUtil {
return triAreaVec2(a,b,c) > 0;
}
- /** Compute the winding of given points
+ /**
+ * Compute the winding of the 3 given points
+ * <p>
+ * Consider using {@link #getWinding(ArrayList)} using the {@link #area(ArrayList)} function over all points
+ * on complex shapes for a reliable result!
+ * </p>
* @param a first vertex
* @param b second vertex
* @param c third vertex
- * @return Winding
+ * @return {@link Winding#CCW} or {@link Winding#CW}
+ * @see #getWinding(ArrayList)
*/
public static Winding getWinding(final Vert2fImmutable a, final Vert2fImmutable b, final Vert2fImmutable c) {
return triAreaVec2(a,b,c) > 0 ? Winding.CCW : Winding.CW ;
}
- /** Computes the area of a list of vertices to check if ccw
+ /**
+ * Computes the area of a list of vertices.
+ * <p>
+ * This method is utilized e.g. to reliably compute the {@link Winding} of complex shapes.
+ * </p>
* @param vertices
* @return positive area if ccw else negative area value
+ * @see #getWinding(ArrayList)
*/
public static float area(final ArrayList<? extends Vert2fImmutable> vertices) {
final int n = vertices.size();
float area = 0.0f;
- for (int p = n - 1, q = 0; q < n; p = q++)
- {
+ for (int p = n - 1, q = 0; q < n; p = q++) {
final float[] pCoord = vertices.get(p).getCoord();
final float[] qCoord = vertices.get(q).getCoord();
area += pCoord[0] * qCoord[1] - qCoord[0] * pCoord[1];
@@ -914,9 +924,15 @@ public final class VectorUtil {
return area;
}
- /** Compute the general winding of the vertices
+ /**
+ * Compute the winding using the {@link #area(ArrayList)} function over all vertices for complex shapes.
+ * <p>
+ * Uses the {@link #area(ArrayList)} function over all points
+ * on complex shapes for a reliable result!
+ * </p>
* @param vertices array of Vertices
- * @return CCW or CW {@link Winding}
+ * @return {@link Winding#CCW} or {@link Winding#CW}
+ * @see #area(ArrayList)
*/
public static Winding getWinding(final ArrayList<? extends Vert2fImmutable> vertices) {
return area(vertices) >= 0 ? Winding.CCW : Winding.CW ;
diff --git a/src/jogl/classes/jogamp/graph/curve/tess/CDTriangulator2D.java b/src/jogl/classes/jogamp/graph/curve/tess/CDTriangulator2D.java
index 369d0b493..331116f7e 100644
--- a/src/jogl/classes/jogamp/graph/curve/tess/CDTriangulator2D.java
+++ b/src/jogl/classes/jogamp/graph/curve/tess/CDTriangulator2D.java
@@ -80,20 +80,20 @@ public class CDTriangulator2D implements Triangulator {
@Override
public final void addCurve(final List<Triangle> sink, final Outline polyline, final float sharpness) {
- Loop loop = null;
-
- if(!loops.isEmpty()) {
- loop = getContainerLoop(polyline);
- }
+ Loop loop = getContainerLoop(polyline);
if(loop == null) {
- final GraphOutline outline = new GraphOutline(polyline);
+ final Winding winding = Winding.CCW; // -> HEdge.BOUNDARY
+ // Too late: polyline.setWinding(winding);
+ final GraphOutline outline = new GraphOutline(polyline); // , winding);
final GraphOutline innerPoly = extractBoundaryTriangles(sink, outline, false, sharpness);
// vertices.addAll(polyline.getVertices());
- loop = new Loop(innerPoly, Winding.CCW);
+ loop = new Loop(innerPoly, winding);
loops.add(loop);
} else {
- final GraphOutline outline = new GraphOutline(polyline);
+ // final Winding winding = Winding.CW; // -> HEdge.HOLE
+ // Not required, handled in Loop.initFromPolyline(): polyline.setWinding(winding);
+ final GraphOutline outline = new GraphOutline(polyline); // , winding);
final GraphOutline innerPoly = extractBoundaryTriangles(sink, outline, true, sharpness);
// vertices.addAll(innerPoly.getVertices());
loop.addConstraintCurve(innerPoly);
@@ -221,12 +221,15 @@ public class CDTriangulator2D implements Triangulator {
}
private Loop getContainerLoop(final Outline polyline) {
- final ArrayList<Vertex> vertices = polyline.getVertices();
- for(int i=0; i < loops.size(); i++) {
- final Loop loop = loops.get(i);
- for(int j=0; j < vertices.size(); j++) {
- if( loop.checkInside( vertices.get(j) ) ) {
- return loop;
+ final int count = loops.size();
+ if( 0 < count ) {
+ final ArrayList<Vertex> vertices = polyline.getVertices();
+ for(int i=0; i < count; i++) {
+ final Loop loop = loops.get(i);
+ for(int j=0; j < vertices.size(); j++) {
+ if( loop.checkInside( vertices.get(j) ) ) {
+ return loop;
+ }
}
}
}
diff --git a/src/jogl/classes/jogamp/graph/curve/tess/GraphOutline.java b/src/jogl/classes/jogamp/graph/curve/tess/GraphOutline.java
index 81e6efdad..75192d45a 100644
--- a/src/jogl/classes/jogamp/graph/curve/tess/GraphOutline.java
+++ b/src/jogl/classes/jogamp/graph/curve/tess/GraphOutline.java
@@ -31,6 +31,7 @@ import java.util.ArrayList;
import com.jogamp.graph.geom.Outline;
import com.jogamp.graph.geom.Vertex;
+import com.jogamp.graph.geom.plane.Winding;
public class GraphOutline {
final private Outline outline;
@@ -40,11 +41,14 @@ public class GraphOutline {
this.outline = new Outline();
}
- /**Create a control polyline of control vertices
+ /**
+ * Create a control polyline of control vertices
* the curve pieces can be identified by onCurve flag
* of each cp the control polyline is open by default
+ *
+ * @param ol the source {@link Outline}
*/
- public GraphOutline(final Outline ol){
+ public GraphOutline(final Outline ol) {
this.outline = ol;
final ArrayList<Vertex> vertices = this.outline.getVertices();
for(int i = 0; i< vertices.size(); i++){
diff --git a/src/jogl/classes/jogamp/graph/curve/tess/Loop.java b/src/jogl/classes/jogamp/graph/curve/tess/Loop.java
index 5d1bc051f..1d8264607 100644
--- a/src/jogl/classes/jogamp/graph/curve/tess/Loop.java
+++ b/src/jogl/classes/jogamp/graph/curve/tess/Loop.java
@@ -34,6 +34,7 @@ import com.jogamp.graph.geom.Vertex;
import com.jogamp.graph.geom.plane.Winding;
import com.jogamp.graph.geom.Triangle;
import com.jogamp.opengl.math.VectorUtil;
+import com.jogamp.opengl.math.Vert2fImmutable;
import com.jogamp.opengl.math.geom.AABBox;
public class Loop {
@@ -91,9 +92,24 @@ public class Loop {
return (root.getNext().getNext().getNext() == root);
}
- /**Create a connected list of half edges (loop)
+ private static float area(final ArrayList<GraphVertex> vertices) {
+ final int n = vertices.size();
+ float area = 0.0f;
+ for (int p = n - 1, q = 0; q < n; p = q++) {
+ final float[] pCoord = vertices.get(p).getCoord();
+ final float[] qCoord = vertices.get(q).getCoord();
+ area += pCoord[0] * qCoord[1] - qCoord[0] * pCoord[1];
+ }
+ return area;
+ }
+ private static Winding getWinding(final ArrayList<GraphVertex> vertices) {
+ return area(vertices) >= 0 ? Winding.CCW : Winding.CW ;
+ }
+
+ /**
+ * Create a connected list of half edges (loop)
* from the boundary profile
- * @param reqWinding requested winding of edges (CCW or CW)
+ * @param reqWinding requested winding of edges, either {@link Winding#CCW} for {@link HEdge#BOUNDARY} or {@link Winding#CW} for {@link HEdge#HOLE}
*/
private HEdge initFromPolyline(final GraphOutline outline, final Winding reqWinding){
final ArrayList<GraphVertex> vertices = outline.getGraphPoint();
@@ -101,57 +117,64 @@ public class Loop {
if(vertices.size()<3) {
throw new IllegalArgumentException("outline's vertices < 3: " + vertices.size());
}
- final Winding hasWinding = VectorUtil.getWinding(
- vertices.get(0).getPoint(),
- vertices.get(1).getPoint(),
- vertices.get(2).getPoint());
- //FIXME: handle case when vertices come inverted - Rami
- // skips inversion CW -> CCW
- final boolean invert = hasWinding != reqWinding &&
- reqWinding == Winding.CW;
-
- final int max;
+ final Winding hasWinding = getWinding( vertices ); // requires area-winding detection
+
final int edgeType = reqWinding == Winding.CCW ? HEdge.BOUNDARY : HEdge.HOLE ;
- int index;
HEdge firstEdge = null;
HEdge lastEdge = null;
- if(!invert) {
- max = vertices.size();
- index = 0;
- } else {
- max = -1;
- index = vertices.size() -1;
- }
-
- while(index != max){
- final GraphVertex v1 = vertices.get(index);
- box.resize(v1.getX(), v1.getY(), v1.getZ());
-
- final HEdge edge = new HEdge(v1, edgeType);
-
- v1.addEdge(edge);
- if(lastEdge != null) {
- lastEdge.setNext(edge);
- edge.setPrev(lastEdge);
- } else {
- firstEdge = edge;
- }
-
- if(!invert) {
- if(index == vertices.size()-1) {
+ /**
+ * The winding conversion CW -> CCW can't be resolved here (-> Rami?)
+ * Therefore we require outline boundaries to be in CCW, see API-doc comment in OutlineShape.
+ *
+ * Original comment:
+ * FIXME: handle case when vertices come inverted - Rami
+ * Skips inversion CW -> CCW
+ */
+ if( hasWinding == reqWinding || reqWinding == Winding.CCW ) {
+ // Correct Winding or skipped CW -> CCW (no inversion possible here, too late ??)
+ final int max = vertices.size() - 1;
+ for(int index = 0; index <= max; ++index) {
+ final GraphVertex v1 = vertices.get(index);
+ box.resize(v1.getX(), v1.getY(), v1.getZ());
+
+ final HEdge edge = new HEdge(v1, edgeType);
+
+ v1.addEdge(edge);
+ if(lastEdge != null) {
+ lastEdge.setNext(edge);
+ edge.setPrev(lastEdge);
+ } else {
+ firstEdge = edge;
+ }
+ if(index == max ) {
edge.setNext(firstEdge);
firstEdge.setPrev(edge);
}
- index++;
- } else {
+ lastEdge = edge;
+ }
+ } else { // if( reqWinding == Winding.CW ) {
+ // CCW -> CW
+ for(int index = vertices.size() - 1; index >= 0; --index) {
+ final GraphVertex v1 = vertices.get(index);
+ box.resize(v1.getX(), v1.getY(), v1.getZ());
+
+ final HEdge edge = new HEdge(v1, edgeType);
+
+ v1.addEdge(edge);
+ if(lastEdge != null) {
+ lastEdge.setNext(edge);
+ edge.setPrev(lastEdge);
+ } else {
+ firstEdge = edge;
+ }
+
if (index == 0) {
edge.setNext(firstEdge);
firstEdge.setPrev(edge);
}
- index--;
+ lastEdge = edge;
}
- lastEdge = edge;
}
return firstEdge;
}
@@ -159,7 +182,7 @@ public class Loop {
public void addConstraintCurve(final GraphOutline polyline) {
// GraphOutline outline = new GraphOutline(polyline);
/**needed to generate vertex references.*/
- initFromPolyline(polyline, Winding.CW);
+ initFromPolyline(polyline, Winding.CW); // -> HEdge.HOLE
final GraphVertex v3 = locateClosestVertex(polyline);
final HEdge v3Edge = v3.findBoundEdge();
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT01.java b/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT01.java
index 8826275b1..52ca9041b 100644
--- a/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT01.java
+++ b/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT01.java
@@ -48,6 +48,7 @@ import org.junit.runners.MethodSorters;
import com.jogamp.common.os.Platform;
import com.jogamp.graph.curve.Region;
import com.jogamp.graph.curve.opengl.RenderState;
+import com.jogamp.graph.font.Font;
import com.jogamp.graph.font.FontFactory;
import com.jogamp.graph.font.FontSet;
import com.jogamp.graph.geom.SVertex;
@@ -142,51 +143,87 @@ public class TestTextRendererNEWT01 extends UITestCase {
final Runnable action_per_font = new Runnable() {
@Override
public void run() {
+ if( false ) {
+ textGLListener.setHeadBox(1, false);
+ textGLListener.setSampleCount(2);
+ window.display();
+ textGLListener.printScreenOnGLThread(window, "./", window.getTitle(), "", false);
+ sleep();
+
+ textGLListener.setHeadBox(2, false);
+ textGLListener.setSampleCount(2);
+ window.display();
+ textGLListener.printScreenOnGLThread(window, "./", window.getTitle(), "", false);
+ sleep();
+ }
+
textGLListener.setHeadBox(1, false);
- textGLListener.setSampleCount(2);
+ textGLListener.setSampleCount(4);
window.display();
textGLListener.printScreenOnGLThread(window, "./", window.getTitle(), "", false);
sleep();
textGLListener.setHeadBox(2, false);
- textGLListener.setSampleCount(2);
+ textGLListener.setSampleCount(4);
window.display();
textGLListener.printScreenOnGLThread(window, "./", window.getTitle(), "", false);
sleep();
+ } };
- textGLListener.setHeadBox(1, false);
- textGLListener.setSampleCount(3);
- window.display();
- textGLListener.printScreenOnGLThread(window, "./", window.getTitle(), "", false);
- sleep();
+ final Font[] fonts = FontSet01.getSet01();
+ for(final Font f : fonts) {
+ if( textGLListener.setFont(f) ) {
+ action_per_font.run();
+ }
+ }
+ if(textGLListener.setFontSet(FontFactory.JAVA, 0, 0)) {
+ action_per_font.run();
+ }
+ destroyWindow(window);
+ }
- textGLListener.setHeadBox(2, false);
- textGLListener.setSampleCount(3);
- window.display();
- textGLListener.printScreenOnGLThread(window, "./", window.getTitle(), "", false);
- sleep();
+ @Test
+ public void testTextRendererMSAA01() throws InterruptedException, GLException, IOException {
+ final GLProfile glp = GLProfile.get(GLProfile.GL2ES2);
+ final GLCapabilities caps = new GLCapabilities(glp);
+ caps.setAlphaBits(4);
+ caps.setSampleBuffers(true);
+ caps.setNumSamples(4);
+ System.err.println("Requested: "+caps);
+
+ final GLWindow window = createWindow("text-vbaa0-msaa1", caps, 1024, 640);
+ window.display();
+ System.err.println("Chosen: "+window.getChosenGLCapabilities());
+ final RenderState rs = RenderState.createRenderState(SVertex.factory());
+ final TextGLListener textGLListener = new TextGLListener(rs, 0, 0 /* sampleCount */, DEBUG, TRACE);
+ textGLListener.attachInputListenerTo(window);
+ window.addGLEventListener(textGLListener);
+ textGLListener.setHeadBox(2, true);
+ window.display();
+
+ final Runnable action_per_font = new Runnable() {
+ @Override
+ public void run() {
textGLListener.setHeadBox(1, false);
- textGLListener.setSampleCount(4);
+ textGLListener.setSampleCount(0);
window.display();
textGLListener.printScreenOnGLThread(window, "./", window.getTitle(), "", false);
sleep();
textGLListener.setHeadBox(2, false);
- textGLListener.setSampleCount(4);
+ textGLListener.setSampleCount(0);
window.display();
textGLListener.printScreenOnGLThread(window, "./", window.getTitle(), "", false);
sleep();
} };
- if(textGLListener.setFontSet(FontFactory.UBUNTU, FontSet.FAMILY_LIGHT, FontSet.STYLE_NONE)) {
- action_per_font.run();
- }
-
- if(textGLListener.setFontSet(FontFactory.UBUNTU, FontSet.FAMILY_REGULAR, FontSet.STYLE_NONE)) {
- action_per_font.run();
+ final Font[] fonts = FontSet01.getSet01();
+ for(final Font f : fonts) {
+ if( textGLListener.setFont(f) ) {
+ action_per_font.run();
+ }
}
-
if(textGLListener.setFontSet(FontFactory.JAVA, 0, 0)) {
action_per_font.run();
}
@@ -195,15 +232,13 @@ public class TestTextRendererNEWT01 extends UITestCase {
}
@Test
- public void testTextRendererMSAA01() throws InterruptedException, GLException, IOException {
+ public void testTextRendererNoSampling() throws InterruptedException, GLException, IOException {
final GLProfile glp = GLProfile.get(GLProfile.GL2ES2);
final GLCapabilities caps = new GLCapabilities(glp);
caps.setAlphaBits(4);
- caps.setSampleBuffers(true);
- caps.setNumSamples(4);
System.err.println("Requested: "+caps);
- final GLWindow window = createWindow("text-vbaa0-msaa1", caps, 1024, 640);
+ final GLWindow window = createWindow("text-vbaa0-msaa0", caps, 1024, 640);
window.display();
System.err.println("Chosen: "+window.getChosenGLCapabilities());
@@ -230,14 +265,12 @@ public class TestTextRendererNEWT01 extends UITestCase {
sleep();
} };
- if(textGLListener.setFontSet(FontFactory.UBUNTU, FontSet.FAMILY_LIGHT, FontSet.STYLE_NONE)) {
- action_per_font.run();
- }
-
- if(textGLListener.setFontSet(FontFactory.UBUNTU, FontSet.FAMILY_REGULAR, FontSet.STYLE_NONE)) {
- action_per_font.run();
+ final Font[] fonts = FontSet01.getSet01();
+ for(final Font f : fonts) {
+ if( textGLListener.setFont(f) ) {
+ action_per_font.run();
+ }
}
-
if(textGLListener.setFontSet(FontFactory.JAVA, 0, 0)) {
action_per_font.run();
}
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUTextRendererListenerBase01.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUTextRendererListenerBase01.java
index b86cc60aa..7b1fe6177 100644
--- a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUTextRendererListenerBase01.java
+++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUTextRendererListenerBase01.java
@@ -34,7 +34,6 @@ import com.jogamp.opengl.GL2ES2;
import com.jogamp.opengl.GLAnimatorControl;
import com.jogamp.opengl.GLAutoDrawable;
import com.jogamp.opengl.GLException;
-import com.jogamp.opengl.GLRunnable;
import com.jogamp.opengl.fixedfunc.GLMatrixFunc;
import com.jogamp.common.util.InterruptSource;
import com.jogamp.graph.curve.Region;
@@ -46,7 +45,6 @@ import com.jogamp.graph.font.Font;
import com.jogamp.graph.font.FontFactory;
import com.jogamp.graph.font.FontScale;
import com.jogamp.graph.font.FontSet;
-import com.jogamp.graph.font.Font.Glyph;
import com.jogamp.newt.Window;
import com.jogamp.newt.event.KeyEvent;
import com.jogamp.newt.event.KeyListener;
@@ -114,21 +112,21 @@ public abstract class GPUTextRendererListenerBase01 extends GPURendererListenerB
"in lorem. Maecenas in ipsum ac justo scelerisque sollicitudin. Quisque sit amet neque lorem, \n" +
"-------Press H to change text---------";
- public static final String textX2 = // Kvæven -> Kvaven (error)
+ public static final String textX2 =
"I “Ask Jeff” or ‘Ask Jeff’. Take the chef d’œuvre! Two of [of] (of) ‘of’ “of” of? of! of*. X\n"+
"Les Woëvres, the Fôret de Wœvres, the Voire and Vauvise. Yves is in heaven; D’Amboise is in jail. X\n"+
"Lyford’s in Texas & L’Anse-aux-Griffons in Québec; the Łyna in Poland. Yriarte, Yciar and Ysaÿe are at Yale. X\n"+
- "Kyoto and Ryotsu are both in Japan, Kwikpak on the Yukon delta, Kvaven in Norway, Kyulu in Kenya, not in Rwanda.… X\n"+
+ "Kyoto and Ryotsu are both in Japan, Kwikpak on the Yukon delta, Kvæven in Norway, Kyulu in Kenya, not in Rwanda.… X\n"+
"Von-Vincke-Straße in Münster, Vdovino in Russia, Ytterbium in the periodic table. Are Toussaint L’Ouverture, Wölfflin, Wolfe, X\n"+
"Miłosz and Wū Wŭ all in the library? 1510–1620, 11:00 pm, and the 1980s are over. X\n"+
"-------Press H to change text---------";
- public static final String textX20 = // Kvæven -> Kvaven (error)
+ public static final String textX20 =
"I “Ask Jeff” or ‘Ask Jeff’. Take the chef d’œuvre! Two of [of] (of) ‘of’ “of” of? of! of*.\n"+
"Two of [of] (of) ‘of’ “of” of? of! of*. Ydes, Yffignac and Ygrande are in France: so are Ypres,\n"+
"Les Woëvres, the Fôret de Wœvres, the Voire and Vauvise. Yves is in heaven; D’Amboise is in jail.\n"+
"Lyford’s in Texas & L’Anse-aux-Griffons in Québec; the Łyna in Poland. Yriarte, Yciar and Ysaÿe are at Yale.\n"+
- "Kyoto and Ryotsu are both in Japan, Kwikpak on the Yukon delta, Kvaven in Norway, Kyulu in Kenya, not in Rwanda.…\n"+
+ "Kyoto and Ryotsu are both in Japan, Kwikpak on the Yukon delta, Kvæven in Norway, Kyulu in Kenya, not in Rwanda.…\n"+
"Walton’s in West Virginia, but «Wren» is in Oregon. Tlálpan is near Xochimilco in México.\n"+
"The Zygos & Xylophagou are in Cyprus, Zwettl in Austria, Fænø in Denmark, the Vøringsfossen and Værøy in Norway.\n"+
"Tchula is in Mississippi, the Tittabawassee in Michigan. Twodot is here in Montana, Ywamun in Burma.\n"+
@@ -448,6 +446,17 @@ public abstract class GPUTextRendererListenerBase01 extends GPURendererListenerB
return false;
}
+ public boolean setFont(final Font _font) {
+ if(null != _font) {
+ // fontSet = ???
+ font = _font;
+ fontName = font.getFullFamilyName()+" (head "+fontSizeHead+"pt)";
+ fontNameBox = font.getMetricBounds(fontName);
+ return true;
+ }
+ return false;
+ }
+
public boolean isUserInputMode() { return userInput; }
void dumpMatrix(final boolean bbox) {
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/TestObject01.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/TestObject01.java
index c3df7c7ed..d2bff1fee 100644
--- a/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/TestObject01.java
+++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/TestObject01.java
@@ -33,6 +33,7 @@ import com.jogamp.graph.curve.OutlineShape;
import com.jogamp.graph.curve.opengl.RegionRenderer;
import com.jogamp.graph.geom.Vertex;
import com.jogamp.graph.geom.Vertex.Factory;
+import com.jogamp.graph.geom.plane.Winding;
/**
* GPU based resolution independent test object
@@ -51,13 +52,17 @@ public class TestObject01 extends UIShape {
protected void destroyImpl(final GL2ES2 gl, final RegionRenderer renderer) {
}
+ @SuppressWarnings("unused")
@Override
protected void addShapeToRegion(final GL2ES2 gl, final RegionRenderer renderer) {
final OutlineShape shape = new OutlineShape(renderer.getRenderState().getVertexFactory());
// lower case 'o'
// Start TTF Shape for Glyph 82
- if( true ) {
+ if( false ) {
+ // Original Outer shape: Winding.CW
+ // Moved into OutlineShape reverse -> Winding.CCW -> OK
+ //
// Shape.MoveTo:
shape.closeLastOutline(false);
shape.addEmptyOutline();
@@ -126,8 +131,12 @@ public class TestObject01 extends UIShape {
// Shape.QuadTo:
shape.addVertex(0, 0.527000f, 0.319000f, false);
shape.addVertex(0, 0.527000f, 0.258000f, true);
+ System.err.println("TestObject01.shape01a.winding_area: "+shape.getWindingOfLastOutline());
shape.closeLastOutline(false);
} else {
+ // Outer shape: Winding.CW
+ // Moved into OutlineShape same-order -> Winding.CW -> ERROR (so we fix it in the end, see below)
+ //
// Shape.MoveTo:
shape.closeLastOutline(false);
shape.addEmptyOutline();
@@ -196,10 +205,16 @@ public class TestObject01 extends UIShape {
// Shape.QuadTo:
shape.addVertex(0.527000f, 0.319000f, false);
shape.addVertex(0.527000f, 0.258000f, true);
+ System.err.println("TestObject01.shape01b.1.winding_area: "+shape.getWindingOfLastOutline());
+ shape.setWindingOfLastOutline(Winding.CCW);
+ System.err.println("TestObject01.shape01b.2.winding_area: "+shape.getWindingOfLastOutline());
shape.closeLastOutline(false);
}
- if( false ) {
+ if( true ) {
+ // Original Inner shape: Winding.CCW
+ // Moved into OutlineShape reverse -> Winding.CW -> OK
+ //
// Shape.MoveTo:
shape.closeLastOutline(false);
shape.addEmptyOutline();
@@ -236,8 +251,12 @@ public class TestObject01 extends UIShape {
// Shape.QuadTo:
shape.addVertex(0, 0.458000f, 0.161000f, false);
shape.addVertex(0, 0.458000f, 0.258000f, true);
+ System.err.println("TestObject01.shape02a.winding_area: "+shape.getWindingOfLastOutline());
shape.closeLastOutline(false);
} else {
+ // Inner shape: Winding.CCW
+ // Moved into OutlineShape same-order -> Winding.CCW -> OK
+ //
// Shape.MoveTo:
shape.closeLastOutline(false);
shape.addEmptyOutline();
@@ -276,6 +295,7 @@ public class TestObject01 extends UIShape {
shape.addVertex(0.458000f, 0.161000f, false);
shape.addVertex(0.458000f, 0.258000f, true);
+ System.err.println("TestObject01.shape02b.winding_area: "+shape.getWindingOfLastOutline());
shape.closeLastOutline(false);
}
// End Shape for Glyph 82
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/TestObject02.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/TestObject02.java
index 34aec67c3..fe1d965ee 100644
--- a/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/TestObject02.java
+++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/TestObject02.java
@@ -51,6 +51,7 @@ public class TestObject02 extends UIShape {
protected void destroyImpl(final GL2ES2 gl, final RegionRenderer renderer) {
}
+ @SuppressWarnings("unused")
@Override
protected void addShapeToRegion(final GL2ES2 gl, final RegionRenderer renderer) {
final OutlineShape shape = new OutlineShape(renderer.getRenderState().getVertexFactory());
@@ -58,7 +59,10 @@ public class TestObject02 extends UIShape {
// lower case 'æ'
// Start TTF Shape for Glyph 193
- {
+ if( true ) {
+ // Original Inner e-shape: Winding.CCW
+ // Moved into OutlineShape reverse -> Winding.CW -> OK
+ //
// Shape.MoveTo:
shape.closeLastOutline(false);
shape.addEmptyOutline();
@@ -90,10 +94,51 @@ public class TestObject02 extends UIShape {
// 008: B1: line-to p0-p1
// Shape.LineTo:
shape.addVertex(0, 0.728000f, 0.300000f, true);
+ System.err.println("TestObject02.shape01a.winding_area: "+shape.getWindingOfLastOutline());
+ shape.closeLastOutline(false);
+ } else {
+ // Inner e-shape: Winding.CCW
+ // Moved into OutlineShape same-order -> Winding.CCW -> ??
+ //
+ // Shape.MoveTo:
+ shape.closeLastOutline(false);
+ shape.addEmptyOutline();
+ shape.addVertex(0.728000f, 0.300000f, true);
+ // 000: B4: quad-to p0-p1-p2h **** MID
+ // Shape.QuadTo:
+ shape.addVertex(0.726000f, 0.381000f, false);
+ shape.addVertex(0.690000f, 0.426000f, true);
+ // 002: B6: quad-to pMh-p0-p1
+ // Shape.QuadTo:
+ shape.addVertex(0.654000f, 0.471000f, false);
+ shape.addVertex(0.588000f, 0.471000f, true);
+ // 003: B4: quad-to p0-p1-p2h **** MID
+ // Shape.QuadTo:
+ shape.addVertex(0.553000f, 0.471000f, false);
+ shape.addVertex(0.526000f, 0.457000f, true);
+ // 005: B5: quad-to pMh-p0-p1h ***** MID
+ // Shape.QuadTo:
+ shape.addVertex(0.498000f, 0.443000f, false);
+ shape.addVertex(0.478000f, 0.420000f, true);
+ // 006: B5: quad-to pMh-p0-p1h ***** MID
+ // Shape.QuadTo:
+ shape.addVertex(0.457000f, 0.396000f, false);
+ shape.addVertex(0.446000f, 0.365000f, true);
+ // 007: B6: quad-to pMh-p0-p1
+ // Shape.QuadTo:
+ shape.addVertex(0.434000f, 0.334000f, false);
+ shape.addVertex(0.432000f, 0.300000f, true);
+ // 008: B1: line-to p0-p1
+ // Shape.LineTo:
+ shape.addVertex(0.728000f, 0.300000f, true);
+ System.err.println("TestObject02.shape01b.winding_area: "+shape.getWindingOfLastOutline());
shape.closeLastOutline(false);
}
- {
+ if( true ) {
+ // Original Outer shape: Winding.CW
+ // Moved into OutlineShape reverse -> Winding.CCW -> OK
+ //
// Shape.MoveTo:
shape.closeLastOutline(false);
shape.addEmptyOutline();
@@ -270,10 +315,196 @@ public class TestObject02 extends UIShape {
// Shape.QuadTo:
shape.addVertex(0, 0.289000f, -0.011000f, false);
shape.addVertex(0, 0.252000f, -0.011000f, true);
+ System.err.println("TestObject02.shape02a.winding_area: "+shape.getWindingOfLastOutline());
+ shape.closeLastOutline(false);
+ } else {
+ // Outer shape: Winding.CW
+ // Moved into OutlineShape same-order -> Winding.CW -> OK now
+ //
+ // Shape.MoveTo:
+ shape.closeLastOutline(false);
+ shape.addEmptyOutline();
+ shape.addVertex(0.252000f, -0.011000f, true);
+ // 009: B4: quad-to p0-p1-p2h **** MID
+ // Shape.QuadTo:
+ shape.addVertex(0.208000f, -0.011000f, false);
+ shape.addVertex(0.171000f, -0.002000f, true);
+ // 011: B5: quad-to pMh-p0-p1h ***** MID
+ // Shape.QuadTo:
+ shape.addVertex(0.133000f, 0.007000f, false);
+ shape.addVertex(0.106000f, 0.026000f, true);
+ // 012: B5: quad-to pMh-p0-p1h ***** MID
+ // Shape.QuadTo:
+ shape.addVertex(0.079000f, 0.046000f, false);
+ shape.addVertex(0.064000f, 0.076000f, true);
+ // 013: B6: quad-to pMh-p0-p1
+ // Shape.QuadTo:
+ shape.addVertex(0.048000f, 0.107000f, false);
+ shape.addVertex(0.048000f, 0.151000f, true);
+ // 014: B4: quad-to p0-p1-p2h **** MID
+ // Shape.QuadTo:
+ shape.addVertex(0.048000f, 0.193000f, false);
+ shape.addVertex(0.064000f, 0.223000f, true);
+ // 016: B5: quad-to pMh-p0-p1h ***** MID
+ // Shape.QuadTo:
+ shape.addVertex(0.080000f, 0.253000f, false);
+ shape.addVertex(0.109000f, 0.272000f, true);
+ // 017: B5: quad-to pMh-p0-p1h ***** MID
+ // Shape.QuadTo:
+ shape.addVertex(0.138000f, 0.292000f, false);
+ shape.addVertex(0.178000f, 0.301000f, true);
+ // 018: B6: quad-to pMh-p0-p1
+ // Shape.QuadTo:
+ shape.addVertex(0.218000f, 0.310000f, false);
+ shape.addVertex(0.265000f, 0.310000f, true);
+ // 019: B4: quad-to p0-p1-p2h **** MID
+ // Shape.QuadTo:
+ shape.addVertex(0.279000f, 0.310000f, false);
+ shape.addVertex(0.294000f, 0.309000f, true);
+ // 021: B5: quad-to pMh-p0-p1h ***** MID
+ // Shape.QuadTo:
+ shape.addVertex(0.310000f, 0.307000f, false);
+ shape.addVertex(0.324000f, 0.305000f, true);
+ // 022: B5: quad-to pMh-p0-p1h ***** MID
+ // Shape.QuadTo:
+ shape.addVertex(0.339000f, 0.302000f, false);
+ shape.addVertex(0.349000f, 0.300000f, true);
+ // 023: B6: quad-to pMh-p0-p1
+ // Shape.QuadTo:
+ shape.addVertex(0.360000f, 0.297000f, false);
+ shape.addVertex(0.364000f, 0.295000f, true);
+ // 024: B1: line-to p0-p1
+ // Shape.LineTo:
+ shape.addVertex(0.364000f, 0.327000f, true);
+ // 025: B4: quad-to p0-p1-p2h **** MID
+ // Shape.QuadTo:
+ shape.addVertex(0.364000f, 0.354000f, false);
+ shape.addVertex(0.360000f, 0.379000f, true);
+ // 027: B5: quad-to pMh-p0-p1h ***** MID
+ // Shape.QuadTo:
+ shape.addVertex(0.356000f, 0.405000f, false);
+ shape.addVertex(0.343000f, 0.425000f, true);
+ // 028: B5: quad-to pMh-p0-p1h ***** MID
+ // Shape.QuadTo:
+ shape.addVertex(0.329000f, 0.446000f, false);
+ shape.addVertex(0.305000f, 0.458000f, true);
+ // 029: B6: quad-to pMh-p0-p1
+ // Shape.QuadTo:
+ shape.addVertex(0.280000f, 0.471000f, false);
+ shape.addVertex(0.240000f, 0.471000f, true);
+ // 030: B4: quad-to p0-p1-p2h **** MID
+ // Shape.QuadTo:
+ shape.addVertex(0.186000f, 0.471000f, false);
+ shape.addVertex(0.156000f, 0.464000f, true);
+ // 032: B6: quad-to pMh-p0-p1
+ // Shape.QuadTo:
+ shape.addVertex(0.126000f, 0.456000f, false);
+ shape.addVertex(0.113000f, 0.451000f, true);
+ // 033: B1: line-to p0-p1
+ // Shape.LineTo:
+ shape.addVertex(0.105000f, 0.507000f, true);
+ // 034: B4: quad-to p0-p1-p2h **** MID
+ // Shape.QuadTo:
+ shape.addVertex(0.122000f, 0.515000f, false);
+ shape.addVertex(0.158000f, 0.522000f, true);
+ // 036: B6: quad-to pMh-p0-p1
+ // Shape.QuadTo:
+ shape.addVertex(0.194000f, 0.529000f, false);
+ shape.addVertex(0.243000f, 0.529000f, true);
+ // 037: B4: quad-to p0-p1-p2h **** MID
+ // Shape.QuadTo:
+ shape.addVertex(0.314000f, 0.529000f, false);
+ shape.addVertex(0.354000f, 0.503000f, true);
+ // 039: B6: quad-to pMh-p0-p1
+ // Shape.QuadTo:
+ shape.addVertex(0.395000f, 0.476000f, false);
+ shape.addVertex(0.412000f, 0.431000f, true);
+ // 040: B4: quad-to p0-p1-p2h **** MID
+ // Shape.QuadTo:
+ shape.addVertex(0.445000f, 0.480000f, false);
+ shape.addVertex(0.491000f, 0.504000f, true);
+ // 042: B6: quad-to pMh-p0-p1
+ // Shape.QuadTo:
+ shape.addVertex(0.537000f, 0.529000f, false);
+ shape.addVertex(0.587000f, 0.529000f, true);
+ // 043: B4: quad-to p0-p1-p2h **** MID
+ // Shape.QuadTo:
+ shape.addVertex(0.682000f, 0.529000f, false);
+ shape.addVertex(0.738000f, 0.467000f, true);
+ // 045: B6: quad-to pMh-p0-p1
+ // Shape.QuadTo:
+ shape.addVertex(0.795000f, 0.405000f, false);
+ shape.addVertex(0.795000f, 0.276000f, true);
+ // 046: B4: quad-to p0-p1-p2h **** MID
+ // Shape.QuadTo:
+ shape.addVertex(0.795000f, 0.268000f, false);
+ shape.addVertex(0.795000f, 0.260000f, true);
+ // 048: B6: quad-to pMh-p0-p1
+ // Shape.QuadTo:
+ shape.addVertex(0.794000f, 0.252000f, false);
+ shape.addVertex(0.793000f, 0.245000f, true);
+ // 049: B1: line-to p0-p1
+ // Shape.LineTo:
+ shape.addVertex(0.430000f, 0.245000f, true);
+ // 050: B4: quad-to p0-p1-p2h **** MID
+ // Shape.QuadTo:
+ shape.addVertex(0.433000f, 0.150000f, false);
+ shape.addVertex(0.477000f, 0.099000f, true);
+ // 052: B6: quad-to pMh-p0-p1
+ // Shape.QuadTo:
+ shape.addVertex(0.521000f, 0.048000f, false);
+ shape.addVertex(0.617000f, 0.048000f, true);
+ // 053: B4: quad-to p0-p1-p2h **** MID
+ // Shape.QuadTo:
+ shape.addVertex(0.670000f, 0.048000f, false);
+ shape.addVertex(0.701000f, 0.058000f, true);
+ // 055: B6: quad-to pMh-p0-p1
+ // Shape.QuadTo:
+ shape.addVertex(0.732000f, 0.068000f, false);
+ shape.addVertex(0.746000f, 0.075000f, true);
+ // 056: B1: line-to p0-p1
+ // Shape.LineTo:
+ shape.addVertex(0.758000f, 0.019000f, true);
+ // 057: B4: quad-to p0-p1-p2h **** MID
+ // Shape.QuadTo:
+ shape.addVertex(0.744000f, 0.011000f, false);
+ shape.addVertex(0.706000f, 0.000000f, true);
+ // 059: B6: quad-to pMh-p0-p1
+ // Shape.QuadTo:
+ shape.addVertex(0.667000f, -0.011000f, false);
+ shape.addVertex(0.615000f, -0.011000f, true);
+ // 060: B4: quad-to p0-p1-p2h **** MID
+ // Shape.QuadTo:
+ shape.addVertex(0.558000f, -0.011000f, false);
+ shape.addVertex(0.514000f, 0.003000f, true);
+ // 062: B6: quad-to pMh-p0-p1
+ // Shape.QuadTo:
+ shape.addVertex(0.470000f, 0.017000f, false);
+ shape.addVertex(0.437000f, 0.049000f, true);
+ // 063: B4: quad-to p0-p1-p2h **** MID
+ // Shape.QuadTo:
+ shape.addVertex(0.426000f, 0.040000f, false);
+ shape.addVertex(0.410000f, 0.030000f, true);
+ // 065: B5: quad-to pMh-p0-p1h ***** MID
+ // Shape.QuadTo:
+ shape.addVertex(0.393000f, 0.019000f, false);
+ shape.addVertex(0.370000f, 0.010000f, true);
+ // 066: B5: quad-to pMh-p0-p1h ***** MID
+ // Shape.QuadTo:
+ shape.addVertex(0.347000f, 0.001000f, false);
+ shape.addVertex(0.318000f, -0.005000f, true);
+ // 067: B6: quad-to pMh-p0-p1
+ // Shape.QuadTo:
+ shape.addVertex(0.289000f, -0.011000f, false);
+ shape.addVertex(0.252000f, -0.011000f, true);
+ System.err.println("TestObject02.shape02b.winding_area: "+shape.getWindingOfLastOutline());
shape.closeLastOutline(false);
}
if( true ) {
+ // Original Inner a-shape: Winding.CCW
+ // Moved into OutlineShape reverse -> Winding.CW -> OK now
+ //
// Shape.MoveTo:
shape.closeLastOutline(false);
shape.addEmptyOutline();
@@ -334,6 +565,73 @@ public class TestObject02 extends UIShape {
// Shape.QuadTo:
shape.addVertex(0, 0.366000f, 0.190000f, false);
shape.addVertex(0, 0.365000f, 0.238000f, true);
+ System.err.println("TestObject02.shape03a.winding_area: "+shape.getWindingOfLastOutline());
+ shape.closeLastOutline(false);
+ } else {
+ // Inner a-shape: Winding.CCW
+ // Moved into OutlineShape same-order -> Winding.CCW -> OK
+ //
+ // Shape.MoveTo:
+ shape.closeLastOutline(false);
+ shape.addEmptyOutline();
+ shape.addVertex(0.365000f, 0.238000f, true);
+ // 068: B4: quad-to p0-p1-p2h **** MID
+ // Shape.QuadTo:
+ shape.addVertex(0.354000f, 0.243000f, false);
+ shape.addVertex(0.330000f, 0.248000f, true);
+ // 070: B6: quad-to pMh-p0-p1
+ // Shape.QuadTo:
+ shape.addVertex(0.305000f, 0.254000f, false);
+ shape.addVertex(0.263000f, 0.254000f, true);
+ // 071: B4: quad-to p0-p1-p2h **** MID
+ // Shape.QuadTo:
+ shape.addVertex(0.239000f, 0.254000f, false);
+ shape.addVertex(0.213000f, 0.251000f, true);
+ // 073: B5: quad-to pMh-p0-p1h ***** MID
+ // Shape.QuadTo:
+ shape.addVertex(0.187000f, 0.247000f, false);
+ shape.addVertex(0.165000f, 0.236000f, true);
+ // 074: B5: quad-to pMh-p0-p1h ***** MID
+ // Shape.QuadTo:
+ shape.addVertex(0.143000f, 0.224000f, false);
+ shape.addVertex(0.129000f, 0.204000f, true);
+ // 075: B6: quad-to pMh-p0-p1
+ // Shape.QuadTo:
+ shape.addVertex(0.115000f, 0.184000f, false);
+ shape.addVertex(0.115000f, 0.151000f, true);
+ // 076: B4: quad-to p0-p1-p2h **** MID
+ // Shape.QuadTo:
+ shape.addVertex(0.115000f, 0.122000f, false);
+ shape.addVertex(0.125000f, 0.102000f, true);
+ // 078: B5: quad-to pMh-p0-p1h ***** MID
+ // Shape.QuadTo:
+ shape.addVertex(0.135000f, 0.082000f, false);
+ shape.addVertex(0.153000f, 0.070000f, true);
+ // 079: B5: quad-to pMh-p0-p1h ***** MID
+ // Shape.QuadTo:
+ shape.addVertex(0.172000f, 0.058000f, false);
+ shape.addVertex(0.197000f, 0.053000f, true);
+ // 080: B6: quad-to pMh-p0-p1
+ // Shape.QuadTo:
+ shape.addVertex(0.222000f, 0.047000f, false);
+ shape.addVertex(0.252000f, 0.047000f, true);
+ // 081: B4: quad-to p0-p1-p2h **** MID
+ // Shape.QuadTo:
+ shape.addVertex(0.314000f, 0.047000f, false);
+ shape.addVertex(0.350000f, 0.063000f, true);
+ // 083: B6: quad-to pMh-p0-p1
+ // Shape.QuadTo:
+ shape.addVertex(0.386000f, 0.080000f, false);
+ shape.addVertex(0.400000f, 0.093000f, true);
+ // 084: B4: quad-to p0-p1-p2h **** MID
+ // Shape.QuadTo:
+ shape.addVertex(0.384000f, 0.119000f, false);
+ shape.addVertex(0.375000f, 0.154000f, true);
+ // 086: B6: quad-to pMh-p0-p1
+ // Shape.QuadTo:
+ shape.addVertex(0.366000f, 0.190000f, false);
+ shape.addVertex(0.365000f, 0.238000f, true);
+ System.err.println("TestObject02.shape03b.winding_area: "+shape.getWindingOfLastOutline());
shape.closeLastOutline(false);
}
// End Shape for Glyph 193
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/UITypeDemo01.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/UITypeDemo01.java
index 0fe9b300e..b3a56d9b7 100644
--- a/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/UITypeDemo01.java
+++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/UITypeDemo01.java
@@ -204,7 +204,7 @@ public class UITypeDemo01 implements GLEventListener {
} else {
final float scale = 0.15312886f;
final float size_xz = 0.541f;
- final UIShape o = new TestObject01(SVertex.factory(), renderModes);
+ final UIShape o = new TestObject02(SVertex.factory(), renderModes);
o.scale(scale, scale, 1f);
// o.translate(size_xz, -size_xz, 0f);
testObj = o;