Work on portal rendering bugs

This commit is contained in:
James Lambert 2022-05-10 22:38:39 -06:00
parent 04e889521d
commit 930a4e4bcc
17 changed files with 215 additions and 58 deletions

View file

@ -2,29 +2,32 @@
void renderStateInit(struct RenderState* renderState) { void renderStateInit(struct RenderState* renderState) {
renderState->dl = renderState->glist; renderState->dl = renderState->glist;
renderState->currentMatrix = 0; renderState->currentMemoryChunk = 0;
renderState->currentLight = 0;
renderState->currentChunkEnd = MAX_DL_LENGTH; renderState->currentChunkEnd = MAX_DL_LENGTH;
} }
Mtx* renderStateRequestMatrices(struct RenderState* renderState, unsigned count) { void* renderStateRequestMemory(struct RenderState* renderState, unsigned size) {
if (renderState->currentMatrix + count <= MAX_ACTIVE_TRANSFORMS) { unsigned memorySlots = (size + 7) >> 3;
Mtx* result = &renderState->matrices[renderState->currentMatrix];
renderState->currentMatrix += count; if (renderState->currentMemoryChunk + memorySlots <= MAX_RENDER_STATE_MEMORY_CHUNKS) {
void* result = &renderState->renderStateMemory[renderState->currentMemoryChunk];
renderState->currentMemoryChunk += memorySlots;
return result; return result;
} }
return 0; return 0;
} }
Light* renderStateRequestLights(struct RenderState* renderState, unsigned count) { Mtx* renderStateRequestMatrices(struct RenderState* renderState, unsigned count) {
if (renderState->currentLight + count <= MAX_ACTIVE_TRANSFORMS) { return renderStateRequestMemory(renderState, sizeof(Mtx) * count);
Light* result = &renderState->lights[renderState->currentLight]; }
renderState->currentLight += count;
return result;
}
return 0; Light* renderStateRequestLights(struct RenderState* renderState, unsigned count) {
return renderStateRequestMemory(renderState, sizeof(Light) * count);
}
Vp* renderStateRequestViewport(struct RenderState* renderState) {
return renderStateRequestMemory(renderState, sizeof(Vp));
} }
void renderStateFlushCache(struct RenderState* renderState) { void renderStateFlushCache(struct RenderState* renderState) {

View file

@ -4,22 +4,22 @@
#include <ultra64.h> #include <ultra64.h>
#define MAX_DL_LENGTH 2000 #define MAX_DL_LENGTH 2000
#define MAX_ACTIVE_TRANSFORMS 100 #define MAX_RENDER_STATE_MEMORY 6400
#define MAX_RENDER_STATE_MEMORY_CHUNKS (MAX_RENDER_STATE_MEMORY / sizeof(u64))
#define MAX_DYNAMIC_LIGHTS 128 #define MAX_DYNAMIC_LIGHTS 128
struct RenderState { struct RenderState {
Gfx glist[MAX_DL_LENGTH]; Gfx glist[MAX_DL_LENGTH];
Mtx matrices[MAX_ACTIVE_TRANSFORMS]; u64 renderStateMemory[MAX_RENDER_STATE_MEMORY_CHUNKS];
Light lights[MAX_DYNAMIC_LIGHTS];
Gfx* dl; Gfx* dl;
unsigned short currentMatrix; unsigned short currentMemoryChunk;
unsigned short currentLight; unsigned short currentChunkEnd;
unsigned currentChunkEnd;
}; };
void renderStateInit(struct RenderState* renderState); void renderStateInit(struct RenderState* renderState);
Mtx* renderStateRequestMatrices(struct RenderState* renderState, unsigned count); Mtx* renderStateRequestMatrices(struct RenderState* renderState, unsigned count);
Light* renderStateRequestLights(struct RenderState* renderState, unsigned count); Light* renderStateRequestLights(struct RenderState* renderState, unsigned count);
Vp* renderStateRequestViewport(struct RenderState* renderState);
void renderStateFlushCache(struct RenderState* renderState); void renderStateFlushCache(struct RenderState* renderState);
Gfx* renderStateAllocateDLChunk(struct RenderState* renderState, unsigned count); Gfx* renderStateAllocateDLChunk(struct RenderState* renderState, unsigned count);
Gfx* renderStateReplaceDL(struct RenderState* renderState, Gfx* nextDL); Gfx* renderStateReplaceDL(struct RenderState* renderState, Gfx* nextDL);

View file

@ -10,6 +10,7 @@
#include "util/memory.h" #include "util/memory.h"
#include "string.h" #include "string.h"
#include "controls/controller.h" #include "controls/controller.h"
#include "scene/dynamic_scene.h"
#include "levels/levels.h" #include "levels/levels.h"
@ -129,6 +130,7 @@ static void gameProc(void* arg) {
heapInit(_heapStart, memoryEnd); heapInit(_heapStart, memoryEnd);
romInit(); romInit();
dynamicSceneInit();
contactSolverInit(&gContactSolver); contactSolverInit(&gContactSolver);
levelLoad(0); levelLoad(0);
sceneInit(&gScene); sceneInit(&gScene);

View file

@ -48,7 +48,9 @@ void collisionObjectCollideWithQuad(struct CollisionObject* object, struct Colli
return; return;
} }
contactSolverAssign(contact, &localContact, 1); if (contactSolverAssign(contact, &localContact, 1) && object->body) {
object->body->flags |= RigidBodyIsTouchingPortal;
}
} else if (contact) { } else if (contact) {
contactSolverRemoveContact(contactSolver, contact); contactSolverRemoveContact(contactSolver, contact);
} }

View file

@ -379,7 +379,7 @@ struct ContactState* contactSolverGetContact(struct ContactConstraintState* cont
return result; return result;
} }
void contactSolverAssign(struct ContactConstraintState* into, struct ContactConstraintState* from, int filterPortalContacts) { int contactSolverAssign(struct ContactConstraintState* into, struct ContactConstraintState* from, int filterPortalContacts) {
for (int sourceIndex = 0; sourceIndex < from->contactCount; ++sourceIndex) { for (int sourceIndex = 0; sourceIndex < from->contactCount; ++sourceIndex) {
int targetIndex; int targetIndex;
@ -399,9 +399,11 @@ void contactSolverAssign(struct ContactConstraintState* into, struct ContactCons
} }
int copiedCount = 0; int copiedCount = 0;
int result = 0;
for (int sourceIndex = 0; sourceIndex < from->contactCount; ++sourceIndex) { for (int sourceIndex = 0; sourceIndex < from->contactCount; ++sourceIndex) {
if (filterPortalContacts && collisionSceneIsTouchingPortal(&from->contacts[sourceIndex].ra)) { if (filterPortalContacts && collisionSceneIsTouchingPortal(&from->contacts[sourceIndex].ra)) {
result = 1;
continue; continue;
} }
@ -415,4 +417,6 @@ void contactSolverAssign(struct ContactConstraintState* into, struct ContactCons
into->normal = from->normal; into->normal = from->normal;
into->restitution = from->restitution; into->restitution = from->restitution;
into->friction = from->friction; into->friction = from->friction;
return result;
} }

View file

@ -62,7 +62,7 @@ void contactSolverRemoveContact(struct ContactSolver* solver, struct ContactCons
struct ContactState* contactSolverGetContact(struct ContactConstraintState* contact, int id); struct ContactState* contactSolverGetContact(struct ContactConstraintState* contact, int id);
void contactSolverAssign(struct ContactConstraintState* into, struct ContactConstraintState* from, int filterPortalContacts); int contactSolverAssign(struct ContactConstraintState* into, struct ContactConstraintState* from, int filterPortalContacts);
#endif #endif

View file

@ -73,6 +73,10 @@ void rigidBodyCheckPortals(struct RigidBody* rigidBody) {
enum RigidBodyFlags newFlags = 0; enum RigidBodyFlags newFlags = 0;
if (rigidBody->flags & RigidBodyIsTouchingPortal) {
newFlags |= RigidBodyWasTouchingPortal;
}
for (int i = 0; i < 2; ++i) { for (int i = 0; i < 2; ++i) {
transformPointInverse(gCollisionScene.portalTransforms[i], &rigidBody->transform.position, &localPoint); transformPointInverse(gCollisionScene.portalTransforms[i], &rigidBody->transform.position, &localPoint);
@ -143,7 +147,9 @@ void rigidBodyCheckPortals(struct RigidBody* rigidBody) {
RigidBodyFlagsInFrontPortal1 | RigidBodyFlagsInFrontPortal1 |
RigidBodyFlagsPortalsInactive | RigidBodyFlagsPortalsInactive |
RigidBodyFlagsCrossedPortal0 | RigidBodyFlagsCrossedPortal0 |
RigidBodyFlagsCrossedPortal1 RigidBodyFlagsCrossedPortal1 |
RigidBodyIsTouchingPortal |
RigidBodyWasTouchingPortal
); );
rigidBody->flags |= newFlags; rigidBody->flags |= newFlags;
} }

View file

@ -11,6 +11,8 @@ enum RigidBodyFlags {
RigidBodyFlagsCrossedPortal0 = (1 << 3), RigidBodyFlagsCrossedPortal0 = (1 << 3),
RigidBodyFlagsCrossedPortal1 = (1 << 4), RigidBodyFlagsCrossedPortal1 = (1 << 4),
RigidBodyFlagsGrabbable = (1 << 5), RigidBodyFlagsGrabbable = (1 << 5),
RigidBodyIsTouchingPortal = (1 << 6),
RigidBodyWasTouchingPortal = (1 << 7),
}; };
struct RigidBody { struct RigidBody {

View file

@ -2,6 +2,7 @@
#include "camera.h" #include "camera.h"
#include "math/transform.h" #include "math/transform.h"
#include "defs.h" #include "defs.h"
#include "../graphics/graphics.h"
void cameraInit(struct Camera* camera, float fov, float near, float far) { void cameraInit(struct Camera* camera, float fov, float near, float far) {
transformInitIdentity(&camera->transform); transformInitIdentity(&camera->transform);
@ -28,7 +29,7 @@ void cameraBuildProjectionMatrix(struct Camera* camera, float matrix[4][4], u16*
guPerspectiveF(matrix, perspectiveNormalize, camera->fov, aspectRatio, camera->nearPlane * planeScalar, camera->farPlane * planeScalar, 1.0f); 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) { Mtx* cameraSetupMatrices(struct Camera* camera, struct RenderState* renderState, float aspectRatio, u16* perspNorm, Vp* viewport) {
Mtx* viewProjMatrix = renderStateRequestMatrices(renderState, 2); Mtx* viewProjMatrix = renderStateRequestMatrices(renderState, 2);
if (!viewProjMatrix) { if (!viewProjMatrix) {
@ -42,9 +43,18 @@ Mtx* cameraSetupMatrices(struct Camera* camera, struct RenderState* renderState,
float persp[4][4]; float persp[4][4];
float combined[4][4]; float combined[4][4];
cameraBuildViewMatrix(camera, view); float scaleX = viewport->vp.vscale[0] * (1.0f / (SCREEN_WD << 1));
float scaleY = viewport->vp.vscale[1] * (1.0f / (SCREEN_HT << 1));
float centerX = ((float)viewport->vp.vtrans[0] - (SCREEN_WD << 1)) * (1.0f / (SCREEN_WD << 1));
float centerY = ((SCREEN_HT << 1) - (float)viewport->vp.vtrans[1]) * (1.0f / (SCREEN_HT << 1));
guOrthoF(combined, centerX - scaleX, centerX + scaleX, centerY - scaleY, centerY + scaleY, 1.0f, -1.0f, 1.0f);
u16 perspectiveNormalize; u16 perspectiveNormalize;
cameraBuildProjectionMatrix(camera, persp, &perspectiveNormalize, aspectRatio); cameraBuildProjectionMatrix(camera, view, &perspectiveNormalize, aspectRatio);
guMtxCatF(view, combined, persp);
cameraBuildViewMatrix(camera, view);
guMtxCatF(view, persp, combined); guMtxCatF(view, persp, combined);
guMtxF2L(combined, &viewProjMatrix[1]); guMtxF2L(combined, &viewProjMatrix[1]);

View file

@ -18,6 +18,6 @@ struct Camera {
void cameraInit(struct Camera* camera, float fov, float near, float far); void cameraInit(struct Camera* camera, float fov, float near, float far);
void cameraBuildViewMatrix(struct Camera* camera, float matrix[4][4]); void cameraBuildViewMatrix(struct Camera* camera, float matrix[4][4]);
void cameraBuildProjectionMatrix(struct Camera* camera, float matrix[4][4], u16* perspectiveNorm, float aspectRatio); 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); Mtx* cameraSetupMatrices(struct Camera* camera, struct RenderState* renderState, float aspectRatio, u16* perspNorm, Vp* viewport);
#endif #endif

View file

@ -5,6 +5,7 @@
#include "../graphics/debug_render.h" #include "../graphics/debug_render.h"
#include "levels/levels.h" #include "levels/levels.h"
#include "physics/collision_scene.h" #include "physics/collision_scene.h"
#include "dynamic_scene.h"
struct CollisionBox gCubeCollisionBox = { struct CollisionBox gCubeCollisionBox = {
{0.3165f, 0.3165f, 0.3165f} {0.3165f, 0.3165f, 0.3165f}
@ -57,22 +58,29 @@ struct ColliderTypeData gCubeCollider = {
&gCollisionBoxCallbacks, &gCollisionBoxCallbacks,
}; };
void cubeInit(struct Cube* cube) { void cubeRender(void* data, struct RenderState* renderState) {
collisionObjectInit(&cube->collisionObject, &gCubeCollider, &cube->rigidBody, 1.0f); struct Cube* cube = (struct Cube*)data;
collisionSceneAddDynamicObject(&cube->collisionObject);
cube->collisionObject.body->flags |= RigidBodyFlagsGrabbable;
}
void cubeUpdate(struct Cube* cube) {
}
void cubeRender(struct Cube* cube, struct RenderState* renderState) {
Mtx* matrix = renderStateRequestMatrices(renderState, 1); Mtx* matrix = renderStateRequestMatrices(renderState, 1);
transformToMatrixL(&cube->rigidBody.transform, matrix, SCENE_SCALE); transformToMatrixL(&cube->rigidBody.transform, matrix, SCENE_SCALE);
gSPMatrix(renderState->dl++, matrix, G_MTX_MODELVIEW | G_MTX_PUSH | G_MTX_MUL); gSPMatrix(renderState->dl++, matrix, G_MTX_MODELVIEW | G_MTX_PUSH | G_MTX_MUL);
gSPDisplayList(renderState->dl++, cube_CubeSimpleBevel_mesh); gSPDisplayList(renderState->dl++, cube_CubeSimpleBevel_mesh);
gSPPopMatrix(renderState->dl++, G_MTX_MODELVIEW); gSPPopMatrix(renderState->dl++, G_MTX_MODELVIEW);
} }
void cubeInit(struct Cube* cube) {
collisionObjectInit(&cube->collisionObject, &gCubeCollider, &cube->rigidBody, 1.0f);
collisionSceneAddDynamicObject(&cube->collisionObject);
cube->collisionObject.body->flags |= RigidBodyFlagsGrabbable;
cube->dynamicId = dynamicSceneAdd(cube, cubeRender);
}
void cubeUpdate(struct Cube* cube) {
if (cube->rigidBody.flags & (RigidBodyIsTouchingPortal | RigidBodyWasTouchingPortal)) {
dynamicSceneSetFlags(cube->dynamicId, DYNAMIC_SCENE_OBJECT_FLAGS_TOUCHING_PORTAL);
} else {
dynamicSceneClearFlags(cube->dynamicId, DYNAMIC_SCENE_OBJECT_FLAGS_TOUCHING_PORTAL);
}
}

View file

@ -8,10 +8,10 @@
struct Cube { struct Cube {
struct CollisionObject collisionObject; struct CollisionObject collisionObject;
struct RigidBody rigidBody; struct RigidBody rigidBody;
short dynamicId;
}; };
void cubeInit(struct Cube* cube); void cubeInit(struct Cube* cube);
void cubeUpdate(struct Cube* cube); void cubeUpdate(struct Cube* cube);
void cubeRender(struct Cube* cube, struct RenderState* renderState);
#endif #endif

54
src/scene/dynamic_scene.c Normal file
View file

@ -0,0 +1,54 @@
#include "dynamic_scene.h"
struct DynamicScene gDynamicScene;
void dynamicSceneInit() {
for (int i = 0; i < MAX_DYNAMIC_SCENE_OBJECTS; ++i) {
gDynamicScene.objects[i].flags = 0;
}
}
void dynamicSceneRender(struct RenderState* renderState, int touchingPortals) {
int flagMask = DYNAMIC_SCENE_OBJECT_FLAGS_USED | DYNAMIC_SCENE_OBJECT_FLAGS_ACTIVE | DYNAMIC_SCENE_OBJECT_FLAGS_TOUCHING_PORTAL;
int flagValue = DYNAMIC_SCENE_OBJECT_FLAGS_USED | DYNAMIC_SCENE_OBJECT_FLAGS_ACTIVE;
if (touchingPortals) {
flagValue |= DYNAMIC_SCENE_OBJECT_FLAGS_TOUCHING_PORTAL;
}
for (int i = 0; i < MAX_DYNAMIC_SCENE_OBJECTS; ++i) {
if ((gDynamicScene.objects[i].flags & flagMask) == flagValue) {
gDynamicScene.objects[i].renderCallback(gDynamicScene.objects[i].data, renderState);
}
}
}
int dynamicSceneAdd(void* data, DynamicRender renderCallback) {
for (int i = 0; i < MAX_DYNAMIC_SCENE_OBJECTS; ++i) {
if (!(gDynamicScene.objects[i].flags & DYNAMIC_SCENE_OBJECT_FLAGS_USED)) {
gDynamicScene.objects[i].flags = DYNAMIC_SCENE_OBJECT_FLAGS_USED | DYNAMIC_SCENE_OBJECT_FLAGS_ACTIVE;
gDynamicScene.objects[i].data = data;
gDynamicScene.objects[i].renderCallback = renderCallback;
return i;
}
}
return INVALID_DYNAMIC_OBJECT;
}
void dynamicSceneRemove(int id) {
if (id < 0 || id >= MAX_DYNAMIC_SCENE_OBJECTS) {
return;
}
gDynamicScene.objects[id].flags = 0;
}
void dynamicSceneSetFlags(int id, int flags) {
gDynamicScene.objects[id].flags |= flags;
}
void dynamicSceneClearFlags(int id, int flags) {
gDynamicScene.objects[id].flags &= ~flags;
}

35
src/scene/dynamic_scene.h Normal file
View file

@ -0,0 +1,35 @@
#ifndef __DYNAMIC_SCENE_H__
#define __DYNAMIC_SCENE_H__
#include "../graphics/renderstate.h"
typedef void (*DynamicRender)(void* data, struct RenderState* renderState);
#define MAX_DYNAMIC_SCENE_OBJECTS 32
#define DYNAMIC_SCENE_OBJECT_FLAGS_USED (1 << 0)
#define DYNAMIC_SCENE_OBJECT_FLAGS_ACTIVE (1 << 1)
#define DYNAMIC_SCENE_OBJECT_FLAGS_TOUCHING_PORTAL (1 << 2)
#define INVALID_DYNAMIC_OBJECT -1
struct DynamicSceneObject {
void* data;
DynamicRender renderCallback;
int flags;
};
struct DynamicScene {
struct DynamicSceneObject objects[MAX_DYNAMIC_SCENE_OBJECTS];
};
void dynamicSceneInit();
void dynamicSceneRender(struct RenderState* renderState, int touchingPortals);
int dynamicSceneAdd(void* data, DynamicRender renderCallback);
void dynamicSceneRemove(int id);
void dynamicSceneSetFlags(int id, int flags);
void dynamicSceneClearFlags(int id, int flags);
#endif

View file

@ -4,6 +4,7 @@
#include "../graphics/screen_clipper.h" #include "../graphics/screen_clipper.h"
#include "../graphics/graphics.h" #include "../graphics/graphics.h"
#include "../defs.h" #include "../defs.h"
#include "dynamic_scene.h"
#define CALC_SCREEN_SPACE(clip_space, screen_size) ((clip_space + 1.0f) * ((screen_size) / 2)) #define CALC_SCREEN_SPACE(clip_space, screen_size) ((clip_space + 1.0f) * ((screen_size) / 2))
@ -34,7 +35,8 @@ struct Quaternion gVerticalFlip = {0.0f, 1.0f, 0.0f, 0.0f};
void renderPropsInit(struct RenderProps* props, struct Camera* camera, float aspectRatio, struct RenderState* renderState) { void renderPropsInit(struct RenderProps* props, struct Camera* camera, float aspectRatio, struct RenderState* renderState) {
props->camera = *camera; props->camera = *camera;
props->aspectRatio = aspectRatio; props->aspectRatio = aspectRatio;
props->perspectiveMatrix = cameraSetupMatrices(camera, renderState, aspectRatio, &props->perspectiveCorrect); props->perspectiveMatrix = cameraSetupMatrices(camera, renderState, aspectRatio, &props->perspectiveCorrect, &fullscreenViewport);
props->viewport = &fullscreenViewport;
props->currentDepth = STARTING_RENDER_DEPTH; props->currentDepth = STARTING_RENDER_DEPTH;
props->minX = 0; props->minX = 0;
@ -43,7 +45,7 @@ void renderPropsInit(struct RenderProps* props, struct Camera* camera, float asp
props->maxY = SCREEN_HT; props->maxY = SCREEN_HT;
} }
void renderPropsNext(struct RenderProps* current, struct RenderProps* next, struct Transform* fromPortal, struct Transform* toPortal, short minX, short minY, short maxX, short maxY, struct RenderState* renderState) { void renderPropsNext(struct RenderProps* current, struct RenderProps* next, struct Transform* fromPortal, struct Transform* toPortal, struct RenderState* renderState) {
struct Transform otherInverse; struct Transform otherInverse;
transformInvert(fromPortal, &otherInverse); transformInvert(fromPortal, &otherInverse);
struct Transform portalCombined; struct Transform portalCombined;
@ -53,16 +55,30 @@ void renderPropsNext(struct RenderProps* current, struct RenderProps* next, stru
next->aspectRatio = current->aspectRatio; next->aspectRatio = current->aspectRatio;
transformConcat(&portalCombined, &current->camera.transform, &next->camera.transform); transformConcat(&portalCombined, &current->camera.transform, &next->camera.transform);
next->perspectiveMatrix = cameraSetupMatrices(&next->camera, renderState, next->aspectRatio, &next->perspectiveCorrect); // render any objects halfway through portals
cameraSetupMatrices(&next->camera, renderState, next->aspectRatio, &next->perspectiveCorrect, current->viewport);
dynamicSceneRender(renderState, 1);
Vp* viewport = renderStateRequestViewport(renderState);
viewport->vp.vscale[0] = (next->maxX - next->minX) << 1;
viewport->vp.vscale[1] = (next->maxY - next->minY) << 1;
viewport->vp.vscale[2] = G_MAXZ/2;
viewport->vp.vscale[3] = 0;
viewport->vp.vtrans[0] = (next->maxX + next->minX) << 1;
viewport->vp.vtrans[1] = (next->maxY + next->minY) << 1;
viewport->vp.vtrans[2] = G_MAXZ/2;
viewport->vp.vtrans[3] = 0;
next->viewport = viewport;
next->perspectiveMatrix = cameraSetupMatrices(&next->camera, renderState, next->aspectRatio, &next->perspectiveCorrect, viewport);
next->currentDepth = current->currentDepth - 1; next->currentDepth = current->currentDepth - 1;
next->minX = minX; gSPViewport(renderState->dl++, viewport);
next->minY = minY; gDPSetScissor(renderState->dl++, G_SC_NON_INTERLACE, next->minX, next->minY, next->maxX, next->maxY);
next->maxX = maxX;
next->maxY = maxY;
gDPSetScissor(renderState->dl++, G_SC_NON_INTERLACE, minX, minY, maxX, maxY);
} }
void portalInit(struct Portal* portal, enum PortalFlags flags) { void portalInit(struct Portal* portal, enum PortalFlags flags) {
@ -107,19 +123,26 @@ void portalRender(struct Portal* portal, struct Portal* otherPortal, struct Rend
screenClipperBoundingPoints(&clipper, gPortalOutline, sizeof(gPortalOutline) / sizeof(*gPortalOutline), &clippingBounds); screenClipperBoundingPoints(&clipper, gPortalOutline, sizeof(gPortalOutline) / sizeof(*gPortalOutline), &clippingBounds);
if (clippingBounds.min.x < clippingBounds.max.x && clippingBounds.min.y < clippingBounds.max.y) { if (clippingBounds.min.x < clippingBounds.max.x && clippingBounds.min.y < clippingBounds.max.y) {
int minX = CALC_SCREEN_SPACE(clippingBounds.min.x, SCREEN_WD);
int maxX = CALC_SCREEN_SPACE(clippingBounds.max.x, SCREEN_WD);
int minY = CALC_SCREEN_SPACE(-clippingBounds.max.y, SCREEN_HT);
int maxY = CALC_SCREEN_SPACE(-clippingBounds.min.y, SCREEN_HT);
struct RenderProps nextProps; struct RenderProps nextProps;
renderPropsNext(props, &nextProps, &portal->transform, &otherPortal->transform, minX, minY, maxX, maxY, renderState);
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);
renderPropsNext(props, &nextProps, &portal->transform, &otherPortal->transform, renderState);
sceneRenderer(data, &nextProps, renderState); sceneRenderer(data, &nextProps, renderState);
// revert to previous state // revert to previous state
gSPMatrix(renderState->dl++, osVirtualToPhysical(props->perspectiveMatrix), G_MTX_PROJECTION | G_MTX_LOAD | G_MTX_NOPUSH); gSPMatrix(renderState->dl++, osVirtualToPhysical(props->perspectiveMatrix), G_MTX_PROJECTION | G_MTX_LOAD | G_MTX_NOPUSH);
gSPPerspNormalize(renderState->dl++, props->perspectiveCorrect); gSPPerspNormalize(renderState->dl++, props->perspectiveCorrect);
gDPSetScissor(renderState->dl++, G_SC_NON_INTERLACE, props->minX, props->minY, props->maxX, props->maxY); gDPSetScissor(renderState->dl++, G_SC_NON_INTERLACE, props->minX, props->minY, props->maxX, props->maxY);
gSPViewport(renderState->dl++, props->viewport);
Mtx* matrix = renderStateRequestMatrices(renderState, 1); Mtx* matrix = renderStateRequestMatrices(renderState, 1);

View file

@ -26,6 +26,7 @@ struct RenderProps {
struct Camera camera; struct Camera camera;
float aspectRatio; float aspectRatio;
Mtx* perspectiveMatrix; Mtx* perspectiveMatrix;
Vp* viewport;
u16 perspectiveCorrect; u16 perspectiveCorrect;
short currentDepth; short currentDepth;
@ -38,7 +39,7 @@ struct RenderProps {
#define STARTING_RENDER_DEPTH 1 #define STARTING_RENDER_DEPTH 1
void renderPropsInit(struct RenderProps* props, struct Camera* camera, float aspectRatio, struct RenderState* renderState); void renderPropsInit(struct RenderProps* props, struct Camera* camera, float aspectRatio, struct RenderState* renderState);
void renderPropsNext(struct RenderProps* current, struct RenderProps* next, struct Transform* fromPortal, struct Transform* toPortal, short minX, short minY, short maxX, short maxY, struct RenderState* renderState); void 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 portalInit(struct Portal* portal, enum PortalFlags flags);

View file

@ -21,6 +21,7 @@
#include "../scene/portal_surface.h" #include "../scene/portal_surface.h"
#include "../math/mathf.h" #include "../math/mathf.h"
#include "./hud.h" #include "./hud.h"
#include "dynamic_scene.h"
struct Vector3 gStartPosition = {5.0f, 1.2f, -5.0f}; struct Vector3 gStartPosition = {5.0f, 1.2f, -5.0f};
@ -67,7 +68,7 @@ void sceneRenderWithProperties(void* data, struct RenderProps* properties, struc
staticRender(renderState); staticRender(renderState);
cubeRender(&scene->cube, renderState); dynamicSceneRender(renderState, 0);
} }
#define SOLID_COLOR 0, 0, 0, ENVIRONMENT, 0, 0, 0, ENVIRONMENT #define SOLID_COLOR 0, 0, 0, ENVIRONMENT, 0, 0, 0, ENVIRONMENT
@ -92,6 +93,10 @@ void sceneRender(struct Scene* scene, struct RenderState* renderState, struct Gr
renderProperties.camera = scene->camera; renderProperties.camera = scene->camera;
renderProperties.currentDepth = STARTING_RENDER_DEPTH; renderProperties.currentDepth = STARTING_RENDER_DEPTH;
gDPSetRenderMode(renderState->dl++, G_RM_ZB_OPA_SURF, G_RM_ZB_OPA_SURF2);
dynamicSceneRender(renderState, 1);
sceneRenderWithProperties(scene, &renderProperties, renderState); sceneRenderWithProperties(scene, &renderProperties, renderState);
gDPPipeSync(renderState->dl++); gDPPipeSync(renderState->dl++);
@ -129,6 +134,8 @@ void sceneUpdate(struct Scene* scene) {
playerUpdate(&scene->player, &scene->camera.transform); playerUpdate(&scene->player, &scene->camera.transform);
sceneCheckPortals(scene); sceneCheckPortals(scene);
cubeUpdate(&scene->cube);
collisionSceneUpdateDynamics(); collisionSceneUpdateDynamics();