bevy_mod_physx 0.9.0

PhysX plugin for Bevy
Documentation
mod common;

use bevy::prelude::*;
use bevy_mod_physx::prelude::{self as bpx, *};

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .add_plugins(PhysicsPlugins.set(
            PhysicsCore::new().with_pvd()
        ))
        .add_plugins(common::DemoUtils) // optional
        .add_systems(Startup, (
            spawn_plane,
            spawn_stacks,
            spawn_dynamic,
            spawn_camera_and_light,
        ))
        .run();
}

fn spawn_plane(
    mut commands: Commands,
    mut meshes: ResMut<Assets<Mesh>>,
    mut materials: ResMut<Assets<StandardMaterial>>,
    mut physics: ResMut<Physics>,
    mut px_geometries: ResMut<Assets<bpx::Geometry>>,
    mut px_materials: ResMut<Assets<bpx::Material>>,
) {
    let primitive = Plane3d::default();
    let mesh = meshes.add(primitive.mesh().size(500., 500.));
    let material = materials.add(Color::srgb(0.3, 0.5, 0.3));
    let px_geometry = px_geometries.add(primitive);
    let px_material = px_materials.add(bpx::Material::new(&mut physics, 0.5, 0.5, 0.6));

    commands.spawn_empty()
        .insert((
            Mesh3d::from(mesh.clone()),
            MeshMaterial3d::from(material.clone()),
        ))
        .insert(bpx::RigidBody::Static)
        .insert(bpx::Shape {
            geometry: px_geometry,
            material: px_material,
            ..default()
        })
        .insert(Name::new("Plane"));
}

fn spawn_stacks(
    mut commands: Commands,
    mut meshes: ResMut<Assets<Mesh>>,
    mut materials: ResMut<Assets<StandardMaterial>>,
    mut px_geometries: ResMut<Assets<bpx::Geometry>>,
) {
    const WIDTH: f32 = 0.5;
    const SIZE: usize = 10;

    let primitive = Cuboid::from_size(Vec3::splat(WIDTH));
    let mesh = meshes.add(primitive);
    let material = materials.add(Color::srgb(0.8, 0.7, 0.6));

    let px_geometry = px_geometries.add(primitive);

    for i in 0..5 {
        commands.spawn((
            Name::new(format!("Stack {i}")),
            Transform::from_xyz(0., 0., -1.25 * i as f32),
            Visibility::default(),
        ))
            .with_children(|builder| {
                for i in 0..SIZE {
                    for j in 0..SIZE-i {
                        let transform = Transform::from_xyz(
                            ((j * 2) as f32 - (SIZE - i) as f32) / 2. * WIDTH,
                            (i * 2 + 1) as f32 / 2. * WIDTH,
                            0.,
                        );

                        builder.spawn_empty()
                            .insert((
                                Mesh3d::from(mesh.clone()),
                                MeshMaterial3d::from(material.clone()),
                                transform,
                            ))
                            .insert(bpx::RigidBody::Dynamic)
                            .insert(MassProperties::density(10.))
                            .insert(bpx::Shape {
                                geometry: px_geometry.clone(),
                                ..default()
                            });
                    }
                }
            })
            .insert(Name::new(format!("Stack {i}")));
    }
}

fn spawn_dynamic(
    mut commands: Commands,
    mut meshes: ResMut<Assets<Mesh>>,
    mut materials: ResMut<Assets<StandardMaterial>>,
    mut physics: ResMut<Physics>,
    mut px_geometries: ResMut<Assets<bpx::Geometry>>,
    mut px_materials: ResMut<Assets<bpx::Material>>,
) {
    const RADIUS: f32 = 1.25;

    let primitive = Sphere::new(RADIUS);
    let mesh = meshes.add(primitive);
    let material = materials.add(Color::srgb(0.8, 0.7, 0.6));

    let px_geometry = px_geometries.add(primitive);
    let px_material = px_materials.add(bpx::Material::new(&mut physics, 0.5, 0.5, 0.6));

    let transform = Transform::from_xyz(0., 5., 12.5);

    commands.spawn_empty()
        .insert((
            Mesh3d::from(mesh.clone()),
            MeshMaterial3d::from(material.clone()),
            transform,
        ))
        .insert(bpx::RigidBody::Dynamic)
        .insert(MassProperties::density(10.))
        .insert(bpx::Shape {
            material: px_material,
            geometry: px_geometry,
            ..default()
        })
        .insert(Velocity::linear(Vec3::new(0., -6.25, -12.5)))
        .insert(Name::new("Ball"));
}

fn spawn_camera_and_light(mut commands: Commands) {
    commands
        .spawn((
            Name::new("Camera"),
            Transform::from_xyz(0., 0., 0.),
            Visibility::default(),
        ))
        .with_children(|builder| {
            builder.spawn((
                Camera3d::default(),
                Transform::from_xyz(-32.5, 13.6, 18.8).looking_at(Vec3::ZERO, Vec3::Y),
            ));
        });

    commands.spawn((
        Name::new("Light"),
        DirectionalLight::default(),
        Transform::from_rotation(Quat::from_euler(EulerRot::XYZ, -1.2, -0.2, 0.)),
    ));
}