Compare commits
24 Commits
spawn-beha
...
runs
| Author | SHA1 | Date | |
|---|---|---|---|
| db4ba34a42 | |||
| 56ccc4b58b | |||
| 6ce2e64961 | |||
| 1401c7ad13 | |||
| 7b826e11be | |||
| f337c71c5b | |||
| ba00fed9b8 | |||
| 7e91c85822 | |||
| 33aa8d5d9c | |||
| 6cd5234c91 | |||
| 0215df9f96 | |||
| 582009baed | |||
| 0e4489b360 | |||
| 324e0eb69b | |||
| a9f3e61f2b | |||
| db142d125b | |||
| ef922135e6 | |||
| 9aec0e1b52 | |||
| b065f83faf | |||
| 39b202176f | |||
| 093a54c527 | |||
| 45dc9e4bd3 | |||
| f2635be0fb | |||
| 47cdea0c8a |
2
.cargo/config.toml
Normal file
2
.cargo/config.toml
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
[registries.strafesnet]
|
||||||
|
index = "sparse+https://git.itzana.me/api/packages/strafesnet/cargo/"
|
||||||
62
Cargo.lock
generated
62
Cargo.lock
generated
@@ -3,14 +3,68 @@
|
|||||||
version = 3
|
version = 3
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "glam"
|
name = "bitflags"
|
||||||
version = "0.25.0"
|
version = "2.6.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "151665d9be52f9bb40fc7966565d39666f2d1e69233571b71b87791c7e0528b3"
|
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "glam"
|
||||||
|
version = "0.28.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "779ae4bf7e8421cf91c0b3b64e7e8b40b862fba4d393f59150042de7c4965a94"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "id"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "sparse+https://git.itzana.me/api/packages/strafesnet/cargo/"
|
||||||
|
checksum = "2337e7a6c273082b672e377e159d7a168fb51438461b7c4033c79a515dd7a25a"
|
||||||
|
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.2.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
"glam",
|
"glam",
|
||||||
|
"id",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "2.0.52"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b699d15b36d1f02c3e7c69f8ffef53de37aefae075d8488d4ba1a7788d574a07"
|
||||||
|
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"
|
||||||
|
|||||||
10
Cargo.toml
10
Cargo.toml
@@ -1,9 +1,15 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "strafesnet_common"
|
name = "strafesnet_common"
|
||||||
version = "0.1.0"
|
version = "0.2.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
repository = "https://git.itzana.me/StrafesNET/common"
|
||||||
|
license = "MIT OR Apache-2.0"
|
||||||
|
description = "Common types and helpers for Strafe Client associated projects."
|
||||||
|
authors = ["Rhys Lloyd <krakow20@gmail.com>"]
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
glam = "0.25.0"
|
bitflags = "2.6.0"
|
||||||
|
glam = "0.28.0"
|
||||||
|
id = { version = "0.1.0", registry = "strafesnet" }
|
||||||
|
|||||||
13
src/aabb.rs
13
src/aabb.rs
@@ -6,13 +6,22 @@ pub struct Aabb{
|
|||||||
max:Planar64Vec3,
|
max:Planar64Vec3,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Aabb {
|
impl Default for Aabb{
|
||||||
fn default()->Self {
|
fn default()->Self{
|
||||||
Self{min:Planar64Vec3::MAX,max:Planar64Vec3::MIN}
|
Self{min:Planar64Vec3::MAX,max:Planar64Vec3::MIN}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Aabb{
|
impl Aabb{
|
||||||
|
pub const fn new(min:Planar64Vec3,max:Planar64Vec3)->Self{
|
||||||
|
Self{min,max}
|
||||||
|
}
|
||||||
|
pub const fn max(&self)->Planar64Vec3{
|
||||||
|
self.max
|
||||||
|
}
|
||||||
|
pub const fn min(&self)->Planar64Vec3{
|
||||||
|
self.min
|
||||||
|
}
|
||||||
pub fn grow(&mut self,point:Planar64Vec3){
|
pub fn grow(&mut self,point:Planar64Vec3){
|
||||||
self.min=self.min.min(point);
|
self.min=self.min.min(point);
|
||||||
self.max=self.max.max(point);
|
self.max=self.max.max(point);
|
||||||
|
|||||||
120
src/bvh.rs
120
src/bvh.rs
@@ -9,26 +9,32 @@ 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>),
|
pub enum RecursiveContent<R,T>{
|
||||||
Leaf(usize),
|
Branch(Vec<R>),
|
||||||
|
Leaf(T),
|
||||||
}
|
}
|
||||||
impl Default for BvhNodeContent{
|
impl<R,T> Default for RecursiveContent<R,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:RecursiveContent<BvhNode<T>,T>,
|
||||||
|
aabb:Aabb,
|
||||||
|
}
|
||||||
|
pub struct BvhWeightNode<W,T>{
|
||||||
|
content:RecursiveContent<BvhWeightNode<W,T>,T>,
|
||||||
|
weight:W,
|
||||||
aabb:Aabb,
|
aabb:Aabb,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BvhNode{
|
impl<T> 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),
|
RecursiveContent::Leaf(model)=>f(model),
|
||||||
BvhNodeContent::Branch(children)=>for child in children{
|
RecursiveContent::Branch(children)=>for child in children{
|
||||||
//this test could be moved outside the match statement
|
//this test could be moved outside the match statement
|
||||||
//but that would test the root node aabb
|
//but that would test the root node aabb
|
||||||
//you're probably not going to spend a lot of time outside the map,
|
//you're probably not going to spend a lot of time outside the map,
|
||||||
@@ -39,25 +45,72 @@ impl BvhNode{
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pub fn into_visitor<F:FnMut(T)>(self,f:&mut F){
|
||||||
|
match self.content{
|
||||||
|
RecursiveContent::Leaf(model)=>f(model),
|
||||||
|
RecursiveContent::Branch(children)=>for child in children{
|
||||||
|
child.into_visitor(f)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn weigh_contents<W:Copy+std::iter::Sum<W>,F:Fn(&T)->W>(self,f:&F)->BvhWeightNode<W,T>{
|
||||||
|
match self.content{
|
||||||
|
RecursiveContent::Leaf(model)=>BvhWeightNode{
|
||||||
|
weight:f(&model),
|
||||||
|
content:RecursiveContent::Leaf(model),
|
||||||
|
aabb:self.aabb,
|
||||||
|
},
|
||||||
|
RecursiveContent::Branch(children)=>{
|
||||||
|
let branch:Vec<BvhWeightNode<W,T>>=children.into_iter().map(|child|
|
||||||
|
child.weigh_contents(f)
|
||||||
|
).collect();
|
||||||
|
BvhWeightNode{
|
||||||
|
weight:branch.iter().map(|node|node.weight).sum(),
|
||||||
|
content:RecursiveContent::Branch(branch),
|
||||||
|
aabb:self.aabb,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn generate_bvh(boxen:Vec<Aabb>)->BvhNode{
|
impl <W,T> BvhWeightNode<W,T>{
|
||||||
generate_bvh_node(boxen.into_iter().enumerate().collect())
|
pub const fn weight(&self)->&W{
|
||||||
|
&self.weight
|
||||||
|
}
|
||||||
|
pub const fn aabb(&self)->&Aabb{
|
||||||
|
&self.aabb
|
||||||
|
}
|
||||||
|
pub fn into_content(self)->RecursiveContent<BvhWeightNode<W,T>,T>{
|
||||||
|
self.content
|
||||||
|
}
|
||||||
|
pub fn into_visitor<F:FnMut(T)>(self,f:&mut F){
|
||||||
|
match self.content{
|
||||||
|
RecursiveContent::Leaf(model)=>f(model),
|
||||||
|
RecursiveContent::Branch(children)=>for child in children{
|
||||||
|
child.into_visitor(f)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generate_bvh_node(boxen:Vec<(usize,Aabb)>)->BvhNode{
|
pub fn generate_bvh<T>(boxen:Vec<(T,Aabb)>)->BvhNode<T>{
|
||||||
|
generate_bvh_node(boxen,false)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn generate_bvh_node<T>(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);
|
||||||
BvhNode{
|
BvhNode{
|
||||||
content:BvhNodeContent::Leaf(b.0),
|
content:RecursiveContent::Leaf(b.0),
|
||||||
aabb:b.1,
|
aabb:b.1,
|
||||||
}
|
}
|
||||||
}).collect();
|
}).collect();
|
||||||
BvhNode{
|
BvhNode{
|
||||||
content:BvhNodeContent::Branch(nodes),
|
content:RecursiveContent::Branch(nodes),
|
||||||
aabb,
|
aabb,
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
@@ -65,12 +118,12 @@ fn generate_bvh_node(boxen:Vec<(usize,Aabb)>)->BvhNode{
|
|||||||
let mut sort_x=Vec::with_capacity(n);
|
let mut sort_x=Vec::with_capacity(n);
|
||||||
let mut sort_y=Vec::with_capacity(n);
|
let mut sort_y=Vec::with_capacity(n);
|
||||||
let mut sort_z=Vec::with_capacity(n);
|
let mut sort_z=Vec::with_capacity(n);
|
||||||
for (i,aabb) in boxen.iter(){
|
for (i,(_,aabb)) in boxen.iter().enumerate(){
|
||||||
let center=aabb.center();
|
let center=aabb.center();
|
||||||
octant.insert(*i,0);
|
octant.insert(i,0);
|
||||||
sort_x.push((*i,center.x()));
|
sort_x.push((i,center.x()));
|
||||||
sort_y.push((*i,center.y()));
|
sort_y.push((i,center.y()));
|
||||||
sort_z.push((*i,center.z()));
|
sort_z.push((i,center.z()));
|
||||||
}
|
}
|
||||||
sort_x.sort_by(|tup0,tup1|tup0.1.cmp(&tup1.1));
|
sort_x.sort_by(|tup0,tup1|tup0.1.cmp(&tup1.1));
|
||||||
sort_y.sort_by(|tup0,tup1|tup0.1.cmp(&tup1.1));
|
sort_y.sort_by(|tup0,tup1|tup0.1.cmp(&tup1.1));
|
||||||
@@ -97,7 +150,7 @@ fn generate_bvh_node(boxen:Vec<(usize,Aabb)>)->BvhNode{
|
|||||||
//generate lists for unique octant values
|
//generate lists for unique octant values
|
||||||
let mut list_list=Vec::with_capacity(8);
|
let mut list_list=Vec::with_capacity(8);
|
||||||
let mut octant_list=Vec::with_capacity(8);
|
let mut octant_list=Vec::with_capacity(8);
|
||||||
for (i,aabb) in boxen.into_iter(){
|
for (i,(data,aabb)) in boxen.into_iter().enumerate(){
|
||||||
let octant_id=octant[&i];
|
let octant_id=octant[&i];
|
||||||
let list_id=if let Some(list_id)=octant_list.iter().position(|&id|id==octant_id){
|
let list_id=if let Some(list_id)=octant_list.iter().position(|&id|id==octant_id){
|
||||||
list_id
|
list_id
|
||||||
@@ -107,17 +160,22 @@ fn generate_bvh_node(boxen:Vec<(usize,Aabb)>)->BvhNode{
|
|||||||
list_list.push(Vec::new());
|
list_list.push(Vec::new());
|
||||||
list_id
|
list_id
|
||||||
};
|
};
|
||||||
list_list[list_id].push((i,aabb));
|
list_list[list_id].push((data,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:RecursiveContent::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,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
30
src/controls_bitflag.rs
Normal file
30
src/controls_bitflag.rs
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
bitflags::bitflags!{
|
||||||
|
#[derive(Clone,Copy,Debug,Default)]
|
||||||
|
pub struct Controls:u32{
|
||||||
|
const MoveForward=1<<0;
|
||||||
|
const MoveLeft=1<<1;
|
||||||
|
const MoveBackward=1<<2;
|
||||||
|
const MoveRight=1<<3;
|
||||||
|
const MoveUp=1<<4;
|
||||||
|
const MoveDown=1<<5;
|
||||||
|
const LookUp=1<<6;
|
||||||
|
const LookLeft=1<<7;
|
||||||
|
const LookDown=1<<8;
|
||||||
|
const LookRight=1<<9;
|
||||||
|
const Jump=1<<10;
|
||||||
|
const Crouch=1<<11;
|
||||||
|
const Sprint=1<<12;
|
||||||
|
const Zoom=1<<13;
|
||||||
|
const Use=1<<14;//Interact with object
|
||||||
|
const PrimaryAction=1<<15;//LBM/Shoot/Melee
|
||||||
|
const SecondaryAction=1<<16;//RMB/ADS/Block
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl Controls{
|
||||||
|
pub const fn wasd()->Self{
|
||||||
|
Self::MoveForward.union(Self::MoveLeft).union(Self::MoveBackward).union(Self::MoveRight)
|
||||||
|
}
|
||||||
|
pub const fn wasdqe()->Self{
|
||||||
|
Self::MoveForward.union(Self::MoveLeft).union(Self::MoveBackward).union(Self::MoveRight).union(Self::MoveUp).union(Self::MoveDown)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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
|
||||||
@@ -142,8 +146,8 @@ pub enum CollisionAttributes{
|
|||||||
general:GeneralAttributes,
|
general:GeneralAttributes,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
impl std::default::Default for CollisionAttributes{
|
impl CollisionAttributes{
|
||||||
fn default()->Self{
|
pub fn contact_default()->Self{
|
||||||
Self::Contact{
|
Self::Contact{
|
||||||
contacting:ContactingAttributes::default(),
|
contacting:ContactingAttributes::default(),
|
||||||
general:GeneralAttributes::default()
|
general:GeneralAttributes::default()
|
||||||
|
|||||||
@@ -1,15 +1,44 @@
|
|||||||
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::gameplay_attributes;
|
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,
|
||||||
|
jump_limit:Option<u8>,
|
||||||
|
}
|
||||||
|
impl StageElement{
|
||||||
|
#[inline]
|
||||||
|
pub const fn new(stage_id:StageId,force:bool,behaviour:StageElementBehaviour,jump_limit:Option<u8>)->Self{
|
||||||
|
Self{
|
||||||
|
stage_id,
|
||||||
|
force,
|
||||||
|
behaviour,
|
||||||
|
jump_limit,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[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
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
pub const fn jump_limit(&self)->Option<u8>{
|
||||||
|
self.jump_limit
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[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,
|
||||||
@@ -21,86 +50,282 @@ 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.
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum ClipVelocity{
|
#[derive(Clone,Copy,Debug,Hash,id::Id,Eq,PartialEq)]
|
||||||
All,//Set velocity to spawn.velocity
|
pub struct CheckpointId(u32);
|
||||||
Normal,//clip all out-of-plane velocity when spawning (always "top" face normal)
|
impl CheckpointId{
|
||||||
None,//no clipping
|
pub const FIRST:Self=Self(0);
|
||||||
}
|
}
|
||||||
|
#[derive(Clone,Copy,Debug,Hash,id::Id,Eq,PartialEq,Ord,PartialOrd)]
|
||||||
pub struct SpawnBehaviour{
|
|
||||||
set_camera_angles:bool,//set camera angles to spawn direction like source
|
|
||||||
//gain access to a ridiculous amount of velocity targetting options
|
|
||||||
set_velocity:Option<gameplay_attributes::SetTrajectory>,
|
|
||||||
//or just the basics
|
|
||||||
//set_velocity:ClipVelocity,
|
|
||||||
}
|
|
||||||
|
|
||||||
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,
|
||||||
spawn_behaviour:SpawnBehaviour,
|
//open world support lol
|
||||||
//other behaviour models of this stage can have
|
ordered_checkpoints_count:u32,
|
||||||
ordered_checkpoints:Vec<ModelId>,
|
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(
|
||||||
pub enum ZoneBehaviour{
|
spawn:ModelId,
|
||||||
Finish,
|
ordered_checkpoints_count:u32,
|
||||||
Anitcheat,
|
unordered_checkpoints_count:u32,
|
||||||
|
ordered_checkpoints:HashMap<CheckpointId,ModelId>,
|
||||||
|
unordered_checkpoints:HashSet<ModelId>,
|
||||||
|
)->Self{
|
||||||
|
Self{
|
||||||
|
spawn,
|
||||||
|
ordered_checkpoints_count,
|
||||||
|
unordered_checkpoints_count,
|
||||||
|
ordered_checkpoints,
|
||||||
|
unordered_checkpoints,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn empty(spawn:ModelId)->Self{
|
||||||
|
Self{
|
||||||
|
spawn,
|
||||||
|
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 ordered_checkpoints_count(&self)->u32{
|
||||||
|
self.ordered_checkpoints_count
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
pub const fn unordered_checkpoints_count(&self)->u32{
|
||||||
|
self.unordered_checkpoints_count
|
||||||
|
}
|
||||||
|
pub fn into_inner(self)->(HashMap<CheckpointId,ModelId>,HashSet<ModelId>){
|
||||||
|
(self.ordered_checkpoints,self.unordered_checkpoints)
|
||||||
|
}
|
||||||
|
#[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,Debug,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>,
|
|
||||||
}
|
}
|
||||||
impl Mode{
|
impl Mode{
|
||||||
|
pub fn new(
|
||||||
|
style:gameplay_style::StyleModifiers,
|
||||||
|
start:ModelId,
|
||||||
|
zones:HashMap<ModelId,Zone>,
|
||||||
|
stages:Vec<Stage>,
|
||||||
|
elements:HashMap<ModelId,StageElement>,
|
||||||
|
)->Self{
|
||||||
|
Self{
|
||||||
|
style,
|
||||||
|
start,
|
||||||
|
zones,
|
||||||
|
stages,
|
||||||
|
elements,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn empty(style:gameplay_style::StyleModifiers,start:ModelId)->Self{
|
||||||
|
Self{
|
||||||
|
style,
|
||||||
|
start,
|
||||||
|
zones:HashMap::new(),
|
||||||
|
stages:Vec::new(),
|
||||||
|
elements:HashMap::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn into_inner(self)->(
|
||||||
|
gameplay_style::StyleModifiers,
|
||||||
|
ModelId,
|
||||||
|
HashMap<ModelId,Zone>,
|
||||||
|
Vec<Stage>,
|
||||||
|
HashMap<ModelId,StageElement>,
|
||||||
|
){
|
||||||
|
(
|
||||||
|
self.style,
|
||||||
|
self.start,
|
||||||
|
self.zones,
|
||||||
|
self.stages,
|
||||||
|
self.elements,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
//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,
|
||||||
|
jump_limit:None,
|
||||||
});
|
});
|
||||||
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,
|
||||||
|
jump_limit:None,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
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,
|
||||||
|
jump_limit:None,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//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>,
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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 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>,
|
pub modes:Vec<Mode>,
|
||||||
}
|
}
|
||||||
impl Modes{
|
impl Modes{
|
||||||
pub fn clear(&mut self){
|
pub const fn new(modes:Vec<Mode>)->Self{
|
||||||
self.modes.clear();
|
Self{
|
||||||
|
modes,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn into_inner(self)->Vec<Mode>{
|
||||||
|
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,223 +1,53 @@
|
|||||||
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};
|
||||||
|
use crate::controls_bitflag::Controls;
|
||||||
|
|
||||||
|
#[derive(Clone,Debug)]
|
||||||
pub struct StyleModifiers{
|
pub struct StyleModifiers{
|
||||||
controls_used:u32,//controls which are allowed to pass into gameplay
|
//controls which are allowed to pass into gameplay (usually all)
|
||||||
controls_mask:u32,//controls which are masked from control state (e.g. jump in scroll style)
|
pub controls_mask:Controls,
|
||||||
strafe:Option<StrafeSettings>,
|
//controls which are masked from control state (e.g. !jump in scroll style)
|
||||||
jump_impulse:JumpImpulse,
|
pub controls_mask_state:Controls,
|
||||||
jump_calculation:JumpCalculation,
|
//strafing
|
||||||
static_friction:Planar64,
|
pub strafe:Option<StrafeSettings>,
|
||||||
kinetic_friction:Planar64,
|
//player gets a controllable rocket force
|
||||||
walk_speed:Planar64,
|
pub rocket:Option<PropulsionSettings>,
|
||||||
walk_accel:Planar64,
|
//flying
|
||||||
ladder_speed:Planar64,
|
//pub move_type:MoveType::Fly(FlySettings)
|
||||||
ladder_accel:Planar64,
|
//MoveType::Physics(PhysicsSettings) -> PhysicsSettings (strafe,rocket,jump,walk,ladder,swim,gravity)
|
||||||
ladder_dot:Planar64,
|
//jumping is allowed
|
||||||
swim_speed:Planar64,
|
pub jump:Option<JumpSettings>,
|
||||||
mass:Planar64,
|
//standing & walking is allowed
|
||||||
mv:Planar64,
|
pub walk:Option<WalkSettings>,
|
||||||
surf_slope:Option<Planar64>,
|
//laddering is allowed
|
||||||
rocket_force:Option<Planar64>,
|
pub ladder:Option<LadderSettings>,
|
||||||
gravity:Planar64Vec3,
|
//water propulsion
|
||||||
hitbox:Hitbox,
|
pub swim:Option<PropulsionSettings>,
|
||||||
camera_offset:Planar64Vec3,
|
//maximum slope before sloped surfaces become frictionless
|
||||||
|
pub gravity:Planar64Vec3,
|
||||||
|
//hitbox
|
||||||
|
pub hitbox:Hitbox,
|
||||||
|
//camera location relative to the center (0,0,0) of the hitbox
|
||||||
|
pub camera_offset:Planar64Vec3,
|
||||||
|
//unused
|
||||||
|
pub mass:Planar64,
|
||||||
}
|
}
|
||||||
impl std::default::Default for StyleModifiers{
|
impl std::default::Default for StyleModifiers{
|
||||||
fn default()->Self{
|
fn default()->Self{
|
||||||
Self::roblox_bhop()
|
Self::roblox_bhop()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl StyleModifiers{
|
|
||||||
const CONTROL_MOVEFORWARD:u32=0b00000001;
|
|
||||||
const CONTROL_MOVEBACK:u32=0b00000010;
|
|
||||||
const CONTROL_MOVERIGHT:u32=0b00000100;
|
|
||||||
const CONTROL_MOVELEFT:u32=0b00001000;
|
|
||||||
const CONTROL_MOVEUP:u32=0b00010000;
|
|
||||||
const CONTROL_MOVEDOWN:u32=0b00100000;
|
|
||||||
const CONTROL_JUMP:u32=0b01000000;
|
|
||||||
const CONTROL_ZOOM:u32=0b10000000;
|
|
||||||
|
|
||||||
const RIGHT_DIR:Planar64Vec3=Planar64Vec3::X;
|
#[derive(Clone,Debug)]
|
||||||
const UP_DIR:Planar64Vec3=Planar64Vec3::Y;
|
pub enum JumpCalculation{
|
||||||
const FORWARD_DIR:Planar64Vec3=Planar64Vec3::NEG_Z;
|
|
||||||
|
|
||||||
fn neo()->Self{
|
|
||||||
Self{
|
|
||||||
controls_used:!0,
|
|
||||||
controls_mask:!0,//&!(Self::CONTROL_MOVEUP|Self::CONTROL_MOVEDOWN),
|
|
||||||
strafe:Some(StrafeSettings{
|
|
||||||
enable:EnableStrafe::Always,
|
|
||||||
air_accel_limit:None,
|
|
||||||
tick_rate:Ratio64::new(64,Time::ONE_SECOND.nanos() as u64).unwrap(),
|
|
||||||
}),
|
|
||||||
jump_impulse:JumpImpulse::FromEnergy(Planar64::int(512)),
|
|
||||||
jump_calculation:JumpCalculation::Energy,
|
|
||||||
gravity:Planar64Vec3::int(0,-80,0),
|
|
||||||
static_friction:Planar64::int(2),
|
|
||||||
kinetic_friction:Planar64::int(3),//unrealistic: kinetic friction is typically lower than static
|
|
||||||
mass:Planar64::int(1),
|
|
||||||
mv:Planar64::int(3),
|
|
||||||
rocket_force:None,
|
|
||||||
walk_speed:Planar64::int(16),
|
|
||||||
walk_accel:Planar64::int(80),
|
|
||||||
ladder_speed:Planar64::int(16),
|
|
||||||
ladder_accel:Planar64::int(160),
|
|
||||||
ladder_dot:(Planar64::int(1)/2).sqrt(),
|
|
||||||
swim_speed:Planar64::int(12),
|
|
||||||
surf_slope:Some(Planar64::raw(7)/8),
|
|
||||||
hitbox:Hitbox::roblox(),
|
|
||||||
camera_offset:Planar64Vec3::int(0,2,0),//4.5-2.5=2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn roblox_bhop()->Self{
|
|
||||||
Self{
|
|
||||||
controls_used:!0,
|
|
||||||
controls_mask:!0,//&!(Self::CONTROL_MOVEUP|Self::CONTROL_MOVEDOWN),
|
|
||||||
strafe:Some(StrafeSettings{
|
|
||||||
enable:EnableStrafe::Always,
|
|
||||||
air_accel_limit:None,
|
|
||||||
tick_rate:Ratio64::new(100,Time::ONE_SECOND.nanos() as u64).unwrap(),
|
|
||||||
}),
|
|
||||||
jump_impulse:JumpImpulse::FromTime(Time::from_micros(715_588)),
|
|
||||||
jump_calculation:JumpCalculation::Capped,
|
|
||||||
gravity:Planar64Vec3::int(0,-100,0),
|
|
||||||
static_friction:Planar64::int(2),
|
|
||||||
kinetic_friction:Planar64::int(3),//unrealistic: kinetic friction is typically lower than static
|
|
||||||
mass:Planar64::int(1),
|
|
||||||
mv:Planar64::int(27)/10,
|
|
||||||
rocket_force:None,
|
|
||||||
walk_speed:Planar64::int(18),
|
|
||||||
walk_accel:Planar64::int(90),
|
|
||||||
ladder_speed:Planar64::int(18),
|
|
||||||
ladder_accel:Planar64::int(180),
|
|
||||||
ladder_dot:(Planar64::int(1)/2).sqrt(),
|
|
||||||
swim_speed:Planar64::int(12),
|
|
||||||
surf_slope:Some(Planar64::raw(3787805118)),// normal.y=0.75
|
|
||||||
hitbox:Hitbox::roblox(),
|
|
||||||
camera_offset:Planar64Vec3::int(0,2,0),//4.5-2.5=2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn roblox_surf()->Self{
|
|
||||||
Self{
|
|
||||||
controls_used:!0,
|
|
||||||
controls_mask:!0,//&!(Self::CONTROL_MOVEUP|Self::CONTROL_MOVEDOWN),
|
|
||||||
strafe:Some(StrafeSettings{
|
|
||||||
enable:EnableStrafe::Always,
|
|
||||||
air_accel_limit:None,
|
|
||||||
tick_rate:Ratio64::new(100,Time::ONE_SECOND.nanos() as u64).unwrap(),
|
|
||||||
}),
|
|
||||||
jump_impulse:JumpImpulse::FromTime(Time::from_micros(715_588)),
|
|
||||||
jump_calculation:JumpCalculation::Capped,
|
|
||||||
gravity:Planar64Vec3::int(0,-50,0),
|
|
||||||
static_friction:Planar64::int(2),
|
|
||||||
kinetic_friction:Planar64::int(3),//unrealistic: kinetic friction is typically lower than static
|
|
||||||
mass:Planar64::int(1),
|
|
||||||
mv:Planar64::int(27)/10,
|
|
||||||
rocket_force:None,
|
|
||||||
walk_speed:Planar64::int(18),
|
|
||||||
walk_accel:Planar64::int(90),
|
|
||||||
ladder_speed:Planar64::int(18),
|
|
||||||
ladder_accel:Planar64::int(180),
|
|
||||||
ladder_dot:(Planar64::int(1)/2).sqrt(),
|
|
||||||
swim_speed:Planar64::int(12),
|
|
||||||
surf_slope:Some(Planar64::raw(3787805118)),// normal.y=0.75
|
|
||||||
hitbox:Hitbox::roblox(),
|
|
||||||
camera_offset:Planar64Vec3::int(0,2,0),//4.5-2.5=2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn source_bhop()->Self{
|
|
||||||
Self{
|
|
||||||
controls_used:!0,
|
|
||||||
controls_mask:!0,//&!(Self::CONTROL_MOVEUP|Self::CONTROL_MOVEDOWN),
|
|
||||||
strafe:Some(StrafeSettings{
|
|
||||||
enable:EnableStrafe::Always,
|
|
||||||
air_accel_limit:Some(Planar64::raw(150<<28)*100),
|
|
||||||
tick_rate:Ratio64::new(100,Time::ONE_SECOND.nanos() as u64).unwrap(),
|
|
||||||
}),
|
|
||||||
jump_impulse:JumpImpulse::FromHeight(Planar64::int(52)/VALVE_SCALE),
|
|
||||||
jump_calculation:JumpCalculation::Linear,
|
|
||||||
gravity:Planar64Vec3::int(0,-800,0)/VALVE_SCALE,
|
|
||||||
static_friction:Planar64::int(2),//?
|
|
||||||
kinetic_friction:Planar64::int(3),//?
|
|
||||||
mass:Planar64::int(1),
|
|
||||||
mv:Planar64::raw(30)/VALVE_SCALE,
|
|
||||||
rocket_force:None,
|
|
||||||
walk_speed:Planar64::int(18),//?
|
|
||||||
walk_accel:Planar64::int(90),//?
|
|
||||||
ladder_speed:Planar64::int(18),//?
|
|
||||||
ladder_accel:Planar64::int(180),//?
|
|
||||||
ladder_dot:(Planar64::int(1)/2).sqrt(),//?
|
|
||||||
swim_speed:Planar64::int(12),//?
|
|
||||||
surf_slope:Some(Planar64::raw(3787805118)),// normal.y=0.75
|
|
||||||
hitbox:Hitbox::source(),
|
|
||||||
camera_offset:(Planar64Vec3::int(0,64,0)-Planar64Vec3::int(0,73,0)/2)/VALVE_SCALE,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn source_surf()->Self{
|
|
||||||
Self{
|
|
||||||
controls_used:!0,
|
|
||||||
controls_mask:!0,//&!(Self::CONTROL_MOVEUP|Self::CONTROL_MOVEDOWN),
|
|
||||||
strafe:Some(StrafeSettings{
|
|
||||||
enable:EnableStrafe::Always,
|
|
||||||
air_accel_limit:Some(Planar64::int(150)*66/VALVE_SCALE),
|
|
||||||
tick_rate:Ratio64::new(66,Time::ONE_SECOND.nanos() as u64).unwrap(),
|
|
||||||
}),
|
|
||||||
jump_impulse:JumpImpulse::FromHeight(Planar64::int(52)/VALVE_SCALE),
|
|
||||||
jump_calculation:JumpCalculation::Linear,
|
|
||||||
gravity:Planar64Vec3::int(0,-800,0)/VALVE_SCALE,
|
|
||||||
static_friction:Planar64::int(2),//?
|
|
||||||
kinetic_friction:Planar64::int(3),//?
|
|
||||||
mass:Planar64::int(1),
|
|
||||||
mv:Planar64::int(30)/VALVE_SCALE,
|
|
||||||
rocket_force:None,
|
|
||||||
walk_speed:Planar64::int(18),//?
|
|
||||||
walk_accel:Planar64::int(90),//?
|
|
||||||
ladder_speed:Planar64::int(18),//?
|
|
||||||
ladder_accel:Planar64::int(180),//?
|
|
||||||
ladder_dot:(Planar64::int(1)/2).sqrt(),//?
|
|
||||||
swim_speed:Planar64::int(12),//?
|
|
||||||
surf_slope:Some(Planar64::raw(3787805118)),// normal.y=0.75
|
|
||||||
hitbox:Hitbox::source(),
|
|
||||||
camera_offset:(Planar64Vec3::int(0,64,0)-Planar64Vec3::int(0,73,0)/2)/VALVE_SCALE,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn roblox_rocket()->Self{
|
|
||||||
Self{
|
|
||||||
controls_used:!0,
|
|
||||||
controls_mask:!0,
|
|
||||||
strafe:None,
|
|
||||||
jump_impulse:JumpImpulse::FromTime(Time::from_micros(715_588)),
|
|
||||||
jump_calculation:JumpCalculation::Capped,
|
|
||||||
gravity:Planar64Vec3::int(0,-100,0),
|
|
||||||
static_friction:Planar64::int(2),
|
|
||||||
kinetic_friction:Planar64::int(3),//unrealistic: kinetic friction is typically lower than static
|
|
||||||
mass:Planar64::int(1),
|
|
||||||
mv:Planar64::int(27)/10,
|
|
||||||
rocket_force:Some(Planar64::int(200)),
|
|
||||||
walk_speed:Planar64::int(18),
|
|
||||||
walk_accel:Planar64::int(90),
|
|
||||||
ladder_speed:Planar64::int(18),
|
|
||||||
ladder_accel:Planar64::int(180),
|
|
||||||
ladder_dot:(Planar64::int(1)/2).sqrt(),
|
|
||||||
swim_speed:Planar64::int(12),
|
|
||||||
surf_slope:Some(Planar64::raw(3787805118)),// normal.y=0.75
|
|
||||||
hitbox:Hitbox::roblox(),
|
|
||||||
camera_offset:Planar64Vec3::int(0,2,0),//4.5-2.5=2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
enum JumpCalculation{
|
|
||||||
Capped,//roblox
|
Capped,//roblox
|
||||||
Energy,//new
|
Energy,//new
|
||||||
Linear,//source
|
Linear,//source
|
||||||
}
|
}
|
||||||
|
|
||||||
enum JumpImpulse{
|
#[derive(Clone,Debug)]
|
||||||
|
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
|
||||||
@@ -227,21 +57,330 @@ enum JumpImpulse{
|
|||||||
//Capped means it increases the dot to the cap
|
//Capped means it increases the dot to the cap
|
||||||
//Energy means it adds energy
|
//Energy means it adds energy
|
||||||
//Linear means it linearly adds on
|
//Linear means it linearly adds on
|
||||||
|
impl JumpImpulse{
|
||||||
enum EnableStrafe{
|
//fn get_jump_time(&self)->Planar64
|
||||||
Always,
|
//fn get_jump_height(&self)->Planar64
|
||||||
MaskAny(u32),//hsw, shsw
|
//fn get_jump_energy(&self)->Planar64
|
||||||
MaskAll(u32),
|
pub fn get_jump_deltav(&self,gravity:&Planar64Vec3,mass:Planar64)->Planar64{
|
||||||
//Function(Box<dyn Fn(u32)->bool>),
|
//gravity.length() is actually the proper calculation because the jump is always opposite the gravity direction
|
||||||
|
match self{
|
||||||
|
&JumpImpulse::FromTime(time)=>gravity.length()*(time/2),
|
||||||
|
&JumpImpulse::FromHeight(height)=>(gravity.length()*height*2).sqrt(),
|
||||||
|
&JumpImpulse::FromDeltaV(deltav)=>deltav,
|
||||||
|
&JumpImpulse::FromEnergy(energy)=>(energy*2/mass).sqrt(),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct StrafeSettings{
|
#[derive(Clone,Debug)]
|
||||||
enable:EnableStrafe,
|
pub struct ControlsActivation{
|
||||||
|
//allowed keys
|
||||||
|
controls_mask:Controls,
|
||||||
|
//allow strafing only if any of the masked controls are held, eg W|S for shsw
|
||||||
|
controls_intersects:Controls,
|
||||||
|
//allow strafing only if all of the masked controls are held, eg W for hsw, w-only
|
||||||
|
controls_contains:Controls,
|
||||||
|
//Function(Box<dyn Fn(u32)->bool>),
|
||||||
|
}
|
||||||
|
impl ControlsActivation{
|
||||||
|
pub const fn new(
|
||||||
|
controls_mask:Controls,
|
||||||
|
controls_intersects:Controls,
|
||||||
|
controls_contains:Controls,
|
||||||
|
)->Self{
|
||||||
|
Self{
|
||||||
|
controls_mask,
|
||||||
|
controls_intersects,
|
||||||
|
controls_contains,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub const fn controls_mask(&self)->Controls{
|
||||||
|
self.controls_mask
|
||||||
|
}
|
||||||
|
pub const fn controls_intersects(&self)->Controls{
|
||||||
|
self.controls_intersects
|
||||||
|
}
|
||||||
|
pub const fn controls_contains(&self)->Controls{
|
||||||
|
self.controls_contains
|
||||||
|
}
|
||||||
|
pub const fn mask(&self,controls:Controls)->Controls{
|
||||||
|
controls.intersection(self.controls_mask)
|
||||||
|
}
|
||||||
|
pub const fn activates(&self,controls:Controls)->bool{
|
||||||
|
(self.controls_intersects.is_empty()||controls.intersects(self.controls_intersects))
|
||||||
|
&&controls.contains(self.controls_contains)
|
||||||
|
}
|
||||||
|
pub const fn full_3d()->Self{
|
||||||
|
Self{
|
||||||
|
controls_mask:Controls::wasdqe(),
|
||||||
|
controls_intersects:Controls::wasdqe(),
|
||||||
|
controls_contains:Controls::empty(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//classical styles
|
||||||
|
//Normal
|
||||||
|
pub const fn full_2d()->Self{
|
||||||
|
Self{
|
||||||
|
controls_mask:Controls::wasd(),
|
||||||
|
controls_intersects:Controls::wasd(),
|
||||||
|
controls_contains:Controls::empty(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//Sideways
|
||||||
|
pub const fn sideways()->Self{
|
||||||
|
Self{
|
||||||
|
controls_mask:Controls::MoveForward.union(Controls::MoveBackward),
|
||||||
|
controls_intersects:Controls::MoveForward.union(Controls::MoveBackward),
|
||||||
|
controls_contains:Controls::empty(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//Half-Sideways
|
||||||
|
pub const fn half_sideways()->Self{
|
||||||
|
Self{
|
||||||
|
controls_mask:Controls::MoveForward.union(Controls::MoveLeft).union(Controls::MoveRight),
|
||||||
|
controls_intersects:Controls::MoveLeft.union(Controls::MoveRight),
|
||||||
|
controls_contains:Controls::MoveForward,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//Surf Half-Sideways
|
||||||
|
pub const fn surf_half_sideways()->Self{
|
||||||
|
Self{
|
||||||
|
controls_mask:Controls::MoveForward.union(Controls::MoveBackward).union(Controls::MoveLeft).union(Controls::MoveRight),
|
||||||
|
controls_intersects:Controls::MoveForward.union(Controls::MoveBackward),
|
||||||
|
controls_contains:Controls::empty(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//W-Only
|
||||||
|
pub const fn w_only()->Self{
|
||||||
|
Self{
|
||||||
|
controls_mask:Controls::MoveForward,
|
||||||
|
controls_intersects:Controls::empty(),
|
||||||
|
controls_contains:Controls::MoveForward,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//A-Only
|
||||||
|
pub const fn a_only()->Self{
|
||||||
|
Self{
|
||||||
|
controls_mask:Controls::MoveLeft,
|
||||||
|
controls_intersects:Controls::empty(),
|
||||||
|
controls_contains:Controls::MoveLeft,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//Backwards
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone,Debug)]
|
||||||
|
pub struct StrafeSettings{
|
||||||
|
enable:ControlsActivation,
|
||||||
|
mv:Planar64,
|
||||||
air_accel_limit:Option<Planar64>,
|
air_accel_limit:Option<Planar64>,
|
||||||
tick_rate:Ratio64,
|
tick_rate:Ratio64,
|
||||||
}
|
}
|
||||||
|
impl StrafeSettings{
|
||||||
|
pub const fn new(
|
||||||
|
enable:ControlsActivation,
|
||||||
|
mv:Planar64,
|
||||||
|
air_accel_limit:Option<Planar64>,
|
||||||
|
tick_rate:Ratio64,
|
||||||
|
)->Self{
|
||||||
|
Self{enable,mv,air_accel_limit,tick_rate}
|
||||||
|
}
|
||||||
|
pub fn into_inner(self)->(ControlsActivation,Planar64,Option<Planar64>,Ratio64){
|
||||||
|
(self.enable,self.mv,self.air_accel_limit,self.tick_rate)
|
||||||
|
}
|
||||||
|
pub fn tick_velocity(&self,velocity:Planar64Vec3,control_dir:Planar64Vec3)->Option<Planar64Vec3>{
|
||||||
|
let d=velocity.dot(control_dir);
|
||||||
|
match d<self.mv{
|
||||||
|
true=>Some(velocity+control_dir*self.air_accel_limit.map_or(self.mv-d,|limit|limit.min(self.mv-d))),
|
||||||
|
false=>None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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 const fn activates(&self,controls:Controls)->bool{
|
||||||
|
self.enable.activates(controls)
|
||||||
|
}
|
||||||
|
pub const fn mask(&self,controls:Controls)->Controls{
|
||||||
|
self.enable.mask(controls)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
enum HitboxMesh{
|
#[derive(Clone,Debug)]
|
||||||
|
pub struct PropulsionSettings{
|
||||||
|
magnitude:Planar64,
|
||||||
|
}
|
||||||
|
impl PropulsionSettings{
|
||||||
|
pub const fn new(magnitude:Planar64)->Self{
|
||||||
|
Self{magnitude}
|
||||||
|
}
|
||||||
|
pub fn magnitude(&self)->Planar64{
|
||||||
|
self.magnitude
|
||||||
|
}
|
||||||
|
pub fn acceleration(&self,control_dir:Planar64Vec3)->Planar64Vec3{
|
||||||
|
control_dir*self.magnitude
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone,Debug)]
|
||||||
|
pub struct JumpSettings{
|
||||||
|
//information used to calculate jump power
|
||||||
|
impulse:JumpImpulse,
|
||||||
|
//information used to calculate jump behaviour
|
||||||
|
calculation:JumpCalculation,
|
||||||
|
}
|
||||||
|
impl JumpSettings{
|
||||||
|
pub const fn new(
|
||||||
|
impulse:JumpImpulse,
|
||||||
|
calculation:JumpCalculation,
|
||||||
|
)->Self{
|
||||||
|
Self{impulse,calculation}
|
||||||
|
}
|
||||||
|
pub fn into_inner(self)->(JumpImpulse,JumpCalculation){
|
||||||
|
(self.impulse,self.calculation)
|
||||||
|
}
|
||||||
|
pub fn jumped_velocity(&self,style:&StyleModifiers,jump_dir:Planar64Vec3,velocity:Planar64Vec3)->Planar64Vec3{
|
||||||
|
match self.calculation{
|
||||||
|
//roblox style
|
||||||
|
JumpCalculation::Capped=>todo!(),
|
||||||
|
//something different
|
||||||
|
JumpCalculation::Energy=>todo!(),
|
||||||
|
//source style
|
||||||
|
JumpCalculation::Linear=>velocity+jump_dir*(self.impulse.get_jump_deltav(&style.gravity,style.mass)/jump_dir.length()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone,Debug)]
|
||||||
|
pub struct AccelerateSettings{
|
||||||
|
accel:Planar64,
|
||||||
|
topspeed:Planar64,
|
||||||
|
}
|
||||||
|
impl AccelerateSettings{
|
||||||
|
pub const fn new(
|
||||||
|
accel:Planar64,
|
||||||
|
topspeed:Planar64,
|
||||||
|
)->Self{
|
||||||
|
Self{accel,topspeed}
|
||||||
|
}
|
||||||
|
pub const fn accel(&self)->Planar64{
|
||||||
|
self.accel
|
||||||
|
}
|
||||||
|
pub const fn topspeed(&self)->Planar64{
|
||||||
|
self.topspeed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[derive(Clone,Debug)]
|
||||||
|
pub struct WalkSettings{
|
||||||
|
accelerate:AccelerateSettings,
|
||||||
|
static_friction:Planar64,
|
||||||
|
kinetic_friction:Planar64,
|
||||||
|
//if a surf slope angle does not exist, then everything is slippery and walking is impossible
|
||||||
|
surf_dot:Planar64,//surf_dot<n.dot(up)/n.length()
|
||||||
|
}
|
||||||
|
impl WalkSettings{
|
||||||
|
pub const fn new(
|
||||||
|
accelerate:AccelerateSettings,
|
||||||
|
static_friction:Planar64,
|
||||||
|
kinetic_friction:Planar64,
|
||||||
|
surf_dot:Planar64,
|
||||||
|
)->Self{
|
||||||
|
Self{accelerate,static_friction,kinetic_friction,surf_dot}
|
||||||
|
}
|
||||||
|
pub fn into_inner(self)->(AccelerateSettings,Planar64,Planar64,Planar64){
|
||||||
|
(self.accelerate,self.static_friction,self.kinetic_friction,self.surf_dot)
|
||||||
|
}
|
||||||
|
pub fn accel(&self,target_diff:Planar64Vec3,gravity:Planar64Vec3)->Planar64{
|
||||||
|
//TODO: fallible walk accel
|
||||||
|
let diff_len=target_diff.length();
|
||||||
|
let friction=if diff_len<self.accelerate.topspeed{
|
||||||
|
self.static_friction
|
||||||
|
}else{
|
||||||
|
self.kinetic_friction
|
||||||
|
};
|
||||||
|
self.accelerate.accel.min(-Planar64Vec3::Y.dot(gravity)*friction)
|
||||||
|
}
|
||||||
|
pub fn get_walk_target_velocity(&self,control_dir:Planar64Vec3,normal:Planar64Vec3)->Planar64Vec3{
|
||||||
|
if control_dir==Planar64Vec3::ZERO{
|
||||||
|
return control_dir;
|
||||||
|
}
|
||||||
|
let n=normal.length();
|
||||||
|
let m=control_dir.length();
|
||||||
|
let d=normal.dot(control_dir)/m;
|
||||||
|
if d<n{
|
||||||
|
let cr=normal.cross(control_dir);
|
||||||
|
if cr==Planar64Vec3::ZERO{
|
||||||
|
Planar64Vec3::ZERO
|
||||||
|
}else{
|
||||||
|
cr.cross(normal)*(self.accelerate.topspeed/(n*(n*n-d*d).sqrt()*m))
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
Planar64Vec3::ZERO
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn is_slope_walkable(&self,normal:Planar64Vec3,up:Planar64Vec3)->bool{
|
||||||
|
//normal is not guaranteed to be unit length
|
||||||
|
let ny=normal.dot(up);
|
||||||
|
let h=normal.length();
|
||||||
|
//remember this is a normal vector
|
||||||
|
Planar64::ZERO<ny&&h*self.surf_dot<ny
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone,Debug)]
|
||||||
|
pub struct LadderSettings{
|
||||||
|
accelerate:AccelerateSettings,
|
||||||
|
//how close to pushing directly into/out of the ladder normal
|
||||||
|
//does your input need to be to redirect straight up/down the ladder
|
||||||
|
dot:Planar64,
|
||||||
|
}
|
||||||
|
impl LadderSettings{
|
||||||
|
pub const fn new(
|
||||||
|
accelerate:AccelerateSettings,
|
||||||
|
dot:Planar64,
|
||||||
|
)->Self{
|
||||||
|
Self{accelerate,dot}
|
||||||
|
}
|
||||||
|
pub fn into_inner(self)->(AccelerateSettings,Planar64){
|
||||||
|
(self.accelerate,self.dot)
|
||||||
|
}
|
||||||
|
pub const fn accel(&self,target_diff:Planar64Vec3,gravity:Planar64Vec3)->Planar64{
|
||||||
|
//TODO: fallible ladder accel
|
||||||
|
self.accelerate.accel
|
||||||
|
}
|
||||||
|
pub fn get_ladder_target_velocity(&self,mut control_dir:Planar64Vec3,normal:Planar64Vec3)->Planar64Vec3{
|
||||||
|
if control_dir==Planar64Vec3::ZERO{
|
||||||
|
return control_dir;
|
||||||
|
}
|
||||||
|
let n=normal.length();
|
||||||
|
let m=control_dir.length();
|
||||||
|
let mut d=normal.dot(control_dir)/m;
|
||||||
|
if d< -self.dot*n{
|
||||||
|
control_dir=Planar64Vec3::Y*m;
|
||||||
|
d=normal.y();
|
||||||
|
}else if self.dot*n<d{
|
||||||
|
control_dir=Planar64Vec3::NEG_Y*m;
|
||||||
|
d=-normal.y();
|
||||||
|
}
|
||||||
|
//n=d if you are standing on top of a ladder and press E.
|
||||||
|
//two fixes:
|
||||||
|
//- ladder movement is not allowed on walkable surfaces
|
||||||
|
//- fix the underlying issue
|
||||||
|
if d.get().unsigned_abs()<n.get().unsigned_abs(){
|
||||||
|
let cr=normal.cross(control_dir);
|
||||||
|
if cr==Planar64Vec3::ZERO{
|
||||||
|
Planar64Vec3::ZERO
|
||||||
|
}else{
|
||||||
|
cr.cross(normal)*(self.accelerate.topspeed/(n*(n*n-d*d).sqrt()))
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
Planar64Vec3::ZERO
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone,Debug)]
|
||||||
|
pub enum HitboxMesh{
|
||||||
Box,//source
|
Box,//source
|
||||||
Cylinder,//roblox
|
Cylinder,//roblox
|
||||||
//Sphere,//roblox old physics
|
//Sphere,//roblox old physics
|
||||||
@@ -250,21 +389,206 @@ enum HitboxMesh{
|
|||||||
//DualCone,
|
//DualCone,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Hitbox{
|
#[derive(Clone,Debug)]
|
||||||
halfsize:Planar64Vec3,
|
pub struct Hitbox{
|
||||||
mesh:HitboxMesh,
|
pub halfsize:Planar64Vec3,
|
||||||
|
pub mesh:HitboxMesh,
|
||||||
}
|
}
|
||||||
impl Hitbox{
|
impl Hitbox{
|
||||||
fn roblox()->Self{
|
pub fn roblox()->Self{
|
||||||
Self{
|
Self{
|
||||||
halfsize:Planar64Vec3::int(2,5,2)/2,
|
halfsize:Planar64Vec3::int(2,5,2)/2,
|
||||||
mesh:HitboxMesh::Cylinder,
|
mesh:HitboxMesh::Cylinder,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn source()->Self{
|
pub fn source()->Self{
|
||||||
Self{
|
Self{
|
||||||
halfsize:Planar64Vec3::raw(33,73,33)/2/VALVE_SCALE,
|
halfsize:Planar64Vec3::int(33,73,33)/2*VALVE_SCALE,
|
||||||
mesh:HitboxMesh::Box,
|
mesh:HitboxMesh::Box,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl StyleModifiers{
|
||||||
|
pub const RIGHT_DIR:Planar64Vec3=Planar64Vec3::X;
|
||||||
|
pub const UP_DIR:Planar64Vec3=Planar64Vec3::Y;
|
||||||
|
pub const FORWARD_DIR:Planar64Vec3=Planar64Vec3::NEG_Z;
|
||||||
|
|
||||||
|
pub fn neo()->Self{
|
||||||
|
Self{
|
||||||
|
controls_mask:Controls::all(),
|
||||||
|
controls_mask_state:Controls::all(),
|
||||||
|
strafe:Some(StrafeSettings{
|
||||||
|
enable:ControlsActivation::full_2d(),
|
||||||
|
air_accel_limit:None,
|
||||||
|
mv:Planar64::int(3),
|
||||||
|
tick_rate:Ratio64::new(64,Time::ONE_SECOND.nanos() as u64).unwrap(),
|
||||||
|
}),
|
||||||
|
jump:Some(JumpSettings{
|
||||||
|
impulse:JumpImpulse::FromEnergy(Planar64::int(512)),
|
||||||
|
calculation:JumpCalculation::Energy,
|
||||||
|
}),
|
||||||
|
gravity:Planar64Vec3::int(0,-80,0),
|
||||||
|
mass:Planar64::int(1),
|
||||||
|
rocket:None,
|
||||||
|
walk:Some(WalkSettings{
|
||||||
|
accelerate:AccelerateSettings{
|
||||||
|
topspeed:Planar64::int(16),
|
||||||
|
accel:Planar64::int(80),
|
||||||
|
},
|
||||||
|
static_friction:Planar64::int(2),
|
||||||
|
kinetic_friction:Planar64::int(3),//unrealistic: kinetic friction is typically lower than static
|
||||||
|
surf_dot:Planar64::int(3)/4,
|
||||||
|
}),
|
||||||
|
ladder:Some(LadderSettings{
|
||||||
|
accelerate:AccelerateSettings{
|
||||||
|
topspeed:Planar64::int(16),
|
||||||
|
accel:Planar64::int(160),
|
||||||
|
},
|
||||||
|
dot:(Planar64::int(1)/2).sqrt(),
|
||||||
|
}),
|
||||||
|
swim:Some(PropulsionSettings{
|
||||||
|
magnitude:Planar64::int(12),
|
||||||
|
}),
|
||||||
|
hitbox:Hitbox::roblox(),
|
||||||
|
camera_offset:Planar64Vec3::int(0,2,0),//4.5-2.5=2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn roblox_bhop()->Self{
|
||||||
|
Self{
|
||||||
|
controls_mask:Controls::all(),
|
||||||
|
controls_mask_state:Controls::all(),
|
||||||
|
strafe:Some(StrafeSettings{
|
||||||
|
enable:ControlsActivation::full_2d(),
|
||||||
|
air_accel_limit:None,
|
||||||
|
mv:Planar64::int(27)/10,
|
||||||
|
tick_rate:Ratio64::new(100,Time::ONE_SECOND.nanos() as u64).unwrap(),
|
||||||
|
}),
|
||||||
|
jump:Some(JumpSettings{
|
||||||
|
impulse:JumpImpulse::FromTime(Time::from_micros(715_588)),
|
||||||
|
calculation:JumpCalculation::Linear,//Should be capped
|
||||||
|
}),
|
||||||
|
gravity:Planar64Vec3::int(0,-100,0),
|
||||||
|
mass:Planar64::int(1),
|
||||||
|
rocket:None,
|
||||||
|
walk:Some(WalkSettings{
|
||||||
|
accelerate:AccelerateSettings{
|
||||||
|
topspeed:Planar64::int(18),
|
||||||
|
accel:Planar64::int(90),
|
||||||
|
},
|
||||||
|
static_friction:Planar64::int(2),
|
||||||
|
kinetic_friction:Planar64::int(3),//unrealistic: kinetic friction is typically lower than static
|
||||||
|
surf_dot:Planar64::int(3)/4,// normal.y=0.75
|
||||||
|
}),
|
||||||
|
ladder:Some(LadderSettings{
|
||||||
|
accelerate:AccelerateSettings{
|
||||||
|
topspeed:Planar64::int(18),
|
||||||
|
accel:Planar64::int(180),
|
||||||
|
},
|
||||||
|
dot:(Planar64::int(1)/2).sqrt(),
|
||||||
|
}),
|
||||||
|
swim:Some(PropulsionSettings{
|
||||||
|
magnitude:Planar64::int(12),
|
||||||
|
}),
|
||||||
|
hitbox:Hitbox::roblox(),
|
||||||
|
camera_offset:Planar64Vec3::int(0,2,0),//4.5-2.5=2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn roblox_surf()->Self{
|
||||||
|
Self{
|
||||||
|
gravity:Planar64Vec3::int(0,-50,0),
|
||||||
|
..Self::roblox_bhop()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn roblox_rocket()->Self{
|
||||||
|
Self{
|
||||||
|
strafe:None,
|
||||||
|
rocket:Some(PropulsionSettings{
|
||||||
|
magnitude:Planar64::int(200),
|
||||||
|
}),
|
||||||
|
..Self::roblox_bhop()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn source_bhop()->Self{
|
||||||
|
Self{
|
||||||
|
controls_mask:Controls::all()-Controls::MoveUp-Controls::MoveDown,
|
||||||
|
controls_mask_state:Controls::all(),
|
||||||
|
strafe:Some(StrafeSettings{
|
||||||
|
enable:ControlsActivation::full_2d(),
|
||||||
|
air_accel_limit:Some(Planar64::raw(150<<28)*100),
|
||||||
|
mv:Planar64::raw(30)*VALVE_SCALE,
|
||||||
|
tick_rate:Ratio64::new(100,Time::ONE_SECOND.nanos() as u64).unwrap(),
|
||||||
|
}),
|
||||||
|
jump:Some(JumpSettings{
|
||||||
|
impulse:JumpImpulse::FromHeight(Planar64::int(52)*VALVE_SCALE),
|
||||||
|
calculation:JumpCalculation::Linear,
|
||||||
|
}),
|
||||||
|
gravity:Planar64Vec3::int(0,-800,0)*VALVE_SCALE,
|
||||||
|
mass:Planar64::int(1),
|
||||||
|
rocket:None,
|
||||||
|
walk:Some(WalkSettings{
|
||||||
|
accelerate:AccelerateSettings{
|
||||||
|
topspeed:Planar64::int(18),//?
|
||||||
|
accel:Planar64::int(90),//?
|
||||||
|
},
|
||||||
|
static_friction:Planar64::int(2),//?
|
||||||
|
kinetic_friction:Planar64::int(3),//?
|
||||||
|
surf_dot:Planar64::int(3)/4,// normal.y=0.75
|
||||||
|
}),
|
||||||
|
ladder:Some(LadderSettings{
|
||||||
|
accelerate:AccelerateSettings{
|
||||||
|
topspeed:Planar64::int(18),//?
|
||||||
|
accel:Planar64::int(180),//?
|
||||||
|
},
|
||||||
|
dot:(Planar64::int(1)/2).sqrt(),//?
|
||||||
|
}),
|
||||||
|
swim:Some(PropulsionSettings{
|
||||||
|
magnitude:Planar64::int(12),//?
|
||||||
|
}),
|
||||||
|
hitbox:Hitbox::source(),
|
||||||
|
camera_offset:(Planar64Vec3::int(0,64,0)-Planar64Vec3::int(0,73,0)/2)*VALVE_SCALE,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn source_surf()->Self{
|
||||||
|
Self{
|
||||||
|
controls_mask:Controls::all()-Controls::MoveUp-Controls::MoveDown,
|
||||||
|
controls_mask_state:Controls::all(),
|
||||||
|
strafe:Some(StrafeSettings{
|
||||||
|
enable:ControlsActivation::full_2d(),
|
||||||
|
air_accel_limit:Some(Planar64::int(150)*66*VALVE_SCALE),
|
||||||
|
mv:Planar64::int(30)*VALVE_SCALE,
|
||||||
|
tick_rate:Ratio64::new(66,Time::ONE_SECOND.nanos() as u64).unwrap(),
|
||||||
|
}),
|
||||||
|
jump:Some(JumpSettings{
|
||||||
|
impulse:JumpImpulse::FromHeight(Planar64::int(52)*VALVE_SCALE),
|
||||||
|
calculation:JumpCalculation::Linear,
|
||||||
|
}),
|
||||||
|
gravity:Planar64Vec3::int(0,-800,0)*VALVE_SCALE,
|
||||||
|
mass:Planar64::int(1),
|
||||||
|
rocket:None,
|
||||||
|
walk:Some(WalkSettings{
|
||||||
|
accelerate:AccelerateSettings{
|
||||||
|
topspeed:Planar64::int(18),//?
|
||||||
|
accel:Planar64::int(90),//?
|
||||||
|
},
|
||||||
|
static_friction:Planar64::int(2),//?
|
||||||
|
kinetic_friction:Planar64::int(3),//?
|
||||||
|
surf_dot:Planar64::int(3)/4,// normal.y=0.75
|
||||||
|
}),
|
||||||
|
ladder:Some(LadderSettings{
|
||||||
|
accelerate:AccelerateSettings{
|
||||||
|
topspeed:Planar64::int(18),//?
|
||||||
|
accel:Planar64::int(180),//?
|
||||||
|
},
|
||||||
|
dot:(Planar64::int(1)/2).sqrt(),//?
|
||||||
|
}),
|
||||||
|
swim:Some(PropulsionSettings{
|
||||||
|
magnitude:Planar64::int(12),//?
|
||||||
|
}),
|
||||||
|
hitbox:Hitbox::source(),
|
||||||
|
camera_offset:(Planar64Vec3::int(0,64,0)-Planar64Vec3::int(0,73,0)/2)*VALVE_SCALE,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
113
src/integer.rs
113
src/integer.rs
@@ -10,24 +10,32 @@ impl Time{
|
|||||||
pub const ONE_MICROSECOND:Self=Self(1_000);
|
pub const ONE_MICROSECOND:Self=Self(1_000);
|
||||||
pub const ONE_NANOSECOND:Self=Self(1);
|
pub const ONE_NANOSECOND:Self=Self(1);
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_secs(num:i64)->Self{
|
pub const fn raw(num:i64)->Self{
|
||||||
|
Self(num)
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
pub const fn get(self)->i64{
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
pub const fn from_secs(num:i64)->Self{
|
||||||
Self(Self::ONE_SECOND.0*num)
|
Self(Self::ONE_SECOND.0*num)
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_millis(num:i64)->Self{
|
pub const fn from_millis(num:i64)->Self{
|
||||||
Self(Self::ONE_MILLISECOND.0*num)
|
Self(Self::ONE_MILLISECOND.0*num)
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_micros(num:i64)->Self{
|
pub const fn from_micros(num:i64)->Self{
|
||||||
Self(Self::ONE_MICROSECOND.0*num)
|
Self(Self::ONE_MICROSECOND.0*num)
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_nanos(num:i64)->Self{
|
pub const fn from_nanos(num:i64)->Self{
|
||||||
Self(Self::ONE_NANOSECOND.0*num)
|
Self(Self::ONE_NANOSECOND.0*num)
|
||||||
}
|
}
|
||||||
//should I have checked subtraction? force all time variables to be positive?
|
//should I have checked subtraction? force all time variables to be positive?
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn nanos(&self)->i64{
|
pub const fn nanos(self)->i64{
|
||||||
self.0
|
self.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -91,7 +99,7 @@ const fn gcd(mut a:u64,mut b:u64)->u64{
|
|||||||
};
|
};
|
||||||
a
|
a
|
||||||
}
|
}
|
||||||
#[derive(Clone,Hash)]
|
#[derive(Clone,Copy,Debug,Hash)]
|
||||||
pub struct Ratio64{
|
pub struct Ratio64{
|
||||||
num:i64,
|
num:i64,
|
||||||
den:u64,
|
den:u64,
|
||||||
@@ -109,15 +117,23 @@ impl Ratio64{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn mul_int(&self,rhs:i64)->i64{
|
pub const fn num(self)->i64{
|
||||||
|
self.num
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
pub const fn den(self)->u64{
|
||||||
|
self.den
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
pub const fn mul_int(&self,rhs:i64)->i64{
|
||||||
rhs*self.num/(self.den as i64)
|
rhs*self.num/(self.den as i64)
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn rhs_div_int(&self,rhs:i64)->i64{
|
pub const fn rhs_div_int(&self,rhs:i64)->i64{
|
||||||
rhs*(self.den as i64)/self.num
|
rhs*(self.den as i64)/self.num
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn mul_ref(&self,rhs:&Ratio64)->Ratio64{
|
pub const fn mul_ref(&self,rhs:&Ratio64)->Ratio64{
|
||||||
let (num,den)=(self.num*rhs.num,self.den*rhs.den);
|
let (num,den)=(self.num*rhs.num,self.den*rhs.den);
|
||||||
let d=gcd(num.unsigned_abs(),den);
|
let d=gcd(num.unsigned_abs(),den);
|
||||||
Self{
|
Self{
|
||||||
@@ -259,7 +275,7 @@ impl std::ops::Div<u64> for Ratio64{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[derive(Clone,Hash)]
|
#[derive(Clone,Copy,Debug,Hash)]
|
||||||
pub struct Ratio64Vec2{
|
pub struct Ratio64Vec2{
|
||||||
pub x:Ratio64,
|
pub x:Ratio64,
|
||||||
pub y:Ratio64,
|
pub y:Ratio64,
|
||||||
@@ -267,11 +283,11 @@ pub struct Ratio64Vec2{
|
|||||||
impl Ratio64Vec2{
|
impl Ratio64Vec2{
|
||||||
pub const ONE:Self=Self{x:Ratio64::ONE,y:Ratio64::ONE};
|
pub const ONE:Self=Self{x:Ratio64::ONE,y:Ratio64::ONE};
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new(x:Ratio64,y:Ratio64)->Self{
|
pub const fn new(x:Ratio64,y:Ratio64)->Self{
|
||||||
Self{x,y}
|
Self{x,y}
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn mul_int(&self,rhs:glam::I64Vec2)->glam::I64Vec2{
|
pub const fn mul_int(&self,rhs:glam::I64Vec2)->glam::I64Vec2{
|
||||||
glam::i64vec2(
|
glam::i64vec2(
|
||||||
self.x.mul_int(rhs.x),
|
self.x.mul_int(rhs.x),
|
||||||
self.y.mul_int(rhs.y),
|
self.y.mul_int(rhs.y),
|
||||||
@@ -294,9 +310,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 +325,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 +428,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 +596,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);
|
||||||
@@ -597,23 +614,35 @@ impl Planar64Vec3{
|
|||||||
Self(glam::i64vec3(x.0,y.0,z.0))
|
Self(glam::i64vec3(x.0,y.0,z.0))
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
|
pub const fn get(self)->glam::I64Vec3{
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
pub const fn int(x:i32,y:i32,z:i32)->Self{
|
pub const fn int(x:i32,y:i32,z:i32)->Self{
|
||||||
Self(glam::i64vec3((x as i64)<<32,(y as i64)<<32,(z as i64)<<32))
|
Self(glam::i64vec3((x as i64)<<32,(y as i64)<<32,(z as i64)<<32))
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn raw(x:i64,y:i64,z:i64)->Self{
|
pub const fn raw_xyz(x:i64,y:i64,z:i64)->Self{
|
||||||
Self(glam::i64vec3(x,y,z))
|
Self(glam::i64vec3(x,y,z))
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn x(&self)->Planar64{
|
pub const fn raw_array(xyz:[i64;3])->Self{
|
||||||
|
Self(glam::I64Vec3::from_array(xyz))
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
pub const fn raw(xyz:glam::I64Vec3)->Self{
|
||||||
|
Self(xyz)
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
pub const fn x(&self)->Planar64{
|
||||||
Planar64(self.0.x)
|
Planar64(self.0.x)
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn y(&self)->Planar64{
|
pub const fn y(&self)->Planar64{
|
||||||
Planar64(self.0.y)
|
Planar64(self.0.y)
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn z(&self)->Planar64{
|
pub const fn z(&self)->Planar64{
|
||||||
Planar64(self.0.z)
|
Planar64(self.0.z)
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
@@ -641,7 +670,7 @@ impl Planar64Vec3{
|
|||||||
self.0.cmplt(rhs.0)
|
self.0.cmplt(rhs.0)
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn dot(&self,rhs:Self)->Planar64{
|
pub const fn dot(&self,rhs:Self)->Planar64{
|
||||||
Planar64(((
|
Planar64(((
|
||||||
(self.0.x as i128)*(rhs.0.x as i128)+
|
(self.0.x as i128)*(rhs.0.x as i128)+
|
||||||
(self.0.y as i128)*(rhs.0.y as i128)+
|
(self.0.y as i128)*(rhs.0.y as i128)+
|
||||||
@@ -649,13 +678,13 @@ impl Planar64Vec3{
|
|||||||
)>>32) as i64)
|
)>>32) as i64)
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn dot128(&self,rhs:Self)->i128{
|
pub const fn dot128(&self,rhs:Self)->i128{
|
||||||
(self.0.x as i128)*(rhs.0.x as i128)+
|
(self.0.x as i128)*(rhs.0.x as i128)+
|
||||||
(self.0.y as i128)*(rhs.0.y as i128)+
|
(self.0.y as i128)*(rhs.0.y as i128)+
|
||||||
(self.0.z as i128)*(rhs.0.z as i128)
|
(self.0.z as i128)*(rhs.0.z as i128)
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn cross(&self,rhs:Self)->Planar64Vec3{
|
pub const fn cross(&self,rhs:Self)->Planar64Vec3{
|
||||||
Planar64Vec3(glam::i64vec3(
|
Planar64Vec3(glam::i64vec3(
|
||||||
(((self.0.y as i128)*(rhs.0.z as i128)-(self.0.z as i128)*(rhs.0.y as i128))>>32) as i64,
|
(((self.0.y as i128)*(rhs.0.z as i128)-(self.0.z as i128)*(rhs.0.y as i128))>>32) as i64,
|
||||||
(((self.0.z as i128)*(rhs.0.x as i128)-(self.0.x as i128)*(rhs.0.z as i128))>>32) as i64,
|
(((self.0.z as i128)*(rhs.0.x as i128)-(self.0.x as i128)*(rhs.0.z as i128))>>32) as i64,
|
||||||
@@ -663,12 +692,6 @@ impl Planar64Vec3{
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn walkable(&self,slope:Planar64,up:Self)->bool{
|
|
||||||
let y=self.dot(up);
|
|
||||||
let x=self.cross(up).length();
|
|
||||||
x*slope<y
|
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
pub fn length(&self)->Planar64{
|
pub fn length(&self)->Planar64{
|
||||||
let radicand=(self.0.x as i128)*(self.0.x as i128)+(self.0.y as i128)*(self.0.y as i128)+(self.0.z as i128)*(self.0.z as i128);
|
let radicand=(self.0.x as i128)*(self.0.x as i128)+(self.0.y as i128)*(self.0.y as i128)+(self.0.z as i128)*(self.0.z as i128);
|
||||||
Planar64(unsafe{(radicand as f64).sqrt().to_int_unchecked()})
|
Planar64(unsafe{(radicand as f64).sqrt().to_int_unchecked()})
|
||||||
@@ -829,9 +852,9 @@ impl std::ops::Div<i64> for Planar64Vec3{
|
|||||||
///[-1.0,1.0] = [-2^32,2^32]
|
///[-1.0,1.0] = [-2^32,2^32]
|
||||||
#[derive(Clone,Copy,Hash,Eq,PartialEq)]
|
#[derive(Clone,Copy,Hash,Eq,PartialEq)]
|
||||||
pub struct Planar64Mat3{
|
pub struct Planar64Mat3{
|
||||||
x_axis:Planar64Vec3,
|
pub x_axis:Planar64Vec3,
|
||||||
y_axis:Planar64Vec3,
|
pub y_axis:Planar64Vec3,
|
||||||
z_axis:Planar64Vec3,
|
pub z_axis:Planar64Vec3,
|
||||||
}
|
}
|
||||||
impl Default for Planar64Mat3{
|
impl Default for Planar64Mat3{
|
||||||
#[inline]
|
#[inline]
|
||||||
@@ -845,7 +868,7 @@ impl Default for Planar64Mat3{
|
|||||||
}
|
}
|
||||||
impl Planar64Mat3{
|
impl Planar64Mat3{
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_cols(x_axis:Planar64Vec3,y_axis:Planar64Vec3,z_axis:Planar64Vec3)->Self{
|
pub const fn from_cols(x_axis:Planar64Vec3,y_axis:Planar64Vec3,z_axis:Planar64Vec3)->Self{
|
||||||
Self{
|
Self{
|
||||||
x_axis,
|
x_axis,
|
||||||
y_axis,
|
y_axis,
|
||||||
@@ -862,9 +885,9 @@ impl Planar64Mat3{
|
|||||||
#[inline]
|
#[inline]
|
||||||
pub const fn from_diagonal(diagonal:Planar64Vec3)->Self{
|
pub const fn from_diagonal(diagonal:Planar64Vec3)->Self{
|
||||||
Self{
|
Self{
|
||||||
x_axis:Planar64Vec3::raw(diagonal.0.x,0,0),
|
x_axis:Planar64Vec3::raw_xyz(diagonal.0.x,0,0),
|
||||||
y_axis:Planar64Vec3::raw(0,diagonal.0.y,0),
|
y_axis:Planar64Vec3::raw_xyz(0,diagonal.0.y,0),
|
||||||
z_axis:Planar64Vec3::raw(0,0,diagonal.0.z),
|
z_axis:Planar64Vec3::raw_xyz(0,0,diagonal.0.z),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
@@ -908,25 +931,25 @@ impl Planar64Mat3{
|
|||||||
+self.x_axis.0.x as i128*self.y_axis.0.y as i128*self.z_axis.0.z as i128
|
+self.x_axis.0.x as i128*self.y_axis.0.y as i128*self.z_axis.0.z as i128
|
||||||
)>>32;
|
)>>32;
|
||||||
Self{
|
Self{
|
||||||
x_axis:Planar64Vec3::raw((((-(self.y_axis.0.z as i128*self.z_axis.0.y as i128)+self.y_axis.0.y as i128*self.z_axis.0.z as i128)<<32)/det) as i64,(((self.x_axis.0.z as i128*self.z_axis.0.y as i128-self.x_axis.0.y as i128*self.z_axis.0.z as i128)<<32)/det) as i64,(((-(self.x_axis.0.z as i128*self.y_axis.0.y as i128)+self.x_axis.0.y as i128*self.y_axis.0.z as i128)<<32)/det) as i64),
|
x_axis:Planar64Vec3::raw_xyz((((-(self.y_axis.0.z as i128*self.z_axis.0.y as i128)+self.y_axis.0.y as i128*self.z_axis.0.z as i128)<<32)/det) as i64,(((self.x_axis.0.z as i128*self.z_axis.0.y as i128-self.x_axis.0.y as i128*self.z_axis.0.z as i128)<<32)/det) as i64,(((-(self.x_axis.0.z as i128*self.y_axis.0.y as i128)+self.x_axis.0.y as i128*self.y_axis.0.z as i128)<<32)/det) as i64),
|
||||||
y_axis:Planar64Vec3::raw((((self.y_axis.0.z as i128*self.z_axis.0.x as i128-self.y_axis.0.x as i128*self.z_axis.0.z as i128)<<32)/det) as i64,(((-(self.x_axis.0.z as i128*self.z_axis.0.x as i128)+self.x_axis.0.x as i128*self.z_axis.0.z as i128)<<32)/det) as i64,(((self.x_axis.0.z as i128*self.y_axis.0.x as i128-self.x_axis.0.x as i128*self.y_axis.0.z as i128)<<32)/det) as i64),
|
y_axis:Planar64Vec3::raw_xyz((((self.y_axis.0.z as i128*self.z_axis.0.x as i128-self.y_axis.0.x as i128*self.z_axis.0.z as i128)<<32)/det) as i64,(((-(self.x_axis.0.z as i128*self.z_axis.0.x as i128)+self.x_axis.0.x as i128*self.z_axis.0.z as i128)<<32)/det) as i64,(((self.x_axis.0.z as i128*self.y_axis.0.x as i128-self.x_axis.0.x as i128*self.y_axis.0.z as i128)<<32)/det) as i64),
|
||||||
z_axis:Planar64Vec3::raw((((-(self.y_axis.0.y as i128*self.z_axis.0.x as i128)+self.y_axis.0.x as i128*self.z_axis.0.y as i128)<<32)/det) as i64,(((self.x_axis.0.y as i128*self.z_axis.0.x as i128-self.x_axis.0.x as i128*self.z_axis.0.y as i128)<<32)/det) as i64,(((-(self.x_axis.0.y as i128*self.y_axis.0.x as i128)+self.x_axis.0.x as i128*self.y_axis.0.y as i128)<<32)/det) as i64),
|
z_axis:Planar64Vec3::raw_xyz((((-(self.y_axis.0.y as i128*self.z_axis.0.x as i128)+self.y_axis.0.x as i128*self.z_axis.0.y as i128)<<32)/det) as i64,(((self.x_axis.0.y as i128*self.z_axis.0.x as i128-self.x_axis.0.x as i128*self.z_axis.0.y as i128)<<32)/det) as i64,(((-(self.x_axis.0.y as i128*self.y_axis.0.x as i128)+self.x_axis.0.x as i128*self.y_axis.0.y as i128)<<32)/det) as i64),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn inverse_times_det(&self)->Self{
|
pub const fn inverse_times_det(&self)->Self{
|
||||||
Self{
|
Self{
|
||||||
x_axis:Planar64Vec3::raw(((-(self.y_axis.0.z as i128*self.z_axis.0.y as i128)+self.y_axis.0.y as i128*self.z_axis.0.z as i128)>>32) as i64,((self.x_axis.0.z as i128*self.z_axis.0.y as i128-self.x_axis.0.y as i128*self.z_axis.0.z as i128)>>32) as i64,((-(self.x_axis.0.z as i128*self.y_axis.0.y as i128)+self.x_axis.0.y as i128*self.y_axis.0.z as i128)>>32) as i64),
|
x_axis:Planar64Vec3::raw_xyz(((-(self.y_axis.0.z as i128*self.z_axis.0.y as i128)+self.y_axis.0.y as i128*self.z_axis.0.z as i128)>>32) as i64,((self.x_axis.0.z as i128*self.z_axis.0.y as i128-self.x_axis.0.y as i128*self.z_axis.0.z as i128)>>32) as i64,((-(self.x_axis.0.z as i128*self.y_axis.0.y as i128)+self.x_axis.0.y as i128*self.y_axis.0.z as i128)>>32) as i64),
|
||||||
y_axis:Planar64Vec3::raw(((self.y_axis.0.z as i128*self.z_axis.0.x as i128-self.y_axis.0.x as i128*self.z_axis.0.z as i128)>>32) as i64,((-(self.x_axis.0.z as i128*self.z_axis.0.x as i128)+self.x_axis.0.x as i128*self.z_axis.0.z as i128)>>32) as i64,((self.x_axis.0.z as i128*self.y_axis.0.x as i128-self.x_axis.0.x as i128*self.y_axis.0.z as i128)>>32) as i64),
|
y_axis:Planar64Vec3::raw_xyz(((self.y_axis.0.z as i128*self.z_axis.0.x as i128-self.y_axis.0.x as i128*self.z_axis.0.z as i128)>>32) as i64,((-(self.x_axis.0.z as i128*self.z_axis.0.x as i128)+self.x_axis.0.x as i128*self.z_axis.0.z as i128)>>32) as i64,((self.x_axis.0.z as i128*self.y_axis.0.x as i128-self.x_axis.0.x as i128*self.y_axis.0.z as i128)>>32) as i64),
|
||||||
z_axis:Planar64Vec3::raw(((-(self.y_axis.0.y as i128*self.z_axis.0.x as i128)+self.y_axis.0.x as i128*self.z_axis.0.y as i128)>>32) as i64,((self.x_axis.0.y as i128*self.z_axis.0.x as i128-self.x_axis.0.x as i128*self.z_axis.0.y as i128)>>32) as i64,((-(self.x_axis.0.y as i128*self.y_axis.0.x as i128)+self.x_axis.0.x as i128*self.y_axis.0.y as i128)>>32) as i64),
|
z_axis:Planar64Vec3::raw_xyz(((-(self.y_axis.0.y as i128*self.z_axis.0.x as i128)+self.y_axis.0.x as i128*self.z_axis.0.y as i128)>>32) as i64,((self.x_axis.0.y as i128*self.z_axis.0.x as i128-self.x_axis.0.x as i128*self.z_axis.0.y as i128)>>32) as i64,((-(self.x_axis.0.y as i128*self.y_axis.0.x as i128)+self.x_axis.0.x as i128*self.y_axis.0.y as i128)>>32) as i64),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn transpose(&self)->Self{
|
pub const fn transpose(&self)->Self{
|
||||||
Self{
|
Self{
|
||||||
x_axis:Planar64Vec3::raw(self.x_axis.0.x,self.y_axis.0.x,self.z_axis.0.x),
|
x_axis:Planar64Vec3::raw_xyz(self.x_axis.0.x,self.y_axis.0.x,self.z_axis.0.x),
|
||||||
y_axis:Planar64Vec3::raw(self.x_axis.0.y,self.y_axis.0.y,self.z_axis.0.y),
|
y_axis:Planar64Vec3::raw_xyz(self.x_axis.0.y,self.y_axis.0.y,self.z_axis.0.y),
|
||||||
z_axis:Planar64Vec3::raw(self.x_axis.0.z,self.y_axis.0.z,self.z_axis.0.z),
|
z_axis:Planar64Vec3::raw_xyz(self.x_axis.0.z,self.y_axis.0.z,self.z_axis.0.z),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|||||||
@@ -1,9 +1,13 @@
|
|||||||
pub mod bvh;
|
pub mod bvh;
|
||||||
|
pub mod map;
|
||||||
|
pub mod run;
|
||||||
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_attributes;
|
||||||
pub mod gameplay_modes;
|
pub mod gameplay_modes;
|
||||||
pub mod gameplay_style;
|
pub mod gameplay_style;
|
||||||
pub mod gameplay_attributes;
|
pub mod controls_bitflag;
|
||||||
14
src/map.rs
Normal file
14
src/map.rs
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
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 textures:Vec<Vec<u8>>,
|
||||||
|
pub render_configs:Vec<model::RenderConfig>,
|
||||||
|
}
|
||||||
121
src/model.rs
121
src/model.rs
@@ -3,51 +3,130 @@ 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 RenderId(u32);
|
#[derive(Clone)]
|
||||||
|
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);
|
||||||
|
#[derive(Clone)]
|
||||||
|
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,Debug,Hash,id::Id,Eq,PartialEq)]
|
||||||
|
pub struct TextureId(u32);
|
||||||
|
#[derive(Clone,Copy,Hash,id::Id,Eq,PartialEq)]
|
||||||
|
pub struct RenderConfigId(u32);
|
||||||
|
#[derive(Clone,Copy,Default)]
|
||||||
|
pub struct RenderConfig{
|
||||||
|
pub texture:Option<TextureId>,
|
||||||
|
}
|
||||||
|
impl RenderConfig{
|
||||||
|
pub const fn texture(texture:TextureId)->Self{
|
||||||
|
Self{
|
||||||
|
texture:Some(texture),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[derive(Clone)]
|
||||||
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(Clone,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,Debug,Hash,id::Id,Eq,PartialEq)]
|
||||||
|
pub struct MeshId(u32);
|
||||||
|
#[derive(Clone)]
|
||||||
|
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,
|
||||||
|
|||||||
70
src/run.rs
Normal file
70
src/run.rs
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
use crate::timer::{Timer,Scaled,Error as TimerError};
|
||||||
|
use crate::integer::Time;
|
||||||
|
|
||||||
|
pub enum InvalidationReason{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum Error{
|
||||||
|
AlreadyStarted,
|
||||||
|
NotStarted,
|
||||||
|
AlreadyFinished,
|
||||||
|
}
|
||||||
|
impl std::fmt::Display for Error{
|
||||||
|
fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{
|
||||||
|
write!(f,"{self:?}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl std::error::Error for Error{}
|
||||||
|
|
||||||
|
enum RunState{
|
||||||
|
Created{timer:Timer<Paused>},
|
||||||
|
Started{timer:Timer<Unpaused>},
|
||||||
|
Finished{timer:Timer<Paused>},
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Run{
|
||||||
|
invalidated:Option<InvalidationReason>,
|
||||||
|
created:Time,
|
||||||
|
state:RunState,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Run{
|
||||||
|
pub fn new(created:Time)->Self{
|
||||||
|
Self{
|
||||||
|
timer:Timer::scaled_paused(
|
||||||
|
created,
|
||||||
|
Time::ZERO,
|
||||||
|
crate::integer::Ratio64::ONE,
|
||||||
|
),
|
||||||
|
invalidated:None,
|
||||||
|
created,
|
||||||
|
started:None,
|
||||||
|
finished:None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn start(&mut self,time:Time)->Result<(),Error>{
|
||||||
|
match self.started{
|
||||||
|
Some(_)=>Err(Error::AlreadyStarted),
|
||||||
|
None=>{
|
||||||
|
self.started=Some(time);
|
||||||
|
self.timer.unpause(time).map_err(Error::Timer)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn finish(&mut self,time:Time)->Result<(),Error>{
|
||||||
|
if self.started.is_none(){
|
||||||
|
return Err(Error::NotStarted);
|
||||||
|
}
|
||||||
|
match self.finished{
|
||||||
|
Some(_)=>Err(Error::AlreadyFinished),
|
||||||
|
None=>{
|
||||||
|
self.finished=Some(time);
|
||||||
|
self.timer.pause(time).map_err(Error::Timer)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
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),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//*/
|
||||||
Reference in New Issue
Block a user