Physics Support #8

Merged
reo merged 6 commits from 2025-10-19-physics into master 2025-11-16 15:38:20 +00:00
19 changed files with 1013 additions and 61 deletions

523
Cargo.lock generated
View file

@ -46,6 +46,12 @@ dependencies = [
"zerocopy",
]
[[package]]
name = "allocator-api2"
version = "0.2.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923"
[[package]]
name = "android-activity"
version = "0.6.0"
@ -64,7 +70,7 @@ dependencies = [
"ndk-context",
"ndk-sys",
"num_enum",
"thiserror",
"thiserror 1.0.69",
]
[[package]]
@ -79,6 +85,15 @@ version = "1.0.99"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b0674a1ddeecb70197781e945de4b3b8ffb61fa939a5597bcf48503737663100"
[[package]]
name = "approx"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6"
dependencies = [
"num-traits",
]
[[package]]
name = "arrayref"
version = "0.3.9"
@ -130,6 +145,12 @@ version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
[[package]]
name = "bit-vec"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7"
[[package]]
name = "bit_field"
version = "0.10.3"
@ -198,7 +219,7 @@ dependencies = [
"polling",
"rustix 0.38.44",
"slab",
"thiserror",
"thiserror 1.0.69",
]
[[package]]
@ -393,12 +414,33 @@ version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2"
[[package]]
name = "downcast-rs"
version = "2.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "117240f60069e65410b3ae1bb213295bd828f707b5bec6596a1afc8793ce0cbc"
[[package]]
name = "dpi"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8b14ccef22fc6f5a8f4d7d768562a182c04ce9a3b3157b91390b52ddfdf1a76"
[[package]]
name = "either"
version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
[[package]]
name = "ena"
version = "0.14.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d248bdd43ce613d87415282f69b9bb99d947d290b10962dd6c56233312c2ad5"
dependencies = [
"log",
]
[[package]]
name = "equivalent"
version = "1.0.2"
@ -455,6 +497,18 @@ version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]]
name = "foldhash"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
[[package]]
name = "foldhash"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb"
[[package]]
name = "foreign-types"
version = "0.5.0"
@ -521,6 +575,96 @@ dependencies = [
"xml-rs",
]
[[package]]
name = "glam"
version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "333928d5eb103c5d4050533cec0384302db6be8ef7d3cebd30ec6a35350353da"
[[package]]
name = "glam"
version = "0.15.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3abb554f8ee44336b72d522e0a7fe86a29e09f839a36022fa869a7dfe941a54b"
[[package]]
name = "glam"
version = "0.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4126c0479ccf7e8664c36a2d719f5f2c140fbb4f9090008098d2c291fa5b3f16"
[[package]]
name = "glam"
version = "0.17.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e01732b97afd8508eee3333a541b9f7610f454bb818669e66e90f5f57c93a776"
[[package]]
name = "glam"
version = "0.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "525a3e490ba77b8e326fb67d4b44b4bd2f920f44d4cc73ccec50adc68e3bee34"
[[package]]
name = "glam"
version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b8509e6791516e81c1a630d0bd7fbac36d2fa8712a9da8662e716b52d5051ca"
[[package]]
name = "glam"
version = "0.20.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f43e957e744be03f5801a55472f593d43fabdebf25a4585db250f04d86b1675f"
[[package]]
name = "glam"
version = "0.21.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "518faa5064866338b013ff9b2350dc318e14cc4fcd6cb8206d7e7c9886c98815"
[[package]]
name = "glam"
version = "0.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "12f597d56c1bd55a811a1be189459e8fad2bbc272616375602443bdfb37fa774"
[[package]]
name = "glam"
version = "0.23.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e4afd9ad95555081e109fe1d21f2a30c691b5f0919c67dfa690a2e1eb6bd51c"
[[package]]
name = "glam"
version = "0.24.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5418c17512bdf42730f9032c74e1ae39afc408745ebb2acf72fbc4691c17945"
[[package]]
name = "glam"
version = "0.25.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "151665d9be52f9bb40fc7966565d39666f2d1e69233571b71b87791c7e0528b3"
[[package]]
name = "glam"
version = "0.27.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e05e7e6723e3455f4818c7b26e855439f7546cf617ef669d1adedb8669e5cb9"
[[package]]
name = "glam"
version = "0.28.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "779ae4bf7e8421cf91c0b3b64e7e8b40b862fba4d393f59150042de7c4965a94"
[[package]]
name = "glam"
version = "0.29.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8babf46d4c1c9d92deac9f7be466f76dfc4482b6452fc5024b5e8daf6ffeb3ee"
[[package]]
name = "glam"
version = "0.30.8"
@ -659,6 +803,15 @@ dependencies = [
"crunchy",
]
[[package]]
name = "hash32"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606"
dependencies = [
"byteorder",
]
[[package]]
name = "hashbrown"
version = "0.14.5"
@ -673,6 +826,30 @@ name = "hashbrown"
version = "0.15.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5"
dependencies = [
"allocator-api2",
"equivalent",
"foldhash 0.1.5",
]
[[package]]
name = "hashbrown"
version = "0.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d"
dependencies = [
"foldhash 0.2.0",
]
[[package]]
name = "heapless"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad"
dependencies = [
"hash32",
"stable_deref_trait",
]
[[package]]
name = "hecs"
@ -784,7 +961,7 @@ dependencies = [
"combine",
"jni-sys",
"log",
"thiserror",
"thiserror 1.0.69",
"walkdir",
"windows-sys 0.45.0",
]
@ -849,6 +1026,12 @@ dependencies = [
"windows-targets 0.53.3",
]
[[package]]
name = "libm"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de"
[[package]]
name = "libredox"
version = "0.1.9"
@ -888,6 +1071,16 @@ version = "0.4.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94"
[[package]]
name = "matrixmultiply"
version = "0.3.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a06de3016e9fae57a36fd14dba131fccf49f74b40b7fbdb472f96e361ec71a08"
dependencies = [
"autocfg",
"rawpointer",
]
[[package]]
name = "memchr"
version = "2.7.5"
@ -938,6 +1131,49 @@ dependencies = [
"pxfm",
]
[[package]]
name = "nalgebra"
version = "0.34.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4d5b3eff5cd580f93da45e64715e8c20a3996342f1e466599cf7a267a0c2f5f"
dependencies = [
"approx",
"glam 0.14.0",
"glam 0.15.2",
"glam 0.16.0",
"glam 0.17.3",
"glam 0.18.0",
"glam 0.19.0",
"glam 0.20.5",
"glam 0.21.3",
"glam 0.22.0",
"glam 0.23.0",
"glam 0.24.2",
"glam 0.25.0",
"glam 0.27.0",
"glam 0.28.0",
"glam 0.29.3",
"glam 0.30.8",
"matrixmultiply",
"nalgebra-macros",
"num-complex",
"num-rational",
"num-traits",
"simba",
"typenum",
]
[[package]]
name = "nalgebra-macros"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "973e7178a678cfd059ccec50887658d482ce16b0aa9da3888ddeab5cd5eb4889"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "ndk"
version = "0.9.0"
@ -950,7 +1186,7 @@ dependencies = [
"ndk-sys",
"num_enum",
"raw-window-handle",
"thiserror",
"thiserror 1.0.69",
]
[[package]]
@ -968,6 +1204,56 @@ dependencies = [
"jni-sys",
]
[[package]]
name = "num-bigint"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9"
dependencies = [
"num-integer",
"num-traits",
]
[[package]]
name = "num-complex"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495"
dependencies = [
"num-traits",
]
[[package]]
name = "num-derive"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "num-integer"
version = "0.1.46"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f"
dependencies = [
"num-traits",
]
[[package]]
name = "num-rational"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824"
dependencies = [
"num-bigint",
"num-integer",
"num-traits",
]
[[package]]
name = "num-traits"
version = "0.2.19"
@ -975,6 +1261,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
dependencies = [
"autocfg",
"libm",
]
[[package]]
@ -1269,6 +1556,15 @@ dependencies = [
"libredox",
]
[[package]]
name = "ordered-float"
version = "5.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f4779c6901a562440c3786d08192c6fbda7c1c2060edd10006b05ee35d10f2d"
dependencies = [
"num-traits",
]
[[package]]
name = "owned_ttf_parser"
version = "0.25.1"
@ -1301,6 +1597,40 @@ dependencies = [
"windows-targets 0.52.6",
]
[[package]]
name = "parry3d"
version = "0.25.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "017be73f24c8ca8b10f9727616e5cb9af82b98488cc6d5eea468e727ffa780ca"
dependencies = [
"approx",
"arrayvec",
"bitflags 2.9.1",
"downcast-rs 2.0.2",
"either",
"ena",
"foldhash 0.2.0",
"hashbrown 0.16.0",
"log",
"nalgebra",
"num-derive",
"num-traits",
"ordered-float",
"rstar",
"simba",
"slab",
"smallvec",
"spade",
"static_assertions",
"thiserror 2.0.17",
]
[[package]]
name = "paste"
version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
[[package]]
name = "percent-encoding"
version = "2.3.1"
@ -1384,6 +1714,25 @@ dependencies = [
"unicode-ident",
]
[[package]]
name = "profiling"
version = "1.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3eb8486b569e12e2c32ad3e204dbaba5e4b5b216e9367044f25f1dba42341773"
dependencies = [
"profiling-procmacros",
]
[[package]]
name = "profiling-procmacros"
version = "1.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "52717f9a02b6965224f95ca2a81e2e0c5c43baacd28ca057577988930b6c3d5b"
dependencies = [
"quote",
"syn",
]
[[package]]
name = "pxfm"
version = "0.1.24"
@ -1436,19 +1785,21 @@ dependencies = [
name = "raidillon_ecs"
version = "0.1.0"
dependencies = [
"glam",
"glam 0.30.8",
"raidillon_assets",
"rapier3d",
]
[[package]]
name = "raidillon_engine"
version = "0.1.0"
dependencies = [
"glam",
"glam 0.30.8",
"hecs",
"indexmap",
"raidillon_assets",
"raidillon_core",
"raidillon_ecs",
"raidillon_platform",
"winit",
]
@ -1457,13 +1808,16 @@ dependencies = [
name = "raidillon_game"
version = "0.1.0"
dependencies = [
"glam",
"glam 0.30.8",
"hecs",
"raidillon_assets",
"raidillon_core",
"raidillon_ecs",
"raidillon_engine",
"raidillon_glium",
"raidillon_physics",
"raidillon_platform",
"rapier3d",
"winit",
]
@ -1473,7 +1827,7 @@ version = "0.1.0"
dependencies = [
"anyhow",
"exr",
"glam",
"glam 0.30.8",
"glium",
"gltf",
"image",
@ -1489,22 +1843,62 @@ dependencies = [
"winit",
]
[[package]]
name = "raidillon_physics"
version = "0.1.0"
dependencies = [
"glam 0.30.8",
"raidillon_ecs",
"rapier3d",
]
[[package]]
name = "raidillon_platform"
version = "0.1.0"
dependencies = [
"glam",
"glam 0.30.8",
"raidillon_assets",
"raidillon_core",
"winit",
]
[[package]]
name = "rapier3d"
version = "0.30.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5bd27b8eb36d0833fa0f2aea40164fabfad0fc34b9932286ae9e84f3452f5364"
dependencies = [
"approx",
"arrayvec",
"bit-vec",
"bitflags 2.9.1",
"downcast-rs 2.0.2",
"log",
"nalgebra",
"num-derive",
"num-traits",
"ordered-float",
"parry3d",
"profiling",
"rustc-hash",
"simba",
"static_assertions",
"thiserror 2.0.17",
"wide",
]
[[package]]
name = "raw-window-handle"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539"
[[package]]
name = "rawpointer"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3"
[[package]]
name = "rayon-core"
version = "1.13.0"
@ -1533,12 +1927,35 @@ dependencies = [
"bitflags 2.9.1",
]
[[package]]
name = "robust"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4e27ee8bb91ca0adcf0ecb116293afa12d393f9c2b9b9cd54d33e8078fe19839"
[[package]]
name = "rstar"
version = "0.12.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "421400d13ccfd26dfa5858199c30a5d76f9c54e0dba7575273025b43c5175dbb"
dependencies = [
"heapless",
"num-traits",
"smallvec",
]
[[package]]
name = "rustc-demangle"
version = "0.1.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace"
[[package]]
name = "rustc-hash"
version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d"
[[package]]
name = "rustix"
version = "0.38.44"
@ -1577,6 +1994,15 @@ version = "1.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
[[package]]
name = "safe_arch"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96b02de82ddbe1b636e6170c21be622223aea188ef2e139be0a5b219ec215323"
dependencies = [
"bytemuck",
]
[[package]]
name = "same-file"
version = "1.0.6"
@ -1649,6 +2075,19 @@ version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
[[package]]
name = "simba"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c99284beb21666094ba2b75bbceda012e610f5479dfcc2d6e2426f53197ffd95"
dependencies = [
"approx",
"num-complex",
"num-traits",
"paste",
"wide",
]
[[package]]
name = "simd-adler32"
version = "0.3.7"
@ -1681,7 +2120,7 @@ dependencies = [
"log",
"memmap2",
"rustix 0.38.44",
"thiserror",
"thiserror 1.0.69",
"wayland-backend",
"wayland-client",
"wayland-csd-frame",
@ -1701,12 +2140,36 @@ dependencies = [
"serde",
]
[[package]]
name = "spade"
version = "2.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a14e31a007e9f85c32784b04f89e6e194bb252a4d41b4a8ccd9e77245d901c8c"
dependencies = [
"hashbrown 0.15.4",
"num-traits",
"robust",
"smallvec",
]
[[package]]
name = "spin"
version = "0.9.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
[[package]]
name = "stable_deref_trait"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596"
[[package]]
name = "static_assertions"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
[[package]]
name = "strict-num"
version = "0.1.1"
@ -1730,7 +2193,16 @@ version = "1.0.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
dependencies = [
"thiserror-impl",
"thiserror-impl 1.0.69",
]
[[package]]
name = "thiserror"
version = "2.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8"
dependencies = [
"thiserror-impl 2.0.17",
]
[[package]]
@ -1744,6 +2216,17 @@ dependencies = [
"syn",
]
[[package]]
name = "thiserror-impl"
version = "2.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "tiny-skia"
version = "0.11.4"
@ -1808,6 +2291,12 @@ version = "0.25.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2df906b07856748fa3f6e0ad0cbaa047052d4a7dd609e231c4f72cee8c36f31"
[[package]]
name = "typenum"
version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb"
[[package]]
name = "unicode-ident"
version = "1.0.18"
@ -1929,7 +2418,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "673a33c33048a5ade91a6b139580fa174e19fb0d23f396dca9fa15f2e1e49b35"
dependencies = [
"cc",
"downcast-rs",
"downcast-rs 1.2.1",
"rustix 1.0.8",
"scoped-tls",
"smallvec",
@ -2051,6 +2540,16 @@ dependencies = [
"wasm-bindgen",
]
[[package]]
name = "wide"
version = "0.7.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ce5da8ecb62bcd8ec8b7ea19f69a51275e91299be594ea5cc6ef7819e16cd03"
dependencies = [
"bytemuck",
"safe_arch",
]
[[package]]
name = "winapi-util"
version = "0.1.9"

View file

@ -7,4 +7,5 @@ members = [
"game",
"ecs",
"engine",
"physics",
]

BIN
assets/models/plane.glb (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/models/sphere.glb (Stored with Git LFS) Normal file

Binary file not shown.

View file

@ -6,3 +6,4 @@ edition = "2024"
[dependencies]
glam = "0.30.5"
raidillon_assets = { path = "../asset" }
rapier3d = "0.30.1"

View file

@ -15,3 +15,16 @@ impl Transform {
}
pub struct ModelHandle(pub ModelID);
#[derive(Copy, Clone)]
pub struct RigidBodyComponent(pub rapier3d::dynamics::RigidBodyHandle);
#[derive(Copy, Clone)]
pub struct CharacterBodyComponent(pub rapier3d::dynamics::RigidBodyHandle);
#[derive(Debug, Default, PartialEq, Eq, Clone, Copy)]
pub enum CameraMode {
#[default]
Kinematic,
Debug,
}

View file

@ -7,6 +7,7 @@ edition = "2024"
raidillon_assets = { path = "../asset" }
raidillon_core = { path = "../core" }
raidillon_platform = { path = "../platform" }
raidillon_ecs = { path = "../ecs" }
winit = "0.30.12"
hecs = "0.10.5"
indexmap = "2.10.0"

View file

@ -6,3 +6,4 @@ mod resources;
pub use crate::engine::Engine;
pub use crate::resources::EngineResources;
pub use input::InputState;

View file

@ -1 +0,0 @@
pub mod fps_camera;

View file

@ -13,6 +13,9 @@ raidillon_platform = { path = "../platform" }
raidillon_assets = { path = "../asset" }
raidillon_ecs = { path = "../ecs" }
raidillon_engine = { path = "../engine" }
raidillon_physics = { path = "../physics" }
raidillon_glium = { path = "../glium_platform", optional = true }
glam = "0.30.5"
winit = "0.30.12"
rapier3d = "0.30.1"
hecs = "0.10.5"

View file

@ -1,11 +1,14 @@
mod systems;
use std::fmt::format;
use glam::{Quat, Vec3};
use raidillon_engine::{Engine, system::System, EngineResources};
use rapier3d::dynamics::{CoefficientCombineRule, RigidBodyType};
use rapier3d::prelude::ColliderBuilder;
use raidillon_engine::{Engine, system::System, EngineResources, InputState};
use raidillon_engine::system::SystemContext;
use raidillon_platform::{Platform, Camera, PlatformContext};
use raidillon_assets::model_path;
use raidillon_core::engine::EngineTrait;
use raidillon_ecs::components::ModelHandle;
use raidillon_ecs::components::{CameraMode, CharacterBodyComponent, ModelHandle, RigidBodyComponent};
use raidillon_ecs::Transform;
use raidillon_core::scene::Scene;
#[cfg(feature = "glium")]
@ -14,10 +17,13 @@ use winit::event::{ElementState, Event, WindowEvent};
use winit::event::DeviceEvent::MouseMotion;
use winit::keyboard::{KeyCode, PhysicalKey};
use raidillon_core::DebugUIBuffer;
use raidillon_engine::systems::fps_camera::FPSDebugCameraSystem;
const TEST_GLTF: &str = "pink-monkey.gltf";
use systems::debug_camera::FPSDebugCameraSystem;
use raidillon_glium::RenderingSystem;
use raidillon_physics::Physics;
use crate::systems::{KeybindsSystem, KinematicCharacterController, PhysicsSystem};
const TEST_GLTF: &str = "sphere.glb";
const PLANE_GLTF: &str = "plane.glb";
const MAIN_SCENE_ID: &str = "main_scene";
#[derive(Default)]
@ -40,54 +46,83 @@ impl System for UpdateAspectRatioSystem {
}
#[derive(Default)]
struct RenderingTestSystem {
rotation_speed: std::rc::Rc<std::cell::RefCell<f32>>,
}
struct RenderingTestSystem;
impl System for RenderingTestSystem {
fn load_world(&mut self, res: &mut EngineResources, scene: &mut Scene) {
let pctx = res.get::<PlatformContext>().unwrap();
let pctx = res.get::<PlatformContext>().expect("PlatformContext missing").clone();
let physics = scene.resources.get_mut::<Physics>().expect("Physics missing");
self.rotation_speed = std::rc::Rc::new(std::cell::RefCell::new(5.0));
// Spawn Sphere
{
let tr = Transform {
translation: Vec3::new(0.0, 5.0, 0.0),
rotation: Quat::IDENTITY,
scale: Vec3::new(1.0, 1.0, 1.0),
};
let collider = ColliderBuilder::ball(1.0)
.restitution(0.7)
.restitution_combine_rule(CoefficientCombineRule::Max)
.build();
let rb_handle = physics.add_rigid_body(RigidBodyType::Dynamic, tr, collider);
pctx.asset_manager.borrow_mut().load_gltf(TEST_GLTF, &model_path(TEST_GLTF));
scene.world.spawn((
tr,
ModelHandle(TEST_GLTF),
RigidBodyComponent(rb_handle),
));
}
// Spawn Plane
{
let tr = Transform {
translation: Vec3::new(0.0, 0.0, 0.0),
rotation: Quat::IDENTITY,
scale: Vec3::new(10.0, 1.0, 10.0),
};
let collider = ColliderBuilder::cuboid(10.0, 0.01, 10.0).build();
let rb_handle = physics.add_rigid_body(RigidBodyType::Fixed, tr, collider);
pctx.asset_manager.borrow_mut().load_gltf(PLANE_GLTF, &model_path(PLANE_GLTF));
scene.world.spawn((
tr,
ModelHandle(PLANE_GLTF),
RigidBodyComponent(rb_handle),
));
}
let mut am = pctx.asset_manager.borrow_mut();
am.load_gltf(TEST_GLTF, &model_path(TEST_GLTF));
scene.world.spawn((
Transform {
translation: Vec3::new(0.0, 0.0, 0.0),
rotation: Quat::IDENTITY,
scale: Vec3::new(1.0, 1.0, 1.0),
},
ModelHandle(TEST_GLTF),
scene.world.spawn((Camera {
eye: Vec3::new(0.0, 2.0, 3.0),
center: Vec3::ZERO,
up: Vec3::Y,
fovy: 60_f32.to_radians(),
aspect: pctx.frame_width / pctx.frame_height,
znear: 0.1,
zfar: 100.0},
CameraMode::default(),
));
}
fn frame_update(&mut self, res: &mut EngineResources, scene: &mut Scene) {
let pctx = res.get::<PlatformContext>().unwrap();
let input = res.get::<InputState>().unwrap();
let dbg_ui = scene.resources.get_mut::<DebugUIBuffer>().unwrap();
dbg_ui.text("Hello World!".to_owned());
dbg_ui.text(format!("Frame Delta: {}", pctx.time_ctx.frame_dt));
dbg_ui.text(format!("Fixed Delta: {}", pctx.time_ctx.fixed_dt));
dbg_ui.text(format!("FPS: {}", 1.0 / pctx.time_ctx.frame_dt));
dbg_ui.slider_f32("Rotation Speed", -10.0, 10.0, self.rotation_speed.clone());
for (_ent, (tr, ch_component)) in scene.world.query::<(&Transform, &CharacterBodyComponent)>().iter() {
dbg_ui.text(format!("Character POS: {}", tr.translation));
}
}
fn fixed_update(&mut self, res: &mut EngineResources, scene: &mut Scene) {
let pctx = res.get::<PlatformContext>().unwrap();
scene.world.query_mut::<(&mut Transform, &ModelHandle)>().into_iter().for_each(|(_, (t, _))| {
t.rotation *= Quat::from_rotation_y(*self.rotation_speed.borrow() * pctx.time_ctx.fixed_dt);
});
}
}
fn main() {
let mut engine = Engine::new();
// Define systems
engine.system_manager.add::<PhysicsSystem>();
engine.system_manager.add::<KeybindsSystem>();
engine.system_manager.add::<KinematicCharacterController>();
engine.system_manager.add::<FPSDebugCameraSystem>();
engine.system_manager.add::<RenderingTestSystem>();
engine.system_manager.add::<UpdateAspectRatioSystem>();

View file

@ -1,4 +1,4 @@
use crate::system::{System, SystemContext};
use raidillon_engine::system::{System, SystemContext};
use glam::{Quat, Vec3};
use winit::event::DeviceEvent::MouseMotion;
use winit::event::{ElementState, Event, MouseButton, WindowEvent};
@ -6,9 +6,10 @@ use winit::keyboard::{KeyCode, PhysicalKey};
use winit::window::CursorGrabMode;
use raidillon_assets::model_path;
use raidillon_platform::{Camera, PlatformContext};
use crate::input::InputState;
use crate::resources::EngineResources;
use raidillon_engine::InputState;
use raidillon_engine::EngineResources;
use raidillon_core::scene::Scene;
use raidillon_ecs::components::CameraMode;
pub struct FPSDebugCameraSystem {
mouse_delta: (f64, f64),
@ -28,27 +29,17 @@ impl Default for FPSDebugCameraSystem {
position: Vec3::new(0.0, 0.0, 2.0),
yaw: -90.0,
pitch: 0.0,
speed: 3.0,
speed: 8.0,
sensitivity: 0.1,
}
}
}
impl System for FPSDebugCameraSystem {
fn load_world(&mut self, res: &mut EngineResources, scene: &mut Scene) {
let pctx = res.get::<PlatformContext>().unwrap();
scene.world.spawn((Camera {
eye: Vec3::new(0.0, 0.0, 2.0),
center: Vec3::ZERO,
up: Vec3::Y,
fovy: 60_f32.to_radians(),
aspect: pctx.frame_width / pctx.frame_height,
znear: 0.1,
zfar: 100.0,
},));
}
fn handle_event(&mut self, res: &mut EngineResources, scene: &mut Scene) {
if !self.is_camera_mode_valid(scene) {
return
}
let pctx = res.get::<PlatformContext>().unwrap();
let event2 = pctx.current_event.clone();
match event2 {
@ -92,6 +83,9 @@ impl System for FPSDebugCameraSystem {
}
fn frame_update(&mut self, res: &mut EngineResources, scene: &mut Scene) {
if !self.is_camera_mode_valid(scene) {
return
}
let (pctx, input) = res.get_many::<(PlatformContext, InputState)>().unwrap();
if self.mouse_enabled {
@ -134,4 +128,13 @@ impl FPSDebugCameraSystem {
yaw_rad.sin() * pitch_rad.cos(),
).normalize()
}
fn is_camera_mode_valid(&self, scene: &mut Scene) -> bool {
let mut q = scene.world.query::<(&Camera, &CameraMode)>();
let (cam_ent, (cam, cam_mode)) = q
.iter()
.next()
.unwrap();
*cam_mode == CameraMode::Debug
}
}

View file

@ -0,0 +1,57 @@
use winit::keyboard::KeyCode;
use raidillon_core::DebugUIBuffer;
use raidillon_core::scene::Scene;
use raidillon_ecs::components::CameraMode;
use raidillon_engine::{EngineResources, InputState};
use raidillon_engine::system::System;
use raidillon_platform::{Camera, PlatformContext};
#[derive(Default)]
pub struct KeybindsSystem {
camera_toggle_held: bool,
}
impl System for KeybindsSystem {
fn fixed_update(&mut self, res: &mut EngineResources, scene: &mut Scene) {
let input = res.get::<InputState>().unwrap();
if input.key_held(KeyCode::F5) {
if self.camera_toggle_held { return }
self.toggle_camera_mode(scene);
self.camera_toggle_held = true;
} else {
self.camera_toggle_held = false;
}
}
fn frame_update(&mut self, res: &mut EngineResources, scene: &mut Scene) {
let dbg_ui = scene.resources.get_mut::<DebugUIBuffer>().unwrap();
dbg_ui.text("F5 to switch camera".to_owned());
let mut q = scene.world.query::<(&Camera, &CameraMode)>();
let (cam_ent, (cam, cam_mode)) = q
.iter()
.next()
.unwrap();
dbg_ui.text(format!("Camera Mode: {:?}", cam_mode));
}
}
impl KeybindsSystem {
fn toggle_camera_mode(&mut self, scene: &mut Scene) {
let q = scene.world.query_mut::<(&mut Camera, &mut CameraMode)>();
let (cam_ent, (cam, cam_mode)) = q
.into_iter()
.next()
.unwrap();
match *cam_mode {
CameraMode::Kinematic => {
*cam_mode = CameraMode::Debug;
}
CameraMode::Debug => {
*cam_mode = CameraMode::Kinematic;
}
}
}
}

View file

@ -0,0 +1,195 @@
use glam::{Quat, Vec3};
use rapier3d::prelude::{nalgebra, ColliderBuilder, QueryFilter, RigidBodyBuilder};
use rapier3d::prelude::vector;
use raidillon_core::scene::Scene;
use raidillon_engine::{EngineResources, InputState};
use raidillon_engine::system::System;
use rapier3d::control::KinematicCharacterController as RapierKinematicCharacterController;
use rapier3d::na::{Isometry3, Vector3};
use winit::event::DeviceEvent::MouseMotion;
use winit::event::Event;
use winit::keyboard::KeyCode;
use raidillon_ecs::components::{CameraMode, CharacterBodyComponent};
use raidillon_ecs::Transform;
use raidillon_physics::Physics;
use raidillon_platform::{Camera, PlatformContext};
#[derive(Default)]
pub struct KinematicCharacterController {
character_controller: RapierKinematicCharacterController,
character_collider: ColliderBuilder,
desired_movement: Vec3,
last_position: Vector3<f32>,
yaw: f32,
pitch: f32,
speed: f32,
sensitivity: f32,
mouse_delta: (f64, f64),
vertical_velocity: f32,
gravity: f32,
max_fall_speed: f32,
}
impl System for KinematicCharacterController {
fn load_world(&mut self, res: &mut EngineResources, scene: &mut Scene) {
// create the rigid body, add it to the body set
let p = scene.resources.get_mut::<Physics>().expect("Physics missing");
let rb = RigidBodyBuilder::kinematic_position_based().build();
let rb_handle = p.rigid_body_set.insert(rb);
self.character_collider = ColliderBuilder::capsule_z(1.5, 1.0);
p.collider_set.insert_with_parent(self.character_collider.build(), rb_handle, &mut p.rigid_body_set);
let tr = Transform {
translation: Vec3::new(0.0, 2.0, 3.0),
rotation: Quat::IDENTITY,
scale: Vec3::new(1.0, 1.0, 1.0),
};
self.last_position = vector![
tr.translation.x,
tr.translation.y,
tr.translation.z,
];
scene.world.spawn((
tr,
CharacterBodyComponent(rb_handle),
));
self.speed = 5.0;
self.sensitivity = 0.1;
self.gravity = -9.81;
self.max_fall_speed = -50.0;
self.vertical_velocity = 0.0;
}
fn handle_event(&mut self, res: &mut EngineResources, scene: &mut Scene) {
if !self.is_camera_mode_valid(scene) {
return
}
let pctx = res.get::<PlatformContext>().unwrap();
let event2 = pctx.current_event.clone();
match event2 {
Event::DeviceEvent { device_id, event } => {
match event {
MouseMotion { delta } => {
self.mouse_delta.0 += delta.0;
self.mouse_delta.1 += delta.1;
},
_ => {}
}
},
_ => {},
}
}
fn frame_update(&mut self, res: &mut EngineResources, scene: &mut Scene) {
if !self.is_camera_mode_valid(scene) {
return
}
let (pctx, input) = res.get_many::<(PlatformContext, InputState)>().unwrap();
self.yaw += (self.mouse_delta.0 as f32) * self.sensitivity;
self.pitch -= (self.mouse_delta.1 as f32) * self.sensitivity;
self.pitch = self.pitch.clamp(-89.0, 89.0);
let front = self.front();
let right_vec = front.cross(Vec3::Y).normalize();
if input.key_held(KeyCode::KeyW) {
self.desired_movement += front * pctx.time_ctx.frame_dt * self.speed;
}
if input.key_held(KeyCode::KeyS) {
self.desired_movement -= front * pctx.time_ctx.frame_dt * self.speed;
}
if input.key_held(KeyCode::KeyA) {
self.desired_movement -= right_vec * pctx.time_ctx.frame_dt * self.speed;
}
if input.key_held(KeyCode::KeyD) {
self.desired_movement += right_vec * pctx.time_ctx.frame_dt * self.speed;
}
let pos = Physics::rapier_translation_to_glam(&self.last_position);
scene.world.query_mut::<&mut Camera>().into_iter().for_each(|(_, camera)| {
// INTERPOLATION NEEDED.
camera.eye = pos;
camera.center = pos + front;
});
self.mouse_delta = (0.0, 0.0);
}
fn fixed_update(&mut self, res: &mut EngineResources, scene: &mut Scene) {
if !self.is_camera_mode_valid(scene) {
return
}
let p = scene.resources.get_mut::<Physics>().unwrap();
let (pctx, input) = res.get_many::<(PlatformContext, InputState)>().unwrap();
let (ch_ent, (ch_tr, ch_component)) = scene
.world
.query_mut::<(&mut Transform, &mut CharacterBodyComponent)>()
.into_iter()
.next()
.expect("no character entity in world");
let query_pipeline = p.broad_phase.as_query_pipeline(
p.narrow_phase.query_dispatcher(),
&p.rigid_body_set,
&p.collider_set,
QueryFilter::default().exclude_rigid_body(ch_component.0),
);
self.vertical_velocity = (self.vertical_velocity + self.gravity * pctx.time_ctx.fixed_dt)
.max(self.max_fall_speed);
let mut total_displacement = self.desired_movement;
total_displacement.y += self.vertical_velocity * pctx.time_ctx.fixed_dt;
let corrected_movement = self.character_controller.move_shape(
pctx.time_ctx.fixed_dt,
&query_pipeline,
&*self.character_collider.shape,
&Isometry3::from(self.last_position),
vector![total_displacement.x, total_displacement.y, total_displacement.z],
|_| {},
);
// update character rigid body with the new translation.
if let Some(body) = p.get_rigid_body_mut(ch_component.0) {
self.last_position = vector![
self.last_position.x + corrected_movement.translation.x,
self.last_position.y + corrected_movement.translation.y,
self.last_position.z + corrected_movement.translation.z,
];
body.set_next_kinematic_position(Isometry3::from(self.last_position));
ch_tr.translation = Physics::rapier_translation_to_glam(&self.last_position);
// reset vertical velocity if grounded
if corrected_movement.grounded {
self.vertical_velocity = 0.0;
}
}
self.desired_movement = Vec3::ZERO;
}
}
impl KinematicCharacterController {
pub fn front(&self) -> Vec3 {
let yaw_rad = self.yaw.to_radians();
let pitch_rad = self.pitch.to_radians();
Vec3::new(
yaw_rad.cos() * pitch_rad.cos(),
pitch_rad.sin(),
yaw_rad.sin() * pitch_rad.cos(),
).normalize()
}
fn is_camera_mode_valid(&self, scene: &mut Scene) -> bool {
let mut q = scene.world.query::<(&Camera, &CameraMode)>();
let (cam_ent, (cam, cam_mode)) = q
.iter()
.next()
.unwrap();
*cam_mode == CameraMode::Kinematic
}
}

8
game/src/systems/mod.rs Normal file
View file

@ -0,0 +1,8 @@
mod physics;
mod kinematic_character_controller;
mod keybinds;
pub mod debug_camera;
pub use physics::PhysicsSystem;
pub use kinematic_character_controller::KinematicCharacterController;
pub use keybinds::KeybindsSystem;

View file

@ -0,0 +1,36 @@
use raidillon_core::scene::Scene;
use raidillon_ecs::components::RigidBodyComponent;
use raidillon_ecs::Transform;
use raidillon_engine::EngineResources;
use raidillon_engine::system::System;
use raidillon_physics::Physics;
use raidillon_platform::PlatformContext;
/// Do physics calculations and apply to world.
#[derive(Default)]
pub struct PhysicsSystem;
impl System for PhysicsSystem {
fn load_world(&mut self, res: &mut EngineResources, scene: &mut Scene) {
let p = Physics::default();
scene.resources.insert(p);
}
fn fixed_update(&mut self, res: &mut EngineResources, scene: &mut Scene) {
let pctx = res.get::<PlatformContext>().expect("PlatformContext missing").clone();
let physics = scene.resources.get_mut::<Physics>().expect("Physics missing");
physics.step(pctx.time_ctx.fixed_dt);
// apply calculations to dynamic bodies
let mut query = scene.world.query::<(&mut Transform, &RigidBodyComponent)>();
for (_ent, (tr, rb_component)) in query.iter() {
if let Some(body) = physics.get_rigid_body(rb_component.0) {
let pos = body.position();
let translation = Physics::rapier_translation_to_glam(&pos.translation.vector);
let rotation = Physics::rapier_rotation_to_glam(&pos.rotation);
tr.translation = translation;
tr.rotation = rotation;
}
}
}
}

9
physics/Cargo.toml Normal file
View file

@ -0,0 +1,9 @@
[package]
name = "raidillon_physics"
version = "0.1.0"
edition = "2024"
[dependencies]
rapier3d = "0.30.1"
raidillon_ecs = { path = "../ecs" }
glam = "0.30.8"

3
physics/src/lib.rs Normal file
View file

@ -0,0 +1,3 @@
mod physics;
pub use crate::physics::Physics;

82
physics/src/physics.rs Normal file
View file

@ -0,0 +1,82 @@
use glam::{Quat, Vec3};
use rapier3d::na::{Quaternion, UnitQuaternion};
use rapier3d::prelude::*;
use raidillon_ecs::Transform;
/// Tiny wrapper around rapier3d.
pub struct Physics {
pub rigid_body_set: RigidBodySet,
pub collider_set: ColliderSet,
physics_pipeline: PhysicsPipeline,
island_manager: IslandManager,
pub broad_phase: DefaultBroadPhase,
pub narrow_phase: NarrowPhase,
impulse_joint_set: ImpulseJointSet,
multibody_joint_set: MultibodyJointSet,
ccd_solver: CCDSolver,
gravity: Vector<f32>,
integration_parameters: IntegrationParameters,
}
impl Default for Physics {
fn default() -> Self {
Self {
gravity: vector![0.0, -9.81, 0.0],
rigid_body_set: Default::default(),
collider_set: Default::default(),
physics_pipeline: Default::default(),
island_manager: Default::default(),
broad_phase: Default::default(),
narrow_phase: Default::default(),
impulse_joint_set: Default::default(),
multibody_joint_set: Default::default(),
ccd_solver: Default::default(),
integration_parameters: Default::default(),
}
}
}
impl Physics {
pub fn step(&mut self, dt: f32) {
self.integration_parameters.dt = dt;
self.physics_pipeline.step(
&self.gravity,
&self.integration_parameters,
&mut self.island_manager,
&mut self.broad_phase,
&mut self.narrow_phase,
&mut self.rigid_body_set,
&mut self.collider_set,
&mut self.impulse_joint_set,
&mut self.multibody_joint_set,
&mut self.ccd_solver,
&(),
&(),
);
}
pub fn add_rigid_body(&mut self, kind: RigidBodyType, transform: Transform, collider: Collider) -> RigidBodyHandle {
let rb = RigidBodyBuilder::new(kind)
.translation(vector![transform.translation.x, transform.translation.y, transform.translation.z])
.build();
let rb_handle = self.rigid_body_set.insert(rb);
self.collider_set.insert_with_parent(collider, rb_handle, &mut self.rigid_body_set);
rb_handle
}
pub fn get_rigid_body(&self, handle: RigidBodyHandle) -> Option<&RigidBody> {
self.rigid_body_set.get(handle)
}
pub fn get_rigid_body_mut(&mut self, handle: RigidBodyHandle) -> Option<&mut RigidBody> {
self.rigid_body_set.get_mut(handle)
}
pub fn rapier_translation_to_glam(v: &Vector<f32>) -> Vec3 {
Vec3::new(v.x, v.y, v.z)
}
pub fn rapier_rotation_to_glam(r: &UnitQuaternion<f32>) -> Quat {
Quat::from_xyzw(r.i, r.j, r.k, r.w)
}
}