mirror of
https://github.com/coop-deluxe/sm64coopdx.git
synced 2024-11-26 05:55:15 +00:00
Bettercam improvements: no longer sways when close to geo, no longer zooms if player partially visible
This commit is contained in:
parent
0778226e60
commit
c15f8bfef0
5 changed files with 134 additions and 86 deletions
|
@ -985,3 +985,25 @@ f32 not_zero(f32 value, f32 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);
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue