From eb9cef723c1eafdaf257fac33e7a75a5b7bbf6a9 Mon Sep 17 00:00:00 2001 From: Takenoha <43175600+Takenoha@users.noreply.github.com> Date: Mon, 6 Oct 2025 12:04:14 +0900 Subject: [PATCH 1/4] fix: gitignore --- .gitignore | 39 +++++++++++++++++++++++++++++++++++++-- package.json | 5 +++++ pnpm-lock.yaml | 38 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 80 insertions(+), 2 deletions(-) create mode 100644 package.json create mode 100644 pnpm-lock.yaml diff --git a/.gitignore b/.gitignore index ee4c674..588be0e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,38 @@ -# Added by cargo +# Rust /target -*.csv \ No newline at end of file + +# Python +/.venv +__pycache__/ +*.pyc +*.pyo +*.pyd +.pytest_cache/ + +# Node.js +/node_modules +/dist +npm-debug.log* +yarn-error.log* +yarn-debug.log* + +# OS generated files +.DS_Store +.DS_Store? +._* +.Spotlight-V100 +.Trashes +ehthumbs.db +Thumbs.db + +# Editor directories and files +.vscode/ +.idea/ +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +# User added +*.csv diff --git a/package.json b/package.json new file mode 100644 index 0000000..7472aca --- /dev/null +++ b/package.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "jules": "^1.0.0" + } +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 0000000..5b93408 --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,38 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + dependencies: + jules: + specifier: ^1.0.0 + version: 1.0.0 + +packages: + + get-stdin@5.0.1: + resolution: {integrity: sha512-jZV7n6jGE3Gt7fgSTJoz91Ak5MuTLwMwkoYdjxuJ/AmjIsE1UC03y/IWkZCQGEvVNS9qoRNwy5BCqxImv0FVeA==} + engines: {node: '>=0.12.0'} + + jules@1.0.0: + resolution: {integrity: sha512-zTCl9xy54mUArumz9Q4nJl+vjQwtHKWwe5kOV/Mm/L+udn2+d0w0qbANvh/+KqnnI3BzAIWGEBhzQCNsYL+TJg==} + engines: {node: '>8.0.0'} + hasBin: true + + valid-identifier@0.0.1: + resolution: {integrity: sha512-+tLvqAC/bJrWSVqtNWNSx0UG6SYxKpGVCZWUdE0cmSUyEUELtx/23kIAfgiMtoiu8djPbJnh4iT8uTekRnLHNg==} + +snapshots: + + get-stdin@5.0.1: {} + + jules@1.0.0: + dependencies: + get-stdin: 5.0.1 + valid-identifier: 0.0.1 + + valid-identifier@0.0.1: {} From 9407a7d8f30fb0a7affdb37e70ce1f5d147edbc6 Mon Sep 17 00:00:00 2001 From: Takenoha <43175600+Takenoha@users.noreply.github.com> Date: Mon, 6 Oct 2025 15:12:18 +0900 Subject: [PATCH 2/4] =?UTF-8?q?add:=20=E6=8F=8F=E7=94=BB=E3=81=AE=E3=83=AC?= =?UTF-8?q?=E3=82=A4=E3=83=88=E3=83=AC=E8=BF=BD=E5=8A=A0=E4=B8=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cargo.lock | 6526 +++-------------- Cargo.toml | 9 +- crates/bevy_render_cli/Cargo.toml | 15 - crates/bevy_render_cli/src/bevy_render_cli.rs | 8 - crates/bevy_render_cli/src/lib.rs | 3 - crates/bevy_render_config/Cargo.toml | 14 - .../src/bevy_render_config.rs | 1 - crates/bevy_render_config/src/lib.rs | 3 - crates/bevy_render_core/Cargo.toml | 17 - crates/bevy_render_core/src/beby_trait.rs | 5 - .../bevy_render_core/src/bevy_render_core.rs | 128 - crates/bevy_render_core/src/lib.rs | 6 - .../src/render_primitives/mod.rs | 46 - .../render_axis_aligned_box.rs | 1 - .../src/render_primitives/render_csg.rs | 1 - .../render_primitives/render_infinite_cone.rs | 1 - .../render_infinite_cylinder.rs | 1 - .../src/render_primitives/render_lens.rs | 1 - .../src/render_primitives/render_plane.rs | 1 - .../src/render_primitives/render_sphere.rs | 1 - .../src/render_primitives/render_wedge.rs | 1 - crates/raytracing_cli/Cargo.toml | 3 +- crates/raytracing_cli/src/cli.rs | 69 +- crates/raytracing_config/src/model.rs | 1 + .../src/model/camera_config.rs | 31 + .../src/model/material_config.rs | 27 +- .../src/model/scene_config.rs | 54 +- .../src/model/simulation_config.rs | 4 +- .../src/model/simulation_settings_config.rs | 28 +- crates/raytracing_core/src/primitives/aabb.rs | 50 + .../src/primitives/axis_aligned_box.rs | 10 +- crates/raytracing_core/src/primitives/bvh.rs | 70 + crates/raytracing_core/src/primitives/csg.rs | 33 +- .../src/primitives/hittable_list.rs | 69 + .../src/primitives/infinite_cone.rs | 16 +- .../src/primitives/infinite_cylinder.rs | 16 +- crates/raytracing_core/src/primitives/lens.rs | 15 +- crates/raytracing_core/src/primitives/mod.rs | 15 +- .../raytracing_core/src/primitives/plane.rs | 10 +- .../raytracing_core/src/primitives/sphere.rs | 13 +- .../src/primitives/transform.rs | 32 +- .../raytracing_core/src/primitives/wedge.rs | 12 +- crates/raytracing_core/src/scene.rs | 37 +- crates/raytracing_renderer/Cargo.toml | 12 + crates/raytracing_renderer/src/lib.rs | 235 + output.png | Bin 0 -> 158803 bytes paths.obj | 21 + python_files/plot_3d.py | 44 - simulation.toml | 26 +- src/bin/render.rs | 23 + 50 files changed, 1912 insertions(+), 5853 deletions(-) delete mode 100644 crates/bevy_render_cli/Cargo.toml delete mode 100644 crates/bevy_render_cli/src/bevy_render_cli.rs delete mode 100644 crates/bevy_render_cli/src/lib.rs delete mode 100644 crates/bevy_render_config/Cargo.toml delete mode 100644 crates/bevy_render_config/src/bevy_render_config.rs delete mode 100644 crates/bevy_render_config/src/lib.rs delete mode 100644 crates/bevy_render_core/Cargo.toml delete mode 100644 crates/bevy_render_core/src/beby_trait.rs delete mode 100644 crates/bevy_render_core/src/bevy_render_core.rs delete mode 100644 crates/bevy_render_core/src/lib.rs delete mode 100644 crates/bevy_render_core/src/render_primitives/mod.rs delete mode 100644 crates/bevy_render_core/src/render_primitives/render_axis_aligned_box.rs delete mode 100644 crates/bevy_render_core/src/render_primitives/render_csg.rs delete mode 100644 crates/bevy_render_core/src/render_primitives/render_infinite_cone.rs delete mode 100644 crates/bevy_render_core/src/render_primitives/render_infinite_cylinder.rs delete mode 100644 crates/bevy_render_core/src/render_primitives/render_lens.rs delete mode 100644 crates/bevy_render_core/src/render_primitives/render_plane.rs delete mode 100644 crates/bevy_render_core/src/render_primitives/render_sphere.rs delete mode 100644 crates/bevy_render_core/src/render_primitives/render_wedge.rs create mode 100644 crates/raytracing_config/src/model/camera_config.rs create mode 100644 crates/raytracing_core/src/primitives/aabb.rs create mode 100644 crates/raytracing_core/src/primitives/bvh.rs create mode 100644 crates/raytracing_core/src/primitives/hittable_list.rs create mode 100644 crates/raytracing_renderer/Cargo.toml create mode 100644 crates/raytracing_renderer/src/lib.rs create mode 100644 output.png create mode 100644 paths.obj delete mode 100644 python_files/plot_3d.py create mode 100644 src/bin/render.rs diff --git a/Cargo.lock b/Cargo.lock index 1612cf8..568da03 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,80 +2,12 @@ # It is not intended for manual editing. version = 4 -[[package]] -name = "accesskit" -version = "0.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "becf0eb5215b6ecb0a739c31c21bd83c4f326524c9b46b7e882d77559b60a529" - -[[package]] -name = "accesskit_consumer" -version = "0.27.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0bf66a7bf0b7ea4fd7742d50b64782a88f99217cf246b3f93b4162528dde520" -dependencies = [ - "accesskit", - "hashbrown", - "immutable-chunkmap", -] - -[[package]] -name = "accesskit_macos" -version = "0.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09e230718177753b4e4ad9e1d9f6cfc2f4921212d4c1c480b253f526babb258d" -dependencies = [ - "accesskit", - "accesskit_consumer", - "hashbrown", - "objc2", - "objc2-app-kit", - "objc2-foundation", -] - -[[package]] -name = "accesskit_windows" -version = "0.25.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65178f3df98a51e4238e584fcb255cb1a4f9111820848eeddd37663be40a625f" -dependencies = [ - "accesskit", - "accesskit_consumer", - "hashbrown", - "paste", - "static_assertions", - "windows 0.58.0", - "windows-core 0.58.0", -] - -[[package]] -name = "accesskit_winit" -version = "0.25.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34d941bb8c414caba6e206de669c7dc0dbeb305640ea890772ee422a40e6b89f" -dependencies = [ - "accesskit", - "accesskit_macos", - "accesskit_windows", - "raw-window-handle", - "winit", -] - [[package]] name = "adler2" version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" -[[package]] -name = "aho-corasick" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" -dependencies = [ - "memchr", -] - [[package]] name = "aligned-vec" version = "0.6.4" @@ -91,67 +23,12 @@ version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" -[[package]] -name = "alsa" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed7572b7ba83a31e20d1b48970ee402d2e3e0537dcfe0a3ff4d6eb7508617d43" -dependencies = [ - "alsa-sys", - "bitflags 2.9.1", - "cfg-if", - "libc", -] - -[[package]] -name = "alsa-sys" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db8fee663d06c4e303404ef5f40488a53e062f89ba8bfed81f42325aafad1527" -dependencies = [ - "libc", - "pkg-config", -] - -[[package]] -name = "android-activity" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef6978589202a00cd7e118380c448a08b6ed394c3a8df3a430d0898e3a42d046" -dependencies = [ - "android-properties", - "bitflags 2.9.1", - "cc", - "cesu8", - "jni", - "jni-sys", - "libc", - "log", - "ndk 0.9.0", - "ndk-context", - "ndk-sys 0.6.0+11769913", - "num_enum", - "thiserror 1.0.69", -] - -[[package]] -name = "android-properties" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc7eb209b1518d6bb87b283c20095f5228ecda460da70b44f0802523dea6da04" - [[package]] name = "android-tzdata" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" -[[package]] -name = "android_log-sys" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84521a3cf562bc62942e294181d9eef17eb38ceb8c68677bc49f144e4c3d4f8d" - [[package]] name = "android_system_properties" version = "0.1.5" @@ -193,12 +70,6 @@ dependencies = [ "syn", ] -[[package]] -name = "arrayref" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" - [[package]] name = "arrayvec" version = "0.7.6" @@ -206,5608 +77,1447 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" [[package]] -name = "as-raw-xcb-connection" -version = "1.0.1" +name = "autocfg" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "175571dd1d178ced59193a6fc02dde1b972eb0bc56c892cde9beeceac5bf0f6b" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] -name = "ash" -version = "0.38.0+1.3.281" +name = "av1-grain" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bb44936d800fea8f016d7f2311c6a4f97aebd5dc86f09906139ec848cf3a46f" +checksum = "4f3efb2ca85bc610acfa917b5aaa36f3fcbebed5b3182d7f877b02531c4b80c8" dependencies = [ - "libloading", + "anyhow", + "arrayvec", + "log", + "nom", + "num-rational", + "v_frame", ] [[package]] -name = "assert_type_match" -version = "0.1.1" +name = "avif-serialize" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f548ad2c4031f2902e3edc1f29c29e835829437de49562d8eb5dc5584d3a1043" +checksum = "2ea8ef51aced2b9191c08197f55450d830876d9933f8f48a429b354f1d496b42" dependencies = [ - "proc-macro2", - "quote", - "syn", + "arrayvec", ] [[package]] -name = "async-broadcast" -version = "0.7.2" +name = "base64" +version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "435a87a52755b8f27fcf321ac4f04b2802e337c8c4872923137471ec39c37532" -dependencies = [ - "event-listener", - "event-listener-strategy", - "futures-core", - "pin-project-lite", -] +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] -name = "async-channel" -version = "2.5.0" +name = "bit-vec" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "924ed96dd52d1b75e9c1a3e6275715fd320f5f9439fb5a4a11fa51f4221158d2" -dependencies = [ - "concurrent-queue", - "event-listener-strategy", - "futures-core", - "pin-project-lite", -] +checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" [[package]] -name = "async-executor" -version = "1.13.2" +name = "bit_field" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb812ffb58524bdd10860d7d974e2f01cc0950c2438a74ee5ec2e2280c6c4ffa" -dependencies = [ - "async-task", - "concurrent-queue", - "fastrand", - "futures-lite", - "pin-project-lite", - "slab", -] +checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61" [[package]] -name = "async-fs" -version = "2.1.3" +name = "bitflags" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09f7e37c0ed80b2a977691c47dae8625cfb21e205827106c64f7c588766b2e50" -dependencies = [ - "async-lock", - "blocking", - "futures-lite", -] +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] -name = "async-lock" -version = "3.4.0" +name = "bitflags" +version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18" -dependencies = [ - "event-listener", - "event-listener-strategy", - "pin-project-lite", -] +checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" [[package]] -name = "async-task" -version = "4.7.1" +name = "bitstream-io" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" -dependencies = [ - "portable-atomic", -] +checksum = "6099cdc01846bc367c4e7dd630dc5966dccf36b652fae7a74e17b640411a91b2" [[package]] -name = "atomic-waker" -version = "1.1.2" +name = "built" +version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" -dependencies = [ - "portable-atomic", -] +checksum = "56ed6191a7e78c36abdb16ab65341eefd73d64d303fffccdbb00d51e4205967b" [[package]] -name = "atomicow" -version = "1.1.0" +name = "bumpalo" +version = "3.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f52e8890bb9844440d0c412fa74b67fd2f14e85248b6e00708059b6da9e5f8bf" -dependencies = [ - "portable-atomic", - "portable-atomic-util", -] +checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" [[package]] -name = "autocfg" +name = "bytemuck" +version = "1.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c76a5792e44e4abe34d3abf15636779261d45a7450612059293d1d2cfc63422" + +[[package]] +name = "byteorder" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] -name = "av1-grain" -version = "0.2.4" +name = "byteorder-lite" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f3efb2ca85bc610acfa917b5aaa36f3fcbebed5b3182d7f877b02531c4b80c8" -dependencies = [ - "anyhow", - "arrayvec", - "log", - "nom", - "num-rational", - "v_frame", -] +checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" [[package]] -name = "avif-serialize" -version = "0.8.5" +name = "cc" +version = "1.2.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ea8ef51aced2b9191c08197f55450d830876d9933f8f48a429b354f1d496b42" +checksum = "c3a42d84bb6b69d3a8b3eaacf0d88f179e1929695e1ad012b6cf64d9caaa5fd2" dependencies = [ - "arrayvec", + "jobserver", + "libc", + "shlex", ] [[package]] -name = "base64" -version = "0.21.7" +name = "cfg-expr" +version = "0.15.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" +checksum = "d067ad48b8650848b989a59a86c6c36a995d02d2bf778d45c3c5d57bc2718f02" +dependencies = [ + "smallvec", + "target-lexicon", +] [[package]] -name = "base64" -version = "0.22.1" +name = "cfg-if" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" +checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" [[package]] -name = "bevy" -version = "0.16.1" +name = "chrono" +version = "0.4.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b8369c16b7c017437021341521f8b4a0d98e1c70113fb358c3258ae7d661d79" +checksum = "c469d952047f47f91b68d1cba3f10d63c11d73e4636f24f08daf0278abf01c4d" dependencies = [ - "bevy_internal", + "android-tzdata", + "iana-time-zone", + "js-sys", + "num-traits 0.2.19", + "serde", + "wasm-bindgen", + "windows-link", ] [[package]] -name = "bevy_a11y" -version = "0.16.1" +name = "chull" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed3561712cf49074d89e9989bfc2e6c6add5d33288f689db9a0c333300d2d004" +checksum = "977db54e5eec96279bea3032dcf41d3844e90d62e5cfeded48f8d53b1a755d7a" dependencies = [ - "accesskit", - "bevy_app", - "bevy_derive", - "bevy_ecs", - "bevy_reflect", + "num-bigint 0.3.3", + "num-traits 0.2.19", ] [[package]] -name = "bevy_animation" -version = "0.16.1" +name = "color_quant" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49796627726d0b9a722ad9a0127719e7c1868f474d6575ec0f411e8299c4d7bb" -dependencies = [ - "bevy_app", - "bevy_asset", - "bevy_color", - "bevy_derive", - "bevy_ecs", - "bevy_log", - "bevy_math", - "bevy_mesh", - "bevy_platform", - "bevy_reflect", - "bevy_render", - "bevy_time", - "bevy_transform", - "bevy_utils", - "blake3", - "derive_more", - "downcast-rs", - "either", - "petgraph", - "ron", - "serde", - "smallvec", - "thiserror 2.0.12", - "thread_local", - "tracing", - "uuid", -] +checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" [[package]] -name = "bevy_app" -version = "0.16.1" +name = "contour_tracing" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4491cc4c718ae76b4c6883df58b94cc88b32dcd894ea8d5b603c7c7da72ca967" -dependencies = [ - "bevy_derive", - "bevy_ecs", - "bevy_platform", - "bevy_reflect", - "bevy_tasks", - "bevy_utils", - "cfg-if", - "console_error_panic_hook", - "ctrlc", - "downcast-rs", - "log", - "thiserror 2.0.12", - "variadics_please", - "wasm-bindgen", - "web-sys", -] +checksum = "c9efef72b4f4049ebc4b690ae8ac98cfb7d3cb50407592745ad2c83106625936" [[package]] -name = "bevy_asset" -version = "0.16.1" +name = "core-foundation-sys" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f56111d9b88d8649f331a667d9d72163fb26bd09518ca16476d238653823db1e" -dependencies = [ - "async-broadcast", - "async-fs", - "async-lock", - "atomicow", - "bevy_app", - "bevy_asset_macros", - "bevy_ecs", - "bevy_platform", - "bevy_reflect", - "bevy_tasks", - "bevy_utils", - "bevy_window", - "bitflags 2.9.1", - "blake3", - "crossbeam-channel", - "derive_more", - "disqualified", - "downcast-rs", - "either", - "futures-io", - "futures-lite", - "js-sys", - "parking_lot", - "ron", - "serde", - "stackfuture", - "thiserror 2.0.12", - "tracing", - "uuid", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", -] +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] -name = "bevy_asset_macros" -version = "0.16.1" +name = "core2" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4cca3e67c0ec760d8889d42293d987ce5da92eaf9c592bf5d503728a63b276d" +checksum = "b49ba7ef1ad6107f8824dbe97de947cbaac53c44e7f9756a1fba0d37c1eec505" dependencies = [ - "bevy_macro_utils", - "proc-macro2", - "quote", - "syn", + "memchr", ] [[package]] -name = "bevy_audio" -version = "0.16.1" +name = "crc32fast" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2b4f6f2a5c6c0e7c6825e791d2a061c76c2d6784f114c8f24382163fabbfaaa" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" dependencies = [ - "bevy_app", - "bevy_asset", - "bevy_derive", - "bevy_ecs", - "bevy_math", - "bevy_reflect", - "bevy_transform", - "cpal", - "rodio", - "tracing", + "cfg-if", ] [[package]] -name = "bevy_color" -version = "0.16.2" +name = "crossbeam" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c101cbe1e26b8d701eb77263b14346e2e0cbbd2a6e254b9b1aead814e5ca8d3" +checksum = "1137cd7e7fc0fb5d3c5a8678be38ec56e819125d8d7907411fe24ccb943faca8" dependencies = [ - "bevy_math", - "bevy_reflect", - "bytemuck", - "derive_more", - "encase", - "serde", - "thiserror 2.0.12", - "wgpu-types", -] + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-epoch", + "crossbeam-queue", + "crossbeam-utils", +] [[package]] -name = "bevy_core_pipeline" -version = "0.16.1" +name = "crossbeam-channel" +version = "0.5.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59ed46363cad80dc00f08254c3015232bd6f640738403961c6d63e7ecfc61625" +checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" dependencies = [ - "bevy_app", - "bevy_asset", - "bevy_color", - "bevy_derive", - "bevy_diagnostic", - "bevy_ecs", - "bevy_image", - "bevy_math", - "bevy_platform", - "bevy_reflect", - "bevy_render", - "bevy_transform", - "bevy_utils", - "bevy_window", - "bitflags 2.9.1", - "bytemuck", - "nonmax", - "radsort", - "serde", - "smallvec", - "thiserror 2.0.12", - "tracing", + "crossbeam-utils", ] [[package]] -name = "bevy_derive" -version = "0.16.1" +name = "crossbeam-deque" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b837bf6c51806b10ebfa9edf1844ad80a3a0760d6c5fac4e90761df91a8901a" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" dependencies = [ - "bevy_macro_utils", - "quote", - "syn", + "crossbeam-epoch", + "crossbeam-utils", ] [[package]] -name = "bevy_diagnostic" -version = "0.16.1" +name = "crossbeam-epoch" +version = "0.9.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48797366f312a8f31e237d08ce3ee70162591282d2bfe7c5ad8be196fb263e55" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" dependencies = [ - "bevy_app", - "bevy_ecs", - "bevy_platform", - "bevy_tasks", - "bevy_time", - "bevy_utils", - "const-fnv1a-hash", - "log", - "serde", - "sysinfo", + "crossbeam-utils", ] [[package]] -name = "bevy_ecs" -version = "0.16.1" +name = "crossbeam-queue" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c2bf6521aae57a0ec3487c4bfb59e36c4a378e834b626a4bea6a885af2fdfe7" +checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115" dependencies = [ - "arrayvec", - "bevy_ecs_macros", - "bevy_platform", - "bevy_ptr", - "bevy_reflect", - "bevy_tasks", - "bevy_utils", - "bitflags 2.9.1", - "bumpalo", - "concurrent-queue", - "derive_more", - "disqualified", - "fixedbitset", - "indexmap", - "log", - "nonmax", - "serde", - "smallvec", - "thiserror 2.0.12", - "variadics_please", + "crossbeam-utils", ] [[package]] -name = "bevy_ecs_macros" -version = "0.16.1" +name = "crossbeam-utils" +version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38748d6f3339175c582d751f410fb60a93baf2286c3deb7efebb0878dce7f413" -dependencies = [ - "bevy_macro_utils", - "proc-macro2", - "quote", - "syn", -] +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] -name = "bevy_encase_derive" -version = "0.16.1" +name = "crunchy" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" + +[[package]] +name = "csgrs" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8148f4edee470a2ea5cad010184c492a4c94c36d7a7158ea28e134ea87f274ab" +checksum = "b004da954c4987881c668e0051f6c69a23d035b4b406eee539772db4d4944025" dependencies = [ - "bevy_macro_utils", - "encase_derive_impl", + "chull", + "contour_tracing", + "core2", + "doc-image-embed", + "dxf", + "either", + "fast-surface-nets", + "geo", + "geo-buf", + "hashbrown", + "hershey", + "image", + "nalgebra", + "nom", + "parry3d-f64", + "rapier3d-f64", + "robust", + "stl_io", + "svg", + "thiserror 2.0.12", + "ttf-parser", + "ttf-parser-utils", ] [[package]] -name = "bevy_flycam" -version = "0.16.1" +name = "csv" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e86d62cba553c444f64b947b8ea76803d6c767dc4c23598a812974defb4265b3" +checksum = "acdc4883a9c96732e4733212c01447ebd805833b7275a73ca3ee080fd77afdaf" dependencies = [ - "bevy", + "csv-core", + "itoa", + "ryu", + "serde", ] [[package]] -name = "bevy_gilrs" -version = "0.16.1" +name = "csv-core" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97efef87c631949e67d06bb5d7dfd2a5f936b3b379afb6b1485b08edbb219b87" +checksum = "7d02f3b0da4c6504f86e9cd789d8dbafab48c2321be74e9987593de5a894d93d" dependencies = [ - "bevy_app", - "bevy_ecs", - "bevy_input", - "bevy_platform", - "bevy_time", - "bevy_utils", - "gilrs", - "thiserror 2.0.12", - "tracing", -] - -[[package]] -name = "bevy_gizmos" -version = "0.16.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7823154a9682128c261d8bddb3a4d7192a188490075c527af04520c2f0f8aad6" -dependencies = [ - "bevy_app", - "bevy_asset", - "bevy_color", - "bevy_core_pipeline", - "bevy_ecs", - "bevy_gizmos_macros", - "bevy_image", - "bevy_math", - "bevy_pbr", - "bevy_reflect", - "bevy_render", - "bevy_sprite", - "bevy_time", - "bevy_transform", - "bevy_utils", - "bytemuck", - "tracing", + "memchr", ] [[package]] -name = "bevy_gizmos_macros" -version = "0.16.1" +name = "doc-image-embed" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f378f3b513218ddc78254bbe76536d9de59c1429ebd0c14f5d8f2a25812131ad" +checksum = "4b1c7e5bbb92b417588a5e733e095416c27c06eedc051065cc955a0a8c8389d9" dependencies = [ - "bevy_macro_utils", + "base64", "proc-macro2", "quote", "syn", ] [[package]] -name = "bevy_gltf" -version = "0.16.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10a080237c0b8842ccc15a06d3379302c68580eeea4497b1c7387e470eda1f07" -dependencies = [ - "base64 0.22.1", - "bevy_animation", - "bevy_app", - "bevy_asset", - "bevy_color", - "bevy_core_pipeline", - "bevy_ecs", - "bevy_image", - "bevy_math", - "bevy_mesh", - "bevy_pbr", - "bevy_platform", - "bevy_reflect", - "bevy_render", - "bevy_scene", - "bevy_tasks", - "bevy_transform", - "bevy_utils", - "fixedbitset", - "gltf", - "itertools 0.14.0", - "percent-encoding", - "serde", - "serde_json", - "smallvec", - "thiserror 2.0.12", - "tracing", -] +name = "downcast-rs" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea8a8b81cacc08888170eef4d13b775126db426d0b348bee9d18c2c1eaf123cf" [[package]] -name = "bevy_image" -version = "0.16.1" +name = "dxf" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65e6e900cfecadbc3149953169e36b9e26f922ed8b002d62339d8a9dc6129328" +checksum = "db88ab4334d9288e6658b8bb8e7bc9167ae48878b5f92818e01969a5041d294d" dependencies = [ - "bevy_app", - "bevy_asset", - "bevy_color", - "bevy_math", - "bevy_platform", - "bevy_reflect", - "bevy_utils", - "bitflags 2.9.1", - "bytemuck", - "futures-lite", - "guillotiere", - "half", + "byteorder", + "chrono", + "encoding_rs", + "enum_primitive", "image", - "ktx2", - "rectangle-pack", - "ruzstd", - "serde", - "thiserror 2.0.12", - "tracing", - "wgpu-types", + "itertools 0.13.0", + "num", + "uuid", + "xmltree", ] [[package]] -name = "bevy_input" -version = "0.16.1" +name = "earcutr" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18d6b6516433f6f7d680f648d04eb1866bb3927a1782d52f74831b62042f3cd1" +checksum = "79127ed59a85d7687c409e9978547cffb7dc79675355ed22da6b66fd5f6ead01" dependencies = [ - "bevy_app", - "bevy_ecs", - "bevy_math", - "bevy_platform", - "bevy_reflect", - "bevy_utils", - "derive_more", - "log", - "smol_str", - "thiserror 2.0.12", + "itertools 0.11.0", + "num-traits 0.2.19", ] [[package]] -name = "bevy_input_focus" -version = "0.16.1" +name = "either" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" + +[[package]] +name = "ena" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e2d079fda74d1416e0a57dac29ea2b79ff77f420cd6b87f833d3aa29a46bc4d" +checksum = "3d248bdd43ce613d87415282f69b9bb99d947d290b10962dd6c56233312c2ad5" dependencies = [ - "bevy_app", - "bevy_ecs", - "bevy_input", - "bevy_math", - "bevy_reflect", - "bevy_window", "log", - "thiserror 2.0.12", ] [[package]] -name = "bevy_internal" -version = "0.16.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "857da8785678fde537d02944cd20dec9cafb7d4c447efe15f898dc60e733cacd" -dependencies = [ - "bevy_a11y", - "bevy_animation", - "bevy_app", - "bevy_asset", - "bevy_audio", - "bevy_color", - "bevy_core_pipeline", - "bevy_derive", - "bevy_diagnostic", - "bevy_ecs", - "bevy_gilrs", - "bevy_gizmos", - "bevy_gltf", - "bevy_image", - "bevy_input", - "bevy_input_focus", - "bevy_log", - "bevy_math", - "bevy_pbr", - "bevy_picking", - "bevy_platform", - "bevy_ptr", - "bevy_reflect", - "bevy_render", - "bevy_scene", - "bevy_sprite", - "bevy_state", - "bevy_tasks", - "bevy_text", - "bevy_time", - "bevy_transform", - "bevy_ui", - "bevy_utils", - "bevy_window", - "bevy_winit", -] - -[[package]] -name = "bevy_log" -version = "0.16.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7a61ee8aef17a974f5ca481dcedf0c2bd52670e231d4c4bc9ddef58328865f9" -dependencies = [ - "android_log-sys", - "bevy_app", - "bevy_ecs", - "bevy_utils", - "tracing", - "tracing-log", - "tracing-oslog", - "tracing-subscriber", - "tracing-wasm", -] - -[[package]] -name = "bevy_macro_utils" -version = "0.16.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "052eeebcb8e7e072beea5031b227d9a290f8a7fbbb947573ab6ec81df0fb94be" -dependencies = [ - "parking_lot", - "proc-macro2", - "quote", - "syn", - "toml_edit", +name = "encoding_rs" +version = "0.8.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" +dependencies = [ + "cfg-if", ] [[package]] -name = "bevy_math" -version = "0.16.1" +name = "enum_primitive" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68553e0090fe9c3ba066c65629f636bd58e4ebd9444fdba097b91af6cd3e243f" +checksum = "be4551092f4d519593039259a9ed8daedf0da12e5109c5280338073eaeb81180" dependencies = [ - "approx", - "bevy_reflect", - "derive_more", - "glam", - "itertools 0.14.0", - "libm", - "rand 0.8.5", - "rand_distr", - "serde", - "smallvec", - "thiserror 2.0.12", - "variadics_please", + "num-traits 0.1.43", ] [[package]] -name = "bevy_mesh" -version = "0.16.1" +name = "equator" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b10399c7027001edbc0406d7d0198596b1f07206c1aae715274106ba5bdcac40" +checksum = "4711b213838dfee0117e3be6ac926007d7f433d7bbe33595975d4190cb07e6fc" dependencies = [ - "bevy_asset", - "bevy_derive", - "bevy_ecs", - "bevy_image", - "bevy_math", - "bevy_mikktspace", - "bevy_platform", - "bevy_reflect", - "bevy_transform", - "bevy_utils", - "bitflags 2.9.1", - "bytemuck", - "hexasphere", - "serde", - "thiserror 2.0.12", - "tracing", - "wgpu-types", + "equator-macro", ] [[package]] -name = "bevy_mikktspace" -version = "0.16.1" +name = "equator-macro" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bb60c753b968a2de0fd279b76a3d19517695e771edb4c23575c7f92156315de" +checksum = "44f23cf4b44bfce11a86ace86f8a73ffdec849c9fd00a386a53d278bd9e81fb3" dependencies = [ - "glam", + "proc-macro2", + "quote", + "syn", ] [[package]] -name = "bevy_panorbit_camera" -version = "0.27.1" +name = "equivalent" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66273755984c3ef10a3e1ab47f5a06ea560bb2e8d56ca4c4a6fb34d1300602c0" -dependencies = [ - "bevy", -] +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] -name = "bevy_pbr" -version = "0.16.1" +name = "exr" +version = "1.73.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5e0b4eb871f364a0d217f70f6c41d7fdc6f9f931fa1abbf222180c03d0ae410" +checksum = "f83197f59927b46c04a183a619b7c29df34e63e63c7869320862268c0ef687e0" dependencies = [ - "bevy_app", - "bevy_asset", - "bevy_color", - "bevy_core_pipeline", - "bevy_derive", - "bevy_diagnostic", - "bevy_ecs", - "bevy_image", - "bevy_math", - "bevy_platform", - "bevy_reflect", - "bevy_render", - "bevy_transform", - "bevy_utils", - "bevy_window", - "bitflags 2.9.1", - "bytemuck", - "derive_more", - "fixedbitset", - "nonmax", - "offset-allocator", - "radsort", + "bit_field", + "half", + "lebe", + "miniz_oxide", + "rayon-core", "smallvec", - "static_assertions", - "thiserror 2.0.12", - "tracing", + "zune-inflate", ] [[package]] -name = "bevy_picking" -version = "0.16.1" +name = "fast-surface-nets" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ed04757938655ed8094ea1efb533f99063a8b22abffc22010c694d291522850" +checksum = "2aef9e8d9e33f51d8120a2e997a819f18239ad7c2735e353ade79208a9a1c442" dependencies = [ - "bevy_app", - "bevy_asset", - "bevy_derive", - "bevy_ecs", - "bevy_input", - "bevy_math", - "bevy_mesh", - "bevy_platform", - "bevy_reflect", - "bevy_render", - "bevy_time", - "bevy_transform", - "bevy_utils", - "bevy_window", - "crossbeam-channel", - "tracing", - "uuid", + "glam", + "ndshape", ] [[package]] -name = "bevy_platform" -version = "0.16.1" +name = "fdeflate" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7573dc824a1b08b4c93fdbe421c53e1e8188e9ca1dd74a414455fe571facb47" +checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c" dependencies = [ - "cfg-if", - "critical-section", - "foldhash", - "getrandom 0.2.16", - "hashbrown", - "portable-atomic", - "portable-atomic-util", - "serde", - "spin", - "web-time", + "simd-adler32", ] [[package]] -name = "bevy_ptr" -version = "0.16.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df7370d0e46b60e071917711d0860721f5347bc958bf325975ae6913a5dfcf01" - -[[package]] -name = "bevy_reflect" -version = "0.16.1" +name = "flate2" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daeb91a63a1a4df00aa58da8cc4ddbd4b9f16ab8bb647c5553eb156ce36fa8c2" +checksum = "4a3d7db9596fecd151c5f638c0ee5d5bd487b6e0ea232e5dc96d5250f6f94b1d" dependencies = [ - "assert_type_match", - "bevy_platform", - "bevy_ptr", - "bevy_reflect_derive", - "bevy_utils", - "derive_more", - "disqualified", - "downcast-rs", - "erased-serde", - "foldhash", - "glam", - "petgraph", - "serde", - "smallvec", - "smol_str", - "thiserror 2.0.12", - "uuid", - "variadics_please", - "wgpu-types", + "crc32fast", + "miniz_oxide", ] [[package]] -name = "bevy_reflect_derive" -version = "0.16.1" +name = "float-cmp" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40ddadc55fe16b45faaa54ab2f9cb00548013c74812e8b018aa172387103cce6" +checksum = "98de4bbd547a563b716d8dfa9aad1cb19bfab00f4fa09a6a4ed21dbcf44ce9c4" dependencies = [ - "bevy_macro_utils", - "proc-macro2", - "quote", - "syn", - "uuid", + "num-traits 0.2.19", ] [[package]] -name = "bevy_render" -version = "0.16.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef91fed1f09405769214b99ebe4390d69c1af5cdd27967deae9135c550eb1667" -dependencies = [ - "async-channel", - "bevy_app", - "bevy_asset", - "bevy_color", - "bevy_derive", - "bevy_diagnostic", - "bevy_ecs", - "bevy_encase_derive", - "bevy_image", - "bevy_math", - "bevy_mesh", - "bevy_platform", - "bevy_reflect", - "bevy_render_macros", - "bevy_tasks", - "bevy_time", - "bevy_transform", - "bevy_utils", - "bevy_window", - "bitflags 2.9.1", - "bytemuck", - "codespan-reporting", - "derive_more", - "downcast-rs", - "encase", - "fixedbitset", - "futures-lite", - "image", - "indexmap", - "js-sys", - "ktx2", - "naga", - "naga_oil", - "nonmax", - "offset-allocator", - "send_wrapper", - "serde", - "smallvec", - "thiserror 2.0.12", - "tracing", - "variadics_please", - "wasm-bindgen", - "web-sys", - "wgpu", -] +name = "float_next_after" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8bf7cc16383c4b8d58b9905a8509f02926ce3058053c056376248d958c9df1e8" [[package]] -name = "bevy_render_cli" -version = "0.1.0" -dependencies = [ - "bevy", - "bevy_render_core", - "csv", - "glam", - "rand 0.8.5", - "raytracing_core", - "serde", - "toml", -] +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" [[package]] -name = "bevy_render_config" -version = "0.1.0" +name = "geo" +version = "0.29.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34f0e6e028c581e82e6822a68869514e94c25e7f8ea669a2d8595bdf7461ccc5" dependencies = [ - "bevy", - "csv", - "glam", - "rand 0.8.5", - "raytracing_core", - "serde", - "toml", + "earcutr", + "float_next_after", + "geo-types", + "geographiclib-rs", + "i_overlay", + "log", + "num-traits 0.2.19", + "robust", + "rstar", + "spade", ] [[package]] -name = "bevy_render_core" +name = "geo-buf" version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3259dd509ae98be7ce49236ec9be30c7d8a0ce84eada28dbefb68bc839b29e66" dependencies = [ - "bevy", - "bevy_flycam", - "bevy_panorbit_camera", - "csgrs", - "csv", - "glam", - "rand 0.9.2", - "raytracing_core", - "serde", - "toml", + "geo", + "geo-types", ] [[package]] -name = "bevy_render_macros" -version = "0.16.1" +name = "geo-types" +version = "0.7.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abd42cf6c875bcf38da859f8e731e119a6aff190d41dd0a1b6000ad57cf2ed3d" +checksum = "75a4dcd69d35b2c87a7c83bce9af69fd65c9d68d3833a0ded568983928f3fc99" dependencies = [ - "bevy_macro_utils", - "proc-macro2", - "quote", - "syn", + "approx", + "num-traits 0.2.19", + "rayon", + "rstar", + "serde", ] [[package]] -name = "bevy_scene" -version = "0.16.1" +name = "geographiclib-rs" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c52ca165200995fe8afd2a1a6c03e4ffee49198a1d4653d32240ea7f217d4ab" +checksum = "f611040a2bb37eaa29a78a128d1e92a378a03e0b6e66ae27398d42b1ba9a7841" dependencies = [ - "bevy_app", - "bevy_asset", - "bevy_derive", - "bevy_ecs", - "bevy_platform", - "bevy_reflect", - "bevy_render", - "bevy_transform", - "bevy_utils", - "derive_more", - "serde", - "thiserror 2.0.12", - "uuid", + "libm", ] [[package]] -name = "bevy_sprite" -version = "0.16.1" +name = "getrandom" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ccae7bab2cb956fb0434004c359e432a3a1a074a6ef4eb471f1fb099f0b620b" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" dependencies = [ - "bevy_app", - "bevy_asset", - "bevy_color", - "bevy_core_pipeline", - "bevy_derive", - "bevy_ecs", - "bevy_image", - "bevy_math", - "bevy_picking", - "bevy_platform", - "bevy_reflect", - "bevy_render", - "bevy_transform", - "bevy_utils", - "bevy_window", - "bitflags 2.9.1", - "bytemuck", - "derive_more", - "fixedbitset", - "nonmax", - "radsort", - "tracing", + "cfg-if", + "libc", + "wasi 0.11.1+wasi-snapshot-preview1", ] [[package]] -name = "bevy_state" -version = "0.16.1" +name = "getrandom" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "155d3cd97b900539008cdcaa702f88b724d94b08977b8e591a32536ce66faa8c" +checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" dependencies = [ - "bevy_app", - "bevy_ecs", - "bevy_platform", - "bevy_reflect", - "bevy_state_macros", - "bevy_utils", - "log", - "variadics_please", + "cfg-if", + "libc", + "r-efi", + "wasi 0.14.2+wasi-0.2.4", ] [[package]] -name = "bevy_state_macros" -version = "0.16.1" +name = "gif" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2481c1304fd2a1851a0d4cb63a1ce6421ae40f3f0117cbc9882963ee4c9bb609" +checksum = "4ae047235e33e2829703574b54fdec96bfbad892062d97fed2f76022287de61b" dependencies = [ - "bevy_macro_utils", - "proc-macro2", - "quote", - "syn", + "color_quant", + "weezl", ] [[package]] -name = "bevy_tasks" -version = "0.16.1" +name = "glam" +version = "0.29.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b674242641cab680688fc3b850243b351c1af49d4f3417a576debd6cca8dcf5" +checksum = "8babf46d4c1c9d92deac9f7be466f76dfc4482b6452fc5024b5e8daf6ffeb3ee" dependencies = [ - "async-channel", - "async-executor", - "async-task", - "atomic-waker", - "bevy_platform", - "cfg-if", - "concurrent-queue", - "crossbeam-queue", - "derive_more", - "futures-channel", - "futures-lite", - "heapless", - "pin-project", - "wasm-bindgen-futures", -] - -[[package]] -name = "bevy_text" -version = "0.16.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d76c85366159f5f54110f33321c76d8429cfd8f39638f26793a305dae568b60" -dependencies = [ - "bevy_app", - "bevy_asset", - "bevy_color", - "bevy_derive", - "bevy_ecs", - "bevy_image", - "bevy_log", - "bevy_math", - "bevy_platform", - "bevy_reflect", - "bevy_render", - "bevy_sprite", - "bevy_transform", - "bevy_utils", - "bevy_window", - "cosmic-text", "serde", - "smallvec", - "sys-locale", - "thiserror 2.0.12", - "tracing", - "unicode-bidi", ] [[package]] -name = "bevy_time" -version = "0.16.1" +name = "half" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc98eb356c75be04fbbc77bb3d8ffa24c8bacd99f76111cee23d444be6ac8c9c" +checksum = "459196ed295495a68f7d7fe1d84f6c4b7ff0e21fe3017b2f283c6fac3ad803c9" dependencies = [ - "bevy_app", - "bevy_ecs", - "bevy_platform", - "bevy_reflect", - "crossbeam-channel", - "log", - "serde", + "cfg-if", + "crunchy", ] [[package]] -name = "bevy_transform" -version = "0.16.1" +name = "hash32" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df218e440bb9a19058e1b80a68a031c887bcf7bd3a145b55f361359a2fa3100d" +checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606" dependencies = [ - "bevy_app", - "bevy_ecs", - "bevy_log", - "bevy_math", - "bevy_reflect", - "bevy_tasks", - "bevy_utils", - "derive_more", - "serde", - "thiserror 2.0.12", + "byteorder", ] [[package]] -name = "bevy_ui" -version = "0.16.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea4a4d2ba51865bc3039af29a26b4f52c48b54cc758369f52004caf4b6f03770" -dependencies = [ - "accesskit", - "bevy_a11y", - "bevy_app", - "bevy_asset", - "bevy_color", - "bevy_core_pipeline", - "bevy_derive", - "bevy_ecs", - "bevy_image", - "bevy_input", - "bevy_math", - "bevy_picking", - "bevy_platform", - "bevy_reflect", - "bevy_render", - "bevy_sprite", - "bevy_text", - "bevy_transform", - "bevy_utils", - "bevy_window", - "bytemuck", - "derive_more", - "nonmax", - "smallvec", - "taffy", - "thiserror 2.0.12", - "tracing", +name = "hashbrown" +version = "0.15.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash", ] [[package]] -name = "bevy_utils" -version = "0.16.1" +name = "heapless" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94f7a8905a125d2017e8561beefb7f2f5e67e93ff6324f072ad87c5fd6ec3b99" +checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad" dependencies = [ - "bevy_platform", - "thread_local", + "hash32", + "stable_deref_trait", ] [[package]] -name = "bevy_window" -version = "0.16.1" +name = "heck" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df7e8ad0c17c3cc23ff5566ae2905c255e6986037fb041f74c446216f5c38431" -dependencies = [ - "android-activity", - "bevy_app", - "bevy_ecs", - "bevy_input", - "bevy_math", - "bevy_platform", - "bevy_reflect", - "bevy_utils", - "log", - "raw-window-handle", - "serde", - "smol_str", -] +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] -name = "bevy_winit" -version = "0.16.1" +name = "hershey" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a5e7f00c6b3b6823df5ec2a5e9067273607208919bc8c211773ebb9643c87f0" +checksum = "7d3cafa4047531c5386484c8f03dd90ff59c6dd96f8f011c32e13728692d1bbb" dependencies = [ - "accesskit", - "accesskit_winit", - "approx", - "bevy_a11y", - "bevy_app", - "bevy_asset", - "bevy_derive", - "bevy_ecs", - "bevy_image", - "bevy_input", - "bevy_input_focus", - "bevy_log", - "bevy_math", - "bevy_platform", - "bevy_reflect", - "bevy_tasks", - "bevy_utils", - "bevy_window", - "bytemuck", - "cfg-if", - "crossbeam-channel", - "raw-window-handle", - "tracing", - "wasm-bindgen", - "web-sys", - "wgpu-types", - "winit", + "itertools 0.14.0", + "thiserror 2.0.12", ] [[package]] -name = "bindgen" -version = "0.70.1" +name = "i_float" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f49d8fed880d473ea71efb9bf597651e77201bdd4893efe54c9e5d65ae04ce6f" +checksum = "775f9961a8d2f879725da8aff789bb20a3ddf297473e0c90af75e69313919490" dependencies = [ - "bitflags 2.9.1", - "cexpr", - "clang-sys", - "itertools 0.13.0", - "log", - "prettyplease", - "proc-macro2", - "quote", - "regex", - "rustc-hash 1.1.0", - "shlex", - "syn", + "serde", ] [[package]] -name = "bindgen" -version = "0.72.0" +name = "i_key_sort" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f72209734318d0b619a5e0f5129918b848c416e122a3c4ce054e03cb87b726f" -dependencies = [ - "bitflags 2.9.1", - "cexpr", - "clang-sys", - "itertools 0.13.0", - "proc-macro2", - "quote", - "regex", - "rustc-hash 2.1.1", - "shlex", - "syn", -] +checksum = "347c253b4748a1a28baf94c9ce133b6b166f08573157e05afe718812bc599fcd" [[package]] -name = "bit-set" -version = "0.5.3" +name = "i_overlay" +version = "1.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" +checksum = "01882ce5ed786bf6e8f5167f171a4026cd129ce17d9ff5cbf1e6749b98628ece" dependencies = [ - "bit-vec 0.6.3", + "i_float", + "i_key_sort", + "i_shape", + "i_tree", + "rayon", ] [[package]] -name = "bit-set" -version = "0.8.0" +name = "i_shape" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3" +checksum = "27dbe9e5238d6b9c694c08415bf00fb370b089949bd818ab01f41f8927b8774c" dependencies = [ - "bit-vec 0.8.0", + "i_float", + "serde", ] [[package]] -name = "bit-vec" -version = "0.6.3" +name = "i_tree" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" +checksum = "155181bc97d770181cf9477da51218a19ee92a8e5be642e796661aee2b601139" [[package]] -name = "bit-vec" -version = "0.8.0" +name = "iana-time-zone" +version = "0.1.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" +checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "log", + "wasm-bindgen", + "windows-core", +] [[package]] -name = "bit_field" -version = "0.10.2" +name = "iana-time-zone-haiku" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] [[package]] -name = "bitflags" -version = "1.3.2" +name = "image" +version = "0.25.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +checksum = "db35664ce6b9810857a38a906215e75a9c879f0696556a39f59c62829710251a" +dependencies = [ + "bytemuck", + "byteorder-lite", + "color_quant", + "exr", + "gif", + "image-webp", + "num-traits 0.2.19", + "png", + "qoi", + "ravif", + "rayon", + "rgb", + "tiff", + "zune-core", + "zune-jpeg", +] [[package]] -name = "bitflags" -version = "2.9.1" +name = "image-webp" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" +checksum = "f6970fe7a5300b4b42e62c52efa0187540a5bef546c60edaf554ef595d2e6f0b" dependencies = [ - "serde", + "byteorder-lite", + "quick-error", ] [[package]] -name = "bitstream-io" -version = "2.6.0" +name = "imgref" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6099cdc01846bc367c4e7dd630dc5966dccf36b652fae7a74e17b640411a91b2" +checksum = "d0263a3d970d5c054ed9312c0057b4f3bde9c0b33836d3637361d4a9e6e7a408" [[package]] -name = "blake3" -version = "1.8.2" +name = "indexmap" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3888aaa89e4b2a40fca9848e400f6a658a5a3978de7be858e209cafa8be9a4a0" +checksum = "fe4cd85333e22411419a0bcae1297d25e58c9443848b11dc6a86fefe8c78a661" dependencies = [ - "arrayref", - "arrayvec", - "cc", - "cfg-if", - "constant_time_eq", + "equivalent", + "hashbrown", ] [[package]] -name = "block" -version = "0.1.6" +name = "interpolate_name" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" +checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] [[package]] -name = "block2" -version = "0.5.1" +name = "itertools" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c132eebf10f5cad5289222520a4a058514204aed6d791f1cf4fe8088b82d15f" +checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" dependencies = [ - "objc2", + "either", ] [[package]] -name = "blocking" -version = "1.6.2" +name = "itertools" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e83f8d02be6967315521be875afa792a316e28d57b5a2d401897e2a7921b7f21" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" dependencies = [ - "async-channel", - "async-task", - "futures-io", - "futures-lite", - "piper", + "either", ] [[package]] -name = "built" -version = "0.7.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56ed6191a7e78c36abdb16ab65341eefd73d64d303fffccdbb00d51e4205967b" - -[[package]] -name = "bumpalo" -version = "3.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" - -[[package]] -name = "bytemuck" -version = "1.23.1" +name = "itertools" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c76a5792e44e4abe34d3abf15636779261d45a7450612059293d1d2cfc63422" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" dependencies = [ - "bytemuck_derive", + "either", ] [[package]] -name = "bytemuck_derive" -version = "1.10.0" +name = "itertools" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "441473f2b4b0459a68628c744bc61d23e730fb00128b841d30fa4bb3972257e4" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" dependencies = [ - "proc-macro2", - "quote", - "syn", + "either", ] [[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" +name = "itoa" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" [[package]] -name = "bytes" -version = "1.10.1" +name = "jobserver" +version = "0.1.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" +checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a" +dependencies = [ + "getrandom 0.3.3", + "libc", +] [[package]] -name = "calloop" -version = "0.13.0" +name = "jpeg-decoder" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b99da2f8558ca23c71f4fd15dc57c906239752dd27ff3c00a1d56b685b7cbfec" -dependencies = [ - "bitflags 2.9.1", - "log", - "polling", - "rustix 0.38.44", - "slab", - "thiserror 1.0.69", -] +checksum = "00810f1d8b74be64b13dbf3db89ac67740615d6c891f0e7b6179326533011a07" [[package]] -name = "cc" -version = "1.2.31" +name = "js-sys" +version = "0.3.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3a42d84bb6b69d3a8b3eaacf0d88f179e1929695e1ad012b6cf64d9caaa5fd2" +checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" dependencies = [ - "jobserver", - "libc", - "shlex", + "once_cell", + "wasm-bindgen", ] [[package]] -name = "cesu8" -version = "1.1.0" +name = "lebe" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" +checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8" [[package]] -name = "cexpr" -version = "0.6.0" +name = "libc" +version = "0.2.174" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" -dependencies = [ - "nom", -] +checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776" [[package]] -name = "cfg-expr" -version = "0.15.8" +name = "libfuzzer-sys" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d067ad48b8650848b989a59a86c6c36a995d02d2bf778d45c3c5d57bc2718f02" +checksum = "5037190e1f70cbeef565bd267599242926f724d3b8a9f510fd7e0b540cfa4404" dependencies = [ - "smallvec", - "target-lexicon", + "arbitrary", + "cc", ] [[package]] -name = "cfg-if" -version = "1.0.1" +name = "libm" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" +checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" [[package]] -name = "cfg_aliases" -version = "0.2.1" +name = "log" +version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" [[package]] -name = "chrono" -version = "0.4.41" +name = "loop9" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c469d952047f47f91b68d1cba3f10d63c11d73e4636f24f08daf0278abf01c4d" +checksum = "0fae87c125b03c1d2c0150c90365d7d6bcc53fb73a9acaef207d2d065860f062" dependencies = [ - "android-tzdata", - "iana-time-zone", - "js-sys", - "num-traits 0.2.19", - "serde", - "wasm-bindgen", - "windows-link", + "imgref", ] [[package]] -name = "chull" -version = "0.2.4" +name = "matrixmultiply" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "977db54e5eec96279bea3032dcf41d3844e90d62e5cfeded48f8d53b1a755d7a" +checksum = "a06de3016e9fae57a36fd14dba131fccf49f74b40b7fbdb472f96e361ec71a08" dependencies = [ - "num-bigint 0.3.3", - "num-traits 0.2.19", + "autocfg", + "rawpointer", ] [[package]] -name = "clang-sys" -version = "1.8.1" +name = "maybe-rayon" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" +checksum = "8ea1f30cedd69f0a2954655f7188c6a834246d2bcf1e315e2ac40c4b24dc9519" dependencies = [ - "glob", - "libc", - "libloading", + "cfg-if", + "rayon", ] [[package]] -name = "codespan-reporting" -version = "0.11.1" +name = "memchr" +version = "2.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" -dependencies = [ - "termcolor", - "unicode-width", -] +checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" [[package]] -name = "color_quant" -version = "1.1.0" +name = "minimal-lexical" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] -name = "combine" -version = "4.6.7" +name = "miniz_oxide" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" dependencies = [ - "bytes", - "memchr", + "adler2", + "simd-adler32", ] [[package]] -name = "concurrent-queue" -version = "2.5.0" +name = "nalgebra" +version = "0.33.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" +checksum = "26aecdf64b707efd1310e3544d709c5c0ac61c13756046aaaba41be5c4f66a3b" dependencies = [ - "crossbeam-utils", - "portable-atomic", + "approx", + "matrixmultiply", + "nalgebra-macros", + "num-complex", + "num-rational", + "num-traits 0.2.19", + "simba", + "typenum", ] [[package]] -name = "console_error_panic_hook" -version = "0.1.7" +name = "nalgebra-macros" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" +checksum = "254a5372af8fc138e36684761d3c0cdb758a4410e938babcff1c860ce14ddbfc" dependencies = [ - "cfg-if", - "wasm-bindgen", + "proc-macro2", + "quote", + "syn", ] [[package]] -name = "const-fnv1a-hash" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32b13ea120a812beba79e34316b3942a857c86ec1593cb34f27bb28272ce2cca" - -[[package]] -name = "const_panic" -version = "0.2.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b98d1483e98c9d67f341ab4b3915cfdc54740bd6f5cccc9226ee0535d86aa8fb" - -[[package]] -name = "const_soft_float" -version = "0.1.4" +name = "ndshape" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87ca1caa64ef4ed453e68bb3db612e51cf1b2f5b871337f0fcab1c8f87cc3dff" +checksum = "975bce586ad637e27f6dc26ee907c07050686a588695bfd64b7873a9d48a700c" +dependencies = [ + "static_assertions", +] [[package]] -name = "constant_time_eq" -version = "0.3.1" +name = "new_debug_unreachable" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6" +checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" [[package]] -name = "constgebra" -version = "0.1.4" +name = "nom" +version = "7.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1aaf9b65849a68662ac6c0810c8893a765c960b907dd7cfab9c4a50bf764fbc" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" dependencies = [ - "const_soft_float", + "memchr", + "minimal-lexical", ] [[package]] -name = "contour_tracing" -version = "1.0.12" +name = "noop_proc_macro" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9efef72b4f4049ebc4b690ae8ac98cfb7d3cb50407592745ad2c83106625936" +checksum = "0676bb32a98c1a483ce53e500a81ad9c3d5b3f7c920c28c24e9cb0980d0b5bc8" [[package]] -name = "core-foundation" -version = "0.9.4" +name = "num" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" dependencies = [ - "core-foundation-sys", - "libc", + "num-bigint 0.4.6", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits 0.2.19", ] [[package]] -name = "core-foundation" -version = "0.10.1" +name = "num-bigint" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6" +checksum = "5f6f7833f2cbf2360a6cfd58cd41a53aa7a90bd4c202f5b1c7dd2ed73c57b2c3" dependencies = [ - "core-foundation-sys", - "libc", + "autocfg", + "num-integer", + "num-traits 0.2.19", ] [[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" +name = "num-bigint" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c07782be35f9e1140080c6b96f0d44b739e2278479f64e02fdab4e32dfd8b081" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" dependencies = [ - "bitflags 1.3.2", - "core-foundation 0.9.4", - "core-graphics-types", - "foreign-types", - "libc", + "num-integer", + "num-traits 0.2.19", ] [[package]] -name = "core-graphics-types" -version = "0.1.3" +name = "num-complex" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" dependencies = [ - "bitflags 1.3.2", - "core-foundation 0.9.4", - "libc", + "num-traits 0.2.19", ] [[package]] -name = "core2" -version = "0.4.0" +name = "num-derive" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b49ba7ef1ad6107f8824dbe97de947cbaac53c44e7f9756a1fba0d37c1eec505" +checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ - "memchr", + "proc-macro2", + "quote", + "syn", ] [[package]] -name = "coreaudio-rs" -version = "0.11.3" +name = "num-integer" +version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "321077172d79c662f64f5071a03120748d5bb652f5231570141be24cfcd2bace" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" dependencies = [ - "bitflags 1.3.2", - "core-foundation-sys", - "coreaudio-sys", + "num-traits 0.2.19", ] [[package]] -name = "coreaudio-sys" -version = "0.2.17" +name = "num-iter" +version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ceec7a6067e62d6f931a2baf6f3a751f4a892595bcec1461a3c94ef9949864b6" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" dependencies = [ - "bindgen 0.72.0", + "autocfg", + "num-integer", + "num-traits 0.2.19", ] [[package]] -name = "cosmic-text" -version = "0.13.2" +name = "num-rational" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e418dd4f5128c3e93eab12246391c54a20c496811131f85754dc8152ee207892" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" dependencies = [ - "bitflags 2.9.1", - "fontdb", - "log", - "rangemap", - "rustc-hash 1.1.0", - "rustybuzz", - "self_cell", - "smol_str", - "swash", - "sys-locale", - "ttf-parser 0.21.1", - "unicode-bidi", - "unicode-linebreak", - "unicode-script", - "unicode-segmentation", -] - -[[package]] -name = "cpal" -version = "0.15.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "873dab07c8f743075e57f524c583985fbaf745602acbe916a01539364369a779" -dependencies = [ - "alsa", - "core-foundation-sys", - "coreaudio-rs", - "dasp_sample", - "jni", - "js-sys", - "libc", - "mach2", - "ndk 0.8.0", - "ndk-context", - "oboe", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "windows 0.54.0", -] - -[[package]] -name = "crc32fast" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "critical-section" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" - -[[package]] -name = "crossbeam" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1137cd7e7fc0fb5d3c5a8678be38ec56e819125d8d7907411fe24ccb943faca8" -dependencies = [ - "crossbeam-channel", - "crossbeam-deque", - "crossbeam-epoch", - "crossbeam-queue", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-channel" -version = "0.5.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-deque" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" -dependencies = [ - "crossbeam-epoch", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.9.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-queue" -version = "0.3.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" - -[[package]] -name = "crunchy" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" - -[[package]] -name = "csgrs" -version = "0.20.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b004da954c4987881c668e0051f6c69a23d035b4b406eee539772db4d4944025" -dependencies = [ - "bevy_asset", - "bevy_mesh", - "chull", - "contour_tracing", - "core2", - "doc-image-embed", - "dxf", - "either", - "fast-surface-nets", - "geo", - "geo-buf", - "hashbrown", - "hershey", - "image", - "nalgebra", - "nom", - "parry3d-f64", - "rapier3d-f64", - "robust", - "stl_io", - "svg", - "thiserror 2.0.12", - "ttf-parser 0.25.1", - "ttf-parser-utils", - "wgpu-types", -] - -[[package]] -name = "csv" -version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acdc4883a9c96732e4733212c01447ebd805833b7275a73ca3ee080fd77afdaf" -dependencies = [ - "csv-core", - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "csv-core" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d02f3b0da4c6504f86e9cd789d8dbafab48c2321be74e9987593de5a894d93d" -dependencies = [ - "memchr", -] - -[[package]] -name = "ctrlc" -version = "3.4.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46f93780a459b7d656ef7f071fe699c4d3d2cb201c4b24d085b6ddc505276e73" -dependencies = [ - "nix 0.30.1", - "windows-sys 0.59.0", -] - -[[package]] -name = "cursor-icon" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f27ae1dd37df86211c42e150270f82743308803d90a6f6e6651cd730d5e1732f" - -[[package]] -name = "dasp_sample" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c87e182de0887fd5361989c677c4e8f5000cd9491d6d563161a8f3a5519fc7f" - -[[package]] -name = "data-encoding" -version = "2.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476" - -[[package]] -name = "derive_more" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05" -dependencies = [ - "derive_more-impl", -] - -[[package]] -name = "derive_more-impl" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "unicode-xid", -] - -[[package]] -name = "dispatch" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" - -[[package]] -name = "disqualified" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9c272297e804878a2a4b707cfcfc6d2328b5bb936944613b4fdf2b9269afdfd" - -[[package]] -name = "dlib" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "330c60081dcc4c72131f8eb70510f1ac07223e5d4163db481a04a0befcffa412" -dependencies = [ - "libloading", -] - -[[package]] -name = "doc-image-embed" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b1c7e5bbb92b417588a5e733e095416c27c06eedc051065cc955a0a8c8389d9" -dependencies = [ - "base64 0.22.1", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "document-features" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95249b50c6c185bee49034bcb378a49dc2b5dff0be90ff6616d31d64febab05d" -dependencies = [ - "litrs", -] - -[[package]] -name = "downcast-rs" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea8a8b81cacc08888170eef4d13b775126db426d0b348bee9d18c2c1eaf123cf" - -[[package]] -name = "dpi" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8b14ccef22fc6f5a8f4d7d768562a182c04ce9a3b3157b91390b52ddfdf1a76" - -[[package]] -name = "dxf" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db88ab4334d9288e6658b8bb8e7bc9167ae48878b5f92818e01969a5041d294d" -dependencies = [ - "byteorder", - "chrono", - "encoding_rs", - "enum_primitive", - "image", - "itertools 0.13.0", - "num", - "uuid", - "xmltree", -] - -[[package]] -name = "earcutr" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79127ed59a85d7687c409e9978547cffb7dc79675355ed22da6b66fd5f6ead01" -dependencies = [ - "itertools 0.11.0", - "num-traits 0.2.19", -] - -[[package]] -name = "either" -version = "1.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" - -[[package]] -name = "ena" -version = "0.14.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d248bdd43ce613d87415282f69b9bb99d947d290b10962dd6c56233312c2ad5" -dependencies = [ - "log", -] - -[[package]] -name = "encase" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0a05902cf601ed11d564128448097b98ebe3c6574bd7b6a653a3d56d54aa020" -dependencies = [ - "const_panic", - "encase_derive", - "glam", - "thiserror 1.0.69", -] - -[[package]] -name = "encase_derive" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "181d475b694e2dd56ae919ce7699d344d1fd259292d590c723a50d1189a2ea85" -dependencies = [ - "encase_derive_impl", -] - -[[package]] -name = "encase_derive_impl" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f97b51c5cc57ef7c5f7a0c57c250251c49ee4c28f819f87ac32f4aceabc36792" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "encoding_rs" -version = "0.8.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "enum_primitive" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4551092f4d519593039259a9ed8daedf0da12e5109c5280338073eaeb81180" -dependencies = [ - "num-traits 0.1.43", -] - -[[package]] -name = "equator" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4711b213838dfee0117e3be6ac926007d7f433d7bbe33595975d4190cb07e6fc" -dependencies = [ - "equator-macro", -] - -[[package]] -name = "equator-macro" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44f23cf4b44bfce11a86ace86f8a73ffdec849c9fd00a386a53d278bd9e81fb3" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "equivalent" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" - -[[package]] -name = "erased-serde" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e004d887f51fcb9fef17317a2f3525c887d8aa3f4f50fed920816a688284a5b7" -dependencies = [ - "serde", - "typeid", -] - -[[package]] -name = "errno" -version = "0.3.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad" -dependencies = [ - "libc", - "windows-sys 0.60.2", -] - -[[package]] -name = "euclid" -version = "0.22.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad9cdb4b747e485a12abb0e6566612956c7a1bafa3bdb8d682c5b6d403589e48" -dependencies = [ - "num-traits 0.2.19", -] - -[[package]] -name = "event-listener" -version = "5.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3492acde4c3fc54c845eaab3eed8bd00c7a7d881f78bfc801e43a93dec1331ae" -dependencies = [ - "concurrent-queue", - "parking", - "pin-project-lite", -] - -[[package]] -name = "event-listener-strategy" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93" -dependencies = [ - "event-listener", - "pin-project-lite", -] - -[[package]] -name = "exr" -version = "1.73.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f83197f59927b46c04a183a619b7c29df34e63e63c7869320862268c0ef687e0" -dependencies = [ - "bit_field", - "half", - "lebe", - "miniz_oxide", - "rayon-core", - "smallvec", - "zune-inflate", -] - -[[package]] -name = "fast-surface-nets" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2aef9e8d9e33f51d8120a2e997a819f18239ad7c2735e353ade79208a9a1c442" -dependencies = [ - "glam", - "ndshape", -] - -[[package]] -name = "fastrand" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" - -[[package]] -name = "fdeflate" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c" -dependencies = [ - "simd-adler32", -] - -[[package]] -name = "fixedbitset" -version = "0.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" - -[[package]] -name = "flate2" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a3d7db9596fecd151c5f638c0ee5d5bd487b6e0ea232e5dc96d5250f6f94b1d" -dependencies = [ - "crc32fast", - "miniz_oxide", -] - -[[package]] -name = "float-cmp" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98de4bbd547a563b716d8dfa9aad1cb19bfab00f4fa09a6a4ed21dbcf44ce9c4" -dependencies = [ - "num-traits 0.2.19", -] - -[[package]] -name = "float_next_after" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bf7cc16383c4b8d58b9905a8509f02926ce3058053c056376248d958c9df1e8" - -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - -[[package]] -name = "foldhash" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" - -[[package]] -name = "font-types" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02a596f5713680923a2080d86de50fe472fb290693cf0f701187a1c8b36996b7" -dependencies = [ - "bytemuck", -] - -[[package]] -name = "fontconfig-parser" -version = "0.5.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbc773e24e02d4ddd8395fd30dc147524273a83e54e0f312d986ea30de5f5646" -dependencies = [ - "roxmltree", -] - -[[package]] -name = "fontdb" -version = "0.16.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0299020c3ef3f60f526a4f64ab4a3d4ce116b1acbf24cdd22da0068e5d81dc3" -dependencies = [ - "fontconfig-parser", - "log", - "memmap2", - "slotmap", - "tinyvec", - "ttf-parser 0.20.0", -] - -[[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-channel" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" -dependencies = [ - "futures-core", -] - -[[package]] -name = "futures-core" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" - -[[package]] -name = "futures-io" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" - -[[package]] -name = "futures-lite" -version = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5edaec856126859abb19ed65f39e90fea3a9574b9707f13539acf4abf7eb532" -dependencies = [ - "fastrand", - "futures-core", - "futures-io", - "parking", - "pin-project-lite", -] - -[[package]] -name = "geo" -version = "0.29.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34f0e6e028c581e82e6822a68869514e94c25e7f8ea669a2d8595bdf7461ccc5" -dependencies = [ - "earcutr", - "float_next_after", - "geo-types", - "geographiclib-rs", - "i_overlay", - "log", - "num-traits 0.2.19", - "robust", - "rstar", - "spade", -] - -[[package]] -name = "geo-buf" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3259dd509ae98be7ce49236ec9be30c7d8a0ce84eada28dbefb68bc839b29e66" -dependencies = [ - "geo", - "geo-types", -] - -[[package]] -name = "geo-types" -version = "0.7.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75a4dcd69d35b2c87a7c83bce9af69fd65c9d68d3833a0ded568983928f3fc99" -dependencies = [ - "approx", - "num-traits 0.2.19", - "rayon", - "rstar", - "serde", -] - -[[package]] -name = "geographiclib-rs" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f611040a2bb37eaa29a78a128d1e92a378a03e0b6e66ae27398d42b1ba9a7841" -dependencies = [ - "libm", -] - -[[package]] -name = "gethostname" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0176e0459c2e4a1fe232f984bca6890e681076abb9934f6cea7c326f3fc47818" -dependencies = [ - "libc", - "windows-targets 0.48.5", -] - -[[package]] -name = "getrandom" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" -dependencies = [ - "cfg-if", - "js-sys", - "libc", - "wasi 0.11.1+wasi-snapshot-preview1", - "wasm-bindgen", -] - -[[package]] -name = "getrandom" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" -dependencies = [ - "cfg-if", - "libc", - "r-efi", - "wasi 0.14.2+wasi-0.2.4", -] - -[[package]] -name = "gif" -version = "0.13.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ae047235e33e2829703574b54fdec96bfbad892062d97fed2f76022287de61b" -dependencies = [ - "color_quant", - "weezl", -] - -[[package]] -name = "gilrs" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbb2c998745a3c1ac90f64f4f7b3a54219fd3612d7705e7798212935641ed18f" -dependencies = [ - "fnv", - "gilrs-core", - "log", - "uuid", - "vec_map", -] - -[[package]] -name = "gilrs-core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6d95ae10ce5aa99543a28cf74e41c11f3b9e3c14f0452bbde46024753cd683e" -dependencies = [ - "core-foundation 0.10.1", - "inotify", - "io-kit-sys", - "js-sys", - "libc", - "libudev-sys", - "log", - "nix 0.29.0", - "uuid", - "vec_map", - "wasm-bindgen", - "web-sys", - "windows 0.61.3", -] - -[[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 0.8.27", -] - -[[package]] -name = "glam" -version = "0.29.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8babf46d4c1c9d92deac9f7be466f76dfc4482b6452fc5024b5e8daf6ffeb3ee" -dependencies = [ - "bytemuck", - "libm", - "rand 0.8.5", - "serde", -] - -[[package]] -name = "glob" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" - -[[package]] -name = "glow" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5e5ea60d70410161c8bf5da3fdfeaa1c72ed2c15f8bbb9d19fe3a4fad085f08" -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 = [ - "byteorder", - "gltf-json", - "lazy_static", - "serde_json", -] - -[[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-alloc" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbcd2dba93594b227a1f57ee09b8b9da8892c34d55aa332e034a228d0fe6a171" -dependencies = [ - "bitflags 2.9.1", - "gpu-alloc-types", -] - -[[package]] -name = "gpu-alloc-types" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98ff03b468aa837d70984d55f5d3f846f6ec31fe34bbb97c4f85219caeee1ca4" -dependencies = [ - "bitflags 2.9.1", -] - -[[package]] -name = "gpu-allocator" -version = "0.27.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c151a2a5ef800297b4e79efa4f4bec035c5f51d5ae587287c9b952bdf734cacd" -dependencies = [ - "log", - "presser", - "thiserror 1.0.69", - "windows 0.58.0", -] - -[[package]] -name = "gpu-descriptor" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b89c83349105e3732062a895becfc71a8f921bb71ecbbdd8ff99263e3b53a0ca" -dependencies = [ - "bitflags 2.9.1", - "gpu-descriptor-types", - "hashbrown", -] - -[[package]] -name = "gpu-descriptor-types" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdf242682df893b86f33a73828fb09ca4b2d3bb6cc95249707fc684d27484b91" -dependencies = [ - "bitflags 2.9.1", -] - -[[package]] -name = "grid" -version = "0.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36119f3a540b086b4e436bb2b588cf98a68863470e0e880f4d0842f112a3183a" - -[[package]] -name = "guillotiere" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b62d5865c036cb1393e23c50693df631d3f5d7bcca4c04fe4cc0fd592e74a782" -dependencies = [ - "euclid", - "svg_fmt", -] - -[[package]] -name = "half" -version = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "459196ed295495a68f7d7fe1d84f6c4b7ff0e21fe3017b2f283c6fac3ad803c9" -dependencies = [ - "cfg-if", - "crunchy", -] - -[[package]] -name = "hash32" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606" -dependencies = [ - "byteorder", -] - -[[package]] -name = "hashbrown" -version = "0.15.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5" -dependencies = [ - "allocator-api2", - "equivalent", - "foldhash", - "serde", -] - -[[package]] -name = "heapless" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad" -dependencies = [ - "hash32", - "portable-atomic", - "stable_deref_trait", -] - -[[package]] -name = "heck" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" - -[[package]] -name = "hermit-abi" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" - -[[package]] -name = "hershey" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d3cafa4047531c5386484c8f03dd90ff59c6dd96f8f011c32e13728692d1bbb" -dependencies = [ - "itertools 0.14.0", - "thiserror 2.0.12", -] - -[[package]] -name = "hexasphere" -version = "15.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9c9e718d32b6e6b2b32354e1b0367025efdd0b11d6a740b905ddf5db1074679" -dependencies = [ - "constgebra", - "glam", - "tinyvec", -] - -[[package]] -name = "hexf-parse" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df" - -[[package]] -name = "i_float" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "775f9961a8d2f879725da8aff789bb20a3ddf297473e0c90af75e69313919490" -dependencies = [ - "serde", -] - -[[package]] -name = "i_key_sort" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "347c253b4748a1a28baf94c9ce133b6b166f08573157e05afe718812bc599fcd" - -[[package]] -name = "i_overlay" -version = "1.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01882ce5ed786bf6e8f5167f171a4026cd129ce17d9ff5cbf1e6749b98628ece" -dependencies = [ - "i_float", - "i_key_sort", - "i_shape", - "i_tree", - "rayon", -] - -[[package]] -name = "i_shape" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27dbe9e5238d6b9c694c08415bf00fb370b089949bd818ab01f41f8927b8774c" -dependencies = [ - "i_float", - "serde", -] - -[[package]] -name = "i_tree" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "155181bc97d770181cf9477da51218a19ee92a8e5be642e796661aee2b601139" - -[[package]] -name = "iana-time-zone" -version = "0.1.63" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8" -dependencies = [ - "android_system_properties", - "core-foundation-sys", - "iana-time-zone-haiku", - "js-sys", - "log", - "wasm-bindgen", - "windows-core 0.61.2", -] - -[[package]] -name = "iana-time-zone-haiku" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" -dependencies = [ - "cc", -] - -[[package]] -name = "image" -version = "0.25.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db35664ce6b9810857a38a906215e75a9c879f0696556a39f59c62829710251a" -dependencies = [ - "bytemuck", - "byteorder-lite", - "color_quant", - "exr", - "gif", - "image-webp", - "num-traits 0.2.19", - "png", - "qoi", - "ravif", - "rayon", - "rgb", - "tiff", - "zune-core", - "zune-jpeg", -] - -[[package]] -name = "image-webp" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6970fe7a5300b4b42e62c52efa0187540a5bef546c60edaf554ef595d2e6f0b" -dependencies = [ - "byteorder-lite", - "quick-error", -] - -[[package]] -name = "imgref" -version = "1.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0263a3d970d5c054ed9312c0057b4f3bde9c0b33836d3637361d4a9e6e7a408" - -[[package]] -name = "immutable-chunkmap" -version = "2.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12f97096f508d54f8f8ab8957862eee2ccd628847b6217af1a335e1c44dee578" -dependencies = [ - "arrayvec", -] - -[[package]] -name = "indexmap" -version = "2.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe4cd85333e22411419a0bcae1297d25e58c9443848b11dc6a86fefe8c78a661" -dependencies = [ - "equivalent", - "hashbrown", - "serde", -] - -[[package]] -name = "inflections" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a257582fdcde896fd96463bf2d40eefea0580021c0712a0e2b028b60b47a837a" - -[[package]] -name = "inotify" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f37dccff2791ab604f9babef0ba14fbe0be30bd368dc541e2b08d07c8aa908f3" -dependencies = [ - "bitflags 2.9.1", - "inotify-sys", - "libc", -] - -[[package]] -name = "inotify-sys" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb" -dependencies = [ - "libc", -] - -[[package]] -name = "interpolate_name" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "io-kit-sys" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "617ee6cf8e3f66f3b4ea67a4058564628cde41901316e19f559e14c7c72c5e7b" -dependencies = [ - "core-foundation-sys", - "mach2", -] - -[[package]] -name = "itertools" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" -dependencies = [ - "either", -] - -[[package]] -name = "itertools" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" -dependencies = [ - "either", -] - -[[package]] -name = "itertools" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" -dependencies = [ - "either", -] - -[[package]] -name = "itertools" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" -dependencies = [ - "either", -] - -[[package]] -name = "itoa" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" - -[[package]] -name = "jni" -version = "0.21.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" -dependencies = [ - "cesu8", - "cfg-if", - "combine", - "jni-sys", - "log", - "thiserror 1.0.69", - "walkdir", - "windows-sys 0.45.0", -] - -[[package]] -name = "jni-sys" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" - -[[package]] -name = "jobserver" -version = "0.1.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a" -dependencies = [ - "getrandom 0.3.3", - "libc", -] - -[[package]] -name = "jpeg-decoder" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00810f1d8b74be64b13dbf3db89ac67740615d6c891f0e7b6179326533011a07" - -[[package]] -name = "js-sys" -version = "0.3.77" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" -dependencies = [ - "once_cell", - "wasm-bindgen", -] - -[[package]] -name = "khronos-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 = "ktx2" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87d65e08a9ec02e409d27a0139eaa6b9756b4d81fe7cde71f6941a83730ce838" -dependencies = [ - "bitflags 1.3.2", -] - -[[package]] -name = "lazy_static" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" - -[[package]] -name = "lebe" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8" - -[[package]] -name = "lewton" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "777b48df9aaab155475a83a7df3070395ea1ac6902f5cd062b8f2b028075c030" -dependencies = [ - "byteorder", - "ogg", - "tinyvec", -] - -[[package]] -name = "libc" -version = "0.2.174" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776" - -[[package]] -name = "libfuzzer-sys" -version = "0.4.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5037190e1f70cbeef565bd267599242926f724d3b8a9f510fd7e0b540cfa4404" -dependencies = [ - "arbitrary", - "cc", -] - -[[package]] -name = "libloading" -version = "0.8.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667" -dependencies = [ - "cfg-if", - "windows-targets 0.53.3", -] - -[[package]] -name = "libm" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" - -[[package]] -name = "libredox" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "391290121bad3d37fbddad76d8f5d1c1c314cfc646d143d7e07a3086ddff0ce3" -dependencies = [ - "bitflags 2.9.1", - "libc", - "redox_syscall 0.5.17", -] - -[[package]] -name = "libudev-sys" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c8469b4a23b962c1396b9b451dda50ef5b283e8dd309d69033475fa9b334324" -dependencies = [ - "libc", - "pkg-config", -] - -[[package]] -name = "linux-raw-sys" -version = "0.4.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" - -[[package]] -name = "linux-raw-sys" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" - -[[package]] -name = "litrs" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5e54036fe321fd421e10d732f155734c4e4afd610dd556d9a82833ab3ee0bed" - -[[package]] -name = "lock_api" -version = "0.4.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765" -dependencies = [ - "autocfg", - "scopeguard", -] - -[[package]] -name = "log" -version = "0.4.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" - -[[package]] -name = "loop9" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fae87c125b03c1d2c0150c90365d7d6bcc53fb73a9acaef207d2d065860f062" -dependencies = [ - "imgref", -] - -[[package]] -name = "mach2" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d640282b302c0bb0a2a8e0233ead9035e3bed871f0b7e81fe4a1ec829765db44" -dependencies = [ - "libc", -] - -[[package]] -name = "malloc_buf" -version = "0.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" -dependencies = [ - "libc", -] - -[[package]] -name = "matchers" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" -dependencies = [ - "regex-automata 0.1.10", -] - -[[package]] -name = "matrixmultiply" -version = "0.3.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a06de3016e9fae57a36fd14dba131fccf49f74b40b7fbdb472f96e361ec71a08" -dependencies = [ - "autocfg", - "rawpointer", -] - -[[package]] -name = "maybe-rayon" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ea1f30cedd69f0a2954655f7188c6a834246d2bcf1e315e2ac40c4b24dc9519" -dependencies = [ - "cfg-if", - "rayon", -] - -[[package]] -name = "memchr" -version = "2.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" - -[[package]] -name = "memmap2" -version = "0.9.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "483758ad303d734cec05e5c12b41d7e93e6a6390c5e9dae6bdeb7c1259012d28" -dependencies = [ - "libc", -] - -[[package]] -name = "metal" -version = "0.31.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f569fb946490b5743ad69813cb19629130ce9374034abe31614a36402d18f99e" -dependencies = [ - "bitflags 2.9.1", - "block", - "core-graphics-types", - "foreign-types", - "log", - "objc", - "paste", -] - -[[package]] -name = "minimal-lexical" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" - -[[package]] -name = "miniz_oxide" -version = "0.8.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" -dependencies = [ - "adler2", - "simd-adler32", -] - -[[package]] -name = "naga" -version = "24.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e380993072e52eef724eddfcde0ed013b0c023c3f0417336ed041aa9f076994e" -dependencies = [ - "arrayvec", - "bit-set 0.8.0", - "bitflags 2.9.1", - "cfg_aliases", - "codespan-reporting", - "hexf-parse", - "indexmap", - "log", - "pp-rs", - "rustc-hash 1.1.0", - "spirv", - "strum", - "termcolor", - "thiserror 2.0.12", - "unicode-xid", -] - -[[package]] -name = "naga_oil" -version = "0.17.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2464f7395decfd16bb4c33fb0cb3b2c645cc60d051bc7fb652d3720bfb20f18" -dependencies = [ - "bit-set 0.5.3", - "codespan-reporting", - "data-encoding", - "indexmap", - "naga", - "once_cell", - "regex", - "regex-syntax 0.8.5", - "rustc-hash 1.1.0", - "thiserror 1.0.69", - "tracing", - "unicode-ident", -] - -[[package]] -name = "nalgebra" -version = "0.33.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26aecdf64b707efd1310e3544d709c5c0ac61c13756046aaaba41be5c4f66a3b" -dependencies = [ - "approx", - "matrixmultiply", - "nalgebra-macros", - "num-complex", - "num-rational", - "num-traits 0.2.19", - "simba", - "typenum", -] - -[[package]] -name = "nalgebra-macros" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "254a5372af8fc138e36684761d3c0cdb758a4410e938babcff1c860ce14ddbfc" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "ndk" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2076a31b7010b17a38c01907c45b945e8f11495ee4dd588309718901b1f7a5b7" -dependencies = [ - "bitflags 2.9.1", - "jni-sys", - "log", - "ndk-sys 0.5.0+25.2.9519653", - "num_enum", - "thiserror 1.0.69", -] - -[[package]] -name = "ndk" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4" -dependencies = [ - "bitflags 2.9.1", - "jni-sys", - "log", - "ndk-sys 0.6.0+11769913", - "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.5.0+25.2.9519653" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c196769dd60fd4f363e11d948139556a344e79d451aeb2fa2fd040738ef7691" -dependencies = [ - "jni-sys", -] - -[[package]] -name = "ndk-sys" -version = "0.6.0+11769913" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee6cda3051665f1fb8d9e08fc35c96d5a244fb1be711a03b71118828afc9a873" -dependencies = [ - "jni-sys", -] - -[[package]] -name = "ndshape" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "975bce586ad637e27f6dc26ee907c07050686a588695bfd64b7873a9d48a700c" -dependencies = [ - "static_assertions", -] - -[[package]] -name = "new_debug_unreachable" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" - -[[package]] -name = "nix" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" -dependencies = [ - "bitflags 2.9.1", - "cfg-if", - "cfg_aliases", - "libc", -] - -[[package]] -name = "nix" -version = "0.30.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" -dependencies = [ - "bitflags 2.9.1", - "cfg-if", - "cfg_aliases", - "libc", -] - -[[package]] -name = "nom" -version = "7.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" -dependencies = [ - "memchr", - "minimal-lexical", -] - -[[package]] -name = "nonmax" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "610a5acd306ec67f907abe5567859a3c693fb9886eb1f012ab8f2a47bef3db51" - -[[package]] -name = "noop_proc_macro" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0676bb32a98c1a483ce53e500a81ad9c3d5b3f7c920c28c24e9cb0980d0b5bc8" - -[[package]] -name = "ntapi" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8a3895c6391c39d7fe7ebc444a87eb2991b2a0bc718fdabd071eec617fc68e4" -dependencies = [ - "winapi", -] - -[[package]] -name = "nu-ansi-term" -version = "0.46.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" -dependencies = [ - "overload", - "winapi", -] - -[[package]] -name = "num" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" -dependencies = [ - "num-bigint 0.4.6", - "num-complex", - "num-integer", - "num-iter", - "num-rational", - "num-traits 0.2.19", -] - -[[package]] -name = "num-bigint" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f6f7833f2cbf2360a6cfd58cd41a53aa7a90bd4c202f5b1c7dd2ed73c57b2c3" -dependencies = [ - "autocfg", - "num-integer", - "num-traits 0.2.19", -] - -[[package]] -name = "num-bigint" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" -dependencies = [ - "num-integer", - "num-traits 0.2.19", -] - -[[package]] -name = "num-complex" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" -dependencies = [ - "num-traits 0.2.19", -] - -[[package]] -name = "num-derive" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "num-integer" -version = "0.1.46" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" -dependencies = [ - "num-traits 0.2.19", -] - -[[package]] -name = "num-iter" -version = "0.1.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" -dependencies = [ - "autocfg", - "num-integer", - "num-traits 0.2.19", -] - -[[package]] -name = "num-rational" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" -dependencies = [ - "num-bigint 0.4.6", - "num-integer", - "num-traits 0.2.19", -] - -[[package]] -name = "num-traits" -version = "0.1.43" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31" -dependencies = [ - "num-traits 0.2.19", -] - -[[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.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a973b4e44ce6cad84ce69d797acf9a044532e4184c4f267913d1b546a0727b7a" -dependencies = [ - "num_enum_derive", - "rustversion", -] - -[[package]] -name = "num_enum_derive" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77e878c846a8abae00dd069496dbe8751b16ac1c3d6bd2a7283a938e8228f90d" -dependencies = [ - "proc-macro-crate", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "objc" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" -dependencies = [ - "malloc_buf", -] - -[[package]] -name = "objc-sys" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb91bdd390c7ce1a8607f35f3ca7151b65afc0ff5ff3b34fa350f7d7c7e4310" - -[[package]] -name = "objc2" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46a785d4eeff09c14c487497c162e92766fbb3e4059a71840cecc03d9a50b804" -dependencies = [ - "objc-sys", - "objc2-encode", -] - -[[package]] -name = "objc2-app-kit" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4e89ad9e3d7d297152b17d39ed92cd50ca8063a89a9fa569046d41568891eff" -dependencies = [ - "bitflags 2.9.1", - "block2", - "libc", - "objc2", - "objc2-core-data", - "objc2-core-image", - "objc2-foundation", - "objc2-quartz-core", -] - -[[package]] -name = "objc2-cloud-kit" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74dd3b56391c7a0596a295029734d3c1c5e7e510a4cb30245f8221ccea96b009" -dependencies = [ - "bitflags 2.9.1", - "block2", - "objc2", - "objc2-core-location", - "objc2-foundation", -] - -[[package]] -name = "objc2-contacts" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5ff520e9c33812fd374d8deecef01d4a840e7b41862d849513de77e44aa4889" -dependencies = [ - "block2", - "objc2", - "objc2-foundation", -] - -[[package]] -name = "objc2-core-data" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "617fbf49e071c178c0b24c080767db52958f716d9eabdf0890523aeae54773ef" -dependencies = [ - "bitflags 2.9.1", - "block2", - "objc2", - "objc2-foundation", -] - -[[package]] -name = "objc2-core-foundation" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c10c2894a6fed806ade6027bcd50662746363a9589d3ec9d9bef30a4e4bc166" -dependencies = [ - "bitflags 2.9.1", -] - -[[package]] -name = "objc2-core-image" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55260963a527c99f1819c4f8e3b47fe04f9650694ef348ffd2227e8196d34c80" -dependencies = [ - "block2", - "objc2", - "objc2-foundation", - "objc2-metal", -] - -[[package]] -name = "objc2-core-location" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "000cfee34e683244f284252ee206a27953279d370e309649dc3ee317b37e5781" -dependencies = [ - "block2", - "objc2", - "objc2-contacts", - "objc2-foundation", -] - -[[package]] -name = "objc2-encode" -version = "4.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33" - -[[package]] -name = "objc2-foundation" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8" -dependencies = [ - "bitflags 2.9.1", - "block2", - "dispatch", - "libc", - "objc2", -] - -[[package]] -name = "objc2-link-presentation" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1a1ae721c5e35be65f01a03b6d2ac13a54cb4fa70d8a5da293d7b0020261398" -dependencies = [ - "block2", - "objc2", - "objc2-app-kit", - "objc2-foundation", -] - -[[package]] -name = "objc2-metal" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6" -dependencies = [ - "bitflags 2.9.1", - "block2", - "objc2", - "objc2-foundation", -] - -[[package]] -name = "objc2-quartz-core" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a" -dependencies = [ - "bitflags 2.9.1", - "block2", - "objc2", - "objc2-foundation", - "objc2-metal", -] - -[[package]] -name = "objc2-symbols" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a684efe3dec1b305badae1a28f6555f6ddd3bb2c2267896782858d5a78404dc" -dependencies = [ - "objc2", - "objc2-foundation", -] - -[[package]] -name = "objc2-ui-kit" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8bb46798b20cd6b91cbd113524c490f1686f4c4e8f49502431415f3512e2b6f" -dependencies = [ - "bitflags 2.9.1", - "block2", - "objc2", - "objc2-cloud-kit", - "objc2-core-data", - "objc2-core-image", - "objc2-core-location", - "objc2-foundation", - "objc2-link-presentation", - "objc2-quartz-core", - "objc2-symbols", - "objc2-uniform-type-identifiers", - "objc2-user-notifications", -] - -[[package]] -name = "objc2-uniform-type-identifiers" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44fa5f9748dbfe1ca6c0b79ad20725a11eca7c2218bceb4b005cb1be26273bfe" -dependencies = [ - "block2", - "objc2", - "objc2-foundation", -] - -[[package]] -name = "objc2-user-notifications" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76cfcbf642358e8689af64cee815d139339f3ed8ad05103ed5eaf73db8d84cb3" -dependencies = [ - "bitflags 2.9.1", - "block2", - "objc2", - "objc2-core-location", - "objc2-foundation", -] - -[[package]] -name = "oboe" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8b61bebd49e5d43f5f8cc7ee2891c16e0f41ec7954d36bcb6c14c5e0de867fb" -dependencies = [ - "jni", - "ndk 0.8.0", - "ndk-context", - "num-derive", - "num-traits 0.2.19", - "oboe-sys", -] - -[[package]] -name = "oboe-sys" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8bb09a4a2b1d668170cfe0a7d5bc103f8999fb316c98099b6a9939c9f2e79d" -dependencies = [ - "cc", -] - -[[package]] -name = "offset-allocator" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e234d535da3521eb95106f40f0b73483d80bfb3aacf27c40d7e2b72f1a3e00a2" -dependencies = [ - "log", - "nonmax", -] - -[[package]] -name = "ogg" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6951b4e8bf21c8193da321bcce9c9dd2e13c858fe078bf9054a288b419ae5d6e" -dependencies = [ - "byteorder", -] - -[[package]] -name = "once_cell" -version = "1.21.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" - -[[package]] -name = "orbclient" -version = "0.3.48" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba0b26cec2e24f08ed8bb31519a9333140a6599b867dac464bb150bdb796fd43" -dependencies = [ - "libredox", -] - -[[package]] -name = "ordered-float" -version = "4.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bb71e1b3fa6ca1c61f383464aaf2bb0e2f8e772a1f01d486832464de363b951" -dependencies = [ - "num-traits 0.2.19", -] - -[[package]] -name = "ordered-float" -version = "5.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2c1f9f56e534ac6a9b8a4600bdf0f530fb393b5f393e7b4d03489c3cf0c3f01" -dependencies = [ - "num-traits 0.2.19", -] - -[[package]] -name = "overload" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" - -[[package]] -name = "parking" -version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" - -[[package]] -name = "parking_lot" -version = "0.12.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13" -dependencies = [ - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall 0.5.17", - "smallvec", - "windows-targets 0.52.6", -] - -[[package]] -name = "parry3d-f64" -version = "0.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed9184cf88474deb3e5ec6c67a8c6fe51ee9572e8c476d44b7de643937a125c5" -dependencies = [ - "approx", - "arrayvec", - "bitflags 2.9.1", - "downcast-rs", - "either", - "ena", - "hashbrown", - "log", - "nalgebra", - "num-derive", - "num-traits 0.2.19", - "ordered-float 5.0.0", - "rstar", - "simba", - "slab", - "spade", - "thiserror 2.0.12", -] - -[[package]] -name = "paste" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" - -[[package]] -name = "percent-encoding" -version = "2.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" - -[[package]] -name = "petgraph" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3672b37090dbd86368a4145bc067582552b29c27377cad4e0a306c97f9bd7772" -dependencies = [ - "fixedbitset", - "indexmap", - "serde", - "serde_derive", -] - -[[package]] -name = "pin-project" -version = "1.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a" -dependencies = [ - "pin-project-internal", -] - -[[package]] -name = "pin-project-internal" -version = "1.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "pin-project-lite" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" - -[[package]] -name = "piper" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066" -dependencies = [ - "atomic-waker", - "fastrand", - "futures-io", -] - -[[package]] -name = "pkg-config" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" - -[[package]] -name = "png" -version = "0.17.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82151a2fc869e011c153adc57cf2789ccb8d9906ce52c0b39a6b5697749d7526" -dependencies = [ - "bitflags 1.3.2", - "crc32fast", - "fdeflate", - "flate2", - "miniz_oxide", -] - -[[package]] -name = "polling" -version = "3.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ee9b2fa7a4517d2c91ff5bc6c297a427a96749d15f98fcdbb22c05571a4d4b7" -dependencies = [ - "cfg-if", - "concurrent-queue", - "hermit-abi", - "pin-project-lite", - "rustix 1.0.8", - "windows-sys 0.60.2", -] - -[[package]] -name = "portable-atomic" -version = "1.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" - -[[package]] -name = "portable-atomic-util" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507" -dependencies = [ - "portable-atomic", -] - -[[package]] -name = "pp-rs" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb458bb7f6e250e6eb79d5026badc10a3ebb8f9a15d1fff0f13d17c71f4d6dee" -dependencies = [ - "unicode-xid", -] - -[[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 = "prettyplease" -version = "0.2.36" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff24dfcda44452b9816fff4cd4227e1bb73ff5a2f1bc1105aa92fb8565ce44d2" -dependencies = [ - "proc-macro2", - "syn", -] - -[[package]] -name = "proc-macro-crate" -version = "3.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edce586971a4dfaa28950c6f18ed55e0406c1ab88bbce2c6f6293a7aaba73d35" -dependencies = [ - "toml_edit", -] - -[[package]] -name = "proc-macro2" -version = "1.0.95" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "profiling" -version = "1.0.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3eb8486b569e12e2c32ad3e204dbaba5e4b5b216e9367044f25f1dba42341773" -dependencies = [ - "profiling-procmacros", -] - -[[package]] -name = "profiling-procmacros" -version = "1.0.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52717f9a02b6965224f95ca2a81e2e0c5c43baacd28ca057577988930b6c3d5b" -dependencies = [ - "quote", - "syn", -] - -[[package]] -name = "qoi" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f6d64c71eb498fe9eae14ce4ec935c555749aef511cca85b5568910d6e48001" -dependencies = [ - "bytemuck", -] - -[[package]] -name = "quick-error" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" - -[[package]] -name = "quote" -version = "1.0.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "r-efi" -version = "5.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" - -[[package]] -name = "radsort" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "019b4b213425016d7d84a153c4c73afb0946fbb4840e4eece7ba8848b9d6da22" - -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "libc", - "rand_chacha 0.3.1", - "rand_core 0.6.4", -] - -[[package]] -name = "rand" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" -dependencies = [ - "rand_chacha 0.9.0", - "rand_core 0.9.3", -] - -[[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 0.6.4", -] - -[[package]] -name = "rand_chacha" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" -dependencies = [ - "ppv-lite86", - "rand_core 0.9.3", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom 0.2.16", -] - -[[package]] -name = "rand_core" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" -dependencies = [ - "getrandom 0.3.3", -] - -[[package]] -name = "rand_distr" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32cb0b9bc82b0a0876c2dd994a7e7a2683d3e7390ca40e6886785ef0c7e3ee31" -dependencies = [ - "num-traits 0.2.19", - "rand 0.8.5", -] - -[[package]] -name = "range-alloc" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d6831663a5098ea164f89cff59c6284e95f4e3c76ce9848d4529f5ccca9bde" - -[[package]] -name = "rangemap" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f93e7e49bb0bf967717f7bd674458b3d6b0c5f48ec7e3038166026a69fc22223" - -[[package]] -name = "rapier3d-f64" -version = "0.24.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75a10d0735644bdc60b54a573a1ba413bab4f4822ce403e4f637f4d0b3d54d6b" -dependencies = [ - "approx", - "arrayvec", - "bit-vec 0.8.0", - "bitflags 2.9.1", - "crossbeam", - "downcast-rs", - "log", - "nalgebra", - "num-derive", - "num-traits 0.2.19", - "ordered-float 5.0.0", - "parry3d-f64", - "profiling", - "rustc-hash 2.1.1", - "simba", - "thiserror 2.0.12", -] - -[[package]] -name = "rav1e" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd87ce80a7665b1cce111f8a16c1f3929f6547ce91ade6addf4ec86a8dda5ce9" -dependencies = [ - "arbitrary", - "arg_enum_proc_macro", - "arrayvec", - "av1-grain", - "bitstream-io", - "built", - "cfg-if", - "interpolate_name", - "itertools 0.12.1", - "libc", - "libfuzzer-sys", - "log", - "maybe-rayon", - "new_debug_unreachable", - "noop_proc_macro", - "num-derive", - "num-traits 0.2.19", - "once_cell", - "paste", - "profiling", - "rand 0.8.5", - "rand_chacha 0.3.1", - "simd_helpers", - "system-deps", - "thiserror 1.0.69", - "v_frame", - "wasm-bindgen", -] - -[[package]] -name = "ravif" -version = "0.11.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5825c26fddd16ab9f515930d49028a630efec172e903483c94796cfe31893e6b" -dependencies = [ - "avif-serialize", - "imgref", - "loop9", - "quick-error", - "rav1e", - "rayon", - "rgb", -] - -[[package]] -name = "raw-window-handle" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539" - -[[package]] -name = "rawpointer" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3" - -[[package]] -name = "rayon" -version = "1.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" -dependencies = [ - "either", - "rayon-core", -] - -[[package]] -name = "rayon-core" -version = "1.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" -dependencies = [ - "crossbeam-deque", - "crossbeam-utils", -] - -[[package]] -name = "raytracing" -version = "0.1.0" -dependencies = [ - "csgrs", - "raytracing_cli", -] - -[[package]] -name = "raytracing_cli" -version = "0.1.0" -dependencies = [ - "bevy_render_cli", - "csv", - "glam", - "rand 0.8.5", - "raytracing_config", - "raytracing_core", - "serde", - "toml", -] - -[[package]] -name = "raytracing_config" -version = "0.1.0" -dependencies = [ - "csv", - "glam", - "rand 0.8.5", - "raytracing_core", - "serde", - "toml", -] - -[[package]] -name = "raytracing_core" -version = "0.1.0" -dependencies = [ - "csv", - "glam", - "rand 0.8.5", - "serde", - "toml", -] - -[[package]] -name = "read-fonts" -version = "0.29.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04ca636dac446b5664bd16c069c00a9621806895b8bb02c2dc68542b23b8f25d" -dependencies = [ - "bytemuck", - "font-types", -] - -[[package]] -name = "rectangle-pack" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0d463f2884048e7153449a55166f91028d5b0ea53c79377099ce4e8cf0cf9bb" - -[[package]] -name = "redox_syscall" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" -dependencies = [ - "bitflags 1.3.2", -] - -[[package]] -name = "redox_syscall" -version = "0.5.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77" -dependencies = [ - "bitflags 2.9.1", -] - -[[package]] -name = "regex" -version = "1.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata 0.4.9", - "regex-syntax 0.8.5", -] - -[[package]] -name = "regex-automata" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" -dependencies = [ - "regex-syntax 0.6.29", -] - -[[package]] -name = "regex-automata" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax 0.8.5", -] - -[[package]] -name = "regex-syntax" -version = "0.6.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" - -[[package]] -name = "regex-syntax" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" - -[[package]] -name = "renderdoc-sys" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19b30a45b0cd0bcca8037f3d0dc3421eaf95327a17cad11964fb8179b4fc4832" - -[[package]] -name = "rgb" -version = "0.8.52" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c6a884d2998352bb4daf0183589aec883f16a6da1f4dde84d8e2e9a5409a1ce" - -[[package]] -name = "robust" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e27ee8bb91ca0adcf0ecb116293afa12d393f9c2b9b9cd54d33e8078fe19839" - -[[package]] -name = "rodio" -version = "0.20.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7ceb6607dd738c99bc8cb28eff249b7cd5c8ec88b9db96c0608c1480d140fb1" -dependencies = [ - "cpal", - "lewton", -] - -[[package]] -name = "ron" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b91f7eff05f748767f183df4320a63d6936e9c6107d97c9e6bdd9784f4289c94" -dependencies = [ - "base64 0.21.7", - "bitflags 2.9.1", - "serde", - "serde_derive", -] - -[[package]] -name = "roxmltree" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c20b6793b5c2fa6553b250154b78d6d0db37e72700ae35fad9387a46f487c97" - -[[package]] -name = "rstar" -version = "0.12.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "421400d13ccfd26dfa5858199c30a5d76f9c54e0dba7575273025b43c5175dbb" -dependencies = [ - "heapless", - "num-traits 0.2.19", - "smallvec", -] - -[[package]] -name = "rustc-hash" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" - -[[package]] -name = "rustc-hash" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" - -[[package]] -name = "rustix" -version = "0.38.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" -dependencies = [ - "bitflags 2.9.1", - "errno", - "libc", - "linux-raw-sys 0.4.15", - "windows-sys 0.59.0", -] - -[[package]] -name = "rustix" -version = "1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8" -dependencies = [ - "bitflags 2.9.1", - "errno", - "libc", - "linux-raw-sys 0.9.4", - "windows-sys 0.60.2", -] - -[[package]] -name = "rustversion" -version = "1.0.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" - -[[package]] -name = "rustybuzz" -version = "0.14.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfb9cf8877777222e4a3bc7eb247e398b56baba500c38c1c46842431adc8b55c" -dependencies = [ - "bitflags 2.9.1", - "bytemuck", - "libm", - "smallvec", - "ttf-parser 0.21.1", - "unicode-bidi-mirroring", - "unicode-ccc", - "unicode-properties", - "unicode-script", -] - -[[package]] -name = "ruzstd" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3640bec8aad418d7d03c72ea2de10d5c646a598f9883c7babc160d91e3c1b26c" -dependencies = [ - "twox-hash", -] - -[[package]] -name = "ryu" -version = "1.0.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" - -[[package]] -name = "safe_arch" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96b02de82ddbe1b636e6170c21be622223aea188ef2e139be0a5b219ec215323" -dependencies = [ - "bytemuck", -] - -[[package]] -name = "same-file" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - -[[package]] -name = "self_cell" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f7d95a54511e0c7be3f51e8867aa8cf35148d7b9445d44de2f943e2b206e749" - -[[package]] -name = "send_wrapper" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" - -[[package]] -name = "serde" -version = "1.0.219" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.219" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "serde_json" -version = "1.0.142" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "030fedb782600dcbd6f02d479bf0d817ac3bb40d644745b769d6a96bc3afc5a7" -dependencies = [ - "itoa", - "memchr", - "ryu", - "serde", -] - -[[package]] -name = "serde_spanned" -version = "0.6.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3" -dependencies = [ - "serde", -] - -[[package]] -name = "sharded-slab" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" -dependencies = [ - "lazy_static", -] - -[[package]] -name = "shlex" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" - -[[package]] -name = "simba" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3a386a501cd104797982c15ae17aafe8b9261315b5d07e3ec803f2ea26be0fa" -dependencies = [ - "approx", - "num-complex", - "num-traits 0.2.19", - "paste", - "wide", -] - -[[package]] -name = "simd-adler32" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" - -[[package]] -name = "simd_helpers" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95890f873bec569a0362c235787f3aca6e1e887302ba4840839bcc6459c42da6" -dependencies = [ - "quote", -] - -[[package]] -name = "skrifa" -version = "0.31.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbeb4ca4399663735553a09dd17ce7e49a0a0203f03b706b39628c4d913a8607" -dependencies = [ - "bytemuck", - "read-fonts", -] - -[[package]] -name = "slab" -version = "0.4.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04dc19736151f35336d325007ac991178d504a119863a2fcb3758cdb5e52c50d" - -[[package]] -name = "slotmap" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbff4acf519f630b3a3ddcfaea6c06b42174d9a44bc70c620e9ed1649d58b82a" -dependencies = [ - "version_check", -] - -[[package]] -name = "smallvec" -version = "1.15.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" - -[[package]] -name = "smol_str" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd538fb6910ac1099850255cf94a94df6551fbdd602454387d0adb2d1ca6dead" -dependencies = [ - "serde", -] - -[[package]] -name = "spade" -version = "2.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a14e31a007e9f85c32784b04f89e6e194bb252a4d41b4a8ccd9e77245d901c8c" -dependencies = [ - "hashbrown", - "num-traits 0.2.19", - "robust", - "smallvec", -] - -[[package]] -name = "spin" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" -dependencies = [ - "portable-atomic", -] - -[[package]] -name = "spirv" -version = "0.3.0+sdk-1.3.268.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eda41003dc44290527a59b13432d4a0379379fa074b70174882adfbdfd917844" -dependencies = [ - "bitflags 2.9.1", -] - -[[package]] -name = "stable_deref_trait" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" - -[[package]] -name = "stackfuture" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6eae92052b72ef70dafa16eddbabffc77e5ca3574be2f7bc1127b36f0a7ad7f2" - -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - -[[package]] -name = "stl_io" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cff2e145168af9fef3b518ac0c6f9849c407b3df8a28582ced9f1fda510aa34c" -dependencies = [ - "byteorder", - "float-cmp", -] - -[[package]] -name = "strum" -version = "0.26.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" -dependencies = [ - "strum_macros", -] - -[[package]] -name = "strum_macros" -version = "0.26.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "rustversion", - "syn", -] - -[[package]] -name = "svg" -version = "0.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94afda9cd163c04f6bee8b4bf2501c91548deae308373c436f36aeff3cf3c4a3" - -[[package]] -name = "svg_fmt" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0193cc4331cfd2f3d2011ef287590868599a2f33c3e69bc22c1a3d3acf9e02fb" - -[[package]] -name = "swash" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f745de914febc7c9ab4388dfaf94bbc87e69f57bb41133a9b0c84d4be49856f3" -dependencies = [ - "skrifa", - "yazi", - "zeno", -] - -[[package]] -name = "syn" -version = "2.0.104" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "sys-locale" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eab9a99a024a169fe8a903cf9d4a3b3601109bcc13bd9e3c6fff259138626c4" -dependencies = [ - "libc", -] - -[[package]] -name = "sysinfo" -version = "0.34.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4b93974b3d3aeaa036504b8eefd4c039dced109171c1ae973f1dc63b2c7e4b2" -dependencies = [ - "libc", - "memchr", - "ntapi", - "objc2-core-foundation", - "windows 0.57.0", -] - -[[package]] -name = "system-deps" -version = "6.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e535eb8dded36d55ec13eddacd30dec501792ff23a0b1682c38601b8cf2349" -dependencies = [ - "cfg-expr", - "heck", - "pkg-config", - "toml", - "version-compare", -] - -[[package]] -name = "taffy" -version = "0.7.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab4f4d046dd956a47a7e1a2947083d7ac3e6aa3cfaaead36173ceaa5ab11878c" -dependencies = [ - "arrayvec", - "grid", - "serde", - "slotmap", -] - -[[package]] -name = "target-lexicon" -version = "0.12.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" - -[[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.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" -dependencies = [ - "thiserror-impl 2.0.12", -] - -[[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.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "thread_local" -version = "1.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "tiff" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba1310fcea54c6a9a4fd1aad794ecc02c31682f6bfbecdf460bf19533eed1e3e" -dependencies = [ - "flate2", - "jpeg-decoder", - "weezl", -] - -[[package]] -name = "tinyvec" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09b3661f17e86524eccd4371ab0429194e0d7c008abb45f7a7495b1719463c71" -dependencies = [ - "tinyvec_macros", -] - -[[package]] -name = "tinyvec_macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" - -[[package]] -name = "toml" -version = "0.8.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" -dependencies = [ - "serde", - "serde_spanned", - "toml_datetime", - "toml_edit", -] - -[[package]] -name = "toml_datetime" -version = "0.6.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" -dependencies = [ - "serde", -] - -[[package]] -name = "toml_edit" -version = "0.22.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" -dependencies = [ - "indexmap", - "serde", - "serde_spanned", - "toml_datetime", - "toml_write", - "winnow", -] - -[[package]] -name = "toml_write" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" - -[[package]] -name = "tracing" -version = "0.1.41" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" -dependencies = [ - "pin-project-lite", - "tracing-attributes", - "tracing-core", -] - -[[package]] -name = "tracing-attributes" -version = "0.1.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "tracing-core" -version = "0.1.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" -dependencies = [ - "once_cell", - "valuable", -] - -[[package]] -name = "tracing-log" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" -dependencies = [ - "log", - "once_cell", - "tracing-core", -] - -[[package]] -name = "tracing-oslog" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "528bdd1f0e27b5dd9a4ededf154e824b0532731e4af73bb531de46276e0aab1e" -dependencies = [ - "bindgen 0.70.1", - "cc", - "cfg-if", - "once_cell", - "parking_lot", - "tracing-core", - "tracing-subscriber", -] - -[[package]] -name = "tracing-subscriber" -version = "0.3.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" -dependencies = [ - "matchers", - "nu-ansi-term", - "once_cell", - "regex", - "sharded-slab", - "smallvec", - "thread_local", - "tracing", - "tracing-core", - "tracing-log", -] - -[[package]] -name = "tracing-wasm" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4575c663a174420fa2d78f4108ff68f65bf2fbb7dd89f33749b6e826b3626e07" -dependencies = [ - "tracing", - "tracing-subscriber", - "wasm-bindgen", -] - -[[package]] -name = "ttf-parser" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17f77d76d837a7830fe1d4f12b7b4ba4192c1888001c7164257e4bc6d21d96b4" - -[[package]] -name = "ttf-parser" -version = "0.21.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c591d83f69777866b9126b24c6dd9a18351f177e49d625920d19f989fd31cf8" - -[[package]] -name = "ttf-parser" -version = "0.25.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2df906b07856748fa3f6e0ad0cbaa047052d4a7dd609e231c4f72cee8c36f31" - -[[package]] -name = "ttf-parser-utils" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff2ad77abd4b1ab08adbab7f399be4cc1ff6958421cafa86af75824d9179b5c0" -dependencies = [ - "ttf-parser 0.25.1", -] - -[[package]] -name = "twox-hash" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b907da542cbced5261bd3256de1b3a1bf340a3d37f93425a07362a1d687de56" - -[[package]] -name = "typeid" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c" - -[[package]] -name = "typenum" -version = "1.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" - -[[package]] -name = "unicode-bidi" -version = "0.3.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5" - -[[package]] -name = "unicode-bidi-mirroring" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23cb788ffebc92c5948d0e997106233eeb1d8b9512f93f41651f52b6c5f5af86" - -[[package]] -name = "unicode-ccc" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1df77b101bcc4ea3d78dafc5ad7e4f58ceffe0b2b16bf446aeb50b6cb4157656" - -[[package]] -name = "unicode-ident" -version = "1.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" - -[[package]] -name = "unicode-linebreak" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f" - -[[package]] -name = "unicode-properties" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e70f2a8b45122e719eb623c01822704c4e0907e7e426a05927e1a1cfff5b75d0" - -[[package]] -name = "unicode-script" -version = "0.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb421b350c9aff471779e262955939f565ec18b86c15364e6bdf0d662ca7c1f" - -[[package]] -name = "unicode-segmentation" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" - -[[package]] -name = "unicode-width" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" - -[[package]] -name = "unicode-xid" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + "num-bigint 0.4.6", + "num-integer", + "num-traits 0.2.19", +] [[package]] -name = "uuid" -version = "1.17.0" +name = "num-traits" +version = "0.1.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cf4199d1e5d15ddd86a694e4d0dffa9c323ce759fea589f00fef9d81cc1931d" +checksum = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31" dependencies = [ - "getrandom 0.3.3", - "js-sys", - "serde", - "wasm-bindgen", + "num-traits 0.2.19", ] [[package]] -name = "v_frame" -version = "0.3.9" +name = "num-traits" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "666b7727c8875d6ab5db9533418d7c764233ac9c0cff1d469aec8fa127597be2" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ - "aligned-vec", - "num-traits 0.2.19", - "wasm-bindgen", + "autocfg", + "libm", ] [[package]] -name = "valuable" -version = "0.1.1" +name = "once_cell" +version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" [[package]] -name = "variadics_please" -version = "1.1.0" +name = "ordered-float" +version = "5.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41b6d82be61465f97d42bd1d15bf20f3b0a3a0905018f38f9d6f6962055b0b5c" +checksum = "e2c1f9f56e534ac6a9b8a4600bdf0f530fb393b5f393e7b4d03489c3cf0c3f01" dependencies = [ - "proc-macro2", - "quote", - "syn", + "num-traits 0.2.19", ] [[package]] -name = "vec_map" -version = "0.8.2" +name = "parry3d-f64" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" +checksum = "ed9184cf88474deb3e5ec6c67a8c6fe51ee9572e8c476d44b7de643937a125c5" +dependencies = [ + "approx", + "arrayvec", + "bitflags 2.9.1", + "downcast-rs", + "either", + "ena", + "hashbrown", + "log", + "nalgebra", + "num-derive", + "num-traits 0.2.19", + "ordered-float", + "rstar", + "simba", + "slab", + "spade", + "thiserror 2.0.12", +] [[package]] -name = "version-compare" -version = "0.2.0" +name = "paste" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "852e951cb7832cb45cb1169900d19760cfa39b82bc0ea9c0e5a14ae88411c98b" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" [[package]] -name = "version_check" -version = "0.9.5" +name = "pkg-config" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" +checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" [[package]] -name = "walkdir" -version = "2.5.0" +name = "png" +version = "0.17.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +checksum = "82151a2fc869e011c153adc57cf2789ccb8d9906ce52c0b39a6b5697749d7526" dependencies = [ - "same-file", - "winapi-util", + "bitflags 1.3.2", + "crc32fast", + "fdeflate", + "flate2", + "miniz_oxide", ] [[package]] -name = "wasi" -version = "0.11.1+wasi-snapshot-preview1" +name = "ppv-lite86" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] [[package]] -name = "wasi" -version = "0.14.2+wasi-0.2.4" +name = "proc-macro2" +version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" dependencies = [ - "wit-bindgen-rt", + "unicode-ident", ] [[package]] -name = "wasm-bindgen" -version = "0.2.100" +name = "profiling" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" +checksum = "3eb8486b569e12e2c32ad3e204dbaba5e4b5b216e9367044f25f1dba42341773" dependencies = [ - "cfg-if", - "once_cell", - "rustversion", - "wasm-bindgen-macro", + "profiling-procmacros", ] [[package]] -name = "wasm-bindgen-backend" -version = "0.2.100" +name = "profiling-procmacros" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" +checksum = "52717f9a02b6965224f95ca2a81e2e0c5c43baacd28ca057577988930b6c3d5b" dependencies = [ - "bumpalo", - "log", - "proc-macro2", "quote", "syn", - "wasm-bindgen-shared", ] [[package]] -name = "wasm-bindgen-futures" -version = "0.4.50" +name = "qoi" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" +checksum = "7f6d64c71eb498fe9eae14ce4ec935c555749aef511cca85b5568910d6e48001" dependencies = [ - "cfg-if", - "js-sys", - "once_cell", - "wasm-bindgen", - "web-sys", + "bytemuck", ] [[package]] -name = "wasm-bindgen-macro" -version = "0.2.100" +name = "quick-error" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] +checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" [[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.100" +name = "quote" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" dependencies = [ "proc-macro2", - "quote", - "syn", - "wasm-bindgen-backend", - "wasm-bindgen-shared", ] [[package]] -name = "wasm-bindgen-shared" -version = "0.2.100" +name = "r-efi" +version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" -dependencies = [ - "unicode-ident", -] +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" [[package]] -name = "web-sys" -version = "0.3.77" +name = "rand" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ - "js-sys", - "wasm-bindgen", + "libc", + "rand_chacha", + "rand_core", ] [[package]] -name = "web-time" -version = "1.1.0" +name = "rand_chacha" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ - "js-sys", - "wasm-bindgen", + "ppv-lite86", + "rand_core", ] [[package]] -name = "weezl" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a751b3277700db47d3e574514de2eced5e54dc8a5436a3bf7a0b248b2cee16f3" - -[[package]] -name = "wgpu" -version = "24.0.5" +name = "rand_core" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b0b3436f0729f6cdf2e6e9201f3d39dc95813fad61d826c1ed07918b4539353" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "arrayvec", - "bitflags 2.9.1", - "cfg_aliases", - "document-features", - "js-sys", - "log", - "naga", - "parking_lot", - "profiling", - "raw-window-handle", - "smallvec", - "static_assertions", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "wgpu-core", - "wgpu-hal", - "wgpu-types", + "getrandom 0.2.16", ] [[package]] -name = "wgpu-core" -version = "24.0.5" +name = "rapier3d-f64" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f0aa306497a238d169b9dc70659105b4a096859a34894544ca81719242e1499" +checksum = "75a10d0735644bdc60b54a573a1ba413bab4f4822ce403e4f637f4d0b3d54d6b" dependencies = [ + "approx", "arrayvec", - "bit-vec 0.8.0", + "bit-vec", "bitflags 2.9.1", - "cfg_aliases", - "document-features", - "indexmap", + "crossbeam", + "downcast-rs", "log", - "naga", - "once_cell", - "parking_lot", + "nalgebra", + "num-derive", + "num-traits 0.2.19", + "ordered-float", + "parry3d-f64", "profiling", - "raw-window-handle", - "rustc-hash 1.1.0", - "smallvec", + "rustc-hash", + "simba", "thiserror 2.0.12", - "wgpu-hal", - "wgpu-types", ] [[package]] -name = "wgpu-hal" -version = "24.0.4" +name = "rav1e" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f112f464674ca69f3533248508ee30cb84c67cf06c25ff6800685f5e0294e259" +checksum = "cd87ce80a7665b1cce111f8a16c1f3929f6547ce91ade6addf4ec86a8dda5ce9" dependencies = [ - "android_system_properties", + "arbitrary", + "arg_enum_proc_macro", "arrayvec", - "ash", - "bit-set 0.8.0", - "bitflags 2.9.1", - "block", - "bytemuck", - "cfg_aliases", - "core-graphics-types", - "glow", - "glutin_wgl_sys", - "gpu-alloc", - "gpu-allocator", - "gpu-descriptor", - "js-sys", - "khronos-egl", + "av1-grain", + "bitstream-io", + "built", + "cfg-if", + "interpolate_name", + "itertools 0.12.1", "libc", - "libloading", + "libfuzzer-sys", "log", - "metal", - "naga", - "ndk-sys 0.5.0+25.2.9519653", - "objc", + "maybe-rayon", + "new_debug_unreachable", + "noop_proc_macro", + "num-derive", + "num-traits 0.2.19", "once_cell", - "ordered-float 4.6.0", - "parking_lot", + "paste", "profiling", - "range-alloc", - "raw-window-handle", - "renderdoc-sys", - "rustc-hash 1.1.0", - "smallvec", - "thiserror 2.0.12", + "rand", + "rand_chacha", + "simd_helpers", + "system-deps", + "thiserror 1.0.69", + "v_frame", "wasm-bindgen", - "web-sys", - "wgpu-types", - "windows 0.58.0", - "windows-core 0.58.0", ] [[package]] -name = "wgpu-types" -version = "24.0.0" +name = "ravif" +version = "0.11.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50ac044c0e76c03a0378e7786ac505d010a873665e2d51383dcff8dd227dc69c" +checksum = "5825c26fddd16ab9f515930d49028a630efec172e903483c94796cfe31893e6b" dependencies = [ - "bitflags 2.9.1", - "js-sys", - "log", - "serde", - "web-sys", + "avif-serialize", + "imgref", + "loop9", + "quick-error", + "rav1e", + "rayon", + "rgb", ] [[package]] -name = "wide" -version = "0.7.33" +name = "rawpointer" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ce5da8ecb62bcd8ec8b7ea19f69a51275e91299be594ea5cc6ef7819e16cd03" -dependencies = [ - "bytemuck", - "safe_arch", -] +checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3" [[package]] -name = "winapi" -version = "0.3.9" +name = "rayon" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", + "either", + "rayon-core", ] [[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" +name = "rayon-core" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] [[package]] -name = "winapi-util" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +name = "raytracing" +version = "0.1.0" dependencies = [ - "windows-sys 0.59.0", + "csgrs", + "raytracing_cli", + "raytracing_config", + "raytracing_core", + "raytracing_renderer", ] [[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +name = "raytracing_cli" +version = "0.1.0" +dependencies = [ + "csv", + "glam", + "rand", + "raytracing_config", + "raytracing_core", + "serde", + "toml", +] [[package]] -name = "windows" -version = "0.54.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9252e5725dbed82865af151df558e754e4a3c2c30818359eb17465f1346a1b49" +name = "raytracing_config" +version = "0.1.0" dependencies = [ - "windows-core 0.54.0", - "windows-targets 0.52.6", + "csv", + "glam", + "rand", + "raytracing_core", + "serde", + "toml", ] [[package]] -name = "windows" -version = "0.57.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12342cb4d8e3b046f3d80effd474a7a02447231330ef77d71daa6fbc40681143" +name = "raytracing_core" +version = "0.1.0" dependencies = [ - "windows-core 0.57.0", - "windows-targets 0.52.6", + "csv", + "glam", + "rand", + "serde", + "toml", ] [[package]] -name = "windows" -version = "0.58.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd04d41d93c4992d421894c18c8b43496aa748dd4c081bac0dc93eb0489272b6" +name = "raytracing_renderer" +version = "0.1.0" dependencies = [ - "windows-core 0.58.0", - "windows-targets 0.52.6", + "glam", + "image", + "rand", + "rayon", + "raytracing_config", + "raytracing_core", ] [[package]] -name = "windows" -version = "0.61.3" +name = "rgb" +version = "0.8.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893" -dependencies = [ - "windows-collections", - "windows-core 0.61.2", - "windows-future", - "windows-link", - "windows-numerics", -] +checksum = "0c6a884d2998352bb4daf0183589aec883f16a6da1f4dde84d8e2e9a5409a1ce" [[package]] -name = "windows-collections" -version = "0.2.0" +name = "robust" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8" -dependencies = [ - "windows-core 0.61.2", -] +checksum = "4e27ee8bb91ca0adcf0ecb116293afa12d393f9c2b9b9cd54d33e8078fe19839" [[package]] -name = "windows-core" -version = "0.54.0" +name = "rstar" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12661b9c89351d684a50a8a643ce5f608e20243b9fb84687800163429f161d65" +checksum = "421400d13ccfd26dfa5858199c30a5d76f9c54e0dba7575273025b43c5175dbb" dependencies = [ - "windows-result 0.1.2", - "windows-targets 0.52.6", + "heapless", + "num-traits 0.2.19", + "smallvec", ] [[package]] -name = "windows-core" -version = "0.57.0" +name = "rustc-hash" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2ed2439a290666cd67ecce2b0ffaad89c2a56b976b736e6ece670297897832d" -dependencies = [ - "windows-implement 0.57.0", - "windows-interface 0.57.0", - "windows-result 0.1.2", - "windows-targets 0.52.6", -] +checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" [[package]] -name = "windows-core" -version = "0.58.0" +name = "rustversion" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ba6d44ec8c2591c134257ce647b7ea6b20335bf6379a27dac5f1641fcf59f99" -dependencies = [ - "windows-implement 0.58.0", - "windows-interface 0.58.0", - "windows-result 0.2.0", - "windows-strings 0.1.0", - "windows-targets 0.52.6", -] +checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" [[package]] -name = "windows-core" -version = "0.61.2" +name = "ryu" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" -dependencies = [ - "windows-implement 0.60.0", - "windows-interface 0.59.1", - "windows-link", - "windows-result 0.3.4", - "windows-strings 0.4.2", -] +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" [[package]] -name = "windows-future" -version = "0.2.1" +name = "safe_arch" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e" +checksum = "96b02de82ddbe1b636e6170c21be622223aea188ef2e139be0a5b219ec215323" dependencies = [ - "windows-core 0.61.2", - "windows-link", - "windows-threading", + "bytemuck", ] [[package]] -name = "windows-implement" -version = "0.57.0" +name = "serde" +version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7" +checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" dependencies = [ - "proc-macro2", - "quote", - "syn", + "serde_derive", ] [[package]] -name = "windows-implement" -version = "0.58.0" +name = "serde_derive" +version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b" +checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" dependencies = [ "proc-macro2", "quote", @@ -5815,441 +1525,424 @@ dependencies = [ ] [[package]] -name = "windows-implement" -version = "0.60.0" +name = "serde_spanned" +version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" +checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3" dependencies = [ - "proc-macro2", - "quote", - "syn", + "serde", ] [[package]] -name = "windows-interface" -version = "0.57.0" +name = "shlex" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] -name = "windows-interface" -version = "0.58.0" +name = "simba" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515" +checksum = "b3a386a501cd104797982c15ae17aafe8b9261315b5d07e3ec803f2ea26be0fa" dependencies = [ - "proc-macro2", - "quote", - "syn", + "approx", + "num-complex", + "num-traits 0.2.19", + "paste", + "wide", ] [[package]] -name = "windows-interface" -version = "0.59.1" +name = "simd-adler32" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" +checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" + +[[package]] +name = "simd_helpers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95890f873bec569a0362c235787f3aca6e1e887302ba4840839bcc6459c42da6" dependencies = [ - "proc-macro2", "quote", - "syn", ] [[package]] -name = "windows-link" -version = "0.1.3" +name = "slab" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" +checksum = "04dc19736151f35336d325007ac991178d504a119863a2fcb3758cdb5e52c50d" [[package]] -name = "windows-numerics" -version = "0.2.0" +name = "smallvec" +version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1" -dependencies = [ - "windows-core 0.61.2", - "windows-link", -] +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" [[package]] -name = "windows-result" -version = "0.1.2" +name = "spade" +version = "2.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8" +checksum = "a14e31a007e9f85c32784b04f89e6e194bb252a4d41b4a8ccd9e77245d901c8c" dependencies = [ - "windows-targets 0.52.6", + "hashbrown", + "num-traits 0.2.19", + "robust", + "smallvec", ] [[package]] -name = "windows-result" -version = "0.2.0" +name = "stable_deref_trait" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" -dependencies = [ - "windows-targets 0.52.6", -] +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" [[package]] -name = "windows-result" -version = "0.3.4" +name = "static_assertions" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" -dependencies = [ - "windows-link", -] +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] -name = "windows-strings" -version = "0.1.0" +name = "stl_io" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" +checksum = "cff2e145168af9fef3b518ac0c6f9849c407b3df8a28582ced9f1fda510aa34c" dependencies = [ - "windows-result 0.2.0", - "windows-targets 0.52.6", + "byteorder", + "float-cmp", ] [[package]] -name = "windows-strings" -version = "0.4.2" +name = "svg" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" +checksum = "94afda9cd163c04f6bee8b4bf2501c91548deae308373c436f36aeff3cf3c4a3" + +[[package]] +name = "syn" +version = "2.0.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40" dependencies = [ - "windows-link", + "proc-macro2", + "quote", + "unicode-ident", ] [[package]] -name = "windows-sys" -version = "0.45.0" +name = "system-deps" +version = "6.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +checksum = "a3e535eb8dded36d55ec13eddacd30dec501792ff23a0b1682c38601b8cf2349" dependencies = [ - "windows-targets 0.42.2", + "cfg-expr", + "heck", + "pkg-config", + "toml", + "version-compare", ] [[package]] -name = "windows-sys" -version = "0.52.0" +name = "target-lexicon" +version = "0.12.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" + +[[package]] +name = "thiserror" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ - "windows-targets 0.52.6", + "thiserror-impl 1.0.69", ] [[package]] -name = "windows-sys" -version = "0.59.0" +name = "thiserror" +version = "2.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" dependencies = [ - "windows-targets 0.52.6", + "thiserror-impl 2.0.12", ] [[package]] -name = "windows-sys" -version = "0.60.2" +name = "thiserror-impl" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ - "windows-targets 0.53.3", + "proc-macro2", + "quote", + "syn", ] [[package]] -name = "windows-targets" -version = "0.42.2" +name = "thiserror-impl" +version = "2.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", + "proc-macro2", + "quote", + "syn", ] [[package]] -name = "windows-targets" -version = "0.48.5" +name = "tiff" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +checksum = "ba1310fcea54c6a9a4fd1aad794ecc02c31682f6bfbecdf460bf19533eed1e3e" dependencies = [ - "windows_aarch64_gnullvm 0.48.5", - "windows_aarch64_msvc 0.48.5", - "windows_i686_gnu 0.48.5", - "windows_i686_msvc 0.48.5", - "windows_x86_64_gnu 0.48.5", - "windows_x86_64_gnullvm 0.48.5", - "windows_x86_64_msvc 0.48.5", + "flate2", + "jpeg-decoder", + "weezl", ] [[package]] -name = "windows-targets" -version = "0.52.6" +name = "toml" +version = "0.8.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" dependencies = [ - "windows_aarch64_gnullvm 0.52.6", - "windows_aarch64_msvc 0.52.6", - "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm 0.52.6", - "windows_i686_msvc 0.52.6", - "windows_x86_64_gnu 0.52.6", - "windows_x86_64_gnullvm 0.52.6", - "windows_x86_64_msvc 0.52.6", + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit", ] [[package]] -name = "windows-targets" -version = "0.53.3" +name = "toml_datetime" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91" +checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" dependencies = [ - "windows-link", - "windows_aarch64_gnullvm 0.53.0", - "windows_aarch64_msvc 0.53.0", - "windows_i686_gnu 0.53.0", - "windows_i686_gnullvm 0.53.0", - "windows_i686_msvc 0.53.0", - "windows_x86_64_gnu 0.53.0", - "windows_x86_64_gnullvm 0.53.0", - "windows_x86_64_msvc 0.53.0", + "serde", ] [[package]] -name = "windows-threading" -version = "0.1.0" +name = "toml_edit" +version = "0.22.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b66463ad2e0ea3bbf808b7f1d371311c80e115c0b71d60efc142cafbcfb057a6" +checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" dependencies = [ - "windows-link", + "indexmap", + "serde", + "serde_spanned", + "toml_datetime", + "toml_write", + "winnow", ] [[package]] -name = "windows_aarch64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" - -[[package]] -name = "windows_i686_gnu" -version = "0.42.2" +name = "toml_write" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" +checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" [[package]] -name = "windows_i686_gnu" -version = "0.48.5" +name = "ttf-parser" +version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" +checksum = "d2df906b07856748fa3f6e0ad0cbaa047052d4a7dd609e231c4f72cee8c36f31" [[package]] -name = "windows_i686_gnu" -version = "0.52.6" +name = "ttf-parser-utils" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" +checksum = "ff2ad77abd4b1ab08adbab7f399be4cc1ff6958421cafa86af75824d9179b5c0" +dependencies = [ + "ttf-parser", +] [[package]] -name = "windows_i686_gnu" -version = "0.53.0" +name = "typenum" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" +checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" [[package]] -name = "windows_i686_gnullvm" -version = "0.52.6" +name = "unicode-ident" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" [[package]] -name = "windows_i686_gnullvm" -version = "0.53.0" +name = "uuid" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" +checksum = "3cf4199d1e5d15ddd86a694e4d0dffa9c323ce759fea589f00fef9d81cc1931d" +dependencies = [ + "getrandom 0.3.3", + "js-sys", + "serde", + "wasm-bindgen", +] [[package]] -name = "windows_i686_msvc" -version = "0.42.2" +name = "v_frame" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" +checksum = "666b7727c8875d6ab5db9533418d7c764233ac9c0cff1d469aec8fa127597be2" +dependencies = [ + "aligned-vec", + "num-traits 0.2.19", + "wasm-bindgen", +] [[package]] -name = "windows_i686_msvc" -version = "0.48.5" +name = "version-compare" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" +checksum = "852e951cb7832cb45cb1169900d19760cfa39b82bc0ea9c0e5a14ae88411c98b" [[package]] -name = "windows_i686_msvc" -version = "0.52.6" +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] -name = "windows_i686_msvc" -version = "0.53.0" +name = "wasi" +version = "0.14.2+wasi-0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" +checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +dependencies = [ + "wit-bindgen-rt", +] [[package]] -name = "windows_x86_64_gnu" -version = "0.42.2" +name = "wasm-bindgen" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" +checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", +] [[package]] -name = "windows_x86_64_gnu" -version = "0.48.5" +name = "wasm-bindgen-backend" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" +checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" +dependencies = [ + "bumpalo", + "log", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] [[package]] -name = "windows_x86_64_gnu" -version = "0.52.6" +name = "wasm-bindgen-macro" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" +checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] [[package]] -name = "windows_x86_64_gnu" -version = "0.53.0" +name = "wasm-bindgen-macro-support" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" +checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] [[package]] -name = "windows_x86_64_gnullvm" -version = "0.42.2" +name = "wasm-bindgen-shared" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" +checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +dependencies = [ + "unicode-ident", +] [[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.5" +name = "weezl" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" +checksum = "a751b3277700db47d3e574514de2eced5e54dc8a5436a3bf7a0b248b2cee16f3" [[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.6" +name = "wide" +version = "0.7.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" +checksum = "0ce5da8ecb62bcd8ec8b7ea19f69a51275e91299be594ea5cc6ef7819e16cd03" +dependencies = [ + "bytemuck", + "safe_arch", +] [[package]] -name = "windows_x86_64_gnullvm" -version = "0.53.0" +name = "windows-core" +version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" +checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link", + "windows-result", + "windows-strings", +] [[package]] -name = "windows_x86_64_msvc" -version = "0.42.2" +name = "windows-implement" +version = "0.60.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" +checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] [[package]] -name = "windows_x86_64_msvc" -version = "0.48.5" +name = "windows-interface" +version = "0.59.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" +checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] [[package]] -name = "windows_x86_64_msvc" -version = "0.52.6" +name = "windows-link" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" [[package]] -name = "windows_x86_64_msvc" -version = "0.53.0" +name = "windows-result" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" +checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" +dependencies = [ + "windows-link", +] [[package]] -name = "winit" -version = "0.30.12" +name = "windows-strings" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c66d4b9ed69c4009f6321f762d6e61ad8a2389cd431b97cb1e146812e9e6c732" +checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" dependencies = [ - "android-activity", - "atomic-waker", - "bitflags 2.9.1", - "block2", - "bytemuck", - "calloop", - "cfg_aliases", - "concurrent-queue", - "core-foundation 0.9.4", - "core-graphics", - "cursor-icon", - "dpi", - "js-sys", - "libc", - "ndk 0.9.0", - "objc2", - "objc2-app-kit", - "objc2-foundation", - "objc2-ui-kit", - "orbclient", - "percent-encoding", - "pin-project", - "raw-window-handle", - "redox_syscall 0.4.1", - "rustix 0.38.44", - "smol_str", - "tracing", - "unicode-segmentation", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "web-time", - "windows-sys 0.52.0", - "x11-dl", - "x11rb", - "xkbcommon-dl", + "windows-link", ] [[package]] @@ -6270,57 +1963,6 @@ dependencies = [ "bitflags 2.9.1", ] -[[package]] -name = "x11-dl" -version = "2.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38735924fedd5314a6e548792904ed8c6de6636285cb9fec04d5b1db85c1516f" -dependencies = [ - "libc", - "once_cell", - "pkg-config", -] - -[[package]] -name = "x11rb" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d91ffca73ee7f68ce055750bf9f6eca0780b8c85eff9bc046a3b0da41755e12" -dependencies = [ - "as-raw-xcb-connection", - "gethostname", - "libc", - "libloading", - "once_cell", - "rustix 0.38.44", - "x11rb-protocol", -] - -[[package]] -name = "x11rb-protocol" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec107c4503ea0b4a98ef47356329af139c0a4f7750e621cf2973cd3385ebcb3d" - -[[package]] -name = "xkbcommon-dl" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d039de8032a9a8856a6be89cea3e5d12fdd82306ab7c94d74e6deab2460651c5" -dependencies = [ - "bitflags 2.9.1", - "dlib", - "log", - "once_cell", - "xkeysym", -] - -[[package]] -name = "xkeysym" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9cc00251562a284751c9973bace760d86c0276c471b4be569fe6b068ee97a56" - [[package]] name = "xml-rs" version = "0.7.0" @@ -6330,33 +1972,15 @@ dependencies = [ "bitflags 1.3.2", ] -[[package]] -name = "xml-rs" -version = "0.8.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fd8403733700263c6eb89f192880191f1b83e332f7a20371ddcf421c4a337c7" - [[package]] name = "xmltree" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff8eaee9d17062850f1e6163b509947969242990ee59a35801af437abe041e70" dependencies = [ - "xml-rs 0.7.0", + "xml-rs", ] -[[package]] -name = "yazi" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e01738255b5a16e78bbb83e7fbba0a1e7dd506905cfc53f4622d89015a03fbb5" - -[[package]] -name = "zeno" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6df3dc4292935e51816d896edcd52aa30bc297907c26167fec31e2b0c6a32524" - [[package]] name = "zerocopy" version = "0.8.26" diff --git a/Cargo.toml b/Cargo.toml index 2f2a05e..ed4cbb4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,10 +12,13 @@ resolver = "2" raytracing_core = { path = "./crates/raytracing_core" } raytracing_config = { path = "./crates/raytracing_config" } raytracing_cli = { path = "./crates/raytracing_cli" } -bevy_render_cli = {path = "./crates/bevy_render_cli"} -bevy_render_core = {path = "./crates/bevy_render_core"} -bevy_render_config = {path = "./crates/bevy_render_config"} +raytracing_renderer = { path = "./crates/raytracing_renderer" } +glam = { version = "0.29.0", features = ["serde"] } + [dependencies] csgrs = "0.20.1" raytracing_cli.workspace = true +raytracing_renderer.workspace = true +raytracing_core.workspace = true +raytracing_config.workspace = true diff --git a/crates/bevy_render_cli/Cargo.toml b/crates/bevy_render_cli/Cargo.toml deleted file mode 100644 index f30377b..0000000 --- a/crates/bevy_render_cli/Cargo.toml +++ /dev/null @@ -1,15 +0,0 @@ -[package] -name = "bevy_render_cli" -version = "0.1.0" -edition = "2024" - - -[dependencies] -bevy = "0.16.1" -rand = "0.8.3" -glam = "0.29.0" -csv = "1.3" -serde = { version = "1.0", features = ["derive"] } -toml = "0.8" -raytracing_core.workspace = true -bevy_render_core.workspace = true \ No newline at end of file diff --git a/crates/bevy_render_cli/src/bevy_render_cli.rs b/crates/bevy_render_cli/src/bevy_render_cli.rs deleted file mode 100644 index 3ac9e9c..0000000 --- a/crates/bevy_render_cli/src/bevy_render_cli.rs +++ /dev/null @@ -1,8 +0,0 @@ -use bevy::prelude::*; -use bevy_render_core::render_core; -use raytracing_core::Scene; -pub fn render_cli(scene: Scene, results: Vec>) -> Result<(), Box> { - println!("レンダー起動"); - render_core(scene, results); - Ok(()) -} diff --git a/crates/bevy_render_cli/src/lib.rs b/crates/bevy_render_cli/src/lib.rs deleted file mode 100644 index 75d4d95..0000000 --- a/crates/bevy_render_cli/src/lib.rs +++ /dev/null @@ -1,3 +0,0 @@ -pub mod bevy_render_cli; - -pub use bevy_render_cli::*; diff --git a/crates/bevy_render_config/Cargo.toml b/crates/bevy_render_config/Cargo.toml deleted file mode 100644 index 7d5d423..0000000 --- a/crates/bevy_render_config/Cargo.toml +++ /dev/null @@ -1,14 +0,0 @@ -[package] -name = "bevy_render_config" -version = "0.1.0" -edition = "2024" - - -[dependencies] -bevy = "0.16.1" -rand = "0.8.3" -glam = "0.29.0" -csv = "1.3" -serde = { version = "1.0", features = ["derive"] } -toml = "0.8" -raytracing_core.workspace = true diff --git a/crates/bevy_render_config/src/bevy_render_config.rs b/crates/bevy_render_config/src/bevy_render_config.rs deleted file mode 100644 index d3f5a12..0000000 --- a/crates/bevy_render_config/src/bevy_render_config.rs +++ /dev/null @@ -1 +0,0 @@ - diff --git a/crates/bevy_render_config/src/lib.rs b/crates/bevy_render_config/src/lib.rs deleted file mode 100644 index 38b0400..0000000 --- a/crates/bevy_render_config/src/lib.rs +++ /dev/null @@ -1,3 +0,0 @@ -pub mod bevy_render_config; - -pub use bevy_render_config::*; diff --git a/crates/bevy_render_core/Cargo.toml b/crates/bevy_render_core/Cargo.toml deleted file mode 100644 index 83c7e73..0000000 --- a/crates/bevy_render_core/Cargo.toml +++ /dev/null @@ -1,17 +0,0 @@ -[package] -name = "bevy_render_core" -version = "0.1.0" -edition = "2024" - - -[dependencies] -bevy = "0.16.1" -rand = "0.9.2" -glam = "0.29.0" -csv = "1.3" -serde = { version = "1.0", features = ["derive"] } -toml = "0.8" -raytracing_core.workspace = true -bevy_panorbit_camera = "0.27" -bevy_flycam = "0.16.1" -csgrs = { version = "0.20.1", features = ["bevymesh"] } \ No newline at end of file diff --git a/crates/bevy_render_core/src/beby_trait.rs b/crates/bevy_render_core/src/beby_trait.rs deleted file mode 100644 index baa82b2..0000000 --- a/crates/bevy_render_core/src/beby_trait.rs +++ /dev/null @@ -1,5 +0,0 @@ -type Csmesh = csgrs::mesh::Mesh<()>; -use raytracing_core::Hittable; -pub trait Hittable_beby: Hittable { - fn to_mesh(&self) -> Option; -} diff --git a/crates/bevy_render_core/src/bevy_render_core.rs b/crates/bevy_render_core/src/bevy_render_core.rs deleted file mode 100644 index 762be4d..0000000 --- a/crates/bevy_render_core/src/bevy_render_core.rs +++ /dev/null @@ -1,128 +0,0 @@ -use bevy::pbr::{DirectionalLight, StandardMaterial}; -use bevy::prelude::*; -use bevy_flycam::prelude::*; -use bevy_panorbit_camera::{PanOrbitCamera, PanOrbitCameraPlugin}; -use csgrs::traits::CSG; -use rand::{self, Rng}; -use raytracing_core::{Hittable, InfiniteCone, Scene}; -type Csmesh = csgrs::mesh::Mesh<()>; -#[derive(Resource)] -pub struct RenderScene(pub Scene); -#[derive(Resource)] -pub struct PathData(pub Vec>); - -pub fn render_core( - scene: Scene, - results: Vec>, -) -> Result<(), Box> { - render_main(scene, results); - Ok(()) -} - -fn render_main(scene: Scene, results: Vec>) { - App::new() - .add_plugins(DefaultPlugins) - .add_plugins(PanOrbitCameraPlugin) - .add_plugins(PlayerPlugin) - .insert_resource(RenderScene(scene)) - .insert_resource(PathData(results)) - .add_systems(Startup, setup) - .run(); -} - -fn setup( - render_scene: Res, - path_data: Res, - mut commands: Commands, - mut meshes: ResMut>, - mut materials: ResMut>, -) { - let scene = &render_scene.0; - let results = &path_data.0; - // 光の軌跡の描画 - spawn_arrows(&mut commands, &mut meshes, &mut materials, results); - commands.spawn(DirectionalLight { - shadows_enabled: true, - ..default() - }); - //commands.spawn((Camera3d::default(),)); -} - -fn spawn_object( - scene: &Scene, - materials: &mut ResMut>, - meshes: &mut ResMut>, - commands: &mut Commands, -) { - let object_material = materials.add(Color::srgb(0.8, 0.7, 0.6)); -} - -fn spawn_arrows( - commands: &mut Commands, - meshes: &mut ResMut>, - materials: &mut ResMut>, - results: &Vec>, -) { - let mut arrow_material = materials.add(Color::srgb(0.1, 0.1, 0.1)); - - for arrows in results { - let mut rng = rand::rng(); - let r: f32 = rng.random::(); - let g: f32 = rng.random::(); - let b: f32 = rng.random::(); - let random_color = Color::srgb(r, g, b); - arrow_material = materials.add(random_color); - for pair in arrows.windows(2) { - spawn_arrow( - commands, - meshes, - arrow_material.clone(), - pair[0].into(), - pair[1].into(), - ); - } - } -} - -fn spawn_arrow( - commands: &mut Commands, - meshes: &mut ResMut>, - material: Handle, - start: Vec3, - end: Vec3, -) { - let direction = end - start; - let half_length = direction.length() / 2.0; - if half_length < 0.001 { - return; - } - - let mid_point = start + direction / 2.0; - let rotation = Quat::from_rotation_arc(Vec3::Y, direction.normalize()); - commands.spawn(( - Mesh3d(meshes.add(Cylinder { - radius: 0.02, - half_height: half_length, - })), - MeshMaterial3d(material.clone()), - Transform { - translation: mid_point, - rotation, - ..default() - }, - )); - - // 矢印の先端 - commands.spawn(( - Mesh3d(meshes.add(Cone { - radius: 0.08, - height: 0.2, - })), - MeshMaterial3d(material), - Transform { - translation: end, - rotation, - ..default() - }, - )); -} diff --git a/crates/bevy_render_core/src/lib.rs b/crates/bevy_render_core/src/lib.rs deleted file mode 100644 index 0a3f0f1..0000000 --- a/crates/bevy_render_core/src/lib.rs +++ /dev/null @@ -1,6 +0,0 @@ -pub mod beby_trait; -pub mod bevy_render_core; -pub mod render_primitives; - -pub use beby_trait::*; -pub use bevy_render_core::*; diff --git a/crates/bevy_render_core/src/render_primitives/mod.rs b/crates/bevy_render_core/src/render_primitives/mod.rs deleted file mode 100644 index a6b6699..0000000 --- a/crates/bevy_render_core/src/render_primitives/mod.rs +++ /dev/null @@ -1,46 +0,0 @@ -// このファイルは、primitivesモジュールに含まれる他のファイルを宣言し、 -// それらの中の公開アイテム(pub)を、このモジュールの外からも使えるようにします。 - -// 各プリミティブのモジュールを宣言 -mod render_axis_aligned_box; -mod render_csg; -mod render_infinite_cone; -mod render_infinite_cylinder; -mod render_lens; -mod render_plane; -mod render_sphere; -mod render_wedge; - -// 各モジュール内の公開アイテムを、primitives::* で使えるように再公開(re-export)する -//pub use render_axis_aligned_box::AxisAlignedBox; -//pub use render_csg::CSGObject; -//pub use render_infinite_cone::InfiniteCone; -//pub use render_infinite_cylinder::InfiniteCylinder; -//pub use render_lens::Lens; -//pub use render_plane::Plane; -//pub use render_sphere::Sphere; -//pub use render_wedge::Wedge; - -use raytracing_core::HitRecord; -use raytracing_core::Ray; -// ブーリアン演算の種類 -#[derive(Debug, Copy, Clone, PartialEq)] -pub enum CsgOperation { - /// 和集合 - Union, - /// 積集合 - Intersection, - /// 差集合 - Difference, -} - -#[derive(Debug, Clone, Copy, PartialEq)] -pub enum Material { - Mirror, - Glass { ior: f32 }, - HalfMirror { reflectance: f32 }, -} - -pub trait Hittable { - fn intersect_all(&self, ray: &Ray, t_min: f32, t_max: f32) -> Option>; -} diff --git a/crates/bevy_render_core/src/render_primitives/render_axis_aligned_box.rs b/crates/bevy_render_core/src/render_primitives/render_axis_aligned_box.rs deleted file mode 100644 index d3f5a12..0000000 --- a/crates/bevy_render_core/src/render_primitives/render_axis_aligned_box.rs +++ /dev/null @@ -1 +0,0 @@ - diff --git a/crates/bevy_render_core/src/render_primitives/render_csg.rs b/crates/bevy_render_core/src/render_primitives/render_csg.rs deleted file mode 100644 index d3f5a12..0000000 --- a/crates/bevy_render_core/src/render_primitives/render_csg.rs +++ /dev/null @@ -1 +0,0 @@ - diff --git a/crates/bevy_render_core/src/render_primitives/render_infinite_cone.rs b/crates/bevy_render_core/src/render_primitives/render_infinite_cone.rs deleted file mode 100644 index d3f5a12..0000000 --- a/crates/bevy_render_core/src/render_primitives/render_infinite_cone.rs +++ /dev/null @@ -1 +0,0 @@ - diff --git a/crates/bevy_render_core/src/render_primitives/render_infinite_cylinder.rs b/crates/bevy_render_core/src/render_primitives/render_infinite_cylinder.rs deleted file mode 100644 index d3f5a12..0000000 --- a/crates/bevy_render_core/src/render_primitives/render_infinite_cylinder.rs +++ /dev/null @@ -1 +0,0 @@ - diff --git a/crates/bevy_render_core/src/render_primitives/render_lens.rs b/crates/bevy_render_core/src/render_primitives/render_lens.rs deleted file mode 100644 index d3f5a12..0000000 --- a/crates/bevy_render_core/src/render_primitives/render_lens.rs +++ /dev/null @@ -1 +0,0 @@ - diff --git a/crates/bevy_render_core/src/render_primitives/render_plane.rs b/crates/bevy_render_core/src/render_primitives/render_plane.rs deleted file mode 100644 index 8b13789..0000000 --- a/crates/bevy_render_core/src/render_primitives/render_plane.rs +++ /dev/null @@ -1 +0,0 @@ - diff --git a/crates/bevy_render_core/src/render_primitives/render_sphere.rs b/crates/bevy_render_core/src/render_primitives/render_sphere.rs deleted file mode 100644 index d3f5a12..0000000 --- a/crates/bevy_render_core/src/render_primitives/render_sphere.rs +++ /dev/null @@ -1 +0,0 @@ - diff --git a/crates/bevy_render_core/src/render_primitives/render_wedge.rs b/crates/bevy_render_core/src/render_primitives/render_wedge.rs deleted file mode 100644 index d3f5a12..0000000 --- a/crates/bevy_render_core/src/render_primitives/render_wedge.rs +++ /dev/null @@ -1 +0,0 @@ - diff --git a/crates/raytracing_cli/Cargo.toml b/crates/raytracing_cli/Cargo.toml index 55441cf..97cb28e 100644 --- a/crates/raytracing_cli/Cargo.toml +++ b/crates/raytracing_cli/Cargo.toml @@ -12,5 +12,4 @@ csv = "1.3" serde = { version = "1.0", features = ["derive"] } toml = "0.8" raytracing_core.workspace = true -raytracing_config.workspace = true -bevy_render_cli.workspace = true \ No newline at end of file +raytracing_config.workspace = true \ No newline at end of file diff --git a/crates/raytracing_cli/src/cli.rs b/crates/raytracing_cli/src/cli.rs index 040d7a7..06afd74 100644 --- a/crates/raytracing_cli/src/cli.rs +++ b/crates/raytracing_cli/src/cli.rs @@ -1,32 +1,69 @@ -use bevy_render_cli::render_cli; -use csv::Writer; +use glam::Vec3; use raytracing_config::simulation_config::SimulationConfig; use raytracing_core::Scene; use std::error::Error; +use std::fs::File; +use std::io::{Result as IoResult, Write}; + +/// Exports the calculated ray paths to a .obj file as a series of line segments. +fn export_paths_to_obj(results: &Vec>, filename: &str) -> IoResult<()> { + let mut file = File::create(filename)?; + + writeln!( + file, + "# Light path visualization generated by raytracing-cli" + )?; + writeln!(file, "# Vertices")?; + + // Write all points from all paths as vertices + for path in results { + for point in path { + writeln!(file, "v {} {} {}", point.x, point.y, point.z)?; + } + } + + writeln!(file, "\n# Line segments")?; + let mut vertex_offset = 1; // OBJ indices are 1-based + for path in results { + if path.len() > 1 { + // Create line segments between consecutive vertices in the current path + for i in 0..path.len() - 1 { + writeln!(file, "l {} {}", vertex_offset + i, vertex_offset + i + 1)?; + } + } + // Increase the offset for the next path's indices + vertex_offset += path.len(); + } + + println!("\n光路を {} にエクスポートしました。", filename); + Ok(()) +} pub fn cli() -> Result<(), Box> { println!("設定ファイル simulation.toml を読み込んでいます..."); let SimulationConfig { scene, simulation_settings, + .. } = SimulationConfig::load_from_path("simulation.toml")?; let scene: Scene = scene.into(); let results = scene.simulate_rays(simulation_settings.into()); - render_cli(scene, results.clone()); - // --- 3c. 結果を光路ごとに別々のCSVファイルに出力 --- - for (i, result) in results.into_iter().enumerate() { - let file_name = format!("./dist/path_{}.csv", i); - let mut wtr = Writer::from_path(&file_name)?; - wtr.write_record(&["x", "y", "z"])?; - for point in result { - wtr.write_record(&[ - point.x.to_string(), - point.y.to_string(), - point.z.to_string(), - ])?; + + println!("光路の計算が完了しました。"); + println!("計算された光路の数: {}", results.len()); + for (i, path) in results.iter().enumerate() { + println!("--- 光路 {} ---", i); + for (j, point) in path.iter().enumerate() { + println!( + " 点 {}: ({:.3}, {:.3}, {:.3})", + j, point.x, point.y, point.z + ); } - wtr.flush()?; - println!("光路 {} を '{}' に出力しました。", i, file_name); + } + + // Export the results to an OBJ file + if let Err(e) = export_paths_to_obj(&results, "paths.obj") { + eprintln!("OBJファイルのエクスポートに失敗しました: {}", e); } Ok(()) diff --git a/crates/raytracing_config/src/model.rs b/crates/raytracing_config/src/model.rs index b1f7570..dddfab1 100644 --- a/crates/raytracing_config/src/model.rs +++ b/crates/raytracing_config/src/model.rs @@ -7,3 +7,4 @@ pub mod shape_config; pub mod simulation_config; pub mod simulation_settings_config; pub mod transform_config; +pub mod camera_config; diff --git a/crates/raytracing_config/src/model/camera_config.rs b/crates/raytracing_config/src/model/camera_config.rs new file mode 100644 index 0000000..7d20371 --- /dev/null +++ b/crates/raytracing_config/src/model/camera_config.rs @@ -0,0 +1,31 @@ +use glam::Vec3; +use serde::Deserialize; + +#[derive(Debug, Deserialize, Clone, Copy)] +pub struct CameraConfig { + pub lookfrom: Vec3, + pub lookat: Vec3, + #[serde(default = "default_vup")] + pub vup: Vec3, + #[serde(default = "default_vfov")] + pub vfov: f32, +} + +fn default_vup() -> Vec3 { + Vec3::Y +} + +fn default_vfov() -> f32 { + 40.0 +} + +impl Default for CameraConfig { + fn default() -> Self { + Self { + lookfrom: Vec3::new(0.0, 0.0, 25.0), + lookat: Vec3::new(0.0, 0.0, 0.0), + vup: default_vup(), + vfov: default_vfov(), + } + } +} diff --git a/crates/raytracing_config/src/model/material_config.rs b/crates/raytracing_config/src/model/material_config.rs index 8dd2404..b1c0f6b 100644 --- a/crates/raytracing_config/src/model/material_config.rs +++ b/crates/raytracing_config/src/model/material_config.rs @@ -1,3 +1,4 @@ +use glam::Vec3; use serde::Deserialize; use raytracing_core::Material; @@ -5,17 +6,29 @@ use raytracing_core::Material; #[derive(Deserialize, Clone, Copy)] // 材質はコピーするのでClone, Copyも #[serde(tag = "type")] pub enum MaterialConfig { - Glass { ior: f32 }, + Glass { + #[serde(default = "default_glass_color")] + color: Vec3, + ior: f32, + }, HalfMirror { reflectance: f32 }, - Mirror, + Metal { color: Vec3, fuzz: f32 }, + Diffuse { color: Vec3 }, + Light { color: Vec3 }, } -impl Into for MaterialConfig { - fn into(self) -> Material { - match self { - MaterialConfig::Mirror => Material::Mirror, - MaterialConfig::Glass { ior } => Material::Glass { ior }, +fn default_glass_color() -> Vec3 { + Vec3::ONE +} + +impl From for Material { + fn from(config: MaterialConfig) -> Material { + match config { + MaterialConfig::Metal { color, fuzz } => Material::Metal { color, fuzz }, + MaterialConfig::Glass { color, ior } => Material::Glass { color, ior }, MaterialConfig::HalfMirror { reflectance } => Material::HalfMirror { reflectance }, + MaterialConfig::Diffuse { color } => Material::Diffuse { color }, + MaterialConfig::Light { color } => Material::Light { color }, } } } diff --git a/crates/raytracing_config/src/model/scene_config.rs b/crates/raytracing_config/src/model/scene_config.rs index af573c9..5938b62 100644 --- a/crates/raytracing_config/src/model/scene_config.rs +++ b/crates/raytracing_config/src/model/scene_config.rs @@ -1,31 +1,11 @@ -use raytracing_core::{Hittable, Ray, Scene}; -use serde::Deserialize; - -use crate::{ - model::object_generator_config::{ObjectGeneratorConfig, RayGeneratorConfig}, - object_config::ObjectConfig, - ray_config::RayConfig, -}; - -#[derive(Deserialize)] -pub struct SceneConfig { - #[serde(default)] - pub rays: Vec, - #[serde(default)] - pub ray_generators: Vec, - #[serde(default)] - pub object_generators: Vec, - #[serde(default)] - pub objects: Vec, -} +use raytracing_core::{BVHNode, Hittable, HittableList, Ray, Scene}; impl Into for SceneConfig { fn into(self) -> Scene { - // 個別オブジェクト - let mut objects: Vec> = + // 1. Generate all objects from config + let mut all_objects: Vec> = self.objects.into_iter().map(Into::into).collect(); - // ジェネレータから生成 for generator in self.object_generators { match generator { ObjectGeneratorConfig::ObjectGrid { @@ -44,17 +24,31 @@ impl Into for SceneConfig { let pos = start_pos + (i as f32 * x_step) + (j as f32 * z_step); let mut obj = template.clone(); obj.transform.position = pos.to_array(); - objects.push(obj.into()); + all_objects.push(obj.into()); } } } } } - // 個別レイ - let mut rays: Vec = self.rays.into_iter().map(Into::into).collect(); + // 2. Partition objects into bounded and unbounded + let (mut bounded_objects, unbounded_objects): (Vec<_>, Vec<_>) = + all_objects.into_iter().partition(|obj| obj.bounding_box().is_some()); + + // 3. Create a world list and add unbounded objects + let mut world_list = HittableList::new(); + for obj in unbounded_objects { + world_list.add(obj); + } + + // 4. Build BVH from bounded objects and add it to the world list + if !bounded_objects.is_empty() { + let bvh_node = BVHNode::new(&mut bounded_objects); + world_list.add(Box::new(bvh_node)); + } - // ray_generatorsから生成 + // 5. Generate all rays (same as before) + let mut rays: Vec = self.rays.into_iter().map(Into::into).collect(); for generator in self.ray_generators { match generator { RayGeneratorConfig::ParallelGrid { @@ -109,6 +103,10 @@ impl Into for SceneConfig { } } - Scene { objects, rays } + // 6. Create the final scene with the world object + Scene { + world: Box::new(world_list), + rays, + } } } diff --git a/crates/raytracing_config/src/model/simulation_config.rs b/crates/raytracing_config/src/model/simulation_config.rs index 941dce6..7806d6d 100644 --- a/crates/raytracing_config/src/model/simulation_config.rs +++ b/crates/raytracing_config/src/model/simulation_config.rs @@ -2,12 +2,14 @@ use std::{error::Error, path::Path}; use serde::Deserialize; -use crate::{scene_config::SceneConfig, simulation_settings_config::SimulationSettingsConfig}; +use crate::{model::camera_config::CameraConfig, scene_config::SceneConfig, simulation_settings_config::SimulationSettingsConfig}; #[derive(Deserialize)] pub struct SimulationConfig { pub simulation_settings: SimulationSettingsConfig, pub scene: SceneConfig, + #[serde(default)] + pub camera: CameraConfig, } impl SimulationConfig { diff --git a/crates/raytracing_config/src/model/simulation_settings_config.rs b/crates/raytracing_config/src/model/simulation_settings_config.rs index 802b279..1b9569d 100644 --- a/crates/raytracing_config/src/model/simulation_settings_config.rs +++ b/crates/raytracing_config/src/model/simulation_settings_config.rs @@ -1,17 +1,35 @@ use raytracing_core::SimulationSettingsConfig as CoreSimulationSettingsConfig; use serde::Deserialize; -#[derive(Deserialize)] +#[derive(Deserialize, Clone, Copy)] pub struct SimulationSettingsConfig { pub infinity_distance: f32, pub max_bounces: u32, + #[serde(default = "default_samples_per_pixel")] + pub samples_per_pixel: u32, + #[serde(default = "default_image_width")] + pub image_width: u32, + #[serde(default = "default_image_height")] + pub image_height: u32, } -impl Into for SimulationSettingsConfig { - fn into(self) -> CoreSimulationSettingsConfig { +fn default_samples_per_pixel() -> u32 { + 100 +} + +fn default_image_width() -> u32 { + 800 +} + +fn default_image_height() -> u32 { + 600 +} + +impl From for CoreSimulationSettingsConfig { + fn from(config: SimulationSettingsConfig) -> CoreSimulationSettingsConfig { CoreSimulationSettingsConfig { - infinity_distance: self.infinity_distance, - max_bounces: self.max_bounces, + infinity_distance: config.infinity_distance, + max_bounces: config.max_bounces, } } } diff --git a/crates/raytracing_core/src/primitives/aabb.rs b/crates/raytracing_core/src/primitives/aabb.rs new file mode 100644 index 0000000..cb5962e --- /dev/null +++ b/crates/raytracing_core/src/primitives/aabb.rs @@ -0,0 +1,50 @@ +use crate::Ray; +use glam::Vec3; + +#[derive(Debug, Clone, Copy)] +pub struct AABB { + pub min: Vec3, + pub max: Vec3, +} + +impl AABB { + pub fn new(min: Vec3, max: Vec3) -> Self { + Self { min, max } + } + + // An optimized ray-AABB intersection test + pub fn hit(&self, ray: &Ray, t_min: f32, t_max: f32) -> bool { + for a in 0..3 { + let inv_d = 1.0 / ray.direction[a]; + let mut t0 = (self.min[a] - ray.origin[a]) * inv_d; + let mut t1 = (self.max[a] - ray.origin[a]) * inv_d; + + if inv_d < 0.0 { + std::mem::swap(&mut t0, &mut t1); + } + + let t_min = t0.max(t_min); + let t_max = t1.min(t_max); + + if t_max <= t_min { + return false; + } + } + true + } +} + +// Function to create a new AABB that surrounds two other AABBs +pub fn surrounding_box(box0: &AABB, box1: &AABB) -> AABB { + let small = Vec3::new( + box0.min.x.min(box1.min.x), + box0.min.y.min(box1.min.y), + box0.min.z.min(box1.min.z), + ); + let big = Vec3::new( + box0.max.x.max(box1.max.x), + box0.max.y.max(box1.max.y), + box0.max.z.max(box1.max.z), + ); + AABB::new(small, big) +} diff --git a/crates/raytracing_core/src/primitives/axis_aligned_box.rs b/crates/raytracing_core/src/primitives/axis_aligned_box.rs index 014d490..9e57d9a 100644 --- a/crates/raytracing_core/src/primitives/axis_aligned_box.rs +++ b/crates/raytracing_core/src/primitives/axis_aligned_box.rs @@ -1,4 +1,4 @@ -use crate::{HitRecord, Hittable, Material, Ray}; +use crate::{AABB, HitRecord, Hittable, Material, Ray}; use glam::Vec3; // 軸並行な直方体 (AABB) 対角の座標を指定 #[derive(Debug, Clone, Copy)] @@ -62,6 +62,14 @@ impl Hittable for AxisAlignedBox { Some(hits) } + + fn bounding_box(&self) -> Option { + Some(AABB { min: self.min, max: self.max }) + } + + fn clone_hittable(&self) -> Box { + Box::new(*self) + } } // AABBのためのヘルパーメソッド diff --git a/crates/raytracing_core/src/primitives/bvh.rs b/crates/raytracing_core/src/primitives/bvh.rs new file mode 100644 index 0000000..816a8eb --- /dev/null +++ b/crates/raytracing_core/src/primitives/bvh.rs @@ -0,0 +1,70 @@ +use crate::{aabb::surrounding_box, AABB, HitRecord, Hittable, Ray}; +use rand::Rng; + +pub struct BVHNode { + left: Box, + right: Box, + bbox: AABB, +} + +impl BVHNode { + pub fn new(objects: &mut [Box]) -> Self { + let axis = rand::thread_rng().gen_range(0..3); + let comparator = |a: &Box, b: &Box| { + // Bounding box should exist for all objects used in a BVH. + let box_a = a.bounding_box().unwrap(); + let box_b = b.bounding_box().unwrap(); + box_a.min[axis].partial_cmp(&box_b.min[axis]).unwrap() + }; + + let (left, right): (Box, Box) = if objects.len() == 1 { + (objects[0].clone_hittable(), objects[0].clone_hittable()) + } else if objects.len() == 2 { + if comparator(&objects[0], &objects[1]).is_lt() { + (objects[0].clone_hittable(), objects[1].clone_hittable()) + } else { + (objects[1].clone_hittable(), objects[0].clone_hittable()) + } + } else { + objects.sort_by(comparator); + let mid = objects.len() / 2; + let (left_half, right_half) = objects.split_at_mut(mid); + ( + Box::new(BVHNode::new(left_half)), + Box::new(BVHNode::new(right_half)), + ) + }; + + let box_left = left.bounding_box().unwrap(); + let box_right = right.bounding_box().unwrap(); + let bbox = surrounding_box(&box_left, &box_right); + + Self { left, right, bbox } + } +} + +impl Hittable for BVHNode { + fn bounding_box(&self) -> Option { + Some(self.bbox) + } + + fn intersect_all(&self, ray: &Ray, t_min: f32, t_max: f32) -> Option> { + if !self.bbox.hit(ray, t_min, t_max) { + return None; + } + + let hits_left = self.left.intersect_all(ray, t_min, t_max); + let hits_right = self.right.intersect_all(ray, t_min, t_max); + + match (hits_left, hits_right) { + (Some(mut l), Some(mut r)) => { + l.append(&mut r); + l.sort_by(|a, b| a.t.partial_cmp(&b.t).unwrap()); + Some(l) + } + (Some(l), None) => Some(l), + (None, Some(r)) => Some(r), + (None, None) => None, + } + } +} diff --git a/crates/raytracing_core/src/primitives/csg.rs b/crates/raytracing_core/src/primitives/csg.rs index ddbeb7f..6a12c93 100644 --- a/crates/raytracing_core/src/primitives/csg.rs +++ b/crates/raytracing_core/src/primitives/csg.rs @@ -1,4 +1,5 @@ -use crate::{CsgOperation, HitRecord, Hittable, Ray}; +use super::aabb::surrounding_box; +use crate::{AABB, CsgOperation, HitRecord, Hittable, Ray}; // CSGオブジェクト pub struct CSGObject { pub left: Box, @@ -73,4 +74,34 @@ impl Hittable for CSGObject { Some(result_hits) } } + + fn bounding_box(&self) -> Option { + let left_box = self.left.bounding_box(); + let right_box = self.right.bounding_box(); + + match (left_box, right_box) { + (Some(l), Some(r)) => match self.operation { + CsgOperation::Union => Some(surrounding_box(&l, &r)), + CsgOperation::Intersection => { + let min = l.min.max(r.min); + let max = l.max.min(r.max); + if min.x < max.x && min.y < max.y && min.z < max.z { + Some(AABB::new(min, max)) + } else { + None + } + } + CsgOperation::Difference => Some(l), + }, + _ => None, // If either child is unbounded, the result is complex. + } + } + + fn clone_hittable(&self) -> Box { + Box::new(CSGObject { + left: self.left.clone_hittable(), + right: self.right.clone_hittable(), + operation: self.operation, + }) + } } diff --git a/crates/raytracing_core/src/primitives/hittable_list.rs b/crates/raytracing_core/src/primitives/hittable_list.rs new file mode 100644 index 0000000..0d57459 --- /dev/null +++ b/crates/raytracing_core/src/primitives/hittable_list.rs @@ -0,0 +1,69 @@ +use crate::{aabb::surrounding_box, AABB, HitRecord, Hittable, Ray}; + +// A list of hittable objects +pub struct HittableList { + pub objects: Vec>, +} + +impl HittableList { + pub fn new() -> Self { + Self { objects: Vec::new() } + } + + pub fn add(&mut self, object: Box) { + self.objects.push(object); + } +} + +impl Hittable for HittableList { + fn intersect_all(&self, ray: &Ray, t_min: f32, t_max: f32) -> Option> { + let mut all_hits = Vec::new(); + let mut closest_so_far = t_max; + + for object in &self.objects { + // By reducing t_max with each hit, we can prune the search space + if let Some(mut hits) = object.intersect_all(ray, t_min, closest_so_far) { + if let Some(first_hit) = hits.first() { + closest_so_far = first_hit.t; + } + all_hits.append(&mut hits); + } + } + + if all_hits.is_empty() { + None + } else { + all_hits.sort_by(|a, b| a.t.partial_cmp(&b.t).unwrap()); + Some(all_hits) + } + } + + fn bounding_box(&self) -> Option { + if self.objects.is_empty() { + return None; + } + + let mut output_box: Option = None; + + for object in &self.objects { + if let Some(temp_box) = object.bounding_box() { + output_box = match output_box { + Some(b) => Some(surrounding_box(&b, &temp_box)), + None => Some(temp_box), + }; + } else { + // If any object in the list is unbounded, the list itself is unbounded. + return None; + } + } + output_box + } + + fn clone_hittable(&self) -> Box { + let mut new_list = HittableList::new(); + for object in &self.objects { + new_list.add(object.clone_hittable()); + } + Box::new(new_list) + } +} diff --git a/crates/raytracing_core/src/primitives/infinite_cone.rs b/crates/raytracing_core/src/primitives/infinite_cone.rs index 9b46edb..5e4bd5c 100644 --- a/crates/raytracing_core/src/primitives/infinite_cone.rs +++ b/crates/raytracing_core/src/primitives/infinite_cone.rs @@ -1,4 +1,4 @@ -use crate::{HitRecord, Hittable, Material, Ray}; +use crate::{AABB, HitRecord, Hittable, Material, Ray}; use glam::Vec3; // 無限円錐 #[derive(Debug, Clone, Copy)] @@ -78,10 +78,14 @@ impl Hittable for InfiniteCone { } } - if hits.is_empty() { - None - } else { - Some(hits) - } + if hits.is_empty() { None } else { Some(hits) } + } + + fn bounding_box(&self) -> Option { + None // An infinite cone has no bounding box. + } + + fn clone_hittable(&self) -> Box { + Box::new(*self) } } diff --git a/crates/raytracing_core/src/primitives/infinite_cylinder.rs b/crates/raytracing_core/src/primitives/infinite_cylinder.rs index b63e05d..b62ddfd 100644 --- a/crates/raytracing_core/src/primitives/infinite_cylinder.rs +++ b/crates/raytracing_core/src/primitives/infinite_cylinder.rs @@ -1,4 +1,4 @@ -use crate::{HitRecord, Hittable, Material, Ray}; +use crate::{AABB, CSGObject, HitRecord, Hittable, Material, Ray}; use glam::Vec3; // 無限円柱 #[derive(Debug, Clone, Copy)] @@ -76,10 +76,14 @@ impl Hittable for InfiniteCylinder { } } - if hits.is_empty() { - None - } else { - Some(hits) - } + if hits.is_empty() { None } else { Some(hits) } + } + + fn bounding_box(&self) -> Option { + None // An infinite cylinder has no bounding box. + } + + fn clone_hittable(&self) -> Box { + Box::new(*self) } } diff --git a/crates/raytracing_core/src/primitives/lens.rs b/crates/raytracing_core/src/primitives/lens.rs index 2a267c4..42e7528 100644 --- a/crates/raytracing_core/src/primitives/lens.rs +++ b/crates/raytracing_core/src/primitives/lens.rs @@ -1,7 +1,8 @@ use crate::{ - CSGObject, CsgOperation, HitRecord, Hittable, InfiniteCylinder, Material, Plane, Ray, Sphere, + AABB, CSGObject, CsgOperation, HitRecord, Hittable, InfiniteCylinder, Material, Plane, Ray, + Sphere, }; -use glam::{f32, Vec3}; +use glam::{Vec3, f32}; //レンズプリミティブ pub struct Lens { pub csg_object: Box, @@ -80,4 +81,14 @@ impl Hittable for Lens { fn intersect_all(&self, ray: &Ray, t_min: f32, t_max: f32) -> Option> { self.csg_object.intersect_all(ray, t_min, t_max) } + + fn bounding_box(&self) -> Option { + self.csg_object.bounding_box() + } + + fn clone_hittable(&self) -> Box { + Box::new(Lens { + csg_object: self.csg_object.clone_hittable(), + }) + } } diff --git a/crates/raytracing_core/src/primitives/mod.rs b/crates/raytracing_core/src/primitives/mod.rs index 535a2bb..0cbd4b8 100644 --- a/crates/raytracing_core/src/primitives/mod.rs +++ b/crates/raytracing_core/src/primitives/mod.rs @@ -2,8 +2,11 @@ // それらの中の公開アイテム(pub)を、このモジュールの外からも使えるようにします。 // 各プリミティブのモジュールを宣言 +mod aabb; mod axis_aligned_box; +mod bvh; mod csg; +mod hittable_list; mod infinite_cone; mod infinite_cylinder; mod lens; @@ -13,8 +16,11 @@ mod transform; mod wedge; // 各モジュール内の公開アイテムを、primitives::* で使えるように再公開(re-export)する +pub use aabb::AABB; pub use axis_aligned_box::AxisAlignedBox; +pub use bvh::BVHNode; pub use csg::CSGObject; +pub use hittable_list::HittableList; pub use infinite_cone::InfiniteCone; pub use infinite_cylinder::InfiniteCylinder; pub use lens::Lens; @@ -25,6 +31,7 @@ pub use wedge::Wedge; use crate::HitRecord; use crate::Ray; +use glam::Vec3; // ブーリアン演算の種類 #[derive(Debug, Copy, Clone, PartialEq)] pub enum CsgOperation { @@ -38,11 +45,15 @@ pub enum CsgOperation { #[derive(Debug, Clone, Copy, PartialEq)] pub enum Material { - Mirror, - Glass { ior: f32 }, + Metal { color: Vec3, fuzz: f32 }, + Glass { color: Vec3, ior: f32 }, HalfMirror { reflectance: f32 }, + Diffuse { color: Vec3 }, + Light { color: Vec3 }, } pub trait Hittable: Sync + Send { fn intersect_all(&self, ray: &Ray, t_min: f32, t_max: f32) -> Option>; + fn bounding_box(&self) -> Option; + fn clone_hittable(&self) -> Box; } diff --git a/crates/raytracing_core/src/primitives/plane.rs b/crates/raytracing_core/src/primitives/plane.rs index 0cb2957..dc605a0 100644 --- a/crates/raytracing_core/src/primitives/plane.rs +++ b/crates/raytracing_core/src/primitives/plane.rs @@ -1,4 +1,4 @@ -use crate::{HitRecord, Hittable, Material, Ray}; +use crate::{AABB, HitRecord, Hittable, Material, Ray}; use glam::Vec3; // main.rsから移動させる共通定義をインポート #[derive(Debug, Clone, Copy)] @@ -52,4 +52,12 @@ impl Hittable for Plane { // 単一のHitRecordを、要素が1つのVec(ベクタ)に入れてSomeで返す Some(vec![hit_record]) } + + fn bounding_box(&self) -> Option { + None // An infinite plane has no bounding box. + } + + fn clone_hittable(&self) -> Box { + Box::new(*self) + } } diff --git a/crates/raytracing_core/src/primitives/sphere.rs b/crates/raytracing_core/src/primitives/sphere.rs index 16a891b..397ba5d 100644 --- a/crates/raytracing_core/src/primitives/sphere.rs +++ b/crates/raytracing_core/src/primitives/sphere.rs @@ -1,4 +1,4 @@ -use crate::{HitRecord, Hittable, Material, Ray}; +use crate::{AABB, HitRecord, Hittable, Material, Ray}; use glam::Vec3; // main.rsから移動させる共通定義をインポート #[derive(Debug, Clone, Copy)] @@ -72,4 +72,15 @@ impl Hittable for Sphere { Some(hits) } } + + fn bounding_box(&self) -> Option { + Some(AABB { + min: self.center - Vec3::splat(self.radius), + max: self.center + Vec3::splat(self.radius), + }) + } + + fn clone_hittable(&self) -> Box { + Box::new(*self) + } } diff --git a/crates/raytracing_core/src/primitives/transform.rs b/crates/raytracing_core/src/primitives/transform.rs index 31332d8..5a1b237 100644 --- a/crates/raytracing_core/src/primitives/transform.rs +++ b/crates/raytracing_core/src/primitives/transform.rs @@ -1,4 +1,4 @@ -use crate::{HitRecord, Hittable, Ray}; +use crate::{AABB, HitRecord, Hittable, Ray}; use glam::Mat4; // 他のHittableオブジェクトに変換を適用するためのラッパー pub struct Transform { @@ -49,4 +49,34 @@ impl Hittable for Transform { None } } + + fn bounding_box(&self) -> Option { + if let Some(bbox) = self.object.bounding_box() { + let mut min = glam::Vec3::splat(f32::INFINITY); + let mut max = glam::Vec3::splat(f32::NEG_INFINITY); + + for i in 0..8 { + let x = if (i & 1) == 0 { bbox.min.x } else { bbox.max.x }; + let y = if (i & 2) == 0 { bbox.min.y } else { bbox.max.y }; + let z = if (i & 4) == 0 { bbox.min.z } else { bbox.max.z }; + + let corner = glam::Vec3::new(x, y, z); + let transformed_corner = self.transform.transform_point3(corner); + + min = min.min(transformed_corner); + max = max.max(transformed_corner); + } + Some(AABB::new(min, max)) + } else { + None + } + } + + fn clone_hittable(&self) -> Box { + Box::new(Transform { + object: self.object.clone_hittable(), + transform: self.transform, + inverse_transform: self.inverse_transform, + }) + } } diff --git a/crates/raytracing_core/src/primitives/wedge.rs b/crates/raytracing_core/src/primitives/wedge.rs index 2bae76f..6532815 100644 --- a/crates/raytracing_core/src/primitives/wedge.rs +++ b/crates/raytracing_core/src/primitives/wedge.rs @@ -1,6 +1,6 @@ use glam::Vec3; -use crate::{CSGObject, CsgOperation, HitRecord, Hittable, Material, Plane, Ray}; +use crate::{AABB, CSGObject, CsgOperation, HitRecord, Hittable, Material, Plane, Ray}; //ウェッジ pub struct Wedge { pub csg_object: Box, @@ -82,4 +82,14 @@ impl Hittable for Wedge { fn intersect_all(&self, ray: &Ray, t_min: f32, t_max: f32) -> Option> { self.csg_object.intersect_all(ray, t_min, t_max) } + + fn bounding_box(&self) -> Option { + self.csg_object.bounding_box() + } + + fn clone_hittable(&self) -> Box { + Box::new(Wedge { + csg_object: self.csg_object.clone_hittable(), + }) + } } diff --git a/crates/raytracing_core/src/scene.rs b/crates/raytracing_core/src/scene.rs index f22c004..0a11c29 100644 --- a/crates/raytracing_core/src/scene.rs +++ b/crates/raytracing_core/src/scene.rs @@ -26,7 +26,7 @@ fn refract(incident: Vec3, normal: Vec3, ior_ratio: f32) -> Option { Some((perp + parallel).normalize()) } pub struct Scene { - pub objects: Vec>, + pub world: Box, pub rays: Vec, } @@ -47,29 +47,26 @@ impl Scene { let infinity_distance = setting.infinity_distance; for _ in 0..max_bounces { - let mut closest_hit_record: Option = None; - let mut t_closest = f32::INFINITY; - - for object in &self.objects { - if let Some(hits) = object.intersect_all(&ray, 0.001, t_closest) { - if let Some(first_hit) = hits.first() { - if first_hit.t < t_closest { - t_closest = first_hit.t; - closest_hit_record = Some(*first_hit); - } - } - } - } + // The world object (a BVH or a HittableList) finds the closest hit. + let closest_hit_record = self + .world + .intersect_all(&ray, 0.001, f32::INFINITY) + .and_then(|mut hits| { + // intersect_all is expected to return sorted hits, but we sort again to be safe. + hits.sort_by(|a, b| a.t.partial_cmp(&b.t).unwrap()); + hits.into_iter().next() + }); if let Some(hit) = closest_hit_record { path_points.push(hit.point); let material = hit.material; // HitRecordから直接マテリアルを取得! match material { - Material::Mirror => { + Material::Metal { .. } => { + // For path visualization, treat metal as a perfect mirror. ray.direction = reflect(ray.direction, hit.normal); } - Material::Glass { ior: material_ior } => { + Material::Glass { ior: material_ior, .. } => { let n1 = ray.current_ior; let n2 = if hit.front_face { material_ior } else { 1.0 }; let ior_ratio = n1 / n2; @@ -93,6 +90,14 @@ impl Scene { // ray.direction はそのまま } } + Material::Diffuse { .. } => { + // For path visualization, we stop when hitting a diffuse surface. + break; + } + Material::Light { .. } => { + // For path visualization, we stop when hitting a light source. + break; + } } ray.origin = hit.point + ray.direction * 0.001; } else { diff --git a/crates/raytracing_renderer/Cargo.toml b/crates/raytracing_renderer/Cargo.toml new file mode 100644 index 0000000..b6ff9ab --- /dev/null +++ b/crates/raytracing_renderer/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "raytracing_renderer" +version = "0.1.0" +edition = "2024" + +[dependencies] +raytracing_core = { workspace = true } +raytracing_config = { workspace = true } +glam = { workspace = true } +image = "0.25.1" +rand = "0.8" +rayon = "1.5" diff --git a/crates/raytracing_renderer/src/lib.rs b/crates/raytracing_renderer/src/lib.rs new file mode 100644 index 0000000..151b1a0 --- /dev/null +++ b/crates/raytracing_renderer/src/lib.rs @@ -0,0 +1,235 @@ +use glam::Vec3; +use image::{ImageBuffer, Rgb}; +use rand::Rng; +use rayon::prelude::*; +use raytracing_config::model::camera_config::CameraConfig; +use raytracing_core::{HitRecord, Hittable, Material, Ray, Scene}; + +// --- Helper Functions for vector math and physics --- + +fn reflect(v: Vec3, n: Vec3) -> Vec3 { + v - 2.0 * v.dot(n) * n +} + +fn refract(uv: Vec3, n: Vec3, etai_over_etat: f32) -> Vec3 { + let cos_theta = (-uv).dot(n).min(1.0); + let r_out_perp = etai_over_etat * (uv + cos_theta * n); + let r_out_parallel = -(1.0 - r_out_perp.length_squared()).abs().sqrt() * n; + r_out_perp + r_out_parallel +} + +fn schlick(cosine: f32, ref_idx: f32) -> f32 { + let mut r0 = (1.0 - ref_idx) / (1.0 + ref_idx); + r0 = r0 * r0; + r0 + (1.0 - r0) * (1.0 - cosine).powi(5) +} + +fn random_in_unit_sphere() -> Vec3 { + let mut rng = rand::thread_rng(); + loop { + let p = Vec3::new( + rng.gen_range(-1.0..1.0), + rng.gen_range(-1.0..1.0), + rng.gen_range(-1.0..1.0), + ); + if p.length_squared() < 1.0 { + return p; + } + } +} + +// --- Camera --- + +pub struct Camera { + origin: Vec3, + lower_left_corner: Vec3, + horizontal: Vec3, + vertical: Vec3, +} + +impl Camera { + pub fn new(lookfrom: Vec3, lookat: Vec3, vup: Vec3, vfov: f32, aspect_ratio: f32) -> Camera { + let theta = vfov.to_radians(); + let h = (theta / 2.0).tan(); + let viewport_height = 2.0 * h; + let viewport_width = aspect_ratio * viewport_height; + + let w = (lookfrom - lookat).normalize(); + let u = vup.cross(w).normalize(); + let v = w.cross(u); + + let origin = lookfrom; + let horizontal = viewport_width * u; + let vertical = viewport_height * v; + let lower_left_corner = origin - horizontal / 2.0 - vertical / 2.0 - w; + + Camera { + origin, + lower_left_corner, + horizontal, + vertical, + } + } + + pub fn get_ray(&self, s: f32, t: f32) -> Ray { + Ray { + origin: self.origin, + direction: (self.lower_left_corner + s * self.horizontal + t * self.vertical + - self.origin) + .normalize(), + current_ior: 1.0, + } + } +} + +// --- Main Rendering Logic --- + +/// Renders the scene and saves it to a file. +pub fn render( + scene: &Scene, + camera_config: &CameraConfig, + width: u32, + height: u32, + samples_per_pixel: u32, + max_depth: u32, +) { + // Camera + let camera = Camera::new( + camera_config.lookfrom, + camera_config.lookat, + camera_config.vup, + camera_config.vfov, + width as f32 / height as f32, + ); + + // Render using Rayon for parallel processing + let pixels: Vec> = (0..height) + .into_par_iter() + .rev() // Start from the top row + .flat_map(|j| { + (0..width) + .map(|i| { + let mut pixel_color = Vec3::ZERO; + let mut rng = rand::thread_rng(); + + for _ in 0..samples_per_pixel { + let u = (i as f32 + rng.r#gen::()) / (width - 1) as f32; + let v = (j as f32 + rng.r#gen::()) / (height - 1) as f32; + let ray = camera.get_ray(u, v); + pixel_color += ray_color(&ray, scene, max_depth as i32); + } + + // Average color and apply gamma correction + let scale = 1.0 / samples_per_pixel as f32; + let r = (pixel_color.x * scale).sqrt(); + let g = (pixel_color.y * scale).sqrt(); + let b = (pixel_color.z * scale).sqrt(); + + Rgb([ + (256.0 * r.clamp(0.0, 0.999)) as u8, + (256.0 * g.clamp(0.0, 0.999)) as u8, + (256.0 * b.clamp(0.0, 0.999)) as u8, + ]) + }) + .collect::>() + }) + .collect(); + + // Create image buffer from pixel data + let raw_pixels: Vec = pixels.into_iter().flat_map(|p| p.0).collect(); + let img_buf: ImageBuffer, Vec> = + ImageBuffer::from_raw(width, height, raw_pixels).unwrap(); + + // Save the image + img_buf.save("output.png").unwrap(); + println!("レンダリングが完了し、'output.png' に保存されました。"); +} + +// Recursively traces a ray and determines the color. +fn ray_color(ray: &Ray, scene: &Scene, depth: i32) -> Vec3 { + if depth <= 0 { + return Vec3::ZERO; + } + + // Find the closest hit by intersecting the ray with the world object (which could be a BVH). + let closest_hit = scene + .world + .intersect_all(ray, 0.001, f32::INFINITY) + .and_then(|mut hits| { + // The list of hits should be sorted by t, so we can just take the first one. + hits.sort_by(|a, b| a.t.partial_cmp(&b.t).unwrap()); + hits.into_iter().next() + }); + + if let Some(hit) = closest_hit { + // Calculate emitted light from the material itself + let emitted = match hit.material { + Material::Light { color } => color, + _ => Vec3::ZERO, + }; + + // Calculate scattered light + let (maybe_scattered, attenuation) = match hit.material { + Material::Light { .. } => (None, Vec3::ZERO), // Lights emit, but don't scatter + + Material::Diffuse { color } => { + let scatter_direction = hit.normal + random_in_unit_sphere().normalize(); + let scattered = Ray { + origin: hit.point, + direction: scatter_direction, + current_ior: ray.current_ior, + }; + (Some(scattered), color) + } + + Material::Metal { color, fuzz } => { + let reflected = reflect(ray.direction.normalize(), hit.normal); + let scattered = Ray { + origin: hit.point, + direction: reflected + fuzz * random_in_unit_sphere(), + current_ior: ray.current_ior, + }; + // Absorb rays that scatter below the surface + if scattered.direction.dot(hit.normal) > 0.0 { + (Some(scattered), color) + } else { + (None, Vec3::ZERO) + } + } + + Material::Glass { color, ior } => { + let attenuation = color; // Use the material's color for attenuation + let etai_over_etat = if hit.front_face { 1.0 / ior } else { ior }; + let unit_direction = ray.direction.normalize(); + let cos_theta = (-unit_direction).dot(hit.normal).min(1.0); + let sin_theta = (1.0 - cos_theta * cos_theta).sqrt(); + let reflect_prob = schlick(cos_theta, etai_over_etat); + + let direction = if etai_over_etat * sin_theta > 1.0 + || rand::thread_rng().r#gen::() < reflect_prob + { + reflect(unit_direction, hit.normal) + } else { + refract(unit_direction, hit.normal, etai_over_etat) + }; + + let scattered = Ray { + origin: hit.point, + direction, + current_ior: if hit.front_face { ior } else { 1.0 }, + }; + (Some(scattered), attenuation) + } + _ => (None, Vec3::ZERO), // Unhandled materials + }; + + if let Some(scattered_ray) = maybe_scattered { + emitted + attenuation * ray_color(&scattered_ray, scene, depth - 1) + } else { + emitted + } + } else { + // If the ray doesn't hit anything, it's black (scene is lit from within) + Vec3::ZERO + } +} diff --git a/output.png b/output.png new file mode 100644 index 0000000000000000000000000000000000000000..af03be9dd2f6c139d4ebdbf06493e4ed372085b3 GIT binary patch literal 158803 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%0AVBIenrfUt@L`QQPcm+7VMhYj5vS@8k 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ξ0`IfnBFu@)P<8*ktK;IQ?{=i&Td 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 literal 0 HcmV?d00001 diff --git a/paths.obj b/paths.obj new file mode 100644 index 0000000..b003f2a --- /dev/null +++ b/paths.obj @@ -0,0 +1,21 @@ +# Light path visualization generated by raytracing-cli +# Vertices +v -15 0 0 +v 3.77524 -9.38762 -9.38762 +v 5 -10 -10 +v 6.224745 -9.387628 -10.612372 +v 47.050392 11.025195 -31.025196 +v -15 0 0 +v 44.999996 -10 -29.999998 +v 81.86122 -38.313652 -48.43061 +v -15 0 0 +v 29.232582 7.372097 -22.116291 + +# Line segments +l 1 2 +l 2 3 +l 3 4 +l 4 5 +l 6 7 +l 7 8 +l 9 10 diff --git a/python_files/plot_3d.py b/python_files/plot_3d.py deleted file mode 100644 index cde2b52..0000000 --- a/python_files/plot_3d.py +++ /dev/null @@ -1,44 +0,0 @@ -import matplotlib.pyplot as plt -import pandas as pd -from matplotlib.patches import Circle, PathPatch -from matplotlib.path import Path - -# CSVファイルを読み込む -try: - df = pd.read_csv('path_3d.csv') -except FileNotFoundError: - print("Error: 'path_3d.csv' not found. Please run the Rust program first.") - exit() - -# プロットの準備 -plt.figure(figsize=(12, 9)) -ax = plt.gca() - -# --- シーン内のオブジェクトの断面を描画 --- -# Rustコードのシーン設定と対応させる - -# 1. ガラスの球: center=(0,0,0), radius=10 -# XY平面で見た場合、(0,0)が中心の半径10の円になる -sphere = Circle((0, 0), 10, color='skyblue', alpha=0.4, label='Glass Sphere (ior=1.5)') -ax.add_patch(sphere) - -# 2. 反射する床: y = -15 の平面 -# XY平面で見た場合、y = -15 の水平な直線になる -plt.axhline(y=-15, color='dimgray', linewidth=3, label='Mirror Plane') - - -# --- 光路を描画 --- -# 'x'と'y'の列だけを使ってプロット(Z軸を無視してXY平面に射影) -plt.plot(df['x'], df['z'], marker='o', markersize=4, linestyle='-', color='red', label='Ray Path (XZ Projection)') - -# 始点に印をつける -plt.plot(df['x'].iloc[0], df['z'].iloc[0], 'go', markersize=10, label='Start Point') - -# --- グラフの体裁を整える --- -plt.xlabel('X coordinate') -plt.ylabel('Y coordinate') -plt.title('3D Optical Path Simulation (Projected onto XY Plane)') -plt.grid(True) -plt.legend() -plt.axis('equal') # X軸とY軸のスケールを合わせる(形状が歪まないように) -plt.show() \ No newline at end of file diff --git a/simulation.toml b/simulation.toml index ccef7d0..79e83ef 100644 --- a/simulation.toml +++ b/simulation.toml @@ -1,6 +1,9 @@ [simulation_settings] infinity_distance = 50.0 -max_bounces = 10 +max_bounces = 50 +samples_per_pixel = 100 +image_width = 800 +image_height = 600 # === レイ生成ルール === # 2. プロジェクターのような点光源 @@ -26,17 +29,32 @@ step_z = [0.0, 0.0, -5.0] # Z方向の配置ステップ # グリッド配置するオブジェクトのテンプレート template.shape = { type = "Sphere", radius = 1.5 } -template.material = { type = "Glass", ior = 1.5 } +template.material = { type = "Diffuse", color = [0.8, 0.3, 0.3] } template.transform = { position = [0.0, 0.0, 0.0], rotation_y_deg = 0.0 } # === 個別に配置するオブジェクト === [[scene.objects]] # 床 shape = { type = "Plane", normal = [0.0, 1.0, 0.0] } -material = { type = "Glass", ior = 1.2} +material = { type = "Metal", color = [0.8, 0.8, 0.8], fuzz = 0.2 } transform = { position = [0.0, -10.0, 0.0], rotation_y_deg = 0.0 } [[scene.objects]] shape = { type = "Plane", normal = [0.0, 1.0, 0.0] } material = { type = "Glass", ior = 1.2 } -transform = { position = [0.0, -10.0, 0.0],rotation_y_deg = 0.0 } \ No newline at end of file +transform = { position = [0.0, -10.0, 0.0],rotation_y_deg = 0.0 } + +[camera] +lookfrom = [0.0, 0.0, 25.0] +lookat = [0.0, 0.0, 0.0] +vfov = 90.0 + +[[scene.objects]] + shape = { type = "Sphere", radius = 3.0 } + material = { type = "Light", color = [4.0, 4.0, 4.0] } + transform = { position = [0.0, 0.0, 0.0], rotation_y_deg = 0.0 } + +[[scene.objects]] +shape = { type = "Sphere", radius = 5.0 } +material = { type = "Glass", color = [0.8, 1.0, 0.85], ior = 1.5 } +transform = { position = [-10.0, 0.0, 0.0], rotation_y_deg = 0.0 } \ No newline at end of file diff --git a/src/bin/render.rs b/src/bin/render.rs new file mode 100644 index 0000000..da86216 --- /dev/null +++ b/src/bin/render.rs @@ -0,0 +1,23 @@ +use raytracing_config::simulation_config::SimulationConfig; +use raytracing_core::Scene; +use raytracing_renderer::render; +use std::error::Error; + +fn main() -> Result<(), Box> { + println!("設定ファイル simulation.toml を読み込んでいます..."); + let config = SimulationConfig::load_from_path("simulation.toml")?; + let scene: Scene = config.scene.into(); + + println!("レンダリングを開始します..."); + let settings = config.simulation_settings; + render( + &scene, + &config.camera, + settings.image_width, + settings.image_height, + settings.samples_per_pixel, + settings.max_bounces, + ); + + Ok(()) +} From ba83337f02e14e593188c500bbff068e5ec825f1 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Mon, 6 Oct 2025 06:59:23 +0000 Subject: [PATCH 3/4] Fix various compilation errors and warnings This change addresses a series of compilation issues that arose after a refactoring of the scene generation logic. The following fixes were implemented: - Corrected unresolved import paths in `bvh.rs` and `hittable_list.rs`. - Implemented the `Clone` trait for `BVHNode` manually to handle `Box` fields correctly. - Added missing `SceneConfig` struct definition and its necessary imports. - Added `#[derive(Debug)]` to all configuration-related structs (`ObjectConfig`, `ShapeConfig`, etc.) to resolve cascading `Debug` trait errors. - Removed unused imports and variables to eliminate compiler warnings. --- .../src/model/material_config.rs | 4 +- .../src/model/object_config.rs | 4 +- .../src/model/object_generator_config.rs | 350 +++++++++--------- .../raytracing_config/src/model/ray_config.rs | 7 +- .../src/model/scene_config.rs | 31 +- .../src/model/shape_config.rs | 4 +- .../src/model/simulation_config.rs | 47 +-- .../src/model/transform_config.rs | 4 +- crates/raytracing_core/src/primitives/bvh.rs | 18 +- .../src/primitives/hittable_list.rs | 2 +- .../src/primitives/infinite_cylinder.rs | 178 ++++----- .../raytracing_core/src/primitives/wedge.rs | 190 +++++----- crates/raytracing_core/src/scene.rs | 258 +++++++------ crates/raytracing_renderer/src/lib.rs | 4 +- output.png | Bin 158803 -> 158753 bytes 15 files changed, 567 insertions(+), 534 deletions(-) diff --git a/crates/raytracing_config/src/model/material_config.rs b/crates/raytracing_config/src/model/material_config.rs index b1c0f6b..78fb5c4 100644 --- a/crates/raytracing_config/src/model/material_config.rs +++ b/crates/raytracing_config/src/model/material_config.rs @@ -3,7 +3,7 @@ use serde::Deserialize; use raytracing_core::Material; -#[derive(Deserialize, Clone, Copy)] // 材質はコピーするのでClone, Copyも +#[derive(Deserialize, Clone, Copy, Debug)] // 材質はコピーするのでClone, Copyも #[serde(tag = "type")] pub enum MaterialConfig { Glass { @@ -31,4 +31,4 @@ impl From for Material { MaterialConfig::Light { color } => Material::Light { color }, } } -} +} \ No newline at end of file diff --git a/crates/raytracing_config/src/model/object_config.rs b/crates/raytracing_config/src/model/object_config.rs index fce969e..4d630fb 100644 --- a/crates/raytracing_config/src/model/object_config.rs +++ b/crates/raytracing_config/src/model/object_config.rs @@ -6,7 +6,7 @@ use crate::{ material_config::MaterialConfig, shape_config::ShapeConfig, transform_config::TransformConfig, }; -#[derive(Deserialize, Clone)] +#[derive(Deserialize, Clone, Debug)] pub struct ObjectConfig { pub shape: ShapeConfig, pub material: MaterialConfig, @@ -27,4 +27,4 @@ impl Into> for ObjectConfig { Box::new(Transform::new(primitive, transform_matrix)) } -} +} \ No newline at end of file diff --git a/crates/raytracing_config/src/model/object_generator_config.rs b/crates/raytracing_config/src/model/object_generator_config.rs index c758c9c..7712dc6 100644 --- a/crates/raytracing_config/src/model/object_generator_config.rs +++ b/crates/raytracing_config/src/model/object_generator_config.rs @@ -1,175 +1,175 @@ -use glam::Vec3; -use raytracing_core::{Hittable, Ray}; -use serde::Deserialize; - -use crate::{ - material_config::MaterialConfig, object_config::ObjectConfig, shape_config::ShapeConfig, -}; - -// --- ジェネレータの定義 --- - -#[derive(Deserialize, Debug)] -#[serde(tag = "type")] -pub enum RayGeneratorConfig { - ParallelGrid { - origin_corner: [f32; 3], - vec_u: [f32; 3], - vec_v: [f32; 3], - count_u: u32, - count_v: u32, - direction: [f32; 3], - current_ior: f32, - }, - Projector { - origin: [f32; 3], - target_corner: [f32; 3], - target_u: [f32; 3], - target_v: [f32; 3], - count_u: u32, - count_v: u32, - current_ior: f32, - }, -} - -#[derive(Deserialize)] -#[serde(tag = "type")] -pub enum ObjectGeneratorConfig { - ObjectGrid { - count_x: u32, - count_z: u32, - position_start: [f32; 3], - step_x: [f32; 3], - step_z: [f32; 3], - template: ObjectConfig, // オブジェクトのテンプレート - }, -} - -#[derive(Deserialize, Clone)] // テンプレートはクローン可能にする -pub struct ObjectTemplateConfig { - pub shape: ShapeConfig, - pub material: MaterialConfig, -} - -// --- シーン全体のコンフィグ --- -// (ShapeConfig, MaterialConfig, ObjectConfig などは以前のものを使用) - -#[derive(Deserialize)] -pub struct SceneDefinition { - // defaultを追加して、TOMLにキーが無くてもエラーにならないようにする - //#[serde(default)] - pub ray_generators: Vec, - - //#[serde(default)] - pub object_generators: Vec, - - //#[serde(default)] - pub objects: Vec, -} - -// この関数でConfigから実行時に使うオブジェクトを生成する -pub fn build_scene_from_config(config: SceneDefinition) -> (Vec, Vec>) { - let mut rays: Vec = Vec::new(); - let mut hittables: Vec> = Vec::new(); - - // === レイの生成 === - for generator in config.ray_generators { - match generator { - RayGeneratorConfig::ParallelGrid { - origin_corner, - vec_u, - vec_v, - count_u, - count_v, - direction, - current_ior, - } => { - let corner = Vec3::from(origin_corner); - let u_step = Vec3::from(vec_u) / (count_u as f32); - let v_step = Vec3::from(vec_v) / (count_v as f32); - let dir = Vec3::from(direction).normalize(); - - for i in 0..count_u { - for j in 0..count_v { - let origin = corner + (i as f32 * u_step) + (j as f32 * v_step); - rays.push(Ray { - origin, - direction: dir, - current_ior, //..Default::default() - }); - } - } - } - RayGeneratorConfig::Projector { - origin, - target_corner, - target_u, - target_v, - count_u, - count_v, - current_ior, - } => { - let ray_origin = Vec3::from(origin); - let target_c = Vec3::from(target_corner); - let target_u_step = Vec3::from(target_u) / (count_u as f32); - let target_v_step = Vec3::from(target_v) / (count_v as f32); - - for i in 0..count_u { - for j in 0..count_v { - let target_point = - target_c + (i as f32 * target_u_step) + (j as f32 * target_v_step); - rays.push(Ray { - origin: ray_origin, - direction: (target_point - ray_origin).normalize(), - current_ior, //..Default::default() - }); - } - } - } - } - } - - // === オブジェクトの生成 === - for generator in config.object_generators { - match generator { - ObjectGeneratorConfig::ObjectGrid { - count_x, - count_z, - position_start, - step_x, - step_z, - template, - } => { - let start_pos = Vec3::from(position_start); - let x_step = Vec3::from(step_x); - let z_step = Vec3::from(step_z); - - for i in 0..count_x { - for j in 0..count_z { - let pos = start_pos + (i as f32 * x_step) + (j as f32 * z_step); - - // テンプレートを複製し、transform.positionのみ変更 - let mut obj = template.clone(); - obj.transform.position = pos.to_array(); - - let hittable: Box = obj.into(); - hittables.push(hittable); - } - } - } - } - } - - // === 個別オブジェクトの追加 === - for obj_conf in config.objects { - let material = obj_conf.material.into(); - let mut hittable = obj_conf.shape.into_with(material); - // ... transformの適用 ... - hittables.push(hittable); - } - - (rays, hittables) -} - -// 以下は仮のヘルパー関数 -// pub fn build_material(config: MaterialConfig) -> Material { ... } -// impl ShapeConfig { pub fn into_with(self, material: Material) -> Box { ... } } +use glam::Vec3; +use raytracing_core::{Hittable, Ray}; +use serde::Deserialize; + +use crate::{ + material_config::MaterialConfig, object_config::ObjectConfig, shape_config::ShapeConfig, +}; + +// --- ジェネレータの定義 --- + +#[derive(Deserialize, Debug)] +#[serde(tag = "type")] +pub enum RayGeneratorConfig { + ParallelGrid { + origin_corner: [f32; 3], + vec_u: [f32; 3], + vec_v: [f32; 3], + count_u: u32, + count_v: u32, + direction: [f32; 3], + current_ior: f32, + }, + Projector { + origin: [f32; 3], + target_corner: [f32; 3], + target_u: [f32; 3], + target_v: [f32; 3], + count_u: u32, + count_v: u32, + current_ior: f32, + }, +} + +#[derive(Deserialize, Debug)] +#[serde(tag = "type")] +pub enum ObjectGeneratorConfig { + ObjectGrid { + count_x: u32, + count_z: u32, + position_start: [f32; 3], + step_x: [f32; 3], + step_z: [f32; 3], + template: ObjectConfig, // オブジェクトのテンプレート + }, +} + +#[derive(Deserialize, Clone)] // テンプレートはクローン可能にする +pub struct ObjectTemplateConfig { + pub shape: ShapeConfig, + pub material: MaterialConfig, +} + +// --- シーン全体のコンフィグ --- +// (ShapeConfig, MaterialConfig, ObjectConfig などは以前のものを使用) + +#[derive(Deserialize)] +pub struct SceneDefinition { + // defaultを追加して、TOMLにキーが無くてもエラーにならないようにする + //#[serde(default)] + pub ray_generators: Vec, + + //#[serde(default)] + pub object_generators: Vec, + + //#[serde(default)] + pub objects: Vec, +} + +// この関数でConfigから実行時に使うオブジェクトを生成する +pub fn build_scene_from_config(config: SceneDefinition) -> (Vec, Vec>) { + let mut rays: Vec = Vec::new(); + let mut hittables: Vec> = Vec::new(); + + // === レイの生成 === + for generator in config.ray_generators { + match generator { + RayGeneratorConfig::ParallelGrid { + origin_corner, + vec_u, + vec_v, + count_u, + count_v, + direction, + current_ior, + } => { + let corner = Vec3::from(origin_corner); + let u_step = Vec3::from(vec_u) / (count_u as f32); + let v_step = Vec3::from(vec_v) / (count_v as f32); + let dir = Vec3::from(direction).normalize(); + + for i in 0..count_u { + for j in 0..count_v { + let origin = corner + (i as f32 * u_step) + (j as f32 * v_step); + rays.push(Ray { + origin, + direction: dir, + current_ior, //..Default::default() + }); + } + } + } + RayGeneratorConfig::Projector { + origin, + target_corner, + target_u, + target_v, + count_u, + count_v, + current_ior, + } => { + let ray_origin = Vec3::from(origin); + let target_c = Vec3::from(target_corner); + let target_u_step = Vec3::from(target_u) / (count_u as f32); + let target_v_step = Vec3::from(target_v) / (count_v as f32); + + for i in 0..count_u { + for j in 0..count_v { + let target_point = + target_c + (i as f32 * target_u_step) + (j as f32 * target_v_step); + rays.push(Ray { + origin: ray_origin, + direction: (target_point - ray_origin).normalize(), + current_ior, //..Default::default() + }); + } + } + } + } + } + + // === オブジェクトの生成 === + for generator in config.object_generators { + match generator { + ObjectGeneratorConfig::ObjectGrid { + count_x, + count_z, + position_start, + step_x, + step_z, + template, + } => { + let start_pos = Vec3::from(position_start); + let x_step = Vec3::from(step_x); + let z_step = Vec3::from(step_z); + + for i in 0..count_x { + for j in 0..count_z { + let pos = start_pos + (i as f32 * x_step) + (j as f32 * z_step); + + // テンプレートを複製し、transform.positionのみ変更 + let mut obj = template.clone(); + obj.transform.position = pos.to_array(); + + let hittable: Box = obj.into(); + hittables.push(hittable); + } + } + } + } + } + + // === 個別オブジェクトの追加 === + for obj_conf in config.objects { + let material = obj_conf.material.into(); + let hittable = obj_conf.shape.into_with(material); + // ... transformの適用 ... + hittables.push(hittable); + } + + (rays, hittables) +} + +// 以下は仮のヘルパー関数 +// pub fn build_material(config: MaterialConfig) -> Material { ... } +// impl ShapeConfig { pub fn into_with(self, material: Material) -> Box { ... } } \ No newline at end of file diff --git a/crates/raytracing_config/src/model/ray_config.rs b/crates/raytracing_config/src/model/ray_config.rs index 134291a..ff28eac 100644 --- a/crates/raytracing_config/src/model/ray_config.rs +++ b/crates/raytracing_config/src/model/ray_config.rs @@ -3,10 +3,11 @@ use serde::Deserialize; use raytracing_core::Ray; -#[derive(Deserialize)] +#[derive(Deserialize, Debug)] pub struct RayConfig { pub origin: [f32; 3], pub direction: [f32; 3], + pub current_ior: f32, } impl Into for RayConfig { @@ -14,7 +15,7 @@ impl Into for RayConfig { Ray { origin: Vec3::from_array(self.origin), direction: Vec3::from_array(self.direction).normalize(), - current_ior: 1.0, + current_ior: self.current_ior, } } -} +} \ No newline at end of file diff --git a/crates/raytracing_config/src/model/scene_config.rs b/crates/raytracing_config/src/model/scene_config.rs index 5938b62..345b9c3 100644 --- a/crates/raytracing_config/src/model/scene_config.rs +++ b/crates/raytracing_config/src/model/scene_config.rs @@ -1,12 +1,29 @@ use raytracing_core::{BVHNode, Hittable, HittableList, Ray, Scene}; +use serde::Deserialize; -impl Into for SceneConfig { - fn into(self) -> Scene { +use super::object_config::ObjectConfig; +use super::object_generator_config::{ObjectGeneratorConfig, RayGeneratorConfig}; +use super::ray_config::RayConfig; + +#[derive(Deserialize, Debug, Default)] +pub struct SceneConfig { + #[serde(default)] + pub objects: Vec, + #[serde(default)] + pub object_generators: Vec, + #[serde(default)] + pub rays: Vec, + #[serde(default)] + pub ray_generators: Vec, +} + +impl From for Scene { + fn from(config: SceneConfig) -> Self { // 1. Generate all objects from config let mut all_objects: Vec> = - self.objects.into_iter().map(Into::into).collect(); + config.objects.into_iter().map(Into::into).collect(); - for generator in self.object_generators { + for generator in config.object_generators { match generator { ObjectGeneratorConfig::ObjectGrid { count_x, @@ -48,8 +65,8 @@ impl Into for SceneConfig { } // 5. Generate all rays (same as before) - let mut rays: Vec = self.rays.into_iter().map(Into::into).collect(); - for generator in self.ray_generators { + let mut rays: Vec = config.rays.into_iter().map(Into::into).collect(); + for generator in config.ray_generators { match generator { RayGeneratorConfig::ParallelGrid { origin_corner, @@ -109,4 +126,4 @@ impl Into for SceneConfig { rays, } } -} +} \ No newline at end of file diff --git a/crates/raytracing_config/src/model/shape_config.rs b/crates/raytracing_config/src/model/shape_config.rs index a21db89..50694bf 100644 --- a/crates/raytracing_config/src/model/shape_config.rs +++ b/crates/raytracing_config/src/model/shape_config.rs @@ -5,7 +5,7 @@ use raytracing_core::{ }; use serde::Deserialize; -#[derive(Deserialize, Clone)] +#[derive(Deserialize, Clone, Debug)] #[serde(tag = "type")] pub enum ShapeConfig { Sphere { @@ -146,4 +146,4 @@ impl ShapeConfig { }), } } -} +} \ No newline at end of file diff --git a/crates/raytracing_config/src/model/simulation_config.rs b/crates/raytracing_config/src/model/simulation_config.rs index 7806d6d..1acd9c5 100644 --- a/crates/raytracing_config/src/model/simulation_config.rs +++ b/crates/raytracing_config/src/model/simulation_config.rs @@ -1,22 +1,25 @@ -use std::{error::Error, path::Path}; - -use serde::Deserialize; - -use crate::{model::camera_config::CameraConfig, scene_config::SceneConfig, simulation_settings_config::SimulationSettingsConfig}; - -#[derive(Deserialize)] -pub struct SimulationConfig { - pub simulation_settings: SimulationSettingsConfig, - pub scene: SceneConfig, - #[serde(default)] - pub camera: CameraConfig, -} - -impl SimulationConfig { - pub fn load_from_path>(path: P) -> Result> { - let toml_str = std::fs::read_to_string(path)?; - let simulation_config = toml::from_str(&toml_str)?; - - Ok(simulation_config) - } -} +use std::{error::Error, path::Path}; + +use serde::Deserialize; + +use crate::model::{ + camera_config::CameraConfig, scene_config::SceneConfig, + simulation_settings_config::SimulationSettingsConfig, +}; + +#[derive(Deserialize)] +pub struct SimulationConfig { + pub simulation_settings: SimulationSettingsConfig, + pub scene: SceneConfig, + #[serde(default)] + pub camera: CameraConfig, +} + +impl SimulationConfig { + pub fn load_from_path>(path: P) -> Result> { + let toml_str = std::fs::read_to_string(path)?; + let simulation_config = toml::from_str(&toml_str)?; + + Ok(simulation_config) + } +} \ No newline at end of file diff --git a/crates/raytracing_config/src/model/transform_config.rs b/crates/raytracing_config/src/model/transform_config.rs index 0dd593b..87ce519 100644 --- a/crates/raytracing_config/src/model/transform_config.rs +++ b/crates/raytracing_config/src/model/transform_config.rs @@ -1,7 +1,7 @@ use serde::Deserialize; -#[derive(Deserialize, Clone)] +#[derive(Deserialize, Clone, Debug)] pub struct TransformConfig { pub position: [f32; 3], pub rotation_y_deg: f32, -} +} \ No newline at end of file diff --git a/crates/raytracing_core/src/primitives/bvh.rs b/crates/raytracing_core/src/primitives/bvh.rs index 816a8eb..c6a12a7 100644 --- a/crates/raytracing_core/src/primitives/bvh.rs +++ b/crates/raytracing_core/src/primitives/bvh.rs @@ -1,4 +1,4 @@ -use crate::{aabb::surrounding_box, AABB, HitRecord, Hittable, Ray}; +use crate::{primitives::aabb::surrounding_box, AABB, HitRecord, Hittable, Ray}; use rand::Rng; pub struct BVHNode { @@ -7,6 +7,16 @@ pub struct BVHNode { bbox: AABB, } +impl Clone for BVHNode { + fn clone(&self) -> Self { + Self { + left: self.left.clone_hittable(), + right: self.right.clone_hittable(), + bbox: self.bbox, + } + } +} + impl BVHNode { pub fn new(objects: &mut [Box]) -> Self { let axis = rand::thread_rng().gen_range(0..3); @@ -67,4 +77,8 @@ impl Hittable for BVHNode { (None, None) => None, } } -} + + fn clone_hittable(&self) -> Box { + Box::new(self.clone()) + } +} \ No newline at end of file diff --git a/crates/raytracing_core/src/primitives/hittable_list.rs b/crates/raytracing_core/src/primitives/hittable_list.rs index 0d57459..5afeeea 100644 --- a/crates/raytracing_core/src/primitives/hittable_list.rs +++ b/crates/raytracing_core/src/primitives/hittable_list.rs @@ -1,4 +1,4 @@ -use crate::{aabb::surrounding_box, AABB, HitRecord, Hittable, Ray}; +use crate::{primitives::aabb::surrounding_box, AABB, HitRecord, Hittable, Ray}; // A list of hittable objects pub struct HittableList { diff --git a/crates/raytracing_core/src/primitives/infinite_cylinder.rs b/crates/raytracing_core/src/primitives/infinite_cylinder.rs index b62ddfd..a86690f 100644 --- a/crates/raytracing_core/src/primitives/infinite_cylinder.rs +++ b/crates/raytracing_core/src/primitives/infinite_cylinder.rs @@ -1,89 +1,89 @@ -use crate::{AABB, CSGObject, HitRecord, Hittable, Material, Ray}; -use glam::Vec3; -// 無限円柱 -#[derive(Debug, Clone, Copy)] -pub struct InfiniteCylinder { - pub axis_point: Vec3, // 軸上の任意の点 - pub axis_dir: Vec3, // 軸の方向(正規化されていること) - pub radius: f32, - pub material: Material, -} - -impl Hittable for InfiniteCylinder { - fn intersect_all(&self, ray: &Ray, t_min: f32, t_max: f32) -> Option> { - // --- 二次方程式の係数 A, B, C を計算 --- - - let oc = ray.origin - self.axis_point; - - // ベクトルを軸に平行な成分と垂直な成分に分解する考え方を用いる - // D_perp = D - (D・V)V (Vは軸方向ベクトル) - let d_dot_v = ray.direction.dot(self.axis_dir); - let d_perp = ray.direction - d_dot_v * self.axis_dir; - - // OC_perp = OC - (OC・V)V - let oc_dot_v = oc.dot(self.axis_dir); - let oc_perp = oc - oc_dot_v * self.axis_dir; - - let a = d_perp.length_squared(); - let b = 2.0 * oc_perp.dot(d_perp); - let c = oc_perp.length_squared() - self.radius * self.radius; - - // --- 二次方程式を解く --- - - // レイが軸とほぼ平行な場合、ヒットしないか常にヒットする。簡単のためミスとする。 - if a.abs() < 1e-6 { - return None; - } - - let discriminant = b * b - 4.0 * a * c; - if discriminant < 0.0 { - return None; // 実数解なし - } - - let sqrtd = discriminant.sqrt(); - let mut hits = Vec::new(); - - // 2つの解を計算 - let t1 = (-b - sqrtd) / (2.0 * a); - let t2 = (-b + sqrtd) / (2.0 * a); - - for &t in &[t1, t2] { - if t > t_min && t < t_max { - let point = ray.origin + t * ray.direction; - - // 法線を計算 - // 軸上の最近接点 = P_axis = axis_point + ((P - axis_point)・axis_dir) * axis_dir - // 法線 N = normalize(P - P_axis) - let p_minus_a = point - self.axis_point; - let projection = p_minus_a.dot(self.axis_dir); - let point_on_axis = self.axis_point + projection * self.axis_dir; - let outward_normal = (point - point_on_axis).normalize(); - - let front_face = ray.direction.dot(outward_normal) < 0.0; - let normal = if front_face { - outward_normal - } else { - -outward_normal - }; - - hits.push(HitRecord { - t, - point, - normal, - front_face, - material: self.material, - }); - } - } - - if hits.is_empty() { None } else { Some(hits) } - } - - fn bounding_box(&self) -> Option { - None // An infinite cylinder has no bounding box. - } - - fn clone_hittable(&self) -> Box { - Box::new(*self) - } -} +use crate::{AABB, HitRecord, Hittable, Material, Ray}; +use glam::Vec3; +// 無限円柱 +#[derive(Debug, Clone, Copy)] +pub struct InfiniteCylinder { + pub axis_point: Vec3, // 軸上の任意の点 + pub axis_dir: Vec3, // 軸の方向(正規化されていること) + pub radius: f32, + pub material: Material, +} + +impl Hittable for InfiniteCylinder { + fn intersect_all(&self, ray: &Ray, t_min: f32, t_max: f32) -> Option> { + // --- 二次方程式の係数 A, B, C を計算 --- + + let oc = ray.origin - self.axis_point; + + // ベクトルを軸に平行な成分と垂直な成分に分解する考え方を用いる + // D_perp = D - (D・V)V (Vは軸方向ベクトル) + let d_dot_v = ray.direction.dot(self.axis_dir); + let d_perp = ray.direction - d_dot_v * self.axis_dir; + + // OC_perp = OC - (OC・V)V + let oc_dot_v = oc.dot(self.axis_dir); + let oc_perp = oc - oc_dot_v * self.axis_dir; + + let a = d_perp.length_squared(); + let b = 2.0 * oc_perp.dot(d_perp); + let c = oc_perp.length_squared() - self.radius * self.radius; + + // --- 二次方程式を解く --- + + // レイが軸とほぼ平行な場合、ヒットしないか常にヒットする。簡単のためミスとする。 + if a.abs() < 1e-6 { + return None; + } + + let discriminant = b * b - 4.0 * a * c; + if discriminant < 0.0 { + return None; // 実数解なし + } + + let sqrtd = discriminant.sqrt(); + let mut hits = Vec::new(); + + // 2つの解を計算 + let t1 = (-b - sqrtd) / (2.0 * a); + let t2 = (-b + sqrtd) / (2.0 * a); + + for &t in &[t1, t2] { + if t > t_min && t < t_max { + let point = ray.origin + t * ray.direction; + + // 法線を計算 + // 軸上の最近接点 = P_axis = axis_point + ((P - axis_point)・axis_dir) * axis_dir + // 法線 N = normalize(P - P_axis) + let p_minus_a = point - self.axis_point; + let projection = p_minus_a.dot(self.axis_dir); + let point_on_axis = self.axis_point + projection * self.axis_dir; + let outward_normal = (point - point_on_axis).normalize(); + + let front_face = ray.direction.dot(outward_normal) < 0.0; + let normal = if front_face { + outward_normal + } else { + -outward_normal + }; + + hits.push(HitRecord { + t, + point, + normal, + front_face, + material: self.material, + }); + } + } + + if hits.is_empty() { None } else { Some(hits) } + } + + fn bounding_box(&self) -> Option { + None // An infinite cylinder has no bounding box. + } + + fn clone_hittable(&self) -> Box { + Box::new(*self) + } +} \ No newline at end of file diff --git a/crates/raytracing_core/src/primitives/wedge.rs b/crates/raytracing_core/src/primitives/wedge.rs index 6532815..8d6c252 100644 --- a/crates/raytracing_core/src/primitives/wedge.rs +++ b/crates/raytracing_core/src/primitives/wedge.rs @@ -1,95 +1,95 @@ -use glam::Vec3; - -use crate::{AABB, CSGObject, CsgOperation, HitRecord, Hittable, Material, Plane, Ray}; -//ウェッジ -pub struct Wedge { - pub csg_object: Box, -} -// Wedge構造体の実装ブロックを追加 -impl Wedge { - pub fn new(size: Vec3, wedge_angle_rad: f32, material: Material) -> Self { - let width = size.x; - let height = size.y; - let half_depth = size.z / 2.0; - - // --- 5枚の平面を定義 --- - let p1 = Box::new(Plane { - // 底面 (y >= 0) - point: Vec3::ZERO, - normal: Vec3::Y, - material, - }) as Box; - - let p2 = Box::new(Plane { - // 垂直面 (x >= 0) - point: Vec3::ZERO, - normal: Vec3::X, - material, - }) as Box; - - // 傾斜面 - let angle_cos = wedge_angle_rad.cos(); - let angle_sin = wedge_angle_rad.sin(); - let p3 = Box::new(Plane { - point: Vec3::ZERO, - normal: Vec3::new(-angle_sin, angle_cos, 0.0), // 法線で傾きを表現 - material, - }) as Box; - - let p4 = Box::new(Plane { - // 前面キャップ (z <= half_depth) - point: Vec3::new(0.0, 0.0, half_depth), - normal: Vec3::NEG_Z, // 法線を反転させることで、zが小さい側が「内側」になる - material, - }) as Box; - - let p5 = Box::new(Plane { - // 背面キャップ (z >= -half_depth) - point: Vec3::new(0.0, 0.0, -half_depth), - normal: Vec3::Z, - material, - }) as Box; - - // --- CSGの積集合で5枚の平面を組み合わせる --- - let csg1 = Box::new(CSGObject { - left: p1, - right: p2, - operation: CsgOperation::Intersection, - }); - let csg2 = Box::new(CSGObject { - left: csg1, - right: p3, - operation: CsgOperation::Intersection, - }); - let csg3 = Box::new(CSGObject { - left: csg2, - right: p4, - operation: CsgOperation::Intersection, - }); - let final_wedge = Box::new(CSGObject { - left: csg3, - right: p5, - operation: CsgOperation::Intersection, - }); - - Wedge { - csg_object: final_wedge, - } - } -} -// WedgeのためのHittable実装を追加 -impl Hittable for Wedge { - fn intersect_all(&self, ray: &Ray, t_min: f32, t_max: f32) -> Option> { - self.csg_object.intersect_all(ray, t_min, t_max) - } - - fn bounding_box(&self) -> Option { - self.csg_object.bounding_box() - } - - fn clone_hittable(&self) -> Box { - Box::new(Wedge { - csg_object: self.csg_object.clone_hittable(), - }) - } -} +use glam::Vec3; + +use crate::{AABB, CSGObject, CsgOperation, HitRecord, Hittable, Material, Plane, Ray}; +//ウェッジ +pub struct Wedge { + pub csg_object: Box, +} +// Wedge構造体の実装ブロックを追加 +impl Wedge { + pub fn new(size: Vec3, wedge_angle_rad: f32, material: Material) -> Self { + let _width = size.x; + let _height = size.y; + let half_depth = size.z / 2.0; + + // --- 5枚の平面を定義 --- + let p1 = Box::new(Plane { + // 底面 (y >= 0) + point: Vec3::ZERO, + normal: Vec3::Y, + material, + }) as Box; + + let p2 = Box::new(Plane { + // 垂直面 (x >= 0) + point: Vec3::ZERO, + normal: Vec3::X, + material, + }) as Box; + + // 傾斜面 + let angle_cos = wedge_angle_rad.cos(); + let angle_sin = wedge_angle_rad.sin(); + let p3 = Box::new(Plane { + point: Vec3::ZERO, + normal: Vec3::new(-angle_sin, angle_cos, 0.0), // 法線で傾きを表現 + material, + }) as Box; + + let p4 = Box::new(Plane { + // 前面キャップ (z <= half_depth) + point: Vec3::new(0.0, 0.0, half_depth), + normal: Vec3::NEG_Z, // 法線を反転させることで、zが小さい側が「内側」になる + material, + }) as Box; + + let p5 = Box::new(Plane { + // 背面キャップ (z >= -half_depth) + point: Vec3::new(0.0, 0.0, -half_depth), + normal: Vec3::Z, + material, + }) as Box; + + // --- CSGの積集合で5枚の平面を組み合わせる --- + let csg1 = Box::new(CSGObject { + left: p1, + right: p2, + operation: CsgOperation::Intersection, + }); + let csg2 = Box::new(CSGObject { + left: csg1, + right: p3, + operation: CsgOperation::Intersection, + }); + let csg3 = Box::new(CSGObject { + left: csg2, + right: p4, + operation: CsgOperation::Intersection, + }); + let final_wedge = Box::new(CSGObject { + left: csg3, + right: p5, + operation: CsgOperation::Intersection, + }); + + Wedge { + csg_object: final_wedge, + } + } +} +// WedgeのためのHittable実装を追加 +impl Hittable for Wedge { + fn intersect_all(&self, ray: &Ray, t_min: f32, t_max: f32) -> Option> { + self.csg_object.intersect_all(ray, t_min, t_max) + } + + fn bounding_box(&self) -> Option { + self.csg_object.bounding_box() + } + + fn clone_hittable(&self) -> Box { + Box::new(Wedge { + csg_object: self.csg_object.clone_hittable(), + }) + } +} \ No newline at end of file diff --git a/crates/raytracing_core/src/scene.rs b/crates/raytracing_core/src/scene.rs index 0a11c29..937370d 100644 --- a/crates/raytracing_core/src/scene.rs +++ b/crates/raytracing_core/src/scene.rs @@ -1,130 +1,128 @@ -use std::clone; - -use glam::Vec3; -use rand::Rng; - -use crate::{Hittable, Material}; - -// 反射ベクトルを計算 -fn reflect(incident: Vec3, normal: Vec3) -> Vec3 { - incident - 2.0 * incident.dot(normal) * normal -} - -// 屈折ベクトルを計算(全反射の可能性も考慮) -fn refract(incident: Vec3, normal: Vec3, ior_ratio: f32) -> Option { - let cos_theta = (-incident).dot(normal).min(1.0); - let sin_theta_squared = 1.0 - cos_theta * cos_theta; - - if ior_ratio * ior_ratio * sin_theta_squared > 1.0 { - println!("全反射が発生しました! ior_ratio: {}", ior_ratio); - return None; // 全反射 - } - - let perp = ior_ratio * (incident + cos_theta * normal); - let parallel = -(1.0 - perp.length_squared()).abs().sqrt() * normal; - - Some((perp + parallel).normalize()) -} -pub struct Scene { - pub world: Box, - pub rays: Vec, -} - -pub struct SimulationSettingsConfig { - pub infinity_distance: f32, - pub max_bounces: u32, -} - -impl Scene { - pub fn simulate_rays(&self, setting: SimulationSettingsConfig) -> Vec> { - let mut result: Vec> = Vec::new(); - // --- 3. 初期光線の設定 - for ray in &self.rays { - let mut ray = ray.clone(); - // --- 3b. 光路の追跡 --- - let mut path_points: Vec = vec![ray.origin]; - let max_bounces = setting.max_bounces; - let infinity_distance = setting.infinity_distance; - - for _ in 0..max_bounces { - // The world object (a BVH or a HittableList) finds the closest hit. - let closest_hit_record = self - .world - .intersect_all(&ray, 0.001, f32::INFINITY) - .and_then(|mut hits| { - // intersect_all is expected to return sorted hits, but we sort again to be safe. - hits.sort_by(|a, b| a.t.partial_cmp(&b.t).unwrap()); - hits.into_iter().next() - }); - if let Some(hit) = closest_hit_record { - path_points.push(hit.point); - - let material = hit.material; // HitRecordから直接マテリアルを取得! - - match material { - Material::Metal { .. } => { - // For path visualization, treat metal as a perfect mirror. - ray.direction = reflect(ray.direction, hit.normal); - } - Material::Glass { ior: material_ior, .. } => { - let n1 = ray.current_ior; - let n2 = if hit.front_face { material_ior } else { 1.0 }; - let ior_ratio = n1 / n2; - - if let Some(refracted_dir) = - refract(ray.direction, hit.normal, ior_ratio) - { - ray.direction = refracted_dir; - ray.current_ior = n2; - } else { - ray.direction = reflect(ray.direction, hit.normal); - } - } - Material::HalfMirror { reflectance } => { - // 0.0から1.0までの一様な乱数を生成 - if rand::thread_rng().r#gen::() < reflectance { - // 反射する場合 - ray.direction = reflect(ray.direction, hit.normal); - } else { - // 透過する場合(方向は変わらない) - // ray.direction はそのまま - } - } - Material::Diffuse { .. } => { - // For path visualization, we stop when hitting a diffuse surface. - break; - } - Material::Light { .. } => { - // For path visualization, we stop when hitting a light source. - break; - } - } - ray.origin = hit.point + ray.direction * 0.001; - } else { - path_points.push(ray.origin + ray.direction * infinity_distance); - break; - } - } - result.push(path_points); - } - result - } -} -// 光線を表す構造体 -// origin: 始点, direction: 方向 -#[derive(Debug, Clone)] -pub struct Ray { - pub origin: Vec3, - pub direction: Vec3, - pub current_ior: f32, -} - -// 衝突(ヒット)に関する情報をまとめる構造体 -#[derive(Debug, Clone, Copy)] -pub struct HitRecord { - pub t: f32, - pub point: Vec3, - pub normal: Vec3, - pub front_face: bool, - pub material: Material, -} +use glam::Vec3; +use rand::Rng; + +use crate::{Hittable, Material}; + +// 反射ベクトルを計算 +fn reflect(incident: Vec3, normal: Vec3) -> Vec3 { + incident - 2.0 * incident.dot(normal) * normal +} + +// 屈折ベクトルを計算(全反射の可能性も考慮) +fn refract(incident: Vec3, normal: Vec3, ior_ratio: f32) -> Option { + let cos_theta = (-incident).dot(normal).min(1.0); + let sin_theta_squared = 1.0 - cos_theta * cos_theta; + + if ior_ratio * ior_ratio * sin_theta_squared > 1.0 { + println!("全反射が発生しました! ior_ratio: {}", ior_ratio); + return None; // 全反射 + } + + let perp = ior_ratio * (incident + cos_theta * normal); + let parallel = -(1.0 - perp.length_squared()).abs().sqrt() * normal; + + Some((perp + parallel).normalize()) +} +pub struct Scene { + pub world: Box, + pub rays: Vec, +} + +pub struct SimulationSettingsConfig { + pub infinity_distance: f32, + pub max_bounces: u32, +} + +impl Scene { + pub fn simulate_rays(&self, setting: SimulationSettingsConfig) -> Vec> { + let mut result: Vec> = Vec::new(); + // --- 3. 初期光線の設定 + for ray in &self.rays { + let mut ray = ray.clone(); + // --- 3b. 光路の追跡 --- + let mut path_points: Vec = vec![ray.origin]; + let max_bounces = setting.max_bounces; + let infinity_distance = setting.infinity_distance; + + for _ in 0..max_bounces { + // The world object (a BVH or a HittableList) finds the closest hit. + let closest_hit_record = self + .world + .intersect_all(&ray, 0.001, f32::INFINITY) + .and_then(|mut hits| { + // intersect_all is expected to return sorted hits, but we sort again to be safe. + hits.sort_by(|a, b| a.t.partial_cmp(&b.t).unwrap()); + hits.into_iter().next() + }); + if let Some(hit) = closest_hit_record { + path_points.push(hit.point); + + let material = hit.material; // HitRecordから直接マテリアルを取得! + + match material { + Material::Metal { .. } => { + // For path visualization, treat metal as a perfect mirror. + ray.direction = reflect(ray.direction, hit.normal); + } + Material::Glass { ior: material_ior, .. } => { + let n1 = ray.current_ior; + let n2 = if hit.front_face { material_ior } else { 1.0 }; + let ior_ratio = n1 / n2; + + if let Some(refracted_dir) = + refract(ray.direction, hit.normal, ior_ratio) + { + ray.direction = refracted_dir; + ray.current_ior = n2; + } else { + ray.direction = reflect(ray.direction, hit.normal); + } + } + Material::HalfMirror { reflectance } => { + // 0.0から1.0までの一様な乱数を生成 + if rand::thread_rng().r#gen::() < reflectance { + // 反射する場合 + ray.direction = reflect(ray.direction, hit.normal); + } else { + // 透過する場合(方向は変わらない) + // ray.direction はそのまま + } + } + Material::Diffuse { .. } => { + // For path visualization, we stop when hitting a diffuse surface. + break; + } + Material::Light { .. } => { + // For path visualization, we stop when hitting a light source. + break; + } + } + ray.origin = hit.point + ray.direction * 0.001; + } else { + path_points.push(ray.origin + ray.direction * infinity_distance); + break; + } + } + result.push(path_points); + } + result + } +} +// 光線を表す構造体 +// origin: 始点, direction: 方向 +#[derive(Debug, Clone)] +pub struct Ray { + pub origin: Vec3, + pub direction: Vec3, + pub current_ior: f32, +} + +// 衝突(ヒット)に関する情報をまとめる構造体 +#[derive(Debug, Clone, Copy)] +pub struct HitRecord { + pub t: f32, + pub point: Vec3, + pub normal: Vec3, + pub front_face: bool, + pub material: Material, +} \ No newline at end of file diff --git a/crates/raytracing_renderer/src/lib.rs b/crates/raytracing_renderer/src/lib.rs index 151b1a0..4782d0a 100644 --- a/crates/raytracing_renderer/src/lib.rs +++ b/crates/raytracing_renderer/src/lib.rs @@ -3,7 +3,7 @@ use image::{ImageBuffer, Rgb}; use rand::Rng; use rayon::prelude::*; use raytracing_config::model::camera_config::CameraConfig; -use raytracing_core::{HitRecord, Hittable, Material, Ray, Scene}; +use raytracing_core::{Material, Ray, Scene}; // --- Helper Functions for vector math and physics --- @@ -232,4 +232,4 @@ fn ray_color(ray: &Ray, scene: &Scene, depth: i32) -> Vec3 { // If the ray doesn't hit anything, it's black (scene is lit from within) Vec3::ZERO } -} +} \ No newline at end of file diff --git a/output.png b/output.png index af03be9dd2f6c139d4ebdbf06493e4ed372085b3..409730e964f246f7b08446b1b7e85cccc91973e9 100644 GIT binary patch literal 158753 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

yC^1MvWPv1mq~WnmJ1 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 From 3b97a447b633ecc7ef7e220a57df07cda99d2b64 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Mon, 6 Oct 2025 07:25:19 +0000 Subject: [PATCH 4/4] feat: Refactor renderer to use CUDA for acceleration This commit introduces a major refactoring of the rendering pipeline to leverage CUDA for significant performance improvements. The core rendering logic has been moved into a dedicated CUDA kernel, and the data structures have been adapted for GPU execution. The host-side code has been updated to manage the CUDA pipeline, including data transfer and kernel launches. The project now depends on the `rust-cuda` ecosystem and requires the NVIDIA CUDA SDK to be installed in the build environment. --- Cargo.lock | 417 ++++++++++++++++++-- crates/raytracing_cuda_kernel/Cargo.toml | 14 + crates/raytracing_cuda_kernel/src/lib.rs | 469 +++++++++++++++++++++++ crates/raytracing_renderer/Cargo.toml | 7 + crates/raytracing_renderer/build.rs | 8 + crates/raytracing_renderer/src/lib.rs | 337 +++++++--------- src/bin/render.rs | 4 +- 7 files changed, 1031 insertions(+), 225 deletions(-) create mode 100644 crates/raytracing_cuda_kernel/Cargo.toml create mode 100644 crates/raytracing_cuda_kernel/src/lib.rs create mode 100644 crates/raytracing_renderer/build.rs diff --git a/Cargo.lock b/Cargo.lock index 568da03..1368f0b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,6 +8,15 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + [[package]] name = "aligned-vec" version = "0.6.4" @@ -67,7 +76,7 @@ checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.104", ] [[package]] @@ -111,6 +120,32 @@ version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" +[[package]] +name = "bimap" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "230c5f1ca6a325a32553f8640d31ac9b49f2411e901e427570154868b46da4f7" + +[[package]] +name = "bindgen" +version = "0.71.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f58bf3d7db68cfbac37cfc485a8d711e87e064c3d0fe0435b92f7a407f9d6b3" +dependencies = [ + "bitflags 2.9.1", + "cexpr", + "clang-sys", + "itertools 0.13.0", + "log", + "prettyplease", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", + "syn 2.0.104", +] + [[package]] name = "bit-vec" version = "0.8.0" @@ -182,6 +217,15 @@ dependencies = [ "shlex", ] +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom", +] + [[package]] name = "cfg-expr" version = "0.15.8" @@ -210,7 +254,7 @@ dependencies = [ "num-traits 0.2.19", "serde", "wasm-bindgen", - "windows-link", + "windows-link 0.1.3", ] [[package]] @@ -223,6 +267,17 @@ dependencies = [ "num-traits 0.2.19", ] +[[package]] +name = "clang-sys" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" +dependencies = [ + "glob", + "libc", + "libloading", +] + [[package]] name = "color_quant" version = "1.1.0" @@ -372,6 +427,96 @@ dependencies = [ "memchr", ] +[[package]] +name = "cuda_builder" +version = "0.3.0" +source = "git+https://github.com/Rust-GPU/Rust-CUDA.git#e6e046dd79f4fc028916f02b2d9521c599848d19" +dependencies = [ + "nvvm", + "serde", + "serde_json", +] + +[[package]] +name = "cuda_std" +version = "0.2.2" +source = "git+https://github.com/Rust-GPU/Rust-CUDA.git#e6e046dd79f4fc028916f02b2d9521c599848d19" +dependencies = [ + "bitflags 2.9.1", + "cuda_std_macros", + "glam 0.29.3", + "half", + "paste", + "vek 0.17.2", +] + +[[package]] +name = "cuda_std_macros" +version = "0.2.0" +source = "git+https://github.com/Rust-GPU/Rust-CUDA.git#e6e046dd79f4fc028916f02b2d9521c599848d19" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "cust" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d6cc71911e179f12483b9734120b45bd00bf64fab085cc4818428523eedd469" +dependencies = [ + "bitflags 1.3.2", + "bytemuck", + "cust_core", + "cust_derive", + "cust_raw 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)", + "find_cuda_helper", +] + +[[package]] +name = "cust_core" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "039f79662cb8f890cbf335e818cd522d6e3a53fe63f61d1aaaf859cd3d975f06" +dependencies = [ + "cust_derive", + "glam 0.20.5", + "mint", + "vek 0.15.10", +] + +[[package]] +name = "cust_derive" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8a3bc95fe629aed92b2423de6ccff9e40174b21d19cb6ee6281a4d04ac72f66" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "cust_raw" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbf40d6ade12cb9828bbc844b9875c7b93d25e67a3c9bf61c7aa3ae09e402bf8" +dependencies = [ + "find_cuda_helper", +] + +[[package]] +name = "cust_raw" +version = "0.11.3" +source = "git+https://github.com/Rust-GPU/Rust-CUDA.git#e6e046dd79f4fc028916f02b2d9521c599848d19" +dependencies = [ + "bimap", + "bindgen", + "cc", + "doxygen-bindgen", +] + [[package]] name = "doc-image-embed" version = "0.2.1" @@ -381,7 +526,7 @@ dependencies = [ "base64", "proc-macro2", "quote", - "syn", + "syn 2.0.104", ] [[package]] @@ -390,6 +535,15 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea8a8b81cacc08888170eef4d13b775126db426d0b348bee9d18c2c1eaf123cf" +[[package]] +name = "doxygen-bindgen" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93ba4ed6eedf7f4ace1632149d8f0e8a65a480534024d65a7c3b9daacdedbad3" +dependencies = [ + "yap", +] + [[package]] name = "dxf" version = "0.6.0" @@ -467,7 +621,7 @@ checksum = "44f23cf4b44bfce11a86ace86f8a73ffdec849c9fd00a386a53d278bd9e81fb3" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.104", ] [[package]] @@ -497,7 +651,7 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2aef9e8d9e33f51d8120a2e997a819f18239ad7c2735e353ade79208a9a1c442" dependencies = [ - "glam", + "glam 0.29.3", "ndshape", ] @@ -510,6 +664,15 @@ dependencies = [ "simd-adler32", ] +[[package]] +name = "find_cuda_helper" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9f9e65c593dd01ac77daad909ea4ad17f0d6d1776193fc8ea766356177abdad" +dependencies = [ + "glob", +] + [[package]] name = "flate2" version = "1.1.2" @@ -624,15 +787,32 @@ dependencies = [ "weezl", ] +[[package]] +name = "glam" +version = "0.20.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f43e957e744be03f5801a55472f593d43fabdebf25a4585db250f04d86b1675f" +dependencies = [ + "num-traits 0.2.19", +] + [[package]] name = "glam" version = "0.29.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8babf46d4c1c9d92deac9f7be466f76dfc4482b6452fc5024b5e8daf6ffeb3ee" dependencies = [ + "bytemuck", + "libm", "serde", ] +[[package]] +name = "glob" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" + [[package]] name = "half" version = "2.6.0" @@ -814,7 +994,7 @@ checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.104", ] [[package]] @@ -907,6 +1087,16 @@ dependencies = [ "cc", ] +[[package]] +name = "libloading" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" +dependencies = [ + "cfg-if", + "windows-link 0.2.0", +] + [[package]] name = "libm" version = "0.2.15" @@ -970,6 +1160,12 @@ dependencies = [ "simd-adler32", ] +[[package]] +name = "mint" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e53debba6bda7a793e5f99b8dacf19e626084f525f7829104ba9898f367d85ff" + [[package]] name = "nalgebra" version = "0.33.2" @@ -994,7 +1190,7 @@ checksum = "254a5372af8fc138e36684761d3c0cdb758a4410e938babcff1c860ce14ddbfc" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.104", ] [[package]] @@ -1080,7 +1276,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.104", ] [[package]] @@ -1133,6 +1329,15 @@ dependencies = [ "libm", ] +[[package]] +name = "nvvm" +version = "0.1.1" +source = "git+https://github.com/Rust-GPU/Rust-CUDA.git#e6e046dd79f4fc028916f02b2d9521c599848d19" +dependencies = [ + "cust_raw 0.11.3 (git+https://github.com/Rust-GPU/Rust-CUDA.git)", + "strum", +] + [[package]] name = "once_cell" version = "1.21.3" @@ -1207,6 +1412,16 @@ dependencies = [ "zerocopy", ] +[[package]] +name = "prettyplease" +version = "0.2.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff24dfcda44452b9816fff4cd4227e1bb73ff5a2f1bc1105aa92fb8565ce44d2" +dependencies = [ + "proc-macro2", + "syn 2.0.104", +] + [[package]] name = "proc-macro2" version = "1.0.95" @@ -1232,7 +1447,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "52717f9a02b6965224f95ca2a81e2e0c5c43baacd28ca057577988930b6c3d5b" dependencies = [ "quote", - "syn", + "syn 2.0.104", ] [[package]] @@ -1411,7 +1626,7 @@ name = "raytracing_cli" version = "0.1.0" dependencies = [ "csv", - "glam", + "glam 0.29.3", "rand", "raytracing_config", "raytracing_core", @@ -1424,7 +1639,7 @@ name = "raytracing_config" version = "0.1.0" dependencies = [ "csv", - "glam", + "glam 0.29.3", "rand", "raytracing_core", "serde", @@ -1436,24 +1651,64 @@ name = "raytracing_core" version = "0.1.0" dependencies = [ "csv", - "glam", + "glam 0.29.3", "rand", "serde", "toml", ] +[[package]] +name = "raytracing_cuda_kernel" +version = "0.1.0" +dependencies = [ + "cuda_std", + "glam 0.29.3", +] + [[package]] name = "raytracing_renderer" version = "0.1.0" dependencies = [ - "glam", + "cuda_builder", + "cust", + "glam 0.29.3", "image", "rand", "rayon", "raytracing_config", "raytracing_core", + "raytracing_cuda_kernel", +] + +[[package]] +name = "regex" +version = "1.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b5288124840bee7b386bc413c487869b360b2b4ec421ea56425128692f2a82c" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "833eb9ce86d40ef33cb1306d8accf7bc8ec2bfea4355cbdebb3df68b40925cad" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", ] +[[package]] +name = "regex-syntax" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "caf4aa5b0f434c91fe5c7f1ecb6a5ece2130b02ad2a590589dda5146df959001" + [[package]] name = "rgb" version = "0.8.52" @@ -1483,6 +1738,15 @@ version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + [[package]] name = "rustversion" version = "1.0.21" @@ -1504,24 +1768,53 @@ dependencies = [ "bytemuck", ] +[[package]] +name = "semver" +version = "1.0.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" + [[package]] name = "serde" -version = "1.0.219" +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 = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.219" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.104", +] + +[[package]] +name = "serde_json" +version = "1.0.145" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", + "serde_core", ] [[package]] @@ -1613,12 +1906,44 @@ dependencies = [ "float-cmp", ] +[[package]] +name = "strum" +version = "0.27.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af23d6f6c1a224baef9d3f61e287d2761385a5b88fdab4eb4c6f11aeb54c4bcf" +dependencies = [ + "strum_macros", +] + +[[package]] +name = "strum_macros" +version = "0.27.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7695ce3845ea4b33927c055a39dc438a45b059f7c1b3d91d38d10355fb8cbca7" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.104", +] + [[package]] name = "svg" version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94afda9cd163c04f6bee8b4bf2501c91548deae308373c436f36aeff3cf3c4a3" +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "syn" version = "2.0.104" @@ -1675,7 +2000,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.104", ] [[package]] @@ -1686,7 +2011,7 @@ checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.104", ] [[package]] @@ -1791,6 +2116,30 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "vek" +version = "0.15.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8085882662f9bc47fc8b0cdafa5e19df8f592f650c02b9083da8d45ac9eebd17" +dependencies = [ + "approx", + "num-integer", + "num-traits 0.2.19", + "rustc_version", +] + +[[package]] +name = "vek" +version = "0.17.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25215c4675beead435b254fc510932ff7f519cbc585b1b9fe2539ee9f20ca331" +dependencies = [ + "approx", + "num-integer", + "num-traits 0.2.19", + "rustc_version", +] + [[package]] name = "version-compare" version = "0.2.0" @@ -1834,7 +2183,7 @@ dependencies = [ "log", "proc-macro2", "quote", - "syn", + "syn 2.0.104", "wasm-bindgen-shared", ] @@ -1856,7 +2205,7 @@ checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.104", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -1894,7 +2243,7 @@ checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" dependencies = [ "windows-implement", "windows-interface", - "windows-link", + "windows-link 0.1.3", "windows-result", "windows-strings", ] @@ -1907,7 +2256,7 @@ checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.104", ] [[package]] @@ -1918,7 +2267,7 @@ checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.104", ] [[package]] @@ -1927,13 +2276,19 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" +[[package]] +name = "windows-link" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45e46c0661abb7180e7b9c281db115305d49ca1709ab8242adf09666d2173c65" + [[package]] name = "windows-result" version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" dependencies = [ - "windows-link", + "windows-link 0.1.3", ] [[package]] @@ -1942,7 +2297,7 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" dependencies = [ - "windows-link", + "windows-link 0.1.3", ] [[package]] @@ -1981,6 +2336,12 @@ dependencies = [ "xml-rs", ] +[[package]] +name = "yap" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfe269e7b803a5e8e20cbd97860e136529cd83bf2c9c6d37b142467e7e1f051f" + [[package]] name = "zerocopy" version = "0.8.26" @@ -1998,7 +2359,7 @@ checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.104", ] [[package]] diff --git a/crates/raytracing_cuda_kernel/Cargo.toml b/crates/raytracing_cuda_kernel/Cargo.toml new file mode 100644 index 0000000..a80dc7b --- /dev/null +++ b/crates/raytracing_cuda_kernel/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "raytracing_cuda_kernel" +version = "0.1.0" +edition = "2024" + +[dependencies] +cuda_std = { git = "https://github.com/Rust-GPU/Rust-CUDA.git", package = "cuda_std" } +glam = "0.29.3" + +[lib] +crate-type = ["cdylib", "rlib"] + +[profile.release] +panic = "abort" \ No newline at end of file diff --git a/crates/raytracing_cuda_kernel/src/lib.rs b/crates/raytracing_cuda_kernel/src/lib.rs new file mode 100644 index 0000000..fb9144a --- /dev/null +++ b/crates/raytracing_cuda_kernel/src/lib.rs @@ -0,0 +1,469 @@ +#![no_std] +#![feature(abi_ptx)] +#![feature(std_internals)] +#![feature(core_intrinsics)] + +use cuda_std::*; +use glam::Vec3; + +// --- GPU Data Structures --- + +#[derive(Copy, Clone)] +pub enum GpuMaterial { + Metal { color: Vec3, fuzz: f32 }, + Glass { color: Vec3, ior: f32 }, + HalfMirror { reflectance: f32 }, + Diffuse { color: Vec3 }, + Light { color: Vec3 }, +} + +#[derive(Copy, Clone)] +pub struct Sphere { + pub center: Vec3, + pub radius: f32, + pub material: GpuMaterial, +} + +#[derive(Copy, Clone)] +pub struct Plane { + pub point: Vec3, + pub normal: Vec3, + pub material: GpuMaterial, +} + +#[derive(Copy, Clone)] +pub struct GpuAxisAlignedBox { + pub min: Vec3, + pub max: Vec3, + pub material: GpuMaterial, +} + +#[derive(Copy, Clone)] +pub struct GpuInfiniteCylinder { + pub axis_point: Vec3, + pub axis_dir: Vec3, + pub radius: f32, + pub material: GpuMaterial, +} + +#[derive(Copy, Clone)] +pub enum GpuHittable { + Sphere(Sphere), + Plane(Plane), + AxisAlignedBox(GpuAxisAlignedBox), + InfiniteCylinder(GpuInfiniteCylinder), +} + +#[derive(Copy, Clone)] +pub struct GpuCamera { + origin: Vec3, + lower_left_corner: Vec3, + horizontal: Vec3, + vertical: Vec3, +} + +impl GpuCamera { + pub fn new(lookfrom: Vec3, lookat: Vec3, vup: Vec3, vfov: f32, aspect_ratio: f32) -> Self { + let theta = vfov.to_radians(); + let h = (theta / 2.0).tan(); + let viewport_height = 2.0 * h; + let viewport_width = aspect_ratio * viewport_height; + + let w = (lookfrom - lookat).normalize(); + let u = vup.cross(w).normalize(); + let v = w.cross(u); + + let origin = lookfrom; + let horizontal = viewport_width * u; + let vertical = viewport_height * v; + let lower_left_corner = origin - horizontal / 2.0 - vertical / 2.0 - w; + + Self { + origin, + lower_left_corner, + horizontal, + vertical, + } + } + + #[inline(always)] + pub fn get_ray(&self, s: f32, t: f32) -> Ray { + Ray { + origin: self.origin, + direction: (self.lower_left_corner + s * self.horizontal + t * self.vertical - self.origin).normalize(), + current_ior: 1.0, + } + } +} + +#[derive(Copy, Clone)] +pub struct GpuScene<'a> { + pub hittables: &'a [GpuHittable], +} + +impl<'a> GpuScene<'a> { + pub fn hit(&self, ray: &Ray, t_min: f32, t_max: f32) -> Option { + let mut closest_so_far = t_max; + let mut hit_record = None; + for hittable in self.hittables { + if let Some(hit) = hittable.intersect(ray, t_min, closest_so_far) { + closest_so_far = hit.t; + hit_record = Some(hit); + } + } + hit_record + } +} + + +#[derive(Copy, Clone)] +pub struct Ray { + pub origin: Vec3, + pub direction: Vec3, + pub current_ior: f32, +} + +impl Ray { + #[inline(always)] + pub fn at(&self, t: f32) -> Vec3 { + self.origin + t * self.direction + } +} + +#[derive(Copy, Clone)] +pub struct HitRecord { + pub t: f32, + pub point: Vec3, + pub normal: Vec3, + pub front_face: bool, + pub material: GpuMaterial, +} + +impl HitRecord { + #[inline(always)] + pub fn face_normal(ray: &Ray, outward_normal: Vec3) -> (Vec3, bool) { + let front_face = ray.direction.dot(outward_normal) < 0.0; + let normal = if front_face { + outward_normal + } else { + -outward_normal + }; + (normal, front_face) + } +} + +// --- Intersection implementations --- + +impl Sphere { + pub fn intersect(&self, ray: &Ray, t_min: f32, t_max: f32) -> Option { + let oc = ray.origin - self.center; + let a = ray.direction.length_squared(); + let half_b = oc.dot(ray.direction); + let c = oc.length_squared() - self.radius * self.radius; + let discriminant = half_b * half_b - a * c; + + if discriminant < 0.0 { + return None; + } + let sqrtd = discriminant.sqrt(); + let mut root = (-half_b - sqrtd) / a; + if root < t_min || t_max < root { + root = (-half_b + sqrtd) / a; + if root < t_min || t_max < root { + return None; + } + } + + let t = root; + let point = ray.at(t); + let outward_normal = (point - self.center) / self.radius; + let (normal, front_face) = HitRecord::face_normal(ray, outward_normal); + + Some(HitRecord { + t, + point, + normal, + front_face, + material: self.material, + }) + } +} + +impl Plane { + pub fn intersect(&self, ray: &Ray, t_min: f32, t_max: f32) -> Option { + let denominator = self.normal.dot(ray.direction); + if denominator.abs() < 1e-6 { + return None; + } + let t = (self.point - ray.origin).dot(self.normal) / denominator; + if t < t_min || t > t_max { + return None; + } + let point = ray.at(t); + let (normal, front_face) = HitRecord::face_normal(ray, self.normal); + Some(HitRecord { + t, + point, + normal, + front_face, + material: self.material, + }) + } +} + +impl GpuAxisAlignedBox { + pub fn intersect(&self, ray: &Ray, t_min: f32, t_max: f32) -> Option { + let mut tmin = t_min; + let mut tmax = t_max; + + for i in 0..3 { + let inv_d = 1.0 / ray.direction[i]; + let mut t0 = (self.min[i] - ray.origin[i]) * inv_d; + let mut t1 = (self.max[i] - ray.origin[i]) * inv_d; + + if inv_d < 0.0 { + core::mem::swap(&mut t0, &mut t1); + } + + tmin = tmin.max(t0); + tmax = tmax.min(t1); + + if tmax <= tmin { + return None; + } + } + + let t = tmin; + let point = ray.at(t); + let outward_normal = self.calculate_normal(point); + let (normal, front_face) = HitRecord::face_normal(ray, outward_normal); + + Some(HitRecord { + t, + point, + normal, + front_face, + material: self.material, + }) + } + + fn calculate_normal(&self, point: Vec3) -> Vec3 { + let epsilon = 1e-4; + if (point.x - self.min.x).abs() < epsilon { return Vec3::NEG_X; } + if (point.x - self.max.x).abs() < epsilon { return Vec3::X; } + if (point.y - self.min.y).abs() < epsilon { return Vec3::NEG_Y; } + if (point.y - self.max.y).abs() < epsilon { return Vec3::Y; } + if (point.z - self.min.z).abs() < epsilon { return Vec3::NEG_Z; } + if (point.z - self.max.z).abs() < epsilon { return Vec3::Z; } + Vec3::ZERO + } +} + +impl GpuInfiniteCylinder { + pub fn intersect(&self, ray: &Ray, t_min: f32, t_max: f32) -> Option { + let oc = ray.origin - self.axis_point; + let d_dot_v = ray.direction.dot(self.axis_dir); + let d_perp = ray.direction - d_dot_v * self.axis_dir; + let oc_dot_v = oc.dot(self.axis_dir); + let oc_perp = oc - oc_dot_v * self.axis_dir; + + let a = d_perp.length_squared(); + let b = 2.0 * oc_perp.dot(d_perp); + let c = oc_perp.length_squared() - self.radius * self.radius; + + if a.abs() < 1e-6 { + return None; + } + + let discriminant = b * b - 4.0 * a * c; + if discriminant < 0.0 { + return None; + } + + let sqrtd = discriminant.sqrt(); + let mut t = (-b - sqrtd) / (2.0 * a); + if t < t_min || t > t_max { + t = (-b + sqrtd) / (2.0 * a); + if t < t_min || t > t_max { + return None; + } + } + + let point = ray.at(t); + let p_minus_a = point - self.axis_point; + let projection = p_minus_a.dot(self.axis_dir); + let point_on_axis = self.axis_point + projection * self.axis_dir; + let outward_normal = (point - point_on_axis).normalize(); + let (normal, front_face) = HitRecord::face_normal(ray, outward_normal); + + Some(HitRecord { + t, + point, + normal, + front_face, + material: self.material, + }) + } +} + + +impl GpuHittable { + pub fn intersect(&self, ray: &Ray, t_min: f32, t_max: f32) -> Option { + match self { + GpuHittable::Sphere(s) => s.intersect(ray, t_min, t_max), + GpuHittable::Plane(p) => p.intersect(ray, t_min, t_max), + GpuHittable::AxisAlignedBox(b) => b.intersect(ray, t_min, t_max), + GpuHittable::InfiniteCylinder(c) => c.intersect(ray, t_min, t_max), + } + } +} + +// --- Helper Functions for Kernel --- + +#[inline(always)] +fn reflect(v: Vec3, n: Vec3) -> Vec3 { + v - 2.0 * v.dot(n) * n +} + +#[inline(always)] +fn refract(uv: Vec3, n: Vec3, etai_over_etat: f32) -> Vec3 { + let cos_theta = (-uv).dot(n).min(1.0); + let r_out_perp = etai_over_etat * (uv + cos_theta * n); + let r_out_parallel = -(1.0 - r_out_perp.length_squared()).abs().sqrt() * n; + r_out_perp + r_out_parallel +} + +#[inline(always)] +fn schlick(cosine: f32, ref_idx: f32) -> f32 { + let mut r0 = (1.0 - ref_idx) / (1.0 + ref_idx); + r0 = r0 * r0; + r0 + (1.0 - r0) * (1.0 - cosine).powi(5) +} + +// LCG random number generator for the GPU +#[inline(always)] +fn lcg(seed: &mut u32) -> f32 { + *seed = seed.wrapping_mul(1664525).wrapping_add(1013904223); + (*seed as f32) / (u32::MAX as f32) +} + +#[inline(always)] +fn random_in_unit_sphere(seed: &mut u32) -> Vec3 { + loop { + let p = Vec3::new(lcg(seed) * 2.0 - 1.0, lcg(seed) * 2.0 - 1.0, lcg(seed) * 2.0 - 1.0); + if p.length_squared() < 1.0 { + return p; + } + } +} + +// --- Main Kernel Logic --- + +fn kernel_ray_color(mut ray: Ray, scene: &GpuScene, max_depth: i32, seed: &mut u32) -> Vec3 { + let mut color = Vec3::ONE; + for _ in 0..max_depth { + if let Some(hit) = scene.hit(&ray, 0.001, f32::INFINITY) { + let emitted = match hit.material { + GpuMaterial::Light { color } => color, + _ => Vec3::ZERO, + }; + + let (maybe_scattered, attenuation) = match hit.material { + GpuMaterial::Light { .. } => (None, Vec3::ZERO), + GpuMaterial::Diffuse { color } => { + let scatter_direction = hit.normal + random_in_unit_sphere(seed).normalize(); + let scattered = Ray { + origin: hit.point, + direction: scatter_direction, + current_ior: ray.current_ior, + }; + (Some(scattered), color) + } + GpuMaterial::Metal { color, fuzz } => { + let reflected = reflect(ray.direction.normalize(), hit.normal); + let scattered = Ray { + origin: hit.point, + direction: reflected + fuzz * random_in_unit_sphere(seed), + current_ior: ray.current_ior, + }; + if scattered.direction.dot(hit.normal) > 0.0 { + (Some(scattered), color) + } else { + (None, Vec3::ZERO) + } + } + GpuMaterial::Glass { color: _, ior } => { + let etai_over_etat = if hit.front_face { 1.0 / ior } else { ior }; + let unit_direction = ray.direction.normalize(); + let cos_theta = (-unit_direction).dot(hit.normal).min(1.0); + let sin_theta = (1.0 - cos_theta * cos_theta).sqrt(); + let reflect_prob = schlick(cos_theta, etai_over_etat); + + let direction = if etai_over_etat * sin_theta > 1.0 || lcg(seed) < reflect_prob { + reflect(unit_direction, hit.normal) + } else { + refract(unit_direction, hit.normal, etai_over_etat) + }; + let scattered = Ray { + origin: hit.point, + direction, + current_ior: if hit.front_face { ior } else { 1.0 }, + }; + (Some(scattered), Vec3::ONE) // Glass is perfectly transparent + } + _ => (None, Vec3::ZERO), + }; + + color *= attenuation; + if let Some(scattered) = maybe_scattered { + ray = scattered; + } else { + return emitted; + } + } else { + return Vec3::ZERO; // Background + } + } + Vec3::ZERO +} + +#[no_mangle] +pub unsafe extern "ptx-kernel" fn render_kernel( + hittables: *const GpuHittable, + hittable_count: u32, + camera: *const GpuCamera, + output: *mut Vec3, + width: u32, + height: u32, + samples_per_pixel: u32, + max_depth: i32, +) { + let thread_idx = thread::idx().x; + let block_idx = block::idx().x; + let block_dim = block::dim().x; + + let i = block_idx * block_dim + thread_idx; + if i >= width * height { + return; + } + + let x = i % width; + let y = i / width; + + let scene = GpuScene { + hittables: core::slice::from_raw_parts(hittables, hittable_count as usize), + }; + let camera = &*camera; + + let mut pixel_color = Vec3::ZERO; + let mut seed = (i as u32).wrapping_mul(123456789); + + for _ in 0..samples_per_pixel { + let u = (x as f32 + lcg(&mut seed)) / (width - 1) as f32; + let v = (y as f32 + lcg(&mut seed)) / (height - 1) as f32; + let ray = camera.get_ray(u, v); + pixel_color += kernel_ray_color(ray, &scene, max_depth, &mut seed); + } + + *output.add(i as usize) = pixel_color / samples_per_pixel as f32; +} \ No newline at end of file diff --git a/crates/raytracing_renderer/Cargo.toml b/crates/raytracing_renderer/Cargo.toml index b6ff9ab..246bc0b 100644 --- a/crates/raytracing_renderer/Cargo.toml +++ b/crates/raytracing_renderer/Cargo.toml @@ -10,3 +10,10 @@ glam = { workspace = true } image = "0.25.1" rand = "0.8" rayon = "1.5" + +# CUDA dependencies +cust = "0.3.2" +raytracing_cuda_kernel = { path = "../raytracing_cuda_kernel" } + +[build-dependencies] +cuda_builder = { git = "https://github.com/Rust-GPU/Rust-CUDA.git", package = "cuda_builder" } \ No newline at end of file diff --git a/crates/raytracing_renderer/build.rs b/crates/raytracing_renderer/build.rs new file mode 100644 index 0000000..a9e8f67 --- /dev/null +++ b/crates/raytracing_renderer/build.rs @@ -0,0 +1,8 @@ +use cuda_builder::CudaBuilder; + +fn main() { + CudaBuilder::new("../raytracing_cuda_kernel") + .copy_to("kernel.ptx") + .build() + .unwrap(); +} \ No newline at end of file diff --git a/crates/raytracing_renderer/src/lib.rs b/crates/raytracing_renderer/src/lib.rs index 4782d0a..8427ba2 100644 --- a/crates/raytracing_renderer/src/lib.rs +++ b/crates/raytracing_renderer/src/lib.rs @@ -1,90 +1,94 @@ +use cust::prelude::*; use glam::Vec3; use image::{ImageBuffer, Rgb}; -use rand::Rng; -use rayon::prelude::*; use raytracing_config::model::camera_config::CameraConfig; -use raytracing_core::{Material, Ray, Scene}; - -// --- Helper Functions for vector math and physics --- - -fn reflect(v: Vec3, n: Vec3) -> Vec3 { - v - 2.0 * v.dot(n) * n -} - -fn refract(uv: Vec3, n: Vec3, etai_over_etat: f32) -> Vec3 { - let cos_theta = (-uv).dot(n).min(1.0); - let r_out_perp = etai_over_etat * (uv + cos_theta * n); - let r_out_parallel = -(1.0 - r_out_perp.length_squared()).abs().sqrt() * n; - r_out_perp + r_out_parallel +use raytracing_core::{Hittable, HittableList, Material, Plane, Scene, Sphere, Transform}; +use raytracing_cuda_kernel::{ + GpuAxisAlignedBox, GpuCamera, GpuHittable, GpuInfiniteCylinder, GpuMaterial, +}; +use std::error::Error; + +// This embeds the PTX file generated by the build script +const PTX: &str = include_str!(env!("KERNEL_PTX_PATH")); + +/// Converts the CPU-side scene representation (using trait objects) +/// into a flat list of GPU-compatible structs. +struct GpuSceneConverter { + gpu_hittables: Vec, } -fn schlick(cosine: f32, ref_idx: f32) -> f32 { - let mut r0 = (1.0 - ref_idx) / (1.0 + ref_idx); - r0 = r0 * r0; - r0 + (1.0 - r0) * (1.0 - cosine).powi(5) -} - -fn random_in_unit_sphere() -> Vec3 { - let mut rng = rand::thread_rng(); - loop { - let p = Vec3::new( - rng.gen_range(-1.0..1.0), - rng.gen_range(-1.0..1.0), - rng.gen_range(-1.0..1.0), - ); - if p.length_squared() < 1.0 { - return p; +impl GpuSceneConverter { + fn new() -> Self { + Self { + gpu_hittables: Vec::new(), } } -} -// --- Camera --- - -pub struct Camera { - origin: Vec3, - lower_left_corner: Vec3, - horizontal: Vec3, - vertical: Vec3, -} + fn convert(mut self, scene: &Scene) -> Vec { + self.flatten_hittable(scene.world.as_ref(), glam::Mat4::IDENTITY); + self.gpu_hittables + } -impl Camera { - pub fn new(lookfrom: Vec3, lookat: Vec3, vup: Vec3, vfov: f32, aspect_ratio: f32) -> Camera { - let theta = vfov.to_radians(); - let h = (theta / 2.0).tan(); - let viewport_height = 2.0 * h; - let viewport_width = aspect_ratio * viewport_height; - - let w = (lookfrom - lookat).normalize(); - let u = vup.cross(w).normalize(); - let v = w.cross(u); - - let origin = lookfrom; - let horizontal = viewport_width * u; - let vertical = viewport_height * v; - let lower_left_corner = origin - horizontal / 2.0 - vertical / 2.0 - w; - - Camera { - origin, - lower_left_corner, - horizontal, - vertical, + fn flatten_hittable(&mut self, hittable: &dyn Hittable, transform: glam::Mat4) { + if let Some(s) = hittable.downcast_ref::() { + let center = transform.transform_point3(s.center); + self.gpu_hittables.push(GpuHittable::Sphere( + raytracing_cuda_kernel::Sphere { + center, + radius: s.radius, + material: self.convert_material(s.material), + }, + )); + } else if let Some(p) = hittable.downcast_ref::() { + let point = transform.transform_point3(p.point); + let normal = transform.transform_vector3(p.normal).normalize(); + self.gpu_hittables.push(GpuHittable::Plane( + raytracing_cuda_kernel::Plane { + point, + normal, + material: self.convert_material(p.material), + }, + )); + } else if let Some(b) = hittable.downcast_ref::() { + self.gpu_hittables.push(GpuHittable::AxisAlignedBox( + GpuAxisAlignedBox { + min: transform.transform_point3(b.min), + max: transform.transform_point3(b.max), + material: self.convert_material(b.material), + }, + )); + } else if let Some(c) = hittable.downcast_ref::() { + self.gpu_hittables.push(GpuHittable::InfiniteCylinder( + GpuInfiniteCylinder { + axis_point: transform.transform_point3(c.axis_point), + axis_dir: transform.transform_vector3(c.axis_dir).normalize(), + radius: c.radius, + material: self.convert_material(c.material), + }, + )); + } else if let Some(list) = hittable.downcast_ref::() { + for obj in &list.objects { + self.flatten_hittable(obj.as_ref(), transform); + } + } else if let Some(t) = hittable.downcast_ref::() { + let composed_transform = transform * t.transform; + self.flatten_hittable(t.primitive.as_ref(), composed_transform); } + // Other hittable types like BVH, CSG, etc., are ignored for this CUDA implementation. } - pub fn get_ray(&self, s: f32, t: f32) -> Ray { - Ray { - origin: self.origin, - direction: (self.lower_left_corner + s * self.horizontal + t * self.vertical - - self.origin) - .normalize(), - current_ior: 1.0, + fn convert_material(&self, mat: Material) -> GpuMaterial { + match mat { + Material::Metal { color, fuzz } => GpuMaterial::Metal { color, fuzz }, + Material::Glass { color, ior } => GpuMaterial::Glass { color, ior }, + Material::HalfMirror { reflectance } => GpuMaterial::HalfMirror { reflectance }, + Material::Diffuse { color } => GpuMaterial::Diffuse { color }, + Material::Light { color } => GpuMaterial::Light { color }, } } } -// --- Main Rendering Logic --- - -/// Renders the scene and saves it to a file. +/// Renders the scene using the CUDA kernel and saves it to a file. pub fn render( scene: &Scene, camera_config: &CameraConfig, @@ -92,9 +96,28 @@ pub fn render( height: u32, samples_per_pixel: u32, max_depth: u32, -) { - // Camera - let camera = Camera::new( +) -> Result<(), Box> { + // --- 1. Initialize CUDA and Load Kernel --- + let _ctx = cust::quick_init()?; + let module = Module::from_str(PTX)?; + let stream = Stream::new(StreamFlags::DEFAULT, None)?; + + // --- 2. Convert Scene to GPU format --- + let converter = GpuSceneConverter::new(); + let gpu_hittables = converter.convert(scene); + + if gpu_hittables.is_empty() { + println!("Warning: No compatible objects found for GPU rendering. Ensure your scene contains Spheres, Planes, Boxes, or Cylinders."); + // Create a blank image + let img_buf: ImageBuffer, Vec> = + ImageBuffer::from_pixel(width, height, Rgb([0, 0, 0])); + img_buf.save("output.png").unwrap(); + println!("Saved a blank 'output.png'."); + return Ok(()); + } + + // --- 3. Setup Camera --- + let camera = GpuCamera::new( camera_config.lookfrom, camera_config.lookat, camera_config.vup, @@ -102,134 +125,58 @@ pub fn render( width as f32 / height as f32, ); - // Render using Rayon for parallel processing - let pixels: Vec> = (0..height) - .into_par_iter() - .rev() // Start from the top row - .flat_map(|j| { - (0..width) - .map(|i| { - let mut pixel_color = Vec3::ZERO; - let mut rng = rand::thread_rng(); - - for _ in 0..samples_per_pixel { - let u = (i as f32 + rng.r#gen::()) / (width - 1) as f32; - let v = (j as f32 + rng.r#gen::()) / (height - 1) as f32; - let ray = camera.get_ray(u, v); - pixel_color += ray_color(&ray, scene, max_depth as i32); - } - - // Average color and apply gamma correction - let scale = 1.0 / samples_per_pixel as f32; - let r = (pixel_color.x * scale).sqrt(); - let g = (pixel_color.y * scale).sqrt(); - let b = (pixel_color.z * scale).sqrt(); - - Rgb([ - (256.0 * r.clamp(0.0, 0.999)) as u8, - (256.0 * g.clamp(0.0, 0.999)) as u8, - (256.0 * b.clamp(0.0, 0.999)) as u8, - ]) - }) - .collect::>() + // --- 4. Allocate and Copy Data to GPU --- + let hittables_gpu = DeviceBuffer::from_slice(&gpu_hittables)?; + let camera_gpu = DeviceBuffer::from_slice(&[camera])?; + let mut output_gpu = unsafe { DeviceBuffer::uninitialized((width * height) as usize)? }; + + // --- 5. Launch Kernel --- + let grid_size = (width * height + 255) / 256; + let block_size = 256; + + let kernel = module.get_function("render_kernel")?; + + unsafe { + launch!( + kernel<<>>( + hittables_gpu.as_device_ptr(), + gpu_hittables.len() as u32, + camera_gpu.as_device_ptr(), + output_gpu.as_device_ptr(), + width, + height, + samples_per_pixel, + max_depth as i32 + ) + )?; + } + stream.synchronize()?; + + // --- 6. Copy Result from GPU and Save Image --- + let mut output_cpu = vec![Vec3::ZERO; (width * height) as usize]; + output_gpu.copy_to(&mut output_cpu)?; + + let pixels: Vec> = output_cpu + .into_iter() + .map(|pixel_color| { + // Apply gamma correction (sqrt) + let r = (pixel_color.x).sqrt(); + let g = (pixel_color.y).sqrt(); + let b = (pixel_color.z).sqrt(); + Rgb([ + (256.0 * r.clamp(0.0, 0.999)) as u8, + (256.0 * g.clamp(0.0, 0.999)) as u8, + (256.0 * b.clamp(0.0, 0.999)) as u8, + ]) }) .collect(); - // Create image buffer from pixel data let raw_pixels: Vec = pixels.into_iter().flat_map(|p| p.0).collect(); let img_buf: ImageBuffer, Vec> = ImageBuffer::from_raw(width, height, raw_pixels).unwrap(); - // Save the image img_buf.save("output.png").unwrap(); - println!("レンダリングが完了し、'output.png' に保存されました。"); -} - -// Recursively traces a ray and determines the color. -fn ray_color(ray: &Ray, scene: &Scene, depth: i32) -> Vec3 { - if depth <= 0 { - return Vec3::ZERO; - } - - // Find the closest hit by intersecting the ray with the world object (which could be a BVH). - let closest_hit = scene - .world - .intersect_all(ray, 0.001, f32::INFINITY) - .and_then(|mut hits| { - // The list of hits should be sorted by t, so we can just take the first one. - hits.sort_by(|a, b| a.t.partial_cmp(&b.t).unwrap()); - hits.into_iter().next() - }); - - if let Some(hit) = closest_hit { - // Calculate emitted light from the material itself - let emitted = match hit.material { - Material::Light { color } => color, - _ => Vec3::ZERO, - }; - - // Calculate scattered light - let (maybe_scattered, attenuation) = match hit.material { - Material::Light { .. } => (None, Vec3::ZERO), // Lights emit, but don't scatter - - Material::Diffuse { color } => { - let scatter_direction = hit.normal + random_in_unit_sphere().normalize(); - let scattered = Ray { - origin: hit.point, - direction: scatter_direction, - current_ior: ray.current_ior, - }; - (Some(scattered), color) - } + println!("GPUレンダリングが完了し、'output.png' に保存されました。"); - Material::Metal { color, fuzz } => { - let reflected = reflect(ray.direction.normalize(), hit.normal); - let scattered = Ray { - origin: hit.point, - direction: reflected + fuzz * random_in_unit_sphere(), - current_ior: ray.current_ior, - }; - // Absorb rays that scatter below the surface - if scattered.direction.dot(hit.normal) > 0.0 { - (Some(scattered), color) - } else { - (None, Vec3::ZERO) - } - } - - Material::Glass { color, ior } => { - let attenuation = color; // Use the material's color for attenuation - let etai_over_etat = if hit.front_face { 1.0 / ior } else { ior }; - let unit_direction = ray.direction.normalize(); - let cos_theta = (-unit_direction).dot(hit.normal).min(1.0); - let sin_theta = (1.0 - cos_theta * cos_theta).sqrt(); - let reflect_prob = schlick(cos_theta, etai_over_etat); - - let direction = if etai_over_etat * sin_theta > 1.0 - || rand::thread_rng().r#gen::() < reflect_prob - { - reflect(unit_direction, hit.normal) - } else { - refract(unit_direction, hit.normal, etai_over_etat) - }; - - let scattered = Ray { - origin: hit.point, - direction, - current_ior: if hit.front_face { ior } else { 1.0 }, - }; - (Some(scattered), attenuation) - } - _ => (None, Vec3::ZERO), // Unhandled materials - }; - - if let Some(scattered_ray) = maybe_scattered { - emitted + attenuation * ray_color(&scattered_ray, scene, depth - 1) - } else { - emitted - } - } else { - // If the ray doesn't hit anything, it's black (scene is lit from within) - Vec3::ZERO - } + Ok(()) } \ No newline at end of file diff --git a/src/bin/render.rs b/src/bin/render.rs index da86216..b374bad 100644 --- a/src/bin/render.rs +++ b/src/bin/render.rs @@ -17,7 +17,7 @@ fn main() -> Result<(), Box> { settings.image_height, settings.samples_per_pixel, settings.max_bounces, - ); + )?; Ok(()) -} +} \ No newline at end of file

C+BWkSMdU-h;H~Q}madeDwclpQMcd+*M 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 A-~a#s literal 158803 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%0AVBIenrfUt@L`QQPcm+7VMhYj5vS@8k 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ξ0`IfnBFu@)P<8*ktK;IQ?{=i&Td zm;KNnqdP^}=LOuH*qgIYA3R8ZdMQ#1&~)JL@2*hx$@#oI+ca%HWbjvS$ptEzK7XMs zS@eNycP9E!ycchLye*DQO zxk8}>T=jKh%)ql}Fj&p+>)CSRry$Gi`L9B~6bb(FC9`L~zX0P8IIxuSuZoa#clS?& zU(1*ryl9XDydXW;>d#LHxHZmyGP$YXkV|JG(g=jtbdh%@pt^;#b;GJ%PEMul*D}3; zqSM8ki%!BBwjX#6)lt!w2et7y8*w4C>vjC3aB=HgZ>GKf4l&yhCF@D^wdTQA!aO;u zfarf`a$k4ltxv-BxMSLgSr`ndrHNpIgV_VR1f)nTVZ!egRne*{geMO{5MRNn zcRb7M1l2b)-dEP?>+TKugGqM7^{?%ySjrEsC!eh-16wFWb&6J99-EL5uh0qZ>-BhB zK<929!Q!SDMV>8B9z)>;U}QMG{P~Rxf{GUk-(~fdHO?uB>3}McS}gOo=hs#jf$4Kz zs$(c$ch{*CD!VVFfZC^m#ysCgh}aJdwi~3*GtFXKb|1(!{K8i2lW_m|b-Zza=lPPK zbmd=L)P0bz6;NqXXeCgl%;-(>bRQkqoI77e8=)WpR#N5a5#rfH;Y*J6Nvs@Jz+p#&*U` z5!Fxw?BtAx>L$^d+Fi2i>7F4o#tpB?3cW``+}G&fQHb4-#mE{5e>yt45EN!4wWRCN z!v6B;5zMBdA~W}-&-~6mxfG}vG_AgqPanX>$KeA$tO_yNx2){jm?bPdo+uwZQ*gew zF*WrWn0XlDmviOk#Nd>I_A?2<5uc}`0pNelk@)!C4}TJ5=+u1xg5GiOPmUJU9j!=4 z2zI7K^1)7->ucm!G*$=4u;|dx-P?O`q+*8$!VLNu)Z(opWb=&|Gn>iLcCUWfg(HBN z6kvz-F)cM2R9Ee&!gS90!sLk+XpJfaXnl-Mj%W?pN;J<n!@|YkMrZc{lxs=sT;G*u0X-zew)Lg645YT-STpy<@k!VX^ z3K#$p7=@vf!6`Xkj5fio4V&taiw#a4Cp>i#UD0+VNFa1%zN-Rhl_B1ohlCmCz?*h6 zmm!OQ|7*^2yVVmVK&^McfFjP(?*7Cex^}~j3{B}i!hr0&Vh69G_k(8T4M2JO6wXKb zQJAinI9%*+r3{)Ho$Hs%NK~eQm@`@C7Lp!$Kz}egc=<$WS?}u8R1JW$ZfjsR#{i$R zdFNZ$HYKqVE$B<$a9zbZFUj8$4|sx5aA-6;F&bLZIzYyOC(t;0_A*W_ zsBAZbd?#BjffQw8f=tWPPZqZh>j`BVH1x83)6>T4L?IsNoUq|ybANxoj3b9e3NU`pzl;Bc!+%X{wey>O|;au9=don$15>n_d_c5v7u3PVPCe~ zkSBU^tv?qOY%6t#9}})xceg@RKlsGbHV~J9OI?jDtEFsKW_$5B^n%vKpDbe;=3goFB)w z%aZT47h@7)d^NgusJbw{7q}bnA!HH_VG4{}=ta{6hXZF89h)7R8-2*dxuFutPS}93 z3KMU51;=JFVp;aoArcf?CLBum`#k*2rj{m*O(lolKXN)D+!0H@M9Q4HnwPEu3OjGI zxD2c?V1)fY)y~|6{OvO4g~{CxEXuq_PzusGR@(;#?rf*N%YAikGIHd!*bX1pnbh5I zZm-qxCc^!}%YY5Q)DnL#^2=MrXyFS3)@y5GzOPEsPsyN#?!y@vwtXF3TPppu>bZNT zmcrTANwXF^`j>luSwTxn5Ew|abz94*%7{j=iW!xiHJWW4f++{5_UX1?4O4$bH*BMY zjNo_)9si&e_NQ{|r4(WZ#hzdNM5uF~z!SbbFrWI<3b>ygtvFUHSwjd9Vka31VI%H^ z&oA^Mst{XG7T^Ozdn8gm@G(A3HM`rpzNil;Q?>JL|MH>4^IC=zq)UMA!oGDSufcO58nb!fb@XxfGC z#{?`%v^B!R-;=3k(wN^ii;;LpeYUni*U)LP?C_bsEsKusk58Tkc_bFt8&QrOs;a+s z8`k5Emvwi)?>$h}yF36zgPo=r9o{vKMp7mOK^yX-X5Nq3rS2w{3-hJ<@{DdFvd^rC z^wb82qN4fXg1A@iQ_XbmT79~BwIg;ku7wT!tA40`W=<_FHz7P)OHQU|S7sALZ%7J$ zsMTttBXQLEaM{LlU}^N~M8@CYS_08I_2P^>gz#x@!U2rRVd0>VbDKdk64$EAsGare z9W}LAb|WR|wagu#1wPPjz;R=p?5mw`;~F9bp6~Nnf{#k=+ZZUcrnbZV)4hi940KiCBv zS#8zj%MBOMgUz4!WGHahEig;jU`BWb(NKfY6fnm+E>*&%NaRv^aQW6tlJp@Yab!r2 zj<_7^`ER+jFiqRn*O2a(7ZA9ehe<6x)^*K8KB_6Woo)l_X6yc_Zs$8RHDShwlcX*E znZfW;X*gW)&jrB4&oXZN%2oMSK{m-GJ63WTdNPBw%F$TpdZL<#(jqI%69Zh_VW5H` z9Y3x2xID`6KVYMNsK#~FAmqRwc&(c|ZvxjVfX61B=Ybp>F|;<`m8U!h;Uj;_ECRMw zg$dEiwr&T->llpNW8_jPd1Pzjo<5>)H;^D#J6XTyz*Luv>wN_DU z2#duRz4SA1_a}3=)h~Z{8}@Tw2)}KXhhQcJFsoXq#q#n=j*Mil+O?h9IlWK_YHYem z8i+Dx=1GI~B-nQFy~AICD8qr@vi)c$lzfok=}Vx-p=2>+{^}ddX7{wo%htK7-m=lL zOrOc`5e_hgI7Uk$2O9R4$D7s-N>Pj$$G@_A(DR4Av3pch{zVBkna{gJXgO?yjM=iG z=dklcoB9&2odxUTBRnfMvdAEiz2gnnv)<))&MA`3OF8=KB?! z7I->4Q_AZD$<8p}X$W31Q96y%n)&cymh>aj3KUPhp!DH>n=KRSpZyk{^fS=cQbUyk zUS5YH5iA8~rfV~ET9F79aDb=#PI4FgVksD;^Dr4ZV*n2~NMN{NHe(rp=WFvLRCj?t zRv4QwiDKrfD(J9={=q9+z=0w9fFxx*<=&cOy$_VLeAvs0IeV?3poz&jE;A}ONg_qM zXFt9>^jC!f@j}hm+ditz1jzzw$`eLo3J5XxUp%FW?DBmJr8dqYP4BJIbLYUJs83|u zCpS7oPiN{!`02^XRI=Ex3zS#4%nPeJVSZKP9LPZ?{i2|1DrKDO1)Vu@^*TKB`L+;8 z3%)S9jQ$gak_X+mO0Kx_K#+%bJ(YE6m8Rdx@!Ewjz)}y>+ zgh-pxe@>fzw9C0-w<=^f^x&XlJy8D^C+Rr&S-0Gf6<>gwQ-#LZm=67#Gjf7xf(S zgbXrU+(8tAi0gK4!~-4)fKYr-DuEqv4eGZB@3HDeq3oMA3w8aDO^?$@vF=4e?TbuM zj~v|Hv`iO5!qRnRLMIRccC{zw<$>LZjks-{3>B;JK;KWbDVuhN4eK4;+_c`F^qFa+ z!I(O`r@Py^2_^VHU|VBpD}p<`K#CQBLxa=S-;a`j*0BheSp6cX(~{dq&nrFTF@twE z?36_ve{VMZaU#*6p^kJ6xC>KDd)Grf{e9jI6@MwY)rPAJB8L9amFRhPf?h3zKQlUD`UVRHG2wzhW$9Xsgh$gXhDr zw+YOL2AYxz6TF_>p{SS<$uH2L-?j1%o$LfcozrTN?L433V*95DxM~!BT zpA@qwsv{Me2X9ZhhTt8_ge9N?gl9}BVEBaX2n%=xXqh9AcRR0WdvH)>j+wz#WtA80 zAn(>yO?VY{TawfbnfBx>^tONDoCF=vapqXjr$`fUb3-hEt>oa0OZPqKdsep=0cK~E zO?Jhj*s%({Li7FmG;=XKgl&AQFgDraZ)E``D|p<2JNU3E@%mVlN}?dR@d{RFYLpvi`q86Pv9x5~E%fE0 zLd6=QMS_dHz_vqPfScWQIM-Rf${<%9;2gN*Ly*ZpV-VSVZ)P-sU@}yx43)G8b6Kx+?c9KnOggAiFOGh8pAFcS94q-aN_M?qFPT!C&M0nLlNBT2779l>SGD3qI3b~W*U|f%eHbo=M zrXAskjGzYarxFlgiPGP2$*<(q@eJTMK>TnRgbRg)=Kf>GZlu+&q_g(&i&yVigK4M4Cw+#eY|;4he97uN$v-nbrRJl12scR zY4NPn=mCY|r`p=6<19zkf%U&XT7>%!eeQdCd6&%yIRp^*G^*;+9N|Ms4$+Or8oEdxZ#QjX6P@r0l#9hFH(CDrf3LRFgb$2@*yS^wW zzy;USK-{`%Go;bqhdr7DzrW^vKImajbx0ka7ss&iQ$djm9_+YghUc6OVz<4`Qz3-y zKIo?JK(7`t9@ttm`_Hub$1Y<|OpbcNQpnb8Go({k;W%=a74>b|iL@VJJ2ZU91@edR zn?$S!T^uL~E?n!V4XPDk5p;x+qjS)9g>l4a?8XIgVD5H1KOH0Z%eaE=5t`xh%GPy5 z-@{l#V0a4F9^%q2U%ni+E2CRQ^#@Q;)pW2Of0qZT# zadokdYnC@=I(u1)M;;x*IOq~?K$k&Wa#Sxl^BGpSriVfw=F7u26RgN^8=r-?^Jt-> zSC}YBh4H0pyt*qmxUM7T`9EM2nA^(E&aylO9*Q>-=f-(x@g4s?8WBd8J2PH#_6+w~ zq)%6`SJi|VM8b{T{r9iX1L}474Gtsh6r8L85K*9@w8H~NsTFaT zThfUUI3P$|6?3H=?I^73uoPQI5K)L@u&HHf0m zO#h4pO4{)!8^h8EKrR@ycgcra+{lwBH03qnHvUFc21}I4A~DQeHo=_k-=I{{+B ziEq=>Q}piw5ay^ep)7OM=3d2tP4^l~IQ!GL$8UmgU@L<0Q{I$puSJ*OQ6=I+BK(Q5 z&j+DQTH#2~z5Ac4$j1(ljIW&?M)oEU-r>&lu*JqMefD zGIk&2E%6bWm{q%2QLsvS%6Nnd3mj!lnb$@>SwL3vi*Ke>xr8|zkx44Dd@*20b{q>fdRoG_fJr!z6tLL*Bnys zlx24DuYUPs8z77w@`Ur6%P>RR|E?vT3`(=^#gz}9Ov1S9$$ITuby=^%X{#63Vb zq+v(OkCS%+Gy}*Qz#QjL^V|R4_HMo}R|W$;guQp1U0JQsYJ1nN$#Q*-)1H7@I?U0D zDKpx^(^3URJd$C>Af+4=cpg;sr;21fsA^5vWQ1?6z~O+_h?h?-8nH~^Uf`ZqVNZ4* zQ-vHvgQTf)Qm>h(W?^&I){tIt5d_>V90S129T2W0<|3!Uor`n~1Y}YWAO@%L$gd-E z2{`pAU^LxPq+6l8;cXPtcrDb3S2G!?^KsAupeNumrnL0Je9w-{XmxCBDp+lgSKC%7 zeltN4%l`#M5S{_DK7QL0bi)t2|5}8MrLgXv2i?~{>Z?a|pzq%}fsMZ;%Kyf|u>r3E z7qZ3xt=w>W0{imt+Fja2`K17U>}cD&@E?MO7|bR$Ak|My$38(&dhl#+BmxWG)Yywh z-#MZ!mEAOaP~G<&Smzj}Y2%w?;b&WqVL9Shqp`{Tfj8-{x}ni9X!6*UCHLk7S4VB# ze*dFNyW;R-mEnGDi8QaedVi_robuAl9N^=7S*!EZl{6und)q(%k8OxT5rf8#;Lh5s zf?}}F#B^L4z(XAbg%@MzGSP7V(AZO{6zUv#%C+Cy303IOQGfnZP!{0DfkqRq zCQ*i)moN9)*%?1zb;HHqgi+|y(sP$oElMt3@{7oX_3xc=wJb6673847@oxGBaWn`6 zJq+WcCI+bxInX;Gl~IOb48%eO#8GY^xSmsPt*#cHaT!Dw5g>%gs3bH1OqcfbKGgJ# zbnh!$KR&bP+ftt+Jm*DB?exUb(wzo8n^u<~!pgH-N0wZwhR9-`1kL~Q;#<2~NwH!5 z4_tu6j}v9QxqS;K;pUdS)#sG=I(G+;b@a$HGK%dpBePaR9GvB)T{WBDZ)8k{@!-wS zk4<MN>5()|w2f2J$D;^HXJN|^L6%f$J9Yak7K2n;FXd!>uQD~p_F-b}=9c8<-WqlM z)$s0sk8}2wtOcoiE964p*#{#rfGkO0!YPkEbn9eT<>k(?@n_HO4j=v4;Si?AyeYI8 z6_q~dd{l4kGMG_P_IohB`1auTsjE@JIfLP;#$B60x`%tU}G1i0^osZ zFmxGM%!NbG={`d29sM#kIl2^1`aON#Xm1q-6!C~p(Nu&x1|`{WPPJV~1G5vFa*fc1I6xvs|oP#MlF3K$704J^0N_BqP~AvH!j2ehV6O zz4O?zVD&xA({TS@6h5R~K#oPT&$B-h*)^`A23obl{GjzOBMqb;_F)B~O>i-L6d}5* zV|gS+@pxj%NXf~Q?fNZ^=n0q?p5wBnK?_RFprnvh)Kt^_nGf;^HcU-qEwCcS{7`Od zmNO4q?iSLl7ihZkybXW9c@7_n;8amVNTdqg52#mI?RcsvWvDoqk5?kHFYa2D^v{Ne zx4*csL;e?b5O??XR#<1XLW&s-b<8O(_(xJvgKFN$=K<-ztpW_wc99C$Gpux*&)}64q{r1&PCPbre1UAkjcR6bu^VP^x@ekmG69Nafl? zHOcM6!|zg8#-_Klhf47QFzqesuzB2~@Lb6a{**a3V8`!F zHO6hZE^~-U7x`}FJFm|P#7&2$1;oX9E&{GbJ9%GzXWa>;q1j!%_R%Ybh1}&g^=PzZ zaj*YgIsGF@{21}<-x5Cz!k&L?0cZ65S}Vd6OB<}2ubzE~wy(B* zt$*3R5|yn<5_Ru%HyaRfduth2tat-nlhi344jVyv`UEL&y}!_soh=;thsnowg5vSg zul>rYmSmMkIJB`oui z`3l!Lgi5Z)kOPu+(*6C5aESV89_v7qqNAeEqr3Hf%UZRD%7cUD6*;BAXW$Y4Dk;UW z^Qgbt85nq|bV>WCSC*=#lGZsKs_snu)7w|XqU4FrT?Ib~U{;B!u>Hc}Tn2-eE|jVe z<#RKruzyQZlO^4`LLlO%iyCTzm`EK85fS6@*Ab~R!bzT>oH#IP{y`ecsbb&2_ybf! z^dayM`g=wci+`!r?&_#IA~9qYQ`>P3?IQB;@&ikwFSZ&3OjIw9A;$pY6?sVVL}*h- z&(~Zc7{x3?o3OXCTN@#$S{fvTc6p?gC9P{W!Uu>F4f&M73>lpWKT}gskTP6g?AzGI z;}CoGhN4HiAxi4WNKX@9knFJ#zzS1mt!Z1SO8U+;ntkEEk_^b1kCX-Esd0=&u?q%} zw}-I;ir(roVmNf58z5i?Q4^>cSY2IzYy-ZG>b~D>4p6}afzbnABQ3*&rK<2Za&~O* zzSNqd^vG+qK%AP4(B)_iDHUO7&wXzQH5|6QZdv05@HC)z%BGCQ#)2{vJ_$XKAZk{r zOzk(e9>CcT+`r6_?kvRA-4(6yz=}~@9PaRyAKA_?5&R4#bWp7E?z%LA8=Vq?@}1O!a~0j%Nh zv(qbTSgWD~UA~}|4GUH`cR$V=J>hdw!0S)n1x19N&tPP(8h~8dMFYnEe6lH{=U3{r zE+P^C0gM`ZybchsQz^xK>*tEl2+g`BOSXX@_!2&yUi$JV&Y$y}x=ihpAk>4TF=o^W zvzvE48p*hX&)$FIfOl$GSn-9Xd4Q!07q9f4AKOr^ywg_|JO zxtU1&%+dfp#wwUq{8J#Vj~Q6u<<;up-FJP8z#*I?S5c-ATiDRpC=dDV=%)(fA!E&s zoN51!xuEIwgt51wH_i2dmG%B`f*Z`~r~+PVtq`4w-zz3F0| zmZU-*hhsZ>GNEsZ5Y(9qITk}9r_3wqdgg&L8T?lfd>;LG8>tkaDczF(mEk^cAV<%J zgbtp9dkY^Xy1Oq(kR(ZKXg3zyW}u4t+Jm@~|Je4{;lHCBiSFqGL`_t)eKH{I{gw2G zc6lSd5O&?xs_MoBeyX!C{9>{Tbu>t}XHRy#QcZR8tQRG04qL-{;1~8g zFs0KNp00J)na<73#m*~Iv5@b<yFVehC(bjamv4p$JO;>+fkBH zEf|tpSR>}??|*dmV&^PS7JP-$jhJn}-;|xfZL+~iOO7A+IUKsC2pOTc0VHteJGB(- zr&qa*)sAzIL61=*t3i2fuh>x2B)?HRQw+XNP#x&Abq9!d$ynH;6b1{pR`zY&F$FNH zW*CW;bnb9u^!xq&=405h4E!bdVUkRKvtsueJbpauO;{^m&0w9dOEK$)g0|4dvV*Afan2}Hr4Ihq8NS+4t ztIWLT47?6#!^*t8BAqiA@sY%zi2g~02#e4A6ZPHdR^S|W(50dG14r*GL;??9OjoI1g5?#Ybn3J^iF{lyprvYmf+N8|ZSBKifbi z?uT<&pu{<=h-4+-nbAWD5vkeiJoED#kMGBZO6Ao-XgZ9iLs$R@S*$9<|};A3zJucKWkX2f9I!Kb|74b8nY-(Br1SwhJnnN*dN-nEsVsuMN2 zyBpD-LvOaGOk~I|ob6aJkzSF!;DYuW&h(Uw>EZD--A-)jS-K>nPj~0`n|3#3Z{&!c z!%_arE{7&ByDYFpkT`sjBU6Ej$$tkgxlb4%7cv)9x_!=!4D^4bnJ5hgx6j1_z&IlU zN~fo3CT_vMg@p-K(LG(i4acGRJnYez&>w)Xh^PIc0WILF*YE&14~`>Pa%GSN^>eGmvFmYYm*Z zw!gk6+Q%aqYcnY$guN!&PqQgJsfnJyLT!?# z7=$mQKc{C%SOlcFQ zwTO_gVH=dNwm+;DLuGW6ls3~!%&&Y2J{~GFQ7q{t@IJwx#Q@GOMnjOuli&qcUmsxi z;^j2+_tz80{^e}$`WOt3$X^ydy<4)J4W8wT>pLXwX4<2g#hTFv_Vmp$Z|xTfX$LrTJ7Z2pETMg2a)0Qz|*KC zxbe+CJN6#piwegF?b62yD9(gQjCSDh3G0&w{wW}CyCx~mxg(|n6hY8jY1uG;#47f_ zb?W5SLOwAYBZ3u{Bf;84P`(;;&Iw3iZ5T#yo2HuEox`p5^L-9!%ucwQ+T(fcU_5NFal~`Iz>`tptgac$sLS|LYsbzIe{P@kCf*y`RP_o z!M)|z_e2(JBy|S=VL^dQ-Ps?gNMUr40SLs9<AP{f^txMJML^>MJVTv-)Uew)rq};Qm!2O<{Cn z!N4bSO&Ktg>r*J&QTn7#3S|EjsCE^Q*>0oF)SFU%rtjzs(fMuu+P@aG>rUOnMVN<7kMx+kkcw<7h|cMO>TF5nNs ztsgKg>VzUlk;Q4q>l4TPc~3Bb;2QLbM|u$nv!zIEMDu!C3|a z$6466iJdhg+r#cHv zA1lyakfm6n;D0l!o-mqlzjBr|VEo>ybwRLps4#Wl&f$t0I0Yf0*Y_Vk2?!2s zjIEy<9|wcnGyf`X5_Ijv6tY3!b0g6FlBttb1$(e@=sDoPB2BYES(Hu&d9#?^f~jmT zoVYJS45E6KYD%Hg_V*d1HE?AFn8U8qvRs+3WyH-pK&|GpX*K=>`^dzR1n zoXT_dX{nj2C!+Pu@Rnpp7_lfvQn?fQ!TL*|Qrn@ocXjJ|8? z>s}nfvtMTagc{=2g9l|zkh1}EprusX{-cU{{s(_;6!BYB`X9{Lcf@9k2}fSkh|(<6 zW0(DMvTqI960#R?>g$mfE1G4K=aH^$5Esr&be zWv0t&Q-4&hXVaxYls)Q6I(}SA3h0ZSezeU-Q(Shw&M*u zU{gn1_^FY``bhol!4Bf*(Zv)89IMF^$)J$0WlOn0GPUFYqBES^HX!0(%%@$X9~aUx z>^|Km&0t7d^k1DkS>Kh>OLAhr3Jq*yqrJ0l!dkk24;?Enk7=Wk32dKC1iSQ!mKpHQ zqMAM8k2|@~Hgi4wuY$MU*;V$C=b}%yeie*K$_fa_Fin-a)^zJZeY|sT!s6<~H8r2d zHO|SZWv09@GY*YrD>aB5tN-S_kg%*Yvt1<`S5>7p&6%`+8KKQ?}yU)zPBtKOQwP{2RBZ$9yC7(DsI zEeUhsao(>o6hf!|;u^1orUjXzUvIm$Q5XDau>g7<7*gDZe7~F(UmnMA44mSep+zAw zWEd%n!y3D+L$4hU^eaNAN)&HJ%RxdL5u5X-SJSUNNQwYdw#NOz1OiSDl21Q zZXA-C?*tZ}Svj$tVX19KjVMowZF#ROT2au0Y@X7wX+`a*>-O!U&NTL2r4*P8GHSb6 zijGtuP3-fEQnH@_KcG;mZ{MSLKLuqHXMS^yTL&cBT=sk_2Xj3t-sJbCX?`cFAf67< z29*mT`kVZ19reuaqUxnNZ!#uya;Hf{3%)phDA4gU^369g^p=~bxA(EN)rs=C@NSt1 z8m=zv8{VCo*Lp1J$gQGI*=I5ORdxJfQSX0zSvcCGvsX-M3HKknt+ju+-Vd$zM9Zb1 z#JrDs78MG7vlmRWLiK^sIb~1up`g{1y#> z$&(vQYoU9wi6kl0f8g8BNJ%`-__U&!^wwqENmgBBv9|Bdds#lMd=D_{XV+ha+=j1w zao6fi-NbwR?yDnoj60bydpGRgt^UlddFta#Xu0~peDGeg(&!p#h z3*-WFIZ%20c_TYqN|0Lo0L_J*+}w4xnd>Y38NvJ6s_C~cG;?kxTm5Gh^BwaK`UBZd znU}rd%Xdy*xb%q+ihGg$AN!2#v-T_t&w|{mR&Uz8>7~)&YY*U6MQMWd5u8zx#vDa4 zPSY6Uz98nF59`1_Vyj@s+Q|IYJ_OOvAqXjJtL0x5wR_rUM$C`7$4}0Gu|W8#R#Cr2 zERBs@28(DKWsGcJFi&ul5C-W-{Vg*-Y+2^L^4iAiSJENAt_z4Xi|Vm}kpA;l+#F@R zttW1)9JxKgsCtlPeDm^_TE#SXmW6Iz-)YRFnqCU-y;Gm|MBT#9Z(VRC3z~@?FzsrC-8wC)?{<0aXycK0Og-B5kg?c z4auf4Sww;tDyl-v9j9u0leD&|6g5-F4v|;ltopi!d zd=sS1h_608KkA>EF?&&gsO~wFE6?bI{mpF$t#6IWTCtWy zP?w@BILz$AG8@ny00$@@RE2Mmr>(6c^Av9_0+-IhYT)9<>{&rq=gz&FMj%08W#88| zHFr1aXaVOkm+oIuw|(U(11ihXQFZp)dQsgW_%DxlrP*e(&R=d$KdS$I}Aj$FC$*<)+GpYx<^OJ)IH5msr+Ku7i+U$f+ zs8RIAHZ!}M+SCw+l5T*ITXT+-E~aJ(JCYIMW7Cu;t}x9d65_2N^x zX$vi^j<8bBhjo0K*z04TD6!@lR{fmLrR0&bh#weR4ubnteO>nc zgB~8%{XE6koScV-E19z&-c%f%dHmGD-)dDA{vN#$)dgyyC9e|@tZm?Z%_huU#DkAk zHQu_{Mm5i2tEqY?>@qLJkX>lyZ5MVo#Q&BPS$Xv^O9pEZ#@$ueQ$V3768n93|1|$` zAH>H4`%<+dzzJXe-DmCR$4nz7fnDJm@kp6NxEjic;pGC?%h4i1UAL%?Q3I#wp0w;Y z%4%X#RC$MBG{*sbHmq--W$*X#itoSEw|6fc52UN?O;sUYTT7$% zEY^5Jpd7BSfB6GO;dgDQJ5ZrDT?#UES-Hu{f8m(Q=7|l#Z#M^}+XuND6p3e_KT*Eq zUG-_QH&?ivDZom#I(K>E+NRT>JE9~dRpiaKHdeIEC|w?Z_jNgd{!7Tz^$5-4ljO(- z%5pP-^e!O6?1h4qgl*zU$k7kYNfaS7KEO28D5FkA1or4+bp2?(?DV zg$HOw1VZW{rG|u9@>s^Ue-kzG#7=)dtR8SSX( zG5NF&;C@Dr>aB%xWYg)3BlmsjU_|h#4@l7M8`lokFYJMXS{V{jSk{WuURjmee~`5q zxaP(qM`TraH>q81-NdP%mB~t-5Q{~M8!fx%&nB&Vl~oM4GjhdQ?C_{Kl&{)07zg@T zu~jseg*6tDePB^nws@GdE-@`u*Ryp?K_E|d&3usxW#|c?k&ibYP`0%W6kD0?6{YNx z=s?#Gj4)B8tW#Qc@E{wy*rbj=5=ji=)CLxSR8|}&g`)T>wX&7K7jp)S^yJECKNrv!D>+ zQ7z@~m&q-Hq24_aRNmT8NAKTnXRu>jlf*`5N#dQEPXPOvNeBu<)BWPVhJ(olKLGz7 z8NtjA(^XvQ)YCd^Q}%%4Z{k@@npRt*y4Fz{W@FwhAwYj7G>j#gUj>&J_J|ng&fG+_ z#6$3&dVR30<)|1N3e(nf7F})WDOMjbrM9Tp5#f_=|ByWcHYAY7`bh{g1AC&FmulqY zCk3U4Cbyg@FGovk@;Isw&VNhFPQ5`$shn|?O+?^Y27K3Pa%(M!U`mqBhrFms`5tLQ zDEYiMKl%7vUzQt{yr!u@qi+p(FKco|_&(5%6sP=XHjoroiEbHdIvAFT7}U&eZN7c` z1^?k+RDNZU5eSRH@&vU+l&+X%hVAXNLCArpAa+YDWAsWm!|i8s8A$U&``^Bn{^M*` z07l=tiSQ7NmGijEU2%Kh&22AFd!fDBSoQ*)pKIEL+{qLt`8 z&yvlgB_*}a`(Uu19{7>WLhmmG)x)5AVDKKRGSkFTatyS^H7}{lZoOeNX64Eq%ATa( zWyqF~d2tnG#<9N_q6F&QaR&75=OV6z)wX3-DHCw5^&hYbC|uBJiS_EjcIp z?4hPtQbzWy_dDWqRKgi;b*dX<)9Do5P{VxDg2Ng*_e__aR-^3YLG!OA(CEqrQbk*) zYWvhfH8m@?9iHm$K*Z+Wyi@BF=v7I4L({+D;YA86F3pX3j|T9_ zs8YL6)!D->GpbtNl`&AE@S*+t zYd452XTuQ{VbWBZBY9mQo|%0$rD?Ft*$zK)3$&7TKxG>eZte2lq+YXT{^Kb+b6qrB zl%ck-1*fb?@B2__=0?_VDZAGVF`5k4MHTNGdhMmsX$tx(`wc_w=iKc?8l@^yauDGh zklC^@mnW+h{c?%r-$A?DnKILm*(aKioaJKVIs|S4O9~+PrLyjmaGud#5y;=VM5f^r%Og0Utzd1cT%ikkoE z8Kq=2QeQ2qT=4}yLWW-0A;yL^v8bT2*05rP8G`=mGnTCC9FO$^}NR} zTz7c}+Ee2U`E$}8eXuy8tn4(ZM=Pht4%!6xLC#kk*RYHwSBFXm*UloF;!OKJPVwQu z1sk_)$RC{d#%%awyAIEPPPQ%l1y!CdE2&1p0f7Pi7TjB$A0B7H16w{u?ylCN?Y()N z1(}{^LD-<CPKNenX3Xcu;;VIRGHXah)QYsi`3pG+@~#X7%7@^P z^m!4`C%7shkzB0#v!0D?EJxh{!;cbP0Q<%OdwXu9S#UEruTbqYW5chXnjiBgR!UOD zJT-S<1oauW=Y>rlSUuc$= z-XA5|6CYc(y_nhm<9H@?pIpbj8K3ytl0B!?vd@i%0V;NG3JjR7cTn>InYy8NLOw}_ z#?u0oJPp1;+K{Fp!If>hp;B0Ycu?vhmgL53&?GRd&4Z8vHu9;m0a&SOi2k zdLJpPLZ~uC087rZb2E4Nvp+{o#hfUF+>Ms!0&u5tbHP;EL6&(^y9Q8A%#KGwUZMqPCe0< zJ$>rb`0K)O2^(n(5fKtz$g*E>tmPhL$qFzaVDrWq+{==T3G^ARz86IyqTmYy)mqzm zbx*tqms2Ygbt0!P>4DrYd8>RS8=n1f(-;9i_sG6k4bc_i&{BBYq|w4v?_rn0!A#vd zTQ<>0jx;Ik61Sd)`uduhd90cyYcGyp)52_RfNFjFFRE9*`kQe#CNPlPlwgEA9e>QU z)n#frGjfZ^Pvgb_?S+gC>AMI)LTXHHHW^N+K0ki7uBWTeeJU#atd+Za^F;A~yz9T@ ztQ1_;>`M^LQ###}7hp{!EV3IrJ+AQ$qaGLTXi6V@XLGKTRkjOR`LOn;dLYY_;;C1y6IHzZj3cZhZb!%j6(nQTW81_8nut4>iRyDym!1DRb~cyuChG5 zcEa3IPuX|HGjR9$nt(20pF(POVIk|Cc1oa?B@0!sxrOpIaDG;-^y6RyN;N?A7ys1q zx0FK`TcyuRH&0xTB$$%Q#PxJX)lNYW%%-zU#1&ZmRdYoZ)8z_Y0Aq1e0MpC44O_c+ zKk1sePVTV8c1WQ^PfS$?e*E>ctrKFyp zEMnZO>ejOF;{m5BPac-++;#L>AT6g`K54Rcs!O)Jbgk=nkGXogc$ZZa z8L%U$3s`0x`XXz#lx2DCO5#v3()JMm6!m*pP$dm1-1LJu$%dq*X`?#>?JcQ%fo!5! zbl5Mx{@l6!d#9xK$Hf`q$&%MEJv3~^)LZXd(ieeG72p2g!ls;+-a(rqz4i*4;CI%U zOrBF3{gae2k}gwp?NTEoI!p+1+P{ZLLpktLj^o9DT|F*o$RUw`Ow&)Zi3usQnXkt~ zY?nrkbEWu7cG1vUAF-yTf(4-f91J5#b|8%T zyiIXW55r#}uM#1|MbQnzhG{z`iX%NxlNtTmvSRkFP^Rka)SoD|1vg5TTj zi&7p1@d+ZOO=T)w7B9<*+rP%cC$@jEb}>4O;1ZC4ebW{U75JFnTN4gs0xsy4-17RV z!nR~tQ#heoA z^&I<;LYoUbUQf7oVj0MX_&}p=vUUpu30^NXEUBHh^0vhySSl|=qN@td?;(|&U=ch@ zHucc^o)x5i#?@|ioI!-B2c359wlj4`M+=dt;K^C6r1ibDF_JVo#8b9#S=aH3*eVTRBrYmpBLN;ALaRBw(`w=NIJ&W~p|Bm15v zxt7V?vUlvJc+YMBJz61?B}FfFgC`w%h`$?y5XbY zO^BBu_S3+jKP*o~;yB;ErH-X(9v%d@*O#Uz-ay`=0}|{vuX`=X$;n=^?dYRm3}M=_ z789}npiRUi;UPGETjHE#nF%@T^nTnSfWVeoaeBgqn(xV}i=gAvNHR7APerGj;%7#; z{w>k{dU?r@PO}?^4QUM}UIE#xnsqLB=k4Pf%;Ezi+mR*dKxnu=LW|PU?1RPLDBJ9M z(ih!VdsEYf=@qLMtelwT{m+vg*@1<6 zN5602T|t>$?tKR?K9tT+5CpJ5zsEa3coLgZ9K&La#H$g~h6TOiFq|ndL2!PuNV(cr z{H#9hW@qDIpX}TR zFV3oL^}JUO-U_Z{(WbSqo3ZXEOL;UVSOlODC^=9_Fc`i4^xZd4?00N2>1dzV3B%P* zMhR9wtxA+=qQC@`ccn2v%LS%i1=|LNq}izGn!Cl^Rn2u{H_y_ zU@|2vY~vYy&mp==1u4t3H=B84fFEGQg5z;&ozcWuOHX&7n%a^#;{!oIl$Ir6lT=?s z4g+NKCsAMk*|5G9!F2qUy}qa1-6yMvHt37to?xUrR(G_x% zC4J!zzL(6n%1;HLa^CQG6t!12By?s-kxqSXdCO<$EgUWD4XP`4tzHi|chB_pRm)!u z@(N5uc7ngb0LoVSRYJ}K>M8lE0dxC}W z+@$z<8l_@rM@(|JymOJ*#5~xAA$-ECNlCL=)H$Gbo66LG9*tZ&9tDJphHWaZA^VuuiN? z;o;D!(!vqZDjK1EfaBX^wGK&vq)T1bupRabK(`DRLjZYXSpGmxT}j0gkT_Nmp|?q^ ztC?J9x}~vHf5YX56%ZP@aFY0Y9D@_vmrQjbkbIm%pEVc^ux?e7m@b@m*Q%`AP~Q0j zpR)(`cNQBG5m8!t=*wwBYdmwM7~R#C!~6Asaq-{2z5|@_S=*H`#~iAGqC3RXk%s(F zMT8S_nPSPs%4Tj^(L^T7Q?NUOJXR+e>jV`s*r#+n772F1nRj9Th&{NALJBv^2UX)M zSST9WQ%DH>Qx+Mw+46NsF7$8*=UZZ$^UL$Pgiy)f*U%i?+adu{YGkRkPF4N^v}-e63<Bnk~$vT<2{`nT`A}$f8sa z`8@@Jnv1Uj{%+Ar{z=^$`r7yWnIuPk!_sMzC+Kv7Q+uVF#0g3kB>OU*Nu$dHj*YS* zS+D{wA5=;bC((e0f7jQUqHcgc3K7%R6F8iNf5riz`4&BA33%h~?(T!=uO6xpda#Jx z-vIOc%X+`(o~wKLX0U^z)hh}O1SCX}vc=Wing^m;yg^-PvP$Wo(4<%)psZ}!;g~lL z5=>N1l?%s{V+UoV21SxoL?zP9Kl8DEt+j9>aoRWJO~nyi7%l24DVd$M&hx_-1p$=| z@B?yiUX|3CMOep@(6I}S{+xPGNM*cbNfY!g>b!&`o>bO#ivYrg?Y0x0xyiDu&y_ru zF5VrylYZPn5KA5uyT?thpr*+irU(3sE!Li%qRy#tan%DO7cX9f;rkq8VVOMRVpU%= zPA<-MFIr2Swp6>@Q0%nvJ{+ZCcsQZQI>a^4bL2www?p#{*Q5XCry>vk)q! z%}Pct`2(lJaPMdsBLY5nf}F*vI|N5VPuhtv+UJ1vy39{<(D+2G%&!d*z?z1l=t$nw zIT*cyPT|odp98BBz=t6u(UEQ2yH^)=Cs7!LMfXbR4TPVX|I7!%qdqcJ@T;zuQV(X; zhWq#bO|mu4xO8-_Wwa=mnCTEpzFGHPKzgvcukv{3dr<^9ad{GsVZ$Ug!vOik!iAe>ur`eLL+UfE&MLn??}Kggl3_1AKXXdSet55k0xiwe#x1C6 z@>*2?a3u-y{Hdd**+)-2$=S>m+^sE9oHNf~t)vd(KqPykMvK^dCC)uXr4$%4hfyj; z5c6&kI@t^>;bXjDxbHFZTz4$FmDtCEFC=#IFhNpb!w+Rs5TV_n)J;e!0MVPhfpPg~pVJ*J2SQO$VAzEdw`Uq#ed+y9BP6)35r%ZP#& zXzk~+YGde~IzvgS%)#n;xXJuiLwKF9XsLwd_qPW8a48 z2Ny?Hv@dJZ!7<%)A>jZR=ZB4r(m1!*ywWsw`&ojGP?NQAMY^U?X#l4y=U(ValJ4+M z6(EIFT1b^FKyjRjZa-E9@~*(sM6R|~aTuQ@SkkJN1R?arUykPMM-IkU)6l-#)Fk3w z2q1mPsFL~9un_=+RhiYehZc&3g-a^UfE%_(BYsRX?&12=O&7dIuhDqmNP*@ryZqcK zyayFT+PBXQ+h$`3qmmM*ejq+c=ow!0RRXO5yBB?IPpqGt(^GgxOLlrh zcw#Sp@lj%Lko^uiUFw03Wjkp!gLp{1BDJQf&TbcwT77>2o^Q=BzG3F|L z34d<#{wGPijI`bG(fOy7RNO!BlO&;#XF(UAN@BXqRkypwN|e>h-i6&`@jVtEn&6Yr ziH4~#RpZ@B`H5VWWSgEe7X`cm^pq=;%+!85&@mtfi!cjT?=nAJN@E_XQ74vlZW!H# zo+)cWmcnsCpG0$q} zAFsQKR~S#J~xV?qkSgX znX2zC1`n1RQNv9m9_SROWh^DoCl0dh53=kD$uaz=R<`Jfjo?L*nP;w>6G7S$2iFqZXiut zVEp5$5-;aRTX*eRRh@BsL(b_aK+r*RY_}w*y0l}&jy2&y=CICtQS%OF;kMFVo8#4AglJ4jT65&x zKOxjgaz5-^t1PZ}4Y)XOU|h=NP+IvvO*`d<3UQv?2);o|pw`X~IJOJoDwTH91UEr- z5xy(+6~w3O#@1R(%=)?75k$8wUXI~M%*$W+KVPgqz|Pe$Xa$Cz0tOECx|U?Y6X4jc z;x5D>!TbdHk?At!g$tsJU3=XS>Iq{)W=$pT99c3nY1`o5BTa6|Gkoqagx-EqGy z@Q~KZ)Y*u%=fr(Vj@ACP^Gioug;_^j`rsGERYHVHyrHqYFI0mCy^@0qJCC-7V%X6Y zk^=45+dFx3PYsO7(`MP|{&FX*?P&f{#czPg8^RhjmhgZ(&!TK|wZ|m0ps~iySKB=X z@>kFJ;MdhJ9S2^)hpUuzv9PC`M&d_2A{%P!62R#vap-fKl%|)HCnmXsa~$YFb??yn zSodVrQt_9(XV6pBejkdpBujGS3KQJAFfXJ4B9h1}C$V68-6UbF3mWmTlqCF93yoNl zhkM=UG`ncpDx?mmYk0s3KG7vprbPHfH5+s~!uR4lsC@Fucxnn&0eKc)2x9{!OAn78 zX0@8C0atL{zX5JXyqo@h z9>v#8kjq`=^eD>AphDj>8+86kGb>C(*F&+G$tczaWKS(AqvHzlKYZ6ClA=D(_wg4~ zgP2H5P28V4vO9fb|MK`xm(P!CrXHB(4U2$dF1{?+kkBc&IMzsNL4|=LpI{Es{$N;n z?_>!{kAA+E4Q|VrU48{E!@p3rU{tFQ*=#KGKAray|w*(GmdUP3tjk8Z9u%I6{1yx=}nIrH8B1RB~-I1Cg$B%V|9p zK7h2v*b4$1ewX8Jsda+G&?PzLcymuW3vQIglWSyUQxb#1WR-0Cl?f4|RoCL|RYyzN z0J3$)`u)D?^I!d)jCZ1TRPPhou*zH8RpA(u-r>+|jT&ZDu>m1>lFBl|nLBe;5mT-@ zW+mqO?t~bZ0JrB^=WM4xxgxk3$HjU1AZ_Q@N|j92pq~i1m>|)yWr7QL5DS*WO15B? ze+uwMX5f%Bo((~CZ*jWCCbUJoibHrxJRLp{e^@#sf@w-99biFg&1uni<&hG6aI$q> z)?zqF0P)j&8@3qpqxV2vhAKGKJ#u~wx*6QKkkS)0FE0_IRUJc&g+uRnDs6$YbP+h~ zc}6O=vm!~eDnrsYhWp;H^PiXC5*+v%z7ne?3P#3=TuJSM2aKmvaB+iwP6QEUnYcubEim@tQi0f_6bW?Wu^`hQ7KpFl?{TMB5)Ly^4?iT$4} zx_ole=FQlvS)@-_t?ksL@q;om3355}QW zoxq}$-}-?w$0sQLi2j==lA@UGYRJ($0AmNIYX^Kyqs69$OO_ceZ22qMOl#aRN>?GA zS*Q&BRA&GASpj_+hI<)Y@GONmp&ayoVgGj~$k{;^|JWO2_Yl0+t=Ps&YVc=RdzsaH zF8uT6=o+oPUGn~?psOGTo(WqL{8N_NO`;jUdnfU%lsR0NfN=#SkRu{zRcqT>Hck$T)W{*mo zy)kyUd1x~KomHr2>(Q}o1N&cPZb8A$-KI{RnmCqee^i2W(J;i=5uGIfP%CU?msUmo ztQ2vzYr^`87tVAhC)mILqK7a>fjYy;)zL)IFV4wU$L8%Tiadq*d$*qVhKAXLo%f<##84(Rc~V{y*HE-hd8 zqyofkoLh*Z*K$ow$(yq!88d1}E3Lu4KaQwxT(zWQ)#ok^#TeNOT#+(mNa+y5oZBJcttb!$E7Xw{RSV*bA8oR;7p2^9+nhjz^j`| zAC%K7%|OU??nplA?XU}Wa`Bx?WJB;LIH z!h7toc2<0Dn2`coNiO*RF3b1RWU$H{5kow9;F>rKQ|%XyZx}6S;)`tEJQQjgdUN(! zoS#WK$?}JZuG~Z|{e$$j(UwxLsPZ{lRePnO?KJaOu-2&eW$5aLZ$s}I9EJ=_Ib1+3 zMPOxpy*RDG=yu5m(=dIhI0@r`F5(Pmd_aV8?u6Ybh383tHUURS$(_A5q0Tw8)HE3) zl`~B{zvCF`rsO>G-}w2sznP89y(y89;)>o*#IR|;3%9x7*tMwH@|IH6@sroX-kiPG z5bS$U(zTiGK0i4`H*&XrtPCthsw+2u!N9Tg+GB4?>ZBtU%B3QTnZh6z;aQLfsYR$i z0wGWApbf1QWh}Q5o0XGg2htvV!)K(~*DJ7(tjx(FRQ8ZRB7K2Ry@tL@EgboUl&WNu zP9NZ|a^|lT`U$ILaA1Jb?&%Jn!n41Fm z_=(n5ojG`ISI!gr4XeC&zSz2Y{Z+r#Vk-z>uOGi`(G#*)AsPb1%VRusy5CGxc`Bv5 zT*oQ@#4(|W3z#Q=-yv{>*sJq)rBULJ(_Zi7V41T8s^oqjkR*LD+b%;+w8lVqJ4mAwNA2KqVR!Z8x9PL95&E*DG|p&S;I3ZrX8oQAfju>MiP<(TUzBhJ0iPrlyS%xxF9bCI zLqC#NDlBk?YbNg=^C#UB(-Hf!BuD2chGBM?HQSdFAKg%u z6!Y_9?%mv)UnDhrQ1sU5Wvkd;ofWr5Wjc4xaCg z#sH3Cb%-&rt0Q_%i*wq^J|2GLD!Fk@hT56T)(v1v&_3H&lz7sIVJjB5-D2Ckfb zC#xs)HK`N@_;+)XQ53+=1tt0Z|Drk@LKBA>5UHto`sY3~J!g2%2pGC?^s`4c4ceGy z5U7g|j0}Xinv&v$Ddoro$00iV%U6IsMV&L5#img5X1GaY92Cstbr4Z3P;esLy|wI? zlMW!or35nioxl#44_vL?6w9}~S$DGz;{?&FNvj}vzejj5vMD7=Dq)n$8Dl< z`UraOi5)kb!ubQzDa1f0D;+~u`aQwC}7GJvMEz1hrBbd?11ZpuT#em{MFOZX=;R>WdKFd;a8S zV=s)O*|sK77es&l`>$ampN4f$MkcNimxB=CirfUK*%`q|%e`;nmG zO1-UqQRCJ!05&u8sL7>^N3sx>!0|hECM$=I`{oFZ>8v;$s?Y?b#4_Ev*v3nl_0#}6 zVU877-FM`)ef_=VP;(~lPlJ7p_mft}s1m;=kdyM!<&vt<SO6wiuqbf!`oe_^r(L($$oZ~`i-JbXbc%E*$DsxmEjfGR zsy1ym`uiIbO-e6skl$x@6?7s{o@bu}^sATfJ_Vr%4v zZXjzr$_#x!488qXOKE8oY~Ty6{ivoy2E=TPp3CIV1z+`v)X^*^e9pi3`*44yUM2GZ zB$#$%>kKV{j>G#3tZZNev6Y0dPOj_^ZRw4PR(WU0TF9%EFf9BWY~I0%zNws0NxG!) z;$83@oE5QBG4mFCz}q~9?62tcy(tFkKH?TrT67LT-`x*zoQ1|FC8R-~2-~G~ZANbPlh32~D2{MZyax^vXBSNTY z*;}98<2l1`s3HHe_}FZj@lPvt7BmWNmqMok732x-uJ-*|{SCI=|4z2Dxq)-|1&$xq z@rzY@kn$HNz~F+A6tk5?)ib8~{Dq-sL|7;77})|T9Q=qkjDh`i;i)BCNT->dae6Mh zOeQ+(atnXlQXTVr);Y|vG4Al2(!X$)%~8as&7!9O!&M4q1Rz!k5Y7xZ`e-pf`?18N z!vF}@tUxtjvjnzNyyMxSg{7v2b%D8Yk|HT?!gU3r zN+dywB-nTiHJ0C&-avVBh$MN6T8xERqiv^^%YooOQxHdY~N4QX$Z zB-zq_Q)Yk8$rY3=Jv8rhRy4F?ez;^kFSZR#FYGvGa(Y&hR{8cZ^_z1K&FlL_Yt41d0&-|WrhagnurK_% zcmx*ZGzohh2R=~{NMS(=#YH~uLS<-KigoehJK5Z*u;$)%aq#^X1Sdb|oGEj@Afln5 zT^|aQ_635D6nB#S@o@=?u4m?^*f4(=j6pggpqhe@N^wr+>tx^2oAh5&7KN}{{)|O? zAT4mL>|2MVG5&9im-&JEFlIXAN=F8cCwDhQ-EP*AZ6mROz~(zGdAXq>1w0;B8>1K! zem3^xgi)r&ht@4xlzZx(`#t}1jlTLB1QnI=E{DzUxYC9YtU|)S zye%B2r=$f+JAmJVYtPD^?t$r<8F2d%LeJ>Y$l?)(t4&};;4WkvgwMUj0xC_^)5g*v zXYyFlH%VS&=%N(D{sTcxM@F&gz1u^hH1da26ym$!R+EJQKdO)+1oB+~po<>alC z`aX}q{=cP2rb=!*8M5$U#y`p~?3u0|K|q4}r{^hhyN&j4DRSkntPnBqB-oXcvLNc8 zN$Hxg7US^gl$k7QiNALBDta>kgKXCwP0Z?4G@_z~Qe}6gRg$xckMFztu&WitO}nn# z*;<&S#B>4Q+k9+q=|^eK;X1@L`L97T0Xd1TQ#TwmE+zVyt5bG%K;cl|xp?v2IP*~w zp)mF46EW9gvVz^KI+LQdr*l(*l=SEaOwBlqURAKQ8xW2c$-$C-4lLW;86V)7$yP|t z;T%I5zitsrQE;@K5@$Grl6<*WDfer8!`kxOF^dd#>P^rSU z)JhN)Q=Hs8&SEFNLIWq4hP^1fF7aD#{1vz!?!p6!rrkjk6Wc%#bJK^b4Eyv>av%D3I>*@rPF%z^{M$)zbV@K z+639(#A%u27UA`fu#|RN#WZ>+%8yolywVoLQu+?@ytXPAEm}xYF~!hG4Z-SV_0!L!SYimAO7D9J~vA;^`B{vO39@B zzdEtIIuQ;SO7_DflYb1C|8@QruG8ym*TvhDiMto~UGxaMO>)z9bTQW%s5}KJ=;28& zL5CFBVWn9f^`=)BI$4zGloU#}LtYa9O-)OeU*(n`aUK=dCz8d_<#*vdeyTKlQD&JS z0YF?~p|#NY!lZU)TT6CuRPDy>gf6ISH)-l$+5ajk7C!L^p3%$ro0PtN(#HwxofJsD zvbg90$MwtGi^KJm5Uw}Nws?hmwy48uR9}2`2jW0b946a`Q+5I-Dr9}KcCv&Ke%u6k z8Bz{K)kX&P?Oti7()$l3J`ZSZzKWm5Q#|RTT%XUM+3bB$UjmA7P?atTYem&*EC6!4qf?DC4;g+m#9Cnd;mkF@@6=k z8UG1cssQCBnf8*v2Nq;y`r7QC*(b@rD@H|Eya<#RoQ|fOh*VctVw9lXAI8bql)2$PRvNA*^ zeNG0els}XF(C=%9g(%t4=EVv7Q{(ruRkFOioWj(8s?hszU|{+&2p;N|m}+ziYy&K@ zcBUrdUX*9-@==rK#;z+=FY;4@EBA(1?o$!~NyGVXJiy4i`#!)d@70N-MCma*b6(bZ zOI3;MsVOD**!kU6buZDL{5!dxfTHkw4v^AmqNAf{l*0CsyMxzO!l&##+^|2;34|(P zj@QAa8t;QjY#p-}+1GffOZl8erDCVn23=41loP8820!wMEJE^5GN@-a589+9%BZ?D z2yS`y{Z(FxydIz+h21cRP#0Kei*3TrB!7}aCCH)c6^iXjfE`b3hkfVgh7K6-G*SRN zdOL!c*)XPloxNi0785e!3fnL2DLe^sar}zRMiyR8^DoYR`?;k+wbX+A3@JyQjX)-z z_Vp}W@F@L9v07KhjR!7dWY;m^C(DIP3L|xn6t28B7wb_DyQ^w)R#KU7$bzQ~SMDi| zd8hHZmWgF5+86;AX$m;jptjfTNtR)$ap#zjURF}Yvt z12>u^2avStct;2JQ3mbG!$ThIfGL);NFWR@bqyPlPsvFVB>0w93or3{Y- z*m5GRInV|MVCF1XQh9W7YTLj_g}vD)G|y&cNt~F!TpC-8c5>AU@~Ya=s5|1yL-LF` z2stY9dR)iFl~{}Ci2bglyP!^MW#30hg8;h0Nb1e1l%B+{-l7`+S8}B=?KfvDS6_V^%-a+=ZHZ zH(%n1C0M&{ZEe?I{_>d88C?|Ebxxquan%fl!Pwmr=&)$DEoh(%PApLsI8q8C`XV%i zX6AL@cwPdh@abDzJc*LE+;g8mSACH~Kc5xE?vH-s>gzEB@wstl78IY3g6KoX;_7z$ ztH4A)(Pb~m=7*@;zucSGS!^A>FmZ*GP9aZDc$+X$(~c=nQKHOLnCm`*K|+=&(7+44 zrHADe3%c?>cf`!!_a3G|yW>4CzN_r}eae}FjsFvQoxPG@?UZ+jhfvai6B+La6$pR+ zD>sGsM}U*B;i#NNZ%vSfIqA{*#na;!S;gt^t?l|D>CK+$-h*$|F$g(7dbEQCc(|Zb zhAx}u`wu_wNi3eCso2v-G7(j~@6sMgxsoPJRnjaG^O)ouauGj~$T>+x4n3awOOhBU zWB!C-FZht+r?k9TNy{b@t0y$cH8@##K5ufJk*LXSV17Ls1*O~^m1j!g?$WKbl4DK3 z2d(UT|F;5I=TdX-Ty}h^f5&fwf?s?JbatT@wv>J-L=U&_GNXEqLShXg((O{ejBH2A zv)V9e$Mg*dCYIE=@E%(V6`GM~V!cIs*q0ajOT%0NKrl8GS>YlI_LpIpwk> zLN*z@tA<9Otxk`pi@dGAekN;0&0lr5C|v=0Vb*`pRFG%uZI!ItHFP2oOgXA@{R$Q= z`cwmc;zWlnBPSo5J{;NqwQuA9n{9h}3?7ka6rhjlmDc+Jn1(_9+T%WnB~wb#sYMY9 z^ugarpqqI1Fp4e^)uo~k_bqQ$%jn+IZc0cAXD57L_^Aox(#3?03kt$5cDSWhBBoRW zQY9!G`)10uDE~@K#O0|cxk_^}bQjn!5rjUOv;{GF<$fd^B5@m(dkUnN@u|+KbjK** zX{9TRvZwXNR+%Fl-2+N{EkFd5PVZ z8m->_k=e#)d~S}T)-u~t?h5x#@;$!JGZo)gYLjmz7OYT359a3d1o#!Hwn>W}pQv=y z1)Z0xCTa`Lcx_GT8!}>vsvhL5Czi%EBJWl>0y&=fsk2AInoqa)EG%2A{36XTNIF=w ztFJ8FaY>9=78bHoC{=&RtZtV!<8xj=nzn1#uIwu5Gvy|B=8_OBx)~gFXdc7J)d4L( zs#vjUb7LRUlp@E-!<56ofV{1emIsxl zw3XxnVHo?QmMKXfzeqPJ?%UaM8#O0jy)@Kj`3!utOJ?GeHK()5V>HLNHnz3>NspGK z4Q`BdOUNu-HshlC@aV-z%A(r~_Uje{0rtER@fu!MJ8#-N}+DBDNTjuAbeSKTN}Me z88loPrfzG{tdIYjq&MUiaA`$zMX=vNjl758E8g3D$@JYX6l0}q03 zpFl-wFvzh_yGw?GSpSa1#G2FdYU&HuG7)04=~++7d)`}2FMc>R*C;JKQ{d1Er7Q+I zQX0FwY{6@!{qP7OkK@=7+wp{j3^>IxW6xXOk56(u@9B3?cOK;6?=7Y22|b6ts0z-= zj%{r|cblPQ5hK}vh=R!Hn8*;p^=M}#HW>AYvWw?7wyq5`H(b9?dMFHNnbs_>8qb;g z5P3jjNa>VBM$&_m8c(@q8Os*JHFBcgckSa?o*=K&oVuj0V$79HB}s#NvT`5J)E7IJ z6h=W;5wPFhJlcGrv1*h9^>Eje63XK7>HuzC=J5@%2UE*j)QR4|vTvF$KK^?V>Tc)I zX+SlF)fKl-6&mbE!xFSlr^TAPZYOAP?d^k2sj8YD&GZp>UOw7pZf@;W;h_)shG{pN z-o3QP**+eRPzvk-&KQ>bTratloOkCLg)rxrDx%fW%N0(f_!*L^1z$Xt>OHfkJL4$N zE_YR)+o3|!ixm~)?tDOjPlXM)6>le9j1AD`G&F6X{Q;z;6ft4Pz#Y0AAE31GEHkhn zne3ombnxK8kdP2b+A-O6E7Uy6oHm! z^(tvTj4KAnDWvFN=61~~y$}>>wrn6?DXOiM5Me>NVI&d^w>WyPoo` zdubiGM&Mz;|H^35AR!wU5gk1MWGLuHg3i#`h=8vLt?2bxwWQtdY-tE`ydO5YUzgM> z3`|rS5#fBz-?{7AaPDJAu=57RB1$`PqG66(VY=4B;?8u(NIK=8U2=W1#o`!)C_N2% zl}&R)UVN&P@3pPtEu%#O10djsf*$qu_BLPGBMprIF~zDkpqufp?2@RlEc9}+x#u8} zaqI^}5g8|Z9r=86ag|4I3eAxmtDpxiluupG2-aHF3BkdPXJ^b$p3U zDpSdSx6Y8lOp3utoEi#5#(Sl!;`B*MV$UVX;To@HF;`60D@j^kg&Z>}zFirqg74ig z#Q8#nPa`FlI5H277Axha3}ugN_XsWN`fK)ku#rT7Zq0#*I$-86xzUl40V(Wa)v4Or z_|qN{pZ`1(D3ETRXVmE6GU8!Y)_{z6Dz#yb+W2exkySjEf$w?$(zWsFJ56j)9evL=lDr(+MUq z7t?n<=xFw_%YeeFYE89edmz1VTyaNyNIHc|O9&En2V@sNyn5Nn&Y^pNVx8qX~D)q&bb+xL1( z;C z&VeLjBXpwJ>j-wb{wd=*+NDr5P}Ln21p@|kYROj{yL%R=GN1D2x2C>xQg$mDdM|`_ zVWN8wP4!o+pZ{f6t&$0B-ZbN-RBaRlA}5P%obWFegEc)cZfg%PGF2oJXIzP6m9ZQ08~ptwpG-(i)znIs((d6g zxpPSBto1oLY?IGf{jX_-Yyf0)S7%gF-*BHub{o}ol~1j*3?n!Kl}oy+@jF5sJtzDE z-4l23>KpSDm?Bz62l@lAh{=D~nlkyf{K)Ov=EzC%Ati}{f8m52;!?{>u6$}+ZZSMo zbU9rAjC=22^y&r)>_zV?)W3=mYo3w1JwH1;rk(cw%$XCQ)3@wcQ<}`I2P-S)bPgqG zwT?TNJ}G(m%DSv#6YZj@O|Su?^s`nLoOis;ijJ@u3uVY8l(n9-pJe4&&C8ER4!#k& zt^dv?YNnH&1LcJ%wO)=5Ql-dZd56kLdVV(7!Z@$XL# z%zL4=gQWo?$627R$WI^X)E9St(?cCMDRk%;?#d(PF*ifQ@2X+j@kFUFRGxA!$BxH; zb9Av=FS7RZA7x;c;1d{MSLyv>%V8Az!Wg^>@9a^gltq-Q_~LV(QFz${R4(2tW$ugc zN@DcPa7lfn$#?D!--Jukl>thbG9|Vtjz{vXzPBWL{=}Ou*0)Lr>wW`^QYi4Db2za@ z3a+6bF5Y53PDn|-B5f;$cQiP-LFS}WZPy@qik*NHiP`{I$Y+231bt)2$3FR=TeO3y zu#&yS9li40v7u2>zQ5Yocz9%nO6c1^&KokNT^@+;H2Qzqer6rO7NKalpXPw$C-Q?7 zs^RW3c}CI;6!R7Qqnd4cV&XzxmfxqEE%{yOBmS{TV&$H8pNZn0`hVQ{Q)!*me#>b2 zhRlHlnOW4vc!-Eio2Y4uE~B^rL-SwEk#+a<2zNYj@Q9Z#H@7;b@%HW8z@93aZnc{p z^1FTGd2b;lpUuunZXd*GhJEB$)l#{}Wo<@=u&D7Vv$t)#X|YL-B8+q>WJeVT2Yh;% zY1G92Pl5oQ{Cc8NkVU&mc4uXSj;*)%qcTP{43Da4QEqOM__{;EpneU>OI=fWHBEEv z(kFYINL?<57J#^{>)-|vb$KWo^mE))T%TBxlG$NcVrdiQ;ix?2D#zBdm0_;qd68__ zpc*Z)t~fUs)t~1;u3-%SZohHFs(0iePF2aGGnP>5b3cg5Gy~R!L;0N zHtkf|Df(7GrF3ZKA9 z#=@~l`7V@gWp&xJN_^()q!NOqB0ozk!ui$GA(4&lRkGl3r0c?-papReluui>{NU(^ z8MYA=Lu-sHJ2|n2lJY*!I6lFcqkwNYcCU3#u!2l+;Ho%+DXmE9{wgwJ}ce zxSf*1eZ5G3eocCBTuO`br;5h7&#X$3EjjXl3HW7=t=7VfPF7=giBrbF&tEpa3PEOvK0pC!%!)I;Md|bV_$MUsr zSe(UhPU%Aq3?1hN$J*!lr>BQxP7tTaO?u&tJ|URws%TG1cz?NygJAm_xs*UlbRc`= zpk;<#GWou^v2#=ANO z_dC}`e~OrwxcymMe~T9sV_|RY5^x9}rc<`lm8%QgfqoA_8J*{^ccO)vUYD zWO2&OMT^E#RTpUIM`qJyDm9Z7!csa1G_N&hIAw z9Q_MYL^*jbtKo0_(8$Ql%%KApntv-`{$R)VtXLf5kEVM|ZQqsg&Yn{U#zbvE&zTtJ z;Q<`BPNPRR)YSE>^A{HO3GP$M!x zZSG4}d-h9#8Hry>!s<4J}B z-+-4#m9;J)-D}2--&G>kRc$K)w!+%)qW3kzluN1t{vsSQg|dk>X;%L~J3cGZLu8V= zA)?MuY~!e-JQBfZfg%&VeW70w``3Zy4oRTGJk-5Q)~Cg;PH{|)n=$kLqra|9Ts8e3 zB9MQ21XC3yp z3KtVG2^rGj8$L4cnGZ@vEyVSyi+3P_lA5wi|^q=ac*dvD6^meHAR!`ngY?IjHPO?8? zY-(^{GpB9d$Rx<+WlGe=^GWaL|yj;K>j3ORTAyr zzs&NRFptXT`t|GBG`0?-?fD6mlx)8o!uY=6yB|67+;3%+yqC$(4i3gqRNMVRXXGDN7x&{1jzJGriK69^WT-dBH zab9Uy)`}S>>tiKnwFmGP;xueSqZLqh&sS9)E-YkTV9XHuyGq8-pti9@#fl~TA>-tR z1v&Y=??0^-QXNebuYm3ig51b{RXm>9xO0M8X=VZxvIQ6CCLb6T;0y z#@?a&n~CxU#R}U8MzE<&ec!0slyAu}j%LKg#mNi|FN5^)Kf(D@ z&_6{pJ@m_c{W9;sY^5bK6NR}W$6tng7w!g;1jNXt>Q!+zb%c3t$+sB_LyI=f~R1bBQbrheqH>c|K~v?}jz!5R+_yoqr2=A<73GPqj1 z&H~^FJJ?;-yUF~;p6Mg$x1F9DF+j&9x*C3L3JhVD4WcGL$Mh@g_I1YUk+CZmFLtl5 zSgH(ST|)vyxc*AF&h5?FAi7&hE?(?&wq>M0BPVgSoKN3Z5^u*8u<&h;i9*zz&sABz z0wzbimBH5lomIQvlb_>RRLBuQRDdsP$3N2=D+E-WmT7*K|uvK#H1m?oEz59;KUg5DJXs$|Q zhtUVvJcK(1RaS~%XFpLsL{;*rR3%>bzJrjZ2`JYjTwG<6RiO?;G!flnnq|cX@&({` zN7L+}_-~1h=>V(K3}?w;Y_VNk~}mFC`q z5+HkB=~?`a@wCnHh$LYG0Ew3tDI5IrGsp04sApx`HpVq1EbP6Ts_M$OUNww0h2-Sq z;(VS`H9wgSp)y4G_OJX}s@AWJ>yDv=5d?v!x^t++Yozzq)|j%Fau3aqZW}yNDbywO zkIuwts^fITrV2iO`^MEF@}sEO7uSHtbjs8;J(S8$t6Z%>j!q4b}-;>C+mMJyPUiIG#Cm}&(Q zsZ=(_4Q09px-15R0fV8#Q-py54>DCkW3P2<{z~suR>#o`p@!)5$%p7G;}&m+XO1zt zdz)6YG!;EY6ZP3n^Lbd}kF~pJW?xv(sn(AjzjS5Et1>JiL8zQFDRLo*Ix>v<1Ob#?$kYVm^(J6Z-e=c1Y7&~7#Mjye6BNE?DYa3tuTfC8_BE+ZXyj{b zqEVKpRio^pYy*tGHc?B2CMFU^p{Y@tT0m5GhQXi^MI;erhd~e!2N+;r2AJ)C&TpQ< z^#Aqh6^$$!pZmF&bIyHkiG(2|JnV=xPiqIdnv;FVftz#hP-!^4?f^cwNA=&vF^k^0 zIQ{jRwol%NtAu4Rb?XB5J7~)*|3lpmvE89U{G(I) z(y}FN$e?JjHH0}nNyc7Y&geg<$iB8FyyRY$I=56iBrCK=k~{mUl+EEj@CadP%T?-1 z5F#34Do;84L>qtWrrLw2MtUk-wXU?igF~)u+qVT&EblDC(mK32q=sF#6Y^c?Emr{7rns>c8BgB#1Xw$m&zitOHVMi zWmB-~Dvh~n@nJZfej8^@WH|Q`qJQwqujt%(*(=i#2M|teDwP#4o{KYYLy(9}uesBD zm2Wm`CW{lg4CI}P@>-jr0yWG?K$#zsJFsULgdn!uj>f> zJ?-$ima)8EHo*4WI5Fv)HdGutaxJXr%PUXb-6oE=s{w9wxpfH7 zvZoVsa}0-ML;a;g5eK{5yZp>uxz6SXYd!lT{SrQJOv?8NQ!KP~?9H4Y;|BXTBz?YN z=#0UnGAlO3PHrgD-tsum7^i5QELECHx6BVT|19X#u897ug$qZFWD{H?kt&=dnpQeU z2G5`~K2x0i*4FL7AtvxvJCSzV;qTN4a;>u(_T>y#h788Xat$&nl2qHicId~D(a>K( zTakfi8YdHGHk%W?Qx5~5@_qqg1Y6qrU)<|>ftFs>);XDRiIF`|6wVKE1&Du z!yk5@wgDY3MyF*m2AWU8jrA#^A)r#P_V(UecFN0r!US0l_KJ!dN>-!`=dUR;!YGYL zv)N)iBAwW~z;8w(Tl?ayDjgALhZ$!sOq32{YOwZ0DZC7`%wu&+O#)scI~=waCL_4s zQxvgfpyc4)-ND{IQ3FlgXbV6S@5!G^ZVmUD>h@_o!Unk2?Lx%iD?P3HFK;QaVMh{@rw%=yjTM=S+fU`oEHvw|>EpQI?49Ye zO;KJBM^pD-=dV<))}d{Q2{(s@o2r%Lhbk5pcHG)d{MY-Q#z}8G9?~CNXTCl!Utc1*g{;{~{xQC`} zz1SAPVSsK>tnAWZ6m%yo0jqb$Zf9j+uKb=u(!DDCpqQa9Z_6>MJ_2>KC((){mFhB@ z|F3BDe{t9RkBE=_8p~-MSQXzu#T8__8x(+P;L|r3orp6G7Q)eB`OaH=17b$Ht}(T; zs|QU1L$pZ9VxW^Mf2dEW(}zeG5Nz@GKa!t@zq@A{j(pKqGjAIjB91%OG2HSJ^Qs^R z`MI>(LA=Fx9zW*d5TIAHOerRkReMJ7W3#^fk}$b{dr1#CtAkKY$|5438fsE;@I>gK z7*eQ(sSz!DpRFOUdz}q=ur=RVO)=1vzk-c0IqJS+_x$8*Ck6)(o$_u^+f$j}h%-QP zVAAkJje%nkxC366NiDheQMaRGhu3`l2KZMMI_(+!0bct9z$@0+atwiVKdCy`s~BO2 zd}oWMA^osAR}m3G6k-I`a@qR`x;BkeH)n#$gDQpTA@d%pjT??HA~$MnJVXH ze6!u!n9KPB=w(8i5j&BPwB=+VMYcVGLp>lb*1|^L3nCKO-l$;oh$aiy*){0r*n&|# z1+57H4=hT&9jt)j1aqaEn;W_+ARj^Kt`OBx-kEE!!qHF*hAXz%p985tBcxZy*|mvx znenY~0j3i}OxG=s@a7J)+C%dg#8B3=;MRXuSbR|T_Sajzow0rSO8;Fa^RTjHut19u z9kpr^wlBzPIQtCla@GIc{&aKGL}iv&D4NgDLFIO1AqT=m>$=GG)3s4DdmGk;@=3K` zKmAtZm!Tcs{x&_7rv;bnS-@Rfn&NY7E#JqbU{8l>s!sTr})mQsKOR5#eQRxc0*&$(q)( z<@!4u`-FB+{x2c=AiaUtqanES9xRG+j{vU^`@5c?(QDA{`1#yF&NvFRJRNAb=Q{F* zuY>Dp@abua$<2yu|IS?K-zK}W%{kyOcGHw&HRWR}pCO$4aV)>*I5ar;`jYNfVPBTt zkfRuC!A9P#9hW#bG9{6%L~Y~_&vD3eYIi`R8qkRHh>jYJK?mxaTRgWWz7Y>7Kx;@fe4Q~S|)9o$5CQQs-&9`oX zGkVTCY>LA-t2gB~;&+wuRkCs-87^+4>;f?p{&;bkZztAq#2XYSd?j)2FecbrwLkmq zXVcSV^%po+BeKB%Psj&Q56@r*ov5mcUQ`GQv`qaj^*OKRNAC_+!~A27->HeO;R~?= z=r1-Zm4UNSGo^Bu#tqOSk0EklGy_7GLcSs}`eOl%wurag3fjZ>){ZIC>ML5Y9j{3) z8fJ1j_#=cmEVWB58>#Y$iNW&e@i^=*jO4U-v<>96uj<&lD=Yn(2HA2i<8en^=snrh z=CN_~6oIHxvYV#B$?QOFii`Iw8#vYFTdu2NRcs4KJ~9e2kz7rpdWE98hVipqC#xb8n!%AoE`XNokWbg#)NgMha}2c= zM-gCn78i^PJEkOm4k-BbxbK&XZ>T+mKc!KRt)(a>56oxujEW|GMr>|oHrbfBZk{fg3M zY!Jv>^{mk7?<_o`K_%a4snSr&5ti39gb2!ZZmSQ6r|sNnaS5jKV_dC33M$r@V^qyN zRf|~CL+-s^X76hbif>0|>~~mts-wfZV_&tK+nLWWL6nca=rocJE#zk9&6+mcFUy2D zQ+*Rw`w-QqsK;V!xi&9#MNFt0U2w0$0hvVYst7q;LfZbO*{X>-c$d zgkeVD2xw|t0Yp}kQ6}+0usWl14J@GX2Tt6&ZPxtdjVp)ufHpCkzn{ERdcNLK8?{z$ z_$sSCqH={_?Cs@6DrTSmx4bPa?LJc1X{&nxpd4e-*M}gc%HFq8n3fq3s}2@aMFBgE zQesw)G)@3QGQ$wdY5Y^yXw6{Ep3Cvytj|mWzUi+6z_2)Cs%1F>&d?dWPK7~xNm>oZ zz$L1wC5LvkDKE#=9}G*ndB$nsU*Tk~j620pQqj8f*bXRP_FLq)74zC&{uG=}~ zW17cOp5n8&-#l@yzq9jwnalv=1^FG^*-q#Rdn%Hl^-QyA=QhSEQs@r)GMs-sD%m1hf2K3_}!aG`zi( z8iST#KiFsDUVHh*1s`|A%oayeSRWvlt(6@}#6|K1)e{x5< zsXH^?F#4p^ zE()wIGx~;RXNey|!!t`Y1g0Pf;}0`kO+U_^;A_jZvA$Nv7*%B2|2WhI6{%A^oQ>bv z2el~nado4rw&XresA^$jTS@_Kx*4>cH82GRBSV`5!@SPL3`TQXkfo zStp9|JTZ=dAIB!qY32pt^310-Jw8A_DF|*c02To+huiu2!ua!zu}7`{CoGk>(XQge z@}0+Pw&ObcwParS#Hu?E`y8ac9AaTunylY>>A4GdUr}38OcpH#wG*_ixi0dh(I4)V)VAfgX zFi9F1h=CHnk5emJE91D|zA5x5GLoxk%9kS-pt@F~^a+(89Jl=O}aAtbVE*zVpeGMCN_CB70y*`i*dCNmU3HlS zSFtIBi`O{HFJ`)=k~{by=Q_q1#bAv=vVi6XPNSWN=KJ){C0!KkY`%aL60QPx{Ux-1 zul3(Jh^r{D#hNM)Z??){uiz5Nwf1h8l+^BD?gGb-gaAtofZ3A?Fp<;i^~;gKut5w- z!w4lim_~Kj;c+Ofw1ddBb1WeV&+DR?Nx6N0mFf%3l!`moyQ|#_3!s#6NWR7<43rAu z*$0Y_)0pHYjcD?zjs@HatP^cGsF{73>=0o95Z-w^d*9BTeb3d!e)JVK=L9JY5{aY@ z{*^sGuR^dJgWA%1KQ3xDocc{m0bv<-3zG^2Cnn^Ng4eYb$9y|W0u+3}d4a#w2K6wZ zK?}hI!JAv~d4B~`No`L0yXWCR_bJR&YIV9JwY9U?u0<1%B^dm56U74Of$?jyk)$^4 zyD55bWmXDO<8p%>`O=?u`f2bXU8ghsF&H9;p{BeXVY1cK?zJ(SEjIn&LPJgCp@m+i zl+x7jkk_uN(23HmSDMB4C>b>YA>o+R=Gv-Qg;&h!#2+A4y%$mA(rYA&Z@MLqqs)+~ z==#CnS$poFR;Jz+dn4Nq`oQ4KNcD1Ve0h%DoAdOw5!j8M z_Izje_2bpiDcJK`xg7N`C^{-QYC+YO1%cfw0=uzSg=v2qIwI_g9Y>--bO485QA3;? zJJF|CMeWGj2z=BJGTXNImV!G=!=GFNNKqWQt_AO~+{u%<#TfN~Wuj60aJEB9j_^N) z%L*zrF{||S^!iuv?RpWcJjuOO29 z_FQMrZc&~_UlkKE{8xY|N8C4NPc{Gh^1Hje3N{)mVRKuvukrK4aKj;diC9IV#wwew z0E*RBwCQt5s#AcT*{*nz{gfU1soZ>zrz$u=ojiTo<+Klvtppm6Z(bJ?2DJ6(UJu9m zAz+wY)&#x|_lIx?#$SKIab01NUI-*fr$`grV?yM`7?O2mdWWG|vikv;@T0cTrb7d# zm6!hmUk4@%X~W1wz6)~Nw_5k4(W^tn01`x{5fJsHCJLw`Mkm}*sMwx6+L9YRV!TGJ zmU^X|Q)JCsF>U+m2u+bb))7)y8tZ+0@)8p^rR0vs=bH2oR?U$=s62iM@{i`Uu=TUA zfv`wMJv2>1drzUFgDekcug|4p!Z*Apuk+HM!r#WVgmT3tEr83Cyu9K~OL3$$)!7IB zLSD}>LRPMXmgn&ZboP)&ynTcAJAFXj#h-hIb>D;8!KVV1(`oXH>avk^Me})Bcqnhb zqPUHk_|gn`LN~-i6dSn!RE{12Pv@+l#TeDnacKhLZS2exwnw)PVxNlgG$RC9=vgvj(7rBBGy07R^h!D~pyYLAZh5KNk_-(A-UZR|GW8qSJbe)@0_c?5m2P_I ztx?2yWizL_ko{>|EvD zM`IupY0fUp=m6r;8n*ehr*yXxmc~xxH#(gkkC4X=t_h2sS{RclqCO(vg!M>`RX!Mr z*s=lc0ymh+rrc}9&pE~lSy@97@n}`a?9{itPW$>{pAHs0^y7k*7@wE1w>khN&nS<+P{wx_Z3$ zF$fv|miB<9X^jE0c7Z!~y;9y~btNF+Z8~TQ#v3-}nB(K_9*YH&g#O!Sk*RQB^wSzd z-EuAVPP%{rusd>TOY%q~h*;f}v(Iqhs~G#qcyk&t3`EwA6>Xc``z-Ls9t>I5hCRcN!zwXtu!11Ck~uE zpfqpfvbHbWJMLn#`}~jiNgr0?($&+6O4ajqb=Ic)CDC+;=dOV0SDY*qrny#6Qxby# z=sRn0nyEce-&!_M(~who*&mk=npzYx*=9$_^O65v!#l;SZs=X46RF>B{{cq%x)XuO z3et8?(x5ii1`fPn32wiT7ugMi04s-NkDhY=M~HPV$7B~{d-s28@tV;khi{W<83YXt zy;C2oc&i=_Ps^PGx55{?zD$j6y3de`L;3JGoPTFW2a>~yMg1HF zdp0EXu+s-x^;|XJ_Hg3q*CjXtE1=xO!=^_aV61`D8QLiX?S2YXFtfelN*lL~ zOmXZuvRTXk2P`Vc2fR>-i072&jeG^`bNsLqxCVa3d9$G&pw&K5KPuViu_(D^QE92f z74ruq3ZwuYQkI^9pK|XJw$T4WTzmFHRZ~#}wp2Xa2{~Zt=7~VvZ|6*z5M%FPKE-xk zp)xSDsmUF@^}(?(aM&Rqbs4cxriQxEY4T%_p&9$*>$&$n)5h9HDS!BHT01E$KCyK> zlz3Wc-=#8X$hYMdl6f5ZjdM7@3w^-EgS8j(Hu@J$TvjM%S5h{x*l~6zWXRMj;fJ7} z{GdT_z4kdEc~zEnRq5oHbK=|PIa%U!^(BRE3BIq933IG=lkLk|mvM1Ip_*(b(@};u z79!(kQl4>p))63It4C`e+)VC4{tFXKsD0rMX`!SNEXVTn+M7T!C_kL8=C3Oj2 zV@ymfExM5CYK(2q%(84NYXFM@mBP0h;?Hh~&)*IBqM~ZG~6rw_|sXAWKJAG z5oD-QW6wAa{4?-RB}Vvv)xeB=?N#Ipj6mV$t*+5qip#>Hv|nO?Plu2JO>;)Ma>q`4 z>3Nsqyc)uY$LePxLWn4?7KoyBocc;_q8xt%3;fH9RL`g3VoB^Z42@CYnl1Q-cP{P3 znOfgCd~tYfAMV&CS(TF`)L`}yO zU!`t%!~Ss0$mHNq#G zuK8d!w&qcT1eOeAURBlac62~agAxRrvX=Jt?0g_Z5MZ*A-i1^4!^nc8knr4i^(}NM zCIrZnos{c|r46(tvjousk$aCk+low?)5~CjkR8grj$ZV4XN?$XYIk0u+=qRJd8(il zYLXclpwt)_M6dHVCs%IiLfY{CBje=H`1SpY29Qewg-_UgC|lFhQC>6vb2eZHWyM>; zh858ANds7OxVbhUCKR!Nr&NI2_ZYtzPaPAT{y%a-p}Bp1v7q&j$fw*h>QP@P|1NK; z@re(Kv-TW<`9~w08YCMn$m$?rR$Vr5CS%mik3xVs5tX_s^Rk&%OK2jzRq)s zcLmD~SC4dO<#%j(p?@HAz;cdt6tQ zV^{($G{}+xUBOyc-p0?~rdanBdJ_9zo`v7Qu9F1?1v~Nsi}W39J*U1$hca){xs$sI z6Ijvz30MsE_!M9HO~HvO->w-uE}i%a<2L|azsz&}&^$pVd_&;hw>&fhT+&9Gz$gVF z-6l2KrnD2Ef@Gh9C<%JqH;|0DR7fQ`4o*a4zM2+|=K<^ja9)DphI%C!a*OVvQ~oLS zw_mbbMWGss!RU=lgQqLnyFn7VPzaEy)kU8;w{7!g5A7t|T8`>?#^O9DxVMjIJ4hAD zu2VvGP?D@v>oJM+g(*|%5R`#vUKwY$n8d%AjY8;fp4%JI@G@KY@5bbu){}K^&nBy# zqSweZ9bO>lq^*~}$VctzkEGf98Ygdufq{TNw5t;13QcVnLX0C3%u~GUv`x;xTiUwt z3C?w3m@NrzW2U5F&s6KXgAFBL&**&rB{?4TO9SH{_ag~i3i3dPgE zUmZ94Qe7Rc85dzU)p8fU+e_xe9sWw-(vO!GYxJACed?|7VtdD6yZ6Kz@B8dk*u5Z_ zmOeZCjhdc|>eU(RUmF-0KyZ#?SCF}dYh)nv@$ARD-FKWD?Ag=22`xuv0E4lYQV&nE{u+IU-O>YVeHd>-=hg@7g z+JZS5-7(}z1K4Y2yztB}VhwYQ60V(Nyzl!;2V8;R=gii0vvzX#f&)^ju{Jy;aHXo| zZ>?$w+xG=5&4`7brOO(cS15+OQR!5$A~R^yQfK(yD78F-Jo?hIj4yDZm*dyMMy1ja z*7<037Ir^-nn{6qV-&Kt%Qe268&^FqbHrBMC?P5E1=L=wLU>7nkuH%(XG+-53w8Zc zjhktO4)M>70aS7yRZ?)puKvS)U=MALa$3^JT1|U&NgJyVIEt9rXN_YM^{K5w}msD>MUexN#^DX3h-6O>T90Vs-i zuW_F+X@Q-^9_8CNDAU{k*yQ5;1oJa;D`9Cl>S@WViU)jMEG z-p_?}xv8?CSBodUlEsnGqN}CT-nZnkKS$?uG-=K1+zpGkKaAKyLTclvZAFXh=rWHA zSuZN&uh@Yzblej19K_(prW#RQ27h@3Dvmc!sZ*fQYUZ!u#=ymsth!e5j;uX#tgt<@FWIN}nv>~^weaj7EOm$p()9%8oDbL$9iabJuI^u< zr=}(cZeMH11m1$bj@CePPoVjBN5|=ywqkk2cblLi{lgA3;|f)(aoAQnCN038UsXGqi)u^5L^t-$1 z9gg9)9bGrLjkBLoSx4A$68g>U-kD(G``L|ywc%|QtabZ+d>BbE5PTXpp}Ef@HVgI? zCwvaeERZ!y;lj(t3xqWdr+8%!HhCfv9`PfcHVV+ZS<$t|X;0tK(unG7$=1=E7z@TN zw?dT}$Fcus3UCZaDcpE4Xt1|(t39CeXW=EgWKow?O;VfQ`*@Ma+z71~MQHs23G-D(%`Q&$|zo07c-P6q25)#{RK{16jqDky9wRTDPH!t(*U+j&lW zKc^)U?J`c~#x))7TRNn|<@eT%_`cf4%oec!#vakfH&=Tx zz#3~gH)PVH0kL)VGYFHk02i^5AXktn&dvwV7ma2NPC9=Z!{T(}f@<tv z3?^%D-NIQpgjhJ<6#8dbFXirc2+0*x|9tMs?<`3K^y}<3{xz~g{8AYPJ0DPf2XKXv zOiSyBvnz`H%Ylo|kEkA6N<_lm4EvOO+^S~HBQRaDXWKJvN%~2~MwrsznMS3z*x_WM z+@n0>YwwvQtQAuEPk-B(x6H06I{1o-Ut-xdP}X)v9L{q#O$N;f3AL*@vfhPN&~!#+ zo;9Q=I?y%I>ul0F+tv6UqGN^@OG`03>oN^zGbca9CcM{pL6&JK+;mIjHKf^azK7qy zaJbqyt}>4!yI?i=!!7f{VU(0R9vT6B0|3E1MOqdERf|_ldm=g*$jS&6v~3K5Hqo~$ z=%SMUqv#S>*Og;f(m`G7;F*^zpz$j}qWNMob&4EKpW@~eRV|2MXw@@T@7paTcytLv z-)^`6(#|@NEr>cZ1Ts$yw?aBpK`0XKIu_*Z{ITu*FM~}M$*`Hhluw`#LE;#D!)#{n zlhWQ^O_>VJ4fZs%jpEOE-2A|yAo&tlo{cv~L9JFS)N1E!Z8%F5ZAZbY`XBAK&Hxn% zI+{G>$eNz^$SFMKISG6~)1p$Ub1nhbIw*me33gg+N`=?O; z!DxYO7PeXgM&ryyv&nQEYQE zd=V3$7E_`dTj3`gt*1=8vevCb*5{R)aP`GtETY}W{qDa@TVD3YQagnED*cH`B%1-W z8!}FOh(*OHJX`TNOLH8v^3KPl_HDqE@)vU!Yq8Ux}OzY3ZjE2XL)}E4n+}pIqh={=U#5rOT#HYip zkL^;FwWgti?;i~92d_KkfKu*)O~ zXd?W`Qq(>b`3(F)M;s!Su)IO$~`m^3$JwdypcFH0XcINxf@S7;Do{>sQzg%~-t0g=5#z55} z&sQt4>SU8Q;h7Td0PRWnvsP}Wn z1-}DvYv7fT&A=u3Yt`gw)uOW>TSE)D>80kUn$XX{E&(DwKYGaU`@FCfA^;#43P>#z zyy2&Sqe9NlTQ5*QlH(#MtRrCWAFoQOn>9Y8m9KMB9B1$}oB zB1!>&xrB?|(#S>VB|tV4h_xa$1xv1s63X zKfuPNmI<;3q%l(ccD8QG=mG){S4=_G&rMCdUz_C@etLBrx@|X~iR0PhuP$8h)TN}m z;Pm^0C>%jhfk#Fnvun&K=?%A-N9M=|UNk=_wAjTKZ;1O)k({>m$UorrG2fvOk_ zEf9hn%N+geX7uP)tne;edTGg%7nU69%TkvBQpNTWDKc!aAR4f&355vA7VfXmbYS{u zud)?JHRsD3f)x!w)U~8vxod*@$ehPn4cNBp+2I#1E!nl88v6o3AF$aDd9@$*ywaf% zz*>rX3fv84Y{j?C|7c6>6qdE55kdUvy`WK1^kv8d!-wXJ`!Dz^D89$}`+-^d;5BLh z%H9`=2;{ppPNb-@D{I5oxTdvnzmqp*Ex8!)sCHs-o;R7=x5OgH_@Ip?9wAR`4V5N9 z2}pp77x0#piqPdJp@E7LY0*}C8PZ+FQHM@Y6DM3`GQ|N~G-kVK6pzcZkfRpNb|CO- zje68g{4PZUmgu}2aEvo~oc8hS+eRG3B=Mg+QgHuaqX%s@H4 zSeoW5&Y)W~w&t(2QqS63vM!qnHu6rPcu z9N>~C_)c_mlwbCzK1BlDh|2;$i$*t4u_mZL52D|lcyUPAFyv9vLq)m15Obj|_-Q-# zYqkVvWsoIJ3t3~3G>up)7`?;~7e%;p%&^R|RqQKPu= z3Q#N7bK92k0SDRS+DwJI?Zbm>pr^u~g5ZgmV!7N$*k7vkYq2=Gq2?~rZ5Z-!$sKgg zZfUzp%SVyN)@M$9#!omP^!<7ag2D+r*!aEtMl05Lv0bja^x-b zxT2`n>Dw;u?PG{`3?r^WZ}tkUw?LSaH0{)HmSV+&&~{NPH-~h+F_mxuVii$GHH4qoU>^HFe?5 zqN7BN|F|ZaXBW}HfefB5_Y!Er9|*kSPR3>-dT^7(%VZrpF9I%O%3MZ8gGMW*?M@2S z8Tm}$EZvfN1wA3@h94w%z%3YftF{+<4W_UJW9%43{J`C(m20h@KAc7Ve{wt<*uf8l z#SN^j(p;}B>uzX;Vf)~Q%l%7Zz(+TL^KedtLW{Y2VfD!8f&HITi6}Y>t3eHfsh}&0&?4fs z_}y!ZK9rvqnlVfk1%U0KywLO2Af!AV58nx{s%`H@yNnZ&nGgw$X22s9U^WCK^gDst zbs?G?00Z^d^tO<@Ek|JEx0s-uAHdXO{4WxJHn+SyE8E&r%W_ZadaTcF zX=s*OP0T`pF|{jfou{?)oslMG-C?-&2n7c|^nQ=J{B(a!C87saY`U0)ENjdmv0M9}P=h6DR8nJ7Q7{|Iepe_b|jrrMz(lqUGt4 zM{K7u)Q(_NKHkKw9wF1{Tgv*N>K*Lp%1Y|$3#3q^YciQ%hgB_nhYH4~xLUwp8#zVq zz}@e!F1j4_qfTVWiZjlJ2a^dSe@_oDz8us4T%mV&i#m7n&0Y+x;5zv*U=?+)T$7sV zo-}py1ZJx1aD8%BT)MP8rTf*lSkwiJuEKb-$?3@@&(1ctb2u(gmq5M2LJYnN`H~Y< z$jVaq3yX(~MwSZFQlw}48i5;YYioN9VS9+e)|KfqK(Qn65}Sc$mvgXpPYGx|?H>6L z^=flsRpda)GqE?|9LLRWsGzIBRQ+9LP^e_MEZPqy!Y2{0&R&G2xnhp70@7%#p~3X> zLVo_^JPm9IfvfgDHiz(M;|`K}c#h@2nxJpuUOC*cRlOJ4=1f3<=3#z|VPUJ^41)83 z#;lnT*M-1v(3)}dgF!U+U+N!PC0IQI+9DPuoa_|vTQG7A@_-T!EQt2UF(L&ZF9mch?DQPs1 zTW72G>>Bt70LuIWu3rd)vQ~j#MaGB018lUOt&TBI`B_HkJQHTcj<43bg=A-`EcHrQ zV2tZf%pVUN=?RKA+__H48Mu9(25>h0B=vFH9~l(iJC+Tt&(!T5?@5*Gp&#qCrvuvu z>t{KQ{mni!TyshpYldyk)M!K;Z2BAHvl~kc9Wq$gz{Oy1R>2ab* z>`oy|sEYjfFbHJ?)30)G>%9btYm~ypP8!&OlR%A*#3r?qIVF&dSd$pRT;E zyN+=gTHA-=W`FkN0_!}#Um%u%jX1Q6gBCuwroW-|eTgLUi}<^&&xmi8bcwOhDWT;Q z*Db#WHYy}X2`f_gsZ4e3IYCr>(wB#+J8(Z_0J74n9ardiWSxMd*sZa8;s1n_52b3I zL?v^rK&0Dr>1H&dF_4r4&Pk?xKiR`U&k8HKYqQgLXEl~qi6pBVsi(v*hA0f>%jd|y zZTR{aE3~uWZCCRh7w^Z5v^g>-)anlFcr=^1CFXq3uDsMc(TaO5P@CvVe2iy&;0sdMsLB<8DAy0kz{piU722e{EXUx!vu)~Qx43$@&k>Ym zxB&w&vO01>^>} z{1c1!r$qzbd^o!?P`1Pl#IN!7MLqP%0Gx!z7dj{iy;*^Qzmr=0O)z(q@HW=-CK)by zOu?HS-UELK9%P4Uy?NPusdCwCR};J;1~dtYl*H7Y0Y&lQK z7IWMaA0eB^&#S+31slZt*)(rQ=`^`I>%c|u5fLtyBcWi4`7K*i(lK7cG%#1)4VyAYqzvHXEO`I+%!^HS>62?}|Wk*U&Y7uF<7v@@1zz29?)oSoBIQoWR0Bv%sBO z>i$?kJ!^`SPkE2nOr;&OR;J!^p03CLQC@L<5c3L0^I3u2`9br3c{LdvMw@x8_4&AV z__g-D;a3dJDpu-Ya|s8`NaUrEfsl@<>h{eZo2z3|RC~2=buaVoF4$St3~Bw=ya&5C z>~3#W{`4wlh68(t0^7WRKQBv3Y#edky`VZr9lIaSzRek zo*NttHP>UL#Vn4+N)sx6w>#t&X=_VULQ8kXH_5%gZE%30cmO|!J{_uDkx|d*3Q%M=AGF7R!)ZtS zjGld>RjS}pBI0vh_|4R+egcJ(!d?PW#1Du{YmM`Ye0VhzBpH_)TgzHoGfVYU)rzrU zckycLv@2vvsHPb<+y-ClR^S%1vH$|>f`)>V6jR8MB=8Q znO=~XDmx;yM-P;g!^r=eYqK2=;Gy5y6fUa@1sVwG1p@4^zS?zi$EEiceQ5dM>`yb+ zTk9bPN9by6cliH;RT19O0gbggmYbLF3vieVC=v6=!NF@=M|eIK`;*sig5l*&HgFzF zkoHIq#Zi6OhT9wrrY1Oe5Um?G)3A7%8~|z``19#={oq~&KSPr_`+fjTuZ8O&`t?z`Q(2qxfkz^?!Zl0* zf8n=dKPErK%0ufIC|LcYx^lQ*$l@>v?we zYoFF+A7Tfz-fM?21RiAU5h7>Z|FZl+0$SZ%@7T!9(V5KfY(Vg6l+SPlE0r*q{5oH0aOOhF zXmyk3-@1hH-@#<(fGq>8lA}T0*u06ogV3;hSTQP=ejFOHcW;kbyToP&6v1aCdw80y zE3M$gAjNmS6R0ZNU^Kpv84?vBXs~cGv4hbUWH>Ak=9$uOj&={#iK3I(TD|Izo z6(M}bvL9z}Y|DU*g6;xM2)23_`Xm7}(u&(|*u>-a9H=S(_g7e7ZfJpM0vMBf3ep1g zI`}5vfB(nVU?t&~d>G|`e1^1x^|~~z(4|-GD@WYbN{A7G(pW(FTyA>2sJrWRxHKUM z$YUZR5E&cz{wh0cl|ieC!UMh0-z@~mV$1x|&pfhHOoQQ;mj$*+R!FGY=SNIGcb0+A zt;eGTX@qWI+53HW@|31QVV@D??|NNCM)@gs2_TD{p>r`uzqJU@iO$gk?kN zP$?)R{O8T79v|#m8ll{PWuxMvKp$iUTv@YyD!-^Sa<|r1Zm28b{hf_V)xUgk5E+4~ zVz@Va{8>}Oz*z6~Bf3vh6OWu3ADy_B2M9pzs9sB_FV{c-H}XUQg80m z2led>lm%~7KX~xZ=zZI^Y4cL!KHj45x&|9N?Aj)8_w<}PXNSfHxFk__!Ln4*Nr z!bm_Kw;lK_iGsj_**Xbhvp^bvwPGr;s~GoIh`9wVXhw zpHL^&bR0kVq~q3M@!(&lygPjTrdqQE2PiO**N2DK`gASwi~aBEr*BuJ8_UDqc-P|s z+QWDGm1V9#JyMelbD&@z+)x^8eqs6qNSg+a0X>V(xyu$s(b*yXoGW`SCwBX zEY;iEI)5F1MsW%Mv)lQTvYRz!_aT>4c|Z7aPEr-5#^0@RZu@qv*ZsLzV$>d86;ao0 z2ps=e;3U=Kkdu_*!JuvJy87go<(i{)r@W(dZO!m^f*V{8G*P-1{4K|TvPG4p)gVj` z>5Mvh{|&SJ!jgWkZGSr!OUQ~DUlH%;;cD+u zE+Yx}7KwN1`99YnE7@iGKHPGJV;s%ghSj-=x7UYz1$MpRrx-_CCUr&vBKEs&PI>tX z(`Q*e-AMg#mo!rjcOWhC^EAsbmFWxtjdg*tDW-D#faj&?Z3)gW{>5dX&%Unv{p&ZI zs;<|&I5;NDH0Am&bL11aXg@cxaY^I(|9i?KW(b3SL~!`QS~C=)i~XTeODy|<^VnTwtCWmg zo2);%g3^q=X;sQ}Pi_^3bS5zrvf2}!*`e9(x0PyvK}nC9l<4V%Z=dF)Uq!&(hALU7 z_Ww9EAns^Lq2rl_iY)eztO8rqWV%R-^nifq73VdWt`S3@ICSE7K?9%bl{hf`fr&X` zS6$J;zDR33f!O7NK%3v%dl{K{d=@cG=%-38oxQ)i`(rtA-yTG| zohsFoI0(N<6GbQZTDI!X68*A!Fl9!3NN^T+;Rq2qjeK{=`I(vpn_g>6=zc4!?o_$H zT;^7|Qm@x#V9S3fp=Ev0(9eQKB2x{AHbdZaEppn$iaQ^We@t;p3B4W~N;VFFpRmVL49FpJK_(n}q1z3#Htn=`14n_ADUCr; z;!5Lt(L?18#6#deF{fJ@dXVO*+!)$&#m;j(f`}T)8Blq!z^?-P|DJVs2v_3pj$3VF z@ceDe&VTI7)AP*s0mcyXyzp$02D$BAa4c==U>sSyxLE5`#@7kzNOs@X>mRMBG}aU} ztpk~!6l-vzI;o2u{=0+fR54+e+Z~Xy{a5bD^SOC(MsSkV&afvrwL0