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++]]); }*/ }