commit 41c106971b3219fe98814aacbc76e04f5077f38e
parent f12eae32691cdef29ab3ea230f3ecabba0e05cac
Author: averagecoder <averagecoder@noreply.codeberg.org>
Date: Mon, 24 Aug 2026 18:37:57 +0300
fix: thin fence collision
Diffstat:
| M | src/render.c | | | 100 | ++++++++++++++++++++++++++++++++++++++++++++++++------------------------------- |
1 file changed, 61 insertions(+), 39 deletions(-)
diff --git a/src/render.c b/src/render.c
@@ -1324,20 +1324,27 @@ move_and_slide(float *px, float py, float *pz, float vx, float vz, float dt)
const struct col_cell *c;
const struct col_triangle *t;
float sphere[3][3];
- float closest[3], diff[3], push_dir[3];
- float rad, dist_sq, dist, push, h_len, dot, step_x, step_z;
- float min_x, max_x, min_z, max_z;
- int sub, iter, s, i, gx, gz, gx0, gx1, gz0, gz1;
+ float closest[3], diff[3];
+ float rad, dist_sq, dist, h_len, dot, step_x, step_z, push;
+ float min_x, max_x, min_y, max_y, min_z, max_z;
+ float prev_x, prev_z, accum_nx, accum_nz, n_len;
+ int sub, iter, s, i, gx, gz, gx0, gx1, gz0, gz1, contacts;
rad = 0.35f;
+ step_x = (vx * dt) * 0.25f;
+ step_z = (vz * dt) * 0.25f;
- for (sub = 0; sub < 2; sub++) {
- step_x = (vx * dt) * 0.5f;
- step_z = (vz * dt) * 0.5f;
+ for (sub = 0; sub < 4; sub++) {
+ prev_x = *px;
+ prev_z = *pz;
*px += step_x;
*pz += step_z;
+ accum_nx = 0.0f;
+ accum_nz = 0.0f;
+ contacts = 0;
+
gx0 = (int)((*px - rad - MAP_MIN) / ((MAP_MAX - MAP_MIN) / GRID_SZ));
gx1 = (int)((*px + rad - MAP_MIN) / ((MAP_MAX - MAP_MIN) / GRID_SZ));
gz0 = (int)((*pz - rad - MAP_MIN) / ((MAP_MAX - MAP_MIN) / GRID_SZ));
@@ -1367,7 +1374,13 @@ move_and_slide(float *px, float py, float *pz, float vx, float vz, float dt)
for (i = 0; i < (int)c->count; i++) {
t = &c->tris[i];
- if (t->norm[1] > 0.5f) {
+ if (t->norm[1] > 0.6f) {
+ continue;
+ }
+
+ min_y = fminf(t->v0[1], fminf(t->v1[1], t->v2[1]));
+ max_y = fmaxf(t->v0[1], fmaxf(t->v1[1], t->v2[1]));
+ if (py + 1.9f < min_y || py > max_y) {
continue;
}
@@ -1397,48 +1410,57 @@ move_and_slide(float *px, float py, float *pz, float vx, float vz, float dt)
if (dist_sq < rad * rad) {
dist = sqrtf(dist_sq);
- dot = diff[0] * t->norm[0] +
- diff[1] * t->norm[1] +
- diff[2] * t->norm[2];
-
- if (dot < 0.0f || dist < 1e-4f) {
- push_dir[0] = t->norm[0];
- push_dir[2] = t->norm[2];
- push = rad + dist;
+ h_len = sqrtf(diff[0] * diff[0] + diff[2] * diff[2]);
+
+ if (h_len > 1e-4f) {
+ diff[0] /= h_len;
+ diff[2] /= h_len;
} else {
- push_dir[0] = diff[0] / dist;
- push_dir[2] = diff[2] / dist;
- push = rad - dist;
+ diff[0] = prev_x - closest[0];
+ diff[2] = prev_z - closest[2];
+ h_len = sqrtf(diff[0] * diff[0] + diff[2] * diff[2]);
+ if (h_len > 1e-4f) {
+ diff[0] /= h_len;
+ diff[2] /= h_len;
+ } else {
+ diff[0] = 1.0f;
+ diff[2] = 0.0f;
+ }
}
- h_len = sqrtf(push_dir[0] * push_dir[0] +
- push_dir[2] * push_dir[2]);
+ push = rad - dist;
+ *px += diff[0] * push;
+ *pz += diff[2] * push;
- if (h_len > 1e-4f) {
- push_dir[0] /= h_len;
- push_dir[2] /= h_len;
- *px += push_dir[0] * push;
- *pz += push_dir[2] * push;
-
- dot = vx * push_dir[0] + vz * push_dir[2];
- if (dot < 0.0f) {
- vx -= dot * push_dir[0];
- vz -= dot * push_dir[2];
- }
+ accum_nx += diff[0];
+ accum_nz += diff[2];
+ contacts++;
- sphere[0][0] = *px;
- sphere[0][2] = *pz;
- sphere[1][0] = *px;
- sphere[1][2] = *pz;
- sphere[2][0] = *px;
- sphere[2][2] = *pz;
- }
+ sphere[0][0] = *px;
+ sphere[0][2] = *pz;
+ sphere[1][0] = *px;
+ sphere[1][2] = *pz;
+ sphere[2][0] = *px;
+ sphere[2][2] = *pz;
}
}
}
}
}
}
+
+ if (contacts > 0) {
+ n_len = sqrtf(accum_nx * accum_nx + accum_nz * accum_nz);
+ if (n_len > 1e-4f) {
+ accum_nx /= n_len;
+ accum_nz /= n_len;
+ dot = vx * accum_nx + vz * accum_nz;
+ if (dot < 0.0f) {
+ vx -= dot * accum_nx;
+ vz -= dot * accum_nz;
+ }
+ }
+ }
}
}