diff --git a/src/body.rs b/src/body.rs index d5d4e9c5..bc0bda0f 100644 --- a/src/body.rs +++ b/src/body.rs @@ -451,13 +451,21 @@ pub struct ModelPhysics { } impl ModelPhysics { - pub fn from_model(model:&crate::model::IndexedModel,model_transform:glam::Affine3A) -> Self { + fn from_model_transform_attributes(model:&crate::model::IndexedModel,transform:&glam::Affine3A,attributes:PhysicsCollisionAttributes)->Self{ let mut aabb=Aabb::new(); for indexed_vertex in &model.unique_vertices { - aabb.grow(model_transform.transform_point3(glam::Vec3::from_array(model.unique_pos[indexed_vertex.pos as usize]))); + aabb.grow(transform.transform_point3(glam::Vec3::from_array(model.unique_pos[indexed_vertex.pos as usize]))); } Self{ mesh:aabb, + attributes, + } + } + pub fn from_model(model:&crate::model::IndexedModel,instance:&crate::model::ModelInstance) -> Option { + match &instance.attributes{ + crate::model::CollisionAttributes::Decoration=>None, + crate::model::CollisionAttributes::Contact{contacting,general}=>Some(ModelPhysics::from_model_transform_attributes(model,&instance.transform,PhysicsCollisionAttributes::Contact{contacting:contacting.clone(),general:general.clone()})), + crate::model::CollisionAttributes::Intersect{intersecting,general}=>None,//Some(ModelPhysics::from_model_transform_attributes(model,&instance.transform,PhysicsCollisionAttributes::Intersecting{intersecting,general})), } } pub fn unit_vertices(&self) -> [glam::Vec3;8] { diff --git a/src/load_roblox.rs b/src/load_roblox.rs index efd490a3..a1f5cd01 100644 --- a/src/load_roblox.rs +++ b/src/load_roblox.rs @@ -30,6 +30,64 @@ fn get_texture_refs(dom:&rbx_dom_weak::WeakDom) -> Vec //next class objects } +fn get_attributes(name:&str,can_collide:bool,velocity:glam::Vec3)->crate::model::CollisionAttributes{ + let mut general=crate::model::GameMechanicAttributes::default(); + let mut intersecting=crate::model::IntersectingAttributes::default(); + let mut contacting=crate::model::ContactingAttributes::default(); + match name{ + // "Water"=>intersecting.water=Some(crate::model::IntersectingWater::default()), + // "Accelerator"=>(), + // "MapFinish"=>(), + // "MapAnticheat"=>(), + "Platform"=>general.stage_element=Some(crate::model::GameMechanicStageElement{ + mode_id:0, + stage_id:0, + force:false, + behaviour:crate::model::StageElementBehaviour::Platform, + }), + other=>{ + let regman=lazy_regex::regex!(r"^(Force)?(SpawnAt|Trigger|Teleport|Platform)(\d+)$"); + if let Some(captures) = regman.captures(other) { + general.stage_element=Some(crate::model::GameMechanicStageElement{ + mode_id:0, + stage_id:captures[3].parse::().unwrap(), + force:match captures.get(1){ + Some(m)=>m.as_str()=="Force", + None=>false, + }, + behaviour:match &captures[2]{ + "SpawnAt"=>crate::model::StageElementBehaviour::SpawnAt, + "Trigger"=>crate::model::StageElementBehaviour::Trigger, + "Teleport"=>crate::model::StageElementBehaviour::Teleport, + "Platform"=>crate::model::StageElementBehaviour::Platform, + _=>panic!("regex[2] messed up bad"), + } + }) + + } + } + } + //need some way to skip this + if velocity!=glam::Vec3::ZERO{ + general.booster=Some(crate::model::GameMechanicBooster{velocity}); + } + match can_collide{ + true=>{ + match name{ + //"Bounce"=>(), + "Surf"=>contacting.surf=Some(crate::model::ContactingSurf{}), + "Ladder"=>contacting.ladder=Some(crate::model::ContactingLadder{sticky:true}), + other=>{ + //REGEX!!!! + //Jump# + //WormholeIn# + } + } + return crate::model::CollisionAttributes::Contact{contacting,general}; + }, + false=>return crate::model::CollisionAttributes::Decoration, + } +} struct RobloxAssetId(u64); struct RobloxAssetIdParseErr; @@ -113,6 +171,8 @@ pub fn generate_indexed_models(dom:rbx_dom_weak::WeakDom) -> crate::model::Index //IndexedModelInstances includes textures let mut spawn_point=glam::Vec3::ZERO; + let mut stages=Vec::new(); + let mut indexed_models=Vec::new(); let mut model_id_from_description=std::collections::HashMap::::new(); @@ -127,13 +187,17 @@ pub fn generate_indexed_models(dom:rbx_dom_weak::WeakDom) -> crate::model::Index if let ( Some(rbx_dom_weak::types::Variant::CFrame(cf)), Some(rbx_dom_weak::types::Variant::Vector3(size)), + Some(rbx_dom_weak::types::Variant::Vector3(velocity)), Some(rbx_dom_weak::types::Variant::Float32(transparency)), Some(rbx_dom_weak::types::Variant::Color3uint8(color3)), + Some(rbx_dom_weak::types::Variant::Bool(can_collide)), ) = ( object.properties.get("CFrame"), object.properties.get("Size"), + object.properties.get("Velocity"), object.properties.get("Transparency"), object.properties.get("Color"), + object.properties.get("CanCollide"), ) { let model_transform=glam::Affine3A::from_translation( @@ -333,6 +397,7 @@ pub fn generate_indexed_models(dom:rbx_dom_weak::WeakDom) -> crate::model::Index indexed_models[model_id].instances.push(crate::model::ModelInstance { transform:model_transform, color:glam::vec4(color3.r as f32/255f32, color3.g as f32/255f32, color3.b as f32/255f32, 1.0-*transparency), + attributes:get_attributes(&object.name,*can_collide,glam::vec3(velocity.x,velocity.y,velocity.z)), }); } } @@ -341,5 +406,6 @@ pub fn generate_indexed_models(dom:rbx_dom_weak::WeakDom) -> crate::model::Index textures:asset_id_from_texture_id.iter().map(|t|t.to_string()).collect(), models:indexed_models, spawn_point, + stages, } } diff --git a/src/main.rs b/src/main.rs index 3d8152a1..9d330dfb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -88,7 +88,9 @@ impl GraphicsData { for model in &indexed_models.models{ //make aabb and run vertices to get realistic bounds for model_instance in &model.instances{ - self.physics.models.push(body::ModelPhysics::from_model(&model,model_instance.transform)); + if let Some(model_physics)=body::ModelPhysics::from_model(model,model_instance){ + self.physics.models.push(model_physics); + } } } println!("Physics Objects: {}",self.physics.models.len()); @@ -375,33 +377,46 @@ impl framework::Example for GraphicsData { indexed_models[0].instances.push(ModelInstance{ transform:glam::Affine3A::from_translation(glam::vec3(10.,0.,-10.)), color:glam::Vec4::ONE, + attributes:model::CollisionAttributes::contact(), }); //quad monkeys indexed_models[1].instances.push(ModelInstance{ transform:glam::Affine3A::from_translation(glam::vec3(10.,5.,10.)), color:glam::Vec4::ONE, + attributes:model::CollisionAttributes::contact(), }); indexed_models[1].instances.push(ModelInstance{ transform:glam::Affine3A::from_translation(glam::vec3(20.,5.,10.)), color:glam::vec4(1.0,0.0,0.0,1.0), + attributes:model::CollisionAttributes::contact(), }); indexed_models[1].instances.push(ModelInstance{ transform:glam::Affine3A::from_translation(glam::vec3(10.,5.,20.)), color:glam::vec4(0.0,1.0,0.0,1.0), + attributes:model::CollisionAttributes::contact(), }); indexed_models[1].instances.push(ModelInstance{ transform:glam::Affine3A::from_translation(glam::vec3(20.,5.,20.)), color:glam::vec4(0.0,0.0,1.0,1.0), + attributes:model::CollisionAttributes::contact(), + }); + //decorative monkey + indexed_models[1].instances.push(ModelInstance{ + transform:glam::Affine3A::from_translation(glam::vec3(15.,10.,15.)), + color:glam::vec4(0.5,0.5,0.5,0.5), + attributes:model::CollisionAttributes::Decoration, }); //teapot indexed_models[2].instances.push(ModelInstance{ transform:glam::Affine3A::from_scale_rotation_translation(glam::vec3(0.5, 1.0, 0.2),glam::quat(-0.22248298016985793,-0.839457167990537,-0.05603504040830783,-0.49261857546227916),glam::vec3(-10.,7.,10.)), color:glam::Vec4::ONE, + attributes:model::CollisionAttributes::contact(), }); //ground indexed_models[3].instances.push(ModelInstance{ transform:glam::Affine3A::from_translation(glam::vec3(0.,0.,0.))*glam::Affine3A::from_scale(glam::vec3(160.0, 1.0, 160.0)), color:glam::Vec4::ONE, + attributes:model::CollisionAttributes::contact(), }); let camera_bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { @@ -513,6 +528,7 @@ impl framework::Example for GraphicsData { controls: 0, world:body::WorldState{}, game:body::GameMechanicsState::default(), + stages:Vec::new(), }; //load textures @@ -768,6 +784,7 @@ impl framework::Example for GraphicsData { textures:Vec::new(), models:indexed_models, spawn_point:glam::Vec3::Y*50.0, + stages:Vec::new(), }; graphics.generate_model_physics(&indexed_model_instances); graphics.generate_model_graphics(&device,&queue,indexed_model_instances); diff --git a/src/model.rs b/src/model.rs index 24755876..159c66d0 100644 --- a/src/model.rs +++ b/src/model.rs @@ -56,13 +56,16 @@ pub struct ModelGraphicsInstance{ pub color:glam::Vec4, } pub struct ModelInstance{ + //pub id:u64,//this does not actually help with map fixes resimulating bots, they must always be resimulated pub transform:glam::Affine3A, - pub color:glam::Vec4, + pub color:glam::Vec4,//transparency is in here + pub attributes:CollisionAttributes, } pub struct IndexedModelInstances{ pub textures:Vec,//RenderPattern pub models:Vec, - //object_index for spawns, triggers etc? + //may make this into an object later. + pub stages:Vec, pub spawn_point:glam::Vec3, } //stage description referencing flattened ids is spooky, but the map loading is meant to be deterministic. @@ -170,6 +173,14 @@ pub enum CollisionAttributes{ general:GameMechanicAttributes, }, } +impl CollisionAttributes{ + pub fn contact() -> Self { + Self::Contact{ + contacting:ContactingAttributes::default(), + general:GameMechanicAttributes::default() + } + } +} pub fn generate_indexed_model_list_from_obj(data:obj::ObjData,color:[f32;4]) -> Vec{ let mut unique_vertex_index = std::collections::HashMap::::new();