better lighting

This commit is contained in:
asrael 2026-01-31 09:31:17 -06:00
parent 805a2713a3
commit 6ed4e17065
75 changed files with 6417 additions and 3667 deletions

View file

@ -1,38 +1,29 @@
extern crate alloc;
use alloc::vec::Vec;
use libm::{cosf, sinf, sqrtf};
use crate::math::Vec3;
use crate::protocol::*;
use crate::math::{Vec3, Vec3Ext, VEC3_ZERO};
use crate::pxl8::*;
use crate::voxel::VoxelWorld;
use crate::world::World;
const ALIVE: u32 = 1 << 0;
const PLAYER: u32 = 1 << 1;
const GROUNDED: u32 = 1 << 2;
pub type Entity = pxl8_sim_entity;
const ALIVE: u32 = PXL8_SIM_FLAG_ALIVE;
const PLAYER: u32 = PXL8_SIM_FLAG_PLAYER;
const MAX_ENTITIES: usize = 1024;
#[derive(Clone, Copy)]
pub struct Entity {
pub flags: u32,
pub kind: u16,
pub pos: Vec3,
pub vel: Vec3,
pub yaw: f32,
pub pitch: f32,
}
impl Default for Entity {
fn default() -> Self {
Self {
flags: 0,
kind: 0,
pos: Vec3::ZERO,
vel: Vec3::ZERO,
pos: VEC3_ZERO,
vel: VEC3_ZERO,
yaw: 0.0,
pitch: 0.0,
flags: 0,
kind: 0,
_pad: 0,
}
}
}
@ -96,6 +87,13 @@ impl Simulation {
id
}
pub fn teleport_player(&mut self, x: f32, y: f32, z: f32) {
if let Some(id) = self.player {
let ent = &mut self.entities[id as usize];
ent.pos = Vec3::new(x, y, z);
}
}
pub fn step(&mut self, inputs: &[pxl8_input_msg], dt: f32) {
self.tick += 1;
self.time += dt;
@ -107,120 +105,68 @@ impl Simulation {
self.integrate(dt);
}
fn trace(&self, from: Vec3, to: Vec3, radius: f32) -> Vec3 {
if self.world.active().is_some() {
return self.world.trace(from, to, radius);
fn make_sim_world(&self, pos: Vec3) -> pxl8_sim_world {
if let Some(chunk) = self.world.active() {
if let Some(bsp) = chunk.as_bsp() {
return pxl8_sim_world {
bsp: bsp.as_c_bsp(),
vxl: core::ptr::null(),
vxl_cx: 0,
vxl_cy: 0,
vxl_cz: 0,
};
}
}
let cx = VoxelWorld::world_to_chunk(pos.x);
let cy = VoxelWorld::world_to_chunk(pos.y);
let cz = VoxelWorld::world_to_chunk(pos.z);
if let Some(chunk) = self.voxels.get_chunk(cx, cy, cz) {
pxl8_sim_world {
bsp: core::ptr::null(),
vxl: chunk.chunk as *const _,
vxl_cx: cx,
vxl_cy: cy,
vxl_cz: cz,
}
} else {
pxl8_sim_world {
bsp: core::ptr::null(),
vxl: core::ptr::null(),
vxl_cx: 0,
vxl_cy: 0,
vxl_cz: 0,
}
}
self.voxels.trace(from, to, radius)
}
fn integrate(&mut self, dt: f32) {
const GRAVITY: f32 = 800.0;
const FRICTION: f32 = 6.0;
const RADIUS: f32 = 16.0;
for i in 0..self.entities.len() {
let ent = &self.entities[i];
if ent.flags & ALIVE == 0 || ent.flags & PLAYER != 0 {
continue;
}
let mut vel = ent.vel;
let pos = ent.pos;
let flags = ent.flags;
vel.y = vel.y - GRAVITY * dt;
if flags & GROUNDED != 0 {
let speed = sqrtf(vel.x * vel.x + vel.z * vel.z);
if speed > 0.0 {
let drop = speed * FRICTION * dt;
let scale = (speed - drop).max(0.0) / speed;
vel.x = vel.x * scale;
vel.z = vel.z * scale;
}
}
let target = pos + vel * dt;
let new_pos = self.trace(pos, target, RADIUS);
let world = self.make_sim_world(ent.pos);
let ent = &mut self.entities[i];
ent.vel = vel;
ent.pos = new_pos;
unsafe {
pxl8_sim_integrate(ent, &world, dt);
}
}
}
fn move_player(&mut self, input: &pxl8_input_msg, dt: f32) {
let Some(id) = self.player else { return };
let ent = &mut self.entities[id as usize];
let ent = &self.entities[id as usize];
if ent.flags & ALIVE == 0 {
return;
}
const MOVE_SPEED: f32 = 320.0;
const GROUND_ACCEL: f32 = 10.0;
const AIR_ACCEL: f32 = 1.0;
const STOP_SPEED: f32 = 100.0;
const FRICTION: f32 = 6.0;
const RADIUS: f32 = 16.0;
let sin_yaw = sinf(input.yaw);
let cos_yaw = cosf(input.yaw);
let input_len = sqrtf(input.move_x * input.move_x + input.move_y * input.move_y);
let (move_dir, target_speed) = if input_len > 0.0 {
let nx = input.move_x / input_len;
let ny = input.move_y / input_len;
let dir = Vec3::new(
cos_yaw * nx - sin_yaw * ny,
0.0,
-sin_yaw * nx - cos_yaw * ny,
);
(dir, MOVE_SPEED)
} else {
(Vec3::ZERO, 0.0)
};
let grounded = ent.flags & GROUNDED != 0;
if grounded {
let speed = sqrtf(ent.vel.x * ent.vel.x + ent.vel.z * ent.vel.z);
if speed > 0.0 {
let control = speed.max(STOP_SPEED);
let drop = control * FRICTION * dt;
let scale = (speed - drop).max(0.0) / speed;
ent.vel.x *= scale;
ent.vel.z *= scale;
}
}
if target_speed > 0.0 {
let accel = if grounded { GROUND_ACCEL } else { AIR_ACCEL };
let current = ent.vel.x * move_dir.x + ent.vel.z * move_dir.z;
let add = target_speed - current;
if add > 0.0 {
let amount = (accel * target_speed * dt).min(add);
ent.vel.x += move_dir.x * amount;
ent.vel.z += move_dir.z * amount;
}
}
ent.yaw = input.yaw;
ent.pitch = (ent.pitch - input.look_dy * 0.008).clamp(-1.5, 1.5);
let pos = ent.pos;
let vel = ent.vel;
let target = pos + vel * dt;
let new_pos = self.trace(pos, target, RADIUS);
let ground_check = self.trace(new_pos, new_pos - Vec3::Y * 2.0, RADIUS);
let world = self.make_sim_world(ent.pos);
let ent = &mut self.entities[id as usize];
ent.pos = new_pos;
if ground_check.y < new_pos.y - 1.0 {
ent.flags &= !GROUNDED;
} else {
ent.flags |= GROUNDED;
unsafe {
pxl8_sim_move_player(ent, input, &world, dt);
}
}