Catmull-Rom Spline C++ (uniform spacing, unlimited points)


SUBMITTED BY: Guest

DATE: Nov. 12, 2013, 2:44 a.m.

FORMAT: Text only

SIZE: 3.9 kB

HITS: 844

  1. struct DistanceTableEntry
  2. {
  3. f32 t;
  4. f32 distance;
  5. };
  6. //The base Catmull-Rom evaluation function which requires 4 points
  7. void CatmullRom_Evaluate(vec3* pOut_result, const vec3* p0, const vec3* p1, const vec3* p2, const vec3* p3, f32 t)
  8. {
  9. const f32 c0 = ((-t + 2.0f) * t - 1.0f) * t * 0.5f;
  10. const f32 c1 = (((3.0f * t - 5.0f) * t) * t + 2.0f) * 0.5f;
  11. const f32 c2 = ((-3.0f * t + 4.0f) * t + 1.0f) * t * 0.5f;
  12. const f32 c3 = ((t - 1.0f) * t * t) * 0.5f;
  13. ScaleVec3(pOut_result, p0, c0);
  14. AddScaledVec3_Self(pOut_result, p1, c1);
  15. AddScaledVec3_Self(pOut_result, p2, c2);
  16. AddScaledVec3_Self(pOut_result, p3, c3);
  17. }
  18. //Evaluates a curve with any number of points using the Catmull-Rom method
  19. void CatmullRom_EvaluateCurve(vec3* pOut_result, const vec3* pPoints, u32 numPoints, f32 t)
  20. {
  21. const f32 index1F = t * (f32)(numPoints-1);
  22. const u32 index1 = (u32)index1F;
  23. const f32 remainder = index1F - (f32)index1;
  24. const u32 index0 = MaxS32(0,index1 - 1);
  25. const u32 index2 = index1 + 1;
  26. const u32 index3 = MinS32(numPoints-1,index1 + 2);
  27. const vec3* p0 = &pPoints[index0];
  28. const vec3* p1 = &pPoints[index1];
  29. const vec3* p2 = &pPoints[index2];
  30. const vec3* p3 = &pPoints[index3];
  31. CatmullRom_Evaluate(pOut_result, p0, p1, p2, p3, remainder);
  32. }
  33. //Creates the specified number of points along a Catmull-Rom spline (non-uniform)
  34. void CatmullRom_CreatePoints(vec3* pOut_pointArray, u32 numPointsDesired, const vec3* pCurvePoints, u32 numCurvePoints)
  35. {
  36. const f32 numPointsDesiredMin1 = (f32)(numPointsDesired-1);
  37. for(u32 i=0; i<numPointsDesired; ++i)
  38. {
  39. const f32 t = (f32)i/numPointsDesiredMin1;
  40. CatmullRom_EvaluateCurve(&pOut_pointArray[i],pCurvePoints,numCurvePoints,t);
  41. }
  42. }
  43. //Creates the specified number of points along a Catmull-Rom spline (uniformly spaced)
  44. void CatmullRom_CreatePoints_Uniform(vec3* pOut_pointArray, u32 numPointsDesired, const vec3* pCurvePoints, u32 numCurvePoints, DistanceTableEntry* pDistTable, u32 numDistTableEntries)
  45. {
  46. const f32 numPointsDesiredMin1 = (f32)(numPointsDesired-1);
  47. const f32 totalLength = pDistTable[numDistTableEntries-1].distance;
  48. for(u32 i=0; i<numPointsDesired; ++i)
  49. {
  50. const f32 distT = (f32)i/(f32)numPointsDesiredMin1;
  51. const f32 distance = distT * totalLength;
  52. const f32 t = Curve_TValueFromDist(distance,pDistTable,numDistTableEntries);
  53. CatmullRom_EvaluateCurve(&pOut_pointArray[i],pCurvePoints,numCurvePoints,t);
  54. }
  55. }
  56. //Creates a distance table used by Curve_TValueFromDist below
  57. void Curve_CreateDistanceTable(DistanceTableEntry* pOut_result, const vec3* pPoints, u32 numPoints)
  58. {
  59. const u32 numPointsMin1 = numPoints-1;
  60. f32 distSoFar = 0.0f;
  61. pOut_result[0].distance = 0.0f;
  62. pOut_result[0].t = 0.0f;
  63. for(u32 i=1; i<numPoints; ++i)
  64. {
  65. const f32 dist = DistVec3(&pPoints[i-1], &pPoints[i]);
  66. distSoFar += dist;
  67. DistanceTableEntry* pEntry = &pOut_result[i];
  68. pEntry->distance = distSoFar;
  69. pEntry->t = (f32)i/(f32)numPointsMin1;
  70. }
  71. }
  72. //When evaluating a spline, pass in a dist (0 to max) to get a T value to pass in
  73. f32 Curve_TValueFromDist(f32 dist, DistanceTableEntry* pDistTable, u32 numDistTableEntries)
  74. {
  75. for(s32 i=numDistTableEntries-2; i != -1; --i)
  76. {
  77. DistanceTableEntry* pEntry = &pDistTable[i];
  78. if(dist >= pEntry->distance)
  79. {
  80. if(i == numDistTableEntries-1)
  81. {
  82. return 1.0f;
  83. }
  84. else
  85. {
  86. DistanceTableEntry* pNextEntry = &pDistTable[i+1];
  87. const f32 lerpT = (dist-pEntry->distance)/(pNextEntry->distance-pEntry->distance);
  88. const f32 t = Lerp(pEntry->t, pNextEntry->t, lerpT);
  89. return t;
  90. }
  91. }
  92. }
  93. return 0.0f;
  94. }

comments powered by Disqus