use new Tessellator for Mesh- and ExtrusionLayer

This commit is contained in:
Hannes Janetzek 2014-09-19 22:12:31 +02:00
parent 7db70f239f
commit 20afbfe230
13 changed files with 948 additions and 762 deletions

View File

@ -1,2 +1,3 @@
cp libs/armeabi/libvtm-jni.so ../vtm-ext-libs/vtm-android/armeabi 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/armeabi-v7a/libvtm-jni.so ../vtm-ext-libs/vtm-android/armeabi-v7a
cp libs/vtm-jni-natives.jar ../vtm-ext-libs/gdx/

View File

@ -9,14 +9,14 @@ LOCAL_CPPFLAGS := $(LOCAL_C_INCLUDES:%=-I%) -O2 -Wall -D__ANDROID__ -Wall -std=c
LOCAL_LDLIBS := -lm -llog LOCAL_LDLIBS := -lm -llog
LOCAL_ARM_MODE := arm 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/priorityq.c\
libtess2/Source/bucketalloc.c\ libtess2/Source/bucketalloc.c\
libtess2/Source/geom.c\ libtess2/Source/geom.c\
libtess2/Source/tess.c\ libtess2/Source/tess.c\
libtess2/Source/dict.c\ libtess2/Source/dict.c\
libtess2/Source/mesh.c\ libtess2/Source/mesh.c\
org.oscim.utils.tess.Tesselator.cpp\
gl/utils.c gl/utils.c
include $(BUILD_SHARED_LIBRARY) include $(BUILD_SHARED_LIBRARY)

View File

@ -0,0 +1,155 @@
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* 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

View File

@ -1,224 +0,0 @@
#include <org.oscim.utils.tess.Tesselator.h>
//@line:103
#include <tesselator.h>
#include <string.h>
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);
}

View File

@ -1,155 +0,0 @@
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* 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

View File

@ -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 <tesselator.h>
#include <string.h>
#include <stdlib.h>
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++]]);
}*/
}

View File

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

View File

@ -107,7 +107,7 @@ public class Tessellator {
return numIndices; 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) { int ipos, int rings, int vertexOffset, VertexData outTris) {
Int32Array io; Int32Array io;

View File

@ -418,19 +418,20 @@ public class ExtrusionLayer extends RenderElement {
int[] index = geom.index; int[] index = geom.index;
float[] points = geom.points; float[] points = geom.points;
int len = 0; int numPoints = 0;
int rings = 0; int numRings = 0;
/* get sum of points in polygon */ /* get sum of points in polygon */
for (int i = ipos, n = index.length; i < n && index[i] > 0; i++) { for (int i = ipos, n = index.length; i < n && index[i] > 0; i++) {
len += index[i]; numPoints += index[i];
rings++; numRings++;
} }
sumIndices += Tessellator.tessellate(points, ppos, len, sumIndices += Tessellator.tessellate(points, ppos, numPoints,
index, ipos, rings, index, ipos, numRings,
startVertex + 1, startVertex + 1,
mIndices[IND_ROOF]); mIndices[IND_ROOF]);
} }
private boolean extrudeOutline(float[] points, int pos, int len, private boolean extrudeOutline(float[] points, int pos, int len,

View File

@ -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_SHORT;
import static org.oscim.backend.GL20.GL_TRIANGLES; import static org.oscim.backend.GL20.GL_TRIANGLES;
import static org.oscim.backend.GL20.GL_UNSIGNED_SHORT; 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.backend.canvas.Color;
import org.oscim.core.GeometryBuffer; import org.oscim.core.GeometryBuffer;
@ -30,9 +29,11 @@ import org.oscim.renderer.GLShader;
import org.oscim.renderer.GLState; import org.oscim.renderer.GLState;
import org.oscim.renderer.GLUtils; import org.oscim.renderer.GLUtils;
import org.oscim.renderer.GLViewport; 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.theme.styles.AreaStyle;
import org.oscim.utils.ColorUtil; import org.oscim.utils.ColorUtil;
import org.oscim.utils.Tessellator; import org.oscim.utils.TessJNI;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -43,24 +44,66 @@ public class MeshLayer extends IndexedRenderElement {
public AreaStyle area; public AreaStyle area;
public float heightOffset; public float heightOffset;
TessJNI tess = new TessJNI(8);
public MeshLayer(int level) { public MeshLayer(int level) {
super(RenderElement.MESH); super(RenderElement.MESH);
this.level = level; this.level = level;
} }
int pcount;
public void addMesh(GeometryBuffer geom) { 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; return;
}
numIndices += Tessellator.tessellate(geom, COORD_SCALE, int nelems = tess.getElementCount() * 3;
vertexItems,
indiceItems,
numVertices);
numVertices = vertexItems.countSize() / 2; for (int offset = 0; offset < nelems;) {
int size = nelems - offset;
if (size > VertexData.SIZE)
size = VertexData.SIZE;
if (numIndices <= 0) Chunk chunk = indiceItems.obtainChunk();
log.debug("empty " + geom.index);
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 { public static class Renderer {
@ -124,7 +167,9 @@ public class MeshLayer extends IndexedRenderElement {
GL_UNSIGNED_SHORT, 0); GL_UNSIGNED_SHORT, 0);
if (dbgRender) { 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); GLUtils.setColor(s.uColor, c, 0.8f);
GL.glDrawElements(GL_LINES, ml.numIndices, GL.glDrawElements(GL_LINES, ml.numIndices,
GL_UNSIGNED_SHORT, 0); GL_UNSIGNED_SHORT, 0);

View File

@ -199,6 +199,7 @@ public class VertexData extends Inlist.List<Chunk> {
public Chunk obtainChunk() { public Chunk obtainChunk() {
if (used == SIZE) if (used == SIZE)
getNext(); getNext();
cur.used = used; cur.used = used;
return cur; return cur;
@ -208,6 +209,11 @@ public class VertexData extends Inlist.List<Chunk> {
used = cur.used; used = cur.used;
} }
public void releaseChunk(int size) {
cur.used = size;
used = size;
}
/* Do not use! */ /* Do not use! */
public void seek(int offset) { public void seek(int offset) {
used += offset; used += offset;

View File

@ -1,16 +1,14 @@
package org.oscim.utils.tess; package org.oscim.utils;
import static java.lang.System.out;
import java.io.File;
import java.util.Arrays;
public class Tesselator {
public class TessJNI {
private long inst; private long inst;
public Tesselator() { public TessJNI() {
inst = newTess(); inst = newTess(0);
}
public TessJNI(int bucketSize) {
inst = newTess(bucketSize);
} }
@Override @Override
@ -25,6 +23,10 @@ public class Tesselator {
} }
} }
protected long instance() {
return inst;
}
/** /**
* See OpenGL Red Book for description of the winding rules * See OpenGL Red Book for description of the winding rules
* http://www.glprogramming.com/red/chapter11.html * http://www.glprogramming.com/red/chapter11.html
@ -54,7 +56,6 @@ public class Tesselator {
throw new IllegalArgumentException("Invalid input: length:" + length throw new IllegalArgumentException("Invalid input: length:" + length
+ ", offset:" + offset + ", offset:" + offset
+ ", points.length:" + points.length); + ", points.length:" + points.length);
addContour(inst, 2, points, 8, offset, length); addContour(inst, 2, points, 8, offset, length);
} }
@ -62,6 +63,17 @@ public class Tesselator {
addMultiContour2D(inst, index, contour, 0, index.length); 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) { public boolean tesselate(int windingRule, int elementType) {
return tessContour2D(inst, windingRule, elementType, 3, 2) == 1; return tessContour2D(inst, windingRule, elementType, 3, 2) == 1;
} }
@ -94,25 +106,52 @@ public class Tesselator {
getVertexIndices(inst, out, offset, length); getVertexIndices(inst, out, offset, length);
} }
public void getElementsWithInputVertexIds(short[] out, int dstOffset, int offset, int length) { public void getElementsWithInputVertexIds(short[] dst, int dstOffset, int offset, int length) {
getElementsWithInputVertexIds(inst, out, dstOffset, offset, length); getElementsWithInputVertexIds(inst, dst, dstOffset, offset, length);
} }
// @formatter:off // @formatter:off
/*JNI /*JNI
#include <tesselator.h> #include <tesselator.h>
#include <string.h> #include <string.h>
#include <stdlib.h>
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(); /* { static native long newTess(int size); /* {
return (long)tessNewTess(0); 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); /* {
private static native void freeTess(long inst); /* {
tessDeleteTess((TESStesselator*) inst); tessDeleteTess((TESStesselator*) inst);
} */ } */
/**
/**
* Adds a contour to be tesselated. * Adds a contour to be tesselated.
* The type of the vertex coordinates is assumed to be TESSreal. * 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 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 pointer - pointer to the first coordinate of the first vertex in the array.
* @param stride - defines offset in bytes between consecutive vertices. * @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); tessAddContour((TESStesselator*) inst, size, contour + (offset * stride), stride, count);
} */ } */
static native void addMultiContour2D(long inst, int[] index, float[] contour, int idxStart, int idxCount);/* {
private static native void addMultiContour2D(long inst, int[] index, float[] contour, int idxStart, int idxCount);/* {
TESStesselator* tess = (TESStesselator*) inst; TESStesselator* tess = (TESStesselator*) inst;
int offset = 0; int offset = 0;
// start at 0 to get the correct offset in contour..
for (int i = 0; i < idxStart + idxCount; i++){ for (int i = 0; i < idxStart + idxCount; i++){
int len = index[i]; int len = index[i];
if ((len % 2 != 0) || (len < 0)) if ((len % 2 != 0) || (len < 0))
break; break;
if (len < 6 || i < idxStart) { if (len < 6 || i < idxStart) {
offset += len; offset += len;
continue; continue;
} }
tessAddContour(tess, 2, contour + offset, 8, len >> 1); tessAddContour(tess, 2, contour + offset, 8, len >> 1);
offset += len; offset += len;
} }
} */ } */
/** /**
* Tesselate contours. * Tesselate contours.
* *
* @param tess - pointer to tesselator object. * @param tess - pointer to tesselator object.
* @param windingRule - winding rules used for tesselation, must be one of TessWindingRule. * @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 elementType - defines the tesselation result element type, must be one of TessElementType.
* @param polySize - defines maximum vertices per polygons if output is polygons. * @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 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. * @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); return tessTesselate((TESStesselator*) inst, windingRule, elementType, polySize, vertexSize, 0);
} */ } */
static native int getVertexCount(long inst); /*{
private static native int getVertexCount(long inst); /*{
return tessGetVertexCount((TESStesselator*) inst); return tessGetVertexCount((TESStesselator*) inst);
}*/ }*/
/** /**
* Returns pointer to first coordinate of first vertex. * Returns pointer to first coordinate of first vertex.
*/ */
private static native boolean getVertices(long inst, float[] out, int offset, int length);/*{ static native boolean getVertices(long inst, float[] out, int offset, int length);/*{
const TESSIOreal* vertices = tessGetVertices((TESStesselator*) inst); const TESSreal* vertices = tessGetVertices((TESStesselator*) inst);
//const TESSreal* vertices = tessGetVertices((TESStesselator*) inst);
if (!vertices) if (!vertices)
return 0; return 0;
memcpy(out, vertices + offset, length * sizeof(TESSreal));
memcpy(out, vertices + offset, length * sizeof(TESSIOreal));
//memcpy(out, vertices + offset, length * sizeof(TESSreal));
return 1; return 1;
}*/ }*/
/** /**
* Returns pointer to first coordinate of first vertex. * Returns pointer to first coordinate of first vertex.
*/ */
private static native void getVerticesS(long inst, short[] out, int offset, int length, float scale);/*{ 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);
//const TESSreal* vertices = tessGetVertices((TESStesselator*) inst);
for(int i = 0; i < length; i++) for(int i = 0; i < length; i++)
out[i] = (short)(vertices[offset++] * scale + 0.5f); out[i] = (short)(vertices[offset++] * scale + 0.5f);
}*/ }*/
/** /**
* Returns pointer to first vertex index. * Returns pointer to first vertex index.
* *
* Vertex indices can be used to map the generated vertices to the original vertices. * 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. * 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. * 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); const TESSindex* indices = tessGetVertexIndices((TESStesselator*) inst);
if (!indices) if (!indices)
return 0; return 0;
memcpy(out, indices + offset, length * sizeof(TESSindex)); memcpy(out, indices + offset, length * sizeof(TESSindex));
return 1; return 1;
} */ } */
/** /**
* Returns number of elements in the the tesselated output. * 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); 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); const TESSindex* elements = tessGetElements((TESStesselator*) inst);
if (!elements) if (!elements)
return 0; return 0;
memcpy(out, elements + offset, length * sizeof(TESSindex)); memcpy(out, elements + offset, length * sizeof(TESSindex));
return 1; 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); const TESSindex* elements = tessGetElements((TESStesselator*) inst);
for(int i = 0; i < length; i++) for(int i = 0; i < length; i++)
out[i] = (short)elements[offset++]; 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* elements = tessGetElements((TESStesselator*) inst);
const TESSindex* indices = tessGetVertexIndices((TESStesselator*) inst); const TESSindex* indices = tessGetVertexIndices((TESStesselator*) inst);
for(int i = 0; i < length; i++) 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);
}
}

View File

@ -18,55 +18,78 @@ package org.oscim.utils;
import java.util.Arrays; import java.util.Arrays;
import org.oscim.core.GeometryBuffer;
import org.oscim.renderer.elements.VertexData; import org.oscim.renderer.elements.VertexData;
import org.oscim.utils.math.MathUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
public class Tessellator { public class Tessellator {
static final Logger log = LoggerFactory.getLogger(Tessellator.class); 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 * Special version for ExtrusionLayer to match indices with vertex
* positions. * positions.
*/ */
public static int tessellate(float[] points, int ppos, int plen, int[] index, public static int tessellate(float[] points, int ppos, int numPoints, int[] index,
int ipos, int rings, int vertexOffset, VertexData outTris) { 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; TessJNI tess = new TessJNI(buckets);
for (int i = 0; i < rings; i++)
numPoints += index[ipos + i];
long ctx = Tessellator.tessellate(points, ppos, index, ipos, rings, result); tess.addContour2D(index, points, ipos, numRings);
if ((numPoints / 2) < result[RESULT_VERTICES]) { //log.debug("tess ipos:{} rings:{}", ipos, numRings);
log.debug("skip poly: " + Arrays.toString(result) + " " + numPoints);
Tessellator.tessFinish(ctx); 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; return 0;
} }
int cnt;
int sumIndices = 0; int sumIndices = 0;
VertexData.Chunk vd = outTris.obtainChunk(); 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 start = vd.used;
int end = start + cnt; int end = start + size;
short[] v = vd.vertices; short[] indices = vd.vertices;
for (int i = start; i < end; i++)
v[i] *= 2;
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) /* when a ring has an odd number of points one (or rather two)
* additional vertices will be added. so the following rings * additional vertices will be added. so the following rings
* needs extra offset */ * needs extra offset */
int shift = 0; 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]); shift += (index[ipos + i]);
/* even number of points? */ /* even number of points? */
@ -74,203 +97,273 @@ public class Tessellator {
continue; continue;
for (int j = start; j < end; j++) for (int j = start; j < end; j++)
if (v[j] >= shift) if (indices[j] >= shift)
v[j] += 2; indices[j] += 2;
shift += 2; shift += 2;
} }
/* shift by vertexOffset */ /* shift by vertexOffset */
for (int i = start; i < end; i++) 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(); outTris.releaseChunk();
if (vd.used == VertexData.SIZE) { offset += size;
/* gets next item since this one is full */
vd = outTris.obtainChunk();
continue;
}
/* no more indices to get. */
break;
} }
Tessellator.tessFinish(ctx); tess.dispose();
return sumIndices; return sumIndices;
} }
// private static final int RESULT_VERTICES = 0;
/** // private static final int RESULT_TRIANGLES = 1;
* Untested! //
*/ // /**
public static int tessellate(GeometryBuffer geom, GeometryBuffer out) { // * Special version for ExtrusionLayer to match indices with vertex
// * positions.
int[] result = new int[2]; // */
// public static int tessellate(float[] points, int ppos, int plen, int[] index,
int numRings = 0; // int ipos, int rings, int vertexOffset, VertexData outTris) {
int numPoints = 0; //
// int[] result = new int[2];
for (int i = 0; i < geom.indexPos; i++) { //
if (geom.index[i] > 0) { // int numPoints = 0;
numRings++; // for (int i = 0; i < rings; i++)
numPoints += geom.index[i]; // numPoints += index[ipos + i];
} else //
break; // long ctx = Tessellator.tessellate(points, ppos, index, ipos, rings, result);
} // if ((numPoints / 2) < result[RESULT_VERTICES]) {
// log.debug("skip poly: " + Arrays.toString(result) + " " + numPoints);
long ctx = Tessellator.tessellate(geom.points, 0, // Tessellator.tessFinish(ctx);
geom.index, 0, // return 0;
numRings, result); // }
//
boolean verticesAdded = false; // int cnt;
if (numPoints < result[RESULT_VERTICES] * 2) { // int sumIndices = 0;
//log.debug("grow vertices" + geom.pointPos); //
verticesAdded = true; // VertexData.Chunk vd = outTris.obtainChunk();
} //
// while ((cnt = Tessellator.tessGetIndicesWO(ctx, vd.vertices, vd.used)) > 0) {
if (out == null) { // int start = vd.used;
/* overwrite geom contents */ // int end = start + cnt;
out = geom; // short[] v = vd.vertices;
if (verticesAdded) { //
out.ensurePointSize(result[RESULT_VERTICES], false); // for (int i = start; i < end; i++)
Tessellator.tessGetVerticesFloat(ctx, out.points); // v[i] *= 2;
} //
} else { // /* when a ring has an odd number of points one (or rather two)
out.ensurePointSize(result[RESULT_VERTICES], false); // * additional vertices will be added. so the following rings
// * needs extra offset */
if (verticesAdded) { // int shift = 0;
Tessellator.tessGetVerticesFloat(ctx, out.points); // for (int i = 0, m = rings - 1; i < m; i++) {
} else { // shift += (index[ipos + i]);
System.arraycopy(geom.points, 0, out.points, 0, numPoints); //
} // /* even number of points? */
} // if (((index[ipos + i] >> 1) & 1) == 0)
// continue;
out.ensureIndexSize(result[RESULT_TRIANGLES * 3], false); //
Tessellator.tessGetIndices(ctx, out.index); // for (int j = start; j < end; j++)
// if (v[j] >= shift)
Tessellator.tessFinish(ctx); // v[j] += 2;
//
return 1; // shift += 2;
} // }
//
/* FIXME This modifies geom ?! */ // /* shift by vertexOffset */
public static int tessellate(GeometryBuffer geom, float scale, // for (int i = start; i < end; i++)
VertexData outPoints, VertexData outTris, int vertexOffset) { // v[i] += vertexOffset;
//
int numIndices = 0; // sumIndices += cnt;
int indexPos = 0; //
int pointPos = 0; // vd.used += cnt;
int indexEnd = geom.index.length; // outTris.releaseChunk();
//
int[] result = new int[2]; // if (vd.used == VertexData.SIZE) {
// /* gets next item since this one is full */
float s = scale; // vd = outTris.obtainChunk();
scale = 1; // continue;
// }
for (int idx = 0; idx < indexEnd && geom.index[idx] > 0; idx++) { // /* no more indices to get. */
indexPos = idx; // break;
// }
int numRings = 1; //
int numPoints = geom.index[idx++]; // Tessellator.tessFinish(ctx);
//
for (; idx < indexEnd && geom.index[idx] > 0; idx++) { // return sumIndices;
numRings++; // }
numPoints += geom.index[idx]; //
} // /**
// * Untested!
/* FIXME !!! */ // */
for (int i = pointPos; i < pointPos + numPoints; i += 2) { // public static int tessellate(GeometryBuffer geom, GeometryBuffer out) {
geom.points[i + 0] = (int) (geom.points[i + 0] * s); //
geom.points[i + 1] = (int) (geom.points[i + 1] * s); // int[] result = new int[2];
} //
// int numRings = 0;
long ctx = Tessellator.tessellate(geom.points, pointPos, // int numPoints = 0;
geom.index, indexPos, //
numRings, result); // for (int i = 0; i < geom.indexPos; i++) {
// if (geom.index[i] > 0) {
if (result[RESULT_VERTICES] == 0 || result[RESULT_TRIANGLES] == 0) { // numRings++;
log.debug("ppos " + pointPos + " ipos:" + indexPos + // numPoints += geom.index[i];
" rings:" + numRings + " " + Arrays.toString(geom.index)); // } else
continue; // break;
} // }
//
pointPos += numPoints; // long ctx = Tessellator.tessellate(geom.points, 0,
// geom.index, 0,
while (true) { // numRings, result);
VertexData.Chunk vd = outTris.obtainChunk(); //
// boolean verticesAdded = false;
int cnt = Tessellator.tessGetIndicesWO(ctx, vd.vertices, vd.used); // if (numPoints < result[RESULT_VERTICES] * 2) {
if (cnt <= 0) // //log.debug("grow vertices" + geom.pointPos);
break; // verticesAdded = true;
// }
/* shift by vertexOffset */ //
for (int pos = vd.used, end = pos + cnt; pos < end; pos++) // if (out == null) {
vd.vertices[pos] += vertexOffset; // /* overwrite geom contents */
// out = geom;
numIndices += cnt; // if (verticesAdded) {
// out.ensurePointSize(result[RESULT_VERTICES], false);
vd.used += cnt; // Tessellator.tessGetVerticesFloat(ctx, out.points);
outTris.releaseChunk(); // }
// } else {
if (vd.used < VertexData.SIZE) // out.ensurePointSize(result[RESULT_VERTICES], false);
break; //
} // if (verticesAdded) {
// Tessellator.tessGetVerticesFloat(ctx, out.points);
while (true) { // } else {
VertexData.Chunk vd = outPoints.obtainChunk(); // System.arraycopy(geom.points, 0, out.points, 0, numPoints);
// }
int cnt = Tessellator.tessGetVerticesWO(ctx, vd.vertices, vd.used, scale); // }
if (cnt <= 0) //
break; // out.ensureIndexSize(result[RESULT_TRIANGLES * 3], false);
// Tessellator.tessGetIndices(ctx, out.index);
vertexOffset += cnt >> 1; //
// Tessellator.tessFinish(ctx);
vd.used += cnt; //
outPoints.releaseChunk(); // return 1;
// }
if (vd.used < VertexData.SIZE) //
break; // /* FIXME This modifies geom ?! */
} // public static int tessellate(GeometryBuffer geom, float scale,
// VertexData outPoints, VertexData outTris, int vertexOffset) {
Tessellator.tessFinish(ctx); //
// int numIndices = 0;
if (idx >= indexEnd || geom.index[idx] < 0) // int indexPos = 0;
break; // int pointPos = 0;
} // int indexEnd = geom.index.length;
//
if (vertexOffset > Short.MAX_VALUE) { // int[] result = new int[2];
log.debug("too much !!!" + Arrays.toString(geom.index)); //
return 0; // float s = scale;
} // scale = 1;
//
return numIndices; // for (int idx = 0; idx < indexEnd && geom.index[idx] > 0; idx++) {
} // indexPos = idx;
//
/** // int numRings = 1;
* @param points an array of x,y coordinates // int numPoints = geom.index[idx++];
* @param pos position in points array //
* @param index geom indices // for (; idx < indexEnd && geom.index[idx] > 0; idx++) {
* @param ipos position in index array // numRings++;
* @param numRings number of rings in polygon == outer(1) + inner rings // numPoints += geom.index[idx];
* @param result contains number of vertices and number of triangles // }
* @return context - must be freed with tessFinish() //
*/ // /* FIXME !!! */
protected static native long tessellate(float[] points, int pos, // for (int i = pointPos; i < pointPos + numPoints; i += 2) {
int[] index, int ipos, int numRings, int[] result); // geom.points[i + 0] = (int) (geom.points[i + 0] * s);
// geom.points[i + 1] = (int) (geom.points[i + 1] * s);
protected static native void tessFinish(long ctx); // }
//
protected static native int tessGetVertices(long ctx, short[] coordinates, float scale); // long ctx = Tessellator.tessellate(geom.points, pointPos,
// geom.index, indexPos,
protected static native int tessGetVerticesWO(long ctx, short[] coordinates, // numRings, result);
int offset, float scale); //
// if (result[RESULT_VERTICES] == 0 || result[RESULT_TRIANGLES] == 0) {
protected static native int tessGetVerticesFloat(long ctx, float[] coordinates); // log.debug("ppos " + pointPos + " ipos:" + indexPos +
// " rings:" + numRings + " " + Arrays.toString(geom.index));
protected static native int tessGetIndices(long ctx, int[] indices); // continue;
// }
protected static native int tessGetIndicesWO(long ctx, short[] indices, int offset); //
// 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);
} }