Frustum.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. #include "core/Frustum.h"
  2. #include <math.h>
  3. #include "core/Generic.h"
  4. void initFrustum(Frustum* f, float fieldOfView, float nearClip, float farClip) {
  5. f->tan = tanf(fieldOfView * 0.5f);
  6. f->nearClip = nearClip;
  7. f->farClip = farClip;
  8. float diff = 1.0f / (nearClip - farClip);
  9. f->projection.data[0] = V(0.0f, 0.0f, 0.0f, 0.0f);
  10. f->projection.data[1] = V(0.0f, 1.0f / f->tan, 0.0f, 0.0f);
  11. f->projection.data[2] =
  12. V(0.0f, 0.0f, (nearClip + farClip) * diff,
  13. (2.0f * nearClip * farClip) * diff);
  14. f->projection.data[3] = V(0.0f, 0.0f, -1.0f, 0.0f);
  15. }
  16. const Matrix* updateProjection(Frustum* f, const IntVector2* size) {
  17. float x = (float)size->y / (f->tan * (float)size->x);
  18. f->projection.data[0] = V(x, 0.0f, 0.0f, 0.0f);
  19. return &f->projection;
  20. }
  21. void updateFrustumPlanes(
  22. Frustum* f, const Vector3* pos, const Vector3* right, const Vector3* up,
  23. const Vector3* front, const IntVector2* size) {
  24. float aspect = (float)size->x / (float)size->y;
  25. float hNearHeight = f->tan * f->nearClip;
  26. float hNearWidth = hNearHeight * aspect;
  27. float hFarHeight = f->tan * f->farClip;
  28. float hFarWidth = hFarHeight * aspect;
  29. Vector3 fCenter;
  30. add(&fCenter, pos, mul(front, f->farClip));
  31. Vector3 upFar;
  32. mul(&upFar, up, hFarHeight);
  33. Vector3 rightFar;
  34. mul(&rightFar, right, hFarWidth);
  35. Vector3 fTopLeft;
  36. add(&fTopLeft, &fCenter, sub(&upFar, &rightFar));
  37. Vector3 fTopRight;
  38. add(&fTopRight, &fCenter, add(&upFar, &rightFar));
  39. Vector3 fBottomRight;
  40. sub(&fBottomRight, &fCenter, sub(&upFar, &rightFar));
  41. Vector3 nCenter;
  42. add(&nCenter, pos, mul(front, f->nearClip));
  43. Vector3 upNear;
  44. mul(&upNear, up, hNearHeight);
  45. Vector3 rightNear;
  46. mul(&rightNear, right, hNearWidth);
  47. Vector3 nTopLeft;
  48. add(&nTopLeft, &nCenter, sub(&upNear, &rightNear));
  49. Vector3 nBottomLeft;
  50. sub(&nBottomLeft, &nCenter, add(&upNear, &rightNear));
  51. Vector3 nBottomRight;
  52. sub(&nBottomRight, &nCenter, sub(&upNear, &rightNear));
  53. // near plane
  54. initPlane(f->planes + 0, &nBottomRight, &nTopLeft, &nBottomLeft);
  55. // far plane
  56. initPlane(f->planes + 1, &fTopRight, &fBottomRight, &fTopLeft);
  57. // bottom plane
  58. initPlane(f->planes + 2, &nBottomRight, &nBottomLeft, &fBottomRight);
  59. // top plane
  60. initPlane(f->planes + 3, &fTopLeft, &nTopLeft, &fTopRight);
  61. // left plane
  62. initPlane(f->planes + 4, &nBottomLeft, &nTopLeft, &fTopLeft);
  63. // right plane
  64. initPlane(f->planes + 5, &fBottomRight, &fTopRight, &nBottomRight);
  65. }
  66. bool isInsideFrustum(const Frustum* f, const Vector3* pos) {
  67. for(size_t i = 0; i < ARRAY_LENGTH(f->planes); i++) {
  68. if(signedDistance(f->planes + i, pos) < 0.0f) {
  69. return false;
  70. }
  71. }
  72. return true;
  73. }
  74. bool isInsideFrustumRadius(const Frustum* f, const Vector3* pos, float radius) {
  75. for(size_t i = 0; i < ARRAY_LENGTH(f->planes); i++) {
  76. if(signedDistance(f->planes + i, pos) < -radius) {
  77. return false;
  78. }
  79. }
  80. return true;
  81. }