diff --git a/src/main.rs b/src/main.rs index 4d44215..91ba742 100644 --- a/src/main.rs +++ b/src/main.rs @@ -16,6 +16,7 @@ mod framework; mod primitives; mod instruction; mod load_roblox; +mod render_thread; pub struct GlobalState{ diff --git a/src/physics.rs b/src/physics.rs index 35340d5..5b62f80 100644 --- a/src/physics.rs +++ b/src/physics.rs @@ -32,23 +32,7 @@ pub enum PhysicsInputInstruction { Reset, Idle, } -#[derive(Debug)] -pub enum InputInstruction { - MoveMouse(glam::IVec2), - MoveRight(bool), - MoveUp(bool), - MoveBack(bool), - MoveLeft(bool), - MoveDown(bool), - MoveForward(bool), - Jump(bool), - Zoom(bool), - Reset, - Idle, - //Idle: there were no input events, but the simulation is safe to advance to this timestep - //for interpolation / networking / playback reasons, most playback heads will always want - //to be 1 instruction ahead to generate the next state for interpolation. -} + #[derive(Clone,Hash)] pub struct Body { position: Planar64Vec3,//I64 where 2^32 = 1 u @@ -531,7 +515,7 @@ pub struct PhysicsState{ touching:TouchingState, //camera must exist in state because wormholes modify the camera, also camera punch camera:PhysicsCamera, - next_mouse:MouseState,//Where is the mouse headed next + pub next_mouse:MouseState,//Where is the mouse headed next controls:u32, move_state:MoveState, //all models @@ -736,92 +720,6 @@ impl PhysicsState { self.touching.clear(); } - pub fn into_worker(mut self)->crate::worker::CNWorker>{ - let mut mouse_blocking=true; - let mut last_mouse_time=self.next_mouse.time; - let mut timeline=std::collections::VecDeque::new(); - crate::worker::CNWorker::new(move |ins:TimedInstruction|{ - if if let Some(phys_input)=match ins.instruction{ - InputInstruction::MoveMouse(m)=>{ - if mouse_blocking{ - //tell the game state which is living in the past about its future - timeline.push_front(TimedInstruction{ - time:last_mouse_time, - instruction:PhysicsInputInstruction::SetNextMouse(MouseState{time:ins.time,pos:m}), - }); - }else{ - //mouse has just started moving again after being still for longer than 10ms. - //replace the entire mouse interpolation state to avoid an intermediate state with identical m0.t m1.t timestamps which will divide by zero - timeline.push_front(TimedInstruction{ - time:last_mouse_time, - instruction:PhysicsInputInstruction::ReplaceMouse( - MouseState{time:last_mouse_time,pos:self.next_mouse.pos}, - MouseState{time:ins.time,pos:m} - ), - }); - //delay physics execution until we have an interpolation target - mouse_blocking=true; - } - last_mouse_time=ins.time; - None - }, - InputInstruction::MoveForward(s)=>Some(PhysicsInputInstruction::SetMoveForward(s)), - InputInstruction::MoveLeft(s)=>Some(PhysicsInputInstruction::SetMoveLeft(s)), - InputInstruction::MoveBack(s)=>Some(PhysicsInputInstruction::SetMoveBack(s)), - InputInstruction::MoveRight(s)=>Some(PhysicsInputInstruction::SetMoveRight(s)), - InputInstruction::MoveUp(s)=>Some(PhysicsInputInstruction::SetMoveUp(s)), - InputInstruction::MoveDown(s)=>Some(PhysicsInputInstruction::SetMoveDown(s)), - InputInstruction::Jump(s)=>Some(PhysicsInputInstruction::SetJump(s)), - InputInstruction::Zoom(s)=>Some(PhysicsInputInstruction::SetZoom(s)), - InputInstruction::Reset=>Some(PhysicsInputInstruction::Reset), - InputInstruction::Idle=>Some(PhysicsInputInstruction::Idle), - }{ - //non-mouse event - timeline.push_back(TimedInstruction{ - time:ins.time, - instruction:phys_input, - }); - - if mouse_blocking{ - //assume the mouse has stopped moving after 10ms. - //shitty mice are 125Hz which is 8ms so this should cover that. - //setting this to 100us still doesn't print even though it's 10x lower than the polling rate, - //so mouse events are probably not handled separately from drawing and fire right before it :( - if Time::from_millis(10)PhysicsOutputState{ PhysicsOutputState{ body:self.body.clone(), diff --git a/src/render_thread.rs b/src/render_thread.rs new file mode 100644 index 0000000..c8651cd --- /dev/null +++ b/src/render_thread.rs @@ -0,0 +1,117 @@ +use crate::integer::Time; +use crate::physics::{MouseState,PhysicsInputInstruction}; +use crate::instruction::{TimedInstruction,InstructionConsumer}; + +#[derive(Debug)] +pub enum InputInstruction { + MoveMouse(glam::IVec2), + MoveRight(bool), + MoveUp(bool), + MoveBack(bool), + MoveLeft(bool), + MoveDown(bool), + MoveForward(bool), + Jump(bool), + Zoom(bool), + Reset, + Render, + //Idle: there were no input events, but the simulation is safe to advance to this timestep + //for interpolation / networking / playback reasons, most playback heads will always want + //to be 1 instruction ahead to generate the next state for interpolation. +} + +pub struct RenderState{ + physics:crate::physics::PhysicsState, + graphics:crate::graphics::GraphicsState, +} +impl RenderState{ + pub fn into_worker(mut self)->crate::worker::CNWorker>{ + let mut mouse_blocking=true; + let mut last_mouse_time=self.physics.next_mouse.time; + let mut timeline=std::collections::VecDeque::new(); + crate::worker::CNWorker::new(move |ins:TimedInstruction|{ + let mut render=false; + if if let Some(phys_input)=match ins.instruction{ + InputInstruction::MoveMouse(m)=>{ + if mouse_blocking{ + //tell the game state which is living in the past about its future + timeline.push_front(TimedInstruction{ + time:last_mouse_time, + instruction:PhysicsInputInstruction::SetNextMouse(MouseState{time:ins.time,pos:m}), + }); + }else{ + //mouse has just started moving again after being still for longer than 10ms. + //replace the entire mouse interpolation state to avoid an intermediate state with identical m0.t m1.t timestamps which will divide by zero + timeline.push_front(TimedInstruction{ + time:last_mouse_time, + instruction:PhysicsInputInstruction::ReplaceMouse( + MouseState{time:last_mouse_time,pos:self.physics.next_mouse.pos}, + MouseState{time:ins.time,pos:m} + ), + }); + //delay physics execution until we have an interpolation target + mouse_blocking=true; + } + last_mouse_time=ins.time; + None + }, + InputInstruction::MoveForward(s)=>Some(PhysicsInputInstruction::SetMoveForward(s)), + InputInstruction::MoveLeft(s)=>Some(PhysicsInputInstruction::SetMoveLeft(s)), + InputInstruction::MoveBack(s)=>Some(PhysicsInputInstruction::SetMoveBack(s)), + InputInstruction::MoveRight(s)=>Some(PhysicsInputInstruction::SetMoveRight(s)), + InputInstruction::MoveUp(s)=>Some(PhysicsInputInstruction::SetMoveUp(s)), + InputInstruction::MoveDown(s)=>Some(PhysicsInputInstruction::SetMoveDown(s)), + InputInstruction::Jump(s)=>Some(PhysicsInputInstruction::SetJump(s)), + InputInstruction::Zoom(s)=>Some(PhysicsInputInstruction::SetZoom(s)), + InputInstruction::Reset=>Some(PhysicsInputInstruction::Reset), + InputInstruction::Render=>{render=true;Some(PhysicsInputInstruction::Idle)}, + }{ + //non-mouse event + timeline.push_back(TimedInstruction{ + time:ins.time, + instruction:phys_input, + }); + + if mouse_blocking{ + //assume the mouse has stopped moving after 10ms. + //shitty mice are 125Hz which is 8ms so this should cover that. + //setting this to 100us still doesn't print even though it's 10x lower than the polling rate, + //so mouse events are probably not handled separately from drawing and fire right before it :( + if Time::from_millis(10)