Compare commits
10 Commits
b1fd987955
...
f633b3cd4a
Author | SHA1 | Date |
---|---|---|
Jarrod Doyle | f633b3cd4a | |
Jarrod Doyle | fb56f03a74 | |
Jarrod Doyle | 1a702b7fd4 | |
Jarrod Doyle | 93ca0bc404 | |
Jarrod Doyle | 9b5fd86a7c | |
Jarrod Doyle | bc101702aa | |
Jarrod Doyle | d40c870caf | |
Jarrod Doyle | ae18dbac3d | |
Jarrod Doyle | 020260a2f3 | |
Jarrod Doyle | fe503f51de |
|
@ -175,6 +175,18 @@ dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anes"
|
||||||
|
version = "0.1.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstyle"
|
||||||
|
version = "1.0.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2faccea4cc4ab4a667ce676a30e8ec13922a692c99bb8f5b11f1502c72e04220"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "approx"
|
name = "approx"
|
||||||
version = "0.5.1"
|
version = "0.5.1"
|
||||||
|
@ -1211,6 +1223,12 @@ version = "1.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223"
|
checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cast"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
version = "1.0.83"
|
version = "1.0.83"
|
||||||
|
@ -1248,6 +1266,33 @@ version = "0.1.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e"
|
checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ciborium"
|
||||||
|
version = "0.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e"
|
||||||
|
dependencies = [
|
||||||
|
"ciborium-io",
|
||||||
|
"ciborium-ll",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ciborium-io"
|
||||||
|
version = "0.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ciborium-ll"
|
||||||
|
version = "0.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9"
|
||||||
|
dependencies = [
|
||||||
|
"ciborium-io",
|
||||||
|
"half",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clang-sys"
|
name = "clang-sys"
|
||||||
version = "1.7.0"
|
version = "1.7.0"
|
||||||
|
@ -1259,6 +1304,31 @@ dependencies = [
|
||||||
"libloading 0.8.1",
|
"libloading 0.8.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap"
|
||||||
|
version = "4.4.18"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1e578d6ec4194633722ccf9544794b71b1385c3c027efe0c55db226fc880865c"
|
||||||
|
dependencies = [
|
||||||
|
"clap_builder",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap_builder"
|
||||||
|
version = "4.4.18"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4df4df40ec50c46000231c914968278b1eb05098cf8f1b3a518a95030e71d1c7"
|
||||||
|
dependencies = [
|
||||||
|
"anstyle",
|
||||||
|
"clap_lex",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap_lex"
|
||||||
|
version = "0.6.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "codespan-reporting"
|
name = "codespan-reporting"
|
||||||
version = "0.11.1"
|
version = "0.11.1"
|
||||||
|
@ -1431,6 +1501,42 @@ dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "criterion"
|
||||||
|
version = "0.5.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f2b12d017a929603d80db1831cd3a24082f8137ce19c69e6447f54f5fc8d692f"
|
||||||
|
dependencies = [
|
||||||
|
"anes",
|
||||||
|
"cast",
|
||||||
|
"ciborium",
|
||||||
|
"clap",
|
||||||
|
"criterion-plot",
|
||||||
|
"is-terminal",
|
||||||
|
"itertools",
|
||||||
|
"num-traits",
|
||||||
|
"once_cell",
|
||||||
|
"oorandom",
|
||||||
|
"plotters",
|
||||||
|
"rayon",
|
||||||
|
"regex",
|
||||||
|
"serde",
|
||||||
|
"serde_derive",
|
||||||
|
"serde_json",
|
||||||
|
"tinytemplate",
|
||||||
|
"walkdir",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "criterion-plot"
|
||||||
|
version = "0.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1"
|
||||||
|
dependencies = [
|
||||||
|
"cast",
|
||||||
|
"itertools",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossbeam-channel"
|
name = "crossbeam-channel"
|
||||||
version = "0.5.11"
|
version = "0.5.11"
|
||||||
|
@ -1440,12 +1546,37 @@ dependencies = [
|
||||||
"crossbeam-utils",
|
"crossbeam-utils",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-deque"
|
||||||
|
version = "0.8.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d"
|
||||||
|
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]]
|
[[package]]
|
||||||
name = "crossbeam-utils"
|
name = "crossbeam-utils"
|
||||||
version = "0.8.19"
|
version = "0.8.19"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345"
|
checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crunchy"
|
||||||
|
version = "0.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "d3d12"
|
name = "d3d12"
|
||||||
version = "0.7.0"
|
version = "0.7.0"
|
||||||
|
@ -1481,6 +1612,12 @@ version = "1.2.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650"
|
checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "either"
|
||||||
|
version = "1.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "encase"
|
name = "encase"
|
||||||
version = "0.6.1"
|
version = "0.6.1"
|
||||||
|
@ -1528,6 +1665,16 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "errno"
|
||||||
|
version = "0.3.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"windows-sys 0.52.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "euclid"
|
name = "euclid"
|
||||||
version = "0.22.9"
|
version = "0.22.9"
|
||||||
|
@ -1888,12 +2035,25 @@ dependencies = [
|
||||||
"svg_fmt",
|
"svg_fmt",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "half"
|
||||||
|
version = "2.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bc52e53916c08643f1b56ec082790d1e86a32e58dc5268f897f313fbae7b4872"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"crunchy",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "haranae-rs"
|
name = "haranae-rs"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bevy",
|
"bevy",
|
||||||
|
"criterion",
|
||||||
|
"ndarray",
|
||||||
"rand",
|
"rand",
|
||||||
|
"rayon",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1928,6 +2088,12 @@ dependencies = [
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hermit-abi"
|
||||||
|
version = "0.3.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5d3d0e0f38255e7fa3cf31335b3a56f05febd18025f4db5ef7a0cfb4f8da651f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hexasphere"
|
name = "hexasphere"
|
||||||
version = "9.1.0"
|
version = "9.1.0"
|
||||||
|
@ -2025,6 +2191,26 @@ dependencies = [
|
||||||
"mach2",
|
"mach2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "is-terminal"
|
||||||
|
version = "0.4.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0bad00257d07be169d870ab665980b06cdb366d792ad690bf2e76876dc503455"
|
||||||
|
dependencies = [
|
||||||
|
"hermit-abi",
|
||||||
|
"rustix",
|
||||||
|
"windows-sys 0.52.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "itertools"
|
||||||
|
version = "0.10.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
|
||||||
|
dependencies = [
|
||||||
|
"either",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itoa"
|
name = "itoa"
|
||||||
version = "1.0.10"
|
version = "1.0.10"
|
||||||
|
@ -2173,6 +2359,12 @@ dependencies = [
|
||||||
"pkg-config",
|
"pkg-config",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "linux-raw-sys"
|
||||||
|
version = "0.4.13"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lock_api"
|
name = "lock_api"
|
||||||
version = "0.4.11"
|
version = "0.4.11"
|
||||||
|
@ -2216,6 +2408,16 @@ dependencies = [
|
||||||
"regex-automata 0.1.10",
|
"regex-automata 0.1.10",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "matrixmultiply"
|
||||||
|
version = "0.3.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7574c1cf36da4798ab73da5b215bbf444f50718207754cb522201d78d1cd0ff2"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"rawpointer",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "memchr"
|
name = "memchr"
|
||||||
version = "2.7.1"
|
version = "2.7.1"
|
||||||
|
@ -2306,6 +2508,20 @@ dependencies = [
|
||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ndarray"
|
||||||
|
version = "0.15.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "adb12d4e967ec485a5f71c6311fe28158e9d6f4bc4a447b474184d0f91a8fa32"
|
||||||
|
dependencies = [
|
||||||
|
"matrixmultiply",
|
||||||
|
"num-complex",
|
||||||
|
"num-integer",
|
||||||
|
"num-traits",
|
||||||
|
"rawpointer",
|
||||||
|
"rayon",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ndk"
|
name = "ndk"
|
||||||
version = "0.7.0"
|
version = "0.7.0"
|
||||||
|
@ -2392,6 +2608,15 @@ dependencies = [
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-complex"
|
||||||
|
version = "0.4.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1ba157ca0885411de85d6ca030ba7e2a83a28636056c7c699b07c8b6f7383214"
|
||||||
|
dependencies = [
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-derive"
|
name = "num-derive"
|
||||||
version = "0.3.3"
|
version = "0.3.3"
|
||||||
|
@ -2403,6 +2628,16 @@ dependencies = [
|
||||||
"syn 1.0.109",
|
"syn 1.0.109",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-integer"
|
||||||
|
version = "0.1.45"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-traits"
|
name = "num-traits"
|
||||||
version = "0.2.17"
|
version = "0.2.17"
|
||||||
|
@ -2546,6 +2781,12 @@ version = "1.19.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
|
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "oorandom"
|
||||||
|
version = "11.1.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "orbclient"
|
name = "orbclient"
|
||||||
version = "0.3.47"
|
version = "0.3.47"
|
||||||
|
@ -2650,6 +2891,34 @@ version = "0.3.29"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2900ede94e305130c13ddd391e0ab7cbaeb783945ae07a279c268cb05109c6cb"
|
checksum = "2900ede94e305130c13ddd391e0ab7cbaeb783945ae07a279c268cb05109c6cb"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "plotters"
|
||||||
|
version = "0.3.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d2c224ba00d7cadd4d5c660deaf2098e5e80e07846537c51f9cfa4be50c1fd45"
|
||||||
|
dependencies = [
|
||||||
|
"num-traits",
|
||||||
|
"plotters-backend",
|
||||||
|
"plotters-svg",
|
||||||
|
"wasm-bindgen",
|
||||||
|
"web-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "plotters-backend"
|
||||||
|
version = "0.3.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9e76628b4d3a7581389a35d5b6e2139607ad7c75b17aed325f210aa91f4a9609"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "plotters-svg"
|
||||||
|
version = "0.3.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "38f6d39893cca0701371e3c27294f09797214b86f1fb951b89ade8ec04e2abab"
|
||||||
|
dependencies = [
|
||||||
|
"plotters-backend",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "png"
|
name = "png"
|
||||||
version = "0.17.11"
|
version = "0.17.11"
|
||||||
|
@ -2760,6 +3029,32 @@ version = "0.5.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f2ff9a1f06a88b01621b7ae906ef0211290d1c8a168a15542486a8f61c0833b9"
|
checksum = "f2ff9a1f06a88b01621b7ae906ef0211290d1c8a168a15542486a8f61c0833b9"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rawpointer"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rayon"
|
||||||
|
version = "1.8.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fa7237101a77a10773db45d62004a272517633fbcc3df19d96455ede1122e051"
|
||||||
|
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]]
|
[[package]]
|
||||||
name = "rectangle-pack"
|
name = "rectangle-pack"
|
||||||
version = "0.4.2"
|
version = "0.4.2"
|
||||||
|
@ -2874,6 +3169,19 @@ version = "1.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
|
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustix"
|
||||||
|
version = "0.38.31"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 2.4.2",
|
||||||
|
"errno",
|
||||||
|
"libc",
|
||||||
|
"linux-raw-sys",
|
||||||
|
"windows-sys 0.52.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ruzstd"
|
name = "ruzstd"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
|
@ -3123,6 +3431,16 @@ dependencies = [
|
||||||
"once_cell",
|
"once_cell",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tinytemplate"
|
||||||
|
version = "1.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tinyvec"
|
name = "tinyvec"
|
||||||
version = "1.6.0"
|
version = "1.6.0"
|
||||||
|
@ -3644,6 +3962,15 @@ dependencies = [
|
||||||
"windows-targets 0.48.5",
|
"windows-targets 0.48.5",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-sys"
|
||||||
|
version = "0.52.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
|
||||||
|
dependencies = [
|
||||||
|
"windows-targets 0.52.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-targets"
|
name = "windows-targets"
|
||||||
version = "0.42.2"
|
version = "0.42.2"
|
||||||
|
|
|
@ -7,7 +7,14 @@ edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bevy = "0.12.1"
|
bevy = "0.12.1"
|
||||||
|
criterion = "0.5.1"
|
||||||
|
ndarray = { version = "0.15.6", features = ["rayon"] }
|
||||||
rand = "0.8.5"
|
rand = "0.8.5"
|
||||||
|
rayon = "1.8.1"
|
||||||
|
|
||||||
[profile.dev.package."*"]
|
[profile.dev.package."*"]
|
||||||
opt-level = 3
|
opt-level = 3
|
||||||
|
|
||||||
|
[[bench]]
|
||||||
|
name = "rule_generation"
|
||||||
|
harness = false
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
use criterion::{black_box, criterion_group, criterion_main, Criterion};
|
||||||
|
use haranae_rs::falling_sand::rules::FallingSandRules;
|
||||||
|
|
||||||
|
fn criterion_benchmark(c: &mut Criterion) {
|
||||||
|
c.bench_function("Rule Generation", |b| {
|
||||||
|
b.iter(|| black_box(FallingSandRules::default()))
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
criterion_group!(benches, criterion_benchmark);
|
||||||
|
criterion_main!(benches);
|
|
@ -0,0 +1,104 @@
|
||||||
|
use bevy::ecs::{component::Component, system::Res};
|
||||||
|
use ndarray::Array2;
|
||||||
|
use rand::Rng;
|
||||||
|
|
||||||
|
use crate::util::DirtyRect;
|
||||||
|
|
||||||
|
use super::{element::Element, rules::FallingSandRules};
|
||||||
|
|
||||||
|
#[derive(Component)]
|
||||||
|
pub struct Chunk {
|
||||||
|
step: usize,
|
||||||
|
pub width: usize,
|
||||||
|
pub height: usize,
|
||||||
|
cells: Array2<Element>,
|
||||||
|
pub dirty_rect: DirtyRect,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Chunk {
|
||||||
|
pub fn new(width: usize, height: usize) -> Self {
|
||||||
|
let mut initial = Self {
|
||||||
|
step: 0,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
cells: Array2::from_elem((width + 2, height + 2), Element::None),
|
||||||
|
dirty_rect: DirtyRect::default(),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Set Main area to air
|
||||||
|
for y in 0..height {
|
||||||
|
for x in 0..width {
|
||||||
|
initial.set_cell(x, y, Element::Air);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let max_y = height / rand::thread_rng().gen_range(2..10);
|
||||||
|
for y in 0..=max_y {
|
||||||
|
for x in 0..width {
|
||||||
|
initial.set_cell(x, y, Element::Water);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
initial
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_cell(&mut self, x: usize, y: usize, element: Element) {
|
||||||
|
if x >= self.width || y >= self.height {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let x = x + 1;
|
||||||
|
let y = y + 1;
|
||||||
|
|
||||||
|
self.cells[(x, y)] = element;
|
||||||
|
self.dirty_rect.add_point(x - 1, y - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_cell(&self, x: usize, y: usize) -> Option<Element> {
|
||||||
|
if x >= self.width || y >= self.height {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let x = x + 1;
|
||||||
|
let y = y + 1;
|
||||||
|
|
||||||
|
Some(self.cells[(x, y)])
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn update(&mut self, rules: &Res<FallingSandRules>) {
|
||||||
|
// We operate on 2x2 blocks of cells. Each update we offset the blocks using a
|
||||||
|
// modified Margolus neighbourhood.
|
||||||
|
let offsets = [(0, 1), (1, 1), (0, 0), (1, 0)];
|
||||||
|
let block_offset = [(0, 0), (1, 1), (0, 1), (1, 0)][self.step];
|
||||||
|
self.step = (self.step + 1) % 4;
|
||||||
|
|
||||||
|
// Faster to reuse rather than keep remaking it within the loops
|
||||||
|
// Also we directly access the cells here rather than using the helper function
|
||||||
|
// because we know the values will never be out of bounds
|
||||||
|
let mut in_elements: [Element; 4] = [Element::None; 4];
|
||||||
|
for block_y in 0..(self.height / 2) {
|
||||||
|
let y = block_y * 2 + block_offset.1 + 1;
|
||||||
|
for block_x in 0..(self.width / 2) {
|
||||||
|
let x = block_x * 2 + block_offset.0 + 1;
|
||||||
|
|
||||||
|
// Get all the cells in our block and convert them to a rule state for lookup
|
||||||
|
// Because our offset can cause cell look-ups to go ourside of the grid we have
|
||||||
|
// a default `Element::None`
|
||||||
|
for i in 0..offsets.len() {
|
||||||
|
let o = offsets[i];
|
||||||
|
in_elements[i] = self.cells[(x + o.0, y + o.1)];
|
||||||
|
}
|
||||||
|
let out_elements = rules.get_result(&in_elements);
|
||||||
|
|
||||||
|
// We only need to actually update things if the state changed
|
||||||
|
for i in 0..offsets.len() {
|
||||||
|
let o = offsets[i];
|
||||||
|
if in_elements[i] != out_elements[i] {
|
||||||
|
let pos = (x + o.0, y + o.1);
|
||||||
|
self.cells[pos] = out_elements[i];
|
||||||
|
self.dirty_rect.add_point(pos.0 - 1, pos.1 - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,67 @@
|
||||||
|
use super::rules::RuleBuilder;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
|
pub enum Element {
|
||||||
|
None,
|
||||||
|
Air,
|
||||||
|
Sand,
|
||||||
|
Water,
|
||||||
|
ElementCount,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<u32> for Element {
|
||||||
|
fn from(value: u32) -> Self {
|
||||||
|
match value {
|
||||||
|
x if x == Element::Air as u32 => Element::Air,
|
||||||
|
x if x == Element::Sand as u32 => Element::Sand,
|
||||||
|
x if x == Element::Water as u32 => Element::Water,
|
||||||
|
_ => Element::None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn update_sand(block: &mut RuleBuilder, me: Element) {
|
||||||
|
let swap_elements = [Element::Air, Element::Water];
|
||||||
|
|
||||||
|
let bottom = block.get(0, -1);
|
||||||
|
let bottom_left = block.get(-1, -1);
|
||||||
|
let bottom_right = block.get(1, -1);
|
||||||
|
|
||||||
|
if swap_elements.contains(&bottom) {
|
||||||
|
block.set(0, 0, bottom);
|
||||||
|
block.set(0, -1, me);
|
||||||
|
} else if swap_elements.contains(&bottom_left) {
|
||||||
|
block.set(0, 0, bottom_left);
|
||||||
|
block.set(-1, -1, me);
|
||||||
|
} else if swap_elements.contains(&bottom_right) {
|
||||||
|
block.set(0, 0, bottom_right);
|
||||||
|
block.set(1, -1, me);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn update_water(block: &mut RuleBuilder, me: Element) {
|
||||||
|
let swap_elements = [Element::Air];
|
||||||
|
|
||||||
|
let bottom = block.get(0, -1);
|
||||||
|
let bottom_left = block.get(-1, -1);
|
||||||
|
let bottom_right = block.get(1, -1);
|
||||||
|
let left = block.get(-1, 0);
|
||||||
|
let right = block.get(1, 0);
|
||||||
|
|
||||||
|
if swap_elements.contains(&bottom) {
|
||||||
|
block.set(0, 0, bottom);
|
||||||
|
block.set(0, -1, me);
|
||||||
|
} else if swap_elements.contains(&bottom_left) {
|
||||||
|
block.set(0, 0, bottom_left);
|
||||||
|
block.set(-1, -1, me);
|
||||||
|
} else if swap_elements.contains(&bottom_right) {
|
||||||
|
block.set(0, 0, bottom_right);
|
||||||
|
block.set(1, -1, me);
|
||||||
|
} else if swap_elements.contains(&left) {
|
||||||
|
block.set(0, 0, left);
|
||||||
|
block.set(-1, 0, me);
|
||||||
|
} else if swap_elements.contains(&right) {
|
||||||
|
block.set(0, 0, right);
|
||||||
|
block.set(1, 0, me);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,7 @@
|
||||||
mod rules;
|
mod chunk;
|
||||||
|
mod element;
|
||||||
|
pub mod rules;
|
||||||
|
mod systems;
|
||||||
|
|
||||||
use bevy::{
|
use bevy::{
|
||||||
app::{Plugin, Startup},
|
app::{Plugin, Startup},
|
||||||
|
@ -13,11 +16,8 @@ use bevy::{
|
||||||
sprite::SpriteBundle,
|
sprite::SpriteBundle,
|
||||||
transform::components::Transform,
|
transform::components::Transform,
|
||||||
};
|
};
|
||||||
use rand::Rng;
|
|
||||||
|
|
||||||
use crate::util::DirtyRect;
|
use self::{chunk::Chunk, element::Element, rules::FallingSandRules};
|
||||||
|
|
||||||
use self::rules::{to_rule_state, FallingSandRules};
|
|
||||||
|
|
||||||
pub struct FallingSandPlugin;
|
pub struct FallingSandPlugin;
|
||||||
|
|
||||||
|
@ -27,9 +27,9 @@ impl Plugin for FallingSandPlugin {
|
||||||
app.add_systems(
|
app.add_systems(
|
||||||
Update,
|
Update,
|
||||||
(
|
(
|
||||||
place_sand_system,
|
systems::place_sand,
|
||||||
simulate_chunk_system,
|
systems::simulate_chunk,
|
||||||
update_chunk_texture_system,
|
systems::update_chunk_texture,
|
||||||
)
|
)
|
||||||
.chain(),
|
.chain(),
|
||||||
);
|
);
|
||||||
|
@ -49,190 +49,21 @@ fn setup(mut commands: Commands, mut images: ResMut<Assets<Image>>) {
|
||||||
TextureFormat::Rgba8UnormSrgb,
|
TextureFormat::Rgba8UnormSrgb,
|
||||||
);
|
);
|
||||||
|
|
||||||
let image_handle = images.add(image);
|
let sprite_bundle1 = SpriteBundle {
|
||||||
|
|
||||||
commands.spawn(Chunk::new(256, 256)).insert(SpriteBundle {
|
|
||||||
sprite: Sprite {
|
sprite: Sprite {
|
||||||
flip_y: true,
|
flip_y: true,
|
||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
texture: image_handle,
|
texture: images.add(image.clone()),
|
||||||
transform: Transform::from_translation(Vec3::new(256., 0., 0.))
|
transform: Transform::from_translation(Vec3::new(256., 0., 0.))
|
||||||
.with_scale(Vec3::new(2., 2., 0.)),
|
.with_scale(Vec3::new(2., 2., 0.)),
|
||||||
..default()
|
..default()
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Component)]
|
|
||||||
pub struct Chunk {
|
|
||||||
step: usize,
|
|
||||||
width: usize,
|
|
||||||
height: usize,
|
|
||||||
cells: Vec<Element>,
|
|
||||||
dirty_rect: DirtyRect,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Chunk {
|
|
||||||
pub fn new(width: usize, height: usize) -> Self {
|
|
||||||
let mut initial = Self {
|
|
||||||
step: 0,
|
|
||||||
width,
|
|
||||||
height,
|
|
||||||
cells: vec![Element::Air; width * height],
|
|
||||||
dirty_rect: DirtyRect::default(),
|
|
||||||
};
|
};
|
||||||
|
let mut sprite_bundle2 = sprite_bundle1.clone();
|
||||||
|
sprite_bundle2.texture = images.add(image.clone());
|
||||||
|
sprite_bundle2.transform =
|
||||||
|
Transform::from_translation(Vec3::new(-256., 0., 0.)).with_scale(Vec3::new(2., 2., 0.));
|
||||||
|
|
||||||
let max_y = height / rand::thread_rng().gen_range(2..10);
|
commands.spawn(Chunk::new(256, 256)).insert(sprite_bundle1);
|
||||||
for y in 0..=max_y {
|
commands.spawn(Chunk::new(256, 256)).insert(sprite_bundle2);
|
||||||
for x in 0..width {
|
|
||||||
initial.set_cell(x, y, Element::Water);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
initial
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_cell(&mut self, x: usize, y: usize, element: Element) {
|
|
||||||
if x >= self.width || y >= self.height {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
self.cells[x + y * self.width] = element;
|
|
||||||
self.dirty_rect.add_point(x, y);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn swap_cells(&mut self, x0: usize, y0: usize, x1: usize, y1: usize) {
|
|
||||||
if x0 >= self.width || y0 >= self.height || x1 >= self.width || y1 >= self.height {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let i0 = x0 + y0 * self.width;
|
|
||||||
let i1 = x1 + y1 * self.width;
|
|
||||||
self.cells.swap(i0, i1);
|
|
||||||
self.dirty_rect.add_point(x0, y0);
|
|
||||||
self.dirty_rect.add_point(x1, y1);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_cell(&self, x: usize, y: usize) -> Option<Element> {
|
|
||||||
if x >= self.width || y >= self.height {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
Some(self.cells[x + y * self.width])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn place_sand_system(mut query: Query<&mut Chunk>) {
|
|
||||||
for mut chunk in &mut query {
|
|
||||||
let frac = chunk.width / 2;
|
|
||||||
let x = (chunk.width - frac) / 2 + rand::thread_rng().gen_range(0..frac);
|
|
||||||
let y = chunk.height - 1;
|
|
||||||
chunk.set_cell(x, y, Element::Sand);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn simulate_chunk_system(rules: Res<FallingSandRules>, mut query: Query<&mut Chunk>) {
|
|
||||||
for mut chunk in &mut query {
|
|
||||||
// Determine which Margolus neighbourhood offset we're using this update
|
|
||||||
let offset = if chunk.step == 0 {
|
|
||||||
(0, 0)
|
|
||||||
} else if chunk.step == 1 {
|
|
||||||
(1, 1)
|
|
||||||
} else if chunk.step == 2 {
|
|
||||||
(0, 1)
|
|
||||||
} else {
|
|
||||||
(1, 0)
|
|
||||||
};
|
|
||||||
chunk.step = (chunk.step + 1) % 4;
|
|
||||||
|
|
||||||
// We're operating on 2x2 blocks of cells
|
|
||||||
for block_y in 0..(chunk.height / 2) {
|
|
||||||
let y = block_y * 2 + offset.1;
|
|
||||||
for block_x in 0..(chunk.width / 2) {
|
|
||||||
let x = block_x * 2 + offset.0;
|
|
||||||
|
|
||||||
// Get all the cells in our block and convert them to a rule state for lookup
|
|
||||||
// Because our offset can cause cell look-ups to go ourside of the grid we have
|
|
||||||
// a default `Element::None`
|
|
||||||
// Cells are obtained in the order top-left, top-right, bottom-left, bottom-right
|
|
||||||
let start_state = to_rule_state((
|
|
||||||
chunk.get_cell(x, y + 1).unwrap_or(Element::None),
|
|
||||||
chunk.get_cell(x + 1, y + 1).unwrap_or(Element::None),
|
|
||||||
chunk.get_cell(x, y).unwrap_or(Element::None),
|
|
||||||
chunk.get_cell(x + 1, y).unwrap_or(Element::None),
|
|
||||||
));
|
|
||||||
let end_state = rules.get_result(start_state);
|
|
||||||
|
|
||||||
// We only need to actually update things if the state changed
|
|
||||||
// Same ordering as above.
|
|
||||||
if start_state != end_state {
|
|
||||||
if (start_state & 0xFF000000) != (end_state & 0xFF000000) {
|
|
||||||
chunk.set_cell(x, y + 1, Element::from((end_state >> 24) & 0xFF));
|
|
||||||
}
|
|
||||||
if (start_state & 0x00FF0000) != (end_state & 0x00FF0000) {
|
|
||||||
chunk.set_cell(x + 1, y + 1, Element::from((end_state >> 16) & 0xFF));
|
|
||||||
}
|
|
||||||
if (start_state & 0x0000FF00) != (end_state & 0x0000FF00) {
|
|
||||||
chunk.set_cell(x, y, Element::from((end_state >> 8) & 0xFF));
|
|
||||||
}
|
|
||||||
if (start_state & 0x000000FF) != (end_state & 0x000000FF) {
|
|
||||||
chunk.set_cell(x + 1, y, Element::from(end_state & 0xFF));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn update_chunk_texture_system(
|
|
||||||
mut images: ResMut<Assets<Image>>,
|
|
||||||
mut query: Query<(&mut Chunk, &Handle<Image>)>,
|
|
||||||
) {
|
|
||||||
for (mut chunk, image_handle) in &mut query {
|
|
||||||
if !chunk.dirty_rect.is_dirty() {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(image) = images.get_mut(image_handle) {
|
|
||||||
for y in chunk.dirty_rect.range_y() {
|
|
||||||
for x in chunk.dirty_rect.range_x() {
|
|
||||||
let mut colour = (0, 0, 0);
|
|
||||||
if let Some(element) = chunk.cells.get(x + y * chunk.width) {
|
|
||||||
match element {
|
|
||||||
Element::Air => colour = (25, 24, 26),
|
|
||||||
Element::Sand => colour = (255, 216, 102),
|
|
||||||
Element::Water => colour = (120, 220, 232),
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let index = (x + y * chunk.width) * 4;
|
|
||||||
image.data[index] = colour.0;
|
|
||||||
image.data[index + 1] = colour.1;
|
|
||||||
image.data[index + 2] = colour.2;
|
|
||||||
image.data[index + 3] = 255;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
chunk.dirty_rect.reset();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
|
||||||
pub enum Element {
|
|
||||||
None,
|
|
||||||
Air,
|
|
||||||
Sand,
|
|
||||||
Water,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<u32> for Element {
|
|
||||||
fn from(value: u32) -> Self {
|
|
||||||
match value {
|
|
||||||
x if x == Element::Air as u32 => Element::Air,
|
|
||||||
x if x == Element::Sand as u32 => Element::Sand,
|
|
||||||
x if x == Element::Water as u32 => Element::Water,
|
|
||||||
_ => Element::None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,35 +1,60 @@
|
||||||
use bevy::{ecs::system::Resource, utils::HashMap};
|
use bevy::{ecs::system::Resource, utils::HashMap};
|
||||||
|
|
||||||
use super::Element;
|
use super::{
|
||||||
|
element::{update_sand, update_water},
|
||||||
|
Element,
|
||||||
|
};
|
||||||
|
|
||||||
struct RuleConfig {
|
pub struct RuleBuilder {
|
||||||
element_groups: Vec<Vec<Element>>,
|
elements: [Element; 4],
|
||||||
rules: Vec<([usize; 4], [usize; 4])>,
|
processed: [bool; 4],
|
||||||
|
position: i8,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RuleConfig {
|
impl RuleBuilder {
|
||||||
fn compile(&self) -> HashMap<u32, u32> {
|
pub fn build(input: &[Element; 4]) -> u32 {
|
||||||
let mut rules = HashMap::new();
|
let mut block = RuleBuilder {
|
||||||
for i in 0..self.rules.len() {
|
elements: *input,
|
||||||
let rule = self.rules[i];
|
processed: [false; 4],
|
||||||
|
position: 0,
|
||||||
|
};
|
||||||
|
|
||||||
let i0 = &self.element_groups[rule.0[0]];
|
for i in 0..4 {
|
||||||
let i1 = &self.element_groups[rule.0[1]];
|
if block.processed[i] {
|
||||||
let i2 = &self.element_groups[rule.0[2]];
|
continue;
|
||||||
let i3 = &self.element_groups[rule.0[3]];
|
|
||||||
|
|
||||||
let o0 = &self.element_groups[rule.1[0]];
|
|
||||||
let o1 = &self.element_groups[rule.1[1]];
|
|
||||||
let o2 = &self.element_groups[rule.1[2]];
|
|
||||||
let o3 = &self.element_groups[rule.1[3]];
|
|
||||||
|
|
||||||
// !HACK: Assume element groups are length 1 for now!
|
|
||||||
let input = to_rule_state((i0[0], i1[0], i2[0], i3[0]));
|
|
||||||
let output = to_rule_state((o0[0], o1[0], o2[0], o3[0]));
|
|
||||||
rules.insert(input, output);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rules
|
block.position = i as i8;
|
||||||
|
let element = block.elements[i];
|
||||||
|
match element {
|
||||||
|
Element::Sand => update_sand(&mut block, element),
|
||||||
|
Element::Water => update_water(&mut block, element),
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
to_rule_state(&block.elements)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get(&self, x: i8, y: i8) -> Element {
|
||||||
|
let x = x + (self.position % 2);
|
||||||
|
let y = (self.position / 2) - y;
|
||||||
|
if !(0..2).contains(&x) || !(0..2).contains(&y) {
|
||||||
|
return Element::None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let idx = (x + y * 2) as usize;
|
||||||
|
self.elements[idx]
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set(&mut self, x: i8, y: i8, element: Element) {
|
||||||
|
let x = x + (self.position % 2);
|
||||||
|
let y = (self.position / 2) - y;
|
||||||
|
if (0..2).contains(&x) && (0..2).contains(&y) {
|
||||||
|
let idx = (x + y * 2) as usize;
|
||||||
|
self.elements[idx] = element;
|
||||||
|
self.processed[idx] = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,98 +65,59 @@ pub struct FallingSandRules {
|
||||||
|
|
||||||
impl Default for FallingSandRules {
|
impl Default for FallingSandRules {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
// Pre-computed rules
|
// Build a list of elements
|
||||||
// I should really start building a tool for this instead of manually calculating it huh
|
// We do it this way so it automatically handles adding new elements
|
||||||
let rule_config = RuleConfig {
|
let mut elements = vec![];
|
||||||
element_groups: vec![
|
for i in 0..(Element::ElementCount as u32) {
|
||||||
vec![Element::Air],
|
elements.push(Element::from(i));
|
||||||
vec![Element::Sand],
|
}
|
||||||
vec![Element::Water],
|
|
||||||
],
|
// Attempt to compute a rule for every possible element block permutation
|
||||||
rules: vec![
|
// Only bother keeping the rule if the state actually changes
|
||||||
// Air/Sand
|
// TODO: See if there's a better way to build the permutations than nesting loops
|
||||||
([0, 1, 0, 0], [0, 0, 0, 1]),
|
let mut rules = HashMap::new();
|
||||||
([0, 1, 0, 1], [0, 0, 1, 1]),
|
for a in 0..elements.len() {
|
||||||
([0, 1, 1, 0], [0, 0, 1, 1]),
|
for b in 0..elements.len() {
|
||||||
([1, 0, 0, 0], [0, 0, 1, 0]),
|
for c in 0..elements.len() {
|
||||||
([1, 0, 0, 1], [0, 0, 1, 1]),
|
for d in 0..elements.len() {
|
||||||
([1, 0, 1, 0], [0, 0, 1, 1]),
|
let input = [elements[a], elements[b], elements[c], elements[d]];
|
||||||
([1, 1, 0, 0], [0, 0, 1, 1]),
|
let in_rule = to_rule_state(&input);
|
||||||
([1, 1, 0, 1], [0, 1, 1, 1]),
|
let out_rule = RuleBuilder::build(&input);
|
||||||
([1, 1, 1, 0], [1, 0, 1, 1]),
|
if in_rule != out_rule {
|
||||||
// Air/Water
|
rules.insert(in_rule, out_rule);
|
||||||
([0, 2, 0, 0], [0, 0, 0, 2]),
|
}
|
||||||
([0, 2, 0, 2], [0, 0, 2, 2]),
|
}
|
||||||
([0, 2, 2, 0], [0, 0, 2, 2]),
|
}
|
||||||
([2, 0, 0, 0], [0, 0, 2, 0]),
|
}
|
||||||
([2, 0, 0, 2], [0, 0, 2, 2]),
|
}
|
||||||
([2, 0, 2, 0], [0, 0, 2, 2]),
|
|
||||||
([2, 2, 0, 0], [0, 0, 2, 2]),
|
|
||||||
([2, 2, 0, 2], [0, 2, 2, 2]),
|
|
||||||
([2, 2, 2, 0], [2, 0, 2, 2]),
|
|
||||||
([0, 2, 2, 2], [2, 0, 2, 2]),
|
|
||||||
([2, 0, 2, 2], [0, 2, 2, 2]),
|
|
||||||
// Air/Sand/Water
|
|
||||||
([0, 1, 0, 2], [0, 0, 2, 1]),
|
|
||||||
([0, 1, 1, 2], [0, 2, 1, 1]),
|
|
||||||
([0, 1, 2, 0], [0, 0, 2, 1]),
|
|
||||||
([0, 1, 2, 1], [2, 0, 1, 1]),
|
|
||||||
([0, 1, 2, 2], [0, 2, 2, 1]),
|
|
||||||
([0, 2, 0, 1], [0, 0, 2, 1]),
|
|
||||||
([0, 2, 1, 0], [0, 0, 1, 2]),
|
|
||||||
([0, 2, 1, 1], [2, 0, 1, 1]),
|
|
||||||
([0, 2, 1, 2], [2, 0, 1, 2]),
|
|
||||||
([0, 2, 2, 1], [2, 0, 2, 1]),
|
|
||||||
([1, 0, 0, 2], [0, 0, 1, 2]),
|
|
||||||
([1, 0, 1, 2], [0, 2, 1, 1]),
|
|
||||||
([1, 0, 2, 0], [0, 0, 1, 2]),
|
|
||||||
([1, 0, 2, 1], [2, 0, 1, 1]),
|
|
||||||
([1, 0, 2, 2], [2, 0, 1, 2]),
|
|
||||||
([1, 1, 0, 2], [0, 2, 1, 1]),
|
|
||||||
([1, 1, 1, 2], [1, 2, 1, 1]),
|
|
||||||
([1, 1, 2, 0], [2, 0, 1, 1]),
|
|
||||||
([1, 1, 2, 1], [2, 1, 1, 1]),
|
|
||||||
([1, 1, 2, 2], [2, 2, 1, 1]),
|
|
||||||
([1, 2, 0, 0], [0, 0, 1, 2]),
|
|
||||||
([1, 2, 0, 1], [0, 2, 1, 1]),
|
|
||||||
([1, 2, 0, 2], [0, 2, 1, 2]),
|
|
||||||
([1, 2, 1, 0], [0, 2, 1, 1]),
|
|
||||||
([1, 2, 1, 2], [2, 2, 1, 1]),
|
|
||||||
([1, 2, 2, 0], [0, 2, 1, 2]),
|
|
||||||
([1, 2, 2, 1], [2, 2, 1, 1]),
|
|
||||||
([1, 2, 2, 2], [2, 2, 1, 2]),
|
|
||||||
([2, 0, 0, 1], [0, 0, 2, 1]),
|
|
||||||
([2, 0, 1, 0], [0, 0, 1, 2]),
|
|
||||||
([2, 0, 1, 1], [0, 2, 1, 1]),
|
|
||||||
([2, 0, 1, 2], [0, 2, 1, 2]),
|
|
||||||
([2, 0, 2, 1], [0, 2, 2, 1]),
|
|
||||||
([2, 1, 0, 0], [0, 0, 2, 1]),
|
|
||||||
([2, 1, 0, 1], [2, 0, 1, 1]),
|
|
||||||
([2, 1, 0, 2], [2, 0, 2, 1]),
|
|
||||||
([2, 1, 1, 0], [2, 0, 1, 1]),
|
|
||||||
([2, 1, 1, 2], [2, 2, 1, 1]),
|
|
||||||
([2, 1, 2, 0], [2, 0, 2, 1]),
|
|
||||||
([2, 1, 2, 1], [2, 2, 1, 1]),
|
|
||||||
([2, 1, 2, 2], [2, 2, 2, 1]),
|
|
||||||
([2, 2, 0, 1], [0, 2, 2, 1]),
|
|
||||||
([2, 2, 1, 0], [2, 0, 1, 2]),
|
|
||||||
],
|
|
||||||
};
|
|
||||||
let rules = rule_config.compile();
|
|
||||||
|
|
||||||
Self { rules }
|
Self { rules }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FallingSandRules {
|
impl FallingSandRules {
|
||||||
pub fn get_result(&self, input_rule: u32) -> u32 {
|
pub fn get_result(&self, input: &[Element; 4]) -> [Element; 4] {
|
||||||
match self.rules.get(&input_rule) {
|
let input_rule = to_rule_state(&input);
|
||||||
|
let output_rule = match self.rules.get(&input_rule) {
|
||||||
Some(&result) => result,
|
Some(&result) => result,
|
||||||
None => input_rule,
|
None => input_rule,
|
||||||
}
|
};
|
||||||
|
from_rule_state(output_rule)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_rule_state(input: (Element, Element, Element, Element)) -> u32 {
|
fn to_rule_state(input: &[Element; 4]) -> u32 {
|
||||||
((input.0 as u32) << 24) + ((input.1 as u32) << 16) + ((input.2 as u32) << 8) + input.3 as u32
|
((input[0] as u32) << 24)
|
||||||
|
+ ((input[1] as u32) << 16)
|
||||||
|
+ ((input[2] as u32) << 8)
|
||||||
|
+ input[3] as u32
|
||||||
|
}
|
||||||
|
|
||||||
|
fn from_rule_state(input: u32) -> [Element; 4] {
|
||||||
|
[
|
||||||
|
Element::from((input >> 24) & 0xFF),
|
||||||
|
Element::from((input >> 16) & 0xFF),
|
||||||
|
Element::from((input >> 8) & 0xFF),
|
||||||
|
Element::from(input & 0xFF),
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,58 @@
|
||||||
|
use bevy::{
|
||||||
|
asset::{Assets, Handle},
|
||||||
|
ecs::system::{Query, Res, ResMut},
|
||||||
|
render::texture::Image,
|
||||||
|
};
|
||||||
|
use rand::Rng;
|
||||||
|
|
||||||
|
use super::{element::Element, rules::FallingSandRules, Chunk};
|
||||||
|
|
||||||
|
pub fn place_sand(mut query: Query<&mut Chunk>) {
|
||||||
|
for mut chunk in &mut query {
|
||||||
|
let frac = chunk.width / 2;
|
||||||
|
let x = (chunk.width - frac) / 2 + rand::thread_rng().gen_range(0..frac);
|
||||||
|
let y = chunk.height - 1;
|
||||||
|
chunk.set_cell(x, y, Element::Sand);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn simulate_chunk(rules: Res<FallingSandRules>, mut query: Query<&mut Chunk>) {
|
||||||
|
for mut chunk in &mut query {
|
||||||
|
chunk.update(&rules);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn update_chunk_texture(
|
||||||
|
mut images: ResMut<Assets<Image>>,
|
||||||
|
mut query: Query<(&mut Chunk, &Handle<Image>)>,
|
||||||
|
) {
|
||||||
|
for (mut chunk, image_handle) in &mut query {
|
||||||
|
if !chunk.dirty_rect.is_dirty() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(image) = images.get_mut(image_handle) {
|
||||||
|
for y in chunk.dirty_rect.range_y() {
|
||||||
|
for x in chunk.dirty_rect.range_x() {
|
||||||
|
let mut colour = (0, 0, 0);
|
||||||
|
if let Some(element) = chunk.get_cell(x, y) {
|
||||||
|
match element {
|
||||||
|
Element::Air => colour = (25, 24, 26),
|
||||||
|
Element::Sand => colour = (255, 216, 102),
|
||||||
|
Element::Water => colour = (120, 220, 232),
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let index = (x + y * chunk.width) * 4;
|
||||||
|
image.data[index] = colour.0;
|
||||||
|
image.data[index + 1] = colour.1;
|
||||||
|
image.data[index + 2] = colour.2;
|
||||||
|
image.data[index + 3] = 255;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
chunk.dirty_rect.reset();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,2 @@
|
||||||
|
pub mod falling_sand;
|
||||||
|
pub mod util;
|
|
@ -1,11 +1,9 @@
|
||||||
mod falling_sand;
|
|
||||||
mod util;
|
|
||||||
|
|
||||||
use bevy::{
|
use bevy::{
|
||||||
diagnostic::{FrameTimeDiagnosticsPlugin, LogDiagnosticsPlugin},
|
diagnostic::{FrameTimeDiagnosticsPlugin, LogDiagnosticsPlugin},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
window::PresentMode,
|
window::PresentMode,
|
||||||
};
|
};
|
||||||
|
use haranae_rs::falling_sand;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let window_plugin = WindowPlugin {
|
let window_plugin = WindowPlugin {
|
||||||
|
|
Loading…
Reference in New Issue