// ======================================================================================================================== GETTERS internal SplineLerpResult Lerp(SplineLerpQuery query) { if (spline != null) { return(spline.Lerp(transform, query)); } return(new SplineLerpResult()); }
// ======================================================================================================================== 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)); }
// ======================================================================================================================== 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); }