diff --git a/jni/cp.sh b/jni/cp.sh index 62534d5f..10b00644 100755 --- a/jni/cp.sh +++ b/jni/cp.sh @@ -1,2 +1,3 @@ cp libs/armeabi/libvtm-jni.so ../vtm-ext-libs/vtm-android/armeabi cp libs/armeabi-v7a/libvtm-jni.so ../vtm-ext-libs/vtm-android/armeabi-v7a +cp libs/vtm-jni-natives.jar ../vtm-ext-libs/gdx/ diff --git a/jni/jni/Android.mk b/jni/jni/Android.mk index 1f45269f..3ac41939 100644 --- a/jni/jni/Android.mk +++ b/jni/jni/Android.mk @@ -9,14 +9,14 @@ LOCAL_CPPFLAGS := $(LOCAL_C_INCLUDES:%=-I%) -O2 -Wall -D__ANDROID__ -Wall -std=c LOCAL_LDLIBS := -lm -llog LOCAL_ARM_MODE := arm -LOCAL_SRC_FILES := libtess2/Source/sweep.c\ +LOCAL_SRC_FILES := org.oscim.utils.TessJNI.cpp\ + libtess2/Source/sweep.c\ libtess2/Source/priorityq.c\ libtess2/Source/bucketalloc.c\ libtess2/Source/geom.c\ libtess2/Source/tess.c\ libtess2/Source/dict.c\ libtess2/Source/mesh.c\ - org.oscim.utils.tess.Tesselator.cpp\ gl/utils.c include $(BUILD_SHARED_LIBRARY) diff --git a/jni/jni/org.oscim.utils.TessJNI.h b/jni/jni/org.oscim.utils.TessJNI.h new file mode 100644 index 00000000..b19d953d --- /dev/null +++ b/jni/jni/org.oscim.utils.TessJNI.h @@ -0,0 +1,155 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class org_oscim_utils_TessJNI */ + +#ifndef _Included_org_oscim_utils_TessJNI +#define _Included_org_oscim_utils_TessJNI +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: org_oscim_utils_TessJNI + * Method: newTess + * Signature: (I)J + */ +JNIEXPORT jlong JNICALL Java_org_oscim_utils_TessJNI_newTess + (JNIEnv *, jclass, jint); + +/* + * Class: org_oscim_utils_TessJNI + * Method: freeTess + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_org_oscim_utils_TessJNI_freeTess + (JNIEnv *, jclass, jlong); + +/* + * Class: org_oscim_utils_TessJNI + * Method: addContour + * Signature: (JI[FIII)V + */ +JNIEXPORT void JNICALL Java_org_oscim_utils_TessJNI_addContour + (JNIEnv *, jclass, jlong, jint, jfloatArray, jint, jint, jint); + +/* + * Class: org_oscim_utils_TessJNI + * Method: addMultiContour2D + * Signature: (J[I[FII)V + */ +JNIEXPORT void JNICALL Java_org_oscim_utils_TessJNI_addMultiContour2D + (JNIEnv *, jclass, jlong, jintArray, jfloatArray, jint, jint); + +/* + * Class: org_oscim_utils_TessJNI + * Method: tessContour2D + * Signature: (JIIII)I + */ +JNIEXPORT jint JNICALL Java_org_oscim_utils_TessJNI_tessContour2D + (JNIEnv *, jclass, jlong, jint, jint, jint, jint); + +/* + * Class: org_oscim_utils_TessJNI + * Method: getVertexCount + * Signature: (J)I + */ +JNIEXPORT jint JNICALL Java_org_oscim_utils_TessJNI_getVertexCount + (JNIEnv *, jclass, jlong); + +/* + * Class: org_oscim_utils_TessJNI + * Method: getVertices + * Signature: (J[FII)Z + */ +JNIEXPORT jboolean JNICALL Java_org_oscim_utils_TessJNI_getVertices + (JNIEnv *, jclass, jlong, jfloatArray, jint, jint); + +/* + * Class: org_oscim_utils_TessJNI + * Method: getVerticesS + * Signature: (J[SIIF)V + */ +JNIEXPORT void JNICALL Java_org_oscim_utils_TessJNI_getVerticesS + (JNIEnv *, jclass, jlong, jshortArray, jint, jint, jfloat); + +/* + * Class: org_oscim_utils_TessJNI + * Method: getVertexIndices + * Signature: (J[III)Z + */ +JNIEXPORT jboolean JNICALL Java_org_oscim_utils_TessJNI_getVertexIndices + (JNIEnv *, jclass, jlong, jintArray, jint, jint); + +/* + * Class: org_oscim_utils_TessJNI + * Method: getElementCount + * Signature: (J)I + */ +JNIEXPORT jint JNICALL Java_org_oscim_utils_TessJNI_getElementCount + (JNIEnv *, jclass, jlong); + +/* + * Class: org_oscim_utils_TessJNI + * Method: getElements + * Signature: (J[III)Z + */ +JNIEXPORT jboolean JNICALL Java_org_oscim_utils_TessJNI_getElements + (JNIEnv *, jclass, jlong, jintArray, jint, jint); + +/* + * Class: org_oscim_utils_TessJNI + * Method: getElementsS + * Signature: (J[SII)V + */ +JNIEXPORT void JNICALL Java_org_oscim_utils_TessJNI_getElementsS + (JNIEnv *, jclass, jlong, jshortArray, jint, jint); + +/* + * Class: org_oscim_utils_TessJNI + * Method: getElementsWithInputVertexIds + * Signature: (J[SIII)V + */ +JNIEXPORT void JNICALL Java_org_oscim_utils_TessJNI_getElementsWithInputVertexIds + (JNIEnv *, jclass, jlong, jshortArray, jint, jint, jint); + +#ifdef __cplusplus +} +#endif +#endif +/* Header for class org_oscim_utils_TessJNI_ElementType */ + +#ifndef _Included_org_oscim_utils_TessJNI_ElementType +#define _Included_org_oscim_utils_TessJNI_ElementType +#ifdef __cplusplus +extern "C" { +#endif +#undef org_oscim_utils_TessJNI_ElementType_POLYGONS +#define org_oscim_utils_TessJNI_ElementType_POLYGONS 0L +#undef org_oscim_utils_TessJNI_ElementType_CONNECTED_POLYGONS +#define org_oscim_utils_TessJNI_ElementType_CONNECTED_POLYGONS 1L +#undef org_oscim_utils_TessJNI_ElementType_BOUNDARY_CONTOURS +#define org_oscim_utils_TessJNI_ElementType_BOUNDARY_CONTOURS 2L +#ifdef __cplusplus +} +#endif +#endif +/* Header for class org_oscim_utils_TessJNI_WindingRule */ + +#ifndef _Included_org_oscim_utils_TessJNI_WindingRule +#define _Included_org_oscim_utils_TessJNI_WindingRule +#ifdef __cplusplus +extern "C" { +#endif +#undef org_oscim_utils_TessJNI_WindingRule_ODD +#define org_oscim_utils_TessJNI_WindingRule_ODD 0L +#undef org_oscim_utils_TessJNI_WindingRule_NONZERO +#define org_oscim_utils_TessJNI_WindingRule_NONZERO 1L +#undef org_oscim_utils_TessJNI_WindingRule_POSITIVE +#define org_oscim_utils_TessJNI_WindingRule_POSITIVE 2L +#undef org_oscim_utils_TessJNI_WindingRule_NEGATIVE +#define org_oscim_utils_TessJNI_WindingRule_NEGATIVE 3L +#undef org_oscim_utils_TessJNI_WindingRule_ABS_GEQ_TWO +#define org_oscim_utils_TessJNI_WindingRule_ABS_GEQ_TWO 4L +#ifdef __cplusplus +} +#endif +#endif diff --git a/jni/jni/org.oscim.utils.tess.Tesselator.cpp b/jni/jni/org.oscim.utils.tess.Tesselator.cpp deleted file mode 100644 index 5fee7a76..00000000 --- a/jni/jni/org.oscim.utils.tess.Tesselator.cpp +++ /dev/null @@ -1,224 +0,0 @@ -#include - -//@line:103 - - #include - #include - JNIEXPORT jlong JNICALL Java_org_oscim_utils_tess_Tesselator_newTess(JNIEnv* env, jclass clazz) { - - -//@line:107 - { - return (long)tessNewTess(0); - } - -} - -JNIEXPORT void JNICALL Java_org_oscim_utils_tess_Tesselator_freeTess(JNIEnv* env, jclass clazz, jlong inst) { - - -//@line:111 - { - tessDeleteTess((TESStesselator*) inst); - } - -} - -JNIEXPORT void JNICALL Java_org_oscim_utils_tess_Tesselator_addContour(JNIEnv* env, jclass clazz, jlong inst, jint size, jfloatArray obj_contour, jint stride, jint offset, jint count) { - float* contour = (float*)env->GetPrimitiveArrayCritical(obj_contour, 0); - - -//@line:125 - { - tessAddContour((TESStesselator*) inst, size, contour + (offset * stride), stride, count); - } - env->ReleasePrimitiveArrayCritical(obj_contour, contour, 0); - -} - -JNIEXPORT void JNICALL Java_org_oscim_utils_tess_Tesselator_addMultiContour2D(JNIEnv* env, jclass clazz, jlong inst, jintArray obj_index, jfloatArray obj_contour, jint idxStart, jint idxCount) { - int* index = (int*)env->GetPrimitiveArrayCritical(obj_index, 0); - float* contour = (float*)env->GetPrimitiveArrayCritical(obj_contour, 0); - - -//@line:129 - { - TESStesselator* tess = (TESStesselator*) inst; - int offset = 0; - - for (int i = 0; i < idxStart + idxCount; i++){ - int len = index[i]; - - if ((len % 2 != 0) || (len < 0)) - break; - - if (len < 6 || i < idxStart) { - offset += len; - continue; - } - - tessAddContour(tess, 2, contour + offset, 8, len >> 1); - - offset += len; - } - } - env->ReleasePrimitiveArrayCritical(obj_index, index, 0); - env->ReleasePrimitiveArrayCritical(obj_contour, contour, 0); - -} - -JNIEXPORT jint JNICALL Java_org_oscim_utils_tess_Tesselator_tessContour2D(JNIEnv* env, jclass clazz, jlong inst, jint windingRule, jint elementType, jint polySize, jint vertexSize) { - - -//@line:161 -{ - return tessTesselate((TESStesselator*) inst, windingRule, elementType, polySize, vertexSize, 0); - } - -} - -JNIEXPORT jint JNICALL Java_org_oscim_utils_tess_Tesselator_getVertexCount(JNIEnv* env, jclass clazz, jlong inst) { - - -//@line:165 -{ - return tessGetVertexCount((TESStesselator*) inst); - } - -} - -static inline jboolean wrapped_Java_org_oscim_utils_tess_Tesselator_getVertices -(JNIEnv* env, jclass clazz, jlong inst, jfloatArray obj_out, jint offset, jint length, float* out) { - -//@line:172 -{ - const TESSIOreal* vertices = tessGetVertices((TESStesselator*) inst); - - //const TESSreal* vertices = tessGetVertices((TESStesselator*) inst); - - if (!vertices) - return 0; - - memcpy(out, vertices + offset, length * sizeof(TESSIOreal)); - - //memcpy(out, vertices + offset, length * sizeof(TESSreal)); - - return 1; - } -} - -JNIEXPORT jboolean JNICALL Java_org_oscim_utils_tess_Tesselator_getVertices(JNIEnv* env, jclass clazz, jlong inst, jfloatArray obj_out, jint offset, jint length) { - float* out = (float*)env->GetPrimitiveArrayCritical(obj_out, 0); - - jboolean JNI_returnValue = wrapped_Java_org_oscim_utils_tess_Tesselator_getVertices(env, clazz, inst, obj_out, offset, length, out); - - env->ReleasePrimitiveArrayCritical(obj_out, out, 0); - - return JNI_returnValue; -} - -JNIEXPORT void JNICALL Java_org_oscim_utils_tess_Tesselator_getVerticesS(JNIEnv* env, jclass clazz, jlong inst, jshortArray obj_out, jint offset, jint length, jfloat scale) { - short* out = (short*)env->GetPrimitiveArrayCritical(obj_out, 0); - - -//@line:190 -{ - const TESSIOreal* vertices = tessGetVertices((TESStesselator*) inst); - - //const TESSreal* vertices = tessGetVertices((TESStesselator*) inst); - - for(int i = 0; i < length; i++) - out[i] = (short)(vertices[offset++] * scale + 0.5f); - } - env->ReleasePrimitiveArrayCritical(obj_out, out, 0); - -} - -static inline jboolean wrapped_Java_org_oscim_utils_tess_Tesselator_getVertexIndices -(JNIEnv* env, jclass clazz, jlong inst, jintArray obj_out, jint offset, jint length, int* out) { - -//@line:206 - { - const TESSindex* indices = tessGetVertexIndices((TESStesselator*) inst); - if (!indices) - return 0; - - memcpy(out, indices + offset, length * sizeof(TESSindex)); - return 1; - } -} - -JNIEXPORT jboolean JNICALL Java_org_oscim_utils_tess_Tesselator_getVertexIndices(JNIEnv* env, jclass clazz, jlong inst, jintArray obj_out, jint offset, jint length) { - int* out = (int*)env->GetPrimitiveArrayCritical(obj_out, 0); - - jboolean JNI_returnValue = wrapped_Java_org_oscim_utils_tess_Tesselator_getVertexIndices(env, clazz, inst, obj_out, offset, length, out); - - env->ReleasePrimitiveArrayCritical(obj_out, out, 0); - - return JNI_returnValue; -} - -JNIEXPORT jint JNICALL Java_org_oscim_utils_tess_Tesselator_getElementCount(JNIEnv* env, jclass clazz, jlong inst) { - - -//@line:218 -{ - return tessGetElementCount((TESStesselator*) inst); - } - -} - -static inline jboolean wrapped_Java_org_oscim_utils_tess_Tesselator_getElements -(JNIEnv* env, jclass clazz, jlong inst, jintArray obj_out, jint offset, jint length, int* out) { - -//@line:225 -{ - const TESSindex* elements = tessGetElements((TESStesselator*) inst); - if (!elements) - return 0; - - memcpy(out, elements + offset, length * sizeof(TESSindex)); - return 1; - } -} - -JNIEXPORT jboolean JNICALL Java_org_oscim_utils_tess_Tesselator_getElements(JNIEnv* env, jclass clazz, jlong inst, jintArray obj_out, jint offset, jint length) { - int* out = (int*)env->GetPrimitiveArrayCritical(obj_out, 0); - - jboolean JNI_returnValue = wrapped_Java_org_oscim_utils_tess_Tesselator_getElements(env, clazz, inst, obj_out, offset, length, out); - - env->ReleasePrimitiveArrayCritical(obj_out, out, 0); - - return JNI_returnValue; -} - -JNIEXPORT void JNICALL Java_org_oscim_utils_tess_Tesselator_getElementsS(JNIEnv* env, jclass clazz, jlong inst, jshortArray obj_out, jint offset, jint length) { - short* out = (short*)env->GetPrimitiveArrayCritical(obj_out, 0); - - -//@line:238 -{ - const TESSindex* elements = tessGetElements((TESStesselator*) inst); - for(int i = 0; i < length; i++) - out[i] = (short)elements[offset++]; - } - env->ReleasePrimitiveArrayCritical(obj_out, out, 0); - -} - -JNIEXPORT void JNICALL Java_org_oscim_utils_tess_Tesselator_getElementsWithInputVertexIds(JNIEnv* env, jclass clazz, jlong inst, jshortArray obj_out, jint dstOffset, jint offset, jint length) { - short* out = (short*)env->GetPrimitiveArrayCritical(obj_out, 0); - - -//@line:247 -{ - const TESSindex* elements = tessGetElements((TESStesselator*) inst); - const TESSindex* indices = tessGetVertexIndices((TESStesselator*) inst); - - for(int i = 0; i < length; i++) - out[dstOffset++] = (short)indices[elements[offset++]]; - } - env->ReleasePrimitiveArrayCritical(obj_out, out, 0); - -} - diff --git a/jni/jni/org.oscim.utils.tess.Tesselator.h b/jni/jni/org.oscim.utils.tess.Tesselator.h deleted file mode 100644 index 5f00bbbb..00000000 --- a/jni/jni/org.oscim.utils.tess.Tesselator.h +++ /dev/null @@ -1,155 +0,0 @@ -/* DO NOT EDIT THIS FILE - it is machine generated */ -#include -/* Header for class org_oscim_utils_tess_Tesselator */ - -#ifndef _Included_org_oscim_utils_tess_Tesselator -#define _Included_org_oscim_utils_tess_Tesselator -#ifdef __cplusplus -extern "C" { -#endif -/* - * Class: org_oscim_utils_tess_Tesselator - * Method: newTess - * Signature: ()J - */ -JNIEXPORT jlong JNICALL Java_org_oscim_utils_tess_Tesselator_newTess - (JNIEnv *, jclass); - -/* - * Class: org_oscim_utils_tess_Tesselator - * Method: freeTess - * Signature: (J)V - */ -JNIEXPORT void JNICALL Java_org_oscim_utils_tess_Tesselator_freeTess - (JNIEnv *, jclass, jlong); - -/* - * Class: org_oscim_utils_tess_Tesselator - * Method: addContour - * Signature: (JI[FIII)V - */ -JNIEXPORT void JNICALL Java_org_oscim_utils_tess_Tesselator_addContour - (JNIEnv *, jclass, jlong, jint, jfloatArray, jint, jint, jint); - -/* - * Class: org_oscim_utils_tess_Tesselator - * Method: addMultiContour2D - * Signature: (J[I[FII)V - */ -JNIEXPORT void JNICALL Java_org_oscim_utils_tess_Tesselator_addMultiContour2D - (JNIEnv *, jclass, jlong, jintArray, jfloatArray, jint, jint); - -/* - * Class: org_oscim_utils_tess_Tesselator - * Method: tessContour2D - * Signature: (JIIII)I - */ -JNIEXPORT jint JNICALL Java_org_oscim_utils_tess_Tesselator_tessContour2D - (JNIEnv *, jclass, jlong, jint, jint, jint, jint); - -/* - * Class: org_oscim_utils_tess_Tesselator - * Method: getVertexCount - * Signature: (J)I - */ -JNIEXPORT jint JNICALL Java_org_oscim_utils_tess_Tesselator_getVertexCount - (JNIEnv *, jclass, jlong); - -/* - * Class: org_oscim_utils_tess_Tesselator - * Method: getVertices - * Signature: (J[FII)Z - */ -JNIEXPORT jboolean JNICALL Java_org_oscim_utils_tess_Tesselator_getVertices - (JNIEnv *, jclass, jlong, jfloatArray, jint, jint); - -/* - * Class: org_oscim_utils_tess_Tesselator - * Method: getVerticesS - * Signature: (J[SIIF)V - */ -JNIEXPORT void JNICALL Java_org_oscim_utils_tess_Tesselator_getVerticesS - (JNIEnv *, jclass, jlong, jshortArray, jint, jint, jfloat); - -/* - * Class: org_oscim_utils_tess_Tesselator - * Method: getVertexIndices - * Signature: (J[III)Z - */ -JNIEXPORT jboolean JNICALL Java_org_oscim_utils_tess_Tesselator_getVertexIndices - (JNIEnv *, jclass, jlong, jintArray, jint, jint); - -/* - * Class: org_oscim_utils_tess_Tesselator - * Method: getElementCount - * Signature: (J)I - */ -JNIEXPORT jint JNICALL Java_org_oscim_utils_tess_Tesselator_getElementCount - (JNIEnv *, jclass, jlong); - -/* - * Class: org_oscim_utils_tess_Tesselator - * Method: getElements - * Signature: (J[III)Z - */ -JNIEXPORT jboolean JNICALL Java_org_oscim_utils_tess_Tesselator_getElements - (JNIEnv *, jclass, jlong, jintArray, jint, jint); - -/* - * Class: org_oscim_utils_tess_Tesselator - * Method: getElementsS - * Signature: (J[SII)V - */ -JNIEXPORT void JNICALL Java_org_oscim_utils_tess_Tesselator_getElementsS - (JNIEnv *, jclass, jlong, jshortArray, jint, jint); - -/* - * Class: org_oscim_utils_tess_Tesselator - * Method: getElementsWithInputVertexIds - * Signature: (J[SIII)V - */ -JNIEXPORT void JNICALL Java_org_oscim_utils_tess_Tesselator_getElementsWithInputVertexIds - (JNIEnv *, jclass, jlong, jshortArray, jint, jint, jint); - -#ifdef __cplusplus -} -#endif -#endif -/* Header for class org_oscim_utils_tess_Tesselator_ElementType */ - -#ifndef _Included_org_oscim_utils_tess_Tesselator_ElementType -#define _Included_org_oscim_utils_tess_Tesselator_ElementType -#ifdef __cplusplus -extern "C" { -#endif -#undef org_oscim_utils_tess_Tesselator_ElementType_POLYGONS -#define org_oscim_utils_tess_Tesselator_ElementType_POLYGONS 0L -#undef org_oscim_utils_tess_Tesselator_ElementType_CONNECTED_POLYGONS -#define org_oscim_utils_tess_Tesselator_ElementType_CONNECTED_POLYGONS 1L -#undef org_oscim_utils_tess_Tesselator_ElementType_BOUNDARY_CONTOURS -#define org_oscim_utils_tess_Tesselator_ElementType_BOUNDARY_CONTOURS 2L -#ifdef __cplusplus -} -#endif -#endif -/* Header for class org_oscim_utils_tess_Tesselator_WindingRule */ - -#ifndef _Included_org_oscim_utils_tess_Tesselator_WindingRule -#define _Included_org_oscim_utils_tess_Tesselator_WindingRule -#ifdef __cplusplus -extern "C" { -#endif -#undef org_oscim_utils_tess_Tesselator_WindingRule_ODD -#define org_oscim_utils_tess_Tesselator_WindingRule_ODD 0L -#undef org_oscim_utils_tess_Tesselator_WindingRule_NONZERO -#define org_oscim_utils_tess_Tesselator_WindingRule_NONZERO 1L -#undef org_oscim_utils_tess_Tesselator_WindingRule_POSITIVE -#define org_oscim_utils_tess_Tesselator_WindingRule_POSITIVE 2L -#undef org_oscim_utils_tess_Tesselator_WindingRule_NEGATIVE -#define org_oscim_utils_tess_Tesselator_WindingRule_NEGATIVE 3L -#undef org_oscim_utils_tess_Tesselator_WindingRule_ABS_GEQ_TWO -#define org_oscim_utils_tess_Tesselator_WindingRule_ABS_GEQ_TWO 4L -#ifdef __cplusplus -} -#endif -#endif diff --git a/jni/src/org/oscim/utils/TessJNI.java b/jni/src/org/oscim/utils/TessJNI.java new file mode 100644 index 00000000..2513e8e4 --- /dev/null +++ b/jni/src/org/oscim/utils/TessJNI.java @@ -0,0 +1,265 @@ +package org.oscim.utils; + +public class TessJNI { + private long inst; + + public TessJNI() { + inst = newTess(0); + } + + public TessJNI(int bucketSize) { + inst = newTess(bucketSize); + } + + @Override + protected void finalize() { + dispose(); + } + + public void dispose() { + if (inst != 0) { + freeTess(inst); + inst = 0; + } + } + + protected long instance() { + return inst; + } + + /** + * See OpenGL Red Book for description of the winding rules + * http://www.glprogramming.com/red/chapter11.html + */ + public static final class WindingRule { + public static final int ODD = 0; + public static final int NONZERO = 1; + public static final int POSITIVE = 2; + public static final int NEGATIVE = 3; + public static final int ABS_GEQ_TWO = 4; + } + + public static final class ElementType { + public static final int POLYGONS = 0; + public static final int CONNECTED_POLYGONS = 1; + public static final int BOUNDARY_CONTOURS = 2; + } + + public void addContour2D(float[] points) { + addContour2D(points, 0, points.length >> 1); + } + + public void addContour2D(float[] points, int offset, int length) { + if (length < 6) + return; + if ((length % 2 != 0) || (offset % 2 != 0) || (points.length >> 1) < (offset + length)) + throw new IllegalArgumentException("Invalid input: length:" + length + + ", offset:" + offset + + ", points.length:" + points.length); + addContour(inst, 2, points, 8, offset, length); + } + + public void addContour2D(int[] index, float[] contour) { + addMultiContour2D(inst, index, contour, 0, index.length); + } + + public void addContour2D(int[] index, float[] contour, int idxStart, int idxEnd) { + addMultiContour2D(inst, index, contour, idxStart, idxEnd); + } + + public boolean tesselate() { + return tessContour2D(inst, + TessJNI.WindingRule.POSITIVE, + TessJNI.ElementType.POLYGONS, + 3, 2) == 1; + } + + public boolean tesselate(int windingRule, int elementType) { + return tessContour2D(inst, windingRule, elementType, 3, 2) == 1; + } + + public int getVertexCount() { + return getVertexCount(inst); + } + + public int getElementCount() { + return getElementCount(inst); + } + + public void getVertices(float[] out, int offset, int length) { + getVertices(inst, out, offset, length); + } + + public void getVertices(short[] out, int offset, int length, float scale) { + getVerticesS(inst, out, offset, length, scale); + } + + public void getElements(int[] out, int offset, int length) { + getElements(inst, out, offset, length); + } + + public void getElements(short[] out, int offset, int length) { + getElementsS(inst, out, offset, length); + } + + public void getVertexIndices(int[] out, int offset, int length) { + getVertexIndices(inst, out, offset, length); + } + + public void getElementsWithInputVertexIds(short[] dst, int dstOffset, int offset, int length) { + getElementsWithInputVertexIds(inst, dst, dstOffset, offset, length); + } + + // @formatter:off + /*JNI + #include + #include + #include + void* heapAlloc( void* userData, unsigned int size ){ + TESS_NOTUSED( userData ); + return malloc( size ); + } + void* heapRealloc( void *userData, void* ptr, unsigned int size ){ + TESS_NOTUSED( userData ); + return realloc( ptr, size ); + } + void heapFree( void* userData, void* ptr ){ + TESS_NOTUSED( userData ); + free( ptr ); + } + */ + static native long newTess(int size); /* { + if (size <= 0) + return (long)tessNewTess(0); + if (size > 10) + size = 10; + TESSalloc ma; + memset(&ma, 0, sizeof(ma)); + ma.memalloc = heapAlloc; + ma.memfree = heapFree; + ma.memrealloc = heapRealloc; + //ma.userData = (void*)&allocated; + ma.meshEdgeBucketSize = 2 << size; // 512 + ma.meshVertexBucketSize = 2 << size; // 512 + ma.meshFaceBucketSize = 1 << size; // 256 + ma.dictNodeBucketSize = 2 << size; // 512 + ma.regionBucketSize = 1 << size; // 256 + ma.extraVertices = 8; + //ma.extraVertices = 256; + return (long)tessNewTess(&ma); + } */ + static native void freeTess(long inst); /* { + tessDeleteTess((TESStesselator*) inst); + } */ + /** + * Adds a contour to be tesselated. + * The type of the vertex coordinates is assumed to be TESSreal. + * + * @param tess - pointer to tesselator object. + * @param size - number of coordinates per vertex. Must be 2 or 3. + * @param pointer - pointer to the first coordinate of the first vertex in the array. + * @param stride - defines offset in bytes between consecutive vertices. + * @param count - number of vertices in contour. + */ + static native void addContour(long inst, int size, float[] contour, int stride, int offset, int count);/* { + tessAddContour((TESStesselator*) inst, size, contour + (offset * stride), stride, count); + } */ + static native void addMultiContour2D(long inst, int[] index, float[] contour, int idxStart, int idxCount);/* { + TESStesselator* tess = (TESStesselator*) inst; + int offset = 0; + // start at 0 to get the correct offset in contour.. + for (int i = 0; i < idxStart + idxCount; i++){ + int len = index[i]; + if ((len % 2 != 0) || (len < 0)) + break; + if (len < 6 || i < idxStart) { + offset += len; + continue; + } + tessAddContour(tess, 2, contour + offset, 8, len >> 1); + offset += len; + } + } */ + /** + * Tesselate contours. + * + * @param tess - pointer to tesselator object. + * @param windingRule - winding rules used for tesselation, must be one of TessWindingRule. + * @param elementType - defines the tesselation result element type, must be one of TessElementType. + * @param polySize - defines maximum vertices per polygons if output is polygons. + * @param vertexSize - defines the number of coordinates in tesselation result vertex, must be 2 or 3. + * @param normal - defines the normal of the input contours, of null the normal is calculated automatically. + * @return 1 if succeed, 0 if failed. + */ + static native int tessContour2D(long inst, int windingRule, int elementType, int polySize, int vertexSize);/*{ + return tessTesselate((TESStesselator*) inst, windingRule, elementType, polySize, vertexSize, 0); + } */ + static native int getVertexCount(long inst); /*{ + return tessGetVertexCount((TESStesselator*) inst); + }*/ + /** + * Returns pointer to first coordinate of first vertex. + */ + static native boolean getVertices(long inst, float[] out, int offset, int length);/*{ + const TESSreal* vertices = tessGetVertices((TESStesselator*) inst); + if (!vertices) + return 0; + memcpy(out, vertices + offset, length * sizeof(TESSreal)); + return 1; + }*/ + /** + * Returns pointer to first coordinate of first vertex. + */ + static native void getVerticesS(long inst, short[] out, int offset, int length, float scale);/*{ + const TESSreal* vertices = tessGetVertices((TESStesselator*) inst); + for(int i = 0; i < length; i++) + out[i] = (short)(vertices[offset++] * scale + 0.5f); + }*/ + /** + * Returns pointer to first vertex index. + * + * Vertex indices can be used to map the generated vertices to the original vertices. + * Every point added using tessAddContour() will get a new index starting at 0. + * New vertices generated at the intersections of segments are assigned value TESS_UNDEF. + */ + static native boolean getVertexIndices(long inst, int[] out, int offset, int length);/* { + const TESSindex* indices = tessGetVertexIndices((TESStesselator*) inst); + if (!indices) + return 0; + memcpy(out, indices + offset, length * sizeof(TESSindex)); + return 1; + } */ + /** + * Returns number of elements in the the tesselated output. + */ + static native int getElementCount(long inst);/*{ + return tessGetElementCount((TESStesselator*) inst); + }*/ + /** + * Returns pointer to the first element. + */ + static native boolean getElements(long inst, int[] out, int offset, int length);/*{ + const TESSindex* elements = tessGetElements((TESStesselator*) inst); + if (!elements) + return 0; + memcpy(out, elements + offset, length * sizeof(TESSindex)); + return 1; + }*/ + /** + * Returns pointer to the first element. + */ + static native void getElementsS(long inst, short[] out, int offset, int length);/*{ + const TESSindex* elements = tessGetElements((TESStesselator*) inst); + for(int i = 0; i < length; i++) + out[i] = (short)elements[offset++]; + }*/ + /** + * Returns list of triangles indices (or to the first element of convex polygons). + */ + static native void getElementsWithInputVertexIds(long inst, short[] out, int dstOffset, int offset, int length);/*{ + const TESSindex* elements = tessGetElements((TESStesselator*) inst); + const TESSindex* indices = tessGetVertexIndices((TESStesselator*) inst); + for(int i = 0; i < length; i++) + out[dstOffset++] = (short)(indices[elements[offset++]]); + }*/ +} \ No newline at end of file diff --git a/vtm-web/src/org/oscim/gdx/emu/org/oscim/utils/TessJNI.java b/vtm-web/src/org/oscim/gdx/emu/org/oscim/utils/TessJNI.java new file mode 100644 index 00000000..c6a45d7a --- /dev/null +++ b/vtm-web/src/org/oscim/gdx/emu/org/oscim/utils/TessJNI.java @@ -0,0 +1,73 @@ +package org.oscim.utils; + +public class TessJNI { + + public TessJNI() { + + } + + public TessJNI(int size) { + throw new RuntimeException("unimplemented"); + } + + public void dispose() { + throw new RuntimeException("unimplemented"); + } + + public void addContour2D(float[] points) { + throw new RuntimeException("unimplemented"); + } + + public void addContour2D(float[] points, int offset, int length) { + throw new RuntimeException("unimplemented"); + } + + public void addContour2D(int[] index, float[] contour) { + throw new RuntimeException("unimplemented"); + } + + public void addContour2D(int[] index, float[] contour, int idxStart, int idxEnd) { + throw new RuntimeException("unimplemented"); + } + + public boolean tesselate() { + throw new RuntimeException("unimplemented"); + } + + public boolean tesselate(int windingRule, int elementType) { + throw new RuntimeException("unimplemented"); + } + + public int getVertexCount() { + throw new RuntimeException("unimplemented"); + } + + public int getElementCount() { + throw new RuntimeException("unimplemented"); + } + + public void getVertices(float[] out, int offset, int length) { + throw new RuntimeException("unimplemented"); + } + + public void getVertices(short[] out, int offset, int length, float scale) { + throw new RuntimeException("unimplemented"); + } + + public void getElements(int[] out, int offset, int length) { + throw new RuntimeException("unimplemented"); + } + + public void getElements(short[] out, int offset, int length) { + throw new RuntimeException("unimplemented"); + } + + public void getVertexIndices(int[] out, int offset, int length) { + throw new RuntimeException("unimplemented"); + } + + public void getElementsWithInputVertexIds(short[] dst, int dstOffset, int offset, int length) { + throw new RuntimeException("unimplemented"); + } + +} diff --git a/vtm-web/src/org/oscim/gdx/emu/org/oscim/utils/Tessellator.java b/vtm-web/src/org/oscim/gdx/emu/org/oscim/utils/Tessellator.java index 5a2987e3..4c4edcb1 100644 --- a/vtm-web/src/org/oscim/gdx/emu/org/oscim/utils/Tessellator.java +++ b/vtm-web/src/org/oscim/gdx/emu/org/oscim/utils/Tessellator.java @@ -107,7 +107,7 @@ public class Tessellator { return numIndices; } - public static int tessellate(float[] points, int ppos, int plen, short[] index, + public static int tessellate(float[] points, int ppos, int plen, int[] index, int ipos, int rings, int vertexOffset, VertexData outTris) { Int32Array io; diff --git a/vtm/src/org/oscim/renderer/elements/ExtrusionLayer.java b/vtm/src/org/oscim/renderer/elements/ExtrusionLayer.java index cd356392..316f724b 100644 --- a/vtm/src/org/oscim/renderer/elements/ExtrusionLayer.java +++ b/vtm/src/org/oscim/renderer/elements/ExtrusionLayer.java @@ -418,19 +418,20 @@ public class ExtrusionLayer extends RenderElement { int[] index = geom.index; float[] points = geom.points; - int len = 0; - int rings = 0; + int numPoints = 0; + int numRings = 0; /* get sum of points in polygon */ for (int i = ipos, n = index.length; i < n && index[i] > 0; i++) { - len += index[i]; - rings++; + numPoints += index[i]; + numRings++; } - sumIndices += Tessellator.tessellate(points, ppos, len, - index, ipos, rings, + sumIndices += Tessellator.tessellate(points, ppos, numPoints, + index, ipos, numRings, startVertex + 1, mIndices[IND_ROOF]); + } private boolean extrudeOutline(float[] points, int pos, int len, diff --git a/vtm/src/org/oscim/renderer/elements/MeshLayer.java b/vtm/src/org/oscim/renderer/elements/MeshLayer.java index 547e813b..c8319077 100644 --- a/vtm/src/org/oscim/renderer/elements/MeshLayer.java +++ b/vtm/src/org/oscim/renderer/elements/MeshLayer.java @@ -21,7 +21,6 @@ import static org.oscim.backend.GL20.GL_LINES; import static org.oscim.backend.GL20.GL_SHORT; import static org.oscim.backend.GL20.GL_TRIANGLES; import static org.oscim.backend.GL20.GL_UNSIGNED_SHORT; -import static org.oscim.renderer.MapRenderer.COORD_SCALE; import org.oscim.backend.canvas.Color; import org.oscim.core.GeometryBuffer; @@ -30,9 +29,11 @@ import org.oscim.renderer.GLShader; import org.oscim.renderer.GLState; import org.oscim.renderer.GLUtils; import org.oscim.renderer.GLViewport; +import org.oscim.renderer.MapRenderer; +import org.oscim.renderer.elements.VertexData.Chunk; import org.oscim.theme.styles.AreaStyle; import org.oscim.utils.ColorUtil; -import org.oscim.utils.Tessellator; +import org.oscim.utils.TessJNI; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -43,24 +44,66 @@ public class MeshLayer extends IndexedRenderElement { public AreaStyle area; public float heightOffset; + TessJNI tess = new TessJNI(8); + public MeshLayer(int level) { super(RenderElement.MESH); this.level = level; + } + int pcount; + public void addMesh(GeometryBuffer geom) { - if (geom.index[0] < 6) + pcount += geom.pointPos; + + tess.addContour2D(geom.index, geom.points); + } + + protected void prepare() { + if (!tess.tesselate()) { + log.error("error in tessellation"); return; + } - numIndices += Tessellator.tessellate(geom, COORD_SCALE, - vertexItems, - indiceItems, - numVertices); + int nelems = tess.getElementCount() * 3; - numVertices = vertexItems.countSize() / 2; + for (int offset = 0; offset < nelems;) { + int size = nelems - offset; + if (size > VertexData.SIZE) + size = VertexData.SIZE; - if (numIndices <= 0) - log.debug("empty " + geom.index); + Chunk chunk = indiceItems.obtainChunk(); + + tess.getElements(chunk.vertices, offset, size); + offset += size; + + indiceItems.releaseChunk(size); + } + + int nverts = tess.getVertexCount() * 2; + + for (int offset = 0; offset < nverts;) { + int size = nverts - offset; + if (size > VertexData.SIZE) + size = VertexData.SIZE; + + Chunk chunk = vertexItems.obtainChunk(); + + tess.getVertices(chunk.vertices, offset, size, + MapRenderer.COORD_SCALE); + + offset += size; + + vertexItems.releaseChunk(size); + } + + this.numIndices = nelems; + this.numVertices = nverts >> 1; + + //log.debug("{} - {}", nverts, pcount); + + tess.dispose(); } public static class Renderer { @@ -124,7 +167,9 @@ public class MeshLayer extends IndexedRenderElement { GL_UNSIGNED_SHORT, 0); if (dbgRender) { - int c = ColorUtil.shiftHue(ml.area.color, 0.5); + int c = (ml.area == null) ? Color.BLUE : ml.area.color; + + c = ColorUtil.shiftHue(c, 0.5); GLUtils.setColor(s.uColor, c, 0.8f); GL.glDrawElements(GL_LINES, ml.numIndices, GL_UNSIGNED_SHORT, 0); diff --git a/vtm/src/org/oscim/renderer/elements/VertexData.java b/vtm/src/org/oscim/renderer/elements/VertexData.java index 39314266..a9c8aef7 100644 --- a/vtm/src/org/oscim/renderer/elements/VertexData.java +++ b/vtm/src/org/oscim/renderer/elements/VertexData.java @@ -199,6 +199,7 @@ public class VertexData extends Inlist.List { public Chunk obtainChunk() { if (used == SIZE) getNext(); + cur.used = used; return cur; @@ -208,6 +209,11 @@ public class VertexData extends Inlist.List { used = cur.used; } + public void releaseChunk(int size) { + cur.used = size; + used = size; + } + /* Do not use! */ public void seek(int offset) { used += offset; diff --git a/jni/src/org/oscim/utils/tess/Tesselator.java b/vtm/src/org/oscim/utils/TessJNI.java similarity index 56% rename from jni/src/org/oscim/utils/tess/Tesselator.java rename to vtm/src/org/oscim/utils/TessJNI.java index 9a431bd6..5d521775 100644 --- a/jni/src/org/oscim/utils/tess/Tesselator.java +++ b/vtm/src/org/oscim/utils/TessJNI.java @@ -1,16 +1,14 @@ -package org.oscim.utils.tess; - -import static java.lang.System.out; - -import java.io.File; -import java.util.Arrays; - -public class Tesselator { +package org.oscim.utils; +public class TessJNI { private long inst; - public Tesselator() { - inst = newTess(); + public TessJNI() { + inst = newTess(0); + } + + public TessJNI(int bucketSize) { + inst = newTess(bucketSize); } @Override @@ -25,6 +23,10 @@ public class Tesselator { } } + protected long instance() { + return inst; + } + /** * See OpenGL Red Book for description of the winding rules * http://www.glprogramming.com/red/chapter11.html @@ -54,7 +56,6 @@ public class Tesselator { throw new IllegalArgumentException("Invalid input: length:" + length + ", offset:" + offset + ", points.length:" + points.length); - addContour(inst, 2, points, 8, offset, length); } @@ -62,6 +63,17 @@ public class Tesselator { addMultiContour2D(inst, index, contour, 0, index.length); } + public void addContour2D(int[] index, float[] contour, int idxStart, int idxEnd) { + addMultiContour2D(inst, index, contour, idxStart, idxEnd); + } + + public boolean tesselate() { + return tessContour2D(inst, + TessJNI.WindingRule.POSITIVE, + TessJNI.ElementType.POLYGONS, + 3, 2) == 1; + } + public boolean tesselate(int windingRule, int elementType) { return tessContour2D(inst, windingRule, elementType, 3, 2) == 1; } @@ -94,25 +106,52 @@ public class Tesselator { getVertexIndices(inst, out, offset, length); } - public void getElementsWithInputVertexIds(short[] out, int dstOffset, int offset, int length) { - getElementsWithInputVertexIds(inst, out, dstOffset, offset, length); + public void getElementsWithInputVertexIds(short[] dst, int dstOffset, int offset, int length) { + getElementsWithInputVertexIds(inst, dst, dstOffset, offset, length); } // @formatter:off - /*JNI #include #include + #include + void* heapAlloc( void* userData, unsigned int size ){ + TESS_NOTUSED( userData ); + return malloc( size ); + } + void* heapRealloc( void *userData, void* ptr, unsigned int size ){ + TESS_NOTUSED( userData ); + return realloc( ptr, size ); + } + void heapFree( void* userData, void* ptr ){ + TESS_NOTUSED( userData ); + free( ptr ); + } */ - private static native long newTess(); /* { - return (long)tessNewTess(0); + static native long newTess(int size); /* { + if (size <= 0) + return (long)tessNewTess(0); + if (size > 10) + size = 10; + TESSalloc ma; + memset(&ma, 0, sizeof(ma)); + ma.memalloc = heapAlloc; + ma.memfree = heapFree; + ma.memrealloc = heapRealloc; + //ma.userData = (void*)&allocated; + ma.meshEdgeBucketSize = 2 << size; // 512 + ma.meshVertexBucketSize = 2 << size; // 512 + ma.meshFaceBucketSize = 1 << size; // 256 + ma.dictNodeBucketSize = 2 << size; // 512 + ma.regionBucketSize = 1 << size; // 256 + ma.extraVertices = 8; + //ma.extraVertices = 256; + return (long)tessNewTess(&ma); } */ - - private static native void freeTess(long inst); /* { + static native void freeTess(long inst); /* { tessDeleteTess((TESStesselator*) inst); } */ - - /** + /** * Adds a contour to be tesselated. * The type of the vertex coordinates is assumed to be TESSreal. * @@ -120,220 +159,107 @@ public class Tesselator { * @param size - number of coordinates per vertex. Must be 2 or 3. * @param pointer - pointer to the first coordinate of the first vertex in the array. * @param stride - defines offset in bytes between consecutive vertices. - * @param count - number of vertices in contour. + * @param count - number of vertices in contour. */ - private static native void addContour(long inst, int size, float[] contour, int stride, int offset, int count);/* { + static native void addContour(long inst, int size, float[] contour, int stride, int offset, int count);/* { tessAddContour((TESStesselator*) inst, size, contour + (offset * stride), stride, count); } */ - - private static native void addMultiContour2D(long inst, int[] index, float[] contour, int idxStart, int idxCount);/* { + static native void addMultiContour2D(long inst, int[] index, float[] contour, int idxStart, int idxCount);/* { TESStesselator* tess = (TESStesselator*) inst; int offset = 0; - + // start at 0 to get the correct offset in contour.. for (int i = 0; i < idxStart + idxCount; i++){ int len = index[i]; - if ((len % 2 != 0) || (len < 0)) break; - if (len < 6 || i < idxStart) { offset += len; continue; } - tessAddContour(tess, 2, contour + offset, 8, len >> 1); - offset += len; } } */ - /** * Tesselate contours. - * + * * @param tess - pointer to tesselator object. * @param windingRule - winding rules used for tesselation, must be one of TessWindingRule. * @param elementType - defines the tesselation result element type, must be one of TessElementType. * @param polySize - defines maximum vertices per polygons if output is polygons. * @param vertexSize - defines the number of coordinates in tesselation result vertex, must be 2 or 3. * @param normal - defines the normal of the input contours, of null the normal is calculated automatically. - * @return 1 if succeed, 0 if failed. + * @return 1 if succeed, 0 if failed. */ - private static native int tessContour2D(long inst, int windingRule, int elementType, int polySize, int vertexSize);/*{ + static native int tessContour2D(long inst, int windingRule, int elementType, int polySize, int vertexSize);/*{ return tessTesselate((TESStesselator*) inst, windingRule, elementType, polySize, vertexSize, 0); } */ - - private static native int getVertexCount(long inst); /*{ + static native int getVertexCount(long inst); /*{ return tessGetVertexCount((TESStesselator*) inst); }*/ - /** * Returns pointer to first coordinate of first vertex. */ - private static native boolean getVertices(long inst, float[] out, int offset, int length);/*{ - const TESSIOreal* vertices = tessGetVertices((TESStesselator*) inst); - - //const TESSreal* vertices = tessGetVertices((TESStesselator*) inst); - + static native boolean getVertices(long inst, float[] out, int offset, int length);/*{ + const TESSreal* vertices = tessGetVertices((TESStesselator*) inst); if (!vertices) return 0; - - memcpy(out, vertices + offset, length * sizeof(TESSIOreal)); - - //memcpy(out, vertices + offset, length * sizeof(TESSreal)); - + memcpy(out, vertices + offset, length * sizeof(TESSreal)); return 1; }*/ - /** * Returns pointer to first coordinate of first vertex. */ - private static native void getVerticesS(long inst, short[] out, int offset, int length, float scale);/*{ - const TESSIOreal* vertices = tessGetVertices((TESStesselator*) inst); - - //const TESSreal* vertices = tessGetVertices((TESStesselator*) inst); - + static native void getVerticesS(long inst, short[] out, int offset, int length, float scale);/*{ + const TESSreal* vertices = tessGetVertices((TESStesselator*) inst); for(int i = 0; i < length; i++) out[i] = (short)(vertices[offset++] * scale + 0.5f); }*/ - /** * Returns pointer to first vertex index. - * + * * Vertex indices can be used to map the generated vertices to the original vertices. * Every point added using tessAddContour() will get a new index starting at 0. * New vertices generated at the intersections of segments are assigned value TESS_UNDEF. */ - private static native boolean getVertexIndices(long inst, int[] out, int offset, int length);/* { + static native boolean getVertexIndices(long inst, int[] out, int offset, int length);/* { const TESSindex* indices = tessGetVertexIndices((TESStesselator*) inst); if (!indices) return 0; - memcpy(out, indices + offset, length * sizeof(TESSindex)); return 1; } */ - /** * Returns number of elements in the the tesselated output. */ - private static native int getElementCount(long inst);/*{ + static native int getElementCount(long inst);/*{ return tessGetElementCount((TESStesselator*) inst); }*/ - /** - * Returns pointer to the first element. + * Returns pointer to the first element. */ - private static native boolean getElements(long inst, int[] out, int offset, int length);/*{ + static native boolean getElements(long inst, int[] out, int offset, int length);/*{ const TESSindex* elements = tessGetElements((TESStesselator*) inst); if (!elements) return 0; - memcpy(out, elements + offset, length * sizeof(TESSindex)); return 1; }*/ - - /** - * Returns pointer to the first element. + * Returns pointer to the first element. */ - private static native void getElementsS(long inst, short[] out, int offset, int length);/*{ + static native void getElementsS(long inst, short[] out, int offset, int length);/*{ const TESSindex* elements = tessGetElements((TESStesselator*) inst); for(int i = 0; i < length; i++) out[i] = (short)elements[offset++]; }*/ - /** - * Returns list of triangles indices (or to the first element of convex polygons). + * Returns list of triangles indices (or to the first element of convex polygons). */ - private static native void getElementsWithInputVertexIds(long inst, short[] out, int dstOffset, int offset, int length);/*{ + static native void getElementsWithInputVertexIds(long inst, short[] out, int dstOffset, int offset, int length);/*{ const TESSindex* elements = tessGetElements((TESStesselator*) inst); const TESSindex* indices = tessGetVertexIndices((TESStesselator*) inst); - for(int i = 0; i < length; i++) - out[dstOffset++] = (short)indices[elements[offset++]]; + out[dstOffset++] = (short)(indices[elements[offset++]]); }*/ - - //@formatter:on - public static void main(String[] args) throws Exception { - System.load(new File("libs/linux64/libvtm-jni64.so").getAbsolutePath()); - Tesselator tess = new Tesselator(); - - float[] c1 = new float[] { - 0, 0, - 4, 0, - 4, 4, - 0, 4, - }; - - float[] c2 = new float[] { - 1, 1, - 1, 2, - 2, 2, - 2, 1 - }; - - float[] c3 = new float[] { - 0, 0, - 4, 0, - 4, 4, - 0, 4, - - 1, 1, - 1, 2, - 2, 2, - 2, 1 - }; - - int polySize = 3; - - addContour(tess.inst, 2, c1, 8, 0, c1.length / 2); - - //addContour(tess.inst, 2, c2, 8, c2.length / 2); - - //addContour(tess.inst, 2, c3, 8, c3.length / 2); - - //int[] index = { 8, 8, -1 }; - - //addMultiContour2D(tess.inst, index, c3, 0, 4); - out.println("yup"); - - tessContour2D(tess.inst, - WindingRule.POSITIVE, - ElementType.POLYGONS, - polySize, 2); - - out.println("y0!"); - - int nElem = getElementCount(tess.inst); - int nVert = getVertexCount(tess.inst); - - out.println(nVert + "/" + nElem); - - short[] elems = new short[nElem * polySize]; - getElementsS(tess.inst, elems, 0, nElem * polySize); - - out.println(Arrays.toString(elems)); - - int half = nElem * polySize / 2; - elems = new short[half]; - getElementsS(tess.inst, elems, half, half); - - out.println(Arrays.toString(elems)); - - float[] verts = new float[nVert * 2]; - getVertices(tess.inst, verts, 0, nVert * 2); - - out.println(Arrays.toString(verts)); - - short[] ids = new short[nElem * polySize]; - getElementsWithInputVertexIds(tess.inst, ids, 0, 0, ids.length); - - out.println(Arrays.toString(ids)); - - for (int i = 0; i < nElem * polySize; i++) { - out.println(c3[ids[i] * 2] + ", " + c3[ids[i] * 2 + 1]); - } - out.println(); - - freeTess(tess.inst); - } -} +} \ No newline at end of file diff --git a/vtm/src/org/oscim/utils/Tessellator.java b/vtm/src/org/oscim/utils/Tessellator.java index 2b23de15..84ece4b6 100644 --- a/vtm/src/org/oscim/utils/Tessellator.java +++ b/vtm/src/org/oscim/utils/Tessellator.java @@ -18,55 +18,78 @@ package org.oscim.utils; import java.util.Arrays; -import org.oscim.core.GeometryBuffer; import org.oscim.renderer.elements.VertexData; +import org.oscim.utils.math.MathUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class Tessellator { static final Logger log = LoggerFactory.getLogger(Tessellator.class); - private static final int RESULT_VERTICES = 0; - private static final int RESULT_TRIANGLES = 1; - /** * Special version for ExtrusionLayer to match indices with vertex * positions. */ - public static int tessellate(float[] points, int ppos, int plen, int[] index, - int ipos, int rings, int vertexOffset, VertexData outTris) { + public static int tessellate(float[] points, int ppos, int numPoints, int[] index, + int ipos, int numRings, int vertexOffset, VertexData outTris) { - int[] result = new int[2]; + int buckets = FastMath.log2(MathUtils.nextPowerOfTwo(numPoints)); + buckets -= 2; + //log.debug("tess use {}", buckets); - int numPoints = 0; - for (int i = 0; i < rings; i++) - numPoints += index[ipos + i]; + TessJNI tess = new TessJNI(buckets); - long ctx = Tessellator.tessellate(points, ppos, index, ipos, rings, result); - if ((numPoints / 2) < result[RESULT_VERTICES]) { - log.debug("skip poly: " + Arrays.toString(result) + " " + numPoints); - Tessellator.tessFinish(ctx); + tess.addContour2D(index, points, ipos, numRings); + //log.debug("tess ipos:{} rings:{}", ipos, numRings); + + if (!tess.tesselate()) + return 0; + + int nverts = tess.getVertexCount() * 2; + int nelems = tess.getElementCount() * 3; + + //log.debug("tess elems:{} verts:{} points:{}", nelems, nverts, numPoints); + + if (numPoints != nverts) { + log.debug("tess ----- skip poly: " + nverts + " " + numPoints); + tess.dispose(); return 0; } - int cnt; int sumIndices = 0; VertexData.Chunk vd = outTris.obtainChunk(); - while ((cnt = Tessellator.tessGetIndicesWO(ctx, vd.vertices, vd.used)) > 0) { + for (int offset = 0; offset < nelems;) { + int size = nelems - offset; + + if (VertexData.SIZE == vd.used) { + vd = outTris.obtainChunk(); + } + + if (size > VertexData.SIZE - vd.used) + size = VertexData.SIZE - vd.used; + + tess.getElementsWithInputVertexIds(vd.vertices, vd.used, offset, size); + int start = vd.used; - int end = start + cnt; - short[] v = vd.vertices; - - for (int i = start; i < end; i++) - v[i] *= 2; + int end = start + size; + short[] indices = vd.vertices; + for (int i = start; i < end; i++) { + if (indices[i] < 0) { + log.debug(">>>> eeek {} {} {}", + start, end, + Arrays.toString(Arrays.copyOfRange(indices, start, end))); + break; + } + indices[i] *= 2; + } /* when a ring has an odd number of points one (or rather two) * additional vertices will be added. so the following rings * needs extra offset */ int shift = 0; - for (int i = 0, m = rings - 1; i < m; i++) { + for (int i = 0, m = numRings - 1; i < m; i++) { shift += (index[ipos + i]); /* even number of points? */ @@ -74,203 +97,273 @@ public class Tessellator { continue; for (int j = start; j < end; j++) - if (v[j] >= shift) - v[j] += 2; + if (indices[j] >= shift) + indices[j] += 2; shift += 2; } /* shift by vertexOffset */ for (int i = start; i < end; i++) - v[i] += vertexOffset; + indices[i] += vertexOffset; - sumIndices += cnt; + sumIndices += size; - vd.used += cnt; + vd.used += size; outTris.releaseChunk(); - if (vd.used == VertexData.SIZE) { - /* gets next item since this one is full */ - vd = outTris.obtainChunk(); - continue; - } - /* no more indices to get. */ - break; + offset += size; } - Tessellator.tessFinish(ctx); + tess.dispose(); return sumIndices; } - - /** - * Untested! - */ - public static int tessellate(GeometryBuffer geom, GeometryBuffer out) { - - int[] result = new int[2]; - - 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); - - boolean verticesAdded = false; - if (numPoints < result[RESULT_VERTICES] * 2) { - //log.debug("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; - } - - /* FIXME This modifies geom ?! */ - public static int tessellate(GeometryBuffer geom, float scale, - VertexData outPoints, VertexData outTris, int vertexOffset) { - - int numIndices = 0; - int indexPos = 0; - int pointPos = 0; - int indexEnd = geom.index.length; - - int[] result = new int[2]; - - float s = scale; - scale = 1; - - 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]; - } - - /* FIXME !!! */ - for (int i = pointPos; i < pointPos + numPoints; i += 2) { - geom.points[i + 0] = (int) (geom.points[i + 0] * s); - geom.points[i + 1] = (int) (geom.points[i + 1] * s); - } - - long ctx = Tessellator.tessellate(geom.points, pointPos, - geom.index, indexPos, - numRings, result); - - if (result[RESULT_VERTICES] == 0 || result[RESULT_TRIANGLES] == 0) { - log.debug("ppos " + pointPos + " ipos:" + indexPos + - " rings:" + numRings + " " + Arrays.toString(geom.index)); - continue; - } - - pointPos += numPoints; - - while (true) { - VertexData.Chunk vd = outTris.obtainChunk(); - - int cnt = Tessellator.tessGetIndicesWO(ctx, vd.vertices, vd.used); - if (cnt <= 0) - break; - - /* shift by vertexOffset */ - for (int pos = vd.used, end = pos + cnt; pos < end; pos++) - vd.vertices[pos] += vertexOffset; - - numIndices += cnt; - - vd.used += cnt; - outTris.releaseChunk(); - - if (vd.used < VertexData.SIZE) - break; - } - - while (true) { - VertexData.Chunk vd = outPoints.obtainChunk(); - - int cnt = Tessellator.tessGetVerticesWO(ctx, vd.vertices, vd.used, scale); - if (cnt <= 0) - break; - - vertexOffset += cnt >> 1; - - vd.used += cnt; - outPoints.releaseChunk(); - - if (vd.used < VertexData.SIZE) - break; - } - - 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 0; - } - - return numIndices; - } - - /** - * @param points an array of x,y coordinates - * @param pos position in points array - * @param index geom indices - * @param ipos position in index array - * @param numRings number of rings in polygon == outer(1) + inner rings - * @param result contains number of vertices and number of triangles - * @return context - must be freed with tessFinish() - */ - protected static native long tessellate(float[] points, int pos, - int[] index, int ipos, int numRings, int[] result); - - protected static native void tessFinish(long ctx); - - protected static native int tessGetVertices(long ctx, short[] coordinates, float scale); - - 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, int[] indices); - - protected static native int tessGetIndicesWO(long ctx, short[] indices, int offset); + // private static final int RESULT_VERTICES = 0; + // private static final int RESULT_TRIANGLES = 1; + // + // /** + // * Special version for ExtrusionLayer to match indices with vertex + // * positions. + // */ + // public static int tessellate(float[] points, int ppos, int plen, int[] index, + // int ipos, int rings, int vertexOffset, VertexData outTris) { + // + // int[] result = new int[2]; + // + // int numPoints = 0; + // for (int i = 0; i < rings; i++) + // numPoints += index[ipos + i]; + // + // long ctx = Tessellator.tessellate(points, ppos, index, ipos, rings, result); + // if ((numPoints / 2) < result[RESULT_VERTICES]) { + // log.debug("skip poly: " + Arrays.toString(result) + " " + numPoints); + // Tessellator.tessFinish(ctx); + // return 0; + // } + // + // int cnt; + // int sumIndices = 0; + // + // VertexData.Chunk vd = outTris.obtainChunk(); + // + // while ((cnt = Tessellator.tessGetIndicesWO(ctx, vd.vertices, vd.used)) > 0) { + // int start = vd.used; + // int end = start + cnt; + // short[] v = vd.vertices; + // + // 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 + // * needs extra offset */ + // int shift = 0; + // for (int i = 0, m = rings - 1; i < m; i++) { + // shift += (index[ipos + i]); + // + // /* even number of points? */ + // if (((index[ipos + i] >> 1) & 1) == 0) + // continue; + // + // for (int j = start; j < end; j++) + // if (v[j] >= shift) + // v[j] += 2; + // + // shift += 2; + // } + // + // /* shift by vertexOffset */ + // for (int i = start; i < end; i++) + // v[i] += vertexOffset; + // + // sumIndices += cnt; + // + // vd.used += cnt; + // outTris.releaseChunk(); + // + // if (vd.used == VertexData.SIZE) { + // /* gets next item since this one is full */ + // vd = outTris.obtainChunk(); + // continue; + // } + // /* no more indices to get. */ + // break; + // } + // + // Tessellator.tessFinish(ctx); + // + // return sumIndices; + // } + // + // /** + // * Untested! + // */ + // public static int tessellate(GeometryBuffer geom, GeometryBuffer out) { + // + // int[] result = new int[2]; + // + // 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); + // + // boolean verticesAdded = false; + // if (numPoints < result[RESULT_VERTICES] * 2) { + // //log.debug("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; + // } + // + // /* FIXME This modifies geom ?! */ + // public static int tessellate(GeometryBuffer geom, float scale, + // VertexData outPoints, VertexData outTris, int vertexOffset) { + // + // int numIndices = 0; + // int indexPos = 0; + // int pointPos = 0; + // int indexEnd = geom.index.length; + // + // int[] result = new int[2]; + // + // float s = scale; + // scale = 1; + // + // 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]; + // } + // + // /* FIXME !!! */ + // for (int i = pointPos; i < pointPos + numPoints; i += 2) { + // geom.points[i + 0] = (int) (geom.points[i + 0] * s); + // geom.points[i + 1] = (int) (geom.points[i + 1] * s); + // } + // + // long ctx = Tessellator.tessellate(geom.points, pointPos, + // geom.index, indexPos, + // numRings, result); + // + // if (result[RESULT_VERTICES] == 0 || result[RESULT_TRIANGLES] == 0) { + // log.debug("ppos " + pointPos + " ipos:" + indexPos + + // " rings:" + numRings + " " + Arrays.toString(geom.index)); + // continue; + // } + // + // pointPos += numPoints; + // + // while (true) { + // VertexData.Chunk vd = outTris.obtainChunk(); + // + // int cnt = Tessellator.tessGetIndicesWO(ctx, vd.vertices, vd.used); + // if (cnt <= 0) + // break; + // + // /* shift by vertexOffset */ + // for (int pos = vd.used, end = pos + cnt; pos < end; pos++) + // vd.vertices[pos] += vertexOffset; + // + // numIndices += cnt; + // + // vd.used += cnt; + // outTris.releaseChunk(); + // + // if (vd.used < VertexData.SIZE) + // break; + // } + // + // while (true) { + // VertexData.Chunk vd = outPoints.obtainChunk(); + // + // int cnt = Tessellator.tessGetVerticesWO(ctx, vd.vertices, vd.used, scale); + // if (cnt <= 0) + // break; + // + // vertexOffset += cnt >> 1; + // + // vd.used += cnt; + // outPoints.releaseChunk(); + // + // if (vd.used < VertexData.SIZE) + // break; + // } + // + // 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 0; + // } + // + // return numIndices; + // } + // + // /** + // * @param points an array of x,y coordinates + // * @param pos position in points array + // * @param index geom indices + // * @param ipos position in index array + // * @param numRings number of rings in polygon == outer(1) + inner rings + // * @param result contains number of vertices and number of triangles + // * @return context - must be freed with tessFinish() + // */ + // protected static native long tessellate(float[] points, int pos, + // int[] index, int ipos, int numRings, int[] result); + // + // protected static native void tessFinish(long ctx); + // + // protected static native int tessGetVertices(long ctx, short[] coordinates, float scale); + // + // 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, int[] indices); + // + // protected static native int tessGetIndicesWO(long ctx, short[] indices, int offset); }