From f10fc3ef95b37ce1bc25707761061d8ea95016c4 Mon Sep 17 00:00:00 2001 From: James Lambert Date: Mon, 14 Nov 2022 20:59:21 -0700 Subject: [PATCH] Only keep one clipper result in the render plan --- Makefile | 2 + src/scene/portal.c | 335 -------------------------------------- src/scene/portal.h | 10 +- src/scene/portal_render.c | 110 +++++++++++++ src/scene/portal_render.h | 12 ++ src/scene/render_plan.c | 111 ++++++++++--- src/scene/render_plan.h | 4 + src/scene/scene.c | 41 ----- 8 files changed, 223 insertions(+), 402 deletions(-) create mode 100644 src/scene/portal_render.c create mode 100644 src/scene/portal_render.h diff --git a/Makefile b/Makefile index 5b08f3c..8ed49c2 100644 --- a/Makefile +++ b/Makefile @@ -203,6 +203,8 @@ build/src/scene/pedestal.o: $(MODEL_HEADERS) build/src/scene/render_plan.o: $(MODEL_HEADERS) +build/src/scene/portal_render.o: $(MODEL_HEADERS) + build/anims.ld: $(ANIM_LIST) tools/generate_animation_ld.js @mkdir -p $(@D) node tools/generate_animation_ld.js $@ $(ANIM_LIST) diff --git a/src/scene/portal.c b/src/scene/portal.c index 9dc80b7..c9a1678 100644 --- a/src/scene/portal.c +++ b/src/scene/portal.c @@ -37,10 +37,6 @@ struct Vector3 gPortalOutline[PORTAL_LOOP_SIZE] = { {-0.353553f * SCENE_SCALE * PORTAL_COVER_WIDTH, 0.707107f * SCENE_SCALE * PORTAL_COVER_HEIGHT, 0}, }; -struct Quaternion gVerticalFlip = {0.0f, 1.0f, 0.0f, 0.0f}; - -#define STARTING_RENDER_DEPTH 2 - #define PORTAL_CLIPPING_PLANE_BIAS (SCENE_SCALE * 0.25f) #define CAMERA_CLIPPING_RADIUS 0.2f @@ -106,128 +102,6 @@ void renderPropsInit(struct RenderProps* props, struct Camera* camera, float asp props->portalRenderType = 0; } -#define MIN_VP_WIDTH 64 - -void renderPropscheckViewportSize(int* min, int* max, int screenSize) { - if (*max < MIN_VP_WIDTH) { - *max = MIN_VP_WIDTH; - } - - if (*min > screenSize - MIN_VP_WIDTH) { - *min = screenSize - MIN_VP_WIDTH; - } - - int widthGrowBy = MIN_VP_WIDTH - (*max - *min); - - if (widthGrowBy > 0) { - *min -= widthGrowBy >> 1; - *max += (widthGrowBy + 1) >> 1; - } -} - -int renderPropsZDistance(int currentDepth) { - if (currentDepth >= STARTING_RENDER_DEPTH) { - return 0; - } else if (currentDepth < 0) { - return G_MAXZ; - } else { - return G_MAXZ - (G_MAXZ >> (STARTING_RENDER_DEPTH - currentDepth)); - } -} - -Vp* renderPropsBuildViewport(struct RenderProps* props, struct RenderState* renderState) { - int minX = props->minX; - int maxX = props->maxX; - int minY = props->minY; - int maxY = props->maxY; - - int minZ = renderPropsZDistance(props->currentDepth); - int maxZ = renderPropsZDistance(props->currentDepth - 1); - - renderPropscheckViewportSize(&minX, &maxX, SCREEN_WD); - renderPropscheckViewportSize(&minY, &maxY, SCREEN_HT); - - Vp* viewport = renderStateRequestViewport(renderState); - - if (!viewport) { - return NULL; - } - - viewport->vp.vscale[0] = (maxX - minX) << 1; - viewport->vp.vscale[1] = (maxY - minY) << 1; - viewport->vp.vscale[2] = (maxZ - minZ) >> 1; - viewport->vp.vscale[3] = 0; - - viewport->vp.vtrans[0] = (maxX + minX) << 1; - viewport->vp.vtrans[1] = (maxY + minY) << 1; - viewport->vp.vtrans[2] = (maxZ + minZ) >> 1; - viewport->vp.vtrans[3] = 0; - - return viewport; -} - -int renderPropsNext(struct RenderProps* current, struct RenderProps* next, struct Transform* fromPortal, struct Transform* toPortal, struct RenderState* renderState) { - struct Transform otherInverse; - transformInvert(fromPortal, &otherInverse); - struct Transform portalCombined; - transformConcat(toPortal, &otherInverse, &portalCombined); - - next->camera = current->camera; - next->aspectRatio = current->aspectRatio; - transformConcat(&portalCombined, ¤t->camera.transform, &next->camera.transform); - - struct Vector3 portalOffset; - vector3Sub(&toPortal->position, &next->camera.transform.position, &portalOffset); - - struct Vector3 cameraForward; - quatMultVector(&next->camera.transform.rotation, &gForward, &cameraForward); - - next->camera.nearPlane = (-vector3Dot(&portalOffset, &cameraForward)) * SCENE_SCALE; - - if (next->camera.nearPlane < current->camera.nearPlane) { - next->camera.nearPlane = current->camera.nearPlane; - - if (next->camera.nearPlane > next->camera.farPlane) { - next->camera.nearPlane = next->camera.farPlane; - } - } - - next->currentDepth = current->currentDepth - 1; - Vp* viewport = renderPropsBuildViewport(next, renderState); - - if (!viewport) { - return 0; - } - - next->viewport = viewport; - - if (!cameraSetupMatrices(&next->camera, renderState, next->aspectRatio, viewport, &next->cameraMatrixInfo)) { - return 0; - } - - if (!cameraApplyMatrices(renderState, &next->cameraMatrixInfo)) { - return 0; - } - - if (current->clippingPortalIndex == -1) { - // set the near clipping plane to be the exit portal surface - quatMultVector(&toPortal->rotation, &gForward, &next->cameraMatrixInfo.cullingInformation.clippingPlanes[4].normal); - if (toPortal < fromPortal) { - vector3Negate(&next->cameraMatrixInfo.cullingInformation.clippingPlanes[4].normal, &next->cameraMatrixInfo.cullingInformation.clippingPlanes[4].normal); - } - next->cameraMatrixInfo.cullingInformation.clippingPlanes[4].d = -vector3Dot(&next->cameraMatrixInfo.cullingInformation.clippingPlanes[4].normal, &toPortal->position) * SCENE_SCALE; - } - next->clippingPortalIndex = -1; - - next->exitPortalIndex = toPortal < fromPortal ? 0 : 1; - next->fromRoom = gCollisionScene.portalRooms[next->exitPortalIndex]; - - gSPViewport(renderState->dl++, viewport); - gDPSetScissor(renderState->dl++, G_SC_NON_INTERLACE, next->minX, next->minY, next->maxX, next->maxY); - - return 1; -} - void portalInit(struct Portal* portal, enum PortalFlags flags) { transformInitIdentity(&portal->transform); portal->flags = flags; @@ -262,215 +136,6 @@ void portalUpdate(struct Portal* portal, int isOpen) { } } -void portalRenderScreenCover(struct Vector2s16* points, int pointCount, struct RenderProps* props, struct RenderState* renderState) { - if (pointCount == 0) { - return; - } - - gDPPipeSync(renderState->dl++); - gDPSetDepthSource(renderState->dl++, G_ZS_PRIM); - gDPSetPrimDepth(renderState->dl++, 0, 0); - gDPSetRenderMode(renderState->dl++, CLR_ON_CVG | FORCE_BL | IM_RD | Z_CMP | Z_UPD | CVG_DST_WRAP | ZMODE_OPA | GBL_c1(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA), CLR_ON_CVG | FORCE_BL | IM_RD | Z_CMP | Z_UPD | CVG_DST_WRAP | ZMODE_OPA | GBL_c2(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA)); - gDPSetCombineLERP(renderState->dl++, 0, 0, 0, PRIMITIVE, 0, 0, 0, PRIMITIVE, 0, 0, 0, PRIMITIVE, 0, 0, 0, PRIMITIVE); - - if (controllerGetButton(1, D_CBUTTONS)) { - gDPSetPrimColor(renderState->dl++, 255, 255, 0, 0, 0, 128); - } - - Mtx* idenity = renderStateRequestMatrices(renderState, 1); - - if (!idenity) { - return; - } - - guMtxIdent(idenity); - - gSPMatrix(renderState->dl++, idenity, G_MTX_LOAD | G_MTX_MODELVIEW | G_MTX_PUSH); - - Mtx* ortho = renderStateRequestMatrices(renderState, 1); - - if (!ortho) { - return; - } - - guOrtho(ortho, 0, SCREEN_WD << 2, 0, SCREEN_HT << 2, -10, 10, 1); - - gSPMatrix(renderState->dl++, ortho, G_MTX_LOAD | G_MTX_PROJECTION | G_MTX_NOPUSH); - - Vtx* vertices = renderStateRequestVertices(renderState, pointCount); - - if (!vertices) { - return; - } - - for (int i = 0; i < pointCount; ++i) { - Vtx* vertex = &vertices[i]; - vertex->v.ob[0] = points[i].x; - vertex->v.ob[1] = points[i].y; - vertex->v.ob[2] = 0; - - vertex->v.flag = 0; - - vertex->v.tc[0] = 0; - vertex->v.tc[1] = 0; - - vertex->v.cn[0] = 255; - vertex->v.cn[1] = 255; - vertex->v.cn[2] = 255; - vertex->v.cn[3] = 255; - } - - gSPVertex(renderState->dl++, vertices, pointCount, 0); - - for (int i = 2; i < pointCount; i += 2) { - if (i + 1 < pointCount) { - gSP2Triangles(renderState->dl++, 0, i - 1, i, 0, 0, i, i + 1, 0); - } else { - gSP1Triangle(renderState->dl++, 0, i - 1, i, 0); - } - } - - gDPPipeSync(renderState->dl++); - gSPPopMatrix(renderState->dl++, G_MTX_MODELVIEW); - gSPMatrix(renderState->dl++, props->cameraMatrixInfo.projectionView, G_MTX_LOAD | G_MTX_PROJECTION | G_MTX_NOPUSH); - gDPSetDepthSource(renderState->dl++, G_ZS_PIXEL); - gDPSetRenderMode(renderState->dl++, G_RM_ZB_OPA_SURF, G_RM_ZB_OPA_SURF2); -} - -void portalDetermineTransform(struct Portal* portal, float portalTransform[4][4]) { - struct Transform finalTransform; - finalTransform = portal->transform; - - if (portal->flags & PortalFlagsOddParity) { - quatMultiply(&portal->transform.rotation, &gVerticalFlip, &finalTransform.rotation); - } - - vector3Scale(&gOneVec, &finalTransform.scale, portal->scale); - - transformToMatrix(&finalTransform, portalTransform, SCENE_SCALE); -} - -void portalRenderCover(struct Portal* portal, float portalTransform[4][4], struct RenderState* renderState) { - Mtx* matrix = renderStateRequestMatrices(renderState, 1); - - if (!matrix) { - return; - } - - guMtxF2L(portalTransform, matrix); - gSPMatrix(renderState->dl++, matrix, G_MTX_MODELVIEW | G_MTX_PUSH | G_MTX_MUL); - if (portal->flags & PortalFlagsOddParity) { - gSPDisplayList(renderState->dl++, portal_portal_blue_filled_model_gfx); - } else { - gSPDisplayList(renderState->dl++, portal_portal_orange_filled_model_gfx); - } - gSPPopMatrix(renderState->dl++, G_MTX_MODELVIEW); -} - -void portalRender(struct Portal* portal, struct Portal* otherPortal, struct RenderProps* props, SceneRenderCallback sceneRenderer, void* data, struct RenderState* renderState) { - struct Vector3 forward = gForward; - if (!(portal->flags & PortalFlagsOddParity)) { - forward.z = -1.0f; - } - - struct Vector3 worldForward; - quatMultVector(&portal->transform.rotation, &forward, &worldForward); - - struct Vector3 offsetFromCamera; - vector3Sub(&props->camera.transform.position, &portal->transform.position, &offsetFromCamera); - - // don't render the portal if it is facing the wrong way - if (vector3Dot(&worldForward, &offsetFromCamera) < 0.0f) { - return; - } - - struct ScreenClipper clipper; - float portalTransform[4][4]; - - portalDetermineTransform(portal, portalTransform); - - if (props->currentDepth == 0 || !otherPortal) { - portalRenderCover(portal, portalTransform, renderState); - return; - } - - struct RenderProps nextProps; - int portalIndex = portal < otherPortal ? 0 : 1; - - screenClipperInitWithCamera(&clipper, &props->camera, (float)SCREEN_WD / (float)SCREEN_HT, portalTransform); - struct Box2D clippingBounds; - screenClipperBoundingPoints(&clipper, gPortalOutline, sizeof(gPortalOutline) / sizeof(*gPortalOutline), &clippingBounds); - - if (props->clippingPortalIndex == portalIndex) { - nextProps.minX = 0; - nextProps.maxX = SCREEN_WD; - nextProps.minY = 0; - nextProps.maxY = SCREEN_HT; - } else { - nextProps.minX = CALC_SCREEN_SPACE(clippingBounds.min.x, SCREEN_WD); - nextProps.maxX = CALC_SCREEN_SPACE(clippingBounds.max.x, SCREEN_WD); - nextProps.minY = CALC_SCREEN_SPACE(-clippingBounds.max.y, SCREEN_HT); - nextProps.maxY = CALC_SCREEN_SPACE(-clippingBounds.min.y, SCREEN_HT); - - nextProps.minX = MAX(nextProps.minX, props->minX); - nextProps.maxX = MIN(nextProps.maxX, props->maxX); - nextProps.minY = MAX(nextProps.minY, props->minY); - nextProps.maxY = MIN(nextProps.maxY, props->maxY); - } - - if (nextProps.minX < nextProps.maxX && nextProps.minY < nextProps.maxY) { - if (!renderPropsNext(props, &nextProps, &portal->transform, &otherPortal->transform, renderState)) { - portalRenderCover(portal, portalTransform, renderState); - return; - } - - sceneRenderer(data, &nextProps, renderState); - - // revert to previous state - gSPMatrix(renderState->dl++, osVirtualToPhysical(props->cameraMatrixInfo.projectionView), G_MTX_PROJECTION | G_MTX_LOAD | G_MTX_NOPUSH); - gSPPerspNormalize(renderState->dl++, props->cameraMatrixInfo.perspectiveNormalize); - gDPSetScissor(renderState->dl++, G_SC_NON_INTERLACE, props->minX, props->minY, props->maxX, props->maxY); - gSPViewport(renderState->dl++, props->viewport); - - // render the front portal cover - Mtx* matrix = renderStateRequestMatrices(renderState, 1); - - if (!matrix) { - return; - } - - guMtxF2L(portalTransform, matrix); - gSPMatrix(renderState->dl++, matrix, G_MTX_MODELVIEW | G_MTX_PUSH | G_MTX_MUL); - - gDPSetEnvColor(renderState->dl++, 255, 255, 255, portal->opacity < 0.0f ? 0 : (portal->opacity > 1.0f ? 255 : (u8)(portal->opacity * 255.0f))); - - if (portal->flags & PortalFlagsOddParity) { - if (!controllerGetButton(1, L_CBUTTONS)) { - gSPDisplayList(renderState->dl++, portal_portal_blue_face_model_gfx); - if (!controllerGetButton(1, U_CBUTTONS)) { - portalRenderScreenCover(clipper.nearPolygon, clipper.nearPolygonCount, props, renderState); - } - } - gDPPipeSync(renderState->dl++); - - gSPDisplayList(renderState->dl++, portal_portal_blue_model_gfx); - } else { - if (!controllerGetButton(1, L_CBUTTONS)) { - gSPDisplayList(renderState->dl++, portal_portal_orange_face_model_gfx); - if (!controllerGetButton(1, U_CBUTTONS)) { - portalRenderScreenCover(clipper.nearPolygon, clipper.nearPolygonCount, props, renderState); - } - } - gDPPipeSync(renderState->dl++); - - gSPDisplayList(renderState->dl++, portal_portal_orange_model_gfx); - } - - gSPPopMatrix(renderState->dl++, G_MTX_MODELVIEW); - } - -} - int portalAttachToSurface(struct Portal* portal, struct PortalSurface* surface, int surfaceIndex, struct Transform* portalAt) { // determine if portal is on surface if (!portalSurfaceIsInside(surface, portalAt)) { diff --git a/src/scene/portal.h b/src/scene/portal.h index e395544..95eb4dd 100644 --- a/src/scene/portal.h +++ b/src/scene/portal.h @@ -8,9 +8,8 @@ #include "camera.h" #include "static_scene.h" #include "./portal_surface.h" -#include "../graphics/screen_clipper.h" - +#define STARTING_RENDER_DEPTH 2 #define PORTAL_LOOP_SIZE 8 enum PortalFlags { @@ -45,6 +44,8 @@ typedef void SceneRenderCallback(void* data, struct RenderProps* properties, str #define PORTAL_RENDER_TYPE_VISIBLE(portalIndex) (PORTAL_RENDER_TYPE_VISIBLE_0 << (portalIndex)) #define PORTAL_RENDER_TYPE_ENABLED(portalIndex) (PORTAL_RENDER_TYPE_ENABLED_0 << (portalIndex)) +extern struct Vector3 gPortalOutline[PORTAL_LOOP_SIZE]; + struct RenderProps { struct Camera camera; float aspectRatio; @@ -69,17 +70,12 @@ struct RenderProps { struct RenderProps* previousProperties; struct RenderProps* nextProperites[2]; - struct ScreenClipper clipper; }; void renderPropsInit(struct RenderProps* props, struct Camera* camera, float aspectRatio, struct RenderState* renderState, u16 roomIndex); -int renderPropsNext(struct RenderProps* current, struct RenderProps* next, struct Transform* fromPortal, struct Transform* toPortal, struct RenderState* renderState); void portalInit(struct Portal* portal, enum PortalFlags flags); void portalUpdate(struct Portal* portal, int isOpen); -void portalRender(struct Portal* portal, struct Portal* otherPortal, struct RenderProps* props, SceneRenderCallback sceneRenderer, void* data, struct RenderState* renderState); - -void portalDetermineTransform(struct Portal* portal, float portalTransform[4][4]); int portalAttachToSurface(struct Portal* portal, struct PortalSurface* surface, int surfaceIndex, struct Transform* portalAt); void portalCheckForHoles(struct Portal* portals); diff --git a/src/scene/portal_render.c b/src/scene/portal_render.c new file mode 100644 index 0000000..e4845bc --- /dev/null +++ b/src/scene/portal_render.c @@ -0,0 +1,110 @@ +#include "portal_render.h" + +#include "../defs.h" +#include "../graphics/graphics.h" + +#include "../build/assets/models/portal/portal_blue_filled.h" +#include "../build/assets/models/portal/portal_orange_filled.h" + +struct Quaternion gVerticalFlip = {0.0f, 1.0f, 0.0f, 0.0f}; + +void portalRenderScreenCover(struct Vector2s16* points, int pointCount, struct RenderProps* props, struct RenderState* renderState) { + if (pointCount == 0) { + return; + } + + gDPPipeSync(renderState->dl++); + gDPSetDepthSource(renderState->dl++, G_ZS_PRIM); + gDPSetPrimDepth(renderState->dl++, 0, 0); + gDPSetRenderMode(renderState->dl++, CLR_ON_CVG | FORCE_BL | IM_RD | Z_CMP | Z_UPD | CVG_DST_WRAP | ZMODE_OPA | GBL_c1(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA), CLR_ON_CVG | FORCE_BL | IM_RD | Z_CMP | Z_UPD | CVG_DST_WRAP | ZMODE_OPA | GBL_c2(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA)); + gDPSetCombineLERP(renderState->dl++, 0, 0, 0, PRIMITIVE, 0, 0, 0, PRIMITIVE, 0, 0, 0, PRIMITIVE, 0, 0, 0, PRIMITIVE); + + Mtx* idenity = renderStateRequestMatrices(renderState, 1); + + if (!idenity) { + return; + } + + guMtxIdent(idenity); + + gSPMatrix(renderState->dl++, idenity, G_MTX_LOAD | G_MTX_MODELVIEW | G_MTX_PUSH); + + Mtx* ortho = renderStateRequestMatrices(renderState, 1); + + if (!ortho) { + return; + } + + guOrtho(ortho, 0, SCREEN_WD << 2, 0, SCREEN_HT << 2, -10, 10, 1); + + gSPMatrix(renderState->dl++, ortho, G_MTX_LOAD | G_MTX_PROJECTION | G_MTX_NOPUSH); + + Vtx* vertices = renderStateRequestVertices(renderState, pointCount); + + if (!vertices) { + return; + } + + for (int i = 0; i < pointCount; ++i) { + Vtx* vertex = &vertices[i]; + vertex->v.ob[0] = points[i].x; + vertex->v.ob[1] = points[i].y; + vertex->v.ob[2] = 0; + + vertex->v.flag = 0; + + vertex->v.tc[0] = 0; + vertex->v.tc[1] = 0; + + vertex->v.cn[0] = 255; + vertex->v.cn[1] = 255; + vertex->v.cn[2] = 255; + vertex->v.cn[3] = 255; + } + + gSPVertex(renderState->dl++, vertices, pointCount, 0); + + for (int i = 2; i < pointCount; i += 2) { + if (i + 1 < pointCount) { + gSP2Triangles(renderState->dl++, 0, i - 1, i, 0, 0, i, i + 1, 0); + } else { + gSP1Triangle(renderState->dl++, 0, i - 1, i, 0); + } + } + + gDPPipeSync(renderState->dl++); + gSPPopMatrix(renderState->dl++, G_MTX_MODELVIEW); + gSPMatrix(renderState->dl++, props->cameraMatrixInfo.projectionView, G_MTX_LOAD | G_MTX_PROJECTION | G_MTX_NOPUSH); + gDPSetDepthSource(renderState->dl++, G_ZS_PIXEL); + gDPSetRenderMode(renderState->dl++, G_RM_ZB_OPA_SURF, G_RM_ZB_OPA_SURF2); +} + +void portalDetermineTransform(struct Portal* portal, float portalTransform[4][4]) { + struct Transform finalTransform; + finalTransform = portal->transform; + + if (portal->flags & PortalFlagsOddParity) { + quatMultiply(&portal->transform.rotation, &gVerticalFlip, &finalTransform.rotation); + } + + vector3Scale(&gOneVec, &finalTransform.scale, portal->scale); + + transformToMatrix(&finalTransform, portalTransform, SCENE_SCALE); +} + +void portalRenderCover(struct Portal* portal, float portalTransform[4][4], struct RenderState* renderState) { + Mtx* matrix = renderStateRequestMatrices(renderState, 1); + + if (!matrix) { + return; + } + + guMtxF2L(portalTransform, matrix); + gSPMatrix(renderState->dl++, matrix, G_MTX_MODELVIEW | G_MTX_PUSH | G_MTX_MUL); + if (portal->flags & PortalFlagsOddParity) { + gSPDisplayList(renderState->dl++, portal_portal_blue_filled_model_gfx); + } else { + gSPDisplayList(renderState->dl++, portal_portal_orange_filled_model_gfx); + } + gSPPopMatrix(renderState->dl++, G_MTX_MODELVIEW); +} \ No newline at end of file diff --git a/src/scene/portal_render.h b/src/scene/portal_render.h new file mode 100644 index 0000000..7487f25 --- /dev/null +++ b/src/scene/portal_render.h @@ -0,0 +1,12 @@ +#ifndef __SCENE_PORTAL_RENDER_H__ +#define __SCENE_PORTAL_RENDER_H__ + +#include "../math/vector2s16.h" +#include "portal.h" +#include "../graphics/renderstate.h" + +void portalRenderScreenCover(struct Vector2s16* points, int pointCount, struct RenderProps* props, struct RenderState* renderState); +void portalDetermineTransform(struct Portal* portal, float portalTransform[4][4]); +void portalRenderCover(struct Portal* portal, float portalTransform[4][4], struct RenderState* renderState); + +#endif \ No newline at end of file diff --git a/src/scene/render_plan.c b/src/scene/render_plan.c index 137f28d..139df65 100644 --- a/src/scene/render_plan.c +++ b/src/scene/render_plan.c @@ -5,19 +5,77 @@ #include "../physics/collision_scene.h" #include "../levels/static_render.h" +#include "../util/memory.h" + +#include "portal_render.h" + #include "../build/assets/models/portal/portal_blue.h" -#include "../build/assets/models/portal/portal_blue_filled.h" #include "../build/assets/models/portal/portal_blue_face.h" #include "../build/assets/models/portal/portal_orange.h" #include "../build/assets/models/portal/portal_orange_face.h" -#include "../build/assets/models/portal/portal_orange_filled.h" -Vp* renderPropsBuildViewport(struct RenderProps* props, struct RenderState* renderState); +#define MIN_VP_WIDTH 64 + +void renderPropscheckViewportSize(int* min, int* max, int screenSize) { + if (*max < MIN_VP_WIDTH) { + *max = MIN_VP_WIDTH; + } + + if (*min > screenSize - MIN_VP_WIDTH) { + *min = screenSize - MIN_VP_WIDTH; + } + + int widthGrowBy = MIN_VP_WIDTH - (*max - *min); + + if (widthGrowBy > 0) { + *min -= widthGrowBy >> 1; + *max += (widthGrowBy + 1) >> 1; + } +} + +int renderPropsZDistance(int currentDepth) { + if (currentDepth >= STARTING_RENDER_DEPTH) { + return 0; + } else if (currentDepth < 0) { + return G_MAXZ; + } else { + return G_MAXZ - (G_MAXZ >> (STARTING_RENDER_DEPTH - currentDepth)); + } +} + +Vp* renderPropsBuildViewport(struct RenderProps* props, struct RenderState* renderState) { + int minX = props->minX; + int maxX = props->maxX; + int minY = props->minY; + int maxY = props->maxY; + + int minZ = renderPropsZDistance(props->currentDepth); + int maxZ = renderPropsZDistance(props->currentDepth - 1); + + renderPropscheckViewportSize(&minX, &maxX, SCREEN_WD); + renderPropscheckViewportSize(&minY, &maxY, SCREEN_HT); + + Vp* viewport = renderStateRequestViewport(renderState); + + if (!viewport) { + return NULL; + } + + viewport->vp.vscale[0] = (maxX - minX) << 1; + viewport->vp.vscale[1] = (maxY - minY) << 1; + viewport->vp.vscale[2] = (maxZ - minZ) >> 1; + viewport->vp.vscale[3] = 0; + + viewport->vp.vtrans[0] = (maxX + minX) << 1; + viewport->vp.vtrans[1] = (maxY + minY) << 1; + viewport->vp.vtrans[2] = (maxZ + minZ) >> 1; + viewport->vp.vtrans[3] = 0; + + return viewport; +} + void renderPlanFinishView(struct RenderPlan* renderPlan, struct Scene* scene, struct RenderProps* properties, struct RenderState* renderState); -void portalRenderScreenCover(struct Vector2s16* points, int pointCount, struct RenderProps* props, struct RenderState* renderState); -void portalRenderCover(struct Portal* portal, float portalTransform[4][4], struct RenderState* renderState); -extern struct Quaternion gVerticalFlip; -extern struct Vector3 gPortalOutline[PORTAL_LOOP_SIZE]; + #define CALC_SCREEN_SPACE(clip_space, screen_size) ((clip_space + 1.0f) * ((screen_size) / 2)) @@ -53,9 +111,17 @@ int renderPlanPortal(struct RenderPlan* renderPlan, struct Scene* scene, struct struct RenderProps* next = &renderPlan->stageProps[renderPlan->stageCount]; - screenClipperInitWithCamera(&next->clipper, ¤t->camera, (float)SCREEN_WD / (float)SCREEN_HT, portalTransform); + struct ScreenClipper clipper; + + screenClipperInitWithCamera(&clipper, ¤t->camera, (float)SCREEN_WD / (float)SCREEN_HT, portalTransform); struct Box2D clippingBounds; - screenClipperBoundingPoints(&next->clipper, gPortalOutline, sizeof(gPortalOutline) / sizeof(*gPortalOutline), &clippingBounds); + screenClipperBoundingPoints(&clipper, gPortalOutline, sizeof(gPortalOutline) / sizeof(*gPortalOutline), &clippingBounds); + + if (clipper.nearPolygonCount) { + renderPlan->nearPolygonCount = clipper.nearPolygonCount; + memCopy(renderPlan->nearPolygon, clipper.nearPolygon, sizeof(struct Vector2s16) * clipper.nearPolygonCount); + renderPlan->clippedPortalIndex = portalIndex; + } if (current->clippingPortalIndex == portalIndex) { next->minX = 0; @@ -193,6 +259,8 @@ void renderPlanFinishView(struct RenderPlan* renderPlan, struct Scene* scene, st void renderPlanBuild(struct RenderPlan* renderPlan, struct Scene* scene, struct RenderState* renderState) { renderPropsInit(&renderPlan->stageProps[0], &scene->camera, (float)SCREEN_WD / (float)SCREEN_HT, renderState, scene->player.body.currentRoom); renderPlan->stageCount = 1; + renderPlan->clippedPortalIndex = -1; + renderPlan->nearPolygonCount = 0; renderPlanFinishView(renderPlan, scene, &renderPlan->stageProps[0], renderState); } @@ -231,19 +299,24 @@ void renderPlanExecute(struct RenderPlan* renderPlan, struct Scene* scene, struc gDPSetEnvColor(renderState->dl++, 255, 255, 255, portal->opacity < 0.0f ? 0 : (portal->opacity > 1.0f ? 255 : (u8)(portal->opacity * 255.0f))); + Gfx* faceModel; + Gfx* portalModel; + if (portal->flags & PortalFlagsOddParity) { - gSPDisplayList(renderState->dl++, portal_portal_blue_face_model_gfx); - portalRenderScreenCover(portalProps->clipper.nearPolygon, portalProps->clipper.nearPolygonCount, current, renderState); - gDPPipeSync(renderState->dl++); - - gSPDisplayList(renderState->dl++, portal_portal_blue_model_gfx); + faceModel = portal_portal_blue_face_model_gfx; + portalModel = portal_portal_blue_model_gfx; } else { - gSPDisplayList(renderState->dl++, portal_portal_orange_face_model_gfx); - portalRenderScreenCover(portalProps->clipper.nearPolygon, portalProps->clipper.nearPolygonCount, current, renderState); - gDPPipeSync(renderState->dl++); - - gSPDisplayList(renderState->dl++, portal_portal_orange_model_gfx); + faceModel = portal_portal_orange_face_model_gfx; + portalModel = portal_portal_orange_model_gfx; } + + gSPDisplayList(renderState->dl++, faceModel); + if (current->previousProperties == NULL && portalIndex == renderPlan->clippedPortalIndex && renderPlan->nearPolygonCount) { + portalRenderScreenCover(renderPlan->nearPolygon, renderPlan->nearPolygonCount, current, renderState); + } + gDPPipeSync(renderState->dl++); + + gSPDisplayList(renderState->dl++, portalModel); gSPPopMatrix(renderState->dl++, G_MTX_MODELVIEW); } else { diff --git a/src/scene/render_plan.h b/src/scene/render_plan.h index c3c5f3b..358b295 100644 --- a/src/scene/render_plan.h +++ b/src/scene/render_plan.h @@ -2,12 +2,16 @@ #define __SCENE_RENDER_PLAN_H__ #include "./scene.h" +#include "../graphics/screen_clipper.h" #define MAX_PORTAL_STEPS 6 struct RenderPlan { struct RenderProps stageProps[MAX_PORTAL_STEPS]; short stageCount; + short clippedPortalIndex; + short nearPolygonCount; + struct Vector2s16 nearPolygon[MAX_NEAR_POLYGON_SIZE]; }; void renderPlanBuild(struct RenderPlan* renderPlan, struct Scene* scene, struct RenderState* renderState); diff --git a/src/scene/scene.c b/src/scene/scene.c index 4a36293..3fd8cd2 100644 --- a/src/scene/scene.c +++ b/src/scene/scene.c @@ -120,40 +120,6 @@ void sceneInit(struct Scene* scene) { scene->freeCameraOffset = gZeroVec; } -void sceneRenderWithProperties(void* data, struct RenderProps* properties, struct RenderState* renderState) { - struct Scene* scene = (struct Scene*)data; - - u64 visibleRooms = 0; - staticRenderDetermineVisibleRooms(&properties->cameraMatrixInfo.cullingInformation, properties->fromRoom, &visibleRooms); - - int closerPortal = vector3DistSqrd(&properties->camera.transform.position, &scene->portals[0].transform.position) < vector3DistSqrd(&properties->camera.transform.position, &scene->portals[1].transform.position) ? 0 : 1; - int otherPortal = 1 - closerPortal; - - for (int i = 0; i < 2; ++i) { - if (gCollisionScene.portalTransforms[closerPortal] && - properties->exitPortalIndex != closerPortal && - staticRenderIsRoomVisible(visibleRooms, gCollisionScene.portalRooms[closerPortal])) { - portalRender( - &scene->portals[closerPortal], - gCollisionScene.portalTransforms[otherPortal] ? &scene->portals[otherPortal] : NULL, - properties, - sceneRenderWithProperties, - data, - renderState - ); - } - - closerPortal = 1 - closerPortal; - otherPortal = 1 - otherPortal; - } - - if (controllerGetButton(1, A_BUTTON) && properties->currentDepth == 2) { - return; - } - - staticRender(&properties->camera.transform, &properties->cameraMatrixInfo.cullingInformation, visibleRooms, renderState); -} - #define SOLID_COLOR 0, 0, 0, ENVIRONMENT, 0, 0, 0, ENVIRONMENT void sceneRenderPerformanceMetrics(struct Scene* scene, struct RenderState* renderState, struct GraphicsTask* task) { @@ -204,11 +170,6 @@ void sceneRender(struct Scene* scene, struct RenderState* renderState, struct Gr *lookAt = gLookAt; gSPLookAt(renderState->dl++, lookAt); - - struct RenderProps renderProperties; - - renderPropsInit(&renderProperties, &scene->camera, (float)SCREEN_WD / (float)SCREEN_HT, renderState, scene->player.body.currentRoom); - cameraApplyMatrices(renderState, &renderProperties.cameraMatrixInfo); gDPSetRenderMode(renderState->dl++, G_RM_ZB_OPA_SURF, G_RM_ZB_OPA_SURF2); @@ -217,8 +178,6 @@ void sceneRender(struct Scene* scene, struct RenderState* renderState, struct Gr renderPlanBuild(&renderPlan, scene, renderState); renderPlanExecute(&renderPlan, scene, renderState); - // sceneRenderWithProperties(scene, &renderProperties, renderState); - sceneRenderPortalGun(scene, renderState); gDPPipeSync(renderState->dl++);