mirror of
https://github.com/coop-deluxe/sm64coopdx.git
synced 2024-11-25 21:45:12 +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;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
void vec3f_project(Vec3f vec, Vec3f onto, Vec3f out);
|
||||
f32 vec3f_dist(Vec3f v1, Vec3f v2);
|
||||
|
||||
#endif // MATH_UTIL_H
|
||||
|
|
|
@ -482,60 +482,93 @@ static void newcam_update_values(void) {
|
|||
}
|
||||
}
|
||||
|
||||
static void newcam_bounding_box(void) {
|
||||
Vec3f camdirs[NEW_CAM_BOUNDING_BOX_RAYS] = { 0 };
|
||||
Vec3f raypos[NEW_CAM_BOUNDING_BOX_RAYS] = { 0 };
|
||||
s16 antiYaw = newcam_yaw - 0x4000;
|
||||
|
||||
// sideways ray 1
|
||||
camdirs[0][0] = coss(antiYaw) * NEW_CAM_BOUNDING_BOX_HRADIUS;
|
||||
camdirs[0][2] = sins(antiYaw) * NEW_CAM_BOUNDING_BOX_HRADIUS;
|
||||
|
||||
// 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 debug_pos(f32 x, f32 y, f32 z, u8 hit) { // DO NOT COMMIT
|
||||
if(gMarioStates[0].marioObj == NULL) { return; }
|
||||
struct Object* obj = spawn_object(gMarioStates[0].marioObj, hit ? MODEL_RED_COIN : MODEL_YELLOW_COIN, bhvSparkle);
|
||||
if (obj == NULL) { return; }
|
||||
obj->oPosX = x;
|
||||
obj->oPosY = y;
|
||||
obj->oPosZ = z;
|
||||
obj_scale(obj, 0.5f);
|
||||
}
|
||||
|
||||
static void newcam_collision(void) {
|
||||
struct Surface *surf;
|
||||
Vec3f camdir;
|
||||
// check if we can see player
|
||||
Vec3f up = { 0, 1, 0 };
|
||||
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);
|
||||
|
||||
f32 checkWidth = 75;
|
||||
f32 checkHeight = 90;
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
Vec3f camray = {
|
||||
newcam_pos[0] - newcam_lookat[0] - offset[0],
|
||||
newcam_pos[1] - newcam_lookat[1] - offset[1],
|
||||
newcam_pos[2] - newcam_lookat[2] - offset[2],
|
||||
};
|
||||
|
||||
Vec3f camorig = {
|
||||
newcam_pos_target[0] + offset[0],
|
||||
newcam_pos_target[1] + offset[1],
|
||||
newcam_pos_target[2] + offset[2],
|
||||
};
|
||||
|
||||
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;
|
||||
|
||||
camdir[0] = newcam_pos[0]-newcam_lookat[0];
|
||||
camdir[1] = newcam_pos[1]-newcam_lookat[1];
|
||||
camdir[2] = newcam_pos[2]-newcam_lookat[2];
|
||||
|
||||
find_surface_on_ray(newcam_pos_target, camdir, &surf, hitpos);
|
||||
|
||||
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 (surf) {
|
||||
// offset the hit pos by the hit normal
|
||||
Vec3f offset = { 0 };
|
||||
|
@ -551,6 +584,15 @@ static void newcam_collision(void) {
|
|||
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);
|
||||
}
|
||||
}
|
||||
|
||||
static void newcam_set_pan(void) {
|
||||
|
@ -611,7 +653,6 @@ static void newcam_position_cam(void) {
|
|||
newcam_level_bounds();
|
||||
if (newcam_modeflags & NC_FLAG_COLLISION) {
|
||||
newcam_collision();
|
||||
newcam_bounding_box();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -11741,28 +11741,6 @@ static s8 sRomHackIsUpdate = 0;
|
|||
static f32 sRomHackWaterFocus = 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) {
|
||||
// do collision checking
|
||||
struct Surface *surf = NULL;
|
||||
|
|
|
@ -42,6 +42,8 @@
|
|||
|
||||
#define MATRIX_STACK_SIZE 32
|
||||
|
||||
#define MAX_PROJECTION_NEAR_VALUE 5
|
||||
|
||||
s16 gMatStackIndex;
|
||||
Mat4 gMatStack[MATRIX_STACK_SIZE] = {};
|
||||
Mat4 gMatStackPrev[MATRIX_STACK_SIZE] = {};
|
||||
|
@ -222,7 +224,8 @@ void patch_mtx_interpolated(f32 delta) {
|
|||
if (sPerspectiveNode != NULL) {
|
||||
u16 perspNorm;
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -456,7 +459,8 @@ static void geo_process_perspective(struct GraphNodePerspective *node) {
|
|||
f32 aspect = (f32) gCurGraphNodeRoot->width / divisor;
|
||||
#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;
|
||||
sPerspectiveMtx = mtx;
|
||||
|
|
Loading…
Reference in a new issue