Frustum.c 3.1 KB

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