refactor: decouple sim from framework, remove voxel geometry
This commit is contained in:
parent
c538641ec8
commit
5a565844dd
41 changed files with 477 additions and 2407 deletions
|
|
@ -2,15 +2,6 @@
|
|||
|
||||
#include <math.h>
|
||||
|
||||
static usize vxl_world_to_local(f32 x, i32 chunk_coord) {
|
||||
f32 chunk_base = chunk_coord * PXL8_VXL_WORLD_CHUNK_SIZE;
|
||||
f32 local_world = x - chunk_base;
|
||||
i32 local_voxel = (i32)floorf(local_world / PXL8_VXL_SCALE);
|
||||
if (local_voxel < 0) return 0;
|
||||
if (local_voxel >= PXL8_VXL_CHUNK_SIZE) return PXL8_VXL_CHUNK_SIZE - 1;
|
||||
return (usize)local_voxel;
|
||||
}
|
||||
|
||||
static i32 bsp_find_leaf(const pxl8_bsp* bsp, pxl8_vec3 pos) {
|
||||
if (!bsp || bsp->num_nodes == 0) return -1;
|
||||
|
||||
|
|
@ -59,82 +50,36 @@ pxl8_vec3 pxl8_bsp_trace(const pxl8_bsp* bsp, pxl8_vec3 from, pxl8_vec3 to, f32
|
|||
return result;
|
||||
}
|
||||
|
||||
bool pxl8_vxl_point_solid(const pxl8_vxl_chunk* chunk, i32 cx, i32 cy, i32 cz,
|
||||
f32 x, f32 y, f32 z) {
|
||||
if (!chunk) return false;
|
||||
|
||||
usize lx = vxl_world_to_local(x, cx);
|
||||
usize ly = vxl_world_to_local(y, cy);
|
||||
usize lz = vxl_world_to_local(z, cz);
|
||||
|
||||
return pxl8_vxl_block_get(chunk, (i32)lx, (i32)ly, (i32)lz) != PXL8_VXL_BLOCK_AIR;
|
||||
}
|
||||
|
||||
static bool vxl_point_clear(const pxl8_vxl_chunk* chunk, i32 cx, i32 cy, i32 cz,
|
||||
f32 x, f32 y, f32 z, f32 radius) {
|
||||
if (pxl8_vxl_point_solid(chunk, cx, cy, cz, x - radius, y, z)) return false;
|
||||
if (pxl8_vxl_point_solid(chunk, cx, cy, cz, x + radius, y, z)) return false;
|
||||
if (pxl8_vxl_point_solid(chunk, cx, cy, cz, x, y - radius, z)) return false;
|
||||
if (pxl8_vxl_point_solid(chunk, cx, cy, cz, x, y + radius, z)) return false;
|
||||
if (pxl8_vxl_point_solid(chunk, cx, cy, cz, x, y, z - radius)) return false;
|
||||
if (pxl8_vxl_point_solid(chunk, cx, cy, cz, x, y, z + radius)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
pxl8_vec3 pxl8_vxl_trace(const pxl8_vxl_chunk* chunk, i32 cx, i32 cy, i32 cz,
|
||||
pxl8_vec3 from, pxl8_vec3 to, f32 radius) {
|
||||
if (!chunk) return to;
|
||||
|
||||
if (vxl_point_clear(chunk, cx, cy, cz, to.x, to.y, to.z, radius)) {
|
||||
return to;
|
||||
}
|
||||
|
||||
bool x_ok = vxl_point_clear(chunk, cx, cy, cz, to.x, from.y, from.z, radius);
|
||||
bool y_ok = vxl_point_clear(chunk, cx, cy, cz, from.x, to.y, from.z, radius);
|
||||
bool z_ok = vxl_point_clear(chunk, cx, cy, cz, from.x, from.y, to.z, radius);
|
||||
|
||||
pxl8_vec3 result = from;
|
||||
if (x_ok) result.x = to.x;
|
||||
if (y_ok) result.y = to.y;
|
||||
if (z_ok) result.z = to.z;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
pxl8_vec3 pxl8_sim_trace(const pxl8_sim_world* world, pxl8_vec3 from, pxl8_vec3 to, f32 radius) {
|
||||
pxl8_vec3 pxl8_sim_trace(const pxl8_sim_world* world, pxl8_vec3 from, pxl8_vec3 to, f32 radius, f32 height) {
|
||||
(void)height;
|
||||
if (!world) return to;
|
||||
|
||||
if (world->bsp) {
|
||||
return pxl8_bsp_trace(world->bsp, from, to, radius);
|
||||
}
|
||||
|
||||
if (world->vxl) {
|
||||
return pxl8_vxl_trace(world->vxl, world->vxl_cx, world->vxl_cy, world->vxl_cz,
|
||||
from, to, radius);
|
||||
}
|
||||
|
||||
return to;
|
||||
}
|
||||
|
||||
bool pxl8_sim_check_ground(const pxl8_sim_world* world, pxl8_vec3 pos, f32 radius) {
|
||||
if (!world) return true;
|
||||
if (!world->bsp && !world->vxl) return true;
|
||||
if (!world->bsp) return true;
|
||||
|
||||
pxl8_vec3 down = {pos.x, pos.y - 2.0f, pos.z};
|
||||
pxl8_vec3 result = pxl8_sim_trace(world, pos, down, radius);
|
||||
pxl8_vec3 result = pxl8_sim_trace(world, pos, down, radius, 0.0f);
|
||||
|
||||
return result.y > down.y;
|
||||
}
|
||||
|
||||
void pxl8_sim_move_player(pxl8_sim_entity* ent, const pxl8_input_msg* input,
|
||||
const pxl8_sim_world* world, f32 dt) {
|
||||
if (!ent || !input) return;
|
||||
const pxl8_sim_world* world, const pxl8_sim_config* cfg, f32 dt) {
|
||||
if (!ent || !input || !cfg) return;
|
||||
if (!(ent->flags & PXL8_SIM_FLAG_ALIVE)) return;
|
||||
|
||||
ent->yaw -= input->look_dx * 0.008f;
|
||||
f32 new_pitch = ent->pitch - input->look_dy * 0.008f;
|
||||
if (new_pitch > PXL8_SIM_MAX_PITCH) new_pitch = PXL8_SIM_MAX_PITCH;
|
||||
if (new_pitch < -PXL8_SIM_MAX_PITCH) new_pitch = -PXL8_SIM_MAX_PITCH;
|
||||
if (new_pitch > cfg->max_pitch) new_pitch = cfg->max_pitch;
|
||||
if (new_pitch < -cfg->max_pitch) new_pitch = -cfg->max_pitch;
|
||||
ent->pitch = new_pitch;
|
||||
|
||||
f32 sin_yaw = sinf(ent->yaw);
|
||||
|
|
@ -150,7 +95,7 @@ void pxl8_sim_move_player(pxl8_sim_entity* ent, const pxl8_input_msg* input,
|
|||
f32 ny = input->move_y / input_len;
|
||||
move_dir.x = cos_yaw * nx - sin_yaw * ny;
|
||||
move_dir.z = -sin_yaw * nx - cos_yaw * ny;
|
||||
target_speed = PXL8_SIM_MOVE_SPEED;
|
||||
target_speed = cfg->move_speed;
|
||||
}
|
||||
|
||||
ent->vel.x = move_dir.x * target_speed;
|
||||
|
|
@ -159,13 +104,13 @@ void pxl8_sim_move_player(pxl8_sim_entity* ent, const pxl8_input_msg* input,
|
|||
bool grounded = (ent->flags & PXL8_SIM_FLAG_GROUNDED) != 0;
|
||||
|
||||
if (grounded && (input->buttons & 1)) {
|
||||
ent->vel.y = PXL8_SIM_JUMP_VELOCITY;
|
||||
ent->vel.y = cfg->jump_velocity;
|
||||
ent->flags &= ~PXL8_SIM_FLAG_GROUNDED;
|
||||
grounded = false;
|
||||
}
|
||||
|
||||
if (!grounded) {
|
||||
ent->vel.y -= PXL8_SIM_GRAVITY * dt;
|
||||
ent->vel.y -= cfg->gravity * dt;
|
||||
}
|
||||
|
||||
pxl8_vec3 target = {
|
||||
|
|
@ -174,10 +119,27 @@ void pxl8_sim_move_player(pxl8_sim_entity* ent, const pxl8_input_msg* input,
|
|||
ent->pos.z + ent->vel.z * dt
|
||||
};
|
||||
|
||||
pxl8_vec3 new_pos = pxl8_sim_trace(world, ent->pos, target, PXL8_SIM_PLAYER_RADIUS);
|
||||
pxl8_vec3 new_pos = pxl8_sim_trace(world, ent->pos, target, cfg->player_radius, cfg->player_height);
|
||||
|
||||
if (ent->vel.y < 0 && new_pos.y > target.y + 0.01f) {
|
||||
f32 hi = new_pos.y;
|
||||
f32 lo = target.y;
|
||||
for (i32 i = 0; i < 8; i++) {
|
||||
f32 mid = (hi + lo) * 0.5f;
|
||||
pxl8_vec3 test = {new_pos.x, mid, new_pos.z};
|
||||
pxl8_vec3 result = pxl8_sim_trace(world, new_pos, test, cfg->player_radius, cfg->player_height);
|
||||
if (result.y > mid + 0.01f) {
|
||||
lo = mid;
|
||||
} else {
|
||||
hi = mid;
|
||||
}
|
||||
}
|
||||
new_pos.y = hi;
|
||||
}
|
||||
|
||||
ent->pos = new_pos;
|
||||
|
||||
if (pxl8_sim_check_ground(world, ent->pos, PXL8_SIM_PLAYER_RADIUS)) {
|
||||
if (pxl8_sim_check_ground(world, ent->pos, cfg->player_radius)) {
|
||||
ent->flags |= PXL8_SIM_FLAG_GROUNDED;
|
||||
if (ent->vel.y < 0) ent->vel.y = 0;
|
||||
} else {
|
||||
|
|
@ -185,19 +147,20 @@ void pxl8_sim_move_player(pxl8_sim_entity* ent, const pxl8_input_msg* input,
|
|||
}
|
||||
}
|
||||
|
||||
void pxl8_sim_integrate(pxl8_sim_entity* ent, const pxl8_sim_world* world, f32 dt) {
|
||||
if (!ent) return;
|
||||
void pxl8_sim_integrate(pxl8_sim_entity* ent, const pxl8_sim_world* world,
|
||||
const pxl8_sim_config* cfg, f32 dt) {
|
||||
if (!ent || !cfg) return;
|
||||
if (!(ent->flags & PXL8_SIM_FLAG_ALIVE)) return;
|
||||
if (ent->flags & PXL8_SIM_FLAG_PLAYER) return;
|
||||
|
||||
bool grounded = (ent->flags & PXL8_SIM_FLAG_GROUNDED) != 0;
|
||||
|
||||
ent->vel.y -= PXL8_SIM_GRAVITY * dt;
|
||||
ent->vel.y -= cfg->gravity * dt;
|
||||
|
||||
if (grounded) {
|
||||
f32 speed = sqrtf(ent->vel.x * ent->vel.x + ent->vel.z * ent->vel.z);
|
||||
if (speed > 0.0f) {
|
||||
f32 drop = speed * PXL8_SIM_FRICTION * dt;
|
||||
f32 drop = speed * cfg->friction * dt;
|
||||
f32 new_speed = speed - drop;
|
||||
if (new_speed < 0.0f) new_speed = 0.0f;
|
||||
f32 scale = new_speed / speed;
|
||||
|
|
@ -212,10 +175,27 @@ void pxl8_sim_integrate(pxl8_sim_entity* ent, const pxl8_sim_world* world, f32 d
|
|||
ent->pos.z + ent->vel.z * dt
|
||||
};
|
||||
|
||||
pxl8_vec3 new_pos = pxl8_sim_trace(world, ent->pos, target, PXL8_SIM_PLAYER_RADIUS);
|
||||
pxl8_vec3 new_pos = pxl8_sim_trace(world, ent->pos, target, cfg->player_radius, cfg->player_height);
|
||||
|
||||
if (ent->vel.y < 0 && new_pos.y > target.y + 0.01f) {
|
||||
f32 hi = new_pos.y;
|
||||
f32 lo = target.y;
|
||||
for (i32 i = 0; i < 8; i++) {
|
||||
f32 mid = (hi + lo) * 0.5f;
|
||||
pxl8_vec3 test = {new_pos.x, mid, new_pos.z};
|
||||
pxl8_vec3 result = pxl8_sim_trace(world, new_pos, test, cfg->player_radius, cfg->player_height);
|
||||
if (result.y > mid + 0.01f) {
|
||||
lo = mid;
|
||||
} else {
|
||||
hi = mid;
|
||||
}
|
||||
}
|
||||
new_pos.y = hi;
|
||||
}
|
||||
|
||||
ent->pos = new_pos;
|
||||
|
||||
if (pxl8_sim_check_ground(world, ent->pos, PXL8_SIM_PLAYER_RADIUS)) {
|
||||
if (pxl8_sim_check_ground(world, ent->pos, cfg->player_radius)) {
|
||||
ent->flags |= PXL8_SIM_FLAG_GROUNDED;
|
||||
if (ent->vel.y < 0.0f) ent->vel.y = 0.0f;
|
||||
} else {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue