work on frustum culling

This commit is contained in:
James Lambert 2022-05-13 17:50:41 -06:00
parent 2eda4a3710
commit 39a9bc4afd
7 changed files with 61 additions and 26 deletions

View file

@ -14,6 +14,11 @@ struct BoundingSphere {
short radius;
};
struct BoundingBoxs16 {
short minX, minY, minZ;
short maxX, maxY, maxZ;
};
struct LevelDefinition {
struct CollisionObject* collisionQuads;
struct StaticContentElement *staticContent;

View file

@ -29,7 +29,14 @@ void cameraBuildProjectionMatrix(struct Camera* camera, float matrix[4][4], u16*
guPerspectiveF(matrix, perspectiveNormalize, camera->fov, aspectRatio, camera->nearPlane * planeScalar, camera->farPlane * planeScalar, 1.0f);
}
Mtx* cameraSetupMatrices(struct Camera* camera, struct RenderState* renderState, float aspectRatio, u16* perspNorm, Vp* viewport) {
void cameraExtractClippingPlane(float viewPersp[4][4], struct Plane* output, int axis, float direction) {
output->normal.x = viewPersp[0][axis] * direction + viewPersp[0][3];
output->normal.y = viewPersp[1][axis] * direction + viewPersp[1][3];
output->normal.z = viewPersp[2][axis] * direction + viewPersp[2][3];
output->d = viewPersp[3][axis] * direction + viewPersp[3][3];
}
Mtx* cameraSetupMatrices(struct Camera* camera, struct RenderState* renderState, float aspectRatio, u16* perspNorm, Vp* viewport, struct FrustrumCullingInformation* clippingInfo) {
Mtx* viewProjMatrix = renderStateRequestMatrices(renderState, 2);
if (!viewProjMatrix) {
@ -58,6 +65,14 @@ Mtx* cameraSetupMatrices(struct Camera* camera, struct RenderState* renderState,
guMtxCatF(view, persp, combined);
guMtxF2L(combined, &viewProjMatrix[1]);
if (clippingInfo) {
cameraExtractClippingPlane(combined, &clippingInfo->clippingPlanes[0], 0, 1.0f);
cameraExtractClippingPlane(combined, &clippingInfo->clippingPlanes[1], 0, -1.0f);
cameraExtractClippingPlane(combined, &clippingInfo->clippingPlanes[2], 1, 1.0f);
cameraExtractClippingPlane(combined, &clippingInfo->clippingPlanes[3], 1, -1.0f);
cameraExtractClippingPlane(combined, &clippingInfo->clippingPlanes[4], 2, 1.0f);
}
gSPMatrix(renderState->dl++, osVirtualToPhysical(&viewProjMatrix[1]), G_MTX_PROJECTION | G_MTX_LOAD | G_MTX_NOPUSH);
gSPPerspNormalize(renderState->dl++, perspectiveNormalize);

View file

@ -6,8 +6,15 @@
#include "math/quaternion.h"
#include "math/vector3.h"
#include "math/transform.h"
#include "math/plane.h"
#include "graphics/renderstate.h"
#define CLIPPING_PLANE_COUNT 5
struct FrustrumCullingInformation {
struct Plane clippingPlanes[CLIPPING_PLANE_COUNT];
};
struct Camera {
struct Transform transform;
float nearPlane;
@ -18,6 +25,6 @@ struct Camera {
void cameraInit(struct Camera* camera, float fov, float near, float far);
void cameraBuildViewMatrix(struct Camera* camera, float matrix[4][4]);
void cameraBuildProjectionMatrix(struct Camera* camera, float matrix[4][4], u16* perspectiveNorm, float aspectRatio);
Mtx* cameraSetupMatrices(struct Camera* camera, struct RenderState* renderState, float aspectRatio, u16* perspNorm, Vp* viewport);
Mtx* cameraSetupMatrices(struct Camera* camera, struct RenderState* renderState, float aspectRatio, u16* perspNorm, Vp* viewport, struct FrustrumCullingInformation* clippingInfo);
#endif

View file

@ -35,7 +35,7 @@ struct Quaternion gVerticalFlip = {0.0f, 1.0f, 0.0f, 0.0f};
void renderPropsInit(struct RenderProps* props, struct Camera* camera, float aspectRatio, struct RenderState* renderState) {
props->camera = *camera;
props->aspectRatio = aspectRatio;
props->perspectiveMatrix = cameraSetupMatrices(camera, renderState, aspectRatio, &props->perspectiveCorrect, &fullscreenViewport);
props->perspectiveMatrix = cameraSetupMatrices(camera, renderState, aspectRatio, &props->perspectiveCorrect, &fullscreenViewport, &props->cullingInfo);
props->viewport = &fullscreenViewport;
props->currentDepth = STARTING_RENDER_DEPTH;
@ -85,14 +85,14 @@ void renderPropsNext(struct RenderProps* current, struct RenderProps* next, stru
transformConcat(&portalCombined, &current->camera.transform, &next->camera.transform);
// render any objects halfway through portals
cameraSetupMatrices(&next->camera, renderState, next->aspectRatio, &next->perspectiveCorrect, current->viewport);
cameraSetupMatrices(&next->camera, renderState, next->aspectRatio, &next->perspectiveCorrect, current->viewport, NULL);
dynamicSceneRender(renderState, 1);
Vp* viewport = renderPropsBuildViewport(next, renderState);
next->viewport = viewport;
next->perspectiveMatrix = cameraSetupMatrices(&next->camera, renderState, next->aspectRatio, &next->perspectiveCorrect, viewport);
next->perspectiveMatrix = cameraSetupMatrices(&next->camera, renderState, next->aspectRatio, &next->perspectiveCorrect, viewport, &next->cullingInfo);
next->currentDepth = current->currentDepth - 1;

View file

@ -66,8 +66,10 @@ void sceneInit(struct Scene* scene) {
void sceneRenderWithProperties(void* data, struct RenderProps* properties, struct RenderState* renderState) {
struct Scene* scene = (struct Scene*)data;
portalRender(&scene->portals[0], &scene->portals[1], properties, sceneRenderWithProperties, data, renderState);
portalRender(&scene->portals[1], &scene->portals[0], properties, sceneRenderWithProperties, data, renderState);
int closerPortal = vector3DistSqrd(&properties->camera.transform.position, &scene->portals[0].transform.position) > vector3DistSqrd(&properties->camera.transform.position, &scene->portals[1].transform.position) ? 0 : 1;
portalRender(&scene->portals[closerPortal], &scene->portals[1 - closerPortal], properties, sceneRenderWithProperties, data, renderState);
portalRender(&scene->portals[1 - closerPortal], &scene->portals[closerPortal], properties, sceneRenderWithProperties, data, renderState);
gDPSetRenderMode(renderState->dl++, G_RM_ZB_OPA_SURF, G_RM_ZB_OPA_SURF2);

View file

@ -1,18 +1,31 @@
#include "static_scene.h"
#include "defs.h"
#include "../math/box3d.h"
int isOutsideFrustrum(struct FrustrumCullingInformation* frustrum, struct BoundingSphere* boundingSphere) {
struct Vector3 spherePos;
int isOutsideFrustrum(struct FrustrumCullingInformation* frustrum, struct BoundingBoxs16* boundingSphere) {
struct Box3D boxAsFloat;
spherePos.x = boundingSphere->x * (1.0f / SCENE_SCALE);
spherePos.y = boundingSphere->y * (1.0f / SCENE_SCALE);
spherePos.z = boundingSphere->z * (1.0f / SCENE_SCALE);
boxAsFloat.min.x = boundingSphere->minX * (1.0f / SCENE_SCALE);
boxAsFloat.min.y = boundingSphere->minY * (1.0f / SCENE_SCALE);
boxAsFloat.min.z = boundingSphere->minZ * (1.0f / SCENE_SCALE);
vector3Sub(&spherePos, &frustrum->cameraPosition, &spherePos);
struct Vector3 crossDirection;
vector3Cross(&frustrum->frustrumDirection, &spherePos, &crossDirection);
boxAsFloat.max.x = boundingSphere->maxX * (1.0f / SCENE_SCALE);
boxAsFloat.max.y = boundingSphere->maxY * (1.0f / SCENE_SCALE);
boxAsFloat.max.z = boundingSphere->maxZ * (1.0f / SCENE_SCALE);
float distance = sqrtf(vector3MagSqrd(&crossDirection)) * frustrum->cosFrustumAngle - vector3Dot(&frustrum->frustrumDirection, &crossDirection) * frustrum->sinFrustrumAngle;
return distance > boundingSphere->radius * (1.0f / SCENE_SCALE);
for (int i = 0; i < CLIPPING_PLANE_COUNT; ++i) {
struct Vector3 closestPoint;
closestPoint.x = frustrum->clippingPlanes[i].normal.x > 0.0f ? boxAsFloat.min.x : boxAsFloat.max.x;
closestPoint.y = frustrum->clippingPlanes[i].normal.y > 0.0f ? boxAsFloat.min.y : boxAsFloat.max.y;
closestPoint.z = frustrum->clippingPlanes[i].normal.z > 0.0f ? boxAsFloat.min.z : boxAsFloat.max.z;
if (planePointDistance(&frustrum->clippingPlanes[i], &closestPoint) < 0.0f) {
return 1;
}
}
return 0;
}

View file

@ -6,6 +6,7 @@
#include "../math/transform.h"
#include "../math/box3d.h"
#include "../levels/level_definition.h"
#include "../scene/camera.h"
enum StaticSceneEntryFlags {
StaticSceneEntryFlagsHidden,
@ -31,16 +32,8 @@ struct StaticScene {
u16 gridHeight;
};
struct FrustrumCullingInformation {
struct Plane nearPlane;
struct Vector3 frustrumDirection;
struct Vector3 cameraPosition;
float cosFrustumAngle;
float sinFrustrumAngle;
};
void staticSceneInit();
int isOutsideFrustrum(struct FrustrumCullingInformation* frustrum, struct BoundingSphere* boundingSphere);
int isOutsideFrustrum(struct FrustrumCullingInformation* frustrum, struct BoundingBoxs16* boundingBox);
#endif