|
@@ -0,0 +1,113 @@
|
|
|
+#include "core/Frustum.h"
|
|
|
+
|
|
|
+#include <math.h>
|
|
|
+#include <stdio.h>
|
|
|
+
|
|
|
+#include "core/Utility.h"
|
|
|
+
|
|
|
+#define CV30 (&(CoreVector3){0})
|
|
|
+#define CV4(a, b, c, d) ((CoreVector4){{a, b, c, d}})
|
|
|
+
|
|
|
+CoreFrustum* coreInitFrustum(CoreFrustum* f, float fieldOfView, float nearClip,
|
|
|
+ float farClip) {
|
|
|
+ for(size_t i = 0; i < CORE_ARRAY_LENGTH(f->planes); i++) {
|
|
|
+ f->planes[i] = (CorePlane){0};
|
|
|
+ }
|
|
|
+ f->tan = tanf(coreDegreeToRadian(fieldOfView) * 0.5f);
|
|
|
+ f->nearClip = nearClip;
|
|
|
+ f->farClip = farClip;
|
|
|
+
|
|
|
+ float diff = 1.0f / (nearClip - farClip);
|
|
|
+ f->projection.data[0] = CV4(0.0f, 0.0f, 0.0f, 0.0f);
|
|
|
+ f->projection.data[1] = CV4(0.0f, 1.0f / f->tan, 0.0f, 0.0f);
|
|
|
+ f->projection.data[2] = CV4(0.0f, 0.0f, (nearClip + farClip) * diff,
|
|
|
+ (2.0f * nearClip * farClip) * diff);
|
|
|
+ f->projection.data[3] = CV4(0.0f, 0.0f, -1.0f, 0.0f);
|
|
|
+ return f;
|
|
|
+}
|
|
|
+
|
|
|
+const CoreMatrix* coreUpdateProjection(CoreFrustum* f,
|
|
|
+ const CoreIntVector2* size) {
|
|
|
+ f->projection.data[0] =
|
|
|
+ CV4((float)size->data[1] / (f->tan * (float)size->data[0]), 0.0f, 0.0f,
|
|
|
+ 0.0f);
|
|
|
+ return &f->projection;
|
|
|
+}
|
|
|
+
|
|
|
+void coreUpdateFrustumPlanes(CoreFrustum* f, const CoreVector3* pos,
|
|
|
+ const CoreVector3* right, const CoreVector3* up,
|
|
|
+ const CoreVector3* front,
|
|
|
+ const CoreIntVector2* size) {
|
|
|
+ float aspect = (float)size->data[0] / (float)size->data[1];
|
|
|
+
|
|
|
+ float hNearHeight = f->tan * f->nearClip;
|
|
|
+ float hNearWidth = hNearHeight * aspect;
|
|
|
+
|
|
|
+ float hFarHeight = f->tan * f->farClip;
|
|
|
+ float hFarWidth = hFarHeight * aspect;
|
|
|
+
|
|
|
+ CoreVector3 fCenter;
|
|
|
+ coreAddV3(&fCenter, pos, coreMulV3F(CV30, front, f->farClip));
|
|
|
+ CoreVector3 upFar;
|
|
|
+ coreMulV3F(&upFar, up, hFarHeight);
|
|
|
+ CoreVector3 rightFar;
|
|
|
+ coreMulV3F(&rightFar, right, hFarWidth);
|
|
|
+
|
|
|
+ CoreVector3 fTopLeft;
|
|
|
+ coreAddV3(&fTopLeft, &fCenter, coreSubV3(CV30, &upFar, &rightFar));
|
|
|
+ CoreVector3 fTopRight;
|
|
|
+ coreAddV3(&fTopRight, &fCenter, coreAddV3(CV30, &upFar, &rightFar));
|
|
|
+ CoreVector3 fBottomRight;
|
|
|
+ coreSubV3(&fBottomRight, &fCenter, coreSubV3(CV30, &upFar, &rightFar));
|
|
|
+
|
|
|
+ CoreVector3 nCenter;
|
|
|
+ coreAddV3(&nCenter, pos, coreMulV3F(CV30, front, f->nearClip));
|
|
|
+ CoreVector3 upNear;
|
|
|
+ coreMulV3F(&upNear, up, hNearHeight);
|
|
|
+ CoreVector3 rightNear;
|
|
|
+ coreMulV3F(&rightNear, right, hNearWidth);
|
|
|
+
|
|
|
+ CoreVector3 nTopLeft;
|
|
|
+ coreAddV3(&nTopLeft, &nCenter, coreSubV3(CV30, &upNear, &rightNear));
|
|
|
+ CoreVector3 nBottomLeft;
|
|
|
+ coreSubV3(&nBottomLeft, &nCenter, coreAddV3(CV30, &upNear, &rightNear));
|
|
|
+ CoreVector3 nBottomRight;
|
|
|
+ coreSubV3(&nBottomRight, &nCenter, coreSubV3(CV30, &upNear, &rightNear));
|
|
|
+
|
|
|
+ coreInitPlane(f->planes + 0, &nBottomRight, &nTopLeft,
|
|
|
+ &nBottomLeft); // n plane
|
|
|
+ coreInitPlane(f->planes + 1, &fTopRight, &fBottomRight,
|
|
|
+ &fTopLeft); // f plane
|
|
|
+ coreInitPlane(f->planes + 2, &nBottomRight, &nBottomLeft,
|
|
|
+ &fBottomRight); // bottom plane
|
|
|
+ coreInitPlane(f->planes + 3, &fTopLeft, &nTopLeft, &fTopRight); // top plane
|
|
|
+ coreInitPlane(f->planes + 4, &nBottomLeft, &nTopLeft,
|
|
|
+ &fTopLeft); // left plane
|
|
|
+ coreInitPlane(f->planes + 5, &fBottomRight, &fTopRight,
|
|
|
+ &nBottomRight); // right plane
|
|
|
+}
|
|
|
+
|
|
|
+bool coreIsInsideFrustum(const CoreFrustum* f, const CoreVector3* pos) {
|
|
|
+ for(size_t i = 0; i < CORE_ARRAY_LENGTH(f->planes); i++) {
|
|
|
+ if(coreSignedDistance(f->planes + i, pos) < 0.0f) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+}
|
|
|
+
|
|
|
+bool coreIsInsideFrustumRadius(const CoreFrustum* f, const CoreVector3* pos,
|
|
|
+ float radius) {
|
|
|
+ for(size_t i = 0; i < CORE_ARRAY_LENGTH(f->planes); i++) {
|
|
|
+ if(coreSignedDistance(f->planes + i, pos) < -radius) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+}
|
|
|
+
|
|
|
+size_t coreToStringFrustum(const CoreFrustum* f, char* buffer, size_t n) {
|
|
|
+ int w = snprintf(buffer, n, "(tan = %.3f, nearClip = %.3f, farClip = %.3f)",
|
|
|
+ (double)f->tan, (double)f->nearClip, (double)f->farClip);
|
|
|
+ return w < 0 ? 0 : (size_t)w;
|
|
|
+}
|