Tessellator: process all polygons from GeometryBuffer

(not just the first)
This commit is contained in:
Hannes Janetzek 2014-01-22 22:51:20 +01:00
parent a0586a1897
commit 36d540da18
3 changed files with 236 additions and 127 deletions

View File

@ -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;
}-*/;
}
} }

View File

@ -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;

View File

@ -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;
} }