This commit is contained in:
Joe Ardent 2025-04-26 16:32:31 -07:00
parent 3777f120e7
commit b54e0a637f

View file

@ -6,15 +6,19 @@ use avian3d::{
TransformInterpolation, TransformInterpolation,
}, },
}; };
use bevy::prelude::{ use bevy::{
children, AlphaMode, App, Assets, Capsule3d, Color, Commands, Component, Dir3, EntityCommands, asset::Handle,
Mesh, Mesh3d, MeshMaterial3d, Name, Plugin, Reflect, ResMut, SpawnRelated, Sphere, ecs::{bundle::Bundle, entity::Entity},
StandardMaterial, Startup, Transform, Vec3, Visibility, prelude::{
children, AlphaMode, App, Assets, Capsule3d, Color, Commands, Component, Dir3, Mesh,
Mesh3d, MeshMaterial3d, Name, Plugin, Reflect, ResMut, SpawnRelated, Sphere,
StandardMaterial, Startup, Transform, Vec3, Visibility,
},
}; };
use crate::physics::CatControllerState; use crate::physics::CatControllerState;
pub const SPRING_CONSTANT: Scalar = 60.0; pub const SPRING_CONSTANT: Scalar = 50.0;
pub const DAMPING_CONSTANT: Scalar = 10.0; pub const DAMPING_CONSTANT: Scalar = 10.0;
pub const WHEEL_RADIUS: Scalar = 0.4; pub const WHEEL_RADIUS: Scalar = 0.4;
pub const REST_DISTANCE: Scalar = 1.5 + WHEEL_RADIUS; pub const REST_DISTANCE: Scalar = 1.5 + WHEEL_RADIUS;
@ -97,87 +101,96 @@ fn spawn_bike(
SleepingDisabled, SleepingDisabled,
CyberBikeBody, CyberBikeBody,
CatControllerState::default(), CatControllerState::default(),
ColliderDensity(1.2), ColliderDensity(1.4),
AngularDamping(0.2), AngularDamping(0.2),
LinearDamping(0.1), LinearDamping(0.1),
ExternalForce::ZERO.with_persistence(false), ExternalForce::ZERO.with_persistence(false),
ExternalTorque::ZERO.with_persistence(false), ExternalTorque::ZERO.with_persistence(false),
)); ));
let color = Color::srgb(0.7, 0.05, 0.7); let pbr_bundle = {
let mut xform = Transform::default(); let color = Color::srgb(0.7, 0.05, 0.7);
xform.rotate_x(FRAC_PI_2); let mut xform = Transform::default();
let pbr_bundle = ( xform.rotate_x(FRAC_PI_2);
Mesh3d(meshes.add(Capsule3d::new(0.5, 1.45))), (
xform, Mesh3d(meshes.add(Capsule3d::new(0.5, 1.45))),
MeshMaterial3d(materials.add(color)), xform,
); Visibility::Visible,
MeshMaterial3d(materials.add(color)),
body.insert(children![pbr_bundle]); TransformInterpolation,
)
spawn_wheels(&mut body, meshes, materials); };
let parent = body.id();
body.insert(spawn_children(parent, pbr_bundle, meshes, materials));
} }
fn spawn_wheels( fn spawn_children(
commands: &mut EntityCommands, parent: Entity,
body: impl Bundle,
mut meshes: ResMut<Assets<Mesh>>, mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>, mut materials: ResMut<Assets<StandardMaterial>>,
) { ) -> impl Bundle {
let mesh: Mesh = Sphere::new(WHEEL_RADIUS).into(); let mesh: Mesh = Sphere::new(WHEEL_RADIUS).into();
let wheel_material = StandardMaterial {
base_color: Color::srgb(0.01, 0.01, 0.01),
alpha_mode: AlphaMode::Opaque,
perceptual_roughness: 0.5,
..Default::default()
};
let mesh = meshes.add(mesh);
let material = materials.add(wheel_material);
let front_rake = Vec3::new(0.0, -1.0, -0.9).normalize(); // about 30 degrees let front_rake = Vec3::new(0.0, -1.0, -0.9).normalize(); // about 30 degrees
let front_wheel_pos = FRONT_ATTACH + (front_rake * REST_DISTANCE); let front_wheel_pos = FRONT_ATTACH + (front_rake * REST_DISTANCE);
wheel_caster(
commands,
FRONT_ATTACH,
Dir3::new_unchecked(front_rake),
REST_DISTANCE,
CyberWheel::Front,
);
wheel_mesh(
commands,
&mut meshes,
&mut materials,
front_wheel_pos,
mesh.clone(),
WheelConfig::new(
FRONT_ATTACH,
REST_DISTANCE,
SPRING_CONSTANT,
DAMPING_CONSTANT,
FRICTION_COEFF,
WHEEL_RADIUS,
),
CyberWheel::Front,
);
let rear_rake = Vec3::new(0.0, -1.0, 0.9).normalize(); let rear_rake = Vec3::new(0.0, -1.0, 0.9).normalize();
let rear_wheel_pos = REAR_ATTACH + (rear_rake * REST_DISTANCE); let rear_wheel_pos = REAR_ATTACH + (rear_rake * REST_DISTANCE);
wheel_caster( children!(
commands, body,
REAR_ATTACH, wheel_caster(
Dir3::new_unchecked(rear_rake), parent,
REST_DISTANCE, FRONT_ATTACH,
CyberWheel::Rear, Dir3::new_unchecked(front_rake),
);
wheel_mesh(
commands,
&mut meshes,
&mut materials,
rear_wheel_pos,
mesh,
WheelConfig::new(
REAR_ATTACH,
REST_DISTANCE, REST_DISTANCE,
SPRING_CONSTANT, CyberWheel::Front,
DAMPING_CONSTANT,
FRICTION_COEFF,
WHEEL_RADIUS,
), ),
CyberWheel::Rear, wheel_mesh(
); mesh.clone(),
material.clone(),
front_wheel_pos,
WheelConfig::new(
FRONT_ATTACH,
REST_DISTANCE,
SPRING_CONSTANT,
DAMPING_CONSTANT,
FRICTION_COEFF,
WHEEL_RADIUS,
),
CyberWheel::Front,
),
wheel_caster(
parent,
REAR_ATTACH,
Dir3::new_unchecked(rear_rake),
REST_DISTANCE,
CyberWheel::Rear,
),
wheel_mesh(
mesh,
material,
rear_wheel_pos,
WheelConfig::new(
REAR_ATTACH,
REST_DISTANCE,
SPRING_CONSTANT,
DAMPING_CONSTANT,
FRICTION_COEFF,
WHEEL_RADIUS,
),
CyberWheel::Rear,
),
)
} }
//-************************************************************************ //-************************************************************************
@ -185,36 +198,27 @@ fn spawn_wheels(
//-************************************************************************ //-************************************************************************
fn wheel_caster( fn wheel_caster(
commands: &mut EntityCommands, parent: Entity,
origin: Vec3, origin: Vec3,
direction: Dir3, direction: Dir3,
rest_dist: Scalar, rest_dist: Scalar,
wheel: CyberWheel, wheel: CyberWheel,
) { ) -> impl Bundle {
let caster = RayCaster::new(origin, direction) let caster = RayCaster::new(origin, direction)
.with_max_distance(rest_dist) .with_max_distance(rest_dist)
.with_max_hits(1) .with_max_hits(1)
.with_query_filter(SpatialQueryFilter::from_excluded_entities([commands.id()])); .with_query_filter(SpatialQueryFilter::from_excluded_entities([parent]));
commands.insert(children![(caster, wheel)]); (caster, wheel)
} }
fn wheel_mesh( fn wheel_mesh(
commands: &mut EntityCommands, mesh: Handle<Mesh>,
meshes: &mut ResMut<Assets<Mesh>>, material: Handle<StandardMaterial>,
materials: &mut ResMut<Assets<StandardMaterial>>,
position: Vec3, position: Vec3,
tire_mesh: Mesh,
config: WheelConfig, config: WheelConfig,
wheel: CyberWheel, wheel: CyberWheel,
) { ) -> impl Bundle {
let wheel_material = &StandardMaterial {
base_color: Color::srgb(0.01, 0.01, 0.01),
alpha_mode: AlphaMode::Opaque,
perceptual_roughness: 0.5,
..Default::default()
};
let xform = Transform::from_translation(position); let xform = Transform::from_translation(position);
let name = match wheel { let name = match wheel {
@ -222,18 +226,18 @@ fn wheel_mesh(
CyberWheel::Rear => "rear tire", CyberWheel::Rear => "rear tire",
}; };
commands.insert(children![( (
Name::new(name), Name::new(name),
config, config,
Mesh3d(meshes.add(tire_mesh)), Mesh3d(mesh),
MeshMaterial3d(materials.add(wheel_material.clone())), MeshMaterial3d(material),
xform, xform,
Collider::sphere(WHEEL_RADIUS), Collider::sphere(WHEEL_RADIUS),
ColliderDensity(0.5), ColliderDensity(0.5),
CollisionLayers::NONE, CollisionLayers::NONE,
TransformInterpolation, TransformInterpolation,
wheel, wheel,
)]); )
} }
pub struct CyberBikePlugin; pub struct CyberBikePlugin;