fix PID params for lean; fix camera wobble; add torque arrow gizmo

This commit is contained in:
Joe Ardent 2024-07-22 15:33:14 -07:00
parent 040bf10f41
commit d66a26d63c
6 changed files with 863 additions and 166 deletions

530
Cargo.lock generated
View File

@ -180,6 +180,24 @@ dependencies = [
"num-traits",
]
[[package]]
name = "arboard"
version = "3.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9fb4009533e8ff8f1450a5bcbc30f4242a1d34442221f72314bea1f5dc9c7f89"
dependencies = [
"clipboard-win",
"core-graphics",
"image 0.25.2",
"log",
"objc2",
"objc2-app-kit",
"objc2-foundation",
"parking_lot",
"windows-sys 0.48.0",
"x11rb",
]
[[package]]
name = "arrayref"
version = "0.3.8"
@ -333,6 +351,50 @@ dependencies = [
"bevy_internal",
]
[[package]]
name = "bevy-inspector-egui"
version = "0.25.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8d77dbe53c8840aa74b66ea19dac6675d0a1752c989610cbded909d03967bec"
dependencies = [
"bevy-inspector-egui-derive",
"bevy_app",
"bevy_asset",
"bevy_color",
"bevy_core",
"bevy_core_pipeline",
"bevy_ecs",
"bevy_egui",
"bevy_hierarchy",
"bevy_log",
"bevy_math",
"bevy_pbr",
"bevy_reflect",
"bevy_render",
"bevy_state",
"bevy_time",
"bevy_utils",
"bevy_window",
"bytemuck",
"egui",
"fuzzy-matcher",
"image 0.24.9",
"once_cell",
"pretty-type-name",
"smallvec",
]
[[package]]
name = "bevy-inspector-egui-derive"
version = "0.25.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "161d93f4b3a9246a87485e30ccf4cc927f204a14f26df42da977e383f0a0ec5d"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.71",
]
[[package]]
name = "bevy_a11y"
version = "0.14.0"
@ -598,6 +660,28 @@ dependencies = [
"syn 2.0.71",
]
[[package]]
name = "bevy_egui"
version = "0.28.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e4a90f30f2849a07d91e393b10c0cc05df09b5773c010ddde57dd8b583be230"
dependencies = [
"arboard",
"bevy",
"bytemuck",
"console_log",
"crossbeam-channel",
"egui",
"js-sys",
"log",
"thread_local",
"wasm-bindgen",
"wasm-bindgen-futures",
"web-sys",
"webbrowser",
"winit",
]
[[package]]
name = "bevy_encase_derive"
version = "0.14.0"
@ -907,7 +991,7 @@ dependencies = [
"encase",
"futures-lite",
"hexasphere",
"image",
"image 0.25.2",
"js-sys",
"ktx2",
"naga",
@ -1320,6 +1404,18 @@ dependencies = [
"thiserror",
]
[[package]]
name = "calloop-wayland-source"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95a66a987056935f7efce4ab5668920b5d0dac4a7c99991a67395f13702ddd20"
dependencies = [
"calloop",
"rustix",
"wayland-backend",
"wayland-client",
]
[[package]]
name = "cc"
version = "1.1.6"
@ -1374,6 +1470,15 @@ dependencies = [
"libloading 0.8.5",
]
[[package]]
name = "clipboard-win"
version = "5.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "15efe7a882b08f34e38556b14f2fb3daa98769d06c7f0c1b076dfd0d983bc892"
dependencies = [
"error-code",
]
[[package]]
name = "codespan-reporting"
version = "0.11.1"
@ -1384,6 +1489,12 @@ dependencies = [
"unicode-width",
]
[[package]]
name = "color_quant"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b"
[[package]]
name = "com"
version = "0.6.0"
@ -1444,6 +1555,16 @@ dependencies = [
"wasm-bindgen",
]
[[package]]
name = "console_log"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "be8aed40e4edbf4d3b4431ab260b63fdc40f5780a4766824329ea0f1eefe3c0f"
dependencies = [
"log",
"web-sys",
]
[[package]]
name = "const-fnv1a-hash"
version = "1.1.0"
@ -1687,12 +1808,43 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f25c0e292a7ca6d6498557ff1df68f32c99850012b6ea401cf8daf771f22ff53"
[[package]]
name = "ecolor"
version = "0.28.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e6b451ff1143f6de0f33fc7f1b68fecfd2c7de06e104de96c4514de3f5396f8"
dependencies = [
"bytemuck",
"emath",
]
[[package]]
name = "egui"
version = "0.28.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "20c97e70a2768de630f161bb5392cbd3874fcf72868f14df0e002e82e06cb798"
dependencies = [
"ahash",
"emath",
"epaint",
"nohash-hasher",
]
[[package]]
name = "either"
version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
[[package]]
name = "emath"
version = "0.28.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a6a21708405ea88f63d8309650b4d77431f4bc28fb9d8e6f77d3963b51249e6"
dependencies = [
"bytemuck",
]
[[package]]
name = "encase"
version = "0.8.0"
@ -1725,6 +1877,21 @@ dependencies = [
"syn 2.0.71",
]
[[package]]
name = "epaint"
version = "0.28.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f0dcc0a0771e7500e94cd1cb797bd13c9f23b9409bdc3c824e2cbc562b7fa01"
dependencies = [
"ab_glyph",
"ahash",
"bytemuck",
"ecolor",
"emath",
"nohash-hasher",
"parking_lot",
]
[[package]]
name = "equivalent"
version = "1.0.1"
@ -1751,6 +1918,12 @@ dependencies = [
"windows-sys 0.52.0",
]
[[package]]
name = "error-code"
version = "3.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a0474425d51df81997e2f90a21591180b38eccf27292d755f3e30750225c175b"
[[package]]
name = "euclid"
version = "0.22.10"
@ -1857,6 +2030,15 @@ version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b"
[[package]]
name = "form_urlencoded"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456"
dependencies = [
"percent-encoding",
]
[[package]]
name = "futures-core"
version = "0.3.30"
@ -1882,6 +2064,15 @@ dependencies = [
"pin-project-lite",
]
[[package]]
name = "fuzzy-matcher"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "54614a3312934d066701a80f20f15fa3b56d67ac7722b39eea5b4c9dd1d66c94"
dependencies = [
"thread_local",
]
[[package]]
name = "fxhash"
version = "0.2.1"
@ -2160,6 +2351,37 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df"
[[package]]
name = "home"
version = "0.5.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5"
dependencies = [
"windows-sys 0.52.0",
]
[[package]]
name = "idna"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6"
dependencies = [
"unicode-bidi",
"unicode-normalization",
]
[[package]]
name = "image"
version = "0.24.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5690139d2f55868e080017335e4b94cb7414274c74f1669c84fb5feba2c9f69d"
dependencies = [
"bytemuck",
"byteorder",
"color_quant",
"num-traits",
]
[[package]]
name = "image"
version = "0.25.2"
@ -2170,6 +2392,7 @@ dependencies = [
"byteorder-lite",
"num-traits",
"png",
"tiff",
]
[[package]]
@ -2282,6 +2505,12 @@ dependencies = [
"libc",
]
[[package]]
name = "jpeg-decoder"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f5d4a7da358eff58addd2877a45865158f0d78c911d43a5784ceb7bbf52833b0"
[[package]]
name = "js-sys"
version = "0.3.69"
@ -2464,6 +2693,15 @@ version = "2.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
[[package]]
name = "memmap2"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe751422e4a8caa417e13c3ea66452215d7d63e19e604f4980461212f3ae1322"
dependencies = [
"libc",
]
[[package]]
name = "metal"
version = "0.28.0"
@ -2630,6 +2868,12 @@ dependencies = [
"libc",
]
[[package]]
name = "nohash-hasher"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451"
[[package]]
name = "nom"
version = "7.1.3"
@ -3114,6 +3358,7 @@ version = "0.1.0"
dependencies = [
"avian3d",
"bevy",
"bevy-inspector-egui",
]
[[package]]
@ -3202,6 +3447,12 @@ version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8cf8e6a8aa66ce33f63993ffc4ea4271eb5b0530a9002db8455ea6050c77bfa"
[[package]]
name = "pretty-type-name"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0f73cdaf19b52e6143685c3606206e114a4dfa969d6b14ec3894c88eb38bd4b"
[[package]]
name = "proc-macro-crate"
version = "3.1.0"
@ -3226,6 +3477,15 @@ version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43d84d1d7a6ac92673717f9f6d1518374ef257669c24ebc5ac25d5033828be58"
[[package]]
name = "quick-xml"
version = "0.34.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f24d770aeca0eacb81ac29dfbc55ebcc09312fdd1f8bbecdc7e4a84e000e3b4"
dependencies = [
"memchr",
]
[[package]]
name = "quote"
version = "1.0.36"
@ -3459,12 +3719,31 @@ dependencies = [
"winapi-util",
]
[[package]]
name = "scoped-tls"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294"
[[package]]
name = "scopeguard"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "sctk-adwaita"
version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6277f0217056f77f1d8f49f2950ac6c278c0d607c45f5ee99328d792ede24ec"
dependencies = [
"ab_glyph",
"log",
"memmap2",
"smithay-client-toolkit",
"tiny-skia",
]
[[package]]
name = "semver"
version = "1.0.23"
@ -3566,6 +3845,31 @@ version = "1.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
[[package]]
name = "smithay-client-toolkit"
version = "0.19.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3457dea1f0eb631b4034d61d4d8c32074caa6cd1ab2d59f2327bd8461e2c0016"
dependencies = [
"bitflags 2.6.0",
"calloop",
"calloop-wayland-source",
"cursor-icon",
"libc",
"log",
"memmap2",
"rustix",
"thiserror",
"wayland-backend",
"wayland-client",
"wayland-csd-frame",
"wayland-cursor",
"wayland-protocols",
"wayland-protocols-wlr",
"wayland-scanner",
"xkeysym",
]
[[package]]
name = "smol_str"
version = "0.2.2"
@ -3602,6 +3906,12 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
[[package]]
name = "strict-num"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6637bab7722d379c8b41ba849228d680cc12d0a45ba1fa2b48f2a30577a06731"
[[package]]
name = "svg_fmt"
version = "0.4.3"
@ -3696,6 +4006,42 @@ dependencies = [
"once_cell",
]
[[package]]
name = "tiff"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba1310fcea54c6a9a4fd1aad794ecc02c31682f6bfbecdf460bf19533eed1e3e"
dependencies = [
"flate2",
"jpeg-decoder",
"weezl",
]
[[package]]
name = "tiny-skia"
version = "0.11.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "83d13394d44dae3207b52a326c0c85a8bf87f1541f23b0d143811088497b09ab"
dependencies = [
"arrayref",
"arrayvec",
"bytemuck",
"cfg-if",
"log",
"tiny-skia-path",
]
[[package]]
name = "tiny-skia-path"
version = "0.11.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c9e7fc0c2e86a30b117d0462aa261b72b7a99b7ebd7deb3a14ceda95c5bdc93"
dependencies = [
"arrayref",
"bytemuck",
"strict-num",
]
[[package]]
name = "tinyvec"
version = "1.8.0"
@ -3839,12 +4185,27 @@ version = "1.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
[[package]]
name = "unicode-bidi"
version = "0.3.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75"
[[package]]
name = "unicode-ident"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]]
name = "unicode-normalization"
version = "0.1.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5"
dependencies = [
"tinyvec",
]
[[package]]
name = "unicode-segmentation"
version = "1.11.0"
@ -3863,6 +4224,17 @@ version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
[[package]]
name = "url"
version = "2.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c"
dependencies = [
"form_urlencoded",
"idna",
"percent-encoding",
]
[[package]]
name = "uuid"
version = "1.10.0"
@ -3973,6 +4345,115 @@ version = "0.2.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96"
[[package]]
name = "wayland-backend"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f90e11ce2ca99c97b940ee83edbae9da2d56a08f9ea8158550fd77fa31722993"
dependencies = [
"cc",
"downcast-rs",
"rustix",
"scoped-tls",
"smallvec",
"wayland-sys",
]
[[package]]
name = "wayland-client"
version = "0.31.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7e321577a0a165911bdcfb39cf029302479d7527b517ee58ab0f6ad09edf0943"
dependencies = [
"bitflags 2.6.0",
"rustix",
"wayland-backend",
"wayland-scanner",
]
[[package]]
name = "wayland-csd-frame"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "625c5029dbd43d25e6aa9615e88b829a5cad13b2819c4ae129fdbb7c31ab4c7e"
dependencies = [
"bitflags 2.6.0",
"cursor-icon",
"wayland-backend",
]
[[package]]
name = "wayland-cursor"
version = "0.31.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ef9489a8df197ebf3a8ce8a7a7f0a2320035c3743f3c1bd0bdbccf07ce64f95"
dependencies = [
"rustix",
"wayland-client",
"xcursor",
]
[[package]]
name = "wayland-protocols"
version = "0.32.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62989625a776e827cc0f15d41444a3cea5205b963c3a25be48ae1b52d6b4daaa"
dependencies = [
"bitflags 2.6.0",
"wayland-backend",
"wayland-client",
"wayland-scanner",
]
[[package]]
name = "wayland-protocols-plasma"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f79f2d57c7fcc6ab4d602adba364bf59a5c24de57bd194486bf9b8360e06bfc4"
dependencies = [
"bitflags 2.6.0",
"wayland-backend",
"wayland-client",
"wayland-protocols",
"wayland-scanner",
]
[[package]]
name = "wayland-protocols-wlr"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd993de54a40a40fbe5601d9f1fbcaef0aebcc5fda447d7dc8f6dcbaae4f8953"
dependencies = [
"bitflags 2.6.0",
"wayland-backend",
"wayland-client",
"wayland-protocols",
"wayland-scanner",
]
[[package]]
name = "wayland-scanner"
version = "0.31.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d7b56f89937f1cf2ee1f1259cf2936a17a1f45d8f0aa1019fae6d470d304cfa6"
dependencies = [
"proc-macro2",
"quick-xml",
"quote",
]
[[package]]
name = "wayland-sys"
version = "0.31.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43676fe2daf68754ecf1d72026e4e6c15483198b5d24e888b74d3f22f887a148"
dependencies = [
"dlib",
"log",
"once_cell",
"pkg-config",
]
[[package]]
name = "web-sys"
version = "0.3.69"
@ -3993,6 +4474,30 @@ dependencies = [
"wasm-bindgen",
]
[[package]]
name = "webbrowser"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "425ba64c1e13b1c6e8c5d2541c8fac10022ca584f33da781db01b5756aef1f4e"
dependencies = [
"block2",
"core-foundation",
"home",
"jni",
"log",
"ndk-context",
"objc2",
"objc2-foundation",
"url",
"web-sys",
]
[[package]]
name = "weezl"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53a85b86a771b1c87058196170769dd264f66c0782acf1ae6cc51bfd64b39082"
[[package]]
name = "wgpu"
version = "0.20.1"
@ -4294,6 +4799,15 @@ dependencies = [
"windows-targets 0.42.2",
]
[[package]]
name = "windows-sys"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
dependencies = [
"windows-targets 0.48.5",
]
[[package]]
name = "windows-sys"
version = "0.52.0"
@ -4487,6 +5001,7 @@ version = "0.30.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4225ddd8ab67b8b59a2fee4b34889ebf13c0460c1c3fa297c58e21eb87801b33"
dependencies = [
"ahash",
"android-activity",
"atomic-waker",
"bitflags 2.6.0",
@ -4501,6 +5016,7 @@ dependencies = [
"dpi",
"js-sys",
"libc",
"memmap2",
"ndk 0.9.0",
"objc2",
"objc2-app-kit",
@ -4512,11 +5028,17 @@ dependencies = [
"raw-window-handle",
"redox_syscall 0.4.1",
"rustix",
"sctk-adwaita",
"smithay-client-toolkit",
"smol_str",
"tracing",
"unicode-segmentation",
"wasm-bindgen",
"wasm-bindgen-futures",
"wayland-backend",
"wayland-client",
"wayland-protocols",
"wayland-protocols-plasma",
"web-sys",
"web-time",
"windows-sys 0.52.0",
@ -4575,6 +5097,12 @@ version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec107c4503ea0b4a98ef47356329af139c0a4f7750e621cf2973cd3385ebcb3d"
[[package]]
name = "xcursor"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d491ee231a51ae64a5b762114c3ac2104b967aadba1de45c86ca42cf051513b7"
[[package]]
name = "xi-unicode"
version = "0.3.0"

View File

@ -6,6 +6,7 @@ edition = "2021"
[dependencies]
avian3d = "0.1.1"
bevy = { version = "0.14.0", features = ["bevy_dev_tools"] }
bevy-inspector-egui = "0.25.1"
[features]
no-mesh = []

58
src/bike.rs Normal file
View File

@ -0,0 +1,58 @@
use std::f32::consts::FRAC_PI_2;
use avian3d::prelude::*;
use bevy::prelude::*;
use crate::physics::CatControllerState;
#[derive(Component)]
pub struct CyberBikeBody;
fn spawn_bike(
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>,
) {
let xform = Transform::from_xyz(0.0, 4.0, 0.0);
let body_collider =
Collider::capsule_endpoints(0.5, Vec3::new(0.0, 0.0, -0.65), Vec3::new(0.0, 0.0, 0.8));
let _bike = commands
.spawn(SpatialBundle::from_transform(xform))
.insert((
RigidBody::Dynamic,
body_collider,
CollisionLayers::from_bits(1, 1),
SleepingDisabled,
CyberBikeBody,
CatControllerState::default(),
ColliderDensity(0.12),
LinearDamping(0.1),
AngularDamping(2.0),
LinearVelocity::ZERO,
AngularVelocity::ZERO,
ExternalForce::ZERO.with_persistence(false),
ExternalTorque::ZERO.with_persistence(false),
))
.with_children(|builder| {
let color = Color::srgb(0.7, 0.05, 0.7);
let mut rotation = Transform::default(); // Transform::from_rotation(Quat::from_rotation_y(FRAC_PI_2));
rotation.rotate_x(FRAC_PI_2);
let pbr_bundle = PbrBundle {
mesh: meshes.add(Capsule3d::new(0.5, 1.45)),
transform: rotation,
material: materials.add(color),
..Default::default()
};
builder.spawn(pbr_bundle);
})
.id();
}
pub struct CyberBikePlugin;
impl Plugin for CyberBikePlugin {
fn build(&self, app: &mut App) {
app.add_systems(Startup, spawn_bike);
}
}

98
src/camera.rs Normal file
View File

@ -0,0 +1,98 @@
use bevy::{prelude::*, utils::HashSet};
use crate::bike::CyberBikeBody;
#[derive(Component)]
pub struct CyberCameras;
#[derive(Debug, Resource)]
pub struct DebugCamOffset {
pub rot: f32,
pub dist: f32,
pub alt: f32,
}
impl Default for DebugCamOffset {
fn default() -> Self {
DebugCamOffset {
rot: 60.0,
dist: 10.0,
alt: 4.0,
}
}
}
fn spawn_camera(mut commands: Commands) {
commands
.spawn(Camera3dBundle::default())
.insert(CyberCameras);
}
fn update_camera_pos(mut offset: ResMut<DebugCamOffset>, mut keys: ResMut<ButtonInput<KeyCode>>) {
let keyset: HashSet<_> = keys.get_pressed().collect();
let shifted = keyset.contains(&KeyCode::ShiftLeft) || keyset.contains(&KeyCode::ShiftRight);
for key in keyset {
match key {
KeyCode::ArrowLeft => offset.rot -= 5.0,
KeyCode::ArrowRight => offset.rot += 5.0,
KeyCode::ArrowUp => {
if shifted {
bevy::log::info!("up, shifted");
offset.alt += 0.5;
} else {
bevy::log::info!("up");
offset.dist -= 0.5;
}
}
KeyCode::ArrowDown => {
if shifted {
bevy::log::info!("down, shifted");
offset.alt -= 0.5;
} else {
bevy::log::info!("down");
offset.dist += 0.5;
}
}
_ => continue,
}
}
let just_released: HashSet<_> = keys.get_just_released().cloned().collect();
if !just_released.is_empty() {
let released_shift = just_released.contains(&KeyCode::ShiftLeft)
|| just_released.contains(&KeyCode::ShiftRight);
keys.reset_all();
if !released_shift && shifted {
keys.press(KeyCode::ShiftLeft);
}
}
}
fn follow_bike(
mut camera: Query<&mut Transform, (With<CyberCameras>, Without<CyberBikeBody>)>,
bike: Query<&Transform, (With<CyberBikeBody>, Without<CyberCameras>)>,
offset: Res<DebugCamOffset>,
) {
let bike_xform = *bike.single();
let up = Vec3::Y;
let mut ncx = Transform::from_translation(bike_xform.translation);
ncx.rotate(Quat::from_axis_angle(up, offset.rot.to_radians()));
ncx.translation += ncx.forward() * offset.dist;
ncx.translation += ncx.up() * offset.alt;
ncx.look_at(bike_xform.translation, up);
let mut cam_xform = camera.single_mut();
*cam_xform = ncx;
}
pub struct CamPlug;
impl Plugin for CamPlug {
fn build(&self, app: &mut App) {
app.insert_resource(DebugCamOffset::default())
.add_systems(Startup, spawn_camera)
.add_systems(Update, (follow_bike, update_camera_pos));
}
}

View File

@ -1,16 +1,23 @@
use avian3d::prelude::*;
use bevy::{self, color::palettes::css::SILVER, prelude::*};
use bevy_inspector_egui::quick::WorldInspectorPlugin;
mod bike;
mod camera;
mod physics;
use bike::CyberBikePlugin;
use camera::CamPlug;
use physics::CyberPhysicsPlugin;
fn main() {
let mut app = App::new();
app.add_plugins((
DefaultPlugins,
PhysicsPlugins::default(),
PhysicsDebugPlugin::default(),
CamPlug,
CyberBikePlugin,
CyberPhysicsPlugin,
WorldInspectorPlugin::new(),
))
.insert_gizmo_config(
PhysicsGizmos {
@ -19,7 +26,7 @@ fn main() {
joint_separation_color: Some(Srgba::RED.into()),
#[cfg(feature = "no-mesh")]
hide_meshes: true,
//axis_lengths: Some(Vec3::ZERO),
axis_lengths: Some(Vec3::new(2.0, 2.0, 4.0)),
..Default::default()
},
GizmoConfig::default(),
@ -40,7 +47,7 @@ fn ground_and_light(
PbrBundle {
mesh: meshes.add(Plane3d::default().mesh().size(50.0, 50.0)),
material: materials.add(Color::from(SILVER)),
transform: Transform::from_xyz(0.0, 0.5, 0.0),
transform: Transform::from_xyz(0.0, -3., 0.0),
..default()
},
));
@ -72,164 +79,3 @@ fn close_on_esc(
}
}
}
mod bike {
use std::f32::consts::FRAC_PI_2;
use avian3d::prelude::*;
use bevy::prelude::*;
#[derive(Component)]
pub struct CyberBikeBody;
fn spawn_bike(
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>,
) {
let xform = Transform::from_xyz(0.0, 4.0, 0.0);
let body_collider =
Collider::capsule_endpoints(0.5, Vec3::new(0.0, 0.0, -0.65), Vec3::new(0.0, 0.0, 0.8));
let _bike = commands
.spawn(SpatialBundle::from_transform(xform))
.insert((
RigidBody::Dynamic,
body_collider,
SleepingDisabled,
CyberBikeBody,
//CatControllerState::default(),
ColliderDensity(0.06),
LinearDamping(0.1),
AngularDamping(2.0),
LinearVelocity::ZERO,
AngularVelocity::ZERO,
ExternalForce::ZERO.with_persistence(false),
ExternalTorque::ZERO.with_persistence(false),
))
.with_children(|builder| {
let color = Color::srgb(0.7, 0.05, 0.7);
let mut rotation = Transform::from_rotation(Quat::from_rotation_y(FRAC_PI_2));
rotation.rotate_x(FRAC_PI_2);
let pbr_bundle = PbrBundle {
mesh: meshes.add(Capsule3d::new(0.5, 1.45)),
transform: rotation,
material: materials.add(color),
..Default::default()
};
builder.spawn(pbr_bundle);
});
}
pub struct CyberBikePlugin;
impl Plugin for CyberBikePlugin {
fn build(&self, app: &mut App) {
app.add_systems(Startup, spawn_bike);
}
}
}
mod camera {
use bevy::{prelude::*, utils::HashSet};
use crate::bike::CyberBikeBody;
#[derive(Component)]
pub struct CyberCameras;
#[derive(Debug, Resource)]
pub struct DebugCamOffset {
pub rot: f32,
pub dist: f32,
pub alt: f32,
}
impl Default for DebugCamOffset {
fn default() -> Self {
DebugCamOffset {
rot: 60.0,
dist: 10.0,
alt: 4.0,
}
}
}
fn spawn_camera(mut commands: Commands) {
commands
.spawn(Camera3dBundle::default())
.insert(CyberCameras);
}
fn update_camera_pos(
mut offset: ResMut<DebugCamOffset>,
mut keys: ResMut<ButtonInput<KeyCode>>,
) {
let keyset: HashSet<_> = keys.get_pressed().collect();
let shifted = keyset.contains(&KeyCode::ShiftLeft) || keyset.contains(&KeyCode::ShiftRight);
for key in keyset {
match key {
KeyCode::ArrowLeft => offset.rot -= 5.0,
KeyCode::ArrowRight => offset.rot += 5.0,
KeyCode::ArrowUp => {
if shifted {
bevy::log::info!("up, shifted");
offset.alt += 0.5;
} else {
bevy::log::info!("up");
offset.dist -= 0.5;
}
}
KeyCode::ArrowDown => {
if shifted {
bevy::log::info!("down, shifted");
offset.alt -= 0.5;
} else {
bevy::log::info!("down");
offset.dist += 0.5;
}
}
_ => continue,
}
}
let just_released: HashSet<_> = keys.get_just_released().cloned().collect();
if !just_released.is_empty() {
let released_shift = just_released.contains(&KeyCode::ShiftLeft)
|| just_released.contains(&KeyCode::ShiftRight);
keys.reset_all();
if !released_shift && shifted {
keys.press(KeyCode::ShiftLeft);
}
}
}
fn follow_bike(
mut camera: Query<&mut Transform, (With<CyberCameras>, Without<CyberBikeBody>)>,
bike: Query<&Transform, (With<CyberBikeBody>, Without<CyberCameras>)>,
offset: Res<DebugCamOffset>,
) {
let bike_xform = *bike.single();
let up = Vec3::Y;
let mut ncx = bike_xform;
ncx.rotate(Quat::from_axis_angle(up, offset.rot.to_radians()));
ncx.translation += ncx.forward() * offset.dist;
ncx.translation += ncx.up() * offset.alt;
ncx.look_at(bike_xform.translation, up);
let mut cam_xform = camera.single_mut();
*cam_xform = ncx;
}
pub struct CamPlug;
impl Plugin for CamPlug {
fn build(&self, app: &mut App) {
app.insert_resource(DebugCamOffset::default())
.add_systems(Startup, spawn_camera)
.add_systems(Update, (follow_bike, update_camera_pos));
}
}
}

166
src/physics.rs Normal file
View File

@ -0,0 +1,166 @@
use avian3d::prelude::*;
use bevy::prelude::*;
use crate::CyberBikePlugin;
#[derive(Resource, Default, Debug, Reflect)]
#[reflect(Resource)]
struct CyberLean {
pub lean: f32,
}
#[derive(Debug, Resource, Reflect)]
#[reflect(Resource)]
pub struct CatControllerSettings {
pub kp: f32,
pub kd: f32,
pub ki: f32,
}
impl Default for CatControllerSettings {
fn default() -> Self {
Self {
kp: 10.0,
kd: 1.0,
ki: 0.1,
}
}
}
#[derive(Component, Debug, Clone, Copy)]
pub struct CatControllerState {
pub roll_integral: f32,
pub roll_prev: f32,
decay_factor: f32,
roll_limit: f32,
}
impl Default for CatControllerState {
fn default() -> Self {
Self {
roll_integral: Default::default(),
roll_prev: Default::default(),
decay_factor: 0.99,
roll_limit: 1.5,
}
}
}
impl CatControllerState {
pub fn decay(&mut self) {
if self.roll_integral.abs() > 0.001 {
self.roll_integral *= self.decay_factor;
}
}
pub fn update_roll(&mut self, error: f32, dt: f32) -> (f32, f32) {
let lim = self.roll_limit;
self.roll_integral = (self.roll_integral + (error * dt)).min(lim).max(-lim);
let derivative = (error - self.roll_prev) / dt;
self.roll_prev = error;
(derivative, self.roll_integral)
}
pub fn set_integral_limits(&mut self, roll: f32) {
self.roll_limit = roll;
}
}
mod systems {
use std::f32::consts::{FRAC_PI_3, FRAC_PI_4};
use avian3d::prelude::*;
use bevy::prelude::*;
use super::{CatControllerSettings, CatControllerState, CyberLean};
use crate::bike::CyberBikeBody;
fn _yaw_to_angle(yaw: f32) -> f32 {
let v = yaw.powi(5) * FRAC_PI_4;
if v.is_normal() {
v
} else {
0.0
}
}
fn rotate_point(pt: &Vec3, rot: &Quat) -> Vec3 {
// thanks to https://danceswithcode.net/engineeringnotes/quaternions/quaternions.html
let [x, y, z] = pt.normalize().to_array();
let qpt = Quat::from_xyzw(x, y, z, 0.0);
// p' = rot^-1 * qpt * rot
let rot_qpt = rot.inverse() * qpt * *rot;
// why does this need to be inverted???
-Vec3::from_array([rot_qpt.x, rot_qpt.y, rot_qpt.z])
}
pub(super) fn calculate_lean(
bike_state: Query<(&LinearVelocity, &Transform), With<CyberBikeBody>>,
mut lean: ResMut<CyberLean>,
) {
let (velocity, xform) = bike_state.single();
let vel = velocity.dot(*xform.forward());
let v_squared = vel.powi(2);
let wheel_base = 1.145f32;
let radius = wheel_base;
let gravity = -9.8f32;
let v2_r = v_squared / radius;
let tan_theta = (v2_r / gravity).clamp(-FRAC_PI_3, FRAC_PI_3);
if tan_theta.is_finite() && !tan_theta.is_subnormal() {
lean.lean = tan_theta.atan().clamp(-FRAC_PI_3, FRAC_PI_3);
} else {
lean.lean = 0.0;
}
}
pub(super) fn apply_lean(
mut bike_query: Query<(&Transform, &mut ExternalTorque, &mut CatControllerState)>,
time: Res<Time>,
settings: Res<CatControllerSettings>,
lean: Res<CyberLean>,
mut gizmos: Gizmos,
) {
let (xform, mut torque, mut control_vars) = bike_query.single_mut();
let world_up = xform.translation.normalize();
let rot = Quat::from_axis_angle(*xform.back(), lean.lean);
let target_up = rotate_point(&world_up, &rot).normalize();
let bike_right = xform.right();
let roll_error = bike_right.dot(target_up);
let pitch_error = world_up.dot(*xform.back());
// only try to correct roll if we're not totally vertical
if pitch_error.abs() < 0.95 {
let (derivative, integral) = control_vars.update_roll(roll_error, time.delta_seconds());
let mag =
(settings.kp * roll_error) + (settings.ki * integral) + (settings.kd * derivative);
if mag.is_finite() {
let tork = mag * *xform.back();
torque.apply_torque(tork);
gizmos.arrow(
xform.translation + Vec3::Y,
xform.translation + tork + Vec3::Y,
Color::WHITE,
);
}
}
}
}
use systems::{apply_lean, calculate_lean};
pub struct CyberPhysicsPlugin;
impl Plugin for CyberPhysicsPlugin {
fn build(&self, app: &mut App) {
app.init_resource::<CatControllerSettings>()
.register_type::<CatControllerSettings>()
.init_resource::<CyberLean>()
.register_type::<CyberLean>()
.add_plugins((PhysicsPlugins::default(), PhysicsDebugPlugin::default()))
.add_systems(Update, (apply_lean, calculate_lean));
}
}