This commit is contained in:
Quaternions 2024-02-04 20:59:33 -08:00
parent 9f2c3cd242
commit 8687c65e80
6 changed files with 83 additions and 76 deletions

View File

@ -1,4 +1,6 @@
use std::borrow::Cow; use std::borrow::Cow;
use strafesnet_common::map;
use strafesnet_common::model;
use strafesnet_common::integer; use strafesnet_common::integer;
use wgpu::{util::DeviceExt,AstcBlock,AstcChannel}; use wgpu::{util::DeviceExt,AstcBlock,AstcChannel};
use crate::model_graphics::{GraphicsVertex,GraphicsModelColor4,GraphicsModelInstance,GraphicsModelSingleTexture,IndexedGraphicsModelSingleTexture,IndexedGroupFixedTexture}; use crate::model_graphics::{GraphicsVertex,GraphicsModelColor4,GraphicsModelInstance,GraphicsModelSingleTexture,IndexedGraphicsModelSingleTexture,IndexedGroupFixedTexture};
@ -145,14 +147,14 @@ impl GraphicsState{
pub fn load_user_settings(&mut self,user_settings:&crate::settings::UserSettings){ pub fn load_user_settings(&mut self,user_settings:&crate::settings::UserSettings){
self.camera.fov=user_settings.calculate_fov(1.0,&self.camera.screen_size).as_vec2(); self.camera.fov=user_settings.calculate_fov(1.0,&self.camera.screen_size).as_vec2();
} }
pub fn generate_models(&mut self,device:&wgpu::Device,queue:&wgpu::Queue,indexed_models:crate::model::IndexedModelInstances){ pub fn generate_models(&mut self,device:&wgpu::Device,queue:&wgpu::Queue,map:map::Map){
//generate texture view per texture //generate texture view per texture
//idk how to do this gooder lol //idk how to do this gooder lol
let mut double_map=std::collections::HashMap::<u32,u32>::new(); let mut double_map=std::collections::HashMap::<u32,u32>::new();
let mut texture_loading_threads=Vec::new(); let mut texture_loading_threads=Vec::new();
let num_textures=indexed_models.textures.len(); let num_textures=map.textures.len();
for (i,texture_id) in indexed_models.textures.into_iter().enumerate(){ for (i,texture_id) in map.textures.into_iter().enumerate(){
let path=std::path::PathBuf::from(format!("textures/{}.dds",texture_id)); let path=std::path::PathBuf::from(format!("textures/{}.dds",texture_id));
if let Ok(mut file) = std::fs::File::open(path.clone()){ if let Ok(mut file) = std::fs::File::open(path.clone()){
double_map.insert(i as u32, texture_loading_threads.len() as u32); double_map.insert(i as u32, texture_loading_threads.len() as u32);
@ -216,9 +218,9 @@ impl GraphicsState{
//split groups with different textures into separate models //split groups with different textures into separate models
//the models received here are supposed to be tightly packed, i.e. no code needs to check if two models are using the same groups. //the models received here are supposed to be tightly packed, i.e. no code needs to check if two models are using the same groups.
let indexed_models_len=indexed_models.models.len(); let indexed_models_len=map.models.len();
let mut unique_texture_models=Vec::with_capacity(indexed_models_len); let mut unique_texture_models=Vec::with_capacity(indexed_models_len);
for model in indexed_models.models.into_iter(){ for model in map.models.into_iter(){
//convert ModelInstance into GraphicsModelInstance //convert ModelInstance into GraphicsModelInstance
let instances:Vec<GraphicsModelInstance>=model.instances.into_iter().filter_map(|instance|{ let instances:Vec<GraphicsModelInstance>=model.instances.into_iter().filter_map(|instance|{
if instance.color.w==0.0{ if instance.color.w==0.0{
@ -379,7 +381,7 @@ impl GraphicsState{
//map the indexed vertices onto new indices //map the indexed vertices onto new indices
//creating the vertex map is slightly different because the vertices are directly hashable //creating the vertex map is slightly different because the vertices are directly hashable
let map_vertex_id:Vec<u32>=model.unique_vertices.iter().map(|unmapped_vertex|{ let map_vertex_id:Vec<u32>=model.unique_vertices.iter().map(|unmapped_vertex|{
let vertex=crate::model::IndexedVertex{ let vertex=model::IndexedVertex{
pos:map_pos_id[unmapped_vertex.pos as usize], pos:map_pos_id[unmapped_vertex.pos as usize],
tex:map_tex_id[unmapped_vertex.tex as usize], tex:map_tex_id[unmapped_vertex.tex as usize],
normal:map_normal_id[unmapped_vertex.normal as usize], normal:map_normal_id[unmapped_vertex.normal as usize],
@ -396,7 +398,7 @@ impl GraphicsState{
}).collect(); }).collect();
for group in &model.groups{ for group in &model.groups{
for poly in &group.polys{ for poly in &group.polys{
polys.push(crate::model::IndexedPolygon{vertices:poly.vertices.iter().map(|&vertex_id|map_vertex_id[vertex_id as usize]).collect()}); polys.push(model::IndexedPolygon{vertices:poly.vertices.iter().map(|&vertex_id|map_vertex_id[vertex_id as usize]).collect()});
} }
} }
} }

View File

@ -4,7 +4,7 @@ pub enum Instruction{
Render(crate::physics::PhysicsOutputState,integer::Time,glam::IVec2), Render(crate::physics::PhysicsOutputState,integer::Time,glam::IVec2),
//UpdateModel(crate::graphics::GraphicsModelUpdate), //UpdateModel(crate::graphics::GraphicsModelUpdate),
Resize(winit::dpi::PhysicalSize<u32>,crate::settings::UserSettings), Resize(winit::dpi::PhysicalSize<u32>,crate::settings::UserSettings),
GenerateModels(crate::model::IndexedModelInstances), GenerateModels(strafesnet_common::map::Map),
ClearModels, ClearModels,
} }

View File

@ -1,24 +1,24 @@
use bytemuck::{Pod, Zeroable}; use bytemuck::{Pod, Zeroable};
use crate::model::{IndexedVertex,IndexedPolygon}; use strafesnet_common::model::{IndexedVertex,IndexedPolygon};
#[derive(Clone, Copy, Pod, Zeroable)] #[derive(Clone,Copy,Pod,Zeroable)]
#[repr(C)] #[repr(C)]
pub struct GraphicsVertex { pub struct GraphicsVertex{
pub pos: [f32; 3], pub pos:[f32;3],
pub tex: [f32; 2], pub tex:[f32;2],
pub normal: [f32; 3], pub normal:[f32;3],
pub color: [f32; 4], pub color:[f32;4],
} }
pub struct IndexedGroupFixedTexture{ pub struct IndexedGroupFixedTexture{
pub polys:Vec<IndexedPolygon>, pub polys:Vec<IndexedPolygon>,
} }
pub struct IndexedGraphicsModelSingleTexture{ pub struct IndexedGraphicsModelSingleTexture{
pub unique_pos:Vec<[f32; 3]>, pub unique_pos:Vec<[f32;3]>,
pub unique_tex:Vec<[f32; 2]>, pub unique_tex:Vec<[f32;2]>,
pub unique_normal:Vec<[f32; 3]>, pub unique_normal:Vec<[f32;3]>,
pub unique_color:Vec<[f32; 4]>, pub unique_color:Vec<[f32;4]>,
pub unique_vertices:Vec<IndexedVertex>, pub unique_vertices:Vec<IndexedVertex>,
pub texture:Option<u32>,//RenderPattern? material/texture/shader/flat color pub texture:Option<u32>,//RenderPattern? material/texture/shader/flat color
pub groups: Vec<IndexedGroupFixedTexture>, pub groups:Vec<IndexedGroupFixedTexture>,
pub instances:Vec<GraphicsModelInstance>, pub instances:Vec<GraphicsModelInstance>,
} }
pub enum Entities{ pub enum Entities{

View File

@ -1,4 +1,5 @@
use std::borrow::{Borrow,Cow}; use std::borrow::{Borrow,Cow};
use strafesnet_common::model;
use strafesnet_common::zeroes; use strafesnet_common::zeroes;
use strafesnet_common::integer::{self,Planar64,Planar64Vec3}; use strafesnet_common::integer::{self,Planar64,Planar64Vec3};
@ -134,8 +135,8 @@ impl EdgePool{
(&mut unsafe{self.edge_guys.get_unchecked_mut(edge_id)}.1,EdgeId(edge_id)) (&mut unsafe{self.edge_guys.get_unchecked_mut(edge_id)}.1,EdgeId(edge_id))
} }
} }
impl From<&crate::model::IndexedModel> for PhysicsMesh{ impl From<&model::IndexedModel> for PhysicsMesh{
fn from(indexed_model:&crate::model::IndexedModel)->Self{ fn from(indexed_model:&model::IndexedModel)->Self{
assert!(indexed_model.unique_pos.len()!=0,"Mesh cannot have 0 vertices"); assert!(indexed_model.unique_pos.len()!=0,"Mesh cannot have 0 vertices");
let verts=indexed_model.unique_pos.iter().map(|v|Vert(v.clone())).collect(); let verts=indexed_model.unique_pos.iter().map(|v|Vert(v.clone())).collect();
let mut vert_ref_guys=vec![VertRefGuy::default();indexed_model.unique_pos.len()]; let mut vert_ref_guys=vec![VertRefGuy::default();indexed_model.unique_pos.len()];

View File

@ -8,7 +8,7 @@ use strafesnet_common::gameplay_attributes;
use strafesnet_common::gameplay_modes; use strafesnet_common::gameplay_modes;
use strafesnet_common::map; use strafesnet_common::map;
use strafesnet_common::model; use strafesnet_common::model;
use strafesnet_common::gameplay_style::{self,StyleModifiers,StrafeSettings}; use strafesnet_common::gameplay_style::{self,StyleModifiers};
use strafesnet_common::instruction::{self,InstructionEmitter,InstructionConsumer,TimedInstruction}; use strafesnet_common::instruction::{self,InstructionEmitter,InstructionConsumer,TimedInstruction};
use strafesnet_common::integer::{self,Time,Planar64,Planar64Vec3,Planar64Mat3,Angle32,Ratio64Vec2}; use strafesnet_common::integer::{self,Time,Planar64,Planar64Vec3,Planar64Mat3,Angle32,Ratio64Vec2};
use strafesnet_common::model::ModelId; use strafesnet_common::model::ModelId;
@ -346,10 +346,10 @@ impl StyleHelper for StyleModifiers{
//fn get_jump_energy(&self)->Planar64 //fn get_jump_energy(&self)->Planar64
fn get_jump_deltav(&self)->Planar64{ fn get_jump_deltav(&self)->Planar64{
match &self.jump_impulse{ match &self.jump_impulse{
&JumpImpulse::FromTime(time)=>self.gravity.length()*(time/2), &gameplay_style::JumpImpulse::FromTime(time)=>self.gravity.length()*(time/2),
&JumpImpulse::FromHeight(height)=>(self.gravity.length()*height*2).sqrt(), &gameplay_style::JumpImpulse::FromHeight(height)=>(self.gravity.length()*height*2).sqrt(),
&JumpImpulse::FromDeltaV(deltav)=>deltav, &gameplay_style::JumpImpulse::FromDeltaV(deltav)=>deltav,
&JumpImpulse::FromEnergy(energy)=>(energy*2/self.mass).sqrt(), &gameplay_style::JumpImpulse::FromEnergy(energy)=>(energy*2/self.mass).sqrt(),
} }
} }
@ -423,23 +423,6 @@ enum MoveState{
Ladder(WalkState), Ladder(WalkState),
} }
pub struct PhysicsState{
time:Time,
body:Body,
world:WorldState,//currently there is only one state the world can be in
mode_state:ModeState,
style:StyleModifiers,//mode style with custom style updates applied
touching:TouchingState,
//camera must exist in state because wormholes modify the camera, also camera punch
camera:PhysicsCamera,
pub next_mouse:MouseState,//Where is the mouse headed next
controls:u32,//TODO this should be a struct
move_state:MoveState,
//does not belong here
//bvh:bvh::BvhNode,
//models:PhysicsModels,
//modes:gameplay_modes::Modes,
}
#[derive(Clone,Default)] #[derive(Clone,Default)]
pub struct PhysicsOutputState{ pub struct PhysicsOutputState{
body:Body, body:Body,
@ -483,15 +466,18 @@ enum PhysicsAttributesId{
Intersect(IntersectAttributesId) Intersect(IntersectAttributesId)
} }
//id assigned to deindexed IndexedPhysicsGroup
struct PhysicsModelId(u32);
struct PhysicsGroupId(u32);
//unique physics meshes indexed by this //unique physics meshes indexed by this
struct MeshId{ struct ConvexMeshId{
model_id:ModelId, model_id:PhysicsModelId,// = IndexedModelId
group_id:GroupId, group_id:PhysicsGroupId,// group in model
} }
pub struct PhysicsModel{ pub struct PhysicsModel{
//A model is a thing that has a hitbox. can be represented by a list of TreyMesh-es //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. //in this iteration, all it needs is extents.
mesh_id:MeshId, mesh_id:ConvexMeshId,
//put these up on the Model (data normalization) //put these up on the Model (data normalization)
general_attributes:GeneralAttributesId, general_attributes:GeneralAttributesId,
collision_attributes:PhysicsAttributesId, collision_attributes:PhysicsAttributesId,
@ -501,7 +487,7 @@ pub struct PhysicsModel{
} }
impl PhysicsModel{ impl PhysicsModel{
pub fn new(mesh_id:MeshId,attr_id:PhysicsAttributesId,transform:integer::Planar64Affine3)->Self{ pub fn new(mesh_id:ConvexMeshId,attr_id:PhysicsAttributesId,transform:integer::Planar64Affine3)->Self{
Self{ Self{
mesh_id, mesh_id,
attr_id, attr_id,
@ -626,7 +612,7 @@ impl TouchingState{
PhysicsCollisionAttributes::Contact{contacting,general}=>{ PhysicsCollisionAttributes::Contact{contacting,general}=>{
let normal=contact_normal(models,&style_mesh,contact); let normal=contact_normal(models,&style_mesh,contact);
match &contacting.contact_behaviour{ match &contacting.contact_behaviour{
Some(model::ContactingBehaviour::Ladder(_))=>{ Some(gameplay_attributes::ContactingBehaviour::Ladder(_))=>{
//ladder walkstate //ladder walkstate
let mut target_velocity=style.get_ladder_target_velocity(camera,controls,next_mouse,time,&normal); let mut target_velocity=style.get_ladder_target_velocity(camera,controls,next_mouse,time,&normal);
self.constrain_velocity(models,&style_mesh,&mut target_velocity); self.constrain_velocity(models,&style_mesh,&mut target_velocity);
@ -779,23 +765,39 @@ impl VirtualBody<'_>{
} }
} }
pub struct PhysicsState{
time:Time,
body:Body,
world:WorldState,//currently there is only one state the world can be in
mode_state:ModeState,
style:StyleModifiers,//mode style with custom style updates applied
touching:TouchingState,
//camera must exist in state because wormholes modify the camera, also camera punch
camera:PhysicsCamera,
pub next_mouse:MouseState,//Where is the mouse headed next
controls:u32,//TODO this should be a struct
move_state:MoveState,
//does not belong here
//bvh:bvh::BvhNode,
//models:PhysicsModels,
//modes:gameplay_modes::Modes,
}
impl Default for PhysicsState{ impl Default for PhysicsState{
fn default()->Self{ fn default()->Self{
Self{ Self{
spawn_point:Planar64Vec3::int(0,50,0),
body:Body::new(Planar64Vec3::int(0,50,0),Planar64Vec3::int(0,0,0),Planar64Vec3::int(0,-100,0),Time::ZERO), body:Body::new(Planar64Vec3::int(0,50,0),Planar64Vec3::int(0,0,0),Planar64Vec3::int(0,-100,0),Time::ZERO),
time:Time::ZERO, time:Time::ZERO,
style:StyleModifiers::default(), style:StyleModifiers::default(),
touching:TouchingState::default(), touching:TouchingState::default(),
models:PhysicsModels::default(),
bvh:bvh::BvhNode::default(),
move_state: MoveState::Air, move_state: MoveState::Air,
camera:PhysicsCamera::default(), camera:PhysicsCamera::default(),
next_mouse:MouseState::default(), next_mouse:MouseState::default(),
controls:0, controls:0,
world:WorldState{}, world:WorldState{},
mode_state:ModeState::default(), mode_state:ModeState::default(),
modes:Modes::default(), //modes:Modes::default(),
//bvh:bvh::BvhNode::default(),
//models:PhysicsModels::default(),
} }
} }
} }
@ -1072,7 +1074,7 @@ fn teleport(body:&mut Body,touching:&mut TouchingState,models:&PhysicsModels,sty
set_acceleration(body,touching,models,&style.mesh(),style.gravity); set_acceleration(body,touching,models,&style.mesh(),style.gravity);
MoveState::Air MoveState::Air
} }
fn teleport_to_spawn(body:&mut Body,touching:&mut TouchingState,style:&StyleModifiers,mode:&gameplay_modes::Mode,models:&PhysicsModels,stage_id:StageId)->Option<MoveState>{ fn teleport_to_spawn(body:&mut Body,touching:&mut TouchingState,style:&StyleModifiers,mode:&gameplay_modes::Mode,models:&PhysicsModels,stage_id:gameplay_modes::StageId)->Option<MoveState>{
let model=models.model(mode.get_spawn_model_id(stage_id)?); let model=models.model(mode.get_spawn_model_id(stage_id)?);
let point=model.transform.transform_point3(Planar64Vec3::Y)+Planar64Vec3::Y*(style.hitbox.halfsize.y()+Planar64::ONE/16); let point=model.transform.transform_point3(Planar64Vec3::Y)+Planar64Vec3::Y*(style.hitbox.halfsize.y()+Planar64::ONE/16);
Some(teleport(body,touching,models,style,point)) Some(teleport(body,touching,models,style,point))
@ -1082,20 +1084,21 @@ fn run_teleport_behaviour(wormhole:&Option<gameplay_attributes::Wormhole>,game:&
//TODO: jump count and checkpoints are always reset on teleport. //TODO: jump count and checkpoints are always reset on teleport.
//Map makers are expected to use tools to prevent //Map makers are expected to use tools to prevent
//multi-boosting on JumpLimit boosters such as spawning into a SetVelocity //multi-boosting on JumpLimit boosters such as spawning into a SetVelocity
mode.get_element(model_id).map(|stage_element|{ let stage_element=mode.get_element(model_id)?;
{
if stage_element.force||game.stage_id<stage_element.stage_id{ if stage_element.force||game.stage_id<stage_element.stage_id{
//TODO: check if all checkpoints are complete up to destination stage id, otherwise set to checkpoint completion stage it //TODO: check if all checkpoints are complete up to destination stage id, otherwise set to checkpoint completion stage it
game.stage_id=stage_element.stage_id; game.stage_id=stage_element.stage_id;
} }
match &stage_element.behaviour{ match &stage_element.behaviour{
model::StageElementBehaviour::SpawnAt=>None, gameplay_modes::StageElementBehaviour::SpawnAt=>None,
model::StageElementBehaviour::Trigger gameplay_modes::StageElementBehaviour::Trigger
|model::StageElementBehaviour::Teleport=>{ |gameplay_modes::StageElementBehaviour::Teleport=>{
//I guess this is correct behaviour when trying to teleport to a non-existent spawn but it's still weird //I guess this is correct behaviour when trying to teleport to a non-existent spawn but it's still weird
teleport_to_spawn(body,touching,style,modes.get_mode(stage_element.mode_id)?,models,game.stage_id) teleport_to_spawn(body,touching,style,mode,models,game.stage_id)
}, },
model::StageElementBehaviour::Platform=>None, gameplay_modes::StageElementBehaviour::Platform=>None,
&model::StageElementBehaviour::Checkpoint=>{ &gameplay_modes::StageElementBehaviour::Checkpoint=>{
// let mode=modes.get_mode(stage_element.mode_id)?; // let mode=modes.get_mode(stage_element.mode_id)?;
// if mode.ordered_checkpoint_id.map_or(true,|id|id<game.next_ordered_checkpoint_id) // if mode.ordered_checkpoint_id.map_or(true,|id|id<game.next_ordered_checkpoint_id)
// &&mode.unordered_checkpoint_count<=game.unordered_checkpoints.len() as u32{ // &&mode.unordered_checkpoint_count<=game.unordered_checkpoints.len() as u32{
@ -1106,7 +1109,7 @@ fn run_teleport_behaviour(wormhole:&Option<gameplay_attributes::Wormhole>,game:&
// teleport_to_spawn(body,touching,style,modes.get_mode(stage_element.mode_id)?,models,game.stage_id) // teleport_to_spawn(body,touching,style,modes.get_mode(stage_element.mode_id)?,models,game.stage_id)
// } // }
}, },
&model::StageElementBehaviour::Ordered{checkpoint_id}=>{ &gameplay_modes::StageElementBehaviour::Ordered{checkpoint_id}=>{
if checkpoint_id<game.next_ordered_checkpoint_id{ if checkpoint_id<game.next_ordered_checkpoint_id{
//if you hit a checkpoint you already hit, nothing happens //if you hit a checkpoint you already hit, nothing happens
None None
@ -1117,30 +1120,31 @@ fn run_teleport_behaviour(wormhole:&Option<gameplay_attributes::Wormhole>,game:&
None None
}else{ }else{
//If you hit an ordered checkpoint after missing a previous one //If you hit an ordered checkpoint after missing a previous one
teleport_to_spawn(body,touching,style,modes.get_mode(stage_element.mode_id)?,models,game.stage_id) teleport_to_spawn(body,touching,style,mode,models,game.stage_id)
} }
}, },
model::StageElementBehaviour::Unordered=>{ gameplay_modes::StageElementBehaviour::Unordered=>{
//count model id in accumulated unordered checkpoints //count model id in accumulated unordered checkpoints
game.unordered_checkpoints.insert(model_id); game.unordered_checkpoints.insert(model_id);
None None
}, },
&model::StageElementBehaviour::JumpLimit(jump_limit)=>{ &gameplay_modes::StageElementBehaviour::JumpLimit(jump_limit)=>{
//let count=game.jump_counts.get(&model.id); //let count=game.jump_counts.get(&model.id);
//TODO //TODO
None None
}, },
} }
}).or_else(|| }.or_else(||
match wormhole{ match wormhole{
Some(gameplay_attributes::Wormhole{destination_model})=>{ Some(gameplay_attributes::Wormhole{destination_model})=>{
let origin_model=models.model(model_id); let origin_model=models.model(model_id);
let destination_model=models.get_wormhole_model(destination_model)?; let destination_model=models.get_wormhole_model(destination_model)?;
//ignore the transform for now //ignore the transform for now
Some(teleport(body,touching,models,style,body.position-origin_model.transform.translation+destination_model.transform.translation)) Some(teleport(body,touching,models,style,body.position-origin_model.transform.translation+destination_model.transform.translation))
}
None=>None,
} }
None=>None, )
})
} }
impl instruction::InstructionConsumer<PhysicsInstruction> for PhysicsState { impl instruction::InstructionConsumer<PhysicsInstruction> for PhysicsState {

View File

@ -18,7 +18,7 @@ pub enum Instruction{
Input(InputInstruction), Input(InputInstruction),
Render, Render,
Resize(winit::dpi::PhysicalSize<u32>,crate::settings::UserSettings), Resize(winit::dpi::PhysicalSize<u32>,crate::settings::UserSettings),
GenerateModels(crate::model::IndexedModelInstances), GenerateModels(strafesnet_common::map::Map),
ClearModels, ClearModels,
//Graphics(crate::graphics_worker::Instruction), //Graphics(crate::graphics_worker::Instruction),
} }