//Math stuff to generate the spline points private void GenerateSplinePoints() { InitializeProperties(); Vector3 p0, p1; //Start point, end point Vector3 m0, m1; //Tangents // First for loop goes through each individual control point and connects it to the next, so 0-1, 1-2, 2-3 and so on int closedAdjustment = 1; for (int currentPoint = 0; currentPoint < controlPoints.Length - closedAdjustment; currentPoint++) { p0 = controlPoints[currentPoint]; p1 = controlPoints[currentPoint + 1]; // m0 // Tangent M[k] = (P[k+1] - P[k-1]) / 2 if (currentPoint == 0) { m0 = p1 - p0; } else { m0 = p1 - controlPoints[currentPoint - 1]; } // m1 if (currentPoint < controlPoints.Length - 2) { m1 = controlPoints[(currentPoint + 2) % controlPoints.Length] - p0; } else { m1 = p1 - p0; } m0 *= 0.5f; //Doing this here instead of in every single above statement m1 *= 0.5f; float pointStep = 1.0f / resolution; // Creates [resolution] points between this control point and the next for (int tesselatedPoint = 0; tesselatedPoint < resolution; tesselatedPoint++) { float t = tesselatedPoint * pointStep; CatmullRomPoint point = Evaluate(p0, p1, m0, m1, t); splinePoints[currentPoint * resolution + tesselatedPoint] = point; } } }
//Math stuff to generate the spline points private void GenerateSplinePoints() { InitializeProperties(); Vector3 p0, p1; //Start point, end point Vector3 m0, m1; //Tangents // First for loop goes through each individual control point and connects it to the next, so 0-1, 1-2, 2-3 and so on int closedAdjustment = closedLoop ? 0 : 1; for (int currentPoint = 0; currentPoint < controlPoints.Length - closedAdjustment; currentPoint++) { bool closedLoopFinalPoint = (closedLoop && currentPoint == controlPoints.Length - 1); p0 = controlPoints[currentPoint]; if (closedLoopFinalPoint) { p1 = controlPoints[0]; } else { p1 = controlPoints[currentPoint + 1]; } // m0 if (currentPoint == 0) // Tangent M[k] = (P[k+1] - P[k-1]) / 2 { if (closedLoop) { m0 = p1 - controlPoints[controlPoints.Length - 1]; } else { m0 = p1 - p0; } } else { m0 = p1 - controlPoints[currentPoint - 1]; } // m1 if (closedLoop) { if (currentPoint == controlPoints.Length - 1) //Last point case { m1 = controlPoints[(currentPoint + 2) % controlPoints.Length] - p0; } else if (currentPoint == 0) //First point case { m1 = controlPoints[currentPoint + 2] - p0; } else { m1 = controlPoints[(currentPoint + 2) % controlPoints.Length] - p0; } } else { if (currentPoint < controlPoints.Length - 2) { m1 = controlPoints[(currentPoint + 2) % controlPoints.Length] - p0; } else { m1 = p1 - p0; } } m0 *= 0.5f; //Doing this here instead of in every single above statement m1 *= 0.5f; float pointStep = 1.0f / resolution; if ((currentPoint == controlPoints.Length - 2 && !closedLoop) || closedLoopFinalPoint) //Final point { pointStep = 1.0f / (resolution - 1); // last point of last segment should reach p1 } // Creates [resolution] points between this control point and the next for (int tesselatedPoint = 0; tesselatedPoint < resolution; tesselatedPoint++) { float t = tesselatedPoint * pointStep; CatmullRomPoint point = Evaluate(p0, p1, m0, m1, t); splinePoints[currentPoint * resolution + tesselatedPoint] = point; } } }
//Evaluates curve at t[0, 1]. Returns point/normal/tan struct. [0, 1] means clamped between 0 and 1. public static void Evaluate(Vector3 start, Vector3 end, Vector3 tanPoint1, Vector3 tanPoint2, float t, out CatmullRomPoint result) { result.position = CalculatePosition(start, end, tanPoint1, tanPoint2, t); result.tangent = CalculateTangent(start, end, tanPoint1, tanPoint2, t); result.normal = NormalFromTangent(result.tangent); }