You've already forked Microtransactions64
mirror of
https://github.com/Print-and-Panic/Microtransactions64.git
synced 2026-01-21 10:17:19 -08:00
Puppylights Bugfixes
Distance scaling is now correct on every axis, and there is a new flag, that will ignore the Y axis completely when calculating distance scaling. Additionally, ambient lights will now only apply brightening once for directional lights, and the light diffuse now approaches the correct value, eliminating light clipping.
This commit is contained in:
@@ -73,34 +73,57 @@ void puppylights_allocate(void)
|
||||
extern Mat4 gMatStack[32];
|
||||
|
||||
//Function that iterates through each light.
|
||||
void puppylights_iterate(struct PuppyLight *light, Lights1 *src, struct Object *obj)
|
||||
void puppylights_iterate(struct PuppyLight *light, Lights1 *src, struct Object *obj, s32 flags)
|
||||
{
|
||||
Lights1 *tempLight;
|
||||
s32 lightPos[2];
|
||||
Vec3i lightRelative;
|
||||
Vec3i lightDir = {0, 0, 0};
|
||||
s32 lightIntensity = 0;
|
||||
s32 i;
|
||||
s32 colour;
|
||||
s32 ambient;
|
||||
f64 scale = 1.0f;
|
||||
f64 scaleOrig;
|
||||
f32 scale;
|
||||
f32 scale2;
|
||||
f64 scaleVal = 1.0f;
|
||||
Vec3f debugPos[2];
|
||||
|
||||
//Relative positions of the object vs the centre of the node.
|
||||
//Relative positions of the object vs. the centre of the node.
|
||||
lightRelative[0] = light->pos[0][0] - obj->oPosX;
|
||||
lightRelative[1] = light->pos[0][1] - obj->oPosY;
|
||||
lightRelative[2] = light->pos[0][2] - obj->oPosZ;
|
||||
|
||||
//If the nodes X and Z values are equal, then a check is made if the angle is a derivative of 90.
|
||||
//If so, then it will completely skip over the calculation that figures out position from rotation.
|
||||
//If it's a cylinder, then it ignores that check, simply because an equal sided cylinder will have the
|
||||
//same result no matter the yaw. If neither is true, then it simply checks if it's 180 degrees, since
|
||||
//That will just be the same as 0.
|
||||
if (light->pos[1][0] == light->pos[1][2])
|
||||
{
|
||||
if (light->yaw % 0x4000 == 0 || light->flags & PUPPYLIGHT_SHAPE_CYLINDER)
|
||||
{
|
||||
lightPos[0] = lightRelative[0];
|
||||
lightPos[1] = lightRelative[2];
|
||||
goto skippingTrig;
|
||||
}
|
||||
}
|
||||
else
|
||||
if (light->yaw % 0x8000 == 0)
|
||||
{
|
||||
lightPos[0] = lightRelative[0];
|
||||
lightPos[1] = lightRelative[2];
|
||||
goto skippingTrig;
|
||||
}
|
||||
|
||||
//Get the position based off the rotation of the box.
|
||||
lightPos[0] = lightRelative[2] * sins(-light->yaw) + lightRelative[0] * coss(-light->yaw);
|
||||
lightPos[1] = lightRelative[2] * coss(-light->yaw) - lightRelative[0] * sins(-light->yaw);
|
||||
skippingTrig:
|
||||
|
||||
#ifdef VISUAL_DEBUG
|
||||
Vec3f debugPos[2];
|
||||
vec3f_set(debugPos[0], light->pos[0][0], light->pos[0][1], light->pos[0][2]);
|
||||
vec3f_set(debugPos[1], light->pos[1][0], light->pos[1][1], light->pos[1][2]);
|
||||
debug_box_color(0x00FF0040);
|
||||
debug_box_color(0x08FF00FF);
|
||||
if (light->flags & PUPPYLIGHT_SHAPE_CYLINDER)
|
||||
debug_box_rot(debugPos[0], debugPos[1], light->yaw, DEBUG_SHAPE_CYLINDER);
|
||||
else
|
||||
@@ -116,40 +139,39 @@ void puppylights_iterate(struct PuppyLight *light, Lights1 *src, struct Object *
|
||||
//This way, the colour value will scale correctly, no matter which side is entered.
|
||||
//Because positions are a vector, and Y is up, it means tempID needs to be multiplied
|
||||
//By 2 in order to reach the X and Z axis. Thanks SM64.
|
||||
s32 lightPos2[2];
|
||||
lightPos2[0] = light->pos[1][2] * sins(-light->yaw) + light->pos[1][0] * coss(-light->yaw);
|
||||
lightPos2[1] = light->pos[1][2] * coss(-light->yaw) - light->pos[1][0] * sins(-light->yaw);
|
||||
s32 tempID;
|
||||
f32 scaleFac;
|
||||
if (ABS(lightPos2[0]) > ABS(lightPos2[1]))
|
||||
tempID = 0;
|
||||
//It will skip scaling the opposite axis if there's no need to.
|
||||
|
||||
//Every axis needs to be the same as Z, so X and Y, if necessary, will be scaled to match it.
|
||||
//This is done, so that when calculating scale, it's done spherically.
|
||||
if (light->pos[1][0] != light->pos[1][2])
|
||||
lightPos[0] /= ((f32)light->pos[1][0]/light->pos[1][2]);
|
||||
//Same for Y axis.
|
||||
if (light->pos[1][1] != light->pos[1][2])
|
||||
lightRelative[1] /= ((f32)light->pos[1][1]/light->pos[1][2]);
|
||||
|
||||
if (light->flags & PUPPYLIGHT_IGNORE_Y)
|
||||
scaleOrig = (lightPos[0] * lightPos[0]) + (lightPos[1] * lightPos[1]);
|
||||
else
|
||||
tempID = 1;
|
||||
scaleFac = (f32)light->pos[1][(tempID^1)*2]/(f32)light->pos[1][tempID*2];
|
||||
lightPos[tempID] *= scaleFac;
|
||||
scale = (lightPos[0] * lightPos[0]) + (lightRelative[1] * lightRelative[1]) + (lightPos[1] * lightPos[1]);
|
||||
scaleVal = (light->pos[1][0] + light->pos[1][1] + light->pos[1][2])/3;
|
||||
scaleVal *= scaleVal;
|
||||
scaleOrig = (lightPos[0] * lightPos[0]) + (lightRelative[1] * lightRelative[1]) + (lightPos[1] * lightPos[1]);
|
||||
scaleVal = (light->pos[1][2]*light->pos[1][2]);
|
||||
//If it's a cylinder, then bin anything outside it.
|
||||
if (light->flags & PUPPYLIGHT_SHAPE_CYLINDER)
|
||||
{
|
||||
if (scale > scaleVal)
|
||||
if (scaleOrig > scaleVal)
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
return;
|
||||
|
||||
f32 epc = (f32)(light->epicentre/100.0f);
|
||||
tempLight = segmented_to_virtual(src);
|
||||
//Now we have a scale value and a scale factor, we can start lighting things up.
|
||||
//Convert to a percentage.
|
||||
scale /= scaleVal;
|
||||
scale = CLAMP(scale, 0.0f, 1.0f);
|
||||
scale = CLAMP(scaleOrig/scaleVal, 0.0f, 1.0f);
|
||||
//Reduce scale2 by the epicentre.
|
||||
scale2 = (scale - (f32)(light->epicentre/100.0f)) * (1+(f32)(light->epicentre/100.0f));
|
||||
scale2 = CLAMP(scale2, 0.0f, 1.0f);
|
||||
//Normalise the light brightness.
|
||||
lightIntensity = (tempLight->a.l.col[0]+tempLight->a.l.col[1]+tempLight->a.l.col[2])/3.0f;
|
||||
scale2 = CLAMP((scale - epc) * (1+epc), 0.0f, 1.0f);
|
||||
|
||||
//Get the direction numbers we want by applying some maths to the relative positions. We use 64 because light directions range from -64 to 63.
|
||||
//Note: can this be optimised further? Simply squaring lightRelative and then dividing it by preScale doesn't work.
|
||||
if (light->flags & PUPPYLIGHT_DIRECTIONAL)
|
||||
@@ -162,19 +184,25 @@ void puppylights_iterate(struct PuppyLight *light, Lights1 *src, struct Object *
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
//So it works by starting from the final colour, and then lerping to the original colour, by a factor of the epicentre corrected scale. Light opacity affects this further.
|
||||
colour = approach_f32_asymptotic(light->rgba[i], sLightBase->l[0].l.col[i], scale2*((f32)light->rgba[3]/255.0f));
|
||||
colour = approach_f32_asymptotic(light->rgba[i], tempLight->l[0].l.col[i], scale2*((f32)light->rgba[3]/255.0f));
|
||||
//If it's a directional light, then increase the current ambient by 50%, to give the effect better.
|
||||
//Otherwise, just normalise the brightness to keep it in line with the current ambient.
|
||||
if (light->flags & PUPPYLIGHT_DIRECTIONAL)
|
||||
ambient = approach_f32_asymptotic(MIN(tempLight->a.l.col[i]*1.5f, 0xFF), tempLight->a.l.col[i], scale*((f32)light->rgba[3]/255.0f));
|
||||
else
|
||||
ambient = approach_f32_asymptotic(lightIntensity, tempLight->a.l.col[i], scale*((f32)light->rgba[3]/255.0f));
|
||||
//And now to apply the values.
|
||||
tempLight->l[0].l.col[i] = colour;
|
||||
tempLight->l[0].l.colc[i] = colour;
|
||||
//Ambient, too.
|
||||
tempLight->a.l.col[i] = ambient;
|
||||
tempLight->a.l.colc[i] = ambient;
|
||||
if (!(light->flags & PUPPYLIGHT_DIRECTIONAL))
|
||||
{
|
||||
ambient = approach_f32_asymptotic(light->rgba[i]/2, tempLight->a.l.col[i], scale*((f32)light->rgba[3]/255.0f));
|
||||
tempLight->a.l.col[i] = ambient;
|
||||
tempLight->a.l.colc[i] = ambient;
|
||||
}
|
||||
//A slightly hacky way to offset the ambient lighting in order to prevent directional lighting from having a noticeable change in ambient brightness.
|
||||
if (flags & LIGHTFLAG_DIRECTIONAL_OFFSET)
|
||||
{
|
||||
tempLight->a.l.col[i] *= 1.5f;
|
||||
tempLight->a.l.colc[i] *= 1.5f;
|
||||
}
|
||||
//Apply direction. It takes the relative positions, and then multiplies them with the perspective matrix to get a correct direction.
|
||||
//Index 1 of the first dimension of gMatStack is perspective. Note that if you ever decide to cheat your way into rendering things after the game does :^)
|
||||
if (light->flags & PUPPYLIGHT_DIRECTIONAL)
|
||||
@@ -188,6 +216,7 @@ void puppylights_run(Lights1 *src, struct Object *obj, s32 flags, u32 baseColour
|
||||
{
|
||||
s32 i;
|
||||
s32 numlights = 0;
|
||||
s32 lightFlags = flags;
|
||||
|
||||
if (gCurrLevelNum < 4)
|
||||
return;
|
||||
@@ -206,8 +235,7 @@ void puppylights_run(Lights1 *src, struct Object *obj, s32 flags, u32 baseColour
|
||||
else
|
||||
{
|
||||
s32 colour;
|
||||
Lights1 tempLight;
|
||||
sLightBase = &tempLight;
|
||||
sLightBase = (levelAmbient) ? &gLevelLight : &sDefaultLights;
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
colour = (((baseColour >> (24-(i*8)))) & 0xFF);
|
||||
@@ -224,7 +252,11 @@ void puppylights_run(Lights1 *src, struct Object *obj, s32 flags, u32 baseColour
|
||||
{
|
||||
if (gPuppyLights[i]->rgba[3] > 0 && gPuppyLights[i]->active == TRUE && gPuppyLights[i]->area == gCurrAreaIndex && (gPuppyLights[i]->room == -1 || gPuppyLights[i]->room == gMarioCurrentRoom))
|
||||
{
|
||||
puppylights_iterate(gPuppyLights[i], src, obj);
|
||||
if (i == gDynLightStart)
|
||||
lightFlags |= LIGHTFLAG_DIRECTIONAL_OFFSET;
|
||||
else
|
||||
lightFlags &= ~LIGHTFLAG_DIRECTIONAL_OFFSET;
|
||||
puppylights_iterate(gPuppyLights[i], src, obj, lightFlags);
|
||||
numlights++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,9 @@
|
||||
#define PUPPYLIGHT_SHADOW 0x10
|
||||
#define PUPPYLIGHT_WET 0x20
|
||||
#define PUPPYLIGHT_DELETE 0x40
|
||||
#define PUPPYLIGHT_IGNORE_Y 0x80
|
||||
|
||||
#define LIGHTFLAG_DIRECTIONAL_OFFSET 0x1
|
||||
|
||||
#define PUPPYLIGHT_ENVIRONMENT(ambientR, ambientG, ambientB, diffuseR, diffuseG, diffuseB, diffuseX, diffuseY, diffuseZ) \
|
||||
CMD_BBBB(0x3F, 0x0C, ambientR, ambientG), \
|
||||
|
||||
Reference in New Issue
Block a user