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 strafesnet_common::map;
use strafesnet_common::model;
use strafesnet_common::integer;
use wgpu::{util::DeviceExt,AstcBlock,AstcChannel};
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){
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
//idk how to do this gooder lol
let mut double_map=std::collections::HashMap::<u32,u32>::new();
let mut texture_loading_threads=Vec::new();
let num_textures=indexed_models.textures.len();
for (i,texture_id) in indexed_models.textures.into_iter().enumerate(){
let num_textures=map.textures.len();
for (i,texture_id) in map.textures.into_iter().enumerate(){
let path=std::path::PathBuf::from(format!("textures/{}.dds",texture_id));
if let Ok(mut file) = std::fs::File::open(path.clone()){
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
//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);
for model in indexed_models.models.into_iter(){
for model in map.models.into_iter(){
//convert ModelInstance into GraphicsModelInstance
let instances:Vec<GraphicsModelInstance>=model.instances.into_iter().filter_map(|instance|{
if instance.color.w==0.0{
@ -379,7 +381,7 @@ impl GraphicsState{
//map the indexed vertices onto new indices
//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 vertex=crate::model::IndexedVertex{
let vertex=model::IndexedVertex{
pos:map_pos_id[unmapped_vertex.pos as usize],
tex:map_tex_id[unmapped_vertex.tex as usize],
normal:map_normal_id[unmapped_vertex.normal as usize],
@ -396,7 +398,7 @@ impl GraphicsState{
}).collect();
for group in &model.groups{
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),
//UpdateModel(crate::graphics::GraphicsModelUpdate),
Resize(winit::dpi::PhysicalSize<u32>,crate::settings::UserSettings),
GenerateModels(crate::model::IndexedModelInstances),
GenerateModels(strafesnet_common::map::Map),
ClearModels,
}

View File

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

View File

@ -1,4 +1,5 @@
use std::borrow::{Borrow,Cow};
use strafesnet_common::model;
use strafesnet_common::zeroes;
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))
}
}
impl From<&crate::model::IndexedModel> for PhysicsMesh{
fn from(indexed_model:&crate::model::IndexedModel)->Self{
impl From<&model::IndexedModel> for PhysicsMesh{
fn from(indexed_model:&model::IndexedModel)->Self{
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 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::map;
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::integer::{self,Time,Planar64,Planar64Vec3,Planar64Mat3,Angle32,Ratio64Vec2};
use strafesnet_common::model::ModelId;
@ -346,10 +346,10 @@ impl StyleHelper for StyleModifiers{
//fn get_jump_energy(&self)->Planar64
fn get_jump_deltav(&self)->Planar64{
match &self.jump_impulse{
&JumpImpulse::FromTime(time)=>self.gravity.length()*(time/2),
&JumpImpulse::FromHeight(height)=>(self.gravity.length()*height*2).sqrt(),
&JumpImpulse::FromDeltaV(deltav)=>deltav,
&JumpImpulse::FromEnergy(energy)=>(energy*2/self.mass).sqrt(),
&gameplay_style::JumpImpulse::FromTime(time)=>self.gravity.length()*(time/2),
&gameplay_style::JumpImpulse::FromHeight(height)=>(self.gravity.length()*height*2).sqrt(),
&gameplay_style::JumpImpulse::FromDeltaV(deltav)=>deltav,
&gameplay_style::JumpImpulse::FromEnergy(energy)=>(energy*2/self.mass).sqrt(),
}
}
@ -423,23 +423,6 @@ enum MoveState{
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)]
pub struct PhysicsOutputState{
body:Body,
@ -483,15 +466,18 @@ enum PhysicsAttributesId{
Intersect(IntersectAttributesId)
}
//id assigned to deindexed IndexedPhysicsGroup
struct PhysicsModelId(u32);
struct PhysicsGroupId(u32);
//unique physics meshes indexed by this
struct MeshId{
model_id:ModelId,
group_id:GroupId,
struct ConvexMeshId{
model_id:PhysicsModelId,// = IndexedModelId
group_id:PhysicsGroupId,// group in model
}
pub struct PhysicsModel{
//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.
mesh_id:MeshId,
mesh_id:ConvexMeshId,
//put these up on the Model (data normalization)
general_attributes:GeneralAttributesId,
collision_attributes:PhysicsAttributesId,
@ -501,7 +487,7 @@ pub struct 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{
mesh_id,
attr_id,
@ -626,7 +612,7 @@ impl TouchingState{
PhysicsCollisionAttributes::Contact{contacting,general}=>{
let normal=contact_normal(models,&style_mesh,contact);
match &contacting.contact_behaviour{
Some(model::ContactingBehaviour::Ladder(_))=>{
Some(gameplay_attributes::ContactingBehaviour::Ladder(_))=>{
//ladder walkstate
let mut target_velocity=style.get_ladder_target_velocity(camera,controls,next_mouse,time,&normal);
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{
fn default()->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),
time:Time::ZERO,
style:StyleModifiers::default(),
touching:TouchingState::default(),
models:PhysicsModels::default(),
bvh:bvh::BvhNode::default(),
move_state: MoveState::Air,
camera:PhysicsCamera::default(),
next_mouse:MouseState::default(),
controls:0,
world:WorldState{},
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);
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 point=model.transform.transform_point3(Planar64Vec3::Y)+Planar64Vec3::Y*(style.hitbox.halfsize.y()+Planar64::ONE/16);
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.
//Map makers are expected to use tools to prevent
//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{
//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;
}
match &stage_element.behaviour{
model::StageElementBehaviour::SpawnAt=>None,
model::StageElementBehaviour::Trigger
|model::StageElementBehaviour::Teleport=>{
gameplay_modes::StageElementBehaviour::SpawnAt=>None,
gameplay_modes::StageElementBehaviour::Trigger
|gameplay_modes::StageElementBehaviour::Teleport=>{
//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,
&model::StageElementBehaviour::Checkpoint=>{
gameplay_modes::StageElementBehaviour::Platform=>None,
&gameplay_modes::StageElementBehaviour::Checkpoint=>{
// let mode=modes.get_mode(stage_element.mode_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{
@ -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)
// }
},
&model::StageElementBehaviour::Ordered{checkpoint_id}=>{
&gameplay_modes::StageElementBehaviour::Ordered{checkpoint_id}=>{
if checkpoint_id<game.next_ordered_checkpoint_id{
//if you hit a checkpoint you already hit, nothing happens
None
@ -1117,21 +1120,21 @@ fn run_teleport_behaviour(wormhole:&Option<gameplay_attributes::Wormhole>,game:&
None
}else{
//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
game.unordered_checkpoints.insert(model_id);
None
},
&model::StageElementBehaviour::JumpLimit(jump_limit)=>{
&gameplay_modes::StageElementBehaviour::JumpLimit(jump_limit)=>{
//let count=game.jump_counts.get(&model.id);
//TODO
None
},
}
}).or_else(||
}.or_else(||
match wormhole{
Some(gameplay_attributes::Wormhole{destination_model})=>{
let origin_model=models.model(model_id);
@ -1140,7 +1143,8 @@ fn run_teleport_behaviour(wormhole:&Option<gameplay_attributes::Wormhole>,game:&
Some(teleport(body,touching,models,style,body.position-origin_model.transform.translation+destination_model.transform.translation))
}
None=>None,
})
}
)
}
impl instruction::InstructionConsumer<PhysicsInstruction> for PhysicsState {

View File

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