mirror of https://github.com/sm64pc/sm64pc.git
Improve bettercam's collision detection and avoidance
The precision of ray casting was too low previously, causing the collision checks to skip right past a wall sometimes. There was also nothing to prevent the camera from getting too close to a wall horizontally or vertically.
This commit is contained in:
parent
dcc16eaed7
commit
75bed240fa
|
@ -920,11 +920,14 @@ void find_surface_on_ray(Vec3f orig, Vec3f dir, struct Surface **hit_surface, Ve
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// increase collision checking precision (normally 1)
|
||||||
|
f32 precision = 2;
|
||||||
|
|
||||||
// Get cells we cross using DDA
|
// Get cells we cross using DDA
|
||||||
if (absx(dir[0]) >= absx(dir[2]))
|
if (absx(dir[0]) >= absx(dir[2]))
|
||||||
step = absx(dir[0]) / CELL_SIZE;
|
step = precision * absx(dir[0]) / CELL_SIZE;
|
||||||
else
|
else
|
||||||
step = absx(dir[2]) / CELL_SIZE;
|
step = precision * absx(dir[2]) / CELL_SIZE;
|
||||||
|
|
||||||
dx = dir[0] / step / CELL_SIZE;
|
dx = dir[0] / step / CELL_SIZE;
|
||||||
dz = dir[2] / step / CELL_SIZE;
|
dz = dir[2] / step / CELL_SIZE;
|
||||||
|
|
|
@ -16,6 +16,9 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define NEW_CAM_BOUNDING_BOX_RAYS 4
|
||||||
|
#define NEW_CAM_BOUNDING_BOX_HRADIUS 250
|
||||||
|
#define NEW_CAM_BOUNDING_BOX_VRADIUS 50
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Quick explanation of the camera modes
|
Quick explanation of the camera modes
|
||||||
|
@ -473,6 +476,47 @@ 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 (int 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 (int 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;
|
struct Surface *surf;
|
||||||
Vec3f camdir;
|
Vec3f camdir;
|
||||||
|
@ -486,8 +530,16 @@ static void newcam_collision(void) {
|
||||||
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]));
|
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) {
|
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[0] = hitpos[0];
|
||||||
newcam_pos[1] = approach_f32(hitpos[1],newcam_pos[1],25,-25);
|
newcam_pos[1] = hitpos[1];
|
||||||
newcam_pos[2] = hitpos[2];
|
newcam_pos[2] = hitpos[2];
|
||||||
newcam_pan_x = 0;
|
newcam_pan_x = 0;
|
||||||
newcam_pan_z = 0;
|
newcam_pan_z = 0;
|
||||||
|
@ -541,8 +593,10 @@ static void newcam_position_cam(void) {
|
||||||
if (newcam_modeflags & NC_FLAG_FOCUSZ)
|
if (newcam_modeflags & NC_FLAG_FOCUSZ)
|
||||||
newcam_lookat[2] = newcam_pos_target[2]-newcam_pan_z;
|
newcam_lookat[2] = newcam_pos_target[2]-newcam_pan_z;
|
||||||
|
|
||||||
if (newcam_modeflags & NC_FLAG_COLLISION)
|
if (newcam_modeflags & NC_FLAG_COLLISION) {
|
||||||
newcam_collision();
|
newcam_collision();
|
||||||
|
newcam_bounding_box();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue