Compare commits

...

77 Commits

Author SHA1 Message Date
1d9d4efedb do not step physics on mouse input, only update pos (overwriting previous pos) 2023-09-20 22:31:26 -07:00
bd04f680d8 fix angles 2023-09-20 22:31:26 -07:00
46cc082c07 accumulate deltas 2023-09-20 22:31:26 -07:00
55fcdb8e27 implement jump() + remove jump_trying + prevent air jumping 2023-09-20 22:31:26 -07:00
d7df468388 wip 2 2023-09-20 22:31:26 -07:00
990199b4c7 wip 2023-09-20 22:31:26 -07:00
1de3501e89 no default transform 2023-09-20 22:29:46 -07:00
0135b17917 make proper model data and stop passing device into add_obj 2023-09-20 22:29:33 -07:00
1878528a4f v0.4.0 instanced rendering + model textures 2023-09-20 17:45:39 -07:00
25e80a7c17 scope skybox 2023-09-20 17:13:08 -07:00
21835d13f6 load squid texture 2023-09-20 17:13:08 -07:00
91f6a5261f move camera_uniforms and skybox_texture 2023-09-20 17:13:08 -07:00
fb4a5efa14 split main bind group, rename everything, organize GraphicsData 2023-09-20 17:13:08 -07:00
acb658f3e9 goal: repeating ground texture 2023-09-20 14:07:11 -07:00
7e427b3879 instanced rendering 2023-09-20 13:48:07 -07:00
d16485ae6d replace visual ground with custom ground model! 2023-09-20 13:37:46 -07:00
cdf695ee6e label bind group 2023-09-20 13:02:47 -07:00
5fc4044284 small physics opti 2023-09-19 18:14:24 -07:00
6f4fda8cc0 clip walk target velocity in RefreshWalkTarget 2023-09-19 17:54:43 -07:00
d58f915082 v0.3.0 physics + walking 2023-09-19 01:21:00 -07:00
8e95fe484a unnecessary cast 2023-09-19 00:58:35 -07:00
5854128164 edit comments 2023-09-19 00:00:14 -07:00
db5b3328bd update time for extern instructions 2023-09-19 00:00:06 -07:00
4951d1513d stop skipping over time 2023-09-18 23:57:42 -07:00
17e71d884f SetControlDir + contact constrain + walk.state enum instead of hash 2023-09-18 23:36:14 -07:00
1dc98d9c2d stupid mistake 2023-09-18 23:33:52 -07:00
fd38502e07 only walk if grounded 2023-09-18 21:28:09 -07:00
0632e322cf implement walk with hashing lole!! 2023-09-18 21:10:07 -07:00
7544c6e6ef fix roblox camera offset 2023-09-18 19:47:15 -07:00
2f0a073fd5 fix aabb normals + face_mesh 2023-09-18 19:04:32 -07:00
21dc425fc2 edit comments 2023-09-18 19:04:32 -07:00
ca141c800c debug print instructions 2023-09-18 19:04:32 -07:00
63ce06f069 syntactic sugar 2023-09-18 18:31:15 -07:00
fe14d5e0fa worthless opti 2023-09-18 18:31:04 -07:00
bffc254a0d put -t back 2023-09-18 18:27:02 -07:00
a5f203484b comment on CollisionEnd handling 2023-09-18 18:08:03 -07:00
e67479a9bd TEMP: move jump out 2023-09-18 18:08:03 -07:00
ad7abbdf1c rework predict_collision_end 2023-09-18 18:08:03 -07:00
3a0b3900ec fix falling 2023-09-18 16:04:55 -07:00
765ed42b9d start in air 2023-09-18 16:04:55 -07:00
8137a26f81 standardize vec init 2023-09-18 16:04:55 -07:00
21ae7a0e4f use pva for init 2023-09-18 16:04:55 -07:00
5a886b76d1 comment about processed_time 2023-09-18 16:04:55 -07:00
f1e26cb07a don't print frame delta 2023-09-18 16:04:55 -07:00
14a74c6e1e consume vec 2023-09-18 16:04:55 -07:00
5b55873bd5 halfsize 2023-09-18 16:04:55 -07:00
fd5d71e1af use hashset for contacts 2023-09-18 16:04:55 -07:00
28c3f21736 implement aabb collision 2023-09-18 16:04:55 -07:00
a58464efb0 how will I do this 2023-09-18 15:49:09 -07:00
b070b9706f InputState 2023-09-18 15:49:09 -07:00
dcfbee8de1 MouseInterpolationState 2023-09-18 15:49:09 -07:00
c5636f7fcd delete unused 2023-09-18 15:26:21 -07:00
a5aa89064b next_instruction non-optional time_limit 2023-09-18 15:26:21 -07:00
0fe14749d3 wip: tickless physics 2023-09-18 15:26:21 -07:00
8daf432991 zeroes 2023-09-18 15:26:21 -07:00
4f5c9afed3 comments on implementing game mechanics 2023-09-08 20:18:31 -07:00
53605746d4 rename best to collector 2023-09-08 20:18:31 -07:00
cead05b08b rename event.rs to instruction.rs 2023-09-08 20:18:31 -07:00
949897a558 rename EventStruct to TimedInstruction 2023-09-08 20:18:31 -07:00
a4ed50fc38 EventConsumer 2023-09-08 20:15:36 -07:00
846f681648 generic events 2023-09-08 20:15:36 -07:00
ff54a03487 happy compiler happy programmer 2023-09-08 20:15:36 -07:00
8c2dda5205 bad data normalization 2023-09-08 16:06:17 -07:00
addde65caa fix up next_event lsp errors 2023-09-08 16:06:17 -07:00
2c4e6f642b boilerplate 2023-09-08 16:06:17 -07:00
f11742ef3b RelativeCollision concept 2023-09-08 16:06:17 -07:00
e6862b5bad rename Model to ModelGRaphics + move model graphics gen code 2023-09-08 16:06:17 -07:00
e18e8a9a7d walk event 2023-09-08 16:06:17 -07:00
f600092f13 LETS GET RUSTY 2023-09-08 16:06:17 -07:00
1f1ef5d3ad there is no model 2023-09-08 12:28:16 -07:00
54bf0358d6 can't stand the idea of 10 nanoseconds less than 66 ticks per second 2023-09-08 12:27:45 -07:00
6caa273623 jump implementation details 2023-09-08 12:04:30 -07:00
101f0f8d12 localize EventStruct 2023-09-08 12:03:32 -07:00
fc751a9fe8 stage sweep 2023-09-08 11:38:47 -07:00
5391b635fb reorder elements 2023-09-08 11:38:47 -07:00
230469496e brainstorm tickless events 2023-09-08 11:38:47 -07:00
ea3134de51 move physics into its own module 2023-09-08 11:35:40 -07:00
11 changed files with 1604 additions and 525 deletions

2
Cargo.lock generated

@ -1405,7 +1405,7 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
[[package]]
name = "strafe-client"
version = "0.2.0"
version = "0.4.0"
dependencies = [
"async-executor",
"bytemuck",

@ -1,6 +1,6 @@
[package]
name = "strafe-client"
version = "0.2.0"
version = "0.4.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

BIN
images/squid.dds Normal file

Binary file not shown.

1021
src/body.rs Normal file

File diff suppressed because it is too large Load Diff

@ -1,12 +1,10 @@
use std::future::Future;
#[cfg(target_arch = "wasm32")]
use std::str::FromStr;
#[cfg(not(target_arch = "wasm32"))]
use std::time::Instant;
#[cfg(target_arch = "wasm32")]
use web_sys::{ImageBitmapRenderingContext, OffscreenCanvas};
use winit::{
event::{self, WindowEvent},
event::{self, WindowEvent, DeviceEvent},
event_loop::{ControlFlow, EventLoop},
};
@ -54,7 +52,7 @@ pub trait Example: 'static + Sized {
queue: &wgpu::Queue,
);
fn update(&mut self, event: WindowEvent);
fn move_mouse(&mut self, delta: (f64,f64));
fn device_event(&mut self, event: DeviceEvent);
fn render(
&mut self,
view: &wgpu::TextureView,
@ -279,11 +277,6 @@ fn start<E: Example>(
log::info!("Initializing the example...");
let mut example = E::init(&config, &adapter, &device, &queue);
#[cfg(not(target_arch = "wasm32"))]
let mut last_frame_inst = Instant::now();
#[cfg(not(target_arch = "wasm32"))]
let (mut frame_count, mut accum_time) = (0, 0.0);
log::info!("Entering render loop...");
event_loop.run(move |event, _, control_flow| {
let _ = (&instance, &adapter); // force ownership by the closure
@ -355,29 +348,12 @@ fn start<E: Example>(
}
},
event::Event::DeviceEvent {
event:
winit::event::DeviceEvent::MouseMotion {
delta,
},
event,
..
} => {
example.move_mouse(delta);
example.device_event(event);
},
event::Event::RedrawRequested(_) => {
#[cfg(not(target_arch = "wasm32"))]
{
accum_time += last_frame_inst.elapsed().as_secs_f32();
last_frame_inst = Instant::now();
frame_count += 1;
if frame_count == 100 {
println!(
"Avg frame time {}ms",
accum_time * 1000.0 / frame_count as f32
);
accum_time = 0.0;
frame_count = 0;
}
}
let frame = match surface.get_current_texture() {
Ok(frame) => frame,

48
src/instruction.rs Normal file

@ -0,0 +1,48 @@
#[derive(Debug)]
pub struct TimedInstruction<I> {
pub time: crate::body::TIME,
pub instruction: I,
}
pub trait InstructionEmitter<I> {
fn next_instruction(&self, time_limit: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,4 @@
pub mod framework;
pub mod body;
pub mod zeroes;
pub mod instruction;

File diff suppressed because it is too large Load Diff

@ -1,9 +1,4 @@
struct SkyOutput {
@builtin(position) position: vec4<f32>,
@location(0) sampledir: vec3<f32>,
};
struct Data {
struct Camera {
// from camera to screen
proj: mat4x4<f32>,
// from screen to camera
@ -13,9 +8,16 @@ struct Data {
// camera position
cam_pos: vec4<f32>,
};
//group 0 is the camera
@group(0)
@binding(0)
var<uniform> r_data: Data;
var<uniform> camera: Camera;
struct SkyOutput {
@builtin(position) position: vec4<f32>,
@location(0) sampledir: vec3<f32>,
};
@vertex
fn vs_sky(@builtin(vertex_index) vertex_index: u32) -> SkyOutput {
@ -30,8 +32,8 @@ fn vs_sky(@builtin(vertex_index) vertex_index: u32) -> SkyOutput {
);
// transposition = inversion for this orthonormal matrix
let inv_model_view = transpose(mat3x3<f32>(r_data.view[0].xyz, r_data.view[1].xyz, r_data.view[2].xyz));
let unprojected = r_data.proj_inv * pos;
let inv_model_view = transpose(mat3x3<f32>(camera.view[0].xyz, camera.view[1].xyz, camera.view[2].xyz));
let unprojected = camera.proj_inv * pos;
var result: SkyOutput;
result.sampledir = inv_model_view * unprojected.xyz;
@ -39,93 +41,65 @@ fn vs_sky(@builtin(vertex_index) vertex_index: u32) -> SkyOutput {
return result;
}
struct GroundOutput {
@builtin(position) position: vec4<f32>,
@location(4) pos: vec3<f32>,
};
const MAX_ENTITY_INSTANCES=1024;
//group 1 is the model
@group(1)
@binding(0)
var<uniform> entity_transforms: array<mat4x4<f32>,MAX_ENTITY_INSTANCES>;
//var<uniform> entity_texture_transforms: array<mat3x3<f32>,MAX_ENTITY_INSTANCES>;
//my fancy idea is to create a megatexture for each model that includes all the textures each intance will need
//the texture transform then maps the texture coordinates to the location of the specific texture
//how to do no texture?
@group(1)
@binding(1)
var model_texture: texture_2d<f32>;
@group(1)
@binding(2)
var model_sampler: sampler;
@vertex
fn vs_ground(@builtin(vertex_index) vertex_index: u32) -> GroundOutput {
// hacky way to draw two triangles that make a square
let tmp1 = i32(vertex_index)/2-i32(vertex_index)/3;
let tmp2 = i32(vertex_index)&1;
let pos = vec3<f32>(
f32(tmp1) * 2.0 - 1.0,
0.0,
f32(tmp2) * 2.0 - 1.0
) * 160.0;
var result: GroundOutput;
result.pos = pos;
result.position = r_data.proj * r_data.view * vec4<f32>(pos, 1.0);
return result;
}
struct EntityOutput {
struct EntityOutputTexture {
@builtin(position) position: vec4<f32>,
@location(1) texture: vec2<f32>,
@location(2) normal: vec3<f32>,
@location(3) view: vec3<f32>,
};
@group(1)
@binding(0)
var<uniform> r_EntityTransform: mat4x4<f32>;
@vertex
fn vs_entity(
fn vs_entity_texture(
@builtin(instance_index) instance: u32,
@location(0) pos: vec3<f32>,
@location(1) texture: vec2<f32>,
@location(2) normal: vec3<f32>,
) -> EntityOutput {
var position: vec4<f32> = r_EntityTransform * vec4<f32>(pos, 1.0);
var result: EntityOutput;
result.normal = (r_EntityTransform * vec4<f32>(normal, 0.0)).xyz;
result.texture=texture;
result.view = position.xyz - r_data.cam_pos.xyz;
result.position = r_data.proj * r_data.view * position;
) -> EntityOutputTexture {
var position: vec4<f32> = entity_transforms[instance] * vec4<f32>(pos, 1.0);
var result: EntityOutputTexture;
result.normal = (entity_transforms[instance] * vec4<f32>(normal, 0.0)).xyz;
result.texture=texture;//(entity_texture_transforms[instance] * vec3<f32>(texture, 1.0)).xy;
result.view = position.xyz - camera.cam_pos.xyz;
result.position = camera.proj * camera.view * position;
return result;
}
@group(0)
//group 2 is the skybox texture
@group(2)
@binding(0)
var cube_texture: texture_cube<f32>;
@group(2)
@binding(1)
var r_texture: texture_cube<f32>;
@group(0)
@binding(2)
var r_sampler: sampler;
var cube_sampler: sampler;
@fragment
fn fs_sky(vertex: SkyOutput) -> @location(0) vec4<f32> {
return textureSample(r_texture, r_sampler, vertex.sampledir);
return textureSample(cube_texture, model_sampler, vertex.sampledir);
}
@fragment
fn fs_entity(vertex: EntityOutput) -> @location(0) vec4<f32> {
fn fs_entity_texture(vertex: EntityOutputTexture) -> @location(0) vec4<f32> {
let incident = normalize(vertex.view);
let normal = normalize(vertex.normal);
let d = dot(normal, incident);
let reflected = incident - 2.0 * d * normal;
let dir = vec3<f32>(-1.0)+2.0*vec3<f32>(vertex.texture.x,0.0,vertex.texture.y);
let texture_color = textureSample(r_texture, r_sampler, dir).rgb;
let reflected_color = textureSample(r_texture, r_sampler, reflected).rgb;
return vec4<f32>(mix(vec3<f32>(0.1) + 0.5 * reflected_color,texture_color,1.0-pow(1.0-abs(d),2.0)), 1.0);
}
fn modulo_euclidean (a: f32, b: f32) -> f32 {
var m = a % b;
if (m < 0.0) {
if (b < 0.0) {
m -= b;
} else {
m += b;
}
}
return m;
}
@fragment
fn fs_ground(vertex: GroundOutput) -> @location(0) vec4<f32> {
let dir = vec3<f32>(-1.0)+vec3<f32>(modulo_euclidean(vertex.pos.x/16.,1.0),0.0,modulo_euclidean(vertex.pos.z/16.,1.0))*2.0;
return vec4<f32>(textureSample(r_texture, r_sampler, dir).rgb, 1.0);
let fragment_color = textureSample(model_texture, model_sampler, vertex.texture).rgb;
let reflected_color = textureSample(cube_texture, cube_sampler, reflected).rgb;
return vec4<f32>(mix(vec3<f32>(0.1) + 0.5 * reflected_color,fragment_color,1.0-pow(1.0-abs(d),2.0)), 1.0);
}

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
}
}

27
src/zeroes.rs Normal file

@ -0,0 +1,27 @@
//find roots of polynomials
pub fn zeroes2(a0:f32,a1:f32,a2:f32) -> Vec<f32>{
if a2==0f32{
return zeroes1(a0, a1);
}
let mut radicand=a1*a1-4f32*a2*a0;
if 0f32<radicand {
radicand=radicand.sqrt();
if 0f32<a2 {
return vec![(-a1-radicand)/(2f32*a2),(-a1+radicand)/(2f32*a2)];
} else {
return vec![(-a1+radicand)/(2f32*a2),(-a1-radicand)/(2f32*a2)];
}
} else if radicand==0f32 {
return vec![-a1/(2f32*a2)];
} else {
return vec![];
}
}
#[inline]
pub fn zeroes1(a0:f32,a1:f32) -> Vec<f32> {
if a1==0f32{
return vec![];
} else {
return vec![-a0/a1];
}
}