You've already forked Microtransactions64
mirror of
https://github.com/Print-and-Panic/Microtransactions64.git
synced 2026-01-21 10:17:19 -08:00
remove puppylights (#736)
This commit is contained in:
@@ -36,7 +36,6 @@ Thanks to Frame#5375 and AloXado320 for also helping with silhouette stuff
|
||||
|
||||
**Lighting Engine by Wiseguy**
|
||||
- Lighting Engine is available on a separate branch ([base/lighting-engine](https://github.com/Reonu/HackerSM64/tree/base/lighting-engine)). Instructions on how to use it are in the readme of that branch.
|
||||
- Alternatively, the main repo has `Puppylights` available, which is a more lightweight, but limited lighting library intended to be used to modify existing light properties. You can look at `puppylights.c` to find out how to use it.
|
||||
|
||||
**Puppycam**
|
||||
- Puppycam is available on the master branch now, you can toggle it in `config/config_camera.h`. *
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
|
||||
#include "level_table.h"
|
||||
#include "config.h"
|
||||
#include "game/puppylights.h"
|
||||
|
||||
enum LevelCommands {
|
||||
/*0x00*/ LEVEL_CMD_LOAD_AND_EXECUTE,
|
||||
@@ -71,9 +70,7 @@ enum LevelCommands {
|
||||
/*0x3C*/ LEVEL_CMD_GET_OR_SET_VAR,
|
||||
/*0x3D*/ LEVEL_CMD_PUPPYVOLUME,
|
||||
/*0x3E*/ LEVEL_CMD_CHANGE_AREA_SKYBOX,
|
||||
/*0x3F*/ LEVEL_CMD_PUPPYLIGHT_ENVIRONMENT,
|
||||
/*0x40*/ LEVEL_CMD_PUPPYLIGHT_NODE,
|
||||
/*0x41*/ LEVEL_CMD_SET_ECHO,
|
||||
/*0x3F*/ LEVEL_CMD_SET_ECHO,
|
||||
};
|
||||
|
||||
enum LevelActs {
|
||||
|
||||
@@ -169,9 +169,6 @@
|
||||
#define /*0x1BC*/ oAngleToHome OBJECT_FIELD_S32(0x4D)
|
||||
#define /*0x1C0*/ oFloor OBJECT_FIELD_SURFACE(0x4E)
|
||||
#define /*0x1C4*/ oDeathSound OBJECT_FIELD_S32(0x4F)
|
||||
#ifdef PUPPYLIGHTS
|
||||
#define /*0x1C4*/ oLightID OBJECT_FIELD_S32(0x50)
|
||||
#endif
|
||||
|
||||
/* Pathed (see obj_follow_path) */
|
||||
#define /*0x0FC*/ oPathedStartWaypoint OBJECT_FIELD_WAYPOINT(0x1D)
|
||||
|
||||
@@ -256,27 +256,9 @@ struct ObjectNode {
|
||||
struct ObjectNode *prev;
|
||||
};
|
||||
|
||||
#ifdef PUPPYLIGHTS
|
||||
struct PuppyLight {
|
||||
Vec3t pos[2]; // The location of the light. First index is the absolute position, second index are offsets.
|
||||
s16 yaw; // Used by cubes. Allows epic rotating of the volume.
|
||||
RoomData room; // Which room to use. -1 is visible from all rooms.
|
||||
s8 epicentre; // What percentage inside the volume you'll be before maximum light strength is applied. (E.g: 100 will be full strength always, and 0 will be full strength at the centre.)
|
||||
u8 flags; // Some stuff to define how the volume is used. Mostly just shape stuff, but can potentially have other uses.
|
||||
ColorRGBA rgba; // Colour. Go on, take even the tiniest guess as to what this entails.
|
||||
u8 area; // Which section of the level this light is stored in.
|
||||
u8 active: 1; // Whether the light will actually work. Mostly intended to be used for objects.
|
||||
};
|
||||
#endif
|
||||
|
||||
// NOTE: Since ObjectNode is the first member of Object, it is difficult to determine
|
||||
// whether some of these pointers point to ObjectNode or Object.
|
||||
|
||||
#ifdef PUPPYLIGHTS
|
||||
#define MAX_OBJECT_FIELDS 0x51
|
||||
#else
|
||||
#define MAX_OBJECT_FIELDS 0x50
|
||||
#endif
|
||||
|
||||
struct Object {
|
||||
/*0x000*/ struct ObjectNode header;
|
||||
@@ -335,9 +317,6 @@ struct Object {
|
||||
/*0x218*/ void *collisionData;
|
||||
/*0x21C*/ Mat4 transform;
|
||||
/*0x25C*/ void *respawnInfo;
|
||||
#ifdef PUPPYLIGHTS
|
||||
struct PuppyLight puppylight;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct ObjectHitbox {
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
#include "usb/debug.h"
|
||||
#endif
|
||||
#include "game/puppyprint.h"
|
||||
#include "game/puppylights.h"
|
||||
#include "game/profiling.h"
|
||||
#include "game/emutest.h"
|
||||
|
||||
@@ -115,9 +114,6 @@ void alloc_pool(void) {
|
||||
|
||||
main_pool_init(start, end);
|
||||
gEffectsMemoryPool = mem_pool_init(EFFECTS_MEMORY_POOL, MEMORY_POOL_LEFT);
|
||||
#ifdef PUPPYLIGHTS
|
||||
gLightsPool = mem_pool_init(PUPPYLIGHTS_POOL, MEMORY_POOL_LEFT);
|
||||
#endif
|
||||
}
|
||||
|
||||
void create_thread(OSThread *thread, OSId id, void (*entry)(void *), void *arg, void *sp, OSPri pri) {
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
#include "math_util.h"
|
||||
#include "graph_node.h"
|
||||
#include "surface_collision.h"
|
||||
#include "game/puppylights.h"
|
||||
|
||||
// Macros for retrieving arguments from behavior scripts.
|
||||
#define BHV_CMD_GET_1ST_U8(index) (u8)((gCurBhvCommand[index] >> 24) & 0xFF) // unused
|
||||
@@ -911,10 +910,6 @@ void cur_obj_update(void) {
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef PUPPYLIGHTS
|
||||
puppylights_object_emit(o);
|
||||
#endif
|
||||
|
||||
// Handle visibility of object
|
||||
if (o->oRoom != -1) {
|
||||
// If the object is in a room, only show it when Mario is in the room.
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
#include "string.h"
|
||||
#include "game/puppycam2.h"
|
||||
#include "game/puppyprint.h"
|
||||
#include "game/puppylights.h"
|
||||
#include "game/emutest.h"
|
||||
|
||||
#include "config.h"
|
||||
@@ -859,52 +858,6 @@ static void level_cmd_puppyvolume(void) {
|
||||
sCurrentCmd = CMD_NEXT;
|
||||
}
|
||||
|
||||
static void level_cmd_puppylight_environment(void) {
|
||||
#ifdef PUPPYLIGHTS
|
||||
Lights1 temp = gdSPDefLights1(CMD_GET(u8, 2), CMD_GET(u8, 3), CMD_GET(u8, 4),
|
||||
CMD_GET(u8, 5), CMD_GET(u8, 6), CMD_GET(u8, 7),
|
||||
CMD_GET(u8, 8), CMD_GET(u8, 9), CMD_GET(u8, 10));
|
||||
|
||||
memcpy(&gLevelLight, &temp, sizeof(Lights1));
|
||||
levelAmbient = TRUE;
|
||||
#endif
|
||||
sCurrentCmd = CMD_NEXT;
|
||||
}
|
||||
|
||||
static void level_cmd_puppylight_node(void) {
|
||||
#ifdef PUPPYLIGHTS
|
||||
gPuppyLights[gNumLights] = mem_pool_alloc(gLightsPool, sizeof(struct PuppyLight));
|
||||
if (gPuppyLights[gNumLights] == NULL) {
|
||||
append_puppyprint_log("Puppylight allocation failed.");
|
||||
sCurrentCmd = CMD_NEXT;
|
||||
return;
|
||||
}
|
||||
|
||||
vec4_set(gPuppyLights[gNumLights]->rgba, CMD_GET(u8, 2),
|
||||
CMD_GET(u8, 3),
|
||||
CMD_GET(u8, 4),
|
||||
CMD_GET(u8, 5));
|
||||
|
||||
vec3s_set(gPuppyLights[gNumLights]->pos[0], CMD_GET(s16, 6),
|
||||
CMD_GET(s16, 8),
|
||||
CMD_GET(s16, 10));
|
||||
|
||||
vec3s_set(gPuppyLights[gNumLights]->pos[1], CMD_GET(s16, 12),
|
||||
CMD_GET(s16, 14),
|
||||
CMD_GET(s16, 16));
|
||||
gPuppyLights[gNumLights]->yaw = CMD_GET(s16, 18);
|
||||
gPuppyLights[gNumLights]->epicentre = CMD_GET(u8, 20);
|
||||
gPuppyLights[gNumLights]->flags = CMD_GET(u8, 21);
|
||||
gPuppyLights[gNumLights]->active = TRUE;
|
||||
gPuppyLights[gNumLights]->area = sCurrAreaIndex;
|
||||
gPuppyLights[gNumLights]->room = CMD_GET(s16, 22);
|
||||
|
||||
gNumLights++;
|
||||
|
||||
#endif
|
||||
sCurrentCmd = CMD_NEXT;
|
||||
}
|
||||
|
||||
static void level_cmd_set_echo(void) {
|
||||
if (sCurrAreaIndex >= 0 && sCurrAreaIndex < AREA_COUNT) {
|
||||
gAreaData[sCurrAreaIndex].useEchoOverride = TRUE;
|
||||
@@ -980,8 +933,6 @@ static void (*LevelScriptJumpTable[])(void) = {
|
||||
/*LEVEL_CMD_GET_OR_SET_VAR */ level_cmd_get_or_set_var,
|
||||
/*LEVEL_CMD_PUPPYVOLUME */ level_cmd_puppyvolume,
|
||||
/*LEVEL_CMD_CHANGE_AREA_SKYBOX */ level_cmd_change_area_skybox,
|
||||
/*LEVEL_CMD_PUPPYLIGHT_ENVIRONMENT */ level_cmd_puppylight_environment,
|
||||
/*LEVEL_CMD_PUPPYLIGHT_NODE */ level_cmd_puppylight_node,
|
||||
/*LEVEL_CMD_SET_ECHO */ level_cmd_set_echo,
|
||||
};
|
||||
|
||||
|
||||
@@ -44,7 +44,6 @@
|
||||
#include "spawn_object.h"
|
||||
#include "spawn_sound.h"
|
||||
#include "rumble_init.h"
|
||||
#include "puppylights.h"
|
||||
|
||||
#include "behaviors/star_door.inc.c"
|
||||
#include "behaviors/mr_i.inc.c"
|
||||
|
||||
@@ -30,7 +30,6 @@
|
||||
#include "rumble_init.h"
|
||||
#include "puppycam2.h"
|
||||
#include "puppyprint.h"
|
||||
#include "puppylights.h"
|
||||
#include "level_commands.h"
|
||||
|
||||
#include "config.h"
|
||||
@@ -630,30 +629,16 @@ void initiate_warp(s16 destLevel, s16 destArea, s16 destWarpNode, s32 warpFlags)
|
||||
sWarpDest.areaIdx = destArea;
|
||||
sWarpDest.nodeId = destWarpNode;
|
||||
sWarpDest.arg = warpFlags;
|
||||
#if defined(PUPPYCAM) || defined(PUPPYLIGHTS)
|
||||
s32 i = 0;
|
||||
#endif
|
||||
#ifdef PUPPYCAM
|
||||
if (sWarpDest.type == WARP_TYPE_CHANGE_LEVEL)
|
||||
{
|
||||
for (i = 0; i < gPuppyVolumeCount; i++)
|
||||
for (s32 i = 0; i < gPuppyVolumeCount; i++)
|
||||
{
|
||||
mem_pool_free(gPuppyMemoryPool, sPuppyVolumeStack[i]);
|
||||
}
|
||||
gPuppyVolumeCount = 0;
|
||||
}
|
||||
#endif
|
||||
#ifdef PUPPYLIGHTS
|
||||
if (sWarpDest.type == WARP_TYPE_CHANGE_LEVEL)
|
||||
{
|
||||
for (i = 0; i < gNumLights; i++)
|
||||
{
|
||||
mem_pool_free(gLightsPool, gPuppyLights[i]);
|
||||
}
|
||||
gNumLights = 0;
|
||||
levelAmbient = FALSE;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// From Surface 0xD3 to 0xFC
|
||||
@@ -992,9 +977,6 @@ void update_hud_values(void) {
|
||||
void basic_update(void) {
|
||||
area_update_objects();
|
||||
update_hud_values();
|
||||
#ifdef PUPPYLIGHTS
|
||||
delete_lights();
|
||||
#endif
|
||||
|
||||
if (gCurrentArea != NULL) {
|
||||
update_camera(gCurrentArea->camera);
|
||||
@@ -1035,9 +1017,6 @@ s32 play_mode_normal(void) {
|
||||
area_update_objects();
|
||||
#endif
|
||||
update_hud_values();
|
||||
#ifdef PUPPYLIGHTS
|
||||
delete_lights();
|
||||
#endif
|
||||
if (gCurrentArea != NULL) {
|
||||
#ifdef PUPPYPRINT_DEBUG
|
||||
#ifdef BETTER_REVERB
|
||||
@@ -1318,10 +1297,6 @@ s32 init_level(void) {
|
||||
sound_banks_disable(SEQ_PLAYER_SFX, SOUND_BANKS_DISABLED_DURING_INTRO_CUTSCENE);
|
||||
}
|
||||
|
||||
#ifdef PUPPYLIGHTS
|
||||
puppylights_allocate();
|
||||
#endif
|
||||
|
||||
append_puppyprint_log("Level loaded in %d" PP_CYCLE_STRING ".", (s32)(PP_CYCLE_CONV(osGetTime() - first)));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -32,7 +32,6 @@
|
||||
#include "spawn_object.h"
|
||||
#include "spawn_sound.h"
|
||||
#include "rumble_init.h"
|
||||
#include "puppylights.h"
|
||||
|
||||
/**
|
||||
* @file obj_behaviors.c
|
||||
|
||||
@@ -45,7 +45,6 @@
|
||||
#include "save_file.h"
|
||||
#include "seq_ids.h"
|
||||
#include "spawn_sound.h"
|
||||
#include "puppylights.h"
|
||||
|
||||
//! TODO: remove static
|
||||
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
#include "rendering_graph_node.h"
|
||||
#include "spawn_object.h"
|
||||
#include "spawn_sound.h"
|
||||
#include "puppylights.h"
|
||||
|
||||
static s32 clear_move_flag(u32 *bitSet, s32 flag);
|
||||
|
||||
@@ -878,9 +877,6 @@ s32 cur_obj_clear_interact_status_flag(s32 flag) {
|
||||
* Mark an object to be unloaded at the end of the frame.
|
||||
*/
|
||||
void obj_mark_for_deletion(struct Object *obj) {
|
||||
#ifdef PUPPYLIGHTS
|
||||
obj_disable_light(obj);
|
||||
#endif
|
||||
//! This clears all activeFlags. Since some of these flags disable behavior,
|
||||
// setting it to 0 could potentially enable unexpected behavior. After an
|
||||
// object is marked for deletion, it still updates on that frame (I think),
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
#include "platform_displacement.h"
|
||||
#include "spawn_object.h"
|
||||
#include "puppyprint.h"
|
||||
#include "puppylights.h"
|
||||
#include "profiling.h"
|
||||
|
||||
|
||||
@@ -382,10 +381,6 @@ s32 unload_deactivated_objects_in_list(struct ObjectNode *objList) {
|
||||
obj = obj->next;
|
||||
|
||||
if ((gCurrentObject->activeFlags & ACTIVE_FLAG_ACTIVE) != ACTIVE_FLAG_ACTIVE) {
|
||||
#ifdef PUPPYLIGHTS
|
||||
if (gCurrentObject->oLightID != 0xFFFF)
|
||||
obj_disable_light(gCurrentObject);
|
||||
#endif
|
||||
// Prevent object from respawning after exiting and re-entering the
|
||||
// area
|
||||
if (!(gCurrentObject->oFlags & OBJ_FLAG_PERSISTENT_RESPAWN)) {
|
||||
|
||||
@@ -1,382 +0,0 @@
|
||||
///Puppylights 2.0 by Fazana. What happened to 1.0? Tragic accident.
|
||||
/**
|
||||
Intended for use with manipulating existing Lights1 structs for objects in real time.
|
||||
Can support static lights that are loaded with the level, or lights created by objects.
|
||||
|
||||
Puppylights is generally intended to be used with things that don't directly use lights to colour
|
||||
themselves. Inside the main function, you can pass through a colour to override the default light
|
||||
but it will not be affected by environmental tinting. If you wish for an object to emit a light,
|
||||
simply set the object flag OBJ_FLAG_EMIT_LIGHT and set some values to o->puppylight.
|
||||
|
||||
For easy light modification, you can call set_light_properties, so set all the attributes of any
|
||||
given loaded puppylight struct. Objects will ignore x, y, z, active and room, as it will set all
|
||||
of these automatically. It will force the PUPPYLIGHT_DYNAMIC flag, too.
|
||||
|
||||
If you're introducing a static light in the level script with PUPPYLIGHT_NODE, ensure it's contained
|
||||
inside the respective area node it's going to be inside, otherwise it will not show up. If you do not
|
||||
use rooms in your level, or if you wish for this light to be seen from any room, use -1 for that param.
|
||||
|
||||
If you have visual debug enabled, light nodes will show up as magenta in the world. They will be
|
||||
shaped and rotated correctly, for accurate representation of their properties.
|
||||
**/
|
||||
|
||||
#include <ultra64.h>
|
||||
#include "types.h"
|
||||
#include "puppylights.h"
|
||||
#include "area.h"
|
||||
#include "engine/math_util.h"
|
||||
#include "string.h"
|
||||
#include "object_fields.h"
|
||||
#include "object_constants.h"
|
||||
#include "camera.h"
|
||||
#include "memory.h"
|
||||
#include "print.h"
|
||||
#include "debug_box.h"
|
||||
#include "object_list_processor.h"
|
||||
#include "level_update.h"
|
||||
#include "engine/surface_collision.h"
|
||||
#include "surface_terrains.h"
|
||||
|
||||
#ifdef PUPPYLIGHTS
|
||||
|
||||
Lights1 gLevelLight; // Existing ambient light in the area. Will be set by the level script, though can always be changed afterwards if desired.
|
||||
u8 levelAmbient = FALSE;
|
||||
Lights1 *sLightBase; // The base value where lights are written to when worked with.
|
||||
Lights1 sDefaultLights = gdSPDefLights1(0x7F, 0x7F, 0x7F, 0xFE, 0xFE, 0xFE, 0x28, 0x28, 0x28); // Default lights default lights
|
||||
u16 gNumLights = 0; // How many lights are loaded.
|
||||
u16 gDynLightStart = 0; // Where the dynamic lights will start.
|
||||
struct PuppyLight *gPuppyLights[MAX_LIGHTS]; // This contains all the loaded data.
|
||||
struct MemoryPool *gLightsPool; // The memory pool where the above is stored.
|
||||
|
||||
// Runs after an area load, allocates the dynamic light slots.
|
||||
void puppylights_allocate(void) {
|
||||
s32 numAllocate = MIN(MAX_LIGHTS - gNumLights, MAX_LIGHTS_DYNAMIC);
|
||||
s32 i;
|
||||
|
||||
gDynLightStart = gNumLights;
|
||||
|
||||
if (numAllocate <= 0) { // If this happens you've allocated too many static lights and therefore cucked dynamic.
|
||||
return;
|
||||
}
|
||||
// Now it has the number it wants, it will allocate this many extra lights, intended for dynamic lights.
|
||||
for (i = 0; i < numAllocate; i++) {
|
||||
gPuppyLights[gNumLights] = mem_pool_alloc(gLightsPool, sizeof(struct PuppyLight));
|
||||
if (gPuppyLights[gNumLights] == NULL) {
|
||||
return;
|
||||
}
|
||||
gPuppyLights[gNumLights]->active = FALSE;
|
||||
gPuppyLights[gNumLights]->flags = 0;
|
||||
gNumLights++;
|
||||
}
|
||||
}
|
||||
|
||||
extern Mat4 gMatStack[32];
|
||||
|
||||
// Function that iterates through each light.
|
||||
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 i;
|
||||
s32 colour;
|
||||
s32 ambient;
|
||||
f64 scaleOrig;
|
||||
f32 scale;
|
||||
f32 scale2;
|
||||
f64 scaleVal = 1.0f;
|
||||
Vec3f debugPos[2];
|
||||
|
||||
// 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_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(0xFF00FF08);
|
||||
if (light->flags & PUPPYLIGHT_SHAPE_CYLINDER) {
|
||||
debug_box_rot(debugPos[0], debugPos[1], light->yaw, DEBUG_SHAPE_CYLINDER | DEBUG_UCODE_DEFAULT);
|
||||
} else {
|
||||
debug_box_rot(debugPos[0], debugPos[1], light->yaw, DEBUG_SHAPE_BOX | DEBUG_UCODE_DEFAULT);
|
||||
}
|
||||
#endif
|
||||
// Check if the object is inside the box, after correcting it for rotation.
|
||||
if (-light->pos[1][0] < lightPos[0] && lightPos[0] < light->pos[1][0] &&
|
||||
-light->pos[1][1] < lightRelative[1] && lightRelative[1] < light->pos[1][1] &&
|
||||
-light->pos[1][2] < lightPos[1] && lightPos[1] < light->pos[1][2]) {
|
||||
// If so, then start making preparations to see how alongside they're in.
|
||||
// This takes the largest side of the box and multiplies the other axis to match the numbers.
|
||||
// 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.
|
||||
// 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 = sqr(lightPos[0]) + sqr(lightPos[1]);
|
||||
} else {
|
||||
scaleOrig = sqr(lightPos[0]) + sqr(lightRelative[1]) + sqr(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 (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 = CLAMP(scaleOrig/scaleVal, 0.0f, 1.0f);
|
||||
// Reduce scale2 by the epicentre.
|
||||
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) {
|
||||
lightDir[0] = ((lightRelative[0]) * 64.0f) / light->pos[1][0];
|
||||
lightDir[1] = ((lightRelative[1]) * 64.0f) / light->pos[1][1];
|
||||
lightDir[2] = ((lightRelative[2]) * 64.0f) / light->pos[1][2];
|
||||
}
|
||||
//Get direction if applicable.
|
||||
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], 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.
|
||||
// And now to apply the values.
|
||||
tempLight->l[0].l.col[i] = colour;
|
||||
tempLight->l[0].l.colc[i] = colour;
|
||||
// Ambient, too.
|
||||
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) {
|
||||
ambient = approach_f32_asymptotic(MIN(tempLight->a.l.col[i] * 2, 0xFF), tempLight->a.l.col[i], scale2*((f32)light->rgba[3] / 255.0f));
|
||||
tempLight->a.l.col[i] = ambient;
|
||||
tempLight->a.l.colc[i] = ambient;
|
||||
}
|
||||
// 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) {
|
||||
tempLight->l->l.dir[i] = approach_f32_asymptotic((s8)(lightDir[0] * gMatStack[1][0][i] + lightDir[1] * gMatStack[1][1][i] + lightDir[2] * gMatStack[1][2][i]), tempLight->l->l.dir[i], scale);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Main function. Run this in the object you wish to illuminate, and just give it its light, object pointer and any potential flags if you want to use them.
|
||||
// If the object has multiple lights, then you run this for each light.
|
||||
void puppylights_run(Lights1 *src, struct Object *obj, s32 flags, u32 baseColour) {
|
||||
s32 i;
|
||||
s32 numlights = 0;
|
||||
s32 offsetPlaced = 0;
|
||||
s32 lightFlags = flags;
|
||||
|
||||
if (gCurrLevelNum < LEVEL_BBH) {
|
||||
return;
|
||||
}
|
||||
// Checks if there's a hardset colour. Colours are only the first 3 bytes, so you can really put whatever you want in the last.
|
||||
// If there isn't a colour, then it decides whether to apply the ambient lighting, or the default lighting as the baseline.
|
||||
// Otherwise, it hardsets a colour to begin with. I don't recommend you use this, simply because it's intended to be used
|
||||
// As a hacky quick-fix for models coloured by lights. Lightcoloured models don't blend nearly as nicely as ones coloured
|
||||
// By other means.
|
||||
if (baseColour < 0x100) {
|
||||
sLightBase = (levelAmbient ? &gLevelLight : &sDefaultLights);
|
||||
} else {
|
||||
s32 colour;
|
||||
sLightBase = (levelAmbient) ? &gLevelLight : &sDefaultLights;
|
||||
for (i = 0; i < 3; i++) {
|
||||
colour = (((baseColour >> (24-(i*8)))) & 0xFF);
|
||||
sLightBase->l[0].l.col[i] = colour;
|
||||
sLightBase->l[0].l.colc[i] = colour;
|
||||
sLightBase->a.l.col[i] = colour/2;
|
||||
sLightBase->a.l.colc[i] = colour/2;
|
||||
sLightBase->l->l.dir[i] = 0x28;
|
||||
}
|
||||
}
|
||||
memcpy(segmented_to_virtual(src), &sLightBase[0], sizeof(Lights1));
|
||||
|
||||
for (i = 0; i < gNumLights; i++) {
|
||||
if (gPuppyLights[i]->rgba[3] > 0 && gPuppyLights[i]->active == TRUE && gPuppyLights[i]->area == gCurrAreaIndex && (gPuppyLights[i]->room == -1 || gPuppyLights[i]->room == gMarioCurrentRoom)) {
|
||||
if (gPuppyLights[i]->flags & PUPPYLIGHT_DIRECTIONAL && !offsetPlaced) {
|
||||
lightFlags |= LIGHTFLAG_DIRECTIONAL_OFFSET;
|
||||
offsetPlaced = 1;
|
||||
} else {
|
||||
lightFlags &= ~LIGHTFLAG_DIRECTIONAL_OFFSET;
|
||||
}
|
||||
puppylights_iterate(gPuppyLights[i], src, obj, lightFlags);
|
||||
numlights++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sets and updates dynamic lights from objects.
|
||||
// 0xFFFF is essentially the null ID. If the display flag is met, it will find and set an ID, otherwise it frees up the spot.
|
||||
void puppylights_object_emit(struct Object *obj) {
|
||||
s32 i;
|
||||
if (gCurrLevelNum < LEVEL_BBH) {
|
||||
return;
|
||||
}
|
||||
if (obj->oFlags & OBJ_FLAG_EMIT_LIGHT) {
|
||||
f64 dist = ((obj->oPosX - gMarioState->pos[0]) * (obj->oPosX - gMarioState->pos[0])) +
|
||||
((obj->oPosY - gMarioState->pos[1]) * (obj->oPosY - gMarioState->pos[1])) +
|
||||
((obj->oPosZ - gMarioState->pos[2]) * (obj->oPosZ - gMarioState->pos[2]));
|
||||
f64 lightSize = ((obj->puppylight.pos[1][0]) * (obj->puppylight.pos[1][0])) +
|
||||
((obj->puppylight.pos[1][1]) * (obj->puppylight.pos[1][1])) +
|
||||
((obj->puppylight.pos[1][2]) * (obj->puppylight.pos[1][2]));
|
||||
if (dist > lightSize) {
|
||||
goto deallocate; // That's right. I used a goto. Eat your heart out xkcd.
|
||||
}
|
||||
if (obj->oLightID == 0xFFFF) {
|
||||
s32 fadingExists = FALSE;
|
||||
if (ABS(gNumLights - gDynLightStart) < MAX_LIGHTS_DYNAMIC) {
|
||||
goto deallocate;
|
||||
}
|
||||
for (i = gDynLightStart; i < MIN(gDynLightStart+MAX_LIGHTS_DYNAMIC, MAX_LIGHTS); i++) {
|
||||
if (gPuppyLights[i]->active == TRUE) {
|
||||
if (gPuppyLights[i]->flags & PUPPYLIGHT_DELETE) {
|
||||
fadingExists = TRUE;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
memcpy(gPuppyLights[i], &obj->puppylight, sizeof(struct PuppyLight));
|
||||
gPuppyLights[i]->active = TRUE;
|
||||
gPuppyLights[i]->area = gCurrAreaIndex;
|
||||
gPuppyLights[i]->room = obj->oRoom;
|
||||
obj->oLightID = i;
|
||||
goto updatepos;
|
||||
}
|
||||
// Go through all the lights again, now this time, ignore the fading light flag and overwrite them.
|
||||
if (fadingExists) {
|
||||
for (i = gDynLightStart; i < MIN(gDynLightStart+MAX_LIGHTS_DYNAMIC, MAX_LIGHTS); i++) {
|
||||
if (gPuppyLights[i]->active == TRUE && !(gPuppyLights[i]->flags & PUPPYLIGHT_DELETE)) {
|
||||
continue;
|
||||
}
|
||||
memcpy(gPuppyLights[i], &obj->puppylight, sizeof(struct PuppyLight));
|
||||
gPuppyLights[i]->active = TRUE;
|
||||
gPuppyLights[i]->area = gCurrAreaIndex;
|
||||
gPuppyLights[i]->room = obj->oRoom;
|
||||
gPuppyLights[i]->flags &= ~PUPPYLIGHT_DELETE;
|
||||
obj->oLightID = i;
|
||||
goto updatepos;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
updatepos:
|
||||
gPuppyLights[obj->oLightID]->pos[0][0] = obj->oPosX;
|
||||
gPuppyLights[obj->oLightID]->pos[0][1] = obj->oPosY;
|
||||
gPuppyLights[obj->oLightID]->pos[0][2] = obj->oPosZ;
|
||||
}
|
||||
} else {
|
||||
deallocate:
|
||||
if (obj->oLightID != 0xFFFF) {
|
||||
gPuppyLights[obj->oLightID]->active = FALSE;
|
||||
gPuppyLights[obj->oLightID]->flags = 0;
|
||||
}
|
||||
obj->oLightID = 0xFFFF;
|
||||
}
|
||||
}
|
||||
|
||||
// A bit unorthodox, but anything to avoid having to set up data to pass through in the original function.
|
||||
// Objects will completely ignore X, Y, Z and active though.
|
||||
void set_light_properties(struct PuppyLight *light, s32 x, s32 y, s32 z, s32 offsetX, s32 offsetY, s32 offsetZ, s32 yaw, s32 epicentre, s32 colour, s32 flags, s32 room, s32 active) {
|
||||
light->active = active;
|
||||
light->pos[0][0] = x;
|
||||
light->pos[0][1] = y;
|
||||
light->pos[0][2] = z;
|
||||
light->pos[1][0] = MAX(offsetX, 10);
|
||||
light->pos[1][1] = MAX(offsetY, 10);
|
||||
light->pos[1][2] = MAX(offsetZ, 10);
|
||||
light->rgba[0] = (colour >> 24) & 0xFF;
|
||||
light->rgba[1] = (colour >> 16) & 0xFF;
|
||||
light->rgba[2] = (colour >> 8) & 0xFF;
|
||||
light->rgba[3] = colour & 0xFF;
|
||||
light->yaw = yaw;
|
||||
light->area = gCurrAreaIndex;
|
||||
light->room = room;
|
||||
light->epicentre = epicentre;
|
||||
if (!(flags & PUPPYLIGHT_SHAPE_CYLINDER) && flags & PUPPYLIGHT_SHAPE_CUBE)
|
||||
light->flags |= PUPPYLIGHT_SHAPE_CYLINDER;
|
||||
light->flags |= flags | PUPPYLIGHT_DYNAMIC;
|
||||
}
|
||||
|
||||
// You can run these in objects to enable or disable their light properties.
|
||||
void cur_obj_enable_light(void) {
|
||||
gCurrentObject->oFlags |= OBJ_FLAG_EMIT_LIGHT;
|
||||
}
|
||||
|
||||
void cur_obj_disable_light(void) {
|
||||
gCurrentObject->oFlags &= ~OBJ_FLAG_EMIT_LIGHT;
|
||||
if (gPuppyLights[gCurrentObject->oLightID] && gCurrentObject->oLightID != 0xFFFF)
|
||||
gPuppyLights[gCurrentObject->oLightID]->flags |= PUPPYLIGHT_DELETE;
|
||||
}
|
||||
|
||||
void obj_enable_light(struct Object *obj) {
|
||||
obj->oFlags |= OBJ_FLAG_EMIT_LIGHT;
|
||||
}
|
||||
|
||||
void obj_disable_light(struct Object *obj) {
|
||||
obj->oFlags &= ~OBJ_FLAG_EMIT_LIGHT;
|
||||
if (gPuppyLights[obj->oLightID] && obj->oLightID != 0xFFFF) {
|
||||
gPuppyLights[obj->oLightID]->flags |= PUPPYLIGHT_DELETE;
|
||||
}
|
||||
}
|
||||
|
||||
// This is ran during a standard area update
|
||||
void delete_lights(void) {
|
||||
s32 i;
|
||||
|
||||
for (i = 0; i < gNumLights; i++) {
|
||||
if (gPuppyLights[i]->active == TRUE && gPuppyLights[i]->flags & PUPPYLIGHT_DELETE) {
|
||||
gPuppyLights[i]->pos[1][0] = approach_f32_asymptotic(gPuppyLights[i]->pos[1][0], 0, 0.15f);
|
||||
gPuppyLights[i]->pos[1][1] = approach_f32_asymptotic(gPuppyLights[i]->pos[1][1], 0, 0.15f);
|
||||
gPuppyLights[i]->pos[1][2] = approach_f32_asymptotic(gPuppyLights[i]->pos[1][2], 0, 0.15f);
|
||||
if (gPuppyLights[i]->pos[1][0] < 1.0f && gPuppyLights[i]->pos[1][1] < 1.0f && gPuppyLights[i]->pos[1][2] < 1.0f) {
|
||||
gPuppyLights[i]->flags &= ~ PUPPYLIGHT_DELETE;
|
||||
gPuppyLights[i]->active = FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,57 +0,0 @@
|
||||
#ifdef PUPPYLIGHTS
|
||||
#ifndef PUPPYLIGHTS_H
|
||||
#define PUPPYLIGHTS_H
|
||||
|
||||
#include "types.h"
|
||||
#include "command_macros_base.h"
|
||||
|
||||
// The maximum number of lights that can be loaded at once. Any further lights that attempt to be created past this will simply not spawn.
|
||||
#define MAX_LIGHTS 32
|
||||
// The maximum number of dynamic lights available at one time.
|
||||
#define MAX_LIGHTS_DYNAMIC 8
|
||||
|
||||
// Two shapes. Choose your destiny.
|
||||
#define PUPPYLIGHT_SHAPE_CUBE (1 << 0) // 0x01
|
||||
#define PUPPYLIGHT_SHAPE_CYLINDER (1 << 1) // 0x02
|
||||
#define PUPPYLIGHT_DYNAMIC (1 << 2) // 0x04
|
||||
#define PUPPYLIGHT_DIRECTIONAL (1 << 3) // 0x08
|
||||
#define PUPPYLIGHT_SHADOW (1 << 4) // 0x10
|
||||
#define PUPPYLIGHT_WET (1 << 5) // 0x20
|
||||
#define PUPPYLIGHT_DELETE (1 << 6) // 0x40
|
||||
#define PUPPYLIGHT_IGNORE_Y (1 << 7) // 0x80
|
||||
|
||||
#define LIGHTFLAG_DIRECTIONAL_OFFSET 0x1
|
||||
|
||||
#define PUPPYLIGHT_ENVIRONMENT(ambientR, ambientG, ambientB, diffuseR, diffuseG, diffuseB, diffuseX, diffuseY, diffuseZ) \
|
||||
CMD_BBBB(0x3F, 0x0C, ambientR, ambientG), \
|
||||
CMD_BBBB(ambientB, diffuseR, diffuseG, diffuseB), \
|
||||
CMD_BBBB(diffuseX, diffuseY, diffuseZ, 0x0)
|
||||
|
||||
#define PUPPYLIGHT_NODE(r, g, b, a, x, y, z, offsetX, offsetY, offsetZ, yaw, epicentre, flags, room) \
|
||||
CMD_BBBB(0x40, 0x18, r, g), \
|
||||
CMD_BBH(b, a, x), \
|
||||
CMD_HH(y, z), \
|
||||
CMD_HH(offsetX, offsetY), \
|
||||
CMD_HH(offsetZ, yaw), \
|
||||
CMD_BBH(epicentre, flags, room)
|
||||
|
||||
//How much RAM is allocated to puppylights
|
||||
#define PUPPYLIGHTS_POOL sizeof(struct PuppyLight) * MAX_LIGHTS
|
||||
|
||||
extern Lights1 gLevelLight;
|
||||
extern u16 gNumLights;
|
||||
extern u8 levelAmbient;
|
||||
extern struct PuppyLight *gPuppyLights[MAX_LIGHTS];
|
||||
extern struct MemoryPool *gLightsPool;
|
||||
extern void puppylights_run(Lights1 *src, struct Object *obj, s32 flags, u32 baseColour);
|
||||
extern void puppylights_object_emit(struct Object *obj);
|
||||
extern void cur_obj_enable_light(void);
|
||||
extern void cur_obj_disable_light(void);
|
||||
extern void obj_enable_light(struct Object *obj);
|
||||
extern void obj_disable_light(struct Object *obj);
|
||||
extern void set_light_properties(struct PuppyLight *light, s32 x, s32 y, s32 z, s32 offsetX, s32 offsetY, s32 offsetZ, s32 yaw, s32 epicentre, s32 colour, s32 flags, s32 room, s32 active);
|
||||
extern void puppylights_allocate(void);
|
||||
extern void delete_lights(void);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -12,7 +12,6 @@
|
||||
#include "object_list_processor.h"
|
||||
#include "spawn_object.h"
|
||||
#include "types.h"
|
||||
#include "puppylights.h"
|
||||
|
||||
/**
|
||||
* Attempt to allocate an object from freeList (singly linked) and append it
|
||||
@@ -190,9 +189,6 @@ struct Object *allocate_object(struct ObjectNode *objList) {
|
||||
obj->header.gfx.node.flags &= ~GRAPH_RENDER_INVISIBLE;
|
||||
vec3_same(obj->header.gfx.pos, -10000.0f);
|
||||
obj->header.gfx.throwMatrix = NULL;
|
||||
#ifdef PUPPYLIGHTS
|
||||
obj->oLightID = 0xFFFF;
|
||||
#endif
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user