diff --git a/README.md b/README.md index b97dc472..37850f2d 100644 --- a/README.md +++ b/README.md @@ -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`. * diff --git a/include/level_commands.h b/include/level_commands.h index 32331286..fa8f8d13 100644 --- a/include/level_commands.h +++ b/include/level_commands.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 { diff --git a/include/object_fields.h b/include/object_fields.h index d3487dad..aa00f163 100644 --- a/include/object_fields.h +++ b/include/object_fields.h @@ -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) diff --git a/include/types.h b/include/types.h index eeeeac15..68eb1379 100644 --- a/include/types.h +++ b/include/types.h @@ -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 { diff --git a/src/boot/main.c b/src/boot/main.c index 9d812aad..2fe93aaf 100644 --- a/src/boot/main.c +++ b/src/boot/main.c @@ -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) { diff --git a/src/engine/behavior_script.c b/src/engine/behavior_script.c index 8c918392..282b8b3b 100644 --- a/src/engine/behavior_script.c +++ b/src/engine/behavior_script.c @@ -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. diff --git a/src/engine/level_script.c b/src/engine/level_script.c index 3dad0c35..7c471b13 100644 --- a/src/engine/level_script.c +++ b/src/engine/level_script.c @@ -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, }; diff --git a/src/game/behavior_actions.c b/src/game/behavior_actions.c index d2f80578..d400977a 100644 --- a/src/game/behavior_actions.c +++ b/src/game/behavior_actions.c @@ -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" diff --git a/src/game/level_update.c b/src/game/level_update.c index ade15313..086e9972 100644 --- a/src/game/level_update.c +++ b/src/game/level_update.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; } diff --git a/src/game/obj_behaviors.c b/src/game/obj_behaviors.c index 46c699df..0e83b4b3 100644 --- a/src/game/obj_behaviors.c +++ b/src/game/obj_behaviors.c @@ -32,7 +32,6 @@ #include "spawn_object.h" #include "spawn_sound.h" #include "rumble_init.h" -#include "puppylights.h" /** * @file obj_behaviors.c diff --git a/src/game/obj_behaviors_2.c b/src/game/obj_behaviors_2.c index e7626ab1..90b18e76 100644 --- a/src/game/obj_behaviors_2.c +++ b/src/game/obj_behaviors_2.c @@ -45,7 +45,6 @@ #include "save_file.h" #include "seq_ids.h" #include "spawn_sound.h" -#include "puppylights.h" //! TODO: remove static diff --git a/src/game/object_helpers.c b/src/game/object_helpers.c index 5df500a4..33aabfa4 100644 --- a/src/game/object_helpers.c +++ b/src/game/object_helpers.c @@ -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), diff --git a/src/game/object_list_processor.c b/src/game/object_list_processor.c index abb28183..5dd018e2 100644 --- a/src/game/object_list_processor.c +++ b/src/game/object_list_processor.c @@ -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)) { diff --git a/src/game/puppylights.c b/src/game/puppylights.c deleted file mode 100644 index ad01a4e2..00000000 --- a/src/game/puppylights.c +++ /dev/null @@ -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 -#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 diff --git a/src/game/puppylights.h b/src/game/puppylights.h deleted file mode 100644 index bd0bcbcf..00000000 --- a/src/game/puppylights.h +++ /dev/null @@ -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 diff --git a/src/game/spawn_object.c b/src/game/spawn_object.c index 92f7beae..c0ec3233 100644 --- a/src/game/spawn_object.c +++ b/src/game/spawn_object.c @@ -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; }