Exemple #1
0
        /* Takes a single contour and tries to render it
         * as a triangle fan.  This handles convex polygons, as well as some
         * non-convex polygons if we get lucky.
         *
         * Returns TRUE if the polygon was successfully rendered.  The rendering
         * output is provided as callbacks (see the api).
         */

        public bool RenderCache()
        {
            Tesselator.VertexAndIndex[] vCache = this.simpleVertexCache;
            Tesselator.VertexAndIndex   v0     = vCache[0];
            double[] norm3 = new double[3];
            int      sign;

            if (this.cacheCount < 3)
            {
                /* Degenerate contour -- no output */
                return(true);
            }

            norm3[0] = 0;
            norm3[1] = 0;
            norm3[2] = 1;

            sign = this.ComputeNormal(norm3);
            if (sign == SIGN_INCONSISTENT)
            {
                // Fan triangles did not have a consistent orientation
                return(false);
            }
            if (sign == 0)
            {
                // All triangles were degenerate
                return(true);
            }

            /* Make sure we do the right thing for each winding rule */
            switch (this.windingRule)
            {
            case Tesselator.WindingRuleType.Odd:
            case Tesselator.WindingRuleType.NonZero:
                break;

            case Tesselator.WindingRuleType.Positive:
                if (sign < 0)
                {
                    return(true);
                }
                break;

            case Tesselator.WindingRuleType.Negative:
                if (sign > 0)
                {
                    return(true);
                }
                break;

            case Tesselator.WindingRuleType.ABS_GEQ_Two:
                return(true);
            }

            this.CallBegin(this.BoundaryOnly ? Tesselator.TriangleListType.LineLoop
                                : (this.cacheCount > 3) ? Tesselator.TriangleListType.TriangleFan
                                : Tesselator.TriangleListType.Triangles);

            this.CallVertex(v0.vertexIndex);
            if (sign > 0)
            {
                for (int vcIndex = 1; vcIndex < this.cacheCount; ++vcIndex)
                {
                    this.CallVertex(vCache[vcIndex].vertexIndex);
                }
            }
            else
            {
                for (int vcIndex = this.cacheCount - 1; vcIndex > 0; --vcIndex)
                {
                    this.CallVertex(vCache[vcIndex].vertexIndex);
                }
            }
            this.CallEnd();
            return(true);
        }
Exemple #2
0
        private int ComputeNormal(double[] norm3)

        /*
         * Check that each triangle in the fan from v0 has a
         * consistent orientation with respect to norm3[].  If triangles are
         * consistently oriented CCW, return 1; if CW, return -1; if all triangles
         * are degenerate return 0; otherwise (no consistent orientation) return
         * SIGN_INCONSISTENT.
         */
        {
            Tesselator.VertexAndIndex[] vCache = this.simpleVertexCache;
            Tesselator.VertexAndIndex   v0     = vCache[0];
            int    vcIndex;
            double dot, xc, yc, xp, yp;

            double[] n    = new double[3];
            int      sign = 0;

            /* Find the polygon normal.  It is important to get a reasonable
             * normal even when the polygon is self-intersecting (eg. a bowtie).
             * Otherwise, the computed normal could be very tiny, but perpendicular
             * to the true plane of the polygon due to numerical noise.  Then all
             * the triangles would appear to be degenerate and we would incorrectly
             * decompose the polygon as a fan (or simply not render it at all).
             *
             * We use a sum-of-triangles normal algorithm rather than the more
             * efficient sum-of-trapezoids method (used in CheckOrientation()
             * in normal.c).  This lets us explicitly reverse the signed area
             * of some triangles to get a reasonable normal in the self-intersecting
             * case.
             */
            vcIndex = 1;
            xc      = vCache[vcIndex].x - v0.x;
            yc      = vCache[vcIndex].y - v0.y;
            while (++vcIndex < this.cacheCount)
            {
                xp = xc; yp = yc;
                xc = vCache[vcIndex].x - v0.x;
                yc = vCache[vcIndex].y - v0.y;

                /* Compute (vp - v0) cross (vc - v0) */
                n[0] = 0;
                n[1] = 0;
                n[2] = xp * yc - yp * xc;

                dot = n[0] * norm3[0] + n[1] * norm3[1] + n[2] * norm3[2];
                if (dot != 0)
                {
                    /* Check the new orientation for consistency with previous triangles */
                    if (dot > 0)
                    {
                        if (sign < 0)
                        {
                            return(SIGN_INCONSISTENT);
                        }
                        sign = 1;
                    }
                    else
                    {
                        if (sign > 0)
                        {
                            return(SIGN_INCONSISTENT);
                        }
                        sign = -1;
                    }
                }
            }

            return(sign);
        }