/**
* Copyright 2014 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 jogamp.graph.curve.tess;
import com.jogamp.graph.geom.Triangle;
import com.jogamp.graph.geom.Vertex;
import com.jogamp.opengl.math.Vec2f;
import com.jogamp.opengl.math.Vec3f;
import com.jogamp.opengl.math.VectorUtil;
/**
* Experimental Add-On ..
*
* Disabled by default
*/
public class CDTriangulator2DExpAddOn {
private final Vec3f tempV3a = new Vec3f();
private final Vec3f tempV3b = new Vec3f();
protected final void markLineInTriangle(final Triangle tri1) {
if( !tri1.isOnCurve() || !tri1.isLine() ) {
return;
}
final boolean[] boundVs = tri1.getVerticesBoundary();
final Vertex[] triVs = tri1.getVertices();
final Vertex v0 = triVs[0];
final Vertex v1 = triVs[1];
final Vertex v2 = triVs[2];
int lineSegCount = 0;
final boolean v0IsLS, v1IsLS, v2IsLS;
if( v0.isOnCurve() && VectorUtil.isVec2Zero(v0.getTexCoord()) && !boundVs[0] ) {
v0IsLS = true;
lineSegCount++;
} else {
v0IsLS = false;
}
if( v1.isOnCurve() && VectorUtil.isVec2Zero(v1.getTexCoord()) && !boundVs[1] ) {
v1IsLS = true;
lineSegCount++;
} else {
v1IsLS = false;
}
if( v2.isOnCurve() && VectorUtil.isVec2Zero(v2.getTexCoord()) && !boundVs[2] ) {
v2IsLS = true;
lineSegCount++;
} else {
v2IsLS = false;
}
if( 2 > lineSegCount ) {
return;
} else {
if(CDTriangulator2D.DEBUG) {
System.err.println("CDTri.markLine.1: "+tri1);
System.err.println("CDTri.markLine.1: count "+lineSegCount+", v0IsLS "+v0IsLS+", v1IsLS "+v1IsLS+", v2IsLS "+v2IsLS);
}
final float texZTag = 2f;
if( true ) {
if( v0IsLS ) {
v0.setTexCoord(0f, 0f, texZTag);
}
if( v1IsLS ) {
v1.setTexCoord(0f, 0f, texZTag);
}
if( v2IsLS ) {
v2.setTexCoord(0f, 0f, texZTag);
}
} else {
if( v0IsLS ) {
final Vertex v = v0.clone();
v.setTexCoord(0f, 0f, texZTag);
triVs[0] = v;
}
if( v1IsLS ) {
final Vertex v = v1.clone();
v.setTexCoord(0f, 0f, texZTag);
triVs[1] = v;
}
if( v2IsLS ) {
final Vertex v = v2.clone();
v.setTexCoord(0f, 0f, texZTag);
triVs[2] = v;
}
}
if ( false ) {
final Vertex vL1, vL2, vL3, vO;
if( 3 == lineSegCount ) {
vL1 = v0; vL2=v1; vL3=v2; vO=null;
} else if( v0IsLS && v1IsLS ) {
vL1 = v0; vL2=v1; vL3=null; vO=v2;
} else if( v0IsLS && v2IsLS ) {
vL1 = v0; vL2=v2; vL3=null; vO=v1;
} else if( v1IsLS && v2IsLS ) {
vL1 = v1; vL2=v2; vL3=null; vO=v0;
} else {
return; // unreachable
}
if( null != vL1 ) {
vL1.setTexCoord(texZTag, 0f, 0f);
}
if( null != vL2 ) {
vL2.setTexCoord(texZTag, 0f, 0f);
}
if( null != vL3 ) {
vL3.setTexCoord(texZTag, 0f, 0f);
}
}
}
}
/**
* If this and the other triangle compose a rectangle return the
* given tempV2
array w/ shortest side first.
* Otherwise return null;
*
* Experimental CODE, enabled only if {@link #TEST_LINE_AA} is set .. WIP *
*
One test uses method: ROESSLER-2012-OGLES
* However, we would need to tesselate all lines appropriately, * i.e. create 2 triangles sharing the middle actual line using thickness+radius. * * This test simply used our default font w/ a line thickness of 2 pixels, * which produced mentioned rectangles. * This is of course not the case for arbitrary Outline shapes. *
* @param tri2 * @param checkThisOnCurve * @param temp temp storage */ protected final Vec2f processLineAA(final int i, final Triangle tri1, final Triangle tri2, final Vec2f temp) { if(CDTriangulator2D.DEBUG){ System.err.println("CDTri.genP2["+i+"].1: ? t1 "+tri1); System.err.println("CDTri.genP2["+i+"].1: ? t2 "+tri2); } final Vec2f rect = processLineAAImpl(tri1, tri2, temp); if(CDTriangulator2D.DEBUG){ if( null != rect ) { System.err.println("CDTri.genP2["+i+"].1: RECT ["+rect.x()+", "+rect.y()+"]"); System.err.println("CDTri.genP2["+i+"].1: RECT t1 "+tri1); System.err.println("CDTri.genP2["+i+"].1: RECT t2 "+tri2); } else { System.err.println("CDTri.genP2["+i+"].1: RECT NOPE, t1 "+tri1); System.err.println("CDTri.genP2["+i+"].1: RECT NOPE, t2 "+tri2); } } return rect; } private final Vec2f processLineAAImpl(final Triangle tri1, final Triangle tri2, final Vec2f temp) { if( !tri1.isOnCurve() || !tri2.isOnCurve() || !tri1.isLine() || !tri2.isLine() ) { return null; } final Vec2f rect; int eqCount = 0; final int[] commonIdxA = { -1, -1 }; final int[] commonIdxB = { -1, -1 }; final Vertex[] verts1 = tri1.getVertices(); final Vertex[] verts2 = tri2.getVertices(); Vec3f coord = verts1[0].getCoord(); if( coord.isEqual( verts2[0].getCoord() ) ) { commonIdxA[eqCount] = 0; commonIdxB[eqCount] = 0; eqCount++; } else if( coord.isEqual( verts2[1].getCoord() ) ) { commonIdxA[eqCount] = 0; commonIdxB[eqCount] = 1; eqCount++; } else if( coord.isEqual( verts2[2].getCoord() ) ) { commonIdxA[eqCount] = 0; commonIdxB[eqCount] = 2; eqCount++; } coord = verts1[1].getCoord(); if( coord.isEqual( verts2[0].getCoord() ) ) { commonIdxA[eqCount] = 1; commonIdxB[eqCount] = 0; eqCount++; } else if( coord.isEqual( verts2[1].getCoord() ) ) { commonIdxA[eqCount] = 1; commonIdxB[eqCount] = 1; eqCount++; } else if( coord.isEqual( verts2[2].getCoord() ) ) { commonIdxA[eqCount] = 1; commonIdxB[eqCount] = 2; eqCount++; } final int otherIdxA; if( 2 == eqCount ) { otherIdxA = 3 - ( commonIdxA[0] + commonIdxA[1] ); } else { coord = verts1[2].getCoord(); if( coord.isEqual( verts2[0].getCoord() ) ) { commonIdxA[eqCount] = 2; commonIdxB[eqCount] = 0; eqCount++; } else if( coord.isEqual( verts2[1].getCoord() ) ) { commonIdxA[eqCount] = 2; commonIdxB[eqCount] = 1; eqCount++; } else if( coord.isEqual( verts2[2].getCoord() ) ) { commonIdxA[eqCount] = 2; commonIdxB[eqCount] = 2; eqCount++; } if( 2 == eqCount ) { otherIdxA = 3 - ( commonIdxA[0] + commonIdxA[1] ); } else { otherIdxA = -1; } } if( 0 <= otherIdxA && commonIdxB[0] != commonIdxB[1] ) { final int otherIdxB = 3 - ( commonIdxB[0] + commonIdxB[1] ); // Reference must be equal, i.e. sharing the actual same vertices! if( verts1[commonIdxA[0]] != verts2[commonIdxB[0]] || verts1[commonIdxA[1]] != verts2[commonIdxB[1]] ) { throw new InternalError("XXX: diff shared verts"); // FIXME remove when clear } final Vertex vC0A, vC1A, vOA, vOB; if( false ) { // Fetch only! vC0A = verts1[commonIdxA[0]]; vC1A = verts1[commonIdxA[1]]; vOA = verts1[otherIdxA]; vOB = verts2[otherIdxB]; } else { // Fetch and clone, write-back to triangles vC0A = verts1[commonIdxA[0]].clone(); verts1[commonIdxA[0]] = vC0A; verts2[commonIdxB[0]] = vC0A; vC1A = verts1[commonIdxA[1]].clone(); verts1[commonIdxA[1]] = vC1A; verts2[commonIdxB[1]] = vC1A; vOA = verts1[otherIdxA].clone(); verts1[otherIdxA] = vOA; vOB = verts2[otherIdxB].clone(); verts2[otherIdxB] = vOB; } final float texZTag = 2f; final Vec3f vOACoords = vOA.getCoord(); final float dOC0A = vOACoords.dist( vC0A.getCoord() ); final float dOC1A = vOACoords.dist( vC1A.getCoord() ); if( false ) { final Vec3f vec3Z = new Vec3f(0f, 0f, -1f); final Vec3f vecLongSide, vecLineHeight; if( dOC0A < dOC1A ) { temp.set( dOC0A, // line width dOC1A); // long side vecLongSide = tempV3a.minus(vOACoords, vC1A.getCoord()).normalize(); // normal long side vector vecLineHeight = tempV3b.cross(vec3Z, tempV3a); // the line-height vector (normal) vOA.setTexCoord(-1f, -1f, texZTag); vC1A.setTexCoord(1f, -1f, texZTag); vOB.setTexCoord(0f, 1f, texZTag); vC0A.setTexCoord(0f, 1f, texZTag); } else { temp.set( dOC1A, // line width dOC0A); // long side vecLongSide = tempV3a.minus(vOACoords, vC0A.getCoord()).normalize(); // normal long side vector vecLineHeight = tempV3b.cross(vec3Z, tempV3a); // the line-height vector (normal) } if(CDTriangulator2D.DEBUG){ System.err.println("RECT.0 : long-side-vec "+vecLongSide); System.err.println("RECT.0 : line-height-vec "+vecLineHeight); } } else { /** * Using method: ROESSLER-2012-OGLES