Puppycamera 2.2 + Auto World Render Scale

Puppycam 2.2 introduces splines, with intention to be used for cutscenes.
This commit is contained in:
Fazana
2021-08-27 12:06:53 +01:00
committed by GitHub
6 changed files with 142 additions and 15 deletions

View File

@@ -21,10 +21,10 @@
level boundaries are 4 times as big (-32768 to 32767)
Collision calculations remain as fast as vanilla, at the cost of using far more RAM (16 times vanilla).
64x64 collision cells.
If you see "SURFACE POOL FULL" or "SURFACE NODE POOL FULL" in game, you should increase
SURFACE_POOL_SIZE or SURFACE_NODE_POOL_SIZE, respectively, or reduce the amount of
If you see "SURFACE POOL FULL" or "SURFACE NODE POOL FULL" in game, you should increase
SURFACE_POOL_SIZE or SURFACE_NODE_POOL_SIZE, respectively, or reduce the amount of
collision surfaces in your level.
*/
@@ -55,22 +55,18 @@
#undef LEVEL_BOUNDARY_MAX // Undefine the old value to avoid compiler warnings
#define LEVEL_BOUNDARY_MAX 0x2000L
#define CELL_SIZE 0x400
#define WORLD_SCALE 1.f
#elif EXTENDED_BOUNDS_MODE == 1
#undef LEVEL_BOUNDARY_MAX
#define LEVEL_BOUNDARY_MAX 0x4000L
#define CELL_SIZE 0x400
#define WORLD_SCALE 2.f
#elif EXTENDED_BOUNDS_MODE == 2
#undef LEVEL_BOUNDARY_MAX
#define LEVEL_BOUNDARY_MAX 0x2000L
#define CELL_SIZE 0x200
#define WORLD_SCALE 1.f
#elif EXTENDED_BOUNDS_MODE == 3
#undef LEVEL_BOUNDARY_MAX
#define LEVEL_BOUNDARY_MAX 0x8000L
#define CELL_SIZE 0x400
#define WORLD_SCALE 4.f
#endif
STATIC_ASSERT(LEVEL_BOUNDARY_MAX != 0, "You must set a valid extended bounds mode!");

View File

@@ -8,6 +8,7 @@
#include "trig_tables.inc.c"
#include "surface_load.h"
#include "game/puppyprint.h"
#include "game/rendering_graph_node.h"
#include "config.h"
@@ -583,7 +584,7 @@ void mtxf_to_mtx(Mtx *dest, Mat4 src) {
for( i = 0; i < 4; i++ ) {
for( j = 0; j < 3; j++ ) {
temp[i][j] = src[i][j] / WORLD_SCALE;
temp[i][j] = src[i][j] / gWorldScale;
}
temp[i][3] = src[i][3];
}

View File

@@ -1,4 +1,4 @@
///Puppycam 2.1 by Fazana
///Puppycam 2.2 by Fazana
#include <PR/ultratypes.h>
#include <PR/gbi.h>
@@ -198,7 +198,82 @@ void puppycam_activate_cutscene(s32 *scene, s32 lockinput)
gPuppyCam.sceneInput = lockinput;
}
static void newcam_process_cutscene(void)
//If you've read camera.c this will look familiar.
//It takes the next 4 spline points and extrapolates a curvature based positioning of the camera vector that's passed through.
//It's a standard B spline
static void puppycam_evaluate_spline(f32 progress, Vec3s cameraPos, Vec3f spline1, Vec3f spline2, Vec3f spline3, Vec3f spline4)
{
f32 tempP[4];
if (progress > 1.0f) {
progress = 1.0f;
}
tempP[0] = (1.0f - progress) * (1.0f - progress) * (1.0f - progress) / 6.0f;
tempP[1] = progress * progress * progress / 2.0f - progress * progress + 0.6666667f;
tempP[2] = -progress * progress * progress / 2.0f + progress * progress / 2.0f + progress / 2.0f + 0.16666667f;
tempP[3] = progress * progress * progress / 6.0f;
cameraPos[0] = tempP[0] * spline1[0] + tempP[1] * spline2[0] + tempP[2] * spline3[0] + tempP[3] * spline4[0];
cameraPos[1] = tempP[0] * spline1[1] + tempP[1] * spline2[1] + tempP[2] * spline3[1] + tempP[3] * spline4[1];
cameraPos[2] = tempP[0] * spline1[2] + tempP[1] * spline2[2] + tempP[2] * spline3[2] + tempP[3] * spline4[2];
}
s32 puppycam_move_spline(struct sPuppySpline splinePos[], struct sPuppySpline splineFocus[], s32 mode, s32 index)
{
Vec3f tempPoints[4];
f32 tempProgress[2] = {0.0f, 0.0f};
f32 progChange = 0.0f;
s32 i;
Vec3f prevPos;
if (gPuppyCam.splineIndex == 65000)
gPuppyCam.splineIndex = index;
if (splinePos[gPuppyCam.splineIndex].index == -1 || splinePos[gPuppyCam.splineIndex + 1].index == -1 || splinePos[gPuppyCam.splineIndex + 2].index == -1)
return 1;
if (mode == PUPPYSPLINE_FOLLOW)
if (splineFocus[gPuppyCam.splineIndex].index == -1 || splineFocus[gPuppyCam.splineIndex + 1].index == -1 || splineFocus[gPuppyCam.splineIndex + 2].index == -1)
return 1;
vec3f_set(prevPos, gPuppyCam.pos[0], gPuppyCam.pos[1], gPuppyCam.pos[2]);
for (i = 0; i < 4; i++)
vec3f_set(tempPoints[i], splinePos[gPuppyCam.splineIndex + i].pos[0], splinePos[gPuppyCam.splineIndex + i].pos[1], splinePos[gPuppyCam.splineIndex + i].pos[2]);
puppycam_evaluate_spline(gPuppyCam.splineProgress, gPuppyCam.pos, tempPoints[0], tempPoints[1], tempPoints[2], tempPoints[3]);
if (mode == PUPPYSPLINE_FOLLOW)
{
for (i = 0; i < 4; i++)
vec3f_set(tempPoints[i], splineFocus[gPuppyCam.splineIndex + i].pos[0], splineFocus[gPuppyCam.splineIndex + i].pos[1], splineFocus[gPuppyCam.splineIndex + i].pos[2]);
puppycam_evaluate_spline(gPuppyCam.splineProgress, gPuppyCam.focus, tempPoints[0], tempPoints[1], tempPoints[2], tempPoints[3]);
}
if (splinePos[gPuppyCam.splineIndex+1].speed != 0) {
tempProgress[0] = 1.0f / splinePos[gPuppyCam.splineIndex+1].speed;
}
if (splinePos[gPuppyCam.splineIndex+2].speed != 0) {
tempProgress[1] = 1.0f / splinePos[gPuppyCam.splineIndex+2].speed;
}
progChange = (tempProgress[1] - tempProgress[0]) * gPuppyCam.splineProgress + tempProgress[0];
gPuppyCam.splineProgress += progChange;
if (gPuppyCam.splineProgress >= 1.0f)
{
gPuppyCam.splineIndex++;
if (splinePos[gPuppyCam.splineIndex+3].index == -1)
{
gPuppyCam.splineIndex = 0;
gPuppyCam.splineProgress = 0;
return 1;
}
gPuppyCam.splineProgress -=1;
}
return 0;
}
static void puppycam_process_cutscene(void)
{
if (gPuppyCam.cutscene)
{
@@ -446,6 +521,8 @@ void puppycam_reset_values(void)
gPuppyCam.floorY[0] = 0;
gPuppyCam.floorY[1] = 0;
gPuppyCam.terrainPitch = 0;
gPuppyCam.splineIndex = 0;
gPuppyCam.splineProgress = 0;
}
//Set up values. Runs on level load.
@@ -615,7 +692,7 @@ static void puppycam_input_hold_preset2(f32 ivX)
}
//Another alternative control scheme. This one aims to mimic the parallel camera scheme down to the last bit from the original game.
static void puppycam_input_hold_preset3(f32 ivX)
static void puppycam_input_hold_preset3(void)
{
f32 stickMag[2] = {gPlayer1Controller->rawStickX*0.65f, gPlayer1Controller->rawStickY*0.2f};
//Just in case it happens to be nonzero.
@@ -741,7 +818,7 @@ static void puppycam_input_hold(void)
{
default: puppycam_input_hold_preset1(ivX); puppycam_input_pitch(); puppycam_input_zoom(); puppycam_input_centre(); break;
case 1: puppycam_input_hold_preset2(ivX); puppycam_input_pitch(); puppycam_input_zoom(); puppycam_input_centre(); break;
case 2: puppycam_input_hold_preset3(ivX); puppycam_input_centre(); break;
case 2: puppycam_input_hold_preset3(); puppycam_input_centre(); break;
}
}
else
@@ -972,6 +1049,35 @@ static s32 puppycam_check_volume_bounds(struct sPuppyVolume *volume, s32 index)
return FALSE;
}
//Handles wall adjustment when wall kicking.
void puppycam_wall_angle(void)
{
struct Surface *wall;
struct WallCollisionData cData;
s16 wallYaw;
if (!(gMarioState->action & ACT_WALL_KICK_AIR) || ((gMarioState->action & ACT_FLAG_AIR) && ABS(gMarioState->forwardVel) < 16.0f) || !(gMarioState->action & ACT_FLAG_AIR))
return;
cData.x = gPuppyCam.targetObj->oPosX;
cData.y = gPuppyCam.targetObj->oPosY;
cData.z = gPuppyCam.targetObj->oPosZ;
cData.radius = 150.0f;
cData.offsetY = 0;
if (find_wall_collisions(&cData))
wall = cData.walls[cData.numWalls - 1];
else
return;
wallYaw = atan2s(wall->normal.z, wall->normal.x) + 0x4000;
wallYaw -= gPuppyCam.yawTarget;
if (wallYaw % 0x4000)
wallYaw += 0x4000 - wallYaw % 0x4000;
gPuppyCam.yawTarget = approach_s32(gPuppyCam.yawTarget, wallYaw, 0x200, 0x200);
}
void puppycam_projection_behaviours(void)
{
f32 turnRate = 1;
@@ -1081,6 +1187,9 @@ void puppycam_projection_behaviours(void)
//This sets a pseudo tilt offset based on the floor heights in front and behind mario.
puppycam_terrain_angle();
//This will shift the intended yaw when wall kicking, to align with the wall being kicked.
puppycam_wall_angle();
}
else
{
@@ -1386,7 +1495,7 @@ void puppycam_loop(void)
if (gPuppyCam.cutscene)
{
gPuppyCam.opacity = 255;
newcam_process_cutscene();
puppycam_process_cutscene();
}
puppycam_apply();

View File

@@ -25,6 +25,9 @@
#define PUPPYCAM_MODE3_ZOOMED_OUT 0x4
#define PUPPYCAM_MODE3_ENTER_FIRST_PERSON 0x8
#define PUPPYSPLINE_NONE 1 //Will not write to focus at all.
#define PUPPYSPLINE_FOLLOW 2 //Focus will follow a separate spline, but will mirror the speed and progress of the pos.
#include "include/command_macros_base.h"
#define PUPPYVOLUME(x, y, z, length, height, width, yaw, functionptr, anglesptr, addflags, removeflags, flagpersistance, room, shape) \
@@ -94,6 +97,8 @@ struct gPuppyStruct
s32 sceneTimer; //The cutscene timer that goes up during a cutscene.
Vec3s scenePos; //Where the camera is during a cutscene
Vec3s sceneFocus; //Where the camera looks during a cutscene
u16 splineIndex; //Determines which point of the spline it's at.
f32 splineProgress; //Determines how far along the index the spline is.
struct gPuppyOptions options;
@@ -109,6 +114,14 @@ struct sPuppyAngles
s16 zoom;
};
//Structurally, it's exactly the same as CutsceneSplinePoint
struct sPuppySpline
{
s8 index; //The index of the spline. Ends with -1
u8 speed; //The amount of frames it takes to get through this index.
Vec3s pos; //The vector pos of the spline index itself.
};
//A bounding volume for activating puppycamera scripts and angles.
struct sPuppyVolume
{
@@ -172,7 +185,8 @@ extern void puppycam_set_save(void);
extern void puppycam_check_pause_buttons(void);
extern void puppycam_activate_cutscene(s32 *scene, s32 lockinput);
extern void puppycam_render_option_text();
void puppycam_warp(f32 displacementX, f32 displacementY, f32 displacementZ);
extern void puppycam_warp(f32 displacementX, f32 displacementY, f32 displacementZ);
extern s32 puppycam_move_spline(struct sPuppySpline splinePos[], struct sPuppySpline splineFocus[], s32 mode, s32 index);
#endif

View File

@@ -46,6 +46,7 @@ s16 gMatStackIndex;
Mat4 gMatStack[32];
Mtx *gMatStackFixed[32];
f32 aspect;
f32 gWorldScale = 1.0f;
/**
* Animation nodes have state in global variables, so this struct captures
@@ -259,7 +260,12 @@ static void geo_process_perspective(struct GraphNodePerspective *node) {
aspect = 1.33333f;
#endif
guPerspective(mtx, &perspNorm, node->fov, aspect, node->near / WORLD_SCALE, node->far / WORLD_SCALE, 1.0f);
if (gCamera)
gWorldScale = MAX(((gCamera->pos[0] * gCamera->pos[0]) + (gCamera->pos[1] * gCamera->pos[1]) + (gCamera->pos[2] * gCamera->pos[2]))/67108864, 1.0f);
else
gWorldScale = 1.0f;
guPerspective(mtx, &perspNorm, node->fov, aspect, node->near / gWorldScale, node->far / gWorldScale, 1.0f);
gSPPerspNormalize(gDisplayListHead++, perspNorm);
gSPMatrix(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(mtx), G_MTX_PROJECTION | G_MTX_LOAD | G_MTX_NOPUSH);

View File

@@ -12,6 +12,7 @@ extern struct GraphNodeCamera *gCurGraphNodeCamera;
extern struct GraphNodeObject *gCurGraphNodeObject;
extern struct GraphNodeHeldObject *gCurGraphNodeHeldObject;
extern u16 gAreaUpdateCounter;
extern f32 gWorldScale;
// after processing an object, the type is reset to this
#define ANIM_TYPE_NONE 0