Tessellator: process all polygons from GeometryBuffer
(not just the first)
This commit is contained in:
parent
a0586a1897
commit
36d540da18
@ -2,19 +2,120 @@ package org.oscim.utils;
|
|||||||
|
|
||||||
import org.oscim.core.GeometryBuffer;
|
import org.oscim.core.GeometryBuffer;
|
||||||
import org.oscim.renderer.elements.VertexItem;
|
import org.oscim.renderer.elements.VertexItem;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import com.google.gwt.core.client.JavaScriptException;
|
import com.google.gwt.core.client.JavaScriptException;
|
||||||
|
import com.google.gwt.core.client.JavaScriptObject;
|
||||||
import com.google.gwt.core.client.JsArrayInteger;
|
import com.google.gwt.core.client.JsArrayInteger;
|
||||||
import com.google.gwt.core.client.JsArrayNumber;
|
import com.google.gwt.core.client.JsArrayNumber;
|
||||||
import com.google.gwt.core.client.JsArrayUtils;
|
import com.google.gwt.core.client.JsArrayUtils;
|
||||||
|
import com.google.gwt.typedarrays.shared.Float32Array;
|
||||||
import com.google.gwt.typedarrays.shared.Int32Array;
|
import com.google.gwt.typedarrays.shared.Int32Array;
|
||||||
|
|
||||||
public class Tessellator {
|
public class Tessellator {
|
||||||
|
static final Logger log = LoggerFactory.getLogger(Tessellator.class);
|
||||||
|
|
||||||
|
public static int tessellate(GeometryBuffer geom, float scale,
|
||||||
|
VertexItem outPoints, VertexItem outTris, int vertexOffset) {
|
||||||
|
|
||||||
|
int numIndices = 0;
|
||||||
|
int indexPos = 0;
|
||||||
|
int pointPos = 0;
|
||||||
|
int indexEnd = geom.index.length;
|
||||||
|
|
||||||
|
JsArrayNumber jspoints = JsArrayUtils.readOnlyJsArray(geom.points);
|
||||||
|
JsArrayInteger jsindex = JsArrayUtils.readOnlyJsArray(geom.index);
|
||||||
|
|
||||||
|
for (int idx = 0; idx < indexEnd && geom.index[idx] > 0; idx++) {
|
||||||
|
indexPos = idx;
|
||||||
|
|
||||||
|
int numRings = 1;
|
||||||
|
int numPoints = geom.index[idx++];
|
||||||
|
|
||||||
|
for (; idx < indexEnd && geom.index[idx] > 0; idx++) {
|
||||||
|
numRings++;
|
||||||
|
numPoints += geom.index[idx];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (numPoints <= 0 && numRings == 1){
|
||||||
|
log.debug("tessellation skip empty");
|
||||||
|
pointPos += numPoints;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
TessResult res;
|
||||||
|
try {
|
||||||
|
res = tessellate2(jspoints, pointPos, numPoints,
|
||||||
|
jsindex, indexPos, numRings);
|
||||||
|
} catch (JavaScriptException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
pointPos += numPoints;
|
||||||
|
|
||||||
|
if (res == null) {
|
||||||
|
log.debug("tessellation failed");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Int32Array io = res.getIndices(res);
|
||||||
|
int resIndices = io.length();
|
||||||
|
numIndices += resIndices;
|
||||||
|
|
||||||
|
for (int k = 0, cnt = 0; k < resIndices; k += cnt) {
|
||||||
|
|
||||||
|
if (outTris.used == VertexItem.SIZE) {
|
||||||
|
outTris.next = VertexItem.pool.get();
|
||||||
|
outTris = outTris.next;
|
||||||
|
}
|
||||||
|
|
||||||
|
cnt = VertexItem.SIZE - outTris.used;
|
||||||
|
|
||||||
|
if (k + cnt > resIndices)
|
||||||
|
cnt = resIndices - k;
|
||||||
|
|
||||||
|
for (int i = 0; i < cnt; i++)
|
||||||
|
outTris.vertices[outTris.used + i] =
|
||||||
|
(short) (vertexOffset + io.get(k + i));
|
||||||
|
|
||||||
|
outTris.used += cnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
Float32Array po = res.getPoints(res);
|
||||||
|
int resPoints = po.length();
|
||||||
|
|
||||||
|
vertexOffset += (resPoints >> 1);
|
||||||
|
|
||||||
|
for (int k = 0, cnt = 0; k < resPoints; k += cnt) {
|
||||||
|
|
||||||
|
if (outPoints.used == VertexItem.SIZE) {
|
||||||
|
outPoints.next = VertexItem.pool.get();
|
||||||
|
outPoints = outPoints.next;
|
||||||
|
}
|
||||||
|
|
||||||
|
cnt = VertexItem.SIZE - outPoints.used;
|
||||||
|
|
||||||
|
if (k + cnt > resPoints)
|
||||||
|
cnt = resPoints - k;
|
||||||
|
|
||||||
|
for (int i = 0; i < cnt; i++)
|
||||||
|
outPoints.vertices[outPoints.used + i] =
|
||||||
|
(short) (po.get(k + i) * scale);
|
||||||
|
|
||||||
|
outPoints.used += cnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (idx >= indexEnd || geom.index[idx] < 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return numIndices;
|
||||||
|
}
|
||||||
|
|
||||||
public static int tessellate(float[] points, int ppos, int plen, short[] index,
|
public static int tessellate(float[] points, int ppos, int plen, short[] index,
|
||||||
int ipos, int rings, int vertexOffset, VertexItem outTris) {
|
int ipos, int rings, int vertexOffset, VertexItem outTris) {
|
||||||
|
|
||||||
//JavaScriptObject o;
|
|
||||||
Int32Array io;
|
Int32Array io;
|
||||||
try {
|
try {
|
||||||
io = tessellate(JsArrayUtils.readOnlyJsArray(points), ppos, plen,
|
io = tessellate(JsArrayUtils.readOnlyJsArray(points), ppos, plen,
|
||||||
@ -24,9 +125,6 @@ public class Tessellator {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Float32Array vo = getPoints(o);
|
|
||||||
//Int32Array io = getIndices(o);
|
|
||||||
|
|
||||||
if (io == null) {
|
if (io == null) {
|
||||||
//log.debug("building tessellation failed");
|
//log.debug("building tessellation failed");
|
||||||
return 0;
|
return 0;
|
||||||
@ -72,31 +170,31 @@ public class Tessellator {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int tessellate(GeometryBuffer geom, float scale,
|
|
||||||
VertexItem outPoints, VertexItem outTris, int vertexOffset) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static native Int32Array tessellate(JsArrayNumber points, int pOffset, int pLength,
|
static native Int32Array tessellate(JsArrayNumber points, int pOffset, int pLength,
|
||||||
JsArrayInteger bounds, int bOffset, int bLength)/*-{
|
JsArrayInteger bounds, int bOffset, int bLength)/*-{
|
||||||
|
|
||||||
return $wnd.tessellate(points, pOffset, pOffset + pLength, bounds,
|
return $wnd.tessellate(points, pOffset, pOffset + pLength, bounds,
|
||||||
bOffset, bOffset + bLength);
|
bOffset, bOffset + bLength, false);
|
||||||
}-*/;
|
}-*/;
|
||||||
|
|
||||||
// static native JavaScriptObject tessellate(JsArrayNumber points, int pOffset, int pLength,
|
static native TessResult tessellate2(JsArrayNumber points, int pOffset, int pLength,
|
||||||
// JsArrayInteger bounds, int bOffset, int bLength)/*-{
|
JsArrayInteger bounds, int bOffset, int bLength)
|
||||||
//
|
/*-{
|
||||||
// return $wnd.tessellate(points, pOffset, pOffset + pLength, bounds,
|
|
||||||
// bOffset, bOffset + bLength);
|
|
||||||
// }-*/;
|
|
||||||
|
|
||||||
// static native Float32Array getPoints(JavaScriptObject result)/*-{
|
return $wnd.tessellate(points, pOffset, pOffset + pLength, bounds,
|
||||||
// return result.vertices;
|
bOffset, bOffset + bLength, true);
|
||||||
// }-*/;
|
}-*/;
|
||||||
|
|
||||||
// static native Int32Array getIndices(JavaScriptObject result)/*-{
|
static final class TessResult extends JavaScriptObject {
|
||||||
// return result.triangles;
|
protected TessResult() {
|
||||||
// }-*/;
|
}
|
||||||
|
|
||||||
|
native Float32Array getPoints(JavaScriptObject result)/*-{
|
||||||
|
return result.vertices;
|
||||||
|
}-*/;
|
||||||
|
|
||||||
|
native Int32Array getIndices(JavaScriptObject result)/*-{
|
||||||
|
return result.triangles;
|
||||||
|
}-*/;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ tessellate = (function() {
|
|||||||
|
|
||||||
// special tessellator for extrusion layer - only returns triangle indices
|
// special tessellator for extrusion layer - only returns triangle indices
|
||||||
var tessellate = function(vertices, v_start, v_end, boundaries, b_start,
|
var tessellate = function(vertices, v_start, v_end, boundaries, b_start,
|
||||||
b_end) {
|
b_end, mode) {
|
||||||
var i;
|
var i;
|
||||||
|
|
||||||
var v_len = (v_end - v_start);
|
var v_len = (v_end - v_start);
|
||||||
@ -44,20 +44,22 @@ tessellate = (function() {
|
|||||||
var nverts = Module.getValue(pnverts, 'i32');
|
var nverts = Module.getValue(pnverts, 'i32');
|
||||||
var ntris = Module.getValue(pntris, 'i32');
|
var ntris = Module.getValue(pntris, 'i32');
|
||||||
|
|
||||||
// var result_vertices = new Float32Array(nverts * 2);
|
|
||||||
var result_triangles = null;
|
var result_triangles = null;
|
||||||
|
var result_vertices = null;
|
||||||
|
|
||||||
|
if (mode){
|
||||||
|
result_triangles = new Int32Array(ntris * 3);
|
||||||
|
for (i = 0; i < 3 * ntris; ++i)
|
||||||
|
result_triangles[i] = Module.getValue(ptris_out + i * 4, 'i32');
|
||||||
|
|
||||||
|
result_vertices = new Float32Array(nverts * 2);
|
||||||
|
for (i = 0; i < 2 * nverts; ++i)
|
||||||
|
result_vertices[i] = Module.getValue(pcoordinates_out + i * 8, 'double');
|
||||||
|
|
||||||
|
} else {
|
||||||
if (nverts * 2 == v_len) {
|
if (nverts * 2 == v_len) {
|
||||||
result_triangles = new Int32Array(ntris * 3);
|
result_triangles = new Int32Array(ntris * 3);
|
||||||
|
|
||||||
// for (i=0; i<2*nverts; ++i) {
|
|
||||||
// result_vertices[i] = Module.getValue(pcoordinates_out + i*8,
|
|
||||||
// 'double');
|
|
||||||
// if (result_vertices[i] != vertices[v_start + i])
|
|
||||||
// console.log("i:" + i + " " + result_vertices[i] + " " +
|
|
||||||
// vertices[v_start + i]);
|
|
||||||
// }
|
|
||||||
|
|
||||||
for (i = 0; i < 3 * ntris; ++i) {
|
for (i = 0; i < 3 * ntris; ++i) {
|
||||||
result_triangles[i] = Module.getValue(ptris_out + i * 4, 'i32') * 2;
|
result_triangles[i] = Module.getValue(ptris_out + i * 4, 'i32') * 2;
|
||||||
}
|
}
|
||||||
@ -72,8 +74,6 @@ tessellate = (function() {
|
|||||||
if (!((boundaries[b_start + j] >> 1) & 1))
|
if (!((boundaries[b_start + j] >> 1) & 1))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// console.log("shift " + boundaries[b_start + j]);
|
|
||||||
|
|
||||||
for ( var n = ntris * 3, tri = 0; tri < n; tri++)
|
for ( var n = ntris * 3, tri = 0; tri < n; tri++)
|
||||||
if (result_triangles[tri] >= start)
|
if (result_triangles[tri] >= start)
|
||||||
result_triangles[tri] += 2;
|
result_triangles[tri] += 2;
|
||||||
@ -81,21 +81,25 @@ tessellate = (function() {
|
|||||||
start += 2;
|
start += 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Module._free(pnverts);
|
Module._free(pnverts);
|
||||||
Module._free(pntris);
|
Module._free(pntris);
|
||||||
|
|
||||||
Module._free(ppcoordinates_out);
|
Module._free(ppcoordinates_out);
|
||||||
Module._free(pptris_out);
|
|
||||||
Module._free(pcoordinates_out);
|
Module._free(pcoordinates_out);
|
||||||
|
|
||||||
|
Module._free(pptris_out);
|
||||||
Module._free(ptris_out);
|
Module._free(ptris_out);
|
||||||
|
|
||||||
Module._free(p);
|
Module._free(p);
|
||||||
Module._free(contours);
|
Module._free(contours);
|
||||||
|
|
||||||
|
if (mode)
|
||||||
|
return { vertices: result_vertices, triangles: result_triangles };
|
||||||
|
else
|
||||||
return result_triangles;
|
return result_triangles;
|
||||||
// return {
|
|
||||||
// vertices: result_vertices,
|
|
||||||
// triangles: result_triangles
|
|
||||||
// };
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return tessellate;
|
return tessellate;
|
||||||
|
@ -125,9 +125,6 @@ public class Tessellator {
|
|||||||
|
|
||||||
int[] result = new int[2];
|
int[] result = new int[2];
|
||||||
|
|
||||||
//int numPoints = 0;
|
|
||||||
//for (int i = 0; i < rings; i++)
|
|
||||||
// numPoints += index[ipos + i];
|
|
||||||
int numRings = 0;
|
int numRings = 0;
|
||||||
int numPoints = 0;
|
int numPoints = 0;
|
||||||
|
|
||||||
@ -143,10 +140,6 @@ public class Tessellator {
|
|||||||
geom.index, 0,
|
geom.index, 0,
|
||||||
numRings, result);
|
numRings, result);
|
||||||
|
|
||||||
//log.debug("got "
|
|
||||||
// + result[RESULT_VERTICES] + " "
|
|
||||||
// + result[RESULT_TRIANGLES]);
|
|
||||||
|
|
||||||
boolean verticesAdded = false;
|
boolean verticesAdded = false;
|
||||||
if (numPoints < result[RESULT_VERTICES] * 2) {
|
if (numPoints < result[RESULT_VERTICES] * 2) {
|
||||||
//log.debug("grow vertices" + geom.pointPos);
|
//log.debug("grow vertices" + geom.pointPos);
|
||||||
@ -190,65 +183,54 @@ public class Tessellator {
|
|||||||
public static int tessellate(GeometryBuffer geom, float scale,
|
public static int tessellate(GeometryBuffer geom, float scale,
|
||||||
VertexItem outPoints, VertexItem outTris, int vertexOffset) {
|
VertexItem outPoints, VertexItem outTris, int vertexOffset) {
|
||||||
|
|
||||||
|
int numIndices = 0;
|
||||||
|
int indexPos = 0;
|
||||||
|
int pointPos = 0;
|
||||||
|
int indexEnd = geom.index.length;
|
||||||
|
|
||||||
int[] result = new int[2];
|
int[] result = new int[2];
|
||||||
|
|
||||||
//int numPoints = 0;
|
float s = scale;
|
||||||
//for (int i = 0; i < rings; i++)
|
scale = 1;
|
||||||
// numPoints += index[ipos + i];
|
|
||||||
|
|
||||||
int numRings = 0;
|
for (int idx = 0; idx < indexEnd && geom.index[idx] > 0; idx++) {
|
||||||
int numPoints = 0;
|
indexPos = idx;
|
||||||
|
|
||||||
for (int i = 0; i <= geom.indexPos; i++) {
|
int numRings = 1;
|
||||||
if (geom.index[i] <= 0)
|
int numPoints = geom.index[idx++];
|
||||||
break;
|
|
||||||
|
|
||||||
|
for (; idx < indexEnd && geom.index[idx] > 0; idx++) {
|
||||||
numRings++;
|
numRings++;
|
||||||
numPoints += (geom.index[i]) / 2;
|
numPoints += geom.index[idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (numRings == 0 || numPoints == 0) {
|
for (int i = pointPos; i < pointPos + numPoints; i += 2) {
|
||||||
log.debug("missing " + numPoints + ":" + numRings);
|
geom.points[i + 0] = (int) (geom.points[i + 0] * s);
|
||||||
return 0;
|
geom.points[i + 1] = (int) (geom.points[i + 1] * s);
|
||||||
}
|
}
|
||||||
|
|
||||||
long ctx = Tessellator.tessellate(geom.points, 0,
|
long ctx = Tessellator.tessellate(geom.points, pointPos,
|
||||||
geom.index, 0,
|
geom.index, indexPos,
|
||||||
numRings, result);
|
numRings, result);
|
||||||
|
|
||||||
if (numPoints >= result[RESULT_VERTICES]) {
|
if (result[RESULT_VERTICES] == 0 || result[RESULT_TRIANGLES] == 0) {
|
||||||
// TODO use vertices from geom.points
|
log.debug("ppos " + pointPos + " ipos:" + indexPos +
|
||||||
}
|
" rings:" + numRings + " " + Arrays.toString(geom.index));
|
||||||
|
|
||||||
if (outPoints.used == VertexItem.SIZE) {
|
|
||||||
outPoints = VertexItem.pool.getNext(outPoints);
|
|
||||||
}
|
|
||||||
|
|
||||||
int cnt;
|
|
||||||
|
|
||||||
while ((cnt = Tessellator.tessGetVerticesWO(ctx,
|
|
||||||
outPoints.vertices,
|
|
||||||
outPoints.used,
|
|
||||||
scale)) > 0) {
|
|
||||||
outPoints.used += cnt;
|
|
||||||
|
|
||||||
if (outPoints.used == VertexItem.SIZE) {
|
|
||||||
outPoints = VertexItem.pool.getNext(outPoints);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// no more points to get.
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
int numIndices = 0;
|
pointPos += numPoints;
|
||||||
|
|
||||||
if (outTris.used == VertexItem.SIZE) {
|
if (outTris.used == VertexItem.SIZE)
|
||||||
outTris = VertexItem.pool.getNext(outTris);
|
outTris = VertexItem.pool.getNext(outTris);
|
||||||
}
|
|
||||||
|
|
||||||
while ((cnt = Tessellator.tessGetIndicesWO(ctx,
|
while (true) {
|
||||||
|
int cnt = Tessellator.tessGetIndicesWO(ctx,
|
||||||
outTris.vertices,
|
outTris.vertices,
|
||||||
outTris.used)) > 0) {
|
outTris.used);
|
||||||
|
if (cnt <= 0)
|
||||||
|
break;
|
||||||
|
|
||||||
// shift by vertexOffset
|
// shift by vertexOffset
|
||||||
for (int pos = outTris.used, end = pos + cnt; pos < end; pos++)
|
for (int pos = outTris.used, end = pos + cnt; pos < end; pos++)
|
||||||
outTris.vertices[pos] += vertexOffset;
|
outTris.vertices[pos] += vertexOffset;
|
||||||
@ -256,17 +238,42 @@ public class Tessellator {
|
|||||||
outTris.used += cnt;
|
outTris.used += cnt;
|
||||||
numIndices += cnt;
|
numIndices += cnt;
|
||||||
|
|
||||||
if (outTris.used == VertexItem.SIZE) {
|
if (outTris.used < VertexItem.SIZE)
|
||||||
|
break;
|
||||||
|
|
||||||
outTris = VertexItem.pool.getNext(outTris);
|
outTris = VertexItem.pool.getNext(outTris);
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// no more indices to get.
|
if (outPoints.used == VertexItem.SIZE)
|
||||||
|
outPoints = VertexItem.pool.getNext(outPoints);
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
int cnt = Tessellator.tessGetVerticesWO(ctx,
|
||||||
|
outPoints.vertices,
|
||||||
|
outPoints.used,
|
||||||
|
scale);
|
||||||
|
if (cnt <= 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
outPoints.used += cnt;
|
||||||
|
vertexOffset += cnt >> 1;
|
||||||
|
|
||||||
|
if (outPoints.used < VertexItem.SIZE)
|
||||||
|
break;
|
||||||
|
|
||||||
|
outPoints = VertexItem.pool.getNext(outPoints);
|
||||||
}
|
}
|
||||||
|
|
||||||
Tessellator.tessFinish(ctx);
|
Tessellator.tessFinish(ctx);
|
||||||
|
|
||||||
|
if (idx >= indexEnd || geom.index[idx] < 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vertexOffset > Short.MAX_VALUE) {
|
||||||
|
log.debug("too much !!!" + Arrays.toString(geom.index));
|
||||||
|
}
|
||||||
|
|
||||||
return numIndices;
|
return numIndices;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user