예제 #1
0
        // ======================================================================================================================== GETTERS

        internal SplineLerpResult Lerp(SplineLerpQuery query)
        {
            if (spline != null)
            {
                return(spline.Lerp(transform, query));
            }
            return(new SplineLerpResult());
        }
예제 #2
0
        // ======================================================================================================================== HELPERS

        SplineLerpResult FollowLerp(float time)
        {
            if (!playing)
            {
                return(new SplineLerpResult());
            }
            SplineLerpQuery query = new SplineLerpQuery();

            float duration = movementDuration + movementPause;
            float x        = time * (movementType == SplineMovementType.PingPong ? 2 : 1);
            float t        = Mathf.Clamp01(Mathf.Repeat(x, duration) / movementDuration);

            switch (movementType)
            {
            case SplineMovementType.Forward:
                query.t = t;
                break;

            case SplineMovementType.Backward:
                query.t = 1 - t;
                break;

            case SplineMovementType.PingPong:
                if (Mathf.Repeat(time, duration) / duration < 0.5f)
                {
                    query.t = t;
                }
                else
                {
                    query.t = 1 - t;
                }
                break;
            }

            query.movementSmoothing = movementSmoothing;
            query.valueSmoothing    = rotationSmoothing;

            return(wrapper.Lerp(query));
        }
예제 #3
0
        // ======================================================================================================================== GETTERS

        // This is the crucial function for splines: the one which lets outside objects query for interpolated data.
        // To do so, they pass in a root transform to use as the owner of the spline, as well as a SplineLerpQuery,
        // which contains the desired parametrized time [0-1] on the spline and some additional interpolation settings.
        // This function then returns a SplineLerpResult which contains all of the interpolated information.

        internal SplineLerpResult Lerp(Transform root, SplineLerpQuery query)
        {
            // Failsafe - if this spline is degenerate, just return the first point and don't do any other interpolation

            if (totalLength == 0)
            {
                SplineLerpResult degenerateResult = new SplineLerpResult();
                degenerateResult.worldPosition = Matrix4x4.TRS(root.position, root.rotation, root.lossyScale).MultiplyPoint3x4(vertices[0, 0]);
                return(degenerateResult);
            }

            // First, we need to find the section on the spline that contains the parametrized time being queried for.
            // Convert the parametrized time given into a time-position within the total length of the spline

            float p = Mathf.Clamp01(query.t) * totalLength;

            // If the query says to smooth along the entire spline, do that now

            if (query.movementSmoothing == SplineMovementSmoothing.WholeSpline)
            {
                p = Mathf.SmoothStep(0, totalLength, p / totalLength);
            }

            // Now, find the section of the spline that corresponds to that time-position, by using the total lengths
            // of each section. In doing so, make the time-position p local to that section

            int section;

            for (section = 0; section < sectionCount - 1; section++)
            {
                if (p > lengths[section, segmentCount - 1])
                {
                    p -= lengths[section, segmentCount - 1];
                }
                else
                {
                    break;
                }
            }

            // Now that p is located within a section (between two SplineNodes), we need to do more parameter calculation.
            // v is the [0-1] parameter which will lerp the non-positional values between the nodes, with optional value smoothing if the query says to
            // p is also updated so that it is smoothed between the nodes if the query says to

            float v = p / lengths[section, segmentCount - 1];

            if (query.movementSmoothing == SplineMovementSmoothing.BetweenNodes)
            {
                p = Mathf.SmoothStep(0, lengths[section, segmentCount - 1], v);
            }
            if (query.valueSmoothing)
            {
                v = Mathf.SmoothStep(0, 1, v);
            }

            // Finally, find the segment within the found section that corresponds to p, by using the
            // cumulative segment lengths. In doing so, make p local to that segment

            int segment;

            for (segment = 0; segment < segmentCount - 1; segment++)
            {
                float l1 = lengths[section, segment];
                float l2 = lengths[section, segment + 1];
                float r  = (p - l1) / (l2 - l1);

                if (r >= 0 && r <= 1 || segment == segmentCount - 2)
                {
                    p = r;
                    break;
                }
            }

            // Now that we finally know where we are in terms of sections and segments, we can do the interpolation.

            SplineLerpResult result = new SplineLerpResult();

            // Position

            Vector3   localPos = Vector3.Lerp(vertices[section, segment], vertices[section, segment + 1], p);
            Matrix4x4 m        = Matrix4x4.TRS(root.position, root.rotation, root.lossyScale);

            result.worldPosition = m.MultiplyPoint3x4(localPos);

            // Values
            SplineNode s = nodes[section];
            SplineNode e = nodes[section + 1];

            result.worldRotation = Vector3.Lerp(s.worldOrientation, e.worldOrientation, v);
            result.fieldOfView   = Mathf.Lerp(s.fieldOfView, e.fieldOfView, v);
            result.tangent       = (Tangent(vertices, section, segment, segmentCount, 0)
                                    + Tangent(vertices, section, segment, segmentCount, 1)) / 2;
            result.section = section;
            result.segment = segment;

            return(result);
        }