#include "tessellate.h" #include #include #include #ifdef __ANDROID__ #include #define printf(...) __android_log_print(ANDROID_LOG_DEBUG, "Tesselate", __VA_ARGS__) #endif #define CAST_CTX(x) (TessContext *)(uintptr_t) x void Java_org_oscim_utils_Tessellator_tessFinish(JNIEnv *env, jclass c, jlong ptr_context) { TessContext *ctx = CAST_CTX(ptr_context); while (ctx->latest_v) { Vertex *prev = ctx->latest_v->prev; free(ctx->latest_v); ctx->latest_v = prev; } while (ctx->latest_t) { Triangle *prev = ctx->latest_t->prev; free(ctx->latest_t); ctx->latest_t = prev; } //destroy_tess_context(ctx); free(ctx); } Vertex *reverse(Vertex *root) { Vertex *start = 0; while (root) { Vertex *prev = root->prev; root->prev = start; start = root; root = prev; } return start; } jint Java_org_oscim_utils_Tessellator_tessGetVerticesWO(JNIEnv *env, jclass c, jlong ptr_context, jshortArray obj_coords, jint offset, jfloat scale) { TessContext *ctx = CAST_CTX(ptr_context); int length = (*env)->GetArrayLength(env, obj_coords); jshort* coords = (jshort*) (*env)->GetPrimitiveArrayCritical(env, obj_coords, 0); if (coords == NULL) { return 0; } if (!ctx->reversed) { ctx->reversed = 1; ctx->latest_v = reverse(ctx->latest_v); } int pos = offset; for (; ctx->latest_v && pos < length; pos += 2) { coords[pos + 0] = (ctx->latest_v->pt[0] * scale) + 0.5f; coords[pos + 1] = (ctx->latest_v->pt[1] * scale) + 0.5f; Vertex *prev = ctx->latest_v->prev; free(ctx->latest_v); ctx->latest_v = prev; } (*env)->ReleasePrimitiveArrayCritical(env, obj_coords, coords, JNI_ABORT); return pos - offset; } jint Java_org_oscim_utils_Tessellator_tessGetVertices(JNIEnv *env, jclass c, jlong ptr_context, jshortArray obj_coords, jfloat scale) { return Java_org_oscim_utils_Tessellator_tessGetVerticesWO(env, c, ptr_context, obj_coords, 0, scale); } jint Java_org_oscim_utils_Tessellator_tessGetVerticesD(JNIEnv *env, jclass c, jlong ptr_context, jdoubleArray obj_coords) { TessContext *ctx = CAST_CTX(ptr_context); int length = (*env)->GetArrayLength(env, obj_coords); jdouble* coords = (jdouble*) (*env)->GetPrimitiveArrayCritical(env, obj_coords, 0); if (coords == NULL) { return 0; } if (!ctx->reversed) { ctx->reversed = 1; ctx->latest_v = reverse(ctx->latest_v); } int cnt = 0; for (; ctx->latest_v && cnt < length; cnt += 2) { coords[cnt + 0] = ctx->latest_v->pt[0]; coords[cnt + 1] = ctx->latest_v->pt[1]; Vertex *prev = ctx->latest_v->prev; free(ctx->latest_v); ctx->latest_v = prev; } (*env)->ReleasePrimitiveArrayCritical(env, obj_coords, coords, JNI_ABORT); return cnt; } jint Java_org_oscim_utils_Tessellator_tessGetIndicesWO(JNIEnv *env, jclass c, jlong ptr_context, jshortArray obj_indices, int offset) { TessContext *ctx = CAST_CTX(ptr_context); int length = (*env)->GetArrayLength(env, obj_indices); jshort* tris = (jshort*) (*env)->GetPrimitiveArrayCritical(env, obj_indices, 0); if (tris == NULL) { return 0; } int n_tris_copy = ctx->n_tris; int pos = offset; for (; ctx->latest_t && pos < length; pos += 3) { tris[pos + 0] = ctx->latest_t->v[0]; tris[pos + 1] = ctx->latest_t->v[1]; tris[pos + 2] = ctx->latest_t->v[2]; Triangle *prev = ctx->latest_t->prev; free(ctx->latest_t); ctx->latest_t = prev; n_tris_copy--; } ctx->n_tris = n_tris_copy; (*env)->ReleasePrimitiveArrayCritical(env, obj_indices, tris, JNI_ABORT); return pos - offset; } jint Java_org_oscim_utils_Tessellator_tessGetIndices(JNIEnv *env, jclass c, jlong ptr_context, jshortArray obj_indices, int offset){ return Java_org_oscim_utils_Tessellator_tessGetIndicesWO(env, c, ptr_context, obj_indices, 0); } jlong Java_org_oscim_utils_Tessellator_tessellate(JNIEnv *env, jclass c, jfloatArray obj_points, jint pos, jshortArray obj_index, jint ipos, jint num_rings, jintArray obj_out) { //printf("add %d %d %d\n", pos, ipos, num_rings); jboolean isCopy; float* orig_points = (float*) (*env)->GetPrimitiveArrayCritical(env, obj_points, &isCopy); if (orig_points == NULL) return 0; const float *points = orig_points + pos; jshort* orig_indices = (jshort*) (*env)->GetPrimitiveArrayCritical(env, obj_index, &isCopy); if (orig_indices == NULL) { (*env)->ReleasePrimitiveArrayCritical(env, obj_points, orig_points, JNI_ABORT); return 0; } jshort* indices = orig_indices + ipos; const float **rings = malloc(sizeof(float*) * (num_rings + 1)); int offset = 0; for (int i = 0; i < num_rings; i++) { rings[i] = points + offset; offset += indices[i]; } (*env)->ReleasePrimitiveArrayCritical(env, obj_index, orig_indices, JNI_ABORT); (*env)->ReleasePrimitiveArrayCritical(env, obj_points, orig_points, JNI_ABORT); rings[num_rings] = points + offset; int nverts, ntris; TessContext *ctx = tessellate(NULL, &nverts, NULL, &ntris, rings, rings + (num_rings + 1)); free(rings); nverts = 1 + ctx->latest_v->index; ntris = ctx->n_tris; jint* out = (jint*) (*env)->GetPrimitiveArrayCritical(env, obj_out, &isCopy); if (out == NULL) { return 0; } out[0] = nverts; out[1] = ntris; (*env)->ReleasePrimitiveArrayCritical(env, obj_out, out, JNI_ABORT); return (long) ctx; } jlong Java_org_oscim_renderer_sublayers_MeshLayer_tessellateD(JNIEnv *env, jclass c, jdoubleArray obj_points, jint pos, jshortArray obj_index, jint ipos, jint num_rings) { //, jintArray obj_out) { jboolean isCopy; //printf("add %d %d %d\n", pos, ipos, num_rings); double* orig_points = (double*) (*env)->GetPrimitiveArrayCritical(env, obj_points, &isCopy); if (orig_points == NULL) return 0; const double *points = orig_points + pos; jshort* orig_indices = (jshort*) (*env)->GetPrimitiveArrayCritical(env, obj_index, &isCopy); if (orig_indices == NULL) { (*env)->ReleasePrimitiveArrayCritical(env, obj_points, orig_points, JNI_ABORT); return 0; } jshort* indices = orig_indices + ipos; const double **rings = malloc(sizeof(double*) * (num_rings + 1)); int offset = 0; for (int i = 0; i < num_rings; i++) { rings[i] = points + offset; offset += indices[i]; } rings[num_rings] = points + offset; int nverts, ntris; TessContext *ctx = tessellateD(NULL, &nverts, NULL, &ntris, rings, rings + (num_rings + 1)); free(rings); (*env)->ReleasePrimitiveArrayCritical(env, obj_index, orig_indices, JNI_ABORT); (*env)->ReleasePrimitiveArrayCritical(env, obj_points, orig_points, JNI_ABORT); return (long) ctx; }