use bevy::prelude::{shape::UVSphere as Tire, *}; use bevy_rapier3d::prelude::{ Ccd, Collider, ColliderMassProperties, CollisionGroups, Damping, ExternalForce, Friction, MultibodyJoint, PrismaticJointBuilder, ReadMassProperties, Restitution, RigidBody, Sleeping, TransformInterpolation, Velocity, }; use super::{ CyberBikeBody, CyberWheel, WheelConfig, BIKE_BODY_COLLISION_GROUP, BIKE_WHEEL_COLLISION_GROUP, }; use crate::{action::CatControllerState, planet::PLANET_RADIUS}; type Meshterial<'a> = ( ResMut<'a, Assets>, ResMut<'a, Assets>, ); pub(super) fn spawn_cyberbike( mut commands: Commands, asset_server: Res, wheel_conf: Res, mut meshterials: Meshterial, ) { let altitude = PLANET_RADIUS - 220.0; let mut xform = Transform::from_translation(Vec3::X * altitude) .with_rotation(Quat::from_axis_angle(Vec3::Z, -89.0f32.to_radians())); //.with_rotation(Quat::from_axis_angle(Vec3::X, 140.0f32.to_radians())); let right = xform.right() * 350.0; xform.translation += right; let damping = Damping { angular_damping: 2.0, linear_damping: 0.1, }; let friction = Friction { coefficient: 0.0, ..Default::default() }; let restitution = Restitution { coefficient: 0.0, ..Default::default() }; let mass_properties = ColliderMassProperties::Density(0.9); let (membership, filter) = BIKE_BODY_COLLISION_GROUP; let bike_collision_group = CollisionGroups::new(membership, filter); let scene = asset_server.load("cb-no-y_up.glb#Scene0"); let spatialbundle = SpatialBundle { transform: xform, ..Default::default() }; let bike = commands .spawn(RigidBody::Dynamic) .insert(spatialbundle) .insert(( Collider::capsule(Vec3::new(0.0, 0.0, -1.0), Vec3::new(0.0, 0.0, 1.0), 0.50), bike_collision_group, mass_properties, damping, restitution, friction, Sleeping::disabled(), Ccd { enabled: true }, ReadMassProperties::default(), )) .insert(TransformInterpolation { start: None, end: None, }) .insert(Velocity::zero()) .insert(ExternalForce::default()) .with_children(|rider| { rider.spawn(SceneBundle { scene, ..Default::default() }); }) .insert(CyberBikeBody) .insert(CatControllerState::default()) .id(); spawn_tires(&mut commands, &xform, bike, &wheel_conf, &mut meshterials); } fn spawn_tires( commands: &mut Commands, xform: &Transform, bike: Entity, conf: &WheelConfig, meshterials: &mut Meshterial, ) { //return; // re-set the collision group let (membership, filter) = BIKE_WHEEL_COLLISION_GROUP; let wheels_collision_group = CollisionGroups::new(membership, filter); let wheel_y = conf.y; let wheel_rad = conf.radius; let stiffness = conf.stiffness; let not_sleeping = Sleeping::disabled(); let ccd = Ccd { enabled: true }; let limits = conf.limits; let (meshes, materials) = meshterials; let tire = Tire { radius: wheel_rad, ..Default::default() }; let material = StandardMaterial { base_color: Color::Rgba { red: 0.01, green: 0.01, blue: 0.01, alpha: 1.0, }, alpha_mode: AlphaMode::Opaque, perceptual_roughness: 0.5, ..Default::default() }; let pbr_bundle = PbrBundle { material: materials.add(material), mesh: meshes.add(Mesh::from(tire)), ..Default::default() }; let friction = Friction { coefficient: 0.0, ..Default::default() }; 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); } // 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); } for offset in wheel_poses { let trans = xform.translation + offset; let wheel_pos_in_world = Transform::from_rotation(xform.rotation).with_translation(trans); let wheel_damping = Damping { linear_damping: 0.8, ..Default::default() }; let wheel_collider = Collider::ball(wheel_rad); let mass_props = ColliderMassProperties::Density(0.1); let damping = conf.damping; let prismatic = PrismaticJointBuilder::new(Vec3::Y) .local_anchor1(offset) .limits(limits) .motor_position(-0.1, stiffness, damping); let joint = MultibodyJoint::new(bike, prismatic); let spatial_bundle = SpatialBundle { transform: wheel_pos_in_world, ..Default::default() }; let tire_spundle = SpatialBundle { transform: Transform::IDENTITY, ..Default::default() }; commands .spawn(RigidBody::Dynamic) .insert(spatial_bundle) .insert(( wheel_collider, mass_props, wheel_damping, ccd, not_sleeping, joint, wheels_collision_group, friction, CyberWheel, ExternalForce::default(), )) .with_children(|wheel| { wheel.spawn(tire_spundle).insert(pbr_bundle.clone()).insert( TransformInterpolation { start: None, end: None, }, ); }); } }