mirror of
https://github.com/mwpenny/portal64-still-alive.git
synced 2024-10-19 22:27:36 -04:00
Refactor rendering pipeline
This commit is contained in:
parent
e65b6dbfec
commit
334b1561b8
|
@ -53,4 +53,11 @@ 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
|
||||
`/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
|
Binary file not shown.
|
@ -20,6 +20,8 @@
|
|||
|
||||
#define MAX_DYNAMIC_OBJECTS 16
|
||||
|
||||
#define MAX_RENDER_COUNT 128
|
||||
|
||||
#define SIMPLE_CONTROLLER_MSG (5)
|
||||
|
||||
#define PRINTF(a)
|
||||
|
|
147
src/graphics/render_scene.c
Normal file
147
src/graphics/render_scene.c
Normal 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));
|
||||
}
|
||||
}
|
31
src/graphics/render_scene.h
Normal file
31
src/graphics/render_scene.h
Normal 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
|
|
@ -21,7 +21,6 @@ void levelLoad(int index) {
|
|||
gCurrentLevel = gLevelList[index];
|
||||
|
||||
collisionSceneInit(&gCollisionScene, gCurrentLevel->collisionQuads, gCurrentLevel->collisionQuadCount, &gCurrentLevel->world);
|
||||
staticRenderInit();
|
||||
}
|
||||
|
||||
int levelMaterialCount() {
|
||||
|
|
|
@ -3,109 +3,36 @@
|
|||
#include "levels.h"
|
||||
#include "util/memory.h"
|
||||
#include "defs.h"
|
||||
#include "../graphics/render_scene.h"
|
||||
|
||||
u16* gRenderOrder;
|
||||
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;
|
||||
void staticRenderPopulateRooms(struct FrustrumCullingInformation* cullingInfo, struct RenderScene* renderScene) {
|
||||
int currentRoom = 0;
|
||||
|
||||
while (visitedRooms) {
|
||||
if (0x1 & visitedRooms) {
|
||||
u64 visibleRooms = renderScene->visibleRooms;
|
||||
|
||||
while (visibleRooms) {
|
||||
if (0x1 & visibleRooms) {
|
||||
struct Rangeu16 staticRange = gCurrentLevel->roomStaticMapping[currentRoom];
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
gRenderOrder[renderCount] = i;
|
||||
gSortKey[i] = staticRenderGenerateSortKey(i, cullingInfo);
|
||||
++renderCount;
|
||||
struct Vector3 boxCenter;
|
||||
boxCenter.x = (float)(box->minX + box->maxX) * (0.5f / SCENE_SCALE);
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
return renderCount;
|
||||
}
|
||||
|
||||
void staticRenderDetermineVisibleRooms(struct FrustrumCullingInformation* cullingInfo, u16 currentRoom, u64* visitedRooms) {
|
||||
|
@ -132,50 +59,16 @@ int staticRenderIsRoomVisible(u64 visibleRooms, u16 roomIndex) {
|
|||
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) {
|
||||
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;
|
||||
|
||||
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));
|
||||
}
|
||||
renderSceneGenerate(renderScene, renderState);
|
||||
}
|
|
@ -6,11 +6,8 @@
|
|||
#include "scene/camera.h"
|
||||
#include "../scene/dynamic_scene.h"
|
||||
|
||||
void staticRenderInit();
|
||||
|
||||
int staticRenderSorkKeyFromMaterial(int materialIndex, float distanceScaled);
|
||||
void staticRenderDetermineVisibleRooms(struct FrustrumCullingInformation* cullingInfo, u16 currentRoom, u64* visitedRooms);
|
||||
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
|
|
@ -1,6 +1,11 @@
|
|||
#include "plane.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) {
|
||||
float normalDot = vector3Dot(&plane->normal, rayDirection);
|
||||
|
||||
|
|
|
@ -8,6 +8,8 @@ struct Plane {
|
|||
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);
|
||||
|
||||
float planePointDistance(struct Plane* plane, struct Vector3* point);
|
||||
|
|
|
@ -5,14 +5,12 @@
|
|||
#include "../graphics/renderstate.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;
|
||||
Mtx* matrix = renderStateRequestMatrices(renderState, 1);
|
||||
Mtx* matrix = renderStateRequestMatrices(renderScene->renderState, 1);
|
||||
transformToMatrixL(&button->rigidBody.transform, matrix, SCENE_SCALE);
|
||||
|
||||
gSPMatrix(renderState->dl++, matrix, G_MTX_MODELVIEW | G_MTX_PUSH | G_MTX_MUL);
|
||||
gSPDisplayList(renderState->dl++, button_gfx);
|
||||
gSPPopMatrix(renderState->dl++, G_MTX_MODELVIEW);
|
||||
renderSceneAdd(renderScene, button_gfx, matrix, button_material_index, &button->rigidBody.transform.position);
|
||||
}
|
||||
|
||||
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->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) {
|
||||
|
|
|
@ -58,14 +58,12 @@ struct ColliderTypeData gCubeCollider = {
|
|||
&gCollisionBoxCallbacks,
|
||||
};
|
||||
|
||||
void cubeRender(void* data, struct RenderState* renderState) {
|
||||
void cubeRender(void* data, struct RenderScene* renderScene) {
|
||||
struct Cube* cube = (struct Cube*)data;
|
||||
Mtx* matrix = renderStateRequestMatrices(renderState, 1);
|
||||
Mtx* matrix = renderStateRequestMatrices(renderScene->renderState, 1);
|
||||
transformToMatrixL(&cube->rigidBody.transform, matrix, SCENE_SCALE);
|
||||
|
||||
gSPMatrix(renderState->dl++, matrix, G_MTX_MODELVIEW | G_MTX_PUSH | G_MTX_MUL);
|
||||
gSPDisplayList(renderState->dl++, cube_gfx);
|
||||
gSPPopMatrix(renderState->dl++, G_MTX_MODELVIEW);
|
||||
renderSceneAdd(renderScene, cube_gfx, matrix, cube_material_index, &cube->rigidBody.transform.position);
|
||||
}
|
||||
|
||||
void cubeInit(struct Cube* cube) {
|
||||
|
@ -74,7 +72,7 @@ void cubeInit(struct Cube* cube) {
|
|||
|
||||
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) {
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
struct DynamicScene gDynamicScene;
|
||||
|
||||
#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_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) {
|
||||
struct DynamicSceneObject* object = &gDynamicScene.objects[i];
|
||||
if ((object->flags & FLAG_MASK) == FLAG_VALUE_TOUCHING_PORTAL) {
|
||||
if (object->materialIndex != -1) {
|
||||
gSPDisplayList(renderState->dl++, levelMaterial(object->materialIndex));
|
||||
if ((object->flags & FLAG_MASK) == flags) {
|
||||
struct Vector3 scaledPos;
|
||||
vector3Scale(&object->transform->position, &scaledPos, SCENE_SCALE);
|
||||
|
||||
if (isSphereOutsideFrustrum(cullingInfo, &scaledPos, object->scaledRadius)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
gDynamicScene.objects[i].renderCallback(gDynamicScene.objects[i].data, renderState);
|
||||
|
||||
if (object->materialIndex != -1) {
|
||||
gSPDisplayList(renderState->dl++, levelMaterialRevert(object->materialIndex));
|
||||
}
|
||||
object->renderCallback(object->data, renderScene);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
struct DynamicSceneObject* object = &gDynamicScene.objects[i];
|
||||
if (!(object->flags & DYNAMIC_SCENE_OBJECT_FLAGS_USED)) {
|
||||
|
@ -42,7 +49,6 @@ int dynamicSceneAdd(void* data, DynamicRender renderCallback, struct Transform*
|
|||
object->renderCallback = renderCallback;
|
||||
object->transform = transform;
|
||||
object->scaledRadius = radius * SCENE_SCALE;
|
||||
object->materialIndex = materialIndex;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
@ -66,42 +72,6 @@ void dynamicSceneClearFlags(int id, int flags) {
|
|||
gDynamicScene.objects[id].flags &= ~flags;
|
||||
}
|
||||
|
||||
int dynamicScenePopulate(struct FrustrumCullingInformation* cullingInfo, int currentObjectCount, int staticObjectCount, int* sortKey, u16* renderOrder) {
|
||||
for (int i = 0; i < MAX_DYNAMIC_SCENE_OBJECTS; ++i) {
|
||||
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;
|
||||
void dynamicScenePopulate(struct FrustrumCullingInformation* cullingInfo, struct RenderScene* renderScene) {
|
||||
dynamicScenePopulateWithFlags(cullingInfo, renderScene, FLAG_VALUE_NOT_TOUCHING_PORTAL);
|
||||
}
|
|
@ -4,8 +4,9 @@
|
|||
#include "../graphics/renderstate.h"
|
||||
#include "../math/transform.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
|
||||
|
||||
|
@ -20,7 +21,6 @@ struct DynamicSceneObject {
|
|||
DynamicRender renderCallback;
|
||||
struct Transform* transform;
|
||||
float scaledRadius;
|
||||
u16 materialIndex;
|
||||
u16 flags;
|
||||
};
|
||||
|
||||
|
@ -30,16 +30,13 @@ struct DynamicScene {
|
|||
|
||||
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 dynamicSceneSetFlags(int id, int flags);
|
||||
void dynamicSceneClearFlags(int id, int flags);
|
||||
|
||||
int dynamicScenePopulate(struct FrustrumCullingInformation* cullingInfo, int currentObjectCount, int staticObjectCount, int* sortKey, u16* renderOrder);
|
||||
|
||||
void dynamicSceneRenderObject(int index, struct RenderState* renderState);
|
||||
int dynamicSceneObjectMaterialIndex(int objectIndex);
|
||||
void dynamicScenePopulate(struct FrustrumCullingInformation* cullingInfo, struct RenderScene* renderScene);
|
||||
|
||||
#endif
|
|
@ -123,7 +123,7 @@ void renderPropsNext(struct RenderProps* current, struct RenderProps* next, stru
|
|||
|
||||
// render any objects halfway through portals
|
||||
cameraSetupMatrices(&next->camera, renderState, next->aspectRatio, &next->perspectiveCorrect, current->viewport, NULL);
|
||||
dynamicSceneRenderTouchingPortal(renderState);
|
||||
dynamicSceneRenderTouchingPortal(&next->camera.transform, ¤t->cullingInfo, renderState);
|
||||
|
||||
Vp* viewport = renderPropsBuildViewport(next, renderState);
|
||||
|
||||
|
|
|
@ -87,7 +87,7 @@ void sceneRenderWithProperties(void* data, struct RenderProps* properties, struc
|
|||
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
|
||||
|
@ -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);
|
||||
|
||||
dynamicSceneRenderTouchingPortal(renderState);
|
||||
dynamicSceneRenderTouchingPortal(&scene->camera.transform, &renderProperties.cullingInfo, renderState);
|
||||
|
||||
sceneRenderWithProperties(scene, &renderProperties, renderState);
|
||||
|
||||
|
|
|
@ -338,4 +338,21 @@ void memCopy(void* target, const void* src, int size)
|
|||
++srcAsChar;
|
||||
--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;
|
||||
}
|
|
@ -49,4 +49,7 @@ int calculateLargestFreeChunk();
|
|||
extern void zeroMemory(void* memory, int size);
|
||||
extern void memCopy(void* target, const void* src, int size);
|
||||
|
||||
void stackMallockReset();
|
||||
void* stackMallock(int size);
|
||||
|
||||
#endif
|
Loading…
Reference in a new issue