1
0
Fork 0
mirror of https://github.com/zeldaret/oot.git synced 2024-12-02 15:55:59 +00:00
oot/src/code/z_lights.c

401 lines
12 KiB
C
Raw Normal View History

#include "global.h"
#include "assets/objects/gameplay_keep/gameplay_keep.h"
2020-03-17 04:31:30 +00:00
#define LIGHTS_BUFFER_SIZE 32
2020-03-17 04:31:30 +00:00
typedef struct {
/* 0x000 */ s32 numOccupied;
/* 0x004 */ s32 searchIndex;
/* 0x008 */ LightNode buf[LIGHTS_BUFFER_SIZE];
} LightsBuffer; // size = 0x188
LightsBuffer sLightsBuffer;
void Lights_PointSetInfo(LightInfo* info, s16 x, s16 y, s16 z, u8 r, u8 g, u8 b, s16 radius, s32 type) {
2020-03-17 04:31:30 +00:00
info->type = type;
info->params.point.x = x;
info->params.point.y = y;
info->params.point.z = z;
Lights_PointSetColorAndRadius(info, r, g, b, radius);
2020-03-17 04:31:30 +00:00
}
void Lights_PointNoGlowSetInfo(LightInfo* info, s16 x, s16 y, s16 z, u8 r, u8 g, u8 b, s16 radius) {
Lights_PointSetInfo(info, x, y, z, r, g, b, radius, LIGHT_POINT_NOGLOW);
2020-03-17 04:31:30 +00:00
}
void Lights_PointGlowSetInfo(LightInfo* info, s16 x, s16 y, s16 z, u8 r, u8 g, u8 b, s16 radius) {
Lights_PointSetInfo(info, x, y, z, r, g, b, radius, LIGHT_POINT_GLOW);
2020-03-17 04:31:30 +00:00
}
void Lights_PointSetColorAndRadius(LightInfo* info, u8 r, u8 g, u8 b, s16 radius) {
info->params.point.color[0] = r;
info->params.point.color[1] = g;
info->params.point.color[2] = b;
info->params.point.radius = radius;
2020-03-17 04:31:30 +00:00
}
void Lights_DirectionalSetInfo(LightInfo* info, s8 x, s8 y, s8 z, u8 r, u8 g, u8 b) {
info->type = LIGHT_DIRECTIONAL;
info->params.dir.x = x;
info->params.dir.y = y;
info->params.dir.z = z;
info->params.dir.color[0] = r;
info->params.dir.color[1] = g;
info->params.dir.color[2] = b;
2020-03-17 04:31:30 +00:00
}
// unused
void Lights_Reset(Lights* lights, u8 ambentR, u8 ambentG, u8 ambentB) {
lights->l.a.l.col[0] = lights->l.a.l.colc[0] = ambentR;
lights->l.a.l.col[1] = lights->l.a.l.colc[1] = ambentG;
lights->l.a.l.col[2] = lights->l.a.l.colc[2] = ambentB;
lights->numLights = 0;
2020-03-17 04:31:30 +00:00
}
/*
* Draws every light in the provided Lights group
*/
void Lights_Draw(Lights* lights, GraphicsContext* gfxCtx) {
Light* light;
s32 i;
2020-03-17 04:31:30 +00:00
OPEN_DISPS(gfxCtx, "../z_lights.c", 339);
gSPNumLights(POLY_OPA_DISP++, lights->numLights);
gSPNumLights(POLY_XLU_DISP++, lights->numLights);
i = 0;
light = &lights->l.l[0];
while (i < lights->numLights) {
2022-10-21 22:57:30 +00:00
gSPLight(POLY_OPA_DISP++, light, ++i);
gSPLight(POLY_XLU_DISP++, light, i);
light++;
2020-03-22 21:19:43 +00:00
}
2020-03-17 04:31:30 +00:00
2022-10-21 22:57:30 +00:00
// ambient light is total number of lights + 1
gSPLight(POLY_OPA_DISP++, &lights->l.a, ++i);
gSPLight(POLY_XLU_DISP++, &lights->l.a, i);
CLOSE_DISPS(gfxCtx, "../z_lights.c", 352);
}
Light* Lights_FindSlot(Lights* lights) {
if (lights->numLights >= 7) {
return NULL;
} else {
return &lights->l.l[lights->numLights++];
}
2020-03-17 04:31:30 +00:00
}
void Lights_BindPoint(Lights* lights, LightParams* params, Vec3f* vec) {
f32 xDiff;
f32 yDiff;
f32 zDiff;
f32 posDiff;
f32 scale;
Light* light;
if (vec != NULL) {
xDiff = params->point.x - vec->x;
yDiff = params->point.y - vec->y;
zDiff = params->point.z - vec->z;
scale = params->point.radius;
posDiff = SQ(xDiff) + SQ(yDiff) + SQ(zDiff);
if (posDiff < SQ(scale)) {
light = Lights_FindSlot(lights);
if (light != NULL) {
posDiff = sqrtf(posDiff);
if (1) {}
scale = posDiff / scale;
scale = 1 - SQ(scale);
light->l.col[0] = light->l.colc[0] = params->point.color[0] * scale;
light->l.col[1] = light->l.colc[1] = params->point.color[1] * scale;
light->l.col[2] = light->l.colc[2] = params->point.color[2] * scale;
scale = (posDiff < 1.0f) ? 120.0f : 120.0f / posDiff;
light->l.dir[0] = xDiff * scale;
light->l.dir[1] = yDiff * scale;
light->l.dir[2] = zDiff * scale;
}
}
}
}
2020-03-17 04:31:30 +00:00
void Lights_BindDirectional(Lights* lights, LightParams* params, Vec3f* vec) {
Light* light = Lights_FindSlot(lights);
2020-03-17 04:31:30 +00:00
2020-03-22 21:19:43 +00:00
if (light != NULL) {
light->l.col[0] = light->l.colc[0] = params->dir.color[0];
light->l.col[1] = light->l.colc[1] = params->dir.color[1];
light->l.col[2] = light->l.colc[2] = params->dir.color[2];
light->l.dir[0] = params->dir.x;
light->l.dir[1] = params->dir.y;
light->l.dir[2] = params->dir.z;
2020-03-17 04:31:30 +00:00
}
}
/**
* For every light in a provided list, try to find a free slot in the provided Lights group and bind
* a light to it. Then apply color and positional/directional info for each light
* based on the parameters supplied by the node.
*
* Note: Lights in a given list can only be bound to however many free slots are
* available in the Lights group. This is at most 7 slots for a new group, but could be less.
*/
void Lights_BindAll(Lights* lights, LightNode* listHead, Vec3f* vec) {
LightsBindFunc bindFuncs[] = { Lights_BindPoint, Lights_BindDirectional, Lights_BindPoint };
LightInfo* info;
while (listHead != NULL) {
info = listHead->info;
bindFuncs[info->type](lights, &info->params, vec);
listHead = listHead->next;
}
}
2020-03-17 04:31:30 +00:00
LightNode* Lights_FindBufSlot(void) {
LightNode* node;
2020-03-17 04:31:30 +00:00
if (sLightsBuffer.numOccupied >= LIGHTS_BUFFER_SIZE) {
2020-03-17 04:31:30 +00:00
return NULL;
2020-03-22 21:19:43 +00:00
}
2020-03-17 04:31:30 +00:00
node = &sLightsBuffer.buf[sLightsBuffer.searchIndex];
2020-03-17 04:31:30 +00:00
while (node->info != NULL) {
sLightsBuffer.searchIndex++;
2020-03-17 04:31:30 +00:00
if (sLightsBuffer.searchIndex < LIGHTS_BUFFER_SIZE) {
node++;
2020-03-22 21:19:43 +00:00
} else {
sLightsBuffer.searchIndex = 0;
node = &sLightsBuffer.buf[0];
2020-03-17 04:31:30 +00:00
}
}
sLightsBuffer.numOccupied++;
2020-03-17 04:31:30 +00:00
return node;
2020-03-17 04:31:30 +00:00
}
// return type must not be void to match
s32 Lights_FreeNode(LightNode* light) {
2020-03-22 21:19:43 +00:00
if (light != NULL) {
sLightsBuffer.numOccupied--;
2020-03-17 04:31:30 +00:00
light->info = NULL;
sLightsBuffer.searchIndex = (light - sLightsBuffer.buf) / sizeof(LightNode);
2020-03-17 04:31:30 +00:00
}
}
void LightContext_Init(PlayState* play, LightContext* lightCtx) {
LightContext_InitList(play, lightCtx);
LightContext_SetAmbientColor(lightCtx, 80, 80, 80);
LightContext_SetFog(lightCtx, 0, 0, 0, ENV_FOGNEAR_MAX, ENV_ZFAR_MAX);
bzero(&sLightsBuffer, sizeof(sLightsBuffer));
2020-03-17 04:31:30 +00:00
}
void LightContext_SetAmbientColor(LightContext* lightCtx, u8 r, u8 g, u8 b) {
lightCtx->ambientColor[0] = r;
lightCtx->ambientColor[1] = g;
lightCtx->ambientColor[2] = b;
2020-03-17 04:31:30 +00:00
}
void LightContext_SetFog(LightContext* lightCtx, u8 r, u8 g, u8 b, s16 fogNear, s16 zFar) {
lightCtx->fogColor[0] = r;
lightCtx->fogColor[1] = g;
lightCtx->fogColor[2] = b;
lightCtx->fogNear = fogNear;
lightCtx->zFar = zFar;
2020-03-17 04:31:30 +00:00
}
/**
* Allocate a new Lights group and initialize the ambient color with that provided by LightContext
*/
Lights* LightContext_NewLights(LightContext* lightCtx, GraphicsContext* gfxCtx) {
return Lights_New(gfxCtx, lightCtx->ambientColor[0], lightCtx->ambientColor[1], lightCtx->ambientColor[2]);
2020-03-17 04:31:30 +00:00
}
void LightContext_InitList(PlayState* play, LightContext* lightCtx) {
lightCtx->listHead = NULL;
2020-03-17 04:31:30 +00:00
}
void LightContext_DestroyList(PlayState* play, LightContext* lightCtx) {
while (lightCtx->listHead != NULL) {
LightContext_RemoveLight(play, lightCtx, lightCtx->listHead);
lightCtx->listHead = lightCtx->listHead->next;
2020-03-17 04:31:30 +00:00
}
}
/**
* Insert a new light into the list pointed to by LightContext
*
* Note: Due to the limited number of slots in a Lights group, inserting too many lights in the
* list may result in older entries not being bound to a Light when calling Lights_BindAll
*/
LightNode* LightContext_InsertLight(PlayState* play, LightContext* lightCtx, LightInfo* info) {
LightNode* node;
2020-03-17 04:31:30 +00:00
node = Lights_FindBufSlot();
if (node != NULL) {
node->info = info;
node->prev = NULL;
node->next = lightCtx->listHead;
2020-03-17 04:31:30 +00:00
if (lightCtx->listHead != NULL) {
lightCtx->listHead->prev = node;
2020-03-22 21:19:43 +00:00
}
2020-03-17 04:31:30 +00:00
lightCtx->listHead = node;
2020-03-17 04:31:30 +00:00
}
return node;
2020-03-17 04:31:30 +00:00
}
void LightContext_RemoveLight(PlayState* play, LightContext* lightCtx, LightNode* node) {
if (node != NULL) {
if (node->prev != NULL) {
node->prev->next = node->next;
2020-03-22 21:19:43 +00:00
} else {
lightCtx->listHead = node->next;
2020-03-22 21:19:43 +00:00
}
2020-03-17 04:31:30 +00:00
if (node->next != NULL) {
node->next->prev = node->prev;
2020-03-22 21:19:43 +00:00
}
2020-03-17 04:31:30 +00:00
Lights_FreeNode(node);
2020-03-17 04:31:30 +00:00
}
}
// unused
Lights* Lights_NewAndDraw(GraphicsContext* gfxCtx, u8 ambientR, u8 ambientG, u8 ambientB, u8 numLights, u8 r, u8 g,
u8 b, s8 x, s8 y, s8 z) {
Lights* lights;
s32 i;
lights = Graph_Alloc(gfxCtx, sizeof(Lights));
lights->l.a.l.col[0] = lights->l.a.l.colc[0] = ambientR;
lights->l.a.l.col[1] = lights->l.a.l.colc[1] = ambientG;
lights->l.a.l.col[2] = lights->l.a.l.colc[2] = ambientB;
lights->numLights = numLights;
for (i = 0; i < numLights; i++) {
lights->l.l[i].l.col[0] = lights->l.l[i].l.colc[0] = r;
lights->l.l[i].l.col[1] = lights->l.l[i].l.colc[1] = g;
lights->l.l[i].l.col[2] = lights->l.l[i].l.colc[2] = b;
lights->l.l[i].l.dir[0] = x;
lights->l.l[i].l.dir[1] = y;
lights->l.l[i].l.dir[2] = z;
}
2020-03-17 04:31:30 +00:00
Lights_Draw(lights, gfxCtx);
2020-03-17 04:31:30 +00:00
return lights;
}
2020-03-17 04:31:30 +00:00
Lights* Lights_New(GraphicsContext* gfxCtx, u8 ambientR, u8 ambientG, u8 ambientB) {
Lights* lights;
lights = Graph_Alloc(gfxCtx, sizeof(Lights));
lights->l.a.l.col[0] = lights->l.a.l.colc[0] = ambientR;
lights->l.a.l.col[1] = lights->l.a.l.colc[1] = ambientG;
lights->l.a.l.col[2] = lights->l.a.l.colc[2] = ambientB;
lights->numLights = 0;
return lights;
}
void Lights_GlowCheck(PlayState* play) {
LightNode* node;
LightPoint* params;
Vec3f pos;
Vec3f multDest;
f32 cappedInvWDest;
f32 wX;
f32 wY;
s32 wZ;
s32 zBuf;
node = play->lightCtx.listHead;
while (node != NULL) {
params = &node->info->params.point;
if (node->info->type == LIGHT_POINT_GLOW) {
pos.x = params->x;
pos.y = params->y;
pos.z = params->z;
Actor_ProjectPos(play, &pos, &multDest, &cappedInvWDest);
params->drawGlow = false;
wX = multDest.x * cappedInvWDest;
wY = multDest.y * cappedInvWDest;
if ((multDest.z > 1.0f) && (fabsf(wX) < 1.0f) && (fabsf(wY) < 1.0f)) {
// Compute screen z value assuming the viewport scale and translation both have value G_MAXZ / 2
// The multiplication by 32 follows from how the RSP microcode computes the screen z value.
wZ = (s32)((multDest.z * cappedInvWDest) * ((G_MAXZ / 2) * 32)) + ((G_MAXZ / 2) * 32);
// Obtain the z-buffer value for the screen pixel corresponding to the center of the glow.
zBuf = gZBuffer[(s32)((wY * -(SCREEN_HEIGHT / 2)) + (SCREEN_HEIGHT / 2))]
[(s32)((wX * (SCREEN_WIDTH / 2)) + (SCREEN_WIDTH / 2))]
<< 2;
if (1) {}
if (1) {}
// Compare the computed screen z value to the integer part of the z-buffer value in fixed point. If
// it is less than the value from the z-buffer the depth test passes and the glow can draw.
if (wZ < (Environment_ZBufValToFixedPoint(zBuf) >> 3)) {
params->drawGlow = true;
}
}
}
node = node->next;
}
}
void Lights_DrawGlow(PlayState* play) {
s32 pad;
LightNode* node;
node = play->lightCtx.listHead;
OPEN_DISPS(play->state.gfxCtx, "../z_lights.c", 887);
POLY_XLU_DISP = func_800947AC(POLY_XLU_DISP++);
gDPSetAlphaDither(POLY_XLU_DISP++, G_AD_NOISE);
gDPSetColorDither(POLY_XLU_DISP++, G_CD_MAGICSQ);
Decompile Gameplay_Keep and fix all existing decompiled objects (#595) * First batch of files * Add missing folders back * Fix missing folders again * Finish fixing existing texture files * Gameplay_Keep XML finished * Most actor gameplay_keep undefined syms removed * Only ~200 gkeep symbols remain * All gkeep symbols that ZAP supports are fixed * Cleanup, and make gkeep names more accurate * Starting to figure out what some unknown blobs are, merge zeldaret in * fix a few more things * refactor gkeep * Change how gitkeep is handled * gkeep xml cleanup * Gkeep finished, now just waiting up ZAP updates * 100 link animations finished * 150 link animations finished * 200 link animations finished * 250 link animations finished * 350 link animations finished * 400 link animations finished * 450 link animations finished * 500 link animations finished * 550 link animations finished * All Link animations finished cannot build yet because ZAP doesn't have LinkAnimationHeader yet * xml changes for new zap stuff * finish gameplay_keep * fixing existing objects * ready for pr besides zap padding issue * mostly ready for pr * format all c files * all conflicts fixed * make changes that roman requested * fix thing i didn't mean to change * some animation symbols renamed * fixed roman's stuff * lifemeter hardcoded pointers removed * fix issue with incorrect data in gameplay_keep * removed unused asm * fixed most of fig's comments * fix all of fig's comments * reformat files * Update assets/xml/textures/icon_item_static.xml Co-authored-by: Roman971 <32455037+Roman971@users.noreply.github.com> * Update assets/xml/textures/icon_item_static.xml Co-authored-by: Roman971 <32455037+Roman971@users.noreply.github.com> * fixed stuff * fixed most of roman's comments * remove leading zeroes * should build now * git subrepo pull --force tools/ZAPD subrepo: subdir: "tools/ZAPD" merged: "f84d8337b" upstream: origin: "https://github.com/zeldaret/ZAPD.git" branch: "master" commit: "f84d8337b" git-subrepo: version: "0.4.3" origin: "https://github.com/ingydotnet/git-subrepo.git" commit: "2f68596" * all of gkeep symbols fixed * compiler error fixed * format files * final changes Co-authored-by: Zelllll <elijah@DESKTOP-NMP1I89.localdomain> Co-authored-by: Roman971 <32455037+Roman971@users.noreply.github.com>
2021-01-25 00:36:40 +00:00
gSPDisplayList(POLY_XLU_DISP++, gGlowCircleTextureLoadDL);
while (node != NULL) {
LightInfo* info;
LightPoint* params;
f32 scale;
s32 pad[4];
info = node->info;
params = &info->params.point;
if ((info->type == LIGHT_POINT_GLOW) && (params->drawGlow)) {
scale = SQ(params->radius) * 0.0000026f;
gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, params->color[0], params->color[1], params->color[2], 50);
Matrix_Translate(params->x, params->y, params->z, MTXMODE_NEW);
Matrix_Scale(scale, scale, scale, MTXMODE_APPLY);
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx, "../z_lights.c", 918),
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
Decompile Gameplay_Keep and fix all existing decompiled objects (#595) * First batch of files * Add missing folders back * Fix missing folders again * Finish fixing existing texture files * Gameplay_Keep XML finished * Most actor gameplay_keep undefined syms removed * Only ~200 gkeep symbols remain * All gkeep symbols that ZAP supports are fixed * Cleanup, and make gkeep names more accurate * Starting to figure out what some unknown blobs are, merge zeldaret in * fix a few more things * refactor gkeep * Change how gitkeep is handled * gkeep xml cleanup * Gkeep finished, now just waiting up ZAP updates * 100 link animations finished * 150 link animations finished * 200 link animations finished * 250 link animations finished * 350 link animations finished * 400 link animations finished * 450 link animations finished * 500 link animations finished * 550 link animations finished * All Link animations finished cannot build yet because ZAP doesn't have LinkAnimationHeader yet * xml changes for new zap stuff * finish gameplay_keep * fixing existing objects * ready for pr besides zap padding issue * mostly ready for pr * format all c files * all conflicts fixed * make changes that roman requested * fix thing i didn't mean to change * some animation symbols renamed * fixed roman's stuff * lifemeter hardcoded pointers removed * fix issue with incorrect data in gameplay_keep * removed unused asm * fixed most of fig's comments * fix all of fig's comments * reformat files * Update assets/xml/textures/icon_item_static.xml Co-authored-by: Roman971 <32455037+Roman971@users.noreply.github.com> * Update assets/xml/textures/icon_item_static.xml Co-authored-by: Roman971 <32455037+Roman971@users.noreply.github.com> * fixed stuff * fixed most of roman's comments * remove leading zeroes * should build now * git subrepo pull --force tools/ZAPD subrepo: subdir: "tools/ZAPD" merged: "f84d8337b" upstream: origin: "https://github.com/zeldaret/ZAPD.git" branch: "master" commit: "f84d8337b" git-subrepo: version: "0.4.3" origin: "https://github.com/ingydotnet/git-subrepo.git" commit: "2f68596" * all of gkeep symbols fixed * compiler error fixed * format files * final changes Co-authored-by: Zelllll <elijah@DESKTOP-NMP1I89.localdomain> Co-authored-by: Roman971 <32455037+Roman971@users.noreply.github.com>
2021-01-25 00:36:40 +00:00
gSPDisplayList(POLY_XLU_DISP++, gGlowCircleDL);
}
node = node->next;
}
CLOSE_DISPS(play->state.gfxCtx, "../z_lights.c", 927);
}