antizona

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

commit 41c106971b3219fe98814aacbc76e04f5077f38e
parent f12eae32691cdef29ab3ea230f3ecabba0e05cac
Author: averagecoder <averagecoder@noreply.codeberg.org>
Date:   Mon, 24 Aug 2026 18:37:57 +0300

fix: thin fence collision

Diffstat:
Msrc/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; + } + } + } } }