improve Tessellator, no more 'synchronized' needed
- pass VertexItem arrays to tessGetVertices/Indices until everything is fetched - re-reverse vertices in jni
This commit is contained in:
parent
768df7f6d6
commit
836f6a60e0
@ -1,6 +1,7 @@
|
||||
package org.oscim.utils;
|
||||
|
||||
import org.oscim.backend.Log;
|
||||
import org.oscim.core.GeometryBuffer;
|
||||
import org.oscim.renderer.elements.VertexItem;
|
||||
|
||||
import com.google.gwt.core.client.JavaScriptException;
|
||||
@ -11,7 +12,7 @@ import com.google.gwt.typedarrays.shared.Int32Array;
|
||||
|
||||
public class Tessellator {
|
||||
|
||||
public static synchronized int triangulate(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) {
|
||||
|
||||
//JavaScriptObject o;
|
||||
@ -68,6 +69,15 @@ public class Tessellator {
|
||||
return numIndices;
|
||||
}
|
||||
|
||||
public static int tessellate(GeometryBuffer geom, GeometryBuffer out) {
|
||||
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,
|
||||
JsArrayInteger bounds, int bOffset, int bLength)/*-{
|
||||
|
||||
|
||||
@ -31,8 +31,20 @@ void Java_org_oscim_utils_Tessellator_tessFinish(JNIEnv *env, jclass c, jlong pt
|
||||
free(ctx);
|
||||
}
|
||||
|
||||
jint Java_org_oscim_utils_Tessellator_tessGetCoordinates(JNIEnv *env, jclass c,
|
||||
jlong ptr_context, jshortArray obj_coords, jfloat scale) {
|
||||
Vertex *reverse(Vertex *root) {
|
||||
Vertex *start = 0;
|
||||
|
||||
while (root) {
|
||||
Vertex *prev = root->prev;
|
||||
root->prev = start;
|
||||
start = root;
|
||||
root = prev;
|
||||
}
|
||||
return start;
|
||||
}
|
||||
|
||||
jint Java_org_oscim_utils_Tessellator_tessGetVerticesWO(JNIEnv *env, jclass c,
|
||||
jlong ptr_context, jshortArray obj_coords, jint offset, jfloat scale) {
|
||||
|
||||
TessContext *ctx = CAST_CTX(ptr_context);
|
||||
|
||||
@ -43,23 +55,33 @@ jint Java_org_oscim_utils_Tessellator_tessGetCoordinates(JNIEnv *env, jclass c,
|
||||
return 0;
|
||||
}
|
||||
|
||||
//int n_verts = 1 + ctx->latest_v->index;
|
||||
//int n_tris_copy = ctx->n_tris;
|
||||
if (!ctx->reversed) {
|
||||
ctx->reversed = 1;
|
||||
ctx->latest_v = reverse(ctx->latest_v);
|
||||
}
|
||||
|
||||
int cnt = 0;
|
||||
for (; ctx->latest_v && cnt < length; cnt += 2) {
|
||||
coords[cnt + 0] = (ctx->latest_v->pt[0] * scale) + 0.5f;
|
||||
coords[cnt + 1] = (ctx->latest_v->pt[1] * scale) + 0.5f;
|
||||
int pos = offset;
|
||||
|
||||
for (; ctx->latest_v && pos < length; pos += 2) {
|
||||
coords[pos + 0] = (ctx->latest_v->pt[0] * scale) + 0.5f;
|
||||
coords[pos + 1] = (ctx->latest_v->pt[1] * scale) + 0.5f;
|
||||
Vertex *prev = ctx->latest_v->prev;
|
||||
free(ctx->latest_v);
|
||||
ctx->latest_v = prev;
|
||||
}
|
||||
(*env)->ReleasePrimitiveArrayCritical(env, obj_coords, coords, JNI_ABORT);
|
||||
|
||||
return cnt;
|
||||
return pos - offset;
|
||||
}
|
||||
|
||||
jint Java_org_oscim_utils_Tessellator_tessGetCoordinatesD(JNIEnv *env, jclass c,
|
||||
jint Java_org_oscim_utils_Tessellator_tessGetVertices(JNIEnv *env, jclass c,
|
||||
jlong ptr_context, jshortArray obj_coords, jfloat scale) {
|
||||
|
||||
return Java_org_oscim_utils_Tessellator_tessGetVerticesWO(env, c, ptr_context, obj_coords, 0,
|
||||
scale);
|
||||
}
|
||||
|
||||
jint Java_org_oscim_utils_Tessellator_tessGetVerticesD(JNIEnv *env, jclass c,
|
||||
jlong ptr_context, jdoubleArray obj_coords) {
|
||||
|
||||
TessContext *ctx = CAST_CTX(ptr_context);
|
||||
@ -71,8 +93,10 @@ jint Java_org_oscim_utils_Tessellator_tessGetCoordinatesD(JNIEnv *env, jclass c,
|
||||
return 0;
|
||||
}
|
||||
|
||||
//int n_verts = 1 + ctx->latest_v->index;
|
||||
//int n_tris_copy = ctx->n_tris;
|
||||
if (!ctx->reversed) {
|
||||
ctx->reversed = 1;
|
||||
ctx->latest_v = reverse(ctx->latest_v);
|
||||
}
|
||||
|
||||
int cnt = 0;
|
||||
for (; ctx->latest_v && cnt < length; cnt += 2) {
|
||||
@ -88,8 +112,8 @@ jint Java_org_oscim_utils_Tessellator_tessGetCoordinatesD(JNIEnv *env, jclass c,
|
||||
return cnt;
|
||||
}
|
||||
|
||||
jint Java_org_oscim_utils_Tessellator_tessGetIndices(JNIEnv *env, jclass c,
|
||||
jlong ptr_context, jshortArray obj_indices) {
|
||||
jint Java_org_oscim_utils_Tessellator_tessGetIndicesWO(JNIEnv *env, jclass c,
|
||||
jlong ptr_context, jshortArray obj_indices, int offset) {
|
||||
|
||||
TessContext *ctx = CAST_CTX(ptr_context);
|
||||
|
||||
@ -102,12 +126,12 @@ jint Java_org_oscim_utils_Tessellator_tessGetIndices(JNIEnv *env, jclass c,
|
||||
|
||||
int n_tris_copy = ctx->n_tris;
|
||||
|
||||
int cnt = 0;
|
||||
int pos = offset;
|
||||
|
||||
for (; ctx->latest_t && cnt < length; cnt += 3) {
|
||||
tris[cnt + 0] = ctx->latest_t->v[0];
|
||||
tris[cnt + 1] = ctx->latest_t->v[1];
|
||||
tris[cnt + 2] = ctx->latest_t->v[2];
|
||||
for (; ctx->latest_t && pos < length; pos += 3) {
|
||||
tris[pos + 0] = ctx->latest_t->v[0];
|
||||
tris[pos + 1] = ctx->latest_t->v[1];
|
||||
tris[pos + 2] = ctx->latest_t->v[2];
|
||||
Triangle *prev = ctx->latest_t->prev;
|
||||
|
||||
free(ctx->latest_t);
|
||||
@ -119,7 +143,15 @@ jint Java_org_oscim_utils_Tessellator_tessGetIndices(JNIEnv *env, jclass c,
|
||||
|
||||
(*env)->ReleasePrimitiveArrayCritical(env, obj_indices, tris, JNI_ABORT);
|
||||
|
||||
return cnt;
|
||||
return pos - offset;
|
||||
}
|
||||
|
||||
|
||||
jint Java_org_oscim_utils_Tessellator_tessGetIndices(JNIEnv *env, jclass c,
|
||||
jlong ptr_context, jshortArray obj_indices, int offset){
|
||||
|
||||
return Java_org_oscim_utils_Tessellator_tessGetIndicesWO(env, c,
|
||||
ptr_context, obj_indices, 0);
|
||||
}
|
||||
|
||||
jlong Java_org_oscim_utils_Tessellator_tessellate(JNIEnv *env, jclass c,
|
||||
@ -166,7 +198,6 @@ jlong Java_org_oscim_utils_Tessellator_tessellate(JNIEnv *env, jclass c,
|
||||
nverts = 1 + ctx->latest_v->index;
|
||||
ntris = ctx->n_tris;
|
||||
|
||||
|
||||
jint* out = (jint*) (*env)->GetPrimitiveArrayCritical(env, obj_out, &isCopy);
|
||||
if (out == NULL) {
|
||||
return 0;
|
||||
|
||||
@ -24,6 +24,7 @@ TessContext *new_tess_context()
|
||||
result->v_prev = NULL;
|
||||
result->vertex_cb = &skip_vertex;
|
||||
result->odd_even_strip = 0;
|
||||
result->reversed = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@ -14,6 +14,7 @@ typedef struct Vertex {
|
||||
typedef struct TessContext {
|
||||
Triangle *latest_t;
|
||||
int n_tris;
|
||||
int reversed;
|
||||
|
||||
Vertex *v_prev;
|
||||
Vertex *v_prevprev;
|
||||
|
||||
@ -26,6 +26,7 @@ import org.oscim.renderer.BufferObject;
|
||||
import org.oscim.renderer.MapRenderer;
|
||||
import org.oscim.utils.LineClipper;
|
||||
import org.oscim.utils.Tessellator;
|
||||
import org.oscim.utils.pool.Inlist;
|
||||
|
||||
/**
|
||||
* @author Hannes Janetzek
|
||||
@ -139,7 +140,8 @@ public class ExtrusionLayer extends RenderElement {
|
||||
if (simpleOutline && (ipos < n - 1) && (index[ipos + 1] > 0))
|
||||
simpleOutline = false;
|
||||
|
||||
boolean convex = addOutline(points, ppos, len, minHeight, height, simpleOutline);
|
||||
boolean convex = addOutline(points, ppos, len, minHeight,
|
||||
height, simpleOutline);
|
||||
|
||||
if (simpleOutline && (convex || len <= 8)) {
|
||||
addRoofSimple(startVertex, len);
|
||||
@ -184,20 +186,14 @@ public class ExtrusionLayer extends RenderElement {
|
||||
rings++;
|
||||
}
|
||||
|
||||
int used = Tessellator.triangulate(points, ppos, len, index, ipos, rings,
|
||||
startVertex + 1, mCurIndices[IND_ROOF]);
|
||||
Tessellator.tessellate(points, ppos, len, index, ipos, rings,
|
||||
startVertex + 1, mCurIndices[IND_ROOF]);
|
||||
|
||||
if (used > 0) {
|
||||
// get back to the last item added..
|
||||
VertexItem it = mIndices[IND_ROOF];
|
||||
while (it.next != null)
|
||||
it = it.next;
|
||||
mCurIndices[IND_ROOF] = it;
|
||||
}
|
||||
mCurIndices[IND_ROOF] = Inlist.last(mCurIndices[IND_ROOF]);
|
||||
}
|
||||
|
||||
private boolean addOutline(float[] points, int pos, int len, float minHeight, float height,
|
||||
boolean convex) {
|
||||
private boolean addOutline(float[] points, int pos, int len, float minHeight,
|
||||
float height, boolean convex) {
|
||||
|
||||
// add two vertices for last face to make zigzag indices work
|
||||
boolean addFace = (len % 4 != 0);
|
||||
|
||||
@ -1,14 +1,32 @@
|
||||
package org.oscim.utils;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.oscim.backend.Log;
|
||||
import org.oscim.core.GeometryBuffer;
|
||||
import org.oscim.renderer.elements.VertexItem;
|
||||
|
||||
public class Tessellator {
|
||||
private static final String TAG = Tessellator.class.getName();
|
||||
|
||||
private static final int RESULT_VERTICES = 0;
|
||||
//private static final int RESULT_TRIANGLES = 1;
|
||||
private static final int RESULT_TRIANGLES = 1;
|
||||
|
||||
private static final short[] coordinates = new short[720];
|
||||
|
||||
public static synchronized int triangulate(float[] points, int ppos, int plen, short[] index,
|
||||
/**
|
||||
* Special version for ExtrusionLayer to match indices with vertex
|
||||
* positions.
|
||||
*
|
||||
* @param points
|
||||
* @param ppos
|
||||
* @param plen
|
||||
* @param index
|
||||
* @param ipos
|
||||
* @param rings
|
||||
* @param vertexOffset
|
||||
* @param outTris
|
||||
* @return
|
||||
*/
|
||||
public static int tessellate(float[] points, int ppos, int plen, short[] index,
|
||||
int ipos, int rings, int vertexOffset, VertexItem outTris) {
|
||||
|
||||
int[] result = new int[2];
|
||||
@ -19,27 +37,28 @@ public class Tessellator {
|
||||
|
||||
long ctx = Tessellator.tessellate(points, ppos, index, ipos, rings, result);
|
||||
if ((numPoints / 2) < result[RESULT_VERTICES]) {
|
||||
//Log.d(TAG, "nup" + Arrays.toString(result) + " " + numPoints);
|
||||
Log.d(TAG, "skip poly: " + Arrays.toString(result) + " " + numPoints);
|
||||
Tessellator.tessFinish(ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//while (Tessellator.tessGetCoordinates(ctx, coordinates, 2) > 0) {
|
||||
// Log.d(TAG, Arrays.toString(coordinates));
|
||||
//}
|
||||
|
||||
int cnt;
|
||||
int numIndices = 0;
|
||||
|
||||
while ((cnt = Tessellator.tessGetIndices(ctx, coordinates)) > 0) {
|
||||
//if (cnt > (VertexItem.SIZE - outTris.used))
|
||||
// Log.d(TAG, "ok" + Arrays.toString(result));
|
||||
if (outTris.used == VertexItem.SIZE) {
|
||||
outTris.next = VertexItem.pool.get();
|
||||
outTris = outTris.next;
|
||||
}
|
||||
|
||||
//Log.d(TAG,Arrays.toString(coordinates));
|
||||
numIndices += cnt;
|
||||
while ((cnt = Tessellator.tessGetIndicesWO(ctx,
|
||||
outTris.vertices,
|
||||
outTris.used)) > 0) {
|
||||
int start = outTris.used;
|
||||
int end = start + cnt;
|
||||
short[] v = outTris.vertices;
|
||||
|
||||
for (int j = 0; j < cnt; j++)
|
||||
coordinates[j] *= 2;
|
||||
for (int i = start; i < end; i++)
|
||||
v[i] *= 2;
|
||||
|
||||
// when a ring has an odd number of points one (or rather two)
|
||||
// additional vertices will be added. so the following rings
|
||||
@ -52,30 +71,185 @@ public class Tessellator {
|
||||
if (((index[ipos + i] >> 1) & 1) == 0)
|
||||
continue;
|
||||
|
||||
for (int j = 0; j < cnt; j++)
|
||||
if (coordinates[j] >= shift)
|
||||
coordinates[j] += 2;
|
||||
for (int j = start; j < end; j++)
|
||||
if (v[j] >= shift)
|
||||
v[j] += 2;
|
||||
|
||||
shift += 2;
|
||||
}
|
||||
|
||||
for (int j = 0; j < cnt;) {
|
||||
int outPos = outTris.used;
|
||||
short[] v = outTris.vertices;
|
||||
// shift by vertexOffset
|
||||
for (int i = start; i < end; i++)
|
||||
v[i] += vertexOffset;
|
||||
|
||||
if (outPos == VertexItem.SIZE) {
|
||||
outTris.next = VertexItem.pool.get();
|
||||
outTris = outTris.next;
|
||||
v = outTris.vertices;
|
||||
outPos = 0;
|
||||
}
|
||||
outTris.used += cnt;
|
||||
numIndices += cnt;
|
||||
|
||||
// shift to vertex offset
|
||||
v[outPos++] = (short) (vertexOffset + coordinates[j++]);
|
||||
v[outPos++] = (short) (vertexOffset + coordinates[j++]);
|
||||
v[outPos++] = (short) (vertexOffset + coordinates[j++]);
|
||||
outTris.used = outPos;
|
||||
if (outTris.used == VertexItem.SIZE) {
|
||||
outTris.next = VertexItem.pool.get();
|
||||
outTris = outTris.next;
|
||||
continue;
|
||||
}
|
||||
|
||||
// no more indices to get.
|
||||
break;
|
||||
}
|
||||
|
||||
Tessellator.tessFinish(ctx);
|
||||
|
||||
return numIndices;
|
||||
}
|
||||
|
||||
/**
|
||||
* Untested!
|
||||
*
|
||||
* @param geom
|
||||
* @param out
|
||||
* @return
|
||||
*/
|
||||
public static int tessellate(GeometryBuffer geom, GeometryBuffer out) {
|
||||
|
||||
int[] result = new int[2];
|
||||
|
||||
//int numPoints = 0;
|
||||
//for (int i = 0; i < rings; i++)
|
||||
// numPoints += index[ipos + i];
|
||||
int numRings = 0;
|
||||
int numPoints = 0;
|
||||
|
||||
for (int i = 0; i < geom.indexPos; i++) {
|
||||
if (geom.index[i] > 0) {
|
||||
numRings++;
|
||||
numPoints += geom.index[i];
|
||||
} else
|
||||
break;
|
||||
}
|
||||
|
||||
long ctx = Tessellator.tessellate(geom.points, 0, geom.index, 0, numRings, result);
|
||||
|
||||
Log.d(TAG, "got " + result[RESULT_VERTICES] + " " + result[RESULT_TRIANGLES]);
|
||||
|
||||
boolean verticesAdded = false;
|
||||
if (numPoints < result[RESULT_VERTICES] * 2) {
|
||||
Log.d(TAG, "grow vertices" + geom.pointPos);
|
||||
verticesAdded = true;
|
||||
}
|
||||
|
||||
if (out == null) {
|
||||
// overwrite geom contents
|
||||
out = geom;
|
||||
if (verticesAdded) {
|
||||
out.ensurePointSize(result[RESULT_VERTICES], false);
|
||||
Tessellator.tessGetVerticesFloat(ctx, out.points);
|
||||
}
|
||||
} else {
|
||||
out.ensurePointSize(result[RESULT_VERTICES], false);
|
||||
|
||||
if (verticesAdded) {
|
||||
Tessellator.tessGetVerticesFloat(ctx, out.points);
|
||||
} else {
|
||||
System.arraycopy(geom.points, 0, out.points, 0, numPoints);
|
||||
}
|
||||
}
|
||||
|
||||
out.ensureIndexSize(result[RESULT_TRIANGLES * 3], false);
|
||||
Tessellator.tessGetIndices(ctx, out.index);
|
||||
|
||||
Tessellator.tessFinish(ctx);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param geom
|
||||
* @param scale
|
||||
* @param outPoints
|
||||
* @param outTris
|
||||
* @param vertexOffset
|
||||
* @return
|
||||
*/
|
||||
public static int tessellate(GeometryBuffer geom, float scale,
|
||||
VertexItem outPoints, VertexItem outTris, int vertexOffset) {
|
||||
|
||||
int[] result = new int[2];
|
||||
|
||||
//int numPoints = 0;
|
||||
//for (int i = 0; i < rings; i++)
|
||||
// numPoints += index[ipos + i];
|
||||
|
||||
int numRings = 0;
|
||||
int numPoints = 0;
|
||||
|
||||
for (int i = 0; i <= geom.indexPos; i++) {
|
||||
if (geom.index[i] <= 0)
|
||||
break;
|
||||
|
||||
numRings++;
|
||||
numPoints += (geom.index[i]) / 2;
|
||||
}
|
||||
if (numRings == 0 || numPoints == 0) {
|
||||
Log.d(TAG, "missing " + numPoints + ":" + numRings);
|
||||
return 0;
|
||||
}
|
||||
|
||||
long ctx = Tessellator.tessellate(geom.points, 0,
|
||||
geom.index, 0,
|
||||
numRings, result);
|
||||
|
||||
if (numPoints >= result[RESULT_VERTICES]) {
|
||||
// TODO use vertices from geom.points
|
||||
}
|
||||
|
||||
if (outPoints.used == VertexItem.SIZE) {
|
||||
outPoints.next = VertexItem.pool.get();
|
||||
outPoints = outPoints.next;
|
||||
}
|
||||
|
||||
int cnt;
|
||||
|
||||
while ((cnt = Tessellator.tessGetVerticesWO(ctx,
|
||||
outPoints.vertices,
|
||||
outPoints.used,
|
||||
scale)) > 0) {
|
||||
|
||||
outPoints.used += cnt;
|
||||
|
||||
if (outPoints.used == VertexItem.SIZE) {
|
||||
outPoints.next = VertexItem.pool.get();
|
||||
outPoints = outPoints.next;
|
||||
continue;
|
||||
}
|
||||
// no more points to get.
|
||||
break;
|
||||
}
|
||||
|
||||
int numIndices = 0;
|
||||
|
||||
if (outTris.used == VertexItem.SIZE) {
|
||||
outTris.next = VertexItem.pool.get();
|
||||
outTris = outTris.next;
|
||||
}
|
||||
|
||||
while ((cnt = Tessellator.tessGetIndicesWO(ctx,
|
||||
outTris.vertices,
|
||||
outTris.used)) > 0) {
|
||||
|
||||
// shift by vertexOffset
|
||||
for (int pos = outTris.used, end = pos + cnt; pos < end; pos++)
|
||||
outTris.vertices[pos] += vertexOffset;
|
||||
|
||||
outTris.used += cnt;
|
||||
numIndices += cnt;
|
||||
|
||||
if (outTris.used == VertexItem.SIZE) {
|
||||
outTris.next = VertexItem.pool.get();
|
||||
outTris = outTris.next;
|
||||
continue;
|
||||
}
|
||||
|
||||
// no more indices to get.
|
||||
break;
|
||||
}
|
||||
|
||||
Tessellator.tessFinish(ctx);
|
||||
@ -92,12 +266,19 @@ public class Tessellator {
|
||||
* @param result contains number of vertices and number of triangles
|
||||
* @return context - must be freed with tessFinish()
|
||||
*/
|
||||
public static native long tessellate(float[] points, int pos,
|
||||
protected static native long tessellate(float[] points, int pos,
|
||||
short[] index, int ipos, int numRings, int[] result);
|
||||
|
||||
public static native void tessFinish(long ctx);
|
||||
protected static native void tessFinish(long ctx);
|
||||
|
||||
public static native int tessGetCoordinates(long ctx, short[] coordinates, float scale);
|
||||
protected static native int tessGetVertices(long ctx, short[] coordinates, float scale);
|
||||
|
||||
public static native int tessGetIndices(long ctx, short[] indices);
|
||||
protected static native int tessGetVerticesWO(long ctx, short[] coordinates,
|
||||
int offset, float scale);
|
||||
|
||||
protected static native int tessGetVerticesFloat(long ctx, float[] coordinates);
|
||||
|
||||
protected static native int tessGetIndices(long ctx, short[] indices);
|
||||
|
||||
protected static native int tessGetIndicesWO(long ctx, short[] indices, int offset);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user