diff --git a/vtm-gdx-html/src/org/oscim/gdx/emu/org/oscim/utils/Tessellator.java b/vtm-gdx-html/src/org/oscim/gdx/emu/org/oscim/utils/Tessellator.java
index e2f04c87..a22a93de 100644
--- a/vtm-gdx-html/src/org/oscim/gdx/emu/org/oscim/utils/Tessellator.java
+++ b/vtm-gdx-html/src/org/oscim/gdx/emu/org/oscim/utils/Tessellator.java
@@ -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)/*-{
diff --git a/vtm/jni/tessellate/TessellateJni.c b/vtm/jni/tessellate/TessellateJni.c
index bfa0a776..928ddd3e 100644
--- a/vtm/jni/tessellate/TessellateJni.c
+++ b/vtm/jni/tessellate/TessellateJni.c
@@ -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;
diff --git a/vtm/jni/tessellate/tessellate.c b/vtm/jni/tessellate/tessellate.c
index 7bedfcc4..33c0f4e9 100644
--- a/vtm/jni/tessellate/tessellate.c
+++ b/vtm/jni/tessellate/tessellate.c
@@ -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;
}
diff --git a/vtm/jni/tessellate/tessellate.h b/vtm/jni/tessellate/tessellate.h
index 0a2d5148..58849e47 100644
--- a/vtm/jni/tessellate/tessellate.h
+++ b/vtm/jni/tessellate/tessellate.h
@@ -14,6 +14,7 @@ typedef struct Vertex {
typedef struct TessContext {
Triangle *latest_t;
int n_tris;
+ int reversed;
Vertex *v_prev;
Vertex *v_prevprev;
diff --git a/vtm/src/org/oscim/renderer/elements/ExtrusionLayer.java b/vtm/src/org/oscim/renderer/elements/ExtrusionLayer.java
index e6a5a01b..8dc65d39 100644
--- a/vtm/src/org/oscim/renderer/elements/ExtrusionLayer.java
+++ b/vtm/src/org/oscim/renderer/elements/ExtrusionLayer.java
@@ -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);
diff --git a/vtm/src/org/oscim/utils/Tessellator.java b/vtm/src/org/oscim/utils/Tessellator.java
index 3d16db4e..68ec3cfe 100644
--- a/vtm/src/org/oscim/utils/Tessellator.java
+++ b/vtm/src/org/oscim/utils/Tessellator.java
@@ -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);
}