mirror of
https://github.com/processing/processing4.git
synced 2026-06-16 04:26:26 +02:00
Sorter: getting up to speed
This commit is contained in:
@@ -3012,9 +3012,8 @@ public class PGraphicsOpenGL extends PGraphics {
|
||||
boolean needNormals = customShader ? polyShader.accessNormals() : false;
|
||||
boolean needTexCoords = customShader ? polyShader.accessTexCoords() : false;
|
||||
|
||||
updatePolyBuffers(lights, texCache.hasTextures, needNormals, needTexCoords);
|
||||
|
||||
sorter.sort(tessGeo);
|
||||
|
||||
int[] triangleIndices = sorter.triangleIndices;
|
||||
int[] texCacheMap = sorter.texCacheMap;
|
||||
int[] indexCacheMap = sorter.indexCacheMap;
|
||||
@@ -3023,6 +3022,8 @@ public class PGraphicsOpenGL extends PGraphics {
|
||||
int ti = triangleIndices[i];
|
||||
Texture tex = texCache.getTexture(texCacheMap[ti]);
|
||||
int voffset = tessGeo.polyIndexCache.vertexOffset[indexCacheMap[ti]];
|
||||
updatePolyBuffers(lights, texCache.hasTextures, needNormals, needTexCoords);
|
||||
|
||||
|
||||
// If the renderer is 2D, then lights should always be false,
|
||||
// so no need to worry about that.
|
||||
@@ -13427,17 +13428,36 @@ public class PGraphicsOpenGL extends PGraphics {
|
||||
static final int Z = 2;
|
||||
static final int W = 3;
|
||||
|
||||
static final int X0 = 0;
|
||||
static final int Y0 = 1;
|
||||
static final int Z0 = 2;
|
||||
static final int X1 = 3;
|
||||
static final int Y1 = 4;
|
||||
static final int Z1 = 5;
|
||||
static final int X2 = 6;
|
||||
static final int Y2 = 7;
|
||||
static final int Z2 = 8;
|
||||
|
||||
int[] triangleIndices = new int[0];
|
||||
int[] texCacheMap = new int[0];
|
||||
int[] indexCacheMap = new int[0];
|
||||
|
||||
float[] minXBuffer = new float[0];
|
||||
float[] minYBuffer = new float[0];
|
||||
float[] minZBuffer = new float[0];
|
||||
float[] maxXBuffer = new float[0];
|
||||
float[] maxYBuffer = new float[0];
|
||||
float[] maxZBuffer = new float[0];
|
||||
|
||||
float[] screenVertices = new float[0];
|
||||
|
||||
int[] swapped = new int[8];
|
||||
int[] marked = new int[8];
|
||||
float[] triA = new float[9];
|
||||
float[] triB = new float[9];
|
||||
|
||||
BitSet marked = new BitSet();
|
||||
BitSet swapped = new BitSet();
|
||||
|
||||
PGraphicsOpenGL pg;
|
||||
TessGeometry tessGeo;
|
||||
|
||||
DepthSorter (PGraphicsOpenGL pg) {
|
||||
this.pg = pg;
|
||||
@@ -13449,6 +13469,12 @@ public class PGraphicsOpenGL extends PGraphics {
|
||||
triangleIndices = new int[newSize];
|
||||
texCacheMap = new int[newSize];
|
||||
indexCacheMap = new int[newSize];
|
||||
minXBuffer = new float[newSize];
|
||||
minYBuffer = new float[newSize];
|
||||
minZBuffer = new float[newSize];
|
||||
maxXBuffer = new float[newSize];
|
||||
maxYBuffer = new float[newSize];
|
||||
maxZBuffer = new float[newSize];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13463,40 +13489,32 @@ public class PGraphicsOpenGL extends PGraphics {
|
||||
// Sorting --------------------------------------------
|
||||
|
||||
void sort(TessGeometry tessGeo) {
|
||||
this.tessGeo = tessGeo;
|
||||
|
||||
int triangleCount = tessGeo.polyIndexCount / 3;
|
||||
checkIndexBuffers(triangleCount);
|
||||
int[] triangleIndices = this.triangleIndices;
|
||||
int[] texCacheMap = this.texCacheMap;
|
||||
int[] indexCacheMap = this.indexCacheMap;
|
||||
|
||||
{ // Map vertices to screen
|
||||
float[] polyVertices = tessGeo.polyVertices;
|
||||
int polyVertexCount = tessGeo.polyVertexCount;
|
||||
checkVertexBuffer(polyVertexCount);
|
||||
|
||||
for (int i = 0; i < polyVertexCount; i++) {
|
||||
float x = polyVertices[4*i+X];
|
||||
float y = polyVertices[4*i+Y];
|
||||
float z = polyVertices[4*i+Z];
|
||||
float w = polyVertices[4*i+W];
|
||||
|
||||
screenVertices[3*i+X] = pg.screenXImpl(x, y, z, w);
|
||||
screenVertices[3*i+Y] = pg.screenYImpl(x, y, z, w);
|
||||
screenVertices[3*i+Z] = -pg.screenZImpl(x, y, z, w)
|
||||
* (pg.cameraFar - pg.cameraNear);
|
||||
{ // Initialize triangle indices
|
||||
for (int i = 0; i < triangleCount; i++) {
|
||||
triangleIndices[i] = i;
|
||||
}
|
||||
}
|
||||
|
||||
{ // Map caches to triangles
|
||||
for (int i = 0; i < pg.texCache.size; i++) {
|
||||
int first = pg.texCache.firstCache[i];
|
||||
int last = pg.texCache.lastCache[i];
|
||||
IndexCache cache = tessGeo.polyIndexCache;
|
||||
TexCache texCache = pg.texCache;
|
||||
IndexCache indexCache = tessGeo.polyIndexCache;
|
||||
for (int i = 0; i < texCache.size; i++) {
|
||||
int first = texCache.firstCache[i];
|
||||
int last = texCache.lastCache[i];
|
||||
for (int n = first; n <= last; n++) {
|
||||
int ioffset = n == first ? pg.texCache.firstIndex[i] :
|
||||
cache.indexOffset[n];
|
||||
int icount = n == last ? pg.texCache.lastIndex[i] - ioffset + 1 :
|
||||
cache.indexOffset[n] + cache.indexCount[n] -
|
||||
ioffset;
|
||||
int ioffset = n == first
|
||||
? texCache.firstIndex[i]
|
||||
: indexCache.indexOffset[n];
|
||||
int icount = n == last
|
||||
? texCache.lastIndex[i] - ioffset + 1
|
||||
: indexCache.indexOffset[n] + indexCache.indexCount[n] - ioffset;
|
||||
|
||||
for (int tr = ioffset / 3; tr < (ioffset + icount) / 3; tr++) {
|
||||
texCacheMap[tr] = i;
|
||||
@@ -13506,94 +13524,201 @@ public class PGraphicsOpenGL extends PGraphics {
|
||||
}
|
||||
}
|
||||
|
||||
{ // Initialize triangle indices
|
||||
if (triangleIndices.length < triangleCount) {
|
||||
triangleIndices = new int[triangleCount];
|
||||
}
|
||||
for (int i = 0; i < triangleCount; i++) {
|
||||
triangleIndices[i] = i;
|
||||
{ // Map vertices to screen
|
||||
int polyVertexCount = tessGeo.polyVertexCount;
|
||||
checkVertexBuffer(polyVertexCount);
|
||||
float[] screenVertices = this.screenVertices;
|
||||
|
||||
float[] polyVertices = tessGeo.polyVertices;
|
||||
|
||||
PMatrix3D projection = pg.projection;
|
||||
|
||||
for (int i = 0; i < polyVertexCount; i++) {
|
||||
float x = polyVertices[4*i+X];
|
||||
float y = polyVertices[4*i+Y];
|
||||
float z = polyVertices[4*i+Z];
|
||||
float w = polyVertices[4*i+W];
|
||||
|
||||
float ox = projection.m00 * x + projection.m01 * y +
|
||||
projection.m02 * z + projection.m03 * w;
|
||||
float oy = projection.m10 * x + projection.m11 * y +
|
||||
projection.m12 * z + projection.m13 * w;
|
||||
float oz = projection.m20 * x + projection.m21 * y +
|
||||
projection.m22 * z + projection.m23 * w;
|
||||
float ow = projection.m30 * x + projection.m31 * y +
|
||||
projection.m32 * z + projection.m33 * w;
|
||||
if (nonZero(ow)) {
|
||||
ox /= ow;
|
||||
oy /= ow;
|
||||
oz /= ow;
|
||||
}
|
||||
screenVertices[3*i+X] = ox;
|
||||
screenVertices[3*i+Y] = oy;
|
||||
screenVertices[3*i+Z] = -oz;
|
||||
}
|
||||
}
|
||||
float[] screenVertices = this.screenVertices;
|
||||
|
||||
sortByMinZ(0, triangleCount-1);
|
||||
int[] vertexOffset = tessGeo.polyIndexCache.vertexOffset;
|
||||
short[] polyIndices = tessGeo.polyIndices;
|
||||
|
||||
float[] triA = this.triA;
|
||||
float[] triB = this.triB;
|
||||
|
||||
for (int i = 0; i < triangleCount; i++) {
|
||||
fetchTriCoords(triA, i, vertexOffset, indexCacheMap, screenVertices, polyIndices);
|
||||
minXBuffer[i] = PApplet.min(triA[X0], triA[X1], triA[X2]);
|
||||
maxXBuffer[i] = PApplet.max(triA[X0], triA[X1], triA[X2]);
|
||||
minYBuffer[i] = PApplet.min(triA[Y0], triA[Y1], triA[Y2]);
|
||||
maxYBuffer[i] = PApplet.max(triA[Y0], triA[Y1], triA[Y2]);
|
||||
minZBuffer[i] = PApplet.min(triA[Z0], triA[Z1], triA[Z2]);
|
||||
maxZBuffer[i] = PApplet.max(triA[Z0], triA[Z1], triA[Z2]);
|
||||
}
|
||||
|
||||
sortByMinZ(0, triangleCount - 1, triangleIndices, minZBuffer);
|
||||
|
||||
int activeTid = 0;
|
||||
|
||||
int markedCount = 0;
|
||||
BitSet marked = this.marked;
|
||||
BitSet swapped = this.swapped;
|
||||
|
||||
while (activeTid < triangleCount){
|
||||
marked.clear();
|
||||
|
||||
while (activeTid < triangleCount) {
|
||||
int testTid = activeTid + 1;
|
||||
boolean draw = false;
|
||||
int swappedCount = 0;
|
||||
|
||||
swapped.clear();
|
||||
|
||||
int ati = triangleIndices[activeTid];
|
||||
float minXA = minXBuffer[ati];
|
||||
float maxXA = maxXBuffer[ati];
|
||||
float minYA = minYBuffer[ati];
|
||||
float maxYA = maxYBuffer[ati];
|
||||
float maxZA = maxZBuffer[ati];
|
||||
|
||||
fetchTriCoords(triA, ati, vertexOffset, indexCacheMap, screenVertices, polyIndices);
|
||||
|
||||
while (!draw && testTid < triangleCount) {
|
||||
|
||||
int ati = triangleIndices[activeTid];
|
||||
int bti = triangleIndices[testTid];
|
||||
int tti = triangleIndices[testTid];
|
||||
|
||||
// TEST 1 // Z overlap
|
||||
if (maxCoord(ati, Z) <= minCoord(bti, Z) &&
|
||||
!contains(marked, markedCount, triangleIndices[testTid]) &&
|
||||
!contains(marked, markedCount, triangleIndices[activeTid])) {
|
||||
if (maxZA <= minZBuffer[tti] && !marked.get(tti)) {
|
||||
draw = true; // pass, not overlapping in Z, draw it
|
||||
|
||||
// TEST 2 // XY overlap using square window
|
||||
} else if (
|
||||
maxCoord(ati, X) <= minCoord(bti, X) ||
|
||||
maxCoord(ati, Y) <= minCoord(bti, Y) ||
|
||||
minCoord(ati, X) >= maxCoord(bti, X) ||
|
||||
minCoord(ati, Y) >= maxCoord(bti, Y)) {
|
||||
// TEST 2 // XY overlap using square window
|
||||
} else if (maxXA <= minXBuffer[tti] || maxYA <= minYBuffer[tti] ||
|
||||
minXA >= maxXBuffer[tti] || minYA >= maxYBuffer[tti]) {
|
||||
testTid++; // pass, not overlapping in XY
|
||||
|
||||
// TEST 3 // test on which side ACTIVE is relative to TEST
|
||||
} else if (side(bti, ati, -1) > 0) {
|
||||
testTid++; // pass, ACTIVE is in halfspace behind current TEST
|
||||
|
||||
// TEST 4 // test on which side TEST is relative to ACTIVE
|
||||
} else if (side(ati, bti, 1) > 0) {
|
||||
testTid++; // pass, current TEST is in halfspace in front of ACTIVE
|
||||
|
||||
// FAIL, wrong depth order, swap
|
||||
// TEST 3 // test on which side ACTIVE is relative to TEST
|
||||
} else {
|
||||
rotateRight(triangleIndices, activeTid, testTid);
|
||||
fetchTriCoords(triB, tti, vertexOffset, indexCacheMap,
|
||||
screenVertices, polyIndices);
|
||||
if (side(triB, triA, -1) > 0) {
|
||||
testTid++; // pass, ACTIVE is in halfspace behind current TEST
|
||||
|
||||
marked = arrayCheck(marked, markedCount, 1);
|
||||
if (insert(marked, markedCount, triangleIndices[activeTid])) {
|
||||
markedCount++;
|
||||
}
|
||||
// TEST 4 // test on which side TEST is relative to ACTIVE
|
||||
} else if (side(triA, triB, 1) > 0) {
|
||||
testTid++; // pass, current TEST is in halfspace in front of ACTIVE
|
||||
|
||||
swapped = arrayCheck(swapped, swappedCount, 1);
|
||||
if (insert(swapped, swappedCount, triangleIndices[activeTid])) {
|
||||
swappedCount++;
|
||||
testTid = activeTid + 1;
|
||||
// FAIL, wrong depth order, swap
|
||||
} else {
|
||||
// oops, we already tested this one, probably intersecting or
|
||||
// interlocked in loop with others, just draw it incorrectly :(
|
||||
draw = true;
|
||||
if (!swapped.get(tti)) {
|
||||
swapped.set(ati);
|
||||
marked.set(tti);
|
||||
rotateRight(triangleIndices, activeTid, testTid);
|
||||
|
||||
ati = tti;
|
||||
System.arraycopy(triB, 0, triA, 0, 9);
|
||||
minXA = minXBuffer[ati];
|
||||
maxXA = maxXBuffer[ati];
|
||||
minYA = minYBuffer[ati];
|
||||
maxYA = maxYBuffer[ati];
|
||||
maxZA = maxZBuffer[ati];
|
||||
|
||||
testTid = activeTid + 1;
|
||||
} else {
|
||||
// oops, we already tested this one, probably intersecting or
|
||||
// interlocked in loop with others, just draw it incorrectly :(
|
||||
draw = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
activeTid++;
|
||||
}
|
||||
|
||||
if (remove(marked, markedCount, activeTid)) {
|
||||
markedCount--;
|
||||
}
|
||||
if (draw || testTid >= triangleCount) {
|
||||
activeTid++;
|
||||
{ // Reorder the buffers
|
||||
for (int id = 0; id < triangleCount; id++) {
|
||||
int mappedId = triangleIndices[id];
|
||||
if (id != mappedId) {
|
||||
|
||||
// put the first index aside
|
||||
short i0 = polyIndices[3*id+0];
|
||||
short i1 = polyIndices[3*id+1];
|
||||
short i2 = polyIndices[3*id+2];
|
||||
int texCache = texCacheMap[id];
|
||||
int indexCache = indexCacheMap[id];
|
||||
|
||||
// process the whole permutation cycle
|
||||
int currId = id;
|
||||
int nextId = mappedId;
|
||||
do {
|
||||
triangleIndices[currId] = currId;
|
||||
polyIndices[3*currId+0] = polyIndices[3*nextId+0];
|
||||
polyIndices[3*currId+1] = polyIndices[3*nextId+1];
|
||||
polyIndices[3*currId+2] = polyIndices[3*nextId+2];
|
||||
texCacheMap[currId] = texCacheMap[nextId];
|
||||
indexCacheMap[currId] = indexCacheMap[nextId];
|
||||
|
||||
currId = nextId;
|
||||
nextId = triangleIndices[nextId];
|
||||
} while (nextId != id);
|
||||
|
||||
// place the first index at the end
|
||||
triangleIndices[currId] = currId;
|
||||
polyIndices[3*currId+0] = i0;
|
||||
polyIndices[3*currId+1] = i1;
|
||||
polyIndices[3*currId+2] = i2;
|
||||
texCacheMap[currId] = texCache;
|
||||
indexCacheMap[currId] = indexCache;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void sortByMinZ(int leftTid, int rightTid) {
|
||||
static void fetchTriCoords(float[] tri, int ti, int[] vertexOffset,
|
||||
int[] indexCacheMap, float[] screenVertices, short[] polyIndices) {
|
||||
int voffset = vertexOffset[indexCacheMap[ti]];
|
||||
int i0 = 3 * (voffset + polyIndices[3*ti+0]);
|
||||
int i1 = 3 * (voffset + polyIndices[3*ti+1]);
|
||||
int i2 = 3 * (voffset + polyIndices[3*ti+2]);
|
||||
tri[X0] = screenVertices[i0+X];
|
||||
tri[Y0] = screenVertices[i0+Y];
|
||||
tri[Z0] = screenVertices[i0+Z];
|
||||
tri[X1] = screenVertices[i1+X];
|
||||
tri[Y1] = screenVertices[i1+Y];
|
||||
tri[Z1] = screenVertices[i1+Z];
|
||||
tri[X2] = screenVertices[i2+X];
|
||||
tri[Y2] = screenVertices[i2+Y];
|
||||
tri[Z2] = screenVertices[i2+Z];
|
||||
}
|
||||
|
||||
static void sortByMinZ(int leftTid, int rightTid, int[] triangleIndices,
|
||||
float[] minZBuffer) {
|
||||
|
||||
// swap pivot to the front
|
||||
swap(triangleIndices, leftTid, ((leftTid + rightTid) / 2));
|
||||
|
||||
int k = leftTid;
|
||||
float leftMinZ = minCoord(triangleIndices[leftTid], Z);
|
||||
float leftMinZ = minZBuffer[triangleIndices[leftTid]];
|
||||
|
||||
// sort by min z
|
||||
for (int tid = leftTid+1; tid <= rightTid; tid++) {
|
||||
if (minCoord(triangleIndices[tid], Z) < leftMinZ) {
|
||||
float minZ = minZBuffer[triangleIndices[tid]];
|
||||
if (minZ < leftMinZ) {
|
||||
swap(triangleIndices, ++k, tid);
|
||||
}
|
||||
}
|
||||
@@ -13601,52 +13726,21 @@ public class PGraphicsOpenGL extends PGraphics {
|
||||
// swap pivot back to the middle
|
||||
swap(triangleIndices, leftTid, k);
|
||||
|
||||
if (leftTid < k - 1) sortByMinZ(leftTid, k - 1);
|
||||
if (k + 1 < rightTid) sortByMinZ(k + 1, rightTid);
|
||||
if (leftTid < k - 1) sortByMinZ(leftTid, k - 1, triangleIndices,
|
||||
minZBuffer);
|
||||
if (k + 1 < rightTid) sortByMinZ(k + 1, rightTid, triangleIndices,
|
||||
minZBuffer);
|
||||
}
|
||||
|
||||
// Math -----------------------------------------------
|
||||
|
||||
float minCoord(int ti, int off) {
|
||||
int voffset = tessGeo.polyIndexCache.vertexOffset[indexCacheMap[ti]];
|
||||
short[] is = tessGeo.polyIndices;
|
||||
float[] vs = screenVertices;
|
||||
int i0 = voffset + is[3*ti+0];
|
||||
int i1 = voffset + is[3*ti+1];
|
||||
int i2 = voffset + is[3*ti+2];
|
||||
return Math.min(vs[3*i0+off], Math.min(vs[3*i1+off], vs[3*i2+off]));
|
||||
}
|
||||
|
||||
float maxCoord(int ti, int off) {
|
||||
int voffset = tessGeo.polyIndexCache.vertexOffset[indexCacheMap[ti]];
|
||||
short[] is = tessGeo.polyIndices;
|
||||
float[] vs = screenVertices;
|
||||
int i0 = voffset + is[3*ti+0];
|
||||
int i1 = voffset + is[3*ti+1];
|
||||
int i2 = voffset + is[3*ti+2];
|
||||
return Math.max(vs[3*i0+off], Math.max(vs[3*i1+off], vs[3*i2+off]));
|
||||
}
|
||||
|
||||
int side(int ti, int testTi, float tz) {
|
||||
short[] is = tessGeo.polyIndices;
|
||||
float[] vs = screenVertices;
|
||||
|
||||
int avoffset = tessGeo.polyIndexCache.vertexOffset[indexCacheMap[ti]];
|
||||
int bvoffset = tessGeo.polyIndexCache.vertexOffset[indexCacheMap[testTi]];
|
||||
|
||||
int ia0 = avoffset + is[3*ti+0];
|
||||
int ia1 = avoffset + is[3*ti+1];
|
||||
int ia2 = avoffset + is[3*ti+2];
|
||||
int ib0 = bvoffset + is[3*testTi+0];
|
||||
int ib1 = bvoffset + is[3*testTi+1];
|
||||
int ib2 = bvoffset + is[3*testTi+2];
|
||||
|
||||
static int side(float[] tri1, float[] tri2, float tz) {
|
||||
float Dx, Dy, Dz, Dw;
|
||||
{ // Get the equation of the plane
|
||||
float
|
||||
ABx = vs[3*ia1+X] - vs[3*ia0+X], ACx = vs[3*ia2+X] - vs[3*ia0+X],
|
||||
ABy = vs[3*ia1+Y] - vs[3*ia0+Y], ACy = vs[3*ia2+Y] - vs[3*ia0+Y],
|
||||
ABz = vs[3*ia1+Z] - vs[3*ia0+Z], ACz = vs[3*ia2+Z] - vs[3*ia0+Z];
|
||||
ABx = tri1[X1] - tri1[X0], ACx = tri1[X2] - tri1[X0],
|
||||
ABy = tri1[Y1] - tri1[Y0], ACy = tri1[Y2] - tri1[Y0],
|
||||
ABz = tri1[Z1] - tri1[Z0], ACz = tri1[Z2] - tri1[Z0];
|
||||
|
||||
Dx = ABy*ACz - ABz*ACy; Dy = ABz*ACx - ABx*ACz; Dz = ABx*ACy - ABy*ACx;
|
||||
|
||||
@@ -13654,30 +13748,26 @@ public class PGraphicsOpenGL extends PGraphics {
|
||||
float rMag = 1.0f/(float) Math.sqrt(Dx * Dx + Dy * Dy + Dz * Dz);
|
||||
Dx *= rMag; Dy *= rMag; Dz *= rMag;
|
||||
|
||||
Dw = -dot(Dx, Dy, Dz, vs[3*ia0+X], vs[3*ia0+Y], vs[3*ia0+Z]);
|
||||
Dw = -dot(Dx, Dy, Dz, tri1[X0], tri1[Y0], tri1[Z0]);
|
||||
}
|
||||
|
||||
float distTest = dot(Dx, Dy, Dz,
|
||||
vs[3*ia0+X], vs[3*ia0+Y], vs[3*ia0+Z] + 100*tz) + Dw;
|
||||
tri1[X0], tri1[Y0], tri1[Z0] + 100*tz) + Dw;
|
||||
|
||||
float distA = dot(Dx, Dy, Dz, vs[3*ib0+X], vs[3*ib0+Y], vs[3*ib0+Z]) + Dw;
|
||||
float distB = dot(Dx, Dy, Dz, vs[3*ib1+X], vs[3*ib1+Y], vs[3*ib1+Z]) + Dw;
|
||||
float distC = dot(Dx, Dy, Dz, vs[3*ib2+X], vs[3*ib2+Y], vs[3*ib2+Z]) + Dw;
|
||||
float distA = dot(Dx, Dy, Dz, tri2[X0], tri2[Y0], tri2[Z0]) + Dw;
|
||||
float distB = dot(Dx, Dy, Dz, tri2[X1], tri2[Y1], tri2[Z1]) + Dw;
|
||||
float distC = dot(Dx, Dy, Dz, tri2[X2], tri2[Y2], tri2[Z2]) + Dw;
|
||||
|
||||
{ // Ignore relatively close vertices to get stable results
|
||||
// when some parts of polygons are close to each other
|
||||
float maxDist = Math.max(Math.abs(distA),
|
||||
Math.max(Math.abs(distB), Math.abs(distC)));
|
||||
float eps = maxDist * 0.1f;
|
||||
// Ignore relatively close vertices to get stable results
|
||||
// when some parts of polygons are close to each other
|
||||
float absA = PApplet.abs(distA);
|
||||
float absB = PApplet.abs(distB);
|
||||
float absC = PApplet.abs(distC);
|
||||
float eps = PApplet.max(absA, absB, absC) * 0.1f;
|
||||
|
||||
if (Math.abs(distA) < eps) distA = 0.0f;
|
||||
if (Math.abs(distB) < eps) distB = 0.0f;
|
||||
if (Math.abs(distC) < eps) distC = 0.0f;
|
||||
}
|
||||
|
||||
float sideA = distA * distTest;
|
||||
float sideB = distB * distTest;
|
||||
float sideC = distC * distTest;
|
||||
float sideA = ((absA < eps) ? 0.0f : distA) * distTest;
|
||||
float sideB = ((absB < eps) ? 0.0f : distB) * distTest;
|
||||
float sideC = ((absC < eps) ? 0.0f : distC) * distTest;
|
||||
|
||||
boolean sameSide = sideA >= 0 && sideB >= 0 && sideC >= 0;
|
||||
boolean notSameSide = sideA <= 0 && sideB <= 0 && sideC <= 0;
|
||||
@@ -13691,17 +13781,7 @@ public class PGraphicsOpenGL extends PGraphics {
|
||||
}
|
||||
|
||||
|
||||
// Array check ---------------------------------------
|
||||
|
||||
static int[] arrayCheck(int[] array, int size, int requested) {
|
||||
if (size + requested > array.length) {
|
||||
int newLength = Math.max(size + requested, 2 * array.length);
|
||||
int[] temp = new int[newLength];
|
||||
System.arraycopy(array, 0, temp, 0, size);
|
||||
array = temp;
|
||||
}
|
||||
return array;
|
||||
}
|
||||
// Array utils ---------------------------------------
|
||||
|
||||
static void swap(int[] array, int i1, int i2) {
|
||||
int temp = array[i1];
|
||||
@@ -13712,52 +13792,10 @@ public class PGraphicsOpenGL extends PGraphics {
|
||||
static void rotateRight(int[] array, int i1, int i2) {
|
||||
if (i1 == i2) return;
|
||||
int temp = array[i2];
|
||||
if (i2 - i1 < 100) {
|
||||
for (int i = i2; i > i1; i--) {
|
||||
array[i] = array[i-1];
|
||||
}
|
||||
} else {
|
||||
System.arraycopy(array, i1, array, i1 + 1, i2 - i1);
|
||||
}
|
||||
System.arraycopy(array, i1, array, i1 + 1, i2 - i1);
|
||||
array[i1] = temp;
|
||||
}
|
||||
|
||||
// if the value is not in the array, inserts the value
|
||||
// returns true if the value was inserted, false if found
|
||||
static boolean insert(int[] array, int count, int value) {
|
||||
int index = Arrays.binarySearch(array, 0, count, value);
|
||||
if (index >= 0) return false;
|
||||
index = -(index + 1);
|
||||
if (count - index > 100) {
|
||||
System.arraycopy(array, index, array, index+1, count - index);
|
||||
} else {
|
||||
for (int i = count; i > index; i--) {
|
||||
array[i] = array[i-1];
|
||||
}
|
||||
}
|
||||
array[index] = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
// if the value is in the array, removes the value
|
||||
// returns true if the value was removed, false if found
|
||||
static boolean remove(int[] array, int count, int value) {
|
||||
int index = Arrays.binarySearch(array, 0, count, value);
|
||||
if (index < 0) return false;
|
||||
if (count - index > 100) {
|
||||
System.arraycopy(array, index+1, array, index, count - index - 1);
|
||||
} else {
|
||||
for (int i = index; i < count-1; i++) {
|
||||
array[i] = array[i+1];
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static boolean contains(int[] array, int count, int value) {
|
||||
return Arrays.binarySearch(array, 0, count, value) >= 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user