diff --git a/.gitignore b/.gitignore index 54088d5..83ea247 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ target .DS_Store +Cargo.lock \ No newline at end of file diff --git a/.idea/.gitignore b/.idea/.gitignore deleted file mode 100644 index 30cf57e..0000000 --- a/.idea/.gitignore +++ /dev/null @@ -1,10 +0,0 @@ -# Default ignored files -/shelf/ -/workspace.xml -# Editor-based HTTP Client requests -/httpRequests/ -# Ignored default folder with query files -/queries/ -# Datasource local storage ignored files -/dataSources/ -/dataSources.local.xml diff --git a/.idea/Pool.iml b/.idea/Pool.iml index 0cd351f..cf84ae4 100644 --- a/.idea/Pool.iml +++ b/.idea/Pool.iml @@ -3,13 +3,7 @@ - - - - - - diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml deleted file mode 100644 index a55e7a1..0000000 --- a/.idea/codeStyles/codeStyleConfig.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/dictionaries/project.xml b/.idea/dictionaries/project.xml deleted file mode 100644 index 4c3305b..0000000 --- a/.idea/dictionaries/project.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - forloop - vmcase - - - \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock deleted file mode 100644 index c166bf4..0000000 --- a/Cargo.lock +++ /dev/null @@ -1,2975 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 4 - -[[package]] -name = "ab_glyph" -version = "0.2.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01c0457472c38ea5bd1c3b5ada5e368271cb550be7a4ca4a0b4634e9913f6cc2" -dependencies = [ - "ab_glyph_rasterizer", - "owned_ttf_parser", -] - -[[package]] -name = "ab_glyph_rasterizer" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "366ffbaa4442f4684d91e2cd7c5ea7c4ed8add41959a31447066e279e432b618" - -[[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 = "aho-corasick" -version = "1.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" -dependencies = [ - "memchr", -] - -[[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.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f2a1bb052857d5dd49572219344a7332b31b76405648eabac5bc68978251bcd" -dependencies = [ - "android-properties", - "bitflags 2.11.1", - "cc", - "jni", - "libc", - "log", - "ndk", - "ndk-context", - "ndk-sys", - "num_enum", - "thiserror 2.0.18", -] - -[[package]] -name = "android-properties" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc7eb209b1518d6bb87b283c20095f5228ecda460da70b44f0802523dea6da04" - -[[package]] -name = "android_system_properties" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" -dependencies = [ - "libc", -] - -[[package]] -name = "anstream" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d" -dependencies = [ - "anstyle", - "anstyle-parse", - "anstyle-query", - "anstyle-wincon", - "colorchoice", - "is_terminal_polyfill", - "utf8parse", -] - -[[package]] -name = "anstyle" -version = "1.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" - -[[package]] -name = "anstyle-parse" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52ce7f38b242319f7cabaa6813055467063ecdc9d355bbb4ce0c68908cd8130e" -dependencies = [ - "utf8parse", -] - -[[package]] -name = "anstyle-query" -version = "1.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" -dependencies = [ - "windows-sys 0.61.2", -] - -[[package]] -name = "anstyle-wincon" -version = "3.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" -dependencies = [ - "anstyle", - "once_cell_polyfill", - "windows-sys 0.61.2", -] - -[[package]] -name = "anyhow" -version = "1.0.102" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" - -[[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 = "ash" -version = "0.38.0+1.3.281" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bb44936d800fea8f016d7f2311c6a4f97aebd5dc86f09906139ec848cf3a46f" -dependencies = [ - "libloading", -] - -[[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 = "base64" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" - -[[package]] -name = "bit-set" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34ddef2995421ab6a5c779542c81ee77c115206f4ad9d5a8e05f4ff49716a3dd" -dependencies = [ - "bit-vec", -] - -[[package]] -name = "bit-vec" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b71798fca2c1fe1086445a7258a4bc81e6e49dcd24c8d0dd9a1e57395b603f51" - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "bitflags" -version = "2.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" - -[[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 = "block2" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdeb9d870516001442e364c5220d3574d2da8dc765554b4a617230d33fa58ef5" -dependencies = [ - "objc2 0.6.4", -] - -[[package]] -name = "bumpalo" -version = "3.20.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" - -[[package]] -name = "bytemuck" -version = "1.25.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8efb64bd706a16a1bdde310ae86b351e4d21550d98d056f22f8a7f7a2183fec" -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" -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.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" - -[[package]] -name = "calloop" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b99da2f8558ca23c71f4fd15dc57c906239752dd27ff3c00a1d56b685b7cbfec" -dependencies = [ - "bitflags 2.11.1", - "log", - "polling", - "rustix 0.38.44", - "slab", - "thiserror 1.0.69", -] - -[[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.62" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1dce859f0832a7d088c4f1119888ab94ef4b5d6795d1ce05afb7fe159d79f98" -dependencies = [ - "find-msvc-tools", - "jobserver", - "libc", - "shlex", -] - -[[package]] -name = "cfg-if" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" - -[[package]] -name = "cfg_aliases" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" - -[[package]] -name = "codespan-reporting" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af491d569909a7e4dee0ad7db7f5341fef5c614d5b8ec8cf765732aba3cff681" -dependencies = [ - "serde", - "termcolor", - "unicode-width", -] - -[[package]] -name = "color_quant" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" - -[[package]] -name = "colorchoice" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" - -[[package]] -name = "colored" -version = "3.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "faf9468729b8cbcea668e36183cb69d317348c2e08e994829fb56ebfdfbaac34" -dependencies = [ - "windows-sys 0.61.2", -] - -[[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 = "console_error_panic_hook" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" -dependencies = [ - "cfg-if", - "wasm-bindgen", -] - -[[package]] -name = "console_log" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be8aed40e4edbf4d3b4431ab260b63fdc40f5780a4766824329ea0f1eefe3c0f" -dependencies = [ - "log", - "web-sys", -] - -[[package]] -name = "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 = "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" -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.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e0e367e4e7da84520dedcac1901e4da967309406d1e51017ae1abfb97adbd38" -dependencies = [ - "bitflags 2.11.1", - "objc2 0.6.4", -] - -[[package]] -name = "dlib" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab8ecd87370524b461f8557c119c405552c396ed91fc0a8eec68679eab26f94a" -dependencies = [ - "libloading", -] - -[[package]] -name = "document-features" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4b8a88685455ed29a21542a33abd9cb6510b6b129abadabdcef0f4c55bc8f61" -dependencies = [ - "litrs", -] - -[[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 = "env_filter" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32e90c2accc4b07a8456ea0debdc2e7587bdd890680d71173a15d4ae604f6eef" -dependencies = [ - "log", - "regex", -] - -[[package]] -name = "env_logger" -version = "0.11.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0621c04f2196ac3f488dd583365b9c09be011a4ab8b9f37248ffcc8f6198b56a" -dependencies = [ - "anstream", - "anstyle", - "env_filter", - "jiff", - "log", -] - -[[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.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" -dependencies = [ - "libc", - "windows-sys 0.61.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 = "find-msvc-tools" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" - -[[package]] -name = "flate2" -version = "1.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" -dependencies = [ - "crc32fast", - "miniz_oxide", -] - -[[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" -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 = "futures-core" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" - -[[package]] -name = "futures-task" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" - -[[package]] -name = "futures-util" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" -dependencies = [ - "futures-core", - "futures-task", - "pin-project-lite", - "slab", -] - -[[package]] -name = "game" -version = "0.1.0" -dependencies = [ - "anyhow", - "bytemuck", - "console_error_panic_hook", - "console_log", - "env_logger", - "glam", - "gltf", - "image 0.24.9", - "log", - "mars", - "pollster", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "wgpu", - "winit", -] - -[[package]] -name = "gethostname" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bd49230192a3797a9a4d6abe9b3eed6f7fa4c8a8a4947977c6f80025f92cbd8" -dependencies = [ - "rustix 1.1.4", - "windows-link", -] - -[[package]] -name = "getrandom" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" -dependencies = [ - "cfg-if", - "libc", - "r-efi", - "wasip2", -] - -[[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.33.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7360bd2cd76e0cd9032d42cf2922155cecea2685b0cfa4630c3246df030bcfd6" -dependencies = [ - "bytemuck", -] - -[[package]] -name = "glow" -version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29038e1c483364cc6bb3cf78feee1816002e127c331a1eec55a4d202b9e1adb5" -dependencies = [ - "js-sys", - "slotmap", - "wasm-bindgen", - "web-sys", -] - -[[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 0.25.10", - "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_wgl_sys" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c4ee00b289aba7a9e5306d57c2d05499b2e5dc427f84ac708bd2c090212cf3e" -dependencies = [ - "gl_generator", -] - -[[package]] -name = "gpu-allocator" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51255ea7cfaadb6c5f1528d43e92a82acb2b96c43365989a28b2d44ee38f8795" -dependencies = [ - "ash", - "hashbrown 0.16.1", - "log", - "presser", - "thiserror 2.0.18", - "windows", -] - -[[package]] -name = "gpu-descriptor" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b89c83349105e3732062a895becfc71a8f921bb71ecbbdd8ff99263e3b53a0ca" -dependencies = [ - "bitflags 2.11.1", - "gpu-descriptor-types", - "hashbrown 0.15.5", -] - -[[package]] -name = "gpu-descriptor-types" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdf242682df893b86f33a73828fb09ca4b2d3bb6cc95249707fc684d27484b91" -dependencies = [ - "bitflags 2.11.1", -] - -[[package]] -name = "half" -version = "2.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" -dependencies = [ - "cfg-if", - "crunchy", - "num-traits", - "zerocopy", -] - -[[package]] -name = "hashbrown" -version = "0.15.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" -dependencies = [ - "foldhash 0.1.5", -] - -[[package]] -name = "hashbrown" -version = "0.16.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" -dependencies = [ - "allocator-api2", - "equivalent", - "foldhash 0.2.0", -] - -[[package]] -name = "hashbrown" -version = "0.17.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" - -[[package]] -name = "hermit-abi" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" - -[[package]] -name = "hexf-parse" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df" - -[[package]] -name = "image" -version = "0.24.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5690139d2f55868e080017335e4b94cb7414274c74f1669c84fb5feba2c9f69d" -dependencies = [ - "bytemuck", - "byteorder", - "color_quant", - "jpeg-decoder", - "num-traits", - "png 0.17.16", -] - -[[package]] -name = "image" -version = "0.25.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85ab80394333c02fe689eaf900ab500fbd0c2213da414687ebf995a65d5a6104" -dependencies = [ - "bytemuck", - "byteorder-lite", - "moxcms", - "num-traits", - "png 0.18.1", - "zune-core", - "zune-jpeg", -] - -[[package]] -name = "indexmap" -version = "2.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" -dependencies = [ - "equivalent", - "hashbrown 0.17.1", -] - -[[package]] -name = "inflections" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a257582fdcde896fd96463bf2d40eefea0580021c0712a0e2b028b60b47a837a" - -[[package]] -name = "is_terminal_polyfill" -version = "1.70.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" - -[[package]] -name = "itoa" -version = "1.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" - -[[package]] -name = "jiff" -version = "0.2.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f00b5dbd620d61dfdcb6007c9c1f6054ebd75319f163d886a9055cec1155073d" -dependencies = [ - "jiff-static", - "log", - "portable-atomic", - "portable-atomic-util", - "serde_core", -] - -[[package]] -name = "jiff-static" -version = "0.2.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e000de030ff8022ea1da3f466fbb0f3a809f5e51ed31f6dd931c35181ad8e6d7" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "jni" -version = "0.22.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5efd9a482cf3a427f00d6b35f14332adc7902ce91efb778580e180ff90fa3498" -dependencies = [ - "cfg-if", - "combine", - "jni-macros", - "jni-sys 0.4.1", - "log", - "simd_cesu8", - "thiserror 2.0.18", - "walkdir", - "windows-link", -] - -[[package]] -name = "jni-macros" -version = "0.22.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a00109accc170f0bdb141fed3e393c565b6f5e072365c3bd58f5b062591560a3" -dependencies = [ - "proc-macro2", - "quote", - "rustc_version", - "simd_cesu8", - "syn", -] - -[[package]] -name = "jni-sys" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41a652e1f9b6e0275df1f15b32661cf0d4b78d4d87ddec5e0c3c20f097433258" -dependencies = [ - "jni-sys 0.4.1", -] - -[[package]] -name = "jni-sys" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6377a88cb3910bee9b0fa88d4f42e1d2da8e79915598f65fb0c7ee14c878af2" -dependencies = [ - "jni-sys-macros", -] - -[[package]] -name = "jni-sys-macros" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264" -dependencies = [ - "quote", - "syn", -] - -[[package]] -name = "jobserver" -version = "0.1.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" -dependencies = [ - "getrandom", - "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.98" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67df7112613f8bfd9150013a0314e196f4800d3201ae742489d999db2f979f08" -dependencies = [ - "cfg-if", - "futures-util", - "once_cell", - "wasm-bindgen", -] - -[[package]] -name = "khronos-egl" -version = "6.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6aae1df220ece3c0ada96b8153459b67eebe9ae9212258bb0134ae60416fdf76" -dependencies = [ - "libc", - "libloading", - "pkg-config", -] - -[[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.186" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" - -[[package]] -name = "libloading" -version = "0.8.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" -dependencies = [ - "cfg-if", - "windows-link", -] - -[[package]] -name = "libm" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" - -[[package]] -name = "libredox" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e02f3bb43d335493c96bf3fd3a321600bf6bd07ed34bc64118e9293bdffea46c" -dependencies = [ - "bitflags 2.11.1", - "libc", - "plain", - "redox_syscall 0.7.5", -] - -[[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.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" - -[[package]] -name = "litrs" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092" - -[[package]] -name = "lock_api" -version = "0.4.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" -dependencies = [ - "scopeguard", -] - -[[package]] -name = "log" -version = "0.4.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad" - -[[package]] -name = "mars" -version = "0.1.0" -dependencies = [ - "colored", -] - -[[package]] -name = "memchr" -version = "2.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" - -[[package]] -name = "memmap2" -version = "0.9.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "714098028fe011992e1c3962653c96b2d578c4b4bce9036e15ff220319b1e0e3" -dependencies = [ - "libc", -] - -[[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 = "moxcms" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb85c154ba489f01b25c0d36ae69a87e4a1c73a72631fc6c0eb6dde34a73e44b" -dependencies = [ - "num-traits", - "pxfm", -] - -[[package]] -name = "naga" -version = "29.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dd91265cc2454558f659b3b4b9640f0ddb8cc6521277f166b8a8c181c898079" -dependencies = [ - "arrayvec", - "bit-set", - "bitflags 2.11.1", - "cfg-if", - "cfg_aliases", - "codespan-reporting", - "half", - "hashbrown 0.16.1", - "hexf-parse", - "indexmap", - "libm", - "log", - "num-traits", - "once_cell", - "rustc-hash", - "spirv", - "thiserror 2.0.18", - "unicode-ident", -] - -[[package]] -name = "ndk" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4" -dependencies = [ - "bitflags 2.11.1", - "jni-sys 0.3.1", - "log", - "ndk-sys", - "num_enum", - "raw-window-handle", - "thiserror 1.0.69", -] - -[[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 0.3.1", -] - -[[package]] -name = "num-traits" -version = "0.2.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" -dependencies = [ - "autocfg", - "libm", -] - -[[package]] -name = "num_enum" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d0bca838442ec211fa11de3a8b0e0e8f3a4522575b5c4c06ed722e005036f26" -dependencies = [ - "num_enum_derive", - "rustversion", -] - -[[package]] -name = "num_enum_derive" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "680998035259dcfcafe653688bf2aa6d3e2dc05e98be6ab46afb089dc84f1df8" -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.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a12a8ed07aefc768292f076dc3ac8c48f3781c8f2d5851dd3d98950e8c5a89f" -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.11.1", - "block2 0.5.1", - "libc", - "objc2 0.5.2", - "objc2-core-data", - "objc2-core-image", - "objc2-foundation 0.2.2", - "objc2-quartz-core 0.2.2", -] - -[[package]] -name = "objc2-cloud-kit" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74dd3b56391c7a0596a295029734d3c1c5e7e510a4cb30245f8221ccea96b009" -dependencies = [ - "bitflags 2.11.1", - "block2 0.5.1", - "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 0.5.1", - "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.11.1", - "block2 0.5.1", - "objc2 0.5.2", - "objc2-foundation 0.2.2", -] - -[[package]] -name = "objc2-core-foundation" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" -dependencies = [ - "bitflags 2.11.1", - "dispatch2", - "objc2 0.6.4", -] - -[[package]] -name = "objc2-core-image" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55260963a527c99f1819c4f8e3b47fe04f9650694ef348ffd2227e8196d34c80" -dependencies = [ - "block2 0.5.1", - "objc2 0.5.2", - "objc2-foundation 0.2.2", - "objc2-metal 0.2.2", -] - -[[package]] -name = "objc2-core-location" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "000cfee34e683244f284252ee206a27953279d370e309649dc3ee317b37e5781" -dependencies = [ - "block2 0.5.1", - "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.11.1", - "block2 0.5.1", - "dispatch", - "libc", - "objc2 0.5.2", -] - -[[package]] -name = "objc2-foundation" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272" -dependencies = [ - "bitflags 2.11.1", - "objc2 0.6.4", - "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 0.5.1", - "objc2 0.5.2", - "objc2-app-kit", - "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.11.1", - "block2 0.5.1", - "objc2 0.5.2", - "objc2-foundation 0.2.2", -] - -[[package]] -name = "objc2-metal" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0125f776a10d00af4152d74616409f0d4a2053a6f57fa5b7d6aa2854ac04794" -dependencies = [ - "bitflags 2.11.1", - "block2 0.6.2", - "objc2 0.6.4", - "objc2-foundation 0.3.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.11.1", - "block2 0.5.1", - "objc2 0.5.2", - "objc2-foundation 0.2.2", - "objc2-metal 0.2.2", -] - -[[package]] -name = "objc2-quartz-core" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96c1358452b371bf9f104e21ec536d37a650eb10f7ee379fff67d2e08d537f1f" -dependencies = [ - "bitflags 2.11.1", - "objc2 0.6.4", - "objc2-core-foundation", - "objc2-foundation 0.3.2", - "objc2-metal 0.3.2", -] - -[[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.11.1", - "block2 0.5.1", - "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 0.2.2", - "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 0.5.1", - "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.11.1", - "block2 0.5.1", - "objc2 0.5.2", - "objc2-core-location", - "objc2-foundation 0.2.2", -] - -[[package]] -name = "once_cell" -version = "1.21.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" - -[[package]] -name = "once_cell_polyfill" -version = "1.70.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" - -[[package]] -name = "orbclient" -version = "0.3.54" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a570f6bca41d29acb2139229a7c873ec99bc9a313bd10804081d89bfac8ff329" -dependencies = [ - "libc", - "libredox", -] - -[[package]] -name = "ordered-float" -version = "5.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7d950ca161dc355eaf28f82b11345ed76c6e1f6eb1f4f4479e0323b9e2fbd0e" -dependencies = [ - "num-traits", -] - -[[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 = "parking_lot" -version = "0.12.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" -dependencies = [ - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall 0.5.18", - "smallvec", - "windows-link", -] - -[[package]] -name = "percent-encoding" -version = "2.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" - -[[package]] -name = "pin-project" -version = "1.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbf0d9e68100b3a7989b4901972f265cd542e560a3a8a724e1e20322f4d06ce9" -dependencies = [ - "pin-project-internal", -] - -[[package]] -name = "pin-project-internal" -version = "1.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a990e22f43e84855daf260dded30524ef4a9021cc7541c26540500a50b624389" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "pin-project-lite" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" - -[[package]] -name = "pkg-config" -version = "0.3.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e" - -[[package]] -name = "plain" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" - -[[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 = "png" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60769b8b31b2a9f263dae2776c37b1b28ae246943cf719eb6946a1db05128a61" -dependencies = [ - "bitflags 2.11.1", - "crc32fast", - "fdeflate", - "flate2", - "miniz_oxide", -] - -[[package]] -name = "polling" -version = "3.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d0e4f59085d47d8241c88ead0f274e8a0cb551f3625263c05eb8dd897c34218" -dependencies = [ - "cfg-if", - "concurrent-queue", - "hermit-abi", - "pin-project-lite", - "rustix 1.1.4", - "windows-sys 0.61.2", -] - -[[package]] -name = "pollster" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f3a9f18d041e6d0e102a0a46750538147e5e8992d3b4873aaafee2520b00ce3" - -[[package]] -name = "portable-atomic" -version = "1.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" - -[[package]] -name = "portable-atomic-util" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2a106d1259c23fac8e543272398ae0e3c0b8d33c88ed73d0cc71b0f1d902618" -dependencies = [ - "portable-atomic", -] - -[[package]] -name = "presser" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8cf8e6a8aa66ce33f63993ffc4ea4271eb5b0530a9002db8455ea6050c77bfa" - -[[package]] -name = "proc-macro-crate" -version = "3.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" -dependencies = [ - "toml_edit", -] - -[[package]] -name = "proc-macro2" -version = "1.0.106" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "profiling" -version = "1.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d595e54a326bc53c1c197b32d295e14b169e3cfeaa8dc82b529f947fba6bcf5" - -[[package]] -name = "pxfm" -version = "0.1.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d55d956fa96f5ec02be2e13af0e20391a5aa83d6a074e3ad368959d0fab299ea" - -[[package]] -name = "quick-xml" -version = "0.39.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdcc8dd4e2f670d309a5f0e83fe36dfdc05af317008fea29144da1a2ac858e5e" -dependencies = [ - "memchr", -] - -[[package]] -name = "quote" -version = "1.0.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" -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 = "range-alloc" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca45419789ae5a7899559e9512e58ca889e41f04f1f2445e9f4b290ceccd1d08" - -[[package]] -name = "raw-window-handle" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539" - -[[package]] -name = "raw-window-metal" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40d213455a5f1dc59214213c7330e074ddf8114c9a42411eb890c767357ce135" -dependencies = [ - "objc2 0.6.4", - "objc2-core-foundation", - "objc2-foundation 0.3.2", - "objc2-quartz-core 0.3.2", -] - -[[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.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" -dependencies = [ - "bitflags 2.11.1", -] - -[[package]] -name = "redox_syscall" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4666a1a60d8412eab19d94f6d13dcc9cea0a5ef4fdf6a5db306537413c661b1b" -dependencies = [ - "bitflags 2.11.1", -] - -[[package]] -name = "regex" -version = "1.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata", - "regex-syntax", -] - -[[package]] -name = "regex-automata" -version = "0.4.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.8.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" - -[[package]] -name = "renderdoc-sys" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19b30a45b0cd0bcca8037f3d0dc3421eaf95327a17cad11964fb8179b4fc4832" - -[[package]] -name = "rustc-hash" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" - -[[package]] -name = "rustc_version" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" -dependencies = [ - "semver", -] - -[[package]] -name = "rustix" -version = "0.38.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" -dependencies = [ - "bitflags 2.11.1", - "errno", - "libc", - "linux-raw-sys 0.4.15", - "windows-sys 0.59.0", -] - -[[package]] -name = "rustix" -version = "1.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" -dependencies = [ - "bitflags 2.11.1", - "errno", - "libc", - "linux-raw-sys 0.12.1", - "windows-sys 0.61.2", -] - -[[package]] -name = "rustversion" -version = "1.0.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" - -[[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 = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - -[[package]] -name = "sctk-adwaita" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6277f0217056f77f1d8f49f2950ac6c278c0d607c45f5ee99328d792ede24ec" -dependencies = [ - "ab_glyph", - "log", - "memmap2", - "smithay-client-toolkit", - "tiny-skia", -] - -[[package]] -name = "semver" -version = "1.0.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" - -[[package]] -name = "serde" -version = "1.0.228" -source = "registry+https://github.com/rust-lang/crates.io-index" -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.228" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "serde_json" -version = "1.0.151" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14" -dependencies = [ - "itoa", - "memchr", - "serde", - "serde_core", - "zmij", -] - -[[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.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a219298ac11a56ea9a6d2120044824d6f01aeb034955e7af7bc16858527deea" - -[[package]] -name = "simd_cesu8" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94f90157bb87cddf702797c5dadfa0be7d266cdf49e22da2fcaa32eff75b2c33" -dependencies = [ - "rustc_version", - "simdutf8", -] - -[[package]] -name = "simdutf8" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" - -[[package]] -name = "slab" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" - -[[package]] -name = "slotmap" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdd58c3c93c3d278ca835519292445cb4b0d4dc59ccfdf7ceadaab3f8aeb4038" -dependencies = [ - "version_check", -] - -[[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.11.1", - "calloop", - "calloop-wayland-source", - "cursor-icon", - "libc", - "log", - "memmap2", - "rustix 0.38.44", - "thiserror 1.0.69", - "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 = "spirv" -version = "0.4.0+sdk-1.4.341.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9571ea910ebd84c86af4b3ed27f9dbdc6ad06f17c5f96146b2b671e2976744f" -dependencies = [ - "bitflags 2.11.1", -] - -[[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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6637bab7722d379c8b41ba849228d680cc12d0a45ba1fa2b48f2a30577a06731" - -[[package]] -name = "syn" -version = "2.0.117" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "termcolor" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "thiserror" -version = "1.0.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" -dependencies = [ - "thiserror-impl 1.0.69", -] - -[[package]] -name = "thiserror" -version = "2.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" -dependencies = [ - "thiserror-impl 2.0.18", -] - -[[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 = "thiserror-impl" -version = "2.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" -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 = "1.1.1+spec-1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7" -dependencies = [ - "serde_core", -] - -[[package]] -name = "toml_edit" -version = "0.25.11+spec-1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b59c4d22ed448339746c59b905d24568fcbb3ab65a500494f7b8c3e97739f2b" -dependencies = [ - "indexmap", - "toml_datetime", - "toml_parser", - "winnow", -] - -[[package]] -name = "toml_parser" -version = "1.1.2+spec-1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526" -dependencies = [ - "winnow", -] - -[[package]] -name = "tracing" -version = "0.1.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" -dependencies = [ - "pin-project-lite", - "tracing-core", -] - -[[package]] -name = "tracing-core" -version = "0.1.36" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" - -[[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.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" - -[[package]] -name = "unicode-segmentation" -version = "1.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9629274872b2bfaf8d66f5f15725007f635594914870f65218920345aa11aa8c" - -[[package]] -name = "unicode-width" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" - -[[package]] -name = "urlencoding" -version = "2.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" - -[[package]] -name = "utf8parse" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" - -[[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 = "wasip2" -version = "1.0.3+wasi-0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6" -dependencies = [ - "wit-bindgen", -] - -[[package]] -name = "wasm-bindgen" -version = "0.2.121" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49ace1d07c165b0864824eee619580c4689389afa9dc9ed3a4c75040d82e6790" -dependencies = [ - "cfg-if", - "once_cell", - "rustversion", - "wasm-bindgen-macro", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-futures" -version = "0.4.71" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96492d0d3ffba25305a7dc88720d250b1401d7edca02cc3bcd50633b424673b8" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.121" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e68e6f4afd367a562002c05637acb8578ff2dea1943df76afb9e83d177c8578" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.121" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d95a9ec35c64b2a7cb35d3fead40c4238d0940c86d107136999567a4703259f2" -dependencies = [ - "bumpalo", - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.121" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4e0100b01e9f0d03189a92b96772a1fb998639d981193d7dbab487302513441" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "wayland-backend" -version = "0.3.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2857dd20b54e916ec7253b3d6b4d5c4d7d4ca2c33c2e11c6c76a99bd8744755d" -dependencies = [ - "cc", - "downcast-rs", - "rustix 1.1.4", - "scoped-tls", - "smallvec", - "wayland-sys", -] - -[[package]] -name = "wayland-client" -version = "0.31.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "645c7c96bb74690c3189b5c9cb4ca1627062bb23693a4fad9d8c3de958260144" -dependencies = [ - "bitflags 2.11.1", - "rustix 1.1.4", - "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.11.1", - "cursor-icon", - "wayland-backend", -] - -[[package]] -name = "wayland-cursor" -version = "0.31.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a52d18780be9b1314328a3de5f930b73d2200112e3849ca6cb11822793fb34d" -dependencies = [ - "rustix 1.1.4", - "wayland-client", - "xcursor", -] - -[[package]] -name = "wayland-protocols" -version = "0.32.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "563a85523cade2429938e790815fd7319062103b9f4a2dc806e9b53b95982d8f" -dependencies = [ - "bitflags 2.11.1", - "wayland-backend", - "wayland-client", - "wayland-scanner", -] - -[[package]] -name = "wayland-protocols-plasma" -version = "0.3.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b6d8cf1eb2c1c31ed1f5643c88a6e53538129d4af80030c8cabd1f9fa884d91" -dependencies = [ - "bitflags 2.11.1", - "wayland-backend", - "wayland-client", - "wayland-protocols", - "wayland-scanner", -] - -[[package]] -name = "wayland-protocols-wlr" -version = "0.3.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb04e52f7836d7c7976c78ca0250d61e33873c34156a2a1fc9474828ec268234" -dependencies = [ - "bitflags 2.11.1", - "wayland-backend", - "wayland-client", - "wayland-protocols", - "wayland-scanner", -] - -[[package]] -name = "wayland-scanner" -version = "0.31.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c324a910fd86ebdc364a3e61ec1f11737d3b1d6c273c0239ee8ff4bc0d24b4a" -dependencies = [ - "proc-macro2", - "quick-xml", - "quote", -] - -[[package]] -name = "wayland-sys" -version = "0.31.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8eab23fefc9e41f8e841df4a9c707e8a8c4ed26e944ef69297184de2785e3be" -dependencies = [ - "dlib", - "log", - "once_cell", - "pkg-config", -] - -[[package]] -name = "web-sys" -version = "0.3.98" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b572dff8bcf38bad0fa19729c89bb5748b2b9b1d8be70cf90df697e3a8f32aa" -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 = "wgpu" -version = "29.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb3feacc458f7bee8bc1737149b42b6c731aa461039a4264a67bb6681646b250" -dependencies = [ - "arrayvec", - "bitflags 2.11.1", - "bytemuck", - "cfg-if", - "cfg_aliases", - "document-features", - "hashbrown 0.16.1", - "js-sys", - "log", - "naga", - "parking_lot", - "portable-atomic", - "profiling", - "raw-window-handle", - "smallvec", - "static_assertions", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "wgpu-core", - "wgpu-hal", - "wgpu-types", -] - -[[package]] -name = "wgpu-core" -version = "29.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02da3ad1b568337f25513b317870960ef87073ea0945502e44b864b67a8c77b7" -dependencies = [ - "arrayvec", - "bit-set", - "bit-vec", - "bitflags 2.11.1", - "bytemuck", - "cfg_aliases", - "document-features", - "hashbrown 0.16.1", - "indexmap", - "log", - "naga", - "once_cell", - "parking_lot", - "portable-atomic", - "profiling", - "raw-window-handle", - "rustc-hash", - "smallvec", - "thiserror 2.0.18", - "wgpu-core-deps-apple", - "wgpu-core-deps-emscripten", - "wgpu-core-deps-wasm", - "wgpu-core-deps-windows-linux-android", - "wgpu-hal", - "wgpu-naga-bridge", - "wgpu-types", -] - -[[package]] -name = "wgpu-core-deps-apple" -version = "29.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62e51b5447e144b3dbba4feb01f80f4fa21696fa0cd99afb2c3df1affd6fdb28" -dependencies = [ - "wgpu-hal", -] - -[[package]] -name = "wgpu-core-deps-emscripten" -version = "29.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3487cd6293a963bc5c0c0396f6a2192043c50003c07f4efdccbad3d90ec9d819" -dependencies = [ - "wgpu-hal", -] - -[[package]] -name = "wgpu-core-deps-wasm" -version = "29.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c2f2fb042f36920771deb0b966543c5751b18f3d327760ffc90f74e20b2dcd4" -dependencies = [ - "wgpu-hal", -] - -[[package]] -name = "wgpu-core-deps-windows-linux-android" -version = "29.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb01076d0aa08b0ba9bd741e178b5cc440f5abe99d9581323a4c8b5d1a1916" -dependencies = [ - "wgpu-hal", -] - -[[package]] -name = "wgpu-hal" -version = "29.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31f8e1a9e7a8512f276f7c62e018c7fa8d60954303fed2e5750114332049193f" -dependencies = [ - "android_system_properties", - "arrayvec", - "ash", - "bit-set", - "bitflags 2.11.1", - "block2 0.6.2", - "bytemuck", - "cfg-if", - "cfg_aliases", - "glow", - "glutin_wgl_sys", - "gpu-allocator", - "gpu-descriptor", - "hashbrown 0.16.1", - "js-sys", - "khronos-egl", - "libc", - "libloading", - "log", - "naga", - "ndk-sys", - "objc2 0.6.4", - "objc2-core-foundation", - "objc2-foundation 0.3.2", - "objc2-metal 0.3.2", - "objc2-quartz-core 0.3.2", - "once_cell", - "ordered-float", - "parking_lot", - "portable-atomic", - "portable-atomic-util", - "profiling", - "range-alloc", - "raw-window-handle", - "raw-window-metal", - "renderdoc-sys", - "smallvec", - "thiserror 2.0.18", - "wasm-bindgen", - "wayland-sys", - "web-sys", - "wgpu-naga-bridge", - "wgpu-types", - "windows", - "windows-core", - "windows-result", -] - -[[package]] -name = "wgpu-naga-bridge" -version = "29.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59c654c483f058800972c3645e95388a7eca31bf9fe1933bc20e036588a0be02" -dependencies = [ - "naga", - "wgpu-types", -] - -[[package]] -name = "wgpu-types" -version = "29.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9bcc31518a0e9735aefebedb5f7a9ef3ed1c42549c9f4c882fa9060ceaac639" -dependencies = [ - "bitflags 2.11.1", - "bytemuck", - "js-sys", - "log", - "raw-window-handle", - "web-sys", -] - -[[package]] -name = "winapi-util" -version = "0.1.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" -dependencies = [ - "windows-sys 0.61.2", -] - -[[package]] -name = "windows" -version = "0.62.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "527fadee13e0c05939a6a05d5bd6eec6cd2e3dbd648b9f8e447c6518133d8580" -dependencies = [ - "windows-collections", - "windows-core", - "windows-future", - "windows-numerics", -] - -[[package]] -name = "windows-collections" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23b2d95af1a8a14a3c7367e1ed4fc9c20e0a26e79551b1454d72583c97cc6610" -dependencies = [ - "windows-core", -] - -[[package]] -name = "windows-core" -version = "0.62.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" -dependencies = [ - "windows-implement", - "windows-interface", - "windows-link", - "windows-result", - "windows-strings", -] - -[[package]] -name = "windows-future" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1d6f90251fe18a279739e78025bd6ddc52a7e22f921070ccdc67dde84c605cb" -dependencies = [ - "windows-core", - "windows-link", - "windows-threading", -] - -[[package]] -name = "windows-implement" -version = "0.60.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "windows-interface" -version = "0.59.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "windows-link" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" - -[[package]] -name = "windows-numerics" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e2e40844ac143cdb44aead537bbf727de9b044e107a0f1220392177d15b0f26" -dependencies = [ - "windows-core", - "windows-link", -] - -[[package]] -name = "windows-result" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" -dependencies = [ - "windows-link", -] - -[[package]] -name = "windows-strings" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" -dependencies = [ - "windows-link", -] - -[[package]] -name = "windows-sys" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" -dependencies = [ - "windows-targets", -] - -[[package]] -name = "windows-sys" -version = "0.59.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" -dependencies = [ - "windows-targets", -] - -[[package]] -name = "windows-sys" -version = "0.61.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" -dependencies = [ - "windows-link", -] - -[[package]] -name = "windows-targets" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" -dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_gnullvm", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", -] - -[[package]] -name = "windows-threading" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3949bd5b99cafdf1c7ca86b43ca564028dfe27d66958f2470940f73d86d75b37" -dependencies = [ - "windows-link", -] - -[[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_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" - -[[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_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" - -[[package]] -name = "windows_i686_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" - -[[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_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" - -[[package]] -name = "winit" -version = "0.30.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6755fa58a9f8350bd1e472d4c3fcc25f824ec358933bba33306d0b63df5978d" -dependencies = [ - "ahash", - "android-activity", - "atomic-waker", - "bitflags 2.11.1", - "block2 0.5.1", - "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", - "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 = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ee1708bef14716a11bae175f579062d4554d95be2c6829f518df847b7b3fdd0" -dependencies = [ - "memchr", -] - -[[package]] -name = "wit-bindgen" -version = "0.57.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" - -[[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.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9993aa5be5a26815fe2c3eacfc1fde061fc1a1f094bf1ad2a18bf9c495dd7414" -dependencies = [ - "as-raw-xcb-connection", - "gethostname", - "libc", - "libloading", - "once_cell", - "rustix 1.1.4", - "x11rb-protocol", -] - -[[package]] -name = "x11rb-protocol" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea6fc2961e4ef194dcbfe56bb845534d0dc8098940c7e5c012a258bfec6701bd" - -[[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.11.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.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ae8337f8a065cfc972643663ea4279e04e7256de865aa66fe25cec5fb912d3f" - -[[package]] -name = "zerocopy" -version = "0.8.48" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eed437bf9d6692032087e337407a86f04cd8d6a16a37199ed57949d415bd68e9" -dependencies = [ - "zerocopy-derive", -] - -[[package]] -name = "zerocopy-derive" -version = "0.8.48" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "zmij" -version = "1.0.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b" - -[[package]] -name = "zune-core" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d56377fd46368984a170bc5aac5567e52ca5da874caa60bea39fcbca78fb658b" - -[[package]] -name = "zune-jpeg" -version = "0.5.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27bc9d5b815bc103f142aa054f561d9187d191692ec7c2d1e2b4737f8dbd7296" -dependencies = [ - "zune-core", -] diff --git a/Cargo.toml b/Cargo.toml index 0073a97..823c29a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,14 +1,18 @@ [package] #![recursion_limit = "256"] -name = "game" +name = "pool" version = "0.1.0" edition = "2024" +[features] +big_ids = [] +check_ids = [] + [profile.release] strip = true [[bin]] -name = "game" +name = "pool" path = "src/main.rs" [dependencies] @@ -17,7 +21,7 @@ anyhow = "1.0" winit = { version = "0.30", features = ["android-native-activity"] } env_logger = "0.11.10" log = "0.4" -wgpu = "29.0.3" +wgpu = "29.0.4" pollster = "0.4.0" glam = { version = "0.33.3", features = [ "bytemuck" ] } console_error_panic_hook = "0.1.7" @@ -27,7 +31,7 @@ mars = { path = "../Mars" } [target.'cfg(target_arch = "wasm32")'.dependencies] console_error_panic_hook = "0.1.6" -wgpu = { version = "29.0.3", features = ["webgl"]} +wgpu = { version = "30.0.1", features = ["webgl"]} wasm-bindgen = "0.2.121" wasm-bindgen-futures = "0.4.71" console_log = "1.0.0" diff --git a/README.md b/README.md index 37a444e..c51d11c 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ _Pool. Hop in, the water's warm._ -Pool is a lightweight web-enabled multipurpose engine for UI apps and multiplayer games with physics designed to push the boundaries of what defines a contemporary user experience. +Pool is a lightweight web-enabled multipurpose engine for UI apps and multiplayer games with physics. Taking inspiration from the Roblox game engine, Pool ships with its own scripting language, Mars, and shares a similar instance-service model. diff --git a/src/app.rs b/src/app.rs index 0907c8e..3c9653d 100644 --- a/src/app.rs +++ b/src/app.rs @@ -1,8 +1,8 @@ use std::collections::HashMap; // Credit of most code to https://sotrh.github.io/learn-wgpu/ since I'm not familiar with wgpu -use crate::render::Renderer; -use crate::world::{SimpleObject, World}; -use glam::{Affine3A, EulerRot, Mat4, Quat, Vec2, Vec3, Vec4}; +use crate::render::{loader, Renderer}; +use crate::world::{World, ObjectData}; +use glam::{Affine3, Affine3A, EulerRot, Mat4, Quat, Vec2, Vec3, Vec4}; use std::sync::Arc; #[cfg(target_arch = "wasm32")] use wasm_bindgen::prelude::*; @@ -16,6 +16,12 @@ use winit::{ keyboard::{KeyCode, PhysicalKey}, window::Window, }; +use crate::list::Id; +use crate::render::instance::{Material, ModelData}; +use crate::render::instance::material::MaterialProperties; +use crate::render::texture::Texture; +use crate::state; +use crate::world::debug::OctreeDebug; struct Controller { buttons: HashMap, @@ -34,61 +40,61 @@ impl Controller { } pub struct AppState { - world: World, + state: state::State, + world: Id, + debug: OctreeDebug, + debug_model: ModelData, controller: Controller, window: Arc, - clients: Vec, } -const BLOCKS: i32 = 1; +const BLOCKS: i32 = 2; impl AppState { // We don't need this to be async right now, // but we will in the next tutorial pub async fn new(window: Arc) -> Result> { - let mut world = World::new(); - world.add_renderer(Renderer::new(&window).await?); - let mut clients = Vec::new(); - { - let file = world - .renderer - .as_mut() - .unwrap() - .load_from_gltf(include_bytes!("assets/cube.glb")); - let block = file.first_object().unwrap(); - let skybox = world.renderer.as_mut().unwrap().load_texture_from_bytes( - include_bytes!("assets/skybox1.png"), - Some(image::ImageFormat::Png), - ); - world.renderer.as_mut().unwrap().set_skybox(skybox); - //let color = &renderer.load_texture_from_bytes(include_bytes!("assets/plank/color.png")); - //let normal = &renderer.load_texture_from_bytes(include_bytes!("assets/plank/normal.png")); - //let roughness = &renderer.load_texture_from_bytes(include_bytes!("assets/plank/roughness.png")); - //let mat = renderer.new_material(color,normal,roughness); - for x in -BLOCKS..BLOCKS { - for y in -BLOCKS..BLOCKS { - let block = block.hard_clone(); - world.add_object(block.clone()); - { - let mut model = block.0.borrow_mut(); - model.model.as_mut().unwrap().instance.transform = Mat4::from_translation( - Vec3::new(-x as f32 * 3.0, -8.0, -y as f32 * 3.0), - ) - * Mat4::from_rotation_z((x * y) as f32 / 1.23); - model.model.as_mut().unwrap().instance.color = Vec4::new( + let mut state = state::State::new(); + let (world,debug,debug_model) = { + let mut world = state.worlds.make(World::new()); + state.renderer = Some(Renderer::new(&window).await?); + let renderer = state.renderer.as_mut().unwrap(); + let debug_file = loader::load_from_gltf(renderer,include_bytes!("assets/debug.glb")); + let debug_model = debug_file.first_object().unwrap().model.unwrap(); + { + let file = loader::load_from_gltf(renderer,include_bytes!("assets/sphere.glb")); + let mut block = file.first_object().unwrap(); + let skybox = Texture::load_from_file_bytes(renderer,include_bytes!("assets/skybox2.png"), None); + renderer.set_skybox(skybox.unwrap()); + let color = Texture::load_from_file_bytes(renderer,include_bytes!("assets/plank/color.png"), None); + let normal = Texture::load_from_file_bytes(renderer,include_bytes!("assets/plank/normal.png"), None); + let roughness = Texture::load_from_file_bytes(renderer,include_bytes!("assets/plank/roughness.png"), None); + let mat = Material::new(renderer, &color.unwrap(), &normal.unwrap(), &roughness.unwrap(), MaterialProperties::default()); + block.model.as_mut().unwrap().material = mat; + for x in -BLOCKS..=BLOCKS { + for y in -BLOCKS..=BLOCKS { + let id = world.add_object(state.objects.make(block.clone())); + let block = state.objects.get(&id); + block.set_affine(Affine3::from_translation( + Vec3::new(-x as f32 * 3.0, -2.0, -y as f32 * 3.0) + )); + block.model.as_mut().unwrap().instance.color = Vec4::new( 0.3, (x + BLOCKS) as f32 / BLOCKS as f32, (y + BLOCKS) as f32 / BLOCKS as f32, 1.0, ); } - clients.push(block) } } - } + let debug = OctreeDebug::new(); + (world.id,debug,debug_model) + }; Ok(Self { + state, world, - clients, + debug, + debug_model, controller: Controller::new(), window, }) @@ -101,7 +107,7 @@ impl AppState { pub fn resize(&mut self, width: u32, height: u32) { if width > 0 && height > 0 { - self.world.renderer.as_mut().unwrap().resize(width, height); + self.state.renderer.as_mut().unwrap().resize(width, height); } } @@ -114,7 +120,7 @@ impl AppState { (KeyCode::Escape, true) => event_loop.exit(), (KeyCode::Space, true) => {} (KeyCode::KeyR, true) => { - self.world.renderer.as_mut().unwrap().eye.frame = Affine3A::IDENTITY + self.state.renderer.as_mut().unwrap().eye.frame = Affine3A::IDENTITY } _ => {} } @@ -123,7 +129,7 @@ impl AppState { fn handle_mouse_moved(&mut self, position: PhysicalPosition) { if let Some(true) = self.controller.buttons.get(&MouseButton::Right) { - self.world.renderer.as_mut().unwrap().eye.rotate( + self.state.renderer.as_mut().unwrap().eye.rotate( position.x as f32 - self.controller.mouse.x, position.y as f32 - self.controller.mouse.y, ); @@ -175,6 +181,8 @@ impl ApplicationHandler for App { let window = Arc::new(event_loop.create_window(window_attributes).unwrap()); + window.set_title("Pool"); + #[cfg(not(target_arch = "wasm32"))] { // If we are not on web we can use pollster to @@ -231,15 +239,14 @@ impl ApplicationHandler for App { WindowEvent::CloseRequested => event_loop.exit(), WindowEvent::Resized(size) => state.resize(size.width, size.height), WindowEvent::RedrawRequested => { + use std::time::Instant; + let now = Instant::now(); + state.update(); let mut movement = Vec3::new(0.0, 0.0, 0.0); let pressed = |keycode: KeyCode| { - if let Some(true) = state.controller.keys.get(&keycode) { - true - } else { - false - } + matches!(state.controller.keys.get(&keycode), Some(true)) }; if pressed(KeyCode::KeyA) { @@ -260,15 +267,12 @@ impl ApplicationHandler for App { if pressed(KeyCode::KeyQ) { movement.y -= 1.0; } - - state - .world - .renderer - .as_mut() - .unwrap() - .eye - .control(movement * 0.1); - match state.world.renderer.as_mut().unwrap().render(&state.window) { + let world = state.state.worlds.get(&state.world); + state.debug.set(&mut state.state.objects, world, Some(state.debug_model.clone())); + state.debug.register(&mut state.state.objects,state.state.renderer.as_mut().unwrap()); + world.step(&mut state.state.renderer, &mut state.state.objects, &mut state.state.lights); + state.state.renderer.as_mut().unwrap().eye.control(movement * 0.1); + match state.state.renderer.as_mut().unwrap().render(&state.window,&mut state.state.objects) { Ok(_) => {} Err(e) => { // Log the error and exit gracefully @@ -276,19 +280,9 @@ impl ApplicationHandler for App { event_loop.exit(); } } - for object in state.clients.iter() { - object - .0 - .borrow_mut() - .model - .as_mut() - .unwrap() - .instance - .transform *= Mat4::from_rotation_translation( - Quat::from_euler(EulerRot::XYZ, 0.001, -0.001, 0.001), - Vec3::new(0.0, 0.0, 0.0), - ); - } + + let elapsed = now.elapsed(); + //println!("Elapsed {:.2?}",elapsed); } WindowEvent::MouseInput { button, diff --git a/src/assets/debug.glb b/src/assets/debug.glb index 13fe9af..9f1f226 100644 Binary files a/src/assets/debug.glb and b/src/assets/debug.glb differ diff --git a/src/assets/skybox2.png b/src/assets/skybox2.png new file mode 100644 index 0000000..e828de1 Binary files /dev/null and b/src/assets/skybox2.png differ diff --git a/src/lib.rs b/src/lib.rs index 6c22f2e..edba5d1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,23 @@ #![recursion_limit = "256"] + +use std::error::Error; +use std::fmt::{Display, Formatter}; + pub mod app; pub mod render; pub mod web; -pub mod world; \ No newline at end of file +pub mod world; +pub mod list; +pub mod state; +pub mod net; + +#[derive(Debug)] +struct PoolError(String); + +impl Display for PoolError { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.0) + } +} + +impl Error for PoolError {} \ No newline at end of file diff --git a/src/list.rs b/src/list.rs new file mode 100644 index 0000000..c1eb01f --- /dev/null +++ b/src/list.rs @@ -0,0 +1,185 @@ +use std::hash::{Hash, Hasher}; +use std::marker::PhantomData; +use std::mem::ManuallyDrop; +use std::ops::{Deref, DerefMut}; +use std::sync::Mutex; + +type Index = u32; + +pub struct Element { + it: Option, + count: Index, +} + +pub struct FreeList { + items: Vec>, + free: Vec, +} + +#[derive(Eq,Hash,PartialEq)] +pub struct SingleId { + index: Index, + phantom_data: PhantomData +} + +impl From> for Id { + fn from(value: SingleId) -> Self { + Id { + index: value.index, + phantom_data: PhantomData, + } + } +} + +impl SingleId { + pub(crate) fn shared(self) -> Id { + Id { + index: self.index, + phantom_data: self.phantom_data + } + } +} + +pub struct Id { + index: Index, + phantom_data: PhantomData, +} + +pub struct RefId<'a, T> { + pub id: Id, + it: &'a mut T +} + +impl<'a, T> Deref for RefId<'a, T> { + type Target = T; + + fn deref(&self) -> &Self::Target { + self.it + } +} + +impl<'a, T> DerefMut for RefId<'a, T> { + + fn deref_mut(&mut self) -> &mut Self::Target { + self.it + } +} + +impl From> for Id { + fn from(value: RefId) -> Self { + value.id + } +} + +impl Clone for Id { + fn clone(&self) -> Self { + Id { + index: self.index, + phantom_data: PhantomData::default(), + } + } +} + +impl PartialEq for Id { + fn eq(&self, other: &Self) -> bool { + self.index == other.index + } +} + +impl Eq for Id {} + +impl Hash for Id { + fn hash(&self, state: &mut H) { + self.index.hash(state) + } +} + +impl Id { + pub fn maybe(self) -> MaybeId { + MaybeId(self) + } +} + +pub struct MaybeId(Id); + +impl From> for MaybeId { + fn from(value: Id) -> Self { + MaybeId(value) + } +} + +impl Clone for MaybeId { + fn clone(&self) -> Self { + if self.0.index != u32::MAX { + MaybeId(self.0.clone()) + } else { + MaybeId::NULL + } + } +} + +impl MaybeId { + pub const NULL: MaybeId = MaybeId(Id { index: u32::MAX, phantom_data: PhantomData {}, }); + pub fn unwrap(self) -> Id { + if self.0.index == u32::MAX { + panic!() + } else { + self.0 + } + } + pub fn exists(&self) -> Option> { + if self.0.index == u32::MAX { + None + } else { + Some(self.0.clone()) + } + } +} + +impl Default for FreeList { + fn default() -> Self { + Self::new() + } +} + +impl FreeList { + pub fn new() -> FreeList { + FreeList { + items: Vec::new(), + free: Vec::new(), + } + } + pub fn get(&mut self, id: &Id) -> &mut T { + self.items[id.index as usize].as_mut().unwrap() + } + pub fn get_ref(&mut self, id: Id) -> RefId<'_, T> { + let it = self.get(&id); + RefId { id, it } + } + pub fn remove(&mut self, id: Id) -> T { + self.free.push(id.index); + self.items[id.index as usize].take().unwrap() + } + pub fn make(&mut self, value: T) -> RefId<'_, T> { // todo: shouldn't panic if allocation fails + if let Some(free) = self.free.pop() { + self.items[free as usize] = Some(value); + RefId { + id: Id { + index: free, + phantom_data: PhantomData, + }, + it: self.items[free as usize].as_mut().unwrap(), + } + } else { + self.items.push(Some(value)); + let index = (self.items.len() - 1) as Index; + RefId { + id: Id { + index, + phantom_data: PhantomData, + }, + it: self.items[index as usize].as_mut().unwrap(), + } + } + } +} diff --git a/src/main.rs b/src/main.rs index 9ae830d..7b3961b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,6 @@ #![recursion_limit = "256"] -use game::*; +use pool::*; fn main() { app::run().unwrap(); } diff --git a/src/net/mod.rs b/src/net/mod.rs new file mode 100644 index 0000000..e69de29 diff --git a/src/render/eye.rs b/src/render/eye.rs index 11b7112..17fce37 100644 --- a/src/render/eye.rs +++ b/src/render/eye.rs @@ -1,9 +1,10 @@ -use crate::render::{MaterialProperties, SimpleTexture}; +use crate::render::{Texture}; use bytemuck::{Pod, Zeroable}; use glam::camera::lh::proj::directx::perspective; use glam::{Affine3A, EulerRot, Mat3A, Mat4, Vec3, Vec4}; use wgpu::util::DeviceExt; use wgpu::{Device, Queue}; +use crate::render::instance::material::MaterialProperties; pub(crate) struct Eye { pub(crate) frame: Affine3A, @@ -16,6 +17,7 @@ pub(crate) struct Eye { pub(crate) camera_buffer: wgpu::Buffer, pub(crate) layout: wgpu::BindGroupLayout, pub(crate) group: wgpu::BindGroup, + pub sky_pipeline: wgpu::RenderPipeline, } #[repr(C)] @@ -49,7 +51,7 @@ impl Eye { bytemuck::cast_slice(&[self.environment]), ); } - pub(crate) fn new(device: &Device, width: u32, height: u32, skybox: SimpleTexture) -> Eye { + pub(crate) fn new(device: &Device, config: &wgpu::SurfaceConfiguration, width: u32, height: u32, skybox: Texture) -> Eye { let camera_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { label: Some("Camera Buffer"), contents: bytemuck::cast_slice(&[ @@ -63,7 +65,7 @@ impl Eye { let dir = Vec3::new(1.0, 0.5, 1.0).normalize(); let environment = Environment { - ambient: Vec4::new(0.15, 0.15, 0.15, 0.0), + ambient: Vec4::new(0.1, 0.1, 0.1, 0.0), light: Vec4::new(1.0, 1.0, 1.0, 0.0), dir: Vec4::new(dir.x, dir.y, dir.z, 0.0), }; @@ -116,6 +118,51 @@ impl Eye { label: Some("eye_bind_group_layout"), }); + let shader = device.create_shader_module(wgpu::include_wgsl!("sky.wgsl")); + + let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { + label: Some("Render Pipeline Layout"), + bind_group_layouts: &[Some(&layout)], + immediate_size: 0, + }); + + //todo: use a pipeline cache! + let sky_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { + label: Some("Sky Pipeline"), + layout: Some(&pipeline_layout), + vertex: wgpu::VertexState { + module: &shader, + entry_point: Some("vs_sky"), + compilation_options: Default::default(), + buffers: &[], + }, + fragment: Some(wgpu::FragmentState { + module: &shader, + entry_point: Some("fs_sky"), + compilation_options: Default::default(), + targets: &[Some(wgpu::ColorTargetState { + // 4. + format: config.format, + blend: Some(wgpu::BlendState::REPLACE), + write_mask: wgpu::ColorWrites::ALL, + })], + }), + primitive: wgpu::PrimitiveState { + front_face: wgpu::FrontFace::Cw, + ..Default::default() + }, + depth_stencil: Some(wgpu::DepthStencilState { + format: wgpu::TextureFormat::Depth32Float, + depth_write_enabled: Some(false), + depth_compare: Some(wgpu::CompareFunction::LessEqual), + stencil: wgpu::StencilState::default(), + bias: wgpu::DepthBiasState::default(), + }), + multisample: wgpu::MultisampleState::default(), + multiview_mask: None, + cache: None, + }); + let group = Eye::bind_group(&layout, device, &camera_buffer, &environment_buffer, skybox); Eye { @@ -129,6 +176,7 @@ impl Eye { layout, environment, environment_buffer, + sky_pipeline, } } fn bind_group( @@ -136,7 +184,7 @@ impl Eye { device: &wgpu::Device, camera: &wgpu::Buffer, environment: &wgpu::Buffer, - skybox: SimpleTexture, + skybox: Texture, ) -> wgpu::BindGroup { device.create_bind_group(&wgpu::BindGroupDescriptor { layout: &layout, @@ -163,7 +211,7 @@ impl Eye { label: Some("eye_bind_group"), }) } - pub fn skybox(&mut self, device: &wgpu::Device, texture: SimpleTexture) { + pub fn skybox(&mut self, device: &wgpu::Device, texture: Texture) { self.group = Eye::bind_group( &self.layout, device, @@ -172,8 +220,9 @@ impl Eye { texture, ) } - pub(crate) fn resize(&mut self, width: u32, height: u32) { - self.aspect_ratio = width as f32 / height as f32 + pub(crate) fn resize(&mut self, queue: &Queue, width: u32, height: u32) { + self.aspect_ratio = width as f32 / height as f32; + self.write(queue); } pub(crate) fn control(&mut self, delta: Vec3) { self.frame *= Affine3A::from_translation(delta); diff --git a/src/assets/SimpleShader.wgsl b/src/render/instance/instance.wgsl similarity index 74% rename from src/assets/SimpleShader.wgsl rename to src/render/instance/instance.wgsl index 7a9a592..e882b6e 100644 --- a/src/assets/SimpleShader.wgsl +++ b/src/render/instance/instance.wgsl @@ -15,7 +15,6 @@ struct Eye { frame: mat4x4, } -// Vertex shader @group(0) @binding(0) var eye: Eye; @group(0) @binding(1) @@ -88,31 +87,36 @@ var t_rough: texture_2d; fn sky_aspect(look: vec3) -> vec4 { var pi = 3.14159; let u_angle = atan2(look.x,look.z); - let u = (u_angle/pi) + 0.5; // from -pi/2 -> pi/2 into 0 -> 1 + let u = (u_angle/pi) * 0.5 + 0.5; // from -pi/2 -> pi/2 into 0 -> 1 let v_angle = atan2(-look.y,sqrt(look.x * look.x + look.z * look.z)); - let v = (v_angle/pi) + 0.5;//(v_angle/pi) + 0.5; // from -pi/2 -> pi/2 into 0 -> 1 + let v = (v_angle/pi) - 0.5;//(v_angle/pi) + 0.5; // from -pi/2 -> pi/2 into 0 -> 1 let uv = vec2(u,v); // Get UV on skybox return textureSample(sky_texture, sky_sampler, uv); } -fn rotation(mat: mat4x4) -> mat3x3 { +fn rotation(it: mat4x4) -> mat3x3 { return mat3x3( - mat[0].xyz, - mat[1].xyz, - mat[2].xyz, + it[0].xyz, + it[1].xyz, + it[2].xyz, ); } -fn translation(mat: mat4x4) -> vec4 { - //return vec4(mat[0][3],mat[1][3],mat[2][3],mat[3][3]); - return mat[3]; +fn translation(it: mat4x4) -> vec4 { + return it[3]; +} + +fn light_aspect(light: vec3, dir: vec3) -> vec4 { + return vec4(0.0,0.0,0.0,0.0); } @fragment fn fs_main(in: VertexOutput) -> @location(0) vec4 { let object_color: vec4 = textureSample(t_diffuse, s_diffuse, in.tex_coords); let object_normal: vec4 = textureSample(t_normal, s_diffuse, in.tex_coords); + let object_rough: vec4 = textureSample(t_rough, s_diffuse, in.tex_coords); + let diffuse_result = object_color.xyz * environment.ambient.xyz; let diffuse_color = object_color.xyz; let specular_color = vec3(0.0,0.0,0.0); let reflection = sky_aspect(reflect(normalize(in.world_position-translation(eye.frame).xyz),normalize(in.world_normal))); @@ -129,35 +133,13 @@ fn fs_main(in: VertexOutput) -> @location(0) vec4 { //let specular_strength = pow(max(dot(tangent_normal, half_dir), 0.0), 32.0); //let specular_color = specular_strength * environment.light.xyz; - let result = (environment.ambient.xyz + diffuse_color.xyz + specular_color.xyz) * object_color.xyz; + let reflect_factor = pow(object_rough.x,3); - return vec4(reflection.xyz,object_color.a); -} + let diffuse_brightness = length(diffuse_color); -struct SkyOutput { - @builtin(position) position: vec4, - @location(0) pos: vec4 // unadulterated by WGSL -} + let diffuse_effect = (diffuse_result * (1 - reflect_factor)) + reflection.xyz * reflect_factor * diffuse_brightness; -const TRI_VERTICES = array( - vec4(-1.0, -1.0, 1.0, 1.0), - vec4(-1.0, 1.0, 1.0, 1.0), - vec4( 1.0, -1.0, 1.0, 1.0), - vec4( 1.0, 1.0, 1.0, 1.0), - vec4(-1.0, 1.0, 1.0, 1.0), - vec4( 1.0, -1.0, 1.0, 1.0), -); + let result = (diffuse_effect.xyz + specular_color.xyz); -@vertex -fn vs_sky(@builtin(vertex_index) index: u32) -> SkyOutput { - var out: SkyOutput; - out.position = TRI_VERTICES[index]; - out.pos = out.position; - return out; -} - -@fragment -fn fs_sky(in: SkyOutput) -> @location(0) vec4 { - let look = rotation(eye.frame) * in.pos.xyz; - return sky_aspect(look); -} + return vec4(result.xyz,object_color.a); +} \ No newline at end of file diff --git a/src/render/instance/material.rs b/src/render/instance/material.rs new file mode 100644 index 0000000..cf994d2 --- /dev/null +++ b/src/render/instance/material.rs @@ -0,0 +1,130 @@ +use wgpu::Device; +use crate::list::{FreeList, Id}; +use crate::render::Renderer; +use crate::render::texture::Texture; + +pub struct Materials { + pub(crate) layout: wgpu::BindGroupLayout, + pub(crate) list: FreeList, + default: Material, +} + +impl Materials { + pub(crate) fn new(device: &Device, default: Texture) -> Materials { + fn texture_bind_group_layout_entry(binding: u32) -> wgpu::BindGroupLayoutEntry { + wgpu::BindGroupLayoutEntry { + binding, + visibility: wgpu::ShaderStages::FRAGMENT, + ty: wgpu::BindingType::Texture { + multisampled: false, + view_dimension: wgpu::TextureViewDimension::D2, + sample_type: wgpu::TextureSampleType::Float { filterable: true }, + }, + count: None, + } + } + + let layout = + device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + entries: &[ + wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStages::FRAGMENT, + ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering), + count: None, + }, + texture_bind_group_layout_entry(1), + texture_bind_group_layout_entry(2), + texture_bind_group_layout_entry(3), + ], + label: Some("texture_bind_group_layout"), + }); + + let default = Material::_new( + &device, + &layout, + &default, + &default, + &default, + MaterialProperties::default(), + ); + + Materials { + layout, + list: Default::default(), + default, + } + } +} + +#[derive(Clone)] +pub struct Material { + pub(crate) group: wgpu::BindGroup, +} + +pub struct MaterialProperties { + pub(crate) edge: wgpu::AddressMode, + pub(crate) filter: wgpu::FilterMode, +} + +impl Default for MaterialProperties { + fn default() -> MaterialProperties { + MaterialProperties { + edge: wgpu::AddressMode::Repeat, + filter: wgpu::FilterMode::Linear, + } + } +} + +impl MaterialProperties { + pub(crate) fn sampler(&self, device: &wgpu::Device) -> wgpu::Sampler { + device.create_sampler(&wgpu::SamplerDescriptor { + address_mode_u: self.edge, + address_mode_v: self.edge, + address_mode_w: self.edge, + mag_filter: self.filter, + min_filter: self.filter, + mipmap_filter: wgpu::MipmapFilterMode::Nearest, + ..Default::default() + }) + } +} + +impl Material { + pub(crate) fn _new( + device: &wgpu::Device, + layout: &wgpu::BindGroupLayout, + base: &Texture, + normal: &Texture, + reflect: &Texture, + config: MaterialProperties, + ) -> Material { + let sampler = config.sampler(&device); + let group = device.create_bind_group(&wgpu::BindGroupDescriptor { + layout, + entries: &[ + wgpu::BindGroupEntry { + binding: 0, + resource: wgpu::BindingResource::Sampler(&sampler), + }, + wgpu::BindGroupEntry { + binding: 1, + resource: wgpu::BindingResource::TextureView(&base.view), + }, + wgpu::BindGroupEntry { + binding: 2, + resource: wgpu::BindingResource::TextureView(&normal.view), + }, + wgpu::BindGroupEntry { + binding: 3, + resource: wgpu::BindingResource::TextureView(&reflect.view), + }, + ], + label: Some("diffuse_bind_group"), + }); + Material { group } + } + pub fn new(renderer: &mut Renderer, base: &Texture, normal: &Texture, reflect: &Texture, config: MaterialProperties) -> Id { + renderer.instances.materials.list.make(Material::_new(&renderer.device, &renderer.instances.materials.layout, base, normal, reflect, config)).id + } +} \ No newline at end of file diff --git a/src/render/instance/mod.rs b/src/render/instance/mod.rs new file mode 100644 index 0000000..b7384dd --- /dev/null +++ b/src/render/instance/mod.rs @@ -0,0 +1,376 @@ +pub mod material; + +use std::ops::Range; +use bytemuck::{Pod, Zeroable}; +use glam::{Affine3, Mat4, Vec4}; +use wgpu::{BindGroup, Device}; +use wgpu::naga::FastHashMap; +use crate::list::{FreeList, Id, RefId}; +use crate::render::{instance, Renderer}; +use crate::render::eye::Eye; +pub(crate) use crate::render::instance::material::{Material, Materials}; +use crate::render::mesh::{Mesh, TangentVertex}; +use crate::render::texture::Texture; +use crate::world::ObjectData; + +#[repr(C)] +#[derive(Pod, Zeroable, Copy, Clone)] +pub struct ModelInstance { + pub transform: Mat4, + pub color: Vec4, + pub lights: [u16; 16], + pub point_lights: u32, + pub spot_lights: u32, + pub metal: f32, + pub rough: f32, +} + +#[repr(C)] +#[derive(Pod, Copy, Clone, Zeroable)] +pub struct LightInstance { + pub location: Vec4, + pub rotation: Vec4, + pub color: Vec4, +} + +#[derive(Clone)] +pub struct LightData { + pub instance: LightInstance, + pub transform: Affine3, +} + +#[derive(Clone)] +pub struct ModelData { + pub instance: ModelInstance, + pub material: Id, + pub mesh: Id, +} + +pub struct Instances { + pub materials: Materials, + light_instances: FreeList, + model_instances: FreeList, + pub(crate) pipeline: wgpu::RenderPipeline, + light_count: usize, + light_buffer: wgpu::Buffer, + model_count: usize, + pub(crate) model_buffer: wgpu::Buffer, + models_flag: bool, + pub(crate) program: Program, + models: FastHashMap, FastHashMap, FastHashMap,bool>>>, +} + +pub enum Code { + Material(Material), + Mesh(Mesh), + Draw(Range), +} + +pub struct Program(pub Vec); + +impl Program { + fn push(&mut self, item: Code) { + self.0.push(item) + } + fn new() -> Program { + Program(Vec::new()) + } + pub(crate) fn render(self, pass: &mut wgpu::RenderPass) { + let mut count = 0; + let mut indexed = false; + for code in self.0 { + match code { + Code::Material(material) => pass.set_bind_group( + Renderer::SIMPLE_RENDER_TEXTURE_GROUP_POSITION, + &material.group, + &[], + ), + Code::Mesh(Mesh {vertices, indices, ..}) => { + pass.set_vertex_buffer(0, vertices.0.slice(..)); + if let Some(indices) = indices { + pass.set_index_buffer(indices.0.slice(..), wgpu::IndexFormat::Uint32); + count = indices.1; + indexed = true; + } else { + count = vertices.1; + indexed = false; + } + } + Code::Draw(instances) => { + if indexed { + pass.draw_indexed(0..count, 0, instances) + } else { + pass.draw(0..count, instances); + } + } + } + } + } +} + +impl Instances { + const MIN_SIZE: u64 = 64; + pub fn register_object(&mut self, mut object: RefId) { + let model = object.model.as_mut().unwrap(); + self.model_count += 1; + self.models + .entry(model.mesh.clone()).or_default() + .entry(model.material.clone()).or_default() + .insert(object.into(),self.models_flag); + } + /*pub fn register_light(&mut self, light: Id) { + self.light_count += 1; + self.lights.insert(light); + }*/ + pub fn reallocate_buffer( + device: &wgpu::Device, + buffer: &mut wgpu::Buffer, + count: usize, + item_size: usize, + ) { + let size = buffer.size() / item_size as wgpu::BufferAddress; + if count > Instances::MIN_SIZE as usize { + let mut reallocate: Option = None; + if count < (size / 2) as usize { + reallocate = Some(count / 2); + } else if count > size as usize { + reallocate = Some(count * 2); + } + if let Some(new_size) = reallocate { + *buffer = device.create_buffer(&wgpu::BufferDescriptor { + label: Some("Instance Buffer"), + size: (item_size * new_size) as wgpu::BufferAddress, + usage: wgpu::BufferUsages::COPY_DST | wgpu::BufferUsages::VERTEX, + mapped_at_creation: false, + }); + } + } + } + /*pub fn write_lights(&mut self, device: &wgpu::Device, queue: &wgpu::Queue) { + //SimpleInstances::reallocate_buffer(device, queue, &mut self.light_ref_buffer, self.light_ref_last, size_of::()); + /* + let mut light_ref_buffer = queue.write_buffer_with( + &self.light_ref_buffer, + 0 as wgpu::BufferAddress, + wgpu::BufferSize::new(self.instance_buffer.size()).unwrap() + ).unwrap(); + */ + Instances::reallocate_buffer( + device, + &mut self.light_buffer, + self.light_count, + size_of::(), + ); + let mut buffer = queue + .write_buffer_with( + &self.light_buffer, + 0 as wgpu::BufferAddress, + wgpu::BufferSize::new(self.light_buffer.size()).unwrap(), + ) + .unwrap(); + let stride = size_of::(); + for (new_index, (light, index)) in self.lights.iter_mut().enumerate() { + *index = new_index + 1; + let begin = *index * stride; + buffer + .slice(begin..begin + stride) + .copy_from_slice(bytemuck::cast_slice(&[light.0.borrow().instance])); + } + }*/ + pub(crate) fn write_instances( + &mut self, + device: &wgpu::Device, + queue: &wgpu::Queue, + mesh_list: &mut FreeList, + objects_list: &mut FreeList, + ) { + Instances::reallocate_buffer( + device, + &mut self.model_buffer, + self.model_count, + size_of::(), + ); + let mut buffer = queue + .write_buffer_with( + &self.model_buffer, + 0 as wgpu::BufferAddress, + wgpu::BufferSize::new(self.model_buffer.size()).unwrap(), + ) + .unwrap(); + let mut index: u32 = 0; + let stride = size_of::(); + for (mesh, materials) in self.models.iter_mut() { + self.program.push(Code::Mesh(mesh_list.get(mesh).clone())); + for (material, objects) in materials.iter_mut() { + self.program.push(Code::Material(self.materials.list.get(material).clone())); + let before = index; + objects.retain(|object,flag| { + let object = objects_list.get(object); + if *flag == self.models_flag { + let begin = index as usize * stride; + buffer.slice(begin..begin + stride).copy_from_slice(bytemuck::cast_slice(&[object.model.as_mut().unwrap().instance])); + index += 1; + true + } else { + false + } + }); + self.program.push(Code::Draw(before..index)); + } + } + //println!("objects: {}",index); + self.models_flag = !self.models_flag; + } + + pub(crate) fn desc() -> wgpu::VertexBufferLayout<'static> { + wgpu::VertexBufferLayout { + array_stride: size_of::() as wgpu::BufferAddress, + step_mode: wgpu::VertexStepMode::Instance, + attributes: &[ + // todo: is this too big? + wgpu::VertexAttribute { + offset: 0, + shader_location: 4, + format: wgpu::VertexFormat::Float32x4, + }, + wgpu::VertexAttribute { + offset: size_of::<[f32; 4]>() as wgpu::BufferAddress, + shader_location: 5, + format: wgpu::VertexFormat::Float32x4, + }, + wgpu::VertexAttribute { + offset: size_of::<[f32; 8]>() as wgpu::BufferAddress, + shader_location: 6, + format: wgpu::VertexFormat::Float32x4, + }, + wgpu::VertexAttribute { + offset: size_of::<[f32; 12]>() as wgpu::BufferAddress, + shader_location: 7, + format: wgpu::VertexFormat::Float32x4, + }, + wgpu::VertexAttribute { + offset: size_of::<[f32; 16]>() as wgpu::BufferAddress, + shader_location: 8, + format: wgpu::VertexFormat::Float32x4, + }, + wgpu::VertexAttribute { + offset: size_of::<[f32; 16]>() as wgpu::BufferAddress, + shader_location: 9, + format: wgpu::VertexFormat::Float32x4, + }, + wgpu::VertexAttribute { + offset: size_of::<[f32; 16]>() as wgpu::BufferAddress, + shader_location: 10, + format: wgpu::VertexFormat::Float32x4, + }, + wgpu::VertexAttribute { + offset: size_of::<[f32; 16]>() as wgpu::BufferAddress, + shader_location: 11, + format: wgpu::VertexFormat::Float32x4, + }, + ], + } + } + + pub fn new(device: &wgpu::Device, eye: &Eye, config: &wgpu::SurfaceConfiguration, default: Texture) -> Instances { + let instance_buffer = device.create_buffer(&wgpu::BufferDescriptor { + label: Some("Instance Buffer"), + size: (size_of::() * Instances::MIN_SIZE as usize) + as wgpu::BufferAddress, + usage: wgpu::BufferUsages::VERTEX | wgpu::BufferUsages::COPY_DST, + mapped_at_creation: false, + }); + + let light_buffer = device.create_buffer(&wgpu::BufferDescriptor { + label: Some("Light Buffer"), + size: (size_of::() * Instances::MIN_SIZE as usize) + as wgpu::BufferAddress, + usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST, + mapped_at_creation: false, + }); + + /*let light_ref_buffer = device.create_buffer(&wgpu::BufferDescriptor { + label: Some("Light Ref Buffer"), + size: (size_of::() * SimpleInstances::MIN_SIZE as usize) as wgpu::BufferAddress, + usage: wgpu::BufferUsages::STORAGE | wgpu::BufferUsages::COPY_DST, + mapped_at_creation: false, + });*/ + + let materials = Materials::new(device, default); + + let shader = device.create_shader_module(wgpu::include_wgsl!("instance.wgsl")); + + let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { + label: Some("Render Pipeline Layout"), + bind_group_layouts: &[Some(&eye.layout), Some(&materials.layout)], + immediate_size: 0, + }); + + let instance_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { + label: Some("Render Pipeline"), + layout: Some(&pipeline_layout), + vertex: wgpu::VertexState { + module: &shader, + entry_point: Some("vs_main"), + buffers: &[TangentVertex::desc(), Instances::desc()], + compilation_options: wgpu::PipelineCompilationOptions::default(), + }, + fragment: Some(wgpu::FragmentState { + // 3. + module: &shader, + entry_point: Some("fs_main"), + targets: &[Some(wgpu::ColorTargetState { + // 4. + format: config.format, + blend: Some(wgpu::BlendState::REPLACE), + write_mask: wgpu::ColorWrites::ALL, + })], + compilation_options: wgpu::PipelineCompilationOptions::default(), + }), + primitive: Default::default(), /*wgpu::PrimitiveState { + topology: wgpu::PrimitiveTopology::TriangleList, + strip_index_format: None, + front_face: wgpu::FrontFace::Ccw, + cull_mode: None, + polygon_mode: wgpu::PolygonMode::Fill, + unclipped_depth: false, + conservative: false, + }*/ + depth_stencil: Some(wgpu::DepthStencilState { + stencil: wgpu::StencilState::default(), + format: wgpu::TextureFormat::Depth32Float, + depth_write_enabled: Some(true), + depth_compare: Some(wgpu::CompareFunction::Less), + bias: wgpu::DepthBiasState::default(), + }), + multisample: wgpu::MultisampleState { + count: 1, + mask: !0, + alpha_to_coverage_enabled: false, + }, + multiview_mask: None, + cache: None, + }); + + Instances { + materials, + light_instances: Default::default(), + model_instances: Default::default(), + pipeline: instance_pipeline, + light_count: 0, + //light_ref_last: 0, + model_count: 0, + light_buffer, + model_buffer: instance_buffer, + //light_ref_buffer, + //lights: Default::default(), + models_flag: false, + program: Program(Vec::new()), + models: Default::default(), + } + } + + pub fn render() { + + } +} \ No newline at end of file diff --git a/src/render/loader.rs b/src/render/loader.rs new file mode 100644 index 0000000..0f0ee8b --- /dev/null +++ b/src/render/loader.rs @@ -0,0 +1,302 @@ +use std::collections::HashMap; +use glam::{Mat4, Vec3, Vec4}; +use gltf::Semantic; +use wgpu::{Device, Queue}; +use wgpu::util::DeviceExt; +use crate::list::{FreeList, Id, RefId}; +use crate::render::instance::{Material, Materials, ModelData, ModelInstance}; +use crate::render::instance::material::MaterialProperties; +use crate::render::mesh::{Mesh, TangentVertex}; +use crate::render::texture::{Texture, TextureProperties}; +use crate::render::{Renderer, Textures}; +use crate::world::{ObjectData, AABB, ColliderData, Shape}; + +pub struct TreeNode { + object: Option, + children: Vec, + name: String, +} + +impl TreeNode { + pub fn first_object(&self) -> Option { + if let Some(object) = self.object.clone() { + Some(object) + } else { + for child in self.children.iter() { + if let Some(object) = child.first_object() { + return Some(object); + } + } + None + } + } +} + +type GltfVertexBufferKey = (Option, Option, Option, Option); + +pub fn new_texture_from_gltf( + device: &Device, + queue: &Queue, + info: &gltf::texture::Texture, + images: &Vec, +) -> Option { + if let Some(image) = images.get(info.source().index()) { + let mut new_pixels = Vec::new(); + let pixels: &Vec; + match image.format { + gltf::image::Format::R8G8B8 => { + for pixel in image.pixels.chunks(3) { + new_pixels.push(pixel[0]); + new_pixels.push(pixel[0]); + new_pixels.push(pixel[0]); + new_pixels.push(255); + } + pixels = &new_pixels; + } + gltf::image::Format::R8G8B8A8 => pixels = &image.pixels, + _ => return None, + } + Some(Texture::load( + device, + queue, + pixels.as_slice(), + TextureProperties { + width: image.width, + height: image.height, + }, + )) + } else { + None + } +} +pub fn new_mesh_from_gltf( + device: &Device, + primitive: gltf::Primitive, + meshes: &mut HashMap, + buffers: &[gltf::buffer::Data], +) -> Mesh { + let position_index = primitive + .get(&Semantic::Positions) + .and_then(|it| it.view()).map(|it| it.buffer().index()); + let normals_index = primitive + .get(&Semantic::Normals) + .and_then(|it| it.view()).map(|it| it.buffer().index()); + let tex_coords_index = primitive + .get(&Semantic::TexCoords(0)) + .and_then(|it| it.view()).map(|it| it.buffer().index()); + let indices_index = primitive + .indices() + .and_then(|it| it.view()).map(|it| it.buffer().index()); + let tangent_index = primitive + .get(&Semantic::Tangents) + .and_then(|it| it.view()).map(|it| it.buffer().index()); + let key = ( + position_index, + normals_index, + tex_coords_index, + indices_index, + ); + let insert = || { + let mut tangents = false; + let reader = primitive.reader(|buffer| Some(&buffers[buffer.index()])); + let mut vertex_data: Vec; + let mut aabb = AABB(Vec3::ZERO,Vec3::ZERO); + if let Some(positions) = reader.read_positions() { + vertex_data = Vec::with_capacity(positions.len()); + let mut normal = reader.read_normals().map(|it| it.into_iter()); + let mut tex_coord = reader + .read_tex_coords(0) + .map(|it| it.into_f32().into_iter()); + let mut tangent = reader.read_tangents().map(|it| it.into_iter()); + tangents = tangent.is_some(); + for position in positions { + aabb = aabb.extend_to(Vec3::from(position)); + vertex_data.push(TangentVertex { + position, + normal: if let Some(ref mut normals) = normal { + if let Some(normal) = normals.next() { + normal + } else { + [0.0; 3] + } + } else { + [0.0; 3] + }, + tex_coord: if let Some(ref mut tex_coords) = tex_coord { + tex_coords.next() + } else { + None + } + .unwrap_or([0.0; 2]), + tangent: [0.0; 3], // todo: tangent from model + bitangent: [0.0; 3], + }) + } + } else { + vertex_data = Vec::new(); + } + let vertex_buffer = + device + .create_buffer_init(&wgpu::util::BufferInitDescriptor { + label: Some("Vertex Buffer"), + contents: bytemuck::cast_slice(vertex_data.as_slice()), + usage: wgpu::BufferUsages::VERTEX, + }); + let vertices_result = (vertex_buffer, vertex_data.len() as u32); + let indices_result = if let Some(indices) = reader.read_indices() { + let index_data: Vec = indices.into_u32().collect(); + Some(( + device + .create_buffer_init(&wgpu::util::BufferInitDescriptor { + label: Some("Index Buffer"), + contents: bytemuck::cast_slice(index_data.as_slice()), + usage: wgpu::BufferUsages::INDEX, + }), + index_data.len() as u32, + )) + } else { + None + }; + Mesh { + indices: indices_result, + vertices: vertices_result, + aabb, + } + }; + meshes.entry(key).or_insert_with(insert).clone() +} + +pub fn load_node_from_gltf( + node: gltf::Node, + device: &Device, + queue: &Queue, + mesh_map: &mut HashMap, + texture_map: &mut HashMap, + materials: &mut Materials, + textures: &Textures, + meshes: &mut FreeList, + images: &Vec, + buffers: &Vec, +) -> TreeNode { + let mut tree_node = TreeNode { + object: None, + children: Vec::new(), + name: node.name().unwrap_or("Node").to_string(), + }; + if let Some(mesh) = node.mesh() { + let len = mesh.primitives().len(); + for primitive in mesh.primitives() { + let pbr = primitive.material().pbr_metallic_roughness(); + let material = primitive.material(); + let color = pbr.base_color_factor(); + let metal = pbr.metallic_factor(); + let rough = pbr.roughness_factor(); + let light = primitive.material().emissive_factor(); + let base = match pbr.base_color_texture() { + Some(info) => texture_map + .entry(info.texture().source().index()) + .or_insert_with(|| new_texture_from_gltf(device,queue,&info.texture(), &images).unwrap_or_else(|| textures.default.clone())) + .clone(), + None => textures.default.clone(), + }; + let reflect = match pbr.metallic_roughness_texture() { + Some(info) => texture_map + .entry(info.texture().source().index()) + .or_insert_with(|| new_texture_from_gltf(device,queue,&info.texture(), &images).unwrap_or_else(|| textures.default.clone())) + .clone(), + None => textures.default.clone(), + }; + let normal = match material.normal_texture() { + Some(info) => texture_map + .entry(info.texture().source().index()) + .or_insert_with(|| new_texture_from_gltf(device,queue,&info.texture(), &images).unwrap_or_else(|| textures.default.clone())) + .clone(), + None => textures.default.clone(), + }; + let material = materials.list.make(Material::_new( + &device, + &materials.layout, + &base, + &normal, + &reflect, + MaterialProperties { + edge: wgpu::AddressMode::Repeat, + filter: wgpu::FilterMode::Linear, + }, + )).into();; + let mesh = new_mesh_from_gltf(device, primitive, mesh_map, buffers); + let aabb = mesh.aabb; + let object = ObjectData { + model: Some(ModelData { + instance: ModelInstance { + transform: Mat4::default(), + color: Vec4::from_array(color), + lights: [0; 16], + point_lights: 0, + spot_lights: 0, + metal, + rough, + }, + material, + mesh: meshes.make(mesh).id, + }), + collider: ColliderData { shape: Shape::Sphere(aabb.1.distance(aabb.0)) }, + affine: Default::default(), + asleep: false, + }; + if len == 1 { + tree_node.object = Some(object); + } else { + tree_node.children.push(TreeNode { + object: Some(object), + children: Vec::new(), + name: "Primitive".to_string(), + }) + } + } + } + for node in node.children() { + tree_node + .children + .push(load_node_from_gltf(node, device, queue, mesh_map, texture_map, materials, textures, meshes, images, buffers)); + } + tree_node +} +pub fn _load_from_gltf(device: &Device, queue: &Queue, meshes: &mut FreeList, materials: &mut Materials, textures: &mut Textures, slice: impl AsRef<[u8]>) -> TreeNode { + let mut root = TreeNode { + object: None, + children: Vec::new(), + name: "Root".to_string(), + }; + if let Ok((document, buffers, images)) = gltf::import_slice(slice) { + let mut mesh_map: HashMap = HashMap::new(); + let mut texture_map: HashMap = HashMap::new(); + for scene in document.scenes() { + let mut scene_node = TreeNode { + object: None, + children: Vec::new(), + name: scene.name().unwrap_or("Scene").to_string(), + }; + for node in scene.nodes() { + scene_node.children.push(load_node_from_gltf( + node, + device, + queue, + &mut mesh_map, + &mut texture_map, + materials, + textures, + meshes, + &images, + &buffers, + )); + } + root.children.push(scene_node) + } + } + root +} + +pub fn load_from_gltf(renderer: &mut Renderer, slice: impl AsRef<[u8]>) -> TreeNode { + _load_from_gltf(&renderer.device, &renderer.queue, &mut renderer.meshes, &mut renderer.instances.materials, &mut renderer.textures, slice) +} \ No newline at end of file diff --git a/src/render/mesh.rs b/src/render/mesh.rs new file mode 100644 index 0000000..0d392b8 --- /dev/null +++ b/src/render/mesh.rs @@ -0,0 +1,51 @@ +use crate::world::AABB; + +#[repr(C)] +#[derive(Copy, Clone, Debug, bytemuck::Pod, bytemuck::Zeroable)] +pub struct TangentVertex { + pub(crate) position: [f32; 3], + pub(crate) normal: [f32; 3], + pub(crate) tex_coord: [f32; 2], + pub(crate) tangent: [f32; 3], + pub(crate) bitangent: [f32; 3], +} + +#[repr(C)] +#[derive(Copy, Clone, Debug, bytemuck::Pod, bytemuck::Zeroable)] +pub struct Vertex { + position: [f32; 3], + normal: [f32; 3], + tex_coord: [f32; 3], +} + +impl TangentVertex { + pub(crate) fn desc() -> wgpu::VertexBufferLayout<'static> { + wgpu::VertexBufferLayout { + array_stride: size_of::() as wgpu::BufferAddress, + step_mode: wgpu::VertexStepMode::Vertex, + attributes: &[ + wgpu::VertexAttribute { + offset: 0, + shader_location: 0, + format: wgpu::VertexFormat::Float32x3, + }, + wgpu::VertexAttribute { + offset: size_of::<[f32; 3]>() as wgpu::BufferAddress, + shader_location: 1, + format: wgpu::VertexFormat::Float32x3, + }, + wgpu::VertexAttribute { + offset: size_of::<[f32; 6]>() as wgpu::BufferAddress, + shader_location: 2, + format: wgpu::VertexFormat::Float32x2, + }, + ], + } + } +} +#[derive(Debug, Clone, PartialEq)] +pub struct Mesh { + pub(crate) indices: Option<(wgpu::Buffer, u32)>, + pub(crate) vertices: (wgpu::Buffer, u32), + pub(crate) aabb: AABB, +} \ No newline at end of file diff --git a/src/render/mod.rs b/src/render/mod.rs index 68977e7..b15cbfa 100644 --- a/src/render/mod.rs +++ b/src/render/mod.rs @@ -1,10 +1,14 @@ pub mod eye; +pub mod texture; +pub mod mesh; +pub mod instance; +pub mod loader; use crate::render::eye::Eye; -use crate::world::{Shape, SimpleColliderData, SimpleLight, SimpleObject, SimpleObjectData}; +use crate::world::{Shape, ColliderData, ObjectData, World, AABB}; use bytemuck::{Pod, Zeroable}; use glam::prelude::*; -use gltf::Semantic; +use gltf::{Semantic}; use image::EncodableLayout; use std::cell::RefCell; use std::collections::HashMap; @@ -15,874 +19,71 @@ use std::ops::Range; use std::rc::Rc; use std::sync::Arc; use wgpu::naga::{FastHashMap, FastHashSet}; -use wgpu::util::DeviceExt; use wgpu::{Device, Queue}; use winit::window::Window; +use crate::list::{FreeList, SingleId, Id, RefId}; +use crate::render::instance::{Instances, Program}; +use crate::render::mesh::{Mesh, TangentVertex}; +use crate::render::texture::{Texture, TextureProperties}; +use crate::world; -const DEFAULT_VERTICES: [SimpleVertex; 0] = []; +const DEFAULT_VERTICES: [TangentVertex; 0] = []; + +pub struct Screen { -#[repr(C)] -#[derive(Pod, Zeroable, Copy, Clone)] -pub struct SimpleModelInstance { - pub transform: Mat4, - pub color: Vec4, - pub lights: [u16; 16], - pub point_lights: u32, - pub spot_lights: u32, - pub metal: f32, - pub rough: f32, } -#[repr(C)] -#[derive(Pod, Copy, Clone, Zeroable)] -pub struct SimpleLightInstance { - pub location: Vec4, - pub rotation: Vec4, - pub color: Vec4, +pub struct Textures { + list: FreeList, + default: Texture, } -#[derive(Clone)] -pub struct SimpleLightData { - pub index: usize, - pub instance: SimpleLightInstance, - pub transform: Affine3, -} - -#[derive(Clone)] -pub struct SimpleModelData { - pub instance: SimpleModelInstance, - pub material: Id, - pub mesh: Id, -} - -pub struct SimpleInstances { - light_count: usize, - light_buffer: wgpu::Buffer, - instance_count: usize, - instance_buffer: wgpu::Buffer, - //light_ref_last: usize, - //light_ref_buffer: wgpu::Buffer, - objects: - FastHashMap, FastHashMap, FastHashSet>>, - lights: FastHashMap, -} - -enum SimpleRenderCode { - Material(wgpu::BindGroup), - Mesh((wgpu::Buffer, u32), Option<(wgpu::Buffer, u32)>), - Draw(Range), -} - -struct SimpleRenderProgram(Vec); - -impl SimpleRenderProgram { - fn push(&mut self, item: SimpleRenderCode) { - self.0.push(item) - } - fn new() -> SimpleRenderProgram { - SimpleRenderProgram(Vec::new()) - } - fn render(self, pass: &mut wgpu::RenderPass) { - let mut count = 0; - let mut indexed = false; - for code in self.0 { - match code { - SimpleRenderCode::Material(material) => pass.set_bind_group( - Renderer::SIMPLE_RENDER_TEXTURE_GROUP_POSITION, - &material, - &[], - ), - SimpleRenderCode::Mesh(vertices, indices) => { - pass.set_vertex_buffer(0, vertices.0.slice(..)); - if let Some(indices) = indices { - pass.set_index_buffer(indices.0.slice(..), wgpu::IndexFormat::Uint32); - count = indices.1; - indexed = true; - } else { - count = vertices.1; - indexed = false; - } - } - SimpleRenderCode::Draw(instances) => { - if indexed { - pass.draw_indexed(0..count, 0, instances) - } else { - pass.draw(0..count, instances); - } - } - } - } - } -} - -impl SimpleInstances { - const MIN_SIZE: u64 = 64; - pub fn add_object(&mut self, object: SimpleObject) { - if let Some(ref model) = object.0.borrow().model { - self.instance_count += 1; - self.objects - .entry(model.mesh.clone()) - .or_insert(FastHashMap::with_hasher(BuildHasherDefault::new())) - .entry(model.material.clone()) - .or_insert(FastHashSet::with_hasher(BuildHasherDefault::new())) - .insert(object.clone()); - } - } - - pub fn remove_object(&mut self, object: SimpleObject) { - if let Some(ref model) = object.0.borrow().model { - self.instance_count -= 1; - self.objects - .entry(model.mesh.clone()) - .or_insert(FastHashMap::with_hasher(BuildHasherDefault::new())) - .entry(model.material.clone()) - .or_insert(FastHashSet::with_hasher(BuildHasherDefault::new())) - .remove(&object); - } - } - - pub fn add_light(&mut self, light: SimpleLight) { - self.light_count += 1; - self.lights.insert(light, 0); - } - - pub fn remove_light(&mut self, light: &SimpleLight) { - self.light_count -= 1; - self.lights.remove(light); - } - - pub fn reallocate_buffer( - device: &wgpu::Device, - buffer: &mut wgpu::Buffer, - count: usize, - item_size: usize, - ) { - let size = buffer.size() / item_size as wgpu::BufferAddress; - if count > SimpleInstances::MIN_SIZE as usize { - let mut reallocate: Option = None; - if count < (size / 2) as usize { - reallocate = Some(count / 2); - } else if count > size as usize { - reallocate = Some(count * 2); - } - if let Some(new_size) = reallocate { - *buffer = device.create_buffer(&wgpu::BufferDescriptor { - label: Some("Instance Buffer"), - size: (item_size * new_size) as wgpu::BufferAddress, - usage: wgpu::BufferUsages::COPY_DST | wgpu::BufferUsages::VERTEX, - mapped_at_creation: false, - }); - } - } - } - pub fn write_lights(&mut self, device: &wgpu::Device, queue: &wgpu::Queue) { - //SimpleInstances::reallocate_buffer(device, queue, &mut self.light_ref_buffer, self.light_ref_last, size_of::()); - /* - let mut light_ref_buffer = queue.write_buffer_with( - &self.light_ref_buffer, - 0 as wgpu::BufferAddress, - wgpu::BufferSize::new(self.instance_buffer.size()).unwrap() - ).unwrap(); - */ - SimpleInstances::reallocate_buffer( - device, - &mut self.light_buffer, - self.light_count, - size_of::(), +impl Textures { + fn new(device: &Device, queue: &Queue) -> Textures { + let default = Texture::load( + &device, + &queue, + [0, 0, 255, 255], + TextureProperties { + width: 1, + height: 1, + }, ); - let mut buffer = queue - .write_buffer_with( - &self.light_buffer, - 0 as wgpu::BufferAddress, - wgpu::BufferSize::new(self.light_buffer.size()).unwrap(), - ) - .unwrap(); - let stride = size_of::(); - for (new_index, (light, index)) in self.lights.iter_mut().enumerate() { - *index = new_index + 1; - let begin = *index * stride; - buffer - .slice(begin..begin + stride) - .copy_from_slice(bytemuck::cast_slice(&[light.0.borrow().instance])); - } - } - fn write_instances( - &mut self, - device: &wgpu::Device, - queue: &wgpu::Queue, - ) -> SimpleRenderProgram { - let mut program = SimpleRenderProgram::new(); - SimpleInstances::reallocate_buffer( - device, - &mut self.instance_buffer, - self.instance_count, - size_of::(), - ); - let mut buffer = queue - .write_buffer_with( - &self.instance_buffer, - 0 as wgpu::BufferAddress, - wgpu::BufferSize::new(self.instance_buffer.size()).unwrap(), - ) - .unwrap(); - let mut index: u32 = 0; - let stride = size_of::(); - for (mesh, materials) in self.objects.iter() { - program.push(SimpleRenderCode::Mesh( - mesh.it.vertices.clone(), - mesh.it.indices.clone(), - )); - for (material, objects) in materials.iter() { - program.push(SimpleRenderCode::Material(material.it.group.clone())); - let before = index; - for object in objects.iter() { - let begin = index as usize * stride; - buffer - .slice(begin..begin + stride) - .copy_from_slice(bytemuck::cast_slice(&[object - .0 - .borrow() - .model - .as_ref() - .unwrap() - .instance])); - index += 1; - } - program.push(SimpleRenderCode::Draw(Range::from(before..index))); - } - } - program - } - - fn desc() -> wgpu::VertexBufferLayout<'static> { - wgpu::VertexBufferLayout { - array_stride: size_of::() as wgpu::BufferAddress, - step_mode: wgpu::VertexStepMode::Instance, - attributes: &[ - // todo: is this too big? - wgpu::VertexAttribute { - offset: 0, - shader_location: 4, - format: wgpu::VertexFormat::Float32x4, - }, - wgpu::VertexAttribute { - offset: size_of::<[f32; 4]>() as wgpu::BufferAddress, - shader_location: 5, - format: wgpu::VertexFormat::Float32x4, - }, - wgpu::VertexAttribute { - offset: size_of::<[f32; 8]>() as wgpu::BufferAddress, - shader_location: 6, - format: wgpu::VertexFormat::Float32x4, - }, - wgpu::VertexAttribute { - offset: size_of::<[f32; 12]>() as wgpu::BufferAddress, - shader_location: 7, - format: wgpu::VertexFormat::Float32x4, - }, - wgpu::VertexAttribute { - offset: size_of::<[f32; 16]>() as wgpu::BufferAddress, - shader_location: 8, - format: wgpu::VertexFormat::Float32x4, - }, - wgpu::VertexAttribute { - offset: size_of::<[f32; 16]>() as wgpu::BufferAddress, - shader_location: 9, - format: wgpu::VertexFormat::Float32x4, - }, - wgpu::VertexAttribute { - offset: size_of::<[f32; 16]>() as wgpu::BufferAddress, - shader_location: 10, - format: wgpu::VertexFormat::Float32x4, - }, - wgpu::VertexAttribute { - offset: size_of::<[f32; 16]>() as wgpu::BufferAddress, - shader_location: 11, - format: wgpu::VertexFormat::Float32x4, - }, - ], - } - } - - pub fn new(device: &wgpu::Device) -> SimpleInstances { - let instance_buffer = device.create_buffer(&wgpu::BufferDescriptor { - label: Some("Instance Buffer"), - size: (size_of::() * SimpleInstances::MIN_SIZE as usize) - as wgpu::BufferAddress, - usage: wgpu::BufferUsages::VERTEX | wgpu::BufferUsages::COPY_DST, - mapped_at_creation: false, - }); - let light_buffer = device.create_buffer(&wgpu::BufferDescriptor { - label: Some("Light Buffer"), - size: (size_of::() * SimpleInstances::MIN_SIZE as usize) - as wgpu::BufferAddress, - usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST, - mapped_at_creation: false, - }); - /*let light_ref_buffer = device.create_buffer(&wgpu::BufferDescriptor { - label: Some("Light Ref Buffer"), - size: (size_of::() * SimpleInstances::MIN_SIZE as usize) as wgpu::BufferAddress, - usage: wgpu::BufferUsages::STORAGE | wgpu::BufferUsages::COPY_DST, - mapped_at_creation: false, - });*/ - SimpleInstances { - light_count: 0, - //light_ref_last: 0, - instance_count: 0, - light_buffer, - instance_buffer, - //light_ref_buffer, - objects: FastHashMap::with_hasher(BuildHasherDefault::new()), - lights: Default::default(), + Textures { + list: Default::default(), + default, } } } pub struct Renderer { - id_count: u64, surface: wgpu::Surface<'static>, config: wgpu::SurfaceConfiguration, device: wgpu::Device, queue: wgpu::Queue, + textures: Textures, + meshes: FreeList, + depth: Texture, pub(crate) eye: eye::Eye, - material_layout: wgpu::BindGroupLayout, - default_texture: SimpleTexture, - default_material: SimpleMaterial, - sky_pipeline: wgpu::RenderPipeline, - instance_pipeline: wgpu::RenderPipeline, - depth_texture: SimpleTexture, - pub(crate) instances: SimpleInstances, + pub(crate) instances: instance::Instances, } -#[repr(C)] -#[derive(Copy, Clone, Debug, bytemuck::Pod, bytemuck::Zeroable)] -struct SimpleVertex { - position: [f32; 3], - normal: [f32; 3], - tex_coord: [f32; 2], - tangent: [f32; 3], - bitangent: [f32; 3], -} - -impl SimpleVertex { - fn desc() -> wgpu::VertexBufferLayout<'static> { - wgpu::VertexBufferLayout { - array_stride: size_of::() as wgpu::BufferAddress, - step_mode: wgpu::VertexStepMode::Vertex, - attributes: &[ - wgpu::VertexAttribute { - offset: 0, - shader_location: 0, - format: wgpu::VertexFormat::Float32x3, - }, - wgpu::VertexAttribute { - offset: size_of::<[f32; 3]>() as wgpu::BufferAddress, - shader_location: 1, - format: wgpu::VertexFormat::Float32x3, - }, - wgpu::VertexAttribute { - offset: size_of::<[f32; 6]>() as wgpu::BufferAddress, - shader_location: 2, - format: wgpu::VertexFormat::Float32x2, - }, - ], - } - } -} -#[derive(Debug, Clone, PartialEq)] -pub struct SimpleMesh { - indices: Option<(wgpu::Buffer, u32)>, - vertices: (wgpu::Buffer, u32), -} -#[derive(Debug, Clone, Hash, Eq, PartialEq)] -pub struct SimpleTexture { - texture: wgpu::Texture, - view: wgpu::TextureView, -} -pub struct TextureProperties { - width: u32, - height: u32, -} -// todo: use texture compression! -impl SimpleTexture { - pub fn load( - device: &Device, - queue: &Queue, - slice: impl AsRef<[u8]>, - properties: TextureProperties, - ) -> SimpleTexture { - let size = wgpu::Extent3d { - width: properties.width, - height: properties.height, - depth_or_array_layers: 1, - }; - let diffuse_texture = device.create_texture(&wgpu::TextureDescriptor { - size, - mip_level_count: 1, - sample_count: 1, - dimension: wgpu::TextureDimension::D2, - format: wgpu::TextureFormat::Rgba8UnormSrgb, - usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST, - label: Some("texture"), - view_formats: &[], - }); - let diffuse_texture_view = - diffuse_texture.create_view(&wgpu::TextureViewDescriptor::default()); - queue.write_texture( - wgpu::TexelCopyTextureInfo { - texture: &diffuse_texture, - mip_level: 0, - origin: wgpu::Origin3d::ZERO, - aspect: wgpu::TextureAspect::All, - }, - slice.as_ref(), - wgpu::TexelCopyBufferLayout { - offset: 0, - bytes_per_row: Some(4 * size.width), - rows_per_image: Some(size.height), - }, - size, - ); - SimpleTexture { - texture: diffuse_texture, - view: diffuse_texture_view, - } - } -} - -#[derive(Clone)] -pub struct SimpleMaterial { - group: wgpu::BindGroup, -} - -#[derive(Clone)] -pub struct Id { - id: u64, - it: T, -} - -impl Hash for Id { - fn hash(&self, state: &mut H) { - self.id.hash(state) - } -} - -impl PartialEq for Id { - fn eq(&self, other: &Self) -> bool { - other.id == self.id - } -} - -impl Eq for Id {} - -struct MaterialProperties { - edge: wgpu::AddressMode, - filter: wgpu::FilterMode, -} - -impl Default for MaterialProperties { - fn default() -> MaterialProperties { - MaterialProperties { - edge: wgpu::AddressMode::Repeat, - filter: wgpu::FilterMode::Linear, - } - } -} - -impl MaterialProperties { - fn sampler(&self, device: &wgpu::Device) -> wgpu::Sampler { - device.create_sampler(&wgpu::SamplerDescriptor { - address_mode_u: self.edge, - address_mode_v: self.edge, - address_mode_w: self.edge, - mag_filter: self.filter, - min_filter: self.filter, - mipmap_filter: wgpu::MipmapFilterMode::Nearest, - ..Default::default() - }) - } -} - -impl SimpleMaterial { - fn new( - device: &wgpu::Device, - layout: &wgpu::BindGroupLayout, - base: &SimpleTexture, - normal: &SimpleTexture, - reflect: &SimpleTexture, - config: MaterialProperties, - ) -> SimpleMaterial { - let sampler = config.sampler(&device); - let group = device.create_bind_group(&wgpu::BindGroupDescriptor { - layout: layout, - entries: &[ - wgpu::BindGroupEntry { - binding: 0, - resource: wgpu::BindingResource::Sampler(&sampler), - }, - wgpu::BindGroupEntry { - binding: 1, - resource: wgpu::BindingResource::TextureView(&base.view), - }, - wgpu::BindGroupEntry { - binding: 2, - resource: wgpu::BindingResource::TextureView(&normal.view), - }, - wgpu::BindGroupEntry { - binding: 3, - resource: wgpu::BindingResource::TextureView(&reflect.view), - }, - ], - label: Some("diffuse_bind_group"), - }); - SimpleMaterial { group } - } -} - -#[derive(Debug)] -struct PoolError(String); - -impl Display for PoolError { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", self.0) - } -} - -impl Error for PoolError {} - -pub struct SimpleTreeNode { - object: Option, - children: Vec, - name: String, -} - -impl SimpleTreeNode { - pub fn first_object(&self) -> Option { - if let Some(object) = self.object.clone() { - Some(object) - } else { - for child in self.children.iter() { - if let Some(object) = child.first_object() { - return Some(object); - } - } - None - } - } -} - -type GltfVertexBufferKey = (Option, Option, Option, Option); - impl Renderer { const SIMPLE_RENDER_EYE_GROUP_POSITION: u32 = 0; const SIMPLE_RENDER_TEXTURE_GROUP_POSITION: u32 = 1; const SIMPLE_RENDER_MODEL_GROUP_POSITION: u32 = 2; - pub fn new_id(&mut self, value: T) -> Id { - self.id_count += 1; - Id { - it: value, - id: self.id_count, - } - } - pub fn load_texture_from_bytes( - &mut self, - slice: impl AsRef<[u8]>, - format: Option, - ) -> SimpleTexture { - let image = if let Some(format) = format { - image::load_from_memory_with_format(slice.as_ref(), format) - } else { - image::load_from_memory(slice.as_ref()) - }; - if let Ok(data) = image { - let data = data.into_rgba8(); - SimpleTexture::load( - &self.device, - &self.queue, - data.as_bytes(), - TextureProperties { - width: data.width(), - height: data.height(), - }, - ) - } else { - println!("failed to load texture! error: {:?}", image.unwrap_err()); - self.default_texture.clone() - } - } - pub fn new_material( - &mut self, - base: &SimpleTexture, - normal: &SimpleTexture, - reflect: &SimpleTexture, - ) -> Id { - self.new_id(SimpleMaterial::new( - &self.device, - &self.material_layout, - base, - normal, - reflect, - MaterialProperties { - edge: wgpu::AddressMode::Repeat, - filter: wgpu::FilterMode::Linear, - }, - )) - } - pub fn new_texture_from_gltf( - &mut self, - info: &gltf::texture::Texture, - images: &Vec, - ) -> SimpleTexture { - if let Some(image) = images.get(info.source().index()) { - let mut new_pixels = Vec::new(); - let pixels: &Vec; - match image.format { - gltf::image::Format::R8G8B8 => { - for pixel in image.pixels.chunks(3) { - new_pixels.push(pixel[0]); - new_pixels.push(pixel[0]); - new_pixels.push(pixel[0]); - new_pixels.push(255); - } - pixels = &new_pixels; - } - gltf::image::Format::R8G8B8A8 => pixels = &image.pixels, - _ => return self.default_texture.clone(), - } - SimpleTexture::load( - &self.device, - &self.queue, - pixels.as_slice(), - TextureProperties { - width: image.width, - height: image.height, - }, - ) - } else { - self.default_texture.clone() - } - } - pub fn new_mesh_from_gltf( - &mut self, - primitive: gltf::Primitive, - meshes: &mut HashMap, - buffers: &[gltf::buffer::Data], - ) -> Id { - let position_index = primitive - .get(&Semantic::Positions) - .and_then(|it| it.view()) - .and_then(|it| Some(it.buffer().index())); - let normals_index = primitive - .get(&Semantic::Normals) - .and_then(|it| it.view()) - .and_then(|it| Some(it.buffer().index())); - let tex_coords_index = primitive - .get(&Semantic::TexCoords(0)) - .and_then(|it| it.view()) - .and_then(|it| Some(it.buffer().index())); - let indices_index = primitive - .indices() - .and_then(|it| it.view()) - .and_then(|it| Some(it.buffer().index())); - let tangent_index = primitive - .get(&Semantic::Tangents) - .and_then(|it| it.view()) - .and_then(|it| Some(it.buffer().index())); - let key = ( - position_index, - normals_index, - tex_coords_index, - indices_index, - ); - self.new_id( - meshes - .entry(key) - .or_insert_with(|| { - let mut tangents = false; - let reader = primitive.reader(|buffer| Some(&buffers[buffer.index()])); - let mut vertex_data: Vec; - if let Some(positions) = reader.read_positions() { - vertex_data = Vec::with_capacity(positions.len()); - let mut normal = reader.read_normals().map(|it| it.into_iter()); - let mut tex_coord = reader - .read_tex_coords(0) - .map(|it| it.into_f32().into_iter()); - let mut tangent = reader.read_tangents().map(|it| it.into_iter()); - tangents = tangent.is_some(); - for position in positions { - vertex_data.push(SimpleVertex { - position, - normal: if let Some(ref mut normals) = normal { - if let Some(normal) = normals.next() { - normal - } else { - [0.0; 3] - } - } else { - [0.0; 3] - }, - tex_coord: if let Some(ref mut tex_coords) = tex_coord { - tex_coords.next() - } else { - None - } - .unwrap_or([0.0; 2]), - tangent: [0.0; 3], // todo: tangent from model - bitangent: [0.0; 3], - }) - } - } else { - vertex_data = Vec::new(); - } - let vertex_buffer = - self.device - .create_buffer_init(&wgpu::util::BufferInitDescriptor { - label: Some("Vertex Buffer"), - contents: bytemuck::cast_slice(vertex_data.as_slice()), - usage: wgpu::BufferUsages::VERTEX, - }); - let vertices_result = (vertex_buffer, vertex_data.len() as u32); - let indices_result = if let Some(indices) = reader.read_indices() { - let index_data: Vec = indices.into_u32().collect(); - Some(( - self.device - .create_buffer_init(&wgpu::util::BufferInitDescriptor { - label: Some("Index Buffer"), - contents: bytemuck::cast_slice(index_data.as_slice()), - usage: wgpu::BufferUsages::INDEX, - }), - index_data.len() as u32, - )) - } else { - None - }; - SimpleMesh { - indices: indices_result, - vertices: vertices_result, - } - }) - .clone(), - ) - } - pub fn load_node_from_gltf( - &mut self, - node: gltf::Node, - meshes: &mut HashMap, - textures: &mut HashMap, - images: &Vec, - buffers: &Vec, - ) -> SimpleTreeNode { - let mut tree_node = SimpleTreeNode { - object: None, - children: Vec::new(), - name: node.name().unwrap_or("Node").to_string(), - }; - if let Some(mesh) = node.mesh() { - let len = mesh.primitives().len(); - for primitive in mesh.primitives() { - let pbr = primitive.material().pbr_metallic_roughness(); - let material = primitive.material(); - let color = pbr.base_color_factor(); - let metal = pbr.metallic_factor(); - let rough = pbr.roughness_factor(); - let light = primitive.material().emissive_factor(); - let base = match pbr.base_color_texture() { - Some(info) => textures - .entry(info.texture().source().index()) - .or_insert_with(|| self.new_texture_from_gltf(&info.texture(), &images)) - .clone(), - None => self.default_texture.clone(), - }; - let reflect = match pbr.metallic_roughness_texture() { - Some(info) => textures - .entry(info.texture().source().index()) - .or_insert_with(|| self.new_texture_from_gltf(&info.texture(), &images)) - .clone(), - None => self.default_texture.clone(), - }; - let normal = match material.normal_texture() { - Some(info) => textures - .entry(info.texture().source().index()) - .or_insert_with(|| self.new_texture_from_gltf(&info.texture(), &images)) - .clone(), - None => self.default_texture.clone(), - }; - let material = self.new_material(&base, &normal, &reflect); - let mesh = self.new_mesh_from_gltf(primitive, meshes, buffers); - let object = SimpleObject(Rc::new(RefCell::new(SimpleObjectData { - model: Some(SimpleModelData { - instance: SimpleModelInstance { - transform: Mat4::default(), - color: Vec4::from_array(color), - lights: [0; 16], - point_lights: 0, - spot_lights: 0, - metal, - rough, - }, - material, - mesh, - }), - collider: SimpleColliderData { - transform: Mat4::default(), - shape: Shape::None, - radius: 0.0, - }, - }))); - if len == 1 { - tree_node.object = Some(object); - } else { - tree_node.children.push(SimpleTreeNode { - object: Some(object), - children: Vec::new(), - name: "Primitive".to_string(), - }) - } - } - } - for node in node.children() { - tree_node - .children - .push(self.load_node_from_gltf(node, meshes, textures, images, buffers)); - } - tree_node - } - pub fn load_from_gltf(&mut self, slice: impl AsRef<[u8]>) -> SimpleTreeNode { - let mut root = SimpleTreeNode { - object: None, - children: Vec::new(), - name: "Root".to_string(), - }; - if let Ok((document, buffers, images)) = gltf::import_slice(slice) { - let mut meshes: HashMap = HashMap::new(); - let mut textures: HashMap = HashMap::new(); - for scene in document.scenes() { - let mut scene_node = SimpleTreeNode { - object: None, - children: Vec::new(), - name: scene.name().unwrap_or("Scene").to_string(), - }; - for node in scene.nodes() { - scene_node.children.push(self.load_node_from_gltf( - node, - &mut meshes, - &mut textures, - &images, - &buffers, - )); - } - root.children.push(scene_node) - } - } - root + pub fn write_instances(&mut self, objects: &mut FreeList) { + self.instances.write_instances(&self.device, &self.queue, &mut self.meshes, objects); } pub fn resize(&mut self, width: u32, height: u32) { + println!("resize"); + self.config.width = width; + self.config.height = height; + self.depth = Texture::depth(&self.config, &self.device); self.surface.configure(&self.device, &self.config); - self.eye.resize(width, height); + self.eye.resize(&self.queue, width, height); } - - - pub fn set_skybox(&mut self, skybox: SimpleTexture) { + pub fn set_skybox(&mut self, skybox: Texture) { self.eye.skybox(&self.device, skybox); } pub async fn new(window: &Arc) -> anyhow::Result { @@ -918,6 +119,7 @@ impl Renderer { power_preference: wgpu::PowerPreference::default(), compatible_surface: Some(&surface), force_fallback_adapter: false, + //apply_limit_buckets: false, }) .await?; @@ -951,248 +153,52 @@ impl Renderer { let config = wgpu::SurfaceConfiguration { usage: wgpu::TextureUsages::RENDER_ATTACHMENT, format: surface_format, + //color_space: Default::default(), width, height, - present_mode: surface_caps.present_modes[0], + present_mode: wgpu::PresentMode::Fifo, alpha_mode: surface_caps.alpha_modes[0], view_formats: vec![], desired_maximum_frame_latency: 2, }; + + let textures = Textures::new(&device, &queue); + + let eye = Eye::new(&device, &config, width, height, textures.default.clone()); + + let instances = Instances::new(&device, &eye, &config, textures.default.clone()); - let shader = - device.create_shader_module(wgpu::include_wgsl!("../assets/SimpleShader.wgsl")); - - let default_texture = SimpleTexture::load( - &device, - &queue, - [0, 0, 255, 255], - TextureProperties { - width: 1, - height: 1, - }, - ); - - let eye = Eye::new(&device, width, height, default_texture.clone()); - let texture_bind_group_layout = - device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { - entries: &[ - wgpu::BindGroupLayoutEntry { - binding: 0, - visibility: wgpu::ShaderStages::FRAGMENT, - ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering), - count: None, - }, - wgpu::BindGroupLayoutEntry { - binding: 1, - visibility: wgpu::ShaderStages::FRAGMENT, - ty: wgpu::BindingType::Texture { - multisampled: false, - view_dimension: wgpu::TextureViewDimension::D2, - sample_type: wgpu::TextureSampleType::Float { filterable: true }, - }, - count: None, - }, - wgpu::BindGroupLayoutEntry { - binding: 2, - visibility: wgpu::ShaderStages::FRAGMENT, - ty: wgpu::BindingType::Texture { - multisampled: false, - view_dimension: wgpu::TextureViewDimension::D2, - sample_type: wgpu::TextureSampleType::Float { filterable: true }, - }, - count: None, - }, - wgpu::BindGroupLayoutEntry { - binding: 3, - visibility: wgpu::ShaderStages::FRAGMENT, - ty: wgpu::BindingType::Texture { - multisampled: false, - view_dimension: wgpu::TextureViewDimension::D2, - sample_type: wgpu::TextureSampleType::Float { filterable: true }, - }, - count: None, - }, - ], - label: Some("texture_bind_group_layout"), - }); - - let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { - label: Some("Render Pipeline Layout"), - bind_group_layouts: &[Some(&eye.layout), Some(&texture_bind_group_layout)], - immediate_size: 0, - }); - - let instance_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { - label: Some("Render Pipeline"), - layout: Some(&pipeline_layout), - vertex: wgpu::VertexState { - module: &shader, - entry_point: Some("vs_main"), - buffers: &[SimpleVertex::desc(), SimpleInstances::desc()], - compilation_options: wgpu::PipelineCompilationOptions::default(), - }, - fragment: Some(wgpu::FragmentState { - // 3. - module: &shader, - entry_point: Some("fs_main"), - targets: &[Some(wgpu::ColorTargetState { - // 4. - format: config.format, - blend: Some(wgpu::BlendState::REPLACE), - write_mask: wgpu::ColorWrites::ALL, - })], - compilation_options: wgpu::PipelineCompilationOptions::default(), - }), - primitive: Default::default(), /*wgpu::PrimitiveState { - topology: wgpu::PrimitiveTopology::TriangleList, - strip_index_format: None, - front_face: wgpu::FrontFace::Ccw, - cull_mode: None, - polygon_mode: wgpu::PolygonMode::Fill, - unclipped_depth: false, - conservative: false, - }*/ - depth_stencil: Some(wgpu::DepthStencilState { - stencil: wgpu::StencilState::default(), - format: wgpu::TextureFormat::Depth32Float, - depth_write_enabled: Some(true), - depth_compare: Some(wgpu::CompareFunction::Less), - bias: wgpu::DepthBiasState::default(), - }), - multisample: wgpu::MultisampleState { - count: 1, - mask: !0, - alpha_to_coverage_enabled: false, - }, - multiview_mask: None, - cache: None, - }); - - //todo: use a pipeline cache! - let sky_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { - label: Some("Sky Pipeline"), - layout: Some(&pipeline_layout), - vertex: wgpu::VertexState { - module: &shader, - entry_point: Some("vs_sky"), - compilation_options: Default::default(), - buffers: &[], - }, - fragment: Some(wgpu::FragmentState { - module: &shader, - entry_point: Some("fs_sky"), - compilation_options: Default::default(), - targets: &[Some(wgpu::ColorTargetState { - // 4. - format: config.format, - blend: Some(wgpu::BlendState::REPLACE), - write_mask: wgpu::ColorWrites::ALL, - })], - }), - primitive: wgpu::PrimitiveState { - front_face: wgpu::FrontFace::Cw, - ..Default::default() - }, - depth_stencil: Some(wgpu::DepthStencilState { - format: wgpu::TextureFormat::Depth32Float, - depth_write_enabled: Some(false), - depth_compare: Some(wgpu::CompareFunction::LessEqual), - stencil: wgpu::StencilState::default(), - bias: wgpu::DepthBiasState::default(), - }), - multisample: wgpu::MultisampleState::default(), - multiview_mask: None, - cache: None, - }); - - let size = wgpu::Extent3d { - // 2. - width: config.width.max(1), - height: config.height.max(1), - depth_or_array_layers: 1, - }; - let desc = wgpu::TextureDescriptor { - label: Some("depth texture"), - size, - mip_level_count: 1, - sample_count: 1, - dimension: wgpu::TextureDimension::D2, - format: wgpu::TextureFormat::Depth32Float, - usage: wgpu::TextureUsages::RENDER_ATTACHMENT // 3. - | wgpu::TextureUsages::TEXTURE_BINDING, - view_formats: &[], - }; - let depth_texture = device.create_texture(&desc); - let depth_view = depth_texture.create_view(&wgpu::TextureViewDescriptor::default()); - let depth_sampler = device.create_sampler(&wgpu::SamplerDescriptor { - // 4. - address_mode_u: wgpu::AddressMode::ClampToEdge, - address_mode_v: wgpu::AddressMode::ClampToEdge, - address_mode_w: wgpu::AddressMode::ClampToEdge, - mag_filter: wgpu::FilterMode::Linear, - min_filter: wgpu::FilterMode::Linear, - mipmap_filter: wgpu::MipmapFilterMode::Nearest, - compare: Some(wgpu::CompareFunction::LessEqual), // 5. - lod_min_clamp: 0.0, - lod_max_clamp: 100.0, - ..Default::default() - }); - - let instances = SimpleInstances::new(&device); - - let buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { - label: Some("Vertex Buffer"), - contents: bytemuck::cast_slice(&DEFAULT_VERTICES), - usage: wgpu::BufferUsages::VERTEX, - }); - - let default_material = SimpleMaterial::new( - &device, - &texture_bind_group_layout, - &default_texture, - &default_texture, - &default_texture, - MaterialProperties::default(), - ); + let depth_texture = Texture::depth(&config,&device); Ok(Renderer { - id_count: 0, - material_layout: texture_bind_group_layout, - default_texture, - default_material, - depth_texture: SimpleTexture { - texture: depth_texture, - view: depth_view, - }, + depth: depth_texture, instances, - sky_pipeline, - instance_pipeline, surface, config, device, queue, + textures, + meshes: Default::default(), eye, }) } - pub(crate) fn render(&mut self, window: &Arc) -> anyhow::Result<()> { - window.request_redraw(); - - let mut resize_renderer = false; - - let output = match self.surface.get_current_texture() { + pub(crate) fn render(&mut self, window: &Arc, objects: &mut FreeList) -> anyhow::Result<()> { + let surface_texture = match self.surface.get_current_texture() { wgpu::CurrentSurfaceTexture::Success(surface_texture) => surface_texture, - wgpu::CurrentSurfaceTexture::Suboptimal(surface_texture) => { - resize_renderer = true; //moved reconfigure to avoid a crash when resizing window - surface_texture + wgpu::CurrentSurfaceTexture::Suboptimal(_surface_texture) => { + println!("suboptimal"); + self.surface.configure(&self.device, &self.config); + return Ok(()); } wgpu::CurrentSurfaceTexture::Timeout | wgpu::CurrentSurfaceTexture::Occluded | wgpu::CurrentSurfaceTexture::Validation => { - // Skip this frame + println!("timeout"); return Ok(()); } wgpu::CurrentSurfaceTexture::Outdated => { self.surface.configure(&self.device, &self.config); + println!("outdated"); return Ok(()); } wgpu::CurrentSurfaceTexture::Lost => { @@ -1201,17 +207,19 @@ impl Renderer { anyhow::bail!("Lost device"); } }; - let view = output - .texture - .create_view(&wgpu::TextureViewDescriptor::default()); - let program = self.instances.write_instances(&self.device, &self.queue); + let view = surface_texture + .texture + .create_view(&wgpu::TextureViewDescriptor::default()); let mut encoder = self - .device - .create_command_encoder(&wgpu::CommandEncoderDescriptor { - label: Some("Render Encoder"), - }); + .device + .create_command_encoder(&wgpu::CommandEncoderDescriptor { + label: Some("Render Encoder"), + }); + + self.eye.write(&self.queue); + self.instances.write_instances(&self.device, &self.queue, &mut self.meshes, objects); { let mut pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { @@ -1231,7 +239,7 @@ impl Renderer { }, })], depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachment { - view: &self.depth_texture.view, + view: &self.depth.view, depth_ops: Some(wgpu::Operations { load: wgpu::LoadOp::Clear(1.0), store: wgpu::StoreOp::Store, @@ -1243,37 +251,35 @@ impl Renderer { multiview_mask: None, }); - pass.set_pipeline(&self.instance_pipeline); + pass.set_pipeline(&self.eye.sky_pipeline); pass.set_bind_group(0, &self.eye.group, &[]); - pass.set_vertex_buffer(1, self.instances.instance_buffer.slice(..)); - program.render(&mut pass); - - pass.set_bind_group(1, &self.default_material.group, &[]); - - pass.set_pipeline(&self.sky_pipeline); pass.draw(0..6, 0..1); + + pass.set_pipeline(&self.instances.pipeline); + pass.set_vertex_buffer(1, self.instances.model_buffer.slice(..)); + std::mem::replace(&mut self.instances.program,Program(Vec::new())).render(&mut pass); // todo: improve } self.queue.submit(Some(encoder.finish())); - self.eye.write(&self.queue); + window.pre_present_notify(); - output.present(); + surface_texture.present(); + //self.queue.present(surface_texture); - - if(resize_renderer){ - std::mem::drop(view); //idk how this would affect a multi-pass system like deferred rendering, but this makes sure it's not gonna collide with resizing the swap chain or whatever wGPU does - self.surface.configure(&self.device, &self.config); + // its rust just being stupid + //std::mem::drop(view); // idk how this would affect a multi-pass system like deferred rendering, but this makes sure it's not gonna collide with resizing the swap chain or whatever wGPU does /* also in this snippet call the functions to - a: resize window resolution - b: resize projection + a: resize window resolution // todo: idk why it's ignoring me + b: resize projection // done: made eye.rs write to eye buffer currently when you resize the window the projection matrix is not updated and therefore it gets very skewed and weird looking if you resize the current small window to a big screen like mine(halbear) which is 3440x1440 i would add it myself but i don't know wGPU or rust all that well sooooo */ - } + + window.request_redraw(); Ok(()) } diff --git a/src/render/sky.wgsl b/src/render/sky.wgsl new file mode 100644 index 0000000..fa563d0 --- /dev/null +++ b/src/render/sky.wgsl @@ -0,0 +1,72 @@ +struct Environment { + ambient: vec4, + light: vec4, + dir: vec4, +} + +struct Eye { + // from camera to screen + proj: mat4x4, + // from screen to camera + inv: mat4x4, + // world to camera + view: mat4x4, + // camera transform + frame: mat4x4, +} + +@group(0) @binding(0) +var eye: Eye; +@group(0) @binding(1) +var environment: Environment; +@group(0) @binding(2) +var sky_sampler: sampler; +@group(0) @binding(3) +var sky_texture: texture_2d; + +// written on the 60th sleepless hour +fn sky_aspect(look: vec3) -> vec4 { + var pi = 3.14159; + let u_angle = atan2(look.x,look.z); + let u = (u_angle/pi) * 0.5 + 0.5; // from -pi/2 -> pi/2 into 0 -> 1 + let v_angle = atan2(-look.y,sqrt(look.x * look.x + look.z * look.z)); + let v = (v_angle/pi) - 0.5;//(v_angle/pi) + 0.5; // from -pi/2 -> pi/2 into 0 -> 1 + let uv = vec2(u,v); // Get UV on skybox + return textureSample(sky_texture, sky_sampler, uv); +} + +struct SkyOutput { + @builtin(position) position: vec4, + @location(0) pos: vec4 // unadulterated by WGSL +} + +const VERTICES = array( + vec4(-1.0, -1.0, 1.0, 1.0), + vec4(-1.0, 1.0, 1.0, 1.0), + vec4( 1.0, -1.0, 1.0, 1.0), + vec4( 1.0, 1.0, 1.0, 1.0), + vec4(-1.0, 1.0, 1.0, 1.0), + vec4( 1.0, -1.0, 1.0, 1.0), +); + +fn rotation(it: mat4x4) -> mat3x3 { + return mat3x3( + it[0].xyz, + it[1].xyz, + it[2].xyz, + ); +} + +@vertex +fn vs_sky(@builtin(vertex_index) index: u32) -> SkyOutput { + var out: SkyOutput; + out.position = VERTICES[index]; + out.pos = out.position; + return out; +} + +@fragment +fn fs_sky(in: SkyOutput) -> @location(0) vec4 { + let look = rotation(eye.frame) * in.pos.xyz; + return sky_aspect(look); +} diff --git a/src/render/texture.rs b/src/render/texture.rs new file mode 100644 index 0000000..131d52f --- /dev/null +++ b/src/render/texture.rs @@ -0,0 +1,115 @@ +use image::EncodableLayout; +use wgpu::{Device, Queue}; +use crate::render::Renderer; + +#[derive(Debug, Clone, Hash, Eq, PartialEq)] +pub struct Texture { + texture: wgpu::Texture, + pub(crate) view: wgpu::TextureView, +} +pub struct TextureProperties { + pub(crate) width: u32, + pub(crate) height: u32, +} +// todo: use texture compression! +impl Texture { + pub fn depth(config: &wgpu::SurfaceConfiguration, device: &Device) -> Texture { + let size = wgpu::Extent3d { + // 2. + width: config.width.max(1), + height: config.height.max(1), + depth_or_array_layers: 1, + }; + let desc = wgpu::TextureDescriptor { + label: Some("depth texture"), + size, + mip_level_count: 1, + sample_count: 1, + dimension: wgpu::TextureDimension::D2, + format: wgpu::TextureFormat::Depth32Float, + usage: wgpu::TextureUsages::RENDER_ATTACHMENT // 3. + | wgpu::TextureUsages::TEXTURE_BINDING, + view_formats: &[], + }; + let _depth_texture = device.create_texture(&desc); + let depth_view = _depth_texture.create_view(&wgpu::TextureViewDescriptor::default()); + Texture { + texture: _depth_texture, + view: depth_view, + } + } + pub fn load( + device: &Device, + queue: &Queue, + slice: impl AsRef<[u8]>, + properties: TextureProperties, + ) -> Texture { + let size = wgpu::Extent3d { + width: properties.width, + height: properties.height, + depth_or_array_layers: 1, + }; + let diffuse_texture = device.create_texture(&wgpu::TextureDescriptor { + size, + mip_level_count: 1, + sample_count: 1, + dimension: wgpu::TextureDimension::D2, + format: wgpu::TextureFormat::Rgba8UnormSrgb, + usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST, + label: Some("texture"), + view_formats: &[], + }); + let diffuse_texture_view = + diffuse_texture.create_view(&wgpu::TextureViewDescriptor::default()); + queue.write_texture( + wgpu::TexelCopyTextureInfo { + texture: &diffuse_texture, + mip_level: 0, + origin: wgpu::Origin3d::ZERO, + aspect: wgpu::TextureAspect::All, + }, + slice.as_ref(), + wgpu::TexelCopyBufferLayout { + offset: 0, + bytes_per_row: Some(4 * size.width), + rows_per_image: Some(size.height), + }, + size, + ); + Texture { + texture: diffuse_texture, + view: diffuse_texture_view, + } + } + fn _load_from_file_bytes( + device: &Device, + queue: &Queue, + slice: impl AsRef<[u8]>, + format: Option, + ) -> Option { + let image = if let Some(format) = format { + image::load_from_memory_with_format(slice.as_ref(), format) + } else { + image::load_from_memory(slice.as_ref()) + }; + if let Ok(data) = image { + let data = data.into_rgba8(); + Some(Texture::load( + device, + queue, + data.as_bytes(), + TextureProperties { + width: data.width(), + height: data.height(), + }, + )) + } else { + println!("failed to load texture! error: {:?}", image.unwrap_err()); + None + } + } + + pub fn load_from_file_bytes(renderer: &mut Renderer, slice: impl AsRef<[u8]>, format: Option) -> Option { + Texture::_load_from_file_bytes(&renderer.device,&renderer.queue,slice,format) + } +} \ No newline at end of file diff --git a/src/state.rs b/src/state.rs new file mode 100644 index 0000000..1ef7a2a --- /dev/null +++ b/src/state.rs @@ -0,0 +1,19 @@ +use crate::list::FreeList; +use crate::{render, world}; + +#[derive(Default)] +pub struct State { + pub objects: FreeList, + pub lights: FreeList, + pub worlds: FreeList, + pub renderer: Option, + pub screens: FreeList +} + +impl State { + pub fn new() -> State { + State { + ..Default::default() + } + } +} \ No newline at end of file diff --git a/src/ui/mod.rs b/src/ui/mod.rs new file mode 100644 index 0000000..e69de29 diff --git a/src/world/debug.rs b/src/world/debug.rs new file mode 100644 index 0000000..ce65244 --- /dev/null +++ b/src/world/debug.rs @@ -0,0 +1,100 @@ +use glam::{IVec3, Mat4, Quat, Vec3}; +use wgpu::naga::FastHashMap; +use crate::list::{FreeList, Id}; +use crate::render; +use crate::world::{ColliderData, ObjectData, OctreeBlock, Shape, World}; + +pub struct OctreeDebug { + map: FastHashMap> +} + +pub enum OctreeDebugOperation { + Add(IVec3,i32), + Remove(IVec3), +} + +impl Default for OctreeDebug { + fn default() -> Self { + Self::new() + } +} + +impl OctreeDebug { + pub fn new() -> OctreeDebug { + OctreeDebug { + map: FastHashMap::default() + } + } + fn set_block( + &mut self, + blocks: &mut FreeList, + block: Id, + objects: &mut FreeList, + debug: &Option, + pos: IVec3, + mut size: i32 + ) { + let entry = self.map.get(&pos); + if let Some(debug) = debug { + if entry.is_none() { + let mut model = debug.clone(); + model.instance.transform = Mat4::from_scale_rotation_translation(Vec3::splat(size as f32),Quat::IDENTITY,pos.as_vec3()); + self.map.insert(pos, objects.make(ObjectData { + model: Some(model), + collider: ColliderData { + shape: Shape::Sphere(size as f32), + }, + affine: Default::default(), + asleep: false, + }).id); + println!("pos {} size {}",pos,size) + } + } else { + if entry.is_some() { + objects.remove(self.map.remove(&pos).unwrap()); + } + } + size /= 2; + if let Some(block) = blocks.get(&block).blocks[0].exists() { + self.set_block(blocks,block,objects,debug, pos - (IVec3::new(-1, -1, -1) * size / 2), size); + } + if let Some(block) = blocks.get(&block).blocks[1].exists() { + self.set_block(blocks,block,objects,debug,pos - (IVec3::new(1,-1,-1) * size / 2), size); + } + if let Some(block) = blocks.get(&block).blocks[2].exists() { + self.set_block(blocks,block,objects,debug,pos - (IVec3::new(-1,1,-1) * size / 2), size); + } + if let Some(block) = blocks.get(&block).blocks[3].exists() { + self.set_block(blocks,block,objects,debug,pos - (IVec3::new(1,1,-1) * size / 2), size); + } + if let Some(block) = blocks.get(&block).blocks[4].exists() { + self.set_block(blocks,block,objects,debug,pos - (IVec3::new(-1,-1,1) * size / 2), size); + } + if let Some(block) = blocks.get(&block).blocks[5].exists() { + self.set_block(blocks,block,objects,debug,pos - (IVec3::new(1,-1,1) * size / 2), size); + } + if let Some(block) = blocks.get(&block).blocks[6].exists() { + self.set_block(blocks,block,objects,debug,pos - (IVec3::new(-1,1,1) * size / 2), size); + } + if let Some(block) = blocks.get(&block).blocks[7].exists() { + self.set_block(blocks,block,objects,debug,pos - (IVec3::new(1,1,1) * size / 2), size); + } + } + pub fn set(&mut self, objects: &mut FreeList, world: &mut World, debug: Option) { + for (index,block) in world.matter.map.iter_mut() { + self.set_block( + &mut world.matter.blocks, + block.clone(), + objects, + &debug, + index * OctreeBlock::CHUNK_SIZE, + OctreeBlock::CHUNK_SIZE, + ) + } + } + pub fn register(&mut self, objects: &mut FreeList, renderer: &mut render::Renderer) { + for (pos,block) in self.map.iter() { + renderer.instances.register_object(objects.get_ref(block.clone())); + } + } +} \ No newline at end of file diff --git a/src/world/mod.rs b/src/world/mod.rs index 3802219..a44fad9 100644 --- a/src/world/mod.rs +++ b/src/world/mod.rs @@ -1,228 +1,379 @@ -use crate::render::{Renderer, SimpleLightData, SimpleModelData}; -use glam::{DVec3, IVec3, Mat4, UVec3, Vec3, Vec4Swizzles}; +pub mod debug; + +use crate::render::instance::ModelData; +use glam::{Affine3, IVec3, Mat4, Quat, Vec3}; use std::cell::RefCell; use std::hash::{BuildHasherDefault, Hash, Hasher}; -use std::ops::{Div, Mul}; +use std::path::absolute; use std::rc::Rc; +use mars::vm::Object; use wgpu::naga::{FastHashMap, FastHashSet}; +use crate::{list, render}; +use crate::list::{FreeList, Id, MaybeId, RefId, SingleId}; #[derive(Clone)] pub enum Shape { Block(Vec3), Sphere(f32), - None, } #[derive(Clone)] -pub struct SimpleColliderData { - pub transform: Mat4, +pub struct ColliderData { pub shape: Shape, - pub radius: f32, } -#[derive(Clone)] -pub struct SimpleObjectData { - pub model: Option, - pub collider: SimpleColliderData, -} - -#[derive(Clone)] -pub struct SimpleLight(pub Rc>); - -impl PartialEq for SimpleLight { - fn eq(&self, other: &Self) -> bool { - Rc::ptr_eq(&self.0, &other.0) - } -} - -impl Eq for SimpleLight {} - -impl Hash for SimpleLight { - fn hash(&self, state: &mut H) { - (self.0.as_ptr() as *const RefCell).hash(state) +impl ColliderData { + fn aabb(&self, affine: Affine3) -> AABB { + let (_scale, _rotation, translation) = affine.to_scale_rotation_translation(); + match self.shape { + Shape::Block(size) => { + let radius_offset = Vec3::splat(size.length()); + AABB( + translation - radius_offset, + translation + radius_offset, + ) + } + Shape::Sphere(radius) => { + let radius_offset = Vec3::splat(radius); + AABB( + translation - radius_offset, + translation + radius_offset, + ) + } + } } } #[derive(Clone)] -pub struct SimpleObject(pub Rc>); +pub struct ObjectData { + pub model: Option, + pub collider: ColliderData, + pub affine: Affine3, + pub asleep: bool, +} -impl SimpleObject { - pub(crate) fn hard_clone(&self) -> SimpleObject { - SimpleObject { - 0: Rc::new(RefCell::new(SimpleObjectData { - model: self.0.borrow().model.clone(), - collider: self.0.borrow().collider.clone(), - })), - } +impl ObjectData { + pub fn set_affine(&mut self, affine: Affine3) { + self.affine = affine; + self.asleep = false; } } -impl PartialEq for SimpleObject { - fn eq(&self, other: &Self) -> bool { - Rc::ptr_eq(&self.0, &other.0) +#[derive(Clone, Eq, PartialEq)] +pub enum InterestType { + Light(Id), + Object(Id) +} + +#[derive(Clone)] +pub struct Interest { + it: InterestType, + aabb: AABB, +} + +#[derive(Clone)] +pub struct InterestNode { + interest: Interest, + next: MaybeId, +} + +#[derive(Clone, Copy, Debug, PartialEq)] +pub struct AABB(pub(crate) Vec3, pub(crate) Vec3); + +impl AABB { + pub(crate) fn new(translation: Vec3, size: Vec3) -> AABB { + AABB(translation - size, translation + size) + } + pub fn extend_to(&self, point: Vec3) -> AABB { + AABB(self.0.min(point),self.1.max(point)) + } + pub fn bounded_by(&self, aabb: AABB) -> AABB { + AABB(self.0.max(aabb.0), self.1.min(aabb.1)) + } + fn offset(&self) -> Vec3 { + self.1 - self.0 + } + fn to_iaabb(&self) -> IAABB { + IAABB(self.0.as_ivec3(),self.1.as_ivec3()) } } -impl Eq for SimpleObject {} +#[derive(Clone, Copy, Debug, PartialEq)] +pub struct IAABB(pub(crate) IVec3, pub(crate) IVec3); -impl Hash for SimpleObject { - fn hash(&self, state: &mut H) { - (self.0.as_ptr() as *const RefCell).hash(state); +impl IAABB { + pub(crate) fn new(translation: IVec3, size: IVec3) -> IAABB { + IAABB(translation - size, translation + size) } -} - -#[derive(Eq, Hash, PartialEq, Clone)] -enum Interest { - Light(SimpleLight), - Object(SimpleObject), -} - -struct Block { - debug: Option, - volume: u8, - velocity: Vec3, - material: u8, - interests: FastHashSet, - blocks: [Option>; 64], -} - -const TREE_ATTACK: usize = 4; -const TREE_FLOOR: usize = 4; -impl Block { - fn new() -> Block { - Block { - debug: None, - volume: 0, - velocity: Vec3::ZERO, - material: 0, - interests: FastHashSet::with_hasher(BuildHasherDefault::default()), - blocks: [const { None }; const { TREE_ATTACK * TREE_ATTACK * TREE_ATTACK }], - } + pub fn extend_to(&self, point: IVec3) -> IAABB { + IAABB(self.0.min(point),self.1.max(point)) } - fn place_pos(&mut self, interest: Interest, pos: Vec3, rad: f32, block_size: f32) { - let cs = block_size / const { TREE_ATTACK as f32 }; - if rad < cs || block_size >= TREE_FLOOR as f32 { - let rel = ((pos + block_size / 2.0) / cs).round().as_uvec3(); - let new_pos = pos - (rel.as_vec3() + cs / 2.0); - let index = (rel.x + rel.y * 4 + rel.z * 16) as usize; - match self.blocks[index] { - Some(ref mut block) => { - block.place_pos(interest, new_pos, rad, cs); - } - None => { - let mut block = Box::new(Block::new()); - block.place_pos(interest, new_pos, rad, cs); - self.blocks[index] = Some(block); - } - } - } else { - self.interests.insert(interest); - } + pub fn bounded_by(&self, aabb: IAABB) -> IAABB { + IAABB(self.0.max(aabb.0), self.1.min(aabb.1)) } - fn debug_step(&mut self, value: bool) { - match self.debug { - Some(ref mut debug) => { - if value { - } else { - } - } - None => { - if value { - } else { - } - } - } - for maybe_block in self.blocks.iter_mut() { - if let Some(block) = maybe_block { - block.debug_step(value) - } - } + fn offset(&self) -> IVec3 { + self.1 - self.0 + } + fn to_aabb(self) -> AABB { + AABB(self.0.as_vec3(),self.1.as_vec3()) } } pub struct World { - chunk_size: u32, - map: FastHashMap, - pub renderer: Option, - debug_world_map: bool, - debug_world_map_object: Option, + pub(crate) matter: OctreeMap, +} + +impl Default for World { + fn default() -> Self { + Self::new() + } } impl World { pub fn new() -> World { World { - chunk_size: 512, - map: FastHashMap::with_hasher(BuildHasherDefault::default()), - renderer: None, - debug_world_map: false, - debug_world_map_object: None, + matter: OctreeMap::new(), + } } - pub fn add_renderer(&mut self, renderer: Renderer) { - self.renderer = Some(renderer); - self.debug_world_map_object = self - .renderer - .as_mut() - .unwrap() - .load_from_gltf(include_bytes!("../assets/cube.glb")) - .first_object() + pub fn add_object(&mut self, object: RefId) -> Id { + self.matter.place_interest(Interest { + it: InterestType::Object(object.id.clone()), + aabb: object.collider.aabb(object.affine), + }); + object.id } - pub fn add_object(&mut self, object: SimpleObject) { - self.place(Interest::Object(object.clone())); - if let Some(ref mut renderer) = self.renderer { - renderer.instances.add_object(object) - } + pub fn remove_object(&mut self, object: Id) { + } - pub fn set_debug(&mut self, value: bool) { - self.debug_world_map = value; - } - pub fn light_step(&mut self) {} - pub fn object_step(&mut self) {} - pub fn debug_step(&mut self) { - self.light_step(); - self.object_step(); - for (index, item) in self.map.iter_mut() { - item.debug_step(self.debug_world_map); - } - } - fn place_pos(&mut self, interest: Interest, pos: Vec3, rad: f32) { - let cs = self.chunk_size as f32; - let c_rad = ((cs / 2.0) * (cs / 2.0)) * 3.0; - for x in (pos.x - rad).div(cs) as i32..=(pos.x + rad).div(cs).ceil() as i32 { - for y in (pos.y - rad).div(cs) as i32..=(pos.y + rad).div(cs).ceil() as i32 { - for z in (pos.z - rad).div(cs) as i32..=(pos.z + rad).div(cs).ceil() as i32 { - let block_pos = IVec3::new(x, y, z); - let block_pos_f32 = block_pos.as_vec3(); - if block_pos_f32.distance_squared(pos) < rad + c_rad { - self.map.entry(block_pos).or_insert_with(|| { - let mut block = Block::new(); - block.place_pos( - interest.clone(), - pos - block_pos_f32, - rad, - self.chunk_size as f32, - ); - block - }); + pub fn step( + &mut self, + maybe_renderer: &mut Option, + objects: &mut FreeList, + _lights: &mut FreeList, + ) { + fn reinsert( + block_id: &Id, + blocks: &mut FreeList, + interests: &mut FreeList, + objects: &mut FreeList + ) { + let mut maybe_interest = &blocks.get(block_id).first; + while let Some(interest_id) = maybe_interest.exists() { + let interest = interests.get(&interest_id); + match interest.interest.it { + InterestType::Object(ref object_id) => { } + _ => {} + } + maybe_interest = &interest.next; + } + for id in blocks.get(block_id).blocks.clone().iter() { + if let Some(id) = id.exists() { + reinsert(&id, blocks, interests, objects) + } + } + } + for (_pos,id) in self.matter.map.iter() { + reinsert(id, &mut self.matter.blocks, &mut self.matter.nodes, objects) + } + if let Some(renderer) = maybe_renderer { + fn consider( + block_id: &Id, + renderer: &mut render::Renderer, + blocks: &mut FreeList, + interests: &mut FreeList, + objects: &mut FreeList + ) { + let mut maybe_interest = &blocks.get(block_id).first; + while let Some(interest_id) = maybe_interest.exists() { + let interest = interests.get(&interest_id); + match interest.interest.it { + InterestType::Object(ref object_id) => { + let mut object = objects.get_ref(object_id.clone()); + let transform = Mat4::from_mat3_translation(object.affine.matrix3,object.affine.translation); + object.model.as_mut().unwrap().instance.transform = transform; + renderer.instances.register_object(object) + } + _ => {} + } + maybe_interest = &interest.next; + } + for id in blocks.get(block_id).blocks.clone().iter() { + if let Some(id) = id.exists() { + consider(&id, renderer, blocks, interests, objects) + } + } + } + for (_pos,id) in self.matter.map.iter() { + consider(id, renderer, &mut self.matter.blocks, &mut self.matter.nodes, objects) + } + } + } + fn sync(&mut self) {} +} + +#[derive(Copy, Clone)] +struct Material { + volume: u8, + velocity: Vec3, + material: u8, +} + +impl Material { + const fn new() -> Material { + Material { + volume: 0, + velocity: Vec3::ZERO, + material: 0 + } + } +} + +impl OctreeBlock { + const FLOOR: i32 = 4; + const CHUNK_SIZE: i32 = OctreeBlock::FLOOR * 64; + const MAX_IDEAL_INTEREST: usize = 4; + fn new() -> OctreeBlock { + OctreeBlock { + interests: 0, + material: Material::new(), + first: MaybeId::NULL, + blocks: [MaybeId::NULL;8], + } + } +} + +struct OctreeBlock { + interests: u32, // 1 + first: MaybeId, // 1 + material: Material, // 4 + blocks: Blocks, // 8 +} + +impl OctreeBlock { + fn push_interest(&mut self, interests: &mut FreeList, interest: Interest) { + self.first = interests.make(InterestNode { + interest: interest.clone(), + next: self.first.clone(), + }).id.maybe(); + self.interests += 1; + } + fn remove_interest(&mut self, interests: &mut FreeList, needle: Interest) { // todo: needed? + let mut maybe_last = MaybeId::NULL; + let mut maybe_this = self.first.clone(); + while let Some(this) = maybe_this.exists() { + let interest = interests.get(&this); + let next = interest.next.clone(); + if interest.interest.it == needle.it { + self.interests -= 1; + if let Some(last) = maybe_last.exists() { + interests.get(&last).next = interest.next.clone(); + } else { + self.first = interest.next.clone(); + break; + } + } + maybe_last = maybe_this; + maybe_this = next; + } + panic!() + } + fn place( + it: Id, + blocks: &mut FreeList, + interests: &mut FreeList, + interest: Interest, + pos: IVec3, + size: i32, + ) { + if pos == IVec3::ZERO || blocks.get(&it).interests < OctreeBlock::MAX_IDEAL_INTEREST as u32 { + blocks.get(&it).push_interest(interests, interest) + } else { + let mut index = 0; + let x = if pos.x > 0 { + index += 1; + -size + } else { + size + }; + let y = if pos.y > 0 { + index += 2; + -size + } else { + size + }; + let z = if pos.z > 0 { + index += 4; + -size + } else { + size + }; + let offset = IVec3::new(x,y,z) / 2; + println!("pos {} {} {}",pos,pos + offset,size); + let id = if let Some(id) = blocks.get(&it).blocks[index as usize].exists() { + id + } else { + let id = blocks.make(OctreeBlock::new()).id; + blocks.get(&it).blocks[index as usize] = id.clone().into(); + id + }; + OctreeBlock::place(id,blocks,interests,interest,pos + offset,size / 2); + } + } +} + +type Blocks = [MaybeId; 8]; + +pub struct OctreeMap { + interests: FreeList, + nodes: FreeList, + blocks: FreeList, + map: FastHashMap>, +} + +impl OctreeMap { + fn place_interest(&mut self, interest: Interest) { + let mut d = 4; + let offset = interest.aabb.1 - interest.aabb.0; + while offset.element_sum() > (d * 2) as f32 { + d *= 2 + } + let iaabb = IAABB( + (interest.aabb.0 / d as f32).floor().as_ivec3() + IVec3::splat(d / 2), + (interest.aabb.1 / d as f32).floor().as_ivec3() + IVec3::splat(d / 2), + ); + println!("attempting place I: {} {} {} A: {} {}",iaabb.0,iaabb.1,d,interest.aabb.0,interest.aabb.1); + for x in iaabb.0.x..iaabb.1.x { + for y in iaabb.0.y..iaabb.1.y { + for z in iaabb.0.z..iaabb.1.z { + let index = IVec3::new(x,y,z); + let absolute_pos = index * d; + let chunk_index = absolute_pos / OctreeBlock::CHUNK_SIZE; + let chunk_pos = chunk_index * OctreeBlock::CHUNK_SIZE; + let block = self.map.entry(chunk_index).or_insert_with(|| { + self.blocks.make(OctreeBlock::new()).id + }); + let pos = absolute_pos - chunk_pos; + println!("placing {} {}",pos,OctreeBlock::CHUNK_SIZE); + OctreeBlock::place( + block.clone(), + &mut self.blocks, + &mut self.nodes, + interest.clone(), + pos, + OctreeBlock::CHUNK_SIZE, + ); } } } } - fn place(&mut self, interest: Interest) { - let (pos, rad) = match &interest { - Interest::Light(light) => { - let light = light.0.borrow(); - (light.instance.location.xyz(), light.instance.color.length()) - } - Interest::Object(object) => { - let collider = &object.0.borrow().collider; - ( - collider.transform.to_scale_rotation_translation().2, - collider.radius, - ) - } - }; - self.place_pos(interest, pos, rad); + fn new() -> OctreeMap { + OctreeMap { + interests: Default::default(), + nodes: Default::default(), + blocks: Default::default(), + map: FastHashMap::with_hasher(BuildHasherDefault::default()), + } } -} +} \ No newline at end of file