From 0135974d08a35f8700a15bc6f27814f6863a1eb8 Mon Sep 17 00:00:00 2001 From: reo Date: Sat, 28 Jun 2025 14:20:46 +0300 Subject: [PATCH 01/89] First Commit --- .gitignore | 2 + Cargo.lock | 2721 +++++++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 9 + justfile | 10 + opengl.png | Bin 0 -> 44866 bytes src/main.rs | 127 +++ src/teapot.rs | 2110 ++++++++++++++++++++++++++++++++++++++ 7 files changed, 4979 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 justfile create mode 100644 opengl.png create mode 100644 src/main.rs create mode 100644 src/teapot.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b5d2ef8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/target +.aider* diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..bfff70b --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,2721 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "ab_glyph" +version = "0.2.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec3672c180e71eeaaac3a541fbbc5f5ad4def8b747c595ad30d674e43049f7b0" +dependencies = [ + "ab_glyph_rasterizer", + "owned_ttf_parser", +] + +[[package]] +name = "ab_glyph_rasterizer" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c71b1793ee61086797f5c80b6efa2b8ffa6d5dd703f118545808a7f2e27f7046" + +[[package]] +name = "addr2line" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" + +[[package]] +name = "ahash" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" +dependencies = [ + "cfg-if", + "getrandom 0.3.3", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "aligned-vec" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc890384c8602f339876ded803c97ad529f3842aba97f6392b3dba0dd171769b" +dependencies = [ + "equator", +] + +[[package]] +name = "android-activity" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef6978589202a00cd7e118380c448a08b6ed394c3a8df3a430d0898e3a42d046" +dependencies = [ + "android-properties", + "bitflags 2.9.1", + "cc", + "cesu8", + "jni", + "jni-sys", + "libc", + "log", + "ndk", + "ndk-context", + "ndk-sys", + "num_enum", + "thiserror", +] + +[[package]] +name = "android-properties" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc7eb209b1518d6bb87b283c20095f5228ecda460da70b44f0802523dea6da04" + +[[package]] +name = "anyhow" +version = "1.0.98" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" + +[[package]] +name = "arbitrary" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dde20b3d026af13f561bdd0f15edf01fc734f0dafcedbaf42bba506a9517f223" + +[[package]] +name = "arg_enum_proc_macro" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "arrayref" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" + +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + +[[package]] +name = "as-raw-xcb-connection" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "175571dd1d178ced59193a6fc02dde1b972eb0bc56c892cde9beeceac5bf0f6b" + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + +[[package]] +name = "av1-grain" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f3efb2ca85bc610acfa917b5aaa36f3fcbebed5b3182d7f877b02531c4b80c8" +dependencies = [ + "anyhow", + "arrayvec", + "log", + "nom", + "num-rational", + "v_frame", +] + +[[package]] +name = "avif-serialize" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98922d6a4cfbcb08820c69d8eeccc05bb1f29bfa06b4f5b1dbfe9a868bd7608e" +dependencies = [ + "arrayvec", +] + +[[package]] +name = "backtrace" +version = "0.3.75" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" +dependencies = [ + "addr2line", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", + "windows-targets 0.52.6", +] + +[[package]] +name = "bit_field" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" + +[[package]] +name = "bitstream-io" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6099cdc01846bc367c4e7dd630dc5966dccf36b652fae7a74e17b640411a91b2" + +[[package]] +name = "block2" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c132eebf10f5cad5289222520a4a058514204aed6d791f1cf4fe8088b82d15f" +dependencies = [ + "objc2 0.5.2", +] + +[[package]] +name = "built" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56ed6191a7e78c36abdb16ab65341eefd73d64d303fffccdbb00d51e4205967b" + +[[package]] +name = "bumpalo" +version = "3.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db76d6187cd04dff33004d8e6c9cc4e05cd330500379d2394209271b4aeee" + +[[package]] +name = "bytemuck" +version = "1.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c76a5792e44e4abe34d3abf15636779261d45a7450612059293d1d2cfc63422" + +[[package]] +name = "byteorder-lite" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" + +[[package]] +name = "bytes" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" + +[[package]] +name = "calloop" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b99da2f8558ca23c71f4fd15dc57c906239752dd27ff3c00a1d56b685b7cbfec" +dependencies = [ + "bitflags 2.9.1", + "log", + "polling", + "rustix 0.38.44", + "slab", + "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 0.38.44", + "wayland-backend", + "wayland-client", +] + +[[package]] +name = "cc" +version = "1.2.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d487aa071b5f64da6f19a3e848e3578944b726ee5a4854b82172f02aa876bfdc" +dependencies = [ + "jobserver", + "libc", + "shlex", +] + +[[package]] +name = "cesu8" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" + +[[package]] +name = "cfg-expr" +version = "0.15.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d067ad48b8650848b989a59a86c6c36a995d02d2bf778d45c3c5d57bc2718f02" +dependencies = [ + "smallvec", + "target-lexicon", +] + +[[package]] +name = "cfg-if" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" + +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + +[[package]] +name = "cgl" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ced0551234e87afee12411d535648dd89d2e7f34c78b753395567aff3d447ff" +dependencies = [ + "libc", +] + +[[package]] +name = "color_quant" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" + +[[package]] +name = "combine" +version = "4.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" +dependencies = [ + "bytes", + "memchr", +] + +[[package]] +name = "concurrent-queue" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "core-graphics" +version = "0.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c07782be35f9e1140080c6b96f0d44b739e2278479f64e02fdab4e32dfd8b081" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "core-graphics-types", + "foreign-types", + "libc", +] + +[[package]] +name = "core-graphics-types" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "libc", +] + +[[package]] +name = "crc32fast" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + +[[package]] +name = "crunchy" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43da5946c66ffcc7745f48db692ffbb10a83bfe0afd96235c5c2a4fb23994929" + +[[package]] +name = "cursor-icon" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f27ae1dd37df86211c42e150270f82743308803d90a6f6e6651cd730d5e1732f" + +[[package]] +name = "dispatch" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" + +[[package]] +name = "dispatch2" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89a09f22a6c6069a18470eb92d2298acf25463f14256d24778e1230d789a2aec" +dependencies = [ + "bitflags 2.9.1", + "objc2 0.6.1", +] + +[[package]] +name = "dlib" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "330c60081dcc4c72131f8eb70510f1ac07223e5d4163db481a04a0befcffa412" +dependencies = [ + "libloading", +] + +[[package]] +name = "downcast-rs" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" + +[[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 = "equator" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4711b213838dfee0117e3be6ac926007d7f433d7bbe33595975d4190cb07e6fc" +dependencies = [ + "equator-macro", +] + +[[package]] +name = "equator-macro" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44f23cf4b44bfce11a86ace86f8a73ffdec849c9fd00a386a53d278bd9e81fb3" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "errno" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad" +dependencies = [ + "libc", + "windows-sys 0.60.2", +] + +[[package]] +name = "exr" +version = "1.73.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83197f59927b46c04a183a619b7c29df34e63e63c7869320862268c0ef687e0" +dependencies = [ + "bit_field", + "half", + "lebe", + "miniz_oxide", + "rayon-core", + "smallvec", + "zune-inflate", +] + +[[package]] +name = "fdeflate" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c" +dependencies = [ + "simd-adler32", +] + +[[package]] +name = "flate2" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a3d7db9596fecd151c5f638c0ee5d5bd487b6e0ea232e5dc96d5250f6f94b1d" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foreign-types" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965" +dependencies = [ + "foreign-types-macros", + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-macros" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "foreign-types-shared" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" + +[[package]] +name = "fps" +version = "0.1.0" +dependencies = [ + "glium", + "glutin", + "image", +] + +[[package]] +name = "gethostname" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0176e0459c2e4a1fe232f984bca6890e681076abb9934f6cea7c326f3fc47818" +dependencies = [ + "libc", + "windows-targets 0.48.5", +] + +[[package]] +name = "getrandom" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.11.1+wasi-snapshot-preview1", +] + +[[package]] +name = "getrandom" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasi 0.14.2+wasi-0.2.4", +] + +[[package]] +name = "gif" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ae047235e33e2829703574b54fdec96bfbad892062d97fed2f76022287de61b" +dependencies = [ + "color_quant", + "weezl", +] + +[[package]] +name = "gimli" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" + +[[package]] +name = "gl_generator" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a95dfc23a2b4a9a2f5ab41d194f8bfda3cabec42af4e39f08c339eb2a0c124d" +dependencies = [ + "khronos_api", + "log", + "xml-rs", +] + +[[package]] +name = "glium" +version = "0.36.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cf52ce4f5ce1501bb056627f35484a819e812d1d93f0f3da413676421b1bbe0" +dependencies = [ + "backtrace", + "fnv", + "gl_generator", + "glutin", + "glutin-winit", + "memoffset", + "raw-window-handle", + "smallvec", + "winit", +] + +[[package]] +name = "glutin" +version = "0.32.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12124de845cacfebedff80e877bb37b5b75c34c5a4c89e47e1cdd67fb6041325" +dependencies = [ + "bitflags 2.9.1", + "cfg_aliases", + "cgl", + "dispatch2", + "glutin_egl_sys", + "glutin_glx_sys", + "glutin_wgl_sys", + "libloading", + "objc2 0.6.1", + "objc2-app-kit 0.3.1", + "objc2-core-foundation", + "objc2-foundation 0.3.1", + "once_cell", + "raw-window-handle", + "wayland-sys", + "windows-sys 0.52.0", + "x11-dl", +] + +[[package]] +name = "glutin-winit" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85edca7075f8fc728f28cb8fbb111a96c3b89e930574369e3e9c27eb75d3788f" +dependencies = [ + "cfg_aliases", + "glutin", + "raw-window-handle", + "winit", +] + +[[package]] +name = "glutin_egl_sys" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c4680ba6195f424febdc3ba46e7a42a0e58743f2edb115297b86d7f8ecc02d2" +dependencies = [ + "gl_generator", + "windows-sys 0.52.0", +] + +[[package]] +name = "glutin_glx_sys" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a7bb2938045a88b612499fbcba375a77198e01306f52272e692f8c1f3751185" +dependencies = [ + "gl_generator", + "x11-dl", +] + +[[package]] +name = "glutin_wgl_sys" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c4ee00b289aba7a9e5306d57c2d05499b2e5dc427f84ac708bd2c090212cf3e" +dependencies = [ + "gl_generator", +] + +[[package]] +name = "half" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "459196ed295495a68f7d7fe1d84f6c4b7ff0e21fe3017b2f283c6fac3ad803c9" +dependencies = [ + "cfg-if", + "crunchy", +] + +[[package]] +name = "hashbrown" +version = "0.15.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hermit-abi" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" + +[[package]] +name = "image" +version = "0.25.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db35664ce6b9810857a38a906215e75a9c879f0696556a39f59c62829710251a" +dependencies = [ + "bytemuck", + "byteorder-lite", + "color_quant", + "exr", + "gif", + "image-webp", + "num-traits", + "png", + "qoi", + "ravif", + "rayon", + "rgb", + "tiff", + "zune-core", + "zune-jpeg", +] + +[[package]] +name = "image-webp" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6970fe7a5300b4b42e62c52efa0187540a5bef546c60edaf554ef595d2e6f0b" +dependencies = [ + "byteorder-lite", + "quick-error", +] + +[[package]] +name = "imgref" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0263a3d970d5c054ed9312c0057b4f3bde9c0b33836d3637361d4a9e6e7a408" + +[[package]] +name = "indexmap" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "interpolate_name" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + +[[package]] +name = "jni" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" +dependencies = [ + "cesu8", + "cfg-if", + "combine", + "jni-sys", + "log", + "thiserror", + "walkdir", + "windows-sys 0.45.0", +] + +[[package]] +name = "jni-sys" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" + +[[package]] +name = "jobserver" +version = "0.1.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a" +dependencies = [ + "getrandom 0.3.3", + "libc", +] + +[[package]] +name = "jpeg-decoder" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00810f1d8b74be64b13dbf3db89ac67740615d6c891f0e7b6179326533011a07" + +[[package]] +name = "js-sys" +version = "0.3.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "khronos_api" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc" + +[[package]] +name = "lebe" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8" + +[[package]] +name = "libc" +version = "0.2.174" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776" + +[[package]] +name = "libfuzzer-sys" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf78f52d400cf2d84a3a973a78a592b4adc535739e0a5597a0da6f0c357adc75" +dependencies = [ + "arbitrary", + "cc", +] + +[[package]] +name = "libloading" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667" +dependencies = [ + "cfg-if", + "windows-targets 0.53.2", +] + +[[package]] +name = "libredox" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +dependencies = [ + "bitflags 2.9.1", + "libc", + "redox_syscall 0.5.13", +] + +[[package]] +name = "linux-raw-sys" +version = "0.4.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" + +[[package]] +name = "linux-raw-sys" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" + +[[package]] +name = "log" +version = "0.4.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" + +[[package]] +name = "loop9" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fae87c125b03c1d2c0150c90365d7d6bcc53fb73a9acaef207d2d065860f062" +dependencies = [ + "imgref", +] + +[[package]] +name = "maybe-rayon" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea1f30cedd69f0a2954655f7188c6a834246d2bcf1e315e2ac40c4b24dc9519" +dependencies = [ + "cfg-if", + "rayon", +] + +[[package]] +name = "memchr" +version = "2.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" + +[[package]] +name = "memmap2" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd3f7eed9d3848f8b98834af67102b720745c4ec028fcd0aa0239277e7de374f" +dependencies = [ + "libc", +] + +[[package]] +name = "memoffset" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +dependencies = [ + "autocfg", +] + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "miniz_oxide" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", + "simd-adler32", +] + +[[package]] +name = "ndk" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4" +dependencies = [ + "bitflags 2.9.1", + "jni-sys", + "log", + "ndk-sys", + "num_enum", + "raw-window-handle", + "thiserror", +] + +[[package]] +name = "ndk-context" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" + +[[package]] +name = "ndk-sys" +version = "0.6.0+11769913" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee6cda3051665f1fb8d9e08fc35c96d5a244fb1be711a03b71118828afc9a873" +dependencies = [ + "jni-sys", +] + +[[package]] +name = "new_debug_unreachable" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "noop_proc_macro" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0676bb32a98c1a483ce53e500a81ad9c3d5b3f7c920c28c24e9cb0980d0b5bc8" + +[[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-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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_enum" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a973b4e44ce6cad84ce69d797acf9a044532e4184c4f267913d1b546a0727b7a" +dependencies = [ + "num_enum_derive", + "rustversion", +] + +[[package]] +name = "num_enum_derive" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77e878c846a8abae00dd069496dbe8751b16ac1c3d6bd2a7283a938e8228f90d" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "objc-sys" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb91bdd390c7ce1a8607f35f3ca7151b65afc0ff5ff3b34fa350f7d7c7e4310" + +[[package]] +name = "objc2" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46a785d4eeff09c14c487497c162e92766fbb3e4059a71840cecc03d9a50b804" +dependencies = [ + "objc-sys", + "objc2-encode", +] + +[[package]] +name = "objc2" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88c6597e14493ab2e44ce58f2fdecf095a51f12ca57bec060a11c57332520551" +dependencies = [ + "objc2-encode", +] + +[[package]] +name = "objc2-app-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4e89ad9e3d7d297152b17d39ed92cd50ca8063a89a9fa569046d41568891eff" +dependencies = [ + "bitflags 2.9.1", + "block2", + "libc", + "objc2 0.5.2", + "objc2-core-data", + "objc2-core-image", + "objc2-foundation 0.2.2", + "objc2-quartz-core", +] + +[[package]] +name = "objc2-app-kit" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6f29f568bec459b0ddff777cec4fe3fd8666d82d5a40ebd0ff7e66134f89bcc" +dependencies = [ + "bitflags 2.9.1", + "objc2 0.6.1", + "objc2-core-foundation", + "objc2-foundation 0.3.1", +] + +[[package]] +name = "objc2-cloud-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74dd3b56391c7a0596a295029734d3c1c5e7e510a4cb30245f8221ccea96b009" +dependencies = [ + "bitflags 2.9.1", + "block2", + "objc2 0.5.2", + "objc2-core-location", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-contacts" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5ff520e9c33812fd374d8deecef01d4a840e7b41862d849513de77e44aa4889" +dependencies = [ + "block2", + "objc2 0.5.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-core-data" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "617fbf49e071c178c0b24c080767db52958f716d9eabdf0890523aeae54773ef" +dependencies = [ + "bitflags 2.9.1", + "block2", + "objc2 0.5.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-core-foundation" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c10c2894a6fed806ade6027bcd50662746363a9589d3ec9d9bef30a4e4bc166" +dependencies = [ + "bitflags 2.9.1", + "dispatch2", + "objc2 0.6.1", +] + +[[package]] +name = "objc2-core-image" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55260963a527c99f1819c4f8e3b47fe04f9650694ef348ffd2227e8196d34c80" +dependencies = [ + "block2", + "objc2 0.5.2", + "objc2-foundation 0.2.2", + "objc2-metal", +] + +[[package]] +name = "objc2-core-location" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "000cfee34e683244f284252ee206a27953279d370e309649dc3ee317b37e5781" +dependencies = [ + "block2", + "objc2 0.5.2", + "objc2-contacts", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-encode" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33" + +[[package]] +name = "objc2-foundation" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8" +dependencies = [ + "bitflags 2.9.1", + "block2", + "dispatch", + "libc", + "objc2 0.5.2", +] + +[[package]] +name = "objc2-foundation" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "900831247d2fe1a09a683278e5384cfb8c80c79fe6b166f9d14bfdde0ea1b03c" +dependencies = [ + "bitflags 2.9.1", + "objc2 0.6.1", + "objc2-core-foundation", +] + +[[package]] +name = "objc2-link-presentation" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1a1ae721c5e35be65f01a03b6d2ac13a54cb4fa70d8a5da293d7b0020261398" +dependencies = [ + "block2", + "objc2 0.5.2", + "objc2-app-kit 0.2.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-metal" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6" +dependencies = [ + "bitflags 2.9.1", + "block2", + "objc2 0.5.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-quartz-core" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a" +dependencies = [ + "bitflags 2.9.1", + "block2", + "objc2 0.5.2", + "objc2-foundation 0.2.2", + "objc2-metal", +] + +[[package]] +name = "objc2-symbols" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a684efe3dec1b305badae1a28f6555f6ddd3bb2c2267896782858d5a78404dc" +dependencies = [ + "objc2 0.5.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-ui-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8bb46798b20cd6b91cbd113524c490f1686f4c4e8f49502431415f3512e2b6f" +dependencies = [ + "bitflags 2.9.1", + "block2", + "objc2 0.5.2", + "objc2-cloud-kit", + "objc2-core-data", + "objc2-core-image", + "objc2-core-location", + "objc2-foundation 0.2.2", + "objc2-link-presentation", + "objc2-quartz-core", + "objc2-symbols", + "objc2-uniform-type-identifiers", + "objc2-user-notifications", +] + +[[package]] +name = "objc2-uniform-type-identifiers" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44fa5f9748dbfe1ca6c0b79ad20725a11eca7c2218bceb4b005cb1be26273bfe" +dependencies = [ + "block2", + "objc2 0.5.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-user-notifications" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76cfcbf642358e8689af64cee815d139339f3ed8ad05103ed5eaf73db8d84cb3" +dependencies = [ + "bitflags 2.9.1", + "block2", + "objc2 0.5.2", + "objc2-core-location", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "object" +version = "0.36.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "orbclient" +version = "0.3.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba0b26cec2e24f08ed8bb31519a9333140a6599b867dac464bb150bdb796fd43" +dependencies = [ + "libredox", +] + +[[package]] +name = "owned_ttf_parser" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22ec719bbf3b2a81c109a4e20b1f129b5566b7dce654bc3872f6a05abf82b2c4" +dependencies = [ + "ttf-parser", +] + +[[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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "pin-project" +version = "1.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" + +[[package]] +name = "pkg-config" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" + +[[package]] +name = "png" +version = "0.17.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82151a2fc869e011c153adc57cf2789ccb8d9906ce52c0b39a6b5697749d7526" +dependencies = [ + "bitflags 1.3.2", + "crc32fast", + "fdeflate", + "flate2", + "miniz_oxide", +] + +[[package]] +name = "polling" +version = "3.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b53a684391ad002dd6a596ceb6c74fd004fdce75f4be2e3f615068abbea5fd50" +dependencies = [ + "cfg-if", + "concurrent-queue", + "hermit-abi", + "pin-project-lite", + "rustix 1.0.7", + "tracing", + "windows-sys 0.59.0", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "proc-macro-crate" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edce586971a4dfaa28950c6f18ed55e0406c1ab88bbce2c6f6293a7aaba73d35" +dependencies = [ + "toml_edit", +] + +[[package]] +name = "proc-macro2" +version = "1.0.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" +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 = "qoi" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f6d64c71eb498fe9eae14ce4ec935c555749aef511cca85b5568910d6e48001" +dependencies = [ + "bytemuck", +] + +[[package]] +name = "quick-error" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" + +[[package]] +name = "quick-xml" +version = "0.37.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "331e97a1af0bf59823e6eadffe373d7b27f485be8748f71471c662c1f269b7fb" +dependencies = [ + "memchr", +] + +[[package]] +name = "quote" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.16", +] + +[[package]] +name = "rav1e" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd87ce80a7665b1cce111f8a16c1f3929f6547ce91ade6addf4ec86a8dda5ce9" +dependencies = [ + "arbitrary", + "arg_enum_proc_macro", + "arrayvec", + "av1-grain", + "bitstream-io", + "built", + "cfg-if", + "interpolate_name", + "itertools", + "libc", + "libfuzzer-sys", + "log", + "maybe-rayon", + "new_debug_unreachable", + "noop_proc_macro", + "num-derive", + "num-traits", + "once_cell", + "paste", + "profiling", + "rand", + "rand_chacha", + "simd_helpers", + "system-deps", + "thiserror", + "v_frame", + "wasm-bindgen", +] + +[[package]] +name = "ravif" +version = "0.11.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5825c26fddd16ab9f515930d49028a630efec172e903483c94796cfe31893e6b" +dependencies = [ + "avif-serialize", + "imgref", + "loop9", + "quick-error", + "rav1e", + "rayon", + "rgb", +] + +[[package]] +name = "raw-window-handle" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539" + +[[package]] +name = "rayon" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "redox_syscall" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "redox_syscall" +version = "0.5.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d04b7d0ee6b4a0207a0a7adb104d23ecb0b47d6beae7152d0fa34b692b29fd6" +dependencies = [ + "bitflags 2.9.1", +] + +[[package]] +name = "rgb" +version = "0.8.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57397d16646700483b67d2dd6511d79318f9d057fdbd21a4066aeac8b41d310a" + +[[package]] +name = "rustc-demangle" +version = "0.1.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "989e6739f80c4ad5b13e0fd7fe89531180375b18520cc8c82080e4dc4035b84f" + +[[package]] +name = "rustix" +version = "0.38.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" +dependencies = [ + "bitflags 2.9.1", + "errno", + "libc", + "linux-raw-sys 0.4.15", + "windows-sys 0.59.0", +] + +[[package]] +name = "rustix" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266" +dependencies = [ + "bitflags 2.9.1", + "errno", + "libc", + "linux-raw-sys 0.9.4", + "windows-sys 0.59.0", +] + +[[package]] +name = "rustversion" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +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 = "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 = "serde" +version = "1.0.219" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.219" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_spanned" +version = "0.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3" +dependencies = [ + "serde", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "simd-adler32" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" + +[[package]] +name = "simd_helpers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95890f873bec569a0362c235787f3aca6e1e887302ba4840839bcc6459c42da6" +dependencies = [ + "quote", +] + +[[package]] +name = "slab" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04dc19736151f35336d325007ac991178d504a119863a2fcb3758cdb5e52c50d" + +[[package]] +name = "smallvec" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" + +[[package]] +name = "smithay-client-toolkit" +version = "0.19.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3457dea1f0eb631b4034d61d4d8c32074caa6cd1ab2d59f2327bd8461e2c0016" +dependencies = [ + "bitflags 2.9.1", + "calloop", + "calloop-wayland-source", + "cursor-icon", + "libc", + "log", + "memmap2", + "rustix 0.38.44", + "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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd538fb6910ac1099850255cf94a94df6551fbdd602454387d0adb2d1ca6dead" +dependencies = [ + "serde", +] + +[[package]] +name = "strict-num" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6637bab7722d379c8b41ba849228d680cc12d0a45ba1fa2b48f2a30577a06731" + +[[package]] +name = "syn" +version = "2.0.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "system-deps" +version = "6.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3e535eb8dded36d55ec13eddacd30dec501792ff23a0b1682c38601b8cf2349" +dependencies = [ + "cfg-expr", + "heck", + "pkg-config", + "toml", + "version-compare", +] + +[[package]] +name = "target-lexicon" +version = "0.12.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[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 = "toml" +version = "0.8.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit", +] + +[[package]] +name = "toml_datetime" +version = "0.6.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.22.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" +dependencies = [ + "indexmap", + "serde", + "serde_spanned", + "toml_datetime", + "winnow", +] + +[[package]] +name = "tracing" +version = "0.1.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +dependencies = [ + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" + +[[package]] +name = "ttf-parser" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2df906b07856748fa3f6e0ad0cbaa047052d4a7dd609e231c4f72cee8c36f31" + +[[package]] +name = "unicode-ident" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" + +[[package]] +name = "unicode-segmentation" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" + +[[package]] +name = "v_frame" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "666b7727c8875d6ab5db9533418d7c764233ac9c0cff1d469aec8fa127597be2" +dependencies = [ + "aligned-vec", + "num-traits", + "wasm-bindgen", +] + +[[package]] +name = "version-compare" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "852e951cb7832cb45cb1169900d19760cfa39b82bc0ea9c0e5a14ae88411c98b" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "wasi" +version = "0.14.2+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +dependencies = [ + "wit-bindgen-rt", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" +dependencies = [ + "bumpalo", + "log", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" +dependencies = [ + "cfg-if", + "js-sys", + "once_cell", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "wayland-backend" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe770181423e5fc79d3e2a7f4410b7799d5aab1de4372853de3c6aa13ca24121" +dependencies = [ + "cc", + "downcast-rs", + "rustix 0.38.44", + "scoped-tls", + "smallvec", + "wayland-sys", +] + +[[package]] +name = "wayland-client" +version = "0.31.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "978fa7c67b0847dbd6a9f350ca2569174974cd4082737054dbb7fbb79d7d9a61" +dependencies = [ + "bitflags 2.9.1", + "rustix 0.38.44", + "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.9.1", + "cursor-icon", + "wayland-backend", +] + +[[package]] +name = "wayland-cursor" +version = "0.31.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a65317158dec28d00416cb16705934070aef4f8393353d41126c54264ae0f182" +dependencies = [ + "rustix 0.38.44", + "wayland-client", + "xcursor", +] + +[[package]] +name = "wayland-protocols" +version = "0.32.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "779075454e1e9a521794fed15886323ea0feda3f8b0fc1390f5398141310422a" +dependencies = [ + "bitflags 2.9.1", + "wayland-backend", + "wayland-client", + "wayland-scanner", +] + +[[package]] +name = "wayland-protocols-plasma" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fd38cdad69b56ace413c6bcc1fbf5acc5e2ef4af9d5f8f1f9570c0c83eae175" +dependencies = [ + "bitflags 2.9.1", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-scanner", +] + +[[package]] +name = "wayland-protocols-wlr" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cb6cdc73399c0e06504c437fe3cf886f25568dd5454473d565085b36d6a8bbf" +dependencies = [ + "bitflags 2.9.1", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-scanner", +] + +[[package]] +name = "wayland-scanner" +version = "0.31.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "896fdafd5d28145fce7958917d69f2fd44469b1d4e861cb5961bcbeebc6d1484" +dependencies = [ + "proc-macro2", + "quick-xml", + "quote", +] + +[[package]] +name = "wayland-sys" +version = "0.31.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbcebb399c77d5aa9fa5db874806ee7b4eba4e73650948e8f93963f128896615" +dependencies = [ + "dlib", + "log", + "once_cell", + "pkg-config", +] + +[[package]] +name = "web-sys" +version = "0.3.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "weezl" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a751b3277700db47d3e574514de2eced5e54dc8a5436a3bf7a0b248b2cee16f3" + +[[package]] +name = "winapi-util" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets 0.42.2", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets 0.53.2", +] + +[[package]] +name = "windows-targets" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm 0.52.6", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.53.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c66f69fcc9ce11da9966ddb31a40968cad001c5bedeb5c2b82ede4253ab48aef" +dependencies = [ + "windows_aarch64_gnullvm 0.53.0", + "windows_aarch64_msvc 0.53.0", + "windows_i686_gnu 0.53.0", + "windows_i686_gnullvm 0.53.0", + "windows_i686_msvc 0.53.0", + "windows_x86_64_gnu 0.53.0", + "windows_x86_64_gnullvm 0.53.0", + "windows_x86_64_msvc 0.53.0", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" + +[[package]] +name = "windows_i686_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" + +[[package]] +name = "windows_i686_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_i686_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" + +[[package]] +name = "winit" +version = "0.30.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4409c10174df8779dc29a4788cac85ed84024ccbc1743b776b21a520ee1aaf4" +dependencies = [ + "ahash", + "android-activity", + "atomic-waker", + "bitflags 2.9.1", + "block2", + "bytemuck", + "calloop", + "cfg_aliases", + "concurrent-queue", + "core-foundation", + "core-graphics", + "cursor-icon", + "dpi", + "js-sys", + "libc", + "memmap2", + "ndk", + "objc2 0.5.2", + "objc2-app-kit 0.2.2", + "objc2-foundation 0.2.2", + "objc2-ui-kit", + "orbclient", + "percent-encoding", + "pin-project", + "raw-window-handle", + "redox_syscall 0.4.1", + "rustix 0.38.44", + "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", + "x11-dl", + "x11rb", + "xkbcommon-dl", +] + +[[package]] +name = "winnow" +version = "0.7.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74c7b26e3480b707944fc872477815d29a8e429d2f93a1ce000f5fa84a15cbcd" +dependencies = [ + "memchr", +] + +[[package]] +name = "wit-bindgen-rt" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" +dependencies = [ + "bitflags 2.9.1", +] + +[[package]] +name = "x11-dl" +version = "2.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38735924fedd5314a6e548792904ed8c6de6636285cb9fec04d5b1db85c1516f" +dependencies = [ + "libc", + "once_cell", + "pkg-config", +] + +[[package]] +name = "x11rb" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d91ffca73ee7f68ce055750bf9f6eca0780b8c85eff9bc046a3b0da41755e12" +dependencies = [ + "as-raw-xcb-connection", + "gethostname", + "libc", + "libloading", + "once_cell", + "rustix 0.38.44", + "x11rb-protocol", +] + +[[package]] +name = "x11rb-protocol" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec107c4503ea0b4a98ef47356329af139c0a4f7750e621cf2973cd3385ebcb3d" + +[[package]] +name = "xcursor" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "635887f4315a33cb714eb059bdbd7c1c92bfa71bc5b9d5115460502f788c2ab5" + +[[package]] +name = "xkbcommon-dl" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d039de8032a9a8856a6be89cea3e5d12fdd82306ab7c94d74e6deab2460651c5" +dependencies = [ + "bitflags 2.9.1", + "dlib", + "log", + "once_cell", + "xkeysym", +] + +[[package]] +name = "xkeysym" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9cc00251562a284751c9973bace760d86c0276c471b4be569fe6b068ee97a56" + +[[package]] +name = "xml-rs" +version = "0.8.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a62ce76d9b56901b19a74f19431b0d8b3bc7ca4ad685a746dfd78ca8f4fc6bda" + +[[package]] +name = "zerocopy" +version = "0.8.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "zune-core" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f423a2c17029964870cfaabb1f13dfab7d092a62a29a89264f4d36990ca414a" + +[[package]] +name = "zune-inflate" +version = "0.2.54" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73ab332fe2f6680068f3582b16a24f90ad7096d5d39b974d1c0aff0125116f02" +dependencies = [ + "simd-adler32", +] + +[[package]] +name = "zune-jpeg" +version = "0.4.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7384255a918371b5af158218d131530f694de9ad3815ebdd0453a940485cb0fa" +dependencies = [ + "zune-core", +] diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..8b84c8b --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "fps" +version = "0.1.0" +edition = "2021" + +[dependencies] +glium = "0.36.0" +glutin = "0.32.3" +image = "0.25.6" diff --git a/justfile b/justfile new file mode 100644 index 0000000..a8ef99b --- /dev/null +++ b/justfile @@ -0,0 +1,10 @@ +default: + @just --list + +# Run 'cargo run' on the project +run *ARGS: + cargo run {{ARGS}} + +# Watch for changes and automatically restart +watch: + bacon diff --git a/opengl.png b/opengl.png new file mode 100644 index 0000000000000000000000000000000000000000..f765a0704aa91c2e9876ca96e4cca6a47f2c3d3d GIT binary patch literal 44866 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 JA!i=^zW{cFP_F<0 literal 0 HcmV?d00001 diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..b31ae36 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,127 @@ +#[macro_use] +extern crate glium; +use glium::Surface; +mod teapot; + +fn main() { + let event_loop = glium::winit::event_loop::EventLoop::builder() + .build() + .expect("event loop building"); + let (window, display) = glium::backend::glutin::SimpleWindowBuilder::new() + .with_title("Glium tutorial #3") + .build(&event_loop); + + + let positions = glium::VertexBuffer::new(&display, &teapot::VERTICES).unwrap(); + let normals = glium::VertexBuffer::new(&display, &teapot::NORMALS).unwrap(); + let indices = glium::IndexBuffer::new(&display, glium::index::PrimitiveType::TrianglesList, + &teapot::INDICES).unwrap(); + + let vertex_shader_src = r#" + #version 140 + + in vec3 position; + in vec3 normal; + + out vec3 v_normal; + + uniform mat4 matrix; + uniform mat4 perspective; + + void main() { + v_normal = transpose(inverse(mat3(matrix))) * normal; + gl_Position = perspective * matrix * vec4(position, 1.0); + } + "#; + let fragment_shader_src = r#" + #version 140 + + in vec3 v_normal; + out vec4 color; + uniform vec3 u_light; + + void main() { + float brightness = dot(normalize(v_normal), normalize(u_light)); + vec3 dark_color = vec3(0.6, 0.0, 0.0); + vec3 regular_color = vec3(1.0, 0.0, 0.0); + color = vec4(mix(dark_color, regular_color, brightness), 1.0); + } + "#; + let program = glium::Program::from_source(&display, vertex_shader_src, fragment_shader_src, None).unwrap(); + + let light = [-1.0, 0.4, 0.9f32]; + let mut t: f32 = 0.0; + #[allow(deprecated)] + event_loop.run(move |ev, window_target| { + match ev { + glium::winit::event::Event::WindowEvent { event, .. } => match event { + glium::winit::event::WindowEvent::CloseRequested => { + window_target.exit(); + }, + // We now need to render everyting in response to a RedrawRequested event due to the animation + glium::winit::event::WindowEvent::RedrawRequested => { + let mut target = display.draw(); + target.clear_color_and_depth((0.0, 0.0, 0.0, 1.0), 1.0); + t += 0.01; + let x = t.sin() * 0.5; + let y = t.cos() * 0.5; + + let perspective = { + let (width, height) = target.get_dimensions(); + let aspect_ratio = height as f32 / width as f32; + + let fov: f32 = 3.141592 / 3.0; + let zfar = 1024.0; + let znear = 0.1; + + let f = 1.0 / (fov / 2.0).tan(); + + [ + [f * aspect_ratio , 0.0, 0.0 , 0.0], + [ 0.0 , f , 0.0 , 0.0], + [ 0.0 , 0.0, (zfar+znear)/(zfar-znear) , 1.0], + [ 0.0 , 0.0, -(2.0*zfar*znear)/(zfar-znear), 0.0], + ] + }; + + let uniforms = uniform! { + matrix: [ + [0.01, 0.0, 0.0, 0.0], + [0.0, 0.01, 0.0, 0.0], + [0.0, 0.0, 0.01, 0.0], + [x, y, 2.0, 1.0f32 ], + ], + u_light: light, + perspective: perspective + }; + + let params = glium::DrawParameters { + depth: glium::Depth { + test: glium::draw_parameters::DepthTest::IfLess, + write: true, + .. Default::default() + }, + .. Default::default() + }; + + target.draw((&positions, &normals), &indices, &program, &uniforms, + ¶ms).unwrap(); + target.finish().unwrap(); + }, + // Because glium doesn't know about windows we need to resize the display + // when the window's size has changed. + glium::winit::event::WindowEvent::Resized(window_size) => { + display.resize(window_size.into()); + }, + _ => (), + }, + // By requesting a redraw in response to a RedrawEventsCleared event we get continuous rendering. + // For applications that only change due to user input you could remove this handler. + glium::winit::event::Event::AboutToWait => { + window.request_redraw(); + }, + _ => (), + } + }) + .unwrap(); +} diff --git a/src/teapot.rs b/src/teapot.rs new file mode 100644 index 0000000..914a881 --- /dev/null +++ b/src/teapot.rs @@ -0,0 +1,2110 @@ +#[derive(Copy, Clone)] +pub struct Vertex { + position: (f32, f32, f32) +} + +implement_vertex!(Vertex, position); + +pub const VERTICES: [Vertex; 531] = [ + Vertex { position: (0.0, 0.0, 0.0) }, // dummy vector because in the original model indices + // start at 1 + Vertex { position: (40.6266, 28.3457, -1.10804) }, + Vertex { position: (40.0714, 30.4443, -1.10804) }, + Vertex { position: (40.7155, 31.1438, -1.10804) }, + Vertex { position: (42.0257, 30.4443, -1.10804) }, + Vertex { position: (43.4692, 28.3457, -1.10804) }, + Vertex { position: (37.5425, 28.3457, 14.5117) }, + Vertex { position: (37.0303, 30.4443, 14.2938) }, + Vertex { position: (37.6244, 31.1438, 14.5466) }, + Vertex { position: (38.8331, 30.4443, 15.0609) }, + Vertex { position: (40.1647, 28.3457, 15.6274) }, + Vertex { position: (29.0859, 28.3457, 27.1468) }, + Vertex { position: (28.6917, 30.4443, 26.7527) }, + Vertex { position: (29.149, 31.1438, 27.2099) }, + Vertex { position: (30.0792, 30.4443, 28.1402) }, + Vertex { position: (31.1041, 28.3457, 29.165) }, + Vertex { position: (16.4508, 28.3457, 35.6034) }, + Vertex { position: (16.2329, 30.4443, 35.0912) }, + Vertex { position: (16.4857, 31.1438, 35.6853) }, + Vertex { position: (16.9999, 30.4443, 36.894) }, + Vertex { position: (17.5665, 28.3457, 38.2256) }, + Vertex { position: (0.831025, 28.3457, 38.6876) }, + Vertex { position: (0.831025, 30.4443, 38.1324) }, + Vertex { position: (0.831025, 31.1438, 38.7764) }, + Vertex { position: (0.831025, 30.4443, 40.0866) }, + Vertex { position: (0.831025, 28.3457, 41.5301) }, + Vertex { position: (-15.868, 28.3457, 35.6034) }, + Vertex { position: (-15.0262, 30.4443, 35.0912) }, + Vertex { position: (-14.9585, 31.1438, 35.6853) }, + Vertex { position: (-15.3547, 30.4443, 36.894) }, + Vertex { position: (-15.9044, 28.3457, 38.2256) }, + Vertex { position: (-28.3832, 28.3457, 27.1468) }, + Vertex { position: (-27.4344, 30.4443, 26.7527) }, + Vertex { position: (-27.6068, 31.1438, 27.2099) }, + Vertex { position: (-28.4322, 30.4443, 28.1402) }, + Vertex { position: (-29.4421, 28.3457, 29.165) }, + Vertex { position: (-36.2402, 28.3457, 14.5117) }, + Vertex { position: (-35.52, 30.4443, 14.2938) }, + Vertex { position: (-36.0073, 31.1438, 14.5466) }, + Vertex { position: (-37.1767, 30.4443, 15.0609) }, + Vertex { position: (-38.5027, 28.3457, 15.6274) }, + Vertex { position: (-38.9646, 28.3457, -1.10804) }, + Vertex { position: (-38.4094, 30.4443, -1.10804) }, + Vertex { position: (-39.0534, 31.1438, -1.10804) }, + Vertex { position: (-40.3636, 30.4443, -1.10804) }, + Vertex { position: (-41.8071, 28.3457, -1.10804) }, + Vertex { position: (-35.8804, 28.3457, -16.7278) }, + Vertex { position: (-35.3683, 30.4443, -16.5099) }, + Vertex { position: (-35.9624, 31.1438, -16.7627) }, + Vertex { position: (-37.1711, 30.4443, -17.2769) }, + Vertex { position: (-38.5027, 28.3457, -17.8435) }, + Vertex { position: (-27.4238, 28.3457, -29.3629) }, + Vertex { position: (-27.0297, 30.4443, -28.9687) }, + Vertex { position: (-27.4869, 31.1438, -29.426) }, + Vertex { position: (-28.4172, 30.4443, -30.3562) }, + Vertex { position: (-29.4421, 28.3457, -31.3811) }, + Vertex { position: (-14.7887, 28.3457, -37.8195) }, + Vertex { position: (-14.5708, 30.4443, -37.3073) }, + Vertex { position: (-14.8236, 31.1438, -37.9014) }, + Vertex { position: (-15.3379, 30.4443, -39.1101) }, + Vertex { position: (-15.9044, 28.3457, -40.4417) }, + Vertex { position: (0.831025, 28.3457, -40.9036) }, + Vertex { position: (0.831025, 30.4443, -40.3484) }, + Vertex { position: (0.831025, 31.1438, -40.9925) }, + Vertex { position: (0.831025, 30.4443, -42.3027) }, + Vertex { position: (0.831025, 28.3457, -43.7462) }, + Vertex { position: (16.4508, 28.3457, -37.8195) }, + Vertex { position: (16.2329, 30.4443, -37.3073) }, + Vertex { position: (16.4857, 31.1438, -37.9014) }, + Vertex { position: (16.9999, 30.4443, -39.1101) }, + Vertex { position: (17.5665, 28.3457, -40.4417) }, + Vertex { position: (29.0859, 28.3457, -29.3629) }, + Vertex { position: (28.6917, 30.4443, -28.9687) }, + Vertex { position: (29.149, 31.1438, -29.426) }, + Vertex { position: (30.0792, 30.4443, -30.3562) }, + Vertex { position: (31.1041, 28.3457, -31.3811) }, + Vertex { position: (37.5425, 28.3457, -16.7278) }, + Vertex { position: (37.0303, 30.4443, -16.5099) }, + Vertex { position: (37.6244, 31.1438, -16.7627) }, + Vertex { position: (38.8331, 30.4443, -17.2769) }, + Vertex { position: (40.1647, 28.3457, -17.8435) }, + Vertex { position: (48.6879, 17.1865, -1.10804) }, + Vertex { position: (53.2404, 6.22714, -1.10804) }, + Vertex { position: (56.4605, -4.33246, -1.10804) }, + Vertex { position: (57.6819, -14.2925, -1.10804) }, + Vertex { position: (44.979, 17.1865, 17.6758) }, + Vertex { position: (49.1787, 6.22714, 19.4626) }, + Vertex { position: (52.1492, -4.33246, 20.7265) }, + Vertex { position: (53.2759, -14.2925, 21.2059) }, + Vertex { position: (34.8094, 17.1865, 32.8703) }, + Vertex { position: (38.0417, 6.22714, 36.1026) }, + Vertex { position: (40.3279, -4.33246, 38.3889) }, + Vertex { position: (41.1951, -14.2925, 39.2561) }, + Vertex { position: (19.6148, 17.1865, 43.0399) }, + Vertex { position: (21.4017, 6.22714, 47.2396) }, + Vertex { position: (22.6656, -4.33246, 50.2101) }, + Vertex { position: (23.145, -14.2925, 51.3369) }, + Vertex { position: (0.831025, 17.1865, 46.7488) }, + Vertex { position: (0.831025, 6.22714, 51.3013) }, + Vertex { position: (0.831025, -4.33246, 54.5214) }, + Vertex { position: (0.831025, -14.2925, 55.7428) }, + Vertex { position: (-17.9528, 17.1865, 43.0399) }, + Vertex { position: (-19.7397, 6.22714, 47.2396) }, + Vertex { position: (-21.0035, -4.33246, 50.2101) }, + Vertex { position: (-21.4829, -14.2925, 51.3369) }, + Vertex { position: (-33.1474, 17.1865, 32.8703) }, + Vertex { position: (-36.3796, 6.22714, 36.1026) }, + Vertex { position: (-38.6659, -4.33246, 38.3889) }, + Vertex { position: (-39.5331, -14.2925, 39.2561) }, + Vertex { position: (-43.3169, 17.1865, 17.6758) }, + Vertex { position: (-47.5166, 6.22714, 19.4626) }, + Vertex { position: (-50.4871, -4.33246, 20.7265) }, + Vertex { position: (-51.6139, -14.2925, 21.2059) }, + Vertex { position: (-47.0258, 17.1865, -1.10804) }, + Vertex { position: (-51.5784, 6.22714, -1.10804) }, + Vertex { position: (-54.7984, -4.33246, -1.10804) }, + Vertex { position: (-56.0198, -14.2925, -1.10804) }, + Vertex { position: (-43.3169, 17.1865, -19.8919) }, + Vertex { position: (-47.5166, 6.22714, -21.6787) }, + Vertex { position: (-50.4871, -4.33246, -22.9426) }, + Vertex { position: (-51.6139, -14.2925, -23.422) }, + Vertex { position: (-33.1474, 17.1865, -35.0864) }, + Vertex { position: (-36.3796, 6.22714, -38.3187) }, + Vertex { position: (-38.6659, -4.33246, -40.6049) }, + Vertex { position: (-39.5331, -14.2925, -41.4721) }, + Vertex { position: (-17.9528, 17.1865, -45.256) }, + Vertex { position: (-19.7397, 6.22714, -49.4557) }, + Vertex { position: (-21.0035, -4.33246, -52.4262) }, + Vertex { position: (-21.4829, -14.2925, -53.5529) }, + Vertex { position: (0.831025, 17.1865, -48.9649) }, + Vertex { position: (0.831025, 6.22714, -53.5174) }, + Vertex { position: (0.831025, -4.33246, -56.7375) }, + Vertex { position: (0.831025, -14.2925, -57.9589) }, + Vertex { position: (19.6148, 17.1865, -45.256) }, + Vertex { position: (21.4017, 6.22714, -49.4557) }, + Vertex { position: (22.6656, -4.33246, -52.4262) }, + Vertex { position: (23.145, -14.2925, -53.5529) }, + Vertex { position: (34.8094, 17.1865, -35.0864) }, + Vertex { position: (38.0417, 6.22714, -38.3187) }, + Vertex { position: (40.3279, -4.33246, -40.6049) }, + Vertex { position: (41.1951, -14.2925, -41.4721) }, + Vertex { position: (44.979, 17.1865, -19.8919) }, + Vertex { position: (49.1787, 6.22714, -21.6787) }, + Vertex { position: (52.1492, -4.33246, -22.9426) }, + Vertex { position: (53.2759, -14.2925, -23.422) }, + Vertex { position: (55.4611, -22.7202, -1.10804) }, + Vertex { position: (50.5755, -28.9493, -1.10804) }, + Vertex { position: (45.6899, -33.1798, -1.10804) }, + Vertex { position: (43.4692, -35.6115, -1.10804) }, + Vertex { position: (51.2273, -22.7202, 20.3343) }, + Vertex { position: (46.7203, -28.9493, 18.4167) }, + Vertex { position: (42.2133, -33.1798, 16.4991) }, + Vertex { position: (40.1647, -35.6115, 15.6274) }, + Vertex { position: (39.6184, -22.7202, 37.6793) }, + Vertex { position: (36.1496, -28.9493, 34.2106) }, + Vertex { position: (32.6808, -33.1798, 30.7418) }, + Vertex { position: (31.1041, -35.6115, 29.165) }, + Vertex { position: (22.2733, -22.7202, 49.2882) }, + Vertex { position: (20.3557, -28.9493, 44.7813) }, + Vertex { position: (18.4381, -33.1798, 40.2743) }, + Vertex { position: (17.5665, -35.6115, 38.2256) }, + Vertex { position: (0.831025, -22.7202, 53.5221) }, + Vertex { position: (0.831025, -28.9493, 48.6365) }, + Vertex { position: (0.831025, -33.1798, 43.7508) }, + Vertex { position: (0.831025, -35.6115, 41.5301) }, + Vertex { position: (-20.6113, -22.7202, 49.2882) }, + Vertex { position: (-18.6937, -28.9493, 44.7813) }, + Vertex { position: (-16.7761, -33.1798, 40.2743) }, + Vertex { position: (-15.9044, -35.6115, 38.2256) }, + Vertex { position: (-37.9564, -22.7202, 37.6793) }, + Vertex { position: (-34.4876, -28.9493, 34.2106) }, + Vertex { position: (-31.0188, -33.1798, 30.7418) }, + Vertex { position: (-29.4421, -35.6115, 29.165) }, + Vertex { position: (-49.5653, -22.7202, 20.3343) }, + Vertex { position: (-45.0583, -28.9493, 18.4167) }, + Vertex { position: (-40.5513, -33.1798, 16.4991) }, + Vertex { position: (-38.5027, -35.6115, 15.6274) }, + Vertex { position: (-53.7991, -22.7202, -1.10804) }, + Vertex { position: (-48.9135, -28.9493, -1.10804) }, + Vertex { position: (-44.0279, -33.1798, -1.10804) }, + Vertex { position: (-41.8071, -35.6115, -1.10804) }, + Vertex { position: (-49.5653, -22.7202, -22.5504) }, + Vertex { position: (-45.0583, -28.9493, -20.6327) }, + Vertex { position: (-40.5513, -33.1798, -18.7151) }, + Vertex { position: (-38.5027, -35.6115, -17.8435) }, + Vertex { position: (-37.9564, -22.7202, -39.8954) }, + Vertex { position: (-34.4876, -28.9493, -36.4266) }, + Vertex { position: (-31.0188, -33.1798, -32.9578) }, + Vertex { position: (-29.4421, -35.6115, -31.3811) }, + Vertex { position: (-20.6113, -22.7202, -51.5043) }, + Vertex { position: (-18.6937, -28.9493, -46.9973) }, + Vertex { position: (-16.7761, -33.1798, -42.4903) }, + Vertex { position: (-15.9044, -35.6115, -40.4417) }, + Vertex { position: (0.831025, -22.7202, -55.7382) }, + Vertex { position: (0.831025, -28.9493, -50.8525) }, + Vertex { position: (0.831025, -33.1798, -45.9669) }, + Vertex { position: (0.831025, -35.6115, -43.7462) }, + Vertex { position: (22.2733, -22.7202, -51.5043) }, + Vertex { position: (20.3557, -28.9493, -46.9973) }, + Vertex { position: (18.4381, -33.1798, -42.4903) }, + Vertex { position: (17.5665, -35.6115, -40.4417) }, + Vertex { position: (39.6184, -22.7202, -39.8954) }, + Vertex { position: (36.1496, -28.9493, -36.4266) }, + Vertex { position: (32.6808, -33.1798, -32.9578) }, + Vertex { position: (31.1041, -35.6115, -31.3811) }, + Vertex { position: (51.2273, -22.7202, -22.5504) }, + Vertex { position: (46.7203, -28.9493, -20.6327) }, + Vertex { position: (42.2133, -33.1798, -18.7151) }, + Vertex { position: (40.1647, -35.6115, -17.8435) }, + Vertex { position: (42.5031, -37.1772, -1.10804) }, + Vertex { position: (37.3399, -38.5429, -1.10804) }, + Vertex { position: (24.5818, -39.5089, -1.10804) }, + Vertex { position: (0.831025, -39.8754, -1.10804) }, + Vertex { position: (39.2736, -37.1772, 15.2483) }, + Vertex { position: (34.5105, -38.5429, 13.2217) }, + Vertex { position: (22.7411, -39.5089, 8.21414) }, + Vertex { position: (30.4182, -37.1772, 28.4792) }, + Vertex { position: (26.7523, -38.5429, 24.8133) }, + Vertex { position: (17.6941, -39.5089, 15.755) }, + Vertex { position: (17.1873, -37.1772, 37.3345) }, + Vertex { position: (15.1608, -38.5429, 32.5714) }, + Vertex { position: (10.1532, -39.5089, 20.8021) }, + Vertex { position: (0.831025, -37.1772, 40.5641) }, + Vertex { position: (0.831025, -38.5429, 35.4009) }, + Vertex { position: (0.831025, -39.5089, 22.6427) }, + Vertex { position: (-15.5253, -37.1772, 37.3345) }, + Vertex { position: (-13.4987, -38.5429, 32.5714) }, + Vertex { position: (-8.49115, -39.5089, 20.8021) }, + Vertex { position: (-28.7562, -37.1772, 28.4792) }, + Vertex { position: (-25.0903, -38.5429, 24.8133) }, + Vertex { position: (-16.032, -39.5089, 15.755) }, + Vertex { position: (-37.6115, -37.1772, 15.2483) }, + Vertex { position: (-32.8484, -38.5429, 13.2217) }, + Vertex { position: (-21.0791, -39.5089, 8.21414) }, + Vertex { position: (-40.8411, -37.1772, -1.10804) }, + Vertex { position: (-35.6779, -38.5429, -1.10804) }, + Vertex { position: (-22.9198, -39.5089, -1.10804) }, + Vertex { position: (-37.6115, -37.1772, -17.4643) }, + Vertex { position: (-32.8484, -38.5429, -15.4378) }, + Vertex { position: (-21.0791, -39.5089, -10.4302) }, + Vertex { position: (-28.7562, -37.1772, -30.6952) }, + Vertex { position: (-25.0903, -38.5429, -27.0294) }, + Vertex { position: (-16.032, -39.5089, -17.9711) }, + Vertex { position: (-15.5253, -37.1772, -39.5506) }, + Vertex { position: (-13.4987, -38.5429, -34.7875) }, + Vertex { position: (-8.49115, -39.5089, -23.0181) }, + Vertex { position: (0.831025, -37.1772, -42.7802) }, + Vertex { position: (0.831025, -38.5429, -37.6169) }, + Vertex { position: (0.831025, -39.5089, -24.8588) }, + Vertex { position: (17.1873, -37.1772, -39.5506) }, + Vertex { position: (15.1608, -38.5429, -34.7875) }, + Vertex { position: (10.1532, -39.5089, -23.0181) }, + Vertex { position: (30.4182, -37.1772, -30.6952) }, + Vertex { position: (26.7523, -38.5429, -27.0294) }, + Vertex { position: (17.6941, -39.5089, -17.9711) }, + Vertex { position: (39.2736, -37.1772, -17.4643) }, + Vertex { position: (34.5105, -38.5429, -15.4378) }, + Vertex { position: (22.7411, -39.5089, -10.4302) }, + Vertex { position: (-44.6497, 17.6861, -1.10804) }, + Vertex { position: (-57.9297, 17.5862, -1.10804) }, + Vertex { position: (-67.7453, 16.8867, -1.10804) }, + Vertex { position: (-73.8301, 14.9879, -1.10804) }, + Vertex { position: (-75.9176, 11.2904, -1.10804) }, + Vertex { position: (-44.2055, 18.6855, 3.68876) }, + Vertex { position: (-58.3252, 18.5699, 3.68876) }, + Vertex { position: (-68.6891, 17.7611, 3.68876) }, + Vertex { position: (-75.0724, 15.5657, 3.68876) }, + Vertex { position: (-77.2501, 11.2904, 3.68876) }, + Vertex { position: (-43.2284, 20.884, 5.28769) }, + Vertex { position: (-59.1955, 20.7341, 5.28769) }, + Vertex { position: (-70.7655, 19.6848, 5.28769) }, + Vertex { position: (-77.8053, 16.8367, 5.28769) }, + Vertex { position: (-80.1814, 11.2904, 5.28769) }, + Vertex { position: (-42.2513, 23.0825, 3.68876) }, + Vertex { position: (-60.0657, 22.8983, 3.68876) }, + Vertex { position: (-72.8419, 21.6085, 3.68876) }, + Vertex { position: (-80.5381, 18.1077, 3.68876) }, + Vertex { position: (-83.1128, 11.2904, 3.68876) }, + Vertex { position: (-41.8071, 24.0819, -1.10804) }, + Vertex { position: (-60.4613, 23.882, -1.10804) }, + Vertex { position: (-73.7857, 22.4829, -1.10804) }, + Vertex { position: (-81.7804, 18.6855, -1.10804) }, + Vertex { position: (-84.4453, 11.2904, -1.10804) }, + Vertex { position: (-42.2513, 23.0825, -5.90483) }, + Vertex { position: (-60.0657, 22.8983, -5.90483) }, + Vertex { position: (-72.8419, 21.6085, -5.90483) }, + Vertex { position: (-80.5381, 18.1077, -5.90483) }, + Vertex { position: (-83.1128, 11.2904, -5.90483) }, + Vertex { position: (-43.2284, 20.884, -7.50376) }, + Vertex { position: (-59.1955, 20.7341, -7.50376) }, + Vertex { position: (-70.7655, 19.6848, -7.50376) }, + Vertex { position: (-77.8053, 16.8367, -7.50376) }, + Vertex { position: (-80.1814, 11.2904, -7.50376) }, + Vertex { position: (-44.2055, 18.6855, -5.90483) }, + Vertex { position: (-58.3252, 18.5699, -5.90483) }, + Vertex { position: (-68.6891, 17.7611, -5.90483) }, + Vertex { position: (-75.0724, 15.5657, -5.90483) }, + Vertex { position: (-77.2501, 11.2904, -5.90483) }, + Vertex { position: (-74.8073, 5.4943, -1.10804) }, + Vertex { position: (-71.2985, -1.50103, -1.10804) }, + Vertex { position: (-65.1248, -8.49634, -1.10804) }, + Vertex { position: (-56.0198, -14.2925, -1.10804) }, + Vertex { position: (-76.0183, 4.93477, 3.68876) }, + Vertex { position: (-72.159, -2.35462, 3.68876) }, + Vertex { position: (-65.4267, -9.55033, 3.68876) }, + Vertex { position: (-55.5757, -15.6249, 3.68876) }, + Vertex { position: (-78.6824, 3.70383, 5.28769) }, + Vertex { position: (-74.0522, -4.23253, 5.28769) }, + Vertex { position: (-66.0909, -11.8691, 5.28769) }, + Vertex { position: (-54.5986, -18.5563, 5.28769) }, + Vertex { position: (-81.3466, 2.47288, 3.68876) }, + Vertex { position: (-75.9454, -6.11044, 3.68876) }, + Vertex { position: (-66.755, -14.1878, 3.68876) }, + Vertex { position: (-53.6214, -21.4877, 3.68876) }, + Vertex { position: (-82.5576, 1.91336, -1.10804) }, + Vertex { position: (-76.8059, -6.96404, -1.10804) }, + Vertex { position: (-67.0569, -15.2418, -1.10804) }, + Vertex { position: (-53.1773, -22.8201, -1.10804) }, + Vertex { position: (-81.3466, 2.47288, -5.90483) }, + Vertex { position: (-75.9454, -6.11044, -5.90483) }, + Vertex { position: (-66.755, -14.1878, -5.90483) }, + Vertex { position: (-53.6214, -21.4877, -5.90483) }, + Vertex { position: (-78.6824, 3.70383, -7.50376) }, + Vertex { position: (-74.0522, -4.23253, -7.50376) }, + Vertex { position: (-66.0909, -11.8691, -7.50376) }, + Vertex { position: (-54.5986, -18.5563, -7.50376) }, + Vertex { position: (-76.0183, 4.93477, -5.90483) }, + Vertex { position: (-72.159, -2.35462, -5.90483) }, + Vertex { position: (-65.4267, -9.55033, -5.90483) }, + Vertex { position: (-55.5757, -15.6249, -5.90483) }, + Vertex { position: (49.1543, 0.630882, -1.10804) }, + Vertex { position: (62.7896, 3.76212, -1.10804) }, + Vertex { position: (68.6967, 11.2904, -1.10804) }, + Vertex { position: (71.939, 20.4176, -1.10804) }, + Vertex { position: (77.5797, 28.3457, -1.10804) }, + Vertex { position: (49.1543, -3.03333, 9.4449) }, + Vertex { position: (63.8305, 1.04519, 8.42059) }, + Vertex { position: (70.0292, 9.70814, 6.1671) }, + Vertex { position: (73.5629, 19.8451, 3.91361) }, + Vertex { position: (80.2446, 28.3457, 2.88929) }, + Vertex { position: (49.1543, -11.0946, 12.9626) }, + Vertex { position: (66.1207, -4.93206, 11.5968) }, + Vertex { position: (72.9605, 6.22714, 8.59214) }, + Vertex { position: (77.1355, 18.5855, 5.58749) }, + Vertex { position: (86.1073, 28.3457, 4.22173) }, + Vertex { position: (49.1543, -19.1559, 9.4449) }, + Vertex { position: (68.4108, -10.9093, 8.42059) }, + Vertex { position: (75.8919, 2.74614, 6.1671) }, + Vertex { position: (80.7081, 17.326, 3.91361) }, + Vertex { position: (91.97, 28.3457, 2.88929) }, + Vertex { position: (49.1543, -22.8201, -1.10804) }, + Vertex { position: (69.4518, -13.6262, -1.10804) }, + Vertex { position: (77.2244, 1.16386, -1.10804) }, + Vertex { position: (82.3321, 16.7534, -1.10804) }, + Vertex { position: (94.6349, 28.3457, -1.10804) }, + Vertex { position: (49.1543, -19.1559, -11.661) }, + Vertex { position: (68.4108, -10.9093, -10.6367) }, + Vertex { position: (75.8919, 2.74614, -8.38317) }, + Vertex { position: (80.7081, 17.326, -6.12968) }, + Vertex { position: (91.97, 28.3457, -5.10536) }, + Vertex { position: (49.1543, -11.0946, -15.1786) }, + Vertex { position: (66.1207, -4.93206, -13.8129) }, + Vertex { position: (72.9605, 6.22714, -10.8082) }, + Vertex { position: (77.1355, 18.5855, -7.80356) }, + Vertex { position: (86.1073, 28.3457, -6.4378) }, + Vertex { position: (49.1543, -3.03333, -11.661) }, + Vertex { position: (63.8305, 1.04519, -10.6367) }, + Vertex { position: (70.0292, 9.70814, -8.38317) }, + Vertex { position: (73.5629, 19.8451, -6.12968) }, + Vertex { position: (80.2446, 28.3457, -5.10536) }, + Vertex { position: (79.6227, 29.5449, -1.10804) }, + Vertex { position: (81.1329, 29.9446, -1.10804) }, + Vertex { position: (81.577, 29.5449, -1.10804) }, + Vertex { position: (80.4222, 28.3457, -1.10804) }, + Vertex { position: (82.4767, 29.6034, 2.63946) }, + Vertex { position: (83.8116, 30.0383, 2.08983) }, + Vertex { position: (83.8515, 29.6268, 1.54019) }, + Vertex { position: (82.1988, 28.3457, 1.29036) }, + Vertex { position: (88.7555, 29.7322, 3.88862) }, + Vertex { position: (89.7049, 30.2444, 3.15578) }, + Vertex { position: (88.8555, 29.8072, 2.42294) }, + Vertex { position: (86.1073, 28.3457, 2.08983) }, + Vertex { position: (95.0343, 29.8611, 2.63946) }, + Vertex { position: (95.5982, 30.4505, 2.08983) }, + Vertex { position: (93.8594, 29.9875, 1.54019) }, + Vertex { position: (90.0158, 28.3457, 1.29036) }, + Vertex { position: (97.8883, 29.9196, -1.10804) }, + Vertex { position: (98.2769, 30.5442, -1.10804) }, + Vertex { position: (96.1339, 30.0695, -1.10804) }, + Vertex { position: (91.7924, 28.3457, -1.10804) }, + Vertex { position: (95.0343, 29.8611, -4.85553) }, + Vertex { position: (95.5982, 30.4505, -4.3059) }, + Vertex { position: (93.8594, 29.9875, -3.75626) }, + Vertex { position: (90.0158, 28.3457, -3.50643) }, + Vertex { position: (88.7555, 29.7322, -6.10469) }, + Vertex { position: (89.7049, 30.2444, -5.37185) }, + Vertex { position: (88.8555, 29.8072, -4.63901) }, + Vertex { position: (86.1073, 28.3457, -4.3059) }, + Vertex { position: (82.4767, 29.6034, -4.85553) }, + Vertex { position: (83.8116, 30.0383, -4.3059) }, + Vertex { position: (83.8515, 29.6268, -3.75626) }, + Vertex { position: (82.1988, 28.3457, -3.50643) }, + Vertex { position: (0.831025, 49.6647, -1.10804) }, + Vertex { position: (10.5134, 48.2657, -1.10804) }, + Vertex { position: (10.0693, 44.868, -1.10804) }, + Vertex { position: (6.42728, 40.6708, -1.10804) }, + Vertex { position: (6.51611, 36.8733, -1.10804) }, + Vertex { position: (9.76642, 48.2657, 2.70243) }, + Vertex { position: (9.35632, 44.868, 2.52698) }, + Vertex { position: (5.9947, 40.6708, 1.09187) }, + Vertex { position: (6.07552, 36.8733, 1.12336) }, + Vertex { position: (7.71453, 48.2657, 5.77547) }, + Vertex { position: (7.39819, 44.868, 5.45913) }, + Vertex { position: (4.80736, 40.6708, 2.8683) }, + Vertex { position: (4.86744, 36.8733, 2.92838) }, + Vertex { position: (4.64149, 48.2657, 7.82736) }, + Vertex { position: (4.46604, 44.868, 7.41726) }, + Vertex { position: (3.03093, 40.6708, 4.05564) }, + Vertex { position: (3.06242, 36.8733, 4.13646) }, + Vertex { position: (0.831025, 48.2657, 8.57438) }, + Vertex { position: (0.831025, 44.868, 8.13023) }, + Vertex { position: (0.831025, 40.6708, 4.48822) }, + Vertex { position: (0.831025, 36.8733, 4.57705) }, + Vertex { position: (-2.97944, 48.2657, 7.82736) }, + Vertex { position: (-2.80399, 44.868, 7.41726) }, + Vertex { position: (-1.36888, 40.6708, 4.05564) }, + Vertex { position: (-1.40037, 36.8733, 4.13646) }, + Vertex { position: (-6.05248, 48.2657, 5.77547) }, + Vertex { position: (-5.73614, 44.868, 5.45913) }, + Vertex { position: (-3.14531, 40.6708, 2.8683) }, + Vertex { position: (-3.20539, 36.8733, 2.92838) }, + Vertex { position: (-8.10437, 48.2657, 2.70243) }, + Vertex { position: (-7.69427, 44.868, 2.52698) }, + Vertex { position: (-4.33265, 40.6708, 1.09187) }, + Vertex { position: (-4.41347, 36.8733, 1.12336) }, + Vertex { position: (-8.85139, 48.2657, -1.10804) }, + Vertex { position: (-8.40724, 44.868, -1.10804) }, + Vertex { position: (-4.76523, 40.6708, -1.10804) }, + Vertex { position: (-4.85406, 36.8733, -1.10804) }, + Vertex { position: (-8.10437, 48.2657, -4.9185) }, + Vertex { position: (-7.69427, 44.868, -4.74305) }, + Vertex { position: (-4.33265, 40.6708, -3.30794) }, + Vertex { position: (-4.41347, 36.8733, -3.33943) }, + Vertex { position: (-6.05248, 48.2657, -7.99154) }, + Vertex { position: (-5.73614, 44.868, -7.6752) }, + Vertex { position: (-3.14531, 40.6708, -5.08437) }, + Vertex { position: (-3.20539, 36.8733, -5.14445) }, + Vertex { position: (-2.97944, 48.2657, -10.0434) }, + Vertex { position: (-2.80399, 44.868, -9.63333) }, + Vertex { position: (-1.36888, 40.6708, -6.27171) }, + Vertex { position: (-1.40037, 36.8733, -6.35253) }, + Vertex { position: (0.831025, 48.2657, -10.7904) }, + Vertex { position: (0.831025, 44.868, -10.3463) }, + Vertex { position: (0.831025, 40.6708, -6.70429) }, + Vertex { position: (0.831025, 36.8733, -6.79312) }, + Vertex { position: (4.64149, 48.2657, -10.0434) }, + Vertex { position: (4.46604, 44.868, -9.63333) }, + Vertex { position: (3.03093, 40.6708, -6.27171) }, + Vertex { position: (3.06242, 36.8733, -6.35253) }, + Vertex { position: (7.71453, 48.2657, -7.99154) }, + Vertex { position: (7.39819, 44.868, -7.6752) }, + Vertex { position: (4.80736, 40.6708, -5.08437) }, + Vertex { position: (4.86744, 36.8733, -5.14445) }, + Vertex { position: (9.76642, 48.2657, -4.9185) }, + Vertex { position: (9.35632, 44.868, -4.74305) }, + Vertex { position: (5.9947, 40.6708, -3.30794) }, + Vertex { position: (6.07552, 36.8733, -3.33943) }, + Vertex { position: (13.8001, 34.3417, -1.10804) }, + Vertex { position: (24.282, 32.6095, -1.10804) }, + Vertex { position: (33.6979, 30.8773, -1.10804) }, + Vertex { position: (37.7841, 28.3457, -1.10804) }, + Vertex { position: (12.795, 34.3417, 3.98234) }, + Vertex { position: (22.4646, 32.6095, 8.09647) }, + Vertex { position: (31.1507, 30.8773, 11.7922) }, + Vertex { position: (34.9202, 28.3457, 13.396) }, + Vertex { position: (10.0391, 34.3417, 8.10003) }, + Vertex { position: (17.4812, 32.6095, 15.5422) }, + Vertex { position: (24.1665, 30.8773, 22.2275) }, + Vertex { position: (27.0677, 28.3457, 25.1286) }, + Vertex { position: (5.9214, 34.3417, 10.856) }, + Vertex { position: (10.0355, 32.6095, 20.5255) }, + Vertex { position: (13.7313, 30.8773, 29.2117) }, + Vertex { position: (15.3351, 28.3457, 32.9812) }, + Vertex { position: (0.831025, 34.3417, 11.8611) }, + Vertex { position: (0.831025, 32.6095, 22.3429) }, + Vertex { position: (0.831025, 30.8773, 31.7589) }, + Vertex { position: (0.831025, 28.3457, 35.845) }, + Vertex { position: (-4.25935, 34.3417, 10.856) }, + Vertex { position: (-8.37348, 32.6095, 20.5255) }, + Vertex { position: (-12.0692, 30.8773, 29.2117) }, + Vertex { position: (-13.673, 28.3457, 32.9812) }, + Vertex { position: (-8.37704, 34.3417, 8.10003) }, + Vertex { position: (-15.8192, 32.6095, 15.5422) }, + Vertex { position: (-22.5045, 30.8773, 22.2275) }, + Vertex { position: (-25.4056, 28.3457, 25.1286) }, + Vertex { position: (-11.133, 34.3417, 3.98234) }, + Vertex { position: (-20.8025, 32.6095, 8.09647) }, + Vertex { position: (-29.4887, 30.8773, 11.7922) }, + Vertex { position: (-33.2582, 28.3457, 13.396) }, + Vertex { position: (-12.1381, 34.3417, -1.10804) }, + Vertex { position: (-22.62, 32.6095, -1.10804) }, + Vertex { position: (-32.0359, 30.8773, -1.10804) }, + Vertex { position: (-36.122, 28.3457, -1.10804) }, + Vertex { position: (-11.133, 34.3417, -6.19841) }, + Vertex { position: (-20.8025, 32.6095, -10.3125) }, + Vertex { position: (-29.4887, 30.8773, -14.0083) }, + Vertex { position: (-33.2582, 28.3457, -15.6121) }, + Vertex { position: (-8.37704, 34.3417, -10.3161) }, + Vertex { position: (-15.8192, 32.6095, -17.7582) }, + Vertex { position: (-22.5045, 30.8773, -24.4435) }, + Vertex { position: (-25.4056, 28.3457, -27.3447) }, + Vertex { position: (-4.25935, 34.3417, -13.072) }, + Vertex { position: (-8.37348, 32.6095, -22.7416) }, + Vertex { position: (-12.0692, 30.8773, -31.4277) }, + Vertex { position: (-13.673, 28.3457, -35.1972) }, + Vertex { position: (0.831025, 34.3417, -14.0771) }, + Vertex { position: (0.831025, 32.6095, -24.559) }, + Vertex { position: (0.831025, 30.8773, -33.9749) }, + Vertex { position: (0.831025, 28.3457, -38.0611) }, + Vertex { position: (5.9214, 34.3417, -13.072) }, + Vertex { position: (10.0355, 32.6095, -22.7416) }, + Vertex { position: (13.7313, 30.8773, -31.4277) }, + Vertex { position: (15.3351, 28.3457, -35.1972) }, + Vertex { position: (10.0391, 34.3417, -10.3161) }, + Vertex { position: (17.4812, 32.6095, -17.7582) }, + Vertex { position: (24.1665, 30.8773, -24.4435) }, + Vertex { position: (27.0677, 28.3457, -27.3447) }, + Vertex { position: (12.795, 34.3417, -6.19841) }, + Vertex { position: (22.4646, 32.6095, -10.3125) }, + Vertex { position: (31.1507, 30.8773, -14.0083) }, + Vertex { position: (34.9202, 28.3457, -15.6121) } +]; + +#[derive(Copy, Clone)] +pub struct Normal { + normal: (f32, f32, f32) +} + +implement_vertex!(Normal, normal); + +pub const NORMALS: [Normal; 531] = [ + Normal { normal: (0.0, 0.0, 0.0) }, // dummy vector because in the original model indices + // start at 1 + Normal { normal: (-0.966742, -0.255752, 0.0) }, + Normal { normal: (-0.966824, 0.255443, 0.0) }, + Normal { normal: (-0.092052, 0.995754, 0.0) }, + Normal { normal: (0.68205, 0.731305, 0.0) }, + Normal { normal: (0.870301, 0.492521, -0.0) }, + Normal { normal: (-0.893014, -0.256345, -0.369882) }, + Normal { normal: (-0.893437, 0.255997, -0.369102) }, + Normal { normal: (-0.0838771, 0.995843, -0.0355068) }, + Normal { normal: (0.629724, 0.73186, 0.260439) }, + Normal { normal: (0.803725, 0.49337, 0.332584) }, + Normal { normal: (-0.683407, -0.256729, -0.683407) }, + Normal { normal: (-0.683531, 0.256067, -0.683531) }, + Normal { normal: (-0.0649249, 0.995776, -0.0649248) }, + Normal { normal: (0.481398, 0.732469, 0.481398) }, + Normal { normal: (0.614804, 0.493997, 0.614804) }, + Normal { normal: (-0.369882, -0.256345, -0.893014) }, + Normal { normal: (-0.369102, 0.255997, -0.893437) }, + Normal { normal: (-0.0355067, 0.995843, -0.0838772) }, + Normal { normal: (0.260439, 0.73186, 0.629724) }, + Normal { normal: (0.332584, 0.49337, 0.803725) }, + Normal { normal: (-0.00284834, -0.257863, -0.966177) }, + Normal { normal: (-0.00192311, 0.254736, -0.967009) }, + Normal { normal: (-0.000266114, 0.995734, -0.0922702) }, + Normal { normal: (0.0, 0.731295, 0.682061) }, + Normal { normal: (0.0, 0.492521, 0.870301) }, + Normal { normal: (0.379058, -0.3593, -0.852771) }, + Normal { normal: (0.37711, 0.149086, -0.914091) }, + Normal { normal: (0.0275022, 0.992081, -0.122551) }, + Normal { normal: (-0.26101, 0.726762, 0.635367) }, + Normal { normal: (-0.332485, 0.492546, 0.804271) }, + Normal { normal: (0.663548, -0.410791, -0.625264) }, + Normal { normal: (0.712664, 0.0737216, -0.697621) }, + Normal { normal: (0.0997268, 0.987509, -0.121984) }, + Normal { normal: (-0.48732, 0.723754, 0.488568) }, + Normal { normal: (-0.615242, 0.492602, 0.615484) }, + Normal { normal: (0.880028, -0.332908, -0.338709) }, + Normal { normal: (0.917276, 0.167113, -0.361493) }, + Normal { normal: (0.113584, 0.992365, -0.0480695) }, + Normal { normal: (-0.63415, 0.727508, 0.261889) }, + Normal { normal: (-0.804126, 0.492634, 0.332705) }, + Normal { normal: (0.96669, -0.255738, 0.0104537) }, + Normal { normal: (0.967442, 0.252962, 0.00810329) }, + Normal { normal: (0.0934365, 0.995624, 0.00128063) }, + Normal { normal: (-0.682167, 0.731196, -0.00034353) }, + Normal { normal: (-0.870322, 0.492483, -0.0) }, + Normal { normal: (0.893014, -0.256345, 0.369882) }, + Normal { normal: (0.893437, 0.255997, 0.369102) }, + Normal { normal: (0.0838768, 0.995843, 0.0355066) }, + Normal { normal: (-0.629724, 0.73186, -0.260439) }, + Normal { normal: (-0.803725, 0.49337, -0.332584) }, + Normal { normal: (0.683407, -0.256729, 0.683407) }, + Normal { normal: (0.683531, 0.256067, 0.683531) }, + Normal { normal: (0.0649249, 0.995776, 0.0649249) }, + Normal { normal: (-0.481398, 0.732469, -0.481398) }, + Normal { normal: (-0.614804, 0.493997, -0.614804) }, + Normal { normal: (0.369882, -0.256345, 0.893014) }, + Normal { normal: (0.369102, 0.255997, 0.893437) }, + Normal { normal: (0.0355067, 0.995843, 0.083877) }, + Normal { normal: (-0.260439, 0.73186, -0.629724) }, + Normal { normal: (-0.332584, 0.49337, -0.803725) }, + Normal { normal: (0.0, -0.255752, 0.966742) }, + Normal { normal: (0.0, 0.255443, 0.966824) }, + Normal { normal: (0.0, 0.995754, 0.092052) }, + Normal { normal: (0.0, 0.731305, -0.68205) }, + Normal { normal: (-0.0, 0.492521, -0.870301) }, + Normal { normal: (-0.369882, -0.256345, 0.893014) }, + Normal { normal: (-0.369102, 0.255996, 0.893437) }, + Normal { normal: (-0.0355068, 0.995843, 0.0838771) }, + Normal { normal: (0.260439, 0.73186, -0.629724) }, + Normal { normal: (0.332584, 0.49337, -0.803725) }, + Normal { normal: (-0.683407, -0.256729, 0.683407) }, + Normal { normal: (-0.683531, 0.256067, 0.683531) }, + Normal { normal: (-0.0649249, 0.995776, 0.064925) }, + Normal { normal: (0.481398, 0.732469, -0.481398) }, + Normal { normal: (0.614804, 0.493997, -0.614804) }, + Normal { normal: (-0.893014, -0.256345, 0.369882) }, + Normal { normal: (-0.893437, 0.255997, 0.369102) }, + Normal { normal: (-0.0838767, 0.995843, 0.0355066) }, + Normal { normal: (0.629724, 0.73186, -0.260439) }, + Normal { normal: (0.803725, 0.49337, -0.332584) }, + Normal { normal: (0.915321, 0.402725, 0.0) }, + Normal { normal: (0.941808, 0.336151, -0.0) }, + Normal { normal: (0.97869, 0.205342, 0.0) }, + Normal { normal: (0.997804, -0.0662397, 0.0) }, + Normal { normal: (0.845438, 0.403546, 0.349835) }, + Normal { normal: (0.869996, 0.336859, 0.360047) }, + Normal { normal: (0.904193, 0.205791, 0.37428) }, + Normal { normal: (0.921879, -0.0663697, 0.381752) }, + Normal { normal: (0.646802, 0.404096, 0.646802) }, + Normal { normal: (0.665655, 0.337351, 0.665655) }, + Normal { normal: (0.691923, 0.20612, 0.691923) }, + Normal { normal: (0.705542, -0.0664796, 0.705543) }, + Normal { normal: (0.349835, 0.403546, 0.845438) }, + Normal { normal: (0.360047, 0.336859, 0.869996) }, + Normal { normal: (0.37428, 0.205791, 0.904193) }, + Normal { normal: (0.381752, -0.0663697, 0.921879) }, + Normal { normal: (-0.0, 0.402725, 0.915321) }, + Normal { normal: (0.0, 0.336151, 0.941808) }, + Normal { normal: (-0.0, 0.205342, 0.97869) }, + Normal { normal: (-0.0, -0.0662397, 0.997804) }, + Normal { normal: (-0.349835, 0.403546, 0.845438) }, + Normal { normal: (-0.360047, 0.336859, 0.869996) }, + Normal { normal: (-0.37428, 0.205791, 0.904193) }, + Normal { normal: (-0.381752, -0.0663697, 0.921879) }, + Normal { normal: (-0.646802, 0.404096, 0.646802) }, + Normal { normal: (-0.665655, 0.337351, 0.665655) }, + Normal { normal: (-0.691923, 0.20612, 0.691923) }, + Normal { normal: (-0.705543, -0.0664796, 0.705543) }, + Normal { normal: (-0.845438, 0.403546, 0.349835) }, + Normal { normal: (-0.869996, 0.336859, 0.360047) }, + Normal { normal: (-0.904193, 0.205791, 0.37428) }, + Normal { normal: (-0.921879, -0.0663697, 0.381752) }, + Normal { normal: (-0.915321, 0.402725, -0.0) }, + Normal { normal: (-0.941808, 0.336151, -0.0) }, + Normal { normal: (-0.97869, 0.205342, -0.0) }, + Normal { normal: (-0.997804, -0.0662397, -0.0) }, + Normal { normal: (-0.845438, 0.403546, -0.349835) }, + Normal { normal: (-0.869996, 0.336859, -0.360047) }, + Normal { normal: (-0.904193, 0.205791, -0.37428) }, + Normal { normal: (-0.921879, -0.0663697, -0.381752) }, + Normal { normal: (-0.646802, 0.404096, -0.646802) }, + Normal { normal: (-0.665655, 0.337351, -0.665655) }, + Normal { normal: (-0.691923, 0.20612, -0.691923) }, + Normal { normal: (-0.705542, -0.0664796, -0.705543) }, + Normal { normal: (-0.349835, 0.403546, -0.845438) }, + Normal { normal: (-0.360047, 0.336859, -0.869996) }, + Normal { normal: (-0.37428, 0.205791, -0.904193) }, + Normal { normal: (-0.381752, -0.0663697, -0.921879) }, + Normal { normal: (0.0, 0.402725, -0.915321) }, + Normal { normal: (-0.0, 0.336151, -0.941808) }, + Normal { normal: (0.0, 0.205342, -0.97869) }, + Normal { normal: (0.0, -0.0662397, -0.997804) }, + Normal { normal: (0.349835, 0.403546, -0.845438) }, + Normal { normal: (0.360047, 0.336859, -0.869996) }, + Normal { normal: (0.37428, 0.205791, -0.904193) }, + Normal { normal: (0.381752, -0.0663697, -0.921879) }, + Normal { normal: (0.646802, 0.404096, -0.646802) }, + Normal { normal: (0.665655, 0.337351, -0.665655) }, + Normal { normal: (0.691923, 0.20612, -0.691923) }, + Normal { normal: (0.705543, -0.0664796, -0.705542) }, + Normal { normal: (0.845438, 0.403546, -0.349835) }, + Normal { normal: (0.869996, 0.336859, -0.360047) }, + Normal { normal: (0.904193, 0.205791, -0.37428) }, + Normal { normal: (0.921879, -0.0663697, -0.381752) }, + Normal { normal: (0.900182, -0.435513, -0.0) }, + Normal { normal: (0.729611, -0.683863, -0.0) }, + Normal { normal: (0.693951, -0.720022, -0.0) }, + Normal { normal: (0.79395, -0.607984, 0.0) }, + Normal { normal: (0.831437, -0.43618, 0.344179) }, + Normal { normal: (0.673512, -0.684665, 0.278594) }, + Normal { normal: (0.640399, -0.720924, 0.264874) }, + Normal { normal: (0.732949, -0.608996, 0.303166) }, + Normal { normal: (0.636092, -0.436777, 0.636092) }, + Normal { normal: (0.514965, -0.685289, 0.514965) }, + Normal { normal: (0.489651, -0.721446, 0.489651) }, + Normal { normal: (0.560555, -0.609554, 0.560555) }, + Normal { normal: (0.344179, -0.43618, 0.831437) }, + Normal { normal: (0.278594, -0.684665, 0.673512) }, + Normal { normal: (0.264874, -0.720924, 0.640399) }, + Normal { normal: (0.303166, -0.608996, 0.732949) }, + Normal { normal: (0.0, -0.435513, 0.900182) }, + Normal { normal: (-0.0, -0.683863, 0.729611) }, + Normal { normal: (0.0, -0.720022, 0.693951) }, + Normal { normal: (-0.0, -0.607984, 0.79395) }, + Normal { normal: (-0.344179, -0.43618, 0.831437) }, + Normal { normal: (-0.278594, -0.684665, 0.673512) }, + Normal { normal: (-0.264874, -0.720924, 0.640399) }, + Normal { normal: (-0.303166, -0.608996, 0.732949) }, + Normal { normal: (-0.636092, -0.436777, 0.636092) }, + Normal { normal: (-0.514965, -0.685289, 0.514965) }, + Normal { normal: (-0.489651, -0.721446, 0.489651) }, + Normal { normal: (-0.560555, -0.609554, 0.560555) }, + Normal { normal: (-0.831437, -0.43618, 0.344179) }, + Normal { normal: (-0.673512, -0.684665, 0.278595) }, + Normal { normal: (-0.640399, -0.720924, 0.264874) }, + Normal { normal: (-0.732949, -0.608996, 0.303166) }, + Normal { normal: (-0.900182, -0.435513, -0.0) }, + Normal { normal: (-0.729611, -0.683863, -0.0) }, + Normal { normal: (-0.693951, -0.720022, 0.0) }, + Normal { normal: (-0.79395, -0.607983, -0.0) }, + Normal { normal: (-0.831437, -0.43618, -0.344179) }, + Normal { normal: (-0.673512, -0.684665, -0.278594) }, + Normal { normal: (-0.640399, -0.720924, -0.264874) }, + Normal { normal: (-0.732949, -0.608996, -0.303166) }, + Normal { normal: (-0.636092, -0.436777, -0.636092) }, + Normal { normal: (-0.514965, -0.685289, -0.514965) }, + Normal { normal: (-0.489651, -0.721446, -0.489651) }, + Normal { normal: (-0.560555, -0.609554, -0.560555) }, + Normal { normal: (-0.344179, -0.43618, -0.831437) }, + Normal { normal: (-0.278594, -0.684665, -0.673512) }, + Normal { normal: (-0.264874, -0.720924, -0.640399) }, + Normal { normal: (-0.303166, -0.608996, -0.732949) }, + Normal { normal: (-0.0, -0.435513, -0.900182) }, + Normal { normal: (0.0, -0.683863, -0.729611) }, + Normal { normal: (-0.0, -0.720022, -0.693951) }, + Normal { normal: (0.0, -0.607984, -0.79395) }, + Normal { normal: (0.344179, -0.43618, -0.831437) }, + Normal { normal: (0.278594, -0.684665, -0.673512) }, + Normal { normal: (0.264874, -0.720924, -0.640399) }, + Normal { normal: (0.303167, -0.608996, -0.732949) }, + Normal { normal: (0.636092, -0.436777, -0.636092) }, + Normal { normal: (0.514965, -0.685289, -0.514965) }, + Normal { normal: (0.489651, -0.721446, -0.489651) }, + Normal { normal: (0.560555, -0.609554, -0.560555) }, + Normal { normal: (0.831437, -0.43618, -0.344179) }, + Normal { normal: (0.673512, -0.684665, -0.278595) }, + Normal { normal: (0.640399, -0.720924, -0.264874) }, + Normal { normal: (0.732949, -0.608996, -0.303166) }, + Normal { normal: (0.62386, -0.781536, 0.0) }, + Normal { normal: (0.177291, -0.984159, -0.0) }, + Normal { normal: (0.0492072, -0.998789, 0.0) }, + Normal { normal: (0.0, -1.0, -0.0) }, + Normal { normal: (0.576229, -0.781801, 0.238217) }, + Normal { normal: (0.163629, -0.984208, 0.0675273) }, + Normal { normal: (0.0454217, -0.998792, 0.0187357) }, + Normal { normal: (0.440416, -0.782348, 0.440416) }, + Normal { normal: (0.124903, -0.984276, 0.124903) }, + Normal { normal: (0.0346621, -0.998798, 0.0346621) }, + Normal { normal: (0.238217, -0.781801, 0.576229) }, + Normal { normal: (0.0675273, -0.984208, 0.163629) }, + Normal { normal: (0.0187357, -0.998792, 0.0454217) }, + Normal { normal: (-0.0, -0.781536, 0.62386) }, + Normal { normal: (0.0, -0.984159, 0.177291) }, + Normal { normal: (-0.0, -0.998789, 0.0492072) }, + Normal { normal: (-0.238216, -0.781801, 0.576229) }, + Normal { normal: (-0.0675273, -0.984208, 0.163629) }, + Normal { normal: (-0.0187357, -0.998792, 0.0454217) }, + Normal { normal: (-0.440416, -0.782348, 0.440416) }, + Normal { normal: (-0.124903, -0.984276, 0.124903) }, + Normal { normal: (-0.0346621, -0.998798, 0.0346621) }, + Normal { normal: (-0.576229, -0.781801, 0.238217) }, + Normal { normal: (-0.163629, -0.984208, 0.0675273) }, + Normal { normal: (-0.0454217, -0.998792, 0.0187357) }, + Normal { normal: (-0.62386, -0.781536, -0.0) }, + Normal { normal: (-0.177291, -0.984159, 0.0) }, + Normal { normal: (-0.0492072, -0.998789, -0.0) }, + Normal { normal: (-0.576229, -0.781801, -0.238217) }, + Normal { normal: (-0.163629, -0.984208, -0.0675273) }, + Normal { normal: (-0.0454217, -0.998792, -0.0187357) }, + Normal { normal: (-0.440416, -0.782348, -0.440416) }, + Normal { normal: (-0.124903, -0.984276, -0.124903) }, + Normal { normal: (-0.0346621, -0.998798, -0.0346621) }, + Normal { normal: (-0.238217, -0.781801, -0.576229) }, + Normal { normal: (-0.0675273, -0.984208, -0.163629) }, + Normal { normal: (-0.0187357, -0.998792, -0.0454217) }, + Normal { normal: (0.0, -0.781536, -0.62386) }, + Normal { normal: (-0.0, -0.984159, -0.177291) }, + Normal { normal: (0.0, -0.998789, -0.0492072) }, + Normal { normal: (0.238217, -0.781801, -0.576229) }, + Normal { normal: (0.0675273, -0.984208, -0.163629) }, + Normal { normal: (0.0187357, -0.998792, -0.0454217) }, + Normal { normal: (0.440416, -0.782348, -0.440416) }, + Normal { normal: (0.124903, -0.984276, -0.124903) }, + Normal { normal: (0.0346621, -0.998798, -0.0346621) }, + Normal { normal: (0.576229, -0.781801, -0.238217) }, + Normal { normal: (0.163629, -0.984208, -0.0675273) }, + Normal { normal: (0.0454217, -0.998792, -0.0187357) }, + Normal { normal: (0.00778619, -0.99997, -0.000215809) }, + Normal { normal: (0.0391385, -0.999233, -0.000988567) }, + Normal { normal: (0.179511, -0.983746, -0.00436856) }, + Normal { normal: (0.6123, -0.790556, -0.0104598) }, + Normal { normal: (0.986152, -0.165707, -0.00666949) }, + Normal { normal: (0.00703893, -0.812495, 0.582926) }, + Normal { normal: (0.0361273, -0.837257, 0.545614) }, + Normal { normal: (0.161845, -0.810421, 0.563048) }, + Normal { normal: (0.482365, -0.595148, 0.642746) }, + Normal { normal: (0.73872, -0.114593, 0.664199) }, + Normal { normal: (-0.00190867, 0.162121, 0.986769) }, + Normal { normal: (0.0027616, 0.0171073, 0.99985) }, + Normal { normal: (0.0105326, 0.0733989, 0.997247) }, + Normal { normal: (-0.0660406, 0.130069, 0.989303) }, + Normal { normal: (-0.0944272, 0.0165946, 0.995393) }, + Normal { normal: (-0.009203, 0.871509, 0.490293) }, + Normal { normal: (-0.0486064, 0.840609, 0.539457) }, + Normal { normal: (-0.223298, 0.802881, 0.552739) }, + Normal { normal: (-0.596365, 0.559971, 0.575135) }, + Normal { normal: (-0.803337, 0.0682361, 0.591602) }, + Normal { normal: (-0.0105609, 0.999944, 0.000103364) }, + Normal { normal: (-0.0587986, 0.99827, 0.000709759) }, + Normal { normal: (-0.28071, 0.959787, 0.00326876) }, + Normal { normal: (-0.749723, 0.661738, 0.0042684) }, + Normal { normal: (-0.997351, 0.0727144, 0.00205923) }, + Normal { normal: (-0.00879197, 0.871493, -0.49033) }, + Normal { normal: (-0.0464937, 0.841178, -0.538756) }, + Normal { normal: (-0.217909, 0.806807, -0.549161) }, + Normal { normal: (-0.597291, 0.560026, -0.574121) }, + Normal { normal: (-0.804, 0.0629127, -0.591291) }, + Normal { normal: (-0.00180555, 0.161691, -0.98684) }, + Normal { normal: (0.00203087, 0.014555, -0.999892) }, + Normal { normal: (0.00921499, 0.0600698, -0.998152) }, + Normal { normal: (-0.0593333, 0.113865, -0.991723) }, + Normal { normal: (-0.0868992, 0.0122903, -0.996141) }, + Normal { normal: (0.00641779, -0.812379, -0.583094) }, + Normal { normal: (0.0337833, -0.837512, -0.545373) }, + Normal { normal: (0.157112, -0.811947, -0.56219) }, + Normal { normal: (0.484407, -0.589365, -0.646528) }, + Normal { normal: (0.73887, -0.10132, -0.666187) }, + Normal { normal: (0.946512, 0.32265, -0.0033571) }, + Normal { normal: (0.82583, 0.56387, -0.00745213) }, + Normal { normal: (0.650011, 0.759893, -0.00693681) }, + Normal { normal: (0.532429, 0.846458, -0.00524544) }, + Normal { normal: (0.725608, 0.259351, 0.637362) }, + Normal { normal: (0.645945, 0.461988, 0.607719) }, + Normal { normal: (0.531614, 0.63666, 0.558615) }, + Normal { normal: (0.424964, 0.681717, 0.59554) }, + Normal { normal: (-0.0495616, -0.019755, 0.998576) }, + Normal { normal: (-0.0378162, -0.0356243, 0.99865) }, + Normal { normal: (-0.0379139, -0.0365122, 0.998614) }, + Normal { normal: (-0.168854, -0.297946, 0.93953) }, + Normal { normal: (-0.742342, -0.299166, 0.599523) }, + Normal { normal: (-0.619602, -0.529406, 0.579503) }, + Normal { normal: (-0.483708, -0.685761, 0.543837) }, + Normal { normal: (-0.445293, -0.794355, 0.413176) }, + Normal { normal: (-0.926513, -0.376257, 0.00199587) }, + Normal { normal: (-0.75392, -0.656952, 0.00431723) }, + Normal { normal: (-0.566224, -0.824244, 0.00346105) }, + Normal { normal: (-0.481804, -0.876277, 0.00185047) }, + Normal { normal: (-0.744675, -0.294424, -0.598977) }, + Normal { normal: (-0.621949, -0.528114, -0.578165) }, + Normal { normal: (-0.481171, -0.68834, -0.542828) }, + Normal { normal: (-0.438055, -0.797035, -0.415744) }, + Normal { normal: (-0.0443368, -0.0170558, -0.998871) }, + Normal { normal: (-0.0261761, -0.0281665, -0.99926) }, + Normal { normal: (-0.0252939, -0.0283323, -0.999278) }, + Normal { normal: (-0.157482, -0.289392, -0.944167) }, + Normal { normal: (0.728244, 0.25241, -0.637142) }, + Normal { normal: (0.647055, 0.459725, -0.608254) }, + Normal { normal: (0.522994, 0.640657, -0.562171) }, + Normal { normal: (0.409978, 0.682857, -0.604669) }, + Normal { normal: (-0.230787, 0.972982, -0.00652338) }, + Normal { normal: (-0.548936, 0.835863, -0.00151111) }, + Normal { normal: (-0.875671, 0.482807, 0.00989278) }, + Normal { normal: (-0.877554, 0.479097, 0.0190923) }, + Normal { normal: (-0.69619, 0.717439, 0.024497) }, + Normal { normal: (-0.152878, 0.687211, 0.71019) }, + Normal { normal: (-0.316721, 0.63775, 0.702113) }, + Normal { normal: (-0.601067, 0.471452, 0.64533) }, + Normal { normal: (-0.635889, 0.44609, 0.6298) }, + Normal { normal: (-0.435746, 0.601008, 0.670011) }, + Normal { normal: (0.111112, -0.0850694, 0.99016) }, + Normal { normal: (0.22331, 0.00654036, 0.974726) }, + Normal { normal: (0.190097, 0.154964, 0.969458) }, + Normal { normal: (0.00527077, 0.189482, 0.98187) }, + Normal { normal: (-0.0117518, 0.246688, 0.969024) }, + Normal { normal: (0.343906, -0.722796, 0.599412) }, + Normal { normal: (0.572489, -0.567656, 0.591627) }, + Normal { normal: (0.787436, -0.256459, 0.560512) }, + Normal { normal: (0.647097, -0.306374, 0.698141) }, + Normal { normal: (0.427528, -0.499343, 0.753576) }, + Normal { normal: (0.410926, -0.911668, 0.00128446) }, + Normal { normal: (0.67152, -0.740986, -0.000899122) }, + Normal { normal: (0.922026, -0.38706, -0.00725269) }, + Normal { normal: (0.84691, -0.531556, -0.0138542) }, + Normal { normal: (0.535925, -0.8442, -0.0105045) }, + Normal { normal: (0.341188, -0.722822, -0.600931) }, + Normal { normal: (0.578664, -0.561139, -0.591838) }, + Normal { normal: (0.784869, -0.25102, -0.566542) }, + Normal { normal: (0.642681, -0.302257, -0.70399) }, + Normal { normal: (0.418589, -0.500042, -0.758117) }, + Normal { normal: (0.115806, -0.0791394, -0.990114) }, + Normal { normal: (0.232811, 0.0125652, -0.972441) }, + Normal { normal: (0.206662, 0.153601, -0.96628) }, + Normal { normal: (0.0244996, 0.161443, -0.986578) }, + Normal { normal: (0.00338193, 0.211115, -0.977455) }, + Normal { normal: (-0.134912, 0.687491, -0.713551) }, + Normal { normal: (-0.31954, 0.633073, -0.705062) }, + Normal { normal: (-0.603902, 0.461442, -0.649903) }, + Normal { normal: (-0.631816, 0.437169, -0.640072) }, + Normal { normal: (-0.424306, 0.612706, -0.66675) }, + Normal { normal: (-0.4258, 0.904753, 0.0108049) }, + Normal { normal: (0.0220472, 0.999756, 0.00162273) }, + Normal { normal: (0.999599, 0.0258705, 0.0115556) }, + Normal { normal: (0.709585, -0.704553, 0.00967183) }, + Normal { normal: (-0.259858, 0.791936, 0.552549) }, + Normal { normal: (0.00953916, 0.99972, -0.0216718) }, + Normal { normal: (0.410156, 0.332912, -0.849083) }, + Normal { normal: (0.541523, -0.54862, -0.637) }, + Normal { normal: (0.0463104, 0.455224, 0.889172) }, + Normal { normal: (-0.0106883, 0.988794, 0.148901) }, + Normal { normal: (-0.0443756, 0.682947, -0.729118) }, + Normal { normal: (0.122825, 0.00923214, -0.992385) }, + Normal { normal: (0.481839, -0.180439, 0.85748) }, + Normal { normal: (0.455272, 0.736752, 0.499925) }, + Normal { normal: (-0.220542, 0.907193, -0.358276) }, + Normal { normal: (-0.23592, 0.657249, -0.715797) }, + Normal { normal: (0.728092, -0.685302, -0.0155853) }, + Normal { normal: (0.888739, 0.45811, -0.0166791) }, + Normal { normal: (-0.260097, 0.965582, 0.000800195) }, + Normal { normal: (-0.371612, 0.928378, -0.00441745) }, + Normal { normal: (0.480166, -0.17836, -0.858853) }, + Normal { normal: (0.488103, 0.716801, -0.497947) }, + Normal { normal: (-0.222004, 0.905399, 0.361893) }, + Normal { normal: (-0.235405, 0.66318, 0.710477) }, + Normal { normal: (0.0587203, 0.437704, -0.8972) }, + Normal { normal: (0.00132612, 0.986459, -0.164003) }, + Normal { normal: (-0.0441901, 0.681677, 0.730317) }, + Normal { normal: (0.138801, -0.0341896, 0.98973) }, + Normal { normal: (-0.25889, 0.797206, -0.54538) }, + Normal { normal: (0.0122703, 0.999739, 0.0192865) }, + Normal { normal: (0.39863, 0.35489, 0.845663) }, + Normal { normal: (0.537564, -0.5814, 0.610737) }, + Normal { normal: (-0.0, 1.0, 0.0) }, + Normal { normal: (0.82454, 0.565804, 0.0) }, + Normal { normal: (0.917701, -0.397272, 0.0) }, + Normal { normal: (0.935269, -0.353939, 0.000112842) }, + Normal { normal: (0.780712, 0.624891, 0.0) }, + Normal { normal: (0.762641, 0.565035, 0.314825) }, + Normal { normal: (0.847982, -0.397998, 0.350034) }, + Normal { normal: (0.864141, -0.355261, 0.356441) }, + Normal { normal: (0.720991, 0.625625, 0.297933) }, + Normal { normal: (0.583357, 0.565165, 0.583338) }, + Normal { normal: (0.648485, -0.398726, 0.648448) }, + Normal { normal: (0.660872, -0.355894, 0.660748) }, + Normal { normal: (0.551862, 0.62529, 0.55178) }, + Normal { normal: (0.314824, 0.565051, 0.762629) }, + Normal { normal: (0.350045, -0.397976, 0.847988) }, + Normal { normal: (0.356474, -0.3552, 0.864153) }, + Normal { normal: (0.297983, 0.625515, 0.721067) }, + Normal { normal: (-0.0, 0.565804, 0.82454) }, + Normal { normal: (-0.0, -0.397272, 0.917701) }, + Normal { normal: (-0.000112839, -0.353939, 0.935269) }, + Normal { normal: (-0.0, 0.624891, 0.780712) }, + Normal { normal: (-0.314825, 0.565035, 0.762641) }, + Normal { normal: (-0.350034, -0.397998, 0.847982) }, + Normal { normal: (-0.356441, -0.355261, 0.864141) }, + Normal { normal: (-0.297933, 0.625625, 0.720991) }, + Normal { normal: (-0.583338, 0.565165, 0.583357) }, + Normal { normal: (-0.648448, -0.398726, 0.648485) }, + Normal { normal: (-0.660748, -0.355894, 0.660872) }, + Normal { normal: (-0.55178, 0.62529, 0.551862) }, + Normal { normal: (-0.762629, 0.565051, 0.314824) }, + Normal { normal: (-0.847988, -0.397976, 0.350045) }, + Normal { normal: (-0.864153, -0.3552, 0.356474) }, + Normal { normal: (-0.721067, 0.625515, 0.297983) }, + Normal { normal: (-0.82454, 0.565804, -0.0) }, + Normal { normal: (-0.917701, -0.397272, -0.0) }, + Normal { normal: (-0.935269, -0.353939, -0.000112839) }, + Normal { normal: (-0.780712, 0.624891, -0.0) }, + Normal { normal: (-0.76264, 0.565035, -0.314825) }, + Normal { normal: (-0.847982, -0.397998, -0.350034) }, + Normal { normal: (-0.864141, -0.355261, -0.356441) }, + Normal { normal: (-0.720991, 0.625625, -0.297933) }, + Normal { normal: (-0.583357, 0.565165, -0.583338) }, + Normal { normal: (-0.648485, -0.398726, -0.648448) }, + Normal { normal: (-0.660872, -0.355894, -0.660748) }, + Normal { normal: (-0.551862, 0.62529, -0.55178) }, + Normal { normal: (-0.314824, 0.565051, -0.762629) }, + Normal { normal: (-0.350045, -0.397976, -0.847988) }, + Normal { normal: (-0.356474, -0.3552, -0.864153) }, + Normal { normal: (-0.297983, 0.625515, -0.721067) }, + Normal { normal: (0.0, 0.565804, -0.82454) }, + Normal { normal: (0.0, -0.397272, -0.917701) }, + Normal { normal: (0.000112839, -0.353939, -0.935269) }, + Normal { normal: (0.0, 0.624891, -0.780712) }, + Normal { normal: (0.314825, 0.565035, -0.762641) }, + Normal { normal: (0.350034, -0.397998, -0.847982) }, + Normal { normal: (0.356441, -0.355261, -0.864141) }, + Normal { normal: (0.297933, 0.625625, -0.720991) }, + Normal { normal: (0.583338, 0.565165, -0.583357) }, + Normal { normal: (0.648448, -0.398726, -0.648485) }, + Normal { normal: (0.660748, -0.355894, -0.660872) }, + Normal { normal: (0.55178, 0.62529, -0.551862) }, + Normal { normal: (0.762629, 0.565051, -0.314824) }, + Normal { normal: (0.847988, -0.397976, -0.350045) }, + Normal { normal: (0.864153, -0.3552, -0.356474) }, + Normal { normal: (0.721067, 0.625515, -0.297983) }, + Normal { normal: (0.236584, 0.971611, 0.0) }, + Normal { normal: (0.173084, 0.984907, -0.0) }, + Normal { normal: (0.379703, 0.925108, 0.0) }, + Normal { normal: (0.526673, 0.850068, 0.0) }, + Normal { normal: (0.217978, 0.971775, 0.0902162) }, + Normal { normal: (0.15959, 0.984977, 0.0659615) }, + Normal { normal: (0.350498, 0.925312, 0.14474) }, + Normal { normal: (0.48559, 0.850653, 0.201474) }, + Normal { normal: (0.166631, 0.971838, 0.166631) }, + Normal { normal: (0.121908, 0.985026, 0.121908) }, + Normal { normal: (0.267668, 0.925585, 0.267668) }, + Normal { normal: (0.371315, 0.851029, 0.371315) }, + Normal { normal: (0.0902162, 0.971775, 0.217978) }, + Normal { normal: (0.0659615, 0.984977, 0.15959) }, + Normal { normal: (0.14474, 0.925312, 0.350498) }, + Normal { normal: (0.201474, 0.850653, 0.48559) }, + Normal { normal: (-0.0, 0.971611, 0.236584) }, + Normal { normal: (0.0, 0.984907, 0.173084) }, + Normal { normal: (0.0, 0.925108, 0.379703) }, + Normal { normal: (0.0, 0.850068, 0.526673) }, + Normal { normal: (-0.0902162, 0.971775, 0.217978) }, + Normal { normal: (-0.0659615, 0.984977, 0.15959) }, + Normal { normal: (-0.14474, 0.925312, 0.350498) }, + Normal { normal: (-0.201474, 0.850653, 0.48559) }, + Normal { normal: (-0.166631, 0.971838, 0.166631) }, + Normal { normal: (-0.121908, 0.985026, 0.121908) }, + Normal { normal: (-0.267668, 0.925585, 0.267668) }, + Normal { normal: (-0.371315, 0.851029, 0.371315) }, + Normal { normal: (-0.217978, 0.971775, 0.0902162) }, + Normal { normal: (-0.15959, 0.984977, 0.0659615) }, + Normal { normal: (-0.350498, 0.925312, 0.14474) }, + Normal { normal: (-0.48559, 0.850653, 0.201474) }, + Normal { normal: (-0.236583, 0.971611, -0.0) }, + Normal { normal: (-0.173084, 0.984907, 0.0) }, + Normal { normal: (-0.379703, 0.925108, -0.0) }, + Normal { normal: (-0.526673, 0.850068, 0.0) }, + Normal { normal: (-0.217978, 0.971775, -0.0902162) }, + Normal { normal: (-0.15959, 0.984977, -0.0659615) }, + Normal { normal: (-0.350498, 0.925312, -0.14474) }, + Normal { normal: (-0.48559, 0.850653, -0.201474) }, + Normal { normal: (-0.166631, 0.971838, -0.166631) }, + Normal { normal: (-0.121908, 0.985026, -0.121908) }, + Normal { normal: (-0.267668, 0.925585, -0.267668) }, + Normal { normal: (-0.371315, 0.851029, -0.371315) }, + Normal { normal: (-0.0902162, 0.971775, -0.217978) }, + Normal { normal: (-0.0659615, 0.984977, -0.15959) }, + Normal { normal: (-0.14474, 0.925312, -0.350498) }, + Normal { normal: (-0.201474, 0.850653, -0.485589) }, + Normal { normal: (0.0, 0.971611, -0.236584) }, + Normal { normal: (-0.0, 0.984907, -0.173084) }, + Normal { normal: (-0.0, 0.925108, -0.379703) }, + Normal { normal: (-0.0, 0.850068, -0.526673) }, + Normal { normal: (0.0902162, 0.971775, -0.217978) }, + Normal { normal: (0.0659615, 0.984977, -0.15959) }, + Normal { normal: (0.14474, 0.925312, -0.350498) }, + Normal { normal: (0.201474, 0.850653, -0.48559) }, + Normal { normal: (0.166631, 0.971838, -0.166631) }, + Normal { normal: (0.121908, 0.985026, -0.121908) }, + Normal { normal: (0.267668, 0.925585, -0.267668) }, + Normal { normal: (0.371315, 0.851029, -0.371315) }, + Normal { normal: (0.217978, 0.971775, -0.0902162) }, + Normal { normal: (0.15959, 0.984977, -0.0659615) }, + Normal { normal: (0.350498, 0.925312, -0.14474) }, + Normal { normal: (0.48559, 0.850653, -0.201474) }, +]; + +pub const INDICES: [u16; 3072] = [ + 7, 6, 1, + 1, 2, 7, + 8, 7, 2, + 2, 3, 8, + 9, 8, 3, + 3, 4, 9, + 10, 9, 4, + 4, 5, 10, + 12, 11, 6, + 6, 7, 12, + 13, 12, 7, + 7, 8, 13, + 14, 13, 8, + 8, 9, 14, + 15, 14, 9, + 9, 10, 15, + 17, 16, 11, + 11, 12, 17, + 18, 17, 12, + 12, 13, 18, + 19, 18, 13, + 13, 14, 19, + 20, 19, 14, + 14, 15, 20, + 22, 21, 16, + 16, 17, 22, + 23, 22, 17, + 17, 18, 23, + 24, 23, 18, + 18, 19, 24, + 25, 24, 19, + 19, 20, 25, + 27, 26, 21, + 21, 22, 27, + 28, 27, 22, + 22, 23, 28, + 29, 28, 23, + 23, 24, 29, + 30, 29, 24, + 24, 25, 30, + 32, 31, 26, + 26, 27, 32, + 33, 32, 27, + 27, 28, 33, + 34, 33, 28, + 28, 29, 34, + 35, 34, 29, + 29, 30, 35, + 37, 36, 31, + 31, 32, 37, + 38, 37, 32, + 32, 33, 38, + 39, 38, 33, + 33, 34, 39, + 40, 39, 34, + 34, 35, 40, + 42, 41, 36, + 36, 37, 42, + 43, 42, 37, + 37, 38, 43, + 44, 43, 38, + 38, 39, 44, + 45, 44, 39, + 39, 40, 45, + 47, 46, 41, + 41, 42, 47, + 48, 47, 42, + 42, 43, 48, + 49, 48, 43, + 43, 44, 49, + 50, 49, 44, + 44, 45, 50, + 52, 51, 46, + 46, 47, 52, + 53, 52, 47, + 47, 48, 53, + 54, 53, 48, + 48, 49, 54, + 55, 54, 49, + 49, 50, 55, + 57, 56, 51, + 51, 52, 57, + 58, 57, 52, + 52, 53, 58, + 59, 58, 53, + 53, 54, 59, + 60, 59, 54, + 54, 55, 60, + 62, 61, 56, + 56, 57, 62, + 63, 62, 57, + 57, 58, 63, + 64, 63, 58, + 58, 59, 64, + 65, 64, 59, + 59, 60, 65, + 67, 66, 61, + 61, 62, 67, + 68, 67, 62, + 62, 63, 68, + 69, 68, 63, + 63, 64, 69, + 70, 69, 64, + 64, 65, 70, + 72, 71, 66, + 66, 67, 72, + 73, 72, 67, + 67, 68, 73, + 74, 73, 68, + 68, 69, 74, + 75, 74, 69, + 69, 70, 75, + 77, 76, 71, + 71, 72, 77, + 78, 77, 72, + 72, 73, 78, + 79, 78, 73, + 73, 74, 79, + 80, 79, 74, + 74, 75, 80, + 2, 1, 76, + 76, 77, 2, + 3, 2, 77, + 77, 78, 3, + 4, 3, 78, + 78, 79, 4, + 5, 4, 79, + 79, 80, 5, + 85, 10, 5, + 5, 81, 85, + 86, 85, 81, + 81, 82, 86, + 87, 86, 82, + 82, 83, 87, + 88, 87, 83, + 83, 84, 88, + 89, 15, 10, + 10, 85, 89, + 90, 89, 85, + 85, 86, 90, + 91, 90, 86, + 86, 87, 91, + 92, 91, 87, + 87, 88, 92, + 93, 20, 15, + 15, 89, 93, + 94, 93, 89, + 89, 90, 94, + 95, 94, 90, + 90, 91, 95, + 96, 95, 91, + 91, 92, 96, + 97, 25, 20, + 20, 93, 97, + 98, 97, 93, + 93, 94, 98, + 99, 98, 94, + 94, 95, 99, + 100, 99, 95, + 95, 96, 100, + 101, 30, 25, + 25, 97, 101, + 102, 101, 97, + 97, 98, 102, + 103, 102, 98, + 98, 99, 103, + 104, 103, 99, + 99, 100, 104, + 105, 35, 30, + 30, 101, 105, + 106, 105, 101, + 101, 102, 106, + 107, 106, 102, + 102, 103, 107, + 108, 107, 103, + 103, 104, 108, + 109, 40, 35, + 35, 105, 109, + 110, 109, 105, + 105, 106, 110, + 111, 110, 106, + 106, 107, 111, + 112, 111, 107, + 107, 108, 112, + 113, 45, 40, + 40, 109, 113, + 114, 113, 109, + 109, 110, 114, + 115, 114, 110, + 110, 111, 115, + 116, 115, 111, + 111, 112, 116, + 117, 50, 45, + 45, 113, 117, + 118, 117, 113, + 113, 114, 118, + 119, 118, 114, + 114, 115, 119, + 120, 119, 115, + 115, 116, 120, + 121, 55, 50, + 50, 117, 121, + 122, 121, 117, + 117, 118, 122, + 123, 122, 118, + 118, 119, 123, + 124, 123, 119, + 119, 120, 124, + 125, 60, 55, + 55, 121, 125, + 126, 125, 121, + 121, 122, 126, + 127, 126, 122, + 122, 123, 127, + 128, 127, 123, + 123, 124, 128, + 129, 65, 60, + 60, 125, 129, + 130, 129, 125, + 125, 126, 130, + 131, 130, 126, + 126, 127, 131, + 132, 131, 127, + 127, 128, 132, + 133, 70, 65, + 65, 129, 133, + 134, 133, 129, + 129, 130, 134, + 135, 134, 130, + 130, 131, 135, + 136, 135, 131, + 131, 132, 136, + 137, 75, 70, + 70, 133, 137, + 138, 137, 133, + 133, 134, 138, + 139, 138, 134, + 134, 135, 139, + 140, 139, 135, + 135, 136, 140, + 141, 80, 75, + 75, 137, 141, + 142, 141, 137, + 137, 138, 142, + 143, 142, 138, + 138, 139, 143, + 144, 143, 139, + 139, 140, 144, + 81, 5, 80, + 80, 141, 81, + 82, 81, 141, + 141, 142, 82, + 83, 82, 142, + 142, 143, 83, + 84, 83, 143, + 143, 144, 84, + 149, 88, 84, + 84, 145, 149, + 150, 149, 145, + 145, 146, 150, + 151, 150, 146, + 146, 147, 151, + 152, 151, 147, + 147, 148, 152, + 153, 92, 88, + 88, 149, 153, + 154, 153, 149, + 149, 150, 154, + 155, 154, 150, + 150, 151, 155, + 156, 155, 151, + 151, 152, 156, + 157, 96, 92, + 92, 153, 157, + 158, 157, 153, + 153, 154, 158, + 159, 158, 154, + 154, 155, 159, + 160, 159, 155, + 155, 156, 160, + 161, 100, 96, + 96, 157, 161, + 162, 161, 157, + 157, 158, 162, + 163, 162, 158, + 158, 159, 163, + 164, 163, 159, + 159, 160, 164, + 165, 104, 100, + 100, 161, 165, + 166, 165, 161, + 161, 162, 166, + 167, 166, 162, + 162, 163, 167, + 168, 167, 163, + 163, 164, 168, + 169, 108, 104, + 104, 165, 169, + 170, 169, 165, + 165, 166, 170, + 171, 170, 166, + 166, 167, 171, + 172, 171, 167, + 167, 168, 172, + 173, 112, 108, + 108, 169, 173, + 174, 173, 169, + 169, 170, 174, + 175, 174, 170, + 170, 171, 175, + 176, 175, 171, + 171, 172, 176, + 177, 116, 112, + 112, 173, 177, + 178, 177, 173, + 173, 174, 178, + 179, 178, 174, + 174, 175, 179, + 180, 179, 175, + 175, 176, 180, + 181, 120, 116, + 116, 177, 181, + 182, 181, 177, + 177, 178, 182, + 183, 182, 178, + 178, 179, 183, + 184, 183, 179, + 179, 180, 184, + 185, 124, 120, + 120, 181, 185, + 186, 185, 181, + 181, 182, 186, + 187, 186, 182, + 182, 183, 187, + 188, 187, 183, + 183, 184, 188, + 189, 128, 124, + 124, 185, 189, + 190, 189, 185, + 185, 186, 190, + 191, 190, 186, + 186, 187, 191, + 192, 191, 187, + 187, 188, 192, + 193, 132, 128, + 128, 189, 193, + 194, 193, 189, + 189, 190, 194, + 195, 194, 190, + 190, 191, 195, + 196, 195, 191, + 191, 192, 196, + 197, 136, 132, + 132, 193, 197, + 198, 197, 193, + 193, 194, 198, + 199, 198, 194, + 194, 195, 199, + 200, 199, 195, + 195, 196, 200, + 201, 140, 136, + 136, 197, 201, + 202, 201, 197, + 197, 198, 202, + 203, 202, 198, + 198, 199, 203, + 204, 203, 199, + 199, 200, 204, + 205, 144, 140, + 140, 201, 205, + 206, 205, 201, + 201, 202, 206, + 207, 206, 202, + 202, 203, 207, + 208, 207, 203, + 203, 204, 208, + 145, 84, 144, + 144, 205, 145, + 146, 145, 205, + 205, 206, 146, + 147, 146, 206, + 206, 207, 147, + 148, 147, 207, + 207, 208, 148, + 213, 152, 148, + 148, 209, 213, + 214, 213, 209, + 209, 210, 214, + 215, 214, 210, + 210, 211, 215, + 212, 215, 211, + 211, 212, 212, + 216, 156, 152, + 152, 213, 216, + 217, 216, 213, + 213, 214, 217, + 218, 217, 214, + 214, 215, 218, + 212, 218, 215, + 215, 212, 212, + 219, 160, 156, + 156, 216, 219, + 220, 219, 216, + 216, 217, 220, + 221, 220, 217, + 217, 218, 221, + 212, 221, 218, + 218, 212, 212, + 222, 164, 160, + 160, 219, 222, + 223, 222, 219, + 219, 220, 223, + 224, 223, 220, + 220, 221, 224, + 212, 224, 221, + 221, 212, 212, + 225, 168, 164, + 164, 222, 225, + 226, 225, 222, + 222, 223, 226, + 227, 226, 223, + 223, 224, 227, + 212, 227, 224, + 224, 212, 212, + 228, 172, 168, + 168, 225, 228, + 229, 228, 225, + 225, 226, 229, + 230, 229, 226, + 226, 227, 230, + 212, 230, 227, + 227, 212, 212, + 231, 176, 172, + 172, 228, 231, + 232, 231, 228, + 228, 229, 232, + 233, 232, 229, + 229, 230, 233, + 212, 233, 230, + 230, 212, 212, + 234, 180, 176, + 176, 231, 234, + 235, 234, 231, + 231, 232, 235, + 236, 235, 232, + 232, 233, 236, + 212, 236, 233, + 233, 212, 212, + 237, 184, 180, + 180, 234, 237, + 238, 237, 234, + 234, 235, 238, + 239, 238, 235, + 235, 236, 239, + 212, 239, 236, + 236, 212, 212, + 240, 188, 184, + 184, 237, 240, + 241, 240, 237, + 237, 238, 241, + 242, 241, 238, + 238, 239, 242, + 212, 242, 239, + 239, 212, 212, + 243, 192, 188, + 188, 240, 243, + 244, 243, 240, + 240, 241, 244, + 245, 244, 241, + 241, 242, 245, + 212, 245, 242, + 242, 212, 212, + 246, 196, 192, + 192, 243, 246, + 247, 246, 243, + 243, 244, 247, + 248, 247, 244, + 244, 245, 248, + 212, 248, 245, + 245, 212, 212, + 249, 200, 196, + 196, 246, 249, + 250, 249, 246, + 246, 247, 250, + 251, 250, 247, + 247, 248, 251, + 212, 251, 248, + 248, 212, 212, + 252, 204, 200, + 200, 249, 252, + 253, 252, 249, + 249, 250, 253, + 254, 253, 250, + 250, 251, 254, + 212, 254, 251, + 251, 212, 212, + 255, 208, 204, + 204, 252, 255, + 256, 255, 252, + 252, 253, 256, + 257, 256, 253, + 253, 254, 257, + 212, 257, 254, + 254, 212, 212, + 209, 148, 208, + 208, 255, 209, + 210, 209, 255, + 255, 256, 210, + 211, 210, 256, + 256, 257, 211, + 212, 211, 257, + 257, 212, 212, + 264, 263, 258, + 258, 259, 264, + 265, 264, 259, + 259, 260, 265, + 266, 265, 260, + 260, 261, 266, + 267, 266, 261, + 261, 262, 267, + 269, 268, 263, + 263, 264, 269, + 270, 269, 264, + 264, 265, 270, + 271, 270, 265, + 265, 266, 271, + 272, 271, 266, + 266, 267, 272, + 274, 273, 268, + 268, 269, 274, + 275, 274, 269, + 269, 270, 275, + 276, 275, 270, + 270, 271, 276, + 277, 276, 271, + 271, 272, 277, + 279, 278, 273, + 273, 274, 279, + 280, 279, 274, + 274, 275, 280, + 281, 280, 275, + 275, 276, 281, + 282, 281, 276, + 276, 277, 282, + 284, 283, 278, + 278, 279, 284, + 285, 284, 279, + 279, 280, 285, + 286, 285, 280, + 280, 281, 286, + 287, 286, 281, + 281, 282, 287, + 289, 288, 283, + 283, 284, 289, + 290, 289, 284, + 284, 285, 290, + 291, 290, 285, + 285, 286, 291, + 292, 291, 286, + 286, 287, 292, + 294, 293, 288, + 288, 289, 294, + 295, 294, 289, + 289, 290, 295, + 296, 295, 290, + 290, 291, 296, + 297, 296, 291, + 291, 292, 297, + 259, 258, 293, + 293, 294, 259, + 260, 259, 294, + 294, 295, 260, + 261, 260, 295, + 295, 296, 261, + 262, 261, 296, + 296, 297, 262, + 302, 267, 262, + 262, 298, 302, + 303, 302, 298, + 298, 299, 303, + 304, 303, 299, + 299, 300, 304, + 305, 304, 300, + 300, 301, 305, + 306, 272, 267, + 267, 302, 306, + 307, 306, 302, + 302, 303, 307, + 308, 307, 303, + 303, 304, 308, + 309, 308, 304, + 304, 305, 309, + 310, 277, 272, + 272, 306, 310, + 311, 310, 306, + 306, 307, 311, + 312, 311, 307, + 307, 308, 312, + 313, 312, 308, + 308, 309, 313, + 314, 282, 277, + 277, 310, 314, + 315, 314, 310, + 310, 311, 315, + 316, 315, 311, + 311, 312, 316, + 317, 316, 312, + 312, 313, 317, + 318, 287, 282, + 282, 314, 318, + 319, 318, 314, + 314, 315, 319, + 320, 319, 315, + 315, 316, 320, + 321, 320, 316, + 316, 317, 321, + 322, 292, 287, + 287, 318, 322, + 323, 322, 318, + 318, 319, 323, + 324, 323, 319, + 319, 320, 324, + 325, 324, 320, + 320, 321, 325, + 326, 297, 292, + 292, 322, 326, + 327, 326, 322, + 322, 323, 327, + 328, 327, 323, + 323, 324, 328, + 329, 328, 324, + 324, 325, 329, + 298, 262, 297, + 297, 326, 298, + 299, 298, 326, + 326, 327, 299, + 300, 299, 327, + 327, 328, 300, + 301, 300, 328, + 328, 329, 301, + 336, 335, 330, + 330, 331, 336, + 337, 336, 331, + 331, 332, 337, + 338, 337, 332, + 332, 333, 338, + 339, 338, 333, + 333, 334, 339, + 341, 340, 335, + 335, 336, 341, + 342, 341, 336, + 336, 337, 342, + 343, 342, 337, + 337, 338, 343, + 344, 343, 338, + 338, 339, 344, + 346, 345, 340, + 340, 341, 346, + 347, 346, 341, + 341, 342, 347, + 348, 347, 342, + 342, 343, 348, + 349, 348, 343, + 343, 344, 349, + 351, 350, 345, + 345, 346, 351, + 352, 351, 346, + 346, 347, 352, + 353, 352, 347, + 347, 348, 353, + 354, 353, 348, + 348, 349, 354, + 356, 355, 350, + 350, 351, 356, + 357, 356, 351, + 351, 352, 357, + 358, 357, 352, + 352, 353, 358, + 359, 358, 353, + 353, 354, 359, + 361, 360, 355, + 355, 356, 361, + 362, 361, 356, + 356, 357, 362, + 363, 362, 357, + 357, 358, 363, + 364, 363, 358, + 358, 359, 364, + 366, 365, 360, + 360, 361, 366, + 367, 366, 361, + 361, 362, 367, + 368, 367, 362, + 362, 363, 368, + 369, 368, 363, + 363, 364, 369, + 331, 330, 365, + 365, 366, 331, + 332, 331, 366, + 366, 367, 332, + 333, 332, 367, + 367, 368, 333, + 334, 333, 368, + 368, 369, 334, + 374, 339, 334, + 334, 370, 374, + 375, 374, 370, + 370, 371, 375, + 376, 375, 371, + 371, 372, 376, + 377, 376, 372, + 372, 373, 377, + 378, 344, 339, + 339, 374, 378, + 379, 378, 374, + 374, 375, 379, + 380, 379, 375, + 375, 376, 380, + 381, 380, 376, + 376, 377, 381, + 382, 349, 344, + 344, 378, 382, + 383, 382, 378, + 378, 379, 383, + 384, 383, 379, + 379, 380, 384, + 385, 384, 380, + 380, 381, 385, + 386, 354, 349, + 349, 382, 386, + 387, 386, 382, + 382, 383, 387, + 388, 387, 383, + 383, 384, 388, + 389, 388, 384, + 384, 385, 389, + 390, 359, 354, + 354, 386, 390, + 391, 390, 386, + 386, 387, 391, + 392, 391, 387, + 387, 388, 392, + 393, 392, 388, + 388, 389, 393, + 394, 364, 359, + 359, 390, 394, + 395, 394, 390, + 390, 391, 395, + 396, 395, 391, + 391, 392, 396, + 397, 396, 392, + 392, 393, 397, + 398, 369, 364, + 364, 394, 398, + 399, 398, 394, + 394, 395, 399, + 400, 399, 395, + 395, 396, 400, + 401, 400, 396, + 396, 397, 401, + 370, 334, 369, + 369, 398, 370, + 371, 370, 398, + 398, 399, 371, + 372, 371, 399, + 399, 400, 372, + 373, 372, 400, + 400, 401, 373, + 407, 402, 402, + 402, 403, 407, + 408, 407, 403, + 403, 404, 408, + 409, 408, 404, + 404, 405, 409, + 410, 409, 405, + 405, 406, 410, + 411, 402, 402, + 402, 407, 411, + 412, 411, 407, + 407, 408, 412, + 413, 412, 408, + 408, 409, 413, + 414, 413, 409, + 409, 410, 414, + 415, 402, 402, + 402, 411, 415, + 416, 415, 411, + 411, 412, 416, + 417, 416, 412, + 412, 413, 417, + 418, 417, 413, + 413, 414, 418, + 419, 402, 402, + 402, 415, 419, + 420, 419, 415, + 415, 416, 420, + 421, 420, 416, + 416, 417, 421, + 422, 421, 417, + 417, 418, 422, + 423, 402, 402, + 402, 419, 423, + 424, 423, 419, + 419, 420, 424, + 425, 424, 420, + 420, 421, 425, + 426, 425, 421, + 421, 422, 426, + 427, 402, 402, + 402, 423, 427, + 428, 427, 423, + 423, 424, 428, + 429, 428, 424, + 424, 425, 429, + 430, 429, 425, + 425, 426, 430, + 431, 402, 402, + 402, 427, 431, + 432, 431, 427, + 427, 428, 432, + 433, 432, 428, + 428, 429, 433, + 434, 433, 429, + 429, 430, 434, + 435, 402, 402, + 402, 431, 435, + 436, 435, 431, + 431, 432, 436, + 437, 436, 432, + 432, 433, 437, + 438, 437, 433, + 433, 434, 438, + 439, 402, 402, + 402, 435, 439, + 440, 439, 435, + 435, 436, 440, + 441, 440, 436, + 436, 437, 441, + 442, 441, 437, + 437, 438, 442, + 443, 402, 402, + 402, 439, 443, + 444, 443, 439, + 439, 440, 444, + 445, 444, 440, + 440, 441, 445, + 446, 445, 441, + 441, 442, 446, + 447, 402, 402, + 402, 443, 447, + 448, 447, 443, + 443, 444, 448, + 449, 448, 444, + 444, 445, 449, + 450, 449, 445, + 445, 446, 450, + 451, 402, 402, + 402, 447, 451, + 452, 451, 447, + 447, 448, 452, + 453, 452, 448, + 448, 449, 453, + 454, 453, 449, + 449, 450, 454, + 455, 402, 402, + 402, 451, 455, + 456, 455, 451, + 451, 452, 456, + 457, 456, 452, + 452, 453, 457, + 458, 457, 453, + 453, 454, 458, + 459, 402, 402, + 402, 455, 459, + 460, 459, 455, + 455, 456, 460, + 461, 460, 456, + 456, 457, 461, + 462, 461, 457, + 457, 458, 462, + 463, 402, 402, + 402, 459, 463, + 464, 463, 459, + 459, 460, 464, + 465, 464, 460, + 460, 461, 465, + 466, 465, 461, + 461, 462, 466, + 403, 402, 402, + 402, 463, 403, + 404, 403, 463, + 463, 464, 404, + 405, 404, 464, + 464, 465, 405, + 406, 405, 465, + 465, 466, 406, + 471, 410, 406, + 406, 467, 471, + 472, 471, 467, + 467, 468, 472, + 473, 472, 468, + 468, 469, 473, + 474, 473, 469, + 469, 470, 474, + 475, 414, 410, + 410, 471, 475, + 476, 475, 471, + 471, 472, 476, + 477, 476, 472, + 472, 473, 477, + 478, 477, 473, + 473, 474, 478, + 479, 418, 414, + 414, 475, 479, + 480, 479, 475, + 475, 476, 480, + 481, 480, 476, + 476, 477, 481, + 482, 481, 477, + 477, 478, 482, + 483, 422, 418, + 418, 479, 483, + 484, 483, 479, + 479, 480, 484, + 485, 484, 480, + 480, 481, 485, + 486, 485, 481, + 481, 482, 486, + 487, 426, 422, + 422, 483, 487, + 488, 487, 483, + 483, 484, 488, + 489, 488, 484, + 484, 485, 489, + 490, 489, 485, + 485, 486, 490, + 491, 430, 426, + 426, 487, 491, + 492, 491, 487, + 487, 488, 492, + 493, 492, 488, + 488, 489, 493, + 494, 493, 489, + 489, 490, 494, + 495, 434, 430, + 430, 491, 495, + 496, 495, 491, + 491, 492, 496, + 497, 496, 492, + 492, 493, 497, + 498, 497, 493, + 493, 494, 498, + 499, 438, 434, + 434, 495, 499, + 500, 499, 495, + 495, 496, 500, + 501, 500, 496, + 496, 497, 501, + 502, 501, 497, + 497, 498, 502, + 503, 442, 438, + 438, 499, 503, + 504, 503, 499, + 499, 500, 504, + 505, 504, 500, + 500, 501, 505, + 506, 505, 501, + 501, 502, 506, + 507, 446, 442, + 442, 503, 507, + 508, 507, 503, + 503, 504, 508, + 509, 508, 504, + 504, 505, 509, + 510, 509, 505, + 505, 506, 510, + 511, 450, 446, + 446, 507, 511, + 512, 511, 507, + 507, 508, 512, + 513, 512, 508, + 508, 509, 513, + 514, 513, 509, + 509, 510, 514, + 515, 454, 450, + 450, 511, 515, + 516, 515, 511, + 511, 512, 516, + 517, 516, 512, + 512, 513, 517, + 518, 517, 513, + 513, 514, 518, + 519, 458, 454, + 454, 515, 519, + 520, 519, 515, + 515, 516, 520, + 521, 520, 516, + 516, 517, 521, + 522, 521, 517, + 517, 518, 522, + 523, 462, 458, + 458, 519, 523, + 524, 523, 519, + 519, 520, 524, + 525, 524, 520, + 520, 521, 525, + 526, 525, 521, + 521, 522, 526, + 527, 466, 462, + 462, 523, 527, + 528, 527, 523, + 523, 524, 528, + 529, 528, 524, + 524, 525, 529, + 530, 529, 525, + 525, 526, 530, + 467, 406, 466, + 466, 527, 467, + 468, 467, 527, + 527, 528, 468, + 469, 468, 528, + 528, 529, 469, + 470, 469, 529, + 529, 530, 470u16, +]; From 95070f854cb7d0b5d1815d9046fa41e88fcac98d Mon Sep 17 00:00:00 2001 From: reo Date: Sun, 29 Jun 2025 23:17:53 +0300 Subject: [PATCH 02/89] Implement a basic engine with separate modules --- Cargo.lock | 130 +++++++++++++++++++++- Cargo.toml | 15 ++- resources/cube.bin | Bin 0 -> 840 bytes resources/cube.gltf | 121 +++++++++++++++++++++ resources/cube.obj | 33 ++++++ resources/monkey-smooth.bin | Bin 0 -> 23568 bytes resources/monkey-smooth.gltf | 104 ++++++++++++++++++ resources/monkey.bin | Bin 0 -> 68720 bytes resources/monkey.gltf | 104 ++++++++++++++++++ resources/uvsphere-smooth.bin | Bin 0 -> 23648 bytes resources/uvsphere-smooth.gltf | 109 +++++++++++++++++++ resources/uvsphere.bin | Bin 0 -> 69248 bytes resources/uvsphere.gltf | 104 ++++++++++++++++++ resources/uvsphere2.bin | Bin 0 -> 70088 bytes resources/uvsphere2.gltf | 190 +++++++++++++++++++++++++++++++++ src/camera.rs | 24 +++++ src/ecs.rs | 32 ++++++ src/main.rs | 185 +++++++++++++------------------- src/model.rs | 124 +++++++++++++++++++++ src/render.rs | 95 +++++++++++++++++ 20 files changed, 1253 insertions(+), 117 deletions(-) create mode 100644 resources/cube.bin create mode 100644 resources/cube.gltf create mode 100644 resources/cube.obj create mode 100644 resources/monkey-smooth.bin create mode 100644 resources/monkey-smooth.gltf create mode 100644 resources/monkey.bin create mode 100644 resources/monkey.gltf create mode 100644 resources/uvsphere-smooth.bin create mode 100644 resources/uvsphere-smooth.gltf create mode 100644 resources/uvsphere.bin create mode 100644 resources/uvsphere.gltf create mode 100644 resources/uvsphere2.bin create mode 100644 resources/uvsphere2.gltf create mode 100644 src/camera.rs create mode 100644 src/ecs.rs create mode 100644 src/model.rs create mode 100644 src/render.rs diff --git a/Cargo.lock b/Cargo.lock index bfff70b..df2430f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -173,6 +173,12 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + [[package]] name = "bit_field" version = "0.10.2" @@ -224,6 +230,12 @@ version = "1.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c76a5792e44e4abe34d3abf15636779261d45a7450612059293d1d2cfc63422" +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + [[package]] name = "byteorder-lite" version = "0.1.0" @@ -571,8 +583,12 @@ checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" name = "fps" version = "0.1.0" dependencies = [ + "anyhow", + "glam", "glium", + "gltf", "glutin", + "hecs", "image", ] @@ -636,6 +652,12 @@ dependencies = [ "xml-rs", ] +[[package]] +name = "glam" +version = "0.30.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50a99dbe56b72736564cfa4b85bf9a33079f16ae8b74983ab06af3b1a3696b11" + [[package]] name = "glium" version = "0.36.0" @@ -653,6 +675,45 @@ dependencies = [ "winit", ] +[[package]] +name = "gltf" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3ce1918195723ce6ac74e80542c5a96a40c2b26162c1957a5cd70799b8cacf7" +dependencies = [ + "base64", + "byteorder", + "gltf-json", + "image", + "lazy_static", + "serde_json", + "urlencoding", +] + +[[package]] +name = "gltf-derive" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14070e711538afba5d6c807edb74bcb84e5dbb9211a3bf5dea0dfab5b24f4c51" +dependencies = [ + "inflections", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "gltf-json" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6176f9d60a7eab0a877e8e96548605dedbde9190a7ae1e80bbcc1c9af03ab14" +dependencies = [ + "gltf-derive", + "serde", + "serde_derive", + "serde_json", +] + [[package]] name = "glutin" version = "0.32.3" @@ -729,6 +790,15 @@ dependencies = [ "crunchy", ] +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +dependencies = [ + "ahash", +] + [[package]] name = "hashbrown" version = "0.15.4" @@ -741,6 +811,16 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" +[[package]] +name = "hecs" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cbc675ee8d97b4d206a985137f8ad59666538f56f906474f554467a63c776d" +dependencies = [ + "hashbrown 0.14.5", + "spin", +] + [[package]] name = "hermit-abi" version = "0.5.2" @@ -793,9 +873,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" dependencies = [ "equivalent", - "hashbrown", + "hashbrown 0.15.4", ] +[[package]] +name = "inflections" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a257582fdcde896fd96463bf2d40eefea0580021c0712a0e2b028b60b47a837a" + [[package]] name = "interpolate_name" version = "0.2.4" @@ -816,6 +902,12 @@ dependencies = [ "either", ] +[[package]] +name = "itoa" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" + [[package]] name = "jni" version = "0.21.1" @@ -870,6 +962,12 @@ version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc" +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + [[package]] name = "lebe" version = "0.5.2" @@ -1718,6 +1816,12 @@ version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" +[[package]] +name = "ryu" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" + [[package]] name = "same-file" version = "1.0.6" @@ -1766,6 +1870,18 @@ dependencies = [ "syn", ] +[[package]] +name = "serde_json" +version = "1.0.140" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + [[package]] name = "serde_spanned" version = "0.6.9" @@ -1842,6 +1958,12 @@ dependencies = [ "serde", ] +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + [[package]] name = "strict-num" version = "0.1.1" @@ -2002,6 +2124,12 @@ version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" +[[package]] +name = "urlencoding" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" + [[package]] name = "v_frame" version = "0.3.9" diff --git a/Cargo.toml b/Cargo.toml index 8b84c8b..8657bbe 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,6 +4,15 @@ version = "0.1.0" edition = "2021" [dependencies] -glium = "0.36.0" -glutin = "0.32.3" -image = "0.25.6" +anyhow = "1.0.98" +glam = "0.30.4" + +# glium already re-exports glutin/winit, but we enable the helper features explicitly +glium = { version = "0.36.0", features = ["glutin_backend", "simple_window_builder"] } +gltf = { version = "1.4.1", features = ["import"] } + +# explicit glutin for raw types (same semver as glium’s internal one) +glutin = { version = "0.32.3", default-features = false } + +hecs = "0.10.5" +image = "0.25.6" diff --git a/resources/cube.bin b/resources/cube.bin new file mode 100644 index 0000000000000000000000000000000000000000..29df9d975689d89810aab5225917fb635df0774c GIT binary patch literal 840 zcmaJ-TMmLS5FC6WDk#2wJ&E-w9HlqYqd6np1U7{x+u3q^hF3jvmN1l%U*ARP_G|L#K>?q^Dx4vv&`I9u$nLCd?v4G&yV^R98m2`f~*E8MZh0wwPfdo(z(u;DE61Gt!b{Qv*} literal 0 HcmV?d00001 diff --git a/resources/cube.gltf b/resources/cube.gltf new file mode 100644 index 0000000..8db6d67 --- /dev/null +++ b/resources/cube.gltf @@ -0,0 +1,121 @@ +{ + "asset":{ + "generator":"Khronos glTF Blender I/O v4.4.56", + "version":"2.0" + }, + "scene":0, + "scenes":[ + { + "name":"Scene", + "nodes":[ + 0 + ] + } + ], + "nodes":[ + { + "mesh":0, + "name":"Cube" + } + ], + "materials":[ + { + "doubleSided":true, + "name":"Material", + "pbrMetallicRoughness":{ + "baseColorFactor":[ + 0.800000011920929, + 0.800000011920929, + 0.800000011920929, + 1 + ], + "metallicFactor":0, + "roughnessFactor":0.5 + } + } + ], + "meshes":[ + { + "name":"Cube", + "primitives":[ + { + "attributes":{ + "POSITION":0, + "NORMAL":1, + "TEXCOORD_0":2 + }, + "indices":3, + "material":0 + } + ] + } + ], + "accessors":[ + { + "bufferView":0, + "componentType":5126, + "count":24, + "max":[ + 1, + 1, + 1 + ], + "min":[ + -1, + -1, + -1 + ], + "type":"VEC3" + }, + { + "bufferView":1, + "componentType":5126, + "count":24, + "type":"VEC3" + }, + { + "bufferView":2, + "componentType":5126, + "count":24, + "type":"VEC2" + }, + { + "bufferView":3, + "componentType":5123, + "count":36, + "type":"SCALAR" + } + ], + "bufferViews":[ + { + "buffer":0, + "byteLength":288, + "byteOffset":0, + "target":34962 + }, + { + "buffer":0, + "byteLength":288, + "byteOffset":288, + "target":34962 + }, + { + "buffer":0, + "byteLength":192, + "byteOffset":576, + "target":34962 + }, + { + "buffer":0, + "byteLength":72, + "byteOffset":768, + "target":34963 + } + ], + "buffers":[ + { + "byteLength":840, + "uri":"cube.bin" + } + ] +} diff --git a/resources/cube.obj b/resources/cube.obj new file mode 100644 index 0000000..c4d834c --- /dev/null +++ b/resources/cube.obj @@ -0,0 +1,33 @@ +# cube.obj +# + +g cube + +v 0.0 0.0 0.0 +v 0.0 0.0 1.0 +v 0.0 1.0 0.0 +v 0.0 1.0 1.0 +v 1.0 0.0 0.0 +v 1.0 0.0 1.0 +v 1.0 1.0 0.0 +v 1.0 1.0 1.0 + +vn 0.0 0.0 1.0 +vn 0.0 0.0 -1.0 +vn 0.0 1.0 0.0 +vn 0.0 -1.0 0.0 +vn 1.0 0.0 0.0 +vn -1.0 0.0 0.0 + +f 1//2 7//2 5//2 +f 1//2 3//2 7//2 +f 1//6 4//6 3//6 +f 1//6 2//6 4//6 +f 3//3 8//3 7//3 +f 3//3 4//3 8//3 +f 5//5 7//5 8//5 +f 5//5 8//5 6//5 +f 1//4 5//4 6//4 +f 1//4 6//4 2//4 +f 2//1 6//1 8//1 +f 2//1 8//1 4//1 diff --git a/resources/monkey-smooth.bin b/resources/monkey-smooth.bin new file mode 100644 index 0000000000000000000000000000000000000000..f6f4431ca0ef9904a1662b50e34ed08b9b7cfc38 GIT binary patch literal 23568 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 TT1(h(P&(iq@-?-=o%H_zzt6C? literal 0 HcmV?d00001 diff --git a/resources/monkey-smooth.gltf b/resources/monkey-smooth.gltf new file mode 100644 index 0000000..21b6404 --- /dev/null +++ b/resources/monkey-smooth.gltf @@ -0,0 +1,104 @@ +{ + "asset":{ + "generator":"Khronos glTF Blender I/O v4.4.56", + "version":"2.0" + }, + "scene":0, + "scenes":[ + { + "name":"Scene", + "nodes":[ + 0 + ] + } + ], + "nodes":[ + { + "mesh":0, + "name":"Suzanne" + } + ], + "meshes":[ + { + "name":"Suzanne", + "primitives":[ + { + "attributes":{ + "POSITION":0, + "NORMAL":1, + "TEXCOORD_0":2 + }, + "indices":3 + } + ] + } + ], + "accessors":[ + { + "bufferView":0, + "componentType":5126, + "count":555, + "max":[ + 1.3671875, + 0.984375, + 0.8515625 + ], + "min":[ + -1.3671875, + -0.984375, + -0.8515625 + ], + "type":"VEC3" + }, + { + "bufferView":1, + "componentType":5126, + "count":555, + "type":"VEC3" + }, + { + "bufferView":2, + "componentType":5126, + "count":555, + "type":"VEC2" + }, + { + "bufferView":3, + "componentType":5123, + "count":2904, + "type":"SCALAR" + } + ], + "bufferViews":[ + { + "buffer":0, + "byteLength":6660, + "byteOffset":0, + "target":34962 + }, + { + "buffer":0, + "byteLength":6660, + "byteOffset":6660, + "target":34962 + }, + { + "buffer":0, + "byteLength":4440, + "byteOffset":13320, + "target":34962 + }, + { + "buffer":0, + "byteLength":5808, + "byteOffset":17760, + "target":34963 + } + ], + "buffers":[ + { + "byteLength":23568, + "uri":"monkey-smooth.bin" + } + ] +} diff --git a/resources/monkey.bin b/resources/monkey.bin new file mode 100644 index 0000000000000000000000000000000000000000..e7992f36d75135cc5966e2abe94e5937420da413 GIT binary patch literal 68720 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 literal 0 HcmV?d00001 diff --git a/resources/monkey.gltf b/resources/monkey.gltf new file mode 100644 index 0000000..d3e2438 --- /dev/null +++ b/resources/monkey.gltf @@ -0,0 +1,104 @@ +{ + "asset":{ + "generator":"Khronos glTF Blender I/O v4.4.56", + "version":"2.0" + }, + "scene":0, + "scenes":[ + { + "name":"Scene", + "nodes":[ + 0 + ] + } + ], + "nodes":[ + { + "mesh":0, + "name":"Suzanne" + } + ], + "meshes":[ + { + "name":"Suzanne", + "primitives":[ + { + "attributes":{ + "POSITION":0, + "NORMAL":1, + "TEXCOORD_0":2 + }, + "indices":3 + } + ] + } + ], + "accessors":[ + { + "bufferView":0, + "componentType":5126, + "count":1966, + "max":[ + 1.3671875, + 0.984375, + 0.8515625 + ], + "min":[ + -1.3671875, + -0.984375, + -0.8515625 + ], + "type":"VEC3" + }, + { + "bufferView":1, + "componentType":5126, + "count":1966, + "type":"VEC3" + }, + { + "bufferView":2, + "componentType":5126, + "count":1966, + "type":"VEC2" + }, + { + "bufferView":3, + "componentType":5123, + "count":2904, + "type":"SCALAR" + } + ], + "bufferViews":[ + { + "buffer":0, + "byteLength":23592, + "byteOffset":0, + "target":34962 + }, + { + "buffer":0, + "byteLength":23592, + "byteOffset":23592, + "target":34962 + }, + { + "buffer":0, + "byteLength":15728, + "byteOffset":47184, + "target":34962 + }, + { + "buffer":0, + "byteLength":5808, + "byteOffset":62912, + "target":34963 + } + ], + "buffers":[ + { + "byteLength":68720, + "uri":"monkey.bin" + } + ] +} diff --git a/resources/uvsphere-smooth.bin b/resources/uvsphere-smooth.bin new file mode 100644 index 0000000000000000000000000000000000000000..f8b6e5cd108dc4067d8bf9789f596f67d82c790e GIT binary patch literal 23648 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 PDr7Lsx`S+kIQRbmKkNhC literal 0 HcmV?d00001 diff --git a/resources/uvsphere-smooth.gltf b/resources/uvsphere-smooth.gltf new file mode 100644 index 0000000..0f65991 --- /dev/null +++ b/resources/uvsphere-smooth.gltf @@ -0,0 +1,109 @@ +{ + "asset":{ + "generator":"Khronos glTF Blender I/O v4.4.56", + "version":"2.0" + }, + "scene":0, + "scenes":[ + { + "name":"Scene", + "nodes":[ + 0 + ] + } + ], + "nodes":[ + { + "mesh":0, + "name":"Sphere", + "translation":[ + 0, + 0, + 0.003377079963684082 + ] + } + ], + "meshes":[ + { + "name":"Sphere", + "primitives":[ + { + "attributes":{ + "POSITION":0, + "NORMAL":1, + "TEXCOORD_0":2 + }, + "indices":3 + } + ] + } + ], + "accessors":[ + { + "bufferView":0, + "componentType":5126, + "count":559, + "max":[ + 0.9999997019767761, + 1, + 0.9999993443489075 + ], + "min":[ + -0.9999990463256836, + -1, + -1 + ], + "type":"VEC3" + }, + { + "bufferView":1, + "componentType":5126, + "count":559, + "type":"VEC3" + }, + { + "bufferView":2, + "componentType":5126, + "count":559, + "type":"VEC2" + }, + { + "bufferView":3, + "componentType":5123, + "count":2880, + "type":"SCALAR" + } + ], + "bufferViews":[ + { + "buffer":0, + "byteLength":6708, + "byteOffset":0, + "target":34962 + }, + { + "buffer":0, + "byteLength":6708, + "byteOffset":6708, + "target":34962 + }, + { + "buffer":0, + "byteLength":4472, + "byteOffset":13416, + "target":34962 + }, + { + "buffer":0, + "byteLength":5760, + "byteOffset":17888, + "target":34963 + } + ], + "buffers":[ + { + "byteLength":23648, + "uri":"uvsphere-smooth.bin" + } + ] +} diff --git a/resources/uvsphere.bin b/resources/uvsphere.bin new file mode 100644 index 0000000000000000000000000000000000000000..dda76ba8ec32da7b97d7044c7e3dac792e01255f GIT binary patch literal 69248 zcmeHwcbpVO^M3bq&kRN|2Ml1ujAEAEJtGEG%vsNz6#;YL6m!I!6>~-e#Kg^DL=1>I zzn(d~iWpuaa=)tX>b3TEdg#BtfBpD;rs~^tJ9+BU09%0lqyKR>RZ|7&N=m51PmH<_pUi(aR8&V_5{A^7#hSEyo)`aCx% z55aGYT)(>TkIzSjBVw$t~mSW;e&iGS`iIeDi$Inu{Ht-Yq41UT&@Z!HMR7F1jsvpfl@Jo;G zQAIuvIz;6m_^pdBG<+UbSuqd6lfJ#(@OkTdHp@fs&-zir=abLcGY`RAuQJK-8Tk`} z7lN^ZeBNioQQ-I4V`|fIG6YkfGuHo7Og_n(e@Zd=JZJtd#T3(=#kUj_XL81$QcRr0 zxySLd6h8>_C-QmP;wxk!82gWWe)`+nvk-iIw_6OK_a5gLol>! z`26hOee)0uey`#DybbU_1jD>j!+93xw-Aiq70Bl`;QKuUQ=1uUzZ6rSGuHo7Og_n( ze@Zd=JZJtd#S~NYy^C)tCeGxHKc$#BnKOQt;?eN^j(mP-lX1$<9ckic;OKX<65$|5b!?)53Q_d_>A*U2!`)n!{@VM{S$(z z?_!2tClA5YX2#kt#nk7F^}iI8Pjcp;QcONa-#h=8Vv1?b;#-P|Gdbf=DJD+ljGv_# zcyIW8|DPYXhhP|2hR-iPx4SEm;VLdBJcP=7}r>KlgWE!{AU5DfFanNMII#d&|W7{?cWKTd@8X9zy&tUb+qg6roH{M+w` zn)zf4$UlVOy}>ug;(333HVeVjX2#kt#nk7F^}iI8Pjcp;QcOO_XGiD%QcN+;S$s<| zaVBT{DaFLeobj_1&ky+%SjBVw$t~mSWUWh@iijtjvPfuA<-IjLU={=0Ly z;j<8Z*ABtdW(NLr?U!QeGt{Z~zZ8>Ca%?{Ylh2`k-T$SSVhVNY@h!!~8K_g|Pbnr& zLY+E4OYwX(KVzOX1iLwTJ;<|$U|5$MK0g9^tPl*(rH0S&{8bIX%hUY)Hav%gU^gef z2J5U4{2n5wOIknU zb6yB`Yvvj791wzkrS&uHzf?o;ZnS>JHBAVnHZ#_KDR%2;*8i*wlTR=w>HJfQ$>%xq ze<`Mzn!TM6?AFhWKY1A@PUeiCrT7)fFWn3CX9&(IzcdB-8G?7G{L(Pk2MEEK-$OnR zggk2qewy-2nCA|`l%J_?592HZwhUG zpP0Ro5KKPLng2^M#WZK}Eycu{objg=6DM=V&r*Cp<^LZ59fDu~H~(J^!2>A&kNye4 zvpPG?eirHwyuiQt|5^y9{CRZ|QW`hG679&d)ecgy7wvU3?yV2IlDyO#7SFtzexJf;Xc5ScLz0TAa9d;`q?$Y-2;LNGp8BcJj6Hv~_H?-k_paxi~} zV0Wew`4fV>fnRX_d_UwlLh#*C7x_E^@*E+U+RRw{rI`9`I3I$^Cpq&^DJGxi%>SjB zVw$t~mSW;e&iGS`iIX|wXDJ5PkH!6zCu|%7aO*ha^ZaHW3c=IHA)nti-@_reZ7lK` z*PoaJojvXthkRZY-b08GEc)U6yr<1W1mGUyk&juTxXV(2c8*E~lv-r*i8_wj6KeNGxpE=`aDaL&ln4d%NYp^efd>#uv4Z+lA#@a8%)aQ)#zZ8>Ca^{~>Og_(<|4T8&G-vTG#l#si zCx>9-WX||mieY_X`23PxKhG9Jt}sJBW6m=K{TzbfOt|6mPr&~Wya=4zKtAsPJ_^CqX2#kt#nk7F^}iI8Pjcp; zQcOP2ng2^M#WZK}Eycu{objg=6F+mt&r*B`%%34f*~)QN-6_J4Ea^Rn=n zLol_OvGz+b^*LkxFU91OocX5|lg~{~F9cIea~9uHOq|IXe@ZcNGH3iO#rMMZJM#G+ zcn%A}IDV1O(;yEKg0}>IBA+*bJX{F=r?b=Wc_!qaL-2xd?i~3%AMif}4~BE+$mio= z{tvx|y{4B-jdwA}`7_=e!|M>sb4>0eT`D7I2fkJQw>nog3o`F1Q2;LRG zzi>V|0`>tyF#g>IKEG@Y^G^tdJx4R2>}2<6XNw2G-(}%^g897=4Ev{MK3U)H&(0RZ zo~)TqUV%9-1XKGNYrhmzpEK6~QcV8InSV+#`8;R-FU1tooW-{k6K8V9pHfVm%o#t+ zF+88*_v6Zt2b~gte}wfv@_7N+2MEEiuFa9p6M+9A7}m{(&$y2lf?-{5I6MK?pCNb{ z{M{__8Twug!SLK`I9!4Ja0uQB{%#g$<(bo;t%hJ~Gh^+SV(N3o`d^C4Cpq&^DJGxi z%>SjBVw$t~mSW;e&iGS`iIX|wXDOZ&@+ZjWSzq+5gy7BL`4st#?T28PcMP8|gZV!M z(NIKLk@ua~9uHOq?;C48g?7obj_1Pq4oQQWIj-*bv+u z@+Zh=IBz^I1ixW_I|Sz5DfdKhR?XS5P~18|L(@f@gaCd z=WsJW3o&DS2&Oh6Csl916jPs}PQCx7n0x|#s{5xDlh5%pIRBSoiYe5o$F~#{XP{1< zKc$#B33clHEX8xs{M-%p0YdO*G(W?c;r0-`9?j2>LLMsw!}%yPKf~{!WFfd0&Cl<` zb3h1&yrkhXoY}^_t@Gyjxg z@;UzYkMn;irkLg|zNMHrgJ;eie@ZcNGH3iO#gl2xjCs}&`~$6@@$c_K@RqcGo(y@` z5Da+}!)MGxgy2nS{fv3;5ImID&zMIK!P9B|JP^il2p&l5XUzSFU}`gC?U!QebH@5# zipeK<{>u5M6qC>K%(?S_DW;g_EWV|fIAi{1GXxVSbH>k7`~u}SZio3Z1jG3vv);hJ zKMlbHDZg;r^g%@)GG~ewZnEITt{+D9%NzVLJipl4g^LPF)#T3(=#kUj_XE5jQ_*06BlbG{&{4B*c z(f%x)gUdp2PW!X?`vW2PVA`LB{AU(|aeoBoXUv0!;O(GY+Mmrs@Icz1#d$6SuM6`g z?$5&clRN}Zq5atvV4e=a)Mm!oFU8d7jP<`1lTUC@*7>Itlh1K~*7?5_Q%o_Z?c!UC zi8JOmD?%`FGH3iO#eL}f%nPuN4#D%$`59clh2V#P|CoQ?3V0NPUxRUre8xOz2p$XL z3i-Sl@G}H|5B4LW(KUIL+~Hd?fIGQVI3WUsm+YFUy7;EX6+w>$tOAU zPbns!xkm{3*r6$(-@C6#w&uJ>QtZ^Lq$h5%`b!I($wI!EG@A zBcIoSc`gLw_X_eEbDtsjN%&qtKI1wx1Y>?4`HcJt!GBM;=NmB(5rVIz^NkNeo+AWP znf~n7j^C6ggV%Fv%n0$_B8lC@3F~u}z@h!!~nVj*b6cZT|k0nXIb`!gGS*xE22 z^QmSX5rU0Ra^|1eVB_!m9R)){$UE6Sn&GS|JJW}a(+>Gk^KeXmh-pmb%c1$%VUWafy)~EI}*1oAv?VEC5pZcG({%5TJt{nSs z%6FN*RR1HMKBKn5gcsYN9r#`U;hzkv4Zr59Y{6~6>wg=R>*Q85GUYqm7o;k0>W5MgJvc@6R#UVz2 zPOM;D3ggA=9JSGi>Ip+;R4*H_dqYfl?0B7}wz{;MKukY5=LqNjrugzY_kVk3b%{?W zSEfvD-*wM?Pu5rUY|H=V#jT%{~3NpZtLR%`6ovoa$E9$j$?$|lK*pz z5x1rI=4^Z!TZ(Uv9N@OZpBy>HZHYfQa*W#&KXb-UV@v$Z89$9J=k5L7tCh8Z!yEtg zNCStz9zS<=y-$bLCf_+C^YNC~*>sPCs;%emU%U98w_V>1w>c+yoyiwpUp)x;eD_`LTCx(~nnozBSzDoaA+uUF_}ZnS*Ck`|mWs#m;b>bCTD2ru)~` z<$u4jy1=q^ZWwNJPVzbj^_@{&1?H=P<60f}47WKCc^$&-Sf6u`*QfR~>;tdQxyNm( z{~3NpZp*pHZOK15`jFdl?r~f4e~vNYww!z1mg1Wu2e_?|x5S?uImT@{Z;78d!d{l}F3)av8F=f$S}?LNEVHs>U-^Wa5)R~PuXckR&47IVHe+~%C*b!P0}z1H)X8P)wB ztH;i8n{$%a+41C_wR!%$vf6)0#c{)Mn{$%ax$utOwe?0%uKYb?Gsiu{ZO%hphj2UA z=iKAGV~n^h=N`AE_~ys~Zp*nx zyvmVRyd7@KIZXV_89xpGc{`lLP|xrg%Gx=H;r$Gsp)B*2bAG~SFnorx%va9&2|hA> zhBEir4YxTbc^!yB4fzcBoo@}dIVX7?h_T@_+;_1v+~%C*b$~;L&v4&y!*H8(lGg!V z8a~5)$34Ss&O=^@a68uL+~f7B{S5oS>vQgLTk3y?pOM>g?r~f4PmVt1ww!z1mi(V% zjJPf59>qP!xbt?nE$1HbDo0-V+Tk1~e&&pyW-Rb_IEP^#H|q@;6YZSC@Eu^*8!)yq zUpeP6e8-se28_APSI+qf-(fXeZ@~D@eC3><@Euvh^#;rz&bNl!oRho`dKU`hU*QO|8Rb+bDMLL*MW6I4c8kmzh=A+=OM2{xEhz za1IkcbH-0I7I-`Cd9cE8J6l&*7;b0llM2J_Y@V+$+|I^Jh2eHKb}9_F!}`90&!PC9 z3{QmTfeJpiVjmfv2(Ks7^DOq?VeJ1zdY;ApJBpC8~EvWCy&u)fZG<$QjCXVe-#kHh-ijU6+$@Hv6kfoI?vK99rm zfg77ogg>hE$1ADTtgLecaT45_my)FLoTC+`8~*OwEN0Ahaq=X z!(1QaKiYleoS%?it6@G6ax?9|a?Vf4<<&4Zh&eo7&N<2JKz^|1a!I@n=OM2{xE*X< z`%S#1_A~4Qug|$hpDV-9#W~DvIrqqKCRgffhjW3bx{?+sr&?7ODndxvqjKf@ClZYXCQt}xura6>ucaE0M^h8xNmhbs)X zGu%+lI9y@4o#BRZ#?K1F?F=`RLoU0fVT}j5YRr$<`OM1+w|A|>`N_EF+BY07ur>T= z9CrOTeD<}&xaa(1`0Q(kaoG9a@Y&Z67`ipDUchzH&AXS2>4$3b~4x3k9+>y@}Ups7Gb-Y48_xH8K=4Z!Gu1dMyY(~XN!_zK=0M$ZcS9Y{VP1!=pK(9Ht+5>sas6E7 zb=Z2ip$_LQTLU{=d`@@m8-DWoZ2j!|kI(F`|G0i`ux0CK=Qp!w!rS58X6s%T7qchh zYlp3SUEFc~T=liX*1e8bxPGqq+F|Qw$4^{8_xH8Ko{{-;afRiPs+_~Va+XJ`at`~- zSsuxKcFZqTedR2_ROKAzxWC@3@4y zR>#8%-sg2#KEI(3=Pk8w@}|5#=PIvH{Wp1EZp*pKZCMV##%(!2xh?r0_pPejmh+t3 zvb?>EJLdmg98EjimiU8td&euoNnbm}Pu#J4>pr{TEU!cRgJv%A@toJ8{YNt&`*_al(Eg_R-uCgF*P;DW z+TiKZ^!F%u5zAJ|4qJ)+j6dQTk=nib1JvxT;;ape>_)!`zv^^ z!`S+GPVvQa1yyd#`N?gGKe(^zcxAZF+u^pvPdsDb^6-Y+zIJde;_~F2+jPzW&wy1q zhj}@joxrm(4Rtt&c^x`mf#<$zybk9uuS4fI@NA4(i@34CIn3+O`4F>~+?I2d+me6q z+*gg;a;|b)@;{#Y!u&p-yEC?&tK632i|4+o+?Ml`+Y*29+)I_)a(;4K;wPT_a{En& z+q@lai_eN~KZwqr;rYfY=Q-yvuY=FAbVjtw>u?V9I_&IXjo0BE=5^TFMciv~XCR%Q z4bOQUI{Rmy`+Yp;b?AJc$p`p&&g)Q)+2rSZJm+-?oBXkl=hS|N`3zp4bCvU)`j6)u zYuuJ|mD{p2iZyP_xyo(H|9D0b^ZR&q6wkyu|2OfR;)~}StK61zmGhkVgJ%@0+?Ml` z+Y&$Vd}D>%a-MTrAD^Mz?R8>16X_gp)yHRE2m0yGLc2cWd1?1~@w~LzYjI-%{NT<@ z%jQR==?eIxz26QNnQuWZ${_Oy}adhU~b9i{5kTu&TWc|o1g1-VE)PI{5kTu z&TY;~UI*s4jLx4U-|F1voaA+2{>9*)V^DXVEd*%=N`AE{=0Pu z_TSk0cuPKX>k#yhvGwtm{O{&x^sTY=@s{H2)*%>QW9#EB@yD%0kUz%O$6Mm3S%+|2 z&RbYNyYnOs9ESBtM(59QT~X&Y=OnKK>z|CypW_;-&TY;~UI*4!nOht4I-Iw>4y@lY zI)9F9k3!z^I==?dZA?w`coaA+2{h87Eb6lg=xy?Dr>%jUpqx0vu2Cj3P^On~k zY@QQ+yruTtb0W5H>ic+0{ddoa*neZ|<1P8eJtv}njIEEiU-1Nn!X&Y$CRU!B{Wx4aHvJb&)mZ{jVr@A7!qzNzoyE%o2!@v#5K z*2i1&51v2AJRbVT*!p-&{&#si^uMv?+~c+sUp#+~`74aCvE|$&{L!)GYN97~h(S*0&oM_@=QigguLJp2!)LhfVrO#HoRho`fGj> zc815;kG{Bl7I00 zIr_rz8U4e#$8E{~W`Bg+a_&)lUH-YwVQ$MgO#E^AXXJ_DKW~R~nE2`P&vg#-cKCXm zVRv5FtWRLh$DE$|TR9jnn6EZ-KErt4758P#*kKsYyP9$=V;Il7ns%@ahTVBxv!}`S z?kD=rrSSC?!|uGU>pwmVxc=js%Jtu2cV5@^AICLf?7zX(e}}RE#+Lf;usg5o`j6*z z&G|;?Kc3MwXAc;jNbT3KeQL9YZSuJSa<%3=5#~1BgQ(9fyqwP!kP9~JJ(xRjkE1@f z@NzysK(0B*^&ZTxxVKfGTX;F2A0U^V)A@hg+p5nkd`{qXVE-|v^Z#z_;Q4>tld8`f zybkPd=5+qQ%Ioksf!Bfjeop8AtGo`M2Y4OA=3D_E`@BB2Z_X0%`h4tjTk1cazpZjx zKK8jS`N!?gqJNAnAN%Bgw?B)1HuDd+-J~Oe1hK*yd6IFi9c?C*32jP9mLz= z{O6qawZl0KU*XP`${=4&ybq;e|&OP!^j(JdDJDhvue|NqS{cOepZ-;Y_;_l8jVjRs_;O%hk z5wG0&Mw3&*Igq!*In34-j)!I}@OC(d8OC$wbq+J^E$19&7|);Axy>-1Gp}=)VQ)F- zD#LjGyv}Wg@tk>`!wh@NIX@Z3^XGMLGi-iKMceb|xL;N0GvxGhS56qupEuOu{G>Jw zZy9#&b6dlI&S8dKKbzVipBN4^?EGNH0&jzT$$8G%kAU8iZl(Tsl_kkRT+j%*gdmHL-4)Z!}e$IFu&U0!X=V$!8Hn*;D z?IS-MxXtEO*MIZ(6ucciF4+9+{Dz!#elUL@$N9|WXBQXbB>sJno1YunVe_+#yWyd) z9X3BZUYWnA@U_F{XU9)`2E@M)!gYfATRF~WwtjZck~Pe^vUPICIqWOn>F&3)h2U@8 zRvB_o#yRXOXY1#TbJ$nT*2x*?u&&S758*3S)fIEQ&1wtmLFBDW54JjCe*BG&I=6l0EYF{D4*SYk{y*a!=H)E6k9#35kLP@A zexrleq1?F1$@zHB>#*E@?&CSH!*ctMOXjyeIEQ&1!nhCRxQb`g9X7mWIeh%>8nV?izm|$>skW+QGS)&Y!y+xZyV2hsEDeGJHl}`^woqtow}a z_rcuR1N`kTxA$s3v-=G(&S74M?Y$a5y5A7v9OiY{-mCF7?cusO8lLkyZ11(94(Bkh z!}ebBcaYpZm*XM+ody0rnA@Lq7|#hb)Zx6P_RV(!+s}3Fo9_o+pY6}$Z;QEe1+M>1 zJZJl}_`7!QT!Hfs?y)x5lK=5+fSG^kT!Hhy;Wg(u+n;suHMX3eoZG}7+*ftH!hKcz zeK5B_>-b}STa5UL`!$ZAhTFb&*!da$+bsC|jqaRG1BZDzoqxdd=M8l@w|O0QHU@L< zg*@kV*x4BKokwSEoS$pBrr>qh*_ehpoWr~hI~(I-ZSvEc!@LeV8{@cS^2eORybfVJ z$K|+PL2h&2vhy=Jug|&4>$CGS_}h=}+?VUWSvzoBc76tbyV9Nea{e*v4$gCSe#ZG0 z&wV-nH}Ra}i)Xj+cSqg1FBe}tKhVH)c76tb+tZ!|x!xXsQt;_sunvy1pUrFH&u4)Z$fe4}}0aKFLJIn3*@vy0}Lgw8-Z zKjZmx^Q?}!Xv}%Avx^ONIEQ&1c6QOlx{A+^oWr~hJG9(Q<^xWcKtE&;<4ZypwH;y zRk!uUk^F;ap`Cw>Esq7aCI2`59kz_vsG0@6+fv(|?afzu|qK z?nU>DwG@5LeV?|m!}eRKovwNil^5&I&i%}NpO#{K=`2K@UJB_*z#n-QGT>F5n06!M#7Ap7YHoEWAqv*a*Pon!i-9h(#8slsF?a@7` z+@~?FXkV;tT>DUbo3)KA+GBi+G{zOni?xkwABu0Yw(-RG9c`*a)KFV?dDFHlFytgH63g zeLnaG|MiD^`0qM;y*9nRmtL<*uOFw^%hBr>>Gcxy`aOERAie&EUe8Uh|De~JUJs_% zo6+k*^m-t@?n|$CHm_%OcBj{S)BO%u8{)r%==CUieUy3KO|;PKVRXN(zpZ~7z3xH$ z_G_pQ?}@SZ=@z>0(`|I$r$^C!pPoebeY%70`?P?*oBn$=-YdI$(fwj=`Q3x~-K;II zvHccmr>h=BHO3Y1`*bVaFV;4m z_`ZWpy+$o4zJ6`vD!^8N9~*UNXD5`kRDIgk$GDTHMWcK^=aE~3)weo+pj^!9^>2fwY6_0`(kb5DJZ^O^^B^0{`YHm z5Afd%^r1($P`OXH(fwj=$L$OgXMCUL*Envmyja`ui~Z}M_xV?McK!%u7~f)TKNrRo z?R~lz-7nU5{LV0O#&){Cw&NDtZ=rU&>OoZQ)2(#BSljsG`wlks8g&Q7*RO3{(Psj# zM%~%@Np)st4aQ%ww)NY{u34j<9lymI?QLBB+P(+&tNFtAZG4NhwZXWetxxx&`^_5L zx8t{1+jd*XzFFJ;;kd>AHEV0%O7_Lt#ooKeT+JHei{(CT=Vi2O zBl|{e$Llm2w?#TPb~espGkYt)k{zJ6`vItl#*SEKF(U)%9ptZn@^vMbg$ zzLO}vMH=IY<;B{@75mje@AI#=HlpU!wtpB`wD;*=biY{J_)enuHftMKY`=xt`B$U= z?6@t~wqLDeSFCM3@qIDAUG*4>uV34^j)8s%xSF*cw_|AhHfuX>(XNf`8?}w^7>aL^ z#?OxB#oERd+wY+E|JAcPABHlFZ?U$Y2jhzNKHZD%7i$~eF%;isZR3jVw@^D>^&l$u z=~lX5tZiKJeFvL*jd~Qt*RO3{N1>nKYSuQsqbR=3+Qt>_+Q`09+xU*6_!eo5E0z~) z8&_<zZ=rU&YK$x1_vu!; zU#x9B@qGuIdX0J{#n-QGTt}jR;A+&JotK%o`n0XzMs~&8#&;yew@71LvAkH@xMIIL z=zadxv!H(%SD&{1!?>coPxqqx#oESqB*nK`+qh!;E!57x8vSPH=VER9)k=27+Qt*# z7vtMiw^4kH^{md}=pXQ{U*q`2`$gK0S&Xayvhi)B_!eo5E0#BF+piAlpHE|aP5(W* z2bDK#+wWfBH|&40w()JF_%>@BSF~@TcK+42UxVoVeY%zIH*4&djjK<$Qhfc|j@wq~ zpMa}b+xfZG#24>(eQkY%c5P(esBL^(DZY(5g7z@3K5hHcLG3o{nVtK=JyG*%Ymei$ z73wu>d|!;KPotfUuV34^VmlbuB0Y%8eY%zI7i$||eE-3wUZZZI`1-YtYYX}b``Dmo z!PvFqwpiQxZDd!hZG2lOzC{|xEtVH+J1=9uI_Q1=)!09buTR_lVO-JPr+d-;Vr}Ew zLUC@^&^FmOYuhgzx7g2SZTr`2?D#F#wqG68zh*tt_8Z2p>3@^9_C3JAc)wZOe&hJX&(W;W4&&?7 z)~#jH^%E`fX&}tkDkR z>(gj&$8E7jI~=z@{fD_PYCdi4dO+Nj|OAhK`P z*1nbOi?toMg2r!Gjr*f*V2}HwsBwQ3HSUk1#{E&$xIc;-_eW9V{wQkPA4QG(qo{Fz z6gBRTqQ?DE)VM#28uv$0!SovUNAdL_dX4*|__{B>#{JPY;Bj|)jr*f`ANNO5 zY1H6@w-@K{h4NM z=hw(@tmo749_D_L#`m}UF4n)A`=aL4)*g9{_RSjmB@M63bYJ5~`#pvA8eiM*C-hs3 zsmC?GFV0&&ZT;O!cE#HA8{ZedpStQcimzYWxVBMzn>Ef~z!ekcu3AGmlvRBi>(4at zE!JoUpWWCOX|%WNj$%!7vv-fs+V=pzpnbE(_s979G}=Wbp2gaJ?iOQ@aqapV?J>S( z8o!@x|BAJZE4G92?WzUEw^+~U?Cg(od%3Q`cO2Gh*1!!DU!O)h9JfA=cJ%#JsL>AN z>(d?PzNq=MwZpR=*iN&y{q6;R!_U#I(GJI}Pg}bdvTxSbZV=fQYmBe$U$e&cZCt%t zSdOuWnN<9E-k z=6=`LIBtQLIERsa<7*nf;KL46&uZ+6do7UH=wrO_Ul(o0EtGMM)$p|tc7ASy{pDVs z*L|TJ@1w^0jj!!|jPKuK?st7n;}`4)kv(c`&%UPd3uUcjj~d&vuW8&u{lVsb@E8AEVvIYhdRX??J$l$ zjqhvYTCC9y=VzZrdmGPUjdmEvGL3P>`$gLJ595mcE7F50zJ6`T>tGXSSPwSn&dy^g zuEiSb+woeg(cZ?lSX+CHE7~_}w72ms*0bQgjc>6=dmGmU{ZG4M0+S&12tkK@awOC{SFup!*?a|hM*|=i=>=sSfjm-Z?Q&u8{cA$_R4(!7Heydu|@l0ZR3gk!}xa9gW%Z#$FE=8_zt4@ zHtNpK?J2&+8r!www^*aSjc>8G_83>RZ`NpU<6Ep}!F?OwVvY7TzQr2f*T%P4qrHu9 zu||6v-(rpSHonE$+GAYNzF0>lu7jW-7~igXONwu??(7_3;##Kd_#HrTZq!0-3Gdkk z@hR5Wu8nW8MmrnVVvY7TzQuYL+_&*9)@X0zTdeW@ZG4M0+S~XRYx}ud;63p3H*2)F z@%3wrtLTdX@fYZTvNjeWM`vrOZ-!~4bB`mcrj*sQHz&^OH&_Rspq zudRP-V2}Q3)Yzu=k5Av0E(ru#QuGoFi3ijEAp47r#hs}Xy+QUC%ZW$Q1w{+U7O}a| z;;wXgkjslc;?Z| zAjpAY2QjypL#zpMO|iDPDcxKyD!$bd(?McBF^^aWfZRjuEjEQz^GP625~qt5#Ij-^ko$;M zF+gl0P6K(GI8&@FRuub#++Q3dwh>#1Hjr)N9I?7sMH~$BU~!n(UTiJS26?u)K&&O! z5Ql?2TpT5K65EOML7p!z73+$A;%JaZi@{=XF+lDt{;PKs7mJO=dg3^c$BE;`5#msB z8_3(lo#G;Ku9yUJl6XNJBaRezfxJuHD=rfkiswK+Cteam#IfQ&koSoP#V%qiIa2(f zFA*<_6U9*R5XgtbBVtdno45kx72+y!syIQ60XarID)tq7iEBV!Bd!y}#VKMu$noL{ zae&xQTo3Ykag!J!&Jd4-d|b4PL&SmNW{@|FQQ|ytmY4`~qIg<7CdP{IL4GfO5;urz z#Ty{s5O0a6!~`(|*ohwBURvUnbnEHA^A$kE~f@ue6I*EiyF zv5kC1{HUi0Eysz6#kXP{TtA4b#g$?z$f;tQQ1TzKzEpC3S(RUj&&84;mz2F^Dy8fX zvcKF!ekZ;by+QVt%gI;8wz8Z2NyoB9{wV${mIt}KTuHtzUK4YIoKwy%e-YC~ACP_I zYVvLIrkEGxyt0ScFPXKv>JW1B%2J$M9SIHaXGID8oGRTwV zX>wCpk=KE|PTnF{kju)`L7pz#4QnIO-U=g4{FT=Ec*hseX^ z8ggZMHpsK(1@a7es+<6Ff_z-wDzBGsfqYATAkUJ+atAp|{!ia5-;?Lb z5waa*yL?(6E)SKrgS=hdDKC=e%1Iz6$rt3&@<@3%$h+me@-lg$d=BJu@+EnkJXYQh z@_zZCyi#5wUj+H0oGOo(L*;0YqvaTRt-M^m0`e94hCD@{D93^vE62+l<<)W;$Z7H& z`LcXo%IIad(&!=ifc#oM1lPCnH91Ab(Q9zc6+I#!mj9KH!1aTCQ@$$ah~9*&d-SLr zCx4WW!u6AUSH3RiiQa{4f#^y3nEXXP3D^JRhw^PXU-Thdi$s}xO8zc0xc-v2$(`iK z@^}5dTqt^0=JId(EL@%PE_sLi1mq|3Q#n~aBmV*Uk5tip@*erQybrD~<-$>qXxnIE zxOR&EkiW@(Ap1q@Mjy!?1bn+8%G18@8x%LMUX2-D@F50 z-J;DwZXRtD&5+aODj-*hR*UA3=8m=kxmC1%^sD??t^sn5Xsu|As3kfb?Z4j*!4Fx$gIx$)zT0Ghf4WJ^}ej^jY*mG%5NAOK_#?!RWr|>*zta zzKcdi1LdpH4E!NF-H$lD` zy&XLfjgNi?`E&GpbW?Og^e)JEqYt7idOZ3KfqqN&kbAm>u^ zsGp+mqm@CftkzI(MQ=piL3UU3tN%qaqSZmJuKKC>qIaSNKrWybR)0pnMr(mwORc9q zir$YF0lA1;T+NF9h}H$UuG&a-L?1^zLH1NjsYuO?HUzn$s;MucPot$lF0GbPi4v*; zvZ6Ls-$Y+V%Ys~1t)O0sww80K=~}Ce)dp&9H3Z}kb)s5AEv9w@xtrQkRn_|H1du1F zQ&lguq}mJQUTR;piR!OT0eOlVu9j21)qWuNQwOMSYD>Af`d+uF)7469d37Mj1J$8w zZZ)SG0CIrZTCJw~s6#*=qK;HO)VyjNklU#3)S7Blbp*&G)Uj$oHJ{oZB zTRor#scqFoATLsvs^ipA>VA;-tB2LjY6o>0$jj6f>UcF+jRrYdjZ?d;UDTBzuTK3(`+CrYCzSF0vC)L4f ze|0O!Th$%vDs{Pf738aGntD`?QQw37Uj3x5Q&+3kLB6iuQctMyY6i#|>VN7cb-j8U zAGSe>oTRP7+!)g*P78l^r0`H}imov+SOPlJ3~ zJ*Vzdcd8DM9qLPUvARG#5Au2SqIyW(tG)pFh5A;FRF|kJAg8ET)FbLa^$o~x)DP-& z^&hpU{v56)^$Y4*^^bZ1E}_3xpQ$B4E}?ttm(*k>K}xOlf7Ms27sy_Ec|BFVtYVO{ z?xufK->Kz5E~i)0Z>ZPQ93bb=bL(H!bkzrBAHAA>N4=@$0XdKEp?_CDt5rd+s@K#X zsCU(TAm`Hy>P+n{|4@JE-&9}yiTY421acw0n0`j(>QD6yTr<@gdS!i(UIVVf_58ZK z-U{SadZ6y7SJ#JuJWL;>7uE~tZ9#6U2kF1mu5xYtmtIRBrF-f{^bR0*(7Wha>Tk6! z$aVGldTG75-WlZ1dJi4xPPGBZ4Rn9KtX@j*4sv(Bk507G6_6F(qF2<*=)FPit@qb+ z>QrwGa$~)jUPZ561a8tWVPi>V5Tf zAg|Lm>n-%A`gD+|>o$F;K0x0D@+N(o-dYdPXM#LapRJG7hv-otN9nuuc6u9q4#;!# z`TAIWguWBxo%(*gquyR$0P+HTv0g{-E(hzG`e=Qx-c9eMF9CUpzFcpp*V98l4$;H( zUV2wO668pIwXW)o^a&tO&?o5!^j*3GWQYDrU#c(C&x3qkzo?JXd&&p(EPbE;LSLyb z(^EiB(XZ;`^-w(;?I7FrBz=#*U4I1fBmJ4a zP@kut2KlspPCuz1)APqq!nI)hp?*jA1=%-VH_r4^dSQ?Y$BV|F=nwSTAlHsJjGxiD zUJT@7@e=Xp`eVI5$o1oD{DOW~F9~wVxL5qO{#5q|*+1SSeo0T(y+QVlmx~|Ld&_RI zh`-b=@oV~Jy*$X}O0kXyuC#%shY#|MEt zC_X%%FYX?14RY&vVB9ZWJw6QNVev8XLh%Ceb|ANl2gU2fYsE)_JSrX%FCH%v?+9|o zc;|Sdc%67K$ieXm@ltWmcvq0S#=FP0c!PKt$YJp*@iOt!@g5-ei1&^+jVtjK!&2jj8vp7Cz+6(FyOuZmBNkB`TI91~B7 z_l@_8uK{^Yd|f;|J~-hBe@%YgA!1!j6H^;Zd zTg3z7vp}8|pB*0=9}viK#CFU7CKDeu;mGR|2_GvPSZD{AS!8WcOtLJj5NR`CNf8#IX-XMD?D<+F23ne>& z+$q^DnHm2TuLp9yWP@a>WYJ_-kh>;(B_f#>Zv=9qq>?O?ERpO9a?fPHL?=;F16fNp zPF6^ICHsKfCpj?bmL$ohAU91mPgYKrOZEr3e{yItcQR)(0OWvV>tyw$PjWEGgOekZ z9?87PHXyf2woBGZR!t5Ed3bVcvS2b_vOUP{lO2;k;{D}1NgVf0j!q6qT9cbW-kjW# zY?*A4i~u!J!Pfbow4oLP+ZUA{ha%-|#vPm)=?0paWPES(Wpa6PN%Attmy_3$Vabr>VUQ0ek0hTZA0>;YpTV_s`dspK z(wRI5SCoF0bRCqz@*0$#0WR{YBC{eKnbqq#)CDu5?T?I{9xh z2Cg5H*OOP0In&qS>Yk2I#wI@|x;4nH z)9uq=lb@0`K(3Lll`fR_NVfyIUAj~HNAkaw#P^ z-7sA$T{PVlveS zI!79(n}Xal9gu#Xe3z^Ua>aDzbe^_eFN2J@PTc+oNJU6{4?VGNa9trZu^q6#qbYOZR$P3fU(zVky(_=v%n+{2L zNe88ug1j`nGF?AiCmjlMXnI1rN4j%*1;{JXYtswTv(wQaN2iO3qte4u1yYH-(@WCx z(}l$)aE(g`r$?vvfV?M7#O3M5>DcsgxE@P~rN^bI7zWq<>DB4TbOOi;=~L-R>GA0U zARkEQ6xXL$rB9~U!t~Mo|&GWb{A*DwSYJ%-9NoG eJqWJb({s|cbbfITTo0#*r3a^XfV?A(#Qy^XTs8y% literal 0 HcmV?d00001 diff --git a/resources/uvsphere.gltf b/resources/uvsphere.gltf new file mode 100644 index 0000000..edf10c7 --- /dev/null +++ b/resources/uvsphere.gltf @@ -0,0 +1,104 @@ +{ + "asset":{ + "generator":"Khronos glTF Blender I/O v4.4.56", + "version":"2.0" + }, + "scene":0, + "scenes":[ + { + "name":"Scene", + "nodes":[ + 0 + ] + } + ], + "nodes":[ + { + "mesh":0, + "name":"Sphere" + } + ], + "meshes":[ + { + "name":"Sphere", + "primitives":[ + { + "attributes":{ + "POSITION":0, + "NORMAL":1, + "TEXCOORD_0":2 + }, + "indices":3 + } + ] + } + ], + "accessors":[ + { + "bufferView":0, + "componentType":5126, + "count":1984, + "max":[ + 0.9999997019767761, + 1, + 0.9999993443489075 + ], + "min":[ + -0.9999990463256836, + -1, + -1 + ], + "type":"VEC3" + }, + { + "bufferView":1, + "componentType":5126, + "count":1984, + "type":"VEC3" + }, + { + "bufferView":2, + "componentType":5126, + "count":1984, + "type":"VEC2" + }, + { + "bufferView":3, + "componentType":5123, + "count":2880, + "type":"SCALAR" + } + ], + "bufferViews":[ + { + "buffer":0, + "byteLength":23808, + "byteOffset":0, + "target":34962 + }, + { + "buffer":0, + "byteLength":23808, + "byteOffset":23808, + "target":34962 + }, + { + "buffer":0, + "byteLength":15872, + "byteOffset":47616, + "target":34962 + }, + { + "buffer":0, + "byteLength":5760, + "byteOffset":63488, + "target":34963 + } + ], + "buffers":[ + { + "byteLength":69248, + "uri":"uvsphere.bin" + } + ] +} diff --git a/resources/uvsphere2.bin b/resources/uvsphere2.bin new file mode 100644 index 0000000000000000000000000000000000000000..c71a8bedfad77adf2c623fc4d5a0e310ddbd1991 GIT binary patch literal 70088 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 WQo65ZAUT5y)a+_nrAcblPyIjlAF==d literal 0 HcmV?d00001 diff --git a/resources/uvsphere2.gltf b/resources/uvsphere2.gltf new file mode 100644 index 0000000..6657f6e --- /dev/null +++ b/resources/uvsphere2.gltf @@ -0,0 +1,190 @@ +{ + "asset":{ + "generator":"Khronos glTF Blender I/O v4.4.56", + "version":"2.0" + }, + "scene":0, + "scenes":[ + { + "name":"Scene", + "nodes":[ + 0, + 1 + ] + } + ], + "nodes":[ + { + "mesh":0, + "name":"Sphere", + "translation":[ + 0, + 0, + -1.0871706008911133 + ] + }, + { + "mesh":1, + "name":"Cube", + "translation":[ + 0, + 0, + 1.0190757513046265 + ] + } + ], + "meshes":[ + { + "name":"Sphere", + "primitives":[ + { + "attributes":{ + "POSITION":0, + "NORMAL":1, + "TEXCOORD_0":2 + }, + "indices":3 + } + ] + }, + { + "name":"Cube.001", + "primitives":[ + { + "attributes":{ + "POSITION":4, + "NORMAL":5, + "TEXCOORD_0":6 + }, + "indices":7 + } + ] + } + ], + "accessors":[ + { + "bufferView":0, + "componentType":5126, + "count":1984, + "max":[ + 0.9999997019767761, + 1, + 0.9999993443489075 + ], + "min":[ + -0.9999990463256836, + -1, + -1 + ], + "type":"VEC3" + }, + { + "bufferView":1, + "componentType":5126, + "count":1984, + "type":"VEC3" + }, + { + "bufferView":2, + "componentType":5126, + "count":1984, + "type":"VEC2" + }, + { + "bufferView":3, + "componentType":5123, + "count":2880, + "type":"SCALAR" + }, + { + "bufferView":4, + "componentType":5126, + "count":24, + "max":[ + 1, + 1, + 1 + ], + "min":[ + -1, + -1, + -1 + ], + "type":"VEC3" + }, + { + "bufferView":5, + "componentType":5126, + "count":24, + "type":"VEC3" + }, + { + "bufferView":6, + "componentType":5126, + "count":24, + "type":"VEC2" + }, + { + "bufferView":7, + "componentType":5123, + "count":36, + "type":"SCALAR" + } + ], + "bufferViews":[ + { + "buffer":0, + "byteLength":23808, + "byteOffset":0, + "target":34962 + }, + { + "buffer":0, + "byteLength":23808, + "byteOffset":23808, + "target":34962 + }, + { + "buffer":0, + "byteLength":15872, + "byteOffset":47616, + "target":34962 + }, + { + "buffer":0, + "byteLength":5760, + "byteOffset":63488, + "target":34963 + }, + { + "buffer":0, + "byteLength":288, + "byteOffset":69248, + "target":34962 + }, + { + "buffer":0, + "byteLength":288, + "byteOffset":69536, + "target":34962 + }, + { + "buffer":0, + "byteLength":192, + "byteOffset":69824, + "target":34962 + }, + { + "buffer":0, + "byteLength":72, + "byteOffset":70016, + "target":34963 + } + ], + "buffers":[ + { + "byteLength":70088, + "uri":"uvsphere2.bin" + } + ] +} diff --git a/src/camera.rs b/src/camera.rs new file mode 100644 index 0000000..53b3599 --- /dev/null +++ b/src/camera.rs @@ -0,0 +1,24 @@ +use glam::{Mat4, Vec3}; + +#[derive(Copy, Clone)] +pub struct Camera { + pub eye: Vec3, + pub center: Vec3, + pub up: Vec3, + pub fovy: f32, + pub aspect: f32, + pub znear: f32, + pub zfar: f32, +} + +impl Camera { + pub fn view(&self) -> Mat4 { + Mat4::look_at_rh(self.eye, self.center, self.up) + } + pub fn projection(&self) -> Mat4 { + Mat4::perspective_rh(self.fovy, self.aspect, self.znear, self.zfar) + } + pub fn view_proj(&self) -> Mat4 { + self.projection() * self.view() + } +} diff --git a/src/ecs.rs b/src/ecs.rs new file mode 100644 index 0000000..2fed082 --- /dev/null +++ b/src/ecs.rs @@ -0,0 +1,32 @@ +use glam::{Mat4, Quat, Vec3}; +use hecs::World; + +/// ------------ components ------------ +#[derive(Copy, Clone)] +pub struct Transform { + pub translation: Vec3, + pub rotation: Quat, + pub scale: Vec3, +} +impl Transform { + pub fn matrix(&self) -> Mat4 { + Mat4::from_scale_rotation_translation(self.scale, self.rotation, self.translation) + } +} + +#[derive(Clone)] +pub struct MeshHandle(pub usize); + +/// ------------ systems ------------ +pub fn rotation_system(world: &mut World, dt: f32) { + for (_, transform) in world.query_mut::<&mut Transform>() { + transform.rotation *= Quat::from_rotation_y(dt); + } +} + +/// Update the aspect ratio for all camera components in the world. +pub fn set_camera_aspect(world: &mut World, aspect: f32) { + for (_, cam) in world.query_mut::<&mut crate::camera::Camera>() { + cam.aspect = aspect; + } +} diff --git a/src/main.rs b/src/main.rs index b31ae36..7d0ac14 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,127 +1,86 @@ -#[macro_use] -extern crate glium; -use glium::Surface; -mod teapot; +mod camera; +mod ecs; +mod model; +mod render; -fn main() { +use anyhow::Result; +use camera::Camera; +use ecs::{rotation_system, MeshHandle, Transform}; +use glam::{Quat, Vec3}; +use glium::backend::glutin::SimpleWindowBuilder; +use render::{Renderer, GliumRenderer}; +use std::time::Instant; + +fn main() -> Result<()> { let event_loop = glium::winit::event_loop::EventLoop::builder() .build() - .expect("event loop building"); - let (window, display) = glium::backend::glutin::SimpleWindowBuilder::new() - .with_title("Glium tutorial #3") + .expect("create event-loop"); + + let (window, display) = SimpleWindowBuilder::new() + .with_title("fps") + .with_inner_size(1280, 720) .build(&event_loop); + let mut world = hecs::World::new(); - let positions = glium::VertexBuffer::new(&display, &teapot::VERTICES).unwrap(); - let normals = glium::VertexBuffer::new(&display, &teapot::NORMALS).unwrap(); - let indices = glium::IndexBuffer::new(&display, glium::index::PrimitiveType::TrianglesList, - &teapot::INDICES).unwrap(); + let mesh = model::load_gltf("resources/monkey-smooth.gltf", &display)?; + // let mesh = model::cube(&display)?; + let mut renderer = GliumRenderer::new(display)?; + let mesh_id = renderer.meshes.len(); + renderer.meshes.push(mesh); - let vertex_shader_src = r#" - #version 140 + world.spawn(( + Transform { + translation: Vec3::ZERO, + rotation: Quat::IDENTITY, + scale: Vec3::ONE, + }, + MeshHandle(mesh_id), + )); - in vec3 position; - in vec3 normal; + { + let (w, h): (u32, u32) = window.inner_size().into(); + world.spawn((Camera { + eye: Vec3::new(3.0, 2.0, 3.0), + center: Vec3::ZERO, + up: Vec3::Y, + fovy: 45_f32.to_radians(), + aspect: w as f32 / h as f32, + znear: 0.1, + zfar: 100.0, + },)); + } - out vec3 v_normal; + event_loop + .run(move |event, el| { + use glium::winit::event::{Event, WindowEvent}; - uniform mat4 matrix; - uniform mat4 perspective; - - void main() { - v_normal = transpose(inverse(mat3(matrix))) * normal; - gl_Position = perspective * matrix * vec4(position, 1.0); - } - "#; - let fragment_shader_src = r#" - #version 140 - - in vec3 v_normal; - out vec4 color; - uniform vec3 u_light; - - void main() { - float brightness = dot(normalize(v_normal), normalize(u_light)); - vec3 dark_color = vec3(0.6, 0.0, 0.0); - vec3 regular_color = vec3(1.0, 0.0, 0.0); - color = vec4(mix(dark_color, regular_color, brightness), 1.0); - } - "#; - let program = glium::Program::from_source(&display, vertex_shader_src, fragment_shader_src, None).unwrap(); - - let light = [-1.0, 0.4, 0.9f32]; - let mut t: f32 = 0.0; - #[allow(deprecated)] - event_loop.run(move |ev, window_target| { - match ev { - glium::winit::event::Event::WindowEvent { event, .. } => match event { - glium::winit::event::WindowEvent::CloseRequested => { - window_target.exit(); + match event { + Event::WindowEvent { event, .. } => match event { + WindowEvent::CloseRequested => el.exit(), + WindowEvent::Resized(sz) => { + ecs::set_camera_aspect(&mut world, sz.width as f32 / sz.height as f32); + } + WindowEvent::RedrawRequested => { + renderer.render(&world); + } + _ => {} }, - // We now need to render everyting in response to a RedrawRequested event due to the animation - glium::winit::event::WindowEvent::RedrawRequested => { - let mut target = display.draw(); - target.clear_color_and_depth((0.0, 0.0, 0.0, 1.0), 1.0); - t += 0.01; - let x = t.sin() * 0.5; - let y = t.cos() * 0.5; - - let perspective = { - let (width, height) = target.get_dimensions(); - let aspect_ratio = height as f32 / width as f32; - - let fov: f32 = 3.141592 / 3.0; - let zfar = 1024.0; - let znear = 0.1; - - let f = 1.0 / (fov / 2.0).tan(); - - [ - [f * aspect_ratio , 0.0, 0.0 , 0.0], - [ 0.0 , f , 0.0 , 0.0], - [ 0.0 , 0.0, (zfar+znear)/(zfar-znear) , 1.0], - [ 0.0 , 0.0, -(2.0*zfar*znear)/(zfar-znear), 0.0], - ] + Event::AboutToWait => { + // -- update logic -- + let now = Instant::now(); + static mut LAST: Option = None; + let dt = unsafe { // FIXME + let last = LAST.replace(now).unwrap_or(now); + (now - last).as_secs_f32() }; + rotation_system(&mut world, dt); - let uniforms = uniform! { - matrix: [ - [0.01, 0.0, 0.0, 0.0], - [0.0, 0.01, 0.0, 0.0], - [0.0, 0.0, 0.01, 0.0], - [x, y, 2.0, 1.0f32 ], - ], - u_light: light, - perspective: perspective - }; - - let params = glium::DrawParameters { - depth: glium::Depth { - test: glium::draw_parameters::DepthTest::IfLess, - write: true, - .. Default::default() - }, - .. Default::default() - }; - - target.draw((&positions, &normals), &indices, &program, &uniforms, - ¶ms).unwrap(); - target.finish().unwrap(); - }, - // Because glium doesn't know about windows we need to resize the display - // when the window's size has changed. - glium::winit::event::WindowEvent::Resized(window_size) => { - display.resize(window_size.into()); - }, - _ => (), - }, - // By requesting a redraw in response to a RedrawEventsCleared event we get continuous rendering. - // For applications that only change due to user input you could remove this handler. - glium::winit::event::Event::AboutToWait => { - window.request_redraw(); - }, - _ => (), - } - }) - .unwrap(); + // ask for next frame + window.request_redraw(); + } + _ => {} + } + }) + .map_err(Into::into) } diff --git a/src/model.rs b/src/model.rs new file mode 100644 index 0000000..815e2a2 --- /dev/null +++ b/src/model.rs @@ -0,0 +1,124 @@ +//! GPU-ready mesh loader for **glTF 2.0** +//! +//! Loads the first mesh/primitive found in a .gltf/.glb file. + +use anyhow::{Context, Result}; +use glium::{backend::Facade, implement_vertex, IndexBuffer, VertexBuffer}; +use glium::index::PrimitiveType; +use gltf::mesh::util::ReadIndices; +use std::{fmt::Debug, path::Path}; + +#[derive(Copy, Clone)] +pub struct Vertex { + pub position: [f32; 3], + pub normal: [f32; 3], +} +implement_vertex!(Vertex, position, normal); + +pub struct Mesh { + pub vbuf: VertexBuffer, + pub ibuf: IndexBuffer, +} + +/// Load a glTF 2.0 file from disk and upload the first primitive to the GPU. +pub fn load_gltf(path: P, facade: &F) -> Result +where + P: AsRef + Debug, // `gltf::import` wants Debug for diagnostics :contentReference[oaicite:3]{index=3} + F: Facade + ?Sized, +{ + // -- parse the asset & bring buffer blobs into memory -- + let (doc, buffers, _images) = + gltf::import(path.as_ref()).context("failed to import glTF file")?; // :contentReference[oaicite:4]{index=4} + + // -- grab the very first mesh / primitive -- + let mesh = doc.meshes().next().context("glTF has no meshes")?; + let primitive = mesh.primitives().next().context("mesh has no primitives")?; + + // -- read vertex and index streams using the util::Reader helper -- + let reader = primitive.reader(|buf| Some(&buffers[buf.index()].0)); // Reader pattern :contentReference[oaicite:5]{index=5} + + let positions : Vec<[f32; 3]> = reader + .read_positions() + .context("primitive is missing POSITION attribute")? // POSITION is mandatory :contentReference[oaicite:6]{index=6} + .collect(); + + let normals : Vec<[f32; 3]> = reader + .read_normals() + .context("primitive is missing NORMAL attribute")? + .collect(); + + let indices : Vec = reader + .read_indices() + .context("primitive has no indices")? + .into_u32() + .collect(); // ReadIndices enum :contentReference[oaicite:7]{index=7} + + // -- interleave into our engine's Vertex struct -- + let vertices: Vec = positions + .into_iter() + .zip(normals.into_iter()) + .map(|(p, n)| Vertex { position: p, normal: n }) + .collect(); + + // -- immutable GPU buffers (fast path in glium) -- + let vbuf = VertexBuffer::immutable(facade, &vertices)?; // Immutable VBO :contentReference[oaicite:8]{index=8} + let ibuf = IndexBuffer ::immutable(facade, PrimitiveType::TrianglesList, &indices)?; + + Ok(Mesh { vbuf, ibuf }) +} + +/// Create a unit cube (edge length = 2) with per-face normals. +pub fn cube(facade: &F) -> Result +where + F: Facade + ?Sized, +{ + // 24 unique vertices (4 per face) so that each face has a flat normal. + let vertices: [Vertex; 24] = [ + // Front (+Z) + Vertex { position: [-1.0, -1.0, 1.0], normal: [ 0.0, 0.0, 1.0] }, + Vertex { position: [ 1.0, -1.0, 1.0], normal: [ 0.0, 0.0, 1.0] }, + Vertex { position: [ 1.0, 1.0, 1.0], normal: [ 0.0, 0.0, 1.0] }, + Vertex { position: [-1.0, 1.0, 1.0], normal: [ 0.0, 0.0, 1.0] }, + + // Back (-Z) + Vertex { position: [ 1.0, -1.0, -1.0], normal: [ 0.0, 0.0, -1.0] }, + Vertex { position: [-1.0, -1.0, -1.0], normal: [ 0.0, 0.0, -1.0] }, + Vertex { position: [-1.0, 1.0, -1.0], normal: [ 0.0, 0.0, -1.0] }, + Vertex { position: [ 1.0, 1.0, -1.0], normal: [ 0.0, 0.0, -1.0] }, + + // Left (-X) + Vertex { position: [-1.0, -1.0, -1.0], normal: [-1.0, 0.0, 0.0] }, + Vertex { position: [-1.0, -1.0, 1.0], normal: [-1.0, 0.0, 0.0] }, + Vertex { position: [-1.0, 1.0, 1.0], normal: [-1.0, 0.0, 0.0] }, + Vertex { position: [-1.0, 1.0, -1.0], normal: [-1.0, 0.0, 0.0] }, + + // Right (+X) + Vertex { position: [ 1.0, -1.0, 1.0], normal: [ 1.0, 0.0, 0.0] }, + Vertex { position: [ 1.0, -1.0, -1.0], normal: [ 1.0, 0.0, 0.0] }, + Vertex { position: [ 1.0, 1.0, -1.0], normal: [ 1.0, 0.0, 0.0] }, + Vertex { position: [ 1.0, 1.0, 1.0], normal: [ 1.0, 0.0, 0.0] }, + + // Top (+Y) + Vertex { position: [-1.0, 1.0, 1.0], normal: [ 0.0, 1.0, 0.0] }, + Vertex { position: [ 1.0, 1.0, 1.0], normal: [ 0.0, 1.0, 0.0] }, + Vertex { position: [ 1.0, 1.0, -1.0], normal: [ 0.0, 1.0, 0.0] }, + Vertex { position: [-1.0, 1.0, -1.0], normal: [ 0.0, 1.0, 0.0] }, + + // Bottom (-Y) + Vertex { position: [-1.0, -1.0, -1.0], normal: [ 0.0, -1.0, 0.0] }, + Vertex { position: [ 1.0, -1.0, -1.0], normal: [ 0.0, -1.0, 0.0] }, + Vertex { position: [ 1.0, -1.0, 1.0], normal: [ 0.0, -1.0, 0.0] }, + Vertex { position: [-1.0, -1.0, 1.0], normal: [ 0.0, -1.0, 0.0] }, + ]; + + let mut indices: Vec = Vec::with_capacity(36); + for face in 0..6 { + let o = (face * 4) as u32; + indices.extend_from_slice(&[o, o + 1, o + 2, o, o + 2, o + 3]); + } + + let vbuf = VertexBuffer::immutable(facade, &vertices)?; + let ibuf = IndexBuffer::immutable(facade, PrimitiveType::TrianglesList, &indices)?; + + Ok(Mesh { vbuf, ibuf }) +} diff --git a/src/render.rs b/src/render.rs new file mode 100644 index 0000000..e6319b4 --- /dev/null +++ b/src/render.rs @@ -0,0 +1,95 @@ +use crate::camera::Camera; +use crate::ecs::{MeshHandle, Transform}; +use crate::model::Mesh; +use glium::{uniform, Program, Surface}; +use glam::Vec3; +use hecs::World; +use glium::glutin::surface::WindowSurface; + +/// Generic rendering backend trait. +pub trait Renderer { + /// Render a single frame for the given `World`. + fn render(&mut self, world: &World); +} + +/// Concrete OpenGL (glium) renderer implementing `Renderer`. +pub struct GliumRenderer { + display: glium::Display, + program: Program, + pub meshes: Vec, + params: glium::DrawParameters<'static>, +} + +impl GliumRenderer { + /// Create a new OpenGL renderer consuming the provided `display`. + pub fn new(display: glium::Display) -> anyhow::Result { + const VERT: &str = r#" + #version 330 core + in vec3 position; + in vec3 normal; + uniform mat4 model; + uniform mat4 view; + uniform mat4 projection; + uniform vec3 light_dir; + out vec3 v_color; + void main() { + vec3 n = normalize(mat3(model) * normal); + float diff = max(dot(n, -light_dir), 0.0); + vec3 base = vec3(0.6, 0.6, 0.8); + v_color = base * diff + 0.1; + gl_Position = projection * view * model * vec4(position, 1.0); + }"#; + + const FRAG: &str = r#" + #version 330 core + in vec3 v_color; + out vec4 color; + void main() { color = vec4(v_color, 1.0); }"#; + + let program = Program::from_source(&display, VERT, FRAG, None)?; + + let params = glium::DrawParameters { + depth: glium::Depth { + test: glium::draw_parameters::DepthTest::IfLess, + write: true, + .. Default::default() + }, + .. Default::default() + }; + + Ok(Self { display, program, meshes: Vec::new(), params }) + } +} + +impl Renderer for GliumRenderer { + fn render(&mut self, world: &World) { + let mut frame = self.display.draw(); + frame.clear_color_and_depth((0.1, 0.1, 0.15, 1.0), 1.0); + + // Expect exactly one active camera in the world. + let cam = match world.query::<&Camera>().iter().next() { + Some((_, cam)) => *cam, + None => { + eprintln!("[renderer] No camera component found – skipping frame"); + return; + } + }; + + let light_dir: Vec3 = Vec3::new(-1.0, -1.0, -1.0).normalize(); + + for (_, (tr, mh)) in world.query::<(&Transform, &MeshHandle)>().iter() { + let mesh = &self.meshes[mh.0]; + let uniforms = uniform! { + model: tr.matrix().to_cols_array_2d(), + view: cam.view().to_cols_array_2d(), + projection: cam.projection().to_cols_array_2d(), + light_dir: [light_dir.x, light_dir.y, light_dir.z], + }; + + frame.draw(&mesh.vbuf, &mesh.ibuf, &self.program, &uniforms, &self.params) + .unwrap(); + } + + frame.finish().unwrap(); + } +} From b793bec63afc007c06186955d6987efc84578fdb Mon Sep 17 00:00:00 2001 From: reo Date: Mon, 30 Jun 2025 11:04:54 +0300 Subject: [PATCH 03/89] Update shaders to do light processing in the fragment shaders --- src/render.rs | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/src/render.rs b/src/render.rs index e6319b4..3f579c0 100644 --- a/src/render.rs +++ b/src/render.rs @@ -30,21 +30,27 @@ impl GliumRenderer { uniform mat4 model; uniform mat4 view; uniform mat4 projection; - uniform vec3 light_dir; - out vec3 v_color; + out vec3 v_normal; void main() { - vec3 n = normalize(mat3(model) * normal); - float diff = max(dot(n, -light_dir), 0.0); - vec3 base = vec3(0.6, 0.6, 0.8); - v_color = base * diff + 0.1; - gl_Position = projection * view * model * vec4(position, 1.0); + mat4 modelview = view * model; + v_normal = transpose(inverse(mat3(modelview))) * normal; + gl_Position = projection * modelview * vec4(position, 1.0); }"#; const FRAG: &str = r#" #version 330 core - in vec3 v_color; + in vec3 v_normal; out vec4 color; - void main() { color = vec4(v_color, 1.0); }"#; + uniform vec3 light_dir; + + void main() { + float brightness = dot(normalize(v_normal), normalize(light_dir)); + vec3 dark_color = vec3(0.6, 0.0, 0.0); + vec3 regular_color = vec3(1.0, 0.0, 0.0); + color = vec4(mix(dark_color, regular_color, brightness), 1.0); + }"#; + + let program = Program::from_source(&display, VERT, FRAG, None)?; From cdbac0d4ab03a5fe2bf243993118bb09e7d74834 Mon Sep 17 00:00:00 2001 From: reo Date: Mon, 30 Jun 2025 23:29:41 +0300 Subject: [PATCH 04/89] Improve ECS Use query_one_mut instead of query_mut for single objects --- src/ecs.rs | 13 ------------- src/main.rs | 19 ++++++++++++------- src/render.rs | 1 - 3 files changed, 12 insertions(+), 21 deletions(-) diff --git a/src/ecs.rs b/src/ecs.rs index 2fed082..0f47217 100644 --- a/src/ecs.rs +++ b/src/ecs.rs @@ -17,16 +17,3 @@ impl Transform { #[derive(Clone)] pub struct MeshHandle(pub usize); -/// ------------ systems ------------ -pub fn rotation_system(world: &mut World, dt: f32) { - for (_, transform) in world.query_mut::<&mut Transform>() { - transform.rotation *= Quat::from_rotation_y(dt); - } -} - -/// Update the aspect ratio for all camera components in the world. -pub fn set_camera_aspect(world: &mut World, aspect: f32) { - for (_, cam) in world.query_mut::<&mut crate::camera::Camera>() { - cam.aspect = aspect; - } -} diff --git a/src/main.rs b/src/main.rs index 7d0ac14..cebe8e7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,7 +5,7 @@ mod render; use anyhow::Result; use camera::Camera; -use ecs::{rotation_system, MeshHandle, Transform}; +use ecs::{MeshHandle, Transform}; use glam::{Quat, Vec3}; use glium::backend::glutin::SimpleWindowBuilder; use render::{Renderer, GliumRenderer}; @@ -29,7 +29,7 @@ fn main() -> Result<()> { let mesh_id = renderer.meshes.len(); renderer.meshes.push(mesh); - world.spawn(( + let object_ent = world.spawn(( Transform { translation: Vec3::ZERO, rotation: Quat::IDENTITY, @@ -38,7 +38,8 @@ fn main() -> Result<()> { MeshHandle(mesh_id), )); - { + + let camera_ent = { let (w, h): (u32, u32) = window.inner_size().into(); world.spawn((Camera { eye: Vec3::new(3.0, 2.0, 3.0), @@ -48,8 +49,8 @@ fn main() -> Result<()> { aspect: w as f32 / h as f32, znear: 0.1, zfar: 100.0, - },)); - } + },)) + }; event_loop .run(move |event, el| { @@ -59,7 +60,9 @@ fn main() -> Result<()> { Event::WindowEvent { event, .. } => match event { WindowEvent::CloseRequested => el.exit(), WindowEvent::Resized(sz) => { - ecs::set_camera_aspect(&mut world, sz.width as f32 / sz.height as f32); + world.query_one_mut::<&mut crate::camera::Camera>(camera_ent).map(|mut cam| { + cam.aspect = sz.width as f32 / sz.height as f32; + }); } WindowEvent::RedrawRequested => { renderer.render(&world); @@ -74,7 +77,9 @@ fn main() -> Result<()> { let last = LAST.replace(now).unwrap_or(now); (now - last).as_secs_f32() }; - rotation_system(&mut world, dt); + world.query_one_mut::<&mut Transform>(object_ent).map(|mut object| { + object.rotation *= Quat::from_rotation_y(dt); + }); // ask for next frame window.request_redraw(); diff --git a/src/render.rs b/src/render.rs index 3f579c0..a4097db 100644 --- a/src/render.rs +++ b/src/render.rs @@ -72,7 +72,6 @@ impl Renderer for GliumRenderer { let mut frame = self.display.draw(); frame.clear_color_and_depth((0.1, 0.1, 0.15, 1.0), 1.0); - // Expect exactly one active camera in the world. let cam = match world.query::<&Camera>().iter().next() { Some((_, cam)) => *cam, None => { From 7e4168eee5e16dc29c6d8261513ee108d1d94dd0 Mon Sep 17 00:00:00 2001 From: reo Date: Tue, 1 Jul 2025 23:25:57 +0300 Subject: [PATCH 05/89] Add ECSRenderer for improved integration of rendering and ECS - Introduced ECSRenderer struct to manage the connection between the renderer and the ECS. - Implemented methods for spawning and despawning meshes within the ECS. - Updated main function to utilize ECSRenderer for rendering and object management. - Added a new Time module to handle frame timing and updates. --- src/ecs.rs | 40 ++++++++++++++++++++++++++++++++++--- src/main.rs | 57 ++++++++++++++++++++++++++++------------------------- src/time.rs | 34 ++++++++++++++++++++++++++++++++ 3 files changed, 101 insertions(+), 30 deletions(-) create mode 100644 src/time.rs diff --git a/src/ecs.rs b/src/ecs.rs index 0f47217..a67aa32 100644 --- a/src/ecs.rs +++ b/src/ecs.rs @@ -1,13 +1,48 @@ use glam::{Mat4, Quat, Vec3}; -use hecs::World; +use hecs::{Entity, World}; +use crate::{render::{GliumRenderer, Renderer}, model}; + +/// This system joins the renderer and ECS, +/// and provides tools to use them together +/// effectively. +pub struct ECSRenderer { + pub renderer: GliumRenderer, + pub world: World, +} + +impl ECSRenderer { + pub fn new(renderer: GliumRenderer, world: World) -> Self { + Self { renderer, world } + } + + pub fn spawn_mesh(&mut self, mesh: model::Mesh, transform: Transform) -> Entity { + let mesh_id = self.renderer.meshes.len(); + self.renderer.meshes.push(mesh); + self.world.spawn((transform, MeshHandle(mesh_id))) + } + + pub fn despawn_mesh(&mut self, entity: Entity) { + if let Ok(mesh_handle) = self.world.get::<&MeshHandle>(entity) { + if mesh_handle.0 < self.renderer.meshes.len() { + self.renderer.meshes.remove(mesh_handle.0); + } + } + let _ = self.world.despawn(entity); + } + + /// Render a single frame using the internal renderer & world. + pub fn render(&mut self) { + self.renderer.render(&self.world); + } +} -/// ------------ components ------------ #[derive(Copy, Clone)] pub struct Transform { pub translation: Vec3, pub rotation: Quat, pub scale: Vec3, } + impl Transform { pub fn matrix(&self) -> Mat4 { Mat4::from_scale_rotation_translation(self.scale, self.rotation, self.translation) @@ -16,4 +51,3 @@ impl Transform { #[derive(Clone)] pub struct MeshHandle(pub usize); - diff --git a/src/main.rs b/src/main.rs index cebe8e7..74fda0c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,6 +2,7 @@ mod camera; mod ecs; mod model; mod render; +mod time; use anyhow::Result; use camera::Camera; @@ -9,9 +10,10 @@ use ecs::{MeshHandle, Transform}; use glam::{Quat, Vec3}; use glium::backend::glutin::SimpleWindowBuilder; use render::{Renderer, GliumRenderer}; -use std::time::Instant; fn main() -> Result<()> { + const ROTATION_SPEED: f32 = 1.0; + let event_loop = glium::winit::event_loop::EventLoop::builder() .build() .expect("create event-loop"); @@ -21,27 +23,28 @@ fn main() -> Result<()> { .with_inner_size(1280, 720) .build(&event_loop); - let mut world = hecs::World::new(); + // Create ECS renderer which internally owns both the world and the renderer + let mut ecsr = { + let world = hecs::World::new(); + let renderer = GliumRenderer::new(display.clone())?; + ecs::ECSRenderer::new(renderer, world) + }; - let mesh = model::load_gltf("resources/monkey-smooth.gltf", &display)?; - // let mesh = model::cube(&display)?; - let mut renderer = GliumRenderer::new(display)?; - let mesh_id = renderer.meshes.len(); - renderer.meshes.push(mesh); + let mut time = time::Time::new(); - let object_ent = world.spawn(( - Transform { - translation: Vec3::ZERO, - rotation: Quat::IDENTITY, - scale: Vec3::ONE, - }, - MeshHandle(mesh_id), - )); + let object_ent = { + let mesh = model::load_gltf("resources/monkey-smooth.gltf", &display)?; + ecsr.spawn_mesh(mesh, Transform { + translation: Vec3::ZERO, + rotation: Quat::IDENTITY, + scale: Vec3::ONE, + }) + }; let camera_ent = { let (w, h): (u32, u32) = window.inner_size().into(); - world.spawn((Camera { + ecsr.world.spawn((Camera { eye: Vec3::new(3.0, 2.0, 3.0), center: Vec3::ZERO, up: Vec3::Y, @@ -60,27 +63,27 @@ fn main() -> Result<()> { Event::WindowEvent { event, .. } => match event { WindowEvent::CloseRequested => el.exit(), WindowEvent::Resized(sz) => { - world.query_one_mut::<&mut crate::camera::Camera>(camera_ent).map(|mut cam| { + ecsr.world.query_one_mut::<&mut crate::camera::Camera>(camera_ent).map(|mut cam| { cam.aspect = sz.width as f32 / sz.height as f32; }); } WindowEvent::RedrawRequested => { - renderer.render(&world); + ecsr.render(); } _ => {} }, Event::AboutToWait => { - // -- update logic -- - let now = Instant::now(); - static mut LAST: Option = None; - let dt = unsafe { // FIXME - let last = LAST.replace(now).unwrap_or(now); - (now - last).as_secs_f32() - }; - world.query_one_mut::<&mut Transform>(object_ent).map(|mut object| { - object.rotation *= Quat::from_rotation_y(dt); + time.tick(); + let dt = time.delta_seconds(); + ecsr.world.query_one_mut::<&mut Transform>(object_ent).map(|mut object| { + object.rotation *= Quat::from_rotation_y(ROTATION_SPEED * dt); }); + // despawn the object after 3 seconds + if time.total_seconds() > 3.0 { + ecsr.despawn_mesh(object_ent); + } + // ask for next frame window.request_redraw(); } diff --git a/src/time.rs b/src/time.rs new file mode 100644 index 0000000..5e8159b --- /dev/null +++ b/src/time.rs @@ -0,0 +1,34 @@ +use std::time::{Duration, Instant}; + +#[derive(Clone, Debug)] +pub struct Time { + last: Instant, + delta: Duration, + total: Duration, +} + +impl Time { + pub fn new() -> Self { + let now = Instant::now(); + Self { + last: now, + delta: Duration::ZERO, + total: Duration::ZERO, + } + } + + pub fn tick(&mut self) { + let now = Instant::now(); + self.delta = now - self.last; + self.total += self.delta; + self.last = now; + } + + pub fn delta_seconds(&self) -> f32 { + self.delta.as_secs_f32() + } + + pub fn total_seconds(&self) -> f32 { + self.total.as_secs_f32() + } +} \ No newline at end of file From 5358fea0f9ad4e688f9a3642c7724fa1b9f22eb3 Mon Sep 17 00:00:00 2001 From: reo Date: Sat, 5 Jul 2025 20:39:35 +0300 Subject: [PATCH 06/89] Add new dependencies, downgrade glium Added imgui and its renderer dependencies. Downgraded glium to 0.35 to make it work with imgui-glium-renderer --- Cargo.lock | 113 +++++++++++++++++++++++++++++++++++++++++++++++++---- Cargo.toml | 11 ++++-- 2 files changed, 113 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index df2430f..a227390 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -322,6 +322,12 @@ dependencies = [ "libc", ] +[[package]] +name = "chlorine" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c00d31b1d19317b4777ec879192d3745bd97d05262b4b19cb1dda284b9d22f19" + [[package]] name = "color_quant" version = "1.1.0" @@ -590,6 +596,10 @@ dependencies = [ "glutin", "hecs", "image", + "imgui", + "imgui-glium-renderer", + "imgui-winit-support", + "winit", ] [[package]] @@ -660,9 +670,9 @@ checksum = "50a99dbe56b72736564cfa4b85bf9a33079f16ae8b74983ab06af3b1a3696b11" [[package]] name = "glium" -version = "0.36.0" +version = "0.35.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cf52ce4f5ce1501bb056627f35484a819e812d1d93f0f3da413676421b1bbe0" +checksum = "0a3028d1f135b5395e6e4336916b424bc5dd2b38c6e378ce2704e4b8f4a617ed" dependencies = [ "backtrace", "fnv", @@ -866,6 +876,51 @@ version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0263a3d970d5c054ed9312c0057b4f3bde9c0b33836d3637361d4a9e6e7a408" +[[package]] +name = "imgui" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8addafa5cecf0515812226e806913814e02ce38d10215778082af5174abe5669" +dependencies = [ + "bitflags 1.3.2", + "cfg-if", + "imgui-sys", + "mint", + "parking_lot", +] + +[[package]] +name = "imgui-glium-renderer" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "781e53a393214a132c89c62e6e4b817645ad38832d3e334b2ad543f2c3df5106" +dependencies = [ + "glium", + "imgui", +] + +[[package]] +name = "imgui-sys" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ead193f9f4b60398e8b8f4ab1483e2321640d87aeebdaa3e5f44c55633ccd804" +dependencies = [ + "cc", + "cfg-if", + "chlorine", + "mint", +] + +[[package]] +name = "imgui-winit-support" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff7fcccfa9efab56c94274c0fec9939bb14149342b49e6a425883a5b7dda6a3f" +dependencies = [ + "imgui", + "winit", +] + [[package]] name = "indexmap" version = "2.9.0" @@ -1023,6 +1078,16 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" +[[package]] +name = "lock_api" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765" +dependencies = [ + "autocfg", + "scopeguard", +] + [[package]] name = "log" version = "0.4.27" @@ -1088,6 +1153,12 @@ dependencies = [ "simd-adler32", ] +[[package]] +name = "mint" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e53debba6bda7a793e5f99b8dacf19e626084f525f7829104ba9898f367d85ff" + [[package]] name = "ndk" version = "0.9.0" @@ -1491,6 +1562,29 @@ dependencies = [ "ttf-parser", ] +[[package]] +name = "parking_lot" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall 0.5.13", + "smallvec", + "windows-targets 0.52.6", +] + [[package]] name = "paste" version = "1.0.15" @@ -1837,6 +1931,12 @@ 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" @@ -2206,13 +2306,12 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.50" +version = "0.4.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" +checksum = "cc7ec4f8827a71586374db3e87abdb5a2bb3a15afed140221307c3ec06b1f63b" dependencies = [ "cfg-if", "js-sys", - "once_cell", "wasm-bindgen", "web-sys", ] @@ -2360,9 +2459,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.77" +version = "0.3.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" +checksum = "f6488b90108c040df0fe62fa815cbdee25124641df01814dd7282749234c6112" dependencies = [ "js-sys", "wasm-bindgen", diff --git a/Cargo.toml b/Cargo.toml index 8657bbe..86f321c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,12 +7,15 @@ edition = "2021" anyhow = "1.0.98" glam = "0.30.4" -# glium already re-exports glutin/winit, but we enable the helper features explicitly -glium = { version = "0.36.0", features = ["glutin_backend", "simple_window_builder"] } +glium = { version = "0.35.0", features = ["glutin_backend", "simple_window_builder"] } gltf = { version = "1.4.1", features = ["import"] } - -# explicit glutin for raw types (same semver as glium’s internal one) glutin = { version = "0.32.3", default-features = false } hecs = "0.10.5" image = "0.25.6" + +imgui = "0.12" +imgui-winit-support = "0.13" +imgui-glium-renderer = "0.13" + +winit = "0.30" From 5df87387110b254c6bcf8bda657cc15b3d605a9b Mon Sep 17 00:00:00 2001 From: reo Date: Sat, 5 Jul 2025 20:42:35 +0300 Subject: [PATCH 07/89] Move model files to resources/models --- resources/{ => models}/cube.bin | Bin resources/{ => models}/cube.gltf | 0 resources/{ => models}/cube.obj | 0 resources/{ => models}/monkey-smooth.bin | Bin resources/{ => models}/monkey-smooth.gltf | 0 resources/{ => models}/monkey.bin | Bin resources/{ => models}/monkey.gltf | 0 resources/{ => models}/uvsphere-smooth.bin | Bin resources/{ => models}/uvsphere-smooth.gltf | 0 resources/{ => models}/uvsphere.bin | Bin resources/{ => models}/uvsphere.gltf | 0 resources/{ => models}/uvsphere2.bin | Bin resources/{ => models}/uvsphere2.gltf | 0 src/main.rs | 2 +- 14 files changed, 1 insertion(+), 1 deletion(-) rename resources/{ => models}/cube.bin (100%) rename resources/{ => models}/cube.gltf (100%) rename resources/{ => models}/cube.obj (100%) rename resources/{ => models}/monkey-smooth.bin (100%) rename resources/{ => models}/monkey-smooth.gltf (100%) rename resources/{ => models}/monkey.bin (100%) rename resources/{ => models}/monkey.gltf (100%) rename resources/{ => models}/uvsphere-smooth.bin (100%) rename resources/{ => models}/uvsphere-smooth.gltf (100%) rename resources/{ => models}/uvsphere.bin (100%) rename resources/{ => models}/uvsphere.gltf (100%) rename resources/{ => models}/uvsphere2.bin (100%) rename resources/{ => models}/uvsphere2.gltf (100%) diff --git a/resources/cube.bin b/resources/models/cube.bin similarity index 100% rename from resources/cube.bin rename to resources/models/cube.bin diff --git a/resources/cube.gltf b/resources/models/cube.gltf similarity index 100% rename from resources/cube.gltf rename to resources/models/cube.gltf diff --git a/resources/cube.obj b/resources/models/cube.obj similarity index 100% rename from resources/cube.obj rename to resources/models/cube.obj diff --git a/resources/monkey-smooth.bin b/resources/models/monkey-smooth.bin similarity index 100% rename from resources/monkey-smooth.bin rename to resources/models/monkey-smooth.bin diff --git a/resources/monkey-smooth.gltf b/resources/models/monkey-smooth.gltf similarity index 100% rename from resources/monkey-smooth.gltf rename to resources/models/monkey-smooth.gltf diff --git a/resources/monkey.bin b/resources/models/monkey.bin similarity index 100% rename from resources/monkey.bin rename to resources/models/monkey.bin diff --git a/resources/monkey.gltf b/resources/models/monkey.gltf similarity index 100% rename from resources/monkey.gltf rename to resources/models/monkey.gltf diff --git a/resources/uvsphere-smooth.bin b/resources/models/uvsphere-smooth.bin similarity index 100% rename from resources/uvsphere-smooth.bin rename to resources/models/uvsphere-smooth.bin diff --git a/resources/uvsphere-smooth.gltf b/resources/models/uvsphere-smooth.gltf similarity index 100% rename from resources/uvsphere-smooth.gltf rename to resources/models/uvsphere-smooth.gltf diff --git a/resources/uvsphere.bin b/resources/models/uvsphere.bin similarity index 100% rename from resources/uvsphere.bin rename to resources/models/uvsphere.bin diff --git a/resources/uvsphere.gltf b/resources/models/uvsphere.gltf similarity index 100% rename from resources/uvsphere.gltf rename to resources/models/uvsphere.gltf diff --git a/resources/uvsphere2.bin b/resources/models/uvsphere2.bin similarity index 100% rename from resources/uvsphere2.bin rename to resources/models/uvsphere2.bin diff --git a/resources/uvsphere2.gltf b/resources/models/uvsphere2.gltf similarity index 100% rename from resources/uvsphere2.gltf rename to resources/models/uvsphere2.gltf diff --git a/src/main.rs b/src/main.rs index 74fda0c..7f5a5a6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -33,7 +33,7 @@ fn main() -> Result<()> { let mut time = time::Time::new(); let object_ent = { - let mesh = model::load_gltf("resources/monkey-smooth.gltf", &display)?; + let mesh = model::load_gltf("resources/models/monkey.gltf", &display)?; ecsr.spawn_mesh(mesh, Transform { translation: Vec3::ZERO, rotation: Quat::IDENTITY, From a17a6016b88685c7afc7f03786761b502fa74ccf Mon Sep 17 00:00:00 2001 From: reo Date: Sat, 5 Jul 2025 20:42:55 +0300 Subject: [PATCH 08/89] Move shaders to separate files --- resources/shaders/gl_solid_color.frag | 11 ++++++++++ resources/shaders/gl_solid_color.vert | 12 +++++++++++ src/render.rs | 30 ++------------------------- 3 files changed, 25 insertions(+), 28 deletions(-) create mode 100644 resources/shaders/gl_solid_color.frag create mode 100644 resources/shaders/gl_solid_color.vert diff --git a/resources/shaders/gl_solid_color.frag b/resources/shaders/gl_solid_color.frag new file mode 100644 index 0000000..c3da69f --- /dev/null +++ b/resources/shaders/gl_solid_color.frag @@ -0,0 +1,11 @@ +#version 330 core +in vec3 v_normal; +out vec4 color; +uniform vec3 light_dir; + +void main() { + float brightness = dot(normalize(v_normal), normalize(light_dir)); + vec3 dark_color = vec3(0.6, 0.0, 0.0); + vec3 regular_color = vec3(1.0, 0.0, 0.0); + color = vec4(mix(dark_color, regular_color, brightness), 1.0); +} diff --git a/resources/shaders/gl_solid_color.vert b/resources/shaders/gl_solid_color.vert new file mode 100644 index 0000000..cc65b9f --- /dev/null +++ b/resources/shaders/gl_solid_color.vert @@ -0,0 +1,12 @@ +#version 330 core +in vec3 position; +in vec3 normal; +uniform mat4 model; +uniform mat4 view; +uniform mat4 projection; +out vec3 v_normal; +void main() { + mat4 modelview = view * model; + v_normal = transpose(inverse(mat3(modelview))) * normal; + gl_Position = projection * modelview * vec4(position, 1.0); +} diff --git a/src/render.rs b/src/render.rs index a4097db..58557af 100644 --- a/src/render.rs +++ b/src/render.rs @@ -23,34 +23,8 @@ pub struct GliumRenderer { impl GliumRenderer { /// Create a new OpenGL renderer consuming the provided `display`. pub fn new(display: glium::Display) -> anyhow::Result { - const VERT: &str = r#" - #version 330 core - in vec3 position; - in vec3 normal; - uniform mat4 model; - uniform mat4 view; - uniform mat4 projection; - out vec3 v_normal; - void main() { - mat4 modelview = view * model; - v_normal = transpose(inverse(mat3(modelview))) * normal; - gl_Position = projection * modelview * vec4(position, 1.0); - }"#; - - const FRAG: &str = r#" - #version 330 core - in vec3 v_normal; - out vec4 color; - uniform vec3 light_dir; - - void main() { - float brightness = dot(normalize(v_normal), normalize(light_dir)); - vec3 dark_color = vec3(0.6, 0.0, 0.0); - vec3 regular_color = vec3(1.0, 0.0, 0.0); - color = vec4(mix(dark_color, regular_color, brightness), 1.0); - }"#; - - + const VERT: &str = include_str!("../resources/shaders/gl_solid_color.vert"); + const FRAG: &str = include_str!("../resources/shaders/gl_solid_color.frag"); let program = Program::from_source(&display, VERT, FRAG, None)?; From 111c42a7464eab18b990ca351ec7978afb890424 Mon Sep 17 00:00:00 2001 From: reo Date: Sat, 5 Jul 2025 20:43:18 +0300 Subject: [PATCH 09/89] Add function "render_into" to the ECS system This is needed for the imgui integration --- src/ecs.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/ecs.rs b/src/ecs.rs index a67aa32..8fc4ab8 100644 --- a/src/ecs.rs +++ b/src/ecs.rs @@ -1,6 +1,6 @@ use glam::{Mat4, Quat, Vec3}; use hecs::{Entity, World}; -use crate::{render::{GliumRenderer, Renderer}, model}; +use crate::{render::GliumRenderer, model}; /// This system joins the renderer and ECS, /// and provides tools to use them together @@ -34,6 +34,12 @@ impl ECSRenderer { pub fn render(&mut self) { self.renderer.render(&self.world); } + + /// Render into an existing glium target surface. Useful for composing with + /// other render passes (e.g. Dear ImGui). + pub fn render_into(&mut self, target: &mut S) { + self.renderer.render_into(&self.world, target); + } } #[derive(Copy, Clone)] From 76dabf2e63a4c6b32a18379775566cdd6986cd58 Mon Sep 17 00:00:00 2001 From: reo Date: Sat, 5 Jul 2025 20:44:20 +0300 Subject: [PATCH 10/89] Add function render_into to the renderer To be used for the Dear ImGui integration --- src/render.rs | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/src/render.rs b/src/render.rs index 58557af..eca2710 100644 --- a/src/render.rs +++ b/src/render.rs @@ -6,13 +6,6 @@ use glam::Vec3; use hecs::World; use glium::glutin::surface::WindowSurface; -/// Generic rendering backend trait. -pub trait Renderer { - /// Render a single frame for the given `World`. - fn render(&mut self, world: &World); -} - -/// Concrete OpenGL (glium) renderer implementing `Renderer`. pub struct GliumRenderer { display: glium::Display, program: Program, @@ -21,7 +14,6 @@ pub struct GliumRenderer { } impl GliumRenderer { - /// Create a new OpenGL renderer consuming the provided `display`. pub fn new(display: glium::Display) -> anyhow::Result { const VERT: &str = include_str!("../resources/shaders/gl_solid_color.vert"); const FRAG: &str = include_str!("../resources/shaders/gl_solid_color.frag"); @@ -39,17 +31,12 @@ impl GliumRenderer { Ok(Self { display, program, meshes: Vec::new(), params }) } -} - -impl Renderer for GliumRenderer { - fn render(&mut self, world: &World) { - let mut frame = self.display.draw(); - frame.clear_color_and_depth((0.1, 0.1, 0.15, 1.0), 1.0); + fn draw_scene(&self, world: &World, target: &mut S) { let cam = match world.query::<&Camera>().iter().next() { Some((_, cam)) => *cam, None => { - eprintln!("[renderer] No camera component found – skipping frame"); + eprintln!("[renderer] No camera component found. Skipping frame"); return; } }; @@ -65,10 +52,21 @@ impl Renderer for GliumRenderer { light_dir: [light_dir.x, light_dir.y, light_dir.z], }; - frame.draw(&mesh.vbuf, &mesh.ibuf, &self.program, &uniforms, &self.params) - .unwrap(); + target + .draw(&mesh.vbuf, &mesh.ibuf, &self.program, &uniforms, &self.params) + .unwrap(); } + } + pub fn render_into(&mut self, world: &World, target: &mut S) { + target.clear_color_and_depth((0.1, 0.1, 0.15, 1.0), 1.0); + self.draw_scene(world, target); + } + + pub fn render(&mut self, world: &World) { + let mut frame = self.display.draw(); + frame.clear_color_and_depth((0.1, 0.1, 0.15, 1.0), 1.0); + self.draw_scene(world, &mut frame); frame.finish().unwrap(); } } From 498989fb1e4de3c87f07beedc552d9b4a13ef252 Mon Sep 17 00:00:00 2001 From: reo Date: Sat, 5 Jul 2025 20:44:47 +0300 Subject: [PATCH 11/89] Add module ui.rs for the imgui integration --- src/ui.rs | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 src/ui.rs diff --git a/src/ui.rs b/src/ui.rs new file mode 100644 index 0000000..c6be88a --- /dev/null +++ b/src/ui.rs @@ -0,0 +1,84 @@ +use std::time::Instant; + +use anyhow::Result; +use imgui::{Context as ImguiContext, Ui}; +use imgui_winit_support::{HiDpiMode, WinitPlatform}; +use imgui_glium_renderer::Renderer as ImguiGliumRenderer; +use winit::window::Window; +use glium::{Frame}; +use glium::glutin::surface::WindowSurface; + +/// Convenience wrapper that owns all ImGui state required for integration with +/// winit + glium. +pub struct Gui { + imgui: ImguiContext, + platform: WinitPlatform, + renderer: ImguiGliumRenderer, + last_frame: Instant, +} + +impl Gui { + pub fn new(display: &glium::Display, window: &Window) -> Result { + let mut imgui = ImguiContext::create(); + imgui.set_ini_filename(None); + let mut platform = WinitPlatform::new(&mut imgui); + platform.attach_window(imgui.io_mut(), window, HiDpiMode::Default); + imgui.fonts().add_font(&[imgui::FontSource::DefaultFontData { config: None }]); + let renderer = ImguiGliumRenderer::new(&mut imgui, display)?; + + Ok(Self { + imgui, + platform, + renderer, + last_frame: Instant::now(), + }) + } + + pub fn handle_event(&mut self, window: &Window, event: &winit::event::Event) { + self.platform + .handle_event(self.imgui.io_mut(), window, event); + } + + pub fn prepare_frame(&mut self, window: &Window) { + let now = Instant::now(); + self.imgui.io_mut().update_delta_time(now - self.last_frame); + self.last_frame = now; + + self + .platform + .prepare_frame(self.imgui.io_mut(), window) + .expect("failed to prepare imgui frame"); + } + + pub fn render(&mut self, target: &mut Frame, window: &Window) { + let mut open = true; + self.render_with(target, window, |ui| { + ui.show_demo_window(&mut open); + }); + } + + pub fn render_with(&mut self, target: &mut Frame, window: &Window, build_ui: F) + where + F: FnOnce(&Ui), + { + let ui = self.imgui.frame(); + + build_ui(&ui); + + self.platform.prepare_render(ui, window); + let draw_data = self.imgui.render(); + + self + .renderer + .render(target, draw_data) + .expect("imgui rendering failed"); + } + + pub fn ui(&mut self, build: F) + where + F: FnOnce(&Ui), + { + let ui = self.imgui.frame(); + build(&ui); + } +} \ No newline at end of file From 876d624d2dbc6f5686971acd7ac8dbd30254033e Mon Sep 17 00:00:00 2001 From: reo Date: Sat, 5 Jul 2025 20:45:25 +0300 Subject: [PATCH 12/89] Utilize the new UI module in main.rs Added simple transformation inputs for testing --- src/main.rs | 65 ++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 44 insertions(+), 21 deletions(-) diff --git a/src/main.rs b/src/main.rs index 7f5a5a6..5b45c33 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,17 +3,16 @@ mod ecs; mod model; mod render; mod time; +mod ui; use anyhow::Result; use camera::Camera; use ecs::{MeshHandle, Transform}; -use glam::{Quat, Vec3}; +use glam::{Quat, Vec3, EulerRot}; use glium::backend::glutin::SimpleWindowBuilder; -use render::{Renderer, GliumRenderer}; +use render::GliumRenderer; fn main() -> Result<()> { - const ROTATION_SPEED: f32 = 1.0; - let event_loop = glium::winit::event_loop::EventLoop::builder() .build() .expect("create event-loop"); @@ -30,14 +29,17 @@ fn main() -> Result<()> { ecs::ECSRenderer::new(renderer, world) }; + // Dear ImGui integration + let mut gui = ui::Gui::new(&display, &window)?; + let mut time = time::Time::new(); let object_ent = { let mesh = model::load_gltf("resources/models/monkey.gltf", &display)?; ecsr.spawn_mesh(mesh, Transform { - translation: Vec3::ZERO, - rotation: Quat::IDENTITY, - scale: Vec3::ONE, + translation: Vec3::ZERO, + rotation: Quat::IDENTITY, + scale: Vec3::ONE, }) }; @@ -45,10 +47,10 @@ fn main() -> Result<()> { let camera_ent = { let (w, h): (u32, u32) = window.inner_size().into(); ecsr.world.spawn((Camera { - eye: Vec3::new(3.0, 2.0, 3.0), + eye: Vec3::new(0.0, 0.0, 2.0), center: Vec3::ZERO, up: Vec3::Y, - fovy: 45_f32.to_radians(), + fovy: 60_f32.to_radians(), aspect: w as f32 / h as f32, znear: 0.1, zfar: 100.0, @@ -59,6 +61,8 @@ fn main() -> Result<()> { .run(move |event, el| { use glium::winit::event::{Event, WindowEvent}; + gui.handle_event(&window, &event); + match event { Event::WindowEvent { event, .. } => match event { WindowEvent::CloseRequested => el.exit(), @@ -68,23 +72,42 @@ fn main() -> Result<()> { }); } WindowEvent::RedrawRequested => { - ecsr.render(); + let mut target = display.draw(); + + ecsr.render_into(&mut target); + + gui.render_with(&mut target, &window, |ui| { + if let Ok(mut tr) = ecsr.world.query_one_mut::<&mut Transform>(object_ent) { + // Translation controls + let mut translation = [tr.translation.x, tr.translation.y, tr.translation.z]; + if ui.input_float3("Translation", &mut translation).build() { + tr.translation = Vec3::from(translation); + } + + // Scale controls + let mut scale = [tr.scale.x, tr.scale.y, tr.scale.z]; + if ui.input_float3("Scale", &mut scale).build() { + tr.scale = Vec3::from(scale); + } + + // Rotation controls + let (yaw, pitch, roll) = tr.rotation.to_euler(EulerRot::YXZ); + let mut rotation_deg = [yaw.to_degrees(), pitch.to_degrees(), roll.to_degrees()]; + if ui.input_float3("Rotation (deg)", &mut rotation_deg).build() { + let yaw = rotation_deg[0].to_radians(); + let pitch = rotation_deg[1].to_radians(); + let roll = rotation_deg[2].to_radians(); + tr.rotation = Quat::from_euler(EulerRot::YXZ, yaw, pitch, roll); + } + } + }); + target.finish().unwrap(); } _ => {} }, Event::AboutToWait => { time.tick(); - let dt = time.delta_seconds(); - ecsr.world.query_one_mut::<&mut Transform>(object_ent).map(|mut object| { - object.rotation *= Quat::from_rotation_y(ROTATION_SPEED * dt); - }); - - // despawn the object after 3 seconds - if time.total_seconds() > 3.0 { - ecsr.despawn_mesh(object_ent); - } - - // ask for next frame + gui.prepare_frame(&window); window.request_redraw(); } _ => {} From 3db523790934fc659aee2c848a2addc40eec6e52 Mon Sep 17 00:00:00 2001 From: reo Date: Sun, 13 Jul 2025 18:46:21 +0300 Subject: [PATCH 13/89] Add KHR_texture_transform and utils features to the gltf package --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 86f321c..d26e25b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,7 +8,7 @@ anyhow = "1.0.98" glam = "0.30.4" glium = { version = "0.35.0", features = ["glutin_backend", "simple_window_builder"] } -gltf = { version = "1.4.1", features = ["import"] } +gltf = { version = "1.4.1", features = ["import", "utils", "KHR_texture_transform"] } glutin = { version = "0.32.3", default-features = false } hecs = "0.10.5" From 0ecdb2cb6fac1b9b8c3a1d56c35b70bb2a2243ab Mon Sep 17 00:00:00 2001 From: reo Date: Sun, 13 Jul 2025 19:54:39 +0300 Subject: [PATCH 14/89] Move gltf_loader to a separate module, new GLTF features - glTF loader now supports textures. I was able to successfully load multiple blender models with different texturing methods. - Added Material to represent textures and material properties. --- src/gltf_loader.rs | 180 +++++++++++++++++++++++++++++++++++++++++++++ src/model.rs | 149 +++++++++++-------------------------- 2 files changed, 221 insertions(+), 108 deletions(-) create mode 100644 src/gltf_loader.rs diff --git a/src/gltf_loader.rs b/src/gltf_loader.rs new file mode 100644 index 0000000..81b24b7 --- /dev/null +++ b/src/gltf_loader.rs @@ -0,0 +1,180 @@ +//! GPU-ready mesh loader for **glTF 2.0** (internal helper) +//! +//! Converts the first primitive of a glTF document into our engine `Model`. + +use anyhow::{Context, Result}; +use glium::{backend::Facade, IndexBuffer, VertexBuffer}; +use glium::index::PrimitiveType; +use gltf::mesh::util::ReadIndices; +use std::{fmt::Debug, path::Path}; +use crate::model::{Vertex, Mesh, Material, Model}; +use glium::texture::{RawImage2d, Texture2d, SrgbTexture2d}; +use glium::uniforms::{SamplerWrapFunction, MinifySamplerFilter, MagnifySamplerFilter}; +use gltf::image::Format as GltfFormat; +use glam::Vec2; + +/// Load a glTF 2.0 file from disk and upload the first primitive to the GPU. +pub fn load_gltf(path: P, facade: &F) -> Result +where + P: AsRef + Debug, + F: Facade + ?Sized, +{ + // -- parse the asset & bring buffer blobs into memory -- + let (doc, buffers, images) = gltf::import(path.as_ref()).context("failed to import glTF file")?; + + // -- grab the very first mesh / primitive -- + let mesh = doc.meshes().next().context("glTF has no meshes")?; + let primitive = mesh.primitives().next().context("mesh has no primitives")?; + + // ---------- MATERIAL ---------- + let mut mat = Material::default(); + + let mat_idx = primitive.material().index().context("primitive has no material")?; + let material = doc.materials().nth(mat_idx).unwrap(); + let pbr = material.pbr_metallic_roughness(); + + // Factors -------------------------------------------------- + mat.base_color_factor = pbr.base_color_factor(); + mat.metal_factor = pbr.metallic_factor(); + mat.roughness_factor = pbr.roughness_factor(); + mat.emissive_factor = material.emissive_factor(); + + // Helper to update sampler settings from glTF sampler + fn update_sampler(mat: &mut Material, t: &gltf::texture::Texture<'_>) { + let sampler_info = t.sampler(); + mat.sampler.wrap_function.0 = match sampler_info.wrap_s() { + gltf::texture::WrappingMode::ClampToEdge => SamplerWrapFunction::Clamp, + gltf::texture::WrappingMode::MirroredRepeat => SamplerWrapFunction::Mirror, + gltf::texture::WrappingMode::Repeat => SamplerWrapFunction::Repeat, + }; + mat.sampler.wrap_function.1 = match sampler_info.wrap_t() { + gltf::texture::WrappingMode::ClampToEdge => SamplerWrapFunction::Clamp, + gltf::texture::WrappingMode::MirroredRepeat => SamplerWrapFunction::Mirror, + gltf::texture::WrappingMode::Repeat => SamplerWrapFunction::Repeat, + }; + if let Some(f) = sampler_info.mag_filter() { + mat.sampler.magnify_filter = match f { + gltf::texture::MagFilter::Nearest => MagnifySamplerFilter::Nearest, + gltf::texture::MagFilter::Linear => MagnifySamplerFilter::Linear, + }; + } + if let Some(f) = sampler_info.min_filter() { + mat.sampler.minify_filter = match f { + gltf::texture::MinFilter::Nearest => MinifySamplerFilter::Nearest, + gltf::texture::MinFilter::Linear => MinifySamplerFilter::Linear, + gltf::texture::MinFilter::NearestMipmapNearest => MinifySamplerFilter::NearestMipmapNearest, + gltf::texture::MinFilter::NearestMipmapLinear => MinifySamplerFilter::NearestMipmapLinear, + gltf::texture::MinFilter::LinearMipmapNearest => MinifySamplerFilter::LinearMipmapNearest, + gltf::texture::MinFilter::LinearMipmapLinear => MinifySamplerFilter::LinearMipmapLinear, + }; + } + } + + // Base-color texture (sRGB) + if let Some(info) = pbr.base_color_texture() { + update_sampler(&mut mat, &info.texture()); + let view = info.texture().source().index(); + mat.base_color = Some(glium_srgb_texture(facade, &images[view])?); + } + + // Metallic-Roughness (linear) + if let Some(info) = pbr.metallic_roughness_texture() { + update_sampler(&mut mat, &info.texture()); + let view = info.texture().source().index(); + mat.metallic_roughness = Some(glium_linear_texture(facade, &images[view])?); + } + + // Normal map (linear) + if let Some(info) = primitive.material().normal_texture() { + update_sampler(&mut mat, &info.texture()); + let view = info.texture().source().index(); + mat.normal = Some(glium_linear_texture(facade, &images[view])?); + } + + // Occlusion (linear) + if let Some(info) = primitive.material().occlusion_texture() { + update_sampler(&mut mat, &info.texture()); + let view = info.texture().source().index(); + mat.occlusion = Some(glium_linear_texture(facade, &images[view])?); + } + + // Emissive (sRGB) + if let Some(info) = primitive.material().emissive_texture() { + update_sampler(&mut mat, &info.texture()); + let view = info.texture().source().index(); + mat.emissive = Some(glium_srgb_texture(facade, &images[view])?); + } + + // KHR_texture_transform + if let Some(tex) = pbr.base_color_texture() { + if let Some(xform) = tex.texture_transform() { + mat.uv_offset = Vec2::new(xform.offset()[0], xform.offset()[1]); + mat.uv_scale = Vec2::new(xform.scale()[0], xform.scale()[1]); + } + } + + // ---- Vertex/index data ---- + let reader = primitive.reader(|buf| Some(&buffers[buf.index()].0)); + + let positions: Vec<[f32; 3]> = reader.read_positions().context("missing POSITION")?.collect(); + let normals: Vec<[f32; 3]> = reader.read_normals().context("missing NORMAL")?.collect(); + let tex_coords: Vec<[f32; 2]> = reader.read_tex_coords(0).map(|tc| tc.into_f32().collect()).unwrap_or_else(|| vec![[0.0, 0.0]; positions.len()]); + let indices: Vec = reader.read_indices().context("missing indices")?.into_u32().collect(); + + // Interleave + let vertices: Vec = (0..positions.len()).map(|i| Vertex { position: positions[i], normal: normals[i], tex_coords: tex_coords[i] }).collect(); + + let vbuf = VertexBuffer::immutable(facade, &vertices)?; + let ibuf = IndexBuffer ::immutable(facade, PrimitiveType::TrianglesList, &indices)?; + + Ok(Model { mesh: Mesh { vbuf, ibuf }, material: mat }) +} + +/// Linear-space texture (RGBA8) from glTF image data. +fn glium_linear_texture(facade: &F, img: &gltf::image::Data) -> Result +where + F: Facade + ?Sized, +{ + let rgba = to_rgba(img); + let raw = RawImage2d::from_raw_rgba(rgba, (img.width, img.height)); + Ok(Texture2d::new(facade, raw)?) +} + +/// sRGB texture from glTF image data. +fn glium_srgb_texture(facade: &F, img: &gltf::image::Data) -> Result +where + F: Facade + ?Sized, +{ + let rgba = to_rgba(img); + let raw = RawImage2d::from_raw_rgba(rgba, (img.width, img.height)); + Ok(SrgbTexture2d::new(facade, raw)?) +} + +/// Convert various glTF image formats to RGBA8 as expected by glium. +fn to_rgba(img: &gltf::image::Data) -> Vec { + match img.format { + GltfFormat::R8G8B8A8 => img.pixels.clone(), + GltfFormat::R8G8B8 => { + // Expand RGB to RGBA with alpha=255 + img.pixels + .chunks(3) + .flat_map(|rgb| [rgb[0], rgb[1], rgb[2], 255u8]) + .collect() + } + GltfFormat::R8G8 => { + // Treat RG as luminance+alpha? For simplicity, replicate first channel into RGB, second as alpha. + img.pixels + .chunks(2) + .flat_map(|rg| [rg[0], rg[0], rg[0], rg[1]]) + .collect() + } + GltfFormat::R8 => { + // Grayscale: replicate into RGB, alpha=255 + img.pixels + .iter() + .flat_map(|l| [*l, *l, *l, 255u8]) + .collect() + } + _ => img.pixels.clone(), + } +} \ No newline at end of file diff --git a/src/model.rs b/src/model.rs index 815e2a2..e474fe4 100644 --- a/src/model.rs +++ b/src/model.rs @@ -1,124 +1,57 @@ -//! GPU-ready mesh loader for **glTF 2.0** -//! -//! Loads the first mesh/primitive found in a .gltf/.glb file. - -use anyhow::{Context, Result}; +use glium::texture::{RawImage2d, SrgbTexture2d, Texture2d}; +use glium::uniforms::SamplerBehavior; +use glam::{Vec2}; use glium::{backend::Facade, implement_vertex, IndexBuffer, VertexBuffer}; use glium::index::PrimitiveType; -use gltf::mesh::util::ReadIndices; -use std::{fmt::Debug, path::Path}; #[derive(Copy, Clone)] pub struct Vertex { - pub position: [f32; 3], - pub normal: [f32; 3], + pub position: [f32; 3], + pub normal: [f32; 3], + pub tex_coords: [f32; 2], } -implement_vertex!(Vertex, position, normal); +implement_vertex!(Vertex, position, normal, tex_coords); pub struct Mesh { pub vbuf: VertexBuffer, pub ibuf: IndexBuffer, } -/// Load a glTF 2.0 file from disk and upload the first primitive to the GPU. -pub fn load_gltf(path: P, facade: &F) -> Result -where - P: AsRef + Debug, // `gltf::import` wants Debug for diagnostics :contentReference[oaicite:3]{index=3} - F: Facade + ?Sized, -{ - // -- parse the asset & bring buffer blobs into memory -- - let (doc, buffers, _images) = - gltf::import(path.as_ref()).context("failed to import glTF file")?; // :contentReference[oaicite:4]{index=4} - - // -- grab the very first mesh / primitive -- - let mesh = doc.meshes().next().context("glTF has no meshes")?; - let primitive = mesh.primitives().next().context("mesh has no primitives")?; - - // -- read vertex and index streams using the util::Reader helper -- - let reader = primitive.reader(|buf| Some(&buffers[buf.index()].0)); // Reader pattern :contentReference[oaicite:5]{index=5} - - let positions : Vec<[f32; 3]> = reader - .read_positions() - .context("primitive is missing POSITION attribute")? // POSITION is mandatory :contentReference[oaicite:6]{index=6} - .collect(); - - let normals : Vec<[f32; 3]> = reader - .read_normals() - .context("primitive is missing NORMAL attribute")? - .collect(); - - let indices : Vec = reader - .read_indices() - .context("primitive has no indices")? - .into_u32() - .collect(); // ReadIndices enum :contentReference[oaicite:7]{index=7} - - // -- interleave into our engine's Vertex struct -- - let vertices: Vec = positions - .into_iter() - .zip(normals.into_iter()) - .map(|(p, n)| Vertex { position: p, normal: n }) - .collect(); - - // -- immutable GPU buffers (fast path in glium) -- - let vbuf = VertexBuffer::immutable(facade, &vertices)?; // Immutable VBO :contentReference[oaicite:8]{index=8} - let ibuf = IndexBuffer ::immutable(facade, PrimitiveType::TrianglesList, &indices)?; - - Ok(Mesh { vbuf, ibuf }) +pub struct Material { + pub base_color: Option, + pub metallic_roughness: Option, + pub normal: Option, + pub occlusion: Option, + pub emissive: Option, + pub sampler: SamplerBehavior, + pub uv_offset: Vec2, + pub uv_scale: Vec2, + pub base_color_factor: [f32; 4], + pub emissive_factor: [f32; 3], + pub metal_factor: f32, + pub roughness_factor: f32, } -/// Create a unit cube (edge length = 2) with per-face normals. -pub fn cube(facade: &F) -> Result -where - F: Facade + ?Sized, -{ - // 24 unique vertices (4 per face) so that each face has a flat normal. - let vertices: [Vertex; 24] = [ - // Front (+Z) - Vertex { position: [-1.0, -1.0, 1.0], normal: [ 0.0, 0.0, 1.0] }, - Vertex { position: [ 1.0, -1.0, 1.0], normal: [ 0.0, 0.0, 1.0] }, - Vertex { position: [ 1.0, 1.0, 1.0], normal: [ 0.0, 0.0, 1.0] }, - Vertex { position: [-1.0, 1.0, 1.0], normal: [ 0.0, 0.0, 1.0] }, - - // Back (-Z) - Vertex { position: [ 1.0, -1.0, -1.0], normal: [ 0.0, 0.0, -1.0] }, - Vertex { position: [-1.0, -1.0, -1.0], normal: [ 0.0, 0.0, -1.0] }, - Vertex { position: [-1.0, 1.0, -1.0], normal: [ 0.0, 0.0, -1.0] }, - Vertex { position: [ 1.0, 1.0, -1.0], normal: [ 0.0, 0.0, -1.0] }, - - // Left (-X) - Vertex { position: [-1.0, -1.0, -1.0], normal: [-1.0, 0.0, 0.0] }, - Vertex { position: [-1.0, -1.0, 1.0], normal: [-1.0, 0.0, 0.0] }, - Vertex { position: [-1.0, 1.0, 1.0], normal: [-1.0, 0.0, 0.0] }, - Vertex { position: [-1.0, 1.0, -1.0], normal: [-1.0, 0.0, 0.0] }, - - // Right (+X) - Vertex { position: [ 1.0, -1.0, 1.0], normal: [ 1.0, 0.0, 0.0] }, - Vertex { position: [ 1.0, -1.0, -1.0], normal: [ 1.0, 0.0, 0.0] }, - Vertex { position: [ 1.0, 1.0, -1.0], normal: [ 1.0, 0.0, 0.0] }, - Vertex { position: [ 1.0, 1.0, 1.0], normal: [ 1.0, 0.0, 0.0] }, - - // Top (+Y) - Vertex { position: [-1.0, 1.0, 1.0], normal: [ 0.0, 1.0, 0.0] }, - Vertex { position: [ 1.0, 1.0, 1.0], normal: [ 0.0, 1.0, 0.0] }, - Vertex { position: [ 1.0, 1.0, -1.0], normal: [ 0.0, 1.0, 0.0] }, - Vertex { position: [-1.0, 1.0, -1.0], normal: [ 0.0, 1.0, 0.0] }, - - // Bottom (-Y) - Vertex { position: [-1.0, -1.0, -1.0], normal: [ 0.0, -1.0, 0.0] }, - Vertex { position: [ 1.0, -1.0, -1.0], normal: [ 0.0, -1.0, 0.0] }, - Vertex { position: [ 1.0, -1.0, 1.0], normal: [ 0.0, -1.0, 0.0] }, - Vertex { position: [-1.0, -1.0, 1.0], normal: [ 0.0, -1.0, 0.0] }, - ]; - - let mut indices: Vec = Vec::with_capacity(36); - for face in 0..6 { - let o = (face * 4) as u32; - indices.extend_from_slice(&[o, o + 1, o + 2, o, o + 2, o + 3]); +impl Default for Material { + fn default() -> Self { + Self { + base_color: None, + metallic_roughness: None, + normal: None, + occlusion: None, + emissive: None, + sampler: SamplerBehavior::default(), + uv_offset: Vec2::ZERO, + uv_scale: Vec2::ONE, + base_color_factor: [1.0; 4], + emissive_factor: [0.0; 3], + metal_factor: 1.0, + roughness_factor: 1.0, + } } - - let vbuf = VertexBuffer::immutable(facade, &vertices)?; - let ibuf = IndexBuffer::immutable(facade, PrimitiveType::TrianglesList, &indices)?; - - Ok(Mesh { vbuf, ibuf }) +} + +pub struct Model { + pub mesh: Mesh, + pub material: Material, } From 67f59139079578965f99bf50061a0ed59e001639 Mon Sep 17 00:00:00 2001 From: reo Date: Sun, 13 Jul 2025 19:57:16 +0300 Subject: [PATCH 15/89] Refactor ecs module to use the new structs The ecs module now uses the new model::Model struct instead of the previous Mesh struct. --- src/ecs.rs | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/src/ecs.rs b/src/ecs.rs index 8fc4ab8..a81c9e3 100644 --- a/src/ecs.rs +++ b/src/ecs.rs @@ -1,6 +1,7 @@ use glam::{Mat4, Quat, Vec3}; use hecs::{Entity, World}; -use crate::{render::GliumRenderer, model}; +use crate::render::GliumRenderer; +use crate::model::Model; /// This system joins the renderer and ECS, /// and provides tools to use them together @@ -15,16 +16,20 @@ impl ECSRenderer { Self { renderer, world } } - pub fn spawn_mesh(&mut self, mesh: model::Mesh, transform: Transform) -> Entity { - let mesh_id = self.renderer.meshes.len(); - self.renderer.meshes.push(mesh); - self.world.spawn((transform, MeshHandle(mesh_id))) + pub fn spawn_mesh(&mut self, model: Model, transform: Transform) -> Entity { + let model_id = self.renderer.models.len(); + self.renderer.models.push(model); + + self.world.spawn(( + transform, + ModelHandle(model_id), + )) } pub fn despawn_mesh(&mut self, entity: Entity) { - if let Ok(mesh_handle) = self.world.get::<&MeshHandle>(entity) { - if mesh_handle.0 < self.renderer.meshes.len() { - self.renderer.meshes.remove(mesh_handle.0); + if let Ok(model_handle) = self.world.get::<&ModelHandle>(entity) { + if model_handle.0 < self.renderer.models.len() { + self.renderer.models.remove(model_handle.0); } } let _ = self.world.despawn(entity); @@ -56,4 +61,4 @@ impl Transform { } #[derive(Clone)] -pub struct MeshHandle(pub usize); +pub struct ModelHandle(pub usize); From 0af4622525e04134c72adc3b9661db7dc73977cf Mon Sep 17 00:00:00 2001 From: reo Date: Sun, 13 Jul 2025 20:03:43 +0300 Subject: [PATCH 16/89] Add texture support to the renderer - Refactor to use the new model::Model struct - Implement blinn-phong shading - Add texture support for shaders --- resources/shaders/gl_solid_color.frag | 11 ----- resources/shaders/gl_solid_color.vert | 12 ----- resources/shaders/gl_textured.frag | 34 ++++++++++++++ resources/shaders/gl_textured.vert | 23 ++++++++++ src/render.rs | 66 +++++++++++++++++++++------ 5 files changed, 109 insertions(+), 37 deletions(-) delete mode 100644 resources/shaders/gl_solid_color.frag delete mode 100644 resources/shaders/gl_solid_color.vert create mode 100644 resources/shaders/gl_textured.frag create mode 100644 resources/shaders/gl_textured.vert diff --git a/resources/shaders/gl_solid_color.frag b/resources/shaders/gl_solid_color.frag deleted file mode 100644 index c3da69f..0000000 --- a/resources/shaders/gl_solid_color.frag +++ /dev/null @@ -1,11 +0,0 @@ -#version 330 core -in vec3 v_normal; -out vec4 color; -uniform vec3 light_dir; - -void main() { - float brightness = dot(normalize(v_normal), normalize(light_dir)); - vec3 dark_color = vec3(0.6, 0.0, 0.0); - vec3 regular_color = vec3(1.0, 0.0, 0.0); - color = vec4(mix(dark_color, regular_color, brightness), 1.0); -} diff --git a/resources/shaders/gl_solid_color.vert b/resources/shaders/gl_solid_color.vert deleted file mode 100644 index cc65b9f..0000000 --- a/resources/shaders/gl_solid_color.vert +++ /dev/null @@ -1,12 +0,0 @@ -#version 330 core -in vec3 position; -in vec3 normal; -uniform mat4 model; -uniform mat4 view; -uniform mat4 projection; -out vec3 v_normal; -void main() { - mat4 modelview = view * model; - v_normal = transpose(inverse(mat3(modelview))) * normal; - gl_Position = projection * modelview * vec4(position, 1.0); -} diff --git a/resources/shaders/gl_textured.frag b/resources/shaders/gl_textured.frag new file mode 100644 index 0000000..e0da565 --- /dev/null +++ b/resources/shaders/gl_textured.frag @@ -0,0 +1,34 @@ +#version 330 core + +in vec3 v_normal; +in vec2 v_tex; +in vec3 v_position; + +out vec4 frag_color; + +uniform vec3 u_light; +uniform sampler2D tex; +uniform vec3 color; // base colour factor (acts as solid colour when no texture) + +void main() { + // Combine base texture (or constant white) with colour factor supplied by CPU. + vec3 base_col = texture(tex, v_tex).rgb * color; + + vec3 ambient_color = base_col * 0.2; + vec3 diffuse_color = base_col * 0.6; + vec3 specular_color = vec3(1.0); + + // u_light is the direction **from the light towards the fragment**. + float diffuse = max(dot(normalize(v_normal), normalize(u_light)), 0.0); + + vec3 camera_dir = normalize(-v_position); + vec3 half_dir = normalize(normalize(u_light) + camera_dir); + float specular = pow(max(dot(half_dir, normalize(v_normal)), 0.0), 16.0); + + vec3 result = ambient_color + diffuse * diffuse_color + specular * specular_color; + + // Convert from linear to sRGB for display (approximate γ-correction) + result = pow(result, vec3(1.0 / 2.2)); + + frag_color = vec4(result, 1.0); +} \ No newline at end of file diff --git a/resources/shaders/gl_textured.vert b/resources/shaders/gl_textured.vert new file mode 100644 index 0000000..269c9d3 --- /dev/null +++ b/resources/shaders/gl_textured.vert @@ -0,0 +1,23 @@ +#version 330 core + +in vec3 position; +in vec3 normal; +in vec2 tex_coords; + +uniform mat4 model; +uniform mat4 view; +uniform mat4 projection; +uniform vec2 uv_offset; +uniform vec2 uv_scale; + +out vec3 v_normal; +out vec2 v_tex; +out vec3 v_position; + +void main() { + mat4 modelview = view * model; + v_normal = transpose(inverse(mat3(modelview))) * normal; + v_tex = tex_coords * uv_scale + uv_offset; + v_position = (modelview * vec4(position, 1.0)).xyz; + gl_Position = projection * modelview * vec4(position, 1.0); +} \ No newline at end of file diff --git a/src/render.rs b/src/render.rs index eca2710..80972a5 100644 --- a/src/render.rs +++ b/src/render.rs @@ -1,7 +1,9 @@ use crate::camera::Camera; -use crate::ecs::{MeshHandle, Transform}; -use crate::model::Mesh; +use crate::ecs::{ModelHandle, Transform}; +use crate::model::{Model}; +use glium::texture::{RawImage2d, SrgbTexture2d}; use glium::{uniform, Program, Surface}; +use glium::uniforms::{MinifySamplerFilter, MagnifySamplerFilter, SamplerWrapFunction}; use glam::Vec3; use hecs::World; use glium::glutin::surface::WindowSurface; @@ -9,16 +11,25 @@ use glium::glutin::surface::WindowSurface; pub struct GliumRenderer { display: glium::Display, program: Program, - pub meshes: Vec, + white_tex: SrgbTexture2d, + + pub models: Vec, + params: glium::DrawParameters<'static>, } impl GliumRenderer { pub fn new(display: glium::Display) -> anyhow::Result { - const VERT: &str = include_str!("../resources/shaders/gl_solid_color.vert"); - const FRAG: &str = include_str!("../resources/shaders/gl_solid_color.frag"); + const VERT_SRC: &str = include_str!("../resources/shaders/gl_textured.vert"); + const FRAG_SRC: &str = include_str!("../resources/shaders/gl_textured.frag"); - let program = Program::from_source(&display, VERT, FRAG, None)?; + let program = Program::from_source(&display, VERT_SRC, FRAG_SRC, None)?; + + let white_tex = { + let data = vec![255u8, 255u8, 255u8, 255u8]; + let raw = RawImage2d::from_raw_rgba(data, (1, 1)); + SrgbTexture2d::new(&display, raw)? + }; let params = glium::DrawParameters { depth: glium::Depth { @@ -29,7 +40,13 @@ impl GliumRenderer { .. Default::default() }; - Ok(Self { display, program, meshes: Vec::new(), params }) + Ok(Self { + display, + program, + white_tex, + models: Vec::new(), + params, + }) } fn draw_scene(&self, world: &World, target: &mut S) { @@ -41,20 +58,41 @@ impl GliumRenderer { } }; - let light_dir: Vec3 = Vec3::new(-1.0, -1.0, -1.0).normalize(); + // Direction from the light source (0,+Y) towards the scene. + let light_dir: Vec3 = Vec3::new(0.0, -1.0, 0.0).normalize(); + + for (_, (tr, mh)) in world.query::<(&Transform, &ModelHandle)>().iter() { + let model = &self.models[mh.0]; + let mesh = &model.mesh; + let mat = &model.material; + + let tex_ref: &SrgbTexture2d = mat.base_color.as_ref().unwrap_or(&self.white_tex); + + let mut sampler = tex_ref.sampled(); + sampler = sampler.wrap_function(SamplerWrapFunction::Repeat); + sampler = sampler.minify_filter(MinifySamplerFilter::Linear); + sampler = sampler.magnify_filter(MagnifySamplerFilter::Linear); + + let c = mat.base_color_factor; - for (_, (tr, mh)) in world.query::<(&Transform, &MeshHandle)>().iter() { - let mesh = &self.meshes[mh.0]; let uniforms = uniform! { model: tr.matrix().to_cols_array_2d(), view: cam.view().to_cols_array_2d(), projection: cam.projection().to_cols_array_2d(), - light_dir: [light_dir.x, light_dir.y, light_dir.z], + u_light: [light_dir.x, light_dir.y, light_dir.z], + tex: sampler, + color: [c[0], c[1], c[2]], + uv_offset: [mat.uv_offset.x, mat.uv_offset.y], + uv_scale: [mat.uv_scale.x, mat.uv_scale.y], }; - target - .draw(&mesh.vbuf, &mesh.ibuf, &self.program, &uniforms, &self.params) - .unwrap(); + target.draw( + &mesh.vbuf, + &mesh.ibuf, + &self.program, + &uniforms, + &self.params, + ).unwrap(); } } From a555f7f61e04eb5b5f81d278ed2b33a472347a67 Mon Sep 17 00:00:00 2001 From: reo Date: Sun, 13 Jul 2025 20:07:43 +0300 Subject: [PATCH 17/89] Add new tree and plane models --- assets_src/blender/plane.blend | Bin 0 -> 545163 bytes resources/models/Grass Texture 1.png | Bin 0 -> 2688 bytes resources/models/plane.bin | Bin 0 -> 140 bytes resources/models/plane.gltf | 160 +++++++++++++++++++++++++++ resources/models/tree.bin | Bin 0 -> 13584 bytes resources/models/tree.gltf | 140 +++++++++++++++++++++++ resources/models/tree_texture.png | Bin 0 -> 845 bytes resources/textures/grass.png | Bin 0 -> 2688 bytes 8 files changed, 300 insertions(+) create mode 100644 assets_src/blender/plane.blend create mode 100644 resources/models/Grass Texture 1.png create mode 100644 resources/models/plane.bin create mode 100644 resources/models/plane.gltf create mode 100644 resources/models/tree.bin create mode 100644 resources/models/tree.gltf create mode 100644 resources/models/tree_texture.png create mode 100644 resources/textures/grass.png diff --git a/assets_src/blender/plane.blend b/assets_src/blender/plane.blend new file mode 100644 index 0000000000000000000000000000000000000000..535b755a5be52f0cc19c86ac62c90b8b7c15f6eb GIT binary patch literal 545163 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

Z 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 A3jhEB literal 0 HcmV?d00001 diff --git a/resources/models/tree.gltf b/resources/models/tree.gltf new file mode 100644 index 0000000..51bf9ed --- /dev/null +++ b/resources/models/tree.gltf @@ -0,0 +1,140 @@ +{ + "asset":{ + "generator":"Khronos glTF Blender I/O v4.4.56", + "version":"2.0" + }, + "scene":0, + "scenes":[ + { + "name":"Scene", + "nodes":[ + 0 + ] + } + ], + "nodes":[ + { + "mesh":0, + "name":"tree01", + "scale":[ + 0.009999999776482582, + 0.009999999776482582, + 0.009999999776482582 + ] + } + ], + "materials":[ + { + "name":"Mat", + "pbrMetallicRoughness":{ + "baseColorTexture":{ + "index":0 + }, + "metallicFactor":0 + } + } + ], + "meshes":[ + { + "name":"tree01_1", + "primitives":[ + { + "attributes":{ + "POSITION":0, + "NORMAL":1, + "TEXCOORD_0":2 + }, + "indices":3, + "material":0 + } + ] + } + ], + "textures":[ + { + "sampler":0, + "source":0 + } + ], + "images":[ + { + "mimeType":"image/png", + "name":"tree_texture", + "uri":"tree_texture.png" + } + ], + "accessors":[ + { + "bufferView":0, + "componentType":5126, + "count":395, + "max":[ + 123.4296646118164, + 509.0864562988281, + 168.36563110351562 + ], + "min":[ + -184.9799346923828, + 0, + -155.37196350097656 + ], + "type":"VEC3" + }, + { + "bufferView":1, + "componentType":5126, + "count":395, + "type":"VEC3" + }, + { + "bufferView":2, + "componentType":5126, + "count":395, + "type":"VEC2" + }, + { + "bufferView":3, + "componentType":5123, + "count":471, + "type":"SCALAR" + } + ], + "bufferViews":[ + { + "buffer":0, + "byteLength":4740, + "byteOffset":0, + "target":34962 + }, + { + "buffer":0, + "byteLength":4740, + "byteOffset":4740, + "target":34962 + }, + { + "buffer":0, + "byteLength":3160, + "byteOffset":9480, + "target":34962 + }, + { + "buffer":0, + "byteLength":942, + "byteOffset":12640, + "target":34963 + } + ], + "samplers":[ + { + "magFilter":9729, + "minFilter":9987 + } + ], + "buffers":[ + { + "byteLength":13584, + "uri":"tree.bin" + } + ] +} diff --git a/resources/models/tree_texture.png b/resources/models/tree_texture.png new file mode 100644 index 0000000000000000000000000000000000000000..f5726d41ea881c58cf74e16442f6e7856ad98742 GIT binary patch literal 845 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 Date: Sun, 13 Jul 2025 20:07:58 +0300 Subject: [PATCH 18/89] Add model attribution to README --- readme.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 readme.md diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..f1458ae --- /dev/null +++ b/readme.md @@ -0,0 +1,3 @@ +## Attributions + +- [Tree](./resources/models/tree.gltf) by "Poly by Google" [CC-BY] (https://creativecommons.org/licenses/by/3.0/) via [Poly Pizza](https://poly.pizza/m/6pwiq7hSrHr) \ No newline at end of file From f6a9d18c5c82bec08c5db460b3a5a4b846bbf1f7 Mon Sep 17 00:00:00 2001 From: reo Date: Sun, 13 Jul 2025 20:08:16 +0300 Subject: [PATCH 19/89] Refactor main.rs to use the new rendering features --- src/main.rs | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/src/main.rs b/src/main.rs index 5b45c33..1a92617 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,13 +1,14 @@ mod camera; mod ecs; mod model; +mod gltf_loader; mod render; mod time; mod ui; use anyhow::Result; use camera::Camera; -use ecs::{MeshHandle, Transform}; +use ecs::{Transform}; use glam::{Quat, Vec3, EulerRot}; use glium::backend::glutin::SimpleWindowBuilder; use render::GliumRenderer; @@ -35,11 +36,20 @@ fn main() -> Result<()> { let mut time = time::Time::new(); let object_ent = { - let mesh = model::load_gltf("resources/models/monkey.gltf", &display)?; - ecsr.spawn_mesh(mesh, Transform { - translation: Vec3::ZERO, + let model_3d = gltf_loader::load_gltf("resources/models/tree.gltf", &display)?; + ecsr.spawn_mesh(model_3d, Transform { + translation: Vec3::new(0.0, -2.5, -5.0), rotation: Quat::IDENTITY, - scale: Vec3::ONE, + scale: Vec3::new(0.01, 0.01, 0.01), + }) + }; + + let ground_ent = { + let model_3d = gltf_loader::load_gltf("resources/models/plane.gltf", &display)?; + ecsr.spawn_mesh(model_3d, Transform { + translation: Vec3::new(0.0, -1.5, 0.0), + rotation: Quat::IDENTITY, + scale: Vec3::new(1.0, 1.0, 1.0), }) }; From f943e4c9452244abd237fe0afad40add226fc3fe Mon Sep 17 00:00:00 2001 From: reo Date: Tue, 15 Jul 2025 01:27:50 +0300 Subject: [PATCH 20/89] Add skybox rendering support --- resources/shaders/skybox.frag | 22 ++++++++++++ resources/shaders/skybox.vert | 15 ++++++++ resources/skyboxes/sky_24_2k.png | Bin 0 -> 1218704 bytes src/render.rs | 59 +++++++++++++++++++++++++++++-- 4 files changed, 93 insertions(+), 3 deletions(-) create mode 100644 resources/shaders/skybox.frag create mode 100644 resources/shaders/skybox.vert create mode 100644 resources/skyboxes/sky_24_2k.png diff --git a/resources/shaders/skybox.frag b/resources/shaders/skybox.frag new file mode 100644 index 0000000..4ad6a8c --- /dev/null +++ b/resources/shaders/skybox.frag @@ -0,0 +1,22 @@ +#version 330 core + +in vec3 direction; + +out vec4 frag_color; + +uniform sampler2D equirect; + +const vec2 inv_atan = vec2(0.15915494309, 0.31830988618); + +vec2 sample_spherical_map(vec3 v) { + vec2 uv = vec2(atan(v.z, v.x), asin(v.y)); + uv *= inv_atan; + uv += 0.5; + return uv; +} + +void main() { + vec2 uv = sample_spherical_map(normalize(direction)); + vec3 color = texture(equirect, uv).rgb; + frag_color = vec4(color, 1.0); +} \ No newline at end of file diff --git a/resources/shaders/skybox.vert b/resources/shaders/skybox.vert new file mode 100644 index 0000000..fe5ce38 --- /dev/null +++ b/resources/shaders/skybox.vert @@ -0,0 +1,15 @@ +#version 330 core + +in vec3 position; + +uniform mat4 view; + +uniform mat4 projection; + +out vec3 direction; + +void main() { + direction = position; + vec4 pos = projection * view * vec4(position, 1.0); + gl_Position = pos.xyww; +} \ No newline at end of file diff --git a/resources/skyboxes/sky_24_2k.png b/resources/skyboxes/sky_24_2k.png new file mode 100644 index 0000000000000000000000000000000000000000..ac2d556ff3a571c32945cb1e18495b1d590420d3 GIT binary patch literal 1218704 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 z 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 YUx** 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

!-Tw6 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%0D3ma+Tj20{Clcupnem#xUy%k81u#Dew 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%0D8$uDoS@$UOSL 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�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 vQR?gz?iB&!W&ti5<8Yu1SQ4 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


`~hHp(SXGapr8=9HT zpu!>-$?)pucPM_^{hJcqm)8RF(A3H${H{6*f>Nha1OF`Tki5pH!ztkqUjJ#3w+Z#q zwLii83G=%IVoy+c-dfWEA!qU)->qTSMn%Rp7AF^-jN+9m*19mGB6(Q zV2U=1rYLI_sx`OKzliFWG3&LmeO!}9T$Jej3`Z0r*TL?V@={*_40{Z>ZP=!mqpVJ8 zm4~Hpopan;uO(S*YH#CvMLu>BpOG(pF})NEe+*kXS8!f#lY1Y~wr6s^);SbtrG6JZ zPBME5YmfRU?caJip2ftSQULmo5jN*^maBUUc~jtygjg|8-0qq8;el&BKVjP4$4Hx( z!=f-MDYU&uh6=Fmm*QpWX&>3v`xXFO?*QZ6pbi9QFW3920V&|ufB*BZzB`Frxd4FU zyCIF=8z*3;Hc>w96Io$y`%8gtqUg&>Br`WespS zWcChQ%$yBEWZ1Zn27xOK?4Pba`)BU!*iY1i;il4FSmz{mp^G--Qh*HTMrf>TQH!LM zj*GALDY3%7#jGKw$)OrOsPe}n&CuSaw-SnIzEB%nvv4sX;qpm$xasgJLzA(?YGS<< z9!?DVNc3_}J)oz ztM1)(05x0O#;)ejZ1d|xVOWZ7;JI08}eMA5<&3P-;VGgTs=KLh8_>HlWbYJwj zDE3WV$`6{hV!#^5+!$oz+Uv8jBM4Z-Ct|*;Zyw@nlBUOOZZJ|vT4dJgI~N%Py%dPj z5CYJk=^m{KA<(3kC{Y21(vQOh2sBdnSU1xWw@faInoG86>6seEIbo#DqRv~bXuZwE zN#jBWQukh|Qf0uVYlukHm^_595~TkYwv`|!-+=kBkxx?5j<)S!fuE;C?D&%^} zM}jB}TK*6yGZ8fZTWU=qf#&;zDt@Kgj#oA4Q+1~yC&DQ(=#!ZM$(xBr36%lNX>$@> zw7p^)3$5#m5N>h~WIkPFWQ1oo*3G40>%FY*S|LP`^97qHH)ZNFP$O!d1(1oO?gCn% zL@7;(^?jzCh^srZi*=$<-Sqplx@>biunz4YgrtWxA-y`e3t_fy9+rCW3(dM|tRh4% zgS}~x)u1F-Z&DcFTu3}kf!R7Tl1n!`K?ifV$RZ}%*=$|Fv z!`eH&23s!`?Sa$+q3h;j9t3p>IfxnXX;qs<{V=b*Y9x7pwc8SuFaRS3rnI!Nd#URa z8QzuyQ~BkG<1YA|mD{LIj{&rJNJb@=!UtD($W*vl2i8%ntozyY?Jl-|g>>O6CiH8`&-F$~%)W(zK(iix5ARll~2Q&Z#}*P4FHC@ufd+Tuk1@zU;lL9Yffs z&Q|#dKM}Ud4E%55Dl41%GVznL?ORqEQ>>uR(~G#Qc`zQ}ZOn|C?4^DEqp3Vx!PC^5hsh2@!reAw`_L0scJ(`O!}r|x&06*AmkQop}Sri zxR$OoON=>!O8VO3T70M?ZA**X8G@{7Pyvugo1+Lsln_8cwFX(c5D^GW{j_`^fC54J zb&0|DB>)7%RCvWx9kK~x(C4#}F&-#dFD{0HM4%BXYS!pRzi8!_4hrhd5StoV;yLMy z!F_OXX@2De(aKbev}vzxQdc&94&8guf0$eyFAzr$PmB*u@?g6^$Gj1gx0R@g1O3lh zaKdAhO=*u)_2~V{G;Z+_8jkl|4tH(RhVGq=oWL*TZ#nZPm_(L70YIPUPZAc(jJmqI zc9(}3ZTLnQL?5iwB(goEvQ5(xn0*T*b#L+1>fEw;(&V8(NQUcDv!|?lW9%%iTTg^- z*LboYytP_%t^w{%-4E5YkR`ctH@70Pn=?Qd`duNKq%QwqcK3plIO(k%Vz#CPZe{M@ zce2=M9=4?69iIo9l{88+F)jn>Y7~8tTBLy^0Y&S*d2EVWNI6suFJ^u!o5$K^TWwY^ zi#5Cs=EZ^6m-Ax82I;r%5#e;ND6#iaA%mW}#l0Tbk8tc~)+dgaHs#rMxwuidrFA>+=t9=boJ{cQfxg5@aw<+_}|u){hg$(gp7CRX^a3t zwhu8SA+Z$<{c+Zj;frX9Yk{iMr_Ag`aj+YoD>vngV1S9n7ULQNfGTz5_u7q9$!@tymX@x8Wbaliged=)d-`j{dOJ!r;N^F{B246z2i@|_u z4xmf@4${MG?f52%ZDIM~@J~|c>VE@AkiLt5DcJbmboi-1uaNEx3ppYjsf(D>AZJQ9x=LV~P00;#@Op^dcfKbOUC)_j@sPjw zvM`qBPc$Ee%rY0^2bQalL{@~G$X&@pf{E;Y=tiBh1}oN2J*p_WXOoOQ*u@V%hU9FdoG& zwV%zIMIog7Uu=2PhwkQ(RRq}ajrIxN2W5l!#4tv^)Ns8iTo`noz^>MIZxty?DnNiS zCj%jFcMab6IG0u7;JWRmK9r6JlBUzz9I_$z$$WHdqc9l$n#60P z3_>0UXV0g*LI~)2dCzp*R3eT+iTBGXViOn-^%Ym8-hR0=>?=Wk@{|#?3Au=o9+_t^ zV+xok&eg)ipDqM=@U2-}qj2Gu@zzID1eXKvNR})%PmDzPG^fHNU*;Flm+-?&Nom&( zjzIwA*MI%_zsGQ*47DCod%(&xi^BYDq2RJ6PK!r&ko7Ajn;sXgIK@s;IifC|dnBEZ z@#jDcqpC!GJ}F6$mxbZ20DwVMvWyq`=VxI$-%VZt2wI3E~vf4-EczTO;og0GSMQEkdgFJ(e-p_%b%&e2&G#Tz`S3EKee zwaFL&`0O?!D?S)?meWzotUJ`~_DoZA{yf_KVRSBKok{T(3?&a)UkU*ZzEQc9yJ=Hi zz+;dPpAF{Cn|ZJEg-?R_AbjT+HuiV=PjCriiTj-cCh>q%rFS@|gAb9G?n zfI6E4a=tgymE2md(KG^?h3$_%4dX?h!LXz{dV{O&wi(-6|*~b zD+kz-8RL56J@D7n>Py}%bKC$(+0<)YSF&L4gn*KuG#fgBF#hwLsLvtHUybzOf? zJ)@d-8zq;xQ3hr`)~p5~)hnW7rr$tu9vWmy0oL`R?4@{v=w?JUZK;(q6#x$rfpwN)t|yCwjh8#bQ*pcz+F!CwMcTOl&kg{ zjlr8DqhDrkBe^EqWz#gFuTalq&O(!H+gt2#6?h_-Ic3XsJtzle7ih-_POjMKH)Uc7 zw>vut1`K)&S=WMVS~<%0_Wd^XE|=jq#7EQa?|FTGW1tDhF@75|0Ki~3Es#`u>xDeu zjFDsM>K$==v2MqtTBpL7tx=Hv*+x!eS6D-nwp6=sX>Uj~_ja7wiCtNH73G#8h(it5BHyjmrR+ zhc!YK4K44*oHf1M4WCtu;6m0c>Rw7s;~ep}#c*va5}*9{W0!K;*-|hDZq^s^k$g=l zo6I?b_d#4b?y0mhI{qw(A#3j$o}07S>kNq4`Q4P?np&%IYJWf%&|&L$c4{$P*>mx` zj=fvt?6Myj`dz;p|E)}#HD6xF>smV4KJRdsl4=a>^V=-x+PKN+6S=?d#G_h*gMTZ` z@|X=C=r84NSO;rzZE;lnz)Bz=ReC8eT5VcyaHJr&IWf79Oh`g+( zSiCDf@(|3XR)Bz7FNMt9OS!&@+jK*iCk?xYsqMBpr`@`-Mw1s2+F4t%pqv{^Y?&lg zyyV>_R;^b_9wnx@8_cP9vI?&Ce1+n%d=%W4vqc*vs1*?cH3w$G_kRT9aZH-71 zTA5c%WR}$y2c0Mvp3pJPLj~;-HUe%b-@%pIo>jEOJ(Q2XFH|$qMi!06X74GXZ{Xqq z&$9vzzYNb&9B}&RBSv5*fpmDa?>7s0)k;fVQ~!3aPbUHTyw+A3MGPBu^W?Sug8XeV zKV8NbG*f1P+gT#i5bwO1n8rx%e!nAqwsHz(~_6b6m_;YVHES zQ>QU6Z@vXUR?eLxdnp>xo*FvSck6U@H19L7ljW&&Y2lr~Vd;R058$A0LTtnV=7D3o z6%5MXvv&_^B|n$6aYp3smd<->cq?l%1X~=A$+Y)7%jHn@P%My)vf3(l#xOD#5_uUK z1G~2QQuoo(ehHA5X|$*0MlU;3LoqhTpFiEPVS=52eknb`Lw5PC-Y&~;_If%ns@K-9 z;O3$l<~2aQNoc_vc{FaFS*;`zV9!DAR$-~jQO*<@<4;GXv~GKB(v%mCV5N}k$gEE;^SY02%Fd5y zJ=f%N`+q`uJUYzamSDmbLcM zoDe9IpJ(xla$&446px{OOSuWlhfgW@0VA@KMeMN`yR4+V=WD?_yB>beg=vFr>?@So(W#`YmeIryEZ2s?v`jF0~GyqZ`a$ z%Gq=o9K9{B6yUM5*v4)fjByz#Xf`fb3YEsQwS%qJ*M?J|H{L>usD#Qn;l*gDjM-T| ztgu!?1({o!y<>psk&2@ze{Us8I6RU9UQ0`69YV2Qy%|y;LUSp!u9m{*@;!|d%&)vw zO3YSWdp0F9N}@!8m`7lkY;~ogZA4RkIxSjV3loS0R(&xlw4eG3LxDEdkPjEi3J?ff z>CN2pXb{OVwF1=JZU2|0209RR`1wv>H(;>L0DC}$zn+6H>|tr!G+c^S_&?Ho6mq4R z=9IlWi~0unq{B1*k`(vrFEAeo5@S|V0Z&(arP2%1Y#M?ZwE$vweA8ssdBtBTzajJW z@+==EAc*7gL~gt^Cy;n%x$E{pAI#xaYtn@|46YHf>j9DrkT|tj`K9C(LYO0L8Mg1~ zLa=2gN;udeC6#%yaf!UTXyu-i?pZRimL|+5&+&L@0%%P%{MmYuS^iIgw>?+@;BebU zBF@Tl_O2KRWo|#vIu$ne{+k0Hg_$z&sMGE=Td1WcGVx^Hi^!}u6JhY6&pdWT$Xe5)&Lh5!j ze_k>V44-v=x?DckrtY&vo#q1Lt$FEpN^6`-YJJ(I8e$PD`SN!y2LRWuACzgJc_3tekuQBhebz6eMTvX*>%7aM%i=h3y4e5F+08rc>V1CQN?I5E&|||VKVf`;(r1;a=huOql<`b(mXaK|rtiAGdf}Nq zmgK9dw$ILWm-a>Z+K?ZY7qJ~5_ji8Re%|Z#u_p`Y7!}u$?7*0Q1i#3fOYf z*~L~*K8IWOvqy`l(U3p#ahbT%2EXE1B(O11#xV9u|Q9 z`@Y%!I7Si>@)GW zJ^ZxXJSqG@ua8ZG<_ez}-^({$zmVzOT{p~|z>fqCv%+t8$s+421$x#01M)MtK8&90wW3ua}EBs=RPw4z7l$XrjPrI%{qdEnRyfZlxk20-7HPup2b;#>}6;{`tpWJ1z;Y&ZJ-tPdqSm%Fl~G6#1a6 zT9+K$iBBjZ3AsPPNr%=(6wf={FU0L|lW=so zt9>sc)ovEQbAl^);q=%dxj^ym{oZ={J$TUbGj!edhEMvPjbC@|1NQ?YiQ;PqL!!T5 z_B*O~@CT*ex9y!ysk=L*ZjiqV*r)OakFomD|BKune!<^Tl5lF_P@y7c};Jnl|f`)45utQ5RwmB$* zHC5^y8WhCaDdI9}o(ksQbMah>g@kGyDA;ffxvm1Zj!q}a>L_CSIimqrWLLCZ3Cs3u z7vyH)6^ip*lgyL#OAQ0)vUiN=JZ=WLoTA26cnTetk(UFG%i^`YFxv@s zh*9%)+MZk5ruy1z`^=&!$M1Z6eaW-JZxWs{(F973M;TaI8Np~)K{hq1nY)LMZys)N zA&bfv)mMfPZ5;LKEtCUkzT#Auu)JZ%KwKVnBs}5iK2_?dH2V8N%g?JI?RQ6h{qrCF z0YLB1?4`%Cc{5~q6TRQuWjTWQLUSvDwT^S{;BRwdmt5*~;yoV>mTwf>JQFwV-b)d` zGNw&!WP-SudF6a^T}Xz^W8{gl=b)S4tnNOQr*XgScv`tS$k7@{>w1UttARO|JgHTy zyQq?x^-)5Uc8?zb2A~lE220fv9|Ek~-7~exJpgKeghV_WG<(^a86Y`PRwtLBlq8(YPwx5BGz7 zf5M_nb_;(j-yc-^d3ib7N@RzQZ?W_s0gN7200z(x{g4=^z&raP(D&|M37#cvP-F{p z?dv1*5##DKXpgb3jLLB`mbw)qTVJo21bs%(4*`$}}j_B5WWpg&LR%vHb;j67p46-vr)5R=@`}!)GnF zzj>KThK2!#5=6k2p1gXC%=>H|5_XXN`J>nRF&YrM_w}#9c@9%?TOKW~| zEXbmXWkI*58?~f8ke&CrBOv##?dl0g)s_=LVc(lg>ta=+Bm+=~H>9Hd;JT2&x@DWa z5WTIyqtZa&K2l-FySB~UmXaa}xhI$)L)9uD!|XyZ2BP}Xqz_85ZmvL}L`pyi)Bmaj zsu(13t2gFuk6i%?=iN~3T776=UTHY|+XU#;yBeVuwb zX8jrt|G$?f%J&B&y+kp!DSR^>W9=5!cU*h@Yn6 z9eK;r9qfObgjn^Fd`>rh)u7oNykG?Z z(IP4PICA#4z4(dp2UFmQD7e%6h38_ z*w&DEzTCtzn{F)YEwfTAWdD!Fn)MG5EZAbL~P8+&Z*5T%y^VCC*kt_`!+}=hcl6Of8uUYBrJl%El64&Y#X0$v~U%T)z zf%X#5O~1?a@;KHT=4U0In=WOWygw-E(}|87NrLO|3zzAl_%!+eXUdqeti1Onw2;2{ z|JvOsC;v^29|>5n{S4c4#(6KFGlMlI zZ6_Prokj&03*7$h@NDs0695Dcoi=DqYdJoYbi-^(65NkZ$js?Vp84Z0!*7m1SshwT zf!AKDFLPR%UB9y5@cT9 zM5VGYK#345{UB>8JaThO*H6j>*aj)nR}aXsn3y_rne~KL!sUu1sqwn)A4*X<# z@%9%@DP>iZ>?n9$BSNan~)#{p^Abu#O9q8xNKmw`zf;<4c_(;p9V`9-VFme8TY zFDM}N!-MVwYif!R$NWmOuOYe*ePNU)76dWyf^Ggz2uO*II)>94#7aG$U3@6D2(~HxcA!?eJ^8rAy2s>%A^^Jc1@p$( zblOH#svb(TS@jbzcSM%nT z?ulf2k;von{AQRg{U`y=OgsM30RYA95OCLAP&9{i2567FjcJzD^=Qeo(Kjr9-ce2B z!E&^$qY>WSk|J`Lzl5uPtuY=*ej4Q$xb^rI_?g#Pzm)Fc!|j(l?M>D~7+fS=OHa8j z38V6owg!kR@a{0q6$a}Lr+>ax;}M#tHJVOOEB>c>6Y$)a<)akAw+Z;6Twyb(W}vO3 zkPrTR@Awn*+7k6xd*<3AJG!2eYtI19UAvrXcg_ZA_n1pPvz-TFpr*`N~B&@ImpHd-#Q*`DkZb5}qz`h{)b zd+cjL=EI}+>kuR+&{u*N%;u|&rd%fzIWZ?=!^ASp<~6gXkv5}bHVgt4LW4lmFgeZ1 zE@1hfO5{}yO0STYu4<&vxKY*aAPN41-2jtJF4K}WX zexfmy4R*|KFu7*b33$(->o9b&M4Tc|#DLiTPIxeCK_j?1W#p6rSIH-Gt{JiZnUk(< zU8?tsoTJ(fdBM6|7HorlT=q>TVar5)Hdn8c{rX7h{CUjn$w$=gxCl=Am)5sSj&;$r z;!(nhY(8Cbz>B?QQ4%bqVlA5jVAPCgaEYR0q!@>(0z_GtxGF&?G}*Fu6oBpNQKQ=< zty<>+dnpEiHIb4h9e!MpPaw*OXo{T(rEmkHCT@ zk#x#caVVc;N+;OQZ8M@mopRbndLQ&L;~RZcBr0{+I#>^=iQBZU>M}VF?0{zboDI`6 zpCIM0@MuntP0+htU&4KK3-4RmYTn?yaVeD6j zefekV_6@{2kqxc?*@-?bO|IL;HVTP8121YVgzIVIvi*b;>8wdNgew$H-D4+fNW%vx z)W+FE>^gU7w@p$)R_HDnkd^hi_V81l$K>;YB@r+}wR8jXn{v688&INayb2T0Mzk26 zpXHiUHhD`UVBS)QIj~O$tIsjol-9 zfn|pxHm%=Egayr9fyPy zbEv&P(eZ;;f9LYIF&~hvEv7>N%I}3VnY!Ttu%`m$dj5F}*EaeK9kbJFkE(SE^nIQr zVGOD+xgQ{yM}@O^T2afmWFPA#cze$PWQ;AtkeXhn`ARzq~erAjIIj}-| zg&}IpJ83}L9vNk;Jz8@u%+=f@@`RwLswNY>vBdZzQ}~R5nhf<>L)-Tvd3YHCpq<#_ ziip+3Z5=C!Shre{JOLPioPN3=hqb#-_$?aBnFh8tJh1U(MPSis}JY+(BYfNN@7 ziD!32J2G0cOrQ=p@)uWhwR=@eYP+2x2pvmv-)5LgzA(2gl3QOuBJ!n{M&IBmNJ_hG zEyB(biQaC5Rj*1K?J(}4+TL$1lATJ zBv`!%K@gggCC?KBS}z9Wza@XYwXl3rtxb)?*Z_rSZmyO{b4LQ)JDmcfDHr5tHQnIA zOXRs=z-{vxm)afP+xLU8Mm?gj>0oQxg}0Dqs|K_QShN0A&j+1FmhLFD}k%q|D<)(fzCa_-fx2NDtYgcIAu1kRC# zv|viOD%M~b9YrX4KlPYqT~~3o)};Wy{`kkgKvfGYq;6tFmN)O*bjrlh$D?nbLxf)>8 zEEmN9P|FwTAl3OaGlbPh*vA8;9$bg9ensH9*h=li8jR_-m62twJ7y4U{~^hGR=!#x z0A2sL+pE(nI=cLnocGDH5{)8J(pyYMzucm(yviuuO{wcK@jd8xzbsqtrIO|=Y)$HP zp{y+Mw_qQc?CjJx?$#aVcTxR9shh~h(q!&nuVqna&e_ogEp#%5@lJ~lxmf^AvsIMTw0<=+j49b z^Vz(;tL$(|IeTeA-XTdSFLc1vf+>BBQNTYUhPX ztRq4W>z*`xRbIbh+&1L`xmADR`fUur4a0?N^FtWJCXboA5A^G0#GPt)G*E|Z!01A>mUF4tF*zEE}~DN zO}8Nv;r=dsgP^&rl^a(8OT&XEMFoV!-gPS5x(ER5&qKNb7r$exuj~CHI!!8aS(ye% zAF?wvpUSd=&u}4jUPpe|nleqfh?+C=N%Lm*##_~B0#0~tX&@-(QSXDC^=70Q5`y)J ze6V#&1h-d>Tx3mJxGu3zj(QqmL^>u6f?AS|(E7S)09t*9^yw2bLI|FHwGcgu9wtt+ z3yh<&ciQsCSMhnwz$O=<+3^9QDWmITrZulx7xxxRKKN&p^+b4+GiLh-_$sJ3c%t4@ z&=uqyBX7uIX}^qn7mq_W5m#RwJeOoB&0SA=5=k3_?*ZO?Wk|kDmnEvBOYcuw9p!z5 zobu!J-w-i_?akPK7ksqf2A$(w$ymhO)C<%63w*DYq`*;vmU2HqhHaCefkrJoo8%Q9 zCOydYcRMFRmfm-Td6D(jt$q_yuY9WZ_L9Dkbt%}x!=FmZjl z*tT)hqLDzA#j%)k+fs|&_LiOiG3R$xLr9Av)dR^M1G?-v*nq3M0CNvgVIYuibxXwB zM@5hX1U%jvyn=wS`uzy`q@*cbO>Gn^z_vB_=wu)|!u@w%POnB_^z%E2U-eTAt-rRn|Bl3`N$PCoWGJ)QI7#Z_ax_5NI zL`F`;bW*~`dx~qaD*sG=sG0xA+@f>8m@{{uiFRtmA1 z9kj_M5oo*9lBQII)GeFRzFAHSxeAqq36=@9Rk+Q=)73y{p2+fSkZy>%gWW?b*pzM3 zt{Oq>V2+u6(2{l(olJ)&W%7llnlmI8lkIc&+S#^;)Pktt4^Rk6rKf(MBn>!dqAQ=t ziuA*S+sRF2!Q$Cj1l#PlVKG{!MA3bLONS3Vn-v2;;YoSmi`H|A?`9U+|rn#x79FhYdHl>43CW7^&|0$#s7fksf8f$r*3{i8bnK?ir z7|ZcyUi6;;y4|c4OC%LAYfbEPzFQ0L6OEjrj_xX_r^8QKW;zI#z@SE@)W|<0G|GXo zRYphaqA?qoZKj~xsuFuIrx6>N%74jHW4+tjDkt|bcJd86)xOi~)6V`RWH7U(s zL(1TBZ7WjD4?xzo@LkB5Z!(n(dFWbLEvA)`e9h(suD>I9Z1Uxn2NFuiji4gUDfNzz zAJQMK8=Ux#xwTf#fT>SW7(^6}5P3*iq*3!P;@+c>^zO*2=h%mErrA#Uh>UjFCyef( zG~UhxyUdmoUVAUZz-YcZ&n|z)C&W!!2bVr+OcJl?UJ{Z*h^zpvCB%J|T@G`d(g2s^ zej!vUVFZY!O8_fZMnpvfmFbuEQs=Tk^P8Ql6S&Elo4#rdHRjfNU^=f22UBh2-aA z=waNIIl6vqI;`mP;bs+0$J`mKZS-4X86r`WTL7AwR$nlsn2YmPso z3&1M2ItX5(ic@8XgK?GY;*q9F3#gHC*DcnL;gg)IhhPrFBF@#m3zt&TM{Q%nT<8O+ zaa?mg6{?T3?GehdAF*5%H`n|pAEr6Z1R2TeD=ShwOS=C`%VXzwXh$^W`M)r-ckhi*$Ci(ENFuHvv* zq7-gxPB$f}6N(OPTpppsb<+sSW`sGxSi4ZVB11nR=2AGapUW3HQ#Mh{v6s;=$3?Ju z5mh51l@J9(sVsnjEg9IN<>)29d;RcTd>RO#m7dnT>tk6bKwdNN5^ip#&g8Z*P4osz ztiFX>LW{A4fNd+hh72eht0}+8p@}eZ#3aD>I+5uY3{!(+;{+^JK5eKCQjnf3Ynyri z&;kgMJk^UQdQ&Svu!Um!(~5CF6q_gS#_`ND<{7xcrd3e9P^M%C8A1yTVV|0}qFmOv z29}U#3I93#6Ebd1pD@uT*aHm>IYBNN<5Q2X$R+m^WN`3%|lcsQ2O#8^GaDkyOSkv~?wxz^#jil=!5TvNlMIt!$3R zYzg+1bpvHh|Eu9cji%UK`Za$zm>z}#r`%-9*>722ertg}UT9dFc&el?_JCPJ z7G{+eQ@$yT|XR=f)5Z3EN2z(Majhv(6k}#aj zZ|S)<3?WC?F8^0kCXEp6lmX7ZY)-hqOCqhVh}LBrVjp~1CGwSpp<^3@U;po9dEF2fe-5VLdXlm18=kf;Ho$J74XrvOVNh1 z>M_eCBbv05A3?sjw^&wpk#Rov0(*UiMfF$)T*9UlXjG#i;TyL<(DcZFyqLcIP`ai2 z_Vzi$@EvSwzlQpwe|`^UMDgApc&O6PhEK@{|`PGh0eyJZ+)oi#)>var3C$lzKYNP=j0Z1I%q=$|13&~{MKCR(ZC zRn#ngNA_3>x{|*ODK*-(`!S@D-&W;`@wWvQd@tdktO>HpmWV-6We)2p>O7Ku((T`a zys6nYHdg5VwES=dZys9;Zmu{DvHcqYAGB)b1Y+;jN;nrV|4OAa>p%nYSAY;S|4WdC zG08HckxMR6Q>p@@o&`kig@Pp@)0bd`$uCfuhn{)(uEeVNum?K=I|!^5YuQm_^~Bi5 z1^IT%m&;a;U=!@`m)^yD>sD-^)biBV?{dO&#VC;ya_IpfQpmCBn8SK=S1yIC*Oyei zHyuhf>>>&-K8a$}#?hDN)!V*ar=KI*WwY+Kz6;y)sgLyV=napit)q*;_zKhISuacV zxcZr#h3WbpEXU*MFD_TS^z;JpksXX<{$6P2v|5*OXZh%vj|5lDXR;842wE_wzpo(_ zmm1S00x0pVO0RkbQ2nGikT4@SlUEeMvdnJq1_5L3X!voLNpr~n`w0E? zOl_wZByyWN${eaqiTfx@U)Ovty`%lDgo^LfyP!HPFRf3pCA4z>wqoozwKrsd6=*jN z$K}`X825lTNkR}9N<=&jbl)6!3GYiVw>KOk-4$T{I#B1eG2(c@wvpwF22~N;7La>H zt*vW~q32i+DK|OCrm5&{R2?q<+=x~bEoq}^1ECxx79iKGQ#;9WXu&2wov`mcuMPpO z2A_U=F4uf;5z?V6^CR}H^+BH=OZT~O+!l=Hl7EGqf>*a~&}cH+Z;EV4egv{9($(p6%5v70m=*lrmezY)IG$GN2Pv<>hXOu?=nk{TYdGP-Pt#TwW?k%x+8DMiCSsMAkQykU$Bo_zfTe*lwkkzpDV$ zq*%`Y6eI|&PRc{j_f7!<1V})Hp@9*`A_j~QKy0sX1R)voRb!jhMER5K~>4ca3Ko+- zwwzGq9FB!)A!io@6SEqgtossqLPs9Pu12wLduvUPW=mh_JHFDrrq#(fC@tp z%{!sBqBX5#m{5kCo{58uZW_YUu?8Y2xX~ksMySR(rtS(bR|f+{G}>|>di}=1y;CBf z68i@6Y%nY-(#MJXCP{D0QYHcfIJH?!x=ofX;bS%BO7UsApECjf#J6`6h8cvzVd2;!R{ zMMY!K4#>dj#5c;P3)rpY?YLAV8<%-p616_<#Q#&MEzcV-^p28RHL#%ry}o ztKQh}%Anl&%l?%Qr^5%s_K7(702~_DkfC97>vl<=oaTIQqsGo36K;N+=;`|zgblui zJ#Zn(eo=hqT6#zF;?<(;()7hk%`h*@UsBnBuK~V#yC6YK8*(Jw2|r3?eeEMqSsdzX zLG7XlVHUv*wbSk`u@{JsXzY|X4LcC%L9;^nCb8jOdwU0n!YuoOZ^e1FRsfm%h<7k0 z0r*D$;6E?Ew6s2o#r&sH_x5$;l!`{rrg`yWdz$vkfj=_2@$uPu4eOt3KVZDH>a98Q zn6A4&PG&I8!@oxXL16CceWl@D@N*Q5`QoOV=($PYf2Wn1=ilg>B) zZ0?;#RUq>+uxa?dpgbM;X!Uqk>DWvDHO+Px1*~ET^cWwBYSA~Wv9K!nz13FhfPu`q zodbtXCn(m&wJ0_YhrZK~@wH5!&aI~mt|U<&PpoQv4hVpbi5h~vpQ~|Rc71L?U#IgT z%fKTB%(gH=DqwU}1m@B7U@oo!03ekxeVS4kvq<)|v3$R9vlUYXkIW52FjpOi1iYuhA#x64YJ zF}0t9JR;tyS2YOJOYO=3cgQDAz9Tbr0oKgn1YrgF=(tjUSq+cowO&1v_U@T+^yi^K zN3AfenQlQ9F(BEb^tDtCwq70@1yD!fs;L$+f_6P{3`YTa{h+GIvN}~;te2GiN|G9{ zBv};(sL7u3aM%_-p(E$ne#*K|TI|~hW5FELVM%W$BWWH87$fSgxmfQTuH(2G+Hg%* z9$pfJthns0{Vn!Q%H%Q;k+%s&uiI8iD4kRRnzLj17@mA=yV_pt z=3D}hBCaGELfuXe$3E8O_jf(-_{A`j`9=DVteRV{^uI)InDZ|IxbIp6Tz3SUYn(2f zg4)a=&l>&Z_93y?sDMQvbWq=weA+%p4+~Ew4+s9>&tDMyK2j$Vkz~xY05{6#@P-`L z+b3&mS#aZ7V-5(=(S6P8^?Y$vweUUMok_QWPsM+3IDr+$tA_Bm3KNnMrpeR7>QA)O{1Q1vP_s0g? zdnx|e>*auFg!*xBdZmg)U)KkgN`re)AE;;G3cvlQYCY~Pf#z6X*h=P&A)ay0l6UxO z_iDBB?iyUbCPNN}?pgS-<$ZbI;FV_V9Dqok6Jt^j2r%fApVc^_pNw0*b>v~P#Q{jA zc7SnRgviV)HpAD7tou40S3OwknDzleAb>Jr(e7y#FGA@M4S7qE%p7)EysYWAZ)O)0 zuutvUs2t>_c8SxS;pBYbU&M=S--&0CRVpFI6`FqulsHws>E?9d59U1eJWTt|Kqyy^ zZdS*Fr^Sr+3VxY`#S`B5FW0mg*T0doLHRrzE>l+2fT`#-1S%VM4~|x+h|VF`1f|kD zg$N@GJ$({DG}sRSP%104*v8=YLP4v#FGos`dYEY)voz-!9Bsujk8QR9X`3>SxB{RM z#LR_Yv~Bi3=b6HO+_CrfRk`(&BPAg1xVinp1mQ;iNvLgsV1L-lvuU--eZ4zK0*7q+hYHOrGO>aAO zYUes$L99u*<_eTEwwV>4xk2|IkNR%E(+=C+2SM!_4eayXtHi0;@=m3J0E%*a6nJA; zHXg4+HiBJ&Lz$xs2@di|Hsx7p2dSPcZq|aK|3QAyPt4AyuU^Bp} z{v+5@@-wN*{Le57K2x~)WU0hHf9Y=(uw?9}eeSy~^aXI(JC&KYS@=!oyc0h;?>e+^ z>6zCvVElE8CzFYJ_QaJxAiw(~sQrj4MnlKxJ#07M}i}3w@qLEKKFe zg~N{dk>J3bnhduuN*CGK4t60eJ+o7Sy{V9NUJXQk8Ja@Nwbxm57}uW0r+p zUWZm4tjd;B`{RVNx#@Q%3O(`NM6U}T_<1YVUd!wuX340r*4UlnLUv9D zsxf|ku8v3E&#uu*`{tGI%zl*lfnn$r=;4M5L)A5UZj?U+R)|je;SRsFZ8C569u8i{ zF0HfavbB=H&&_&_-$z~DGN8?r0iUreEiY%>ga3!g(0hUeD^!9qduOB+Si+n~5j=78UU= z7C?@CTWvhs!9$OOm+&bXHI2OSe6+zPjIA8V55uSCKhBpi?jzy_gpn)$Yi%g-iv<74 zoW=8N`^CW8ao;OBmyDWyKfxG#l`(X2$7JP+vS!or;VLBC%?r#bA&gYa;T(NT@9*vI z*hf1xf75p@dVXGiU)om=4Napcn@iiPU)2tq*yjrP4R%uNzvKmBZjo-1{|-F4WbgQF z13JKuy<(-&;BlN?05h9}j7qo-th4)X@FjJ%{Xf$2rHE~UH-4qS;*gE{GbV4GBgp3^ z`h{jNIcsMbXWcm-03e^ObJ>_y;;>iPjq*b>5s#^{CGMvm!RSXwi!F{$j)O)U#o*6N zn-YPUX;~DlQG28n5V{b2etdX*E4%9nXmlQR_A^*NhY>}DpKk!9 zzrrY=59|Q#;mho1m=NKa3;+cB10v5}>-lCW^CWmt;Ct5v)&$xFy;--CWi)>`d_(%l zcpp2652k-=9pcW$=NM#G(ZiMl^LyP2PKBSyf&+Ptg4<<)&+Jc6_|>kdyCXk*p8EK> zdetPGe_WkoGFZQGFGU~h;sfM!p6N>Be5NxIUB~?zKCcHpw|)+XtCU&0n~#1U^;#;z z=M7Nn)TgNZ7NAf0Asv_$S>Us2DVNr#NX|{vjOcLa;alJZsjyj*QE)zXA0u$&?FTni zvS{owW~Yhr*%#*I-J`GY+Pkzp?{v_xd{v<@y+1xyKOdiCAGq7pW6BYecpKOv4re_s zP7rD}ItOpCbxm&lGO3o4k8XM8ww$;4SR0r|tK{9vhJFO)zd~Cd?VDURXd;R$nKu4a{f#t`x)n+iRYHYTw zH`Cjz$T15)68CIopSwYL9Mv?zObY$Hq8MKsz%2@gl23Phfvn7Gr*0r@LG`_jUBhzw zJtrRJI<(!7UGZ!CkOe;*tDK_0_*T)B&ibO~C&icJTjIBZ3&r;?wtSXtW1km2@hytb}|#7DNw{?WoT*0Zh&_3eb0u>j9Y z*LExCs3(`1y?aSygH7hf#wv`T37F z|Cl1cTsk*b1^uD@PzRnC?d=N;vQ5s_qKPyJ@xuQ#+|L*V*pa^+_(FJVIz9lu8Cg@Q<-^5iAq0qZPzjXh{)_Zljj;RsEmGt ztB2xJ071ZTzG7aFPfp?Mgy>h$>aBU?)-v3c7H6My(Yr*qUKC|*Zbi0ZX|-M;xG<1H zw1}chkwq9gcA&OEq7^baVZgOHOjGWLZ&|!bN!qkUBQh|CtcaALbruS1<9U%XV80t$ zjP@m;UZDc1UMry#!Vy^GIizVrEMz5GR+BEGaQ%jj=c*iIuCV*OqbSgADP z=^&7PmZ{rbnvLqnI)tMqEK+C1AcMKcs=MQm|>UxHE&q)+gx z5Ea3t^7j-IE&v<2z)Vj4z`QK*p z*1h>o#SNs^0$o4Pc|Lv$*`2cs zD!XUCo}4d-FnQ4PUW9Akb0vtw)nhj0C52WQYZt-F!7p0v6ZTZ5<*tNTtctj2!@>Ma zk2hE3e+@~`;6acL`5q1Mx+|21={?q5;U;p`!|M7HUN%c&DuDEUNwrvR4 zHMoQ109rt$zts4lIyn61ZgY%g5(6Ajn(*dQsCiK)DDDn9i@vJQr*m+N0-}f; z=hYDGcf6OX*l^eaY!38yEqwI@XKfv=;rsCKt*GuyzDO6=sLiCe0p-#=I4=ecz?meCuKs!Er3` zkkx^ruD{86*pSOr!8TBY{#V`4VC~8rY74Mbb3!%;ox#oEWr=uOyVs-sWCFICg3PHi zFD=x_fWwd?94qzFpD!5$>s%NZ7l%e?bX@VRl&J5w&UkOGb4!M1-E6?(>_8qy7bge` z_2mvhRH|pKDC6O|RoJo;xaJ*8>)r^?1k-+)iFm<_scmMTlC00vfI_d|XxV}GsS%7( zU}wVIb1oOvX*)ijdsqA@Un6~drdj7@>GuKf7+P0ph3g_1#{O5V@me}-`af(`!kH|K zsSiBDZ8lU6?c>{>Eu31NA43IaF$s=567BsP+7TZc>5`WRWp=VzZAxelUtboE?tEr@ zcJlwog&dQa2V zKs^IA^uKuEcOs5~V;Ud?_i6#!`&CvK$I9C|QbonyBzF#^?uTd{N?IX<>0ztLp!B_C zMmRJRNl}1GKxMrSKon6X3mMvgN|!hzQbT7()YE9y3KQms5mUB?@#ID3!qm>C-g#Kn zG$J#-d2i2rxaAnYz=U!_P=N%Fc^#dfJ`L(gFfc0zIuT;u1StlKqSO1x`DZUKO`2$t zl>m^zh*;j0int1ig4WNLckHAjw3y(!9_pg0!Rm-EF0Gaux3y0Y>su<)g>6fa{k9;% zIwoDLkbt*u`DW@)FP{~uViFXQxdzQD9hLRct8=xdc_~wEJGW?J)`ZyMy6qWwXUl&3 z8|0}cLW+N5xbpdi(bBUmIA{n6si1BV*(3Ga+wG_)rS=Ik=_2Oz{4)?2CSNfb8g$?H zA;6(qcW3)Gkb;!$L4%AW1mScM$Z-yaU?~3|vvPc2McmZIi4T~qwzXn`*ced6^ z?IQqpKDrl7sQPvZ!GK4XRB@bBd$YII?i}+%z^yK#fBok_{u^LX_KT9;RJRs6AC7^Q zPl5g0G(GnA7UqO0s8l%*Rf}6OvYAUZA?36sFZ~0g>$rR4*#h>k74j@4aFN_5>r!Lc z(^q4_#AWL#2q4}&H%O=n0F)j}>#`(u_IMb3s@3b#`~wL4W+vNt$H}lyV;aH%8H2t- zd3>$D4cW#z!*fu+!62UB68I73q(ial#!Nim$ZGd4m!qE$7z!#co|-1q<=v%kIsa%! z5f&L}HmW@<-dpo*llRUa5+T@mdgknlECnCL7wF0x&|1`vLh&ot{gBGAYx@-Oqm;vq z$Jp25n_{bUk7)9fmp0hh`)nsoFO;ISbe@UU-1uEPDOWPec-p-U{zXw;)9JNsY2Qyc zyJMG3O34?n9kG;h=)vGpcWoQ3D`>yCiS$k|#Xky*d|fQ_ z%zT6pK*o;NwTp}p;&W@?`e`3_-?sV!?FkMgVDR!)uNcTC)Sxe&}Q{~ zXynTta>enN$l7NtL#ixQb#Yu%k%~~Uf9Akr-dM;MyqJ4ou;5!?^AcnOVU#jEcbB1- zcZH}>sbiQWXpOKKw7;w$Wn89+ak0xq*Hd^&UNfSHJdBrDSlqVeBM@SE_iE*un_KI7 zxS(psIT2R>%GuqJQ?8C<>*gi66|d3WQh#kPhC){}pUAJ6=07p{Y19{tn~Fw?*jwEapEt)vGe?DSHKOEjG$(YH!mhQ-0=Ti0jusQqIN69cYz)TC#`i4%w#jXW# zGf>t6z|&d1ttygD+<+YTErLQWQ3U`DF^5_Q1d!z=I)tkbhvP5|oonce4>7>&-S-EkvT<8IKQ0_#I+>1N@OT_$D z+ox>$+ZADz!p@!uZnwRluk)mR;!J}wu;)A)Alnl~l2vyDI>Oh7;36-t3y5oEjYB z&f&68E;ZKENS}T7#nn-cj8gGfqfU^yT0S}vGUOinw6}pjz_!XEWa#kkv}{bdz@S#V z=ErkvxY{UWci^STntIemw=4R1%v~3qLTT*LR=+>Av396cYmp8t>ksuk+fTO5wxm5b zW)Eok&fI7n03+1X;DzJRq3f~K`qXEWbxyFU(#|W}i_!SJOJ5uUN(s9Zg7t`|^-(Wy z&eMa239Z0mKL!N4j?Xw;Vq&(9mZH&U=nraF%O+xTGekWe64tKb%sc>CYq#LQj|8QB z9!aP}p0yoSNx;-@5)er3bXM_q@!YIAB?^E7gwyv2SV3Jo;Zm~Q6QO=0v{J@cM6^)Q zX5IL7->^dn^@t)G)AeGD_>p?0M}%7ZB6Yqd5(wnD2*Fszt({ZuiVjT2z!1jSV`^(J z2!^bkelz_6o^%48&U=)vTuo3OdlT2`nfMAE>u}_ndI|mlcQ-^2Q z3_@1w-teRLA0;afWQ5xIrkNZ(VXAl0P5WWRv90LgV`&*Yon%(Nct}~k8gr1L|1?KQ zEuDe((_w|Ti}u8^AASxzFohISw(E`fu&crTF+?{6=p+mRd)b|Wfc0tpqOhb^(TSBk zHCNrIyAni1H4tmK)=L7Bb=)sD9?-4@McWD@)PMV|KoB7kf~8TaSP@02_rM8aYITgX z1GI=;w)zOc>9kvj58{Pc+v%o}+D8Fhh*4O18)3|~_q-BxB}3Qw0B&6{_yEi9LD0R6 zKvK#h)Y8yeSCEj34u~pA6cwm&M*u{?vb+#UUB+P|3#82h?N8)sWfxW&wW?8c{_&2a zT_*@;zkPNM8c;M^MZLs9&zPbofD%`5OFB4NWg56xjTl+iDWk^Ttg_vmgJQJ*-rke# zQ`}F;<*vg~?9#anL{AKk1>vsPz_hHH^8_A&%hiw@&&%yeyoKgs?8ZR`lb*E(rlpG} z>$dF5u)d5 zbTOX;FNz_3p;HG0HS{b4bh5IP8F3$`wZy5w=$aLP$>9jZj2aNusA<&V0Ki}W`H%l8 ziKM26dJ?kT1^}c!N(rr^qx)!8w&+DJUdUMZV66+@44RM{C#iixaRH!8P{778VG%yr z&x8Wl49u>7alPMEpCD zsRw8K5-#7`a+Ye)O88-iKh4gf(SA&LP`s_YHTcq0qx;Nz=K=udiXyN@c4L#fk2vwn6v@Ar1`48S&D zgv@6W>NtJ*VNds)YVB;RL@-^`4>UrT&_{;d>bX7WAbz+jLeO@8jg~MTK7@#U^Ogqu z5QVASm)5T6jA6T0sn@aqx~hS z^*%PaT5Jadtn7LC#u=yQrlF+7ng`NEI>;Oycjc^m(ux+o_ zbelO}lm|mZCfn!JlRQN1)_&b2z4k8rL)?}4+wdoHU~UTR(XS*`vd?S4ag;WZ`!DNZ zV#(#vuIj}ZR(iJ05gvy$CH1ISH~w5CZW!pz^hQXz_S|sp{s!qP!f2Zyi?piEU;#kX zz^aW30fGu9sHlQQ38F}9$`-ur_A`sZ$a-Z$zX*Do)T^dkfDr99Z*ta9n=?tmhJ_>@m>h!|%$mequ z@69P_dShTzlvx{7HXwjwU8q2U2rkpgJ1&=`IRFw+B2_S*E-JnoleG>CvOWz^MJH=S zx9cW!_8tWaq;c)N8c@lwNs1^-*iN!o4Z(TQNd$2hvHk!N$TFXHQQ7=lS^OQ6$@BEc zem^OXfg8;W<|*#rGkr@*7nWi}A73>2F5<`A4NiAl9Kx=)aGnwEQhZDEdd zYRFB!$)q+ySstbCA7eW=@=&4^2C=5?jOmeGbK=!So)#XS(K;yGt6W&9jS1sHx9P!k zsJRO#w|8K`{OpCFNnUQq64Ad+1 zgyoax9*EkUJ>M+tSL05`yi9a_W^7B(Ef_&o4m!9MfjIW@`}CTM+>C(5dxKH%+cB)q zh8#i8`V|1$w#@$O`U1-Jlg|B+vRTv>Xxa?@`c9WW0`B8eLtL0gILrG&0?vB zQ~8Wv8?OAEF@C|rzc~mN@^br~;g4ehVE;d>FYtxWCAfh~qu$X!AOIreq+?@Bib)T@mb3*2 zR&Mcf%gp}`5V-l_T9CMvuP04G=%=D*=H0z;LV$W6y8GxGt9!>Iv0oy*X2i)S;bN29 zubBFRXhyM-m-_-l8Q`^vZF|JA=%gaeMR+0~!`xNUd>)V9ir>1$ym zy^u%A=!G?7HMdHVvg` z`!z`r;?AO%0TXSOm+i@RpQ2*}pPGDy2<6zWf2J;m2NEi50c`!3k!B5G(FHg%Mi5gU zPaw1I^q^&%`$d{_`X|7`+~Db$kq;ABF#EPNOR3rqA$N&5er~7(!i`6)lfu>KQe~rm ziMl{*KfDCx#sa%ME}JW?S#ljr0vE{--L8HIwyuYj^FC$xWc6gyp`XJqvRL??;mQZA zyKQ$kupK8a$N=^6?y4W7XXsoP7fhhk0(NbaXGBhJdEqat33sJg$nz6C|#hBtfdafKusOFD(OTF|$tPRf3FxDU5)oSE5q6 z?dsF~q^JU2rsfQeDf+P16oVKbWMAg!!G$qq6zPMC1NkG~MPUFUVzM^X099JkVQTTs zb}<}KNb7E`1cNeDPvFT1IA{#?teh?q!j^w)jnD*RghW=hG@Gcki3%OT@^$nUgrr*Bz&dtj8VzWAtKTWoG^>=r92@9lqr4|v4&u^31}vx5o20>PI*cQrgL{U4 z01)}>KmO~VHKGzGt{2q(o&mv(29^n%@^%%UZOL3Jg}OT0fI&Vk9jNtU{OOJ-X1tSW;M!{J9)){r0?~d^HUfGb;uC+9E~ag{F&vZa z=DitOUfmr4RL$ju^F?S~FGohbxtt$iqw#OHSP3W@XsuBQT#emzuH_l!x~wx5I=Ta@gBiy(5p|rBBZt ze%ARLX3Rmn*5@Zuym4D9{ocK605x~si|DsQ9SXW4vgsSAy`2kslI+`S4y%DS#yjRs&)FjP1o z00{qw5KK(!fKtYM;5x z?@?vW>N<4T6{B406n8j(c&c9@1sPu{YB+M>oPFJ%_MTIi-nyL0@Mvx3wM{XO_J!x6 zL;sA#H-5`4jvDj^T%40R7p`i&w$g^cPp&YFetF}k#(w?e@FSnQ*T#|BPtEsMu48Y% z9qwzQCS6hgM&ljttsUVT*IpZsTU^!pQLy<%Q>{1PgVC+{U*N)QE)gg@(~J4!2wcbR zl=*X=`QENxz3vU3%9aB4n|_*TwYixv6&QZn9LIxIgd2yaE1t{oQEgCmiw^H~Qn5RP z_-DA~Pth-A{6i9wBsJsBA}$Vpvd=8|b0qw>jQS`3VHlph?Q1R};m=_5r@Q7-`|$AA zMgiGkx~W&5Jl&hOm>yE*;$rQ{Ly36N;n}n(+XIq%`UnP-aq?cr>xn%oh6-+CLL`tR z@elrqf9fKV5d0JWK+K<*_y-gJ#6KE(K{&4Kv_k1Ud6rhNE)vsjN3U~q3onmyZ`T7(MRN{{TVQ{)P{wwBN}vBb=If!mJa%)_zM`%@QrOr^Oh z@v!u*i;#M7n+n8N3FhMJttyrSsb`aRnl%NQUX97}@x_og%&>IwS(@}K zhkQleFq=v@iQkZ8cWo!(a~;vBkyxb@0s)Wf5`+-Z6xMAUjlejIz*xl+L==KS(MagM z1X$-E6o%S!GrIzrg0!DQ5$uHz?PMc@0VI*sMAL+-NDxBZYOvRZwP==CQA$k^yRd-_ z9hUQ-7xVT^jFj}4s78|{seBH3W%5j|n-q3TVyx?@k`=9u;oznf?jZhu*1jy=d0kho zD)-DMUy>Ol8MZg|i#~hL@g%k-$=&gINar5>>N(2Z} z0086)s2sFc7D7H98C_9W+rMp`9xWKbcJhk8WjUGhw{ zz#NZnTyIF1=J_Q-qBcAt1PSo-vD#wger9F|Fw8)fgp>w#Ljr8`25Q)!E~DKkT{%%C z*Xek@Ch@Qwq)1qHDmay3BQq(X*2i%vTU1{^P&>kN=f(9YG-{ zXad`Z2LcGP@5Y+!WcFr|62}5?Z1!(39uf8%-1vp;kRW@$*sa~bZ96?^xb!L24d@-x zi<8zR<_;(eV0IbPCiD3!Mv}PLIG`fB!$=!Ih#&ywPOZf@sUURCBur5v$XAU3Ac0o8 zzk=|X^xuW-#J_Rw=A*x&p_>mcSy6dyg*_X2my%_OCzwIGXW&7?W~|@74Y8w$#?^4` zz67Wz1Kl`2fp@Me>q~y{Bc04)>ZZ|K-9?ARft_>lwP||QNx>u z(lVAk6g)7G7yf+ZdYTs8#I^x9cKiX}k~ngF)%H=@4b!F;!6EK|sZIp6tKHf7c0E*- zZb+teJ^Stv0JaEvDUGSjxJ2|9cG>-UVV}??{k9_kOwgUmu%74*e94&TiITmK!nmrr z-ELry*##Xs02zb62Ogux@ivhUwaQLzz0Db(G@R*;Ygbon6O*`hLGY%6>Cr?kA zTOkM+R|x>+ogvxnEnUojY(@=89j=GS92CC`gd3qa7fpf+1;B z_gZW;jF&0_4T=XC1hh*4K!O03qtfgk$$H>d6`WYM09Gx<)Pc^RSiowX1@lP(EHO>j zmIx&J48sZQR%M9*3=04}R0RM$6^zLGARse~+Jj7BdIkdR5IRa$9>8$z0uM+|%><}g z0n!86$0vyb6n46#TY8ewHPJ{0BWsqNW<=?3T4O6(Av{5p9hFT(*@Ej{400eRSqCfTlN$s0KR|Aw+hV; zy5Ky3=Uu~rXTPdm(rTwx1xM~j?g^^b>F+SzKj7jW?X^K?I_^SgE%_spZpzC2XAd?| zRfY)^U}a=bfomXOdnf=PL_+oS=mP7OKREeZr%=5<7^I`o2(MYk@6o=9{%~KHp>)fk&43Rw1>nw$ z$)ZbZz*WSPA3NOWz9Rk%KahMyxZoi&FCCBC_jA6-)dBZetx!4|o2a({%sw9-88&g43q-v+M_*zro%G)q9$wODkq-xuV z?kd{aWIdM7D;QVF2hxmj=z^{OCjFm*85WdCw_iX$T7D?HbraAhBY;gQ(BXCFujdXH z*V*x4#*;uP!fuCWH)2JEkmJL19EW$@A3Gef`n^?>;nRlqlbF>xG}R@_#?66#!k z7M%ze!({GY2NUP>nd;o1K}pzIy9hvJAeASrM1G>ML5da-pD(Dqm`|kw!lP;fP%!Pi zM%G%ItwT~Y007iykT!97unz|g*aSxS#-o3J1^|HdSwniuGJn%G!gtdW63tv$csfm)ne=*Tr<`&XxIY6^s80|@{@wZ`gdiK%Yild#Bg z;=cssh;W0pw@{Pc6jrBI=_1@pp$DkvM+5}2SN#rhnmxlX-Y~TIptYA&arOjQ{3qzr zdL=V>AY;DBXbuB@Qs+r8G*6b+J1{S|Eo$_R5H>tp*f)mh{?E@4{~fXvQLH=7SG z$Bb$HM1GzS3nwqkcWDzV;6MJ`|M*{<3lDb0Op(XPwFyoOh*;RU;VRJ~{VzT6psJe57e6P11yaDZ<)3S{^TWT>t*JKjT` z1ctW6J?g{c@&v^t63EY9?_Z#`5xrmeuIH~^yhivmd}`jrJ_#ZY&WqW4V&6)a+aH>I zUHeq`blpO@6a5I6ME)${h4&D`Yx*t{*p27Dx^&RJ6oO;iq$kFA*z^|v-BSl{*KMra zm^RSlz7O~7b-+7$Tv=&d&%(!)@gcFVw@UsfiD+qR9E0wU`FNn-9Mz>|Fa+hz@Ze^Z z*JMq%m<@&7Gio{&kURm7#Li6gOn-1Y$5ShAs#He(3vr*3ba{4Ni!i-UsZUhHpXXx(Z#yS>+0uK zPDuET_Zdl46f)XBNyu}=pos5Fk5j;t@rrS{>52~`-{t(S&M{dwyV)lYHDC3sQFbZ< zGOl?CjRxFh3$|Dgh(En+qez zaIP1z8K1u8!P397a+Ue4f_ZD(_+#6=n|;N+XfYTx!d3E{x=|!MsNZkVP6(u10`R0R z^P;%gtMrLZF&%AasTLC&rtz9W(tw*}_3RqJi9bQ`F4_nt+3md0Tjz#O!)3230PS4A z3INC|v*J7xb_EX+@vm42-#85FGt77o^v125H-URr)N^mVPg3=(kPZMCk61M^j_(8* zE24WtwPB(9>@SiLtJBj46E!E~Dx5ZP+`($*4XWE+dpAm1LK*Ff)t(sTCs_bM0=jsv z*eMAi`>NV&Y%HTrJu8{kzJlznX^3BfP+nafZv7~}KP0vervw`O>As+-bbUMN@?>$Evz@bG?Vy|#bdfyTcUWnjBu5U$mbfjR@@uRmLf9`QiOEMwI|naafmuZf!#G5T7>IKED>!ShqsD!1zgHQ!T)} zY77 zF#-AA zXY2pb4AA!h1TW@FkDHQI0wb{06#u9c7w|9XdG4e~@mW=&KnNkElOLJ&a43}3^e zD^}2)l@i*GU`MZVMH97F@8(-nJ;3fIFOfHohFoWN6L&a~|CmgUjv=svj@A#7IWgO*Chs+xeIq&*{Hr%fr}6_t z03_0uq`&Z47rjI@3~d6zc9sWGWjdRCva4=H%OhI;X6+#!rn>m)Jy$oMv4SOfKC#O_ zSTbArp~xZkG@G5Dj1uPYL4`-KRY+(u^a?ZP8^wl%Rk_`1wN#=g>?@~bL78(7Zs0i_ zEqS1x$PGqmJi`5*lj5#GOU^lTTdGWhpY8T+2`sM8yOG00K85)X1IV@4Ik)* z{L0~L5(UI*0vjdNULm;mpp5_~3}p6|i%mT1qMU*3_6csz#Dug7y}M0pl*3t^Vw5c} z=a?p*4ZbLke5U~dZj6cJTtYuUlTM}TEtClag!qGx{9+=2dcLf0A~GeDiXR9dz05%G$$|h9=;^lz(POYx5%kqxZKS;y zxLLa{OyYc|;MOI$lUp2k$Z4b=F#vGz>V^z}|OKN%Aa0me_L2!!l4{LM#ztUsw{?O4`PkgA!@ z3~z+51Z^MqTSDKEjY+KJBU=JUZgUIsH`u0lC)hEzF4giJ89BFwWfktC!rE{fL8ts{ z3()E>5CD3qPfKj+N-A5ZOGmP|S>_7Ri$E#NCNFHVYD;^M&^o2@`)AsD}A35F&^Q%i>~RsK00sQ2*evAVgyz1<85Cs}_rKm5KF} zpr-+1D?dwz|o z%p1mUSJ~`QotDFFmZsjro#8SNk*~1K3Wr60kB>PBXSWOQm-fr8m0y!lpO;HLrPY;X zwy_V)3;X5bOYhaw$LnWLp9ZX7JI$PdU+lSe)x=wa_t}g)K7;?~OD`Ag)h(ss795jyiQ!B! zgr537$BUka=Mz1QU?kmY<0ys>yGeUB@3d-QU^9Fp56nTpPcA&jc@n&f7kYpYns#Nx}}W1=lePn2<+wgG+HMfGqY9trw3?5rJQ*&KL#74nC4 z6iDFTO~%HDSZ1657XK{@k{B$ysr$Ta^6asnK1)zO;q(-jE<40j;A95To064IAzVm; zeZ1eVk|`^s>b|=9)I0E2Gi^B_3}UxLz6~~ec6GOEl)yMeP2S@gHbe-mm)1_1foI$7 z&VC?qU~+)ekU1NB8&f!M=9R9)=GK1I=+3@2wzgjJ8+*LU+B|x15?szn@Qx{{h}BuO zJv#y<*=0us8CY#WpcqHRR3ALViK|EeVtxQlAtf>h@|>A0E=F65sV#r)Bbe^C16f%;mL!I-Rd|s*%6kYMLsd8yR>@)MV^jZN&8G})nViubeUuz$^*cw;lXylYA z#@}N|fGANC7$&D%%r4t4+?3kInlKcqsF*+KTO+sXYQN0dD2Namzgj2}$j^O`$TSk)(+s#2+O1Eo0O-J5@sFawh%}bLu@8#JaSnQkBpHQ(1=7Omz^3gv~+$f@*9O zW6|^s+%&~yW?LQBYL#4thflnv4lNKm!Z;-iU%VZSdeTMhmNRJ38 z)(Gp<#sg&dxXBD%?3>;A*^k+%dzM-B&clugx=<*Ug-c0rhQWcKHXg9qnWOR!g=ZCF zybSxQD3gqe7os9m>;me8`sP)jbdc38Tdjk#96G)4Q4EGZ==kkAy z{|vqXlK>!Mgg?qMYf9`^JkBc%%MdA*MVH<;ARybbH)IVkeQJuIg(HMd#1*<+XF8kw zq0#^dXOu^MpYHv|g>TrWvOmFe{2u@-dKdnE8oYym`j*Nw2xxVkj$80mv<+FGXIHAf zLk+bJh~cu+=-O=fj`=+hFOg&{6Ys(PZ7$eB^|qeUweA8P&wC%K<5VrX)lK{AB-R?f z{p~??s;0@|RIxrsY)w13z|(~J7}qc$CXI{C^dVuIS7sVPVBNJc>o!#mwXwwJqw?KL zH{+9R4X15<_}#`^UF5he+g10vkFI-}9;l(WpT5~4^nRdaOuZL%+?zLo47^+ta5Wy5 zB@?b2sY9*c#q`Aig*L@^{{mG~)@Gj|6n`R+Ge=iL(&RTZ{;k+et-mX%HbT7WhnUy* zH0v9tF1RBZcIm!4tY;6DaMWa@oH^o|gskV51v(cITUW}GlIA%vSHksRU=rV8X!9ho zEh)##sm(^9tZPLbuIu!wdO>Y-g1Bf(gd1aw+)PoH$fB7(Z^A2vQ$XshzX4f>Eem}o zr>4IOY2^02sK#u(t=$D?v9G^P2`Ed}>Sf|;9WDD;`%o19;oyTY!;%~Lwt2yu91of% z4RM+EF2M0-SPQaha5MX8afqM%%DIE9Q1+rJk;xgOY8Bb~FUA>H{Sq;rW2J}(j{JB* zCAV&C8d*D&g;&T{?f%zC4#65RT(XsO3)j%k-Xv$7?-$ux3v>TM!2X6{eOrC0tclz0 zwJ3LY6Y8-9=%=TX6@X4Fswa&uGxqg?~Czn zZL}G!I1#FVSlrm}@+zGZe+vsiIRmtHXqi}*(1i+N4JStB%Nz}ZU`CavGz$x4T@}=w z%58CIua<#nMHVE`!h{H#3+F8iRz_j&D<0h&6Sjk<%h?cJ1nVvzu@%x?-+A_ z!oV!+`ALRvQ5P!S2p(@g3GDVa?>;fw-a83e|JQ9~xxokN6K35!(8zUNHvGjq>u4ul zEn+CjQ5)+?-&f}xLBlW;lOveOiu?foC~%OPPfO`6B>O z_`N{VZ(+_}<NHJl0zYI<`cH@O=`Z|)pfGo1QJBR(Kv{yxB}n2Z#$e(WRyyjJ#>fd8bPR*gliUg+Z)wDng=p3)c%KAb@)I(95w1;`|*eX3u>cbJm&QoQ#jf|%; za);}tW~qD{MYjq3I;;Y`!YpV!8H&;jxNo7D@fIJPc=VjJE956i8F5ZCGLr*#q&*%I zgK^`%BBM^?7`bDm>}B0pjdgtT>5HZyW7JNcjy$MY6SdM`sA zI$J7~ve##jN)whN%bDBvW4h&wRZD{DDckluKVSy@f+^#gQiz;{dr-76?)2;(Ab-tcNDIAdM} zgLt{H4HDNCee&L2oysu4hi;BZ0XC^cV@>{>nY$(e*gmWT!eR_j5v4#Z4?;zp^(y4g zZU2(n_J=|J)_%EVI{X##*FmGY6!Z5meW_lGv_iRfk}Paf{v*J~YRwE=`59@MS=K);bpeI4D%cimUmjae*~6h7gZHq0z=kAhBYK;?Zs1g< z>kh-EJMO|Od*>uOSJtQ*FX?T#ui;4K(iqFQM|^5h?G0DYlY6-pskqfnr#Yq}<2KtK zkS3usINO9pGNbZj?*@V1rF>wWU=#jUrx3V01ljjbO-H%NTLkY1DpFTOmg+JvYH zg~q4*39U|n}HT9y1 zMajraq|HCeYGti=>u@o|&ubivqN>(Fi1oa77 z3mULx*3d_@2m7Qw!Pn7o%5yOwAcE=h{zgfAui)&GyU0plGVN{#0UD}3x~3WZnb91e z*CDnei7VwVm<8maU6a_5{e0*1Km;xL^8=zPDgI*244qDzC;LyNN?c)TI1A3Q<;!nJ z2{f?ZJ6!cyVs}Ll;;|}|w1h26DgzcLs#F|o#|;vT`ka8VfHP{4D0V>ob@`RjaseTv zj3$)FuE_75(L5hJi24PII4Xv+7F3f0;xo}WXCUI7SYeGS^cAHFUv@D}FUvKeUxkz} zi!fQ6Fv$lp#cpI)5yJZMe|wVJg#arB8JsHk-PHUXSd9Q|Doy)(70Iw95Y9jGY`M$q zx=9+wZG7e=lfzWkAJJu9(0qc-(lj-LlLr!z)_DZEz68<6EL|PF)gx#_qFQTN3?&%= zwtgoso)cLdioz^Ul5!K4qooka*IMj?qZ1POa$iGLqN+v!|G*T0rF)^>wiYT(CLH%S z%niv`vW~+W8RxCRhWXDX&}mplMll@E;q$I#@AaBr@a%7uW`GV18l$=?nm}pL7_+7; z8gBzDvlFZ2_b>oWy!z-YyKwe_7Bk(j<$LIIg2~I$A2?Mhb_IJ8}cr2@-l61;og_;@~9fn6usMjfwE-hT$^ih z_@MDNyr@%-+U6Pz36CS|p8BnR?r@RGF&`!LdUX-GIeLa<=n;6=ae-$|muPM99FxDDKEslHV1Bm zFhFs;rYr`IXIQrZKRPxztTV~eRpXVKlTV7SLE=meriRnarX zt=-yqq6}lqqCT$J5?g#T_nRksT6SQPoYL*~5~22jED`HSY;`jy(e;Zxjl}wPE8!jt ziR<8{Ct<~RpL*Z59&oC%gN}jUo+3{8cXiJ_q*6%FZg%`#Yl8j$2g(9Z@j`~=ahgTu zezd>gYmkpNoUd!I11d|7$-p&!mhOUBUX}?`{wWF9FMTa-F{v*X!?N`m)bcGb9pR-p#&sCa zsM~S~h6j4;OB!2B3K?05dSNA(<&o^QSfB85;LZ$HB$1hi@XA@>@mI=p!6qy>6zFg-9Ziu&-1ZkyP7)yn28@+^$&uj!p#JCp zTtK70DStREx5>zPqRIc`zyA0C8BT}mMHw$0gb=>nPs=8RGfORx-w9RDf+#tk>dSqPUB* zjKyPO?jUB&gK)A77>T%r0-Ky%*PDaGiXY*DcB{Gn9B}7Otg^w=Chg5QAU>~W-`Al# zA1H;JUW8$f>b{g>bDOy=LQiZbb_j@!bA7|e3}f|un*`hn>b(9^PyD!4?GHi|_*)GI zqfh~POV+%2yYz#{UxMGG7X8Bzk`MNzL-D!Mrsyge{@iGNw~NI3!rH41>(b!;Mf$pW zbRXBGJao+75A%o@7b=e694S?kb5Xj()*%cY@|O5DQ%@_${mSf`&cWYn-qaHJ>y1-g zERWY*tL1X;utgT2~PbCMSbxW<*fUnWpUHL~shOh9buiAZA2Mtd|?}|N2%l5TA-9 zu|i0EcX|n5yQY+uzXuejiCnr=@|USh$B7)iL=67CxIR>14GZ-H%HpS>+$w3=7f`34 zF{>!51M5>wp$f2cuA3!YVQ+53N^XYjc+I~hD5^9d0uc^Hc{8~%p-1bwHsyhcXxF`} zxk8W96BqLzSxu);u{T8|*FOqT3CUvG?Ow)KttKX&NbxJ5C^5|lM9r)Qlz$i!#WJ25 zT}$BCFV$7pATmg|hPMh)7U$C6c9$q&p3p_Z^dUkXuKKgnBBEW#7c=q-qN&=6YN z#LS)7hA`wOKJ`}aGZ@TKXUn93AvQa9;CzXO9}x$fy#ENp9O>My+~Tzv!Y<%b{wKjd zV7c9vsRH)>?_UKLY!#&k4C}`54d)~D?U8?ASX?v(i*C1}{dX04?$61)V3)9TDQ}Wl zK+JRHIZGR9mb zb>nT||NcM!7o)iPCWvj0-N2=dURsy`*xsb$oZ~f=AE48C2y14rjb1fM&ivqLp@i)> zk#@KuA0bQV;8Jcf9w58;s&Vh)(a1Ze+__5E+>xu^IPIC@qB$4F^}?D#sv5UEo^GDy z;O1KHe4*S-b&f3*S9l<~)ZCE#cUab&N-c z*RdJU1d9919`gKxTBG%nofPMfz3E|CQ zhnyJye+*dl`DY1yHg1&AOF3@v=`Ap*UWt#+J;<-zmDv;j$7uiN)Zc;m`WIs+TJCJ>e@ptFx(Usw?s8_ZJVY(87!J5NmLF_B*dOl{lksq4G_bQoR%f)Ks+0+X4dg91aw)O7_kcwv{hPFJUvrret zkl$ciO|4sHyMMMDYyYl1e-X3}CxeCY8U*WhaV5(-m8&glAJRR3!aa(MX{7H~-crqe zza{h$*p2+b3g_IynlW#xhqywr#xO zxIe83V<~Z&OWbs(#znzlVMONC`-17ix3>S21+X}{nM}V{^?I1;G_#Fr5EYhnPt(Dq z>*uz3sbBb6e+rN)lwZe2JRy^a&w!G5r7w>DOB&;$|C~C~4E6hZ^ZF;^``^7oQka!N zRNAGaQL-yu8MjP&5hY-qE-%Ky(#*jL9`dw5-?oWmO{8in0H~jy*&r&j??Y_KtTCr` z2SlNAFx{%IY$%NR>zDw6E~@Al(vqsYVjT_;hd_%`{wogg>rPdbRQ!i^ppTW2%#ytx~k-yC4Y4;-Q;8$#9`PX6^1t>?8cLE9@BBM2^t?JTl4U@<^vb5 zKCMzY9}O*45qo0ebp`*5&p(5?15y49SV^+{qL_+xgk9dX*4VUeGFIKxvbuv6kn9y) zD!hW}Bdl zta?|>edsdDL{~4sAK{>+q*L^}Q!Z3%XArDm6Fb^OR-aPPUNCLckMPFud-kuOqp<~f zsOMDI!#G|du%}hq{U$kwa!@643!Hj22lcnQ1((6U!0Y5SoE*)OmB_XFj!ni{Gml^v z?((z0;KjxDqI&xcE&>xZ^!_aHgv!^B*EIE<*LZFI1=hJtMduDT-~NHWJe6pB{|4FX zg3ENz7iT!$-r$8K^YWwJM}_`%i8{#Z^yM!yrrt9Za~|-r^cvh-GY0)YP?(M6v|Bg= zWN_qKlj1!N7kmqh=|t#?*)r2J>iLnNCvXE{#EGOl&&MfnO!cl3~e+_ zfl6y0*4E*{usPp{gHuSAU!i~8FS(ffT*;Q3!&KF7dC6M@hveWRW~b`S?c88=t*9hX z@o!x9w@6!TuhuR5{irg%(J^g~;Z;t#<63Qh%J5Cd^fOkIU3GLGn3Lv?$)}Uu{#Tap zf<7*e{vp!n%)#l zRJqin#~H$^)vC{0OkmMeU6#!&t2uSA^HMGy`Oyi}f{~A$Zw91cC5Nb)u0)JbupLJ9 z)yKw(To%U+A3y+*wqMr*KtCm$``^ru2_RHsO;c3k1r>dTgHSIb zW(cu#KgLviv3rqG(^lXc5qup9R2FlK^ar+D#ha($okM5&#>a7KD4mJdy$c{{vY9 zEL#Nt00juO{U5x*h{C@F0RVwARsCL+(~q`EfJ+7dKtO$>E|h`hBA~m@^9BF}fT$1) zfY{=C?J%Q>-DUF&sDA|rm$Y3>cmn|tFpLlY*kX4Fd&KlXJ4pZl00@i%**pR+Jrimr zAOO_Psd^!d%vN@sPGtuGi0TacLhaS#xv&kcCVfpJ{<$L9cKXK^I)nA(^MI3KxbvR{ zCE9NX3J^emI((Uq?2f+VSpB|#$HZKupe?6B+XLt(`vM-btug_C@cRB4c2C8=Q}whz z^HE* z$`TDXL;&FnA!@?G4W&;2qUaV7kq7Tu@!}zrAOuBw2PHN215ga+x))t<<)?MgSdb6gM+J z%wAjxL=O<6C`G&uZ!#Z?R|#ia#>^K`-QWU=y!mB9*v+G#66(qTo4Q7iDOOjP`tlBh z1?t&N-47Q*vl5jfLOI_M?pwX7vY|ybw0wk_V~fuXu(>f^uZI=|vf>A6RKh z404w{g4&cW$)F{?tgD@?1pD z(%`OO*^t+Wb%}(?w6OazS_!j2p{^$c6RO7;Fre0xj{D#{oqb`vtk6IPTzJi}q4J%S zyO1sO4=s)Ksr8p(N32E%9Kk$U3T|pIWcWhqE{_^JZ?(=iu>Sj}I-R41t2!)7!Fsi# zP`jyyINg>mgSd%=yBBTh9!+`wIn+|R=46us)s!wNwuQV^beI}pg1X3>UEBzJ7iqoY zF>UQ2j4>DEqIH})g$uBexK_m)?`iJFLq^TL!tF(+I+z%-ANg4HIDY>N3glG$~+JiGUIc;J9yk3VNyd5fdQ%Jjwjv zJ?s1=Q%qW$B|qZ=bnyoN#o9_uCgtT`oGH!Ay3G^UfwrLmr%{_HesTWCFbtl@xnxg* zw8?!mgXHlC(sv+OAQrt-h@e~5iEl8xZjDa378@`HsQ(P&$=Rj1PBJ-{ey19_z_q;J zaH#~}4*wXI78YhGjso6h`J&ES;%=bpHS&ZgnTFx%7vE<*i}w|+8|%Q$bQmxow41F( z@x$gNuY_Mn@7y1rHkk940|3}s*+%uS`4shv=$CbhPw;l~oV);2@+aK}OX=Y$c_o^o zeb4d*XRtmP{${g*-=TnuF0Y$1Z!+ro=}TkzsjE|TI@gS6^B<9q@u_QHlqwF+(0W#l zm^%~GH-Tes;v+M;g6`Y?-ig>uI;YQuk#3e8vr!E3bxK^TG~%Q97jZaqmoD$4*?2Cz zn>{gLAta1}u`e&wJ_-q_{~^)VdTAFxw#p1i!c7Axez;>zz`Fc5V;^t3An|8{>!U_H z-!7~LeeYxpwSghP66^ml!=@*bz35v}r%d^{tm-ThbgWC->lg?DV-hy~=JzIZ-dfPa z!P4cab4pS(A=Oz>$TaV?WD+bH6@kJ2dq@-S2foN&)kYaIo}9PbTtLsJ6Tsx<%Nby9(1#cjPC zF1#kSsa<}k-Uoo#{ZTM&}%E-CIlGQUFG>`$gWdm!JQoZO3x{PK%K3_y&R{?7GAtWL(BY>A1sKy4LBk z{)tpGs{N`-vN2wStMIN4x7G>$rv+jFjCC|^v%;~&0$TOoLP8X$g@3`QvRFvtE7TqL8q0H=vN?B|pQylnM-c zQws@s#k*K5(;f+22@z|GyG%sIw&s^9(@n@N5d3SL74!saYm(o<>?0}JfJdYXlo%IE z;3*+3$?LKWggXLGW(*yTi&zKV8Z>n!4yjZ00M#VI@uWOfs@>L~kfCU}$K(W$zfF8` zydWv>WK}3`Gjei7Tx!M*3A?we47(l-in?wTC2H7ZATCSHncu6eL4AR3pvAS9|1kJC zK69D}0#)!AZ-=fBD&j_MU!lMmA+EE)fH(`x@mX9seo5~#1Mb6KCWAM301mbqRh~T2 zEHlL}>pFu@Ou)SoVm1Ig=}s_*8LK4>OFqroG;Y6Y@L)B-r_rmuf2U+S7eMpvtlkfG ziI(FN2n|Er=JdGTaEzS3J|x~kHJH8{!XwTn`0DWP^C9l8bq6s>eH>gMuj30f58v8@ zRPpCmI6ge>7>R6G{6T8Ktd4&IG(z!;$h0?aCIP%PY{2Lu>sQ!Y%2!<&R=pX(M2q3t z0uN6=<7c3E2zE5ilPI&syd=lc0O%#FHpWe$0g&m7)0J#t^7^>QmfuFT!!`(Q0}8Z( z&usWOSm(#3be>k7pp(0=Z(4R?=GwKN_N#n~H?;(oaB~;-^y;QRk)E~!hF;K(*whAL zP6(IAZjs(nsYP#5D~PqFV-Fg{h;7+q;~HJ>(HB*-()b>`<=4=Y>NTS_aD`<@zM-rV z0F}UzrUDI-#tAA8P$d)8TKRB$PMv+7`aVcCi2&fbr3v8#;!gUwa-|+8}an(fhKu|vk z=(oT-T5>->lx&yedurV7i#`GHLB=Z5I9oV*qT|oJtiKwqRCq^r(#E z@#0&f=jlnXeQMEkgbB=+&>>bg0^eCSjBl8Rg;bDr-~i~=j!m~q3;MGJ?ZOL53pdeo z$gPIc_&c&g(Ph@Ed)|hk&TmUgI~4-mj3Ao5SW38j45hTd$B<&jAHc?=Hw5u&^mV;m z-{@>&C*v|6T+s$xcDH%kSFS9;vYbnIXoW(6M`MGP*?NeV%mIdft*iu*vN(FALkxy4 zlufuI84taD?1vsFU;sr=HZHHK@9*R{)u%EoOK^_(E@6P%*Lw5{M0rfBUa$-(IL-V5 z6PanmjaMY)oy=^>T~~CMtrJq9Z!J z4F1yu{0W*0Gj!JgoJtK9iW`R?f&ymfzn?7Dd@HRlSmp66PGi^<@9na3*mV=V@>-C` zSJ#>)V`yIFOJWRfSJ#Va�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%0DOQSC?tMk`vuMwh)1v~&#WO3WX)dy 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 z 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 RdszSg002ovPDHLkV1n6l;q(9i literal 0 HcmV?d00001 diff --git a/src/render.rs b/src/render.rs index 80972a5..c382239 100644 --- a/src/render.rs +++ b/src/render.rs @@ -1,12 +1,14 @@ use crate::camera::Camera; use crate::ecs::{ModelHandle, Transform}; -use crate::model::{Model}; +use crate::model::{Model, Mesh}; use glium::texture::{RawImage2d, SrgbTexture2d}; use glium::{uniform, Program, Surface}; use glium::uniforms::{MinifySamplerFilter, MagnifySamplerFilter, SamplerWrapFunction}; -use glam::Vec3; +use glam::{Vec3, Vec4}; use hecs::World; use glium::glutin::surface::WindowSurface; +use image::io::Reader as ImageReader; +use glium::draw_parameters::DepthTest; pub struct GliumRenderer { display: glium::Display, @@ -16,6 +18,10 @@ pub struct GliumRenderer { pub models: Vec, params: glium::DrawParameters<'static>, + + skybox_program: Program, + skybox_texture: SrgbTexture2d, + skybox_mesh: Mesh, } impl GliumRenderer { @@ -39,13 +45,28 @@ impl GliumRenderer { }, .. Default::default() }; - + + let sky_vert = include_str!("../resources/shaders/skybox.vert"); + let sky_frag = include_str!("../resources/shaders/skybox.frag"); + let skybox_program = Program::from_source(&display, sky_vert, sky_frag, None)?; + + let image = ImageReader::open("resources/skyboxes/sky_24_2k.png")?.decode()?.to_rgba8(); + let dimensions = image.dimensions(); + let raw = RawImage2d::from_raw_rgba(image.into_raw(), dimensions); + let skybox_texture = SrgbTexture2d::new(&display, raw)?; + + let cube_model = crate::gltf_loader::load_gltf("resources/models/cube.gltf", &display)?; + let skybox_mesh = cube_model.mesh; + Ok(Self { display, program, white_tex, models: Vec::new(), params, + skybox_program, + skybox_texture, + skybox_mesh, }) } @@ -94,6 +115,38 @@ impl GliumRenderer { &self.params, ).unwrap(); } + + // Render skybox + let mut sky_view = cam.view(); + sky_view.w_axis = Vec4::new(0.0, 0.0, 0.0, 1.0); + + let mut sampler = self.skybox_texture.sampled(); + sampler = sampler.wrap_function(SamplerWrapFunction::Clamp); + sampler = sampler.minify_filter(MinifySamplerFilter::Linear); + sampler = sampler.magnify_filter(MagnifySamplerFilter::Linear); + + let uniforms = uniform! { + view: sky_view.to_cols_array_2d(), + projection: cam.projection().to_cols_array_2d(), + equirect: sampler, + }; + + let sky_params = glium::DrawParameters { + depth: glium::Depth { + test: DepthTest::IfLessOrEqual, + write: false, + .. Default::default() + }, + .. Default::default() + }; + + target.draw( + &self.skybox_mesh.vbuf, + &self.skybox_mesh.ibuf, + &self.skybox_program, + &uniforms, + &sky_params, + ).unwrap(); } pub fn render_into(&mut self, world: &World, target: &mut S) { From d0440f3da34fe3d48b79180cf4f19e6a2495203a Mon Sep 17 00:00:00 2001 From: reo Date: Thu, 17 Jul 2025 23:19:46 +0300 Subject: [PATCH 21/89] Major Refactor: separate project into multiple crates --- .gitignore | 1 + Cargo.lock | 152 +- Cargo.toml | 29 +- justfile | 2 - opengl.png | Bin 44866 -> 0 bytes raidillon_core/Cargo.toml | 4 + raidillon_core/src/lib.rs | 3 + {src => raidillon_core/src}/time.rs | 2 +- raidillon_ecs/Cargo.toml | 8 + raidillon_ecs/src/lib.rs | 17 + raidillon_game/Cargo.toml | 16 + {src => raidillon_game/src}/main.rs | 25 +- raidillon_render/Cargo.toml | 14 + {src => raidillon_render/src}/camera.rs | 0 .../src/ecs_renderer.rs | 18 +- {src => raidillon_render/src}/gltf_loader.rs | 2 +- raidillon_render/src/lib.rs | 9 + {src => raidillon_render/src}/model.rs | 0 {src => raidillon_render/src}/render.rs | 10 +- raidillon_ui/Cargo.toml | 12 + raidillon_ui/src/lib.rs | 3 + {src => raidillon_ui/src}/ui.rs | 2 +- readme.md | 2 +- src/teapot.rs | 2110 ----------------- 24 files changed, 209 insertions(+), 2232 deletions(-) delete mode 100644 opengl.png create mode 100644 raidillon_core/Cargo.toml create mode 100644 raidillon_core/src/lib.rs rename {src => raidillon_core/src}/time.rs (99%) create mode 100644 raidillon_ecs/Cargo.toml create mode 100644 raidillon_ecs/src/lib.rs create mode 100644 raidillon_game/Cargo.toml rename {src => raidillon_game/src}/main.rs (91%) create mode 100644 raidillon_render/Cargo.toml rename {src => raidillon_render/src}/camera.rs (100%) rename src/ecs.rs => raidillon_render/src/ecs_renderer.rs (79%) rename {src => raidillon_render/src}/gltf_loader.rs (99%) create mode 100644 raidillon_render/src/lib.rs rename {src => raidillon_render/src}/model.rs (100%) rename {src => raidillon_render/src}/render.rs (93%) create mode 100644 raidillon_ui/Cargo.toml create mode 100644 raidillon_ui/src/lib.rs rename {src => raidillon_ui/src}/ui.rs (99%) delete mode 100644 src/teapot.rs diff --git a/.gitignore b/.gitignore index b5d2ef8..3db9b6f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ /target .aider* +*.patch diff --git a/Cargo.lock b/Cargo.lock index a227390..b75daea 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 4 [[package]] name = "ab_glyph" -version = "0.2.29" +version = "0.2.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec3672c180e71eeaaac3a541fbbc5f5ad4def8b747c595ad30d674e43049f7b0" +checksum = "e074464580a518d16a7126262fffaaa47af89d4099d4cb403f8ed938ba12ee7d" dependencies = [ "ab_glyph_rasterizer", "owned_ttf_parser", @@ -14,9 +14,9 @@ dependencies = [ [[package]] name = "ab_glyph_rasterizer" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c71b1793ee61086797f5c80b6efa2b8ffa6d5dd703f118545808a7f2e27f7046" +checksum = "b2187590a23ab1e3df8681afdf0987c48504d80291f002fcdb651f0ef5e25169" [[package]] name = "addr2line" @@ -151,9 +151,9 @@ dependencies = [ [[package]] name = "avif-serialize" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98922d6a4cfbcb08820c69d8eeccc05bb1f29bfa06b4f5b1dbfe9a868bd7608e" +checksum = "2ea8ef51aced2b9191c08197f55450d830876d9933f8f48a429b354f1d496b42" dependencies = [ "arrayvec", ] @@ -220,9 +220,9 @@ checksum = "56ed6191a7e78c36abdb16ab65341eefd73d64d303fffccdbb00d51e4205967b" [[package]] name = "bumpalo" -version = "3.18.1" +version = "3.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793db76d6187cd04dff33004d8e6c9cc4e05cd330500379d2394209271b4aeee" +checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" [[package]] name = "bytemuck" @@ -276,9 +276,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.27" +version = "1.2.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d487aa071b5f64da6f19a3e848e3578944b726ee5a4854b82172f02aa876bfdc" +checksum = "5c1599538de2394445747c8cf7935946e3cc27e9625f889d979bfb2aaf569362" dependencies = [ "jobserver", "libc", @@ -395,9 +395,9 @@ dependencies = [ [[package]] name = "crc32fast" -version = "1.4.2" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" dependencies = [ "cfg-if", ] @@ -429,9 +429,9 @@ checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] name = "crunchy" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43da5946c66ffcc7745f48db692ffbb10a83bfe0afd96235c5c2a4fb23994929" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" [[package]] name = "cursor-icon" @@ -585,23 +585,6 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" -[[package]] -name = "fps" -version = "0.1.0" -dependencies = [ - "anyhow", - "glam", - "glium", - "gltf", - "glutin", - "hecs", - "image", - "imgui", - "imgui-glium-renderer", - "imgui-winit-support", - "winit", -] - [[package]] name = "gethostname" version = "0.4.3" @@ -923,9 +906,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.9.0" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" +checksum = "fe4cd85333e22411419a0bcae1297d25e58c9443848b11dc6a86fefe8c78a661" dependencies = [ "equivalent", "hashbrown 0.15.4", @@ -1037,9 +1020,9 @@ checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776" [[package]] name = "libfuzzer-sys" -version = "0.4.9" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf78f52d400cf2d84a3a973a78a592b4adc535739e0a5597a0da6f0c357adc75" +checksum = "5037190e1f70cbeef565bd267599242926f724d3b8a9f510fd7e0b540cfa4404" dependencies = [ "arbitrary", "cc", @@ -1057,9 +1040,9 @@ dependencies = [ [[package]] name = "libredox" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +checksum = "1580801010e535496706ba011c15f8532df6b42297d2e471fec38ceadd8c0638" dependencies = [ "bitflags 2.9.1", "libc", @@ -1121,9 +1104,9 @@ checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" [[package]] name = "memmap2" -version = "0.9.5" +version = "0.9.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd3f7eed9d3848f8b98834af67102b720745c4ec028fcd0aa0239277e7de374f" +checksum = "483758ad303d734cec05e5c12b41d7e93e6a6390c5e9dae6bdeb7c1259012d28" dependencies = [ "libc", ] @@ -1652,7 +1635,7 @@ dependencies = [ "concurrent-queue", "hermit-abi", "pin-project-lite", - "rustix 1.0.7", + "rustix 1.0.8", "tracing", "windows-sys 0.59.0", ] @@ -1742,6 +1725,60 @@ version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" +[[package]] +name = "raidillon_core" +version = "0.1.0" + +[[package]] +name = "raidillon_ecs" +version = "0.1.0" +dependencies = [ + "glam", + "hecs", +] + +[[package]] +name = "raidillon_game" +version = "0.1.0" +dependencies = [ + "anyhow", + "glam", + "glium", + "glutin", + "hecs", + "raidillon_core", + "raidillon_ecs", + "raidillon_render", + "raidillon_ui", + "winit", +] + +[[package]] +name = "raidillon_render" +version = "0.1.0" +dependencies = [ + "anyhow", + "glam", + "glium", + "gltf", + "glutin", + "hecs", + "image", + "raidillon_ecs", +] + +[[package]] +name = "raidillon_ui" +version = "0.1.0" +dependencies = [ + "anyhow", + "glium", + "imgui", + "imgui-glium-renderer", + "imgui-winit-support", + "winit", +] + [[package]] name = "rand" version = "0.8.5" @@ -1868,9 +1905,9 @@ dependencies = [ [[package]] name = "rgb" -version = "0.8.50" +version = "0.8.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57397d16646700483b67d2dd6511d79318f9d057fdbd21a4066aeac8b41d310a" +checksum = "0c6a884d2998352bb4daf0183589aec883f16a6da1f4dde84d8e2e9a5409a1ce" [[package]] name = "rustc-demangle" @@ -1893,15 +1930,15 @@ dependencies = [ [[package]] name = "rustix" -version = "1.0.7" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266" +checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8" dependencies = [ "bitflags 2.9.1", "errno", "libc", "linux-raw-sys 0.9.4", - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] [[package]] @@ -2306,12 +2343,13 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.45" +version = "0.4.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc7ec4f8827a71586374db3e87abdb5a2bb3a15afed140221307c3ec06b1f63b" +checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" dependencies = [ "cfg-if", "js-sys", + "once_cell", "wasm-bindgen", "web-sys", ] @@ -2459,9 +2497,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.72" +version = "0.3.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6488b90108c040df0fe62fa815cbdee25124641df01814dd7282749234c6112" +checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" dependencies = [ "js-sys", "wasm-bindgen", @@ -2824,9 +2862,9 @@ dependencies = [ [[package]] name = "winnow" -version = "0.7.11" +version = "0.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74c7b26e3480b707944fc872477815d29a8e429d2f93a1ce000f5fa84a15cbcd" +checksum = "f3edebf492c8125044983378ecb5766203ad3b4c2f7a922bd7dd207f6d443e95" dependencies = [ "memchr", ] @@ -2874,9 +2912,9 @@ checksum = "ec107c4503ea0b4a98ef47356329af139c0a4f7750e621cf2973cd3385ebcb3d" [[package]] name = "xcursor" -version = "0.3.9" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "635887f4315a33cb714eb059bdbd7c1c92bfa71bc5b9d5115460502f788c2ab5" +checksum = "bec9e4a500ca8864c5b47b8b482a73d62e4237670e5b5f1d6b9e3cae50f28f2b" [[package]] name = "xkbcommon-dl" @@ -2899,9 +2937,9 @@ checksum = "b9cc00251562a284751c9973bace760d86c0276c471b4be569fe6b068ee97a56" [[package]] name = "xml-rs" -version = "0.8.26" +version = "0.8.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a62ce76d9b56901b19a74f19431b0d8b3bc7ca4ad685a746dfd78ca8f4fc6bda" +checksum = "6fd8403733700263c6eb89f192880191f1b83e332f7a20371ddcf421c4a337c7" [[package]] name = "zerocopy" @@ -2940,9 +2978,9 @@ dependencies = [ [[package]] name = "zune-jpeg" -version = "0.4.18" +version = "0.4.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7384255a918371b5af158218d131530f694de9ad3815ebdd0453a940485cb0fa" +checksum = "2c9e525af0a6a658e031e95f14b7f889976b74a11ba0eca5a5fc9ac8a1c43a6a" dependencies = [ "zune-core", ] diff --git a/Cargo.toml b/Cargo.toml index d26e25b..67268bd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,21 +1,8 @@ -[package] -name = "fps" -version = "0.1.0" -edition = "2021" - -[dependencies] -anyhow = "1.0.98" -glam = "0.30.4" - -glium = { version = "0.35.0", features = ["glutin_backend", "simple_window_builder"] } -gltf = { version = "1.4.1", features = ["import", "utils", "KHR_texture_transform"] } -glutin = { version = "0.32.3", default-features = false } - -hecs = "0.10.5" -image = "0.25.6" - -imgui = "0.12" -imgui-winit-support = "0.13" -imgui-glium-renderer = "0.13" - -winit = "0.30" +[workspace] +members = [ + "raidillon_core", + "raidillon_ecs", + "raidillon_render", + "raidillon_ui", + "raidillon_game", +] diff --git a/justfile b/justfile index a8ef99b..7236755 100644 --- a/justfile +++ b/justfile @@ -1,10 +1,8 @@ default: @just --list -# Run 'cargo run' on the project run *ARGS: cargo run {{ARGS}} -# Watch for changes and automatically restart watch: bacon diff --git a/opengl.png b/opengl.png deleted file mode 100644 index f765a0704aa91c2e9876ca96e4cca6a47f2c3d3d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 44866 zcmdRV1yEc;wxpVQ|a>Hco0ysQ`^94;IL1O%dlxUeDw#0T}i2h3-1OS@_E3i#)% zk+`A^1cWC!1jLU(2#6bW(6Mbg->PzG6E0~RZ-s0 z3UT0bNGC-xL5T8k{6p}`XG1A5VTkv?pWkhTe=oz@i)%PRKp^%0Js=Zkknq6lAS8qZ zl--w3+Mv_5)jaOs)0%9~My<~^u@?VqKz#nlMEB*ZHzVvP7}#AoaX|?{Hu?7-_i~+I zJ`n38{FK*|X3EAj(qgxDWDu;@o;@yCot9kUtC`s!Z@bRiUumIPY!qLvU3&D{d>S7e zA1yyy`F8J>d7ZxBdj$7I5QaD~28wiC=sWn&7r`zP@E1(BKFZ&A`O1H^!9a!ogUny# zeLOTPbI zVg6Tq|GUEco1XuZhW^XK{2x-{zZB-5^ZVab;=i1ke;Uod4=m#U#$&aE-n~Qob!Uf>IkwBW{h^58%FaSi%nA(|^&ehLLj#|a`RCLSZGVji z0s-!Ta``Xm_6YAju`i#B7LK1h=Dr4N{#bnW$Ex`aD4Eui8n@Ss}M z6YO>)g%6Ftec+U)4PS2|+`%5)e#eTxEbJ!-EqiVuCg%me8~H^LtbAJhfSz3JwDkT! zV8KUHH0%*{Mx7E8y*qh%BqbqyK7`q=aii8ABcArbfYa#s8eCLlKSBGOJ@w5^{-sQ+ z5DwR!IltiU<=gKPY0&U0oR?hqbEvh2I?k-1GPX!tfPq=Xk+7c|1+aV!E#xo5JcX3O zol28)fs++C?B^(HVy)7g4am$y@@pm%@hb7u^!{P-h+-o{&Z9=o$*0|qxf*p7^FKb~ zxRA2Y7*#b#yUQz0ly)fsQi4riUH^HldcS?RpDqAP`q#OCn_H~4g8A5!`-jQ- z6RDDjbo>Y9*INF1`;$sD)I*~X*anZnjg5^4!m-|E;{BCYCWL1Ohi7c}BU za@hcsfs#A)ao!rWp#^H5+mji02-v@VFA+XELNsz8MET^PyiI?^N!|b}Avw$ZJ;wkF zppVML!}?)`Bj>F~*XA~|GJtu-9r08Gt8!Y?~JRG zpo&dv<3Yrk+{k_D$hP&uzmTy399O$YB7dq~Uv}OJtkifg+~KEo8_)f~%Ax}3Lo$U! zhmOiL$Hym)k>i(sfOf-h=qZQ(QepQ44}EIJcq?W9X1j0VjUat(xhp^f9JFJV@Tj_* zY_ADdI*z|0ned`-(?|2o^@;7x&<|%zr{lg_W6mQLlsxs9q?>@^pTPFjs|w*^F8bbsUpcHqzD%> zNhPix9&SdKIwmxK27FQ zw%{rK&P9wU{H1{j7Ow$8)!}$yzWdh6eGiAu9R#FPO{W0oMT5B{bJKnf*PbiowMo5x4@~7|NXO4ytl!Y+$6XDa;=Rb8kgf5Y zbfE7r8j?H!t(Nf40pC^>+f&S!wYZjxqzVrlApJEyELiO((X+*xPW!K5dHAG1E9k03 z2>l48rI0j*w11HaoF}LaUs0);OTW$BmY(M5Lp_{#=EWyH2c{^b_tf^9x7X4dWpLzoECFu zONR@0sz0r+Z&!-@42@pzuIFD%$TzfiM_+G0qCXkycSgq6EQcYc@mI(HmW$Z2#1m;n z*ox{Si*xS18vYGF7VOqN4Kr~OwH_kU=#GbHudbH z#~-YYAU}ak<9mSgVtD91S$^1rBK{>Udl4sl^(RiAzKQ341Cm7ek>Xll>t? zb$C_PqURE>26bn}co#|+^m|>(Yp-(bHH%OBVz-`p;pFIFbKMcPE*&Y#Grxc)-qd-~ z!*%U=!`OLW+I@vz2{y~$DBr{6?_N5yd}MiBLsQk@iIgfT7J3>gM8~4^IOM}YGOI~Q zAw)IuEchxbSmkTW$x^0jZ?xy^2S9J{ASRr5FRE@4{@D?_g zo`Z8rRWh|V{ z;IA~z#I0)LTAJ4{2s+I|z0?I+xNxdGgab_F0DcvQ&E3aGBCGVc{H6lIOr zgx07WOST)57$ruIA2zcW68mKje!@_DYb!5n7AiP{9NZ%IA=MFzGWWStgNn=z$}Z zBvHzd5Ovq$Hywphq|_!6yFA#h67SyeaK)lloocIc52XpF|}(U!RFiub$B9*gnxmXA2xm6<9*n3!DG@iATn8n`>6 z>aWAlQ?gL|eM~&MIFQOTY$sV$c`F!^^vv=wc3(VRB9O|q|8^~Ae?TyFItLv-S4uNw z$Lx}k8Q?`~dN7#SOdL)52nUevDCEJ6wqj!1{Z=L47=@AVPG(XQOY6f=xNAKIlfvs`SK$oIzm-oT7WoV2h<( zUl5AQwl6Lt2Le8jD`K=~VbY>7)KySPpm~5E+3FJJYykRK>fgMx9QCtN8(e0kFoi2p zsoYIxs0bcW9klu3UNHV4zNE==r-1iqlABR&zao4g{*j=~BNRXpK&PN8KPlwqDzAV= z6N{vTJcm=igjc<|DW8e3i8B?WOC}W@B^z`f`4GWayzKc$&R9A}<>*5ZJBz2ygD#6B z>vgj`D;YNITm!l5YQk}`6AzZbKKqbE8|z<3!Sfx<|)Ny!mQKW zIo)R@YDv|S%RJNyR!dVwiruWRoZC`eG$QxqV@gf1-8oZf`dfI|d6t^+HHs1!aK?&vnmRPZ?0l98lPX-hRgk?aHIj-d zFcOw&haDR)LSho=w|r9di^M$I#jkx-I8TrtbW9m9f7{Afy&Dos6OA>q0nTwxR{QzTZ9cr0U(Yl4w;iC#Xvg6VR~&`nFnHselQ^L;e zO<93bbyb4eS5mUz!R1drao=jrFkMh@IVP0EQ<$nYG15t+ERSG~o?xFaR!fgcz3hlq z#{Yg#w5_s#zrmn;56zPe&PeDO@&>#XRT{SEGvW+(U54i*dP;V450p`0>6BG6X!3&w zRIUuwkNoiw&oyGnaKua`GR=|=ZiXgfvvUwsgt+3RJ;ep+I#3y+Ndn5fjocJ><#&T*gYavhJ(Cvz)En(#Q;I6w1_YSIVmnP z0DRPJ7&d}s_&e9%Hft`Pu`(yng28TkNX$}0$7kJlPQSUd)t6azG8L7I;bUQ<2(x^{ zwg9$)BxO@zXj0ir@({3MkwYEKkQ$3{>5&RZELz$r3}(WEC%I-#0iFJMT!rD&;E*6e|lhkxVNqkN`Y% zFy@9*L(S)IY*0WYp5@{iDw&`=65F4@(uBKOQClTH2OUy7GU2FN3ocsBuwcnynt%}X zbhv*JtyDt3zjMD~gPvPF48d8crl+w++WXUCMlxJpV#3JBYGH97DlyoEW2)>cC;N!+ zBQb|zv`wDwayiPHKw2YqF19#QlY=ZOfohoyZU71ufdz2CAJ9yuP%K|=O=oI~osmiq z##~qQ4YqEvo-lQKstkMNyyDfKCzNGcMbRskx`MhVh{Py!O-iwK zP$ge+zFI}qaBt`$4}nItWXcFiSyG7-lV@kkB7V#?{ zo!MZoU;*|NQUM6iZxa&>TW3BZvl=6o5<$a=SDva_QCt#%!_t=DnCq0On5wOLU&v8t zV`*P`XmIc1%oBLjkS|j_@8W&WA~;2a+)%TD`=Lbud=x6^s5qD`yQ|~xgj3%|6)KdE z4kQt{4t0m(#MQFpg*C3)hB4?2F&IYoOO!{rvOq^FvlDaM`C(CEDm=ID5<9fvjvk*x zhz1wpD3?wp8<&!3Ep&Y+x_%R!H}2r_fVexw-tHn_D#29*9buX);wF%0KKrX7hSAxm zp@CY0v>c6fO=d+MRTuB=V{T7aXA4cqHaGOag{v{0RWgL?V6|K|~4}4>w!= z@YC&qN49$k7w#@65^6a-H!6eRo<9P-RA!Pj9UWcGG{9elmimwy)7du(lOBgYK3hyK zN8jW%8Ad~8m0rRbq%GP+-4m8eiGlQ0N$$6CeNLXS71g{!yhuKWEQH_XA<<@qt}7wE z=aka}BpTRYILRz;7teLV>9+M}EftzaAW`S2$Utc3aMku(Fu5}2`NkA%cs|UfDKACx zMb_NtRLiNMsv5DJV}o(R;NoxFC5PSrF!iT)E0js0&y-U`-cGOE8E!vD z1Me@t_W_RIptc|)YGU-#M~CC!vWIaQEd`Uzxo%ziBQ~;OGNYkIsn*6- zbK&D)V>^_&XE|~qSRCFhh^0Y~_g0B_PH;I>mB`WD4NI)_7j75^#D_@^8tdT-^PL;v zj&W53nzX{Fkp&UrOgYxBZ}BeE*EsoZ7X12=!G+j-XxtdaMasEebXV&b*&USNRq@Kv zC&e`~#al&6A+Dqns(6}MO0NPWWzN<@w4pleP)3br)p$%wI_1RiwCXYWUgIX*0pJQ1 z){wHISP^Ge6n8xEqvK^3`EqT69}6q<9o^R*9HFA3Y3vq%WR>B;S!u>T z>aZU1tqfyN&oQwsglB&Tn7~v>zysr18BN2imJISFb7Tv0dxt7-jkvB@pVL!{67u!1 z;8Z>oJ1d?NAl=7e1UMrpmgL5SS-OVW?_PVf?Ha2y=}pGcg&Gf?wt7kjV=a?)=l6ot z|Aa&c*Bh2ma;|zJ_66lxH*8&7x&AgATYZ=gS?f1(1BV!1c2YDP@1trwCQTz5(Bqae zi@2I-Ou3AOKy@6m_QHqd#7%Co&{&i)2v#$IWbaTtKAlo?K|DdCR?NVT3)jN1Ym74Q zi}CcF#9{iP7_LNPYFgSYxwyd0p*B*=p#_}|IB(RJkX3_(0_YGtDmr^1SBreLs?AA0 z&~5zmsE$v1(7nueuhhB=Wwy!2;0MW133f-w``l`4VQKYp#2fY->9NF}${wG_>KqzH ze+Lc9avT%4<9wS|pvIX;v#9Ro0i}G%s3+LfmY9;Ih|v6|usLo_9aMWXG-1-lC8$a= zO?+r>w~!{>;Ml}dP>q9rZ7}Vv5USe#)e)e;P{%+8tHeLD@20=f5L?qM@5+Uh2W%x< ze7EnxF4wy!(0-~o*JlNn8mh@ww^epJ;RB`qdOom7i4`gy#>>k4<+$v@SU8h4&rMI4a!4d5d6yLrArxHC zP@+q2P8!k|27-#t_9v-?!h#&6caaShk%{j{yJ&lKYm%VG?Gj&4MBt)F6A3Zq00IS+zs3!b1B%_x2&*|`xZ5x&72F9M3!GTE#nCj z)1(|YS~Y_fei$WDy)MH4VHDo*2bTaef?Mb~Bt_=G`VJHwVSzc-Bh{BccAiZ6*aGuc7WzIed; z%1T}mR<<%qwX-L%>)t_uPZ7nohmFrpQE#ELN2LFJt1oR06=jrUY4aWEGBN%BCIb)w(y4h zo7OjgveEYTpm9NheGm(p(+rNYX-)Dtf&r_VSpQjul45JARb%0NXoJp+j`x{Pg^->b zG(Uu(Do|g?ZU5s#SH{PS?RXG{U`c6Vc#k=VKtPa0o(iQn9q!Ovt}j2h@x90 z_V&rjpw`k9Mt+!zl`VhnG|+YymUu+2-gKCM@QT;SXgfK5_-k6md{2mmON&r2dSM}B zCP9DWVvu*vdEj+zm@F3G#i`cCQenf!gq|A;GEcUCS)gCw!1X}`xM1g^MIosn48(SzG&yPVDL#qgwqV|wBra>82 zW!}uGs}tGx_#!B4Gp*=#R*G)f9z7HaOQ#hlSx!DcF_n@bI5CUfPtIXfyB6kMO(byg zK##@T%ZY#7v&{cUpndhmk=<680-Xk~Hv#i@YXMRf9uR~fpNOy;c*5?kAoKDV&8f4| zChN2pv-N{wsY7J}wfaFQwA|jh-BUt-#d*I}Xq-SW8lhN_J>T8j8rF>KH?xI8m=cC4 z4~KsnIU=k|HujU(8={vDX8bV6K;?D6S6kR1V(_Ha?bQel^mnoRsPd?~N;O2p zjlK%KkI7j~hf5KCWA?usl9i5-`EBHluCuL#o$@D`^imdmwS8MMI7uV;-DgI3rNe|` z?RlKz8UhV&-f<5&;uqgf_r`;(__el-@dxHktT_3`l1wF9D5V0gw7wf!wtA@W zB5VpyQ6BYSw@bJ2-TXXzn>AwGJgkLup6{xLSy}&KVODT#tU^SDtAVtzl{Gr=_BJPL zJ1prQb$og`g?B|~rNcr|Q1*m3f!+)M`BoPIy>xf5Z@nE?i`;$6kCkkKT8Hz8tAxHA z0U4U&S5{at)R{8*(ma1p!6YsF+-mr!DD6;tiGZc4wP0hQPpP;BL&q=4sU;8cG-}{m_rsZB(kZHjgCk5YC zonCOC(2$*hTH%z&Qn+(#u&|S)gc9>;Rv7A{NQrjFB;lzIxA$nm3JsPGU0Jg(5~*rn zjM!;saea101$0~6Di==su|0INSo4&}LkzH-6ni+*kh%%C3$66t^N(hv-}5NeMe+N! z0HLyA7uTY=$(`TpQUa&E|q1`Q2kQ zGDj7bBdC7f6rgI6sQEPzzrpOxMwehSEzm~{CZC^X70)s=DcGKfTBV6gm8SLt(am0P&{$R z;9F=e3XMxkejNtgm<)JjdN5r?icG40=INQy`QmFc7xyGDYsAl~vgFEV`Ko22+dAg- z#@k7hm#r|pO+>#t3Z7)}X2Yzp6O{J@o)zPvQaRy#<(yCL?)~qwOhmL9Gsj|QUln&f zTPaqlJnC;=df<@2vb3~B3DzZ)&@i{Ni%WKc)ZOaAN&~VGbTCuOaseI_q1k_^J|GPb`@$d z&^&>xWVt395F-hgD)vkQdVwJ;@N1XheK!$862a%Ery^zx5O>H_UBj~3$}7>`&QKn6 znO;nDe2*GrTWqsDSlspJoh9wM>2;oL$RuD}VTX>A-q=oBm2UF!A`!yOPv;7 zzD!x6BoXDIdfoyz*d$x?w$kKS)!D`M$XgzqFojd95j~#K6;*RRPkkO?$Ytrk8@ps) zDcG@Q_TuEhK8t(um87T`u}Q)C6EB%tQf#aUc2cScRg9=2n-FCK$n85 zOHiOsB%Z56n3<-LQZ7-!$K}hjvPA)xN8d%snd3oXF|k0DUe*#Q0@<@(y;;980dH~+fCIgmOZYGm#nE!G+^wK$g@1m0Fn zB&|2e?&v@Usov%&7K5XqXtsLb`LpMTDB<;hulmrj@|Boj$Zz)y3J`tYV^9$?nlj8I zF*XX6xTtpvfLuR$i%B(@@sr`qK8wbdDN~mfil>n~mBA1fe&@yt4{~{)C6_M&4+`ZW z`nV0J0%sB1Y@utZOP}6rc#EC0N%D+R8K9B*RthTmefGKu4a_Tn3%=0{?I=qXiRVba` zgko|(%Ds&g)B38Vdn}eFosbztNCfAnd2jFxVAX(>Jr>^_GP~LEFH8@0n%KFq5FDHi zn?1d^8JJYZjPpPi;g6EkR+J>Ha4P0HMJv(4<9xXYIfjhr3;@s>(f+XNpG>U10Gefm zC-L5UtB)E03Y+zZP&u*Q&vh;|qBa$Fsq@1_3Y_C5O}|JIPdRhtAM4aLH00*zYY_EV zoqK+{x90uDG$HyW?GdKTK0L@~RJ(WpL3xyw+C|?R-(CK7-|RlR=i*!-M58-A%K=mO zd3wKEOdLkT{%=N+HgDH+7YhUyrwqx-HjYuK&|oeQ$PyV8vJgQSdFU??Kwo4m-xFi( zT*kMXzHGv0{e&Oa8bkI^*YpQWCHg%+;VL(N8t>VaG?u&q-T04Ev2qkIABs0B+NyhY zIbOu2v2V1u84b>^7C|TVDkkzK_FL4RZG?ps*!Kl=h%ygurWDp~*i?8?acQPK$dCk% zhPDu`gdQ*0^sPw{Wk$&t2iw4o+=&-5+tuoCQ&wK8rKy-Xeq0)b%XG3O(tU@X(3w9? z)73m{;W+X%gdbX@>!etF-RJoxhtc(P@U9(d{k;je=x;EdfRkV-e(0%++Gm-V4swno z#H5}3u;PC2dO`@w$-_;v2RzMQJ%|;p=_{~_-xGeG_wk`?-kNy`;rD?Z=f9Ws&4nSB z8>BmK*m%0-cF=E*($vn8Oti!=Gr4Sd6#cM$`^ol?N^fL~t%ww3(0%)5{z$bCjT$v& zFP1Ojz$>ZH!y`j^XV&ZC@wXADCiwXzKX20DFxeg=>mj?NAsdn5(Bmi7;+>vd>eX3< zo?3@nyE{X*aaCT>?#uy??zvs!Ai_)#_LpKGMnlsHN}wS_5U0lEyl1OR0tjEn4*!L$p_v;Sb8h9A$smd4tuy zO(WXU@q58<-O!NR<%sy=-?gdW{Wj2G*qW%E7HlqY`CR3HSOdLVCD{1(sNU`9G|C>P z5xp*Yj?enc)?UeL>lnqtV?>1=?K<2aZyVn$L!RIUJ9t%VQ>_}dUhO<#Gv9V2{MbB!DLJR(JXB z!^V26hlpRIn5gJ2vkl18%iS;wBAnfp;=m+Euwt(xP$yUPdKU{< zzOoBW@^Jx`71Cq|H*2JrZ%>4@iM5(BVX>5hf#X2?LkwZ z4um9lTou=<60Zc>TSFfs&Dv9%+YN3j)TLfNf*Q7_&)*`}c?4B|YwNUGVBih(6jMdir^D zVZAT-+xzW^h-swDRUMmqF27Qts9Do&<-Xt2WuhBz#;x$bZ)+(d7gV7wmuV8NCIr~0 z0V`L@qzAePLZstI_W+Np1$y&PGGon4{$Xo)x40*b$fPh|ibN-s+N2pwvp>W8YTGa^ zTF)Y2Wv8ilz>`D;hfby5q}$nsGZC?;R=;G7F~PXc(6cx|eFetOY6v)h zxQg%z4A4tJ1^tdnC87jxs02W)Vj$;t!(2W34EClf)GlFZ*XN<&O7Os*Klfr??uIYI zpg2-rCSis^ZZh86<8CQ6KedPC7B!EJ!vW8?4?Q(E2VNJZXhANrHWwK*V(C;_p9h;EZ`Wc+dpOM&CYFET^ z>G&bkLL;|1|0qfSuKw{&Em%*~$^oM6mIt-?llCn)?eb3o*aRv?z`czU@1FT)wT%?N zt@sT!p-4Fb3T+b+{QZ&Nt@>|L4Htk~CIZg6RoJOgRXjMW+AX&ianP0{8fRi_@W^|r?BjJr(W=3%eO zK<5hYHr8E0o+4G_jb@qT@)m54W~?0_6T}|pO^78>h_kNRw9N4ey_jPwDv5FwCe?Da zi?9@l`c<-t7FXD=`D3;7S^^c&Bw4dwnqX1!%4FC^=$*V`uj|?hd|B+d8MVxCQHTmy z>P;LSRsKN~DcVra6dmo%a#bpg0jS+UweCOC?)Gi%@~&fpBQD0|SDwH2^~RM1RBTjX z1b*)^VZ`r}Gc}hqoTB=%=w;8XC_7G1*Y%;i6X%V+F(Gha8-mq#@yHWPsXh>*d`dvi zjp+APEBrZD-Vm)p`=r=8+jf-SnchP+qpwX|iw|{-iY%QBwH%e2;-|1-fqQXo$Y-Eg#exfcB3ZjyTPkWPNkO#+x}(QVg7vNIZO-+E z00QAkXuzE7&gz@TyH|eHDDOw1gO*FomrW7BPCE+Xkq9|m*8pHroZ7ZLcw;t0a9SxX zONl^gP9eTF#5|npJe;OU@pXU^P7jn@u*AS$l&dcHwa`g|TQS}p50f8(syI|B; zymHr!1+wY1zYY8GL90cw=T#(15&(JI^FuUDqGhiscW8AI&x|Eqw4nofihrmD2u-BH z?GSh~x9-k49{^g=4tHxmWtdu78I23`zx^X^?D!`xl+8QSNb2ziF#S{1Y^r?ao?bq$ z2A}`hux}nvGDopo7hCfajRDP&BzX+5C>KK$cT+s10kyH`*SrtjaiO}EO}3~K9HpNbrUB1+QHDW1fn#Gb=2liS zQw90Lz+-Sd8fsmps1?0b-umhr(R>|8tD$IiKg&5^+Jt21F_Pv&!cV-jb6Gr6E=Jcb z++!*EYkIfmK>qZ1ChKgvqD>~emV|1zL%ecIGkPSwjM0*(VYEr{fJmh>9_3>}aONyp zSfVh*%kP3*^*YUDHO=C9@TS$IE+sJwTX6O$igcqH-O%J_qtoX*BJBPQx7C28ww*qn zCQ9{a!>xR3c0$@>+u+qn=*lK<7}(|hwcqeuqP%uZxbxqXB;p^0>% zXO>dGya7rF2M3cvffQ(mROPyDnqoE0&7K!!dM}=9K(++!$WyNd!_%^c&1ia0sE*>m zbh7eRlaEL$iK6Ak)$($_6u=U>gcwH-$s)3K<-2;zec{Ty0IJ74mT!fqT|n7n16lfW|I0Ts{fhqpWj8w9$K48}@}7ohK{ElFeZK2E`fq zL`2VyW87<4$sMRrNjSc{u$pgX!FtnmEoEN3FVD!Wz^=8&pq4qPf?bE&B{_=p9IBr` z#}{Eaw0&w*He!pQ7mS?c@TTP8;K#t{bLi$U$SanlpPW`F(JqMPYO@|R^Q5}@a-G$0 zM?)+n&92rtF^>pV>+jizW4aSX0*N7RnP87Xpk6A>4DrogBbOrsnwN03wN6z3yoW}! za3mc|8CvsMRw5%nmnF{A_!cgfrb07FP04FQh%ZZsK1L}&7xzRIEX<%u6;cZH((qbjKq)9L~L^!z+I?hS^n$G^9}e4b7GUYq?NAnR)1O z(l7#PQV5c5C26wZb|vp*WWaj@9Jvh*UK%5FCml4HJq!Ggx*56b`$Du*hshv&_Z>!d zsv)?W4`G2Z`QK5O-OR8$$}EPE50Ff;+vJXl+ICV4l+CL1o1n_*%FGjG>O$#C5aY}0 z$`A{0@3%);6BA9->z<@}&YLE>&O0809%isI3-j%mhEfOy zO=__Ja0kXtF=g7Lm&RC~<5@m@+*j@2#CD1JZKQiXlbXb(R#h27p6yVVpEl#EE{}^B z3#vVutE;U)BD+dSVJd_pa(@l_HTU|hqkYHOz`gZX_A7Ly)xE8+5v&FY{rhd3Q=4%5 z5A9PSH=hp@q2m-YT!IWe0aO5`v653O3rp1uDHOW8y1EkAN}N~F(+#=JuAwu+1kW}? z>kG23zu&|5{-ME0Ury0deX%xd(;>p$8IC?Q&>zZri7n7DeY@}Qh?1uU$HeLkHkO(7 zkM4wU6O;retQH47>JZQo9vIF>s)jnuH@73{KK{7BDQ)E&IomiFP*tUHg0~VanB8ed zM=aI()HRyZ-hqyAiXiGdtGh!z7e77aB@tw6cZ~;B+-+& zYR+`qgmQl;()%5rM*mr0MXujz{ zC_pi|ONQJzN`QLv=(8|;sG$U<_Rf*=UI*X9xCbIeV!CXE+%6Nd=ckr?gextnK@z8) zwlw)jhP5lR>0sA{&&tdD!8D3_IzBDMO%h_KO3YT8BoC-ViqU17bA@&cE)>^pS+CMO z4R)6#QXVZ*4E*dF6NWr2p_*m=aTT#pR>xh^Jw&WHgg0a8VRtJb(9s0A@fu7~nXg+U zvC@YFKnbxS6&mo8vT83=+Jd|RZInZ;z9UHhsaVw4xUs7=@PHiWbe6GhU%9VZViZra zr1u;E*{iT-(o$;)(kD|2rR1U7b=eIKYFOyJ8ZXz}>w$Te*H{5zt6_rKzglSp5{C>d z!xk2TF=&f@5*tpV7HErKGB;C)=?X;K%q=VsFj+}_7 zM=73S#!Q%)zWwxh#+IZou8O%e8F=lp+MntB2woBFQDhym-}F2*CSQ%G7a{cr^aLpK zG!+(FjSn5e4~48C7;7t^lFTOjih-_> z9HK9gU`T~j0@e%;Zu|?4#7aC4Q}x-pqq#aJ@V?^~d4EM*B51d&I@Fpx{PNO4T2}UI z8LXABL#N?&d|5jzE?yxyt_<3>d@16G2W`&GXw#U(&4mO62Pf)$Q_qF`9(B6#4os9i z0(F>kJBmP+a%Fc^_8k4yCJVbBBF2G{-==^$C_mde1G4)P5g&!q6fXL4(%{cJViU=+ z!DjgmXDJ|MQnvdq?p@YOh?A@Z%yFE~2aFwUfwYW@Kb&SZuX5V_lq}RKVnU#VR_*U< zchV&ZXvB^*0M3xR^Ye)&Zq~YwEpnRi_X*k@>!4yIJtd$@=bt~Ea=oJHrLQ>T8%>gx zSC>tGk8!&wWX7ko%TtJvRutXhi8njI&B@<^{c6+|?e=Gp@nkLgVAQUe)1Yznppz&u zG5l~U_nBU8cg}Q^_3c3JfsY`ASKO?KNbaByb^4!~#VQ_nxQ?yI32m}2$u1>-6_AQc z!sCi_6vY6tFHMU$j_x?hIvZy}CVsmO`X_iS#eYrBNN;qKC34nx1 zID)79=+(H@o|R*o{?J4=lUkD*WSITSnjM6;HsLWH_drK({IhX88}jfo{jk^Zcz&%% zNn6}_KJ7*+Jk4>*X|}n<)a35cn@cTw_5^>R;G)*#eVsqEB@?pBgxJ`%d~u=zb%HZJ zy~UR(2BKRWV>xh>Al%0V{*z-6S5>|&&kKKq0Xt&Dpul3RuZmo=e(s^9t4@Qa3!(6#-CdQIPXtS_XIUtdR<@Hz2}wru6w<~@;?nt z$m{42h2aDPOW|5e3O|*PqE*L!vMRM?xGRAjAq1&@U(3|;{jo#DI(J=}VY*tR?wTB+ z&uu^^<@f~`fJ&Num*|O^@+Xu?Dn&;9;+PU+M6&uSdDu89QeOfmZga{ZLUwm@bv`fd zN#a)?Ha=mRpq3LVc-30G*|mo-d{rofkxfT=-4DKeX-O;f#%;^k>As*(E372n5nEO< zG-0=>eqz#pcThf?US<1t?)K~ucY;E2hxS9%@4aXEr?p@dv9i5v?LF!4V3g9^ zwEKgXq+ovapUp*SPA%q3bET+7@&(3F?u%NoB$npZygYxz)7>}t-sqUJVInQrQv-CsvCBd;fT zo%-iB(KlHkMKLYUW zT36#rD)vN)S}ie?;SLqXZj$>WuD*Hk+ayDC0n4I6?>be@;59h%;#J=uItf^6Sr_Kn z<||1bEh;Nti4-Y!DGqzhxk$hO!j0vW779)9VZE2U3oU9iC%yEV@UBKJ&2aLxS+o`v zfd!%Or%AZ`v37B-wRW{fVe)Jb$$1+j!OWQ~tVDU;NfXpWh#xtSw)n2hr`?Fv5Zb%{ zj;PaX!;$G?rROQc^Ls17%BZde3~Vp85Oxxz-5JyxiexZeo7Y@%E?9clVpKzVxcK0v zePY+Ef=%>89zSNioL6hZmgDldB#j&Jib`)Qxo#u{P7}XwM&dDTHN`qh-MojAx&oKK zA=d5w)cO0aoDfGY+u&B;e%4Qp)~%p$!rNtj6~%WMhKFa#{b@!UItAvcfhpKCW?}Q< z^D<|8ExEDqLW`~LbszT6_h6JoP-kKO?F%j0@J+vv9{;BLXcV*#p))Mbj|`{m0$C=;Z>=#r_KnQN_y z=kZgafm`39E0orAIr`ojhQ zE&6$H$LpAtLqAR-|DKcWdLzMl%O&xS5f$yAG>=QBaRj?|4PA&;Lur?i7U<#6dK=0- z2_2qN5k)2Tt%w;{Qm{o(4RkI(?P`-V8W-=DvdE`{6{m55FQ4Gw)@VG~J#y`}vo;3N zj}eDxvHhZY@~)PQ$3`Zor+NSO^Wf8faOcqvbFtJDuJkr@ZxYM<2M2ArSnlL`RZyT&xU*nA zfw^=oBmL)ZbgIGmp7tdUu~pCZjgzzRY3$S!-0vsfI_mLjT%rW)v=N~|F?zp_Db6%H zAX83Q`Q9RF9Ii9BfZD7?n8l3N*4SC|=B+hqhxelg@>WCKe6R4}?|he$X~#)= z6qiJ~lKQ3hr{Qw%tMe79L@mItQK^GCUVZ|FO>o9j;AQFHdsHLC4Gv#mQD}uY*b8Kx z?UZ$2O0V}?ADq}S1J$nO;RT1NF{I#~p`hMQwHEZn_I46Si!|vT?z8MV8On9Mrr(04 z=-=7eJ(ee#U|%V+T4y5feOwSf-xKh7RAbFvHjR{bvuUw}^GQFs@1VZA?^CpAlSW+o zR!CM-`sMEENqCtRM+s@)O*h5!D344_1)@w}`0sX^KYUbS*~|PzMeIm}T9T42kP(s} zDAm7&hmpc-_So0tLs$SxN{BfcU|SbzQk)CVA5Xdsz`?&uOB(vNzqOBSdcnW`dI@|# zlX}1Zyy9i=AzBV{h3C6`#Y-?I;H2t!|CxF7&c9feiTqB(~ z(nCU+rvRx|T8Z6-OzPYPNbx@ayFf(0L*$k*N5L{2)cgQ}+GLneqFLqg+y$#rH?h0Y zHRqfwnFJx*Vj#m%TPxl8*k`}8=%0rq_AjJd%^a6l-Cyv(HSey%N51?cU1)Ymq)we9 zJH76CpCkG_sW04+ocujUtkdy@OD>)Bd-#i#M`rmIm_|GtCKS0c!&C{EZ69ff0KyX> zOI(ooU0@{mWf(DCJkGR_=3&V!nnuT#8I*Il)&xqh0(H@rD3%^3^n8@(x;9unhW+S2 zuGI=8XDm@3gX8Db#iIsr z|Moeo`cV?Jb(tMQ@FdM+Xoi4D5GQw?vr!mcuN_mf3I7eK*G!FawN%m2{9!a z@hB25$3xz<9M~wuT@?#IWq zWZ7YwgxcI>0)#ZYV2v*0x;&=>azU00Ot{5#1FLIcMKfs{ou-6|u{oq+Nw3|9p{`?r zl9~XX@1a_qTRD+pqU#BVfaP;^l{~bShmkUZaM5l@eU?T-T|83y0wNO^&}qRZuApAeRr2jkRDpdB&XUFpVcx zJsg9vkI)o9l=-)M$V=?KTiT(R_;QAZa;twx+`EkE)G23`ak2u=)#q>- z2MK9-!OG@~JWBJ5U{!PjBaO54V2yZ8hs>o83;}Fw?)iOw5YvmT$}piwmPE2dY)-hY z*b`hh-SQ~f%LkBDV&$X~IyqMg#L8p^$*GIS4ZTRK^w#6*!YF%RT|DbGU(1#x;diOq z)6*ju&mY8u*`uUxZp*+_>~^dh96;x_H{i9ee&vFF4xjnKjR;O~wxFz?*H+kz=2%Hr z<93`DJ$XYUOO}I@NQDs(Jt6RfG+;vBNNuO(X!oye8QrEdRB zbI}*J9~>UVN56juaEeTTe?hO0_x<&oc|mA2!8*N1l70tyq~_7c7}B`JqooXWLmk&W zTLP@=Xu^){+;eD@#)KE`nq0WUA;X0%+?p;8qo;ZhZYnt|R*qhzTb4SK+m?=888ZjK+!d8-H+ffl+J6sA%%Y{U-;^8on?CVM>e7~-xB2dSs zRH~x0R6y5s76T(&F_Jp(gv%df-7_$FU?;A*_By=g)vsFe?|55&FWT!FB$7$EvY4@w zD>*-GSr$v3FIqTf$`nXNb1j}mSXc|;@u;i!DU~Yd>MWsUcm$hDIAO`k8?BhmWU*`4 zZmjC>M|;~7C*|%xohaGvfi1Z0_B-*? zm%Nx4g+>yr{_aj5rTH{6bx)g>zQD|GF?~TMP|_le?c4;*Q>SlTq)KgiuP)XLxj<^N zG@|7yspKl9HrGw*g=$5z+>O`qI$rD4VaNY*nv{ z>{JGwnG7Bp*nuO7b51<(MqR9i?Xz(6+O_EI=~AM#YR>;gS+MyBx9vQk^%Yz4`_LJT zB9(UaM2&|o;1Gw-x&ss9M>d9?Et65Y3{*;m{b)F<$onL8-XvvZ= zP9$7Xu0R(WHo|C@?s&y@kVPL4C0lZyR4X1jyStIvJ%BqWT^*S^UP?}fI*yabW~Z@Z z$4*9?!--7?|jen+PZ!Ub{N7tWFA$d6Uk7tTy;ETs8DX}MSUg8C&Oj3m*Tq7G<}h-nc+gu^L755U-PwK^>lZk zr?V4l*FA_K`$;DxSvmJK3?12w&Vd2+_w`}bs@_FCcO@^cJ-<`SRWg-AGMUngw@Wln zBA&@)QlA@^V`~Z5iyYfgJv=!+mK7Bp4*!jMI9VNsnmSJkr6PLOc`|U_Jve~l7ibwS z%@*qF^(9OxkssW*4`;1j{rHkyS)5szaV4LUbE>6UcRXTRxVVV%V>2)~gudP#cm zMontdLSZ{PS|gDOsYu<{+Jcn2pdQa6ts)jBbpbpwGJ@`|Zv67bJ1~H=Pk6X+I?;=R z2lnH(+wQ_2{n0B<_}?kB$F__~=jr$)rm3)B%a!~)lWs~$mW!m4iIkEpcSg39V2NmH z`Bb8n*2gcUfA&PjMUuWt0bf#}j3h!nyytst+Id=8Y#b z+p=IZp`>KBSS(;-atf!NcA6fVd@QD>rM$_)w@2}y8VOdE+9&@t$j90JK13v<)dU>QC9*lhGefRO zwV_A4nwnd%Zp|8T(hSc^jiiv-+O=!&)la;gH|=_nu(~iYHG$sV1DKwkuIqd6*gIaM z5>Z5Zc0Us;O5k<`c_3vk6biAr$D~3K#z;7XNF<6iJw0e?Zl1MDyQaGfue@MmUHvLK zL{7FFJQCIy5^KWf^1fX#||9WKj(AS$xk5Y&x^T1DyJ#t zit80Z1ihR+nkOzgJ37$X(lYD$dDhA6*%G5xP&x;%IpQLh`(!G8LS?rp5}KELoBFqM zrDzqNg^Be4QUyK=ieMeP=>(OfK;r~Ula*59Tv;VkL7!Y~lz`=((z1;y3~b=)mr1iS zzs=8{Hxwppn6Q^|oOjL{2$kyZoDkPq5SyID z_{2B{1_o;So-1#eF6G5)p+S>*3oI7PG;IBQDUgkqx zh0Gs3udy5wiAPtlHg(TWr8ukiRlX^?(szbjsT?c?MX-)RB%sndsH7oX9X?DwSb!H8e6hXTJ-P@PNO_#M?3*HWQ_=sqM&cA*olb&CNV6 zbBQLWc2$rpD>yHaDiW)5?MWsdonVE7^AjQ@dkJolRH=Bq7prVpqtYW36v283!BUMm z8wH;xJz~X+UPbyMRjXAsI0A)YV~P`1XUf6>$o_6V>9I2#;ud zhsTIW%=hMS;gipTQ>-r+i#D=UNkdAItnu+tjE;<)@bBNebw^DN+{xo9TAYy8l0-Vm zoT74=Mg$Xm+G?Ic~rQ*psDSjZ>`DwPCAmxfw zPD#S0n&k?z6^%wY!GEr?uA_DWJ43K&jiFXjL~sfxurKLonLlz|uKJ~jRjD%ZuZl-i zL9L(&)-hP$)22qMQTSx&iWa$Qslo@jst+~i%B*x`8;s~_mBNw4S?+n~pYhmfj9`&6 z;rPq!uutye(#Oe?3I$cgg+dEf`T6{F*3|tyX)TCcE{j+qiQ$pa6B79Q_w?2DGb!ob zG&Sj1PvamS9nV-b;7BWiwzh>aB0g(lePP0)F2*A(!-VN{3bEMSm}$D@xNO+YO^XdC zS4_Y?%Z}!GQu0n&UuVgF1+s;dXK-8b`eQ!o{ZyVGH}|sGV#wQz(jGX|tC*LX@qtaA#xv+>;uR@Z2v7!jpF(=%Hc&pcf$mf&g{XV};b~lX12$qwd zlHoyW!maDvE7Im1EQ^!67qVRX(&sk8FqYj223bxbVFCEGUY4fK@B%b4X#r>BQ_C8q=I}Dp@uP)kwwS zR!I(<&C=M=9GSQAXh1ogAy%?A(TUd_KjvpWqHYUf;Fw%dsItr^Y-e`5O1wvCApmG+DtiB%v_4 zm!64eG_s&!4eFlYR_b%NFBlPI^Cjd8S>$s$Oin#|vV5{sTat00oZvP$x+#gL<%J4~ zcv3YbDOn4JGd8VZyNH^}g=Ql!4l<=ek*x}n@zkutgk~`=#(``GWWU8370Yof@tH|a zu=zsJY0!tTDjQ1k!R`bE%Rp&fesAiwP~|p2-kL`}C`(1P@F^&Qbu89|RouK$ zQqy7{7pY*)XHxs4lHh8#zWdH+ad@g&DsZ?k7Mq^czps~aJSVufqSx|=+ad{)6%NlY z32$$jg_S~8_IxZB9=%Y&(&p#DSM=GE*m3E*3yzs~9ChCWl_E^a7NMUdF4@pok}Ogu zs5$RK%n0)NqFCsQ;v`uFxnh-yN+#dc zH`Umr74y*c6`|=z$(3wDgoZqJDEv*~L2{VZyh|r_LXe2SBB)n{$Dg*L?mR3~151Ly z6RF7LvPh;LNhr1-7^+RJDd)tH%J8cp#)F6!se2SE422hGOu|lmpDi`9W~+j7NjBUr zOMh=jW1pHBQG|-Y`(x%G%Cp*m@aA!^_Vq_Nska|tS%Y+{HTgm z_f1gFi0_x)WPVmCG$wDRVX~3tV!^CrP|#{8GiCBzE9aS16vU=R4W%jX<=8P9j#2xK zU=4FtL(CUJCZ%DdkcBlp0dpV$%Nl~~9z4>bXd#iR)037e35(@%ahNHgB<{TeDOuwF zqpHxx2$moyV#;bn=EZ#Df(XliYcGErn~rDzyW?|Dd?*(#O^)*Uydb(|R_+%f|CGGF z0{PMT`?sn-WSkBtD9j1LB0R3A30sEMpf!S=&lLo#$fsyp}ATVDA&56ca>%l>|R;RR>ow!`<%%g;_#9YOdDV*Sf;Rb#O<|B(>#_WGyS zJ{v#%`Oh#P94k?Fkbxpt3Uf%XE_&9v*z&V`)u=UqtPw^rKgA0TwXVoy^Q(G1YRv^Y z9;|W_nq@EvBE^ZU8K?zEql8GWK zxLT{sc}K?*tkqP#N`{-&Y8j+YznSxSKQy7*{V2>a!J?bc zDE}En%~c~;CkmA4o*xz`>AWCXq%P!GZCI_Y#`o-@o_URxo?GRtAXhF|Z|Q#H2q|hb z@tQVH-Yh-SQdv!?v2*!iqABDYqZ-vfC^$suRclpc#TF^1583Q|tEaChRaREL4hp2` z6~slMsz#ytWVn@-D^jp#Dp*%a+pA_hkFo096RaHNVP(hIO`fV;^SRuDy{GQ3E?oMG zOYo;Z{RNmqFUQ1`ve{9XV}eC!F-sUxMId#fq`OFD{b(&p1&cxzbef|+W~&hc$!bIS zS2Dr949y_*ipY>(mdXo~Wi>dKejl~nkqOD77;e~$a zXPe8QGVCGmqf%n?RVsrgV@WQFFFo`$RMxCjHP=c$zjQIDwlSp&C%TtPrG~0aj}R@d zVX<$ff^~)9lIJ{G5UgA0wmUE#dl0QHSw2Z;G8F%5S#{%Z?VWUzY^*vjm>-Af z7=mOOvWn2~9yPt;To?`!`oM}9Rfutw*b)f+1i8t2?FtsDdzw$`EZmxj8jDwz++1aY zU&snJ&n93t1dHbkd8YYf4%SKmb?h+8DHOH2x8X>*YmrLt7YEE7C%Y$8sRcKyrGBFB zNtjbMZQ(KN3>WVfuhc7r8uzS5zUd>ce{tO=h%0K)s*U@_r0h<_r{kEO zn&w3J)n?c5gWugLHvh(mi<29dz43I}klFA^74?RjO}Jquw?>jJSs~`v7hjkW9rnRJa`1zHj~C9f~z5)K2Id`KAp$?TD185!YK*<)D!xF%wK*{rt432QZ%S zp)Hv}Oc1S9I*n#?byRj`vIQK7p<#JFRGNV4nu1JOOsKeDpeY^3sR{9{u+aoqJ}1F zDT4s0A#((#WpHmiCR&DUxZ9|CBoi67E~t1U#n0QYwgi%wlQ~jKYbTCICC5##!C_8# z;m#wpf}xSqdyR?izDfz57>8{w<3bEUyh+icYRZz=Xt-2T1nbd2DIiWciL4%(m!BWE zyD&c9C$3RUO}8&f)9^;|t>4{)Msr6M6v3(sPdwu!1g^RrX=C-}Vo@#?^=fMrIja>T z@e#DeW0;(ZaZ8h9%^+7KDJ_+8>#lLY-`M*M9 z6v=*rY%Az<%*NrY;2pJr*%LNVJKywZEOOgqZ8P$e*LoW5u?iIq#{=e3q`O9 zfA_32@%`I}R^`Bv=TO7R?(kv6*&r5~QM9#BVPs?!8#iuP(c|^m@BRjPf8!)FRGNey zvRJt?I6P>udSzKATtQA}laOBa>9Rkh7dl!hc{PcOU2{0qS1rS?=EY`ZvvNiMBc|xr z9$F1)poE$;2sw{S&e%{W)UeOkQUJ{kznA>K>de6E#E0Mba=hg$*P^1$Pxx*!uo(vi z_oAa?1pR}9*syNhl0O_?dHaEe4~GhhU^RpnKjU2d^wyp1)Vtb1;lW^bn9GkFJ;@zN zO`~IU3>}>vShs%Nk_b!92X4D}7xu&&CoNVX2G?KVoGa7RkK|wx!J=?sI1--K?^p6$ zs8%zat3(ZH;amI-c-!8?b%j%nV#;e+ZLoC!kqJ`aC}emn`82fp!ed3TM6kLiene9= zDn5hd?W08>?LzdzTh5?dy$x;-z4`eeSQG*1H#cJ2t^?@o=)~GJYnJrdclmd&nbqM? zK@qHm@vJktaQ(jQsv9`+0n@4lP6Te$6O72&j^3T(B-e?tv2k>DuDs@ewZr;4Z~zR29wk)%VHIalH2WBCb(C`g3nEo%U-ovdGT{}?tJh-eI&G$;EGB^ z*QD{PZm^dZt69fvUXCDM@j4=8rK%t0iZto03IZCAgrwitay2g(WO22&r>X}Zd&|r5 zo^RebZ+?fQ{O>Kaq5Z+_Sku#uwQJWb$#MAF&;EeDaYIcAg~cIQZ@ct)xao60Ls1W| zy1`2uZHQzCFzs$=Y^@i&)UdS<+js0jcX#)SBv}9Y!{4DW3vy)^;%KTS1fdE`#mba< zSC+V_S0LpF%@zecfO2_Cx}OulBC@r}2Aw{iAaX%Ld74AzKxc~n9F*&)i zS`blaa9_Of&>&^Zv}6y#G96fgOc@qc4O*;T8D7GBC^-9#K2ObP^Cgh`289U8oU^pZ zD%M!GzHxKP8R&kE+X#{Is%dDl0k-kbGt~2*a#np~BMwf~B$*mV6Y&((lNBI#GGC^b zQm|^nC*O84EA;b;jNOTA?;pcmcip?B-uvzM@4?US9&XsPPeEbM2-XMRa1kebuSUeR zHZ&J!m*`KS!fm}nxa*$#P^qqr1l<0SNqqZ;?Xy~--0TQ~{sLF9*^X4LY)krIS+)!f z8gtPv(C0_8Y73H;N4Zpmpjv`pEnc3^)i-bDys%nf6q9hYDmTD31bLAC84Ye&{qUTr zvrk#ij`+0`tT2j&0*b}b5oh>fu?U5gkGAFry0yf-|2rwC8~=IZK3wz1+m^)pzVZ)u z;_KJ#Fc@yrb-Zs}ir1DJ6-(VW`ODpsRaH$*}Pol|kko!hXcs|RPF zea5mUS0DfW%?&qnX67$W&dvEDI6)h>ZL=4X?Ku2gCcB#mh376Toz^3QV5Lzi7AWy( zQS-2Vzm@W@YFFlh`B4s^8oCLe7a}BbMUMBb`^Ye35NRY(TVV;1SUemX+v@oFVq=X7N>(ZqIE+f_ zRX)Es3KkVij1(MXv`|ggzCAl}lmakuW}imcU&rqn2`!W8mmpVdR^J6d_n=LFz!Ln?br$$N^JwG0vdiE*!uj?M<-f*=bZ$>eZ z>_eLvlYBAHP0AMo*WS4gwT4dZ{1kMu^$-Me_uf5dX>P`8r=6m9&IUleXU__yuq_o? zxPR2=M_g~lf82Zs-??EMo_$6;Uh|R*>+YxdXt;N0FMf2xy%^40V$C(xhx{;*jYcCT z+DjEz|KBy}YK<(oq4%60&p+|**N9W~)T*111tW~{G_bZZFzcU1Bx}^!jK9D98=M!g z)N#w!9r*mO?wJ#EMJiy}mlfp7lKEDYdu6*!tZdU1M9V@`v}sIxu4>)uly80`Q4vcF|QTzWE$7~<$iqZ8^6M9KmSX7@i#j#l($ut;3@$Xk6m^3 zH5eLN*v>QalF9eczk3Eg_v;7d&7^LrV$$7&mg;_la>Gd4U9%=x6ZQtY`3pbCYo5Lt zFMIaV3vrB2#_+}e{UZi))Y4`4r$B1x+?G8E+a=YC!ht3$S=7kc5zpNKsaGySq51P% zo3__rXk-8#?VU)aGYdABU;feWk@MB3mPN9COsZz`uMEpP;uA&{mM6+l`@rj7iogHn zO*MyosM4!Hwi6x67&6%mt5|bkkx?u8{N{D{12v8hRWwJcX)z8F4wur{P{?#_Yz*OW zSP=9G6zaz}|M{JG>*s%hoViHN>3x3W^biIMz~F;1{NICjK&z11bD3K}>HaD#%_k0G z8XN3p3nk=AK&EP-e55MZng>}yVL5<0QvBh@oAL6Oy#&q83)4e+UZ&bvr*6W@PIC3J zWX;5(atF?CuD~dz=j3OSGWMgp#_*2MeGlVP@g?y-X~X-^EB}ZO{P!)AT+PKqEEmv` z+J%Va=iY)x65GXdhtw;}X42IvZjAXfiX>mM-mF-}hXqMaC1vZJdB%-*Zo^;4>Qj`A zQVP-1B$H6eyW#|QB3PCrT%`U{CE=rij3irq_06X-dlL@#4`6yKhN%TC#Q5Cze~Ww_ zva5TbXnk3XOr3&yT(8X-mqIhZ>R>HCgzO@P#p6386pdqAzP> zyc|T*7d(bsDJYUv#ob%)LvDf69OjM7f9|q3!Y;&C-3OSnTCjUOi?c&XZooSylL9`( z^me@OTQ}hg-~Pp-zCQ}py#33+!mYizIa4TUoH~;`5fbFe3Ah~EqWmHDy5h@ZqD9J; zy#Nh|lg=94cPNITfgw!Iv-vBLtN*^Gx9(f9Idc&1kvuh8U6))~ z-)5%SIFN6`z~F!wmnqq!aGvp%A76)^Q?-u`*?UBb6P)l*IaowKsQ`c~Dv5;Jwhe_@ z9G*|xjOT3B;ZqH>6_zo{+P!-(r-3Y6frNaV7??LAF+;BEtv2f0*8xSbgmoJ%iy6~623VIJ6ns*iJyI0?WEd%u#zJ@XbVk`_< z5aF59N@Y*HX6iMKi^7TV&evXouF`-S2ygugW(U+l3~0-G|2(5r2j(-LPg<=ZCqwrxMz%1wSxZL{#&mpmPt*LKb+ zsk-W>dvVv^Axu>qkBiTJ&P{W27ou7LZXm#+LDwOI6+kHHAQ%X8E|D$BRX7qpuI0eI zeTLL0(me&=y=DvATRX6RUC*5Udjl-Gx)F#T|Yc7nz3?Yi{the|`_%eED~|oPRZ=Ik6W3v3{k{qb7yI!V)aPmp}4Wyza9<=Ek0@ z36#sTBc8&uHoK@E?!`fU)4ce|P%D!evSpT1*wmzBV^1r3I$E%)yA>OHIyiUYL^wD& zhN1Ckj87+Ucw`bg`lc~mb?1##&7diD04+!(APAM?Nc#m+7^so38w~Pm!C-)`5~7iX zpFc#hrkr*7=O5mLPrmj-oPN^!S^rG3v-rwYcOp$HU<30ZlI}x5ugcsj@(3e!kBS03 z8w<;{5s8Lt{&|!yd8+dl?8?=r4pJ!m2X~BM`@vu0LvMZMoQ*kIRs6@b_aWOrMQTgt z0GIJIDHlZ3vZz?Xm5P=a7n(<^(evEl>mPnC-usm+c`mF*L{hzI_9YM$>sOyR_{_K4 zy@DcG$3G>%;yirmn(Ym@l3A{xaLS+e_u*Afe>`s7@>h0hpHH*Cf*!=~B(QsTO8iG$ zILxn;>7rgO!tj;hip{xD@graMq2$varRQC6-p3}G=|^*A>PXHNDOdD75D4-`U(<$2 z1goo~V^JIQQq|O_e|bMzaSJYc_49D*#x)HQt1EB14}0SNnycX+4ktg3meLsPuq#P~ zWr}gKID~3?q#`7UDTT%A!DlafBi{JgA0TVC*7belqqSuWc>NVW!ONbw2CshUg$<7} z5v%WCe-9?hg3vcWu7cSig!~jX4Z%#4}ID^X}h{KlYbbT?5U8yAD_Xc^f|P znwR3czql6t_9+W~(xKd~0_YN?Z>Csn5kH1dx)1H;VFbkDM7{EeNI3zAPl9w&4pxB4 zRsbD>TrFg1@KGT?vkA1|Q@^+mf$~i_Yh4Ro^t8w0j7`TUTNLKn)jNRe@7#`U11aSF z?yPP%vk*r|_8?nTxYRC)`Z8KnVd=_BOGkzYTUr_`KmNiyFT#hvcS}R&g5*8e(`bAeQ%j9f5^cEwI3eeVUm6?I za{ivl;}R6}$uyOrs}o;(|Euunum1>>fs+hfYkU#s>k8j8Bfhm5S{(R917U3PQzZAV+ z{4X59npJ1+HWk=}|N8mw@VO7a6aV^^Z)4C{yDCpRRNmc^-iL@U$L&j8TM{fH3q-5} z6c(f;cd;3U#MR!>R<{~6-=Mjh(weblu!=2L{uTbpU91l3sK6AYHCOhd=rg!{{0RKB zD+-|8qR!kt1O$l+P@WovRBe~Tf{tg#>WW8lx7YQ?m~&5OE1ufp!yO~lhVRdcc+XQX zal^i>xc#^{8V9oYAd=4Z9;U-N zSdnNH3iE@uwpLvJzSrZ6|M^1E4V(I*2600NY(?Y(XFMRwxoS?hf zKpWPWvl;*T)$ia-mwyyz86&H%^2E)JU`^tFG@B&^!$Aata&aPpK!%l+O}fB2sxhfV4k^xH#eS_-J$EOGLkCyBM3G>1Se2N&<~Tz^go! z_8vCEMBHuVg*2b&=xE13eei8KrP|Ai;z~p`-HVRmpg0J+vM7fh#XJjy0_cpW;)#`r zb5Cl=)_q5-_3zpZwbZU@^)1r?6`GOE53%ezU3`= z?s;e6)aw2fwHO@>O3Lm@Z%2!sM_7=nK!}J{h!v`UAX<@d1fftwRt-8*y`nHzEhd@s zfm4E6{+*Ws?EECwrXD!r4@QePSq!*do?4JY6b?dS?7~b^=gyn#%b)rXHWz!BEcqwW z-kEq1QN1j4(l}H@`7lxiCI2+nkvUjR(dg31;aer3`}c$Ie>a}J-iPM&{$+oF8Rng^I$;!b~WT!idRifkT8d;ld?Luq@NSXW#T3 zp1i9Kq+|^k8}a_jzlKXLei>f)+zWADa~5r>z0k|q74aUaYOy7`6W#fP2s;*suG~?M zsB-1X@gqV?`9-Amk-I&GQ|B6=|MZ7(imwl5acPBns2Mns_J~!L#C(Qa(T2yNo1hF6 za;TZ+loecL)6Rb?Ui9J@;DR&P;`Hi%L9}+kEF_lc8>=9Y9Y%Lz8``uSt5%f%;?iQo3lXVS zAtnt$L9*y;A_zpZh$OVNF20`*HHm%EDS<`Fk)zy|uEYaq_s3-zmBOiBC{BshI^9^MO5Uosc zH+wT^$RuNO80Q3RnHxh1p`07TCG-|Q54sN8+S|Fs%TfWUYHzr(4OicMH^!Zf4Oth| z0}6Qsa-(Q2j3OY&gX86Q$T74ep>iD0?ViYl!=Z{!L9XW8AM67kcn^O3)1PA3{yi8j zM3Hh9z6zLBtJcgR1dJ-2a6r1&yE4I_swv$W|1?+Trv)8BJjI;SGz|)ii)UPLK6*Mk zap%^p7#|(S$oLM7_*;>(yO!LVPZ5MjrVo)y91gWvvSsg6TD!RQk}dNf1CB@PgEHTb z!qAlG*VF7^dRl$vD-D}FqZo_J=+bFx>dWU`^yGw(zxU1f&=uc6zp-Ieet1c{2XFkB zAK)wRzXUIM-gEI_dnfkp+l$u8X-vl^FqRm?l+iATR@;*D5TkIKQAi+^A4a5{fNAP5 zT^p7m+meurwrLw;0}ODLn@m0y+MSUi~s$dG$3I%!QD0 zd*-aU_00HDC^DEIMW~vRtzE({x4of+cD7%zWknp1o%fnt;01x`Y+tb4qSwFnwYctv z8?krqUi6P{$As3(#Gm}t=5v10_(XC;2>SD|0v695BJE@(%05@F<85}1450=CoEJl5 zV=2$8C4)_yHlkS&kbCcY0BxfqXdfNJ=)`u6A%dLM%v~=QSFuVWm>Wa1Bo2tS4%-YI zG4JIj>YV%N%3i60&|9u&mm=;(D#)RAjBxVWc5GJ+YenMRlRBXJ>))rAME2)bKJ|XQ z`!iq1q_c5Vet5K5z5knkz~4Th9hbi3Sz?1|!|vVtF)=xYmZ>=6@hQY&!$_8OWV9f1 zMg#?MEi~bxJPJEM1*aGjq#y=U^TRL%F$e~kRGEgjsC|p23!-K7;w04unV{_)yD+u3 zu@m`HMzdHv-}kP!;mTiLg`trhn5YJkHd|-a_KETi1Njkzi((vgK~jl`T45eLgNUhV zaX&$4hCq;CSU|RXaa@b@jwqbE&;;VeFMJ-_+gq?__Z|!n4-4`?f<#G2(r8B3Y?%|4 zk17MrVjON^8o|;uY%xBjc+a*OVy`diyGR6!+}Q*64Ds|z<%2S@y}hHI=UlCLL01~P z_w1=nNn6Aa5VgE|N?=HgeQgci{rb{6v{0+7XFUCULDKhOq-_+fBg1GPn?NFQ5UFe# zDFl!)n~*b`7i3){)z}rJDkMmi<127pu<5$&nMTT}$&JEo?gqdF%TttPzMoX%TiaSW zG(CgAdG?dB=l=gdDph~pBKhbEsyFZRVzuH#_il5@d4!oL;n>$+cj0Ld`Liot|1?Ac zRt=x)62Z6rR@?f!Q~3U=BDVPw!Wzc?d|P&-D_Ws8*aQ2Bg11z z#QTs;7RA^*DEI^7^eugzNZqRXb!yWNt&)RY&U5J0sEX&6ylhoeEy47a1o$6ex+bH`DR=3JNQ;v=2d*v5nGNVpu;yGW{0?#i?jFVLn<0bYOLyUzk-Y*eO z8Xq1f(_lr9=95bet(^dGgcM4pkSV+Vi_glaGt~T!H@zCyT=QG(-M_!KjZj;hv8R5b zAA0XQ@PF4_ivzs}Yx*8@iB(V1nsDah&cK>AJvelzA0s0p7#$lC_ftyDqa3o?QRFfM zh*u0`{9#Ysnj1rA3ja}Vl~qcL`IZ(3#I&4WL2|z5hWx5wD;0X}*T%#gBjbGmMUoL*YbYb^QB*l&Rwx zhaUTyZ9epSTSB!R;+E7M`0dYr5byrfSK0Y|wYj~^oyU&>baBY=3-7uJr=EH$de&qx zI5>pK2|=``rufFqbAYbvLT-8wWi%Xn_D&ptyCMPyKv8C~5 zSA}1UY{fgp<%vnbFUXX?Qj!XSAP02WzM{C{{bEDW;1d&5xBburk<&GUPkWl~5i5Q) zc~i8g(XMH;0>dXlTC^;=SW#{akw#jimK&(_{Njr)!j`-4#_-S(;;{rW*(?hA6bi*@ zl=3Bz|9OSVw5x(h_({LnM5YaU_qO41{{WI=KBlu7@VqTt%r^LZx!_^hn`gd5QT%k785ti^YrPm8RL^(s?dvh9)*J@j8u@ zVIJ)*$O?nZO`|+MB3iPNvbAC2dGWTsOYa~d-q9xX~9L=X`6vXpFRY#H6HPU%x z|J0J-rv>q*OJ9srPdN$Mb!#{@Gchs6 z$^qTH`Me-id9f%J@=Uh!g#yauBC3_DcqBLOig?V64UV^eR7zFe>?*V*3D)lC@uf{p z{8tx`L<;zn?uZ*b$Yg*vI?d-jiW`|0A17vts=B$dWm6JyEa zOXQ1)D~+9QvU+8D1dGOt$QF&IZPPf~2n8Gt2`(isCpy)iefHx7`R_t+??Evi#pamF zAT6#;CXHfI5-gg7)v|c3%8SXTr(x0mQ$>0T%P~xacJ>#_e0~6r`lKP!y5-r3gB3(KSBah5ms- zF^`ghToG9(l9dyLD=Q9@IdPaQh;^&X>loc*)pA;_VJZ2VSkp@4k>?VT9wO}qw-3LG6U8@e+=z8+*NP2(1e23f;*>|EN)W7kQ7%f}VpJ-Zyv@GCi&BLZ1@SXW zWvN|Nhl>WU%_8GZ~;w&=8M&0`&5(NO7163-Z^xCKf77CcBGA zst%;mWoH4~-ORhdD6TWlJRRNL9XQ-SB-NW#3OPY+3*ssfvG5U*t$3$VvBVQu@XJS9 z1SQduuMufAN%1q~7;AP;PW*Y>0rbU6Uej}6 zgEo#YfAp>VoDLAJt*sat8RJw4B33kqXiZD!h_sV3n&-nIsiT#$T-T&ZT9N8;S*~e* z+Alo9&hv{%z2-Zj9Me2ASasL<^P_oYYLq)_$$V1!nhrXaR81+Zfk=G4IgfNmxbVVf z;K2uXiS@XCl4TfL!}DUhI0Vw6Tj4|`c46*aU$t6YvMnk<;AJ5fO4_Gn_8t>W`p4ppZuf;4W0N%S)fmz z)B|ux%UhIKS^#f)bkd{EjR=83i<2%FCtj@hxp5@aMUNB;qy%g?=5Pj|N9q4#xbvD!JXBm>CK30~GIbEiR&aZMjvgCA_!O>|V!j-|U{+zrWv`3(IUb2kq+D5zkt~=sgN;;N7X~ ze36i!oV}g%T9h-}Jb~`oh6X9;jw2p=wK5FJXD}(V{R&6N)*p*{zYVm(vve`o1KZpQ zHMqw1n7*OX-7B7i;){rE3>f_jyk!t4NzN8N^a0u*PA1dB_JK*5S{{%DjF1ltwgto6 zu0}I$AYaEucfThra%NL0vFNv@^85^{zKSID20GEw%p^6Cb+`&2UI!cOXNS(@uoYu5&%TKZ>HsU>{OKwRRJdWj;^ct;@Z0`1b& zC|%DI8lCf0sJ)veVZzL7_H%g)?;yF4W_NSAS9=uH0L?}6B%^J#GeFWdh$ZIby%(|R z)$KOTE|jTH$sNY7?6CvEI^#!j=(%?SmD zl-BfCDxDlW3Y9rkrI^z=_vd=FUB%K5;C+tE@2&6)-DlttDmKB@A7)qR_ZPvqO&iVR zR3AcWonBk|NhV9>DQ1|C!%y-m3+oPL648ENLZ`py%Q>mW_JEaAUPN2D74u7PT0m zB+?=$&C<5LUfr9E?yjJ^M+PnWP*hxPK(1y2Z^Rq6#kD7vzzsfk-;5QfjgHEcM^Y2IV!uk z@DB$(%uh>&n51aN)6W{$@@3|O_0?Bte_iQ1{ltRNd8k;+gB}irQLnsODllzc6FZ;tXxdEJ=a~DsSb$-S3<@j^GU(jZtrPqe zz303TN$)#Zsud9U8?iNj#x!n!+4m<7+4NxAv%bVtM_c=Al;Pb<`hv?|mdYU?R^UOi z#>Uc2)_hEr&Z>6K0m6lj9qcTd$l+{#h>*^(J|c7hJC`H*q=tb!7ISZ!>V8-G@brRg zK0zd7iuIZ|PbkdBZzHe)8C=>A&+=q3Jv(!sYC@IXIVyfC^sPo!|R`tX*g2NxG}nw$aF#@x10;I9~y+WhnIoh%#^MPKFpM8om;F} zd$m*kx)~<8zf5WOI_c+KcHKE`zG)2(4o3axRu@qUV_FAdv3ORZ zJGMH4CoHtt@FvY&QB|Mr8-15{{2&LVk+?5~S8(5X;igx#(tMC?dcHoQ z0-yhTr@%%5yoKZhOLVw#P0zme`%}*YT9rrt1dbjuB>HuKUOp?V8!x7Re?5upY1GQq zP77@3#01652NxKroFi8Mn8&+SK&=zpmC3-hVt&if5;Ws1odAIN&b!YshnrBq?V0&E)ATr-H1$R*P6rIOQSiDuj zpHKY1RziS5Q5K_*nJ z@Bi>9C0oDu_j?`8P62iItFIOtJSD=ud#cls*vsq3nGX|GZOS++G$nrf^tQau!Sp1W z5x0nxgd|0};Xo=n`}UZIO7*Haj{UZlQNO@QsPK~BNTXW34w?-t%O=2oh0^qKk!f<45!&%xAxt^mm`%-npA@|N3Wn@CcHcuEzT)84M@X1_;Kis3ilY3R1gt`3>y+u!% zAh)GCyq|MI&p95vSnu21F_D#I$l-y`@Dm(Y{Kf)b!V~fpG!w%V5InZn=y+z)Oq-># zvA+Jq0UH_iUCwVCAj93X;^*P`$RLHv1Rq>j)h}3M#IDI zli!;X<96i7nXF$T$)ygk0Lfo-#^_2~&aeQK(G-Nfm>RXP&`QE!g6k}i3g!G}3?pxmr9Zz#6cM6R{710K)Ni3`rCS_7@ zA#N}<%sT63&1r=vy^L=-S_qd4k>Il_ zm)AKLG$Dv5wCpDDyCeQ~H*@gu;Zh>i#mV;h3VYl_XmO^e+fv2JPw5?SWgCgevd44& zW)r7h`I_t4r$oaeQ=KVnxwI#B$zc{RG4@>uiXgs`Febyy zw-7bU%_g$Oj%w<^;$TeOd>b(RSL9UDfAjlr*D`o&d^$Fz-Pd(x<;fXqY3h4n7wLrV zZsH23q;Cx}=d}+huQeI-K37!>M4pZ=b1KiU$5HAtC7$1IOFg?>>cnmCwo2lh7X}T= zTW|wuz#_}F&u^3_l&@{6bN@nqloZNwxzr-PMmXQ5;EOWxazQCd73z~GK3GOdZslcZ ze{!zGNidP^Nnii{N0O#QajJtd-AB@X@9fC=`o1)}p#JtpnI}xIh|XwFXB@4v9y)a_<9@)gX#BBwM6+ zj7d!v!@`S!<~YRYO9J-=5%r?6Tl(~2Tl*Ghcj$)P^^JTM8T|VLqviRr`xCLiM9w*@ zu~%vW&DC&>ACEHigV4y>_)qj($(SYR<-t;TLxM$g^kJ7aH?*Kt|KdW|(B$fNa1V&{ zIcRm6%6WI`$uFUW70`t3b6Zgdck(QkU5reBgb$vbqe-z}GszZBfwt3>T*kDo;acAbVw85@=IMx+xtTlErOAy){aR3#e;Ma-)y z3wa=NnQeZyxt{5Iz4LqLus`;TFE1}|&~!Djx#&T!vQT8fu2a*7?9eGCS9Fiq%AZ)Y zfL5yvuj7DJ7-zQ+r4-kb%$AC$aWbA#nx?a*g#cF5u8ojN70&= zWF(4Mxh>8LUk-7iprYy?`@=gQuEfh!r-A3H7 ztiYFX)f`{xz@vrAEi!9zpCfC}5>LMedPE5m{s&g#}&av(!W#y)R^M1+p>kyagp;qykN8^75$J4T4zKKM2I@E2bpXu7R#J_L*qb8C{Ow;pIR?G9-7_E_(k zL!bu(Ee!;kzs6z&ge$xHv)&8Ya*!ldGab%(5-i~3J*5$3>)q+1+tZitN4GGJ*88*a9|@-~MQme!#^={eaUQ4tQtNP#IcP zo(mu9E6Nhi1YpjpIJEY@D#WHsd8!PXclV-Lz>hWO)RAqm%-Lv+{rj?l=WjWgYGtCLKUJ`_mQw2WPstycLAh3Ba4Pg{AXBh zu7zM6o|U5`$z6nn`htV@PgwZ0D(a`O$n@u3t?`^FA!R-qD3=Mwx5BoYlAIfaB$9B( zHA{H|B+m|d?Sg~q6{buK*+|qN`+G0@??3WU{if|1^uV6nLFI?wdOuW`CbL&U`nkSR zx{FHCLBS`4y^-BP1txsed6FCrmZ`^0HBIffQenYBL7{|$;9c{aM`0sU1Z5%*NJd^G zCxOC)>`M%cSL2ee6yW&zSadd?3~x&^v!;S-Z0H%;^oww!HJ;#WMqpKiT+<&ywjJ|z zgYrKU@OlcOtJjHqs;a0(cha!%s23_(tQ41}Z-081AFL3wwlc=VLiD=VjdTNk%?I`q zsH&pq&~wMFjhAH-2~viYqDCmA$88z9vW=aTk<+M@HCfc!J-6J${Ge!#9zxH?m#GMuI3t~bz54dt6yV=68hzsuf*(teMKmZ! z8M4^vj5!$%PI6ZSv@eLoL@%WC+UP6a{=!zH&#S8Y@=~dQHyFjO>UA!5wH(ANa*8nm zrc}W;ia?sLO(H@{e~*v^BPqTmlh4L~^M=~?$QDU5vHx8N1tqoIo;A+#Rh_8kyB?-I z<=G`f6==1IjOlVpfMipAe_q=+iHQk2+k(4i%d21XVb= zzyCV!;(_jN85-54M%=p zUPx*mTSi*?<2WC%&Jy`!8RwUZ!2>oFS+(+JRVVNpCp4ymIcU&7L2v?_QAA`Sl`W`Z z^~pjJL91bgCHy!HdSOZx)=hDw9Fq>N^45stRXJhYdX3N?!cci2grF3;NThVTlE0}I zeeY3sN=jT{?`2J*r#Go|Ql~tn+N%_=O5LB#6I?eJ8=RZCMoNqyCc-=bhaOR$ zhjt!Mr`OVDtHM+Bu_FXXSw2ky&k+pM zH0r5o#9GNQS=EFkkWea1mvaLDhe@e3iYA;jKf}T+yd*zXN4OrRDu~0#dLu#QOu9&$ zJ!-((O`$D-LJvykRG*97rlJ7YzHi_IT3b|0 z$>)Mu8xc@|A5=1G_4AG-2w8wT9>LCsC2~yTe?fIaPEXV+E;U0p~ zX*ICBm#B|UBGYRW`oGG>55X+DT}?t6>6>CzjSP@_Q_Vsps2h)(n%b{W;I(s4k}`{A zB5cj1+&WPX`dYtfqC`r$z+c&pej}R2RWUiOBv=l&0HC}o11x3B98e`q0w5CjW8(o! z@$|9{M&{>;=jbCKtn{L{H1=+JK5P_nY$O|+_{ihK$4}EiGkNyW(?PpjKh0c2Lz5vz znE_UyMohUp|EOSmL3DKngiD@ zG51L~S+!C|p2O=lLCqmhYe@VkS^V%o{0}_F*Jq4{pArPpb$A&8DyA0Tpp%laZoy1T z9A{>%VKcJcp&&{o2*M(-fU;&@i;-D%GLEGp2>?<46d6I*S#-)MQIj!YCqnG(Lpg;@8QtAvc1LzR)vpZ^l5GV3vxvAOXs1I_pnSHz5J zZ-OQy{>S$0Y;q+s9VpGw^tPST?JxUAjl6QQXThC?^$!~`>?@LW{tr-4^QLH~sy+cd zEgaM$uTUBxAHe@P(yvtTxE`Z(Yg6L~8#qgq83y2CvVE!4@!oM8vqV=F_KytF`45@d1GB%2yV@`Q4nq;jgH z^2}oAO?N($=T?I@svEDlFbz<=rM`d0W(ROml#)^u3VydFdM}0*{$09V5}^BaFhg}l zU8Mj=CCg)J6j@Bok{K(h$k)k1eblCFtoM?V21`Iv zVH)p!U(WY|xj(;N$}8|vjn#VV&hMf8na=D?GJ{!BjiB6;P!TwCQW)$-MKoh!jqDz1 zAutE9r6-BbsR`9iCDx9UY2gHx?z>^XucsSKG#nJf4G2HUkKNL-qp4;9t1@IQox zq{D`6td;qaw;ix6%+#I!cVB$7E|eL`i* zi5aYjn8q0bSflR%$l`fO(fxRGpb6ge|jN62?Qq>bcC>zyXE_ncNT zK-6yid&FP$5ye>-%9^^7-0L~nBUJ!WQ5sT#KmIJYP3GYjW@hHlJn){d+hCV@95_<~ z4q!#9BPq6ehw>(}gbtWwgCm;<>tqwzgf`hr`jcf#5Yg?RzWT;3o@&5z#UGm&(#%WX zr=7ZFnQml0>`&VhL+G!8>)WS$dE_RF_`QK z{&n0$OUV0^OQ)mAV1UnT;>}{=t>5^&zRipCxvoAZtalVyv+BMKlqHuoXxI>JGNteY z13TcQBCts{z?HH>w>^bUIc7rbH85v_7jVWl2ol0q^9ydF(+<$hyj3XhsOXsN-ByV! z;3lL`r`IGoJSEOOameIQjM!Evi1h;h-DFH)?__~-F&MWfA&@DXP(vLWa8Tl;6ZrT) z1oJ<2ivB1Y#DmIiV(pebWQ|;!+Uwl}tl{5q;iqL@5i{5ifxegB3;nL><{mbm3rJYM z-aG`_5V8t4$BncL42Q25phseO`rvWK8*#HMMXck0cs0B?+gQKhJ`Ld-Za7 zo+xuWeu$Bd&&{&jZ^@1^U;|fitk)18XXe2i8 z;WXBF^WZzT=fxM9S07{4o|i&Pn%aV+{83S(I+Igf-t_y{_9a?E8~;QMB5+T++APzj zE?r_~TVkb*_qd8*t3{PFGjOmNAA7gbx_UY^F3k7r@tt2QW&8M>B0QJehxm$29n#z< zJTsON;$Kehh2J2=JL?x}*=OCE8qFiIe%Ad$w7pr_HbdCG`!#goI$!DiuvjCU2#I6| zg^eT+yET*B->2q!luD&CKl6HW0caUS!hgcU|areLf>S9?3pkJ^)gf z;(GUv5~QZtYy@)RDwsbYi{qIgGdB*KYjD=mt1Nf)ZPRRh6X1N=SkoBCg<95rzf7~x zkUr$%5J<()KOJ3t`K#Y>`JqD?s6;X4MA`Mzxsit}-AJ@AtC&pp6k4RWG~E0}pq`?X zP-#6sOO1P{FV9FpJB{bSOJcf%+;uZ1Q&;i!XZjOCMI6`;UmBw1C%Z_&w%dy2g{Hvt;?SA)@E5W5=9kE>TOYOa*;}7gIe!qQ-9hIMUpOZDFm9!baVNfj!zvoCf|t&;65= zwj0{-=fjMN3^ztNOU3Gh8V4|h*Row}gZo7$MSnu7U|(&lT3nx9oUQ$KroCp;+A1_- zKERAms+3Tza7&@2-vdyredi6?{Yat*zY_PBK`ql1gCSB8?0V|(5pPpxh3xC|VtbQC z_pBq|^4+FPxnChdal;&$r>9nv$R?P~ta{ZOla@^ zMMLUiP!XY#-eD911uj*^kbbhKDOHiTF)~@5UCQ(HqVQXFn*V+pVn*zoeVV;z*JQb0 z>wFV7F}i(ILl^WdSVrZx??&FQ?$7nYq_3vZzJkK07Ry%H-`UCf4bLXGHBa@y~!nY6@J1MkWnmQ9~Jj#jqI&<;1* zn-zC-EDM&hIjN*4Ym??dZWVONwWGVyjKW_kCNYk25_Fj+5Q1AiiH- z9o${b5Y|fzfw=rt^-a^uXouN+u=6e z&LvjzVmx^`Ml5&UZOE1Srfsd5bbXfV()GNsKh?4PCiT4(SWhAmc#)`MY!Dw`gO~jQuF-yHo9a!1W=&?wqo?HxX@_! zGuWQ=PrCLt`7Q7(|H!RFtBrH>2`1-N5hK|ezTB<#Jgt}|r*s9Sm9cYP9L2(b7U0nA z3oTzmd+5~t)G{1enywaqzSHKke~Rb=bK_1AoS1VC^c7uLje@`Q=agQsPl1kf-lNS{ zM;o{ufw_t&857s!GEbYbeH%EJ9ud`AahlvKM&Gr@#OZ%boG2(C(f_&qp8!2R z^WVPdUqJsG`~QjV{{i$L68}Tf|0kgTVE+%{|EB3*=>7%tFOEF^``-fnizAPZ{@>s9 zKLvUmwEy-^{{ng(*?$rKFLeKRpnvi9|1A{%Q=tFNTR)|HtZ6qf?x+Np0Tkq=qNu4* JA!i=^zW{cFP_F<0 diff --git a/raidillon_core/Cargo.toml b/raidillon_core/Cargo.toml new file mode 100644 index 0000000..1d15e30 --- /dev/null +++ b/raidillon_core/Cargo.toml @@ -0,0 +1,4 @@ +[package] +name = "raidillon_core" +version = "0.1.0" +edition = "2021" diff --git a/raidillon_core/src/lib.rs b/raidillon_core/src/lib.rs new file mode 100644 index 0000000..230f8bb --- /dev/null +++ b/raidillon_core/src/lib.rs @@ -0,0 +1,3 @@ +pub mod time; + +pub use time::Time; diff --git a/src/time.rs b/raidillon_core/src/time.rs similarity index 99% rename from src/time.rs rename to raidillon_core/src/time.rs index 5e8159b..13876f1 100644 --- a/src/time.rs +++ b/raidillon_core/src/time.rs @@ -31,4 +31,4 @@ impl Time { pub fn total_seconds(&self) -> f32 { self.total.as_secs_f32() } -} \ No newline at end of file +} diff --git a/raidillon_ecs/Cargo.toml b/raidillon_ecs/Cargo.toml new file mode 100644 index 0000000..7a88695 --- /dev/null +++ b/raidillon_ecs/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "raidillon_ecs" +version = "0.1.0" +edition = "2021" + +[dependencies] +glam = "0.30.4" +hecs = "0.10.5" diff --git a/raidillon_ecs/src/lib.rs b/raidillon_ecs/src/lib.rs new file mode 100644 index 0000000..19a3e69 --- /dev/null +++ b/raidillon_ecs/src/lib.rs @@ -0,0 +1,17 @@ +use glam::{Mat4, Quat, Vec3}; + +#[derive(Copy, Clone)] +pub struct Transform { + pub translation: Vec3, + pub rotation: Quat, + pub scale: Vec3, +} + +impl Transform { + pub fn matrix(&self) -> Mat4 { + Mat4::from_scale_rotation_translation(self.scale, self.rotation, self.translation) + } +} + +#[derive(Clone)] +pub struct ModelHandle(pub usize); diff --git a/raidillon_game/Cargo.toml b/raidillon_game/Cargo.toml new file mode 100644 index 0000000..5c88109 --- /dev/null +++ b/raidillon_game/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "raidillon_game" +version = "0.1.0" +edition = "2021" + +[dependencies] +anyhow = "1.0.98" +glam = "0.30.4" +glium = { version = "0.35.0", features = ["glutin_backend", "simple_window_builder"] } +glutin = { version = "0.32.3", default-features = false } +winit = "0.30" +raidillon_render = { path = "../raidillon_render" } +raidillon_ecs = { path = "../raidillon_ecs" } +raidillon_ui = { path = "../raidillon_ui" } +raidillon_core = { path = "../raidillon_core" } +hecs = "0.10.5" diff --git a/src/main.rs b/raidillon_game/src/main.rs similarity index 91% rename from src/main.rs rename to raidillon_game/src/main.rs index 1a92617..fc9d741 100644 --- a/src/main.rs +++ b/raidillon_game/src/main.rs @@ -1,17 +1,10 @@ -mod camera; -mod ecs; -mod model; -mod gltf_loader; -mod render; -mod time; -mod ui; - use anyhow::Result; -use camera::Camera; -use ecs::{Transform}; use glam::{Quat, Vec3, EulerRot}; use glium::backend::glutin::SimpleWindowBuilder; -use render::GliumRenderer; +use raidillon_core::Time; +use raidillon_ecs::Transform; +use raidillon_render::{Camera, GliumRenderer, gltf_loader, ECSRenderer}; +use raidillon_ui::Gui; fn main() -> Result<()> { let event_loop = glium::winit::event_loop::EventLoop::builder() @@ -19,7 +12,7 @@ fn main() -> Result<()> { .expect("create event-loop"); let (window, display) = SimpleWindowBuilder::new() - .with_title("fps") + .with_title("raidillon") .with_inner_size(1280, 720) .build(&event_loop); @@ -27,13 +20,13 @@ fn main() -> Result<()> { let mut ecsr = { let world = hecs::World::new(); let renderer = GliumRenderer::new(display.clone())?; - ecs::ECSRenderer::new(renderer, world) + ECSRenderer::new(renderer, world) }; // Dear ImGui integration - let mut gui = ui::Gui::new(&display, &window)?; + let mut gui = Gui::new(&display, &window)?; - let mut time = time::Time::new(); + let mut time = Time::new(); let object_ent = { let model_3d = gltf_loader::load_gltf("resources/models/tree.gltf", &display)?; @@ -77,7 +70,7 @@ fn main() -> Result<()> { Event::WindowEvent { event, .. } => match event { WindowEvent::CloseRequested => el.exit(), WindowEvent::Resized(sz) => { - ecsr.world.query_one_mut::<&mut crate::camera::Camera>(camera_ent).map(|mut cam| { + ecsr.world.query_one_mut::<&mut Camera>(camera_ent).map(|mut cam| { cam.aspect = sz.width as f32 / sz.height as f32; }); } diff --git a/raidillon_render/Cargo.toml b/raidillon_render/Cargo.toml new file mode 100644 index 0000000..1f5247c --- /dev/null +++ b/raidillon_render/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "raidillon_render" +version = "0.1.0" +edition = "2021" + +[dependencies] +anyhow = "1.0.98" +glam = "0.30.4" +glium = { version = "0.35.0", features = ["glutin_backend", "simple_window_builder"] } +gltf = { version = "1.4.1", features = ["import", "utils", "KHR_texture_transform"] } +glutin = { version = "0.32.3", default-features = false } +hecs = "0.10.5" +image = "0.25.6" +raidillon_ecs = { path = "../raidillon_ecs" } diff --git a/src/camera.rs b/raidillon_render/src/camera.rs similarity index 100% rename from src/camera.rs rename to raidillon_render/src/camera.rs diff --git a/src/ecs.rs b/raidillon_render/src/ecs_renderer.rs similarity index 79% rename from src/ecs.rs rename to raidillon_render/src/ecs_renderer.rs index a81c9e3..edac676 100644 --- a/src/ecs.rs +++ b/raidillon_render/src/ecs_renderer.rs @@ -1,4 +1,4 @@ -use glam::{Mat4, Quat, Vec3}; +use raidillon_ecs::{Transform, ModelHandle}; use hecs::{Entity, World}; use crate::render::GliumRenderer; use crate::model::Model; @@ -46,19 +46,3 @@ impl ECSRenderer { self.renderer.render_into(&self.world, target); } } - -#[derive(Copy, Clone)] -pub struct Transform { - pub translation: Vec3, - pub rotation: Quat, - pub scale: Vec3, -} - -impl Transform { - pub fn matrix(&self) -> Mat4 { - Mat4::from_scale_rotation_translation(self.scale, self.rotation, self.translation) - } -} - -#[derive(Clone)] -pub struct ModelHandle(pub usize); diff --git a/src/gltf_loader.rs b/raidillon_render/src/gltf_loader.rs similarity index 99% rename from src/gltf_loader.rs rename to raidillon_render/src/gltf_loader.rs index 81b24b7..4d006fb 100644 --- a/src/gltf_loader.rs +++ b/raidillon_render/src/gltf_loader.rs @@ -177,4 +177,4 @@ fn to_rgba(img: &gltf::image::Data) -> Vec { } _ => img.pixels.clone(), } -} \ No newline at end of file +} diff --git a/raidillon_render/src/lib.rs b/raidillon_render/src/lib.rs new file mode 100644 index 0000000..40e3033 --- /dev/null +++ b/raidillon_render/src/lib.rs @@ -0,0 +1,9 @@ +pub mod camera; +pub mod model; +pub mod gltf_loader; +pub mod render; +pub mod ecs_renderer; + +pub use camera::Camera; +pub use render::GliumRenderer; +pub use ecs_renderer::ECSRenderer; diff --git a/src/model.rs b/raidillon_render/src/model.rs similarity index 100% rename from src/model.rs rename to raidillon_render/src/model.rs diff --git a/src/render.rs b/raidillon_render/src/render.rs similarity index 93% rename from src/render.rs rename to raidillon_render/src/render.rs index c382239..38f4175 100644 --- a/src/render.rs +++ b/raidillon_render/src/render.rs @@ -1,5 +1,5 @@ use crate::camera::Camera; -use crate::ecs::{ModelHandle, Transform}; +use raidillon_ecs::{ModelHandle, Transform}; use crate::model::{Model, Mesh}; use glium::texture::{RawImage2d, SrgbTexture2d}; use glium::{uniform, Program, Surface}; @@ -26,8 +26,8 @@ pub struct GliumRenderer { impl GliumRenderer { pub fn new(display: glium::Display) -> anyhow::Result { - const VERT_SRC: &str = include_str!("../resources/shaders/gl_textured.vert"); - const FRAG_SRC: &str = include_str!("../resources/shaders/gl_textured.frag"); + const VERT_SRC: &str = include_str!("../../resources/shaders/gl_textured.vert"); + const FRAG_SRC: &str = include_str!("../../resources/shaders/gl_textured.frag"); let program = Program::from_source(&display, VERT_SRC, FRAG_SRC, None)?; @@ -46,8 +46,8 @@ impl GliumRenderer { .. Default::default() }; - let sky_vert = include_str!("../resources/shaders/skybox.vert"); - let sky_frag = include_str!("../resources/shaders/skybox.frag"); + let sky_vert = include_str!("../../resources/shaders/skybox.vert"); + let sky_frag = include_str!("../../resources/shaders/skybox.frag"); let skybox_program = Program::from_source(&display, sky_vert, sky_frag, None)?; let image = ImageReader::open("resources/skyboxes/sky_24_2k.png")?.decode()?.to_rgba8(); diff --git a/raidillon_ui/Cargo.toml b/raidillon_ui/Cargo.toml new file mode 100644 index 0000000..d26d063 --- /dev/null +++ b/raidillon_ui/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "raidillon_ui" +version = "0.1.0" +edition = "2021" + +[dependencies] +anyhow = "1.0.98" +glium = { version = "0.35.0", features = ["glutin_backend", "simple_window_builder"] } +imgui = "0.12" +imgui-winit-support = "0.13" +imgui-glium-renderer = "0.13" +winit = "0.30" diff --git a/raidillon_ui/src/lib.rs b/raidillon_ui/src/lib.rs new file mode 100644 index 0000000..35f3bd9 --- /dev/null +++ b/raidillon_ui/src/lib.rs @@ -0,0 +1,3 @@ +pub mod ui; + +pub use ui::Gui; diff --git a/src/ui.rs b/raidillon_ui/src/ui.rs similarity index 99% rename from src/ui.rs rename to raidillon_ui/src/ui.rs index c6be88a..8ac7b0d 100644 --- a/src/ui.rs +++ b/raidillon_ui/src/ui.rs @@ -81,4 +81,4 @@ impl Gui { let ui = self.imgui.frame(); build(&ui); } -} \ No newline at end of file +} diff --git a/readme.md b/readme.md index f1458ae..48b6b50 100644 --- a/readme.md +++ b/readme.md @@ -1,3 +1,3 @@ ## Attributions -- [Tree](./resources/models/tree.gltf) by "Poly by Google" [CC-BY] (https://creativecommons.org/licenses/by/3.0/) via [Poly Pizza](https://poly.pizza/m/6pwiq7hSrHr) \ No newline at end of file +- [Tree](./resources/models/tree.gltf) by "Poly by Google" [CC-BY](https://creativecommons.org/licenses/by/3.0/) via [Poly Pizza](https://poly.pizza/m/6pwiq7hSrHr) diff --git a/src/teapot.rs b/src/teapot.rs deleted file mode 100644 index 914a881..0000000 --- a/src/teapot.rs +++ /dev/null @@ -1,2110 +0,0 @@ -#[derive(Copy, Clone)] -pub struct Vertex { - position: (f32, f32, f32) -} - -implement_vertex!(Vertex, position); - -pub const VERTICES: [Vertex; 531] = [ - Vertex { position: (0.0, 0.0, 0.0) }, // dummy vector because in the original model indices - // start at 1 - Vertex { position: (40.6266, 28.3457, -1.10804) }, - Vertex { position: (40.0714, 30.4443, -1.10804) }, - Vertex { position: (40.7155, 31.1438, -1.10804) }, - Vertex { position: (42.0257, 30.4443, -1.10804) }, - Vertex { position: (43.4692, 28.3457, -1.10804) }, - Vertex { position: (37.5425, 28.3457, 14.5117) }, - Vertex { position: (37.0303, 30.4443, 14.2938) }, - Vertex { position: (37.6244, 31.1438, 14.5466) }, - Vertex { position: (38.8331, 30.4443, 15.0609) }, - Vertex { position: (40.1647, 28.3457, 15.6274) }, - Vertex { position: (29.0859, 28.3457, 27.1468) }, - Vertex { position: (28.6917, 30.4443, 26.7527) }, - Vertex { position: (29.149, 31.1438, 27.2099) }, - Vertex { position: (30.0792, 30.4443, 28.1402) }, - Vertex { position: (31.1041, 28.3457, 29.165) }, - Vertex { position: (16.4508, 28.3457, 35.6034) }, - Vertex { position: (16.2329, 30.4443, 35.0912) }, - Vertex { position: (16.4857, 31.1438, 35.6853) }, - Vertex { position: (16.9999, 30.4443, 36.894) }, - Vertex { position: (17.5665, 28.3457, 38.2256) }, - Vertex { position: (0.831025, 28.3457, 38.6876) }, - Vertex { position: (0.831025, 30.4443, 38.1324) }, - Vertex { position: (0.831025, 31.1438, 38.7764) }, - Vertex { position: (0.831025, 30.4443, 40.0866) }, - Vertex { position: (0.831025, 28.3457, 41.5301) }, - Vertex { position: (-15.868, 28.3457, 35.6034) }, - Vertex { position: (-15.0262, 30.4443, 35.0912) }, - Vertex { position: (-14.9585, 31.1438, 35.6853) }, - Vertex { position: (-15.3547, 30.4443, 36.894) }, - Vertex { position: (-15.9044, 28.3457, 38.2256) }, - Vertex { position: (-28.3832, 28.3457, 27.1468) }, - Vertex { position: (-27.4344, 30.4443, 26.7527) }, - Vertex { position: (-27.6068, 31.1438, 27.2099) }, - Vertex { position: (-28.4322, 30.4443, 28.1402) }, - Vertex { position: (-29.4421, 28.3457, 29.165) }, - Vertex { position: (-36.2402, 28.3457, 14.5117) }, - Vertex { position: (-35.52, 30.4443, 14.2938) }, - Vertex { position: (-36.0073, 31.1438, 14.5466) }, - Vertex { position: (-37.1767, 30.4443, 15.0609) }, - Vertex { position: (-38.5027, 28.3457, 15.6274) }, - Vertex { position: (-38.9646, 28.3457, -1.10804) }, - Vertex { position: (-38.4094, 30.4443, -1.10804) }, - Vertex { position: (-39.0534, 31.1438, -1.10804) }, - Vertex { position: (-40.3636, 30.4443, -1.10804) }, - Vertex { position: (-41.8071, 28.3457, -1.10804) }, - Vertex { position: (-35.8804, 28.3457, -16.7278) }, - Vertex { position: (-35.3683, 30.4443, -16.5099) }, - Vertex { position: (-35.9624, 31.1438, -16.7627) }, - Vertex { position: (-37.1711, 30.4443, -17.2769) }, - Vertex { position: (-38.5027, 28.3457, -17.8435) }, - Vertex { position: (-27.4238, 28.3457, -29.3629) }, - Vertex { position: (-27.0297, 30.4443, -28.9687) }, - Vertex { position: (-27.4869, 31.1438, -29.426) }, - Vertex { position: (-28.4172, 30.4443, -30.3562) }, - Vertex { position: (-29.4421, 28.3457, -31.3811) }, - Vertex { position: (-14.7887, 28.3457, -37.8195) }, - Vertex { position: (-14.5708, 30.4443, -37.3073) }, - Vertex { position: (-14.8236, 31.1438, -37.9014) }, - Vertex { position: (-15.3379, 30.4443, -39.1101) }, - Vertex { position: (-15.9044, 28.3457, -40.4417) }, - Vertex { position: (0.831025, 28.3457, -40.9036) }, - Vertex { position: (0.831025, 30.4443, -40.3484) }, - Vertex { position: (0.831025, 31.1438, -40.9925) }, - Vertex { position: (0.831025, 30.4443, -42.3027) }, - Vertex { position: (0.831025, 28.3457, -43.7462) }, - Vertex { position: (16.4508, 28.3457, -37.8195) }, - Vertex { position: (16.2329, 30.4443, -37.3073) }, - Vertex { position: (16.4857, 31.1438, -37.9014) }, - Vertex { position: (16.9999, 30.4443, -39.1101) }, - Vertex { position: (17.5665, 28.3457, -40.4417) }, - Vertex { position: (29.0859, 28.3457, -29.3629) }, - Vertex { position: (28.6917, 30.4443, -28.9687) }, - Vertex { position: (29.149, 31.1438, -29.426) }, - Vertex { position: (30.0792, 30.4443, -30.3562) }, - Vertex { position: (31.1041, 28.3457, -31.3811) }, - Vertex { position: (37.5425, 28.3457, -16.7278) }, - Vertex { position: (37.0303, 30.4443, -16.5099) }, - Vertex { position: (37.6244, 31.1438, -16.7627) }, - Vertex { position: (38.8331, 30.4443, -17.2769) }, - Vertex { position: (40.1647, 28.3457, -17.8435) }, - Vertex { position: (48.6879, 17.1865, -1.10804) }, - Vertex { position: (53.2404, 6.22714, -1.10804) }, - Vertex { position: (56.4605, -4.33246, -1.10804) }, - Vertex { position: (57.6819, -14.2925, -1.10804) }, - Vertex { position: (44.979, 17.1865, 17.6758) }, - Vertex { position: (49.1787, 6.22714, 19.4626) }, - Vertex { position: (52.1492, -4.33246, 20.7265) }, - Vertex { position: (53.2759, -14.2925, 21.2059) }, - Vertex { position: (34.8094, 17.1865, 32.8703) }, - Vertex { position: (38.0417, 6.22714, 36.1026) }, - Vertex { position: (40.3279, -4.33246, 38.3889) }, - Vertex { position: (41.1951, -14.2925, 39.2561) }, - Vertex { position: (19.6148, 17.1865, 43.0399) }, - Vertex { position: (21.4017, 6.22714, 47.2396) }, - Vertex { position: (22.6656, -4.33246, 50.2101) }, - Vertex { position: (23.145, -14.2925, 51.3369) }, - Vertex { position: (0.831025, 17.1865, 46.7488) }, - Vertex { position: (0.831025, 6.22714, 51.3013) }, - Vertex { position: (0.831025, -4.33246, 54.5214) }, - Vertex { position: (0.831025, -14.2925, 55.7428) }, - Vertex { position: (-17.9528, 17.1865, 43.0399) }, - Vertex { position: (-19.7397, 6.22714, 47.2396) }, - Vertex { position: (-21.0035, -4.33246, 50.2101) }, - Vertex { position: (-21.4829, -14.2925, 51.3369) }, - Vertex { position: (-33.1474, 17.1865, 32.8703) }, - Vertex { position: (-36.3796, 6.22714, 36.1026) }, - Vertex { position: (-38.6659, -4.33246, 38.3889) }, - Vertex { position: (-39.5331, -14.2925, 39.2561) }, - Vertex { position: (-43.3169, 17.1865, 17.6758) }, - Vertex { position: (-47.5166, 6.22714, 19.4626) }, - Vertex { position: (-50.4871, -4.33246, 20.7265) }, - Vertex { position: (-51.6139, -14.2925, 21.2059) }, - Vertex { position: (-47.0258, 17.1865, -1.10804) }, - Vertex { position: (-51.5784, 6.22714, -1.10804) }, - Vertex { position: (-54.7984, -4.33246, -1.10804) }, - Vertex { position: (-56.0198, -14.2925, -1.10804) }, - Vertex { position: (-43.3169, 17.1865, -19.8919) }, - Vertex { position: (-47.5166, 6.22714, -21.6787) }, - Vertex { position: (-50.4871, -4.33246, -22.9426) }, - Vertex { position: (-51.6139, -14.2925, -23.422) }, - Vertex { position: (-33.1474, 17.1865, -35.0864) }, - Vertex { position: (-36.3796, 6.22714, -38.3187) }, - Vertex { position: (-38.6659, -4.33246, -40.6049) }, - Vertex { position: (-39.5331, -14.2925, -41.4721) }, - Vertex { position: (-17.9528, 17.1865, -45.256) }, - Vertex { position: (-19.7397, 6.22714, -49.4557) }, - Vertex { position: (-21.0035, -4.33246, -52.4262) }, - Vertex { position: (-21.4829, -14.2925, -53.5529) }, - Vertex { position: (0.831025, 17.1865, -48.9649) }, - Vertex { position: (0.831025, 6.22714, -53.5174) }, - Vertex { position: (0.831025, -4.33246, -56.7375) }, - Vertex { position: (0.831025, -14.2925, -57.9589) }, - Vertex { position: (19.6148, 17.1865, -45.256) }, - Vertex { position: (21.4017, 6.22714, -49.4557) }, - Vertex { position: (22.6656, -4.33246, -52.4262) }, - Vertex { position: (23.145, -14.2925, -53.5529) }, - Vertex { position: (34.8094, 17.1865, -35.0864) }, - Vertex { position: (38.0417, 6.22714, -38.3187) }, - Vertex { position: (40.3279, -4.33246, -40.6049) }, - Vertex { position: (41.1951, -14.2925, -41.4721) }, - Vertex { position: (44.979, 17.1865, -19.8919) }, - Vertex { position: (49.1787, 6.22714, -21.6787) }, - Vertex { position: (52.1492, -4.33246, -22.9426) }, - Vertex { position: (53.2759, -14.2925, -23.422) }, - Vertex { position: (55.4611, -22.7202, -1.10804) }, - Vertex { position: (50.5755, -28.9493, -1.10804) }, - Vertex { position: (45.6899, -33.1798, -1.10804) }, - Vertex { position: (43.4692, -35.6115, -1.10804) }, - Vertex { position: (51.2273, -22.7202, 20.3343) }, - Vertex { position: (46.7203, -28.9493, 18.4167) }, - Vertex { position: (42.2133, -33.1798, 16.4991) }, - Vertex { position: (40.1647, -35.6115, 15.6274) }, - Vertex { position: (39.6184, -22.7202, 37.6793) }, - Vertex { position: (36.1496, -28.9493, 34.2106) }, - Vertex { position: (32.6808, -33.1798, 30.7418) }, - Vertex { position: (31.1041, -35.6115, 29.165) }, - Vertex { position: (22.2733, -22.7202, 49.2882) }, - Vertex { position: (20.3557, -28.9493, 44.7813) }, - Vertex { position: (18.4381, -33.1798, 40.2743) }, - Vertex { position: (17.5665, -35.6115, 38.2256) }, - Vertex { position: (0.831025, -22.7202, 53.5221) }, - Vertex { position: (0.831025, -28.9493, 48.6365) }, - Vertex { position: (0.831025, -33.1798, 43.7508) }, - Vertex { position: (0.831025, -35.6115, 41.5301) }, - Vertex { position: (-20.6113, -22.7202, 49.2882) }, - Vertex { position: (-18.6937, -28.9493, 44.7813) }, - Vertex { position: (-16.7761, -33.1798, 40.2743) }, - Vertex { position: (-15.9044, -35.6115, 38.2256) }, - Vertex { position: (-37.9564, -22.7202, 37.6793) }, - Vertex { position: (-34.4876, -28.9493, 34.2106) }, - Vertex { position: (-31.0188, -33.1798, 30.7418) }, - Vertex { position: (-29.4421, -35.6115, 29.165) }, - Vertex { position: (-49.5653, -22.7202, 20.3343) }, - Vertex { position: (-45.0583, -28.9493, 18.4167) }, - Vertex { position: (-40.5513, -33.1798, 16.4991) }, - Vertex { position: (-38.5027, -35.6115, 15.6274) }, - Vertex { position: (-53.7991, -22.7202, -1.10804) }, - Vertex { position: (-48.9135, -28.9493, -1.10804) }, - Vertex { position: (-44.0279, -33.1798, -1.10804) }, - Vertex { position: (-41.8071, -35.6115, -1.10804) }, - Vertex { position: (-49.5653, -22.7202, -22.5504) }, - Vertex { position: (-45.0583, -28.9493, -20.6327) }, - Vertex { position: (-40.5513, -33.1798, -18.7151) }, - Vertex { position: (-38.5027, -35.6115, -17.8435) }, - Vertex { position: (-37.9564, -22.7202, -39.8954) }, - Vertex { position: (-34.4876, -28.9493, -36.4266) }, - Vertex { position: (-31.0188, -33.1798, -32.9578) }, - Vertex { position: (-29.4421, -35.6115, -31.3811) }, - Vertex { position: (-20.6113, -22.7202, -51.5043) }, - Vertex { position: (-18.6937, -28.9493, -46.9973) }, - Vertex { position: (-16.7761, -33.1798, -42.4903) }, - Vertex { position: (-15.9044, -35.6115, -40.4417) }, - Vertex { position: (0.831025, -22.7202, -55.7382) }, - Vertex { position: (0.831025, -28.9493, -50.8525) }, - Vertex { position: (0.831025, -33.1798, -45.9669) }, - Vertex { position: (0.831025, -35.6115, -43.7462) }, - Vertex { position: (22.2733, -22.7202, -51.5043) }, - Vertex { position: (20.3557, -28.9493, -46.9973) }, - Vertex { position: (18.4381, -33.1798, -42.4903) }, - Vertex { position: (17.5665, -35.6115, -40.4417) }, - Vertex { position: (39.6184, -22.7202, -39.8954) }, - Vertex { position: (36.1496, -28.9493, -36.4266) }, - Vertex { position: (32.6808, -33.1798, -32.9578) }, - Vertex { position: (31.1041, -35.6115, -31.3811) }, - Vertex { position: (51.2273, -22.7202, -22.5504) }, - Vertex { position: (46.7203, -28.9493, -20.6327) }, - Vertex { position: (42.2133, -33.1798, -18.7151) }, - Vertex { position: (40.1647, -35.6115, -17.8435) }, - Vertex { position: (42.5031, -37.1772, -1.10804) }, - Vertex { position: (37.3399, -38.5429, -1.10804) }, - Vertex { position: (24.5818, -39.5089, -1.10804) }, - Vertex { position: (0.831025, -39.8754, -1.10804) }, - Vertex { position: (39.2736, -37.1772, 15.2483) }, - Vertex { position: (34.5105, -38.5429, 13.2217) }, - Vertex { position: (22.7411, -39.5089, 8.21414) }, - Vertex { position: (30.4182, -37.1772, 28.4792) }, - Vertex { position: (26.7523, -38.5429, 24.8133) }, - Vertex { position: (17.6941, -39.5089, 15.755) }, - Vertex { position: (17.1873, -37.1772, 37.3345) }, - Vertex { position: (15.1608, -38.5429, 32.5714) }, - Vertex { position: (10.1532, -39.5089, 20.8021) }, - Vertex { position: (0.831025, -37.1772, 40.5641) }, - Vertex { position: (0.831025, -38.5429, 35.4009) }, - Vertex { position: (0.831025, -39.5089, 22.6427) }, - Vertex { position: (-15.5253, -37.1772, 37.3345) }, - Vertex { position: (-13.4987, -38.5429, 32.5714) }, - Vertex { position: (-8.49115, -39.5089, 20.8021) }, - Vertex { position: (-28.7562, -37.1772, 28.4792) }, - Vertex { position: (-25.0903, -38.5429, 24.8133) }, - Vertex { position: (-16.032, -39.5089, 15.755) }, - Vertex { position: (-37.6115, -37.1772, 15.2483) }, - Vertex { position: (-32.8484, -38.5429, 13.2217) }, - Vertex { position: (-21.0791, -39.5089, 8.21414) }, - Vertex { position: (-40.8411, -37.1772, -1.10804) }, - Vertex { position: (-35.6779, -38.5429, -1.10804) }, - Vertex { position: (-22.9198, -39.5089, -1.10804) }, - Vertex { position: (-37.6115, -37.1772, -17.4643) }, - Vertex { position: (-32.8484, -38.5429, -15.4378) }, - Vertex { position: (-21.0791, -39.5089, -10.4302) }, - Vertex { position: (-28.7562, -37.1772, -30.6952) }, - Vertex { position: (-25.0903, -38.5429, -27.0294) }, - Vertex { position: (-16.032, -39.5089, -17.9711) }, - Vertex { position: (-15.5253, -37.1772, -39.5506) }, - Vertex { position: (-13.4987, -38.5429, -34.7875) }, - Vertex { position: (-8.49115, -39.5089, -23.0181) }, - Vertex { position: (0.831025, -37.1772, -42.7802) }, - Vertex { position: (0.831025, -38.5429, -37.6169) }, - Vertex { position: (0.831025, -39.5089, -24.8588) }, - Vertex { position: (17.1873, -37.1772, -39.5506) }, - Vertex { position: (15.1608, -38.5429, -34.7875) }, - Vertex { position: (10.1532, -39.5089, -23.0181) }, - Vertex { position: (30.4182, -37.1772, -30.6952) }, - Vertex { position: (26.7523, -38.5429, -27.0294) }, - Vertex { position: (17.6941, -39.5089, -17.9711) }, - Vertex { position: (39.2736, -37.1772, -17.4643) }, - Vertex { position: (34.5105, -38.5429, -15.4378) }, - Vertex { position: (22.7411, -39.5089, -10.4302) }, - Vertex { position: (-44.6497, 17.6861, -1.10804) }, - Vertex { position: (-57.9297, 17.5862, -1.10804) }, - Vertex { position: (-67.7453, 16.8867, -1.10804) }, - Vertex { position: (-73.8301, 14.9879, -1.10804) }, - Vertex { position: (-75.9176, 11.2904, -1.10804) }, - Vertex { position: (-44.2055, 18.6855, 3.68876) }, - Vertex { position: (-58.3252, 18.5699, 3.68876) }, - Vertex { position: (-68.6891, 17.7611, 3.68876) }, - Vertex { position: (-75.0724, 15.5657, 3.68876) }, - Vertex { position: (-77.2501, 11.2904, 3.68876) }, - Vertex { position: (-43.2284, 20.884, 5.28769) }, - Vertex { position: (-59.1955, 20.7341, 5.28769) }, - Vertex { position: (-70.7655, 19.6848, 5.28769) }, - Vertex { position: (-77.8053, 16.8367, 5.28769) }, - Vertex { position: (-80.1814, 11.2904, 5.28769) }, - Vertex { position: (-42.2513, 23.0825, 3.68876) }, - Vertex { position: (-60.0657, 22.8983, 3.68876) }, - Vertex { position: (-72.8419, 21.6085, 3.68876) }, - Vertex { position: (-80.5381, 18.1077, 3.68876) }, - Vertex { position: (-83.1128, 11.2904, 3.68876) }, - Vertex { position: (-41.8071, 24.0819, -1.10804) }, - Vertex { position: (-60.4613, 23.882, -1.10804) }, - Vertex { position: (-73.7857, 22.4829, -1.10804) }, - Vertex { position: (-81.7804, 18.6855, -1.10804) }, - Vertex { position: (-84.4453, 11.2904, -1.10804) }, - Vertex { position: (-42.2513, 23.0825, -5.90483) }, - Vertex { position: (-60.0657, 22.8983, -5.90483) }, - Vertex { position: (-72.8419, 21.6085, -5.90483) }, - Vertex { position: (-80.5381, 18.1077, -5.90483) }, - Vertex { position: (-83.1128, 11.2904, -5.90483) }, - Vertex { position: (-43.2284, 20.884, -7.50376) }, - Vertex { position: (-59.1955, 20.7341, -7.50376) }, - Vertex { position: (-70.7655, 19.6848, -7.50376) }, - Vertex { position: (-77.8053, 16.8367, -7.50376) }, - Vertex { position: (-80.1814, 11.2904, -7.50376) }, - Vertex { position: (-44.2055, 18.6855, -5.90483) }, - Vertex { position: (-58.3252, 18.5699, -5.90483) }, - Vertex { position: (-68.6891, 17.7611, -5.90483) }, - Vertex { position: (-75.0724, 15.5657, -5.90483) }, - Vertex { position: (-77.2501, 11.2904, -5.90483) }, - Vertex { position: (-74.8073, 5.4943, -1.10804) }, - Vertex { position: (-71.2985, -1.50103, -1.10804) }, - Vertex { position: (-65.1248, -8.49634, -1.10804) }, - Vertex { position: (-56.0198, -14.2925, -1.10804) }, - Vertex { position: (-76.0183, 4.93477, 3.68876) }, - Vertex { position: (-72.159, -2.35462, 3.68876) }, - Vertex { position: (-65.4267, -9.55033, 3.68876) }, - Vertex { position: (-55.5757, -15.6249, 3.68876) }, - Vertex { position: (-78.6824, 3.70383, 5.28769) }, - Vertex { position: (-74.0522, -4.23253, 5.28769) }, - Vertex { position: (-66.0909, -11.8691, 5.28769) }, - Vertex { position: (-54.5986, -18.5563, 5.28769) }, - Vertex { position: (-81.3466, 2.47288, 3.68876) }, - Vertex { position: (-75.9454, -6.11044, 3.68876) }, - Vertex { position: (-66.755, -14.1878, 3.68876) }, - Vertex { position: (-53.6214, -21.4877, 3.68876) }, - Vertex { position: (-82.5576, 1.91336, -1.10804) }, - Vertex { position: (-76.8059, -6.96404, -1.10804) }, - Vertex { position: (-67.0569, -15.2418, -1.10804) }, - Vertex { position: (-53.1773, -22.8201, -1.10804) }, - Vertex { position: (-81.3466, 2.47288, -5.90483) }, - Vertex { position: (-75.9454, -6.11044, -5.90483) }, - Vertex { position: (-66.755, -14.1878, -5.90483) }, - Vertex { position: (-53.6214, -21.4877, -5.90483) }, - Vertex { position: (-78.6824, 3.70383, -7.50376) }, - Vertex { position: (-74.0522, -4.23253, -7.50376) }, - Vertex { position: (-66.0909, -11.8691, -7.50376) }, - Vertex { position: (-54.5986, -18.5563, -7.50376) }, - Vertex { position: (-76.0183, 4.93477, -5.90483) }, - Vertex { position: (-72.159, -2.35462, -5.90483) }, - Vertex { position: (-65.4267, -9.55033, -5.90483) }, - Vertex { position: (-55.5757, -15.6249, -5.90483) }, - Vertex { position: (49.1543, 0.630882, -1.10804) }, - Vertex { position: (62.7896, 3.76212, -1.10804) }, - Vertex { position: (68.6967, 11.2904, -1.10804) }, - Vertex { position: (71.939, 20.4176, -1.10804) }, - Vertex { position: (77.5797, 28.3457, -1.10804) }, - Vertex { position: (49.1543, -3.03333, 9.4449) }, - Vertex { position: (63.8305, 1.04519, 8.42059) }, - Vertex { position: (70.0292, 9.70814, 6.1671) }, - Vertex { position: (73.5629, 19.8451, 3.91361) }, - Vertex { position: (80.2446, 28.3457, 2.88929) }, - Vertex { position: (49.1543, -11.0946, 12.9626) }, - Vertex { position: (66.1207, -4.93206, 11.5968) }, - Vertex { position: (72.9605, 6.22714, 8.59214) }, - Vertex { position: (77.1355, 18.5855, 5.58749) }, - Vertex { position: (86.1073, 28.3457, 4.22173) }, - Vertex { position: (49.1543, -19.1559, 9.4449) }, - Vertex { position: (68.4108, -10.9093, 8.42059) }, - Vertex { position: (75.8919, 2.74614, 6.1671) }, - Vertex { position: (80.7081, 17.326, 3.91361) }, - Vertex { position: (91.97, 28.3457, 2.88929) }, - Vertex { position: (49.1543, -22.8201, -1.10804) }, - Vertex { position: (69.4518, -13.6262, -1.10804) }, - Vertex { position: (77.2244, 1.16386, -1.10804) }, - Vertex { position: (82.3321, 16.7534, -1.10804) }, - Vertex { position: (94.6349, 28.3457, -1.10804) }, - Vertex { position: (49.1543, -19.1559, -11.661) }, - Vertex { position: (68.4108, -10.9093, -10.6367) }, - Vertex { position: (75.8919, 2.74614, -8.38317) }, - Vertex { position: (80.7081, 17.326, -6.12968) }, - Vertex { position: (91.97, 28.3457, -5.10536) }, - Vertex { position: (49.1543, -11.0946, -15.1786) }, - Vertex { position: (66.1207, -4.93206, -13.8129) }, - Vertex { position: (72.9605, 6.22714, -10.8082) }, - Vertex { position: (77.1355, 18.5855, -7.80356) }, - Vertex { position: (86.1073, 28.3457, -6.4378) }, - Vertex { position: (49.1543, -3.03333, -11.661) }, - Vertex { position: (63.8305, 1.04519, -10.6367) }, - Vertex { position: (70.0292, 9.70814, -8.38317) }, - Vertex { position: (73.5629, 19.8451, -6.12968) }, - Vertex { position: (80.2446, 28.3457, -5.10536) }, - Vertex { position: (79.6227, 29.5449, -1.10804) }, - Vertex { position: (81.1329, 29.9446, -1.10804) }, - Vertex { position: (81.577, 29.5449, -1.10804) }, - Vertex { position: (80.4222, 28.3457, -1.10804) }, - Vertex { position: (82.4767, 29.6034, 2.63946) }, - Vertex { position: (83.8116, 30.0383, 2.08983) }, - Vertex { position: (83.8515, 29.6268, 1.54019) }, - Vertex { position: (82.1988, 28.3457, 1.29036) }, - Vertex { position: (88.7555, 29.7322, 3.88862) }, - Vertex { position: (89.7049, 30.2444, 3.15578) }, - Vertex { position: (88.8555, 29.8072, 2.42294) }, - Vertex { position: (86.1073, 28.3457, 2.08983) }, - Vertex { position: (95.0343, 29.8611, 2.63946) }, - Vertex { position: (95.5982, 30.4505, 2.08983) }, - Vertex { position: (93.8594, 29.9875, 1.54019) }, - Vertex { position: (90.0158, 28.3457, 1.29036) }, - Vertex { position: (97.8883, 29.9196, -1.10804) }, - Vertex { position: (98.2769, 30.5442, -1.10804) }, - Vertex { position: (96.1339, 30.0695, -1.10804) }, - Vertex { position: (91.7924, 28.3457, -1.10804) }, - Vertex { position: (95.0343, 29.8611, -4.85553) }, - Vertex { position: (95.5982, 30.4505, -4.3059) }, - Vertex { position: (93.8594, 29.9875, -3.75626) }, - Vertex { position: (90.0158, 28.3457, -3.50643) }, - Vertex { position: (88.7555, 29.7322, -6.10469) }, - Vertex { position: (89.7049, 30.2444, -5.37185) }, - Vertex { position: (88.8555, 29.8072, -4.63901) }, - Vertex { position: (86.1073, 28.3457, -4.3059) }, - Vertex { position: (82.4767, 29.6034, -4.85553) }, - Vertex { position: (83.8116, 30.0383, -4.3059) }, - Vertex { position: (83.8515, 29.6268, -3.75626) }, - Vertex { position: (82.1988, 28.3457, -3.50643) }, - Vertex { position: (0.831025, 49.6647, -1.10804) }, - Vertex { position: (10.5134, 48.2657, -1.10804) }, - Vertex { position: (10.0693, 44.868, -1.10804) }, - Vertex { position: (6.42728, 40.6708, -1.10804) }, - Vertex { position: (6.51611, 36.8733, -1.10804) }, - Vertex { position: (9.76642, 48.2657, 2.70243) }, - Vertex { position: (9.35632, 44.868, 2.52698) }, - Vertex { position: (5.9947, 40.6708, 1.09187) }, - Vertex { position: (6.07552, 36.8733, 1.12336) }, - Vertex { position: (7.71453, 48.2657, 5.77547) }, - Vertex { position: (7.39819, 44.868, 5.45913) }, - Vertex { position: (4.80736, 40.6708, 2.8683) }, - Vertex { position: (4.86744, 36.8733, 2.92838) }, - Vertex { position: (4.64149, 48.2657, 7.82736) }, - Vertex { position: (4.46604, 44.868, 7.41726) }, - Vertex { position: (3.03093, 40.6708, 4.05564) }, - Vertex { position: (3.06242, 36.8733, 4.13646) }, - Vertex { position: (0.831025, 48.2657, 8.57438) }, - Vertex { position: (0.831025, 44.868, 8.13023) }, - Vertex { position: (0.831025, 40.6708, 4.48822) }, - Vertex { position: (0.831025, 36.8733, 4.57705) }, - Vertex { position: (-2.97944, 48.2657, 7.82736) }, - Vertex { position: (-2.80399, 44.868, 7.41726) }, - Vertex { position: (-1.36888, 40.6708, 4.05564) }, - Vertex { position: (-1.40037, 36.8733, 4.13646) }, - Vertex { position: (-6.05248, 48.2657, 5.77547) }, - Vertex { position: (-5.73614, 44.868, 5.45913) }, - Vertex { position: (-3.14531, 40.6708, 2.8683) }, - Vertex { position: (-3.20539, 36.8733, 2.92838) }, - Vertex { position: (-8.10437, 48.2657, 2.70243) }, - Vertex { position: (-7.69427, 44.868, 2.52698) }, - Vertex { position: (-4.33265, 40.6708, 1.09187) }, - Vertex { position: (-4.41347, 36.8733, 1.12336) }, - Vertex { position: (-8.85139, 48.2657, -1.10804) }, - Vertex { position: (-8.40724, 44.868, -1.10804) }, - Vertex { position: (-4.76523, 40.6708, -1.10804) }, - Vertex { position: (-4.85406, 36.8733, -1.10804) }, - Vertex { position: (-8.10437, 48.2657, -4.9185) }, - Vertex { position: (-7.69427, 44.868, -4.74305) }, - Vertex { position: (-4.33265, 40.6708, -3.30794) }, - Vertex { position: (-4.41347, 36.8733, -3.33943) }, - Vertex { position: (-6.05248, 48.2657, -7.99154) }, - Vertex { position: (-5.73614, 44.868, -7.6752) }, - Vertex { position: (-3.14531, 40.6708, -5.08437) }, - Vertex { position: (-3.20539, 36.8733, -5.14445) }, - Vertex { position: (-2.97944, 48.2657, -10.0434) }, - Vertex { position: (-2.80399, 44.868, -9.63333) }, - Vertex { position: (-1.36888, 40.6708, -6.27171) }, - Vertex { position: (-1.40037, 36.8733, -6.35253) }, - Vertex { position: (0.831025, 48.2657, -10.7904) }, - Vertex { position: (0.831025, 44.868, -10.3463) }, - Vertex { position: (0.831025, 40.6708, -6.70429) }, - Vertex { position: (0.831025, 36.8733, -6.79312) }, - Vertex { position: (4.64149, 48.2657, -10.0434) }, - Vertex { position: (4.46604, 44.868, -9.63333) }, - Vertex { position: (3.03093, 40.6708, -6.27171) }, - Vertex { position: (3.06242, 36.8733, -6.35253) }, - Vertex { position: (7.71453, 48.2657, -7.99154) }, - Vertex { position: (7.39819, 44.868, -7.6752) }, - Vertex { position: (4.80736, 40.6708, -5.08437) }, - Vertex { position: (4.86744, 36.8733, -5.14445) }, - Vertex { position: (9.76642, 48.2657, -4.9185) }, - Vertex { position: (9.35632, 44.868, -4.74305) }, - Vertex { position: (5.9947, 40.6708, -3.30794) }, - Vertex { position: (6.07552, 36.8733, -3.33943) }, - Vertex { position: (13.8001, 34.3417, -1.10804) }, - Vertex { position: (24.282, 32.6095, -1.10804) }, - Vertex { position: (33.6979, 30.8773, -1.10804) }, - Vertex { position: (37.7841, 28.3457, -1.10804) }, - Vertex { position: (12.795, 34.3417, 3.98234) }, - Vertex { position: (22.4646, 32.6095, 8.09647) }, - Vertex { position: (31.1507, 30.8773, 11.7922) }, - Vertex { position: (34.9202, 28.3457, 13.396) }, - Vertex { position: (10.0391, 34.3417, 8.10003) }, - Vertex { position: (17.4812, 32.6095, 15.5422) }, - Vertex { position: (24.1665, 30.8773, 22.2275) }, - Vertex { position: (27.0677, 28.3457, 25.1286) }, - Vertex { position: (5.9214, 34.3417, 10.856) }, - Vertex { position: (10.0355, 32.6095, 20.5255) }, - Vertex { position: (13.7313, 30.8773, 29.2117) }, - Vertex { position: (15.3351, 28.3457, 32.9812) }, - Vertex { position: (0.831025, 34.3417, 11.8611) }, - Vertex { position: (0.831025, 32.6095, 22.3429) }, - Vertex { position: (0.831025, 30.8773, 31.7589) }, - Vertex { position: (0.831025, 28.3457, 35.845) }, - Vertex { position: (-4.25935, 34.3417, 10.856) }, - Vertex { position: (-8.37348, 32.6095, 20.5255) }, - Vertex { position: (-12.0692, 30.8773, 29.2117) }, - Vertex { position: (-13.673, 28.3457, 32.9812) }, - Vertex { position: (-8.37704, 34.3417, 8.10003) }, - Vertex { position: (-15.8192, 32.6095, 15.5422) }, - Vertex { position: (-22.5045, 30.8773, 22.2275) }, - Vertex { position: (-25.4056, 28.3457, 25.1286) }, - Vertex { position: (-11.133, 34.3417, 3.98234) }, - Vertex { position: (-20.8025, 32.6095, 8.09647) }, - Vertex { position: (-29.4887, 30.8773, 11.7922) }, - Vertex { position: (-33.2582, 28.3457, 13.396) }, - Vertex { position: (-12.1381, 34.3417, -1.10804) }, - Vertex { position: (-22.62, 32.6095, -1.10804) }, - Vertex { position: (-32.0359, 30.8773, -1.10804) }, - Vertex { position: (-36.122, 28.3457, -1.10804) }, - Vertex { position: (-11.133, 34.3417, -6.19841) }, - Vertex { position: (-20.8025, 32.6095, -10.3125) }, - Vertex { position: (-29.4887, 30.8773, -14.0083) }, - Vertex { position: (-33.2582, 28.3457, -15.6121) }, - Vertex { position: (-8.37704, 34.3417, -10.3161) }, - Vertex { position: (-15.8192, 32.6095, -17.7582) }, - Vertex { position: (-22.5045, 30.8773, -24.4435) }, - Vertex { position: (-25.4056, 28.3457, -27.3447) }, - Vertex { position: (-4.25935, 34.3417, -13.072) }, - Vertex { position: (-8.37348, 32.6095, -22.7416) }, - Vertex { position: (-12.0692, 30.8773, -31.4277) }, - Vertex { position: (-13.673, 28.3457, -35.1972) }, - Vertex { position: (0.831025, 34.3417, -14.0771) }, - Vertex { position: (0.831025, 32.6095, -24.559) }, - Vertex { position: (0.831025, 30.8773, -33.9749) }, - Vertex { position: (0.831025, 28.3457, -38.0611) }, - Vertex { position: (5.9214, 34.3417, -13.072) }, - Vertex { position: (10.0355, 32.6095, -22.7416) }, - Vertex { position: (13.7313, 30.8773, -31.4277) }, - Vertex { position: (15.3351, 28.3457, -35.1972) }, - Vertex { position: (10.0391, 34.3417, -10.3161) }, - Vertex { position: (17.4812, 32.6095, -17.7582) }, - Vertex { position: (24.1665, 30.8773, -24.4435) }, - Vertex { position: (27.0677, 28.3457, -27.3447) }, - Vertex { position: (12.795, 34.3417, -6.19841) }, - Vertex { position: (22.4646, 32.6095, -10.3125) }, - Vertex { position: (31.1507, 30.8773, -14.0083) }, - Vertex { position: (34.9202, 28.3457, -15.6121) } -]; - -#[derive(Copy, Clone)] -pub struct Normal { - normal: (f32, f32, f32) -} - -implement_vertex!(Normal, normal); - -pub const NORMALS: [Normal; 531] = [ - Normal { normal: (0.0, 0.0, 0.0) }, // dummy vector because in the original model indices - // start at 1 - Normal { normal: (-0.966742, -0.255752, 0.0) }, - Normal { normal: (-0.966824, 0.255443, 0.0) }, - Normal { normal: (-0.092052, 0.995754, 0.0) }, - Normal { normal: (0.68205, 0.731305, 0.0) }, - Normal { normal: (0.870301, 0.492521, -0.0) }, - Normal { normal: (-0.893014, -0.256345, -0.369882) }, - Normal { normal: (-0.893437, 0.255997, -0.369102) }, - Normal { normal: (-0.0838771, 0.995843, -0.0355068) }, - Normal { normal: (0.629724, 0.73186, 0.260439) }, - Normal { normal: (0.803725, 0.49337, 0.332584) }, - Normal { normal: (-0.683407, -0.256729, -0.683407) }, - Normal { normal: (-0.683531, 0.256067, -0.683531) }, - Normal { normal: (-0.0649249, 0.995776, -0.0649248) }, - Normal { normal: (0.481398, 0.732469, 0.481398) }, - Normal { normal: (0.614804, 0.493997, 0.614804) }, - Normal { normal: (-0.369882, -0.256345, -0.893014) }, - Normal { normal: (-0.369102, 0.255997, -0.893437) }, - Normal { normal: (-0.0355067, 0.995843, -0.0838772) }, - Normal { normal: (0.260439, 0.73186, 0.629724) }, - Normal { normal: (0.332584, 0.49337, 0.803725) }, - Normal { normal: (-0.00284834, -0.257863, -0.966177) }, - Normal { normal: (-0.00192311, 0.254736, -0.967009) }, - Normal { normal: (-0.000266114, 0.995734, -0.0922702) }, - Normal { normal: (0.0, 0.731295, 0.682061) }, - Normal { normal: (0.0, 0.492521, 0.870301) }, - Normal { normal: (0.379058, -0.3593, -0.852771) }, - Normal { normal: (0.37711, 0.149086, -0.914091) }, - Normal { normal: (0.0275022, 0.992081, -0.122551) }, - Normal { normal: (-0.26101, 0.726762, 0.635367) }, - Normal { normal: (-0.332485, 0.492546, 0.804271) }, - Normal { normal: (0.663548, -0.410791, -0.625264) }, - Normal { normal: (0.712664, 0.0737216, -0.697621) }, - Normal { normal: (0.0997268, 0.987509, -0.121984) }, - Normal { normal: (-0.48732, 0.723754, 0.488568) }, - Normal { normal: (-0.615242, 0.492602, 0.615484) }, - Normal { normal: (0.880028, -0.332908, -0.338709) }, - Normal { normal: (0.917276, 0.167113, -0.361493) }, - Normal { normal: (0.113584, 0.992365, -0.0480695) }, - Normal { normal: (-0.63415, 0.727508, 0.261889) }, - Normal { normal: (-0.804126, 0.492634, 0.332705) }, - Normal { normal: (0.96669, -0.255738, 0.0104537) }, - Normal { normal: (0.967442, 0.252962, 0.00810329) }, - Normal { normal: (0.0934365, 0.995624, 0.00128063) }, - Normal { normal: (-0.682167, 0.731196, -0.00034353) }, - Normal { normal: (-0.870322, 0.492483, -0.0) }, - Normal { normal: (0.893014, -0.256345, 0.369882) }, - Normal { normal: (0.893437, 0.255997, 0.369102) }, - Normal { normal: (0.0838768, 0.995843, 0.0355066) }, - Normal { normal: (-0.629724, 0.73186, -0.260439) }, - Normal { normal: (-0.803725, 0.49337, -0.332584) }, - Normal { normal: (0.683407, -0.256729, 0.683407) }, - Normal { normal: (0.683531, 0.256067, 0.683531) }, - Normal { normal: (0.0649249, 0.995776, 0.0649249) }, - Normal { normal: (-0.481398, 0.732469, -0.481398) }, - Normal { normal: (-0.614804, 0.493997, -0.614804) }, - Normal { normal: (0.369882, -0.256345, 0.893014) }, - Normal { normal: (0.369102, 0.255997, 0.893437) }, - Normal { normal: (0.0355067, 0.995843, 0.083877) }, - Normal { normal: (-0.260439, 0.73186, -0.629724) }, - Normal { normal: (-0.332584, 0.49337, -0.803725) }, - Normal { normal: (0.0, -0.255752, 0.966742) }, - Normal { normal: (0.0, 0.255443, 0.966824) }, - Normal { normal: (0.0, 0.995754, 0.092052) }, - Normal { normal: (0.0, 0.731305, -0.68205) }, - Normal { normal: (-0.0, 0.492521, -0.870301) }, - Normal { normal: (-0.369882, -0.256345, 0.893014) }, - Normal { normal: (-0.369102, 0.255996, 0.893437) }, - Normal { normal: (-0.0355068, 0.995843, 0.0838771) }, - Normal { normal: (0.260439, 0.73186, -0.629724) }, - Normal { normal: (0.332584, 0.49337, -0.803725) }, - Normal { normal: (-0.683407, -0.256729, 0.683407) }, - Normal { normal: (-0.683531, 0.256067, 0.683531) }, - Normal { normal: (-0.0649249, 0.995776, 0.064925) }, - Normal { normal: (0.481398, 0.732469, -0.481398) }, - Normal { normal: (0.614804, 0.493997, -0.614804) }, - Normal { normal: (-0.893014, -0.256345, 0.369882) }, - Normal { normal: (-0.893437, 0.255997, 0.369102) }, - Normal { normal: (-0.0838767, 0.995843, 0.0355066) }, - Normal { normal: (0.629724, 0.73186, -0.260439) }, - Normal { normal: (0.803725, 0.49337, -0.332584) }, - Normal { normal: (0.915321, 0.402725, 0.0) }, - Normal { normal: (0.941808, 0.336151, -0.0) }, - Normal { normal: (0.97869, 0.205342, 0.0) }, - Normal { normal: (0.997804, -0.0662397, 0.0) }, - Normal { normal: (0.845438, 0.403546, 0.349835) }, - Normal { normal: (0.869996, 0.336859, 0.360047) }, - Normal { normal: (0.904193, 0.205791, 0.37428) }, - Normal { normal: (0.921879, -0.0663697, 0.381752) }, - Normal { normal: (0.646802, 0.404096, 0.646802) }, - Normal { normal: (0.665655, 0.337351, 0.665655) }, - Normal { normal: (0.691923, 0.20612, 0.691923) }, - Normal { normal: (0.705542, -0.0664796, 0.705543) }, - Normal { normal: (0.349835, 0.403546, 0.845438) }, - Normal { normal: (0.360047, 0.336859, 0.869996) }, - Normal { normal: (0.37428, 0.205791, 0.904193) }, - Normal { normal: (0.381752, -0.0663697, 0.921879) }, - Normal { normal: (-0.0, 0.402725, 0.915321) }, - Normal { normal: (0.0, 0.336151, 0.941808) }, - Normal { normal: (-0.0, 0.205342, 0.97869) }, - Normal { normal: (-0.0, -0.0662397, 0.997804) }, - Normal { normal: (-0.349835, 0.403546, 0.845438) }, - Normal { normal: (-0.360047, 0.336859, 0.869996) }, - Normal { normal: (-0.37428, 0.205791, 0.904193) }, - Normal { normal: (-0.381752, -0.0663697, 0.921879) }, - Normal { normal: (-0.646802, 0.404096, 0.646802) }, - Normal { normal: (-0.665655, 0.337351, 0.665655) }, - Normal { normal: (-0.691923, 0.20612, 0.691923) }, - Normal { normal: (-0.705543, -0.0664796, 0.705543) }, - Normal { normal: (-0.845438, 0.403546, 0.349835) }, - Normal { normal: (-0.869996, 0.336859, 0.360047) }, - Normal { normal: (-0.904193, 0.205791, 0.37428) }, - Normal { normal: (-0.921879, -0.0663697, 0.381752) }, - Normal { normal: (-0.915321, 0.402725, -0.0) }, - Normal { normal: (-0.941808, 0.336151, -0.0) }, - Normal { normal: (-0.97869, 0.205342, -0.0) }, - Normal { normal: (-0.997804, -0.0662397, -0.0) }, - Normal { normal: (-0.845438, 0.403546, -0.349835) }, - Normal { normal: (-0.869996, 0.336859, -0.360047) }, - Normal { normal: (-0.904193, 0.205791, -0.37428) }, - Normal { normal: (-0.921879, -0.0663697, -0.381752) }, - Normal { normal: (-0.646802, 0.404096, -0.646802) }, - Normal { normal: (-0.665655, 0.337351, -0.665655) }, - Normal { normal: (-0.691923, 0.20612, -0.691923) }, - Normal { normal: (-0.705542, -0.0664796, -0.705543) }, - Normal { normal: (-0.349835, 0.403546, -0.845438) }, - Normal { normal: (-0.360047, 0.336859, -0.869996) }, - Normal { normal: (-0.37428, 0.205791, -0.904193) }, - Normal { normal: (-0.381752, -0.0663697, -0.921879) }, - Normal { normal: (0.0, 0.402725, -0.915321) }, - Normal { normal: (-0.0, 0.336151, -0.941808) }, - Normal { normal: (0.0, 0.205342, -0.97869) }, - Normal { normal: (0.0, -0.0662397, -0.997804) }, - Normal { normal: (0.349835, 0.403546, -0.845438) }, - Normal { normal: (0.360047, 0.336859, -0.869996) }, - Normal { normal: (0.37428, 0.205791, -0.904193) }, - Normal { normal: (0.381752, -0.0663697, -0.921879) }, - Normal { normal: (0.646802, 0.404096, -0.646802) }, - Normal { normal: (0.665655, 0.337351, -0.665655) }, - Normal { normal: (0.691923, 0.20612, -0.691923) }, - Normal { normal: (0.705543, -0.0664796, -0.705542) }, - Normal { normal: (0.845438, 0.403546, -0.349835) }, - Normal { normal: (0.869996, 0.336859, -0.360047) }, - Normal { normal: (0.904193, 0.205791, -0.37428) }, - Normal { normal: (0.921879, -0.0663697, -0.381752) }, - Normal { normal: (0.900182, -0.435513, -0.0) }, - Normal { normal: (0.729611, -0.683863, -0.0) }, - Normal { normal: (0.693951, -0.720022, -0.0) }, - Normal { normal: (0.79395, -0.607984, 0.0) }, - Normal { normal: (0.831437, -0.43618, 0.344179) }, - Normal { normal: (0.673512, -0.684665, 0.278594) }, - Normal { normal: (0.640399, -0.720924, 0.264874) }, - Normal { normal: (0.732949, -0.608996, 0.303166) }, - Normal { normal: (0.636092, -0.436777, 0.636092) }, - Normal { normal: (0.514965, -0.685289, 0.514965) }, - Normal { normal: (0.489651, -0.721446, 0.489651) }, - Normal { normal: (0.560555, -0.609554, 0.560555) }, - Normal { normal: (0.344179, -0.43618, 0.831437) }, - Normal { normal: (0.278594, -0.684665, 0.673512) }, - Normal { normal: (0.264874, -0.720924, 0.640399) }, - Normal { normal: (0.303166, -0.608996, 0.732949) }, - Normal { normal: (0.0, -0.435513, 0.900182) }, - Normal { normal: (-0.0, -0.683863, 0.729611) }, - Normal { normal: (0.0, -0.720022, 0.693951) }, - Normal { normal: (-0.0, -0.607984, 0.79395) }, - Normal { normal: (-0.344179, -0.43618, 0.831437) }, - Normal { normal: (-0.278594, -0.684665, 0.673512) }, - Normal { normal: (-0.264874, -0.720924, 0.640399) }, - Normal { normal: (-0.303166, -0.608996, 0.732949) }, - Normal { normal: (-0.636092, -0.436777, 0.636092) }, - Normal { normal: (-0.514965, -0.685289, 0.514965) }, - Normal { normal: (-0.489651, -0.721446, 0.489651) }, - Normal { normal: (-0.560555, -0.609554, 0.560555) }, - Normal { normal: (-0.831437, -0.43618, 0.344179) }, - Normal { normal: (-0.673512, -0.684665, 0.278595) }, - Normal { normal: (-0.640399, -0.720924, 0.264874) }, - Normal { normal: (-0.732949, -0.608996, 0.303166) }, - Normal { normal: (-0.900182, -0.435513, -0.0) }, - Normal { normal: (-0.729611, -0.683863, -0.0) }, - Normal { normal: (-0.693951, -0.720022, 0.0) }, - Normal { normal: (-0.79395, -0.607983, -0.0) }, - Normal { normal: (-0.831437, -0.43618, -0.344179) }, - Normal { normal: (-0.673512, -0.684665, -0.278594) }, - Normal { normal: (-0.640399, -0.720924, -0.264874) }, - Normal { normal: (-0.732949, -0.608996, -0.303166) }, - Normal { normal: (-0.636092, -0.436777, -0.636092) }, - Normal { normal: (-0.514965, -0.685289, -0.514965) }, - Normal { normal: (-0.489651, -0.721446, -0.489651) }, - Normal { normal: (-0.560555, -0.609554, -0.560555) }, - Normal { normal: (-0.344179, -0.43618, -0.831437) }, - Normal { normal: (-0.278594, -0.684665, -0.673512) }, - Normal { normal: (-0.264874, -0.720924, -0.640399) }, - Normal { normal: (-0.303166, -0.608996, -0.732949) }, - Normal { normal: (-0.0, -0.435513, -0.900182) }, - Normal { normal: (0.0, -0.683863, -0.729611) }, - Normal { normal: (-0.0, -0.720022, -0.693951) }, - Normal { normal: (0.0, -0.607984, -0.79395) }, - Normal { normal: (0.344179, -0.43618, -0.831437) }, - Normal { normal: (0.278594, -0.684665, -0.673512) }, - Normal { normal: (0.264874, -0.720924, -0.640399) }, - Normal { normal: (0.303167, -0.608996, -0.732949) }, - Normal { normal: (0.636092, -0.436777, -0.636092) }, - Normal { normal: (0.514965, -0.685289, -0.514965) }, - Normal { normal: (0.489651, -0.721446, -0.489651) }, - Normal { normal: (0.560555, -0.609554, -0.560555) }, - Normal { normal: (0.831437, -0.43618, -0.344179) }, - Normal { normal: (0.673512, -0.684665, -0.278595) }, - Normal { normal: (0.640399, -0.720924, -0.264874) }, - Normal { normal: (0.732949, -0.608996, -0.303166) }, - Normal { normal: (0.62386, -0.781536, 0.0) }, - Normal { normal: (0.177291, -0.984159, -0.0) }, - Normal { normal: (0.0492072, -0.998789, 0.0) }, - Normal { normal: (0.0, -1.0, -0.0) }, - Normal { normal: (0.576229, -0.781801, 0.238217) }, - Normal { normal: (0.163629, -0.984208, 0.0675273) }, - Normal { normal: (0.0454217, -0.998792, 0.0187357) }, - Normal { normal: (0.440416, -0.782348, 0.440416) }, - Normal { normal: (0.124903, -0.984276, 0.124903) }, - Normal { normal: (0.0346621, -0.998798, 0.0346621) }, - Normal { normal: (0.238217, -0.781801, 0.576229) }, - Normal { normal: (0.0675273, -0.984208, 0.163629) }, - Normal { normal: (0.0187357, -0.998792, 0.0454217) }, - Normal { normal: (-0.0, -0.781536, 0.62386) }, - Normal { normal: (0.0, -0.984159, 0.177291) }, - Normal { normal: (-0.0, -0.998789, 0.0492072) }, - Normal { normal: (-0.238216, -0.781801, 0.576229) }, - Normal { normal: (-0.0675273, -0.984208, 0.163629) }, - Normal { normal: (-0.0187357, -0.998792, 0.0454217) }, - Normal { normal: (-0.440416, -0.782348, 0.440416) }, - Normal { normal: (-0.124903, -0.984276, 0.124903) }, - Normal { normal: (-0.0346621, -0.998798, 0.0346621) }, - Normal { normal: (-0.576229, -0.781801, 0.238217) }, - Normal { normal: (-0.163629, -0.984208, 0.0675273) }, - Normal { normal: (-0.0454217, -0.998792, 0.0187357) }, - Normal { normal: (-0.62386, -0.781536, -0.0) }, - Normal { normal: (-0.177291, -0.984159, 0.0) }, - Normal { normal: (-0.0492072, -0.998789, -0.0) }, - Normal { normal: (-0.576229, -0.781801, -0.238217) }, - Normal { normal: (-0.163629, -0.984208, -0.0675273) }, - Normal { normal: (-0.0454217, -0.998792, -0.0187357) }, - Normal { normal: (-0.440416, -0.782348, -0.440416) }, - Normal { normal: (-0.124903, -0.984276, -0.124903) }, - Normal { normal: (-0.0346621, -0.998798, -0.0346621) }, - Normal { normal: (-0.238217, -0.781801, -0.576229) }, - Normal { normal: (-0.0675273, -0.984208, -0.163629) }, - Normal { normal: (-0.0187357, -0.998792, -0.0454217) }, - Normal { normal: (0.0, -0.781536, -0.62386) }, - Normal { normal: (-0.0, -0.984159, -0.177291) }, - Normal { normal: (0.0, -0.998789, -0.0492072) }, - Normal { normal: (0.238217, -0.781801, -0.576229) }, - Normal { normal: (0.0675273, -0.984208, -0.163629) }, - Normal { normal: (0.0187357, -0.998792, -0.0454217) }, - Normal { normal: (0.440416, -0.782348, -0.440416) }, - Normal { normal: (0.124903, -0.984276, -0.124903) }, - Normal { normal: (0.0346621, -0.998798, -0.0346621) }, - Normal { normal: (0.576229, -0.781801, -0.238217) }, - Normal { normal: (0.163629, -0.984208, -0.0675273) }, - Normal { normal: (0.0454217, -0.998792, -0.0187357) }, - Normal { normal: (0.00778619, -0.99997, -0.000215809) }, - Normal { normal: (0.0391385, -0.999233, -0.000988567) }, - Normal { normal: (0.179511, -0.983746, -0.00436856) }, - Normal { normal: (0.6123, -0.790556, -0.0104598) }, - Normal { normal: (0.986152, -0.165707, -0.00666949) }, - Normal { normal: (0.00703893, -0.812495, 0.582926) }, - Normal { normal: (0.0361273, -0.837257, 0.545614) }, - Normal { normal: (0.161845, -0.810421, 0.563048) }, - Normal { normal: (0.482365, -0.595148, 0.642746) }, - Normal { normal: (0.73872, -0.114593, 0.664199) }, - Normal { normal: (-0.00190867, 0.162121, 0.986769) }, - Normal { normal: (0.0027616, 0.0171073, 0.99985) }, - Normal { normal: (0.0105326, 0.0733989, 0.997247) }, - Normal { normal: (-0.0660406, 0.130069, 0.989303) }, - Normal { normal: (-0.0944272, 0.0165946, 0.995393) }, - Normal { normal: (-0.009203, 0.871509, 0.490293) }, - Normal { normal: (-0.0486064, 0.840609, 0.539457) }, - Normal { normal: (-0.223298, 0.802881, 0.552739) }, - Normal { normal: (-0.596365, 0.559971, 0.575135) }, - Normal { normal: (-0.803337, 0.0682361, 0.591602) }, - Normal { normal: (-0.0105609, 0.999944, 0.000103364) }, - Normal { normal: (-0.0587986, 0.99827, 0.000709759) }, - Normal { normal: (-0.28071, 0.959787, 0.00326876) }, - Normal { normal: (-0.749723, 0.661738, 0.0042684) }, - Normal { normal: (-0.997351, 0.0727144, 0.00205923) }, - Normal { normal: (-0.00879197, 0.871493, -0.49033) }, - Normal { normal: (-0.0464937, 0.841178, -0.538756) }, - Normal { normal: (-0.217909, 0.806807, -0.549161) }, - Normal { normal: (-0.597291, 0.560026, -0.574121) }, - Normal { normal: (-0.804, 0.0629127, -0.591291) }, - Normal { normal: (-0.00180555, 0.161691, -0.98684) }, - Normal { normal: (0.00203087, 0.014555, -0.999892) }, - Normal { normal: (0.00921499, 0.0600698, -0.998152) }, - Normal { normal: (-0.0593333, 0.113865, -0.991723) }, - Normal { normal: (-0.0868992, 0.0122903, -0.996141) }, - Normal { normal: (0.00641779, -0.812379, -0.583094) }, - Normal { normal: (0.0337833, -0.837512, -0.545373) }, - Normal { normal: (0.157112, -0.811947, -0.56219) }, - Normal { normal: (0.484407, -0.589365, -0.646528) }, - Normal { normal: (0.73887, -0.10132, -0.666187) }, - Normal { normal: (0.946512, 0.32265, -0.0033571) }, - Normal { normal: (0.82583, 0.56387, -0.00745213) }, - Normal { normal: (0.650011, 0.759893, -0.00693681) }, - Normal { normal: (0.532429, 0.846458, -0.00524544) }, - Normal { normal: (0.725608, 0.259351, 0.637362) }, - Normal { normal: (0.645945, 0.461988, 0.607719) }, - Normal { normal: (0.531614, 0.63666, 0.558615) }, - Normal { normal: (0.424964, 0.681717, 0.59554) }, - Normal { normal: (-0.0495616, -0.019755, 0.998576) }, - Normal { normal: (-0.0378162, -0.0356243, 0.99865) }, - Normal { normal: (-0.0379139, -0.0365122, 0.998614) }, - Normal { normal: (-0.168854, -0.297946, 0.93953) }, - Normal { normal: (-0.742342, -0.299166, 0.599523) }, - Normal { normal: (-0.619602, -0.529406, 0.579503) }, - Normal { normal: (-0.483708, -0.685761, 0.543837) }, - Normal { normal: (-0.445293, -0.794355, 0.413176) }, - Normal { normal: (-0.926513, -0.376257, 0.00199587) }, - Normal { normal: (-0.75392, -0.656952, 0.00431723) }, - Normal { normal: (-0.566224, -0.824244, 0.00346105) }, - Normal { normal: (-0.481804, -0.876277, 0.00185047) }, - Normal { normal: (-0.744675, -0.294424, -0.598977) }, - Normal { normal: (-0.621949, -0.528114, -0.578165) }, - Normal { normal: (-0.481171, -0.68834, -0.542828) }, - Normal { normal: (-0.438055, -0.797035, -0.415744) }, - Normal { normal: (-0.0443368, -0.0170558, -0.998871) }, - Normal { normal: (-0.0261761, -0.0281665, -0.99926) }, - Normal { normal: (-0.0252939, -0.0283323, -0.999278) }, - Normal { normal: (-0.157482, -0.289392, -0.944167) }, - Normal { normal: (0.728244, 0.25241, -0.637142) }, - Normal { normal: (0.647055, 0.459725, -0.608254) }, - Normal { normal: (0.522994, 0.640657, -0.562171) }, - Normal { normal: (0.409978, 0.682857, -0.604669) }, - Normal { normal: (-0.230787, 0.972982, -0.00652338) }, - Normal { normal: (-0.548936, 0.835863, -0.00151111) }, - Normal { normal: (-0.875671, 0.482807, 0.00989278) }, - Normal { normal: (-0.877554, 0.479097, 0.0190923) }, - Normal { normal: (-0.69619, 0.717439, 0.024497) }, - Normal { normal: (-0.152878, 0.687211, 0.71019) }, - Normal { normal: (-0.316721, 0.63775, 0.702113) }, - Normal { normal: (-0.601067, 0.471452, 0.64533) }, - Normal { normal: (-0.635889, 0.44609, 0.6298) }, - Normal { normal: (-0.435746, 0.601008, 0.670011) }, - Normal { normal: (0.111112, -0.0850694, 0.99016) }, - Normal { normal: (0.22331, 0.00654036, 0.974726) }, - Normal { normal: (0.190097, 0.154964, 0.969458) }, - Normal { normal: (0.00527077, 0.189482, 0.98187) }, - Normal { normal: (-0.0117518, 0.246688, 0.969024) }, - Normal { normal: (0.343906, -0.722796, 0.599412) }, - Normal { normal: (0.572489, -0.567656, 0.591627) }, - Normal { normal: (0.787436, -0.256459, 0.560512) }, - Normal { normal: (0.647097, -0.306374, 0.698141) }, - Normal { normal: (0.427528, -0.499343, 0.753576) }, - Normal { normal: (0.410926, -0.911668, 0.00128446) }, - Normal { normal: (0.67152, -0.740986, -0.000899122) }, - Normal { normal: (0.922026, -0.38706, -0.00725269) }, - Normal { normal: (0.84691, -0.531556, -0.0138542) }, - Normal { normal: (0.535925, -0.8442, -0.0105045) }, - Normal { normal: (0.341188, -0.722822, -0.600931) }, - Normal { normal: (0.578664, -0.561139, -0.591838) }, - Normal { normal: (0.784869, -0.25102, -0.566542) }, - Normal { normal: (0.642681, -0.302257, -0.70399) }, - Normal { normal: (0.418589, -0.500042, -0.758117) }, - Normal { normal: (0.115806, -0.0791394, -0.990114) }, - Normal { normal: (0.232811, 0.0125652, -0.972441) }, - Normal { normal: (0.206662, 0.153601, -0.96628) }, - Normal { normal: (0.0244996, 0.161443, -0.986578) }, - Normal { normal: (0.00338193, 0.211115, -0.977455) }, - Normal { normal: (-0.134912, 0.687491, -0.713551) }, - Normal { normal: (-0.31954, 0.633073, -0.705062) }, - Normal { normal: (-0.603902, 0.461442, -0.649903) }, - Normal { normal: (-0.631816, 0.437169, -0.640072) }, - Normal { normal: (-0.424306, 0.612706, -0.66675) }, - Normal { normal: (-0.4258, 0.904753, 0.0108049) }, - Normal { normal: (0.0220472, 0.999756, 0.00162273) }, - Normal { normal: (0.999599, 0.0258705, 0.0115556) }, - Normal { normal: (0.709585, -0.704553, 0.00967183) }, - Normal { normal: (-0.259858, 0.791936, 0.552549) }, - Normal { normal: (0.00953916, 0.99972, -0.0216718) }, - Normal { normal: (0.410156, 0.332912, -0.849083) }, - Normal { normal: (0.541523, -0.54862, -0.637) }, - Normal { normal: (0.0463104, 0.455224, 0.889172) }, - Normal { normal: (-0.0106883, 0.988794, 0.148901) }, - Normal { normal: (-0.0443756, 0.682947, -0.729118) }, - Normal { normal: (0.122825, 0.00923214, -0.992385) }, - Normal { normal: (0.481839, -0.180439, 0.85748) }, - Normal { normal: (0.455272, 0.736752, 0.499925) }, - Normal { normal: (-0.220542, 0.907193, -0.358276) }, - Normal { normal: (-0.23592, 0.657249, -0.715797) }, - Normal { normal: (0.728092, -0.685302, -0.0155853) }, - Normal { normal: (0.888739, 0.45811, -0.0166791) }, - Normal { normal: (-0.260097, 0.965582, 0.000800195) }, - Normal { normal: (-0.371612, 0.928378, -0.00441745) }, - Normal { normal: (0.480166, -0.17836, -0.858853) }, - Normal { normal: (0.488103, 0.716801, -0.497947) }, - Normal { normal: (-0.222004, 0.905399, 0.361893) }, - Normal { normal: (-0.235405, 0.66318, 0.710477) }, - Normal { normal: (0.0587203, 0.437704, -0.8972) }, - Normal { normal: (0.00132612, 0.986459, -0.164003) }, - Normal { normal: (-0.0441901, 0.681677, 0.730317) }, - Normal { normal: (0.138801, -0.0341896, 0.98973) }, - Normal { normal: (-0.25889, 0.797206, -0.54538) }, - Normal { normal: (0.0122703, 0.999739, 0.0192865) }, - Normal { normal: (0.39863, 0.35489, 0.845663) }, - Normal { normal: (0.537564, -0.5814, 0.610737) }, - Normal { normal: (-0.0, 1.0, 0.0) }, - Normal { normal: (0.82454, 0.565804, 0.0) }, - Normal { normal: (0.917701, -0.397272, 0.0) }, - Normal { normal: (0.935269, -0.353939, 0.000112842) }, - Normal { normal: (0.780712, 0.624891, 0.0) }, - Normal { normal: (0.762641, 0.565035, 0.314825) }, - Normal { normal: (0.847982, -0.397998, 0.350034) }, - Normal { normal: (0.864141, -0.355261, 0.356441) }, - Normal { normal: (0.720991, 0.625625, 0.297933) }, - Normal { normal: (0.583357, 0.565165, 0.583338) }, - Normal { normal: (0.648485, -0.398726, 0.648448) }, - Normal { normal: (0.660872, -0.355894, 0.660748) }, - Normal { normal: (0.551862, 0.62529, 0.55178) }, - Normal { normal: (0.314824, 0.565051, 0.762629) }, - Normal { normal: (0.350045, -0.397976, 0.847988) }, - Normal { normal: (0.356474, -0.3552, 0.864153) }, - Normal { normal: (0.297983, 0.625515, 0.721067) }, - Normal { normal: (-0.0, 0.565804, 0.82454) }, - Normal { normal: (-0.0, -0.397272, 0.917701) }, - Normal { normal: (-0.000112839, -0.353939, 0.935269) }, - Normal { normal: (-0.0, 0.624891, 0.780712) }, - Normal { normal: (-0.314825, 0.565035, 0.762641) }, - Normal { normal: (-0.350034, -0.397998, 0.847982) }, - Normal { normal: (-0.356441, -0.355261, 0.864141) }, - Normal { normal: (-0.297933, 0.625625, 0.720991) }, - Normal { normal: (-0.583338, 0.565165, 0.583357) }, - Normal { normal: (-0.648448, -0.398726, 0.648485) }, - Normal { normal: (-0.660748, -0.355894, 0.660872) }, - Normal { normal: (-0.55178, 0.62529, 0.551862) }, - Normal { normal: (-0.762629, 0.565051, 0.314824) }, - Normal { normal: (-0.847988, -0.397976, 0.350045) }, - Normal { normal: (-0.864153, -0.3552, 0.356474) }, - Normal { normal: (-0.721067, 0.625515, 0.297983) }, - Normal { normal: (-0.82454, 0.565804, -0.0) }, - Normal { normal: (-0.917701, -0.397272, -0.0) }, - Normal { normal: (-0.935269, -0.353939, -0.000112839) }, - Normal { normal: (-0.780712, 0.624891, -0.0) }, - Normal { normal: (-0.76264, 0.565035, -0.314825) }, - Normal { normal: (-0.847982, -0.397998, -0.350034) }, - Normal { normal: (-0.864141, -0.355261, -0.356441) }, - Normal { normal: (-0.720991, 0.625625, -0.297933) }, - Normal { normal: (-0.583357, 0.565165, -0.583338) }, - Normal { normal: (-0.648485, -0.398726, -0.648448) }, - Normal { normal: (-0.660872, -0.355894, -0.660748) }, - Normal { normal: (-0.551862, 0.62529, -0.55178) }, - Normal { normal: (-0.314824, 0.565051, -0.762629) }, - Normal { normal: (-0.350045, -0.397976, -0.847988) }, - Normal { normal: (-0.356474, -0.3552, -0.864153) }, - Normal { normal: (-0.297983, 0.625515, -0.721067) }, - Normal { normal: (0.0, 0.565804, -0.82454) }, - Normal { normal: (0.0, -0.397272, -0.917701) }, - Normal { normal: (0.000112839, -0.353939, -0.935269) }, - Normal { normal: (0.0, 0.624891, -0.780712) }, - Normal { normal: (0.314825, 0.565035, -0.762641) }, - Normal { normal: (0.350034, -0.397998, -0.847982) }, - Normal { normal: (0.356441, -0.355261, -0.864141) }, - Normal { normal: (0.297933, 0.625625, -0.720991) }, - Normal { normal: (0.583338, 0.565165, -0.583357) }, - Normal { normal: (0.648448, -0.398726, -0.648485) }, - Normal { normal: (0.660748, -0.355894, -0.660872) }, - Normal { normal: (0.55178, 0.62529, -0.551862) }, - Normal { normal: (0.762629, 0.565051, -0.314824) }, - Normal { normal: (0.847988, -0.397976, -0.350045) }, - Normal { normal: (0.864153, -0.3552, -0.356474) }, - Normal { normal: (0.721067, 0.625515, -0.297983) }, - Normal { normal: (0.236584, 0.971611, 0.0) }, - Normal { normal: (0.173084, 0.984907, -0.0) }, - Normal { normal: (0.379703, 0.925108, 0.0) }, - Normal { normal: (0.526673, 0.850068, 0.0) }, - Normal { normal: (0.217978, 0.971775, 0.0902162) }, - Normal { normal: (0.15959, 0.984977, 0.0659615) }, - Normal { normal: (0.350498, 0.925312, 0.14474) }, - Normal { normal: (0.48559, 0.850653, 0.201474) }, - Normal { normal: (0.166631, 0.971838, 0.166631) }, - Normal { normal: (0.121908, 0.985026, 0.121908) }, - Normal { normal: (0.267668, 0.925585, 0.267668) }, - Normal { normal: (0.371315, 0.851029, 0.371315) }, - Normal { normal: (0.0902162, 0.971775, 0.217978) }, - Normal { normal: (0.0659615, 0.984977, 0.15959) }, - Normal { normal: (0.14474, 0.925312, 0.350498) }, - Normal { normal: (0.201474, 0.850653, 0.48559) }, - Normal { normal: (-0.0, 0.971611, 0.236584) }, - Normal { normal: (0.0, 0.984907, 0.173084) }, - Normal { normal: (0.0, 0.925108, 0.379703) }, - Normal { normal: (0.0, 0.850068, 0.526673) }, - Normal { normal: (-0.0902162, 0.971775, 0.217978) }, - Normal { normal: (-0.0659615, 0.984977, 0.15959) }, - Normal { normal: (-0.14474, 0.925312, 0.350498) }, - Normal { normal: (-0.201474, 0.850653, 0.48559) }, - Normal { normal: (-0.166631, 0.971838, 0.166631) }, - Normal { normal: (-0.121908, 0.985026, 0.121908) }, - Normal { normal: (-0.267668, 0.925585, 0.267668) }, - Normal { normal: (-0.371315, 0.851029, 0.371315) }, - Normal { normal: (-0.217978, 0.971775, 0.0902162) }, - Normal { normal: (-0.15959, 0.984977, 0.0659615) }, - Normal { normal: (-0.350498, 0.925312, 0.14474) }, - Normal { normal: (-0.48559, 0.850653, 0.201474) }, - Normal { normal: (-0.236583, 0.971611, -0.0) }, - Normal { normal: (-0.173084, 0.984907, 0.0) }, - Normal { normal: (-0.379703, 0.925108, -0.0) }, - Normal { normal: (-0.526673, 0.850068, 0.0) }, - Normal { normal: (-0.217978, 0.971775, -0.0902162) }, - Normal { normal: (-0.15959, 0.984977, -0.0659615) }, - Normal { normal: (-0.350498, 0.925312, -0.14474) }, - Normal { normal: (-0.48559, 0.850653, -0.201474) }, - Normal { normal: (-0.166631, 0.971838, -0.166631) }, - Normal { normal: (-0.121908, 0.985026, -0.121908) }, - Normal { normal: (-0.267668, 0.925585, -0.267668) }, - Normal { normal: (-0.371315, 0.851029, -0.371315) }, - Normal { normal: (-0.0902162, 0.971775, -0.217978) }, - Normal { normal: (-0.0659615, 0.984977, -0.15959) }, - Normal { normal: (-0.14474, 0.925312, -0.350498) }, - Normal { normal: (-0.201474, 0.850653, -0.485589) }, - Normal { normal: (0.0, 0.971611, -0.236584) }, - Normal { normal: (-0.0, 0.984907, -0.173084) }, - Normal { normal: (-0.0, 0.925108, -0.379703) }, - Normal { normal: (-0.0, 0.850068, -0.526673) }, - Normal { normal: (0.0902162, 0.971775, -0.217978) }, - Normal { normal: (0.0659615, 0.984977, -0.15959) }, - Normal { normal: (0.14474, 0.925312, -0.350498) }, - Normal { normal: (0.201474, 0.850653, -0.48559) }, - Normal { normal: (0.166631, 0.971838, -0.166631) }, - Normal { normal: (0.121908, 0.985026, -0.121908) }, - Normal { normal: (0.267668, 0.925585, -0.267668) }, - Normal { normal: (0.371315, 0.851029, -0.371315) }, - Normal { normal: (0.217978, 0.971775, -0.0902162) }, - Normal { normal: (0.15959, 0.984977, -0.0659615) }, - Normal { normal: (0.350498, 0.925312, -0.14474) }, - Normal { normal: (0.48559, 0.850653, -0.201474) }, -]; - -pub const INDICES: [u16; 3072] = [ - 7, 6, 1, - 1, 2, 7, - 8, 7, 2, - 2, 3, 8, - 9, 8, 3, - 3, 4, 9, - 10, 9, 4, - 4, 5, 10, - 12, 11, 6, - 6, 7, 12, - 13, 12, 7, - 7, 8, 13, - 14, 13, 8, - 8, 9, 14, - 15, 14, 9, - 9, 10, 15, - 17, 16, 11, - 11, 12, 17, - 18, 17, 12, - 12, 13, 18, - 19, 18, 13, - 13, 14, 19, - 20, 19, 14, - 14, 15, 20, - 22, 21, 16, - 16, 17, 22, - 23, 22, 17, - 17, 18, 23, - 24, 23, 18, - 18, 19, 24, - 25, 24, 19, - 19, 20, 25, - 27, 26, 21, - 21, 22, 27, - 28, 27, 22, - 22, 23, 28, - 29, 28, 23, - 23, 24, 29, - 30, 29, 24, - 24, 25, 30, - 32, 31, 26, - 26, 27, 32, - 33, 32, 27, - 27, 28, 33, - 34, 33, 28, - 28, 29, 34, - 35, 34, 29, - 29, 30, 35, - 37, 36, 31, - 31, 32, 37, - 38, 37, 32, - 32, 33, 38, - 39, 38, 33, - 33, 34, 39, - 40, 39, 34, - 34, 35, 40, - 42, 41, 36, - 36, 37, 42, - 43, 42, 37, - 37, 38, 43, - 44, 43, 38, - 38, 39, 44, - 45, 44, 39, - 39, 40, 45, - 47, 46, 41, - 41, 42, 47, - 48, 47, 42, - 42, 43, 48, - 49, 48, 43, - 43, 44, 49, - 50, 49, 44, - 44, 45, 50, - 52, 51, 46, - 46, 47, 52, - 53, 52, 47, - 47, 48, 53, - 54, 53, 48, - 48, 49, 54, - 55, 54, 49, - 49, 50, 55, - 57, 56, 51, - 51, 52, 57, - 58, 57, 52, - 52, 53, 58, - 59, 58, 53, - 53, 54, 59, - 60, 59, 54, - 54, 55, 60, - 62, 61, 56, - 56, 57, 62, - 63, 62, 57, - 57, 58, 63, - 64, 63, 58, - 58, 59, 64, - 65, 64, 59, - 59, 60, 65, - 67, 66, 61, - 61, 62, 67, - 68, 67, 62, - 62, 63, 68, - 69, 68, 63, - 63, 64, 69, - 70, 69, 64, - 64, 65, 70, - 72, 71, 66, - 66, 67, 72, - 73, 72, 67, - 67, 68, 73, - 74, 73, 68, - 68, 69, 74, - 75, 74, 69, - 69, 70, 75, - 77, 76, 71, - 71, 72, 77, - 78, 77, 72, - 72, 73, 78, - 79, 78, 73, - 73, 74, 79, - 80, 79, 74, - 74, 75, 80, - 2, 1, 76, - 76, 77, 2, - 3, 2, 77, - 77, 78, 3, - 4, 3, 78, - 78, 79, 4, - 5, 4, 79, - 79, 80, 5, - 85, 10, 5, - 5, 81, 85, - 86, 85, 81, - 81, 82, 86, - 87, 86, 82, - 82, 83, 87, - 88, 87, 83, - 83, 84, 88, - 89, 15, 10, - 10, 85, 89, - 90, 89, 85, - 85, 86, 90, - 91, 90, 86, - 86, 87, 91, - 92, 91, 87, - 87, 88, 92, - 93, 20, 15, - 15, 89, 93, - 94, 93, 89, - 89, 90, 94, - 95, 94, 90, - 90, 91, 95, - 96, 95, 91, - 91, 92, 96, - 97, 25, 20, - 20, 93, 97, - 98, 97, 93, - 93, 94, 98, - 99, 98, 94, - 94, 95, 99, - 100, 99, 95, - 95, 96, 100, - 101, 30, 25, - 25, 97, 101, - 102, 101, 97, - 97, 98, 102, - 103, 102, 98, - 98, 99, 103, - 104, 103, 99, - 99, 100, 104, - 105, 35, 30, - 30, 101, 105, - 106, 105, 101, - 101, 102, 106, - 107, 106, 102, - 102, 103, 107, - 108, 107, 103, - 103, 104, 108, - 109, 40, 35, - 35, 105, 109, - 110, 109, 105, - 105, 106, 110, - 111, 110, 106, - 106, 107, 111, - 112, 111, 107, - 107, 108, 112, - 113, 45, 40, - 40, 109, 113, - 114, 113, 109, - 109, 110, 114, - 115, 114, 110, - 110, 111, 115, - 116, 115, 111, - 111, 112, 116, - 117, 50, 45, - 45, 113, 117, - 118, 117, 113, - 113, 114, 118, - 119, 118, 114, - 114, 115, 119, - 120, 119, 115, - 115, 116, 120, - 121, 55, 50, - 50, 117, 121, - 122, 121, 117, - 117, 118, 122, - 123, 122, 118, - 118, 119, 123, - 124, 123, 119, - 119, 120, 124, - 125, 60, 55, - 55, 121, 125, - 126, 125, 121, - 121, 122, 126, - 127, 126, 122, - 122, 123, 127, - 128, 127, 123, - 123, 124, 128, - 129, 65, 60, - 60, 125, 129, - 130, 129, 125, - 125, 126, 130, - 131, 130, 126, - 126, 127, 131, - 132, 131, 127, - 127, 128, 132, - 133, 70, 65, - 65, 129, 133, - 134, 133, 129, - 129, 130, 134, - 135, 134, 130, - 130, 131, 135, - 136, 135, 131, - 131, 132, 136, - 137, 75, 70, - 70, 133, 137, - 138, 137, 133, - 133, 134, 138, - 139, 138, 134, - 134, 135, 139, - 140, 139, 135, - 135, 136, 140, - 141, 80, 75, - 75, 137, 141, - 142, 141, 137, - 137, 138, 142, - 143, 142, 138, - 138, 139, 143, - 144, 143, 139, - 139, 140, 144, - 81, 5, 80, - 80, 141, 81, - 82, 81, 141, - 141, 142, 82, - 83, 82, 142, - 142, 143, 83, - 84, 83, 143, - 143, 144, 84, - 149, 88, 84, - 84, 145, 149, - 150, 149, 145, - 145, 146, 150, - 151, 150, 146, - 146, 147, 151, - 152, 151, 147, - 147, 148, 152, - 153, 92, 88, - 88, 149, 153, - 154, 153, 149, - 149, 150, 154, - 155, 154, 150, - 150, 151, 155, - 156, 155, 151, - 151, 152, 156, - 157, 96, 92, - 92, 153, 157, - 158, 157, 153, - 153, 154, 158, - 159, 158, 154, - 154, 155, 159, - 160, 159, 155, - 155, 156, 160, - 161, 100, 96, - 96, 157, 161, - 162, 161, 157, - 157, 158, 162, - 163, 162, 158, - 158, 159, 163, - 164, 163, 159, - 159, 160, 164, - 165, 104, 100, - 100, 161, 165, - 166, 165, 161, - 161, 162, 166, - 167, 166, 162, - 162, 163, 167, - 168, 167, 163, - 163, 164, 168, - 169, 108, 104, - 104, 165, 169, - 170, 169, 165, - 165, 166, 170, - 171, 170, 166, - 166, 167, 171, - 172, 171, 167, - 167, 168, 172, - 173, 112, 108, - 108, 169, 173, - 174, 173, 169, - 169, 170, 174, - 175, 174, 170, - 170, 171, 175, - 176, 175, 171, - 171, 172, 176, - 177, 116, 112, - 112, 173, 177, - 178, 177, 173, - 173, 174, 178, - 179, 178, 174, - 174, 175, 179, - 180, 179, 175, - 175, 176, 180, - 181, 120, 116, - 116, 177, 181, - 182, 181, 177, - 177, 178, 182, - 183, 182, 178, - 178, 179, 183, - 184, 183, 179, - 179, 180, 184, - 185, 124, 120, - 120, 181, 185, - 186, 185, 181, - 181, 182, 186, - 187, 186, 182, - 182, 183, 187, - 188, 187, 183, - 183, 184, 188, - 189, 128, 124, - 124, 185, 189, - 190, 189, 185, - 185, 186, 190, - 191, 190, 186, - 186, 187, 191, - 192, 191, 187, - 187, 188, 192, - 193, 132, 128, - 128, 189, 193, - 194, 193, 189, - 189, 190, 194, - 195, 194, 190, - 190, 191, 195, - 196, 195, 191, - 191, 192, 196, - 197, 136, 132, - 132, 193, 197, - 198, 197, 193, - 193, 194, 198, - 199, 198, 194, - 194, 195, 199, - 200, 199, 195, - 195, 196, 200, - 201, 140, 136, - 136, 197, 201, - 202, 201, 197, - 197, 198, 202, - 203, 202, 198, - 198, 199, 203, - 204, 203, 199, - 199, 200, 204, - 205, 144, 140, - 140, 201, 205, - 206, 205, 201, - 201, 202, 206, - 207, 206, 202, - 202, 203, 207, - 208, 207, 203, - 203, 204, 208, - 145, 84, 144, - 144, 205, 145, - 146, 145, 205, - 205, 206, 146, - 147, 146, 206, - 206, 207, 147, - 148, 147, 207, - 207, 208, 148, - 213, 152, 148, - 148, 209, 213, - 214, 213, 209, - 209, 210, 214, - 215, 214, 210, - 210, 211, 215, - 212, 215, 211, - 211, 212, 212, - 216, 156, 152, - 152, 213, 216, - 217, 216, 213, - 213, 214, 217, - 218, 217, 214, - 214, 215, 218, - 212, 218, 215, - 215, 212, 212, - 219, 160, 156, - 156, 216, 219, - 220, 219, 216, - 216, 217, 220, - 221, 220, 217, - 217, 218, 221, - 212, 221, 218, - 218, 212, 212, - 222, 164, 160, - 160, 219, 222, - 223, 222, 219, - 219, 220, 223, - 224, 223, 220, - 220, 221, 224, - 212, 224, 221, - 221, 212, 212, - 225, 168, 164, - 164, 222, 225, - 226, 225, 222, - 222, 223, 226, - 227, 226, 223, - 223, 224, 227, - 212, 227, 224, - 224, 212, 212, - 228, 172, 168, - 168, 225, 228, - 229, 228, 225, - 225, 226, 229, - 230, 229, 226, - 226, 227, 230, - 212, 230, 227, - 227, 212, 212, - 231, 176, 172, - 172, 228, 231, - 232, 231, 228, - 228, 229, 232, - 233, 232, 229, - 229, 230, 233, - 212, 233, 230, - 230, 212, 212, - 234, 180, 176, - 176, 231, 234, - 235, 234, 231, - 231, 232, 235, - 236, 235, 232, - 232, 233, 236, - 212, 236, 233, - 233, 212, 212, - 237, 184, 180, - 180, 234, 237, - 238, 237, 234, - 234, 235, 238, - 239, 238, 235, - 235, 236, 239, - 212, 239, 236, - 236, 212, 212, - 240, 188, 184, - 184, 237, 240, - 241, 240, 237, - 237, 238, 241, - 242, 241, 238, - 238, 239, 242, - 212, 242, 239, - 239, 212, 212, - 243, 192, 188, - 188, 240, 243, - 244, 243, 240, - 240, 241, 244, - 245, 244, 241, - 241, 242, 245, - 212, 245, 242, - 242, 212, 212, - 246, 196, 192, - 192, 243, 246, - 247, 246, 243, - 243, 244, 247, - 248, 247, 244, - 244, 245, 248, - 212, 248, 245, - 245, 212, 212, - 249, 200, 196, - 196, 246, 249, - 250, 249, 246, - 246, 247, 250, - 251, 250, 247, - 247, 248, 251, - 212, 251, 248, - 248, 212, 212, - 252, 204, 200, - 200, 249, 252, - 253, 252, 249, - 249, 250, 253, - 254, 253, 250, - 250, 251, 254, - 212, 254, 251, - 251, 212, 212, - 255, 208, 204, - 204, 252, 255, - 256, 255, 252, - 252, 253, 256, - 257, 256, 253, - 253, 254, 257, - 212, 257, 254, - 254, 212, 212, - 209, 148, 208, - 208, 255, 209, - 210, 209, 255, - 255, 256, 210, - 211, 210, 256, - 256, 257, 211, - 212, 211, 257, - 257, 212, 212, - 264, 263, 258, - 258, 259, 264, - 265, 264, 259, - 259, 260, 265, - 266, 265, 260, - 260, 261, 266, - 267, 266, 261, - 261, 262, 267, - 269, 268, 263, - 263, 264, 269, - 270, 269, 264, - 264, 265, 270, - 271, 270, 265, - 265, 266, 271, - 272, 271, 266, - 266, 267, 272, - 274, 273, 268, - 268, 269, 274, - 275, 274, 269, - 269, 270, 275, - 276, 275, 270, - 270, 271, 276, - 277, 276, 271, - 271, 272, 277, - 279, 278, 273, - 273, 274, 279, - 280, 279, 274, - 274, 275, 280, - 281, 280, 275, - 275, 276, 281, - 282, 281, 276, - 276, 277, 282, - 284, 283, 278, - 278, 279, 284, - 285, 284, 279, - 279, 280, 285, - 286, 285, 280, - 280, 281, 286, - 287, 286, 281, - 281, 282, 287, - 289, 288, 283, - 283, 284, 289, - 290, 289, 284, - 284, 285, 290, - 291, 290, 285, - 285, 286, 291, - 292, 291, 286, - 286, 287, 292, - 294, 293, 288, - 288, 289, 294, - 295, 294, 289, - 289, 290, 295, - 296, 295, 290, - 290, 291, 296, - 297, 296, 291, - 291, 292, 297, - 259, 258, 293, - 293, 294, 259, - 260, 259, 294, - 294, 295, 260, - 261, 260, 295, - 295, 296, 261, - 262, 261, 296, - 296, 297, 262, - 302, 267, 262, - 262, 298, 302, - 303, 302, 298, - 298, 299, 303, - 304, 303, 299, - 299, 300, 304, - 305, 304, 300, - 300, 301, 305, - 306, 272, 267, - 267, 302, 306, - 307, 306, 302, - 302, 303, 307, - 308, 307, 303, - 303, 304, 308, - 309, 308, 304, - 304, 305, 309, - 310, 277, 272, - 272, 306, 310, - 311, 310, 306, - 306, 307, 311, - 312, 311, 307, - 307, 308, 312, - 313, 312, 308, - 308, 309, 313, - 314, 282, 277, - 277, 310, 314, - 315, 314, 310, - 310, 311, 315, - 316, 315, 311, - 311, 312, 316, - 317, 316, 312, - 312, 313, 317, - 318, 287, 282, - 282, 314, 318, - 319, 318, 314, - 314, 315, 319, - 320, 319, 315, - 315, 316, 320, - 321, 320, 316, - 316, 317, 321, - 322, 292, 287, - 287, 318, 322, - 323, 322, 318, - 318, 319, 323, - 324, 323, 319, - 319, 320, 324, - 325, 324, 320, - 320, 321, 325, - 326, 297, 292, - 292, 322, 326, - 327, 326, 322, - 322, 323, 327, - 328, 327, 323, - 323, 324, 328, - 329, 328, 324, - 324, 325, 329, - 298, 262, 297, - 297, 326, 298, - 299, 298, 326, - 326, 327, 299, - 300, 299, 327, - 327, 328, 300, - 301, 300, 328, - 328, 329, 301, - 336, 335, 330, - 330, 331, 336, - 337, 336, 331, - 331, 332, 337, - 338, 337, 332, - 332, 333, 338, - 339, 338, 333, - 333, 334, 339, - 341, 340, 335, - 335, 336, 341, - 342, 341, 336, - 336, 337, 342, - 343, 342, 337, - 337, 338, 343, - 344, 343, 338, - 338, 339, 344, - 346, 345, 340, - 340, 341, 346, - 347, 346, 341, - 341, 342, 347, - 348, 347, 342, - 342, 343, 348, - 349, 348, 343, - 343, 344, 349, - 351, 350, 345, - 345, 346, 351, - 352, 351, 346, - 346, 347, 352, - 353, 352, 347, - 347, 348, 353, - 354, 353, 348, - 348, 349, 354, - 356, 355, 350, - 350, 351, 356, - 357, 356, 351, - 351, 352, 357, - 358, 357, 352, - 352, 353, 358, - 359, 358, 353, - 353, 354, 359, - 361, 360, 355, - 355, 356, 361, - 362, 361, 356, - 356, 357, 362, - 363, 362, 357, - 357, 358, 363, - 364, 363, 358, - 358, 359, 364, - 366, 365, 360, - 360, 361, 366, - 367, 366, 361, - 361, 362, 367, - 368, 367, 362, - 362, 363, 368, - 369, 368, 363, - 363, 364, 369, - 331, 330, 365, - 365, 366, 331, - 332, 331, 366, - 366, 367, 332, - 333, 332, 367, - 367, 368, 333, - 334, 333, 368, - 368, 369, 334, - 374, 339, 334, - 334, 370, 374, - 375, 374, 370, - 370, 371, 375, - 376, 375, 371, - 371, 372, 376, - 377, 376, 372, - 372, 373, 377, - 378, 344, 339, - 339, 374, 378, - 379, 378, 374, - 374, 375, 379, - 380, 379, 375, - 375, 376, 380, - 381, 380, 376, - 376, 377, 381, - 382, 349, 344, - 344, 378, 382, - 383, 382, 378, - 378, 379, 383, - 384, 383, 379, - 379, 380, 384, - 385, 384, 380, - 380, 381, 385, - 386, 354, 349, - 349, 382, 386, - 387, 386, 382, - 382, 383, 387, - 388, 387, 383, - 383, 384, 388, - 389, 388, 384, - 384, 385, 389, - 390, 359, 354, - 354, 386, 390, - 391, 390, 386, - 386, 387, 391, - 392, 391, 387, - 387, 388, 392, - 393, 392, 388, - 388, 389, 393, - 394, 364, 359, - 359, 390, 394, - 395, 394, 390, - 390, 391, 395, - 396, 395, 391, - 391, 392, 396, - 397, 396, 392, - 392, 393, 397, - 398, 369, 364, - 364, 394, 398, - 399, 398, 394, - 394, 395, 399, - 400, 399, 395, - 395, 396, 400, - 401, 400, 396, - 396, 397, 401, - 370, 334, 369, - 369, 398, 370, - 371, 370, 398, - 398, 399, 371, - 372, 371, 399, - 399, 400, 372, - 373, 372, 400, - 400, 401, 373, - 407, 402, 402, - 402, 403, 407, - 408, 407, 403, - 403, 404, 408, - 409, 408, 404, - 404, 405, 409, - 410, 409, 405, - 405, 406, 410, - 411, 402, 402, - 402, 407, 411, - 412, 411, 407, - 407, 408, 412, - 413, 412, 408, - 408, 409, 413, - 414, 413, 409, - 409, 410, 414, - 415, 402, 402, - 402, 411, 415, - 416, 415, 411, - 411, 412, 416, - 417, 416, 412, - 412, 413, 417, - 418, 417, 413, - 413, 414, 418, - 419, 402, 402, - 402, 415, 419, - 420, 419, 415, - 415, 416, 420, - 421, 420, 416, - 416, 417, 421, - 422, 421, 417, - 417, 418, 422, - 423, 402, 402, - 402, 419, 423, - 424, 423, 419, - 419, 420, 424, - 425, 424, 420, - 420, 421, 425, - 426, 425, 421, - 421, 422, 426, - 427, 402, 402, - 402, 423, 427, - 428, 427, 423, - 423, 424, 428, - 429, 428, 424, - 424, 425, 429, - 430, 429, 425, - 425, 426, 430, - 431, 402, 402, - 402, 427, 431, - 432, 431, 427, - 427, 428, 432, - 433, 432, 428, - 428, 429, 433, - 434, 433, 429, - 429, 430, 434, - 435, 402, 402, - 402, 431, 435, - 436, 435, 431, - 431, 432, 436, - 437, 436, 432, - 432, 433, 437, - 438, 437, 433, - 433, 434, 438, - 439, 402, 402, - 402, 435, 439, - 440, 439, 435, - 435, 436, 440, - 441, 440, 436, - 436, 437, 441, - 442, 441, 437, - 437, 438, 442, - 443, 402, 402, - 402, 439, 443, - 444, 443, 439, - 439, 440, 444, - 445, 444, 440, - 440, 441, 445, - 446, 445, 441, - 441, 442, 446, - 447, 402, 402, - 402, 443, 447, - 448, 447, 443, - 443, 444, 448, - 449, 448, 444, - 444, 445, 449, - 450, 449, 445, - 445, 446, 450, - 451, 402, 402, - 402, 447, 451, - 452, 451, 447, - 447, 448, 452, - 453, 452, 448, - 448, 449, 453, - 454, 453, 449, - 449, 450, 454, - 455, 402, 402, - 402, 451, 455, - 456, 455, 451, - 451, 452, 456, - 457, 456, 452, - 452, 453, 457, - 458, 457, 453, - 453, 454, 458, - 459, 402, 402, - 402, 455, 459, - 460, 459, 455, - 455, 456, 460, - 461, 460, 456, - 456, 457, 461, - 462, 461, 457, - 457, 458, 462, - 463, 402, 402, - 402, 459, 463, - 464, 463, 459, - 459, 460, 464, - 465, 464, 460, - 460, 461, 465, - 466, 465, 461, - 461, 462, 466, - 403, 402, 402, - 402, 463, 403, - 404, 403, 463, - 463, 464, 404, - 405, 404, 464, - 464, 465, 405, - 406, 405, 465, - 465, 466, 406, - 471, 410, 406, - 406, 467, 471, - 472, 471, 467, - 467, 468, 472, - 473, 472, 468, - 468, 469, 473, - 474, 473, 469, - 469, 470, 474, - 475, 414, 410, - 410, 471, 475, - 476, 475, 471, - 471, 472, 476, - 477, 476, 472, - 472, 473, 477, - 478, 477, 473, - 473, 474, 478, - 479, 418, 414, - 414, 475, 479, - 480, 479, 475, - 475, 476, 480, - 481, 480, 476, - 476, 477, 481, - 482, 481, 477, - 477, 478, 482, - 483, 422, 418, - 418, 479, 483, - 484, 483, 479, - 479, 480, 484, - 485, 484, 480, - 480, 481, 485, - 486, 485, 481, - 481, 482, 486, - 487, 426, 422, - 422, 483, 487, - 488, 487, 483, - 483, 484, 488, - 489, 488, 484, - 484, 485, 489, - 490, 489, 485, - 485, 486, 490, - 491, 430, 426, - 426, 487, 491, - 492, 491, 487, - 487, 488, 492, - 493, 492, 488, - 488, 489, 493, - 494, 493, 489, - 489, 490, 494, - 495, 434, 430, - 430, 491, 495, - 496, 495, 491, - 491, 492, 496, - 497, 496, 492, - 492, 493, 497, - 498, 497, 493, - 493, 494, 498, - 499, 438, 434, - 434, 495, 499, - 500, 499, 495, - 495, 496, 500, - 501, 500, 496, - 496, 497, 501, - 502, 501, 497, - 497, 498, 502, - 503, 442, 438, - 438, 499, 503, - 504, 503, 499, - 499, 500, 504, - 505, 504, 500, - 500, 501, 505, - 506, 505, 501, - 501, 502, 506, - 507, 446, 442, - 442, 503, 507, - 508, 507, 503, - 503, 504, 508, - 509, 508, 504, - 504, 505, 509, - 510, 509, 505, - 505, 506, 510, - 511, 450, 446, - 446, 507, 511, - 512, 511, 507, - 507, 508, 512, - 513, 512, 508, - 508, 509, 513, - 514, 513, 509, - 509, 510, 514, - 515, 454, 450, - 450, 511, 515, - 516, 515, 511, - 511, 512, 516, - 517, 516, 512, - 512, 513, 517, - 518, 517, 513, - 513, 514, 518, - 519, 458, 454, - 454, 515, 519, - 520, 519, 515, - 515, 516, 520, - 521, 520, 516, - 516, 517, 521, - 522, 521, 517, - 517, 518, 522, - 523, 462, 458, - 458, 519, 523, - 524, 523, 519, - 519, 520, 524, - 525, 524, 520, - 520, 521, 525, - 526, 525, 521, - 521, 522, 526, - 527, 466, 462, - 462, 523, 527, - 528, 527, 523, - 523, 524, 528, - 529, 528, 524, - 524, 525, 529, - 530, 529, 525, - 525, 526, 530, - 467, 406, 466, - 466, 527, 467, - 468, 467, 527, - 527, 528, 468, - 469, 468, 528, - 528, 529, 469, - 470, 469, 529, - 529, 530, 470u16, -]; From 97195fbd052c5f92f2415dbaaf2058c116ddc465 Mon Sep 17 00:00:00 2001 From: reo Date: Fri, 18 Jul 2025 12:09:24 +0300 Subject: [PATCH 22/89] Add raidillon_input and FPSCameraController --- Cargo.lock | 9 +++ Cargo.toml | 1 + raidillon_game/Cargo.toml | 1 + raidillon_game/src/main.rs | 69 ++++++++++++++++++++++ raidillon_input/Cargo.toml | 8 +++ raidillon_input/src/camera.rs | 73 +++++++++++++++++++++++ raidillon_input/src/lib.rs | 107 ++++++++++++++++++++++++++++++++++ 7 files changed, 268 insertions(+) create mode 100644 raidillon_input/Cargo.toml create mode 100644 raidillon_input/src/camera.rs create mode 100644 raidillon_input/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index b75daea..bc40061 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1748,11 +1748,20 @@ dependencies = [ "hecs", "raidillon_core", "raidillon_ecs", + "raidillon_input", "raidillon_render", "raidillon_ui", "winit", ] +[[package]] +name = "raidillon_input" +version = "0.1.0" +dependencies = [ + "glam", + "winit", +] + [[package]] name = "raidillon_render" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index 67268bd..27dcb24 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,4 +5,5 @@ members = [ "raidillon_render", "raidillon_ui", "raidillon_game", + "raidillon_input", ] diff --git a/raidillon_game/Cargo.toml b/raidillon_game/Cargo.toml index 5c88109..a5aad2f 100644 --- a/raidillon_game/Cargo.toml +++ b/raidillon_game/Cargo.toml @@ -14,3 +14,4 @@ raidillon_ecs = { path = "../raidillon_ecs" } raidillon_ui = { path = "../raidillon_ui" } raidillon_core = { path = "../raidillon_core" } hecs = "0.10.5" +raidillon_input = { path = "../raidillon_input" } diff --git a/raidillon_game/src/main.rs b/raidillon_game/src/main.rs index fc9d741..17d665c 100644 --- a/raidillon_game/src/main.rs +++ b/raidillon_game/src/main.rs @@ -5,6 +5,17 @@ use raidillon_core::Time; use raidillon_ecs::Transform; use raidillon_render::{Camera, GliumRenderer, gltf_loader, ECSRenderer}; use raidillon_ui::Gui; +use raidillon_input::{Input, FPSCameraController}; +use winit::keyboard::KeyCode; +use winit::window::CursorGrabMode; + +#[derive(Copy, Clone, Eq, PartialEq, Hash)] +enum Action { + MoveForward, + MoveBackward, + MoveLeft, + MoveRight, +} fn main() -> Result<()> { let event_loop = glium::winit::event_loop::EventLoop::builder() @@ -26,6 +37,17 @@ fn main() -> Result<()> { // Dear ImGui integration let mut gui = Gui::new(&display, &window)?; + let mut input = Input::::new(); + input.map_key(KeyCode::KeyW, Action::MoveForward); + input.map_key(KeyCode::KeyS, Action::MoveBackward); + input.map_key(KeyCode::KeyA, Action::MoveLeft); + input.map_key(KeyCode::KeyD, Action::MoveRight); + + let mut camera_controller = FPSCameraController::new(Vec3::new(0.0, 0.0, 2.0)); + + let mut cursor_grabbed = false; + let mut attempted_initial_grab = false; + let mut time = Time::new(); let object_ent = { @@ -66,6 +88,8 @@ fn main() -> Result<()> { gui.handle_event(&window, &event); + input.handle_event(&event); + match event { Event::WindowEvent { event, .. } => match event { WindowEvent::CloseRequested => el.exit(), @@ -110,6 +134,51 @@ fn main() -> Result<()> { }, Event::AboutToWait => { time.tick(); + + if !attempted_initial_grab { + attempted_initial_grab = true; + if window + .set_cursor_grab(CursorGrabMode::Confined) + .or_else(|_| window.set_cursor_grab(CursorGrabMode::Locked)) + .is_ok() + { + window.set_cursor_visible(false); + cursor_grabbed = true; + } + } + + { + let dt = time.delta_seconds(); + camera_controller.update( + &input, + dt, + cursor_grabbed, + (Action::MoveForward, Action::MoveBackward, Action::MoveLeft, Action::MoveRight), + ); + + if input.key_pressed(KeyCode::Escape) { + if cursor_grabbed { + let _ = window.set_cursor_grab(CursorGrabMode::None); + window.set_cursor_visible(true); + cursor_grabbed = false; + } else if window + .set_cursor_grab(CursorGrabMode::Confined) + .or_else(|_| window.set_cursor_grab(CursorGrabMode::Locked)) + .is_ok() + { + window.set_cursor_visible(false); + cursor_grabbed = true; + } + } + + if let Ok(mut cam) = ecsr.world.query_one_mut::<&mut Camera>(camera_ent) { + cam.eye = camera_controller.position; + cam.center = camera_controller.position + camera_controller.front(); + } + } + + input.end_frame(); + gui.prepare_frame(&window); window.request_redraw(); } diff --git a/raidillon_input/Cargo.toml b/raidillon_input/Cargo.toml new file mode 100644 index 0000000..1f1700d --- /dev/null +++ b/raidillon_input/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "raidillon_input" +version = "0.1.0" +edition = "2021" + +[dependencies] +winit = "0.30" +glam = "0.30.4" \ No newline at end of file diff --git a/raidillon_input/src/camera.rs b/raidillon_input/src/camera.rs new file mode 100644 index 0000000..00b4fea --- /dev/null +++ b/raidillon_input/src/camera.rs @@ -0,0 +1,73 @@ +use glam::Vec3; +use std::hash::Hash; + +use super::Input; + +#[derive(Debug, Clone)] +pub struct FPSCameraController { + pub position: Vec3, + yaw: f32, + pitch: f32, + pub speed: f32, + pub sensitivity: f32, +} + +impl FPSCameraController { + pub fn new(position: Vec3) -> Self { + Self { + position, + yaw: -90.0, + pitch: 0.0, + speed: 3.0, + sensitivity: 0.1, + } + } + + pub fn update(&mut self, + input: &Input, + dt: f32, + mouse_enabled: bool, + actions: (A, A, A, A)) + where + A: Copy + Eq + Hash, + { + let (forward, backward, left, right) = actions; + + // Mouse look + if mouse_enabled { + let (dx, dy) = input.mouse_delta(); + self.yaw += dx as f32 * self.sensitivity; + self.pitch -= dy as f32 * self.sensitivity; + self.pitch = self.pitch.clamp(-89.0, 89.0); + } + + // Movement + let front = self.front(); + let right_vec = front.cross(Vec3::Y).normalize(); + let frame_speed = self.speed * dt; + + if input.action_held(forward) { + self.position += front * frame_speed; + } + if input.action_held(backward) { + self.position -= front * frame_speed; + } + if input.action_held(left) { + self.position -= right_vec * frame_speed; + } + if input.action_held(right) { + self.position += right_vec * frame_speed; + } + } + + 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() + } +} \ No newline at end of file diff --git a/raidillon_input/src/lib.rs b/raidillon_input/src/lib.rs new file mode 100644 index 0000000..25f5a95 --- /dev/null +++ b/raidillon_input/src/lib.rs @@ -0,0 +1,107 @@ +use std::collections::{HashMap, HashSet}; +use std::hash::Hash; + +use winit::event::{DeviceEvent, ElementState, Event, WindowEvent}; +use winit::keyboard::{KeyCode, PhysicalKey}; + +pub mod camera; +pub use camera::FPSCameraController; + +pub struct Input { + pressed_keys: HashSet, + pressed_once: HashSet, + + keymap: HashMap, + pressed_actions: HashSet, + pressed_actions_once: HashSet, + + mouse_delta: (f64, f64), +} + +impl Input { + pub fn new() -> Self { + Self { + pressed_keys: HashSet::new(), + pressed_once: HashSet::new(), + keymap: HashMap::new(), + pressed_actions: HashSet::new(), + pressed_actions_once: HashSet::new(), + mouse_delta: (0.0, 0.0), + } + } + + pub fn map_key(&mut self, key: KeyCode, action: A) { + self.keymap.insert(key, action); + } + + pub fn clear_keymap(&mut self) { + self.keymap.clear(); + self.pressed_actions.clear(); + self.pressed_actions_once.clear(); + } + + pub fn handle_event(&mut self, event: &Event) { + match event { + Event::WindowEvent { event, .. } => match event { + WindowEvent::KeyboardInput { event, .. } => { + let key_code = match event.physical_key { + PhysicalKey::Code(code) => code, + _ => return, + }; + + match event.state { + ElementState::Pressed => { + self.pressed_keys.insert(key_code); + self.pressed_once.insert(key_code); + + if let Some(&action) = self.keymap.get(&key_code) { + self.pressed_actions.insert(action); + self.pressed_actions_once.insert(action); + } + } + ElementState::Released => { + self.pressed_keys.remove(&key_code); + + if let Some(&action) = self.keymap.get(&key_code) { + self.pressed_actions.remove(&action); + } + } + } + } + _ => {} + }, + Event::DeviceEvent { event, .. } => match event { + DeviceEvent::MouseMotion { delta } => { + self.mouse_delta.0 += delta.0; + self.mouse_delta.1 += delta.1; + } + _ => {} + }, + _ => {} + } + } + + pub fn key_held(&self, key: KeyCode) -> bool { + self.pressed_keys.contains(&key) + } + pub fn key_pressed(&self, key: KeyCode) -> bool { + self.pressed_once.contains(&key) + } + + pub fn action_held(&self, action: A) -> bool { + self.pressed_actions.contains(&action) + } + pub fn action_pressed(&self, action: A) -> bool { + self.pressed_actions_once.contains(&action) + } + + pub fn mouse_delta(&self) -> (f64, f64) { + self.mouse_delta + } + + pub fn end_frame(&mut self) { + self.mouse_delta = (0.0, 0.0); + self.pressed_once.clear(); + self.pressed_actions_once.clear(); + } +} \ No newline at end of file From a3d3f641cd8d9db2a256a60b0624a87b7db835db Mon Sep 17 00:00:00 2001 From: reo Date: Sat, 19 Jul 2025 00:15:21 +0300 Subject: [PATCH 23/89] Improve abstraction of the engine - Improved camera controls - Introduce new convenience function ecsr.load_mesh_from_gltf - Abstract out the glium stuff to allow for more backends in the future. We're still tied to winit though as it can be used with any of the major graphics libraries in the Rust ecosystem. --- Cargo.lock | 4 +- raidillon_game/Cargo.toml | 2 - raidillon_game/src/main.rs | 110 +++++++++++---------------- raidillon_render/Cargo.toml | 1 + raidillon_render/src/ecs_renderer.rs | 14 ++++ raidillon_render/src/lib.rs | 2 + raidillon_render/src/render.rs | 4 + raidillon_render/src/window.rs | 28 +++++++ raidillon_ui/Cargo.toml | 1 + raidillon_ui/src/ui.rs | 23 +++++- 10 files changed, 115 insertions(+), 74 deletions(-) create mode 100644 raidillon_render/src/window.rs diff --git a/Cargo.lock b/Cargo.lock index bc40061..0a091ac 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1743,8 +1743,6 @@ version = "0.1.0" dependencies = [ "anyhow", "glam", - "glium", - "glutin", "hecs", "raidillon_core", "raidillon_ecs", @@ -1774,6 +1772,7 @@ dependencies = [ "hecs", "image", "raidillon_ecs", + "winit", ] [[package]] @@ -1785,6 +1784,7 @@ dependencies = [ "imgui", "imgui-glium-renderer", "imgui-winit-support", + "raidillon_render", "winit", ] diff --git a/raidillon_game/Cargo.toml b/raidillon_game/Cargo.toml index a5aad2f..c127172 100644 --- a/raidillon_game/Cargo.toml +++ b/raidillon_game/Cargo.toml @@ -6,8 +6,6 @@ edition = "2021" [dependencies] anyhow = "1.0.98" glam = "0.30.4" -glium = { version = "0.35.0", features = ["glutin_backend", "simple_window_builder"] } -glutin = { version = "0.32.3", default-features = false } winit = "0.30" raidillon_render = { path = "../raidillon_render" } raidillon_ecs = { path = "../raidillon_ecs" } diff --git a/raidillon_game/src/main.rs b/raidillon_game/src/main.rs index 17d665c..825f1c2 100644 --- a/raidillon_game/src/main.rs +++ b/raidillon_game/src/main.rs @@ -1,13 +1,13 @@ use anyhow::Result; use glam::{Quat, Vec3, EulerRot}; -use glium::backend::glutin::SimpleWindowBuilder; use raidillon_core::Time; use raidillon_ecs::Transform; -use raidillon_render::{Camera, GliumRenderer, gltf_loader, ECSRenderer}; +use raidillon_render::{Camera, ECSRenderer, init_render_window, DisplayHandle}; use raidillon_ui::Gui; use raidillon_input::{Input, FPSCameraController}; use winit::keyboard::KeyCode; use winit::window::CursorGrabMode; +use winit::event::MouseButton; #[derive(Copy, Clone, Eq, PartialEq, Hash)] enum Action { @@ -18,24 +18,17 @@ enum Action { } fn main() -> Result<()> { - let event_loop = glium::winit::event_loop::EventLoop::builder() + let event_loop = winit::event_loop::EventLoop::builder() .build() .expect("create event-loop"); - let (window, display) = SimpleWindowBuilder::new() - .with_title("raidillon") - .with_inner_size(1280, 720) - .build(&event_loop); + let (window, _display): (winit::window::Window, DisplayHandle) = init_render_window(&event_loop, "raidillon", (1280, 720))?; // Create ECS renderer which internally owns both the world and the renderer - let mut ecsr = { - let world = hecs::World::new(); - let renderer = GliumRenderer::new(display.clone())?; - ECSRenderer::new(renderer, world) - }; + let mut ecsr = ECSRenderer::from_display_handle(&_display)?; // Dear ImGui integration - let mut gui = Gui::new(&display, &window)?; + let mut gui = Gui::new(&_display, &window)?; let mut input = Input::::new(); input.map_key(KeyCode::KeyW, Action::MoveForward); @@ -45,28 +38,21 @@ fn main() -> Result<()> { let mut camera_controller = FPSCameraController::new(Vec3::new(0.0, 0.0, 2.0)); - let mut cursor_grabbed = false; - let mut attempted_initial_grab = false; + let mut right_mouse_held = false; let mut time = Time::new(); - let object_ent = { - let model_3d = gltf_loader::load_gltf("resources/models/tree.gltf", &display)?; - ecsr.spawn_mesh(model_3d, Transform { - translation: Vec3::new(0.0, -2.5, -5.0), - rotation: Quat::IDENTITY, - scale: Vec3::new(0.01, 0.01, 0.01), - }) - }; + let object_ent = ecsr.load_mesh_from_gltf("resources/models/tree.gltf", Transform { + translation: Vec3::new(0.0, -2.5, -5.0), + rotation: Quat::IDENTITY, + scale: Vec3::new(0.01, 0.01, 0.01), + })?; - let ground_ent = { - let model_3d = gltf_loader::load_gltf("resources/models/plane.gltf", &display)?; - ecsr.spawn_mesh(model_3d, Transform { - translation: Vec3::new(0.0, -1.5, 0.0), - rotation: Quat::IDENTITY, - scale: Vec3::new(1.0, 1.0, 1.0), - }) - }; + let ground_ent = ecsr.load_mesh_from_gltf("resources/models/plane.gltf", Transform { + translation: Vec3::new(0.0, -1.5, 0.0), + rotation: Quat::IDENTITY, + scale: Vec3::new(1.0, 1.0, 1.0), + })?; let camera_ent = { @@ -84,7 +70,7 @@ fn main() -> Result<()> { event_loop .run(move |event, el| { - use glium::winit::event::{Event, WindowEvent}; + use winit::event::{Event, WindowEvent}; gui.handle_event(&window, &event); @@ -98,13 +84,33 @@ fn main() -> Result<()> { cam.aspect = sz.width as f32 / sz.height as f32; }); } + WindowEvent::MouseInput { state, button, .. } => { + if button == MouseButton::Right { + match state { + winit::event::ElementState::Pressed => { + if window + .set_cursor_grab(CursorGrabMode::Confined) + .or_else(|_| window.set_cursor_grab(CursorGrabMode::Locked)) + .is_ok() + { + window.set_cursor_visible(false); + right_mouse_held = true; + } + } + winit::event::ElementState::Released => { + let _ = window.set_cursor_grab(CursorGrabMode::None); + window.set_cursor_visible(true); + right_mouse_held = false; + } + } + } + } WindowEvent::RedrawRequested => { - let mut target = display.draw(); - - ecsr.render_into(&mut target); - - gui.render_with(&mut target, &window, |ui| { + gui.render_world(&mut ecsr, &window, |ui, ecsr| { if let Ok(mut tr) = ecsr.world.query_one_mut::<&mut Transform>(object_ent) { + ui.text("Hold right click to control the camera"); + ui.text("WASD to move"); + // Translation controls let mut translation = [tr.translation.x, tr.translation.y, tr.translation.z]; if ui.input_float3("Translation", &mut translation).build() { @@ -128,49 +134,21 @@ fn main() -> Result<()> { } } }); - target.finish().unwrap(); } _ => {} }, Event::AboutToWait => { time.tick(); - if !attempted_initial_grab { - attempted_initial_grab = true; - if window - .set_cursor_grab(CursorGrabMode::Confined) - .or_else(|_| window.set_cursor_grab(CursorGrabMode::Locked)) - .is_ok() - { - window.set_cursor_visible(false); - cursor_grabbed = true; - } - } - { let dt = time.delta_seconds(); camera_controller.update( &input, dt, - cursor_grabbed, + right_mouse_held, (Action::MoveForward, Action::MoveBackward, Action::MoveLeft, Action::MoveRight), ); - if input.key_pressed(KeyCode::Escape) { - if cursor_grabbed { - let _ = window.set_cursor_grab(CursorGrabMode::None); - window.set_cursor_visible(true); - cursor_grabbed = false; - } else if window - .set_cursor_grab(CursorGrabMode::Confined) - .or_else(|_| window.set_cursor_grab(CursorGrabMode::Locked)) - .is_ok() - { - window.set_cursor_visible(false); - cursor_grabbed = true; - } - } - if let Ok(mut cam) = ecsr.world.query_one_mut::<&mut Camera>(camera_ent) { cam.eye = camera_controller.position; cam.center = camera_controller.position + camera_controller.front(); diff --git a/raidillon_render/Cargo.toml b/raidillon_render/Cargo.toml index 1f5247c..ae6c94a 100644 --- a/raidillon_render/Cargo.toml +++ b/raidillon_render/Cargo.toml @@ -12,3 +12,4 @@ glutin = { version = "0.32.3", default-features = false } hecs = "0.10.5" image = "0.25.6" raidillon_ecs = { path = "../raidillon_ecs" } +winit = "0.30" diff --git a/raidillon_render/src/ecs_renderer.rs b/raidillon_render/src/ecs_renderer.rs index edac676..e21b036 100644 --- a/raidillon_render/src/ecs_renderer.rs +++ b/raidillon_render/src/ecs_renderer.rs @@ -12,6 +12,11 @@ pub struct ECSRenderer { } impl ECSRenderer { + pub fn from_display_handle(handle: &crate::window::DisplayHandle) -> anyhow::Result { + let world = World::new(); + let renderer = crate::render::GliumRenderer::new(handle.as_inner().clone())?; + Ok(Self { renderer, world }) + } pub fn new(renderer: GliumRenderer, world: World) -> Self { Self { renderer, world } } @@ -45,4 +50,13 @@ impl ECSRenderer { pub fn render_into(&mut self, target: &mut S) { self.renderer.render_into(&self.world, target); } + + pub fn load_mesh_from_gltf + std::fmt::Debug>( + &mut self, + path: P, + transform: Transform, + ) -> anyhow::Result { + let model = crate::gltf_loader::load_gltf(path, self.renderer.display())?; + Ok(self.spawn_mesh(model, transform)) + } } diff --git a/raidillon_render/src/lib.rs b/raidillon_render/src/lib.rs index 40e3033..f883c91 100644 --- a/raidillon_render/src/lib.rs +++ b/raidillon_render/src/lib.rs @@ -3,7 +3,9 @@ pub mod model; pub mod gltf_loader; pub mod render; pub mod ecs_renderer; +pub mod window; pub use camera::Camera; pub use render::GliumRenderer; pub use ecs_renderer::ECSRenderer; +pub use window::{DisplayHandle, init_window as init_render_window}; diff --git a/raidillon_render/src/render.rs b/raidillon_render/src/render.rs index 38f4175..1d7554d 100644 --- a/raidillon_render/src/render.rs +++ b/raidillon_render/src/render.rs @@ -160,4 +160,8 @@ impl GliumRenderer { self.draw_scene(world, &mut frame); frame.finish().unwrap(); } + + pub fn display(&self) -> &glium::Display { + &self.display + } } diff --git a/raidillon_render/src/window.rs b/raidillon_render/src/window.rs new file mode 100644 index 0000000..db0897c --- /dev/null +++ b/raidillon_render/src/window.rs @@ -0,0 +1,28 @@ +use glium::backend::glutin::SimpleWindowBuilder; +use glium::glutin::surface::WindowSurface; +use glium::Display; +use anyhow::Result; +use winit::event_loop::EventLoop; +use winit::window::Window; + +#[derive(Clone)] +pub struct DisplayHandle(Display); + +impl DisplayHandle { + pub fn as_inner(&self) -> &Display { + &self.0 + } +} + +pub fn init_window( + event_loop: &EventLoop, + title: &str, + size: (u32, u32), +) -> Result<(Window, DisplayHandle)> { + let (window, display) = SimpleWindowBuilder::new() + .with_title(title) + .with_inner_size(size.0, size.1) + .build(event_loop); + + Ok((window, DisplayHandle(display))) +} diff --git a/raidillon_ui/Cargo.toml b/raidillon_ui/Cargo.toml index d26d063..2f4b606 100644 --- a/raidillon_ui/Cargo.toml +++ b/raidillon_ui/Cargo.toml @@ -10,3 +10,4 @@ imgui = "0.12" imgui-winit-support = "0.13" imgui-glium-renderer = "0.13" winit = "0.30" +raidillon_render = { path = "../raidillon_render" } diff --git a/raidillon_ui/src/ui.rs b/raidillon_ui/src/ui.rs index 8ac7b0d..224ee1a 100644 --- a/raidillon_ui/src/ui.rs +++ b/raidillon_ui/src/ui.rs @@ -5,8 +5,8 @@ use imgui::{Context as ImguiContext, Ui}; use imgui_winit_support::{HiDpiMode, WinitPlatform}; use imgui_glium_renderer::Renderer as ImguiGliumRenderer; use winit::window::Window; -use glium::{Frame}; -use glium::glutin::surface::WindowSurface; +use glium::Frame; +use raidillon_render::{DisplayHandle, ECSRenderer}; /// Convenience wrapper that owns all ImGui state required for integration with /// winit + glium. @@ -18,13 +18,13 @@ pub struct Gui { } impl Gui { - pub fn new(display: &glium::Display, window: &Window) -> Result { + pub fn new(display: &DisplayHandle, window: &Window) -> Result { let mut imgui = ImguiContext::create(); imgui.set_ini_filename(None); let mut platform = WinitPlatform::new(&mut imgui); platform.attach_window(imgui.io_mut(), window, HiDpiMode::Default); imgui.fonts().add_font(&[imgui::FontSource::DefaultFontData { config: None }]); - let renderer = ImguiGliumRenderer::new(&mut imgui, display)?; + let renderer = ImguiGliumRenderer::new(&mut imgui, display.as_inner())?; Ok(Self { imgui, @@ -74,6 +74,21 @@ impl Gui { .expect("imgui rendering failed"); } + pub fn render_world(&mut self, ecsr: &mut ECSRenderer, window: &Window, build_ui: F) + where + F: FnOnce(&Ui, &mut ECSRenderer), + { + let mut target = ecsr.renderer.display().draw(); + + ecsr.render_into(&mut target); + + self.render_with(&mut target, window, |ui| { + build_ui(ui, ecsr); + }); + + target.finish().expect("Failed to swap buffers"); + } + pub fn ui(&mut self, build: F) where F: FnOnce(&Ui), From 341d531db3ddb52cbe9442d74c6e2049cf79d19a Mon Sep 17 00:00:00 2001 From: reo Date: Mon, 21 Jul 2025 22:56:17 +0300 Subject: [PATCH 24/89] Refactor rendering process in main.rs and remove obsolete render_world function from Gui --- raidillon_game/src/main.rs | 9 ++++++++- raidillon_ui/src/ui.rs | 17 +---------------- 2 files changed, 9 insertions(+), 17 deletions(-) diff --git a/raidillon_game/src/main.rs b/raidillon_game/src/main.rs index 825f1c2..2373c5d 100644 --- a/raidillon_game/src/main.rs +++ b/raidillon_game/src/main.rs @@ -106,7 +106,12 @@ fn main() -> Result<()> { } } WindowEvent::RedrawRequested => { - gui.render_world(&mut ecsr, &window, |ui, ecsr| { + // First render the 3D world + let mut target = ecsr.renderer.display().draw(); + ecsr.render_into(&mut target); + + // Then overlay ImGui on top + gui.render_with(&mut target, &window, |ui| { if let Ok(mut tr) = ecsr.world.query_one_mut::<&mut Transform>(object_ent) { ui.text("Hold right click to control the camera"); ui.text("WASD to move"); @@ -134,6 +139,8 @@ fn main() -> Result<()> { } } }); + + target.finish().expect("Failed to swap buffers"); } _ => {} }, diff --git a/raidillon_ui/src/ui.rs b/raidillon_ui/src/ui.rs index 224ee1a..abf347d 100644 --- a/raidillon_ui/src/ui.rs +++ b/raidillon_ui/src/ui.rs @@ -6,7 +6,7 @@ use imgui_winit_support::{HiDpiMode, WinitPlatform}; use imgui_glium_renderer::Renderer as ImguiGliumRenderer; use winit::window::Window; use glium::Frame; -use raidillon_render::{DisplayHandle, ECSRenderer}; +use raidillon_render::DisplayHandle; /// Convenience wrapper that owns all ImGui state required for integration with /// winit + glium. @@ -74,21 +74,6 @@ impl Gui { .expect("imgui rendering failed"); } - pub fn render_world(&mut self, ecsr: &mut ECSRenderer, window: &Window, build_ui: F) - where - F: FnOnce(&Ui, &mut ECSRenderer), - { - let mut target = ecsr.renderer.display().draw(); - - ecsr.render_into(&mut target); - - self.render_with(&mut target, window, |ui| { - build_ui(ui, ecsr); - }); - - target.finish().expect("Failed to swap buffers"); - } - pub fn ui(&mut self, build: F) where F: FnOnce(&Ui), From 88a21040cd757d755d8b5fac90d76b7c4a345975 Mon Sep 17 00:00:00 2001 From: reo Date: Mon, 21 Jul 2025 23:52:32 +0300 Subject: [PATCH 25/89] Giant refactor for a better event-driven architecture --- Cargo.lock | 10 ++ raidillon_core/Cargo.toml | 5 + raidillon_core/src/assets.rs | 95 ++++++++++++++++ raidillon_core/src/engine.rs | 80 ++++++++++++++ raidillon_core/src/events.rs | 60 ++++++++++ raidillon_core/src/lib.rs | 8 ++ raidillon_core/src/systems.rs | 45 ++++++++ raidillon_ecs/src/lib.rs | 2 +- raidillon_game/Cargo.toml | 1 + raidillon_game/src/game_state.rs | 88 +++++++++++++++ raidillon_game/src/lib.rs | 4 + raidillon_game/src/main.rs | 153 +++++++++++++++----------- raidillon_game/src/main_clean.rs | 116 +++++++++++++++++++ raidillon_input/Cargo.toml | 5 +- raidillon_input/src/camera_system.rs | 109 ++++++++++++++++++ raidillon_input/src/input_system.rs | 64 +++++++++++ raidillon_input/src/lib.rs | 5 + raidillon_render/Cargo.toml | 1 + raidillon_render/src/lib.rs | 3 + raidillon_render/src/model.rs | 6 + raidillon_render/src/render.rs | 93 +++++++++++++++- raidillon_render/src/render_system.rs | 50 +++++++++ 22 files changed, 936 insertions(+), 67 deletions(-) create mode 100644 raidillon_core/src/assets.rs create mode 100644 raidillon_core/src/engine.rs create mode 100644 raidillon_core/src/events.rs create mode 100644 raidillon_core/src/systems.rs create mode 100644 raidillon_game/src/game_state.rs create mode 100644 raidillon_game/src/lib.rs create mode 100644 raidillon_game/src/main_clean.rs create mode 100644 raidillon_input/src/camera_system.rs create mode 100644 raidillon_input/src/input_system.rs create mode 100644 raidillon_render/src/render_system.rs diff --git a/Cargo.lock b/Cargo.lock index 0a091ac..b5f6919 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1728,6 +1728,11 @@ checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" [[package]] name = "raidillon_core" version = "0.1.0" +dependencies = [ + "anyhow", + "glam", + "hecs", +] [[package]] name = "raidillon_ecs" @@ -1743,6 +1748,7 @@ version = "0.1.0" dependencies = [ "anyhow", "glam", + "glium", "hecs", "raidillon_core", "raidillon_ecs", @@ -1757,6 +1763,9 @@ name = "raidillon_input" version = "0.1.0" dependencies = [ "glam", + "hecs", + "raidillon_core", + "raidillon_render", "winit", ] @@ -1771,6 +1780,7 @@ dependencies = [ "glutin", "hecs", "image", + "raidillon_core", "raidillon_ecs", "winit", ] diff --git a/raidillon_core/Cargo.toml b/raidillon_core/Cargo.toml index 1d15e30..27b9c1e 100644 --- a/raidillon_core/Cargo.toml +++ b/raidillon_core/Cargo.toml @@ -2,3 +2,8 @@ name = "raidillon_core" version = "0.1.0" edition = "2021" + +[dependencies] +anyhow = "1.0.98" +glam = "0.30.4" +hecs = "0.10.5" diff --git a/raidillon_core/src/assets.rs b/raidillon_core/src/assets.rs new file mode 100644 index 0000000..04dd337 --- /dev/null +++ b/raidillon_core/src/assets.rs @@ -0,0 +1,95 @@ +use std::collections::HashMap; + +// Forward declarations - these will be from other crates +pub trait Model {} +pub trait Material {} + +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] +pub struct ModelId(pub usize); + +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] +pub struct MaterialId(pub usize); + +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] +pub struct TextureHandle(pub usize); + +pub struct AssetManager { + models: Vec>, + materials: Vec>, + textures: HashMap, + model_cache: HashMap, + next_texture_id: usize, +} + +impl AssetManager { + pub fn new() -> Self { + Self { + models: Vec::new(), + materials: Vec::new(), + textures: HashMap::new(), + model_cache: HashMap::new(), + next_texture_id: 0, + } + } + + pub fn add_model(&mut self, model: Box) -> ModelId { + let id = ModelId(self.models.len()); + self.models.push(model); + id + } + + pub fn cache_model(&mut self, path: String, model: Box) -> ModelId { + if let Some(&cached_id) = self.model_cache.get(&path) { + return cached_id; + } + + let model_id = self.add_model(model); + self.model_cache.insert(path, model_id); + model_id + } + + pub fn get_model(&self, id: ModelId) -> Option<&M> { + self.models.get(id.0).map(|boxed| boxed.as_ref()) + } + + pub fn get_model_mut(&mut self, id: ModelId) -> Option<&mut M> { + self.models.get_mut(id.0).map(|boxed| boxed.as_mut()) + } + + pub fn add_material(&mut self, material: Box) -> MaterialId { + let id = MaterialId(self.materials.len()); + self.materials.push(material); + id + } + + pub fn get_material(&self, id: MaterialId) -> Option<&Mat> { + self.materials.get(id.0).map(|boxed| boxed.as_ref()) + } + + pub fn add_texture(&mut self, name: String) -> TextureHandle { + if let Some(&handle) = self.textures.get(&name) { + return handle; + } + + let handle = TextureHandle(self.next_texture_id); + self.next_texture_id += 1; + self.textures.insert(name, handle); + handle + } + + pub fn get_texture_handle(&self, name: &str) -> Option { + self.textures.get(name).copied() + } + + pub fn model_count(&self) -> usize { + self.models.len() + } + + pub fn material_count(&self) -> usize { + self.materials.len() + } + + pub fn clear_cache(&mut self) { + self.model_cache.clear(); + } +} \ No newline at end of file diff --git a/raidillon_core/src/engine.rs b/raidillon_core/src/engine.rs new file mode 100644 index 0000000..13b82ba --- /dev/null +++ b/raidillon_core/src/engine.rs @@ -0,0 +1,80 @@ +use hecs::World; +use crate::{ + Time, EventBus, GameEvent, SystemRegistry, + AssetManager, Model, Material, ModelId +}; + +pub struct Engine { + pub world: World, + pub systems: SystemRegistry, + pub assets: AssetManager, + pub events: EventBus, + pub time: Time, +} + +impl Engine { + pub fn new() -> Self { + let systems = SystemRegistry::new(); + + Self { + world: World::new(), + systems, + assets: AssetManager::new(), + events: EventBus::new(), + time: Time::new(), + } + } + + pub fn add_system(&mut self, system: S) { + self.systems.add_system(system); + } + + pub fn update(&mut self) { + self.time.tick(); + let dt = self.time.delta_seconds(); + + // Update all systems + self.systems.update_all(&mut self.world, &self.assets, &mut self.events, dt); + + // Process events + self.events.process(); + } + + pub fn handle_window_event(&mut self, event: &GameEvent) { + self.events.emit(event.clone()); + self.systems.handle_event_for_all(event, &mut self.world); + } + + pub fn load_model(&mut self, path: &str) -> anyhow::Result { + // This is a placeholder - in a real implementation, we'd need to + // coordinate with the render system to actually load the model + // For now, just return a dummy ID + Ok(ModelId(0)) + } + + pub fn spawn_entity_with_model(&mut self, model_id: ModelId) -> hecs::Entity { + // This would need proper Transform and ModelHandle types + // For now, return a placeholder entity + self.world.spawn(()) + } + + pub fn delta_time(&self) -> f32 { + self.time.delta_seconds() + } + + pub fn emit_event(&mut self, event: GameEvent) { + self.events.emit(event); + } + + pub fn world(&self) -> &World { + &self.world + } + + pub fn world_mut(&mut self) -> &mut World { + &mut self.world + } + + pub fn system_count(&self) -> usize { + self.systems.system_count() + } +} \ No newline at end of file diff --git a/raidillon_core/src/events.rs b/raidillon_core/src/events.rs new file mode 100644 index 0000000..3a7dc1e --- /dev/null +++ b/raidillon_core/src/events.rs @@ -0,0 +1,60 @@ +use glam::Vec3; +use hecs::Entity; + +#[derive(Debug, Clone)] +pub enum GameEvent { + InputAction(InputAction), + CameraMove { position: Vec3, front: Vec3 }, + WindowResize { width: u32, height: u32 }, + EntitySpawned(Entity), +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub enum InputAction { + MoveForward, + MoveBackward, + MoveLeft, + MoveRight, +} + +pub trait EventHandler { + fn handle(&mut self, event: &GameEvent); +} + +pub struct EventBus { + events: Vec, + handlers: Vec>, +} + +impl EventBus { + pub fn new() -> Self { + Self { + events: Vec::new(), + handlers: Vec::new(), + } + } + + pub fn emit(&mut self, event: GameEvent) { + self.events.push(event); + } + + pub fn subscribe(&mut self, handler: H) { + self.handlers.push(Box::new(handler)); + } + + pub fn process(&mut self) { + for event in self.events.drain(..) { + for handler in &mut self.handlers { + handler.handle(&event); + } + } + } + + pub fn has_events(&self) -> bool { + !self.events.is_empty() + } + + pub fn events(&self) -> &[GameEvent] { + &self.events + } +} \ No newline at end of file diff --git a/raidillon_core/src/lib.rs b/raidillon_core/src/lib.rs index 230f8bb..d646dcb 100644 --- a/raidillon_core/src/lib.rs +++ b/raidillon_core/src/lib.rs @@ -1,3 +1,11 @@ pub mod time; +pub mod events; +pub mod assets; +pub mod systems; +pub mod engine; pub use time::Time; +pub use events::{GameEvent, InputAction, EventHandler, EventBus}; +pub use assets::{AssetManager, ModelId, MaterialId, TextureHandle, Model, Material}; +pub use systems::{System, SystemRegistry}; +pub use engine::Engine; diff --git a/raidillon_core/src/systems.rs b/raidillon_core/src/systems.rs new file mode 100644 index 0000000..3ccd41e --- /dev/null +++ b/raidillon_core/src/systems.rs @@ -0,0 +1,45 @@ +use hecs::World; +use crate::assets::{AssetManager, Model, Material}; +use crate::events::{EventBus, GameEvent}; + +pub trait System { + fn update(&mut self, world: &mut World, resources: &AssetManager, events: &mut EventBus, dt: f32); + fn handle_event(&mut self, event: &GameEvent, world: &mut World); + fn name(&self) -> &'static str; +} + +pub struct SystemRegistry { + systems: Vec>, +} + +impl SystemRegistry { + pub fn new() -> Self { + Self { + systems: Vec::new(), + } + } + + pub fn add_system(&mut self, system: S) { + self.systems.push(Box::new(system)); + } + + pub fn update_all(&mut self, world: &mut World, resources: &AssetManager, events: &mut EventBus, dt: f32) { + for system in &mut self.systems { + system.update(world, resources, events, dt); + } + } + + pub fn handle_event_for_all(&mut self, event: &GameEvent, world: &mut World) { + for system in &mut self.systems { + system.handle_event(event, world); + } + } + + pub fn system_count(&self) -> usize { + self.systems.len() + } + + pub fn clear(&mut self) { + self.systems.clear(); + } +} \ No newline at end of file diff --git a/raidillon_ecs/src/lib.rs b/raidillon_ecs/src/lib.rs index 19a3e69..0a15576 100644 --- a/raidillon_ecs/src/lib.rs +++ b/raidillon_ecs/src/lib.rs @@ -13,5 +13,5 @@ impl Transform { } } -#[derive(Clone)] +#[derive(Copy, Clone, Debug)] pub struct ModelHandle(pub usize); diff --git a/raidillon_game/Cargo.toml b/raidillon_game/Cargo.toml index c127172..08fe8cb 100644 --- a/raidillon_game/Cargo.toml +++ b/raidillon_game/Cargo.toml @@ -7,6 +7,7 @@ edition = "2021" anyhow = "1.0.98" glam = "0.30.4" winit = "0.30" +glium = { version = "0.35.0", features = ["glutin_backend", "simple_window_builder"] } raidillon_render = { path = "../raidillon_render" } raidillon_ecs = { path = "../raidillon_ecs" } raidillon_ui = { path = "../raidillon_ui" } diff --git a/raidillon_game/src/game_state.rs b/raidillon_game/src/game_state.rs new file mode 100644 index 0000000..c57117b --- /dev/null +++ b/raidillon_game/src/game_state.rs @@ -0,0 +1,88 @@ +use anyhow; +use glam::{Quat, Vec3}; +use hecs::{Entity, World}; +use raidillon_ecs::{Transform, ModelHandle}; +use raidillon_render::{Camera, ModelId}; +use raidillon_core::InputAction; + +pub struct GameState { + pub world: World, + pub camera_entity: Entity, + pub object_entity: Entity, + pub ground_entity: Entity, +} + +impl GameState { + pub fn new() -> Self { + let mut world = World::new(); + + // Create camera entity + let camera_entity = world.spawn((Camera { + eye: Vec3::new(0.0, 0.0, 2.0), + center: Vec3::ZERO, + up: Vec3::Y, + fovy: 60_f32.to_radians(), + aspect: 1280.0 / 720.0, // default aspect ratio + znear: 0.1, + zfar: 100.0, + },)); + + // Create placeholder entities for object and ground (will be properly loaded later) + let object_entity = world.spawn(( + Transform { + translation: Vec3::new(0.0, -2.5, -5.0), + rotation: Quat::IDENTITY, + scale: Vec3::new(0.01, 0.01, 0.01), + }, + ModelHandle(0), + )); + + let ground_entity = world.spawn(( + Transform { + translation: Vec3::new(0.0, -1.5, 0.0), + rotation: Quat::IDENTITY, + scale: Vec3::new(1.0, 1.0, 1.0), + }, + ModelHandle(1), + )); + + Self { + world, + camera_entity, + object_entity, + ground_entity, + } + } + + pub fn update(&mut self, _dt: f32) { + // Game state update logic will go here + // Camera updates are now handled by CameraSystem + } + + pub fn resize_camera(&mut self, width: u32, height: u32) { + if let Ok(cam) = self.world.query_one_mut::<&mut Camera>(self.camera_entity) { + cam.aspect = width as f32 / height as f32; + } + } + + pub fn world(&self) -> &World { + &self.world + } + + pub fn world_mut(&mut self) -> &mut World { + &mut self.world + } + + pub fn spawn_model(&mut self, model_id: ModelId, transform: Transform) -> Entity { + self.world.spawn((transform, ModelHandle(model_id.0))) + } + + pub fn update_entity_model(&mut self, entity: Entity, model_id: ModelId) -> anyhow::Result<()> { + if let Ok(model_handle) = self.world.query_one_mut::<&mut ModelHandle>(entity) { + model_handle.0 = model_id.0; + Ok(()) + } else { + Err(anyhow::anyhow!("Entity does not have a ModelHandle component")) + } + } +} \ No newline at end of file diff --git a/raidillon_game/src/lib.rs b/raidillon_game/src/lib.rs new file mode 100644 index 0000000..e40c650 --- /dev/null +++ b/raidillon_game/src/lib.rs @@ -0,0 +1,4 @@ +pub mod game_state; + +pub use game_state::GameState; +pub use raidillon_core::InputAction; \ No newline at end of file diff --git a/raidillon_game/src/main.rs b/raidillon_game/src/main.rs index 2373c5d..9843297 100644 --- a/raidillon_game/src/main.rs +++ b/raidillon_game/src/main.rs @@ -1,20 +1,52 @@ use anyhow::Result; use glam::{Quat, Vec3, EulerRot}; -use raidillon_core::Time; +use raidillon_core::{Time, EventBus, GameEvent, InputAction, System, SystemRegistry, AssetManager, Model, Material}; use raidillon_ecs::Transform; -use raidillon_render::{Camera, ECSRenderer, init_render_window, DisplayHandle}; +use raidillon_render::{RenderSystem, init_render_window, DisplayHandle}; use raidillon_ui::Gui; -use raidillon_input::{Input, FPSCameraController}; -use winit::keyboard::KeyCode; +use raidillon_input::{InputSystem, CameraSystem}; +use raidillon_game::GameState; use winit::window::CursorGrabMode; use winit::event::MouseButton; +use hecs::World; -#[derive(Copy, Clone, Eq, PartialEq, Hash)] -enum Action { - MoveForward, - MoveBackward, - MoveLeft, - MoveRight, +// Wrapper to make RenderSystem implement the System trait +struct RenderSystemWrapper { + render_system: RenderSystem, +} + +impl RenderSystemWrapper { + fn new(display: DisplayHandle) -> anyhow::Result { + Ok(Self { + render_system: RenderSystem::new(display)?, + }) + } + + fn load_model(&mut self, path: &str) -> anyhow::Result { + self.render_system.load_model(path) + } + + fn render(&mut self, world: &World, target: &mut impl glium::Surface) { + self.render_system.render(world, target) + } + + fn display(&self) -> &glium::Display { + self.render_system.display() + } +} + +impl System for RenderSystemWrapper { + fn update(&mut self, _world: &mut World, _resources: &AssetManager, _events: &mut EventBus, _dt: f32) { + // Rendering is handled separately in the main loop + } + + fn handle_event(&mut self, _event: &GameEvent, _world: &mut World) { + // RenderSystem doesn't need to respond to events currently + } + + fn name(&self) -> &'static str { + "RenderSystem" + } } fn main() -> Result<()> { @@ -24,65 +56,50 @@ fn main() -> Result<()> { let (window, _display): (winit::window::Window, DisplayHandle) = init_render_window(&event_loop, "raidillon", (1280, 720))?; - // Create ECS renderer which internally owns both the world and the renderer - let mut ecsr = ECSRenderer::from_display_handle(&_display)?; + // Create game state and systems + let mut game_state = GameState::new(); + let mut render_system_wrapper = RenderSystemWrapper::new(_display.clone())?; // Dear ImGui integration let mut gui = Gui::new(&_display, &window)?; - let mut input = Input::::new(); - input.map_key(KeyCode::KeyW, Action::MoveForward); - input.map_key(KeyCode::KeyS, Action::MoveBackward); - input.map_key(KeyCode::KeyA, Action::MoveLeft); - input.map_key(KeyCode::KeyD, Action::MoveRight); + // Create system registry and register systems + let mut system_registry = SystemRegistry::new(); + let mut event_bus = EventBus::new(); + let mut input_system = InputSystem::new(); // Keep this for direct access + let mut camera_system = CameraSystem::new(game_state.camera_entity); // Keep this for direct access - let mut camera_controller = FPSCameraController::new(Vec3::new(0.0, 0.0, 2.0)); + // Register systems later when we have proper asset manager integration + // For now, manage systems directly in main loop let mut right_mouse_held = false; - let mut time = Time::new(); - let object_ent = ecsr.load_mesh_from_gltf("resources/models/tree.gltf", Transform { - translation: Vec3::new(0.0, -2.5, -5.0), - rotation: Quat::IDENTITY, - scale: Vec3::new(0.01, 0.01, 0.01), - })?; + // Load models using the RenderSystem + let object_model_id = render_system_wrapper.load_model("resources/models/tree.gltf")?; + let ground_model_id = render_system_wrapper.load_model("resources/models/plane.gltf")?; - let ground_ent = ecsr.load_mesh_from_gltf("resources/models/plane.gltf", Transform { - translation: Vec3::new(0.0, -1.5, 0.0), - rotation: Quat::IDENTITY, - scale: Vec3::new(1.0, 1.0, 1.0), - })?; + // Update the model handles in game state using the new method + game_state.update_entity_model(game_state.object_entity, object_model_id)?; + game_state.update_entity_model(game_state.ground_entity, ground_model_id)?; - - let camera_ent = { - let (w, h): (u32, u32) = window.inner_size().into(); - ecsr.world.spawn((Camera { - eye: Vec3::new(0.0, 0.0, 2.0), - center: Vec3::ZERO, - up: Vec3::Y, - fovy: 60_f32.to_radians(), - aspect: w as f32 / h as f32, - znear: 0.1, - zfar: 100.0, - },)) - }; + // Set initial camera aspect ratio + let (w, h): (u32, u32) = window.inner_size().into(); + game_state.resize_camera(w, h); event_loop .run(move |event, el| { use winit::event::{Event, WindowEvent}; gui.handle_event(&window, &event); - - input.handle_event(&event); + input_system.handle_event(&event); match event { Event::WindowEvent { event, .. } => match event { WindowEvent::CloseRequested => el.exit(), WindowEvent::Resized(sz) => { - ecsr.world.query_one_mut::<&mut Camera>(camera_ent).map(|mut cam| { - cam.aspect = sz.width as f32 / sz.height as f32; - }); + camera_system.resize_camera(game_state.world_mut(), sz.width, sz.height); + event_bus.emit(GameEvent::WindowResize { width: sz.width, height: sz.height }); } WindowEvent::MouseInput { state, button, .. } => { if button == MouseButton::Right { @@ -107,12 +124,13 @@ fn main() -> Result<()> { } WindowEvent::RedrawRequested => { // First render the 3D world - let mut target = ecsr.renderer.display().draw(); - ecsr.render_into(&mut target); + let mut target = render_system_wrapper.display().draw(); + render_system_wrapper.render(game_state.world(), &mut target); // Then overlay ImGui on top gui.render_with(&mut target, &window, |ui| { - if let Ok(mut tr) = ecsr.world.query_one_mut::<&mut Transform>(object_ent) { + let object_entity = game_state.object_entity; + if let Ok(tr) = game_state.world_mut().query_one_mut::<&mut Transform>(object_entity) { ui.text("Hold right click to control the camera"); ui.text("WASD to move"); @@ -146,24 +164,31 @@ fn main() -> Result<()> { }, Event::AboutToWait => { time.tick(); - - { - let dt = time.delta_seconds(); - camera_controller.update( - &input, - dt, - right_mouse_held, - (Action::MoveForward, Action::MoveBackward, Action::MoveLeft, Action::MoveRight), - ); - - if let Ok(mut cam) = ecsr.world.query_one_mut::<&mut Camera>(camera_ent) { - cam.eye = camera_controller.position; - cam.center = camera_controller.position + camera_controller.front(); + let dt = time.delta_seconds(); + + // Update input system and generate events + input_system.update(&mut event_bus, right_mouse_held); + + // Process input events for camera movement + let mouse_delta = input_system.mouse_delta(); + + // Handle camera input actions + for event in event_bus.events() { + if let GameEvent::InputAction(action) = event { + camera_system.handle_input_action(*action, dt); } } + + // Update camera with mouse movement + camera_system.update(game_state.world_mut(), dt, mouse_delta); + + // Update game state + game_state.update(dt); - input.end_frame(); + // Process all events + event_bus.process(); + input_system.end_frame(); gui.prepare_frame(&window); window.request_redraw(); } diff --git a/raidillon_game/src/main_clean.rs b/raidillon_game/src/main_clean.rs new file mode 100644 index 0000000..c3a8c34 --- /dev/null +++ b/raidillon_game/src/main_clean.rs @@ -0,0 +1,116 @@ +use anyhow::Result; +use raidillon_core::{Engine, GameEvent}; +use raidillon_render::{init_render_window, RenderSystem}; +use raidillon_ui::Gui; +use raidillon_input::{InputSystem, CameraSystem}; +use winit::event::{Event, WindowEvent}; +use winit::window::CursorGrabMode; +use winit::event::MouseButton; + +fn main() -> Result<()> { + let event_loop = winit::event_loop::EventLoop::builder() + .build() + .expect("create event-loop"); + + let (window, _display) = init_render_window(&event_loop, "raidillon", (1280, 720))?; + + // Create the unified engine + let mut engine = Engine::new(); + + // Create render system separately (for now, until full integration) + let mut render_system = RenderSystem::new(_display.clone())?; + + // Create GUI system + let mut gui = Gui::new(&_display, &window)?; + + // Add systems to the engine + let input_system = InputSystem::new(); + let camera_system = CameraSystem::new(engine.world().spawn(())); // placeholder camera entity + + engine.add_system(input_system); + engine.add_system(camera_system); + + // Load initial scene content + load_default_scene(&mut engine, &mut render_system)?; + + let mut right_mouse_held = false; + + event_loop + .run(move |event, el| { + gui.handle_event(&window, &event); + + match event { + Event::WindowEvent { event, .. } => match event { + WindowEvent::CloseRequested => el.exit(), + WindowEvent::Resized(sz) => { + engine.handle_window_event(&GameEvent::WindowResize { + width: sz.width, + height: sz.height + }); + } + WindowEvent::MouseInput { state, button, .. } => { + if button == MouseButton::Right { + match state { + winit::event::ElementState::Pressed => { + if window + .set_cursor_grab(CursorGrabMode::Confined) + .or_else(|_| window.set_cursor_grab(CursorGrabMode::Locked)) + .is_ok() + { + window.set_cursor_visible(false); + right_mouse_held = true; + } + } + winit::event::ElementState::Released => { + let _ = window.set_cursor_grab(CursorGrabMode::None); + window.set_cursor_visible(true); + right_mouse_held = false; + } + } + } + } + WindowEvent::RedrawRequested => { + // Update engine + engine.update(); + + // Render + let mut target = render_system.display().draw(); + render_system.render(engine.world(), &mut target); + + // Render debug UI + gui.render_with(&mut target, &window, |ui| { + render_debug_ui(&engine, ui); + }); + + target.finish().expect("Failed to swap buffers"); + } + _ => {} + }, + Event::AboutToWait => { + gui.prepare_frame(&window); + window.request_redraw(); + } + _ => {} + } + }) + .map_err(Into::into) +} + +fn load_default_scene(engine: &mut Engine, render_system: &mut RenderSystem) -> Result<()> { + // Load and setup default scene + let _tree_model = render_system.load_model("resources/models/tree.gltf")?; + let _ground_model = render_system.load_model("resources/models/plane.gltf")?; + + // Note: Full integration would require coordinating between engine and render system + // For now, this demonstrates the clean architecture structure + + println!("Loaded default scene with {} systems", engine.system_count()); + Ok(()) +} + +fn render_debug_ui(engine: &Engine, ui: &imgui::Ui) { + ui.text(format!("Engine Systems: {}", engine.system_count())); + ui.text(format!("Delta Time: {:.3}ms", engine.delta_time() * 1000.0)); + ui.text("Clean Architecture Demo"); + ui.text("This shows the unified Engine approach"); +} \ No newline at end of file diff --git a/raidillon_input/Cargo.toml b/raidillon_input/Cargo.toml index 1f1700d..abcbe66 100644 --- a/raidillon_input/Cargo.toml +++ b/raidillon_input/Cargo.toml @@ -5,4 +5,7 @@ edition = "2021" [dependencies] winit = "0.30" -glam = "0.30.4" \ No newline at end of file +glam = "0.30.4" +hecs = "0.10.5" +raidillon_core = { path = "../raidillon_core" } +raidillon_render = { path = "../raidillon_render" } \ No newline at end of file diff --git a/raidillon_input/src/camera_system.rs b/raidillon_input/src/camera_system.rs new file mode 100644 index 0000000..7925d47 --- /dev/null +++ b/raidillon_input/src/camera_system.rs @@ -0,0 +1,109 @@ +use hecs::{Entity, World}; +use raidillon_core::{EventHandler, GameEvent, InputAction, System, AssetManager, Model, Material, EventBus}; +use raidillon_render::Camera; +use crate::FPSCameraController; +use glam::Vec3; + +pub struct CameraSystem { + controller: FPSCameraController, + camera_entity: Entity, + yaw: f32, + pitch: f32, +} + +impl CameraSystem { + pub fn new(camera_entity: Entity) -> Self { + Self { + controller: FPSCameraController::new(Vec3::new(0.0, 0.0, 2.0)), + camera_entity, + yaw: -90.0, + pitch: 0.0, + } + } + + pub fn update(&mut self, world: &mut World, dt: f32, mouse_delta: (f64, f64)) { + // Apply mouse movement if there's any + if mouse_delta.0 != 0.0 || mouse_delta.1 != 0.0 { + self.yaw += mouse_delta.0 as f32 * self.controller.sensitivity; + self.pitch -= mouse_delta.1 as f32 * self.controller.sensitivity; + self.pitch = self.pitch.clamp(-89.0, 89.0); + + // Update front vector based on new yaw/pitch + let yaw_rad = self.yaw.to_radians(); + let pitch_rad = self.pitch.to_radians(); + let front = Vec3::new( + yaw_rad.cos() * pitch_rad.cos(), + pitch_rad.sin(), + yaw_rad.sin() * pitch_rad.cos(), + ).normalize(); + } + + // Update camera component in the world + if let Ok(cam) = world.query_one_mut::<&mut Camera>(self.camera_entity) { + cam.eye = self.controller.position; + cam.center = self.controller.position + self.controller.front(); + } + } + + pub fn handle_input_action(&mut self, action: InputAction, dt: f32) { + let front = self.controller.front(); + let right = front.cross(Vec3::Y).normalize(); + let frame_speed = self.controller.speed * dt; + + match action { + InputAction::MoveForward => { + self.controller.position += front * frame_speed; + } + InputAction::MoveBackward => { + self.controller.position -= front * frame_speed; + } + InputAction::MoveLeft => { + self.controller.position -= right * frame_speed; + } + InputAction::MoveRight => { + self.controller.position += right * frame_speed; + } + } + } + + pub fn resize_camera(&mut self, world: &mut World, width: u32, height: u32) { + if let Ok(cam) = world.query_one_mut::<&mut Camera>(self.camera_entity) { + cam.aspect = width as f32 / height as f32; + } + } +} + +impl EventHandler for CameraSystem { + fn handle(&mut self, event: &GameEvent) { + match event { + GameEvent::InputAction(_action) => { + // Movement will be handled separately with delta time + // This is just for event registration + } + GameEvent::WindowResize { width: _, height: _ } => { + // Window resize will be handled separately with world access + } + _ => {} + } + } +} + +impl System for CameraSystem { + fn update(&mut self, world: &mut World, _resources: &AssetManager, _events: &mut EventBus, _dt: f32) { + // Camera update logic is handled separately with mouse input + // This system mainly responds to events + } + + fn handle_event(&mut self, event: &GameEvent, world: &mut World) { + match event { + GameEvent::WindowResize { width, height } => { + self.resize_camera(world, *width, *height); + } + _ => {} + } + } + + fn name(&self) -> &'static str { + "CameraSystem" + } +} \ No newline at end of file diff --git a/raidillon_input/src/input_system.rs b/raidillon_input/src/input_system.rs new file mode 100644 index 0000000..4283b7e --- /dev/null +++ b/raidillon_input/src/input_system.rs @@ -0,0 +1,64 @@ +use raidillon_core::{EventBus, GameEvent, InputAction, System, AssetManager, Model, Material}; +use crate::Input; +use hecs::World; + +pub struct InputSystem { + input: Input, +} + +impl InputSystem { + pub fn new() -> Self { + let mut input = Input::::new(); + input.map_key(winit::keyboard::KeyCode::KeyW, InputAction::MoveForward); + input.map_key(winit::keyboard::KeyCode::KeyS, InputAction::MoveBackward); + input.map_key(winit::keyboard::KeyCode::KeyA, InputAction::MoveLeft); + input.map_key(winit::keyboard::KeyCode::KeyD, InputAction::MoveRight); + + Self { input } + } + + pub fn handle_event(&mut self, event: &winit::event::Event) { + self.input.handle_event(event); + } + + pub fn update(&mut self, event_bus: &mut EventBus, right_mouse_held: bool) { + if right_mouse_held { + if self.input.action_held(InputAction::MoveForward) { + event_bus.emit(GameEvent::InputAction(InputAction::MoveForward)); + } + if self.input.action_held(InputAction::MoveBackward) { + event_bus.emit(GameEvent::InputAction(InputAction::MoveBackward)); + } + if self.input.action_held(InputAction::MoveLeft) { + event_bus.emit(GameEvent::InputAction(InputAction::MoveLeft)); + } + if self.input.action_held(InputAction::MoveRight) { + event_bus.emit(GameEvent::InputAction(InputAction::MoveRight)); + } + } + } + + pub fn end_frame(&mut self) { + self.input.end_frame(); + } + + pub fn mouse_delta(&self) -> (f64, f64) { + self.input.mouse_delta() + } +} + +impl System for InputSystem { + fn update(&mut self, _world: &mut World, _resources: &AssetManager, _events: &mut EventBus, _dt: f32) { + // Input processing is handled separately in the main loop + // This system mainly generates events based on input state + } + + fn handle_event(&mut self, _event: &GameEvent, _world: &mut World) { + // InputSystem doesn't need to respond to events + // It generates events based on input state + } + + fn name(&self) -> &'static str { + "InputSystem" + } +} \ No newline at end of file diff --git a/raidillon_input/src/lib.rs b/raidillon_input/src/lib.rs index 25f5a95..30908cb 100644 --- a/raidillon_input/src/lib.rs +++ b/raidillon_input/src/lib.rs @@ -5,7 +5,12 @@ use winit::event::{DeviceEvent, ElementState, Event, WindowEvent}; use winit::keyboard::{KeyCode, PhysicalKey}; pub mod camera; +pub mod input_system; +pub mod camera_system; + pub use camera::FPSCameraController; +pub use input_system::InputSystem; +pub use camera_system::CameraSystem; pub struct Input { pressed_keys: HashSet, diff --git a/raidillon_render/Cargo.toml b/raidillon_render/Cargo.toml index ae6c94a..18a7279 100644 --- a/raidillon_render/Cargo.toml +++ b/raidillon_render/Cargo.toml @@ -11,5 +11,6 @@ gltf = { version = "1.4.1", features = ["import", "utils", "KHR_texture_transf glutin = { version = "0.32.3", default-features = false } hecs = "0.10.5" image = "0.25.6" +raidillon_core = { path = "../raidillon_core" } raidillon_ecs = { path = "../raidillon_ecs" } winit = "0.30" diff --git a/raidillon_render/src/lib.rs b/raidillon_render/src/lib.rs index f883c91..8a5b192 100644 --- a/raidillon_render/src/lib.rs +++ b/raidillon_render/src/lib.rs @@ -3,9 +3,12 @@ pub mod model; pub mod gltf_loader; pub mod render; pub mod ecs_renderer; +pub mod render_system; pub mod window; pub use camera::Camera; pub use render::GliumRenderer; pub use ecs_renderer::ECSRenderer; +pub use render_system::RenderSystem; +pub use raidillon_core::ModelId; pub use window::{DisplayHandle, init_window as init_render_window}; diff --git a/raidillon_render/src/model.rs b/raidillon_render/src/model.rs index e474fe4..f980b8b 100644 --- a/raidillon_render/src/model.rs +++ b/raidillon_render/src/model.rs @@ -51,7 +51,13 @@ impl Default for Material { } } +// Implement the Material trait from raidillon_core +impl raidillon_core::Material for Material {} + pub struct Model { pub mesh: Mesh, pub material: Material, } + +// Implement the Model trait from raidillon_core +impl raidillon_core::Model for Model {} diff --git a/raidillon_render/src/render.rs b/raidillon_render/src/render.rs index 1d7554d..df6be7a 100644 --- a/raidillon_render/src/render.rs +++ b/raidillon_render/src/render.rs @@ -1,6 +1,7 @@ use crate::camera::Camera; use raidillon_ecs::{ModelHandle, Transform}; -use crate::model::{Model, Mesh}; +use crate::model::{Model, Material, Mesh}; +use raidillon_core::AssetManager; use glium::texture::{RawImage2d, SrgbTexture2d}; use glium::{uniform, Program, Surface}; use glium::uniforms::{MinifySamplerFilter, MagnifySamplerFilter, SamplerWrapFunction}; @@ -164,4 +165,94 @@ impl GliumRenderer { pub fn display(&self) -> &glium::Display { &self.display } + + pub fn render_into_with_assets(&mut self, world: &World, assets: &AssetManager, target: &mut S) { + target.clear_color_and_depth((0.1, 0.1, 0.15, 1.0), 1.0); + self.draw_scene_with_assets(world, assets, target); + } + + fn draw_scene_with_assets(&mut self, world: &World, assets: &AssetManager, target: &mut S) { + let cam = match world.query::<&Camera>().iter().next() { + Some((_, cam)) => *cam, + None => { + eprintln!("[renderer] No camera component found. Skipping frame"); + return; + } + }; + + // Direction from the light source (0,+Y) towards the scene. + let light_dir: Vec3 = Vec3::new(0.0, -1.0, 0.0).normalize(); + + for (_, (tr, mh)) in world.query::<(&Transform, &ModelHandle)>().iter() { + let model = match assets.get_model(raidillon_core::ModelId(mh.0)) { + Some(model) => model, + None => { + eprintln!("[renderer] Model with ID {} not found in assets", mh.0); + continue; + } + }; + let mesh = &model.mesh; + let mat = &model.material; + + let tex_ref: &SrgbTexture2d = mat.base_color.as_ref().unwrap_or(&self.white_tex); + + let mut sampler = tex_ref.sampled(); + sampler = sampler.wrap_function(SamplerWrapFunction::Repeat); + sampler = sampler.minify_filter(MinifySamplerFilter::Linear); + sampler = sampler.magnify_filter(MagnifySamplerFilter::Linear); + + let c = mat.base_color_factor; + + let uniforms = uniform! { + model: tr.matrix().to_cols_array_2d(), + view: cam.view().to_cols_array_2d(), + projection: cam.projection().to_cols_array_2d(), + u_light: [light_dir.x, light_dir.y, light_dir.z], + tex: sampler, + color: [c[0], c[1], c[2]], + uv_offset: [mat.uv_offset.x, mat.uv_offset.y], + uv_scale: [mat.uv_scale.x, mat.uv_scale.y], + }; + + target.draw( + &mesh.vbuf, + &mesh.ibuf, + &self.program, + &uniforms, + &self.params, + ).unwrap(); + } + + // Render skybox + let mut sky_view = cam.view(); + sky_view.w_axis = Vec4::new(0.0, 0.0, 0.0, 1.0); + + let mut sampler = self.skybox_texture.sampled(); + sampler = sampler.wrap_function(SamplerWrapFunction::Clamp); + sampler = sampler.minify_filter(MinifySamplerFilter::Linear); + sampler = sampler.magnify_filter(MagnifySamplerFilter::Linear); + + let uniforms = uniform! { + view: sky_view.to_cols_array_2d(), + projection: cam.projection().to_cols_array_2d(), + equirect: sampler, + }; + + let sky_params = glium::DrawParameters { + depth: glium::Depth { + test: DepthTest::IfLessOrEqual, + write: false, + .. Default::default() + }, + .. Default::default() + }; + + target.draw( + &self.skybox_mesh.vbuf, + &self.skybox_mesh.ibuf, + &self.skybox_program, + &uniforms, + &sky_params, + ).unwrap(); + } } diff --git a/raidillon_render/src/render_system.rs b/raidillon_render/src/render_system.rs new file mode 100644 index 0000000..7c3a468 --- /dev/null +++ b/raidillon_render/src/render_system.rs @@ -0,0 +1,50 @@ +use hecs::World; +use raidillon_core::{AssetManager, ModelId}; +use crate::render::GliumRenderer; +use crate::model::{Model, Material}; +use crate::window::DisplayHandle; +use glium::Surface; + +/// A pure render system that doesn't own the ECS world. +/// This decouples rendering from ECS world ownership. +pub struct RenderSystem { + renderer: GliumRenderer, + assets: AssetManager, +} + +impl RenderSystem { + pub fn new(display: DisplayHandle) -> anyhow::Result { + Ok(Self { + renderer: GliumRenderer::new(display.as_inner().clone())?, + assets: AssetManager::new(), + }) + } + + pub fn render(&mut self, world: &World, target: &mut impl Surface) { + // Pass the asset manager to the renderer for accessing models + self.renderer.render_into_with_assets(world, &self.assets, target); + } + + pub fn load_model(&mut self, path: &str) -> anyhow::Result { + // Check cache first + let model = crate::gltf_loader::load_gltf(path, self.renderer.display())?; + let model_id = self.assets.cache_model(path.to_string(), Box::new(model)); + Ok(model_id) + } + + pub fn display(&self) -> &glium::Display { + self.renderer.display() + } + + pub fn get_model(&self, id: ModelId) -> Option<&Model> { + self.assets.get_model(id) + } + + pub fn assets(&self) -> &AssetManager { + &self.assets + } + + pub fn assets_mut(&mut self) -> &mut AssetManager { + &mut self.assets + } +} \ No newline at end of file From f7d5c14caf49a8332059c4c9cf63494fb83a8b57 Mon Sep 17 00:00:00 2001 From: reo Date: Wed, 6 Aug 2025 11:43:04 +0300 Subject: [PATCH 26/89] Kickstart a new rewrite of the raidillon engine Endless refactors, refactor everyday, refactor relentlessly, refactor every morning, every day, every hour. --- .gitignore | 2 + README.md | 3 + raidillon_core/Cargo.lock | 7 + raidillon_core/Cargo.toml | 6 + raidillon_core/src/lib.rs | 0 raidillon_glium/Cargo.lock | 2236 ++++++++++++++++++++++++++++ raidillon_glium/Cargo.toml | 11 + raidillon_glium/src/assets.rs | 30 + raidillon_glium/src/gltf_loader.rs | 170 +++ raidillon_glium/src/lib.rs | 7 + raidillon_glium/src/model.rs | 57 + raidillon_glium/src/platform.rs | 31 + raidillon_platform/Cargo.lock | 1779 ++++++++++++++++++++++ raidillon_platform/Cargo.toml | 7 + raidillon_platform/src/assets.rs | 11 + raidillon_platform/src/context.rs | 11 + raidillon_platform/src/event.rs | 11 + raidillon_platform/src/lib.rs | 7 + raidillon_platform/src/platform.rs | 5 + 19 files changed, 4391 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 raidillon_core/Cargo.lock create mode 100644 raidillon_core/Cargo.toml create mode 100644 raidillon_core/src/lib.rs create mode 100644 raidillon_glium/Cargo.lock create mode 100644 raidillon_glium/Cargo.toml create mode 100644 raidillon_glium/src/assets.rs create mode 100644 raidillon_glium/src/gltf_loader.rs create mode 100644 raidillon_glium/src/lib.rs create mode 100644 raidillon_glium/src/model.rs create mode 100644 raidillon_glium/src/platform.rs create mode 100644 raidillon_platform/Cargo.lock create mode 100644 raidillon_platform/Cargo.toml create mode 100644 raidillon_platform/src/assets.rs create mode 100644 raidillon_platform/src/context.rs create mode 100644 raidillon_platform/src/event.rs create mode 100644 raidillon_platform/src/lib.rs create mode 100644 raidillon_platform/src/platform.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e1df7ae --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +target/ +*.patch diff --git a/README.md b/README.md new file mode 100644 index 0000000..bac9855 --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# Raidillon rewrite number #23818491847214 + +Starting in 2025-08-03, 17:59 UTC+3 diff --git a/raidillon_core/Cargo.lock b/raidillon_core/Cargo.lock new file mode 100644 index 0000000..d279de1 --- /dev/null +++ b/raidillon_core/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "raidillon_core" +version = "0.1.0" diff --git a/raidillon_core/Cargo.toml b/raidillon_core/Cargo.toml new file mode 100644 index 0000000..50eec90 --- /dev/null +++ b/raidillon_core/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "raidillon_core" +version = "0.1.0" +edition = "2024" + +[dependencies] diff --git a/raidillon_core/src/lib.rs b/raidillon_core/src/lib.rs new file mode 100644 index 0000000..e69de29 diff --git a/raidillon_glium/Cargo.lock b/raidillon_glium/Cargo.lock new file mode 100644 index 0000000..9bc6b80 --- /dev/null +++ b/raidillon_glium/Cargo.lock @@ -0,0 +1,2236 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "ab_glyph" +version = "0.2.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e074464580a518d16a7126262fffaaa47af89d4099d4cb403f8ed938ba12ee7d" +dependencies = [ + "ab_glyph_rasterizer", + "owned_ttf_parser", +] + +[[package]] +name = "ab_glyph_rasterizer" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2187590a23ab1e3df8681afdf0987c48504d80291f002fcdb651f0ef5e25169" + +[[package]] +name = "addr2line" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" + +[[package]] +name = "ahash" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" +dependencies = [ + "cfg-if", + "getrandom", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "android-activity" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef6978589202a00cd7e118380c448a08b6ed394c3a8df3a430d0898e3a42d046" +dependencies = [ + "android-properties", + "bitflags 2.9.1", + "cc", + "cesu8", + "jni", + "jni-sys", + "libc", + "log", + "ndk", + "ndk-context", + "ndk-sys", + "num_enum", + "thiserror", +] + +[[package]] +name = "android-properties" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc7eb209b1518d6bb87b283c20095f5228ecda460da70b44f0802523dea6da04" + +[[package]] +name = "anyhow" +version = "1.0.98" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" + +[[package]] +name = "arrayref" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" + +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + +[[package]] +name = "as-raw-xcb-connection" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "175571dd1d178ced59193a6fc02dde1b972eb0bc56c892cde9beeceac5bf0f6b" + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + +[[package]] +name = "backtrace" +version = "0.3.75" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" +dependencies = [ + "addr2line", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", + "windows-targets 0.52.6", +] + +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" + +[[package]] +name = "block2" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c132eebf10f5cad5289222520a4a058514204aed6d791f1cf4fe8088b82d15f" +dependencies = [ + "objc2 0.5.2", +] + +[[package]] +name = "bumpalo" +version = "3.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" + +[[package]] +name = "bytemuck" +version = "1.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c76a5792e44e4abe34d3abf15636779261d45a7450612059293d1d2cfc63422" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "byteorder-lite" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" + +[[package]] +name = "bytes" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" + +[[package]] +name = "calloop" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b99da2f8558ca23c71f4fd15dc57c906239752dd27ff3c00a1d56b685b7cbfec" +dependencies = [ + "bitflags 2.9.1", + "log", + "polling", + "rustix 0.38.44", + "slab", + "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 0.38.44", + "wayland-backend", + "wayland-client", +] + +[[package]] +name = "cc" +version = "1.2.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3a42d84bb6b69d3a8b3eaacf0d88f179e1929695e1ad012b6cf64d9caaa5fd2" +dependencies = [ + "jobserver", + "libc", + "shlex", +] + +[[package]] +name = "cesu8" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" + +[[package]] +name = "cfg-if" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" + +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + +[[package]] +name = "cgl" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ced0551234e87afee12411d535648dd89d2e7f34c78b753395567aff3d447ff" +dependencies = [ + "libc", +] + +[[package]] +name = "combine" +version = "4.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" +dependencies = [ + "bytes", + "memchr", +] + +[[package]] +name = "concurrent-queue" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "core-graphics" +version = "0.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c07782be35f9e1140080c6b96f0d44b739e2278479f64e02fdab4e32dfd8b081" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "core-graphics-types", + "foreign-types", + "libc", +] + +[[package]] +name = "core-graphics-types" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "libc", +] + +[[package]] +name = "crc32fast" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + +[[package]] +name = "cursor-icon" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f27ae1dd37df86211c42e150270f82743308803d90a6f6e6651cd730d5e1732f" + +[[package]] +name = "dispatch" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" + +[[package]] +name = "dispatch2" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89a09f22a6c6069a18470eb92d2298acf25463f14256d24778e1230d789a2aec" +dependencies = [ + "bitflags 2.9.1", + "objc2 0.6.1", +] + +[[package]] +name = "dlib" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "330c60081dcc4c72131f8eb70510f1ac07223e5d4163db481a04a0befcffa412" +dependencies = [ + "libloading", +] + +[[package]] +name = "downcast-rs" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" + +[[package]] +name = "dpi" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8b14ccef22fc6f5a8f4d7d768562a182c04ce9a3b3157b91390b52ddfdf1a76" + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "errno" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad" +dependencies = [ + "libc", + "windows-sys 0.60.2", +] + +[[package]] +name = "fdeflate" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c" +dependencies = [ + "simd-adler32", +] + +[[package]] +name = "flate2" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a3d7db9596fecd151c5f638c0ee5d5bd487b6e0ea232e5dc96d5250f6f94b1d" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foreign-types" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965" +dependencies = [ + "foreign-types-macros", + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-macros" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "foreign-types-shared" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" + +[[package]] +name = "gethostname" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0176e0459c2e4a1fe232f984bca6890e681076abb9934f6cea7c326f3fc47818" +dependencies = [ + "libc", + "windows-targets 0.48.5", +] + +[[package]] +name = "getrandom" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasi", +] + +[[package]] +name = "gimli" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" + +[[package]] +name = "gl_generator" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a95dfc23a2b4a9a2f5ab41d194f8bfda3cabec42af4e39f08c339eb2a0c124d" +dependencies = [ + "khronos_api", + "log", + "xml-rs", +] + +[[package]] +name = "glam" +version = "0.30.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2d1aab06663bdce00d6ca5e5ed586ec8d18033a771906c993a1e3755b368d85" + +[[package]] +name = "glium" +version = "0.35.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a3028d1f135b5395e6e4336916b424bc5dd2b38c6e378ce2704e4b8f4a617ed" +dependencies = [ + "backtrace", + "fnv", + "gl_generator", + "glutin", + "glutin-winit", + "memoffset", + "raw-window-handle", + "smallvec", + "winit", +] + +[[package]] +name = "gltf" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3ce1918195723ce6ac74e80542c5a96a40c2b26162c1957a5cd70799b8cacf7" +dependencies = [ + "base64", + "byteorder", + "gltf-json", + "image", + "lazy_static", + "serde_json", + "urlencoding", +] + +[[package]] +name = "gltf-derive" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14070e711538afba5d6c807edb74bcb84e5dbb9211a3bf5dea0dfab5b24f4c51" +dependencies = [ + "inflections", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "gltf-json" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6176f9d60a7eab0a877e8e96548605dedbde9190a7ae1e80bbcc1c9af03ab14" +dependencies = [ + "gltf-derive", + "serde", + "serde_derive", + "serde_json", +] + +[[package]] +name = "glutin" +version = "0.32.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12124de845cacfebedff80e877bb37b5b75c34c5a4c89e47e1cdd67fb6041325" +dependencies = [ + "bitflags 2.9.1", + "cfg_aliases", + "cgl", + "dispatch2", + "glutin_egl_sys", + "glutin_glx_sys", + "glutin_wgl_sys", + "libloading", + "objc2 0.6.1", + "objc2-app-kit 0.3.1", + "objc2-core-foundation", + "objc2-foundation 0.3.1", + "once_cell", + "raw-window-handle", + "wayland-sys", + "windows-sys 0.52.0", + "x11-dl", +] + +[[package]] +name = "glutin-winit" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85edca7075f8fc728f28cb8fbb111a96c3b89e930574369e3e9c27eb75d3788f" +dependencies = [ + "cfg_aliases", + "glutin", + "raw-window-handle", + "winit", +] + +[[package]] +name = "glutin_egl_sys" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c4680ba6195f424febdc3ba46e7a42a0e58743f2edb115297b86d7f8ecc02d2" +dependencies = [ + "gl_generator", + "windows-sys 0.52.0", +] + +[[package]] +name = "glutin_glx_sys" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a7bb2938045a88b612499fbcba375a77198e01306f52272e692f8c1f3751185" +dependencies = [ + "gl_generator", + "x11-dl", +] + +[[package]] +name = "glutin_wgl_sys" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c4ee00b289aba7a9e5306d57c2d05499b2e5dc427f84ac708bd2c090212cf3e" +dependencies = [ + "gl_generator", +] + +[[package]] +name = "hashbrown" +version = "0.15.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5" + +[[package]] +name = "hermit-abi" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" + +[[package]] +name = "image" +version = "0.25.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db35664ce6b9810857a38a906215e75a9c879f0696556a39f59c62829710251a" +dependencies = [ + "bytemuck", + "byteorder-lite", + "num-traits", + "png", + "zune-core", + "zune-jpeg", +] + +[[package]] +name = "indexmap" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe4cd85333e22411419a0bcae1297d25e58c9443848b11dc6a86fefe8c78a661" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "inflections" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a257582fdcde896fd96463bf2d40eefea0580021c0712a0e2b028b60b47a837a" + +[[package]] +name = "itoa" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" + +[[package]] +name = "jni" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" +dependencies = [ + "cesu8", + "cfg-if", + "combine", + "jni-sys", + "log", + "thiserror", + "walkdir", + "windows-sys 0.45.0", +] + +[[package]] +name = "jni-sys" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" + +[[package]] +name = "jobserver" +version = "0.1.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a" +dependencies = [ + "getrandom", + "libc", +] + +[[package]] +name = "js-sys" +version = "0.3.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "khronos_api" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc" + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.174" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776" + +[[package]] +name = "libloading" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667" +dependencies = [ + "cfg-if", + "windows-targets 0.53.3", +] + +[[package]] +name = "libredox" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "391290121bad3d37fbddad76d8f5d1c1c314cfc646d143d7e07a3086ddff0ce3" +dependencies = [ + "bitflags 2.9.1", + "libc", + "redox_syscall 0.5.17", +] + +[[package]] +name = "linux-raw-sys" +version = "0.4.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" + +[[package]] +name = "linux-raw-sys" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" + +[[package]] +name = "log" +version = "0.4.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" + +[[package]] +name = "memchr" +version = "2.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" + +[[package]] +name = "memmap2" +version = "0.9.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "483758ad303d734cec05e5c12b41d7e93e6a6390c5e9dae6bdeb7c1259012d28" +dependencies = [ + "libc", +] + +[[package]] +name = "memoffset" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +dependencies = [ + "autocfg", +] + +[[package]] +name = "miniz_oxide" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", + "simd-adler32", +] + +[[package]] +name = "ndk" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4" +dependencies = [ + "bitflags 2.9.1", + "jni-sys", + "log", + "ndk-sys", + "num_enum", + "raw-window-handle", + "thiserror", +] + +[[package]] +name = "ndk-context" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" + +[[package]] +name = "ndk-sys" +version = "0.6.0+11769913" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee6cda3051665f1fb8d9e08fc35c96d5a244fb1be711a03b71118828afc9a873" +dependencies = [ + "jni-sys", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_enum" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a973b4e44ce6cad84ce69d797acf9a044532e4184c4f267913d1b546a0727b7a" +dependencies = [ + "num_enum_derive", + "rustversion", +] + +[[package]] +name = "num_enum_derive" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77e878c846a8abae00dd069496dbe8751b16ac1c3d6bd2a7283a938e8228f90d" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "objc-sys" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb91bdd390c7ce1a8607f35f3ca7151b65afc0ff5ff3b34fa350f7d7c7e4310" + +[[package]] +name = "objc2" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46a785d4eeff09c14c487497c162e92766fbb3e4059a71840cecc03d9a50b804" +dependencies = [ + "objc-sys", + "objc2-encode", +] + +[[package]] +name = "objc2" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88c6597e14493ab2e44ce58f2fdecf095a51f12ca57bec060a11c57332520551" +dependencies = [ + "objc2-encode", +] + +[[package]] +name = "objc2-app-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4e89ad9e3d7d297152b17d39ed92cd50ca8063a89a9fa569046d41568891eff" +dependencies = [ + "bitflags 2.9.1", + "block2", + "libc", + "objc2 0.5.2", + "objc2-core-data", + "objc2-core-image", + "objc2-foundation 0.2.2", + "objc2-quartz-core", +] + +[[package]] +name = "objc2-app-kit" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6f29f568bec459b0ddff777cec4fe3fd8666d82d5a40ebd0ff7e66134f89bcc" +dependencies = [ + "bitflags 2.9.1", + "objc2 0.6.1", + "objc2-core-foundation", + "objc2-foundation 0.3.1", +] + +[[package]] +name = "objc2-cloud-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74dd3b56391c7a0596a295029734d3c1c5e7e510a4cb30245f8221ccea96b009" +dependencies = [ + "bitflags 2.9.1", + "block2", + "objc2 0.5.2", + "objc2-core-location", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-contacts" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5ff520e9c33812fd374d8deecef01d4a840e7b41862d849513de77e44aa4889" +dependencies = [ + "block2", + "objc2 0.5.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-core-data" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "617fbf49e071c178c0b24c080767db52958f716d9eabdf0890523aeae54773ef" +dependencies = [ + "bitflags 2.9.1", + "block2", + "objc2 0.5.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-core-foundation" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c10c2894a6fed806ade6027bcd50662746363a9589d3ec9d9bef30a4e4bc166" +dependencies = [ + "bitflags 2.9.1", + "dispatch2", + "objc2 0.6.1", +] + +[[package]] +name = "objc2-core-image" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55260963a527c99f1819c4f8e3b47fe04f9650694ef348ffd2227e8196d34c80" +dependencies = [ + "block2", + "objc2 0.5.2", + "objc2-foundation 0.2.2", + "objc2-metal", +] + +[[package]] +name = "objc2-core-location" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "000cfee34e683244f284252ee206a27953279d370e309649dc3ee317b37e5781" +dependencies = [ + "block2", + "objc2 0.5.2", + "objc2-contacts", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-encode" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33" + +[[package]] +name = "objc2-foundation" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8" +dependencies = [ + "bitflags 2.9.1", + "block2", + "dispatch", + "libc", + "objc2 0.5.2", +] + +[[package]] +name = "objc2-foundation" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "900831247d2fe1a09a683278e5384cfb8c80c79fe6b166f9d14bfdde0ea1b03c" +dependencies = [ + "bitflags 2.9.1", + "objc2 0.6.1", + "objc2-core-foundation", +] + +[[package]] +name = "objc2-link-presentation" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1a1ae721c5e35be65f01a03b6d2ac13a54cb4fa70d8a5da293d7b0020261398" +dependencies = [ + "block2", + "objc2 0.5.2", + "objc2-app-kit 0.2.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-metal" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6" +dependencies = [ + "bitflags 2.9.1", + "block2", + "objc2 0.5.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-quartz-core" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a" +dependencies = [ + "bitflags 2.9.1", + "block2", + "objc2 0.5.2", + "objc2-foundation 0.2.2", + "objc2-metal", +] + +[[package]] +name = "objc2-symbols" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a684efe3dec1b305badae1a28f6555f6ddd3bb2c2267896782858d5a78404dc" +dependencies = [ + "objc2 0.5.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-ui-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8bb46798b20cd6b91cbd113524c490f1686f4c4e8f49502431415f3512e2b6f" +dependencies = [ + "bitflags 2.9.1", + "block2", + "objc2 0.5.2", + "objc2-cloud-kit", + "objc2-core-data", + "objc2-core-image", + "objc2-core-location", + "objc2-foundation 0.2.2", + "objc2-link-presentation", + "objc2-quartz-core", + "objc2-symbols", + "objc2-uniform-type-identifiers", + "objc2-user-notifications", +] + +[[package]] +name = "objc2-uniform-type-identifiers" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44fa5f9748dbfe1ca6c0b79ad20725a11eca7c2218bceb4b005cb1be26273bfe" +dependencies = [ + "block2", + "objc2 0.5.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-user-notifications" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76cfcbf642358e8689af64cee815d139339f3ed8ad05103ed5eaf73db8d84cb3" +dependencies = [ + "bitflags 2.9.1", + "block2", + "objc2 0.5.2", + "objc2-core-location", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "object" +version = "0.36.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "orbclient" +version = "0.3.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba0b26cec2e24f08ed8bb31519a9333140a6599b867dac464bb150bdb796fd43" +dependencies = [ + "libredox", +] + +[[package]] +name = "owned_ttf_parser" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36820e9051aca1014ddc75770aab4d68bc1e9e632f0f5627c4086bc216fb583b" +dependencies = [ + "ttf-parser", +] + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "pin-project" +version = "1.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" + +[[package]] +name = "pkg-config" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" + +[[package]] +name = "png" +version = "0.17.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82151a2fc869e011c153adc57cf2789ccb8d9906ce52c0b39a6b5697749d7526" +dependencies = [ + "bitflags 1.3.2", + "crc32fast", + "fdeflate", + "flate2", + "miniz_oxide", +] + +[[package]] +name = "polling" +version = "3.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ee9b2fa7a4517d2c91ff5bc6c297a427a96749d15f98fcdbb22c05571a4d4b7" +dependencies = [ + "cfg-if", + "concurrent-queue", + "hermit-abi", + "pin-project-lite", + "rustix 1.0.8", + "windows-sys 0.60.2", +] + +[[package]] +name = "proc-macro-crate" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edce586971a4dfaa28950c6f18ed55e0406c1ab88bbce2c6f6293a7aaba73d35" +dependencies = [ + "toml_edit", +] + +[[package]] +name = "proc-macro2" +version = "1.0.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quick-xml" +version = "0.37.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "331e97a1af0bf59823e6eadffe373d7b27f485be8748f71471c662c1f269b7fb" +dependencies = [ + "memchr", +] + +[[package]] +name = "quote" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "raidillon_glium" +version = "0.1.0" +dependencies = [ + "anyhow", + "glam", + "glium", + "gltf", + "raidillon_platform", +] + +[[package]] +name = "raidillon_platform" +version = "0.1.0" +dependencies = [ + "winit", +] + +[[package]] +name = "raw-window-handle" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539" + +[[package]] +name = "redox_syscall" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "redox_syscall" +version = "0.5.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77" +dependencies = [ + "bitflags 2.9.1", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace" + +[[package]] +name = "rustix" +version = "0.38.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" +dependencies = [ + "bitflags 2.9.1", + "errno", + "libc", + "linux-raw-sys 0.4.15", + "windows-sys 0.59.0", +] + +[[package]] +name = "rustix" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8" +dependencies = [ + "bitflags 2.9.1", + "errno", + "libc", + "linux-raw-sys 0.9.4", + "windows-sys 0.60.2", +] + +[[package]] +name = "rustversion" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" + +[[package]] +name = "ryu" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +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 = "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 = "serde" +version = "1.0.219" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.219" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.142" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "030fedb782600dcbd6f02d479bf0d817ac3bb40d644745b769d6a96bc3afc5a7" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "simd-adler32" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" + +[[package]] +name = "slab" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04dc19736151f35336d325007ac991178d504a119863a2fcb3758cdb5e52c50d" + +[[package]] +name = "smallvec" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" + +[[package]] +name = "smithay-client-toolkit" +version = "0.19.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3457dea1f0eb631b4034d61d4d8c32074caa6cd1ab2d59f2327bd8461e2c0016" +dependencies = [ + "bitflags 2.9.1", + "calloop", + "calloop-wayland-source", + "cursor-icon", + "libc", + "log", + "memmap2", + "rustix 0.38.44", + "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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd538fb6910ac1099850255cf94a94df6551fbdd602454387d0adb2d1ca6dead" +dependencies = [ + "serde", +] + +[[package]] +name = "strict-num" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6637bab7722d379c8b41ba849228d680cc12d0a45ba1fa2b48f2a30577a06731" + +[[package]] +name = "syn" +version = "2.0.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[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 = "toml_datetime" +version = "0.6.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" + +[[package]] +name = "toml_edit" +version = "0.22.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" +dependencies = [ + "indexmap", + "toml_datetime", + "winnow", +] + +[[package]] +name = "tracing" +version = "0.1.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +dependencies = [ + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" + +[[package]] +name = "ttf-parser" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2df906b07856748fa3f6e0ad0cbaa047052d4a7dd609e231c4f72cee8c36f31" + +[[package]] +name = "unicode-ident" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" + +[[package]] +name = "unicode-segmentation" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" + +[[package]] +name = "urlencoding" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "wasi" +version = "0.14.2+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +dependencies = [ + "wit-bindgen-rt", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" +dependencies = [ + "bumpalo", + "log", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" +dependencies = [ + "cfg-if", + "js-sys", + "once_cell", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "wayland-backend" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "673a33c33048a5ade91a6b139580fa174e19fb0d23f396dca9fa15f2e1e49b35" +dependencies = [ + "cc", + "downcast-rs", + "rustix 1.0.8", + "scoped-tls", + "smallvec", + "wayland-sys", +] + +[[package]] +name = "wayland-client" +version = "0.31.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c66a47e840dc20793f2264eb4b3e4ecb4b75d91c0dd4af04b456128e0bdd449d" +dependencies = [ + "bitflags 2.9.1", + "rustix 1.0.8", + "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.9.1", + "cursor-icon", + "wayland-backend", +] + +[[package]] +name = "wayland-cursor" +version = "0.31.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "447ccc440a881271b19e9989f75726d60faa09b95b0200a9b7eb5cc47c3eeb29" +dependencies = [ + "rustix 1.0.8", + "wayland-client", + "xcursor", +] + +[[package]] +name = "wayland-protocols" +version = "0.32.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efa790ed75fbfd71283bd2521a1cfdc022aabcc28bdcff00851f9e4ae88d9901" +dependencies = [ + "bitflags 2.9.1", + "wayland-backend", + "wayland-client", + "wayland-scanner", +] + +[[package]] +name = "wayland-protocols-plasma" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a07a14257c077ab3279987c4f8bb987851bf57081b93710381daea94f2c2c032" +dependencies = [ + "bitflags 2.9.1", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-scanner", +] + +[[package]] +name = "wayland-protocols-wlr" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efd94963ed43cf9938a090ca4f7da58eb55325ec8200c3848963e98dc25b78ec" +dependencies = [ + "bitflags 2.9.1", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-scanner", +] + +[[package]] +name = "wayland-scanner" +version = "0.31.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54cb1e9dc49da91950bdfd8b848c49330536d9d1fb03d4bfec8cae50caa50ae3" +dependencies = [ + "proc-macro2", + "quick-xml", + "quote", +] + +[[package]] +name = "wayland-sys" +version = "0.31.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34949b42822155826b41db8e5d0c1be3a2bd296c747577a43a3e6daefc296142" +dependencies = [ + "dlib", + "log", + "once_cell", + "pkg-config", +] + +[[package]] +name = "web-sys" +version = "0.3.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "winapi-util" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "windows-link" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" + +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets 0.42.2", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets 0.53.3", +] + +[[package]] +name = "windows-targets" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm 0.52.6", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.53.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91" +dependencies = [ + "windows-link", + "windows_aarch64_gnullvm 0.53.0", + "windows_aarch64_msvc 0.53.0", + "windows_i686_gnu 0.53.0", + "windows_i686_gnullvm 0.53.0", + "windows_i686_msvc 0.53.0", + "windows_x86_64_gnu 0.53.0", + "windows_x86_64_gnullvm 0.53.0", + "windows_x86_64_msvc 0.53.0", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" + +[[package]] +name = "windows_i686_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" + +[[package]] +name = "windows_i686_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_i686_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" + +[[package]] +name = "winit" +version = "0.30.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c66d4b9ed69c4009f6321f762d6e61ad8a2389cd431b97cb1e146812e9e6c732" +dependencies = [ + "ahash", + "android-activity", + "atomic-waker", + "bitflags 2.9.1", + "block2", + "bytemuck", + "calloop", + "cfg_aliases", + "concurrent-queue", + "core-foundation", + "core-graphics", + "cursor-icon", + "dpi", + "js-sys", + "libc", + "memmap2", + "ndk", + "objc2 0.5.2", + "objc2-app-kit 0.2.2", + "objc2-foundation 0.2.2", + "objc2-ui-kit", + "orbclient", + "percent-encoding", + "pin-project", + "raw-window-handle", + "redox_syscall 0.4.1", + "rustix 0.38.44", + "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", + "x11-dl", + "x11rb", + "xkbcommon-dl", +] + +[[package]] +name = "winnow" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3edebf492c8125044983378ecb5766203ad3b4c2f7a922bd7dd207f6d443e95" +dependencies = [ + "memchr", +] + +[[package]] +name = "wit-bindgen-rt" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" +dependencies = [ + "bitflags 2.9.1", +] + +[[package]] +name = "x11-dl" +version = "2.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38735924fedd5314a6e548792904ed8c6de6636285cb9fec04d5b1db85c1516f" +dependencies = [ + "libc", + "once_cell", + "pkg-config", +] + +[[package]] +name = "x11rb" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d91ffca73ee7f68ce055750bf9f6eca0780b8c85eff9bc046a3b0da41755e12" +dependencies = [ + "as-raw-xcb-connection", + "gethostname", + "libc", + "libloading", + "once_cell", + "rustix 0.38.44", + "x11rb-protocol", +] + +[[package]] +name = "x11rb-protocol" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec107c4503ea0b4a98ef47356329af139c0a4f7750e621cf2973cd3385ebcb3d" + +[[package]] +name = "xcursor" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bec9e4a500ca8864c5b47b8b482a73d62e4237670e5b5f1d6b9e3cae50f28f2b" + +[[package]] +name = "xkbcommon-dl" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d039de8032a9a8856a6be89cea3e5d12fdd82306ab7c94d74e6deab2460651c5" +dependencies = [ + "bitflags 2.9.1", + "dlib", + "log", + "once_cell", + "xkeysym", +] + +[[package]] +name = "xkeysym" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9cc00251562a284751c9973bace760d86c0276c471b4be569fe6b068ee97a56" + +[[package]] +name = "xml-rs" +version = "0.8.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fd8403733700263c6eb89f192880191f1b83e332f7a20371ddcf421c4a337c7" + +[[package]] +name = "zerocopy" +version = "0.8.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "zune-core" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f423a2c17029964870cfaabb1f13dfab7d092a62a29a89264f4d36990ca414a" + +[[package]] +name = "zune-jpeg" +version = "0.4.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc1f7e205ce79eb2da3cd71c5f55f3589785cb7c79f6a03d1c8d1491bda5d089" +dependencies = [ + "zune-core", +] diff --git a/raidillon_glium/Cargo.toml b/raidillon_glium/Cargo.toml new file mode 100644 index 0000000..37c9a16 --- /dev/null +++ b/raidillon_glium/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "raidillon_glium" +version = "0.1.0" +edition = "2024" + +[dependencies] +anyhow = "1.0.98" +glam = "0.30.5" +glium = { version = "0.35.0", features = ["glutin_backend", "simple_window_builder"] } +gltf = { version = "1.4.1", features = ["import", "utils", "KHR_texture_transform"] } +raidillon_platform = { path = "../raidillon_platform" } diff --git a/raidillon_glium/src/assets.rs b/raidillon_glium/src/assets.rs new file mode 100644 index 0000000..8e04c4a --- /dev/null +++ b/raidillon_glium/src/assets.rs @@ -0,0 +1,30 @@ +use raidillon_platform::AssetManager; +use crate::model::Model; +use std::path::Path; +use raidillon_platform::assets::ModelHandle; +use crate::gltf_loader::load_gltf; +use glium::backend::Facade; +use std::collections::HashMap; + +/// Glium platform asset manager implementation. +pub struct GliumAssetManager { + models: Vec>, + facade: Box, + next_model_id: usize, +} + +impl AssetManager for GliumAssetManager { + fn load_gltf(&mut self, path: &Path) -> ModelHandle { + let model_id = self.next_model_id; + let model = load_gltf(path, self.facade.as_ref()).unwrap(); + self.models.push(Some(model)); + self.next_model_id += 1; + model_id + } + + fn unload_model(&mut self, model_handle: ModelHandle) { + if model_handle < self.models.len() { + self.models[model_handle] = None; + } + } +} diff --git a/raidillon_glium/src/gltf_loader.rs b/raidillon_glium/src/gltf_loader.rs new file mode 100644 index 0000000..e41bbfb --- /dev/null +++ b/raidillon_glium/src/gltf_loader.rs @@ -0,0 +1,170 @@ +use anyhow::{Context, Result}; +use glium::{backend::Facade, IndexBuffer, VertexBuffer}; +use glium::index::PrimitiveType; +use std::{fmt::Debug, path::Path}; +use crate::model::{Vertex, Mesh, Material, Model}; +use glium::texture::{RawImage2d, Texture2d, SrgbTexture2d}; +use glium::uniforms::{SamplerWrapFunction, MinifySamplerFilter, MagnifySamplerFilter}; +use gltf::image::Format as GltfFormat; +use glam::Vec2; + +/// Load a glTF 2.0 file from disk and upload the first primitive to the GPU. +pub fn load_gltf

(path: P, facade: &dyn Facade) -> Result +where + P: AsRef + Debug, +{ + // -- parse the asset & bring buffer blobs into memory -- + let (doc, buffers, images) = gltf::import(path.as_ref()).context("failed to import glTF file")?; + + // -- grab the very first mesh / primitive -- + let mesh = doc.meshes().next().context("glTF has no meshes")?; + let primitive = mesh.primitives().next().context("mesh has no primitives")?; + + // ---------- MATERIAL ---------- + let mut mat = Material::default(); + + let mat_idx = primitive.material().index().context("primitive has no material")?; + let material = doc.materials().nth(mat_idx).unwrap(); + let pbr = material.pbr_metallic_roughness(); + + // Factors -------------------------------------------------- + mat.base_color_factor = pbr.base_color_factor(); + mat.metal_factor = pbr.metallic_factor(); + mat.roughness_factor = pbr.roughness_factor(); + mat.emissive_factor = material.emissive_factor(); + + // Helper to update sampler settings from glTF sampler + fn update_sampler(mat: &mut Material, t: &gltf::texture::Texture<'_>) { + let sampler_info = t.sampler(); + mat.sampler.wrap_function.0 = match sampler_info.wrap_s() { + gltf::texture::WrappingMode::ClampToEdge => SamplerWrapFunction::Clamp, + gltf::texture::WrappingMode::MirroredRepeat => SamplerWrapFunction::Mirror, + gltf::texture::WrappingMode::Repeat => SamplerWrapFunction::Repeat, + }; + mat.sampler.wrap_function.1 = match sampler_info.wrap_t() { + gltf::texture::WrappingMode::ClampToEdge => SamplerWrapFunction::Clamp, + gltf::texture::WrappingMode::MirroredRepeat => SamplerWrapFunction::Mirror, + gltf::texture::WrappingMode::Repeat => SamplerWrapFunction::Repeat, + }; + if let Some(f) = sampler_info.mag_filter() { + mat.sampler.magnify_filter = match f { + gltf::texture::MagFilter::Nearest => MagnifySamplerFilter::Nearest, + gltf::texture::MagFilter::Linear => MagnifySamplerFilter::Linear, + }; + } + if let Some(f) = sampler_info.min_filter() { + mat.sampler.minify_filter = match f { + gltf::texture::MinFilter::Nearest => MinifySamplerFilter::Nearest, + gltf::texture::MinFilter::Linear => MinifySamplerFilter::Linear, + gltf::texture::MinFilter::NearestMipmapNearest => MinifySamplerFilter::NearestMipmapNearest, + gltf::texture::MinFilter::NearestMipmapLinear => MinifySamplerFilter::NearestMipmapLinear, + gltf::texture::MinFilter::LinearMipmapNearest => MinifySamplerFilter::LinearMipmapNearest, + gltf::texture::MinFilter::LinearMipmapLinear => MinifySamplerFilter::LinearMipmapLinear, + }; + } + } + + // Base-color texture (sRGB) + if let Some(info) = pbr.base_color_texture() { + update_sampler(&mut mat, &info.texture()); + let view = info.texture().source().index(); + mat.base_color = Some(glium_srgb_texture(facade, &images[view])?); + } + + // Metallic-Roughness (linear) + if let Some(info) = pbr.metallic_roughness_texture() { + update_sampler(&mut mat, &info.texture()); + let view = info.texture().source().index(); + mat.metallic_roughness = Some(glium_linear_texture(facade, &images[view])?); + } + + // Normal map (linear) + if let Some(info) = primitive.material().normal_texture() { + update_sampler(&mut mat, &info.texture()); + let view = info.texture().source().index(); + mat.normal = Some(glium_linear_texture(facade, &images[view])?); + } + + // Occlusion (linear) + if let Some(info) = primitive.material().occlusion_texture() { + update_sampler(&mut mat, &info.texture()); + let view = info.texture().source().index(); + mat.occlusion = Some(glium_linear_texture(facade, &images[view])?); + } + + // Emissive (sRGB) + if let Some(info) = primitive.material().emissive_texture() { + update_sampler(&mut mat, &info.texture()); + let view = info.texture().source().index(); + mat.emissive = Some(glium_srgb_texture(facade, &images[view])?); + } + + // KHR_texture_transform + if let Some(tex) = pbr.base_color_texture() { + if let Some(xform) = tex.texture_transform() { + mat.uv_offset = Vec2::new(xform.offset()[0], xform.offset()[1]); + mat.uv_scale = Vec2::new(xform.scale()[0], xform.scale()[1]); + } + } + + // ---- Vertex/index data ---- + let reader = primitive.reader(|buf| Some(&buffers[buf.index()].0)); + + let positions: Vec<[f32; 3]> = reader.read_positions().context("missing POSITION")?.collect(); + let normals: Vec<[f32; 3]> = reader.read_normals().context("missing NORMAL")?.collect(); + let tex_coords: Vec<[f32; 2]> = reader.read_tex_coords(0).map(|tc| tc.into_f32().collect()).unwrap_or_else(|| vec![[0.0, 0.0]; positions.len()]); + let indices: Vec = reader.read_indices().context("missing indices")?.into_u32().collect(); + + // Interleave + let vertices: Vec = (0..positions.len()).map(|i| Vertex { position: positions[i], normal: normals[i], tex_coords: tex_coords[i] }).collect(); + + let vbuf = VertexBuffer::immutable(facade, &vertices)?; + let ibuf = IndexBuffer ::immutable(facade, PrimitiveType::TrianglesList, &indices)?; + + Ok(Model { mesh: Mesh { vbuf, ibuf }, material: mat }) +} + +/// Linear-space texture (RGBA8) from glTF image data. +fn glium_linear_texture(facade: &dyn Facade, img: &gltf::image::Data) -> Result +{ + let rgba = to_rgba(img); + let raw = RawImage2d::from_raw_rgba(rgba, (img.width, img.height)); + Ok(Texture2d::new(facade, raw)?) +} + +/// sRGB texture from glTF image data. +fn glium_srgb_texture(facade: &dyn Facade, img: &gltf::image::Data) -> Result +{ + let rgba = to_rgba(img); + let raw = RawImage2d::from_raw_rgba(rgba, (img.width, img.height)); + Ok(SrgbTexture2d::new(facade, raw)?) +} + +/// Convert various glTF image formats to RGBA8 as expected by glium. +fn to_rgba(img: &gltf::image::Data) -> Vec { + match img.format { + GltfFormat::R8G8B8A8 => img.pixels.clone(), + GltfFormat::R8G8B8 => { + // Expand RGB to RGBA with alpha=255 + img.pixels + .chunks(3) + .flat_map(|rgb| [rgb[0], rgb[1], rgb[2], 255u8]) + .collect() + } + GltfFormat::R8G8 => { + // Treat RG as luminance+alpha? For simplicity, replicate first channel into RGB, second as alpha. + img.pixels + .chunks(2) + .flat_map(|rg| [rg[0], rg[0], rg[0], rg[1]]) + .collect() + } + GltfFormat::R8 => { + // Grayscale: replicate into RGB, alpha=255 + img.pixels + .iter() + .flat_map(|l| [*l, *l, *l, 255u8]) + .collect() + } + _ => img.pixels.clone(), + } +} diff --git a/raidillon_glium/src/lib.rs b/raidillon_glium/src/lib.rs new file mode 100644 index 0000000..777462b --- /dev/null +++ b/raidillon_glium/src/lib.rs @@ -0,0 +1,7 @@ +pub mod platform; +pub mod assets; +pub mod model; +pub mod gltf_loader; + +pub use assets::GliumAssetManager; +pub use platform::GliumPlatform; diff --git a/raidillon_glium/src/model.rs b/raidillon_glium/src/model.rs new file mode 100644 index 0000000..815cd96 --- /dev/null +++ b/raidillon_glium/src/model.rs @@ -0,0 +1,57 @@ +use glium::{IndexBuffer, VertexBuffer, implement_vertex}; +use glium::texture::{SrgbTexture2d, Texture2d}; +use glium::uniforms::SamplerBehavior; +use glam::{Vec2}; +use std::sync::atomic::{AtomicUsize, Ordering}; + +#[derive(Copy, Clone)] +pub struct Vertex { + pub position: [f32; 3], + pub normal: [f32; 3], + pub tex_coords: [f32; 2], +} +implement_vertex!(Vertex, position, normal, tex_coords); + +pub struct Mesh { + pub vbuf: VertexBuffer, + pub ibuf: IndexBuffer, +} + +pub struct Material { + pub base_color: Option, + pub metallic_roughness: Option, + pub normal: Option, + pub occlusion: Option, + pub emissive: Option, + pub sampler: SamplerBehavior, + pub uv_offset: Vec2, + pub uv_scale: Vec2, + pub base_color_factor: [f32; 4], + pub emissive_factor: [f32; 3], + pub metal_factor: f32, + pub roughness_factor: f32, +} + +impl Default for Material { + fn default() -> Self { + Self { + base_color: None, + metallic_roughness: None, + normal: None, + occlusion: None, + emissive: None, + sampler: SamplerBehavior::default(), + uv_offset: Vec2::ZERO, + uv_scale: Vec2::ONE, + base_color_factor: [1.0; 4], + emissive_factor: [0.0; 3], + metal_factor: 1.0, + roughness_factor: 1.0, + } + } +} + +pub struct Model { + pub mesh: Mesh, + pub material: Material, +} diff --git a/raidillon_glium/src/platform.rs b/raidillon_glium/src/platform.rs new file mode 100644 index 0000000..dc01ad7 --- /dev/null +++ b/raidillon_glium/src/platform.rs @@ -0,0 +1,31 @@ +use raidillon_platform::Platform; +use glium::winit::event_loop::EventLoop; +use glium::winit::window::Window; +use glium::backend::glutin::Display; +use glium::glutin::surface::WindowSurface; +use glium::backend::glutin::SimpleWindowBuilder; + +pub struct GliumPlatform { + event_loop: EventLoop<()>, + window: Window, + display: Display, +} + +impl Platform for GliumPlatform { + fn initialize(title: String, width: u32, height: u32) -> Self { + let event_loop = glium::winit::event_loop::EventLoop::builder() + .build() + .expect("create event-loop"); + + let (window, display) = SimpleWindowBuilder::new() + .with_title(title.as_str()) + .with_inner_size(width, height) + .build(&event_loop); + + Self { + event_loop, + window, + display + } + } +} diff --git a/raidillon_platform/Cargo.lock b/raidillon_platform/Cargo.lock new file mode 100644 index 0000000..4ca8f54 --- /dev/null +++ b/raidillon_platform/Cargo.lock @@ -0,0 +1,1779 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "ab_glyph" +version = "0.2.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e074464580a518d16a7126262fffaaa47af89d4099d4cb403f8ed938ba12ee7d" +dependencies = [ + "ab_glyph_rasterizer", + "owned_ttf_parser", +] + +[[package]] +name = "ab_glyph_rasterizer" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2187590a23ab1e3df8681afdf0987c48504d80291f002fcdb651f0ef5e25169" + +[[package]] +name = "ahash" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" +dependencies = [ + "cfg-if", + "getrandom", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "android-activity" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef6978589202a00cd7e118380c448a08b6ed394c3a8df3a430d0898e3a42d046" +dependencies = [ + "android-properties", + "bitflags 2.9.1", + "cc", + "cesu8", + "jni", + "jni-sys", + "libc", + "log", + "ndk", + "ndk-context", + "ndk-sys", + "num_enum", + "thiserror", +] + +[[package]] +name = "android-properties" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc7eb209b1518d6bb87b283c20095f5228ecda460da70b44f0802523dea6da04" + +[[package]] +name = "arrayref" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" + +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + +[[package]] +name = "as-raw-xcb-connection" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "175571dd1d178ced59193a6fc02dde1b972eb0bc56c892cde9beeceac5bf0f6b" + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" + +[[package]] +name = "block2" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c132eebf10f5cad5289222520a4a058514204aed6d791f1cf4fe8088b82d15f" +dependencies = [ + "objc2", +] + +[[package]] +name = "bumpalo" +version = "3.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" + +[[package]] +name = "bytemuck" +version = "1.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c76a5792e44e4abe34d3abf15636779261d45a7450612059293d1d2cfc63422" + +[[package]] +name = "bytes" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" + +[[package]] +name = "calloop" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b99da2f8558ca23c71f4fd15dc57c906239752dd27ff3c00a1d56b685b7cbfec" +dependencies = [ + "bitflags 2.9.1", + "log", + "polling", + "rustix 0.38.44", + "slab", + "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 0.38.44", + "wayland-backend", + "wayland-client", +] + +[[package]] +name = "cc" +version = "1.2.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3a42d84bb6b69d3a8b3eaacf0d88f179e1929695e1ad012b6cf64d9caaa5fd2" +dependencies = [ + "jobserver", + "libc", + "shlex", +] + +[[package]] +name = "cesu8" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" + +[[package]] +name = "cfg-if" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" + +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + +[[package]] +name = "combine" +version = "4.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" +dependencies = [ + "bytes", + "memchr", +] + +[[package]] +name = "concurrent-queue" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "core-graphics" +version = "0.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c07782be35f9e1140080c6b96f0d44b739e2278479f64e02fdab4e32dfd8b081" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "core-graphics-types", + "foreign-types", + "libc", +] + +[[package]] +name = "core-graphics-types" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "libc", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + +[[package]] +name = "cursor-icon" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f27ae1dd37df86211c42e150270f82743308803d90a6f6e6651cd730d5e1732f" + +[[package]] +name = "dispatch" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" + +[[package]] +name = "dlib" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "330c60081dcc4c72131f8eb70510f1ac07223e5d4163db481a04a0befcffa412" +dependencies = [ + "libloading", +] + +[[package]] +name = "downcast-rs" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" + +[[package]] +name = "dpi" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8b14ccef22fc6f5a8f4d7d768562a182c04ce9a3b3157b91390b52ddfdf1a76" + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "errno" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad" +dependencies = [ + "libc", + "windows-sys 0.60.2", +] + +[[package]] +name = "foreign-types" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965" +dependencies = [ + "foreign-types-macros", + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-macros" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "foreign-types-shared" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" + +[[package]] +name = "gethostname" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0176e0459c2e4a1fe232f984bca6890e681076abb9934f6cea7c326f3fc47818" +dependencies = [ + "libc", + "windows-targets 0.48.5", +] + +[[package]] +name = "getrandom" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasi", +] + +[[package]] +name = "hashbrown" +version = "0.15.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5" + +[[package]] +name = "hermit-abi" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" + +[[package]] +name = "indexmap" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe4cd85333e22411419a0bcae1297d25e58c9443848b11dc6a86fefe8c78a661" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "jni" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" +dependencies = [ + "cesu8", + "cfg-if", + "combine", + "jni-sys", + "log", + "thiserror", + "walkdir", + "windows-sys 0.45.0", +] + +[[package]] +name = "jni-sys" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" + +[[package]] +name = "jobserver" +version = "0.1.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a" +dependencies = [ + "getrandom", + "libc", +] + +[[package]] +name = "js-sys" +version = "0.3.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "libc" +version = "0.2.174" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776" + +[[package]] +name = "libloading" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667" +dependencies = [ + "cfg-if", + "windows-targets 0.53.3", +] + +[[package]] +name = "libredox" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "391290121bad3d37fbddad76d8f5d1c1c314cfc646d143d7e07a3086ddff0ce3" +dependencies = [ + "bitflags 2.9.1", + "libc", + "redox_syscall 0.5.17", +] + +[[package]] +name = "linux-raw-sys" +version = "0.4.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" + +[[package]] +name = "linux-raw-sys" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" + +[[package]] +name = "log" +version = "0.4.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" + +[[package]] +name = "memchr" +version = "2.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" + +[[package]] +name = "memmap2" +version = "0.9.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "483758ad303d734cec05e5c12b41d7e93e6a6390c5e9dae6bdeb7c1259012d28" +dependencies = [ + "libc", +] + +[[package]] +name = "ndk" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4" +dependencies = [ + "bitflags 2.9.1", + "jni-sys", + "log", + "ndk-sys", + "num_enum", + "raw-window-handle", + "thiserror", +] + +[[package]] +name = "ndk-context" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" + +[[package]] +name = "ndk-sys" +version = "0.6.0+11769913" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee6cda3051665f1fb8d9e08fc35c96d5a244fb1be711a03b71118828afc9a873" +dependencies = [ + "jni-sys", +] + +[[package]] +name = "num_enum" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a973b4e44ce6cad84ce69d797acf9a044532e4184c4f267913d1b546a0727b7a" +dependencies = [ + "num_enum_derive", + "rustversion", +] + +[[package]] +name = "num_enum_derive" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77e878c846a8abae00dd069496dbe8751b16ac1c3d6bd2a7283a938e8228f90d" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "objc-sys" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb91bdd390c7ce1a8607f35f3ca7151b65afc0ff5ff3b34fa350f7d7c7e4310" + +[[package]] +name = "objc2" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46a785d4eeff09c14c487497c162e92766fbb3e4059a71840cecc03d9a50b804" +dependencies = [ + "objc-sys", + "objc2-encode", +] + +[[package]] +name = "objc2-app-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4e89ad9e3d7d297152b17d39ed92cd50ca8063a89a9fa569046d41568891eff" +dependencies = [ + "bitflags 2.9.1", + "block2", + "libc", + "objc2", + "objc2-core-data", + "objc2-core-image", + "objc2-foundation", + "objc2-quartz-core", +] + +[[package]] +name = "objc2-cloud-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74dd3b56391c7a0596a295029734d3c1c5e7e510a4cb30245f8221ccea96b009" +dependencies = [ + "bitflags 2.9.1", + "block2", + "objc2", + "objc2-core-location", + "objc2-foundation", +] + +[[package]] +name = "objc2-contacts" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5ff520e9c33812fd374d8deecef01d4a840e7b41862d849513de77e44aa4889" +dependencies = [ + "block2", + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-core-data" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "617fbf49e071c178c0b24c080767db52958f716d9eabdf0890523aeae54773ef" +dependencies = [ + "bitflags 2.9.1", + "block2", + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-core-image" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55260963a527c99f1819c4f8e3b47fe04f9650694ef348ffd2227e8196d34c80" +dependencies = [ + "block2", + "objc2", + "objc2-foundation", + "objc2-metal", +] + +[[package]] +name = "objc2-core-location" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "000cfee34e683244f284252ee206a27953279d370e309649dc3ee317b37e5781" +dependencies = [ + "block2", + "objc2", + "objc2-contacts", + "objc2-foundation", +] + +[[package]] +name = "objc2-encode" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33" + +[[package]] +name = "objc2-foundation" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8" +dependencies = [ + "bitflags 2.9.1", + "block2", + "dispatch", + "libc", + "objc2", +] + +[[package]] +name = "objc2-link-presentation" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1a1ae721c5e35be65f01a03b6d2ac13a54cb4fa70d8a5da293d7b0020261398" +dependencies = [ + "block2", + "objc2", + "objc2-app-kit", + "objc2-foundation", +] + +[[package]] +name = "objc2-metal" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6" +dependencies = [ + "bitflags 2.9.1", + "block2", + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-quartz-core" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a" +dependencies = [ + "bitflags 2.9.1", + "block2", + "objc2", + "objc2-foundation", + "objc2-metal", +] + +[[package]] +name = "objc2-symbols" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a684efe3dec1b305badae1a28f6555f6ddd3bb2c2267896782858d5a78404dc" +dependencies = [ + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-ui-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8bb46798b20cd6b91cbd113524c490f1686f4c4e8f49502431415f3512e2b6f" +dependencies = [ + "bitflags 2.9.1", + "block2", + "objc2", + "objc2-cloud-kit", + "objc2-core-data", + "objc2-core-image", + "objc2-core-location", + "objc2-foundation", + "objc2-link-presentation", + "objc2-quartz-core", + "objc2-symbols", + "objc2-uniform-type-identifiers", + "objc2-user-notifications", +] + +[[package]] +name = "objc2-uniform-type-identifiers" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44fa5f9748dbfe1ca6c0b79ad20725a11eca7c2218bceb4b005cb1be26273bfe" +dependencies = [ + "block2", + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-user-notifications" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76cfcbf642358e8689af64cee815d139339f3ed8ad05103ed5eaf73db8d84cb3" +dependencies = [ + "bitflags 2.9.1", + "block2", + "objc2", + "objc2-core-location", + "objc2-foundation", +] + +[[package]] +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "orbclient" +version = "0.3.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba0b26cec2e24f08ed8bb31519a9333140a6599b867dac464bb150bdb796fd43" +dependencies = [ + "libredox", +] + +[[package]] +name = "owned_ttf_parser" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36820e9051aca1014ddc75770aab4d68bc1e9e632f0f5627c4086bc216fb583b" +dependencies = [ + "ttf-parser", +] + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "pin-project" +version = "1.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" + +[[package]] +name = "pkg-config" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" + +[[package]] +name = "polling" +version = "3.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5bd19146350fe804f7cb2669c851c03d69da628803dab0d98018142aaa5d829" +dependencies = [ + "cfg-if", + "concurrent-queue", + "hermit-abi", + "pin-project-lite", + "rustix 1.0.8", + "windows-sys 0.60.2", +] + +[[package]] +name = "proc-macro-crate" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edce586971a4dfaa28950c6f18ed55e0406c1ab88bbce2c6f6293a7aaba73d35" +dependencies = [ + "toml_edit", +] + +[[package]] +name = "proc-macro2" +version = "1.0.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quick-xml" +version = "0.37.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "331e97a1af0bf59823e6eadffe373d7b27f485be8748f71471c662c1f269b7fb" +dependencies = [ + "memchr", +] + +[[package]] +name = "quote" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "raidillon_platform" +version = "0.1.0" +dependencies = [ + "winit", +] + +[[package]] +name = "raw-window-handle" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539" + +[[package]] +name = "redox_syscall" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "redox_syscall" +version = "0.5.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77" +dependencies = [ + "bitflags 2.9.1", +] + +[[package]] +name = "rustix" +version = "0.38.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" +dependencies = [ + "bitflags 2.9.1", + "errno", + "libc", + "linux-raw-sys 0.4.15", + "windows-sys 0.59.0", +] + +[[package]] +name = "rustix" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8" +dependencies = [ + "bitflags 2.9.1", + "errno", + "libc", + "linux-raw-sys 0.9.4", + "windows-sys 0.60.2", +] + +[[package]] +name = "rustversion" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +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 = "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 = "serde" +version = "1.0.219" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.219" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "slab" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04dc19736151f35336d325007ac991178d504a119863a2fcb3758cdb5e52c50d" + +[[package]] +name = "smallvec" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" + +[[package]] +name = "smithay-client-toolkit" +version = "0.19.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3457dea1f0eb631b4034d61d4d8c32074caa6cd1ab2d59f2327bd8461e2c0016" +dependencies = [ + "bitflags 2.9.1", + "calloop", + "calloop-wayland-source", + "cursor-icon", + "libc", + "log", + "memmap2", + "rustix 0.38.44", + "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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd538fb6910ac1099850255cf94a94df6551fbdd602454387d0adb2d1ca6dead" +dependencies = [ + "serde", +] + +[[package]] +name = "strict-num" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6637bab7722d379c8b41ba849228d680cc12d0a45ba1fa2b48f2a30577a06731" + +[[package]] +name = "syn" +version = "2.0.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[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 = "toml_datetime" +version = "0.6.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" + +[[package]] +name = "toml_edit" +version = "0.22.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" +dependencies = [ + "indexmap", + "toml_datetime", + "winnow", +] + +[[package]] +name = "tracing" +version = "0.1.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +dependencies = [ + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" + +[[package]] +name = "ttf-parser" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2df906b07856748fa3f6e0ad0cbaa047052d4a7dd609e231c4f72cee8c36f31" + +[[package]] +name = "unicode-ident" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" + +[[package]] +name = "unicode-segmentation" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "wasi" +version = "0.14.2+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +dependencies = [ + "wit-bindgen-rt", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" +dependencies = [ + "bumpalo", + "log", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" +dependencies = [ + "cfg-if", + "js-sys", + "once_cell", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "wayland-backend" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "673a33c33048a5ade91a6b139580fa174e19fb0d23f396dca9fa15f2e1e49b35" +dependencies = [ + "cc", + "downcast-rs", + "rustix 1.0.8", + "scoped-tls", + "smallvec", + "wayland-sys", +] + +[[package]] +name = "wayland-client" +version = "0.31.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c66a47e840dc20793f2264eb4b3e4ecb4b75d91c0dd4af04b456128e0bdd449d" +dependencies = [ + "bitflags 2.9.1", + "rustix 1.0.8", + "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.9.1", + "cursor-icon", + "wayland-backend", +] + +[[package]] +name = "wayland-cursor" +version = "0.31.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "447ccc440a881271b19e9989f75726d60faa09b95b0200a9b7eb5cc47c3eeb29" +dependencies = [ + "rustix 1.0.8", + "wayland-client", + "xcursor", +] + +[[package]] +name = "wayland-protocols" +version = "0.32.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efa790ed75fbfd71283bd2521a1cfdc022aabcc28bdcff00851f9e4ae88d9901" +dependencies = [ + "bitflags 2.9.1", + "wayland-backend", + "wayland-client", + "wayland-scanner", +] + +[[package]] +name = "wayland-protocols-plasma" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a07a14257c077ab3279987c4f8bb987851bf57081b93710381daea94f2c2c032" +dependencies = [ + "bitflags 2.9.1", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-scanner", +] + +[[package]] +name = "wayland-protocols-wlr" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efd94963ed43cf9938a090ca4f7da58eb55325ec8200c3848963e98dc25b78ec" +dependencies = [ + "bitflags 2.9.1", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-scanner", +] + +[[package]] +name = "wayland-scanner" +version = "0.31.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54cb1e9dc49da91950bdfd8b848c49330536d9d1fb03d4bfec8cae50caa50ae3" +dependencies = [ + "proc-macro2", + "quick-xml", + "quote", +] + +[[package]] +name = "wayland-sys" +version = "0.31.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34949b42822155826b41db8e5d0c1be3a2bd296c747577a43a3e6daefc296142" +dependencies = [ + "dlib", + "log", + "once_cell", + "pkg-config", +] + +[[package]] +name = "web-sys" +version = "0.3.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "winapi-util" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "windows-link" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" + +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets 0.42.2", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets 0.53.3", +] + +[[package]] +name = "windows-targets" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm 0.52.6", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.53.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91" +dependencies = [ + "windows-link", + "windows_aarch64_gnullvm 0.53.0", + "windows_aarch64_msvc 0.53.0", + "windows_i686_gnu 0.53.0", + "windows_i686_gnullvm 0.53.0", + "windows_i686_msvc 0.53.0", + "windows_x86_64_gnu 0.53.0", + "windows_x86_64_gnullvm 0.53.0", + "windows_x86_64_msvc 0.53.0", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" + +[[package]] +name = "windows_i686_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" + +[[package]] +name = "windows_i686_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_i686_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" + +[[package]] +name = "winit" +version = "0.30.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c66d4b9ed69c4009f6321f762d6e61ad8a2389cd431b97cb1e146812e9e6c732" +dependencies = [ + "ahash", + "android-activity", + "atomic-waker", + "bitflags 2.9.1", + "block2", + "bytemuck", + "calloop", + "cfg_aliases", + "concurrent-queue", + "core-foundation", + "core-graphics", + "cursor-icon", + "dpi", + "js-sys", + "libc", + "memmap2", + "ndk", + "objc2", + "objc2-app-kit", + "objc2-foundation", + "objc2-ui-kit", + "orbclient", + "percent-encoding", + "pin-project", + "raw-window-handle", + "redox_syscall 0.4.1", + "rustix 0.38.44", + "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", + "x11-dl", + "x11rb", + "xkbcommon-dl", +] + +[[package]] +name = "winnow" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3edebf492c8125044983378ecb5766203ad3b4c2f7a922bd7dd207f6d443e95" +dependencies = [ + "memchr", +] + +[[package]] +name = "wit-bindgen-rt" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" +dependencies = [ + "bitflags 2.9.1", +] + +[[package]] +name = "x11-dl" +version = "2.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38735924fedd5314a6e548792904ed8c6de6636285cb9fec04d5b1db85c1516f" +dependencies = [ + "libc", + "once_cell", + "pkg-config", +] + +[[package]] +name = "x11rb" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d91ffca73ee7f68ce055750bf9f6eca0780b8c85eff9bc046a3b0da41755e12" +dependencies = [ + "as-raw-xcb-connection", + "gethostname", + "libc", + "libloading", + "once_cell", + "rustix 0.38.44", + "x11rb-protocol", +] + +[[package]] +name = "x11rb-protocol" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec107c4503ea0b4a98ef47356329af139c0a4f7750e621cf2973cd3385ebcb3d" + +[[package]] +name = "xcursor" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bec9e4a500ca8864c5b47b8b482a73d62e4237670e5b5f1d6b9e3cae50f28f2b" + +[[package]] +name = "xkbcommon-dl" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d039de8032a9a8856a6be89cea3e5d12fdd82306ab7c94d74e6deab2460651c5" +dependencies = [ + "bitflags 2.9.1", + "dlib", + "log", + "once_cell", + "xkeysym", +] + +[[package]] +name = "xkeysym" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9cc00251562a284751c9973bace760d86c0276c471b4be569fe6b068ee97a56" + +[[package]] +name = "zerocopy" +version = "0.8.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff --git a/raidillon_platform/Cargo.toml b/raidillon_platform/Cargo.toml new file mode 100644 index 0000000..92e8df0 --- /dev/null +++ b/raidillon_platform/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "raidillon_platform" +version = "0.1.0" +edition = "2024" + +[dependencies] +winit = "0.30.12" diff --git a/raidillon_platform/src/assets.rs b/raidillon_platform/src/assets.rs new file mode 100644 index 0000000..8c1a2ae --- /dev/null +++ b/raidillon_platform/src/assets.rs @@ -0,0 +1,11 @@ +use std::path::Path; + +pub type ModelHandle = usize; + +/// The asset manager trait of Raidillon. +pub trait AssetManager { + /// Loads a gltf model to VRAM. + fn load_gltf(&mut self, path: &Path) -> ModelHandle; + /// Unloads the loaded model from VRAM. + fn unload_model(&mut self, model_handle: ModelHandle); +} diff --git a/raidillon_platform/src/context.rs b/raidillon_platform/src/context.rs new file mode 100644 index 0000000..ff2e30e --- /dev/null +++ b/raidillon_platform/src/context.rs @@ -0,0 +1,11 @@ +use winit::event::Event; +use crate::AssetManager; + +pub struct FrameContext { + pub event: Event<()>, +} + +pub struct PlatformContext { + pub frame_context: FrameContext, + pub asset_manager: dyn AssetManager, +} diff --git a/raidillon_platform/src/event.rs b/raidillon_platform/src/event.rs new file mode 100644 index 0000000..82ce8b6 --- /dev/null +++ b/raidillon_platform/src/event.rs @@ -0,0 +1,11 @@ +pub enum PlatformEvent { + /// Emmited when the window should + RedrawRequested, + + /// The platform has requested to close the app. + CloseRequested, + + /// Platform event loop is about to block and wait for new + /// new events. + AboutToWait +} diff --git a/raidillon_platform/src/lib.rs b/raidillon_platform/src/lib.rs new file mode 100644 index 0000000..ddce345 --- /dev/null +++ b/raidillon_platform/src/lib.rs @@ -0,0 +1,7 @@ +pub mod platform; +pub mod assets; +pub mod context; + +pub use context::PlatformContext; +pub use assets::AssetManager; +pub use platform::Platform; diff --git a/raidillon_platform/src/platform.rs b/raidillon_platform/src/platform.rs new file mode 100644 index 0000000..ae3ce4e --- /dev/null +++ b/raidillon_platform/src/platform.rs @@ -0,0 +1,5 @@ + +pub trait Platform { + /// Initialize platform. + fn initialize(title: String, width: u32, height: u32) -> Self; +} From e817abf8ab68bb8167da8c4a1c4b68c2034e8006 Mon Sep 17 00:00:00 2001 From: reo Date: Thu, 7 Aug 2025 17:56:35 +0300 Subject: [PATCH 27/89] Continue new platform/glium implementations - Assets, asset manager system - Rendering system trait - Kick off glium platform implementation - And more --- .gitignore | 1 + Cargo.lock | 2270 +++++++++++++++++++++++++++ Cargo.toml | 6 + raidillon_core/Cargo.lock | 113 ++ raidillon_core/Cargo.toml | 1 + raidillon_core/src/lib.rs | 2 + raidillon_core/src/scene.rs | 30 + raidillon_glium/Cargo.lock | 6 + raidillon_glium/Cargo.toml | 2 + raidillon_glium/src/assets.rs | 51 +- raidillon_glium/src/lib.rs | 3 + raidillon_glium/src/platform.rs | 35 +- raidillon_glium/src/render/basic.rs | 12 + raidillon_glium/src/render/mod.rs | 2 + raidillon_glium/src/system.rs | 35 + raidillon_platform/src/assets.rs | 8 +- raidillon_platform/src/context.rs | 10 +- raidillon_platform/src/platform.rs | 2 +- 18 files changed, 2557 insertions(+), 32 deletions(-) create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 raidillon_core/src/scene.rs create mode 100644 raidillon_glium/src/render/basic.rs create mode 100644 raidillon_glium/src/render/mod.rs create mode 100644 raidillon_glium/src/system.rs diff --git a/.gitignore b/.gitignore index e1df7ae..84b7805 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ target/ *.patch +.idea/ \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..8dd4c8f --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,2270 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "ab_glyph" +version = "0.2.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e074464580a518d16a7126262fffaaa47af89d4099d4cb403f8ed938ba12ee7d" +dependencies = [ + "ab_glyph_rasterizer", + "owned_ttf_parser", +] + +[[package]] +name = "ab_glyph_rasterizer" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2187590a23ab1e3df8681afdf0987c48504d80291f002fcdb651f0ef5e25169" + +[[package]] +name = "addr2line" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" + +[[package]] +name = "ahash" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" +dependencies = [ + "cfg-if", + "getrandom", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "android-activity" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef6978589202a00cd7e118380c448a08b6ed394c3a8df3a430d0898e3a42d046" +dependencies = [ + "android-properties", + "bitflags 2.9.1", + "cc", + "cesu8", + "jni", + "jni-sys", + "libc", + "log", + "ndk", + "ndk-context", + "ndk-sys", + "num_enum", + "thiserror", +] + +[[package]] +name = "android-properties" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc7eb209b1518d6bb87b283c20095f5228ecda460da70b44f0802523dea6da04" + +[[package]] +name = "anyhow" +version = "1.0.98" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" + +[[package]] +name = "arrayref" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" + +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + +[[package]] +name = "as-raw-xcb-connection" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "175571dd1d178ced59193a6fc02dde1b972eb0bc56c892cde9beeceac5bf0f6b" + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + +[[package]] +name = "backtrace" +version = "0.3.75" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" +dependencies = [ + "addr2line", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", + "windows-targets 0.52.6", +] + +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" + +[[package]] +name = "block2" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c132eebf10f5cad5289222520a4a058514204aed6d791f1cf4fe8088b82d15f" +dependencies = [ + "objc2 0.5.2", +] + +[[package]] +name = "bumpalo" +version = "3.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" + +[[package]] +name = "bytemuck" +version = "1.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c76a5792e44e4abe34d3abf15636779261d45a7450612059293d1d2cfc63422" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "byteorder-lite" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" + +[[package]] +name = "bytes" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" + +[[package]] +name = "calloop" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b99da2f8558ca23c71f4fd15dc57c906239752dd27ff3c00a1d56b685b7cbfec" +dependencies = [ + "bitflags 2.9.1", + "log", + "polling", + "rustix 0.38.44", + "slab", + "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 0.38.44", + "wayland-backend", + "wayland-client", +] + +[[package]] +name = "cc" +version = "1.2.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3a42d84bb6b69d3a8b3eaacf0d88f179e1929695e1ad012b6cf64d9caaa5fd2" +dependencies = [ + "jobserver", + "libc", + "shlex", +] + +[[package]] +name = "cesu8" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" + +[[package]] +name = "cfg-if" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" + +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + +[[package]] +name = "cgl" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ced0551234e87afee12411d535648dd89d2e7f34c78b753395567aff3d447ff" +dependencies = [ + "libc", +] + +[[package]] +name = "combine" +version = "4.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" +dependencies = [ + "bytes", + "memchr", +] + +[[package]] +name = "concurrent-queue" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "core-graphics" +version = "0.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c07782be35f9e1140080c6b96f0d44b739e2278479f64e02fdab4e32dfd8b081" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "core-graphics-types", + "foreign-types", + "libc", +] + +[[package]] +name = "core-graphics-types" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "libc", +] + +[[package]] +name = "crc32fast" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + +[[package]] +name = "cursor-icon" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f27ae1dd37df86211c42e150270f82743308803d90a6f6e6651cd730d5e1732f" + +[[package]] +name = "dispatch" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" + +[[package]] +name = "dispatch2" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89a09f22a6c6069a18470eb92d2298acf25463f14256d24778e1230d789a2aec" +dependencies = [ + "bitflags 2.9.1", + "objc2 0.6.1", +] + +[[package]] +name = "dlib" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "330c60081dcc4c72131f8eb70510f1ac07223e5d4163db481a04a0befcffa412" +dependencies = [ + "libloading", +] + +[[package]] +name = "downcast-rs" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" + +[[package]] +name = "dpi" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8b14ccef22fc6f5a8f4d7d768562a182c04ce9a3b3157b91390b52ddfdf1a76" + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "errno" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad" +dependencies = [ + "libc", + "windows-sys 0.60.2", +] + +[[package]] +name = "fdeflate" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c" +dependencies = [ + "simd-adler32", +] + +[[package]] +name = "flate2" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a3d7db9596fecd151c5f638c0ee5d5bd487b6e0ea232e5dc96d5250f6f94b1d" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foreign-types" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965" +dependencies = [ + "foreign-types-macros", + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-macros" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "foreign-types-shared" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" + +[[package]] +name = "gethostname" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0176e0459c2e4a1fe232f984bca6890e681076abb9934f6cea7c326f3fc47818" +dependencies = [ + "libc", + "windows-targets 0.48.5", +] + +[[package]] +name = "getrandom" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasi", +] + +[[package]] +name = "gimli" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" + +[[package]] +name = "gl_generator" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a95dfc23a2b4a9a2f5ab41d194f8bfda3cabec42af4e39f08c339eb2a0c124d" +dependencies = [ + "khronos_api", + "log", + "xml-rs", +] + +[[package]] +name = "glam" +version = "0.30.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2d1aab06663bdce00d6ca5e5ed586ec8d18033a771906c993a1e3755b368d85" + +[[package]] +name = "glium" +version = "0.35.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a3028d1f135b5395e6e4336916b424bc5dd2b38c6e378ce2704e4b8f4a617ed" +dependencies = [ + "backtrace", + "fnv", + "gl_generator", + "glutin", + "glutin-winit", + "memoffset", + "raw-window-handle", + "smallvec", + "winit", +] + +[[package]] +name = "gltf" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3ce1918195723ce6ac74e80542c5a96a40c2b26162c1957a5cd70799b8cacf7" +dependencies = [ + "base64", + "byteorder", + "gltf-json", + "image", + "lazy_static", + "serde_json", + "urlencoding", +] + +[[package]] +name = "gltf-derive" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14070e711538afba5d6c807edb74bcb84e5dbb9211a3bf5dea0dfab5b24f4c51" +dependencies = [ + "inflections", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "gltf-json" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6176f9d60a7eab0a877e8e96548605dedbde9190a7ae1e80bbcc1c9af03ab14" +dependencies = [ + "gltf-derive", + "serde", + "serde_derive", + "serde_json", +] + +[[package]] +name = "glutin" +version = "0.32.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12124de845cacfebedff80e877bb37b5b75c34c5a4c89e47e1cdd67fb6041325" +dependencies = [ + "bitflags 2.9.1", + "cfg_aliases", + "cgl", + "dispatch2", + "glutin_egl_sys", + "glutin_glx_sys", + "glutin_wgl_sys", + "libloading", + "objc2 0.6.1", + "objc2-app-kit 0.3.1", + "objc2-core-foundation", + "objc2-foundation 0.3.1", + "once_cell", + "raw-window-handle", + "wayland-sys", + "windows-sys 0.52.0", + "x11-dl", +] + +[[package]] +name = "glutin-winit" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85edca7075f8fc728f28cb8fbb111a96c3b89e930574369e3e9c27eb75d3788f" +dependencies = [ + "cfg_aliases", + "glutin", + "raw-window-handle", + "winit", +] + +[[package]] +name = "glutin_egl_sys" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c4680ba6195f424febdc3ba46e7a42a0e58743f2edb115297b86d7f8ecc02d2" +dependencies = [ + "gl_generator", + "windows-sys 0.52.0", +] + +[[package]] +name = "glutin_glx_sys" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a7bb2938045a88b612499fbcba375a77198e01306f52272e692f8c1f3751185" +dependencies = [ + "gl_generator", + "x11-dl", +] + +[[package]] +name = "glutin_wgl_sys" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c4ee00b289aba7a9e5306d57c2d05499b2e5dc427f84ac708bd2c090212cf3e" +dependencies = [ + "gl_generator", +] + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +dependencies = [ + "ahash", +] + +[[package]] +name = "hashbrown" +version = "0.15.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5" + +[[package]] +name = "hecs" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cbc675ee8d97b4d206a985137f8ad59666538f56f906474f554467a63c776d" +dependencies = [ + "hashbrown 0.14.5", + "spin", +] + +[[package]] +name = "hermit-abi" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" + +[[package]] +name = "image" +version = "0.25.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db35664ce6b9810857a38a906215e75a9c879f0696556a39f59c62829710251a" +dependencies = [ + "bytemuck", + "byteorder-lite", + "num-traits", + "png", + "zune-core", + "zune-jpeg", +] + +[[package]] +name = "indexmap" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe4cd85333e22411419a0bcae1297d25e58c9443848b11dc6a86fefe8c78a661" +dependencies = [ + "equivalent", + "hashbrown 0.15.4", +] + +[[package]] +name = "inflections" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a257582fdcde896fd96463bf2d40eefea0580021c0712a0e2b028b60b47a837a" + +[[package]] +name = "itoa" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" + +[[package]] +name = "jni" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" +dependencies = [ + "cesu8", + "cfg-if", + "combine", + "jni-sys", + "log", + "thiserror", + "walkdir", + "windows-sys 0.45.0", +] + +[[package]] +name = "jni-sys" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" + +[[package]] +name = "jobserver" +version = "0.1.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a" +dependencies = [ + "getrandom", + "libc", +] + +[[package]] +name = "js-sys" +version = "0.3.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "khronos_api" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc" + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.174" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776" + +[[package]] +name = "libloading" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667" +dependencies = [ + "cfg-if", + "windows-targets 0.53.3", +] + +[[package]] +name = "libredox" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "391290121bad3d37fbddad76d8f5d1c1c314cfc646d143d7e07a3086ddff0ce3" +dependencies = [ + "bitflags 2.9.1", + "libc", + "redox_syscall 0.5.17", +] + +[[package]] +name = "linux-raw-sys" +version = "0.4.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" + +[[package]] +name = "linux-raw-sys" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" + +[[package]] +name = "log" +version = "0.4.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" + +[[package]] +name = "memchr" +version = "2.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" + +[[package]] +name = "memmap2" +version = "0.9.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "483758ad303d734cec05e5c12b41d7e93e6a6390c5e9dae6bdeb7c1259012d28" +dependencies = [ + "libc", +] + +[[package]] +name = "memoffset" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +dependencies = [ + "autocfg", +] + +[[package]] +name = "miniz_oxide" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", + "simd-adler32", +] + +[[package]] +name = "ndk" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4" +dependencies = [ + "bitflags 2.9.1", + "jni-sys", + "log", + "ndk-sys", + "num_enum", + "raw-window-handle", + "thiserror", +] + +[[package]] +name = "ndk-context" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" + +[[package]] +name = "ndk-sys" +version = "0.6.0+11769913" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee6cda3051665f1fb8d9e08fc35c96d5a244fb1be711a03b71118828afc9a873" +dependencies = [ + "jni-sys", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_enum" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a973b4e44ce6cad84ce69d797acf9a044532e4184c4f267913d1b546a0727b7a" +dependencies = [ + "num_enum_derive", + "rustversion", +] + +[[package]] +name = "num_enum_derive" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77e878c846a8abae00dd069496dbe8751b16ac1c3d6bd2a7283a938e8228f90d" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "objc-sys" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb91bdd390c7ce1a8607f35f3ca7151b65afc0ff5ff3b34fa350f7d7c7e4310" + +[[package]] +name = "objc2" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46a785d4eeff09c14c487497c162e92766fbb3e4059a71840cecc03d9a50b804" +dependencies = [ + "objc-sys", + "objc2-encode", +] + +[[package]] +name = "objc2" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88c6597e14493ab2e44ce58f2fdecf095a51f12ca57bec060a11c57332520551" +dependencies = [ + "objc2-encode", +] + +[[package]] +name = "objc2-app-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4e89ad9e3d7d297152b17d39ed92cd50ca8063a89a9fa569046d41568891eff" +dependencies = [ + "bitflags 2.9.1", + "block2", + "libc", + "objc2 0.5.2", + "objc2-core-data", + "objc2-core-image", + "objc2-foundation 0.2.2", + "objc2-quartz-core", +] + +[[package]] +name = "objc2-app-kit" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6f29f568bec459b0ddff777cec4fe3fd8666d82d5a40ebd0ff7e66134f89bcc" +dependencies = [ + "bitflags 2.9.1", + "objc2 0.6.1", + "objc2-core-foundation", + "objc2-foundation 0.3.1", +] + +[[package]] +name = "objc2-cloud-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74dd3b56391c7a0596a295029734d3c1c5e7e510a4cb30245f8221ccea96b009" +dependencies = [ + "bitflags 2.9.1", + "block2", + "objc2 0.5.2", + "objc2-core-location", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-contacts" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5ff520e9c33812fd374d8deecef01d4a840e7b41862d849513de77e44aa4889" +dependencies = [ + "block2", + "objc2 0.5.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-core-data" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "617fbf49e071c178c0b24c080767db52958f716d9eabdf0890523aeae54773ef" +dependencies = [ + "bitflags 2.9.1", + "block2", + "objc2 0.5.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-core-foundation" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c10c2894a6fed806ade6027bcd50662746363a9589d3ec9d9bef30a4e4bc166" +dependencies = [ + "bitflags 2.9.1", + "dispatch2", + "objc2 0.6.1", +] + +[[package]] +name = "objc2-core-image" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55260963a527c99f1819c4f8e3b47fe04f9650694ef348ffd2227e8196d34c80" +dependencies = [ + "block2", + "objc2 0.5.2", + "objc2-foundation 0.2.2", + "objc2-metal", +] + +[[package]] +name = "objc2-core-location" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "000cfee34e683244f284252ee206a27953279d370e309649dc3ee317b37e5781" +dependencies = [ + "block2", + "objc2 0.5.2", + "objc2-contacts", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-encode" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33" + +[[package]] +name = "objc2-foundation" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8" +dependencies = [ + "bitflags 2.9.1", + "block2", + "dispatch", + "libc", + "objc2 0.5.2", +] + +[[package]] +name = "objc2-foundation" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "900831247d2fe1a09a683278e5384cfb8c80c79fe6b166f9d14bfdde0ea1b03c" +dependencies = [ + "bitflags 2.9.1", + "objc2 0.6.1", + "objc2-core-foundation", +] + +[[package]] +name = "objc2-link-presentation" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1a1ae721c5e35be65f01a03b6d2ac13a54cb4fa70d8a5da293d7b0020261398" +dependencies = [ + "block2", + "objc2 0.5.2", + "objc2-app-kit 0.2.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-metal" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6" +dependencies = [ + "bitflags 2.9.1", + "block2", + "objc2 0.5.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-quartz-core" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a" +dependencies = [ + "bitflags 2.9.1", + "block2", + "objc2 0.5.2", + "objc2-foundation 0.2.2", + "objc2-metal", +] + +[[package]] +name = "objc2-symbols" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a684efe3dec1b305badae1a28f6555f6ddd3bb2c2267896782858d5a78404dc" +dependencies = [ + "objc2 0.5.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-ui-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8bb46798b20cd6b91cbd113524c490f1686f4c4e8f49502431415f3512e2b6f" +dependencies = [ + "bitflags 2.9.1", + "block2", + "objc2 0.5.2", + "objc2-cloud-kit", + "objc2-core-data", + "objc2-core-image", + "objc2-core-location", + "objc2-foundation 0.2.2", + "objc2-link-presentation", + "objc2-quartz-core", + "objc2-symbols", + "objc2-uniform-type-identifiers", + "objc2-user-notifications", +] + +[[package]] +name = "objc2-uniform-type-identifiers" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44fa5f9748dbfe1ca6c0b79ad20725a11eca7c2218bceb4b005cb1be26273bfe" +dependencies = [ + "block2", + "objc2 0.5.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-user-notifications" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76cfcbf642358e8689af64cee815d139339f3ed8ad05103ed5eaf73db8d84cb3" +dependencies = [ + "bitflags 2.9.1", + "block2", + "objc2 0.5.2", + "objc2-core-location", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "object" +version = "0.36.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "orbclient" +version = "0.3.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba0b26cec2e24f08ed8bb31519a9333140a6599b867dac464bb150bdb796fd43" +dependencies = [ + "libredox", +] + +[[package]] +name = "owned_ttf_parser" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36820e9051aca1014ddc75770aab4d68bc1e9e632f0f5627c4086bc216fb583b" +dependencies = [ + "ttf-parser", +] + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "pin-project" +version = "1.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" + +[[package]] +name = "pkg-config" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" + +[[package]] +name = "png" +version = "0.17.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82151a2fc869e011c153adc57cf2789ccb8d9906ce52c0b39a6b5697749d7526" +dependencies = [ + "bitflags 1.3.2", + "crc32fast", + "fdeflate", + "flate2", + "miniz_oxide", +] + +[[package]] +name = "polling" +version = "3.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5bd19146350fe804f7cb2669c851c03d69da628803dab0d98018142aaa5d829" +dependencies = [ + "cfg-if", + "concurrent-queue", + "hermit-abi", + "pin-project-lite", + "rustix 1.0.8", + "windows-sys 0.60.2", +] + +[[package]] +name = "proc-macro-crate" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edce586971a4dfaa28950c6f18ed55e0406c1ab88bbce2c6f6293a7aaba73d35" +dependencies = [ + "toml_edit", +] + +[[package]] +name = "proc-macro2" +version = "1.0.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quick-xml" +version = "0.37.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "331e97a1af0bf59823e6eadffe373d7b27f485be8748f71471c662c1f269b7fb" +dependencies = [ + "memchr", +] + +[[package]] +name = "quote" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "raidillon_core" +version = "0.1.0" +dependencies = [ + "hecs", +] + +[[package]] +name = "raidillon_glium" +version = "0.1.0" +dependencies = [ + "anyhow", + "glam", + "glium", + "gltf", + "raidillon_core", + "raidillon_platform", + "winit", +] + +[[package]] +name = "raidillon_platform" +version = "0.1.0" +dependencies = [ + "winit", +] + +[[package]] +name = "raw-window-handle" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539" + +[[package]] +name = "redox_syscall" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "redox_syscall" +version = "0.5.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77" +dependencies = [ + "bitflags 2.9.1", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace" + +[[package]] +name = "rustix" +version = "0.38.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" +dependencies = [ + "bitflags 2.9.1", + "errno", + "libc", + "linux-raw-sys 0.4.15", + "windows-sys 0.59.0", +] + +[[package]] +name = "rustix" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8" +dependencies = [ + "bitflags 2.9.1", + "errno", + "libc", + "linux-raw-sys 0.9.4", + "windows-sys 0.60.2", +] + +[[package]] +name = "rustversion" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" + +[[package]] +name = "ryu" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +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 = "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 = "serde" +version = "1.0.219" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.219" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.142" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "030fedb782600dcbd6f02d479bf0d817ac3bb40d644745b769d6a96bc3afc5a7" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "simd-adler32" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" + +[[package]] +name = "slab" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04dc19736151f35336d325007ac991178d504a119863a2fcb3758cdb5e52c50d" + +[[package]] +name = "smallvec" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" + +[[package]] +name = "smithay-client-toolkit" +version = "0.19.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3457dea1f0eb631b4034d61d4d8c32074caa6cd1ab2d59f2327bd8461e2c0016" +dependencies = [ + "bitflags 2.9.1", + "calloop", + "calloop-wayland-source", + "cursor-icon", + "libc", + "log", + "memmap2", + "rustix 0.38.44", + "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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd538fb6910ac1099850255cf94a94df6551fbdd602454387d0adb2d1ca6dead" +dependencies = [ + "serde", +] + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + +[[package]] +name = "strict-num" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6637bab7722d379c8b41ba849228d680cc12d0a45ba1fa2b48f2a30577a06731" + +[[package]] +name = "syn" +version = "2.0.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[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 = "toml_datetime" +version = "0.6.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" + +[[package]] +name = "toml_edit" +version = "0.22.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" +dependencies = [ + "indexmap", + "toml_datetime", + "winnow", +] + +[[package]] +name = "tracing" +version = "0.1.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +dependencies = [ + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" + +[[package]] +name = "ttf-parser" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2df906b07856748fa3f6e0ad0cbaa047052d4a7dd609e231c4f72cee8c36f31" + +[[package]] +name = "unicode-ident" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" + +[[package]] +name = "unicode-segmentation" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" + +[[package]] +name = "urlencoding" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "wasi" +version = "0.14.2+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +dependencies = [ + "wit-bindgen-rt", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" +dependencies = [ + "bumpalo", + "log", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" +dependencies = [ + "cfg-if", + "js-sys", + "once_cell", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "wayland-backend" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "673a33c33048a5ade91a6b139580fa174e19fb0d23f396dca9fa15f2e1e49b35" +dependencies = [ + "cc", + "downcast-rs", + "rustix 1.0.8", + "scoped-tls", + "smallvec", + "wayland-sys", +] + +[[package]] +name = "wayland-client" +version = "0.31.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c66a47e840dc20793f2264eb4b3e4ecb4b75d91c0dd4af04b456128e0bdd449d" +dependencies = [ + "bitflags 2.9.1", + "rustix 1.0.8", + "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.9.1", + "cursor-icon", + "wayland-backend", +] + +[[package]] +name = "wayland-cursor" +version = "0.31.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "447ccc440a881271b19e9989f75726d60faa09b95b0200a9b7eb5cc47c3eeb29" +dependencies = [ + "rustix 1.0.8", + "wayland-client", + "xcursor", +] + +[[package]] +name = "wayland-protocols" +version = "0.32.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efa790ed75fbfd71283bd2521a1cfdc022aabcc28bdcff00851f9e4ae88d9901" +dependencies = [ + "bitflags 2.9.1", + "wayland-backend", + "wayland-client", + "wayland-scanner", +] + +[[package]] +name = "wayland-protocols-plasma" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a07a14257c077ab3279987c4f8bb987851bf57081b93710381daea94f2c2c032" +dependencies = [ + "bitflags 2.9.1", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-scanner", +] + +[[package]] +name = "wayland-protocols-wlr" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efd94963ed43cf9938a090ca4f7da58eb55325ec8200c3848963e98dc25b78ec" +dependencies = [ + "bitflags 2.9.1", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-scanner", +] + +[[package]] +name = "wayland-scanner" +version = "0.31.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54cb1e9dc49da91950bdfd8b848c49330536d9d1fb03d4bfec8cae50caa50ae3" +dependencies = [ + "proc-macro2", + "quick-xml", + "quote", +] + +[[package]] +name = "wayland-sys" +version = "0.31.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34949b42822155826b41db8e5d0c1be3a2bd296c747577a43a3e6daefc296142" +dependencies = [ + "dlib", + "log", + "once_cell", + "pkg-config", +] + +[[package]] +name = "web-sys" +version = "0.3.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "winapi-util" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "windows-link" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" + +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets 0.42.2", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets 0.53.3", +] + +[[package]] +name = "windows-targets" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm 0.52.6", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.53.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91" +dependencies = [ + "windows-link", + "windows_aarch64_gnullvm 0.53.0", + "windows_aarch64_msvc 0.53.0", + "windows_i686_gnu 0.53.0", + "windows_i686_gnullvm 0.53.0", + "windows_i686_msvc 0.53.0", + "windows_x86_64_gnu 0.53.0", + "windows_x86_64_gnullvm 0.53.0", + "windows_x86_64_msvc 0.53.0", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" + +[[package]] +name = "windows_i686_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" + +[[package]] +name = "windows_i686_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_i686_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" + +[[package]] +name = "winit" +version = "0.30.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c66d4b9ed69c4009f6321f762d6e61ad8a2389cd431b97cb1e146812e9e6c732" +dependencies = [ + "ahash", + "android-activity", + "atomic-waker", + "bitflags 2.9.1", + "block2", + "bytemuck", + "calloop", + "cfg_aliases", + "concurrent-queue", + "core-foundation", + "core-graphics", + "cursor-icon", + "dpi", + "js-sys", + "libc", + "memmap2", + "ndk", + "objc2 0.5.2", + "objc2-app-kit 0.2.2", + "objc2-foundation 0.2.2", + "objc2-ui-kit", + "orbclient", + "percent-encoding", + "pin-project", + "raw-window-handle", + "redox_syscall 0.4.1", + "rustix 0.38.44", + "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", + "x11-dl", + "x11rb", + "xkbcommon-dl", +] + +[[package]] +name = "winnow" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3edebf492c8125044983378ecb5766203ad3b4c2f7a922bd7dd207f6d443e95" +dependencies = [ + "memchr", +] + +[[package]] +name = "wit-bindgen-rt" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" +dependencies = [ + "bitflags 2.9.1", +] + +[[package]] +name = "x11-dl" +version = "2.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38735924fedd5314a6e548792904ed8c6de6636285cb9fec04d5b1db85c1516f" +dependencies = [ + "libc", + "once_cell", + "pkg-config", +] + +[[package]] +name = "x11rb" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d91ffca73ee7f68ce055750bf9f6eca0780b8c85eff9bc046a3b0da41755e12" +dependencies = [ + "as-raw-xcb-connection", + "gethostname", + "libc", + "libloading", + "once_cell", + "rustix 0.38.44", + "x11rb-protocol", +] + +[[package]] +name = "x11rb-protocol" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec107c4503ea0b4a98ef47356329af139c0a4f7750e621cf2973cd3385ebcb3d" + +[[package]] +name = "xcursor" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bec9e4a500ca8864c5b47b8b482a73d62e4237670e5b5f1d6b9e3cae50f28f2b" + +[[package]] +name = "xkbcommon-dl" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d039de8032a9a8856a6be89cea3e5d12fdd82306ab7c94d74e6deab2460651c5" +dependencies = [ + "bitflags 2.9.1", + "dlib", + "log", + "once_cell", + "xkeysym", +] + +[[package]] +name = "xkeysym" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9cc00251562a284751c9973bace760d86c0276c471b4be569fe6b068ee97a56" + +[[package]] +name = "xml-rs" +version = "0.8.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fd8403733700263c6eb89f192880191f1b83e332f7a20371ddcf421c4a337c7" + +[[package]] +name = "zerocopy" +version = "0.8.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "zune-core" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f423a2c17029964870cfaabb1f13dfab7d092a62a29a89264f4d36990ca414a" + +[[package]] +name = "zune-jpeg" +version = "0.4.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc1f7e205ce79eb2da3cd71c5f55f3589785cb7c79f6a03d1c8d1491bda5d089" +dependencies = [ + "zune-core", +] diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..adb9ac6 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,6 @@ +[workspace] +members = [ + "raidillon_core", + "raidillon_glium", + "raidillon_platform" +] diff --git a/raidillon_core/Cargo.lock b/raidillon_core/Cargo.lock index d279de1..1377fa3 100644 --- a/raidillon_core/Cargo.lock +++ b/raidillon_core/Cargo.lock @@ -2,6 +2,119 @@ # It is not intended for manual editing. version = 4 +[[package]] +name = "ahash" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" +dependencies = [ + "cfg-if", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "cfg-if" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +dependencies = [ + "ahash", +] + +[[package]] +name = "hecs" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cbc675ee8d97b4d206a985137f8ad59666538f56f906474f554467a63c776d" +dependencies = [ + "hashbrown", + "spin", +] + +[[package]] +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "proc-macro2" +version = "1.0.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +dependencies = [ + "proc-macro2", +] + [[package]] name = "raidillon_core" version = "0.1.0" +dependencies = [ + "hecs", +] + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + +[[package]] +name = "syn" +version = "2.0.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "zerocopy" +version = "0.8.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff --git a/raidillon_core/Cargo.toml b/raidillon_core/Cargo.toml index 50eec90..6b2f4ce 100644 --- a/raidillon_core/Cargo.toml +++ b/raidillon_core/Cargo.toml @@ -4,3 +4,4 @@ version = "0.1.0" edition = "2024" [dependencies] +hecs = "0.10.5" diff --git a/raidillon_core/src/lib.rs b/raidillon_core/src/lib.rs index e69de29..82e3bb3 100644 --- a/raidillon_core/src/lib.rs +++ b/raidillon_core/src/lib.rs @@ -0,0 +1,2 @@ +mod scene; +pub use scene::{Scene, SceneManager}; \ No newline at end of file diff --git a/raidillon_core/src/scene.rs b/raidillon_core/src/scene.rs new file mode 100644 index 0000000..ebd272c --- /dev/null +++ b/raidillon_core/src/scene.rs @@ -0,0 +1,30 @@ +pub struct Scene { + title: String, + world: hecs::World, + skybox_texture_path: String, +} + +pub struct SceneManager { + scenes: Vec>, + active_index: usize, +} + +impl SceneManager { + pub fn current(&self) -> &Scene { + self.scenes[self.active_index].as_ref().unwrap() + } + + pub fn current_mut(&mut self) -> &mut Scene { + self.scenes[self.active_index].as_mut().unwrap() + } + + pub fn add_scene(&mut self, scene: Scene) -> usize { + let idx = self.scenes.len(); + self.scenes.push(Some(scene)); + idx + } + + pub fn remove_scene(&mut self, idx: usize) { + self.scenes[idx] = None; + } +} \ No newline at end of file diff --git a/raidillon_glium/Cargo.lock b/raidillon_glium/Cargo.lock index 9bc6b80..4606b6a 100644 --- a/raidillon_glium/Cargo.lock +++ b/raidillon_glium/Cargo.lock @@ -1225,6 +1225,10 @@ version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" +[[package]] +name = "raidillon_core" +version = "0.1.0" + [[package]] name = "raidillon_glium" version = "0.1.0" @@ -1233,7 +1237,9 @@ dependencies = [ "glam", "glium", "gltf", + "raidillon_core", "raidillon_platform", + "winit", ] [[package]] diff --git a/raidillon_glium/Cargo.toml b/raidillon_glium/Cargo.toml index 37c9a16..bf2cb84 100644 --- a/raidillon_glium/Cargo.toml +++ b/raidillon_glium/Cargo.toml @@ -9,3 +9,5 @@ glam = "0.30.5" glium = { version = "0.35.0", features = ["glutin_backend", "simple_window_builder"] } gltf = { version = "1.4.1", features = ["import", "utils", "KHR_texture_transform"] } raidillon_platform = { path = "../raidillon_platform" } +raidillon_core = { path = "../raidillon_core" } +winit = "0.30.12" diff --git a/raidillon_glium/src/assets.rs b/raidillon_glium/src/assets.rs index 8e04c4a..9f4ffc2 100644 --- a/raidillon_glium/src/assets.rs +++ b/raidillon_glium/src/assets.rs @@ -1,30 +1,47 @@ -use raidillon_platform::AssetManager; +use raidillon_platform::assets::AssetManager; use crate::model::Model; -use std::path::Path; -use raidillon_platform::assets::ModelHandle; +use std::path::{Path, PathBuf}; use crate::gltf_loader::load_gltf; use glium::backend::Facade; use std::collections::HashMap; +use std::collections::hash_map::Entry; /// Glium platform asset manager implementation. pub struct GliumAssetManager { - models: Vec>, + models: HashMap, facade: Box, - next_model_id: usize, } -impl AssetManager for GliumAssetManager { - fn load_gltf(&mut self, path: &Path) -> ModelHandle { - let model_id = self.next_model_id; - let model = load_gltf(path, self.facade.as_ref()).unwrap(); - self.models.push(Some(model)); - self.next_model_id += 1; - model_id - } - - fn unload_model(&mut self, model_handle: ModelHandle) { - if model_handle < self.models.len() { - self.models[model_handle] = None; +impl GliumAssetManager { + pub fn new(facade: Box) -> Self { + let models = HashMap::new(); + Self { + models, + facade, + } + } +} + +impl AssetManager for GliumAssetManager { + type Model = Model; + + fn load_gltf(&mut self, path: &Path) { + let model = load_gltf(path, self.facade.as_ref()).unwrap(); + self.models.insert(path.to_path_buf(), model); + } + + fn unload_model(&mut self, path: &Path) { + self.models.remove(&path.to_path_buf()); + } + + fn get_model(&mut self, path: &Path) -> &Self::Model { + let path_buf = path.to_path_buf(); + match self.models.entry(path_buf) { + Entry::Occupied(entry) => entry.into_mut(), + Entry::Vacant(entry) => { + let model = load_gltf(path, self.facade.as_ref()).unwrap(); + entry.insert(model) + } } } } diff --git a/raidillon_glium/src/lib.rs b/raidillon_glium/src/lib.rs index 777462b..6fd924f 100644 --- a/raidillon_glium/src/lib.rs +++ b/raidillon_glium/src/lib.rs @@ -2,6 +2,9 @@ pub mod platform; pub mod assets; pub mod model; pub mod gltf_loader; +pub mod system; +mod render; pub use assets::GliumAssetManager; pub use platform::GliumPlatform; +pub use system::RenderingSystem; diff --git a/raidillon_glium/src/platform.rs b/raidillon_glium/src/platform.rs index dc01ad7..ff1e023 100644 --- a/raidillon_glium/src/platform.rs +++ b/raidillon_glium/src/platform.rs @@ -1,17 +1,24 @@ +use std::sync::{Arc, RwLock}; +use glium::backend::Facade; use raidillon_platform::Platform; use glium::winit::event_loop::EventLoop; use glium::winit::window::Window; use glium::backend::glutin::Display; use glium::glutin::surface::WindowSurface; use glium::backend::glutin::SimpleWindowBuilder; +use crate::system::{RenderingSystemManager, RenderingSystem}; +use winit::event::{Event, WindowEvent}; +use crate::GliumAssetManager; -pub struct GliumPlatform { +pub struct GliumPlatform { event_loop: EventLoop<()>, window: Window, display: Display, + rendering_system_manager: RenderingSystemManager, + asset_manager: Arc>, } -impl Platform for GliumPlatform { +impl Platform for GliumPlatform { fn initialize(title: String, width: u32, height: u32) -> Self { let event_loop = glium::winit::event_loop::EventLoop::builder() .build() @@ -22,10 +29,32 @@ impl Platform for GliumPlatform { .with_inner_size(width, height) .build(&event_loop); + let rendering_system_manager = RenderingSystemManager::new(); + let asset_manager = Arc::new(RwLock::new(GliumAssetManager::new(Box::new(display.clone())))); Self { event_loop, window, - display + display, + rendering_system_manager, + asset_manager, } } + + fn run(self) { + let _ = &self.event_loop.run(move |event, el| { + match event { + Event::WindowEvent { event, .. } => match event { + WindowEvent::CloseRequested => {}, + WindowEvent::RedrawRequested => { + + } + _ => {}, + }, + Event::AboutToWait => { + self.window.request_redraw(); + } + _ => {}, + } + }); + } } diff --git a/raidillon_glium/src/render/basic.rs b/raidillon_glium/src/render/basic.rs new file mode 100644 index 0000000..4536186 --- /dev/null +++ b/raidillon_glium/src/render/basic.rs @@ -0,0 +1,12 @@ +use glium::Surface; +use crate::RenderingSystem; +use crate::system::RenderingContext; + +/// A basic renderer pipeline step. +pub struct BasicRenderingSystem; + +impl RenderingSystem for BasicRenderingSystem { + fn render(ctx: &mut RenderingContext) { + todo!() + } +} diff --git a/raidillon_glium/src/render/mod.rs b/raidillon_glium/src/render/mod.rs new file mode 100644 index 0000000..e2288bc --- /dev/null +++ b/raidillon_glium/src/render/mod.rs @@ -0,0 +1,2 @@ +mod basic; +pub use basic::BasicRenderingSystem; \ No newline at end of file diff --git a/raidillon_glium/src/system.rs b/raidillon_glium/src/system.rs new file mode 100644 index 0000000..9e6fe3d --- /dev/null +++ b/raidillon_glium/src/system.rs @@ -0,0 +1,35 @@ +use std::collections::HashMap; +use raidillon_core::Scene; +use glium::Surface; + +pub struct RenderingContext<'a, S: Surface> { + pub scene: &'a mut Scene, + pub target: &'a mut S, +} + +/// The internal "rendering system" trait of raidillon_glium. +/// This is unrelated to the main System trait in raidillon_core. +pub trait RenderingSystem { + fn render(ctx: &mut RenderingContext); +} + +type SystemID = String; + +pub struct RenderingSystemManager { + pub systems: HashMap>, +} + +impl RenderingSystemManager { + pub fn new() -> Self { + Self { + systems: HashMap::new(), + } + } + pub fn add_system(&mut self, id: SystemID, system: T) { + self.systems.insert(id, Box::new(system)); + } + + pub fn remove_system(&mut self, id: SystemID) { + self.systems.remove(&id); + } +} diff --git a/raidillon_platform/src/assets.rs b/raidillon_platform/src/assets.rs index 8c1a2ae..673487f 100644 --- a/raidillon_platform/src/assets.rs +++ b/raidillon_platform/src/assets.rs @@ -1,11 +1,11 @@ use std::path::Path; -pub type ModelHandle = usize; - /// The asset manager trait of Raidillon. pub trait AssetManager { + type Model; /// Loads a gltf model to VRAM. - fn load_gltf(&mut self, path: &Path) -> ModelHandle; + fn load_gltf(&mut self, path: &Path); /// Unloads the loaded model from VRAM. - fn unload_model(&mut self, model_handle: ModelHandle); + fn unload_model(&mut self, path: &Path); + fn get_model(&mut self, path: &Path) -> &Self::Model; } diff --git a/raidillon_platform/src/context.rs b/raidillon_platform/src/context.rs index ff2e30e..e5a09e4 100644 --- a/raidillon_platform/src/context.rs +++ b/raidillon_platform/src/context.rs @@ -1,11 +1,7 @@ use winit::event::Event; use crate::AssetManager; -pub struct FrameContext { - pub event: Event<()>, -} - -pub struct PlatformContext { - pub frame_context: FrameContext, - pub asset_manager: dyn AssetManager, +pub struct PlatformContext { + pub current_event: Event<()>, + pub asset_manager: AM, } diff --git a/raidillon_platform/src/platform.rs b/raidillon_platform/src/platform.rs index ae3ce4e..2db5a54 100644 --- a/raidillon_platform/src/platform.rs +++ b/raidillon_platform/src/platform.rs @@ -1,5 +1,5 @@ - pub trait Platform { /// Initialize platform. fn initialize(title: String, width: u32, height: u32) -> Self; + fn run(self); } From 1cc63a0dab4eaa537fbce0794150493106d24344 Mon Sep 17 00:00:00 2001 From: reo Date: Thu, 7 Aug 2025 20:07:29 +0300 Subject: [PATCH 28/89] Implement Engine, add compile_shader to rendering systems - Implement the initial version of the run method of the glium platform - Add asset manager to the context of the renderer. I will probably move that to either the engine or somewhere else later. - Other unimportant stuff that I'm too lazy to include here. Early stage commit messages don't really matter anyways. --- Cargo.lock | 1 + raidillon_core/src/engine.rs | 6 ++++++ raidillon_core/src/lib.rs | 5 ++++- raidillon_glium/src/platform.rs | 17 +++++++++++++---- raidillon_glium/src/system.rs | 4 ++++ raidillon_platform/Cargo.toml | 1 + raidillon_platform/src/platform.rs | 4 +++- 7 files changed, 32 insertions(+), 6 deletions(-) create mode 100644 raidillon_core/src/engine.rs diff --git a/Cargo.lock b/Cargo.lock index 8dd4c8f..d778047 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1268,6 +1268,7 @@ dependencies = [ name = "raidillon_platform" version = "0.1.0" dependencies = [ + "raidillon_core", "winit", ] diff --git a/raidillon_core/src/engine.rs b/raidillon_core/src/engine.rs new file mode 100644 index 0000000..91fd6de --- /dev/null +++ b/raidillon_core/src/engine.rs @@ -0,0 +1,6 @@ +use crate::SceneManager; + +pub struct Engine { + scene_manager: SceneManager, + // TODO: Systems +} diff --git a/raidillon_core/src/lib.rs b/raidillon_core/src/lib.rs index 82e3bb3..7f2750e 100644 --- a/raidillon_core/src/lib.rs +++ b/raidillon_core/src/lib.rs @@ -1,2 +1,5 @@ mod scene; -pub use scene::{Scene, SceneManager}; \ No newline at end of file +mod engine; + +pub use scene::{Scene, SceneManager}; +pub use engine::Engine; \ No newline at end of file diff --git a/raidillon_glium/src/platform.rs b/raidillon_glium/src/platform.rs index ff1e023..7e7d776 100644 --- a/raidillon_glium/src/platform.rs +++ b/raidillon_glium/src/platform.rs @@ -1,14 +1,16 @@ use std::sync::{Arc, RwLock}; -use glium::backend::Facade; use raidillon_platform::Platform; use glium::winit::event_loop::EventLoop; use glium::winit::window::Window; use glium::backend::glutin::Display; use glium::glutin::surface::WindowSurface; use glium::backend::glutin::SimpleWindowBuilder; -use crate::system::{RenderingSystemManager, RenderingSystem}; +use glium::Surface; +use crate::system::{RenderingSystemManager, RenderingSystem, RenderingContext}; use winit::event::{Event, WindowEvent}; +use raidillon_core::Engine; use crate::GliumAssetManager; +use crate::render::BasicRenderingSystem; pub struct GliumPlatform { event_loop: EventLoop<()>, @@ -29,8 +31,8 @@ impl Platform for GliumPlatform { .with_inner_size(width, height) .build(&event_loop); - let rendering_system_manager = RenderingSystemManager::new(); let asset_manager = Arc::new(RwLock::new(GliumAssetManager::new(Box::new(display.clone())))); + let rendering_system_manager = RenderingSystemManager::new(); Self { event_loop, window, @@ -40,17 +42,24 @@ impl Platform for GliumPlatform { } } - fn run(self) { + fn run(mut self, engine: Engine) { let _ = &self.event_loop.run(move |event, el| { match event { Event::WindowEvent { event, .. } => match event { WindowEvent::CloseRequested => {}, WindowEvent::RedrawRequested => { + let mut target = self.display.draw(); + target.clear_color(0.0, 0.0, 0.0, 1.0); + // TODO: let mut context; + for (system_id, system) in self.rendering_system_manager.systems.iter_mut() { + todo!(); + } } _ => {}, }, Event::AboutToWait => { + // TODO: Run systems here self.window.request_redraw(); } _ => {}, diff --git a/raidillon_glium/src/system.rs b/raidillon_glium/src/system.rs index 9e6fe3d..8fd8a9e 100644 --- a/raidillon_glium/src/system.rs +++ b/raidillon_glium/src/system.rs @@ -1,16 +1,20 @@ use std::collections::HashMap; +use std::sync::{Arc, RwLock}; use raidillon_core::Scene; use glium::Surface; +use crate::GliumAssetManager; pub struct RenderingContext<'a, S: Surface> { pub scene: &'a mut Scene, pub target: &'a mut S, + pub asset_manager: Arc>, } /// The internal "rendering system" trait of raidillon_glium. /// This is unrelated to the main System trait in raidillon_core. pub trait RenderingSystem { fn render(ctx: &mut RenderingContext); + fn compile_shaders() {} } type SystemID = String; diff --git a/raidillon_platform/Cargo.toml b/raidillon_platform/Cargo.toml index 92e8df0..f411ead 100644 --- a/raidillon_platform/Cargo.toml +++ b/raidillon_platform/Cargo.toml @@ -5,3 +5,4 @@ edition = "2024" [dependencies] winit = "0.30.12" +raidillon_core = { path = "../raidillon_core" } diff --git a/raidillon_platform/src/platform.rs b/raidillon_platform/src/platform.rs index 2db5a54..4042982 100644 --- a/raidillon_platform/src/platform.rs +++ b/raidillon_platform/src/platform.rs @@ -1,5 +1,7 @@ +use raidillon_core::Engine; + pub trait Platform { /// Initialize platform. fn initialize(title: String, width: u32, height: u32) -> Self; - fn run(self); + fn run(self, engine: Engine); } From 8ffa01ad48663257450b27d7888ebfba498ae5b9 Mon Sep 17 00:00:00 2001 From: reo Date: Sun, 10 Aug 2025 13:34:02 +0300 Subject: [PATCH 29/89] Implement the core engine methods --- raidillon_core/src/engine.rs | 54 ++++++++++++++++++++++++++++++++++-- 1 file changed, 52 insertions(+), 2 deletions(-) diff --git a/raidillon_core/src/engine.rs b/raidillon_core/src/engine.rs index 91fd6de..68ecdc2 100644 --- a/raidillon_core/src/engine.rs +++ b/raidillon_core/src/engine.rs @@ -1,6 +1,56 @@ +use std::alloc::System; use crate::SceneManager; +use crate::system::{SystemContext, SystemManager}; +use raidillon_platform::EngineTrait; pub struct Engine { - scene_manager: SceneManager, - // TODO: Systems + pub scene_manager: SceneManager, + pub system_manager: SystemManager, +} + +impl EngineTrait for Engine { + fn new() -> Self { + let scene_manager = SceneManager::new(); + let system_manager = SystemManager::new(); + Self { + scene_manager, + system_manager, + } + } + + /// Run the first frame, load the world. + fn initialize(&mut self) -> bool { + // Engine Loading Stage 1: initialize systems + for (system_id, system) in self.system_manager.systems.iter_mut() { + system.initialize(); + } + + let mut ctx = SystemContext { + scene: self.scene_manager.current_mut(), + }; + + // Engine Loading Stage 2: load world + for (system_id, system) in self.system_manager.systems.iter_mut() { + system.load_world(&mut ctx); + } + + true + } + + /// Runs every frame + fn update(&mut self) { + let mut ctx = SystemContext { + scene: self.scene_manager.current_mut(), + }; + + for (system_id, system) in self.system_manager.systems.iter_mut() { + system.update(&mut ctx); + } + } + + // pub fn build_system_context(&mut self) -> SystemContext { + // SystemContext { + // scene: self.scene_manager.current_mut(), + // } + // } } From 147a9d3a85d1c1ab8ffb127edf5a56710771d8ca Mon Sep 17 00:00:00 2001 From: reo Date: Sun, 10 Aug 2025 13:35:16 +0300 Subject: [PATCH 30/89] Improve Scene & SceneManager system - Implement AsRef and AsMut for Scene - Add "new" method to SceneManager --- raidillon_core/src/scene.rs | 55 +++++++++++++++++++++++++++++-------- 1 file changed, 44 insertions(+), 11 deletions(-) diff --git a/raidillon_core/src/scene.rs b/raidillon_core/src/scene.rs index ebd272c..809c646 100644 --- a/raidillon_core/src/scene.rs +++ b/raidillon_core/src/scene.rs @@ -1,30 +1,63 @@ +use std::collections::HashMap; + pub struct Scene { title: String, world: hecs::World, skybox_texture_path: String, } +impl AsRef for Scene { + fn as_ref(&self) -> &Scene { + &self + } +} + +impl AsMut for Scene { + fn as_mut(&mut self) -> &mut Scene { + self + } +} + +type SceneID = String; + pub struct SceneManager { - scenes: Vec>, - active_index: usize, + scenes: HashMap, + active_scene: Option, } impl SceneManager { + pub fn new() -> Self { + let scenes = HashMap::new(); + Self { + scenes, + active_scene: None, + } + } + pub fn current(&self) -> &Scene { - self.scenes[self.active_index].as_ref().unwrap() + match &self.active_scene { + Some(id) => self.scenes[id].as_ref(), + None => panic!("No active scene"), + } + } pub fn current_mut(&mut self) -> &mut Scene { - self.scenes[self.active_index].as_mut().unwrap() + match &mut self.active_scene { + Some(id) => self.scenes.get_mut(id.as_mut()).unwrap().as_mut(), + None => panic!("No active scene"), + } } - pub fn add_scene(&mut self, scene: Scene) -> usize { - let idx = self.scenes.len(); - self.scenes.push(Some(scene)); - idx + pub fn set_active_scene(&mut self, scene: SceneID) { + self.active_scene = Some(scene); } - pub fn remove_scene(&mut self, idx: usize) { - self.scenes[idx] = None; + pub fn add_scene(&mut self, id: SceneID, scene: Scene) { + self.scenes.insert(id, scene); } -} \ No newline at end of file + + pub fn remove_scene(&mut self, id: SceneID) { + self.scenes.remove(&id); + } +} From 379d54b04871612a35bf3cf49dd2e68ed7d00d07 Mon Sep 17 00:00:00 2001 From: reo Date: Sun, 10 Aug 2025 13:36:25 +0300 Subject: [PATCH 31/89] Use IndexMap in glium rendering systems - Improve RenderingContext - Improve RenderingSystem trait --- raidillon_glium/src/system.rs | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/raidillon_glium/src/system.rs b/raidillon_glium/src/system.rs index 8fd8a9e..60c3527 100644 --- a/raidillon_glium/src/system.rs +++ b/raidillon_glium/src/system.rs @@ -1,39 +1,38 @@ -use std::collections::HashMap; -use std::sync::{Arc, RwLock}; use raidillon_core::Scene; -use glium::Surface; +use glium::Frame; use crate::GliumAssetManager; +use indexmap::IndexMap; -pub struct RenderingContext<'a, S: Surface> { - pub scene: &'a mut Scene, - pub target: &'a mut S, - pub asset_manager: Arc>, +pub struct RenderingContext<'a> { + pub scene: &'a Scene, + pub target: &'a mut Frame, + pub asset_manager: &'a mut GliumAssetManager, } /// The internal "rendering system" trait of raidillon_glium. /// This is unrelated to the main System trait in raidillon_core. pub trait RenderingSystem { - fn render(ctx: &mut RenderingContext); - fn compile_shaders() {} + fn render(&mut self, ctx: &mut RenderingContext); + fn compile_shaders(&mut self) {} } type SystemID = String; -pub struct RenderingSystemManager { - pub systems: HashMap>, +pub struct RenderingSystemManager { + pub systems: IndexMap>, } -impl RenderingSystemManager { +impl RenderingSystemManager { pub fn new() -> Self { Self { - systems: HashMap::new(), + systems: IndexMap::default(), } } - pub fn add_system(&mut self, id: SystemID, system: T) { - self.systems.insert(id, Box::new(system)); + pub fn add_system(&mut self, id: SystemID, system: Box) { + self.systems.insert(id, system); } pub fn remove_system(&mut self, id: SystemID) { - self.systems.remove(&id); + self.systems.shift_remove(&id); } } From 84f8a495b7f36a2c524fe3c0b1e277c9f735e693 Mon Sep 17 00:00:00 2001 From: reo Date: Sun, 10 Aug 2025 13:36:58 +0300 Subject: [PATCH 32/89] Implement core "system" system --- raidillon_core/src/lib.rs | 4 +++- raidillon_core/src/system.rs | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 raidillon_core/src/system.rs diff --git a/raidillon_core/src/lib.rs b/raidillon_core/src/lib.rs index 7f2750e..0527964 100644 --- a/raidillon_core/src/lib.rs +++ b/raidillon_core/src/lib.rs @@ -1,5 +1,7 @@ mod scene; mod engine; +pub mod system; pub use scene::{Scene, SceneManager}; -pub use engine::Engine; \ No newline at end of file +pub use engine::Engine; +pub use system::{System, SystemManager}; diff --git a/raidillon_core/src/system.rs b/raidillon_core/src/system.rs new file mode 100644 index 0000000..fc2b600 --- /dev/null +++ b/raidillon_core/src/system.rs @@ -0,0 +1,35 @@ +use crate::Scene; +use indexmap::IndexMap; + +pub struct SystemContext<'a> { + // TODO: time delta etc. + pub scene: &'a mut Scene, +} + +pub trait System { + /// Initialize the system. + fn initialize(&mut self); + /// Spawn the first entities of the world. + fn load_world(&mut self, ctx: &mut SystemContext); + fn update(&mut self, ctx: &mut SystemContext); +} + +pub type SystemID = String; +pub struct SystemManager { + pub systems: IndexMap>, +} + +impl SystemManager { + pub fn new() -> Self { + let systems = IndexMap::default(); + Self { systems } + } + + pub fn add_system(&mut self, id: SystemID, system: Box) { + self.systems.insert(id, system); + } + + pub fn remove_system(&mut self, id: SystemID) { + self.systems.shift_remove(&id); + } +} \ No newline at end of file From ec04d921e8d72669cb56927d9d109003b99056bf Mon Sep 17 00:00:00 2001 From: reo Date: Sun, 10 Aug 2025 13:37:45 +0300 Subject: [PATCH 33/89] Add indexmap to raidillon_glium --- raidillon_glium/Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/raidillon_glium/Cargo.toml b/raidillon_glium/Cargo.toml index bf2cb84..8625212 100644 --- a/raidillon_glium/Cargo.toml +++ b/raidillon_glium/Cargo.toml @@ -11,3 +11,4 @@ gltf = { version = "1.4.1", features = ["import", "utils", "KHR_texture_transfor raidillon_platform = { path = "../raidillon_platform" } raidillon_core = { path = "../raidillon_core" } winit = "0.30.12" +indexmap = "2.10.0" \ No newline at end of file From 03e8f34dba6afa70b6130ff1bf5b63cbec6ae6fe Mon Sep 17 00:00:00 2001 From: reo Date: Sun, 10 Aug 2025 13:37:58 +0300 Subject: [PATCH 34/89] Add indexmap to raidillon_core --- raidillon_core/Cargo.toml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/raidillon_core/Cargo.toml b/raidillon_core/Cargo.toml index 6b2f4ce..f3f6159 100644 --- a/raidillon_core/Cargo.toml +++ b/raidillon_core/Cargo.toml @@ -5,3 +5,5 @@ edition = "2024" [dependencies] hecs = "0.10.5" +indexmap = "2.10.0" +raidillon_platform = { path = "../raidillon_platform" } From 176ea52ab0f8c762e86eae4777feb9f340e46387 Mon Sep 17 00:00:00 2001 From: reo Date: Sat, 16 Aug 2025 21:24:10 +0300 Subject: [PATCH 35/89] wip: week of changes --- Cargo.lock | 19 ++++++++++ Cargo.toml | 4 ++- raidillon_assets/Cargo.toml | 6 ++++ raidillon_assets/src/lib.rs | 3 ++ .../src/model_manager.rs | 9 +++-- raidillon_core/Cargo.toml | 3 +- raidillon_core/src/engine.rs | 33 ++++++++++++----- raidillon_core/src/scene.rs | 13 ++++++- raidillon_core/src/system.rs | 2 ++ raidillon_game/Cargo.toml | 13 +++++++ raidillon_game/src/main.rs | 35 +++++++++++++++++++ raidillon_glium/Cargo.toml | 1 + raidillon_glium/src/assets.rs | 26 +++++++------- raidillon_glium/src/platform.rs | 31 +++++++++++----- raidillon_glium/src/render/basic.rs | 3 +- raidillon_glium/src/system.rs | 3 +- raidillon_platform/Cargo.toml | 1 + raidillon_platform/src/context.rs | 6 ++-- raidillon_platform/src/lib.rs | 2 -- raidillon_platform/src/platform.rs | 5 +-- 20 files changed, 171 insertions(+), 47 deletions(-) create mode 100644 raidillon_assets/Cargo.toml create mode 100644 raidillon_assets/src/lib.rs rename raidillon_platform/src/assets.rs => raidillon_assets/src/model_manager.rs (64%) create mode 100644 raidillon_game/Cargo.toml create mode 100644 raidillon_game/src/main.rs diff --git a/Cargo.lock b/Cargo.lock index d778047..9cd14d4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1244,11 +1244,27 @@ version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" +[[package]] +name = "raidillon_assets" +version = "0.1.0" + [[package]] name = "raidillon_core" version = "0.1.0" dependencies = [ "hecs", + "indexmap", + "raidillon_assets", + "winit", +] + +[[package]] +name = "raidillon_game" +version = "0.1.0" +dependencies = [ + "raidillon_core", + "raidillon_glium", + "raidillon_platform", ] [[package]] @@ -1259,6 +1275,8 @@ dependencies = [ "glam", "glium", "gltf", + "indexmap", + "raidillon_assets", "raidillon_core", "raidillon_platform", "winit", @@ -1268,6 +1286,7 @@ dependencies = [ name = "raidillon_platform" version = "0.1.0" dependencies = [ + "raidillon_assets", "raidillon_core", "winit", ] diff --git a/Cargo.toml b/Cargo.toml index adb9ac6..ded884a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,5 +2,7 @@ members = [ "raidillon_core", "raidillon_glium", - "raidillon_platform" + "raidillon_platform", + "raidillon_assets", + "raidillon_game" ] diff --git a/raidillon_assets/Cargo.toml b/raidillon_assets/Cargo.toml new file mode 100644 index 0000000..6abd397 --- /dev/null +++ b/raidillon_assets/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "raidillon_assets" +version = "0.1.0" +edition = "2024" + +[dependencies] diff --git a/raidillon_assets/src/lib.rs b/raidillon_assets/src/lib.rs new file mode 100644 index 0000000..71eb407 --- /dev/null +++ b/raidillon_assets/src/lib.rs @@ -0,0 +1,3 @@ +pub mod model_manager; + +pub use crate::model_manager::{ModelManager, ModelManagerRef}; diff --git a/raidillon_platform/src/assets.rs b/raidillon_assets/src/model_manager.rs similarity index 64% rename from raidillon_platform/src/assets.rs rename to raidillon_assets/src/model_manager.rs index 673487f..de7c254 100644 --- a/raidillon_platform/src/assets.rs +++ b/raidillon_assets/src/model_manager.rs @@ -1,11 +1,14 @@ +use std::cell::RefCell; use std::path::Path; +use std::rc::Rc; + +pub type ModelManagerRef = Rc>>; + /// The asset manager trait of Raidillon. -pub trait AssetManager { - type Model; +pub trait ModelManager { /// Loads a gltf model to VRAM. fn load_gltf(&mut self, path: &Path); /// Unloads the loaded model from VRAM. fn unload_model(&mut self, path: &Path); - fn get_model(&mut self, path: &Path) -> &Self::Model; } diff --git a/raidillon_core/Cargo.toml b/raidillon_core/Cargo.toml index f3f6159..2b414ed 100644 --- a/raidillon_core/Cargo.toml +++ b/raidillon_core/Cargo.toml @@ -6,4 +6,5 @@ edition = "2024" [dependencies] hecs = "0.10.5" indexmap = "2.10.0" -raidillon_platform = { path = "../raidillon_platform" } +raidillon_assets = { path = "../raidillon_assets" } +winit = "0.30.12" diff --git a/raidillon_core/src/engine.rs b/raidillon_core/src/engine.rs index 68ecdc2..eae1e74 100644 --- a/raidillon_core/src/engine.rs +++ b/raidillon_core/src/engine.rs @@ -1,25 +1,34 @@ -use std::alloc::System; +use std::cell::RefCell; +use std::rc::Rc; +use winit::event::Event; use crate::SceneManager; use crate::system::{SystemContext, SystemManager}; -use raidillon_platform::EngineTrait; +use raidillon_assets::{ModelManager, ModelManagerRef}; pub struct Engine { pub scene_manager: SceneManager, pub system_manager: SystemManager, + pub assets_model_manager: Option, + winit_event: Option>, } -impl EngineTrait for Engine { - fn new() -> Self { +impl Engine { + /// Initialize the engine. + /// Engine is expected to be initialized after the platform, so reasonably + /// it takes platform-dependent structures while being initialized. + pub fn new() -> Self { let scene_manager = SceneManager::new(); let system_manager = SystemManager::new(); Self { scene_manager, system_manager, + assets_model_manager: None, + winit_event: None, } } /// Run the first frame, load the world. - fn initialize(&mut self) -> bool { + pub fn initialize(&mut self) { // Engine Loading Stage 1: initialize systems for (system_id, system) in self.system_manager.systems.iter_mut() { system.initialize(); @@ -27,20 +36,20 @@ impl EngineTrait for Engine { let mut ctx = SystemContext { scene: self.scene_manager.current_mut(), + event: self.winit_event.clone(), }; // Engine Loading Stage 2: load world for (system_id, system) in self.system_manager.systems.iter_mut() { system.load_world(&mut ctx); } - - true } /// Runs every frame - fn update(&mut self) { + pub fn update(&mut self) { let mut ctx = SystemContext { scene: self.scene_manager.current_mut(), + event: self.winit_event.clone(), }; for (system_id, system) in self.system_manager.systems.iter_mut() { @@ -48,6 +57,14 @@ impl EngineTrait for Engine { } } + pub fn set_winit_event(&mut self, event: Event<()>) { + self.winit_event = Some(event); + } + + pub fn set_model_manager(&mut self, model_manager: ModelManagerRef) { + self.assets_model_manager = Some(model_manager); + } + // pub fn build_system_context(&mut self) -> SystemContext { // SystemContext { // scene: self.scene_manager.current_mut(), diff --git a/raidillon_core/src/scene.rs b/raidillon_core/src/scene.rs index 809c646..be47abd 100644 --- a/raidillon_core/src/scene.rs +++ b/raidillon_core/src/scene.rs @@ -1,9 +1,20 @@ use std::collections::HashMap; +use std::path::{Path, PathBuf}; pub struct Scene { title: String, world: hecs::World, - skybox_texture_path: String, + skybox_texture_path: Option, +} + +impl Scene { + pub fn new(title: String, skybox_texture_path: Option) -> Self { + Self { + title, + world: hecs::World::new(), + skybox_texture_path, + } + } } impl AsRef for Scene { diff --git a/raidillon_core/src/system.rs b/raidillon_core/src/system.rs index fc2b600..3480901 100644 --- a/raidillon_core/src/system.rs +++ b/raidillon_core/src/system.rs @@ -1,9 +1,11 @@ use crate::Scene; use indexmap::IndexMap; +use winit::event::Event; pub struct SystemContext<'a> { // TODO: time delta etc. pub scene: &'a mut Scene, + pub event: Option>, } pub trait System { diff --git a/raidillon_game/Cargo.toml b/raidillon_game/Cargo.toml new file mode 100644 index 0000000..2862874 --- /dev/null +++ b/raidillon_game/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "raidillon_game" +version = "0.1.0" +edition = "2024" + +[features] +default = ["glium"] +glium = ["raidillon_glium"] + +[dependencies] +raidillon_core = { path = "../raidillon_core" } +raidillon_platform = { path = "../raidillon_platform" } +raidillon_glium = { path = "../raidillon_glium", optional = true } diff --git a/raidillon_game/src/main.rs b/raidillon_game/src/main.rs new file mode 100644 index 0000000..c4ca0e7 --- /dev/null +++ b/raidillon_game/src/main.rs @@ -0,0 +1,35 @@ +use raidillon_core::{Engine, Scene}; +use raidillon_platform::Platform; + +#[cfg(feature = "glium")] +use raidillon_glium::GliumPlatform; + +fn main() { + let mut engine = Engine::new(); + // Define systems + // engine.system_manager.add_system("spawn_chunks".to_string(), ChunkSystem); + // engine.system_manager.add_system("movement".to_string(), MovementSystem); + + // Set up the scene + let main_scene_id = "Main".to_owned(); + let mut main_scene = Scene::new( + main_scene_id.clone(), + None, + ); + engine.scene_manager.add_scene(main_scene_id.clone(), main_scene); + engine.scene_manager.set_active_scene(main_scene_id.clone()); + + #[cfg(feature = "glium")] + { + let mut platform = GliumPlatform::initialize( + engine, + "Raidillon".to_string(), + 1920, + 1080, + ); + platform.run() + }; + + #[cfg(not(any(feature = "glium")))] + compile_error!("No platform feature enabled."); +} diff --git a/raidillon_glium/Cargo.toml b/raidillon_glium/Cargo.toml index 8625212..8363ef3 100644 --- a/raidillon_glium/Cargo.toml +++ b/raidillon_glium/Cargo.toml @@ -10,5 +10,6 @@ glium = { version = "0.35.0", features = ["glutin_backend", "simple_window_build gltf = { version = "1.4.1", features = ["import", "utils", "KHR_texture_transform"] } raidillon_platform = { path = "../raidillon_platform" } raidillon_core = { path = "../raidillon_core" } +raidillon_assets = { path = "../raidillon_assets" } winit = "0.30.12" indexmap = "2.10.0" \ No newline at end of file diff --git a/raidillon_glium/src/assets.rs b/raidillon_glium/src/assets.rs index 9f4ffc2..5786059 100644 --- a/raidillon_glium/src/assets.rs +++ b/raidillon_glium/src/assets.rs @@ -1,4 +1,4 @@ -use raidillon_platform::assets::AssetManager; +use raidillon_assets::{ModelManagerRef, ModelManager}; use crate::model::Model; use std::path::{Path, PathBuf}; use crate::gltf_loader::load_gltf; @@ -22,9 +22,7 @@ impl GliumAssetManager { } } -impl AssetManager for GliumAssetManager { - type Model = Model; - +impl ModelManager for GliumAssetManager { fn load_gltf(&mut self, path: &Path) { let model = load_gltf(path, self.facade.as_ref()).unwrap(); self.models.insert(path.to_path_buf(), model); @@ -34,14 +32,14 @@ impl AssetManager for GliumAssetManager { self.models.remove(&path.to_path_buf()); } - fn get_model(&mut self, path: &Path) -> &Self::Model { - let path_buf = path.to_path_buf(); - match self.models.entry(path_buf) { - Entry::Occupied(entry) => entry.into_mut(), - Entry::Vacant(entry) => { - let model = load_gltf(path, self.facade.as_ref()).unwrap(); - entry.insert(model) - } - } - } + // fn get_model(&mut self, path: &Path) -> &Self::Model { + // let path_buf = path.to_path_buf(); + // match self.models.entry(path_buf) { + // Entry::Occupied(entry) => entry.into_mut(), + // Entry::Vacant(entry) => { + // let model = load_gltf(path, self.facade.as_ref()).unwrap(); + // entry.insert(model) + // } + // } + // } } diff --git a/raidillon_glium/src/platform.rs b/raidillon_glium/src/platform.rs index 7e7d776..d72b3c3 100644 --- a/raidillon_glium/src/platform.rs +++ b/raidillon_glium/src/platform.rs @@ -1,3 +1,5 @@ +use std::cell::RefCell; +use std::rc::Rc; use std::sync::{Arc, RwLock}; use raidillon_platform::Platform; use glium::winit::event_loop::EventLoop; @@ -8,20 +10,22 @@ use glium::backend::glutin::SimpleWindowBuilder; use glium::Surface; use crate::system::{RenderingSystemManager, RenderingSystem, RenderingContext}; use winit::event::{Event, WindowEvent}; +use raidillon_assets::{ModelManager, ModelManagerRef}; use raidillon_core::Engine; use crate::GliumAssetManager; use crate::render::BasicRenderingSystem; -pub struct GliumPlatform { +pub struct GliumPlatform { event_loop: EventLoop<()>, window: Window, display: Display, - rendering_system_manager: RenderingSystemManager, - asset_manager: Arc>, + rendering_system_manager: RenderingSystemManager, + asset_manager: ModelManagerRef, + engine: Engine, } -impl Platform for GliumPlatform { - fn initialize(title: String, width: u32, height: u32) -> Self { +impl Platform for GliumPlatform { + fn initialize(mut engine: Engine, title: String, width: u32, height: u32) -> Self { let event_loop = glium::winit::event_loop::EventLoop::builder() .build() .expect("create event-loop"); @@ -31,18 +35,20 @@ impl Platform for GliumPlatform { .with_inner_size(width, height) .build(&event_loop); - let asset_manager = Arc::new(RwLock::new(GliumAssetManager::new(Box::new(display.clone())))); + let asset_manager: ModelManagerRef = Rc::new(RefCell::new(Box::new(GliumAssetManager::new(Box::new(display.clone()))))); let rendering_system_manager = RenderingSystemManager::new(); + engine.set_model_manager(asset_manager.clone()); Self { event_loop, window, display, rendering_system_manager, asset_manager, + engine } } - fn run(mut self, engine: Engine) { + fn run(mut self) { let _ = &self.event_loop.run(move |event, el| { match event { Event::WindowEvent { event, .. } => match event { @@ -51,15 +57,22 @@ impl Platform for GliumPlatform { let mut target = self.display.draw(); target.clear_color(0.0, 0.0, 0.0, 1.0); // TODO: let mut context; + let mut context = RenderingContext { + scene: self.engine.scene_manager.current_mut(), + target: &mut target, + asset_manager: self.asset_manager.clone(), + }; for (system_id, system) in self.rendering_system_manager.systems.iter_mut() { - todo!(); + system.render(&mut context); } + target.finish().unwrap(); } _ => {}, }, Event::AboutToWait => { - // TODO: Run systems here + self.engine.set_winit_event(event.clone()); + self.engine.update(); self.window.request_redraw(); } _ => {}, diff --git a/raidillon_glium/src/render/basic.rs b/raidillon_glium/src/render/basic.rs index 4536186..32d2a5c 100644 --- a/raidillon_glium/src/render/basic.rs +++ b/raidillon_glium/src/render/basic.rs @@ -1,4 +1,3 @@ -use glium::Surface; use crate::RenderingSystem; use crate::system::RenderingContext; @@ -6,7 +5,7 @@ use crate::system::RenderingContext; pub struct BasicRenderingSystem; impl RenderingSystem for BasicRenderingSystem { - fn render(ctx: &mut RenderingContext) { + fn render(&mut self, ctx: &mut RenderingContext) { todo!() } } diff --git a/raidillon_glium/src/system.rs b/raidillon_glium/src/system.rs index 60c3527..a83d79a 100644 --- a/raidillon_glium/src/system.rs +++ b/raidillon_glium/src/system.rs @@ -2,11 +2,12 @@ use raidillon_core::Scene; use glium::Frame; use crate::GliumAssetManager; use indexmap::IndexMap; +use raidillon_assets::ModelManagerRef; pub struct RenderingContext<'a> { pub scene: &'a Scene, pub target: &'a mut Frame, - pub asset_manager: &'a mut GliumAssetManager, + pub asset_manager: ModelManagerRef, } /// The internal "rendering system" trait of raidillon_glium. diff --git a/raidillon_platform/Cargo.toml b/raidillon_platform/Cargo.toml index f411ead..af05ba3 100644 --- a/raidillon_platform/Cargo.toml +++ b/raidillon_platform/Cargo.toml @@ -6,3 +6,4 @@ edition = "2024" [dependencies] winit = "0.30.12" raidillon_core = { path = "../raidillon_core" } +raidillon_assets = { path = "../raidillon_assets" } diff --git a/raidillon_platform/src/context.rs b/raidillon_platform/src/context.rs index e5a09e4..ff3072b 100644 --- a/raidillon_platform/src/context.rs +++ b/raidillon_platform/src/context.rs @@ -1,7 +1,7 @@ use winit::event::Event; -use crate::AssetManager; +use raidillon_assets::{ModelManagerRef, ModelManager}; -pub struct PlatformContext { +pub struct PlatformContext { pub current_event: Event<()>, - pub asset_manager: AM, + pub asset_manager: ModelManagerRef, } diff --git a/raidillon_platform/src/lib.rs b/raidillon_platform/src/lib.rs index ddce345..477c025 100644 --- a/raidillon_platform/src/lib.rs +++ b/raidillon_platform/src/lib.rs @@ -1,7 +1,5 @@ pub mod platform; -pub mod assets; pub mod context; pub use context::PlatformContext; -pub use assets::AssetManager; pub use platform::Platform; diff --git a/raidillon_platform/src/platform.rs b/raidillon_platform/src/platform.rs index 4042982..b0250e4 100644 --- a/raidillon_platform/src/platform.rs +++ b/raidillon_platform/src/platform.rs @@ -1,7 +1,8 @@ +use raidillon_assets::ModelManager; use raidillon_core::Engine; pub trait Platform { /// Initialize platform. - fn initialize(title: String, width: u32, height: u32) -> Self; - fn run(self, engine: Engine); + fn initialize(engine: Engine, title: String, width: u32, height: u32) -> Self; + fn run(self); } From 3458662cfcde3202430d4eb9e41d38a43616363c Mon Sep 17 00:00:00 2001 From: reo Date: Sun, 17 Aug 2025 21:14:59 +0300 Subject: [PATCH 36/89] Rename crate folders to remove raidillon prefix --- Cargo.toml | 10 +++++----- {raidillon_assets => assets}/Cargo.toml | 0 {raidillon_assets => assets}/src/lib.rs | 0 {raidillon_assets => assets}/src/model_manager.rs | 0 {raidillon_core => core}/Cargo.lock | 0 {raidillon_core => core}/Cargo.toml | 2 +- {raidillon_core => core}/src/engine.rs | 0 {raidillon_core => core}/src/lib.rs | 0 {raidillon_core => core}/src/scene.rs | 0 {raidillon_core => core}/src/system.rs | 0 game/Cargo.toml | 13 +++++++++++++ {raidillon_game => game}/src/main.rs | 2 +- {raidillon_glium => glium_platform}/Cargo.lock | 0 {raidillon_glium => glium_platform}/Cargo.toml | 6 +++--- {raidillon_glium => glium_platform}/src/assets.rs | 0 .../src/gltf_loader.rs | 0 {raidillon_glium => glium_platform}/src/lib.rs | 0 {raidillon_glium => glium_platform}/src/model.rs | 0 {raidillon_glium => glium_platform}/src/platform.rs | 5 ++++- .../src/render/basic.rs | 0 .../src/render/mod.rs | 0 {raidillon_glium => glium_platform}/src/system.rs | 4 ++-- {raidillon_platform => platform}/Cargo.lock | 0 {raidillon_platform => platform}/Cargo.toml | 4 ++-- {raidillon_platform => platform}/src/context.rs | 0 {raidillon_platform => platform}/src/event.rs | 0 {raidillon_platform => platform}/src/lib.rs | 0 {raidillon_platform => platform}/src/platform.rs | 0 raidillon_game/Cargo.toml | 13 ------------- 29 files changed, 31 insertions(+), 28 deletions(-) rename {raidillon_assets => assets}/Cargo.toml (100%) rename {raidillon_assets => assets}/src/lib.rs (100%) rename {raidillon_assets => assets}/src/model_manager.rs (100%) rename {raidillon_core => core}/Cargo.lock (100%) rename {raidillon_core => core}/Cargo.toml (72%) rename {raidillon_core => core}/src/engine.rs (100%) rename {raidillon_core => core}/src/lib.rs (100%) rename {raidillon_core => core}/src/scene.rs (100%) rename {raidillon_core => core}/src/system.rs (100%) create mode 100644 game/Cargo.toml rename {raidillon_game => game}/src/main.rs (96%) rename {raidillon_glium => glium_platform}/Cargo.lock (100%) rename {raidillon_glium => glium_platform}/Cargo.toml (67%) rename {raidillon_glium => glium_platform}/src/assets.rs (100%) rename {raidillon_glium => glium_platform}/src/gltf_loader.rs (100%) rename {raidillon_glium => glium_platform}/src/lib.rs (100%) rename {raidillon_glium => glium_platform}/src/model.rs (100%) rename {raidillon_glium => glium_platform}/src/platform.rs (94%) rename {raidillon_glium => glium_platform}/src/render/basic.rs (100%) rename {raidillon_glium => glium_platform}/src/render/mod.rs (100%) rename {raidillon_glium => glium_platform}/src/system.rs (87%) rename {raidillon_platform => platform}/Cargo.lock (100%) rename {raidillon_platform => platform}/Cargo.toml (51%) rename {raidillon_platform => platform}/src/context.rs (100%) rename {raidillon_platform => platform}/src/event.rs (100%) rename {raidillon_platform => platform}/src/lib.rs (100%) rename {raidillon_platform => platform}/src/platform.rs (100%) delete mode 100644 raidillon_game/Cargo.toml diff --git a/Cargo.toml b/Cargo.toml index ded884a..2601dec 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,8 +1,8 @@ [workspace] members = [ - "raidillon_core", - "raidillon_glium", - "raidillon_platform", - "raidillon_assets", - "raidillon_game" + "core", + "glium_platform", + "platform", + "assets", + "game" ] diff --git a/raidillon_assets/Cargo.toml b/assets/Cargo.toml similarity index 100% rename from raidillon_assets/Cargo.toml rename to assets/Cargo.toml diff --git a/raidillon_assets/src/lib.rs b/assets/src/lib.rs similarity index 100% rename from raidillon_assets/src/lib.rs rename to assets/src/lib.rs diff --git a/raidillon_assets/src/model_manager.rs b/assets/src/model_manager.rs similarity index 100% rename from raidillon_assets/src/model_manager.rs rename to assets/src/model_manager.rs diff --git a/raidillon_core/Cargo.lock b/core/Cargo.lock similarity index 100% rename from raidillon_core/Cargo.lock rename to core/Cargo.lock diff --git a/raidillon_core/Cargo.toml b/core/Cargo.toml similarity index 72% rename from raidillon_core/Cargo.toml rename to core/Cargo.toml index 2b414ed..4b234a6 100644 --- a/raidillon_core/Cargo.toml +++ b/core/Cargo.toml @@ -6,5 +6,5 @@ edition = "2024" [dependencies] hecs = "0.10.5" indexmap = "2.10.0" -raidillon_assets = { path = "../raidillon_assets" } +raidillon_assets = { path = "../assets" } winit = "0.30.12" diff --git a/raidillon_core/src/engine.rs b/core/src/engine.rs similarity index 100% rename from raidillon_core/src/engine.rs rename to core/src/engine.rs diff --git a/raidillon_core/src/lib.rs b/core/src/lib.rs similarity index 100% rename from raidillon_core/src/lib.rs rename to core/src/lib.rs diff --git a/raidillon_core/src/scene.rs b/core/src/scene.rs similarity index 100% rename from raidillon_core/src/scene.rs rename to core/src/scene.rs diff --git a/raidillon_core/src/system.rs b/core/src/system.rs similarity index 100% rename from raidillon_core/src/system.rs rename to core/src/system.rs diff --git a/game/Cargo.toml b/game/Cargo.toml new file mode 100644 index 0000000..0c76ce4 --- /dev/null +++ b/game/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "raidillon_game" +version = "0.1.0" +edition = "2024" + +[features] +default = ["glium"] +glium = ["raidillon_glium"] + +[dependencies] +raidillon_core = { path = "../core" } +raidillon_platform = { path = "../platform" } +raidillon_glium = { path = "../glium_platform", optional = true } diff --git a/raidillon_game/src/main.rs b/game/src/main.rs similarity index 96% rename from raidillon_game/src/main.rs rename to game/src/main.rs index c4ca0e7..3b201a7 100644 --- a/raidillon_game/src/main.rs +++ b/game/src/main.rs @@ -12,7 +12,7 @@ fn main() { // Set up the scene let main_scene_id = "Main".to_owned(); - let mut main_scene = Scene::new( + let main_scene = Scene::new( main_scene_id.clone(), None, ); diff --git a/raidillon_glium/Cargo.lock b/glium_platform/Cargo.lock similarity index 100% rename from raidillon_glium/Cargo.lock rename to glium_platform/Cargo.lock diff --git a/raidillon_glium/Cargo.toml b/glium_platform/Cargo.toml similarity index 67% rename from raidillon_glium/Cargo.toml rename to glium_platform/Cargo.toml index 8363ef3..aa35243 100644 --- a/raidillon_glium/Cargo.toml +++ b/glium_platform/Cargo.toml @@ -8,8 +8,8 @@ anyhow = "1.0.98" glam = "0.30.5" glium = { version = "0.35.0", features = ["glutin_backend", "simple_window_builder"] } gltf = { version = "1.4.1", features = ["import", "utils", "KHR_texture_transform"] } -raidillon_platform = { path = "../raidillon_platform" } -raidillon_core = { path = "../raidillon_core" } -raidillon_assets = { path = "../raidillon_assets" } +raidillon_platform = { path = "../platform" } +raidillon_core = { path = "../core" } +raidillon_assets = { path = "../assets" } winit = "0.30.12" indexmap = "2.10.0" \ No newline at end of file diff --git a/raidillon_glium/src/assets.rs b/glium_platform/src/assets.rs similarity index 100% rename from raidillon_glium/src/assets.rs rename to glium_platform/src/assets.rs diff --git a/raidillon_glium/src/gltf_loader.rs b/glium_platform/src/gltf_loader.rs similarity index 100% rename from raidillon_glium/src/gltf_loader.rs rename to glium_platform/src/gltf_loader.rs diff --git a/raidillon_glium/src/lib.rs b/glium_platform/src/lib.rs similarity index 100% rename from raidillon_glium/src/lib.rs rename to glium_platform/src/lib.rs diff --git a/raidillon_glium/src/model.rs b/glium_platform/src/model.rs similarity index 100% rename from raidillon_glium/src/model.rs rename to glium_platform/src/model.rs diff --git a/raidillon_glium/src/platform.rs b/glium_platform/src/platform.rs similarity index 94% rename from raidillon_glium/src/platform.rs rename to glium_platform/src/platform.rs index d72b3c3..f9a6eb9 100644 --- a/raidillon_glium/src/platform.rs +++ b/glium_platform/src/platform.rs @@ -52,7 +52,10 @@ impl Platform for GliumPlatform { let _ = &self.event_loop.run(move |event, el| { match event { Event::WindowEvent { event, .. } => match event { - WindowEvent::CloseRequested => {}, + WindowEvent::CloseRequested => { + // TODO: Run uninitialize on renderer and engine + el.exit(); + }, WindowEvent::RedrawRequested => { let mut target = self.display.draw(); target.clear_color(0.0, 0.0, 0.0, 1.0); diff --git a/raidillon_glium/src/render/basic.rs b/glium_platform/src/render/basic.rs similarity index 100% rename from raidillon_glium/src/render/basic.rs rename to glium_platform/src/render/basic.rs diff --git a/raidillon_glium/src/render/mod.rs b/glium_platform/src/render/mod.rs similarity index 100% rename from raidillon_glium/src/render/mod.rs rename to glium_platform/src/render/mod.rs diff --git a/raidillon_glium/src/system.rs b/glium_platform/src/system.rs similarity index 87% rename from raidillon_glium/src/system.rs rename to glium_platform/src/system.rs index a83d79a..03d228f 100644 --- a/raidillon_glium/src/system.rs +++ b/glium_platform/src/system.rs @@ -10,8 +10,8 @@ pub struct RenderingContext<'a> { pub asset_manager: ModelManagerRef, } -/// The internal "rendering system" trait of raidillon_glium. -/// This is unrelated to the main System trait in raidillon_core. +/// The internal "rendering system" trait of glium_platform. +/// This is unrelated to the main System trait in core. pub trait RenderingSystem { fn render(&mut self, ctx: &mut RenderingContext); fn compile_shaders(&mut self) {} diff --git a/raidillon_platform/Cargo.lock b/platform/Cargo.lock similarity index 100% rename from raidillon_platform/Cargo.lock rename to platform/Cargo.lock diff --git a/raidillon_platform/Cargo.toml b/platform/Cargo.toml similarity index 51% rename from raidillon_platform/Cargo.toml rename to platform/Cargo.toml index af05ba3..06d4e12 100644 --- a/raidillon_platform/Cargo.toml +++ b/platform/Cargo.toml @@ -5,5 +5,5 @@ edition = "2024" [dependencies] winit = "0.30.12" -raidillon_core = { path = "../raidillon_core" } -raidillon_assets = { path = "../raidillon_assets" } +raidillon_core = { path = "../core" } +raidillon_assets = { path = "../assets" } diff --git a/raidillon_platform/src/context.rs b/platform/src/context.rs similarity index 100% rename from raidillon_platform/src/context.rs rename to platform/src/context.rs diff --git a/raidillon_platform/src/event.rs b/platform/src/event.rs similarity index 100% rename from raidillon_platform/src/event.rs rename to platform/src/event.rs diff --git a/raidillon_platform/src/lib.rs b/platform/src/lib.rs similarity index 100% rename from raidillon_platform/src/lib.rs rename to platform/src/lib.rs diff --git a/raidillon_platform/src/platform.rs b/platform/src/platform.rs similarity index 100% rename from raidillon_platform/src/platform.rs rename to platform/src/platform.rs diff --git a/raidillon_game/Cargo.toml b/raidillon_game/Cargo.toml deleted file mode 100644 index 2862874..0000000 --- a/raidillon_game/Cargo.toml +++ /dev/null @@ -1,13 +0,0 @@ -[package] -name = "raidillon_game" -version = "0.1.0" -edition = "2024" - -[features] -default = ["glium"] -glium = ["raidillon_glium"] - -[dependencies] -raidillon_core = { path = "../raidillon_core" } -raidillon_platform = { path = "../raidillon_platform" } -raidillon_glium = { path = "../raidillon_glium", optional = true } From 9816f14f5376059dae7e11b5d0763d27ee6dd664 Mon Sep 17 00:00:00 2001 From: reo Date: Sun, 17 Aug 2025 21:23:11 +0300 Subject: [PATCH 37/89] Rename assets crate to asset --- Cargo.toml | 2 +- {assets => asset}/Cargo.toml | 0 {assets => asset}/src/lib.rs | 0 {assets => asset}/src/model_manager.rs | 0 core/Cargo.toml | 2 +- glium_platform/Cargo.toml | 2 +- platform/Cargo.toml | 2 +- 7 files changed, 4 insertions(+), 4 deletions(-) rename {assets => asset}/Cargo.toml (100%) rename {assets => asset}/src/lib.rs (100%) rename {assets => asset}/src/model_manager.rs (100%) diff --git a/Cargo.toml b/Cargo.toml index 2601dec..7b2793f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,6 +3,6 @@ members = [ "core", "glium_platform", "platform", - "assets", + "asset", "game" ] diff --git a/assets/Cargo.toml b/asset/Cargo.toml similarity index 100% rename from assets/Cargo.toml rename to asset/Cargo.toml diff --git a/assets/src/lib.rs b/asset/src/lib.rs similarity index 100% rename from assets/src/lib.rs rename to asset/src/lib.rs diff --git a/assets/src/model_manager.rs b/asset/src/model_manager.rs similarity index 100% rename from assets/src/model_manager.rs rename to asset/src/model_manager.rs diff --git a/core/Cargo.toml b/core/Cargo.toml index 4b234a6..7b8bf94 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -6,5 +6,5 @@ edition = "2024" [dependencies] hecs = "0.10.5" indexmap = "2.10.0" -raidillon_assets = { path = "../assets" } +raidillon_assets = { path = "../asset" } winit = "0.30.12" diff --git a/glium_platform/Cargo.toml b/glium_platform/Cargo.toml index aa35243..941ce0e 100644 --- a/glium_platform/Cargo.toml +++ b/glium_platform/Cargo.toml @@ -10,6 +10,6 @@ glium = { version = "0.35.0", features = ["glutin_backend", "simple_window_build gltf = { version = "1.4.1", features = ["import", "utils", "KHR_texture_transform"] } raidillon_platform = { path = "../platform" } raidillon_core = { path = "../core" } -raidillon_assets = { path = "../assets" } +raidillon_assets = { path = "../asset" } winit = "0.30.12" indexmap = "2.10.0" \ No newline at end of file diff --git a/platform/Cargo.toml b/platform/Cargo.toml index 06d4e12..e3369e8 100644 --- a/platform/Cargo.toml +++ b/platform/Cargo.toml @@ -6,4 +6,4 @@ edition = "2024" [dependencies] winit = "0.30.12" raidillon_core = { path = "../core" } -raidillon_assets = { path = "../assets" } +raidillon_assets = { path = "../asset" } From cc7921a5fe389de6d37a476745150b30e4e7cc37 Mon Sep 17 00:00:00 2001 From: reo Date: Sun, 24 Aug 2025 18:49:41 +0300 Subject: [PATCH 38/89] wip: engine enhancements and fixes --- Cargo.lock | 15 +++- Cargo.toml | 3 +- asset/Cargo.toml | 2 - asset/src/lib.rs | 9 ++- asset/src/model_manager.rs | 9 ++- assets/shaders/gl_textured.frag | 34 +++++++++ assets/shaders/gl_textured.vert | 23 ++++++ assets/shaders/skybox.frag | 22 ++++++ assets/shaders/skybox.vert | 15 ++++ core/src/scene.rs | 6 +- core/src/system.rs | 2 +- ecs/Cargo.toml | 8 +++ ecs/src/components.rs | 15 ++++ ecs/src/lib.rs | 3 + game/Cargo.toml | 1 + game/src/main.rs | 29 +++++++- glium_platform/Cargo.toml | 1 + glium_platform/src/assets.rs | 10 ++- glium_platform/src/lib.rs | 2 +- glium_platform/src/model.rs | 1 + glium_platform/src/platform.rs | 19 +++-- glium_platform/src/render/basic.rs | 108 +++++++++++++++++++++++++++-- glium_platform/src/render/mod.rs | 2 +- glium_platform/src/system.rs | 11 +-- platform/Cargo.toml | 1 + platform/src/camera.rs | 24 +++++++ platform/src/lib.rs | 4 +- 27 files changed, 347 insertions(+), 32 deletions(-) create mode 100644 assets/shaders/gl_textured.frag create mode 100644 assets/shaders/gl_textured.vert create mode 100644 assets/shaders/skybox.frag create mode 100644 assets/shaders/skybox.vert create mode 100644 ecs/Cargo.toml create mode 100644 ecs/src/components.rs create mode 100644 ecs/src/lib.rs create mode 100644 platform/src/camera.rs diff --git a/Cargo.lock b/Cargo.lock index 9cd14d4..308e9da 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -75,9 +75,9 @@ checksum = "fc7eb209b1518d6bb87b283c20095f5228ecda460da70b44f0802523dea6da04" [[package]] name = "anyhow" -version = "1.0.98" +version = "1.0.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" +checksum = "b0674a1ddeecb70197781e945de4b3b8ffb61fa939a5597bcf48503737663100" [[package]] name = "arrayref" @@ -1258,10 +1258,19 @@ dependencies = [ "winit", ] +[[package]] +name = "raidillon_ecs" +version = "0.1.0" +dependencies = [ + "glam", + "raidillon_assets", +] + [[package]] name = "raidillon_game" version = "0.1.0" dependencies = [ + "glam", "raidillon_core", "raidillon_glium", "raidillon_platform", @@ -1278,6 +1287,7 @@ dependencies = [ "indexmap", "raidillon_assets", "raidillon_core", + "raidillon_ecs", "raidillon_platform", "winit", ] @@ -1286,6 +1296,7 @@ dependencies = [ name = "raidillon_platform" version = "0.1.0" dependencies = [ + "glam", "raidillon_assets", "raidillon_core", "winit", diff --git a/Cargo.toml b/Cargo.toml index 7b2793f..aedf63e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,5 +4,6 @@ members = [ "glium_platform", "platform", "asset", - "game" + "game", + "ecs" ] diff --git a/asset/Cargo.toml b/asset/Cargo.toml index 6abd397..7b35051 100644 --- a/asset/Cargo.toml +++ b/asset/Cargo.toml @@ -2,5 +2,3 @@ name = "raidillon_assets" version = "0.1.0" edition = "2024" - -[dependencies] diff --git a/asset/src/lib.rs b/asset/src/lib.rs index 71eb407..f0349ac 100644 --- a/asset/src/lib.rs +++ b/asset/src/lib.rs @@ -1,3 +1,10 @@ pub mod model_manager; - pub use crate::model_manager::{ModelManager, ModelManagerRef}; + +pub use crate::model_manager::ModelID; +#[macro_export] +macro_rules! include_shader { + ($path:expr) => { + include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/../assets/shaders/", $path)) + }; +} \ No newline at end of file diff --git a/asset/src/model_manager.rs b/asset/src/model_manager.rs index de7c254..4f1a9bb 100644 --- a/asset/src/model_manager.rs +++ b/asset/src/model_manager.rs @@ -1,14 +1,17 @@ +use std::any::Any; use std::cell::RefCell; -use std::path::Path; +use std::path::{Path, PathBuf}; use std::rc::Rc; pub type ModelManagerRef = Rc>>; - +pub type ModelID = PathBuf; /// The asset manager trait of Raidillon. -pub trait ModelManager { +pub trait ModelManager: Any { /// Loads a gltf model to VRAM. fn load_gltf(&mut self, path: &Path); /// Unloads the loaded model from VRAM. fn unload_model(&mut self, path: &Path); + + fn get_model(&self, id: &ModelID) -> Option<&dyn Any>; } diff --git a/assets/shaders/gl_textured.frag b/assets/shaders/gl_textured.frag new file mode 100644 index 0000000..b264f77 --- /dev/null +++ b/assets/shaders/gl_textured.frag @@ -0,0 +1,34 @@ +#version 330 core + +in vec3 v_normal; +in vec2 v_tex; +in vec3 v_position; + +out vec4 frag_color; + +uniform vec3 u_light; +uniform sampler2D tex; +uniform vec3 color; // base colour factor (acts as solid colour when no texture) + +void main() { + // Combine base texture (or constant white) with colour factor supplied by CPU. + vec3 base_col = texture(tex, v_tex).rgb * color; + + vec3 ambient_color = base_col * 0.2; + vec3 diffuse_color = base_col * 0.6; + vec3 specular_color = vec3(1.0); + + // u_light is the direction **from the light towards the fragment**. + float diffuse = max(dot(normalize(v_normal), normalize(u_light)), 0.0); + + vec3 camera_dir = normalize(-v_position); + vec3 half_dir = normalize(normalize(u_light) + camera_dir); + float specular = pow(max(dot(half_dir, normalize(v_normal)), 0.0), 16.0); + + vec3 result = ambient_color + diffuse * diffuse_color + specular * specular_color; + + // Convert from linear to sRGB for display (approximate γ-correction) + result = pow(result, vec3(1.0 / 2.2)); + + frag_color = vec4(result, 1.0); +} diff --git a/assets/shaders/gl_textured.vert b/assets/shaders/gl_textured.vert new file mode 100644 index 0000000..df2c27d --- /dev/null +++ b/assets/shaders/gl_textured.vert @@ -0,0 +1,23 @@ +#version 330 core + +in vec3 position; +in vec3 normal; +in vec2 tex_coords; + +uniform mat4 model; +uniform mat4 view; +uniform mat4 projection; +uniform vec2 uv_offset; +uniform vec2 uv_scale; + +out vec3 v_normal; +out vec2 v_tex; +out vec3 v_position; + +void main() { + mat4 modelview = view * model; + v_normal = transpose(inverse(mat3(modelview))) * normal; + v_tex = tex_coords * uv_scale + uv_offset; + v_position = (modelview * vec4(position, 1.0)).xyz; + gl_Position = projection * modelview * vec4(position, 1.0); +} diff --git a/assets/shaders/skybox.frag b/assets/shaders/skybox.frag new file mode 100644 index 0000000..8418e54 --- /dev/null +++ b/assets/shaders/skybox.frag @@ -0,0 +1,22 @@ +#version 330 core + +in vec3 direction; + +out vec4 frag_color; + +uniform sampler2D equirect; + +const vec2 inv_atan = vec2(0.15915494309, 0.31830988618); + +vec2 sample_spherical_map(vec3 v) { + vec2 uv = vec2(atan(v.z, v.x), asin(v.y)); + uv *= inv_atan; + uv += 0.5; + return uv; +} + +void main() { + vec2 uv = sample_spherical_map(normalize(direction)); + vec3 color = texture(equirect, uv).rgb; + frag_color = vec4(color, 1.0); +} diff --git a/assets/shaders/skybox.vert b/assets/shaders/skybox.vert new file mode 100644 index 0000000..2db3b53 --- /dev/null +++ b/assets/shaders/skybox.vert @@ -0,0 +1,15 @@ +#version 330 core + +in vec3 position; + +uniform mat4 view; + +uniform mat4 projection; + +out vec3 direction; + +void main() { + direction = position; + vec4 pos = projection * view * vec4(position, 1.0); + gl_Position = pos.xyww; +} diff --git a/core/src/scene.rs b/core/src/scene.rs index be47abd..5014d63 100644 --- a/core/src/scene.rs +++ b/core/src/scene.rs @@ -2,9 +2,9 @@ use std::collections::HashMap; use std::path::{Path, PathBuf}; pub struct Scene { - title: String, - world: hecs::World, - skybox_texture_path: Option, + pub title: String, + pub world: hecs::World, + pub skybox_texture_path: Option, } impl Scene { diff --git a/core/src/system.rs b/core/src/system.rs index 3480901..7bc5a94 100644 --- a/core/src/system.rs +++ b/core/src/system.rs @@ -16,7 +16,7 @@ pub trait System { fn update(&mut self, ctx: &mut SystemContext); } -pub type SystemID = String; +pub type SystemID = &'static str; pub struct SystemManager { pub systems: IndexMap>, } diff --git a/ecs/Cargo.toml b/ecs/Cargo.toml new file mode 100644 index 0000000..0e1efb5 --- /dev/null +++ b/ecs/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "raidillon_ecs" +version = "0.1.0" +edition = "2024" + +[dependencies] +glam = "0.30.5" +raidillon_assets = { path = "../asset" } diff --git a/ecs/src/components.rs b/ecs/src/components.rs new file mode 100644 index 0000000..83bc7df --- /dev/null +++ b/ecs/src/components.rs @@ -0,0 +1,15 @@ +use glam::{Vec3, Quat, Mat4}; +pub use raidillon_assets::ModelID; + +#[derive(Copy, Clone)] +pub struct Transform { + pub translation: Vec3, + pub rotation: Quat, + pub scale: Vec3, +} + +impl Transform { + pub fn matrix(&self) -> Mat4 { + Mat4::from_scale_rotation_translation(self.scale, self.rotation, self.translation) + } +} diff --git a/ecs/src/lib.rs b/ecs/src/lib.rs new file mode 100644 index 0000000..d08fe80 --- /dev/null +++ b/ecs/src/lib.rs @@ -0,0 +1,3 @@ +pub mod components; + +pub use components::{Transform, ModelID}; diff --git a/game/Cargo.toml b/game/Cargo.toml index 0c76ce4..835bf39 100644 --- a/game/Cargo.toml +++ b/game/Cargo.toml @@ -11,3 +11,4 @@ glium = ["raidillon_glium"] raidillon_core = { path = "../core" } raidillon_platform = { path = "../platform" } raidillon_glium = { path = "../glium_platform", optional = true } +glam = "0.30.5" \ No newline at end of file diff --git a/game/src/main.rs b/game/src/main.rs index 3b201a7..e0403c7 100644 --- a/game/src/main.rs +++ b/game/src/main.rs @@ -1,14 +1,39 @@ -use raidillon_core::{Engine, Scene}; -use raidillon_platform::Platform; +use glam::Vec3; +use raidillon_core::{Engine, Scene, System}; +use raidillon_core::system::SystemContext; +use raidillon_platform::{Platform, Camera}; #[cfg(feature = "glium")] use raidillon_glium::GliumPlatform; +const RENDERING_TEST_SYSTEM: &str = "rendering_test_system"; +struct RenderingTestSystem; + +impl System for RenderingTestSystem { + fn initialize(&mut self) {} + fn load_world(&mut self, ctx: &mut SystemContext) { + ctx.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: 1920 as f32 / 1080 as f32, // FIXME + znear: 0.1, + zfar: 100.0, + },)); + + // TODO: Load a sample glTF file + } + + fn update(&mut self, ctx: &mut SystemContext) {} +} + fn main() { let mut engine = Engine::new(); // Define systems // engine.system_manager.add_system("spawn_chunks".to_string(), ChunkSystem); // engine.system_manager.add_system("movement".to_string(), MovementSystem); + engine.system_manager.add_system(RENDERING_TEST_SYSTEM, Box::new(RenderingTestSystem)); // Set up the scene let main_scene_id = "Main".to_owned(); diff --git a/glium_platform/Cargo.toml b/glium_platform/Cargo.toml index 941ce0e..c206b4e 100644 --- a/glium_platform/Cargo.toml +++ b/glium_platform/Cargo.toml @@ -11,5 +11,6 @@ gltf = { version = "1.4.1", features = ["import", "utils", "KHR_texture_transfor raidillon_platform = { path = "../platform" } raidillon_core = { path = "../core" } raidillon_assets = { path = "../asset" } +raidillon_ecs = { path = "../ecs" } winit = "0.30.12" indexmap = "2.10.0" \ No newline at end of file diff --git a/glium_platform/src/assets.rs b/glium_platform/src/assets.rs index 5786059..6d33887 100644 --- a/glium_platform/src/assets.rs +++ b/glium_platform/src/assets.rs @@ -1,3 +1,5 @@ +use std::any::Any; +use std::cell::RefCell; use raidillon_assets::{ModelManagerRef, ModelManager}; use crate::model::Model; use std::path::{Path, PathBuf}; @@ -5,10 +7,12 @@ use crate::gltf_loader::load_gltf; use glium::backend::Facade; use std::collections::HashMap; use std::collections::hash_map::Entry; +use std::rc::Rc; +use raidillon_assets::model_manager::ModelID; /// Glium platform asset manager implementation. pub struct GliumAssetManager { - models: HashMap, + pub models: HashMap, facade: Box, } @@ -42,4 +46,8 @@ impl ModelManager for GliumAssetManager { // } // } // } + + fn get_model(&self, id: &ModelID) -> Option<&dyn Any> { + self.models.get(id).map(|model| model as &dyn Any) + } } diff --git a/glium_platform/src/lib.rs b/glium_platform/src/lib.rs index 6fd924f..7d91b4d 100644 --- a/glium_platform/src/lib.rs +++ b/glium_platform/src/lib.rs @@ -5,6 +5,6 @@ pub mod gltf_loader; pub mod system; mod render; -pub use assets::GliumAssetManager; +pub use assets::{GliumAssetManager}; pub use platform::GliumPlatform; pub use system::RenderingSystem; diff --git a/glium_platform/src/model.rs b/glium_platform/src/model.rs index 815cd96..1d18dd8 100644 --- a/glium_platform/src/model.rs +++ b/glium_platform/src/model.rs @@ -1,3 +1,4 @@ +use std::any::{Any, TypeId}; use glium::{IndexBuffer, VertexBuffer, implement_vertex}; use glium::texture::{SrgbTexture2d, Texture2d}; use glium::uniforms::SamplerBehavior; diff --git a/glium_platform/src/platform.rs b/glium_platform/src/platform.rs index f9a6eb9..69b0735 100644 --- a/glium_platform/src/platform.rs +++ b/glium_platform/src/platform.rs @@ -1,5 +1,6 @@ use std::cell::RefCell; use std::rc::Rc; +use std::str::FromStr; use std::sync::{Arc, RwLock}; use raidillon_platform::Platform; use glium::winit::event_loop::EventLoop; @@ -8,12 +9,14 @@ use glium::backend::glutin::Display; use glium::glutin::surface::WindowSurface; use glium::backend::glutin::SimpleWindowBuilder; use glium::Surface; -use crate::system::{RenderingSystemManager, RenderingSystem, RenderingContext}; +use crate::system::{RenderingSystemManager, RenderingSystem, RenderingContext, SystemID}; use winit::event::{Event, WindowEvent}; use raidillon_assets::{ModelManager, ModelManagerRef}; use raidillon_core::Engine; -use crate::GliumAssetManager; -use crate::render::BasicRenderingSystem; +use crate::{GliumAssetManager}; +use crate::render::BasicMeshRenderingSystem; + +pub const MESH_RENDERER: &str = "mesh_renderer"; pub struct GliumPlatform { event_loop: EventLoop<()>, @@ -36,8 +39,15 @@ impl Platform for GliumPlatform { .build(&event_loop); let asset_manager: ModelManagerRef = Rc::new(RefCell::new(Box::new(GliumAssetManager::new(Box::new(display.clone()))))); - let rendering_system_manager = RenderingSystemManager::new(); + let mut rendering_system_manager = RenderingSystemManager::new(); engine.set_model_manager(asset_manager.clone()); + + // Install rendering systems + rendering_system_manager.add_system( + MESH_RENDERER, + Box::new(BasicMeshRenderingSystem::initialize(&display)) + ); + Self { event_loop, window, @@ -49,6 +59,7 @@ impl Platform for GliumPlatform { } fn run(mut self) { + self.engine.initialize(); let _ = &self.event_loop.run(move |event, el| { match event { Event::WindowEvent { event, .. } => match event { diff --git a/glium_platform/src/render/basic.rs b/glium_platform/src/render/basic.rs index 32d2a5c..66ffadf 100644 --- a/glium_platform/src/render/basic.rs +++ b/glium_platform/src/render/basic.rs @@ -1,11 +1,111 @@ -use crate::RenderingSystem; +use std::any::Any; +use glium::{uniform, Display, Program, Surface}; +use glium::glutin::surface::WindowSurface; +use glium::texture::{RawImage2d, SrgbTexture2d}; +use crate::{GliumAssetManager, RenderingSystem}; use crate::system::RenderingContext; +use raidillon_assets::include_shader; +pub use raidillon_platform::Camera; +use glam::Vec3; +use glium::uniforms::{MagnifySamplerFilter, MinifySamplerFilter, SamplerWrapFunction}; +use raidillon_ecs::{Transform, ModelID}; +use crate::model::Model; /// A basic renderer pipeline step. -pub struct BasicRenderingSystem; +pub struct BasicMeshRenderingSystem { + program: Program, + white_tex: SrgbTexture2d, + params: glium::DrawParameters<'static>, +} + +impl RenderingSystem for BasicMeshRenderingSystem { + fn initialize(display: &Display) -> Self { + const VERT_SRC: &str = include_shader!("gl_textured.vert"); + const FRAG_SRC: &str = include_shader!("gl_textured.frag"); + + let program = Program::from_source(display, VERT_SRC, FRAG_SRC, None).unwrap(); + + let white_tex = { + let data = vec![255u8, 255u8, 255u8, 255u8]; + let raw = RawImage2d::from_raw_rgba(data, (1, 1)); + SrgbTexture2d::new(display, raw).unwrap() + }; + + let params = glium::DrawParameters { + depth: glium::Depth { + test: glium::draw_parameters::DepthTest::IfLess, + write: true, + .. Default::default() + }, + .. Default::default() + }; + + Self { + program, white_tex, params + } + } -impl RenderingSystem for BasicRenderingSystem { fn render(&mut self, ctx: &mut RenderingContext) { - todo!() + let cam = match ctx.scene.world.query::<&Camera>().iter().next() { + Some((_, cam)) => *cam, + None => { + eprintln!("[renderer] No camera component found. Skipping frame"); + return; + } + }; + + // Direction from the light source (0,+Y) towards the scene. + let light_dir: Vec3 = Vec3::new(0.0, -1.0, 0.0).normalize(); + + // let asset_manager = ctx.asset_manager.borrow(); + // let any_ref: &dyn Any = &**asset_manager; + // if let Some(glium_manager) = any_ref.downcast_ref::() { + // &glium_manager.models; + // } + + let asset_manager = ctx.asset_manager.borrow(); + + for (_, (tr, mh)) in ctx.scene.world.query::<(&Transform, &ModelID)>().iter() { + let model = match asset_manager.get_model(mh) { + Some(model) => model, + _ => continue, + }; + + let model = match model.downcast_ref::() { + Some(model) => model, + None => continue, + }; + + let mesh = &model.mesh; + let mat = &model.material; + + let tex_ref: &SrgbTexture2d = mat.base_color.as_ref().unwrap_or(&self.white_tex); + + let mut sampler = tex_ref.sampled(); + sampler = sampler.wrap_function(SamplerWrapFunction::Repeat); + sampler = sampler.minify_filter(MinifySamplerFilter::Linear); + sampler = sampler.magnify_filter(MagnifySamplerFilter::Linear); + + let c = mat.base_color_factor; + + let uniforms = uniform! { + model: tr.matrix().to_cols_array_2d(), + view: cam.view().to_cols_array_2d(), + projection: cam.projection().to_cols_array_2d(), + u_light: [light_dir.x, light_dir.y, light_dir.z], + tex: sampler, + color: [c[0], c[1], c[2]], + uv_offset: [mat.uv_offset.x, mat.uv_offset.y], + uv_scale: [mat.uv_scale.x, mat.uv_scale.y], + }; + + ctx.target.draw( + &mesh.vbuf, + &mesh.ibuf, + &self.program, + &uniforms, + &self.params, + ).unwrap(); + } } } diff --git a/glium_platform/src/render/mod.rs b/glium_platform/src/render/mod.rs index e2288bc..01028df 100644 --- a/glium_platform/src/render/mod.rs +++ b/glium_platform/src/render/mod.rs @@ -1,2 +1,2 @@ mod basic; -pub use basic::BasicRenderingSystem; \ No newline at end of file +pub use basic::BasicMeshRenderingSystem; \ No newline at end of file diff --git a/glium_platform/src/system.rs b/glium_platform/src/system.rs index 03d228f..63d58b4 100644 --- a/glium_platform/src/system.rs +++ b/glium_platform/src/system.rs @@ -1,8 +1,11 @@ +use std::cell::RefCell; +use std::rc::Rc; use raidillon_core::Scene; -use glium::Frame; -use crate::GliumAssetManager; +use glium::{Display, Frame}; +use glium::glutin::surface::WindowSurface; use indexmap::IndexMap; use raidillon_assets::ModelManagerRef; +use crate::GliumAssetManager; pub struct RenderingContext<'a> { pub scene: &'a Scene, @@ -14,10 +17,10 @@ pub struct RenderingContext<'a> { /// This is unrelated to the main System trait in core. pub trait RenderingSystem { fn render(&mut self, ctx: &mut RenderingContext); - fn compile_shaders(&mut self) {} + fn initialize(display: &Display) -> Self where Self: Sized; } -type SystemID = String; +pub type SystemID = &'static str; pub struct RenderingSystemManager { pub systems: IndexMap>, diff --git a/platform/Cargo.toml b/platform/Cargo.toml index e3369e8..3b42bac 100644 --- a/platform/Cargo.toml +++ b/platform/Cargo.toml @@ -7,3 +7,4 @@ edition = "2024" winit = "0.30.12" raidillon_core = { path = "../core" } raidillon_assets = { path = "../asset" } +glam = "0.30.5" diff --git a/platform/src/camera.rs b/platform/src/camera.rs new file mode 100644 index 0000000..53b3599 --- /dev/null +++ b/platform/src/camera.rs @@ -0,0 +1,24 @@ +use glam::{Mat4, Vec3}; + +#[derive(Copy, Clone)] +pub struct Camera { + pub eye: Vec3, + pub center: Vec3, + pub up: Vec3, + pub fovy: f32, + pub aspect: f32, + pub znear: f32, + pub zfar: f32, +} + +impl Camera { + pub fn view(&self) -> Mat4 { + Mat4::look_at_rh(self.eye, self.center, self.up) + } + pub fn projection(&self) -> Mat4 { + Mat4::perspective_rh(self.fovy, self.aspect, self.znear, self.zfar) + } + pub fn view_proj(&self) -> Mat4 { + self.projection() * self.view() + } +} diff --git a/platform/src/lib.rs b/platform/src/lib.rs index 477c025..0750166 100644 --- a/platform/src/lib.rs +++ b/platform/src/lib.rs @@ -1,5 +1,5 @@ pub mod platform; -pub mod context; +mod camera; -pub use context::PlatformContext; pub use platform::Platform; +pub use camera::Camera; From 3692736a618186f2a3deb2459b65485b1b0af0b0 Mon Sep 17 00:00:00 2001 From: reo Date: Sat, 30 Aug 2025 12:55:42 +0300 Subject: [PATCH 39/89] wip --- Cargo.lock | 2 + asset/src/lib.rs | 14 ++- asset/src/model_manager.rs | 6 +- assets/models/monkey.bin | Bin 0 -> 68720 bytes assets/models/monkey.gltf | 104 +++++++++++++++++++++ assets/models/pink-monkey.bin | Bin 0 -> 68720 bytes assets/models/pink-monkey.gltf | 121 +++++++++++++++++++++++++ assets/models/tree.bin | Bin 0 -> 13584 bytes assets/models/tree.gltf | 140 +++++++++++++++++++++++++++++ assets/models/tree_texture.png | Bin 0 -> 845 bytes {platform => core}/src/context.rs | 2 + core/src/engine.rs | 28 ++---- core/src/lib.rs | 1 + core/src/system.rs | 3 +- ecs/src/components.rs | 2 + game/Cargo.toml | 4 +- game/src/main.rs | 24 ++++- glium_platform/src/assets.rs | 10 +-- glium_platform/src/platform.rs | 23 +++-- glium_platform/src/render/basic.rs | 5 +- platform/src/lib.rs | 1 + platform/src/platform.rs | 1 + 22 files changed, 447 insertions(+), 44 deletions(-) create mode 100644 assets/models/monkey.bin create mode 100644 assets/models/monkey.gltf create mode 100644 assets/models/pink-monkey.bin create mode 100644 assets/models/pink-monkey.gltf create mode 100644 assets/models/tree.bin create mode 100644 assets/models/tree.gltf create mode 100644 assets/models/tree_texture.png rename {platform => core}/src/context.rs (77%) diff --git a/Cargo.lock b/Cargo.lock index 308e9da..0c0aafe 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1271,7 +1271,9 @@ name = "raidillon_game" version = "0.1.0" dependencies = [ "glam", + "raidillon_assets", "raidillon_core", + "raidillon_ecs", "raidillon_glium", "raidillon_platform", ] diff --git a/asset/src/lib.rs b/asset/src/lib.rs index f0349ac..617ced9 100644 --- a/asset/src/lib.rs +++ b/asset/src/lib.rs @@ -1,10 +1,22 @@ pub mod model_manager; + +use std::path::PathBuf; pub use crate::model_manager::{ModelManager, ModelManagerRef}; pub use crate::model_manager::ModelID; + #[macro_export] macro_rules! include_shader { ($path:expr) => { include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/../assets/shaders/", $path)) }; -} \ No newline at end of file +} + +pub fn model_path(path: &str) -> PathBuf { + let manifest_dir = env!("CARGO_MANIFEST_DIR"); + PathBuf::from(manifest_dir) + .join("..") + .join("assets") + .join("models") + .join(path) +} diff --git a/asset/src/model_manager.rs b/asset/src/model_manager.rs index 4f1a9bb..2989a3b 100644 --- a/asset/src/model_manager.rs +++ b/asset/src/model_manager.rs @@ -4,14 +4,14 @@ use std::path::{Path, PathBuf}; use std::rc::Rc; pub type ModelManagerRef = Rc>>; -pub type ModelID = PathBuf; +pub type ModelID = &'static str; /// The asset manager trait of Raidillon. pub trait ModelManager: Any { /// Loads a gltf model to VRAM. - fn load_gltf(&mut self, path: &Path); + fn load_gltf(&mut self, id: ModelID, path: &Path); /// Unloads the loaded model from VRAM. - fn unload_model(&mut self, path: &Path); + fn unload_model(&mut self, id: ModelID); fn get_model(&self, id: &ModelID) -> Option<&dyn Any>; } diff --git a/assets/models/monkey.bin b/assets/models/monkey.bin new file mode 100644 index 0000000000000000000000000000000000000000..e7992f36d75135cc5966e2abe94e5937420da413 GIT binary patch literal 68720 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 literal 0 HcmV?d00001 diff --git a/assets/models/monkey.gltf b/assets/models/monkey.gltf new file mode 100644 index 0000000..d3e2438 --- /dev/null +++ b/assets/models/monkey.gltf @@ -0,0 +1,104 @@ +{ + "asset":{ + "generator":"Khronos glTF Blender I/O v4.4.56", + "version":"2.0" + }, + "scene":0, + "scenes":[ + { + "name":"Scene", + "nodes":[ + 0 + ] + } + ], + "nodes":[ + { + "mesh":0, + "name":"Suzanne" + } + ], + "meshes":[ + { + "name":"Suzanne", + "primitives":[ + { + "attributes":{ + "POSITION":0, + "NORMAL":1, + "TEXCOORD_0":2 + }, + "indices":3 + } + ] + } + ], + "accessors":[ + { + "bufferView":0, + "componentType":5126, + "count":1966, + "max":[ + 1.3671875, + 0.984375, + 0.8515625 + ], + "min":[ + -1.3671875, + -0.984375, + -0.8515625 + ], + "type":"VEC3" + }, + { + "bufferView":1, + "componentType":5126, + "count":1966, + "type":"VEC3" + }, + { + "bufferView":2, + "componentType":5126, + "count":1966, + "type":"VEC2" + }, + { + "bufferView":3, + "componentType":5123, + "count":2904, + "type":"SCALAR" + } + ], + "bufferViews":[ + { + "buffer":0, + "byteLength":23592, + "byteOffset":0, + "target":34962 + }, + { + "buffer":0, + "byteLength":23592, + "byteOffset":23592, + "target":34962 + }, + { + "buffer":0, + "byteLength":15728, + "byteOffset":47184, + "target":34962 + }, + { + "buffer":0, + "byteLength":5808, + "byteOffset":62912, + "target":34963 + } + ], + "buffers":[ + { + "byteLength":68720, + "uri":"monkey.bin" + } + ] +} diff --git a/assets/models/pink-monkey.bin b/assets/models/pink-monkey.bin new file mode 100644 index 0000000000000000000000000000000000000000..2db45966ba391e44f67a7dcc92cd338340566448 GIT binary patch literal 68720 zcmcG%1$Y%l)IPp`ad(0{ln@|5fZRDqfZ*=#5G=Sm6ezSn(V{_GptzO-*#(NVNOAWT zEd`1d&+jbF>~qM&d`!OY|IhQxdEeaoo_FTX&dkp4-GHK8XNr;^OBg6}+$MSnuAuL3 zzoG;oN^ytiC3q6_ZG--45I^FW>%C6+7W}NccPUC%)PKbBvv{vlj(P?CLt^!x<(TVf zWH|aKz!Dzo|5=Wno<@RCL2vi?)Uy9pAFTtP1`d3DODIV+j zK`+7oME^Bd-0>;J(bLmQ@DJxu^sj~fQXD;ZbG-zgh+4Nj_0V66qo=2r;9bz$J-)8L z6h}`_FTve5XOH!l;^^t=CAiz?ZhIQU_W%Fq9NXY|{{O+T?T_)C&BxDYIkv&mNN{(| zyZy<>|7SURdKw9iyFKMH`n%^xS?(S)cf7ej{}&$UC`xFokBBeF&)|M`_eX}8L%qBA zaDQZYWo(0cZgqcT_;LK~nPT-aJQZr);{N%o?e1Sq5pN%x&14}QS0d?xI4y+Vc)p^QXD-!y#(Kd z{vFUi0s2dE^z`%+d?ot#L4OPVr8s(edI=ta{)5mz8Tw0c^z`%++#O@X(BIvI$?)sg zo)qZo_NNp_t*4jZIng&eUV|kZ-U9vIH9rHQ6h}`_ zFTqQq?@RP|_rFpcJw3eye~aGk8XSa0irYjl!Iz_d1@sQZBE`|u(@XH|=S6o?I`%-FaIM>&S~J#T}xT z;JMLvZmho)M^8^L!QHjN?e~I+QXD-!y#&9E-q*3Xb5e@iL@&Wdq4#4f?)o6b(bLmQ zaQ7SuZB?T zZhv+_fA`!Z%fs=Qm5bF=?(RwWb=m)xAIHy|A=XEV<7f2r5?o<;-+{MZhNITgOYjZY z{+XzA`yt*O+wbMZlOMs)QVw(6HCBpa8$G=Q&x*cn@Uyw=s}y&LUV@iF-#Yji-1Se2 zqo=2r;O_C*jsE!&r8s(edI|2%A9v5-wq1&&r>B?T*U>u(db{@uq_|D=5B?T6VbmO`n!7`DUP0=UV=xWe+2sHM1Luc zo}ONUyVnstWBsK#dU|>Z?w*VLpuaoEWO+H91Md3c{`_CKJD$Q~eLlxmqV^dUcTJVz z_}M+Z1b6#31r~R|A;rMu2LM=7*8+3qtM@- z*KYqvarE@`65Jh2TrbO4Vtd^2;QoA$@5c5|L47#tr8u_P(@Svon07&b_q-{^QS0d? z_;qZ50@S(fm*UuFPcOl*(ViNB46{arE)@5BwNZXbrD zzk6LK!`(KNL%q9il;YS1PcOsKzYhB6j`jZ}M<4HX0WXI>&Cti)e@b!m@$?eh?W-2C z{xUoW=S3SV?s-az<6Q9c61*IGXUF2+W0&IS>FFi-8uY%5#oeb#arE@`5_}4JpU2|1 zUy7rrrJ47$R)1mK7^bbOm;^^t=C3qV24M+b# zL@AD*o?e1KLvQ!KfO`*IirYjl!FQwoDD-#ty;2-KJ-r0)g8tXh-<`iw96dd~1P?*~ zxma9(DUP0=UV=A4Z?|7ue<_Zho?e2x=lbnf-1Xrjj=A3Jgu7#BZmj+zjvDWE!Uv&N ziPe9^QRBT%xZCy(c)UKGHz`Mr_d4MZP~%=724nj_;;8XnC)~Xk*aUOFK>Ub1ZrjyYulQjvDWE!cU|25El13^doMQ*9mv)Jc1<*^&fH6c&`)g z)_EL@>;Dl)jrTg?bx<1=tN)0j#(SM`cMNoi)qliM1hPq?L&7h&wxe9G1t=w_)GM0$CF#)&C%1#jVE`<hC^z`%+{JPtA9J`MZ%ESB5pRxldAafA?l^GgPcY_5acrNbm*AoJx!k^-hQ}-39NXmO#*@3}6$RUu zA4|MB*5&2Kle^dL3jV#}Wvo|%XeHHXSgeb+))6+}vmFOFR{znjn z9DO{EfTzIx3h1*7QHrCFrfX<_@_c_+ou)6+}vGU$CAz1Luo;ttVEaQA+? z+b`3wNOAP^^b*|NGr0F)+;g@RM^8^L!QE@g6j&5&zZ6GLPcOsKJ1dsQI6htf&vNwi zG!oqH6ZalWxcy)Me3ql9r;*|49f;-6SpUy*^z<|m-0hP@Shl0TkfV>M5pcK9R^l;C zhwn>q)OmUd{t~@+<1_h5P#bTKpUumSC$9(pwX+W9#hb@|t`E8KFFi-a`boC+RNxK#nIE#OYpVmzntNBb?7g}(bLmQ@I~maVR8MXIC^?|2|gCR zpJDsmJ(d(lPfstw$Dsdd^q-0TQXD-!y#$|&{@2m}5c*4T^z`%+d@1_RME~RHFU8T* z(@XIA=pTjS)Ag6)=;`St_&D^>j`M2)`b%;2^z;(E0s6ap)dc7-#nIE#OYrXKzn$Tn zM1Luco}ONU_d)*!=Z?yi{|(0@DnOL6q{ z^b))Y`n&6iJAR}%dU|>Z-U$7J(0>a0OL6q{^b))R`n%)7^_Sx4>FFi7yN7hY?{@u# z9DO{EfV+L`{>`cDBgN6j(@XF=u0O5=uD=v_J-J?jyVt_*kGr-?arE@`59m%?q0jqVgJoLDUSZ0UV?W(|3Th9jy~=f{-6=?X7JxUay3%i^$GpYvzY{U_asp`eq4Vk zj-H-gf`_61?pS{zM;}ik;O?3e#Qtli6h|LVFTvft!AkT$jr}0S(bLmQ@VV%}0sUX1 zzZ6GLPcOljpuao*-=e=1M^8^L!QH*Ldya71FU8T*(@XF#(ck?!kN#2|Jw3eyclVa= zTyxhGDUP0=UV`^Se|KN80sW;odU|>Z?yiB?vHw@1zZ6GLPcOkE(SH>BuR(t)j-H-g zf{#Lf1^Z_g`b%;2^z;&Z0Q$T0eGB?aarE@`5_}B$N2333^q1o3>FFi-1oSV5{`=5h zile8em*C%^e-rdSg#JQ~KAuLvC!^1lSRW~lKAv8JyVnTU(cfKXq&RwddI=td{*Te$ zy{{|9QRnF;_FFhS zHS|~T7`p3~6h}`_FTvesllEahyYoegqo=3;EdM22J+>lMJ?GGr1kUi<+u4*#nlmOa z99EPq2+bGNw13PW0uz3$0nfHWg~YuM~%ZZm}~P~^t3PvmG zBsxjjM9%ibjez!*$cMHQbNxIQJw5+drO(?V&sA}n{PCAf{YA%xdeVNT{^-fL=c+n& zoQYp;vVTqY(2h>^*#2TgW&6uHEkIPS$Om&7&qYt*p1x|8oXiVX+gt5KK>bDiM*V3& zP=E9U?n(WrC(RYpA5EzGnvqKeXwwh_65GbMyr6N&Ts3?C}M6Ts>*NH#+6Xl(1f@3&{PP$BvT^8v0qN zKkY;6zvR^@ds5lD&~laGdVbO$HH>ShKkX~(Pd#Za)lgg}1$SMgby3gQ`TIdb{poQL`Gj381mjOv zW!>(Tgx1Sz!=>~;us?!c*~lHvQR8rps9xGO+7Hw}-QD_7G2a~azS=W}+~J)1)BdM* zQBRQ%&7~UAdQRIw&m*EX%lOdGLeD!Qe|k<7^*=pViu`9BIl|Pyk72nuk^v&DKI3y%;#!a(a*!JT`XeHlHk&q%yJ;6I}PUoXpF z@7Lj+-L+U-=dUd7S+xu^?DJVuJGBdi0dmGUY8cn_4sPe{Gq$mk+5#3ZIG?j9Z6*jA zao^>@Ick7wZUrx}x7_RPe0TXD|E<&=?Ny!gIopiVfSh?ecmd-Y+CL?S=CRM`^s{Y+ z1_5%$IqkRk{kzy>o~DA$ovXSUPk$*@V08Ji5m2T7QHI>lIrYI@#&e$^-efO<3{b62 zY3Jxv&Cb?$FpQk+w~;f>QNy@~>U+%EU?0x=ceK&Jr-PhvPW6ABi?-|6dt#@ZR>ReN zQjZ$OHOSNdckaTr?$@1);H`5kG^Le z=GS#`b&33`C+0dl7d>t6N&R!K-o;uL zZv(@ZEw&GRufpKrd0=?jR6y&cKB#fH26JtmOZ`Qj%~qs`&Y1v~<(zLvyvPhm!wvZ5 zT}D9eaE=;>YeaRe89c`ty{V~_ibJ3G=&vVzCI;{eu zS->mXzBj70^S1CZcBoqbi0T#jU@q`n^aSoH@~7u+dM=~qEP9R>`QNSD&^{iR(Z8$s z5ZHQR`mSZeN3!LY2Le6UZ}2CCt<2oya~`auT~&v>ya4 z*v+Ee4DjdP*xlte=cr*^gSm|7q9=UH^X`q+tZVZb_TmK{Kl1Ec>jX>CEwj@qG7ym4 zoYT56*XFsjF6wzOiBdVbO$H4fKMfAqAuXZB)c{m;{+bUMtf2edBgzbPgq zoc-}1|I(bMy%bL#uQ^RdyZ zx3i8(xRIfjqiWda zq6dDoKc|{1%a*W$KYV3}9P0uvO08gj>@@8J%X_)p<{ULP*NE!Hx)`sk@q@{B%6liG z>s{;zv<;*7Ggf;{Dkn$p8bIr%{;09JCXOfLp430==E3N&n^jnq(}Ususu}+9hQ*vO zca;QM7xhFLvzRXYHg42be;sZRrWr;Vc%jMph~&A5S}=-Q$JCOXpui^9InA!o9EKH#`bNqYh%W4{v%(Hgr@2| z78qR9zw=mMpx1q(dPV;9x)MEY?um7U^1A4C3SDpMc|o*?6s_TOKS@358cRLtevj_! z=)RGzu`+8o-Q$V;=^l^z$60SbxrWny9j%Lc(*0f>PrBZIat)8~9x}dbIQ19pA?dzR zw1(630^LK>HC*IR*KoS`qjk}JqsU+896|l*evkUoePew0c%uEJXkDUvFgge6y!+_B z0l7aw=N+AEbk9cD7P^knwI#*L1uQzvgRu`8t=3dln_r(=wcD|$U5%B9yeblni` z{pdcE?kDNGLHB-i-JsV#W?{{#k?d=`8iT0D!6LX_^F5Sn{eKq}#Kvb{DNA#Tn_0*U7qo@4SofX+X z2=|^ye(F!p=}XeKfeeSovW3%6eDvKxH@zpk$Q;G~O;yE4?r=`O zJHT9r=hD4_==zA(CECwWPto-eU6<%}kmz$!PufoEPuDTpPTCJ2wOQi38`^KQ4J~4F z*m;xmg?D$pV)WXXUL&K1am~vyMV&h}O2D(XK1Q$Q}<_5cGIj)0lCdNt&958dziHSfib6dJ?h)U$vGiGyzjwcZYa;C z?LU)ci`}{Vc>9+Eoq+n&`?@mskf}dJ%8#sKYfzukabz`S;VUG{tg0j{XCb}MZcG!{;h^= zXWKich4t0Td{h_xUIR5Y*HC}@9SWUav@YsT=Ng?;)IW}=_Z<+u_MzWlby{5z&M*Jb zc2TrG;Cl|&h`z(3o^-C!IYsNDo^-C!IYsM=uMe$D=5xijpG9MU9t(P`MdLG$hK_A- zKGIw|Ch7R6^NY@3(R`#Dx}J#E2hsXQ^>n?8@48C;X)axRsXv_yGUpwt5se3W&Z6I0 z)9!r_zWf{GmZA{q%TCB@q)8`*V{`A=i%(Zzg?JL>_`pkx?E<5Tpt97>{ zeBU~ajojv3R2O|_gZfh+`kcx9RYPE1;%e;d`AUA|4(Igw7FsX$r_aosUsfM#Y*d|$ zGl#JF`eUxcbLlfP^qHTEi~eL6s<(7re%+mk>J|B5uFZ4lvqtoprP101R;BT6`&qAM zAgcFbcxIUKuDtVI#Q_Yt!@0;GJ#FqupPi%6C|+*;BKqOY0q`JiZ-(5@Ieiw9K7T0E z)8`WDvxW4zLHc|keYSAcPf>Q6MLnHy2}=u~Ekq6Dn$SWIqYo9nYu_l@&JjHuh8jQD zY&)IWA^ntC)E`PP<3z=wMpvK`E%yoD!9edPsP1>$dOFe8qU-~$j`frFH0*%sE zWc}Jsh_2LRC`{ZLVxLOg$K?*^sByT4){CAF_oQuTQ83)8HZ~h&6&YbUVM~jXr?H_uKFxTO^bpB#pHm~bfe71T|t?tf_gR||hF=2Me zUf;5kjUr)vy=82AWK$F-&@#vAsL+8{h$sIj?*t~2x*=I8&GgEPlw*^{HvIilx*i{2g#=c_fe%SH~4 zM(%Jpx;Z`b;Vt?Z)52Rq-4%*$R*Ulsb}q+w2c zpAE)bo9Ciu=%+kso8$XzGyN=a>hju8pA8m0Z%m&7rtPHtK-X&8Cv+XA>o#o0ZVA+W}ga=faVSB5?tY@plfZXAn)+O2}(`z)kPo~#UB7b^aM*ZnET8_U$ z*|C6NNVmQS(Ca3;f0NlC((5Mlw7Dnsr){QniP}#+>1Pr77xHC>`{SxW*%i6n` z%@ox|*HXIIrPo1!?K$P|eIhGsKXxe4@k6hQSZqK)`Ob-F%4(F(e<{HuU6!l56 z?Qiy|QUB-#rP{&jJPNFw-_o&D=%FHi)Hqy&xi-(G^=@i6l$~J9qc_(X2qOP0n|eUT zO(X61o2D@24(B3&^t8Dr^&bS|*!tw>{XNd~hZh$c!O07Wpunk2(IS7;I9!9dHqWL0 zSqk>H_Z;g5HK&cUssFA6_gJolMOetN)*sbHJyBzG4fRJ)#y#nnp>@$QL+hfRbS%a3 z^u`kPX}9+-J8GqLHasl?)bnPh;xMlKZ99FgWPse^oYsZ8HqWK?uIgbqp|iHx+m2TP z+CQSYM4q&N&=a_4F#cWd$axX0@OcerU83VoeduwF;|bi8`u{O`q8+}a0c=V7no)l` zZs|Cu{+P>nE_!?A ziTVU{LwPQG`nhMXeJPxaH^RY;8Ew;JP3xt{g8EY*dQ8z1xaZO#4V@F6`?3PQ7@Lk& zQN1D`IwsK*xF_{LSG1w?BC+NKRB8KBU3A`w<`L!s&!zsL*6m z3cAjq#^xGYFRe@DBN|JhF(ay%j{kgn(?H9nr|f^fE)I0u()|+M7twKuxem{z-647tO($cMIV zv5^P%p4}21*rftgIaUCUBn4;on09`VCu$t7!CZ&u(z--*UsRXKldh9=O`!L;Mc;88 z2*zbj;B2aYXgf&q&8G zZ38`CbY6(+63shNU36Yhe>#`xxrWX`I@jnqNHoXqt{cl1ycrPv^v(c$R`)0yJ0eMR z^NtY^Uw_QCc`ka|+;do|9d_&D!C(Xh03F+OzR)pD$13JBo=bi5y-3ZXFK!Ke2*cw& z?=aWqxzzvL{$u<>YYOiwIdCLUf4Xjn<~3bss6To}b5H6|J?Z*J*D>lT@}b9$`iRB@ z^{2;(`qT4N{~2@Hy9sHaT9OKob>b#=@yc{oYGwzZ=PbIPL5|Wz5=a*)i;(~a|QtJ@op z+nm!eFPf*cf2cq86!j0Si~7_4d7mMQ4M}2$=1AYyZJXE5_#R(c7kb*r^k`D89i<8De|ZNBQw8b{Hc%3njmVYXq^;! z(te<88ukD7WJ2fc*V%U^+TPd^-Fpd{Rnbn}WB;yzl0zNjjC0XF7W4$}N$=rMpA`9j zXLIge2tA`kIP~5Wy(aXDm=XEYd%1Buz2}0GpKK4=6C7tE z%)GrZ{8=s=6XC975umlb#zZ*Us0&B-gfbC!|F$m-s`iL+eEy;eY}nh9aon)FB|Pq| z0LP72TEgB=qZr5Tn_I%fi2F>0na{KYrExtb!WsKpLXDoMnF#0XYY8utwM@x5pMlH;zR$5@Q-~}KJ*{Q5&Qan=s%8u8bAmCe#SA^gkdmc zWkSZWY3l0GuHb$qLOpRLWFMK3iEvx0MzAHpekQ^W13SW@@(Gy;-G1BkXgd?3+ix4P z-Smsl?YBRl{>Vh=_FLrOHGUDg{q~^OcZ{RkZ*5A3`#HMfZp{4&jH5g5%6$s2}-Z{E0AlarF=5PlS2QP9Mgf z2(9rAKa4*S&euCY`0IU4gm=d`hVwZSG7+}v+Yau}-N{6lD_v9A;5_h)aO2*VP;0|a zOoS&7w1neXuJ}c03~2hHei8Oe-R?vEBHT8*@rTbZ!d<=&A3nbb-FlbKILbum)?1@t zCMH7nbG!Zjzr{V+Kko7Q-=bSD8+PJD{hva&-$&)m$wcTLclYy)&^_+%=NDm*Low`+ zw^=}h#SX-E_0E;ek`&$>(s*s$-bx$kpq12x!?ailB)FF3;-NYy%-50 z-2pg0UsNr0;@Bp@@ti#jPTXz+9NWHLjfN39_z$@Ej=7K{`jO4 zH2iWnaLo2JEu7REfC!zDr&zM*^+ANo`lo z^wZd?<8yX>OeBc#>v=IOTdF=F!sdChLzUmEfe4orc36gO)j)*TJLZMJZ!3TZgLZ9V z8Swv*5Mg+oAjlkE7DTw?)gm^xNLdhJ>EuP=^wvNS;kz%Fu($Y~rU>t^F9b(g6$BC9 zs<@Jks9O+3SpHN_=$|zQh;YfvpV`**IY5M$UT1{8(V0MmeU=|)_Kr*-!pC2wfig-a z5Mk%hXPNRoBZ#on8y}oL8vr8wZvG?o!prvyh_JSm99oSi3nEO}_XfK?pe%^+a>w-W<}d>hF4}UOrE(aEuyw@% zSlTKSL>LuwfK96%3L@MenFC(8D+MCVv2GVjTE7&C@WISj{3mK!p7^$FQK0HG$*OEitV1@6|yT7yM$v)PR~G!kjmr zvId!If(XMSePCb3f0I*y)|kia(xti}!pD~k7cM40vZ&unpaKZtPl=6q10Vkr<|r@#$tTTm$wVZ!D4q3fST zK!h0^u49$Y6af)ldzA-{k1h-%gq54w{(gl)gr)unfWu4jfCxvQ*w22Nmj^`H<4$^* z`7%3*@Xo>C+54y2L4@<>q=t@>*+GPTJDz7dx@QLwny(VVZ#D9O2s1DIizTX-2mc?n zPor@s0ep8l9At55)Zc8<@oZ@0z-R&2$$@NVf$JG$YR*u7&f^YqZ~_ktk8nHP?;B!>!u z2+JN!0vT_IfC%e7y~UL4At1tj4->(n`@tZ>t}E}c<+p-Cgx3RgIGU|9h;YoUmuy7V z&LF~awRM- z#Kk100egDa1reTY{4YBYSrJPa$FORN8h{8l|DGD` zZY@BB&d=xAi&iZ_gm2Zvu;pNV5MgA?du+g7yyqgoGvyOOzm`ovghA)-v#**o0TC99 zNdxm{HvtjeYjcLxnA8MB*bDcEN7r@-5mtSoz>To(Ai}4O-mz-kXUrBmzYEQvnSM9_#`leDdHmt8<_Wh%gu4H`|mt0z^2xl?vMrbp;Wg9{rZ3#P>xw zHG>LQHb+2QY@OsCtBkM5#pI(D=v1p4h_HX?dzK2{7h%Yv7?wA(8;Gz1URT$c6bvG~ zu<-_4I3^fGcx!ud$lxypA`D4&okf)>1tNUnOAm<(27(CRk2t{&yTKTm(eedj3(i9sg!gghTpdfgz2Hf(XA^vya);i-HJ?X<1=c zzv3XmW0QYjr#lx15zgF`1uji02_np&Xdl}=v?Pcy!`~SpVTRHm!aZvbvt5Zwg9xJ! zq=Vdp%YX^C$e%sv_dA`F~znLXYY0wN6hCpmo4u_%b}+7H**H?4|- z2q*oX5~A?`t`XtG2bb9Ou7M!J?YB}x_ftW@@qlxVeRDVnINB3a!Ryw=faBD@62S4+){89Xp%TDxLT&v2iW&q1$1-;>vgg%>lQGEIA-8T&|J|IHr2xhxexv!bN2qt9L#jlw5n7 zb#~v6#S>Yx!9y!8bXChhz49r6|NcwcJ*K9l=HyB)cKW6QTmSwG)k;Fz{_3s}-|FmTMga|=uP!yw@JZ<#!hCJB}Y0O~Y7?nN~w8%UJIF^3oFxGz%aNMyt z8)Tm|2snOYh2dT#3`7`GtQWi3FbqVvAZ=BMxLOH5hj-pLV;k02g3sZ~Z?eF!aW@&q znQ8F(lFqduE@pkr*mJzTh>HylJ@+@me2!VXJbG`;CxJFy;!@K7EGZ5q~u z&*8l)V_ExxHQ{rZZ0xUWN-_NIG8RjZtO9p0G=R96ykJ|Fby)+5i-VG^XBOsj?4B3z zhur&%ZU43=tm@JL;{HDAuW&Z3a07V!We4^H>f-)B;7W5ynyDR#aMSkWEYIP#Ai^tbUNmQTxq(22xpDh!BRbs01IEX~mgFW2tltYn zc(-Ue7*sI=L}=bP$<7sx01>{)nGl8#h=jQ4|K|Za)+-X?;t3-e^q$clMEGr05b~-kh;YH4UaTh8C&FCg>%pH@JAnwxKMQ7Ml};eS-vc{C z#zuY+;k<+g{K?Y$L4-{wwS{g;i-HJOw|wevb}0x%I3!aOcw90ch_Ge1Y;13;d?3PJ ziz`8b`q@E*e-!V^ZkEdqA{;oH!I-SYK!ja3k6~x^Vj#k0Y8Ygy8wesyJ*pR5ULp`g zm~~Qp*!7?|h_L*~qHM?B;vm9H@2bK4CLtigYZL0Tp+!SLgspzA2WRmaQxQI25X^R; zU?9Tf*P7wI@UkGnfZSvZ!n=iA!Nq=IAVT$`#kQ6T0}%$DZwP6pRff1&H%)%F zvT~Y{v{#$Kp!quELATAC$Se3nhP#xmp_bE5CHiduk@9AUsE1=JV=pZ;Uw;6m6 ze}BG^{o1D)d=4*c3WHr0T7w9;7VplkBxnsHocC8SbXs|lah%lZHXBtipP%E7pl?6? z&T-51zd~I-$2WK1vMq;yVj{d=bKr;fMVRnPQkd&3Wg^_Lx-{E??~AZ&?@X}rx2a5o zkDB_}eSBYpSsE9DnI{G@5#|~`!-%L zw|U?fA%1tk!ts3(rYe#ij%*BIBK)pH8kS;H02AQ}e|l)~OA98#)A`e|D12Xp4SOVq zaWBR&5gv#r&JN)FBJ5qpgo#CFFcHov*@C(6i?Hw6N9;(8C?>+4KTl*2@qH1#`1=71 z8Ggkt!jPqtSpZ~HM3YEK$6_k9tb&=bSB1&x^qo29J8-1kK|F=-+Q z=~0r2aQFRi=Dsh&3$rxH-8lyn;fP;5G538DR-S!?4Jz@<9~Uo&*MwxLYr>%X)!3@b zHK6C~)vQhNSN^!DPCUiJx7T4Jj7;!7+xJr)Cc>XHonSS>hcXdv@4teLt1^^{P)mB2 zH90t%#l>D@m$EeYdR%<;&1shG$yZE-W7OsB;Xhw75e{E_iCvujEfe9%n+ra?FT!mv z!=SpqHi&R;t#0f_;@Tj>0u_E^18)Do;-Z$UDqKES7dVc5(~PZJQWrSxt+|eE$Go_> zX5}8XDeX)a7ytRED(rkz2RKGYHfEiFt^*wR-`U2#z`VHl(AvYUgP(CMnxF>U%vK9H z2IQ&DcHgTB9LG-jiDf`N$63j)vOm)lW+J>idLCxK{yj(tFF^o0KPB6 z^o4G+c2_2{xY(@YY*r3mkBghmUuE-}j%6Zre)^6z!S_YjdiZ75VdP-^H)cMKsZuXs zmq!d{B5YLn0-L)olEp=T`^78;z8)73J-WiugtcTMTopBsO{v(DiE#b#7?xmu879JU zBYU%b^U5$04(Opn?wE>9gbBN~XMeu0$V3>1&)3WhYs5r&0@^b7eGyhmsKVXUU6}|6 zyy?!|_eI$A(!VU~{17I>8(T(wcwdCiUjN0uSu>7_aQLh#AKn+?j5SZ$=|-VUgjfF< z$7bUDBAjva50)ZnHzvZXYiF{FNxCr+jw^JR)mb-~iSX|Z(^wLGUxcsz{fEt6+>MEF z(A+OSyf4CE@V-^>-sVh%>lRIBkM}fZA}qN71smtoW+JR|cr+`A?~5?-&TBTVL@Or3 z3H644cwdCmIw_E#eFGL3mwefaxv$5?ucpSZa_hsH2vcZ%*xPmCOoYtJ2WLxdXCmC0 z^hbZDknK!_!v`0D8oxv_5klYDe)oM5POh5|?~l)5ak28I75@BPX0W)JA$Ja#op>P= zVTY_2{O9p~5nij0e|HeFfr+sB@x<&VzAr+5cyd^9?GO`T-k9R-D!wnmLd9}I!1Ujl z2OL;S(Mz0h0#)yD>;-xN^y+Em5fTT@`aKYV_qez zl0hk^l*U+ENu!ieN+{VdW>eBDK}tC#6l16oqJUCGDTT3=QdTLTR97lutf&-K!ju|H zAjUwYq*6_(t2D*fRH>k}QW_~WG1gQnDdm+WN*j!A6u;75X{}VoSXp68Go_2t0b>WH zt z*_G=UuPeVQca(feVT^^9V@gi^&nfR>ysO+)9w|O055_#oEk#%6DN8XfRsK@GR~9M; zMnid^oK@~CQOXMCZ{>pWhjLFjqg+%TDt{^`mBY#n<+gG}xuTpI!Y6R#V-m zHB#4UYqUBT>!|hBFmcJwdGn>j8)azYFTxzwnQtdF3~EfOSSo01&kHc zaJ9HPP5VwOu70P5s`IoNS{aOG)beT}b)q(1E2K`>g4J)e$yzat#njSjZncS8Ov{aB zxK>(gsTNR6YX#IXS~Inc8j3MgE1`kbQEje*)?6*AwNtyQl`vM){90wLyV_o@thHB} z)R@e_+FScheXKlFzEhtmeYIE0Q)Pkr3duPhY9maOrF0HH9M!ThU#qx`G zPOYak!`Mu_rnc3ZYF9B{Rd1`mtJSpn+V5(8?Y!DVtE-*Gcviil9#ku6)wP3ab?vxX zN2{tG!+17*S>2^>R1avIwT>yCL0hjS)e>S%sIArBt3GWd#+BM4ZMBv_Q!%RA_u6wcMvcN4rOnosX^Qqz zU4~_$HbJ|loyB-o`$oHm~Av^*H|Xoa=RT8#ED#(%Y3+DlE*126_?xwW*KrN71aR?DR6dO|%7 z#xzU{?ZC+4>3N}6!jmih;~=|2g^GpMtPv+(_@r; zdJ(;#{#1Lf6x81rj5+k@T24K)uIf3lyw;v++4cPTGcCXVw^l&UrN6=WMth>A(6i|o^b}Z9>sj>N zdQyx@^>li2Jy6e!F|VFgFQgaNlVMDz=h0JZ8MGlm9TuJ71hJ_GI~)g6?MN}TQ7;Rq#mZ{QAcWJF_zV<>7n{4 zEx#J7=T~d$&(wcZpZW|-C*4vXsjpNEOIQ7!`b6!Bv7_EvkI>(!niipJS{vQa-m0xI zw$dBwZFOBsthLn>Yt8f|nyEF$*jTTtH_;Pm$+aeWa;=_TM{lH$#5hv_QXi)`)$3!d zuTRn&=q>fZ7zgVk^kI5Cy*b9_`gpyC-a(JV7^x4^2kPDQ_88mi!}ZR30<{;$UV2}> zyKbsoFm}=V={@y{`Y4Q}^xpbdeS+QtV-J0R-bWv;57CF}WAy&|5pBOV1LF++D}Ap1 zn|4Z@tDn-Q>nqfw+GLEA^_%)M{iL=|ou;o-@9B%xmFgcD|IqL2clEXE59(e02lXF) zpSE7Ti1DKSt$st_rXJRA=!doM^bP7y>Pd_z^-KB%-B!1%7xb;_b$y4rM?He^h<--@ zUEinfRDaiZs%Q1R>Tl|PjQjPY`T_m0`ipu%|3y8f|Eiu)cVXP6@6#Rqw0cB!^dss) z{iJ$P-HLIm9<6WFFR7>0ZTczI)-R|x)wLMc>Ra@6`XB0Lb)9}${Yk%}I@$t^3-mSm zVtu#vr@C1GQ(dn|Yj@RU7?RxT7zE_LV@2FAgUl{+=m+Fu8@70IuWBsAJ zO8;Jepg+O*L{D!#*B|LW=+CiaFc#{|^>i518JUfY#tMCrp3zvO2N*x<^Yly@Ga0Fj zEXERjqn^dssHZhH>#OzD7*iX`jWosveY>8<*siBAcIun-WEhhfiH(%T&-!jXrLkL2 zV(is-=!q~UGAtvhu}A+^Pip+CCp3Q3f6;vyeTHTvFb?S_^aREU-84?=hjksJZoJnG zR0qP7~kkwjko$$eUAPXOAh02{ZIXc z{x_DV`YZj8{t)9s{h5AC|60#w+`{s&p4<3Fzm4&>{!*W!&(gCQQ?TSTvKzDYsd{!} zs-DOAN13PQ!`d5sdrY;}=Z!dRphF{Y~%)RGuW z8byt=#y9FrwX88y4K^mJqt$X4%NZd?d1IV9MJ;bkQA-;m)j?`F#&83S>c(*OOSQW3 zrCPxlsPKM(9Zfak(xzSgxZ**4Ms%#$+P_#ssEnCN?J;P zH%A){)OzY@qn?_^tf~cxwD@lv7Koe;cLLXU084F)j0+VVRGOq^52@#Q4zo*SKrEG?JNjvAj3Z zn(vH97#|s?dEWTPNQg0^dDBQ_zA&y~yk^`o0@V`g6O2!ci^g*!L@lB|H;SlNjN*Dm zGpAWx&uLcG^OylHMf~hEoA0W^P8QFTxutyvD(WhY!<{=P;I4VRZke@&8%v9bEr|-JZofDE1Q|s zLBs?4ln4mKE;Y-$cQ#0)fZsDb7Pqm&6|cC{3i;l@a#hCVq7x*Fp8O%uw*ien|~UYjpF8IBeU7qXlwjrG{!Q`*kQCYT3~Ep%rP>m zYmDO&V5jdbc-Ba^zxsAZ2XnDm)7)q*#>WE3>~MjNvrmK17dGt4MtbT$ha$<;(^0VA23QvJe6tkyM}8Z(T#Sh|@rjb=tY zV6%^fO*giHnW%skVBBDyGPas)%ncYf7^jWh z#u0O!x!YK0{%ZVWo-+4i+;1E+%9<6;O=ejvznh!QFf$ZmsCnExX{ovfA^TUxoTc2-v_7sgyxAuEm5!|IH&vz5i_V)d~yW6W&jw31r=tzH;=S?R1u zYlxK!V=617mD~cWGRDf*K&z@%&PstXg*C|9X6!Y#V%%!|Xl=KCF?Jf;t)0e3%Q3E) z!5D+BO;%a!rg^|9YaK9lTGNf~#%heKt+~bq>t|y&#@WUa<7ac26>9x#hFWLMiq=?b zH^$xO1+#=z%UWiYz_Qs|Y1OsLU@T+pu;yFQ))tIgtmW3v);=o=W0bYR`r6uM&BHj) znq@7q_FLa#{MMRlO|TAHHb&c;YW-pzu_j`iXic+*TL-Lh7{^)1tjX3)Ued5q<)>ed3|S8F83k=9Ogl=Yjn&=`fqHor60SdR6b;aG>Pz1Dgw z%GitLu(j6OX6?52SU*|otSZ)V>paHuRteuF>y#C4UBXh*cf$J8dS{)$a>06UO|nj6 zJZW9D##`T5FEGBa-dg`!)2**Cer3g2Q>>ZRLyQlt=hi>gch(GyGpv`^Y-^!)2jd;< zk#*NvWX-`i$9ilnu)ephW4vzNwr*HISc@?(w(eO=t(w*szNJ{MSw(#HtW_9SSvRc# zRwXOgHvo(2E9I+Z4Yo@823wY|r`6BWFlxTUzJ$J^R&OhzueX)L*U{>3CBm4#+ccc)0f@X)@p8L_cgZ) z_-a^&+>y}j!V?|$CU%2nS^~4JIJ+aF9{Jt<>b&S=0 z4SaQcReTI1^ELL>_f_+?$JpN2+}Fid*VhDN6JHx&GhaJj1jYzoq_3B+tFJA_w!VQr z!&l7L0%HqbA75)uqc;4pyWf;^V)ll zmv`9Qos<(Pxo|;Br1X{%St%Ze&*$5|*+8;*)nDzGy|!uGscb!uO#C*JTkE&U6p%x* zN+*{>QuGuuh@+T%J)b0sC?io%B$X)2DbY)ar<6)!^;i-Jry7UuAestlh|nX5A&4r% zh@_Ta?&Mll^c80DawC56;+F*;74C}+pFhvhddJ~Iu(8~yu4AG6p?8%vU%$cllDF?D`F4Znxvx!@Gb8I|p avGu<>G5hAoEVHk!#K);QG(HZ^t^5H`4fe$V literal 0 HcmV?d00001 diff --git a/assets/models/pink-monkey.gltf b/assets/models/pink-monkey.gltf new file mode 100644 index 0000000..a27e895 --- /dev/null +++ b/assets/models/pink-monkey.gltf @@ -0,0 +1,121 @@ +{ + "asset":{ + "generator":"Khronos glTF Blender I/O v4.0.44", + "version":"2.0" + }, + "scene":0, + "scenes":[ + { + "name":"Scene", + "nodes":[ + 0 + ] + } + ], + "nodes":[ + { + "mesh":0, + "name":"Suzanne" + } + ], + "materials":[ + { + "doubleSided":true, + "name":"Material.001", + "pbrMetallicRoughness":{ + "baseColorFactor":[ + 0.8002749681472778, + 0, + 0.07706787437200546, + 1 + ], + "metallicFactor":0, + "roughnessFactor":0.5 + } + } + ], + "meshes":[ + { + "name":"Suzanne", + "primitives":[ + { + "attributes":{ + "POSITION":0, + "NORMAL":1, + "TEXCOORD_0":2 + }, + "indices":3, + "material":0 + } + ] + } + ], + "accessors":[ + { + "bufferView":0, + "componentType":5126, + "count":1966, + "max":[ + 1.3671875, + 0.984375, + 0.8515625 + ], + "min":[ + -1.3671875, + -0.984375, + -0.8515625 + ], + "type":"VEC3" + }, + { + "bufferView":1, + "componentType":5126, + "count":1966, + "type":"VEC3" + }, + { + "bufferView":2, + "componentType":5126, + "count":1966, + "type":"VEC2" + }, + { + "bufferView":3, + "componentType":5123, + "count":2904, + "type":"SCALAR" + } + ], + "bufferViews":[ + { + "buffer":0, + "byteLength":23592, + "byteOffset":0, + "target":34962 + }, + { + "buffer":0, + "byteLength":23592, + "byteOffset":23592, + "target":34962 + }, + { + "buffer":0, + "byteLength":15728, + "byteOffset":47184, + "target":34962 + }, + { + "buffer":0, + "byteLength":5808, + "byteOffset":62912, + "target":34963 + } + ], + "buffers":[ + { + "byteLength":68720, + "uri":"pink-monkey.bin" + } + ] +} diff --git a/assets/models/tree.bin b/assets/models/tree.bin new file mode 100644 index 0000000000000000000000000000000000000000..e7826210d4c2a288d9825d6987ca7d963ef294b5 GIT binary patch literal 13584 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 A3jhEB literal 0 HcmV?d00001 diff --git a/assets/models/tree.gltf b/assets/models/tree.gltf new file mode 100644 index 0000000..51bf9ed --- /dev/null +++ b/assets/models/tree.gltf @@ -0,0 +1,140 @@ +{ + "asset":{ + "generator":"Khronos glTF Blender I/O v4.4.56", + "version":"2.0" + }, + "scene":0, + "scenes":[ + { + "name":"Scene", + "nodes":[ + 0 + ] + } + ], + "nodes":[ + { + "mesh":0, + "name":"tree01", + "scale":[ + 0.009999999776482582, + 0.009999999776482582, + 0.009999999776482582 + ] + } + ], + "materials":[ + { + "name":"Mat", + "pbrMetallicRoughness":{ + "baseColorTexture":{ + "index":0 + }, + "metallicFactor":0 + } + } + ], + "meshes":[ + { + "name":"tree01_1", + "primitives":[ + { + "attributes":{ + "POSITION":0, + "NORMAL":1, + "TEXCOORD_0":2 + }, + "indices":3, + "material":0 + } + ] + } + ], + "textures":[ + { + "sampler":0, + "source":0 + } + ], + "images":[ + { + "mimeType":"image/png", + "name":"tree_texture", + "uri":"tree_texture.png" + } + ], + "accessors":[ + { + "bufferView":0, + "componentType":5126, + "count":395, + "max":[ + 123.4296646118164, + 509.0864562988281, + 168.36563110351562 + ], + "min":[ + -184.9799346923828, + 0, + -155.37196350097656 + ], + "type":"VEC3" + }, + { + "bufferView":1, + "componentType":5126, + "count":395, + "type":"VEC3" + }, + { + "bufferView":2, + "componentType":5126, + "count":395, + "type":"VEC2" + }, + { + "bufferView":3, + "componentType":5123, + "count":471, + "type":"SCALAR" + } + ], + "bufferViews":[ + { + "buffer":0, + "byteLength":4740, + "byteOffset":0, + "target":34962 + }, + { + "buffer":0, + "byteLength":4740, + "byteOffset":4740, + "target":34962 + }, + { + "buffer":0, + "byteLength":3160, + "byteOffset":9480, + "target":34962 + }, + { + "buffer":0, + "byteLength":942, + "byteOffset":12640, + "target":34963 + } + ], + "samplers":[ + { + "magFilter":9729, + "minFilter":9987 + } + ], + "buffers":[ + { + "byteLength":13584, + "uri":"tree.bin" + } + ] +} diff --git a/assets/models/tree_texture.png b/assets/models/tree_texture.png new file mode 100644 index 0000000000000000000000000000000000000000..f5726d41ea881c58cf74e16442f6e7856ad98742 GIT binary patch literal 845 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K58911L)MWvCLk0$B5l7=R`)GBhwSI502( z#RSL@CQB1Gn;9NBk>>&o!x#>, pub asset_manager: ModelManagerRef, + pub frame_width: f32, + pub frame_height: f32, } diff --git a/core/src/engine.rs b/core/src/engine.rs index eae1e74..6eb000f 100644 --- a/core/src/engine.rs +++ b/core/src/engine.rs @@ -4,31 +4,25 @@ use winit::event::Event; use crate::SceneManager; use crate::system::{SystemContext, SystemManager}; use raidillon_assets::{ModelManager, ModelManagerRef}; +use crate::context::PlatformContext; pub struct Engine { pub scene_manager: SceneManager, pub system_manager: SystemManager, - pub assets_model_manager: Option, - winit_event: Option>, } impl Engine { - /// Initialize the engine. - /// Engine is expected to be initialized after the platform, so reasonably - /// it takes platform-dependent structures while being initialized. pub fn new() -> Self { let scene_manager = SceneManager::new(); let system_manager = SystemManager::new(); Self { scene_manager, system_manager, - assets_model_manager: None, - winit_event: None, } } - /// Run the first frame, load the world. - pub fn initialize(&mut self) { + /// Initialize systems, load the world. + pub fn initialize(&mut self, platform_context: PlatformContext) { // Engine Loading Stage 1: initialize systems for (system_id, system) in self.system_manager.systems.iter_mut() { system.initialize(); @@ -36,7 +30,7 @@ impl Engine { let mut ctx = SystemContext { scene: self.scene_manager.current_mut(), - event: self.winit_event.clone(), + platform_context, }; // Engine Loading Stage 2: load world @@ -45,11 +39,11 @@ impl Engine { } } - /// Runs every frame - pub fn update(&mut self) { + /// Update the engine + pub fn update(&mut self, platform_context: PlatformContext) { let mut ctx = SystemContext { scene: self.scene_manager.current_mut(), - event: self.winit_event.clone(), + platform_context, }; for (system_id, system) in self.system_manager.systems.iter_mut() { @@ -57,14 +51,6 @@ impl Engine { } } - pub fn set_winit_event(&mut self, event: Event<()>) { - self.winit_event = Some(event); - } - - pub fn set_model_manager(&mut self, model_manager: ModelManagerRef) { - self.assets_model_manager = Some(model_manager); - } - // pub fn build_system_context(&mut self) -> SystemContext { // SystemContext { // scene: self.scene_manager.current_mut(), diff --git a/core/src/lib.rs b/core/src/lib.rs index 0527964..6fddfd0 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -1,6 +1,7 @@ mod scene; mod engine; pub mod system; +pub mod context; pub use scene::{Scene, SceneManager}; pub use engine::Engine; diff --git a/core/src/system.rs b/core/src/system.rs index 7bc5a94..4412d7b 100644 --- a/core/src/system.rs +++ b/core/src/system.rs @@ -1,11 +1,12 @@ use crate::Scene; use indexmap::IndexMap; use winit::event::Event; +use crate::context::PlatformContext; pub struct SystemContext<'a> { // TODO: time delta etc. pub scene: &'a mut Scene, - pub event: Option>, + pub platform_context: PlatformContext, } pub trait System { diff --git a/ecs/src/components.rs b/ecs/src/components.rs index 83bc7df..758f0f4 100644 --- a/ecs/src/components.rs +++ b/ecs/src/components.rs @@ -13,3 +13,5 @@ impl Transform { Mat4::from_scale_rotation_translation(self.scale, self.rotation, self.translation) } } + +pub struct ModelHandle(pub ModelID); diff --git a/game/Cargo.toml b/game/Cargo.toml index 835bf39..e8fac5f 100644 --- a/game/Cargo.toml +++ b/game/Cargo.toml @@ -10,5 +10,7 @@ glium = ["raidillon_glium"] [dependencies] raidillon_core = { path = "../core" } raidillon_platform = { path = "../platform" } +raidillon_assets = { path = "../asset" } +raidillon_ecs = { path = "../ecs" } raidillon_glium = { path = "../glium_platform", optional = true } -glam = "0.30.5" \ No newline at end of file +glam = "0.30.5" diff --git a/game/src/main.rs b/game/src/main.rs index e0403c7..e4d1136 100644 --- a/game/src/main.rs +++ b/game/src/main.rs @@ -1,11 +1,16 @@ -use glam::Vec3; +use std::path::Path; +use glam::{Quat, Vec3}; use raidillon_core::{Engine, Scene, System}; use raidillon_core::system::SystemContext; use raidillon_platform::{Platform, Camera}; - +use raidillon_assets::model_path; +use raidillon_ecs::components::ModelHandle; +use raidillon_ecs::Transform; #[cfg(feature = "glium")] use raidillon_glium::GliumPlatform; +const TEST_GLTF: &str = "pink-monkey.gltf"; + const RENDERING_TEST_SYSTEM: &str = "rendering_test_system"; struct RenderingTestSystem; @@ -17,12 +22,23 @@ impl System for RenderingTestSystem { center: Vec3::ZERO, up: Vec3::Y, fovy: 60_f32.to_radians(), - aspect: 1920 as f32 / 1080 as f32, // FIXME + aspect: ctx.platform_context.frame_width / ctx.platform_context.frame_height, znear: 0.1, zfar: 100.0, },)); - // TODO: Load a sample glTF file + let mut am = ctx.platform_context.asset_manager.borrow_mut(); + + am.load_gltf(TEST_GLTF, &model_path(TEST_GLTF)); + + ctx.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), + )); } fn update(&mut self, ctx: &mut SystemContext) {} diff --git a/glium_platform/src/assets.rs b/glium_platform/src/assets.rs index 6d33887..1b3b4e1 100644 --- a/glium_platform/src/assets.rs +++ b/glium_platform/src/assets.rs @@ -12,7 +12,7 @@ use raidillon_assets::model_manager::ModelID; /// Glium platform asset manager implementation. pub struct GliumAssetManager { - pub models: HashMap, + pub models: HashMap, facade: Box, } @@ -27,13 +27,13 @@ impl GliumAssetManager { } impl ModelManager for GliumAssetManager { - fn load_gltf(&mut self, path: &Path) { + fn load_gltf(&mut self, id: ModelID, path: &Path) { let model = load_gltf(path, self.facade.as_ref()).unwrap(); - self.models.insert(path.to_path_buf(), model); + self.models.insert(id, model); } - fn unload_model(&mut self, path: &Path) { - self.models.remove(&path.to_path_buf()); + fn unload_model(&mut self, id: ModelID) { + self.models.remove(&id); } // fn get_model(&mut self, path: &Path) -> &Self::Model { diff --git a/glium_platform/src/platform.rs b/glium_platform/src/platform.rs index 69b0735..9a491c2 100644 --- a/glium_platform/src/platform.rs +++ b/glium_platform/src/platform.rs @@ -2,7 +2,7 @@ use std::cell::RefCell; use std::rc::Rc; use std::str::FromStr; use std::sync::{Arc, RwLock}; -use raidillon_platform::Platform; +use raidillon_platform::{Platform, PlatformContext}; use glium::winit::event_loop::EventLoop; use glium::winit::window::Window; use glium::backend::glutin::Display; @@ -40,7 +40,6 @@ impl Platform for GliumPlatform { let asset_manager: ModelManagerRef = Rc::new(RefCell::new(Box::new(GliumAssetManager::new(Box::new(display.clone()))))); let mut rendering_system_manager = RenderingSystemManager::new(); - engine.set_model_manager(asset_manager.clone()); // Install rendering systems rendering_system_manager.add_system( @@ -59,7 +58,14 @@ impl Platform for GliumPlatform { } fn run(mut self) { - self.engine.initialize(); + let (w, h): (u32, u32) = self.window.inner_size().into(); + let ctx = PlatformContext { + current_event: Event::AboutToWait, + asset_manager: self.asset_manager.clone(), + frame_width: w as f32, + frame_height: h as f32, + }; + self.engine.initialize(ctx); let _ = &self.event_loop.run(move |event, el| { match event { Event::WindowEvent { event, .. } => match event { @@ -69,7 +75,7 @@ impl Platform for GliumPlatform { }, WindowEvent::RedrawRequested => { let mut target = self.display.draw(); - target.clear_color(0.0, 0.0, 0.0, 1.0); + target.clear_color_and_depth((0.1, 0.1, 0.15, 1.0), 1.0); // TODO: let mut context; let mut context = RenderingContext { scene: self.engine.scene_manager.current_mut(), @@ -85,8 +91,13 @@ impl Platform for GliumPlatform { _ => {}, }, Event::AboutToWait => { - self.engine.set_winit_event(event.clone()); - self.engine.update(); + let ctx = PlatformContext { + current_event: event.clone(), + asset_manager: self.asset_manager.clone(), + frame_width: w as f32, + frame_height: h as f32, + }; + self.engine.update(ctx); self.window.request_redraw(); } _ => {}, diff --git a/glium_platform/src/render/basic.rs b/glium_platform/src/render/basic.rs index 66ffadf..60e7621 100644 --- a/glium_platform/src/render/basic.rs +++ b/glium_platform/src/render/basic.rs @@ -9,6 +9,7 @@ pub use raidillon_platform::Camera; use glam::Vec3; use glium::uniforms::{MagnifySamplerFilter, MinifySamplerFilter, SamplerWrapFunction}; use raidillon_ecs::{Transform, ModelID}; +use raidillon_ecs::components::ModelHandle; use crate::model::Model; /// A basic renderer pipeline step. @@ -65,8 +66,8 @@ impl RenderingSystem for BasicMeshRenderingSystem { let asset_manager = ctx.asset_manager.borrow(); - for (_, (tr, mh)) in ctx.scene.world.query::<(&Transform, &ModelID)>().iter() { - let model = match asset_manager.get_model(mh) { + for (_, (tr, mh)) in ctx.scene.world.query::<(&Transform, &ModelHandle)>().iter() { + let model = match asset_manager.get_model(&mh.0) { Some(model) => model, _ => continue, }; diff --git a/platform/src/lib.rs b/platform/src/lib.rs index 0750166..3ff1a65 100644 --- a/platform/src/lib.rs +++ b/platform/src/lib.rs @@ -3,3 +3,4 @@ mod camera; pub use platform::Platform; pub use camera::Camera; +pub use raidillon_core::context::PlatformContext; diff --git a/platform/src/platform.rs b/platform/src/platform.rs index b0250e4..3e0309f 100644 --- a/platform/src/platform.rs +++ b/platform/src/platform.rs @@ -1,5 +1,6 @@ use raidillon_assets::ModelManager; use raidillon_core::Engine; +use crate::PlatformContext; pub trait Platform { /// Initialize platform. From b3b69756e6757d88cfbf5d3a8d38853e9578eed2 Mon Sep 17 00:00:00 2001 From: reo Date: Sun, 31 Aug 2025 12:56:05 +0300 Subject: [PATCH 40/89] Use static string literals instead of String for scene IDs --- core/src/scene.rs | 4 ++-- game/src/main.rs | 10 ++++++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/core/src/scene.rs b/core/src/scene.rs index 5014d63..94b49fa 100644 --- a/core/src/scene.rs +++ b/core/src/scene.rs @@ -29,7 +29,7 @@ impl AsMut for Scene { } } -type SceneID = String; +type SceneID = &'static str; pub struct SceneManager { scenes: HashMap, @@ -55,7 +55,7 @@ impl SceneManager { pub fn current_mut(&mut self) -> &mut Scene { match &mut self.active_scene { - Some(id) => self.scenes.get_mut(id.as_mut()).unwrap().as_mut(), + Some(id) => self.scenes.get_mut(id).unwrap().as_mut(), None => panic!("No active scene"), } } diff --git a/game/src/main.rs b/game/src/main.rs index e4d1136..fe810dd 100644 --- a/game/src/main.rs +++ b/game/src/main.rs @@ -12,6 +12,9 @@ use raidillon_glium::GliumPlatform; const TEST_GLTF: &str = "pink-monkey.gltf"; const RENDERING_TEST_SYSTEM: &str = "rendering_test_system"; + +const MAIN_SCENE_ID: &str = "main_scene"; + struct RenderingTestSystem; impl System for RenderingTestSystem { @@ -52,13 +55,12 @@ fn main() { engine.system_manager.add_system(RENDERING_TEST_SYSTEM, Box::new(RenderingTestSystem)); // Set up the scene - let main_scene_id = "Main".to_owned(); let main_scene = Scene::new( - main_scene_id.clone(), + MAIN_SCENE_ID.to_owned(), None, ); - engine.scene_manager.add_scene(main_scene_id.clone(), main_scene); - engine.scene_manager.set_active_scene(main_scene_id.clone()); + engine.scene_manager.add_scene(MAIN_SCENE_ID, main_scene); + engine.scene_manager.set_active_scene(MAIN_SCENE_ID); #[cfg(feature = "glium")] { From 1a200e62ef5f5719c2588c8a81359eefd349c271 Mon Sep 17 00:00:00 2001 From: reo Date: Fri, 5 Sep 2025 16:07:48 +0300 Subject: [PATCH 41/89] Clone the context instead of repeating the same code --- core/src/context.rs | 9 +++++++++ glium_platform/src/platform.rs | 12 ++++-------- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/core/src/context.rs b/core/src/context.rs index 01db2f9..a89d46c 100644 --- a/core/src/context.rs +++ b/core/src/context.rs @@ -1,7 +1,16 @@ +use std::cell::RefCell; +use std::rc::Rc; use winit::event::Event; use raidillon_assets::{ModelManagerRef, ModelManager}; +// TODO: Find a way to move this to raidillon_platform as it belongs there. +// TODO: The name "Context" doesn't imply the wide role of this structure. + +/// This provides a bridge between the game logic systems (raidillon_core::System) and +/// platform-related data/utilities. +#[derive(Clone)] pub struct PlatformContext { + /// The latest winit event. pub current_event: Event<()>, pub asset_manager: ModelManagerRef, pub frame_width: f32, diff --git a/glium_platform/src/platform.rs b/glium_platform/src/platform.rs index 9a491c2..478974f 100644 --- a/glium_platform/src/platform.rs +++ b/glium_platform/src/platform.rs @@ -65,7 +65,7 @@ impl Platform for GliumPlatform { frame_width: w as f32, frame_height: h as f32, }; - self.engine.initialize(ctx); + self.engine.initialize(ctx.clone()); let _ = &self.event_loop.run(move |event, el| { match event { Event::WindowEvent { event, .. } => match event { @@ -91,13 +91,9 @@ impl Platform for GliumPlatform { _ => {}, }, Event::AboutToWait => { - let ctx = PlatformContext { - current_event: event.clone(), - asset_manager: self.asset_manager.clone(), - frame_width: w as f32, - frame_height: h as f32, - }; - self.engine.update(ctx); + let mut ctx2 = ctx.clone(); + ctx2.current_event = event.clone(); + self.engine.update(ctx2); self.window.request_redraw(); } _ => {}, From 3fd5b09a9401ac6655578e18ff7db31a32fb6f74 Mon Sep 17 00:00:00 2001 From: reo Date: Sat, 6 Sep 2025 11:52:49 +0300 Subject: [PATCH 42/89] Initial implementation of imgui support --- game/src/main.rs | 6 ++- glium_platform/Cargo.toml | 5 +- glium_platform/src/lib.rs | 2 +- glium_platform/src/platform.rs | 7 ++- glium_platform/src/render/debug_ui.rs | 77 +++++++++++++++++++++++++++ glium_platform/src/render/mod.rs | 2 + 6 files changed, 95 insertions(+), 4 deletions(-) create mode 100644 glium_platform/src/render/debug_ui.rs diff --git a/game/src/main.rs b/game/src/main.rs index fe810dd..e72db32 100644 --- a/game/src/main.rs +++ b/game/src/main.rs @@ -44,7 +44,11 @@ impl System for RenderingTestSystem { )); } - fn update(&mut self, ctx: &mut SystemContext) {} + fn update(&mut self, ctx: &mut SystemContext) { + // if let Some(mut debug_ui) = ctx.platform_context.imgui_ui.as_ref().map(|ui| ui.borrow_mut()) { + // debug_ui.text("Hello World!"); + // } + } } fn main() { diff --git a/glium_platform/Cargo.toml b/glium_platform/Cargo.toml index c206b4e..ebae599 100644 --- a/glium_platform/Cargo.toml +++ b/glium_platform/Cargo.toml @@ -13,4 +13,7 @@ raidillon_core = { path = "../core" } raidillon_assets = { path = "../asset" } raidillon_ecs = { path = "../ecs" } winit = "0.30.12" -indexmap = "2.10.0" \ No newline at end of file +indexmap = "2.10.0" +imgui = "0.12.0" +imgui-winit-support = "0.13.0" +imgui-glium-renderer = "0.13.0" diff --git a/glium_platform/src/lib.rs b/glium_platform/src/lib.rs index 7d91b4d..6fd924f 100644 --- a/glium_platform/src/lib.rs +++ b/glium_platform/src/lib.rs @@ -5,6 +5,6 @@ pub mod gltf_loader; pub mod system; mod render; -pub use assets::{GliumAssetManager}; +pub use assets::GliumAssetManager; pub use platform::GliumPlatform; pub use system::RenderingSystem; diff --git a/glium_platform/src/platform.rs b/glium_platform/src/platform.rs index 478974f..bf1aeac 100644 --- a/glium_platform/src/platform.rs +++ b/glium_platform/src/platform.rs @@ -14,6 +14,7 @@ use winit::event::{Event, WindowEvent}; use raidillon_assets::{ModelManager, ModelManagerRef}; use raidillon_core::Engine; use crate::{GliumAssetManager}; +use crate::render::debug_ui::ImguiBridge; use crate::render::BasicMeshRenderingSystem; pub const MESH_RENDERER: &str = "mesh_renderer"; @@ -25,6 +26,7 @@ pub struct GliumPlatform { rendering_system_manager: RenderingSystemManager, asset_manager: ModelManagerRef, engine: Engine, + imgui_bridge: ImguiBridge, } impl Platform for GliumPlatform { @@ -47,13 +49,16 @@ impl Platform for GliumPlatform { Box::new(BasicMeshRenderingSystem::initialize(&display)) ); + let imgui_bridge = ImguiBridge::new(&display, &window).unwrap(); + Self { event_loop, window, display, rendering_system_manager, asset_manager, - engine + engine, + imgui_bridge, } } diff --git a/glium_platform/src/render/debug_ui.rs b/glium_platform/src/render/debug_ui.rs new file mode 100644 index 0000000..796be6d --- /dev/null +++ b/glium_platform/src/render/debug_ui.rs @@ -0,0 +1,77 @@ +use std::cell::RefCell; +use std::rc::Rc; +use std::time::Instant; +use glium::Display; +use glium::glutin::surface::WindowSurface; +use imgui::{Context as ImguiContext}; +use imgui_winit_support::{HiDpiMode, WinitPlatform}; +use imgui_glium_renderer::Renderer as ImguiGliumRenderer; +use winit::raw_window_handle::DisplayHandle; +use winit::window::Window; +use anyhow::Result; +use crate::RenderingSystem; +use crate::system::RenderingContext; +use glium::Frame; + +pub struct ImguiBridge { + imgui: ImguiContext, + platform: WinitPlatform, + renderer: ImguiGliumRenderer, +} + +impl ImguiBridge { + pub fn new(display: &Display, window: &Window) -> Result { + let mut imgui = ImguiContext::create(); + imgui.set_ini_filename(None); + let mut platform = WinitPlatform::new(&mut imgui); + platform.attach_window(imgui.io_mut(), window, HiDpiMode::Default); + imgui.fonts().add_font(&[imgui::FontSource::DefaultFontData { config: None }]); + let renderer = ImguiGliumRenderer::new(&mut imgui, display)?; + + Ok(Self { + imgui, + platform, + renderer, + }) + } + + pub fn render(&mut self, target: &mut Frame, window: &Window, build_ui: F) + where + F: FnOnce(&imgui::Ui), + { + let ui = self.imgui.frame(); + + build_ui(&ui); + + self.platform.prepare_render(ui, window); + let draw_data = self.imgui.render(); + + self + .renderer + .render(target, draw_data) + .expect("imgui rendering failed"); + } + + pub fn initialize_frame(&mut self) -> &mut imgui::Ui { + self.imgui.frame() + } + + pub fn finish_frame(&mut self, target: &mut Frame, window: &Window, ui: imgui::Ui) { + self.platform.prepare_render(&ui, window); + let draw_data = self.imgui.render(); + self.renderer.render(target, draw_data).expect("imgui rendering failed"); + } +} + +impl RenderingSystem for ImguiBridge { + fn render(&mut self, ctx: &mut RenderingContext) { + todo!() + } + + fn initialize(display: &Display) -> Self + where + Self: Sized, + { + todo!() + } +} \ No newline at end of file diff --git a/glium_platform/src/render/mod.rs b/glium_platform/src/render/mod.rs index 01028df..e98554f 100644 --- a/glium_platform/src/render/mod.rs +++ b/glium_platform/src/render/mod.rs @@ -1,2 +1,4 @@ mod basic; +pub mod debug_ui; + pub use basic::BasicMeshRenderingSystem; \ No newline at end of file From 15122b8ebd56014eae41334e4ca969bb163d0f21 Mon Sep 17 00:00:00 2001 From: reo Date: Sun, 7 Sep 2025 17:00:04 +0300 Subject: [PATCH 43/89] wip: Changes of the week - Move engine to a different crate - Add engine trait - Refactor the rest of the codebase to work with these changes - Add debug ui buffer, use it to finish imgui support --- Cargo.lock | 114 ++++++++++++++++++++++++++ Cargo.toml | 3 +- core/Cargo.toml | 1 + core/src/context.rs | 7 +- core/src/debug_ui.rs | 40 +++++++++ core/src/engine.rs | 64 +++------------ core/src/lib.rs | 11 +-- core/src/scene.rs | 2 + engine/Cargo.toml | 12 +++ engine/src/engine.rs | 83 +++++++++++++++++++ engine/src/lib.rs | 4 + {core => engine}/src/system.rs | 8 +- game/Cargo.toml | 1 + game/src/main.rs | 8 +- glium_platform/Cargo.toml | 1 + glium_platform/src/platform.rs | 27 +++--- glium_platform/src/render/basic.rs | 2 +- glium_platform/src/render/debug_ui.rs | 60 +++++++------- glium_platform/src/system.rs | 7 +- platform/src/platform.rs | 6 +- 20 files changed, 344 insertions(+), 117 deletions(-) create mode 100644 core/src/debug_ui.rs create mode 100644 engine/Cargo.toml create mode 100644 engine/src/engine.rs create mode 100644 engine/src/lib.rs rename {core => engine}/src/system.rs (80%) diff --git a/Cargo.lock b/Cargo.lock index 0c0aafe..adf963e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -245,6 +245,12 @@ dependencies = [ "libc", ] +[[package]] +name = "chlorine" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c00d31b1d19317b4777ec879192d3745bd97d05262b4b19cb1dda284b9d22f19" + [[package]] name = "combine" version = "4.6.7" @@ -642,6 +648,51 @@ dependencies = [ "zune-jpeg", ] +[[package]] +name = "imgui" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8addafa5cecf0515812226e806913814e02ce38d10215778082af5174abe5669" +dependencies = [ + "bitflags 1.3.2", + "cfg-if", + "imgui-sys", + "mint", + "parking_lot", +] + +[[package]] +name = "imgui-glium-renderer" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "781e53a393214a132c89c62e6e4b817645ad38832d3e334b2ad543f2c3df5106" +dependencies = [ + "glium", + "imgui", +] + +[[package]] +name = "imgui-sys" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ead193f9f4b60398e8b8f4ab1483e2321640d87aeebdaa3e5f44c55633ccd804" +dependencies = [ + "cc", + "cfg-if", + "chlorine", + "mint", +] + +[[package]] +name = "imgui-winit-support" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff7fcccfa9efab56c94274c0fec9939bb14149342b49e6a425883a5b7dda6a3f" +dependencies = [ + "imgui", + "winit", +] + [[package]] name = "indexmap" version = "2.10.0" @@ -757,6 +808,16 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" +[[package]] +name = "lock_api" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765" +dependencies = [ + "autocfg", + "scopeguard", +] + [[package]] name = "log" version = "0.4.27" @@ -797,6 +858,12 @@ dependencies = [ "simd-adler32", ] +[[package]] +name = "mint" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e53debba6bda7a793e5f99b8dacf19e626084f525f7829104ba9898f367d85ff" + [[package]] name = "ndk" version = "0.9.0" @@ -1137,6 +1204,29 @@ dependencies = [ "ttf-parser", ] +[[package]] +name = "parking_lot" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall 0.5.17", + "smallvec", + "windows-targets 0.52.6", +] + [[package]] name = "percent-encoding" version = "2.3.1" @@ -1253,6 +1343,7 @@ name = "raidillon_core" version = "0.1.0" dependencies = [ "hecs", + "imgui", "indexmap", "raidillon_assets", "winit", @@ -1266,6 +1357,18 @@ dependencies = [ "raidillon_assets", ] +[[package]] +name = "raidillon_engine" +version = "0.1.0" +dependencies = [ + "hecs", + "indexmap", + "raidillon_assets", + "raidillon_core", + "raidillon_platform", + "winit", +] + [[package]] name = "raidillon_game" version = "0.1.0" @@ -1274,6 +1377,7 @@ dependencies = [ "raidillon_assets", "raidillon_core", "raidillon_ecs", + "raidillon_engine", "raidillon_glium", "raidillon_platform", ] @@ -1286,10 +1390,14 @@ dependencies = [ "glam", "glium", "gltf", + "imgui", + "imgui-glium-renderer", + "imgui-winit-support", "indexmap", "raidillon_assets", "raidillon_core", "raidillon_ecs", + "raidillon_engine", "raidillon_platform", "winit", ] @@ -1387,6 +1495,12 @@ 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" diff --git a/Cargo.toml b/Cargo.toml index aedf63e..102844c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,5 +5,6 @@ members = [ "platform", "asset", "game", - "ecs" + "ecs", + "engine" ] diff --git a/core/Cargo.toml b/core/Cargo.toml index 7b8bf94..fc6b73f 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -8,3 +8,4 @@ hecs = "0.10.5" indexmap = "2.10.0" raidillon_assets = { path = "../asset" } winit = "0.30.12" +imgui = "0.12.0" \ No newline at end of file diff --git a/core/src/context.rs b/core/src/context.rs index a89d46c..f1cdffe 100644 --- a/core/src/context.rs +++ b/core/src/context.rs @@ -1,16 +1,11 @@ use std::cell::RefCell; use std::rc::Rc; +use std::sync::Arc; use winit::event::Event; use raidillon_assets::{ModelManagerRef, ModelManager}; -// TODO: Find a way to move this to raidillon_platform as it belongs there. -// TODO: The name "Context" doesn't imply the wide role of this structure. - -/// This provides a bridge between the game logic systems (raidillon_core::System) and -/// platform-related data/utilities. #[derive(Clone)] pub struct PlatformContext { - /// The latest winit event. pub current_event: Event<()>, pub asset_manager: ModelManagerRef, pub frame_width: f32, diff --git a/core/src/debug_ui.rs b/core/src/debug_ui.rs new file mode 100644 index 0000000..18d846f --- /dev/null +++ b/core/src/debug_ui.rs @@ -0,0 +1,40 @@ +pub enum UICommand { + Text(String), + Separator, +} + +pub struct DebugUIBuffer { + cmds: Vec, +} + +impl DebugUIBuffer { + pub fn new() -> DebugUIBuffer { + DebugUIBuffer { cmds: vec![] } + } + + // Commands + pub fn text(&mut self, text: String) { + self.cmds.push(UICommand::Text(text)); + } + + pub fn separator(&mut self) { + self.cmds.push(UICommand::Separator); + } + + pub fn write_buffer(&self, ui: &imgui::Ui) { + for cmd in &self.cmds { + match cmd { + UICommand::Text(s) => { + ui.text(s); + } + UICommand::Separator => { + ui.separator(); + } + } + } + } + + pub fn reset_buffer(&mut self) { + self.cmds = vec![]; + } +} diff --git a/core/src/engine.rs b/core/src/engine.rs index 6eb000f..4c73815 100644 --- a/core/src/engine.rs +++ b/core/src/engine.rs @@ -1,59 +1,15 @@ use std::cell::RefCell; use std::rc::Rc; -use winit::event::Event; -use crate::SceneManager; -use crate::system::{SystemContext, SystemManager}; -use raidillon_assets::{ModelManager, ModelManagerRef}; use crate::context::PlatformContext; +use crate::DebugUIBuffer; +use crate::scene::Scene; -pub struct Engine { - pub scene_manager: SceneManager, - pub system_manager: SystemManager, -} - -impl Engine { - pub fn new() -> Self { - let scene_manager = SceneManager::new(); - let system_manager = SystemManager::new(); - Self { - scene_manager, - system_manager, - } - } - - /// Initialize systems, load the world. - pub fn initialize(&mut self, platform_context: PlatformContext) { - // Engine Loading Stage 1: initialize systems - for (system_id, system) in self.system_manager.systems.iter_mut() { - system.initialize(); - } - - let mut ctx = SystemContext { - scene: self.scene_manager.current_mut(), - platform_context, - }; - - // Engine Loading Stage 2: load world - for (system_id, system) in self.system_manager.systems.iter_mut() { - system.load_world(&mut ctx); - } - } - - /// Update the engine - pub fn update(&mut self, platform_context: PlatformContext) { - let mut ctx = SystemContext { - scene: self.scene_manager.current_mut(), - platform_context, - }; - - for (system_id, system) in self.system_manager.systems.iter_mut() { - system.update(&mut ctx); - } - } - - // pub fn build_system_context(&mut self) -> SystemContext { - // SystemContext { - // scene: self.scene_manager.current_mut(), - // } - // } +pub trait EngineTrait { + fn new() -> Self; + fn initialize(&mut self, platform_context: PlatformContext); + fn update(&mut self, platform_context: PlatformContext); + fn current_scene_mut(&mut self) -> &mut Scene; + fn get_debug_ui_buffer(&self) -> Rc>; + fn reset_debug_ui_buffer(&mut self); + fn scene_and_debug_ui_buffer_mut(&mut self) -> (&mut Scene, Rc>); } diff --git a/core/src/lib.rs b/core/src/lib.rs index 6fddfd0..b6fc074 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -1,8 +1,5 @@ -mod scene; -mod engine; -pub mod system; +pub mod engine; +pub mod scene; pub mod context; - -pub use scene::{Scene, SceneManager}; -pub use engine::Engine; -pub use system::{System, SystemManager}; +pub mod debug_ui; +pub use debug_ui::*; \ No newline at end of file diff --git a/core/src/scene.rs b/core/src/scene.rs index 94b49fa..9d1a7d4 100644 --- a/core/src/scene.rs +++ b/core/src/scene.rs @@ -17,6 +17,8 @@ impl Scene { } } +impl Scene {} + impl AsRef for Scene { fn as_ref(&self) -> &Scene { &self diff --git a/engine/Cargo.toml b/engine/Cargo.toml new file mode 100644 index 0000000..726ac44 --- /dev/null +++ b/engine/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "raidillon_engine" +version = "0.1.0" +edition = "2024" + +[dependencies] +raidillon_assets = { path = "../asset" } +raidillon_core = { path = "../core" } +raidillon_platform = { path = "../platform" } +winit = "0.30.12" +hecs = "0.10.5" +indexmap = "2.10.0" diff --git a/engine/src/engine.rs b/engine/src/engine.rs new file mode 100644 index 0000000..ea6a894 --- /dev/null +++ b/engine/src/engine.rs @@ -0,0 +1,83 @@ +use std::cell::RefCell; +use std::rc::Rc; +use winit::event::Event; +use raidillon_core::scene::{Scene, SceneManager}; +use crate::system::{SystemContext, SystemManager}; +use raidillon_assets::{ModelManager, ModelManagerRef}; +use raidillon_core::context::PlatformContext; +use raidillon_core::DebugUIBuffer; +use raidillon_core::engine::{EngineTrait}; + +pub struct Engine { + pub scene_manager: SceneManager, + pub system_manager: SystemManager, + debug_ui_buffer: Rc>, +} + +impl EngineTrait for Engine { + fn new() -> Self { + let scene_manager = SceneManager::new(); + let system_manager = SystemManager::new(); + Self { + scene_manager, + system_manager, + debug_ui_buffer: Rc::new(RefCell::new(DebugUIBuffer::new())), + } + } + + /// Initialize systems, load the world. + fn initialize(&mut self, platform_context: PlatformContext) { + // Engine Loading Stage 1: initialize systems + for (system_id, system) in self.system_manager.systems.iter_mut() { + system.initialize(); + } + + let mut ctx = SystemContext { + scene: self.scene_manager.current_mut(), + platform_context, + debug_ui_buffer: self.debug_ui_buffer.clone(), + }; + + // Engine Loading Stage 2: load world + for (system_id, system) in self.system_manager.systems.iter_mut() { + system.load_world(&mut ctx); + } + } + + /// Update the engine + fn update(&mut self, platform_context: PlatformContext) { + self.debug_ui_buffer.borrow_mut().reset_buffer(); + let mut ctx = SystemContext { + scene: self.scene_manager.current_mut(), + platform_context, + debug_ui_buffer: self.debug_ui_buffer.clone(), + }; + + for (system_id, system) in self.system_manager.systems.iter_mut() { + system.update(&mut ctx); + } + } + + // pub fn build_system_context(&mut self) -> SystemContext { + // SystemContext { + // scene: self.scene_manager.current_mut(), + // } + // } + + fn current_scene_mut(&mut self) -> &mut Scene { + self.scene_manager.current_mut() + } + + fn get_debug_ui_buffer(&self) -> Rc> { + self.debug_ui_buffer.clone() + } + + fn reset_debug_ui_buffer(&mut self) { + self.debug_ui_buffer.borrow_mut().reset_buffer(); + } + + fn scene_and_debug_ui_buffer_mut(&mut self) -> (&mut Scene, Rc>) { + let (sm, dub) = (&mut self.scene_manager, &mut self.debug_ui_buffer); + (sm.current_mut(), dub.clone()) + } +} diff --git a/engine/src/lib.rs b/engine/src/lib.rs new file mode 100644 index 0000000..e17307d --- /dev/null +++ b/engine/src/lib.rs @@ -0,0 +1,4 @@ +pub mod engine; +pub mod system; + +pub use crate::engine::Engine; \ No newline at end of file diff --git a/core/src/system.rs b/engine/src/system.rs similarity index 80% rename from core/src/system.rs rename to engine/src/system.rs index 4412d7b..18eb01e 100644 --- a/core/src/system.rs +++ b/engine/src/system.rs @@ -1,12 +1,16 @@ -use crate::Scene; +use std::cell::RefCell; +use std::rc::Rc; +use raidillon_core::scene::Scene; use indexmap::IndexMap; use winit::event::Event; -use crate::context::PlatformContext; +use raidillon_core::context::PlatformContext; +use raidillon_core::DebugUIBuffer; pub struct SystemContext<'a> { // TODO: time delta etc. pub scene: &'a mut Scene, pub platform_context: PlatformContext, + pub debug_ui_buffer: Rc>, } pub trait System { diff --git a/game/Cargo.toml b/game/Cargo.toml index e8fac5f..0e1d7e9 100644 --- a/game/Cargo.toml +++ b/game/Cargo.toml @@ -12,5 +12,6 @@ raidillon_core = { path = "../core" } raidillon_platform = { path = "../platform" } raidillon_assets = { path = "../asset" } raidillon_ecs = { path = "../ecs" } +raidillon_engine = { path = "../engine" } raidillon_glium = { path = "../glium_platform", optional = true } glam = "0.30.5" diff --git a/game/src/main.rs b/game/src/main.rs index e72db32..c19ca94 100644 --- a/game/src/main.rs +++ b/game/src/main.rs @@ -1,13 +1,16 @@ use std::path::Path; use glam::{Quat, Vec3}; -use raidillon_core::{Engine, Scene, System}; -use raidillon_core::system::SystemContext; +use raidillon_engine::{Engine, system::System}; +use raidillon_engine::system::SystemContext; use raidillon_platform::{Platform, Camera}; use raidillon_assets::model_path; +use raidillon_core::engine::EngineTrait; use raidillon_ecs::components::ModelHandle; use raidillon_ecs::Transform; +use raidillon_core::scene::Scene; #[cfg(feature = "glium")] use raidillon_glium::GliumPlatform; +use raidillon_core::DebugUIBuffer; const TEST_GLTF: &str = "pink-monkey.gltf"; @@ -48,6 +51,7 @@ impl System for RenderingTestSystem { // if let Some(mut debug_ui) = ctx.platform_context.imgui_ui.as_ref().map(|ui| ui.borrow_mut()) { // debug_ui.text("Hello World!"); // } + ctx.debug_ui_buffer.borrow_mut().text("Hello World!".to_owned()); } } diff --git a/glium_platform/Cargo.toml b/glium_platform/Cargo.toml index ebae599..0c0ecc2 100644 --- a/glium_platform/Cargo.toml +++ b/glium_platform/Cargo.toml @@ -12,6 +12,7 @@ raidillon_platform = { path = "../platform" } raidillon_core = { path = "../core" } raidillon_assets = { path = "../asset" } raidillon_ecs = { path = "../ecs" } +raidillon_engine = { path = "../engine" } winit = "0.30.12" indexmap = "2.10.0" imgui = "0.12.0" diff --git a/glium_platform/src/platform.rs b/glium_platform/src/platform.rs index bf1aeac..c01cf60 100644 --- a/glium_platform/src/platform.rs +++ b/glium_platform/src/platform.rs @@ -12,25 +12,26 @@ use glium::Surface; use crate::system::{RenderingSystemManager, RenderingSystem, RenderingContext, SystemID}; use winit::event::{Event, WindowEvent}; use raidillon_assets::{ModelManager, ModelManagerRef}; -use raidillon_core::Engine; +use raidillon_core::engine::EngineTrait; +use raidillon_engine::Engine; use crate::{GliumAssetManager}; use crate::render::debug_ui::ImguiBridge; use crate::render::BasicMeshRenderingSystem; pub const MESH_RENDERER: &str = "mesh_renderer"; +pub const DEBUG_UI_RENDERER: &str = "debug_ui_renderer"; -pub struct GliumPlatform { +pub struct GliumPlatform { event_loop: EventLoop<()>, window: Window, display: Display, rendering_system_manager: RenderingSystemManager, asset_manager: ModelManagerRef, - engine: Engine, - imgui_bridge: ImguiBridge, + engine: E, } -impl Platform for GliumPlatform { - fn initialize(mut engine: Engine, title: String, width: u32, height: u32) -> Self { +impl Platform for GliumPlatform { + fn initialize(mut engine: E, title: String, width: u32, height: u32) -> Self { let event_loop = glium::winit::event_loop::EventLoop::builder() .build() .expect("create event-loop"); @@ -46,10 +47,13 @@ impl Platform for GliumPlatform { // Install rendering systems rendering_system_manager.add_system( MESH_RENDERER, - Box::new(BasicMeshRenderingSystem::initialize(&display)) + Box::new(BasicMeshRenderingSystem::initialize(&display, &window)) ); - let imgui_bridge = ImguiBridge::new(&display, &window).unwrap(); + rendering_system_manager.add_system( + DEBUG_UI_RENDERER, + Box::new(ImguiBridge::initialize(&display, &window)), + ); Self { event_loop, @@ -58,7 +62,6 @@ impl Platform for GliumPlatform { rendering_system_manager, asset_manager, engine, - imgui_bridge, } } @@ -81,11 +84,13 @@ impl Platform for GliumPlatform { WindowEvent::RedrawRequested => { let mut target = self.display.draw(); target.clear_color_and_depth((0.1, 0.1, 0.15, 1.0), 1.0); - // TODO: let mut context; + let (scene_mut, debug_ui_buffer) = self.engine.scene_and_debug_ui_buffer_mut(); let mut context = RenderingContext { - scene: self.engine.scene_manager.current_mut(), + scene: scene_mut, target: &mut target, asset_manager: self.asset_manager.clone(), + window: &mut self.window, + debug_ui_buffer, }; for (system_id, system) in self.rendering_system_manager.systems.iter_mut() { diff --git a/glium_platform/src/render/basic.rs b/glium_platform/src/render/basic.rs index 60e7621..0f1db93 100644 --- a/glium_platform/src/render/basic.rs +++ b/glium_platform/src/render/basic.rs @@ -20,7 +20,7 @@ pub struct BasicMeshRenderingSystem { } impl RenderingSystem for BasicMeshRenderingSystem { - fn initialize(display: &Display) -> Self { + fn initialize(display: &Display, _window: &glium::winit::window::Window) -> Self { const VERT_SRC: &str = include_shader!("gl_textured.vert"); const FRAG_SRC: &str = include_shader!("gl_textured.frag"); diff --git a/glium_platform/src/render/debug_ui.rs b/glium_platform/src/render/debug_ui.rs index 796be6d..3f141c5 100644 --- a/glium_platform/src/render/debug_ui.rs +++ b/glium_platform/src/render/debug_ui.rs @@ -1,5 +1,6 @@ use std::cell::RefCell; use std::rc::Rc; +use std::sync::Arc; use std::time::Instant; use glium::Display; use glium::glutin::surface::WindowSurface; @@ -8,10 +9,11 @@ use imgui_winit_support::{HiDpiMode, WinitPlatform}; use imgui_glium_renderer::Renderer as ImguiGliumRenderer; use winit::raw_window_handle::DisplayHandle; use winit::window::Window; -use anyhow::Result; +use anyhow::{Result}; use crate::RenderingSystem; use crate::system::RenderingContext; use glium::Frame; +use raidillon_core::DebugUIBuffer; pub struct ImguiBridge { imgui: ImguiContext, @@ -20,21 +22,6 @@ pub struct ImguiBridge { } impl ImguiBridge { - pub fn new(display: &Display, window: &Window) -> Result { - let mut imgui = ImguiContext::create(); - imgui.set_ini_filename(None); - let mut platform = WinitPlatform::new(&mut imgui); - platform.attach_window(imgui.io_mut(), window, HiDpiMode::Default); - imgui.fonts().add_font(&[imgui::FontSource::DefaultFontData { config: None }]); - let renderer = ImguiGliumRenderer::new(&mut imgui, display)?; - - Ok(Self { - imgui, - platform, - renderer, - }) - } - pub fn render(&mut self, target: &mut Frame, window: &Window, build_ui: F) where F: FnOnce(&imgui::Ui), @@ -52,26 +39,43 @@ impl ImguiBridge { .expect("imgui rendering failed"); } - pub fn initialize_frame(&mut self) -> &mut imgui::Ui { - self.imgui.frame() - } - - pub fn finish_frame(&mut self, target: &mut Frame, window: &Window, ui: imgui::Ui) { - self.platform.prepare_render(&ui, window); - let draw_data = self.imgui.render(); - self.renderer.render(target, draw_data).expect("imgui rendering failed"); - } + // pub fn initialize_frame(&mut self) -> &mut imgui::Ui { + // self.imgui.frame() + // } + // + // pub fn finish_frame(&mut self, target: &mut Frame, window: &Window, ui: imgui::Ui) { + // self.platform.prepare_render(&ui, window); + // let draw_data = self.imgui.render(); + // self.renderer.render(target, draw_data).expect("imgui rendering failed"); + // } } impl RenderingSystem for ImguiBridge { fn render(&mut self, ctx: &mut RenderingContext) { - todo!() + let mut ui = self.imgui.frame(); + + ctx.debug_ui_buffer.borrow_mut().write_buffer(&mut ui); + + self.platform.prepare_render(&ui, ctx.window); + let draw_data = self.imgui.render(); + self.renderer.render(ctx.target, draw_data).expect("imgui rendering failed"); } - fn initialize(display: &Display) -> Self + fn initialize(display: &Display, window: &glium::winit::window::Window) -> Self where Self: Sized, { - todo!() + let mut imgui = ImguiContext::create(); + imgui.set_ini_filename(None); + let mut platform = WinitPlatform::new(&mut imgui); + platform.attach_window(imgui.io_mut(), window, HiDpiMode::Default); + imgui.fonts().add_font(&[imgui::FontSource::DefaultFontData { config: None }]); + let renderer = ImguiGliumRenderer::new(&mut imgui, display).unwrap(); + + Self { + imgui, + platform, + renderer, + } } } \ No newline at end of file diff --git a/glium_platform/src/system.rs b/glium_platform/src/system.rs index 63d58b4..3c21a04 100644 --- a/glium_platform/src/system.rs +++ b/glium_platform/src/system.rs @@ -1,23 +1,26 @@ use std::cell::RefCell; use std::rc::Rc; -use raidillon_core::Scene; +use raidillon_core::scene::Scene; use glium::{Display, Frame}; use glium::glutin::surface::WindowSurface; use indexmap::IndexMap; use raidillon_assets::ModelManagerRef; +use raidillon_core::DebugUIBuffer; use crate::GliumAssetManager; pub struct RenderingContext<'a> { pub scene: &'a Scene, pub target: &'a mut Frame, + pub window: &'a mut glium::winit::window::Window, pub asset_manager: ModelManagerRef, + pub debug_ui_buffer: Rc>, } /// The internal "rendering system" trait of glium_platform. /// This is unrelated to the main System trait in core. pub trait RenderingSystem { fn render(&mut self, ctx: &mut RenderingContext); - fn initialize(display: &Display) -> Self where Self: Sized; + fn initialize(display: &Display, window: &glium::winit::window::Window) -> Self where Self: Sized; } pub type SystemID = &'static str; diff --git a/platform/src/platform.rs b/platform/src/platform.rs index 3e0309f..44b799f 100644 --- a/platform/src/platform.rs +++ b/platform/src/platform.rs @@ -1,9 +1,9 @@ use raidillon_assets::ModelManager; -use raidillon_core::Engine; +use raidillon_core::engine::EngineTrait; use crate::PlatformContext; -pub trait Platform { +pub trait Platform { /// Initialize platform. - fn initialize(engine: Engine, title: String, width: u32, height: u32) -> Self; + fn initialize(engine: E, title: String, width: u32, height: u32) -> Self; fn run(self); } From 0c0d5cdb2afb3cf115dd43825159737719db1bb3 Mon Sep 17 00:00:00 2001 From: reo Date: Wed, 10 Sep 2025 01:31:43 +0300 Subject: [PATCH 44/89] Fix imgui renderer once and for all Finally solved the problems with the imgui renderer after a long chat with clankers. Fixed some other stuff as well. Reminder to keep the rendered_this_frame check as that's what solved it. Probably a deeper issue down there that caused us to render twice, but whatever. --- Cargo.lock | 1 + engine/src/system.rs | 6 +-- game/Cargo.toml | 1 + game/src/main.rs | 27 +++++++++- glium_platform/src/platform.rs | 16 ++++-- glium_platform/src/render/debug_ui.rs | 75 +++++++++++---------------- glium_platform/src/system.rs | 2 + 7 files changed, 77 insertions(+), 51 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index adf963e..3665a1b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1380,6 +1380,7 @@ dependencies = [ "raidillon_engine", "raidillon_glium", "raidillon_platform", + "winit", ] [[package]] diff --git a/engine/src/system.rs b/engine/src/system.rs index 18eb01e..cd4c1d4 100644 --- a/engine/src/system.rs +++ b/engine/src/system.rs @@ -15,10 +15,10 @@ pub struct SystemContext<'a> { pub trait System { /// Initialize the system. - fn initialize(&mut self); + fn initialize(&mut self) {} /// Spawn the first entities of the world. - fn load_world(&mut self, ctx: &mut SystemContext); - fn update(&mut self, ctx: &mut SystemContext); + fn load_world(&mut self, ctx: &mut SystemContext) {} + fn update(&mut self, ctx: &mut SystemContext) {} } pub type SystemID = &'static str; diff --git a/game/Cargo.toml b/game/Cargo.toml index 0e1d7e9..484e434 100644 --- a/game/Cargo.toml +++ b/game/Cargo.toml @@ -15,3 +15,4 @@ raidillon_ecs = { path = "../ecs" } raidillon_engine = { path = "../engine" } raidillon_glium = { path = "../glium_platform", optional = true } glam = "0.30.5" +winit = "0.30.12" diff --git a/game/src/main.rs b/game/src/main.rs index c19ca94..a02b359 100644 --- a/game/src/main.rs +++ b/game/src/main.rs @@ -11,15 +11,39 @@ use raidillon_core::scene::Scene; #[cfg(feature = "glium")] use raidillon_glium::GliumPlatform; use raidillon_core::DebugUIBuffer; +use winit::event::{Event, WindowEvent}; const TEST_GLTF: &str = "pink-monkey.gltf"; const RENDERING_TEST_SYSTEM: &str = "rendering_test_system"; +const UPDATE_ASPECT_RATIO_SYSTEM: &str = "update_aspect_ratio_system"; + const MAIN_SCENE_ID: &str = "main_scene"; -struct RenderingTestSystem; +struct UpdateAspectRatioSystem; +impl System for UpdateAspectRatioSystem { + fn initialize(&mut self) {} + fn load_world(&mut self, ctx: &mut SystemContext) {} + + fn update(&mut self, ctx: &mut SystemContext) { + // FIXME: Need an event handler rework for systems. + match &ctx.platform_context.current_event { + Event::WindowEvent { event, .. } => match event { + WindowEvent::Resized(sz) => { + let _ = ctx.scene.world.query_mut::<&mut Camera>().into_iter().map(|mut cam| { + cam.1.aspect = sz.width as f32 / sz.height as f32; + }); + } + _ => {} + }, + _ => {} + } + } +} + +struct RenderingTestSystem; impl System for RenderingTestSystem { fn initialize(&mut self) {} fn load_world(&mut self, ctx: &mut SystemContext) { @@ -61,6 +85,7 @@ fn main() { // engine.system_manager.add_system("spawn_chunks".to_string(), ChunkSystem); // engine.system_manager.add_system("movement".to_string(), MovementSystem); engine.system_manager.add_system(RENDERING_TEST_SYSTEM, Box::new(RenderingTestSystem)); + engine.system_manager.add_system(UPDATE_ASPECT_RATIO_SYSTEM, Box::new(UpdateAspectRatioSystem)); // Set up the scene let main_scene = Scene::new( diff --git a/glium_platform/src/platform.rs b/glium_platform/src/platform.rs index c01cf60..34864c3 100644 --- a/glium_platform/src/platform.rs +++ b/glium_platform/src/platform.rs @@ -75,6 +75,11 @@ impl Platform for GliumPlatform { }; self.engine.initialize(ctx.clone()); let _ = &self.event_loop.run(move |event, el| { + self.rendering_system_manager + .systems + .iter_mut() + .for_each(|(_, system)| system.handle_event(&mut self.window, event.clone())); + match event { Event::WindowEvent { event, .. } => match event { WindowEvent::CloseRequested => { @@ -93,9 +98,10 @@ impl Platform for GliumPlatform { debug_ui_buffer, }; - for (system_id, system) in self.rendering_system_manager.systems.iter_mut() { - system.render(&mut context); - } + self.rendering_system_manager + .systems + .iter_mut() + .for_each(|(_, system)| system.render(&mut context)); target.finish().unwrap(); } _ => {}, @@ -104,6 +110,10 @@ impl Platform for GliumPlatform { let mut ctx2 = ctx.clone(); ctx2.current_event = event.clone(); self.engine.update(ctx2); + self.rendering_system_manager + .systems + .iter_mut() + .for_each(|(_, system)| system.prepare_frame(&mut self.window)); self.window.request_redraw(); } _ => {}, diff --git a/glium_platform/src/render/debug_ui.rs b/glium_platform/src/render/debug_ui.rs index 3f141c5..ff29fe1 100644 --- a/glium_platform/src/render/debug_ui.rs +++ b/glium_platform/src/render/debug_ui.rs @@ -1,70 +1,55 @@ -use std::cell::RefCell; -use std::rc::Rc; -use std::sync::Arc; use std::time::Instant; use glium::Display; use glium::glutin::surface::WindowSurface; use imgui::{Context as ImguiContext}; use imgui_winit_support::{HiDpiMode, WinitPlatform}; use imgui_glium_renderer::Renderer as ImguiGliumRenderer; -use winit::raw_window_handle::DisplayHandle; use winit::window::Window; -use anyhow::{Result}; +use winit::event::Event; +use glium::Frame; use crate::RenderingSystem; use crate::system::RenderingContext; -use glium::Frame; -use raidillon_core::DebugUIBuffer; pub struct ImguiBridge { imgui: ImguiContext, platform: WinitPlatform, renderer: ImguiGliumRenderer, -} - -impl ImguiBridge { - pub fn render(&mut self, target: &mut Frame, window: &Window, build_ui: F) - where - F: FnOnce(&imgui::Ui), - { - let ui = self.imgui.frame(); - - build_ui(&ui); - - self.platform.prepare_render(ui, window); - let draw_data = self.imgui.render(); - - self - .renderer - .render(target, draw_data) - .expect("imgui rendering failed"); - } - - // pub fn initialize_frame(&mut self) -> &mut imgui::Ui { - // self.imgui.frame() - // } - // - // pub fn finish_frame(&mut self, target: &mut Frame, window: &Window, ui: imgui::Ui) { - // self.platform.prepare_render(&ui, window); - // let draw_data = self.imgui.render(); - // self.renderer.render(target, draw_data).expect("imgui rendering failed"); - // } + last_frame: Instant, + rendered_this_frame: bool, } impl RenderingSystem for ImguiBridge { - fn render(&mut self, ctx: &mut RenderingContext) { - let mut ui = self.imgui.frame(); + fn handle_event(&mut self, window: &mut Window, event: Event<()>) { + self.platform.handle_event(self.imgui.io_mut(), window, &event); + } - ctx.debug_ui_buffer.borrow_mut().write_buffer(&mut ui); + fn prepare_frame(&mut self, window: &mut Window) { + self.rendered_this_frame = false; + let now = Instant::now(); + self.imgui.io_mut().update_delta_time(now - self.last_frame); + self.last_frame = now; + self.platform + .prepare_frame(self.imgui.io_mut(), window) + .expect("Failed to prepare frame"); + } + + fn render(&mut self, ctx: &mut RenderingContext) { + if self.rendered_this_frame { return; } + self.rendered_this_frame = true; + + let ui = self.imgui.frame(); + ctx.debug_ui_buffer.borrow().write_buffer(&ui); self.platform.prepare_render(&ui, ctx.window); let draw_data = self.imgui.render(); + if draw_data.total_vtx_count == 0 && draw_data.total_idx_count == 0 { + return; + } + self.renderer.render(ctx.target, draw_data).expect("imgui rendering failed"); } - fn initialize(display: &Display, window: &glium::winit::window::Window) -> Self - where - Self: Sized, - { + fn initialize(display: &Display, window: &Window) -> Self { let mut imgui = ImguiContext::create(); imgui.set_ini_filename(None); let mut platform = WinitPlatform::new(&mut imgui); @@ -76,6 +61,8 @@ impl RenderingSystem for ImguiBridge { imgui, platform, renderer, + last_frame: Instant::now(), + rendered_this_frame: false, } } -} \ No newline at end of file +} diff --git a/glium_platform/src/system.rs b/glium_platform/src/system.rs index 3c21a04..6a31a2d 100644 --- a/glium_platform/src/system.rs +++ b/glium_platform/src/system.rs @@ -19,6 +19,8 @@ pub struct RenderingContext<'a> { /// The internal "rendering system" trait of glium_platform. /// This is unrelated to the main System trait in core. pub trait RenderingSystem { + fn handle_event(&mut self, window: &mut glium::winit::window::Window, event: winit::event::Event<()>) {} + fn prepare_frame(&mut self, window: &mut glium::winit::window::Window) {} fn render(&mut self, ctx: &mut RenderingContext); fn initialize(display: &Display, window: &glium::winit::window::Window) -> Self where Self: Sized; } From 75fd59a5049f557564029f98e5fd8a85be83ac26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emre=20Osmano=C4=9Flu?= Date: Wed, 10 Sep 2025 13:21:35 +0300 Subject: [PATCH 45/89] Refactor system registration to use TypeIds --- engine/src/engine.rs | 10 ++++----- engine/src/system.rs | 25 +++++++++++---------- game/src/main.rs | 29 ++++++++++++------------ glium_platform/src/platform.rs | 41 ++++++++++++---------------------- glium_platform/src/system.rs | 36 ++++++++++++++++++----------- 5 files changed, 68 insertions(+), 73 deletions(-) diff --git a/engine/src/engine.rs b/engine/src/engine.rs index ea6a894..171d631 100644 --- a/engine/src/engine.rs +++ b/engine/src/engine.rs @@ -1,12 +1,10 @@ use std::cell::RefCell; use std::rc::Rc; -use winit::event::Event; use raidillon_core::scene::{Scene, SceneManager}; use crate::system::{SystemContext, SystemManager}; -use raidillon_assets::{ModelManager, ModelManagerRef}; use raidillon_core::context::PlatformContext; use raidillon_core::DebugUIBuffer; -use raidillon_core::engine::{EngineTrait}; +use raidillon_core::engine::EngineTrait; pub struct Engine { pub scene_manager: SceneManager, @@ -28,7 +26,7 @@ impl EngineTrait for Engine { /// Initialize systems, load the world. fn initialize(&mut self, platform_context: PlatformContext) { // Engine Loading Stage 1: initialize systems - for (system_id, system) in self.system_manager.systems.iter_mut() { + for system in self.system_manager.systems.values_mut() { system.initialize(); } @@ -39,7 +37,7 @@ impl EngineTrait for Engine { }; // Engine Loading Stage 2: load world - for (system_id, system) in self.system_manager.systems.iter_mut() { + for system in self.system_manager.systems.values_mut() { system.load_world(&mut ctx); } } @@ -53,7 +51,7 @@ impl EngineTrait for Engine { debug_ui_buffer: self.debug_ui_buffer.clone(), }; - for (system_id, system) in self.system_manager.systems.iter_mut() { + for system in self.system_manager.systems.values_mut() { system.update(&mut ctx); } } diff --git a/engine/src/system.rs b/engine/src/system.rs index cd4c1d4..1e62e52 100644 --- a/engine/src/system.rs +++ b/engine/src/system.rs @@ -1,9 +1,9 @@ +use std::any::TypeId; use std::cell::RefCell; use std::rc::Rc; -use raidillon_core::scene::Scene; use indexmap::IndexMap; -use winit::event::Event; use raidillon_core::context::PlatformContext; +use raidillon_core::scene::Scene; use raidillon_core::DebugUIBuffer; pub struct SystemContext<'a> { @@ -17,26 +17,27 @@ pub trait System { /// Initialize the system. fn initialize(&mut self) {} /// Spawn the first entities of the world. - fn load_world(&mut self, ctx: &mut SystemContext) {} - fn update(&mut self, ctx: &mut SystemContext) {} + fn load_world(&mut self, _ctx: &mut SystemContext) {} + fn update(&mut self, _ctx: &mut SystemContext) {} } -pub type SystemID = &'static str; pub struct SystemManager { - pub systems: IndexMap>, + pub systems: IndexMap>, } impl SystemManager { pub fn new() -> Self { - let systems = IndexMap::default(); - Self { systems } + Self { + systems: IndexMap::default(), + } } - pub fn add_system(&mut self, id: SystemID, system: Box) { - self.systems.insert(id, system); + pub fn add(&mut self) { + self.systems + .insert(TypeId::of::(), Box::new(S::default())); } - pub fn remove_system(&mut self, id: SystemID) { - self.systems.shift_remove(&id); + pub fn remove(&mut self) { + self.systems.shift_remove(&TypeId::of::()); } } \ No newline at end of file diff --git a/game/src/main.rs b/game/src/main.rs index a02b359..396d962 100644 --- a/game/src/main.rs +++ b/game/src/main.rs @@ -1,4 +1,3 @@ -use std::path::Path; use glam::{Quat, Vec3}; use raidillon_engine::{Engine, system::System}; use raidillon_engine::system::SystemContext; @@ -10,31 +9,32 @@ use raidillon_ecs::Transform; use raidillon_core::scene::Scene; #[cfg(feature = "glium")] use raidillon_glium::GliumPlatform; -use raidillon_core::DebugUIBuffer; use winit::event::{Event, WindowEvent}; const TEST_GLTF: &str = "pink-monkey.gltf"; -const RENDERING_TEST_SYSTEM: &str = "rendering_test_system"; - -const UPDATE_ASPECT_RATIO_SYSTEM: &str = "update_aspect_ratio_system"; - const MAIN_SCENE_ID: &str = "main_scene"; +#[derive(Default)] struct UpdateAspectRatioSystem; impl System for UpdateAspectRatioSystem { fn initialize(&mut self) {} - fn load_world(&mut self, ctx: &mut SystemContext) {} + fn load_world(&mut self, _ctx: &mut SystemContext) {} fn update(&mut self, ctx: &mut SystemContext) { // FIXME: Need an event handler rework for systems. match &ctx.platform_context.current_event { Event::WindowEvent { event, .. } => match event { WindowEvent::Resized(sz) => { - let _ = ctx.scene.world.query_mut::<&mut Camera>().into_iter().map(|mut cam| { - cam.1.aspect = sz.width as f32 / sz.height as f32; - }); + let _ = ctx + .scene + .world + .query_mut::<&mut Camera>() + .into_iter() + .map(|(_, cam)| { + cam.aspect = sz.width as f32 / sz.height as f32; + }); } _ => {} }, @@ -43,6 +43,7 @@ impl System for UpdateAspectRatioSystem { } } +#[derive(Default)] struct RenderingTestSystem; impl System for RenderingTestSystem { fn initialize(&mut self) {} @@ -82,10 +83,8 @@ impl System for RenderingTestSystem { fn main() { let mut engine = Engine::new(); // Define systems - // engine.system_manager.add_system("spawn_chunks".to_string(), ChunkSystem); - // engine.system_manager.add_system("movement".to_string(), MovementSystem); - engine.system_manager.add_system(RENDERING_TEST_SYSTEM, Box::new(RenderingTestSystem)); - engine.system_manager.add_system(UPDATE_ASPECT_RATIO_SYSTEM, Box::new(UpdateAspectRatioSystem)); + engine.system_manager.add::(); + engine.system_manager.add::(); // Set up the scene let main_scene = Scene::new( @@ -97,7 +96,7 @@ fn main() { #[cfg(feature = "glium")] { - let mut platform = GliumPlatform::initialize( + let platform = GliumPlatform::initialize( engine, "Raidillon".to_string(), 1920, diff --git a/glium_platform/src/platform.rs b/glium_platform/src/platform.rs index 34864c3..7f4320f 100644 --- a/glium_platform/src/platform.rs +++ b/glium_platform/src/platform.rs @@ -1,25 +1,19 @@ use std::cell::RefCell; use std::rc::Rc; -use std::str::FromStr; -use std::sync::{Arc, RwLock}; use raidillon_platform::{Platform, PlatformContext}; +use glium::backend::glutin::Display; +use glium::backend::glutin::SimpleWindowBuilder; +use glium::glutin::surface::WindowSurface; use glium::winit::event_loop::EventLoop; use glium::winit::window::Window; -use glium::backend::glutin::Display; -use glium::glutin::surface::WindowSurface; -use glium::backend::glutin::SimpleWindowBuilder; use glium::Surface; -use crate::system::{RenderingSystemManager, RenderingSystem, RenderingContext, SystemID}; +use crate::system::{RenderingContext, RenderingSystemManager}; use winit::event::{Event, WindowEvent}; -use raidillon_assets::{ModelManager, ModelManagerRef}; +use raidillon_assets::ModelManagerRef; use raidillon_core::engine::EngineTrait; -use raidillon_engine::Engine; -use crate::{GliumAssetManager}; use crate::render::debug_ui::ImguiBridge; use crate::render::BasicMeshRenderingSystem; - -pub const MESH_RENDERER: &str = "mesh_renderer"; -pub const DEBUG_UI_RENDERER: &str = "debug_ui_renderer"; +use crate::GliumAssetManager; pub struct GliumPlatform { event_loop: EventLoop<()>, @@ -45,15 +39,8 @@ impl Platform for GliumPlatform { let mut rendering_system_manager = RenderingSystemManager::new(); // Install rendering systems - rendering_system_manager.add_system( - MESH_RENDERER, - Box::new(BasicMeshRenderingSystem::initialize(&display, &window)) - ); - - rendering_system_manager.add_system( - DEBUG_UI_RENDERER, - Box::new(ImguiBridge::initialize(&display, &window)), - ); + rendering_system_manager.add::(&display, &window); + rendering_system_manager.add::(&display, &window); Self { event_loop, @@ -77,8 +64,8 @@ impl Platform for GliumPlatform { let _ = &self.event_loop.run(move |event, el| { self.rendering_system_manager .systems - .iter_mut() - .for_each(|(_, system)| system.handle_event(&mut self.window, event.clone())); + .values_mut() + .for_each(|system| system.handle_event(&mut self.window, event.clone())); match event { Event::WindowEvent { event, .. } => match event { @@ -100,8 +87,8 @@ impl Platform for GliumPlatform { self.rendering_system_manager .systems - .iter_mut() - .for_each(|(_, system)| system.render(&mut context)); + .values_mut() + .for_each(|system| system.render(&mut context)); target.finish().unwrap(); } _ => {}, @@ -112,8 +99,8 @@ impl Platform for GliumPlatform { self.engine.update(ctx2); self.rendering_system_manager .systems - .iter_mut() - .for_each(|(_, system)| system.prepare_frame(&mut self.window)); + .values_mut() + .for_each(|system| system.prepare_frame(&mut self.window)); self.window.request_redraw(); } _ => {}, diff --git a/glium_platform/src/system.rs b/glium_platform/src/system.rs index 6a31a2d..7f1f55e 100644 --- a/glium_platform/src/system.rs +++ b/glium_platform/src/system.rs @@ -1,12 +1,12 @@ +use std::any::TypeId; use std::cell::RefCell; use std::rc::Rc; -use raidillon_core::scene::Scene; +use indexmap::IndexMap; use glium::{Display, Frame}; use glium::glutin::surface::WindowSurface; -use indexmap::IndexMap; use raidillon_assets::ModelManagerRef; use raidillon_core::DebugUIBuffer; -use crate::GliumAssetManager; +use raidillon_core::scene::Scene; pub struct RenderingContext<'a> { pub scene: &'a Scene, @@ -19,16 +19,21 @@ pub struct RenderingContext<'a> { /// The internal "rendering system" trait of glium_platform. /// This is unrelated to the main System trait in core. pub trait RenderingSystem { - fn handle_event(&mut self, window: &mut glium::winit::window::Window, event: winit::event::Event<()>) {} - fn prepare_frame(&mut self, window: &mut glium::winit::window::Window) {} + fn handle_event( + &mut self, + _window: &mut glium::winit::window::Window, + _event: winit::event::Event<()>, + ) { + } + fn prepare_frame(&mut self, _window: &mut glium::winit::window::Window) {} fn render(&mut self, ctx: &mut RenderingContext); - fn initialize(display: &Display, window: &glium::winit::window::Window) -> Self where Self: Sized; + fn initialize(display: &Display, window: &glium::winit::window::Window) -> Self + where + Self: Sized; } -pub type SystemID = &'static str; - pub struct RenderingSystemManager { - pub systems: IndexMap>, + pub systems: IndexMap>, } impl RenderingSystemManager { @@ -37,11 +42,16 @@ impl RenderingSystemManager { systems: IndexMap::default(), } } - pub fn add_system(&mut self, id: SystemID, system: Box) { - self.systems.insert(id, system); + + pub fn add(&mut self, display: &Display, window: &glium::winit::window::Window) + where + R: RenderingSystem + 'static, + { + let system = R::initialize(display, window); + self.systems.insert(TypeId::of::(), Box::new(system)); } - pub fn remove_system(&mut self, id: SystemID) { - self.systems.shift_remove(&id); + pub fn remove(&mut self) { + self.systems.shift_remove(&TypeId::of::()); } } From 9905ffd26bb2de051f477cc9665778f5090c5ced Mon Sep 17 00:00:00 2001 From: reo Date: Thu, 18 Sep 2025 00:32:12 +0300 Subject: [PATCH 46/89] Add event handler methods to the engine structure --- core/src/engine.rs | 1 + engine/src/engine.rs | 12 ++++++++++++ engine/src/system.rs | 3 ++- game/src/main.rs | 34 ++++++++++------------------------ glium_platform/src/platform.rs | 4 ++++ 5 files changed, 29 insertions(+), 25 deletions(-) diff --git a/core/src/engine.rs b/core/src/engine.rs index 4c73815..53aeef1 100644 --- a/core/src/engine.rs +++ b/core/src/engine.rs @@ -8,6 +8,7 @@ pub trait EngineTrait { fn new() -> Self; fn initialize(&mut self, platform_context: PlatformContext); fn update(&mut self, platform_context: PlatformContext); + fn handle_event(&mut self, platform_context: PlatformContext); fn current_scene_mut(&mut self) -> &mut Scene; fn get_debug_ui_buffer(&self) -> Rc>; fn reset_debug_ui_buffer(&mut self); diff --git a/engine/src/engine.rs b/engine/src/engine.rs index 171d631..bf3b692 100644 --- a/engine/src/engine.rs +++ b/engine/src/engine.rs @@ -56,6 +56,18 @@ impl EngineTrait for Engine { } } + fn handle_event(&mut self, platform_context: PlatformContext) { + let mut ctx = SystemContext { + scene: self.scene_manager.current_mut(), + platform_context, + debug_ui_buffer: self.debug_ui_buffer.clone(), + }; + + for system in self.system_manager.systems.values_mut() { + system.handle_event(&mut ctx); + } + } + // pub fn build_system_context(&mut self) -> SystemContext { // SystemContext { // scene: self.scene_manager.current_mut(), diff --git a/engine/src/system.rs b/engine/src/system.rs index 1e62e52..b11d8fd 100644 --- a/engine/src/system.rs +++ b/engine/src/system.rs @@ -18,6 +18,7 @@ pub trait System { fn initialize(&mut self) {} /// Spawn the first entities of the world. fn load_world(&mut self, _ctx: &mut SystemContext) {} + fn handle_event(&mut self, _ctx: &mut SystemContext) {} fn update(&mut self, _ctx: &mut SystemContext) {} } @@ -40,4 +41,4 @@ impl SystemManager { pub fn remove(&mut self) { self.systems.shift_remove(&TypeId::of::()); } -} \ No newline at end of file +} diff --git a/game/src/main.rs b/game/src/main.rs index 396d962..126c2e4 100644 --- a/game/src/main.rs +++ b/game/src/main.rs @@ -18,27 +18,16 @@ const MAIN_SCENE_ID: &str = "main_scene"; #[derive(Default)] struct UpdateAspectRatioSystem; impl System for UpdateAspectRatioSystem { - fn initialize(&mut self) {} - - fn load_world(&mut self, _ctx: &mut SystemContext) {} - - fn update(&mut self, ctx: &mut SystemContext) { - // FIXME: Need an event handler rework for systems. - match &ctx.platform_context.current_event { - Event::WindowEvent { event, .. } => match event { - WindowEvent::Resized(sz) => { - let _ = ctx - .scene - .world - .query_mut::<&mut Camera>() - .into_iter() - .map(|(_, cam)| { - cam.aspect = sz.width as f32 / sz.height as f32; - }); - } - _ => {} - }, - _ => {} + fn handle_event(&mut self, ctx: &mut SystemContext) { + if let Event::WindowEvent { event: WindowEvent::Resized(sz), .. } = + &ctx.platform_context.current_event + { + ctx.scene.world + .query_mut::<&mut Camera>() + .into_iter() + .for_each(|(_, cam)| { + cam.aspect = sz.width as f32 / sz.height as f32; + }); } } } @@ -73,9 +62,6 @@ impl System for RenderingTestSystem { } fn update(&mut self, ctx: &mut SystemContext) { - // if let Some(mut debug_ui) = ctx.platform_context.imgui_ui.as_ref().map(|ui| ui.borrow_mut()) { - // debug_ui.text("Hello World!"); - // } ctx.debug_ui_buffer.borrow_mut().text("Hello World!".to_owned()); } } diff --git a/glium_platform/src/platform.rs b/glium_platform/src/platform.rs index 7f4320f..4848c7c 100644 --- a/glium_platform/src/platform.rs +++ b/glium_platform/src/platform.rs @@ -66,6 +66,10 @@ impl Platform for GliumPlatform { .systems .values_mut() .for_each(|system| system.handle_event(&mut self.window, event.clone())); + + let mut ctx2 = ctx.clone(); + ctx2.current_event = event.clone(); + self.engine.handle_event(ctx2); match event { Event::WindowEvent { event, .. } => match event { From 369bbd19c7329bc624f12e02acabbfa1b166d622 Mon Sep 17 00:00:00 2001 From: reo Date: Mon, 22 Sep 2025 19:45:30 +0300 Subject: [PATCH 47/89] Move PlatformContext to the raidillon_platform crate --- core/src/engine.rs | 8 ++++---- core/src/lib.rs | 1 - engine/src/engine.rs | 3 ++- engine/src/system.rs | 2 +- glium_platform/src/platform.rs | 4 ++-- {core => platform}/src/context.rs | 7 ++----- platform/src/lib.rs | 4 +++- platform/src/platform.rs | 2 +- 8 files changed, 15 insertions(+), 16 deletions(-) rename {core => platform}/src/context.rs (62%) diff --git a/core/src/engine.rs b/core/src/engine.rs index 53aeef1..9aafdf5 100644 --- a/core/src/engine.rs +++ b/core/src/engine.rs @@ -1,14 +1,14 @@ use std::cell::RefCell; use std::rc::Rc; -use crate::context::PlatformContext; use crate::DebugUIBuffer; use crate::scene::Scene; pub trait EngineTrait { + type PlatformCtx: Clone; fn new() -> Self; - fn initialize(&mut self, platform_context: PlatformContext); - fn update(&mut self, platform_context: PlatformContext); - fn handle_event(&mut self, platform_context: PlatformContext); + fn initialize(&mut self, platform_context: Self::PlatformCtx); + fn update(&mut self, platform_context: Self::PlatformCtx); + fn handle_event(&mut self, platform_context: Self::PlatformCtx); fn current_scene_mut(&mut self) -> &mut Scene; fn get_debug_ui_buffer(&self) -> Rc>; fn reset_debug_ui_buffer(&mut self); diff --git a/core/src/lib.rs b/core/src/lib.rs index b6fc074..ee279f9 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -1,5 +1,4 @@ pub mod engine; pub mod scene; -pub mod context; pub mod debug_ui; pub use debug_ui::*; \ No newline at end of file diff --git a/engine/src/engine.rs b/engine/src/engine.rs index bf3b692..38b6657 100644 --- a/engine/src/engine.rs +++ b/engine/src/engine.rs @@ -2,7 +2,7 @@ use std::cell::RefCell; use std::rc::Rc; use raidillon_core::scene::{Scene, SceneManager}; use crate::system::{SystemContext, SystemManager}; -use raidillon_core::context::PlatformContext; +use raidillon_platform::PlatformContext; use raidillon_core::DebugUIBuffer; use raidillon_core::engine::EngineTrait; @@ -13,6 +13,7 @@ pub struct Engine { } impl EngineTrait for Engine { + type PlatformCtx = PlatformContext; fn new() -> Self { let scene_manager = SceneManager::new(); let system_manager = SystemManager::new(); diff --git a/engine/src/system.rs b/engine/src/system.rs index b11d8fd..49b6c44 100644 --- a/engine/src/system.rs +++ b/engine/src/system.rs @@ -2,7 +2,7 @@ use std::any::TypeId; use std::cell::RefCell; use std::rc::Rc; use indexmap::IndexMap; -use raidillon_core::context::PlatformContext; +use raidillon_platform::PlatformContext; use raidillon_core::scene::Scene; use raidillon_core::DebugUIBuffer; diff --git a/glium_platform/src/platform.rs b/glium_platform/src/platform.rs index 4848c7c..97a94a1 100644 --- a/glium_platform/src/platform.rs +++ b/glium_platform/src/platform.rs @@ -15,7 +15,7 @@ use crate::render::debug_ui::ImguiBridge; use crate::render::BasicMeshRenderingSystem; use crate::GliumAssetManager; -pub struct GliumPlatform { +pub struct GliumPlatform> { event_loop: EventLoop<()>, window: Window, display: Display, @@ -24,7 +24,7 @@ pub struct GliumPlatform { engine: E, } -impl Platform for GliumPlatform { +impl> Platform for GliumPlatform { fn initialize(mut engine: E, title: String, width: u32, height: u32) -> Self { let event_loop = glium::winit::event_loop::EventLoop::builder() .build() diff --git a/core/src/context.rs b/platform/src/context.rs similarity index 62% rename from core/src/context.rs rename to platform/src/context.rs index f1cdffe..fb5ec65 100644 --- a/core/src/context.rs +++ b/platform/src/context.rs @@ -1,8 +1,5 @@ -use std::cell::RefCell; -use std::rc::Rc; -use std::sync::Arc; use winit::event::Event; -use raidillon_assets::{ModelManagerRef, ModelManager}; +use raidillon_assets::ModelManagerRef; #[derive(Clone)] pub struct PlatformContext { @@ -10,4 +7,4 @@ pub struct PlatformContext { pub asset_manager: ModelManagerRef, pub frame_width: f32, pub frame_height: f32, -} +} \ No newline at end of file diff --git a/platform/src/lib.rs b/platform/src/lib.rs index 3ff1a65..962c05f 100644 --- a/platform/src/lib.rs +++ b/platform/src/lib.rs @@ -1,6 +1,8 @@ pub mod platform; mod camera; +mod event; +pub mod context; pub use platform::Platform; pub use camera::Camera; -pub use raidillon_core::context::PlatformContext; +pub use context::PlatformContext; diff --git a/platform/src/platform.rs b/platform/src/platform.rs index 44b799f..d840723 100644 --- a/platform/src/platform.rs +++ b/platform/src/platform.rs @@ -2,7 +2,7 @@ use raidillon_assets::ModelManager; use raidillon_core::engine::EngineTrait; use crate::PlatformContext; -pub trait Platform { +pub trait Platform> { /// Initialize platform. fn initialize(engine: E, title: String, width: u32, height: u32) -> Self; fn run(self); From 50d07ffea59f2729fa9ea754610524fb407d9227 Mon Sep 17 00:00:00 2001 From: reo Date: Tue, 23 Sep 2025 21:06:24 +0300 Subject: [PATCH 48/89] Optimize imports --- platform/src/platform.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/platform/src/platform.rs b/platform/src/platform.rs index d840723..8884c46 100644 --- a/platform/src/platform.rs +++ b/platform/src/platform.rs @@ -1,6 +1,5 @@ -use raidillon_assets::ModelManager; -use raidillon_core::engine::EngineTrait; use crate::PlatformContext; +use raidillon_core::engine::EngineTrait; pub trait Platform> { /// Initialize platform. From 59963cdec142fe2ba2b0cde485a1764470106984 Mon Sep 17 00:00:00 2001 From: reo Date: Tue, 23 Sep 2025 21:11:09 +0300 Subject: [PATCH 49/89] Add pre-commit-config, run pre-commit on all files --- .pre-commit-config.yaml | 11 +++++++++++ core/src/lib.rs | 2 +- engine/src/engine.rs | 2 +- engine/src/lib.rs | 2 +- glium_platform/src/platform.rs | 2 +- glium_platform/src/render/mod.rs | 2 +- platform/src/context.rs | 2 +- platform/src/event.rs | 2 +- 8 files changed, 18 insertions(+), 7 deletions(-) create mode 100644 .pre-commit-config.yaml diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..1927e4f --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,11 @@ +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.6.0 + hooks: + - id: trailing-whitespace + files: "\\.rs$" + - id: end-of-file-fixer + files: "\\.rs$" + - id: mixed-line-ending + args: [--fix=lf] + files: "\\.rs$" diff --git a/core/src/lib.rs b/core/src/lib.rs index ee279f9..f4b8d0c 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -1,4 +1,4 @@ pub mod engine; pub mod scene; pub mod debug_ui; -pub use debug_ui::*; \ No newline at end of file +pub use debug_ui::*; diff --git a/engine/src/engine.rs b/engine/src/engine.rs index 38b6657..5d6af36 100644 --- a/engine/src/engine.rs +++ b/engine/src/engine.rs @@ -79,7 +79,7 @@ impl EngineTrait for Engine { self.scene_manager.current_mut() } - fn get_debug_ui_buffer(&self) -> Rc> { + fn get_debug_ui_buffer(&self) -> Rc> { self.debug_ui_buffer.clone() } diff --git a/engine/src/lib.rs b/engine/src/lib.rs index e17307d..b3a2dc8 100644 --- a/engine/src/lib.rs +++ b/engine/src/lib.rs @@ -1,4 +1,4 @@ pub mod engine; pub mod system; -pub use crate::engine::Engine; \ No newline at end of file +pub use crate::engine::Engine; diff --git a/glium_platform/src/platform.rs b/glium_platform/src/platform.rs index 97a94a1..97c1535 100644 --- a/glium_platform/src/platform.rs +++ b/glium_platform/src/platform.rs @@ -66,7 +66,7 @@ impl> Platform for GliumPlatfor .systems .values_mut() .for_each(|system| system.handle_event(&mut self.window, event.clone())); - + let mut ctx2 = ctx.clone(); ctx2.current_event = event.clone(); self.engine.handle_event(ctx2); diff --git a/glium_platform/src/render/mod.rs b/glium_platform/src/render/mod.rs index e98554f..c31a0d9 100644 --- a/glium_platform/src/render/mod.rs +++ b/glium_platform/src/render/mod.rs @@ -1,4 +1,4 @@ mod basic; pub mod debug_ui; -pub use basic::BasicMeshRenderingSystem; \ No newline at end of file +pub use basic::BasicMeshRenderingSystem; diff --git a/platform/src/context.rs b/platform/src/context.rs index fb5ec65..45e8fa4 100644 --- a/platform/src/context.rs +++ b/platform/src/context.rs @@ -7,4 +7,4 @@ pub struct PlatformContext { pub asset_manager: ModelManagerRef, pub frame_width: f32, pub frame_height: f32, -} \ No newline at end of file +} diff --git a/platform/src/event.rs b/platform/src/event.rs index 82ce8b6..bb27077 100644 --- a/platform/src/event.rs +++ b/platform/src/event.rs @@ -4,7 +4,7 @@ pub enum PlatformEvent { /// The platform has requested to close the app. CloseRequested, - + /// Platform event loop is about to block and wait for new /// new events. AboutToWait From 5e8897c2717ec6a975bab35edbd255fea5a9c5c9 Mon Sep 17 00:00:00 2001 From: reo Date: Tue, 23 Sep 2025 21:16:06 +0300 Subject: [PATCH 50/89] Optimize imports --- engine/src/system.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/engine/src/system.rs b/engine/src/system.rs index 49b6c44..31708b3 100644 --- a/engine/src/system.rs +++ b/engine/src/system.rs @@ -1,10 +1,10 @@ +use indexmap::IndexMap; +use raidillon_core::scene::Scene; +use raidillon_core::DebugUIBuffer; +use raidillon_platform::PlatformContext; use std::any::TypeId; use std::cell::RefCell; use std::rc::Rc; -use indexmap::IndexMap; -use raidillon_platform::PlatformContext; -use raidillon_core::scene::Scene; -use raidillon_core::DebugUIBuffer; pub struct SystemContext<'a> { // TODO: time delta etc. From 84ab3a26b16bad457d787cc57385cb95a78b5219 Mon Sep 17 00:00:00 2001 From: reo Date: Wed, 24 Sep 2025 23:20:51 +0300 Subject: [PATCH 51/89] Timing Module Update - Implement a new timing module - Utilize the new timing module in glium platform implementation for frame limiting and fixed engine updates timing. --- core/src/engine.rs | 3 +- core/src/lib.rs | 2 + core/src/time.rs | 144 +++++++++++++++++++++++++++++++++ engine/src/engine.rs | 16 +++- engine/src/system.rs | 3 +- game/src/main.rs | 17 +++- glium_platform/src/platform.rs | 37 ++++++++- platform/src/context.rs | 8 ++ platform/src/lib.rs | 2 +- 9 files changed, 221 insertions(+), 11 deletions(-) create mode 100644 core/src/time.rs diff --git a/core/src/engine.rs b/core/src/engine.rs index 9aafdf5..80d2a69 100644 --- a/core/src/engine.rs +++ b/core/src/engine.rs @@ -7,7 +7,8 @@ pub trait EngineTrait { type PlatformCtx: Clone; fn new() -> Self; fn initialize(&mut self, platform_context: Self::PlatformCtx); - fn update(&mut self, platform_context: Self::PlatformCtx); + fn frame_update(&mut self, platform_context: Self::PlatformCtx); + fn fixed_update(&mut self, platform_context: Self::PlatformCtx); fn handle_event(&mut self, platform_context: Self::PlatformCtx); fn current_scene_mut(&mut self) -> &mut Scene; fn get_debug_ui_buffer(&self) -> Rc>; diff --git a/core/src/lib.rs b/core/src/lib.rs index f4b8d0c..4b7d531 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -1,4 +1,6 @@ pub mod engine; pub mod scene; pub mod debug_ui; +pub mod time; + pub use debug_ui::*; diff --git a/core/src/time.rs b/core/src/time.rs new file mode 100644 index 0000000..c47466d --- /dev/null +++ b/core/src/time.rs @@ -0,0 +1,144 @@ +use std::thread; +use std::time::{Duration, Instant}; + +#[derive(Clone, Debug)] +pub struct Config { + pub target_frame_hz: Option, + pub target_update_hz: f64, + pub max_updates_per_frame: u32, + pub max_accumulated_steps: u32, + pub sleep_tolerance: Duration, +} + +impl Default for Config { + fn default() -> Self { + Self { + target_frame_hz: Some(144.0), + target_update_hz: 60.0, + max_updates_per_frame: 5, + max_accumulated_steps: 8, + sleep_tolerance: Duration::from_micros(500), + } + } +} + +#[derive(Debug)] +pub struct Time { + cfg: Config, + last_instant: Instant, + next_frame_due: Instant, + frame_interval: Option, + fixed_dt: Duration, + + // tracking + frame_dt: Duration, + accumulator: Duration, + + // counters + pub frame_count: u64, + pub update_count: u64, +} + +pub struct TickPlan { + /// How many fixed updates to run this frame + pub updates: u32, + /// Interpolation factor for rendering between previous/next sim states + pub alpha: f32, + /// Measured last frame delta (seconds) + pub frame_dt: f32, + /// Fixed timestep (seconds) + pub fixed_dt: f32, +} + +impl Time { + pub fn new(cfg: Config) -> Self { + let now = Instant::now(); + let frame_interval = cfg.target_frame_hz.map(|hz| Duration::from_secs_f64(1.0 / hz)); + let fixed_dt = Duration::from_secs_f64(1.0 / cfg.target_update_hz); + Self { + cfg, + last_instant: now, + next_frame_due: now, + frame_interval, + fixed_dt, + frame_dt: Duration::ZERO, + accumulator: Duration::ZERO, + frame_count: 0, + update_count: 0, + } + } + + pub fn reconfigure(&mut self, cfg: Config) { + self.cfg = cfg.clone(); + self.frame_interval = cfg.target_frame_hz.map(|hz| Duration::from_secs_f64(1.0 / hz)); + self.fixed_dt = Duration::from_secs_f64(1.0 / cfg.target_update_hz); + } + + pub fn begin_frame_blocking(&mut self) -> TickPlan { + // 1) If there's a frame cap, block until next frame deadline + if let Some(interval) = self.frame_interval { + let mut now = Instant::now(); + if now < self.next_frame_due { + // Sleep most of the remainder, then spin the last tiny bit for precision + let total_remaining = self.next_frame_due - now; + if total_remaining > self.cfg.sleep_tolerance { + let sleep_for = total_remaining - self.cfg.sleep_tolerance; + thread::sleep(sleep_for); + } + // Short spin-wait for precision + while Instant::now() < self.next_frame_due { + std::hint::spin_loop(); + } + now = self.next_frame_due; + } + self.next_frame_due = self.next_frame_due + interval; + // In case we fell far behind (e.g., debugger pause), resync. + if self.next_frame_due < now { + self.next_frame_due = now + interval; + } + } + + // 2) Measure frame dt + let now = Instant::now(); + self.frame_dt = now.saturating_duration_since(self.last_instant); + self.last_instant = now; + self.frame_count += 1; + + // 3) Accumulate for fixed updates + self.accumulator += self.frame_dt; + + // Clamp accumulator to avoid doing a huge number of updates after a stall + let max_accumulated = self.fixed_dt * self.cfg.max_accumulated_steps; + if self.accumulator > max_accumulated { + self.accumulator = max_accumulated; + } + + // 4) Determine how many updates to run this frame + let mut updates = 0u32; + while self.accumulator >= self.fixed_dt && updates < self.cfg.max_updates_per_frame { + self.accumulator -= self.fixed_dt; + updates += 1; + self.update_count += 1; + } + + // 5) Compute interpolation factor for rendering (0..1) + let alpha = if self.fixed_dt.is_zero() { + 1.0 + } else { + (self.accumulator.as_secs_f32() / self.fixed_dt.as_secs_f32()).clamp(0.0, 1.0) + }; + + TickPlan { + updates, + alpha, + frame_dt: self.frame_dt.as_secs_f32(), + fixed_dt: self.fixed_dt.as_secs_f32(), + } + } + + pub fn frame_dt_seconds(&self) -> f32 { self.frame_dt.as_secs_f32() } + pub fn fixed_dt_seconds(&self) -> f32 { self.fixed_dt.as_secs_f32() } + pub fn alpha(&self) -> f32 { + if self.fixed_dt.is_zero() { 1.0 } else { (self.accumulator.as_secs_f32() / self.fixed_dt.as_secs_f32()).clamp(0.0, 1.0) } + } +} diff --git a/engine/src/engine.rs b/engine/src/engine.rs index 5d6af36..82b1f91 100644 --- a/engine/src/engine.rs +++ b/engine/src/engine.rs @@ -44,7 +44,7 @@ impl EngineTrait for Engine { } /// Update the engine - fn update(&mut self, platform_context: PlatformContext) { + fn frame_update(&mut self, platform_context: PlatformContext) { self.debug_ui_buffer.borrow_mut().reset_buffer(); let mut ctx = SystemContext { scene: self.scene_manager.current_mut(), @@ -53,7 +53,19 @@ impl EngineTrait for Engine { }; for system in self.system_manager.systems.values_mut() { - system.update(&mut ctx); + system.frame_update(&mut ctx); + } + } + + fn fixed_update(&mut self, platform_context: PlatformContext) { + let mut ctx = SystemContext { + scene: self.scene_manager.current_mut(), + platform_context, + debug_ui_buffer: self.debug_ui_buffer.clone(), + }; + + for system in self.system_manager.systems.values_mut() { + system.fixed_update(&mut ctx); } } diff --git a/engine/src/system.rs b/engine/src/system.rs index 31708b3..1ab49bf 100644 --- a/engine/src/system.rs +++ b/engine/src/system.rs @@ -19,7 +19,8 @@ pub trait System { /// Spawn the first entities of the world. fn load_world(&mut self, _ctx: &mut SystemContext) {} fn handle_event(&mut self, _ctx: &mut SystemContext) {} - fn update(&mut self, _ctx: &mut SystemContext) {} + fn fixed_update(&mut self, _ctx: &mut SystemContext) {} + fn frame_update(&mut self, _ctx: &mut SystemContext) {} } pub struct SystemManager { diff --git a/game/src/main.rs b/game/src/main.rs index 126c2e4..b1b5c2c 100644 --- a/game/src/main.rs +++ b/game/src/main.rs @@ -1,3 +1,4 @@ +use std::fmt::format; use glam::{Quat, Vec3}; use raidillon_engine::{Engine, system::System}; use raidillon_engine::system::SystemContext; @@ -34,8 +35,8 @@ impl System for UpdateAspectRatioSystem { #[derive(Default)] struct RenderingTestSystem; + impl System for RenderingTestSystem { - fn initialize(&mut self) {} fn load_world(&mut self, ctx: &mut SystemContext) { ctx.scene.world.spawn((Camera { eye: Vec3::new(0.0, 0.0, 2.0), @@ -61,9 +62,19 @@ impl System for RenderingTestSystem { )); } - fn update(&mut self, ctx: &mut SystemContext) { - ctx.debug_ui_buffer.borrow_mut().text("Hello World!".to_owned()); + fn frame_update(&mut self, ctx: &mut SystemContext) { + let mut dbg_ui = ctx.debug_ui_buffer.borrow_mut(); + dbg_ui.text("Hello World!".to_owned()); + dbg_ui.text(format!("Frame Delta: {}", ctx.platform_context.time_ctx.frame_dt)); + dbg_ui.text(format!("Fixed Delta: {}", ctx.platform_context.time_ctx.fixed_dt)); } + + fn fixed_update(&mut self, ctx: &mut SystemContext) { + ctx.scene.world.query_mut::<(&mut Transform, &ModelHandle)>().into_iter().for_each(|(_, (t, _))| { + t.rotation *= Quat::from_rotation_y(10.0 * ctx.platform_context.time_ctx.fixed_dt); + }); + } + } fn main() { diff --git a/glium_platform/src/platform.rs b/glium_platform/src/platform.rs index 97c1535..16df321 100644 --- a/glium_platform/src/platform.rs +++ b/glium_platform/src/platform.rs @@ -1,6 +1,6 @@ use std::cell::RefCell; use std::rc::Rc; -use raidillon_platform::{Platform, PlatformContext}; +use raidillon_platform::{Platform, PlatformContext, TimeContext}; use glium::backend::glutin::Display; use glium::backend::glutin::SimpleWindowBuilder; use glium::glutin::surface::WindowSurface; @@ -11,6 +11,8 @@ use crate::system::{RenderingContext, RenderingSystemManager}; use winit::event::{Event, WindowEvent}; use raidillon_assets::ModelManagerRef; use raidillon_core::engine::EngineTrait; +use raidillon_core::time; +use raidillon_core::time::Time; use crate::render::debug_ui::ImguiBridge; use crate::render::BasicMeshRenderingSystem; use crate::GliumAssetManager; @@ -22,6 +24,7 @@ pub struct GliumPlatform> { rendering_system_manager: RenderingSystemManager, asset_manager: ModelManagerRef, engine: E, + time: time::Time, } impl> Platform for GliumPlatform { @@ -38,6 +41,9 @@ impl> Platform for GliumPlatfor let asset_manager: ModelManagerRef = Rc::new(RefCell::new(Box::new(GliumAssetManager::new(Box::new(display.clone()))))); let mut rendering_system_manager = RenderingSystemManager::new(); + let time_cfg = time::Config::default(); + let time = time::Time::new(time_cfg); + // Install rendering systems rendering_system_manager.add::(&display, &window); rendering_system_manager.add::(&display, &window); @@ -49,6 +55,7 @@ impl> Platform for GliumPlatfor rendering_system_manager, asset_manager, engine, + time, } } @@ -59,6 +66,7 @@ impl> Platform for GliumPlatfor asset_manager: self.asset_manager.clone(), frame_width: w as f32, frame_height: h as f32, + time_ctx: self.construct_time_ctx(), }; self.engine.initialize(ctx.clone()); let _ = &self.event_loop.run(move |event, el| { @@ -98,9 +106,22 @@ impl> Platform for GliumPlatfor _ => {}, }, Event::AboutToWait => { + let plan = self.time.begin_frame_blocking(); + let mut ctx2 = ctx.clone(); - ctx2.current_event = event.clone(); - self.engine.update(ctx2); + ctx2.time_ctx = TimeContext { + frame_dt: self.time.frame_dt_seconds(), + fixed_dt: self.time.fixed_dt_seconds(), + alpha: self.time.alpha(), + }; + ctx2.current_event = Event::AboutToWait; + + for _ in 0..plan.updates { + self.engine.fixed_update(ctx2.clone()); + } + + self.engine.frame_update(ctx2.clone()); + self.rendering_system_manager .systems .values_mut() @@ -112,3 +133,13 @@ impl> Platform for GliumPlatfor }); } } + +impl> GliumPlatform { + fn construct_time_ctx(&self) -> TimeContext { + TimeContext { + frame_dt: self.time.frame_dt_seconds(), + fixed_dt: self.time.fixed_dt_seconds(), + alpha: self.time.alpha(), + } + } +} diff --git a/platform/src/context.rs b/platform/src/context.rs index 45e8fa4..bea1cb1 100644 --- a/platform/src/context.rs +++ b/platform/src/context.rs @@ -7,4 +7,12 @@ pub struct PlatformContext { pub asset_manager: ModelManagerRef, pub frame_width: f32, pub frame_height: f32, + pub time_ctx: TimeContext, +} + +#[derive(Clone)] +pub struct TimeContext { + pub frame_dt: f32, + pub fixed_dt: f32, + pub alpha: f32, } diff --git a/platform/src/lib.rs b/platform/src/lib.rs index 962c05f..8875d35 100644 --- a/platform/src/lib.rs +++ b/platform/src/lib.rs @@ -5,4 +5,4 @@ pub mod context; pub use platform::Platform; pub use camera::Camera; -pub use context::PlatformContext; +pub use context::{PlatformContext, TimeContext}; From f34a9b01a0b855b2147b17c57e142a7cb9fba4cb Mon Sep 17 00:00:00 2001 From: reo Date: Thu, 25 Sep 2025 13:01:02 +0300 Subject: [PATCH 52/89] Add imgui slider command to the debug ui buffer implementation --- core/src/debug_ui.rs | 10 ++++++++++ game/src/main.rs | 9 +++++++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/core/src/debug_ui.rs b/core/src/debug_ui.rs index 18d846f..df3b9f1 100644 --- a/core/src/debug_ui.rs +++ b/core/src/debug_ui.rs @@ -1,6 +1,7 @@ pub enum UICommand { Text(String), Separator, + SliderF32 { label: String, min: f32, max: f32, value: std::rc::Rc> }, } pub struct DebugUIBuffer { @@ -21,6 +22,11 @@ impl DebugUIBuffer { self.cmds.push(UICommand::Separator); } + pub fn slider_f32>(&mut self, label: T, min: f32, max: f32, value: std::rc::Rc>) { + self.cmds.push(UICommand::SliderF32 { label: label.into(), min, max, value }); + } + // End of commands + pub fn write_buffer(&self, ui: &imgui::Ui) { for cmd in &self.cmds { match cmd { @@ -30,6 +36,10 @@ impl DebugUIBuffer { UICommand::Separator => { ui.separator(); } + UICommand::SliderF32 { label, min, max, value } => { + let mut v = value.borrow_mut(); + ui.slider_config(label.as_str(), *min, *max).build(&mut *v); + } } } } diff --git a/game/src/main.rs b/game/src/main.rs index b1b5c2c..05ae11e 100644 --- a/game/src/main.rs +++ b/game/src/main.rs @@ -34,10 +34,14 @@ impl System for UpdateAspectRatioSystem { } #[derive(Default)] -struct RenderingTestSystem; +struct RenderingTestSystem { + rotation_speed: std::rc::Rc>, +} impl System for RenderingTestSystem { fn load_world(&mut self, ctx: &mut SystemContext) { + self.rotation_speed = std::rc::Rc::new(std::cell::RefCell::new(5.0)); + ctx.scene.world.spawn((Camera { eye: Vec3::new(0.0, 0.0, 2.0), center: Vec3::ZERO, @@ -67,11 +71,12 @@ impl System for RenderingTestSystem { dbg_ui.text("Hello World!".to_owned()); dbg_ui.text(format!("Frame Delta: {}", ctx.platform_context.time_ctx.frame_dt)); dbg_ui.text(format!("Fixed Delta: {}", ctx.platform_context.time_ctx.fixed_dt)); + dbg_ui.slider_f32("Rotation Speed", -10.0, 10.0, self.rotation_speed.clone()); } fn fixed_update(&mut self, ctx: &mut SystemContext) { ctx.scene.world.query_mut::<(&mut Transform, &ModelHandle)>().into_iter().for_each(|(_, (t, _))| { - t.rotation *= Quat::from_rotation_y(10.0 * ctx.platform_context.time_ctx.fixed_dt); + t.rotation *= Quat::from_rotation_y(*self.rotation_speed.borrow() * ctx.platform_context.time_ctx.fixed_dt); }); } From 44489f9fe356d1357d96652b50ab1a8db848dc90 Mon Sep 17 00:00:00 2001 From: reo Date: Fri, 26 Sep 2025 16:52:14 +0300 Subject: [PATCH 53/89] Move models to git LFS --- .gitattributes | 1 + assets/models/monkey.bin | Bin 68720 -> 130 bytes assets/models/monkey.gltf | 107 +----------------------- assets/models/pink-monkey.bin | Bin 68720 -> 130 bytes assets/models/pink-monkey.gltf | 124 +--------------------------- assets/models/tree.bin | Bin 13584 -> 130 bytes assets/models/tree.gltf | 143 +-------------------------------- assets/models/tree_texture.png | Bin 845 -> 128 bytes 8 files changed, 10 insertions(+), 365 deletions(-) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..7dc2605 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +assets/models/* filter=lfs diff=lfs merge=lfs -text diff --git a/assets/models/monkey.bin b/assets/models/monkey.bin index e7992f36d75135cc5966e2abe94e5937420da413..56f4aa06d5161846423e6a1fd1ce39019a203efd 100644 GIT binary patch literal 130 zcmWN?K@!3s3;@78uiyigKp`dl4TMyfQRxWw;OliSd&zsW{?c{MbL__4+q^xFvHY)} zyl{V-aSEHus@{qoHMxMhBex1BPsGuS7ZT3QjIfpv8A9?A1-4j%1+j=inH?1jAOij% MHQHA+#?68H0qdA2e*gdg literal 68720 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 diff --git a/assets/models/monkey.gltf b/assets/models/monkey.gltf index d3e2438..2651b01 100644 --- a/assets/models/monkey.gltf +++ b/assets/models/monkey.gltf @@ -1,104 +1,3 @@ -{ - "asset":{ - "generator":"Khronos glTF Blender I/O v4.4.56", - "version":"2.0" - }, - "scene":0, - "scenes":[ - { - "name":"Scene", - "nodes":[ - 0 - ] - } - ], - "nodes":[ - { - "mesh":0, - "name":"Suzanne" - } - ], - "meshes":[ - { - "name":"Suzanne", - "primitives":[ - { - "attributes":{ - "POSITION":0, - "NORMAL":1, - "TEXCOORD_0":2 - }, - "indices":3 - } - ] - } - ], - "accessors":[ - { - "bufferView":0, - "componentType":5126, - "count":1966, - "max":[ - 1.3671875, - 0.984375, - 0.8515625 - ], - "min":[ - -1.3671875, - -0.984375, - -0.8515625 - ], - "type":"VEC3" - }, - { - "bufferView":1, - "componentType":5126, - "count":1966, - "type":"VEC3" - }, - { - "bufferView":2, - "componentType":5126, - "count":1966, - "type":"VEC2" - }, - { - "bufferView":3, - "componentType":5123, - "count":2904, - "type":"SCALAR" - } - ], - "bufferViews":[ - { - "buffer":0, - "byteLength":23592, - "byteOffset":0, - "target":34962 - }, - { - "buffer":0, - "byteLength":23592, - "byteOffset":23592, - "target":34962 - }, - { - "buffer":0, - "byteLength":15728, - "byteOffset":47184, - "target":34962 - }, - { - "buffer":0, - "byteLength":5808, - "byteOffset":62912, - "target":34963 - } - ], - "buffers":[ - { - "byteLength":68720, - "uri":"monkey.bin" - } - ] -} +version https://git-lfs.github.com/spec/v1 +oid sha256:6513b26c81eb59be818a8ddc0331eccd2e54d8c2e9b0d7edb01b491a16cdc421 +size 1333 diff --git a/assets/models/pink-monkey.bin b/assets/models/pink-monkey.bin index 2db45966ba391e44f67a7dcc92cd338340566448..627ca3e113752425edd688115646fdf9ceb9a10e 100644 GIT binary patch literal 130 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 avGu<>G5hAoEVHk!#K);QG(HZ^t^5H`4fe$V diff --git a/assets/models/pink-monkey.gltf b/assets/models/pink-monkey.gltf index a27e895..d4c6adf 100644 --- a/assets/models/pink-monkey.gltf +++ b/assets/models/pink-monkey.gltf @@ -1,121 +1,3 @@ -{ - "asset":{ - "generator":"Khronos glTF Blender I/O v4.0.44", - "version":"2.0" - }, - "scene":0, - "scenes":[ - { - "name":"Scene", - "nodes":[ - 0 - ] - } - ], - "nodes":[ - { - "mesh":0, - "name":"Suzanne" - } - ], - "materials":[ - { - "doubleSided":true, - "name":"Material.001", - "pbrMetallicRoughness":{ - "baseColorFactor":[ - 0.8002749681472778, - 0, - 0.07706787437200546, - 1 - ], - "metallicFactor":0, - "roughnessFactor":0.5 - } - } - ], - "meshes":[ - { - "name":"Suzanne", - "primitives":[ - { - "attributes":{ - "POSITION":0, - "NORMAL":1, - "TEXCOORD_0":2 - }, - "indices":3, - "material":0 - } - ] - } - ], - "accessors":[ - { - "bufferView":0, - "componentType":5126, - "count":1966, - "max":[ - 1.3671875, - 0.984375, - 0.8515625 - ], - "min":[ - -1.3671875, - -0.984375, - -0.8515625 - ], - "type":"VEC3" - }, - { - "bufferView":1, - "componentType":5126, - "count":1966, - "type":"VEC3" - }, - { - "bufferView":2, - "componentType":5126, - "count":1966, - "type":"VEC2" - }, - { - "bufferView":3, - "componentType":5123, - "count":2904, - "type":"SCALAR" - } - ], - "bufferViews":[ - { - "buffer":0, - "byteLength":23592, - "byteOffset":0, - "target":34962 - }, - { - "buffer":0, - "byteLength":23592, - "byteOffset":23592, - "target":34962 - }, - { - "buffer":0, - "byteLength":15728, - "byteOffset":47184, - "target":34962 - }, - { - "buffer":0, - "byteLength":5808, - "byteOffset":62912, - "target":34963 - } - ], - "buffers":[ - { - "byteLength":68720, - "uri":"pink-monkey.bin" - } - ] -} +version https://git-lfs.github.com/spec/v1 +oid sha256:a955cb6bcdcaed40dee676c707ba562f93ca960806107c6e9f328764be49a303 +size 1613 diff --git a/assets/models/tree.bin b/assets/models/tree.bin index e7826210d4c2a288d9825d6987ca7d963ef294b5..225ddd1884035a2c5d098123da7d4e5ca48c572d 100644 GIT binary patch literal 130 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 A3jhEB diff --git a/assets/models/tree.gltf b/assets/models/tree.gltf index 51bf9ed..58b4fb9 100644 --- a/assets/models/tree.gltf +++ b/assets/models/tree.gltf @@ -1,140 +1,3 @@ -{ - "asset":{ - "generator":"Khronos glTF Blender I/O v4.4.56", - "version":"2.0" - }, - "scene":0, - "scenes":[ - { - "name":"Scene", - "nodes":[ - 0 - ] - } - ], - "nodes":[ - { - "mesh":0, - "name":"tree01", - "scale":[ - 0.009999999776482582, - 0.009999999776482582, - 0.009999999776482582 - ] - } - ], - "materials":[ - { - "name":"Mat", - "pbrMetallicRoughness":{ - "baseColorTexture":{ - "index":0 - }, - "metallicFactor":0 - } - } - ], - "meshes":[ - { - "name":"tree01_1", - "primitives":[ - { - "attributes":{ - "POSITION":0, - "NORMAL":1, - "TEXCOORD_0":2 - }, - "indices":3, - "material":0 - } - ] - } - ], - "textures":[ - { - "sampler":0, - "source":0 - } - ], - "images":[ - { - "mimeType":"image/png", - "name":"tree_texture", - "uri":"tree_texture.png" - } - ], - "accessors":[ - { - "bufferView":0, - "componentType":5126, - "count":395, - "max":[ - 123.4296646118164, - 509.0864562988281, - 168.36563110351562 - ], - "min":[ - -184.9799346923828, - 0, - -155.37196350097656 - ], - "type":"VEC3" - }, - { - "bufferView":1, - "componentType":5126, - "count":395, - "type":"VEC3" - }, - { - "bufferView":2, - "componentType":5126, - "count":395, - "type":"VEC2" - }, - { - "bufferView":3, - "componentType":5123, - "count":471, - "type":"SCALAR" - } - ], - "bufferViews":[ - { - "buffer":0, - "byteLength":4740, - "byteOffset":0, - "target":34962 - }, - { - "buffer":0, - "byteLength":4740, - "byteOffset":4740, - "target":34962 - }, - { - "buffer":0, - "byteLength":3160, - "byteOffset":9480, - "target":34962 - }, - { - "buffer":0, - "byteLength":942, - "byteOffset":12640, - "target":34963 - } - ], - "samplers":[ - { - "magFilter":9729, - "minFilter":9987 - } - ], - "buffers":[ - { - "byteLength":13584, - "uri":"tree.bin" - } - ] -} +version https://git-lfs.github.com/spec/v1 +oid sha256:7f5b405308b025a6fdc8e5dad59d374350415338102219f5a31562064d3624c8 +size 1846 diff --git a/assets/models/tree_texture.png b/assets/models/tree_texture.png index f5726d41ea881c58cf74e16442f6e7856ad98742..1d2807bd98744fa735b0b5ac83e02b7ac3c1be8f 100644 GIT binary patch literal 128 zcmWN_$qmCG5J1s8RnS0;*}>hg%mkz)SQ+d?st>2H_iy-8A0OW4Jn0bP+2`Yhw5_%) zZ)Lm%olwLr+31y1OUk-K7Y)_tJ%F@YO3cyu;0kJtMY&LePD@6*jHW~h3NfSi#zER) L9Y*~JJQ&OVsp==K literal 845 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K58911L)MWvCLk0$B5l7=R`)GBhwSI502( z#RSL@CQB1Gn;9NBk>>&o!x#> Date: Fri, 26 Sep 2025 22:44:43 +0300 Subject: [PATCH 54/89] Implement HDRI skybox support --- .gitattributes | 1 + Cargo.lock | 114 +++++++++++++- assets/exr/citrus_orchard_road_puresky_4k.exr | 3 + assets/exr/qwantani_sunset_puresky_2k.exr | 3 + assets/shaders/skybox.frag | 1 + game/src/main.rs | 4 +- glium_platform/Cargo.toml | 2 + glium_platform/src/platform.rs | 8 +- glium_platform/src/render/basic.rs | 10 +- glium_platform/src/render/mod.rs | 2 + glium_platform/src/render/skybox.rs | 149 ++++++++++++++++++ glium_platform/src/system.rs | 2 + 12 files changed, 282 insertions(+), 17 deletions(-) create mode 100644 assets/exr/citrus_orchard_road_puresky_4k.exr create mode 100644 assets/exr/qwantani_sunset_puresky_2k.exr create mode 100644 glium_platform/src/render/skybox.rs diff --git a/.gitattributes b/.gitattributes index 7dc2605..7182511 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1 +1,2 @@ assets/models/* filter=lfs diff=lfs merge=lfs -text +assets/exr/* filter=lfs diff=lfs merge=lfs -text diff --git a/Cargo.lock b/Cargo.lock index 3665a1b..25cb3cb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -130,6 +130,12 @@ version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" +[[package]] +name = "bit_field" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e4b40c7323adcfc0a41c4b88143ed58346ff65a288fc144329c5c45e05d70c6" + [[package]] name = "bitflags" version = "1.3.2" @@ -319,12 +325,37 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "crossbeam-deque" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "crossbeam-utils" version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" +[[package]] +name = "crunchy" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" + [[package]] name = "cursor-icon" version = "1.2.0" @@ -384,6 +415,21 @@ dependencies = [ "windows-sys 0.60.2", ] +[[package]] +name = "exr" +version = "1.73.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83197f59927b46c04a183a619b7c29df34e63e63c7869320862268c0ef687e0" +dependencies = [ + "bit_field", + "half", + "lebe", + "miniz_oxide", + "rayon-core", + "smallvec", + "zune-inflate", +] + [[package]] name = "fdeflate" version = "0.3.7" @@ -603,6 +649,16 @@ dependencies = [ "gl_generator", ] +[[package]] +name = "half" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "459196ed295495a68f7d7fe1d84f6c4b7ff0e21fe3017b2f283c6fac3ad803c9" +dependencies = [ + "cfg-if", + "crunchy", +] + [[package]] name = "hashbrown" version = "0.14.5" @@ -636,12 +692,14 @@ checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" [[package]] name = "image" -version = "0.25.6" +version = "0.25.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db35664ce6b9810857a38a906215e75a9c879f0696556a39f59c62829710251a" +checksum = "529feb3e6769d234375c4cf1ee2ce713682b8e76538cb13f9fc23e1400a591e7" dependencies = [ "bytemuck", "byteorder-lite", + "exr", + "moxcms", "num-traits", "png", "zune-core", @@ -769,6 +827,12 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +[[package]] +name = "lebe" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a79a3332a6609480d7d0c9eab957bca6b455b91bb84e66d19f5ff66294b85b8" + [[package]] name = "libc" version = "0.2.174" @@ -864,6 +928,16 @@ version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e53debba6bda7a793e5f99b8dacf19e626084f525f7829104ba9898f367d85ff" +[[package]] +name = "moxcms" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd32fa8935aeadb8a8a6b6b351e40225570a37c43de67690383d87ef170cd08" +dependencies = [ + "num-traits", + "pxfm", +] + [[package]] name = "ndk" version = "0.9.0" @@ -1267,11 +1341,11 @@ checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" [[package]] name = "png" -version = "0.17.16" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82151a2fc869e011c153adc57cf2789ccb8d9906ce52c0b39a6b5697749d7526" +checksum = "97baced388464909d42d89643fe4361939af9b7ce7a31ee32a168f832a70f2a0" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.9.1", "crc32fast", "fdeflate", "flate2", @@ -1310,6 +1384,15 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "pxfm" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83f9b339b02259ada5c0f4a389b7fb472f933aa17ce176fd2ad98f28bb401fde" +dependencies = [ + "num-traits", +] + [[package]] name = "quick-xml" version = "0.37.5" @@ -1388,9 +1471,11 @@ name = "raidillon_glium" version = "0.1.0" dependencies = [ "anyhow", + "exr", "glam", "glium", "gltf", + "image", "imgui", "imgui-glium-renderer", "imgui-winit-support", @@ -1419,6 +1504,16 @@ version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539" +[[package]] +name = "rayon-core" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + [[package]] name = "redox_syscall" version = "0.4.1" @@ -2408,6 +2503,15 @@ version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f423a2c17029964870cfaabb1f13dfab7d092a62a29a89264f4d36990ca414a" +[[package]] +name = "zune-inflate" +version = "0.2.54" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73ab332fe2f6680068f3582b16a24f90ad7096d5d39b974d1c0aff0125116f02" +dependencies = [ + "simd-adler32", +] + [[package]] name = "zune-jpeg" version = "0.4.20" diff --git a/assets/exr/citrus_orchard_road_puresky_4k.exr b/assets/exr/citrus_orchard_road_puresky_4k.exr new file mode 100644 index 0000000..c57cb53 --- /dev/null +++ b/assets/exr/citrus_orchard_road_puresky_4k.exr @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8aa6cc5bb4a5a8f5fa12870cefdd6a6b600072454add837dca45e340c1549d30 +size 70720809 diff --git a/assets/exr/qwantani_sunset_puresky_2k.exr b/assets/exr/qwantani_sunset_puresky_2k.exr new file mode 100644 index 0000000..86cd3d7 --- /dev/null +++ b/assets/exr/qwantani_sunset_puresky_2k.exr @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f738ddd35a5e1a291eb45b30eea73b4d296dc4a05a412ae2f187ef5e95dc076a +size 18335204 diff --git a/assets/shaders/skybox.frag b/assets/shaders/skybox.frag index 8418e54..864be50 100644 --- a/assets/shaders/skybox.frag +++ b/assets/shaders/skybox.frag @@ -17,6 +17,7 @@ vec2 sample_spherical_map(vec3 v) { void main() { vec2 uv = sample_spherical_map(normalize(direction)); + uv.y = 1.0 - uv.y; vec3 color = texture(equirect, uv).rgb; frag_color = vec4(color, 1.0); } diff --git a/game/src/main.rs b/game/src/main.rs index 05ae11e..bea5fe0 100644 --- a/game/src/main.rs +++ b/game/src/main.rs @@ -101,8 +101,8 @@ fn main() { let platform = GliumPlatform::initialize( engine, "Raidillon".to_string(), - 1920, - 1080, + 2560, + 1440, ); platform.run() }; diff --git a/glium_platform/Cargo.toml b/glium_platform/Cargo.toml index 0c0ecc2..6e51be6 100644 --- a/glium_platform/Cargo.toml +++ b/glium_platform/Cargo.toml @@ -18,3 +18,5 @@ indexmap = "2.10.0" imgui = "0.12.0" imgui-winit-support = "0.13.0" imgui-glium-renderer = "0.13.0" +exr = "1.73.0" +image = { version = "0.25.8", default-features = false, features = ["exr"] } diff --git a/glium_platform/src/platform.rs b/glium_platform/src/platform.rs index 16df321..f03cd96 100644 --- a/glium_platform/src/platform.rs +++ b/glium_platform/src/platform.rs @@ -14,8 +14,9 @@ use raidillon_core::engine::EngineTrait; use raidillon_core::time; use raidillon_core::time::Time; use crate::render::debug_ui::ImguiBridge; -use crate::render::BasicMeshRenderingSystem; +use crate::render::{BasicMeshRenderingSystem, SkyboxRenderingSystem}; use crate::GliumAssetManager; +use glam::Vec3; pub struct GliumPlatform> { event_loop: EventLoop<()>, @@ -44,7 +45,8 @@ impl> Platform for GliumPlatfor let time_cfg = time::Config::default(); let time = time::Time::new(time_cfg); - // Install rendering systems + // Install rendering systems in order + rendering_system_manager.add::(&display, &window); rendering_system_manager.add::(&display, &window); rendering_system_manager.add::(&display, &window); @@ -95,12 +97,14 @@ impl> Platform for GliumPlatfor asset_manager: self.asset_manager.clone(), window: &mut self.window, debug_ui_buffer, + env_light_dir: Vec3::new(0.0, -1.0, 0.0), }; self.rendering_system_manager .systems .values_mut() .for_each(|system| system.render(&mut context)); + target.finish().unwrap(); } _ => {}, diff --git a/glium_platform/src/render/basic.rs b/glium_platform/src/render/basic.rs index 0f1db93..8551ecd 100644 --- a/glium_platform/src/render/basic.rs +++ b/glium_platform/src/render/basic.rs @@ -55,14 +55,8 @@ impl RenderingSystem for BasicMeshRenderingSystem { } }; - // Direction from the light source (0,+Y) towards the scene. - let light_dir: Vec3 = Vec3::new(0.0, -1.0, 0.0).normalize(); - - // let asset_manager = ctx.asset_manager.borrow(); - // let any_ref: &dyn Any = &**asset_manager; - // if let Some(glium_manager) = any_ref.downcast_ref::() { - // &glium_manager.models; - // } + // Use HDR-derived environment light direction if provided, otherwise default to downward + let light_dir: Vec3 = if ctx.env_light_dir.length_squared() > 0.0 { ctx.env_light_dir.normalize() } else { Vec3::new(0.0, -1.0, 0.0) }; let asset_manager = ctx.asset_manager.borrow(); diff --git a/glium_platform/src/render/mod.rs b/glium_platform/src/render/mod.rs index c31a0d9..f49e308 100644 --- a/glium_platform/src/render/mod.rs +++ b/glium_platform/src/render/mod.rs @@ -1,4 +1,6 @@ mod basic; pub mod debug_ui; +mod skybox; pub use basic::BasicMeshRenderingSystem; +pub use skybox::SkyboxRenderingSystem; diff --git a/glium_platform/src/render/skybox.rs b/glium_platform/src/render/skybox.rs new file mode 100644 index 0000000..49ea594 --- /dev/null +++ b/glium_platform/src/render/skybox.rs @@ -0,0 +1,149 @@ +use std::path::PathBuf; +use std::rc::Rc; +use std::cell::RefCell; +use glium::{Display, Program, Surface, VertexBuffer, IndexBuffer, implement_vertex}; +use glium::glutin::surface::WindowSurface; +use glium::index::PrimitiveType; +use glium::texture::{RawImage2d, SrgbTexture2d, Texture2d}; +use glium::uniform; +use glam::{Mat4, Vec2, Vec3}; +use raidillon_assets::include_shader; +use crate::system::RenderingContext; +use crate::RenderingSystem; + +#[derive(Copy, Clone)] +struct SkyboxVertex { position: [f32; 3] } +implement_vertex!(SkyboxVertex, position); + +pub struct SkyboxRenderingSystem { + program: Program, + quad_vb: VertexBuffer, + quad_ib: IndexBuffer, + /// Equirectangular HDR image, tonemapped to sRGB for skybox view + equirect_srgb: SrgbTexture2d, + /// Dominant light direction estimated from HDRI + light_dir: Vec3, +} + +impl SkyboxRenderingSystem { + fn build_cube(display: &Display) -> (VertexBuffer, IndexBuffer) { + // Unit cube centered at origin + let p = &[ + [-1.0, -1.0, -1.0], [ 1.0, -1.0, -1.0], [ 1.0, 1.0, -1.0], [-1.0, 1.0, -1.0], // back + [-1.0, -1.0, 1.0], [ 1.0, -1.0, 1.0], [ 1.0, 1.0, 1.0], [-1.0, 1.0, 1.0], // front + ]; + let verts = vec![ + SkyboxVertex { position: p[0] }, SkyboxVertex { position: p[1] }, SkyboxVertex { position: p[2] }, SkyboxVertex { position: p[3] }, // back + SkyboxVertex { position: p[4] }, SkyboxVertex { position: p[5] }, SkyboxVertex { position: p[6] }, SkyboxVertex { position: p[7] }, // front + ]; + let idx: [u16; 36] = [ + // back face + 0,1,2, 2,3,0, + // front face + 4,6,5, 6,4,7, + // left face + 0,3,7, 7,4,0, + // right face + 1,5,6, 6,2,1, + // bottom face + 0,4,5, 5,1,0, + // top face + 3,2,6, 6,7,3, + ]; + ( + VertexBuffer::new(display, &verts).unwrap(), + IndexBuffer::new(display, PrimitiveType::TrianglesList, &idx).unwrap(), + ) + } + + fn load_hdr_equirect_and_analyze(display: &Display, path: &std::path::Path) -> (SrgbTexture2d, Vec3) { + // Use image crate to decode EXR as f32 RGB + let dyn_img = image::ImageReader::open(path).expect("open exr").with_guessed_format().expect("guess format").decode().expect("decode exr"); + let hdr = dyn_img.to_rgb32f(); + let (width, height) = hdr.dimensions(); + let width = width as usize; let height = height as usize; + let mut dir_accum = Vec3::ZERO; + let mut weight_sum = 0.0f32; + for y in 0..height { + let v = (y as f32 + 0.5) / height as f32; + let theta = (v - 0.5) * std::f32::consts::PI; + let lat_weight = theta.cos().max(0.0); + for x in 0..width { + let u = (x as f32 + 0.5) / width as f32; + let phi = (u - 0.5) * 2.0 * std::f32::consts::PI; + let px = hdr.get_pixel(x as u32, y as u32).0; + let rgb = Vec3::new(px[0], px[1], px[2]); + let lum = 0.2126*rgb.x + 0.7152*rgb.y + 0.0722*rgb.z; + if lum > 0.0 { + let dir = Vec3::new(phi.cos()*theta.cos(), theta.sin(), phi.sin()*theta.cos()); + let w = lum * lat_weight; + dir_accum += dir * w; + weight_sum += w; + } + } + } + let mut light_dir = if weight_sum > 0.0 { dir_accum / weight_sum } else { Vec3::new(0.0, -1.0, 0.0) }; + if light_dir.length_squared() < 1e-6 { light_dir = Vec3::new(0.0,-1.0,0.0); } + light_dir = light_dir.normalize(); + + // Tonemap to sRGB + let mut srgb_bytes = Vec::with_capacity(width*height*4); + for y in 0..height { + for x in 0..width { + let px = hdr.get_pixel(x as u32, y as u32).0; + let mapped = Vec3::new(px[0], px[1], px[2]) / (Vec3::new(px[0], px[1], px[2]) + Vec3::ONE); + let srgb = mapped.powf(1.0/2.2); + srgb_bytes.extend_from_slice(&[ + (srgb.x.clamp(0.0,1.0)*255.0) as u8, + (srgb.y.clamp(0.0,1.0)*255.0) as u8, + (srgb.z.clamp(0.0,1.0)*255.0) as u8, + 255u8, + ]); + } + } + let raw = RawImage2d::from_raw_rgba(srgb_bytes, (width as u32, height as u32)); + let tex = SrgbTexture2d::new(display, raw).unwrap(); + (tex, light_dir) + } +} + +impl RenderingSystem for SkyboxRenderingSystem { + fn initialize(display: &Display, _window: &glium::winit::window::Window) -> Self { + const VERT_SRC: &str = include_shader!("skybox.vert"); + const FRAG_SRC: &str = include_shader!("skybox.frag"); + let program = Program::from_source(display, VERT_SRC, FRAG_SRC, None).unwrap(); + let (quad_vb, quad_ib) = Self::build_cube(display); + + // Load EXR from assets/exr + let manifest_dir = env!("CARGO_MANIFEST_DIR"); + let path = std::path::Path::new(manifest_dir).join("../assets/exr/qwantani_sunset_puresky_2k.exr"); + let (equirect_srgb, light_dir) = Self::load_hdr_equirect_and_analyze(display, &path); + Self { program, quad_vb, quad_ib, equirect_srgb, light_dir } + } + + fn render(&mut self, ctx: &mut RenderingContext) { + // Provide view and projection without translation for skybox + let cam = match ctx.scene.world.query::<&raidillon_platform::Camera>().iter().next() { + Some((_, cam)) => *cam, + None => return, + }; + let mut view = cam.view(); + // remove translation from view matrix (only orientation) + view.col_mut(3).x = 0.0; view.col_mut(3).y = 0.0; view.col_mut(3).z = 0.0; + let uniforms = uniform! { + view: view.to_cols_array_2d(), + projection: cam.projection().to_cols_array_2d(), + equirect: &self.equirect_srgb, + }; + let params = glium::DrawParameters { depth: glium::Depth { test: glium::draw_parameters::DepthTest::IfLessOrEqual, write: false, ..Default::default() }, ..Default::default() }; + ctx.target.draw(&self.quad_vb, &self.quad_ib, &self.program, &uniforms, ¶ms).ok(); + + // Share light direction with following passes + ctx.env_light_dir = self.light_dir; + } +} + +// Provide a getter for light direction for other systems +impl SkyboxRenderingSystem { + pub fn light_direction(&self) -> Vec3 { self.light_dir } +} diff --git a/glium_platform/src/system.rs b/glium_platform/src/system.rs index 7f1f55e..891fec0 100644 --- a/glium_platform/src/system.rs +++ b/glium_platform/src/system.rs @@ -7,6 +7,7 @@ use glium::glutin::surface::WindowSurface; use raidillon_assets::ModelManagerRef; use raidillon_core::DebugUIBuffer; use raidillon_core::scene::Scene; +use glam::Vec3; pub struct RenderingContext<'a> { pub scene: &'a Scene, @@ -14,6 +15,7 @@ pub struct RenderingContext<'a> { pub window: &'a mut glium::winit::window::Window, pub asset_manager: ModelManagerRef, pub debug_ui_buffer: Rc>, + pub env_light_dir: Vec3, } /// The internal "rendering system" trait of glium_platform. From 46c8c3281907ed42d45b6a2c0eef41732b533635 Mon Sep 17 00:00:00 2001 From: reo Date: Sun, 28 Sep 2025 01:31:14 +0300 Subject: [PATCH 55/89] Huge input update, FPS Camera controls system Long day. I now store winit::window::Window in a mutex. --- Cargo.lock | 5 +- engine/Cargo.toml | 1 + engine/src/engine.rs | 9 ++ engine/src/input.rs | 69 ++++++++++++++++ engine/src/lib.rs | 2 + engine/src/system.rs | 3 +- engine/src/systems/fps_camera.rs | 114 ++++++++++++++++++++++++++ engine/src/systems/mod.rs | 1 + game/src/main.rs | 74 ++++++++++++++--- glium_platform/src/platform.rs | 28 ++++--- glium_platform/src/render/basic.rs | 3 +- glium_platform/src/render/debug_ui.rs | 21 +++-- glium_platform/src/render/skybox.rs | 3 +- glium_platform/src/system.rs | 11 +-- platform/src/context.rs | 2 + 15 files changed, 307 insertions(+), 39 deletions(-) create mode 100644 engine/src/input.rs create mode 100644 engine/src/systems/fps_camera.rs create mode 100644 engine/src/systems/mod.rs diff --git a/Cargo.lock b/Cargo.lock index 25cb3cb..e1b6adb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -523,9 +523,9 @@ dependencies = [ [[package]] name = "glam" -version = "0.30.5" +version = "0.30.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2d1aab06663bdce00d6ca5e5ed586ec8d18033a771906c993a1e3755b368d85" +checksum = "e12d847aeb25f41be4c0ec9587d624e9cd631bc007a8fd7ce3f5851e064c6460" [[package]] name = "glium" @@ -1444,6 +1444,7 @@ dependencies = [ name = "raidillon_engine" version = "0.1.0" dependencies = [ + "glam", "hecs", "indexmap", "raidillon_assets", diff --git a/engine/Cargo.toml b/engine/Cargo.toml index 726ac44..98202e4 100644 --- a/engine/Cargo.toml +++ b/engine/Cargo.toml @@ -10,3 +10,4 @@ raidillon_platform = { path = "../platform" } winit = "0.30.12" hecs = "0.10.5" indexmap = "2.10.0" +glam = "0.30.8" \ No newline at end of file diff --git a/engine/src/engine.rs b/engine/src/engine.rs index 82b1f91..68f17e0 100644 --- a/engine/src/engine.rs +++ b/engine/src/engine.rs @@ -5,11 +5,13 @@ use crate::system::{SystemContext, SystemManager}; use raidillon_platform::PlatformContext; use raidillon_core::DebugUIBuffer; use raidillon_core::engine::EngineTrait; +use crate::input::InputState; pub struct Engine { pub scene_manager: SceneManager, pub system_manager: SystemManager, debug_ui_buffer: Rc>, + input_state: Rc>, } impl EngineTrait for Engine { @@ -21,6 +23,7 @@ impl EngineTrait for Engine { scene_manager, system_manager, debug_ui_buffer: Rc::new(RefCell::new(DebugUIBuffer::new())), + input_state: Default::default(), } } @@ -35,6 +38,7 @@ impl EngineTrait for Engine { scene: self.scene_manager.current_mut(), platform_context, debug_ui_buffer: self.debug_ui_buffer.clone(), + input_state: self.input_state.clone(), }; // Engine Loading Stage 2: load world @@ -50,6 +54,7 @@ impl EngineTrait for Engine { scene: self.scene_manager.current_mut(), platform_context, debug_ui_buffer: self.debug_ui_buffer.clone(), + input_state: self.input_state.clone(), }; for system in self.system_manager.systems.values_mut() { @@ -62,6 +67,7 @@ impl EngineTrait for Engine { scene: self.scene_manager.current_mut(), platform_context, debug_ui_buffer: self.debug_ui_buffer.clone(), + input_state: self.input_state.clone(), }; for system in self.system_manager.systems.values_mut() { @@ -70,10 +76,13 @@ impl EngineTrait for Engine { } fn handle_event(&mut self, platform_context: PlatformContext) { + self.input_state.borrow_mut().handle_event(&platform_context.current_event); + let mut ctx = SystemContext { scene: self.scene_manager.current_mut(), platform_context, debug_ui_buffer: self.debug_ui_buffer.clone(), + input_state: self.input_state.clone(), }; for system in self.system_manager.systems.values_mut() { diff --git a/engine/src/input.rs b/engine/src/input.rs new file mode 100644 index 0000000..27eb6fc --- /dev/null +++ b/engine/src/input.rs @@ -0,0 +1,69 @@ +use std::collections::HashSet; +use winit::event::{ElementState, Event, MouseButton, WindowEvent}; +use winit::keyboard::{KeyCode, PhysicalKey}; + +/// A utility to help with buffering input. +/// Meant to be plugged into systems. +#[derive(Default, Clone, Debug)] +pub struct InputState { + held_keys: HashSet, + held_mouse: HashSet, +} + +impl InputState { + fn new() -> Self { + Default::default() + } + + pub fn handle_event(&mut self, event: &Event<()>) { + if let Event::WindowEvent { event, .. } = event { + match event { + // Keyboard + WindowEvent::KeyboardInput { event: key_event, .. } => { + if let PhysicalKey::Code(code) = key_event.physical_key { + match key_event.state { + ElementState::Pressed => { + self.held_keys.insert(code); + } + ElementState::Released => { + self.held_keys.remove(&code); + } + } + } + } + + // Mouse + WindowEvent::MouseInput { state, button, .. } => { + match state { + ElementState::Pressed => { + self.held_mouse.insert(*button); + } + ElementState::Released => { + self.held_mouse.remove(button); + } + } + } + + WindowEvent::Focused(focused) => { + if !*focused { + self.clear(); + } + } + _ => {} + } + } + } + + pub fn key_held(&self, code: KeyCode) -> bool { + self.held_keys.contains(&code) + } + + pub fn mouse_held(&self, button: MouseButton) -> bool { + self.held_mouse.contains(&button) + } + + pub fn clear(&mut self) { + self.held_keys.clear(); + self.held_mouse.clear(); + } +} diff --git a/engine/src/lib.rs b/engine/src/lib.rs index b3a2dc8..18ce5fd 100644 --- a/engine/src/lib.rs +++ b/engine/src/lib.rs @@ -1,4 +1,6 @@ pub mod engine; pub mod system; +mod input; +pub mod systems; pub use crate::engine::Engine; diff --git a/engine/src/system.rs b/engine/src/system.rs index 1ab49bf..b863a75 100644 --- a/engine/src/system.rs +++ b/engine/src/system.rs @@ -5,12 +5,13 @@ use raidillon_platform::PlatformContext; use std::any::TypeId; use std::cell::RefCell; use std::rc::Rc; +use crate::input::InputState; pub struct SystemContext<'a> { - // TODO: time delta etc. pub scene: &'a mut Scene, pub platform_context: PlatformContext, pub debug_ui_buffer: Rc>, + pub input_state: Rc>, } pub trait System { diff --git a/engine/src/systems/fps_camera.rs b/engine/src/systems/fps_camera.rs new file mode 100644 index 0000000..cbe14b6 --- /dev/null +++ b/engine/src/systems/fps_camera.rs @@ -0,0 +1,114 @@ +use crate::system::{System, SystemContext}; +use glam::{Quat, Vec3}; +use winit::event::DeviceEvent::MouseMotion; +use winit::event::{ElementState, Event, MouseButton, WindowEvent}; +use winit::keyboard::PhysicalKey; +use winit::window::CursorGrabMode; +use raidillon_assets::model_path; +use raidillon_platform::Camera; + +pub struct FPSCameraSystem { + mouse_delta: (f64, f64), + mouse_enabled: bool, + position: Vec3, + yaw: f32, + pitch: f32, + speed: f32, + sensitivity: f32, +} + +impl Default for FPSCameraSystem { + fn default() -> Self { + Self { + mouse_delta: Default::default(), + mouse_enabled: Default::default(), + position: Vec3::new(0.0, 0.0, 2.0), + yaw: -90.0, + pitch: 0.0, + speed: 3.0, + sensitivity: 0.1, + } + } +} + +impl System for FPSCameraSystem { + fn load_world(&mut self, ctx: &mut SystemContext) { + ctx.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: ctx.platform_context.frame_width / ctx.platform_context.frame_height, + znear: 0.1, + zfar: 100.0, + },)); + } + + fn handle_event(&mut self, ctx: &mut SystemContext) { + let event2 = ctx.platform_context.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; + }, + _ => {} + } + }, + Event::WindowEvent { event, .. } => match event { + WindowEvent::MouseInput { state, button, .. } => { + if button == MouseButton::Right { + // blood and tear + let window = ctx.platform_context.window.lock().unwrap(); + match state { + ElementState::Pressed => { + if window + .set_cursor_grab(CursorGrabMode::Confined) + .or_else(|_| window.set_cursor_grab(CursorGrabMode::Locked)) + .is_ok() + { + window.set_cursor_visible(false); + self.mouse_enabled = true; + } + } + ElementState::Released => { + let _ = window.set_cursor_grab(CursorGrabMode::None); + window.set_cursor_visible(true); + self.mouse_enabled = false; + } + } + } + } + _ => {}, + }, + _ => {}, + } + } + + fn frame_update(&mut self, ctx: &mut SystemContext) { + if self.mouse_enabled { + 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); + } + + ctx.scene.world.query_mut::<&mut Camera>().into_iter().for_each(|(_, camera)| { + camera.eye = self.position; + camera.center = self.position + self.front(); + }); + self.mouse_delta = (0.0, 0.0); + } +} + +impl FPSCameraSystem { + 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() + } +} diff --git a/engine/src/systems/mod.rs b/engine/src/systems/mod.rs new file mode 100644 index 0000000..8489571 --- /dev/null +++ b/engine/src/systems/mod.rs @@ -0,0 +1 @@ +pub mod fps_camera; diff --git a/game/src/main.rs b/game/src/main.rs index bea5fe0..b7c45e0 100644 --- a/game/src/main.rs +++ b/game/src/main.rs @@ -10,12 +10,56 @@ use raidillon_ecs::Transform; use raidillon_core::scene::Scene; #[cfg(feature = "glium")] use raidillon_glium::GliumPlatform; -use winit::event::{Event, WindowEvent}; +use winit::event::{ElementState, Event, WindowEvent}; +use winit::event::DeviceEvent::MouseMotion; +use winit::keyboard::{KeyCode, PhysicalKey}; +use raidillon_engine::systems::fps_camera::FPSCameraSystem; const TEST_GLTF: &str = "pink-monkey.gltf"; const MAIN_SCENE_ID: &str = "main_scene"; +#[derive(Default)] +struct InputTestSystem { + mouse_delta: (f64, f64), +} + +impl System for InputTestSystem { + fn handle_event(&mut self, ctx: &mut SystemContext) { + let event2 = ctx.platform_context.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; + println!("UPDATED mouse delta: ({},{})", self.mouse_delta.0, self.mouse_delta.1); + }, + _ => {} + } + }, + Event::WindowEvent { event, .. } => match event { + WindowEvent::KeyboardInput { device_id, event, is_synthetic} => { + let PhysicalKey::Code(key_code) = event.physical_key else { + return; + }; + + match event.state { + ElementState::Pressed => { + println!("Pressed Key: {:?}", key_code); + } + ElementState::Released => { + println!("Released Key: {:?}", key_code); + } + } + } + _ => {}, + } + _ => {}, + } + } +} + #[derive(Default)] struct UpdateAspectRatioSystem; impl System for UpdateAspectRatioSystem { @@ -42,16 +86,6 @@ impl System for RenderingTestSystem { fn load_world(&mut self, ctx: &mut SystemContext) { self.rotation_speed = std::rc::Rc::new(std::cell::RefCell::new(5.0)); - ctx.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: ctx.platform_context.frame_width / ctx.platform_context.frame_height, - znear: 0.1, - zfar: 100.0, - },)); - let mut am = ctx.platform_context.asset_manager.borrow_mut(); am.load_gltf(TEST_GLTF, &model_path(TEST_GLTF)); @@ -72,6 +106,20 @@ impl System for RenderingTestSystem { dbg_ui.text(format!("Frame Delta: {}", ctx.platform_context.time_ctx.frame_dt)); dbg_ui.text(format!("Fixed Delta: {}", ctx.platform_context.time_ctx.fixed_dt)); dbg_ui.slider_f32("Rotation Speed", -10.0, 10.0, self.rotation_speed.clone()); + + let input = ctx.input_state.borrow(); + if input.key_held(KeyCode::KeyW) { + dbg_ui.text("W".to_owned()); + } + if input.key_held(KeyCode::KeyA) { + dbg_ui.text("A".to_owned()); + } + if input.key_held(KeyCode::KeyS) { + dbg_ui.text("S".to_owned()); + } + if input.key_held(KeyCode::KeyD) { + dbg_ui.text("D".to_owned()); + } } fn fixed_update(&mut self, ctx: &mut SystemContext) { @@ -85,8 +133,10 @@ impl System for RenderingTestSystem { fn main() { let mut engine = Engine::new(); // Define systems + engine.system_manager.add::(); engine.system_manager.add::(); engine.system_manager.add::(); + // engine.system_manager.add::(); // Set up the scene let main_scene = Scene::new( @@ -102,7 +152,7 @@ fn main() { engine, "Raidillon".to_string(), 2560, - 1440, + 1080, ); platform.run() }; diff --git a/glium_platform/src/platform.rs b/glium_platform/src/platform.rs index f03cd96..9418ab1 100644 --- a/glium_platform/src/platform.rs +++ b/glium_platform/src/platform.rs @@ -1,5 +1,6 @@ use std::cell::RefCell; use std::rc::Rc; +use std::sync::{Arc, Mutex}; use raidillon_platform::{Platform, PlatformContext, TimeContext}; use glium::backend::glutin::Display; use glium::backend::glutin::SimpleWindowBuilder; @@ -8,7 +9,7 @@ use glium::winit::event_loop::EventLoop; use glium::winit::window::Window; use glium::Surface; use crate::system::{RenderingContext, RenderingSystemManager}; -use winit::event::{Event, WindowEvent}; +use winit::event::{DeviceEvent, Event, WindowEvent}; use raidillon_assets::ModelManagerRef; use raidillon_core::engine::EngineTrait; use raidillon_core::time; @@ -17,10 +18,11 @@ use crate::render::debug_ui::ImguiBridge; use crate::render::{BasicMeshRenderingSystem, SkyboxRenderingSystem}; use crate::GliumAssetManager; use glam::Vec3; +use winit::event::DeviceEvent::MouseMotion; pub struct GliumPlatform> { event_loop: EventLoop<()>, - window: Window, + window: Arc>, display: Display, rendering_system_manager: RenderingSystemManager, asset_manager: ModelManagerRef, @@ -45,10 +47,12 @@ impl> Platform for GliumPlatfor let time_cfg = time::Config::default(); let time = time::Time::new(time_cfg); + let window = Arc::new(Mutex::new(window)); + // Install rendering systems in order - rendering_system_manager.add::(&display, &window); - rendering_system_manager.add::(&display, &window); - rendering_system_manager.add::(&display, &window); + rendering_system_manager.add::(&display, window.clone()); + rendering_system_manager.add::(&display, window.clone()); + rendering_system_manager.add::(&display, window.clone()); Self { event_loop, @@ -62,20 +66,24 @@ impl> Platform for GliumPlatfor } fn run(mut self) { - let (w, h): (u32, u32) = self.window.inner_size().into(); + let (w, h): (u32, u32) = match self.window.lock() { + Ok(window) => window.inner_size().into(), + Err(_) => (0, 0), // fallback values + }; let ctx = PlatformContext { current_event: Event::AboutToWait, asset_manager: self.asset_manager.clone(), frame_width: w as f32, frame_height: h as f32, time_ctx: self.construct_time_ctx(), + window: self.window.clone(), }; self.engine.initialize(ctx.clone()); let _ = &self.event_loop.run(move |event, el| { self.rendering_system_manager .systems .values_mut() - .for_each(|system| system.handle_event(&mut self.window, event.clone())); + .for_each(|system| system.handle_event(self.window.clone(), event.clone())); let mut ctx2 = ctx.clone(); ctx2.current_event = event.clone(); @@ -95,7 +103,7 @@ impl> Platform for GliumPlatfor scene: scene_mut, target: &mut target, asset_manager: self.asset_manager.clone(), - window: &mut self.window, + window: self.window.clone(), debug_ui_buffer, env_light_dir: Vec3::new(0.0, -1.0, 0.0), }; @@ -129,8 +137,8 @@ impl> Platform for GliumPlatfor self.rendering_system_manager .systems .values_mut() - .for_each(|system| system.prepare_frame(&mut self.window)); - self.window.request_redraw(); + .for_each(|system| system.prepare_frame(self.window.clone())); + self.window.lock().unwrap().request_redraw(); } _ => {}, } diff --git a/glium_platform/src/render/basic.rs b/glium_platform/src/render/basic.rs index 8551ecd..663b2dd 100644 --- a/glium_platform/src/render/basic.rs +++ b/glium_platform/src/render/basic.rs @@ -1,4 +1,5 @@ use std::any::Any; +use std::sync::{Arc, Mutex}; use glium::{uniform, Display, Program, Surface}; use glium::glutin::surface::WindowSurface; use glium::texture::{RawImage2d, SrgbTexture2d}; @@ -20,7 +21,7 @@ pub struct BasicMeshRenderingSystem { } impl RenderingSystem for BasicMeshRenderingSystem { - fn initialize(display: &Display, _window: &glium::winit::window::Window) -> Self { + fn initialize(display: &Display, _window: Arc>) -> Self { const VERT_SRC: &str = include_shader!("gl_textured.vert"); const FRAG_SRC: &str = include_shader!("gl_textured.frag"); diff --git a/glium_platform/src/render/debug_ui.rs b/glium_platform/src/render/debug_ui.rs index ff29fe1..be4ff0d 100644 --- a/glium_platform/src/render/debug_ui.rs +++ b/glium_platform/src/render/debug_ui.rs @@ -1,3 +1,4 @@ +use std::sync::{Arc, Mutex}; use std::time::Instant; use glium::Display; use glium::glutin::surface::WindowSurface; @@ -19,17 +20,19 @@ pub struct ImguiBridge { } impl RenderingSystem for ImguiBridge { - fn handle_event(&mut self, window: &mut Window, event: Event<()>) { - self.platform.handle_event(self.imgui.io_mut(), window, &event); + fn handle_event(&mut self, window: Arc>, event: Event<()>) { + let window = window.lock().unwrap(); + self.platform.handle_event(self.imgui.io_mut(), &*window, &event); } - fn prepare_frame(&mut self, window: &mut Window) { + fn prepare_frame(&mut self, window: Arc>) { self.rendered_this_frame = false; let now = Instant::now(); self.imgui.io_mut().update_delta_time(now - self.last_frame); self.last_frame = now; + let window = window.lock().unwrap(); self.platform - .prepare_frame(self.imgui.io_mut(), window) + .prepare_frame(self.imgui.io_mut(), &*window) .expect("Failed to prepare frame"); } @@ -40,7 +43,10 @@ impl RenderingSystem for ImguiBridge { let ui = self.imgui.frame(); ctx.debug_ui_buffer.borrow().write_buffer(&ui); - self.platform.prepare_render(&ui, ctx.window); + { + let window = ctx.window.lock().unwrap(); + self.platform.prepare_render(&ui, &*window); + } let draw_data = self.imgui.render(); if draw_data.total_vtx_count == 0 && draw_data.total_idx_count == 0 { return; @@ -49,11 +55,12 @@ impl RenderingSystem for ImguiBridge { self.renderer.render(ctx.target, draw_data).expect("imgui rendering failed"); } - fn initialize(display: &Display, window: &Window) -> Self { + fn initialize(display: &Display, window: Arc>) -> Self { let mut imgui = ImguiContext::create(); imgui.set_ini_filename(None); let mut platform = WinitPlatform::new(&mut imgui); - platform.attach_window(imgui.io_mut(), window, HiDpiMode::Default); + let window = window.lock().unwrap(); + platform.attach_window(imgui.io_mut(), &*window, HiDpiMode::Default); imgui.fonts().add_font(&[imgui::FontSource::DefaultFontData { config: None }]); let renderer = ImguiGliumRenderer::new(&mut imgui, display).unwrap(); diff --git a/glium_platform/src/render/skybox.rs b/glium_platform/src/render/skybox.rs index 49ea594..ac22210 100644 --- a/glium_platform/src/render/skybox.rs +++ b/glium_platform/src/render/skybox.rs @@ -1,6 +1,7 @@ use std::path::PathBuf; use std::rc::Rc; use std::cell::RefCell; +use std::sync::{Arc, Mutex}; use glium::{Display, Program, Surface, VertexBuffer, IndexBuffer, implement_vertex}; use glium::glutin::surface::WindowSurface; use glium::index::PrimitiveType; @@ -108,7 +109,7 @@ impl SkyboxRenderingSystem { } impl RenderingSystem for SkyboxRenderingSystem { - fn initialize(display: &Display, _window: &glium::winit::window::Window) -> Self { + fn initialize(display: &Display, _window: Arc>) -> Self { const VERT_SRC: &str = include_shader!("skybox.vert"); const FRAG_SRC: &str = include_shader!("skybox.frag"); let program = Program::from_source(display, VERT_SRC, FRAG_SRC, None).unwrap(); diff --git a/glium_platform/src/system.rs b/glium_platform/src/system.rs index 891fec0..3460bc3 100644 --- a/glium_platform/src/system.rs +++ b/glium_platform/src/system.rs @@ -1,6 +1,7 @@ use std::any::TypeId; use std::cell::RefCell; use std::rc::Rc; +use std::sync::{Arc, Mutex}; use indexmap::IndexMap; use glium::{Display, Frame}; use glium::glutin::surface::WindowSurface; @@ -12,7 +13,7 @@ use glam::Vec3; pub struct RenderingContext<'a> { pub scene: &'a Scene, pub target: &'a mut Frame, - pub window: &'a mut glium::winit::window::Window, + pub window: Arc>, pub asset_manager: ModelManagerRef, pub debug_ui_buffer: Rc>, pub env_light_dir: Vec3, @@ -23,13 +24,13 @@ pub struct RenderingContext<'a> { pub trait RenderingSystem { fn handle_event( &mut self, - _window: &mut glium::winit::window::Window, + _window: Arc>, _event: winit::event::Event<()>, ) { } - fn prepare_frame(&mut self, _window: &mut glium::winit::window::Window) {} + fn prepare_frame(&mut self, _window: Arc>) {} fn render(&mut self, ctx: &mut RenderingContext); - fn initialize(display: &Display, window: &glium::winit::window::Window) -> Self + fn initialize(display: &Display, window: Arc>) -> Self where Self: Sized; } @@ -45,7 +46,7 @@ impl RenderingSystemManager { } } - pub fn add(&mut self, display: &Display, window: &glium::winit::window::Window) + pub fn add(&mut self, display: &Display, window: Arc>) where R: RenderingSystem + 'static, { diff --git a/platform/src/context.rs b/platform/src/context.rs index bea1cb1..892b69e 100644 --- a/platform/src/context.rs +++ b/platform/src/context.rs @@ -1,3 +1,4 @@ +use std::sync::{Arc, Mutex}; use winit::event::Event; use raidillon_assets::ModelManagerRef; @@ -8,6 +9,7 @@ pub struct PlatformContext { pub frame_width: f32, pub frame_height: f32, pub time_ctx: TimeContext, + pub window: Arc>, } #[derive(Clone)] From 7732280229cedbeaa8771c0b487a87eb51cec823 Mon Sep 17 00:00:00 2001 From: reo Date: Mon, 29 Sep 2025 16:04:40 +0300 Subject: [PATCH 56/89] Add WASD keys to FPSDebugCamera system, rename to FPSDebugCameraSystem --- engine/src/systems/fps_camera.rs | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/engine/src/systems/fps_camera.rs b/engine/src/systems/fps_camera.rs index cbe14b6..3cc0a3d 100644 --- a/engine/src/systems/fps_camera.rs +++ b/engine/src/systems/fps_camera.rs @@ -2,12 +2,12 @@ use crate::system::{System, SystemContext}; use glam::{Quat, Vec3}; use winit::event::DeviceEvent::MouseMotion; use winit::event::{ElementState, Event, MouseButton, WindowEvent}; -use winit::keyboard::PhysicalKey; +use winit::keyboard::{KeyCode, PhysicalKey}; use winit::window::CursorGrabMode; use raidillon_assets::model_path; use raidillon_platform::Camera; -pub struct FPSCameraSystem { +pub struct FPSDebugCameraSystem { mouse_delta: (f64, f64), mouse_enabled: bool, position: Vec3, @@ -17,7 +17,7 @@ pub struct FPSCameraSystem { sensitivity: f32, } -impl Default for FPSCameraSystem { +impl Default for FPSDebugCameraSystem { fn default() -> Self { Self { mouse_delta: Default::default(), @@ -31,7 +31,7 @@ impl Default for FPSCameraSystem { } } -impl System for FPSCameraSystem { +impl System for FPSDebugCameraSystem { fn load_world(&mut self, ctx: &mut SystemContext) { ctx.scene.world.spawn((Camera { eye: Vec3::new(0.0, 0.0, 2.0), @@ -93,15 +93,32 @@ impl System for FPSCameraSystem { self.pitch = self.pitch.clamp(-89.0, 89.0); } + let front = self.front(); + let right_vec = front.cross(Vec3::Y).normalize(); + let input = ctx.input_state.borrow_mut(); + + if input.key_held(KeyCode::KeyW) { + self.position += front * ctx.platform_context.time_ctx.frame_dt * self.speed; + } + if input.key_held(KeyCode::KeyS) { + self.position -= front * ctx.platform_context.time_ctx.frame_dt * self.speed; + } + if input.key_held(KeyCode::KeyA) { + self.position -= right_vec * ctx.platform_context.time_ctx.frame_dt * self.speed; + } + if input.key_held(KeyCode::KeyD) { + self.position += right_vec * ctx.platform_context.time_ctx.frame_dt * self.speed; + } + ctx.scene.world.query_mut::<&mut Camera>().into_iter().for_each(|(_, camera)| { camera.eye = self.position; - camera.center = self.position + self.front(); + camera.center = self.position + front; }); self.mouse_delta = (0.0, 0.0); } } -impl FPSCameraSystem { +impl FPSDebugCameraSystem { pub fn front(&self) -> Vec3 { let yaw_rad = self.yaw.to_radians(); let pitch_rad = self.pitch.to_radians(); From 6e42d94b4416c62fdfed4a11056fc2b215b1c033 Mon Sep 17 00:00:00 2001 From: reo Date: Mon, 29 Sep 2025 16:05:54 +0300 Subject: [PATCH 57/89] Remove the older debug system, rename FPSDebugCameraSystem --- game/src/main.rs | 59 ++---------------------------------------------- 1 file changed, 2 insertions(+), 57 deletions(-) diff --git a/game/src/main.rs b/game/src/main.rs index b7c45e0..d5a826b 100644 --- a/game/src/main.rs +++ b/game/src/main.rs @@ -13,53 +13,12 @@ use raidillon_glium::GliumPlatform; use winit::event::{ElementState, Event, WindowEvent}; use winit::event::DeviceEvent::MouseMotion; use winit::keyboard::{KeyCode, PhysicalKey}; -use raidillon_engine::systems::fps_camera::FPSCameraSystem; +use raidillon_engine::systems::fps_camera::FPSDebugCameraSystem; const TEST_GLTF: &str = "pink-monkey.gltf"; const MAIN_SCENE_ID: &str = "main_scene"; -#[derive(Default)] -struct InputTestSystem { - mouse_delta: (f64, f64), -} - -impl System for InputTestSystem { - fn handle_event(&mut self, ctx: &mut SystemContext) { - let event2 = ctx.platform_context.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; - println!("UPDATED mouse delta: ({},{})", self.mouse_delta.0, self.mouse_delta.1); - }, - _ => {} - } - }, - Event::WindowEvent { event, .. } => match event { - WindowEvent::KeyboardInput { device_id, event, is_synthetic} => { - let PhysicalKey::Code(key_code) = event.physical_key else { - return; - }; - - match event.state { - ElementState::Pressed => { - println!("Pressed Key: {:?}", key_code); - } - ElementState::Released => { - println!("Released Key: {:?}", key_code); - } - } - } - _ => {}, - } - _ => {}, - } - } -} - #[derive(Default)] struct UpdateAspectRatioSystem; impl System for UpdateAspectRatioSystem { @@ -106,20 +65,6 @@ impl System for RenderingTestSystem { dbg_ui.text(format!("Frame Delta: {}", ctx.platform_context.time_ctx.frame_dt)); dbg_ui.text(format!("Fixed Delta: {}", ctx.platform_context.time_ctx.fixed_dt)); dbg_ui.slider_f32("Rotation Speed", -10.0, 10.0, self.rotation_speed.clone()); - - let input = ctx.input_state.borrow(); - if input.key_held(KeyCode::KeyW) { - dbg_ui.text("W".to_owned()); - } - if input.key_held(KeyCode::KeyA) { - dbg_ui.text("A".to_owned()); - } - if input.key_held(KeyCode::KeyS) { - dbg_ui.text("S".to_owned()); - } - if input.key_held(KeyCode::KeyD) { - dbg_ui.text("D".to_owned()); - } } fn fixed_update(&mut self, ctx: &mut SystemContext) { @@ -133,7 +78,7 @@ impl System for RenderingTestSystem { fn main() { let mut engine = Engine::new(); // Define systems - engine.system_manager.add::(); + engine.system_manager.add::(); engine.system_manager.add::(); engine.system_manager.add::(); // engine.system_manager.add::(); From ef055a1bda1f627c8e28fc51196e425e99980c53 Mon Sep 17 00:00:00 2001 From: reo Date: Wed, 15 Oct 2025 22:33:04 +0300 Subject: [PATCH 58/89] Replace contexts with resources - Implements a new macro to generate code for a new structure: TypeMap - TypeMaps are wrappers for HashMaps that use TypeIDs as keys. - Refactor the entire codebase to use the new resource structures. - This commit is the first step towards getting rid of "god context objects everywhere". --- Cargo.toml | 2 +- core/src/engine.rs | 5 +- core/src/lib.rs | 3 +- core/src/scene.rs | 16 +++- core/src/utils/managers.rs | 44 ++++++++++ core/src/utils/mod.rs | 2 + core/src/utils/typemap.rs | 122 ++++++++++++++++++++++++++ engine/src/engine.rs | 85 ++++++++---------- engine/src/lib.rs | 2 + engine/src/resources.rs | 3 + engine/src/system.rs | 9 +- engine/src/systems/fps_camera.rs | 35 +++++--- game/src/main.rs | 37 ++++---- glium_platform/src/platform.rs | 7 +- glium_platform/src/render/debug_ui.rs | 2 +- glium_platform/src/system.rs | 6 +- 16 files changed, 287 insertions(+), 93 deletions(-) create mode 100644 core/src/utils/managers.rs create mode 100644 core/src/utils/mod.rs create mode 100644 core/src/utils/typemap.rs create mode 100644 engine/src/resources.rs diff --git a/Cargo.toml b/Cargo.toml index 102844c..23332d0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,5 +6,5 @@ members = [ "asset", "game", "ecs", - "engine" + "engine", ] diff --git a/core/src/engine.rs b/core/src/engine.rs index 80d2a69..b70a945 100644 --- a/core/src/engine.rs +++ b/core/src/engine.rs @@ -11,7 +11,8 @@ pub trait EngineTrait { fn fixed_update(&mut self, platform_context: Self::PlatformCtx); fn handle_event(&mut self, platform_context: Self::PlatformCtx); fn current_scene_mut(&mut self) -> &mut Scene; - fn get_debug_ui_buffer(&self) -> Rc>; + fn current_scene(&self) -> &Scene; + fn get_debug_ui_buffer(&self) -> &DebugUIBuffer; fn reset_debug_ui_buffer(&mut self); - fn scene_and_debug_ui_buffer_mut(&mut self) -> (&mut Scene, Rc>); + // fn scene_and_debug_ui_buffer_mut(&mut self) -> (&mut Self::Scene, &DebugUIBuffer); } diff --git a/core/src/lib.rs b/core/src/lib.rs index 4b7d531..238d5a6 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -1,6 +1,7 @@ pub mod engine; -pub mod scene; pub mod debug_ui; pub mod time; +pub mod utils; +pub mod scene; pub use debug_ui::*; diff --git a/core/src/scene.rs b/core/src/scene.rs index 9d1a7d4..1a075bf 100644 --- a/core/src/scene.rs +++ b/core/src/scene.rs @@ -1,19 +1,31 @@ use std::collections::HashMap; use std::path::{Path, PathBuf}; +use crate::{define_typemap, DebugUIBuffer}; pub struct Scene { pub title: String, pub world: hecs::World, pub skybox_texture_path: Option, + pub resources: SceneResources, } +define_typemap!(SceneResources,); + impl Scene { pub fn new(title: String, skybox_texture_path: Option) -> Self { - Self { + let mut s = Self { title, world: hecs::World::new(), skybox_texture_path, - } + resources: SceneResources::new(), + }; + s.load_default_resources(); + s + } + + pub fn load_default_resources(&mut self) { + let dbg = DebugUIBuffer::new(); + self.resources.insert(dbg); } } diff --git a/core/src/utils/managers.rs b/core/src/utils/managers.rs new file mode 100644 index 0000000..aac2ce7 --- /dev/null +++ b/core/src/utils/managers.rs @@ -0,0 +1,44 @@ +/// Unused as of now. +#[macro_export] +macro_rules! create_manager { + ($manager_name:ident, $trait_name:ident) => { + pub struct $manager_name { + systems: ::indexmap::IndexMap<::std::any::TypeId, Box>, + } + + impl $manager_name { + pub fn new() -> Self { + Self { + systems: ::indexmap::IndexMap::default(), + } + } + + pub fn add(&mut self) { + self.systems + .insert(::std::any::TypeId::of::(), Box::new(S::default())); + } + + pub fn remove(&mut self) { + self.systems.shift_remove(&::std::any::TypeId::of::()); + } + + pub fn for_each_value(&self, mut f: F) + where + F: FnMut(&dyn $trait_name), + { + for value in self.systems.values() { + f(value.as_ref()); + } + } + + pub fn for_each_value_mut(&mut self, mut f: F) + where + F: FnMut(&mut dyn $trait_name), + { + for value in self.systems.values_mut() { + f(value.as_mut()); + } + } + } + }; +} diff --git a/core/src/utils/mod.rs b/core/src/utils/mod.rs new file mode 100644 index 0000000..4a5eaf5 --- /dev/null +++ b/core/src/utils/mod.rs @@ -0,0 +1,2 @@ +pub mod typemap; +mod managers; diff --git a/core/src/utils/typemap.rs b/core/src/utils/typemap.rs new file mode 100644 index 0000000..88d3dc5 --- /dev/null +++ b/core/src/utils/typemap.rs @@ -0,0 +1,122 @@ +#[macro_export] +macro_rules! define_typemap { + ($name:ident, $($trait_bound:tt)*) => { + pub struct $name { + map: std::collections::HashMap>, + } + + impl $name { + pub fn new() -> Self { + Self { + map: std::collections::HashMap::new(), + } + } + + pub fn insert(&mut self, value: T) -> Option> + where + T: std::any::Any + 'static + $($trait_bound)*, + { + let type_id = std::any::TypeId::of::(); + self.map + .insert(type_id, Box::new(value)) + .and_then(|boxed| boxed.downcast().ok()) + } + + pub fn get(&self) -> Option<&T> + where + T: std::any::Any + 'static + $($trait_bound)*, + { + self.map + .get(&std::any::TypeId::of::()) + .and_then(|any| any.downcast_ref::()) + } + + pub fn get_mut(&mut self) -> Option<&mut T> + where + T: std::any::Any + 'static + $($trait_bound)*, + { + self.map + .get_mut(&std::any::TypeId::of::()) + .and_then(|any| any.downcast_mut::()) + } + + pub fn remove(&mut self) -> Option> + where + T: std::any::Any + 'static + $($trait_bound)*, + { + self.map + .remove(&std::any::TypeId::of::()) + .and_then(|boxed| boxed.downcast().ok()) + } + + pub fn len(&self) -> usize { + self.map.len() + } + + pub fn is_empty(&self) -> bool { + self.map.is_empty() + } + + pub fn clear(&mut self) { + self.map.clear(); + } + + pub fn contains(&self) -> bool + where + T: std::any::Any + 'static + $($trait_bound)*, + { + self.map.contains_key(&std::any::TypeId::of::()) + } + } + + impl Default for $name { + fn default() -> Self { + Self::new() + } + } + }; +} + +// pub struct TypeMap { +// map: HashMap>, +// } +// +// impl TypeMap { +// pub fn new() -> Self { +// Self { +// map: HashMap::new(), +// } +// } +// +// pub fn insert(&mut self, value: T) -> Option> { +// let type_id = TypeId::of::(); +// self.map +// .insert(type_id, Box::new(value)) +// .and_then(|boxed| boxed.downcast().ok()) +// } +// +// pub fn get(&self) -> Option<&T> +// where +// T: Any + 'static, +// { +// self.map.get(&TypeId::of::()) +// .and_then(|any| any.downcast_ref::()) +// } +// +// pub fn get_mut(&mut self) -> Option<&mut T> +// where +// T: Any + 'static, +// { +// self.map.get_mut(&TypeId::of::()).and_then(|any| any.downcast_mut::()) +// } +// +// pub fn remove(&mut self) -> Option> { +// unimplemented!() +// } +// } +// +// impl Default for TypeMap { +// fn default() -> Self { +// Self::new() +// } +// } diff --git a/engine/src/engine.rs b/engine/src/engine.rs index 68f17e0..7c366dc 100644 --- a/engine/src/engine.rs +++ b/engine/src/engine.rs @@ -3,15 +3,22 @@ use std::rc::Rc; use raidillon_core::scene::{Scene, SceneManager}; use crate::system::{SystemContext, SystemManager}; use raidillon_platform::PlatformContext; -use raidillon_core::DebugUIBuffer; +use raidillon_core::{define_typemap, DebugUIBuffer}; use raidillon_core::engine::EngineTrait; use crate::input::InputState; +use crate::resources::EngineResources; pub struct Engine { pub scene_manager: SceneManager, pub system_manager: SystemManager, - debug_ui_buffer: Rc>, - input_state: Rc>, + pub resources: EngineResources, +} + +impl Engine { + fn load_default_resources(&mut self) { + let input = InputState::default(); + self.resources.insert(input); + } } impl EngineTrait for Engine { @@ -19,12 +26,13 @@ impl EngineTrait for Engine { fn new() -> Self { let scene_manager = SceneManager::new(); let system_manager = SystemManager::new(); - Self { + let mut s = Self { scene_manager, system_manager, - debug_ui_buffer: Rc::new(RefCell::new(DebugUIBuffer::new())), - input_state: Default::default(), - } + resources: EngineResources::new(), + }; + s.load_default_resources(); + s } /// Initialize systems, load the world. @@ -33,60 +41,35 @@ impl EngineTrait for Engine { for system in self.system_manager.systems.values_mut() { system.initialize(); } - - let mut ctx = SystemContext { - scene: self.scene_manager.current_mut(), - platform_context, - debug_ui_buffer: self.debug_ui_buffer.clone(), - input_state: self.input_state.clone(), - }; - + self.resources.insert(platform_context); // Engine Loading Stage 2: load world for system in self.system_manager.systems.values_mut() { - system.load_world(&mut ctx); + system.load_world(&mut self.resources, &mut self.scene_manager.current_mut()); } } /// Update the engine fn frame_update(&mut self, platform_context: PlatformContext) { - self.debug_ui_buffer.borrow_mut().reset_buffer(); - let mut ctx = SystemContext { - scene: self.scene_manager.current_mut(), - platform_context, - debug_ui_buffer: self.debug_ui_buffer.clone(), - input_state: self.input_state.clone(), - }; + self.scene_manager.current_mut().resources.get_mut::().unwrap().reset_buffer(); + self.resources.insert(platform_context); for system in self.system_manager.systems.values_mut() { - system.frame_update(&mut ctx); + system.frame_update(&mut self.resources, &mut self.scene_manager.current_mut()); } } fn fixed_update(&mut self, platform_context: PlatformContext) { - let mut ctx = SystemContext { - scene: self.scene_manager.current_mut(), - platform_context, - debug_ui_buffer: self.debug_ui_buffer.clone(), - input_state: self.input_state.clone(), - }; - + self.resources.insert(platform_context); for system in self.system_manager.systems.values_mut() { - system.fixed_update(&mut ctx); + system.fixed_update(&mut self.resources, &mut self.scene_manager.current_mut()); } } fn handle_event(&mut self, platform_context: PlatformContext) { - self.input_state.borrow_mut().handle_event(&platform_context.current_event); - - let mut ctx = SystemContext { - scene: self.scene_manager.current_mut(), - platform_context, - debug_ui_buffer: self.debug_ui_buffer.clone(), - input_state: self.input_state.clone(), - }; - + // self.input_state.borrow_mut().handle_event(&platform_context.current_event); + self.resources.insert(platform_context); for system in self.system_manager.systems.values_mut() { - system.handle_event(&mut ctx); + system.handle_event(&mut self.resources, &mut self.scene_manager.current_mut()); } } @@ -100,16 +83,20 @@ impl EngineTrait for Engine { self.scene_manager.current_mut() } - fn get_debug_ui_buffer(&self) -> Rc> { - self.debug_ui_buffer.clone() + fn current_scene(&self) -> &Scene { + self.scene_manager.current() + } + + fn get_debug_ui_buffer(&self) -> &DebugUIBuffer { + self.scene_manager.current().resources.get::().unwrap() } fn reset_debug_ui_buffer(&mut self) { - self.debug_ui_buffer.borrow_mut().reset_buffer(); + self.scene_manager.current_mut().resources.get_mut::().unwrap().reset_buffer(); } - fn scene_and_debug_ui_buffer_mut(&mut self) -> (&mut Scene, Rc>) { - let (sm, dub) = (&mut self.scene_manager, &mut self.debug_ui_buffer); - (sm.current_mut(), dub.clone()) - } + // fn scene_and_debug_ui_buffer_mut(&mut self) -> (&mut Scene, &DebugUIBuffer) { + // let (sm, dub) = (&mut self.scene_manager, self.scene_manager.current().resources.get::().unwrap()); + // (sm.current_mut(), dub) + // } } diff --git a/engine/src/lib.rs b/engine/src/lib.rs index 18ce5fd..9a87556 100644 --- a/engine/src/lib.rs +++ b/engine/src/lib.rs @@ -2,5 +2,7 @@ pub mod engine; pub mod system; mod input; pub mod systems; +mod resources; pub use crate::engine::Engine; +pub use crate::resources::EngineResources; diff --git a/engine/src/resources.rs b/engine/src/resources.rs new file mode 100644 index 0000000..cd4be0b --- /dev/null +++ b/engine/src/resources.rs @@ -0,0 +1,3 @@ +use raidillon_core::define_typemap; + +define_typemap!(EngineResources,); diff --git a/engine/src/system.rs b/engine/src/system.rs index b863a75..55cccb1 100644 --- a/engine/src/system.rs +++ b/engine/src/system.rs @@ -6,6 +6,7 @@ use std::any::TypeId; use std::cell::RefCell; use std::rc::Rc; use crate::input::InputState; +use crate::resources::EngineResources; pub struct SystemContext<'a> { pub scene: &'a mut Scene, @@ -18,10 +19,10 @@ pub trait System { /// Initialize the system. fn initialize(&mut self) {} /// Spawn the first entities of the world. - fn load_world(&mut self, _ctx: &mut SystemContext) {} - fn handle_event(&mut self, _ctx: &mut SystemContext) {} - fn fixed_update(&mut self, _ctx: &mut SystemContext) {} - fn frame_update(&mut self, _ctx: &mut SystemContext) {} + fn load_world(&mut self, res: &mut EngineResources, scene: &mut Scene) {} + fn handle_event(&mut self, res: &mut EngineResources, scene: &mut Scene) {} + fn fixed_update(&mut self, res: &mut EngineResources, scene: &mut Scene) {} + fn frame_update(&mut self, res: &mut EngineResources, scene: &mut Scene) {} } pub struct SystemManager { diff --git a/engine/src/systems/fps_camera.rs b/engine/src/systems/fps_camera.rs index 3cc0a3d..6bd99f7 100644 --- a/engine/src/systems/fps_camera.rs +++ b/engine/src/systems/fps_camera.rs @@ -5,7 +5,10 @@ use winit::event::{ElementState, Event, MouseButton, WindowEvent}; use winit::keyboard::{KeyCode, PhysicalKey}; use winit::window::CursorGrabMode; use raidillon_assets::model_path; -use raidillon_platform::Camera; +use raidillon_platform::{Camera, PlatformContext}; +use crate::input::InputState; +use crate::resources::EngineResources; +use raidillon_core::scene::Scene; pub struct FPSDebugCameraSystem { mouse_delta: (f64, f64), @@ -32,20 +35,22 @@ impl Default for FPSDebugCameraSystem { } impl System for FPSDebugCameraSystem { - fn load_world(&mut self, ctx: &mut SystemContext) { - ctx.scene.world.spawn((Camera { + fn load_world(&mut self, res: &mut EngineResources, scene: &mut Scene) { + let pctx = res.get::().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: ctx.platform_context.frame_width / ctx.platform_context.frame_height, + aspect: pctx.frame_width / pctx.frame_height, znear: 0.1, zfar: 100.0, },)); } - fn handle_event(&mut self, ctx: &mut SystemContext) { - let event2 = ctx.platform_context.current_event.clone(); + fn handle_event(&mut self, res: &mut EngineResources, scene: &mut Scene) { + let pctx = res.get::().unwrap(); + let event2 = pctx.current_event.clone(); match event2 { Event::DeviceEvent { device_id, event} => { match event { @@ -60,7 +65,7 @@ impl System for FPSDebugCameraSystem { WindowEvent::MouseInput { state, button, .. } => { if button == MouseButton::Right { // blood and tear - let window = ctx.platform_context.window.lock().unwrap(); + let window = pctx.window.lock().unwrap(); match state { ElementState::Pressed => { if window @@ -86,7 +91,10 @@ impl System for FPSDebugCameraSystem { } } - fn frame_update(&mut self, ctx: &mut SystemContext) { + fn frame_update(&mut self, res: &mut EngineResources, scene: &mut Scene) { + let pctx = res.get::().unwrap(); + let input = res.get::().unwrap(); + if self.mouse_enabled { self.yaw += self.mouse_delta.0 as f32 * self.sensitivity; self.pitch -= self.mouse_delta.1 as f32 * self.sensitivity; @@ -95,22 +103,21 @@ impl System for FPSDebugCameraSystem { let front = self.front(); let right_vec = front.cross(Vec3::Y).normalize(); - let input = ctx.input_state.borrow_mut(); if input.key_held(KeyCode::KeyW) { - self.position += front * ctx.platform_context.time_ctx.frame_dt * self.speed; + self.position += front * pctx.time_ctx.frame_dt * self.speed; } if input.key_held(KeyCode::KeyS) { - self.position -= front * ctx.platform_context.time_ctx.frame_dt * self.speed; + self.position -= front * pctx.time_ctx.frame_dt * self.speed; } if input.key_held(KeyCode::KeyA) { - self.position -= right_vec * ctx.platform_context.time_ctx.frame_dt * self.speed; + self.position -= right_vec * pctx.time_ctx.frame_dt * self.speed; } if input.key_held(KeyCode::KeyD) { - self.position += right_vec * ctx.platform_context.time_ctx.frame_dt * self.speed; + self.position += right_vec * pctx.time_ctx.frame_dt * self.speed; } - ctx.scene.world.query_mut::<&mut Camera>().into_iter().for_each(|(_, camera)| { + scene.world.query_mut::<&mut Camera>().into_iter().for_each(|(_, camera)| { camera.eye = self.position; camera.center = self.position + front; }); diff --git a/game/src/main.rs b/game/src/main.rs index d5a826b..acedefd 100644 --- a/game/src/main.rs +++ b/game/src/main.rs @@ -1,8 +1,8 @@ use std::fmt::format; use glam::{Quat, Vec3}; -use raidillon_engine::{Engine, system::System}; +use raidillon_engine::{Engine, system::System, EngineResources}; use raidillon_engine::system::SystemContext; -use raidillon_platform::{Platform, Camera}; +use raidillon_platform::{Platform, Camera, PlatformContext}; use raidillon_assets::model_path; use raidillon_core::engine::EngineTrait; use raidillon_ecs::components::ModelHandle; @@ -13,6 +13,7 @@ use raidillon_glium::GliumPlatform; 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"; @@ -22,11 +23,13 @@ const MAIN_SCENE_ID: &str = "main_scene"; #[derive(Default)] struct UpdateAspectRatioSystem; impl System for UpdateAspectRatioSystem { - fn handle_event(&mut self, ctx: &mut SystemContext) { + fn handle_event(&mut self, res: &mut EngineResources, scene: &mut Scene) { + let pctx = res.get::().unwrap(); + if let Event::WindowEvent { event: WindowEvent::Resized(sz), .. } = - &ctx.platform_context.current_event + pctx.current_event { - ctx.scene.world + scene.world .query_mut::<&mut Camera>() .into_iter() .for_each(|(_, cam)| { @@ -42,14 +45,16 @@ struct RenderingTestSystem { } impl System for RenderingTestSystem { - fn load_world(&mut self, ctx: &mut SystemContext) { + fn load_world(&mut self, res: &mut EngineResources, scene: &mut Scene) { + let pctx = res.get::().unwrap(); + self.rotation_speed = std::rc::Rc::new(std::cell::RefCell::new(5.0)); - let mut am = ctx.platform_context.asset_manager.borrow_mut(); + let mut am = pctx.asset_manager.borrow_mut(); am.load_gltf(TEST_GLTF, &model_path(TEST_GLTF)); - ctx.scene.world.spawn(( + scene.world.spawn(( Transform { translation: Vec3::new(0.0, 0.0, 0.0), rotation: Quat::IDENTITY, @@ -59,17 +64,19 @@ impl System for RenderingTestSystem { )); } - fn frame_update(&mut self, ctx: &mut SystemContext) { - let mut dbg_ui = ctx.debug_ui_buffer.borrow_mut(); + fn frame_update(&mut self, res: &mut EngineResources, scene: &mut Scene) { + let pctx = res.get::().unwrap().clone(); + let dbg_ui = scene.resources.get_mut::().unwrap(); dbg_ui.text("Hello World!".to_owned()); - dbg_ui.text(format!("Frame Delta: {}", ctx.platform_context.time_ctx.frame_dt)); - dbg_ui.text(format!("Fixed Delta: {}", ctx.platform_context.time_ctx.fixed_dt)); + dbg_ui.text(format!("Frame Delta: {}", pctx.time_ctx.frame_dt)); + dbg_ui.text(format!("Fixed Delta: {}", pctx.time_ctx.fixed_dt)); dbg_ui.slider_f32("Rotation Speed", -10.0, 10.0, self.rotation_speed.clone()); } - fn fixed_update(&mut self, ctx: &mut SystemContext) { - ctx.scene.world.query_mut::<(&mut Transform, &ModelHandle)>().into_iter().for_each(|(_, (t, _))| { - t.rotation *= Quat::from_rotation_y(*self.rotation_speed.borrow() * ctx.platform_context.time_ctx.fixed_dt); + fn fixed_update(&mut self, res: &mut EngineResources, scene: &mut Scene) { + let pctx = res.get::().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); }); } diff --git a/glium_platform/src/platform.rs b/glium_platform/src/platform.rs index 9418ab1..db8e56e 100644 --- a/glium_platform/src/platform.rs +++ b/glium_platform/src/platform.rs @@ -98,9 +98,12 @@ impl> Platform for GliumPlatfor WindowEvent::RedrawRequested => { let mut target = self.display.draw(); target.clear_color_and_depth((0.1, 0.1, 0.15, 1.0), 1.0); - let (scene_mut, debug_ui_buffer) = self.engine.scene_and_debug_ui_buffer_mut(); + let (scene, debug_ui_buffer) = ( + self.engine.current_scene(), + self.engine.get_debug_ui_buffer(), + ); let mut context = RenderingContext { - scene: scene_mut, + scene, target: &mut target, asset_manager: self.asset_manager.clone(), window: self.window.clone(), diff --git a/glium_platform/src/render/debug_ui.rs b/glium_platform/src/render/debug_ui.rs index be4ff0d..ac4a06e 100644 --- a/glium_platform/src/render/debug_ui.rs +++ b/glium_platform/src/render/debug_ui.rs @@ -41,7 +41,7 @@ impl RenderingSystem for ImguiBridge { self.rendered_this_frame = true; let ui = self.imgui.frame(); - ctx.debug_ui_buffer.borrow().write_buffer(&ui); + ctx.debug_ui_buffer.write_buffer(&ui); { let window = ctx.window.lock().unwrap(); diff --git a/glium_platform/src/system.rs b/glium_platform/src/system.rs index 3460bc3..51a292f 100644 --- a/glium_platform/src/system.rs +++ b/glium_platform/src/system.rs @@ -6,7 +6,7 @@ use indexmap::IndexMap; use glium::{Display, Frame}; use glium::glutin::surface::WindowSurface; use raidillon_assets::ModelManagerRef; -use raidillon_core::DebugUIBuffer; +use raidillon_core::{define_typemap, DebugUIBuffer}; use raidillon_core::scene::Scene; use glam::Vec3; @@ -15,7 +15,7 @@ pub struct RenderingContext<'a> { pub target: &'a mut Frame, pub window: Arc>, pub asset_manager: ModelManagerRef, - pub debug_ui_buffer: Rc>, + pub debug_ui_buffer: &'a DebugUIBuffer, pub env_light_dir: Vec3, } @@ -35,6 +35,8 @@ pub trait RenderingSystem { Self: Sized; } +// define_typemap!(RenderingSystemManager, RenderingSystem); + pub struct RenderingSystemManager { pub systems: IndexMap>, } From b86bbdd237706dfea4c9e5db182d23d83daab8ed Mon Sep 17 00:00:00 2001 From: reo Date: Thu, 16 Oct 2025 16:11:53 +0300 Subject: [PATCH 59/89] fix spacing --- game/src/main.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/game/src/main.rs b/game/src/main.rs index acedefd..4e0ee6e 100644 --- a/game/src/main.rs +++ b/game/src/main.rs @@ -65,8 +65,9 @@ impl System for RenderingTestSystem { } fn frame_update(&mut self, res: &mut EngineResources, scene: &mut Scene) { - let pctx = res.get::().unwrap().clone(); + let pctx = res.get::().unwrap(); let dbg_ui = scene.resources.get_mut::().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)); @@ -75,6 +76,7 @@ impl System for RenderingTestSystem { fn fixed_update(&mut self, res: &mut EngineResources, scene: &mut Scene) { let pctx = res.get::().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); }); From 1a48e58a1cfca6baea4cd60437abfca69fe0d6dd Mon Sep 17 00:00:00 2001 From: reo Date: Thu, 16 Oct 2025 16:12:18 +0300 Subject: [PATCH 60/89] Implement get_many. I believe the repeated code can be generated with procedural macros, but I don't need that right now. I'll do it if I ever end up needing this. Right now I need to start making the game itself more than anything. --- core/src/utils/typemap.rs | 436 +++++++++++++++++++++++++++++-- engine/src/systems/fps_camera.rs | 3 +- 2 files changed, 408 insertions(+), 31 deletions(-) diff --git a/core/src/utils/typemap.rs b/core/src/utils/typemap.rs index 88d3dc5..bd28a66 100644 --- a/core/src/utils/typemap.rs +++ b/core/src/utils/typemap.rs @@ -7,9 +7,7 @@ macro_rules! define_typemap { impl $name { pub fn new() -> Self { - Self { - map: std::collections::HashMap::new(), - } + Self { map: std::collections::HashMap::new() } } pub fn insert(&mut self, value: T) -> Option> @@ -17,49 +15,33 @@ macro_rules! define_typemap { T: std::any::Any + 'static + $($trait_bound)*, { let type_id = std::any::TypeId::of::(); - self.map - .insert(type_id, Box::new(value)) - .and_then(|boxed| boxed.downcast().ok()) + self.map.insert(type_id, Box::new(value)).and_then(|b| b.downcast().ok()) } pub fn get(&self) -> Option<&T> where T: std::any::Any + 'static + $($trait_bound)*, { - self.map - .get(&std::any::TypeId::of::()) - .and_then(|any| any.downcast_ref::()) + self.map.get(&std::any::TypeId::of::())?.downcast_ref::() } pub fn get_mut(&mut self) -> Option<&mut T> where T: std::any::Any + 'static + $($trait_bound)*, { - self.map - .get_mut(&std::any::TypeId::of::()) - .and_then(|any| any.downcast_mut::()) + self.map.get_mut(&std::any::TypeId::of::())?.downcast_mut::() } pub fn remove(&mut self) -> Option> where T: std::any::Any + 'static + $($trait_bound)*, { - self.map - .remove(&std::any::TypeId::of::()) - .and_then(|boxed| boxed.downcast().ok()) + self.map.remove(&std::any::TypeId::of::())?.downcast().ok() } - pub fn len(&self) -> usize { - self.map.len() - } - - pub fn is_empty(&self) -> bool { - self.map.is_empty() - } - - pub fn clear(&mut self) { - self.map.clear(); - } + pub fn len(&self) -> usize { self.map.len() } + pub fn is_empty(&self) -> bool { self.map.is_empty() } + pub fn clear(&mut self) { self.map.clear(); } pub fn contains(&self) -> bool where @@ -67,11 +49,407 @@ macro_rules! define_typemap { { self.map.contains_key(&std::any::TypeId::of::()) } + + // --- tuple-based multi-get API --- + pub fn get_many<'a, T>(&'a self) -> Option<::Output<'a>> + where + T: __tm_get::GetTuple, + { + ::get_from(&self.map) + } + + pub fn get_many_mut<'a, T>(&'a mut self) -> Option<::Output<'a>> + where + T: __tm_get::GetTupleMut, + { + ::get_from_mut(&mut self.map) + } } - impl Default for $name { - fn default() -> Self { - Self::new() + impl Default for $name { fn default() -> Self { Self::new() } } + + // Put helper traits/impls in a private module to avoid name clashes. + mod __tm_get { + use std::any::{Any, TypeId}; + use std::collections::HashMap; + + pub trait GetTuple { + type Output<'a>; + fn get_from<'a>(map: &'a HashMap>) -> Option>; + } + + pub trait GetTupleMut { + type Output<'a>; + fn get_from_mut<'a>(map: &'a mut HashMap>) -> Option>; + } + + // Manual implementations for arities 1..=8. + impl GetTuple for (A,) + where + A: Any + 'static, + { + type Output<'a> = (&'a A,); + fn get_from<'a>(map: &'a HashMap>) -> Option> { + let a = map.get(&TypeId::of::())?.downcast_ref::()?; + Some((a,)) + } + } + + impl GetTupleMut for (A,) + where + A: Any + 'static, + { + type Output<'a> = (&'a mut A,); + fn get_from_mut<'a>(map: &'a mut HashMap>) -> Option> { + let ptr_a = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; + unsafe { + let a = (&mut *ptr_a).downcast_mut::()?; + Some((a,)) + } + } + } + + impl GetTuple for (A, B) + where + A: Any + 'static, + B: Any + 'static, + { + type Output<'a> = (&'a A, &'a B); + fn get_from<'a>(map: &'a HashMap>) -> Option> { + let ids = [TypeId::of::(), TypeId::of::()]; + if ids[0] == ids[1] { return None; } + let a = map.get(&TypeId::of::())?.downcast_ref::()?; + let b = map.get(&TypeId::of::())?.downcast_ref::()?; + Some((a, b)) + } + } + + impl GetTupleMut for (A, B) + where + A: Any + 'static, + B: Any + 'static, + { + type Output<'a> = (&'a mut A, &'a mut B); + fn get_from_mut<'a>(map: &'a mut HashMap>) -> Option> { + let ids = [TypeId::of::(), TypeId::of::()]; + if ids[0] == ids[1] { return None; } + let ptr_a = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; + let ptr_b = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; + unsafe { + let a = (&mut *ptr_a).downcast_mut::()?; + let b = (&mut *ptr_b).downcast_mut::()?; + Some((a, b)) + } + } + } + + impl GetTuple for (A, B, C) + where + A: Any + 'static, + B: Any + 'static, + C: Any + 'static, + { + type Output<'a> = (&'a A, &'a B, &'a C); + fn get_from<'a>(map: &'a HashMap>) -> Option> { + let ids = [TypeId::of::(), TypeId::of::(), TypeId::of::()]; + if ids[0] == ids[1] || ids[0] == ids[2] || ids[1] == ids[2] { return None; } + let a = map.get(&TypeId::of::())?.downcast_ref::()?; + let b = map.get(&TypeId::of::())?.downcast_ref::()?; + let c = map.get(&TypeId::of::())?.downcast_ref::()?; + Some((a, b, c)) + } + } + + impl GetTupleMut for (A, B, C) + where + A: Any + 'static, + B: Any + 'static, + C: Any + 'static, + { + type Output<'a> = (&'a mut A, &'a mut B, &'a mut C); + fn get_from_mut<'a>(map: &'a mut HashMap>) -> Option> { + let ids = [TypeId::of::(), TypeId::of::(), TypeId::of::()]; + if ids[0] == ids[1] || ids[0] == ids[2] || ids[1] == ids[2] { return None; } + let ptr_a = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; + let ptr_b = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; + let ptr_c = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; + unsafe { + let a = (&mut *ptr_a).downcast_mut::()?; + let b = (&mut *ptr_b).downcast_mut::()?; + let c = (&mut *ptr_c).downcast_mut::()?; + Some((a, b, c)) + } + } + } + + impl GetTuple for (A, B, C, D) + where + A: Any + 'static, + B: Any + 'static, + C: Any + 'static, + D: Any + 'static, + { + type Output<'a> = (&'a A, &'a B, &'a C, &'a D); + fn get_from<'a>(map: &'a HashMap>) -> Option> { + let ids = [TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::()]; + for i in 0..ids.len() { for j in (i+1)..ids.len() { if ids[i] == ids[j] { return None; } } } + let a = map.get(&TypeId::of::())?.downcast_ref::()?; + let b = map.get(&TypeId::of::())?.downcast_ref::()?; + let c = map.get(&TypeId::of::())?.downcast_ref::()?; + let d = map.get(&TypeId::of::())?.downcast_ref::()?; + Some((a, b, c, d)) + } + } + + impl GetTupleMut for (A, B, C, D) + where + A: Any + 'static, + B: Any + 'static, + C: Any + 'static, + D: Any + 'static, + { + type Output<'a> = (&'a mut A, &'a mut B, &'a mut C, &'a mut D); + fn get_from_mut<'a>(map: &'a mut HashMap>) -> Option> { + let ids = [TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::()]; + for i in 0..ids.len() { for j in (i+1)..ids.len() { if ids[i] == ids[j] { return None; } } } + let ptr_a = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; + let ptr_b = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; + let ptr_c = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; + let ptr_d = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; + unsafe { + let a = (&mut *ptr_a).downcast_mut::()?; + let b = (&mut *ptr_b).downcast_mut::()?; + let c = (&mut *ptr_c).downcast_mut::()?; + let d = (&mut *ptr_d).downcast_mut::()?; + Some((a, b, c, d)) + } + } + } + + impl GetTuple for (A, B, C, D, E) + where + A: Any + 'static, + B: Any + 'static, + C: Any + 'static, + D: Any + 'static, + E: Any + 'static, + { + type Output<'a> = (&'a A, &'a B, &'a C, &'a D, &'a E); + fn get_from<'a>(map: &'a HashMap>) -> Option> { + let ids = [TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::()]; + for i in 0..ids.len() { for j in (i+1)..ids.len() { if ids[i] == ids[j] { return None; } } } + let a = map.get(&TypeId::of::())?.downcast_ref::()?; + let b = map.get(&TypeId::of::())?.downcast_ref::()?; + let c = map.get(&TypeId::of::())?.downcast_ref::()?; + let d = map.get(&TypeId::of::())?.downcast_ref::()?; + let e = map.get(&TypeId::of::())?.downcast_ref::()?; + Some((a, b, c, d, e)) + } + } + + impl GetTupleMut for (A, B, C, D, E) + where + A: Any + 'static, + B: Any + 'static, + C: Any + 'static, + D: Any + 'static, + E: Any + 'static, + { + type Output<'a> = (&'a mut A, &'a mut B, &'a mut C, &'a mut D, &'a mut E); + fn get_from_mut<'a>(map: &'a mut HashMap>) -> Option> { + let ids = [TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::()]; + for i in 0..ids.len() { for j in (i+1)..ids.len() { if ids[i] == ids[j] { return None; } } } + let ptr_a = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; + let ptr_b = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; + let ptr_c = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; + let ptr_d = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; + let ptr_e = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; + unsafe { + let a = (&mut *ptr_a).downcast_mut::()?; + let b = (&mut *ptr_b).downcast_mut::()?; + let c = (&mut *ptr_c).downcast_mut::()?; + let d = (&mut *ptr_d).downcast_mut::()?; + let e = (&mut *ptr_e).downcast_mut::()?; + Some((a, b, c, d, e)) + } + } + } + + impl GetTuple for (A, B, C, D, E, F) + where + A: Any + 'static, + B: Any + 'static, + C: Any + 'static, + D: Any + 'static, + E: Any + 'static, + F: Any + 'static, + { + type Output<'a> = (&'a A, &'a B, &'a C, &'a D, &'a E, &'a F); + fn get_from<'a>(map: &'a HashMap>) -> Option> { + let ids = [TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::()]; + for i in 0..ids.len() { for j in (i+1)..ids.len() { if ids[i] == ids[j] { return None; } } } + let a = map.get(&TypeId::of::())?.downcast_ref::()?; + let b = map.get(&TypeId::of::())?.downcast_ref::()?; + let c = map.get(&TypeId::of::())?.downcast_ref::()?; + let d = map.get(&TypeId::of::())?.downcast_ref::()?; + let e = map.get(&TypeId::of::())?.downcast_ref::()?; + let f = map.get(&TypeId::of::())?.downcast_ref::()?; + Some((a, b, c, d, e, f)) + } + } + + impl GetTupleMut for (A, B, C, D, E, F) + where + A: Any + 'static, + B: Any + 'static, + C: Any + 'static, + D: Any + 'static, + E: Any + 'static, + F: Any + 'static, + { + type Output<'a> = (&'a mut A, &'a mut B, &'a mut C, &'a mut D, &'a mut E, &'a mut F); + fn get_from_mut<'a>(map: &'a mut HashMap>) -> Option> { + let ids = [TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::()]; + for i in 0..ids.len() { for j in (i+1)..ids.len() { if ids[i] == ids[j] { return None; } } } + let ptr_a = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; + let ptr_b = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; + let ptr_c = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; + let ptr_d = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; + let ptr_e = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; + let ptr_f = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; + unsafe { + let a = (&mut *ptr_a).downcast_mut::()?; + let b = (&mut *ptr_b).downcast_mut::()?; + let c = (&mut *ptr_c).downcast_mut::()?; + let d = (&mut *ptr_d).downcast_mut::()?; + let e = (&mut *ptr_e).downcast_mut::()?; + let f = (&mut *ptr_f).downcast_mut::()?; + Some((a, b, c, d, e, f)) + } + } + } + + impl GetTuple for (A, B, C, D, E, F, G) + where + A: Any + 'static, + B: Any + 'static, + C: Any + 'static, + D: Any + 'static, + E: Any + 'static, + F: Any + 'static, + G: Any + 'static, + { + type Output<'a> = (&'a A, &'a B, &'a C, &'a D, &'a E, &'a F, &'a G); + fn get_from<'a>(map: &'a HashMap>) -> Option> { + let ids = [TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::()]; + for i in 0..ids.len() { for j in (i+1)..ids.len() { if ids[i] == ids[j] { return None; } } } + let a = map.get(&TypeId::of::())?.downcast_ref::()?; + let b = map.get(&TypeId::of::())?.downcast_ref::()?; + let c = map.get(&TypeId::of::())?.downcast_ref::()?; + let d = map.get(&TypeId::of::())?.downcast_ref::()?; + let e = map.get(&TypeId::of::())?.downcast_ref::()?; + let f = map.get(&TypeId::of::())?.downcast_ref::()?; + let g = map.get(&TypeId::of::())?.downcast_ref::()?; + Some((a, b, c, d, e, f, g)) + } + } + + impl GetTupleMut for (A, B, C, D, E, F, G) + where + A: Any + 'static, + B: Any + 'static, + C: Any + 'static, + D: Any + 'static, + E: Any + 'static, + F: Any + 'static, + G: Any + 'static, + { + type Output<'a> = (&'a mut A, &'a mut B, &'a mut C, &'a mut D, &'a mut E, &'a mut F, &'a mut G); + fn get_from_mut<'a>(map: &'a mut HashMap>) -> Option> { + let ids = [TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::()]; + for i in 0..ids.len() { for j in (i+1)..ids.len() { if ids[i] == ids[j] { return None; } } } + let ptr_a = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; + let ptr_b = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; + let ptr_c = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; + let ptr_d = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; + let ptr_e = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; + let ptr_f = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; + let ptr_g = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; + unsafe { + let a = (&mut *ptr_a).downcast_mut::()?; + let b = (&mut *ptr_b).downcast_mut::()?; + let c = (&mut *ptr_c).downcast_mut::()?; + let d = (&mut *ptr_d).downcast_mut::()?; + let e = (&mut *ptr_e).downcast_mut::()?; + let f = (&mut *ptr_f).downcast_mut::()?; + let g = (&mut *ptr_g).downcast_mut::()?; + Some((a, b, c, d, e, f, g)) + } + } + } + + impl GetTuple for (A, B, C, D, E, F, G, H) + where + A: Any + 'static, + B: Any + 'static, + C: Any + 'static, + D: Any + 'static, + E: Any + 'static, + F: Any + 'static, + G: Any + 'static, + H: Any + 'static, + { + type Output<'a> = (&'a A, &'a B, &'a C, &'a D, &'a E, &'a F, &'a G, &'a H); + fn get_from<'a>(map: &'a HashMap>) -> Option> { + let ids = [TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::()]; + for i in 0..ids.len() { for j in (i+1)..ids.len() { if ids[i] == ids[j] { return None; } } } + let a = map.get(&TypeId::of::())?.downcast_ref::()?; + let b = map.get(&TypeId::of::())?.downcast_ref::()?; + let c = map.get(&TypeId::of::())?.downcast_ref::()?; + let d = map.get(&TypeId::of::())?.downcast_ref::()?; + let e = map.get(&TypeId::of::())?.downcast_ref::()?; + let f = map.get(&TypeId::of::())?.downcast_ref::()?; + let g = map.get(&TypeId::of::())?.downcast_ref::()?; + let h = map.get(&TypeId::of::())?.downcast_ref::()?; + Some((a, b, c, d, e, f, g, h)) + } + } + + impl GetTupleMut for (A, B, C, D, E, F, G, H) + where + A: Any + 'static, + B: Any + 'static, + C: Any + 'static, + D: Any + 'static, + E: Any + 'static, + F: Any + 'static, + G: Any + 'static, + H: Any + 'static, + { + type Output<'a> = (&'a mut A, &'a mut B, &'a mut C, &'a mut D, &'a mut E, &'a mut F, &'a mut G, &'a mut H); + fn get_from_mut<'a>(map: &'a mut HashMap>) -> Option> { + let ids = [TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::()]; + for i in 0..ids.len() { for j in (i+1)..ids.len() { if ids[i] == ids[j] { return None; } } } + let ptr_a = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; + let ptr_b = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; + let ptr_c = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; + let ptr_d = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; + let ptr_e = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; + let ptr_f = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; + let ptr_g = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; + let ptr_h = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; + unsafe { + let a = (&mut *ptr_a).downcast_mut::()?; + let b = (&mut *ptr_b).downcast_mut::()?; + let c = (&mut *ptr_c).downcast_mut::()?; + let d = (&mut *ptr_d).downcast_mut::()?; + let e = (&mut *ptr_e).downcast_mut::()?; + let f = (&mut *ptr_f).downcast_mut::()?; + let g = (&mut *ptr_g).downcast_mut::()?; + let h = (&mut *ptr_h).downcast_mut::()?; + Some((a, b, c, d, e, f, g, h)) + } + } } } }; diff --git a/engine/src/systems/fps_camera.rs b/engine/src/systems/fps_camera.rs index 6bd99f7..0d98577 100644 --- a/engine/src/systems/fps_camera.rs +++ b/engine/src/systems/fps_camera.rs @@ -92,8 +92,7 @@ impl System for FPSDebugCameraSystem { } fn frame_update(&mut self, res: &mut EngineResources, scene: &mut Scene) { - let pctx = res.get::().unwrap(); - let input = res.get::().unwrap(); + let (pctx, input) = res.get_many::<(PlatformContext, InputState)>().unwrap(); if self.mouse_enabled { self.yaw += self.mouse_delta.0 as f32 * self.sensitivity; From 54967067bdf034e05280c59147ec297071b902d2 Mon Sep 17 00:00:00 2001 From: reo Date: Thu, 16 Oct 2025 17:01:23 +0300 Subject: [PATCH 61/89] Enable InputState event handler in engine --- engine/src/engine.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/engine/src/engine.rs b/engine/src/engine.rs index 7c366dc..a5c8a1d 100644 --- a/engine/src/engine.rs +++ b/engine/src/engine.rs @@ -66,7 +66,7 @@ impl EngineTrait for Engine { } fn handle_event(&mut self, platform_context: PlatformContext) { - // self.input_state.borrow_mut().handle_event(&platform_context.current_event); + self.resources.get_mut::().unwrap().handle_event(&platform_context.current_event); self.resources.insert(platform_context); for system in self.system_manager.systems.values_mut() { system.handle_event(&mut self.resources, &mut self.scene_manager.current_mut()); From 5f3da6ab99b7a3e8e86a440e212a1ee11910726e Mon Sep 17 00:00:00 2001 From: reo Date: Fri, 17 Oct 2025 23:18:18 +0300 Subject: [PATCH 62/89] Add FPS counter to the debug UI --- game/src/main.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/game/src/main.rs b/game/src/main.rs index 4e0ee6e..ad230cf 100644 --- a/game/src/main.rs +++ b/game/src/main.rs @@ -71,6 +71,7 @@ impl System for RenderingTestSystem { 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()); } From 8b5a6167ebfd06c345edb13db62cfea95ba4a9cf Mon Sep 17 00:00:00 2001 From: reo Date: Sun, 19 Oct 2025 17:40:51 +0300 Subject: [PATCH 63/89] Physics Support - NEW CRATE: raidillon_physics. - Added new models to be able to test the physics support. - Added a new system "PhysicsSystem" to apply physics calculations to the ECS world. - NEW COMPONENT: RigidBodyComponent --- Cargo.lock | 521 +++++++++++++++++++++++++++++++++++- Cargo.toml | 1 + assets/models/plane.glb | 3 + assets/models/sphere.glb | 3 + ecs/Cargo.toml | 1 + ecs/src/components.rs | 3 + game/Cargo.toml | 2 + game/src/main.rs | 75 +++--- game/src/systems/mod.rs | 3 + game/src/systems/physics.rs | 34 +++ physics/Cargo.toml | 9 + physics/src/lib.rs | 3 + physics/src/physics.rs | 82 ++++++ 13 files changed, 697 insertions(+), 43 deletions(-) create mode 100644 assets/models/plane.glb create mode 100644 assets/models/sphere.glb create mode 100644 game/src/systems/mod.rs create mode 100644 game/src/systems/physics.rs create mode 100644 physics/Cargo.toml create mode 100644 physics/src/lib.rs create mode 100644 physics/src/physics.rs diff --git a/Cargo.lock b/Cargo.lock index e1b6adb..525e6ad 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -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,15 +1785,16 @@ 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", @@ -1457,13 +1807,15 @@ dependencies = [ name = "raidillon_game" version = "0.1.0" dependencies = [ - "glam", + "glam 0.30.8", "raidillon_assets", "raidillon_core", "raidillon_ecs", "raidillon_engine", "raidillon_glium", + "raidillon_physics", "raidillon_platform", + "rapier3d", "winit", ] @@ -1473,7 +1825,7 @@ version = "0.1.0" dependencies = [ "anyhow", "exr", - "glam", + "glam 0.30.8", "glium", "gltf", "image", @@ -1489,22 +1841,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 +1925,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 +1992,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 +2073,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 +2118,7 @@ dependencies = [ "log", "memmap2", "rustix 0.38.44", - "thiserror", + "thiserror 1.0.69", "wayland-backend", "wayland-client", "wayland-csd-frame", @@ -1701,12 +2138,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 +2191,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 +2214,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 +2289,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 +2416,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 +2538,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" diff --git a/Cargo.toml b/Cargo.toml index 23332d0..dd544ab 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,4 +7,5 @@ members = [ "game", "ecs", "engine", + "physics", ] diff --git a/assets/models/plane.glb b/assets/models/plane.glb new file mode 100644 index 0000000..e755152 --- /dev/null +++ b/assets/models/plane.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b54f00f327a5edc76c03f83d4efa2a4400215d7ca9c961b38537e7f836bca710 +size 1240 diff --git a/assets/models/sphere.glb b/assets/models/sphere.glb new file mode 100644 index 0000000..ea99045 --- /dev/null +++ b/assets/models/sphere.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:78583ec562098f7fa4eaf95c6e21b7d1ced53416eb4c71351e246d53f93aa0a3 +size 24744 diff --git a/ecs/Cargo.toml b/ecs/Cargo.toml index 0e1efb5..a47173d 100644 --- a/ecs/Cargo.toml +++ b/ecs/Cargo.toml @@ -6,3 +6,4 @@ edition = "2024" [dependencies] glam = "0.30.5" raidillon_assets = { path = "../asset" } +rapier3d = "0.30.1" diff --git a/ecs/src/components.rs b/ecs/src/components.rs index 758f0f4..fa30cc2 100644 --- a/ecs/src/components.rs +++ b/ecs/src/components.rs @@ -15,3 +15,6 @@ impl Transform { } pub struct ModelHandle(pub ModelID); + +#[derive(Copy, Clone)] +pub struct RigidBodyComponent(pub rapier3d::dynamics::RigidBodyHandle); diff --git a/game/Cargo.toml b/game/Cargo.toml index 484e434..9bb72c4 100644 --- a/game/Cargo.toml +++ b/game/Cargo.toml @@ -13,6 +13,8 @@ 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" diff --git a/game/src/main.rs b/game/src/main.rs index ad230cf..8ddce6a 100644 --- a/game/src/main.rs +++ b/game/src/main.rs @@ -1,11 +1,14 @@ +mod systems; use std::fmt::format; use glam::{Quat, Vec3}; +use rapier3d::dynamics::RigidBodyType; +use rapier3d::prelude::ColliderBuilder; use raidillon_engine::{Engine, system::System, EngineResources}; 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::{ModelHandle, RigidBodyComponent}; use raidillon_ecs::Transform; use raidillon_core::scene::Scene; #[cfg(feature = "glium")] @@ -15,9 +18,11 @@ use winit::event::DeviceEvent::MouseMotion; use winit::keyboard::{KeyCode, PhysicalKey}; use raidillon_core::DebugUIBuffer; use raidillon_engine::systems::fps_camera::FPSDebugCameraSystem; +use raidillon_physics::Physics; +use crate::systems::PhysicsSystem; -const TEST_GLTF: &str = "pink-monkey.gltf"; - +const TEST_GLTF: &str = "sphere.glb"; +const PLANE_GLTF: &str = "plane.glb"; const MAIN_SCENE_ID: &str = "main_scene"; #[derive(Default)] @@ -40,28 +45,45 @@ impl System for UpdateAspectRatioSystem { } #[derive(Default)] -struct RenderingTestSystem { - rotation_speed: std::rc::Rc>, -} +struct RenderingTestSystem; impl System for RenderingTestSystem { fn load_world(&mut self, res: &mut EngineResources, scene: &mut Scene) { - let pctx = res.get::().unwrap(); + let pctx = res.get::().expect("PlatformContext missing").clone(); + let physics = res.get_mut::().expect("Physics missing"); - self.rotation_speed = std::rc::Rc::new(std::cell::RefCell::new(5.0)); - - 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), - )); + // 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).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), + )); + } } fn frame_update(&mut self, res: &mut EngineResources, scene: &mut Scene) { @@ -72,22 +94,13 @@ impl System for RenderingTestSystem { 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()); } - - fn fixed_update(&mut self, res: &mut EngineResources, scene: &mut Scene) { - let pctx = res.get::().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::(); engine.system_manager.add::(); engine.system_manager.add::(); engine.system_manager.add::(); diff --git a/game/src/systems/mod.rs b/game/src/systems/mod.rs new file mode 100644 index 0000000..0ab4645 --- /dev/null +++ b/game/src/systems/mod.rs @@ -0,0 +1,3 @@ +mod physics; + +pub use physics::PhysicsSystem; diff --git a/game/src/systems/physics.rs b/game/src/systems/physics.rs new file mode 100644 index 0000000..c5d4807 --- /dev/null +++ b/game/src/systems/physics.rs @@ -0,0 +1,34 @@ +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; + +#[derive(Default)] +pub struct PhysicsSystem; + +impl System for PhysicsSystem { + fn load_world(&mut self, res: &mut EngineResources, scene: &mut Scene) { + let p = Physics::default(); + res.insert(p); + } + + fn fixed_update(&mut self, res: &mut EngineResources, scene: &mut Scene) { + let pctx = res.get::().expect("PlatformContext missing").clone(); + let physics = res.get_mut::().expect("Physics missing"); + physics.step(pctx.time_ctx.fixed_dt); + + 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; + } + } + } +} diff --git a/physics/Cargo.toml b/physics/Cargo.toml new file mode 100644 index 0000000..dc34e98 --- /dev/null +++ b/physics/Cargo.toml @@ -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" \ No newline at end of file diff --git a/physics/src/lib.rs b/physics/src/lib.rs new file mode 100644 index 0000000..a5dafc6 --- /dev/null +++ b/physics/src/lib.rs @@ -0,0 +1,3 @@ +mod physics; + +pub use crate::physics::Physics; diff --git a/physics/src/physics.rs b/physics/src/physics.rs new file mode 100644 index 0000000..009984c --- /dev/null +++ b/physics/src/physics.rs @@ -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 { + rigid_body_set: RigidBodySet, + collider_set: ColliderSet, + physics_pipeline: PhysicsPipeline, + island_manager: IslandManager, + broad_phase: DefaultBroadPhase, + narrow_phase: NarrowPhase, + impulse_joint_set: ImpulseJointSet, + multibody_joint_set: MultibodyJointSet, + ccd_solver: CCDSolver, + gravity: Vector, + 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) -> Vec3 { + Vec3::new(v.x, v.y, v.z) + } + + pub fn rapier_rotation_to_glam(r: &UnitQuaternion) -> Quat { + Quat::from_xyzw(r.i, r.j, r.k, r.w) + } +} From 713d865dd7799c59c2a5ec018258ce00d260fd1d Mon Sep 17 00:00:00 2001 From: reo Date: Sun, 26 Oct 2025 18:29:59 +0300 Subject: [PATCH 64/89] MASSIVE Kinematic Character Controller Update - NEW kinematic character controller powered by rapier3d at kinematic_character_controller.rs - NEW camera modes. The ability to switch between the free debug camera and new character controller. - NEW keybinds system to support the camera mode swap --- Cargo.lock | 2 + ecs/src/components.rs | 10 + engine/Cargo.toml | 1 + engine/src/lib.rs | 1 + engine/src/systems/fps_camera.rs | 29 +-- game/Cargo.toml | 1 + game/src/main.rs | 35 ++- game/src/systems/keybinds.rs | 52 +++++ .../systems/kinematic_character_controller.rs | 200 ++++++++++++++++++ game/src/systems/mod.rs | 4 + game/src/systems/physics.rs | 6 +- physics/src/physics.rs | 8 +- 12 files changed, 323 insertions(+), 26 deletions(-) create mode 100644 game/src/systems/keybinds.rs create mode 100644 game/src/systems/kinematic_character_controller.rs diff --git a/Cargo.lock b/Cargo.lock index 525e6ad..91f50f1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1799,6 +1799,7 @@ dependencies = [ "indexmap", "raidillon_assets", "raidillon_core", + "raidillon_ecs", "raidillon_platform", "winit", ] @@ -1808,6 +1809,7 @@ name = "raidillon_game" version = "0.1.0" dependencies = [ "glam 0.30.8", + "hecs", "raidillon_assets", "raidillon_core", "raidillon_ecs", diff --git a/ecs/src/components.rs b/ecs/src/components.rs index fa30cc2..3c20ec7 100644 --- a/ecs/src/components.rs +++ b/ecs/src/components.rs @@ -18,3 +18,13 @@ 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, +} diff --git a/engine/Cargo.toml b/engine/Cargo.toml index 98202e4..79a2de9 100644 --- a/engine/Cargo.toml +++ b/engine/Cargo.toml @@ -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" diff --git a/engine/src/lib.rs b/engine/src/lib.rs index 9a87556..a7ad724 100644 --- a/engine/src/lib.rs +++ b/engine/src/lib.rs @@ -6,3 +6,4 @@ mod resources; pub use crate::engine::Engine; pub use crate::resources::EngineResources; +pub use input::InputState; diff --git a/engine/src/systems/fps_camera.rs b/engine/src/systems/fps_camera.rs index 0d98577..5ff9cc7 100644 --- a/engine/src/systems/fps_camera.rs +++ b/engine/src/systems/fps_camera.rs @@ -9,6 +9,7 @@ use raidillon_platform::{Camera, PlatformContext}; use crate::input::InputState; use crate::resources::EngineResources; use raidillon_core::scene::Scene; +use raidillon_ecs::components::CameraMode; pub struct FPSDebugCameraSystem { mouse_delta: (f64, f64), @@ -35,20 +36,10 @@ impl Default for FPSDebugCameraSystem { } impl System for FPSDebugCameraSystem { - fn load_world(&mut self, res: &mut EngineResources, scene: &mut Scene) { - let pctx = res.get::().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::().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 + } } diff --git a/game/Cargo.toml b/game/Cargo.toml index 9bb72c4..9579d22 100644 --- a/game/Cargo.toml +++ b/game/Cargo.toml @@ -18,3 +18,4 @@ raidillon_glium = { path = "../glium_platform", optional = true } glam = "0.30.5" winit = "0.30.12" rapier3d = "0.30.1" +hecs = "0.10.5" diff --git a/game/src/main.rs b/game/src/main.rs index 8ddce6a..a5a3d9c 100644 --- a/game/src/main.rs +++ b/game/src/main.rs @@ -1,14 +1,14 @@ mod systems; use std::fmt::format; use glam::{Quat, Vec3}; -use rapier3d::dynamics::RigidBodyType; +use rapier3d::dynamics::{CoefficientCombineRule, RigidBodyType}; use rapier3d::prelude::ColliderBuilder; -use raidillon_engine::{Engine, system::System, EngineResources}; +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, RigidBodyComponent}; +use raidillon_ecs::components::{CameraMode, CharacterBodyComponent, ModelHandle, RigidBodyComponent}; use raidillon_ecs::Transform; use raidillon_core::scene::Scene; #[cfg(feature = "glium")] @@ -18,8 +18,9 @@ use winit::event::DeviceEvent::MouseMotion; use winit::keyboard::{KeyCode, PhysicalKey}; use raidillon_core::DebugUIBuffer; use raidillon_engine::systems::fps_camera::FPSDebugCameraSystem; +use raidillon_glium::RenderingSystem; use raidillon_physics::Physics; -use crate::systems::PhysicsSystem; +use crate::systems::{KeybindsSystem, KinematicCharacterController, PhysicsSystem}; const TEST_GLTF: &str = "sphere.glb"; const PLANE_GLTF: &str = "plane.glb"; @@ -50,7 +51,7 @@ struct RenderingTestSystem; impl System for RenderingTestSystem { fn load_world(&mut self, res: &mut EngineResources, scene: &mut Scene) { let pctx = res.get::().expect("PlatformContext missing").clone(); - let physics = res.get_mut::().expect("Physics missing"); + let physics = scene.resources.get_mut::().expect("Physics missing"); // Spawn Sphere { @@ -59,7 +60,10 @@ impl System for RenderingTestSystem { rotation: Quat::IDENTITY, scale: Vec3::new(1.0, 1.0, 1.0), }; - let collider = ColliderBuilder::ball(1.0).build(); + 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(( @@ -84,16 +88,32 @@ impl System for RenderingTestSystem { RigidBodyComponent(rb_handle), )); } + + 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::().unwrap(); + let input = res.get::().unwrap(); let dbg_ui = scene.resources.get_mut::().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)); + + for (_ent, (tr, ch_component)) in scene.world.query::<(&Transform, &CharacterBodyComponent)>().iter() { + dbg_ui.text(format!("Character POS: {}", tr.translation)); + } } } @@ -101,7 +121,8 @@ fn main() { let mut engine = Engine::new(); // Define systems engine.system_manager.add::(); - engine.system_manager.add::(); + engine.system_manager.add::(); + engine.system_manager.add::(); engine.system_manager.add::(); engine.system_manager.add::(); // engine.system_manager.add::(); diff --git a/game/src/systems/keybinds.rs b/game/src/systems/keybinds.rs new file mode 100644 index 0000000..6bc3e70 --- /dev/null +++ b/game/src/systems/keybinds.rs @@ -0,0 +1,52 @@ +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; + +#[derive(Default)] +pub struct KeybindsSystem; + +impl System for KeybindsSystem { + fn fixed_update(&mut self, res: &mut EngineResources, scene: &mut Scene) { + let input = res.get::().unwrap(); + + if input.key_held(KeyCode::F5) { + self.toggle_camera_mode(scene); + } + } + + fn frame_update(&mut self, res: &mut EngineResources, scene: &mut Scene) { + let dbg_ui = scene.resources.get_mut::().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; + } + } + } +} diff --git a/game/src/systems/kinematic_character_controller.rs b/game/src/systems/kinematic_character_controller.rs new file mode 100644 index 0000000..4608e67 --- /dev/null +++ b/game/src/systems/kinematic_character_controller.rs @@ -0,0 +1,200 @@ +use glam::{Quat, Vec3}; +use hecs::Entity; +use rapier3d::prelude::{nalgebra, ColliderBuilder, QueryFilter, QueryPipeline, 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::math::Isometry; +use rapier3d::na::{Isometry3, Vector3}; +use winit::event::DeviceEvent::MouseMotion; +use winit::event::{ElementState, Event, MouseButton, WindowEvent}; +use winit::keyboard::KeyCode; +use winit::window::CursorGrabMode; +use raidillon_core::DebugUIBuffer; +use raidillon_ecs::components::{CameraMode, CharacterBodyComponent}; +use raidillon_ecs::Transform; +use raidillon_engine::systems::fps_camera::FPSDebugCameraSystem; +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, + 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::().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::().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::().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 + } +} diff --git a/game/src/systems/mod.rs b/game/src/systems/mod.rs index 0ab4645..f975aff 100644 --- a/game/src/systems/mod.rs +++ b/game/src/systems/mod.rs @@ -1,3 +1,7 @@ mod physics; +mod kinematic_character_controller; +mod keybinds; pub use physics::PhysicsSystem; +pub use kinematic_character_controller::KinematicCharacterController; +pub use keybinds::KeybindsSystem; diff --git a/game/src/systems/physics.rs b/game/src/systems/physics.rs index c5d4807..a77c75c 100644 --- a/game/src/systems/physics.rs +++ b/game/src/systems/physics.rs @@ -6,20 +6,22 @@ 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(); - res.insert(p); + scene.resources.insert(p); } fn fixed_update(&mut self, res: &mut EngineResources, scene: &mut Scene) { let pctx = res.get::().expect("PlatformContext missing").clone(); - let physics = res.get_mut::().expect("Physics missing"); + let physics = scene.resources.get_mut::().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) { diff --git a/physics/src/physics.rs b/physics/src/physics.rs index 009984c..5eff699 100644 --- a/physics/src/physics.rs +++ b/physics/src/physics.rs @@ -5,12 +5,12 @@ use raidillon_ecs::Transform; /// Tiny wrapper around rapier3d. pub struct Physics { - rigid_body_set: RigidBodySet, - collider_set: ColliderSet, + pub rigid_body_set: RigidBodySet, + pub collider_set: ColliderSet, physics_pipeline: PhysicsPipeline, island_manager: IslandManager, - broad_phase: DefaultBroadPhase, - narrow_phase: NarrowPhase, + pub broad_phase: DefaultBroadPhase, + pub narrow_phase: NarrowPhase, impulse_joint_set: ImpulseJointSet, multibody_joint_set: MultibodyJointSet, ccd_solver: CCDSolver, From 96a59b68fa23ddbf927e3d5540f7b2fe8efb8b22 Mon Sep 17 00:00:00 2001 From: reo Date: Wed, 29 Oct 2025 21:35:55 +0300 Subject: [PATCH 65/89] Move debug_camera to the game crate, activate FPSDebugCameraSystem --- engine/src/systems/mod.rs | 1 - game/src/main.rs | 3 ++- .../fps_camera.rs => game/src/systems/debug_camera.rs | 8 ++++---- game/src/systems/mod.rs | 1 + 4 files changed, 7 insertions(+), 6 deletions(-) rename engine/src/systems/fps_camera.rs => game/src/systems/debug_camera.rs (96%) diff --git a/engine/src/systems/mod.rs b/engine/src/systems/mod.rs index 8489571..e69de29 100644 --- a/engine/src/systems/mod.rs +++ b/engine/src/systems/mod.rs @@ -1 +0,0 @@ -pub mod fps_camera; diff --git a/game/src/main.rs b/game/src/main.rs index a5a3d9c..99eb0e2 100644 --- a/game/src/main.rs +++ b/game/src/main.rs @@ -17,7 +17,7 @@ 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; +use systems::debug_camera::FPSDebugCameraSystem; use raidillon_glium::RenderingSystem; use raidillon_physics::Physics; use crate::systems::{KeybindsSystem, KinematicCharacterController, PhysicsSystem}; @@ -123,6 +123,7 @@ fn main() { engine.system_manager.add::(); engine.system_manager.add::(); engine.system_manager.add::(); + engine.system_manager.add::(); engine.system_manager.add::(); engine.system_manager.add::(); // engine.system_manager.add::(); diff --git a/engine/src/systems/fps_camera.rs b/game/src/systems/debug_camera.rs similarity index 96% rename from engine/src/systems/fps_camera.rs rename to game/src/systems/debug_camera.rs index 5ff9cc7..13cb971 100644 --- a/engine/src/systems/fps_camera.rs +++ b/game/src/systems/debug_camera.rs @@ -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,8 +6,8 @@ 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; @@ -29,7 +29,7 @@ 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, } } diff --git a/game/src/systems/mod.rs b/game/src/systems/mod.rs index f975aff..2a387b1 100644 --- a/game/src/systems/mod.rs +++ b/game/src/systems/mod.rs @@ -1,6 +1,7 @@ mod physics; mod kinematic_character_controller; mod keybinds; +pub mod debug_camera; pub use physics::PhysicsSystem; pub use kinematic_character_controller::KinematicCharacterController; From ded85dcd72c9e70adf6301249807215efb02122c Mon Sep 17 00:00:00 2001 From: reo Date: Wed, 29 Oct 2025 21:36:38 +0300 Subject: [PATCH 66/89] Optimize imports of kinematic_character_controller.rs --- game/src/systems/kinematic_character_controller.rs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/game/src/systems/kinematic_character_controller.rs b/game/src/systems/kinematic_character_controller.rs index 4608e67..e3fc099 100644 --- a/game/src/systems/kinematic_character_controller.rs +++ b/game/src/systems/kinematic_character_controller.rs @@ -1,21 +1,16 @@ use glam::{Quat, Vec3}; -use hecs::Entity; -use rapier3d::prelude::{nalgebra, ColliderBuilder, QueryFilter, QueryPipeline, RigidBodyBuilder}; +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::math::Isometry; use rapier3d::na::{Isometry3, Vector3}; use winit::event::DeviceEvent::MouseMotion; -use winit::event::{ElementState, Event, MouseButton, WindowEvent}; +use winit::event::Event; use winit::keyboard::KeyCode; -use winit::window::CursorGrabMode; -use raidillon_core::DebugUIBuffer; use raidillon_ecs::components::{CameraMode, CharacterBodyComponent}; use raidillon_ecs::Transform; -use raidillon_engine::systems::fps_camera::FPSDebugCameraSystem; use raidillon_physics::Physics; use raidillon_platform::{Camera, PlatformContext}; From e88ce258ce43ca48fcf82bbde46aea742a1e33b1 Mon Sep 17 00:00:00 2001 From: reo Date: Wed, 29 Oct 2025 21:37:49 +0300 Subject: [PATCH 67/89] Tweak keybinds.rs to make camera mode toggle smoother --- game/src/systems/keybinds.rs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/game/src/systems/keybinds.rs b/game/src/systems/keybinds.rs index 6bc3e70..e701dad 100644 --- a/game/src/systems/keybinds.rs +++ b/game/src/systems/keybinds.rs @@ -4,17 +4,22 @@ use raidillon_core::scene::Scene; use raidillon_ecs::components::CameraMode; use raidillon_engine::{EngineResources, InputState}; use raidillon_engine::system::System; -use raidillon_platform::Camera; +use raidillon_platform::{Camera, PlatformContext}; #[derive(Default)] -pub struct KeybindsSystem; +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::().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; } } From ce24354f3b71ecf597f4f9800ff33305e8f77f88 Mon Sep 17 00:00:00 2001 From: reo Date: Sun, 16 Nov 2025 18:14:12 +0300 Subject: [PATCH 68/89] egui support - New Resource, EguiQueue: Utility to queue egui ui builders - New Rendering System, EguiRenderer: Utilizes a modified egui_glium library to render egui UI - Adjusted RenderingSystem trait and RenderingContext structure to provide event_loop and egui_queue. - Various minor adjusments --- Cargo.lock | 770 ++++++++++++++++++++++---- core/Cargo.toml | 3 +- core/src/egui_queue.rs | 22 + core/src/engine.rs | 3 - core/src/lib.rs | 2 + engine/Cargo.toml | 3 +- engine/src/engine.rs | 5 - game/Cargo.toml | 1 + game/src/main.rs | 32 +- glium_platform/Cargo.toml | 7 +- glium_platform/src/platform.rs | 17 +- glium_platform/src/render/basic.rs | 4 +- glium_platform/src/render/debug_ui.rs | 75 --- glium_platform/src/render/egui.rs | 46 ++ glium_platform/src/render/mod.rs | 3 +- glium_platform/src/render/skybox.rs | 3 +- glium_platform/src/system.rs | 11 +- platform/src/context.rs | 3 + 18 files changed, 806 insertions(+), 204 deletions(-) create mode 100644 core/src/egui_queue.rs delete mode 100644 glium_platform/src/render/debug_ui.rs create mode 100644 glium_platform/src/render/egui.rs diff --git a/Cargo.lock b/Cargo.lock index 91f50f1..3e9b382 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 4 [[package]] name = "ab_glyph" -version = "0.2.31" +version = "0.2.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e074464580a518d16a7126262fffaaa47af89d4099d4cb403f8ed938ba12ee7d" +checksum = "01c0457472c38ea5bd1c3b5ada5e368271cb550be7a4ca4a0b4634e9913f6cc2" dependencies = [ "ab_glyph_rasterizer", "owned_ttf_parser", @@ -59,7 +59,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef6978589202a00cd7e118380c448a08b6ed394c3a8df3a430d0898e3a42d046" dependencies = [ "android-properties", - "bitflags 2.9.1", + "bitflags 2.10.0", "cc", "cesu8", "jni", @@ -94,6 +94,26 @@ dependencies = [ "num-traits", ] +[[package]] +name = "arboard" +version = "3.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0348a1c054491f4bfe6ab86a7b6ab1e44e45d899005de92f58b3df180b36ddaf" +dependencies = [ + "clipboard-win", + "image", + "log", + "objc2 0.6.3", + "objc2-app-kit 0.3.1", + "objc2-core-foundation", + "objc2-core-graphics", + "objc2-foundation 0.3.1", + "parking_lot", + "percent-encoding", + "windows-sys 0.60.2", + "x11rb", +] + [[package]] name = "arrayref" version = "0.3.9" @@ -165,9 +185,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.9.1" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" +checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" [[package]] name = "block2" @@ -186,9 +206,23 @@ checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" [[package]] name = "bytemuck" -version = "1.23.1" +version = "1.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c76a5792e44e4abe34d3abf15636779261d45a7450612059293d1d2cfc63422" +checksum = "1fbdf580320f38b612e485521afda1ee26d10cc9884efaaa750d383e13e3c5f4" +dependencies = [ + "bytemuck_derive", +] + +[[package]] +name = "bytemuck_derive" +version = "1.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9abbd1bc6865053c427f7198e6af43bfdedc55ab791faed4fbd361d789575ff" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] [[package]] name = "byteorder" @@ -214,7 +248,7 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b99da2f8558ca23c71f4fd15dc57c906239752dd27ff3c00a1d56b685b7cbfec" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.10.0", "log", "polling", "rustix 0.38.44", @@ -222,18 +256,43 @@ dependencies = [ "thiserror 1.0.69", ] +[[package]] +name = "calloop" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb9f6e1368bd4621d2c86baa7e37de77a938adf5221e5dd3d6133340101b309e" +dependencies = [ + "bitflags 2.10.0", + "polling", + "rustix 1.0.8", + "slab", + "tracing", +] + [[package]] name = "calloop-wayland-source" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95a66a987056935f7efce4ab5668920b5d0dac4a7c99991a67395f13702ddd20" dependencies = [ - "calloop", + "calloop 0.13.0", "rustix 0.38.44", "wayland-backend", "wayland-client", ] +[[package]] +name = "calloop-wayland-source" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "138efcf0940a02ebf0cc8d1eff41a1682a46b431630f4c52450d6265876021fa" +dependencies = [ + "calloop 0.14.3", + "rustix 1.0.8", + "wayland-backend", + "wayland-client", +] + [[package]] name = "cc" version = "1.2.31" @@ -278,6 +337,15 @@ version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c00d31b1d19317b4777ec879192d3745bd97d05262b4b19cb1dda284b9d22f19" +[[package]] +name = "clipboard-win" +version = "5.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bde03770d3df201d4fb868f2c9c59e66a3e4e2bd06692a0fe701e7103c7e84d4" +dependencies = [ + "error-code", +] + [[package]] name = "combine" version = "4.6.7" @@ -307,6 +375,16 @@ dependencies = [ "libc", ] +[[package]] +name = "core-foundation" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "core-foundation-sys" version = "0.8.7" @@ -320,7 +398,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c07782be35f9e1140080c6b96f0d44b739e2278479f64e02fdab4e32dfd8b081" dependencies = [ "bitflags 1.3.2", - "core-foundation", + "core-foundation 0.9.4", "core-graphics-types", "foreign-types", "libc", @@ -333,7 +411,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf" dependencies = [ "bitflags 1.3.2", - "core-foundation", + "core-foundation 0.9.4", "libc", ] @@ -395,8 +473,19 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89a09f22a6c6069a18470eb92d2298acf25463f14256d24778e1230d789a2aec" dependencies = [ - "bitflags 2.9.1", - "objc2 0.6.1", + "bitflags 2.10.0", + "objc2 0.6.3", +] + +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -426,12 +515,84 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d8b14ccef22fc6f5a8f4d7d768562a182c04ce9a3b3157b91390b52ddfdf1a76" +[[package]] +name = "ecolor" +version = "0.33.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "084980ebede2fb1ad6c4f54285b3e489052ef2b6aa4016e4c19349417adc75c5" +dependencies = [ + "bytemuck", + "emath", +] + +[[package]] +name = "egui" +version = "0.33.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b75645894de4ca1695ab3ab7201c7953bb95c1725aafeefa6822dc901ad2a81b" +dependencies = [ + "ahash", + "bitflags 2.10.0", + "emath", + "epaint", + "log", + "nohash-hasher", + "profiling", + "smallvec", + "unicode-segmentation", +] + +[[package]] +name = "egui-winit" +version = "0.33.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4772ed5f16fa8ec2ba295e58f62b58ee83fcf49e67ec13d2b7ddf4e9a2dea34e" +dependencies = [ + "arboard", + "bytemuck", + "egui", + "log", + "objc2 0.5.2", + "objc2-foundation 0.2.2", + "objc2-ui-kit", + "profiling", + "raw-window-handle", + "smithay-clipboard", + "web-time", + "webbrowser", + "winit", +] + +[[package]] +name = "egui_glium" +version = "0.31.1" +source = "git+https://github.com/reo6/egui_glium.git#66dbadcb16b3e6c827847eaa51a0ca9bd296d768" +dependencies = [ + "ahash", + "bytemuck", + "egui", + "egui-winit", + "glium", + "log", + "raw-window-handle", + "winit", +] + [[package]] name = "either" version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" +[[package]] +name = "emath" +version = "0.33.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e561352ae95c22ad179fb56c38d6e6eecd86cf4925cf5c70e738dd01df9b620" +dependencies = [ + "bytemuck", +] + [[package]] name = "ena" version = "0.14.3" @@ -441,6 +602,30 @@ dependencies = [ "log", ] +[[package]] +name = "epaint" +version = "0.33.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a909ce8cee63e8350fb0c251ad39277a5b24f19add60787e84a3b3ab3f2bd83a" +dependencies = [ + "ab_glyph", + "ahash", + "bytemuck", + "ecolor", + "emath", + "epaint_default_fonts", + "log", + "nohash-hasher", + "parking_lot", + "profiling", +] + +[[package]] +name = "epaint_default_fonts" +version = "0.33.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad9649446c23368ae138716910e3e28143995691b598fbb9de16b42b0722cbcc" + [[package]] name = "equivalent" version = "1.0.2" @@ -457,6 +642,12 @@ dependencies = [ "windows-sys 0.60.2", ] +[[package]] +name = "error-code" +version = "3.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dea2df4cf52843e0452895c455a1a2cfbb842a1e7329671acf418fdc53ed4c59" + [[package]] name = "exr" version = "1.73.0" @@ -472,6 +663,26 @@ dependencies = [ "zune-inflate", ] +[[package]] +name = "fax" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f05de7d48f37cd6730705cbca900770cab77a89f413d23e100ad7fad7795a0ab" +dependencies = [ + "fax_derive", +] + +[[package]] +name = "fax_derive" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0aca10fb742cb43f9e7bb8467c91aa9bcb8e3ffbc6a6f7389bb93ffc920577d" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "fdeflate" version = "0.3.7" @@ -536,6 +747,15 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" +[[package]] +name = "form_urlencoded" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" +dependencies = [ + "percent-encoding", +] + [[package]] name = "gethostname" version = "0.4.3" @@ -673,9 +893,9 @@ checksum = "e12d847aeb25f41be4c0ec9587d624e9cd631bc007a8fd7ce3f5851e064c6460" [[package]] name = "glium" -version = "0.35.0" +version = "0.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a3028d1f135b5395e6e4336916b424bc5dd2b38c6e378ce2704e4b8f4a617ed" +checksum = "8cf52ce4f5ce1501bb056627f35484a819e812d1d93f0f3da413676421b1bbe0" dependencies = [ "backtrace", "fnv", @@ -733,7 +953,7 @@ version = "0.32.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "12124de845cacfebedff80e877bb37b5b75c34c5a4c89e47e1cdd67fb6041325" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.10.0", "cfg_aliases", "cgl", "dispatch2", @@ -741,7 +961,7 @@ dependencies = [ "glutin_glx_sys", "glutin_wgl_sys", "libloading", - "objc2 0.6.1", + "objc2 0.6.3", "objc2-app-kit 0.3.1", "objc2-core-foundation", "objc2-foundation 0.3.1", @@ -867,6 +1087,108 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" +[[package]] +name = "icu_collections" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43" +dependencies = [ + "displaydoc", + "potential_utf", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locale_core" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_normalizer" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599" +dependencies = [ + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a" + +[[package]] +name = "icu_properties" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e93fcd3157766c0c8da2f8cff6ce651a31f0810eaa1c51ec363ef790bbb5fb99" +dependencies = [ + "icu_collections", + "icu_locale_core", + "icu_properties_data", + "icu_provider", + "zerotrie", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02845b3647bb045f1100ecd6480ff52f34c35f82d9880e029d329c21d1054899" + +[[package]] +name = "icu_provider" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614" +dependencies = [ + "displaydoc", + "icu_locale_core", + "writeable", + "yoke", + "zerofrom", + "zerotrie", + "zerovec", +] + +[[package]] +name = "idna" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" +dependencies = [ + "icu_normalizer", + "icu_properties", +] + [[package]] name = "image" version = "0.25.8" @@ -879,6 +1201,7 @@ dependencies = [ "moxcms", "num-traits", "png", + "tiff", "zune-core", "zune-jpeg", ] @@ -896,16 +1219,6 @@ dependencies = [ "parking_lot", ] -[[package]] -name = "imgui-glium-renderer" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "781e53a393214a132c89c62e6e4b817645ad38832d3e334b2ad543f2c3df5106" -dependencies = [ - "glium", - "imgui", -] - [[package]] name = "imgui-sys" version = "0.12.0" @@ -918,16 +1231,6 @@ dependencies = [ "mint", ] -[[package]] -name = "imgui-winit-support" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff7fcccfa9efab56c94274c0fec9939bb14149342b49e6a425883a5b7dda6a3f" -dependencies = [ - "imgui", - "winit", -] - [[package]] name = "indexmap" version = "2.10.0" @@ -1038,7 +1341,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "391290121bad3d37fbddad76d8f5d1c1c314cfc646d143d7e07a3086ddff0ce3" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.10.0", "libc", "redox_syscall 0.5.17", ] @@ -1056,20 +1359,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" [[package]] -name = "lock_api" -version = "0.4.13" +name = "litemap" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765" +checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" + +[[package]] +name = "lock_api" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" dependencies = [ - "autocfg", "scopeguard", ] [[package]] name = "log" -version = "0.4.27" +version = "0.4.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" +checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" [[package]] name = "matrixmultiply" @@ -1180,7 +1488,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.10.0", "jni-sys", "log", "ndk-sys", @@ -1204,6 +1512,12 @@ dependencies = [ "jni-sys", ] +[[package]] +name = "nohash-hasher" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451" + [[package]] name = "num-bigint" version = "0.4.6" @@ -1304,9 +1618,9 @@ dependencies = [ [[package]] name = "objc2" -version = "0.6.1" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88c6597e14493ab2e44ce58f2fdecf095a51f12ca57bec060a11c57332520551" +checksum = "b7c2599ce0ec54857b29ce62166b0ed9b4f6f1a70ccc9a71165b6154caca8c05" dependencies = [ "objc2-encode", ] @@ -1317,7 +1631,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e4e89ad9e3d7d297152b17d39ed92cd50ca8063a89a9fa569046d41568891eff" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.10.0", "block2", "libc", "objc2 0.5.2", @@ -1333,9 +1647,10 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6f29f568bec459b0ddff777cec4fe3fd8666d82d5a40ebd0ff7e66134f89bcc" dependencies = [ - "bitflags 2.9.1", - "objc2 0.6.1", + "bitflags 2.10.0", + "objc2 0.6.3", "objc2-core-foundation", + "objc2-core-graphics", "objc2-foundation 0.3.1", ] @@ -1345,7 +1660,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74dd3b56391c7a0596a295029734d3c1c5e7e510a4cb30245f8221ccea96b009" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.10.0", "block2", "objc2 0.5.2", "objc2-core-location", @@ -1369,7 +1684,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "617fbf49e071c178c0b24c080767db52958f716d9eabdf0890523aeae54773ef" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.10.0", "block2", "objc2 0.5.2", "objc2-foundation 0.2.2", @@ -1377,13 +1692,26 @@ dependencies = [ [[package]] name = "objc2-core-foundation" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c10c2894a6fed806ade6027bcd50662746363a9589d3ec9d9bef30a4e4bc166" +checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.10.0", "dispatch2", - "objc2 0.6.1", + "objc2 0.6.3", +] + +[[package]] +name = "objc2-core-graphics" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e022c9d066895efa1345f8e33e584b9f958da2fd4cd116792e15e07e4720a807" +dependencies = [ + "bitflags 2.10.0", + "dispatch2", + "objc2 0.6.3", + "objc2-core-foundation", + "objc2-io-surface", ] [[package]] @@ -1422,7 +1750,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.10.0", "block2", "dispatch", "libc", @@ -1435,8 +1763,19 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "900831247d2fe1a09a683278e5384cfb8c80c79fe6b166f9d14bfdde0ea1b03c" dependencies = [ - "bitflags 2.9.1", - "objc2 0.6.1", + "bitflags 2.10.0", + "objc2 0.6.3", + "objc2-core-foundation", +] + +[[package]] +name = "objc2-io-surface" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "180788110936d59bab6bd83b6060ffdfffb3b922ba1396b312ae795e1de9d81d" +dependencies = [ + "bitflags 2.10.0", + "objc2 0.6.3", "objc2-core-foundation", ] @@ -1458,7 +1797,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.10.0", "block2", "objc2 0.5.2", "objc2-foundation 0.2.2", @@ -1470,7 +1809,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.10.0", "block2", "objc2 0.5.2", "objc2-foundation 0.2.2", @@ -1493,7 +1832,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8bb46798b20cd6b91cbd113524c490f1686f4c4e8f49502431415f3512e2b6f" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.10.0", "block2", "objc2 0.5.2", "objc2-cloud-kit", @@ -1525,7 +1864,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "76cfcbf642358e8689af64cee815d139339f3ed8ad05103ed5eaf73db8d84cb3" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.10.0", "block2", "objc2 0.5.2", "objc2-core-location", @@ -1576,9 +1915,9 @@ dependencies = [ [[package]] name = "parking_lot" -version = "0.12.4" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" dependencies = [ "lock_api", "parking_lot_core", @@ -1586,15 +1925,15 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.11" +version = "0.9.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" dependencies = [ "cfg-if", "libc", "redox_syscall 0.5.17", "smallvec", - "windows-targets 0.52.6", + "windows-link 0.2.1", ] [[package]] @@ -1605,7 +1944,7 @@ checksum = "017be73f24c8ca8b10f9727616e5cb9af82b98488cc6d5eea468e727ffa780ca" dependencies = [ "approx", "arrayvec", - "bitflags 2.9.1", + "bitflags 2.10.0", "downcast-rs 2.0.2", "either", "ena", @@ -1675,7 +2014,7 @@ version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97baced388464909d42d89643fe4361939af9b7ce7a31ee32a168f832a70f2a0" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.10.0", "crc32fast", "fdeflate", "flate2", @@ -1696,6 +2035,15 @@ dependencies = [ "windows-sys 0.60.2", ] +[[package]] +name = "potential_utf" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77" +dependencies = [ + "zerovec", +] + [[package]] name = "proc-macro-crate" version = "3.3.0" @@ -1742,6 +2090,12 @@ dependencies = [ "num-traits", ] +[[package]] +name = "quick-error" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" + [[package]] name = "quick-xml" version = "0.37.5" @@ -1774,6 +2128,7 @@ version = "0.1.0" name = "raidillon_core" version = "0.1.0" dependencies = [ + "egui", "hecs", "imgui", "indexmap", @@ -1794,6 +2149,7 @@ dependencies = [ name = "raidillon_engine" version = "0.1.0" dependencies = [ + "egui", "glam 0.30.8", "hecs", "indexmap", @@ -1808,6 +2164,7 @@ dependencies = [ name = "raidillon_game" version = "0.1.0" dependencies = [ + "egui", "glam 0.30.8", "hecs", "raidillon_assets", @@ -1826,14 +2183,13 @@ name = "raidillon_glium" version = "0.1.0" dependencies = [ "anyhow", + "egui", + "egui_glium", "exr", "glam 0.30.8", "glium", "gltf", "image", - "imgui", - "imgui-glium-renderer", - "imgui-winit-support", "indexmap", "raidillon_assets", "raidillon_core", @@ -1871,7 +2227,7 @@ dependencies = [ "approx", "arrayvec", "bit-vec", - "bitflags 2.9.1", + "bitflags 2.10.0", "downcast-rs 2.0.2", "log", "nalgebra", @@ -1924,7 +2280,7 @@ version = "0.5.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.10.0", ] [[package]] @@ -1962,7 +2318,7 @@ version = "0.38.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.10.0", "errno", "libc", "linux-raw-sys 0.4.15", @@ -1975,7 +2331,7 @@ version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.10.0", "errno", "libc", "linux-raw-sys 0.9.4", @@ -2033,7 +2389,7 @@ dependencies = [ "ab_glyph", "log", "memmap2", - "smithay-client-toolkit", + "smithay-client-toolkit 0.19.2", "tiny-skia", ] @@ -2112,9 +2468,9 @@ version = "0.19.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3457dea1f0eb631b4034d61d4d8c32074caa6cd1ab2d59f2327bd8461e2c0016" dependencies = [ - "bitflags 2.9.1", - "calloop", - "calloop-wayland-source", + "bitflags 2.10.0", + "calloop 0.13.0", + "calloop-wayland-source 0.3.0", "cursor-icon", "libc", "log", @@ -2131,6 +2487,44 @@ dependencies = [ "xkeysym", ] +[[package]] +name = "smithay-client-toolkit" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0512da38f5e2b31201a93524adb8d3136276fa4fe4aafab4e1f727a82b534cc0" +dependencies = [ + "bitflags 2.10.0", + "calloop 0.14.3", + "calloop-wayland-source 0.4.1", + "cursor-icon", + "libc", + "log", + "memmap2", + "rustix 1.0.8", + "thiserror 2.0.17", + "wayland-backend", + "wayland-client", + "wayland-csd-frame", + "wayland-cursor", + "wayland-protocols", + "wayland-protocols-experimental", + "wayland-protocols-misc", + "wayland-protocols-wlr", + "wayland-scanner", + "xkeysym", +] + +[[package]] +name = "smithay-clipboard" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71704c03f739f7745053bde45fa203a46c58d25bc5c4efba1d9a60e9dba81226" +dependencies = [ + "libc", + "smithay-client-toolkit 0.20.0", + "wayland-backend", +] + [[package]] name = "smol_str" version = "0.2.2" @@ -2187,6 +2581,17 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "synstructure" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "thiserror" version = "1.0.69" @@ -2227,6 +2632,20 @@ dependencies = [ "syn", ] +[[package]] +name = "tiff" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af9605de7fee8d9551863fd692cce7637f548dbd9db9180fcc07ccc6d26c336f" +dependencies = [ + "fax", + "flate2", + "half", + "quick-error", + "weezl", + "zune-jpeg", +] + [[package]] name = "tiny-skia" version = "0.11.4" @@ -2252,6 +2671,16 @@ dependencies = [ "strict-num", ] +[[package]] +name = "tinystr" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869" +dependencies = [ + "displaydoc", + "zerovec", +] + [[package]] name = "toml_datetime" version = "0.6.11" @@ -2275,6 +2704,7 @@ version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" dependencies = [ + "log", "pin-project-lite", "tracing-core", ] @@ -2309,12 +2739,29 @@ version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" +[[package]] +name = "url" +version = "2.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + [[package]] name = "urlencoding" version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + [[package]] name = "version_check" version = "0.9.5" @@ -2431,7 +2878,7 @@ version = "0.31.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c66a47e840dc20793f2264eb4b3e4ecb4b75d91c0dd4af04b456128e0bdd449d" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.10.0", "rustix 1.0.8", "wayland-backend", "wayland-scanner", @@ -2443,7 +2890,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "625c5029dbd43d25e6aa9615e88b829a5cad13b2819c4ae129fdbb7c31ab4c7e" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.10.0", "cursor-icon", "wayland-backend", ] @@ -2465,19 +2912,45 @@ version = "0.32.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "efa790ed75fbfd71283bd2521a1cfdc022aabcc28bdcff00851f9e4ae88d9901" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.10.0", "wayland-backend", "wayland-client", "wayland-scanner", ] +[[package]] +name = "wayland-protocols-experimental" +version = "20250721.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40a1f863128dcaaec790d7b4b396cc9b9a7a079e878e18c47e6c2d2c5a8dcbb1" +dependencies = [ + "bitflags 2.10.0", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-scanner", +] + +[[package]] +name = "wayland-protocols-misc" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dfe33d551eb8bffd03ff067a8b44bb963919157841a99957151299a6307d19c" +dependencies = [ + "bitflags 2.10.0", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-scanner", +] + [[package]] name = "wayland-protocols-plasma" version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a07a14257c077ab3279987c4f8bb987851bf57081b93710381daea94f2c2c032" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.10.0", "wayland-backend", "wayland-client", "wayland-protocols", @@ -2490,7 +2963,7 @@ version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "efd94963ed43cf9938a090ca4f7da58eb55325ec8200c3848963e98dc25b78ec" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.10.0", "wayland-backend", "wayland-client", "wayland-protocols", @@ -2540,6 +3013,28 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "webbrowser" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00f1243ef785213e3a32fa0396093424a3a6ea566f9948497e5a2309261a4c97" +dependencies = [ + "core-foundation 0.10.1", + "jni", + "log", + "ndk-context", + "objc2 0.6.3", + "objc2-foundation 0.3.1", + "url", + "web-sys", +] + +[[package]] +name = "weezl" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a28ac98ddc8b9274cb41bb4d9d4d5c425b6020c50c46f25559911905610b4a88" + [[package]] name = "wide" version = "0.7.33" @@ -2565,6 +3060,12 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + [[package]] name = "windows-sys" version = "0.45.0" @@ -2653,7 +3154,7 @@ version = "0.53.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91" dependencies = [ - "windows-link", + "windows-link 0.1.3", "windows_aarch64_gnullvm 0.53.0", "windows_aarch64_msvc 0.53.0", "windows_i686_gnu 0.53.0", @@ -2853,13 +3354,13 @@ dependencies = [ "ahash", "android-activity", "atomic-waker", - "bitflags 2.9.1", + "bitflags 2.10.0", "block2", "bytemuck", - "calloop", + "calloop 0.13.0", "cfg_aliases", "concurrent-queue", - "core-foundation", + "core-foundation 0.9.4", "core-graphics", "cursor-icon", "dpi", @@ -2878,7 +3379,7 @@ dependencies = [ "redox_syscall 0.4.1", "rustix 0.38.44", "sctk-adwaita", - "smithay-client-toolkit", + "smithay-client-toolkit 0.19.2", "smol_str", "tracing", "unicode-segmentation", @@ -2911,9 +3412,15 @@ version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.10.0", ] +[[package]] +name = "writeable" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" + [[package]] name = "x11-dl" version = "2.21.0" @@ -2958,7 +3465,7 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d039de8032a9a8856a6be89cea3e5d12fdd82306ab7c94d74e6deab2460651c5" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.10.0", "dlib", "log", "once_cell", @@ -2977,6 +3484,29 @@ version = "0.8.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6fd8403733700263c6eb89f192880191f1b83e332f7a20371ddcf421c4a337c7" +[[package]] +name = "yoke" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954" +dependencies = [ + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + [[package]] name = "zerocopy" version = "0.8.26" @@ -2997,6 +3527,60 @@ dependencies = [ "syn", ] +[[package]] +name = "zerofrom" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "zerotrie" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", +] + +[[package]] +name = "zerovec" +version = "0.11.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "zune-core" version = "0.4.12" diff --git a/core/Cargo.toml b/core/Cargo.toml index fc6b73f..a8d650d 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -8,4 +8,5 @@ hecs = "0.10.5" indexmap = "2.10.0" raidillon_assets = { path = "../asset" } winit = "0.30.12" -imgui = "0.12.0" \ No newline at end of file +imgui = "0.12.0" +egui = "0.33.2" \ No newline at end of file diff --git a/core/src/egui_queue.rs b/core/src/egui_queue.rs new file mode 100644 index 0000000..fbbb789 --- /dev/null +++ b/core/src/egui_queue.rs @@ -0,0 +1,22 @@ +pub struct EguiQueue { + pub queue_vec: Vec>, +} + +impl EguiQueue { + pub fn new() -> Self { + Self { queue_vec: Vec::new() } + } + + pub fn queue(&mut self, func: impl FnOnce(&egui::Context) + Send + 'static) { + self.queue_vec.push(Box::new(func)); + } + + pub fn clear(&mut self) { + self.queue_vec.clear() + } + + pub fn run(&mut self, ctx: &egui::Context) { + self.queue_vec.drain(..).for_each(|func| func(ctx)); + self.clear(); + } +} diff --git a/core/src/engine.rs b/core/src/engine.rs index b70a945..1308e20 100644 --- a/core/src/engine.rs +++ b/core/src/engine.rs @@ -1,5 +1,3 @@ -use std::cell::RefCell; -use std::rc::Rc; use crate::DebugUIBuffer; use crate::scene::Scene; @@ -14,5 +12,4 @@ pub trait EngineTrait { fn current_scene(&self) -> &Scene; fn get_debug_ui_buffer(&self) -> &DebugUIBuffer; fn reset_debug_ui_buffer(&mut self); - // fn scene_and_debug_ui_buffer_mut(&mut self) -> (&mut Self::Scene, &DebugUIBuffer); } diff --git a/core/src/lib.rs b/core/src/lib.rs index 238d5a6..61f5286 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -3,5 +3,7 @@ pub mod debug_ui; pub mod time; pub mod utils; pub mod scene; +mod egui_queue; pub use debug_ui::*; +pub use egui_queue::EguiQueue; diff --git a/engine/Cargo.toml b/engine/Cargo.toml index 79a2de9..1264629 100644 --- a/engine/Cargo.toml +++ b/engine/Cargo.toml @@ -11,4 +11,5 @@ raidillon_ecs = { path = "../ecs" } winit = "0.30.12" hecs = "0.10.5" indexmap = "2.10.0" -glam = "0.30.8" \ No newline at end of file +glam = "0.30.8" +egui = "0.33.2" \ No newline at end of file diff --git a/engine/src/engine.rs b/engine/src/engine.rs index a5c8a1d..398920c 100644 --- a/engine/src/engine.rs +++ b/engine/src/engine.rs @@ -94,9 +94,4 @@ impl EngineTrait for Engine { fn reset_debug_ui_buffer(&mut self) { self.scene_manager.current_mut().resources.get_mut::().unwrap().reset_buffer(); } - - // fn scene_and_debug_ui_buffer_mut(&mut self) -> (&mut Scene, &DebugUIBuffer) { - // let (sm, dub) = (&mut self.scene_manager, self.scene_manager.current().resources.get::().unwrap()); - // (sm.current_mut(), dub) - // } } diff --git a/game/Cargo.toml b/game/Cargo.toml index 9579d22..f88ea43 100644 --- a/game/Cargo.toml +++ b/game/Cargo.toml @@ -19,3 +19,4 @@ glam = "0.30.5" winit = "0.30.12" rapier3d = "0.30.1" hecs = "0.10.5" +egui = "0.33.2" \ No newline at end of file diff --git a/game/src/main.rs b/game/src/main.rs index 99eb0e2..42ab2d3 100644 --- a/game/src/main.rs +++ b/game/src/main.rs @@ -16,7 +16,7 @@ use raidillon_glium::GliumPlatform; use winit::event::{ElementState, Event, WindowEvent}; use winit::event::DeviceEvent::MouseMotion; use winit::keyboard::{KeyCode, PhysicalKey}; -use raidillon_core::DebugUIBuffer; +use raidillon_core::{DebugUIBuffer, EguiQueue}; use systems::debug_camera::FPSDebugCameraSystem; use raidillon_glium::RenderingSystem; use raidillon_physics::Physics; @@ -102,18 +102,30 @@ impl System for RenderingTestSystem { } fn frame_update(&mut self, res: &mut EngineResources, scene: &mut Scene) { - let pctx = res.get::().unwrap(); - let input = res.get::().unwrap(); - let dbg_ui = scene.resources.get_mut::().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)); + let ( + pctx, + input, + ) = res.get_many_mut::<( + PlatformContext, + InputState, + )>().unwrap(); + let mut egui_queue = pctx.egui_queue.borrow_mut(); + let time_ctx = pctx.time_ctx.clone(); + let mut character_pos = Vec3::ZERO; for (_ent, (tr, ch_component)) in scene.world.query::<(&Transform, &CharacterBodyComponent)>().iter() { - dbg_ui.text(format!("Character POS: {}", tr.translation)); + character_pos = tr.translation; } + egui_queue.queue(move |egui_ctx| { + egui::Window::new("Debug").show(egui_ctx, |ui| { + ui.label("Hello World!"); + ui.label(format!("Frame Delta: {}", time_ctx.frame_dt)); + ui.label(format!("Fixed Delta: {}", time_ctx.fixed_dt)); + ui.label(format!("FPS: {}", 1.0 / time_ctx.frame_dt)); + ui.label(format!("Character POS: {}", character_pos)); + }); + }); + } } diff --git a/glium_platform/Cargo.toml b/glium_platform/Cargo.toml index 6e51be6..109fc57 100644 --- a/glium_platform/Cargo.toml +++ b/glium_platform/Cargo.toml @@ -6,7 +6,7 @@ edition = "2024" [dependencies] anyhow = "1.0.98" glam = "0.30.5" -glium = { version = "0.35.0", features = ["glutin_backend", "simple_window_builder"] } +glium = { version = "0.36.0", features = ["glutin_backend", "simple_window_builder"] } gltf = { version = "1.4.1", features = ["import", "utils", "KHR_texture_transform"] } raidillon_platform = { path = "../platform" } raidillon_core = { path = "../core" } @@ -15,8 +15,7 @@ raidillon_ecs = { path = "../ecs" } raidillon_engine = { path = "../engine" } winit = "0.30.12" indexmap = "2.10.0" -imgui = "0.12.0" -imgui-winit-support = "0.13.0" -imgui-glium-renderer = "0.13.0" exr = "1.73.0" image = { version = "0.25.8", default-features = false, features = ["exr"] } +egui = "0.33.2" +egui_glium = { version = "0.31.1", git = "https://github.com/reo6/egui_glium.git" } diff --git a/glium_platform/src/platform.rs b/glium_platform/src/platform.rs index db8e56e..efc1543 100644 --- a/glium_platform/src/platform.rs +++ b/glium_platform/src/platform.rs @@ -14,11 +14,11 @@ use raidillon_assets::ModelManagerRef; use raidillon_core::engine::EngineTrait; use raidillon_core::time; use raidillon_core::time::Time; -use crate::render::debug_ui::ImguiBridge; -use crate::render::{BasicMeshRenderingSystem, SkyboxRenderingSystem}; +use crate::render::{BasicMeshRenderingSystem, EguiRenderer, SkyboxRenderingSystem}; use crate::GliumAssetManager; use glam::Vec3; use winit::event::DeviceEvent::MouseMotion; +use raidillon_core::EguiQueue; pub struct GliumPlatform> { event_loop: EventLoop<()>, @@ -28,6 +28,7 @@ pub struct GliumPlatform> { asset_manager: ModelManagerRef, engine: E, time: time::Time, + egui_queue: Rc>, } impl> Platform for GliumPlatform { @@ -50,9 +51,11 @@ impl> Platform for GliumPlatfor let window = Arc::new(Mutex::new(window)); // Install rendering systems in order - rendering_system_manager.add::(&display, window.clone()); - rendering_system_manager.add::(&display, window.clone()); - rendering_system_manager.add::(&display, window.clone()); + rendering_system_manager.add::(&display, window.clone(), &event_loop); + rendering_system_manager.add::(&display, window.clone(), &event_loop); + rendering_system_manager.add::(&display, window.clone(), &event_loop); + + let egui_queue = Rc::new(RefCell::new(EguiQueue::new())); Self { event_loop, @@ -62,6 +65,7 @@ impl> Platform for GliumPlatfor asset_manager, engine, time, + egui_queue, } } @@ -77,6 +81,7 @@ impl> Platform for GliumPlatfor frame_height: h as f32, time_ctx: self.construct_time_ctx(), window: self.window.clone(), + egui_queue: self.egui_queue.clone(), }; self.engine.initialize(ctx.clone()); let _ = &self.event_loop.run(move |event, el| { @@ -105,9 +110,11 @@ impl> Platform for GliumPlatfor let mut context = RenderingContext { scene, target: &mut target, + display: &self.display, asset_manager: self.asset_manager.clone(), window: self.window.clone(), debug_ui_buffer, + egui_queue: self.egui_queue.clone(), env_light_dir: Vec3::new(0.0, -1.0, 0.0), }; diff --git a/glium_platform/src/render/basic.rs b/glium_platform/src/render/basic.rs index 663b2dd..a55d865 100644 --- a/glium_platform/src/render/basic.rs +++ b/glium_platform/src/render/basic.rs @@ -9,6 +9,8 @@ use raidillon_assets::include_shader; pub use raidillon_platform::Camera; use glam::Vec3; use glium::uniforms::{MagnifySamplerFilter, MinifySamplerFilter, SamplerWrapFunction}; +use winit::event::Event; +use winit::event_loop::EventLoop; use raidillon_ecs::{Transform, ModelID}; use raidillon_ecs::components::ModelHandle; use crate::model::Model; @@ -21,7 +23,7 @@ pub struct BasicMeshRenderingSystem { } impl RenderingSystem for BasicMeshRenderingSystem { - fn initialize(display: &Display, _window: Arc>) -> Self { + fn initialize(display: &Display, _window: Arc>, event_loop: &EventLoop<()>) -> Self { const VERT_SRC: &str = include_shader!("gl_textured.vert"); const FRAG_SRC: &str = include_shader!("gl_textured.frag"); diff --git a/glium_platform/src/render/debug_ui.rs b/glium_platform/src/render/debug_ui.rs deleted file mode 100644 index ac4a06e..0000000 --- a/glium_platform/src/render/debug_ui.rs +++ /dev/null @@ -1,75 +0,0 @@ -use std::sync::{Arc, Mutex}; -use std::time::Instant; -use glium::Display; -use glium::glutin::surface::WindowSurface; -use imgui::{Context as ImguiContext}; -use imgui_winit_support::{HiDpiMode, WinitPlatform}; -use imgui_glium_renderer::Renderer as ImguiGliumRenderer; -use winit::window::Window; -use winit::event::Event; -use glium::Frame; -use crate::RenderingSystem; -use crate::system::RenderingContext; - -pub struct ImguiBridge { - imgui: ImguiContext, - platform: WinitPlatform, - renderer: ImguiGliumRenderer, - last_frame: Instant, - rendered_this_frame: bool, -} - -impl RenderingSystem for ImguiBridge { - fn handle_event(&mut self, window: Arc>, event: Event<()>) { - let window = window.lock().unwrap(); - self.platform.handle_event(self.imgui.io_mut(), &*window, &event); - } - - fn prepare_frame(&mut self, window: Arc>) { - self.rendered_this_frame = false; - let now = Instant::now(); - self.imgui.io_mut().update_delta_time(now - self.last_frame); - self.last_frame = now; - let window = window.lock().unwrap(); - self.platform - .prepare_frame(self.imgui.io_mut(), &*window) - .expect("Failed to prepare frame"); - } - - fn render(&mut self, ctx: &mut RenderingContext) { - if self.rendered_this_frame { return; } - self.rendered_this_frame = true; - - let ui = self.imgui.frame(); - ctx.debug_ui_buffer.write_buffer(&ui); - - { - let window = ctx.window.lock().unwrap(); - self.platform.prepare_render(&ui, &*window); - } - let draw_data = self.imgui.render(); - if draw_data.total_vtx_count == 0 && draw_data.total_idx_count == 0 { - return; - } - - self.renderer.render(ctx.target, draw_data).expect("imgui rendering failed"); - } - - fn initialize(display: &Display, window: Arc>) -> Self { - let mut imgui = ImguiContext::create(); - imgui.set_ini_filename(None); - let mut platform = WinitPlatform::new(&mut imgui); - let window = window.lock().unwrap(); - platform.attach_window(imgui.io_mut(), &*window, HiDpiMode::Default); - imgui.fonts().add_font(&[imgui::FontSource::DefaultFontData { config: None }]); - let renderer = ImguiGliumRenderer::new(&mut imgui, display).unwrap(); - - Self { - imgui, - platform, - renderer, - last_frame: Instant::now(), - rendered_this_frame: false, - } - } -} diff --git a/glium_platform/src/render/egui.rs b/glium_platform/src/render/egui.rs new file mode 100644 index 0000000..e754ba3 --- /dev/null +++ b/glium_platform/src/render/egui.rs @@ -0,0 +1,46 @@ +use std::sync::{Arc, Mutex}; +use egui::ViewportId; +use glium::{Display, Frame}; +use glium::glutin::surface::WindowSurface; +use winit::window::Window; +use crate::RenderingSystem; +use crate::system::RenderingContext; +use egui_glium::EguiGlium; +use winit::event::{Event, WindowEvent}; +use winit::event_loop::EventLoop; + +pub struct EguiRenderer { + egui_glium: EguiGlium, +} + +impl RenderingSystem for EguiRenderer { + fn initialize(display: &Display, window: Arc>, event_loop: &EventLoop<()>) -> Self + where + Self: Sized, + { + let window = window.lock().unwrap(); + let egui_glium = EguiGlium::new(ViewportId::ROOT, &display, &window, &event_loop); + + Self { egui_glium } + } + + fn render(&mut self, ctx: &mut RenderingContext) { + let window = ctx.window.lock().unwrap(); + + self.egui_glium.run(&window, |egui_ctx| { + ctx.egui_queue.borrow_mut().run(egui_ctx); + }); + + self.egui_glium.paint(ctx.display, ctx.target); + } + + fn handle_event(&mut self, window: Arc>, event: Event<()>) { + let window = window.lock().unwrap(); + match event { + Event::WindowEvent { event, .. } => { + let _ = self.egui_glium.on_event(&window, &event); + } + _ => {}, + } + } +} diff --git a/glium_platform/src/render/mod.rs b/glium_platform/src/render/mod.rs index f49e308..fdfa1ea 100644 --- a/glium_platform/src/render/mod.rs +++ b/glium_platform/src/render/mod.rs @@ -1,6 +1,7 @@ mod basic; -pub mod debug_ui; mod skybox; +mod egui; pub use basic::BasicMeshRenderingSystem; pub use skybox::SkyboxRenderingSystem; +pub use egui::EguiRenderer; diff --git a/glium_platform/src/render/skybox.rs b/glium_platform/src/render/skybox.rs index ac22210..94832d0 100644 --- a/glium_platform/src/render/skybox.rs +++ b/glium_platform/src/render/skybox.rs @@ -8,6 +8,7 @@ use glium::index::PrimitiveType; use glium::texture::{RawImage2d, SrgbTexture2d, Texture2d}; use glium::uniform; use glam::{Mat4, Vec2, Vec3}; +use winit::event_loop::EventLoop; use raidillon_assets::include_shader; use crate::system::RenderingContext; use crate::RenderingSystem; @@ -109,7 +110,7 @@ impl SkyboxRenderingSystem { } impl RenderingSystem for SkyboxRenderingSystem { - fn initialize(display: &Display, _window: Arc>) -> Self { + fn initialize(display: &Display, _window: Arc>, event_loop: &EventLoop<()>) -> Self { const VERT_SRC: &str = include_shader!("skybox.vert"); const FRAG_SRC: &str = include_shader!("skybox.frag"); let program = Program::from_source(display, VERT_SRC, FRAG_SRC, None).unwrap(); diff --git a/glium_platform/src/system.rs b/glium_platform/src/system.rs index 51a292f..5d7f197 100644 --- a/glium_platform/src/system.rs +++ b/glium_platform/src/system.rs @@ -6,16 +6,19 @@ use indexmap::IndexMap; use glium::{Display, Frame}; use glium::glutin::surface::WindowSurface; use raidillon_assets::ModelManagerRef; -use raidillon_core::{define_typemap, DebugUIBuffer}; +use raidillon_core::{define_typemap, DebugUIBuffer, EguiQueue}; use raidillon_core::scene::Scene; use glam::Vec3; +use winit::event_loop::EventLoop; pub struct RenderingContext<'a> { pub scene: &'a Scene, pub target: &'a mut Frame, pub window: Arc>, + pub display: &'a Display, pub asset_manager: ModelManagerRef, pub debug_ui_buffer: &'a DebugUIBuffer, + pub egui_queue: Rc>, pub env_light_dir: Vec3, } @@ -30,7 +33,7 @@ pub trait RenderingSystem { } fn prepare_frame(&mut self, _window: Arc>) {} fn render(&mut self, ctx: &mut RenderingContext); - fn initialize(display: &Display, window: Arc>) -> Self + fn initialize(display: &Display, window: Arc>, event_loop: &EventLoop<()>) -> Self where Self: Sized; } @@ -48,11 +51,11 @@ impl RenderingSystemManager { } } - pub fn add(&mut self, display: &Display, window: Arc>) + pub fn add(&mut self, display: &Display, window: Arc>, event_loop: &EventLoop<()>) where R: RenderingSystem + 'static, { - let system = R::initialize(display, window); + let system = R::initialize(display, window, event_loop); self.systems.insert(TypeId::of::(), Box::new(system)); } diff --git a/platform/src/context.rs b/platform/src/context.rs index 892b69e..b78ea94 100644 --- a/platform/src/context.rs +++ b/platform/src/context.rs @@ -1,6 +1,8 @@ +use std::{cell::RefCell, rc::Rc}; use std::sync::{Arc, Mutex}; use winit::event::Event; use raidillon_assets::ModelManagerRef; +use raidillon_core::EguiQueue; #[derive(Clone)] pub struct PlatformContext { @@ -10,6 +12,7 @@ pub struct PlatformContext { pub frame_height: f32, pub time_ctx: TimeContext, pub window: Arc>, + pub egui_queue: Rc>, } #[derive(Clone)] From 4b97bd98d2a99eb0c5e1c8cf35d35f81ec3f1e0f Mon Sep 17 00:00:00 2001 From: reo Date: Sun, 16 Nov 2025 18:22:09 +0300 Subject: [PATCH 69/89] Fix #9, add tests to typemap.rs --- core/src/utils/typemap.rs | 116 ++++++++++++++++++++++++++------------ 1 file changed, 80 insertions(+), 36 deletions(-) diff --git a/core/src/utils/typemap.rs b/core/src/utils/typemap.rs index bd28a66..c04c2c9 100644 --- a/core/src/utils/typemap.rs +++ b/core/src/utils/typemap.rs @@ -101,7 +101,7 @@ macro_rules! define_typemap { { type Output<'a> = (&'a mut A,); fn get_from_mut<'a>(map: &'a mut HashMap>) -> Option> { - let ptr_a = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; + let ptr_a = { map.get_mut(&TypeId::of::()).map(|v| v.as_mut() as *mut dyn Any) }?; unsafe { let a = (&mut *ptr_a).downcast_mut::()?; Some((a,)) @@ -133,8 +133,8 @@ macro_rules! define_typemap { fn get_from_mut<'a>(map: &'a mut HashMap>) -> Option> { let ids = [TypeId::of::(), TypeId::of::()]; if ids[0] == ids[1] { return None; } - let ptr_a = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; - let ptr_b = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; + let ptr_a = { map.get_mut(&TypeId::of::()).map(|v| v.as_mut() as *mut dyn Any) }?; + let ptr_b = { map.get_mut(&TypeId::of::()).map(|v| v.as_mut() as *mut dyn Any) }?; unsafe { let a = (&mut *ptr_a).downcast_mut::()?; let b = (&mut *ptr_b).downcast_mut::()?; @@ -170,9 +170,9 @@ macro_rules! define_typemap { fn get_from_mut<'a>(map: &'a mut HashMap>) -> Option> { let ids = [TypeId::of::(), TypeId::of::(), TypeId::of::()]; if ids[0] == ids[1] || ids[0] == ids[2] || ids[1] == ids[2] { return None; } - let ptr_a = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; - let ptr_b = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; - let ptr_c = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; + let ptr_a = { map.get_mut(&TypeId::of::()).map(|v| v.as_mut() as *mut dyn Any) }?; + let ptr_b = { map.get_mut(&TypeId::of::()).map(|v| v.as_mut() as *mut dyn Any) }?; + let ptr_c = { map.get_mut(&TypeId::of::()).map(|v| v.as_mut() as *mut dyn Any) }?; unsafe { let a = (&mut *ptr_a).downcast_mut::()?; let b = (&mut *ptr_b).downcast_mut::()?; @@ -212,10 +212,10 @@ macro_rules! define_typemap { fn get_from_mut<'a>(map: &'a mut HashMap>) -> Option> { let ids = [TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::()]; for i in 0..ids.len() { for j in (i+1)..ids.len() { if ids[i] == ids[j] { return None; } } } - let ptr_a = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; - let ptr_b = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; - let ptr_c = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; - let ptr_d = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; + let ptr_a = { map.get_mut(&TypeId::of::()).map(|v| v.as_mut() as *mut dyn Any) }?; + let ptr_b = { map.get_mut(&TypeId::of::()).map(|v| v.as_mut() as *mut dyn Any) }?; + let ptr_c = { map.get_mut(&TypeId::of::()).map(|v| v.as_mut() as *mut dyn Any) }?; + let ptr_d = { map.get_mut(&TypeId::of::()).map(|v| v.as_mut() as *mut dyn Any) }?; unsafe { let a = (&mut *ptr_a).downcast_mut::()?; let b = (&mut *ptr_b).downcast_mut::()?; @@ -259,11 +259,11 @@ macro_rules! define_typemap { fn get_from_mut<'a>(map: &'a mut HashMap>) -> Option> { let ids = [TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::()]; for i in 0..ids.len() { for j in (i+1)..ids.len() { if ids[i] == ids[j] { return None; } } } - let ptr_a = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; - let ptr_b = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; - let ptr_c = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; - let ptr_d = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; - let ptr_e = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; + let ptr_a = { map.get_mut(&TypeId::of::()).map(|v| v.as_mut() as *mut dyn Any) }?; + let ptr_b = { map.get_mut(&TypeId::of::()).map(|v| v.as_mut() as *mut dyn Any) }?; + let ptr_c = { map.get_mut(&TypeId::of::()).map(|v| v.as_mut() as *mut dyn Any) }?; + let ptr_d = { map.get_mut(&TypeId::of::()).map(|v| v.as_mut() as *mut dyn Any) }?; + let ptr_e = { map.get_mut(&TypeId::of::()).map(|v| v.as_mut() as *mut dyn Any) }?; unsafe { let a = (&mut *ptr_a).downcast_mut::()?; let b = (&mut *ptr_b).downcast_mut::()?; @@ -311,12 +311,12 @@ macro_rules! define_typemap { fn get_from_mut<'a>(map: &'a mut HashMap>) -> Option> { let ids = [TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::()]; for i in 0..ids.len() { for j in (i+1)..ids.len() { if ids[i] == ids[j] { return None; } } } - let ptr_a = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; - let ptr_b = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; - let ptr_c = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; - let ptr_d = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; - let ptr_e = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; - let ptr_f = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; + let ptr_a = { map.get_mut(&TypeId::of::()).map(|v| v.as_mut() as *mut dyn Any) }?; + let ptr_b = { map.get_mut(&TypeId::of::()).map(|v| v.as_mut() as *mut dyn Any) }?; + let ptr_c = { map.get_mut(&TypeId::of::()).map(|v| v.as_mut() as *mut dyn Any) }?; + let ptr_d = { map.get_mut(&TypeId::of::()).map(|v| v.as_mut() as *mut dyn Any) }?; + let ptr_e = { map.get_mut(&TypeId::of::()).map(|v| v.as_mut() as *mut dyn Any) }?; + let ptr_f = { map.get_mut(&TypeId::of::()).map(|v| v.as_mut() as *mut dyn Any) }?; unsafe { let a = (&mut *ptr_a).downcast_mut::()?; let b = (&mut *ptr_b).downcast_mut::()?; @@ -368,13 +368,13 @@ macro_rules! define_typemap { fn get_from_mut<'a>(map: &'a mut HashMap>) -> Option> { let ids = [TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::()]; for i in 0..ids.len() { for j in (i+1)..ids.len() { if ids[i] == ids[j] { return None; } } } - let ptr_a = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; - let ptr_b = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; - let ptr_c = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; - let ptr_d = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; - let ptr_e = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; - let ptr_f = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; - let ptr_g = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; + let ptr_a = { map.get_mut(&TypeId::of::()).map(|v| v.as_mut() as *mut dyn Any) }?; + let ptr_b = { map.get_mut(&TypeId::of::()).map(|v| v.as_mut() as *mut dyn Any) }?; + let ptr_c = { map.get_mut(&TypeId::of::()).map(|v| v.as_mut() as *mut dyn Any) }?; + let ptr_d = { map.get_mut(&TypeId::of::()).map(|v| v.as_mut() as *mut dyn Any) }?; + let ptr_e = { map.get_mut(&TypeId::of::()).map(|v| v.as_mut() as *mut dyn Any) }?; + let ptr_f = { map.get_mut(&TypeId::of::()).map(|v| v.as_mut() as *mut dyn Any) }?; + let ptr_g = { map.get_mut(&TypeId::of::()).map(|v| v.as_mut() as *mut dyn Any) }?; unsafe { let a = (&mut *ptr_a).downcast_mut::()?; let b = (&mut *ptr_b).downcast_mut::()?; @@ -430,14 +430,14 @@ macro_rules! define_typemap { fn get_from_mut<'a>(map: &'a mut HashMap>) -> Option> { let ids = [TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::()]; for i in 0..ids.len() { for j in (i+1)..ids.len() { if ids[i] == ids[j] { return None; } } } - let ptr_a = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; - let ptr_b = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; - let ptr_c = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; - let ptr_d = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; - let ptr_e = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; - let ptr_f = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; - let ptr_g = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; - let ptr_h = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; + let ptr_a = { map.get_mut(&TypeId::of::()).map(|v| v.as_mut() as *mut dyn Any) }?; + let ptr_b = { map.get_mut(&TypeId::of::()).map(|v| v.as_mut() as *mut dyn Any) }?; + let ptr_c = { map.get_mut(&TypeId::of::()).map(|v| v.as_mut() as *mut dyn Any) }?; + let ptr_d = { map.get_mut(&TypeId::of::()).map(|v| v.as_mut() as *mut dyn Any) }?; + let ptr_e = { map.get_mut(&TypeId::of::()).map(|v| v.as_mut() as *mut dyn Any) }?; + let ptr_f = { map.get_mut(&TypeId::of::()).map(|v| v.as_mut() as *mut dyn Any) }?; + let ptr_g = { map.get_mut(&TypeId::of::()).map(|v| v.as_mut() as *mut dyn Any) }?; + let ptr_h = { map.get_mut(&TypeId::of::()).map(|v| v.as_mut() as *mut dyn Any) }?; unsafe { let a = (&mut *ptr_a).downcast_mut::()?; let b = (&mut *ptr_b).downcast_mut::()?; @@ -498,3 +498,47 @@ macro_rules! define_typemap { // Self::new() // } // } + +#[cfg(test)] +mod tests { + use crate::define_typemap; + + define_typemap!(TestMap,); + + #[test] + fn get_test() { + let mut tm = TestMap::new(); + tm.insert::(42); + let v = tm.get::().expect("value should be present"); + assert_eq!(*v, 42); + } + + #[test] + fn get_many_test() { + let mut tm = TestMap::new(); + tm.insert::(1); + tm.insert::(-2); + tm.insert::(3.5); + + let (a, b, c) = tm + .get_many::<(u32, i32, f32)>() + .expect("all values should be present"); + assert_eq!((*a, *b, *c), (1, -2, 3.5)); + } + + #[test] + fn get_many_mut_test() { + let mut tm = TestMap::new(); + + tm.insert::(-2); + tm.insert::(1); + tm.insert::(3.5); + + let (a, b, c) = tm + .get_many_mut::<(i32, u32, f32)>() + .expect("all values should be present"); + *a = 4; + *b = 5; + *c = 6.5; + } +} From 13aefcc86fb7e45afc9534b6cfac36147b3c056a Mon Sep 17 00:00:00 2001 From: reo Date: Sun, 16 Nov 2025 18:34:48 +0300 Subject: [PATCH 70/89] Remove imgui from the entire project --- Cargo.lock | 38 -------------------------- core/Cargo.toml | 1 - core/src/debug_ui.rs | 50 ---------------------------------- core/src/engine.rs | 3 -- core/src/lib.rs | 2 -- core/src/scene.rs | 7 ++--- engine/src/engine.rs | 11 +------- engine/src/system.rs | 2 -- game/src/main.rs | 2 +- game/src/systems/keybinds.rs | 16 +++++++---- glium_platform/src/platform.rs | 6 +--- glium_platform/src/system.rs | 3 +- 12 files changed, 16 insertions(+), 125 deletions(-) delete mode 100644 core/src/debug_ui.rs diff --git a/Cargo.lock b/Cargo.lock index 3e9b382..877142c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -331,12 +331,6 @@ dependencies = [ "libc", ] -[[package]] -name = "chlorine" -version = "1.0.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c00d31b1d19317b4777ec879192d3745bd97d05262b4b19cb1dda284b9d22f19" - [[package]] name = "clipboard-win" version = "5.4.1" @@ -1206,31 +1200,6 @@ dependencies = [ "zune-jpeg", ] -[[package]] -name = "imgui" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8addafa5cecf0515812226e806913814e02ce38d10215778082af5174abe5669" -dependencies = [ - "bitflags 1.3.2", - "cfg-if", - "imgui-sys", - "mint", - "parking_lot", -] - -[[package]] -name = "imgui-sys" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ead193f9f4b60398e8b8f4ab1483e2321640d87aeebdaa3e5f44c55633ccd804" -dependencies = [ - "cc", - "cfg-if", - "chlorine", - "mint", -] - [[package]] name = "indexmap" version = "2.10.0" @@ -1423,12 +1392,6 @@ dependencies = [ "simd-adler32", ] -[[package]] -name = "mint" -version = "0.5.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e53debba6bda7a793e5f99b8dacf19e626084f525f7829104ba9898f367d85ff" - [[package]] name = "moxcms" version = "0.7.5" @@ -2130,7 +2093,6 @@ version = "0.1.0" dependencies = [ "egui", "hecs", - "imgui", "indexmap", "raidillon_assets", "winit", diff --git a/core/Cargo.toml b/core/Cargo.toml index a8d650d..9b3f82f 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -8,5 +8,4 @@ hecs = "0.10.5" indexmap = "2.10.0" raidillon_assets = { path = "../asset" } winit = "0.30.12" -imgui = "0.12.0" egui = "0.33.2" \ No newline at end of file diff --git a/core/src/debug_ui.rs b/core/src/debug_ui.rs deleted file mode 100644 index df3b9f1..0000000 --- a/core/src/debug_ui.rs +++ /dev/null @@ -1,50 +0,0 @@ -pub enum UICommand { - Text(String), - Separator, - SliderF32 { label: String, min: f32, max: f32, value: std::rc::Rc> }, -} - -pub struct DebugUIBuffer { - cmds: Vec, -} - -impl DebugUIBuffer { - pub fn new() -> DebugUIBuffer { - DebugUIBuffer { cmds: vec![] } - } - - // Commands - pub fn text(&mut self, text: String) { - self.cmds.push(UICommand::Text(text)); - } - - pub fn separator(&mut self) { - self.cmds.push(UICommand::Separator); - } - - pub fn slider_f32>(&mut self, label: T, min: f32, max: f32, value: std::rc::Rc>) { - self.cmds.push(UICommand::SliderF32 { label: label.into(), min, max, value }); - } - // End of commands - - pub fn write_buffer(&self, ui: &imgui::Ui) { - for cmd in &self.cmds { - match cmd { - UICommand::Text(s) => { - ui.text(s); - } - UICommand::Separator => { - ui.separator(); - } - UICommand::SliderF32 { label, min, max, value } => { - let mut v = value.borrow_mut(); - ui.slider_config(label.as_str(), *min, *max).build(&mut *v); - } - } - } - } - - pub fn reset_buffer(&mut self) { - self.cmds = vec![]; - } -} diff --git a/core/src/engine.rs b/core/src/engine.rs index 1308e20..5890063 100644 --- a/core/src/engine.rs +++ b/core/src/engine.rs @@ -1,4 +1,3 @@ -use crate::DebugUIBuffer; use crate::scene::Scene; pub trait EngineTrait { @@ -10,6 +9,4 @@ pub trait EngineTrait { fn handle_event(&mut self, platform_context: Self::PlatformCtx); fn current_scene_mut(&mut self) -> &mut Scene; fn current_scene(&self) -> &Scene; - fn get_debug_ui_buffer(&self) -> &DebugUIBuffer; - fn reset_debug_ui_buffer(&mut self); } diff --git a/core/src/lib.rs b/core/src/lib.rs index 61f5286..759393d 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -1,9 +1,7 @@ pub mod engine; -pub mod debug_ui; pub mod time; pub mod utils; pub mod scene; mod egui_queue; -pub use debug_ui::*; pub use egui_queue::EguiQueue; diff --git a/core/src/scene.rs b/core/src/scene.rs index 1a075bf..2f748c4 100644 --- a/core/src/scene.rs +++ b/core/src/scene.rs @@ -1,6 +1,6 @@ use std::collections::HashMap; use std::path::{Path, PathBuf}; -use crate::{define_typemap, DebugUIBuffer}; +use crate::{define_typemap}; pub struct Scene { pub title: String, @@ -23,10 +23,7 @@ impl Scene { s } - pub fn load_default_resources(&mut self) { - let dbg = DebugUIBuffer::new(); - self.resources.insert(dbg); - } + pub fn load_default_resources(&mut self) {} } impl Scene {} diff --git a/engine/src/engine.rs b/engine/src/engine.rs index 398920c..ec9841f 100644 --- a/engine/src/engine.rs +++ b/engine/src/engine.rs @@ -3,7 +3,7 @@ use std::rc::Rc; use raidillon_core::scene::{Scene, SceneManager}; use crate::system::{SystemContext, SystemManager}; use raidillon_platform::PlatformContext; -use raidillon_core::{define_typemap, DebugUIBuffer}; +use raidillon_core::{define_typemap}; use raidillon_core::engine::EngineTrait; use crate::input::InputState; use crate::resources::EngineResources; @@ -50,7 +50,6 @@ impl EngineTrait for Engine { /// Update the engine fn frame_update(&mut self, platform_context: PlatformContext) { - self.scene_manager.current_mut().resources.get_mut::().unwrap().reset_buffer(); self.resources.insert(platform_context); for system in self.system_manager.systems.values_mut() { @@ -86,12 +85,4 @@ impl EngineTrait for Engine { fn current_scene(&self) -> &Scene { self.scene_manager.current() } - - fn get_debug_ui_buffer(&self) -> &DebugUIBuffer { - self.scene_manager.current().resources.get::().unwrap() - } - - fn reset_debug_ui_buffer(&mut self) { - self.scene_manager.current_mut().resources.get_mut::().unwrap().reset_buffer(); - } } diff --git a/engine/src/system.rs b/engine/src/system.rs index 55cccb1..420da1b 100644 --- a/engine/src/system.rs +++ b/engine/src/system.rs @@ -1,6 +1,5 @@ use indexmap::IndexMap; use raidillon_core::scene::Scene; -use raidillon_core::DebugUIBuffer; use raidillon_platform::PlatformContext; use std::any::TypeId; use std::cell::RefCell; @@ -11,7 +10,6 @@ use crate::resources::EngineResources; pub struct SystemContext<'a> { pub scene: &'a mut Scene, pub platform_context: PlatformContext, - pub debug_ui_buffer: Rc>, pub input_state: Rc>, } diff --git a/game/src/main.rs b/game/src/main.rs index 42ab2d3..e81d77c 100644 --- a/game/src/main.rs +++ b/game/src/main.rs @@ -16,7 +16,7 @@ use raidillon_glium::GliumPlatform; use winit::event::{ElementState, Event, WindowEvent}; use winit::event::DeviceEvent::MouseMotion; use winit::keyboard::{KeyCode, PhysicalKey}; -use raidillon_core::{DebugUIBuffer, EguiQueue}; +use raidillon_core::{EguiQueue}; use systems::debug_camera::FPSDebugCameraSystem; use raidillon_glium::RenderingSystem; use raidillon_physics::Physics; diff --git a/game/src/systems/keybinds.rs b/game/src/systems/keybinds.rs index e701dad..10bbbe8 100644 --- a/game/src/systems/keybinds.rs +++ b/game/src/systems/keybinds.rs @@ -1,5 +1,4 @@ use winit::keyboard::KeyCode; -use raidillon_core::DebugUIBuffer; use raidillon_core::scene::Scene; use raidillon_ecs::components::CameraMode; use raidillon_engine::{EngineResources, InputState}; @@ -24,16 +23,21 @@ impl System for KeybindsSystem { } fn frame_update(&mut self, res: &mut EngineResources, scene: &mut Scene) { - let dbg_ui = scene.resources.get_mut::().unwrap(); - - dbg_ui.text("F5 to switch camera".to_owned()); - + let pctx = res.get_mut::().unwrap(); 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)); + + let cam_mode_str = format!("Camera Mode: {:?}", cam_mode); + + pctx.egui_queue.borrow_mut().queue(move |egui_ctx| { + egui::Window::new("Camera").show(egui_ctx, |ui| { + ui.label("F5 to switch camera"); + ui.label(cam_mode_str); + }); + }); } } diff --git a/glium_platform/src/platform.rs b/glium_platform/src/platform.rs index efc1543..1b1ba08 100644 --- a/glium_platform/src/platform.rs +++ b/glium_platform/src/platform.rs @@ -103,17 +103,13 @@ impl> Platform for GliumPlatfor WindowEvent::RedrawRequested => { let mut target = self.display.draw(); target.clear_color_and_depth((0.1, 0.1, 0.15, 1.0), 1.0); - let (scene, debug_ui_buffer) = ( - self.engine.current_scene(), - self.engine.get_debug_ui_buffer(), - ); + let scene = self.engine.current_scene(); let mut context = RenderingContext { scene, target: &mut target, display: &self.display, asset_manager: self.asset_manager.clone(), window: self.window.clone(), - debug_ui_buffer, egui_queue: self.egui_queue.clone(), env_light_dir: Vec3::new(0.0, -1.0, 0.0), }; diff --git a/glium_platform/src/system.rs b/glium_platform/src/system.rs index 5d7f197..d94e9c3 100644 --- a/glium_platform/src/system.rs +++ b/glium_platform/src/system.rs @@ -6,7 +6,7 @@ use indexmap::IndexMap; use glium::{Display, Frame}; use glium::glutin::surface::WindowSurface; use raidillon_assets::ModelManagerRef; -use raidillon_core::{define_typemap, DebugUIBuffer, EguiQueue}; +use raidillon_core::{define_typemap, EguiQueue}; use raidillon_core::scene::Scene; use glam::Vec3; use winit::event_loop::EventLoop; @@ -17,7 +17,6 @@ pub struct RenderingContext<'a> { pub window: Arc>, pub display: &'a Display, pub asset_manager: ModelManagerRef, - pub debug_ui_buffer: &'a DebugUIBuffer, pub egui_queue: Rc>, pub env_light_dir: Vec3, } From db1b427e2ae2f905f1b0413953370d97fb027f9a Mon Sep 17 00:00:00 2001 From: reo Date: Sun, 19 Oct 2025 17:40:51 +0300 Subject: [PATCH 71/89] Physics Support - NEW CRATE: raidillon_physics. - Added new models to be able to test the physics support. - Added a new system "PhysicsSystem" to apply physics calculations to the ECS world. - NEW COMPONENT: RigidBodyComponent --- Cargo.lock | 521 +++++++++++++++++++++++++++++++++++- Cargo.toml | 1 + assets/models/plane.glb | 3 + assets/models/sphere.glb | 3 + ecs/Cargo.toml | 1 + ecs/src/components.rs | 3 + game/Cargo.toml | 2 + game/src/main.rs | 75 +++--- game/src/systems/mod.rs | 3 + game/src/systems/physics.rs | 34 +++ physics/Cargo.toml | 9 + physics/src/lib.rs | 3 + physics/src/physics.rs | 82 ++++++ 13 files changed, 697 insertions(+), 43 deletions(-) create mode 100644 assets/models/plane.glb create mode 100644 assets/models/sphere.glb create mode 100644 game/src/systems/mod.rs create mode 100644 game/src/systems/physics.rs create mode 100644 physics/Cargo.toml create mode 100644 physics/src/lib.rs create mode 100644 physics/src/physics.rs diff --git a/Cargo.lock b/Cargo.lock index e1b6adb..525e6ad 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -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,15 +1785,16 @@ 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", @@ -1457,13 +1807,15 @@ dependencies = [ name = "raidillon_game" version = "0.1.0" dependencies = [ - "glam", + "glam 0.30.8", "raidillon_assets", "raidillon_core", "raidillon_ecs", "raidillon_engine", "raidillon_glium", + "raidillon_physics", "raidillon_platform", + "rapier3d", "winit", ] @@ -1473,7 +1825,7 @@ version = "0.1.0" dependencies = [ "anyhow", "exr", - "glam", + "glam 0.30.8", "glium", "gltf", "image", @@ -1489,22 +1841,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 +1925,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 +1992,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 +2073,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 +2118,7 @@ dependencies = [ "log", "memmap2", "rustix 0.38.44", - "thiserror", + "thiserror 1.0.69", "wayland-backend", "wayland-client", "wayland-csd-frame", @@ -1701,12 +2138,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 +2191,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 +2214,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 +2289,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 +2416,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 +2538,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" diff --git a/Cargo.toml b/Cargo.toml index 23332d0..dd544ab 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,4 +7,5 @@ members = [ "game", "ecs", "engine", + "physics", ] diff --git a/assets/models/plane.glb b/assets/models/plane.glb new file mode 100644 index 0000000..e755152 --- /dev/null +++ b/assets/models/plane.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b54f00f327a5edc76c03f83d4efa2a4400215d7ca9c961b38537e7f836bca710 +size 1240 diff --git a/assets/models/sphere.glb b/assets/models/sphere.glb new file mode 100644 index 0000000..ea99045 --- /dev/null +++ b/assets/models/sphere.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:78583ec562098f7fa4eaf95c6e21b7d1ced53416eb4c71351e246d53f93aa0a3 +size 24744 diff --git a/ecs/Cargo.toml b/ecs/Cargo.toml index 0e1efb5..a47173d 100644 --- a/ecs/Cargo.toml +++ b/ecs/Cargo.toml @@ -6,3 +6,4 @@ edition = "2024" [dependencies] glam = "0.30.5" raidillon_assets = { path = "../asset" } +rapier3d = "0.30.1" diff --git a/ecs/src/components.rs b/ecs/src/components.rs index 758f0f4..fa30cc2 100644 --- a/ecs/src/components.rs +++ b/ecs/src/components.rs @@ -15,3 +15,6 @@ impl Transform { } pub struct ModelHandle(pub ModelID); + +#[derive(Copy, Clone)] +pub struct RigidBodyComponent(pub rapier3d::dynamics::RigidBodyHandle); diff --git a/game/Cargo.toml b/game/Cargo.toml index 484e434..9bb72c4 100644 --- a/game/Cargo.toml +++ b/game/Cargo.toml @@ -13,6 +13,8 @@ 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" diff --git a/game/src/main.rs b/game/src/main.rs index ad230cf..8ddce6a 100644 --- a/game/src/main.rs +++ b/game/src/main.rs @@ -1,11 +1,14 @@ +mod systems; use std::fmt::format; use glam::{Quat, Vec3}; +use rapier3d::dynamics::RigidBodyType; +use rapier3d::prelude::ColliderBuilder; use raidillon_engine::{Engine, system::System, EngineResources}; 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::{ModelHandle, RigidBodyComponent}; use raidillon_ecs::Transform; use raidillon_core::scene::Scene; #[cfg(feature = "glium")] @@ -15,9 +18,11 @@ use winit::event::DeviceEvent::MouseMotion; use winit::keyboard::{KeyCode, PhysicalKey}; use raidillon_core::DebugUIBuffer; use raidillon_engine::systems::fps_camera::FPSDebugCameraSystem; +use raidillon_physics::Physics; +use crate::systems::PhysicsSystem; -const TEST_GLTF: &str = "pink-monkey.gltf"; - +const TEST_GLTF: &str = "sphere.glb"; +const PLANE_GLTF: &str = "plane.glb"; const MAIN_SCENE_ID: &str = "main_scene"; #[derive(Default)] @@ -40,28 +45,45 @@ impl System for UpdateAspectRatioSystem { } #[derive(Default)] -struct RenderingTestSystem { - rotation_speed: std::rc::Rc>, -} +struct RenderingTestSystem; impl System for RenderingTestSystem { fn load_world(&mut self, res: &mut EngineResources, scene: &mut Scene) { - let pctx = res.get::().unwrap(); + let pctx = res.get::().expect("PlatformContext missing").clone(); + let physics = res.get_mut::().expect("Physics missing"); - self.rotation_speed = std::rc::Rc::new(std::cell::RefCell::new(5.0)); - - 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), - )); + // 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).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), + )); + } } fn frame_update(&mut self, res: &mut EngineResources, scene: &mut Scene) { @@ -72,22 +94,13 @@ impl System for RenderingTestSystem { 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()); } - - fn fixed_update(&mut self, res: &mut EngineResources, scene: &mut Scene) { - let pctx = res.get::().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::(); engine.system_manager.add::(); engine.system_manager.add::(); engine.system_manager.add::(); diff --git a/game/src/systems/mod.rs b/game/src/systems/mod.rs new file mode 100644 index 0000000..0ab4645 --- /dev/null +++ b/game/src/systems/mod.rs @@ -0,0 +1,3 @@ +mod physics; + +pub use physics::PhysicsSystem; diff --git a/game/src/systems/physics.rs b/game/src/systems/physics.rs new file mode 100644 index 0000000..c5d4807 --- /dev/null +++ b/game/src/systems/physics.rs @@ -0,0 +1,34 @@ +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; + +#[derive(Default)] +pub struct PhysicsSystem; + +impl System for PhysicsSystem { + fn load_world(&mut self, res: &mut EngineResources, scene: &mut Scene) { + let p = Physics::default(); + res.insert(p); + } + + fn fixed_update(&mut self, res: &mut EngineResources, scene: &mut Scene) { + let pctx = res.get::().expect("PlatformContext missing").clone(); + let physics = res.get_mut::().expect("Physics missing"); + physics.step(pctx.time_ctx.fixed_dt); + + 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; + } + } + } +} diff --git a/physics/Cargo.toml b/physics/Cargo.toml new file mode 100644 index 0000000..dc34e98 --- /dev/null +++ b/physics/Cargo.toml @@ -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" \ No newline at end of file diff --git a/physics/src/lib.rs b/physics/src/lib.rs new file mode 100644 index 0000000..a5dafc6 --- /dev/null +++ b/physics/src/lib.rs @@ -0,0 +1,3 @@ +mod physics; + +pub use crate::physics::Physics; diff --git a/physics/src/physics.rs b/physics/src/physics.rs new file mode 100644 index 0000000..009984c --- /dev/null +++ b/physics/src/physics.rs @@ -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 { + rigid_body_set: RigidBodySet, + collider_set: ColliderSet, + physics_pipeline: PhysicsPipeline, + island_manager: IslandManager, + broad_phase: DefaultBroadPhase, + narrow_phase: NarrowPhase, + impulse_joint_set: ImpulseJointSet, + multibody_joint_set: MultibodyJointSet, + ccd_solver: CCDSolver, + gravity: Vector, + 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) -> Vec3 { + Vec3::new(v.x, v.y, v.z) + } + + pub fn rapier_rotation_to_glam(r: &UnitQuaternion) -> Quat { + Quat::from_xyzw(r.i, r.j, r.k, r.w) + } +} From f503c70a9ba89dc2730a9de5ec0761cb569ef9f0 Mon Sep 17 00:00:00 2001 From: reo Date: Sun, 26 Oct 2025 18:29:59 +0300 Subject: [PATCH 72/89] MASSIVE Kinematic Character Controller Update - NEW kinematic character controller powered by rapier3d at kinematic_character_controller.rs - NEW camera modes. The ability to switch between the free debug camera and new character controller. - NEW keybinds system to support the camera mode swap --- Cargo.lock | 2 + ecs/src/components.rs | 10 + engine/Cargo.toml | 1 + engine/src/lib.rs | 1 + engine/src/systems/fps_camera.rs | 29 +-- game/Cargo.toml | 1 + game/src/main.rs | 35 ++- game/src/systems/keybinds.rs | 52 +++++ .../systems/kinematic_character_controller.rs | 200 ++++++++++++++++++ game/src/systems/mod.rs | 4 + game/src/systems/physics.rs | 6 +- physics/src/physics.rs | 8 +- 12 files changed, 323 insertions(+), 26 deletions(-) create mode 100644 game/src/systems/keybinds.rs create mode 100644 game/src/systems/kinematic_character_controller.rs diff --git a/Cargo.lock b/Cargo.lock index 525e6ad..91f50f1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1799,6 +1799,7 @@ dependencies = [ "indexmap", "raidillon_assets", "raidillon_core", + "raidillon_ecs", "raidillon_platform", "winit", ] @@ -1808,6 +1809,7 @@ name = "raidillon_game" version = "0.1.0" dependencies = [ "glam 0.30.8", + "hecs", "raidillon_assets", "raidillon_core", "raidillon_ecs", diff --git a/ecs/src/components.rs b/ecs/src/components.rs index fa30cc2..3c20ec7 100644 --- a/ecs/src/components.rs +++ b/ecs/src/components.rs @@ -18,3 +18,13 @@ 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, +} diff --git a/engine/Cargo.toml b/engine/Cargo.toml index 98202e4..79a2de9 100644 --- a/engine/Cargo.toml +++ b/engine/Cargo.toml @@ -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" diff --git a/engine/src/lib.rs b/engine/src/lib.rs index 9a87556..a7ad724 100644 --- a/engine/src/lib.rs +++ b/engine/src/lib.rs @@ -6,3 +6,4 @@ mod resources; pub use crate::engine::Engine; pub use crate::resources::EngineResources; +pub use input::InputState; diff --git a/engine/src/systems/fps_camera.rs b/engine/src/systems/fps_camera.rs index 0d98577..5ff9cc7 100644 --- a/engine/src/systems/fps_camera.rs +++ b/engine/src/systems/fps_camera.rs @@ -9,6 +9,7 @@ use raidillon_platform::{Camera, PlatformContext}; use crate::input::InputState; use crate::resources::EngineResources; use raidillon_core::scene::Scene; +use raidillon_ecs::components::CameraMode; pub struct FPSDebugCameraSystem { mouse_delta: (f64, f64), @@ -35,20 +36,10 @@ impl Default for FPSDebugCameraSystem { } impl System for FPSDebugCameraSystem { - fn load_world(&mut self, res: &mut EngineResources, scene: &mut Scene) { - let pctx = res.get::().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::().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 + } } diff --git a/game/Cargo.toml b/game/Cargo.toml index 9bb72c4..9579d22 100644 --- a/game/Cargo.toml +++ b/game/Cargo.toml @@ -18,3 +18,4 @@ raidillon_glium = { path = "../glium_platform", optional = true } glam = "0.30.5" winit = "0.30.12" rapier3d = "0.30.1" +hecs = "0.10.5" diff --git a/game/src/main.rs b/game/src/main.rs index 8ddce6a..a5a3d9c 100644 --- a/game/src/main.rs +++ b/game/src/main.rs @@ -1,14 +1,14 @@ mod systems; use std::fmt::format; use glam::{Quat, Vec3}; -use rapier3d::dynamics::RigidBodyType; +use rapier3d::dynamics::{CoefficientCombineRule, RigidBodyType}; use rapier3d::prelude::ColliderBuilder; -use raidillon_engine::{Engine, system::System, EngineResources}; +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, RigidBodyComponent}; +use raidillon_ecs::components::{CameraMode, CharacterBodyComponent, ModelHandle, RigidBodyComponent}; use raidillon_ecs::Transform; use raidillon_core::scene::Scene; #[cfg(feature = "glium")] @@ -18,8 +18,9 @@ use winit::event::DeviceEvent::MouseMotion; use winit::keyboard::{KeyCode, PhysicalKey}; use raidillon_core::DebugUIBuffer; use raidillon_engine::systems::fps_camera::FPSDebugCameraSystem; +use raidillon_glium::RenderingSystem; use raidillon_physics::Physics; -use crate::systems::PhysicsSystem; +use crate::systems::{KeybindsSystem, KinematicCharacterController, PhysicsSystem}; const TEST_GLTF: &str = "sphere.glb"; const PLANE_GLTF: &str = "plane.glb"; @@ -50,7 +51,7 @@ struct RenderingTestSystem; impl System for RenderingTestSystem { fn load_world(&mut self, res: &mut EngineResources, scene: &mut Scene) { let pctx = res.get::().expect("PlatformContext missing").clone(); - let physics = res.get_mut::().expect("Physics missing"); + let physics = scene.resources.get_mut::().expect("Physics missing"); // Spawn Sphere { @@ -59,7 +60,10 @@ impl System for RenderingTestSystem { rotation: Quat::IDENTITY, scale: Vec3::new(1.0, 1.0, 1.0), }; - let collider = ColliderBuilder::ball(1.0).build(); + 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(( @@ -84,16 +88,32 @@ impl System for RenderingTestSystem { RigidBodyComponent(rb_handle), )); } + + 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::().unwrap(); + let input = res.get::().unwrap(); let dbg_ui = scene.resources.get_mut::().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)); + + for (_ent, (tr, ch_component)) in scene.world.query::<(&Transform, &CharacterBodyComponent)>().iter() { + dbg_ui.text(format!("Character POS: {}", tr.translation)); + } } } @@ -101,7 +121,8 @@ fn main() { let mut engine = Engine::new(); // Define systems engine.system_manager.add::(); - engine.system_manager.add::(); + engine.system_manager.add::(); + engine.system_manager.add::(); engine.system_manager.add::(); engine.system_manager.add::(); // engine.system_manager.add::(); diff --git a/game/src/systems/keybinds.rs b/game/src/systems/keybinds.rs new file mode 100644 index 0000000..6bc3e70 --- /dev/null +++ b/game/src/systems/keybinds.rs @@ -0,0 +1,52 @@ +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; + +#[derive(Default)] +pub struct KeybindsSystem; + +impl System for KeybindsSystem { + fn fixed_update(&mut self, res: &mut EngineResources, scene: &mut Scene) { + let input = res.get::().unwrap(); + + if input.key_held(KeyCode::F5) { + self.toggle_camera_mode(scene); + } + } + + fn frame_update(&mut self, res: &mut EngineResources, scene: &mut Scene) { + let dbg_ui = scene.resources.get_mut::().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; + } + } + } +} diff --git a/game/src/systems/kinematic_character_controller.rs b/game/src/systems/kinematic_character_controller.rs new file mode 100644 index 0000000..4608e67 --- /dev/null +++ b/game/src/systems/kinematic_character_controller.rs @@ -0,0 +1,200 @@ +use glam::{Quat, Vec3}; +use hecs::Entity; +use rapier3d::prelude::{nalgebra, ColliderBuilder, QueryFilter, QueryPipeline, 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::math::Isometry; +use rapier3d::na::{Isometry3, Vector3}; +use winit::event::DeviceEvent::MouseMotion; +use winit::event::{ElementState, Event, MouseButton, WindowEvent}; +use winit::keyboard::KeyCode; +use winit::window::CursorGrabMode; +use raidillon_core::DebugUIBuffer; +use raidillon_ecs::components::{CameraMode, CharacterBodyComponent}; +use raidillon_ecs::Transform; +use raidillon_engine::systems::fps_camera::FPSDebugCameraSystem; +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, + 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::().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::().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::().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 + } +} diff --git a/game/src/systems/mod.rs b/game/src/systems/mod.rs index 0ab4645..f975aff 100644 --- a/game/src/systems/mod.rs +++ b/game/src/systems/mod.rs @@ -1,3 +1,7 @@ mod physics; +mod kinematic_character_controller; +mod keybinds; pub use physics::PhysicsSystem; +pub use kinematic_character_controller::KinematicCharacterController; +pub use keybinds::KeybindsSystem; diff --git a/game/src/systems/physics.rs b/game/src/systems/physics.rs index c5d4807..a77c75c 100644 --- a/game/src/systems/physics.rs +++ b/game/src/systems/physics.rs @@ -6,20 +6,22 @@ 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(); - res.insert(p); + scene.resources.insert(p); } fn fixed_update(&mut self, res: &mut EngineResources, scene: &mut Scene) { let pctx = res.get::().expect("PlatformContext missing").clone(); - let physics = res.get_mut::().expect("Physics missing"); + let physics = scene.resources.get_mut::().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) { diff --git a/physics/src/physics.rs b/physics/src/physics.rs index 009984c..5eff699 100644 --- a/physics/src/physics.rs +++ b/physics/src/physics.rs @@ -5,12 +5,12 @@ use raidillon_ecs::Transform; /// Tiny wrapper around rapier3d. pub struct Physics { - rigid_body_set: RigidBodySet, - collider_set: ColliderSet, + pub rigid_body_set: RigidBodySet, + pub collider_set: ColliderSet, physics_pipeline: PhysicsPipeline, island_manager: IslandManager, - broad_phase: DefaultBroadPhase, - narrow_phase: NarrowPhase, + pub broad_phase: DefaultBroadPhase, + pub narrow_phase: NarrowPhase, impulse_joint_set: ImpulseJointSet, multibody_joint_set: MultibodyJointSet, ccd_solver: CCDSolver, From 0af3b41293ef5663cb8752feaff53ae6fed347c5 Mon Sep 17 00:00:00 2001 From: reo Date: Wed, 29 Oct 2025 21:35:55 +0300 Subject: [PATCH 73/89] Move debug_camera to the game crate, activate FPSDebugCameraSystem --- engine/src/systems/mod.rs | 1 - game/src/main.rs | 3 ++- .../fps_camera.rs => game/src/systems/debug_camera.rs | 8 ++++---- game/src/systems/mod.rs | 1 + 4 files changed, 7 insertions(+), 6 deletions(-) rename engine/src/systems/fps_camera.rs => game/src/systems/debug_camera.rs (96%) diff --git a/engine/src/systems/mod.rs b/engine/src/systems/mod.rs index 8489571..e69de29 100644 --- a/engine/src/systems/mod.rs +++ b/engine/src/systems/mod.rs @@ -1 +0,0 @@ -pub mod fps_camera; diff --git a/game/src/main.rs b/game/src/main.rs index a5a3d9c..99eb0e2 100644 --- a/game/src/main.rs +++ b/game/src/main.rs @@ -17,7 +17,7 @@ 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; +use systems::debug_camera::FPSDebugCameraSystem; use raidillon_glium::RenderingSystem; use raidillon_physics::Physics; use crate::systems::{KeybindsSystem, KinematicCharacterController, PhysicsSystem}; @@ -123,6 +123,7 @@ fn main() { engine.system_manager.add::(); engine.system_manager.add::(); engine.system_manager.add::(); + engine.system_manager.add::(); engine.system_manager.add::(); engine.system_manager.add::(); // engine.system_manager.add::(); diff --git a/engine/src/systems/fps_camera.rs b/game/src/systems/debug_camera.rs similarity index 96% rename from engine/src/systems/fps_camera.rs rename to game/src/systems/debug_camera.rs index 5ff9cc7..13cb971 100644 --- a/engine/src/systems/fps_camera.rs +++ b/game/src/systems/debug_camera.rs @@ -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,8 +6,8 @@ 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; @@ -29,7 +29,7 @@ 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, } } diff --git a/game/src/systems/mod.rs b/game/src/systems/mod.rs index f975aff..2a387b1 100644 --- a/game/src/systems/mod.rs +++ b/game/src/systems/mod.rs @@ -1,6 +1,7 @@ mod physics; mod kinematic_character_controller; mod keybinds; +pub mod debug_camera; pub use physics::PhysicsSystem; pub use kinematic_character_controller::KinematicCharacterController; From 445d90b1a5ff2ca191c6a593a7026bb34207858a Mon Sep 17 00:00:00 2001 From: reo Date: Wed, 29 Oct 2025 21:36:38 +0300 Subject: [PATCH 74/89] Optimize imports of kinematic_character_controller.rs --- game/src/systems/kinematic_character_controller.rs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/game/src/systems/kinematic_character_controller.rs b/game/src/systems/kinematic_character_controller.rs index 4608e67..e3fc099 100644 --- a/game/src/systems/kinematic_character_controller.rs +++ b/game/src/systems/kinematic_character_controller.rs @@ -1,21 +1,16 @@ use glam::{Quat, Vec3}; -use hecs::Entity; -use rapier3d::prelude::{nalgebra, ColliderBuilder, QueryFilter, QueryPipeline, RigidBodyBuilder}; +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::math::Isometry; use rapier3d::na::{Isometry3, Vector3}; use winit::event::DeviceEvent::MouseMotion; -use winit::event::{ElementState, Event, MouseButton, WindowEvent}; +use winit::event::Event; use winit::keyboard::KeyCode; -use winit::window::CursorGrabMode; -use raidillon_core::DebugUIBuffer; use raidillon_ecs::components::{CameraMode, CharacterBodyComponent}; use raidillon_ecs::Transform; -use raidillon_engine::systems::fps_camera::FPSDebugCameraSystem; use raidillon_physics::Physics; use raidillon_platform::{Camera, PlatformContext}; From c431ebf74522cdf6cee8d034c5f4d9ac5f2c75b3 Mon Sep 17 00:00:00 2001 From: reo Date: Wed, 29 Oct 2025 21:37:49 +0300 Subject: [PATCH 75/89] Tweak keybinds.rs to make camera mode toggle smoother --- game/src/systems/keybinds.rs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/game/src/systems/keybinds.rs b/game/src/systems/keybinds.rs index 6bc3e70..e701dad 100644 --- a/game/src/systems/keybinds.rs +++ b/game/src/systems/keybinds.rs @@ -4,17 +4,22 @@ use raidillon_core::scene::Scene; use raidillon_ecs::components::CameraMode; use raidillon_engine::{EngineResources, InputState}; use raidillon_engine::system::System; -use raidillon_platform::Camera; +use raidillon_platform::{Camera, PlatformContext}; #[derive(Default)] -pub struct KeybindsSystem; +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::().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; } } From 82f3b277325bc48bb53688b9220232596fe73f14 Mon Sep 17 00:00:00 2001 From: reo Date: Sun, 16 Nov 2025 18:42:45 +0300 Subject: [PATCH 76/89] Regenerate cargo.lock --- Cargo.lock | 558 +++++++++++++++++++++++++---------------------------- 1 file changed, 268 insertions(+), 290 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 877142c..7791e88 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -14,15 +14,15 @@ dependencies = [ [[package]] name = "ab_glyph_rasterizer" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2187590a23ab1e3df8681afdf0987c48504d80291f002fcdb651f0ef5e25169" +checksum = "366ffbaa4442f4684d91e2cd7c5ea7c4ed8add41959a31447066e279e432b618" [[package]] name = "addr2line" -version = "0.24.2" +version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" +checksum = "1b5d307320b3181d6d7954e663bd7c774a838b8220fe0593c86d9fb09f498b4b" dependencies = [ "gimli", ] @@ -81,9 +81,9 @@ checksum = "fc7eb209b1518d6bb87b283c20095f5228ecda460da70b44f0802523dea6da04" [[package]] name = "anyhow" -version = "1.0.99" +version = "1.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0674a1ddeecb70197781e945de4b3b8ffb61fa939a5597bcf48503737663100" +checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" [[package]] name = "approx" @@ -104,10 +104,10 @@ dependencies = [ "image", "log", "objc2 0.6.3", - "objc2-app-kit 0.3.1", + "objc2-app-kit 0.3.2", "objc2-core-foundation", "objc2-core-graphics", - "objc2-foundation 0.3.1", + "objc2-foundation 0.3.2", "parking_lot", "percent-encoding", "windows-sys 0.60.2", @@ -146,9 +146,9 @@ checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "backtrace" -version = "0.3.75" +version = "0.3.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" +checksum = "bb531853791a215d7c62a30daf0dde835f381ab5de4589cfe7c649d2cbe92bd6" dependencies = [ "addr2line", "cfg-if", @@ -156,7 +156,7 @@ dependencies = [ "miniz_oxide", "object", "rustc-demangle", - "windows-targets 0.52.6", + "windows-link", ] [[package]] @@ -238,9 +238,9 @@ checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" [[package]] name = "bytes" -version = "1.10.1" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" +checksum = "b35204fbdc0b3f4446b89fc1ac2cf84a8a68971995d0bf2e925ec7cd960f9cb3" [[package]] name = "calloop" @@ -264,7 +264,7 @@ checksum = "cb9f6e1368bd4621d2c86baa7e37de77a938adf5221e5dd3d6133340101b309e" dependencies = [ "bitflags 2.10.0", "polling", - "rustix 1.0.8", + "rustix 1.1.2", "slab", "tracing", ] @@ -288,17 +288,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "138efcf0940a02ebf0cc8d1eff41a1682a46b431630f4c52450d6265876021fa" dependencies = [ "calloop 0.14.3", - "rustix 1.0.8", + "rustix 1.1.2", "wayland-backend", "wayland-client", ] [[package]] name = "cc" -version = "1.2.31" +version = "1.2.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3a42d84bb6b69d3a8b3eaacf0d88f179e1929695e1ad012b6cf64d9caaa5fd2" +checksum = "b97463e1064cb1b1c1384ad0a0b9c8abd0988e2a91f52606c80ef14aadb63e36" dependencies = [ + "find-msvc-tools", "jobserver", "libc", "shlex", @@ -312,9 +313,9 @@ checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" [[package]] name = "cfg-if" -version = "1.0.1" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] name = "cfg_aliases" @@ -628,12 +629,12 @@ checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "errno" -version = "0.3.13" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -644,9 +645,9 @@ checksum = "dea2df4cf52843e0452895c455a1a2cfbb842a1e7329671acf418fdc53ed4c59" [[package]] name = "exr" -version = "1.73.0" +version = "1.74.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f83197f59927b46c04a183a619b7c29df34e63e63c7869320862268c0ef687e0" +checksum = "4300e043a56aa2cb633c01af81ca8f699a321879a7854d3896a0ba89056363be" dependencies = [ "bit_field", "half", @@ -687,10 +688,16 @@ dependencies = [ ] [[package]] -name = "flate2" -version = "1.1.2" +name = "find-msvc-tools" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a3d7db9596fecd151c5f638c0ee5d5bd487b6e0ea232e5dc96d5250f6f94b1d" +checksum = "3a3076410a55c90011c298b04d0cfa770b00fa04e1e3c97d3f6c9de105a03844" + +[[package]] +name = "flate2" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfe33edd8e85a12a67454e37f8c75e730830d83e313556ab9ebf9ee7fbeb3bfb" dependencies = [ "crc32fast", "miniz_oxide", @@ -752,31 +759,31 @@ dependencies = [ [[package]] name = "gethostname" -version = "0.4.3" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0176e0459c2e4a1fe232f984bca6890e681076abb9934f6cea7c326f3fc47818" +checksum = "1bd49230192a3797a9a4d6abe9b3eed6f7fa4c8a8a4947977c6f80025f92cbd8" dependencies = [ - "libc", - "windows-targets 0.48.5", + "rustix 1.1.2", + "windows-link", ] [[package]] name = "getrandom" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" dependencies = [ "cfg-if", "libc", "r-efi", - "wasi", + "wasip2", ] [[package]] name = "gimli" -version = "0.31.1" +version = "0.32.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" +checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7" [[package]] name = "gl_generator" @@ -881,9 +888,9 @@ checksum = "8babf46d4c1c9d92deac9f7be466f76dfc4482b6452fc5024b5e8daf6ffeb3ee" [[package]] name = "glam" -version = "0.30.8" +version = "0.30.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e12d847aeb25f41be4c0ec9587d624e9cd631bc007a8fd7ce3f5851e064c6460" +checksum = "bd47b05dddf0005d850e5644cae7f2b14ac3df487979dbfff3b56f20b1a6ae46" [[package]] name = "glium" @@ -956,9 +963,9 @@ dependencies = [ "glutin_wgl_sys", "libloading", "objc2 0.6.3", - "objc2-app-kit 0.3.1", + "objc2-app-kit 0.3.2", "objc2-core-foundation", - "objc2-foundation 0.3.1", + "objc2-foundation 0.3.2", "once_cell", "raw-window-handle", "wayland-sys", @@ -1009,12 +1016,13 @@ dependencies = [ [[package]] name = "half" -version = "2.6.0" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "459196ed295495a68f7d7fe1d84f6c4b7ff0e21fe3017b2f283c6fac3ad803c9" +checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" dependencies = [ "cfg-if", "crunchy", + "zerocopy", ] [[package]] @@ -1037,9 +1045,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.15.4" +version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" dependencies = [ "allocator-api2", "equivalent", @@ -1185,9 +1193,9 @@ dependencies = [ [[package]] name = "image" -version = "0.25.8" +version = "0.25.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "529feb3e6769d234375c4cf1ee2ce713682b8e76538cb13f9fc23e1400a591e7" +checksum = "e6506c6c10786659413faa717ceebcb8f70731c0a60cbae39795fdf114519c1a" dependencies = [ "bytemuck", "byteorder-lite", @@ -1196,18 +1204,18 @@ dependencies = [ "num-traits", "png", "tiff", - "zune-core", - "zune-jpeg", + "zune-core 0.5.0", + "zune-jpeg 0.5.5", ] [[package]] name = "indexmap" -version = "2.10.0" +version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe4cd85333e22411419a0bcae1297d25e58c9443848b11dc6a86fefe8c78a661" +checksum = "6717a8d2a5a929a1a2eb43a12812498ed141a0bcfb7e8f7844fbdbe4303bba9f" dependencies = [ "equivalent", - "hashbrown 0.15.4", + "hashbrown 0.16.0", ] [[package]] @@ -1246,9 +1254,9 @@ checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" [[package]] name = "jobserver" -version = "0.1.33" +version = "0.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a" +checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" dependencies = [ "getrandom", "libc", @@ -1256,9 +1264,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.77" +version = "0.3.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" +checksum = "b011eec8cc36da2aab2d5cff675ec18454fad408585853910a202391cf9f8e65" dependencies = [ "once_cell", "wasm-bindgen", @@ -1284,18 +1292,18 @@ checksum = "7a79a3332a6609480d7d0c9eab957bca6b455b91bb84e66d19f5ff66294b85b8" [[package]] name = "libc" -version = "0.2.174" +version = "0.2.177" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776" +checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" [[package]] name = "libloading" -version = "0.8.8" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667" +checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" dependencies = [ "cfg-if", - "windows-targets 0.53.3", + "windows-link", ] [[package]] @@ -1306,13 +1314,13 @@ checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" [[package]] name = "libredox" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "391290121bad3d37fbddad76d8f5d1c1c314cfc646d143d7e07a3086ddff0ce3" +checksum = "416f7e718bdb06000964960ffa43b4335ad4012ae8b99060261aa4a8088d5ccb" dependencies = [ "bitflags 2.10.0", "libc", - "redox_syscall 0.5.17", + "redox_syscall 0.5.18", ] [[package]] @@ -1323,9 +1331,9 @@ checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" [[package]] name = "linux-raw-sys" -version = "0.9.4" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" +checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" [[package]] name = "litemap" @@ -1360,15 +1368,15 @@ dependencies = [ [[package]] name = "memchr" -version = "2.7.5" +version = "2.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" +checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" [[package]] name = "memmap2" -version = "0.9.7" +version = "0.9.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "483758ad303d734cec05e5c12b41d7e93e6a6390c5e9dae6bdeb7c1259012d28" +checksum = "744133e4a0e0a658e1374cf3bf8e415c4052a15a111acd372764c55b4177d490" dependencies = [ "libc", ] @@ -1394,9 +1402,9 @@ dependencies = [ [[package]] name = "moxcms" -version = "0.7.5" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddd32fa8935aeadb8a8a6b6b351e40225570a37c43de67690383d87ef170cd08" +checksum = "0fbdd3d7436f8b5e892b8b7ea114271ff0fa00bc5acae845d53b07d498616ef6" dependencies = [ "num-traits", "pxfm", @@ -1424,7 +1432,7 @@ dependencies = [ "glam 0.27.0", "glam 0.28.0", "glam 0.29.3", - "glam 0.30.8", + "glam 0.30.9", "matrixmultiply", "nalgebra-macros", "num-complex", @@ -1543,9 +1551,9 @@ dependencies = [ [[package]] name = "num_enum" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a973b4e44ce6cad84ce69d797acf9a044532e4184c4f267913d1b546a0727b7a" +checksum = "b1207a7e20ad57b847bbddc6776b968420d38292bbfe2089accff5e19e82454c" dependencies = [ "num_enum_derive", "rustversion", @@ -1553,9 +1561,9 @@ dependencies = [ [[package]] name = "num_enum_derive" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77e878c846a8abae00dd069496dbe8751b16ac1c3d6bd2a7283a938e8228f90d" +checksum = "ff32365de1b6743cb203b710788263c44a03de03802daf96092f2da4fe6ba4d7" dependencies = [ "proc-macro-crate", "proc-macro2", @@ -1606,15 +1614,15 @@ dependencies = [ [[package]] name = "objc2-app-kit" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6f29f568bec459b0ddff777cec4fe3fd8666d82d5a40ebd0ff7e66134f89bcc" +checksum = "d49e936b501e5c5bf01fda3a9452ff86dc3ea98ad5f283e1455153142d97518c" dependencies = [ "bitflags 2.10.0", "objc2 0.6.3", "objc2-core-foundation", "objc2-core-graphics", - "objc2-foundation 0.3.1", + "objc2-foundation 0.3.2", ] [[package]] @@ -1722,9 +1730,9 @@ dependencies = [ [[package]] name = "objc2-foundation" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "900831247d2fe1a09a683278e5384cfb8c80c79fe6b166f9d14bfdde0ea1b03c" +checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272" dependencies = [ "bitflags 2.10.0", "objc2 0.6.3", @@ -1836,9 +1844,9 @@ dependencies = [ [[package]] name = "object" -version = "0.36.7" +version = "0.37.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" +checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe" dependencies = [ "memchr", ] @@ -1851,9 +1859,9 @@ checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" [[package]] name = "orbclient" -version = "0.3.48" +version = "0.3.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba0b26cec2e24f08ed8bb31519a9333140a6599b867dac464bb150bdb796fd43" +checksum = "247ad146e19b9437f8604c21f8652423595cf710ad108af40e77d3ae6e96b827" dependencies = [ "libredox", ] @@ -1894,16 +1902,16 @@ checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.5.17", + "redox_syscall 0.5.18", "smallvec", - "windows-link 0.2.1", + "windows-link", ] [[package]] name = "parry3d" -version = "0.25.1" +version = "0.25.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "017be73f24c8ca8b10f9727616e5cb9af82b98488cc6d5eea468e727ffa780ca" +checksum = "e99471b7b6870f7fe406d5611dd4b4c9b07aa3e5436b1d27e1515f9832bb0c6b" dependencies = [ "approx", "arrayvec", @@ -1935,9 +1943,9 @@ checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" [[package]] name = "percent-encoding" -version = "2.3.1" +version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "pin-project" @@ -1986,16 +1994,16 @@ dependencies = [ [[package]] name = "polling" -version = "3.10.0" +version = "3.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5bd19146350fe804f7cb2669c851c03d69da628803dab0d98018142aaa5d829" +checksum = "5d0e4f59085d47d8241c88ead0f274e8a0cb551f3625263c05eb8dd897c34218" dependencies = [ "cfg-if", "concurrent-queue", "hermit-abi", "pin-project-lite", - "rustix 1.0.8", - "windows-sys 0.60.2", + "rustix 1.1.2", + "windows-sys 0.61.2", ] [[package]] @@ -2009,18 +2017,18 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "3.3.0" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edce586971a4dfaa28950c6f18ed55e0406c1ab88bbce2c6f6293a7aaba73d35" +checksum = "219cb19e96be00ab2e37d6e299658a0cfa83e52429179969b0f0121b4ac46983" dependencies = [ "toml_edit", ] [[package]] name = "proc-macro2" -version = "1.0.95" +version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" +checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8" dependencies = [ "unicode-ident", ] @@ -2046,9 +2054,9 @@ dependencies = [ [[package]] name = "pxfm" -version = "0.1.24" +version = "0.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83f9b339b02259ada5c0f4a389b7fb472f933aa17ce176fd2ad98f28bb401fde" +checksum = "a3cbdf373972bf78df4d3b518d07003938e2c7d1fb5891e55f9cb6df57009d84" dependencies = [ "num-traits", ] @@ -2070,9 +2078,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.40" +version = "1.0.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f" dependencies = [ "proc-macro2", ] @@ -2102,7 +2110,7 @@ dependencies = [ name = "raidillon_ecs" version = "0.1.0" dependencies = [ - "glam 0.30.8", + "glam 0.30.9", "raidillon_assets", "rapier3d", ] @@ -2112,7 +2120,7 @@ name = "raidillon_engine" version = "0.1.0" dependencies = [ "egui", - "glam 0.30.8", + "glam 0.30.9", "hecs", "indexmap", "raidillon_assets", @@ -2127,7 +2135,7 @@ name = "raidillon_game" version = "0.1.0" dependencies = [ "egui", - "glam 0.30.8", + "glam 0.30.9", "hecs", "raidillon_assets", "raidillon_core", @@ -2148,7 +2156,7 @@ dependencies = [ "egui", "egui_glium", "exr", - "glam 0.30.8", + "glam 0.30.9", "glium", "gltf", "image", @@ -2165,7 +2173,7 @@ dependencies = [ name = "raidillon_physics" version = "0.1.0" dependencies = [ - "glam 0.30.8", + "glam 0.30.9", "raidillon_ecs", "rapier3d", ] @@ -2174,7 +2182,7 @@ dependencies = [ name = "raidillon_platform" version = "0.1.0" dependencies = [ - "glam 0.30.8", + "glam 0.30.9", "raidillon_assets", "raidillon_core", "winit", @@ -2238,9 +2246,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.17" +version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ "bitflags 2.10.0", ] @@ -2289,22 +2297,22 @@ dependencies = [ [[package]] name = "rustix" -version = "1.0.8" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8" +checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e" dependencies = [ "bitflags 2.10.0", "errno", "libc", - "linux-raw-sys 0.9.4", - "windows-sys 0.60.2", + "linux-raw-sys 0.11.0", + "windows-sys 0.61.2", ] [[package]] name = "rustversion" -version = "1.0.21" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" [[package]] name = "ryu" @@ -2357,18 +2365,28 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.219" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.219" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", @@ -2377,14 +2395,15 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.142" +version = "1.0.145" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "030fedb782600dcbd6f02d479bf0d817ac3bb40d644745b769d6a96bc3afc5a7" +checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" dependencies = [ "itoa", "memchr", "ryu", "serde", + "serde_core", ] [[package]] @@ -2414,9 +2433,9 @@ checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" [[package]] name = "slab" -version = "0.4.10" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04dc19736151f35336d325007ac991178d504a119863a2fcb3758cdb5e52c50d" +checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" [[package]] name = "smallvec" @@ -2462,7 +2481,7 @@ dependencies = [ "libc", "log", "memmap2", - "rustix 1.0.8", + "rustix 1.1.2", "thiserror 2.0.17", "wayland-backend", "wayland-client", @@ -2498,11 +2517,11 @@ dependencies = [ [[package]] name = "spade" -version = "2.14.0" +version = "2.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a14e31a007e9f85c32784b04f89e6e194bb252a4d41b4a8ccd9e77245d901c8c" +checksum = "fb313e1c8afee5b5647e00ee0fe6855e3d529eb863a0fdae1d60006c4d1e9990" dependencies = [ - "hashbrown 0.15.4", + "hashbrown 0.15.5", "num-traits", "robust", "smallvec", @@ -2534,9 +2553,9 @@ checksum = "6637bab7722d379c8b41ba849228d680cc12d0a45ba1fa2b48f2a30577a06731" [[package]] name = "syn" -version = "2.0.104" +version = "2.0.110" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40" +checksum = "a99801b5bd34ede4cf3fc688c5919368fea4e4814a4664359503e6015b280aea" dependencies = [ "proc-macro2", "quote", @@ -2605,7 +2624,7 @@ dependencies = [ "half", "quick-error", "weezl", - "zune-jpeg", + "zune-jpeg 0.4.21", ] [[package]] @@ -2645,18 +2664,31 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.11" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" +checksum = "f2cdb639ebbc97961c51720f858597f7f24c4fc295327923af55b74c3c724533" +dependencies = [ + "serde_core", +] [[package]] name = "toml_edit" -version = "0.22.27" +version = "0.23.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" +checksum = "6485ef6d0d9b5d0ec17244ff7eb05310113c3f316f2d14200d4de56b3cb98f8d" dependencies = [ "indexmap", "toml_datetime", + "toml_parser", + "winnow", +] + +[[package]] +name = "toml_parser" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0cbe268d35bdb4bb5a56a2de88d0ad0eb70af5384a99d648cd4b3d04039800e" +dependencies = [ "winnow", ] @@ -2691,9 +2723,9 @@ checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" [[package]] name = "unicode-ident" -version = "1.0.18" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" +checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" [[package]] name = "unicode-segmentation" @@ -2703,13 +2735,14 @@ checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" [[package]] name = "url" -version = "2.5.4" +version = "2.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" +checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b" dependencies = [ "form_urlencoded", "idna", "percent-encoding", + "serde", ] [[package]] @@ -2741,45 +2774,32 @@ dependencies = [ ] [[package]] -name = "wasi" -version = "0.14.2+wasi-0.2.4" +name = "wasip2" +version = "1.0.1+wasi-0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" dependencies = [ - "wit-bindgen-rt", + "wit-bindgen", ] [[package]] name = "wasm-bindgen" -version = "0.2.100" +version = "0.2.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" +checksum = "da95793dfc411fbbd93f5be7715b0578ec61fe87cb1a42b12eb625caa5c5ea60" dependencies = [ "cfg-if", "once_cell", "rustversion", "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" -dependencies = [ - "bumpalo", - "log", - "proc-macro2", - "quote", - "syn", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.50" +version = "0.4.55" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" +checksum = "551f88106c6d5e7ccc7cd9a16f312dd3b5d36ea8b4954304657d5dfba115d4a0" dependencies = [ "cfg-if", "js-sys", @@ -2790,9 +2810,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.100" +version = "0.2.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" +checksum = "04264334509e04a7bf8690f2384ef5265f05143a4bff3889ab7a3269adab59c2" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -2800,22 +2820,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.100" +version = "0.2.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" +checksum = "420bc339d9f322e562942d52e115d57e950d12d88983a14c79b86859ee6c7ebc" dependencies = [ + "bumpalo", "proc-macro2", "quote", "syn", - "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.100" +version = "0.2.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +checksum = "76f218a38c84bcb33c25ec7059b07847d465ce0e0a76b995e134a45adcb6af76" dependencies = [ "unicode-ident", ] @@ -2828,7 +2848,7 @@ checksum = "673a33c33048a5ade91a6b139580fa174e19fb0d23f396dca9fa15f2e1e49b35" dependencies = [ "cc", "downcast-rs 1.2.1", - "rustix 1.0.8", + "rustix 1.1.2", "scoped-tls", "smallvec", "wayland-sys", @@ -2841,7 +2861,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c66a47e840dc20793f2264eb4b3e4ecb4b75d91c0dd4af04b456128e0bdd449d" dependencies = [ "bitflags 2.10.0", - "rustix 1.0.8", + "rustix 1.1.2", "wayland-backend", "wayland-scanner", ] @@ -2863,7 +2883,7 @@ version = "0.31.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "447ccc440a881271b19e9989f75726d60faa09b95b0200a9b7eb5cc47c3eeb29" dependencies = [ - "rustix 1.0.8", + "rustix 1.1.2", "wayland-client", "xcursor", ] @@ -2957,9 +2977,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.77" +version = "0.3.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" +checksum = "3a1f95c0d03a47f4ae1f7a64643a6bb97465d9b740f0fa8f90ea33915c99a9a1" dependencies = [ "js-sys", "wasm-bindgen", @@ -2986,7 +3006,7 @@ dependencies = [ "log", "ndk-context", "objc2 0.6.3", - "objc2-foundation 0.3.1", + "objc2-foundation 0.3.2", "url", "web-sys", ] @@ -3009,19 +3029,13 @@ dependencies = [ [[package]] name = "winapi-util" -version = "0.1.9" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] -[[package]] -name = "windows-link" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" - [[package]] name = "windows-link" version = "0.2.1" @@ -3061,7 +3075,16 @@ version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" dependencies = [ - "windows-targets 0.53.3", + "windows-targets 0.53.5", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", ] [[package]] @@ -3079,21 +3102,6 @@ dependencies = [ "windows_x86_64_msvc 0.42.2", ] -[[package]] -name = "windows-targets" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" -dependencies = [ - "windows_aarch64_gnullvm 0.48.5", - "windows_aarch64_msvc 0.48.5", - "windows_i686_gnu 0.48.5", - "windows_i686_msvc 0.48.5", - "windows_x86_64_gnu 0.48.5", - "windows_x86_64_gnullvm 0.48.5", - "windows_x86_64_msvc 0.48.5", -] - [[package]] name = "windows-targets" version = "0.52.6" @@ -3112,19 +3120,19 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.53.3" +version = "0.53.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" dependencies = [ - "windows-link 0.1.3", - "windows_aarch64_gnullvm 0.53.0", - "windows_aarch64_msvc 0.53.0", - "windows_i686_gnu 0.53.0", - "windows_i686_gnullvm 0.53.0", - "windows_i686_msvc 0.53.0", - "windows_x86_64_gnu 0.53.0", - "windows_x86_64_gnullvm 0.53.0", - "windows_x86_64_msvc 0.53.0", + "windows-link", + "windows_aarch64_gnullvm 0.53.1", + "windows_aarch64_msvc 0.53.1", + "windows_i686_gnu 0.53.1", + "windows_i686_gnullvm 0.53.1", + "windows_i686_msvc 0.53.1", + "windows_x86_64_gnu 0.53.1", + "windows_x86_64_gnullvm 0.53.1", + "windows_x86_64_msvc 0.53.1", ] [[package]] @@ -3133,12 +3141,6 @@ version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" - [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" @@ -3147,9 +3149,9 @@ checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_gnullvm" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" +checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" [[package]] name = "windows_aarch64_msvc" @@ -3157,12 +3159,6 @@ version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" - [[package]] name = "windows_aarch64_msvc" version = "0.52.6" @@ -3171,9 +3167,9 @@ checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_aarch64_msvc" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" +checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" [[package]] name = "windows_i686_gnu" @@ -3181,12 +3177,6 @@ version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" -[[package]] -name = "windows_i686_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" - [[package]] name = "windows_i686_gnu" version = "0.52.6" @@ -3195,9 +3185,9 @@ checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] name = "windows_i686_gnu" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" +checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" [[package]] name = "windows_i686_gnullvm" @@ -3207,9 +3197,9 @@ checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_gnullvm" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" +checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" [[package]] name = "windows_i686_msvc" @@ -3217,12 +3207,6 @@ version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" -[[package]] -name = "windows_i686_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" - [[package]] name = "windows_i686_msvc" version = "0.52.6" @@ -3231,9 +3215,9 @@ checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_i686_msvc" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" +checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" [[package]] name = "windows_x86_64_gnu" @@ -3241,12 +3225,6 @@ version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" - [[package]] name = "windows_x86_64_gnu" version = "0.52.6" @@ -3255,9 +3233,9 @@ checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnu" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" +checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" [[package]] name = "windows_x86_64_gnullvm" @@ -3265,12 +3243,6 @@ version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" - [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" @@ -3279,9 +3251,9 @@ checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_gnullvm" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" +checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" [[package]] name = "windows_x86_64_msvc" @@ -3289,12 +3261,6 @@ version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" - [[package]] name = "windows_x86_64_msvc" version = "0.52.6" @@ -3303,9 +3269,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "windows_x86_64_msvc" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" +checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" [[package]] name = "winit" @@ -3361,21 +3327,18 @@ dependencies = [ [[package]] name = "winnow" -version = "0.7.12" +version = "0.7.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3edebf492c8125044983378ecb5766203ad3b4c2f7a922bd7dd207f6d443e95" +checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf" dependencies = [ "memchr", ] [[package]] -name = "wit-bindgen-rt" -version = "0.39.0" +name = "wit-bindgen" +version = "0.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" -dependencies = [ - "bitflags 2.10.0", -] +checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" [[package]] name = "writeable" @@ -3396,24 +3359,24 @@ dependencies = [ [[package]] name = "x11rb" -version = "0.13.1" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d91ffca73ee7f68ce055750bf9f6eca0780b8c85eff9bc046a3b0da41755e12" +checksum = "9993aa5be5a26815fe2c3eacfc1fde061fc1a1f094bf1ad2a18bf9c495dd7414" dependencies = [ "as-raw-xcb-connection", "gethostname", "libc", "libloading", "once_cell", - "rustix 0.38.44", + "rustix 1.1.2", "x11rb-protocol", ] [[package]] name = "x11rb-protocol" -version = "0.13.1" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec107c4503ea0b4a98ef47356329af139c0a4f7750e621cf2973cd3385ebcb3d" +checksum = "ea6fc2961e4ef194dcbfe56bb845534d0dc8098940c7e5c012a258bfec6701bd" [[package]] name = "xcursor" @@ -3442,9 +3405,9 @@ checksum = "b9cc00251562a284751c9973bace760d86c0276c471b4be569fe6b068ee97a56" [[package]] name = "xml-rs" -version = "0.8.27" +version = "0.8.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fd8403733700263c6eb89f192880191f1b83e332f7a20371ddcf421c4a337c7" +checksum = "3ae8337f8a065cfc972643663ea4279e04e7256de865aa66fe25cec5fb912d3f" [[package]] name = "yoke" @@ -3471,18 +3434,18 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.26" +version = "0.8.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f" +checksum = "0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.26" +version = "0.8.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181" +checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831" dependencies = [ "proc-macro2", "quote", @@ -3549,6 +3512,12 @@ version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f423a2c17029964870cfaabb1f13dfab7d092a62a29a89264f4d36990ca414a" +[[package]] +name = "zune-core" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "111f7d9820f05fd715df3144e254d6fc02ee4088b0644c0ffd0efc9e6d9d2773" + [[package]] name = "zune-inflate" version = "0.2.54" @@ -3560,9 +3529,18 @@ dependencies = [ [[package]] name = "zune-jpeg" -version = "0.4.20" +version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc1f7e205ce79eb2da3cd71c5f55f3589785cb7c79f6a03d1c8d1491bda5d089" +checksum = "29ce2c8a9384ad323cf564b67da86e21d3cfdff87908bc1223ed5c99bc792713" dependencies = [ - "zune-core", + "zune-core 0.4.12", +] + +[[package]] +name = "zune-jpeg" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc6fb7703e32e9a07fb3f757360338b3a567a5054f21b5f52a666752e333d58e" +dependencies = [ + "zune-core 0.5.0", ] From 47c3b2b11163e0842948ff351d2335f6abfa9cc5 Mon Sep 17 00:00:00 2001 From: reo Date: Sun, 16 Nov 2025 19:32:56 +0300 Subject: [PATCH 77/89] New crate: raidillon_app, refactor game/main.rs to use the new crate --- Cargo.lock | 21 ++++-- Cargo.toml | 2 +- app/Cargo.toml | 16 +++++ app/src/lib.rs | 45 +++++++++++++ app/src/prelude.rs | 43 ++++++++++++ core/src/scene.rs | 2 +- game/Cargo.toml | 12 +--- game/src/main.rs | 65 +++++-------------- game/src/systems/debug_camera.rs | 8 +-- game/src/systems/keybinds.rs | 6 +- .../systems/kinematic_character_controller.rs | 8 +-- game/src/systems/physics.rs | 8 +-- 12 files changed, 140 insertions(+), 96 deletions(-) create mode 100644 app/Cargo.toml create mode 100644 app/src/lib.rs create mode 100644 app/src/prelude.rs diff --git a/Cargo.lock b/Cargo.lock index 7791e88..ac3f862 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2091,6 +2091,19 @@ version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" +[[package]] +name = "raidillon_app" +version = "0.1.0" +dependencies = [ + "raidillon_assets", + "raidillon_core", + "raidillon_ecs", + "raidillon_engine", + "raidillon_glium", + "raidillon_physics", + "raidillon_platform", +] + [[package]] name = "raidillon_assets" version = "0.1.0" @@ -2137,13 +2150,7 @@ dependencies = [ "egui", "glam 0.30.9", "hecs", - "raidillon_assets", - "raidillon_core", - "raidillon_ecs", - "raidillon_engine", - "raidillon_glium", - "raidillon_physics", - "raidillon_platform", + "raidillon_app", "rapier3d", "winit", ] diff --git a/Cargo.toml b/Cargo.toml index dd544ab..3741214 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,5 +7,5 @@ members = [ "game", "ecs", "engine", - "physics", + "physics", "app", ] diff --git a/app/Cargo.toml b/app/Cargo.toml new file mode 100644 index 0000000..081dae0 --- /dev/null +++ b/app/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "raidillon_app" +version = "0.1.0" +edition = "2024" + +[dependencies] +raidillon_engine = { path = "../engine" } +raidillon_platform = { path = "../platform" } +raidillon_assets = { path = "../asset" } +raidillon_ecs = { path = "../ecs" } +raidillon_physics = { path = "../physics" } +raidillon_glium = { path = "../glium_platform", optional = true } +raidillon_core = { path = "../core" } + +[features] +glium = ["raidillon_glium"] diff --git a/app/src/lib.rs b/app/src/lib.rs new file mode 100644 index 0000000..a5b875a --- /dev/null +++ b/app/src/lib.rs @@ -0,0 +1,45 @@ +pub mod prelude; + +pub use prelude::*; + +pub struct App { + pub engine: Option, +} + +impl App { + pub fn new() -> Self { + let engine = Engine::new(); + Self { engine: Some(engine) } + } + + pub fn add_system(&mut self) -> &mut Self { + self.engine.as_mut().unwrap().system_manager.add::(); + self + } + + pub fn add_scene(&mut self, id: SceneID, scene: Scene) -> &mut Self { + self.engine.as_mut().unwrap().scene_manager.add_scene(id, scene); + self + } + + pub fn set_active_scene(&mut self, id: SceneID) -> &mut Self { + self.engine.as_mut().unwrap().scene_manager.set_active_scene(id); + self + } + + pub fn run(&mut self, title: String, width: u32, height: u32) { + #[cfg(feature = "glium")] + { + let platform = GliumPlatform::initialize( + self.engine.take().unwrap(), + title, + width, + height, + ); + platform.run(); + } + + #[cfg(not(any(feature = "glium")))] + compile_error!("No platform feature enabled."); + } +} diff --git a/app/src/prelude.rs b/app/src/prelude.rs new file mode 100644 index 0000000..1304175 --- /dev/null +++ b/app/src/prelude.rs @@ -0,0 +1,43 @@ +pub use raidillon_engine::{ + Engine, + system::System, + EngineResources, + InputState, + system::SystemContext, +}; + +pub use raidillon_platform::{ + Platform, + Camera, + PlatformContext, + TimeContext, +}; + +pub use raidillon_assets::{ + ModelManagerRef, + model_path, +}; + +pub use raidillon_ecs::{ + components::{ + CameraMode, + CharacterBodyComponent, + ModelHandle, + RigidBodyComponent, + Transform, + }, +}; + +pub use raidillon_physics::Physics; + +pub use raidillon_core::{ + scene::{Scene, SceneID}, + EguiQueue, + engine::EngineTrait, +}; + +#[cfg(feature = "glium")] +pub use raidillon_glium::{ + GliumPlatform, + RenderingSystem, +}; diff --git a/core/src/scene.rs b/core/src/scene.rs index 2f748c4..e586be5 100644 --- a/core/src/scene.rs +++ b/core/src/scene.rs @@ -40,7 +40,7 @@ impl AsMut for Scene { } } -type SceneID = &'static str; +pub type SceneID = &'static str; pub struct SceneManager { scenes: HashMap, diff --git a/game/Cargo.toml b/game/Cargo.toml index 480aea4..0a28217 100644 --- a/game/Cargo.toml +++ b/game/Cargo.toml @@ -3,18 +3,8 @@ name = "raidillon_game" version = "0.1.0" edition = "2024" -[features] -default = ["glium"] -glium = ["raidillon_glium"] - [dependencies] -raidillon_core = { path = "../core" } -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 } +raidillon_app = { path = "../app", features = ["glium"] } glam = "0.30.5" winit = "0.30.12" rapier3d = "0.30.1" diff --git a/game/src/main.rs b/game/src/main.rs index e81d77c..939e4dd 100644 --- a/game/src/main.rs +++ b/game/src/main.rs @@ -1,25 +1,11 @@ +use raidillon_app::prelude::*; + mod systems; -use std::fmt::format; use glam::{Quat, Vec3}; 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::{CameraMode, CharacterBodyComponent, ModelHandle, RigidBodyComponent}; -use raidillon_ecs::Transform; -use raidillon_core::scene::Scene; -#[cfg(feature = "glium")] -use raidillon_glium::GliumPlatform; -use winit::event::{ElementState, Event, WindowEvent}; -use winit::event::DeviceEvent::MouseMotion; -use winit::keyboard::{KeyCode, PhysicalKey}; -use raidillon_core::{EguiQueue}; +use winit::event::{Event, WindowEvent}; 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"; @@ -46,9 +32,9 @@ impl System for UpdateAspectRatioSystem { } #[derive(Default)] -struct RenderingTestSystem; +struct MainSystem; -impl System for RenderingTestSystem { +impl System for MainSystem { fn load_world(&mut self, res: &mut EngineResources, scene: &mut Scene) { let pctx = res.get::().expect("PlatformContext missing").clone(); let physics = scene.resources.get_mut::().expect("Physics missing"); @@ -130,35 +116,14 @@ impl System for RenderingTestSystem { } fn main() { - let mut engine = Engine::new(); - // Define systems - engine.system_manager.add::(); - engine.system_manager.add::(); - engine.system_manager.add::(); - engine.system_manager.add::(); - engine.system_manager.add::(); - engine.system_manager.add::(); - // engine.system_manager.add::(); - - // Set up the scene - let main_scene = Scene::new( - MAIN_SCENE_ID.to_owned(), - None, - ); - engine.scene_manager.add_scene(MAIN_SCENE_ID, main_scene); - engine.scene_manager.set_active_scene(MAIN_SCENE_ID); - - #[cfg(feature = "glium")] - { - let platform = GliumPlatform::initialize( - engine, - "Raidillon".to_string(), - 2560, - 1080, - ); - platform.run() - }; - - #[cfg(not(any(feature = "glium")))] - compile_error!("No platform feature enabled."); + raidillon_app::App::new() + .add_system::() + .add_system::() + .add_system::() + .add_system::() + .add_system::() + .add_system::() + .add_scene(MAIN_SCENE_ID, Scene::new(MAIN_SCENE_ID.to_owned(), None)) + .set_active_scene(MAIN_SCENE_ID) + .run("Raidillon".to_string(), 2560, 1080); } diff --git a/game/src/systems/debug_camera.rs b/game/src/systems/debug_camera.rs index 13cb971..959af5c 100644 --- a/game/src/systems/debug_camera.rs +++ b/game/src/systems/debug_camera.rs @@ -1,15 +1,9 @@ -use raidillon_engine::system::{System, SystemContext}; use glam::{Quat, Vec3}; use winit::event::DeviceEvent::MouseMotion; use winit::event::{ElementState, Event, MouseButton, WindowEvent}; use winit::keyboard::{KeyCode, PhysicalKey}; use winit::window::CursorGrabMode; -use raidillon_assets::model_path; -use raidillon_platform::{Camera, PlatformContext}; -use raidillon_engine::InputState; -use raidillon_engine::EngineResources; -use raidillon_core::scene::Scene; -use raidillon_ecs::components::CameraMode; +use raidillon_app::prelude::*; pub struct FPSDebugCameraSystem { mouse_delta: (f64, f64), diff --git a/game/src/systems/keybinds.rs b/game/src/systems/keybinds.rs index 10bbbe8..d8df7b7 100644 --- a/game/src/systems/keybinds.rs +++ b/game/src/systems/keybinds.rs @@ -1,9 +1,5 @@ use winit::keyboard::KeyCode; -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}; +use raidillon_app::prelude::*; #[derive(Default)] pub struct KeybindsSystem { diff --git a/game/src/systems/kinematic_character_controller.rs b/game/src/systems/kinematic_character_controller.rs index e3fc099..34de5b4 100644 --- a/game/src/systems/kinematic_character_controller.rs +++ b/game/src/systems/kinematic_character_controller.rs @@ -1,18 +1,12 @@ 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}; +use raidillon_app::prelude::*; #[derive(Default)] pub struct KinematicCharacterController { diff --git a/game/src/systems/physics.rs b/game/src/systems/physics.rs index a77c75c..f660526 100644 --- a/game/src/systems/physics.rs +++ b/game/src/systems/physics.rs @@ -1,10 +1,4 @@ -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; +use raidillon_app::prelude::*; /// Do physics calculations and apply to world. #[derive(Default)] From b17a7636d8daf649e63fc5f6f394afce937a8756 Mon Sep 17 00:00:00 2001 From: reo Date: Sat, 22 Nov 2025 14:15:53 +0300 Subject: [PATCH 78/89] Implement MenuSystem, reimplement the mouse grab and menu system, add a new common module in the game systems for common functions, various other fixes --- game/src/main.rs | 35 +++---- game/src/systems/common.rs | 34 +++++++ game/src/systems/debug_camera.rs | 95 +++++-------------- game/src/systems/keybinds.rs | 36 ++++--- .../systems/kinematic_character_controller.rs | 85 +++++++---------- game/src/systems/menu.rs | 81 ++++++++++++++++ game/src/systems/mod.rs | 3 + 7 files changed, 219 insertions(+), 150 deletions(-) create mode 100644 game/src/systems/common.rs create mode 100644 game/src/systems/menu.rs diff --git a/game/src/main.rs b/game/src/main.rs index 939e4dd..582e2d5 100644 --- a/game/src/main.rs +++ b/game/src/main.rs @@ -6,7 +6,8 @@ use rapier3d::dynamics::{CoefficientCombineRule, RigidBodyType}; use rapier3d::prelude::ColliderBuilder; use winit::event::{Event, WindowEvent}; use systems::debug_camera::FPSDebugCameraSystem; -use crate::systems::{KeybindsSystem, KinematicCharacterController, PhysicsSystem}; +use crate::systems::common::should_draw_menu; +use crate::systems::{KeybindsSystem, KinematicCharacterController, MenuSystem, PhysicsSystem}; const TEST_GLTF: &str = "sphere.glb"; const PLANE_GLTF: &str = "plane.glb"; @@ -96,22 +97,23 @@ impl System for MainSystem { InputState, )>().unwrap(); - let mut egui_queue = pctx.egui_queue.borrow_mut(); - let time_ctx = pctx.time_ctx.clone(); - let mut character_pos = Vec3::ZERO; - for (_ent, (tr, ch_component)) in scene.world.query::<(&Transform, &CharacterBodyComponent)>().iter() { - character_pos = tr.translation; - } - egui_queue.queue(move |egui_ctx| { - egui::Window::new("Debug").show(egui_ctx, |ui| { - ui.label("Hello World!"); - ui.label(format!("Frame Delta: {}", time_ctx.frame_dt)); - ui.label(format!("Fixed Delta: {}", time_ctx.fixed_dt)); - ui.label(format!("FPS: {}", 1.0 / time_ctx.frame_dt)); - ui.label(format!("Character POS: {}", character_pos)); + if should_draw_menu(scene) { + let mut egui_queue = pctx.egui_queue.borrow_mut(); + let time_ctx = pctx.time_ctx.clone(); + let mut character_pos = Vec3::ZERO; + for (_ent, (tr, ch_component)) in scene.world.query::<(&Transform, &CharacterBodyComponent)>().iter() { + character_pos = tr.translation; + } + egui_queue.queue(move |egui_ctx| { + egui::Window::new("Debug").show(egui_ctx, |ui| { + ui.label("Hello World!"); + ui.label(format!("Frame Delta: {}", time_ctx.frame_dt)); + ui.label(format!("Fixed Delta: {}", time_ctx.fixed_dt)); + ui.label(format!("FPS: {}", 1.0 / time_ctx.frame_dt)); + ui.label(format!("Character POS: {}", character_pos)); + }); }); - }); - + } } } @@ -121,6 +123,7 @@ fn main() { .add_system::() .add_system::() .add_system::() + .add_system::() .add_system::() .add_system::() .add_scene(MAIN_SCENE_ID, Scene::new(MAIN_SCENE_ID.to_owned(), None)) diff --git a/game/src/systems/common.rs b/game/src/systems/common.rs new file mode 100644 index 0000000..8863f2e --- /dev/null +++ b/game/src/systems/common.rs @@ -0,0 +1,34 @@ +use glam::Vec3; +use raidillon_app::prelude::*; +use crate::systems::menu::MenuState; + +pub fn is_camera_mode_valid(scene: &mut Scene, mode: CameraMode) -> bool { + let mut q = scene.world.query::<(&Camera, &CameraMode)>(); + let (cam_ent, (cam, cam_mode)) = q + .iter() + .next() + .unwrap(); + *cam_mode == mode +} + +pub fn is_mouse_look_enabled(scene: &mut Scene) -> bool { + let mut q = scene.world.query::<(&MenuState)>(); + let (_ent, mode) = q.iter().next().unwrap(); + *mode == MenuState::Closed +} + +pub fn camera_front(yaw: f32, pitch: f32) -> Vec3 { + let yaw_rad = yaw.to_radians(); + let pitch_rad = pitch.to_radians(); + Vec3::new( + yaw_rad.cos() * pitch_rad.cos(), + pitch_rad.sin(), + yaw_rad.sin() * pitch_rad.cos(), + ).normalize() +} + +pub fn should_draw_menu(scene: &mut Scene) -> bool { + let mut q = scene.world.query::<(&MenuState)>(); + let (_ent, mode) = q.iter().next().unwrap(); + *mode == MenuState::Open +} diff --git a/game/src/systems/debug_camera.rs b/game/src/systems/debug_camera.rs index 959af5c..b687e08 100644 --- a/game/src/systems/debug_camera.rs +++ b/game/src/systems/debug_camera.rs @@ -5,9 +5,11 @@ use winit::keyboard::{KeyCode, PhysicalKey}; use winit::window::CursorGrabMode; use raidillon_app::prelude::*; +use crate::systems::common::{camera_front, is_camera_mode_valid, is_mouse_look_enabled}; +use crate::systems::menu::MenuState; + pub struct FPSDebugCameraSystem { mouse_delta: (f64, f64), - mouse_enabled: bool, position: Vec3, yaw: f32, pitch: f32, @@ -19,7 +21,6 @@ impl Default for FPSDebugCameraSystem { fn default() -> Self { Self { mouse_delta: Default::default(), - mouse_enabled: Default::default(), position: Vec3::new(0.0, 0.0, 2.0), yaw: -90.0, pitch: 0.0, @@ -31,7 +32,7 @@ impl Default for FPSDebugCameraSystem { impl System for FPSDebugCameraSystem { fn handle_event(&mut self, res: &mut EngineResources, scene: &mut Scene) { - if !self.is_camera_mode_valid(scene) { + if !(is_camera_mode_valid(scene, CameraMode::Debug) && is_mouse_look_enabled(scene)) { return } let pctx = res.get::().unwrap(); @@ -46,89 +47,43 @@ impl System for FPSDebugCameraSystem { _ => {} } }, - Event::WindowEvent { event, .. } => match event { - WindowEvent::MouseInput { state, button, .. } => { - if button == MouseButton::Right { - // blood and tear - let window = pctx.window.lock().unwrap(); - match state { - ElementState::Pressed => { - if window - .set_cursor_grab(CursorGrabMode::Confined) - .or_else(|_| window.set_cursor_grab(CursorGrabMode::Locked)) - .is_ok() - { - window.set_cursor_visible(false); - self.mouse_enabled = true; - } - } - ElementState::Released => { - let _ = window.set_cursor_grab(CursorGrabMode::None); - window.set_cursor_visible(true); - self.mouse_enabled = false; - } - } - } - } - _ => {}, - }, _ => {}, } } 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 { + if is_mouse_look_enabled(scene) { 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 front = camera_front(self.yaw, self.pitch); let right_vec = front.cross(Vec3::Y).normalize(); - if input.key_held(KeyCode::KeyW) { - self.position += front * pctx.time_ctx.frame_dt * self.speed; - } - if input.key_held(KeyCode::KeyS) { - self.position -= front * pctx.time_ctx.frame_dt * self.speed; - } - if input.key_held(KeyCode::KeyA) { - self.position -= right_vec * pctx.time_ctx.frame_dt * self.speed; - } - if input.key_held(KeyCode::KeyD) { - self.position += right_vec * pctx.time_ctx.frame_dt * self.speed; + if is_mouse_look_enabled(scene) { + if input.key_held(KeyCode::KeyW) { + self.position += front * pctx.time_ctx.frame_dt * self.speed; + } + if input.key_held(KeyCode::KeyS) { + self.position -= front * pctx.time_ctx.frame_dt * self.speed; + } + if input.key_held(KeyCode::KeyA) { + self.position -= right_vec * pctx.time_ctx.frame_dt * self.speed; + } + if input.key_held(KeyCode::KeyD) { + self.position += right_vec * pctx.time_ctx.frame_dt * self.speed; + } } - scene.world.query_mut::<&mut Camera>().into_iter().for_each(|(_, camera)| { - camera.eye = self.position; - camera.center = self.position + front; - }); + if is_camera_mode_valid(scene, CameraMode::Debug) { + scene.world.query_mut::<&mut Camera>().into_iter().for_each(|(_, camera)| { + camera.eye = self.position; + camera.center = self.position + front; + }); + } self.mouse_delta = (0.0, 0.0); } } - -impl FPSDebugCameraSystem { - 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::Debug - } -} diff --git a/game/src/systems/keybinds.rs b/game/src/systems/keybinds.rs index d8df7b7..5519969 100644 --- a/game/src/systems/keybinds.rs +++ b/game/src/systems/keybinds.rs @@ -1,6 +1,8 @@ use winit::keyboard::KeyCode; use raidillon_app::prelude::*; +use crate::systems::{common::should_draw_menu, menu::MenuState}; + #[derive(Default)] pub struct KeybindsSystem { camera_toggle_held: bool, @@ -19,21 +21,31 @@ impl System for KeybindsSystem { } fn frame_update(&mut self, res: &mut EngineResources, scene: &mut Scene) { - let pctx = res.get_mut::().unwrap(); - let mut q = scene.world.query::<(&Camera, &CameraMode)>(); - let (cam_ent, (cam, cam_mode)) = q - .iter() - .next() - .unwrap(); + if should_draw_menu(scene) { + let pctx = res.get_mut::().unwrap(); + let mut q = scene.world.query::<(&Camera, &CameraMode)>(); + let (cam_ent, (cam, cam_mode)) = q + .iter() + .next() + .unwrap(); + let cam_mode_str = format!("Camera Mode: {:?}", cam_mode); - let cam_mode_str = format!("Camera Mode: {:?}", cam_mode); + let mut q = scene.world.query::<(&MenuState)>(); + let (_ent, menu_state) = q + .iter() + .next() + .unwrap(); - pctx.egui_queue.borrow_mut().queue(move |egui_ctx| { - egui::Window::new("Camera").show(egui_ctx, |ui| { - ui.label("F5 to switch camera"); - ui.label(cam_mode_str); + let menu_state_str = format!("Menu State: {:?}", menu_state); + + pctx.egui_queue.borrow_mut().queue(move |egui_ctx| { + egui::Window::new("Camera").show(egui_ctx, |ui| { + ui.label("F5 to switch camera"); + ui.label(cam_mode_str); + ui.label(menu_state_str) + }); }); - }); + } } } diff --git a/game/src/systems/kinematic_character_controller.rs b/game/src/systems/kinematic_character_controller.rs index 34de5b4..41561a5 100644 --- a/game/src/systems/kinematic_character_controller.rs +++ b/game/src/systems/kinematic_character_controller.rs @@ -8,6 +8,9 @@ use winit::event::Event; use winit::keyboard::KeyCode; use raidillon_app::prelude::*; +use crate::systems::common::{camera_front, is_camera_mode_valid, is_mouse_look_enabled}; +use crate::systems::menu::MenuState; + #[derive(Default)] pub struct KinematicCharacterController { character_controller: RapierKinematicCharacterController, @@ -57,7 +60,7 @@ impl System for KinematicCharacterController { } fn handle_event(&mut self, res: &mut EngineResources, scene: &mut Scene) { - if !self.is_camera_mode_valid(scene) { + if !is_camera_mode_valid(scene, CameraMode::Kinematic) { return } @@ -78,45 +81,44 @@ impl System for KinematicCharacterController { } 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 front = camera_front(self.yaw, self.pitch); 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; + if is_camera_mode_valid(scene, CameraMode::Kinematic) && is_mouse_look_enabled(scene) { + 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); + + 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); + if is_camera_mode_valid(scene, CameraMode::Kinematic) { + 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; + }); + } - 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::().unwrap(); let (pctx, input) = res.get_many::<(PlatformContext, InputState)>().unwrap(); @@ -166,24 +168,3 @@ impl System for KinematicCharacterController { 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 - } -} diff --git a/game/src/systems/menu.rs b/game/src/systems/menu.rs new file mode 100644 index 0000000..60350b7 --- /dev/null +++ b/game/src/systems/menu.rs @@ -0,0 +1,81 @@ +use egui::Id; +use raidillon_app::prelude::*; +use winit::{dpi::{LogicalPosition, Position}, keyboard::KeyCode, window::CursorGrabMode}; + +#[derive(Default)] +pub struct MenuSystem { + escape_key_held: bool, + /// Unoptimal solution to fix windows event delay + times_ran_initial_win_event: u32, +} + +#[derive(Default, Eq, PartialEq, Debug)] +pub enum MenuState { + Open, + #[default] + Closed, +} + +impl System for MenuSystem { + fn load_world(&mut self, res: &mut EngineResources, scene: &mut Scene) { + scene.world.spawn((MenuState::Closed,)); + } + + fn frame_update(&mut self, res: &mut EngineResources, scene: &mut Scene) { + // Windows won't register some events in the first miliseconds after initialization + if self.times_ran_initial_win_event < 20 { + let window = res.get::().unwrap().window.lock().unwrap(); + window.set_cursor_grab(CursorGrabMode::Confined).or_else(|_| window.set_cursor_grab(CursorGrabMode::Locked)); + window.set_cursor_visible(false); + self.times_ran_initial_win_event += 1 + } + + let mut egui_queue = res.get::().unwrap().egui_queue.borrow_mut(); + egui_queue.queue(|egui_ctx| { + egui::Area::new(Id::new("esc to pause")) + .anchor(egui::Align2::RIGHT_TOP, [-10.0, 10.0]) + .show(egui_ctx, |ui| { + ui.label( + egui::RichText::new("ESC to pause").size(24.0).color(egui::Color32::BLACK) + ); + }); + }); + } + + fn handle_event(&mut self, res: &mut EngineResources, scene: &mut Scene) { + // The menu is toggled by pressing the escape key + let input = res.get::().unwrap(); + if input.key_held(KeyCode::Escape) { + if self.escape_key_held { return } + self.toggle_menu(res, scene); + self.escape_key_held = true; + } else { + self.escape_key_held = false; + } + } +} + +impl MenuSystem { + fn toggle_menu(&mut self, res: &mut EngineResources, scene: &mut Scene) { + let q = scene.world.query_mut::<(&mut MenuState)>(); + let (menu_ent, menu_state) = q + .into_iter() + .next() + .unwrap(); + + let window = res.get::().unwrap().window.lock().unwrap(); + + match *menu_state { + MenuState::Open => { + *menu_state = MenuState::Closed; + window.set_cursor_grab(CursorGrabMode::Confined).or_else(|_| window.set_cursor_grab(CursorGrabMode::Locked)); + window.set_cursor_visible(false); + }, + MenuState::Closed => { + *menu_state = MenuState::Open; + window.set_cursor_grab(CursorGrabMode::None); + window.set_cursor_visible(true); + }, + } + } +} diff --git a/game/src/systems/mod.rs b/game/src/systems/mod.rs index 2a387b1..2f23ed5 100644 --- a/game/src/systems/mod.rs +++ b/game/src/systems/mod.rs @@ -1,8 +1,11 @@ mod physics; mod kinematic_character_controller; mod keybinds; +mod menu; pub mod debug_camera; +pub mod common; pub use physics::PhysicsSystem; pub use kinematic_character_controller::KinematicCharacterController; pub use keybinds::KeybindsSystem; +pub use menu::MenuSystem; From f5a16213fae1b05339b7372270e944a1c07a1535 Mon Sep 17 00:00:00 2001 From: reo Date: Tue, 9 Dec 2025 17:52:17 +0300 Subject: [PATCH 79/89] Add Settings with fullscreen and windowed options, a config file (settings.toml) to persist settings, fix a bug in platform code where innner window size wasn't updated on resize, various other tweaks --- Cargo.lock | 32 +++++++++ app/src/prelude.rs | 1 + game/src/main.rs | 35 +++++----- game/src/systems/display_settings.rs | 92 ++++++++++++++++++++++++ game/src/systems/mod.rs | 2 + glium_platform/src/platform.rs | 26 ++++++- platform/Cargo.toml | 2 + platform/src/context.rs | 4 +- platform/src/lib.rs | 1 + platform/src/settings.rs | 101 +++++++++++++++++++++++++++ 10 files changed, 277 insertions(+), 19 deletions(-) create mode 100644 game/src/systems/display_settings.rs create mode 100644 platform/src/settings.rs diff --git a/Cargo.lock b/Cargo.lock index ac3f862..d36cc29 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2192,6 +2192,8 @@ dependencies = [ "glam 0.30.9", "raidillon_assets", "raidillon_core", + "serde", + "toml", "winit", ] @@ -2413,6 +2415,15 @@ dependencies = [ "serde_core", ] +[[package]] +name = "serde_spanned" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e24345aa0fe688594e73770a5f6d1b216508b4f93484c0026d521acd30134392" +dependencies = [ + "serde_core", +] + [[package]] name = "shlex" version = "1.3.0" @@ -2669,6 +2680,21 @@ dependencies = [ "zerovec", ] +[[package]] +name = "toml" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0dc8b1fb61449e27716ec0e1bdf0f6b8f3e8f6b05391e8497b8b6d7804ea6d8" +dependencies = [ + "indexmap", + "serde_core", + "serde_spanned", + "toml_datetime", + "toml_parser", + "toml_writer", + "winnow", +] + [[package]] name = "toml_datetime" version = "0.7.3" @@ -2699,6 +2725,12 @@ dependencies = [ "winnow", ] +[[package]] +name = "toml_writer" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df8b2b54733674ad286d16267dcfc7a71ed5c776e4ac7aa3c3e2561f7c637bf2" + [[package]] name = "tracing" version = "0.1.41" diff --git a/app/src/prelude.rs b/app/src/prelude.rs index 1304175..1171d0f 100644 --- a/app/src/prelude.rs +++ b/app/src/prelude.rs @@ -11,6 +11,7 @@ pub use raidillon_platform::{ Camera, PlatformContext, TimeContext, + settings::{Settings, WindowMode}, }; pub use raidillon_assets::{ diff --git a/game/src/main.rs b/game/src/main.rs index 582e2d5..b49445c 100644 --- a/game/src/main.rs +++ b/game/src/main.rs @@ -7,7 +7,9 @@ use rapier3d::prelude::ColliderBuilder; use winit::event::{Event, WindowEvent}; use systems::debug_camera::FPSDebugCameraSystem; use crate::systems::common::should_draw_menu; -use crate::systems::{KeybindsSystem, KinematicCharacterController, MenuSystem, PhysicsSystem}; +use crate::systems::{ + DisplaySettings, KeybindsSystem, KinematicCharacterController, MenuSystem, PhysicsSystem +}; const TEST_GLTF: &str = "sphere.glb"; const PLANE_GLTF: &str = "plane.glb"; @@ -97,23 +99,21 @@ impl System for MainSystem { InputState, )>().unwrap(); - if should_draw_menu(scene) { - let mut egui_queue = pctx.egui_queue.borrow_mut(); - let time_ctx = pctx.time_ctx.clone(); - let mut character_pos = Vec3::ZERO; - for (_ent, (tr, ch_component)) in scene.world.query::<(&Transform, &CharacterBodyComponent)>().iter() { - character_pos = tr.translation; - } - egui_queue.queue(move |egui_ctx| { - egui::Window::new("Debug").show(egui_ctx, |ui| { - ui.label("Hello World!"); - ui.label(format!("Frame Delta: {}", time_ctx.frame_dt)); - ui.label(format!("Fixed Delta: {}", time_ctx.fixed_dt)); - ui.label(format!("FPS: {}", 1.0 / time_ctx.frame_dt)); - ui.label(format!("Character POS: {}", character_pos)); - }); - }); + let mut egui_queue = pctx.egui_queue.borrow_mut(); + let time_ctx = pctx.time_ctx.clone(); + let mut character_pos = Vec3::ZERO; + for (_ent, (tr, ch_component)) in scene.world.query::<(&Transform, &CharacterBodyComponent)>().iter() { + character_pos = tr.translation; } + egui_queue.queue(move |egui_ctx| { + egui::Window::new("Debug").show(egui_ctx, |ui| { + ui.label("Hello World!"); + ui.label(format!("Frame Delta: {:.3}", time_ctx.frame_dt)); + ui.label(format!("Fixed Delta: {:.3}", time_ctx.fixed_dt)); + ui.label(format!("FPS: {:.3}", 1.0 / time_ctx.frame_dt)); + ui.label(format!("Character POS: {character_pos:.3}")); + }); + }); } } @@ -124,6 +124,7 @@ fn main() { .add_system::() .add_system::() .add_system::() + .add_system::() .add_system::() .add_system::() .add_scene(MAIN_SCENE_ID, Scene::new(MAIN_SCENE_ID.to_owned(), None)) diff --git a/game/src/systems/display_settings.rs b/game/src/systems/display_settings.rs new file mode 100644 index 0000000..6384d15 --- /dev/null +++ b/game/src/systems/display_settings.rs @@ -0,0 +1,92 @@ +use std::sync::{Arc, Mutex}; +use raidillon_app::prelude::*; +use crate::systems::common::should_draw_menu; + +#[derive(Clone, Copy, PartialEq, Eq)] +enum SettingsTab { + Display, +} + +impl Default for SettingsTab { + fn default() -> Self { + SettingsTab::Display + } +} + +#[derive(Clone, Default)] +struct DisplaySettingsUiState { + selected_fullscreen_mode: WindowMode, + active_tab: SettingsTab, +} + +#[derive(Default)] +pub struct DisplaySettings { + ui_state: Arc>, +} + +impl System for DisplaySettings { + fn load_world(&mut self, res: &mut EngineResources, scene: &mut Scene) { + let pctx = res.get_mut::().unwrap(); + + // sync the settings with UI state once + if let (Ok(settings_handle), Ok(mut state)) = (pctx.settings.read(), self.ui_state.lock()) { + state.selected_fullscreen_mode = settings_handle.display_settings.fullscreen_mode; + } + } + + fn frame_update(&mut self, res: &mut EngineResources, scene: &mut Scene) { + if should_draw_menu(scene) { + let pctx = res.get_mut::().unwrap(); + let settings = pctx.settings.clone(); + let ui_state = self.ui_state.clone(); + + pctx.egui_queue.borrow_mut().queue(move |egui_ctx| { + egui::Window::new("Settings").default_open(false).show(egui_ctx, |ui| { + let mut state = ui_state.lock().unwrap(); + + ui.horizontal(|ui| { + ui.selectable_value(&mut state.active_tab, SettingsTab::Display, "Display Settings"); + }); + ui.separator(); + + match state.active_tab { + SettingsTab::Display => { + ui.label("Window Mode"); + egui::ComboBox::from_id_salt("window_mode") + .selected_text(window_mode_label(state.selected_fullscreen_mode)) + .show_ui(ui, |ui| { + for mode in [ + WindowMode::Windowed, + WindowMode::BorderlessFullscreen, + ] { + ui.selectable_value( + &mut state.selected_fullscreen_mode, + mode, + window_mode_label(mode), + ); + } + }); + + ui.add_space(8.0); + ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| { + if ui.button("Apply").clicked() { + if let Ok(mut settings_handle) = settings.write() { + settings_handle.display_settings.fullscreen_mode = state.selected_fullscreen_mode; + settings_handle.display_settings.dirty = true; + } + } + }); + } + } + }); + }); + } + } +} + +fn window_mode_label(mode: WindowMode) -> &'static str { + match mode { + WindowMode::Windowed => "Windowed", + WindowMode::BorderlessFullscreen => "Borderless Fullscreen", + } +} diff --git a/game/src/systems/mod.rs b/game/src/systems/mod.rs index 2f23ed5..bcf77ca 100644 --- a/game/src/systems/mod.rs +++ b/game/src/systems/mod.rs @@ -4,8 +4,10 @@ mod keybinds; mod menu; pub mod debug_camera; pub mod common; +mod display_settings; pub use physics::PhysicsSystem; pub use kinematic_character_controller::KinematicCharacterController; pub use keybinds::KeybindsSystem; pub use menu::MenuSystem; +pub use display_settings::DisplaySettings; diff --git a/glium_platform/src/platform.rs b/glium_platform/src/platform.rs index 1b1ba08..bb1e192 100644 --- a/glium_platform/src/platform.rs +++ b/glium_platform/src/platform.rs @@ -1,6 +1,6 @@ use std::cell::RefCell; use std::rc::Rc; -use std::sync::{Arc, Mutex}; +use std::sync::{Arc, Mutex, RwLock}; use raidillon_platform::{Platform, PlatformContext, TimeContext}; use glium::backend::glutin::Display; use glium::backend::glutin::SimpleWindowBuilder; @@ -19,6 +19,7 @@ use crate::GliumAssetManager; use glam::Vec3; use winit::event::DeviceEvent::MouseMotion; use raidillon_core::EguiQueue; +use raidillon_platform::settings::{Settings, default_config_path}; pub struct GliumPlatform> { event_loop: EventLoop<()>, @@ -29,6 +30,7 @@ pub struct GliumPlatform> { engine: E, time: time::Time, egui_queue: Rc>, + settings: Arc>, } impl> Platform for GliumPlatform { @@ -57,6 +59,12 @@ impl> Platform for GliumPlatfor let egui_queue = Rc::new(RefCell::new(EguiQueue::new())); + let settings = Arc::new( + RwLock::new( + Settings::load_or_default(default_config_path()).unwrap() + ) + ); + Self { event_loop, window, @@ -66,6 +74,7 @@ impl> Platform for GliumPlatfor engine, time, egui_queue, + settings, } } @@ -82,9 +91,18 @@ impl> Platform for GliumPlatfor time_ctx: self.construct_time_ctx(), window: self.window.clone(), egui_queue: self.egui_queue.clone(), + settings: self.settings.clone(), }; self.engine.initialize(ctx.clone()); + self.settings.read().unwrap().display_settings.apply(&*self.window.lock().unwrap()); + let _ = &self.event_loop.run(move |event, el| { + let settings_handle = self.settings.read().unwrap(); + if settings_handle.display_settings.dirty { + settings_handle.display_settings.apply(&*self.window.lock().unwrap()); + } + drop(settings_handle); + self.rendering_system_manager .systems .values_mut() @@ -96,8 +114,14 @@ impl> Platform for GliumPlatfor match event { Event::WindowEvent { event, .. } => match event { + WindowEvent::Resized(size) => { + if size.width > 0 && size.height > 0 { + self.display.resize((size.width, size.height)); + } + }, WindowEvent::CloseRequested => { // TODO: Run uninitialize on renderer and engine + self.settings.read().unwrap().save_to_file(default_config_path()); el.exit(); }, WindowEvent::RedrawRequested => { diff --git a/platform/Cargo.toml b/platform/Cargo.toml index 3b42bac..1b7b5b2 100644 --- a/platform/Cargo.toml +++ b/platform/Cargo.toml @@ -8,3 +8,5 @@ winit = "0.30.12" raidillon_core = { path = "../core" } raidillon_assets = { path = "../asset" } glam = "0.30.5" +serde = "1.0.228" +toml = "0.9.8" diff --git a/platform/src/context.rs b/platform/src/context.rs index b78ea94..fdbe087 100644 --- a/platform/src/context.rs +++ b/platform/src/context.rs @@ -1,8 +1,9 @@ use std::{cell::RefCell, rc::Rc}; -use std::sync::{Arc, Mutex}; +use std::sync::{Arc, Mutex, RwLock}; use winit::event::Event; use raidillon_assets::ModelManagerRef; use raidillon_core::EguiQueue; +use crate::settings::Settings; #[derive(Clone)] pub struct PlatformContext { @@ -13,6 +14,7 @@ pub struct PlatformContext { pub time_ctx: TimeContext, pub window: Arc>, pub egui_queue: Rc>, + pub settings: Arc>, } #[derive(Clone)] diff --git a/platform/src/lib.rs b/platform/src/lib.rs index 8875d35..94c467b 100644 --- a/platform/src/lib.rs +++ b/platform/src/lib.rs @@ -2,6 +2,7 @@ pub mod platform; mod camera; mod event; pub mod context; +pub mod settings; pub use platform::Platform; pub use camera::Camera; diff --git a/platform/src/settings.rs b/platform/src/settings.rs new file mode 100644 index 0000000..f6d092f --- /dev/null +++ b/platform/src/settings.rs @@ -0,0 +1,101 @@ +use winit::dpi::LogicalSize; +use winit::window::{Fullscreen, Window}; +use serde::{Serialize, Deserialize}; +use std::error::Error; +use std::fs; +use std::io; +use std::path::{Path, PathBuf}; + +pub fn default_config_path() -> PathBuf { + let exe_path = std::env::current_exe().unwrap(); + let exe_dir = exe_path + .parent() + .ok_or_else(|| std::io::Error::new(std::io::ErrorKind::Other, "executable has no parent")).unwrap(); + + exe_dir.join("settings.toml") +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)] +#[serde(rename_all = "snake_case")] +pub enum WindowMode { + BorderlessFullscreen, + #[default] + Windowed, +} + +#[derive(Debug, Default, Serialize, Deserialize)] +pub struct Settings { + pub display_settings: DisplaySettings, +} + +impl Settings { + pub fn load_from_file(path: impl AsRef) -> Result> { + let path = path.as_ref(); + let text = fs::read_to_string(path)?; + let settings: Settings = toml::from_str(&text)?; + Ok(settings) + } + + pub fn save_to_file(&self, path: impl AsRef) -> Result<(), Box> { + let path = path.as_ref(); + if let Some(parent) = path.parent() { + fs::create_dir_all(parent)?; + } + let toml_str = toml::to_string_pretty(self)?; + fs::write(path, toml_str)?; + Ok(()) + } + + pub fn load_or_default(path: impl AsRef) -> Result> { + let path = path.as_ref(); + + match fs::read_to_string(path) { + Ok(text) => { + let settings: Settings = toml::from_str(&text)?; + Ok(settings) + } + Err(err) if err.kind() == io::ErrorKind::NotFound => { + let settings = Settings::default(); + if let Some(parent) = path.parent() { + fs::create_dir_all(parent)?; + } + let toml_str = toml::to_string_pretty(&settings)?; + fs::write(path, toml_str)?; + Ok(settings) + } + Err(err) => Err(Box::new(err)), + } + } +} + +#[derive(Debug, Serialize, Deserialize)] +#[serde(default)] +pub struct DisplaySettings { + pub fullscreen_mode: WindowMode, + #[serde(skip)] + pub dirty: bool, +} + +impl Default for DisplaySettings { + fn default() -> Self { + Self { + fullscreen_mode: WindowMode::Windowed, + dirty: false, + } + } +} + +impl DisplaySettings { + pub fn apply(&self, window: &Window) { + // apply fullscreen mode + match self.fullscreen_mode { + WindowMode::BorderlessFullscreen => { + let monitor = window.current_monitor().or_else(|| window.primary_monitor()); + window.set_fullscreen(Some(Fullscreen::Borderless(monitor))); + } + WindowMode::Windowed => { + window.set_fullscreen(None); + }, + } + } +} From 8041c7e01d88a1997f2ca3c1ad4727b04ec12aa8 Mon Sep 17 00:00:00 2001 From: reo Date: Sat, 13 Dec 2025 18:23:52 +0300 Subject: [PATCH 80/89] Fix awkward mouse conflict issues between egui and the engine --- game/src/main.rs | 5 +++++ game/src/systems/menu.rs | 6 +++++- glium_platform/src/platform.rs | 8 +++++++- glium_platform/src/render/egui.rs | 32 +++++++++++++++++++++++++++++-- glium_platform/src/system.rs | 2 ++ platform/src/context.rs | 4 ++++ 6 files changed, 53 insertions(+), 4 deletions(-) diff --git a/game/src/main.rs b/game/src/main.rs index b49445c..0f84666 100644 --- a/game/src/main.rs +++ b/game/src/main.rs @@ -106,6 +106,11 @@ impl System for MainSystem { character_pos = tr.translation; } egui_queue.queue(move |egui_ctx| { + // disable text selection on all labels. + egui_ctx.style_mut(|style| { + style.interaction.selectable_labels = false; + }); + egui::Window::new("Debug").show(egui_ctx, |ui| { ui.label("Hello World!"); ui.label(format!("Frame Delta: {:.3}", time_ctx.frame_dt)); diff --git a/game/src/systems/menu.rs b/game/src/systems/menu.rs index 60350b7..8a4b0d5 100644 --- a/game/src/systems/menu.rs +++ b/game/src/systems/menu.rs @@ -42,6 +42,7 @@ impl System for MenuSystem { }); } + fn handle_event(&mut self, res: &mut EngineResources, scene: &mut Scene) { // The menu is toggled by pressing the escape key let input = res.get::().unwrap(); @@ -63,18 +64,21 @@ impl MenuSystem { .next() .unwrap(); - let window = res.get::().unwrap().window.lock().unwrap(); + let pctx = res.get::().unwrap(); + let window = pctx.window.lock().unwrap(); match *menu_state { MenuState::Open => { *menu_state = MenuState::Closed; window.set_cursor_grab(CursorGrabMode::Confined).or_else(|_| window.set_cursor_grab(CursorGrabMode::Locked)); window.set_cursor_visible(false); + pctx.should_egui_receive_input_events.set(false); }, MenuState::Closed => { *menu_state = MenuState::Open; window.set_cursor_grab(CursorGrabMode::None); window.set_cursor_visible(true); + pctx.should_egui_receive_input_events.set(true); }, } } diff --git a/glium_platform/src/platform.rs b/glium_platform/src/platform.rs index bb1e192..b67ef77 100644 --- a/glium_platform/src/platform.rs +++ b/glium_platform/src/platform.rs @@ -1,4 +1,4 @@ -use std::cell::RefCell; +use std::cell::{RefCell, Cell}; use std::rc::Rc; use std::sync::{Arc, Mutex, RwLock}; use raidillon_platform::{Platform, PlatformContext, TimeContext}; @@ -31,6 +31,8 @@ pub struct GliumPlatform> { time: time::Time, egui_queue: Rc>, settings: Arc>, + /// Used for [`raidillon_platform::context::PlatformContext::should_egui_receive_input_events`] + should_egui_receive_input_events: Rc>, } impl> Platform for GliumPlatform { @@ -64,6 +66,7 @@ impl> Platform for GliumPlatfor Settings::load_or_default(default_config_path()).unwrap() ) ); + let should_egui_receive_input_events = Rc::new(Cell::new(false)); Self { event_loop, @@ -75,6 +78,7 @@ impl> Platform for GliumPlatfor time, egui_queue, settings, + should_egui_receive_input_events, } } @@ -92,6 +96,7 @@ impl> Platform for GliumPlatfor window: self.window.clone(), egui_queue: self.egui_queue.clone(), settings: self.settings.clone(), + should_egui_receive_input_events: self.should_egui_receive_input_events.clone(), }; self.engine.initialize(ctx.clone()); self.settings.read().unwrap().display_settings.apply(&*self.window.lock().unwrap()); @@ -136,6 +141,7 @@ impl> Platform for GliumPlatfor window: self.window.clone(), egui_queue: self.egui_queue.clone(), env_light_dir: Vec3::new(0.0, -1.0, 0.0), + should_egui_receive_input_events: self.should_egui_receive_input_events.clone(), }; self.rendering_system_manager diff --git a/glium_platform/src/render/egui.rs b/glium_platform/src/render/egui.rs index e754ba3..3cd0583 100644 --- a/glium_platform/src/render/egui.rs +++ b/glium_platform/src/render/egui.rs @@ -8,9 +8,12 @@ use crate::system::RenderingContext; use egui_glium::EguiGlium; use winit::event::{Event, WindowEvent}; use winit::event_loop::EventLoop; +use std::cell::Cell; +use std::rc::Rc; pub struct EguiRenderer { egui_glium: EguiGlium, + should_egui_receive_input_events: Option>>, } impl RenderingSystem for EguiRenderer { @@ -21,10 +24,14 @@ impl RenderingSystem for EguiRenderer { let window = window.lock().unwrap(); let egui_glium = EguiGlium::new(ViewportId::ROOT, &display, &window, &event_loop); - Self { egui_glium } + Self { egui_glium: egui_glium, should_egui_receive_input_events: None } } fn render(&mut self, ctx: &mut RenderingContext) { + if self.should_egui_receive_input_events.is_none() { + self.should_egui_receive_input_events = Some(ctx.should_egui_receive_input_events.clone()); + } + let window = ctx.window.lock().unwrap(); self.egui_glium.run(&window, |egui_ctx| { @@ -38,7 +45,28 @@ impl RenderingSystem for EguiRenderer { let window = window.lock().unwrap(); match event { Event::WindowEvent { event, .. } => { - let _ = self.egui_glium.on_event(&window, &event); + let should_egui_receive_input_events = match self.should_egui_receive_input_events.as_ref() { + Some(v) => v.get(), + None => true, + }; + + let should_send_event = if should_egui_receive_input_events { + true + } else { + !matches!(event, + WindowEvent::KeyboardInput { .. } | + WindowEvent::ModifiersChanged(_) | + WindowEvent::CursorMoved { .. } | + WindowEvent::MouseInput { .. } | + WindowEvent::MouseWheel { .. } | + WindowEvent::Touch(_) | + WindowEvent::Ime(_) + ) + }; + + if should_send_event { + let _ = self.egui_glium.on_event(&window, &event); + } } _ => {}, } diff --git a/glium_platform/src/system.rs b/glium_platform/src/system.rs index d94e9c3..92fd553 100644 --- a/glium_platform/src/system.rs +++ b/glium_platform/src/system.rs @@ -10,6 +10,7 @@ use raidillon_core::{define_typemap, EguiQueue}; use raidillon_core::scene::Scene; use glam::Vec3; use winit::event_loop::EventLoop; +use std::cell::Cell; pub struct RenderingContext<'a> { pub scene: &'a Scene, @@ -19,6 +20,7 @@ pub struct RenderingContext<'a> { pub asset_manager: ModelManagerRef, pub egui_queue: Rc>, pub env_light_dir: Vec3, + pub should_egui_receive_input_events: Rc> } /// The internal "rendering system" trait of glium_platform. diff --git a/platform/src/context.rs b/platform/src/context.rs index fdbe087..0990527 100644 --- a/platform/src/context.rs +++ b/platform/src/context.rs @@ -1,3 +1,4 @@ +use std::cell::Cell; use std::{cell::RefCell, rc::Rc}; use std::sync::{Arc, Mutex, RwLock}; use winit::event::Event; @@ -15,6 +16,9 @@ pub struct PlatformContext { pub window: Arc>, pub egui_queue: Rc>, pub settings: Arc>, + /// Sets whether or not egui will receive input events. + /// Added to prevent the mouse state conflict between the engine and egui. + pub should_egui_receive_input_events: Rc>, } #[derive(Clone)] From 73692b710e5814bd519b4e30fec10f14b97d32e8 Mon Sep 17 00:00:00 2001 From: reo Date: Mon, 15 Dec 2025 15:53:54 +0300 Subject: [PATCH 81/89] Add debug wireframe rendering support --- app/src/prelude.rs | 3 + assets/shaders/debug_wireframe.frag | 9 +++ assets/shaders/debug_wireframe.vert | 14 ++++ game/src/main.rs | 4 +- game/src/systems/mod.rs | 2 + game/src/systems/physics_debug.rs | 35 +++++++++ glium_platform/src/platform.rs | 14 +++- glium_platform/src/render/debug_wireframe.rs | 80 ++++++++++++++++++++ glium_platform/src/render/mod.rs | 2 + glium_platform/src/system.rs | 2 + platform/src/context.rs | 61 ++++++++++++++- platform/src/lib.rs | 2 +- 12 files changed, 221 insertions(+), 7 deletions(-) create mode 100644 assets/shaders/debug_wireframe.frag create mode 100644 assets/shaders/debug_wireframe.vert create mode 100644 game/src/systems/physics_debug.rs create mode 100644 glium_platform/src/render/debug_wireframe.rs diff --git a/app/src/prelude.rs b/app/src/prelude.rs index 1171d0f..fc9cdc1 100644 --- a/app/src/prelude.rs +++ b/app/src/prelude.rs @@ -11,6 +11,9 @@ pub use raidillon_platform::{ Camera, PlatformContext, TimeContext, + DebugWireframes, + DebugWireframesRef, + DebugWireframeVertex, settings::{Settings, WindowMode}, }; diff --git a/assets/shaders/debug_wireframe.frag b/assets/shaders/debug_wireframe.frag new file mode 100644 index 0000000..96d53b9 --- /dev/null +++ b/assets/shaders/debug_wireframe.frag @@ -0,0 +1,9 @@ +#version 330 core + +in vec4 v_color; + +out vec4 frag_color; + +void main() { + frag_color = v_color; +} diff --git a/assets/shaders/debug_wireframe.vert b/assets/shaders/debug_wireframe.vert new file mode 100644 index 0000000..7a53438 --- /dev/null +++ b/assets/shaders/debug_wireframe.vert @@ -0,0 +1,14 @@ +#version 330 core + +in vec3 position; +in vec4 color; + +uniform mat4 view; +uniform mat4 projection; + +out vec4 v_color; + +void main() { + v_color = color; + gl_Position = projection * view * vec4(position, 1.0); +} diff --git a/game/src/main.rs b/game/src/main.rs index 0f84666..3e1f318 100644 --- a/game/src/main.rs +++ b/game/src/main.rs @@ -8,7 +8,8 @@ use winit::event::{Event, WindowEvent}; use systems::debug_camera::FPSDebugCameraSystem; use crate::systems::common::should_draw_menu; use crate::systems::{ - DisplaySettings, KeybindsSystem, KinematicCharacterController, MenuSystem, PhysicsSystem + DisplaySettings, KeybindsSystem, KinematicCharacterController, MenuSystem, PhysicsSystem, + PhysicsDebugSystem, }; const TEST_GLTF: &str = "sphere.glb"; @@ -125,6 +126,7 @@ impl System for MainSystem { fn main() { raidillon_app::App::new() .add_system::() + .add_system::() .add_system::() .add_system::() .add_system::() diff --git a/game/src/systems/mod.rs b/game/src/systems/mod.rs index bcf77ca..08c54ab 100644 --- a/game/src/systems/mod.rs +++ b/game/src/systems/mod.rs @@ -1,4 +1,5 @@ mod physics; +mod physics_debug; mod kinematic_character_controller; mod keybinds; mod menu; @@ -7,6 +8,7 @@ pub mod common; mod display_settings; pub use physics::PhysicsSystem; +pub use physics_debug::PhysicsDebugSystem; pub use kinematic_character_controller::KinematicCharacterController; pub use keybinds::KeybindsSystem; pub use menu::MenuSystem; diff --git a/game/src/systems/physics_debug.rs b/game/src/systems/physics_debug.rs new file mode 100644 index 0000000..33364d2 --- /dev/null +++ b/game/src/systems/physics_debug.rs @@ -0,0 +1,35 @@ +use raidillon_app::prelude::*; + +/// renders aabb wireframes for all physics colliders +#[derive(Default)] +pub struct PhysicsDebugSystem; + +impl System for PhysicsDebugSystem { + fn frame_update(&mut self, res: &mut EngineResources, scene: &mut Scene) { + let pctx = res.get::().expect("PlatformContext missing").clone(); + + let mut debug_wireframes = pctx.debug_wireframes.borrow_mut(); + if !debug_wireframes.enabled { + return; + } + + let physics = match scene.resources.get::() { + Some(p) => p, + None => return, + }; + + let color = [1.0, 0.0, 0.0, 1.0]; + + for (_, collider) in physics.collider_set.iter() { + let aabb = collider.compute_aabb(); + let min = aabb.mins; + let max = aabb.maxs; + + debug_wireframes.add_box( + [min.x, min.y, min.z], + [max.x, max.y, max.z], + color, + ); + } + } +} diff --git a/glium_platform/src/platform.rs b/glium_platform/src/platform.rs index b67ef77..8f00d92 100644 --- a/glium_platform/src/platform.rs +++ b/glium_platform/src/platform.rs @@ -1,7 +1,7 @@ use std::cell::{RefCell, Cell}; use std::rc::Rc; use std::sync::{Arc, Mutex, RwLock}; -use raidillon_platform::{Platform, PlatformContext, TimeContext}; +use raidillon_platform::{Platform, PlatformContext, TimeContext, DebugWireframes, DebugWireframesRef}; use glium::backend::glutin::Display; use glium::backend::glutin::SimpleWindowBuilder; use glium::glutin::surface::WindowSurface; @@ -14,7 +14,7 @@ use raidillon_assets::ModelManagerRef; use raidillon_core::engine::EngineTrait; use raidillon_core::time; use raidillon_core::time::Time; -use crate::render::{BasicMeshRenderingSystem, EguiRenderer, SkyboxRenderingSystem}; +use crate::render::{BasicMeshRenderingSystem, DebugWireframeRenderingSystem, EguiRenderer, SkyboxRenderingSystem}; use crate::GliumAssetManager; use glam::Vec3; use winit::event::DeviceEvent::MouseMotion; @@ -31,7 +31,7 @@ pub struct GliumPlatform> { time: time::Time, egui_queue: Rc>, settings: Arc>, - /// Used for [`raidillon_platform::context::PlatformContext::should_egui_receive_input_events`] + debug_wireframes: DebugWireframesRef, should_egui_receive_input_events: Rc>, } @@ -57,6 +57,7 @@ impl> Platform for GliumPlatfor // Install rendering systems in order rendering_system_manager.add::(&display, window.clone(), &event_loop); rendering_system_manager.add::(&display, window.clone(), &event_loop); + rendering_system_manager.add::(&display, window.clone(), &event_loop); rendering_system_manager.add::(&display, window.clone(), &event_loop); let egui_queue = Rc::new(RefCell::new(EguiQueue::new())); @@ -66,6 +67,7 @@ impl> Platform for GliumPlatfor Settings::load_or_default(default_config_path()).unwrap() ) ); + let debug_wireframes = Rc::new(RefCell::new(DebugWireframes::new())); let should_egui_receive_input_events = Rc::new(Cell::new(false)); Self { @@ -78,6 +80,7 @@ impl> Platform for GliumPlatfor time, egui_queue, settings, + debug_wireframes, should_egui_receive_input_events, } } @@ -96,6 +99,7 @@ impl> Platform for GliumPlatfor window: self.window.clone(), egui_queue: self.egui_queue.clone(), settings: self.settings.clone(), + debug_wireframes: self.debug_wireframes.clone(), should_egui_receive_input_events: self.should_egui_receive_input_events.clone(), }; self.engine.initialize(ctx.clone()); @@ -140,6 +144,7 @@ impl> Platform for GliumPlatfor asset_manager: self.asset_manager.clone(), window: self.window.clone(), egui_queue: self.egui_queue.clone(), + debug_wireframes: self.debug_wireframes.clone(), env_light_dir: Vec3::new(0.0, -1.0, 0.0), should_egui_receive_input_events: self.should_egui_receive_input_events.clone(), }; @@ -149,6 +154,9 @@ impl> Platform for GliumPlatfor .values_mut() .for_each(|system| system.render(&mut context)); + // clear debug wireframes after rendering + self.debug_wireframes.borrow_mut().clear(); + target.finish().unwrap(); } _ => {}, diff --git a/glium_platform/src/render/debug_wireframe.rs b/glium_platform/src/render/debug_wireframe.rs new file mode 100644 index 0000000..2f259e9 --- /dev/null +++ b/glium_platform/src/render/debug_wireframe.rs @@ -0,0 +1,80 @@ +use std::sync::{Arc, Mutex}; +use glium::{Display, Program, Surface, VertexBuffer, implement_vertex}; +use glium::glutin::surface::WindowSurface; +use glium::index::PrimitiveType; +use glium::uniform; +use winit::event_loop::EventLoop; +use raidillon_assets::include_shader; +use crate::system::RenderingContext; +use crate::RenderingSystem; +pub use raidillon_platform::Camera; + +#[derive(Copy, Clone)] +struct DebugVertex { + position: [f32; 3], + color: [f32; 4], +} + +implement_vertex!(DebugVertex, position, color); + +/// renders debug wireframes from the shared buffer +pub struct DebugWireframeRenderingSystem { + program: Program, + params: glium::DrawParameters<'static>, +} + +impl RenderingSystem for DebugWireframeRenderingSystem { + fn initialize(display: &Display, _window: Arc>, _event_loop: &EventLoop<()>) -> Self { + const VERT_SRC: &str = include_shader!("debug_wireframe.vert"); + const FRAG_SRC: &str = include_shader!("debug_wireframe.frag"); + + let program = Program::from_source(display, VERT_SRC, FRAG_SRC, None).unwrap(); + + let params = glium::DrawParameters { + depth: glium::Depth { + test: glium::draw_parameters::DepthTest::IfLess, + write: false, + ..Default::default() + }, + line_width: Some(1.0), + ..Default::default() + }; + + Self { program, params } + } + + fn render(&mut self, ctx: &mut RenderingContext) { + let debug_wireframes = ctx.debug_wireframes.borrow(); + + if !debug_wireframes.enabled || debug_wireframes.vertices.is_empty() { + return; + } + + let cam = match ctx.scene.world.query::<&Camera>().iter().next() { + Some((_, cam)) => *cam, + None => return, + }; + + let vertices: Vec = debug_wireframes.vertices.iter() + .map(|v| DebugVertex { position: v.position, color: v.color }) + .collect(); + + let vbuf = match VertexBuffer::new(ctx.display, &vertices) { + Ok(vb) => vb, + Err(_) => return, + }; + + let uniforms = uniform! { + view: cam.view().to_cols_array_2d(), + projection: cam.projection().to_cols_array_2d(), + }; + + ctx.target.draw( + &vbuf, + glium::index::NoIndices(PrimitiveType::LinesList), + &self.program, + &uniforms, + &self.params, + ).ok(); + } +} diff --git a/glium_platform/src/render/mod.rs b/glium_platform/src/render/mod.rs index fdfa1ea..22aa047 100644 --- a/glium_platform/src/render/mod.rs +++ b/glium_platform/src/render/mod.rs @@ -1,7 +1,9 @@ mod basic; mod skybox; mod egui; +mod debug_wireframe; pub use basic::BasicMeshRenderingSystem; pub use skybox::SkyboxRenderingSystem; pub use egui::EguiRenderer; +pub use debug_wireframe::DebugWireframeRenderingSystem; diff --git a/glium_platform/src/system.rs b/glium_platform/src/system.rs index 92fd553..cf5f945 100644 --- a/glium_platform/src/system.rs +++ b/glium_platform/src/system.rs @@ -8,6 +8,7 @@ use glium::glutin::surface::WindowSurface; use raidillon_assets::ModelManagerRef; use raidillon_core::{define_typemap, EguiQueue}; use raidillon_core::scene::Scene; +use raidillon_platform::DebugWireframesRef; use glam::Vec3; use winit::event_loop::EventLoop; use std::cell::Cell; @@ -19,6 +20,7 @@ pub struct RenderingContext<'a> { pub display: &'a Display, pub asset_manager: ModelManagerRef, pub egui_queue: Rc>, + pub debug_wireframes: DebugWireframesRef, pub env_light_dir: Vec3, pub should_egui_receive_input_events: Rc> } diff --git a/platform/src/context.rs b/platform/src/context.rs index 0990527..31bd6cb 100644 --- a/platform/src/context.rs +++ b/platform/src/context.rs @@ -6,6 +6,62 @@ use raidillon_assets::ModelManagerRef; use raidillon_core::EguiQueue; use crate::settings::Settings; +/// a single debug wireframe vertex with position and color +#[derive(Clone, Copy)] +pub struct DebugWireframeVertex { + pub position: [f32; 3], + pub color: [f32; 4], +} + +/// shared buffer for debug wireframe rendering +#[derive(Clone, Default)] +pub struct DebugWireframes { + pub vertices: Vec, + pub enabled: bool, +} + +impl DebugWireframes { + pub fn new() -> Self { + Self { vertices: Vec::new(), enabled: true } + } + + pub fn clear(&mut self) { + self.vertices.clear(); + } + + /// add a single line segment + pub fn add_line(&mut self, start: [f32; 3], end: [f32; 3], color: [f32; 4]) { + self.vertices.push(DebugWireframeVertex { position: start, color }); + self.vertices.push(DebugWireframeVertex { position: end, color }); + } + + /// add a wireframe box from min/max corners + pub fn add_box(&mut self, min: [f32; 3], max: [f32; 3], color: [f32; 4]) { + let [x0, y0, z0] = min; + let [x1, y1, z1] = max; + + // bottom face edges + self.add_line([x0, y0, z0], [x1, y0, z0], color); + self.add_line([x1, y0, z0], [x1, y0, z1], color); + self.add_line([x1, y0, z1], [x0, y0, z1], color); + self.add_line([x0, y0, z1], [x0, y0, z0], color); + + // top face edges + self.add_line([x0, y1, z0], [x1, y1, z0], color); + self.add_line([x1, y1, z0], [x1, y1, z1], color); + self.add_line([x1, y1, z1], [x0, y1, z1], color); + self.add_line([x0, y1, z1], [x0, y1, z0], color); + + // vertical edges + self.add_line([x0, y0, z0], [x0, y1, z0], color); + self.add_line([x1, y0, z0], [x1, y1, z0], color); + self.add_line([x1, y0, z1], [x1, y1, z1], color); + self.add_line([x0, y0, z1], [x0, y1, z1], color); + } +} + +pub type DebugWireframesRef = Rc>; + #[derive(Clone)] pub struct PlatformContext { pub current_event: Event<()>, @@ -16,8 +72,9 @@ pub struct PlatformContext { pub window: Arc>, pub egui_queue: Rc>, pub settings: Arc>, - /// Sets whether or not egui will receive input events. - /// Added to prevent the mouse state conflict between the engine and egui. + /// shared debug wireframe buffer + pub debug_wireframes: DebugWireframesRef, + /// sets whether or not egui will receive input events pub should_egui_receive_input_events: Rc>, } diff --git a/platform/src/lib.rs b/platform/src/lib.rs index 94c467b..ef88e08 100644 --- a/platform/src/lib.rs +++ b/platform/src/lib.rs @@ -6,4 +6,4 @@ pub mod settings; pub use platform::Platform; pub use camera::Camera; -pub use context::{PlatformContext, TimeContext}; +pub use context::{PlatformContext, TimeContext, DebugWireframes, DebugWireframesRef, DebugWireframeVertex}; From 2a255affe4bcec7d814a44ba69dc2f5a81f2c5ba Mon Sep 17 00:00:00 2001 From: reo Date: Mon, 15 Dec 2025 17:08:51 +0300 Subject: [PATCH 82/89] Fix the skybox visual artifact bug #10 --- assets/shaders/skybox.frag | 6 +++++- glium_platform/src/render/skybox.rs | 8 +++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/assets/shaders/skybox.frag b/assets/shaders/skybox.frag index 864be50..ce28e95 100644 --- a/assets/shaders/skybox.frag +++ b/assets/shaders/skybox.frag @@ -9,15 +9,19 @@ uniform sampler2D equirect; const vec2 inv_atan = vec2(0.15915494309, 0.31830988618); vec2 sample_spherical_map(vec3 v) { - vec2 uv = vec2(atan(v.z, v.x), asin(v.y)); + vec2 uv = vec2(atan(v.z, v.x), asin(clamp(v.y, -1.0, 1.0))); uv *= inv_atan; uv += 0.5; + uv.x = fract(uv.x); return uv; } void main() { vec2 uv = sample_spherical_map(normalize(direction)); uv.y = 1.0 - uv.y; + vec2 size = vec2(textureSize(equirect, 0)); + float epsY = 0.5 / max(size.y, 1.0); + uv.y = clamp(uv.y, epsY, 1.0 - epsY); vec3 color = texture(equirect, uv).rgb; frag_color = vec4(color, 1.0); } diff --git a/glium_platform/src/render/skybox.rs b/glium_platform/src/render/skybox.rs index 94832d0..2c9b9d9 100644 --- a/glium_platform/src/render/skybox.rs +++ b/glium_platform/src/render/skybox.rs @@ -7,6 +7,7 @@ use glium::glutin::surface::WindowSurface; use glium::index::PrimitiveType; use glium::texture::{RawImage2d, SrgbTexture2d, Texture2d}; use glium::uniform; +use glium::uniforms::{MagnifySamplerFilter, MinifySamplerFilter, SamplerWrapFunction}; use glam::{Mat4, Vec2, Vec3}; use winit::event_loop::EventLoop; use raidillon_assets::include_shader; @@ -132,10 +133,15 @@ impl RenderingSystem for SkyboxRenderingSystem { let mut view = cam.view(); // remove translation from view matrix (only orientation) view.col_mut(3).x = 0.0; view.col_mut(3).y = 0.0; view.col_mut(3).z = 0.0; + let mut sampler = self.equirect_srgb.sampled(); + sampler = sampler.wrap_function(SamplerWrapFunction::Repeat); + sampler = sampler.minify_filter(MinifySamplerFilter::Linear); + sampler = sampler.magnify_filter(MagnifySamplerFilter::Linear); + let uniforms = uniform! { view: view.to_cols_array_2d(), projection: cam.projection().to_cols_array_2d(), - equirect: &self.equirect_srgb, + equirect: sampler, }; let params = glium::DrawParameters { depth: glium::Depth { test: glium::draw_parameters::DepthTest::IfLessOrEqual, write: false, ..Default::default() }, ..Default::default() }; ctx.target.draw(&self.quad_vb, &self.quad_ib, &self.program, &uniforms, ¶ms).ok(); From b50a60755ae9890d3438f34aa87396492556640d Mon Sep 17 00:00:00 2001 From: reo Date: Mon, 15 Dec 2025 22:16:41 +0300 Subject: [PATCH 83/89] Add exclusive fullscreen --- game/src/systems/display_settings.rs | 2 + platform/Cargo.toml | 2 +- platform/src/settings.rs | 67 +++++++++++++++++++++++++++- 3 files changed, 69 insertions(+), 2 deletions(-) diff --git a/game/src/systems/display_settings.rs b/game/src/systems/display_settings.rs index 6384d15..5d8455c 100644 --- a/game/src/systems/display_settings.rs +++ b/game/src/systems/display_settings.rs @@ -58,6 +58,7 @@ impl System for DisplaySettings { for mode in [ WindowMode::Windowed, WindowMode::BorderlessFullscreen, + WindowMode::ExclusiveFullscreen, ] { ui.selectable_value( &mut state.selected_fullscreen_mode, @@ -88,5 +89,6 @@ fn window_mode_label(mode: WindowMode) -> &'static str { match mode { WindowMode::Windowed => "Windowed", WindowMode::BorderlessFullscreen => "Borderless Fullscreen", + WindowMode::ExclusiveFullscreen => "Exclusive Fullscreen", } } diff --git a/platform/Cargo.toml b/platform/Cargo.toml index 1b7b5b2..16fec56 100644 --- a/platform/Cargo.toml +++ b/platform/Cargo.toml @@ -8,5 +8,5 @@ winit = "0.30.12" raidillon_core = { path = "../core" } raidillon_assets = { path = "../asset" } glam = "0.30.5" -serde = "1.0.228" +serde = { version = "1.0.228", features = ["derive"] } toml = "0.9.8" diff --git a/platform/src/settings.rs b/platform/src/settings.rs index f6d092f..a901137 100644 --- a/platform/src/settings.rs +++ b/platform/src/settings.rs @@ -1,4 +1,4 @@ -use winit::dpi::LogicalSize; +use winit::monitor::{MonitorHandle, VideoModeHandle}; use winit::window::{Fullscreen, Window}; use serde::{Serialize, Deserialize}; use std::error::Error; @@ -19,6 +19,7 @@ pub fn default_config_path() -> PathBuf { #[serde(rename_all = "snake_case")] pub enum WindowMode { BorderlessFullscreen, + ExclusiveFullscreen, #[default] Windowed, } @@ -93,9 +94,73 @@ impl DisplaySettings { let monitor = window.current_monitor().or_else(|| window.primary_monitor()); window.set_fullscreen(Some(Fullscreen::Borderless(monitor))); } + WindowMode::ExclusiveFullscreen => { + let monitor = window.current_monitor().or_else(|| window.primary_monitor()); + match monitor { + Some(monitor) => { + if let Some(video_mode) = pick_best_video_mode(&monitor) { + window.set_fullscreen(Some(Fullscreen::Exclusive(video_mode))); + } else { + // fallback to borderless + window.set_fullscreen(Some(Fullscreen::Borderless(Some(monitor)))); + } + } + None => { + // no monitor info, fallback to windowed + window.set_fullscreen(None); + } + } + } WindowMode::Windowed => { window.set_fullscreen(None); }, } } } + +fn pick_best_video_mode(monitor: &MonitorHandle) -> Option { + let target_size = monitor.size(); + + let mut best_native: Option = None; + let mut best_any: Option = None; + + for mode in monitor.video_modes() { + if mode.size() == target_size { + let replace = match best_native.as_ref() { + None => true, + Some(best) => { + (mode.refresh_rate_millihertz(), mode.bit_depth()) + > (best.refresh_rate_millihertz(), best.bit_depth()) + } + }; + if replace { + best_native = Some(mode.clone()); + } + } + + let replace = match best_any.as_ref() { + None => true, + Some(best) => is_better_video_mode(&mode, best), + }; + if replace { + best_any = Some(mode); + } + } + + best_native.or(best_any) +} + +fn is_better_video_mode(a: &VideoModeHandle, b: &VideoModeHandle) -> bool { + let a_size = a.size(); + let b_size = b.size(); + let a_area = u64::from(a_size.width) * u64::from(a_size.height); + let b_area = u64::from(b_size.width) * u64::from(b_size.height); + + match a_area.cmp(&b_area) { + std::cmp::Ordering::Greater => true, + std::cmp::Ordering::Less => false, + std::cmp::Ordering::Equal => { + (a.refresh_rate_millihertz(), a.bit_depth()) > (b.refresh_rate_millihertz(), b.bit_depth()) + } + } +} From 6ac8e8f503ab6c825b14b303141cedc6cbb9e5da Mon Sep 17 00:00:00 2001 From: reo Date: Mon, 15 Dec 2025 22:44:44 +0300 Subject: [PATCH 84/89] Update kinematic character controller to apply forces to dynamic bodies the character collides with --- .../systems/kinematic_character_controller.rs | 25 ++++++++++++++++--- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/game/src/systems/kinematic_character_controller.rs b/game/src/systems/kinematic_character_controller.rs index 41561a5..fd031c5 100644 --- a/game/src/systems/kinematic_character_controller.rs +++ b/game/src/systems/kinematic_character_controller.rs @@ -1,7 +1,7 @@ use glam::{Quat, Vec3}; -use rapier3d::prelude::{nalgebra, ColliderBuilder, QueryFilter, RigidBodyBuilder}; +use rapier3d::prelude::{nalgebra, ColliderBuilder, QueryFilter, RigidBodyBuilder, RigidBodyType}; use rapier3d::prelude::vector; -use rapier3d::control::KinematicCharacterController as RapierKinematicCharacterController; +use rapier3d::control::{CharacterCollision, KinematicCharacterController as RapierKinematicCharacterController}; use rapier3d::na::{Isometry3, Vector3}; use winit::event::DeviceEvent::MouseMotion; use winit::event::Event; @@ -53,7 +53,7 @@ impl System for KinematicCharacterController { )); self.speed = 5.0; - self.sensitivity = 0.1; + self.sensitivity = 0.05; self.gravity = -9.81; self.max_fall_speed = -50.0; self.vertical_velocity = 0.0; @@ -141,13 +141,14 @@ impl System for KinematicCharacterController { let mut total_displacement = self.desired_movement; total_displacement.y += self.vertical_velocity * pctx.time_ctx.fixed_dt; + let mut collisions: Vec = Vec::new(); 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], - |_| {}, + |collision| collisions.push(collision), ); // update character rigid body with the new translation. @@ -165,6 +166,22 @@ impl System for KinematicCharacterController { } } + // apply impulses to dynamic bodies the character collided with + let character_push_force = 50.0; + for collision in collisions { + if let Some(collider) = p.collider_set.get(collision.handle) { + if let Some(rb_handle) = collider.parent() { + if let Some(rb) = p.rigid_body_set.get_mut(rb_handle) { + if rb.body_type() == RigidBodyType::Dynamic { + let push_direction = -collision.hit.normal1.into_inner(); + let impulse = push_direction * character_push_force * pctx.time_ctx.fixed_dt; + rb.apply_impulse(impulse, true); + } + } + } + } + } + self.desired_movement = Vec3::ZERO; } } From 98d2a9dacb0a813b03ed273d5ae83d2dcc543486 Mon Sep 17 00:00:00 2001 From: reo Date: Mon, 15 Dec 2025 23:08:32 +0300 Subject: [PATCH 85/89] Add checkered sphere model --- assets/models/checkered-sphere.glb | 3 +++ game/src/main.rs | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 assets/models/checkered-sphere.glb diff --git a/assets/models/checkered-sphere.glb b/assets/models/checkered-sphere.glb new file mode 100644 index 0000000..ad55283 --- /dev/null +++ b/assets/models/checkered-sphere.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:36498b406df94ee6990c72a932082101fe0427af52260893e299e4d1a44de084 +size 1796992 diff --git a/game/src/main.rs b/game/src/main.rs index 3e1f318..a619cb3 100644 --- a/game/src/main.rs +++ b/game/src/main.rs @@ -12,7 +12,7 @@ use crate::systems::{ PhysicsDebugSystem, }; -const TEST_GLTF: &str = "sphere.glb"; +const TEST_GLTF: &str = "checkered-sphere.glb"; const PLANE_GLTF: &str = "plane.glb"; const MAIN_SCENE_ID: &str = "main_scene"; From a51aeb23bd71d00d8f9ab5207f6382fbe2e2f9d4 Mon Sep 17 00:00:00 2001 From: reo Date: Wed, 17 Dec 2025 20:56:02 +0300 Subject: [PATCH 86/89] Fix character collider shape --- game/src/systems/kinematic_character_controller.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/game/src/systems/kinematic_character_controller.rs b/game/src/systems/kinematic_character_controller.rs index fd031c5..b27450a 100644 --- a/game/src/systems/kinematic_character_controller.rs +++ b/game/src/systems/kinematic_character_controller.rs @@ -35,7 +35,7 @@ impl System for KinematicCharacterController { let p = scene.resources.get_mut::().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); + self.character_collider = ColliderBuilder::capsule_y(1.0, 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), From 71e991db779c4486d934f324c3e25b4bea7332e6 Mon Sep 17 00:00:00 2001 From: reo Date: Mon, 15 Dec 2025 23:34:51 +0300 Subject: [PATCH 87/89] Improve lighting - No specular on surfaces facing away from the light source - Transform the light direction to view space to ensure that all lighting calculations happen in a consistent coordinate space. - Other lighting tweaks --- assets/shaders/gl_textured.frag | 33 ++++++++++++++++++----------- glium_platform/src/render/basic.rs | 8 +++++-- glium_platform/src/render/skybox.rs | 2 +- 3 files changed, 28 insertions(+), 15 deletions(-) diff --git a/assets/shaders/gl_textured.frag b/assets/shaders/gl_textured.frag index b264f77..abfa702 100644 --- a/assets/shaders/gl_textured.frag +++ b/assets/shaders/gl_textured.frag @@ -6,28 +6,37 @@ in vec3 v_position; out vec4 frag_color; -uniform vec3 u_light; +uniform vec3 u_light; // direction TO the light (normalized) uniform sampler2D tex; -uniform vec3 color; // base colour factor (acts as solid colour when no texture) +uniform vec3 color; // base colour factor (acts as solid colour when no texture) void main() { // Combine base texture (or constant white) with colour factor supplied by CPU. vec3 base_col = texture(tex, v_tex).rgb * color; - vec3 ambient_color = base_col * 0.2; - vec3 diffuse_color = base_col * 0.6; - vec3 specular_color = vec3(1.0); + vec3 N = normalize(v_normal); + vec3 L = normalize(u_light); - // u_light is the direction **from the light towards the fragment**. - float diffuse = max(dot(normalize(v_normal), normalize(u_light)), 0.0); + // Classic Blinn-Phong lighting + // Ambient: always present + vec3 ambient = base_col * 0.15; - vec3 camera_dir = normalize(-v_position); - vec3 half_dir = normalize(normalize(u_light) + camera_dir); - float specular = pow(max(dot(half_dir, normalize(v_normal)), 0.0), 16.0); + // Diffuse: N dot L, clamped + float NdotL = max(dot(N, L), 0.0); + vec3 diffuse = base_col * NdotL * 0.7; - vec3 result = ambient_color + diffuse * diffuse_color + specular * specular_color; + // Specular: only on surfaces facing the light (NdotL > 0) + float specular = 0.0; + if (NdotL > 0.0) { + vec3 V = normalize(-v_position); // view direction (camera at origin in view space) + vec3 H = normalize(L + V); // half-vector + float NdotH = max(dot(N, H), 0.0); + specular = pow(NdotH, 32.0) * 0.5; // tighter highlight, moderated intensity + } - // Convert from linear to sRGB for display (approximate γ-correction) + vec3 result = ambient + diffuse + vec3(specular); + + // Convert from linear to sRGB for display (approximate gamma correction) result = pow(result, vec3(1.0 / 2.2)); frag_color = vec4(result, 1.0); diff --git a/glium_platform/src/render/basic.rs b/glium_platform/src/render/basic.rs index a55d865..3ed144b 100644 --- a/glium_platform/src/render/basic.rs +++ b/glium_platform/src/render/basic.rs @@ -59,7 +59,11 @@ impl RenderingSystem for BasicMeshRenderingSystem { }; // Use HDR-derived environment light direction if provided, otherwise default to downward - let light_dir: Vec3 = if ctx.env_light_dir.length_squared() > 0.0 { ctx.env_light_dir.normalize() } else { Vec3::new(0.0, -1.0, 0.0) }; + let light_dir_world: Vec3 = if ctx.env_light_dir.length_squared() > 0.0 { ctx.env_light_dir.normalize() } else { Vec3::new(0.0, -1.0, 0.0) }; + + // Transform light direction to view space (normals/positions are in view space) + let view_mat3 = glam::Mat3::from_mat4(cam.view()); + let light_dir_view = (view_mat3 * light_dir_world).normalize(); let asset_manager = ctx.asset_manager.borrow(); @@ -90,7 +94,7 @@ impl RenderingSystem for BasicMeshRenderingSystem { model: tr.matrix().to_cols_array_2d(), view: cam.view().to_cols_array_2d(), projection: cam.projection().to_cols_array_2d(), - u_light: [light_dir.x, light_dir.y, light_dir.z], + u_light: [light_dir_view.x, light_dir_view.y, light_dir_view.z], tex: sampler, color: [c[0], c[1], c[2]], uv_offset: [mat.uv_offset.x, mat.uv_offset.y], diff --git a/glium_platform/src/render/skybox.rs b/glium_platform/src/render/skybox.rs index 2c9b9d9..d11683b 100644 --- a/glium_platform/src/render/skybox.rs +++ b/glium_platform/src/render/skybox.rs @@ -119,7 +119,7 @@ impl RenderingSystem for SkyboxRenderingSystem { // Load EXR from assets/exr let manifest_dir = env!("CARGO_MANIFEST_DIR"); - let path = std::path::Path::new(manifest_dir).join("../assets/exr/qwantani_sunset_puresky_2k.exr"); + let path = std::path::Path::new(manifest_dir).join("../assets/exr/citrus_orchard_road_puresky_4k.exr"); let (equirect_srgb, light_dir) = Self::load_hdr_equirect_and_analyze(display, &path); Self { program, quad_vb, quad_ib, equirect_srgb, light_dir } } From 0f2209a5d536994541166ae0d4111848d06d1831 Mon Sep 17 00:00:00 2001 From: reo Date: Wed, 31 Dec 2025 22:34:05 +0300 Subject: [PATCH 88/89] Update the gltf loader to support multiple meshes in one file --- glium_platform/src/assets.rs | 8 +- glium_platform/src/gltf_loader.rs | 151 ++++++++++++++++------------- glium_platform/src/render/basic.rs | 56 +++++------ 3 files changed, 115 insertions(+), 100 deletions(-) diff --git a/glium_platform/src/assets.rs b/glium_platform/src/assets.rs index 1b3b4e1..c8cb1d4 100644 --- a/glium_platform/src/assets.rs +++ b/glium_platform/src/assets.rs @@ -12,7 +12,7 @@ use raidillon_assets::model_manager::ModelID; /// Glium platform asset manager implementation. pub struct GliumAssetManager { - pub models: HashMap, + pub models: HashMap>, facade: Box, } @@ -28,8 +28,8 @@ impl GliumAssetManager { impl ModelManager for GliumAssetManager { fn load_gltf(&mut self, id: ModelID, path: &Path) { - let model = load_gltf(path, self.facade.as_ref()).unwrap(); - self.models.insert(id, model); + let models = load_gltf(path, self.facade.as_ref()).unwrap(); + self.models.insert(id, models); } fn unload_model(&mut self, id: ModelID) { @@ -48,6 +48,6 @@ impl ModelManager for GliumAssetManager { // } fn get_model(&self, id: &ModelID) -> Option<&dyn Any> { - self.models.get(id).map(|model| model as &dyn Any) + self.models.get(id).map(|models| models as &dyn Any) } } diff --git a/glium_platform/src/gltf_loader.rs b/glium_platform/src/gltf_loader.rs index e41bbfb..fe4ec37 100644 --- a/glium_platform/src/gltf_loader.rs +++ b/glium_platform/src/gltf_loader.rs @@ -1,4 +1,4 @@ -use anyhow::{Context, Result}; +use anyhow::{bail, Context, Result}; use glium::{backend::Facade, IndexBuffer, VertexBuffer}; use glium::index::PrimitiveType; use std::{fmt::Debug, path::Path}; @@ -8,31 +8,16 @@ use glium::uniforms::{SamplerWrapFunction, MinifySamplerFilter, MagnifySamplerFi use gltf::image::Format as GltfFormat; use glam::Vec2; -/// Load a glTF 2.0 file from disk and upload the first primitive to the GPU. -pub fn load_gltf

(path: P, facade: &dyn Facade) -> Result +/// Load a glTF 2.0 file from disk and upload all primitives to the GPU. +/// +/// Returns one [`Model`] per glTF primitive (across all meshes). +pub fn load_gltf

(path: P, facade: &dyn Facade) -> Result> where P: AsRef + Debug, { // -- parse the asset & bring buffer blobs into memory -- let (doc, buffers, images) = gltf::import(path.as_ref()).context("failed to import glTF file")?; - // -- grab the very first mesh / primitive -- - let mesh = doc.meshes().next().context("glTF has no meshes")?; - let primitive = mesh.primitives().next().context("mesh has no primitives")?; - - // ---------- MATERIAL ---------- - let mut mat = Material::default(); - - let mat_idx = primitive.material().index().context("primitive has no material")?; - let material = doc.materials().nth(mat_idx).unwrap(); - let pbr = material.pbr_metallic_roughness(); - - // Factors -------------------------------------------------- - mat.base_color_factor = pbr.base_color_factor(); - mat.metal_factor = pbr.metallic_factor(); - mat.roughness_factor = pbr.roughness_factor(); - mat.emissive_factor = material.emissive_factor(); - // Helper to update sampler settings from glTF sampler fn update_sampler(mat: &mut Material, t: &gltf::texture::Texture<'_>) { let sampler_info = t.sampler(); @@ -64,64 +49,92 @@ where } } - // Base-color texture (sRGB) - if let Some(info) = pbr.base_color_texture() { - update_sampler(&mut mat, &info.texture()); - let view = info.texture().source().index(); - mat.base_color = Some(glium_srgb_texture(facade, &images[view])?); - } + let mut out: Vec = Vec::new(); - // Metallic-Roughness (linear) - if let Some(info) = pbr.metallic_roughness_texture() { - update_sampler(&mut mat, &info.texture()); - let view = info.texture().source().index(); - mat.metallic_roughness = Some(glium_linear_texture(facade, &images[view])?); - } + for mesh in doc.meshes() { + for primitive in mesh.primitives() { + // ---------- MATERIAL ---------- + let mut mat = Material::default(); + let material = primitive.material(); + let pbr = material.pbr_metallic_roughness(); - // Normal map (linear) - if let Some(info) = primitive.material().normal_texture() { - update_sampler(&mut mat, &info.texture()); - let view = info.texture().source().index(); - mat.normal = Some(glium_linear_texture(facade, &images[view])?); - } + // Factors -------------------------------------------------- + mat.base_color_factor = pbr.base_color_factor(); + mat.metal_factor = pbr.metallic_factor(); + mat.roughness_factor = pbr.roughness_factor(); + mat.emissive_factor = material.emissive_factor(); - // Occlusion (linear) - if let Some(info) = primitive.material().occlusion_texture() { - update_sampler(&mut mat, &info.texture()); - let view = info.texture().source().index(); - mat.occlusion = Some(glium_linear_texture(facade, &images[view])?); - } + // Base-color texture (sRGB) + if let Some(info) = pbr.base_color_texture() { + update_sampler(&mut mat, &info.texture()); + let view = info.texture().source().index(); + mat.base_color = Some(glium_srgb_texture(facade, &images[view])?); + } - // Emissive (sRGB) - if let Some(info) = primitive.material().emissive_texture() { - update_sampler(&mut mat, &info.texture()); - let view = info.texture().source().index(); - mat.emissive = Some(glium_srgb_texture(facade, &images[view])?); - } + // Metallic-Roughness (linear) + if let Some(info) = pbr.metallic_roughness_texture() { + update_sampler(&mut mat, &info.texture()); + let view = info.texture().source().index(); + mat.metallic_roughness = Some(glium_linear_texture(facade, &images[view])?); + } - // KHR_texture_transform - if let Some(tex) = pbr.base_color_texture() { - if let Some(xform) = tex.texture_transform() { - mat.uv_offset = Vec2::new(xform.offset()[0], xform.offset()[1]); - mat.uv_scale = Vec2::new(xform.scale()[0], xform.scale()[1]); + // Normal map (linear) + if let Some(info) = material.normal_texture() { + update_sampler(&mut mat, &info.texture()); + let view = info.texture().source().index(); + mat.normal = Some(glium_linear_texture(facade, &images[view])?); + } + + // Occlusion (linear) + if let Some(info) = material.occlusion_texture() { + update_sampler(&mut mat, &info.texture()); + let view = info.texture().source().index(); + mat.occlusion = Some(glium_linear_texture(facade, &images[view])?); + } + + // Emissive (sRGB) + if let Some(info) = material.emissive_texture() { + update_sampler(&mut mat, &info.texture()); + let view = info.texture().source().index(); + mat.emissive = Some(glium_srgb_texture(facade, &images[view])?); + } + + // KHR_texture_transform (base color only, for now) + if let Some(tex) = pbr.base_color_texture() { + if let Some(xform) = tex.texture_transform() { + mat.uv_offset = Vec2::new(xform.offset()[0], xform.offset()[1]); + mat.uv_scale = Vec2::new(xform.scale()[0], xform.scale()[1]); + } + } + + // ---- Vertex/index data ---- + let reader = primitive.reader(|buf| Some(&buffers[buf.index()].0)); + + let positions: Vec<[f32; 3]> = reader.read_positions().context("missing POSITION")?.collect(); + let normals: Vec<[f32; 3]> = reader.read_normals().context("missing NORMAL")?.collect(); + let tex_coords: Vec<[f32; 2]> = reader + .read_tex_coords(0) + .map(|tc| tc.into_f32().collect()) + .unwrap_or_else(|| vec![[0.0, 0.0]; positions.len()]); + let indices: Vec = reader.read_indices().context("missing indices")?.into_u32().collect(); + + // Interleave + let vertices: Vec = (0..positions.len()) + .map(|i| Vertex { position: positions[i], normal: normals[i], tex_coords: tex_coords[i] }) + .collect(); + + let vbuf = VertexBuffer::immutable(facade, &vertices)?; + let ibuf = IndexBuffer::immutable(facade, PrimitiveType::TrianglesList, &indices)?; + + out.push(Model { mesh: Mesh { vbuf, ibuf }, material: mat }); } } - // ---- Vertex/index data ---- - let reader = primitive.reader(|buf| Some(&buffers[buf.index()].0)); + if out.is_empty() { + bail!("glTF has no mesh primitives"); + } - let positions: Vec<[f32; 3]> = reader.read_positions().context("missing POSITION")?.collect(); - let normals: Vec<[f32; 3]> = reader.read_normals().context("missing NORMAL")?.collect(); - let tex_coords: Vec<[f32; 2]> = reader.read_tex_coords(0).map(|tc| tc.into_f32().collect()).unwrap_or_else(|| vec![[0.0, 0.0]; positions.len()]); - let indices: Vec = reader.read_indices().context("missing indices")?.into_u32().collect(); - - // Interleave - let vertices: Vec = (0..positions.len()).map(|i| Vertex { position: positions[i], normal: normals[i], tex_coords: tex_coords[i] }).collect(); - - let vbuf = VertexBuffer::immutable(facade, &vertices)?; - let ibuf = IndexBuffer ::immutable(facade, PrimitiveType::TrianglesList, &indices)?; - - Ok(Model { mesh: Mesh { vbuf, ibuf }, material: mat }) + Ok(out) } /// Linear-space texture (RGBA8) from glTF image data. diff --git a/glium_platform/src/render/basic.rs b/glium_platform/src/render/basic.rs index 3ed144b..6553cc0 100644 --- a/glium_platform/src/render/basic.rs +++ b/glium_platform/src/render/basic.rs @@ -73,41 +73,43 @@ impl RenderingSystem for BasicMeshRenderingSystem { _ => continue, }; - let model = match model.downcast_ref::() { - Some(model) => model, + let models = match model.downcast_ref::>() { + Some(models) => models, None => continue, }; - let mesh = &model.mesh; - let mat = &model.material; + for model in models { + let mesh = &model.mesh; + let mat = &model.material; - let tex_ref: &SrgbTexture2d = mat.base_color.as_ref().unwrap_or(&self.white_tex); + let tex_ref: &SrgbTexture2d = mat.base_color.as_ref().unwrap_or(&self.white_tex); - let mut sampler = tex_ref.sampled(); - sampler = sampler.wrap_function(SamplerWrapFunction::Repeat); - sampler = sampler.minify_filter(MinifySamplerFilter::Linear); - sampler = sampler.magnify_filter(MagnifySamplerFilter::Linear); + let mut sampler = tex_ref.sampled(); + sampler = sampler.wrap_function(SamplerWrapFunction::Repeat); + sampler = sampler.minify_filter(MinifySamplerFilter::Linear); + sampler = sampler.magnify_filter(MagnifySamplerFilter::Linear); - let c = mat.base_color_factor; + let c = mat.base_color_factor; - let uniforms = uniform! { - model: tr.matrix().to_cols_array_2d(), - view: cam.view().to_cols_array_2d(), - projection: cam.projection().to_cols_array_2d(), - u_light: [light_dir_view.x, light_dir_view.y, light_dir_view.z], - tex: sampler, - color: [c[0], c[1], c[2]], - uv_offset: [mat.uv_offset.x, mat.uv_offset.y], - uv_scale: [mat.uv_scale.x, mat.uv_scale.y], - }; + let uniforms = uniform! { + model: tr.matrix().to_cols_array_2d(), + view: cam.view().to_cols_array_2d(), + projection: cam.projection().to_cols_array_2d(), + u_light: [light_dir_view.x, light_dir_view.y, light_dir_view.z], + tex: sampler, + color: [c[0], c[1], c[2]], + uv_offset: [mat.uv_offset.x, mat.uv_offset.y], + uv_scale: [mat.uv_scale.x, mat.uv_scale.y], + }; - ctx.target.draw( - &mesh.vbuf, - &mesh.ibuf, - &self.program, - &uniforms, - &self.params, - ).unwrap(); + ctx.target.draw( + &mesh.vbuf, + &mesh.ibuf, + &self.program, + &uniforms, + &self.params, + ).unwrap(); + } } } } From a3a235692126b78d7cfdf3bace5f3d1d60f9772a Mon Sep 17 00:00:00 2001 From: Emre Osmanoglu Date: Fri, 3 Apr 2026 01:03:25 +0300 Subject: [PATCH 89/89] Add license --- LICENSE | 661 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 661 insertions(+) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..0ad25db --- /dev/null +++ b/LICENSE @@ -0,0 +1,661 @@ + GNU AFFERO GENERAL PUBLIC LICENSE + Version 3, 19 November 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU Affero General Public License is a free, copyleft license for +software and other kinds of works, specifically designed to ensure +cooperation with the community in the case of network server software. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +our General Public Licenses are intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + Developers that use our General Public Licenses protect your rights +with two steps: (1) assert copyright on the software, and (2) offer +you this License which gives you legal permission to copy, distribute +and/or modify the software. + + A secondary benefit of defending all users' freedom is that +improvements made in alternate versions of the program, if they +receive widespread use, become available for other developers to +incorporate. Many developers of free software are heartened and +encouraged by the resulting cooperation. However, in the case of +software used on network servers, this result may fail to come about. +The GNU General Public License permits making a modified version and +letting the public access it on a server without ever releasing its +source code to the public. + + The GNU Affero General Public License is designed specifically to +ensure that, in such cases, the modified source code becomes available +to the community. It requires the operator of a network server to +provide the source code of the modified version running there to the +users of that server. Therefore, public use of a modified version, on +a publicly accessible server, gives the public access to the source +code of the modified version. + + An older license, called the Affero General Public License and +published by Affero, was designed to accomplish similar goals. This is +a different license, not a version of the Affero GPL, but Affero has +released a new version of the Affero GPL which permits relicensing under +this license. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU Affero General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Remote Network Interaction; Use with the GNU General Public License. + + Notwithstanding any other provision of this License, if you modify the +Program, your modified version must prominently offer all users +interacting with it remotely through a computer network (if your version +supports such interaction) an opportunity to receive the Corresponding +Source of your version by providing access to the Corresponding Source +from a network server at no charge, through some standard or customary +means of facilitating copying of software. This Corresponding Source +shall include the Corresponding Source for any work covered by version 3 +of the GNU General Public License that is incorporated pursuant to the +following paragraph. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the work with which it is combined will remain governed by version +3 of the GNU General Public License. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU Affero General Public License from time to time. Such new versions +will be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU Affero General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU Affero General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU Affero General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If your software can interact with users remotely through a computer +network, you should also make sure that it provides a way for users to +get its source. For example, if your program is a web application, its +interface could display a "Source" link that leads users to an archive +of the code. There are many ways you could offer source, and different +solutions will be better for different programs; see section 13 for the +specific requirements. + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU AGPL, see +.