diff options
author | Sven Gothel <[email protected]> | 2011-06-08 06:00:30 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2011-06-08 06:00:30 +0200 |
commit | f6bd208d8ef15769e13cb959e614349fd1e7cae1 (patch) | |
tree | 1761440a136814803361efc79a6f7c35c844a603 /src | |
parent | 138ddda3f346db0f1d8b4bac1760d415e7dc3d70 (diff) | |
parent | 820fd3f4e45cfa79e94fad385eb47ff26a5fea2b (diff) |
Merge remote-tracking branch 'rsantina/master'
Diffstat (limited to 'src')
19 files changed, 771 insertions, 655 deletions
diff --git a/src/jogl/classes/com/jogamp/graph/curve/OutlineShape.java b/src/jogl/classes/com/jogamp/graph/curve/OutlineShape.java index 5b94d6bda..e4f80ab76 100755 --- a/src/jogl/classes/com/jogamp/graph/curve/OutlineShape.java +++ b/src/jogl/classes/com/jogamp/graph/curve/OutlineShape.java @@ -1,523 +1,531 @@ -/**
- * 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;
-
-import java.util.ArrayList;
-import java.util.Collections;
-
-
-import com.jogamp.graph.geom.AABBox;
-import com.jogamp.graph.geom.Outline;
-import com.jogamp.graph.geom.Triangle;
-import com.jogamp.graph.geom.Vertex;
-import com.jogamp.graph.math.VectorUtil;
-
-import com.jogamp.graph.curve.tess.CDTriangulator2D;
-
-/** 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.
- *
- * 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>
- * Example to creating an Outline Shape:
- * <pre>
- addVertex(...)
- addVertex(...)
- addVertex(...)
- addEmptyOutline()
- addVertex(...)
- addVertex(...)
- addVertex(...)
- * </pre>
- *
- * 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>
- *
- * 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>
- * 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>
- * <pre>
- addVertex(0,0, true);
- addVertex(0,1, false);
- addVertex(1,1, false);
- addVertex(1,0, true);
- * </pre>
- *
- * The above snippet defines a cubic nurbs curve where (0,1 and 1,1)
- * do not belong to the final rendered shape.
- *
- * <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>
- * </ul>
- *
- * @see Outline
- * @see Region
- */
-public class OutlineShape implements Comparable<OutlineShape> {
- /**
- * Outline's vertices have undefined state until transformed.
- */
- public enum VerticesState {
- UNDEFINED(0), QUADRATIC_NURBS(1);
-
- public final int state;
-
- VerticesState(int state){
- this.state = state;
- }
- }
-
- public static final int DIRTY_BOUNDS = 1 << 0;
-
- private final Vertex.Factory<? extends Vertex> vertexFactory;
- private VerticesState outlineState;
-
- /** The list of {@link Outline}s that are part of this
- * outline shape.
- */
- private ArrayList<Outline> outlines;
- private AABBox bbox;
-
- /** dirty bits DIRTY_BOUNDS */
- private int dirtyBits;
-
- /** Create a new Outline based Shape
- */
- public OutlineShape(Vertex.Factory<? extends Vertex> factory) {
- this.vertexFactory = factory;
- this.outlines = new ArrayList<Outline>(3);
- this.outlines.add(new Outline());
- this.outlineState = VerticesState.UNDEFINED;
- this.bbox = new AABBox();
- this.dirtyBits = 0;
- }
-
- /** Clears all data and reset all states as if this instance was newly created */
- public void clear() {
- outlines.clear();
- outlines.add(new Outline());
- outlineState = VerticesState.UNDEFINED;
- bbox.reset();
- dirtyBits = 0;
- }
-
- /** Returns the associated vertex factory of this outline shape
- * @return Vertex.Factory object
- */
- public final Vertex.Factory<? extends Vertex> vertexFactory() { return vertexFactory; }
-
- public int getOutlineNumber() {
- return outlines.size();
- }
-
- /** 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>
- *
- * After a call to this function all new vertices added
- * will belong to the new outline
- */
- public void addEmptyOutline(){
- if( !getLastOutline().isEmpty() ) {
- outlines.add(new Outline());
- }
- }
-
- /** Appends the {@link Outline} element to the end,
- * ensuring a clean tail.
- *
- * <p>A clean tail is ensured, no double empty Outlines are produced
- * and a pre-existing empty outline will be replaced with the given one. </p>
- *
- * @param outline Outline object to be added
- * @throws NullPointerException if the {@link Outline} element is null
- */
- public void addOutline(Outline outline) throws NullPointerException {
- addOutline(outlines.size(), outline);
- }
-
- /** Insert the {@link Outline} element at the given {@code position}.
- *
- * <p>If the {@code position} indicates the end of this list,
- * a clean tail is ensured, no double empty Outlines are produced
- * and a pre-existing empty outline will be replaced with the given one. </p>
- *
- * @param position of the added Outline
- * @param outline Outline object to be added
- * @throws NullPointerException if the {@link Outline} element is null
- * @throws IndexOutOfBoundsException if position is out of range (position < 0 || position > getOutlineNumber())
- */
- public void addOutline(int position, Outline outline) throws NullPointerException, IndexOutOfBoundsException {
- if (null == outline) {
- throw new NullPointerException("outline is null");
- }
- if( outlines.size() == position ) {
- final Outline lastOutline = getLastOutline();
- if( outline.isEmpty() && lastOutline.isEmpty() ) {
- return;
- }
- if( lastOutline.isEmpty() ) {
- outlines.set(position-1, outline);
- if( 0 == ( dirtyBits & DIRTY_BOUNDS ) ) {
- bbox.resize(outline.getBounds());
- }
- return;
- }
- }
- outlines.add(position, outline);
- if( 0 == ( dirtyBits & DIRTY_BOUNDS ) ) {
- bbox.resize(outline.getBounds());
- }
- }
-
- /** Insert the {@link OutlineShape} elements of type {@link Outline}, .. at the end of this shape,
- * using {@link #addOutline(Outline)} for each element.
- * <p>Closes the current last outline via {@link #closeLastOutline()} before adding the new ones.</p>
- * @param outlineShape OutlineShape elements to be added.
- * @throws NullPointerException if the {@link OutlineShape} is null
- * @throws IndexOutOfBoundsException if position is out of range (position < 0 || position > getOutlineNumber())
- */
- public void addOutlineShape(OutlineShape outlineShape) throws NullPointerException {
- if (null == outlineShape) {
- throw new NullPointerException("OutlineShape is null");
- }
- closeLastOutline();
- for(int i=0; i<outlineShape.getOutlineNumber(); i++) {
- addOutline(outlineShape.getOutline(i));
- }
- }
-
- /** Replaces the {@link Outline} element at the given {@code position}.
- * <p>Sets the bounding box dirty, hence a next call to {@link #getBounds()} will validate it.</p>
- *
- * @param position of the replaced Outline
- * @param outline replacement Outline object
- * @throws NullPointerException if the {@link Outline} element is null
- * @throws IndexOutOfBoundsException if position is out of range (position < 0 || position >= getOutlineNumber())
- */
- public void setOutline(int position, Outline outline) throws NullPointerException, IndexOutOfBoundsException {
- if (null == outline) {
- throw new NullPointerException("outline is null");
- }
- outlines.set(position, outline);
- dirtyBits |= DIRTY_BOUNDS;
- }
-
- /** Removes the {@link Outline} element at the given {@code position}.
- * <p>Sets the bounding box dirty, hence a next call to {@link #getBounds()} will validate it.</p>
- *
- * @param position of the to be removed Outline
- * @throws IndexOutOfBoundsException if position is out of range (position < 0 || position >= getOutlineNumber())
- */
- public final Outline removeOutline(int position) throws IndexOutOfBoundsException {
- dirtyBits |= DIRTY_BOUNDS;
- return outlines.remove(position);
- }
-
- /** Get the last added outline to the list
- * of outlines that define the shape
- * @return the last outline
- */
- public final Outline getLastOutline(){
- return outlines.get(outlines.size()-1);
- }
-
- /** @return the {@code Outline} at {@code position}
- * @throws IndexOutOfBoundsException if position is out of range (position < 0 || position >= getOutlineNumber())
- */
- public Outline getOutline(int position) throws IndexOutOfBoundsException {
- return outlines.get(position);
- }
-
- /** Adds a vertex to the last open outline in the
- * shape.
- * @param v the vertex to be added to the OutlineShape
- */
- public final void addVertex(Vertex v){
- final Outline lo = getLastOutline();
- lo.addVertex(v);
- if( 0 == ( dirtyBits & DIRTY_BOUNDS ) ) {
- bbox.resize(lo.getBounds());
- }
- }
-
- /** Adds a vertex to the last open outline in the shape.
- * at {@code position}
- * @param position indx at which the vertex will be added
- * @param v the vertex to be added to the OutlineShape
- */
- public final void addVertex(int position, Vertex v){
- final Outline lo = getLastOutline();
- lo.addVertex(position, v);
- if( 0 == ( dirtyBits & DIRTY_BOUNDS ) ) {
- bbox.resize(lo.getBounds());
- }
- }
-
- /** Add a 2D {@link Vertex} to the last outline by defining the coordniate attribute
- * of the vertex. The 2D vertex will be represented as Z=0.
- *
- * @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.
- */
- public final void addVertex(float x, float y, boolean onCurve) {
- addVertex(vertexFactory.create(x, y, 0f, onCurve));
- }
-
- /** Add a 3D {@link Vertex} to the last outline by defining the coordniate attribute
- * of the vertex.
- * @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.
- */
- public final void addVertex(float x, float y, float z, boolean onCurve) {
- addVertex(vertexFactory.create(x, y, z, onCurve));
- }
-
- /** Add a vertex to the last outline by passing a float array and specifying the
- * offset and length in which. The attributes of the vertex are located.
- * The attributes should be continuous (stride = 0).
- * Attributes which value are not set (when length less than 3)
- * are set implicitly to zero.
- * @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.
- */
- public final void addVertex(float[] coordsBuffer, int offset, int length, boolean onCurve) {
- addVertex(vertexFactory.create(coordsBuffer, offset, length, onCurve));
- }
-
- /** Closes the last outline in the shape.
- * <p>If last vertex is not equal to first vertex.
- * A new temp vertex is added at the end which
- * is equal to the first.</p>
- */
- public void closeLastOutline(){
- getLastOutline().setClosed(true);
- }
-
- /**
- * @return the outline's vertices state, {@link OutlineShape.VerticesState}
- */
- public final VerticesState getOutlineState() {
- return outlineState;
- }
-
- /** Ensure the outlines represent
- * the specified destinationType.
- *
- * @param destinationType the target outline's vertices state. Currently only {@link OutlineShape.VerticesState#QUADRATIC_NURBS} are supported.
- */
- public void transformOutlines(VerticesState destinationType){
- if(outlineState != destinationType){
- if(destinationType == VerticesState.QUADRATIC_NURBS){
- transformOutlines2Quadratic();
- } else {
- throw new IllegalStateException("destinationType "+destinationType.name()+" not supported (currently "+outlineState.name()+")");
- }
- }
- }
-
- private void transformOutlines2Quadratic(){
- final int count = getOutlineNumber();
- for (int cc = 0; cc < count; cc++){
- final Outline outline = getOutline(cc);
- int vertexNumberLessOne = outline.getVertexNumber() - 1;
- for(int i=0; i < vertexNumberLessOne; i++) {
- final Vertex currentVertex = outline.getVertex(i);
- final Vertex nextVertex = outline.getVertex(i+1);
- if ( !currentVertex.isOnCurve() && !nextVertex.isOnCurve() ) {
- final float[] newCoords = VectorUtil.mid(currentVertex.getCoord(), nextVertex.getCoord());
- final Vertex v = vertexFactory.create(newCoords, 0, 3, true);
- v.setOnCurve(true);
- i++;
- vertexNumberLessOne++;
- outline.addVertex(i, v);
- }
- }
- // Cut off last vertex (which is on-curve)
- // FIXME: original code skipped the last element (it _is_ unrelated to the xform above)
- // FIXME: understand why the last element produces artifacts in rendering
- if( vertexNumberLessOne >= 0 ) {
- outline.removeVertex(vertexNumberLessOne);
- }
- }
- outlineState = VerticesState.QUADRATIC_NURBS;
- }
-
- private void generateVertexIds(){
- int maxVertexId = 0;
- for(int i=0; i<outlines.size(); i++) {
- final ArrayList<Vertex> vertices = outlines.get(i).getVertices();
- for(int pos=0; pos<vertices.size(); pos++) {
- Vertex vert = vertices.get(pos);
- vert.setId(maxVertexId);
- maxVertexId++;
- }
- }
- }
-
- /** @return the list of concatenated vertices associated with all
- * {@code Outline}s of this object
- */
- public ArrayList<Vertex> getVertices() {
- ArrayList<Vertex> vertices = new ArrayList<Vertex>();
- for(int i=0; i<outlines.size(); i++) {
- vertices.addAll(outlines.get(i).getVertices());
- }
- return vertices;
- }
-
- /**
- * Triangulate the {@link OutlineShape} generating a list of triangles
- * @return an arraylist of triangles representing the filled region
- * which is produced by the combination of the outlines
- */
- public ArrayList<Triangle> triangulate() {
- if(outlines.size() == 0){
- return null;
- }
- sortOutlines();
- generateVertexIds();
-
- CDTriangulator2D triangulator2d = new CDTriangulator2D();
- for(int index = 0; index<outlines.size(); index++) {
- triangulator2d.addCurve(outlines.get(index));
- }
-
- ArrayList<Triangle> triangles = triangulator2d.generateTriangulation();
- triangulator2d.reset();
-
- return triangles;
- }
-
- /** Sort the outlines from large
- * to small depending on the AABox
- */
- private void sortOutlines() {
- Collections.sort(outlines);
- Collections.reverse(outlines);
- }
-
- /** Compare two outline shapes with Bounding Box area
- * as criteria.
- * @see java.lang.Comparable#compareTo(java.lang.Object)
- */
- public final int compareTo(OutlineShape outline) {
- float size = getBounds().getSize();
- float newSize = outline.getBounds().getSize();
- if(size < newSize){
- return -1;
- }
- else if(size > newSize){
- return 1;
- }
- return 0;
- }
-
- private final void validateBoundingBox() {
- dirtyBits &= ~DIRTY_BOUNDS;
- bbox.reset();
- for (int i=0; i<outlines.size(); i++) {
- bbox.resize(outlines.get(i).getBounds());
- }
- }
-
- public final AABBox getBounds() {
- if( 0 == ( dirtyBits & DIRTY_BOUNDS ) ) {
- validateBoundingBox();
- }
- return bbox;
- }
-
- /**
- * @param obj the Object to compare this OutlineShape with
- * @return true if {@code obj} is an OutlineShape, not null,
- * same outlineState, equal bounds and equal outlines in the same order
- */
- public boolean equals(Object obj) {
- if( obj == this) {
- return true;
- }
- if( null == obj || !(obj instanceof OutlineShape) ) {
- return false;
- }
- final OutlineShape o = (OutlineShape) obj;
- if(getOutlineState() != o.getOutlineState()) {
- return false;
- }
- if(getOutlineNumber() != o.getOutlineNumber()) {
- return false;
- }
- if( !getBounds().equals( o.getBounds() ) ) {
- return false;
- }
- for (int i=getOutlineNumber()-1; i>=0; i--) {
- if( ! getOutline(i).equals( o.getOutline(i) ) ) {
- return false;
- }
- }
- return true;
- }
-
- /**
- * @return deep clone of this OutlineShape w/o Region
- */
- public OutlineShape clone() {
- OutlineShape o;
- try {
- o = (OutlineShape) super.clone();
- } catch (CloneNotSupportedException e) { throw new InternalError(); }
- o.bbox = bbox.clone();
- o.outlines = new ArrayList<Outline>(outlines.size());
- for(int i=0; i<outlines.size(); i++) {
- o.outlines.add(outlines.get(i).clone());
- }
- return o;
- }
-}
+/** + * 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; + +import java.util.ArrayList; +import java.util.Collections; + +import com.jogamp.graph.curve.tess.Triangulation; +import com.jogamp.graph.curve.tess.Triangulator; +import com.jogamp.graph.geom.AABBox; +import com.jogamp.graph.geom.Outline; +import com.jogamp.graph.geom.Triangle; +import com.jogamp.graph.geom.Vertex; +import com.jogamp.graph.math.VectorUtil; + + +/** 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. + * + * 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> + * Example to creating an Outline Shape: + * <pre> + addVertex(...) + addVertex(...) + addVertex(...) + addEmptyOutline() + addVertex(...) + addVertex(...) + addVertex(...) + * </pre> + * + * 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> + * + * 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> + * 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> + * <pre> + addVertex(0,0, true); + addVertex(0,1, false); + addVertex(1,1, false); + addVertex(1,0, true); + * </pre> + * + * The above snippet defines a cubic nurbs curve where (0,1 and 1,1) + * do not belong to the final rendered shape. + * + * <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> + * </ul> + * + * @see Outline + * @see Region + */ +public class OutlineShape implements Comparable<OutlineShape> { + /** + * Outline's vertices have undefined state until transformed. + */ + public enum VerticesState { + UNDEFINED(0), QUADRATIC_NURBS(1); + + public final int state; + + VerticesState(int state){ + this.state = state; + } + } + + public static final int DIRTY_BOUNDS = 1 << 0; + + private final Vertex.Factory<? extends Vertex> vertexFactory; + private VerticesState outlineState; + + /** The list of {@link Outline}s that are part of this + * outline shape. + */ + private ArrayList<Outline> outlines; + private AABBox bbox; + + /** dirty bits DIRTY_BOUNDS */ + private int dirtyBits; + + /** Create a new Outline based Shape + */ + public OutlineShape(Vertex.Factory<? extends Vertex> factory) { + this.vertexFactory = factory; + this.outlines = new ArrayList<Outline>(3); + this.outlines.add(new Outline()); + this.outlineState = VerticesState.UNDEFINED; + this.bbox = new AABBox(); + this.dirtyBits = 0; + } + + /** Clears all data and reset all states as if this instance was newly created */ + public void clear() { + outlines.clear(); + outlines.add(new Outline()); + outlineState = VerticesState.UNDEFINED; + bbox.reset(); + dirtyBits = 0; + } + + /** Returns the associated vertex factory of this outline shape + * @return Vertex.Factory object + */ + public final Vertex.Factory<? extends Vertex> vertexFactory() { return vertexFactory; } + + public int getOutlineNumber() { + return outlines.size(); + } + + /** 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> + * + * After a call to this function all new vertices added + * will belong to the new outline + */ + public void addEmptyOutline() { + if( !getLastOutline().isEmpty() ) { + outlines.add(new Outline()); + } + } + + /** Appends the {@link Outline} element to the end, + * ensuring a clean tail. + * + * <p>A clean tail is ensured, no double empty Outlines are produced + * and a pre-existing empty outline will be replaced with the given one. </p> + * + * @param outline Outline object to be added + * @throws NullPointerException if the {@link Outline} element is null + */ + public void addOutline(Outline outline) throws NullPointerException { + addOutline(outlines.size(), outline); + } + + /** Insert the {@link Outline} element at the given {@code position}. + * + * <p>If the {@code position} indicates the end of this list, + * a clean tail is ensured, no double empty Outlines are produced + * and a pre-existing empty outline will be replaced with the given one. </p> + * + * @param position of the added Outline + * @param outline Outline object to be added + * @throws NullPointerException if the {@link Outline} element is null + * @throws IndexOutOfBoundsException if position is out of range (position < 0 || position > getOutlineNumber()) + */ + public void addOutline(int position, Outline outline) throws NullPointerException, IndexOutOfBoundsException { + if (null == outline) { + throw new NullPointerException("outline is null"); + } + if( outlines.size() == position ) { + final Outline lastOutline = getLastOutline(); + if( outline.isEmpty() && lastOutline.isEmpty() ) { + return; + } + if( lastOutline.isEmpty() ) { + outlines.set(position-1, outline); + if( 0 == ( dirtyBits & DIRTY_BOUNDS ) ) { + bbox.resize(outline.getBounds()); + } + return; + } + } + outlines.add(position, outline); + if( 0 == ( dirtyBits & DIRTY_BOUNDS ) ) { + bbox.resize(outline.getBounds()); + } + } + + /** Insert the {@link OutlineShape} elements of type {@link Outline}, .. at the end of this shape, + * using {@link #addOutline(Outline)} for each element. + * <p>Closes the current last outline via {@link #closeLastOutline()} before adding the new ones.</p> + * @param outlineShape OutlineShape elements to be added. + * @throws NullPointerException if the {@link OutlineShape} is null + * @throws IndexOutOfBoundsException if position is out of range (position < 0 || position > getOutlineNumber()) + */ + public void addOutlineShape(OutlineShape outlineShape) throws NullPointerException { + if (null == outlineShape) { + throw new NullPointerException("OutlineShape is null"); + } + closeLastOutline(); + for(int i=0; i<outlineShape.getOutlineNumber(); i++) { + addOutline(outlineShape.getOutline(i)); + } + } + + /** Replaces the {@link Outline} element at the given {@code position}. + * <p>Sets the bounding box dirty, hence a next call to {@link #getBounds()} will validate it.</p> + * + * @param position of the replaced Outline + * @param outline replacement Outline object + * @throws NullPointerException if the {@link Outline} element is null + * @throws IndexOutOfBoundsException if position is out of range (position < 0 || position >= getOutlineNumber()) + */ + public void setOutline(int position, Outline outline) throws NullPointerException, IndexOutOfBoundsException { + if (null == outline) { + throw new NullPointerException("outline is null"); + } + outlines.set(position, outline); + dirtyBits |= DIRTY_BOUNDS; + } + + /** Removes the {@link Outline} element at the given {@code position}. + * <p>Sets the bounding box dirty, hence a next call to {@link #getBounds()} will validate it.</p> + * + * @param position of the to be removed Outline + * @throws IndexOutOfBoundsException if position is out of range (position < 0 || position >= getOutlineNumber()) + */ + public final Outline removeOutline(int position) throws IndexOutOfBoundsException { + dirtyBits |= DIRTY_BOUNDS; + return outlines.remove(position); + } + + /** Get the last added outline to the list + * of outlines that define the shape + * @return the last outline + */ + public final Outline getLastOutline() { + return outlines.get(outlines.size()-1); + } + + /** @return the {@code Outline} at {@code position} + * @throws IndexOutOfBoundsException if position is out of range (position < 0 || position >= getOutlineNumber()) + */ + public Outline getOutline(int position) throws IndexOutOfBoundsException { + return outlines.get(position); + } + + /** Adds a vertex to the last open outline in the + * shape. + * @param v the vertex to be added to the OutlineShape + */ + public final void addVertex(Vertex v) { + final Outline lo = getLastOutline(); + lo.addVertex(v); + if( 0 == ( dirtyBits & DIRTY_BOUNDS ) ) { + bbox.resize(lo.getBounds()); + } + } + + /** Adds a vertex to the last open outline in the shape. + * at {@code position} + * @param position indx at which the vertex will be added + * @param v the vertex to be added to the OutlineShape + */ + public final void addVertex(int position, Vertex v) { + final Outline lo = getLastOutline(); + lo.addVertex(position, v); + if( 0 == ( dirtyBits & DIRTY_BOUNDS ) ) { + bbox.resize(lo.getBounds()); + } + } + + /** Add a 2D {@link Vertex} to the last outline by defining the coordniate attribute + * of the vertex. The 2D vertex will be represented as Z=0. + * + * @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. + */ + public final void addVertex(float x, float y, boolean onCurve) { + addVertex(vertexFactory.create(x, y, 0f, onCurve)); + } + + /** Add a 3D {@link Vertex} to the last outline by defining the coordniate attribute + * of the vertex. + * @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. + */ + public final void addVertex(float x, float y, float z, boolean onCurve) { + addVertex(vertexFactory.create(x, y, z, onCurve)); + } + + /** Add a vertex to the last outline by passing a float array and specifying the + * offset and length in which. The attributes of the vertex are located. + * The attributes should be continuous (stride = 0). + * Attributes which value are not set (when length less than 3) + * are set implicitly to zero. + * @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. + */ + public final void addVertex(float[] coordsBuffer, int offset, int length, boolean onCurve) { + addVertex(vertexFactory.create(coordsBuffer, offset, length, onCurve)); + } + + /** Closes the last outline in the shape. + * <p>If last vertex is not equal to first vertex. + * A new temp vertex is added at the end which + * is equal to the first.</p> + */ + public void closeLastOutline() { + getLastOutline().setClosed(true); + } + + /** + * @return the outline's vertices state, {@link OutlineShape.VerticesState} + */ + public final VerticesState getOutlineState() { + return outlineState; + } + + /** Ensure the outlines represent + * the specified destinationType. + * + * @param destinationType the target outline's vertices state. Currently only {@link OutlineShape.VerticesState#QUADRATIC_NURBS} are supported. + */ + public void transformOutlines(VerticesState destinationType) { + if(outlineState != destinationType){ + if(destinationType == VerticesState.QUADRATIC_NURBS){ + transformOutlines2Quadratic(); + } else { + throw new IllegalStateException("destinationType "+destinationType.name()+" not supported (currently "+outlineState.name()+")"); + } + } + } + + private void transformOutlines2Quadratic() { + int count = getOutlineNumber(); + for (int cc = 0; cc < count; cc++) { + final Outline outline = getOutline(cc); + int vertexCount = outline.getVertexCount(); + + for(int i=0; i < vertexCount; i++) { + final Vertex currentVertex = outline.getVertex(i); + final Vertex nextVertex = outline.getVertex((i+1)%vertexCount); + if ( !currentVertex.isOnCurve() && !nextVertex.isOnCurve() ) { + final float[] newCoords = VectorUtil.mid(currentVertex.getCoord(), + nextVertex.getCoord()); + final Vertex v = vertexFactory.create(newCoords, 0, 3, true); + i++; + vertexCount++; + outline.addVertex(i, v); + } + } + if(vertexCount <= 0) { + outlines.remove(outline); + cc--; + count--; + continue; + } + + if( vertexCount > 0 ) { + if(VectorUtil.checkEquality(outline.getVertex(0).getCoord(), + outline.getLastVertex().getCoord())) { + outline.removeVertex(vertexCount-1); + } + } + } + outlineState = VerticesState.QUADRATIC_NURBS; + } + + private void generateVertexIds() { + int maxVertexId = 0; + for(int i=0; i<outlines.size(); i++) { + final ArrayList<Vertex> vertices = outlines.get(i).getVertices(); + for(int pos=0; pos<vertices.size(); pos++) { + Vertex vert = vertices.get(pos); + vert.setId(maxVertexId); + maxVertexId++; + } + } + } + + /** @return the list of concatenated vertices associated with all + * {@code Outline}s of this object + */ + public ArrayList<Vertex> getVertices() { + ArrayList<Vertex> vertices = new ArrayList<Vertex>(); + for(int i=0; i<outlines.size(); i++) { + vertices.addAll(outlines.get(i).getVertices()); + } + return vertices; + } + + /** + * Triangulate the {@link OutlineShape} generating a list of triangles + * @return an arraylist of triangles representing the filled region + * which is produced by the combination of the outlines + */ + public ArrayList<Triangle> triangulate() { + if(outlines.size() == 0){ + return null; + } + sortOutlines(); + generateVertexIds(); + + Triangulator triangulator2d = Triangulation.create(); + for(int index = 0; index<outlines.size(); index++) { + triangulator2d.addCurve(outlines.get(index)); + } + + ArrayList<Triangle> triangles = triangulator2d.generate(); + triangulator2d.reset(); + + return triangles; + } + + /** Sort the outlines from large + * to small depending on the AABox + */ + private void sortOutlines() { + Collections.sort(outlines); + Collections.reverse(outlines); + } + + /** Compare two outline shapes with Bounding Box area + * as criteria. + * @see java.lang.Comparable#compareTo(java.lang.Object) + */ + public final int compareTo(OutlineShape outline) { + float size = getBounds().getSize(); + float newSize = outline.getBounds().getSize(); + if(size < newSize){ + return -1; + } + else if(size > newSize){ + return 1; + } + return 0; + } + + private final void validateBoundingBox() { + dirtyBits &= ~DIRTY_BOUNDS; + bbox.reset(); + for (int i=0; i<outlines.size(); i++) { + bbox.resize(outlines.get(i).getBounds()); + } + } + + public final AABBox getBounds() { + if( 0 == ( dirtyBits & DIRTY_BOUNDS ) ) { + validateBoundingBox(); + } + return bbox; + } + + /** + * @param obj the Object to compare this OutlineShape with + * @return true if {@code obj} is an OutlineShape, not null, + * same outlineState, equal bounds and equal outlines in the same order + */ + public boolean equals(Object obj) { + if( obj == this) { + return true; + } + if( null == obj || !(obj instanceof OutlineShape) ) { + return false; + } + final OutlineShape o = (OutlineShape) obj; + if(getOutlineState() != o.getOutlineState()) { + return false; + } + if(getOutlineNumber() != o.getOutlineNumber()) { + return false; + } + if( !getBounds().equals( o.getBounds() ) ) { + return false; + } + for (int i=getOutlineNumber()-1; i>=0; i--) { + if( ! getOutline(i).equals( o.getOutline(i) ) ) { + return false; + } + } + return true; + } + + /** + * @return deep clone of this OutlineShape w/o Region + */ + public OutlineShape clone() { + OutlineShape o; + try { + o = (OutlineShape) super.clone(); + } catch (CloneNotSupportedException e) { throw new InternalError(); } + o.bbox = bbox.clone(); + o.outlines = new ArrayList<Outline>(outlines.size()); + for(int i=0; i<outlines.size(); i++) { + o.outlines.add(outlines.get(i).clone()); + } + return o; + } +} diff --git a/src/jogl/classes/com/jogamp/graph/curve/Region.java b/src/jogl/classes/com/jogamp/graph/curve/Region.java index 46bdedee4..168d8dd70 100644 --- a/src/jogl/classes/com/jogamp/graph/curve/Region.java +++ b/src/jogl/classes/com/jogamp/graph/curve/Region.java @@ -39,9 +39,11 @@ public abstract class Region { public static final boolean DEBUG = Debug.debug("graph.curve"); public static final boolean DEBUG_INSTANCE = false; - /** Two pass region rendering, slower and more resource hungry (FBO), but AA is perfect. - * Otherwise the default fast one pass MSAA region rendering is being used. */ - public static final int TWO_PASS_RENDERING_BIT = 1 << 0; + /** View based Anti-Aliasing, A Two pass region rendering, slower + * and more resource hungry (FBO), but AA is perfect. + * Otherwise the default fast one pass MSAA region rendering is being used. + */ + public static final int VBAA_RENDERING_BIT = 1 << 0; /** Use non uniform weights [0.0 .. 1.9] for curve region rendering. * Otherwise the default weight 1.0 for Bezier curve region rendering is being applied. */ @@ -57,8 +59,8 @@ public abstract class Region { protected ArrayList<Triangle> triangles = new ArrayList<Triangle>(); protected ArrayList<Vertex> vertices = new ArrayList<Vertex>(); - public static boolean usesTwoPassRendering(int renderModes) { - return 0 != ( renderModes & Region.TWO_PASS_RENDERING_BIT ); + public static boolean isVBAA(int renderModes) { + return 0 != ( renderModes & Region.VBAA_RENDERING_BIT ); } public static boolean usesVariableCurveWeight(int renderModes) { @@ -71,7 +73,7 @@ public abstract class Region { public final int getRenderModes() { return renderModes; } - public boolean usesTwoPassRendering() { return Region.usesTwoPassRendering(renderModes); } + public boolean isVBAA() { return Region.isVBAA(renderModes); } public boolean usesVariableCurveWeight() { return Region.usesVariableCurveWeight(renderModes); } /** Get the current number of vertices associated diff --git a/src/jogl/classes/com/jogamp/graph/curve/opengl/RegionRenderer.java b/src/jogl/classes/com/jogamp/graph/curve/opengl/RegionRenderer.java index 8624c582c..86d962fd8 100644 --- a/src/jogl/classes/com/jogamp/graph/curve/opengl/RegionRenderer.java +++ b/src/jogl/classes/com/jogamp/graph/curve/opengl/RegionRenderer.java @@ -38,7 +38,7 @@ public abstract class RegionRenderer extends Renderer { /** * Create a Hardware accelerated Region Renderer. * @param rs the used {@link RenderState} - * @param renderModes bit-field of modes, e.g. {@link Region#VARIABLE_CURVE_WEIGHT_BIT}, {@link Region#TWO_PASS_RENDERING_BIT} + * @param renderModes bit-field of modes, e.g. {@link Region#VARIABLE_CURVE_WEIGHT_BIT}, {@link Region#VBAA_RENDERING_BIT} * @return an instance of Region Renderer */ public static RegionRenderer create(RenderState rs, int renderModes) { diff --git a/src/jogl/classes/com/jogamp/graph/curve/opengl/TextRenderer.java b/src/jogl/classes/com/jogamp/graph/curve/opengl/TextRenderer.java index 073afe9bd..b466670cc 100644 --- a/src/jogl/classes/com/jogamp/graph/curve/opengl/TextRenderer.java +++ b/src/jogl/classes/com/jogamp/graph/curve/opengl/TextRenderer.java @@ -31,27 +31,20 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; -import javax.media.opengl.GL; import javax.media.opengl.GL2ES2; import jogamp.graph.curve.text.GlyphString; -import jogamp.graph.font.FontInt; -import jogamp.graph.geom.plane.AffineTransform; -import jogamp.graph.geom.plane.Path2D; -import com.jogamp.graph.curve.OutlineShape; import com.jogamp.graph.font.Font; -import com.jogamp.graph.geom.Vertex; -import com.jogamp.graph.geom.Vertex.Factory; public abstract class TextRenderer extends Renderer { /** * Create a Hardware accelerated Text Renderer. * @param rs the used {@link RenderState} - * @param renderModes either {@link com.jogamp.graph.curve.opengl.GLRegion#SINGLE_PASS} or {@link com.jogamp.graph.curve.Region#TWO_PASS_RENDERING_BIT} + * @param renderModes either {@link com.jogamp.graph.curve.opengl.GLRegion#SINGLE_PASS} or {@link com.jogamp.graph.curve.Region#VBAA_RENDERING_BIT} */ - public static TextRenderer create(RenderState rs, int type) { - return new jogamp.graph.curve.opengl.TextRendererImpl01(rs, type); + public static TextRenderer create(RenderState rs, int renderModes) { + return new jogamp.graph.curve.opengl.TextRendererImpl01(rs, renderModes); } protected TextRenderer(RenderState rs, int type) { diff --git a/src/jogl/classes/com/jogamp/graph/curve/tess/Triangulation.java b/src/jogl/classes/com/jogamp/graph/curve/tess/Triangulation.java new file mode 100644 index 000000000..7728efcaf --- /dev/null +++ b/src/jogl/classes/com/jogamp/graph/curve/tess/Triangulation.java @@ -0,0 +1,44 @@ +/** + * Copyright 2011 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 jogamp.graph.curve.tess.CDTriangulator2D; + + +public class Triangulation { + /** Create a new instance of a triangulation. + * Currently only a modified version of Constraint Delaunay + * is implemented. + * @return instance of a triangulator + * @see Triangulator + */ + public static Triangulator create() { + return new CDTriangulator2D(); + } +} diff --git a/src/jogl/classes/com/jogamp/graph/curve/tess/Triangulator.java b/src/jogl/classes/com/jogamp/graph/curve/tess/Triangulator.java new file mode 100644 index 000000000..1ffaccebc --- /dev/null +++ b/src/jogl/classes/com/jogamp/graph/curve/tess/Triangulator.java @@ -0,0 +1,69 @@ +/** + * Copyright 2011 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 com.jogamp.graph.geom.Outline; +import com.jogamp.graph.geom.Triangle; + +/** Interface to the triangulation algorithms provided + * A triangulation of 2D outlines where you can + * provides an easy one or more outlines to be triangulated + * + * example usage: + * addCurve(o1); + * addCurve(o2); + * addCurve(o3); + * generate(); + * reset(); + * + * @see Outline + * @see Triangulation + */ +public interface Triangulator { + + /** Add a curve to the list of Outlines + * describing the shape + * @param outline a bounding {@link Outline} + */ + public void addCurve(Outline outline); + + /** Generate the triangulation of the provided + * List of {@link Outline}s + * @return an arraylist of {@link Triangle}s resembling the + * final shape. + */ + public ArrayList<Triangle> generate(); + + /** Reset the triangulation to initial state + * Clearing cached data + */ + public void reset(); +} diff --git a/src/jogl/classes/com/jogamp/graph/geom/Outline.java b/src/jogl/classes/com/jogamp/graph/geom/Outline.java index 6c1557f7b..9e90e5a2c 100644 --- a/src/jogl/classes/com/jogamp/graph/geom/Outline.java +++ b/src/jogl/classes/com/jogamp/graph/geom/Outline.java @@ -57,7 +57,7 @@ public class Outline implements Cloneable, Comparable<Outline> { public Outline() { } - public final int getVertexNumber() { + public final int getVertexCount() { return vertices.size(); } @@ -207,13 +207,13 @@ public class Outline implements Cloneable, Comparable<Outline> { return false; } final Outline o = (Outline) obj; - if(getVertexNumber() != o.getVertexNumber()) { + if(getVertexCount() != o.getVertexCount()) { return false; } if( !getBounds().equals( o.getBounds() ) ) { return false; } - for (int i=getVertexNumber()-1; i>=0; i--) { + for (int i=getVertexCount()-1; i>=0; i--) { if( ! getVertex(i).equals( o.getVertex(i) ) ) { return false; } diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/RegionFactory.java b/src/jogl/classes/jogamp/graph/curve/opengl/RegionFactory.java index b5a89b40a..e33a78ed8 100755 --- a/src/jogl/classes/jogamp/graph/curve/opengl/RegionFactory.java +++ b/src/jogl/classes/jogamp/graph/curve/opengl/RegionFactory.java @@ -39,14 +39,14 @@ public class RegionFactory { /**
* Create a Region using the passed render mode
*
- * <p> In case {@link Region#TWO_PASS_RENDERING_BIT} is being requested the default texture unit
+ * <p> In case {@link Region#VBAA_RENDERING_BIT} is being requested the default texture unit
* {@link Region#TWO_PASS_DEFAULT_TEXTURE_UNIT} is being used.</p>
*
* @param rs the RenderState to be used
- * @param renderModes bit-field of modes, e.g. {@link Region#VARIABLE_CURVE_WEIGHT_BIT}, {@link Region#TWO_PASS_RENDERING_BIT}
+ * @param renderModes bit-field of modes, e.g. {@link Region#VARIABLE_CURVE_WEIGHT_BIT}, {@link Region#VBAA_RENDERING_BIT}
*/
public static GLRegion create(int renderModes) {
- if( 0 != ( Region.TWO_PASS_RENDERING_BIT & renderModes ) ){
+ if( 0 != ( Region.VBAA_RENDERING_BIT & renderModes ) ){
return new VBORegion2PES2(renderModes, Region.TWO_PASS_DEFAULT_TEXTURE_UNIT);
}
else{
diff --git a/src/jogl/classes/com/jogamp/graph/curve/tess/CDTriangulator2D.java b/src/jogl/classes/jogamp/graph/curve/tess/CDTriangulator2D.java index fce2e1bae..10b6d6847 100644 --- a/src/jogl/classes/com/jogamp/graph/curve/tess/CDTriangulator2D.java +++ b/src/jogl/classes/jogamp/graph/curve/tess/CDTriangulator2D.java @@ -26,14 +26,12 @@ * or implied, of JogAmp Community. */ -package com.jogamp.graph.curve.tess; +package jogamp.graph.curve.tess; import java.util.ArrayList; -import jogamp.graph.curve.tess.GraphOutline; -import jogamp.graph.curve.tess.GraphVertex; -import jogamp.graph.curve.tess.Loop; +import com.jogamp.graph.curve.tess.Triangulator; import com.jogamp.graph.geom.Outline; import com.jogamp.graph.geom.Triangle; import com.jogamp.graph.geom.Vertex; @@ -46,7 +44,7 @@ import jogamp.opengl.Debug; * Closed Regions with optional n holes. * */ -public class CDTriangulator2D { +public class CDTriangulator2D implements Triangulator{ protected static final boolean DEBUG = Debug.debug("Triangulation"); @@ -74,14 +72,9 @@ public class CDTriangulator2D { loops = new ArrayList<Loop>(); } - /** Add a curve to the list of profiles provided - * @param polyline a bounding {@link Outline} - */ - public void addCurve(Outline polyline){ + public void addCurve(Outline polyline) { Loop loop = null; - // FIXME: multiple in/out and CW/CCW tests (as follows) ?? - if(!loops.isEmpty()) { loop = getContainerLoop(polyline); } @@ -100,10 +93,7 @@ public class CDTriangulator2D { } } - /** Generate the triangulation of the provided - * List of {@link Outline}s - */ - public ArrayList<Triangle> generateTriangulation(){ + public ArrayList<Triangle> generate() { for(int i=0;i<loops.size();i++) { Loop loop = loops.get(i); int numTries = 0; diff --git a/src/jogl/classes/jogamp/graph/curve/text/GlyphShape.java b/src/jogl/classes/jogamp/graph/curve/text/GlyphShape.java index ed51cce98..578148699 100644 --- a/src/jogl/classes/jogamp/graph/curve/text/GlyphShape.java +++ b/src/jogl/classes/jogamp/graph/curve/text/GlyphShape.java @@ -29,10 +29,9 @@ package jogamp.graph.curve.text; import java.util.ArrayList; -import jogamp.graph.geom.plane.PathIterator; - import com.jogamp.graph.geom.Vertex; import com.jogamp.graph.geom.Triangle; +import com.jogamp.graph.geom.Vertex.Factory; import com.jogamp.graph.curve.OutlineShape; import com.jogamp.graph.math.Quaternion; @@ -40,7 +39,6 @@ import com.jogamp.graph.math.Quaternion; public class GlyphShape { private Quaternion quat= null; - private int numVertices = 0; private OutlineShape shape = null; /** Create a new Glyph shape @@ -50,70 +48,24 @@ public class GlyphShape { shape = new OutlineShape(factory); } - /** Create a GlyphShape from a font Path Iterator - * @param pathIterator the path iterator - * - * @see PathIterator + /** Create a new GlyphShape from a {@link OutlineShape} + * @param factory vertex impl factory {@link Factory} + * @param shape {@link OutlineShape} representation of the Glyph */ - public GlyphShape(Vertex.Factory<? extends Vertex> factory, PathIterator pathIterator){ + public GlyphShape(Vertex.Factory<? extends Vertex> factory, OutlineShape shape){ this(factory); - - if(null != pathIterator){ - while(!pathIterator.isDone()){ - float[] coords = new float[6]; - int segmentType = pathIterator.currentSegment(coords); - addOutlineVerticesFromGlyphVector(coords, segmentType); - - pathIterator.next(); - } - } - shape.transformOutlines(OutlineShape.VerticesState.QUADRATIC_NURBS); + this.shape = shape; + this.shape.transformOutlines(OutlineShape.VerticesState.QUADRATIC_NURBS); } public final Vertex.Factory<? extends Vertex> vertexFactory() { return shape.vertexFactory(); } - private void addVertexToLastOutline(Vertex vertex) { - //FIXME: assuming font outline comes in CW order - shape.addVertex(0, vertex); - } - - private void addOutlineVerticesFromGlyphVector(float[] coords, int segmentType){ - switch(segmentType) { - case PathIterator.SEG_MOVETO: - shape.closeLastOutline(); - shape.addEmptyOutline(); - addVertexToLastOutline(vertexFactory().create(coords, 0, 2, true)); - numVertices++; - break; - case PathIterator.SEG_LINETO: - addVertexToLastOutline(vertexFactory().create(coords, 0, 2, true)); - numVertices++; - break; - case PathIterator.SEG_QUADTO: - addVertexToLastOutline(vertexFactory().create(coords, 0, 2, false)); - addVertexToLastOutline(vertexFactory().create(coords, 2, 2, true)); - numVertices+=2; - break; - case PathIterator.SEG_CUBICTO: - addVertexToLastOutline(vertexFactory().create(coords, 0, 2, false)); - addVertexToLastOutline(vertexFactory().create(coords, 2, 2, false)); - addVertexToLastOutline(vertexFactory().create(coords, 4, 2, true)); - numVertices+=3; - break; - case PathIterator.SEG_CLOSE: - shape.closeLastOutline(); - break; - default: - throw new IllegalArgumentException("Unhandled Segment Type: "+segmentType); - } - } - public OutlineShape getShape() { return shape; } public int getNumVertices() { - return numVertices; + return shape.getVertices().size(); } /** Get the rotational Quaternion attached to this Shape diff --git a/src/jogl/classes/jogamp/graph/curve/text/GlyphString.java b/src/jogl/classes/jogamp/graph/curve/text/GlyphString.java index cd6cd56aa..2fa708404 100644 --- a/src/jogl/classes/jogamp/graph/curve/text/GlyphString.java +++ b/src/jogl/classes/jogamp/graph/curve/text/GlyphString.java @@ -40,10 +40,6 @@ import javax.media.opengl.GL2ES2; import jogamp.graph.curve.opengl.RegionFactory; import jogamp.graph.font.FontInt; -import jogamp.graph.geom.plane.AffineTransform; -import jogamp.graph.geom.plane.Path2D; -import jogamp.graph.geom.plane.PathIterator; - import com.jogamp.graph.curve.OutlineShape; import com.jogamp.graph.curve.Region; @@ -68,9 +64,9 @@ public class GlyphString { * <p>No caching is performed.</p> * * @param shape is not null, add all {@link GlyphShape}'s {@link Outline} to this instance. - * @param vertexFactory - * @param font - * @param str + * @param vertexFactory vertex impl factory {@link Factory} + * @param font the target {@link Font} + * @param str string text * @return the created {@link GlyphString} instance */ public static GlyphString createString(OutlineShape shape, Factory<? extends Vertex> vertexFactory, Font font, String str) { @@ -81,20 +77,17 @@ public class GlyphString { * <p>No caching is performed.</p> * * @param shape is not null, add all {@link GlyphShape}'s {@link Outline} to this instance. - * @param vertexFactory - * @param font - * @param size - * @param str + * @param vertexFactory vertex impl factory {@link Factory} + * @param font the target {@link Font} + * @param size font size + * @param str string text * @return the created {@link GlyphString} instance */ public static GlyphString createString(OutlineShape shape, Factory<? extends Vertex> vertexFactory, Font font, int fontSize, String str) { - AffineTransform affineTransform = new AffineTransform(vertexFactory); - - Path2D[] paths = new Path2D[str.length()]; - ((FontInt)font).getPaths(str, fontSize, affineTransform, paths); + ArrayList<OutlineShape> shapes = ((FontInt)font).getOutlineShapes(str, fontSize, vertexFactory); GlyphString glyphString = new GlyphString(font.getName(Font.NAME_UNIQUNAME), str); - glyphString.createfromFontPath(vertexFactory, paths, affineTransform); + glyphString.createfromOutlineShapes(vertexFactory, shapes); if(null != shape) { for(int i=0; i<glyphString.glyphs.size(); i++) { shape.addOutlineShape(glyphString.glyphs.get(i).getShape()); @@ -121,19 +114,17 @@ public class GlyphString { return str; } - /** Creates the Curve based Glyphs from a Font + /**Creates the Curve based Glyphs from a list of {@link OutlineShape} * @param vertexFactory vertex impl factory {@link Factory} - * @param paths a list of FontPath2D objects that define the outline - * @param affineTransform a global affine transformation applied to the paths. + * @param shapes list of {@link OutlineShape} */ - public void createfromFontPath(Factory<? extends Vertex> vertexFactory, Path2D[] paths, AffineTransform affineTransform) { - final int numGlyps = paths.length; + public void createfromOutlineShapes(Factory<? extends Vertex> vertexFactory, ArrayList<OutlineShape> shapes) { + final int numGlyps = shapes.size(); for (int index=0;index<numGlyps;index++){ - if(paths[index] == null){ + if(shapes.get(index) == null){ continue; } - PathIterator iterator = paths[index].iterator(affineTransform); - GlyphShape glyphShape = new GlyphShape(vertexFactory, iterator); + GlyphShape glyphShape = new GlyphShape(vertexFactory, shapes.get(index)); if(glyphShape.getNumVertices() < 3) { continue; @@ -142,10 +133,11 @@ public class GlyphString { } } + /** Generate a OGL Region to represent this Object. * @param gl the current gl object * @param rs the current attached RenderState - * @param renderModes bit-field of modes, e.g. {@link Region#VARIABLE_CURVE_WEIGHT_BIT}, {@link Region#TWO_PASS_RENDERING_BIT} + * @param renderModes bit-field of modes, e.g. {@link Region#VARIABLE_CURVE_WEIGHT_BIT}, {@link Region#VBAA_RENDERING_BIT} */ public GLRegion createRegion(GL2ES2 gl, int renderModes){ region = RegionFactory.create(renderModes); diff --git a/src/jogl/classes/jogamp/graph/font/FontInt.java b/src/jogl/classes/jogamp/graph/font/FontInt.java index 6c25f9a80..37660bb2c 100644 --- a/src/jogl/classes/jogamp/graph/font/FontInt.java +++ b/src/jogl/classes/jogamp/graph/font/FontInt.java @@ -27,11 +27,14 @@ */ package jogamp.graph.font; -import jogamp.graph.geom.plane.AffineTransform; +import java.util.ArrayList; + import jogamp.graph.geom.plane.Path2D; import com.jogamp.graph.curve.OutlineShape; import com.jogamp.graph.font.Font; +import com.jogamp.graph.geom.Vertex; +import com.jogamp.graph.geom.Vertex.Factory; public interface FontInt extends Font { @@ -46,7 +49,5 @@ public interface FontInt extends Font { public Path2D getPath(float pixelSize); } - public void getPaths(CharSequence string, float pixelSize, - AffineTransform transform, Path2D[] result); - //TODO: Rami - ADD getOutlines without path2D + public ArrayList<OutlineShape> getOutlineShapes(CharSequence string, float pixelSize, Factory<? extends Vertex> vertexFactory); } diff --git a/src/jogl/classes/jogamp/graph/font/typecast/TypecastFont.java b/src/jogl/classes/jogamp/graph/font/typecast/TypecastFont.java index 2e692e5ce..8806f537d 100644 --- a/src/jogl/classes/jogamp/graph/font/typecast/TypecastFont.java +++ b/src/jogl/classes/jogamp/graph/font/typecast/TypecastFont.java @@ -27,6 +27,8 @@ */ package jogamp.graph.font.typecast; +import java.util.ArrayList; + import jogamp.graph.font.FontInt; import jogamp.graph.font.typecast.ot.OTFont; import jogamp.graph.font.typecast.ot.OTFontCollection; @@ -39,9 +41,12 @@ import jogamp.graph.geom.plane.AffineTransform; import jogamp.graph.geom.plane.Path2D; import com.jogamp.common.util.IntObjectHashMap; +import com.jogamp.graph.curve.OutlineShape; import com.jogamp.graph.font.Font; import com.jogamp.graph.font.FontFactory; import com.jogamp.graph.geom.AABBox; +import com.jogamp.graph.geom.Vertex; +import com.jogamp.graph.geom.Vertex.Factory; class TypecastFont implements FontInt { static final boolean DEBUG = false; @@ -208,9 +213,10 @@ class TypecastFont implements FontInt { } return result; } - - public void getPaths(CharSequence string, float pixelSize, AffineTransform transform, Path2D[] result) { - TypecastRenderer.getPaths(this, string, pixelSize, transform, result); + + public ArrayList<OutlineShape> getOutlineShapes(CharSequence string, float pixelSize, Factory<? extends Vertex> vertexFactory) { + AffineTransform transform = new AffineTransform(vertexFactory); + return TypecastRenderer.getOutlineShapes(this, string, pixelSize, transform, vertexFactory); } public float getStringWidth(CharSequence string, float pixelSize) { diff --git a/src/jogl/classes/jogamp/graph/font/typecast/TypecastRenderer.java b/src/jogl/classes/jogamp/graph/font/typecast/TypecastRenderer.java index 310b2b274..50b510d23 100644 --- a/src/jogl/classes/jogamp/graph/font/typecast/TypecastRenderer.java +++ b/src/jogl/classes/jogamp/graph/font/typecast/TypecastRenderer.java @@ -27,12 +27,19 @@ */ package jogamp.graph.font.typecast; +import java.util.ArrayList; + +import jogamp.graph.curve.text.GlyphShape; import jogamp.graph.font.typecast.ot.OTGlyph; import jogamp.graph.font.typecast.ot.Point; import jogamp.graph.geom.plane.AffineTransform; import jogamp.graph.geom.plane.Path2D; +import jogamp.graph.geom.plane.PathIterator; +import com.jogamp.graph.curve.OutlineShape; import com.jogamp.graph.font.Font; +import com.jogamp.graph.geom.Vertex; +import com.jogamp.graph.geom.Vertex.Factory; /** * Factory to build a {@link com.jogamp.graph.geom.Path2D Path2D} from @@ -40,7 +47,7 @@ import com.jogamp.graph.font.Font; */ public class TypecastRenderer { - public static void getPaths(TypecastFont font, + private static void getPaths(TypecastFont font, CharSequence string, float pixelSize, AffineTransform transform, Path2D[] p) { if (string == null) { @@ -82,6 +89,58 @@ public class TypecastRenderer { } } + public static ArrayList<OutlineShape> getOutlineShapes(TypecastFont font, CharSequence string, float pixelSize, AffineTransform transform, Factory<? extends Vertex> vertexFactory) { + Path2D[] paths = new Path2D[string.length()]; + getPaths(font, string, pixelSize, transform, paths); + + ArrayList<OutlineShape> shapes = new ArrayList<OutlineShape>(); + final int numGlyps = paths.length; + for (int index=0;index<numGlyps;index++) { + if(paths[index] == null){ + continue; + } + OutlineShape shape = new OutlineShape(vertexFactory); + shapes.add(shape); + PathIterator iterator = paths[index].iterator(transform); + if(null != iterator){ + while(!iterator.isDone()){ + float[] coords = new float[6]; + int segmentType = iterator.currentSegment(coords); + addPathVertexToOutline(shape, vertexFactory, coords, segmentType); + iterator.next(); + } + } + } + return shapes; + } + private static void addPathVertexToOutline(OutlineShape shape, Factory<? extends Vertex> vertexFactory, float[] coords, int segmentType){ + switch(segmentType) { + case PathIterator.SEG_MOVETO: + shape.closeLastOutline(); + shape.addEmptyOutline(); + shape.addVertex(0, vertexFactory.create(coords, 0, 2, true)); + //numVertices++; + break; + case PathIterator.SEG_LINETO: + shape.addVertex(0, vertexFactory.create(coords, 0, 2, true)); + break; + case PathIterator.SEG_QUADTO: + shape.addVertex(0, vertexFactory.create(coords, 0, 2, false)); + shape.addVertex(0, vertexFactory.create(coords, 2, 2, true)); + break; + case PathIterator.SEG_CUBICTO: + shape.addVertex(0, vertexFactory.create(coords, 0, 2, false)); + shape.addVertex(0, vertexFactory.create(coords, 2, 2, false)); + shape.addVertex(0, vertexFactory.create(coords, 4, 2, true)); + break; + case PathIterator.SEG_CLOSE: + shape.closeLastOutline(); + break; + default: + throw new IllegalArgumentException("Unhandled Segment Type: "+segmentType); + } + } + /** * Build a {@link com.jogamp.graph.geom.Path2D Path2D} from a * {@link jogamp.graph.font.typecast.ot.OTGlyph Glyph}. This glyph path can then diff --git a/src/test/com/jogamp/opengl/test/junit/graph/TestRegionRendererNEWT01.java b/src/test/com/jogamp/opengl/test/junit/graph/TestRegionRendererNEWT01.java index c9c235c69..13aa266dc 100644 --- a/src/test/com/jogamp/opengl/test/junit/graph/TestRegionRendererNEWT01.java +++ b/src/test/com/jogamp/opengl/test/junit/graph/TestRegionRendererNEWT01.java @@ -67,7 +67,7 @@ public class TestRegionRendererNEWT01 extends UITestCase { GLWindow window = createWindow("shape-vbaa1-msaa0", caps, 800,400);
RenderState rs = RenderState.createRenderState(new ShaderState(), SVertex.factory());
- GPURegionGLListener02 demo02Listener = new GPURegionGLListener02 (rs, Region.TWO_PASS_RENDERING_BIT, 1140, false, false);
+ GPURegionGLListener02 demo02Listener = new GPURegionGLListener02 (rs, Region.VBAA_RENDERING_BIT, 1140, false, false);
demo02Listener.attachInputListenerTo(window);
window.addGLEventListener(demo02Listener);
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 a3bf215d9..acbcbc7da 100755 --- a/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT01.java +++ b/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT01.java @@ -69,7 +69,7 @@ public class TestTextRendererNEWT01 extends UITestCase { GLWindow window = createWindow("text-vbaa1-msaa0", caps, 800,400);
RenderState rs = RenderState.createRenderState(new ShaderState(), SVertex.factory());
- TextGLListener textGLListener = new TextGLListener(rs, Region.TWO_PASS_RENDERING_BIT, DEBUG, TRACE);
+ TextGLListener textGLListener = new TextGLListener(rs, Region.VBAA_RENDERING_BIT, DEBUG, TRACE);
textGLListener.attachInputListenerTo(window);
window.addGLEventListener(textGLListener);
diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPURegionNewtDemo02.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPURegionNewtDemo02.java index 4cba9cbd5..f1db1ccdd 100644 --- a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPURegionNewtDemo02.java +++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPURegionNewtDemo02.java @@ -64,7 +64,7 @@ public class GPURegionNewtDemo02 { window.setTitle("GPU Curve Region Newt Demo 02 - vbaa1 msaa0"); RenderState rs = RenderState.createRenderState(new ShaderState(), SVertex.factory()); - GPURegionGLListener02 regionGLListener = new GPURegionGLListener02 (rs, Region.TWO_PASS_RENDERING_BIT|Region.VARIABLE_CURVE_WEIGHT_BIT, 1140, DEBUG, TRACE); + GPURegionGLListener02 regionGLListener = new GPURegionGLListener02 (rs, Region.VBAA_RENDERING_BIT|Region.VARIABLE_CURVE_WEIGHT_BIT, 1140, DEBUG, TRACE); regionGLListener.attachInputListenerTo(window); window.addGLEventListener(regionGLListener); diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPURendererListenerBase01.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPURendererListenerBase01.java index ed6bb3cde..632b78d82 100644 --- a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPURendererListenerBase01.java +++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPURendererListenerBase01.java @@ -277,7 +277,7 @@ public abstract class GPURendererListenerBase01 implements GLEventListener { autoDrawable.invoke(false, new GLRunnable() { public void run(GLAutoDrawable drawable) { try { - final String type = Region.usesTwoPassRendering(renderModes) ? "r2t0-msaa1" : "r2t1-msaa0" + ( Region.usesVariableCurveWeight(renderModes) ? "-vc" : "-uc" ) ; + final String type = Region.isVBAA(renderModes) ? "vbaa0-msaa1" : "vbaa1-msaa0" + ( Region.usesVariableCurveWeight(renderModes) ? "-vc" : "-uc" ) ; printScreen(drawable, "./", "demo-"+type, "snap"+screenshot_num, false); screenshot_num++; } catch (GLException e) { diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUTextNewtDemo02.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUTextNewtDemo02.java index 320e79472..d7dff5170 100644 --- a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUTextNewtDemo02.java +++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUTextNewtDemo02.java @@ -71,7 +71,7 @@ public class GPUTextNewtDemo02 { window.setTitle("GPU Text Newt Demo 02 - vbaa1 msaa0"); RenderState rs = RenderState.createRenderState(new ShaderState(), SVertex.factory()); - GPUTextGLListener0A textGLListener = new GPUTextGLListener0A(rs, Region.TWO_PASS_RENDERING_BIT, window.getWidth()*3, DEBUG, TRACE); + GPUTextGLListener0A textGLListener = new GPUTextGLListener0A(rs, Region.VBAA_RENDERING_BIT, window.getWidth()*3, DEBUG, TRACE); // ((TextRenderer)textGLListener.getRenderer()).setCacheLimit(32); textGLListener.attachInputListenerTo(window); window.addGLEventListener(textGLListener); |