use avian3d::{math::FRAC_PI_2, prelude::*}; use bevy::prelude::*; use super::{CyberSteering, CyberWheel, Meshterial, WheelConfig}; use crate::ColliderGroups; pub fn spawn_wheels( commands: &mut Commands, bike: Entity, xform: &Transform, conf: &WheelConfig, meshterials: &mut Meshterial, ) { let wheel_y = conf.y; let (meshes, materials) = meshterials; let rake_vec: Vec3 = Vec3::new(0.0, 1.0, 0.57).normalize(); // about 30 degrees of rake let mut wheel_poses = Vec::with_capacity(2); // front { let wheel_x = 0.0; let wheel_z = -conf.front_forward; let offset = Vec3::new(wheel_x, wheel_y, wheel_z); wheel_poses.push((offset, Some(CyberSteering))); } // rear { let wheel_x = 0.0; let wheel_z = conf.rear_back; let offset = Vec3::new(wheel_x, wheel_y, wheel_z); wheel_poses.push((offset, None)); } // tires let outer_radius = conf.radius; let inner_radius = conf.radius - conf.thickness; let mesh = Mesh::from(Torus::new(inner_radius, outer_radius)) .rotated_by(Quat::from_rotation_z(FRAC_PI_2)); let collider = Collider::convex_hull_from_mesh(&mesh).unwrap(); for (offset, steering) in wheel_poses { let hub = wheels_helper( commands, meshes, materials, offset + xform.translation, mesh.clone(), collider.clone(), conf, ); if let Some(steering) = steering { commands.spawn(( RevoluteJoint::new(bike, hub) .with_aligned_axis(rake_vec) .with_angle_limits(-0.01, 0.01) .with_local_anchor_2(Vec3::new(0.0, 0.08, -0.05)) .with_local_anchor_1(offset), steering, )); } else { commands.spawn(FixedJoint::new(bike, hub).with_local_anchor_1(offset)); } } } fn wheels_helper( commands: &mut Commands, meshes: &mut ResMut>, materials: &mut ResMut>, position: Vec3, tire_mesh: Mesh, collider: Collider, conf: &WheelConfig, ) -> Entity { 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 hub_mesh: Mesh = Sphere::new(0.1).into(); let hub = commands .spawn(( Name::new("hub"), RigidBody::Dynamic, MassPropertiesBundle::new_computed(&Collider::sphere(0.1), 200.0), PbrBundle { mesh: meshes.add(hub_mesh), material: materials.add(wheel_material.clone()), transform: xform, ..Default::default() }, )) .id(); let tire = commands .spawn(( Name::new("tire"), PbrBundle { mesh: meshes.add(tire_mesh), material: materials.add(wheel_material.clone()), transform: xform, ..Default::default() }, CyberWheel, RigidBody::Dynamic, collider, Friction::new(conf.friction), Restitution::new(conf.restitution), ColliderDensity(conf.density), CollisionLayers::new(ColliderGroups::Wheels, ColliderGroups::Planet), ExternalTorque::ZERO.with_persistence(false), CollisionMargin(0.05), SweptCcd::NON_LINEAR, )) .id(); // connect hubs and tires to make wheels commands.spawn(RevoluteJoint::new(hub, tire).with_aligned_axis(Vec3::X)); hub }