diff --git a/.gitignore b/.gitignore index 83ea247..54088d5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,2 @@ target .DS_Store -Cargo.lock \ No newline at end of file diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..30cf57e --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,10 @@ +# 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 cf84ae4..0cd351f 100644 --- a/.idea/Pool.iml +++ b/.idea/Pool.iml @@ -3,7 +3,13 @@ + + + + + + diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 0000000..a55e7a1 --- /dev/null +++ b/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/.idea/dictionaries/project.xml b/.idea/dictionaries/project.xml new file mode 100644 index 0000000..4c3305b --- /dev/null +++ b/.idea/dictionaries/project.xml @@ -0,0 +1,8 @@ + + + + forloop + vmcase + + + \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..ed30955 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,3033 @@ +# 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 0.3.4", + "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", + "rand", + "rand_chacha", + "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.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[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 0.3.4", + "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 = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + +[[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 = "rand" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e058c7de0b26af77780c769414d6257830bb240f3c38477dbc2c16e5f54d6d4c" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.17", +] + +[[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 = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[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 823c29a..a21b8d5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,18 +1,14 @@ [package] #![recursion_limit = "256"] -name = "pool" +name = "game" version = "0.1.0" edition = "2024" -[features] -big_ids = [] -check_ids = [] - [profile.release] strip = true [[bin]] -name = "pool" +name = "game" path = "src/main.rs" [dependencies] @@ -21,17 +17,19 @@ anyhow = "1.0" winit = { version = "0.30", features = ["android-native-activity"] } env_logger = "0.11.10" log = "0.4" -wgpu = "29.0.4" +wgpu = "29.0.3" pollster = "0.4.0" glam = { version = "0.33.3", features = [ "bytemuck" ] } console_error_panic_hook = "0.1.7" bytemuck = { version = "1.25.0", features = [ "derive" ]} image = { version = "0.24", default-features = false, features = ["png", "jpeg"]} mars = { path = "../Mars" } +rand = "0.8" +rand_chacha = "0.3" [target.'cfg(target_arch = "wasm32")'.dependencies] console_error_panic_hook = "0.1.6" -wgpu = { version = "30.0.1", features = ["webgl"]} +wgpu = { version = "29.0.3", 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 c51d11c..37a444e 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. +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. 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 3c9653d..d2e35ba 100644 --- a/src/app.rs +++ b/src/app.rs @@ -1,8 +1,10 @@ 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::{loader, Renderer}; -use crate::world::{World, ObjectData}; -use glam::{Affine3, Affine3A, EulerRot, Mat4, Quat, Vec2, Vec3, Vec4}; +use crate::render::Renderer; +use crate::world::{SimpleObject, World}; +use crate::permutation_array; +use crate::noise2d; +use glam::{Affine3A, EulerRot, Mat4, Quat, Vec2, Vec3, Vec4}; use std::sync::Arc; #[cfg(target_arch = "wasm32")] use wasm_bindgen::prelude::*; @@ -16,12 +18,8 @@ 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; +use crate::noise2d::Noise2D; +use crate::permutation_array::PermutationArray; struct Controller { buttons: HashMap, @@ -40,66 +38,76 @@ impl Controller { } pub struct AppState { - state: state::State, - world: Id, - debug: OctreeDebug, - debug_model: ModelData, + world: World, controller: Controller, window: Arc, + clients: Vec, + chunks: Vec<(i32, i32)>, + Permutation: PermutationArray, } -const BLOCKS: i32 = 2; +const BLOCKS: i32 = 100; + 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 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, - ); - } - } - } - let debug = OctreeDebug::new(); - (world.id,debug,debug_model) - }; + let mut world = World::new(); + world.add_renderer(Renderer::new(&window).await?); + let mut Permutation: PermutationArray = PermutationArray::new(); + Permutation.generate_permutation_array(0); + let mut chunks = Vec::new(); + 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 * 1.0, Noise2D::fractal_noise(x as f64 * 0.1, y as f64*0.1, 5, 10.0, 0.05, &Permutation).round() as i64 as f32, -y as f32 * 1.0), + // ) + // * Mat4::from_rotation_z(0f32 /*(x * y) as f32 / 1.23*/); + // model.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) + // } + // } + } Ok(Self { - state, world, - debug, - debug_model, + clients, controller: Controller::new(), window, + chunks, + Permutation }) } + + pub fn bounds(&self) -> (u32, u32) { let size = self.window.inner_size(); (size.width, size.height) @@ -107,7 +115,7 @@ impl AppState { pub fn resize(&mut self, width: u32, height: u32) { if width > 0 && height > 0 { - self.state.renderer.as_mut().unwrap().resize(width, height); + self.world.renderer.as_mut().unwrap().resize(width, height); } } @@ -120,7 +128,7 @@ impl AppState { (KeyCode::Escape, true) => event_loop.exit(), (KeyCode::Space, true) => {} (KeyCode::KeyR, true) => { - self.state.renderer.as_mut().unwrap().eye.frame = Affine3A::IDENTITY + self.world.renderer.as_mut().unwrap().eye.frame = Affine3A::IDENTITY } _ => {} } @@ -129,7 +137,7 @@ impl AppState { fn handle_mouse_moved(&mut self, position: PhysicalPosition) { if let Some(true) = self.controller.buttons.get(&MouseButton::Right) { - self.state.renderer.as_mut().unwrap().eye.rotate( + self.world.renderer.as_mut().unwrap().eye.rotate( position.x as f32 - self.controller.mouse.x, position.y as f32 - self.controller.mouse.y, ); @@ -158,6 +166,42 @@ impl App { proxy, } } + + pub fn GenerateChunk(ChunkX: i32, ChunkY: i32, size: i32, state: &mut AppState){ + if(state.chunks.contains(&(ChunkX, ChunkY))){ + return; + } + let file = state.world + .renderer + .as_mut() + .unwrap() + .load_from_gltf(include_bytes!("assets/cube.glb")); + let block = file.first_object().unwrap(); + + for x in 0..size { + for y in 0..size { + let worldPosX = ChunkX * size + x; + let worldPosY = ChunkY * size + y; + let block = block.hard_clone(); + state.world.add_object(block.clone()); + { + let mut model = block.0.borrow_mut(); + model.model.as_mut().unwrap().instance.transform = Mat4::from_translation( + Vec3::new(worldPosX as f32 * 1.0, Noise2D::fractal_noise(worldPosX as f64 * 0.25, worldPosY as f64*0.25, 10, 20.0, 0.05, &state.Permutation).round() as i64 as f32, worldPosY as f32 * 1.0), + ) + * Mat4::from_rotation_z(0f32 /*(x * y) as f32 / 1.23*/); + model.model.as_mut().unwrap().instance.color = Vec4::new( + 0.3, + (x + size) as f32 / size as f32, + (y + size) as f32 / size as f32, + 1.0, + ); + } + state.clients.push(block); + } + } + state.chunks.push((ChunkX, ChunkY)); + } } impl ApplicationHandler for App { @@ -181,8 +225,6 @@ 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 @@ -239,14 +281,15 @@ 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| { - matches!(state.controller.keys.get(&keycode), Some(true)) + if let Some(true) = state.controller.keys.get(&keycode) { + true + } else { + false + } }; if pressed(KeyCode::KeyA) { @@ -267,12 +310,30 @@ impl ApplicationHandler for App { if pressed(KeyCode::KeyQ) { movement.y -= 1.0; } - 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) { + + let PosX = state.world.renderer.as_ref().unwrap().eye.frame.translation.x; + let Posy = state.world.renderer.as_ref().unwrap().eye.frame.translation.z; + + let WorldPosX = (PosX / 16.0).floor() as i32; + let WorldPosY = (Posy / 16.0).floor() as i32; + let startX = WorldPosX - 5; + let endX = WorldPosX + 5; + let startY = WorldPosY - 5; + let endY = WorldPosY + 5; + + for x in startX..endX { + for y in startY..endY { + App::GenerateChunk(x, y, 16, state); + } + } + state + .world + .renderer + .as_mut() + .unwrap() + .eye + .control(movement * 0.5); + match state.world.renderer.as_mut().unwrap().render(&state.window) { Ok(_) => {} Err(e) => { // Log the error and exit gracefully @@ -280,9 +341,19 @@ impl ApplicationHandler for App { event_loop.exit(); } } - - let elapsed = now.elapsed(); - //println!("Elapsed {:.2?}",elapsed); + 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.00,0.00,0.00 /*0.001, -0.001, 0.001*/), + Vec3::new(0.0, 0.0, 0.0), + ); + } } WindowEvent::MouseInput { button, @@ -302,6 +373,9 @@ impl ApplicationHandler for App { _ => {} } } + + + } pub fn run() -> anyhow::Result<()> { diff --git a/src/render/instance/instance.wgsl b/src/assets/SimpleShader.wgsl similarity index 74% rename from src/render/instance/instance.wgsl rename to src/assets/SimpleShader.wgsl index e882b6e..7a9a592 100644 --- a/src/render/instance/instance.wgsl +++ b/src/assets/SimpleShader.wgsl @@ -15,6 +15,7 @@ struct Eye { frame: mat4x4, } +// Vertex shader @group(0) @binding(0) var eye: Eye; @group(0) @binding(1) @@ -87,36 +88,31 @@ 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 + 0.5; // from -pi/2 -> pi/2 into 0 -> 1 + let u = (u_angle/pi) + 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(it: mat4x4) -> mat3x3 { +fn rotation(mat: mat4x4) -> mat3x3 { return mat3x3( - it[0].xyz, - it[1].xyz, - it[2].xyz, + mat[0].xyz, + mat[1].xyz, + mat[2].xyz, ); } -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); +fn translation(mat: mat4x4) -> vec4 { + //return vec4(mat[0][3],mat[1][3],mat[2][3],mat[3][3]); + return mat[3]; } @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))); @@ -133,13 +129,35 @@ 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 reflect_factor = pow(object_rough.x,3); + let result = (environment.ambient.xyz + diffuse_color.xyz + specular_color.xyz) * object_color.xyz; - let diffuse_brightness = length(diffuse_color); + return vec4(reflection.xyz,object_color.a); +} - let diffuse_effect = (diffuse_result * (1 - reflect_factor)) + reflection.xyz * reflect_factor * diffuse_brightness; +struct SkyOutput { + @builtin(position) position: vec4, + @location(0) pos: vec4 // unadulterated by WGSL +} - let result = (diffuse_effect.xyz + specular_color.xyz); +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), +); - return vec4(result.xyz,object_color.a); -} \ No newline at end of file +@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); +} diff --git a/src/assets/debug.glb b/src/assets/debug.glb index 9f1f226..13fe9af 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 deleted file mode 100644 index e828de1..0000000 Binary files a/src/assets/skybox2.png and /dev/null differ diff --git a/src/lib.rs b/src/lib.rs index edba5d1..3275aa0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,23 +1,7 @@ #![recursion_limit = "256"] - -use std::error::Error; -use std::fmt::{Display, Formatter}; - pub mod app; pub mod render; pub mod web; 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 +pub mod permutation_array; +pub mod noise2d; \ No newline at end of file diff --git a/src/list.rs b/src/list.rs deleted file mode 100644 index c1eb01f..0000000 --- a/src/list.rs +++ /dev/null @@ -1,185 +0,0 @@ -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 7b3961b..9ae830d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,6 @@ #![recursion_limit = "256"] -use pool::*; +use game::*; fn main() { app::run().unwrap(); } diff --git a/src/net/mod.rs b/src/net/mod.rs deleted file mode 100644 index e69de29..0000000 diff --git a/src/noise2d.rs b/src/noise2d.rs new file mode 100644 index 0000000..f473026 --- /dev/null +++ b/src/noise2d.rs @@ -0,0 +1,97 @@ +use crate::permutation_array; +use crate::permutation_array::PermutationArray; + +#[derive(Debug, Clone, Copy)] +pub struct Vector2d { + pub x: f64, + pub y: f64, +} + +impl Vector2d { + pub fn new(x: f64, y: f64) -> Self { + Self { x, y } + } + + pub fn dot(&self, other: Vector2d) -> f64 { + self.x * other.x + self.y * other.y + } +} + +pub struct Noise2D; + +impl Noise2D { + pub fn gen_gradient_vector(p: i32) -> Vector2d { + match p & 3 { + 0 => Vector2d::new(1.0, 1.0), + 1 => Vector2d::new(-1.0, 1.0), + 2 => Vector2d::new(-1.0, -1.0), + _ => Vector2d::new(1.0, -1.0), + } + } + + fn fade(t: f64) -> f64 { + t * t * t * (t * (t * 6.0 - 15.0) + 10.0) + } + + fn lerp(t: f64, x: f64, y: f64) -> f64 { + x + t * (y - x) + } + + pub fn noise_2d(x: f64, y: f64, permutation: &[i32; 512]) -> f64 { + let x_floor = x.floor(); + let y_floor = y.floor(); + + let x_grid = (x_floor as i32) & 255; + let y_grid = (y_floor as i32) & 255; + + let xd = x - x_floor; + let yd = y - y_floor; + + let tr = Vector2d::new(xd - 1.0, yd - 1.0); + let tl = Vector2d::new(xd, yd - 1.0); + let br = Vector2d::new(xd - 1.0, yd); + let bl = Vector2d::new(xd, yd); + + let x_idx = x_grid as usize; + let y_idx = y_grid as usize; + + let value_tr = permutation[permutation[x_idx + 1] as usize + y_idx + 1]; + let value_tl = permutation[permutation[x_idx] as usize + y_idx + 1]; + let value_br = permutation[permutation[x_idx + 1] as usize + y_idx]; + let value_bl = permutation[permutation[x_idx] as usize + y_idx]; + + let d_tr = tr.dot(Self::gen_gradient_vector(value_tr)); + let d_tl = tl.dot(Self::gen_gradient_vector(value_tl)); + let d_br = br.dot(Self::gen_gradient_vector(value_br)); + let d_bl = bl.dot(Self::gen_gradient_vector(value_bl)); + + let u = Self::fade(xd); + let v = Self::fade(yd); + + Self::lerp( + u, + Self::lerp(v, d_bl, d_tl), + Self::lerp(v, d_br, d_tr), + ) + } + + pub fn fractal_noise( + x: f64, + y: f64, + octaves: i32, + mut amplitude: f64, + mut frequency: f64, + permutation: &PermutationArray, + ) -> f64 { + let mut fractal_noise = 0.0; + + for _ in 0..octaves { + let layer = amplitude * Self::noise_2d(x * frequency, y * frequency, permutation.get_permutation()); + fractal_noise += layer; + amplitude *= 0.5; + frequency *= 2.0; + } + + fractal_noise + } +} \ No newline at end of file diff --git a/src/permutation_array.rs b/src/permutation_array.rs new file mode 100644 index 0000000..96e23a8 --- /dev/null +++ b/src/permutation_array.rs @@ -0,0 +1,39 @@ +use rand::{Rng, SeedableRng}; +use rand_chacha::ChaCha8Rng; + +//i translated the Terrain4J Noise2D to Rust so i can mess around with the cubes +pub struct PermutationArray { + permutation: [i32; 512], +} + +impl PermutationArray { + pub fn new() -> Self { + Self { + permutation: [0; 512], + } + } + + pub fn get_permutation(&self) -> &[i32; 512] { + &self.permutation + } + + pub fn generate_permutation_array(&mut self, seed: i64) { + let mut seed_bytes = [0u8; 32]; + seed_bytes[0..8].copy_from_slice(&(seed as u64).to_le_bytes()); + let mut rnd = ChaCha8Rng::from_seed(seed_bytes); + + self.permutation = [0; 512]; + for i in 0..256 { + self.permutation[i] = i as i32; + } + + for p in (1..256).rev() { + let index = rnd.gen_range(0..=p); + self.permutation.swap(p, index); + } + + for i in 0..256 { + self.permutation[i + 256] = self.permutation[i]; + } + } +} \ No newline at end of file diff --git a/src/render/eye.rs b/src/render/eye.rs index 17fce37..11b7112 100644 --- a/src/render/eye.rs +++ b/src/render/eye.rs @@ -1,10 +1,9 @@ -use crate::render::{Texture}; +use crate::render::{MaterialProperties, SimpleTexture}; 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, @@ -17,7 +16,6 @@ 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)] @@ -51,7 +49,7 @@ impl Eye { bytemuck::cast_slice(&[self.environment]), ); } - pub(crate) fn new(device: &Device, config: &wgpu::SurfaceConfiguration, width: u32, height: u32, skybox: Texture) -> Eye { + pub(crate) fn new(device: &Device, width: u32, height: u32, skybox: SimpleTexture) -> Eye { let camera_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { label: Some("Camera Buffer"), contents: bytemuck::cast_slice(&[ @@ -65,7 +63,7 @@ impl Eye { let dir = Vec3::new(1.0, 0.5, 1.0).normalize(); let environment = Environment { - ambient: Vec4::new(0.1, 0.1, 0.1, 0.0), + ambient: Vec4::new(0.15, 0.15, 0.15, 0.0), light: Vec4::new(1.0, 1.0, 1.0, 0.0), dir: Vec4::new(dir.x, dir.y, dir.z, 0.0), }; @@ -118,51 +116,6 @@ 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 { @@ -176,7 +129,6 @@ impl Eye { layout, environment, environment_buffer, - sky_pipeline, } } fn bind_group( @@ -184,7 +136,7 @@ impl Eye { device: &wgpu::Device, camera: &wgpu::Buffer, environment: &wgpu::Buffer, - skybox: Texture, + skybox: SimpleTexture, ) -> wgpu::BindGroup { device.create_bind_group(&wgpu::BindGroupDescriptor { layout: &layout, @@ -211,7 +163,7 @@ impl Eye { label: Some("eye_bind_group"), }) } - pub fn skybox(&mut self, device: &wgpu::Device, texture: Texture) { + pub fn skybox(&mut self, device: &wgpu::Device, texture: SimpleTexture) { self.group = Eye::bind_group( &self.layout, device, @@ -220,9 +172,8 @@ impl Eye { texture, ) } - 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 resize(&mut self, width: u32, height: u32) { + self.aspect_ratio = width as f32 / height as f32 } pub(crate) fn control(&mut self, delta: Vec3) { self.frame *= Affine3A::from_translation(delta); diff --git a/src/render/instance/material.rs b/src/render/instance/material.rs deleted file mode 100644 index cf994d2..0000000 --- a/src/render/instance/material.rs +++ /dev/null @@ -1,130 +0,0 @@ -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 deleted file mode 100644 index b7384dd..0000000 --- a/src/render/instance/mod.rs +++ /dev/null @@ -1,376 +0,0 @@ -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 deleted file mode 100644 index 0f0ee8b..0000000 --- a/src/render/loader.rs +++ /dev/null @@ -1,302 +0,0 @@ -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 deleted file mode 100644 index 0d392b8..0000000 --- a/src/render/mesh.rs +++ /dev/null @@ -1,51 +0,0 @@ -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 b15cbfa..68977e7 100644 --- a/src/render/mod.rs +++ b/src/render/mod.rs @@ -1,14 +1,10 @@ pub mod eye; -pub mod texture; -pub mod mesh; -pub mod instance; -pub mod loader; use crate::render::eye::Eye; -use crate::world::{Shape, ColliderData, ObjectData, World, AABB}; +use crate::world::{Shape, SimpleColliderData, SimpleLight, SimpleObject, SimpleObjectData}; use bytemuck::{Pod, Zeroable}; use glam::prelude::*; -use gltf::{Semantic}; +use gltf::Semantic; use image::EncodableLayout; use std::cell::RefCell; use std::collections::HashMap; @@ -19,71 +15,874 @@ 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: [TangentVertex; 0] = []; - -pub struct Screen { +const DEFAULT_VERTICES: [SimpleVertex; 0] = []; +#[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, } -pub struct Textures { - list: FreeList, - default: Texture, +#[repr(C)] +#[derive(Pod, Copy, Clone, Zeroable)] +pub struct SimpleLightInstance { + pub location: Vec4, + pub rotation: Vec4, + pub color: Vec4, } -impl Textures { - fn new(device: &Device, queue: &Queue) -> Textures { - let default = Texture::load( - &device, - &queue, - [0, 0, 255, 255], - TextureProperties { - width: 1, - height: 1, - }, +#[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::(), ); - Textures { - list: Default::default(), - default, + 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(), } } } 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, - pub(crate) instances: instance::Instances, + 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, } +#[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 write_instances(&mut self, objects: &mut FreeList) { - self.instances.write_instances(&self.device, &self.queue, &mut self.meshes, objects); + 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 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(&self.queue, width, height); + self.eye.resize(width, height); } - pub fn set_skybox(&mut self, skybox: Texture) { + + + pub fn set_skybox(&mut self, skybox: SimpleTexture) { self.eye.skybox(&self.device, skybox); } pub async fn new(window: &Arc) -> anyhow::Result { @@ -119,7 +918,6 @@ impl Renderer { power_preference: wgpu::PowerPreference::default(), compatible_surface: Some(&surface), force_fallback_adapter: false, - //apply_limit_buckets: false, }) .await?; @@ -153,52 +951,248 @@ impl Renderer { let config = wgpu::SurfaceConfiguration { usage: wgpu::TextureUsages::RENDER_ATTACHMENT, format: surface_format, - //color_space: Default::default(), width, height, - present_mode: wgpu::PresentMode::Fifo, + present_mode: surface_caps.present_modes[0], 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 depth_texture = Texture::depth(&config,&device); + 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(), + ); Ok(Renderer { - depth: depth_texture, + id_count: 0, + material_layout: texture_bind_group_layout, + default_texture, + default_material, + depth_texture: SimpleTexture { + texture: depth_texture, + view: depth_view, + }, instances, + sky_pipeline, + instance_pipeline, surface, config, device, queue, - textures, - meshes: Default::default(), eye, }) } - pub(crate) fn render(&mut self, window: &Arc, objects: &mut FreeList) -> anyhow::Result<()> { - let surface_texture = match self.surface.get_current_texture() { + 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() { wgpu::CurrentSurfaceTexture::Success(surface_texture) => surface_texture, - wgpu::CurrentSurfaceTexture::Suboptimal(_surface_texture) => { - println!("suboptimal"); - self.surface.configure(&self.device, &self.config); - return Ok(()); + wgpu::CurrentSurfaceTexture::Suboptimal(surface_texture) => { + resize_renderer = true; //moved reconfigure to avoid a crash when resizing window + surface_texture } wgpu::CurrentSurfaceTexture::Timeout | wgpu::CurrentSurfaceTexture::Occluded | wgpu::CurrentSurfaceTexture::Validation => { - println!("timeout"); + // Skip this frame return Ok(()); } wgpu::CurrentSurfaceTexture::Outdated => { self.surface.configure(&self.device, &self.config); - println!("outdated"); return Ok(()); } wgpu::CurrentSurfaceTexture::Lost => { @@ -207,19 +1201,17 @@ impl Renderer { anyhow::bail!("Lost device"); } }; + let view = output + .texture + .create_view(&wgpu::TextureViewDescriptor::default()); - let view = surface_texture - .texture - .create_view(&wgpu::TextureViewDescriptor::default()); + let program = self.instances.write_instances(&self.device, &self.queue); let mut encoder = self - .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); + .device + .create_command_encoder(&wgpu::CommandEncoderDescriptor { + label: Some("Render Encoder"), + }); { let mut pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { @@ -239,7 +1231,7 @@ impl Renderer { }, })], depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachment { - view: &self.depth.view, + view: &self.depth_texture.view, depth_ops: Some(wgpu::Operations { load: wgpu::LoadOp::Clear(1.0), store: wgpu::StoreOp::Store, @@ -251,35 +1243,37 @@ impl Renderer { multiview_mask: None, }); - pass.set_pipeline(&self.eye.sky_pipeline); + pass.set_pipeline(&self.instance_pipeline); pass.set_bind_group(0, &self.eye.group, &[]); - pass.draw(0..6, 0..1); + pass.set_vertex_buffer(1, self.instances.instance_buffer.slice(..)); + program.render(&mut pass); - 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 + pass.set_bind_group(1, &self.default_material.group, &[]); + + pass.set_pipeline(&self.sky_pipeline); + pass.draw(0..6, 0..1); } self.queue.submit(Some(encoder.finish())); - window.pre_present_notify(); + self.eye.write(&self.queue); - surface_texture.present(); - //self.queue.present(surface_texture); + output.present(); - // 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 + + 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); /* also in this snippet call the functions to - a: resize window resolution // todo: idk why it's ignoring me - b: resize projection // done: made eye.rs write to eye buffer + a: resize window resolution + b: resize projection 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 deleted file mode 100644 index fa563d0..0000000 --- a/src/render/sky.wgsl +++ /dev/null @@ -1,72 +0,0 @@ -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 deleted file mode 100644 index 131d52f..0000000 --- a/src/render/texture.rs +++ /dev/null @@ -1,115 +0,0 @@ -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 deleted file mode 100644 index 1ef7a2a..0000000 --- a/src/state.rs +++ /dev/null @@ -1,19 +0,0 @@ -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 deleted file mode 100644 index e69de29..0000000 diff --git a/src/world/debug.rs b/src/world/debug.rs deleted file mode 100644 index ce65244..0000000 --- a/src/world/debug.rs +++ /dev/null @@ -1,100 +0,0 @@ -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 a44fad9..3802219 100644 --- a/src/world/mod.rs +++ b/src/world/mod.rs @@ -1,379 +1,228 @@ -pub mod debug; - -use crate::render::instance::ModelData; -use glam::{Affine3, IVec3, Mat4, Quat, Vec3}; +use crate::render::{Renderer, SimpleLightData, SimpleModelData}; +use glam::{DVec3, IVec3, Mat4, UVec3, Vec3, Vec4Swizzles}; use std::cell::RefCell; use std::hash::{BuildHasherDefault, Hash, Hasher}; -use std::path::absolute; +use std::ops::{Div, Mul}; 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 ColliderData { +pub struct SimpleColliderData { + pub transform: Mat4, pub shape: Shape, + pub radius: f32, } -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, - ) +#[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) + } +} + +#[derive(Clone)] +pub struct SimpleObject(pub Rc>); + +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 PartialEq for SimpleObject { + fn eq(&self, other: &Self) -> bool { + Rc::ptr_eq(&self.0, &other.0) + } +} + +impl Eq for SimpleObject {} + +impl Hash for SimpleObject { + fn hash(&self, state: &mut H) { + (self.0.as_ptr() as *const RefCell).hash(state); + } +} + +#[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 }], + } + } + 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); + } } - Shape::Sphere(radius) => { - let radius_offset = Vec3::splat(radius); - AABB( - translation - radius_offset, - translation + radius_offset, - ) + } else { + self.interests.insert(interest); + } + } + 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) } } } } -#[derive(Clone)] -pub struct ObjectData { - pub model: Option, - pub collider: ColliderData, - pub affine: Affine3, - pub asleep: bool, -} - -impl ObjectData { - pub fn set_affine(&mut self, affine: Affine3) { - self.affine = affine; - self.asleep = false; - } -} - -#[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()) - } -} - -#[derive(Clone, Copy, Debug, PartialEq)] -pub struct IAABB(pub(crate) IVec3, pub(crate) IVec3); - -impl IAABB { - pub(crate) fn new(translation: IVec3, size: IVec3) -> IAABB { - IAABB(translation - size, translation + size) - } - pub fn extend_to(&self, point: IVec3) -> IAABB { - IAABB(self.0.min(point),self.1.max(point)) - } - pub fn bounded_by(&self, aabb: IAABB) -> IAABB { - IAABB(self.0.max(aabb.0), self.1.min(aabb.1)) - } - 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 { - pub(crate) matter: OctreeMap, -} - -impl Default for World { - fn default() -> Self { - Self::new() - } + chunk_size: u32, + map: FastHashMap, + pub renderer: Option, + debug_world_map: bool, + debug_world_map_object: Option, } impl World { pub fn new() -> World { World { - matter: OctreeMap::new(), - - } - } - 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 remove_object(&mut self, object: Id) { - - } - 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 new() -> OctreeMap { - OctreeMap { - interests: Default::default(), - nodes: Default::default(), - blocks: Default::default(), + chunk_size: 512, map: FastHashMap::with_hasher(BuildHasherDefault::default()), + renderer: None, + debug_world_map: false, + debug_world_map_object: None, } } -} \ No newline at end of file + 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: SimpleObject) { + self.place(Interest::Object(object.clone())); + if let Some(ref mut renderer) = self.renderer { + renderer.instances.add_object(object) + } + } + 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 + }); + } + } + } + } + } + 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); + } +}