#![allow(clippy::unnecessary_cast)] use avian3d::{math::*, prelude::*}; use bevy::prelude::*; use examples_common_3d::ExampleCommonPlugin; fn main() { App::new() .add_plugins(( DefaultPlugins, ExampleCommonPlugin, PhysicsPlugins::default(), )) .insert_resource(ClearColor(Color::srgb(0.05, 0.05, 0.1))) .insert_resource(Msaa::Sample4) .insert_resource(AmbientLight { brightness: 2.0, ..default() }) .insert_resource(SubstepCount(80)) .insert_resource(Gravity(Vector::NEG_Y * 9.81 * 2.0)) .add_systems(Startup, (setup, ui)) .add_systems(Update, movement) .run(); } /// The acceleration used for movement. #[derive(Component)] struct MovementAcceleration(Scalar); fn setup( mut commands: Commands, mut materials: ResMut>, mut meshes: ResMut>, ) { let particle_count = 100; let particle_radius = 0.06; let particle_mesh = meshes.add(Sphere::new(particle_radius as f32).mesh().ico(5).unwrap()); let particle_material = materials.add(StandardMaterial { base_color: Color::srgb(0.2, 0.7, 0.9), unlit: true, ..default() }); // Spawn kinematic particle that can follow the mouse let mut previous_particle = commands .spawn(( RigidBody::Kinematic, MovementAcceleration(25.0), PbrBundle { mesh: particle_mesh.clone(), material: particle_material.clone(), ..default() }, )) .id(); // Spawn the rest of the particles, connecting each one to the previous one with joints for i in 1..particle_count { let current_particle = commands .spawn(( RigidBody::Dynamic, MassPropertiesBundle::new_computed(&Collider::sphere(particle_radius), 1.0), PbrBundle { mesh: particle_mesh.clone(), material: particle_material.clone(), transform: Transform::from_xyz( 0.0, -i as f32 * particle_radius as f32 * 2.2, 0.0, ), ..default() }, )) .id(); commands.spawn( SphericalJoint::new(previous_particle, current_particle) .with_local_anchor_1(Vector::NEG_Y * particle_radius * 1.1) .with_local_anchor_2(Vector::Y * particle_radius * 1.1) .with_compliance(0.00001), ); previous_particle = current_particle; } commands.spawn(Camera3dBundle { transform: Transform::from_translation(Vec3::new(0.0, 5.0, 20.0)) .looking_at(Vec3::NEG_Y * 5.0, Vec3::Y), ..default() }); } fn movement( time: Res