Пример #1
0
        /** Calculate the shortest path through the funnel.
         * \param funnel The portals of the funnel. The first and last vertices portals must be single points (so for example left[0] == right[0]).
         * \param unwrap Determines if twists and bends should be straightened out before running the funnel algorithm.
         * \param splitAtEveryPortal If true, then a vertex will be inserted every time the path crosses a portal
         *  instead of only at the corners of the path. The result will have exactly one vertex per portal if this is enabled.
         *  This may introduce vertices with the same position in the output (esp. in corners where many portals meet).
         *
         * If the unwrap option is disabled the funnel will simply be projected onto the XZ plane.
         * If the unwrap option is enabled then the funnel may be oriented arbitrarily and may have twists and bends.
         * This makes it possible to support the funnel algorithm in XY space as well as in more complicated cases, such
         * as on curved worlds.
         * \shadowimage{funnel_unwrap_illustration.png}
         *
         * \shadowimage{funnel_split_at_every_portal.png}
         *
         * \see Unwrap
         */
        //Good Game
        //public static List<Vector3> Calculate (FunnelPortals funnel, bool unwrap, bool splitAtEveryPortal) {
        public static List <VInt3> Calculate(FunnelPortals funnel, bool unwrap, bool splitAtEveryPortal)
        {
            if (funnel.left.Count != funnel.right.Count)
            {
                throw new System.ArgumentException("funnel.left.Count != funnel.right.Count");
            }

            // Get arrays at least as large as the number of portals
            //Good Game

            /*var leftArr = ArrayPool<Vector2>.Claim(funnel.left.Count);
             *          var rightArr = ArrayPool<Vector2>.Claim(funnel.left.Count);*/
            var leftArr = ArrayPool <VInt2> .Claim(funnel.left.Count);

            var rightArr = ArrayPool <VInt2> .Claim(funnel.left.Count);

            if (unwrap)
            {
                Unwrap(funnel, leftArr, rightArr);
            }
            else
            {
                // Copy to arrays
                for (int i = 0; i < funnel.left.Count; i++)
                {
                    leftArr[i]  = ToXZ(funnel.left[i]);
                    rightArr[i] = ToXZ(funnel.right[i]);
                }
            }

            int startIndex         = FixFunnel(leftArr, rightArr, funnel.left.Count);
            var intermediateResult = ListPool <int> .Claim();

            if (startIndex == -1)
            {
                // If funnel algorithm failed, fall back to a simple line
                intermediateResult.Add(0);
                intermediateResult.Add(funnel.left.Count - 1);
            }
            else
            {
                bool lastCorner;
                Calculate(leftArr, rightArr, funnel.left.Count, startIndex, intermediateResult, int.MaxValue, out lastCorner);
            }

            // Get list for the final result
            //Good Game
            //var result = ListPool<Vector3>.Claim(intermediateResult.Count);
            var result = ListPool <VInt3> .Claim(intermediateResult.Count);

            //Good Game
            //Vector2 prev2D = leftArr[0];
            VInt2 prev2D  = leftArr[0];
            var   prevIdx = 0;

            for (int i = 0; i < intermediateResult.Count; i++)
            {
                var idx = intermediateResult[i];

                if (splitAtEveryPortal)
                {
                    // Check intersections with every portal segment
                    var next2D = idx >= 0 ? leftArr[idx] : rightArr[-idx];
                    for (int j = prevIdx + 1; j < System.Math.Abs(idx); j++)
                    {
                        //Good Game
                        //var factor = VectorMath.LineIntersectionFactorXZ(FromXZ(leftArr[j]), FromXZ(rightArr[j]), FromXZ(prev2D), FromXZ(next2D));
                        var factor = IntMath.LineIntersectionFactorXZ(FromXZ(leftArr[j]), FromXZ(rightArr[j]), FromXZ(prev2D), FromXZ(next2D));
                        //result.Add(Vector3.Lerp(funnel.left[j], funnel.right[j], factor));
                        //Good Game
                        result.Add(VInt3.Lerp(funnel.left[j], funnel.right[j], factor));
                    }

                    prevIdx = Mathf.Abs(idx);
                    prev2D  = next2D;
                }

                if (idx >= 0)
                {
                    result.Add(funnel.left[idx]);
                }
                else
                {
                    result.Add(funnel.right[-idx]);
                }
            }

            // Release lists back to the pool
            ListPool <int> .Release(ref intermediateResult);

            //Good Game

            /*ArrayPool<Vector2>.Release(ref leftArr);
             *          ArrayPool<Vector2>.Release(ref rightArr);*/
            ArrayPool <VInt2> .Release(ref leftArr);

            ArrayPool <VInt2> .Release(ref rightArr);

            return(result);
        }