NSMBW-Decomp
A decompilation of New Super Mario Bros. Wii
Loading...
Searching...
No Matches
m_frustum.cpp
1#include <game/mLib/m_frustum.hpp>
2#include <math.h>
3
4void mFrustum_c::set(f32 fovy, f32 aspect, f32 near, f32 far, const mMtx_c &cameraMtx) {
5 f32 tangent = tan(NW4R_MATH_FIDX_TO_RAD(NW4R_MATH_DEG_TO_FIDX(fovy * 0.5f)));
6 f32 top = tangent * near;
7 f32 right = top * aspect;
8 set(top, -top, -right, right, near, far, cameraMtx, false);
9}
10
11void mFrustum_c::set(f32 top, f32 bottom, f32 left, f32 right, f32 near, f32 far, const mMtx_c &cameraMtx, bool orthographic) {
12 mVec3_c eyePos;
13 mMtx_c invCameraMtx;
14 mVec3_c pts[POINT_MAX];
15
16 PSMTXInverse(cameraMtx, invCameraMtx);
17 PSMTXCopy(cameraMtx, mCamMtx);
18
19 mNearZ = -near;
20 mFarZ = -far;
21
22 pts[POINT_NEAR_TL].set(left, top, -near);
23 pts[POINT_NEAR_TR].set(right, top, -near);
24 pts[POINT_NEAR_BR].set(right, bottom, -near);
25 pts[POINT_NEAR_BL].set(left, bottom, -near);
26
27 pts[POINT_FAR_TL].z = -far;
28 pts[POINT_FAR_TR].z = -far;
29 pts[POINT_FAR_BR].z = -far;
30 pts[POINT_FAR_BL].z = -far;
31
32 if (orthographic) {
33 pts[POINT_FAR_TL].x = left;
34 pts[POINT_FAR_TL].y = top;
35 pts[POINT_FAR_TR].x = right;
36 pts[POINT_FAR_TR].y = top;
37 pts[POINT_FAR_BR].x = right;
38 pts[POINT_FAR_BR].y = bottom;
39 pts[POINT_FAR_BL].x = left;
40 pts[POINT_FAR_BL].y = bottom;
41
42 mPlaneL.Set(&pts[POINT_NEAR_BL], &pts[POINT_FAR_BL], &pts[POINT_NEAR_TL]);
43 mPlaneR.Set(&pts[POINT_NEAR_TR], &pts[POINT_FAR_TR], &pts[POINT_NEAR_BR]);
44 mPlaneT.Set(&pts[POINT_NEAR_TL], &pts[POINT_FAR_TL], &pts[POINT_NEAR_TR]);
45 mPlaneB.Set(&pts[POINT_NEAR_BR], &pts[POINT_FAR_BR], &pts[POINT_NEAR_BL]);
46
47 for (int i = 0; i < POINT_MAX; i++) {
48 PSMTXMultVec(invCameraMtx, pts[i], pts[i]);
49 }
50
51 mPlanes[PLANE_L].Set(&pts[POINT_NEAR_BL], &pts[POINT_FAR_BL], &pts[POINT_NEAR_TL]);
52 mPlanes[PLANE_R].Set(&pts[POINT_NEAR_TR], &pts[POINT_FAR_TR], &pts[POINT_NEAR_BR]);
53 mPlanes[PLANE_T].Set(&pts[POINT_NEAR_TL], &pts[POINT_FAR_TL], &pts[POINT_NEAR_TR]);
54 mPlanes[PLANE_B].Set(&pts[POINT_NEAR_BR], &pts[POINT_FAR_BR], &pts[POINT_NEAR_BL]);
55 } else {
56 f32 depthRatio = far / near;
57
58 eyePos.set(0.0f, 0.0f, 0.0f);
59
60 pts[POINT_FAR_TL].x = depthRatio * left;
61 pts[POINT_FAR_TL].y = depthRatio * top;
62 pts[POINT_FAR_TR].x = depthRatio * right;
63 pts[POINT_FAR_TR].y = depthRatio * top;
64 pts[POINT_FAR_BR].x = depthRatio * right;
65 pts[POINT_FAR_BR].y = depthRatio * bottom;
66 pts[POINT_FAR_BL].x = depthRatio * left;
67 pts[POINT_FAR_BL].y = depthRatio * bottom;
68
69 mNearZ = -near;
70 mFarZ = -far;
71
72 mPlaneL.Set(&eyePos, &pts[POINT_NEAR_BL], &pts[POINT_NEAR_TL]);
73 mPlaneR.Set(&eyePos, &pts[POINT_NEAR_TR], &pts[POINT_NEAR_BR]);
74 mPlaneT.Set(&eyePos, &pts[POINT_NEAR_TL], &pts[POINT_NEAR_TR]);
75 mPlaneB.Set(&eyePos, &pts[POINT_NEAR_BR], &pts[POINT_NEAR_BL]);
76
77 for (int i = 0; i < POINT_MAX; i++) {
78 PSMTXMultVec(invCameraMtx, pts[i], pts[i]);
79 }
80 PSMTXMultVec(invCameraMtx, eyePos, eyePos);
81
82 mPlanes[PLANE_L].Set(&eyePos, &pts[POINT_NEAR_BL], &pts[POINT_NEAR_TL]);
83 mPlanes[PLANE_R].Set(&eyePos, &pts[POINT_NEAR_TR], &pts[POINT_NEAR_BR]);
84 mPlanes[PLANE_T].Set(&eyePos, &pts[POINT_NEAR_TL], &pts[POINT_NEAR_TR]);
85 mPlanes[PLANE_B].Set(&eyePos, &pts[POINT_NEAR_BR], &pts[POINT_NEAR_BL]);
86 }
87
88 mBox.Set(pts, POINT_MAX);
89 mPlanes[PLANE_N].Set(&pts[POINT_NEAR_TL], &pts[POINT_NEAR_TR], &pts[POINT_NEAR_BR]);
90 mPlanes[PLANE_F].Set(&pts[POINT_FAR_TL], &pts[POINT_FAR_BL], &pts[POINT_FAR_BR]);
91}
92
93bool mFrustum_c::intersectSphere(const mSphere_c *sphere) const {
94 mVec3_c sphereCenterPos;
95
96 sphereCenterPos.z = mCamMtx._20 * sphere->mCenter.x +
97 mCamMtx._21 * sphere->mCenter.y +
98 mCamMtx._22 * sphere->mCenter.z + mCamMtx._23;
99
100 if (sphereCenterPos.z - sphere->mRadius > mNearZ) {
101 return false;
102 }
103 if (sphereCenterPos.z + sphere->mRadius < mFarZ) {
104 return false;
105 }
106
107 sphereCenterPos.x = mCamMtx._00 * sphere->mCenter.x +
108 mCamMtx._01 * sphere->mCenter.y +
109 mCamMtx._02 * sphere->mCenter.z + mCamMtx._03;
110
111 if (sphereCenterPos.x * mPlaneL.n.x + sphereCenterPos.z * mPlaneL.n.z > sphere->mRadius) {
112 return false;
113 }
114 if (sphereCenterPos.x * mPlaneR.n.x + sphereCenterPos.z * mPlaneR.n.z > sphere->mRadius) {
115 return false;
116 }
117
118 sphereCenterPos.y = mCamMtx._10 * sphere->mCenter.x +
119 mCamMtx._11 * sphere->mCenter.y +
120 mCamMtx._12 * sphere->mCenter.z + mCamMtx._13;
121
122 if (sphereCenterPos.y * mPlaneT.n.y + sphereCenterPos.z * mPlaneT.n.z > sphere->mRadius) {
123 return false;
124 }
125 if (sphereCenterPos.y * mPlaneB.n.y + sphereCenterPos.z * mPlaneB.n.z > sphere->mRadius) {
126 return false;
127 }
128
129 return true;
130}
131
132bool mFrustum_c::intersectAABB(const mAABB_c *box) const {
133 if (!nw4r::math::IntersectionAABB(box, &mBox)) {
134 return false;
135 }
136
137 for (int i = 0; i < PLANE_MAX; i++) {
138 mVec3_c point;
139 point.x = mPlanes[i].n.x >= 0.0f ? box->min.x : box->max.x;
140 point.y = mPlanes[i].n.y >= 0.0f ? box->min.y : box->max.y;
141 point.z = mPlanes[i].n.z >= 0.0f ? box->min.z : box->max.z;
142
143 if (mPlanes[i].Test(point) > 0.0f) {
144 return false;
145 }
146 }
147 return true;
148}
An axis-aligned bounding box.
Definition m_aabb.hpp:7
bool intersectAABB(const mAABB_c *box) const
Checks whether the given bounding box is at least partially inside the frustum.
void set(f32 fovy, f32 aspect, f32 n, f32 f, const mMtx_c &cameraMtx)
Builds a symmetric perspective frustum.
Definition m_frustum.cpp:4
bool intersectSphere(const mSphere_c *sphere) const
Checks whether the given sphere is at least partially inside the frustum.
Definition m_frustum.cpp:93
A 3x4 matrix.
Definition m_mtx.hpp:9
A three-dimensional floating point vector.
Definition m_vec.hpp:122