Compare commits

...

41 Commits

Author SHA1 Message Date
a139b5a409 update deps (aggressive) 2024-07-22 12:58:36 -07:00
1b71bda9c7 wgpu 22.0.0 2024-07-22 12:33:39 -07:00
5f1b162775 use strafesnet registry 2024-03-30 13:39:06 -07:00
ed27ee060b pretty polygon fanning from vbsp code 2024-03-18 21:08:39 -07:00
5c107c1e5f print texture load error 2024-03-18 20:50:39 -07:00
3834194156 update deps 2024-03-13 13:57:21 -07:00
d0432188b5 include meshes symbolic link 2024-03-13 11:48:34 -07:00
9ff946c325 implement roblox mesh loading 2024-03-13 11:48:34 -07:00
63b2b1676c update deps 2024-03-13 11:48:34 -07:00
b7fc7d2a12 update deps 2024-03-02 13:19:01 -08:00
f273bbf4a9 update strafesnet deps 2024-03-02 13:18:56 -08:00
cc19917025 note 2024-02-22 02:17:20 -08:00
cc58f23512 the bug 2024-02-22 01:30:17 -08:00
b6e7ce4e25 fixup double references 2024-02-22 01:29:29 -08:00
b0d8f2e09a not-working 2024-02-22 00:57:09 -08:00
9b4b09798b notes about fixes 2024-02-21 22:58:40 -08:00
5a55aefb4f unused argument 2024-02-21 22:28:33 -08:00
8f606b7cfc ad-hoc fixups 2024-02-21 22:07:40 -08:00
fad7ed393b implicitly apply_to_body in apply_enum 2024-02-21 22:07:21 -08:00
d2a864e2c1 rename MoveState::changed to apply_enum 2024-02-21 22:07:05 -08:00
f027594ab4 before and after not needed currently 2024-02-21 05:24:12 -08:00
0026b92a72 hide hints 2024-02-21 05:20:40 -08:00
4dc706b783 notes 2024-02-21 05:20:40 -08:00
9bf3f55191 it works?? 2024-02-21 05:17:13 -08:00
eb34cce746 flyin 2024-02-21 04:12:08 -08:00
623a2d2a4f be pedantic about public private 2024-02-21 04:11:31 -08:00
aadcca91ea Debug 2024-02-21 03:23:50 -08:00
04c70ba0bc more private 2024-02-21 02:52:20 -08:00
865c086f14 actually implement this function 2024-02-21 02:48:49 -08:00
619049c11f unneeded 2024-02-21 02:48:41 -08:00
2acefe9a1a want water here 2024-02-21 02:41:19 -08:00
2496d71afa compiler 2024-02-21 02:32:00 -08:00
8ffbca204b wishful thinking 2024-02-21 02:31:50 -08:00
05e2f67e36 don't write duplicate code 2024-02-21 02:17:13 -08:00
b955407b06 delete get_move_state function 2024-02-21 01:32:29 -08:00
fb47b09925 wip 2024-02-21 01:32:03 -08:00
dbd08729d7 wip 2024-02-21 00:31:44 -08:00
c895a66ad6 wip 2024-02-20 22:27:31 -08:00
efdb4c97be edit jumped_velocity garbage 2024-02-18 01:52:29 -08:00
9396623f0c wip - notably remove camera interpolation for walking and rocket 2024-02-18 01:52:29 -08:00
c55156bb92 wip 2024-02-18 01:52:29 -08:00
12 changed files with 1200 additions and 867 deletions

2
.cargo/config.toml Normal file
View File

@ -0,0 +1,2 @@
[registries.strafesnet]
index = "sparse+https://git.itzana.me/api/packages/strafesnet/cargo/"

1060
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -2,6 +2,10 @@
name = "strafe-client"
version = "0.9.5"
edition = "2021"
repository = "https://git.itzana.me/StrafesNET/strafe-client"
license = "Custom"
description = "StrafesNET game client for bhop and surf."
authors = ["Rhys Lloyd <krakow20@gmail.com>"]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@ -10,15 +14,15 @@ bytemuck = { version = "1.13.1", features = ["derive"] }
configparser = "3.0.2"
ddsfile = "0.5.1"
glam = "0.25.0"
id = { git = "https://git.itzana.me/Quaternions/id", rev = "1f710976cc786c8853dab73d6e1cee53158deeb0" }
id = { version = "0.1.0", registry = "strafesnet" }
parking_lot = "0.12.1"
pollster = "0.3.0"
strafesnet_common = { git = "https://git.itzana.me/StrafesNET/common", rev = "093a54c527134ef7020a22a0f5778df8cba60228" }
strafesnet_bsp_loader = { git = "https://git.itzana.me/StrafesNET/bsp_loader", rev = "53ad6c171c3ed1bf7ee3411055ceb38d86f841cd" }
strafesnet_rbx_loader = { git = "https://git.itzana.me/StrafesNET/rbx_loader", rev = "e0739fa792ad506e210f076b90697194005bb7de" }
strafesnet_deferred_loader = { git = "https://git.itzana.me/StrafesNET/deferred_loader", rev = "2273f881b2ebcd404e400f0a3aded0661bb29389", features = ["legacy"] }
wgpu = "0.19.0"
winit = "0.29.2"
strafesnet_bsp_loader = { version = "0.1.1", registry = "strafesnet" }
strafesnet_common = { version = "0.1.2", registry = "strafesnet" }
strafesnet_deferred_loader = { version = "0.3.0", features = ["legacy"], registry = "strafesnet" }
strafesnet_rbx_loader = { version = "0.3.0", registry = "strafesnet" }
wgpu = "22.0.0"
winit = "0.30.4"
#[profile.release]
#lto = true

View File

@ -49,14 +49,25 @@ pub fn load<P:AsRef<std::path::Path>>(path:P)->Result<strafesnet_common::map::Co
DataStructure::Roblox(dom)=>{
let mut loader=strafesnet_deferred_loader::roblox_legacy();
let (texture_loader,mesh_loader)=loader.get_inner_mut();
let map_step1=strafesnet_rbx_loader::convert(
&dom,
|name|loader.acquire_render_config_id(name)
|name|texture_loader.acquire_render_config_id(name),
|name|mesh_loader.acquire_mesh_id(name),
);
let meshpart_meshes=mesh_loader.load_meshes().map_err(LoadError::Io)?;
let map_step2=map_step1.add_meshpart_meshes_and_calculate_attributes(
meshpart_meshes.into_iter().map(|(mesh_id,loader_model)|
(mesh_id,strafesnet_rbx_loader::data::RobloxMeshBytes::new(loader_model.get()))
)
);
let (textures,render_configs)=loader.into_render_configs().map_err(LoadError::Io)?.consume();
let map=map_step1.add_render_configs_and_textures(
let map=map_step2.add_render_configs_and_textures(
render_configs.into_iter(),
textures.into_iter().map(|(texture_id,texture)|
(texture_id,match texture{
@ -74,9 +85,7 @@ pub fn load<P:AsRef<std::path::Path>>(path:P)->Result<strafesnet_common::map::Co
let map_step1=strafesnet_bsp_loader::convert(
&bsp,
//acquire_render_config_id
|name|texture_loader.acquire_render_config_id(name),
//acquire_mesh_id
|name|mesh_loader.acquire_mesh_id(name),
);

View File

@ -151,7 +151,13 @@ impl GraphicsState{
//generate texture view per texture
let texture_views:HashMap<strafesnet_common::model::TextureId,wgpu::TextureView>=map.textures.iter().enumerate().filter_map(|(texture_id,texture_data)|{
let texture_id=model::TextureId::new(texture_id as u32);
let image=ddsfile::Dds::read(std::io::Cursor::new(texture_data)).ok()?;
let image=match ddsfile::Dds::read(std::io::Cursor::new(texture_data)){
Ok(image)=>image,
Err(e)=>{
println!("Error loading texture: {e}");
return None;
},
};
let (mut width,mut height)=(image.get_width(),image.get_height());
@ -413,10 +419,8 @@ impl GraphicsState{
//this mut be combined in a more complex way if the models use different render patterns per group
let mut indices=Vec::new();
for poly in model.polys.polys(){
for end_index in 2..poly.len(){
for index in [0,end_index-1,end_index]{
let vertex_index=poly[index];
indices.push(*index_from_vertex.entry(vertex_index).or_insert_with(||{
let mut poly_vertices=poly.iter()
.map(|&vertex_index|*index_from_vertex.entry(vertex_index).or_insert_with(||{
let i=vertices.len();
let vertex=&model.unique_vertices[vertex_index.get() as usize];
vertices.push(GraphicsVertex{
@ -427,8 +431,14 @@ impl GraphicsState{
});
i
}));
}
}
let a=poly_vertices.next().unwrap();
let mut b=poly_vertices.next().unwrap();
poly_vertices.for_each(|c|{
indices.extend([a,b,c]);
b=c;
});
}
GraphicsMeshOwnedRenderConfig{
instances:model.instances,
@ -453,7 +463,9 @@ impl GraphicsState{
instance_count+=model.instances.len();
for instances_chunk in model.instances.rchunks(chunk_size){
model_count+=1;
let model_uniforms=get_instances_buffer_data(instances_chunk);
let mut model_uniforms=get_instances_buffer_data(instances_chunk);
//TEMP: fill with zeroes to pass validation
model_uniforms.resize(MODEL_BUFFER_SIZE*512,0.0f32);
let model_buf=device.create_buffer_init(&wgpu::util::BufferInitDescriptor{
label:Some(format!("Model{} Buf",model_count).as_str()),
contents:bytemuck::cast_slice(&model_uniforms),
@ -744,11 +756,13 @@ impl GraphicsState{
module:&shader,
entry_point:"vs_sky",
buffers:&[],
compilation_options:wgpu::PipelineCompilationOptions::default(),
},
fragment:Some(wgpu::FragmentState{
module:&shader,
entry_point:"fs_sky",
targets:&[Some(config.view_formats[0].into())],
compilation_options:wgpu::PipelineCompilationOptions::default(),
}),
primitive:wgpu::PrimitiveState{
front_face:wgpu::FrontFace::Cw,
@ -763,6 +777,7 @@ impl GraphicsState{
}),
multisample:wgpu::MultisampleState::default(),
multiview:None,
cache:None,
});
let model_pipeline=device.create_render_pipeline(&wgpu::RenderPipelineDescriptor{
label:Some("Model Pipeline"),
@ -775,11 +790,13 @@ impl GraphicsState{
step_mode:wgpu::VertexStepMode::Vertex,
attributes:&wgpu::vertex_attr_array![0=>Float32x3,1=>Float32x2,2=>Float32x3,3=>Float32x4],
}],
compilation_options:wgpu::PipelineCompilationOptions::default(),
},
fragment:Some(wgpu::FragmentState{
module:&shader,
entry_point:"fs_entity_texture",
targets:&[Some(config.view_formats[0].into())],
compilation_options:wgpu::PipelineCompilationOptions::default(),
}),
primitive:wgpu::PrimitiveState{
front_face:wgpu::FrontFace::Cw,
@ -795,10 +812,11 @@ impl GraphicsState{
}),
multisample:wgpu::MultisampleState::default(),
multiview:None,
cache:None,
});
let camera=GraphicsCamera::default();
let camera_uniforms=camera.to_uniform_data(crate::physics::PhysicsOutputState::default().extrapolate(glam::IVec2::ZERO,integer::Time::ZERO));
let camera_uniforms=camera.to_uniform_data(crate::physics::PhysicsOutputState::default().extrapolate(crate::physics::MouseState::default()));
let camera_buf=device.create_buffer_init(&wgpu::util::BufferInitDescriptor{
label:Some("Camera"),
contents:bytemuck::cast_slice(&camera_uniforms),
@ -875,7 +893,7 @@ impl GraphicsState{
let mut encoder=device.create_command_encoder(&wgpu::CommandEncoderDescriptor{label:None});
// update rotation
let camera_uniforms=self.camera.to_uniform_data(physics_output.extrapolate(mouse_pos,predicted_time));
let camera_uniforms=self.camera.to_uniform_data(physics_output.extrapolate(crate::physics::MouseState{pos:mouse_pos,time:predicted_time}));
self.staging_belt
.write_buffer(
&mut encoder,

View File

@ -284,6 +284,7 @@ impl EdgePool{
#[derive(Debug)]
pub enum PhysicsMeshError{
ZeroVertices,
NoPhysicsGroups,
}
impl std::fmt::Display for PhysicsMeshError{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
@ -404,7 +405,7 @@ impl TryFrom<&model::Mesh> for PhysicsMesh{
faces,
verts,
},
complete_mesh:mesh_topologies.pop().unwrap(),
complete_mesh:mesh_topologies.pop().ok_or(PhysicsMeshError::NoPhysicsGroups)?,
submeshes:mesh_topologies,
})
}

File diff suppressed because it is too large Load Diff

View File

@ -13,6 +13,7 @@ pub enum InputInstruction{
Jump(bool),
Zoom(bool),
Reset,
PracticeFly,
}
pub enum Instruction{
Input(InputInstruction),
@ -25,7 +26,7 @@ pub enum Instruction{
pub fn new(mut physics:crate::physics::PhysicsContext,mut graphics_worker:crate::compat_worker::INWorker<crate::graphics_worker::Instruction>)->crate::compat_worker::QNWorker<TimedInstruction<Instruction>>{
let mut mouse_blocking=true;
let mut last_mouse_time=physics.state.next_mouse.time;
let mut last_mouse_time=physics.get_next_mouse().time;
let mut timeline=std::collections::VecDeque::new();
crate::compat_worker::QNWorker::new(move |ins:TimedInstruction<Instruction>|{
if if let Some(phys_input)=match &ins.instruction{
@ -43,7 +44,7 @@ pub enum Instruction{
timeline.push_front(TimedInstruction{
time:last_mouse_time,
instruction:PhysicsInputInstruction::ReplaceMouse(
MouseState{time:last_mouse_time,pos:physics.state.next_mouse.pos},
MouseState{time:last_mouse_time,pos:physics.get_next_mouse().pos},
MouseState{time:ins.time,pos:m}
),
});
@ -62,6 +63,7 @@ pub enum Instruction{
&InputInstruction::Jump(s)=>Some(PhysicsInputInstruction::SetJump(s)),
&InputInstruction::Zoom(s)=>Some(PhysicsInputInstruction::SetZoom(s)),
InputInstruction::Reset=>Some(PhysicsInputInstruction::Reset),
InputInstruction::PracticeFly=>Some(PhysicsInputInstruction::PracticeFly),
},
Instruction::GenerateModels(_)=>Some(PhysicsInputInstruction::Idle),
Instruction::ClearModels=>Some(PhysicsInputInstruction::Idle),
@ -79,11 +81,11 @@ pub enum Instruction{
//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)<ins.time-physics.state.next_mouse.time{
if Time::from_millis(10)<ins.time-physics.get_next_mouse().time{
//push an event to extrapolate no movement from
timeline.push_front(TimedInstruction{
time:last_mouse_time,
instruction:PhysicsInputInstruction::SetNextMouse(MouseState{time:ins.time,pos:physics.state.next_mouse.pos}),
instruction:PhysicsInputInstruction::SetNextMouse(MouseState{time:ins.time,pos:physics.get_next_mouse().pos}),
});
last_mouse_time=ins.time;
//stop blocking. the mouse is not moving so the physics does not need to live in the past and wait for interpolation targets.
@ -104,16 +106,12 @@ pub enum Instruction{
}{
//empty queue
while let Some(instruction)=timeline.pop_front(){
physics.run(instruction.time);
physics.process_instruction(TimedInstruction{
time:instruction.time,
instruction:crate::physics::PhysicsInstruction::Input(instruction.instruction),
});
physics.run_input_instruction(instruction);
}
}
match ins.instruction{
Instruction::Render=>{
graphics_worker.send(crate::graphics_worker::Instruction::Render(physics.state.output(),ins.time,physics.state.next_mouse.pos)).unwrap();
graphics_worker.send(crate::graphics_worker::Instruction::Render(physics.output(),ins.time,physics.get_next_mouse().pos)).unwrap();
},
Instruction::Resize(size,user_settings)=>{
graphics_worker.send(crate::graphics_worker::Instruction::Resize(size,user_settings)).unwrap();
@ -124,7 +122,7 @@ pub enum Instruction{
graphics_worker.send(crate::graphics_worker::Instruction::GenerateModels(map)).unwrap();
},
Instruction::ClearModels=>{
physics.state.clear();
physics.clear();
graphics_worker.send(crate::graphics_worker::Instruction::ClearModels).unwrap();
},
_=>(),

View File

@ -25,14 +25,14 @@ struct SetupContextPartial1{
instance:wgpu::Instance,
}
fn create_window(title:&str,event_loop:&winit::event_loop::EventLoop<()>)->Result<winit::window::Window,winit::error::OsError>{
let mut builder = winit::window::WindowBuilder::new();
builder = builder.with_title(title);
let mut attr=winit::window::WindowAttributes::default();
attr=attr.with_title(title);
#[cfg(windows_OFF)] // TODO
{
use winit::platform::windows::WindowBuilderExtWindows;
builder=builder.with_no_redirection_bitmap(true);
}
builder.build(event_loop)
event_loop.create_window(attr)
}
fn create_instance()->SetupContextPartial1{
let backends=wgpu::util::backend_bits_from_env().unwrap_or_else(wgpu::Backends::all);
@ -143,6 +143,7 @@ impl<'a> SetupContextPartial3<'a>{
label: None,
required_features: (optional_features & self.adapter.features()) | required_features,
required_limits: needed_limits,
memory_hints:wgpu::MemoryHints::Performance,
},
trace_dir.ok().as_ref().map(std::path::Path::new),
))

View File

@ -48,7 +48,7 @@ struct ModelInstance{
//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
//group 1 is the model
const MAX_MODEL_INSTANCES=4096;
const MAX_MODEL_INSTANCES=512;
@group(2)
@binding(0)
var<uniform> model_instances: array<ModelInstance, MAX_MODEL_INSTANCES>;

View File

@ -108,6 +108,7 @@ impl WindowContext<'_>{
"q"=>Some(InputInstruction::MoveDown(s)),
"z"=>Some(InputInstruction::Zoom(s)),
"r"=>if s{Some(InputInstruction::Reset)}else{None},
"f"=>if s{Some(InputInstruction::PracticeFly)}else{None},
_=>None,
},
_=>None,
@ -173,7 +174,7 @@ impl<'a> WindowContextSetup<'a>{
let user_settings=crate::settings::read_user_settings();
let mut physics=crate::physics::PhysicsContext::default();
physics.state.load_user_settings(&user_settings);
physics.load_user_settings(&user_settings);
let mut graphics=crate::graphics::GraphicsState::new(&context.device,&context.queue,&context.config);
graphics.load_user_settings(&user_settings);

1
tools/meshes Symbolic link
View File

@ -0,0 +1 @@
/run/media/quat/Files/Documents/map-files/verify-scripts/meshes/