data structure rewrite
This commit is contained in:
parent
f38d990a54
commit
47cdea0c8a
46
Cargo.lock
generated
46
Cargo.lock
generated
@ -8,9 +8,55 @@ version = "0.25.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "151665d9be52f9bb40fc7966565d39666f2d1e69233571b71b87791c7e0528b3"
|
checksum = "151665d9be52f9bb40fc7966565d39666f2d1e69233571b71b87791c7e0528b3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "id"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "git+https://git.itzana.me/Quaternions/id?rev=1f710976cc786c8853dab73d6e1cee53158deeb0#1f710976cc786c8853dab73d6e1cee53158deeb0"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro2"
|
||||||
|
version = "1.0.78"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quote"
|
||||||
|
version = "1.0.35"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "strafesnet_common"
|
name = "strafesnet_common"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"glam",
|
"glam",
|
||||||
|
"id",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "2.0.48"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-ident"
|
||||||
|
version = "1.0.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
||||||
|
@ -7,3 +7,4 @@ edition = "2021"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
glam = "0.25.0"
|
glam = "0.25.0"
|
||||||
|
id = { git = "https://git.itzana.me/Quaternions/id", rev = "1f710976cc786c8853dab73d6e1cee53158deeb0" }
|
||||||
|
46
src/bvh.rs
46
src/bvh.rs
@ -9,23 +9,24 @@ use crate::aabb::Aabb;
|
|||||||
//start with bisection into octrees because a bad bvh is still 1000x better than no bvh
|
//start with bisection into octrees because a bad bvh is still 1000x better than no bvh
|
||||||
//sort the centerpoints on each axis (3 lists)
|
//sort the centerpoints on each axis (3 lists)
|
||||||
//bv is put into octant based on whether it is upper or lower in each list
|
//bv is put into octant based on whether it is upper or lower in each list
|
||||||
enum BvhNodeContent{
|
|
||||||
Branch(Vec<BvhNode>),
|
enum BvhNodeContent<T>{
|
||||||
Leaf(usize),
|
Branch(Vec<BvhNode<T>>),
|
||||||
|
Leaf(T),
|
||||||
}
|
}
|
||||||
impl Default for BvhNodeContent{
|
impl<T> Default for BvhNodeContent<T>{
|
||||||
fn default()->Self{
|
fn default()->Self{
|
||||||
Self::Branch(Vec::new())
|
Self::Branch(Vec::new())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct BvhNode{
|
pub struct BvhNode<T>{
|
||||||
content:BvhNodeContent,
|
content:BvhNodeContent<T>,
|
||||||
aabb:Aabb,
|
aabb:Aabb,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BvhNode{
|
impl<T:Copy+Eq+std::hash::Hash> BvhNode<T>{
|
||||||
pub fn the_tester<F:FnMut(usize)>(&self,aabb:&Aabb,f:&mut F){
|
pub fn the_tester<F:FnMut(T)>(&self,aabb:&Aabb,f:&mut F){
|
||||||
match &self.content{
|
match &self.content{
|
||||||
&BvhNodeContent::Leaf(model)=>f(model),
|
&BvhNodeContent::Leaf(model)=>f(model),
|
||||||
BvhNodeContent::Branch(children)=>for child in children{
|
BvhNodeContent::Branch(children)=>for child in children{
|
||||||
@ -41,13 +42,13 @@ impl BvhNode{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn generate_bvh(boxen:Vec<Aabb>)->BvhNode{
|
pub fn generate_bvh<T:Copy+Eq+std::hash::Hash>(boxen:Vec<(T,Aabb)>)->BvhNode<T>{
|
||||||
generate_bvh_node(boxen.into_iter().enumerate().collect())
|
generate_bvh_node(boxen,false)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generate_bvh_node(boxen:Vec<(usize,Aabb)>)->BvhNode{
|
fn generate_bvh_node<T:Copy+Eq+std::hash::Hash>(boxen:Vec<(T,Aabb)>,force:bool)->BvhNode<T>{
|
||||||
let n=boxen.len();
|
let n=boxen.len();
|
||||||
if n<20{
|
if force||n<20{
|
||||||
let mut aabb=Aabb::default();
|
let mut aabb=Aabb::default();
|
||||||
let nodes=boxen.into_iter().map(|b|{
|
let nodes=boxen.into_iter().map(|b|{
|
||||||
aabb.join(&b.1);
|
aabb.join(&b.1);
|
||||||
@ -110,14 +111,19 @@ fn generate_bvh_node(boxen:Vec<(usize,Aabb)>)->BvhNode{
|
|||||||
list_list[list_id].push((i,aabb));
|
list_list[list_id].push((i,aabb));
|
||||||
}
|
}
|
||||||
let mut aabb=Aabb::default();
|
let mut aabb=Aabb::default();
|
||||||
let children=list_list.into_iter().map(|b|{
|
if list_list.len()==1{
|
||||||
let node=generate_bvh_node(b);
|
generate_bvh_node(list_list.remove(0),true)
|
||||||
aabb.join(&node.aabb);
|
}else{
|
||||||
node
|
BvhNode{
|
||||||
}).collect();
|
content:BvhNodeContent::Branch(
|
||||||
BvhNode{
|
list_list.into_iter().map(|b|{
|
||||||
content:BvhNodeContent::Branch(children),
|
let node=generate_bvh_node(b,false);
|
||||||
aabb,
|
aabb.join(&node.aabb);
|
||||||
|
node
|
||||||
|
}).collect()
|
||||||
|
),
|
||||||
|
aabb,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
use crate::model;
|
||||||
use crate::integer::{Time,Planar64,Planar64Vec3};
|
use crate::integer::{Time,Planar64,Planar64Vec3};
|
||||||
|
|
||||||
//you have this effect while in contact
|
//you have this effect while in contact
|
||||||
@ -8,8 +9,9 @@ pub struct ContactingLadder{
|
|||||||
#[derive(Clone,Hash,Eq,PartialEq)]
|
#[derive(Clone,Hash,Eq,PartialEq)]
|
||||||
pub enum ContactingBehaviour{
|
pub enum ContactingBehaviour{
|
||||||
Surf,
|
Surf,
|
||||||
Cling,//usable as a zipline, or other weird and wonderful things
|
|
||||||
Ladder(ContactingLadder),
|
Ladder(ContactingLadder),
|
||||||
|
NoJump,
|
||||||
|
Cling,//usable as a zipline, or other weird and wonderful things
|
||||||
Elastic(u32),//[1/2^32,1] 0=None (elasticity+1)/2^32
|
Elastic(u32),//[1/2^32,1] 0=None (elasticity+1)/2^32
|
||||||
}
|
}
|
||||||
//you have this effect while intersecting
|
//you have this effect while intersecting
|
||||||
@ -54,7 +56,7 @@ pub enum SetTrajectory{
|
|||||||
Velocity(Planar64Vec3),//SetVelocity
|
Velocity(Planar64Vec3),//SetVelocity
|
||||||
}
|
}
|
||||||
impl SetTrajectory{
|
impl SetTrajectory{
|
||||||
fn is_velocity(&self)->bool{
|
pub const fn is_absolute(&self)->bool{
|
||||||
match self{
|
match self{
|
||||||
SetTrajectory::AirTime(_)
|
SetTrajectory::AirTime(_)
|
||||||
|SetTrajectory::Height(_)
|
|SetTrajectory::Height(_)
|
||||||
@ -76,7 +78,7 @@ pub struct Wormhole{
|
|||||||
//destination does not need to be another wormhole
|
//destination does not need to be another wormhole
|
||||||
//this defines a one way portal to a destination model transform
|
//this defines a one way portal to a destination model transform
|
||||||
//two of these can create a two way wormhole
|
//two of these can create a two way wormhole
|
||||||
pub destination_model_id:u32,
|
pub destination_model:model::ModelId,
|
||||||
//(position,angles)*=origin.transform.inverse()*destination.transform
|
//(position,angles)*=origin.transform.inverse()*destination.transform
|
||||||
}
|
}
|
||||||
//attributes listed in order of handling
|
//attributes listed in order of handling
|
||||||
@ -88,14 +90,14 @@ pub struct GeneralAttributes{
|
|||||||
pub accelerator:Option<Accelerator>,
|
pub accelerator:Option<Accelerator>,
|
||||||
}
|
}
|
||||||
impl GeneralAttributes{
|
impl GeneralAttributes{
|
||||||
pub fn any(&self)->bool{
|
pub const fn any(&self)->bool{
|
||||||
self.booster.is_some()
|
self.booster.is_some()
|
||||||
||self.trajectory.is_some()
|
||self.trajectory.is_some()
|
||||||
||self.wormhole.is_some()
|
||self.wormhole.is_some()
|
||||||
||self.accelerator.is_some()
|
||self.accelerator.is_some()
|
||||||
}
|
}
|
||||||
pub fn is_wrcp(&self)->bool{
|
pub fn is_wrcp(&self)->bool{
|
||||||
self.trajectory.as_ref().map_or(false,|t|t.is_velocity())
|
self.trajectory.as_ref().map_or(false,|t|t.is_absolute())
|
||||||
/*
|
/*
|
||||||
&&match &self.teleport_behaviour{
|
&&match &self.teleport_behaviour{
|
||||||
Some(TeleportBehaviour::StageElement(
|
Some(TeleportBehaviour::StageElement(
|
||||||
@ -117,7 +119,7 @@ pub struct ContactingAttributes{
|
|||||||
pub contact_behaviour:Option<ContactingBehaviour>,
|
pub contact_behaviour:Option<ContactingBehaviour>,
|
||||||
}
|
}
|
||||||
impl ContactingAttributes{
|
impl ContactingAttributes{
|
||||||
pub fn any(&self)->bool{
|
pub const fn any(&self)->bool{
|
||||||
self.contact_behaviour.is_some()
|
self.contact_behaviour.is_some()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -126,11 +128,13 @@ pub struct IntersectingAttributes{
|
|||||||
pub water:Option<IntersectingWater>,
|
pub water:Option<IntersectingWater>,
|
||||||
}
|
}
|
||||||
impl IntersectingAttributes{
|
impl IntersectingAttributes{
|
||||||
pub fn any(&self)->bool{
|
pub const fn any(&self)->bool{
|
||||||
self.water.is_some()
|
self.water.is_some()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[derive(Clone,Copy,id::Id,Hash,Eq,PartialEq)]
|
||||||
pub struct CollisionAttributesId(u32);
|
pub struct CollisionAttributesId(u32);
|
||||||
|
#[derive(Clone,Hash,Eq,PartialEq)]
|
||||||
pub enum CollisionAttributes{
|
pub enum CollisionAttributes{
|
||||||
Decoration,//visual only
|
Decoration,//visual only
|
||||||
Contact{//track whether you are contacting the object
|
Contact{//track whether you are contacting the object
|
||||||
|
@ -1,14 +1,38 @@
|
|||||||
use std::collections::{HashSet,HashMap};
|
use std::collections::{HashSet,HashMap};
|
||||||
use crate::model::ModelId;
|
use crate::model::ModelId;
|
||||||
use crate::gameplay_style;
|
use crate::gameplay_style;
|
||||||
|
use crate::updatable::Updatable;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct StageElement{
|
pub struct StageElement{
|
||||||
stage:StageId,//which stage spawn to send to
|
stage_id:StageId,//which stage spawn to send to
|
||||||
force:bool,//allow setting to lower spawn id i.e. 7->3
|
force:bool,//allow setting to lower spawn id i.e. 7->3
|
||||||
behaviour:StageElementBehaviour
|
behaviour:StageElementBehaviour
|
||||||
}
|
}
|
||||||
|
impl StageElement{
|
||||||
|
#[inline]
|
||||||
|
pub const fn new(stage_id:StageId,force:bool,behaviour:StageElementBehaviour)->Self{
|
||||||
|
Self{
|
||||||
|
stage_id,
|
||||||
|
force,
|
||||||
|
behaviour,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
pub const fn stage_id(&self)->StageId{
|
||||||
|
self.stage_id
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
pub const fn force(&self)->bool{
|
||||||
|
self.force
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
pub const fn behaviour(&self)->StageElementBehaviour{
|
||||||
|
self.behaviour
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone,Hash,Eq,PartialEq)]
|
#[derive(Clone,Copy,Hash,Eq,PartialEq)]
|
||||||
pub enum StageElementBehaviour{
|
pub enum StageElementBehaviour{
|
||||||
SpawnAt,//must be standing on top to get effect. except cancollide false
|
SpawnAt,//must be standing on top to get effect. except cancollide false
|
||||||
Trigger,
|
Trigger,
|
||||||
@ -20,51 +44,150 @@ pub enum StageElementBehaviour{
|
|||||||
Checkpoint,//this is a combined behaviour for Ordered & Unordered in case a model is used multiple times or for both.
|
Checkpoint,//this is a combined behaviour for Ordered & Unordered in case a model is used multiple times or for both.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone,Copy,Hash,id::Id,Eq,PartialEq)]
|
||||||
|
pub struct CheckpointId(u32);
|
||||||
|
impl CheckpointId{
|
||||||
|
pub const FIRST:Self=Self(0);
|
||||||
|
}
|
||||||
|
#[derive(Clone,Copy,Hash,id::Id,Eq,PartialEq,Ord,PartialOrd)]
|
||||||
pub struct StageId(u32);
|
pub struct StageId(u32);
|
||||||
|
impl StageId{
|
||||||
|
pub const FIRST:Self=Self(0);
|
||||||
|
}
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct Stage{
|
pub struct Stage{
|
||||||
spawn:ModelId,
|
spawn:ModelId,
|
||||||
//other behaviour models of this stage can have
|
//open world support lol
|
||||||
ordered_checkpoints:Vec<ModelId>,
|
ordered_checkpoints_count:u32,
|
||||||
|
unordered_checkpoints_count:u32,
|
||||||
|
//currently loaded checkpoint models
|
||||||
|
ordered_checkpoints:HashMap<CheckpointId,ModelId>,
|
||||||
unordered_checkpoints:HashSet<ModelId>,
|
unordered_checkpoints:HashSet<ModelId>,
|
||||||
}
|
}
|
||||||
|
impl Stage{
|
||||||
#[derive(Clone,Hash,Eq,PartialEq)]
|
pub fn new(spawn:ModelId)->Self{
|
||||||
pub enum ZoneBehaviour{
|
Self{
|
||||||
Finish,
|
spawn,
|
||||||
Anitcheat,
|
ordered_checkpoints_count:0,
|
||||||
|
unordered_checkpoints_count:0,
|
||||||
|
ordered_checkpoints:HashMap::new(),
|
||||||
|
unordered_checkpoints:HashSet::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
pub const fn spawn(&self)->ModelId{
|
||||||
|
self.spawn
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
pub const fn is_empty(&self)->bool{
|
||||||
|
self.is_complete(0,0)
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
pub const fn is_complete(&self,ordered_checkpoints_count:u32,unordered_checkpoints_count:u32)->bool{
|
||||||
|
self.ordered_checkpoints_count==ordered_checkpoints_count&&self.unordered_checkpoints_count==unordered_checkpoints_count
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
pub fn is_next_ordered_checkpoint(&self,next_ordered_checkpoint_id:CheckpointId,model_id:ModelId)->bool{
|
||||||
|
self.ordered_checkpoints.get(&next_ordered_checkpoint_id).is_some_and(|&next_checkpoint|model_id==next_checkpoint)
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
pub fn is_unordered_checkpoint(&self,model_id:ModelId)->bool{
|
||||||
|
self.unordered_checkpoints.contains(&model_id)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct StageUpdate{
|
||||||
|
//other behaviour models of this stage can have
|
||||||
|
ordered_checkpoints:HashMap<CheckpointId,ModelId>,
|
||||||
|
unordered_checkpoints:HashSet<ModelId>,
|
||||||
|
}
|
||||||
|
impl Updatable<StageUpdate> for Stage{
|
||||||
|
fn update(&mut self,update:StageUpdate){
|
||||||
|
self.ordered_checkpoints.extend(update.ordered_checkpoints);
|
||||||
|
self.unordered_checkpoints.extend(update.unordered_checkpoints);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone,Copy,Hash,Eq,PartialEq)]
|
||||||
|
pub enum Zone{
|
||||||
|
Start,
|
||||||
|
Finish,
|
||||||
|
Anticheat,
|
||||||
|
}
|
||||||
|
#[derive(Clone,Copy,Hash,id::Id,Eq,PartialEq,Ord,PartialOrd)]
|
||||||
pub struct ModeId(u32);
|
pub struct ModeId(u32);
|
||||||
|
impl ModeId{
|
||||||
|
pub const MAIN:Self=Self(0);
|
||||||
|
pub const BONUS:Self=Self(1);
|
||||||
|
}
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct Mode{
|
pub struct Mode{
|
||||||
style:gameplay_style::StyleModifiers,
|
style:gameplay_style::StyleModifiers,
|
||||||
start:ModelId,
|
start:ModelId,//when you press reset you go here
|
||||||
zones:HashMap<ModelId,ZoneBehaviour>,
|
zones:HashMap<ModelId,Zone>,
|
||||||
stages:Vec<Stage>,
|
stages:Vec<Stage>,//when you load the map you go to stages[0].spawn
|
||||||
//mutually exlusive stage element behaviour
|
//mutually exlusive stage element behaviour
|
||||||
elements:HashMap<ModelId,StageElement>,
|
elements:HashMap<ModelId,StageElement>,
|
||||||
jump_limit:HashMap<ModelId,u32>,
|
jump_limit:HashMap<ModelId,u32>,
|
||||||
}
|
}
|
||||||
impl Mode{
|
impl Mode{
|
||||||
|
pub fn new(style:gameplay_style::StyleModifiers,start:ModelId)->Self{
|
||||||
|
Self{
|
||||||
|
style,
|
||||||
|
start,
|
||||||
|
zones:HashMap::new(),
|
||||||
|
stages:Vec::new(),
|
||||||
|
elements:HashMap::new(),
|
||||||
|
jump_limit:HashMap::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub const fn get_start(&self)->ModelId{
|
||||||
|
self.start
|
||||||
|
}
|
||||||
|
pub const fn get_style(&self)->&gameplay_style::StyleModifiers{
|
||||||
|
&self.style
|
||||||
|
}
|
||||||
|
pub fn push_stage(&mut self,stage:Stage){
|
||||||
|
self.stages.push(stage)
|
||||||
|
}
|
||||||
|
pub fn get_stage_mut(&mut self,stage:StageId)->Option<&mut Stage>{
|
||||||
|
self.stages.get_mut(stage.0 as usize)
|
||||||
|
}
|
||||||
pub fn get_spawn_model_id(&self,stage:StageId)->Option<ModelId>{
|
pub fn get_spawn_model_id(&self,stage:StageId)->Option<ModelId>{
|
||||||
self.stages.get(stage.0 as usize).map(|s|s.spawn)
|
self.stages.get(stage.0 as usize).map(|s|s.spawn)
|
||||||
}
|
}
|
||||||
|
pub fn get_zone(&self,model_id:ModelId)->Option<&Zone>{
|
||||||
|
self.zones.get(&model_id)
|
||||||
|
}
|
||||||
|
pub fn get_stage(&self,stage_id:StageId)->Option<&Stage>{
|
||||||
|
self.stages.get(stage_id.0 as usize)
|
||||||
|
}
|
||||||
|
pub fn get_element(&self,model_id:ModelId)->Option<&StageElement>{
|
||||||
|
self.elements.get(&model_id)
|
||||||
|
}
|
||||||
|
pub fn get_jump_limit(&self,model_id:ModelId)->Option<u32>{
|
||||||
|
self.jump_limit.get(&model_id).copied()
|
||||||
|
}
|
||||||
|
//TODO: put this in the SNF
|
||||||
pub fn denormalize_data(&mut self){
|
pub fn denormalize_data(&mut self){
|
||||||
//expand and index normalized data
|
//expand and index normalized data
|
||||||
|
self.zones.insert(self.start,Zone::Start);
|
||||||
for (stage_id,stage) in self.stages.iter().enumerate(){
|
for (stage_id,stage) in self.stages.iter().enumerate(){
|
||||||
self.elements.insert(stage.spawn,StageElement{
|
self.elements.insert(stage.spawn,StageElement{
|
||||||
stage:StageId(stage_id as u32),
|
stage_id:StageId(stage_id as u32),
|
||||||
force:false,
|
force:false,
|
||||||
behaviour:StageElementBehaviour::SpawnAt,
|
behaviour:StageElementBehaviour::SpawnAt,
|
||||||
});
|
});
|
||||||
for &model_id in &stage.ordered_checkpoints{
|
for (_,&model) in &stage.ordered_checkpoints{
|
||||||
self.elements.insert(model_id,StageElement{
|
self.elements.insert(model,StageElement{
|
||||||
stage:StageId(stage_id as u32),
|
stage_id:StageId(stage_id as u32),
|
||||||
force:false,
|
force:false,
|
||||||
behaviour:StageElementBehaviour::Checkpoint,
|
behaviour:StageElementBehaviour::Checkpoint,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
for &model_id in &stage.unordered_checkpoints{
|
for &model in &stage.unordered_checkpoints{
|
||||||
self.elements.insert(model_id,StageElement{
|
self.elements.insert(model,StageElement{
|
||||||
stage:StageId(stage_id as u32),
|
stage_id:StageId(stage_id as u32),
|
||||||
force:false,
|
force:false,
|
||||||
behaviour:StageElementBehaviour::Checkpoint,
|
behaviour:StageElementBehaviour::Checkpoint,
|
||||||
});
|
});
|
||||||
@ -72,19 +195,81 @@ impl Mode{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//this would be nice as a macro
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
pub struct ModeUpdate{
|
||||||
|
zones:HashMap<ModelId,Zone>,
|
||||||
|
stages:HashMap<StageId,StageUpdate>,
|
||||||
|
//mutually exlusive stage element behaviour
|
||||||
|
elements:HashMap<ModelId,StageElement>,
|
||||||
|
jump_limit:HashMap<ModelId,u32>,
|
||||||
|
}
|
||||||
|
impl Updatable<ModeUpdate> for Mode{
|
||||||
|
fn update(&mut self,update:ModeUpdate){
|
||||||
|
self.zones.extend(update.zones);
|
||||||
|
for (stage,stage_update) in update.stages{
|
||||||
|
if let Some(stage)=self.stages.get_mut(stage.0 as usize){
|
||||||
|
stage.update(stage_update);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.elements.extend(update.elements);
|
||||||
|
self.jump_limit.extend(update.jump_limit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl ModeUpdate{
|
||||||
|
pub fn zone(model_id:ModelId,zone:Zone)->Self{
|
||||||
|
let mut mu=Self::default();
|
||||||
|
mu.zones.insert(model_id,zone);
|
||||||
|
mu
|
||||||
|
}
|
||||||
|
pub fn stage(stage_id:StageId,stage_update:StageUpdate)->Self{
|
||||||
|
let mut mu=Self::default();
|
||||||
|
mu.stages.insert(stage_id,stage_update);
|
||||||
|
mu
|
||||||
|
}
|
||||||
|
pub fn element(model_id:ModelId,element:StageElement)->Self{
|
||||||
|
let mut mu=Self::default();
|
||||||
|
mu.elements.insert(model_id,element);
|
||||||
|
mu
|
||||||
|
}
|
||||||
|
pub fn jump_limit(model_id:ModelId,jump_limit:u32)->Self{
|
||||||
|
let mut mu=Self::default();
|
||||||
|
mu.jump_limit.insert(model_id,jump_limit);
|
||||||
|
mu
|
||||||
|
}
|
||||||
|
pub fn map_stage_element_ids<F:Fn(StageId)->StageId>(&mut self,f:F){
|
||||||
|
for (_,stage_element) in self.elements.iter_mut(){
|
||||||
|
stage_element.stage_id=f(stage_element.stage_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default,Clone)]
|
||||||
pub struct Modes{
|
pub struct Modes{
|
||||||
modes:Vec<Mode>,
|
modes:Vec<Mode>,
|
||||||
}
|
}
|
||||||
impl Modes{
|
impl Modes{
|
||||||
pub fn clear(&mut self){
|
pub fn new(modes:Vec<Mode>)->Self{
|
||||||
self.modes.clear();
|
Self{
|
||||||
|
modes,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn push_mode(&mut self,mode:Mode){
|
||||||
|
self.modes.push(mode)
|
||||||
}
|
}
|
||||||
pub fn get_mode(&self,mode:ModeId)->Option<&Mode>{
|
pub fn get_mode(&self,mode:ModeId)->Option<&Mode>{
|
||||||
self.modes.get(mode.0 as usize)
|
self.modes.get(mode.0 as usize)
|
||||||
}
|
}
|
||||||
pub fn insert(&mut self,mode:Mode){
|
}
|
||||||
self.modes.push(mode);
|
pub struct ModesUpdate{
|
||||||
|
modes:HashMap<ModeId,ModeUpdate>,
|
||||||
|
}
|
||||||
|
impl Updatable<ModesUpdate> for Modes{
|
||||||
|
fn update(&mut self,update:ModesUpdate){
|
||||||
|
for (mode,mode_update) in update.modes{
|
||||||
|
if let Some(mode)=self.modes.get_mut(mode.0 as usize){
|
||||||
|
mode.update(mode_update);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,28 +1,29 @@
|
|||||||
const VALVE_SCALE:i64=16;
|
const VALVE_SCALE:Planar64=Planar64::raw(1<<28);// 1/16
|
||||||
|
|
||||||
use crate::integer::{Time,Ratio64,Planar64,Planar64Vec3};
|
use crate::integer::{Time,Ratio64,Planar64,Planar64Vec3};
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct StyleModifiers{
|
pub struct StyleModifiers{
|
||||||
controls_used:u32,//controls which are allowed to pass into gameplay
|
pub controls_used:u32,//controls which are allowed to pass into gameplay
|
||||||
controls_mask:u32,//controls which are masked from control state (e.g. jump in scroll style)
|
pub controls_mask:u32,//controls which are masked from control state (e.g. jump in scroll style)
|
||||||
strafe:Option<StrafeSettings>,
|
pub strafe:Option<StrafeSettings>,
|
||||||
jump_impulse:JumpImpulse,
|
pub jump_impulse:JumpImpulse,
|
||||||
jump_calculation:JumpCalculation,
|
pub jump_calculation:JumpCalculation,
|
||||||
static_friction:Planar64,
|
pub static_friction:Planar64,
|
||||||
kinetic_friction:Planar64,
|
pub kinetic_friction:Planar64,
|
||||||
walk_speed:Planar64,
|
pub walk_speed:Planar64,
|
||||||
walk_accel:Planar64,
|
pub walk_accel:Planar64,
|
||||||
ladder_speed:Planar64,
|
pub ladder_speed:Planar64,
|
||||||
ladder_accel:Planar64,
|
pub ladder_accel:Planar64,
|
||||||
ladder_dot:Planar64,
|
pub ladder_dot:Planar64,
|
||||||
swim_speed:Planar64,
|
pub swim_speed:Planar64,
|
||||||
mass:Planar64,
|
pub mass:Planar64,
|
||||||
mv:Planar64,
|
pub mv:Planar64,
|
||||||
surf_slope:Option<Planar64>,
|
pub surf_slope:Option<Planar64>,
|
||||||
rocket_force:Option<Planar64>,
|
pub rocket_force:Option<Planar64>,
|
||||||
gravity:Planar64Vec3,
|
pub gravity:Planar64Vec3,
|
||||||
hitbox:Hitbox,
|
pub hitbox:Hitbox,
|
||||||
camera_offset:Planar64Vec3,
|
pub camera_offset:Planar64Vec3,
|
||||||
}
|
}
|
||||||
impl std::default::Default for StyleModifiers{
|
impl std::default::Default for StyleModifiers{
|
||||||
fn default()->Self{
|
fn default()->Self{
|
||||||
@ -30,18 +31,18 @@ impl std::default::Default for StyleModifiers{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl StyleModifiers{
|
impl StyleModifiers{
|
||||||
const CONTROL_MOVEFORWARD:u32=0b00000001;
|
pub const CONTROL_MOVEFORWARD:u32=0b00000001;
|
||||||
const CONTROL_MOVEBACK:u32=0b00000010;
|
pub const CONTROL_MOVEBACK:u32=0b00000010;
|
||||||
const CONTROL_MOVERIGHT:u32=0b00000100;
|
pub const CONTROL_MOVERIGHT:u32=0b00000100;
|
||||||
const CONTROL_MOVELEFT:u32=0b00001000;
|
pub const CONTROL_MOVELEFT:u32=0b00001000;
|
||||||
const CONTROL_MOVEUP:u32=0b00010000;
|
pub const CONTROL_MOVEUP:u32=0b00010000;
|
||||||
const CONTROL_MOVEDOWN:u32=0b00100000;
|
pub const CONTROL_MOVEDOWN:u32=0b00100000;
|
||||||
const CONTROL_JUMP:u32=0b01000000;
|
pub const CONTROL_JUMP:u32=0b01000000;
|
||||||
const CONTROL_ZOOM:u32=0b10000000;
|
pub const CONTROL_ZOOM:u32=0b10000000;
|
||||||
|
|
||||||
const RIGHT_DIR:Planar64Vec3=Planar64Vec3::X;
|
pub const RIGHT_DIR:Planar64Vec3=Planar64Vec3::X;
|
||||||
const UP_DIR:Planar64Vec3=Planar64Vec3::Y;
|
pub const UP_DIR:Planar64Vec3=Planar64Vec3::Y;
|
||||||
const FORWARD_DIR:Planar64Vec3=Planar64Vec3::NEG_Z;
|
pub const FORWARD_DIR:Planar64Vec3=Planar64Vec3::NEG_Z;
|
||||||
|
|
||||||
fn neo()->Self{
|
fn neo()->Self{
|
||||||
Self{
|
Self{
|
||||||
@ -72,7 +73,7 @@ impl StyleModifiers{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn roblox_bhop()->Self{
|
pub fn roblox_bhop()->Self{
|
||||||
Self{
|
Self{
|
||||||
controls_used:!0,
|
controls_used:!0,
|
||||||
controls_mask:!0,//&!(Self::CONTROL_MOVEUP|Self::CONTROL_MOVEDOWN),
|
controls_mask:!0,//&!(Self::CONTROL_MOVEUP|Self::CONTROL_MOVEDOWN),
|
||||||
@ -138,13 +139,13 @@ impl StyleModifiers{
|
|||||||
air_accel_limit:Some(Planar64::raw(150<<28)*100),
|
air_accel_limit:Some(Planar64::raw(150<<28)*100),
|
||||||
tick_rate:Ratio64::new(100,Time::ONE_SECOND.nanos() as u64).unwrap(),
|
tick_rate:Ratio64::new(100,Time::ONE_SECOND.nanos() as u64).unwrap(),
|
||||||
}),
|
}),
|
||||||
jump_impulse:JumpImpulse::FromHeight(Planar64::int(52)/VALVE_SCALE),
|
jump_impulse:JumpImpulse::FromHeight(Planar64::int(52)*VALVE_SCALE),
|
||||||
jump_calculation:JumpCalculation::Linear,
|
jump_calculation:JumpCalculation::Linear,
|
||||||
gravity:Planar64Vec3::int(0,-800,0)/VALVE_SCALE,
|
gravity:Planar64Vec3::int(0,-800,0)*VALVE_SCALE,
|
||||||
static_friction:Planar64::int(2),//?
|
static_friction:Planar64::int(2),//?
|
||||||
kinetic_friction:Planar64::int(3),//?
|
kinetic_friction:Planar64::int(3),//?
|
||||||
mass:Planar64::int(1),
|
mass:Planar64::int(1),
|
||||||
mv:Planar64::raw(30)/VALVE_SCALE,
|
mv:Planar64::raw(30)*VALVE_SCALE,
|
||||||
rocket_force:None,
|
rocket_force:None,
|
||||||
walk_speed:Planar64::int(18),//?
|
walk_speed:Planar64::int(18),//?
|
||||||
walk_accel:Planar64::int(90),//?
|
walk_accel:Planar64::int(90),//?
|
||||||
@ -154,7 +155,7 @@ impl StyleModifiers{
|
|||||||
swim_speed:Planar64::int(12),//?
|
swim_speed:Planar64::int(12),//?
|
||||||
surf_slope:Some(Planar64::raw(3787805118)),// normal.y=0.75
|
surf_slope:Some(Planar64::raw(3787805118)),// normal.y=0.75
|
||||||
hitbox:Hitbox::source(),
|
hitbox:Hitbox::source(),
|
||||||
camera_offset:(Planar64Vec3::int(0,64,0)-Planar64Vec3::int(0,73,0)/2)/VALVE_SCALE,
|
camera_offset:(Planar64Vec3::int(0,64,0)-Planar64Vec3::int(0,73,0)/2)*VALVE_SCALE,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn source_surf()->Self{
|
fn source_surf()->Self{
|
||||||
@ -163,16 +164,16 @@ impl StyleModifiers{
|
|||||||
controls_mask:!0,//&!(Self::CONTROL_MOVEUP|Self::CONTROL_MOVEDOWN),
|
controls_mask:!0,//&!(Self::CONTROL_MOVEUP|Self::CONTROL_MOVEDOWN),
|
||||||
strafe:Some(StrafeSettings{
|
strafe:Some(StrafeSettings{
|
||||||
enable:EnableStrafe::Always,
|
enable:EnableStrafe::Always,
|
||||||
air_accel_limit:Some(Planar64::int(150)*66/VALVE_SCALE),
|
air_accel_limit:Some(Planar64::int(150)*66*VALVE_SCALE),
|
||||||
tick_rate:Ratio64::new(66,Time::ONE_SECOND.nanos() as u64).unwrap(),
|
tick_rate:Ratio64::new(66,Time::ONE_SECOND.nanos() as u64).unwrap(),
|
||||||
}),
|
}),
|
||||||
jump_impulse:JumpImpulse::FromHeight(Planar64::int(52)/VALVE_SCALE),
|
jump_impulse:JumpImpulse::FromHeight(Planar64::int(52)*VALVE_SCALE),
|
||||||
jump_calculation:JumpCalculation::Linear,
|
jump_calculation:JumpCalculation::Linear,
|
||||||
gravity:Planar64Vec3::int(0,-800,0)/VALVE_SCALE,
|
gravity:Planar64Vec3::int(0,-800,0)*VALVE_SCALE,
|
||||||
static_friction:Planar64::int(2),//?
|
static_friction:Planar64::int(2),//?
|
||||||
kinetic_friction:Planar64::int(3),//?
|
kinetic_friction:Planar64::int(3),//?
|
||||||
mass:Planar64::int(1),
|
mass:Planar64::int(1),
|
||||||
mv:Planar64::int(30)/VALVE_SCALE,
|
mv:Planar64::int(30)*VALVE_SCALE,
|
||||||
rocket_force:None,
|
rocket_force:None,
|
||||||
walk_speed:Planar64::int(18),//?
|
walk_speed:Planar64::int(18),//?
|
||||||
walk_accel:Planar64::int(90),//?
|
walk_accel:Planar64::int(90),//?
|
||||||
@ -182,7 +183,7 @@ impl StyleModifiers{
|
|||||||
swim_speed:Planar64::int(12),//?
|
swim_speed:Planar64::int(12),//?
|
||||||
surf_slope:Some(Planar64::raw(3787805118)),// normal.y=0.75
|
surf_slope:Some(Planar64::raw(3787805118)),// normal.y=0.75
|
||||||
hitbox:Hitbox::source(),
|
hitbox:Hitbox::source(),
|
||||||
camera_offset:(Planar64Vec3::int(0,64,0)-Planar64Vec3::int(0,73,0)/2)/VALVE_SCALE,
|
camera_offset:(Planar64Vec3::int(0,64,0)-Planar64Vec3::int(0,73,0)/2)*VALVE_SCALE,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn roblox_rocket()->Self{
|
fn roblox_rocket()->Self{
|
||||||
@ -211,13 +212,15 @@ impl StyleModifiers{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum JumpCalculation{
|
#[derive(Clone)]
|
||||||
|
pub enum JumpCalculation{
|
||||||
Capped,//roblox
|
Capped,//roblox
|
||||||
Energy,//new
|
Energy,//new
|
||||||
Linear,//source
|
Linear,//source
|
||||||
}
|
}
|
||||||
|
|
||||||
enum JumpImpulse{
|
#[derive(Clone)]
|
||||||
|
pub enum JumpImpulse{
|
||||||
FromTime(Time),//jump time is invariant across mass and gravity changes
|
FromTime(Time),//jump time is invariant across mass and gravity changes
|
||||||
FromHeight(Planar64),//jump height is invariant across mass and gravity changes
|
FromHeight(Planar64),//jump height is invariant across mass and gravity changes
|
||||||
FromDeltaV(Planar64),//jump velocity is invariant across mass and gravity changes
|
FromDeltaV(Planar64),//jump velocity is invariant across mass and gravity changes
|
||||||
@ -228,20 +231,35 @@ enum JumpImpulse{
|
|||||||
//Energy means it adds energy
|
//Energy means it adds energy
|
||||||
//Linear means it linearly adds on
|
//Linear means it linearly adds on
|
||||||
|
|
||||||
enum EnableStrafe{
|
#[derive(Clone)]
|
||||||
|
pub enum EnableStrafe{
|
||||||
Always,
|
Always,
|
||||||
MaskAny(u32),//hsw, shsw
|
MaskAny(u32),//hsw, shsw
|
||||||
MaskAll(u32),
|
MaskAll(u32),
|
||||||
//Function(Box<dyn Fn(u32)->bool>),
|
//Function(Box<dyn Fn(u32)->bool>),
|
||||||
}
|
}
|
||||||
|
|
||||||
struct StrafeSettings{
|
#[derive(Clone)]
|
||||||
|
pub struct StrafeSettings{
|
||||||
enable:EnableStrafe,
|
enable:EnableStrafe,
|
||||||
air_accel_limit:Option<Planar64>,
|
air_accel_limit:Option<Planar64>,
|
||||||
tick_rate:Ratio64,
|
tick_rate:Ratio64,
|
||||||
}
|
}
|
||||||
|
impl StrafeSettings{
|
||||||
|
pub fn next_tick(&self,time:Time)->Time{
|
||||||
|
Time::from_nanos(self.tick_rate.rhs_div_int(self.tick_rate.mul_int(time.nanos())+1))
|
||||||
|
}
|
||||||
|
pub fn mask(&self,controls:u32)->bool{
|
||||||
|
match self.enable{
|
||||||
|
EnableStrafe::Always=>true,
|
||||||
|
EnableStrafe::MaskAny(mask)=>mask&controls!=0,
|
||||||
|
EnableStrafe::MaskAll(mask)=>mask&controls==mask,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
enum HitboxMesh{
|
#[derive(Clone)]
|
||||||
|
pub enum HitboxMesh{
|
||||||
Box,//source
|
Box,//source
|
||||||
Cylinder,//roblox
|
Cylinder,//roblox
|
||||||
//Sphere,//roblox old physics
|
//Sphere,//roblox old physics
|
||||||
@ -250,9 +268,10 @@ enum HitboxMesh{
|
|||||||
//DualCone,
|
//DualCone,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Hitbox{
|
#[derive(Clone)]
|
||||||
halfsize:Planar64Vec3,
|
pub struct Hitbox{
|
||||||
mesh:HitboxMesh,
|
pub halfsize:Planar64Vec3,
|
||||||
|
pub mesh:HitboxMesh,
|
||||||
}
|
}
|
||||||
impl Hitbox{
|
impl Hitbox{
|
||||||
fn roblox()->Self{
|
fn roblox()->Self{
|
||||||
@ -263,7 +282,7 @@ impl Hitbox{
|
|||||||
}
|
}
|
||||||
fn source()->Self{
|
fn source()->Self{
|
||||||
Self{
|
Self{
|
||||||
halfsize:Planar64Vec3::raw(33,73,33)/2/VALVE_SCALE,
|
halfsize:Planar64Vec3::raw(33,73,33)/2*VALVE_SCALE,
|
||||||
mesh:HitboxMesh::Box,
|
mesh:HitboxMesh::Box,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -294,9 +294,10 @@ impl std::ops::Mul<i64> for Ratio64Vec2{
|
|||||||
pub struct Angle32(i32);
|
pub struct Angle32(i32);
|
||||||
impl Angle32{
|
impl Angle32{
|
||||||
pub const FRAC_PI_2:Self=Self(1<<30);
|
pub const FRAC_PI_2:Self=Self(1<<30);
|
||||||
|
pub const NEG_FRAC_PI_2:Self=Self(-1<<30);
|
||||||
pub const PI:Self=Self(-1<<31);
|
pub const PI:Self=Self(-1<<31);
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn wrap_from_i64(theta:i64)->Self{
|
pub const fn wrap_from_i64(theta:i64)->Self{
|
||||||
//take lower bits
|
//take lower bits
|
||||||
//note: this was checked on compiler explorer and compiles to 1 instruction!
|
//note: this was checked on compiler explorer and compiles to 1 instruction!
|
||||||
Self(i32::from_ne_bytes(((theta&((1<<32)-1)) as u32).to_ne_bytes()))
|
Self(i32::from_ne_bytes(((theta&((1<<32)-1)) as u32).to_ne_bytes()))
|
||||||
@ -308,7 +309,7 @@ impl Angle32{
|
|||||||
Self(theta.clamp(i32::MIN as i64,i32::MAX as i64) as i32)
|
Self(theta.clamp(i32::MIN as i64,i32::MAX as i64) as i32)
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn get(&self)->i32{
|
pub const fn get(&self)->i32{
|
||||||
self.0
|
self.0
|
||||||
}
|
}
|
||||||
/// Clamps the value towards the midpoint of the range.
|
/// Clamps the value towards the midpoint of the range.
|
||||||
@ -411,7 +412,7 @@ impl TryFrom<[f32;3]> for Unit32Vec3{
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
///[-1.0,1.0] = [-2^32,2^32]
|
///[-1.0,1.0] = [-2^32,2^32]
|
||||||
#[derive(Clone,Copy,Hash,Eq,Ord,PartialEq,PartialOrd)]
|
#[derive(Clone,Copy,Debug,Hash,Eq,Ord,PartialEq,PartialOrd)]
|
||||||
pub struct Planar64(i64);
|
pub struct Planar64(i64);
|
||||||
impl Planar64{
|
impl Planar64{
|
||||||
pub const ZERO:Self=Self(0);
|
pub const ZERO:Self=Self(0);
|
||||||
@ -579,7 +580,7 @@ impl std::ops::Div<Planar64> for Planar64{
|
|||||||
|
|
||||||
|
|
||||||
///[-1.0,1.0] = [-2^32,2^32]
|
///[-1.0,1.0] = [-2^32,2^32]
|
||||||
#[derive(Clone,Copy,Default,Hash,Eq,PartialEq)]
|
#[derive(Clone,Copy,Debug,Default,Hash,Eq,PartialEq)]
|
||||||
pub struct Planar64Vec3(glam::I64Vec3);
|
pub struct Planar64Vec3(glam::I64Vec3);
|
||||||
impl Planar64Vec3{
|
impl Planar64Vec3{
|
||||||
pub const ZERO:Self=Planar64Vec3(glam::I64Vec3::ZERO);
|
pub const ZERO:Self=Planar64Vec3(glam::I64Vec3::ZERO);
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
pub mod bvh;
|
pub mod bvh;
|
||||||
|
pub mod map;
|
||||||
pub mod aabb;
|
pub mod aabb;
|
||||||
pub mod model;
|
pub mod model;
|
||||||
pub mod zeroes;
|
pub mod zeroes;
|
||||||
pub mod integer;
|
pub mod integer;
|
||||||
|
pub mod updatable;
|
||||||
pub mod instruction;
|
pub mod instruction;
|
||||||
pub mod gameplay_modes;
|
pub mod gameplay_modes;
|
||||||
pub mod gameplay_style;
|
pub mod gameplay_style;
|
||||||
|
13
src/map.rs
Normal file
13
src/map.rs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
use crate::model;
|
||||||
|
use crate::gameplay_modes;
|
||||||
|
use crate::gameplay_attributes;
|
||||||
|
//this is a temporary struct to try to get the code running again
|
||||||
|
//TODO: use snf::map::Region to update the data in physics and graphics instead of this
|
||||||
|
pub struct CompleteMap{
|
||||||
|
pub modes:gameplay_modes::Modes,
|
||||||
|
pub attributes:Vec<gameplay_attributes::CollisionAttributes>,
|
||||||
|
pub meshes:Vec<model::Mesh>,
|
||||||
|
pub models:Vec<model::Model>,
|
||||||
|
//RenderPattern
|
||||||
|
pub render_configs:Vec<model::RenderConfig>,
|
||||||
|
}
|
117
src/model.rs
117
src/model.rs
@ -3,51 +3,126 @@ use crate::gameplay_attributes;
|
|||||||
|
|
||||||
pub type TextureCoordinate=glam::Vec2;
|
pub type TextureCoordinate=glam::Vec2;
|
||||||
pub type Color4=glam::Vec4;
|
pub type Color4=glam::Vec4;
|
||||||
|
#[derive(Clone,Copy,Hash,id::Id,PartialEq,Eq)]
|
||||||
|
pub struct PositionId(u32);
|
||||||
|
#[derive(Clone,Copy,Hash,id::Id,PartialEq,Eq)]
|
||||||
|
pub struct TextureCoordinateId(u32);
|
||||||
|
#[derive(Clone,Copy,Hash,id::Id,PartialEq,Eq)]
|
||||||
|
pub struct NormalId(u32);
|
||||||
|
#[derive(Clone,Copy,Hash,id::Id,PartialEq,Eq)]
|
||||||
|
pub struct ColorId(u32);
|
||||||
#[derive(Clone,Hash,PartialEq,Eq)]
|
#[derive(Clone,Hash,PartialEq,Eq)]
|
||||||
pub struct IndexedVertex{
|
pub struct IndexedVertex{
|
||||||
pub pos:u32,
|
pub pos:PositionId,
|
||||||
pub tex:u32,
|
pub tex:TextureCoordinateId,
|
||||||
pub normal:u32,
|
pub normal:NormalId,
|
||||||
pub color:u32,
|
pub color:ColorId,
|
||||||
}
|
}
|
||||||
|
#[derive(Clone,Copy,Hash,id::Id,PartialEq,Eq)]
|
||||||
pub struct VertexId(u32);
|
pub struct VertexId(u32);
|
||||||
pub struct IndexedVertexList{
|
pub type IndexedVertexList=Vec<VertexId>;
|
||||||
pub vertices:Vec<VertexId>,
|
pub trait PolygonIter{
|
||||||
|
fn polys(&self)->impl Iterator<Item=&[VertexId]>;
|
||||||
}
|
}
|
||||||
pub struct GroupId(u32);
|
pub trait MapVertexId{
|
||||||
pub enum IndexedGroup{
|
fn map_vertex_id<F:Fn(VertexId)->VertexId>(self,f:F)->Self;
|
||||||
PolygonList(Vec<IndexedVertexList>),
|
}
|
||||||
//TriangleStrip(Vec<IndexedVertexList>),
|
pub struct PolygonList(Vec<IndexedVertexList>);
|
||||||
|
impl PolygonList{
|
||||||
|
pub const fn new(list:Vec<IndexedVertexList>)->Self{
|
||||||
|
Self(list)
|
||||||
|
}
|
||||||
|
pub fn extend<T:IntoIterator<Item=IndexedVertexList>>(&mut self,iter:T){
|
||||||
|
self.0.extend(iter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl PolygonIter for PolygonList{
|
||||||
|
fn polys(&self)->impl Iterator<Item=&[VertexId]>{
|
||||||
|
self.0.iter().map(|poly|poly.as_slice())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl MapVertexId for PolygonList{
|
||||||
|
fn map_vertex_id<F:Fn(VertexId)->VertexId>(self,f:F)->Self{
|
||||||
|
Self(self.0.into_iter().map(|ivl|ivl.into_iter().map(&f).collect()).collect())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// pub struct TriangleStrip(IndexedVertexList);
|
||||||
|
// impl PolygonIter for TriangleStrip{
|
||||||
|
// fn polys(&self)->impl Iterator<Item=&[VertexId]>{
|
||||||
|
// self.0.vertices.windows(3).enumerate().map(|(i,s)|if i&0!=0{return s.iter().rev()}else{return s.iter()})
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
#[derive(Clone,Copy,Hash,id::Id,PartialEq,Eq)]
|
||||||
|
pub struct PolygonGroupId(u32);
|
||||||
|
pub enum PolygonGroup{
|
||||||
|
PolygonList(PolygonList),
|
||||||
|
//TriangleStrip(TriangleStrip),
|
||||||
|
}
|
||||||
|
impl PolygonIter for PolygonGroup{
|
||||||
|
fn polys(&self)->impl Iterator<Item=&[VertexId]>{
|
||||||
|
match self{
|
||||||
|
PolygonGroup::PolygonList(list)=>list.polys(),
|
||||||
|
//PolygonGroup::TriangleStrip(strip)=>strip.polys(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl MapVertexId for PolygonGroup{
|
||||||
|
fn map_vertex_id<F:Fn(VertexId)->VertexId>(self,f:F)->Self{
|
||||||
|
match self{
|
||||||
|
PolygonGroup::PolygonList(polys)=>Self::PolygonList(polys.map_vertex_id(f)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// Ah yes, a group of things to render at the same time
|
||||||
|
#[derive(Clone,Copy,Hash,id::Id,Eq,PartialEq)]
|
||||||
|
pub struct TextureId(u32);
|
||||||
|
#[derive(Clone,Copy,Hash,id::Id,Eq,PartialEq)]
|
||||||
|
pub struct RenderConfigId(u32);
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct RenderConfig{
|
||||||
|
pub texture:Option<TextureId>,
|
||||||
|
}
|
||||||
|
impl RenderConfig{
|
||||||
|
pub const fn texture(texture:TextureId)->Self{
|
||||||
|
Self{
|
||||||
|
texture:Some(texture),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
pub struct RenderId(u32);
|
|
||||||
pub struct IndexedGraphicsGroup{
|
pub struct IndexedGraphicsGroup{
|
||||||
//Render pattern material/texture/shader/flat color
|
//Render pattern material/texture/shader/flat color
|
||||||
pub render:RenderId,
|
pub render:RenderConfigId,
|
||||||
pub groups:Vec<GroupId>,
|
pub groups:Vec<PolygonGroupId>,
|
||||||
}
|
}
|
||||||
|
#[derive(Default)]
|
||||||
pub struct IndexedPhysicsGroup{
|
pub struct IndexedPhysicsGroup{
|
||||||
//the polygons in this group are guaranteed to make a closed convex shape
|
//the polygons in this group are guaranteed to make a closed convex shape
|
||||||
pub groups:Vec<GroupId>,
|
pub groups:Vec<PolygonGroupId>,
|
||||||
}
|
}
|
||||||
//This is a superset of PhysicsModel and GraphicsModel
|
//This is a superset of PhysicsModel and GraphicsModel
|
||||||
pub struct IndexedModel{
|
#[derive(Clone,Copy,Hash,id::Id,Eq,PartialEq)]
|
||||||
|
pub struct MeshId(u32);
|
||||||
|
pub struct Mesh{
|
||||||
pub unique_pos:Vec<Planar64Vec3>,//Unit32Vec3
|
pub unique_pos:Vec<Planar64Vec3>,//Unit32Vec3
|
||||||
pub unique_normal:Vec<Planar64Vec3>,//Unit32Vec3
|
pub unique_normal:Vec<Planar64Vec3>,//Unit32Vec3
|
||||||
pub unique_tex:Vec<TextureCoordinate>,
|
pub unique_tex:Vec<TextureCoordinate>,
|
||||||
pub unique_color:Vec<Color4>,
|
pub unique_color:Vec<Color4>,
|
||||||
pub unique_vertices:Vec<IndexedVertex>,
|
pub unique_vertices:Vec<IndexedVertex>,
|
||||||
//groups are constant texture AND convexity slices
|
//polygon groups are constant texture AND convexity slices
|
||||||
pub groups:Vec<IndexedGroup>,
|
//note that this may need to be changed to be a list of individual faces
|
||||||
|
//for submeshes to work since face ids need to be consistent across submeshes
|
||||||
|
//so face == polygon_groups[face_id]
|
||||||
|
pub polygon_groups:Vec<PolygonGroup>,
|
||||||
//graphics indexed (by texture)
|
//graphics indexed (by texture)
|
||||||
pub graphics_sets:Vec<IndexedGraphicsGroup>,
|
pub graphics_groups:Vec<IndexedGraphicsGroup>,
|
||||||
//physics indexed (by convexity)
|
//physics indexed (by convexity)
|
||||||
pub physics_sets:Vec<IndexedPhysicsGroup>,
|
pub physics_groups:Vec<IndexedPhysicsGroup>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone,Copy,Hash,Eq,PartialEq)]
|
#[derive(Debug,Clone,Copy,Hash,id::Id,Eq,PartialEq)]
|
||||||
pub struct ModelId(u32);
|
pub struct ModelId(u32);
|
||||||
pub struct Model{
|
pub struct Model{
|
||||||
pub model:ModelId,
|
pub mesh:MeshId,
|
||||||
pub attributes:gameplay_attributes::CollisionAttributesId,
|
pub attributes:gameplay_attributes::CollisionAttributesId,
|
||||||
pub color:Color4,//transparency is in here
|
pub color:Color4,//transparency is in here
|
||||||
pub transform:Planar64Affine3,
|
pub transform:Planar64Affine3,
|
||||||
|
56
src/updatable.rs
Normal file
56
src/updatable.rs
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
pub trait Updatable<Updater>{
|
||||||
|
fn update(&mut self,update:Updater);
|
||||||
|
}
|
||||||
|
#[derive(Clone,Copy,Hash,Eq,PartialEq)]
|
||||||
|
struct InnerId(u32);
|
||||||
|
#[derive(Clone)]
|
||||||
|
struct Inner{
|
||||||
|
id:InnerId,
|
||||||
|
enabled:bool,
|
||||||
|
}
|
||||||
|
#[derive(Clone,Copy,Hash,Eq,PartialEq)]
|
||||||
|
struct OuterId(u32);
|
||||||
|
struct Outer{
|
||||||
|
id:OuterId,
|
||||||
|
inners:std::collections::HashMap<InnerId,Inner>,
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Update<I,U>{
|
||||||
|
Insert(I),
|
||||||
|
Update(U),
|
||||||
|
Remove
|
||||||
|
}
|
||||||
|
|
||||||
|
struct InnerUpdate{
|
||||||
|
//#[updatable(Update)]
|
||||||
|
enabled:Option<bool>,
|
||||||
|
}
|
||||||
|
struct OuterUpdate{
|
||||||
|
//#[updatable(Insert,Update,Remove)]
|
||||||
|
inners:std::collections::HashMap<InnerId,Update<Inner,InnerUpdate>>,
|
||||||
|
//#[updatable(Update)]
|
||||||
|
//inners:std::collections::HashMap<InnerId,InnerUpdate>,
|
||||||
|
}
|
||||||
|
impl Updatable<InnerUpdate> for Inner{
|
||||||
|
fn update(&mut self,update:InnerUpdate){
|
||||||
|
if let Some(enabled)=update.enabled{
|
||||||
|
self.enabled=enabled;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl Updatable<OuterUpdate> for Outer{
|
||||||
|
fn update(&mut self,update:OuterUpdate){
|
||||||
|
for (id,up) in update.inners{
|
||||||
|
match up{
|
||||||
|
Update::Insert(new_inner)=>self.inners.insert(id,new_inner),
|
||||||
|
Update::Update(inner_update)=>self.inners.get_mut(&id).map(|inner|{
|
||||||
|
let old=inner.clone();
|
||||||
|
inner.update(inner_update);
|
||||||
|
old
|
||||||
|
}),
|
||||||
|
Update::Remove=>self.inners.remove(&id),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//*/
|
Loading…
Reference in New Issue
Block a user