better lighting
This commit is contained in:
parent
805a2713a3
commit
6ed4e17065
75 changed files with 6417 additions and 3667 deletions
172
pxl8d/src/sim.rs
172
pxl8d/src/sim.rs
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue