From 926038b8bc66ef11ba1c4865d8c21a32db1beae8 Mon Sep 17 00:00:00 2001 From: katopz Date: Sat, 21 Oct 2023 13:13:29 +0700 Subject: [PATCH] feat: add bevy --- src/SUMMARY.md | 2 + src/bevy/mod.md | 83 ++++++++++++++ src/bevy/physics-rapier.md | 226 +++++++++++++++++++++++++++++++++++++ 3 files changed, 311 insertions(+) create mode 100644 src/bevy/mod.md create mode 100644 src/bevy/physics-rapier.md diff --git a/src/SUMMARY.md b/src/SUMMARY.md index 8c39658..3acd85a 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -68,4 +68,6 @@ - [Hugging Face - AutoTrain](ml/huggingface-autotrain.md) - [LLM Train and FineTune](ml/llm-train-finetune/mod.md) - [TabbyML](ml/tabbyml.md) +- [Bevy](bevy/mod.md) + - [Physics with Rapier](bevy/physics-rapier.md) - [Bye](bye.md) diff --git a/src/bevy/mod.md b/src/bevy/mod.md new file mode 100644 index 0000000..bea7fe4 --- /dev/null +++ b/src/bevy/mod.md @@ -0,0 +1,83 @@ +# WIP Bevy + +``` +ld: cannot find -lshlwapi: No such file or directory +``` + +``` +# ⚠️ Not working +rustup toolchain install stable-x86_64-pc-windows-gnu + +# Switch to msvc +rustup default stable-x86_64-pc-windows-msvc +``` + +## Note + +- [x] Hot reload: https://github.com/lee-orr/dexterous_developer // Not seem to work and will need `XCode` to be installed for faster reload. +- [ ] Game template: https://github.com/NiklasEi/bevy_game_template +- [x] Load scene from Blender: https://github.com/kaosat-dev/Blender_bevy_components_workflow // Work but animation will failed. +- [ ] Oxidized Navigation: Tiled Runtime Nav-mesh generation for 3D worlds https://github.com/TheGrimsey/oxidized_navigation +- [ ] 💾 Moonshine Save: A save/load framework for Bevy game engine. https://github.com/Zeenobit/moonshine_save +- [ ] Bevy Replicon: Write the same logic that works for both multiplayer and single-player. https://github.com/lifescapegame/bevy_replicon +- [ ] Renet: Renet is a network library for Server/Client game: https://github.com/lucaspoffo/renet +- [x] bevy_xpbd: 2D and 3D physics engine based on Extended Position Based Dynamics for Bevy. https://github.com/Jondolf/bevy_xpbd // Not ready for prod. +- [x] Sea : https://github.com/claudijo/pirate-sea-jam // Work `0.11` but weird firing ammo. + +## Windows + +> Use `dynamic` + +```toml +[profile.dev] +opt-level = 1 + +[profile.dev.package."*"] +opt-level = 3 + +[dependencies] +bevy = {version = "0.11.3", features = ["dynamic"] } +``` + +--- + +## Mac intel + +### Problem + +> https://github.com/RustAudio/coreaudio-sys/issues/85 + +``` + Compiling coreaudio-sys v0.2.11 +error: failed to run custom build command for `coreaudio-sys v0.2.11` + +Caused by: + process didn't exit successfully: `/Users/katopz/git/katopz/bevy-tower-defense-tutorial/target/debug/build/coreaudio-sys-8eda3e49206fc9e3/build-script-build` (exit status: 101) + --- stdout + cargo:rerun-if-env-changed=COREAUDIO_SDK_PATH + cargo:rustc-link-lib=framework=AudioUnit + cargo:rustc-link-lib=framework=CoreAudio + cargo:rerun-if-env-changed=BINDGEN_EXTRA_CLANG_ARGS + + --- stderr + thread 'main' panicked at /Users/katopz/.cargo/registry/src/index.crates.io-6f17d22bba15001f/proc-macro2-1.0.47/src/fallback.rs:756:9: + "enum_(unnamed_at_/Library/Developer/CommandLineTools/SDKs/MacOSX_sdk/usr/include/MacTypes_h_382_1)" is not a valid Ident + note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace +``` + +### Solution + +``` +brew install llvm@15 +cargo update +``` + +--- + +### Problem + +> https://github.com/michaeleisel/homebrew-zld/issues?q=is%3Aissue+is%3Aclosed + +### Solution + +Install `Xcode` diff --git a/src/bevy/physics-rapier.md b/src/bevy/physics-rapier.md new file mode 100644 index 0000000..f15cf3e --- /dev/null +++ b/src/bevy/physics-rapier.md @@ -0,0 +1,226 @@ +# Rapier + +Refer to: https://taintedcoders.com/bevy/rapier/ + +## 3 Pipelines + +```mermaid +graph LR + A["Pipelines"]---B["1️⃣ physics"] + A---C["2️⃣ collider"] + A---D["3️⃣ query"] +``` + +### 1️⃣ The physics pipeline + +#### Our forces are calculated by two separate solvers: + +```mermaid +graph LR + A["Solver"]---B["Velocity"] + A---C["Position"] +``` + +#### The overall sequence looks like this: + +```mermaid +graph TD + A["Wake up our islands for objects that should be simulated"] + -->B["Handle changes we made to any colliders"] + -->C["Handle changes we made to any rigid bodies"] + -->D["Handle joints"] + -->E["Detect collisions"] + -->F["Run any queries"] + -->G["Perform any continuous collision detection (CCD)"] + -->H["Integrate forces"] + -->I["Update our objects"] +``` + +```rust +pub fn step( + &mut self, + gravity: &Vector, + integration_parameters: &IntegrationParameters, + islands: &mut IslandManager, + broad_phase: &mut BroadPhase, + narrow_phase: &mut NarrowPhase, + bodies: &mut RigidBodySet, + colliders: &mut ColliderSet, + impulse_joints: &mut ImpulseJointSet, + multibody_joints: &mut MultibodyJointSet, + ccd_solver: &mut CCDSolver, + query_pipeline: Option<&mut QueryPipeline>, + hooks: &dyn PhysicsHooks, + events: &dyn EventHandler +) +``` + +### 2️⃣ The collider pipeline + +> A lighter alternative to the physics pipeline is using only the collision pipeline. + +```rust +pub fn step( + &mut self, + prediction_distance: Real, + broad_phase: &mut BroadPhase, + narrow_phase: &mut NarrowPhase, + bodies: &mut RigidBodySet, + colliders: &mut ColliderSet, + query_pipeline: Option<&mut QueryPipeline>, + hooks: &dyn PhysicsHooks, + events: &dyn EventHandler, +) +``` + +### 3️⃣ The query pipeline + +> Queries are how we ask about our colliders. The pipeline itself can be in one of three modes: + +```rust +// Indicates how the colliders position should be taken into account when +// updating the query pipeline. +pub enum QueryPipelineMode { + // The `Collider::position` is taken into account. + CurrentPosition, + // The `RigidBody::next_position * Collider::position_wrt_parent` is taken into account for + // the colliders positions. + SweepTestWithNextPosition, + // The `RigidBody::predict_position_using_velocity_and_forces * Collider::position_wrt_parent` + // is taken into account for the colliders position. + SweepTestWithPredictedPosition { + // The time used to integrate the rigid-body's velocity and acceleration. + dt: Real, + }, +} +``` + +--- + +## Simulating physics with Bevy Rapier + +--- + +## Rigid bodies + +> 3 kinds of RigidBody + +1. `RigidBody::Dynamic` // a balls +1. `RigidBody::Fixed` // a grounds +1. `RigidBody::KinematicPositionBased`/`RigidBody::KinematicVelocityBased` // a player + +--- + +## Collisions + +Attach `RigidBody` to `Collider` to the same entity to make it collide. + +```rust +// Create a simple solid ball +commands + .spawn(RigidBody::Dynamic) + .insert(Collider::ball(0.5)); + +// Create a hollow ball from a mesh +commands + .spawn(RigidBody::Dynamic) + .insert(Collider::from_bevy_mesh( + Mesh::from(shape::UVSphere::default()), + ComputedColliderShape::TriMesh + ); +``` + +Or just detect collisions (aka door sensor) + +```rust +commands + .spawn(Collider::ball(0.5)) + .insert(Sensor); +``` + +Other components we can add to affect our colliders: + +1. `LockedAxes` to prevent certain movement. +1. `Damping` to simulate air friction. +1. `Dominance` to make some objects godmode over others. +1. `Ccd` to do continuous collision detection for fast things like bullets. +1. `Sleeping` to manually wake up non moving rigid bodies. + +Collision detection works in Rapier is in two phases: + +1. `The broad phase`: finds anything contacting or intersecting and flags them. +1. `The narrow phase`: iterates over items found in the broad phase and calculates the collision `CollisionEvent`, `ContactForceEvent` events. + +### Filtering collisions + +When we want to make only some things collide with each other we can choose to set a collision group by initializing a `CollisionGroups` component with both the `membership` of our group and the `filter`: + +```rust +commands + .spawn(Collider::ball(0.5)) + // First argument 👇 is the membership, second 👇 is the filter + .insert(CollisionGroups::new(0b1101.into(), 0b0100.into())); +``` + +The `membership` parameter determines who you are and is how others reference you. If you say you are part of group 1 then everyone who filters for group 1 will be able to interact with you. + +The `filter` parameter determines who you can interact with. If you say you can interact with members of group 1 then any entity assigned to group 1 will produce a collision if we make contact. + +`0b` = binary prefix. + +For example, let’s say you have four groups: + +Objects that can collide with walls. +Objects that can collide with other objects of the same group. +Objects that can collide with ground. +Objects that can collide with the ceiling. + +`0b1011` = collide with [`1` walls, `0` not collide, `1` ground, `1` ceiling] + +If instead we wanted to produce the contact events but not apply the forces of the collision then we could do the same thing with `SolverGroups`: (aka `Sensor`) + +```rust +commands + .spawn(Collider::ball(0.5)) + .insert(SolverGroups::new(0b0011.into(), 0b1011.into()); +``` + +One gotcha is that by default your kinematic rigid bodies won’t collide with your fixed bodies. This is because they are not listening for the right contact events. To enable this behaviour we need to add a `ActiveCollisionTypes` component: + +```rust +commands + .spawn(RigidBody::Fixed) + .insert(Collider::ball(0.5)) + .insert(ActiveCollisionTypes::default() | ActiveCollisionTypes::KINEMATIC_FIXED); +``` + +## Events + +The narrow phase will produce events like `CollisionEvent` and `ContactForceEvent` but not by default. To enable this at least one of the contacted entities needs to have a `ActiveEvents::COLLISION_EVENTS` or `ActiveEvents::CONTACT_FORCE_EVENTS` component to trigger them. + +```rust +/* A system that displays the events. */ +fn display_events( + mut collision_events: EventReader, + mut contact_force_events: EventReader, +) { + for collision_event in collision_events.iter() { + println!("Received collision event: {:?}", collision_event); + } + + for contact_force_event in contact_force_events.iter() { + println!("Received contact force event: {:?}", contact_force_event); + } +} +``` + +## Vehicles + +- Good car example but `ammo.js`: https://github.com/kripken/ammo.js/blob/main/examples/webgl_demo_vehicle/index.html +- Perfect `Rapier` example but js: https://github.com/grndctrl/vehicle-canary +- Adjustable wheel and car detail but `Bevy 0.7`: https://github.com/gavlig/gryazevichki +- Weird physics fake suspension and broken Camera `Bevy 0.10`: https://github.com/Biped-Potato/car_game +- Working but `bevy_xpbd_3d` and only box, no wheel `Bevy 0.11.3`: https://github.com/tbillington/driving-physics-repro +- Should work but [freezing](https://github.com/dimforge/rapier/issues/528): https://github.com/dimforge/rapier/blob/master/examples3d/vehicle_controller3.rs +- How to make the ghost's movement respect the surfaces of the terrain. // Work with `Bevy 0.10.0` but weird move.: https://github.com/shnewto/limbo_pass +- Nice but heavy lib rebuild, some sound bug `Bevy 0.11.3`: https://github.com/alexichepura/bevy_garage