Add proper collision shape for displaced geo.

This commit is contained in:
Joe Ardent 2022-02-21 15:42:44 -08:00
parent 373fc30d56
commit a089f3da46
3 changed files with 72 additions and 27 deletions

View file

@ -1,4 +1,7 @@
use bevy::prelude::*; use bevy::{
prelude::*,
render::mesh::{Indices, VertexAttributeValues},
};
use bevy_rapier3d::{na::Vector3, prelude::*}; use bevy_rapier3d::{na::Vector3, prelude::*};
use crate::{ use crate::{
@ -23,38 +26,71 @@ impl Default for MovementSettings {
fn setup_colliders( fn setup_colliders(
mut commands: Commands, mut commands: Commands,
planet_query: Query<Entity, With<CyberSphere>>, meshes: Res<Assets<Mesh>>,
planet_query: Query<(Entity, &Handle<Mesh>), With<CyberSphere>>,
bike_query: Query<(Entity, &Transform), With<CyberBike>>, bike_query: Query<(Entity, &Transform), With<CyberBike>>,
) { ) {
let planet = planet_query.single(); let (planet, mesh_handle) = planet_query.single();
let mesh = meshes.get(mesh_handle).unwrap();
let mut shape = ColliderShape::ball(PLANET_RADIUS);
let vertices = mesh.attribute(Mesh::ATTRIBUTE_POSITION).unwrap();
if let VertexAttributeValues::Float32x3(verts) = vertices {
if let Some(Indices::U32(indices)) = mesh.indices() {
//let vertices: Vec<Vec3> = verts.iter().map(|v|
// Vec3::from_slice(v)).collect();
let mut idxs = Vec::new();
for idx in indices.chunks_exact(3) {
idxs.push([idx[0], idx[1], idx[2]]);
}
let vertices = verts
.iter()
.map(|p| Point::from_slice(p))
.collect::<Vec<Point<_>>>();
shape = ColliderShape::convex_decomposition(&vertices, &idxs);
}
}
// ok, now attach shit
let pbody = RigidBodyBundle { let pbody = RigidBodyBundle {
body_type: RigidBodyType::Static.into(), body_type: RigidBodyType::Static.into(),
..Default::default() ccd: RigidBodyCcd {
}; ccd_enabled: true,
let pcollide = ColliderBundle { ccd_max_dist: PLANET_RADIUS * 1.1,
shape: ColliderShape::ball(PLANET_RADIUS).into(), ccd_thickness: 0.4,
material: ColliderMaterial {
friction: 0.05,
restitution: 0.01,
..Default::default() ..Default::default()
} }
.into(), .into(),
mass_properties: ColliderMassProps::Density(0.0).into(),
..Default::default() ..Default::default()
}; };
let pcollide = ColliderBundle {
shape: shape.into(),
material: ColliderMaterial {
friction: 0.05,
restitution: 0.00,
..Default::default()
}
.into(),
..Default::default()
};
commands commands
.entity(planet) .entity(planet)
.insert_bundle(pbody) .insert_bundle(pbody)
.insert_bundle(pcollide); .insert_bundle(pcollide);
// bike is the easy part
let (bike, xform) = bike_query.single(); let (bike, xform) = bike_query.single();
setup_bike(bike, xform, &mut commands); setup_bike_collider(bike, xform, &mut commands);
} }
fn setup_bike(bike: Entity, xform: &Transform, commands: &mut Commands) { fn setup_bike_collider(bike: Entity, xform: &Transform, commands: &mut Commands) {
let mut bbody = RigidBodyBundle::default(); let mut bbody = RigidBodyBundle::default();
bbody.damping.angular_damping = 0.7; bbody.damping.angular_damping = 0.8;
bbody.damping.linear_damping = 0.3; bbody.damping.linear_damping = 0.5;
bbody.forces = RigidBodyForces { bbody.forces = RigidBodyForces {
torque: Vec3::ZERO.into(), torque: Vec3::ZERO.into(),
..Default::default() ..Default::default()
@ -62,25 +98,24 @@ fn setup_bike(bike: Entity, xform: &Transform, commands: &mut Commands) {
.into(); .into();
bbody.ccd = RigidBodyCcd { bbody.ccd = RigidBodyCcd {
ccd_enabled: true, ccd_enabled: true,
ccd_max_dist: 2.4,
..Default::default() ..Default::default()
} }
.into(); .into();
// bbody.mass_properties = MassProperties::new(Vec3::ZERO.into(), 0.5,
// Vec3::new(0.0, 0.01, 0.0).into()).into();
let isometry = Isometry::from_parts(xform.translation.into(), xform.rotation.into()); let isometry = Isometry::from_parts(xform.translation.into(), xform.rotation.into());
bbody.position = isometry.into(); bbody.position = isometry.into();
// collider // collider
let shape = ColliderShape::capsule( let shape = ColliderShape::capsule(
Vec3::new(0.0, 0.0, -1.25).into(), Vec3::new(0.0, 0.0, -1.25).into(),
Vec3::new(0.0, 0.0, 1.2).into(), Vec3::new(0.0, 0.0, 1.25).into(),
0.4, 0.4,
); );
let bcollide = ColliderBundle { let bcollide = ColliderBundle {
shape: shape.into(), shape: shape.into(),
mass_properties: ColliderMassProps::Density(0.2).into(), mass_properties: ColliderMassProps::Density(0.4).into(),
material: ColliderMaterial { material: ColliderMaterial {
friction: 0.0, friction: 0.0,
restitution: 0.05, restitution: 0.01,
..Default::default() ..Default::default()
} }
.into(), .into(),
@ -144,7 +179,10 @@ impl Plugin for CyberActionPlugin {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
app.init_resource::<MovementSettings>() app.init_resource::<MovementSettings>()
.add_plugin(RapierPhysicsPlugin::<NoUserData>::default()) .add_plugin(RapierPhysicsPlugin::<NoUserData>::default())
.add_startup_system_to_stage(StartupStage::PostStartup, setup_colliders) .add_startup_system_to_stage(
StartupStage::PostStartup,
setup_colliders.label("colliders"),
)
.add_system(gravity) .add_system(gravity)
.add_system(falling_cat.label("cat")) .add_system(falling_cat.label("cat"))
.add_system(update_forces.after("cat")); .add_system(update_forces.after("cat"));

View file

@ -8,8 +8,8 @@ use wgpu::PrimitiveTopology;
use crate::Label; use crate::Label;
pub const PLANET_RADIUS: f32 = 860.0; pub const PLANET_RADIUS: f32 = 1200.0;
pub(crate) const SPAWN_ALTITUDE: f32 = PLANET_RADIUS + 2.0; pub(crate) const SPAWN_ALTITUDE: f32 = PLANET_RADIUS * 1.095;
#[derive(Component, Debug)] #[derive(Component, Debug)]
pub struct CyberBike; pub struct CyberBike;
@ -95,7 +95,7 @@ fn gen_planet(sphere: Icosphere) -> Mesh {
.raw_points() .raw_points()
.iter() .iter()
.map(|&p| { .map(|&p| {
let disp = noise.get(p.as_dvec3().into()) as f32 * 0.07; let disp = noise.get(p.as_dvec3().into()) as f32 * 0.09;
let pt = p + disp; let pt = p + disp;
pt.into() pt.into()
}) })

View file

@ -16,13 +16,13 @@ pub const BISEXY_COLOR: Color = Color::hsla(292.0, 0.9, 0.60, 1.1);
fn wireframe_planet( fn wireframe_planet(
mut commands: Commands, mut commands: Commands,
meshes: Res<Assets<Mesh>>, mut meshes: ResMut<Assets<Mesh>>,
mut polylines: ResMut<Assets<Polyline>>, mut polylines: ResMut<Assets<Polyline>>,
mut polymats: ResMut<Assets<PolylineMaterial>>, mut polymats: ResMut<Assets<PolylineMaterial>>,
query: Query<&Handle<Mesh>, With<CyberSphere>>, query: Query<&Handle<Mesh>, With<CyberSphere>>,
) { ) {
let handle = query.single(); let handle = query.single();
let mesh = meshes.get(handle).unwrap(); let mesh = meshes.get_mut(handle).unwrap();
let vertices = mesh.attribute(Mesh::ATTRIBUTE_POSITION).unwrap(); let vertices = mesh.attribute(Mesh::ATTRIBUTE_POSITION).unwrap();
let mut pts = Vec::with_capacity(vertices.len()); let mut pts = Vec::with_capacity(vertices.len());
@ -46,6 +46,10 @@ fn wireframe_planet(
} }
} }
// don't need the indices anymore
mesh.duplicate_vertices();
mesh.compute_flat_normals();
commands.spawn_bundle(PolylineBundle { commands.spawn_bundle(PolylineBundle {
polyline: polylines.add(Polyline { vertices: verts }), polyline: polylines.add(Polyline { vertices: verts }),
material: polymats.add(PolylineMaterial { material: polymats.add(PolylineMaterial {
@ -86,7 +90,10 @@ impl Plugin for CyberGlamorPlugin {
..Default::default() ..Default::default()
}) })
.insert_resource(WireframeConfig { global: false }) .insert_resource(WireframeConfig { global: false })
.add_startup_system_to_stage(StartupStage::PostStartup, wireframe_planet) .add_startup_system_to_stage(
StartupStage::PostStartup,
wireframe_planet.after("colliders"),
)
.add_system(wireframify_lights) .add_system(wireframify_lights)
.add_plugin(PolylinePlugin) .add_plugin(PolylinePlugin)
.add_plugin(WireframePlugin); .add_plugin(WireframePlugin);