Compare commits

..

3 Commits

Author SHA1 Message Date
c03a424043 holy refactor 2025-08-26 16:27:17 -07:00
a81e12f1e4 common: Mesh v2 2025-08-26 16:26:26 -07:00
3cbad7869f common: Planar32 2025-08-26 16:25:38 -07:00
5 changed files with 39 additions and 95 deletions

View File

@@ -1,29 +0,0 @@
// Project-local debug tasks
//
// For more documentation on how to configure debug tasks,
// see: https://zed.dev/docs/debugger
[
{
"label": "Strafe Client",
"adapter": "CodeLLDB",
"program": "target/debug/strafe-client",
"args": [
"tools/bhop_maps/5692113331.snfm"
],
"request": "launch",
"build": {
"command": "cargo",
"args": ["build","-p strafe-client"]
}
},
{
"label": "Integration Testing",
"adapter": "CodeLLDB",
"program": "target/release/integration-testing",
"request": "launch",
"build": {
"command": "cargo",
"args": ["test","-p integration-testing"]
}
}
]

View File

@@ -1,8 +1,8 @@
use std::collections::{HashSet,HashMap};
use core::ops::{Bound,RangeBounds};
use strafesnet_common::integer::vec3::Vector3;
use strafesnet_common::model::{self,MeshId,PolygonIter};
use strafesnet_common::integer::{self,vec3,Fixed,Planar64,Planar64Vec3,Ratio};
use strafesnet_common::model::{self,MeshId};
use strafesnet_common::integer::{self,vec3,Fixed,Planar32Vec3,Planar64,Planar64Vec3,Ratio};
use strafesnet_common::physics::Time;
type Body=crate::body::Body<strafesnet_common::physics::TimeInner>;
@@ -74,7 +74,7 @@ struct Face{
dot:Planar64,
}
#[derive(Debug)]
struct Vert(Planar64Vec3);
struct Vert(Planar32Vec3);
pub trait MeshQuery{
type Face:Copy;
type Edge:Copy+DirectedEdge;

View File

@@ -552,6 +552,12 @@ impl TryFrom<[f32;3]> for Unit32Vec3{
}
*/
// placeholder until bnum supports u8
#[derive(Clone,Copy,Debug,Hash,Eq,PartialEq,Ord,PartialOrd)]
pub struct Planar32(i32);
pub type Planar32Vec3=linear_ops::types::Vector3<Planar32>;
pub type Planar32Mat3=linear_ops::types::Matrix3<Planar32>;
pub type Planar64TryFromFloatError=fixed_wide::fixed::FixedFromFloatError;
pub type Planar64=fixed_wide::types::I32F32;
pub type Planar64Vec3=linear_ops::types::Vector3<Planar64>;

View File

@@ -1,6 +1,6 @@
use std::collections::HashMap;
use crate::integer::{Planar64,Planar64Vec3,Planar64Affine3};
use crate::integer::{Planar32Vec3,Planar32Mat3,Planar64Vec3};
use crate::gameplay_attributes;
pub type TextureCoordinate=glam::Vec2;
@@ -22,61 +22,32 @@ pub struct IndexedVertex{
}
#[derive(Clone,Copy,Hash,id::Id,PartialEq,Eq)]
pub struct VertexId(u32);
pub type IndexedVertexList=Vec<VertexId>;
pub trait PolygonIter{
fn polys(&self)->impl Iterator<Item=&[VertexId]>;
}
pub trait MapVertexId{
fn map_vertex_id<F:Fn(VertexId)->VertexId>(self,f:F)->Self;
#[derive(Clone)]
pub struct Triangle([VertexId;3]);
impl Triangle{
pub fn new(verts:[VertexId;3])->Self{
Self(verts)
}
}
#[derive(Clone)]
pub struct PolygonList(Vec<IndexedVertexList>);
impl PolygonList{
pub const fn new(list:Vec<IndexedVertexList>)->Self{
pub struct TriangleList(Vec<Triangle>);
impl TriangleList{
pub const fn new(list:Vec<Triangle>)->Self{
Self(list)
}
pub fn extend<T:IntoIterator<Item=IndexedVertexList>>(&mut self,iter:T){
pub fn extend<T:IntoIterator<Item=Triangle>>(&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),
TriangleList(TriangleList),
//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);
@@ -109,8 +80,8 @@ pub struct IndexedPhysicsGroup{
pub struct MeshId(u32);
#[derive(Clone)]
pub struct Mesh{
pub unique_pos:Vec<Planar64Vec3>,//Unit32Vec3
pub unique_normal:Vec<Planar64Vec3>,//Unit32Vec3
pub unique_pos:Vec<Planar32Vec3>,
pub unique_normal:Vec<Planar32Vec3>,
pub unique_tex:Vec<TextureCoordinate>,
pub unique_color:Vec<Color4>,
pub unique_vertices:Vec<IndexedVertex>,
@@ -127,13 +98,13 @@ pub struct Mesh{
#[derive(Default)]
pub struct MeshBuilder{
unique_pos:Vec<Planar64Vec3>,//Unit32Vec3
unique_normal:Vec<Planar64Vec3>,//Unit32Vec3
unique_pos:Vec<Planar32Vec3>,
unique_normal:Vec<Planar32Vec3>,
unique_tex:Vec<TextureCoordinate>,
unique_color:Vec<Color4>,
unique_vertices:Vec<IndexedVertex>,
pos_id_from:HashMap<Planar64Vec3,PositionId>,//Unit32Vec3
normal_id_from:HashMap<Planar64Vec3,NormalId>,//Unit32Vec3
pos_id_from:HashMap<Planar32Vec3,PositionId>,
normal_id_from:HashMap<Planar32Vec3,NormalId>,
tex_id_from:HashMap<[u32;2],TextureCoordinateId>,
color_id_from:HashMap<[u32;4],ColorId>,
vertex_id_from:HashMap<IndexedVertex,VertexId>,
@@ -167,19 +138,14 @@ impl MeshBuilder{
physics_groups,
}
}
pub fn acquire_pos_id(&mut self,pos:Planar64Vec3)->PositionId{
// Truncate the 16 most precise bits of the vertex positions.
// This allows the normal vectors to exactly represent the face.
// Remove this in Mesh V2
const MASK:Planar64=Planar64::raw(!((1<<16)-1));
let pos=pos.map(|c|c&MASK);
pub fn acquire_pos_id(&mut self,pos:Planar32Vec3)->PositionId{
*self.pos_id_from.entry(pos).or_insert_with(||{
let pos_id=PositionId::new(self.unique_pos.len() as u32);
self.unique_pos.push(pos);
pos_id
})
}
pub fn acquire_normal_id(&mut self,normal:Planar64Vec3)->NormalId{
pub fn acquire_normal_id(&mut self,normal:Planar32Vec3)->NormalId{
*self.normal_id_from.entry(normal).or_insert_with(||{
let normal_id=NormalId::new(self.unique_normal.len() as u32);
self.unique_normal.push(normal);
@@ -217,5 +183,6 @@ pub struct Model{
pub mesh:MeshId,
pub attributes:gameplay_attributes::CollisionAttributesId,
pub color:Color4,//transparency is in here
pub transform:Planar64Affine3,
pub matrix3:Planar32Mat3,
pub translation:Planar64Vec3,
}

View File

@@ -3,7 +3,7 @@ use std::collections::HashMap;
use rbx_mesh::mesh::{Vertex2,Vertex2Truncated};
use strafesnet_common::aabb::Aabb;
use strafesnet_common::integer::vec3;
use strafesnet_common::model::{self,ColorId,IndexedVertex,PolygonGroup,PolygonList,RenderConfigId,VertexId};
use strafesnet_common::model::{self,ColorId,IndexedVertex,NormalId,PolygonGroup,Triangle,TriangleList,PositionId,RenderConfigId,TextureCoordinateId,VertexId};
use crate::loader::MeshWithSize;
@@ -67,8 +67,8 @@ fn ingest_faces2_lods3(
){
//faces have to be split into polygon groups based on lod
polygon_groups.extend(lods.windows(2).map(|lod_pair|
PolygonGroup::PolygonList(PolygonList::new(faces[lod_pair[0].0 as usize..lod_pair[1].0 as usize].iter().map(|rbx_mesh::mesh::Face2(v0,v1,v2)|
vec![vertex_id_map[&v0],vertex_id_map[&v1],vertex_id_map[&v2]]
PolygonGroup::TriangleList(TriangleList::new(faces[lod_pair[0].0 as usize..lod_pair[1].0 as usize].iter().map(|rbx_mesh::mesh::Face2(v0,v1,v2)|
Triangle::new([vertex_id_map[&v0],vertex_id_map[&v1],vertex_id_map[&v2]])
).collect()))
))
}
@@ -90,7 +90,7 @@ pub fn convert(roblox_mesh_bytes:crate::data::RobloxMeshBytes)->Result<MeshWithS
};
Ok(mb.acquire_vertex_id(vertex))
};
Ok(vec![ingest_vertex1(&trip[0])?,ingest_vertex1(&trip[1])?,ingest_vertex1(&trip[2])?])
Ok(Triangle::new([ingest_vertex1(&trip[0])?,ingest_vertex1(&trip[1])?,ingest_vertex1(&trip[2])?))
}).collect::<Result<_,_>>().map_err(Error::Planar64Vec3)?)));
},
rbx_mesh::mesh::Mesh::V2(mesh)=>{
@@ -103,8 +103,8 @@ pub fn convert(roblox_mesh_bytes:crate::data::RobloxMeshBytes)->Result<MeshWithS
rbx_mesh::mesh::SizeOfVertex2::Full=>ingest_vertices2(mesh.vertices,&mut mb),
}?;
//one big happy group for all the faces
polygon_groups.push(PolygonGroup::PolygonList(PolygonList::new(mesh.faces.into_iter().map(|face|
vec![vertex_id_map[&face.0],vertex_id_map[&face.1],vertex_id_map[&face.2]]
polygon_groups.push(PolygonGroup::TriangleList(TriangleList::new(mesh.faces.into_iter().map(|face|
Triangle::new([vertex_id_map[&face.0],vertex_id_map[&face.1],vertex_id_map[&face.2]])
).collect())));
},
rbx_mesh::mesh::Mesh::V3(mesh)=>{