Refactor rendering pipeline

This commit is contained in:
James Lambert 2022-05-25 17:30:34 -06:00
parent e65b6dbfec
commit 334b1561b8
18 changed files with 272 additions and 206 deletions

View file

@ -54,3 +54,10 @@ BLENDER_2_9=/blender/blender docker run -v /home/james/Blender/blender-2.93.1-li
where `/home/james/Blender/blender-2.93.1-linux-x64` is the folder where blender is located where `/home/james/Blender/blender-2.93.1-linux-x64` is the folder where blender is located
`/home/james/portal/portal64/vpk` is the folder where the portal vpk files are located `/home/james/portal/portal64/vpk` is the folder where the portal vpk files are located
`/home/james/portal/portal64/docker-output` is where you want the output of the build to located `portal.z64` will be put into this folder `/home/james/portal/portal64/docker-output` is where you want the output of the build to located `portal.z64` will be put into this folder
## Current TODO list
refactor dynamic rendering
cylinder collider type
cube dispenser
logic and trigger wiring

View file

@ -20,6 +20,8 @@
#define MAX_DYNAMIC_OBJECTS 16 #define MAX_DYNAMIC_OBJECTS 16
#define MAX_RENDER_COUNT 128
#define SIMPLE_CONTROLLER_MSG (5) #define SIMPLE_CONTROLLER_MSG (5)
#define PRINTF(a) #define PRINTF(a)

147
src/graphics/render_scene.c Normal file
View file

@ -0,0 +1,147 @@
#include "render_scene.h"
#include "../util/memory.h"
#include "defs.h"
#include "../levels/levels.h"
struct RenderScene* renderSceneInit(struct Transform* cameraTransform, struct RenderState *renderState, int capacity, u64 visibleRooms) {
stackMallockReset();
struct RenderScene* result = stackMallock(sizeof(struct RenderScene));
struct Vector3 cameraForward;
quatMultVector(&cameraTransform->rotation, &gForward, &cameraForward);
vector3Negate(&cameraForward, &cameraForward);
planeInitWithNormalAndPoint(&result->forwardPlane, &cameraForward, &cameraTransform->position);
result->currentRenderPart = 0;
result->maxRenderParts = capacity;
result->renderParts = stackMallock(sizeof(struct RenderPart) * capacity);
result->sortKeys = stackMallock(sizeof(int) * capacity);
result->materials = stackMallock(sizeof(short) * capacity);
result->renderOrder = NULL;
result->renderOrderCopy = NULL;
result->visibleRooms = visibleRooms;
result->renderState = renderState;
return result;
}
int renderSceneSortKey(int materialIndex, float distance) {
int distanceScaled = (int)(distance * SCENE_SCALE);
// sort transparent surfaces from back to front
if (materialIndex >= levelMaterialTransparentStart()) {
distanceScaled = 0x1000000 - distanceScaled;
}
return (materialIndex << 23) | (distanceScaled & 0x7FFFFF);
}
void renderSceneAdd(struct RenderScene* renderScene, Gfx* geometry, Mtx* matrix, int materialIndex, struct Vector3* at) {
if (renderScene->currentRenderPart == renderScene->maxRenderParts) {
return;
}
struct RenderPart* part = &renderScene->renderParts[renderScene->currentRenderPart];
part->geometry = geometry;
part->matrix = matrix;
renderScene->materials[renderScene->currentRenderPart] = materialIndex;
renderScene->sortKeys[renderScene->currentRenderPart] = renderSceneSortKey(materialIndex, planePointDistance(&renderScene->forwardPlane, at));
++renderScene->currentRenderPart;
}
void renderSceneSort(struct RenderScene* renderScene, int min, int max) {
if (min + 1 >= max) {
return;
}
int middle = (min + max) >> 1;
renderSceneSort(renderScene, min, middle);
renderSceneSort(renderScene, middle, max);
int aHead = min;
int bHead = middle;
int output = min;
while (aHead < middle && bHead < max) {
int sortDifference = renderScene->sortKeys[renderScene->renderOrder[aHead]] - renderScene->sortKeys[renderScene->renderOrder[bHead]];
if (sortDifference <= 0) {
renderScene->renderOrderCopy[output] = renderScene->renderOrder[aHead];
++output;
++aHead;
} else {
renderScene->renderOrderCopy[output] = renderScene->renderOrder[bHead];
++output;
++bHead;
}
}
while (aHead < middle) {
renderScene->renderOrderCopy[output] = renderScene->renderOrder[aHead];
++output;
++aHead;
}
while (bHead < max) {
renderScene->renderOrderCopy[output] = renderScene->renderOrder[bHead];
++output;
++bHead;
}
for (output = min; output < max; ++output) {
renderScene->renderOrder[output] = renderScene->renderOrderCopy[output];
}
}
void renderSceneGenerate(struct RenderScene* renderScene, struct RenderState* renderState) {
renderScene->renderOrder = stackMallock(sizeof(short) * renderScene->currentRenderPart);
renderScene->renderOrderCopy = stackMallock(sizeof(short) * renderScene->currentRenderPart);
for (int i = 0; i < renderScene->currentRenderPart; ++i) {
renderScene->renderOrder[i] = i;
}
renderSceneSort(renderScene, 0, renderScene->currentRenderPart);
int prevMaterial = -1;
gSPDisplayList(renderState->dl++, levelMaterialDefault());
for (int i = 0; i < renderScene->currentRenderPart; ++i) {
int renderIndex = renderScene->renderOrder[i];
int materialIndex = renderScene->materials[renderIndex];
if (materialIndex != prevMaterial && materialIndex != -1) {
if (prevMaterial != -1) {
gSPDisplayList(renderState->dl++, levelMaterialRevert(prevMaterial));
}
gSPDisplayList(renderState->dl++, levelMaterial(materialIndex));
prevMaterial = materialIndex;
}
struct RenderPart* renderPart = &renderScene->renderParts[renderIndex];
if (renderPart->matrix) {
gSPMatrix(renderState->dl++, renderPart->matrix, G_MTX_MODELVIEW | G_MTX_PUSH | G_MTX_MUL);
}
gSPDisplayList(renderState->dl++, renderPart->geometry);
if (renderPart->matrix) {
gSPPopMatrix(renderState->dl++, G_MTX_MODELVIEW);
}
}
if (prevMaterial != -1) {
gSPDisplayList(renderState->dl++, levelMaterialRevert(prevMaterial));
}
}

View file

@ -0,0 +1,31 @@
#ifndef __RENDER_SCENE_H__
#define __RENDER_SCENE_H__
#include <ultra64.h>
#include "../math/transform.h"
#include "../math/plane.h"
#include "renderstate.h"
struct RenderPart {
Mtx* matrix;
Gfx* geometry;
};
struct RenderScene {
u64 visibleRooms;
struct Plane forwardPlane;
struct RenderPart* renderParts;
short* materials;
int* sortKeys;
short* renderOrder;
short* renderOrderCopy;
int currentRenderPart;
int maxRenderParts;
struct RenderState *renderState;
};
struct RenderScene* renderSceneInit(struct Transform* cameraTransform, struct RenderState *renderState, int capacity, u64 visibleRooms);
void renderSceneAdd(struct RenderScene* renderScene, Gfx* geometry, Mtx* matrix, int materialIndex, struct Vector3* at);
void renderSceneGenerate(struct RenderScene* renderScene, struct RenderState* renderState);
#endif

View file

@ -21,7 +21,6 @@ void levelLoad(int index) {
gCurrentLevel = gLevelList[index]; gCurrentLevel = gLevelList[index];
collisionSceneInit(&gCollisionScene, gCurrentLevel->collisionQuads, gCurrentLevel->collisionQuadCount, &gCurrentLevel->world); collisionSceneInit(&gCollisionScene, gCurrentLevel->collisionQuads, gCurrentLevel->collisionQuadCount, &gCurrentLevel->world);
staticRenderInit();
} }
int levelMaterialCount() { int levelMaterialCount() {

View file

@ -3,109 +3,36 @@
#include "levels.h" #include "levels.h"
#include "util/memory.h" #include "util/memory.h"
#include "defs.h" #include "defs.h"
#include "../graphics/render_scene.h"
u16* gRenderOrder; void staticRenderPopulateRooms(struct FrustrumCullingInformation* cullingInfo, struct RenderScene* renderScene) {
u16* gRenderOrderCopy;
int* gSortKey;
void staticRenderInit() {
gRenderOrder = malloc(sizeof(u16) * gCurrentLevel->staticContentCount);
gRenderOrderCopy = malloc(sizeof(u16) * gCurrentLevel->staticContentCount);
gSortKey = malloc(sizeof(int) * (gCurrentLevel->staticContentCount + MAX_DYNAMIC_OBJECTS));
}
int staticRenderSorkKeyFromMaterial(int materialIndex, float distanceScaled) {
int distance = (int)distanceScaled;
// sort transparent surfaces from back to front
if (materialIndex >= levelMaterialTransparentStart()) {
distance = 0x1000000 - distance;
}
return (materialIndex << 23) | (distance & 0x7FFFFF);
}
int staticRenderGenerateSortKey(int index, struct FrustrumCullingInformation* cullingInfo) {
struct BoundingBoxs16* box = &gCurrentLevel->staticBoundingBoxes[index];
struct Vector3 boxCenter;
boxCenter.x = (box->minX + box->maxX) >> 1;
boxCenter.y = (box->minY + box->maxY) >> 1;
boxCenter.z = (box->minZ + box->maxZ) >> 1;
int distance = (int)sqrtf(vector3DistSqrd(&boxCenter, &cullingInfo->cameraPosScaled));
return staticRenderSorkKeyFromMaterial(gCurrentLevel->staticContent[index].materialIndex, distance);
}
void staticRenderSort(int min, int max) {
if (min + 1 >= max) {
return;
}
int middle = (min + max) >> 1;
staticRenderSort(min, middle);
staticRenderSort(middle, max);
int aHead = min;
int bHead = middle;
int output = min;
while (aHead < middle && bHead < max) {
int sortDifference = gSortKey[gRenderOrder[aHead]] - gSortKey[gRenderOrder[bHead]];
if (sortDifference <= 0) {
gRenderOrderCopy[output] = gRenderOrder[aHead];
++output;
++aHead;
} else {
gRenderOrderCopy[output] = gRenderOrder[bHead];
++output;
++bHead;
}
}
while (aHead < middle) {
gRenderOrderCopy[output] = gRenderOrder[aHead];
++output;
++aHead;
}
while (bHead < max) {
gRenderOrderCopy[output] = gRenderOrder[bHead];
++output;
++bHead;
}
for (output = min; output < max; ++output) {
gRenderOrder[output] = gRenderOrderCopy[output];
}
}
int staticRenderPopulateRooms(struct FrustrumCullingInformation* cullingInfo, u64 visitedRooms) {
int renderCount = 0;
int currentRoom = 0; int currentRoom = 0;
while (visitedRooms) { u64 visibleRooms = renderScene->visibleRooms;
if (0x1 & visitedRooms) {
while (visibleRooms) {
if (0x1 & visibleRooms) {
struct Rangeu16 staticRange = gCurrentLevel->roomStaticMapping[currentRoom]; struct Rangeu16 staticRange = gCurrentLevel->roomStaticMapping[currentRoom];
for (int i = staticRange.min; i < staticRange.max; ++i) { for (int i = staticRange.min; i < staticRange.max; ++i) {
if (isOutsideFrustrum(cullingInfo, &gCurrentLevel->staticBoundingBoxes[i])) { struct BoundingBoxs16* box = &gCurrentLevel->staticBoundingBoxes[i];
if (isOutsideFrustrum(cullingInfo, box)) {
continue; continue;
} }
gRenderOrder[renderCount] = i; struct Vector3 boxCenter;
gSortKey[i] = staticRenderGenerateSortKey(i, cullingInfo); boxCenter.x = (float)(box->minX + box->maxX) * (0.5f / SCENE_SCALE);
++renderCount; boxCenter.y = (float)(box->minY + box->maxY) * (0.5f / SCENE_SCALE);
boxCenter.z = (float)(box->minZ + box->maxZ) * (0.5f / SCENE_SCALE);
renderSceneAdd(renderScene, gCurrentLevel->staticContent[i].displayList, NULL, gCurrentLevel->staticContent[i].materialIndex, &boxCenter);
} }
} }
visitedRooms >>= 1; visibleRooms >>= 1;
++currentRoom; ++currentRoom;
} }
return renderCount;
} }
void staticRenderDetermineVisibleRooms(struct FrustrumCullingInformation* cullingInfo, u16 currentRoom, u64* visitedRooms) { void staticRenderDetermineVisibleRooms(struct FrustrumCullingInformation* cullingInfo, u16 currentRoom, u64* visitedRooms) {
@ -132,50 +59,16 @@ int staticRenderIsRoomVisible(u64 visibleRooms, u16 roomIndex) {
return (visibleRooms & (1LL << roomIndex)) != 0; return (visibleRooms & (1LL << roomIndex)) != 0;
} }
void staticRender(struct FrustrumCullingInformation* cullingInfo, u64 visibleRooms, struct RenderState* renderState) { void staticRender(struct Transform* cameraTransform, struct FrustrumCullingInformation* cullingInfo, u64 visibleRooms, struct RenderState* renderState) {
if (!gCurrentLevel) { if (!gCurrentLevel) {
return; return;
} }
int renderCount = staticRenderPopulateRooms(cullingInfo, visibleRooms); struct RenderScene* renderScene = renderSceneInit(cameraTransform, renderState, MAX_RENDER_COUNT, visibleRooms);
renderCount = dynamicScenePopulate(cullingInfo, renderCount, gCurrentLevel->staticContentCount, gSortKey, gRenderOrder); staticRenderPopulateRooms(cullingInfo, renderScene);
staticRenderSort(0, renderCount); dynamicScenePopulate(cullingInfo, renderScene);
int prevMaterial = -1; renderSceneGenerate(renderScene, renderState);
gSPDisplayList(renderState->dl++, levelMaterialDefault());
for (int i = 0; i < renderCount; ++i) {
int renderIndex = gRenderOrder[i];
int materialIndex;
if (renderIndex < gCurrentLevel->staticContentCount) {
materialIndex = gCurrentLevel->staticContent[renderIndex].materialIndex;
} else {
materialIndex = dynamicSceneObjectMaterialIndex(renderIndex - gCurrentLevel->staticContentCount);
}
if (materialIndex != prevMaterial && materialIndex != -1) {
if (prevMaterial != -1) {
gSPDisplayList(renderState->dl++, levelMaterialRevert(prevMaterial));
}
gSPDisplayList(renderState->dl++, levelMaterial(materialIndex));
prevMaterial = materialIndex;
}
if (renderIndex < gCurrentLevel->staticContentCount) {
gSPDisplayList(renderState->dl++, gCurrentLevel->staticContent[renderIndex].displayList);
} else {
dynamicSceneRenderObject(renderIndex - gCurrentLevel->staticContentCount, renderState);
}
}
if (prevMaterial != -1) {
gSPDisplayList(renderState->dl++, levelMaterialRevert(prevMaterial));
}
} }

View file

@ -6,11 +6,8 @@
#include "scene/camera.h" #include "scene/camera.h"
#include "../scene/dynamic_scene.h" #include "../scene/dynamic_scene.h"
void staticRenderInit();
int staticRenderSorkKeyFromMaterial(int materialIndex, float distanceScaled);
void staticRenderDetermineVisibleRooms(struct FrustrumCullingInformation* cullingInfo, u16 currentRoom, u64* visitedRooms); void staticRenderDetermineVisibleRooms(struct FrustrumCullingInformation* cullingInfo, u16 currentRoom, u64* visitedRooms);
int staticRenderIsRoomVisible(u64 visibleRooms, u16 roomIndex); int staticRenderIsRoomVisible(u64 visibleRooms, u16 roomIndex);
void staticRender(struct FrustrumCullingInformation* cullingInfo, u64 visibleRooms, struct RenderState* renderState); void staticRender(struct Transform* cameraTransform, struct FrustrumCullingInformation* cullingInfo, u64 visibleRooms, struct RenderState* renderState);
#endif #endif

View file

@ -1,6 +1,11 @@
#include "plane.h" #include "plane.h"
#include "mathf.h" #include "mathf.h"
void planeInitWithNormalAndPoint(struct Plane* plane, struct Vector3* normal, struct Vector3* point) {
plane->normal = *normal;
plane->d = -vector3Dot(normal, point);
}
int planeRayIntersection(struct Plane* plane, struct Vector3* rayOrigin, struct Vector3* rayDirection, float* rayDistance) { int planeRayIntersection(struct Plane* plane, struct Vector3* rayOrigin, struct Vector3* rayDirection, float* rayDistance) {
float normalDot = vector3Dot(&plane->normal, rayDirection); float normalDot = vector3Dot(&plane->normal, rayDirection);

View file

@ -8,6 +8,8 @@ struct Plane {
float d; float d;
}; };
void planeInitWithNormalAndPoint(struct Plane* plane, struct Vector3* normal, struct Vector3* point);
int planeRayIntersection(struct Plane* plane, struct Vector3* rayOrigin, struct Vector3* rayDirection, float* rayDistance); int planeRayIntersection(struct Plane* plane, struct Vector3* rayOrigin, struct Vector3* rayDirection, float* rayDistance);
float planePointDistance(struct Plane* plane, struct Vector3* point); float planePointDistance(struct Plane* plane, struct Vector3* point);

View file

@ -5,14 +5,12 @@
#include "../graphics/renderstate.h" #include "../graphics/renderstate.h"
#include "dynamic_scene.h" #include "dynamic_scene.h"
void buttonRender(void* data, struct RenderState* renderState) { void buttonRender(void* data, struct RenderScene* renderScene) {
struct Button* button = (struct Button*)data; struct Button* button = (struct Button*)data;
Mtx* matrix = renderStateRequestMatrices(renderState, 1); Mtx* matrix = renderStateRequestMatrices(renderScene->renderState, 1);
transformToMatrixL(&button->rigidBody.transform, matrix, SCENE_SCALE); transformToMatrixL(&button->rigidBody.transform, matrix, SCENE_SCALE);
gSPMatrix(renderState->dl++, matrix, G_MTX_MODELVIEW | G_MTX_PUSH | G_MTX_MUL); renderSceneAdd(renderScene, button_gfx, matrix, button_material_index, &button->rigidBody.transform.position);
gSPDisplayList(renderState->dl++, button_gfx);
gSPPopMatrix(renderState->dl++, G_MTX_MODELVIEW);
} }
void buttonInit(struct Button* button, struct Vector3* at, int roomIndex) { void buttonInit(struct Button* button, struct Vector3* at, int roomIndex) {
@ -22,7 +20,7 @@ void buttonInit(struct Button* button, struct Vector3* at, int roomIndex) {
button->rigidBody.currentRoom = roomIndex; button->rigidBody.currentRoom = roomIndex;
button->dynamicId = dynamicSceneAdd(button, buttonRender, &button->rigidBody.transform, 0.74f, button_material_index); button->dynamicId = dynamicSceneAdd(button, buttonRender, &button->rigidBody.transform, 0.74f);
} }
void buttonUpdate(struct Button* button) { void buttonUpdate(struct Button* button) {

View file

@ -58,14 +58,12 @@ struct ColliderTypeData gCubeCollider = {
&gCollisionBoxCallbacks, &gCollisionBoxCallbacks,
}; };
void cubeRender(void* data, struct RenderState* renderState) { void cubeRender(void* data, struct RenderScene* renderScene) {
struct Cube* cube = (struct Cube*)data; struct Cube* cube = (struct Cube*)data;
Mtx* matrix = renderStateRequestMatrices(renderState, 1); Mtx* matrix = renderStateRequestMatrices(renderScene->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); renderSceneAdd(renderScene, cube_gfx, matrix, cube_material_index, &cube->rigidBody.transform.position);
gSPDisplayList(renderState->dl++, cube_gfx);
gSPPopMatrix(renderState->dl++, G_MTX_MODELVIEW);
} }
void cubeInit(struct Cube* cube) { void cubeInit(struct Cube* cube) {
@ -74,7 +72,7 @@ void cubeInit(struct Cube* cube) {
cube->collisionObject.body->flags |= RigidBodyFlagsGrabbable; cube->collisionObject.body->flags |= RigidBodyFlagsGrabbable;
cube->dynamicId = dynamicSceneAdd(cube, cubeRender, &cube->rigidBody.transform, sqrtf(vector3MagSqrd(&gCubeCollisionBox.sideLength)), cube_material_index); cube->dynamicId = dynamicSceneAdd(cube, cubeRender, &cube->rigidBody.transform, sqrtf(vector3MagSqrd(&gCubeCollisionBox.sideLength)));
} }
void cubeUpdate(struct Cube* cube) { void cubeUpdate(struct Cube* cube) {

View file

@ -6,6 +6,7 @@
struct DynamicScene gDynamicScene; struct DynamicScene gDynamicScene;
#define FLAG_MASK (DYNAMIC_SCENE_OBJECT_FLAGS_USED | DYNAMIC_SCENE_OBJECT_FLAGS_ACTIVE | DYNAMIC_SCENE_OBJECT_FLAGS_TOUCHING_PORTAL) #define FLAG_MASK (DYNAMIC_SCENE_OBJECT_FLAGS_USED | DYNAMIC_SCENE_OBJECT_FLAGS_ACTIVE | DYNAMIC_SCENE_OBJECT_FLAGS_TOUCHING_PORTAL)
#define FLAG_VALUE_NOT_TOUCHING_PORTAL (DYNAMIC_SCENE_OBJECT_FLAGS_USED | DYNAMIC_SCENE_OBJECT_FLAGS_ACTIVE) #define FLAG_VALUE_NOT_TOUCHING_PORTAL (DYNAMIC_SCENE_OBJECT_FLAGS_USED | DYNAMIC_SCENE_OBJECT_FLAGS_ACTIVE)
#define FLAG_VALUE_TOUCHING_PORTAL (DYNAMIC_SCENE_OBJECT_FLAGS_USED | DYNAMIC_SCENE_OBJECT_FLAGS_ACTIVE | DYNAMIC_SCENE_OBJECT_FLAGS_TOUCHING_PORTAL) #define FLAG_VALUE_TOUCHING_PORTAL (DYNAMIC_SCENE_OBJECT_FLAGS_USED | DYNAMIC_SCENE_OBJECT_FLAGS_ACTIVE | DYNAMIC_SCENE_OBJECT_FLAGS_TOUCHING_PORTAL)
@ -15,24 +16,30 @@ void dynamicSceneInit() {
} }
} }
void dynamicSceneRenderTouchingPortal(struct RenderState* renderState) {
void dynamicScenePopulateWithFlags(struct FrustrumCullingInformation* cullingInfo, struct RenderScene* renderScene, int flags) {
for (int i = 0; i < MAX_DYNAMIC_SCENE_OBJECTS; ++i) { for (int i = 0; i < MAX_DYNAMIC_SCENE_OBJECTS; ++i) {
struct DynamicSceneObject* object = &gDynamicScene.objects[i]; struct DynamicSceneObject* object = &gDynamicScene.objects[i];
if ((object->flags & FLAG_MASK) == FLAG_VALUE_TOUCHING_PORTAL) { if ((object->flags & FLAG_MASK) == flags) {
if (object->materialIndex != -1) { struct Vector3 scaledPos;
gSPDisplayList(renderState->dl++, levelMaterial(object->materialIndex)); vector3Scale(&object->transform->position, &scaledPos, SCENE_SCALE);
if (isSphereOutsideFrustrum(cullingInfo, &scaledPos, object->scaledRadius)) {
continue;
} }
gDynamicScene.objects[i].renderCallback(gDynamicScene.objects[i].data, renderState); object->renderCallback(object->data, renderScene);
if (object->materialIndex != -1) {
gSPDisplayList(renderState->dl++, levelMaterialRevert(object->materialIndex));
}
} }
} }
} }
int dynamicSceneAdd(void* data, DynamicRender renderCallback, struct Transform* transform, float radius, u16 materialIndex) { void dynamicSceneRenderTouchingPortal(struct Transform* cameraTransform, struct FrustrumCullingInformation* cullingInfo, struct RenderState* renderState) {
struct RenderScene* tmpScene = renderSceneInit(cameraTransform, renderState, MAX_DYNAMIC_SCENE_OBJECTS, ~0);
dynamicScenePopulateWithFlags(cullingInfo, tmpScene, FLAG_VALUE_NOT_TOUCHING_PORTAL);
renderSceneGenerate(tmpScene, renderState);
}
int dynamicSceneAdd(void* data, DynamicRender renderCallback, struct Transform* transform, float radius) {
for (int i = 0; i < MAX_DYNAMIC_SCENE_OBJECTS; ++i) { for (int i = 0; i < MAX_DYNAMIC_SCENE_OBJECTS; ++i) {
struct DynamicSceneObject* object = &gDynamicScene.objects[i]; struct DynamicSceneObject* object = &gDynamicScene.objects[i];
if (!(object->flags & DYNAMIC_SCENE_OBJECT_FLAGS_USED)) { if (!(object->flags & DYNAMIC_SCENE_OBJECT_FLAGS_USED)) {
@ -42,7 +49,6 @@ int dynamicSceneAdd(void* data, DynamicRender renderCallback, struct Transform*
object->renderCallback = renderCallback; object->renderCallback = renderCallback;
object->transform = transform; object->transform = transform;
object->scaledRadius = radius * SCENE_SCALE; object->scaledRadius = radius * SCENE_SCALE;
object->materialIndex = materialIndex;
return i; return i;
} }
} }
@ -66,42 +72,6 @@ void dynamicSceneClearFlags(int id, int flags) {
gDynamicScene.objects[id].flags &= ~flags; gDynamicScene.objects[id].flags &= ~flags;
} }
int dynamicScenePopulate(struct FrustrumCullingInformation* cullingInfo, int currentObjectCount, int staticObjectCount, int* sortKey, u16* renderOrder) { void dynamicScenePopulate(struct FrustrumCullingInformation* cullingInfo, struct RenderScene* renderScene) {
for (int i = 0; i < MAX_DYNAMIC_SCENE_OBJECTS; ++i) { dynamicScenePopulateWithFlags(cullingInfo, renderScene, FLAG_VALUE_NOT_TOUCHING_PORTAL);
struct DynamicSceneObject* object = &gDynamicScene.objects[i];
if ((object->flags & FLAG_MASK) == FLAG_VALUE_NOT_TOUCHING_PORTAL) {
struct Vector3 scaledPos;
vector3Scale(&object->transform->position, &scaledPos, SCENE_SCALE);
if (isSphereOutsideFrustrum(cullingInfo, &scaledPos, object->scaledRadius)) {
continue;
}
renderOrder[currentObjectCount] = staticObjectCount + i;
sortKey[staticObjectCount + i] = staticRenderSorkKeyFromMaterial(
object->materialIndex,
sqrtf(vector3DistSqrd(&scaledPos, &cullingInfo->cameraPosScaled))
);
++currentObjectCount;
}
}
return currentObjectCount;
}
void dynamicSceneRenderObject(int index, struct RenderState* renderState) {
if (index < 0 || index >= MAX_DYNAMIC_OBJECTS) {
return;
}
struct DynamicSceneObject* object = &gDynamicScene.objects[index];
object->renderCallback(object->data, renderState);
}
int dynamicSceneObjectMaterialIndex(int objectIndex) {
if (objectIndex < 0 || objectIndex >= MAX_DYNAMIC_OBJECTS) {
return -1;
}
return gDynamicScene.objects[objectIndex].materialIndex;
} }

View file

@ -4,8 +4,9 @@
#include "../graphics/renderstate.h" #include "../graphics/renderstate.h"
#include "../math/transform.h" #include "../math/transform.h"
#include "../scene/camera.h" #include "../scene/camera.h"
#include "../graphics/render_scene.h"
typedef void (*DynamicRender)(void* data, struct RenderState* renderState); typedef void (*DynamicRender)(void* data, struct RenderScene* renderScene);
#define MAX_DYNAMIC_SCENE_OBJECTS 32 #define MAX_DYNAMIC_SCENE_OBJECTS 32
@ -20,7 +21,6 @@ struct DynamicSceneObject {
DynamicRender renderCallback; DynamicRender renderCallback;
struct Transform* transform; struct Transform* transform;
float scaledRadius; float scaledRadius;
u16 materialIndex;
u16 flags; u16 flags;
}; };
@ -30,16 +30,13 @@ struct DynamicScene {
void dynamicSceneInit(); void dynamicSceneInit();
void dynamicSceneRenderTouchingPortal(struct RenderState* renderState); void dynamicSceneRenderTouchingPortal(struct Transform* cameraTransform, struct FrustrumCullingInformation* cullingInfo, struct RenderState* renderState);
int dynamicSceneAdd(void* data, DynamicRender renderCallback, struct Transform* transform, float radius, u16 materialIndex); int dynamicSceneAdd(void* data, DynamicRender renderCallback, struct Transform* transform, float radius);
void dynamicSceneRemove(int id); void dynamicSceneRemove(int id);
void dynamicSceneSetFlags(int id, int flags); void dynamicSceneSetFlags(int id, int flags);
void dynamicSceneClearFlags(int id, int flags); void dynamicSceneClearFlags(int id, int flags);
int dynamicScenePopulate(struct FrustrumCullingInformation* cullingInfo, int currentObjectCount, int staticObjectCount, int* sortKey, u16* renderOrder); void dynamicScenePopulate(struct FrustrumCullingInformation* cullingInfo, struct RenderScene* renderScene);
void dynamicSceneRenderObject(int index, struct RenderState* renderState);
int dynamicSceneObjectMaterialIndex(int objectIndex);
#endif #endif

View file

@ -123,7 +123,7 @@ void renderPropsNext(struct RenderProps* current, struct RenderProps* next, stru
// render any objects halfway through portals // render any objects halfway through portals
cameraSetupMatrices(&next->camera, renderState, next->aspectRatio, &next->perspectiveCorrect, current->viewport, NULL); cameraSetupMatrices(&next->camera, renderState, next->aspectRatio, &next->perspectiveCorrect, current->viewport, NULL);
dynamicSceneRenderTouchingPortal(renderState); dynamicSceneRenderTouchingPortal(&next->camera.transform, &current->cullingInfo, renderState);
Vp* viewport = renderPropsBuildViewport(next, renderState); Vp* viewport = renderPropsBuildViewport(next, renderState);

View file

@ -87,7 +87,7 @@ void sceneRenderWithProperties(void* data, struct RenderProps* properties, struc
otherPortal = 1 - otherPortal; otherPortal = 1 - otherPortal;
} }
staticRender(&properties->cullingInfo, visibleRooms, renderState); staticRender(&properties->camera.transform, &properties->cullingInfo, visibleRooms, renderState);
} }
#define SOLID_COLOR 0, 0, 0, ENVIRONMENT, 0, 0, 0, ENVIRONMENT #define SOLID_COLOR 0, 0, 0, ENVIRONMENT, 0, 0, 0, ENVIRONMENT
@ -130,7 +130,7 @@ void sceneRender(struct Scene* scene, struct RenderState* renderState, struct Gr
gDPSetRenderMode(renderState->dl++, G_RM_ZB_OPA_SURF, G_RM_ZB_OPA_SURF2); gDPSetRenderMode(renderState->dl++, G_RM_ZB_OPA_SURF, G_RM_ZB_OPA_SURF2);
dynamicSceneRenderTouchingPortal(renderState); dynamicSceneRenderTouchingPortal(&scene->camera.transform, &renderProperties.cullingInfo, renderState);
sceneRenderWithProperties(scene, &renderProperties, renderState); sceneRenderWithProperties(scene, &renderProperties, renderState);

View file

@ -339,3 +339,20 @@ void memCopy(void* target, const void* src, int size)
--size; --size;
} }
} }
#define STACK_MALLOC_SIZE_BYTES 4096
#define STACK_MALLOC_SIZE_WORDS (STACK_MALLOC_SIZE_BYTES >> 3)
int gStackMallocAt;
long long gStackMalloc[STACK_MALLOC_SIZE_WORDS];
void stackMallockReset() {
gStackMallocAt = 0;
}
void* stackMallock(int size) {
int nWords = (size + 7) >> 3;
void* result = &gStackMalloc[gStackMallocAt];
gStackMallocAt += nWords;
return result;
}

View file

@ -49,4 +49,7 @@ int calculateLargestFreeChunk();
extern void zeroMemory(void* memory, int size); extern void zeroMemory(void* memory, int size);
extern void memCopy(void* target, const void* src, int size); extern void memCopy(void* target, const void* src, int size);
void stackMallockReset();
void* stackMallock(int size);
#endif #endif