Esempio n. 1
0
        NNInfoInternal FindClosestConnectionPoint(PointNode node, Vector3 position)
        {
            var closestConnectionPoint = (Vector3)node.position;
            var conns    = node.connections;
            var nodePos  = (Vector3)node.position;
            var bestDist = float.PositiveInfinity;

            if (conns != null)
            {
                for (int i = 0; i < conns.Length; i++)
                {
                    var connectionMidpoint = ((UnityEngine.Vector3)conns[i].node.position + nodePos) * 0.5f;
                    var closestPoint       = VectorMath.ClosestPointOnSegment(nodePos, connectionMidpoint, position);
                    var dist = (closestPoint - position).sqrMagnitude;
                    if (dist < bestDist)
                    {
                        bestDist = dist;
                        closestConnectionPoint = closestPoint;
                    }
                }
            }

            var result = new NNInfoInternal();

            result.node            = node;
            result.clampedPosition = closestConnectionPoint;
            return(result);
        }
Esempio n. 2
0
        //Movement stuff

        /** Returns in which direction to move from a point on the path.
         * A simple and quite slow (well, compared to more optimized algorithms) algorithm first finds the closest path segment (from #vectorPath) and then returns
         * the direction to the next point from there. The direction is not normalized.
         * \returns Direction to move from a \a point, returns Vector3.zero if #vectorPath is null or has a length of 0 */
        public Vector3 GetMovementVector(Vector3 point)
        {
            if (vectorPath == null || vectorPath.Count == 0)
            {
                return(Vector3.zero);
            }

            if (vectorPath.Count == 1)
            {
                return(vectorPath[0] - point);
            }

            float minDist    = float.PositiveInfinity;         //Mathf.Infinity;
            int   minSegment = 0;

            for (int i = 0; i < vectorPath.Count - 1; i++)
            {
                Vector3 closest = VectorMath.ClosestPointOnSegment(vectorPath[i], vectorPath[i + 1], point);
                float   dist    = (closest - point).sqrMagnitude;
                if (dist < minDist)
                {
                    minDist    = dist;
                    minSegment = i;
                }
            }

            return(vectorPath[minSegment + 1] - point);
        }
Esempio n. 3
0
 private Vector3 CalculateWallForce(Vector3 position, Vector3 directionToTarget)
 {
     if (this.wallForce > 0f && this.wallDist > 0f)
     {
         float num  = 0f;
         float num2 = 0f;
         for (int i = 0; i < this.wallBuffer.Count; i += 2)
         {
             Vector3 a            = VectorMath.ClosestPointOnSegment(this.wallBuffer[i], this.wallBuffer[i + 1], this.tr.position);
             float   sqrMagnitude = (a - position).sqrMagnitude;
             if (sqrMagnitude <= this.wallDist * this.wallDist)
             {
                 Vector3 normalized = (this.wallBuffer[i + 1] - this.wallBuffer[i]).normalized;
                 float   num3       = Vector3.Dot(directionToTarget, normalized) * (1f - Math.Max(0f, 2f * (sqrMagnitude / (this.wallDist * this.wallDist)) - 1f));
                 if (num3 > 0f)
                 {
                     num2 = Math.Max(num2, num3);
                 }
                 else
                 {
                     num = Math.Max(num, -num3);
                 }
             }
         }
         Vector3 a2 = Vector3.Cross(Vector3.up, directionToTarget);
         return(a2 * (num2 - num));
     }
     return(Vector3.zero);
 }
Esempio n. 4
0
        // Token: 0x0600217F RID: 8575 RVA: 0x0018E8E8 File Offset: 0x0018CAE8
        private Vector2 CalculateWallForce(Vector2 position, float elevation, Vector2 directionToTarget)
        {
            if (this.wallForce <= 0f || this.wallDist <= 0f)
            {
                return(Vector2.zero);
            }
            float   num    = 0f;
            float   num2   = 0f;
            Vector3 vector = this.movementPlane.ToWorld(position, elevation);

            for (int i = 0; i < this.wallBuffer.Count; i += 2)
            {
                float sqrMagnitude = (VectorMath.ClosestPointOnSegment(this.wallBuffer[i], this.wallBuffer[i + 1], vector) - vector).sqrMagnitude;
                if (sqrMagnitude <= this.wallDist * this.wallDist)
                {
                    Vector2 normalized = this.movementPlane.ToPlane(this.wallBuffer[i + 1] - this.wallBuffer[i]).normalized;
                    float   num3       = Vector2.Dot(directionToTarget, normalized);
                    float   num4       = 1f - Math.Max(0f, 2f * (sqrMagnitude / (this.wallDist * this.wallDist)) - 1f);
                    if (num3 > 0f)
                    {
                        num2 = Math.Max(num2, num3 * num4);
                    }
                    else
                    {
                        num = Math.Max(num, -num3 * num4);
                    }
                }
            }
            return(new Vector2(directionToTarget.y, -directionToTarget.x) * (num2 - num));
        }
Esempio n. 5
0
        public Vector3 GetMovementVector(Vector3 point)
        {
            if ((base.vectorPath == null) || (base.vectorPath.Count == 0))
            {
                return(Vector3.zero);
            }
            if (base.vectorPath.Count == 1)
            {
                return(base.vectorPath[0] - point);
            }
            float positiveInfinity = float.PositiveInfinity;
            int   num2             = 0;

            for (int i = 0; i < (base.vectorPath.Count - 1); i++)
            {
                Vector3 vector2      = VectorMath.ClosestPointOnSegment(base.vectorPath[i], base.vectorPath[i + 1], point) - point;
                float   sqrMagnitude = vector2.sqrMagnitude;
                if (sqrMagnitude < positiveInfinity)
                {
                    positiveInfinity = sqrMagnitude;
                    num2             = i;
                }
            }
            return(base.vectorPath[num2 + 1] - point);
        }
Esempio n. 6
0
        public Vector3 GetMovementVector(Vector3 point)
        {
            if (this.vectorPath == null || this.vectorPath.Count == 0)
            {
                return(Vector3.zero);
            }
            if (this.vectorPath.Count == 1)
            {
                return(this.vectorPath[0] - point);
            }
            float num  = float.PositiveInfinity;
            int   num2 = 0;

            for (int i = 0; i < this.vectorPath.Count - 1; i++)
            {
                Vector3 a            = VectorMath.ClosestPointOnSegment(this.vectorPath[i], this.vectorPath[i + 1], point);
                float   sqrMagnitude = (a - point).sqrMagnitude;
                if (sqrMagnitude < num)
                {
                    num  = sqrMagnitude;
                    num2 = i;
                }
            }
            return(this.vectorPath[num2 + 1] - point);
        }
        Vector2 CalculateWallForce(Vector2 position, float elevation, Vector2 directionToTarget)
        {
            if (wallForce <= 0 || wallDist <= 0)
            {
                return(Vector2.zero);
            }

            float wLeft  = 0;
            float wRight = 0;

            var position3D = movementPlane.ToWorld(position, elevation);

            for (int i = 0; i < wallBuffer.Count; i += 2)
            {
                Vector3 closest = VectorMath.ClosestPointOnSegment(wallBuffer[i], wallBuffer[i + 1], position3D);
                float   dist    = (closest - position3D).sqrMagnitude;

                if (dist > wallDist * wallDist)
                {
                    continue;
                }

                Vector2 tang = movementPlane.ToPlane(wallBuffer[i + 1] - wallBuffer[i]).normalized;

                // Using the fact that all walls are laid out clockwise (looking from inside the obstacle)
                // Then left and right (ish) can be figured out like this
                float dot    = Vector2.Dot(directionToTarget, tang);
                float weight = 1 - System.Math.Max(0, (2 * (dist / (wallDist * wallDist)) - 1));
                if (dot > 0)
                {
                    wRight = System.Math.Max(wRight, dot * weight);
                }
                else
                {
                    wLeft = System.Math.Max(wLeft, -dot * weight);
                }
            }

            Vector2 normal = new Vector2(directionToTarget.y, -directionToTarget.x);

            return(normal * (wRight - wLeft));
        }
Esempio n. 8
0
        Vector3 CalculateWallForce(Vector3 position, Vector3 directionToTarget)
        {
            if (wallForce > 0 && wallDist > 0)
            {
                float wLeft  = 0;
                float wRight = 0;

                for (int i = 0; i < wallBuffer.Count; i += 2)
                {
                    Vector3 closest = VectorMath.ClosestPointOnSegment(wallBuffer[i], wallBuffer[i + 1], tr.position);
                    float   dist    = (closest - position).sqrMagnitude;

                    if (dist > wallDist * wallDist)
                    {
                        continue;
                    }

                    Vector3 tang = (wallBuffer[i + 1] - wallBuffer[i]).normalized;

                    // Using the fact that all walls are laid out clockwise (seeing from inside)
                    // Then left and right (ish) can be figured out like this
                    float dot = Vector3.Dot(directionToTarget, tang) * (1 - System.Math.Max(0, (2 * (dist / (wallDist * wallDist)) - 1)));
                    if (dot > 0)
                    {
                        wRight = System.Math.Max(wRight, dot);
                    }
                    else
                    {
                        wLeft = System.Math.Max(wLeft, -dot);
                    }
                }

                Vector3 norm = Vector3.Cross(Vector3.up, directionToTarget);
                return(norm * (wRight - wLeft));
            }
            return(Vector3.zero);
        }
Esempio n. 9
0
        /** Update is called once per frame */
        protected virtual void Update()
        {
            deltaTime = Mathf.Min(Time.smoothDeltaTime * 2, Time.deltaTime);

            if (rp != null)
            {
                //System.Diagnostics.Stopwatch w = new System.Diagnostics.Stopwatch();
                //w.Start();
                RichPathPart pt = rp.GetCurrentPart();
                var          fn = pt as RichFunnel;
                if (fn != null)
                {
                    //Clear buffers for reuse
                    Vector3 position = UpdateTarget(fn);

                    //tr.position = ps;

                    //Only get walls every 5th frame to save on performance
                    if (Time.frameCount % 5 == 0 && wallForce > 0 && wallDist > 0)
                    {
                        wallBuffer.Clear();
                        fn.FindWalls(wallBuffer, wallDist);
                    }

                    /*for (int i=0;i<wallBuffer.Count;i+=2) {
                     *  Debug.DrawLine (wallBuffer[i],wallBuffer[i+1],Color.magenta);
                     * }*/

                    //Pick next waypoint if current is reached
                    int tgIndex = 0;

                    /*if (buffer.Count > 1) {
                     *  if ((buffer[tgIndex]-tr.position).sqrMagnitude < pickNextWaypointDist*pickNextWaypointDist) {
                     *      tgIndex++;
                     *  }
                     * }*/


                    //Target point
                    Vector3 tg  = buffer[tgIndex];
                    Vector3 dir = tg - position;
                    dir.y = 0;

                    bool passedTarget = Vector3.Dot(dir, currentTargetDirection) < 0;
                    //Check if passed target in another way
                    if (passedTarget && buffer.Count - tgIndex > 1)
                    {
                        tgIndex++;
                        tg = buffer[tgIndex];
                    }

                    if (tg != lastTargetPoint)
                    {
                        currentTargetDirection   = (tg - position);
                        currentTargetDirection.y = 0;
                        currentTargetDirection.Normalize();
                        lastTargetPoint = tg;
                        //Debug.DrawRay (tr.position, Vector3.down*2,Color.blue,0.2f);
                    }

                    //Direction to target
                    dir   = (tg - position);
                    dir.y = 0;
                    float magn = dir.magnitude;

                    //Write out for other scripts to read
                    distanceToWaypoint = magn;

                    //Normalize
                    dir = magn == 0 ? Vector3.zero : dir / magn;
                    Vector3 normdir = dir;

                    Vector3 force = Vector3.zero;

                    if (wallForce > 0 && wallDist > 0)
                    {
                        float wLeft  = 0;
                        float wRight = 0;

                        for (int i = 0; i < wallBuffer.Count; i += 2)
                        {
                            Vector3 closest = VectorMath.ClosestPointOnSegment(wallBuffer[i], wallBuffer[i + 1], tr.position);
                            float   dist    = (closest - position).sqrMagnitude;

                            if (dist > wallDist * wallDist)
                            {
                                continue;
                            }

                            Vector3 tang = (wallBuffer[i + 1] - wallBuffer[i]).normalized;

                            //Using the fact that all walls are laid out clockwise (seeing from inside)
                            //Then left and right (ish) can be figured out like this
                            float dot = Vector3.Dot(dir, tang) * (1 - System.Math.Max(0, (2 * (dist / (wallDist * wallDist)) - 1)));
                            if (dot > 0)
                            {
                                wRight = System.Math.Max(wRight, dot);
                            }
                            else
                            {
                                wLeft = System.Math.Max(wLeft, -dot);
                            }
                        }

                        Vector3 norm = Vector3.Cross(Vector3.up, dir);
                        force = norm * (wRight - wLeft);

                        //Debug.DrawRay (tr.position, force, Color.cyan);
                    }

                    //Is the endpoint of the path (part) the current target point
                    bool endPointIsTarget = lastCorner && buffer.Count - tgIndex == 1;

                    if (endPointIsTarget)
                    {
                        //Use 2nd or 3rd degree motion equation to figure out acceleration to reach target in "exact" [slowdownTime] seconds

                        //Clamp to avoid divide by zero
                        if (slowdownTime < 0.001f)
                        {
                            slowdownTime = 0.001f;
                        }

                        Vector3 diff = tg - position;
                        diff.y = 0;

                        if (preciseSlowdown)
                        {
                            //{ t = slowdownTime
                            //{ diff = vt + at^2/2 + qt^3/6
                            //{ 0 = at + qt^2/2
                            //{ solve for a
                            dir = (6 * diff - 4 * slowdownTime * velocity) / (slowdownTime * slowdownTime);
                        }
                        else
                        {
                            dir = 2 * (diff - slowdownTime * velocity) / (slowdownTime * slowdownTime);
                        }
                        dir = Vector3.ClampMagnitude(dir, acceleration);

                        force *= System.Math.Min(magn / 0.5f, 1);

                        if (magn < endReachedDistance)
                        {
                            //END REACHED
                            NextPart();
                        }
                    }
                    else
                    {
                        dir *= acceleration;
                    }

                    //Debug.DrawRay (tr.position+Vector3.up, dir*3, Color.blue);

                    velocity += (dir + force * wallForce) * deltaTime;

                    if (slowWhenNotFacingTarget)
                    {
                        float dot = (Vector3.Dot(normdir, tr.forward) + 0.5f) * (1.0f / 1.5f);
                        //velocity = Vector3.ClampMagnitude (velocity, maxSpeed * Mathf.Max (dot, 0.2f) );
                        float xzmagn = Mathf.Sqrt(velocity.x * velocity.x + velocity.z * velocity.z);
                        float prevy  = velocity.y;
                        velocity.y = 0;
                        float mg = Mathf.Min(xzmagn, maxSpeed * Mathf.Max(dot, 0.2f));
                        velocity = Vector3.Lerp(tr.forward * mg, velocity.normalized * mg, Mathf.Clamp(endPointIsTarget ? (magn * 2) : 0, 0.5f, 1.0f));

                        velocity.y = prevy;
                    }
                    else
                    {
                        // Clamp magnitude on the XZ axes
                        float xzmagn = Mathf.Sqrt(velocity.x * velocity.x + velocity.z * velocity.z);
                        xzmagn = maxSpeed / xzmagn;
                        if (xzmagn < 1)
                        {
                            velocity.x *= xzmagn;
                            velocity.z *= xzmagn;
                            //Vector3.ClampMagnitude (velocity, maxSpeed);
                        }
                    }

                    //Debug.DrawLine (tr.position, tg, lastCorner ? Color.red : Color.green);


                    if (endPointIsTarget)
                    {
                        Vector3 trotdir = Vector3.Lerp(velocity, currentTargetDirection, System.Math.Max(1 - magn * 2, 0));
                        RotateTowards(trotdir);
                    }
                    else
                    {
                        RotateTowards(velocity);
                    }

                    //Applied after rotation to enable proper checks on if velocity is zero
                    velocity += deltaTime * gravity;

                    if (rvoController != null && rvoController.enabled)
                    {
                        //Use RVOController
                        tr.position = position;
                        rvoController.Move(velocity);
                    }
                    else
                    if (controller != null && controller.enabled)
                    {
                        //Use CharacterController
                        tr.position = position;
                        controller.Move(velocity * deltaTime);
                    }
                    else
                    {
                        //Use Transform
                        float lasty = position.y;
                        position += velocity * deltaTime;

                        position = RaycastPosition(position, lasty);

                        tr.position = position;
                    }
                }
                else
                {
                    if (rvoController != null && rvoController.enabled)
                    {
                        //Use RVOController
                        rvoController.Move(Vector3.zero);
                    }
                }

                if (pt is RichSpecial)
                {
                    if (!traversingSpecialPath)
                    {
                        StartCoroutine(TraverseSpecial(pt as RichSpecial));
                    }
                }
                //w.Stop();
                //Debug.Log ((w.Elapsed.TotalMilliseconds*1000));
            }
            else
            {
                if (rvoController != null && rvoController.enabled)
                {
                    //Use RVOController
                    rvoController.Move(Vector3.zero);
                }
                else
                if (controller != null && controller.enabled)
                {
                }
                else
                {
                    tr.position = RaycastPosition(tr.position, tr.position.y);
                }
            }
        }
Esempio n. 10
0
        Vector3 Snap(ABPath path, Exactness mode, bool start, out bool forceAddPoint)
        {
            var index   = start ? 0 : path.path.Count - 1;
            var node    = path.path[index];
            var nodePos = (Vector3)node.position;

            forceAddPoint = false;

            switch (mode)
            {
            case Exactness.ClosestOnNode:
                return(GetClampedPoint(nodePos, start ? path.startPoint : path.endPoint, node));

            case Exactness.SnapToNode:
                return(nodePos);

            case Exactness.Original:
            case Exactness.Interpolate:
            case Exactness.NodeConnection:
                Vector3 relevantPoint;
                if (start)
                {
                    relevantPoint = adjustStartPoint != null?adjustStartPoint() : path.originalStartPoint;
                }
                else
                {
                    relevantPoint = path.originalEndPoint;
                }

                switch (mode)
                {
                case Exactness.Original:
                    return(GetClampedPoint(nodePos, relevantPoint, node));

                case Exactness.Interpolate:
                    var clamped = GetClampedPoint(nodePos, relevantPoint, node);
                    // Adjacent node to either the start node or the end node in the path
                    var adjacentNode = path.path[Mathf.Clamp(index + (start ? 1 : -1), 0, path.path.Count - 1)];
                    return(VectorMath.ClosestPointOnSegment(nodePos, (Vector3)adjacentNode.position, clamped));

                case Exactness.NodeConnection:
                    // This code uses some tricks to avoid allocations
                    // even though it uses delegates heavily
                    // The connectionBufferAddDelegate delegate simply adds whatever node
                    // it is called with to the connectionBuffer
                    connectionBuffer            = connectionBuffer ?? new List <GraphNode>();
                    connectionBufferAddDelegate = connectionBufferAddDelegate ?? (GraphNodeDelegate)connectionBuffer.Add;

                    // Adjacent node to either the start node or the end node in the path
                    adjacentNode = path.path[Mathf.Clamp(index + (start ? 1 : -1), 0, path.path.Count - 1)];

                    // Add all neighbours of #node to the connectionBuffer
                    node.GetConnections(connectionBufferAddDelegate);
                    var bestPos  = nodePos;
                    var bestDist = float.PositiveInfinity;

                    // Loop through all neighbours
                    // Do it in reverse order because the length of the connectionBuffer
                    // will change during iteration
                    for (int i = connectionBuffer.Count - 1; i >= 0; i--)
                    {
                        var neighbour = connectionBuffer[i];

                        // Find the closest point on the connection between the nodes
                        // and check if the distance to that point is lower than the previous best
                        var closest = VectorMath.ClosestPointOnSegment(nodePos, (Vector3)neighbour.position, relevantPoint);

                        var dist = (closest - relevantPoint).sqrMagnitude;
                        if (dist < bestDist)
                        {
                            bestPos  = closest;
                            bestDist = dist;

                            // If this node is not the adjacent node
                            // then the path should go through the start node as well
                            forceAddPoint = neighbour != adjacentNode;
                        }
                    }

                    connectionBuffer.Clear();
                    return(bestPos);

                default:
                    throw new System.ArgumentException("Cannot reach this point, but the compiler is not smart enough to realize that.");
                }

#if BNICKSON_UPDATED
            case Exactness.VisibilityCheck:
                if (start)
                {
                    return(GetClampedPoint((Vector3)path.path[0].position, path.originalStartPoint, path.path[0], true));
                }
                else
                {
                    return(GetClampedPoint((Vector3)path.path[path.path.Count - 1].position, path.originalEndPoint, path.path[path.path.Count - 1], true));
                }
#endif
            default:
                throw new System.ArgumentException("Invalid mode");
            }
        }
Esempio n. 11
0
        public static float SqrDistancePointSegment(Vector3 a, Vector3 b, Vector3 p)
        {
            Vector3 a2 = VectorMath.ClosestPointOnSegment(a, b, p);

            return((a2 - p).sqrMagnitude);
        }
Esempio n. 12
0
 public static Vector3 NearestPointStrict(Vector3 lineStart, Vector3 lineEnd, Vector3 point)
 {
     return(VectorMath.ClosestPointOnSegment(lineStart, lineEnd, point));
 }
Esempio n. 13
0
        private Vector3 Snap(ABPath path, StartEndModifier.Exactness mode, bool start, out bool forceAddPoint)
        {
            int       num       = start ? 0 : (path.path.Count - 1);
            GraphNode graphNode = path.path[num];
            Vector3   vector    = (Vector3)graphNode.position;

            forceAddPoint = false;
            switch (mode)
            {
            case StartEndModifier.Exactness.SnapToNode:
                return(vector);

            case StartEndModifier.Exactness.Original:
            case StartEndModifier.Exactness.Interpolate:
            case StartEndModifier.Exactness.NodeConnection:
            {
                Vector3 vector2;
                if (start)
                {
                    vector2 = ((this.adjustStartPoint != null) ? this.adjustStartPoint() : path.originalStartPoint);
                }
                else
                {
                    vector2 = path.originalEndPoint;
                }
                switch (mode)
                {
                case StartEndModifier.Exactness.Original:
                    return(this.GetClampedPoint(vector, vector2, graphNode));

                case StartEndModifier.Exactness.Interpolate:
                {
                    Vector3   clampedPoint = this.GetClampedPoint(vector, vector2, graphNode);
                    GraphNode graphNode2   = path.path[Mathf.Clamp(num + (start ? 1 : -1), 0, path.path.Count - 1)];
                    return(VectorMath.ClosestPointOnSegment(vector, (Vector3)graphNode2.position, clampedPoint));
                }

                case StartEndModifier.Exactness.NodeConnection:
                {
                    this.connectionBuffer = (this.connectionBuffer ?? new List <GraphNode>());
                    Action <GraphNode> action;
                    if ((action = this.connectionBufferAddDelegate) == null)
                    {
                        action = new Action <GraphNode>(this.connectionBuffer.Add);
                    }
                    this.connectionBufferAddDelegate = action;
                    GraphNode graphNode2 = path.path[Mathf.Clamp(num + (start ? 1 : -1), 0, path.path.Count - 1)];
                    graphNode.GetConnections(this.connectionBufferAddDelegate);
                    Vector3 result = vector;
                    float   num2   = float.PositiveInfinity;
                    for (int i = this.connectionBuffer.Count - 1; i >= 0; i--)
                    {
                        GraphNode graphNode3   = this.connectionBuffer[i];
                        Vector3   vector3      = VectorMath.ClosestPointOnSegment(vector, (Vector3)graphNode3.position, vector2);
                        float     sqrMagnitude = (vector3 - vector2).sqrMagnitude;
                        if (sqrMagnitude < num2)
                        {
                            result        = vector3;
                            num2          = sqrMagnitude;
                            forceAddPoint = (graphNode3 != graphNode2);
                        }
                    }
                    this.connectionBuffer.Clear();
                    return(result);
                }
                }
                throw new ArgumentException("Cannot reach this point, but the compiler is not smart enough to realize that.");
            }

            case StartEndModifier.Exactness.ClosestOnNode:
                return(this.GetClampedPoint(vector, start ? path.startPoint : path.endPoint, graphNode));

            default:
                throw new ArgumentException("Invalid mode");
            }
        }
Esempio n. 14
0
        private Vector3 Snap(ABPath path, Exactness mode, bool start, out bool forceAddPoint)
        {
            Vector3   originalEndPoint;
            GraphNode node2;
            int       num      = !start ? (path.path.Count - 1) : 0;
            GraphNode hint     = path.path[num];
            Vector3   position = (Vector3)hint.position;

            forceAddPoint = false;
            switch (mode)
            {
            case Exactness.SnapToNode:
                return(position);

            case Exactness.Original:
            case Exactness.Interpolate:
            case Exactness.NodeConnection:
                if (!start)
                {
                    originalEndPoint = path.originalEndPoint;
                    break;
                }
                originalEndPoint = (this.adjustStartPoint == null) ? path.originalStartPoint : this.adjustStartPoint();
                break;

            case Exactness.ClosestOnNode:
                return(this.GetClampedPoint(position, !start ? path.endPoint : path.startPoint, hint));

            default:
                throw new ArgumentException("Invalid mode");
            }
            switch (mode)
            {
            case Exactness.Original:
                return(this.GetClampedPoint(position, originalEndPoint, hint));

            case Exactness.Interpolate:
            {
                Vector3 point = this.GetClampedPoint(position, originalEndPoint, hint);
                node2 = path.path[Mathf.Clamp(num + (!start ? -1 : 1), 0, path.path.Count - 1)];
                return(VectorMath.ClosestPointOnSegment(position, (Vector3)node2.position, point));
            }

            case Exactness.NodeConnection:
            {
                if (this.connectionBuffer == null)
                {
                }
                this.connectionBuffer = new List <GraphNode>();
                if (this.connectionBufferAddDelegate == null)
                {
                }
                this.connectionBufferAddDelegate = new GraphNodeDelegate(this.connectionBuffer.Add);
                node2 = path.path[Mathf.Clamp(num + (!start ? -1 : 1), 0, path.path.Count - 1)];
                hint.GetConnections(this.connectionBufferAddDelegate);
                Vector3 vector4          = position;
                float   positiveInfinity = float.PositiveInfinity;
                for (int i = this.connectionBuffer.Count - 1; i >= 0; i--)
                {
                    GraphNode node3        = this.connectionBuffer[i];
                    Vector3   vector5      = VectorMath.ClosestPointOnSegment(position, (Vector3)node3.position, originalEndPoint);
                    Vector3   vector6      = vector5 - originalEndPoint;
                    float     sqrMagnitude = vector6.sqrMagnitude;
                    if (sqrMagnitude < positiveInfinity)
                    {
                        vector4          = vector5;
                        positiveInfinity = sqrMagnitude;
                        forceAddPoint    = node3 != node2;
                    }
                }
                this.connectionBuffer.Clear();
                return(vector4);
            }
            }
            throw new ArgumentException("Cannot reach this point, but the compiler is not smart enough to realize that.");
        }