//    #define MAX_FAST_ALLOC	(MAX(sizeof(EdgePair), \
        //                 MAX(sizeof(GLUvertex),sizeof(GLUface))))

        private GLUtessellatorImpl()
        {
            state = TessState.T_DORMANT;

            normal[0] = 0;
            normal[1] = 0;
            normal[2] = 0;

            relTolerance = GLU_TESS_DEFAULT_TOLERANCE;
            windingRule  = GLU.GLU_TESS_WINDING_ODD;
            flagBoundary = false;
            boundaryOnly = false;

            callBegin    = NULL_CB;
            callEdgeFlag = NULL_CB;
            callVertex   = NULL_CB;
            callEnd      = NULL_CB;
            callError    = NULL_CB;
            callCombine  = NULL_CB;
            //        callMesh = NULL_CB;

            callBeginData    = NULL_CB;
            callEdgeFlagData = NULL_CB;
            callVertexData   = NULL_CB;
            callEndData      = NULL_CB;
            callErrorData    = NULL_CB;
            callCombineData  = NULL_CB;

            polygonData = null;

            for (int i = 0; i < cache.Length; i++)
            {
                cache[i] = new CachedVertex();
            }
        }
        /**
         * Prepares this GLUTessellatorSupport's internal GLU tessellator for use. This initializes the internal
         * GLUtessellator to a new instance by invoking {@link javax.media.opengl.glu.GLU#gluNewTess()}, and configures the
         * tessellator with the specified callback and normal with calls to {@link javax.media.opengl.glu.GLU#gluTessCallback(javax.media.opengl.glu.GLUtessellator,
         * int, javax.media.opengl.glu.GLUtessellatorCallback)} and {@link javax.media.opengl.glu.GLU#gluTessNormal(javax.media.opengl.glu.GLUtessellator,
         * double, double, double)}, respectively.
         *
         * @param callback the callback to configure the GLU tessellator with.
         * @param normal   the normal to configure the GLU tessellator with.
         *
         * @throws ArgumentException if the callback or the normal is null.
         */
        public void beginTessellation(GLUtessellatorCallback callback, Vec4 normal)
        {
            if (callback == null)
            {
                String message = Logging.getMessage("nullValue.CallbackIsNull");
                Logging.logger().severe(message);
                throw new ArgumentException(message);
            }

            if (normal == null)
            {
                String message = Logging.getMessage("nullValue.NormalIsNull");
                Logging.logger().severe(message);
                throw new ArgumentException(message);
            }

            this.tess = GLU.gluNewTess();
            GLU.gluTessNormal(this.tess, normal.x, normal.y, normal.z);
            GLU.gluTessCallback(this.tess, GLU.GLU_TESS_BEGIN, callback);
            GLU.gluTessCallback(this.tess, GLU.GLU_TESS_VERTEX, callback);
            GLU.gluTessCallback(this.tess, GLU.GLU_TESS_END, callback);
            GLU.gluTessCallback(this.tess, GLU.GLU_TESS_COMBINE, callback);
        }
        public virtual void  gluTessCallback(int which, GLUtessellatorCallback aCallback)
        {
            switch (which)
            {
            case GLU.GLU_TESS_BEGIN:
                callBegin = aCallback == null?NULL_CB:aCallback;
                return;

            case GLU.GLU_TESS_BEGIN_DATA:
                callBeginData = aCallback == null?NULL_CB:aCallback;
                return;

            case GLU.GLU_TESS_EDGE_FLAG:
                callEdgeFlag = aCallback == null?NULL_CB:aCallback;

                /* If the client wants boundary edges to be flagged,
                 * we render everything as separate triangles (no strips or fans).
                 */
                flagBoundary = aCallback != null;
                return;

            case GLU.GLU_TESS_EDGE_FLAG_DATA:
                callEdgeFlagData = callBegin = aCallback == null?NULL_CB:aCallback;

                /* If the client wants boundary edges to be flagged,
                 * we render everything as separate triangles (no strips or fans).
                 */
                flagBoundary = (aCallback != null);
                return;

            case GLU.GLU_TESS_VERTEX:
                callVertex = aCallback == null?NULL_CB:aCallback;
                return;

            case GLU.GLU_TESS_VERTEX_DATA:
                callVertexData = aCallback == null?NULL_CB:aCallback;
                return;

            case GLU.GLU_TESS_END:
                callEnd = aCallback == null?NULL_CB:aCallback;
                return;

            case GLU.GLU_TESS_END_DATA:
                callEndData = aCallback == null?NULL_CB:aCallback;
                return;

            case GLU.GLU_TESS_ERROR:
                callError = aCallback == null?NULL_CB:aCallback;
                return;

            case GLU.GLU_TESS_ERROR_DATA:
                callErrorData = aCallback == null?NULL_CB:aCallback;
                return;

            case GLU.GLU_TESS_COMBINE:
                callCombine = aCallback == null?NULL_CB:aCallback;
                return;

            case GLU.GLU_TESS_COMBINE_DATA:
                callCombineData = aCallback == null?NULL_CB:aCallback;
                return;

            //            case GLU_TESS_MESH:
            //                callMesh = aCallback == null ? NULL_CB : aCallback;
            //                return;

            default:
                callErrorOrErrorData(GLU.GLU_INVALID_ENUM);
                return;
            }
        }
        public virtual void gluTessCallback(int which, GLUtessellatorCallback aCallback)
        {
            switch (which)
            {

                case GLU.GLU_TESS_BEGIN:
                    callBegin = aCallback == null?NULL_CB:aCallback;
                    return ;

                case GLU.GLU_TESS_BEGIN_DATA:
                    callBeginData = aCallback == null?NULL_CB:aCallback;
                    return ;

                case GLU.GLU_TESS_EDGE_FLAG:
                    callEdgeFlag = aCallback == null?NULL_CB:aCallback;
                    /* If the client wants boundary edges to be flagged,
                    * we render everything as separate triangles (no strips or fans).
                    */
                    flagBoundary = aCallback != null;
                    return ;

                case GLU.GLU_TESS_EDGE_FLAG_DATA:
                    callEdgeFlagData = callBegin = aCallback == null?NULL_CB:aCallback;
                    /* If the client wants boundary edges to be flagged,
                    * we render everything as separate triangles (no strips or fans).
                    */
                    flagBoundary = (aCallback != null);
                    return ;

                case GLU.GLU_TESS_VERTEX:
                    callVertex = aCallback == null?NULL_CB:aCallback;
                    return ;

                case GLU.GLU_TESS_VERTEX_DATA:
                    callVertexData = aCallback == null?NULL_CB:aCallback;
                    return ;

                case GLU.GLU_TESS_END:
                    callEnd = aCallback == null?NULL_CB:aCallback;
                    return ;

                case GLU.GLU_TESS_END_DATA:
                    callEndData = aCallback == null?NULL_CB:aCallback;
                    return ;

                case GLU.GLU_TESS_ERROR:
                    callError = aCallback == null?NULL_CB:aCallback;
                    return ;

                case GLU.GLU_TESS_ERROR_DATA:
                    callErrorData = aCallback == null?NULL_CB:aCallback;
                    return ;

                case GLU.GLU_TESS_COMBINE:
                    callCombine = aCallback == null?NULL_CB:aCallback;
                    return ;

                case GLU.GLU_TESS_COMBINE_DATA:
                    callCombineData = aCallback == null?NULL_CB:aCallback;
                    return ;
                    //            case GLU_TESS_MESH:
                    //                callMesh = aCallback == null ? NULL_CB : aCallback;
                    //                return;

                default:
                    callErrorOrErrorData(GLU.GLU_INVALID_ENUM);
                    return ;

            }
        }
        private int state; /* what begin/end calls have we seen? */

        #endregion Fields

        #region Constructors

        //    #define MAX_FAST_ALLOC	(MAX(sizeof(EdgePair), \
        //                 MAX(sizeof(GLUvertex),sizeof(GLUface))))
        private GLUtessellatorImpl()
        {
            state = TessState.T_DORMANT;

            normal[0] = 0;
            normal[1] = 0;
            normal[2] = 0;

            relTolerance = GLU_TESS_DEFAULT_TOLERANCE;
            windingRule = GLU.GLU_TESS_WINDING_ODD;
            flagBoundary = false;
            boundaryOnly = false;

            callBegin = NULL_CB;
            callEdgeFlag = NULL_CB;
            callVertex = NULL_CB;
            callEnd = NULL_CB;
            callError = NULL_CB;
            callCombine = NULL_CB;
            //        callMesh = NULL_CB;

            callBeginData = NULL_CB;
            callEdgeFlagData = NULL_CB;
            callVertexData = NULL_CB;
            callEndData = NULL_CB;
            callErrorData = NULL_CB;
            callCombineData = NULL_CB;

            polygonData = null;

            for (int i = 0; i < cache.Length; i++)
            {
                cache[i] = new CachedVertex();
            }
        }