128 lines
3.8 KiB
Rust
128 lines
3.8 KiB
Rust
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<Assets<Mesh>>,
|
|
materials: &mut ResMut<Assets<StandardMaterial>>,
|
|
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
|
|
}
|