SplineCamera.cpp 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. // ----------------------------------------------------------------
  2. // From Game Programming in C++ by Sanjay Madhav
  3. // Copyright (C) 2017 Sanjay Madhav. All rights reserved.
  4. //
  5. // Released under the BSD License
  6. // See LICENSE in root directory for full details.
  7. // ----------------------------------------------------------------
  8. #include "SplineCamera.h"
  9. #include "Actor.h"
  10. Vector3 Spline::Compute(size_t startIdx, float t) const
  11. {
  12. // Check if startIdx is out of bounds
  13. if (startIdx >= mControlPoints.size())
  14. {
  15. return mControlPoints.back();
  16. }
  17. else if (startIdx == 0)
  18. {
  19. return mControlPoints[startIdx];
  20. }
  21. else if (startIdx + 2 >= mControlPoints.size())
  22. {
  23. return mControlPoints[startIdx];
  24. }
  25. // Get p0 through p3
  26. Vector3 p0 = mControlPoints[startIdx - 1];
  27. Vector3 p1 = mControlPoints[startIdx];
  28. Vector3 p2 = mControlPoints[startIdx + 1];
  29. Vector3 p3 = mControlPoints[startIdx + 2];
  30. // Compute position according to Catmull-Rom equation
  31. Vector3 position = 0.5f * ((2.0f * p1) + (-1.0f * p0 + p2) * t +
  32. (2.0f * p0 - 5.0f * p1 + 4.0f * p2 - p3) * t * t +
  33. (-1.0f * p0 + 3.0f * p1 - 3.0f * p2 + p3) * t * t * t);
  34. return position;
  35. }
  36. SplineCamera::SplineCamera(Actor* owner)
  37. :CameraComponent(owner)
  38. ,mIndex(1)
  39. ,mT(0.0f)
  40. ,mSpeed(0.5f)
  41. ,mPaused(true)
  42. {
  43. }
  44. void SplineCamera::Update(float deltaTime)
  45. {
  46. CameraComponent::Update(deltaTime);
  47. // Update t value
  48. if (!mPaused)
  49. {
  50. mT += mSpeed * deltaTime;
  51. // Advance to the next control point if needed.
  52. // This assumes speed isn't so fast that you jump past
  53. // multiple control points in one frame.
  54. if (mT >= 1.0f)
  55. {
  56. // Make sure we have enough points to advance the path
  57. if (mIndex < mPath.GetNumPoints() - 3)
  58. {
  59. mIndex++;
  60. mT = mT - 1.0f;
  61. }
  62. else
  63. {
  64. // Path's done, so pause
  65. mPaused = true;
  66. }
  67. }
  68. }
  69. // Camera position is the spline at the current t/index
  70. Vector3 cameraPos = mPath.Compute(mIndex, mT);
  71. // Target point is just a small delta ahead on the spline
  72. Vector3 target = mPath.Compute(mIndex, mT + 0.01f);
  73. // Assume spline doesn't flip upside-down
  74. const Vector3 up = Vector3::UnitZ;
  75. Matrix4 view = Matrix4::CreateLookAt(cameraPos, target, up);
  76. SetViewMatrix(view);
  77. }
  78. void SplineCamera::Restart()
  79. {
  80. mIndex = 1;
  81. mT = 0.0f;
  82. mPaused = false;
  83. }