Bettercam improvements: no longer sways when close to geo, no longer zooms if player partially visible

This commit is contained in:
MysterD 2022-05-25 17:47:34 -07:00
parent 0778226e60
commit c15f8bfef0
5 changed files with 134 additions and 86 deletions

View file

@ -984,4 +984,26 @@ f32 not_zero(f32 value, f32 replacement) {
return replacement; return replacement;
} }
return value; return value;
} }
void vec3f_project(Vec3f vec, Vec3f onto, Vec3f out) {
f32 numerator = vec3f_dot(vec, onto);
f32 denominator = vec3f_dot(onto, onto);
if (denominator == 0) {
out[0] = 0;
out[1] = 0;
out[2] = 0;
return;
}
vec3f_copy(out, onto);
vec3f_mul(out, numerator / denominator);
}
f32 vec3f_dist(Vec3f v1, Vec3f v2) {
Vec3f diff = {
v1[0] - v2[0],
v1[1] - v2[1],
v1[2] - v2[2],
};
return vec3f_length(diff);
}

View file

@ -84,4 +84,7 @@ s32 anim_spline_poll(struct MarioState* m, Vec3f result);
f32 not_zero(f32 value, f32 replacement); f32 not_zero(f32 value, f32 replacement);
void vec3f_project(Vec3f vec, Vec3f onto, Vec3f out);
f32 vec3f_dist(Vec3f v1, Vec3f v2);
#endif // MATH_UTIL_H #endif // MATH_UTIL_H

View file

@ -482,74 +482,116 @@ static void newcam_update_values(void) {
} }
} }
static void newcam_bounding_box(void) { static void debug_pos(f32 x, f32 y, f32 z, u8 hit) { // DO NOT COMMIT
Vec3f camdirs[NEW_CAM_BOUNDING_BOX_RAYS] = { 0 }; if(gMarioStates[0].marioObj == NULL) { return; }
Vec3f raypos[NEW_CAM_BOUNDING_BOX_RAYS] = { 0 }; struct Object* obj = spawn_object(gMarioStates[0].marioObj, hit ? MODEL_RED_COIN : MODEL_YELLOW_COIN, bhvSparkle);
s16 antiYaw = newcam_yaw - 0x4000; if (obj == NULL) { return; }
obj->oPosX = x;
// sideways ray 1 obj->oPosY = y;
camdirs[0][0] = coss(antiYaw) * NEW_CAM_BOUNDING_BOX_HRADIUS; obj->oPosZ = z;
camdirs[0][2] = sins(antiYaw) * NEW_CAM_BOUNDING_BOX_HRADIUS; obj_scale(obj, 0.5f);
// sideways ray 2
camdirs[1][0] = -coss(antiYaw) * NEW_CAM_BOUNDING_BOX_HRADIUS;
camdirs[1][2] = -sins(antiYaw) * NEW_CAM_BOUNDING_BOX_HRADIUS;
// vertical rays
camdirs[2][1] = -NEW_CAM_BOUNDING_BOX_VRADIUS;
camdirs[3][1] = NEW_CAM_BOUNDING_BOX_VRADIUS;
for (s32 i = 0; i < NEW_CAM_BOUNDING_BOX_RAYS; i++) {
struct Surface* surf;
Vec3f offset = { 0 };
Vec3f startpos = { 0 };
vec3f_copy(startpos, newcam_pos);
vec3f_add(startpos, offset);
find_surface_on_ray(startpos, camdirs[i], &surf, raypos[i]);
if (!surf) {
vec3f_copy(raypos[i], startpos);
vec3f_add(raypos[i], camdirs[i]);
}
}
Vec3f avg = { 0 };
for (s32 i = 0; i < NEW_CAM_BOUNDING_BOX_RAYS; i++) {
vec3f_add(avg, raypos[i]);
}
vec3f_mul(avg, 1.0f / ((f32)NEW_CAM_BOUNDING_BOX_RAYS));
vec3f_copy(newcam_pos, avg);
} }
static void newcam_collision(void) { static void newcam_collision(void) {
struct Surface *surf; // check if we can see player
Vec3f camdir; Vec3f up = { 0, 1, 0 };
Vec3f hitpos; Vec3f mainRay = {
newcam_pos[0]-newcam_lookat[0],
newcam_pos[1]-newcam_lookat[1],
newcam_pos[2]-newcam_lookat[2],
};
Vec3f sideway;
vec3f_normalize(mainRay);
vec3f_cross(sideway, mainRay, up);
camdir[0] = newcam_pos[0]-newcam_lookat[0]; f32 checkWidth = 75;
camdir[1] = newcam_pos[1]-newcam_lookat[1]; f32 checkHeight = 90;
camdir[2] = newcam_pos[2]-newcam_lookat[2];
find_surface_on_ray(newcam_pos_target, camdir, &surf, hitpos); bool allhit = true;
for (f32 x = -1; x <= 1; x++) {
for (f32 y = 0; y <= 1; y++) {
if (fabs(x) + fabs(y) != 1) { continue; }
Vec3f offset = {
sideway[0] * x * checkWidth,
-checkHeight / 2 + y * checkHeight,
sideway[2] * x * checkWidth,
};
newcam_coldist = sqrtf((newcam_pos_target[0] - hitpos[0]) * (newcam_pos_target[0] - hitpos[0]) + (newcam_pos_target[1] - hitpos[1]) * (newcam_pos_target[1] - hitpos[1]) + (newcam_pos_target[2] - hitpos[2]) * (newcam_pos_target[2] - hitpos[2])); if (x != 0) {
struct Surface* surf;
Vec3f hitpos;
Vec3f move = {
offset[0] * 1.2f,
offset[1],
offset[2] * 1.2f,
};
find_surface_on_ray(newcam_pos_target, move, &surf, hitpos);
vec3f_copy(offset, hitpos);
vec3f_sub(offset, newcam_pos_target);
if (surf) {
offset[0] *= 0;
offset[2] *= 0;
}
}
if (surf) { Vec3f camray = {
// offset the hit pos by the hit normal newcam_pos[0] - newcam_lookat[0] - offset[0],
Vec3f offset = { 0 }; newcam_pos[1] - newcam_lookat[1] - offset[1],
offset[0] = surf->normal.x; newcam_pos[2] - newcam_lookat[2] - offset[2],
offset[1] = surf->normal.y; };
offset[2] = surf->normal.z;
vec3f_mul(offset, 5.0f);
vec3f_add(hitpos, offset);
newcam_pos[0] = hitpos[0]; Vec3f camorig = {
newcam_pos[1] = hitpos[1]; newcam_pos_target[0] + offset[0],
newcam_pos[2] = hitpos[2]; newcam_pos_target[1] + offset[1],
newcam_pan_x = 0; newcam_pos_target[2] + offset[2],
newcam_pan_z = 0; };
struct Surface* surf;
Vec3f hitpos;
find_surface_on_ray(camorig, camray, &surf, hitpos);
debug_pos(camorig[0], camorig[1], camorig[2], surf != NULL);
if (surf == NULL) {
allhit = false;
}
}
}
Vec3f camdir = {
newcam_pos[0]-newcam_lookat[0],
newcam_pos[1]-newcam_lookat[1],
newcam_pos[2]-newcam_lookat[2],
};
if (allhit) {
struct Surface *surf = NULL;
Vec3f hitpos;
find_surface_on_ray(newcam_pos_target, camdir, &surf, hitpos);
if (surf) {
// offset the hit pos by the hit normal
Vec3f offset = { 0 };
offset[0] = surf->normal.x;
offset[1] = surf->normal.y;
offset[2] = surf->normal.z;
vec3f_mul(offset, 5.0f);
vec3f_add(hitpos, offset);
newcam_pos[0] = hitpos[0];
newcam_pos[1] = hitpos[1];
newcam_pos[2] = hitpos[2];
newcam_pan_x = 0;
newcam_pan_z = 0;
}
newcam_coldist = vec3f_dist(newcam_pos_target, hitpos);
} else {
newcam_pos[0] = newcam_pos_target[0] + camdir[0];
newcam_pos[1] = newcam_pos_target[1] + camdir[1];
newcam_pos[2] = newcam_pos_target[2] + camdir[2];
newcam_coldist = vec3f_length(camdir);
} }
} }
@ -611,7 +653,6 @@ static void newcam_position_cam(void) {
newcam_level_bounds(); newcam_level_bounds();
if (newcam_modeflags & NC_FLAG_COLLISION) { if (newcam_modeflags & NC_FLAG_COLLISION) {
newcam_collision(); newcam_collision();
newcam_bounding_box();
} }
} }

View file

@ -11741,28 +11741,6 @@ static s8 sRomHackIsUpdate = 0;
static f32 sRomHackWaterFocus = 0; static f32 sRomHackWaterFocus = 0;
static f32 sRomHackWaterPitchOffset = 0; static f32 sRomHackWaterPitchOffset = 0;
static void vec3f_project(Vec3f vec, Vec3f onto, Vec3f out) {
f32 numerator = vec3f_dot(vec, onto);
f32 denominator = vec3f_dot(onto, onto);
if (denominator == 0) {
out[0] = 0;
out[1] = 0;
out[2] = 0;
return;
}
vec3f_copy(out, onto);
vec3f_mul(out, numerator / denominator);
}
static f32 vec3f_dist(Vec3f v1, Vec3f v2) {
Vec3f diff = {
v1[0] - v2[0],
v1[1] - v2[1],
v1[2] - v2[2],
};
return vec3f_length(diff);
}
static u8 rom_hack_cam_can_see_mario(Vec3f desiredPos) { static u8 rom_hack_cam_can_see_mario(Vec3f desiredPos) {
// do collision checking // do collision checking
struct Surface *surf = NULL; struct Surface *surf = NULL;

View file

@ -42,6 +42,8 @@
#define MATRIX_STACK_SIZE 32 #define MATRIX_STACK_SIZE 32
#define MAX_PROJECTION_NEAR_VALUE 5
s16 gMatStackIndex; s16 gMatStackIndex;
Mat4 gMatStack[MATRIX_STACK_SIZE] = {}; Mat4 gMatStack[MATRIX_STACK_SIZE] = {};
Mat4 gMatStackPrev[MATRIX_STACK_SIZE] = {}; Mat4 gMatStackPrev[MATRIX_STACK_SIZE] = {};
@ -222,7 +224,8 @@ void patch_mtx_interpolated(f32 delta) {
if (sPerspectiveNode != NULL) { if (sPerspectiveNode != NULL) {
u16 perspNorm; u16 perspNorm;
f32 fovInterpolated = delta_interpolate_f32(sPerspectiveNode->prevFov, sPerspectiveNode->fov, delta); f32 fovInterpolated = delta_interpolate_f32(sPerspectiveNode->prevFov, sPerspectiveNode->fov, delta);
guPerspective(sPerspectiveMtx, &perspNorm, not_zero(fovInterpolated, gOverrideFOV), sPerspectiveAspect, not_zero(sPerspectiveNode->near, gOverrideNear), not_zero(sPerspectiveNode->far, gOverrideFar), 1.0f); f32 near = MIN(sPerspectiveNode->near, MAX_PROJECTION_NEAR_VALUE);
guPerspective(sPerspectiveMtx, &perspNorm, not_zero(fovInterpolated, gOverrideFOV), sPerspectiveAspect, not_zero(near, gOverrideNear), not_zero(sPerspectiveNode->far, gOverrideFar), 1.0f);
gSPMatrix(sPerspectivePos, VIRTUAL_TO_PHYSICAL(sPerspectiveNode), G_MTX_PROJECTION | G_MTX_LOAD | G_MTX_NOPUSH); gSPMatrix(sPerspectivePos, VIRTUAL_TO_PHYSICAL(sPerspectiveNode), G_MTX_PROJECTION | G_MTX_LOAD | G_MTX_NOPUSH);
} }
@ -456,7 +459,8 @@ static void geo_process_perspective(struct GraphNodePerspective *node) {
f32 aspect = (f32) gCurGraphNodeRoot->width / divisor; f32 aspect = (f32) gCurGraphNodeRoot->width / divisor;
#endif #endif
guPerspective(mtx, &perspNorm, not_zero(node->prevFov, gOverrideFOV), aspect, not_zero(node->near, gOverrideNear), not_zero(node->far, gOverrideFar), 1.0f); f32 near = MIN(node->near, MAX_PROJECTION_NEAR_VALUE);
guPerspective(mtx, &perspNorm, not_zero(node->prevFov, gOverrideFOV), aspect, not_zero(near, gOverrideNear), not_zero(node->far, gOverrideFar), 1.0f);
sPerspectiveNode = node; sPerspectiveNode = node;
sPerspectiveMtx = mtx; sPerspectiveMtx = mtx;