Only keep one clipper result in the render plan
This commit is contained in:
parent
d824c42317
commit
f10fc3ef95
2
Makefile
2
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)
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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);
|
||||
|
|
110
src/scene/portal_render.c
Normal file
110
src/scene/portal_render.c
Normal file
|
@ -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);
|
||||
}
|
12
src/scene/portal_render.h
Normal file
12
src/scene/portal_render.h
Normal file
|
@ -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
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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++);
|
||||
|
|
Loading…
Reference in a new issue