示例#1
0
    /// <summary>
    /// This method calculates and caches rotation, distance, curveLeft, and curveRight.
    /// </summary>
    /// <param name="shouldRipple">Whether or not to tell neighbors to also recalc and cache. Rippling does not recurse, and so it only affects left and right.</param>
    void CacheData(bool shouldRipple)
    {
        cameraDataNode = GetComponent <CameraDataNode>();
        angleCurveIn   = angleCurveOut = percentCurveIn = percentCurveOut = length = 0;
        curveCenter    = curveIn = curveOut = transform.position;

        if (shouldRipple)
        {
            if (left)
            {
                left.CacheData(false);       // ripple outwards
            }
            if (right)
            {
                right.CacheData(false);        // ripple outwards
            }
        }

        if (right)
        {
            // if there's a node to the right, use it to calculate and cache values for length & rotationYaw
            Vector3 diff = right.transform.position - transform.position;
            length = diff.magnitude;
            float angle = Mathf.Atan2(-diff.z, diff.x) * Mathf.Rad2Deg;
            rotationYaw = Quaternion.Euler(0, angle, 0);
        }

        if (left && right)
        {
            clampedCurveRadius = curveRadius;

            Vector3 p1 = left.transform.position;
            Vector3 p2 = transform.position;
            Vector3 p3 = right.transform.position;

            Vector3 leftDiff  = OverwriteY(p1 - p2);  // get the FLAT vector to left
            Vector3 rightDiff = OverwriteY(p3 - p2);  // get the FLAT vector to right

            Vector3 leftAxis  = leftDiff.normalized;  // direction to left
            Vector3 rightAxis = rightDiff.normalized; // direction to right

            // the YAW to angle1 and angle2
            float angleToP3 = Mathf.Atan2(rightDiff.z, rightDiff.x); // YAW from this to right
            float angleToP1 = Mathf.Atan2(leftDiff.z, leftDiff.x);   // YAW from this to left
            angleToP3 = AngleWrapFromTo(angleToP3, angleToP1);       // wrap the values into the same 180-degree arc

            if (Mathf.Abs(angleToP1 - angleToP3) >= Mathf.PI)        // if in a straight line... don't try to curve.
            {
                clampedCurveRadius = 0;
                return;
            }

            float angleBetween  = Mathf.Abs(angleToP3 - angleToP1) / 2; // save a step, and half the difference
            float angleToCenter = (angleToP3 + angleToP1) / 2;          // angle from p2 to center... use the average of our previous two angles

            float maxAdjacent = Mathf.Min(leftDiff.magnitude, rightDiff.magnitude) * 0.5f;
            float cos         = Mathf.Cos(angleBetween);
            float maxDistance = maxAdjacent / cos;
            float disToCenter = curveRadius / Mathf.Sin(angleBetween);

            if (maxDistance < disToCenter)
            {
                clampedCurveRadius *= maxDistance / disToCenter;
                disToCenter         = maxDistance;
            }

            Vector3 axisToCenter = new Vector3(Mathf.Cos(angleToCenter), 0, Mathf.Sin(angleToCenter));
            curveCenter = transform.position + axisToCenter * disToCenter;

            float disToInOut = cos * disToCenter;               // use trig to find FLAT distance to curveIn and curveOut

            percentCurveIn  = disToInOut / leftDiff.magnitude;  // percent of the way from p2 to p1
            percentCurveOut = disToInOut / rightDiff.magnitude; // percent of the way from p2 to p3

            curveIn  = Vector3.Lerp(p2, p1, percentCurveIn);
            curveOut = Vector3.Lerp(p2, p3, percentCurveOut);

            angleCurveIn  = CurveAngleTo(curveIn);
            angleCurveOut = CurveAngleTo(curveOut);
            angleCurveOut = AngleWrapFromTo(angleCurveOut, angleCurveIn);
        }
    }