forked from StrafesNET/strafe-client
Compare commits
26 Commits
master
...
tickless-p
Author | SHA1 | Date | |
---|---|---|---|
f60a370228 | |||
79053420cd | |||
ea9ac948f8 | |||
7f841427dd | |||
4f5c9afed3 | |||
53605746d4 | |||
cead05b08b | |||
949897a558 | |||
a4ed50fc38 | |||
846f681648 | |||
ff54a03487 | |||
8c2dda5205 | |||
addde65caa | |||
2c4e6f642b | |||
f11742ef3b | |||
e6862b5bad | |||
e18e8a9a7d | |||
f600092f13 | |||
1f1ef5d3ad | |||
54bf0358d6 | |||
6caa273623 | |||
101f0f8d12 | |||
fc751a9fe8 | |||
5391b635fb | |||
230469496e | |||
ea3134de51 |
338
src/body.rs
Normal file
338
src/body.rs
Normal file
@ -0,0 +1,338 @@
|
|||||||
|
use crate::instruction::{InstructionEmitter, InstructionConsumer, TimedInstruction};
|
||||||
|
|
||||||
|
pub enum PhysicsInstruction {
|
||||||
|
CollisionStart(RelativeCollision),
|
||||||
|
CollisionEnd(RelativeCollision),
|
||||||
|
StrafeTick,
|
||||||
|
Jump,
|
||||||
|
SetWalkTargetVelocity(glam::Vec3),
|
||||||
|
ReachWalkTargetVelocity,
|
||||||
|
// Water,
|
||||||
|
// Spawn(
|
||||||
|
// Option<SpawnId>,
|
||||||
|
// bool,//true = Trigger; false = teleport
|
||||||
|
// bool,//true = Force
|
||||||
|
// )
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Body {
|
||||||
|
position: glam::Vec3,//I64 where 2^32 = 1 u
|
||||||
|
velocity: glam::Vec3,//I64 where 2^32 = 1 u/s
|
||||||
|
acceleration: glam::Vec3,//I64 where 2^32 = 1 u/s/s
|
||||||
|
time: TIME,//nanoseconds x xxxxD!
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum MoveRestriction {
|
||||||
|
Air,
|
||||||
|
Water,
|
||||||
|
Ground,
|
||||||
|
Ladder,//multiple ladders how
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct PhysicsState {
|
||||||
|
pub body: Body,
|
||||||
|
pub contacts: Vec<RelativeCollision>,
|
||||||
|
//temp
|
||||||
|
pub models_cringe_clone: Vec<Model>,
|
||||||
|
pub temp_control_dir: glam::Vec3,
|
||||||
|
pub time: TIME,
|
||||||
|
pub strafe_tick_num: TIME,
|
||||||
|
pub strafe_tick_den: TIME,
|
||||||
|
pub tick: u32,
|
||||||
|
pub mv: f32,
|
||||||
|
pub walkspeed: f32,
|
||||||
|
pub friction: f32,
|
||||||
|
pub walk_target_velocity: glam::Vec3,
|
||||||
|
pub gravity: glam::Vec3,
|
||||||
|
pub grounded: bool,
|
||||||
|
pub jump_trying: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone,Copy)]
|
||||||
|
pub enum AabbFace{
|
||||||
|
Right,//+X
|
||||||
|
Top,
|
||||||
|
Back,
|
||||||
|
Left,
|
||||||
|
Bottom,
|
||||||
|
Front,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Aabb {
|
||||||
|
min: glam::Vec3,
|
||||||
|
max: glam::Vec3,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Aabb {
|
||||||
|
// const FACE_DATA: [[f32; 3]; 6] = [
|
||||||
|
// [0.0f32, 0., 1.],
|
||||||
|
// [0.0f32, 0., -1.],
|
||||||
|
// [1.0f32, 0., 0.],
|
||||||
|
// [-1.0f32, 0., 0.],
|
||||||
|
// [0.0f32, 1., 0.],
|
||||||
|
// [0.0f32, -1., 0.],
|
||||||
|
// ];
|
||||||
|
const VERTEX_DATA_RIGHT: [glam::Vec3; 4] = [
|
||||||
|
glam::vec3(1., -1., -1.),
|
||||||
|
glam::vec3(1., 1., -1.),
|
||||||
|
glam::vec3(1., 1., 1.),
|
||||||
|
glam::vec3(1., -1., 1.),
|
||||||
|
];
|
||||||
|
const VERTEX_DATA_TOP: [glam::Vec3; 4] = [
|
||||||
|
glam::vec3(1., 1., -1.),
|
||||||
|
glam::vec3(-1., 1., -1.),
|
||||||
|
glam::vec3(-1., 1., 1.),
|
||||||
|
glam::vec3(1., 1., 1.),
|
||||||
|
];
|
||||||
|
const VERTEX_DATA_BACK: [glam::Vec3; 4] = [
|
||||||
|
glam::vec3(-1., -1., 1.),
|
||||||
|
glam::vec3(1., -1., 1.),
|
||||||
|
glam::vec3(1., 1., 1.),
|
||||||
|
glam::vec3(-1., 1., 1.),
|
||||||
|
];
|
||||||
|
const VERTEX_DATA_LEFT: [glam::Vec3; 4] = [
|
||||||
|
glam::vec3(-1., -1., 1.),
|
||||||
|
glam::vec3(-1., 1., 1.),
|
||||||
|
glam::vec3(-1., 1., -1.),
|
||||||
|
glam::vec3(-1., -1., -1.),
|
||||||
|
];
|
||||||
|
const VERTEX_DATA_BOTTOM: [glam::Vec3; 4] = [
|
||||||
|
glam::vec3(1., -1., 1.),
|
||||||
|
glam::vec3(-1., -1., 1.),
|
||||||
|
glam::vec3(-1., -1., -1.),
|
||||||
|
glam::vec3(1., -1., -1.),
|
||||||
|
];
|
||||||
|
const VERTEX_DATA_FRONT: [glam::Vec3; 4] = [
|
||||||
|
glam::vec3(-1., 1., -1.),
|
||||||
|
glam::vec3(1., 1., -1.),
|
||||||
|
glam::vec3(1., -1., -1.),
|
||||||
|
glam::vec3(-1., -1., -1.),
|
||||||
|
];
|
||||||
|
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {min: glam::Vec3::INFINITY,max: glam::Vec3::NEG_INFINITY}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn grow(&mut self, point:glam::Vec3){
|
||||||
|
self.min=self.min.min(point);
|
||||||
|
self.max=self.max.max(point);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn normal(face:AabbFace) -> glam::Vec3 {
|
||||||
|
match face {
|
||||||
|
AabbFace::Right => glam::vec3(1.,0.,0.),
|
||||||
|
AabbFace::Top => glam::vec3(0.,1.,0.),
|
||||||
|
AabbFace::Back => glam::vec3(0.,0.,1.),
|
||||||
|
AabbFace::Left => glam::vec3(-1.,0.,0.),
|
||||||
|
AabbFace::Bottom => glam::vec3(0.,-1.,0.),
|
||||||
|
AabbFace::Front => glam::vec3(0.,0.,-1.),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn face_vertices(face:AabbFace) -> [glam::Vec3;4] {
|
||||||
|
match face {
|
||||||
|
AabbFace::Right => Self::VERTEX_DATA_RIGHT,
|
||||||
|
AabbFace::Top => Self::VERTEX_DATA_TOP,
|
||||||
|
AabbFace::Back => Self::VERTEX_DATA_BACK,
|
||||||
|
AabbFace::Left => Self::VERTEX_DATA_LEFT,
|
||||||
|
AabbFace::Bottom => Self::VERTEX_DATA_BOTTOM,
|
||||||
|
AabbFace::Front => Self::VERTEX_DATA_FRONT,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type Face = AabbFace;
|
||||||
|
type TreyMesh = Aabb;
|
||||||
|
|
||||||
|
pub struct Model {
|
||||||
|
//A model is a thing that has a hitbox. can be represented by a list of TreyMesh-es
|
||||||
|
//in this iteration, all it needs is extents.
|
||||||
|
transform: glam::Mat4,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Model {
|
||||||
|
pub fn new(transform:glam::Mat4) -> Self {
|
||||||
|
Self{transform}
|
||||||
|
}
|
||||||
|
pub fn face_vertices(&self,face:Face) -> [glam::Vec3;4] {
|
||||||
|
Aabb::face_vertices(face)
|
||||||
|
}
|
||||||
|
pub fn face_mesh(&self,face:Face) -> TreyMesh {
|
||||||
|
let mut aabb=Aabb::new();
|
||||||
|
for &vertex in self.face_vertices(face).iter() {
|
||||||
|
aabb.grow(vertex);
|
||||||
|
}
|
||||||
|
return aabb;
|
||||||
|
}
|
||||||
|
pub fn face_normal(&self,face:Face) -> glam::Vec3 {
|
||||||
|
let mut n=glam::Vec3Swizzles::xyzz(Aabb::normal(face));
|
||||||
|
n.w=0.0;//what a man will do to avoid writing out the components
|
||||||
|
glam::Vec4Swizzles::xyz(self.transform*n)//this is wrong for scale
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct RelativeCollision {
|
||||||
|
face: Face,//just an id
|
||||||
|
model: u32,//using id to avoid lifetimes
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RelativeCollision {
|
||||||
|
pub fn mesh(&self,models:&Vec<Model>) -> TreyMesh {
|
||||||
|
return models.get(self.model as usize).unwrap().face_mesh(self.face)
|
||||||
|
}
|
||||||
|
pub fn normal(&self,models:&Vec<Model>) -> glam::Vec3 {
|
||||||
|
return models.get(self.model as usize).unwrap().face_normal(self.face)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type TIME = i64;
|
||||||
|
|
||||||
|
impl Body {
|
||||||
|
pub fn with_position(position:glam::Vec3) -> Self {
|
||||||
|
Self{
|
||||||
|
position: position,
|
||||||
|
velocity: glam::Vec3::ZERO,
|
||||||
|
acceleration: glam::Vec3::ZERO,
|
||||||
|
time: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn extrapolated_position(&self,time: TIME)->glam::Vec3{
|
||||||
|
let dt=(time-self.time) as f64/1_000_000_000f64;
|
||||||
|
self.position+self.velocity*(dt as f32)+self.acceleration*((0.5*dt*dt) as f32)
|
||||||
|
}
|
||||||
|
pub fn advance_time(&mut self, time: TIME){
|
||||||
|
self.position=self.extrapolated_position(time);
|
||||||
|
self.time=time;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PhysicsState {
|
||||||
|
//tickless gaming
|
||||||
|
pub fn run(&mut self, time: TIME){
|
||||||
|
//prepare is ommitted - everything is done via instructions.
|
||||||
|
while let Some(instruction) = self.next_instruction(time) {//collect
|
||||||
|
//advance
|
||||||
|
//self.advance_time(instruction.time);
|
||||||
|
//process
|
||||||
|
self.process_instruction(instruction);
|
||||||
|
//write hash lol
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn advance_time(&mut self, time: TIME){
|
||||||
|
self.body.advance_time(time);
|
||||||
|
self.time=time;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn next_strafe_instruction(&self) -> Option<TimedInstruction<PhysicsInstruction>> {
|
||||||
|
return Some(TimedInstruction{
|
||||||
|
time:(self.time*self.strafe_tick_num/self.strafe_tick_den+1)*self.strafe_tick_den/self.strafe_tick_num,
|
||||||
|
//only poll the physics if there is a before and after mouse event
|
||||||
|
instruction:PhysicsInstruction::StrafeTick
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
//state mutated on collision:
|
||||||
|
//Accelerator
|
||||||
|
//stair step-up
|
||||||
|
|
||||||
|
//state mutated on instruction
|
||||||
|
//change fly acceleration (fly_sustain)
|
||||||
|
//change fly velocity
|
||||||
|
|
||||||
|
//generic event emmiters
|
||||||
|
//PlatformStandTime
|
||||||
|
//walk/swim/air/ladder sounds
|
||||||
|
//VState?
|
||||||
|
|
||||||
|
//falling under the map
|
||||||
|
// fn next_respawn_instruction(&self) -> Option<TimedInstruction<PhysicsInstruction>> {
|
||||||
|
// if self.body.position<self.world.min_y {
|
||||||
|
// return Some(TimedInstruction{
|
||||||
|
// time:self.time,
|
||||||
|
// instruction:PhysicsInstruction::Trigger(None)
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// fn next_water_instruction(&self) -> Option<TimedInstruction<PhysicsInstruction>> {
|
||||||
|
// return Some(TimedInstruction{
|
||||||
|
// time:(self.time*self.strafe_tick_num/self.strafe_tick_den+1)*self.strafe_tick_den/self.strafe_tick_num,
|
||||||
|
// //only poll the physics if there is a before and after mouse event
|
||||||
|
// instruction:PhysicsInstruction::Water
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
|
||||||
|
fn next_walk_instruction(&self) -> Option<TimedInstruction<PhysicsInstruction>> {
|
||||||
|
//check if you are accelerating towards a walk target velocity and create an instruction
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
fn predict_collision_end(&self,model:&Model) -> Option<TimedInstruction<PhysicsInstruction>> {
|
||||||
|
//must treat cancollide false objects differently: you may not exit through the same face you entered.
|
||||||
|
None
|
||||||
|
}
|
||||||
|
fn predict_collision_start(&self,model:&Model) -> Option<TimedInstruction<PhysicsInstruction>> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl crate::instruction::InstructionEmitter<PhysicsInstruction> for PhysicsState {
|
||||||
|
//this little next instruction function can cache its return value and invalidate the cached value by watching the State.
|
||||||
|
fn next_instruction(&self,time_limit:TIME) -> Option<TimedInstruction<PhysicsInstruction>> {
|
||||||
|
//JUST POLLING!!! NO MUTATION
|
||||||
|
let mut collector = crate::instruction::InstructionCollector::new(time_limit);
|
||||||
|
//autohop (already pressing spacebar; the signal to begin trying to jump is different)
|
||||||
|
if self.grounded&&self.jump_trying {
|
||||||
|
//scroll will be implemented with InputInstruction::Jump(true) but it blocks setting self.jump_trying=true
|
||||||
|
collector.collect(Some(TimedInstruction{
|
||||||
|
time:self.time,
|
||||||
|
instruction:PhysicsInstruction::Jump
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
//check for collision stop instructions with curent contacts
|
||||||
|
for collision_data in self.contacts.iter() {
|
||||||
|
collector.collect(self.predict_collision_end(self.models_cringe_clone.get(collision_data.model as usize).unwrap()));
|
||||||
|
}
|
||||||
|
//check for collision start instructions (against every part in the game with no optimization!!)
|
||||||
|
for model in &self.models_cringe_clone {
|
||||||
|
collector.collect(self.predict_collision_start(model));
|
||||||
|
}
|
||||||
|
if self.grounded {
|
||||||
|
//walk maintenance
|
||||||
|
collector.collect(self.next_walk_instruction());
|
||||||
|
}else{
|
||||||
|
//check to see when the next strafe tick is
|
||||||
|
collector.collect(self.next_strafe_instruction());
|
||||||
|
}
|
||||||
|
collector.instruction()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl crate::instruction::InstructionConsumer<PhysicsInstruction> for PhysicsState {
|
||||||
|
fn process_instruction(&mut self, ins:TimedInstruction<PhysicsInstruction>) {
|
||||||
|
//mutate position and velocity and time
|
||||||
|
self.advance_time(ins.time);//should this be in run?
|
||||||
|
match ins.instruction {
|
||||||
|
PhysicsInstruction::CollisionStart(_) => todo!(),
|
||||||
|
PhysicsInstruction::CollisionEnd(_) => todo!(),
|
||||||
|
PhysicsInstruction::StrafeTick => {
|
||||||
|
//let control_dir=self.get_control_dir();//this should respect your mouse interpolation settings
|
||||||
|
let d=self.body.velocity.dot(self.temp_control_dir);
|
||||||
|
if d<self.mv {
|
||||||
|
self.body.velocity+=(self.mv-d)*self.temp_control_dir;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PhysicsInstruction::Jump => {
|
||||||
|
self.grounded=false;//do I need this?
|
||||||
|
self.body.velocity+=glam::Vec3::new(0.0,0.715588/2.0*100.0,0.0);
|
||||||
|
}
|
||||||
|
PhysicsInstruction::ReachWalkTargetVelocity => {
|
||||||
|
//precisely set velocity
|
||||||
|
self.body.velocity=self.walk_target_velocity;
|
||||||
|
}
|
||||||
|
PhysicsInstruction::SetWalkTargetVelocity(v) => {
|
||||||
|
self.walk_target_velocity=v;
|
||||||
|
//calculate acceleration yada yada
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
47
src/instruction.rs
Normal file
47
src/instruction.rs
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
pub struct TimedInstruction<I> {
|
||||||
|
pub time: crate::body::TIME,
|
||||||
|
pub instruction: I,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait InstructionEmitter<I> {
|
||||||
|
fn next_instruction(&self, time:crate::body::TIME) -> Option<TimedInstruction<I>>;
|
||||||
|
}
|
||||||
|
pub trait InstructionConsumer<I> {
|
||||||
|
fn process_instruction(&mut self, instruction:TimedInstruction<I>);
|
||||||
|
}
|
||||||
|
|
||||||
|
//PROPER PRIVATE FIELDS!!!
|
||||||
|
pub struct InstructionCollector<I> {
|
||||||
|
time: crate::body::TIME,
|
||||||
|
instruction: Option<I>,
|
||||||
|
}
|
||||||
|
impl<I> InstructionCollector<I> {
|
||||||
|
pub fn new(time:crate::body::TIME) -> Self {
|
||||||
|
Self{
|
||||||
|
time,
|
||||||
|
instruction:None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn collect(&mut self,instruction:Option<TimedInstruction<I>>){
|
||||||
|
match instruction {
|
||||||
|
Some(unwrap_instruction) => {
|
||||||
|
if unwrap_instruction.time<self.time {
|
||||||
|
self.time=unwrap_instruction.time;
|
||||||
|
self.instruction=Some(unwrap_instruction.instruction);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
None => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn instruction(self) -> Option<TimedInstruction<I>> {
|
||||||
|
//STEAL INSTRUCTION AND DESTROY INSTRUCTIONCOLLECTOR
|
||||||
|
match self.instruction {
|
||||||
|
Some(instruction)=>Some(TimedInstruction{
|
||||||
|
time:self.time,
|
||||||
|
instruction
|
||||||
|
}),
|
||||||
|
None => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1 +1,3 @@
|
|||||||
pub mod framework;
|
pub mod framework;
|
||||||
|
pub mod body;
|
||||||
|
pub mod instruction;
|
||||||
|
144
src/main.rs
144
src/main.rs
@ -24,7 +24,7 @@ struct ModelData {
|
|||||||
entities: Vec<Entity>,
|
entities: Vec<Entity>,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Model {
|
struct ModelGraphics {
|
||||||
transform: glam::Mat4,
|
transform: glam::Mat4,
|
||||||
vertex_buf: wgpu::Buffer,
|
vertex_buf: wgpu::Buffer,
|
||||||
entities: Vec<Entity>,
|
entities: Vec<Entity>,
|
||||||
@ -34,20 +34,12 @@ struct Model {
|
|||||||
|
|
||||||
// Note: we use the Y=up coordinate space in this example.
|
// Note: we use the Y=up coordinate space in this example.
|
||||||
struct Camera {
|
struct Camera {
|
||||||
time: Instant,
|
|
||||||
pos: glam::Vec3,
|
|
||||||
vel: glam::Vec3,
|
|
||||||
gravity: glam::Vec3,
|
|
||||||
friction: f32,
|
|
||||||
screen_size: (u32, u32),
|
screen_size: (u32, u32),
|
||||||
offset: glam::Vec3,
|
offset: glam::Vec3,
|
||||||
fov: f32,
|
fov: f32,
|
||||||
yaw: f32,
|
yaw: f32,
|
||||||
pitch: f32,
|
pitch: f32,
|
||||||
controls: u32,
|
controls: u32,
|
||||||
mv: f32,
|
|
||||||
grounded: bool,
|
|
||||||
walkspeed: f32,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const CONTROL_MOVEFORWARD:u32 = 0b00000001;
|
const CONTROL_MOVEFORWARD:u32 = 0b00000001;
|
||||||
@ -100,7 +92,7 @@ fn get_control_dir(controls: u32) -> glam::Vec3{
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Camera {
|
impl Camera {
|
||||||
fn to_uniform_data(&self) -> [f32; 16 * 3 + 4] {
|
fn to_uniform_data(&self, pos: glam::Vec3) -> [f32; 16 * 3 + 4] {
|
||||||
let aspect = self.screen_size.0 as f32 / self.screen_size.1 as f32;
|
let aspect = self.screen_size.0 as f32 / self.screen_size.1 as f32;
|
||||||
let fov = if self.controls&CONTROL_ZOOM==0 {
|
let fov = if self.controls&CONTROL_ZOOM==0 {
|
||||||
self.fov
|
self.fov
|
||||||
@ -109,7 +101,7 @@ impl Camera {
|
|||||||
};
|
};
|
||||||
let proj = perspective_rh(fov, aspect, 0.5, 1000.0);
|
let proj = perspective_rh(fov, aspect, 0.5, 1000.0);
|
||||||
let proj_inv = proj.inverse();
|
let proj_inv = proj.inverse();
|
||||||
let view = glam::Mat4::from_translation(self.pos+self.offset) * glam::Mat4::from_euler(glam::EulerRot::YXZ, self.yaw, self.pitch, 0f32);
|
let view = glam::Mat4::from_translation(pos+self.offset) * glam::Mat4::from_euler(glam::EulerRot::YXZ, self.yaw, self.pitch, 0f32);
|
||||||
let view_inv = view.inverse();
|
let view_inv = view.inverse();
|
||||||
|
|
||||||
let mut raw = [0f32; 16 * 3 + 4];
|
let mut raw = [0f32; 16 * 3 + 4];
|
||||||
@ -122,13 +114,15 @@ impl Camera {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct Skybox {
|
pub struct Skybox {
|
||||||
|
start_time: std::time::Instant,
|
||||||
camera: Camera,
|
camera: Camera,
|
||||||
|
physics: strafe_client::body::PhysicsState,
|
||||||
sky_pipeline: wgpu::RenderPipeline,
|
sky_pipeline: wgpu::RenderPipeline,
|
||||||
entity_pipeline: wgpu::RenderPipeline,
|
entity_pipeline: wgpu::RenderPipeline,
|
||||||
ground_pipeline: wgpu::RenderPipeline,
|
ground_pipeline: wgpu::RenderPipeline,
|
||||||
main_bind_group: wgpu::BindGroup,
|
main_bind_group: wgpu::BindGroup,
|
||||||
camera_buf: wgpu::Buffer,
|
camera_buf: wgpu::Buffer,
|
||||||
models: Vec<Model>,
|
models: Vec<ModelGraphics>,
|
||||||
depth_view: wgpu::TextureView,
|
depth_view: wgpu::TextureView,
|
||||||
staging_belt: wgpu::util::StagingBelt,
|
staging_belt: wgpu::util::StagingBelt,
|
||||||
}
|
}
|
||||||
@ -290,28 +284,67 @@ impl strafe_client::framework::Example for Skybox {
|
|||||||
});
|
});
|
||||||
|
|
||||||
let camera = Camera {
|
let camera = Camera {
|
||||||
time: Instant::now(),
|
|
||||||
pos: glam::Vec3::new(5.0,0.0,5.0),
|
|
||||||
vel: glam::Vec3::new(0.0,0.0,0.0),
|
|
||||||
gravity: glam::Vec3::new(0.0,-100.0,0.0),
|
|
||||||
friction: 90.0,
|
|
||||||
screen_size: (config.width, config.height),
|
screen_size: (config.width, config.height),
|
||||||
offset: glam::Vec3::new(0.0,4.5,0.0),
|
offset: glam::Vec3::new(0.0,4.5,0.0),
|
||||||
fov: 1.0, //fov_slope = tan(fov_y/2)
|
fov: 1.0, //fov_slope = tan(fov_y/2)
|
||||||
pitch: 0.0,
|
pitch: 0.0,
|
||||||
yaw: 0.0,
|
yaw: 0.0,
|
||||||
mv: 2.7,
|
|
||||||
controls:0,
|
controls:0,
|
||||||
grounded: true,
|
|
||||||
walkspeed: 18.0,
|
|
||||||
};
|
};
|
||||||
let camera_uniforms = camera.to_uniform_data();
|
let physics = strafe_client::body::PhysicsState {
|
||||||
|
body: strafe_client::body::Body::with_position(glam::Vec3::new(5.0,5.0,5.0)),
|
||||||
|
time: 0,
|
||||||
|
tick: 0,
|
||||||
|
strafe_tick_num: 100,//100t
|
||||||
|
strafe_tick_den: 1_000_000_000,
|
||||||
|
gravity: glam::Vec3::new(0.0,-100.0,0.0),
|
||||||
|
friction: 90.0,
|
||||||
|
mv: 2.7,
|
||||||
|
grounded: false,
|
||||||
|
jump_trying: false,
|
||||||
|
temp_control_dir: glam::Vec3::ZERO,
|
||||||
|
walkspeed: 18.0,
|
||||||
|
contacts: Vec::<strafe_client::body::RelativeCollision>::new(),
|
||||||
|
models_cringe_clone: modeldatas.iter().map(|m|strafe_client::body::Model::new(m.transform)).collect(),
|
||||||
|
walk_target_velocity: glam::Vec3::ZERO,
|
||||||
|
};
|
||||||
|
|
||||||
|
let camera_uniforms = camera.to_uniform_data(physics.body.extrapolated_position(0));
|
||||||
let camera_buf = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
let camera_buf = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
||||||
label: Some("Camera"),
|
label: Some("Camera"),
|
||||||
contents: bytemuck::cast_slice(&camera_uniforms),
|
contents: bytemuck::cast_slice(&camera_uniforms),
|
||||||
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
|
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
//drain the modeldata vec so entities can be /moved/ to models.entities
|
||||||
|
let mut models = Vec::<ModelGraphics>::with_capacity(modeldatas.len());
|
||||||
|
for (i,modeldata) in modeldatas.drain(..).enumerate() {
|
||||||
|
let model_uniforms = get_transform_uniform_data(&modeldata.transform);
|
||||||
|
let model_buf = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
||||||
|
label: Some(format!("ModelGraphics{}",i).as_str()),
|
||||||
|
contents: bytemuck::cast_slice(&model_uniforms),
|
||||||
|
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
|
||||||
|
});
|
||||||
|
let model_bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
|
||||||
|
layout: &model_bind_group_layout,
|
||||||
|
entries: &[
|
||||||
|
wgpu::BindGroupEntry {
|
||||||
|
binding: 0,
|
||||||
|
resource: model_buf.as_entire_binding(),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
label: Some(format!("ModelGraphics{}",i).as_str()),
|
||||||
|
});
|
||||||
|
//all of these are being moved here
|
||||||
|
models.push(ModelGraphics{
|
||||||
|
transform: modeldata.transform,
|
||||||
|
vertex_buf:modeldata.vertex_buf,
|
||||||
|
entities: modeldata.entities,
|
||||||
|
bind_group: model_bind_group,
|
||||||
|
model_buf,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||||
label: None,
|
label: None,
|
||||||
bind_group_layouts: &[&main_bind_group_layout, &model_bind_group_layout],
|
bind_group_layouts: &[&main_bind_group_layout, &model_bind_group_layout],
|
||||||
@ -507,39 +540,12 @@ impl strafe_client::framework::Example for Skybox {
|
|||||||
label: Some("Camera"),
|
label: Some("Camera"),
|
||||||
});
|
});
|
||||||
|
|
||||||
//drain the modeldata vec so entities can be /moved/ to models.entities
|
|
||||||
let mut models = Vec::<Model>::with_capacity(modeldatas.len());
|
|
||||||
for (i,modeldata) in modeldatas.drain(..).enumerate() {
|
|
||||||
let model_uniforms = get_transform_uniform_data(&modeldata.transform);
|
|
||||||
let model_buf = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
|
||||||
label: Some(format!("Model{}",i).as_str()),
|
|
||||||
contents: bytemuck::cast_slice(&model_uniforms),
|
|
||||||
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
|
|
||||||
});
|
|
||||||
let model_bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
|
|
||||||
layout: &model_bind_group_layout,
|
|
||||||
entries: &[
|
|
||||||
wgpu::BindGroupEntry {
|
|
||||||
binding: 0,
|
|
||||||
resource: model_buf.as_entire_binding(),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
label: Some(format!("Model{}",i).as_str()),
|
|
||||||
});
|
|
||||||
//all of these are being moved here
|
|
||||||
models.push(Model{
|
|
||||||
transform: modeldata.transform,
|
|
||||||
vertex_buf:modeldata.vertex_buf,
|
|
||||||
entities: modeldata.entities,
|
|
||||||
bind_group: model_bind_group,
|
|
||||||
model_buf,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
let depth_view = Self::create_depth_texture(config, device);
|
let depth_view = Self::create_depth_texture(config, device);
|
||||||
|
|
||||||
Skybox {
|
Skybox {
|
||||||
|
start_time: Instant::now(),
|
||||||
camera,
|
camera,
|
||||||
|
physics,
|
||||||
sky_pipeline,
|
sky_pipeline,
|
||||||
entity_pipeline,
|
entity_pipeline,
|
||||||
ground_pipeline,
|
ground_pipeline,
|
||||||
@ -625,44 +631,20 @@ impl strafe_client::framework::Example for Skybox {
|
|||||||
queue: &wgpu::Queue,
|
queue: &wgpu::Queue,
|
||||||
_spawner: &strafe_client::framework::Spawner,
|
_spawner: &strafe_client::framework::Spawner,
|
||||||
) {
|
) {
|
||||||
let time = Instant::now();
|
|
||||||
|
|
||||||
//physique
|
|
||||||
let dt=(time-self.camera.time).as_secs_f32();
|
|
||||||
self.camera.time=time;
|
|
||||||
let camera_mat=glam::Mat3::from_euler(glam::EulerRot::YXZ,self.camera.yaw,0f32,0f32);
|
let camera_mat=glam::Mat3::from_euler(glam::EulerRot::YXZ,self.camera.yaw,0f32,0f32);
|
||||||
let control_dir=camera_mat*get_control_dir(self.camera.controls&(CONTROL_MOVELEFT|CONTROL_MOVERIGHT|CONTROL_MOVEFORWARD|CONTROL_MOVEBACK)).normalize_or_zero();
|
let control_dir=camera_mat*get_control_dir(self.camera.controls&(CONTROL_MOVELEFT|CONTROL_MOVERIGHT|CONTROL_MOVEFORWARD|CONTROL_MOVEBACK)).normalize_or_zero();
|
||||||
let d=self.camera.vel.dot(control_dir);
|
|
||||||
if d<self.camera.mv {
|
let time=self.start_time.elapsed().as_nanos() as i64;
|
||||||
self.camera.vel+=(self.camera.mv-d)*control_dir;
|
|
||||||
}
|
self.physics.temp_control_dir=control_dir;
|
||||||
self.camera.vel+=self.camera.gravity*dt;
|
self.physics.jump_trying=self.camera.controls&CONTROL_JUMP!=0;
|
||||||
self.camera.pos+=self.camera.vel*dt;
|
self.physics.run(time);
|
||||||
if self.camera.pos.y<0.0{
|
|
||||||
self.camera.pos.y=0.0;
|
|
||||||
self.camera.vel.y=0.0;
|
|
||||||
self.camera.grounded=true;
|
|
||||||
}
|
|
||||||
if self.camera.grounded&&(self.camera.controls&CONTROL_JUMP)!=0 {
|
|
||||||
self.camera.grounded=false;
|
|
||||||
self.camera.vel+=glam::Vec3::new(0.0,0.715588/2.0*100.0,0.0);
|
|
||||||
}
|
|
||||||
if self.camera.grounded {
|
|
||||||
let applied_friction=self.camera.friction*dt;
|
|
||||||
let targetv=control_dir*self.camera.walkspeed;
|
|
||||||
let diffv=targetv-self.camera.vel;
|
|
||||||
if applied_friction*applied_friction<diffv.length_squared() {
|
|
||||||
self.camera.vel+=applied_friction*diffv.normalize();
|
|
||||||
} else {
|
|
||||||
self.camera.vel=targetv;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut encoder =
|
let mut encoder =
|
||||||
device.create_command_encoder(&wgpu::CommandEncoderDescriptor { label: None });
|
device.create_command_encoder(&wgpu::CommandEncoderDescriptor { label: None });
|
||||||
|
|
||||||
// update rotation
|
// update rotation
|
||||||
let camera_uniforms = self.camera.to_uniform_data();
|
let camera_uniforms = self.camera.to_uniform_data(self.physics.body.extrapolated_position(time));
|
||||||
self.staging_belt
|
self.staging_belt
|
||||||
.write_buffer(
|
.write_buffer(
|
||||||
&mut encoder,
|
&mut encoder,
|
||||||
|
8
src/sweep.rs
Normal file
8
src/sweep.rs
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
|
||||||
|
//something that implements body + hitbox + transform can predict collision
|
||||||
|
impl crate::sweep::PredictCollision for Model {
|
||||||
|
fn predict_collision(&self,other:&Model) -> Option<crate::event::EventStruct> {
|
||||||
|
//math!
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user