From 9739c0c2f3f01f4624314f202842e156f217a5ce Mon Sep 17 00:00:00 2001 From: kralverde Date: Mon, 14 Oct 2024 17:11:39 -0400 Subject: [PATCH 01/11] remove main cargo.lock --- Cargo.lock | 2312 ----------------- pumpkin-world/src/world_gen/blender.rs | 1 + pumpkin-world/src/world_gen/chunk.rs | 59 + pumpkin-world/src/world_gen/mod.rs | 2 + .../src/world_gen/noise/density/mod.rs | 182 ++ .../src/world_gen/noise/density/noise.rs | 107 + .../src/world_gen/noise/density/offset.rs | 73 + .../src/world_gen/noise/density/unary.rs | 147 ++ pumpkin-world/src/world_gen/noise/mod.rs | 167 ++ pumpkin-world/src/world_gen/noise/perlin.rs | 41 +- 10 files changed, 775 insertions(+), 2316 deletions(-) delete mode 100644 Cargo.lock create mode 100644 pumpkin-world/src/world_gen/blender.rs create mode 100644 pumpkin-world/src/world_gen/chunk.rs create mode 100644 pumpkin-world/src/world_gen/noise/density/mod.rs create mode 100644 pumpkin-world/src/world_gen/noise/density/noise.rs create mode 100644 pumpkin-world/src/world_gen/noise/density/offset.rs create mode 100644 pumpkin-world/src/world_gen/noise/density/unary.rs diff --git a/Cargo.lock b/Cargo.lock deleted file mode 100644 index aabd450e2..000000000 --- a/Cargo.lock +++ /dev/null @@ -1,2312 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "addr2line" -version = "0.24.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" -dependencies = [ - "gimli", -] - -[[package]] -name = "adler2" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" - -[[package]] -name = "aes" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" -dependencies = [ - "cfg-if", - "cipher", - "cpufeatures", -] - -[[package]] -name = "atomic-waker" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" - -[[package]] -name = "autocfg" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" - -[[package]] -name = "backtrace" -version = "0.3.74" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" -dependencies = [ - "addr2line", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", - "windows-targets 0.52.6", -] - -[[package]] -name = "base64" -version = "0.22.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" - -[[package]] -name = "base64ct" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "bitflags" -version = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" - -[[package]] -name = "block-buffer" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" -dependencies = [ - "generic-array", -] - -[[package]] -name = "block-buffer" -version = "0.11.0-rc.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "939c0e62efa052fb0b2db2c0f7c479ad32e364c192c3aab605a7641de265a1a7" -dependencies = [ - "hybrid-array", -] - -[[package]] -name = "bumpalo" -version = "3.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" - -[[package]] -name = "byteorder" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" - -[[package]] -name = "bytes" -version = "1.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" - -[[package]] -name = "cc" -version = "1.1.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b16803a61b81d9eabb7eae2588776c4c1e584b738ede45fdbb4c972cec1e9945" -dependencies = [ - "shlex", -] - -[[package]] -name = "cesu8" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" - -[[package]] -name = "cfb8" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "014c0a0e1ad0dae6a86c082db2f9bd7fe8c2c734227047d0d8b4d4a3a094a1e1" -dependencies = [ - "cipher", -] - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "cfg_aliases" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" - -[[package]] -name = "cipher" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" -dependencies = [ - "crypto-common 0.1.6", - "inout", -] - -[[package]] -name = "colored" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbf2150cce219b664a8a70df7a1f933836724b503f8a413af9365b4dcc4d90b8" -dependencies = [ - "lazy_static", - "windows-sys 0.48.0", -] - -[[package]] -name = "const-oid" -version = "0.9.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" - -[[package]] -name = "convert_case" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca" -dependencies = [ - "unicode-segmentation", -] - -[[package]] -name = "core-foundation" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "core-foundation-sys" -version = "0.8.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" - -[[package]] -name = "cpufeatures" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" -dependencies = [ - "libc", -] - -[[package]] -name = "crc32fast" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "crossbeam" -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.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2" -dependencies = [ - "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]] -name = "crossbeam-queue" -version = "0.3.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" - -[[package]] -name = "crypto-common" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" -dependencies = [ - "generic-array", - "typenum", -] - -[[package]] -name = "crypto-common" -version = "0.2.0-rc.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0b8ce8218c97789f16356e7896b3714f26c2ee1079b79c0b7ae7064bb9089fa" -dependencies = [ - "hybrid-array", -] - -[[package]] -name = "ctrlc" -version = "3.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90eeab0aa92f3f9b4e87f258c72b139c207d251f9cbc1080a0086b86a8870dd3" -dependencies = [ - "nix", - "windows-sys 0.59.0", -] - -[[package]] -name = "der" -version = "0.7.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" -dependencies = [ - "const-oid", - "pem-rfc7468", - "zeroize", -] - -[[package]] -name = "deranged" -version = "0.3.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" -dependencies = [ - "powerfmt", -] - -[[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 = [ - "convert_case", - "proc-macro2", - "quote", - "syn", - "unicode-xid", -] - -[[package]] -name = "digest" -version = "0.10.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" -dependencies = [ - "block-buffer 0.10.4", - "const-oid", - "crypto-common 0.1.6", - "subtle", -] - -[[package]] -name = "digest" -version = "0.11.0-pre.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf2e3d6615d99707295a9673e889bf363a04b2a466bd320c65a72536f7577379" -dependencies = [ - "block-buffer 0.11.0-rc.2", - "crypto-common 0.2.0-rc.1", -] - -[[package]] -name = "either" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" - -[[package]] -name = "equivalent" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" - -[[package]] -name = "fastnbt" -version = "2.5.0" -source = "git+https://github.com/owengage/fastnbt.git#e2a5d8a7001d4f074ae99fd21bb485667934baeb" -dependencies = [ - "byteorder", - "cesu8", - "serde", - "serde_bytes", -] - -[[package]] -name = "fdeflate" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8090f921a24b04994d9929e204f50b498a33ea6ba559ffaa05e04f7ee7fb5ab" -dependencies = [ - "simd-adler32", -] - -[[package]] -name = "flate2" -version = "1.0.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1b589b4dc103969ad3cf85c950899926ec64300a1a46d76c03a6072957036f0" -dependencies = [ - "crc32fast", - "miniz_oxide", -] - -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - -[[package]] -name = "form_urlencoded" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" -dependencies = [ - "percent-encoding", -] - -[[package]] -name = "futures" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" -dependencies = [ - "futures-channel", - "futures-core", - "futures-executor", - "futures-io", - "futures-sink", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-channel" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" -dependencies = [ - "futures-core", - "futures-sink", -] - -[[package]] -name = "futures-core" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" - -[[package]] -name = "futures-executor" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" -dependencies = [ - "futures-core", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-io" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" - -[[package]] -name = "futures-macro" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "futures-sink" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" - -[[package]] -name = "futures-task" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" - -[[package]] -name = "futures-util" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" -dependencies = [ - "futures-channel", - "futures-core", - "futures-io", - "futures-macro", - "futures-sink", - "futures-task", - "memchr", - "pin-project-lite", - "pin-utils", - "slab", -] - -[[package]] -name = "generic-array" -version = "0.14.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" -dependencies = [ - "typenum", - "version_check", -] - -[[package]] -name = "getrandom" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" -dependencies = [ - "cfg-if", - "libc", - "wasi", -] - -[[package]] -name = "gimli" -version = "0.31.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" - -[[package]] -name = "h2" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524e8ac6999421f49a846c2d4411f337e53497d8ec55d67753beffa43c5d9205" -dependencies = [ - "atomic-waker", - "bytes", - "fnv", - "futures-core", - "futures-sink", - "http", - "indexmap", - "slab", - "tokio", - "tokio-util", - "tracing", -] - -[[package]] -name = "hashbrown" -version = "0.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" - -[[package]] -name = "hermit-abi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" - -[[package]] -name = "hmac" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" -dependencies = [ - "digest 0.10.7", -] - -[[package]] -name = "http" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" -dependencies = [ - "bytes", - "fnv", - "itoa", -] - -[[package]] -name = "http-body" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" -dependencies = [ - "bytes", - "http", -] - -[[package]] -name = "http-body-util" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" -dependencies = [ - "bytes", - "futures-util", - "http", - "http-body", - "pin-project-lite", -] - -[[package]] -name = "httparse" -version = "1.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" - -[[package]] -name = "hybrid-array" -version = "0.2.0-rc.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5a41e5b0754cae5aaf7915f1df1147ba8d316fc6e019cfcc00fbaba96d5e030" -dependencies = [ - "typenum", -] - -[[package]] -name = "hyper" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" -dependencies = [ - "bytes", - "futures-channel", - "futures-util", - "h2", - "http", - "http-body", - "httparse", - "itoa", - "pin-project-lite", - "smallvec", - "tokio", - "want", -] - -[[package]] -name = "hyper-rustls" -version = "0.27.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333" -dependencies = [ - "futures-util", - "http", - "hyper", - "hyper-util", - "rustls", - "rustls-pki-types", - "tokio", - "tokio-rustls", - "tower-service", - "webpki-roots", -] - -[[package]] -name = "hyper-util" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" -dependencies = [ - "bytes", - "futures-channel", - "futures-util", - "http", - "http-body", - "hyper", - "pin-project-lite", - "socket2", - "tokio", - "tower-service", - "tracing", -] - -[[package]] -name = "idna" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" -dependencies = [ - "unicode-bidi", - "unicode-normalization", -] - -[[package]] -name = "indexmap" -version = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" -dependencies = [ - "equivalent", - "hashbrown", -] - -[[package]] -name = "inout" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" -dependencies = [ - "generic-array", -] - -[[package]] -name = "ipnet" -version = "2.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" - -[[package]] -name = "itertools" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" -dependencies = [ - "either", -] - -[[package]] -name = "itoa" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" - -[[package]] -name = "js-sys" -version = "0.3.72" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9" -dependencies = [ - "wasm-bindgen", -] - -[[package]] -name = "lazy_static" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" -dependencies = [ - "spin", -] - -[[package]] -name = "libc" -version = "0.2.159" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5" - -[[package]] -name = "libm" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" - -[[package]] -name = "lock_api" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" -dependencies = [ - "autocfg", - "scopeguard", -] - -[[package]] -name = "log" -version = "0.4.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" - -[[package]] -name = "lz4" -version = "1.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d1febb2b4a79ddd1980eede06a8f7902197960aa0383ffcfdd62fe723036725" -dependencies = [ - "lz4-sys", -] - -[[package]] -name = "lz4-sys" -version = "1.11.1+lz4-1.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bd8c0d6c6ed0cd30b3652886bb8711dc4bb01d637a68105a3d5158039b418e6" -dependencies = [ - "cc", - "libc", -] - -[[package]] -name = "md-5" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" -dependencies = [ - "cfg-if", - "digest 0.10.7", -] - -[[package]] -name = "md5" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "490cc448043f947bae3cbee9c203358d62dbee0db12107a74be5c30ccfd09771" - -[[package]] -name = "memchr" -version = "2.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" - -[[package]] -name = "mime" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" - -[[package]] -name = "miniz_oxide" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" -dependencies = [ - "adler2", - "simd-adler32", -] - -[[package]] -name = "mio" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" -dependencies = [ - "hermit-abi", - "libc", - "log", - "wasi", - "windows-sys 0.52.0", -] - -[[package]] -name = "nix" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" -dependencies = [ - "bitflags 2.6.0", - "cfg-if", - "cfg_aliases", - "libc", -] - -[[package]] -name = "noise" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6da45c8333f2e152fc665d78a380be060eb84fad8ca4c9f7ac8ca29216cff0cc" -dependencies = [ - "num-traits", - "rand", - "rand_xorshift", -] - -[[package]] -name = "num-bigint" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" -dependencies = [ - "num-integer", - "num-traits", -] - -[[package]] -name = "num-bigint-dig" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc84195820f291c7697304f3cbdadd1cb7199c0efc917ff5eafd71225c136151" -dependencies = [ - "byteorder", - "lazy_static", - "libm", - "num-integer", - "num-iter", - "num-traits", - "rand", - "smallvec", - "zeroize", -] - -[[package]] -name = "num-conv" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" - -[[package]] -name = "num-derive" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "num-integer" -version = "0.1.46" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" -dependencies = [ - "num-traits", -] - -[[package]] -name = "num-iter" -version = "0.1.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-traits" -version = "0.2.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" -dependencies = [ - "autocfg", - "libm", -] - -[[package]] -name = "num_threads" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9" -dependencies = [ - "libc", -] - -[[package]] -name = "object" -version = "0.36.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e" -dependencies = [ - "memchr", -] - -[[package]] -name = "once_cell" -version = "1.20.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" - -[[package]] -name = "parking_lot" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" -dependencies = [ - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "smallvec", - "windows-targets 0.52.6", -] - -[[package]] -name = "pem-rfc7468" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" -dependencies = [ - "base64ct", -] - -[[package]] -name = "percent-encoding" -version = "2.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" - -[[package]] -name = "pin-project-lite" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" - -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - -[[package]] -name = "pkcs1" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" -dependencies = [ - "der", - "pkcs8", - "spki", -] - -[[package]] -name = "pkcs8" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" -dependencies = [ - "der", - "spki", -] - -[[package]] -name = "png" -version = "0.17.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52f9d46a34a05a6a57566bc2bfae066ef07585a6e3fa30fbbdff5936380623f0" -dependencies = [ - "bitflags 1.3.2", - "crc32fast", - "fdeflate", - "flate2", - "miniz_oxide", -] - -[[package]] -name = "powerfmt" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" - -[[package]] -name = "ppv-lite86" -version = "0.2.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" -dependencies = [ - "zerocopy", -] - -[[package]] -name = "proc-macro2" -version = "1.0.87" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3e4daa0dcf6feba26f985457cdf104d4b4256fc5a09547140f3631bb076b19a" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "pumpkin" -version = "0.1.0-dev" -dependencies = [ - "base64", - "bytes", - "crossbeam", - "ctrlc", - "digest 0.11.0-pre.9", - "hmac", - "itertools", - "log", - "mio", - "num-bigint", - "num-derive", - "num-traits", - "parking_lot", - "png", - "pumpkin-config", - "pumpkin-core", - "pumpkin-entity", - "pumpkin-inventory", - "pumpkin-protocol", - "pumpkin-registry", - "pumpkin-world", - "rand", - "rayon", - "reqwest", - "rsa", - "rsa-der", - "serde", - "serde_json", - "sha1", - "sha2", - "simple_logger", - "thiserror", - "tokio", - "uuid", -] - -[[package]] -name = "pumpkin-config" -version = "0.1.0" -dependencies = [ - "log", - "pumpkin-core", - "serde", - "serde-inline-default", - "toml", -] - -[[package]] -name = "pumpkin-core" -version = "0.1.0" -dependencies = [ - "colored", - "fastnbt", - "md5", - "num-derive", - "num-traits", - "serde", - "uuid", -] - -[[package]] -name = "pumpkin-entity" -version = "0.1.0" - -[[package]] -name = "pumpkin-inventory" -version = "0.1.0" -dependencies = [ - "crossbeam", - "itertools", - "num-derive", - "num-traits", - "parking_lot", - "pumpkin-world", - "thiserror", -] - -[[package]] -name = "pumpkin-macros" -version = "0.1.0" -dependencies = [ - "itertools", - "proc-macro2", - "quote", - "serde", - "serde_json", - "syn", -] - -[[package]] -name = "pumpkin-protocol" -version = "0.1.0" -dependencies = [ - "aes", - "bytes", - "cfb8", - "fastnbt", - "flate2", - "itertools", - "log", - "num-derive", - "num-traits", - "pumpkin-config", - "pumpkin-core", - "pumpkin-macros", - "pumpkin-world", - "serde", - "thiserror", - "uuid", -] - -[[package]] -name = "pumpkin-registry" -version = "0.1.0" -dependencies = [ - "fastnbt", - "pumpkin-core", - "pumpkin-protocol", - "serde", -] - -[[package]] -name = "pumpkin-world" -version = "0.1.0" -dependencies = [ - "derive_more", - "fastnbt", - "flate2", - "futures", - "itertools", - "log", - "lz4", - "noise", - "num-derive", - "num-traits", - "parking_lot", - "pumpkin-core", - "pumpkin-macros", - "rand", - "rayon", - "serde", - "serde_json", - "thiserror", - "tokio", -] - -[[package]] -name = "quinn" -version = "0.11.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c7c5fdde3cdae7203427dc4f0a68fe0ed09833edc525a03456b153b79828684" -dependencies = [ - "bytes", - "pin-project-lite", - "quinn-proto", - "quinn-udp", - "rustc-hash", - "rustls", - "socket2", - "thiserror", - "tokio", - "tracing", -] - -[[package]] -name = "quinn-proto" -version = "0.11.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fadfaed2cd7f389d0161bb73eeb07b7b78f8691047a6f3e73caaeae55310a4a6" -dependencies = [ - "bytes", - "rand", - "ring", - "rustc-hash", - "rustls", - "slab", - "thiserror", - "tinyvec", - "tracing", -] - -[[package]] -name = "quinn-udp" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fe68c2e9e1a1234e218683dbdf9f9dfcb094113c5ac2b938dfcb9bab4c4140b" -dependencies = [ - "libc", - "once_cell", - "socket2", - "tracing", - "windows-sys 0.59.0", -] - -[[package]] -name = "quote" -version = "1.0.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "libc", - "rand_chacha", - "rand_core", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom", -] - -[[package]] -name = "rand_xorshift" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f" -dependencies = [ - "rand_core", -] - -[[package]] -name = "rayon" -version = "1.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" -dependencies = [ - "either", - "rayon-core", -] - -[[package]] -name = "rayon-core" -version = "1.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" -dependencies = [ - "crossbeam-deque", - "crossbeam-utils", -] - -[[package]] -name = "redox_syscall" -version = "0.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" -dependencies = [ - "bitflags 2.6.0", -] - -[[package]] -name = "reqwest" -version = "0.12.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f713147fbe92361e52392c73b8c9e48c04c6625bce969ef54dc901e58e042a7b" -dependencies = [ - "base64", - "bytes", - "futures-core", - "futures-util", - "h2", - "http", - "http-body", - "http-body-util", - "hyper", - "hyper-rustls", - "hyper-util", - "ipnet", - "js-sys", - "log", - "mime", - "once_cell", - "percent-encoding", - "pin-project-lite", - "quinn", - "rustls", - "rustls-pemfile", - "rustls-pki-types", - "serde", - "serde_json", - "serde_urlencoded", - "sync_wrapper", - "system-configuration", - "tokio", - "tokio-rustls", - "tower-service", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "webpki-roots", - "windows-registry", -] - -[[package]] -name = "ring" -version = "0.17.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" -dependencies = [ - "cc", - "cfg-if", - "getrandom", - "libc", - "spin", - "untrusted", - "windows-sys 0.52.0", -] - -[[package]] -name = "rsa" -version = "0.9.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d0e5124fcb30e76a7e79bfee683a2746db83784b86289f6251b54b7950a0dfc" -dependencies = [ - "const-oid", - "digest 0.10.7", - "num-bigint-dig", - "num-integer", - "num-traits", - "pkcs1", - "pkcs8", - "rand_core", - "signature", - "spki", - "subtle", - "zeroize", -] - -[[package]] -name = "rsa-der" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a19473b2de3164677ff38e4309c42448ba8d0fe5ad5fa722e7d278f991859aa6" -dependencies = [ - "simple_asn1", -] - -[[package]] -name = "rustc-demangle" -version = "0.1.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" - -[[package]] -name = "rustc-hash" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152" - -[[package]] -name = "rustls" -version = "0.23.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "415d9944693cb90382053259f89fbb077ea730ad7273047ec63b19bc9b160ba8" -dependencies = [ - "once_cell", - "ring", - "rustls-pki-types", - "rustls-webpki", - "subtle", - "zeroize", -] - -[[package]] -name = "rustls-pemfile" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" -dependencies = [ - "rustls-pki-types", -] - -[[package]] -name = "rustls-pki-types" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e696e35370c65c9c541198af4543ccd580cf17fc25d8e05c5a242b202488c55" - -[[package]] -name = "rustls-webpki" -version = "0.102.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" -dependencies = [ - "ring", - "rustls-pki-types", - "untrusted", -] - -[[package]] -name = "ryu" -version = "1.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" - -[[package]] -name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - -[[package]] -name = "serde" -version = "1.0.210" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde-inline-default" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "484b43bb1114a28d1a574f5682d6079fa4c20e76faaff0cfd048216650e57101" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "serde_bytes" -version = "0.11.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "387cc504cb06bb40a96c8e04e951fe01854cf6bc921053c954e4a606d9675c6a" -dependencies = [ - "serde", -] - -[[package]] -name = "serde_derive" -version = "1.0.210" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "serde_json" -version = "1.0.128" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" -dependencies = [ - "itoa", - "memchr", - "ryu", - "serde", -] - -[[package]] -name = "serde_spanned" -version = "0.6.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" -dependencies = [ - "serde", -] - -[[package]] -name = "serde_urlencoded" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" -dependencies = [ - "form_urlencoded", - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "sha1" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest 0.10.7", -] - -[[package]] -name = "sha2" -version = "0.10.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest 0.10.7", -] - -[[package]] -name = "shlex" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" - -[[package]] -name = "signature" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" -dependencies = [ - "digest 0.10.7", - "rand_core", -] - -[[package]] -name = "simd-adler32" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" - -[[package]] -name = "simple_asn1" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adc4e5204eb1910f40f9cfa375f6f05b68c3abac4b6fd879c8ff5e7ae8a0a085" -dependencies = [ - "num-bigint", - "num-traits", - "thiserror", - "time", -] - -[[package]] -name = "simple_logger" -version = "5.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8c5dfa5e08767553704aa0ffd9d9794d527103c736aba9854773851fd7497eb" -dependencies = [ - "colored", - "log", - "time", - "windows-sys 0.48.0", -] - -[[package]] -name = "slab" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" -dependencies = [ - "autocfg", -] - -[[package]] -name = "smallvec" -version = "1.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" - -[[package]] -name = "socket2" -version = "0.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" -dependencies = [ - "libc", - "windows-sys 0.52.0", -] - -[[package]] -name = "spin" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" - -[[package]] -name = "spki" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" -dependencies = [ - "base64ct", - "der", -] - -[[package]] -name = "subtle" -version = "2.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" - -[[package]] -name = "syn" -version = "2.0.79" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "sync_wrapper" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" -dependencies = [ - "futures-core", -] - -[[package]] -name = "system-configuration" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" -dependencies = [ - "bitflags 2.6.0", - "core-foundation", - "system-configuration-sys", -] - -[[package]] -name = "system-configuration-sys" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "thiserror" -version = "1.0.64" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.64" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "time" -version = "0.3.36" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" -dependencies = [ - "deranged", - "itoa", - "libc", - "num-conv", - "num_threads", - "powerfmt", - "serde", - "time-core", - "time-macros", -] - -[[package]] -name = "time-core" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" - -[[package]] -name = "time-macros" -version = "0.2.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" -dependencies = [ - "num-conv", - "time-core", -] - -[[package]] -name = "tinyvec" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" -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 = "tokio" -version = "1.40.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" -dependencies = [ - "backtrace", - "bytes", - "libc", - "mio", - "pin-project-lite", - "socket2", - "tokio-macros", - "windows-sys 0.52.0", -] - -[[package]] -name = "tokio-macros" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "tokio-rustls" -version = "0.26.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" -dependencies = [ - "rustls", - "rustls-pki-types", - "tokio", -] - -[[package]] -name = "tokio-util" -version = "0.7.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" -dependencies = [ - "bytes", - "futures-core", - "futures-sink", - "pin-project-lite", - "tokio", -] - -[[package]] -name = "toml" -version = "0.8.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" -dependencies = [ - "serde", - "serde_spanned", - "toml_datetime", - "toml_edit", -] - -[[package]] -name = "toml_datetime" -version = "0.6.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" -dependencies = [ - "serde", -] - -[[package]] -name = "toml_edit" -version = "0.22.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" -dependencies = [ - "indexmap", - "serde", - "serde_spanned", - "toml_datetime", - "winnow", -] - -[[package]] -name = "tower-service" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" - -[[package]] -name = "tracing" -version = "0.1.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" -dependencies = [ - "pin-project-lite", - "tracing-core", -] - -[[package]] -name = "tracing-core" -version = "0.1.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" -dependencies = [ - "once_cell", -] - -[[package]] -name = "try-lock" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" - -[[package]] -name = "typenum" -version = "1.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" - -[[package]] -name = "unicode-bidi" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" - -[[package]] -name = "unicode-ident" -version = "1.0.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" - -[[package]] -name = "unicode-normalization" -version = "0.1.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" -dependencies = [ - "tinyvec", -] - -[[package]] -name = "unicode-segmentation" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" - -[[package]] -name = "unicode-xid" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" - -[[package]] -name = "untrusted" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" - -[[package]] -name = "url" -version = "2.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" -dependencies = [ - "form_urlencoded", - "idna", - "percent-encoding", -] - -[[package]] -name = "uuid" -version = "1.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314" -dependencies = [ - "getrandom", - "md-5", - "serde", -] - -[[package]] -name = "version_check" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" - -[[package]] -name = "want" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" -dependencies = [ - "try-lock", -] - -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" - -[[package]] -name = "wasm-bindgen" -version = "0.2.95" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e" -dependencies = [ - "cfg-if", - "once_cell", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.95" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358" -dependencies = [ - "bumpalo", - "log", - "once_cell", - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-futures" -version = "0.4.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc7ec4f8827a71586374db3e87abdb5a2bb3a15afed140221307c3ec06b1f63b" -dependencies = [ - "cfg-if", - "js-sys", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.95" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.95" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.95" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" - -[[package]] -name = "web-sys" -version = "0.3.72" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6488b90108c040df0fe62fa815cbdee25124641df01814dd7282749234c6112" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "webpki-roots" -version = "0.26.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "841c67bff177718f1d4dfefde8d8f0e78f9b6589319ba88312f567fc5841a958" -dependencies = [ - "rustls-pki-types", -] - -[[package]] -name = "windows-registry" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" -dependencies = [ - "windows-result", - "windows-strings", - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-result" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" -dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-strings" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" -dependencies = [ - "windows-result", - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "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.6", -] - -[[package]] -name = "windows-sys" -version = "0.59.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" -dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-targets" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" -dependencies = [ - "windows_aarch64_gnullvm 0.48.5", - "windows_aarch64_msvc 0.48.5", - "windows_i686_gnu 0.48.5", - "windows_i686_msvc 0.48.5", - "windows_x86_64_gnu 0.48.5", - "windows_x86_64_gnullvm 0.48.5", - "windows_x86_64_msvc 0.48.5", -] - -[[package]] -name = "windows-targets" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" -dependencies = [ - "windows_aarch64_gnullvm 0.52.6", - "windows_aarch64_msvc 0.52.6", - "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm", - "windows_i686_msvc 0.52.6", - "windows_x86_64_gnu 0.52.6", - "windows_x86_64_gnullvm 0.52.6", - "windows_x86_64_msvc 0.52.6", -] - -[[package]] -name = "windows_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_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_i686_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" - -[[package]] -name = "windows_i686_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" - -[[package]] -name = "windows_i686_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" - -[[package]] -name = "windows_i686_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" - -[[package]] -name = "winnow" -version = "0.6.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" -dependencies = [ - "memchr", -] - -[[package]] -name = "zerocopy" -version = "0.7.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" -dependencies = [ - "byteorder", - "zerocopy-derive", -] - -[[package]] -name = "zerocopy-derive" -version = "0.7.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "zeroize" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" diff --git a/pumpkin-world/src/world_gen/blender.rs b/pumpkin-world/src/world_gen/blender.rs new file mode 100644 index 000000000..5944201c7 --- /dev/null +++ b/pumpkin-world/src/world_gen/blender.rs @@ -0,0 +1 @@ +pub struct Blender {} diff --git a/pumpkin-world/src/world_gen/chunk.rs b/pumpkin-world/src/world_gen/chunk.rs new file mode 100644 index 000000000..eec758a19 --- /dev/null +++ b/pumpkin-world/src/world_gen/chunk.rs @@ -0,0 +1,59 @@ +use lazy_static::lazy_static; + +use crate::chunk::ChunkData; + +#[derive(Clone)] +pub enum GenerationState { + Empty, + StructureStart, + StructureRef, + Biome, + Noise, + Surface, + Carver, + Feature, + InitLight, + Light, + Spawn, + Full, +} + +pub struct Chunk { + data: ChunkData, + state: GenerationState, +} + +pub struct GenerationShapeConfig { + y_min: i32, + height: i32, + horizontal: i32, + vertical: i32, +} + +//Bits avaliable to encode y-pos +const SIZE_BITS_Y: i32 = 12; +const MAX_HEIGHT: i32 = (1 << SIZE_BITS_Y) - 32; +const MAX_COLUMN_HEIGHT: i32 = (MAX_HEIGHT >> 1) - 1; + +impl GenerationShapeConfig { + fn new(y_min: i32, height: i32, horizontal: i32, vertical: i32) -> Self { + if (y_min + height) > (MAX_COLUMN_HEIGHT + 1) { + panic!("Cannot be higher than max column height"); + } else if height % 16 != 0 { + panic!("Height must be a multiple of 16"); + } else if y_min % 16 != 0 { + panic!("Y min must be a multiple of 16"); + } + Self { + y_min, + height, + horizontal, + vertical, + } + } +} + +lazy_static! { + pub static ref surface_config: GenerationShapeConfig = + GenerationShapeConfig::new(-64, 384, 1, 2); +} diff --git a/pumpkin-world/src/world_gen/mod.rs b/pumpkin-world/src/world_gen/mod.rs index 4712a36f3..e3d37a590 100644 --- a/pumpkin-world/src/world_gen/mod.rs +++ b/pumpkin-world/src/world_gen/mod.rs @@ -1,3 +1,5 @@ +mod blender; +mod chunk; mod generator; mod generic_generator; mod implementation; diff --git a/pumpkin-world/src/world_gen/noise/density/mod.rs b/pumpkin-world/src/world_gen/noise/density/mod.rs new file mode 100644 index 000000000..1351d897c --- /dev/null +++ b/pumpkin-world/src/world_gen/noise/density/mod.rs @@ -0,0 +1,182 @@ +use std::rc::Rc; + +use noise::{InternalNoise, NoiseFunction, ShiftedNoiseFunction}; +use offset::{ShiftAFunction, ShiftBFunction}; +use unary::{ClampFunction, UnaryFunction, UnaryType}; + +use crate::world_gen::blender::Blender; + +mod noise; +mod offset; +mod unary; + +#[derive(Clone)] +pub enum DensityFunction<'a> { + Clamp(ClampFunction<'a>), + Unary(UnaryFunction<'a>), + Noise(NoiseFunction<'a>), + ShiftA(ShiftAFunction<'a>), + ShiftB(ShiftBFunction<'a>), + ShiftedNoise(ShiftedNoiseFunction<'a>), +} + +impl<'a> DensityFunction<'a> { + #[inline] + pub fn sample(&self, pos: &impl NoisePos) -> f64 { + match self { + Self::Clamp(func) => func.sample(pos), + Self::Unary(func) => func.sample(pos), + Self::Noise(func) => func.sample(pos), + Self::ShiftA(func) => func.sample(pos), + Self::ShiftB(func) => func.sample(pos), + Self::ShiftedNoise(func) => func.sample(pos), + } + } + + #[inline] + pub fn apply(&'a self, visitor: &'a impl Visitor) -> DensityFunction<'a> { + match self { + Self::Clamp(func) => func.apply(visitor), + Self::Unary(func) => func.apply(visitor), + Self::Noise(func) => func.apply(visitor), + Self::ShiftA(func) => func.apply(visitor), + Self::ShiftB(func) => func.apply(visitor), + Self::ShiftedNoise(func) => func.apply(visitor), + } + } + + #[inline] + pub fn fill(&self, densities: &[f64], applier: &impl Applier) -> Vec { + match self { + Self::Clamp(func) => func.fill(densities, applier), + Self::Unary(func) => func.fill(densities, applier), + Self::Noise(func) => func.fill(densities, applier), + Self::ShiftA(func) => func.fill(densities, applier), + Self::ShiftB(func) => func.fill(densities, applier), + Self::ShiftedNoise(func) => func.fill(densities, applier), + } + } + + #[inline] + pub fn max(&self) -> f64 { + match self { + Self::Clamp(func) => func.max(), + Self::Unary(func) => func.max(), + Self::Noise(func) => func.max(), + Self::ShiftA(func) => func.max(), + Self::ShiftB(func) => func.max(), + Self::ShiftedNoise(func) => func.max(), + } + } + + #[inline] + pub fn min(&self) -> f64 { + match self { + Self::Clamp(func) => func.min(), + Self::Unary(func) => func.min(), + Self::Noise(func) => func.min(), + Self::ShiftA(func) => func.min(), + Self::ShiftB(func) => func.min(), + Self::ShiftedNoise(func) => func.min(), + } + } + + pub fn clamp(&self, max: f64, min: f64) -> Self { + Self::Clamp(ClampFunction { + input: Rc::new(self.clone()), + min, + max, + }) + } + + pub fn abs(&self) -> Self { + Self::Unary(UnaryFunction::create(UnaryType::Abs, Rc::new(self.clone()))) + } + + pub fn square(&self) -> Self { + Self::Unary(UnaryFunction::create( + UnaryType::Square, + Rc::new(self.clone()), + )) + } + + pub fn cube(&self) -> Self { + Self::Unary(UnaryFunction::create( + UnaryType::Cube, + Rc::new(self.clone()), + )) + } + + pub fn half_negative(&self) -> Self { + Self::Unary(UnaryFunction::create( + UnaryType::HalfNeg, + Rc::new(self.clone()), + )) + } + + pub fn quarter_negative(&self) -> Self { + Self::Unary(UnaryFunction::create( + UnaryType::QuartNeg, + Rc::new(self.clone()), + )) + } + + pub fn squeeze(&self) -> Self { + Self::Unary(UnaryFunction::create( + UnaryType::Squeeze, + Rc::new(self.clone()), + )) + } +} + +pub trait NoisePos { + fn x(&self) -> i32; + fn y(&self) -> i32; + fn z(&self) -> i32; + + fn get_blender(&self) -> &Blender { + &Blender {} + } +} + +pub trait Applier { + fn at(&self, index: i32) -> impl NoisePos; + + fn fill<'a>(&self, densities: &[f64], function: &impl DensityFunctionImpl<'a>) -> Vec; +} + +pub trait Visitor { + fn apply(&self, function: &DensityFunction) -> DensityFunction; + + fn apply_internal_noise<'a>(&self, function: Rc>) -> Rc> { + function.clone() + } +} + +pub trait DensityFunctionImpl<'a> { + fn sample(&self, pos: &impl NoisePos) -> f64; + + fn fill(&self, densities: &[f64], applier: &impl Applier) -> Vec; + + fn apply(&'a self, visitor: &'a impl Visitor) -> DensityFunction<'a>; + + fn min(&self) -> f64; + + fn max(&self) -> f64; +} + +pub trait UnaryDensityFunction<'a>: DensityFunctionImpl<'a> { + fn input(&self) -> &DensityFunction; + + fn apply_density(&self, density: f64) -> f64; +} + +pub trait OffsetDensityFunction<'a>: DensityFunctionImpl<'a> { + fn offset_noise(&self) -> &InternalNoise<'a>; + + fn sample_3d(&self, x: f64, y: f64, z: f64) -> f64 { + self.offset_noise() + .sample(x * 0.25f64, y * 0.25f64, z * 0.25f64) + * 4f64 + } +} diff --git a/pumpkin-world/src/world_gen/noise/density/noise.rs b/pumpkin-world/src/world_gen/noise/density/noise.rs new file mode 100644 index 000000000..34131cf57 --- /dev/null +++ b/pumpkin-world/src/world_gen/noise/density/noise.rs @@ -0,0 +1,107 @@ +use std::rc::Rc; + +use crate::world_gen::noise::perlin::{DoublePerlinNoiseParameters, DoublePerlinNoiseSampler}; + +use super::{DensityFunction, DensityFunctionImpl}; + +pub(crate) struct InternalNoise<'a> { + data: DoublePerlinNoiseParameters<'a>, + sampler: Option, +} + +impl<'a> InternalNoise<'a> { + pub(crate) fn sample(&self, x: f64, y: f64, z: f64) -> f64 { + match &self.sampler { + Some(sampler) => sampler.sample(x, y, z), + None => 0f64, + } + } + + pub(crate) fn max_value(&self) -> f64 { + match &self.sampler { + Some(sampler) => sampler.max_value(), + None => 2f64, + } + } +} + +#[derive(Clone)] +pub struct NoiseFunction<'a> { + noise: Rc>, + xz_scale: f64, + y_scale: f64, +} + +impl<'a> DensityFunctionImpl<'a> for NoiseFunction<'a> { + fn sample(&self, pos: &impl super::NoisePos) -> f64 { + self.noise.sample( + pos.x() as f64 * self.xz_scale, + pos.y() as f64 * self.y_scale, + pos.z() as f64 * self.xz_scale, + ) + } + + fn fill(&self, densities: &[f64], applier: &impl super::Applier) -> Vec { + applier.fill(densities, self) + } + + fn apply(&self, visitor: &'a impl super::Visitor) -> super::DensityFunction<'a> { + visitor.apply(&super::DensityFunction::Noise(self.clone())) + } + + fn max(&self) -> f64 { + self.noise.max_value() + } + + fn min(&self) -> f64 { + -self.max() + } +} + +#[derive(Clone)] +pub struct ShiftedNoiseFunction<'a> { + shift_x: Rc>, + shift_y: Rc>, + shift_z: Rc>, + noise: Rc>, + xz_scale: f64, + y_scale: f64, +} + +impl<'a> DensityFunctionImpl<'a> for ShiftedNoiseFunction<'a> { + fn sample(&self, pos: &impl super::NoisePos) -> f64 { + let d = pos.x() as f64 * self.xz_scale + self.shift_x.sample(pos); + let e = pos.y() as f64 * self.y_scale + self.shift_y.sample(pos); + let f = pos.z() as f64 * self.xz_scale + self.shift_z.sample(pos); + + self.noise.sample(d, e, f) + } + + fn fill(&self, densities: &[f64], applier: &impl super::Applier) -> Vec { + applier.fill(densities, self) + } + + fn apply(&'a self, visitor: &'a impl super::Visitor) -> DensityFunction<'a> { + let new_x = self.shift_x.apply(visitor); + let new_y = self.shift_y.apply(visitor); + let new_z = self.shift_z.apply(visitor); + let new_noise = visitor.apply_internal_noise(self.noise.clone()); + + DensityFunction::ShiftedNoise(ShiftedNoiseFunction { + shift_x: Rc::new(new_x), + shift_y: Rc::new(new_y), + shift_z: Rc::new(new_z), + xz_scale: self.xz_scale, + y_scale: self.y_scale, + noise: new_noise, + }) + } + + fn max(&self) -> f64 { + self.noise.max_value() + } + + fn min(&self) -> f64 { + -self.max() + } +} diff --git a/pumpkin-world/src/world_gen/noise/density/offset.rs b/pumpkin-world/src/world_gen/noise/density/offset.rs new file mode 100644 index 000000000..26e16cd84 --- /dev/null +++ b/pumpkin-world/src/world_gen/noise/density/offset.rs @@ -0,0 +1,73 @@ +use std::rc::Rc; + +use super::{noise::InternalNoise, DensityFunction, DensityFunctionImpl, OffsetDensityFunction}; + +#[derive(Clone)] +pub struct ShiftAFunction<'a> { + offset: Rc>, +} + +impl<'a> OffsetDensityFunction<'a> for ShiftAFunction<'a> { + fn offset_noise(&self) -> &InternalNoise<'a> { + &self.offset + } +} + +impl<'a> DensityFunctionImpl<'a> for ShiftAFunction<'a> { + fn sample(&self, pos: &impl super::NoisePos) -> f64 { + self.sample_3d(pos.x() as f64, 0f64, pos.z() as f64) + } + + fn apply(&'a self, visitor: &'a impl super::Visitor) -> super::DensityFunction<'a> { + visitor.apply(&DensityFunction::ShiftA(ShiftAFunction { + offset: visitor.apply_internal_noise(self.offset.clone()), + })) + } + + fn fill(&self, densities: &[f64], applier: &impl super::Applier) -> Vec { + applier.fill(densities, self) + } + + fn max(&self) -> f64 { + self.offset_noise().max_value() * 4f64 + } + + fn min(&self) -> f64 { + -self.max() + } +} + +#[derive(Clone)] +pub struct ShiftBFunction<'a> { + offset: Rc>, +} + +impl<'a> OffsetDensityFunction<'a> for ShiftBFunction<'a> { + fn offset_noise(&self) -> &InternalNoise<'a> { + &self.offset + } +} + +impl<'a> DensityFunctionImpl<'a> for ShiftBFunction<'a> { + fn sample(&self, pos: &impl super::NoisePos) -> f64 { + self.sample_3d(pos.z() as f64, pos.x() as f64, 0f64) + } + + fn apply(&'a self, visitor: &'a impl super::Visitor) -> super::DensityFunction<'a> { + visitor.apply(&DensityFunction::ShiftB(ShiftBFunction { + offset: visitor.apply_internal_noise(self.offset.clone()), + })) + } + + fn fill(&self, densities: &[f64], applier: &impl super::Applier) -> Vec { + applier.fill(densities, self) + } + + fn max(&self) -> f64 { + self.offset_noise().max_value() * 4f64 + } + + fn min(&self) -> f64 { + -self.max() + } +} diff --git a/pumpkin-world/src/world_gen/noise/density/unary.rs b/pumpkin-world/src/world_gen/noise/density/unary.rs new file mode 100644 index 000000000..17fa123b9 --- /dev/null +++ b/pumpkin-world/src/world_gen/noise/density/unary.rs @@ -0,0 +1,147 @@ +use std::rc::Rc; + +use super::{DensityFunction, DensityFunctionImpl, UnaryDensityFunction}; + +#[derive(Clone)] +pub struct ClampFunction<'a> { + pub(crate) input: Rc>, + pub(crate) min: f64, + pub(crate) max: f64, +} + +impl<'a> UnaryDensityFunction<'a> for ClampFunction<'a> { + fn input(&self) -> &DensityFunction { + &self.input + } + + fn apply_density(&self, density: f64) -> f64 { + density.clamp(self.min, self.max) + } +} + +impl<'a> DensityFunctionImpl<'a> for ClampFunction<'a> { + fn apply(&'a self, visitor: &'a impl super::Visitor) -> DensityFunction<'a> { + DensityFunction::Clamp(ClampFunction { + input: Rc::new(self.input().apply(visitor)), + min: self.min, + max: self.max, + }) + } + + fn sample(&self, pos: &impl super::NoisePos) -> f64 { + self.apply_density(self.input().sample(pos)) + } + + fn fill(&self, densities: &[f64], applier: &impl super::Applier) -> Vec { + let densities = self.input().fill(densities, applier); + densities.iter().map(|x| self.apply_density(*x)).collect() + } + + fn min(&self) -> f64 { + self.min + } + + fn max(&self) -> f64 { + self.max + } +} + +#[derive(Clone)] +pub(crate) enum UnaryType { + Abs, + Square, + Cube, + HalfNeg, + QuartNeg, + Squeeze, +} + +#[derive(Clone)] +pub struct UnaryFunction<'a> { + action: UnaryType, + input: Rc>, + min: f64, + max: f64, +} + +impl<'a> UnaryFunction<'a> { + pub(crate) fn create(action: UnaryType, input: Rc>) -> UnaryFunction { + let base_min = input.min(); + let new_min = Self::internal_apply(&action, base_min); + let new_max = Self::internal_apply(&action, input.max()); + match action { + UnaryType::Abs | UnaryType::Square => Self { + action, + input, + min: f64::max(0f64, base_min), + max: f64::max(new_min, new_max), + }, + _ => Self { + action, + input, + min: new_min, + max: new_max, + }, + } + } + + fn internal_apply(action: &UnaryType, density: f64) -> f64 { + match action { + UnaryType::Abs => density.abs(), + UnaryType::Square => density * density, + UnaryType::Cube => density * density * density, + UnaryType::HalfNeg => { + if density > 0f64 { + density + } else { + density * 0.5f64 + } + } + UnaryType::QuartNeg => { + if density > 0f64 { + density + } else { + density * 0.25f64 + } + } + UnaryType::Squeeze => { + let d = density.clamp(-1f64, 1f64); + d / 2f64 - d * d * d / 24f64 + } + } + } +} + +impl<'a> UnaryDensityFunction<'a> for UnaryFunction<'a> { + fn apply_density(&self, density: f64) -> f64 { + Self::internal_apply(&self.action, density) + } + + fn input(&self) -> &DensityFunction { + &self.input + } +} + +impl<'a> DensityFunctionImpl<'a> for UnaryFunction<'a> { + fn sample(&self, pos: &impl super::NoisePos) -> f64 { + self.apply_density(self.input().sample(pos)) + } + + fn fill(&self, densities: &[f64], applier: &impl super::Applier) -> Vec { + let densities = self.input().fill(densities, applier); + densities.iter().map(|x| self.apply_density(*x)).collect() + } + + fn apply(&'a self, visitor: &'a impl super::Visitor) -> DensityFunction<'a> { + let raw = Self::create(self.action.clone(), Rc::new(self.input().apply(visitor))); + DensityFunction::Unary(raw) + } + + fn max(&self) -> f64 { + self.max + } + + fn min(&self) -> f64 { + self.min + } +} diff --git a/pumpkin-world/src/world_gen/noise/mod.rs b/pumpkin-world/src/world_gen/noise/mod.rs index ea5d51196..c5a8de241 100644 --- a/pumpkin-world/src/world_gen/noise/mod.rs +++ b/pumpkin-world/src/world_gen/noise/mod.rs @@ -1,7 +1,174 @@ #![allow(dead_code)] +mod density; mod perlin; mod simplex; +pub mod builtin_noise_params { + use lazy_static::lazy_static; + + use super::perlin::DoublePerlinNoiseParameters; + lazy_static! { + pub static ref temperature: DoublePerlinNoiseParameters<'static> = + DoublePerlinNoiseParameters::new(-10, &[1.5f64, 0f64, 1f64, 0f64, 0f64, 0f64,],); + pub static ref vegetation: DoublePerlinNoiseParameters<'static> = + DoublePerlinNoiseParameters::new(-8, &[1f64, 1f64, 0f64, 0f64, 0f64, 0f64,],); + pub static ref continentalness: DoublePerlinNoiseParameters<'static> = + DoublePerlinNoiseParameters::new( + -9, + &[1f64, 1f64, 2f64, 2f64, 2f64, 1f64, 1f64, 1f64, 1f64,], + ); + pub static ref erosion: DoublePerlinNoiseParameters<'static> = + DoublePerlinNoiseParameters::new(-9, &[1f64, 1f64, 0f64, 1f64, 1f64,],); + pub static ref temperature_large: DoublePerlinNoiseParameters<'static> = + DoublePerlinNoiseParameters::new(-12, &[1.5f64, 0f64, 1f64, 0f64, 0f64, 0f64,],); + pub static ref vegetation_large: DoublePerlinNoiseParameters<'static> = + DoublePerlinNoiseParameters::new(-10, &[1f64, 1f64, 0f64, 0f64, 0f64, 0f64,],); + pub static ref continentalness_large: DoublePerlinNoiseParameters<'static> = + DoublePerlinNoiseParameters::new( + -11, + &[1f64, 1f64, 2f64, 2f64, 2f64, 1f64, 1f64, 1f64, 1f64,], + ); + pub static ref erosion_large: DoublePerlinNoiseParameters<'static> = + DoublePerlinNoiseParameters::new(-11, &[1f64, 1f64, 0f64, 1f64, 1f64,],); + pub static ref ridge: DoublePerlinNoiseParameters<'static> = + DoublePerlinNoiseParameters::new(-7, &[1f64, 2f64, 1f64, 0f64, 0f64, 0f64],); + pub static ref offset: DoublePerlinNoiseParameters<'static> = + DoublePerlinNoiseParameters::new(-3, &[1f64; 4],); + pub static ref aquifer_barrier: DoublePerlinNoiseParameters<'static> = + DoublePerlinNoiseParameters::new(-3, &[1f64,],); + pub static ref aquifer_barrier_floodedness: DoublePerlinNoiseParameters<'static> = + DoublePerlinNoiseParameters::new(-7, &[1f64,],); + pub static ref aquifer_lava: DoublePerlinNoiseParameters<'static> = + DoublePerlinNoiseParameters::new(-1, &[1f64,],); + pub static ref aquifer_fluid_level_spread: DoublePerlinNoiseParameters<'static> = + DoublePerlinNoiseParameters::new(-5, &[1f64,],); + pub static ref pillar: DoublePerlinNoiseParameters<'static> = + DoublePerlinNoiseParameters::new(-7, &[1f64; 2],); + pub static ref pillar_rareness: DoublePerlinNoiseParameters<'static> = + DoublePerlinNoiseParameters::new(-8, &[1f64,],); + pub static ref pillar_thickness: DoublePerlinNoiseParameters<'static> = + DoublePerlinNoiseParameters::new(-8, &[1f64,],); + pub static ref spaghetti_2d: DoublePerlinNoiseParameters<'static> = + DoublePerlinNoiseParameters::new(-7, &[1f64,],); + pub static ref spaghetti_2d_elevation: DoublePerlinNoiseParameters<'static> = + DoublePerlinNoiseParameters::new(-8, &[1f64,],); + pub static ref spaghetti_2d_modulator: DoublePerlinNoiseParameters<'static> = + DoublePerlinNoiseParameters::new(-11, &[1f64,],); + pub static ref spaghetti_2d_thickness: DoublePerlinNoiseParameters<'static> = + DoublePerlinNoiseParameters::new(-11, &[1f64,],); + pub static ref spaghetti_3d_1: DoublePerlinNoiseParameters<'static> = + DoublePerlinNoiseParameters::new(-7, &[1f64,],); + pub static ref spaghetti_3d_2: DoublePerlinNoiseParameters<'static> = + DoublePerlinNoiseParameters::new(-7, &[1f64,],); + pub static ref spaghetti_3d_rarity: DoublePerlinNoiseParameters<'static> = + DoublePerlinNoiseParameters::new(-11, &[1f64,],); + pub static ref spaghetti_3d_thickness: DoublePerlinNoiseParameters<'static> = + DoublePerlinNoiseParameters::new(-8, &[1f64,],); + pub static ref spaghetti_roughness: DoublePerlinNoiseParameters<'static> = + DoublePerlinNoiseParameters::new(-5, &[1f64,],); + pub static ref spaghetti_roughness_modulator: DoublePerlinNoiseParameters<'static> = + DoublePerlinNoiseParameters::new(-8, &[1f64,],); + pub static ref cave_entrance: DoublePerlinNoiseParameters<'static> = + DoublePerlinNoiseParameters::new(-7, &[0.4f64, 0.5f64, 1f64],); + pub static ref cave_layer: DoublePerlinNoiseParameters<'static> = + DoublePerlinNoiseParameters::new(-8, &[1f64,],); + pub static ref cave_cheese: DoublePerlinNoiseParameters<'static> = + DoublePerlinNoiseParameters::new( + -8, + &[0.5f64, 1f64, 2f64, 1f64, 2f64, 1f64, 0f64, 2f64, 0f64,], + ); + pub static ref ore_veininess: DoublePerlinNoiseParameters<'static> = + DoublePerlinNoiseParameters::new(-8, &[1f64,],); + pub static ref ore_vein_a: DoublePerlinNoiseParameters<'static> = + DoublePerlinNoiseParameters::new(-7, &[1f64,],); + pub static ref ore_vein_b: DoublePerlinNoiseParameters<'static> = + DoublePerlinNoiseParameters::new(-7, &[1f64,],); + pub static ref ore_gap: DoublePerlinNoiseParameters<'static> = + DoublePerlinNoiseParameters::new(-5, &[1f64,],); + pub static ref noodle: DoublePerlinNoiseParameters<'static> = + DoublePerlinNoiseParameters::new(-8, &[1f64,],); + pub static ref noodle_thickness: DoublePerlinNoiseParameters<'static> = + DoublePerlinNoiseParameters::new(-8, &[1f64,],); + pub static ref noodle_ridge_a: DoublePerlinNoiseParameters<'static> = + DoublePerlinNoiseParameters::new(-7, &[1f64,],); + pub static ref noodle_ridge_b: DoublePerlinNoiseParameters<'static> = + DoublePerlinNoiseParameters::new(-7, &[1f64,],); + pub static ref jagged: DoublePerlinNoiseParameters<'static> = + DoublePerlinNoiseParameters::new(-16, &[1f64; 16],); + pub static ref surface: DoublePerlinNoiseParameters<'static> = + DoublePerlinNoiseParameters::new(-6, &[1f64; 3],); + pub static ref surface_secondary: DoublePerlinNoiseParameters<'static> = + DoublePerlinNoiseParameters::new(-6, &[1f64, 1f64, 0f64, 1f64,],); + pub static ref clay_bands_offset: DoublePerlinNoiseParameters<'static> = + DoublePerlinNoiseParameters::new(-8, &[1f64,],); + pub static ref badlands_pillar: DoublePerlinNoiseParameters<'static> = + DoublePerlinNoiseParameters::new(-2, &[1f64; 4],); + pub static ref badlands_pillar_roof: DoublePerlinNoiseParameters<'static> = + DoublePerlinNoiseParameters::new(-8, &[1f64,],); + pub static ref badlands_surface: DoublePerlinNoiseParameters<'static> = + DoublePerlinNoiseParameters::new(-6, &[1f64; 3],); + pub static ref iceberg_pillar: DoublePerlinNoiseParameters<'static> = + DoublePerlinNoiseParameters::new(-6, &[1f64; 4],); + pub static ref iceberg_pillar_roof: DoublePerlinNoiseParameters<'static> = + DoublePerlinNoiseParameters::new(-3, &[1f64,],); + pub static ref iceberg_surface: DoublePerlinNoiseParameters<'static> = + DoublePerlinNoiseParameters::new(-6, &[1f64; 3],); + pub static ref surface_swamp: DoublePerlinNoiseParameters<'static> = + DoublePerlinNoiseParameters::new(-2, &[1f64,],); + pub static ref calcite: DoublePerlinNoiseParameters<'static> = + DoublePerlinNoiseParameters::new(-9, &[1f64; 4],); + pub static ref gravel: DoublePerlinNoiseParameters<'static> = + DoublePerlinNoiseParameters::new(-8, &[1f64; 4],); + pub static ref powder_snow: DoublePerlinNoiseParameters<'static> = + DoublePerlinNoiseParameters::new(-6, &[1f64; 4],); + pub static ref packed_ice: DoublePerlinNoiseParameters<'static> = + DoublePerlinNoiseParameters::new(-7, &[1f64; 4],); + pub static ref ice: DoublePerlinNoiseParameters<'static> = + DoublePerlinNoiseParameters::new(-4, &[1f64; 4],); + pub static ref soul_sand_layer: DoublePerlinNoiseParameters<'static> = + DoublePerlinNoiseParameters::new( + -8, + &[ + 1f64, + 1f64, + 1f64, + 1f64, + 0f64, + 0f64, + 0f64, + 0f64, + 0.013333333333333334f64, + ], + ); + pub static ref gravel_layer: DoublePerlinNoiseParameters<'static> = + DoublePerlinNoiseParameters::new( + -8, + &[ + 1f64, + 1f64, + 1f64, + 1f64, + 0f64, + 0f64, + 0f64, + 0f64, + 0.013333333333333334f64, + ], + ); + pub static ref patch: DoublePerlinNoiseParameters<'static> = + DoublePerlinNoiseParameters::new( + -5, + &[1f64, 0f64, 0f64, 0f64, 0f64, 0.013333333333333334f64,], + ); + pub static ref netherrack: DoublePerlinNoiseParameters<'static> = + DoublePerlinNoiseParameters::new(-3, &[1f64, 0f64, 0f64, 0.35f64,],); + pub static ref nether_wart: DoublePerlinNoiseParameters<'static> = + DoublePerlinNoiseParameters::new(-3, &[1f64, 0f64, 0f64, 0.9f64,],); + pub static ref nether_state_selector: DoublePerlinNoiseParameters<'static> = + DoublePerlinNoiseParameters::new(-4, &[1f64,],); + } +} + pub fn lerp(delta: f64, start: f64, end: f64) -> f64 { start + delta * (end - start) } diff --git a/pumpkin-world/src/world_gen/noise/perlin.rs b/pumpkin-world/src/world_gen/noise/perlin.rs index a96b1fc6c..e30f6bf00 100644 --- a/pumpkin-world/src/world_gen/noise/perlin.rs +++ b/pumpkin-world/src/world_gen/noise/perlin.rs @@ -286,6 +286,20 @@ impl OctavePerlinNoiseSampler { } } +pub struct DoublePerlinNoiseParameters<'a> { + first_octave: i32, + amplitudes: &'a [f64], +} + +impl<'a> DoublePerlinNoiseParameters<'a> { + pub fn new(first_octave: i32, amplitudes: &'a [f64]) -> Self { + Self { + first_octave, + amplitudes, + } + } +} + pub struct DoublePerlinNoiseSampler { first_sampler: OctavePerlinNoiseSampler, second_sampler: OctavePerlinNoiseSampler, @@ -298,7 +312,14 @@ impl DoublePerlinNoiseSampler { 0.1f64 * (1f64 + 1f64 / (octaves + 1) as f64) } - pub fn new(rand: &mut RandomGenerator, first_octave: i32, amplitudes: &[f64]) -> Self { + pub fn max_value(&self) -> f64 { + self.max_value + } + + pub fn new(rand: &mut RandomGenerator, parameters: &DoublePerlinNoiseParameters) -> Self { + let first_octave = parameters.first_octave; + let amplitudes = parameters.amplitudes; + let first_sampler = OctavePerlinNoiseSampler::new(rand, first_octave, amplitudes); let second_sampler = OctavePerlinNoiseSampler::new(rand, first_octave, amplitudes); @@ -336,7 +357,9 @@ impl DoublePerlinNoiseSampler { mod double_perlin_noise_sampler_test { use pumpkin_core::random::{legacy_rand::LegacyRand, xoroshiro128::Xoroshiro, RandomImpl}; - use crate::world_gen::noise::perlin::{DoublePerlinNoiseSampler, RandomGenerator}; + use crate::world_gen::noise::perlin::{ + DoublePerlinNoiseParameters, DoublePerlinNoiseSampler, RandomGenerator, + }; #[test] fn sample_legacy() { @@ -344,7 +367,11 @@ mod double_perlin_noise_sampler_test { assert_eq!(rand.next_i32(), -1302745855); let mut rand_gen = RandomGenerator::Legacy(rand); - let sampler = DoublePerlinNoiseSampler::new(&mut rand_gen, 0, &[4f64]); + let params = DoublePerlinNoiseParameters { + first_octave: 0, + amplitudes: &[4f64], + }; + let sampler = DoublePerlinNoiseSampler::new(&mut rand_gen, ¶ms); let values = [ ( @@ -440,7 +467,13 @@ mod double_perlin_noise_sampler_test { assert_eq!(rand.next_i32(), -1678727252); let mut rand_gen = RandomGenerator::Xoroshiro(rand); - let sampler = DoublePerlinNoiseSampler::new(&mut rand_gen, 1, &[2f64, 4f64]); + + let params = DoublePerlinNoiseParameters { + first_octave: 1, + amplitudes: &[2f64, 4f64], + }; + + let sampler = DoublePerlinNoiseSampler::new(&mut rand_gen, ¶ms); let values = [ ( From f98df7144d9dc71c1a21fdae34dd37dbf170aadb Mon Sep 17 00:00:00 2001 From: kralverde Date: Wed, 18 Sep 2024 19:13:48 -0400 Subject: [PATCH 02/11] add noise generation and default overworld noises --- pumpkin-core/src/random/mod.rs | 11 + pumpkin-world/src/world_gen/blender.rs | 8 + pumpkin-world/src/world_gen/chunk.rs | 7 +- .../world_gen/implementation/overworld/mod.rs | 1 + .../overworld/terrain_params.rs | 552 ++++++++++++++++++ .../src/world_gen/noise/density/blend.rs | 94 +++ .../src/world_gen/noise/density/math.rs | 258 ++++++++ .../src/world_gen/noise/density/mod.rs | 406 ++++++++++++- .../src/world_gen/noise/density/noise.rs | 250 +++++++- .../src/world_gen/noise/density/offset.rs | 18 +- .../src/world_gen/noise/density/spline.rs | 293 ++++++++++ .../src/world_gen/noise/density/unary.rs | 12 +- pumpkin-world/src/world_gen/noise/mod.rs | 327 ++++++----- pumpkin-world/src/world_gen/noise/perlin.rs | 50 +- 14 files changed, 2106 insertions(+), 181 deletions(-) create mode 100644 pumpkin-world/src/world_gen/implementation/overworld/terrain_params.rs create mode 100644 pumpkin-world/src/world_gen/noise/density/blend.rs create mode 100644 pumpkin-world/src/world_gen/noise/density/math.rs create mode 100644 pumpkin-world/src/world_gen/noise/density/spline.rs diff --git a/pumpkin-core/src/random/mod.rs b/pumpkin-core/src/random/mod.rs index d0200ebc4..c87372130 100644 --- a/pumpkin-core/src/random/mod.rs +++ b/pumpkin-core/src/random/mod.rs @@ -8,6 +8,7 @@ pub mod xoroshiro128; pub enum RandomGenerator { Xoroshiro(Xoroshiro), Legacy(LegacyRand), + LegacyXoroshiro(Xoroshiro), } impl RandomGenerator { @@ -15,6 +16,7 @@ impl RandomGenerator { pub fn split(&mut self) -> Self { match self { Self::Xoroshiro(rand) => Self::Xoroshiro(rand.split()), + Self::LegacyXoroshiro(rand) => Self::LegacyXoroshiro(rand.split()), Self::Legacy(rand) => Self::Legacy(rand.split()), } } @@ -23,6 +25,7 @@ impl RandomGenerator { pub fn next_splitter(&mut self) -> RandomDeriver { match self { Self::Xoroshiro(rand) => RandomDeriver::Xoroshiro(rand.next_splitter()), + Self::LegacyXoroshiro(rand) => RandomDeriver::Xoroshiro(rand.next_splitter()), Self::Legacy(rand) => RandomDeriver::Legacy(rand.next_splitter()), } } @@ -31,6 +34,7 @@ impl RandomGenerator { pub fn next(&mut self, bits: u64) -> u64 { match self { Self::Xoroshiro(rand) => rand.next(bits), + Self::LegacyXoroshiro(rand) => rand.next(bits), Self::Legacy(rand) => rand.next(bits), } } @@ -39,6 +43,7 @@ impl RandomGenerator { pub fn next_i32(&mut self) -> i32 { match self { Self::Xoroshiro(rand) => rand.next_i32(), + Self::LegacyXoroshiro(rand) => rand.next_i32(), Self::Legacy(rand) => rand.next_i32(), } } @@ -47,6 +52,7 @@ impl RandomGenerator { pub fn next_bounded_i32(&mut self, bound: i32) -> i32 { match self { Self::Xoroshiro(rand) => rand.next_bounded_i32(bound), + Self::LegacyXoroshiro(rand) => rand.next_bounded_i32(bound), Self::Legacy(rand) => rand.next_bounded_i32(bound), } } @@ -60,6 +66,7 @@ impl RandomGenerator { pub fn next_i64(&mut self) -> i64 { match self { Self::Xoroshiro(rand) => rand.next_i64(), + Self::LegacyXoroshiro(rand) => rand.next_i64(), Self::Legacy(rand) => rand.next_i64(), } } @@ -68,6 +75,7 @@ impl RandomGenerator { pub fn next_bool(&mut self) -> bool { match self { Self::Xoroshiro(rand) => rand.next_bool(), + Self::LegacyXoroshiro(rand) => rand.next_bool(), Self::Legacy(rand) => rand.next_bool(), } } @@ -76,6 +84,7 @@ impl RandomGenerator { pub fn next_f32(&mut self) -> f32 { match self { Self::Xoroshiro(rand) => rand.next_f32(), + Self::LegacyXoroshiro(rand) => rand.next_f32(), Self::Legacy(rand) => rand.next_f32(), } } @@ -84,6 +93,7 @@ impl RandomGenerator { pub fn next_f64(&mut self) -> f64 { match self { Self::Xoroshiro(rand) => rand.next_f64(), + Self::LegacyXoroshiro(rand) => rand.next_f64(), Self::Legacy(rand) => rand.next_f64(), } } @@ -92,6 +102,7 @@ impl RandomGenerator { pub fn next_gaussian(&mut self) -> f64 { match self { Self::Xoroshiro(rand) => rand.next_gaussian(), + Self::LegacyXoroshiro(rand) => rand.next_gaussian(), Self::Legacy(rand) => rand.next_gaussian(), } } diff --git a/pumpkin-world/src/world_gen/blender.rs b/pumpkin-world/src/world_gen/blender.rs index 5944201c7..c31446037 100644 --- a/pumpkin-world/src/world_gen/blender.rs +++ b/pumpkin-world/src/world_gen/blender.rs @@ -1 +1,9 @@ +use super::noise::density::NoisePos; + pub struct Blender {} + +impl Blender { + pub fn apply_blend_density(&self, pos: &impl NoisePos, density: f64) -> f64 { + unimplemented!() + } +} diff --git a/pumpkin-world/src/world_gen/chunk.rs b/pumpkin-world/src/world_gen/chunk.rs index eec758a19..53ca05875 100644 --- a/pumpkin-world/src/world_gen/chunk.rs +++ b/pumpkin-world/src/world_gen/chunk.rs @@ -31,9 +31,10 @@ pub struct GenerationShapeConfig { } //Bits avaliable to encode y-pos -const SIZE_BITS_Y: i32 = 12; -const MAX_HEIGHT: i32 = (1 << SIZE_BITS_Y) - 32; -const MAX_COLUMN_HEIGHT: i32 = (MAX_HEIGHT >> 1) - 1; +pub const SIZE_BITS_Y: i32 = 12; +pub const MAX_HEIGHT: i32 = (1 << SIZE_BITS_Y) - 32; +pub const MAX_COLUMN_HEIGHT: i32 = (MAX_HEIGHT >> 1) - 1; +pub const MIN_HEIGHT: i32 = MAX_COLUMN_HEIGHT - MAX_HEIGHT + 1; impl GenerationShapeConfig { fn new(y_min: i32, height: i32, horizontal: i32, vertical: i32) -> Self { diff --git a/pumpkin-world/src/world_gen/implementation/overworld/mod.rs b/pumpkin-world/src/world_gen/implementation/overworld/mod.rs index f1af41c40..f96d401f1 100644 --- a/pumpkin-world/src/world_gen/implementation/overworld/mod.rs +++ b/pumpkin-world/src/world_gen/implementation/overworld/mod.rs @@ -1 +1,2 @@ pub mod biome; +pub mod terrain_params; diff --git a/pumpkin-world/src/world_gen/implementation/overworld/terrain_params.rs b/pumpkin-world/src/world_gen/implementation/overworld/terrain_params.rs new file mode 100644 index 000000000..01a81c77c --- /dev/null +++ b/pumpkin-world/src/world_gen/implementation/overworld/terrain_params.rs @@ -0,0 +1,552 @@ +// From da java + +use crate::world_gen::noise::density::spline::{ + FloatAmplifier, Spline, SplineBuilder, SplineValue, +}; +use crate::world_gen::noise::density::{peaks_valleys_noise, DensityFunction}; +use crate::world_gen::noise::lerp_32; + +#[inline] +fn get_offset_value(f: f32, g: f32, h: f32) -> f32 { + let k = 1f32 - (1f32 - g) * 0.5f32; + let l = 0.5f32 * (1f32 - g); + + let m = (f + 1.17f32) * 0.46082947f32; + let n = m * k - l; + + if f < h { + n.max(-0.2222f32) + } else { + n.max(0f32) + } +} + +#[inline] +fn meth_42045(f: f32) -> f32 { + let k = 1f32 - (1f32 - f) * 0.5f32; + let l = 0.5f32 * (1f32 - f); + + l / (0.46082947f32 * k) - 1.17f32 +} + +#[inline] +fn meth_42047(f: f32, g: f32, h: f32, i: f32) -> f32 { + (g - f) / (i - h) +} + +fn meth_42050(function: DensityFunction, f: f32, bl: bool, amplifier: FloatAmplifier) -> Spline { + let mut builder = SplineBuilder::new(function, amplifier); + + let i = get_offset_value(-1f32, f, -0.7f32); + let k = get_offset_value(1f32, f, -0.7f32); + + let l = meth_42045(f); + + let builder = if -0.65f32 < l && l < 1f32 { + let n = get_offset_value(-0.65f32, f, -0.7f32); + let p = get_offset_value(-0.75f32, f, -0.7f32); + let q = meth_42047(i, p, -1f32, -0.75f32); + let builder = builder + .add_value(-1f32, i, q) + .add_value(-0.75f32, p, 0f32) + .add_value(-0.65f32, n, 0f32); + + let r = get_offset_value(l, f, -0.7f32); + let s = meth_42047(r, k, l, 1f32); + builder + .add_value(l - 0.01f32, r, 0f32) + .add_value(l, r, s) + .add_value(1f32, k, s) + } else { + let n = meth_42047(i, k, -1f32, 1f32); + let builder = if bl { + builder + .add_value(-1f32, 0.2f32.max(i), 0f32) + .add_value(0f32, lerp_32(0.5f32, i, k), n) + } else { + builder.add_value(-1f32, i, n) + }; + + builder.add_value(1f32, k, n) + }; + + builder.build() +} + +#[allow(clippy::too_many_arguments)] +fn meth_42048( + ridges: DensityFunction, + continental: f32, + f: f32, + g: f32, + h: f32, + i: f32, + j: f32, + amplifier: FloatAmplifier, +) -> Spline { + let k = j.max(0.5f32 * (f - continental)); + let l = 5f32 * (g - f); + SplineBuilder::new(ridges, amplifier) + .add_value(-1f32, continental, 0f32) + .add_value(-0.4f32, f, k.min(l)) + .add_value(0f32, g, l) + .add_value(0.4f32, h, 2f32 * (h - g)) + .add_value(1f32, i, 0.7f32 * (i - h)) + .build() +} + +fn method_42054<'a>( + erosion: DensityFunction<'a>, + ridges: DensityFunction<'a>, + ridges_folded: DensityFunction<'a>, + f: f32, + bl: bool, + amplifier: FloatAmplifier, +) -> Spline<'a> { + let spline = SplineBuilder::new(ridges.clone(), amplifier.clone()) + .add_value(-0.2f32, 6.3f32, 0f32) + .add_value(0.2f32, f, 0f32) + .build(); + + let mut builder = SplineBuilder::new(erosion, amplifier.clone()); + let builder = builder + .add_spline(-0.6f32, SplineValue::Spline(spline.clone()), 0f32) + .add_spline( + -0.5f32, + SplineValue::Spline( + SplineBuilder::new(ridges.clone(), amplifier.clone()) + .add_value(-0.05f32, 6.3f32, 0f32) + .add_value(0.05f32, 2.67f32, 0f32) + .build(), + ), + 0f32, + ) + .add_spline(-0.35f32, SplineValue::Spline(spline.clone()), 0f32) + .add_spline(-0.25f32, SplineValue::Spline(spline.clone()), 0f32) + .add_spline( + -0.1f32, + SplineValue::Spline( + SplineBuilder::new(ridges.clone(), amplifier.clone()) + .add_value(-0.05f32, 2.67, 0f32) + .add_value(0.05f32, 6.3f32, 0f32) + .build(), + ), + 0f32, + ) + .add_spline(0.03f32, SplineValue::Spline(spline.clone()), 0f32); + + let builder = if bl { + let spline2 = SplineBuilder::new(ridges.clone(), amplifier.clone()) + .add_value(0f32, f, 0f32) + .add_value(0.1f32, 0.625f32, 0f32) + .build(); + let spline3 = SplineBuilder::new(ridges_folded.clone(), amplifier.clone()) + .add_value(-0.9f32, f, 0f32) + .add_spline(-0.69f32, SplineValue::Spline(spline2), 0f32) + .build(); + + builder + .add_value(0.35f32, f, 0f32) + .add_spline(0.45f32, SplineValue::Spline(spline3.clone()), 0f32) + .add_spline(0.55f32, SplineValue::Spline(spline3.clone()), 0f32) + .add_value(0.62f32, f, 0f32) + } else { + let spline2 = SplineBuilder::new(ridges_folded.clone(), amplifier.clone()) + .add_spline(-0.7f32, SplineValue::Spline(spline.clone()), 0f32) + .add_value(-0.15f32, 1.37f32, 0f32) + .build(); + + let spline3 = SplineBuilder::new(ridges_folded.clone(), amplifier.clone()) + .add_spline(0.45f32, SplineValue::Spline(spline.clone()), 0f32) + .add_value(0.7f32, 1.56f32, 0f32) + .build(); + + builder + .add_spline(0.05f32, SplineValue::Spline(spline3.clone()), 0f32) + .add_spline(0.4f32, SplineValue::Spline(spline3.clone()), 0f32) + .add_spline(0.45f32, SplineValue::Spline(spline2.clone()), 0f32) + .add_spline(0.55f32, SplineValue::Spline(spline2.clone()), 0f32) + .add_value(0.56f32, f, 0f32) + }; + + builder.build() +} + +fn method_42052<'a>( + ridges: DensityFunction<'a>, + ridges_folded: DensityFunction<'a>, + f: f32, + g: f32, + amplifier: FloatAmplifier, +) -> Spline<'a> { + let h = peaks_valleys_noise(0.4f32); + let i = peaks_valleys_noise(0.56666666f32); + let j = (h + i) / 2f32; + + let mut builder = SplineBuilder::new(ridges_folded, amplifier.clone()); + + let builder = builder.add_value(h, 0f32, 0f32); + let builder = if g > 0f32 { + builder.add_spline( + j, + SplineValue::Spline(method_42049(ridges.clone(), f, amplifier.clone())), + 0f32, + ) + } else { + builder.add_value(j, 0f32, 0f32) + }; + + let builder = if f > 0f32 { + builder.add_spline( + 1f32, + SplineValue::Spline(method_42049(ridges.clone(), f, amplifier.clone())), + 0f32, + ) + } else { + builder.add_value(1f32, 0f32, 0f32) + }; + + builder.build() +} + +fn method_42049<'a>(ridges: DensityFunction<'a>, f: f32, amplifier: FloatAmplifier) -> Spline<'a> { + let g = 0.63f32 * f; + let h = 0.3f32 * f; + SplineBuilder::new(ridges, amplifier) + .add_value(-0.01, g, 0f32) + .add_value(0.01f32, h, 0f32) + .build() +} + +fn method_42053<'a>( + erosion: DensityFunction<'a>, + ridges: DensityFunction<'a>, + ridges_folded: DensityFunction<'a>, + f: f32, + g: f32, + h: f32, + i: f32, + amplifier: FloatAmplifier, +) -> Spline<'a> { + let spline = method_42052( + ridges.clone(), + ridges_folded.clone(), + f, + h, + amplifier.clone(), + ); + let spline2 = method_42052( + ridges.clone(), + ridges_folded.clone(), + g, + i, + amplifier.clone(), + ); + + SplineBuilder::new(erosion, amplifier) + .add_spline(-1f32, SplineValue::Spline(spline), 0f32) + .add_spline(-0.78, SplineValue::Spline(spline2.clone()), 0f32) + .add_spline(-05775f32, SplineValue::Spline(spline2), 0f32) + .add_value(-0.375f32, 0f32, 0f32) + .build() +} + +#[allow(clippy::too_many_arguments)] +fn create_continental_offset_spline<'a>( + erosion: DensityFunction<'a>, + ridges: DensityFunction<'a>, + continental: f32, + f: f32, + g: f32, + h: f32, + i: f32, + j: f32, + bl: bool, + bl2: bool, + amplifier: FloatAmplifier, +) -> Spline<'a> { + let spline = meth_42050( + ridges.clone(), + lerp_32(h, 0.6f32, 1.5f32), + bl2, + amplifier.clone(), + ); + let spline2 = meth_42050( + ridges.clone(), + lerp_32(h, 0.6f32, 1f32), + bl2, + amplifier.clone(), + ); + let spline3 = meth_42050(ridges.clone(), h, bl2, amplifier.clone()); + let spline4 = meth_42048( + ridges.clone(), + continental - 0.15f32, + 0.5f32 * h, + lerp_32(0.5f32, 0.5f32, 0.5f32) * h, + 0.5f32 * h, + 0.6f32 * h, + 0.5f32, + amplifier.clone(), + ); + + let spline5 = meth_42048( + ridges.clone(), + continental, + i * h, + f * h, + 0.5f32 * h, + 0.6f32 * h, + 0.5f32, + amplifier.clone(), + ); + let spline6 = meth_42048( + ridges.clone(), + continental, + i, + i, + f, + g, + 0.5f32, + amplifier.clone(), + ); + let spline7 = meth_42048( + ridges.clone(), + continental, + i, + i, + f, + g, + 0.5f32, + amplifier.clone(), + ); + + let spline8 = SplineBuilder::new(ridges.clone(), amplifier.clone()) + .add_value(-1f32, continental, 0f32) + .add_spline(-0.4f32, SplineValue::Spline(spline6.clone()), 0f32) + .add_value(0f32, g + 0.07f32, 0f32) + .build(); + let spline9 = meth_42048( + ridges.clone(), + -0.02f32, + j, + j, + f, + g, + 0f32, + amplifier.clone(), + ); + + let mut builder = SplineBuilder::new(erosion, amplifier); + let builder = builder + .add_spline(-0.85f32, SplineValue::Spline(spline), 0f32) + .add_spline(-0.7f32, SplineValue::Spline(spline2), 0f32) + .add_spline(-0.4f32, SplineValue::Spline(spline3), 0f32) + .add_spline(-0.35f32, SplineValue::Spline(spline4), 0f32) + .add_spline(-0.1f32, SplineValue::Spline(spline5), 0f32) + .add_spline(0.2f32, SplineValue::Spline(spline6), 0f32); + + let builder = if bl { + builder + .add_spline(0.4f32, SplineValue::Spline(spline7.clone()), 0f32) + .add_spline(0.45f32, SplineValue::Spline(spline8.clone()), 0f32) + .add_spline(0.55f32, SplineValue::Spline(spline8), 0f32) + .add_spline(0.58f32, SplineValue::Spline(spline7), 0f32) + } else { + builder + }; + + builder + .add_spline(0.7f32, SplineValue::Spline(spline9), 0f32) + .build() +} + +pub fn create_offset_spline<'a>( + contentents: DensityFunction<'a>, + erosion: DensityFunction<'a>, + ridges: DensityFunction<'a>, + amplified: bool, +) -> Spline<'a> { + let amplification = if amplified { + FloatAmplifier::Amplifier + } else { + FloatAmplifier::Identity + }; + + let spline = create_continental_offset_spline( + erosion.clone(), + ridges.clone(), + -0.15f32, + 0f32, + 0f32, + 0.132, + 0f32, + -0.03f32, + false, + false, + amplification.clone(), + ); + let spline2 = create_continental_offset_spline( + erosion.clone(), + ridges.clone(), + -0.1f32, + 0.03f32, + 0.1f32, + 0.1f32, + 0.01f32, + -0.03f32, + false, + false, + amplification.clone(), + ); + let spline3 = create_continental_offset_spline( + erosion.clone(), + ridges.clone(), + -0.1f32, + 0.03f32, + 0.1f32, + 0.7f32, + 0.01f32, + -0.03f32, + true, + true, + amplification.clone(), + ); + let spline4 = create_continental_offset_spline( + erosion.clone(), + ridges.clone(), + -0.05f32, + 0.03f32, + 0.1f32, + 1f32, + 0.01f32, + 0.01f32, + true, + true, + amplification.clone(), + ); + + SplineBuilder::new(contentents.clone(), amplification.clone()) + .add_value(-1.1f32, 0.044f32, 0f32) + .add_value(-1.02f32, -0.2222f32, 0f32) + .add_value(-0.51f32, -0.2222f32, 0f32) + .add_value(-0.44f32, -0.12f32, 0f32) + .add_value(-0.18f32, -0.12f32, 0f32) + .add_spline(-0.16f32, SplineValue::Spline(spline.clone()), 0f32) + .add_spline(-0.15f32, SplineValue::Spline(spline), 0f32) + .add_spline(-0.1f32, SplineValue::Spline(spline2), 0f32) + .add_spline(0.25f32, SplineValue::Spline(spline3), 0f32) + .add_spline(1f32, SplineValue::Spline(spline4), 0f32) + .build() +} + +pub fn create_factor_spline<'a>( + continents: DensityFunction<'a>, + erosion: DensityFunction<'a>, + ridges: DensityFunction<'a>, + ridges_folded: DensityFunction<'a>, + amplified: bool, +) -> Spline<'a> { + let amplification = if amplified { + FloatAmplifier::Amplifier + } else { + FloatAmplifier::Identity + }; + + SplineBuilder::new(continents, FloatAmplifier::Identity) + .add_value(-0.19f32, 3.95f32, 0f32) + .add_spline( + -0.15f32, + SplineValue::Spline(method_42054( + erosion.clone(), + ridges.clone(), + ridges_folded.clone(), + 6.25f32, + true, + FloatAmplifier::Identity, + )), + 0f32, + ) + .add_spline( + -0.1f32, + SplineValue::Spline(method_42054( + erosion.clone(), + ridges.clone(), + ridges_folded.clone(), + 5.47f32, + true, + amplification.clone(), + )), + 0f32, + ) + .add_spline( + 0.03f32, + SplineValue::Spline(method_42054( + erosion.clone(), + ridges.clone(), + ridges_folded.clone(), + 5.08f32, + true, + amplification.clone(), + )), + 0f32, + ) + .add_spline( + 0.06f32, + SplineValue::Spline(method_42054( + erosion, + ridges, + ridges_folded, + 4.69f32, + false, + amplification, + )), + 0f32, + ) + .build() +} + +pub fn create_jaggedness_spline<'a>( + continents: DensityFunction<'a>, + erosion: DensityFunction<'a>, + ridges: DensityFunction<'a>, + ridges_folded: DensityFunction<'a>, + amplified: bool, +) -> Spline<'a> { + let amplification = if amplified { + FloatAmplifier::Amplifier + } else { + FloatAmplifier::Identity + }; + + SplineBuilder::new(continents.clone(), amplification.clone()) + .add_value(-0.11f32, 0f32, 0f32) + .add_spline( + 0.03f32, + SplineValue::Spline(method_42053( + erosion.clone(), + ridges.clone(), + ridges_folded.clone(), + 1f32, + 0.5f32, + 0f32, + 0f32, + amplification.clone(), + )), + 0f32, + ) + .add_spline( + 0.65f32, + SplineValue::Spline(method_42053( + erosion, + ridges, + ridges_folded, + 1f32, + 1f32, + 1f32, + 0f32, + amplification, + )), + 0f32, + ) + .build() +} diff --git a/pumpkin-world/src/world_gen/noise/density/blend.rs b/pumpkin-world/src/world_gen/noise/density/blend.rs new file mode 100644 index 000000000..579589deb --- /dev/null +++ b/pumpkin-world/src/world_gen/noise/density/blend.rs @@ -0,0 +1,94 @@ +use std::sync::Arc; + +use super::{DensityFunction, DensityFunctionImpl, NoisePos}; + +#[derive(Clone)] +pub struct BlendOffsetFunction {} + +impl<'a> DensityFunctionImpl<'a> for BlendOffsetFunction { + fn sample(&self, _pos: &impl super::NoisePos) -> f64 { + 0f64 + } + + fn fill(&self, densities: &[f64], _applier: &impl super::Applier) -> Vec { + densities.iter().map(|_| 0f64).collect() + } + + fn min(&self) -> f64 { + 0f64 + } + + fn max(&self) -> f64 { + 0f64 + } + + fn apply(&'a self, visitor: &'a impl super::Visitor) -> super::DensityFunction<'a> { + visitor.apply(&DensityFunction::BlendOffset(self.clone())) + } +} + +#[derive(Clone)] +pub struct BlendAlphaFunction {} + +impl<'a> DensityFunctionImpl<'a> for BlendAlphaFunction { + fn sample(&self, _pos: &impl super::NoisePos) -> f64 { + 1f64 + } + + fn fill(&self, densities: &[f64], _applier: &impl super::Applier) -> Vec { + densities.iter().map(|_| 1f64).collect() + } + + fn max(&self) -> f64 { + 1f64 + } + + fn min(&self) -> f64 { + 1f64 + } + + fn apply(&'a self, visitor: &'a impl super::Visitor) -> DensityFunction<'a> { + visitor.apply(&DensityFunction::BlendAlpha(self.clone())) + } +} + +#[derive(Clone)] +pub struct BlendDensityFunction<'a> { + function: Arc>, +} + +impl<'a> BlendDensityFunction<'a> { + fn apply_density(&self, pos: &impl NoisePos, density: f64) -> f64 { + pos.get_blender().apply_blend_density(pos, density) + } +} + +impl<'a> DensityFunctionImpl<'a> for BlendDensityFunction<'a> { + fn sample(&self, pos: &impl super::NoisePos) -> f64 { + self.apply_density(pos, self.function.sample(pos)) + } + + fn fill(&self, densities: &[f64], applier: &impl super::Applier) -> Vec { + let densities = self.function.fill(densities, applier); + densities + .iter() + .enumerate() + .map(|(i, x)| self.apply_density(&applier.at(i as i32), *x)) + .collect() + } + + fn apply(&'a self, visitor: &'a impl super::Visitor) -> DensityFunction<'a> { + let new_function = BlendDensityFunction { + function: Arc::new(self.function.apply(visitor)), + }; + visitor.apply(&DensityFunction::BlendDensity(new_function)) + } + + fn min(&self) -> f64 { + f64::NEG_INFINITY + } + + fn max(&self) -> f64 { + f64::INFINITY + } +} diff --git a/pumpkin-world/src/world_gen/noise/density/math.rs b/pumpkin-world/src/world_gen/noise/density/math.rs new file mode 100644 index 000000000..c9ffb8193 --- /dev/null +++ b/pumpkin-world/src/world_gen/noise/density/math.rs @@ -0,0 +1,258 @@ +use std::sync::Arc; + +use log::warn; + +use super::{DensityFunction, DensityFunctionImpl, UnaryDensityFunction}; + +#[derive(Clone)] +pub enum LinearType { + Mul, + Add, +} + +#[derive(Clone)] +pub struct LinearFunction<'a> { + action: LinearType, + input: Arc>, + min: f64, + max: f64, + arg: f64, +} + +impl<'a> DensityFunctionImpl<'a> for LinearFunction<'a> { + fn apply(&'a self, visitor: &'a impl super::Visitor) -> DensityFunction<'a> { + let new_function = self.input().apply(visitor); + let d = new_function.min(); + let e = new_function.max(); + + let (f, g) = match self.action { + LinearType::Add => (d + self.arg, e + self.arg), + LinearType::Mul => { + if self.arg >= 0f64 { + (d * self.arg, e * self.arg) + } else { + (e * self.arg, d * self.arg) + } + } + }; + + DensityFunction::Linear(LinearFunction { + action: self.action.clone(), + input: Arc::new(new_function), + min: f, + max: g, + arg: self.arg, + }) + } + + fn sample(&self, pos: &impl super::NoisePos) -> f64 { + self.apply_density(self.input().sample(pos)) + } + + fn fill(&self, densities: &[f64], applier: &impl super::Applier) -> Vec { + let densities = self.input().fill(densities, applier); + densities + .iter() + .map(|val| self.apply_density(*val)) + .collect() + } + + fn min(&self) -> f64 { + self.min + } + + fn max(&self) -> f64 { + self.max + } +} + +impl<'a> UnaryDensityFunction<'a> for LinearFunction<'a> { + fn apply_density(&self, density: f64) -> f64 { + match self.action { + LinearType::Mul => density * self.arg, + LinearType::Add => density + self.arg, + } + } + + fn input(&self) -> &DensityFunction { + &self.input + } +} + +#[derive(Clone)] +pub enum BinaryType { + Mul, + Add, + Min, + Max, +} + +#[derive(Clone)] +pub struct BinaryFunction<'a> { + action: BinaryType, + arg1: Arc>, + arg2: Arc>, + min: f64, + max: f64, +} + +impl<'a> BinaryFunction<'a> { + pub fn create( + action: BinaryType, + arg1: DensityFunction<'a>, + arg2: DensityFunction<'a>, + ) -> DensityFunction<'a> { + let d = arg1.min(); + let e = arg2.min(); + let f = arg1.max(); + let g = arg2.max(); + + match action { + BinaryType::Min | BinaryType::Max => { + if d >= e || e >= f { + warn!("Density function does not overlap"); + } + } + _ => {} + } + + let h = match action { + BinaryType::Add => d + e, + BinaryType::Mul => { + if d > 0f64 && e > 0f64 { + d * e + } else if f < 0f64 && g < 0f64 { + f * g + } else { + (d * g).min(f * e) + } + } + BinaryType::Min => d.min(e), + BinaryType::Max => d.max(e), + }; + + let i = match action { + BinaryType::Add => f + g, + BinaryType::Mul => { + if d > 0f64 && e > 0f64 { + f * g + } else if f < 0f64 && g < 0f64 { + d * e + } else { + (d * e).max(f * g) + } + } + BinaryType::Min => f.min(g), + BinaryType::Max => f.max(g), + }; + + match action { + BinaryType::Mul | BinaryType::Add => { + let action = match action { + BinaryType::Add => LinearType::Add, + BinaryType::Mul => LinearType::Mul, + _ => unreachable!(), + }; + + if let DensityFunction::Constant(func) = arg1 { + return DensityFunction::Linear(LinearFunction { + action, + input: Arc::new(arg2), + min: h, + max: i, + arg: func.value, + }); + } + + if let DensityFunction::Constant(func) = arg2 { + return DensityFunction::Linear(LinearFunction { + action, + input: Arc::new(arg1), + min: h, + max: i, + arg: func.value, + }); + } + } + _ => {} + } + + DensityFunction::Binary(BinaryFunction { + action, + arg1: Arc::new(arg1), + arg2: Arc::new(arg2), + min: h, + max: i, + }) + } +} + +impl<'a> DensityFunctionImpl<'a> for BinaryFunction<'a> { + fn sample(&self, pos: &impl super::NoisePos) -> f64 { + let d = self.arg1.sample(pos); + let e = self.arg2.sample(pos); + + match self.action { + BinaryType::Add => d + e, + BinaryType::Mul => d * e, + BinaryType::Min => { + if d < self.arg2.min() { + d + } else { + d.min(e) + } + } + BinaryType::Max => { + if d > self.arg2.max() { + d + } else { + d.max(e) + } + } + } + } + + fn fill(&self, densities: &[f64], applier: &impl super::Applier) -> Vec { + let densities1 = self.arg1.fill(densities, applier); + let densities2 = self.arg2.fill(densities, applier); + + match self.action { + BinaryType::Add => densities1 + .iter() + .zip(densities2) + .map(|(x, y)| x + y) + .collect(), + BinaryType::Mul => densities1 + .iter() + .zip(densities2) + .map(|(x, y)| x * y) + .collect(), + BinaryType::Min => densities1 + .iter() + .zip(densities2) + .map(|(x, y)| x.min(y)) + .collect(), + BinaryType::Max => densities1 + .iter() + .zip(densities2) + .map(|(x, y)| x.max(y)) + .collect(), + } + } + + fn apply(&'a self, visitor: &'a impl super::Visitor) -> DensityFunction<'a> { + visitor.apply(&BinaryFunction::create( + self.action.clone(), + self.arg1.apply(visitor), + self.arg2.apply(visitor), + )) + } + + fn max(&self) -> f64 { + self.max + } + + fn min(&self) -> f64 { + self.min + } +} diff --git a/pumpkin-world/src/world_gen/noise/density/mod.rs b/pumpkin-world/src/world_gen/noise/density/mod.rs index 1351d897c..2f55f5c3a 100644 --- a/pumpkin-world/src/world_gen/noise/density/mod.rs +++ b/pumpkin-world/src/world_gen/noise/density/mod.rs @@ -1,15 +1,242 @@ -use std::rc::Rc; +use std::sync::Arc; -use noise::{InternalNoise, NoiseFunction, ShiftedNoiseFunction}; +use blend::{BlendAlphaFunction, BlendDensityFunction, BlendOffsetFunction}; +use math::{BinaryFunction, BinaryType, LinearFunction}; +use noise::{InternalNoise, InterpolatedNoiseSampler, NoiseFunction, ShiftedNoiseFunction}; use offset::{ShiftAFunction, ShiftBFunction}; +use spline::SplineFunction; use unary::{ClampFunction, UnaryFunction, UnaryType}; use crate::world_gen::blender::Blender; +use super::clamped_map; + +mod blend; +mod math; mod noise; mod offset; +pub mod spline; mod unary; +pub mod built_in_noises { + use std::sync::{Arc, LazyLock}; + + use crate::world_gen::{ + chunk::{MAX_COLUMN_HEIGHT, MIN_HEIGHT}, + implementation::overworld::terrain_params::{ + create_factor_spline, create_jaggedness_spline, create_offset_spline, + }, + noise::builtin_noise_params, + }; + + use super::{ + blend::{BlendAlphaFunction, BlendOffsetFunction}, + lerp_density, + noise::{InternalNoise, InterpolatedNoiseSampler, NoiseFunction, ShiftedNoiseFunction}, + offset::{ShiftAFunction, ShiftBFunction}, + spline::SplineFunction, + ConstantFunction, DensityFunction, YClampedFunction, + }; + + pub struct SlopedCheeseResult<'a> { + offset: DensityFunction<'a>, + factor: DensityFunction<'a>, + depth: DensityFunction<'a>, + jaggedness: DensityFunction<'a>, + sloped_cheese: DensityFunction<'a>, + } + + type BuiltInNoise = LazyLock>; + type BuiltInSlopedCheese = LazyLock>; + + pub static ZERO: BuiltInNoise = + LazyLock::new(|| DensityFunction::Constant(ConstantFunction::new(0f64))); + + pub static TEN: BuiltInNoise = + LazyLock::new(|| DensityFunction::Constant(ConstantFunction::new(10f64))); + + pub static Y: BuiltInNoise = LazyLock::new(|| { + DensityFunction::ClampedY(YClampedFunction { + from: MIN_HEIGHT * 2, + to: MAX_COLUMN_HEIGHT * 2, + from_val: (MIN_HEIGHT * 2) as f64, + to_val: (MAX_COLUMN_HEIGHT * 2) as f64, + }) + }); + + pub static SHIFT_X: BuiltInNoise = LazyLock::new(|| { + DensityFunction::ShiftA(ShiftAFunction::new(Arc::new(InternalNoise::new( + builtin_noise_params::OFFSET.clone(), + None, + )))) + }); + + pub static SHIFT_Z: BuiltInNoise = LazyLock::new(|| { + DensityFunction::ShiftB(ShiftBFunction::new(Arc::new(InternalNoise::new( + builtin_noise_params::OFFSET.clone(), + None, + )))) + }); + + pub static BASE_3D_NOISE_OVERWORLD: BuiltInNoise = LazyLock::new(|| { + DensityFunction::InterpolatedNoise(InterpolatedNoiseSampler::create_base_3d_noise_function( + 0.25f64, 0.125f64, 80f64, 160f64, 8f64, + )) + }); + + pub static BASE_3D_NOISE_NETHER: BuiltInNoise = LazyLock::new(|| { + DensityFunction::InterpolatedNoise(InterpolatedNoiseSampler::create_base_3d_noise_function( + 0.25f64, 0.375f64, 80f64, 60f64, 8f64, + )) + }); + + pub static BASE_3D_NOISE_END: BuiltInNoise = LazyLock::new(|| { + DensityFunction::InterpolatedNoise(InterpolatedNoiseSampler::create_base_3d_noise_function( + 0.25f64, 0.25f64, 80f64, 160f64, 4f64, + )) + }); + + pub static CONTINENTS_OVERWORLD: BuiltInNoise = LazyLock::new(|| { + DensityFunction::ShiftedNoise(ShiftedNoiseFunction::new( + Arc::new(SHIFT_X.clone()), + Arc::new(ZERO.clone()), + Arc::new(SHIFT_Z.clone()), + 0.25f64, + 0f64, + Arc::new(InternalNoise::new( + builtin_noise_params::CONTINENTALNESS.clone(), + None, + )), + )) + }); + + pub static EROSION_OVERWORLD: BuiltInNoise = LazyLock::new(|| { + DensityFunction::ShiftedNoise(ShiftedNoiseFunction::new( + Arc::new(SHIFT_X.clone()), + Arc::new(ZERO.clone()), + Arc::new(SHIFT_Z.clone()), + 0.25f64, + 0f64, + Arc::new(InternalNoise::new( + builtin_noise_params::EROSION.clone(), + None, + )), + )) + }); + + pub static RIDGES_OVERWORLD: BuiltInNoise = LazyLock::new(|| { + DensityFunction::ShiftedNoise(ShiftedNoiseFunction::new( + Arc::new(SHIFT_X.clone()), + Arc::new(ZERO.clone()), + Arc::new(SHIFT_Z.clone()), + 0.25f64, + 0f64, + Arc::new(InternalNoise::new( + builtin_noise_params::RIDGE.clone(), + None, + )), + )) + }); + + pub static RIDGES_FOLDED_OVERWORLD: BuiltInNoise = LazyLock::new(|| { + RIDGES_OVERWORLD + .abs() + .add_const(-0.6666666666666666f64) + .abs() + .add_const(-0.3333333333333333f64) + .mul_const(-3f64) + }); + + pub static OVERWORLD_SLOPED_CHEESE: BuiltInSlopedCheese = LazyLock::new(|| { + sloped_cheese_function( + DensityFunction::Noise(NoiseFunction::new( + Arc::new(InternalNoise::new( + builtin_noise_params::JAGGED.clone(), + None, + )), + 1500f64, + 0f64, + )), + CONTINENTS_OVERWORLD.clone(), + EROSION_OVERWORLD.clone(), + RIDGES_OVERWORLD.clone(), + RIDGES_FOLDED_OVERWORLD.clone(), + false, + ) + }); + + fn sloped_cheese_function<'a>( + jagged_noise: DensityFunction<'a>, + continents: DensityFunction<'a>, + erosion: DensityFunction<'a>, + ridges: DensityFunction<'a>, + ridges_folded: DensityFunction<'a>, + amplified: bool, + ) -> SlopedCheeseResult<'a> { + let offset = lerp_density( + DensityFunction::BlendAlpha(BlendAlphaFunction {}), + DensityFunction::Spline(SplineFunction::new(Arc::new(create_offset_spline( + continents.clone(), + erosion.clone(), + ridges.clone(), + amplified, + )))) + .add_const(-0.50375f32 as f64), + DensityFunction::BlendOffset(BlendOffsetFunction {}), + ); + + let factor = lerp_density( + DensityFunction::BlendAlpha(BlendAlphaFunction {}), + DensityFunction::Spline(SplineFunction::new(Arc::new(create_factor_spline( + continents.clone(), + erosion.clone(), + ridges.clone(), + ridges_folded.clone(), + amplified, + )))), + TEN.clone(), + ); + + let depth = DensityFunction::ClampedY(YClampedFunction { + from: -64, + to: 320, + from_val: 1.564, + to_val: -1.5f64, + }) + .add(offset.clone()); + + let jaggedness = lerp_density( + DensityFunction::BlendAlpha(BlendAlphaFunction {}), + DensityFunction::Spline(SplineFunction::new(Arc::new(create_jaggedness_spline( + continents, + erosion, + ridges, + ridges_folded, + amplified, + )))), + ZERO.clone(), + ); + + let density1 = jaggedness.mul(jagged_noise.half_negative()); + let density2 = DensityFunction::Constant(ConstantFunction::new(4f64)) + .mul(depth.add(density1).mul(factor.clone()).quarter_negative()); + + let sloped_cheese = density2.add(BASE_3D_NOISE_OVERWORLD.clone()); + + SlopedCheeseResult { + offset, + factor, + depth, + jaggedness, + sloped_cheese, + } + } +} + +pub fn peaks_valleys_noise(variance: f32) -> f32 { + -((variance.abs() - 0.6666667f32).abs() - 0.33333334f32) * 3f32 +} + #[derive(Clone)] pub enum DensityFunction<'a> { Clamp(ClampFunction<'a>), @@ -18,6 +245,15 @@ pub enum DensityFunction<'a> { ShiftA(ShiftAFunction<'a>), ShiftB(ShiftBFunction<'a>), ShiftedNoise(ShiftedNoiseFunction<'a>), + Spline(SplineFunction<'a>), + Constant(ConstantFunction), + Linear(LinearFunction<'a>), + Binary(BinaryFunction<'a>), + BlendOffset(BlendOffsetFunction), + BlendAlpha(BlendAlphaFunction), + BlendDensity(BlendDensityFunction<'a>), + ClampedY(YClampedFunction), + InterpolatedNoise(InterpolatedNoiseSampler), } impl<'a> DensityFunction<'a> { @@ -30,6 +266,15 @@ impl<'a> DensityFunction<'a> { Self::ShiftA(func) => func.sample(pos), Self::ShiftB(func) => func.sample(pos), Self::ShiftedNoise(func) => func.sample(pos), + Self::Spline(func) => func.sample(pos), + Self::Constant(func) => func.sample(pos), + Self::Linear(func) => func.sample(pos), + Self::Binary(func) => func.sample(pos), + Self::BlendOffset(func) => func.sample(pos), + Self::BlendAlpha(func) => func.sample(pos), + Self::BlendDensity(func) => func.sample(pos), + Self::ClampedY(func) => func.sample(pos), + Self::InterpolatedNoise(func) => func.sample(pos), } } @@ -42,6 +287,15 @@ impl<'a> DensityFunction<'a> { Self::ShiftA(func) => func.apply(visitor), Self::ShiftB(func) => func.apply(visitor), Self::ShiftedNoise(func) => func.apply(visitor), + Self::Spline(func) => func.apply(visitor), + Self::Constant(func) => func.apply(visitor), + Self::Linear(func) => func.apply(visitor), + Self::Binary(func) => func.apply(visitor), + Self::BlendOffset(func) => func.apply(visitor), + Self::BlendAlpha(func) => func.apply(visitor), + Self::BlendDensity(func) => func.apply(visitor), + Self::ClampedY(func) => func.apply(visitor), + Self::InterpolatedNoise(func) => func.apply(visitor), } } @@ -54,6 +308,15 @@ impl<'a> DensityFunction<'a> { Self::ShiftA(func) => func.fill(densities, applier), Self::ShiftB(func) => func.fill(densities, applier), Self::ShiftedNoise(func) => func.fill(densities, applier), + Self::Spline(func) => func.fill(densities, applier), + Self::Constant(func) => func.fill(densities, applier), + Self::Linear(func) => func.fill(densities, applier), + Self::Binary(func) => func.fill(densities, applier), + Self::BlendOffset(func) => func.fill(densities, applier), + Self::BlendAlpha(func) => func.fill(densities, applier), + Self::BlendDensity(func) => func.fill(densities, applier), + Self::ClampedY(func) => func.fill(densities, applier), + Self::InterpolatedNoise(func) => func.fill(densities, applier), } } @@ -66,6 +329,15 @@ impl<'a> DensityFunction<'a> { Self::ShiftA(func) => func.max(), Self::ShiftB(func) => func.max(), Self::ShiftedNoise(func) => func.max(), + Self::Spline(func) => func.max(), + Self::Constant(func) => func.max(), + Self::Linear(func) => func.max(), + Self::Binary(func) => func.max(), + Self::BlendOffset(func) => func.max(), + Self::BlendAlpha(func) => func.max(), + Self::BlendDensity(func) => func.max(), + Self::ClampedY(func) => func.max(), + Self::InterpolatedNoise(func) => func.max(), } } @@ -78,55 +350,91 @@ impl<'a> DensityFunction<'a> { Self::ShiftA(func) => func.min(), Self::ShiftB(func) => func.min(), Self::ShiftedNoise(func) => func.min(), + Self::Spline(func) => func.min(), + Self::Constant(func) => func.min(), + Self::Linear(func) => func.min(), + Self::Binary(func) => func.min(), + Self::BlendOffset(func) => func.min(), + Self::BlendAlpha(func) => func.min(), + Self::BlendDensity(func) => func.min(), + Self::ClampedY(func) => func.min(), + Self::InterpolatedNoise(func) => func.min(), } } pub fn clamp(&self, max: f64, min: f64) -> Self { Self::Clamp(ClampFunction { - input: Rc::new(self.clone()), + input: Arc::new(self.clone()), min, max, }) } pub fn abs(&self) -> Self { - Self::Unary(UnaryFunction::create(UnaryType::Abs, Rc::new(self.clone()))) + Self::Unary(UnaryFunction::create( + UnaryType::Abs, + Arc::new(self.clone()), + )) } pub fn square(&self) -> Self { Self::Unary(UnaryFunction::create( UnaryType::Square, - Rc::new(self.clone()), + Arc::new(self.clone()), )) } pub fn cube(&self) -> Self { Self::Unary(UnaryFunction::create( UnaryType::Cube, - Rc::new(self.clone()), + Arc::new(self.clone()), )) } pub fn half_negative(&self) -> Self { Self::Unary(UnaryFunction::create( UnaryType::HalfNeg, - Rc::new(self.clone()), + Arc::new(self.clone()), )) } pub fn quarter_negative(&self) -> Self { Self::Unary(UnaryFunction::create( UnaryType::QuartNeg, - Rc::new(self.clone()), + Arc::new(self.clone()), )) } pub fn squeeze(&self) -> Self { Self::Unary(UnaryFunction::create( UnaryType::Squeeze, - Rc::new(self.clone()), + Arc::new(self.clone()), )) } + + pub fn add_const(&self, val: f64) -> Self { + self.add(Self::Constant(ConstantFunction::new(val))) + } + + pub fn add(&self, other: DensityFunction<'a>) -> Self { + BinaryFunction::create(BinaryType::Add, self.clone(), other) + } + + pub fn mul_const(&self, val: f64) -> Self { + self.mul(Self::Constant(ConstantFunction::new(val))) + } + + pub fn mul(&self, other: DensityFunction<'a>) -> Self { + BinaryFunction::create(BinaryType::Mul, self.clone(), other) + } + + pub fn binary_min(&self, other: DensityFunction<'a>) -> Self { + BinaryFunction::create(BinaryType::Min, self.clone(), other) + } + + pub fn binary_max(&self, other: DensityFunction<'a>) -> Self { + BinaryFunction::create(BinaryType::Max, self.clone(), other) + } } pub trait NoisePos { @@ -148,7 +456,7 @@ pub trait Applier { pub trait Visitor { fn apply(&self, function: &DensityFunction) -> DensityFunction; - fn apply_internal_noise<'a>(&self, function: Rc>) -> Rc> { + fn apply_internal_noise<'a>(&self, function: Arc>) -> Arc> { function.clone() } } @@ -165,6 +473,75 @@ pub trait DensityFunctionImpl<'a> { fn max(&self) -> f64; } +#[derive(Clone)] +pub struct ConstantFunction { + value: f64, +} + +impl ConstantFunction { + pub fn new(value: f64) -> Self { + ConstantFunction { value } + } +} + +impl<'a> DensityFunctionImpl<'a> for ConstantFunction { + fn sample(&self, _pos: &impl NoisePos) -> f64 { + self.value + } + + fn fill(&self, densities: &[f64], _applier: &impl Applier) -> Vec { + densities.iter().map(|_| self.value).collect() + } + + fn apply(&'a self, visitor: &'a impl Visitor) -> DensityFunction<'a> { + visitor.apply(&DensityFunction::Constant(self.clone())) + } + + fn min(&self) -> f64 { + self.value + } + + fn max(&self) -> f64 { + self.value + } +} + +#[derive(Clone)] +pub struct YClampedFunction { + from: i32, + to: i32, + from_val: f64, + to_val: f64, +} + +impl<'a> DensityFunctionImpl<'a> for YClampedFunction { + fn sample(&self, pos: &impl NoisePos) -> f64 { + clamped_map( + pos.y() as f64, + self.from as f64, + self.to as f64, + self.from_val, + self.to_val, + ) + } + + fn min(&self) -> f64 { + self.from_val.min(self.to_val) + } + + fn max(&self) -> f64 { + self.from_val.max(self.to_val) + } + + fn fill(&self, densities: &[f64], applier: &impl Applier) -> Vec { + applier.fill(densities, self) + } + + fn apply(&'a self, visitor: &'a impl Visitor) -> DensityFunction<'a> { + visitor.apply(&DensityFunction::ClampedY(self.clone())) + } +} + pub trait UnaryDensityFunction<'a>: DensityFunctionImpl<'a> { fn input(&self) -> &DensityFunction; @@ -180,3 +557,12 @@ pub trait OffsetDensityFunction<'a>: DensityFunctionImpl<'a> { * 4f64 } } + +pub fn lerp_density<'a>( + delta: DensityFunction<'a>, + start: DensityFunction<'a>, + end: DensityFunction<'a>, +) -> DensityFunction<'a> { + let func_2 = delta.mul_const(-1f64).add_const(1f64); + start.mul(func_2.clone()).add(end.mul(func_2)) +} diff --git a/pumpkin-world/src/world_gen/noise/density/noise.rs b/pumpkin-world/src/world_gen/noise/density/noise.rs index 34131cf57..fcd9bf950 100644 --- a/pumpkin-world/src/world_gen/noise/density/noise.rs +++ b/pumpkin-world/src/world_gen/noise/density/noise.rs @@ -1,6 +1,11 @@ -use std::rc::Rc; +use std::sync::Arc; -use crate::world_gen::noise::perlin::{DoublePerlinNoiseParameters, DoublePerlinNoiseSampler}; +use pumpkin_core::random::{xoroshiro128::Xoroshiro, RandomGenerator, RandomImpl}; + +use crate::world_gen::noise::{ + clamped_lerp, + perlin::{DoublePerlinNoiseParameters, DoublePerlinNoiseSampler, OctavePerlinNoiseSampler}, +}; use super::{DensityFunction, DensityFunctionImpl}; @@ -10,6 +15,16 @@ pub(crate) struct InternalNoise<'a> { } impl<'a> InternalNoise<'a> { + pub(crate) fn new( + data: DoublePerlinNoiseParameters<'a>, + function: Option, + ) -> Self { + Self { + data, + sampler: function, + } + } + pub(crate) fn sample(&self, x: f64, y: f64, z: f64) -> f64 { match &self.sampler { Some(sampler) => sampler.sample(x, y, z), @@ -27,11 +42,21 @@ impl<'a> InternalNoise<'a> { #[derive(Clone)] pub struct NoiseFunction<'a> { - noise: Rc>, + noise: Arc>, xz_scale: f64, y_scale: f64, } +impl<'a> NoiseFunction<'a> { + pub fn new(noise: Arc>, xz_scale: f64, y_scale: f64) -> Self { + Self { + noise, + xz_scale, + y_scale, + } + } +} + impl<'a> DensityFunctionImpl<'a> for NoiseFunction<'a> { fn sample(&self, pos: &impl super::NoisePos) -> f64 { self.noise.sample( @@ -60,14 +85,34 @@ impl<'a> DensityFunctionImpl<'a> for NoiseFunction<'a> { #[derive(Clone)] pub struct ShiftedNoiseFunction<'a> { - shift_x: Rc>, - shift_y: Rc>, - shift_z: Rc>, - noise: Rc>, + shift_x: Arc>, + shift_y: Arc>, + shift_z: Arc>, + noise: Arc>, xz_scale: f64, y_scale: f64, } +impl<'a> ShiftedNoiseFunction<'a> { + pub fn new( + shift_x: Arc>, + shift_y: Arc>, + shift_z: Arc>, + xz_scale: f64, + y_scale: f64, + noise: Arc>, + ) -> Self { + Self { + shift_x, + shift_y, + shift_z, + noise, + xz_scale, + y_scale, + } + } +} + impl<'a> DensityFunctionImpl<'a> for ShiftedNoiseFunction<'a> { fn sample(&self, pos: &impl super::NoisePos) -> f64 { let d = pos.x() as f64 * self.xz_scale + self.shift_x.sample(pos); @@ -88,9 +133,9 @@ impl<'a> DensityFunctionImpl<'a> for ShiftedNoiseFunction<'a> { let new_noise = visitor.apply_internal_noise(self.noise.clone()); DensityFunction::ShiftedNoise(ShiftedNoiseFunction { - shift_x: Rc::new(new_x), - shift_y: Rc::new(new_y), - shift_z: Rc::new(new_z), + shift_x: Arc::new(new_x), + shift_y: Arc::new(new_y), + shift_z: Arc::new(new_z), xz_scale: self.xz_scale, y_scale: self.y_scale, noise: new_noise, @@ -105,3 +150,188 @@ impl<'a> DensityFunctionImpl<'a> for ShiftedNoiseFunction<'a> { -self.max() } } + +#[derive(Clone)] +pub struct InterpolatedNoiseSampler { + lower: Arc, + upper: Arc, + interpolation: Arc, + xz_scale_scaled: f64, + y_scale_scaled: f64, + xz_factor: f64, + y_factor: f64, + smear_scale: f64, + max_value: f64, + xz_scale: f64, + y_scale: f64, +} + +impl InterpolatedNoiseSampler { + fn create_from_random( + rand: &mut RandomGenerator, + xz_scale: f64, + y_scale: f64, + xz_factor: f64, + y_factor: f64, + smear_scale: f64, + ) -> Self { + let (start_1, amplitudes_1) = + OctavePerlinNoiseSampler::calculate_amplitudes(&(-15..=0).collect::>()); + + let (start_2, amplitudes_2) = + OctavePerlinNoiseSampler::calculate_amplitudes(&(-7..=0).collect::>()); + + Self::new( + OctavePerlinNoiseSampler::new(rand, start_1, &litudes_1), + OctavePerlinNoiseSampler::new(rand, start_1, &litudes_1), + OctavePerlinNoiseSampler::new(rand, start_2, &litudes_2), + xz_scale, + y_scale, + xz_factor, + y_factor, + smear_scale, + ) + } + + pub fn copy_with_random(&self, rand: &mut RandomGenerator) -> Self { + Self::create_from_random( + rand, + self.xz_scale, + self.y_scale, + self.xz_factor, + self.y_factor, + self.smear_scale, + ) + } + + pub fn create_base_3d_noise_function( + xz_scale: f64, + y_scale: f64, + xz_factor: f64, + y_factor: f64, + smear_scale: f64, + ) -> Self { + let mut rand = RandomGenerator::LegacyXoroshiro(Xoroshiro::from_seed(0)); + Self::create_from_random( + &mut rand, + xz_scale, + y_scale, + xz_factor, + y_factor, + smear_scale, + ) + } + + #[allow(clippy::too_many_arguments)] + fn new( + lower: OctavePerlinNoiseSampler, + upper: OctavePerlinNoiseSampler, + interpolation: OctavePerlinNoiseSampler, + xz_scale: f64, + y_scale: f64, + xz_factor: f64, + y_factor: f64, + smear_scale: f64, + ) -> Self { + let y_scale_scaled = 684.412f64 * y_scale; + let max_value = OctavePerlinNoiseSampler::get_total_amplitude( + y_scale_scaled + 2f64, + lower.persistence, + &lower.amplitudes, + ); + Self { + lower: Arc::new(lower), + upper: Arc::new(upper), + interpolation: Arc::new(interpolation), + xz_scale, + y_scale, + xz_factor, + y_factor, + smear_scale, + y_scale_scaled, + xz_scale_scaled: 684.412f64 * xz_scale, + max_value, + } + } +} + +impl<'a> DensityFunctionImpl<'a> for InterpolatedNoiseSampler { + fn sample(&self, pos: &impl super::NoisePos) -> f64 { + let d = pos.x() as f64 * self.xz_scale_scaled; + let e = pos.y() as f64 * self.y_scale_scaled; + let f = pos.z() as f64 * self.xz_scale_scaled; + + let g = d / self.xz_factor; + let h = e / self.y_factor; + let i = f / self.xz_factor; + + let j = self.y_scale_scaled * self.smear_scale; + let k = j / self.y_factor; + + let mut n = 0f64; + let mut o = 1f64; + + for p in 0..8 { + let sampler = self.interpolation.get_octave(p); + if let Some(sampler) = sampler { + n += sampler.sample_no_fade( + OctavePerlinNoiseSampler::maintain_precision(g * o), + OctavePerlinNoiseSampler::maintain_precision(h * o), + OctavePerlinNoiseSampler::maintain_precision(i * o), + k * o, + h * o, + ) / o; + } + + o /= 2f64; + } + + let q = (n / 10f64 + 1f64) / 2f64; + let bl2 = q >= 1f64; + let bl3 = q <= 0f64; + let mut o = 1f64; + let mut l = 0f64; + let mut m = 0f64; + + for r in 0..16 { + let s = OctavePerlinNoiseSampler::maintain_precision(d * o); + let t = OctavePerlinNoiseSampler::maintain_precision(e * o); + let u = OctavePerlinNoiseSampler::maintain_precision(f * o); + let v = j * o; + + if !bl2 { + let sampler = self.lower.get_octave(r); + if let Some(sampler) = sampler { + l += sampler.sample_no_fade(s, t, u, v, e * o) / o; + } + } + + if !bl3 { + let sampler = self.upper.get_octave(r); + if let Some(sampler) = sampler { + m += sampler.sample_no_fade(s, t, u, v, e * o) / o; + } + } + + o /= 2f64; + } + + clamped_lerp(l / 512f64, m / 512f64, q) / 128f64 + } + + fn max(&self) -> f64 { + self.max_value + } + + fn min(&self) -> f64 { + -self.max() + } + + fn fill(&self, densities: &[f64], applier: &impl super::Applier) -> Vec { + applier.fill(densities, self) + } + + fn apply(&'a self, visitor: &'a impl super::Visitor) -> DensityFunction<'a> { + visitor.apply(&DensityFunction::InterpolatedNoise(self.clone())) + } +} diff --git a/pumpkin-world/src/world_gen/noise/density/offset.rs b/pumpkin-world/src/world_gen/noise/density/offset.rs index 26e16cd84..684f57760 100644 --- a/pumpkin-world/src/world_gen/noise/density/offset.rs +++ b/pumpkin-world/src/world_gen/noise/density/offset.rs @@ -1,10 +1,16 @@ -use std::rc::Rc; +use std::sync::Arc; use super::{noise::InternalNoise, DensityFunction, DensityFunctionImpl, OffsetDensityFunction}; #[derive(Clone)] pub struct ShiftAFunction<'a> { - offset: Rc>, + offset: Arc>, +} + +impl<'a> ShiftAFunction<'a> { + pub fn new(offset: Arc>) -> Self { + Self { offset } + } } impl<'a> OffsetDensityFunction<'a> for ShiftAFunction<'a> { @@ -39,7 +45,13 @@ impl<'a> DensityFunctionImpl<'a> for ShiftAFunction<'a> { #[derive(Clone)] pub struct ShiftBFunction<'a> { - offset: Rc>, + offset: Arc>, +} + +impl<'a> ShiftBFunction<'a> { + pub fn new(offset: Arc>) -> Self { + Self { offset } + } } impl<'a> OffsetDensityFunction<'a> for ShiftBFunction<'a> { diff --git a/pumpkin-world/src/world_gen/noise/density/spline.rs b/pumpkin-world/src/world_gen/noise/density/spline.rs new file mode 100644 index 000000000..775898e73 --- /dev/null +++ b/pumpkin-world/src/world_gen/noise/density/spline.rs @@ -0,0 +1,293 @@ +use std::sync::Arc; + +use crate::world_gen::noise::lerp_32; + +use super::{DensityFunction, DensityFunctionImpl, NoisePos, Visitor}; + +pub enum SplineValue<'a> { + Spline(Spline<'a>), + Fixed(f32), +} + +impl<'a> SplineValue<'a> { + fn max(&self) -> f32 { + match self { + Self::Fixed(value) => *value, + Self::Spline(spline) => spline.max, + } + } + + fn min(&self) -> f32 { + match self { + Self::Fixed(value) => *value, + Self::Spline(spline) => spline.min, + } + } + + fn apply(&self, pos: &impl NoisePos) -> f32 { + match self { + Self::Fixed(value) => *value, + Self::Spline(spline) => spline.apply(pos), + } + } + + fn visit(&'a self, visitor: &'a impl Visitor) -> SplineValue<'a> { + match self { + Self::Fixed(val) => Self::Fixed(*val), + Self::Spline(spline) => Self::Spline(spline.visit(visitor)), + } + } +} + +#[derive(Clone)] +pub(crate) struct SplinePoint<'a> { + location: f32, + value: Arc>, + derivative: f32, +} + +#[derive(Clone)] +pub struct Spline<'a> { + function: DensityFunction<'a>, + points: Vec>, + min: f32, + max: f32, +} + +impl<'a> Spline<'a> { + fn sample_outside_range(point: f32, value: f32, points: &[SplinePoint], i: usize) -> f32 { + let f = points[i].derivative; + if f == 0f32 { + value + } else { + value + f * (point - points[i].location) + } + } + + fn find_range_for_location(locations: &[f32], x: f32) -> i32 { + locations.partition_point(|val| x < *val) as i32 - 1 + } + + pub fn new(function: DensityFunction<'a>, points: &[SplinePoint<'a>]) -> Self { + let i = points.len() - 1; + let mut f = f32::INFINITY; + let mut g = f32::NEG_INFINITY; + + let h = function.min() as f32; + let j = function.max() as f32; + + if h < points[0].location { + let k = Self::sample_outside_range(h, points[0].value.min(), points, 0); + let l = Self::sample_outside_range(h, points[0].value.max(), points, 0); + + f = f.min(k.min(l)); + g = f.max(k.max(l)); + } + + if j > points[i].location { + let k = Self::sample_outside_range(j, points[i].value.min(), points, i); + let l = Self::sample_outside_range(j, points[i].value.max(), points, i); + + f = f.min(k.min(l)); + g = g.max(k.max(l)); + } + + for point in points { + f = f.min(point.value.min()); + g = g.max(point.value.max()); + } + + for m in 0..i { + let l = points[m].location; + let n = points[m + 1].location; + let o = n - l; + + let spline2 = &points[m].value; + let spline3 = &points[m + 1].value; + + let p = spline2.min(); + let q = spline2.max(); + let r = spline3.min(); + let s = spline3.max(); + let t = points[m].derivative; + let u = points[m + 1].derivative; + + if t != 0f32 || u != 0f32 { + let v = t * o; + let w = u * o; + + let x = p.min(r); + let y = q.max(s); + + let z = v - s + p; + let aa = v - r + q; + let ab = -w + r - q; + let ac = -w + s - p; + let ad = z.min(ab); + let ae = aa.max(ac); + + f = f.min(x + 0.25f32 * ad); + g = g.max(y + 0.25f32 * ae); + } + } + + Self { + function, + points: points.to_vec(), + min: f, + max: g, + } + } + + pub fn apply(&self, pos: &impl NoisePos) -> f32 { + let f = self.function.sample(pos) as f32; + let i = Self::find_range_for_location( + self.points + .iter() + .map(|p| p.location) + .collect::>() + .as_ref(), + f, + ); + let j = self.points.len() - 1; + + if i < 0 { + Self::sample_outside_range(f, self.points[0].value.apply(pos), &self.points, 0) + } else if i == j as i32 { + Self::sample_outside_range(f, self.points[j].value.apply(pos), &self.points, j) + } else { + let point_1 = &self.points[i as usize]; + let point_2 = &self.points[i as usize + 1]; + let k = (f - point_1.location) / (point_2.location - point_1.location); + + let n = point_1.value.apply(pos); + let o = point_2.value.apply(pos); + + let p = point_1.derivative * (point_2.location - point_1.location) - (o - n); + let q = -point_2.derivative * (point_2.location - point_1.location) + (o - n); + lerp_32(k, n, o) + k * (1f32 - k) * lerp_32(k, p, q) + } + } + + pub fn visit(&'a self, visitor: &'a impl Visitor) -> Spline<'a> { + let new_function = visitor.apply(&self.function); + let new_points = self + .points + .iter() + .map(|point| SplinePoint { + location: point.location, + derivative: point.derivative, + value: Arc::new(point.value.visit(visitor)), + }) + .collect::>(); + Self::new(new_function, &new_points) + } +} + +#[derive(Clone)] +pub struct SplineFunction<'a> { + spline: Arc>, +} + +impl<'a> SplineFunction<'a> { + pub fn new(spline: Arc>) -> Self { + Self { spline } + } +} + +impl<'a> DensityFunctionImpl<'a> for SplineFunction<'a> { + fn sample(&self, pos: &impl NoisePos) -> f64 { + self.spline.apply(pos) as f64 + } + + fn fill(&self, densities: &[f64], applier: &impl super::Applier) -> Vec { + applier.fill(densities, self) + } + + fn apply(&'a self, visitor: &'a impl Visitor) -> DensityFunction<'a> { + let new_spline = self.spline.visit(visitor); + DensityFunction::Spline(SplineFunction { + spline: Arc::new(new_spline), + }) + } + + fn max(&self) -> f64 { + self.spline.max as f64 + } + + fn min(&self) -> f64 { + self.spline.min as f64 + } +} + +#[derive(Clone)] +pub enum FloatAmplifier { + Identity, + Amplifier, +} + +impl FloatAmplifier { + #[inline] + pub fn apply(&self, f: f32) -> f32 { + match self { + Self::Identity => f, + Self::Amplifier => { + if f < 0f32 { + f + } else { + f * 2f32 + } + } + } + } +} +pub struct SplineBuilder<'a> { + function: DensityFunction<'a>, + amplifier: FloatAmplifier, + points: Vec>, +} + +impl<'a> SplineBuilder<'a> { + pub fn new(function: DensityFunction<'a>, amplifier: FloatAmplifier) -> Self { + Self { + function, + amplifier, + points: Vec::new(), + } + } + + #[must_use] + pub fn add_value(&mut self, location: f32, value: f32, derivative: f32) -> &mut Self { + self.add_spline( + location, + SplineValue::Fixed(self.amplifier.apply(value)), + derivative, + ) + } + + #[must_use] + pub fn add_spline( + &mut self, + location: f32, + value: SplineValue<'a>, + derivative: f32, + ) -> &mut Self { + if let Some(last) = self.points.last() { + if location <= last.location { + panic!("Points must be in asscending order"); + } + } + + self.points.push(SplinePoint { + location, + value: Arc::new(value), + derivative, + }); + + self + } + + pub fn build(&self) -> Spline<'a> { + Spline::new(self.function.clone(), &self.points) + } +} diff --git a/pumpkin-world/src/world_gen/noise/density/unary.rs b/pumpkin-world/src/world_gen/noise/density/unary.rs index 17fa123b9..b9b7cc617 100644 --- a/pumpkin-world/src/world_gen/noise/density/unary.rs +++ b/pumpkin-world/src/world_gen/noise/density/unary.rs @@ -1,10 +1,10 @@ -use std::rc::Rc; +use std::sync::Arc; use super::{DensityFunction, DensityFunctionImpl, UnaryDensityFunction}; #[derive(Clone)] pub struct ClampFunction<'a> { - pub(crate) input: Rc>, + pub(crate) input: Arc>, pub(crate) min: f64, pub(crate) max: f64, } @@ -22,7 +22,7 @@ impl<'a> UnaryDensityFunction<'a> for ClampFunction<'a> { impl<'a> DensityFunctionImpl<'a> for ClampFunction<'a> { fn apply(&'a self, visitor: &'a impl super::Visitor) -> DensityFunction<'a> { DensityFunction::Clamp(ClampFunction { - input: Rc::new(self.input().apply(visitor)), + input: Arc::new(self.input().apply(visitor)), min: self.min, max: self.max, }) @@ -59,13 +59,13 @@ pub(crate) enum UnaryType { #[derive(Clone)] pub struct UnaryFunction<'a> { action: UnaryType, - input: Rc>, + input: Arc>, min: f64, max: f64, } impl<'a> UnaryFunction<'a> { - pub(crate) fn create(action: UnaryType, input: Rc>) -> UnaryFunction { + pub(crate) fn create(action: UnaryType, input: Arc>) -> UnaryFunction { let base_min = input.min(); let new_min = Self::internal_apply(&action, base_min); let new_max = Self::internal_apply(&action, input.max()); @@ -133,7 +133,7 @@ impl<'a> DensityFunctionImpl<'a> for UnaryFunction<'a> { } fn apply(&'a self, visitor: &'a impl super::Visitor) -> DensityFunction<'a> { - let raw = Self::create(self.action.clone(), Rc::new(self.input().apply(visitor))); + let raw = Self::create(self.action.clone(), Arc::new(self.input().apply(visitor))); DensityFunction::Unary(raw) } diff --git a/pumpkin-world/src/world_gen/noise/mod.rs b/pumpkin-world/src/world_gen/noise/mod.rs index c5a8de241..e97f8df27 100644 --- a/pumpkin-world/src/world_gen/noise/mod.rs +++ b/pumpkin-world/src/world_gen/noise/mod.rs @@ -1,146 +1,144 @@ #![allow(dead_code)] -mod density; +pub mod density; mod perlin; mod simplex; pub mod builtin_noise_params { - use lazy_static::lazy_static; + use std::sync::LazyLock; use super::perlin::DoublePerlinNoiseParameters; - lazy_static! { - pub static ref temperature: DoublePerlinNoiseParameters<'static> = - DoublePerlinNoiseParameters::new(-10, &[1.5f64, 0f64, 1f64, 0f64, 0f64, 0f64,],); - pub static ref vegetation: DoublePerlinNoiseParameters<'static> = - DoublePerlinNoiseParameters::new(-8, &[1f64, 1f64, 0f64, 0f64, 0f64, 0f64,],); - pub static ref continentalness: DoublePerlinNoiseParameters<'static> = + + pub static TEMPERATURE: LazyLock> = LazyLock::new(|| { + DoublePerlinNoiseParameters::new(-10, &[1.5f64, 0f64, 1f64, 0f64, 0f64, 0f64]) + }); + pub static VEGETATION: LazyLock> = LazyLock::new(|| { + DoublePerlinNoiseParameters::new(-8, &[1f64, 1f64, 0f64, 0f64, 0f64, 0f64]) + }); + pub static CONTINENTALNESS: LazyLock> = + LazyLock::new(|| { DoublePerlinNoiseParameters::new( -9, - &[1f64, 1f64, 2f64, 2f64, 2f64, 1f64, 1f64, 1f64, 1f64,], - ); - pub static ref erosion: DoublePerlinNoiseParameters<'static> = - DoublePerlinNoiseParameters::new(-9, &[1f64, 1f64, 0f64, 1f64, 1f64,],); - pub static ref temperature_large: DoublePerlinNoiseParameters<'static> = - DoublePerlinNoiseParameters::new(-12, &[1.5f64, 0f64, 1f64, 0f64, 0f64, 0f64,],); - pub static ref vegetation_large: DoublePerlinNoiseParameters<'static> = - DoublePerlinNoiseParameters::new(-10, &[1f64, 1f64, 0f64, 0f64, 0f64, 0f64,],); - pub static ref continentalness_large: DoublePerlinNoiseParameters<'static> = + &[1f64, 1f64, 2f64, 2f64, 2f64, 1f64, 1f64, 1f64, 1f64], + ) + }); + pub static EROSION: LazyLock> = + LazyLock::new(|| DoublePerlinNoiseParameters::new(-9, &[1f64, 1f64, 0f64, 1f64, 1f64])); + pub static TEMPERATURE_LARGE: LazyLock> = + LazyLock::new(|| { + DoublePerlinNoiseParameters::new(-12, &[1.5f64, 0f64, 1f64, 0f64, 0f64, 0f64]) + }); + pub static VEGETATION_LARGE: LazyLock> = + LazyLock::new(|| { + DoublePerlinNoiseParameters::new(-10, &[1f64, 1f64, 0f64, 0f64, 0f64, 0f64]) + }); + pub static CONTINENTALNESS_LARGE: LazyLock> = + LazyLock::new(|| { DoublePerlinNoiseParameters::new( -11, - &[1f64, 1f64, 2f64, 2f64, 2f64, 1f64, 1f64, 1f64, 1f64,], - ); - pub static ref erosion_large: DoublePerlinNoiseParameters<'static> = - DoublePerlinNoiseParameters::new(-11, &[1f64, 1f64, 0f64, 1f64, 1f64,],); - pub static ref ridge: DoublePerlinNoiseParameters<'static> = - DoublePerlinNoiseParameters::new(-7, &[1f64, 2f64, 1f64, 0f64, 0f64, 0f64],); - pub static ref offset: DoublePerlinNoiseParameters<'static> = - DoublePerlinNoiseParameters::new(-3, &[1f64; 4],); - pub static ref aquifer_barrier: DoublePerlinNoiseParameters<'static> = - DoublePerlinNoiseParameters::new(-3, &[1f64,],); - pub static ref aquifer_barrier_floodedness: DoublePerlinNoiseParameters<'static> = - DoublePerlinNoiseParameters::new(-7, &[1f64,],); - pub static ref aquifer_lava: DoublePerlinNoiseParameters<'static> = - DoublePerlinNoiseParameters::new(-1, &[1f64,],); - pub static ref aquifer_fluid_level_spread: DoublePerlinNoiseParameters<'static> = - DoublePerlinNoiseParameters::new(-5, &[1f64,],); - pub static ref pillar: DoublePerlinNoiseParameters<'static> = - DoublePerlinNoiseParameters::new(-7, &[1f64; 2],); - pub static ref pillar_rareness: DoublePerlinNoiseParameters<'static> = - DoublePerlinNoiseParameters::new(-8, &[1f64,],); - pub static ref pillar_thickness: DoublePerlinNoiseParameters<'static> = - DoublePerlinNoiseParameters::new(-8, &[1f64,],); - pub static ref spaghetti_2d: DoublePerlinNoiseParameters<'static> = - DoublePerlinNoiseParameters::new(-7, &[1f64,],); - pub static ref spaghetti_2d_elevation: DoublePerlinNoiseParameters<'static> = - DoublePerlinNoiseParameters::new(-8, &[1f64,],); - pub static ref spaghetti_2d_modulator: DoublePerlinNoiseParameters<'static> = - DoublePerlinNoiseParameters::new(-11, &[1f64,],); - pub static ref spaghetti_2d_thickness: DoublePerlinNoiseParameters<'static> = - DoublePerlinNoiseParameters::new(-11, &[1f64,],); - pub static ref spaghetti_3d_1: DoublePerlinNoiseParameters<'static> = - DoublePerlinNoiseParameters::new(-7, &[1f64,],); - pub static ref spaghetti_3d_2: DoublePerlinNoiseParameters<'static> = - DoublePerlinNoiseParameters::new(-7, &[1f64,],); - pub static ref spaghetti_3d_rarity: DoublePerlinNoiseParameters<'static> = - DoublePerlinNoiseParameters::new(-11, &[1f64,],); - pub static ref spaghetti_3d_thickness: DoublePerlinNoiseParameters<'static> = - DoublePerlinNoiseParameters::new(-8, &[1f64,],); - pub static ref spaghetti_roughness: DoublePerlinNoiseParameters<'static> = - DoublePerlinNoiseParameters::new(-5, &[1f64,],); - pub static ref spaghetti_roughness_modulator: DoublePerlinNoiseParameters<'static> = - DoublePerlinNoiseParameters::new(-8, &[1f64,],); - pub static ref cave_entrance: DoublePerlinNoiseParameters<'static> = - DoublePerlinNoiseParameters::new(-7, &[0.4f64, 0.5f64, 1f64],); - pub static ref cave_layer: DoublePerlinNoiseParameters<'static> = - DoublePerlinNoiseParameters::new(-8, &[1f64,],); - pub static ref cave_cheese: DoublePerlinNoiseParameters<'static> = - DoublePerlinNoiseParameters::new( - -8, - &[0.5f64, 1f64, 2f64, 1f64, 2f64, 1f64, 0f64, 2f64, 0f64,], - ); - pub static ref ore_veininess: DoublePerlinNoiseParameters<'static> = - DoublePerlinNoiseParameters::new(-8, &[1f64,],); - pub static ref ore_vein_a: DoublePerlinNoiseParameters<'static> = - DoublePerlinNoiseParameters::new(-7, &[1f64,],); - pub static ref ore_vein_b: DoublePerlinNoiseParameters<'static> = - DoublePerlinNoiseParameters::new(-7, &[1f64,],); - pub static ref ore_gap: DoublePerlinNoiseParameters<'static> = - DoublePerlinNoiseParameters::new(-5, &[1f64,],); - pub static ref noodle: DoublePerlinNoiseParameters<'static> = - DoublePerlinNoiseParameters::new(-8, &[1f64,],); - pub static ref noodle_thickness: DoublePerlinNoiseParameters<'static> = - DoublePerlinNoiseParameters::new(-8, &[1f64,],); - pub static ref noodle_ridge_a: DoublePerlinNoiseParameters<'static> = - DoublePerlinNoiseParameters::new(-7, &[1f64,],); - pub static ref noodle_ridge_b: DoublePerlinNoiseParameters<'static> = - DoublePerlinNoiseParameters::new(-7, &[1f64,],); - pub static ref jagged: DoublePerlinNoiseParameters<'static> = - DoublePerlinNoiseParameters::new(-16, &[1f64; 16],); - pub static ref surface: DoublePerlinNoiseParameters<'static> = - DoublePerlinNoiseParameters::new(-6, &[1f64; 3],); - pub static ref surface_secondary: DoublePerlinNoiseParameters<'static> = - DoublePerlinNoiseParameters::new(-6, &[1f64, 1f64, 0f64, 1f64,],); - pub static ref clay_bands_offset: DoublePerlinNoiseParameters<'static> = - DoublePerlinNoiseParameters::new(-8, &[1f64,],); - pub static ref badlands_pillar: DoublePerlinNoiseParameters<'static> = - DoublePerlinNoiseParameters::new(-2, &[1f64; 4],); - pub static ref badlands_pillar_roof: DoublePerlinNoiseParameters<'static> = - DoublePerlinNoiseParameters::new(-8, &[1f64,],); - pub static ref badlands_surface: DoublePerlinNoiseParameters<'static> = - DoublePerlinNoiseParameters::new(-6, &[1f64; 3],); - pub static ref iceberg_pillar: DoublePerlinNoiseParameters<'static> = - DoublePerlinNoiseParameters::new(-6, &[1f64; 4],); - pub static ref iceberg_pillar_roof: DoublePerlinNoiseParameters<'static> = - DoublePerlinNoiseParameters::new(-3, &[1f64,],); - pub static ref iceberg_surface: DoublePerlinNoiseParameters<'static> = - DoublePerlinNoiseParameters::new(-6, &[1f64; 3],); - pub static ref surface_swamp: DoublePerlinNoiseParameters<'static> = - DoublePerlinNoiseParameters::new(-2, &[1f64,],); - pub static ref calcite: DoublePerlinNoiseParameters<'static> = - DoublePerlinNoiseParameters::new(-9, &[1f64; 4],); - pub static ref gravel: DoublePerlinNoiseParameters<'static> = - DoublePerlinNoiseParameters::new(-8, &[1f64; 4],); - pub static ref powder_snow: DoublePerlinNoiseParameters<'static> = - DoublePerlinNoiseParameters::new(-6, &[1f64; 4],); - pub static ref packed_ice: DoublePerlinNoiseParameters<'static> = - DoublePerlinNoiseParameters::new(-7, &[1f64; 4],); - pub static ref ice: DoublePerlinNoiseParameters<'static> = - DoublePerlinNoiseParameters::new(-4, &[1f64; 4],); - pub static ref soul_sand_layer: DoublePerlinNoiseParameters<'static> = - DoublePerlinNoiseParameters::new( - -8, - &[ - 1f64, - 1f64, - 1f64, - 1f64, - 0f64, - 0f64, - 0f64, - 0f64, - 0.013333333333333334f64, - ], - ); - pub static ref gravel_layer: DoublePerlinNoiseParameters<'static> = + &[1f64, 1f64, 2f64, 2f64, 2f64, 1f64, 1f64, 1f64, 1f64], + ) + }); + pub static EROSION_LARGE: LazyLock> = + LazyLock::new(|| DoublePerlinNoiseParameters::new(-11, &[1f64, 1f64, 0f64, 1f64, 1f64])); + pub static RIDGE: LazyLock> = LazyLock::new(|| { + DoublePerlinNoiseParameters::new(-7, &[1f64, 2f64, 1f64, 0f64, 0f64, 0f64]) + }); + pub static OFFSET: LazyLock> = + LazyLock::new(|| DoublePerlinNoiseParameters::new(-3, &[1f64; 4])); + pub static AQUIFER_BARRIER: LazyLock> = + LazyLock::new(|| DoublePerlinNoiseParameters::new(-3, &[1f64])); + pub static AQUIFER_BARRIER_FLOODEDNESS: LazyLock> = + LazyLock::new(|| DoublePerlinNoiseParameters::new(-7, &[1f64])); + pub static AQUIFER_LAVA: LazyLock> = + LazyLock::new(|| DoublePerlinNoiseParameters::new(-1, &[1f64])); + pub static AQUIFER_FLUID_LEVEL_SPREAD: LazyLock> = + LazyLock::new(|| DoublePerlinNoiseParameters::new(-5, &[1f64])); + pub static PILLAR: LazyLock> = + LazyLock::new(|| DoublePerlinNoiseParameters::new(-7, &[1f64; 2])); + pub static PILLAR_RARENESS: LazyLock> = + LazyLock::new(|| DoublePerlinNoiseParameters::new(-8, &[1f64])); + pub static PILLAR_THICKNESS: LazyLock> = + LazyLock::new(|| DoublePerlinNoiseParameters::new(-8, &[1f64])); + pub static SPAGHETTI_2D: LazyLock> = + LazyLock::new(|| DoublePerlinNoiseParameters::new(-7, &[1f64])); + pub static SPAGHETTI_2D_ELEVATION: LazyLock> = + LazyLock::new(|| DoublePerlinNoiseParameters::new(-8, &[1f64])); + pub static SPAGHETTI_2D_MODULATOR: LazyLock> = + LazyLock::new(|| DoublePerlinNoiseParameters::new(-11, &[1f64])); + pub static SPAGHETTI_2D_THICKNESS: LazyLock> = + LazyLock::new(|| DoublePerlinNoiseParameters::new(-11, &[1f64])); + pub static SPAGHETTI_3D_1: LazyLock> = + LazyLock::new(|| DoublePerlinNoiseParameters::new(-7, &[1f64])); + pub static SPAGHETTI_3D_2: LazyLock> = + LazyLock::new(|| DoublePerlinNoiseParameters::new(-7, &[1f64])); + pub static SPAGHETTI_3D_RARITY: LazyLock> = + LazyLock::new(|| DoublePerlinNoiseParameters::new(-11, &[1f64])); + pub static SPAGHETTI_3D_THICKNESS: LazyLock> = + LazyLock::new(|| DoublePerlinNoiseParameters::new(-8, &[1f64])); + pub static SPAGHETTI_ROUGHNESS: LazyLock> = + LazyLock::new(|| DoublePerlinNoiseParameters::new(-5, &[1f64])); + pub static SPAGHETTI_ROUGHNESS_MODULATOR: LazyLock> = + LazyLock::new(|| DoublePerlinNoiseParameters::new(-8, &[1f64])); + pub static CAVE_ENTRANCE: LazyLock> = + LazyLock::new(|| DoublePerlinNoiseParameters::new(-7, &[0.4f64, 0.5f64, 1f64])); + pub static CAVE_LAYER: LazyLock> = + LazyLock::new(|| DoublePerlinNoiseParameters::new(-8, &[1f64])); + pub static CAVE_CHEESE: LazyLock> = LazyLock::new(|| { + DoublePerlinNoiseParameters::new( + -8, + &[0.5f64, 1f64, 2f64, 1f64, 2f64, 1f64, 0f64, 2f64, 0f64], + ) + }); + pub static ORE_VEININESS: LazyLock> = + LazyLock::new(|| DoublePerlinNoiseParameters::new(-8, &[1f64])); + pub static ORE_VEIN_A: LazyLock> = + LazyLock::new(|| DoublePerlinNoiseParameters::new(-7, &[1f64])); + pub static ORE_VEIN_B: LazyLock> = + LazyLock::new(|| DoublePerlinNoiseParameters::new(-7, &[1f64])); + pub static ORE_GAP: LazyLock> = + LazyLock::new(|| DoublePerlinNoiseParameters::new(-5, &[1f64])); + pub static NOODLE: LazyLock> = + LazyLock::new(|| DoublePerlinNoiseParameters::new(-8, &[1f64])); + pub static NOODLE_THICKNESS: LazyLock> = + LazyLock::new(|| DoublePerlinNoiseParameters::new(-8, &[1f64])); + pub static NOODLE_RIDGE_A: LazyLock> = + LazyLock::new(|| DoublePerlinNoiseParameters::new(-7, &[1f64])); + pub static NOODLE_RIDGE_B: LazyLock> = + LazyLock::new(|| DoublePerlinNoiseParameters::new(-7, &[1f64])); + pub static JAGGED: LazyLock> = + LazyLock::new(|| DoublePerlinNoiseParameters::new(-16, &[1f64; 16])); + pub static SURFACE: LazyLock> = + LazyLock::new(|| DoublePerlinNoiseParameters::new(-6, &[1f64; 3])); + pub static SURFACE_SECONDARY: LazyLock> = + LazyLock::new(|| DoublePerlinNoiseParameters::new(-6, &[1f64, 1f64, 0f64, 1f64])); + pub static CLAY_BANDS_OFFSET: LazyLock> = + LazyLock::new(|| DoublePerlinNoiseParameters::new(-8, &[1f64])); + pub static BADLANDS_PILLAR: LazyLock> = + LazyLock::new(|| DoublePerlinNoiseParameters::new(-2, &[1f64; 4])); + pub static BADLANDS_PILLAR_ROOF: LazyLock> = + LazyLock::new(|| DoublePerlinNoiseParameters::new(-8, &[1f64])); + pub static BADLANDS_SURFACE: LazyLock> = + LazyLock::new(|| DoublePerlinNoiseParameters::new(-6, &[1f64; 3])); + pub static ICEBERG_PILLAR: LazyLock> = + LazyLock::new(|| DoublePerlinNoiseParameters::new(-6, &[1f64; 4])); + pub static ICEBERG_PILLAR_ROOF: LazyLock> = + LazyLock::new(|| DoublePerlinNoiseParameters::new(-3, &[1f64])); + pub static ICEBERG_SURFACE: LazyLock> = + LazyLock::new(|| DoublePerlinNoiseParameters::new(-6, &[1f64; 3])); + pub static SURFACE_SWAMP: LazyLock> = + LazyLock::new(|| DoublePerlinNoiseParameters::new(-2, &[1f64])); + pub static CALCITE: LazyLock> = + LazyLock::new(|| DoublePerlinNoiseParameters::new(-9, &[1f64; 4])); + pub static GRAVEL: LazyLock> = + LazyLock::new(|| DoublePerlinNoiseParameters::new(-8, &[1f64; 4])); + pub static POWDER_SNOW: LazyLock> = + LazyLock::new(|| DoublePerlinNoiseParameters::new(-6, &[1f64; 4])); + pub static PACKED_ICE: LazyLock> = + LazyLock::new(|| DoublePerlinNoiseParameters::new(-7, &[1f64; 4])); + pub static ICE: LazyLock> = + LazyLock::new(|| DoublePerlinNoiseParameters::new(-4, &[1f64; 4])); + pub static SOUL_SAND_LAYER: LazyLock> = + LazyLock::new(|| { DoublePerlinNoiseParameters::new( -8, &[ @@ -154,25 +152,64 @@ pub mod builtin_noise_params { 0f64, 0.013333333333333334f64, ], - ); - pub static ref patch: DoublePerlinNoiseParameters<'static> = - DoublePerlinNoiseParameters::new( - -5, - &[1f64, 0f64, 0f64, 0f64, 0f64, 0.013333333333333334f64,], - ); - pub static ref netherrack: DoublePerlinNoiseParameters<'static> = - DoublePerlinNoiseParameters::new(-3, &[1f64, 0f64, 0f64, 0.35f64,],); - pub static ref nether_wart: DoublePerlinNoiseParameters<'static> = - DoublePerlinNoiseParameters::new(-3, &[1f64, 0f64, 0f64, 0.9f64,],); - pub static ref nether_state_selector: DoublePerlinNoiseParameters<'static> = - DoublePerlinNoiseParameters::new(-4, &[1f64,],); - } + ) + }); + pub static GRAVEL_LAYER: LazyLock> = LazyLock::new(|| { + DoublePerlinNoiseParameters::new( + -8, + &[ + 1f64, + 1f64, + 1f64, + 1f64, + 0f64, + 0f64, + 0f64, + 0f64, + 0.013333333333333334f64, + ], + ) + }); + pub static PATCH: LazyLock> = LazyLock::new(|| { + DoublePerlinNoiseParameters::new( + -5, + &[1f64, 0f64, 0f64, 0f64, 0f64, 0.013333333333333334f64], + ) + }); + pub static NETHERRACK: LazyLock> = + LazyLock::new(|| DoublePerlinNoiseParameters::new(-3, &[1f64, 0f64, 0f64, 0.35f64])); + pub static NETHER_WART: LazyLock> = + LazyLock::new(|| DoublePerlinNoiseParameters::new(-3, &[1f64, 0f64, 0f64, 0.9f64])); + pub static NETHER_STATE_SELECTOR: LazyLock> = + LazyLock::new(|| DoublePerlinNoiseParameters::new(-4, &[1f64])); +} + +pub fn lerp_32(delta: f32, start: f32, end: f32) -> f32 { + start + delta * (end - start) } pub fn lerp(delta: f64, start: f64, end: f64) -> f64 { start + delta * (end - start) } +pub fn lerp_progress(value: f64, start: f64, end: f64) -> f64 { + (value - start) / (end - start) +} + +pub fn clamped_lerp(start: f64, end: f64, delta: f64) -> f64 { + if delta < 0f64 { + start + } else if delta > 1f64 { + end + } else { + lerp(delta, start, end) + } +} + +pub fn clamped_map(value: f64, old_start: f64, old_end: f64, new_start: f64, new_end: f64) -> f64 { + clamped_lerp(new_start, new_end, lerp_progress(value, old_start, old_end)) +} + pub fn lerp2(delta_x: f64, delta_y: f64, x0y0: f64, x1y0: f64, x0y1: f64, x1y1: f64) -> f64 { lerp( delta_y, diff --git a/pumpkin-world/src/world_gen/noise/perlin.rs b/pumpkin-world/src/world_gen/noise/perlin.rs index e30f6bf00..74dcec723 100644 --- a/pumpkin-world/src/world_gen/noise/perlin.rs +++ b/pumpkin-world/src/world_gen/noise/perlin.rs @@ -152,15 +152,25 @@ impl PerlinNoiseSampler { pub struct OctavePerlinNoiseSampler { octave_samplers: Vec>, - amplitudes: Vec, + pub(crate) amplitudes: Vec, first_octave: i32, - persistence: f64, + pub(crate) persistence: f64, lacunarity: f64, max_value: f64, } impl OctavePerlinNoiseSampler { - fn get_total_amplitude(scale: f64, persistence: f64, amplitudes: &[f64]) -> f64 { + pub(crate) fn get_octave(&self, octave: i32) -> Option<&PerlinNoiseSampler> { + match self + .octave_samplers + .get(self.octave_samplers.len() - 1 - octave as usize) + { + Some(octave) => octave.as_ref(), + None => None, + } + } + + pub(crate) fn get_total_amplitude(scale: f64, persistence: f64, amplitudes: &[f64]) -> f64 { let mut d = 0f64; let mut e = persistence; @@ -172,7 +182,7 @@ impl OctavePerlinNoiseSampler { d } - fn maintain_precision(value: f64) -> f64 { + pub fn maintain_precision(value: f64) -> f64 { value - (value / 3.3554432E7f64 + 0.5f64).floor() * 3.3554432E7f64 } @@ -217,6 +227,37 @@ impl OctavePerlinNoiseSampler { } } } + RandomGenerator::LegacyXoroshiro(random) => { + let sampler = PerlinNoiseSampler::new(random); + if j >= 0 && j < i as i32 { + let d = amplitudes[j as usize]; + if d != 0f64 { + samplers[j as usize] = Some(sampler); + } + } + + for kx in (0..j as usize).rev() { + if kx < i { + let e = amplitudes[kx]; + if e != 0f64 { + samplers[kx] = Some(PerlinNoiseSampler::new(random)); + } else { + random.skip(262); + } + } else { + random.skip(262); + } + } + + if let Ok(length1) = samplers.iter().filter(|x| x.is_some()).try_len() { + if let Ok(length2) = amplitudes.iter().filter(|x| !x.is_zero()).try_len() { + assert_eq!(length1, length2); + } + } + assert!(j >= i as i32 - 1); + } + // TODO: This is exactly the same code as LegacyXoroshiro path + // Is there a way to combine somehow? RandomGenerator::Legacy(random) => { let sampler = PerlinNoiseSampler::new(random); if j >= 0 && j < i as i32 { @@ -286,6 +327,7 @@ impl OctavePerlinNoiseSampler { } } +#[derive(Clone)] pub struct DoublePerlinNoiseParameters<'a> { first_octave: i32, amplitudes: &'a [f64], From 81a263180c69f9a010dce4c2e05c62593589faf0 Mon Sep 17 00:00:00 2001 From: kralverde Date: Thu, 19 Sep 2024 00:16:14 -0400 Subject: [PATCH 03/11] add rest of noise functions --- .../src/world_gen/noise/density/end.rs | 73 ++ .../src/world_gen/noise/density/mod.rs | 645 ++++++++++++++++-- .../src/world_gen/noise/density/noise.rs | 2 +- .../src/world_gen/noise/density/weird.rs | 109 +++ pumpkin-world/src/world_gen/noise/simplex.rs | 1 + 5 files changed, 781 insertions(+), 49 deletions(-) create mode 100644 pumpkin-world/src/world_gen/noise/density/end.rs create mode 100644 pumpkin-world/src/world_gen/noise/density/weird.rs diff --git a/pumpkin-world/src/world_gen/noise/density/end.rs b/pumpkin-world/src/world_gen/noise/density/end.rs new file mode 100644 index 000000000..c69ee8f38 --- /dev/null +++ b/pumpkin-world/src/world_gen/noise/density/end.rs @@ -0,0 +1,73 @@ +use pumpkin_core::random::{legacy_rand::LegacyRand, RandomImpl}; + +use crate::world_gen::noise::simplex::SimplexNoiseSampler; + +use super::{DensityFunction, DensityFunctionImpl}; + +#[derive(Clone)] +pub struct EndIslandFunction { + sampler: SimplexNoiseSampler, +} + +impl EndIslandFunction { + pub fn new(seed: u64) -> Self { + let mut rand = LegacyRand::from_seed(seed); + rand.skip(17292); + Self { + sampler: SimplexNoiseSampler::new(&mut rand), + } + } + + fn sample_2d(sampler: &SimplexNoiseSampler, x: i32, z: i32) -> f32 { + let i = x / 2; + let j = z / 2; + let k = x % 2; + let l = z % 2; + + let f = 100f32 - ((x * x + z * z) as f32).sqrt() * 8f32; + let mut f = f.clamp(-100f32, 80f32); + + for m in -12..=12 { + for n in -12..=12 { + let o = (i + m) as i64; + let p = (j + n) as i64; + + if (o * o + p * p) > 4096i64 + && sampler.sample_2d(o as f64, p as f64) < -0.9f32 as f64 + { + let g = ((o as f32).abs() * 3439f32 + (p as f32).abs() * 147f32) % 13f32 + 9f32; + let h = (k - m * 2) as f32; + let q = (l - n * 2) as f32; + let r = 100f32 - (h * h + q * q).sqrt() * g; + let s = r.clamp(-100f32, 80f32); + + f = f.max(s); + } + } + } + + f + } +} + +impl<'a> DensityFunctionImpl<'a> for EndIslandFunction { + fn fill(&self, densities: &[f64], applier: &impl super::Applier) -> Vec { + applier.fill(densities, self) + } + + fn sample(&self, pos: &impl super::NoisePos) -> f64 { + (Self::sample_2d(&self.sampler, pos.x() / 8, pos.z() / 8) as f64 - 8f64) / 128f64 + } + + fn min(&self) -> f64 { + -0.84375f64 + } + + fn max(&self) -> f64 { + 0.5625f64 + } + + fn apply(&'a self, visitor: &'a impl super::Visitor) -> super::DensityFunction<'a> { + visitor.apply(&DensityFunction::EndIsland(self.clone())) + } +} diff --git a/pumpkin-world/src/world_gen/noise/density/mod.rs b/pumpkin-world/src/world_gen/noise/density/mod.rs index 2f55f5c3a..c121e3134 100644 --- a/pumpkin-world/src/world_gen/noise/density/mod.rs +++ b/pumpkin-world/src/world_gen/noise/density/mod.rs @@ -1,22 +1,26 @@ use std::sync::Arc; use blend::{BlendAlphaFunction, BlendDensityFunction, BlendOffsetFunction}; +use end::EndIslandFunction; use math::{BinaryFunction, BinaryType, LinearFunction}; use noise::{InternalNoise, InterpolatedNoiseSampler, NoiseFunction, ShiftedNoiseFunction}; use offset::{ShiftAFunction, ShiftBFunction}; use spline::SplineFunction; use unary::{ClampFunction, UnaryFunction, UnaryType}; +use weird::WierdScaledFunction; use crate::world_gen::blender::Blender; -use super::clamped_map; +use super::{clamped_map, perlin::DoublePerlinNoiseParameters}; mod blend; +mod end; mod math; mod noise; mod offset; pub mod spline; mod unary; +mod weird; pub mod built_in_noises { use std::sync::{Arc, LazyLock}; @@ -30,12 +34,17 @@ pub mod built_in_noises { }; use super::{ - blend::{BlendAlphaFunction, BlendOffsetFunction}, - lerp_density, + apply_blending, + blend::BlendOffsetFunction, + end::EndIslandFunction, noise::{InternalNoise, InterpolatedNoiseSampler, NoiseFunction, ShiftedNoiseFunction}, + noise_in_range, offset::{ShiftAFunction, ShiftBFunction}, spline::SplineFunction, - ConstantFunction, DensityFunction, YClampedFunction, + veritcal_range_choice, + weird::{RarityMapper, WierdScaledFunction}, + ConstantFunction, DensityFunction, RangeFunction, WrapperFunction, WrapperType, + YClampedFunction, }; pub struct SlopedCheeseResult<'a> { @@ -65,17 +74,27 @@ pub mod built_in_noises { }); pub static SHIFT_X: BuiltInNoise = LazyLock::new(|| { - DensityFunction::ShiftA(ShiftAFunction::new(Arc::new(InternalNoise::new( - builtin_noise_params::OFFSET.clone(), - None, - )))) + DensityFunction::Wrapper(WrapperFunction::new( + Arc::new(DensityFunction::Wrapper(WrapperFunction::new( + Arc::new(DensityFunction::ShiftA(ShiftAFunction::new(Arc::new( + InternalNoise::new(builtin_noise_params::OFFSET.clone(), None), + )))), + WrapperType::Cache2D, + ))), + WrapperType::CacheFlat, + )) }); pub static SHIFT_Z: BuiltInNoise = LazyLock::new(|| { - DensityFunction::ShiftB(ShiftBFunction::new(Arc::new(InternalNoise::new( - builtin_noise_params::OFFSET.clone(), - None, - )))) + DensityFunction::Wrapper(WrapperFunction::new( + Arc::new(DensityFunction::Wrapper(WrapperFunction::new( + Arc::new(DensityFunction::ShiftB(ShiftBFunction::new(Arc::new( + InternalNoise::new(builtin_noise_params::OFFSET.clone(), None), + )))), + WrapperType::Cache2D, + ))), + WrapperType::CacheFlat, + )) }); pub static BASE_3D_NOISE_OVERWORLD: BuiltInNoise = LazyLock::new(|| { @@ -97,44 +116,53 @@ pub mod built_in_noises { }); pub static CONTINENTS_OVERWORLD: BuiltInNoise = LazyLock::new(|| { - DensityFunction::ShiftedNoise(ShiftedNoiseFunction::new( - Arc::new(SHIFT_X.clone()), - Arc::new(ZERO.clone()), - Arc::new(SHIFT_Z.clone()), - 0.25f64, - 0f64, - Arc::new(InternalNoise::new( - builtin_noise_params::CONTINENTALNESS.clone(), - None, - )), + DensityFunction::Wrapper(WrapperFunction::new( + Arc::new(DensityFunction::ShiftedNoise(ShiftedNoiseFunction::new( + Arc::new(SHIFT_X.clone()), + Arc::new(ZERO.clone()), + Arc::new(SHIFT_Z.clone()), + 0.25f64, + 0f64, + Arc::new(InternalNoise::new( + builtin_noise_params::CONTINENTALNESS.clone(), + None, + )), + ))), + WrapperType::CacheFlat, )) }); pub static EROSION_OVERWORLD: BuiltInNoise = LazyLock::new(|| { - DensityFunction::ShiftedNoise(ShiftedNoiseFunction::new( - Arc::new(SHIFT_X.clone()), - Arc::new(ZERO.clone()), - Arc::new(SHIFT_Z.clone()), - 0.25f64, - 0f64, - Arc::new(InternalNoise::new( - builtin_noise_params::EROSION.clone(), - None, - )), + DensityFunction::Wrapper(WrapperFunction::new( + Arc::new(DensityFunction::ShiftedNoise(ShiftedNoiseFunction::new( + Arc::new(SHIFT_X.clone()), + Arc::new(ZERO.clone()), + Arc::new(SHIFT_Z.clone()), + 0.25f64, + 0f64, + Arc::new(InternalNoise::new( + builtin_noise_params::EROSION.clone(), + None, + )), + ))), + WrapperType::CacheFlat, )) }); pub static RIDGES_OVERWORLD: BuiltInNoise = LazyLock::new(|| { - DensityFunction::ShiftedNoise(ShiftedNoiseFunction::new( - Arc::new(SHIFT_X.clone()), - Arc::new(ZERO.clone()), - Arc::new(SHIFT_Z.clone()), - 0.25f64, - 0f64, - Arc::new(InternalNoise::new( - builtin_noise_params::RIDGE.clone(), - None, - )), + DensityFunction::Wrapper(WrapperFunction::new( + Arc::new(DensityFunction::ShiftedNoise(ShiftedNoiseFunction::new( + Arc::new(SHIFT_X.clone()), + Arc::new(ZERO.clone()), + Arc::new(SHIFT_Z.clone()), + 0.25f64, + 0f64, + Arc::new(InternalNoise::new( + builtin_noise_params::RIDGE.clone(), + None, + )), + ))), + WrapperType::CacheFlat, )) }); @@ -165,6 +193,344 @@ pub mod built_in_noises { ) }); + pub static CONTINENTS_OVERWORLD_LARGE_BIOME: BuiltInNoise = LazyLock::new(|| { + DensityFunction::Wrapper(WrapperFunction::new( + Arc::new(DensityFunction::ShiftedNoise(ShiftedNoiseFunction::new( + Arc::new(SHIFT_X.clone()), + Arc::new(ZERO.clone()), + Arc::new(SHIFT_Z.clone()), + 0.25f64, + 0f64, + Arc::new(InternalNoise::new( + builtin_noise_params::CONTINENTALNESS_LARGE.clone(), + None, + )), + ))), + WrapperType::CacheFlat, + )) + }); + + pub static EROSION_OVERWORLD_LARGE_BIOME: BuiltInNoise = LazyLock::new(|| { + DensityFunction::Wrapper(WrapperFunction::new( + Arc::new(DensityFunction::ShiftedNoise(ShiftedNoiseFunction::new( + Arc::new(SHIFT_X.clone()), + Arc::new(ZERO.clone()), + Arc::new(SHIFT_Z.clone()), + 0.25f64, + 0f64, + Arc::new(InternalNoise::new( + builtin_noise_params::EROSION_LARGE.clone(), + None, + )), + ))), + WrapperType::CacheFlat, + )) + }); + + pub static OVERWORLD_LARGE_SLOPED_CHEESE: BuiltInSlopedCheese = LazyLock::new(|| { + sloped_cheese_function( + DensityFunction::Noise(NoiseFunction::new( + Arc::new(InternalNoise::new( + builtin_noise_params::JAGGED.clone(), + None, + )), + 1500f64, + 0f64, + )), + CONTINENTS_OVERWORLD_LARGE_BIOME.clone(), + EROSION_OVERWORLD_LARGE_BIOME.clone(), + RIDGES_OVERWORLD.clone(), + RIDGES_FOLDED_OVERWORLD.clone(), + false, + ) + }); + + pub static OVERWORLD_AMPLIFIED_SLOPED_CHEESE: BuiltInSlopedCheese = LazyLock::new(|| { + sloped_cheese_function( + DensityFunction::Noise(NoiseFunction::new( + Arc::new(InternalNoise::new( + builtin_noise_params::JAGGED.clone(), + None, + )), + 1500f64, + 0f64, + )), + CONTINENTS_OVERWORLD.clone(), + EROSION_OVERWORLD.clone(), + RIDGES_OVERWORLD.clone(), + RIDGES_FOLDED_OVERWORLD.clone(), + true, + ) + }); + + pub static SLOPED_CHEESE_END: BuiltInNoise = LazyLock::new(|| { + DensityFunction::EndIsland(EndIslandFunction::new(0)).add(BASE_3D_NOISE_END.clone()) + }); + + pub static CAVES_SPAGHETTI_ROUGHNESS_FUNCTION_OVERWORLD: BuiltInNoise = LazyLock::new(|| { + DensityFunction::Wrapper(WrapperFunction::new( + Arc::new( + noise_in_range( + builtin_noise_params::SPAGHETTI_ROUGHNESS_MODULATOR.clone(), + 1f64, + 1f64, + 0f64, + -0.1f64, + ) + .mul( + DensityFunction::Noise(NoiseFunction::new( + Arc::new(InternalNoise::new( + builtin_noise_params::SPAGHETTI_ROUGHNESS.clone(), + None, + )), + 1f64, + 1f64, + )) + .abs() + .add_const(-0.4f64), + ), + ), + WrapperType::CacheOnce, + )) + }); + + pub static CAVES_SPAGHETTI_2D_THICKNESS_MODULAR_OVERWORLD: BuiltInNoise = LazyLock::new(|| { + DensityFunction::Wrapper(WrapperFunction::new( + Arc::new(noise_in_range( + builtin_noise_params::SPAGHETTI_2D_THICKNESS.clone(), + 2f64, + 1f64, + -0.6f64, + -1.3f64, + )), + WrapperType::CacheOnce, + )) + }); + + pub static CAVES_SPAGHETTI_2D_OVERWORLD: BuiltInNoise = LazyLock::new(|| { + let function1 = DensityFunction::Noise(NoiseFunction::new( + Arc::new(InternalNoise::new( + builtin_noise_params::SPAGHETTI_2D_MODULATOR.clone(), + None, + )), + 2f64, + 1f64, + )); + + let function2 = DensityFunction::Wierd(WierdScaledFunction::new( + Arc::new(function1), + Arc::new(InternalNoise::new( + builtin_noise_params::SPAGHETTI_2D.clone(), + None, + )), + RarityMapper::Caves, + )); + + let function3 = noise_in_range( + builtin_noise_params::SPAGHETTI_2D_ELEVATION.clone(), + 1f64, + 0f64, + ((-64i32) / 8i32) as f64, + 8f64, + ); + + let function4 = CAVES_SPAGHETTI_2D_THICKNESS_MODULAR_OVERWORLD.clone(); + + let function5 = function3.add( + DensityFunction::ClampedY(YClampedFunction { + from: -64, + to: 320, + from_val: 8f64, + to_val: -40f64, + }) + .abs(), + ); + + let function6 = function5.add(function4.clone()).cube(); + + let function7 = function2.add(function4.mul_const(0.083f64)); + + function7.binary_max(function6).clamp(-1f64, 1f64) + }); + + pub static CAVES_ENTRANCES_OVERWORLD: BuiltInNoise = LazyLock::new(|| { + let function = DensityFunction::Noise(NoiseFunction::new( + Arc::new(InternalNoise::new( + builtin_noise_params::SPAGHETTI_3D_RARITY.clone(), + None, + )), + 2f64, + 1f64, + )); + + let function2 = noise_in_range( + builtin_noise_params::SPAGHETTI_3D_THICKNESS.clone(), + 1f64, + 1f64, + -0.065f64, + -0.088f64, + ); + + let function3 = DensityFunction::Wierd(WierdScaledFunction::new( + Arc::new(function.clone()), + Arc::new(InternalNoise::new( + builtin_noise_params::SPAGHETTI_3D_1.clone(), + None, + )), + RarityMapper::Tunnels, + )); + + let function4 = DensityFunction::Wierd(WierdScaledFunction::new( + Arc::new(function), + Arc::new(InternalNoise::new( + builtin_noise_params::SPAGHETTI_3D_2.clone(), + None, + )), + RarityMapper::Tunnels, + )); + + let function5 = function3 + .binary_max(function4) + .add(function2) + .clamp(-1f64, 1f64); + + let function6 = CAVES_SPAGHETTI_ROUGHNESS_FUNCTION_OVERWORLD.clone(); + + let function7 = DensityFunction::Noise(NoiseFunction::new( + Arc::new(InternalNoise::new( + builtin_noise_params::CAVE_ENTRANCE.clone(), + None, + )), + 0.75f64, + 0.5f64, + )); + + let function8 = + function7 + .add_const(0.37f64) + .add(DensityFunction::ClampedY(YClampedFunction { + from: -10, + to: 30, + from_val: 0.3f64, + to_val: 0f64, + })); + + DensityFunction::Wrapper(WrapperFunction::new( + Arc::new(function8.binary_min(function6.add(function5))), + WrapperType::CacheOnce, + )) + }); + + pub static CAVES_NOODLE_OVERWORLD: BuiltInNoise = LazyLock::new(|| { + let function = Y.clone(); + + let function2 = veritcal_range_choice( + function.clone(), + DensityFunction::Noise(NoiseFunction::new( + Arc::new(InternalNoise::new( + builtin_noise_params::NOODLE.clone(), + None, + )), + 1f64, + 1f64, + )), + -60, + 320, + -1, + ); + + let function3 = veritcal_range_choice( + function.clone(), + noise_in_range( + builtin_noise_params::NOODLE_THICKNESS.clone(), + 1f64, + 1f64, + -0.05f64, + -0.1f64, + ), + -60, + 320, + 0, + ); + + let function4 = veritcal_range_choice( + function.clone(), + DensityFunction::Noise(NoiseFunction::new( + Arc::new(InternalNoise::new( + builtin_noise_params::NOODLE_RIDGE_A.clone(), + None, + )), + 2.6666666666666665f64, + 2.6666666666666665f64, + )), + -60, + 320, + 0, + ); + + let function5 = veritcal_range_choice( + function.clone(), + DensityFunction::Noise(NoiseFunction::new( + Arc::new(InternalNoise::new( + builtin_noise_params::NOODLE_RIDGE_B.clone(), + None, + )), + 2.6666666666666665f64, + 2.6666666666666665f64, + )), + -60, + 320, + 0, + ); + + let function6 = function4 + .abs() + .binary_max(function5.abs()) + .mul_const(1.5f64); + + DensityFunction::Range(RangeFunction { + input: Arc::new(function2), + min: -1000000f64, + max: 0f64, + in_range: Arc::new(DensityFunction::Constant(ConstantFunction::new(64f64))), + out_range: Arc::new(function3.add(function6)), + }) + }); + + pub static CAVES_PILLARS_OVERWORLD: BuiltInNoise = LazyLock::new(|| { + let function = DensityFunction::Noise(NoiseFunction::new( + Arc::new(InternalNoise::new( + builtin_noise_params::PILLAR.clone(), + None, + )), + 25f64, + 0.3f64, + )); + + let function2 = noise_in_range( + builtin_noise_params::PILLAR_RARENESS.clone(), + 1f64, + 1f64, + 0f64, + -2f64, + ); + + let function3 = noise_in_range( + builtin_noise_params::PILLAR_THICKNESS.clone(), + 1f64, + 1f64, + 0f64, + 1.1f64, + ); + + let function4 = function.mul_const(2f64).add(function2); + + DensityFunction::Wrapper(WrapperFunction::new( + Arc::new(function4.mul(function3.cube())), + WrapperType::CacheOnce, + )) + }); + fn sloped_cheese_function<'a>( jagged_noise: DensityFunction<'a>, continents: DensityFunction<'a>, @@ -173,8 +539,7 @@ pub mod built_in_noises { ridges_folded: DensityFunction<'a>, amplified: bool, ) -> SlopedCheeseResult<'a> { - let offset = lerp_density( - DensityFunction::BlendAlpha(BlendAlphaFunction {}), + let offset = apply_blending( DensityFunction::Spline(SplineFunction::new(Arc::new(create_offset_spline( continents.clone(), erosion.clone(), @@ -185,8 +550,7 @@ pub mod built_in_noises { DensityFunction::BlendOffset(BlendOffsetFunction {}), ); - let factor = lerp_density( - DensityFunction::BlendAlpha(BlendAlphaFunction {}), + let factor = apply_blending( DensityFunction::Spline(SplineFunction::new(Arc::new(create_factor_spline( continents.clone(), erosion.clone(), @@ -205,8 +569,7 @@ pub mod built_in_noises { }) .add(offset.clone()); - let jaggedness = lerp_density( - DensityFunction::BlendAlpha(BlendAlphaFunction {}), + let jaggedness = apply_blending( DensityFunction::Spline(SplineFunction::new(Arc::new(create_jaggedness_spline( continents, erosion, @@ -237,6 +600,70 @@ pub fn peaks_valleys_noise(variance: f32) -> f32 { -((variance.abs() - 0.6666667f32).abs() - 0.33333334f32) * 3f32 } +fn veritcal_range_choice<'a>( + input: DensityFunction<'a>, + in_range: DensityFunction<'a>, + min: i32, + max: i32, + out: i32, +) -> DensityFunction<'a> { + DensityFunction::Wrapper(WrapperFunction::new( + Arc::new(DensityFunction::Range(RangeFunction { + input: Arc::new(input), + min: min as f64, + max: (max + 1) as f64, + in_range: Arc::new(in_range), + out_range: Arc::new(DensityFunction::Constant(ConstantFunction::new(out as f64))), + })), + WrapperType::Interpolated, + )) +} + +fn apply_blending<'a>( + function: DensityFunction<'a>, + blend: DensityFunction<'a>, +) -> DensityFunction<'a> { + let function = lerp_density( + DensityFunction::BlendAlpha(BlendAlphaFunction {}), + blend, + function, + ); + + DensityFunction::Wrapper(WrapperFunction::new( + Arc::new(DensityFunction::Wrapper(WrapperFunction::new( + Arc::new(function), + WrapperType::Cache2D, + ))), + WrapperType::CacheFlat, + )) +} + +fn noise_in_range( + noise: DoublePerlinNoiseParameters, + xz_scale: f64, + y_scale: f64, + min: f64, + max: f64, +) -> DensityFunction { + map_range( + DensityFunction::Noise(NoiseFunction::new( + Arc::new(InternalNoise::new(noise, None)), + xz_scale, + y_scale, + )), + min, + max, + ) +} + +fn map_range(function: DensityFunction, min: f64, max: f64) -> DensityFunction { + let d = (min + max) * 0.5f64; + let e = (max - min) * 0.5f64; + + DensityFunction::Constant(ConstantFunction::new(d)) + .add(DensityFunction::Constant(ConstantFunction::new(e)).mul(function)) +} + #[derive(Clone)] pub enum DensityFunction<'a> { Clamp(ClampFunction<'a>), @@ -254,6 +681,10 @@ pub enum DensityFunction<'a> { BlendDensity(BlendDensityFunction<'a>), ClampedY(YClampedFunction), InterpolatedNoise(InterpolatedNoiseSampler), + EndIsland(EndIslandFunction), + Wierd(WierdScaledFunction<'a>), + Range(RangeFunction<'a>), + Wrapper(WrapperFunction<'a>), } impl<'a> DensityFunction<'a> { @@ -275,6 +706,10 @@ impl<'a> DensityFunction<'a> { Self::BlendDensity(func) => func.sample(pos), Self::ClampedY(func) => func.sample(pos), Self::InterpolatedNoise(func) => func.sample(pos), + Self::EndIsland(func) => func.sample(pos), + Self::Wierd(func) => func.sample(pos), + Self::Range(func) => func.sample(pos), + Self::Wrapper(func) => func.sample(pos), } } @@ -296,6 +731,10 @@ impl<'a> DensityFunction<'a> { Self::BlendDensity(func) => func.apply(visitor), Self::ClampedY(func) => func.apply(visitor), Self::InterpolatedNoise(func) => func.apply(visitor), + Self::EndIsland(func) => func.apply(visitor), + Self::Wierd(func) => func.apply(visitor), + Self::Range(func) => func.apply(visitor), + Self::Wrapper(func) => func.apply(visitor), } } @@ -317,6 +756,10 @@ impl<'a> DensityFunction<'a> { Self::BlendDensity(func) => func.fill(densities, applier), Self::ClampedY(func) => func.fill(densities, applier), Self::InterpolatedNoise(func) => func.fill(densities, applier), + Self::EndIsland(func) => func.fill(densities, applier), + Self::Wierd(func) => func.fill(densities, applier), + Self::Range(func) => func.fill(densities, applier), + Self::Wrapper(func) => func.fill(densities, applier), } } @@ -338,6 +781,10 @@ impl<'a> DensityFunction<'a> { Self::BlendDensity(func) => func.max(), Self::ClampedY(func) => func.max(), Self::InterpolatedNoise(func) => func.max(), + Self::EndIsland(func) => func.max(), + Self::Wierd(func) => func.max(), + Self::Range(func) => func.max(), + Self::Wrapper(func) => func.max(), } } @@ -359,6 +806,10 @@ impl<'a> DensityFunction<'a> { Self::BlendDensity(func) => func.min(), Self::ClampedY(func) => func.min(), Self::InterpolatedNoise(func) => func.min(), + Self::EndIsland(func) => func.min(), + Self::Wierd(func) => func.min(), + Self::Range(func) => func.min(), + Self::Wrapper(func) => func.min(), } } @@ -506,6 +957,104 @@ impl<'a> DensityFunctionImpl<'a> for ConstantFunction { } } +#[derive(Clone)] +pub enum WrapperType { + Cache2D, + CacheFlat, + CacheOnce, + Interpolated, +} + +#[derive(Clone)] +pub struct WrapperFunction<'a> { + input: Arc>, + wrapper: WrapperType, +} + +impl<'a> WrapperFunction<'a> { + pub fn new(input: Arc>, wrapper: WrapperType) -> Self { + Self { input, wrapper } + } +} + +impl<'a> DensityFunctionImpl<'a> for WrapperFunction<'a> { + fn max(&self) -> f64 { + self.input.max() + } + + fn min(&self) -> f64 { + self.input.min() + } + + fn sample(&self, pos: &impl NoisePos) -> f64 { + self.input.sample(pos) + } + + fn apply(&'a self, visitor: &'a impl Visitor) -> DensityFunction<'a> { + visitor.apply(&DensityFunction::Wrapper(WrapperFunction { + input: Arc::new(self.input.apply(visitor)), + wrapper: self.wrapper.clone(), + })) + } + + fn fill(&self, densities: &[f64], applier: &impl Applier) -> Vec { + self.input.fill(densities, applier) + } +} + +#[derive(Clone)] +pub struct RangeFunction<'a> { + input: Arc>, + min: f64, + max: f64, + in_range: Arc>, + out_range: Arc>, +} + +impl<'a> DensityFunctionImpl<'a> for RangeFunction<'a> { + fn sample(&self, pos: &impl NoisePos) -> f64 { + let d = self.input.sample(pos); + if d >= self.min && d < self.max { + self.in_range.sample(pos) + } else { + self.out_range.sample(pos) + } + } + + fn fill(&self, densities: &[f64], applier: &impl Applier) -> Vec { + let densities = self.input.fill(densities, applier); + densities + .iter() + .enumerate() + .map(|(i, x)| { + if *x >= self.min && *x < self.max { + self.in_range.sample(&applier.at(i as i32)) + } else { + self.out_range.sample(&applier.at(i as i32)) + } + }) + .collect() + } + + fn apply(&'a self, visitor: &'a impl Visitor) -> DensityFunction<'a> { + visitor.apply(&DensityFunction::Range(RangeFunction { + input: Arc::new(self.input.apply(visitor)), + min: self.min, + max: self.max, + in_range: Arc::new(self.in_range.apply(visitor)), + out_range: Arc::new(self.out_range.apply(visitor)), + })) + } + + fn min(&self) -> f64 { + self.in_range.min().min(self.out_range.min()) + } + + fn max(&self) -> f64 { + self.in_range.max().max(self.out_range.max()) + } +} + #[derive(Clone)] pub struct YClampedFunction { from: i32, diff --git a/pumpkin-world/src/world_gen/noise/density/noise.rs b/pumpkin-world/src/world_gen/noise/density/noise.rs index fcd9bf950..245c56408 100644 --- a/pumpkin-world/src/world_gen/noise/density/noise.rs +++ b/pumpkin-world/src/world_gen/noise/density/noise.rs @@ -42,7 +42,7 @@ impl<'a> InternalNoise<'a> { #[derive(Clone)] pub struct NoiseFunction<'a> { - noise: Arc>, + pub(crate) noise: Arc>, xz_scale: f64, y_scale: f64, } diff --git a/pumpkin-world/src/world_gen/noise/density/weird.rs b/pumpkin-world/src/world_gen/noise/density/weird.rs new file mode 100644 index 000000000..9fada3355 --- /dev/null +++ b/pumpkin-world/src/world_gen/noise/density/weird.rs @@ -0,0 +1,109 @@ +use std::sync::Arc; + +use super::{noise::InternalNoise, DensityFunction, DensityFunctionImpl, NoisePos}; + +#[derive(Clone)] +pub enum RarityMapper { + Tunnels, + Caves, +} + +impl RarityMapper { + #[inline] + pub fn max_multiplier(&self) -> f64 { + match self { + Self::Tunnels => 2f64, + Self::Caves => 3f64, + } + } + + #[inline] + pub fn scale(&self, value: f64) -> f64 { + match self { + Self::Tunnels => { + if value < -0.5f64 { + 0.75f64 + } else if value < 0f64 { + 1f64 + } else if value < 0.5f64 { + 1.5f64 + } else { + 2f64 + } + } + Self::Caves => { + if value < -0.75f64 { + 0.5f64 + } else if value < -0.5f64 { + 0.75f64 + } else if value < 0.5f64 { + 1f64 + } else if value < 0.75 { + 2f64 + } else { + 3f64 + } + } + } + } +} + +#[derive(Clone)] +pub struct WierdScaledFunction<'a> { + input: Arc>, + noise: Arc>, + rarity: RarityMapper, +} + +impl<'a> WierdScaledFunction<'a> { + pub fn new( + input: Arc>, + noise: Arc>, + rarity: RarityMapper, + ) -> Self { + Self { + input, + noise, + rarity, + } + } + + fn apply_loc(&self, pos: &impl NoisePos, density: f64) -> f64 { + let d = self.rarity.scale(density); + d * self + .noise + .sample(pos.x() as f64 / d, pos.y() as f64 / d, pos.z() as f64 / d) + .abs() + } +} + +impl<'a> DensityFunctionImpl<'a> for WierdScaledFunction<'a> { + fn max(&self) -> f64 { + self.rarity.max_multiplier() * self.noise.max_value() + } + + fn min(&self) -> f64 { + 0f64 + } + + fn apply(&'a self, visitor: &'a impl super::Visitor) -> DensityFunction<'a> { + visitor.apply(&DensityFunction::Wierd(WierdScaledFunction { + input: Arc::new(self.input.apply(visitor)), + noise: visitor.apply_internal_noise(self.noise.clone()), + rarity: self.rarity.clone(), + })) + } + + fn sample(&self, pos: &impl NoisePos) -> f64 { + self.apply_loc(pos, self.input.sample(pos)) + } + + fn fill(&self, densities: &[f64], applier: &impl super::Applier) -> Vec { + let densities = self.input.fill(densities, applier); + densities + .iter() + .enumerate() + .map(|(i, x)| self.apply_loc(&applier.at(i as i32), *x)) + .collect() + } +} diff --git a/pumpkin-world/src/world_gen/noise/simplex.rs b/pumpkin-world/src/world_gen/noise/simplex.rs index 8d6fba7fa..fc4d91536 100644 --- a/pumpkin-world/src/world_gen/noise/simplex.rs +++ b/pumpkin-world/src/world_gen/noise/simplex.rs @@ -3,6 +3,7 @@ use pumpkin_core::random::{legacy_rand::LegacyRand, RandomImpl}; use super::{dot, GRADIENTS}; +#[derive(Clone)] pub struct SimplexNoiseSampler { permutation: Box<[u8]>, x_origin: f64, From 7c946bb23f1a95644caa92c17cf2ffc7b5e1974e Mon Sep 17 00:00:00 2001 From: kralverde Date: Thu, 19 Sep 2024 10:44:09 -0400 Subject: [PATCH 04/11] implement overworld noises --- pumpkin-world/src/world_gen/chunk.rs | 12 +- pumpkin-world/src/world_gen/mod.rs | 1 + .../src/world_gen/noise/density/blend.rs | 6 + .../src/world_gen/noise/density/mod.rs | 73 +++- pumpkin-world/src/world_gen/noise/mod.rs | 1 + pumpkin-world/src/world_gen/noise/router.rs | 365 ++++++++++++++++++ pumpkin-world/src/world_gen/sampler.rs | 28 ++ 7 files changed, 474 insertions(+), 12 deletions(-) create mode 100644 pumpkin-world/src/world_gen/noise/router.rs create mode 100644 pumpkin-world/src/world_gen/sampler.rs diff --git a/pumpkin-world/src/world_gen/chunk.rs b/pumpkin-world/src/world_gen/chunk.rs index 53ca05875..cd46fe801 100644 --- a/pumpkin-world/src/world_gen/chunk.rs +++ b/pumpkin-world/src/world_gen/chunk.rs @@ -54,7 +54,13 @@ impl GenerationShapeConfig { } } -lazy_static! { - pub static ref surface_config: GenerationShapeConfig = - GenerationShapeConfig::new(-64, 384, 1, 2); +pub mod shape_configs { + use super::GenerationShapeConfig; + + pub const surface_config: GenerationShapeConfig = GenerationShapeConfig { + y_min: -64, + height: 384, + horizontal: 1, + vertical: 2, + }; } diff --git a/pumpkin-world/src/world_gen/mod.rs b/pumpkin-world/src/world_gen/mod.rs index e3d37a590..112645a71 100644 --- a/pumpkin-world/src/world_gen/mod.rs +++ b/pumpkin-world/src/world_gen/mod.rs @@ -4,6 +4,7 @@ mod generator; mod generic_generator; mod implementation; mod noise; +mod sampler; mod seed; pub use generator::WorldGenerator; diff --git a/pumpkin-world/src/world_gen/noise/density/blend.rs b/pumpkin-world/src/world_gen/noise/density/blend.rs index 579589deb..6f719877d 100644 --- a/pumpkin-world/src/world_gen/noise/density/blend.rs +++ b/pumpkin-world/src/world_gen/noise/density/blend.rs @@ -57,6 +57,12 @@ pub struct BlendDensityFunction<'a> { function: Arc>, } +impl<'a> BlendDensityFunction<'a> { + pub fn new(density: Arc>) -> Self { + Self { function: density } + } +} + impl<'a> BlendDensityFunction<'a> { fn apply_density(&self, pos: &impl NoisePos, density: f64) -> f64 { pos.get_blender().apply_blend_density(pos, density) diff --git a/pumpkin-world/src/world_gen/noise/density/mod.rs b/pumpkin-world/src/world_gen/noise/density/mod.rs index c121e3134..afcc746bd 100644 --- a/pumpkin-world/src/world_gen/noise/density/mod.rs +++ b/pumpkin-world/src/world_gen/noise/density/mod.rs @@ -16,7 +16,7 @@ use super::{clamped_map, perlin::DoublePerlinNoiseParameters}; mod blend; mod end; mod math; -mod noise; +pub mod noise; mod offset; pub mod spline; mod unary; @@ -48,11 +48,11 @@ pub mod built_in_noises { }; pub struct SlopedCheeseResult<'a> { - offset: DensityFunction<'a>, - factor: DensityFunction<'a>, - depth: DensityFunction<'a>, - jaggedness: DensityFunction<'a>, - sloped_cheese: DensityFunction<'a>, + pub(crate) offset: DensityFunction<'a>, + pub(crate) factor: DensityFunction<'a>, + pub(crate) depth: DensityFunction<'a>, + pub(crate) jaggedness: DensityFunction<'a>, + pub(crate) sloped_cheese: DensityFunction<'a>, } type BuiltInNoise = LazyLock>; @@ -600,7 +600,7 @@ pub fn peaks_valleys_noise(variance: f32) -> f32 { -((variance.abs() - 0.6666667f32).abs() - 0.33333334f32) * 3f32 } -fn veritcal_range_choice<'a>( +pub fn veritcal_range_choice<'a>( input: DensityFunction<'a>, in_range: DensityFunction<'a>, min: i32, @@ -619,6 +619,16 @@ fn veritcal_range_choice<'a>( )) } +pub fn apply_blend_density(density: DensityFunction) -> DensityFunction { + let function = DensityFunction::BlendDensity(BlendDensityFunction::new(Arc::new(density))); + DensityFunction::Wrapper(WrapperFunction::new( + Arc::new(function), + WrapperType::Interpolated, + )) + .mul_const(0.64f64) + .squeeze() +} + fn apply_blending<'a>( function: DensityFunction<'a>, blend: DensityFunction<'a>, @@ -1011,6 +1021,24 @@ pub struct RangeFunction<'a> { out_range: Arc>, } +impl<'a> RangeFunction<'a> { + pub fn new( + input: Arc>, + min: f64, + max: f64, + in_range: Arc>, + out_range: Arc>, + ) -> Self { + Self { + input, + min, + max, + in_range, + out_range, + } + } +} + impl<'a> DensityFunctionImpl<'a> for RangeFunction<'a> { fn sample(&self, pos: &impl NoisePos) -> f64 { let d = self.input.sample(pos); @@ -1063,6 +1091,17 @@ pub struct YClampedFunction { to_val: f64, } +impl YClampedFunction { + pub fn new(from: i32, to: i32, from_val: f64, to_val: f64) -> Self { + Self { + from, + to, + from_val, + to_val, + } + } +} + impl<'a> DensityFunctionImpl<'a> for YClampedFunction { fn sample(&self, pos: &impl NoisePos) -> f64 { clamped_map( @@ -1112,6 +1151,22 @@ pub fn lerp_density<'a>( start: DensityFunction<'a>, end: DensityFunction<'a>, ) -> DensityFunction<'a> { - let func_2 = delta.mul_const(-1f64).add_const(1f64); - start.mul(func_2.clone()).add(end.mul(func_2)) + if let DensityFunction::Constant(function) = start { + lerp_density_static_start(delta, function.value, end) + } else { + let function = DensityFunction::Wrapper(WrapperFunction::new( + Arc::new(delta), + WrapperType::CacheOnce, + )); + let function2 = function.mul_const(-1f64).add_const(1f64); + start.mul(function2).add(end.mul(function)) + } +} + +pub fn lerp_density_static_start<'a>( + delta: DensityFunction<'a>, + start: f64, + end: DensityFunction<'a>, +) -> DensityFunction<'a> { + delta.mul(end.add_const(-start)).add_const(start) } diff --git a/pumpkin-world/src/world_gen/noise/mod.rs b/pumpkin-world/src/world_gen/noise/mod.rs index e97f8df27..54e551fd7 100644 --- a/pumpkin-world/src/world_gen/noise/mod.rs +++ b/pumpkin-world/src/world_gen/noise/mod.rs @@ -1,6 +1,7 @@ #![allow(dead_code)] pub mod density; mod perlin; +mod router; mod simplex; pub mod builtin_noise_params { diff --git a/pumpkin-world/src/world_gen/noise/router.rs b/pumpkin-world/src/world_gen/noise/router.rs new file mode 100644 index 000000000..1abc85e96 --- /dev/null +++ b/pumpkin-world/src/world_gen/noise/router.rs @@ -0,0 +1,365 @@ +use std::sync::Arc; + +use crate::world_gen::sampler::VeinType; + +use super::{ + builtin_noise_params, + density::{ + apply_blend_density, built_in_noises, lerp_density_static_start, + noise::{InternalNoise, NoiseFunction, ShiftedNoiseFunction}, + veritcal_range_choice, ConstantFunction, DensityFunction, RangeFunction, Visitor, + WrapperFunction, WrapperType, YClampedFunction, + }, +}; + +pub struct NoiseRouter<'a> { + barrier: DensityFunction<'a>, + fluid_level_floodedness: DensityFunction<'a>, + fluid_level_spread: DensityFunction<'a>, + lava: DensityFunction<'a>, + temperature: DensityFunction<'a>, + vegetation: DensityFunction<'a>, + continents: DensityFunction<'a>, + erosion: DensityFunction<'a>, + depth: DensityFunction<'a>, + ridges: DensityFunction<'a>, + internal_density: DensityFunction<'a>, + final_densitiy: DensityFunction<'a>, + vein_toggle: DensityFunction<'a>, + vein_ridged: DensityFunction<'a>, + vein_gap: DensityFunction<'a>, +} + +impl<'a> NoiseRouter<'a> { + pub fn apply(&'a self, visitor: &'a impl Visitor) -> Self { + NoiseRouter { + barrier: self.barrier.apply(visitor), + fluid_level_floodedness: self.fluid_level_floodedness.apply(visitor), + fluid_level_spread: self.fluid_level_spread.apply(visitor), + lava: self.lava.apply(visitor), + temperature: self.temperature.apply(visitor), + vegetation: self.vegetation.apply(visitor), + continents: self.continents.apply(visitor), + erosion: self.erosion.apply(visitor), + depth: self.depth.apply(visitor), + ridges: self.ridges.apply(visitor), + internal_density: self.internal_density.apply(visitor), + final_densitiy: self.final_densitiy.apply(visitor), + vein_toggle: self.vein_toggle.apply(visitor), + vein_ridged: self.vein_ridged.apply(visitor), + vein_gap: self.vein_gap.apply(visitor), + } + } + + pub fn create_surface_noise_router(large_biomes: bool, amplified: bool) -> Self { + let function = DensityFunction::Noise(NoiseFunction::new( + Arc::new(InternalNoise::new( + builtin_noise_params::AQUIFER_BARRIER.clone(), + None, + )), + 1f64, + 0.5f64, + )); + + let function2 = DensityFunction::Noise(NoiseFunction::new( + Arc::new(InternalNoise::new( + builtin_noise_params::AQUIFER_BARRIER_FLOODEDNESS.clone(), + None, + )), + 1f64, + 0.67f64, + )); + + let function3 = DensityFunction::Noise(NoiseFunction::new( + Arc::new(InternalNoise::new( + builtin_noise_params::AQUIFER_FLUID_LEVEL_SPREAD.clone(), + None, + )), + 1f64, + 0.7142857142857143f64, + )); + + let function4 = DensityFunction::Noise(NoiseFunction::new( + Arc::new(InternalNoise::new( + builtin_noise_params::AQUIFER_LAVA.clone(), + None, + )), + 1f64, + 1f64, + )); + + let function5 = built_in_noises::SHIFT_X.clone(); + let function6 = built_in_noises::SHIFT_Z.clone(); + + let function7 = DensityFunction::ShiftedNoise(ShiftedNoiseFunction::new( + Arc::new(function5.clone()), + Arc::new(built_in_noises::ZERO.clone()), + Arc::new(function6.clone()), + 0.25f64, + 0f64, + Arc::new(InternalNoise::new( + if large_biomes { + builtin_noise_params::TEMPERATURE_LARGE.clone() + } else { + builtin_noise_params::TEMPERATURE.clone() + }, + None, + )), + )); + + let function8 = DensityFunction::ShiftedNoise(ShiftedNoiseFunction::new( + Arc::new(function5.clone()), + Arc::new(built_in_noises::ZERO.clone()), + Arc::new(function6.clone()), + 0.25f64, + 0f64, + Arc::new(InternalNoise::new( + if large_biomes { + builtin_noise_params::VEGETATION_LARGE.clone() + } else { + builtin_noise_params::VEGETATION.clone() + }, + None, + )), + )); + + let function9 = if large_biomes { + built_in_noises::OVERWORLD_LARGE_SLOPED_CHEESE + .factor + .clone() + } else if amplified { + built_in_noises::OVERWORLD_AMPLIFIED_SLOPED_CHEESE + .factor + .clone() + } else { + built_in_noises::OVERWORLD_SLOPED_CHEESE.factor.clone() + }; + + let function10 = if large_biomes { + built_in_noises::OVERWORLD_LARGE_SLOPED_CHEESE.depth.clone() + } else if amplified { + built_in_noises::OVERWORLD_AMPLIFIED_SLOPED_CHEESE + .depth + .clone() + } else { + built_in_noises::OVERWORLD_SLOPED_CHEESE.depth.clone() + }; + + let function11 = DensityFunction::Constant(ConstantFunction::new(4f64)).mul( + function10 + .mul(DensityFunction::Wrapper(WrapperFunction::new( + Arc::new(function9), + WrapperType::Cache2D, + ))) + .quarter_negative(), + ); + + let function12 = if large_biomes { + built_in_noises::OVERWORLD_LARGE_SLOPED_CHEESE + .sloped_cheese + .clone() + } else if amplified { + built_in_noises::OVERWORLD_AMPLIFIED_SLOPED_CHEESE + .sloped_cheese + .clone() + } else { + built_in_noises::OVERWORLD_SLOPED_CHEESE + .sloped_cheese + .clone() + }; + + let function13 = function12.binary_min( + DensityFunction::Constant(ConstantFunction::new(5f64)) + .mul(built_in_noises::CAVES_ENTRANCES_OVERWORLD.clone()), + ); + + let function14 = DensityFunction::Range(RangeFunction::new( + Arc::new(function12.clone()), + -1000000f64, + 1.5625f64, + Arc::new(function13), + Arc::new(create_caves(function12)), + )); + + let function15 = apply_blend_density(apply_surface_slides(amplified, function14)) + .binary_min(built_in_noises::CAVES_NOODLE_OVERWORLD.clone()); + let function16 = built_in_noises::Y.clone(); + + let i = VeinType::overall_min_y(); + let j = VeinType::overall_max_y(); + let function17 = veritcal_range_choice( + function16.clone(), + DensityFunction::Noise(NoiseFunction::new( + Arc::new(InternalNoise::new( + builtin_noise_params::ORE_VEININESS.clone(), + None, + )), + 1.5f64, + 1.5f64, + )), + i, + j, + 0, + ); + + let function18 = veritcal_range_choice( + function16.clone(), + DensityFunction::Noise(NoiseFunction::new( + Arc::new(InternalNoise::new( + builtin_noise_params::ORE_VEIN_A.clone(), + None, + )), + 4f64, + 4f64, + )), + i, + j, + 0, + ) + .abs(); + + let function19 = veritcal_range_choice( + function16, + DensityFunction::Noise(NoiseFunction::new( + Arc::new(InternalNoise::new( + builtin_noise_params::ORE_VEIN_B.clone(), + None, + )), + 4f64, + 4f64, + )), + i, + j, + 0, + ) + .abs(); + + let function20 = DensityFunction::Constant(ConstantFunction::new(-0.08f64)) + .add(function18.binary_max(function19)); + + let function21 = DensityFunction::Noise(NoiseFunction::new( + Arc::new(InternalNoise::new( + builtin_noise_params::ORE_GAP.clone(), + None, + )), + 1f64, + 1f64, + )); + + Self { + barrier: function, + fluid_level_floodedness: function2, + fluid_level_spread: function3, + lava: function4, + temperature: function7, + vegetation: function8, + continents: if large_biomes { + built_in_noises::CONTINENTS_OVERWORLD_LARGE_BIOME.clone() + } else { + built_in_noises::CONTINENTS_OVERWORLD.clone() + }, + erosion: if large_biomes { + built_in_noises::EROSION_OVERWORLD_LARGE_BIOME.clone() + } else { + built_in_noises::CONTINENTS_OVERWORLD.clone() + }, + depth: function10, + ridges: built_in_noises::RIDGES_OVERWORLD.clone(), + internal_density: apply_surface_slides( + amplified, + function11.add_const(-0.703125).clamp(-64f64, 64f64), + ), + final_densitiy: function15, + vein_toggle: function17, + vein_ridged: function20, + vein_gap: function21, + } + } +} + +fn apply_surface_slides(amplified: bool, density: DensityFunction) -> DensityFunction { + apply_slides( + density, + -64, + 384, + if amplified { 16 } else { 80 }, + if amplified { 0 } else { 64 }, + -0.078125f64, + 0, + 24, + if amplified { 0.4f64 } else { 0.1171875f64 }, + ) +} + +#[allow(clippy::too_many_arguments)] +fn apply_slides( + density: DensityFunction, + y_min: i32, + y_max: i32, + top_rel_y_min: i32, + top_rel_y_max: i32, + top_density: f64, + bottom_rel_y_min: i32, + bottom_rel_y_max: i32, + bottom_density: f64, +) -> DensityFunction { + let function2 = DensityFunction::ClampedY(YClampedFunction::new( + y_min + y_max - top_rel_y_min, + y_min + y_max + -top_rel_y_max, + 1f64, + 0f64, + )); + let function = lerp_density_static_start(function2, top_density, density); + let function3 = DensityFunction::ClampedY(YClampedFunction::new( + y_min + bottom_rel_y_min, + y_min + bottom_rel_y_max, + 0f64, + 1f64, + )); + lerp_density_static_start(function3, bottom_density, function) +} + +fn create_caves(sloped_cheese: DensityFunction) -> DensityFunction { + let function = built_in_noises::CAVES_SPAGHETTI_2D_OVERWORLD.clone(); + let function2 = built_in_noises::CAVES_SPAGHETTI_ROUGHNESS_FUNCTION_OVERWORLD.clone(); + let function3 = DensityFunction::Noise(NoiseFunction::new( + Arc::new(InternalNoise::new( + builtin_noise_params::CAVE_LAYER.clone(), + None, + )), + 1f64, + 8f64, + )); + let function4 = DensityFunction::Constant(ConstantFunction::new(4f64)).mul(function3.square()); + let function5 = DensityFunction::Noise(NoiseFunction::new( + Arc::new(InternalNoise::new( + builtin_noise_params::CAVE_CHEESE.clone(), + None, + )), + 1f64, + 0.6666666666666666f64, + )); + let function6 = DensityFunction::Constant(ConstantFunction::new(0.27f64)) + .add(function5) + .clamp(-1f64, 1f64) + .add( + DensityFunction::Constant(ConstantFunction::new(1.5f64)) + .add(DensityFunction::Constant(ConstantFunction::new(-0.64f64)).mul(sloped_cheese)) + .clamp(0f64, 0.5f64), + ); + let function7 = function4.add(function6); + let function8 = function7 + .binary_min(built_in_noises::CAVES_ENTRANCES_OVERWORLD.clone()) + .binary_min(function.add(function2)); + let function9 = built_in_noises::CAVES_PILLARS_OVERWORLD.clone(); + let function10 = DensityFunction::Range(RangeFunction::new( + Arc::new(function9.clone()), + -1000000f64, + 0.03f64, + Arc::new(DensityFunction::Constant(ConstantFunction::new( + -1000000f64, + ))), + Arc::new(function9), + )); + function8.binary_max(function10) +} diff --git a/pumpkin-world/src/world_gen/sampler.rs b/pumpkin-world/src/world_gen/sampler.rs new file mode 100644 index 000000000..93d155a21 --- /dev/null +++ b/pumpkin-world/src/world_gen/sampler.rs @@ -0,0 +1,28 @@ +pub enum VeinType { + Copper, + Iron, +} + +impl VeinType { + pub fn min_y(&self) -> i32 { + match self { + Self::Copper => 0, + Self::Iron => -60, + } + } + + pub fn max_y(&self) -> i32 { + match self { + Self::Copper => 50, + Self::Iron => -8, + } + } + + pub fn overall_min_y() -> i32 { + -60 + } + + pub fn overall_max_y() -> i32 { + 60 + } +} From 2815ff90a9536cf11394f37dc4448bc2891f916b Mon Sep 17 00:00:00 2001 From: kralverde Date: Mon, 14 Oct 2024 17:12:45 -0400 Subject: [PATCH 05/11] remove main cargo.lock --- pumpkin-core/src/math/mod.rs | 12 + pumpkin-world/Cargo.toml | 2 + pumpkin-world/src/height.rs | 69 + pumpkin-world/src/lib.rs | 1 + pumpkin-world/src/world_gen/blender.rs | 9 - pumpkin-world/src/world_gen/blender/data.rs | 391 ++++++ pumpkin-world/src/world_gen/blender/mod.rs | 322 +++++ pumpkin-world/src/world_gen/chunk.rs | 226 +++- .../src/world_gen/implementation/aquifer.rs | 60 + .../src/world_gen/implementation/mod.rs | 31 + .../overworld/terrain_params.rs | 59 +- .../implementation/surface_builder.rs | 0 pumpkin-world/src/world_gen/mod.rs | 53 +- .../src/world_gen/noise/chunk_sampler.rs | 392 ++++++ pumpkin-world/src/world_gen/noise/config.rs | 10 + .../src/world_gen/noise/density/blend.rs | 35 +- .../src/world_gen/noise/density/end.rs | 17 +- .../src/world_gen/noise/density/math.rs | 53 +- .../src/world_gen/noise/density/mod.rs | 1159 ++++++++--------- .../src/world_gen/noise/density/noise.rs | 43 +- .../src/world_gen/noise/density/offset.rs | 29 +- .../src/world_gen/noise/density/spline.rs | 34 +- .../src/world_gen/noise/density/unary.rs | 42 +- .../src/world_gen/noise/density/weird.rs | 19 +- pumpkin-world/src/world_gen/noise/mod.rs | 4 +- pumpkin-world/src/world_gen/noise/router.rs | 261 ++-- pumpkin-world/src/world_gen/supplier.rs | 26 + 27 files changed, 2488 insertions(+), 871 deletions(-) create mode 100644 pumpkin-world/src/height.rs delete mode 100644 pumpkin-world/src/world_gen/blender.rs create mode 100644 pumpkin-world/src/world_gen/blender/data.rs create mode 100644 pumpkin-world/src/world_gen/blender/mod.rs create mode 100644 pumpkin-world/src/world_gen/implementation/aquifer.rs create mode 100644 pumpkin-world/src/world_gen/implementation/surface_builder.rs create mode 100644 pumpkin-world/src/world_gen/noise/chunk_sampler.rs create mode 100644 pumpkin-world/src/world_gen/noise/config.rs create mode 100644 pumpkin-world/src/world_gen/supplier.rs diff --git a/pumpkin-core/src/math/mod.rs b/pumpkin-core/src/math/mod.rs index 044b31add..c568268af 100644 --- a/pumpkin-core/src/math/mod.rs +++ b/pumpkin-core/src/math/mod.rs @@ -20,8 +20,20 @@ pub fn squared_magnitude(a: f64, b: f64, c: f64) -> f64 { a * a + b * b + c * c } +pub fn magnitude(a: f64, b: f64, c: f64) -> f64 { + squared_magnitude(a, b, c).sqrt() +} + /// Converts a world coordinate to the corresponding chunk-section coordinate. // TODO: This proberbly should place not here pub const fn get_section_cord(coord: i32) -> i32 { coord >> 4 } + +pub fn squared_hypot(a: f64, b: f64) -> f64 { + a * a + b * b +} + +pub fn hypot(a: f64, b: f64) -> f64 { + squared_hypot(a, b).sqrt() +} diff --git a/pumpkin-world/Cargo.toml b/pumpkin-world/Cargo.toml index 9a06e04fc..191b3e2fc 100644 --- a/pumpkin-world/Cargo.toml +++ b/pumpkin-world/Cargo.toml @@ -22,6 +22,8 @@ lz4 = "1.11.1" serde.workspace = true serde_json = "1.0" +enum_dispatch = "0.3.13" + log.workspace = true parking_lot.workspace = true diff --git a/pumpkin-world/src/height.rs b/pumpkin-world/src/height.rs new file mode 100644 index 000000000..1effb518e --- /dev/null +++ b/pumpkin-world/src/height.rs @@ -0,0 +1,69 @@ +use enum_dispatch::enum_dispatch; + +use crate::world_gen::chunk::Chunk; + +#[enum_dispatch] +pub enum HeightLimitView { + Standard(StandardHeightLimitView), + Chunk(Chunk), +} + +#[enum_dispatch(HeightLimitView)] +pub trait HeightLimitViewImpl { + fn height(&self) -> i32; + + fn bottom_y(&self) -> i32; + + fn top_y(&self) -> i32 { + self.bottom_y() + self.height() + } + + fn vertical_section_count(&self) -> i32 { + self.top_section_coord() - self.bottom_section_coord() + } + + fn bottom_section_coord(&self) -> i32 { + self.bottom_y() >> 4 + } + + fn top_section_coord(&self) -> i32 { + ((self.top_y() - 1) >> 4) + 1 + } + + fn out_of_height(&self, height: i32) -> bool { + height < self.bottom_y() || height >= self.top_y() + } + + fn section_index(&self, y: i32) -> i32 { + self.section_coord_to_index(y >> 4) + } + + fn section_coord_to_index(&self, coord: i32) -> i32 { + coord - self.bottom_section_coord() + } + + fn section_index_to_coord(&self, index: i32) -> i32 { + index + self.bottom_section_coord() + } +} + +pub struct StandardHeightLimitView { + height: i32, + bottom_y: i32, +} + +impl StandardHeightLimitView { + pub fn new(height: i32, bottom_y: i32) -> Self { + Self { height, bottom_y } + } +} + +impl HeightLimitViewImpl for StandardHeightLimitView { + fn height(&self) -> i32 { + self.height + } + + fn bottom_y(&self) -> i32 { + self.bottom_y + } +} diff --git a/pumpkin-world/src/lib.rs b/pumpkin-world/src/lib.rs index dc1e73d1a..dd1fbafe5 100644 --- a/pumpkin-world/src/lib.rs +++ b/pumpkin-world/src/lib.rs @@ -5,6 +5,7 @@ pub mod coordinates; pub mod cylindrical_chunk_iterator; pub mod dimension; pub mod global_registry; +mod height; pub mod item; pub mod level; mod world_gen; diff --git a/pumpkin-world/src/world_gen/blender.rs b/pumpkin-world/src/world_gen/blender.rs deleted file mode 100644 index c31446037..000000000 --- a/pumpkin-world/src/world_gen/blender.rs +++ /dev/null @@ -1,9 +0,0 @@ -use super::noise::density::NoisePos; - -pub struct Blender {} - -impl Blender { - pub fn apply_blend_density(&self, pos: &impl NoisePos, density: f64) -> f64 { - unimplemented!() - } -} diff --git a/pumpkin-world/src/world_gen/blender/data.rs b/pumpkin-world/src/world_gen/blender/data.rs new file mode 100644 index 000000000..d2559eb6f --- /dev/null +++ b/pumpkin-world/src/world_gen/blender/data.rs @@ -0,0 +1,391 @@ +use crate::{ + self as pumpkin_world, + biome::Biome, + block::BlockId, + height::{HeightLimitView, HeightLimitViewImpl, StandardHeightLimitView}, + world_gen::{ + chunk::{BlockPos, Chunk, GenerationState, HeightMapType}, + Direction, + }, +}; +use num_traits::PrimInt; +use pumpkin_macros::block_id; + +pub const SURFACE_BLOCKS: [BlockId; 11] = [ + block_id!("minecraft:podzol"), + block_id!("minecraft:gravel"), + block_id!("minecraft:grass_block"), + block_id!("minecraft:stone"), + block_id!("minecraft:coarse_dirt"), + block_id!("minecraft:sand"), + block_id!("minecraft:red_sand"), + block_id!("minecraft:mycelium"), + block_id!("minecraft:snow_block"), + block_id!("minecraft:terracotta"), + block_id!("minecraft:dirt"), +]; + +const BIOMES_PER_CHUNK: usize = 16 >> 2; +const LAST_CHUNK_BIOME_INDEX: usize = BIOMES_PER_CHUNK - 1; +const CHUNK_BIOME_END_INDEX: usize = BIOMES_PER_CHUNK; +const NORTH_WEST_END_INDEX: usize = 2 * LAST_CHUNK_BIOME_INDEX + 1; +const SOUTH_EAST_END_INDEX_PART: usize = 2 * CHUNK_BIOME_END_INDEX + 1; +const HORIZONTAL_BIOME_COUNT: usize = NORTH_WEST_END_INDEX + SOUTH_EAST_END_INDEX_PART; + +pub struct BlendingData { + pub(crate) height_limit: HeightLimitView, + pub(crate) surface_heights: Box<[f64; HORIZONTAL_BIOME_COUNT]>, + pub(crate) biomes: Box<[Option>; HORIZONTAL_BIOME_COUNT]>, + pub(crate) collidable_block_densities: Box<[Option>; HORIZONTAL_BIOME_COUNT]>, + initialized: bool, +} + +impl BlendingData { + pub fn get_blending_data(chunk: &Chunk, _chunk_x: i32, _chunk_z: i32) -> Option { + // TODO: We currently assume all chunks have new noise. valid assumption? + if let Some(mut data) = chunk.blending_data() { + if chunk.status() >= GenerationState::Biome { + data.init_chunk_blending_data( + chunk, + &[ + Direction::North, + Direction::NorthWest, + Direction::West, + Direction::SouthWest, + Direction::South, + Direction::SouthEast, + Direction::East, + Direction::NorthEast, + ], + ); + Some(data) + } else { + None + } + } else { + None + } + } + + #[inline] + fn method_39355(i: usize) -> usize { + i & !(i.unsigned_shr(31)) + } + + pub(crate) fn x(index: usize) -> usize { + if index < NORTH_WEST_END_INDEX { + Self::method_39355(LAST_CHUNK_BIOME_INDEX - index) + } else { + let i = index - NORTH_WEST_END_INDEX; + CHUNK_BIOME_END_INDEX - Self::method_39355(CHUNK_BIOME_END_INDEX - i) + } + } + + pub(crate) fn z(index: usize) -> usize { + if index < NORTH_WEST_END_INDEX { + Self::method_39355(index - LAST_CHUNK_BIOME_INDEX) + } else { + let i = index - NORTH_WEST_END_INDEX; + CHUNK_BIOME_END_INDEX - Self::method_39355(i - CHUNK_BIOME_END_INDEX) + } + } + + pub fn height(&self, biome_x: usize, _biome_y: usize, biome_z: usize) -> f64 { + if biome_x == CHUNK_BIOME_END_INDEX || biome_z == CHUNK_BIOME_END_INDEX { + self.surface_heights[Self::south_east_index(biome_x, biome_z)] + } else if biome_x != 0 && biome_z != 0 { + f64::MAX + } else { + self.surface_heights[Self::north_west_index(biome_x, biome_z)] + } + } + + fn collidable_block_density_from_column( + &self, + column: Option<&[f64]>, + half_section_y: i32, + ) -> f64 { + if let Some(column) = column { + let i = self.half_section_height(half_section_y); + if (i >= 0) && ((i as usize) < column.len()) { + column[i as usize] * 0.1f64 + } else { + f64::MAX + } + } else { + f64::MAX + } + } + + pub fn collidable_block_density( + &self, + biome_x: usize, + half_section_y: i32, + biome_z: usize, + ) -> f64 { + if half_section_y == self.bottom_half_section_y() { + 0.1f64 + } else if biome_x == CHUNK_BIOME_END_INDEX || biome_z == CHUNK_BIOME_END_INDEX { + self.collidable_block_density_from_column( + self.collidable_block_densities[Self::south_east_index(biome_x, biome_z)] + .as_deref(), + half_section_y, + ) + } else if biome_x != 0 && biome_z != 0 { + f64::MAX + } else { + self.collidable_block_density_from_column( + self.collidable_block_densities[Self::north_west_index(biome_x, biome_z)] + .as_deref(), + half_section_y, + ) + } + } + + fn new(bottom_section_y: i32, top_section_y: i32, heights: Option<&[f64]>) -> Self { + let heights = match heights { + Some(heights) => { + let mut owned_heights = [0f64; HORIZONTAL_BIOME_COUNT]; + assert!( + heights.len() == HORIZONTAL_BIOME_COUNT, + "Heights needs to be the right length" + ); + owned_heights + .iter_mut() + .zip(heights) + .for_each(|(new, old)| { + *new = *old; + }); + owned_heights + } + None => [f64::MAX; HORIZONTAL_BIOME_COUNT], + }; + + let collidable_block_densities: [Option>; HORIZONTAL_BIOME_COUNT] = + [const { None }; HORIZONTAL_BIOME_COUNT]; + let biomes: [Option>; HORIZONTAL_BIOME_COUNT] = + [const { None }; HORIZONTAL_BIOME_COUNT]; + + let i = bottom_section_y << 4; + let j = (top_section_y << 4) - i; + let height_limit = HeightLimitView::Standard(StandardHeightLimitView::new(i, j)); + + Self { + height_limit, + surface_heights: Box::new(heights.clone()), + biomes: Box::new(biomes), + collidable_block_densities: Box::new(collidable_block_densities), + initialized: false, + } + } + + pub fn vertical_half_section_count(&self) -> i32 { + self.height_limit.vertical_section_count() * 2 + } + + fn collidable_and_not_tree(chunk: &Chunk, pos: &BlockPos) -> bool { + let state = chunk.get_block_state(pos); + if state.is_air() + || state.has_tag("leaves") + || state.has_tag("logs") + || state.is_block(block_id!("minecraft:brown_mushroom_block")) + || state.is_block(block_id!("minecraft:red_mushroom_block")) + { + false + } else { + state.collision_shape(chunk, pos).is_empty() + } + } + + fn above_collidable_block_value(chunk: &Chunk, pos: &BlockPos) -> (f64, BlockPos) { + let pos = pos.down(); + let val = if Self::collidable_and_not_tree(chunk, &pos) { + 1f64 + } else { + -1f64 + }; + (val, pos) + } + + fn north_west_index(biome_x: usize, biome_z: usize) -> usize { + LAST_CHUNK_BIOME_INDEX + biome_x + biome_z + } + + fn south_east_index(biome_x: usize, biome_z: usize) -> usize { + NORTH_WEST_END_INDEX + biome_x + CHUNK_BIOME_END_INDEX - biome_z + } + + fn init_chunk_blending_data(&mut self, chunk: &Chunk, directions: &[Direction]) { + if !self.initialized { + if directions.contains(&Direction::North) + || directions.contains(&Direction::West) + || directions.contains(&Direction::NorthWest) + { + self.init_block_column(Self::north_west_index(0, 0), chunk, 0, 0); + } + + if directions.contains(&Direction::North) { + for i in 1..BIOMES_PER_CHUNK { + self.init_block_column(Self::north_west_index(i, 0), chunk, (4 * i) as i32, 0); + } + } + + if directions.contains(&Direction::West) { + for i in 1..BIOMES_PER_CHUNK { + self.init_block_column(Self::north_west_index(0, i), chunk, 0, (4 * i) as i32); + } + } + + if directions.contains(&Direction::East) { + for i in 1..BIOMES_PER_CHUNK { + self.init_block_column( + Self::south_east_index(CHUNK_BIOME_END_INDEX, i), + chunk, + 15, + (4 * i) as i32, + ); + } + } + + if directions.contains(&Direction::South) { + for i in 1..BIOMES_PER_CHUNK { + self.init_block_column( + Self::south_east_index(i, CHUNK_BIOME_END_INDEX), + chunk, + (4 * i) as i32, + 15, + ); + } + } + + if directions.contains(&Direction::East) && directions.contains(&Direction::NorthEast) { + self.init_block_column( + Self::south_east_index(CHUNK_BIOME_END_INDEX, 0), + chunk, + 15, + 0, + ); + } + + if directions.contains(&Direction::East) + && directions.contains(&Direction::South) + && directions.contains(&Direction::SouthEast) + { + self.init_block_column( + Self::south_east_index(CHUNK_BIOME_END_INDEX, CHUNK_BIOME_END_INDEX), + chunk, + 15, + 15, + ); + } + + self.initialized = true; + } + } + + fn collidable_block_density_below(chunk: &Chunk, pos: &BlockPos) -> (f64, BlockPos) { + let (val, new_pos) = Self::above_collidable_block_value(chunk, &pos); + let mut d = val; + let mut pos = new_pos; + + for _ in 0..6 { + let (val, new_pos) = Self::above_collidable_block_value(chunk, &pos); + d += val; + pos = new_pos; + } + + (d, pos) + } + + pub fn bottom_half_section_y(&self) -> i32 { + self.height_limit.bottom_section_coord() * 2 + } + + fn half_section_height(&self, section_y: i32) -> i32 { + section_y - (self.bottom_half_section_y() + 1) + } + + fn init_block_column(&mut self, index: usize, chunk: &Chunk, chunk_x: i32, chunk_z: i32) { + if self.surface_heights[index] == f64::MAX { + self.surface_heights[index] = self.surface_block_y(chunk, chunk_x, chunk_z) as f64; + } + self.collidable_block_densities[index] = Some(self.collidable_block_density_column( + chunk, + chunk_x, + chunk_z, + self.surface_heights[index].floor() as i32, + )); + self.biomes[index] = Some(self.vertical_biome_sections(chunk, chunk_x, chunk_z)); + } + + fn vertical_biome_sections(&self, chunk: &Chunk, block_x: i32, block_z: i32) -> Vec { + (0..self.vertical_biome_count()) + .map(|i| { + let j = i + (self.height_limit.bottom_y() >> 2); + chunk.biome_for_noise_gen(block_x >> 2, j, block_z >> 2) + }) + .collect() + } + + fn vertical_biome_count(&self) -> i32 { + self.height_limit.vertical_section_count() << 2 + } + + fn collidable_block_density_column( + &self, + chunk: &Chunk, + chunk_x: i32, + chunk_z: i32, + height: i32, + ) -> Vec { + let mut ds: Vec = (0..self.vertical_half_section_count()) + .map(|_| -1f64) + .collect(); + + let pos = BlockPos::new(chunk_x, self.height_limit.top_y(), chunk_z); + let (mut d, mut pos) = Self::collidable_block_density_below(chunk, &pos); + + for i in (0..=(ds.len() - 2)).rev() { + let (e, local_pos) = Self::above_collidable_block_value(chunk, &pos); + let (f, local_pos) = Self::collidable_block_density_below(chunk, &local_pos); + ds[i] = (d + e + f) / 15f64; + d = f; + pos = local_pos; + } + + let i = self.half_section_height(height / 8); + if i >= 0 && (i as usize) < (ds.len() - 1) { + let e = (height as f64 + 0.5f64) % 8f64 / 8f64; + let f = (1f64 - e) / e; + let g = f.max(1f64) * 0.25f64; + ds[(i + 1) as usize] = -f / g; + ds[i as usize] = 1f64 / g; + } + + ds + } + + fn surface_block_y(&self, chunk: &Chunk, block_x: i32, block_z: i32) -> i32 { + let i = if let Some(value) = + chunk.sample_height_map(HeightMapType::WorldGenSurface, block_x, block_z) + { + value + } else { + self.height_limit.top_y() + }; + + let j = self.height_limit.bottom_y(); + + for height in (j..=i).rev() { + if SURFACE_BLOCKS.contains( + &chunk + .get_block_state(&BlockPos::new(block_x, height, block_z)) + .block(), + ) { + return height; + } + } + + j + } +} diff --git a/pumpkin-world/src/world_gen/blender/mod.rs b/pumpkin-world/src/world_gen/blender/mod.rs new file mode 100644 index 000000000..be1755fb9 --- /dev/null +++ b/pumpkin-world/src/world_gen/blender/mod.rs @@ -0,0 +1,322 @@ +use std::{collections::HashMap, sync::LazyLock}; + +use data::BlendingData; +use enum_dispatch::enum_dispatch; +use pumpkin_core::{ + math::{hypot, magnitude}, + random::{xoroshiro128::Xoroshiro, RandomGenerator, RandomImpl}, +}; + +use crate::{biome::Biome, height::HeightLimitViewImpl}; + +use super::{ + biome_coords, + chunk::Chunk, + noise::{builtin_noise_params, density::NoisePosImpl, lerp, perlin::DoublePerlinNoiseSampler}, + supplier::{BiomeSupplier, StaticBiomeSupplier}, +}; + +pub mod data; + +static OFFSET_NOISE: LazyLock = LazyLock::new(|| { + DoublePerlinNoiseSampler::new( + &mut RandomGenerator::Xoroshiro(Xoroshiro::from_seed(42)), + &builtin_noise_params::OFFSET, + ) +}); +const BLENDING_BIOME_DISTANCE_THRESHOLD: i32 = (7 << 2) - 1; +const BLENDING_CHUNK_DISTANCE_THRESHOLD: i32 = (BLENDING_BIOME_DISTANCE_THRESHOLD + 3) >> 2; +const CLOSE_BLENDING_DISTANCE_THRESHOLD: i32 = 5 >> 2; + +pub struct BlendResult { + alpha: f64, + offset: f64, +} + +#[enum_dispatch(BlenderImpl)] +pub enum Blender { + NoBlendBlender, +} + +#[enum_dispatch] +pub trait BlenderImpl { + fn apply_blend_density(&self, pos: &impl NoisePosImpl, density: f64) -> f64; + fn calculate(&self, block_x: i32, block_z: i32) -> BlendResult; + fn biome_supplier(&self, supplier: &BiomeSupplier) -> BiomeSupplier; +} + +pub struct NoBlendBlender {} +impl BlenderImpl for NoBlendBlender { + fn calculate(&self, _block_x: i32, _block_z: i32) -> BlendResult { + BlendResult { + alpha: 1f64, + offset: 0f64, + } + } + + fn apply_blend_density(&self, _pos: &impl NoisePosImpl, density: f64) -> f64 { + density + } + + fn biome_supplier(&self, supplier: &BiomeSupplier) -> BiomeSupplier { + supplier.clone() + } +} + +struct StandardBlender { + blend_data: HashMap, + close_blend_data: HashMap, +} + +#[derive(Clone)] +enum BlendingSampleType { + Height, + Density, +} + +impl StandardBlender { + pub fn new( + blend_data: HashMap, + close_blend_data: HashMap, + ) -> Self { + Self { + blend_data, + close_blend_data, + } + } + + fn blend_offset(height: f64) -> f64 { + let e = height + 0.5f64; + let f = ((e % 8f64) + 8f64) % 8f64; + (32f64 * (e - 128f64) - 3f64 * (e - 128f64) * f + 3f64 * f * f) + / (128f64 * (32f64 - 3f64 * f)) + } + + fn sample_closest( + &self, + sample_type: BlendingSampleType, + biome_x: i32, + biome_y: i32, + biome_z: i32, + ) -> f64 { + let i = biome_coords::to_chunk(biome_x); + let j = biome_coords::to_chunk(biome_z); + + let bl = (biome_x & 3) == 0; + let bl2 = (biome_z & 3) == 0; + + let mut d = self.sample(sample_type.clone(), i, j, biome_x, biome_y, biome_z); + + if d == f64::MAX { + if bl && bl2 { + d = self.sample(sample_type.clone(), i - 1, j - 1, biome_x, biome_y, biome_z); + } + + if d == f64::MAX && bl { + d = self.sample(sample_type.clone(), i - 1, j, biome_x, biome_y, biome_z); + } + + if d == f64::MAX && bl2 { + d = self.sample(sample_type.clone(), i, j - 1, biome_x, biome_y, biome_z); + } + } + + d + } + + fn sample( + &self, + sample_type: BlendingSampleType, + chunk_x: i32, + chunk_z: i32, + biome_x: i32, + biome_y: i32, + biome_z: i32, + ) -> f64 { + if let Some(blending_data) = self.blend_data.get(&Chunk::hash(chunk_x, chunk_z)) { + match sample_type { + BlendingSampleType::Height => blending_data.height( + (biome_x - biome_coords::from_chunk(chunk_x)) as usize, + biome_y as usize, + (biome_z - biome_coords::from_chunk(chunk_z)) as usize, + ), + BlendingSampleType::Density => blending_data.collidable_block_density( + (biome_x - biome_coords::from_chunk(chunk_x)) as usize, + biome_y, + (biome_z - biome_coords::from_chunk(chunk_z)) as usize, + ), + } + } else { + f64::MAX + } + } + + fn blend_biome(&self, x: i32, y: i32, z: i32) -> Option { + for (k, v) in self.blend_data.iter() { + let biome_x = biome_coords::from_chunk(Chunk::packed_x(*k)); + let biome_z = biome_coords::from_chunk(Chunk::packed_z(*k)); + + if y >= biome_coords::from_block(v.height_limit.bottom_y()) + && y < biome_coords::from_block(v.height_limit.top_y()) + { + let mut val = f64::INFINITY; + let mut biome: Option = None; + + let i = biome_coords::from_block(v.height_limit.bottom_y()); + + for (j, biome_list) in v.biomes.iter().enumerate() { + if let Some(biome_list) = biome_list { + if let Some(internal_biome) = biome_list.get(i as usize) { + let biome_x = biome_x + BlendingData::x(j) as i32; + let biome_z = biome_z + BlendingData::z(j) as i32; + + let dx = hypot((x - biome_x) as f64, (z - biome_z) as f64); + if dx <= BLENDING_BIOME_DISTANCE_THRESHOLD as f64 && dx < val { + val = dx; + biome = Some(*internal_biome) + } + } + } + } + + if val < f64::MAX { + let d = OFFSET_NOISE.sample(x as f64, 0f64, z as f64) * 12f64; + let e = ((val + d) / (BLENDING_BIOME_DISTANCE_THRESHOLD + 1) as f64) + .clamp(0f64, 1f64); + if e <= 0.5f64 { + return Some(biome.unwrap()); + } + } + } + } + + None + } +} + +impl BlenderImpl for StandardBlender { + fn calculate(&self, block_x: i32, block_z: i32) -> BlendResult { + let i = biome_coords::from_block(block_x); + let j = biome_coords::from_block(block_z); + + let d = self.sample_closest(BlendingSampleType::Height, i, 0, j); + if d != f64::MAX { + BlendResult { + alpha: 0f64, + offset: Self::blend_offset(d), + } + } else { + let mut val1 = 0f64; + let mut val2 = 0f64; + let mut val3 = f64::INFINITY; + + for (chunk_pos, data) in self.blend_data.iter() { + let biome_x = biome_coords::from_chunk(Chunk::packed_x(*chunk_pos)); + let biome_z = biome_coords::from_chunk(Chunk::packed_z(*chunk_pos)); + + for (index, height) in data.surface_heights.iter().enumerate() { + if *height != f64::MAX { + let biome_x = biome_x + BlendingData::x(index) as i32; + let biome_z = biome_z + BlendingData::z(index) as i32; + + let dx = hypot((i - biome_x) as f64, (j - biome_z) as f64); + if dx <= BLENDING_BIOME_DISTANCE_THRESHOLD as f64 { + if dx < val3 { + val3 = dx; + } + let ex = 1f64 / (dx * dx * dx * dx); + val2 += *height * ex; + val1 += ex; + } + } + } + } + + if val3 == f64::INFINITY { + BlendResult { + alpha: 1f64, + offset: 0f64, + } + } else { + let e = val2 / val1; + let f = (val3 / (BLENDING_BIOME_DISTANCE_THRESHOLD + 1) as f64).clamp(0f64, 1f64); + let f = 3f64 * f * f - 2f64 * f * f * f; + BlendResult { + alpha: f, + offset: Self::blend_offset(e), + } + } + } + } + + fn apply_blend_density(&self, pos: &impl NoisePosImpl, density: f64) -> f64 { + let i = biome_coords::from_block(pos.x()); + let j = pos.y() / 8; + let k = biome_coords::from_block(pos.z()); + + let d = self.sample_closest(BlendingSampleType::Density, i, j, k); + + if d != f64::MAX { + d + } else { + let mut val1 = 0f64; + let mut val2 = 0f64; + let mut val3 = f64::INFINITY; + + for (chunk_pos, data) in self.close_blend_data.iter() { + let biome_x = biome_coords::from_chunk(Chunk::packed_z(*chunk_pos)); + let biome_y = biome_coords::from_chunk(Chunk::packed_z(*chunk_pos)); + let min_half_section_y = j - 1; + let max_half_section_y = j + 1; + + let one_above = data.bottom_half_section_y() + 1; + let j = 0.max(min_half_section_y - one_above); + let k = data + .vertical_half_section_count() + .min(max_half_section_y - one_above); + + for (index, density_vec) in data.collidable_block_densities.iter().enumerate() { + if let Some(density_vec) = density_vec { + let m = biome_x + BlendingData::x(index) as i32; + let n = biome_y + BlendingData::z(index) as i32; + + for o in j..k { + let biome_x = m; + let half_section_y = o + one_above; + let biome_z = n; + let density = density_vec[o as usize] * 0.1f64; + + let dx = magnitude( + (i - biome_x) as f64, + ((j - half_section_y) * 2) as f64, + (k - biome_z) as f64, + ); + + if dx <= 2f64 { + if dx < val3 { + val3 = dx; + } + + let ex = 1f64 / (dx * dx * dx * dx); + val2 += density * ex; + val1 += ex; + } + } + } + } + } + + if val3 == f64::INFINITY { + density + } else { + let e = val2 / val1; + let f = (val3 / 3f64).clamp(0f64, 1f64); + lerp(f, e, density) + } + } + } + + fn biome_supplier(&self, _supplier: &BiomeSupplier) -> BiomeSupplier { + BiomeSupplier::Static(StaticBiomeSupplier {}) + } +} diff --git a/pumpkin-world/src/world_gen/chunk.rs b/pumpkin-world/src/world_gen/chunk.rs index cd46fe801..b268fd5ad 100644 --- a/pumpkin-world/src/world_gen/chunk.rs +++ b/pumpkin-world/src/world_gen/chunk.rs @@ -1,8 +1,12 @@ -use lazy_static::lazy_static; +use std::ops::Add; -use crate::chunk::ChunkData; +use num_traits::PrimInt; -#[derive(Clone)] +use crate::{biome::Biome, block::BlockId, chunk::ChunkData, height::HeightLimitViewImpl}; + +use super::{biome_coords, blender::data::BlendingData}; + +#[derive(Clone, PartialEq, PartialOrd)] pub enum GenerationState { Empty, StructureStart, @@ -18,11 +22,204 @@ pub enum GenerationState { Full, } +pub struct BlockPos { + x: i32, + y: i32, + z: i32, +} + +impl BlockPos { + pub fn new(x: i32, y: i32, z: i32) -> Self { + Self { x, y, z } + } + + pub fn x(&self) -> i32 { + self.x + } + + pub fn y(&self) -> i32 { + self.y + } + + pub fn z(&self) -> i32 { + self.z + } + + pub fn down(&self) -> Self { + self.down_by(1) + } + + pub fn down_by(&self, count: i32) -> Self { + Self { + x: self.x, + y: self.y - count, + z: self.z, + } + } + + pub fn up(&self) -> Self { + self.up_by(1) + } + + pub fn up_by(&self, count: i32) -> Self { + Self { + x: self.x, + y: self.y + count, + z: self.z, + } + } + + pub fn north(&self) -> Self { + self.north_by(1) + } + + pub fn north_by(&self, count: i32) -> Self { + Self { + x: self.x, + y: self.y, + z: self.z - count, + } + } + + pub fn south(&self) -> Self { + self.south_by(1) + } + + pub fn south_by(&self, count: i32) -> Self { + Self { + x: self.x, + y: self.y, + z: self.z + count, + } + } + + pub fn west(&self) -> Self { + self.west_by(1) + } + + pub fn west_by(&self, count: i32) -> Self { + Self { + x: self.x - count, + y: self.y, + z: self.z, + } + } + + pub fn east(&self) -> Self { + self.east_by(1) + } + + pub fn east_by(&self, count: i32) -> Self { + Self { + x: self.x + count, + y: self.y, + z: self.z, + } + } +} + +impl Add for BlockPos { + type Output = Self; + + fn add(self, rhs: Self) -> Self::Output { + Self { + x: self.x + rhs.x, + y: self.y + rhs.y, + z: self.z + rhs.z, + } + } +} + +pub enum HeightMapType { + WorldGenSurface, + WorldSurface, + WorldGenOceanFloor, + OceanFloor, + MotionBlocking, + MotionBlockingNoLeaves, +} + +pub struct VoxelShape {} + +impl VoxelShape { + pub fn is_empty(&self) -> bool { + unimplemented!() + } +} + +pub struct BlockState {} + +impl BlockState { + pub fn block(&self) -> BlockId { + unimplemented!() + } + + pub fn is_air(&self) -> bool { + unimplemented!() + } + + pub fn has_tag(&self, tag: &str) -> bool { + unimplemented!() + } + + pub fn is_block(&self, id: BlockId) -> bool { + unimplemented!() + } + + pub fn collision_shape(&self, chunk: &Chunk, pos: &BlockPos) -> VoxelShape { + unimplemented!() + } +} + pub struct Chunk { data: ChunkData, state: GenerationState, } +impl Chunk { + pub fn hash(chunk_x: i32, chunk_z: i32) -> u64 { + (chunk_x as u64 & 4294967295u64) | ((chunk_z as u64 & 4294967295u64) << 32) + } + + pub fn packed_x(pos: u64) -> i32 { + (pos & 4294967295u64) as i32 + } + + pub fn packed_z(pos: u64) -> i32 { + (pos.unsigned_shr(32) & 4294967295u64) as i32 + } + + pub fn get_block_state(&self, pos: &BlockPos) -> BlockState { + unimplemented!() + } + + pub fn sample_height_map(&self, map: HeightMapType, x: i32, y: i32) -> Option { + unimplemented!() + } + + pub fn biome_for_noise_gen(&self, biome_x: i32, biome_y: i32, biome_z: i32) -> Biome { + unimplemented!() + } + + pub fn blending_data(&self) -> Option { + unimplemented!() + } + + pub fn status(&self) -> GenerationState { + self.state.clone() + } +} + +impl HeightLimitViewImpl for Chunk { + fn bottom_y(&self) -> i32 { + unimplemented!() + } + + fn height(&self) -> i32 { + unimplemented!() + } +} + pub struct GenerationShapeConfig { y_min: i32, height: i32, @@ -52,6 +249,29 @@ impl GenerationShapeConfig { vertical, } } + + pub fn trim_height(&self, view: &impl HeightLimitViewImpl) -> Self { + let i = self.y_min.max(view.bottom_y()); + let j = (self.y_min + self.height).min(view.top_y()) - i; + Self { + y_min: i, + height: j, + horizontal: self.horizontal, + vertical: self.vertical, + } + } + + pub fn min_y(&self) -> i32 { + self.y_min + } + + pub fn height(&self) -> i32 { + self.height + } + + pub fn vertical_cell_block_count(&self) -> i32 { + biome_coords::to_block(self.vertical) + } } pub mod shape_configs { diff --git a/pumpkin-world/src/world_gen/implementation/aquifer.rs b/pumpkin-world/src/world_gen/implementation/aquifer.rs new file mode 100644 index 000000000..eb40404be --- /dev/null +++ b/pumpkin-world/src/world_gen/implementation/aquifer.rs @@ -0,0 +1,60 @@ +use crate::{self as pumpkin_world, world_gen::noise::density::NoisePosImpl}; +use pumpkin_macros::block_id; + +use crate::block::BlockId; + +#[derive(Clone)] +struct FluidLevel { + y: i32, + state: BlockId, +} + +impl FluidLevel { + fn get_block(&self, y: i32) -> BlockId { + if y < self.y { + self.state + } else { + block_id!("minecraft:air") + } + } +} + +pub struct FluidLevelSampler { + sea_level: i32, + fluid_level_1: FluidLevel, + fluid_level_2: FluidLevel, +} + +impl FluidLevelSampler { + fn get_fluid_level(&self, _x: i32, y: i32, _z: i32) -> FluidLevel { + if y < (-51).min(self.sea_level) { + self.fluid_level_1.clone() + } else { + self.fluid_level_2.clone() + } + } +} + +pub trait AquiferSamplerImpl { + fn apply(&self, pos: &impl NoisePosImpl, density: f64) -> Option; +} + +pub struct AquiferSeaLevel { + level_sampler: FluidLevelSampler, +} + +impl AquiferSamplerImpl for AquiferSeaLevel { + fn apply(&self, pos: &impl NoisePosImpl, density: f64) -> Option { + if density > 0f64 { + None + } else { + Some( + self.level_sampler + .get_fluid_level(pos.x(), pos.y(), pos.z()) + .get_block(pos.y()), + ) + } + } +} + +pub struct Aquifier {} diff --git a/pumpkin-world/src/world_gen/implementation/mod.rs b/pumpkin-world/src/world_gen/implementation/mod.rs index 7aa11a83b..f8fb21cec 100644 --- a/pumpkin-world/src/world_gen/implementation/mod.rs +++ b/pumpkin-world/src/world_gen/implementation/mod.rs @@ -1,2 +1,33 @@ +use super::{ + blender::Blender, + chunk::{Chunk, GenerationShapeConfig}, + noise::config::NoiseConfig, +}; + +mod aquifer; pub mod overworld; pub mod superflat; +mod surface_builder; + +pub fn populate_noise( + chunk: &mut Chunk, + blender: &Blender, + config: &NoiseConfig, + shape: &GenerationShapeConfig, +) { + let shape = shape.trim_height(chunk); + let i = shape.min_y(); + let j = i / shape.vertical_cell_block_count(); + let k = shape.height() / shape.vertical_cell_block_count(); + + internal_populate_noise(chunk, blender, config, j, k); +} + +fn internal_populate_noise( + chunk: &mut Chunk, + blender: &Blender, + config: &NoiseConfig, + min_cell_y: i32, + cell_height: i32, +) { +} diff --git a/pumpkin-world/src/world_gen/implementation/overworld/terrain_params.rs b/pumpkin-world/src/world_gen/implementation/overworld/terrain_params.rs index 01a81c77c..31d5ffbae 100644 --- a/pumpkin-world/src/world_gen/implementation/overworld/terrain_params.rs +++ b/pumpkin-world/src/world_gen/implementation/overworld/terrain_params.rs @@ -1,5 +1,7 @@ // From da java +use std::sync::Arc; + use crate::world_gen::noise::density::spline::{ FloatAmplifier, Spline, SplineBuilder, SplineValue, }; @@ -34,7 +36,12 @@ fn meth_42047(f: f32, g: f32, h: f32, i: f32) -> f32 { (g - f) / (i - h) } -fn meth_42050(function: DensityFunction, f: f32, bl: bool, amplifier: FloatAmplifier) -> Spline { +fn meth_42050( + function: Arc, + f: f32, + bl: bool, + amplifier: FloatAmplifier, +) -> Spline { let mut builder = SplineBuilder::new(function, amplifier); let i = get_offset_value(-1f32, f, -0.7f32); @@ -75,7 +82,7 @@ fn meth_42050(function: DensityFunction, f: f32, bl: bool, amplifier: FloatAmpli #[allow(clippy::too_many_arguments)] fn meth_42048( - ridges: DensityFunction, + ridges: Arc, continental: f32, f: f32, g: f32, @@ -96,9 +103,9 @@ fn meth_42048( } fn method_42054<'a>( - erosion: DensityFunction<'a>, - ridges: DensityFunction<'a>, - ridges_folded: DensityFunction<'a>, + erosion: Arc>, + ridges: Arc>, + ridges_folded: Arc>, f: f32, bl: bool, amplifier: FloatAmplifier, @@ -173,8 +180,8 @@ fn method_42054<'a>( } fn method_42052<'a>( - ridges: DensityFunction<'a>, - ridges_folded: DensityFunction<'a>, + ridges: Arc>, + ridges_folded: Arc>, f: f32, g: f32, amplifier: FloatAmplifier, @@ -209,7 +216,11 @@ fn method_42052<'a>( builder.build() } -fn method_42049<'a>(ridges: DensityFunction<'a>, f: f32, amplifier: FloatAmplifier) -> Spline<'a> { +fn method_42049<'a>( + ridges: Arc>, + f: f32, + amplifier: FloatAmplifier, +) -> Spline<'a> { let g = 0.63f32 * f; let h = 0.3f32 * f; SplineBuilder::new(ridges, amplifier) @@ -219,9 +230,9 @@ fn method_42049<'a>(ridges: DensityFunction<'a>, f: f32, amplifier: FloatAmplifi } fn method_42053<'a>( - erosion: DensityFunction<'a>, - ridges: DensityFunction<'a>, - ridges_folded: DensityFunction<'a>, + erosion: Arc>, + ridges: Arc>, + ridges_folded: Arc>, f: f32, g: f32, h: f32, @@ -253,8 +264,8 @@ fn method_42053<'a>( #[allow(clippy::too_many_arguments)] fn create_continental_offset_spline<'a>( - erosion: DensityFunction<'a>, - ridges: DensityFunction<'a>, + erosion: Arc>, + ridges: Arc>, continental: f32, f: f32, g: f32, @@ -361,9 +372,9 @@ fn create_continental_offset_spline<'a>( } pub fn create_offset_spline<'a>( - contentents: DensityFunction<'a>, - erosion: DensityFunction<'a>, - ridges: DensityFunction<'a>, + contentents: Arc>, + erosion: Arc>, + ridges: Arc>, amplified: bool, ) -> Spline<'a> { let amplification = if amplified { @@ -440,10 +451,10 @@ pub fn create_offset_spline<'a>( } pub fn create_factor_spline<'a>( - continents: DensityFunction<'a>, - erosion: DensityFunction<'a>, - ridges: DensityFunction<'a>, - ridges_folded: DensityFunction<'a>, + continents: Arc>, + erosion: Arc>, + ridges: Arc>, + ridges_folded: Arc>, amplified: bool, ) -> Spline<'a> { let amplification = if amplified { @@ -506,10 +517,10 @@ pub fn create_factor_spline<'a>( } pub fn create_jaggedness_spline<'a>( - continents: DensityFunction<'a>, - erosion: DensityFunction<'a>, - ridges: DensityFunction<'a>, - ridges_folded: DensityFunction<'a>, + continents: Arc>, + erosion: Arc>, + ridges: Arc>, + ridges_folded: Arc>, amplified: bool, ) -> Spline<'a> { let amplification = if amplified { diff --git a/pumpkin-world/src/world_gen/implementation/surface_builder.rs b/pumpkin-world/src/world_gen/implementation/surface_builder.rs new file mode 100644 index 000000000..e69de29bb diff --git a/pumpkin-world/src/world_gen/mod.rs b/pumpkin-world/src/world_gen/mod.rs index 112645a71..448ed8ab9 100644 --- a/pumpkin-world/src/world_gen/mod.rs +++ b/pumpkin-world/src/world_gen/mod.rs @@ -1,11 +1,12 @@ mod blender; -mod chunk; +pub mod chunk; mod generator; mod generic_generator; mod implementation; mod noise; -mod sampler; +pub mod sampler; mod seed; +mod supplier; pub use generator::WorldGenerator; use implementation::overworld::biome::plains::PlainsGenerator; @@ -17,3 +18,51 @@ pub fn get_world_gen(seed: Seed) -> Box { // TODO decide which WorldGenerator to pick based on config. Box::new(PlainsGenerator::new(seed)) } + +pub mod biome_coords { + use num_traits::PrimInt; + + #[inline] + pub fn from_block(coord: T) -> T + where + T: PrimInt, + { + coord >> 2 + } + + #[inline] + pub fn to_block(coord: T) -> T + where + T: PrimInt, + { + coord << 2 + } + + #[inline] + pub fn from_chunk(coord: T) -> T + where + T: PrimInt, + { + coord << 2 + } + + #[inline] + pub fn to_chunk(coord: T) -> T + where + T: PrimInt, + { + coord >> 2 + } +} + +#[derive(PartialEq)] +pub enum Direction { + North, + NorthEast, + East, + SouthEast, + South, + SouthWest, + West, + NorthWest, +} diff --git a/pumpkin-world/src/world_gen/noise/chunk_sampler.rs b/pumpkin-world/src/world_gen/noise/chunk_sampler.rs new file mode 100644 index 000000000..c8a60f4d3 --- /dev/null +++ b/pumpkin-world/src/world_gen/noise/chunk_sampler.rs @@ -0,0 +1,392 @@ +use std::{ + borrow::{Borrow, BorrowMut}, + cell::{Cell, RefCell}, + collections::HashMap, + default, + ops::DerefMut, + rc::Rc, + sync::Arc, +}; + +use crate::world_gen::{ + biome_coords, + blender::{BlendResult, Blender}, + chunk::GenerationShapeConfig, + noise::lerp3, + sampler, +}; + +use super::{ + density::{ + Applier, ApplierImpl, DensityFunction, DensityFunctionImpl, NoisePos, NoisePosImpl, + UnblendedNoisePos, VisitorImpl, WrapperFunction, WrapperType, + }, + lerp, +}; + +struct InterpolationApplier<'a> { + parent_sampler: &'a mut NoisePos<'a>, +} + +impl<'a> ApplierImpl<'a> for InterpolationApplier<'a> { + fn at(&self, index: i32) -> NoisePos<'a> { + /* + match self.parent_sampler { + NoisePos::ChunkNoise(sampler) => { + sampler.start_block_y = + (index + sampler.minimum_cell_y) * sampler.vertical_cell_block_count; + sampler.sample_unique += 1; + sampler.cell_block_y = 0; + sampler.index = index; + + NoisePos::ChunkNoise(sampler) + } + _ => unreachable!(), + } + */ + unimplemented!() + } + + fn fill(&self, _densities: &[f64], function: &DensityFunction<'a>) -> Vec { + // This is hella bad... had to get around borrow checker + // TODO: Fix + + /* + let cell_count = match self.parent_sampler { + NoisePos::ChunkNoise(sampler) => sampler.vertical_cell_count, + _ => unreachable!(), + }; + + let mut result: Vec = Vec::new(); + for i in 0..=cell_count { + match self.parent_sampler { + NoisePos::ChunkNoise(sampler) => { + sampler.start_block_y = + (i + sampler.minimum_cell_y) * sampler.vertical_cell_block_count; + sampler.sample_unique += 1; + sampler.cell_block_y = 0; + sampler.index = i; + // collector.push(function.sample(self.parent_sampler)); + } + + _ => unreachable!(), + } + + let sample = match self.parent_sampler { + NoisePos::ChunkNoise(_) => function.sample(self.parent_sampler), + _ => unreachable!(), + }; + + result.push(sample); + } + + result + */ + unimplemented!() + } +} + +#[derive(Clone)] +pub(crate) struct InterpolatorDensityFunction<'a> { + parent_sampler: &'a ChunkNoiseSampler<'a>, + start_buffer: Vec>, + end_buffer: Vec>, + delegate: Arc>, + x0y0z0: f64, + x0y0z1: f64, + x1y0z0: f64, + x1y0z1: f64, + x0y1z0: f64, + x0y1z1: f64, + x1y1z0: f64, + x1y1z1: f64, + x0z0: f64, + x1z0: f64, + x0z1: f64, + x1z1: f64, + z0: f64, + z1: f64, + result: f64, +} + +impl<'a> InterpolatorDensityFunction<'a> { + // TODO: All instances automatically added to Sampler + fn new( + parent_sampler: &'a ChunkNoiseSampler<'a>, + delegate: Arc>, + vertical_cell_count: i32, + horizontal_cell_count: i32, + ) -> Self { + Self { + parent_sampler, + start_buffer: Self::create_buffer(vertical_cell_count, horizontal_cell_count), + end_buffer: Self::create_buffer(vertical_cell_count, horizontal_cell_count), + delegate, + x0y0z0: 0f64, + x0y0z1: 0f64, + x1y0z0: 0f64, + x1y0z1: 0f64, + x0y1z0: 0f64, + x0y1z1: 0f64, + x1y1z0: 0f64, + x1y1z1: 0f64, + x0z0: 0f64, + x1z0: 0f64, + x0z1: 0f64, + x1z1: 0f64, + z0: 0f64, + z1: 0f64, + result: 0f64, + } + } + + fn on_sampled_cell_corners(&mut self, cell_y: usize, cell_z: usize) { + self.x0y0z0 = self.start_buffer[cell_z][cell_y]; + self.x0y0z1 = self.start_buffer[cell_z + 1][cell_y]; + self.x1y0z0 = self.end_buffer[cell_z][cell_y]; + self.x1y0z1 = self.end_buffer[cell_z + 1][cell_y]; + self.x0y1z0 = self.start_buffer[cell_z][cell_y + 1]; + self.x0y1z1 = self.start_buffer[cell_z + 1][cell_y + 1]; + self.x1y1z0 = self.end_buffer[cell_z][cell_y + 1]; + self.x1y1z1 = self.end_buffer[cell_z + 1][cell_y + 1]; + } + + fn interpolate_y(&mut self, delta: f64) { + self.x0z0 = lerp(delta, self.x0y0z0, self.x0y1z0); + self.x1z0 = lerp(delta, self.x1y0z0, self.x1y1z0); + self.x0z1 = lerp(delta, self.x0y0z1, self.x0y1z1); + self.x1z1 = lerp(delta, self.x1y0z1, self.x1y1z1); + } + + fn interpolate_x(&mut self, delta: f64) { + self.z0 = lerp(delta, self.x0z0, self.x1z0); + self.z1 = lerp(delta, self.x0z1, self.x1z1); + } + + fn interpolate_z(&mut self, delta: f64) { + self.result = lerp(delta, self.z0, self.z1); + } + + fn swap_buffers(&mut self) { + let ds = self.start_buffer.clone(); + self.start_buffer = self.end_buffer.clone(); + self.start_buffer = ds; + } + + fn create_buffer(size_z: i32, size_x: i32) -> Vec> { + let i = size_x + 1; + let j = size_z + 1; + + let mut result = Vec::>::new(); + for _ in 0..i { + result.push((0..j).map(|_| 0f64).collect()) + } + + result + } +} + +impl<'a> DensityFunctionImpl<'a> for InterpolatorDensityFunction<'a> { + fn sample(&self, pos: &super::density::NoisePos) -> f64 { + if let NoisePos::ChunkNoise(sampler) = pos { + if !std::ptr::eq(sampler, self.parent_sampler) { + return self.delegate.sample(pos); + } + } + + assert!(self.parent_sampler.interpolating, "Not interpolating"); + if self.parent_sampler.sampling_for_caches { + lerp3( + self.parent_sampler.cell_block_x as f64 + / self.parent_sampler.horizontal_cell_block_count as f64, + self.parent_sampler.cell_block_y as f64 + / self.parent_sampler.vertical_cell_block_count as f64, + self.parent_sampler.cell_block_z as f64 + / self.parent_sampler.horizontal_cell_block_count as f64, + self.x0y0z0, + self.x1y0z0, + self.x0y1z0, + self.x1y1z0, + self.x0y0z1, + self.x1y0z1, + self.x0y1z1, + self.x1y1z1, + ) + } else { + self.result + } + } + + fn apply(&'a self, visitor: &'a super::density::Visitor) -> Arc> { + visitor.apply(Arc::new(DensityFunction::Wrapper(WrapperFunction::new( + self.delegate.clone(), + WrapperType::Interpolated, + )))) + } + + fn fill(&self, densities: &[f64], applier: &Applier) -> Vec { + if self.parent_sampler.sampling_for_caches { + applier.fill(densities, &DensityFunction::Interpolator(self.clone())) + } else { + self.delegate.fill(densities, applier) + } + } + + fn min(&self) -> f64 { + self.delegate.min() + } + + fn max(&self) -> f64 { + self.delegate.max() + } +} + +#[derive(Clone)] +pub(crate) struct FlatCacheDensityFunction<'a> { + parent_sampler: &'a ChunkNoiseSampler<'a>, + delegate: Arc>, + cache: Vec>, +} + +impl<'a> FlatCacheDensityFunction<'a> { + fn new( + parent_sampler: &'a ChunkNoiseSampler<'a>, + delegate: Arc>, + biome_start_x: i32, + biome_start_z: i32, + horizontal_biome_end: usize, + sample: bool, + ) -> Self { + let mut cache: Vec> = Vec::new(); + for _ in 0..(horizontal_biome_end + 1) { + cache.push((0..(horizontal_biome_end + 1)).map(|_| 0f64).collect()) + } + + if sample { + for i in 0..=horizontal_biome_end { + let j = biome_start_x + i as i32; + let k = biome_coords::to_block(j); + + for l in 0..=horizontal_biome_end { + let m = biome_start_z + l as i32; + let n = biome_coords::to_block(m); + cache[i][l] = + delegate.sample(&NoisePos::Unblended(UnblendedNoisePos::new(k, 0, n))); + } + } + } + + Self { + parent_sampler, + delegate, + cache, + } + } +} + +impl<'a> DensityFunctionImpl<'a> for FlatCacheDensityFunction<'a> { + fn sample(&self, pos: &NoisePos) -> f64 { + let i = biome_coords::from_block(pos.x()); + let j = biome_coords::from_block(pos.z()); + let k = i - self.parent_sampler.start_biome_x; + let l = j - self.parent_sampler.start_biome_z; + if k >= 0 && l >= 0 && (k as usize) < self.cache.len() && (l as usize) < self.cache.len() { + self.cache[k as usize][l as usize] + } else { + self.delegate.sample(pos) + } + } + + fn fill(&self, densities: &[f64], applier: &Applier) -> Vec { + applier.fill(densities, &DensityFunction::FlatCache(self.clone())) + } + + fn apply(&'a self, visitor: &'a super::density::Visitor) -> Arc> { + visitor.apply(Arc::new(DensityFunction::Wrapper(WrapperFunction::new( + self.delegate.apply(visitor), + WrapperType::CacheFlat, + )))) + } + + fn min(&self) -> f64 { + self.delegate.min() + } + + fn max(&self) -> f64 { + self.delegate.max() + } +} + +struct CellCacheDensityFunction {} + +enum BlockStateSampler {} + +pub struct ChunkNoiseSampler<'a> { + shape_config: GenerationShapeConfig, + horizontal_cell_count: i32, + vertical_cell_count: i32, + minimum_cell_y: i32, + start_cell_x: i32, + start_cell_z: i32, + start_biome_x: i32, + start_biome_z: i32, + interpolators: Vec>, + caches: Vec, + surface_height_estimate_cache: HashMap, + initial_density: Arc>, + block_state_sampler: BlockStateSampler, + blender: Blender, + cached_blend_alpha_density_function: FlatCacheDensityFunction<'a>, + cached_blend_offset_density_function: FlatCacheDensityFunction<'a>, + last_blended_column_pos: u64, + last_blending_result: BlendResult, + horizontal_biome_end: i32, + horizontal_cell_block_count: i32, + vertical_cell_block_count: i32, + interpolating: bool, + sampling_for_caches: bool, + start_block_x: i32, + start_block_y: i32, + start_block_z: i32, + cell_block_x: i32, + cell_block_y: i32, + cell_block_z: i32, + sample_unique: u64, + cache_unique: u64, + index: i32, +} + +impl<'a> ApplierImpl<'a> for ChunkNoiseSampler<'a> { + fn at(&self, index: i32) -> NoisePos { + /* + let j = index % self.horizontal_cell_block_count; + let k = index % self.horizontal_cell_block_count; + let l = index % self.horizontal_cell_block_count; + let m = self.vertical_cell_block_count - 1 - (k / self.horizontal_cell_block_count); + + self.cell_block_x = l; + self.cell_block_y = m; + self.cell_block_z = j; + self.index = index; + */ + unimplemented!() + } + + fn fill(&self, densities: &[f64], function: &DensityFunction<'a>) -> Vec { + unimplemented!() + } +} + +impl<'a> NoisePosImpl for ChunkNoiseSampler<'a> { + fn z(&self) -> i32 { + unimplemented!() + } + + fn y(&self) -> i32 { + unimplemented!() + } + + fn x(&self) -> i32 { + unimplemented!() + } +} diff --git a/pumpkin-world/src/world_gen/noise/config.rs b/pumpkin-world/src/world_gen/noise/config.rs new file mode 100644 index 000000000..96bd438b6 --- /dev/null +++ b/pumpkin-world/src/world_gen/noise/config.rs @@ -0,0 +1,10 @@ +use pumpkin_core::random::RandomDeriver; + +use crate::world_gen::supplier::MultiNoiseSampler; + +use super::router::NoiseRouter; + +pub struct NoiseConfig<'a> { + random_deriver: RandomDeriver, + router: NoiseRouter<'a>, +} diff --git a/pumpkin-world/src/world_gen/noise/density/blend.rs b/pumpkin-world/src/world_gen/noise/density/blend.rs index 6f719877d..dd5bcb32e 100644 --- a/pumpkin-world/src/world_gen/noise/density/blend.rs +++ b/pumpkin-world/src/world_gen/noise/density/blend.rs @@ -1,16 +1,21 @@ use std::sync::Arc; -use super::{DensityFunction, DensityFunctionImpl, NoisePos}; +use crate::world_gen::blender::BlenderImpl; + +use super::{ + Applier, ApplierImpl, DensityFunction, DensityFunctionImpl, NoisePos, NoisePosImpl, Visitor, + VisitorImpl, +}; #[derive(Clone)] pub struct BlendOffsetFunction {} impl<'a> DensityFunctionImpl<'a> for BlendOffsetFunction { - fn sample(&self, _pos: &impl super::NoisePos) -> f64 { + fn sample(&self, _pos: &NoisePos) -> f64 { 0f64 } - fn fill(&self, densities: &[f64], _applier: &impl super::Applier) -> Vec { + fn fill(&self, densities: &[f64], _applier: &Applier) -> Vec { densities.iter().map(|_| 0f64).collect() } @@ -22,8 +27,8 @@ impl<'a> DensityFunctionImpl<'a> for BlendOffsetFunction { 0f64 } - fn apply(&'a self, visitor: &'a impl super::Visitor) -> super::DensityFunction<'a> { - visitor.apply(&DensityFunction::BlendOffset(self.clone())) + fn apply(&'a self, visitor: &'a Visitor) -> Arc> { + visitor.apply(Arc::new(DensityFunction::BlendOffset(self.clone()))) } } @@ -31,11 +36,11 @@ impl<'a> DensityFunctionImpl<'a> for BlendOffsetFunction { pub struct BlendAlphaFunction {} impl<'a> DensityFunctionImpl<'a> for BlendAlphaFunction { - fn sample(&self, _pos: &impl super::NoisePos) -> f64 { + fn sample(&self, _pos: &NoisePos) -> f64 { 1f64 } - fn fill(&self, densities: &[f64], _applier: &impl super::Applier) -> Vec { + fn fill(&self, densities: &[f64], _applier: &Applier) -> Vec { densities.iter().map(|_| 1f64).collect() } @@ -47,8 +52,8 @@ impl<'a> DensityFunctionImpl<'a> for BlendAlphaFunction { 1f64 } - fn apply(&'a self, visitor: &'a impl super::Visitor) -> DensityFunction<'a> { - visitor.apply(&DensityFunction::BlendAlpha(self.clone())) + fn apply(&'a self, visitor: &'a Visitor) -> Arc> { + visitor.apply(Arc::new(DensityFunction::BlendAlpha(self.clone()))) } } @@ -64,17 +69,17 @@ impl<'a> BlendDensityFunction<'a> { } impl<'a> BlendDensityFunction<'a> { - fn apply_density(&self, pos: &impl NoisePos, density: f64) -> f64 { + fn apply_density(&self, pos: &NoisePos, density: f64) -> f64 { pos.get_blender().apply_blend_density(pos, density) } } impl<'a> DensityFunctionImpl<'a> for BlendDensityFunction<'a> { - fn sample(&self, pos: &impl super::NoisePos) -> f64 { + fn sample(&self, pos: &NoisePos) -> f64 { self.apply_density(pos, self.function.sample(pos)) } - fn fill(&self, densities: &[f64], applier: &impl super::Applier) -> Vec { + fn fill(&self, densities: &[f64], applier: &Applier) -> Vec { let densities = self.function.fill(densities, applier); densities .iter() @@ -83,11 +88,11 @@ impl<'a> DensityFunctionImpl<'a> for BlendDensityFunction<'a> { .collect() } - fn apply(&'a self, visitor: &'a impl super::Visitor) -> DensityFunction<'a> { + fn apply(&'a self, visitor: &'a Visitor) -> Arc> { let new_function = BlendDensityFunction { - function: Arc::new(self.function.apply(visitor)), + function: self.function.apply(visitor), }; - visitor.apply(&DensityFunction::BlendDensity(new_function)) + visitor.apply(Arc::new(DensityFunction::BlendDensity(new_function))) } fn min(&self) -> f64 { diff --git a/pumpkin-world/src/world_gen/noise/density/end.rs b/pumpkin-world/src/world_gen/noise/density/end.rs index c69ee8f38..671f0bfc5 100644 --- a/pumpkin-world/src/world_gen/noise/density/end.rs +++ b/pumpkin-world/src/world_gen/noise/density/end.rs @@ -1,8 +1,13 @@ +use std::sync::Arc; + use pumpkin_core::random::{legacy_rand::LegacyRand, RandomImpl}; use crate::world_gen::noise::simplex::SimplexNoiseSampler; -use super::{DensityFunction, DensityFunctionImpl}; +use super::{ + Applier, ApplierImpl, DensityFunction, DensityFunctionImpl, NoisePos, NoisePosImpl, Visitor, + VisitorImpl, +}; #[derive(Clone)] pub struct EndIslandFunction { @@ -51,11 +56,11 @@ impl EndIslandFunction { } impl<'a> DensityFunctionImpl<'a> for EndIslandFunction { - fn fill(&self, densities: &[f64], applier: &impl super::Applier) -> Vec { - applier.fill(densities, self) + fn fill(&self, densities: &[f64], applier: &Applier) -> Vec { + applier.fill(densities, &DensityFunction::EndIsland(self.clone())) } - fn sample(&self, pos: &impl super::NoisePos) -> f64 { + fn sample(&self, pos: &NoisePos) -> f64 { (Self::sample_2d(&self.sampler, pos.x() / 8, pos.z() / 8) as f64 - 8f64) / 128f64 } @@ -67,7 +72,7 @@ impl<'a> DensityFunctionImpl<'a> for EndIslandFunction { 0.5625f64 } - fn apply(&'a self, visitor: &'a impl super::Visitor) -> super::DensityFunction<'a> { - visitor.apply(&DensityFunction::EndIsland(self.clone())) + fn apply(&'a self, visitor: &'a Visitor) -> Arc> { + visitor.apply(Arc::new(DensityFunction::EndIsland(self.clone()))) } } diff --git a/pumpkin-world/src/world_gen/noise/density/math.rs b/pumpkin-world/src/world_gen/noise/density/math.rs index c9ffb8193..d25b52de4 100644 --- a/pumpkin-world/src/world_gen/noise/density/math.rs +++ b/pumpkin-world/src/world_gen/noise/density/math.rs @@ -2,7 +2,10 @@ use std::sync::Arc; use log::warn; -use super::{DensityFunction, DensityFunctionImpl, UnaryDensityFunction}; +use super::{ + Applier, DensityFunction, DensityFunctionImpl, NoisePos, UnaryDensityFunction, Visitor, + VisitorImpl, +}; #[derive(Clone)] pub enum LinearType { @@ -20,8 +23,8 @@ pub struct LinearFunction<'a> { } impl<'a> DensityFunctionImpl<'a> for LinearFunction<'a> { - fn apply(&'a self, visitor: &'a impl super::Visitor) -> DensityFunction<'a> { - let new_function = self.input().apply(visitor); + fn apply(&'a self, visitor: &'a Visitor) -> Arc> { + let new_function = self.input.apply(visitor); let d = new_function.min(); let e = new_function.max(); @@ -36,21 +39,21 @@ impl<'a> DensityFunctionImpl<'a> for LinearFunction<'a> { } }; - DensityFunction::Linear(LinearFunction { + Arc::new(DensityFunction::Linear(LinearFunction { action: self.action.clone(), - input: Arc::new(new_function), + input: new_function, min: f, max: g, arg: self.arg, - }) + })) } - fn sample(&self, pos: &impl super::NoisePos) -> f64 { - self.apply_density(self.input().sample(pos)) + fn sample(&self, pos: &NoisePos) -> f64 { + self.apply_density(self.input.sample(pos)) } - fn fill(&self, densities: &[f64], applier: &impl super::Applier) -> Vec { - let densities = self.input().fill(densities, applier); + fn fill(&self, densities: &[f64], applier: &Applier) -> Vec { + let densities = self.input.fill(densities, applier); densities .iter() .map(|val| self.apply_density(*val)) @@ -73,10 +76,6 @@ impl<'a> UnaryDensityFunction<'a> for LinearFunction<'a> { LinearType::Add => density + self.arg, } } - - fn input(&self) -> &DensityFunction { - &self.input - } } #[derive(Clone)] @@ -99,8 +98,8 @@ pub struct BinaryFunction<'a> { impl<'a> BinaryFunction<'a> { pub fn create( action: BinaryType, - arg1: DensityFunction<'a>, - arg2: DensityFunction<'a>, + arg1: Arc>, + arg2: Arc>, ) -> DensityFunction<'a> { let d = arg1.min(); let e = arg2.min(); @@ -154,20 +153,20 @@ impl<'a> BinaryFunction<'a> { _ => unreachable!(), }; - if let DensityFunction::Constant(func) = arg1 { + if let DensityFunction::Constant(func) = arg1.as_ref() { return DensityFunction::Linear(LinearFunction { action, - input: Arc::new(arg2), + input: arg2, min: h, max: i, arg: func.value, }); } - if let DensityFunction::Constant(func) = arg2 { + if let DensityFunction::Constant(func) = arg2.as_ref() { return DensityFunction::Linear(LinearFunction { action, - input: Arc::new(arg1), + input: arg1, min: h, max: i, arg: func.value, @@ -179,8 +178,8 @@ impl<'a> BinaryFunction<'a> { DensityFunction::Binary(BinaryFunction { action, - arg1: Arc::new(arg1), - arg2: Arc::new(arg2), + arg1, + arg2, min: h, max: i, }) @@ -188,7 +187,7 @@ impl<'a> BinaryFunction<'a> { } impl<'a> DensityFunctionImpl<'a> for BinaryFunction<'a> { - fn sample(&self, pos: &impl super::NoisePos) -> f64 { + fn sample(&self, pos: &NoisePos) -> f64 { let d = self.arg1.sample(pos); let e = self.arg2.sample(pos); @@ -212,7 +211,7 @@ impl<'a> DensityFunctionImpl<'a> for BinaryFunction<'a> { } } - fn fill(&self, densities: &[f64], applier: &impl super::Applier) -> Vec { + fn fill(&self, densities: &[f64], applier: &Applier) -> Vec { let densities1 = self.arg1.fill(densities, applier); let densities2 = self.arg2.fill(densities, applier); @@ -240,12 +239,12 @@ impl<'a> DensityFunctionImpl<'a> for BinaryFunction<'a> { } } - fn apply(&'a self, visitor: &'a impl super::Visitor) -> DensityFunction<'a> { - visitor.apply(&BinaryFunction::create( + fn apply(&'a self, visitor: &'a Visitor) -> Arc> { + visitor.apply(Arc::new(BinaryFunction::create( self.action.clone(), self.arg1.apply(visitor), self.arg2.apply(visitor), - )) + ))) } fn max(&self) -> f64 { diff --git a/pumpkin-world/src/world_gen/noise/density/mod.rs b/pumpkin-world/src/world_gen/noise/density/mod.rs index afcc746bd..dc073cd49 100644 --- a/pumpkin-world/src/world_gen/noise/density/mod.rs +++ b/pumpkin-world/src/world_gen/noise/density/mod.rs @@ -1,7 +1,8 @@ -use std::sync::Arc; +use std::{ops::Deref, sync::Arc}; use blend::{BlendAlphaFunction, BlendDensityFunction, BlendOffsetFunction}; use end::EndIslandFunction; +use enum_dispatch::enum_dispatch; use math::{BinaryFunction, BinaryType, LinearFunction}; use noise::{InternalNoise, InterpolatedNoiseSampler, NoiseFunction, ShiftedNoiseFunction}; use offset::{ShiftAFunction, ShiftBFunction}; @@ -9,9 +10,13 @@ use spline::SplineFunction; use unary::{ClampFunction, UnaryFunction, UnaryType}; use weird::WierdScaledFunction; -use crate::world_gen::blender::Blender; +use crate::world_gen::blender::{Blender, NoBlendBlender}; -use super::{clamped_map, perlin::DoublePerlinNoiseParameters}; +use super::{ + chunk_sampler::{ChunkNoiseSampler, FlatCacheDensityFunction, InterpolatorDensityFunction}, + clamped_map, + perlin::DoublePerlinNoiseParameters, +}; mod blend; mod end; @@ -35,7 +40,7 @@ pub mod built_in_noises { use super::{ apply_blending, - blend::BlendOffsetFunction, + blend::{BlendAlphaFunction, BlendOffsetFunction}, end::EndIslandFunction, noise::{InternalNoise, InterpolatedNoiseSampler, NoiseFunction, ShiftedNoiseFunction}, noise_in_range, @@ -48,143 +53,175 @@ pub mod built_in_noises { }; pub struct SlopedCheeseResult<'a> { - pub(crate) offset: DensityFunction<'a>, - pub(crate) factor: DensityFunction<'a>, - pub(crate) depth: DensityFunction<'a>, - pub(crate) jaggedness: DensityFunction<'a>, - pub(crate) sloped_cheese: DensityFunction<'a>, + pub(crate) offset: Arc>, + pub(crate) factor: Arc>, + pub(crate) depth: Arc>, + pub(crate) jaggedness: Arc>, + pub(crate) sloped_cheese: Arc>, } - type BuiltInNoise = LazyLock>; + type BuiltInNoise = LazyLock>>; type BuiltInSlopedCheese = LazyLock>; + pub static BLEND_ALPHA: BuiltInNoise = + LazyLock::new(|| Arc::new(DensityFunction::BlendAlpha(BlendAlphaFunction {}))); + + pub static BLEND_OFFSET: BuiltInNoise = + LazyLock::new(|| Arc::new(DensityFunction::BlendOffset(BlendOffsetFunction {}))); + pub static ZERO: BuiltInNoise = - LazyLock::new(|| DensityFunction::Constant(ConstantFunction::new(0f64))); + LazyLock::new(|| Arc::new(DensityFunction::Constant(ConstantFunction::new(0f64)))); pub static TEN: BuiltInNoise = - LazyLock::new(|| DensityFunction::Constant(ConstantFunction::new(10f64))); + LazyLock::new(|| Arc::new(DensityFunction::Constant(ConstantFunction::new(10f64)))); pub static Y: BuiltInNoise = LazyLock::new(|| { - DensityFunction::ClampedY(YClampedFunction { - from: MIN_HEIGHT * 2, - to: MAX_COLUMN_HEIGHT * 2, - from_val: (MIN_HEIGHT * 2) as f64, - to_val: (MAX_COLUMN_HEIGHT * 2) as f64, + Arc::new({ + DensityFunction::ClampedY(YClampedFunction { + from: MIN_HEIGHT * 2, + to: MAX_COLUMN_HEIGHT * 2, + from_val: (MIN_HEIGHT * 2) as f64, + to_val: (MAX_COLUMN_HEIGHT * 2) as f64, + }) }) }); pub static SHIFT_X: BuiltInNoise = LazyLock::new(|| { - DensityFunction::Wrapper(WrapperFunction::new( - Arc::new(DensityFunction::Wrapper(WrapperFunction::new( - Arc::new(DensityFunction::ShiftA(ShiftAFunction::new(Arc::new( - InternalNoise::new(builtin_noise_params::OFFSET.clone(), None), - )))), - WrapperType::Cache2D, - ))), - WrapperType::CacheFlat, - )) + Arc::new({ + DensityFunction::Wrapper(WrapperFunction::new( + Arc::new(DensityFunction::Wrapper(WrapperFunction::new( + Arc::new(DensityFunction::ShiftA(ShiftAFunction::new(Arc::new( + InternalNoise::new(builtin_noise_params::OFFSET.clone(), None), + )))), + WrapperType::Cache2D, + ))), + WrapperType::CacheFlat, + )) + }) }); pub static SHIFT_Z: BuiltInNoise = LazyLock::new(|| { - DensityFunction::Wrapper(WrapperFunction::new( - Arc::new(DensityFunction::Wrapper(WrapperFunction::new( - Arc::new(DensityFunction::ShiftB(ShiftBFunction::new(Arc::new( - InternalNoise::new(builtin_noise_params::OFFSET.clone(), None), - )))), - WrapperType::Cache2D, - ))), - WrapperType::CacheFlat, - )) + Arc::new({ + DensityFunction::Wrapper(WrapperFunction::new( + Arc::new(DensityFunction::Wrapper(WrapperFunction::new( + Arc::new(DensityFunction::ShiftB(ShiftBFunction::new(Arc::new( + InternalNoise::new(builtin_noise_params::OFFSET.clone(), None), + )))), + WrapperType::Cache2D, + ))), + WrapperType::CacheFlat, + )) + }) }); pub static BASE_3D_NOISE_OVERWORLD: BuiltInNoise = LazyLock::new(|| { - DensityFunction::InterpolatedNoise(InterpolatedNoiseSampler::create_base_3d_noise_function( - 0.25f64, 0.125f64, 80f64, 160f64, 8f64, - )) + Arc::new({ + DensityFunction::InterpolatedNoise( + InterpolatedNoiseSampler::create_base_3d_noise_function( + 0.25f64, 0.125f64, 80f64, 160f64, 8f64, + ), + ) + }) }); pub static BASE_3D_NOISE_NETHER: BuiltInNoise = LazyLock::new(|| { - DensityFunction::InterpolatedNoise(InterpolatedNoiseSampler::create_base_3d_noise_function( - 0.25f64, 0.375f64, 80f64, 60f64, 8f64, - )) + Arc::new({ + DensityFunction::InterpolatedNoise( + InterpolatedNoiseSampler::create_base_3d_noise_function( + 0.25f64, 0.375f64, 80f64, 60f64, 8f64, + ), + ) + }) }); pub static BASE_3D_NOISE_END: BuiltInNoise = LazyLock::new(|| { - DensityFunction::InterpolatedNoise(InterpolatedNoiseSampler::create_base_3d_noise_function( - 0.25f64, 0.25f64, 80f64, 160f64, 4f64, - )) + Arc::new({ + DensityFunction::InterpolatedNoise( + InterpolatedNoiseSampler::create_base_3d_noise_function( + 0.25f64, 0.25f64, 80f64, 160f64, 4f64, + ), + ) + }) }); pub static CONTINENTS_OVERWORLD: BuiltInNoise = LazyLock::new(|| { - DensityFunction::Wrapper(WrapperFunction::new( - Arc::new(DensityFunction::ShiftedNoise(ShiftedNoiseFunction::new( - Arc::new(SHIFT_X.clone()), - Arc::new(ZERO.clone()), - Arc::new(SHIFT_Z.clone()), - 0.25f64, - 0f64, - Arc::new(InternalNoise::new( - builtin_noise_params::CONTINENTALNESS.clone(), - None, - )), - ))), - WrapperType::CacheFlat, - )) + Arc::new({ + DensityFunction::Wrapper(WrapperFunction::new( + Arc::new(DensityFunction::ShiftedNoise(ShiftedNoiseFunction::new( + SHIFT_X.clone(), + ZERO.clone(), + SHIFT_Z.clone(), + 0.25f64, + 0f64, + Arc::new(InternalNoise::new( + builtin_noise_params::CONTINENTALNESS.clone(), + None, + )), + ))), + WrapperType::CacheFlat, + )) + }) }); pub static EROSION_OVERWORLD: BuiltInNoise = LazyLock::new(|| { - DensityFunction::Wrapper(WrapperFunction::new( - Arc::new(DensityFunction::ShiftedNoise(ShiftedNoiseFunction::new( - Arc::new(SHIFT_X.clone()), - Arc::new(ZERO.clone()), - Arc::new(SHIFT_Z.clone()), - 0.25f64, - 0f64, - Arc::new(InternalNoise::new( - builtin_noise_params::EROSION.clone(), - None, - )), - ))), - WrapperType::CacheFlat, - )) + Arc::new({ + DensityFunction::Wrapper(WrapperFunction::new( + Arc::new(DensityFunction::ShiftedNoise(ShiftedNoiseFunction::new( + SHIFT_X.clone(), + ZERO.clone(), + SHIFT_Z.clone(), + 0.25f64, + 0f64, + Arc::new(InternalNoise::new( + builtin_noise_params::EROSION.clone(), + None, + )), + ))), + WrapperType::CacheFlat, + )) + }) }); pub static RIDGES_OVERWORLD: BuiltInNoise = LazyLock::new(|| { - DensityFunction::Wrapper(WrapperFunction::new( - Arc::new(DensityFunction::ShiftedNoise(ShiftedNoiseFunction::new( - Arc::new(SHIFT_X.clone()), - Arc::new(ZERO.clone()), - Arc::new(SHIFT_Z.clone()), - 0.25f64, - 0f64, - Arc::new(InternalNoise::new( - builtin_noise_params::RIDGE.clone(), - None, - )), - ))), - WrapperType::CacheFlat, - )) + Arc::new({ + DensityFunction::Wrapper(WrapperFunction::new( + Arc::new(DensityFunction::ShiftedNoise(ShiftedNoiseFunction::new( + SHIFT_X.clone(), + ZERO.clone(), + SHIFT_Z.clone(), + 0.25f64, + 0f64, + Arc::new(InternalNoise::new( + builtin_noise_params::RIDGE.clone(), + None, + )), + ))), + WrapperType::CacheFlat, + )) + }) }); pub static RIDGES_FOLDED_OVERWORLD: BuiltInNoise = LazyLock::new(|| { - RIDGES_OVERWORLD - .abs() - .add_const(-0.6666666666666666f64) - .abs() - .add_const(-0.3333333333333333f64) - .mul_const(-3f64) + Arc::new({ + RIDGES_OVERWORLD + .abs() + .add_const(-0.6666666666666666f64) + .abs() + .add_const(-0.3333333333333333f64) + .mul_const(-3f64) + }) }); pub static OVERWORLD_SLOPED_CHEESE: BuiltInSlopedCheese = LazyLock::new(|| { sloped_cheese_function( - DensityFunction::Noise(NoiseFunction::new( + Arc::new(DensityFunction::Noise(NoiseFunction::new( Arc::new(InternalNoise::new( builtin_noise_params::JAGGED.clone(), None, )), 1500f64, 0f64, - )), + ))), CONTINENTS_OVERWORLD.clone(), EROSION_OVERWORLD.clone(), RIDGES_OVERWORLD.clone(), @@ -194,49 +231,53 @@ pub mod built_in_noises { }); pub static CONTINENTS_OVERWORLD_LARGE_BIOME: BuiltInNoise = LazyLock::new(|| { - DensityFunction::Wrapper(WrapperFunction::new( - Arc::new(DensityFunction::ShiftedNoise(ShiftedNoiseFunction::new( - Arc::new(SHIFT_X.clone()), - Arc::new(ZERO.clone()), - Arc::new(SHIFT_Z.clone()), - 0.25f64, - 0f64, - Arc::new(InternalNoise::new( - builtin_noise_params::CONTINENTALNESS_LARGE.clone(), - None, - )), - ))), - WrapperType::CacheFlat, - )) + Arc::new({ + DensityFunction::Wrapper(WrapperFunction::new( + Arc::new(DensityFunction::ShiftedNoise(ShiftedNoiseFunction::new( + SHIFT_X.clone(), + ZERO.clone(), + SHIFT_Z.clone(), + 0.25f64, + 0f64, + Arc::new(InternalNoise::new( + builtin_noise_params::CONTINENTALNESS_LARGE.clone(), + None, + )), + ))), + WrapperType::CacheFlat, + )) + }) }); pub static EROSION_OVERWORLD_LARGE_BIOME: BuiltInNoise = LazyLock::new(|| { - DensityFunction::Wrapper(WrapperFunction::new( - Arc::new(DensityFunction::ShiftedNoise(ShiftedNoiseFunction::new( - Arc::new(SHIFT_X.clone()), - Arc::new(ZERO.clone()), - Arc::new(SHIFT_Z.clone()), - 0.25f64, - 0f64, - Arc::new(InternalNoise::new( - builtin_noise_params::EROSION_LARGE.clone(), - None, - )), - ))), - WrapperType::CacheFlat, - )) + Arc::new({ + DensityFunction::Wrapper(WrapperFunction::new( + Arc::new(DensityFunction::ShiftedNoise(ShiftedNoiseFunction::new( + SHIFT_X.clone(), + ZERO.clone(), + SHIFT_Z.clone(), + 0.25f64, + 0f64, + Arc::new(InternalNoise::new( + builtin_noise_params::EROSION_LARGE.clone(), + None, + )), + ))), + WrapperType::CacheFlat, + )) + }) }); pub static OVERWORLD_LARGE_SLOPED_CHEESE: BuiltInSlopedCheese = LazyLock::new(|| { sloped_cheese_function( - DensityFunction::Noise(NoiseFunction::new( + Arc::new(DensityFunction::Noise(NoiseFunction::new( Arc::new(InternalNoise::new( builtin_noise_params::JAGGED.clone(), None, )), 1500f64, 0f64, - )), + ))), CONTINENTS_OVERWORLD_LARGE_BIOME.clone(), EROSION_OVERWORLD_LARGE_BIOME.clone(), RIDGES_OVERWORLD.clone(), @@ -247,14 +288,14 @@ pub mod built_in_noises { pub static OVERWORLD_AMPLIFIED_SLOPED_CHEESE: BuiltInSlopedCheese = LazyLock::new(|| { sloped_cheese_function( - DensityFunction::Noise(NoiseFunction::new( + Arc::new(DensityFunction::Noise(NoiseFunction::new( Arc::new(InternalNoise::new( builtin_noise_params::JAGGED.clone(), None, )), 1500f64, 0f64, - )), + ))), CONTINENTS_OVERWORLD.clone(), EROSION_OVERWORLD.clone(), RIDGES_OVERWORLD.clone(), @@ -264,327 +305,347 @@ pub mod built_in_noises { }); pub static SLOPED_CHEESE_END: BuiltInNoise = LazyLock::new(|| { - DensityFunction::EndIsland(EndIslandFunction::new(0)).add(BASE_3D_NOISE_END.clone()) + Arc::new({ + DensityFunction::EndIsland(EndIslandFunction::new(0)).add(BASE_3D_NOISE_END.clone()) + }) }); pub static CAVES_SPAGHETTI_ROUGHNESS_FUNCTION_OVERWORLD: BuiltInNoise = LazyLock::new(|| { - DensityFunction::Wrapper(WrapperFunction::new( - Arc::new( - noise_in_range( - builtin_noise_params::SPAGHETTI_ROUGHNESS_MODULATOR.clone(), - 1f64, - 1f64, - 0f64, - -0.1f64, - ) - .mul( - DensityFunction::Noise(NoiseFunction::new( - Arc::new(InternalNoise::new( - builtin_noise_params::SPAGHETTI_ROUGHNESS.clone(), - None, - )), + Arc::new({ + DensityFunction::Wrapper(WrapperFunction::new( + Arc::new( + noise_in_range( + builtin_noise_params::SPAGHETTI_ROUGHNESS_MODULATOR.clone(), 1f64, 1f64, - )) - .abs() - .add_const(-0.4f64), + 0f64, + -0.1f64, + ) + .mul(Arc::new( + DensityFunction::Noise(NoiseFunction::new( + Arc::new(InternalNoise::new( + builtin_noise_params::SPAGHETTI_ROUGHNESS.clone(), + None, + )), + 1f64, + 1f64, + )) + .abs() + .add_const(-0.4f64), + )), ), - ), - WrapperType::CacheOnce, - )) + WrapperType::CacheOnce, + )) + }) }); pub static CAVES_SPAGHETTI_2D_THICKNESS_MODULAR_OVERWORLD: BuiltInNoise = LazyLock::new(|| { - DensityFunction::Wrapper(WrapperFunction::new( - Arc::new(noise_in_range( - builtin_noise_params::SPAGHETTI_2D_THICKNESS.clone(), - 2f64, - 1f64, - -0.6f64, - -1.3f64, - )), - WrapperType::CacheOnce, - )) + Arc::new({ + DensityFunction::Wrapper(WrapperFunction::new( + Arc::new(noise_in_range( + builtin_noise_params::SPAGHETTI_2D_THICKNESS.clone(), + 2f64, + 1f64, + -0.6f64, + -1.3f64, + )), + WrapperType::CacheOnce, + )) + }) }); pub static CAVES_SPAGHETTI_2D_OVERWORLD: BuiltInNoise = LazyLock::new(|| { - let function1 = DensityFunction::Noise(NoiseFunction::new( - Arc::new(InternalNoise::new( - builtin_noise_params::SPAGHETTI_2D_MODULATOR.clone(), - None, - )), - 2f64, - 1f64, - )); + Arc::new({ + let function1 = DensityFunction::Noise(NoiseFunction::new( + Arc::new(InternalNoise::new( + builtin_noise_params::SPAGHETTI_2D_MODULATOR.clone(), + None, + )), + 2f64, + 1f64, + )); - let function2 = DensityFunction::Wierd(WierdScaledFunction::new( - Arc::new(function1), - Arc::new(InternalNoise::new( - builtin_noise_params::SPAGHETTI_2D.clone(), - None, - )), - RarityMapper::Caves, - )); + let function2 = DensityFunction::Wierd(WierdScaledFunction::new( + Arc::new(function1), + Arc::new(InternalNoise::new( + builtin_noise_params::SPAGHETTI_2D.clone(), + None, + )), + RarityMapper::Caves, + )); - let function3 = noise_in_range( - builtin_noise_params::SPAGHETTI_2D_ELEVATION.clone(), - 1f64, - 0f64, - ((-64i32) / 8i32) as f64, - 8f64, - ); + let function3 = noise_in_range( + builtin_noise_params::SPAGHETTI_2D_ELEVATION.clone(), + 1f64, + 0f64, + ((-64i32) / 8i32) as f64, + 8f64, + ); - let function4 = CAVES_SPAGHETTI_2D_THICKNESS_MODULAR_OVERWORLD.clone(); + let function4 = CAVES_SPAGHETTI_2D_THICKNESS_MODULAR_OVERWORLD.clone(); - let function5 = function3.add( - DensityFunction::ClampedY(YClampedFunction { - from: -64, - to: 320, - from_val: 8f64, - to_val: -40f64, - }) - .abs(), - ); + let function5 = function3.add(Arc::new( + DensityFunction::ClampedY(YClampedFunction { + from: -64, + to: 320, + from_val: 8f64, + to_val: -40f64, + }) + .abs(), + )); - let function6 = function5.add(function4.clone()).cube(); + let function6 = Arc::new(function5.add(function4.clone()).cube()); - let function7 = function2.add(function4.mul_const(0.083f64)); + let function7 = function2.add(Arc::new(function4.mul_const(0.083f64))); - function7.binary_max(function6).clamp(-1f64, 1f64) + function7.binary_max(function6).clamp(-1f64, 1f64) + }) }); pub static CAVES_ENTRANCES_OVERWORLD: BuiltInNoise = LazyLock::new(|| { - let function = DensityFunction::Noise(NoiseFunction::new( - Arc::new(InternalNoise::new( - builtin_noise_params::SPAGHETTI_3D_RARITY.clone(), - None, - )), - 2f64, - 1f64, - )); + Arc::new({ + let function = DensityFunction::Noise(NoiseFunction::new( + Arc::new(InternalNoise::new( + builtin_noise_params::SPAGHETTI_3D_RARITY.clone(), + None, + )), + 2f64, + 1f64, + )); - let function2 = noise_in_range( - builtin_noise_params::SPAGHETTI_3D_THICKNESS.clone(), - 1f64, - 1f64, - -0.065f64, - -0.088f64, - ); + let function2 = Arc::new(noise_in_range( + builtin_noise_params::SPAGHETTI_3D_THICKNESS.clone(), + 1f64, + 1f64, + -0.065f64, + -0.088f64, + )); - let function3 = DensityFunction::Wierd(WierdScaledFunction::new( - Arc::new(function.clone()), - Arc::new(InternalNoise::new( - builtin_noise_params::SPAGHETTI_3D_1.clone(), - None, - )), - RarityMapper::Tunnels, - )); + let function3 = DensityFunction::Wierd(WierdScaledFunction::new( + Arc::new(function.clone()), + Arc::new(InternalNoise::new( + builtin_noise_params::SPAGHETTI_3D_1.clone(), + None, + )), + RarityMapper::Tunnels, + )); - let function4 = DensityFunction::Wierd(WierdScaledFunction::new( - Arc::new(function), - Arc::new(InternalNoise::new( - builtin_noise_params::SPAGHETTI_3D_2.clone(), - None, - )), - RarityMapper::Tunnels, - )); + let function4 = Arc::new(DensityFunction::Wierd(WierdScaledFunction::new( + Arc::new(function), + Arc::new(InternalNoise::new( + builtin_noise_params::SPAGHETTI_3D_2.clone(), + None, + )), + RarityMapper::Tunnels, + ))); - let function5 = function3 - .binary_max(function4) - .add(function2) - .clamp(-1f64, 1f64); + let function5 = Arc::new( + function3 + .binary_max(function4) + .add(function2) + .clamp(-1f64, 1f64), + ); - let function6 = CAVES_SPAGHETTI_ROUGHNESS_FUNCTION_OVERWORLD.clone(); + let function6 = CAVES_SPAGHETTI_ROUGHNESS_FUNCTION_OVERWORLD.clone(); - let function7 = DensityFunction::Noise(NoiseFunction::new( - Arc::new(InternalNoise::new( - builtin_noise_params::CAVE_ENTRANCE.clone(), - None, - )), - 0.75f64, - 0.5f64, - )); + let function7 = DensityFunction::Noise(NoiseFunction::new( + Arc::new(InternalNoise::new( + builtin_noise_params::CAVE_ENTRANCE.clone(), + None, + )), + 0.75f64, + 0.5f64, + )); - let function8 = - function7 + let function8 = function7 .add_const(0.37f64) - .add(DensityFunction::ClampedY(YClampedFunction { + .add(Arc::new(DensityFunction::ClampedY(YClampedFunction { from: -10, to: 30, from_val: 0.3f64, to_val: 0f64, - })); + }))); - DensityFunction::Wrapper(WrapperFunction::new( - Arc::new(function8.binary_min(function6.add(function5))), - WrapperType::CacheOnce, - )) + DensityFunction::Wrapper(WrapperFunction::new( + Arc::new(function8.binary_min(Arc::new(function6.add(function5)))), + WrapperType::CacheOnce, + )) + }) }); pub static CAVES_NOODLE_OVERWORLD: BuiltInNoise = LazyLock::new(|| { - let function = Y.clone(); + Arc::new({ + let function = Y.clone(); + + let function2 = veritcal_range_choice( + function.clone(), + Arc::new(DensityFunction::Noise(NoiseFunction::new( + Arc::new(InternalNoise::new( + builtin_noise_params::NOODLE.clone(), + None, + )), + 1f64, + 1f64, + ))), + -60, + 320, + -1, + ); + + let function3 = veritcal_range_choice( + function.clone(), + Arc::new(noise_in_range( + builtin_noise_params::NOODLE_THICKNESS.clone(), + 1f64, + 1f64, + -0.05f64, + -0.1f64, + )), + -60, + 320, + 0, + ); + + let function4 = veritcal_range_choice( + function.clone(), + Arc::new(DensityFunction::Noise(NoiseFunction::new( + Arc::new(InternalNoise::new( + builtin_noise_params::NOODLE_RIDGE_A.clone(), + None, + )), + 2.6666666666666665f64, + 2.6666666666666665f64, + ))), + -60, + 320, + 0, + ); + + let function5 = veritcal_range_choice( + function.clone(), + Arc::new(DensityFunction::Noise(NoiseFunction::new( + Arc::new(InternalNoise::new( + builtin_noise_params::NOODLE_RIDGE_B.clone(), + None, + )), + 2.6666666666666665f64, + 2.6666666666666665f64, + ))), + -60, + 320, + 0, + ); + + let function6 = Arc::new( + function4 + .abs() + .binary_max(Arc::new(function5.abs())) + .mul_const(1.5f64), + ); + + DensityFunction::Range(RangeFunction { + input: Arc::new(function2), + min: -1000000f64, + max: 0f64, + in_range: Arc::new(DensityFunction::Constant(ConstantFunction::new(64f64))), + out_range: Arc::new(function3.add(function6)), + }) + }) + }); - let function2 = veritcal_range_choice( - function.clone(), - DensityFunction::Noise(NoiseFunction::new( + pub static CAVES_PILLARS_OVERWORLD: BuiltInNoise = LazyLock::new(|| { + Arc::new({ + let function = DensityFunction::Noise(NoiseFunction::new( Arc::new(InternalNoise::new( - builtin_noise_params::NOODLE.clone(), + builtin_noise_params::PILLAR.clone(), None, )), + 25f64, + 0.3f64, + )); + + let function2 = Arc::new(noise_in_range( + builtin_noise_params::PILLAR_RARENESS.clone(), 1f64, 1f64, - )), - -60, - 320, - -1, - ); + 0f64, + -2f64, + )); - let function3 = veritcal_range_choice( - function.clone(), - noise_in_range( - builtin_noise_params::NOODLE_THICKNESS.clone(), + let function3 = noise_in_range( + builtin_noise_params::PILLAR_THICKNESS.clone(), 1f64, 1f64, - -0.05f64, - -0.1f64, - ), - -60, - 320, - 0, - ); - - let function4 = veritcal_range_choice( - function.clone(), - DensityFunction::Noise(NoiseFunction::new( - Arc::new(InternalNoise::new( - builtin_noise_params::NOODLE_RIDGE_A.clone(), - None, - )), - 2.6666666666666665f64, - 2.6666666666666665f64, - )), - -60, - 320, - 0, - ); + 0f64, + 1.1f64, + ); - let function5 = veritcal_range_choice( - function.clone(), - DensityFunction::Noise(NoiseFunction::new( - Arc::new(InternalNoise::new( - builtin_noise_params::NOODLE_RIDGE_B.clone(), - None, - )), - 2.6666666666666665f64, - 2.6666666666666665f64, - )), - -60, - 320, - 0, - ); + let function4 = function.mul_const(2f64).add(function2); - let function6 = function4 - .abs() - .binary_max(function5.abs()) - .mul_const(1.5f64); - - DensityFunction::Range(RangeFunction { - input: Arc::new(function2), - min: -1000000f64, - max: 0f64, - in_range: Arc::new(DensityFunction::Constant(ConstantFunction::new(64f64))), - out_range: Arc::new(function3.add(function6)), + DensityFunction::Wrapper(WrapperFunction::new( + Arc::new(function4.mul(Arc::new(function3.cube()))), + WrapperType::CacheOnce, + )) }) }); - pub static CAVES_PILLARS_OVERWORLD: BuiltInNoise = LazyLock::new(|| { - let function = DensityFunction::Noise(NoiseFunction::new( - Arc::new(InternalNoise::new( - builtin_noise_params::PILLAR.clone(), - None, - )), - 25f64, - 0.3f64, - )); - - let function2 = noise_in_range( - builtin_noise_params::PILLAR_RARENESS.clone(), - 1f64, - 1f64, - 0f64, - -2f64, - ); - - let function3 = noise_in_range( - builtin_noise_params::PILLAR_THICKNESS.clone(), - 1f64, - 1f64, - 0f64, - 1.1f64, - ); - - let function4 = function.mul_const(2f64).add(function2); - - DensityFunction::Wrapper(WrapperFunction::new( - Arc::new(function4.mul(function3.cube())), - WrapperType::CacheOnce, - )) - }); - fn sloped_cheese_function<'a>( - jagged_noise: DensityFunction<'a>, - continents: DensityFunction<'a>, - erosion: DensityFunction<'a>, - ridges: DensityFunction<'a>, - ridges_folded: DensityFunction<'a>, + jagged_noise: Arc>, + continents: Arc>, + erosion: Arc>, + ridges: Arc>, + ridges_folded: Arc>, amplified: bool, ) -> SlopedCheeseResult<'a> { - let offset = apply_blending( - DensityFunction::Spline(SplineFunction::new(Arc::new(create_offset_spline( - continents.clone(), - erosion.clone(), - ridges.clone(), - amplified, - )))) - .add_const(-0.50375f32 as f64), - DensityFunction::BlendOffset(BlendOffsetFunction {}), - ); + let offset = Arc::new(apply_blending( + Arc::new( + DensityFunction::Spline(SplineFunction::new(Arc::new(create_offset_spline( + continents.clone(), + erosion.clone(), + ridges.clone(), + amplified, + )))) + .add_const(-0.50375f32 as f64), + ), + BLEND_OFFSET.clone(), + )); - let factor = apply_blending( - DensityFunction::Spline(SplineFunction::new(Arc::new(create_factor_spline( - continents.clone(), - erosion.clone(), - ridges.clone(), - ridges_folded.clone(), - amplified, + let factor = Arc::new(apply_blending( + Arc::new(DensityFunction::Spline(SplineFunction::new(Arc::new( + create_factor_spline( + continents.clone(), + erosion.clone(), + ridges.clone(), + ridges_folded.clone(), + amplified, + ), )))), TEN.clone(), + )); + + let depth = Arc::new( + DensityFunction::ClampedY(YClampedFunction { + from: -64, + to: 320, + from_val: 1.564, + to_val: -1.5f64, + }) + .add(offset.clone()), ); - let depth = DensityFunction::ClampedY(YClampedFunction { - from: -64, - to: 320, - from_val: 1.564, - to_val: -1.5f64, - }) - .add(offset.clone()); - - let jaggedness = apply_blending( - DensityFunction::Spline(SplineFunction::new(Arc::new(create_jaggedness_spline( - continents, - erosion, - ridges, - ridges_folded, - amplified, + let jaggedness = Arc::new(apply_blending( + Arc::new(DensityFunction::Spline(SplineFunction::new(Arc::new( + create_jaggedness_spline(continents, erosion, ridges, ridges_folded, amplified), )))), ZERO.clone(), - ); + )); - let density1 = jaggedness.mul(jagged_noise.half_negative()); - let density2 = DensityFunction::Constant(ConstantFunction::new(4f64)) - .mul(depth.add(density1).mul(factor.clone()).quarter_negative()); + let density1 = Arc::new(jaggedness.mul(Arc::new(jagged_noise.half_negative()))); + let density2 = DensityFunction::Constant(ConstantFunction::new(4f64)).mul(Arc::new( + depth.add(density1).mul(factor.clone()).quarter_negative(), + )); - let sloped_cheese = density2.add(BASE_3D_NOISE_OVERWORLD.clone()); + let sloped_cheese = Arc::new(density2.add(BASE_3D_NOISE_OVERWORLD.clone())); SlopedCheeseResult { offset, @@ -601,18 +662,18 @@ pub fn peaks_valleys_noise(variance: f32) -> f32 { } pub fn veritcal_range_choice<'a>( - input: DensityFunction<'a>, - in_range: DensityFunction<'a>, + input: Arc>, + in_range: Arc>, min: i32, max: i32, out: i32, ) -> DensityFunction<'a> { DensityFunction::Wrapper(WrapperFunction::new( Arc::new(DensityFunction::Range(RangeFunction { - input: Arc::new(input), + input, min: min as f64, max: (max + 1) as f64, - in_range: Arc::new(in_range), + in_range, out_range: Arc::new(DensityFunction::Constant(ConstantFunction::new(out as f64))), })), WrapperType::Interpolated, @@ -630,14 +691,10 @@ pub fn apply_blend_density(density: DensityFunction) -> DensityFunction { } fn apply_blending<'a>( - function: DensityFunction<'a>, - blend: DensityFunction<'a>, + function: Arc>, + blend: Arc>, ) -> DensityFunction<'a> { - let function = lerp_density( - DensityFunction::BlendAlpha(BlendAlphaFunction {}), - blend, - function, - ); + let function = lerp_density(built_in_noises::BLEND_ALPHA.clone(), blend, function); DensityFunction::Wrapper(WrapperFunction::new( Arc::new(DensityFunction::Wrapper(WrapperFunction::new( @@ -656,25 +713,27 @@ fn noise_in_range( max: f64, ) -> DensityFunction { map_range( - DensityFunction::Noise(NoiseFunction::new( + Arc::new(DensityFunction::Noise(NoiseFunction::new( Arc::new(InternalNoise::new(noise, None)), xz_scale, y_scale, - )), + ))), min, max, ) } -fn map_range(function: DensityFunction, min: f64, max: f64) -> DensityFunction { +fn map_range(function: Arc, min: f64, max: f64) -> DensityFunction { let d = (min + max) * 0.5f64; let e = (max - min) * 0.5f64; - DensityFunction::Constant(ConstantFunction::new(d)) - .add(DensityFunction::Constant(ConstantFunction::new(e)).mul(function)) + DensityFunction::Constant(ConstantFunction::new(d)).add(Arc::new( + DensityFunction::Constant(ConstantFunction::new(e)).mul(function), + )) } #[derive(Clone)] +#[enum_dispatch(DensityFunctionImpl)] pub enum DensityFunction<'a> { Clamp(ClampFunction<'a>), Unary(UnaryFunction<'a>), @@ -695,134 +754,11 @@ pub enum DensityFunction<'a> { Wierd(WierdScaledFunction<'a>), Range(RangeFunction<'a>), Wrapper(WrapperFunction<'a>), + FlatCache(FlatCacheDensityFunction<'a>), + Interpolator(InterpolatorDensityFunction<'a>), } impl<'a> DensityFunction<'a> { - #[inline] - pub fn sample(&self, pos: &impl NoisePos) -> f64 { - match self { - Self::Clamp(func) => func.sample(pos), - Self::Unary(func) => func.sample(pos), - Self::Noise(func) => func.sample(pos), - Self::ShiftA(func) => func.sample(pos), - Self::ShiftB(func) => func.sample(pos), - Self::ShiftedNoise(func) => func.sample(pos), - Self::Spline(func) => func.sample(pos), - Self::Constant(func) => func.sample(pos), - Self::Linear(func) => func.sample(pos), - Self::Binary(func) => func.sample(pos), - Self::BlendOffset(func) => func.sample(pos), - Self::BlendAlpha(func) => func.sample(pos), - Self::BlendDensity(func) => func.sample(pos), - Self::ClampedY(func) => func.sample(pos), - Self::InterpolatedNoise(func) => func.sample(pos), - Self::EndIsland(func) => func.sample(pos), - Self::Wierd(func) => func.sample(pos), - Self::Range(func) => func.sample(pos), - Self::Wrapper(func) => func.sample(pos), - } - } - - #[inline] - pub fn apply(&'a self, visitor: &'a impl Visitor) -> DensityFunction<'a> { - match self { - Self::Clamp(func) => func.apply(visitor), - Self::Unary(func) => func.apply(visitor), - Self::Noise(func) => func.apply(visitor), - Self::ShiftA(func) => func.apply(visitor), - Self::ShiftB(func) => func.apply(visitor), - Self::ShiftedNoise(func) => func.apply(visitor), - Self::Spline(func) => func.apply(visitor), - Self::Constant(func) => func.apply(visitor), - Self::Linear(func) => func.apply(visitor), - Self::Binary(func) => func.apply(visitor), - Self::BlendOffset(func) => func.apply(visitor), - Self::BlendAlpha(func) => func.apply(visitor), - Self::BlendDensity(func) => func.apply(visitor), - Self::ClampedY(func) => func.apply(visitor), - Self::InterpolatedNoise(func) => func.apply(visitor), - Self::EndIsland(func) => func.apply(visitor), - Self::Wierd(func) => func.apply(visitor), - Self::Range(func) => func.apply(visitor), - Self::Wrapper(func) => func.apply(visitor), - } - } - - #[inline] - pub fn fill(&self, densities: &[f64], applier: &impl Applier) -> Vec { - match self { - Self::Clamp(func) => func.fill(densities, applier), - Self::Unary(func) => func.fill(densities, applier), - Self::Noise(func) => func.fill(densities, applier), - Self::ShiftA(func) => func.fill(densities, applier), - Self::ShiftB(func) => func.fill(densities, applier), - Self::ShiftedNoise(func) => func.fill(densities, applier), - Self::Spline(func) => func.fill(densities, applier), - Self::Constant(func) => func.fill(densities, applier), - Self::Linear(func) => func.fill(densities, applier), - Self::Binary(func) => func.fill(densities, applier), - Self::BlendOffset(func) => func.fill(densities, applier), - Self::BlendAlpha(func) => func.fill(densities, applier), - Self::BlendDensity(func) => func.fill(densities, applier), - Self::ClampedY(func) => func.fill(densities, applier), - Self::InterpolatedNoise(func) => func.fill(densities, applier), - Self::EndIsland(func) => func.fill(densities, applier), - Self::Wierd(func) => func.fill(densities, applier), - Self::Range(func) => func.fill(densities, applier), - Self::Wrapper(func) => func.fill(densities, applier), - } - } - - #[inline] - pub fn max(&self) -> f64 { - match self { - Self::Clamp(func) => func.max(), - Self::Unary(func) => func.max(), - Self::Noise(func) => func.max(), - Self::ShiftA(func) => func.max(), - Self::ShiftB(func) => func.max(), - Self::ShiftedNoise(func) => func.max(), - Self::Spline(func) => func.max(), - Self::Constant(func) => func.max(), - Self::Linear(func) => func.max(), - Self::Binary(func) => func.max(), - Self::BlendOffset(func) => func.max(), - Self::BlendAlpha(func) => func.max(), - Self::BlendDensity(func) => func.max(), - Self::ClampedY(func) => func.max(), - Self::InterpolatedNoise(func) => func.max(), - Self::EndIsland(func) => func.max(), - Self::Wierd(func) => func.max(), - Self::Range(func) => func.max(), - Self::Wrapper(func) => func.max(), - } - } - - #[inline] - pub fn min(&self) -> f64 { - match self { - Self::Clamp(func) => func.min(), - Self::Unary(func) => func.min(), - Self::Noise(func) => func.min(), - Self::ShiftA(func) => func.min(), - Self::ShiftB(func) => func.min(), - Self::ShiftedNoise(func) => func.min(), - Self::Spline(func) => func.min(), - Self::Constant(func) => func.min(), - Self::Linear(func) => func.min(), - Self::Binary(func) => func.min(), - Self::BlendOffset(func) => func.min(), - Self::BlendAlpha(func) => func.min(), - Self::BlendDensity(func) => func.min(), - Self::ClampedY(func) => func.min(), - Self::InterpolatedNoise(func) => func.min(), - Self::EndIsland(func) => func.min(), - Self::Wierd(func) => func.min(), - Self::Range(func) => func.min(), - Self::Wrapper(func) => func.min(), - } - } - pub fn clamp(&self, max: f64, min: f64) -> Self { Self::Clamp(ClampFunction { input: Arc::new(self.clone()), @@ -874,60 +810,117 @@ impl<'a> DensityFunction<'a> { } pub fn add_const(&self, val: f64) -> Self { - self.add(Self::Constant(ConstantFunction::new(val))) + self.add(Arc::new(Self::Constant(ConstantFunction::new(val)))) } - pub fn add(&self, other: DensityFunction<'a>) -> Self { - BinaryFunction::create(BinaryType::Add, self.clone(), other) + pub fn add(&self, other: Arc>) -> Self { + BinaryFunction::create(BinaryType::Add, Arc::new(self.clone()), other) } pub fn mul_const(&self, val: f64) -> Self { - self.mul(Self::Constant(ConstantFunction::new(val))) + self.mul(Arc::new(Self::Constant(ConstantFunction::new(val)))) + } + + pub fn mul(&self, other: Arc>) -> Self { + BinaryFunction::create(BinaryType::Mul, Arc::new(self.clone()), other) + } + + pub fn binary_min(&self, other: Arc>) -> Self { + BinaryFunction::create(BinaryType::Min, Arc::new(self.clone()), other) + } + + pub fn binary_max(&self, other: Arc>) -> Self { + BinaryFunction::create(BinaryType::Max, Arc::new(self.clone()), other) + } +} + +#[enum_dispatch(NoisePosImpl)] +pub enum NoisePos<'a> { + Unblended(UnblendedNoisePos), + ChunkNoise(ChunkNoiseSampler<'a>), +} + +pub struct UnblendedNoisePos { + x: i32, + y: i32, + z: i32, +} + +impl UnblendedNoisePos { + pub fn new(x: i32, y: i32, z: i32) -> Self { + Self { x, y, z } } +} - pub fn mul(&self, other: DensityFunction<'a>) -> Self { - BinaryFunction::create(BinaryType::Mul, self.clone(), other) +impl NoisePosImpl for UnblendedNoisePos { + fn x(&self) -> i32 { + self.x } - pub fn binary_min(&self, other: DensityFunction<'a>) -> Self { - BinaryFunction::create(BinaryType::Min, self.clone(), other) + fn y(&self) -> i32 { + self.y } - pub fn binary_max(&self, other: DensityFunction<'a>) -> Self { - BinaryFunction::create(BinaryType::Max, self.clone(), other) + fn z(&self) -> i32 { + self.z } } -pub trait NoisePos { +#[enum_dispatch] +pub trait NoisePosImpl { fn x(&self) -> i32; fn y(&self) -> i32; fn z(&self) -> i32; - fn get_blender(&self) -> &Blender { - &Blender {} + fn get_blender(&self) -> Blender { + Blender::NoBlendBlender(NoBlendBlender {}) } } -pub trait Applier { - fn at(&self, index: i32) -> impl NoisePos; +#[enum_dispatch(ApplierImpl)] +pub enum Applier<'a> { + ChunkNoise(ChunkNoiseSampler<'a>), +} + +#[enum_dispatch] +pub trait ApplierImpl<'a> { + fn at(&self, index: i32) -> NoisePos; + + fn fill(&self, densities: &[f64], function: &DensityFunction<'a>) -> Vec; +} + +#[enum_dispatch(VisitorImpl)] +pub enum Visitor { + Unwrap(UnwrapVisitor), +} + +pub struct UnwrapVisitor {} - fn fill<'a>(&self, densities: &[f64], function: &impl DensityFunctionImpl<'a>) -> Vec; +impl VisitorImpl for UnwrapVisitor { + fn apply<'a>(&self, function: Arc>) -> Arc> { + match function.deref() { + DensityFunction::Wrapper(wrapper) => wrapper.wrapped(), + _ => function.clone(), + } + } } -pub trait Visitor { - fn apply(&self, function: &DensityFunction) -> DensityFunction; +#[enum_dispatch] +pub trait VisitorImpl { + fn apply<'a>(&self, function: Arc>) -> Arc>; fn apply_internal_noise<'a>(&self, function: Arc>) -> Arc> { function.clone() } } +#[enum_dispatch] pub trait DensityFunctionImpl<'a> { - fn sample(&self, pos: &impl NoisePos) -> f64; + fn sample(&self, pos: &NoisePos) -> f64; - fn fill(&self, densities: &[f64], applier: &impl Applier) -> Vec; + fn fill(&self, densities: &[f64], applier: &Applier) -> Vec; - fn apply(&'a self, visitor: &'a impl Visitor) -> DensityFunction<'a>; + fn apply(&'a self, visitor: &'a Visitor) -> Arc>; fn min(&self) -> f64; @@ -946,16 +939,16 @@ impl ConstantFunction { } impl<'a> DensityFunctionImpl<'a> for ConstantFunction { - fn sample(&self, _pos: &impl NoisePos) -> f64 { + fn sample(&self, _pos: &NoisePos) -> f64 { self.value } - fn fill(&self, densities: &[f64], _applier: &impl Applier) -> Vec { + fn fill(&self, densities: &[f64], _applier: &Applier) -> Vec { densities.iter().map(|_| self.value).collect() } - fn apply(&'a self, visitor: &'a impl Visitor) -> DensityFunction<'a> { - visitor.apply(&DensityFunction::Constant(self.clone())) + fn apply(&'a self, visitor: &'a Visitor) -> Arc> { + visitor.apply(Arc::new(DensityFunction::Constant(self.clone()))) } fn min(&self) -> f64 { @@ -985,6 +978,10 @@ impl<'a> WrapperFunction<'a> { pub fn new(input: Arc>, wrapper: WrapperType) -> Self { Self { input, wrapper } } + + pub fn wrapped(&self) -> Arc> { + self.input.clone() + } } impl<'a> DensityFunctionImpl<'a> for WrapperFunction<'a> { @@ -996,18 +993,18 @@ impl<'a> DensityFunctionImpl<'a> for WrapperFunction<'a> { self.input.min() } - fn sample(&self, pos: &impl NoisePos) -> f64 { + fn sample(&self, pos: &NoisePos) -> f64 { self.input.sample(pos) } - fn apply(&'a self, visitor: &'a impl Visitor) -> DensityFunction<'a> { - visitor.apply(&DensityFunction::Wrapper(WrapperFunction { - input: Arc::new(self.input.apply(visitor)), + fn apply(&'a self, visitor: &'a Visitor) -> Arc> { + visitor.apply(Arc::new(DensityFunction::Wrapper(WrapperFunction { + input: self.input.apply(visitor), wrapper: self.wrapper.clone(), - })) + }))) } - fn fill(&self, densities: &[f64], applier: &impl Applier) -> Vec { + fn fill(&self, densities: &[f64], applier: &Applier) -> Vec { self.input.fill(densities, applier) } } @@ -1040,7 +1037,7 @@ impl<'a> RangeFunction<'a> { } impl<'a> DensityFunctionImpl<'a> for RangeFunction<'a> { - fn sample(&self, pos: &impl NoisePos) -> f64 { + fn sample(&self, pos: &NoisePos) -> f64 { let d = self.input.sample(pos); if d >= self.min && d < self.max { self.in_range.sample(pos) @@ -1049,7 +1046,7 @@ impl<'a> DensityFunctionImpl<'a> for RangeFunction<'a> { } } - fn fill(&self, densities: &[f64], applier: &impl Applier) -> Vec { + fn fill(&self, densities: &[f64], applier: &Applier) -> Vec { let densities = self.input.fill(densities, applier); densities .iter() @@ -1064,14 +1061,14 @@ impl<'a> DensityFunctionImpl<'a> for RangeFunction<'a> { .collect() } - fn apply(&'a self, visitor: &'a impl Visitor) -> DensityFunction<'a> { - visitor.apply(&DensityFunction::Range(RangeFunction { - input: Arc::new(self.input.apply(visitor)), + fn apply(&'a self, visitor: &'a Visitor) -> Arc> { + visitor.apply(Arc::new(DensityFunction::Range(RangeFunction { + input: self.input.apply(visitor), min: self.min, max: self.max, - in_range: Arc::new(self.in_range.apply(visitor)), - out_range: Arc::new(self.out_range.apply(visitor)), - })) + in_range: self.in_range.apply(visitor), + out_range: self.out_range.apply(visitor), + }))) } fn min(&self) -> f64 { @@ -1103,7 +1100,7 @@ impl YClampedFunction { } impl<'a> DensityFunctionImpl<'a> for YClampedFunction { - fn sample(&self, pos: &impl NoisePos) -> f64 { + fn sample(&self, pos: &NoisePos) -> f64 { clamped_map( pos.y() as f64, self.from as f64, @@ -1121,18 +1118,16 @@ impl<'a> DensityFunctionImpl<'a> for YClampedFunction { self.from_val.max(self.to_val) } - fn fill(&self, densities: &[f64], applier: &impl Applier) -> Vec { - applier.fill(densities, self) + fn fill(&self, densities: &[f64], applier: &Applier) -> Vec { + applier.fill(densities, &DensityFunction::ClampedY(self.clone())) } - fn apply(&'a self, visitor: &'a impl Visitor) -> DensityFunction<'a> { - visitor.apply(&DensityFunction::ClampedY(self.clone())) + fn apply(&'a self, visitor: &'a Visitor) -> Arc> { + visitor.apply(Arc::new(DensityFunction::ClampedY(self.clone()))) } } pub trait UnaryDensityFunction<'a>: DensityFunctionImpl<'a> { - fn input(&self) -> &DensityFunction; - fn apply_density(&self, density: f64) -> f64; } @@ -1147,26 +1142,26 @@ pub trait OffsetDensityFunction<'a>: DensityFunctionImpl<'a> { } pub fn lerp_density<'a>( - delta: DensityFunction<'a>, - start: DensityFunction<'a>, - end: DensityFunction<'a>, + delta: Arc>, + start: Arc>, + end: Arc>, ) -> DensityFunction<'a> { - if let DensityFunction::Constant(function) = start { + if let DensityFunction::Constant(function) = start.as_ref() { lerp_density_static_start(delta, function.value, end) } else { - let function = DensityFunction::Wrapper(WrapperFunction::new( - Arc::new(delta), + let function = Arc::new(DensityFunction::Wrapper(WrapperFunction::new( + delta, WrapperType::CacheOnce, - )); - let function2 = function.mul_const(-1f64).add_const(1f64); - start.mul(function2).add(end.mul(function)) + ))); + let function2 = Arc::new(function.mul_const(-1f64).add_const(1f64)); + start.mul(function2).add(Arc::new(end.mul(function))) } } pub fn lerp_density_static_start<'a>( - delta: DensityFunction<'a>, + delta: Arc>, start: f64, - end: DensityFunction<'a>, + end: Arc>, ) -> DensityFunction<'a> { - delta.mul(end.add_const(-start)).add_const(start) + delta.mul(Arc::new(end.add_const(-start))).add_const(start) } diff --git a/pumpkin-world/src/world_gen/noise/density/noise.rs b/pumpkin-world/src/world_gen/noise/density/noise.rs index 245c56408..fa258386d 100644 --- a/pumpkin-world/src/world_gen/noise/density/noise.rs +++ b/pumpkin-world/src/world_gen/noise/density/noise.rs @@ -7,7 +7,10 @@ use crate::world_gen::noise::{ perlin::{DoublePerlinNoiseParameters, DoublePerlinNoiseSampler, OctavePerlinNoiseSampler}, }; -use super::{DensityFunction, DensityFunctionImpl}; +use super::{ + Applier, ApplierImpl, DensityFunction, DensityFunctionImpl, NoisePos, NoisePosImpl, Visitor, + VisitorImpl, +}; pub(crate) struct InternalNoise<'a> { data: DoublePerlinNoiseParameters<'a>, @@ -58,7 +61,7 @@ impl<'a> NoiseFunction<'a> { } impl<'a> DensityFunctionImpl<'a> for NoiseFunction<'a> { - fn sample(&self, pos: &impl super::NoisePos) -> f64 { + fn sample(&self, pos: &NoisePos) -> f64 { self.noise.sample( pos.x() as f64 * self.xz_scale, pos.y() as f64 * self.y_scale, @@ -66,12 +69,12 @@ impl<'a> DensityFunctionImpl<'a> for NoiseFunction<'a> { ) } - fn fill(&self, densities: &[f64], applier: &impl super::Applier) -> Vec { - applier.fill(densities, self) + fn fill(&self, densities: &[f64], applier: &Applier) -> Vec { + applier.fill(densities, &DensityFunction::Noise(self.clone())) } - fn apply(&self, visitor: &'a impl super::Visitor) -> super::DensityFunction<'a> { - visitor.apply(&super::DensityFunction::Noise(self.clone())) + fn apply(&self, visitor: &'a Visitor) -> Arc> { + visitor.apply(Arc::new(DensityFunction::Noise(self.clone()))) } fn max(&self) -> f64 { @@ -114,7 +117,7 @@ impl<'a> ShiftedNoiseFunction<'a> { } impl<'a> DensityFunctionImpl<'a> for ShiftedNoiseFunction<'a> { - fn sample(&self, pos: &impl super::NoisePos) -> f64 { + fn sample(&self, pos: &NoisePos) -> f64 { let d = pos.x() as f64 * self.xz_scale + self.shift_x.sample(pos); let e = pos.y() as f64 * self.y_scale + self.shift_y.sample(pos); let f = pos.z() as f64 * self.xz_scale + self.shift_z.sample(pos); @@ -122,24 +125,24 @@ impl<'a> DensityFunctionImpl<'a> for ShiftedNoiseFunction<'a> { self.noise.sample(d, e, f) } - fn fill(&self, densities: &[f64], applier: &impl super::Applier) -> Vec { - applier.fill(densities, self) + fn fill(&self, densities: &[f64], applier: &Applier) -> Vec { + applier.fill(densities, &DensityFunction::ShiftedNoise(self.clone())) } - fn apply(&'a self, visitor: &'a impl super::Visitor) -> DensityFunction<'a> { + fn apply(&'a self, visitor: &'a Visitor) -> Arc> { let new_x = self.shift_x.apply(visitor); let new_y = self.shift_y.apply(visitor); let new_z = self.shift_z.apply(visitor); let new_noise = visitor.apply_internal_noise(self.noise.clone()); - DensityFunction::ShiftedNoise(ShiftedNoiseFunction { - shift_x: Arc::new(new_x), - shift_y: Arc::new(new_y), - shift_z: Arc::new(new_z), + Arc::new(DensityFunction::ShiftedNoise(ShiftedNoiseFunction { + shift_x: new_x, + shift_y: new_y, + shift_z: new_z, xz_scale: self.xz_scale, y_scale: self.y_scale, noise: new_noise, - }) + })) } fn max(&self) -> f64 { @@ -256,7 +259,7 @@ impl InterpolatedNoiseSampler { } impl<'a> DensityFunctionImpl<'a> for InterpolatedNoiseSampler { - fn sample(&self, pos: &impl super::NoisePos) -> f64 { + fn sample(&self, pos: &NoisePos) -> f64 { let d = pos.x() as f64 * self.xz_scale_scaled; let e = pos.y() as f64 * self.y_scale_scaled; let f = pos.z() as f64 * self.xz_scale_scaled; @@ -327,11 +330,11 @@ impl<'a> DensityFunctionImpl<'a> for InterpolatedNoiseSampler { -self.max() } - fn fill(&self, densities: &[f64], applier: &impl super::Applier) -> Vec { - applier.fill(densities, self) + fn fill(&self, densities: &[f64], applier: &Applier) -> Vec { + applier.fill(densities, &DensityFunction::InterpolatedNoise(self.clone())) } - fn apply(&'a self, visitor: &'a impl super::Visitor) -> DensityFunction<'a> { - visitor.apply(&DensityFunction::InterpolatedNoise(self.clone())) + fn apply(&'a self, visitor: &'a Visitor) -> Arc> { + visitor.apply(Arc::new(DensityFunction::InterpolatedNoise(self.clone()))) } } diff --git a/pumpkin-world/src/world_gen/noise/density/offset.rs b/pumpkin-world/src/world_gen/noise/density/offset.rs index 684f57760..3aa6be286 100644 --- a/pumpkin-world/src/world_gen/noise/density/offset.rs +++ b/pumpkin-world/src/world_gen/noise/density/offset.rs @@ -1,6 +1,9 @@ use std::sync::Arc; -use super::{noise::InternalNoise, DensityFunction, DensityFunctionImpl, OffsetDensityFunction}; +use super::{ + noise::InternalNoise, Applier, ApplierImpl, DensityFunction, DensityFunctionImpl, NoisePos, + NoisePosImpl, OffsetDensityFunction, Visitor, VisitorImpl, +}; #[derive(Clone)] pub struct ShiftAFunction<'a> { @@ -20,18 +23,18 @@ impl<'a> OffsetDensityFunction<'a> for ShiftAFunction<'a> { } impl<'a> DensityFunctionImpl<'a> for ShiftAFunction<'a> { - fn sample(&self, pos: &impl super::NoisePos) -> f64 { + fn sample(&self, pos: &NoisePos) -> f64 { self.sample_3d(pos.x() as f64, 0f64, pos.z() as f64) } - fn apply(&'a self, visitor: &'a impl super::Visitor) -> super::DensityFunction<'a> { - visitor.apply(&DensityFunction::ShiftA(ShiftAFunction { + fn apply(&'a self, visitor: &'a Visitor) -> Arc> { + visitor.apply(Arc::new(DensityFunction::ShiftA(ShiftAFunction { offset: visitor.apply_internal_noise(self.offset.clone()), - })) + }))) } - fn fill(&self, densities: &[f64], applier: &impl super::Applier) -> Vec { - applier.fill(densities, self) + fn fill(&self, densities: &[f64], applier: &Applier) -> Vec { + applier.fill(densities, &DensityFunction::ShiftA(self.clone())) } fn max(&self) -> f64 { @@ -61,18 +64,18 @@ impl<'a> OffsetDensityFunction<'a> for ShiftBFunction<'a> { } impl<'a> DensityFunctionImpl<'a> for ShiftBFunction<'a> { - fn sample(&self, pos: &impl super::NoisePos) -> f64 { + fn sample(&self, pos: &NoisePos) -> f64 { self.sample_3d(pos.z() as f64, pos.x() as f64, 0f64) } - fn apply(&'a self, visitor: &'a impl super::Visitor) -> super::DensityFunction<'a> { - visitor.apply(&DensityFunction::ShiftB(ShiftBFunction { + fn apply(&'a self, visitor: &'a Visitor) -> Arc> { + visitor.apply(Arc::new(DensityFunction::ShiftB(ShiftBFunction { offset: visitor.apply_internal_noise(self.offset.clone()), - })) + }))) } - fn fill(&self, densities: &[f64], applier: &impl super::Applier) -> Vec { - applier.fill(densities, self) + fn fill(&self, densities: &[f64], applier: &Applier) -> Vec { + applier.fill(densities, &DensityFunction::ShiftB(self.clone())) } fn max(&self) -> f64 { diff --git a/pumpkin-world/src/world_gen/noise/density/spline.rs b/pumpkin-world/src/world_gen/noise/density/spline.rs index 775898e73..766e5e3cf 100644 --- a/pumpkin-world/src/world_gen/noise/density/spline.rs +++ b/pumpkin-world/src/world_gen/noise/density/spline.rs @@ -2,7 +2,9 @@ use std::sync::Arc; use crate::world_gen::noise::lerp_32; -use super::{DensityFunction, DensityFunctionImpl, NoisePos, Visitor}; +use super::{ + Applier, ApplierImpl, DensityFunction, DensityFunctionImpl, NoisePos, Visitor, VisitorImpl, +}; pub enum SplineValue<'a> { Spline(Spline<'a>), @@ -24,14 +26,14 @@ impl<'a> SplineValue<'a> { } } - fn apply(&self, pos: &impl NoisePos) -> f32 { + fn apply(&self, pos: &NoisePos) -> f32 { match self { Self::Fixed(value) => *value, Self::Spline(spline) => spline.apply(pos), } } - fn visit(&'a self, visitor: &'a impl Visitor) -> SplineValue<'a> { + fn visit(&'a self, visitor: &'a Visitor) -> SplineValue<'a> { match self { Self::Fixed(val) => Self::Fixed(*val), Self::Spline(spline) => Self::Spline(spline.visit(visitor)), @@ -48,7 +50,7 @@ pub(crate) struct SplinePoint<'a> { #[derive(Clone)] pub struct Spline<'a> { - function: DensityFunction<'a>, + function: Arc>, points: Vec>, min: f32, max: f32, @@ -68,7 +70,7 @@ impl<'a> Spline<'a> { locations.partition_point(|val| x < *val) as i32 - 1 } - pub fn new(function: DensityFunction<'a>, points: &[SplinePoint<'a>]) -> Self { + pub fn new(function: Arc>, points: &[SplinePoint<'a>]) -> Self { let i = points.len() - 1; let mut f = f32::INFINITY; let mut g = f32::NEG_INFINITY; @@ -139,7 +141,7 @@ impl<'a> Spline<'a> { } } - pub fn apply(&self, pos: &impl NoisePos) -> f32 { + pub fn apply(&self, pos: &NoisePos) -> f32 { let f = self.function.sample(pos) as f32; let i = Self::find_range_for_location( self.points @@ -169,8 +171,8 @@ impl<'a> Spline<'a> { } } - pub fn visit(&'a self, visitor: &'a impl Visitor) -> Spline<'a> { - let new_function = visitor.apply(&self.function); + pub fn visit(&'a self, visitor: &'a Visitor) -> Spline<'a> { + let new_function = visitor.apply(self.function.clone()); let new_points = self .points .iter() @@ -196,19 +198,19 @@ impl<'a> SplineFunction<'a> { } impl<'a> DensityFunctionImpl<'a> for SplineFunction<'a> { - fn sample(&self, pos: &impl NoisePos) -> f64 { + fn sample(&self, pos: &NoisePos) -> f64 { self.spline.apply(pos) as f64 } - fn fill(&self, densities: &[f64], applier: &impl super::Applier) -> Vec { - applier.fill(densities, self) + fn fill(&self, densities: &[f64], applier: &Applier) -> Vec { + applier.fill(densities, &DensityFunction::Spline(self.clone())) } - fn apply(&'a self, visitor: &'a impl Visitor) -> DensityFunction<'a> { + fn apply(&'a self, visitor: &'a Visitor) -> Arc> { let new_spline = self.spline.visit(visitor); - DensityFunction::Spline(SplineFunction { + Arc::new(DensityFunction::Spline(SplineFunction { spline: Arc::new(new_spline), - }) + })) } fn max(&self) -> f64 { @@ -242,13 +244,13 @@ impl FloatAmplifier { } } pub struct SplineBuilder<'a> { - function: DensityFunction<'a>, + function: Arc>, amplifier: FloatAmplifier, points: Vec>, } impl<'a> SplineBuilder<'a> { - pub fn new(function: DensityFunction<'a>, amplifier: FloatAmplifier) -> Self { + pub fn new(function: Arc>, amplifier: FloatAmplifier) -> Self { Self { function, amplifier, diff --git a/pumpkin-world/src/world_gen/noise/density/unary.rs b/pumpkin-world/src/world_gen/noise/density/unary.rs index b9b7cc617..eaed5f4bd 100644 --- a/pumpkin-world/src/world_gen/noise/density/unary.rs +++ b/pumpkin-world/src/world_gen/noise/density/unary.rs @@ -1,6 +1,8 @@ use std::sync::Arc; -use super::{DensityFunction, DensityFunctionImpl, UnaryDensityFunction}; +use super::{ + Applier, DensityFunction, DensityFunctionImpl, NoisePos, UnaryDensityFunction, Visitor, +}; #[derive(Clone)] pub struct ClampFunction<'a> { @@ -10,30 +12,26 @@ pub struct ClampFunction<'a> { } impl<'a> UnaryDensityFunction<'a> for ClampFunction<'a> { - fn input(&self) -> &DensityFunction { - &self.input - } - fn apply_density(&self, density: f64) -> f64 { density.clamp(self.min, self.max) } } impl<'a> DensityFunctionImpl<'a> for ClampFunction<'a> { - fn apply(&'a self, visitor: &'a impl super::Visitor) -> DensityFunction<'a> { - DensityFunction::Clamp(ClampFunction { - input: Arc::new(self.input().apply(visitor)), + fn apply(&'a self, visitor: &'a Visitor) -> Arc> { + Arc::new(DensityFunction::Clamp(ClampFunction { + input: self.input.apply(visitor), min: self.min, max: self.max, - }) + })) } - fn sample(&self, pos: &impl super::NoisePos) -> f64 { - self.apply_density(self.input().sample(pos)) + fn sample(&self, pos: &NoisePos) -> f64 { + self.apply_density(self.input.sample(pos)) } - fn fill(&self, densities: &[f64], applier: &impl super::Applier) -> Vec { - let densities = self.input().fill(densities, applier); + fn fill(&self, densities: &[f64], applier: &Applier) -> Vec { + let densities = self.input.fill(densities, applier); densities.iter().map(|x| self.apply_density(*x)).collect() } @@ -116,25 +114,21 @@ impl<'a> UnaryDensityFunction<'a> for UnaryFunction<'a> { fn apply_density(&self, density: f64) -> f64 { Self::internal_apply(&self.action, density) } - - fn input(&self) -> &DensityFunction { - &self.input - } } impl<'a> DensityFunctionImpl<'a> for UnaryFunction<'a> { - fn sample(&self, pos: &impl super::NoisePos) -> f64 { - self.apply_density(self.input().sample(pos)) + fn sample(&self, pos: &NoisePos) -> f64 { + self.apply_density(self.input.sample(pos)) } - fn fill(&self, densities: &[f64], applier: &impl super::Applier) -> Vec { - let densities = self.input().fill(densities, applier); + fn fill(&self, densities: &[f64], applier: &Applier) -> Vec { + let densities = self.input.fill(densities, applier); densities.iter().map(|x| self.apply_density(*x)).collect() } - fn apply(&'a self, visitor: &'a impl super::Visitor) -> DensityFunction<'a> { - let raw = Self::create(self.action.clone(), Arc::new(self.input().apply(visitor))); - DensityFunction::Unary(raw) + fn apply(&'a self, visitor: &'a Visitor) -> Arc> { + let raw = Self::create(self.action.clone(), self.input.apply(visitor)); + Arc::new(DensityFunction::Unary(raw)) } fn max(&self) -> f64 { diff --git a/pumpkin-world/src/world_gen/noise/density/weird.rs b/pumpkin-world/src/world_gen/noise/density/weird.rs index 9fada3355..db275f29a 100644 --- a/pumpkin-world/src/world_gen/noise/density/weird.rs +++ b/pumpkin-world/src/world_gen/noise/density/weird.rs @@ -1,6 +1,9 @@ use std::sync::Arc; -use super::{noise::InternalNoise, DensityFunction, DensityFunctionImpl, NoisePos}; +use super::{ + noise::InternalNoise, Applier, ApplierImpl, DensityFunction, DensityFunctionImpl, NoisePos, + NoisePosImpl, Visitor, VisitorImpl, +}; #[derive(Clone)] pub enum RarityMapper { @@ -68,7 +71,7 @@ impl<'a> WierdScaledFunction<'a> { } } - fn apply_loc(&self, pos: &impl NoisePos, density: f64) -> f64 { + fn apply_loc(&self, pos: &NoisePos, density: f64) -> f64 { let d = self.rarity.scale(density); d * self .noise @@ -86,19 +89,19 @@ impl<'a> DensityFunctionImpl<'a> for WierdScaledFunction<'a> { 0f64 } - fn apply(&'a self, visitor: &'a impl super::Visitor) -> DensityFunction<'a> { - visitor.apply(&DensityFunction::Wierd(WierdScaledFunction { - input: Arc::new(self.input.apply(visitor)), + fn apply(&'a self, visitor: &'a Visitor) -> Arc> { + visitor.apply(Arc::new(DensityFunction::Wierd(WierdScaledFunction { + input: self.input.apply(visitor), noise: visitor.apply_internal_noise(self.noise.clone()), rarity: self.rarity.clone(), - })) + }))) } - fn sample(&self, pos: &impl NoisePos) -> f64 { + fn sample(&self, pos: &NoisePos) -> f64 { self.apply_loc(pos, self.input.sample(pos)) } - fn fill(&self, densities: &[f64], applier: &impl super::Applier) -> Vec { + fn fill(&self, densities: &[f64], applier: &Applier) -> Vec { let densities = self.input.fill(densities, applier); densities .iter() diff --git a/pumpkin-world/src/world_gen/noise/mod.rs b/pumpkin-world/src/world_gen/noise/mod.rs index 54e551fd7..e7297adea 100644 --- a/pumpkin-world/src/world_gen/noise/mod.rs +++ b/pumpkin-world/src/world_gen/noise/mod.rs @@ -1,6 +1,8 @@ #![allow(dead_code)] +pub mod chunk_sampler; +pub mod config; pub mod density; -mod perlin; +pub mod perlin; mod router; mod simplex; diff --git a/pumpkin-world/src/world_gen/noise/router.rs b/pumpkin-world/src/world_gen/noise/router.rs index 1abc85e96..2893b293c 100644 --- a/pumpkin-world/src/world_gen/noise/router.rs +++ b/pumpkin-world/src/world_gen/noise/router.rs @@ -7,32 +7,32 @@ use super::{ density::{ apply_blend_density, built_in_noises, lerp_density_static_start, noise::{InternalNoise, NoiseFunction, ShiftedNoiseFunction}, - veritcal_range_choice, ConstantFunction, DensityFunction, RangeFunction, Visitor, - WrapperFunction, WrapperType, YClampedFunction, + veritcal_range_choice, ConstantFunction, DensityFunction, DensityFunctionImpl, + RangeFunction, Visitor, WrapperFunction, WrapperType, YClampedFunction, }, }; pub struct NoiseRouter<'a> { - barrier: DensityFunction<'a>, - fluid_level_floodedness: DensityFunction<'a>, - fluid_level_spread: DensityFunction<'a>, - lava: DensityFunction<'a>, - temperature: DensityFunction<'a>, - vegetation: DensityFunction<'a>, - continents: DensityFunction<'a>, - erosion: DensityFunction<'a>, - depth: DensityFunction<'a>, - ridges: DensityFunction<'a>, - internal_density: DensityFunction<'a>, - final_densitiy: DensityFunction<'a>, - vein_toggle: DensityFunction<'a>, - vein_ridged: DensityFunction<'a>, - vein_gap: DensityFunction<'a>, + barrier: Arc>, + fluid_level_floodedness: Arc>, + fluid_level_spread: Arc>, + lava: Arc>, + temperature: Arc>, + vegetation: Arc>, + continents: Arc>, + erosion: Arc>, + depth: Arc>, + ridges: Arc>, + internal_density: Arc>, + final_densitiy: Arc>, + vein_toggle: Arc>, + vein_ridged: Arc>, + vein_gap: Arc>, } impl<'a> NoiseRouter<'a> { - pub fn apply(&'a self, visitor: &'a impl Visitor) -> Self { - NoiseRouter { + pub fn apply(&'a self, visitor: &'a Visitor) -> Self { + Self { barrier: self.barrier.apply(visitor), fluid_level_floodedness: self.fluid_level_floodedness.apply(visitor), fluid_level_spread: self.fluid_level_spread.apply(visitor), @@ -52,49 +52,49 @@ impl<'a> NoiseRouter<'a> { } pub fn create_surface_noise_router(large_biomes: bool, amplified: bool) -> Self { - let function = DensityFunction::Noise(NoiseFunction::new( + let function = Arc::new(DensityFunction::Noise(NoiseFunction::new( Arc::new(InternalNoise::new( builtin_noise_params::AQUIFER_BARRIER.clone(), None, )), 1f64, 0.5f64, - )); + ))); - let function2 = DensityFunction::Noise(NoiseFunction::new( + let function2 = Arc::new(DensityFunction::Noise(NoiseFunction::new( Arc::new(InternalNoise::new( builtin_noise_params::AQUIFER_BARRIER_FLOODEDNESS.clone(), None, )), 1f64, 0.67f64, - )); + ))); - let function3 = DensityFunction::Noise(NoiseFunction::new( + let function3 = Arc::new(DensityFunction::Noise(NoiseFunction::new( Arc::new(InternalNoise::new( builtin_noise_params::AQUIFER_FLUID_LEVEL_SPREAD.clone(), None, )), 1f64, 0.7142857142857143f64, - )); + ))); - let function4 = DensityFunction::Noise(NoiseFunction::new( + let function4 = Arc::new(DensityFunction::Noise(NoiseFunction::new( Arc::new(InternalNoise::new( builtin_noise_params::AQUIFER_LAVA.clone(), None, )), 1f64, 1f64, - )); + ))); let function5 = built_in_noises::SHIFT_X.clone(); let function6 = built_in_noises::SHIFT_Z.clone(); - let function7 = DensityFunction::ShiftedNoise(ShiftedNoiseFunction::new( - Arc::new(function5.clone()), - Arc::new(built_in_noises::ZERO.clone()), - Arc::new(function6.clone()), + let function7 = Arc::new(DensityFunction::ShiftedNoise(ShiftedNoiseFunction::new( + function5.clone(), + built_in_noises::ZERO.clone(), + function6.clone(), 0.25f64, 0f64, Arc::new(InternalNoise::new( @@ -105,12 +105,12 @@ impl<'a> NoiseRouter<'a> { }, None, )), - )); + ))); - let function8 = DensityFunction::ShiftedNoise(ShiftedNoiseFunction::new( - Arc::new(function5.clone()), - Arc::new(built_in_noises::ZERO.clone()), - Arc::new(function6.clone()), + let function8 = Arc::new(DensityFunction::ShiftedNoise(ShiftedNoiseFunction::new( + function5.clone(), + built_in_noises::ZERO.clone(), + function6.clone(), 0.25f64, 0f64, Arc::new(InternalNoise::new( @@ -121,7 +121,7 @@ impl<'a> NoiseRouter<'a> { }, None, )), - )); + ))); let function9 = if large_biomes { built_in_noises::OVERWORLD_LARGE_SLOPED_CHEESE @@ -145,13 +145,15 @@ impl<'a> NoiseRouter<'a> { built_in_noises::OVERWORLD_SLOPED_CHEESE.depth.clone() }; - let function11 = DensityFunction::Constant(ConstantFunction::new(4f64)).mul( - function10 - .mul(DensityFunction::Wrapper(WrapperFunction::new( - Arc::new(function9), - WrapperType::Cache2D, - ))) - .quarter_negative(), + let function11 = Arc::new( + DensityFunction::Constant(ConstantFunction::new(4f64)).mul(Arc::new( + function10 + .mul(Arc::new(DensityFunction::Wrapper(WrapperFunction::new( + function9, + WrapperType::Cache2D, + )))) + .quarter_negative(), + )), ); let function12 = if large_biomes { @@ -168,83 +170,93 @@ impl<'a> NoiseRouter<'a> { .clone() }; - let function13 = function12.binary_min( - DensityFunction::Constant(ConstantFunction::new(5f64)) - .mul(built_in_noises::CAVES_ENTRANCES_OVERWORLD.clone()), + let function13 = Arc::new( + function12.binary_min(Arc::new( + DensityFunction::Constant(ConstantFunction::new(5f64)) + .mul(built_in_noises::CAVES_ENTRANCES_OVERWORLD.clone()), + )), ); - let function14 = DensityFunction::Range(RangeFunction::new( - Arc::new(function12.clone()), + let function14 = Arc::new(DensityFunction::Range(RangeFunction::new( + function12.clone(), -1000000f64, 1.5625f64, - Arc::new(function13), + function13, Arc::new(create_caves(function12)), - )); + ))); - let function15 = apply_blend_density(apply_surface_slides(amplified, function14)) - .binary_min(built_in_noises::CAVES_NOODLE_OVERWORLD.clone()); + let function15 = Arc::new( + apply_blend_density(apply_surface_slides(amplified, function14)) + .binary_min(built_in_noises::CAVES_NOODLE_OVERWORLD.clone()), + ); let function16 = built_in_noises::Y.clone(); let i = VeinType::overall_min_y(); let j = VeinType::overall_max_y(); - let function17 = veritcal_range_choice( + let function17 = Arc::new(veritcal_range_choice( function16.clone(), - DensityFunction::Noise(NoiseFunction::new( + Arc::new(DensityFunction::Noise(NoiseFunction::new( Arc::new(InternalNoise::new( builtin_noise_params::ORE_VEININESS.clone(), None, )), 1.5f64, 1.5f64, - )), + ))), i, j, 0, - ); + )); - let function18 = veritcal_range_choice( - function16.clone(), - DensityFunction::Noise(NoiseFunction::new( - Arc::new(InternalNoise::new( - builtin_noise_params::ORE_VEIN_A.clone(), - None, - )), - 4f64, - 4f64, - )), - i, - j, - 0, - ) - .abs(); + let function18 = Arc::new( + veritcal_range_choice( + function16.clone(), + Arc::new(DensityFunction::Noise(NoiseFunction::new( + Arc::new(InternalNoise::new( + builtin_noise_params::ORE_VEIN_A.clone(), + None, + )), + 4f64, + 4f64, + ))), + i, + j, + 0, + ) + .abs(), + ); - let function19 = veritcal_range_choice( - function16, - DensityFunction::Noise(NoiseFunction::new( - Arc::new(InternalNoise::new( - builtin_noise_params::ORE_VEIN_B.clone(), - None, - )), - 4f64, - 4f64, - )), - i, - j, - 0, - ) - .abs(); + let function19 = Arc::new( + veritcal_range_choice( + function16, + Arc::new(DensityFunction::Noise(NoiseFunction::new( + Arc::new(InternalNoise::new( + builtin_noise_params::ORE_VEIN_B.clone(), + None, + )), + 4f64, + 4f64, + ))), + i, + j, + 0, + ) + .abs(), + ); - let function20 = DensityFunction::Constant(ConstantFunction::new(-0.08f64)) - .add(function18.binary_max(function19)); + let function20 = Arc::new( + DensityFunction::Constant(ConstantFunction::new(-0.08f64)) + .add(Arc::new(function18.binary_max(function19))), + ); - let function21 = DensityFunction::Noise(NoiseFunction::new( + let function21 = Arc::new(DensityFunction::Noise(NoiseFunction::new( Arc::new(InternalNoise::new( builtin_noise_params::ORE_GAP.clone(), None, )), 1f64, 1f64, - )); + ))); Self { barrier: function, @@ -265,10 +277,10 @@ impl<'a> NoiseRouter<'a> { }, depth: function10, ridges: built_in_noises::RIDGES_OVERWORLD.clone(), - internal_density: apply_surface_slides( + internal_density: Arc::new(apply_surface_slides( amplified, - function11.add_const(-0.703125).clamp(-64f64, 64f64), - ), + Arc::new(function11.add_const(-0.703125).clamp(-64f64, 64f64)), + )), final_densitiy: function15, vein_toggle: function17, vein_ridged: function20, @@ -277,7 +289,7 @@ impl<'a> NoiseRouter<'a> { } } -fn apply_surface_slides(amplified: bool, density: DensityFunction) -> DensityFunction { +fn apply_surface_slides(amplified: bool, density: Arc) -> DensityFunction { apply_slides( density, -64, @@ -293,7 +305,7 @@ fn apply_surface_slides(amplified: bool, density: DensityFunction) -> DensityFun #[allow(clippy::too_many_arguments)] fn apply_slides( - density: DensityFunction, + density: Arc, y_min: i32, y_max: i32, top_rel_y_min: i32, @@ -303,63 +315,70 @@ fn apply_slides( bottom_rel_y_max: i32, bottom_density: f64, ) -> DensityFunction { - let function2 = DensityFunction::ClampedY(YClampedFunction::new( + let function2 = Arc::new(DensityFunction::ClampedY(YClampedFunction::new( y_min + y_max - top_rel_y_min, y_min + y_max + -top_rel_y_max, 1f64, 0f64, - )); - let function = lerp_density_static_start(function2, top_density, density); - let function3 = DensityFunction::ClampedY(YClampedFunction::new( + ))); + let function = Arc::new(lerp_density_static_start(function2, top_density, density)); + let function3 = Arc::new(DensityFunction::ClampedY(YClampedFunction::new( y_min + bottom_rel_y_min, y_min + bottom_rel_y_max, 0f64, 1f64, - )); + ))); lerp_density_static_start(function3, bottom_density, function) } -fn create_caves(sloped_cheese: DensityFunction) -> DensityFunction { +fn create_caves(sloped_cheese: Arc) -> DensityFunction { let function = built_in_noises::CAVES_SPAGHETTI_2D_OVERWORLD.clone(); let function2 = built_in_noises::CAVES_SPAGHETTI_ROUGHNESS_FUNCTION_OVERWORLD.clone(); - let function3 = DensityFunction::Noise(NoiseFunction::new( + let function3 = Arc::new(DensityFunction::Noise(NoiseFunction::new( Arc::new(InternalNoise::new( builtin_noise_params::CAVE_LAYER.clone(), None, )), 1f64, 8f64, - )); - let function4 = DensityFunction::Constant(ConstantFunction::new(4f64)).mul(function3.square()); - let function5 = DensityFunction::Noise(NoiseFunction::new( + ))); + let function4 = Arc::new( + DensityFunction::Constant(ConstantFunction::new(4f64)).mul(Arc::new(function3.square())), + ); + let function5 = Arc::new(DensityFunction::Noise(NoiseFunction::new( Arc::new(InternalNoise::new( builtin_noise_params::CAVE_CHEESE.clone(), None, )), 1f64, 0.6666666666666666f64, - )); - let function6 = DensityFunction::Constant(ConstantFunction::new(0.27f64)) - .add(function5) - .clamp(-1f64, 1f64) - .add( - DensityFunction::Constant(ConstantFunction::new(1.5f64)) - .add(DensityFunction::Constant(ConstantFunction::new(-0.64f64)).mul(sloped_cheese)) - .clamp(0f64, 0.5f64), - ); - let function7 = function4.add(function6); + ))); + let function6 = Arc::new( + DensityFunction::Constant(ConstantFunction::new(0.27f64)) + .add(function5) + .clamp(-1f64, 1f64) + .add(Arc::new( + DensityFunction::Constant(ConstantFunction::new(1.5f64)) + .add(Arc::new( + DensityFunction::Constant(ConstantFunction::new(-0.64f64)) + .mul(sloped_cheese), + )) + .clamp(0f64, 0.5f64), + )), + ); + let function7 = Arc::new(function4.add(function6)); let function8 = function7 .binary_min(built_in_noises::CAVES_ENTRANCES_OVERWORLD.clone()) - .binary_min(function.add(function2)); + .binary_min(Arc::new(function.add(function2))); let function9 = built_in_noises::CAVES_PILLARS_OVERWORLD.clone(); - let function10 = DensityFunction::Range(RangeFunction::new( - Arc::new(function9.clone()), + let function10 = Arc::new(DensityFunction::Range(RangeFunction::new( + function9.clone(), -1000000f64, 0.03f64, Arc::new(DensityFunction::Constant(ConstantFunction::new( -1000000f64, ))), - Arc::new(function9), - )); + function9, + ))); function8.binary_max(function10) } diff --git a/pumpkin-world/src/world_gen/supplier.rs b/pumpkin-world/src/world_gen/supplier.rs new file mode 100644 index 000000000..b5514ed8c --- /dev/null +++ b/pumpkin-world/src/world_gen/supplier.rs @@ -0,0 +1,26 @@ +use enum_dispatch::enum_dispatch; + +use crate::biome::Biome; + +#[derive(Clone)] +#[enum_dispatch] +pub enum BiomeSupplier { + Static(StaticBiomeSupplier), +} + +#[enum_dispatch(BiomeSupplier)] +pub trait BiomeSupplierImpl { + fn biome(&self, x: i32, y: i32, z: i32, noise: &MultiNoiseSampler) -> Biome; +} + +#[derive(Clone)] +pub struct StaticBiomeSupplier {} +impl BiomeSupplierImpl for StaticBiomeSupplier { + fn biome(&self, _x: i32, _y: i32, _z: i32, _noise: &MultiNoiseSampler) -> Biome { + Biome::Plains + } +} + +pub struct MultiNoiseSampler { + +} From 753c60a690d641f70e30206162a73ed83117f2f4 Mon Sep 17 00:00:00 2001 From: kralverde Date: Mon, 14 Oct 2024 17:13:15 -0400 Subject: [PATCH 06/11] remove main cargo.lock --- pumpkin-world/Cargo.toml | 1 + pumpkin-world/src/world_gen/blender/mod.rs | 63 +- pumpkin-world/src/world_gen/chunk.rs | 65 +- pumpkin-world/src/world_gen/heightmap.rs | 1 + .../src/world_gen/implementation/aquifer.rs | 16 +- .../src/world_gen/implementation/mod.rs | 29 +- pumpkin-world/src/world_gen/mod.rs | 1 + .../src/world_gen/noise/chunk_sampler.rs | 963 +++++++++++++++--- pumpkin-world/src/world_gen/noise/config.rs | 6 + .../src/world_gen/noise/density/blend.rs | 26 +- .../src/world_gen/noise/density/end.rs | 4 +- .../src/world_gen/noise/density/math.rs | 77 +- .../src/world_gen/noise/density/mod.rs | 677 ++++++------ .../src/world_gen/noise/density/noise.rs | 12 +- .../src/world_gen/noise/density/offset.rs | 8 +- .../src/world_gen/noise/density/spline.rs | 8 +- .../src/world_gen/noise/density/unary.rs | 20 +- .../src/world_gen/noise/density/weird.rs | 14 +- pumpkin-world/src/world_gen/noise/mod.rs | 325 +++--- pumpkin-world/src/world_gen/noise/router.rs | 138 ++- 20 files changed, 1690 insertions(+), 764 deletions(-) create mode 100644 pumpkin-world/src/world_gen/heightmap.rs diff --git a/pumpkin-world/Cargo.toml b/pumpkin-world/Cargo.toml index 191b3e2fc..c3eed26cb 100644 --- a/pumpkin-world/Cargo.toml +++ b/pumpkin-world/Cargo.toml @@ -23,6 +23,7 @@ lz4 = "1.11.1" serde.workspace = true serde_json = "1.0" enum_dispatch = "0.3.13" +derive-getters = "0.5.0" log.workspace = true diff --git a/pumpkin-world/src/world_gen/blender/mod.rs b/pumpkin-world/src/world_gen/blender/mod.rs index be1755fb9..b32efe658 100644 --- a/pumpkin-world/src/world_gen/blender/mod.rs +++ b/pumpkin-world/src/world_gen/blender/mod.rs @@ -1,4 +1,7 @@ -use std::{collections::HashMap, sync::LazyLock}; +use std::{ + collections::HashMap, + sync::{Arc, LazyLock}, +}; use data::BlendingData; use enum_dispatch::enum_dispatch; @@ -11,8 +14,12 @@ use crate::{biome::Biome, height::HeightLimitViewImpl}; use super::{ biome_coords, - chunk::Chunk, - noise::{builtin_noise_params, density::NoisePosImpl, lerp, perlin::DoublePerlinNoiseSampler}, + chunk::{Chunk, ChunkPos}, + noise::{ + density::NoisePosImpl, + lerp, + perlin::{DoublePerlinNoiseParameters, DoublePerlinNoiseSampler}, + }, supplier::{BiomeSupplier, StaticBiomeSupplier}, }; @@ -21,21 +28,38 @@ pub mod data; static OFFSET_NOISE: LazyLock = LazyLock::new(|| { DoublePerlinNoiseSampler::new( &mut RandomGenerator::Xoroshiro(Xoroshiro::from_seed(42)), - &builtin_noise_params::OFFSET, + &DoublePerlinNoiseParameters::new(-3, &[1f64; 4]), ) }); const BLENDING_BIOME_DISTANCE_THRESHOLD: i32 = (7 << 2) - 1; const BLENDING_CHUNK_DISTANCE_THRESHOLD: i32 = (BLENDING_BIOME_DISTANCE_THRESHOLD + 3) >> 2; const CLOSE_BLENDING_DISTANCE_THRESHOLD: i32 = 5 >> 2; +#[derive(Clone)] pub struct BlendResult { alpha: f64, offset: f64, } +impl BlendResult { + pub fn new(alpha: f64, offset: f64) -> Self { + Self { alpha, offset } + } + + pub fn alpha(&self) -> f64 { + self.alpha + } + + pub fn offset(&self) -> f64 { + self.offset + } +} + #[enum_dispatch(BlenderImpl)] +#[derive(Clone)] pub enum Blender { - NoBlendBlender, + None(NoBlendBlender), + Standard(StandardBlender), } #[enum_dispatch] @@ -45,6 +69,7 @@ pub trait BlenderImpl { fn biome_supplier(&self, supplier: &BiomeSupplier) -> BiomeSupplier; } +#[derive(Clone)] pub struct NoBlendBlender {} impl BlenderImpl for NoBlendBlender { fn calculate(&self, _block_x: i32, _block_z: i32) -> BlendResult { @@ -63,9 +88,10 @@ impl BlenderImpl for NoBlendBlender { } } +#[derive(Clone)] struct StandardBlender { - blend_data: HashMap, - close_blend_data: HashMap, + blend_data: Arc>, + close_blend_data: Arc>, } #[derive(Clone)] @@ -75,13 +101,13 @@ enum BlendingSampleType { } impl StandardBlender { - pub fn new( + fn new( blend_data: HashMap, close_blend_data: HashMap, ) -> Self { Self { - blend_data, - close_blend_data, + blend_data: Arc::new(blend_data), + close_blend_data: Arc::new(close_blend_data), } } @@ -133,7 +159,10 @@ impl StandardBlender { biome_y: i32, biome_z: i32, ) -> f64 { - if let Some(blending_data) = self.blend_data.get(&Chunk::hash(chunk_x, chunk_z)) { + if let Some(blending_data) = self + .blend_data + .get(&ChunkPos::new(chunk_x, chunk_z).to_long()) + { match sample_type { BlendingSampleType::Height => blending_data.height( (biome_x - biome_coords::from_chunk(chunk_x)) as usize, @@ -153,8 +182,8 @@ impl StandardBlender { fn blend_biome(&self, x: i32, y: i32, z: i32) -> Option { for (k, v) in self.blend_data.iter() { - let biome_x = biome_coords::from_chunk(Chunk::packed_x(*k)); - let biome_z = biome_coords::from_chunk(Chunk::packed_z(*k)); + let biome_x = biome_coords::from_chunk(ChunkPos::packed_x(*k)); + let biome_z = biome_coords::from_chunk(ChunkPos::packed_z(*k)); if y >= biome_coords::from_block(v.height_limit.bottom_y()) && y < biome_coords::from_block(v.height_limit.top_y()) @@ -211,8 +240,8 @@ impl BlenderImpl for StandardBlender { let mut val3 = f64::INFINITY; for (chunk_pos, data) in self.blend_data.iter() { - let biome_x = biome_coords::from_chunk(Chunk::packed_x(*chunk_pos)); - let biome_z = biome_coords::from_chunk(Chunk::packed_z(*chunk_pos)); + let biome_x = biome_coords::from_chunk(ChunkPos::packed_x(*chunk_pos)); + let biome_z = biome_coords::from_chunk(ChunkPos::packed_z(*chunk_pos)); for (index, height) in data.surface_heights.iter().enumerate() { if *height != f64::MAX { @@ -264,8 +293,8 @@ impl BlenderImpl for StandardBlender { let mut val3 = f64::INFINITY; for (chunk_pos, data) in self.close_blend_data.iter() { - let biome_x = biome_coords::from_chunk(Chunk::packed_z(*chunk_pos)); - let biome_y = biome_coords::from_chunk(Chunk::packed_z(*chunk_pos)); + let biome_x = biome_coords::from_chunk(ChunkPos::packed_z(*chunk_pos)); + let biome_y = biome_coords::from_chunk(ChunkPos::packed_z(*chunk_pos)); let min_half_section_y = j - 1; let max_half_section_y = j + 1; diff --git a/pumpkin-world/src/world_gen/chunk.rs b/pumpkin-world/src/world_gen/chunk.rs index b268fd5ad..84c84a849 100644 --- a/pumpkin-world/src/world_gen/chunk.rs +++ b/pumpkin-world/src/world_gen/chunk.rs @@ -1,10 +1,14 @@ -use std::ops::Add; +use std::{ops::Add, sync::Arc}; use num_traits::PrimInt; +use parking_lot::Mutex; -use crate::{biome::Biome, block::BlockId, chunk::ChunkData, height::HeightLimitViewImpl}; +use crate::{ + biome::Biome, block::BlockId, chunk::ChunkData, height::HeightLimitViewImpl, + world_gen::noise::chunk_sampler::ChunkNoiseSampler, +}; -use super::{biome_coords, blender::data::BlendingData}; +use super::{biome_coords, blender::data::BlendingData, heightmap::HeightMap}; #[derive(Clone, PartialEq, PartialOrd)] pub enum GenerationState { @@ -171,14 +175,24 @@ impl BlockState { } } -pub struct Chunk { - data: ChunkData, - state: GenerationState, +pub const CHUNK_MARKER: u64 = ChunkPos { + x: 1875066, + z: 1875066, } +.to_long(); -impl Chunk { - pub fn hash(chunk_x: i32, chunk_z: i32) -> u64 { - (chunk_x as u64 & 4294967295u64) | ((chunk_z as u64 & 4294967295u64) << 32) +pub struct ChunkPos { + x: i32, + z: i32, +} + +impl ChunkPos { + pub const fn new(x: i32, z: i32) -> Self { + Self { x, z } + } + + pub const fn to_long(&self) -> u64 { + (self.x as u64 & 4294967295u64) | ((self.z as u64 & 4294967295u64) << 32) } pub fn packed_x(pos: u64) -> i32 { @@ -189,6 +203,22 @@ impl Chunk { (pos.unsigned_shr(32) & 4294967295u64) as i32 } + pub fn get_start_x(&self) -> i32 { + self.x << 4 + } + + pub fn get_start_z(&self) -> i32 { + self.z << 4 + } +} + +pub struct Chunk { + pos: ChunkPos, + data: ChunkData, + state: GenerationState, +} + +impl Chunk { pub fn get_block_state(&self, pos: &BlockPos) -> BlockState { unimplemented!() } @@ -208,6 +238,18 @@ impl Chunk { pub fn status(&self) -> GenerationState { self.state.clone() } + + pub fn get_or_create_noise_sampler(&self) -> Arc> { + unimplemented!() + } + + pub fn get_height_map(&self, map: HeightMapType) -> &HeightMap { + unimplemented!() + } + + pub fn pos(&self) -> &ChunkPos { + &self.pos + } } impl HeightLimitViewImpl for Chunk { @@ -220,6 +262,7 @@ impl HeightLimitViewImpl for Chunk { } } +#[derive(Clone)] pub struct GenerationShapeConfig { y_min: i32, height: i32, @@ -272,6 +315,10 @@ impl GenerationShapeConfig { pub fn vertical_cell_block_count(&self) -> i32 { biome_coords::to_block(self.vertical) } + + pub fn horizontal_cell_block_count(&self) -> i32 { + biome_coords::to_block(self.horizontal) + } } pub mod shape_configs { diff --git a/pumpkin-world/src/world_gen/heightmap.rs b/pumpkin-world/src/world_gen/heightmap.rs new file mode 100644 index 000000000..02e994ef5 --- /dev/null +++ b/pumpkin-world/src/world_gen/heightmap.rs @@ -0,0 +1 @@ +pub enum HeightMap {} diff --git a/pumpkin-world/src/world_gen/implementation/aquifer.rs b/pumpkin-world/src/world_gen/implementation/aquifer.rs index eb40404be..84a0357ab 100644 --- a/pumpkin-world/src/world_gen/implementation/aquifer.rs +++ b/pumpkin-world/src/world_gen/implementation/aquifer.rs @@ -1,4 +1,5 @@ use crate::{self as pumpkin_world, world_gen::noise::density::NoisePosImpl}; +use enum_dispatch::enum_dispatch; use pumpkin_macros::block_id; use crate::block::BlockId; @@ -19,6 +20,7 @@ impl FluidLevel { } } +#[derive(Clone)] pub struct FluidLevelSampler { sea_level: i32, fluid_level_1: FluidLevel, @@ -35,6 +37,12 @@ impl FluidLevelSampler { } } +#[enum_dispatch(AquiferSamplerImpl)] +pub enum AquifierSampler { + SeaLevel(AquiferSeaLevel), +} + +#[enum_dispatch] pub trait AquiferSamplerImpl { fn apply(&self, pos: &impl NoisePosImpl, density: f64) -> Option; } @@ -43,6 +51,12 @@ pub struct AquiferSeaLevel { level_sampler: FluidLevelSampler, } +impl AquiferSeaLevel { + pub fn new(level_sampler: FluidLevelSampler) -> Self { + Self { level_sampler } + } +} + impl AquiferSamplerImpl for AquiferSeaLevel { fn apply(&self, pos: &impl NoisePosImpl, density: f64) -> Option { if density > 0f64 { @@ -56,5 +70,3 @@ impl AquiferSamplerImpl for AquiferSeaLevel { } } } - -pub struct Aquifier {} diff --git a/pumpkin-world/src/world_gen/implementation/mod.rs b/pumpkin-world/src/world_gen/implementation/mod.rs index f8fb21cec..804b134ac 100644 --- a/pumpkin-world/src/world_gen/implementation/mod.rs +++ b/pumpkin-world/src/world_gen/implementation/mod.rs @@ -1,10 +1,12 @@ +use crate::height::HeightLimitViewImpl; + use super::{ blender::Blender, - chunk::{Chunk, GenerationShapeConfig}, + chunk::{Chunk, GenerationShapeConfig, HeightMapType}, noise::config::NoiseConfig, }; -mod aquifer; +pub mod aquifer; pub mod overworld; pub mod superflat; mod surface_builder; @@ -30,4 +32,27 @@ fn internal_populate_noise( min_cell_y: i32, cell_height: i32, ) { + let sampler = chunk.get_or_create_noise_sampler(); + let height_map = chunk.get_height_map(HeightMapType::WorldGenOceanFloor); + let height_map2 = chunk.get_height_map(HeightMapType::WorldGenSurface); + let pos = chunk.pos(); + + let i = pos.get_start_x(); + let j = pos.get_start_z(); + + let mut sampler = sampler.lock(); + sampler.sample_start_density(); + + let k = sampler.horizontal_cell_block_count(); + let l = sampler.vertical_cell_block_count(); + let m = 16 / k; + let n = 16 / k; + + for o in 0..m { + sampler.sample_end_density(o); + + for p in 0..n { + let q = chunk.vertical_section_count() - 1; + } + } } diff --git a/pumpkin-world/src/world_gen/mod.rs b/pumpkin-world/src/world_gen/mod.rs index 448ed8ab9..5a0aca08a 100644 --- a/pumpkin-world/src/world_gen/mod.rs +++ b/pumpkin-world/src/world_gen/mod.rs @@ -2,6 +2,7 @@ mod blender; pub mod chunk; mod generator; mod generic_generator; +mod heightmap; mod implementation; mod noise; pub mod sampler; diff --git a/pumpkin-world/src/world_gen/noise/chunk_sampler.rs b/pumpkin-world/src/world_gen/noise/chunk_sampler.rs index c8a60f4d3..6c3ed9107 100644 --- a/pumpkin-world/src/world_gen/noise/chunk_sampler.rs +++ b/pumpkin-world/src/world_gen/noise/chunk_sampler.rs @@ -1,3 +1,4 @@ +use core::panic; use std::{ borrow::{Borrow, BorrowMut}, cell::{Cell, RefCell}, @@ -5,90 +6,169 @@ use std::{ default, ops::DerefMut, rc::Rc, - sync::Arc, + sync::{Arc, LazyLock}, }; -use crate::world_gen::{ - biome_coords, - blender::{BlendResult, Blender}, - chunk::GenerationShapeConfig, - noise::lerp3, - sampler, +use enum_dispatch::enum_dispatch; +use itertools::Itertools; +use parking_lot::Mutex; + +use crate::{ + block::BlockId, + world_gen::{ + biome_coords, + blender::{BlendResult, Blender, BlenderImpl}, + chunk::{Chunk, ChunkPos, GenerationShapeConfig, CHUNK_MARKER}, + implementation::aquifer::{ + self, AquiferSamplerImpl, AquiferSeaLevel, AquifierSampler, FluidLevelSampler, + }, + noise::lerp3, + sampler, + }, }; use super::{ + config::NoiseConfig, density::{ - Applier, ApplierImpl, DensityFunction, DensityFunctionImpl, NoisePos, NoisePosImpl, - UnblendedNoisePos, VisitorImpl, WrapperFunction, WrapperType, + blend::{BlendAlphaFunction, BlendOffsetFunction}, + Applier, ApplierImpl, BeardifyerFunction, DensityFunction, DensityFunctionImpl, NoisePos, + NoisePosImpl, UnblendedNoisePos, Visitor, VisitorImpl, WrapperFunction, WrapperType, }, lerp, + router::NoiseRouter, }; -struct InterpolationApplier<'a> { - parent_sampler: &'a mut NoisePos<'a>, +pub(crate) struct InterpolationApplier<'a> { + parent_sampler: Arc>>, } impl<'a> ApplierImpl<'a> for InterpolationApplier<'a> { - fn at(&self, index: i32) -> NoisePos<'a> { - /* - match self.parent_sampler { - NoisePos::ChunkNoise(sampler) => { - sampler.start_block_y = - (index + sampler.minimum_cell_y) * sampler.vertical_cell_block_count; - sampler.sample_unique += 1; - sampler.cell_block_y = 0; - sampler.index = index; - - NoisePos::ChunkNoise(sampler) - } - _ => unreachable!(), + fn at(&self, index: usize) -> NoisePos<'a> { + let index = index as i32; + let mut sampler = self.parent_sampler.lock(); + sampler.start_block_y = + (index + sampler.minimum_cell_y) * sampler.vertical_cell_block_count; + sampler.sample_unique += 1; + sampler.cell_block_y = 0; + sampler.index = index; + + NoisePos::ChunkNoise(ChunkNoiseSamplerWrapper { + parent_sampler: self.parent_sampler.clone(), + }) + } + + fn fill(&self, densities: &mut [f64], function: &DensityFunction<'a>) { + let mut sampler = self.parent_sampler.lock(); + + for i in 0..=sampler.vertical_cell_count { + sampler.start_block_y = + (i + sampler.minimum_cell_y) * sampler.vertical_cell_block_count; + sampler.sample_unique += 1; + sampler.cell_block_y = 0; + sampler.index = i; + + drop(sampler); + let sample = function.sample(&NoisePos::ChunkNoise(ChunkNoiseSamplerWrapper { + parent_sampler: self.parent_sampler.clone(), + })); + sampler = self.parent_sampler.lock(); + densities[sampler.index as usize] = sample; } - */ - unimplemented!() - } - - fn fill(&self, _densities: &[f64], function: &DensityFunction<'a>) -> Vec { - // This is hella bad... had to get around borrow checker - // TODO: Fix - - /* - let cell_count = match self.parent_sampler { - NoisePos::ChunkNoise(sampler) => sampler.vertical_cell_count, - _ => unreachable!(), - }; - - let mut result: Vec = Vec::new(); - for i in 0..=cell_count { - match self.parent_sampler { - NoisePos::ChunkNoise(sampler) => { - sampler.start_block_y = - (i + sampler.minimum_cell_y) * sampler.vertical_cell_block_count; - sampler.sample_unique += 1; - sampler.cell_block_y = 0; - sampler.index = i; - // collector.push(function.sample(self.parent_sampler)); - } - - _ => unreachable!(), - } + } +} - let sample = match self.parent_sampler { - NoisePos::ChunkNoise(_) => function.sample(self.parent_sampler), - _ => unreachable!(), - }; +#[derive(Clone)] +pub(crate) struct BlendOffsetDensityFunction<'a> { + parent_sampler: Arc>>, +} - result.push(sample); - } +impl<'a> DensityFunctionImpl<'a> for BlendOffsetDensityFunction<'a> { + fn sample(&self, pos: &NoisePos) -> f64 { + let mut sampler = self.parent_sampler.lock(); + sampler.calculate_blend_result(pos.x(), pos.z()).offset() + } + + fn fill(&self, densities: &mut [f64], applier: &Applier<'a>) { + applier.fill( + densities, + &DensityFunction::ChunkCacheBlendOffset(self.clone()), + ) + } + + fn apply(&self, visitor: &Visitor<'a>) -> Arc> { + DensityFunction::BlendOffset(BlendOffsetFunction {}).apply(visitor) + } + + fn max(&self) -> f64 { + f64::INFINITY + } + + fn min(&self) -> f64 { + f64::NEG_INFINITY + } +} + +#[derive(Clone)] +pub(crate) struct BlendAlphaDensityFunction<'a> { + parent_sampler: Arc>>, +} + +impl<'a> DensityFunctionImpl<'a> for BlendAlphaDensityFunction<'a> { + fn apply(&self, visitor: &Visitor<'a>) -> Arc> { + DensityFunction::BlendAlpha(BlendAlphaFunction {}).apply(visitor) + } + + fn sample(&self, pos: &NoisePos) -> f64 { + let mut sampler = self.parent_sampler.lock(); + sampler.calculate_blend_result(pos.x(), pos.z()).alpha() + } + + fn fill(&self, densities: &mut [f64], applier: &Applier<'a>) { + applier.fill( + densities, + &DensityFunction::ChunkCacheBlendAlpha(self.clone()), + ) + } - result - */ - unimplemented!() + fn min(&self) -> f64 { + 0f64 + } + + fn max(&self) -> f64 { + 1f64 } } #[derive(Clone)] -pub(crate) struct InterpolatorDensityFunction<'a> { - parent_sampler: &'a ChunkNoiseSampler<'a>, +pub(crate) struct InterpolatorDensityFunctionWrapper<'a> { + wrapped: Arc>>, +} + +impl<'a> DensityFunctionImpl<'a> for InterpolatorDensityFunctionWrapper<'a> { + fn sample(&self, pos: &NoisePos) -> f64 { + self.wrapped.lock().sample(pos) + } + + fn fill(&self, densities: &mut [f64], applier: &Applier<'a>) { + self.wrapped.lock().fill(densities, applier) + } + + fn apply(&self, visitor: &Visitor<'a>) -> Arc> { + self.wrapped.lock().apply(visitor) + } + + fn min(&self) -> f64 { + self.wrapped.lock().min() + } + + fn max(&self) -> f64 { + self.wrapped.lock().max() + } +} + +#[derive(Clone)] +struct InterpolatorDensityFunction<'a> { + parent_sampler: Arc>>, start_buffer: Vec>, end_buffer: Vec>, delegate: Arc>, @@ -110,15 +190,14 @@ pub(crate) struct InterpolatorDensityFunction<'a> { } impl<'a> InterpolatorDensityFunction<'a> { - // TODO: All instances automatically added to Sampler fn new( - parent_sampler: &'a ChunkNoiseSampler<'a>, + parent_sampler: Arc>>, delegate: Arc>, vertical_cell_count: i32, horizontal_cell_count: i32, - ) -> Self { - Self { - parent_sampler, + ) -> InterpolatorDensityFunctionWrapper<'a> { + let result = Arc::new(Mutex::new(Self { + parent_sampler: parent_sampler.clone(), start_buffer: Self::create_buffer(vertical_cell_count, horizontal_cell_count), end_buffer: Self::create_buffer(vertical_cell_count, horizontal_cell_count), delegate, @@ -137,7 +216,12 @@ impl<'a> InterpolatorDensityFunction<'a> { z0: 0f64, z1: 0f64, result: 0f64, - } + })); + let wrapper = InterpolatorDensityFunctionWrapper { wrapped: result }; + + let mut sampler = parent_sampler.lock(); + sampler.interpolators.push(wrapper.clone()); + wrapper } fn on_sampled_cell_corners(&mut self, cell_y: usize, cell_z: usize) { @@ -189,20 +273,22 @@ impl<'a> InterpolatorDensityFunction<'a> { impl<'a> DensityFunctionImpl<'a> for InterpolatorDensityFunction<'a> { fn sample(&self, pos: &super::density::NoisePos) -> f64 { if let NoisePos::ChunkNoise(sampler) = pos { - if !std::ptr::eq(sampler, self.parent_sampler) { + let other_lock = { sampler.parent_sampler.lock().uuid }; + + let my_lock = { self.parent_sampler.lock().uuid }; + + if other_lock == my_lock { return self.delegate.sample(pos); } } - assert!(self.parent_sampler.interpolating, "Not interpolating"); - if self.parent_sampler.sampling_for_caches { + let sampler = self.parent_sampler.lock(); + assert!(sampler.interpolating, "Not interpolating"); + if sampler.sampling_for_caches { lerp3( - self.parent_sampler.cell_block_x as f64 - / self.parent_sampler.horizontal_cell_block_count as f64, - self.parent_sampler.cell_block_y as f64 - / self.parent_sampler.vertical_cell_block_count as f64, - self.parent_sampler.cell_block_z as f64 - / self.parent_sampler.horizontal_cell_block_count as f64, + sampler.cell_block_x as f64 / sampler.horizontal_cell_block_count as f64, + sampler.cell_block_y as f64 / sampler.vertical_cell_block_count as f64, + sampler.cell_block_z as f64 / sampler.horizontal_cell_block_count as f64, self.x0y0z0, self.x1y0z0, self.x0y1z0, @@ -217,18 +303,24 @@ impl<'a> DensityFunctionImpl<'a> for InterpolatorDensityFunction<'a> { } } - fn apply(&'a self, visitor: &'a super::density::Visitor) -> Arc> { + fn apply(&self, visitor: &Visitor<'a>) -> Arc> { visitor.apply(Arc::new(DensityFunction::Wrapper(WrapperFunction::new( self.delegate.clone(), WrapperType::Interpolated, )))) } - fn fill(&self, densities: &[f64], applier: &Applier) -> Vec { - if self.parent_sampler.sampling_for_caches { - applier.fill(densities, &DensityFunction::Interpolator(self.clone())) + fn fill(&self, densities: &mut [f64], applier: &Applier<'a>) { + let sampling = { self.parent_sampler.lock().sampling_for_caches }; + if sampling { + applier.fill( + densities, + &DensityFunction::ChunkCacheInterpolator(InterpolatorDensityFunctionWrapper { + wrapped: Arc::new(Mutex::new(self.clone())), + }), + ) } else { - self.delegate.fill(densities, applier) + self.delegate.fill(densities, applier); } } @@ -243,14 +335,14 @@ impl<'a> DensityFunctionImpl<'a> for InterpolatorDensityFunction<'a> { #[derive(Clone)] pub(crate) struct FlatCacheDensityFunction<'a> { - parent_sampler: &'a ChunkNoiseSampler<'a>, + parent_sampler: Arc>>, delegate: Arc>, cache: Vec>, } impl<'a> FlatCacheDensityFunction<'a> { fn new( - parent_sampler: &'a ChunkNoiseSampler<'a>, + parent_sampler: Arc>>, delegate: Arc>, biome_start_x: i32, biome_start_z: i32, @@ -288,8 +380,12 @@ impl<'a> DensityFunctionImpl<'a> for FlatCacheDensityFunction<'a> { fn sample(&self, pos: &NoisePos) -> f64 { let i = biome_coords::from_block(pos.x()); let j = biome_coords::from_block(pos.z()); - let k = i - self.parent_sampler.start_biome_x; - let l = j - self.parent_sampler.start_biome_z; + let (start_biome_x, start_biome_z) = { + let sampler = self.parent_sampler.lock(); + (sampler.start_biome_x, sampler.start_biome_z) + }; + let k = i - start_biome_x; + let l = j - start_biome_z; if k >= 0 && l >= 0 && (k as usize) < self.cache.len() && (l as usize) < self.cache.len() { self.cache[k as usize][l as usize] } else { @@ -297,11 +393,14 @@ impl<'a> DensityFunctionImpl<'a> for FlatCacheDensityFunction<'a> { } } - fn fill(&self, densities: &[f64], applier: &Applier) -> Vec { - applier.fill(densities, &DensityFunction::FlatCache(self.clone())) + fn fill(&self, densities: &mut [f64], applier: &Applier<'a>) { + applier.fill( + densities, + &DensityFunction::ChunkCacheFlatCache(self.clone()), + ); } - fn apply(&'a self, visitor: &'a super::density::Visitor) -> Arc> { + fn apply(&self, visitor: &Visitor<'a>) -> Arc> { visitor.apply(Arc::new(DensityFunction::Wrapper(WrapperFunction::new( self.delegate.apply(visitor), WrapperType::CacheFlat, @@ -317,9 +416,394 @@ impl<'a> DensityFunctionImpl<'a> for FlatCacheDensityFunction<'a> { } } -struct CellCacheDensityFunction {} +#[derive(Clone)] +pub(crate) struct CellCacheDensityFunctionWrapper<'a> { + wrapped: Arc>, +} + +impl<'a> DensityFunctionImpl<'a> for CellCacheDensityFunctionWrapper<'a> { + fn sample(&self, pos: &NoisePos) -> f64 { + self.wrapped.sample(pos) + } + + fn fill(&self, densities: &mut [f64], applier: &Applier<'a>) { + applier.fill( + densities, + &DensityFunction::ChunkCacheCellCache(self.clone()), + ); + } + + fn apply(&self, visitor: &Visitor<'a>) -> Arc> { + self.wrapped.apply(visitor) + } + + fn min(&self) -> f64 { + self.wrapped.min() + } + + fn max(&self) -> f64 { + self.wrapped.max() + } +} + +#[derive(Clone)] +struct CellCacheDensityFunction<'a> { + parent_sampler: Arc>>, + delegate: Arc>, + cache: Vec, +} + +impl<'a> CellCacheDensityFunction<'a> { + fn new( + parent_sampler: Arc>>, + delegate: Arc>, + ) -> CellCacheDensityFunctionWrapper<'a> { + let cache_size = { + let sampler = parent_sampler.lock(); + sampler.horizontal_cell_block_count + * sampler.horizontal_cell_block_count + * sampler.vertical_cell_block_count + }; + let result = Arc::new(Self { + parent_sampler: parent_sampler.clone(), + delegate, + cache: (0..cache_size).map(|_| 0f64).collect(), + }); + + let wrapped = CellCacheDensityFunctionWrapper { wrapped: result }; + let mut sampler = parent_sampler.lock(); + sampler.caches.push(wrapped.clone()); + + wrapped + } +} + +impl<'a> DensityFunctionImpl<'a> for CellCacheDensityFunction<'a> { + fn sample(&self, pos: &NoisePos) -> f64 { + if let NoisePos::ChunkNoise(sampler) = pos { + let other_lock = { sampler.parent_sampler.lock().uuid }; + + let my_lock = { self.parent_sampler.lock().uuid }; + + if other_lock == my_lock { + return self.delegate.sample(pos); + } + } + + let sampler = self.parent_sampler.lock(); + assert!(sampler.interpolating); + let i = sampler.cell_block_x; + let j = sampler.cell_block_y; + let k = sampler.cell_block_z; + + if i >= 0 + && k >= 0 + && i < sampler.horizontal_cell_block_count + && j < sampler.vertical_cell_block_count + && k < sampler.horizontal_cell_block_count + { + self.cache[(((sampler.vertical_cell_block_count - 1 - j) + * sampler.horizontal_cell_block_count + + i) + * sampler.horizontal_cell_block_count + + k) as usize] + } else { + self.delegate.sample(pos) + } + } + + fn fill(&self, densities: &mut [f64], applier: &Applier<'a>) {} + + fn apply(&self, visitor: &Visitor<'a>) -> Arc> { + visitor.apply(Arc::new(DensityFunction::Wrapper(WrapperFunction::new( + self.delegate.apply(visitor), + WrapperType::CacheCell, + )))) + } + + fn min(&self) -> f64 { + self.delegate.min() + } + + fn max(&self) -> f64 { + self.delegate.max() + } +} + +struct CacheOnceDensityFunctionData { + sample_unique_index: u64, + cache_once_unique_index: u64, + last_sampling_result: f64, + cache: Option>, +} + +#[derive(Clone)] +pub(crate) struct CacheOnceDensityFunction<'a> { + parent_sampler: Arc>>, + delegate: Arc>, + data: Arc>, +} + +impl<'a> CacheOnceDensityFunction<'a> { + fn new( + parent_sampler: Arc>>, + delegate: Arc>, + ) -> Self { + Self { + parent_sampler, + delegate, + data: Arc::new(Mutex::new(CacheOnceDensityFunctionData { + sample_unique_index: 0, + cache_once_unique_index: 0, + last_sampling_result: 0f64, + cache: None, + })), + } + } +} + +impl<'a> DensityFunctionImpl<'a> for CacheOnceDensityFunction<'a> { + fn sample(&self, pos: &NoisePos) -> f64 { + let parent_sampler = self.parent_sampler.lock(); + let mut data = self.data.lock(); + + if let NoisePos::ChunkNoise(sampler) = pos { + let other_id = { sampler.parent_sampler.lock().uuid }; + let this_id = { self.parent_sampler.lock().uuid }; + if other_id != this_id { + return self.delegate.sample(pos); + } + } + + if let Some(cache) = &data.cache { + if data.cache_once_unique_index == parent_sampler.cache_unique { + return cache[parent_sampler.index as usize]; + } + } + + if data.sample_unique_index == parent_sampler.sample_unique { + data.last_sampling_result + } else { + data.sample_unique_index = parent_sampler.sample_unique; + let d = self.delegate.sample(pos); + data.last_sampling_result = d; + d + } + } + + fn fill(&self, densities: &mut [f64], applier: &Applier<'a>) { + let parent_sampler = self.parent_sampler.lock(); + let mut data = self.data.lock(); + let cache_once_unique_index = data.cache_once_unique_index; + + if let Some(cache) = &mut data.cache { + if parent_sampler.cache_unique == cache_once_unique_index { + densities + .iter_mut() + .zip_eq(cache) + .for_each(|(val, temp)| *val = *temp); + return; + } + } + + self.delegate.fill(densities, applier); + data.cache_once_unique_index = parent_sampler.cache_unique; + if let Some(cache) = &mut data.cache { + if cache.len() == densities.len() { + cache + .iter_mut() + .zip_eq(densities) + .for_each(|(val, temp)| *val = *temp); + return; + } + } + data.cache = Some(Vec::from_iter(densities.iter().map(|x| *x))); + } + + fn apply(&self, visitor: &Visitor<'a>) -> Arc> { + visitor.apply(Arc::new(DensityFunction::Wrapper(WrapperFunction::new( + self.delegate.apply(visitor), + WrapperType::CacheOnce, + )))) + } + + fn max(&self) -> f64 { + self.delegate.max() + } + + fn min(&self) -> f64 { + self.delegate.min() + } +} + +struct Cache2DDensityFunctionData { + last_sampling_column_pos: u64, + last_sampling_result: f64, +} + +#[derive(Clone)] +pub(crate) struct Cache2DDensityFunction<'a> { + delegate: Arc>, + data: Arc>, +} + +impl<'a> Cache2DDensityFunction<'a> { + fn new(delegate: Arc>) -> Self { + Self { + delegate, + data: Arc::new(Mutex::new(Cache2DDensityFunctionData { + last_sampling_column_pos: CHUNK_MARKER, + last_sampling_result: 0f64, + })), + } + } +} + +impl<'a> DensityFunctionImpl<'a> for Cache2DDensityFunction<'a> { + fn sample(&self, pos: &NoisePos) -> f64 { + let i = pos.x(); + let j = pos.z(); + let l = ChunkPos::new(i, j).to_long(); + let mut data = self.data.lock(); + if data.last_sampling_column_pos == l { + data.last_sampling_result + } else { + data.last_sampling_column_pos = l; + drop(data); + let d = self.delegate.sample(pos); + let mut data = self.data.lock(); + data.last_sampling_result = d; + d + } + } + + fn fill(&self, densities: &mut [f64], applier: &Applier<'a>) { + self.delegate.fill(densities, applier) + } + + fn apply(&self, visitor: &Visitor<'a>) -> Arc> { + visitor.apply(Arc::new(DensityFunction::Wrapper(WrapperFunction::new( + self.delegate.clone(), + WrapperType::Cache2D, + )))) + } + + fn min(&self) -> f64 { + self.delegate.min() + } + + fn max(&self) -> f64 { + self.delegate.max() + } +} + +#[enum_dispatch(BlockStateSamplerImpl)] +enum BlockStateSampler<'a> { + Aquifer(AquiferBlockStateSampler<'a>), +} + +struct AquiferBlockStateSampler<'a> { + aquifier: Arc, + function: Arc>, +} + +impl<'a> BlockStateSamplerImpl for AquiferBlockStateSampler<'a> { + fn sample(&self, pos: &NoisePos) -> Option { + self.aquifier.apply(pos, self.function.sample(pos)) + } +} + +#[enum_dispatch] +trait BlockStateSamplerImpl { + fn sample(&self, pos: &NoisePos) -> Option; +} + +static SAMPLER_ID_COUNTER: LazyLock>> = LazyLock::new(|| Arc::new(Mutex::new(0u64))); + +pub(crate) struct ChunkSamplerDensityFunctionConverter<'a> { + parent_sampler: Arc>>, +} -enum BlockStateSampler {} +impl<'a> VisitorImpl<'a> for ChunkSamplerDensityFunctionConverter<'a> { + fn apply(&self, function: Arc>) -> Arc> { + let sampler = self.parent_sampler.lock(); + let vertical_cell_count = sampler.vertical_cell_count; + let horizontal_cell_count = sampler.horizontal_cell_count; + + let biome_start_x = sampler.start_biome_x; + let biome_start_z = sampler.start_biome_z; + let horizontal_biome_end = sampler.horizontal_biome_end as usize; + + let blender = sampler.blender; + + if let DensityFunction::Wrapper(wrapped) = function.as_ref() { + match wrapped.wrapper() { + WrapperType::Interpolated => Arc::new(DensityFunction::ChunkCacheInterpolator( + InterpolatorDensityFunction::new( + self.parent_sampler.clone(), + wrapped.wrapped(), + vertical_cell_count, + horizontal_cell_count, + ), + )), + WrapperType::Cache2D => Arc::new(DensityFunction::ChunkCache2DCache( + Cache2DDensityFunction::new(wrapped.wrapped()), + )), + WrapperType::CacheFlat => Arc::new(DensityFunction::ChunkCacheFlatCache( + FlatCacheDensityFunction::new( + self.parent_sampler.clone(), + wrapped.wrapped(), + biome_start_x, + biome_start_z, + horizontal_biome_end, + true, + ), + )), + WrapperType::CacheOnce => Arc::new(DensityFunction::ChunkCacheOnceCache( + CacheOnceDensityFunction::new(self.parent_sampler.clone(), wrapped.wrapped()), + )), + WrapperType::CacheCell => Arc::new(DensityFunction::ChunkCacheCellCache( + CellCacheDensityFunction::new(self.parent_sampler.clone(), wrapped.wrapped()), + )), + } + } else if let Blender::None(_) = blender { + if let DensityFunction::BlendAlpha(_) = function.as_ref() { + let alpha_cache = { + sampler + .self_referential + .as_ref() + .unwrap() + .cached_blend_alpha_density_function + .clone() + }; + Arc::new(DensityFunction::ChunkCacheFlatCache(alpha_cache)) + } else if let DensityFunction::BlendOffset(_) = function.as_ref() { + let offset_cache = { + sampler + .self_referential + .as_ref() + .unwrap() + .cached_blend_offset_density_function + .clone() + }; + Arc::new(DensityFunction::ChunkCacheFlatCache(offset_cache)) + } else { + function + } + } else { + function + } + } +} + +struct ChunkNoiseSamplerSelfReferential<'a> { + cached_blend_alpha_density_function: FlatCacheDensityFunction<'a>, + cached_blend_offset_density_function: FlatCacheDensityFunction<'a>, + block_state_sampler: BlockStateSampler<'a>, + initial_density: Arc>, + aquifer_sampler: Arc, + interpolation_applier: Applier<'a>, +} pub struct ChunkNoiseSampler<'a> { shape_config: GenerationShapeConfig, @@ -330,14 +814,10 @@ pub struct ChunkNoiseSampler<'a> { start_cell_z: i32, start_biome_x: i32, start_biome_z: i32, - interpolators: Vec>, - caches: Vec, + interpolators: Vec>, + caches: Vec>, surface_height_estimate_cache: HashMap, - initial_density: Arc>, - block_state_sampler: BlockStateSampler, - blender: Blender, - cached_blend_alpha_density_function: FlatCacheDensityFunction<'a>, - cached_blend_offset_density_function: FlatCacheDensityFunction<'a>, + blender: &'a Blender, last_blended_column_pos: u64, last_blending_result: BlendResult, horizontal_biome_end: i32, @@ -354,39 +834,286 @@ pub struct ChunkNoiseSampler<'a> { sample_unique: u64, cache_unique: u64, index: i32, + uuid: u64, + visitor: Option>>, + self_referential: Option>, } -impl<'a> ApplierImpl<'a> for ChunkNoiseSampler<'a> { - fn at(&self, index: i32) -> NoisePos { - /* - let j = index % self.horizontal_cell_block_count; - let k = index % self.horizontal_cell_block_count; - let l = index % self.horizontal_cell_block_count; - let m = self.vertical_cell_block_count - 1 - (k / self.horizontal_cell_block_count); +impl<'a> ChunkNoiseSampler<'a> { + pub fn horizontal_cell_block_count(&self) -> i32 { + self.horizontal_cell_block_count + } + + pub fn vertical_cell_block_count(&self) -> i32 { + self.vertical_cell_block_count + } + + pub fn sample_start_density(&mut self) { + if self.interpolating { + panic!("interpolating twice"); + } + + self.interpolating = true; + self.sample_unique = 0; + self.sample_density(true, self.start_cell_x); + } + + pub fn sample_end_density(&mut self, cell_x: i32) { + self.sample_density(false, self.start_cell_x + cell_x + 1); + self.start_block_x = (self.start_cell_x * cell_x) * self.horizontal_cell_block_count + } - self.cell_block_x = l; - self.cell_block_y = m; - self.cell_block_z = j; - self.index = index; - */ - unimplemented!() + fn sample_density(&mut self, start: bool, cell_x: i32) { + self.start_block_x = cell_x * self.horizontal_cell_block_count; + self.cell_block_x = 0; + + for i in 0..=self.horizontal_cell_count { + let j = self.start_cell_z + i; + self.start_cell_z = j * self.horizontal_cell_block_count; + self.cell_block_z = 0; + self.cache_unique += 1; + + for interpolator in self.interpolators.iter() { + let mut wrapped = interpolator.wrapped.lock(); + let ds = &mut (if start { + &mut wrapped.start_buffer + } else { + &mut wrapped.end_buffer + })[i as usize]; + + interpolator.fill( + ds, + &self + .self_referential + .as_ref() + .expect("call .init()") + .interpolation_applier, + ); + } + } + + self.cache_unique += 1; } - fn fill(&self, densities: &[f64], function: &DensityFunction<'a>) -> Vec { - unimplemented!() + fn init_visitor(me: Arc>>) { + let visitor = Visitor::ChunkSampler(ChunkSamplerDensityFunctionConverter { + parent_sampler: me.clone(), + }); + + let mut sampler = me.lock(); + sampler.visitor = Some(Arc::new(visitor)) + } + + fn init( + parent_sampler: Arc>>, + noise_router: &'a NoiseRouter<'a>, + fluid_level: FluidLevelSampler, + visitor: &Visitor<'a>, + ) { + let sampler = parent_sampler.lock(); + + let mut cached_blend_alpha_density_function = FlatCacheDensityFunction::new( + parent_sampler.clone(), + Arc::new(DensityFunction::ChunkCacheBlendAlpha( + BlendAlphaDensityFunction { + parent_sampler: parent_sampler.clone(), + }, + )), + sampler.start_biome_x, + sampler.start_biome_z, + sampler.horizontal_biome_end as usize, + false, + ); + + let mut cached_blend_offset_density_function = FlatCacheDensityFunction::new( + parent_sampler.clone(), + Arc::new(DensityFunction::ChunkCacheBlendOffset( + BlendOffsetDensityFunction { + parent_sampler: parent_sampler.clone(), + }, + )), + sampler.start_biome_x, + sampler.start_biome_z, + sampler.horizontal_biome_end as usize, + false, + ); + + for i in 0..=(sampler.horizontal_biome_end as usize) { + let j = sampler.start_biome_x + (i as i32); + let k = biome_coords::to_block(j); + for l in 0..=(sampler.horizontal_biome_end as usize) { + let m = sampler.start_biome_z + (l as i32); + let n = biome_coords::to_block(m); + let result = sampler.blender.calculate(k, n); + cached_blend_alpha_density_function.cache[i][l] = result.alpha(); + cached_blend_offset_density_function.cache[i][l] = result.offset(); + } + } + + let new_router = noise_router.apply(visitor); + let aquifer = Arc::new(AquifierSampler::SeaLevel(AquiferSeaLevel::new(fluid_level))); + let final_density = new_router + .final_densitiy + .add(Arc::new(DensityFunction::Beardifyer(BeardifyerFunction {}))); + + let function = DensityFunction::Wrapper(WrapperFunction::new( + Arc::new(final_density), + WrapperType::CacheCell, + )); + + let block_sampler = BlockStateSampler::Aquifer(AquiferBlockStateSampler { + aquifier: aquifer.clone(), + function: function.apply(visitor), + }); + + let self_referring = ChunkNoiseSamplerSelfReferential { + cached_blend_alpha_density_function, + cached_blend_offset_density_function, + aquifer_sampler: aquifer, + block_state_sampler: block_sampler, + initial_density: new_router.internal_density.clone(), + interpolation_applier: Applier::Interpolation(InterpolationApplier { + parent_sampler: parent_sampler.clone(), + }), + }; + let mut sampler = parent_sampler.lock(); + sampler.self_referential = Some(self_referring); + } + + fn new( + horizontal_cell_count: i32, + start_block_x: i32, + start_block_z: i32, + shape: &GenerationShapeConfig, + blender: &'a Blender, + ) -> Self { + let shape_config = shape.clone(); + let horizontal_cell_block_count = shape_config.horizontal_cell_block_count(); + let vertical_cell_block_count = shape_config.vertical_cell_block_count(); + let vertical_cell_count = shape_config.height() / vertical_cell_block_count; + let minimum_cell_y = shape_config.min_y() / vertical_cell_block_count; + let start_cell_x = start_block_x / horizontal_cell_block_count; + let start_cell_z = start_block_z / horizontal_cell_block_count; + let interpolators: Vec> = Vec::new(); + let caches: Vec> = Vec::new(); + let start_biome_x = biome_coords::from_block(start_block_x); + let start_biome_z = biome_coords::from_block(start_block_z); + let horizontal_biome_end = + biome_coords::from_block(horizontal_cell_count * horizontal_cell_block_count); + + let new_id = { + let mut id = SAMPLER_ID_COUNTER.lock(); + let new_id = *id; + *id += 1; + new_id + }; + + Self { + shape_config, + horizontal_cell_block_count, + vertical_cell_block_count, + horizontal_cell_count, + vertical_cell_count, + minimum_cell_y, + start_cell_x, + start_cell_z, + interpolators, + caches, + start_biome_x, + start_biome_z, + horizontal_biome_end, + blender, + surface_height_estimate_cache: HashMap::new(), + last_blending_result: BlendResult::new(1f64, 0f64), + last_blended_column_pos: CHUNK_MARKER, + interpolating: false, + sampling_for_caches: false, + start_block_z: 0, + start_block_x: 0, + start_block_y: 0, + cell_block_x: 0, + cell_block_y: 0, + cell_block_z: 0, + sample_unique: 0, + cache_unique: 0, + uuid: new_id, + index: 0, + visitor: None, + self_referential: None, + } + } + + fn calculate_blend_result(&mut self, block_x: i32, block_z: i32) -> BlendResult { + let l = ChunkPos::new(block_x, block_z).to_long(); + if l != self.last_blended_column_pos { + self.last_blended_column_pos = l; + let blend_result = self.blender.calculate(block_x, block_z); + self.last_blending_result = blend_result; + } + self.last_blending_result.clone() + } +} + +#[derive(Clone)] +pub(crate) struct ChunkNoiseSamplerWrapper<'a> { + parent_sampler: Arc>>, +} + +impl<'a> ApplierImpl<'a> for ChunkNoiseSamplerWrapper<'a> { + fn at(&self, index: usize) -> NoisePos<'a> { + let index = index as i32; + let mut sampler = self.parent_sampler.lock(); + let j = index % sampler.horizontal_cell_block_count; + let k = index % sampler.horizontal_cell_block_count; + let l = index % sampler.horizontal_cell_block_count; + let m = sampler.vertical_cell_block_count - 1 - (k / sampler.horizontal_cell_block_count); + + sampler.cell_block_x = l; + sampler.cell_block_y = m; + sampler.cell_block_z = j; + sampler.index = index; + + NoisePos::ChunkNoise(self.clone()) + } + + fn fill(&self, densities: &mut [f64], function: &DensityFunction<'a>) { + let mut sampler = self.parent_sampler.lock(); + sampler.index = 0; + for i in (0..=sampler.vertical_cell_block_count).rev() { + sampler.cell_block_y = i; + for j in 0..sampler.horizontal_cell_block_count { + sampler.cell_block_x = j; + for k in 0..sampler.horizontal_cell_block_count { + sampler.cell_block_z = k; + drop(sampler); + let sample = function.sample(&NoisePos::ChunkNoise(self.clone())); + sampler = self.parent_sampler.lock(); + densities[sampler.index as usize] = sample; + sampler.index += 1; + } + } + } } } -impl<'a> NoisePosImpl for ChunkNoiseSampler<'a> { +impl<'a> NoisePosImpl for ChunkNoiseSamplerWrapper<'a> { fn z(&self) -> i32 { - unimplemented!() + let sampler = self.parent_sampler.lock(); + sampler.start_block_z + sampler.cell_block_z } fn y(&self) -> i32 { - unimplemented!() + let sampler = self.parent_sampler.lock(); + sampler.start_block_y + sampler.cell_block_y } fn x(&self) -> i32 { - unimplemented!() + let sampler = self.parent_sampler.lock(); + sampler.start_block_x + sampler.cell_block_x + } + + fn get_blender(&self) -> Blender { + let sampler = self.parent_sampler.lock(); + sampler.blender.clone() } } diff --git a/pumpkin-world/src/world_gen/noise/config.rs b/pumpkin-world/src/world_gen/noise/config.rs index 96bd438b6..ab08dee04 100644 --- a/pumpkin-world/src/world_gen/noise/config.rs +++ b/pumpkin-world/src/world_gen/noise/config.rs @@ -8,3 +8,9 @@ pub struct NoiseConfig<'a> { random_deriver: RandomDeriver, router: NoiseRouter<'a>, } + +impl<'a> NoiseConfig<'a> { + pub fn noise_router(&self) -> NoiseRouter<'a> { + self.router.clone() + } +} diff --git a/pumpkin-world/src/world_gen/noise/density/blend.rs b/pumpkin-world/src/world_gen/noise/density/blend.rs index dd5bcb32e..33f17616a 100644 --- a/pumpkin-world/src/world_gen/noise/density/blend.rs +++ b/pumpkin-world/src/world_gen/noise/density/blend.rs @@ -15,8 +15,8 @@ impl<'a> DensityFunctionImpl<'a> for BlendOffsetFunction { 0f64 } - fn fill(&self, densities: &[f64], _applier: &Applier) -> Vec { - densities.iter().map(|_| 0f64).collect() + fn fill(&self, densities: &mut [f64], _applier: &Applier) { + densities.fill(0f64) } fn min(&self) -> f64 { @@ -27,7 +27,7 @@ impl<'a> DensityFunctionImpl<'a> for BlendOffsetFunction { 0f64 } - fn apply(&'a self, visitor: &'a Visitor) -> Arc> { + fn apply(&self, visitor: &Visitor<'a>) -> Arc> { visitor.apply(Arc::new(DensityFunction::BlendOffset(self.clone()))) } } @@ -40,8 +40,8 @@ impl<'a> DensityFunctionImpl<'a> for BlendAlphaFunction { 1f64 } - fn fill(&self, densities: &[f64], _applier: &Applier) -> Vec { - densities.iter().map(|_| 1f64).collect() + fn fill(&self, densities: &mut [f64], _applier: &Applier) { + densities.fill(1f64); } fn max(&self) -> f64 { @@ -52,7 +52,7 @@ impl<'a> DensityFunctionImpl<'a> for BlendAlphaFunction { 1f64 } - fn apply(&'a self, visitor: &'a Visitor) -> Arc> { + fn apply(&self, visitor: &Visitor<'a>) -> Arc> { visitor.apply(Arc::new(DensityFunction::BlendAlpha(self.clone()))) } } @@ -79,16 +79,14 @@ impl<'a> DensityFunctionImpl<'a> for BlendDensityFunction<'a> { self.apply_density(pos, self.function.sample(pos)) } - fn fill(&self, densities: &[f64], applier: &Applier) -> Vec { - let densities = self.function.fill(densities, applier); - densities - .iter() - .enumerate() - .map(|(i, x)| self.apply_density(&applier.at(i as i32), *x)) - .collect() + fn fill(&self, densities: &mut [f64], applier: &Applier<'a>) { + self.function.fill(densities, applier); + densities.iter_mut().enumerate().for_each(|(i, x)| { + *x = self.apply_density(&applier.at(i), *x); + }); } - fn apply(&'a self, visitor: &'a Visitor) -> Arc> { + fn apply(&self, visitor: &Visitor<'a>) -> Arc> { let new_function = BlendDensityFunction { function: self.function.apply(visitor), }; diff --git a/pumpkin-world/src/world_gen/noise/density/end.rs b/pumpkin-world/src/world_gen/noise/density/end.rs index 671f0bfc5..fd22fb251 100644 --- a/pumpkin-world/src/world_gen/noise/density/end.rs +++ b/pumpkin-world/src/world_gen/noise/density/end.rs @@ -56,7 +56,7 @@ impl EndIslandFunction { } impl<'a> DensityFunctionImpl<'a> for EndIslandFunction { - fn fill(&self, densities: &[f64], applier: &Applier) -> Vec { + fn fill(&self, densities: &mut [f64], applier: &Applier) { applier.fill(densities, &DensityFunction::EndIsland(self.clone())) } @@ -72,7 +72,7 @@ impl<'a> DensityFunctionImpl<'a> for EndIslandFunction { 0.5625f64 } - fn apply(&'a self, visitor: &'a Visitor) -> Arc> { + fn apply(&self, visitor: &Visitor<'a>) -> Arc> { visitor.apply(Arc::new(DensityFunction::EndIsland(self.clone()))) } } diff --git a/pumpkin-world/src/world_gen/noise/density/math.rs b/pumpkin-world/src/world_gen/noise/density/math.rs index d25b52de4..d20cae5f3 100644 --- a/pumpkin-world/src/world_gen/noise/density/math.rs +++ b/pumpkin-world/src/world_gen/noise/density/math.rs @@ -3,8 +3,8 @@ use std::sync::Arc; use log::warn; use super::{ - Applier, DensityFunction, DensityFunctionImpl, NoisePos, UnaryDensityFunction, Visitor, - VisitorImpl, + Applier, ApplierImpl, DensityFunction, DensityFunctionImpl, NoisePos, UnaryDensityFunction, + Visitor, VisitorImpl, }; #[derive(Clone)] @@ -23,7 +23,7 @@ pub struct LinearFunction<'a> { } impl<'a> DensityFunctionImpl<'a> for LinearFunction<'a> { - fn apply(&'a self, visitor: &'a Visitor) -> Arc> { + fn apply(&self, visitor: &Visitor<'a>) -> Arc> { let new_function = self.input.apply(visitor); let d = new_function.min(); let e = new_function.max(); @@ -52,12 +52,11 @@ impl<'a> DensityFunctionImpl<'a> for LinearFunction<'a> { self.apply_density(self.input.sample(pos)) } - fn fill(&self, densities: &[f64], applier: &Applier) -> Vec { - let densities = self.input.fill(densities, applier); + fn fill(&self, densities: &mut [f64], applier: &Applier<'a>) { + self.input.fill(densities, applier); densities - .iter() - .map(|val| self.apply_density(*val)) - .collect() + .iter_mut() + .for_each(|val| *val = self.apply_density(*val)) } fn min(&self) -> f64 { @@ -211,35 +210,47 @@ impl<'a> DensityFunctionImpl<'a> for BinaryFunction<'a> { } } - fn fill(&self, densities: &[f64], applier: &Applier) -> Vec { - let densities1 = self.arg1.fill(densities, applier); - let densities2 = self.arg2.fill(densities, applier); - + fn fill(&self, densities: &mut [f64], applier: &Applier<'a>) { + self.arg1.fill(densities, applier); match self.action { - BinaryType::Add => densities1 - .iter() - .zip(densities2) - .map(|(x, y)| x + y) - .collect(), - BinaryType::Mul => densities1 - .iter() - .zip(densities2) - .map(|(x, y)| x * y) - .collect(), - BinaryType::Min => densities1 - .iter() - .zip(densities2) - .map(|(x, y)| x.min(y)) - .collect(), - BinaryType::Max => densities1 - .iter() - .zip(densities2) - .map(|(x, y)| x.max(y)) - .collect(), + BinaryType::Add => { + let mut ds = Vec::with_capacity(densities.len()); + densities.iter().for_each(|_| ds.push(0f64)); + self.arg2.fill(&mut ds, applier); + densities + .iter_mut() + .zip(ds) + .for_each(|(real, temp)| *real += temp); + } + BinaryType::Mul => { + densities.iter_mut().enumerate().for_each(|(i, val)| { + if *val != 0f64 { + *val *= self.arg2.sample(&applier.at(i)); + }; + }); + } + BinaryType::Min => { + let e = self.arg2.min(); + + densities.iter_mut().enumerate().for_each(|(i, val)| { + if *val >= e { + *val = val.min(self.arg2.sample(&applier.at(i))); + } + }); + } + BinaryType::Max => { + let e = self.arg2.max(); + + densities.iter_mut().enumerate().for_each(|(i, val)| { + if *val <= e { + *val = val.max(self.arg2.sample(&applier.at(i))) + } + }); + } } } - fn apply(&'a self, visitor: &'a Visitor) -> Arc> { + fn apply(&self, visitor: &Visitor<'a>) -> Arc> { visitor.apply(Arc::new(BinaryFunction::create( self.action.clone(), self.arg1.apply(visitor), diff --git a/pumpkin-world/src/world_gen/noise/density/mod.rs b/pumpkin-world/src/world_gen/noise/density/mod.rs index dc073cd49..9ea93436e 100644 --- a/pumpkin-world/src/world_gen/noise/density/mod.rs +++ b/pumpkin-world/src/world_gen/noise/density/mod.rs @@ -1,6 +1,7 @@ use std::{ops::Deref, sync::Arc}; use blend::{BlendAlphaFunction, BlendDensityFunction, BlendOffsetFunction}; +use derive_getters::Getters; use end::EndIslandFunction; use enum_dispatch::enum_dispatch; use math::{BinaryFunction, BinaryType, LinearFunction}; @@ -8,17 +9,29 @@ use noise::{InternalNoise, InterpolatedNoiseSampler, NoiseFunction, ShiftedNoise use offset::{ShiftAFunction, ShiftBFunction}; use spline::SplineFunction; use unary::{ClampFunction, UnaryFunction, UnaryType}; -use weird::WierdScaledFunction; - -use crate::world_gen::blender::{Blender, NoBlendBlender}; +use weird::{RarityMapper, WierdScaledFunction}; + +use crate::world_gen::{ + blender::{Blender, NoBlendBlender}, + chunk::{MAX_COLUMN_HEIGHT, MIN_HEIGHT}, + implementation::overworld::terrain_params::{ + create_factor_spline, create_jaggedness_spline, create_offset_spline, + }, +}; use super::{ - chunk_sampler::{ChunkNoiseSampler, FlatCacheDensityFunction, InterpolatorDensityFunction}, + chunk_sampler::{ + BlendAlphaDensityFunction, BlendOffsetDensityFunction, Cache2DDensityFunction, + CacheOnceDensityFunction, CellCacheDensityFunctionWrapper, ChunkNoiseSamplerWrapper, + ChunkSamplerDensityFunctionConverter, FlatCacheDensityFunction, InterpolationApplier, + InterpolatorDensityFunctionWrapper, + }, clamped_map, perlin::DoublePerlinNoiseParameters, + BuiltInNoiseParams, }; -mod blend; +pub mod blend; mod end; mod math; pub mod noise; @@ -27,295 +40,285 @@ pub mod spline; mod unary; mod weird; -pub mod built_in_noises { - use std::sync::{Arc, LazyLock}; - - use crate::world_gen::{ - chunk::{MAX_COLUMN_HEIGHT, MIN_HEIGHT}, - implementation::overworld::terrain_params::{ - create_factor_spline, create_jaggedness_spline, create_offset_spline, - }, - noise::builtin_noise_params, - }; - - use super::{ - apply_blending, - blend::{BlendAlphaFunction, BlendOffsetFunction}, - end::EndIslandFunction, - noise::{InternalNoise, InterpolatedNoiseSampler, NoiseFunction, ShiftedNoiseFunction}, - noise_in_range, - offset::{ShiftAFunction, ShiftBFunction}, - spline::SplineFunction, - veritcal_range_choice, - weird::{RarityMapper, WierdScaledFunction}, - ConstantFunction, DensityFunction, RangeFunction, WrapperFunction, WrapperType, - YClampedFunction, - }; - - pub struct SlopedCheeseResult<'a> { - pub(crate) offset: Arc>, - pub(crate) factor: Arc>, - pub(crate) depth: Arc>, - pub(crate) jaggedness: Arc>, - pub(crate) sloped_cheese: Arc>, - } - - type BuiltInNoise = LazyLock>>; - type BuiltInSlopedCheese = LazyLock>; - - pub static BLEND_ALPHA: BuiltInNoise = - LazyLock::new(|| Arc::new(DensityFunction::BlendAlpha(BlendAlphaFunction {}))); - - pub static BLEND_OFFSET: BuiltInNoise = - LazyLock::new(|| Arc::new(DensityFunction::BlendOffset(BlendOffsetFunction {}))); +struct SlopedCheeseResult<'a> { + offset: Arc>, + factor: Arc>, + depth: Arc>, + jaggedness: Arc>, + sloped_cheese: Arc>, +} - pub static ZERO: BuiltInNoise = - LazyLock::new(|| Arc::new(DensityFunction::Constant(ConstantFunction::new(0f64)))); +#[derive(Getters)] +pub struct BuiltInNoiseFunctions<'a> { + zero: Arc>, + ten: Arc>, + blend_alpha: Arc>, + blend_offset: Arc>, + y: Arc>, + shift_x: Arc>, + shift_z: Arc>, + base_3d_noise_overworld: Arc>, + base_3d_noise_nether: Arc>, + base_3d_noise_end: Arc>, + continents_overworld: Arc>, + erosion_overworld: Arc>, + ridges_overworld: Arc>, + ridges_folded_overworld: Arc>, + offset_overworld: Arc>, + factor_overworld: Arc>, + jaggedness_overworld: Arc>, + depth_overworld: Arc>, + sloped_cheese_overworld: Arc>, + continents_overworld_large_biome: Arc>, + erosion_overworld_large_biome: Arc>, + offset_overworld_large_biome: Arc>, + factor_overworld_large_biome: Arc>, + jaggedness_overworld_large_biome: Arc>, + depth_overworld_large_biome: Arc>, + sloped_cheese_overworld_large_biome: Arc>, + offset_overworld_amplified: Arc>, + factor_overworld_amplified: Arc>, + jaggedness_overworld_amplified: Arc>, + depth_overworld_amplified: Arc>, + sloped_cheese_overworld_amplified: Arc>, + sloped_cheese_end: Arc>, + caves_spaghetti_roughness_function_overworld: Arc>, + caves_spaghetti_2d_thickness_modular_overworld: Arc>, + caves_spaghetti_2d_overworld: Arc>, + caves_entrances_overworld: Arc>, + caves_noodle_overworld: Arc>, + caves_pillars_overworld: Arc>, +} - pub static TEN: BuiltInNoise = - LazyLock::new(|| Arc::new(DensityFunction::Constant(ConstantFunction::new(10f64)))); +impl<'a> BuiltInNoiseFunctions<'a> { + pub fn new(built_in_noise_params: &BuiltInNoiseParams<'a>) -> Self { + let blend_alpha = Arc::new(DensityFunction::BlendAlpha(BlendAlphaFunction {})); + let blend_offset = Arc::new(DensityFunction::BlendOffset(BlendOffsetFunction {})); + let zero = Arc::new(DensityFunction::Constant(ConstantFunction::new(0f64))); + let ten = Arc::new(DensityFunction::Constant(ConstantFunction::new(10f64))); - pub static Y: BuiltInNoise = LazyLock::new(|| { - Arc::new({ + let y = Arc::new({ DensityFunction::ClampedY(YClampedFunction { from: MIN_HEIGHT * 2, to: MAX_COLUMN_HEIGHT * 2, from_val: (MIN_HEIGHT * 2) as f64, to_val: (MAX_COLUMN_HEIGHT * 2) as f64, }) - }) - }); + }); - pub static SHIFT_X: BuiltInNoise = LazyLock::new(|| { - Arc::new({ + let shift_x = Arc::new({ DensityFunction::Wrapper(WrapperFunction::new( Arc::new(DensityFunction::Wrapper(WrapperFunction::new( Arc::new(DensityFunction::ShiftA(ShiftAFunction::new(Arc::new( - InternalNoise::new(builtin_noise_params::OFFSET.clone(), None), + InternalNoise::new(built_in_noise_params.offset().clone(), None), )))), WrapperType::Cache2D, ))), WrapperType::CacheFlat, )) - }) - }); + }); - pub static SHIFT_Z: BuiltInNoise = LazyLock::new(|| { - Arc::new({ + let shift_z = Arc::new({ DensityFunction::Wrapper(WrapperFunction::new( Arc::new(DensityFunction::Wrapper(WrapperFunction::new( Arc::new(DensityFunction::ShiftB(ShiftBFunction::new(Arc::new( - InternalNoise::new(builtin_noise_params::OFFSET.clone(), None), + InternalNoise::new(built_in_noise_params.offset().clone(), None), )))), WrapperType::Cache2D, ))), WrapperType::CacheFlat, )) - }) - }); + }); - pub static BASE_3D_NOISE_OVERWORLD: BuiltInNoise = LazyLock::new(|| { - Arc::new({ + let base_3d_noise_overworld = Arc::new({ DensityFunction::InterpolatedNoise( InterpolatedNoiseSampler::create_base_3d_noise_function( 0.25f64, 0.125f64, 80f64, 160f64, 8f64, ), ) - }) - }); + }); - pub static BASE_3D_NOISE_NETHER: BuiltInNoise = LazyLock::new(|| { - Arc::new({ + let base_3d_noise_nether = Arc::new({ DensityFunction::InterpolatedNoise( InterpolatedNoiseSampler::create_base_3d_noise_function( 0.25f64, 0.375f64, 80f64, 60f64, 8f64, ), ) - }) - }); + }); - pub static BASE_3D_NOISE_END: BuiltInNoise = LazyLock::new(|| { - Arc::new({ + let base_3d_noise_end = Arc::new({ DensityFunction::InterpolatedNoise( InterpolatedNoiseSampler::create_base_3d_noise_function( 0.25f64, 0.25f64, 80f64, 160f64, 4f64, ), ) - }) - }); + }); - pub static CONTINENTS_OVERWORLD: BuiltInNoise = LazyLock::new(|| { - Arc::new({ + let continents_overworld = Arc::new({ DensityFunction::Wrapper(WrapperFunction::new( Arc::new(DensityFunction::ShiftedNoise(ShiftedNoiseFunction::new( - SHIFT_X.clone(), - ZERO.clone(), - SHIFT_Z.clone(), + shift_x.clone(), + zero.clone(), + shift_z.clone(), 0.25f64, 0f64, Arc::new(InternalNoise::new( - builtin_noise_params::CONTINENTALNESS.clone(), + built_in_noise_params.continentalness().clone(), None, )), ))), WrapperType::CacheFlat, )) - }) - }); + }); - pub static EROSION_OVERWORLD: BuiltInNoise = LazyLock::new(|| { - Arc::new({ + let erosion_overworld = Arc::new({ DensityFunction::Wrapper(WrapperFunction::new( Arc::new(DensityFunction::ShiftedNoise(ShiftedNoiseFunction::new( - SHIFT_X.clone(), - ZERO.clone(), - SHIFT_Z.clone(), + shift_x.clone(), + zero.clone(), + shift_z.clone(), 0.25f64, 0f64, Arc::new(InternalNoise::new( - builtin_noise_params::EROSION.clone(), + built_in_noise_params.erosion().clone(), None, )), ))), WrapperType::CacheFlat, )) - }) - }); + }); - pub static RIDGES_OVERWORLD: BuiltInNoise = LazyLock::new(|| { - Arc::new({ + let ridges_overworld = Arc::new({ DensityFunction::Wrapper(WrapperFunction::new( Arc::new(DensityFunction::ShiftedNoise(ShiftedNoiseFunction::new( - SHIFT_X.clone(), - ZERO.clone(), - SHIFT_Z.clone(), + shift_x.clone(), + zero.clone(), + shift_z.clone(), 0.25f64, 0f64, Arc::new(InternalNoise::new( - builtin_noise_params::RIDGE.clone(), + built_in_noise_params.ridge().clone(), None, )), ))), WrapperType::CacheFlat, )) - }) - }); + }); - pub static RIDGES_FOLDED_OVERWORLD: BuiltInNoise = LazyLock::new(|| { - Arc::new({ - RIDGES_OVERWORLD + let ridges_folded_overworld = Arc::new({ + ridges_overworld .abs() .add_const(-0.6666666666666666f64) .abs() .add_const(-0.3333333333333333f64) .mul_const(-3f64) - }) - }); + }); - pub static OVERWORLD_SLOPED_CHEESE: BuiltInSlopedCheese = LazyLock::new(|| { - sloped_cheese_function( + let overworld_sloped_cheese_result = sloped_cheese_function( Arc::new(DensityFunction::Noise(NoiseFunction::new( Arc::new(InternalNoise::new( - builtin_noise_params::JAGGED.clone(), + built_in_noise_params.jagged().clone(), None, )), 1500f64, 0f64, ))), - CONTINENTS_OVERWORLD.clone(), - EROSION_OVERWORLD.clone(), - RIDGES_OVERWORLD.clone(), - RIDGES_FOLDED_OVERWORLD.clone(), + continents_overworld.clone(), + erosion_overworld.clone(), + ridges_overworld.clone(), + ridges_folded_overworld.clone(), + blend_offset.clone(), + ten.clone(), + zero.clone(), + base_3d_noise_overworld.clone(), false, - ) - }); + ); - pub static CONTINENTS_OVERWORLD_LARGE_BIOME: BuiltInNoise = LazyLock::new(|| { - Arc::new({ + let continents_overworld_large_biome = Arc::new({ DensityFunction::Wrapper(WrapperFunction::new( Arc::new(DensityFunction::ShiftedNoise(ShiftedNoiseFunction::new( - SHIFT_X.clone(), - ZERO.clone(), - SHIFT_Z.clone(), + shift_x.clone(), + zero.clone(), + shift_z.clone(), 0.25f64, 0f64, Arc::new(InternalNoise::new( - builtin_noise_params::CONTINENTALNESS_LARGE.clone(), + built_in_noise_params.continentalness_large().clone(), None, )), ))), WrapperType::CacheFlat, )) - }) - }); + }); - pub static EROSION_OVERWORLD_LARGE_BIOME: BuiltInNoise = LazyLock::new(|| { - Arc::new({ + let erosion_overworld_large_biome = Arc::new({ DensityFunction::Wrapper(WrapperFunction::new( Arc::new(DensityFunction::ShiftedNoise(ShiftedNoiseFunction::new( - SHIFT_X.clone(), - ZERO.clone(), - SHIFT_Z.clone(), + shift_x.clone(), + zero.clone(), + shift_z.clone(), 0.25f64, 0f64, Arc::new(InternalNoise::new( - builtin_noise_params::EROSION_LARGE.clone(), + built_in_noise_params.erosion_large().clone(), None, )), ))), WrapperType::CacheFlat, )) - }) - }); + }); - pub static OVERWORLD_LARGE_SLOPED_CHEESE: BuiltInSlopedCheese = LazyLock::new(|| { - sloped_cheese_function( + let overworld_large_biome_sloped_cheese_result = sloped_cheese_function( Arc::new(DensityFunction::Noise(NoiseFunction::new( Arc::new(InternalNoise::new( - builtin_noise_params::JAGGED.clone(), + built_in_noise_params.jagged().clone(), None, )), 1500f64, 0f64, ))), - CONTINENTS_OVERWORLD_LARGE_BIOME.clone(), - EROSION_OVERWORLD_LARGE_BIOME.clone(), - RIDGES_OVERWORLD.clone(), - RIDGES_FOLDED_OVERWORLD.clone(), + continents_overworld_large_biome.clone(), + erosion_overworld_large_biome.clone(), + ridges_overworld.clone(), + ridges_folded_overworld.clone(), + blend_offset.clone(), + ten.clone(), + zero.clone(), + base_3d_noise_overworld.clone(), false, - ) - }); + ); - pub static OVERWORLD_AMPLIFIED_SLOPED_CHEESE: BuiltInSlopedCheese = LazyLock::new(|| { - sloped_cheese_function( + let overworld_amplified_sloped_cheese_result = sloped_cheese_function( Arc::new(DensityFunction::Noise(NoiseFunction::new( Arc::new(InternalNoise::new( - builtin_noise_params::JAGGED.clone(), + built_in_noise_params.jagged().clone(), None, )), 1500f64, 0f64, ))), - CONTINENTS_OVERWORLD.clone(), - EROSION_OVERWORLD.clone(), - RIDGES_OVERWORLD.clone(), - RIDGES_FOLDED_OVERWORLD.clone(), + continents_overworld.clone(), + erosion_overworld.clone(), + ridges_overworld.clone(), + ridges_folded_overworld.clone(), + blend_offset.clone(), + ten.clone(), + zero.clone(), + base_3d_noise_overworld.clone(), true, - ) - }); + ); - pub static SLOPED_CHEESE_END: BuiltInNoise = LazyLock::new(|| { - Arc::new({ - DensityFunction::EndIsland(EndIslandFunction::new(0)).add(BASE_3D_NOISE_END.clone()) - }) - }); + let sloped_cheese_end = Arc::new({ + DensityFunction::EndIsland(EndIslandFunction::new(0)).add(base_3d_noise_end.clone()) + }); - pub static CAVES_SPAGHETTI_ROUGHNESS_FUNCTION_OVERWORLD: BuiltInNoise = LazyLock::new(|| { - Arc::new({ + let caves_spaghetti_roughness_function_overworld = Arc::new({ DensityFunction::Wrapper(WrapperFunction::new( Arc::new( noise_in_range( - builtin_noise_params::SPAGHETTI_ROUGHNESS_MODULATOR.clone(), + built_in_noise_params + .spaghetti_roughness_modulator() + .clone(), 1f64, 1f64, 0f64, @@ -324,7 +327,7 @@ pub mod built_in_noises { .mul(Arc::new( DensityFunction::Noise(NoiseFunction::new( Arc::new(InternalNoise::new( - builtin_noise_params::SPAGHETTI_ROUGHNESS.clone(), + built_in_noise_params.spaghetti_roughness().clone(), None, )), 1f64, @@ -336,14 +339,12 @@ pub mod built_in_noises { ), WrapperType::CacheOnce, )) - }) - }); + }); - pub static CAVES_SPAGHETTI_2D_THICKNESS_MODULAR_OVERWORLD: BuiltInNoise = LazyLock::new(|| { - Arc::new({ + let caves_spaghetti_2d_thickness_modular_overworld = Arc::new({ DensityFunction::Wrapper(WrapperFunction::new( Arc::new(noise_in_range( - builtin_noise_params::SPAGHETTI_2D_THICKNESS.clone(), + built_in_noise_params.spaghetti_2d_thickness().clone(), 2f64, 1f64, -0.6f64, @@ -351,14 +352,12 @@ pub mod built_in_noises { )), WrapperType::CacheOnce, )) - }) - }); + }); - pub static CAVES_SPAGHETTI_2D_OVERWORLD: BuiltInNoise = LazyLock::new(|| { - Arc::new({ + let caves_spaghetti_2d_overworld = Arc::new({ let function1 = DensityFunction::Noise(NoiseFunction::new( Arc::new(InternalNoise::new( - builtin_noise_params::SPAGHETTI_2D_MODULATOR.clone(), + built_in_noise_params.spaghetti_2d_modulator().clone(), None, )), 2f64, @@ -368,21 +367,21 @@ pub mod built_in_noises { let function2 = DensityFunction::Wierd(WierdScaledFunction::new( Arc::new(function1), Arc::new(InternalNoise::new( - builtin_noise_params::SPAGHETTI_2D.clone(), + built_in_noise_params.spaghetti_2d().clone(), None, )), RarityMapper::Caves, )); let function3 = noise_in_range( - builtin_noise_params::SPAGHETTI_2D_ELEVATION.clone(), + built_in_noise_params.spaghetti_2d_elevation().clone(), 1f64, 0f64, ((-64i32) / 8i32) as f64, 8f64, ); - let function4 = CAVES_SPAGHETTI_2D_THICKNESS_MODULAR_OVERWORLD.clone(); + let function4 = caves_spaghetti_2d_thickness_modular_overworld.clone(); let function5 = function3.add(Arc::new( DensityFunction::ClampedY(YClampedFunction { @@ -399,14 +398,12 @@ pub mod built_in_noises { let function7 = function2.add(Arc::new(function4.mul_const(0.083f64))); function7.binary_max(function6).clamp(-1f64, 1f64) - }) - }); + }); - pub static CAVES_ENTRANCES_OVERWORLD: BuiltInNoise = LazyLock::new(|| { - Arc::new({ + let caves_entrances_overworld = Arc::new({ let function = DensityFunction::Noise(NoiseFunction::new( Arc::new(InternalNoise::new( - builtin_noise_params::SPAGHETTI_3D_RARITY.clone(), + built_in_noise_params.spaghetti_3d_rarity().clone(), None, )), 2f64, @@ -414,7 +411,7 @@ pub mod built_in_noises { )); let function2 = Arc::new(noise_in_range( - builtin_noise_params::SPAGHETTI_3D_THICKNESS.clone(), + built_in_noise_params.spaghetti_3d_thickness().clone(), 1f64, 1f64, -0.065f64, @@ -424,7 +421,7 @@ pub mod built_in_noises { let function3 = DensityFunction::Wierd(WierdScaledFunction::new( Arc::new(function.clone()), Arc::new(InternalNoise::new( - builtin_noise_params::SPAGHETTI_3D_1.clone(), + built_in_noise_params.spaghetti_3d_1().clone(), None, )), RarityMapper::Tunnels, @@ -433,7 +430,7 @@ pub mod built_in_noises { let function4 = Arc::new(DensityFunction::Wierd(WierdScaledFunction::new( Arc::new(function), Arc::new(InternalNoise::new( - builtin_noise_params::SPAGHETTI_3D_2.clone(), + built_in_noise_params.spaghetti_3d_2().clone(), None, )), RarityMapper::Tunnels, @@ -446,11 +443,11 @@ pub mod built_in_noises { .clamp(-1f64, 1f64), ); - let function6 = CAVES_SPAGHETTI_ROUGHNESS_FUNCTION_OVERWORLD.clone(); + let function6 = caves_spaghetti_roughness_function_overworld.clone(); let function7 = DensityFunction::Noise(NoiseFunction::new( Arc::new(InternalNoise::new( - builtin_noise_params::CAVE_ENTRANCE.clone(), + built_in_noise_params.cave_entrance().clone(), None, )), 0.75f64, @@ -470,18 +467,16 @@ pub mod built_in_noises { Arc::new(function8.binary_min(Arc::new(function6.add(function5)))), WrapperType::CacheOnce, )) - }) - }); + }); - pub static CAVES_NOODLE_OVERWORLD: BuiltInNoise = LazyLock::new(|| { - Arc::new({ - let function = Y.clone(); + let caves_noodle_overworld = Arc::new({ + let function = y.clone(); let function2 = veritcal_range_choice( function.clone(), Arc::new(DensityFunction::Noise(NoiseFunction::new( Arc::new(InternalNoise::new( - builtin_noise_params::NOODLE.clone(), + built_in_noise_params.noodle().clone(), None, )), 1f64, @@ -495,7 +490,7 @@ pub mod built_in_noises { let function3 = veritcal_range_choice( function.clone(), Arc::new(noise_in_range( - builtin_noise_params::NOODLE_THICKNESS.clone(), + built_in_noise_params.noodle_thickness().clone(), 1f64, 1f64, -0.05f64, @@ -510,7 +505,7 @@ pub mod built_in_noises { function.clone(), Arc::new(DensityFunction::Noise(NoiseFunction::new( Arc::new(InternalNoise::new( - builtin_noise_params::NOODLE_RIDGE_A.clone(), + built_in_noise_params.noodle_ridge_a().clone(), None, )), 2.6666666666666665f64, @@ -525,7 +520,7 @@ pub mod built_in_noises { function.clone(), Arc::new(DensityFunction::Noise(NoiseFunction::new( Arc::new(InternalNoise::new( - builtin_noise_params::NOODLE_RIDGE_B.clone(), + built_in_noise_params.noodle_ridge_b().clone(), None, )), 2.6666666666666665f64, @@ -550,14 +545,12 @@ pub mod built_in_noises { in_range: Arc::new(DensityFunction::Constant(ConstantFunction::new(64f64))), out_range: Arc::new(function3.add(function6)), }) - }) - }); + }); - pub static CAVES_PILLARS_OVERWORLD: BuiltInNoise = LazyLock::new(|| { - Arc::new({ + let caves_pillars_overworld = Arc::new({ let function = DensityFunction::Noise(NoiseFunction::new( Arc::new(InternalNoise::new( - builtin_noise_params::PILLAR.clone(), + built_in_noise_params.pillar().clone(), None, )), 25f64, @@ -565,7 +558,7 @@ pub mod built_in_noises { )); let function2 = Arc::new(noise_in_range( - builtin_noise_params::PILLAR_RARENESS.clone(), + built_in_noise_params.pillar_rareness().clone(), 1f64, 1f64, 0f64, @@ -573,7 +566,7 @@ pub mod built_in_noises { )); let function3 = noise_in_range( - builtin_noise_params::PILLAR_THICKNESS.clone(), + built_in_noise_params.pillar_thickness().clone(), 1f64, 1f64, 0f64, @@ -586,77 +579,124 @@ pub mod built_in_noises { Arc::new(function4.mul(Arc::new(function3.cube()))), WrapperType::CacheOnce, )) - }) - }); - - fn sloped_cheese_function<'a>( - jagged_noise: Arc>, - continents: Arc>, - erosion: Arc>, - ridges: Arc>, - ridges_folded: Arc>, - amplified: bool, - ) -> SlopedCheeseResult<'a> { - let offset = Arc::new(apply_blending( - Arc::new( - DensityFunction::Spline(SplineFunction::new(Arc::new(create_offset_spline( - continents.clone(), - erosion.clone(), - ridges.clone(), - amplified, - )))) - .add_const(-0.50375f32 as f64), - ), - BLEND_OFFSET.clone(), - )); - - let factor = Arc::new(apply_blending( - Arc::new(DensityFunction::Spline(SplineFunction::new(Arc::new( - create_factor_spline( - continents.clone(), - erosion.clone(), - ridges.clone(), - ridges_folded.clone(), - amplified, - ), - )))), - TEN.clone(), - )); - - let depth = Arc::new( - DensityFunction::ClampedY(YClampedFunction { - from: -64, - to: 320, - from_val: 1.564, - to_val: -1.5f64, - }) - .add(offset.clone()), - ); + }); - let jaggedness = Arc::new(apply_blending( - Arc::new(DensityFunction::Spline(SplineFunction::new(Arc::new( - create_jaggedness_spline(continents, erosion, ridges, ridges_folded, amplified), - )))), - ZERO.clone(), - )); - - let density1 = Arc::new(jaggedness.mul(Arc::new(jagged_noise.half_negative()))); - let density2 = DensityFunction::Constant(ConstantFunction::new(4f64)).mul(Arc::new( - depth.add(density1).mul(factor.clone()).quarter_negative(), - )); - - let sloped_cheese = Arc::new(density2.add(BASE_3D_NOISE_OVERWORLD.clone())); - - SlopedCheeseResult { - offset, - factor, - depth, - jaggedness, - sloped_cheese, + Self { + zero, + ten, + blend_offset, + blend_alpha, + y, + shift_x, + shift_z, + base_3d_noise_overworld, + base_3d_noise_nether, + base_3d_noise_end, + continents_overworld, + erosion_overworld, + ridges_overworld, + ridges_folded_overworld, + offset_overworld: overworld_sloped_cheese_result.offset, + factor_overworld: overworld_sloped_cheese_result.factor, + jaggedness_overworld: overworld_sloped_cheese_result.jaggedness, + depth_overworld: overworld_sloped_cheese_result.depth, + sloped_cheese_overworld: overworld_sloped_cheese_result.sloped_cheese, + continents_overworld_large_biome, + erosion_overworld_large_biome, + offset_overworld_large_biome: overworld_large_biome_sloped_cheese_result.offset, + factor_overworld_large_biome: overworld_large_biome_sloped_cheese_result.factor, + jaggedness_overworld_large_biome: overworld_large_biome_sloped_cheese_result.jaggedness, + depth_overworld_large_biome: overworld_large_biome_sloped_cheese_result.depth, + sloped_cheese_overworld_large_biome: overworld_large_biome_sloped_cheese_result + .sloped_cheese, + offset_overworld_amplified: overworld_amplified_sloped_cheese_result.offset, + factor_overworld_amplified: overworld_amplified_sloped_cheese_result.factor, + jaggedness_overworld_amplified: overworld_amplified_sloped_cheese_result.jaggedness, + depth_overworld_amplified: overworld_amplified_sloped_cheese_result.depth, + sloped_cheese_overworld_amplified: overworld_amplified_sloped_cheese_result + .sloped_cheese, + sloped_cheese_end, + caves_spaghetti_roughness_function_overworld, + caves_spaghetti_2d_thickness_modular_overworld, + caves_spaghetti_2d_overworld, + caves_entrances_overworld, + caves_noodle_overworld, + caves_pillars_overworld, } } } +fn sloped_cheese_function<'a>( + jagged_noise: Arc>, + continents: Arc>, + erosion: Arc>, + ridges: Arc>, + ridges_folded: Arc>, + blend_offset: Arc>, + ten: Arc>, + zero: Arc>, + base_3d_noise_overworld: Arc>, + amplified: bool, +) -> SlopedCheeseResult<'a> { + let offset = Arc::new(apply_blending( + Arc::new( + DensityFunction::Spline(SplineFunction::new(Arc::new(create_offset_spline( + continents.clone(), + erosion.clone(), + ridges.clone(), + amplified, + )))) + .add_const(-0.50375f32 as f64), + ), + blend_offset, + )); + + let factor = Arc::new(apply_blending( + Arc::new(DensityFunction::Spline(SplineFunction::new(Arc::new( + create_factor_spline( + continents.clone(), + erosion.clone(), + ridges.clone(), + ridges_folded.clone(), + amplified, + ), + )))), + ten, + )); + + let depth = Arc::new( + DensityFunction::ClampedY(YClampedFunction { + from: -64, + to: 320, + from_val: 1.564, + to_val: -1.5f64, + }) + .add(offset.clone()), + ); + + let jaggedness = Arc::new(apply_blending( + Arc::new(DensityFunction::Spline(SplineFunction::new(Arc::new( + create_jaggedness_spline(continents, erosion, ridges, ridges_folded, amplified), + )))), + zero, + )); + + let density1 = Arc::new(jaggedness.mul(Arc::new(jagged_noise.half_negative()))); + let density2 = DensityFunction::Constant(ConstantFunction::new(4f64)).mul(Arc::new( + depth.add(density1).mul(factor.clone()).quarter_negative(), + )); + + let sloped_cheese = Arc::new(density2.add(base_3d_noise_overworld)); + + SlopedCheeseResult { + offset, + factor, + depth, + jaggedness, + sloped_cheese, + } +} + pub fn peaks_valleys_noise(variance: f32) -> f32 { -((variance.abs() - 0.6666667f32).abs() - 0.33333334f32) * 3f32 } @@ -694,7 +734,12 @@ fn apply_blending<'a>( function: Arc>, blend: Arc>, ) -> DensityFunction<'a> { - let function = lerp_density(built_in_noises::BLEND_ALPHA.clone(), blend, function); + //let function = lerp_density(built_in_noises::BLEND_ALPHA.clone(), blend, function); + let function = lerp_density( + Arc::new(DensityFunction::BlendAlpha(BlendAlphaFunction {})), + blend, + function, + ); DensityFunction::Wrapper(WrapperFunction::new( Arc::new(DensityFunction::Wrapper(WrapperFunction::new( @@ -754,8 +799,14 @@ pub enum DensityFunction<'a> { Wierd(WierdScaledFunction<'a>), Range(RangeFunction<'a>), Wrapper(WrapperFunction<'a>), - FlatCache(FlatCacheDensityFunction<'a>), - Interpolator(InterpolatorDensityFunction<'a>), + ChunkCacheFlatCache(FlatCacheDensityFunction<'a>), + ChunkCacheInterpolator(InterpolatorDensityFunctionWrapper<'a>), + ChunkCacheBlendAlpha(BlendAlphaDensityFunction<'a>), + ChunkCacheBlendOffset(BlendOffsetDensityFunction<'a>), + ChunkCacheCellCache(CellCacheDensityFunctionWrapper<'a>), + ChunkCache2DCache(Cache2DDensityFunction<'a>), + ChunkCacheOnceCache(CacheOnceDensityFunction<'a>), + Beardifyer(BeardifyerFunction), } impl<'a> DensityFunction<'a> { @@ -837,7 +888,7 @@ impl<'a> DensityFunction<'a> { #[enum_dispatch(NoisePosImpl)] pub enum NoisePos<'a> { Unblended(UnblendedNoisePos), - ChunkNoise(ChunkNoiseSampler<'a>), + ChunkNoise(ChunkNoiseSamplerWrapper<'a>), } pub struct UnblendedNoisePos { @@ -873,31 +924,33 @@ pub trait NoisePosImpl { fn z(&self) -> i32; fn get_blender(&self) -> Blender { - Blender::NoBlendBlender(NoBlendBlender {}) + Blender::None(NoBlendBlender {}) } } #[enum_dispatch(ApplierImpl)] pub enum Applier<'a> { - ChunkNoise(ChunkNoiseSampler<'a>), + ChunkNoise(ChunkNoiseSamplerWrapper<'a>), + Interpolation(InterpolationApplier<'a>), } #[enum_dispatch] pub trait ApplierImpl<'a> { - fn at(&self, index: i32) -> NoisePos; + fn at(&self, index: usize) -> NoisePos<'a>; - fn fill(&self, densities: &[f64], function: &DensityFunction<'a>) -> Vec; + fn fill(&self, densities: &mut [f64], function: &DensityFunction<'a>); } #[enum_dispatch(VisitorImpl)] -pub enum Visitor { +pub enum Visitor<'a> { Unwrap(UnwrapVisitor), + ChunkSampler(ChunkSamplerDensityFunctionConverter<'a>), } pub struct UnwrapVisitor {} -impl VisitorImpl for UnwrapVisitor { - fn apply<'a>(&self, function: Arc>) -> Arc> { +impl<'a> VisitorImpl<'a> for UnwrapVisitor { + fn apply(&self, function: Arc>) -> Arc> { match function.deref() { DensityFunction::Wrapper(wrapper) => wrapper.wrapped(), _ => function.clone(), @@ -906,10 +959,10 @@ impl VisitorImpl for UnwrapVisitor { } #[enum_dispatch] -pub trait VisitorImpl { - fn apply<'a>(&self, function: Arc>) -> Arc>; +pub trait VisitorImpl<'a> { + fn apply(&self, function: Arc>) -> Arc>; - fn apply_internal_noise<'a>(&self, function: Arc>) -> Arc> { + fn apply_internal_noise<'b>(&self, function: Arc>) -> Arc> { function.clone() } } @@ -918,9 +971,9 @@ pub trait VisitorImpl { pub trait DensityFunctionImpl<'a> { fn sample(&self, pos: &NoisePos) -> f64; - fn fill(&self, densities: &[f64], applier: &Applier) -> Vec; + fn fill(&self, densities: &mut [f64], applier: &Applier<'a>); - fn apply(&'a self, visitor: &'a Visitor) -> Arc>; + fn apply(&self, visitor: &Visitor<'a>) -> Arc>; fn min(&self) -> f64; @@ -943,11 +996,11 @@ impl<'a> DensityFunctionImpl<'a> for ConstantFunction { self.value } - fn fill(&self, densities: &[f64], _applier: &Applier) -> Vec { - densities.iter().map(|_| self.value).collect() + fn fill(&self, densities: &mut [f64], _applier: &Applier) { + densities.fill(self.value) } - fn apply(&'a self, visitor: &'a Visitor) -> Arc> { + fn apply(&self, visitor: &Visitor<'a>) -> Arc> { visitor.apply(Arc::new(DensityFunction::Constant(self.clone()))) } @@ -966,6 +1019,7 @@ pub enum WrapperType { CacheFlat, CacheOnce, Interpolated, + CacheCell, } #[derive(Clone)] @@ -982,6 +1036,10 @@ impl<'a> WrapperFunction<'a> { pub fn wrapped(&self) -> Arc> { self.input.clone() } + + pub fn wrapper(&self) -> WrapperType { + self.wrapper.clone() + } } impl<'a> DensityFunctionImpl<'a> for WrapperFunction<'a> { @@ -997,14 +1055,14 @@ impl<'a> DensityFunctionImpl<'a> for WrapperFunction<'a> { self.input.sample(pos) } - fn apply(&'a self, visitor: &'a Visitor) -> Arc> { + fn apply(&self, visitor: &Visitor<'a>) -> Arc> { visitor.apply(Arc::new(DensityFunction::Wrapper(WrapperFunction { input: self.input.apply(visitor), wrapper: self.wrapper.clone(), }))) } - fn fill(&self, densities: &[f64], applier: &Applier) -> Vec { + fn fill(&self, densities: &mut [f64], applier: &Applier<'a>) { self.input.fill(densities, applier) } } @@ -1046,22 +1104,18 @@ impl<'a> DensityFunctionImpl<'a> for RangeFunction<'a> { } } - fn fill(&self, densities: &[f64], applier: &Applier) -> Vec { - let densities = self.input.fill(densities, applier); - densities - .iter() - .enumerate() - .map(|(i, x)| { - if *x >= self.min && *x < self.max { - self.in_range.sample(&applier.at(i as i32)) - } else { - self.out_range.sample(&applier.at(i as i32)) - } - }) - .collect() + fn fill(&self, densities: &mut [f64], applier: &Applier<'a>) { + self.input.fill(densities, applier); + densities.iter_mut().enumerate().for_each(|(i, val)| { + if *val >= self.min && *val < self.max { + *val = self.in_range.sample(&applier.at(i)); + } else { + *val = self.out_range.sample(&applier.at(i)); + } + }); } - fn apply(&'a self, visitor: &'a Visitor) -> Arc> { + fn apply(&self, visitor: &Visitor<'a>) -> Arc> { visitor.apply(Arc::new(DensityFunction::Range(RangeFunction { input: self.input.apply(visitor), min: self.min, @@ -1080,6 +1134,31 @@ impl<'a> DensityFunctionImpl<'a> for RangeFunction<'a> { } } +#[derive(Clone)] +pub struct BeardifyerFunction {} + +impl<'a> DensityFunctionImpl<'a> for BeardifyerFunction { + fn sample(&self, _pos: &NoisePos) -> f64 { + 0f64 + } + + fn fill(&self, densities: &mut [f64], _applier: &Applier<'a>) { + densities.fill(0f64) + } + + fn min(&self) -> f64 { + 0f64 + } + + fn max(&self) -> f64 { + 0f64 + } + + fn apply(&self, visitor: &Visitor<'a>) -> Arc> { + visitor.apply(Arc::new(DensityFunction::Beardifyer(BeardifyerFunction {}))) + } +} + #[derive(Clone)] pub struct YClampedFunction { from: i32, @@ -1118,11 +1197,11 @@ impl<'a> DensityFunctionImpl<'a> for YClampedFunction { self.from_val.max(self.to_val) } - fn fill(&self, densities: &[f64], applier: &Applier) -> Vec { + fn fill(&self, densities: &mut [f64], applier: &Applier) { applier.fill(densities, &DensityFunction::ClampedY(self.clone())) } - fn apply(&'a self, visitor: &'a Visitor) -> Arc> { + fn apply(&self, visitor: &Visitor<'a>) -> Arc> { visitor.apply(Arc::new(DensityFunction::ClampedY(self.clone()))) } } diff --git a/pumpkin-world/src/world_gen/noise/density/noise.rs b/pumpkin-world/src/world_gen/noise/density/noise.rs index fa258386d..d4406bb2e 100644 --- a/pumpkin-world/src/world_gen/noise/density/noise.rs +++ b/pumpkin-world/src/world_gen/noise/density/noise.rs @@ -69,11 +69,11 @@ impl<'a> DensityFunctionImpl<'a> for NoiseFunction<'a> { ) } - fn fill(&self, densities: &[f64], applier: &Applier) -> Vec { + fn fill(&self, densities: &mut [f64], applier: &Applier<'a>) { applier.fill(densities, &DensityFunction::Noise(self.clone())) } - fn apply(&self, visitor: &'a Visitor) -> Arc> { + fn apply(&self, visitor: &Visitor<'a>) -> Arc> { visitor.apply(Arc::new(DensityFunction::Noise(self.clone()))) } @@ -125,11 +125,11 @@ impl<'a> DensityFunctionImpl<'a> for ShiftedNoiseFunction<'a> { self.noise.sample(d, e, f) } - fn fill(&self, densities: &[f64], applier: &Applier) -> Vec { + fn fill(&self, densities: &mut [f64], applier: &Applier<'a>) { applier.fill(densities, &DensityFunction::ShiftedNoise(self.clone())) } - fn apply(&'a self, visitor: &'a Visitor) -> Arc> { + fn apply(&self, visitor: &Visitor<'a>) -> Arc> { let new_x = self.shift_x.apply(visitor); let new_y = self.shift_y.apply(visitor); let new_z = self.shift_z.apply(visitor); @@ -330,11 +330,11 @@ impl<'a> DensityFunctionImpl<'a> for InterpolatedNoiseSampler { -self.max() } - fn fill(&self, densities: &[f64], applier: &Applier) -> Vec { + fn fill(&self, densities: &mut [f64], applier: &Applier) { applier.fill(densities, &DensityFunction::InterpolatedNoise(self.clone())) } - fn apply(&'a self, visitor: &'a Visitor) -> Arc> { + fn apply(&self, visitor: &Visitor<'a>) -> Arc> { visitor.apply(Arc::new(DensityFunction::InterpolatedNoise(self.clone()))) } } diff --git a/pumpkin-world/src/world_gen/noise/density/offset.rs b/pumpkin-world/src/world_gen/noise/density/offset.rs index 3aa6be286..49be5872f 100644 --- a/pumpkin-world/src/world_gen/noise/density/offset.rs +++ b/pumpkin-world/src/world_gen/noise/density/offset.rs @@ -27,13 +27,13 @@ impl<'a> DensityFunctionImpl<'a> for ShiftAFunction<'a> { self.sample_3d(pos.x() as f64, 0f64, pos.z() as f64) } - fn apply(&'a self, visitor: &'a Visitor) -> Arc> { + fn apply(&self, visitor: &Visitor<'a>) -> Arc> { visitor.apply(Arc::new(DensityFunction::ShiftA(ShiftAFunction { offset: visitor.apply_internal_noise(self.offset.clone()), }))) } - fn fill(&self, densities: &[f64], applier: &Applier) -> Vec { + fn fill(&self, densities: &mut [f64], applier: &Applier<'a>) { applier.fill(densities, &DensityFunction::ShiftA(self.clone())) } @@ -68,13 +68,13 @@ impl<'a> DensityFunctionImpl<'a> for ShiftBFunction<'a> { self.sample_3d(pos.z() as f64, pos.x() as f64, 0f64) } - fn apply(&'a self, visitor: &'a Visitor) -> Arc> { + fn apply(&self, visitor: &Visitor<'a>) -> Arc> { visitor.apply(Arc::new(DensityFunction::ShiftB(ShiftBFunction { offset: visitor.apply_internal_noise(self.offset.clone()), }))) } - fn fill(&self, densities: &[f64], applier: &Applier) -> Vec { + fn fill(&self, densities: &mut [f64], applier: &Applier<'a>) { applier.fill(densities, &DensityFunction::ShiftB(self.clone())) } diff --git a/pumpkin-world/src/world_gen/noise/density/spline.rs b/pumpkin-world/src/world_gen/noise/density/spline.rs index 766e5e3cf..04e543a6a 100644 --- a/pumpkin-world/src/world_gen/noise/density/spline.rs +++ b/pumpkin-world/src/world_gen/noise/density/spline.rs @@ -33,7 +33,7 @@ impl<'a> SplineValue<'a> { } } - fn visit(&'a self, visitor: &'a Visitor) -> SplineValue<'a> { + fn visit(&self, visitor: &Visitor<'a>) -> SplineValue<'a> { match self { Self::Fixed(val) => Self::Fixed(*val), Self::Spline(spline) => Self::Spline(spline.visit(visitor)), @@ -171,7 +171,7 @@ impl<'a> Spline<'a> { } } - pub fn visit(&'a self, visitor: &'a Visitor) -> Spline<'a> { + pub fn visit(&self, visitor: &Visitor<'a>) -> Spline<'a> { let new_function = visitor.apply(self.function.clone()); let new_points = self .points @@ -202,11 +202,11 @@ impl<'a> DensityFunctionImpl<'a> for SplineFunction<'a> { self.spline.apply(pos) as f64 } - fn fill(&self, densities: &[f64], applier: &Applier) -> Vec { + fn fill(&self, densities: &mut [f64], applier: &Applier<'a>) { applier.fill(densities, &DensityFunction::Spline(self.clone())) } - fn apply(&'a self, visitor: &'a Visitor) -> Arc> { + fn apply(&self, visitor: &Visitor<'a>) -> Arc> { let new_spline = self.spline.visit(visitor); Arc::new(DensityFunction::Spline(SplineFunction { spline: Arc::new(new_spline), diff --git a/pumpkin-world/src/world_gen/noise/density/unary.rs b/pumpkin-world/src/world_gen/noise/density/unary.rs index eaed5f4bd..143ab1a20 100644 --- a/pumpkin-world/src/world_gen/noise/density/unary.rs +++ b/pumpkin-world/src/world_gen/noise/density/unary.rs @@ -18,7 +18,7 @@ impl<'a> UnaryDensityFunction<'a> for ClampFunction<'a> { } impl<'a> DensityFunctionImpl<'a> for ClampFunction<'a> { - fn apply(&'a self, visitor: &'a Visitor) -> Arc> { + fn apply(&self, visitor: &Visitor<'a>) -> Arc> { Arc::new(DensityFunction::Clamp(ClampFunction { input: self.input.apply(visitor), min: self.min, @@ -30,9 +30,11 @@ impl<'a> DensityFunctionImpl<'a> for ClampFunction<'a> { self.apply_density(self.input.sample(pos)) } - fn fill(&self, densities: &[f64], applier: &Applier) -> Vec { - let densities = self.input.fill(densities, applier); - densities.iter().map(|x| self.apply_density(*x)).collect() + fn fill(&self, densities: &mut [f64], applier: &Applier<'a>) { + self.input.fill(densities, applier); + densities.iter_mut().for_each(|val| { + *val = self.apply_density(*val); + }); } fn min(&self) -> f64 { @@ -121,12 +123,14 @@ impl<'a> DensityFunctionImpl<'a> for UnaryFunction<'a> { self.apply_density(self.input.sample(pos)) } - fn fill(&self, densities: &[f64], applier: &Applier) -> Vec { - let densities = self.input.fill(densities, applier); - densities.iter().map(|x| self.apply_density(*x)).collect() + fn fill(&self, densities: &mut [f64], applier: &Applier<'a>) { + self.input.fill(densities, applier); + densities.iter_mut().for_each(|val| { + *val = self.apply_density(*val); + }); } - fn apply(&'a self, visitor: &'a Visitor) -> Arc> { + fn apply(&self, visitor: &Visitor<'a>) -> Arc> { let raw = Self::create(self.action.clone(), self.input.apply(visitor)); Arc::new(DensityFunction::Unary(raw)) } diff --git a/pumpkin-world/src/world_gen/noise/density/weird.rs b/pumpkin-world/src/world_gen/noise/density/weird.rs index db275f29a..84664474f 100644 --- a/pumpkin-world/src/world_gen/noise/density/weird.rs +++ b/pumpkin-world/src/world_gen/noise/density/weird.rs @@ -89,7 +89,7 @@ impl<'a> DensityFunctionImpl<'a> for WierdScaledFunction<'a> { 0f64 } - fn apply(&'a self, visitor: &'a Visitor) -> Arc> { + fn apply(&self, visitor: &Visitor<'a>) -> Arc> { visitor.apply(Arc::new(DensityFunction::Wierd(WierdScaledFunction { input: self.input.apply(visitor), noise: visitor.apply_internal_noise(self.noise.clone()), @@ -101,12 +101,10 @@ impl<'a> DensityFunctionImpl<'a> for WierdScaledFunction<'a> { self.apply_loc(pos, self.input.sample(pos)) } - fn fill(&self, densities: &[f64], applier: &Applier) -> Vec { - let densities = self.input.fill(densities, applier); - densities - .iter() - .enumerate() - .map(|(i, x)| self.apply_loc(&applier.at(i as i32), *x)) - .collect() + fn fill(&self, densities: &mut [f64], applier: &Applier<'a>) { + self.input.fill(densities, applier); + densities.iter_mut().enumerate().for_each(|(i, val)| { + *val = self.apply_loc(&applier.at(i), *val); + }); } } diff --git a/pumpkin-world/src/world_gen/noise/mod.rs b/pumpkin-world/src/world_gen/noise/mod.rs index e7297adea..bf8d73c9b 100644 --- a/pumpkin-world/src/world_gen/noise/mod.rs +++ b/pumpkin-world/src/world_gen/noise/mod.rs @@ -1,4 +1,7 @@ #![allow(dead_code)] + +use derive_getters::Getters; +use perlin::DoublePerlinNoiseParameters; pub mod chunk_sampler; pub mod config; pub mod density; @@ -6,143 +9,161 @@ pub mod perlin; mod router; mod simplex; -pub mod builtin_noise_params { - use std::sync::LazyLock; - - use super::perlin::DoublePerlinNoiseParameters; +#[derive(Getters)] +pub struct BuiltInNoiseParams<'a> { + temperature: DoublePerlinNoiseParameters<'a>, + vegetation: DoublePerlinNoiseParameters<'a>, + continentalness: DoublePerlinNoiseParameters<'a>, + erosion: DoublePerlinNoiseParameters<'a>, + temperature_large: DoublePerlinNoiseParameters<'a>, + vegetation_large: DoublePerlinNoiseParameters<'a>, + continentalness_large: DoublePerlinNoiseParameters<'a>, + erosion_large: DoublePerlinNoiseParameters<'a>, + ridge: DoublePerlinNoiseParameters<'a>, + offset: DoublePerlinNoiseParameters<'a>, + aquifer_barrier: DoublePerlinNoiseParameters<'a>, + aquifer_fluid_level_floodedness: DoublePerlinNoiseParameters<'a>, + aquifer_lava: DoublePerlinNoiseParameters<'a>, + aquifer_fluid_level_spread: DoublePerlinNoiseParameters<'a>, + pillar: DoublePerlinNoiseParameters<'a>, + pillar_rareness: DoublePerlinNoiseParameters<'a>, + pillar_thickness: DoublePerlinNoiseParameters<'a>, + spaghetti_2d: DoublePerlinNoiseParameters<'a>, + spaghetti_2d_elevation: DoublePerlinNoiseParameters<'a>, + spaghetti_2d_modulator: DoublePerlinNoiseParameters<'a>, + spaghetti_2d_thickness: DoublePerlinNoiseParameters<'a>, + spaghetti_3d_1: DoublePerlinNoiseParameters<'a>, + spaghetti_3d_2: DoublePerlinNoiseParameters<'a>, + spaghetti_3d_rarity: DoublePerlinNoiseParameters<'a>, + spaghetti_3d_thickness: DoublePerlinNoiseParameters<'a>, + spaghetti_roughness: DoublePerlinNoiseParameters<'a>, + spaghetti_roughness_modulator: DoublePerlinNoiseParameters<'a>, + cave_entrance: DoublePerlinNoiseParameters<'a>, + cave_layer: DoublePerlinNoiseParameters<'a>, + cave_cheese: DoublePerlinNoiseParameters<'a>, + ore_veininess: DoublePerlinNoiseParameters<'a>, + ore_vein_a: DoublePerlinNoiseParameters<'a>, + ore_vein_b: DoublePerlinNoiseParameters<'a>, + ore_gap: DoublePerlinNoiseParameters<'a>, + noodle: DoublePerlinNoiseParameters<'a>, + noodle_thickness: DoublePerlinNoiseParameters<'a>, + noodle_ridge_a: DoublePerlinNoiseParameters<'a>, + noodle_ridge_b: DoublePerlinNoiseParameters<'a>, + jagged: DoublePerlinNoiseParameters<'a>, + surface: DoublePerlinNoiseParameters<'a>, + surface_secondary: DoublePerlinNoiseParameters<'a>, + clay_bands_offset: DoublePerlinNoiseParameters<'a>, + badlands_pillar: DoublePerlinNoiseParameters<'a>, + badlands_pillar_roof: DoublePerlinNoiseParameters<'a>, + badlands_surface: DoublePerlinNoiseParameters<'a>, + iceberg_pillar: DoublePerlinNoiseParameters<'a>, + iceberg_pillar_roof: DoublePerlinNoiseParameters<'a>, + iceberg_surface: DoublePerlinNoiseParameters<'a>, + surface_swamp: DoublePerlinNoiseParameters<'a>, + calcite: DoublePerlinNoiseParameters<'a>, + gravel: DoublePerlinNoiseParameters<'a>, + powder_snow: DoublePerlinNoiseParameters<'a>, + packed_ice: DoublePerlinNoiseParameters<'a>, + ice: DoublePerlinNoiseParameters<'a>, + soul_sand_layer: DoublePerlinNoiseParameters<'a>, + gravel_layer: DoublePerlinNoiseParameters<'a>, + patch: DoublePerlinNoiseParameters<'a>, + netherrack: DoublePerlinNoiseParameters<'a>, + nether_wart: DoublePerlinNoiseParameters<'a>, + nether_state_selector: DoublePerlinNoiseParameters<'a>, +} - pub static TEMPERATURE: LazyLock> = LazyLock::new(|| { - DoublePerlinNoiseParameters::new(-10, &[1.5f64, 0f64, 1f64, 0f64, 0f64, 0f64]) - }); - pub static VEGETATION: LazyLock> = LazyLock::new(|| { - DoublePerlinNoiseParameters::new(-8, &[1f64, 1f64, 0f64, 0f64, 0f64, 0f64]) - }); - pub static CONTINENTALNESS: LazyLock> = - LazyLock::new(|| { - DoublePerlinNoiseParameters::new( +impl<'a> BuiltInNoiseParams<'a> { + pub fn new() -> Self { + Self { + temperature: DoublePerlinNoiseParameters::new( + -10, + &[1.5f64, 0f64, 1f64, 0f64, 0f64, 0f64], + ), + vegetation: DoublePerlinNoiseParameters::new(-8, &[1f64, 1f64, 0f64, 0f64, 0f64, 0f64]), + continentalness: DoublePerlinNoiseParameters::new( -9, &[1f64, 1f64, 2f64, 2f64, 2f64, 1f64, 1f64, 1f64, 1f64], - ) - }); - pub static EROSION: LazyLock> = - LazyLock::new(|| DoublePerlinNoiseParameters::new(-9, &[1f64, 1f64, 0f64, 1f64, 1f64])); - pub static TEMPERATURE_LARGE: LazyLock> = - LazyLock::new(|| { - DoublePerlinNoiseParameters::new(-12, &[1.5f64, 0f64, 1f64, 0f64, 0f64, 0f64]) - }); - pub static VEGETATION_LARGE: LazyLock> = - LazyLock::new(|| { - DoublePerlinNoiseParameters::new(-10, &[1f64, 1f64, 0f64, 0f64, 0f64, 0f64]) - }); - pub static CONTINENTALNESS_LARGE: LazyLock> = - LazyLock::new(|| { - DoublePerlinNoiseParameters::new( + ), + + erosion: DoublePerlinNoiseParameters::new(-9, &[1f64, 1f64, 0f64, 1f64, 1f64]), + temperature_large: DoublePerlinNoiseParameters::new( + -12, + &[1.5f64, 0f64, 1f64, 0f64, 0f64, 0f64], + ), + vegetation_large: DoublePerlinNoiseParameters::new( + -10, + &[1f64, 1f64, 0f64, 0f64, 0f64, 0f64], + ), + continentalness_large: DoublePerlinNoiseParameters::new( -11, &[1f64, 1f64, 2f64, 2f64, 2f64, 1f64, 1f64, 1f64, 1f64], - ) - }); - pub static EROSION_LARGE: LazyLock> = - LazyLock::new(|| DoublePerlinNoiseParameters::new(-11, &[1f64, 1f64, 0f64, 1f64, 1f64])); - pub static RIDGE: LazyLock> = LazyLock::new(|| { - DoublePerlinNoiseParameters::new(-7, &[1f64, 2f64, 1f64, 0f64, 0f64, 0f64]) - }); - pub static OFFSET: LazyLock> = - LazyLock::new(|| DoublePerlinNoiseParameters::new(-3, &[1f64; 4])); - pub static AQUIFER_BARRIER: LazyLock> = - LazyLock::new(|| DoublePerlinNoiseParameters::new(-3, &[1f64])); - pub static AQUIFER_BARRIER_FLOODEDNESS: LazyLock> = - LazyLock::new(|| DoublePerlinNoiseParameters::new(-7, &[1f64])); - pub static AQUIFER_LAVA: LazyLock> = - LazyLock::new(|| DoublePerlinNoiseParameters::new(-1, &[1f64])); - pub static AQUIFER_FLUID_LEVEL_SPREAD: LazyLock> = - LazyLock::new(|| DoublePerlinNoiseParameters::new(-5, &[1f64])); - pub static PILLAR: LazyLock> = - LazyLock::new(|| DoublePerlinNoiseParameters::new(-7, &[1f64; 2])); - pub static PILLAR_RARENESS: LazyLock> = - LazyLock::new(|| DoublePerlinNoiseParameters::new(-8, &[1f64])); - pub static PILLAR_THICKNESS: LazyLock> = - LazyLock::new(|| DoublePerlinNoiseParameters::new(-8, &[1f64])); - pub static SPAGHETTI_2D: LazyLock> = - LazyLock::new(|| DoublePerlinNoiseParameters::new(-7, &[1f64])); - pub static SPAGHETTI_2D_ELEVATION: LazyLock> = - LazyLock::new(|| DoublePerlinNoiseParameters::new(-8, &[1f64])); - pub static SPAGHETTI_2D_MODULATOR: LazyLock> = - LazyLock::new(|| DoublePerlinNoiseParameters::new(-11, &[1f64])); - pub static SPAGHETTI_2D_THICKNESS: LazyLock> = - LazyLock::new(|| DoublePerlinNoiseParameters::new(-11, &[1f64])); - pub static SPAGHETTI_3D_1: LazyLock> = - LazyLock::new(|| DoublePerlinNoiseParameters::new(-7, &[1f64])); - pub static SPAGHETTI_3D_2: LazyLock> = - LazyLock::new(|| DoublePerlinNoiseParameters::new(-7, &[1f64])); - pub static SPAGHETTI_3D_RARITY: LazyLock> = - LazyLock::new(|| DoublePerlinNoiseParameters::new(-11, &[1f64])); - pub static SPAGHETTI_3D_THICKNESS: LazyLock> = - LazyLock::new(|| DoublePerlinNoiseParameters::new(-8, &[1f64])); - pub static SPAGHETTI_ROUGHNESS: LazyLock> = - LazyLock::new(|| DoublePerlinNoiseParameters::new(-5, &[1f64])); - pub static SPAGHETTI_ROUGHNESS_MODULATOR: LazyLock> = - LazyLock::new(|| DoublePerlinNoiseParameters::new(-8, &[1f64])); - pub static CAVE_ENTRANCE: LazyLock> = - LazyLock::new(|| DoublePerlinNoiseParameters::new(-7, &[0.4f64, 0.5f64, 1f64])); - pub static CAVE_LAYER: LazyLock> = - LazyLock::new(|| DoublePerlinNoiseParameters::new(-8, &[1f64])); - pub static CAVE_CHEESE: LazyLock> = LazyLock::new(|| { - DoublePerlinNoiseParameters::new( - -8, - &[0.5f64, 1f64, 2f64, 1f64, 2f64, 1f64, 0f64, 2f64, 0f64], - ) - }); - pub static ORE_VEININESS: LazyLock> = - LazyLock::new(|| DoublePerlinNoiseParameters::new(-8, &[1f64])); - pub static ORE_VEIN_A: LazyLock> = - LazyLock::new(|| DoublePerlinNoiseParameters::new(-7, &[1f64])); - pub static ORE_VEIN_B: LazyLock> = - LazyLock::new(|| DoublePerlinNoiseParameters::new(-7, &[1f64])); - pub static ORE_GAP: LazyLock> = - LazyLock::new(|| DoublePerlinNoiseParameters::new(-5, &[1f64])); - pub static NOODLE: LazyLock> = - LazyLock::new(|| DoublePerlinNoiseParameters::new(-8, &[1f64])); - pub static NOODLE_THICKNESS: LazyLock> = - LazyLock::new(|| DoublePerlinNoiseParameters::new(-8, &[1f64])); - pub static NOODLE_RIDGE_A: LazyLock> = - LazyLock::new(|| DoublePerlinNoiseParameters::new(-7, &[1f64])); - pub static NOODLE_RIDGE_B: LazyLock> = - LazyLock::new(|| DoublePerlinNoiseParameters::new(-7, &[1f64])); - pub static JAGGED: LazyLock> = - LazyLock::new(|| DoublePerlinNoiseParameters::new(-16, &[1f64; 16])); - pub static SURFACE: LazyLock> = - LazyLock::new(|| DoublePerlinNoiseParameters::new(-6, &[1f64; 3])); - pub static SURFACE_SECONDARY: LazyLock> = - LazyLock::new(|| DoublePerlinNoiseParameters::new(-6, &[1f64, 1f64, 0f64, 1f64])); - pub static CLAY_BANDS_OFFSET: LazyLock> = - LazyLock::new(|| DoublePerlinNoiseParameters::new(-8, &[1f64])); - pub static BADLANDS_PILLAR: LazyLock> = - LazyLock::new(|| DoublePerlinNoiseParameters::new(-2, &[1f64; 4])); - pub static BADLANDS_PILLAR_ROOF: LazyLock> = - LazyLock::new(|| DoublePerlinNoiseParameters::new(-8, &[1f64])); - pub static BADLANDS_SURFACE: LazyLock> = - LazyLock::new(|| DoublePerlinNoiseParameters::new(-6, &[1f64; 3])); - pub static ICEBERG_PILLAR: LazyLock> = - LazyLock::new(|| DoublePerlinNoiseParameters::new(-6, &[1f64; 4])); - pub static ICEBERG_PILLAR_ROOF: LazyLock> = - LazyLock::new(|| DoublePerlinNoiseParameters::new(-3, &[1f64])); - pub static ICEBERG_SURFACE: LazyLock> = - LazyLock::new(|| DoublePerlinNoiseParameters::new(-6, &[1f64; 3])); - pub static SURFACE_SWAMP: LazyLock> = - LazyLock::new(|| DoublePerlinNoiseParameters::new(-2, &[1f64])); - pub static CALCITE: LazyLock> = - LazyLock::new(|| DoublePerlinNoiseParameters::new(-9, &[1f64; 4])); - pub static GRAVEL: LazyLock> = - LazyLock::new(|| DoublePerlinNoiseParameters::new(-8, &[1f64; 4])); - pub static POWDER_SNOW: LazyLock> = - LazyLock::new(|| DoublePerlinNoiseParameters::new(-6, &[1f64; 4])); - pub static PACKED_ICE: LazyLock> = - LazyLock::new(|| DoublePerlinNoiseParameters::new(-7, &[1f64; 4])); - pub static ICE: LazyLock> = - LazyLock::new(|| DoublePerlinNoiseParameters::new(-4, &[1f64; 4])); - pub static SOUL_SAND_LAYER: LazyLock> = - LazyLock::new(|| { - DoublePerlinNoiseParameters::new( + ), + erosion_large: DoublePerlinNoiseParameters::new(-11, &[1f64, 1f64, 0f64, 1f64, 1f64]), + ridge: DoublePerlinNoiseParameters::new(-7, &[1f64, 2f64, 1f64, 0f64, 0f64, 0f64]), + offset: DoublePerlinNoiseParameters::new(-3, &[1f64; 4]), + aquifer_barrier: DoublePerlinNoiseParameters::new(-3, &[1f64]), + aquifer_fluid_level_floodedness: DoublePerlinNoiseParameters::new(-7, &[1f64]), + aquifer_lava: DoublePerlinNoiseParameters::new(-1, &[1f64]), + aquifer_fluid_level_spread: DoublePerlinNoiseParameters::new(-5, &[1f64]), + pillar: DoublePerlinNoiseParameters::new(-7, &[1f64; 2]), + pillar_rareness: DoublePerlinNoiseParameters::new(-8, &[1f64]), + pillar_thickness: DoublePerlinNoiseParameters::new(-8, &[1f64]), + spaghetti_2d: DoublePerlinNoiseParameters::new(-7, &[1f64]), + spaghetti_2d_elevation: DoublePerlinNoiseParameters::new(-8, &[1f64]), + spaghetti_2d_modulator: DoublePerlinNoiseParameters::new(-11, &[1f64]), + spaghetti_2d_thickness: DoublePerlinNoiseParameters::new(-11, &[1f64]), + spaghetti_3d_1: DoublePerlinNoiseParameters::new(-7, &[1f64]), + spaghetti_3d_2: DoublePerlinNoiseParameters::new(-7, &[1f64]), + spaghetti_3d_rarity: DoublePerlinNoiseParameters::new(-11, &[1f64]), + spaghetti_3d_thickness: DoublePerlinNoiseParameters::new(-8, &[1f64]), + spaghetti_roughness: DoublePerlinNoiseParameters::new(-5, &[1f64]), + spaghetti_roughness_modulator: DoublePerlinNoiseParameters::new(-8, &[1f64]), + cave_entrance: DoublePerlinNoiseParameters::new(-7, &[0.4f64, 0.5f64, 1f64]), + cave_layer: DoublePerlinNoiseParameters::new(-8, &[1f64]), + cave_cheese: DoublePerlinNoiseParameters::new( + -8, + &[0.5f64, 1f64, 2f64, 1f64, 2f64, 1f64, 0f64, 2f64, 0f64], + ), + ore_veininess: DoublePerlinNoiseParameters::new(-8, &[1f64]), + ore_vein_a: DoublePerlinNoiseParameters::new(-7, &[1f64]), + ore_vein_b: DoublePerlinNoiseParameters::new(-7, &[1f64]), + ore_gap: DoublePerlinNoiseParameters::new(-5, &[1f64]), + noodle: DoublePerlinNoiseParameters::new(-8, &[1f64]), + noodle_thickness: DoublePerlinNoiseParameters::new(-8, &[1f64]), + noodle_ridge_a: DoublePerlinNoiseParameters::new(-7, &[1f64]), + noodle_ridge_b: DoublePerlinNoiseParameters::new(-7, &[1f64]), + jagged: DoublePerlinNoiseParameters::new(-16, &[1f64; 16]), + surface: DoublePerlinNoiseParameters::new(-6, &[1f64; 3]), + surface_secondary: DoublePerlinNoiseParameters::new(-6, &[1f64, 1f64, 0f64, 1f64]), + clay_bands_offset: DoublePerlinNoiseParameters::new(-8, &[1f64]), + badlands_pillar: DoublePerlinNoiseParameters::new(-2, &[1f64; 4]), + badlands_pillar_roof: DoublePerlinNoiseParameters::new(-8, &[1f64]), + badlands_surface: DoublePerlinNoiseParameters::new(-6, &[1f64; 3]), + iceberg_pillar: DoublePerlinNoiseParameters::new(-6, &[1f64; 4]), + iceberg_pillar_roof: DoublePerlinNoiseParameters::new(-3, &[1f64]), + iceberg_surface: DoublePerlinNoiseParameters::new(-6, &[1f64; 3]), + surface_swamp: DoublePerlinNoiseParameters::new(-2, &[1f64]), + calcite: DoublePerlinNoiseParameters::new(-9, &[1f64; 4]), + gravel: DoublePerlinNoiseParameters::new(-8, &[1f64; 4]), + powder_snow: DoublePerlinNoiseParameters::new(-6, &[1f64; 4]), + packed_ice: DoublePerlinNoiseParameters::new(-7, &[1f64; 4]), + ice: DoublePerlinNoiseParameters::new(-4, &[1f64; 4]), + soul_sand_layer: DoublePerlinNoiseParameters::new( + -8, + &[ + 1f64, + 1f64, + 1f64, + 1f64, + 0f64, + 0f64, + 0f64, + 0f64, + 0.013333333333333334f64, + ], + ), + gravel_layer: DoublePerlinNoiseParameters::new( -8, &[ 1f64, @@ -155,36 +176,16 @@ pub mod builtin_noise_params { 0f64, 0.013333333333333334f64, ], - ) - }); - pub static GRAVEL_LAYER: LazyLock> = LazyLock::new(|| { - DoublePerlinNoiseParameters::new( - -8, - &[ - 1f64, - 1f64, - 1f64, - 1f64, - 0f64, - 0f64, - 0f64, - 0f64, - 0.013333333333333334f64, - ], - ) - }); - pub static PATCH: LazyLock> = LazyLock::new(|| { - DoublePerlinNoiseParameters::new( - -5, - &[1f64, 0f64, 0f64, 0f64, 0f64, 0.013333333333333334f64], - ) - }); - pub static NETHERRACK: LazyLock> = - LazyLock::new(|| DoublePerlinNoiseParameters::new(-3, &[1f64, 0f64, 0f64, 0.35f64])); - pub static NETHER_WART: LazyLock> = - LazyLock::new(|| DoublePerlinNoiseParameters::new(-3, &[1f64, 0f64, 0f64, 0.9f64])); - pub static NETHER_STATE_SELECTOR: LazyLock> = - LazyLock::new(|| DoublePerlinNoiseParameters::new(-4, &[1f64])); + ), + patch: DoublePerlinNoiseParameters::new( + -5, + &[1f64, 0f64, 0f64, 0f64, 0f64, 0.013333333333333334f64], + ), + netherrack: DoublePerlinNoiseParameters::new(-3, &[1f64, 0f64, 0f64, 0.35f64]), + nether_wart: DoublePerlinNoiseParameters::new(-3, &[1f64, 0f64, 0f64, 0.9f64]), + nether_state_selector: DoublePerlinNoiseParameters::new(-4, &[1f64]), + } + } } pub fn lerp_32(delta: f32, start: f32, end: f32) -> f32 { diff --git a/pumpkin-world/src/world_gen/noise/router.rs b/pumpkin-world/src/world_gen/noise/router.rs index 2893b293c..d3307454f 100644 --- a/pumpkin-world/src/world_gen/noise/router.rs +++ b/pumpkin-world/src/world_gen/noise/router.rs @@ -3,15 +3,17 @@ use std::sync::Arc; use crate::world_gen::sampler::VeinType; use super::{ - builtin_noise_params, density::{ - apply_blend_density, built_in_noises, lerp_density_static_start, + apply_blend_density, lerp_density_static_start, noise::{InternalNoise, NoiseFunction, ShiftedNoiseFunction}, - veritcal_range_choice, ConstantFunction, DensityFunction, DensityFunctionImpl, - RangeFunction, Visitor, WrapperFunction, WrapperType, YClampedFunction, + veritcal_range_choice, BuiltInNoiseFunctions, ConstantFunction, DensityFunction, + DensityFunctionImpl, RangeFunction, Visitor, WrapperFunction, WrapperType, + YClampedFunction, }, + BuiltInNoiseParams, }; +#[derive(Clone)] pub struct NoiseRouter<'a> { barrier: Arc>, fluid_level_floodedness: Arc>, @@ -23,15 +25,15 @@ pub struct NoiseRouter<'a> { erosion: Arc>, depth: Arc>, ridges: Arc>, - internal_density: Arc>, - final_densitiy: Arc>, + pub(crate) internal_density: Arc>, + pub(crate) final_densitiy: Arc>, vein_toggle: Arc>, vein_ridged: Arc>, vein_gap: Arc>, } impl<'a> NoiseRouter<'a> { - pub fn apply(&'a self, visitor: &'a Visitor) -> Self { + pub fn apply(&self, visitor: &Visitor<'a>) -> Self { Self { barrier: self.barrier.apply(visitor), fluid_level_floodedness: self.fluid_level_floodedness.apply(visitor), @@ -51,10 +53,15 @@ impl<'a> NoiseRouter<'a> { } } - pub fn create_surface_noise_router(large_biomes: bool, amplified: bool) -> Self { + pub fn create_surface_noise_router( + noise_params: &'a BuiltInNoiseParams<'a>, + noise_funcs: &'a BuiltInNoiseFunctions<'a>, + large_biomes: bool, + amplified: bool, + ) -> Self { let function = Arc::new(DensityFunction::Noise(NoiseFunction::new( Arc::new(InternalNoise::new( - builtin_noise_params::AQUIFER_BARRIER.clone(), + noise_params.aquifer_barrier().clone(), None, )), 1f64, @@ -63,7 +70,7 @@ impl<'a> NoiseRouter<'a> { let function2 = Arc::new(DensityFunction::Noise(NoiseFunction::new( Arc::new(InternalNoise::new( - builtin_noise_params::AQUIFER_BARRIER_FLOODEDNESS.clone(), + noise_params.aquifer_fluid_level_floodedness().clone(), None, )), 1f64, @@ -72,7 +79,7 @@ impl<'a> NoiseRouter<'a> { let function3 = Arc::new(DensityFunction::Noise(NoiseFunction::new( Arc::new(InternalNoise::new( - builtin_noise_params::AQUIFER_FLUID_LEVEL_SPREAD.clone(), + noise_params.aquifer_fluid_level_spread().clone(), None, )), 1f64, @@ -81,27 +88,27 @@ impl<'a> NoiseRouter<'a> { let function4 = Arc::new(DensityFunction::Noise(NoiseFunction::new( Arc::new(InternalNoise::new( - builtin_noise_params::AQUIFER_LAVA.clone(), + noise_params.aquifer_lava().clone(), None, )), 1f64, 1f64, ))); - let function5 = built_in_noises::SHIFT_X.clone(); - let function6 = built_in_noises::SHIFT_Z.clone(); + let function5 = noise_funcs.shift_x().clone(); + let function6 = noise_funcs.shift_z().clone(); let function7 = Arc::new(DensityFunction::ShiftedNoise(ShiftedNoiseFunction::new( function5.clone(), - built_in_noises::ZERO.clone(), + noise_funcs.zero().clone(), function6.clone(), 0.25f64, 0f64, Arc::new(InternalNoise::new( if large_biomes { - builtin_noise_params::TEMPERATURE_LARGE.clone() + noise_params.temperature_large().clone() } else { - builtin_noise_params::TEMPERATURE.clone() + noise_params.temperature().clone() }, None, )), @@ -109,40 +116,34 @@ impl<'a> NoiseRouter<'a> { let function8 = Arc::new(DensityFunction::ShiftedNoise(ShiftedNoiseFunction::new( function5.clone(), - built_in_noises::ZERO.clone(), + noise_funcs.zero().clone(), function6.clone(), 0.25f64, 0f64, Arc::new(InternalNoise::new( if large_biomes { - builtin_noise_params::VEGETATION_LARGE.clone() + noise_params.vegetation_large().clone() } else { - builtin_noise_params::VEGETATION.clone() + noise_params.vegetation().clone() }, None, )), ))); let function9 = if large_biomes { - built_in_noises::OVERWORLD_LARGE_SLOPED_CHEESE - .factor - .clone() + noise_funcs.factor_overworld_large_biome().clone() } else if amplified { - built_in_noises::OVERWORLD_AMPLIFIED_SLOPED_CHEESE - .factor - .clone() + noise_funcs.factor_overworld_amplified().clone() } else { - built_in_noises::OVERWORLD_SLOPED_CHEESE.factor.clone() + noise_funcs.factor_overworld().clone() }; let function10 = if large_biomes { - built_in_noises::OVERWORLD_LARGE_SLOPED_CHEESE.depth.clone() + noise_funcs.depth_overworld_large_biome().clone() } else if amplified { - built_in_noises::OVERWORLD_AMPLIFIED_SLOPED_CHEESE - .depth - .clone() + noise_funcs.depth_overworld_amplified().clone() } else { - built_in_noises::OVERWORLD_SLOPED_CHEESE.depth.clone() + noise_funcs.depth_overworld().clone() }; let function11 = Arc::new( @@ -157,23 +158,17 @@ impl<'a> NoiseRouter<'a> { ); let function12 = if large_biomes { - built_in_noises::OVERWORLD_LARGE_SLOPED_CHEESE - .sloped_cheese - .clone() + noise_funcs.sloped_cheese_overworld_large_biome().clone() } else if amplified { - built_in_noises::OVERWORLD_AMPLIFIED_SLOPED_CHEESE - .sloped_cheese - .clone() + noise_funcs.sloped_cheese_overworld_amplified().clone() } else { - built_in_noises::OVERWORLD_SLOPED_CHEESE - .sloped_cheese - .clone() + noise_funcs.sloped_cheese_overworld().clone() }; let function13 = Arc::new( function12.binary_min(Arc::new( DensityFunction::Constant(ConstantFunction::new(5f64)) - .mul(built_in_noises::CAVES_ENTRANCES_OVERWORLD.clone()), + .mul(noise_funcs.caves_entrances_overworld().clone()), )), ); @@ -182,14 +177,14 @@ impl<'a> NoiseRouter<'a> { -1000000f64, 1.5625f64, function13, - Arc::new(create_caves(function12)), + Arc::new(create_caves(noise_funcs, noise_params, function12)), ))); let function15 = Arc::new( apply_blend_density(apply_surface_slides(amplified, function14)) - .binary_min(built_in_noises::CAVES_NOODLE_OVERWORLD.clone()), + .binary_min(noise_funcs.caves_noodle_overworld().clone()), ); - let function16 = built_in_noises::Y.clone(); + let function16 = noise_funcs.y().clone(); let i = VeinType::overall_min_y(); let j = VeinType::overall_max_y(); @@ -197,7 +192,7 @@ impl<'a> NoiseRouter<'a> { function16.clone(), Arc::new(DensityFunction::Noise(NoiseFunction::new( Arc::new(InternalNoise::new( - builtin_noise_params::ORE_VEININESS.clone(), + noise_params.ore_veininess().clone(), None, )), 1.5f64, @@ -212,10 +207,7 @@ impl<'a> NoiseRouter<'a> { veritcal_range_choice( function16.clone(), Arc::new(DensityFunction::Noise(NoiseFunction::new( - Arc::new(InternalNoise::new( - builtin_noise_params::ORE_VEIN_A.clone(), - None, - )), + Arc::new(InternalNoise::new(noise_params.ore_vein_a().clone(), None)), 4f64, 4f64, ))), @@ -230,10 +222,7 @@ impl<'a> NoiseRouter<'a> { veritcal_range_choice( function16, Arc::new(DensityFunction::Noise(NoiseFunction::new( - Arc::new(InternalNoise::new( - builtin_noise_params::ORE_VEIN_B.clone(), - None, - )), + Arc::new(InternalNoise::new(noise_params.ore_vein_b().clone(), None)), 4f64, 4f64, ))), @@ -250,10 +239,7 @@ impl<'a> NoiseRouter<'a> { ); let function21 = Arc::new(DensityFunction::Noise(NoiseFunction::new( - Arc::new(InternalNoise::new( - builtin_noise_params::ORE_GAP.clone(), - None, - )), + Arc::new(InternalNoise::new(noise_params.ore_gap().clone(), None)), 1f64, 1f64, ))); @@ -266,17 +252,17 @@ impl<'a> NoiseRouter<'a> { temperature: function7, vegetation: function8, continents: if large_biomes { - built_in_noises::CONTINENTS_OVERWORLD_LARGE_BIOME.clone() + noise_funcs.continents_overworld_large_biome().clone() } else { - built_in_noises::CONTINENTS_OVERWORLD.clone() + noise_funcs.continents_overworld().clone() }, erosion: if large_biomes { - built_in_noises::EROSION_OVERWORLD_LARGE_BIOME.clone() + noise_funcs.erosion_overworld_large_biome().clone() } else { - built_in_noises::CONTINENTS_OVERWORLD.clone() + noise_funcs.erosion_overworld().clone() }, depth: function10, - ridges: built_in_noises::RIDGES_OVERWORLD.clone(), + ridges: noise_funcs.ridges_overworld().clone(), internal_density: Arc::new(apply_surface_slides( amplified, Arc::new(function11.add_const(-0.703125).clamp(-64f64, 64f64)), @@ -331,14 +317,17 @@ fn apply_slides( lerp_density_static_start(function3, bottom_density, function) } -fn create_caves(sloped_cheese: Arc) -> DensityFunction { - let function = built_in_noises::CAVES_SPAGHETTI_2D_OVERWORLD.clone(); - let function2 = built_in_noises::CAVES_SPAGHETTI_ROUGHNESS_FUNCTION_OVERWORLD.clone(); +fn create_caves<'a>( + noise_funcs: &BuiltInNoiseFunctions<'a>, + noise_params: &BuiltInNoiseParams<'a>, + sloped_cheese: Arc>, +) -> DensityFunction<'a> { + let function = noise_funcs.caves_spaghetti_2d_overworld().clone(); + let function2 = noise_funcs + .caves_spaghetti_roughness_function_overworld() + .clone(); let function3 = Arc::new(DensityFunction::Noise(NoiseFunction::new( - Arc::new(InternalNoise::new( - builtin_noise_params::CAVE_LAYER.clone(), - None, - )), + Arc::new(InternalNoise::new(noise_params.cave_layer().clone(), None)), 1f64, 8f64, ))); @@ -346,10 +335,7 @@ fn create_caves(sloped_cheese: Arc) -> DensityFunction { DensityFunction::Constant(ConstantFunction::new(4f64)).mul(Arc::new(function3.square())), ); let function5 = Arc::new(DensityFunction::Noise(NoiseFunction::new( - Arc::new(InternalNoise::new( - builtin_noise_params::CAVE_CHEESE.clone(), - None, - )), + Arc::new(InternalNoise::new(noise_params.cave_cheese().clone(), None)), 1f64, 0.6666666666666666f64, ))); @@ -368,9 +354,9 @@ fn create_caves(sloped_cheese: Arc) -> DensityFunction { ); let function7 = Arc::new(function4.add(function6)); let function8 = function7 - .binary_min(built_in_noises::CAVES_ENTRANCES_OVERWORLD.clone()) + .binary_min(noise_funcs.caves_entrances_overworld().clone()) .binary_min(Arc::new(function.add(function2))); - let function9 = built_in_noises::CAVES_PILLARS_OVERWORLD.clone(); + let function9 = noise_funcs.caves_pillars_overworld().clone(); let function10 = Arc::new(DensityFunction::Range(RangeFunction::new( function9.clone(), -1000000f64, From 0754a128d7d8269a73f4b4518cccf278d5145a33 Mon Sep 17 00:00:00 2001 From: kralverde Date: Thu, 3 Oct 2024 16:29:39 -0400 Subject: [PATCH 07/11] rebase master --- pumpkin-core/src/math/mod.rs | 1 + pumpkin-core/src/math/voxel_shape.rs | 9 + pumpkin-world/src/biome.rs | 24 + pumpkin-world/src/block/block_state.rs | 1 + pumpkin-world/src/lib.rs | 1 - pumpkin-world/src/world_gen/blender/data.rs | 391 ------ pumpkin-world/src/world_gen/blender/mod.rs | 352 +----- pumpkin-world/src/world_gen/chunk.rs | 333 ----- .../{height.rs => world_gen/height_limit.rs} | 3 - pumpkin-world/src/world_gen/heightmap.rs | 1 - .../src/world_gen/implementation/aquifer.rs | 72 -- .../src/world_gen/implementation/mod.rs | 56 - .../world_gen/implementation/overworld/mod.rs | 1 - .../implementation/surface_builder.rs | 0 pumpkin-world/src/world_gen/mod.rs | 10 +- .../src/world_gen/noise/chunk_sampler.rs | 1119 ----------------- pumpkin-world/src/world_gen/noise/config.rs | 16 - .../src/world_gen/noise/density/blend.rs | 2 - .../src/world_gen/noise/density/mod.rs | 249 +++- .../src/world_gen/noise/density/spline.rs | 120 +- .../density/terrain_helpers.rs} | 106 +- pumpkin-world/src/world_gen/noise/mod.rs | 14 +- pumpkin-world/src/world_gen/positions.rs | 28 + pumpkin-world/src/world_gen/proto_chunk.rs | 29 + pumpkin-world/src/world_gen/supplier.rs | 26 - 25 files changed, 477 insertions(+), 2487 deletions(-) create mode 100644 pumpkin-core/src/math/voxel_shape.rs delete mode 100644 pumpkin-world/src/world_gen/blender/data.rs delete mode 100644 pumpkin-world/src/world_gen/chunk.rs rename pumpkin-world/src/{height.rs => world_gen/height_limit.rs} (96%) delete mode 100644 pumpkin-world/src/world_gen/heightmap.rs delete mode 100644 pumpkin-world/src/world_gen/implementation/aquifer.rs delete mode 100644 pumpkin-world/src/world_gen/implementation/surface_builder.rs delete mode 100644 pumpkin-world/src/world_gen/noise/chunk_sampler.rs delete mode 100644 pumpkin-world/src/world_gen/noise/config.rs rename pumpkin-world/src/world_gen/{implementation/overworld/terrain_params.rs => noise/density/terrain_helpers.rs} (84%) create mode 100644 pumpkin-world/src/world_gen/positions.rs create mode 100644 pumpkin-world/src/world_gen/proto_chunk.rs delete mode 100644 pumpkin-world/src/world_gen/supplier.rs diff --git a/pumpkin-core/src/math/mod.rs b/pumpkin-core/src/math/mod.rs index c568268af..29ac634d5 100644 --- a/pumpkin-core/src/math/mod.rs +++ b/pumpkin-core/src/math/mod.rs @@ -2,6 +2,7 @@ pub mod boundingbox; pub mod position; pub mod vector2; pub mod vector3; +pub mod voxel_shape; pub fn wrap_degrees(var: f32) -> f32 { let mut var1 = var % 360.0; diff --git a/pumpkin-core/src/math/voxel_shape.rs b/pumpkin-core/src/math/voxel_shape.rs new file mode 100644 index 000000000..ecf5a88d2 --- /dev/null +++ b/pumpkin-core/src/math/voxel_shape.rs @@ -0,0 +1,9 @@ +pub struct VoxelShape { + // TODO +} + +impl VoxelShape { + pub fn is_empty() -> bool { + unimplemented!() + } +} diff --git a/pumpkin-world/src/biome.rs b/pumpkin-world/src/biome.rs index 6af83f6e0..337a582ce 100644 --- a/pumpkin-world/src/biome.rs +++ b/pumpkin-world/src/biome.rs @@ -1,3 +1,4 @@ +use enum_dispatch::enum_dispatch; use serde::{Deserialize, Serialize}; // TODO make this work with the protocol @@ -9,3 +10,26 @@ pub enum Biome { SnowyTiga, // TODO list all Biomes } + +#[derive(Clone)] +#[enum_dispatch(BiomeSupplierImpl)] +pub enum BiomeSupplier { + Debug(DebugBiomeSupplier), +} + +#[enum_dispatch] +pub trait BiomeSupplierImpl { + fn biome(&self, x: i32, y: i32, z: i32, noise: &MultiNoiseSampler) -> Biome; +} + +#[derive(Clone)] +pub struct DebugBiomeSupplier {} + +impl BiomeSupplierImpl for DebugBiomeSupplier { + fn biome(&self, _x: i32, _y: i32, _z: i32, _noise: &MultiNoiseSampler) -> Biome { + Biome::Plains + } +} + +// TODO: Implement +pub struct MultiNoiseSampler {} diff --git a/pumpkin-world/src/block/block_state.rs b/pumpkin-world/src/block/block_state.rs index df79018c7..8e9a59e5d 100644 --- a/pumpkin-world/src/block/block_state.rs +++ b/pumpkin-world/src/block/block_state.rs @@ -1,3 +1,4 @@ +<<<<<<< HEAD use std::collections::HashMap; use thiserror::Error; diff --git a/pumpkin-world/src/lib.rs b/pumpkin-world/src/lib.rs index dd1fbafe5..dc1e73d1a 100644 --- a/pumpkin-world/src/lib.rs +++ b/pumpkin-world/src/lib.rs @@ -5,7 +5,6 @@ pub mod coordinates; pub mod cylindrical_chunk_iterator; pub mod dimension; pub mod global_registry; -mod height; pub mod item; pub mod level; mod world_gen; diff --git a/pumpkin-world/src/world_gen/blender/data.rs b/pumpkin-world/src/world_gen/blender/data.rs deleted file mode 100644 index d2559eb6f..000000000 --- a/pumpkin-world/src/world_gen/blender/data.rs +++ /dev/null @@ -1,391 +0,0 @@ -use crate::{ - self as pumpkin_world, - biome::Biome, - block::BlockId, - height::{HeightLimitView, HeightLimitViewImpl, StandardHeightLimitView}, - world_gen::{ - chunk::{BlockPos, Chunk, GenerationState, HeightMapType}, - Direction, - }, -}; -use num_traits::PrimInt; -use pumpkin_macros::block_id; - -pub const SURFACE_BLOCKS: [BlockId; 11] = [ - block_id!("minecraft:podzol"), - block_id!("minecraft:gravel"), - block_id!("minecraft:grass_block"), - block_id!("minecraft:stone"), - block_id!("minecraft:coarse_dirt"), - block_id!("minecraft:sand"), - block_id!("minecraft:red_sand"), - block_id!("minecraft:mycelium"), - block_id!("minecraft:snow_block"), - block_id!("minecraft:terracotta"), - block_id!("minecraft:dirt"), -]; - -const BIOMES_PER_CHUNK: usize = 16 >> 2; -const LAST_CHUNK_BIOME_INDEX: usize = BIOMES_PER_CHUNK - 1; -const CHUNK_BIOME_END_INDEX: usize = BIOMES_PER_CHUNK; -const NORTH_WEST_END_INDEX: usize = 2 * LAST_CHUNK_BIOME_INDEX + 1; -const SOUTH_EAST_END_INDEX_PART: usize = 2 * CHUNK_BIOME_END_INDEX + 1; -const HORIZONTAL_BIOME_COUNT: usize = NORTH_WEST_END_INDEX + SOUTH_EAST_END_INDEX_PART; - -pub struct BlendingData { - pub(crate) height_limit: HeightLimitView, - pub(crate) surface_heights: Box<[f64; HORIZONTAL_BIOME_COUNT]>, - pub(crate) biomes: Box<[Option>; HORIZONTAL_BIOME_COUNT]>, - pub(crate) collidable_block_densities: Box<[Option>; HORIZONTAL_BIOME_COUNT]>, - initialized: bool, -} - -impl BlendingData { - pub fn get_blending_data(chunk: &Chunk, _chunk_x: i32, _chunk_z: i32) -> Option { - // TODO: We currently assume all chunks have new noise. valid assumption? - if let Some(mut data) = chunk.blending_data() { - if chunk.status() >= GenerationState::Biome { - data.init_chunk_blending_data( - chunk, - &[ - Direction::North, - Direction::NorthWest, - Direction::West, - Direction::SouthWest, - Direction::South, - Direction::SouthEast, - Direction::East, - Direction::NorthEast, - ], - ); - Some(data) - } else { - None - } - } else { - None - } - } - - #[inline] - fn method_39355(i: usize) -> usize { - i & !(i.unsigned_shr(31)) - } - - pub(crate) fn x(index: usize) -> usize { - if index < NORTH_WEST_END_INDEX { - Self::method_39355(LAST_CHUNK_BIOME_INDEX - index) - } else { - let i = index - NORTH_WEST_END_INDEX; - CHUNK_BIOME_END_INDEX - Self::method_39355(CHUNK_BIOME_END_INDEX - i) - } - } - - pub(crate) fn z(index: usize) -> usize { - if index < NORTH_WEST_END_INDEX { - Self::method_39355(index - LAST_CHUNK_BIOME_INDEX) - } else { - let i = index - NORTH_WEST_END_INDEX; - CHUNK_BIOME_END_INDEX - Self::method_39355(i - CHUNK_BIOME_END_INDEX) - } - } - - pub fn height(&self, biome_x: usize, _biome_y: usize, biome_z: usize) -> f64 { - if biome_x == CHUNK_BIOME_END_INDEX || biome_z == CHUNK_BIOME_END_INDEX { - self.surface_heights[Self::south_east_index(biome_x, biome_z)] - } else if biome_x != 0 && biome_z != 0 { - f64::MAX - } else { - self.surface_heights[Self::north_west_index(biome_x, biome_z)] - } - } - - fn collidable_block_density_from_column( - &self, - column: Option<&[f64]>, - half_section_y: i32, - ) -> f64 { - if let Some(column) = column { - let i = self.half_section_height(half_section_y); - if (i >= 0) && ((i as usize) < column.len()) { - column[i as usize] * 0.1f64 - } else { - f64::MAX - } - } else { - f64::MAX - } - } - - pub fn collidable_block_density( - &self, - biome_x: usize, - half_section_y: i32, - biome_z: usize, - ) -> f64 { - if half_section_y == self.bottom_half_section_y() { - 0.1f64 - } else if biome_x == CHUNK_BIOME_END_INDEX || biome_z == CHUNK_BIOME_END_INDEX { - self.collidable_block_density_from_column( - self.collidable_block_densities[Self::south_east_index(biome_x, biome_z)] - .as_deref(), - half_section_y, - ) - } else if biome_x != 0 && biome_z != 0 { - f64::MAX - } else { - self.collidable_block_density_from_column( - self.collidable_block_densities[Self::north_west_index(biome_x, biome_z)] - .as_deref(), - half_section_y, - ) - } - } - - fn new(bottom_section_y: i32, top_section_y: i32, heights: Option<&[f64]>) -> Self { - let heights = match heights { - Some(heights) => { - let mut owned_heights = [0f64; HORIZONTAL_BIOME_COUNT]; - assert!( - heights.len() == HORIZONTAL_BIOME_COUNT, - "Heights needs to be the right length" - ); - owned_heights - .iter_mut() - .zip(heights) - .for_each(|(new, old)| { - *new = *old; - }); - owned_heights - } - None => [f64::MAX; HORIZONTAL_BIOME_COUNT], - }; - - let collidable_block_densities: [Option>; HORIZONTAL_BIOME_COUNT] = - [const { None }; HORIZONTAL_BIOME_COUNT]; - let biomes: [Option>; HORIZONTAL_BIOME_COUNT] = - [const { None }; HORIZONTAL_BIOME_COUNT]; - - let i = bottom_section_y << 4; - let j = (top_section_y << 4) - i; - let height_limit = HeightLimitView::Standard(StandardHeightLimitView::new(i, j)); - - Self { - height_limit, - surface_heights: Box::new(heights.clone()), - biomes: Box::new(biomes), - collidable_block_densities: Box::new(collidable_block_densities), - initialized: false, - } - } - - pub fn vertical_half_section_count(&self) -> i32 { - self.height_limit.vertical_section_count() * 2 - } - - fn collidable_and_not_tree(chunk: &Chunk, pos: &BlockPos) -> bool { - let state = chunk.get_block_state(pos); - if state.is_air() - || state.has_tag("leaves") - || state.has_tag("logs") - || state.is_block(block_id!("minecraft:brown_mushroom_block")) - || state.is_block(block_id!("minecraft:red_mushroom_block")) - { - false - } else { - state.collision_shape(chunk, pos).is_empty() - } - } - - fn above_collidable_block_value(chunk: &Chunk, pos: &BlockPos) -> (f64, BlockPos) { - let pos = pos.down(); - let val = if Self::collidable_and_not_tree(chunk, &pos) { - 1f64 - } else { - -1f64 - }; - (val, pos) - } - - fn north_west_index(biome_x: usize, biome_z: usize) -> usize { - LAST_CHUNK_BIOME_INDEX + biome_x + biome_z - } - - fn south_east_index(biome_x: usize, biome_z: usize) -> usize { - NORTH_WEST_END_INDEX + biome_x + CHUNK_BIOME_END_INDEX - biome_z - } - - fn init_chunk_blending_data(&mut self, chunk: &Chunk, directions: &[Direction]) { - if !self.initialized { - if directions.contains(&Direction::North) - || directions.contains(&Direction::West) - || directions.contains(&Direction::NorthWest) - { - self.init_block_column(Self::north_west_index(0, 0), chunk, 0, 0); - } - - if directions.contains(&Direction::North) { - for i in 1..BIOMES_PER_CHUNK { - self.init_block_column(Self::north_west_index(i, 0), chunk, (4 * i) as i32, 0); - } - } - - if directions.contains(&Direction::West) { - for i in 1..BIOMES_PER_CHUNK { - self.init_block_column(Self::north_west_index(0, i), chunk, 0, (4 * i) as i32); - } - } - - if directions.contains(&Direction::East) { - for i in 1..BIOMES_PER_CHUNK { - self.init_block_column( - Self::south_east_index(CHUNK_BIOME_END_INDEX, i), - chunk, - 15, - (4 * i) as i32, - ); - } - } - - if directions.contains(&Direction::South) { - for i in 1..BIOMES_PER_CHUNK { - self.init_block_column( - Self::south_east_index(i, CHUNK_BIOME_END_INDEX), - chunk, - (4 * i) as i32, - 15, - ); - } - } - - if directions.contains(&Direction::East) && directions.contains(&Direction::NorthEast) { - self.init_block_column( - Self::south_east_index(CHUNK_BIOME_END_INDEX, 0), - chunk, - 15, - 0, - ); - } - - if directions.contains(&Direction::East) - && directions.contains(&Direction::South) - && directions.contains(&Direction::SouthEast) - { - self.init_block_column( - Self::south_east_index(CHUNK_BIOME_END_INDEX, CHUNK_BIOME_END_INDEX), - chunk, - 15, - 15, - ); - } - - self.initialized = true; - } - } - - fn collidable_block_density_below(chunk: &Chunk, pos: &BlockPos) -> (f64, BlockPos) { - let (val, new_pos) = Self::above_collidable_block_value(chunk, &pos); - let mut d = val; - let mut pos = new_pos; - - for _ in 0..6 { - let (val, new_pos) = Self::above_collidable_block_value(chunk, &pos); - d += val; - pos = new_pos; - } - - (d, pos) - } - - pub fn bottom_half_section_y(&self) -> i32 { - self.height_limit.bottom_section_coord() * 2 - } - - fn half_section_height(&self, section_y: i32) -> i32 { - section_y - (self.bottom_half_section_y() + 1) - } - - fn init_block_column(&mut self, index: usize, chunk: &Chunk, chunk_x: i32, chunk_z: i32) { - if self.surface_heights[index] == f64::MAX { - self.surface_heights[index] = self.surface_block_y(chunk, chunk_x, chunk_z) as f64; - } - self.collidable_block_densities[index] = Some(self.collidable_block_density_column( - chunk, - chunk_x, - chunk_z, - self.surface_heights[index].floor() as i32, - )); - self.biomes[index] = Some(self.vertical_biome_sections(chunk, chunk_x, chunk_z)); - } - - fn vertical_biome_sections(&self, chunk: &Chunk, block_x: i32, block_z: i32) -> Vec { - (0..self.vertical_biome_count()) - .map(|i| { - let j = i + (self.height_limit.bottom_y() >> 2); - chunk.biome_for_noise_gen(block_x >> 2, j, block_z >> 2) - }) - .collect() - } - - fn vertical_biome_count(&self) -> i32 { - self.height_limit.vertical_section_count() << 2 - } - - fn collidable_block_density_column( - &self, - chunk: &Chunk, - chunk_x: i32, - chunk_z: i32, - height: i32, - ) -> Vec { - let mut ds: Vec = (0..self.vertical_half_section_count()) - .map(|_| -1f64) - .collect(); - - let pos = BlockPos::new(chunk_x, self.height_limit.top_y(), chunk_z); - let (mut d, mut pos) = Self::collidable_block_density_below(chunk, &pos); - - for i in (0..=(ds.len() - 2)).rev() { - let (e, local_pos) = Self::above_collidable_block_value(chunk, &pos); - let (f, local_pos) = Self::collidable_block_density_below(chunk, &local_pos); - ds[i] = (d + e + f) / 15f64; - d = f; - pos = local_pos; - } - - let i = self.half_section_height(height / 8); - if i >= 0 && (i as usize) < (ds.len() - 1) { - let e = (height as f64 + 0.5f64) % 8f64 / 8f64; - let f = (1f64 - e) / e; - let g = f.max(1f64) * 0.25f64; - ds[(i + 1) as usize] = -f / g; - ds[i as usize] = 1f64 / g; - } - - ds - } - - fn surface_block_y(&self, chunk: &Chunk, block_x: i32, block_z: i32) -> i32 { - let i = if let Some(value) = - chunk.sample_height_map(HeightMapType::WorldGenSurface, block_x, block_z) - { - value - } else { - self.height_limit.top_y() - }; - - let j = self.height_limit.bottom_y(); - - for height in (j..=i).rev() { - if SURFACE_BLOCKS.contains( - &chunk - .get_block_state(&BlockPos::new(block_x, height, block_z)) - .block(), - ) { - return height; - } - } - - j - } -} diff --git a/pumpkin-world/src/world_gen/blender/mod.rs b/pumpkin-world/src/world_gen/blender/mod.rs index b32efe658..eb1e0ec43 100644 --- a/pumpkin-world/src/world_gen/blender/mod.rs +++ b/pumpkin-world/src/world_gen/blender/mod.rs @@ -1,351 +1,11 @@ -use std::{ - collections::HashMap, - sync::{Arc, LazyLock}, -}; +use super::noise::density::NoisePos; -use data::BlendingData; -use enum_dispatch::enum_dispatch; -use pumpkin_core::{ - math::{hypot, magnitude}, - random::{xoroshiro128::Xoroshiro, RandomGenerator, RandomImpl}, -}; - -use crate::{biome::Biome, height::HeightLimitViewImpl}; - -use super::{ - biome_coords, - chunk::{Chunk, ChunkPos}, - noise::{ - density::NoisePosImpl, - lerp, - perlin::{DoublePerlinNoiseParameters, DoublePerlinNoiseSampler}, - }, - supplier::{BiomeSupplier, StaticBiomeSupplier}, -}; - -pub mod data; - -static OFFSET_NOISE: LazyLock = LazyLock::new(|| { - DoublePerlinNoiseSampler::new( - &mut RandomGenerator::Xoroshiro(Xoroshiro::from_seed(42)), - &DoublePerlinNoiseParameters::new(-3, &[1f64; 4]), - ) -}); -const BLENDING_BIOME_DISTANCE_THRESHOLD: i32 = (7 << 2) - 1; -const BLENDING_CHUNK_DISTANCE_THRESHOLD: i32 = (BLENDING_BIOME_DISTANCE_THRESHOLD + 3) >> 2; -const CLOSE_BLENDING_DISTANCE_THRESHOLD: i32 = 5 >> 2; - -#[derive(Clone)] -pub struct BlendResult { - alpha: f64, - offset: f64, -} - -impl BlendResult { - pub fn new(alpha: f64, offset: f64) -> Self { - Self { alpha, offset } - } - - pub fn alpha(&self) -> f64 { - self.alpha - } - - pub fn offset(&self) -> f64 { - self.offset - } -} - -#[enum_dispatch(BlenderImpl)] -#[derive(Clone)] -pub enum Blender { - None(NoBlendBlender), - Standard(StandardBlender), +pub struct Blender { + // TODO } -#[enum_dispatch] -pub trait BlenderImpl { - fn apply_blend_density(&self, pos: &impl NoisePosImpl, density: f64) -> f64; - fn calculate(&self, block_x: i32, block_z: i32) -> BlendResult; - fn biome_supplier(&self, supplier: &BiomeSupplier) -> BiomeSupplier; -} - -#[derive(Clone)] -pub struct NoBlendBlender {} -impl BlenderImpl for NoBlendBlender { - fn calculate(&self, _block_x: i32, _block_z: i32) -> BlendResult { - BlendResult { - alpha: 1f64, - offset: 0f64, - } - } - - fn apply_blend_density(&self, _pos: &impl NoisePosImpl, density: f64) -> f64 { - density - } - - fn biome_supplier(&self, supplier: &BiomeSupplier) -> BiomeSupplier { - supplier.clone() - } -} - -#[derive(Clone)] -struct StandardBlender { - blend_data: Arc>, - close_blend_data: Arc>, -} - -#[derive(Clone)] -enum BlendingSampleType { - Height, - Density, -} - -impl StandardBlender { - fn new( - blend_data: HashMap, - close_blend_data: HashMap, - ) -> Self { - Self { - blend_data: Arc::new(blend_data), - close_blend_data: Arc::new(close_blend_data), - } - } - - fn blend_offset(height: f64) -> f64 { - let e = height + 0.5f64; - let f = ((e % 8f64) + 8f64) % 8f64; - (32f64 * (e - 128f64) - 3f64 * (e - 128f64) * f + 3f64 * f * f) - / (128f64 * (32f64 - 3f64 * f)) - } - - fn sample_closest( - &self, - sample_type: BlendingSampleType, - biome_x: i32, - biome_y: i32, - biome_z: i32, - ) -> f64 { - let i = biome_coords::to_chunk(biome_x); - let j = biome_coords::to_chunk(biome_z); - - let bl = (biome_x & 3) == 0; - let bl2 = (biome_z & 3) == 0; - - let mut d = self.sample(sample_type.clone(), i, j, biome_x, biome_y, biome_z); - - if d == f64::MAX { - if bl && bl2 { - d = self.sample(sample_type.clone(), i - 1, j - 1, biome_x, biome_y, biome_z); - } - - if d == f64::MAX && bl { - d = self.sample(sample_type.clone(), i - 1, j, biome_x, biome_y, biome_z); - } - - if d == f64::MAX && bl2 { - d = self.sample(sample_type.clone(), i, j - 1, biome_x, biome_y, biome_z); - } - } - - d - } - - fn sample( - &self, - sample_type: BlendingSampleType, - chunk_x: i32, - chunk_z: i32, - biome_x: i32, - biome_y: i32, - biome_z: i32, - ) -> f64 { - if let Some(blending_data) = self - .blend_data - .get(&ChunkPos::new(chunk_x, chunk_z).to_long()) - { - match sample_type { - BlendingSampleType::Height => blending_data.height( - (biome_x - biome_coords::from_chunk(chunk_x)) as usize, - biome_y as usize, - (biome_z - biome_coords::from_chunk(chunk_z)) as usize, - ), - BlendingSampleType::Density => blending_data.collidable_block_density( - (biome_x - biome_coords::from_chunk(chunk_x)) as usize, - biome_y, - (biome_z - biome_coords::from_chunk(chunk_z)) as usize, - ), - } - } else { - f64::MAX - } - } - - fn blend_biome(&self, x: i32, y: i32, z: i32) -> Option { - for (k, v) in self.blend_data.iter() { - let biome_x = biome_coords::from_chunk(ChunkPos::packed_x(*k)); - let biome_z = biome_coords::from_chunk(ChunkPos::packed_z(*k)); - - if y >= biome_coords::from_block(v.height_limit.bottom_y()) - && y < biome_coords::from_block(v.height_limit.top_y()) - { - let mut val = f64::INFINITY; - let mut biome: Option = None; - - let i = biome_coords::from_block(v.height_limit.bottom_y()); - - for (j, biome_list) in v.biomes.iter().enumerate() { - if let Some(biome_list) = biome_list { - if let Some(internal_biome) = biome_list.get(i as usize) { - let biome_x = biome_x + BlendingData::x(j) as i32; - let biome_z = biome_z + BlendingData::z(j) as i32; - - let dx = hypot((x - biome_x) as f64, (z - biome_z) as f64); - if dx <= BLENDING_BIOME_DISTANCE_THRESHOLD as f64 && dx < val { - val = dx; - biome = Some(*internal_biome) - } - } - } - } - - if val < f64::MAX { - let d = OFFSET_NOISE.sample(x as f64, 0f64, z as f64) * 12f64; - let e = ((val + d) / (BLENDING_BIOME_DISTANCE_THRESHOLD + 1) as f64) - .clamp(0f64, 1f64); - if e <= 0.5f64 { - return Some(biome.unwrap()); - } - } - } - } - - None - } -} - -impl BlenderImpl for StandardBlender { - fn calculate(&self, block_x: i32, block_z: i32) -> BlendResult { - let i = biome_coords::from_block(block_x); - let j = biome_coords::from_block(block_z); - - let d = self.sample_closest(BlendingSampleType::Height, i, 0, j); - if d != f64::MAX { - BlendResult { - alpha: 0f64, - offset: Self::blend_offset(d), - } - } else { - let mut val1 = 0f64; - let mut val2 = 0f64; - let mut val3 = f64::INFINITY; - - for (chunk_pos, data) in self.blend_data.iter() { - let biome_x = biome_coords::from_chunk(ChunkPos::packed_x(*chunk_pos)); - let biome_z = biome_coords::from_chunk(ChunkPos::packed_z(*chunk_pos)); - - for (index, height) in data.surface_heights.iter().enumerate() { - if *height != f64::MAX { - let biome_x = biome_x + BlendingData::x(index) as i32; - let biome_z = biome_z + BlendingData::z(index) as i32; - - let dx = hypot((i - biome_x) as f64, (j - biome_z) as f64); - if dx <= BLENDING_BIOME_DISTANCE_THRESHOLD as f64 { - if dx < val3 { - val3 = dx; - } - let ex = 1f64 / (dx * dx * dx * dx); - val2 += *height * ex; - val1 += ex; - } - } - } - } - - if val3 == f64::INFINITY { - BlendResult { - alpha: 1f64, - offset: 0f64, - } - } else { - let e = val2 / val1; - let f = (val3 / (BLENDING_BIOME_DISTANCE_THRESHOLD + 1) as f64).clamp(0f64, 1f64); - let f = 3f64 * f * f - 2f64 * f * f * f; - BlendResult { - alpha: f, - offset: Self::blend_offset(e), - } - } - } - } - - fn apply_blend_density(&self, pos: &impl NoisePosImpl, density: f64) -> f64 { - let i = biome_coords::from_block(pos.x()); - let j = pos.y() / 8; - let k = biome_coords::from_block(pos.z()); - - let d = self.sample_closest(BlendingSampleType::Density, i, j, k); - - if d != f64::MAX { - d - } else { - let mut val1 = 0f64; - let mut val2 = 0f64; - let mut val3 = f64::INFINITY; - - for (chunk_pos, data) in self.close_blend_data.iter() { - let biome_x = biome_coords::from_chunk(ChunkPos::packed_z(*chunk_pos)); - let biome_y = biome_coords::from_chunk(ChunkPos::packed_z(*chunk_pos)); - let min_half_section_y = j - 1; - let max_half_section_y = j + 1; - - let one_above = data.bottom_half_section_y() + 1; - let j = 0.max(min_half_section_y - one_above); - let k = data - .vertical_half_section_count() - .min(max_half_section_y - one_above); - - for (index, density_vec) in data.collidable_block_densities.iter().enumerate() { - if let Some(density_vec) = density_vec { - let m = biome_x + BlendingData::x(index) as i32; - let n = biome_y + BlendingData::z(index) as i32; - - for o in j..k { - let biome_x = m; - let half_section_y = o + one_above; - let biome_z = n; - let density = density_vec[o as usize] * 0.1f64; - - let dx = magnitude( - (i - biome_x) as f64, - ((j - half_section_y) * 2) as f64, - (k - biome_z) as f64, - ); - - if dx <= 2f64 { - if dx < val3 { - val3 = dx; - } - - let ex = 1f64 / (dx * dx * dx * dx); - val2 += density * ex; - val1 += ex; - } - } - } - } - } - - if val3 == f64::INFINITY { - density - } else { - let e = val2 / val1; - let f = (val3 / 3f64).clamp(0f64, 1f64); - lerp(f, e, density) - } - } - } - - fn biome_supplier(&self, _supplier: &BiomeSupplier) -> BiomeSupplier { - BiomeSupplier::Static(StaticBiomeSupplier {}) +impl Blender { + pub fn apply_blend_density(&self, _pos: &NoisePos, _density: f64) -> f64 { + todo!() } } diff --git a/pumpkin-world/src/world_gen/chunk.rs b/pumpkin-world/src/world_gen/chunk.rs deleted file mode 100644 index 84c84a849..000000000 --- a/pumpkin-world/src/world_gen/chunk.rs +++ /dev/null @@ -1,333 +0,0 @@ -use std::{ops::Add, sync::Arc}; - -use num_traits::PrimInt; -use parking_lot::Mutex; - -use crate::{ - biome::Biome, block::BlockId, chunk::ChunkData, height::HeightLimitViewImpl, - world_gen::noise::chunk_sampler::ChunkNoiseSampler, -}; - -use super::{biome_coords, blender::data::BlendingData, heightmap::HeightMap}; - -#[derive(Clone, PartialEq, PartialOrd)] -pub enum GenerationState { - Empty, - StructureStart, - StructureRef, - Biome, - Noise, - Surface, - Carver, - Feature, - InitLight, - Light, - Spawn, - Full, -} - -pub struct BlockPos { - x: i32, - y: i32, - z: i32, -} - -impl BlockPos { - pub fn new(x: i32, y: i32, z: i32) -> Self { - Self { x, y, z } - } - - pub fn x(&self) -> i32 { - self.x - } - - pub fn y(&self) -> i32 { - self.y - } - - pub fn z(&self) -> i32 { - self.z - } - - pub fn down(&self) -> Self { - self.down_by(1) - } - - pub fn down_by(&self, count: i32) -> Self { - Self { - x: self.x, - y: self.y - count, - z: self.z, - } - } - - pub fn up(&self) -> Self { - self.up_by(1) - } - - pub fn up_by(&self, count: i32) -> Self { - Self { - x: self.x, - y: self.y + count, - z: self.z, - } - } - - pub fn north(&self) -> Self { - self.north_by(1) - } - - pub fn north_by(&self, count: i32) -> Self { - Self { - x: self.x, - y: self.y, - z: self.z - count, - } - } - - pub fn south(&self) -> Self { - self.south_by(1) - } - - pub fn south_by(&self, count: i32) -> Self { - Self { - x: self.x, - y: self.y, - z: self.z + count, - } - } - - pub fn west(&self) -> Self { - self.west_by(1) - } - - pub fn west_by(&self, count: i32) -> Self { - Self { - x: self.x - count, - y: self.y, - z: self.z, - } - } - - pub fn east(&self) -> Self { - self.east_by(1) - } - - pub fn east_by(&self, count: i32) -> Self { - Self { - x: self.x + count, - y: self.y, - z: self.z, - } - } -} - -impl Add for BlockPos { - type Output = Self; - - fn add(self, rhs: Self) -> Self::Output { - Self { - x: self.x + rhs.x, - y: self.y + rhs.y, - z: self.z + rhs.z, - } - } -} - -pub enum HeightMapType { - WorldGenSurface, - WorldSurface, - WorldGenOceanFloor, - OceanFloor, - MotionBlocking, - MotionBlockingNoLeaves, -} - -pub struct VoxelShape {} - -impl VoxelShape { - pub fn is_empty(&self) -> bool { - unimplemented!() - } -} - -pub struct BlockState {} - -impl BlockState { - pub fn block(&self) -> BlockId { - unimplemented!() - } - - pub fn is_air(&self) -> bool { - unimplemented!() - } - - pub fn has_tag(&self, tag: &str) -> bool { - unimplemented!() - } - - pub fn is_block(&self, id: BlockId) -> bool { - unimplemented!() - } - - pub fn collision_shape(&self, chunk: &Chunk, pos: &BlockPos) -> VoxelShape { - unimplemented!() - } -} - -pub const CHUNK_MARKER: u64 = ChunkPos { - x: 1875066, - z: 1875066, -} -.to_long(); - -pub struct ChunkPos { - x: i32, - z: i32, -} - -impl ChunkPos { - pub const fn new(x: i32, z: i32) -> Self { - Self { x, z } - } - - pub const fn to_long(&self) -> u64 { - (self.x as u64 & 4294967295u64) | ((self.z as u64 & 4294967295u64) << 32) - } - - pub fn packed_x(pos: u64) -> i32 { - (pos & 4294967295u64) as i32 - } - - pub fn packed_z(pos: u64) -> i32 { - (pos.unsigned_shr(32) & 4294967295u64) as i32 - } - - pub fn get_start_x(&self) -> i32 { - self.x << 4 - } - - pub fn get_start_z(&self) -> i32 { - self.z << 4 - } -} - -pub struct Chunk { - pos: ChunkPos, - data: ChunkData, - state: GenerationState, -} - -impl Chunk { - pub fn get_block_state(&self, pos: &BlockPos) -> BlockState { - unimplemented!() - } - - pub fn sample_height_map(&self, map: HeightMapType, x: i32, y: i32) -> Option { - unimplemented!() - } - - pub fn biome_for_noise_gen(&self, biome_x: i32, biome_y: i32, biome_z: i32) -> Biome { - unimplemented!() - } - - pub fn blending_data(&self) -> Option { - unimplemented!() - } - - pub fn status(&self) -> GenerationState { - self.state.clone() - } - - pub fn get_or_create_noise_sampler(&self) -> Arc> { - unimplemented!() - } - - pub fn get_height_map(&self, map: HeightMapType) -> &HeightMap { - unimplemented!() - } - - pub fn pos(&self) -> &ChunkPos { - &self.pos - } -} - -impl HeightLimitViewImpl for Chunk { - fn bottom_y(&self) -> i32 { - unimplemented!() - } - - fn height(&self) -> i32 { - unimplemented!() - } -} - -#[derive(Clone)] -pub struct GenerationShapeConfig { - y_min: i32, - height: i32, - horizontal: i32, - vertical: i32, -} - -//Bits avaliable to encode y-pos -pub const SIZE_BITS_Y: i32 = 12; -pub const MAX_HEIGHT: i32 = (1 << SIZE_BITS_Y) - 32; -pub const MAX_COLUMN_HEIGHT: i32 = (MAX_HEIGHT >> 1) - 1; -pub const MIN_HEIGHT: i32 = MAX_COLUMN_HEIGHT - MAX_HEIGHT + 1; - -impl GenerationShapeConfig { - fn new(y_min: i32, height: i32, horizontal: i32, vertical: i32) -> Self { - if (y_min + height) > (MAX_COLUMN_HEIGHT + 1) { - panic!("Cannot be higher than max column height"); - } else if height % 16 != 0 { - panic!("Height must be a multiple of 16"); - } else if y_min % 16 != 0 { - panic!("Y min must be a multiple of 16"); - } - Self { - y_min, - height, - horizontal, - vertical, - } - } - - pub fn trim_height(&self, view: &impl HeightLimitViewImpl) -> Self { - let i = self.y_min.max(view.bottom_y()); - let j = (self.y_min + self.height).min(view.top_y()) - i; - Self { - y_min: i, - height: j, - horizontal: self.horizontal, - vertical: self.vertical, - } - } - - pub fn min_y(&self) -> i32 { - self.y_min - } - - pub fn height(&self) -> i32 { - self.height - } - - pub fn vertical_cell_block_count(&self) -> i32 { - biome_coords::to_block(self.vertical) - } - - pub fn horizontal_cell_block_count(&self) -> i32 { - biome_coords::to_block(self.horizontal) - } -} - -pub mod shape_configs { - use super::GenerationShapeConfig; - - pub const surface_config: GenerationShapeConfig = GenerationShapeConfig { - y_min: -64, - height: 384, - horizontal: 1, - vertical: 2, - }; -} diff --git a/pumpkin-world/src/height.rs b/pumpkin-world/src/world_gen/height_limit.rs similarity index 96% rename from pumpkin-world/src/height.rs rename to pumpkin-world/src/world_gen/height_limit.rs index 1effb518e..beb4dd043 100644 --- a/pumpkin-world/src/height.rs +++ b/pumpkin-world/src/world_gen/height_limit.rs @@ -1,11 +1,8 @@ use enum_dispatch::enum_dispatch; -use crate::world_gen::chunk::Chunk; - #[enum_dispatch] pub enum HeightLimitView { Standard(StandardHeightLimitView), - Chunk(Chunk), } #[enum_dispatch(HeightLimitView)] diff --git a/pumpkin-world/src/world_gen/heightmap.rs b/pumpkin-world/src/world_gen/heightmap.rs deleted file mode 100644 index 02e994ef5..000000000 --- a/pumpkin-world/src/world_gen/heightmap.rs +++ /dev/null @@ -1 +0,0 @@ -pub enum HeightMap {} diff --git a/pumpkin-world/src/world_gen/implementation/aquifer.rs b/pumpkin-world/src/world_gen/implementation/aquifer.rs deleted file mode 100644 index 84a0357ab..000000000 --- a/pumpkin-world/src/world_gen/implementation/aquifer.rs +++ /dev/null @@ -1,72 +0,0 @@ -use crate::{self as pumpkin_world, world_gen::noise::density::NoisePosImpl}; -use enum_dispatch::enum_dispatch; -use pumpkin_macros::block_id; - -use crate::block::BlockId; - -#[derive(Clone)] -struct FluidLevel { - y: i32, - state: BlockId, -} - -impl FluidLevel { - fn get_block(&self, y: i32) -> BlockId { - if y < self.y { - self.state - } else { - block_id!("minecraft:air") - } - } -} - -#[derive(Clone)] -pub struct FluidLevelSampler { - sea_level: i32, - fluid_level_1: FluidLevel, - fluid_level_2: FluidLevel, -} - -impl FluidLevelSampler { - fn get_fluid_level(&self, _x: i32, y: i32, _z: i32) -> FluidLevel { - if y < (-51).min(self.sea_level) { - self.fluid_level_1.clone() - } else { - self.fluid_level_2.clone() - } - } -} - -#[enum_dispatch(AquiferSamplerImpl)] -pub enum AquifierSampler { - SeaLevel(AquiferSeaLevel), -} - -#[enum_dispatch] -pub trait AquiferSamplerImpl { - fn apply(&self, pos: &impl NoisePosImpl, density: f64) -> Option; -} - -pub struct AquiferSeaLevel { - level_sampler: FluidLevelSampler, -} - -impl AquiferSeaLevel { - pub fn new(level_sampler: FluidLevelSampler) -> Self { - Self { level_sampler } - } -} - -impl AquiferSamplerImpl for AquiferSeaLevel { - fn apply(&self, pos: &impl NoisePosImpl, density: f64) -> Option { - if density > 0f64 { - None - } else { - Some( - self.level_sampler - .get_fluid_level(pos.x(), pos.y(), pos.z()) - .get_block(pos.y()), - ) - } - } -} diff --git a/pumpkin-world/src/world_gen/implementation/mod.rs b/pumpkin-world/src/world_gen/implementation/mod.rs index 804b134ac..7aa11a83b 100644 --- a/pumpkin-world/src/world_gen/implementation/mod.rs +++ b/pumpkin-world/src/world_gen/implementation/mod.rs @@ -1,58 +1,2 @@ -use crate::height::HeightLimitViewImpl; - -use super::{ - blender::Blender, - chunk::{Chunk, GenerationShapeConfig, HeightMapType}, - noise::config::NoiseConfig, -}; - -pub mod aquifer; pub mod overworld; pub mod superflat; -mod surface_builder; - -pub fn populate_noise( - chunk: &mut Chunk, - blender: &Blender, - config: &NoiseConfig, - shape: &GenerationShapeConfig, -) { - let shape = shape.trim_height(chunk); - let i = shape.min_y(); - let j = i / shape.vertical_cell_block_count(); - let k = shape.height() / shape.vertical_cell_block_count(); - - internal_populate_noise(chunk, blender, config, j, k); -} - -fn internal_populate_noise( - chunk: &mut Chunk, - blender: &Blender, - config: &NoiseConfig, - min_cell_y: i32, - cell_height: i32, -) { - let sampler = chunk.get_or_create_noise_sampler(); - let height_map = chunk.get_height_map(HeightMapType::WorldGenOceanFloor); - let height_map2 = chunk.get_height_map(HeightMapType::WorldGenSurface); - let pos = chunk.pos(); - - let i = pos.get_start_x(); - let j = pos.get_start_z(); - - let mut sampler = sampler.lock(); - sampler.sample_start_density(); - - let k = sampler.horizontal_cell_block_count(); - let l = sampler.vertical_cell_block_count(); - let m = 16 / k; - let n = 16 / k; - - for o in 0..m { - sampler.sample_end_density(o); - - for p in 0..n { - let q = chunk.vertical_section_count() - 1; - } - } -} diff --git a/pumpkin-world/src/world_gen/implementation/overworld/mod.rs b/pumpkin-world/src/world_gen/implementation/overworld/mod.rs index f96d401f1..f1af41c40 100644 --- a/pumpkin-world/src/world_gen/implementation/overworld/mod.rs +++ b/pumpkin-world/src/world_gen/implementation/overworld/mod.rs @@ -1,2 +1 @@ pub mod biome; -pub mod terrain_params; diff --git a/pumpkin-world/src/world_gen/implementation/surface_builder.rs b/pumpkin-world/src/world_gen/implementation/surface_builder.rs deleted file mode 100644 index e69de29bb..000000000 diff --git a/pumpkin-world/src/world_gen/mod.rs b/pumpkin-world/src/world_gen/mod.rs index 5a0aca08a..fbf0490ac 100644 --- a/pumpkin-world/src/world_gen/mod.rs +++ b/pumpkin-world/src/world_gen/mod.rs @@ -1,13 +1,15 @@ +#![allow(dead_code)] + mod blender; -pub mod chunk; mod generator; mod generic_generator; -mod heightmap; +pub mod height_limit; mod implementation; mod noise; -pub mod sampler; +mod positions; +mod proto_chunk; +mod sampler; mod seed; -mod supplier; pub use generator::WorldGenerator; use implementation::overworld::biome::plains::PlainsGenerator; diff --git a/pumpkin-world/src/world_gen/noise/chunk_sampler.rs b/pumpkin-world/src/world_gen/noise/chunk_sampler.rs deleted file mode 100644 index 6c3ed9107..000000000 --- a/pumpkin-world/src/world_gen/noise/chunk_sampler.rs +++ /dev/null @@ -1,1119 +0,0 @@ -use core::panic; -use std::{ - borrow::{Borrow, BorrowMut}, - cell::{Cell, RefCell}, - collections::HashMap, - default, - ops::DerefMut, - rc::Rc, - sync::{Arc, LazyLock}, -}; - -use enum_dispatch::enum_dispatch; -use itertools::Itertools; -use parking_lot::Mutex; - -use crate::{ - block::BlockId, - world_gen::{ - biome_coords, - blender::{BlendResult, Blender, BlenderImpl}, - chunk::{Chunk, ChunkPos, GenerationShapeConfig, CHUNK_MARKER}, - implementation::aquifer::{ - self, AquiferSamplerImpl, AquiferSeaLevel, AquifierSampler, FluidLevelSampler, - }, - noise::lerp3, - sampler, - }, -}; - -use super::{ - config::NoiseConfig, - density::{ - blend::{BlendAlphaFunction, BlendOffsetFunction}, - Applier, ApplierImpl, BeardifyerFunction, DensityFunction, DensityFunctionImpl, NoisePos, - NoisePosImpl, UnblendedNoisePos, Visitor, VisitorImpl, WrapperFunction, WrapperType, - }, - lerp, - router::NoiseRouter, -}; - -pub(crate) struct InterpolationApplier<'a> { - parent_sampler: Arc>>, -} - -impl<'a> ApplierImpl<'a> for InterpolationApplier<'a> { - fn at(&self, index: usize) -> NoisePos<'a> { - let index = index as i32; - let mut sampler = self.parent_sampler.lock(); - sampler.start_block_y = - (index + sampler.minimum_cell_y) * sampler.vertical_cell_block_count; - sampler.sample_unique += 1; - sampler.cell_block_y = 0; - sampler.index = index; - - NoisePos::ChunkNoise(ChunkNoiseSamplerWrapper { - parent_sampler: self.parent_sampler.clone(), - }) - } - - fn fill(&self, densities: &mut [f64], function: &DensityFunction<'a>) { - let mut sampler = self.parent_sampler.lock(); - - for i in 0..=sampler.vertical_cell_count { - sampler.start_block_y = - (i + sampler.minimum_cell_y) * sampler.vertical_cell_block_count; - sampler.sample_unique += 1; - sampler.cell_block_y = 0; - sampler.index = i; - - drop(sampler); - let sample = function.sample(&NoisePos::ChunkNoise(ChunkNoiseSamplerWrapper { - parent_sampler: self.parent_sampler.clone(), - })); - sampler = self.parent_sampler.lock(); - densities[sampler.index as usize] = sample; - } - } -} - -#[derive(Clone)] -pub(crate) struct BlendOffsetDensityFunction<'a> { - parent_sampler: Arc>>, -} - -impl<'a> DensityFunctionImpl<'a> for BlendOffsetDensityFunction<'a> { - fn sample(&self, pos: &NoisePos) -> f64 { - let mut sampler = self.parent_sampler.lock(); - sampler.calculate_blend_result(pos.x(), pos.z()).offset() - } - - fn fill(&self, densities: &mut [f64], applier: &Applier<'a>) { - applier.fill( - densities, - &DensityFunction::ChunkCacheBlendOffset(self.clone()), - ) - } - - fn apply(&self, visitor: &Visitor<'a>) -> Arc> { - DensityFunction::BlendOffset(BlendOffsetFunction {}).apply(visitor) - } - - fn max(&self) -> f64 { - f64::INFINITY - } - - fn min(&self) -> f64 { - f64::NEG_INFINITY - } -} - -#[derive(Clone)] -pub(crate) struct BlendAlphaDensityFunction<'a> { - parent_sampler: Arc>>, -} - -impl<'a> DensityFunctionImpl<'a> for BlendAlphaDensityFunction<'a> { - fn apply(&self, visitor: &Visitor<'a>) -> Arc> { - DensityFunction::BlendAlpha(BlendAlphaFunction {}).apply(visitor) - } - - fn sample(&self, pos: &NoisePos) -> f64 { - let mut sampler = self.parent_sampler.lock(); - sampler.calculate_blend_result(pos.x(), pos.z()).alpha() - } - - fn fill(&self, densities: &mut [f64], applier: &Applier<'a>) { - applier.fill( - densities, - &DensityFunction::ChunkCacheBlendAlpha(self.clone()), - ) - } - - fn min(&self) -> f64 { - 0f64 - } - - fn max(&self) -> f64 { - 1f64 - } -} - -#[derive(Clone)] -pub(crate) struct InterpolatorDensityFunctionWrapper<'a> { - wrapped: Arc>>, -} - -impl<'a> DensityFunctionImpl<'a> for InterpolatorDensityFunctionWrapper<'a> { - fn sample(&self, pos: &NoisePos) -> f64 { - self.wrapped.lock().sample(pos) - } - - fn fill(&self, densities: &mut [f64], applier: &Applier<'a>) { - self.wrapped.lock().fill(densities, applier) - } - - fn apply(&self, visitor: &Visitor<'a>) -> Arc> { - self.wrapped.lock().apply(visitor) - } - - fn min(&self) -> f64 { - self.wrapped.lock().min() - } - - fn max(&self) -> f64 { - self.wrapped.lock().max() - } -} - -#[derive(Clone)] -struct InterpolatorDensityFunction<'a> { - parent_sampler: Arc>>, - start_buffer: Vec>, - end_buffer: Vec>, - delegate: Arc>, - x0y0z0: f64, - x0y0z1: f64, - x1y0z0: f64, - x1y0z1: f64, - x0y1z0: f64, - x0y1z1: f64, - x1y1z0: f64, - x1y1z1: f64, - x0z0: f64, - x1z0: f64, - x0z1: f64, - x1z1: f64, - z0: f64, - z1: f64, - result: f64, -} - -impl<'a> InterpolatorDensityFunction<'a> { - fn new( - parent_sampler: Arc>>, - delegate: Arc>, - vertical_cell_count: i32, - horizontal_cell_count: i32, - ) -> InterpolatorDensityFunctionWrapper<'a> { - let result = Arc::new(Mutex::new(Self { - parent_sampler: parent_sampler.clone(), - start_buffer: Self::create_buffer(vertical_cell_count, horizontal_cell_count), - end_buffer: Self::create_buffer(vertical_cell_count, horizontal_cell_count), - delegate, - x0y0z0: 0f64, - x0y0z1: 0f64, - x1y0z0: 0f64, - x1y0z1: 0f64, - x0y1z0: 0f64, - x0y1z1: 0f64, - x1y1z0: 0f64, - x1y1z1: 0f64, - x0z0: 0f64, - x1z0: 0f64, - x0z1: 0f64, - x1z1: 0f64, - z0: 0f64, - z1: 0f64, - result: 0f64, - })); - let wrapper = InterpolatorDensityFunctionWrapper { wrapped: result }; - - let mut sampler = parent_sampler.lock(); - sampler.interpolators.push(wrapper.clone()); - wrapper - } - - fn on_sampled_cell_corners(&mut self, cell_y: usize, cell_z: usize) { - self.x0y0z0 = self.start_buffer[cell_z][cell_y]; - self.x0y0z1 = self.start_buffer[cell_z + 1][cell_y]; - self.x1y0z0 = self.end_buffer[cell_z][cell_y]; - self.x1y0z1 = self.end_buffer[cell_z + 1][cell_y]; - self.x0y1z0 = self.start_buffer[cell_z][cell_y + 1]; - self.x0y1z1 = self.start_buffer[cell_z + 1][cell_y + 1]; - self.x1y1z0 = self.end_buffer[cell_z][cell_y + 1]; - self.x1y1z1 = self.end_buffer[cell_z + 1][cell_y + 1]; - } - - fn interpolate_y(&mut self, delta: f64) { - self.x0z0 = lerp(delta, self.x0y0z0, self.x0y1z0); - self.x1z0 = lerp(delta, self.x1y0z0, self.x1y1z0); - self.x0z1 = lerp(delta, self.x0y0z1, self.x0y1z1); - self.x1z1 = lerp(delta, self.x1y0z1, self.x1y1z1); - } - - fn interpolate_x(&mut self, delta: f64) { - self.z0 = lerp(delta, self.x0z0, self.x1z0); - self.z1 = lerp(delta, self.x0z1, self.x1z1); - } - - fn interpolate_z(&mut self, delta: f64) { - self.result = lerp(delta, self.z0, self.z1); - } - - fn swap_buffers(&mut self) { - let ds = self.start_buffer.clone(); - self.start_buffer = self.end_buffer.clone(); - self.start_buffer = ds; - } - - fn create_buffer(size_z: i32, size_x: i32) -> Vec> { - let i = size_x + 1; - let j = size_z + 1; - - let mut result = Vec::>::new(); - for _ in 0..i { - result.push((0..j).map(|_| 0f64).collect()) - } - - result - } -} - -impl<'a> DensityFunctionImpl<'a> for InterpolatorDensityFunction<'a> { - fn sample(&self, pos: &super::density::NoisePos) -> f64 { - if let NoisePos::ChunkNoise(sampler) = pos { - let other_lock = { sampler.parent_sampler.lock().uuid }; - - let my_lock = { self.parent_sampler.lock().uuid }; - - if other_lock == my_lock { - return self.delegate.sample(pos); - } - } - - let sampler = self.parent_sampler.lock(); - assert!(sampler.interpolating, "Not interpolating"); - if sampler.sampling_for_caches { - lerp3( - sampler.cell_block_x as f64 / sampler.horizontal_cell_block_count as f64, - sampler.cell_block_y as f64 / sampler.vertical_cell_block_count as f64, - sampler.cell_block_z as f64 / sampler.horizontal_cell_block_count as f64, - self.x0y0z0, - self.x1y0z0, - self.x0y1z0, - self.x1y1z0, - self.x0y0z1, - self.x1y0z1, - self.x0y1z1, - self.x1y1z1, - ) - } else { - self.result - } - } - - fn apply(&self, visitor: &Visitor<'a>) -> Arc> { - visitor.apply(Arc::new(DensityFunction::Wrapper(WrapperFunction::new( - self.delegate.clone(), - WrapperType::Interpolated, - )))) - } - - fn fill(&self, densities: &mut [f64], applier: &Applier<'a>) { - let sampling = { self.parent_sampler.lock().sampling_for_caches }; - if sampling { - applier.fill( - densities, - &DensityFunction::ChunkCacheInterpolator(InterpolatorDensityFunctionWrapper { - wrapped: Arc::new(Mutex::new(self.clone())), - }), - ) - } else { - self.delegate.fill(densities, applier); - } - } - - fn min(&self) -> f64 { - self.delegate.min() - } - - fn max(&self) -> f64 { - self.delegate.max() - } -} - -#[derive(Clone)] -pub(crate) struct FlatCacheDensityFunction<'a> { - parent_sampler: Arc>>, - delegate: Arc>, - cache: Vec>, -} - -impl<'a> FlatCacheDensityFunction<'a> { - fn new( - parent_sampler: Arc>>, - delegate: Arc>, - biome_start_x: i32, - biome_start_z: i32, - horizontal_biome_end: usize, - sample: bool, - ) -> Self { - let mut cache: Vec> = Vec::new(); - for _ in 0..(horizontal_biome_end + 1) { - cache.push((0..(horizontal_biome_end + 1)).map(|_| 0f64).collect()) - } - - if sample { - for i in 0..=horizontal_biome_end { - let j = biome_start_x + i as i32; - let k = biome_coords::to_block(j); - - for l in 0..=horizontal_biome_end { - let m = biome_start_z + l as i32; - let n = biome_coords::to_block(m); - cache[i][l] = - delegate.sample(&NoisePos::Unblended(UnblendedNoisePos::new(k, 0, n))); - } - } - } - - Self { - parent_sampler, - delegate, - cache, - } - } -} - -impl<'a> DensityFunctionImpl<'a> for FlatCacheDensityFunction<'a> { - fn sample(&self, pos: &NoisePos) -> f64 { - let i = biome_coords::from_block(pos.x()); - let j = biome_coords::from_block(pos.z()); - let (start_biome_x, start_biome_z) = { - let sampler = self.parent_sampler.lock(); - (sampler.start_biome_x, sampler.start_biome_z) - }; - let k = i - start_biome_x; - let l = j - start_biome_z; - if k >= 0 && l >= 0 && (k as usize) < self.cache.len() && (l as usize) < self.cache.len() { - self.cache[k as usize][l as usize] - } else { - self.delegate.sample(pos) - } - } - - fn fill(&self, densities: &mut [f64], applier: &Applier<'a>) { - applier.fill( - densities, - &DensityFunction::ChunkCacheFlatCache(self.clone()), - ); - } - - fn apply(&self, visitor: &Visitor<'a>) -> Arc> { - visitor.apply(Arc::new(DensityFunction::Wrapper(WrapperFunction::new( - self.delegate.apply(visitor), - WrapperType::CacheFlat, - )))) - } - - fn min(&self) -> f64 { - self.delegate.min() - } - - fn max(&self) -> f64 { - self.delegate.max() - } -} - -#[derive(Clone)] -pub(crate) struct CellCacheDensityFunctionWrapper<'a> { - wrapped: Arc>, -} - -impl<'a> DensityFunctionImpl<'a> for CellCacheDensityFunctionWrapper<'a> { - fn sample(&self, pos: &NoisePos) -> f64 { - self.wrapped.sample(pos) - } - - fn fill(&self, densities: &mut [f64], applier: &Applier<'a>) { - applier.fill( - densities, - &DensityFunction::ChunkCacheCellCache(self.clone()), - ); - } - - fn apply(&self, visitor: &Visitor<'a>) -> Arc> { - self.wrapped.apply(visitor) - } - - fn min(&self) -> f64 { - self.wrapped.min() - } - - fn max(&self) -> f64 { - self.wrapped.max() - } -} - -#[derive(Clone)] -struct CellCacheDensityFunction<'a> { - parent_sampler: Arc>>, - delegate: Arc>, - cache: Vec, -} - -impl<'a> CellCacheDensityFunction<'a> { - fn new( - parent_sampler: Arc>>, - delegate: Arc>, - ) -> CellCacheDensityFunctionWrapper<'a> { - let cache_size = { - let sampler = parent_sampler.lock(); - sampler.horizontal_cell_block_count - * sampler.horizontal_cell_block_count - * sampler.vertical_cell_block_count - }; - let result = Arc::new(Self { - parent_sampler: parent_sampler.clone(), - delegate, - cache: (0..cache_size).map(|_| 0f64).collect(), - }); - - let wrapped = CellCacheDensityFunctionWrapper { wrapped: result }; - let mut sampler = parent_sampler.lock(); - sampler.caches.push(wrapped.clone()); - - wrapped - } -} - -impl<'a> DensityFunctionImpl<'a> for CellCacheDensityFunction<'a> { - fn sample(&self, pos: &NoisePos) -> f64 { - if let NoisePos::ChunkNoise(sampler) = pos { - let other_lock = { sampler.parent_sampler.lock().uuid }; - - let my_lock = { self.parent_sampler.lock().uuid }; - - if other_lock == my_lock { - return self.delegate.sample(pos); - } - } - - let sampler = self.parent_sampler.lock(); - assert!(sampler.interpolating); - let i = sampler.cell_block_x; - let j = sampler.cell_block_y; - let k = sampler.cell_block_z; - - if i >= 0 - && k >= 0 - && i < sampler.horizontal_cell_block_count - && j < sampler.vertical_cell_block_count - && k < sampler.horizontal_cell_block_count - { - self.cache[(((sampler.vertical_cell_block_count - 1 - j) - * sampler.horizontal_cell_block_count - + i) - * sampler.horizontal_cell_block_count - + k) as usize] - } else { - self.delegate.sample(pos) - } - } - - fn fill(&self, densities: &mut [f64], applier: &Applier<'a>) {} - - fn apply(&self, visitor: &Visitor<'a>) -> Arc> { - visitor.apply(Arc::new(DensityFunction::Wrapper(WrapperFunction::new( - self.delegate.apply(visitor), - WrapperType::CacheCell, - )))) - } - - fn min(&self) -> f64 { - self.delegate.min() - } - - fn max(&self) -> f64 { - self.delegate.max() - } -} - -struct CacheOnceDensityFunctionData { - sample_unique_index: u64, - cache_once_unique_index: u64, - last_sampling_result: f64, - cache: Option>, -} - -#[derive(Clone)] -pub(crate) struct CacheOnceDensityFunction<'a> { - parent_sampler: Arc>>, - delegate: Arc>, - data: Arc>, -} - -impl<'a> CacheOnceDensityFunction<'a> { - fn new( - parent_sampler: Arc>>, - delegate: Arc>, - ) -> Self { - Self { - parent_sampler, - delegate, - data: Arc::new(Mutex::new(CacheOnceDensityFunctionData { - sample_unique_index: 0, - cache_once_unique_index: 0, - last_sampling_result: 0f64, - cache: None, - })), - } - } -} - -impl<'a> DensityFunctionImpl<'a> for CacheOnceDensityFunction<'a> { - fn sample(&self, pos: &NoisePos) -> f64 { - let parent_sampler = self.parent_sampler.lock(); - let mut data = self.data.lock(); - - if let NoisePos::ChunkNoise(sampler) = pos { - let other_id = { sampler.parent_sampler.lock().uuid }; - let this_id = { self.parent_sampler.lock().uuid }; - if other_id != this_id { - return self.delegate.sample(pos); - } - } - - if let Some(cache) = &data.cache { - if data.cache_once_unique_index == parent_sampler.cache_unique { - return cache[parent_sampler.index as usize]; - } - } - - if data.sample_unique_index == parent_sampler.sample_unique { - data.last_sampling_result - } else { - data.sample_unique_index = parent_sampler.sample_unique; - let d = self.delegate.sample(pos); - data.last_sampling_result = d; - d - } - } - - fn fill(&self, densities: &mut [f64], applier: &Applier<'a>) { - let parent_sampler = self.parent_sampler.lock(); - let mut data = self.data.lock(); - let cache_once_unique_index = data.cache_once_unique_index; - - if let Some(cache) = &mut data.cache { - if parent_sampler.cache_unique == cache_once_unique_index { - densities - .iter_mut() - .zip_eq(cache) - .for_each(|(val, temp)| *val = *temp); - return; - } - } - - self.delegate.fill(densities, applier); - data.cache_once_unique_index = parent_sampler.cache_unique; - if let Some(cache) = &mut data.cache { - if cache.len() == densities.len() { - cache - .iter_mut() - .zip_eq(densities) - .for_each(|(val, temp)| *val = *temp); - return; - } - } - data.cache = Some(Vec::from_iter(densities.iter().map(|x| *x))); - } - - fn apply(&self, visitor: &Visitor<'a>) -> Arc> { - visitor.apply(Arc::new(DensityFunction::Wrapper(WrapperFunction::new( - self.delegate.apply(visitor), - WrapperType::CacheOnce, - )))) - } - - fn max(&self) -> f64 { - self.delegate.max() - } - - fn min(&self) -> f64 { - self.delegate.min() - } -} - -struct Cache2DDensityFunctionData { - last_sampling_column_pos: u64, - last_sampling_result: f64, -} - -#[derive(Clone)] -pub(crate) struct Cache2DDensityFunction<'a> { - delegate: Arc>, - data: Arc>, -} - -impl<'a> Cache2DDensityFunction<'a> { - fn new(delegate: Arc>) -> Self { - Self { - delegate, - data: Arc::new(Mutex::new(Cache2DDensityFunctionData { - last_sampling_column_pos: CHUNK_MARKER, - last_sampling_result: 0f64, - })), - } - } -} - -impl<'a> DensityFunctionImpl<'a> for Cache2DDensityFunction<'a> { - fn sample(&self, pos: &NoisePos) -> f64 { - let i = pos.x(); - let j = pos.z(); - let l = ChunkPos::new(i, j).to_long(); - let mut data = self.data.lock(); - if data.last_sampling_column_pos == l { - data.last_sampling_result - } else { - data.last_sampling_column_pos = l; - drop(data); - let d = self.delegate.sample(pos); - let mut data = self.data.lock(); - data.last_sampling_result = d; - d - } - } - - fn fill(&self, densities: &mut [f64], applier: &Applier<'a>) { - self.delegate.fill(densities, applier) - } - - fn apply(&self, visitor: &Visitor<'a>) -> Arc> { - visitor.apply(Arc::new(DensityFunction::Wrapper(WrapperFunction::new( - self.delegate.clone(), - WrapperType::Cache2D, - )))) - } - - fn min(&self) -> f64 { - self.delegate.min() - } - - fn max(&self) -> f64 { - self.delegate.max() - } -} - -#[enum_dispatch(BlockStateSamplerImpl)] -enum BlockStateSampler<'a> { - Aquifer(AquiferBlockStateSampler<'a>), -} - -struct AquiferBlockStateSampler<'a> { - aquifier: Arc, - function: Arc>, -} - -impl<'a> BlockStateSamplerImpl for AquiferBlockStateSampler<'a> { - fn sample(&self, pos: &NoisePos) -> Option { - self.aquifier.apply(pos, self.function.sample(pos)) - } -} - -#[enum_dispatch] -trait BlockStateSamplerImpl { - fn sample(&self, pos: &NoisePos) -> Option; -} - -static SAMPLER_ID_COUNTER: LazyLock>> = LazyLock::new(|| Arc::new(Mutex::new(0u64))); - -pub(crate) struct ChunkSamplerDensityFunctionConverter<'a> { - parent_sampler: Arc>>, -} - -impl<'a> VisitorImpl<'a> for ChunkSamplerDensityFunctionConverter<'a> { - fn apply(&self, function: Arc>) -> Arc> { - let sampler = self.parent_sampler.lock(); - let vertical_cell_count = sampler.vertical_cell_count; - let horizontal_cell_count = sampler.horizontal_cell_count; - - let biome_start_x = sampler.start_biome_x; - let biome_start_z = sampler.start_biome_z; - let horizontal_biome_end = sampler.horizontal_biome_end as usize; - - let blender = sampler.blender; - - if let DensityFunction::Wrapper(wrapped) = function.as_ref() { - match wrapped.wrapper() { - WrapperType::Interpolated => Arc::new(DensityFunction::ChunkCacheInterpolator( - InterpolatorDensityFunction::new( - self.parent_sampler.clone(), - wrapped.wrapped(), - vertical_cell_count, - horizontal_cell_count, - ), - )), - WrapperType::Cache2D => Arc::new(DensityFunction::ChunkCache2DCache( - Cache2DDensityFunction::new(wrapped.wrapped()), - )), - WrapperType::CacheFlat => Arc::new(DensityFunction::ChunkCacheFlatCache( - FlatCacheDensityFunction::new( - self.parent_sampler.clone(), - wrapped.wrapped(), - biome_start_x, - biome_start_z, - horizontal_biome_end, - true, - ), - )), - WrapperType::CacheOnce => Arc::new(DensityFunction::ChunkCacheOnceCache( - CacheOnceDensityFunction::new(self.parent_sampler.clone(), wrapped.wrapped()), - )), - WrapperType::CacheCell => Arc::new(DensityFunction::ChunkCacheCellCache( - CellCacheDensityFunction::new(self.parent_sampler.clone(), wrapped.wrapped()), - )), - } - } else if let Blender::None(_) = blender { - if let DensityFunction::BlendAlpha(_) = function.as_ref() { - let alpha_cache = { - sampler - .self_referential - .as_ref() - .unwrap() - .cached_blend_alpha_density_function - .clone() - }; - Arc::new(DensityFunction::ChunkCacheFlatCache(alpha_cache)) - } else if let DensityFunction::BlendOffset(_) = function.as_ref() { - let offset_cache = { - sampler - .self_referential - .as_ref() - .unwrap() - .cached_blend_offset_density_function - .clone() - }; - Arc::new(DensityFunction::ChunkCacheFlatCache(offset_cache)) - } else { - function - } - } else { - function - } - } -} - -struct ChunkNoiseSamplerSelfReferential<'a> { - cached_blend_alpha_density_function: FlatCacheDensityFunction<'a>, - cached_blend_offset_density_function: FlatCacheDensityFunction<'a>, - block_state_sampler: BlockStateSampler<'a>, - initial_density: Arc>, - aquifer_sampler: Arc, - interpolation_applier: Applier<'a>, -} - -pub struct ChunkNoiseSampler<'a> { - shape_config: GenerationShapeConfig, - horizontal_cell_count: i32, - vertical_cell_count: i32, - minimum_cell_y: i32, - start_cell_x: i32, - start_cell_z: i32, - start_biome_x: i32, - start_biome_z: i32, - interpolators: Vec>, - caches: Vec>, - surface_height_estimate_cache: HashMap, - blender: &'a Blender, - last_blended_column_pos: u64, - last_blending_result: BlendResult, - horizontal_biome_end: i32, - horizontal_cell_block_count: i32, - vertical_cell_block_count: i32, - interpolating: bool, - sampling_for_caches: bool, - start_block_x: i32, - start_block_y: i32, - start_block_z: i32, - cell_block_x: i32, - cell_block_y: i32, - cell_block_z: i32, - sample_unique: u64, - cache_unique: u64, - index: i32, - uuid: u64, - visitor: Option>>, - self_referential: Option>, -} - -impl<'a> ChunkNoiseSampler<'a> { - pub fn horizontal_cell_block_count(&self) -> i32 { - self.horizontal_cell_block_count - } - - pub fn vertical_cell_block_count(&self) -> i32 { - self.vertical_cell_block_count - } - - pub fn sample_start_density(&mut self) { - if self.interpolating { - panic!("interpolating twice"); - } - - self.interpolating = true; - self.sample_unique = 0; - self.sample_density(true, self.start_cell_x); - } - - pub fn sample_end_density(&mut self, cell_x: i32) { - self.sample_density(false, self.start_cell_x + cell_x + 1); - self.start_block_x = (self.start_cell_x * cell_x) * self.horizontal_cell_block_count - } - - fn sample_density(&mut self, start: bool, cell_x: i32) { - self.start_block_x = cell_x * self.horizontal_cell_block_count; - self.cell_block_x = 0; - - for i in 0..=self.horizontal_cell_count { - let j = self.start_cell_z + i; - self.start_cell_z = j * self.horizontal_cell_block_count; - self.cell_block_z = 0; - self.cache_unique += 1; - - for interpolator in self.interpolators.iter() { - let mut wrapped = interpolator.wrapped.lock(); - let ds = &mut (if start { - &mut wrapped.start_buffer - } else { - &mut wrapped.end_buffer - })[i as usize]; - - interpolator.fill( - ds, - &self - .self_referential - .as_ref() - .expect("call .init()") - .interpolation_applier, - ); - } - } - - self.cache_unique += 1; - } - - fn init_visitor(me: Arc>>) { - let visitor = Visitor::ChunkSampler(ChunkSamplerDensityFunctionConverter { - parent_sampler: me.clone(), - }); - - let mut sampler = me.lock(); - sampler.visitor = Some(Arc::new(visitor)) - } - - fn init( - parent_sampler: Arc>>, - noise_router: &'a NoiseRouter<'a>, - fluid_level: FluidLevelSampler, - visitor: &Visitor<'a>, - ) { - let sampler = parent_sampler.lock(); - - let mut cached_blend_alpha_density_function = FlatCacheDensityFunction::new( - parent_sampler.clone(), - Arc::new(DensityFunction::ChunkCacheBlendAlpha( - BlendAlphaDensityFunction { - parent_sampler: parent_sampler.clone(), - }, - )), - sampler.start_biome_x, - sampler.start_biome_z, - sampler.horizontal_biome_end as usize, - false, - ); - - let mut cached_blend_offset_density_function = FlatCacheDensityFunction::new( - parent_sampler.clone(), - Arc::new(DensityFunction::ChunkCacheBlendOffset( - BlendOffsetDensityFunction { - parent_sampler: parent_sampler.clone(), - }, - )), - sampler.start_biome_x, - sampler.start_biome_z, - sampler.horizontal_biome_end as usize, - false, - ); - - for i in 0..=(sampler.horizontal_biome_end as usize) { - let j = sampler.start_biome_x + (i as i32); - let k = biome_coords::to_block(j); - for l in 0..=(sampler.horizontal_biome_end as usize) { - let m = sampler.start_biome_z + (l as i32); - let n = biome_coords::to_block(m); - let result = sampler.blender.calculate(k, n); - cached_blend_alpha_density_function.cache[i][l] = result.alpha(); - cached_blend_offset_density_function.cache[i][l] = result.offset(); - } - } - - let new_router = noise_router.apply(visitor); - let aquifer = Arc::new(AquifierSampler::SeaLevel(AquiferSeaLevel::new(fluid_level))); - let final_density = new_router - .final_densitiy - .add(Arc::new(DensityFunction::Beardifyer(BeardifyerFunction {}))); - - let function = DensityFunction::Wrapper(WrapperFunction::new( - Arc::new(final_density), - WrapperType::CacheCell, - )); - - let block_sampler = BlockStateSampler::Aquifer(AquiferBlockStateSampler { - aquifier: aquifer.clone(), - function: function.apply(visitor), - }); - - let self_referring = ChunkNoiseSamplerSelfReferential { - cached_blend_alpha_density_function, - cached_blend_offset_density_function, - aquifer_sampler: aquifer, - block_state_sampler: block_sampler, - initial_density: new_router.internal_density.clone(), - interpolation_applier: Applier::Interpolation(InterpolationApplier { - parent_sampler: parent_sampler.clone(), - }), - }; - let mut sampler = parent_sampler.lock(); - sampler.self_referential = Some(self_referring); - } - - fn new( - horizontal_cell_count: i32, - start_block_x: i32, - start_block_z: i32, - shape: &GenerationShapeConfig, - blender: &'a Blender, - ) -> Self { - let shape_config = shape.clone(); - let horizontal_cell_block_count = shape_config.horizontal_cell_block_count(); - let vertical_cell_block_count = shape_config.vertical_cell_block_count(); - let vertical_cell_count = shape_config.height() / vertical_cell_block_count; - let minimum_cell_y = shape_config.min_y() / vertical_cell_block_count; - let start_cell_x = start_block_x / horizontal_cell_block_count; - let start_cell_z = start_block_z / horizontal_cell_block_count; - let interpolators: Vec> = Vec::new(); - let caches: Vec> = Vec::new(); - let start_biome_x = biome_coords::from_block(start_block_x); - let start_biome_z = biome_coords::from_block(start_block_z); - let horizontal_biome_end = - biome_coords::from_block(horizontal_cell_count * horizontal_cell_block_count); - - let new_id = { - let mut id = SAMPLER_ID_COUNTER.lock(); - let new_id = *id; - *id += 1; - new_id - }; - - Self { - shape_config, - horizontal_cell_block_count, - vertical_cell_block_count, - horizontal_cell_count, - vertical_cell_count, - minimum_cell_y, - start_cell_x, - start_cell_z, - interpolators, - caches, - start_biome_x, - start_biome_z, - horizontal_biome_end, - blender, - surface_height_estimate_cache: HashMap::new(), - last_blending_result: BlendResult::new(1f64, 0f64), - last_blended_column_pos: CHUNK_MARKER, - interpolating: false, - sampling_for_caches: false, - start_block_z: 0, - start_block_x: 0, - start_block_y: 0, - cell_block_x: 0, - cell_block_y: 0, - cell_block_z: 0, - sample_unique: 0, - cache_unique: 0, - uuid: new_id, - index: 0, - visitor: None, - self_referential: None, - } - } - - fn calculate_blend_result(&mut self, block_x: i32, block_z: i32) -> BlendResult { - let l = ChunkPos::new(block_x, block_z).to_long(); - if l != self.last_blended_column_pos { - self.last_blended_column_pos = l; - let blend_result = self.blender.calculate(block_x, block_z); - self.last_blending_result = blend_result; - } - self.last_blending_result.clone() - } -} - -#[derive(Clone)] -pub(crate) struct ChunkNoiseSamplerWrapper<'a> { - parent_sampler: Arc>>, -} - -impl<'a> ApplierImpl<'a> for ChunkNoiseSamplerWrapper<'a> { - fn at(&self, index: usize) -> NoisePos<'a> { - let index = index as i32; - let mut sampler = self.parent_sampler.lock(); - let j = index % sampler.horizontal_cell_block_count; - let k = index % sampler.horizontal_cell_block_count; - let l = index % sampler.horizontal_cell_block_count; - let m = sampler.vertical_cell_block_count - 1 - (k / sampler.horizontal_cell_block_count); - - sampler.cell_block_x = l; - sampler.cell_block_y = m; - sampler.cell_block_z = j; - sampler.index = index; - - NoisePos::ChunkNoise(self.clone()) - } - - fn fill(&self, densities: &mut [f64], function: &DensityFunction<'a>) { - let mut sampler = self.parent_sampler.lock(); - sampler.index = 0; - for i in (0..=sampler.vertical_cell_block_count).rev() { - sampler.cell_block_y = i; - for j in 0..sampler.horizontal_cell_block_count { - sampler.cell_block_x = j; - for k in 0..sampler.horizontal_cell_block_count { - sampler.cell_block_z = k; - drop(sampler); - let sample = function.sample(&NoisePos::ChunkNoise(self.clone())); - sampler = self.parent_sampler.lock(); - densities[sampler.index as usize] = sample; - sampler.index += 1; - } - } - } - } -} - -impl<'a> NoisePosImpl for ChunkNoiseSamplerWrapper<'a> { - fn z(&self) -> i32 { - let sampler = self.parent_sampler.lock(); - sampler.start_block_z + sampler.cell_block_z - } - - fn y(&self) -> i32 { - let sampler = self.parent_sampler.lock(); - sampler.start_block_y + sampler.cell_block_y - } - - fn x(&self) -> i32 { - let sampler = self.parent_sampler.lock(); - sampler.start_block_x + sampler.cell_block_x - } - - fn get_blender(&self) -> Blender { - let sampler = self.parent_sampler.lock(); - sampler.blender.clone() - } -} diff --git a/pumpkin-world/src/world_gen/noise/config.rs b/pumpkin-world/src/world_gen/noise/config.rs deleted file mode 100644 index ab08dee04..000000000 --- a/pumpkin-world/src/world_gen/noise/config.rs +++ /dev/null @@ -1,16 +0,0 @@ -use pumpkin_core::random::RandomDeriver; - -use crate::world_gen::supplier::MultiNoiseSampler; - -use super::router::NoiseRouter; - -pub struct NoiseConfig<'a> { - random_deriver: RandomDeriver, - router: NoiseRouter<'a>, -} - -impl<'a> NoiseConfig<'a> { - pub fn noise_router(&self) -> NoiseRouter<'a> { - self.router.clone() - } -} diff --git a/pumpkin-world/src/world_gen/noise/density/blend.rs b/pumpkin-world/src/world_gen/noise/density/blend.rs index 33f17616a..952efc818 100644 --- a/pumpkin-world/src/world_gen/noise/density/blend.rs +++ b/pumpkin-world/src/world_gen/noise/density/blend.rs @@ -1,7 +1,5 @@ use std::sync::Arc; -use crate::world_gen::blender::BlenderImpl; - use super::{ Applier, ApplierImpl, DensityFunction, DensityFunctionImpl, NoisePos, NoisePosImpl, Visitor, VisitorImpl, diff --git a/pumpkin-world/src/world_gen/noise/density/mod.rs b/pumpkin-world/src/world_gen/noise/density/mod.rs index 9ea93436e..4f67aa582 100644 --- a/pumpkin-world/src/world_gen/noise/density/mod.rs +++ b/pumpkin-world/src/world_gen/noise/density/mod.rs @@ -8,28 +8,13 @@ use math::{BinaryFunction, BinaryType, LinearFunction}; use noise::{InternalNoise, InterpolatedNoiseSampler, NoiseFunction, ShiftedNoiseFunction}; use offset::{ShiftAFunction, ShiftBFunction}; use spline::SplineFunction; +use terrain_helpers::{create_factor_spline, create_jaggedness_spline, create_offset_spline}; use unary::{ClampFunction, UnaryFunction, UnaryType}; use weird::{RarityMapper, WierdScaledFunction}; -use crate::world_gen::{ - blender::{Blender, NoBlendBlender}, - chunk::{MAX_COLUMN_HEIGHT, MIN_HEIGHT}, - implementation::overworld::terrain_params::{ - create_factor_spline, create_jaggedness_spline, create_offset_spline, - }, -}; - -use super::{ - chunk_sampler::{ - BlendAlphaDensityFunction, BlendOffsetDensityFunction, Cache2DDensityFunction, - CacheOnceDensityFunction, CellCacheDensityFunctionWrapper, ChunkNoiseSamplerWrapper, - ChunkSamplerDensityFunctionConverter, FlatCacheDensityFunction, InterpolationApplier, - InterpolatorDensityFunctionWrapper, - }, - clamped_map, - perlin::DoublePerlinNoiseParameters, - BuiltInNoiseParams, -}; +use crate::world_gen::blender::Blender; + +use super::{clamped_map, perlin::DoublePerlinNoiseParameters, BuiltInNoiseParams}; pub mod blend; mod end; @@ -37,6 +22,7 @@ mod math; pub mod noise; mod offset; pub mod spline; +mod terrain_helpers; mod unary; mod weird; @@ -90,6 +76,12 @@ pub struct BuiltInNoiseFunctions<'a> { caves_pillars_overworld: Arc>, } +//Bits avaliable to encode y-pos +pub const SIZE_BITS_Y: i32 = 12; +pub const MAX_HEIGHT: i32 = (1 << SIZE_BITS_Y) - 32; +pub const MAX_COLUMN_HEIGHT: i32 = (MAX_HEIGHT >> 1) - 1; +pub const MIN_HEIGHT: i32 = MAX_COLUMN_HEIGHT - MAX_HEIGHT + 1; + impl<'a> BuiltInNoiseFunctions<'a> { pub fn new(built_in_noise_params: &BuiltInNoiseParams<'a>) -> Self { let blend_alpha = Arc::new(DensityFunction::BlendAlpha(BlendAlphaFunction {})); @@ -626,6 +618,7 @@ impl<'a> BuiltInNoiseFunctions<'a> { } } +#[allow(clippy::too_many_arguments)] fn sloped_cheese_function<'a>( jagged_noise: Arc>, continents: Arc>, @@ -640,13 +633,14 @@ fn sloped_cheese_function<'a>( ) -> SlopedCheeseResult<'a> { let offset = Arc::new(apply_blending( Arc::new( - DensityFunction::Spline(SplineFunction::new(Arc::new(create_offset_spline( - continents.clone(), - erosion.clone(), - ridges.clone(), - amplified, - )))) - .add_const(-0.50375f32 as f64), + DensityFunction::Constant(ConstantFunction::new(-0.50375f32 as f64)).add(Arc::new( + DensityFunction::Spline(SplineFunction::new(Arc::new(create_offset_spline( + continents.clone(), + erosion.clone(), + ridges_folded.clone(), + amplified, + )))), + )), ), blend_offset, )); @@ -734,7 +728,6 @@ fn apply_blending<'a>( function: Arc>, blend: Arc>, ) -> DensityFunction<'a> { - //let function = lerp_density(built_in_noises::BLEND_ALPHA.clone(), blend, function); let function = lerp_density( Arc::new(DensityFunction::BlendAlpha(BlendAlphaFunction {})), blend, @@ -799,14 +792,6 @@ pub enum DensityFunction<'a> { Wierd(WierdScaledFunction<'a>), Range(RangeFunction<'a>), Wrapper(WrapperFunction<'a>), - ChunkCacheFlatCache(FlatCacheDensityFunction<'a>), - ChunkCacheInterpolator(InterpolatorDensityFunctionWrapper<'a>), - ChunkCacheBlendAlpha(BlendAlphaDensityFunction<'a>), - ChunkCacheBlendOffset(BlendOffsetDensityFunction<'a>), - ChunkCacheCellCache(CellCacheDensityFunctionWrapper<'a>), - ChunkCache2DCache(Cache2DDensityFunction<'a>), - ChunkCacheOnceCache(CacheOnceDensityFunction<'a>), - Beardifyer(BeardifyerFunction), } impl<'a> DensityFunction<'a> { @@ -885,10 +870,44 @@ impl<'a> DensityFunction<'a> { } } +pub struct Unused<'a> { + _x: &'a str, +} + +impl<'a> NoisePosImpl for Unused<'a> { + fn x(&self) -> i32 { + todo!() + } + + fn y(&self) -> i32 { + todo!() + } + + fn z(&self) -> i32 { + todo!() + } +} + +impl<'a> ApplierImpl<'a> for Unused<'a> { + fn at(&self, _index: usize) -> NoisePos<'a> { + todo!() + } + + fn fill(&self, _densities: &mut [f64], _function: &DensityFunction<'a>) { + todo!() + } +} + +impl<'a> VisitorImpl<'a> for Unused<'a> { + fn apply(&self, _function: Arc>) -> Arc> { + todo!() + } +} + #[enum_dispatch(NoisePosImpl)] pub enum NoisePos<'a> { Unblended(UnblendedNoisePos), - ChunkNoise(ChunkNoiseSamplerWrapper<'a>), + Todo(Unused<'a>), } pub struct UnblendedNoisePos { @@ -924,14 +943,13 @@ pub trait NoisePosImpl { fn z(&self) -> i32; fn get_blender(&self) -> Blender { - Blender::None(NoBlendBlender {}) + unimplemented!() } } #[enum_dispatch(ApplierImpl)] pub enum Applier<'a> { - ChunkNoise(ChunkNoiseSamplerWrapper<'a>), - Interpolation(InterpolationApplier<'a>), + Todo(Unused<'a>), } #[enum_dispatch] @@ -944,7 +962,7 @@ pub trait ApplierImpl<'a> { #[enum_dispatch(VisitorImpl)] pub enum Visitor<'a> { Unwrap(UnwrapVisitor), - ChunkSampler(ChunkSamplerDensityFunctionConverter<'a>), + Todo(Unused<'a>), } pub struct UnwrapVisitor {} @@ -1134,31 +1152,6 @@ impl<'a> DensityFunctionImpl<'a> for RangeFunction<'a> { } } -#[derive(Clone)] -pub struct BeardifyerFunction {} - -impl<'a> DensityFunctionImpl<'a> for BeardifyerFunction { - fn sample(&self, _pos: &NoisePos) -> f64 { - 0f64 - } - - fn fill(&self, densities: &mut [f64], _applier: &Applier<'a>) { - densities.fill(0f64) - } - - fn min(&self) -> f64 { - 0f64 - } - - fn max(&self) -> f64 { - 0f64 - } - - fn apply(&self, visitor: &Visitor<'a>) -> Arc> { - visitor.apply(Arc::new(DensityFunction::Beardifyer(BeardifyerFunction {}))) - } -} - #[derive(Clone)] pub struct YClampedFunction { from: i32, @@ -1244,3 +1237,129 @@ pub fn lerp_density_static_start<'a>( ) -> DensityFunction<'a> { delta.mul(Arc::new(end.add_const(-start))).add_const(start) } + +#[cfg(test)] +mod test { + use crate::world_gen::noise::{density::DensityFunctionImpl, BuiltInNoiseParams}; + + use super::{BuiltInNoiseFunctions, NoisePos, UnblendedNoisePos}; + + #[test] + fn test_density_function_correctness() { + let noise_params = BuiltInNoiseParams::new(); + let noise_functions = BuiltInNoiseFunctions::new(&noise_params); + + let pos = NoisePos::Unblended(UnblendedNoisePos { x: 0, y: 0, z: 0 }); + + assert_eq!(noise_functions.blend_alpha.sample(&pos), 1f64); + assert_eq!(noise_functions.blend_alpha.min(), 1f64); + assert_eq!(noise_functions.blend_alpha.max(), 1f64); + + assert_eq!(noise_functions.blend_offset.sample(&pos), 0f64); + assert_eq!(noise_functions.blend_offset.min(), 0f64); + assert_eq!(noise_functions.blend_offset.max(), 0f64); + + assert_eq!(noise_functions.zero.sample(&pos), 0f64); + assert_eq!(noise_functions.zero.min(), 0f64); + assert_eq!(noise_functions.zero.max(), 0f64); + + assert_eq!(noise_functions.y.sample(&pos), 0f64); + assert_eq!(noise_functions.y.min(), -4064f64); + assert_eq!(noise_functions.y.max(), 4062f64); + + assert_eq!(noise_functions.shift_x.sample(&pos), 0f64); + assert_eq!(noise_functions.shift_x.min(), -8f64); + assert_eq!(noise_functions.shift_x.max(), 8f64); + + assert_eq!(noise_functions.shift_z.sample(&pos), 0f64); + assert_eq!(noise_functions.shift_z.min(), -8f64); + assert_eq!(noise_functions.shift_z.max(), 8f64); + + assert_eq!( + noise_functions.base_3d_noise_overworld.sample(&pos), + 0.05283727086562935f64 + ); + assert_eq!( + noise_functions.base_3d_noise_overworld.min(), + -87.55150000000002f64 + ); + assert_eq!( + noise_functions.base_3d_noise_overworld.max(), + 87.55150000000002f64 + ); + + assert_eq!( + noise_functions.base_3d_noise_nether.sample(&pos), + 0.05283727086562935f64 + ); + assert_eq!( + noise_functions.base_3d_noise_nether.min(), + -258.65450000000004f64 + ); + assert_eq!( + noise_functions.base_3d_noise_nether.max(), + 258.65450000000004f64 + ); + + assert_eq!( + noise_functions.base_3d_noise_end.sample(&pos), + 0.05283727086562935f64 + ); + assert_eq!( + noise_functions.base_3d_noise_end.min(), + -173.10299999999998f64 + ); + assert_eq!( + noise_functions.base_3d_noise_end.max(), + 173.10299999999998f64 + ); + + assert_eq!(noise_functions.continents_overworld.sample(&pos), 0f64); + assert_eq!(noise_functions.continents_overworld.min(), -2f64); + assert_eq!(noise_functions.continents_overworld.max(), 2f64); + + assert_eq!(noise_functions.erosion_overworld.sample(&pos), 0f64); + assert_eq!(noise_functions.erosion_overworld.min(), -2f64); + assert_eq!(noise_functions.erosion_overworld.max(), 2f64); + + assert_eq!(noise_functions.ridges_overworld.sample(&pos), 0f64); + assert_eq!(noise_functions.ridges_overworld.min(), -2f64); + assert_eq!(noise_functions.ridges_overworld.max(), 2f64); + + assert_eq!(noise_functions.ridges_folded_overworld.sample(&pos), -1f64); + assert_eq!( + noise_functions.ridges_folded_overworld.min(), + -3.000000000000001f64 + ); + assert_eq!(noise_functions.ridges_folded_overworld.max(), 1f64); + + assert_eq!( + noise_functions.offset_overworld.sample(&pos), + -0.6037500277161598f64 + ); + assert_eq!( + noise_functions.offset_overworld.min(), + -1.3752707839012146f64 + ); + assert_eq!( + noise_functions.offset_overworld.max(), + 0.9962499737739563f64 + ); + + assert_eq!(noise_functions.y.sample(&pos), 0f64); + assert_eq!(noise_functions.y.min(), -4064f64); + assert_eq!(noise_functions.y.max(), 4062f64); + + assert_eq!(noise_functions.y.sample(&pos), 0f64); + assert_eq!(noise_functions.y.min(), -4064f64); + assert_eq!(noise_functions.y.max(), 4062f64); + + assert_eq!(noise_functions.y.sample(&pos), 0f64); + assert_eq!(noise_functions.y.min(), -4064f64); + assert_eq!(noise_functions.y.max(), 4062f64); + + assert_eq!(noise_functions.y.sample(&pos), 0f64); + assert_eq!(noise_functions.y.min(), -4064f64); + assert_eq!(noise_functions.y.max(), 4062f64); + } +} diff --git a/pumpkin-world/src/world_gen/noise/density/spline.rs b/pumpkin-world/src/world_gen/noise/density/spline.rs index 04e543a6a..c2480d7cc 100644 --- a/pumpkin-world/src/world_gen/noise/density/spline.rs +++ b/pumpkin-world/src/world_gen/noise/density/spline.rs @@ -1,6 +1,6 @@ use std::sync::Arc; -use crate::world_gen::noise::lerp_32; +use crate::world_gen::noise::lerp; use super::{ Applier, ApplierImpl, DensityFunction, DensityFunctionImpl, NoisePos, Visitor, VisitorImpl, @@ -56,6 +56,11 @@ pub struct Spline<'a> { max: f32, } +enum Range { + In(usize), + Below, +} + impl<'a> Spline<'a> { fn sample_outside_range(point: f32, value: f32, points: &[SplinePoint], i: usize) -> f32 { let f = points[i].derivative; @@ -66,8 +71,29 @@ impl<'a> Spline<'a> { } } - fn find_range_for_location(locations: &[f32], x: f32) -> i32 { - locations.partition_point(|val| x < *val) as i32 - 1 + fn binary_walk(min: usize, max: usize, pred: impl Fn(usize) -> bool) -> usize { + let mut i = max - min; + let mut min = min; + while i > 0 { + let j = i / 2; + let k = min + j; + if pred(k) { + i = j; + } else { + min = k + 1; + i -= j + 1; + } + } + min + } + + fn find_range_for_location(points: &[SplinePoint], x: f32) -> Range { + let index_greater_than_x = Self::binary_walk(0, points.len(), |i| x < points[i].location); + if index_greater_than_x == 0 { + Range::Below + } else { + Range::In(index_greater_than_x - 1) + } } pub fn new(function: Arc>, points: &[SplinePoint<'a>]) -> Self { @@ -143,31 +169,34 @@ impl<'a> Spline<'a> { pub fn apply(&self, pos: &NoisePos) -> f32 { let f = self.function.sample(pos) as f32; - let i = Self::find_range_for_location( - self.points - .iter() - .map(|p| p.location) - .collect::>() - .as_ref(), - f, - ); - let j = self.points.len() - 1; - - if i < 0 { - Self::sample_outside_range(f, self.points[0].value.apply(pos), &self.points, 0) - } else if i == j as i32 { - Self::sample_outside_range(f, self.points[j].value.apply(pos), &self.points, j) - } else { - let point_1 = &self.points[i as usize]; - let point_2 = &self.points[i as usize + 1]; - let k = (f - point_1.location) / (point_2.location - point_1.location); + let i = Self::find_range_for_location(&self.points, f); + + match i { + Range::In(index) => { + let last_index = self.points.len() - 1; + if index == last_index { + Self::sample_outside_range( + f, + self.points[last_index].value.apply(pos), + &self.points, + last_index, + ) + } else { + let point_1 = &self.points[index]; + let point_2 = &self.points[index + 1]; + let k = (f - point_1.location) / (point_2.location - point_1.location); - let n = point_1.value.apply(pos); - let o = point_2.value.apply(pos); + let n = point_1.value.apply(pos); + let o = point_2.value.apply(pos); - let p = point_1.derivative * (point_2.location - point_1.location) - (o - n); - let q = -point_2.derivative * (point_2.location - point_1.location) + (o - n); - lerp_32(k, n, o) + k * (1f32 - k) * lerp_32(k, p, q) + let p = point_1.derivative * (point_2.location - point_1.location) - (o - n); + let q = -point_2.derivative * (point_2.location - point_1.location) + (o - n); + lerp(k, n, o) + k * (1f32 - k) * lerp(k, p, q) + } + } + Range::Below => { + Self::sample_outside_range(f, self.points[0].value.apply(pos), &self.points, 0) + } } } @@ -225,7 +254,9 @@ impl<'a> DensityFunctionImpl<'a> for SplineFunction<'a> { #[derive(Clone)] pub enum FloatAmplifier { Identity, - Amplifier, + OffsetAmplifier, + FactorAmplifier, + JaggednessAmplifier, } impl FloatAmplifier { @@ -233,13 +264,15 @@ impl FloatAmplifier { pub fn apply(&self, f: f32) -> f32 { match self { Self::Identity => f, - Self::Amplifier => { + Self::OffsetAmplifier => { if f < 0f32 { f } else { f * 2f32 } } + Self::FactorAmplifier => 1.25f32 - 6.25f32 / (f + 5f32), + Self::JaggednessAmplifier => f * 2f32, } } } @@ -293,3 +326,34 @@ impl<'a> SplineBuilder<'a> { Spline::new(self.function.clone(), &self.points) } } + +#[cfg(test)] +mod test { + + use crate::world_gen::noise::{ + density::{BuiltInNoiseFunctions, NoisePos, UnblendedNoisePos}, + BuiltInNoiseParams, + }; + + use super::{FloatAmplifier, SplineBuilder}; + + #[test] + fn test_correctness() { + let noise_params = BuiltInNoiseParams::new(); + let noise_functions = BuiltInNoiseFunctions::new(&noise_params); + let pos = NoisePos::Unblended(UnblendedNoisePos { x: 0, y: 0, z: 0 }); + + let spline = SplineBuilder::new( + noise_functions.continents_overworld, + FloatAmplifier::Identity, + ) + .add_value(-1.1f32, 0.044f32, 0f32) + .add_value(-1.02f32, -0.2222f32, 0f32) + .add_value(-0.51f32, -0.2222f32, 0f32) + .add_value(-0.44f32, -0.12f32, 0f32) + .add_value(-0.18f32, -0.12f32, 0f32) + .build(); + + assert_eq!(spline.apply(&pos), -0.12f32); + } +} diff --git a/pumpkin-world/src/world_gen/implementation/overworld/terrain_params.rs b/pumpkin-world/src/world_gen/noise/density/terrain_helpers.rs similarity index 84% rename from pumpkin-world/src/world_gen/implementation/overworld/terrain_params.rs rename to pumpkin-world/src/world_gen/noise/density/terrain_helpers.rs index 31d5ffbae..432052cb6 100644 --- a/pumpkin-world/src/world_gen/implementation/overworld/terrain_params.rs +++ b/pumpkin-world/src/world_gen/noise/density/terrain_helpers.rs @@ -6,7 +6,7 @@ use crate::world_gen::noise::density::spline::{ FloatAmplifier, Spline, SplineBuilder, SplineValue, }; use crate::world_gen::noise::density::{peaks_valleys_noise, DensityFunction}; -use crate::world_gen::noise::lerp_32; +use crate::world_gen::noise::lerp; #[inline] fn get_offset_value(f: f32, g: f32, h: f32) -> f32 { @@ -69,7 +69,7 @@ fn meth_42050( let builder = if bl { builder .add_value(-1f32, 0.2f32.max(i), 0f32) - .add_value(0f32, lerp_32(0.5f32, i, k), n) + .add_value(0f32, lerp(0.5f32, i, k), n) } else { builder.add_value(-1f32, i, n) }; @@ -216,11 +216,8 @@ fn method_42052<'a>( builder.build() } -fn method_42049<'a>( - ridges: Arc>, - f: f32, - amplifier: FloatAmplifier, -) -> Spline<'a> { +#[inline] +fn method_42049(ridges: Arc, f: f32, amplifier: FloatAmplifier) -> Spline { let g = 0.63f32 * f; let h = 0.3f32 * f; SplineBuilder::new(ridges, amplifier) @@ -229,6 +226,8 @@ fn method_42049<'a>( .build() } +#[allow(clippy::too_many_arguments)] +#[inline] fn method_42053<'a>( erosion: Arc>, ridges: Arc>, @@ -257,7 +256,7 @@ fn method_42053<'a>( SplineBuilder::new(erosion, amplifier) .add_spline(-1f32, SplineValue::Spline(spline), 0f32) .add_spline(-0.78, SplineValue::Spline(spline2.clone()), 0f32) - .add_spline(-05775f32, SplineValue::Spline(spline2), 0f32) + .add_spline(-0.5775f32, SplineValue::Spline(spline2), 0f32) .add_value(-0.375f32, 0f32, 0f32) .build() } @@ -278,13 +277,13 @@ fn create_continental_offset_spline<'a>( ) -> Spline<'a> { let spline = meth_42050( ridges.clone(), - lerp_32(h, 0.6f32, 1.5f32), + lerp(h, 0.6f32, 1.5f32), bl2, amplifier.clone(), ); let spline2 = meth_42050( ridges.clone(), - lerp_32(h, 0.6f32, 1f32), + lerp(h, 0.6f32, 1f32), bl2, amplifier.clone(), ); @@ -293,7 +292,7 @@ fn create_continental_offset_spline<'a>( ridges.clone(), continental - 0.15f32, 0.5f32 * h, - lerp_32(0.5f32, 0.5f32, 0.5f32) * h, + lerp(0.5f32, 0.5f32, 0.5f32) * h, 0.5f32 * h, 0.6f32 * h, 0.5f32, @@ -378,7 +377,7 @@ pub fn create_offset_spline<'a>( amplified: bool, ) -> Spline<'a> { let amplification = if amplified { - FloatAmplifier::Amplifier + FloatAmplifier::OffsetAmplifier } else { FloatAmplifier::Identity }; @@ -458,7 +457,7 @@ pub fn create_factor_spline<'a>( amplified: bool, ) -> Spline<'a> { let amplification = if amplified { - FloatAmplifier::Amplifier + FloatAmplifier::FactorAmplifier } else { FloatAmplifier::Identity }; @@ -524,7 +523,7 @@ pub fn create_jaggedness_spline<'a>( amplified: bool, ) -> Spline<'a> { let amplification = if amplified { - FloatAmplifier::Amplifier + FloatAmplifier::JaggednessAmplifier } else { FloatAmplifier::Identity }; @@ -561,3 +560,82 @@ pub fn create_jaggedness_spline<'a>( ) .build() } + +#[cfg(test)] +mod test { + use crate::world_gen::noise::{ + density::{ + spline::FloatAmplifier, terrain_helpers::create_offset_spline, BuiltInNoiseFunctions, + NoisePos, UnblendedNoisePos, + }, + BuiltInNoiseParams, + }; + + use super::create_continental_offset_spline; + + #[test] + fn test_offset_correctness() { + let noise_params = BuiltInNoiseParams::new(); + let noise_functions = BuiltInNoiseFunctions::new(&noise_params); + + let pos = NoisePos::Unblended(UnblendedNoisePos { x: 0, y: 0, z: 0 }); + + let spline = create_continental_offset_spline( + noise_functions.erosion_overworld.clone(), + noise_functions.ridges_folded_overworld.clone(), + 1f32, + 1f32, + 1f32, + 1f32, + 1f32, + 1f32, + true, + true, + FloatAmplifier::Identity, + ); + + assert_eq!(spline.apply(&pos), 1f32); + + let pos = NoisePos::Unblended(UnblendedNoisePos { + x: 10, + y: 10, + z: 10, + }); + + let spline = create_continental_offset_spline( + noise_functions.erosion_overworld.clone(), + noise_functions.ridges_folded_overworld.clone(), + 2f32, + 2f32, + 2f32, + 2f32, + 2f32, + 2f32, + true, + true, + FloatAmplifier::Identity, + ); + + assert_eq!(spline.apply(&pos), 2f32); + + let pos = NoisePos::Unblended(UnblendedNoisePos { x: 0, y: 0, z: 0 }); + + let spline = create_offset_spline( + noise_functions.continents_overworld.clone(), + noise_functions.erosion_overworld.clone(), + noise_functions.ridges_folded_overworld.clone(), + true, + ); + + assert_eq!(spline.apply(&pos), -0.1f32); + + let spline = create_offset_spline( + noise_functions.continents_overworld, + noise_functions.erosion_overworld.clone(), + noise_functions.ridges_folded_overworld.clone(), + false, + ); + + assert_eq!(spline.apply(&pos), -0.1f32); + } +} diff --git a/pumpkin-world/src/world_gen/noise/mod.rs b/pumpkin-world/src/world_gen/noise/mod.rs index bf8d73c9b..0f9de83f1 100644 --- a/pumpkin-world/src/world_gen/noise/mod.rs +++ b/pumpkin-world/src/world_gen/noise/mod.rs @@ -1,9 +1,6 @@ -#![allow(dead_code)] - use derive_getters::Getters; +use num_traits::Float; use perlin::DoublePerlinNoiseParameters; -pub mod chunk_sampler; -pub mod config; pub mod density; pub mod perlin; mod router; @@ -188,11 +185,10 @@ impl<'a> BuiltInNoiseParams<'a> { } } -pub fn lerp_32(delta: f32, start: f32, end: f32) -> f32 { - start + delta * (end - start) -} - -pub fn lerp(delta: f64, start: f64, end: f64) -> f64 { +pub fn lerp(delta: T, start: T, end: T) -> T +where + T: Float, +{ start + delta * (end - start) } diff --git a/pumpkin-world/src/world_gen/positions.rs b/pumpkin-world/src/world_gen/positions.rs new file mode 100644 index 000000000..4420c96d0 --- /dev/null +++ b/pumpkin-world/src/world_gen/positions.rs @@ -0,0 +1,28 @@ +pub mod chunk_pos { + use noise::Vector2; + + const MARKER: u64 = packed(Vector2 { + x: 1875066, + y: 1875066, + }); + + pub const fn packed(vec: Vector2) -> u64 { + (vec.x as u64 & 4294967295u64) | ((vec.y as u64 & 4294967295u64) << 32) + } + + pub const fn unpack_x(packed: u64) -> i32 { + (packed & 4294967295u64) as i32 + } + + pub const fn unpack_z(packed: u64) -> i32 { + ((packed >> 32) & 4294967295u64) as i32 + } + + pub const fn start_x(vec: Vector2) -> i32 { + vec.x << 4 + } + + pub const fn start_y(vec: Vector2) -> i32 { + vec.y << 4 + } +} diff --git a/pumpkin-world/src/world_gen/proto_chunk.rs b/pumpkin-world/src/world_gen/proto_chunk.rs new file mode 100644 index 000000000..fadb30083 --- /dev/null +++ b/pumpkin-world/src/world_gen/proto_chunk.rs @@ -0,0 +1,29 @@ +use pumpkin_core::math::vector3::Vector3; + +use crate::block::block_state::BlockState; + +pub struct ProtoChunk { + state: GenerationState, +} + +impl ProtoChunk { + pub fn get_block_state(&self, _pos: &Vector3) -> BlockState { + unimplemented!() + } +} + +#[derive(Clone, PartialEq, PartialOrd)] +pub enum GenerationState { + Empty, + StructureStart, + StructureRef, + Biome, + Noise, + Surface, + Carver, + Feature, + InitLight, + Light, + Spawn, + Full, +} diff --git a/pumpkin-world/src/world_gen/supplier.rs b/pumpkin-world/src/world_gen/supplier.rs deleted file mode 100644 index b5514ed8c..000000000 --- a/pumpkin-world/src/world_gen/supplier.rs +++ /dev/null @@ -1,26 +0,0 @@ -use enum_dispatch::enum_dispatch; - -use crate::biome::Biome; - -#[derive(Clone)] -#[enum_dispatch] -pub enum BiomeSupplier { - Static(StaticBiomeSupplier), -} - -#[enum_dispatch(BiomeSupplier)] -pub trait BiomeSupplierImpl { - fn biome(&self, x: i32, y: i32, z: i32, noise: &MultiNoiseSampler) -> Biome; -} - -#[derive(Clone)] -pub struct StaticBiomeSupplier {} -impl BiomeSupplierImpl for StaticBiomeSupplier { - fn biome(&self, _x: i32, _y: i32, _z: i32, _noise: &MultiNoiseSampler) -> Biome { - Biome::Plains - } -} - -pub struct MultiNoiseSampler { - -} From 708b7808a29271a71c694b56f06fdaa04c43c074 Mon Sep 17 00:00:00 2001 From: kralverde Date: Sat, 28 Sep 2024 00:15:13 -0400 Subject: [PATCH 08/11] finish tests for density functions --- .../src/world_gen/noise/density/mod.rs | 255 +++++++++++++++++- 1 file changed, 241 insertions(+), 14 deletions(-) diff --git a/pumpkin-world/src/world_gen/noise/density/mod.rs b/pumpkin-world/src/world_gen/noise/density/mod.rs index 4f67aa582..6ff47be97 100644 --- a/pumpkin-world/src/world_gen/noise/density/mod.rs +++ b/pumpkin-world/src/world_gen/noise/density/mod.rs @@ -662,7 +662,7 @@ fn sloped_cheese_function<'a>( DensityFunction::ClampedY(YClampedFunction { from: -64, to: 320, - from_val: 1.564, + from_val: 1.5f64, to_val: -1.5f64, }) .add(offset.clone()), @@ -795,7 +795,8 @@ pub enum DensityFunction<'a> { } impl<'a> DensityFunction<'a> { - pub fn clamp(&self, max: f64, min: f64) -> Self { + pub fn clamp(&self, min: f64, max: f64) -> Self { + assert!(min <= max); Self::Clamp(ClampFunction { input: Arc::new(self.clone()), min, @@ -1346,20 +1347,246 @@ mod test { 0.9962499737739563f64 ); - assert_eq!(noise_functions.y.sample(&pos), 0f64); - assert_eq!(noise_functions.y.min(), -4064f64); - assert_eq!(noise_functions.y.max(), 4062f64); + assert_eq!( + noise_functions.factor_overworld.sample(&pos), + 5.549900531768799f64 + ); + assert_eq!(noise_functions.factor_overworld.min(), 0.625f64); + assert_eq!(noise_functions.factor_overworld.max(), 6.300000190734863f64); - assert_eq!(noise_functions.y.sample(&pos), 0f64); - assert_eq!(noise_functions.y.min(), -4064f64); - assert_eq!(noise_functions.y.max(), 4062f64); + assert_eq!(noise_functions.jaggedness_overworld.sample(&pos), 0f64); + assert_eq!(noise_functions.jaggedness_overworld.min(), 0f64); + assert_eq!( + noise_functions.jaggedness_overworld.max(), + 0.6299999952316284f64 + ); - assert_eq!(noise_functions.y.sample(&pos), 0f64); - assert_eq!(noise_functions.y.min(), -4064f64); - assert_eq!(noise_functions.y.max(), 4062f64); + assert_eq!( + noise_functions.depth_overworld.sample(&pos), + 0.3962499722838402f64 + ); + assert_eq!( + noise_functions.depth_overworld.min(), + -2.8752707839012146f64 + ); + assert_eq!(noise_functions.depth_overworld.max(), 2.4962499737739563f64); - assert_eq!(noise_functions.y.sample(&pos), 0f64); - assert_eq!(noise_functions.y.min(), -4064f64); - assert_eq!(noise_functions.y.max(), 4062f64); + assert_eq!( + noise_functions.sloped_cheese_overworld.sample(&pos), + 8.849428998431454f64 + ); + assert_eq!( + noise_functions.sloped_cheese_overworld.min(), + -109.63470657711427f64 + ); + assert_eq!( + noise_functions.sloped_cheese_overworld.max(), + 182.2090019645691f64 + ); + + assert_eq!( + noise_functions + .continents_overworld_large_biome + .sample(&pos), + 0f64 + ); + assert_eq!( + noise_functions.continents_overworld_large_biome.min(), + -2f64 + ); + assert_eq!(noise_functions.continents_overworld_large_biome.max(), 2f64); + + assert_eq!( + noise_functions.erosion_overworld_large_biome.sample(&pos), + 0f64 + ); + assert_eq!(noise_functions.erosion_overworld_large_biome.min(), -2f64); + assert_eq!(noise_functions.erosion_overworld_large_biome.max(), 2f64); + + assert_eq!( + noise_functions.offset_overworld_large_biome.sample(&pos), + -0.6037500277161598f64 + ); + assert_eq!( + noise_functions.offset_overworld_large_biome.min(), + -1.3752707839012146f64 + ); + assert_eq!( + noise_functions.offset_overworld_large_biome.max(), + 0.9962499737739563f64 + ); + + assert_eq!( + noise_functions.factor_overworld_large_biome.sample(&pos), + 5.549900531768799f64 + ); + assert_eq!(noise_functions.factor_overworld_large_biome.min(), 0.625f64); + assert_eq!( + noise_functions.factor_overworld_large_biome.max(), + 6.300000190734863f64 + ); + + assert_eq!( + noise_functions + .jaggedness_overworld_large_biome + .sample(&pos), + 0f64 + ); + assert_eq!(noise_functions.jaggedness_overworld_large_biome.min(), 0f64); + assert_eq!( + noise_functions.jaggedness_overworld_large_biome.max(), + 0.6299999952316284f64 + ); + + assert_eq!( + noise_functions.depth_overworld_large_biome.sample(&pos), + 0.3962499722838402f64 + ); + assert_eq!( + noise_functions.depth_overworld_large_biome.min(), + -2.8752707839012146f64 + ); + assert_eq!( + noise_functions.depth_overworld_large_biome.max(), + 2.4962499737739563f64 + ); + + assert_eq!( + noise_functions + .sloped_cheese_overworld_large_biome + .sample(&pos), + 8.849428998431454f64 + ); + assert_eq!( + noise_functions.sloped_cheese_overworld_large_biome.min(), + -109.63470657711427f64 + ); + assert_eq!( + noise_functions.sloped_cheese_overworld_large_biome.max(), + 182.2090019645691f64 + ); + + assert_eq!( + noise_functions.offset_overworld_amplified.sample(&pos), + -0.6037500277161598f64 + ); + assert_eq!( + noise_functions.offset_overworld_amplified.min(), + -1.3752707839012146f64 + ); + assert_eq!( + noise_functions.offset_overworld_amplified.max(), + 2.640259087085724f64 + ); + + assert_eq!( + noise_functions.factor_overworld_amplified.sample(&pos), + 0.6516130566596985f64 + ); + assert_eq!( + noise_functions.factor_overworld_amplified.min(), + 0.13888883590698242f64 + ); + assert_eq!( + noise_functions.factor_overworld_amplified.max(), + 6.300000190734863f64 + ); + + assert_eq!( + noise_functions.jaggedness_overworld_amplified.sample(&pos), + 0f64 + ); + assert_eq!(noise_functions.jaggedness_overworld_amplified.min(), 0f64); + assert_eq!( + noise_functions.jaggedness_overworld_amplified.max(), + 1.2599999904632568f64 + ); + + assert_eq!( + noise_functions.depth_overworld_amplified.sample(&pos), + 0.3962499722838402f64 + ); + assert_eq!( + noise_functions.depth_overworld_amplified.min(), + -2.8752707839012146f64 + ); + assert_eq!( + noise_functions.depth_overworld_amplified.max(), + 4.140259087085724f64 + ); + + assert_eq!( + noise_functions + .sloped_cheese_overworld_amplified + .sample(&pos), + 1.085643893430405f64 + ); + assert_eq!( + noise_functions.sloped_cheese_overworld_amplified.min(), + -113.6037066672365f64 + ); + assert_eq!( + noise_functions.sloped_cheese_overworld_amplified.max(), + 255.39003359528283f64 + ); + + assert_eq!( + noise_functions.sloped_cheese_end.sample(&pos), + 0.6153372708656294f64 + ); + assert_eq!( + noise_functions.sloped_cheese_end.min(), + -173.94674999999998f64 + ); + assert_eq!( + noise_functions.sloped_cheese_end.max(), + 173.66549999999998f64 + ); + + assert_eq!( + noise_functions + .caves_spaghetti_roughness_function_overworld + .sample(&pos), + 0.020000000000000004f64 + ); + assert_eq!( + noise_functions + .caves_spaghetti_roughness_function_overworld + .min(), + -0.24000000000000005f64 + ); + assert_eq!( + noise_functions + .caves_spaghetti_roughness_function_overworld + .max(), + 0.08000000000000002f64 + ); + + assert_eq!( + noise_functions.caves_entrances_overworld.sample(&pos), + -0.056499999999999995f64 + ); + assert_eq!(noise_functions.caves_entrances_overworld.min(), -1.63f64); + // NOTE: this doesn't match java but max/min is never used anywhere so + assert_eq!(noise_functions.caves_entrances_overworld.max(), 1.08f64); + + assert_eq!( + noise_functions.caves_noodle_overworld.sample(&pos), + -0.07500000000000001f64 + ); + assert_eq!(noise_functions.caves_noodle_overworld.min(), -0.125f64); + assert_eq!(noise_functions.caves_noodle_overworld.max(), 64f64); + + assert_eq!(noise_functions.caves_pillars_overworld.sample(&pos), -0.16637500000000005f64); + assert_eq!(noise_functions.caves_pillars_overworld.min(), -31.44487500000001f64); + assert_eq!(noise_functions.caves_pillars_overworld.max(), 22.460625000000007f64); + + assert_eq!(noise_functions.caves_spaghetti_2d_thickness_modular_overworld.sample(&pos), -0.95f64); + assert_eq!(noise_functions.caves_spaghetti_2d_thickness_modular_overworld.min(), -1.65f64); + assert_eq!(noise_functions.caves_spaghetti_2d_thickness_modular_overworld.max(), -0.2499999999999999f64); + + assert_eq!(noise_functions.caves_spaghetti_2d_overworld.sample(&pos), -0.07885f64); + assert_eq!(noise_functions.caves_spaghetti_2d_overworld.min(), -1f64); + assert_eq!(noise_functions.caves_spaghetti_2d_overworld.max(), 1f64); } } From c17b1002d8ff48d0bc215de6a48f1e7128816528 Mon Sep 17 00:00:00 2001 From: kralverde Date: Sat, 28 Sep 2024 00:28:14 -0400 Subject: [PATCH 09/11] fix fmt check --- .../src/world_gen/noise/density/mod.rs | 41 +++++++++++++++---- 1 file changed, 34 insertions(+), 7 deletions(-) diff --git a/pumpkin-world/src/world_gen/noise/density/mod.rs b/pumpkin-world/src/world_gen/noise/density/mod.rs index 6ff47be97..a2edc99bc 100644 --- a/pumpkin-world/src/world_gen/noise/density/mod.rs +++ b/pumpkin-world/src/world_gen/noise/density/mod.rs @@ -1577,15 +1577,42 @@ mod test { assert_eq!(noise_functions.caves_noodle_overworld.min(), -0.125f64); assert_eq!(noise_functions.caves_noodle_overworld.max(), 64f64); - assert_eq!(noise_functions.caves_pillars_overworld.sample(&pos), -0.16637500000000005f64); - assert_eq!(noise_functions.caves_pillars_overworld.min(), -31.44487500000001f64); - assert_eq!(noise_functions.caves_pillars_overworld.max(), 22.460625000000007f64); + assert_eq!( + noise_functions.caves_pillars_overworld.sample(&pos), + -0.16637500000000005f64 + ); + assert_eq!( + noise_functions.caves_pillars_overworld.min(), + -31.44487500000001f64 + ); + assert_eq!( + noise_functions.caves_pillars_overworld.max(), + 22.460625000000007f64 + ); - assert_eq!(noise_functions.caves_spaghetti_2d_thickness_modular_overworld.sample(&pos), -0.95f64); - assert_eq!(noise_functions.caves_spaghetti_2d_thickness_modular_overworld.min(), -1.65f64); - assert_eq!(noise_functions.caves_spaghetti_2d_thickness_modular_overworld.max(), -0.2499999999999999f64); + assert_eq!( + noise_functions + .caves_spaghetti_2d_thickness_modular_overworld + .sample(&pos), + -0.95f64 + ); + assert_eq!( + noise_functions + .caves_spaghetti_2d_thickness_modular_overworld + .min(), + -1.65f64 + ); + assert_eq!( + noise_functions + .caves_spaghetti_2d_thickness_modular_overworld + .max(), + -0.2499999999999999f64 + ); - assert_eq!(noise_functions.caves_spaghetti_2d_overworld.sample(&pos), -0.07885f64); + assert_eq!( + noise_functions.caves_spaghetti_2d_overworld.sample(&pos), + -0.07885f64 + ); assert_eq!(noise_functions.caves_spaghetti_2d_overworld.min(), -1f64); assert_eq!(noise_functions.caves_spaghetti_2d_overworld.max(), 1f64); } From 90c19ae744db93a1dda61ae5c0bdf33a414eef93 Mon Sep 17 00:00:00 2001 From: kralverde Date: Thu, 3 Oct 2024 16:32:06 -0400 Subject: [PATCH 10/11] remove git diff and hypot --- pumpkin-core/src/math/mod.rs | 8 -------- pumpkin-world/src/block/block_state.rs | 1 - 2 files changed, 9 deletions(-) diff --git a/pumpkin-core/src/math/mod.rs b/pumpkin-core/src/math/mod.rs index 29ac634d5..de67a8532 100644 --- a/pumpkin-core/src/math/mod.rs +++ b/pumpkin-core/src/math/mod.rs @@ -30,11 +30,3 @@ pub fn magnitude(a: f64, b: f64, c: f64) -> f64 { pub const fn get_section_cord(coord: i32) -> i32 { coord >> 4 } - -pub fn squared_hypot(a: f64, b: f64) -> f64 { - a * a + b * b -} - -pub fn hypot(a: f64, b: f64) -> f64 { - squared_hypot(a, b).sqrt() -} diff --git a/pumpkin-world/src/block/block_state.rs b/pumpkin-world/src/block/block_state.rs index 8e9a59e5d..df79018c7 100644 --- a/pumpkin-world/src/block/block_state.rs +++ b/pumpkin-world/src/block/block_state.rs @@ -1,4 +1,3 @@ -<<<<<<< HEAD use std::collections::HashMap; use thiserror::Error; From 30fdb14b8db93b3b6415686565aec837a4b29928 Mon Sep 17 00:00:00 2001 From: kralverde Date: Sat, 12 Oct 2024 10:07:34 -0400 Subject: [PATCH 11/11] rename placeholder values --- .../noise/density/terrain_helpers.rs | 72 ++++---- pumpkin-world/src/world_gen/noise/router.rs | 156 ++++++++++-------- 2 files changed, 126 insertions(+), 102 deletions(-) diff --git a/pumpkin-world/src/world_gen/noise/density/terrain_helpers.rs b/pumpkin-world/src/world_gen/noise/density/terrain_helpers.rs index 432052cb6..5e1fdec4d 100644 --- a/pumpkin-world/src/world_gen/noise/density/terrain_helpers.rs +++ b/pumpkin-world/src/world_gen/noise/density/terrain_helpers.rs @@ -24,7 +24,7 @@ fn get_offset_value(f: f32, g: f32, h: f32) -> f32 { } #[inline] -fn meth_42045(f: f32) -> f32 { +fn skew_map(f: f32) -> f32 { let k = 1f32 - (1f32 - f) * 0.5f32; let l = 0.5f32 * (1f32 - f); @@ -32,11 +32,11 @@ fn meth_42045(f: f32) -> f32 { } #[inline] -fn meth_42047(f: f32, g: f32, h: f32, i: f32) -> f32 { +fn diff_quot(f: f32, g: f32, h: f32, i: f32) -> f32 { (g - f) / (i - h) } -fn meth_42050( +fn create_ridges_spline( function: Arc, f: f32, bl: bool, @@ -47,25 +47,25 @@ fn meth_42050( let i = get_offset_value(-1f32, f, -0.7f32); let k = get_offset_value(1f32, f, -0.7f32); - let l = meth_42045(f); + let l = skew_map(f); let builder = if -0.65f32 < l && l < 1f32 { let n = get_offset_value(-0.65f32, f, -0.7f32); let p = get_offset_value(-0.75f32, f, -0.7f32); - let q = meth_42047(i, p, -1f32, -0.75f32); + let q = diff_quot(i, p, -1f32, -0.75f32); let builder = builder .add_value(-1f32, i, q) .add_value(-0.75f32, p, 0f32) .add_value(-0.65f32, n, 0f32); let r = get_offset_value(l, f, -0.7f32); - let s = meth_42047(r, k, l, 1f32); + let s = diff_quot(r, k, l, 1f32); builder .add_value(l - 0.01f32, r, 0f32) .add_value(l, r, s) .add_value(1f32, k, s) } else { - let n = meth_42047(i, k, -1f32, 1f32); + let n = diff_quot(i, k, -1f32, 1f32); let builder = if bl { builder .add_value(-1f32, 0.2f32.max(i), 0f32) @@ -81,7 +81,7 @@ fn meth_42050( } #[allow(clippy::too_many_arguments)] -fn meth_42048( +fn create_standard_spline( ridges: Arc, continental: f32, f: f32, @@ -102,7 +102,7 @@ fn meth_42048( .build() } -fn method_42054<'a>( +fn create_total_spline<'a>( erosion: Arc>, ridges: Arc>, ridges_folded: Arc>, @@ -179,7 +179,7 @@ fn method_42054<'a>( builder.build() } -fn method_42052<'a>( +fn create_folded_ridges_spline<'a>( ridges: Arc>, ridges_folded: Arc>, f: f32, @@ -196,7 +196,11 @@ fn method_42052<'a>( let builder = if g > 0f32 { builder.add_spline( j, - SplineValue::Spline(method_42049(ridges.clone(), f, amplifier.clone())), + SplineValue::Spline(create_ridges_part_spline( + ridges.clone(), + f, + amplifier.clone(), + )), 0f32, ) } else { @@ -206,7 +210,11 @@ fn method_42052<'a>( let builder = if f > 0f32 { builder.add_spline( 1f32, - SplineValue::Spline(method_42049(ridges.clone(), f, amplifier.clone())), + SplineValue::Spline(create_ridges_part_spline( + ridges.clone(), + f, + amplifier.clone(), + )), 0f32, ) } else { @@ -217,7 +225,11 @@ fn method_42052<'a>( } #[inline] -fn method_42049(ridges: Arc, f: f32, amplifier: FloatAmplifier) -> Spline { +fn create_ridges_part_spline( + ridges: Arc, + f: f32, + amplifier: FloatAmplifier, +) -> Spline { let g = 0.63f32 * f; let h = 0.3f32 * f; SplineBuilder::new(ridges, amplifier) @@ -228,7 +240,7 @@ fn method_42049(ridges: Arc, f: f32, amplifier: FloatAmplifier) #[allow(clippy::too_many_arguments)] #[inline] -fn method_42053<'a>( +fn create_eroded_ridges_spline<'a>( erosion: Arc>, ridges: Arc>, ridges_folded: Arc>, @@ -238,14 +250,14 @@ fn method_42053<'a>( i: f32, amplifier: FloatAmplifier, ) -> Spline<'a> { - let spline = method_42052( + let spline = create_folded_ridges_spline( ridges.clone(), ridges_folded.clone(), f, h, amplifier.clone(), ); - let spline2 = method_42052( + let spline2 = create_folded_ridges_spline( ridges.clone(), ridges_folded.clone(), g, @@ -275,20 +287,20 @@ fn create_continental_offset_spline<'a>( bl2: bool, amplifier: FloatAmplifier, ) -> Spline<'a> { - let spline = meth_42050( + let spline = create_ridges_spline( ridges.clone(), lerp(h, 0.6f32, 1.5f32), bl2, amplifier.clone(), ); - let spline2 = meth_42050( + let spline2 = create_ridges_spline( ridges.clone(), lerp(h, 0.6f32, 1f32), bl2, amplifier.clone(), ); - let spline3 = meth_42050(ridges.clone(), h, bl2, amplifier.clone()); - let spline4 = meth_42048( + let spline3 = create_ridges_spline(ridges.clone(), h, bl2, amplifier.clone()); + let spline4 = create_standard_spline( ridges.clone(), continental - 0.15f32, 0.5f32 * h, @@ -299,7 +311,7 @@ fn create_continental_offset_spline<'a>( amplifier.clone(), ); - let spline5 = meth_42048( + let spline5 = create_standard_spline( ridges.clone(), continental, i * h, @@ -309,7 +321,7 @@ fn create_continental_offset_spline<'a>( 0.5f32, amplifier.clone(), ); - let spline6 = meth_42048( + let spline6 = create_standard_spline( ridges.clone(), continental, i, @@ -319,7 +331,7 @@ fn create_continental_offset_spline<'a>( 0.5f32, amplifier.clone(), ); - let spline7 = meth_42048( + let spline7 = create_standard_spline( ridges.clone(), continental, i, @@ -335,7 +347,7 @@ fn create_continental_offset_spline<'a>( .add_spline(-0.4f32, SplineValue::Spline(spline6.clone()), 0f32) .add_value(0f32, g + 0.07f32, 0f32) .build(); - let spline9 = meth_42048( + let spline9 = create_standard_spline( ridges.clone(), -0.02f32, j, @@ -466,7 +478,7 @@ pub fn create_factor_spline<'a>( .add_value(-0.19f32, 3.95f32, 0f32) .add_spline( -0.15f32, - SplineValue::Spline(method_42054( + SplineValue::Spline(create_total_spline( erosion.clone(), ridges.clone(), ridges_folded.clone(), @@ -478,7 +490,7 @@ pub fn create_factor_spline<'a>( ) .add_spline( -0.1f32, - SplineValue::Spline(method_42054( + SplineValue::Spline(create_total_spline( erosion.clone(), ridges.clone(), ridges_folded.clone(), @@ -490,7 +502,7 @@ pub fn create_factor_spline<'a>( ) .add_spline( 0.03f32, - SplineValue::Spline(method_42054( + SplineValue::Spline(create_total_spline( erosion.clone(), ridges.clone(), ridges_folded.clone(), @@ -502,7 +514,7 @@ pub fn create_factor_spline<'a>( ) .add_spline( 0.06f32, - SplineValue::Spline(method_42054( + SplineValue::Spline(create_total_spline( erosion, ridges, ridges_folded, @@ -532,7 +544,7 @@ pub fn create_jaggedness_spline<'a>( .add_value(-0.11f32, 0f32, 0f32) .add_spline( 0.03f32, - SplineValue::Spline(method_42053( + SplineValue::Spline(create_eroded_ridges_spline( erosion.clone(), ridges.clone(), ridges_folded.clone(), @@ -546,7 +558,7 @@ pub fn create_jaggedness_spline<'a>( ) .add_spline( 0.65f32, - SplineValue::Spline(method_42053( + SplineValue::Spline(create_eroded_ridges_spline( erosion, ridges, ridges_folded, diff --git a/pumpkin-world/src/world_gen/noise/router.rs b/pumpkin-world/src/world_gen/noise/router.rs index d3307454f..92be5d555 100644 --- a/pumpkin-world/src/world_gen/noise/router.rs +++ b/pumpkin-world/src/world_gen/noise/router.rs @@ -59,7 +59,7 @@ impl<'a> NoiseRouter<'a> { large_biomes: bool, amplified: bool, ) -> Self { - let function = Arc::new(DensityFunction::Noise(NoiseFunction::new( + let aquifier_barrier = Arc::new(DensityFunction::Noise(NoiseFunction::new( Arc::new(InternalNoise::new( noise_params.aquifer_barrier().clone(), None, @@ -68,16 +68,17 @@ impl<'a> NoiseRouter<'a> { 0.5f64, ))); - let function2 = Arc::new(DensityFunction::Noise(NoiseFunction::new( - Arc::new(InternalNoise::new( - noise_params.aquifer_fluid_level_floodedness().clone(), - None, - )), - 1f64, - 0.67f64, - ))); + let aquifier_fluid_level_floodedness = + Arc::new(DensityFunction::Noise(NoiseFunction::new( + Arc::new(InternalNoise::new( + noise_params.aquifer_fluid_level_floodedness().clone(), + None, + )), + 1f64, + 0.67f64, + ))); - let function3 = Arc::new(DensityFunction::Noise(NoiseFunction::new( + let aquifer_fluid_level_spread = Arc::new(DensityFunction::Noise(NoiseFunction::new( Arc::new(InternalNoise::new( noise_params.aquifer_fluid_level_spread().clone(), None, @@ -86,7 +87,7 @@ impl<'a> NoiseRouter<'a> { 0.7142857142857143f64, ))); - let function4 = Arc::new(DensityFunction::Noise(NoiseFunction::new( + let aquifer_lava = Arc::new(DensityFunction::Noise(NoiseFunction::new( Arc::new(InternalNoise::new( noise_params.aquifer_lava().clone(), None, @@ -95,13 +96,13 @@ impl<'a> NoiseRouter<'a> { 1f64, ))); - let function5 = noise_funcs.shift_x().clone(); - let function6 = noise_funcs.shift_z().clone(); + let shift_x = noise_funcs.shift_x().clone(); + let shift_z = noise_funcs.shift_z().clone(); - let function7 = Arc::new(DensityFunction::ShiftedNoise(ShiftedNoiseFunction::new( - function5.clone(), + let temperature = Arc::new(DensityFunction::ShiftedNoise(ShiftedNoiseFunction::new( + shift_x.clone(), noise_funcs.zero().clone(), - function6.clone(), + shift_z.clone(), 0.25f64, 0f64, Arc::new(InternalNoise::new( @@ -114,10 +115,10 @@ impl<'a> NoiseRouter<'a> { )), ))); - let function8 = Arc::new(DensityFunction::ShiftedNoise(ShiftedNoiseFunction::new( - function5.clone(), + let vegetation = Arc::new(DensityFunction::ShiftedNoise(ShiftedNoiseFunction::new( + shift_x.clone(), noise_funcs.zero().clone(), - function6.clone(), + shift_z.clone(), 0.25f64, 0f64, Arc::new(InternalNoise::new( @@ -130,7 +131,7 @@ impl<'a> NoiseRouter<'a> { )), ))); - let function9 = if large_biomes { + let factor_overworld = if large_biomes { noise_funcs.factor_overworld_large_biome().clone() } else if amplified { noise_funcs.factor_overworld_amplified().clone() @@ -138,7 +139,7 @@ impl<'a> NoiseRouter<'a> { noise_funcs.factor_overworld().clone() }; - let function10 = if large_biomes { + let depth_overworld = if large_biomes { noise_funcs.depth_overworld_large_biome().clone() } else if amplified { noise_funcs.depth_overworld_amplified().clone() @@ -146,18 +147,18 @@ impl<'a> NoiseRouter<'a> { noise_funcs.depth_overworld().clone() }; - let function11 = Arc::new( + let mapped_depth_overworld = Arc::new( DensityFunction::Constant(ConstantFunction::new(4f64)).mul(Arc::new( - function10 + depth_overworld .mul(Arc::new(DensityFunction::Wrapper(WrapperFunction::new( - function9, + factor_overworld, WrapperType::Cache2D, )))) .quarter_negative(), )), ); - let function12 = if large_biomes { + let sloped_cheese_overworld = if large_biomes { noise_funcs.sloped_cheese_overworld_large_biome().clone() } else if amplified { noise_funcs.sloped_cheese_overworld_amplified().clone() @@ -165,31 +166,38 @@ impl<'a> NoiseRouter<'a> { noise_funcs.sloped_cheese_overworld().clone() }; - let function13 = Arc::new( - function12.binary_min(Arc::new( + let cave_entrances_overworld = Arc::new( + sloped_cheese_overworld.binary_min(Arc::new( DensityFunction::Constant(ConstantFunction::new(5f64)) .mul(noise_funcs.caves_entrances_overworld().clone()), )), ); - let function14 = Arc::new(DensityFunction::Range(RangeFunction::new( - function12.clone(), + let mapped_cave_entraces_overworld = Arc::new(DensityFunction::Range(RangeFunction::new( + sloped_cheese_overworld.clone(), -1000000f64, 1.5625f64, - function13, - Arc::new(create_caves(noise_funcs, noise_params, function12)), + cave_entrances_overworld, + Arc::new(create_caves( + noise_funcs, + noise_params, + sloped_cheese_overworld, + )), ))); - let function15 = Arc::new( - apply_blend_density(apply_surface_slides(amplified, function14)) - .binary_min(noise_funcs.caves_noodle_overworld().clone()), + let blended_cave_entrances_overworld = Arc::new( + apply_blend_density(apply_surface_slides( + amplified, + mapped_cave_entraces_overworld, + )) + .binary_min(noise_funcs.caves_noodle_overworld().clone()), ); - let function16 = noise_funcs.y().clone(); + let y = noise_funcs.y().clone(); let i = VeinType::overall_min_y(); let j = VeinType::overall_max_y(); - let function17 = Arc::new(veritcal_range_choice( - function16.clone(), + let ore_veininess = Arc::new(veritcal_range_choice( + y.clone(), Arc::new(DensityFunction::Noise(NoiseFunction::new( Arc::new(InternalNoise::new( noise_params.ore_veininess().clone(), @@ -203,9 +211,9 @@ impl<'a> NoiseRouter<'a> { 0, )); - let function18 = Arc::new( + let ore_vein_a = Arc::new( veritcal_range_choice( - function16.clone(), + y.clone(), Arc::new(DensityFunction::Noise(NoiseFunction::new( Arc::new(InternalNoise::new(noise_params.ore_vein_a().clone(), None)), 4f64, @@ -218,9 +226,9 @@ impl<'a> NoiseRouter<'a> { .abs(), ); - let function19 = Arc::new( + let ore_vein_b = Arc::new( veritcal_range_choice( - function16, + y, Arc::new(DensityFunction::Noise(NoiseFunction::new( Arc::new(InternalNoise::new(noise_params.ore_vein_b().clone(), None)), 4f64, @@ -233,24 +241,24 @@ impl<'a> NoiseRouter<'a> { .abs(), ); - let function20 = Arc::new( + let ore_vein = Arc::new( DensityFunction::Constant(ConstantFunction::new(-0.08f64)) - .add(Arc::new(function18.binary_max(function19))), + .add(Arc::new(ore_vein_a.binary_max(ore_vein_b))), ); - let function21 = Arc::new(DensityFunction::Noise(NoiseFunction::new( + let ore_gap = Arc::new(DensityFunction::Noise(NoiseFunction::new( Arc::new(InternalNoise::new(noise_params.ore_gap().clone(), None)), 1f64, 1f64, ))); Self { - barrier: function, - fluid_level_floodedness: function2, - fluid_level_spread: function3, - lava: function4, - temperature: function7, - vegetation: function8, + barrier: aquifier_barrier, + fluid_level_floodedness: aquifier_fluid_level_floodedness, + fluid_level_spread: aquifer_fluid_level_spread, + lava: aquifer_lava, + temperature, + vegetation, continents: if large_biomes { noise_funcs.continents_overworld_large_biome().clone() } else { @@ -261,16 +269,20 @@ impl<'a> NoiseRouter<'a> { } else { noise_funcs.erosion_overworld().clone() }, - depth: function10, + depth: depth_overworld, ridges: noise_funcs.ridges_overworld().clone(), internal_density: Arc::new(apply_surface_slides( amplified, - Arc::new(function11.add_const(-0.703125).clamp(-64f64, 64f64)), + Arc::new( + mapped_depth_overworld + .add_const(-0.703125) + .clamp(-64f64, 64f64), + ), )), - final_densitiy: function15, - vein_toggle: function17, - vein_ridged: function20, - vein_gap: function21, + final_densitiy: blended_cave_entrances_overworld, + vein_toggle: ore_veininess, + vein_ridged: ore_vein, + vein_gap: ore_gap, } } } @@ -322,26 +334,26 @@ fn create_caves<'a>( noise_params: &BuiltInNoiseParams<'a>, sloped_cheese: Arc>, ) -> DensityFunction<'a> { - let function = noise_funcs.caves_spaghetti_2d_overworld().clone(); - let function2 = noise_funcs + let caves_spaghetti_2d = noise_funcs.caves_spaghetti_2d_overworld().clone(); + let caves_spaghetti_roughness = noise_funcs .caves_spaghetti_roughness_function_overworld() .clone(); - let function3 = Arc::new(DensityFunction::Noise(NoiseFunction::new( + let cave_layer = Arc::new(DensityFunction::Noise(NoiseFunction::new( Arc::new(InternalNoise::new(noise_params.cave_layer().clone(), None)), 1f64, 8f64, ))); - let function4 = Arc::new( - DensityFunction::Constant(ConstantFunction::new(4f64)).mul(Arc::new(function3.square())), + let scaled_cave_layer = Arc::new( + DensityFunction::Constant(ConstantFunction::new(4f64)).mul(Arc::new(cave_layer.square())), ); - let function5 = Arc::new(DensityFunction::Noise(NoiseFunction::new( + let cave_cheese = Arc::new(DensityFunction::Noise(NoiseFunction::new( Arc::new(InternalNoise::new(noise_params.cave_cheese().clone(), None)), 1f64, 0.6666666666666666f64, ))); - let function6 = Arc::new( + let scaled_cave_cheese = Arc::new( DensityFunction::Constant(ConstantFunction::new(0.27f64)) - .add(function5) + .add(cave_cheese) .clamp(-1f64, 1f64) .add(Arc::new( DensityFunction::Constant(ConstantFunction::new(1.5f64)) @@ -352,19 +364,19 @@ fn create_caves<'a>( .clamp(0f64, 0.5f64), )), ); - let function7 = Arc::new(function4.add(function6)); - let function8 = function7 + let final_cave_layer = Arc::new(scaled_cave_layer.add(scaled_cave_cheese)); + let cave_entrances = final_cave_layer .binary_min(noise_funcs.caves_entrances_overworld().clone()) - .binary_min(Arc::new(function.add(function2))); - let function9 = noise_funcs.caves_pillars_overworld().clone(); - let function10 = Arc::new(DensityFunction::Range(RangeFunction::new( - function9.clone(), + .binary_min(Arc::new(caves_spaghetti_2d.add(caves_spaghetti_roughness))); + let pillars = noise_funcs.caves_pillars_overworld().clone(); + let scaled_pillars = Arc::new(DensityFunction::Range(RangeFunction::new( + pillars.clone(), -1000000f64, 0.03f64, Arc::new(DensityFunction::Constant(ConstantFunction::new( -1000000f64, ))), - function9, + pillars, ))); - function8.binary_max(function10) + cave_entrances.binary_max(scaled_pillars) }