Compare commits
20 Commits
generate-n
...
per-tile-c
| Author | SHA1 | Date | |
|---|---|---|---|
| 9a76bef2a4 | |||
| f060c67b74 | |||
| 4e9a35adc6 | |||
| 58a9f62dca | |||
| cd4c9f2acf | |||
| 7b6cae39b7 | |||
| ed94f77323 | |||
| b2622f2126 | |||
| 7732d5ebda | |||
| 1e8aaa502d | |||
| d742ad8a28 | |||
| a933ef791b | |||
| 55226f0181 | |||
| 771c212798 | |||
| c434b2eab0 | |||
| 9de7bc53d0 | |||
| 279b7c0418 | |||
| 28047ebdb5 | |||
| 4c8b52a3ff | |||
| 1547e083a9 |
8
.vscode/launch.json
vendored
8
.vscode/launch.json
vendored
@@ -13,7 +13,13 @@
|
|||||||
"program": "${workspaceRoot}/target/debug/phos.exe",
|
"program": "${workspaceRoot}/target/debug/phos.exe",
|
||||||
"args": [],
|
"args": [],
|
||||||
"cwd": "${workspaceRoot}/target/debug",
|
"cwd": "${workspaceRoot}/target/debug",
|
||||||
"preLaunchTask": "Build"
|
"preLaunchTask": "Build",
|
||||||
|
// "environment": [
|
||||||
|
// {
|
||||||
|
// "name": "RUST_BACKTRACE",
|
||||||
|
// "value": "1"
|
||||||
|
// }
|
||||||
|
// ]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
496
Cargo.lock
generated
496
Cargo.lock
generated
@@ -331,13 +331,13 @@ version = "0.23.4"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bb36c3adb02afa4496085250d437217b2a5280d8dd464937c6c5b21bc88830c0"
|
checksum = "bb36c3adb02afa4496085250d437217b2a5280d8dd464937c6c5b21bc88830c0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bevy-inspector-egui-derive",
|
"bevy-inspector-egui-derive 0.23.0",
|
||||||
"bevy_app",
|
"bevy_app",
|
||||||
"bevy_asset",
|
"bevy_asset",
|
||||||
"bevy_core",
|
"bevy_core",
|
||||||
"bevy_core_pipeline",
|
"bevy_core_pipeline",
|
||||||
"bevy_ecs",
|
"bevy_ecs",
|
||||||
"bevy_egui",
|
"bevy_egui 0.25.0",
|
||||||
"bevy_hierarchy",
|
"bevy_hierarchy",
|
||||||
"bevy_log",
|
"bevy_log",
|
||||||
"bevy_math",
|
"bevy_math",
|
||||||
@@ -347,7 +347,38 @@ dependencies = [
|
|||||||
"bevy_time",
|
"bevy_time",
|
||||||
"bevy_utils",
|
"bevy_utils",
|
||||||
"bevy_window",
|
"bevy_window",
|
||||||
"egui",
|
"egui 0.26.2",
|
||||||
|
"image",
|
||||||
|
"once_cell",
|
||||||
|
"pretty-type-name",
|
||||||
|
"smallvec",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bevy-inspector-egui"
|
||||||
|
version = "0.24.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a437cb56d4ca4d3b770889e0bd9c464cfd8e68ef370e232bd39cb4f40d880a7f"
|
||||||
|
dependencies = [
|
||||||
|
"bevy-inspector-egui-derive 0.24.0",
|
||||||
|
"bevy_app",
|
||||||
|
"bevy_asset",
|
||||||
|
"bevy_core",
|
||||||
|
"bevy_core_pipeline",
|
||||||
|
"bevy_ecs",
|
||||||
|
"bevy_egui 0.27.0",
|
||||||
|
"bevy_hierarchy",
|
||||||
|
"bevy_log",
|
||||||
|
"bevy_math",
|
||||||
|
"bevy_pbr",
|
||||||
|
"bevy_reflect",
|
||||||
|
"bevy_render",
|
||||||
|
"bevy_time",
|
||||||
|
"bevy_utils",
|
||||||
|
"bevy_window",
|
||||||
|
"egui 0.27.2",
|
||||||
|
"egui-dropdown",
|
||||||
|
"fuzzy-matcher",
|
||||||
"image",
|
"image",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"pretty-type-name",
|
"pretty-type-name",
|
||||||
@@ -365,6 +396,17 @@ dependencies = [
|
|||||||
"syn 2.0.55",
|
"syn 2.0.55",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bevy-inspector-egui-derive"
|
||||||
|
version = "0.24.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "975d905908c2d621b5a55a6925ac331feac19df430e4c8818b35ef1b95142b14"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.55",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bevy_a11y"
|
name = "bevy_a11y"
|
||||||
version = "0.13.2"
|
version = "0.13.2"
|
||||||
@@ -578,12 +620,33 @@ checksum = "b84bfb8d4104a1467910cf2090bc6a6d394ebde39c0dbc02397b45aa9ef88e80"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"arboard",
|
"arboard",
|
||||||
"bevy",
|
"bevy",
|
||||||
"egui",
|
"egui 0.26.2",
|
||||||
"thread_local",
|
"thread_local",
|
||||||
"web-sys",
|
"web-sys",
|
||||||
"webbrowser",
|
"webbrowser",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bevy_egui"
|
||||||
|
version = "0.27.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "eac153cb176b04eb0734c60fbc2912aa6fb2539f5b64ba832661c1c4cf9e298a"
|
||||||
|
dependencies = [
|
||||||
|
"arboard",
|
||||||
|
"bevy",
|
||||||
|
"console_log",
|
||||||
|
"crossbeam-channel",
|
||||||
|
"egui 0.27.2",
|
||||||
|
"js-sys",
|
||||||
|
"log",
|
||||||
|
"thread_local",
|
||||||
|
"wasm-bindgen",
|
||||||
|
"wasm-bindgen-futures",
|
||||||
|
"web-sys",
|
||||||
|
"webbrowser",
|
||||||
|
"winit",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bevy_encase_derive"
|
name = "bevy_encase_derive"
|
||||||
version = "0.13.2"
|
version = "0.13.2"
|
||||||
@@ -753,8 +816,10 @@ dependencies = [
|
|||||||
"bevy_ecs",
|
"bevy_ecs",
|
||||||
"bevy_utils",
|
"bevy_utils",
|
||||||
"console_error_panic_hook",
|
"console_error_panic_hook",
|
||||||
|
"tracing-error",
|
||||||
"tracing-log 0.1.4",
|
"tracing-log 0.1.4",
|
||||||
"tracing-subscriber",
|
"tracing-subscriber",
|
||||||
|
"tracing-tracy",
|
||||||
"tracing-wasm",
|
"tracing-wasm",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -901,6 +966,7 @@ dependencies = [
|
|||||||
"ktx2",
|
"ktx2",
|
||||||
"naga",
|
"naga",
|
||||||
"naga_oil",
|
"naga_oil",
|
||||||
|
"profiling",
|
||||||
"ruzstd",
|
"ruzstd",
|
||||||
"serde",
|
"serde",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
@@ -1308,10 +1374,15 @@ dependencies = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "camera_system"
|
name = "calloop-wayland-source"
|
||||||
version = "0.1.0"
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0f0ea9b9476c7fad82841a8dbb380e2eae480c21910feba80725b46931ed8f02"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bevy",
|
"calloop",
|
||||||
|
"rustix",
|
||||||
|
"wayland-backend",
|
||||||
|
"wayland-client",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1447,6 +1518,16 @@ dependencies = [
|
|||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "console_log"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "be8aed40e4edbf4d3b4431ab260b63fdc40f5780a4766824329ea0f1eefe3c0f"
|
||||||
|
dependencies = [
|
||||||
|
"log",
|
||||||
|
"web-sys",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "const-fnv1a-hash"
|
name = "const-fnv1a-hash"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
@@ -1698,6 +1779,15 @@ dependencies = [
|
|||||||
"bytemuck",
|
"bytemuck",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ecolor"
|
||||||
|
version = "0.27.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "20930a432bbd57a6d55e07976089708d4893f3d556cf42a0d79e9e321fa73b10"
|
||||||
|
dependencies = [
|
||||||
|
"bytemuck",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "egui"
|
name = "egui"
|
||||||
version = "0.26.2"
|
version = "0.26.2"
|
||||||
@@ -1705,10 +1795,30 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "180f595432a5b615fc6b74afef3955249b86cfea72607b40740a4cd60d5297d0"
|
checksum = "180f595432a5b615fc6b74afef3955249b86cfea72607b40740a4cd60d5297d0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ahash",
|
"ahash",
|
||||||
"epaint",
|
"epaint 0.26.2",
|
||||||
"nohash-hasher",
|
"nohash-hasher",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "egui"
|
||||||
|
version = "0.27.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "584c5d1bf9a67b25778a3323af222dbe1a1feb532190e103901187f92c7fe29a"
|
||||||
|
dependencies = [
|
||||||
|
"ahash",
|
||||||
|
"epaint 0.27.2",
|
||||||
|
"nohash-hasher",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "egui-dropdown"
|
||||||
|
version = "0.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "240e9423d44c6fd18a72208b442b1101ac871f9636c06d30cc6555d125f57db0"
|
||||||
|
dependencies = [
|
||||||
|
"egui 0.27.2",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "either"
|
name = "either"
|
||||||
version = "1.10.0"
|
version = "1.10.0"
|
||||||
@@ -1724,6 +1834,15 @@ dependencies = [
|
|||||||
"bytemuck",
|
"bytemuck",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "emath"
|
||||||
|
version = "0.27.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e4c3a552cfca14630702449d35f41c84a0d15963273771c6059175a803620f3f"
|
||||||
|
dependencies = [
|
||||||
|
"bytemuck",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "encase"
|
name = "encase"
|
||||||
version = "0.7.0"
|
version = "0.7.0"
|
||||||
@@ -1765,8 +1884,23 @@ dependencies = [
|
|||||||
"ab_glyph",
|
"ab_glyph",
|
||||||
"ahash",
|
"ahash",
|
||||||
"bytemuck",
|
"bytemuck",
|
||||||
"ecolor",
|
"ecolor 0.26.2",
|
||||||
"emath",
|
"emath 0.26.2",
|
||||||
|
"nohash-hasher",
|
||||||
|
"parking_lot",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "epaint"
|
||||||
|
version = "0.27.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b381f8b149657a4acf837095351839f32cd5c4aec1817fc4df84e18d76334176"
|
||||||
|
dependencies = [
|
||||||
|
"ab_glyph",
|
||||||
|
"ahash",
|
||||||
|
"bytemuck",
|
||||||
|
"ecolor 0.27.2",
|
||||||
|
"emath 0.27.2",
|
||||||
"nohash-hasher",
|
"nohash-hasher",
|
||||||
"parking_lot",
|
"parking_lot",
|
||||||
]
|
]
|
||||||
@@ -1957,6 +2091,29 @@ dependencies = [
|
|||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fuzzy-matcher"
|
||||||
|
version = "0.3.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "54614a3312934d066701a80f20f15fa3b56d67ac7722b39eea5b4c9dd1d66c94"
|
||||||
|
dependencies = [
|
||||||
|
"thread_local",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "generator"
|
||||||
|
version = "0.8.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "186014d53bc231d0090ef8d6f03e0920c54d85a5ed22f4f2f74315ec56cf83fb"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"log",
|
||||||
|
"rustversion",
|
||||||
|
"windows 0.54.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gethostname"
|
name = "gethostname"
|
||||||
version = "0.4.3"
|
version = "0.4.3"
|
||||||
@@ -2022,7 +2179,7 @@ dependencies = [
|
|||||||
"vec_map",
|
"vec_map",
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
"web-sys",
|
"web-sys",
|
||||||
"windows 0.48.0",
|
"windows 0.54.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -2520,6 +2677,19 @@ version = "0.4.21"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
|
checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "loom"
|
||||||
|
version = "0.7.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "419e0dc8046cb947daa77eb95ae174acfbddb7673b4151f56d1eed8e93fbfaca"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"generator",
|
||||||
|
"scoped-tls",
|
||||||
|
"tracing",
|
||||||
|
"tracing-subscriber",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mach2"
|
name = "mach2"
|
||||||
version = "0.4.2"
|
version = "0.4.2"
|
||||||
@@ -2563,6 +2733,15 @@ version = "2.7.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149"
|
checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memmap2"
|
||||||
|
version = "0.9.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fe751422e4a8caa417e13c3ea66452215d7d63e19e604f4980461212f3ae1322"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "metal"
|
name = "metal"
|
||||||
version = "0.27.0"
|
version = "0.27.0"
|
||||||
@@ -3065,11 +3244,11 @@ name = "phos"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bevy",
|
"bevy",
|
||||||
"bevy-inspector-egui",
|
"bevy-inspector-egui 0.23.4",
|
||||||
"bevy_rapier3d",
|
"bevy_rapier3d",
|
||||||
"camera_system",
|
|
||||||
"iyes_perf_ui",
|
"iyes_perf_ui",
|
||||||
"noise 0.8.2",
|
"noise 0.8.2",
|
||||||
|
"rayon",
|
||||||
"world_generation",
|
"world_generation",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -3174,6 +3353,29 @@ name = "profiling"
|
|||||||
version = "1.0.15"
|
version = "1.0.15"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "43d84d1d7a6ac92673717f9f6d1518374ef257669c24ebc5ac25d5033828be58"
|
checksum = "43d84d1d7a6ac92673717f9f6d1518374ef257669c24ebc5ac25d5033828be58"
|
||||||
|
dependencies = [
|
||||||
|
"profiling-procmacros",
|
||||||
|
"tracing",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "profiling-procmacros"
|
||||||
|
version = "1.0.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8021cf59c8ec9c432cfc2526ac6b8aa508ecaf29cd415f271b8406c1b851c3fd"
|
||||||
|
dependencies = [
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.55",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quick-xml"
|
||||||
|
version = "0.31.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1004a344b30a54e2ee58d66a71b32d2db2feb0a31f9a2d302bf0536f15de2a33"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quote"
|
name = "quote"
|
||||||
@@ -3286,6 +3488,7 @@ dependencies = [
|
|||||||
"num-derive",
|
"num-derive",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
"parry3d",
|
"parry3d",
|
||||||
|
"rayon",
|
||||||
"rustc-hash",
|
"rustc-hash",
|
||||||
"simba",
|
"simba",
|
||||||
"vec_map",
|
"vec_map",
|
||||||
@@ -3309,6 +3512,26 @@ version = "0.2.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3"
|
checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rayon"
|
||||||
|
version = "1.10.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa"
|
||||||
|
dependencies = [
|
||||||
|
"either",
|
||||||
|
"rayon-core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rayon-core"
|
||||||
|
version = "1.12.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2"
|
||||||
|
dependencies = [
|
||||||
|
"crossbeam-deque",
|
||||||
|
"crossbeam-utils",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rectangle-pack"
|
name = "rectangle-pack"
|
||||||
version = "0.4.2"
|
version = "0.4.2"
|
||||||
@@ -3430,6 +3653,12 @@ dependencies = [
|
|||||||
"windows-sys 0.52.0",
|
"windows-sys 0.52.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustversion"
|
||||||
|
version = "1.0.16"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "092474d1a01ea8278f69e6a358998405fae5b8b963ddaeb2b0b04a128bf1dfb0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ruzstd"
|
name = "ruzstd"
|
||||||
version = "0.5.0"
|
version = "0.5.0"
|
||||||
@@ -3465,12 +3694,31 @@ dependencies = [
|
|||||||
"winapi-util",
|
"winapi-util",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "scoped-tls"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "scopeguard"
|
name = "scopeguard"
|
||||||
version = "1.2.0"
|
version = "1.2.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sctk-adwaita"
|
||||||
|
version = "0.8.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "82b2eaf3a5b264a521b988b2e73042e742df700c4f962cde845d1541adb46550"
|
||||||
|
dependencies = [
|
||||||
|
"ab_glyph",
|
||||||
|
"log",
|
||||||
|
"memmap2",
|
||||||
|
"smithay-client-toolkit",
|
||||||
|
"tiny-skia",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.197"
|
version = "1.0.197"
|
||||||
@@ -3563,6 +3811,31 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "smithay-client-toolkit"
|
||||||
|
version = "0.18.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "922fd3eeab3bd820d76537ce8f582b1cf951eceb5475c28500c7457d9d17f53a"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 2.5.0",
|
||||||
|
"calloop",
|
||||||
|
"calloop-wayland-source",
|
||||||
|
"cursor-icon",
|
||||||
|
"libc",
|
||||||
|
"log",
|
||||||
|
"memmap2",
|
||||||
|
"rustix",
|
||||||
|
"thiserror",
|
||||||
|
"wayland-backend",
|
||||||
|
"wayland-client",
|
||||||
|
"wayland-csd-frame",
|
||||||
|
"wayland-cursor",
|
||||||
|
"wayland-protocols",
|
||||||
|
"wayland-protocols-wlr",
|
||||||
|
"wayland-scanner",
|
||||||
|
"xkeysym",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "smol_str"
|
name = "smol_str"
|
||||||
version = "0.2.1"
|
version = "0.2.1"
|
||||||
@@ -3599,6 +3872,12 @@ version = "1.1.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "strict-num"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6637bab7722d379c8b41ba849228d680cc12d0a45ba1fa2b48f2a30577a06731"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "svg_fmt"
|
name = "svg_fmt"
|
||||||
version = "0.4.2"
|
version = "0.4.2"
|
||||||
@@ -3703,6 +3982,31 @@ dependencies = [
|
|||||||
"weezl",
|
"weezl",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tiny-skia"
|
||||||
|
version = "0.11.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "83d13394d44dae3207b52a326c0c85a8bf87f1541f23b0d143811088497b09ab"
|
||||||
|
dependencies = [
|
||||||
|
"arrayref",
|
||||||
|
"arrayvec",
|
||||||
|
"bytemuck",
|
||||||
|
"cfg-if",
|
||||||
|
"log",
|
||||||
|
"tiny-skia-path",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tiny-skia-path"
|
||||||
|
version = "0.11.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9c9e7fc0c2e86a30b117d0462aa261b72b7a99b7ebd7deb3a14ceda95c5bdc93"
|
||||||
|
dependencies = [
|
||||||
|
"arrayref",
|
||||||
|
"bytemuck",
|
||||||
|
"strict-num",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tinyvec"
|
name = "tinyvec"
|
||||||
version = "1.6.0"
|
version = "1.6.0"
|
||||||
@@ -3767,6 +4071,16 @@ dependencies = [
|
|||||||
"valuable",
|
"valuable",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tracing-error"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d686ec1c0f384b1277f097b2f279a2ecc11afe8c133c1aabf036a27cb4cd206e"
|
||||||
|
dependencies = [
|
||||||
|
"tracing",
|
||||||
|
"tracing-subscriber",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tracing-log"
|
name = "tracing-log"
|
||||||
version = "0.1.4"
|
version = "0.1.4"
|
||||||
@@ -3807,6 +4121,17 @@ dependencies = [
|
|||||||
"tracing-log 0.2.0",
|
"tracing-log 0.2.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tracing-tracy"
|
||||||
|
version = "0.11.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6024d04f84a69fd0d1dc1eee3a2b070bd246530a0582f9982ae487cb6c703614"
|
||||||
|
dependencies = [
|
||||||
|
"tracing-core",
|
||||||
|
"tracing-subscriber",
|
||||||
|
"tracy-client",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tracing-wasm"
|
name = "tracing-wasm"
|
||||||
version = "0.2.1"
|
version = "0.2.1"
|
||||||
@@ -3818,6 +4143,26 @@ dependencies = [
|
|||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tracy-client"
|
||||||
|
version = "0.17.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "59fb931a64ff88984f86d3e9bcd1ae8843aa7fe44dd0f8097527bc172351741d"
|
||||||
|
dependencies = [
|
||||||
|
"loom",
|
||||||
|
"once_cell",
|
||||||
|
"tracy-client-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tracy-client-sys"
|
||||||
|
version = "0.22.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9d104d610dfa9dd154535102cc9c6164ae1fa37842bc2d9e83f9ac82b0ae0882"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ttf-parser"
|
name = "ttf-parser"
|
||||||
version = "0.20.0"
|
version = "0.20.0"
|
||||||
@@ -4006,6 +4351,115 @@ version = "0.2.92"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96"
|
checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wayland-backend"
|
||||||
|
version = "0.3.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9d50fa61ce90d76474c87f5fc002828d81b32677340112b4ef08079a9d459a40"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
"downcast-rs",
|
||||||
|
"rustix",
|
||||||
|
"scoped-tls",
|
||||||
|
"smallvec",
|
||||||
|
"wayland-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wayland-client"
|
||||||
|
version = "0.31.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "82fb96ee935c2cea6668ccb470fb7771f6215d1691746c2d896b447a00ad3f1f"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 2.5.0",
|
||||||
|
"rustix",
|
||||||
|
"wayland-backend",
|
||||||
|
"wayland-scanner",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wayland-csd-frame"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "625c5029dbd43d25e6aa9615e88b829a5cad13b2819c4ae129fdbb7c31ab4c7e"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 2.5.0",
|
||||||
|
"cursor-icon",
|
||||||
|
"wayland-backend",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wayland-cursor"
|
||||||
|
version = "0.31.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "71ce5fa868dd13d11a0d04c5e2e65726d0897be8de247c0c5a65886e283231ba"
|
||||||
|
dependencies = [
|
||||||
|
"rustix",
|
||||||
|
"wayland-client",
|
||||||
|
"xcursor",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wayland-protocols"
|
||||||
|
version = "0.31.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8f81f365b8b4a97f422ac0e8737c438024b5951734506b0e1d775c73030561f4"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 2.5.0",
|
||||||
|
"wayland-backend",
|
||||||
|
"wayland-client",
|
||||||
|
"wayland-scanner",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wayland-protocols-plasma"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "23803551115ff9ea9bce586860c5c5a971e360825a0309264102a9495a5ff479"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 2.5.0",
|
||||||
|
"wayland-backend",
|
||||||
|
"wayland-client",
|
||||||
|
"wayland-protocols",
|
||||||
|
"wayland-scanner",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wayland-protocols-wlr"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ad1f61b76b6c2d8742e10f9ba5c3737f6530b4c243132c2a2ccc8aa96fe25cd6"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 2.5.0",
|
||||||
|
"wayland-backend",
|
||||||
|
"wayland-client",
|
||||||
|
"wayland-protocols",
|
||||||
|
"wayland-scanner",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wayland-scanner"
|
||||||
|
version = "0.31.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "63b3a62929287001986fb58c789dce9b67604a397c15c611ad9f747300b6c283"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quick-xml",
|
||||||
|
"quote",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wayland-sys"
|
||||||
|
version = "0.31.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "15a0c8eaff5216d07f226cb7a549159267f3467b289d9a2e52fd3ef5aae2b7af"
|
||||||
|
dependencies = [
|
||||||
|
"dlib",
|
||||||
|
"log",
|
||||||
|
"once_cell",
|
||||||
|
"pkg-config",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "web-sys"
|
name = "web-sys"
|
||||||
version = "0.3.69"
|
version = "0.3.69"
|
||||||
@@ -4488,6 +4942,7 @@ version = "0.29.15"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0d59ad965a635657faf09c8f062badd885748428933dad8e8bdd64064d92e5ca"
|
checksum = "0d59ad965a635657faf09c8f062badd885748428933dad8e8bdd64064d92e5ca"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"ahash",
|
||||||
"android-activity",
|
"android-activity",
|
||||||
"atomic-waker",
|
"atomic-waker",
|
||||||
"bitflags 2.5.0",
|
"bitflags 2.5.0",
|
||||||
@@ -4501,6 +4956,7 @@ dependencies = [
|
|||||||
"js-sys",
|
"js-sys",
|
||||||
"libc",
|
"libc",
|
||||||
"log",
|
"log",
|
||||||
|
"memmap2",
|
||||||
"ndk",
|
"ndk",
|
||||||
"ndk-sys",
|
"ndk-sys",
|
||||||
"objc2 0.4.1",
|
"objc2 0.4.1",
|
||||||
@@ -4510,10 +4966,16 @@ dependencies = [
|
|||||||
"raw-window-handle 0.6.0",
|
"raw-window-handle 0.6.0",
|
||||||
"redox_syscall 0.3.5",
|
"redox_syscall 0.3.5",
|
||||||
"rustix",
|
"rustix",
|
||||||
|
"sctk-adwaita",
|
||||||
|
"smithay-client-toolkit",
|
||||||
"smol_str",
|
"smol_str",
|
||||||
"unicode-segmentation",
|
"unicode-segmentation",
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
"wasm-bindgen-futures",
|
"wasm-bindgen-futures",
|
||||||
|
"wayland-backend",
|
||||||
|
"wayland-client",
|
||||||
|
"wayland-protocols",
|
||||||
|
"wayland-protocols-plasma",
|
||||||
"web-sys",
|
"web-sys",
|
||||||
"web-time",
|
"web-time",
|
||||||
"windows-sys 0.48.0",
|
"windows-sys 0.48.0",
|
||||||
@@ -4537,7 +4999,9 @@ version = "0.1.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"asset_loader",
|
"asset_loader",
|
||||||
"bevy",
|
"bevy",
|
||||||
|
"bevy-inspector-egui 0.24.0",
|
||||||
"noise 0.9.0",
|
"noise 0.9.0",
|
||||||
|
"rayon",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
]
|
]
|
||||||
@@ -4574,6 +5038,12 @@ version = "0.13.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e63e71c4b8bd9ffec2c963173a4dc4cbde9ee96961d4fcb4429db9929b606c34"
|
checksum = "e63e71c4b8bd9ffec2c963173a4dc4cbde9ee96961d4fcb4429db9929b606c34"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "xcursor"
|
||||||
|
version = "0.3.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6a0ccd7b4a5345edfcd0c3535718a4e9ff7798ffc536bb5b5a0e26ff84732911"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "xi-unicode"
|
name = "xi-unicode"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
|
|||||||
@@ -3,8 +3,7 @@ resolver = "2"
|
|||||||
members = [
|
members = [
|
||||||
"game/main",
|
"game/main",
|
||||||
"engine/world_generation",
|
"engine/world_generation",
|
||||||
"game/camera_system"
|
"engine/asset_loader"]
|
||||||
, "engine/asset_loader"]
|
|
||||||
|
|
||||||
# Enable a small amount of optimization in debug mode
|
# Enable a small amount of optimization in debug mode
|
||||||
[profile.dev]
|
[profile.dev]
|
||||||
|
|||||||
@@ -11,3 +11,8 @@ noise = "0.9.0"
|
|||||||
serde = {version="1.0.197", features=["derive"]}
|
serde = {version="1.0.197", features=["derive"]}
|
||||||
serde_json = "1.0.115"
|
serde_json = "1.0.115"
|
||||||
asset_loader = {path = "../asset_loader"}
|
asset_loader = {path = "../asset_loader"}
|
||||||
|
rayon = "1.10.0"
|
||||||
|
bevy-inspector-egui = "0.24.0"
|
||||||
|
|
||||||
|
[features]
|
||||||
|
tracing = ["bevy/trace_tracy"]
|
||||||
69
engine/world_generation/src/chunk_colliders.rs
Normal file
69
engine/world_generation/src/chunk_colliders.rs
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
use crate::{hex_utils::*, prelude::*};
|
||||||
|
#[cfg(feature = "tracing")]
|
||||||
|
use bevy::log::*;
|
||||||
|
use bevy::prelude::*;
|
||||||
|
|
||||||
|
const CHUNK_TOTAL: usize = Chunk::SIZE * Chunk::SIZE;
|
||||||
|
|
||||||
|
pub fn generate_chunk_collider(chunk: &Chunk, map: &Map) -> (Vec<Vec3>, Vec<[u32; 3]>) {
|
||||||
|
#[cfg(feature = "tracing")]
|
||||||
|
let span = info_span!("generate_chunk_collider").entered();
|
||||||
|
let vertex_count: usize = CHUNK_TOTAL * 6;
|
||||||
|
let mut verts = Vec::with_capacity(vertex_count);
|
||||||
|
let mut indices = Vec::with_capacity(vertex_count);
|
||||||
|
for z in 0..Chunk::SIZE {
|
||||||
|
for x in 0..Chunk::SIZE {
|
||||||
|
let height = chunk.heights[x + z * Chunk::SIZE];
|
||||||
|
let coord =
|
||||||
|
HexCoord::from_offset(IVec2::new(x as i32, z as i32) + (chunk.chunk_offset * Chunk::SIZE as i32));
|
||||||
|
let neighbors = map.get_neighbors(&coord);
|
||||||
|
let off_pos = Vec3::new(x as f32, height, z as f32);
|
||||||
|
let tile_pos = offset3d_to_world(off_pos);
|
||||||
|
create_tile_collider(tile_pos, &mut verts, &mut indices, &neighbors);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (verts, indices);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_tile_collider(pos: Vec3, verts: &mut Vec<Vec3>, indices: &mut Vec<[u32; 3]>, neighbors: &[Option<f32>; 6]) {
|
||||||
|
let idx = verts.len() as u32;
|
||||||
|
for i in 0..6 {
|
||||||
|
let p = pos + HEX_CORNERS[i];
|
||||||
|
verts.push(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Top Surfave
|
||||||
|
indices.push([idx, idx + 1, idx + 5]);
|
||||||
|
indices.push([idx + 1, idx + 2, idx + 5]);
|
||||||
|
indices.push([idx + 2, idx + 4, idx + 5]);
|
||||||
|
indices.push([idx + 2, idx + 3, idx + 4]);
|
||||||
|
|
||||||
|
for i in 0..neighbors.len() {
|
||||||
|
let cur_n = neighbors[i];
|
||||||
|
match cur_n {
|
||||||
|
Some(n_height) => {
|
||||||
|
if n_height < pos.y {
|
||||||
|
create_tile_wall_collider(
|
||||||
|
idx,
|
||||||
|
Vec3::new(pos.x, n_height.min(pos.y - OUTER_RADIUS / 2.), pos.z),
|
||||||
|
i,
|
||||||
|
verts,
|
||||||
|
indices,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_tile_wall_collider(idx: u32, pos: Vec3, dir: usize, verts: &mut Vec<Vec3>, indices: &mut Vec<[u32; 3]>) {
|
||||||
|
let idx2 = verts.len() as u32;
|
||||||
|
|
||||||
|
verts.push(pos + HEX_CORNERS[dir]);
|
||||||
|
verts.push(pos + HEX_CORNERS[(dir + 1) % 6]);
|
||||||
|
|
||||||
|
let off = dir as u32;
|
||||||
|
indices.push([idx + off, idx + ((off + 1) % 6), idx2 + 1]);
|
||||||
|
indices.push([idx + off, idx2 + 1, idx2]);
|
||||||
|
}
|
||||||
@@ -1,20 +1,25 @@
|
|||||||
use bevy::math::IVec2;
|
use bevy::math::IVec2;
|
||||||
use bevy::prelude::{FloatExt, Vec2};
|
use bevy::prelude::{FloatExt, Vec2};
|
||||||
use noise::{NoiseFn, SuperSimplex};
|
use noise::{NoiseFn, SuperSimplex};
|
||||||
|
use rayon::iter::{IntoParallelIterator, ParallelIterator};
|
||||||
|
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
pub fn generate_heightmap(cfg: &GenerationConfig, seed: u32) -> Map {
|
pub fn generate_heightmap(cfg: &GenerationConfig, seed: u32) -> Map {
|
||||||
let mut chunks: Vec<Chunk> = Vec::with_capacity(cfg.size.length_squared() as usize);
|
// let mut chunks: Vec<Chunk> = Vec::with_capacity(cfg.size.length_squared() as usize);
|
||||||
for z in 0..cfg.size.y {
|
let chunks = (0..cfg.size.y)
|
||||||
for x in 0..cfg.size.x {
|
.into_par_iter()
|
||||||
chunks.push(generate_chunk(x as f64, z as f64, cfg, seed));
|
.flat_map(|z| {
|
||||||
}
|
(0..cfg.size.x)
|
||||||
}
|
.into_par_iter()
|
||||||
|
.map(move |x| generate_chunk(x as f64, z as f64, cfg, seed))
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
return Map {
|
return Map {
|
||||||
chunks,
|
chunks,
|
||||||
height: cfg.size.y as usize,
|
height: cfg.size.y as usize,
|
||||||
width: cfg.size.x as usize,
|
width: cfg.size.x as usize,
|
||||||
|
sea_level: cfg.sea_level as f32,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -36,12 +41,8 @@ pub fn generate_chunk(chunk_x: f64, chunk_z: f64, cfg: &GenerationConfig, seed:
|
|||||||
(x as f64 + chunk_x * Chunk::SIZE as f64) / &cfg.noise_scale,
|
(x as f64 + chunk_x * Chunk::SIZE as f64) / &cfg.noise_scale,
|
||||||
(z as f64 + chunk_z * Chunk::SIZE as f64) / &cfg.noise_scale,
|
(z as f64 + chunk_z * Chunk::SIZE as f64) / &cfg.noise_scale,
|
||||||
]) as f32;
|
]) as f32;
|
||||||
temp[x + z * Chunk::SIZE] = sample_tempurature(
|
temp[x + z * Chunk::SIZE] =
|
||||||
z as f32 + chunk_z as f32 * Chunk::SIZE as f32,
|
sample_tempurature(z as f32 + chunk_z as f32 * Chunk::SIZE as f32, sample, &cfg, 100.);
|
||||||
sample,
|
|
||||||
&cfg,
|
|
||||||
100.,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Chunk {
|
return Chunk {
|
||||||
@@ -91,10 +92,7 @@ fn sample_point(x: f64, z: f64, cfg: &GenerationConfig, noise: &impl NoiseFn<f64
|
|||||||
let d1 = p.x.min(p.y);
|
let d1 = p.x.min(p.y);
|
||||||
let od = outer - p;
|
let od = outer - p;
|
||||||
let d2 = od.x.min(od.y);
|
let d2 = od.x.min(od.y);
|
||||||
let d = d1
|
let d = d1.min(d2).min(cfg.border_size).remap(0., cfg.border_size, 0., 1.);
|
||||||
.min(d2)
|
|
||||||
.min(cfg.border_size)
|
|
||||||
.remap(0., cfg.border_size, 0., 1.);
|
|
||||||
|
|
||||||
return (elevation as f32) * d;
|
return (elevation as f32) * d;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,10 @@ use crate::prelude::Chunk;
|
|||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
|
|
||||||
pub const OUTER_RADIUS: f32 = 1.;
|
pub const OUTER_RADIUS: f32 = 1.;
|
||||||
pub const INNER_RADIUS: f32 = OUTER_RADIUS * 0.866025404;
|
pub const INNER_RADIUS: f32 = OUTER_RADIUS * (SQRT_3 / 2.);
|
||||||
|
pub const SHORT_DIAGONAL: f32 = 1. * SQRT_3;
|
||||||
|
pub const LONG_DIAGONAL: f32 = 2. * OUTER_RADIUS;
|
||||||
|
const SQRT_3: f32 = 1.7320508076;
|
||||||
|
|
||||||
pub fn offset3d_to_world(offset: Vec3) -> Vec3 {
|
pub fn offset3d_to_world(offset: Vec3) -> Vec3 {
|
||||||
let x = (offset.x + (offset.z * 0.5) - (offset.z / 2.).floor()) * (INNER_RADIUS * 2.);
|
let x = (offset.x + (offset.z * 0.5) - (offset.z / 2.).floor()) * (INNER_RADIUS * 2.);
|
||||||
@@ -25,6 +28,10 @@ pub fn offset_to_hex(offset: IVec2) -> IVec3 {
|
|||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn offset_to_index(offset: IVec2, width: usize) -> usize {
|
||||||
|
return offset.x as usize + offset.y as usize * width;
|
||||||
|
}
|
||||||
|
|
||||||
pub fn snap_to_hex_grid(world_pos: Vec3) -> Vec3 {
|
pub fn snap_to_hex_grid(world_pos: Vec3) -> Vec3 {
|
||||||
return offset_to_world(world_to_offset_pos(world_pos), world_pos.y);
|
return offset_to_world(world_to_offset_pos(world_pos), world_pos.y);
|
||||||
}
|
}
|
||||||
@@ -41,11 +48,11 @@ pub fn world_to_offset_pos(world_pos: Vec3) -> IVec2 {
|
|||||||
return IVec2::new(ox, oz);
|
return IVec2::new(ox, oz);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn tile_to_world_distance(dist: i32) -> f32 {
|
pub fn tile_to_world_distance(dist: u32) -> f32 {
|
||||||
return dist as f32 * (2. * INNER_RADIUS);
|
return dist as f32 * (2. * INNER_RADIUS);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_tile_count(radius: i32) -> i32 {
|
pub fn get_tile_count(radius: u32) -> u32 {
|
||||||
return 1 + 3 * (radius + 1) * radius;
|
return 1 + 3 * (radius + 1) * radius;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,6 +93,20 @@ impl HexCoord {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn from_world_pos(world_pos: Vec3) -> Self {
|
||||||
|
let offset = world_pos.z / (OUTER_RADIUS * 3.);
|
||||||
|
let mut x = world_pos.x / (INNER_RADIUS * 2.);
|
||||||
|
let mut z = -x;
|
||||||
|
z -= offset;
|
||||||
|
x -= offset;
|
||||||
|
|
||||||
|
let i_x = x.round() as i32;
|
||||||
|
let i_z = (-x - z).round() as i32;
|
||||||
|
let offset_pos = IVec2::new(i_x + i_z / 2, i_z);
|
||||||
|
|
||||||
|
return Self::from_offset(offset_pos);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn is_in_bounds(&self, map_height: usize, map_width: usize) -> bool {
|
pub fn is_in_bounds(&self, map_height: usize, map_width: usize) -> bool {
|
||||||
let off = self.to_offset();
|
let off = self.to_offset();
|
||||||
if off.x < 0 || off.y < 0 {
|
if off.x < 0 || off.y < 0 {
|
||||||
@@ -99,6 +120,12 @@ impl HexCoord {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_on_chunk_edge(&self) -> bool {
|
||||||
|
let offset = self.to_offset().rem_euclid(IVec2::splat(Chunk::SIZE as i32));
|
||||||
|
let e = (Chunk::SIZE - 1) as i32;
|
||||||
|
return offset.x == 0 || offset.y == 0 || offset.x == e || offset.y == e;
|
||||||
|
}
|
||||||
|
|
||||||
pub fn to_chunk_pos(&self) -> IVec2 {
|
pub fn to_chunk_pos(&self) -> IVec2 {
|
||||||
let off = self.to_offset();
|
let off = self.to_offset();
|
||||||
|
|
||||||
@@ -141,9 +168,7 @@ impl HexCoord {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn distance(&self, other: &HexCoord) -> i32 {
|
pub fn distance(&self, other: &HexCoord) -> i32 {
|
||||||
return (self.hex.x - other.hex.x).abs()
|
return (self.hex.x - other.hex.x).abs() + (self.hex.y - other.hex.y).abs() + (self.hex.z - other.hex.z).abs();
|
||||||
+ (self.hex.y - other.hex.y).abs()
|
|
||||||
+ (self.hex.z - other.hex.z).abs();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn rotate_around(&self, center: &HexCoord, angle: i32) -> HexCoord {
|
pub fn rotate_around(&self, center: &HexCoord, angle: i32) -> HexCoord {
|
||||||
|
|||||||
@@ -1,17 +1,42 @@
|
|||||||
pub mod biome_painter;
|
pub mod biome_painter;
|
||||||
|
pub mod chunk_colliders;
|
||||||
pub mod heightmap;
|
pub mod heightmap;
|
||||||
pub mod hex_utils;
|
pub mod hex_utils;
|
||||||
pub mod mesh_generator;
|
pub mod mesh_generator;
|
||||||
|
pub mod packed_mesh_generator;
|
||||||
pub mod tile_manager;
|
pub mod tile_manager;
|
||||||
pub mod tile_mapper;
|
pub mod tile_mapper;
|
||||||
|
|
||||||
pub mod prelude {
|
pub mod prelude {
|
||||||
use crate::hex_utils::HexCoord;
|
use crate::hex_utils::{tile_to_world_distance, HexCoord, INNER_RADIUS, OUTER_RADIUS, SHORT_DIAGONAL};
|
||||||
use bevy::math::{IVec2, UVec2};
|
use bevy::math::{IVec2, UVec2, Vec2, Vec3};
|
||||||
use bevy::prelude::Resource;
|
use bevy::prelude::Resource;
|
||||||
|
use bevy::prelude::*;
|
||||||
use bevy::render::mesh::MeshVertexAttribute;
|
use bevy::render::mesh::MeshVertexAttribute;
|
||||||
use bevy::render::render_resource::VertexFormat;
|
use bevy::render::render_resource::VertexFormat;
|
||||||
|
use bevy_inspector_egui::InspectorOptions;
|
||||||
|
pub const TEX_MULTI: Vec2 = Vec2::new(1000., 1.);
|
||||||
|
|
||||||
|
pub const HEX_CORNERS: [Vec3; 6] = [
|
||||||
|
Vec3::new(0., 0., OUTER_RADIUS),
|
||||||
|
Vec3::new(INNER_RADIUS, 0., 0.5 * OUTER_RADIUS),
|
||||||
|
Vec3::new(INNER_RADIUS, 0., -0.5 * OUTER_RADIUS),
|
||||||
|
Vec3::new(0., 0., -OUTER_RADIUS),
|
||||||
|
Vec3::new(-INNER_RADIUS, 0., -0.5 * OUTER_RADIUS),
|
||||||
|
Vec3::new(-INNER_RADIUS, 0., 0.5 * OUTER_RADIUS),
|
||||||
|
];
|
||||||
|
|
||||||
|
pub const HEX_NORMALS: [Vec3; 6] = [
|
||||||
|
Vec3::new(INNER_RADIUS / 2., 0., (OUTER_RADIUS + 0.5 * OUTER_RADIUS) / 2.),
|
||||||
|
Vec3::Z,
|
||||||
|
Vec3::new(INNER_RADIUS / -2., 0., (OUTER_RADIUS + 0.5 * OUTER_RADIUS) / 2.),
|
||||||
|
Vec3::new(INNER_RADIUS / -2., 0., (OUTER_RADIUS + 0.5 * OUTER_RADIUS) / -2.),
|
||||||
|
Vec3::NEG_Z,
|
||||||
|
Vec3::new(INNER_RADIUS / 2., 0., (OUTER_RADIUS + 0.5 * OUTER_RADIUS) / -2.),
|
||||||
|
];
|
||||||
|
|
||||||
|
#[derive(Resource, Reflect, Default)]
|
||||||
|
#[reflect(Resource)]
|
||||||
pub struct GenerationConfig {
|
pub struct GenerationConfig {
|
||||||
pub noise_scale: f64,
|
pub noise_scale: f64,
|
||||||
pub sea_level: f64,
|
pub sea_level: f64,
|
||||||
@@ -29,6 +54,7 @@ pub mod prelude {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Reflect, InspectorOptions)]
|
||||||
pub struct GeneratorLayer {
|
pub struct GeneratorLayer {
|
||||||
pub strength: f64,
|
pub strength: f64,
|
||||||
pub min_value: f64,
|
pub min_value: f64,
|
||||||
@@ -51,6 +77,9 @@ pub mod prelude {
|
|||||||
|
|
||||||
impl Chunk {
|
impl Chunk {
|
||||||
pub const SIZE: usize = 64;
|
pub const SIZE: usize = 64;
|
||||||
|
pub const WORLD_WIDTH: f32 = Chunk::SIZE as f32 * SHORT_DIAGONAL;
|
||||||
|
pub const WORLD_HEIGHT: f32 = Chunk::SIZE as f32 * 1.5;
|
||||||
|
pub const WORLD_SIZE: Vec2 = Vec2::new(Chunk::WORLD_WIDTH, Chunk::WORLD_HEIGHT);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Resource)]
|
#[derive(Resource)]
|
||||||
@@ -58,6 +87,7 @@ pub mod prelude {
|
|||||||
pub chunks: Vec<Chunk>,
|
pub chunks: Vec<Chunk>,
|
||||||
pub height: usize,
|
pub height: usize,
|
||||||
pub width: usize,
|
pub width: usize,
|
||||||
|
pub sea_level: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Map {
|
impl Map {
|
||||||
@@ -79,11 +109,15 @@ pub mod prelude {
|
|||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_height(&self, pos: &HexCoord) -> f32 {
|
pub fn sample_height(&self, pos: &HexCoord) -> f32 {
|
||||||
let chunk = &self.chunks[pos.to_chunk_index(self.width)];
|
let chunk = &self.chunks[pos.to_chunk_index(self.width)];
|
||||||
return chunk.heights[pos.to_chunk_local_index()];
|
return chunk.heights[pos.to_chunk_local_index()];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_in_bounds(&self, pos: &HexCoord) -> bool {
|
||||||
|
return pos.is_in_bounds(self.height * Chunk::SIZE, self.width * Chunk::SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_moisture(&self, pos: &HexCoord) -> f32 {
|
pub fn get_moisture(&self, pos: &HexCoord) -> f32 {
|
||||||
let chunk = &self.chunks[pos.to_chunk_index(self.width)];
|
let chunk = &self.chunks[pos.to_chunk_index(self.width)];
|
||||||
return chunk.moisture[pos.to_chunk_local_index()];
|
return chunk.moisture[pos.to_chunk_local_index()];
|
||||||
@@ -93,7 +127,32 @@ pub mod prelude {
|
|||||||
let chunk = &self.chunks[pos.to_chunk_index(self.width)];
|
let chunk = &self.chunks[pos.to_chunk_index(self.width)];
|
||||||
return chunk.temperature[pos.to_chunk_local_index()];
|
return chunk.temperature[pos.to_chunk_local_index()];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_center(&self) -> Vec3 {
|
||||||
|
let w = self.get_world_width();
|
||||||
|
let h = self.get_world_height();
|
||||||
|
return Vec3::new(w / 2., self.sea_level, h / 2.);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_world_width(&self) -> f32 {
|
||||||
|
return (self.width * Chunk::SIZE) as f32 * SHORT_DIAGONAL;
|
||||||
|
}
|
||||||
|
pub fn get_world_height(&self) -> f32 {
|
||||||
|
return (self.height * Chunk::SIZE) as f32 * 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_world_size(&self) -> Vec2 {
|
||||||
|
return Vec2::new(self.get_world_width(), self.get_world_height());
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_height(&mut self, pos: &HexCoord, height: f32) {
|
||||||
|
self.chunks[pos.to_chunk_index(self.width)].heights[pos.to_chunk_local_index()] = height;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
pub const ATTRIBUTE_PACKED_VERTEX_DATA: MeshVertexAttribute =
|
||||||
|
MeshVertexAttribute::new("PackedVertexData", 988540817, VertexFormat::Uint32);
|
||||||
|
pub const ATTRIBUTE_VERTEX_HEIGHT: MeshVertexAttribute =
|
||||||
|
MeshVertexAttribute::new("VertexHeight", 988540717, VertexFormat::Float32);
|
||||||
|
|
||||||
pub const ATTRIBUTE_TEXTURE_INDEX: MeshVertexAttribute =
|
pub const ATTRIBUTE_TEXTURE_INDEX: MeshVertexAttribute =
|
||||||
MeshVertexAttribute::new("TextureIndex", 988540917, VertexFormat::Uint32);
|
MeshVertexAttribute::new("TextureIndex", 988540917, VertexFormat::Uint32);
|
||||||
|
|||||||
@@ -2,10 +2,9 @@ use crate::biome_painter::BiomePainterAsset;
|
|||||||
use crate::hex_utils::HexCoord;
|
use crate::hex_utils::HexCoord;
|
||||||
use crate::tile_manager::TileAsset;
|
use crate::tile_manager::TileAsset;
|
||||||
use crate::tile_mapper::TileMapperAsset;
|
use crate::tile_mapper::TileMapperAsset;
|
||||||
use crate::{
|
use crate::{hex_utils::offset3d_to_world, prelude::*};
|
||||||
hex_utils::{offset3d_to_world, INNER_RADIUS, OUTER_RADIUS},
|
#[cfg(feature = "tracing")]
|
||||||
prelude::*,
|
use bevy::log::*;
|
||||||
};
|
|
||||||
use bevy::{
|
use bevy::{
|
||||||
prelude::*,
|
prelude::*,
|
||||||
render::{
|
render::{
|
||||||
@@ -13,41 +12,6 @@ use bevy::{
|
|||||||
render_asset::RenderAssetUsages,
|
render_asset::RenderAssetUsages,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use std::vec::Vec;
|
|
||||||
|
|
||||||
const HEX_CORNERS: [Vec3; 6] = [
|
|
||||||
Vec3::new(0., 0., OUTER_RADIUS),
|
|
||||||
Vec3::new(INNER_RADIUS, 0., 0.5 * OUTER_RADIUS),
|
|
||||||
Vec3::new(INNER_RADIUS, 0., -0.5 * OUTER_RADIUS),
|
|
||||||
Vec3::new(0., 0., -OUTER_RADIUS),
|
|
||||||
Vec3::new(-INNER_RADIUS, 0., -0.5 * OUTER_RADIUS),
|
|
||||||
Vec3::new(-INNER_RADIUS, 0., 0.5 * OUTER_RADIUS),
|
|
||||||
];
|
|
||||||
|
|
||||||
const HEX_NORMALS: [Vec3; 6] = [
|
|
||||||
Vec3::new(
|
|
||||||
INNER_RADIUS / 2.,
|
|
||||||
0.,
|
|
||||||
(OUTER_RADIUS + 0.5 * OUTER_RADIUS) / 2.,
|
|
||||||
),
|
|
||||||
Vec3::Z,
|
|
||||||
Vec3::new(
|
|
||||||
INNER_RADIUS / -2.,
|
|
||||||
0.,
|
|
||||||
(OUTER_RADIUS + 0.5 * OUTER_RADIUS) / 2.,
|
|
||||||
),
|
|
||||||
Vec3::new(
|
|
||||||
INNER_RADIUS / -2.,
|
|
||||||
0.,
|
|
||||||
(OUTER_RADIUS + 0.5 * OUTER_RADIUS) / -2.,
|
|
||||||
),
|
|
||||||
Vec3::NEG_Z,
|
|
||||||
Vec3::new(
|
|
||||||
INNER_RADIUS / 2.,
|
|
||||||
0.,
|
|
||||||
(OUTER_RADIUS + 0.5 * OUTER_RADIUS) / -2.,
|
|
||||||
),
|
|
||||||
];
|
|
||||||
|
|
||||||
pub fn generate_chunk_mesh(
|
pub fn generate_chunk_mesh(
|
||||||
chunk: &Chunk,
|
chunk: &Chunk,
|
||||||
@@ -56,6 +20,9 @@ pub fn generate_chunk_mesh(
|
|||||||
tiles: &Res<Assets<TileAsset>>,
|
tiles: &Res<Assets<TileAsset>>,
|
||||||
mappers: &Res<Assets<TileMapperAsset>>,
|
mappers: &Res<Assets<TileMapperAsset>>,
|
||||||
) -> Mesh {
|
) -> Mesh {
|
||||||
|
#[cfg(feature = "tracing")]
|
||||||
|
let span = info_span!("generate_chunk_mesh").entered();
|
||||||
|
|
||||||
let vertex_count: usize = Chunk::SIZE * Chunk::SIZE * 6;
|
let vertex_count: usize = Chunk::SIZE * Chunk::SIZE * 6;
|
||||||
let mut verts = Vec::with_capacity(vertex_count);
|
let mut verts = Vec::with_capacity(vertex_count);
|
||||||
let mut uvs = Vec::with_capacity(vertex_count);
|
let mut uvs = Vec::with_capacity(vertex_count);
|
||||||
@@ -69,9 +36,8 @@ pub fn generate_chunk_mesh(
|
|||||||
let temperature = chunk.temperature[x + z * Chunk::SIZE];
|
let temperature = chunk.temperature[x + z * Chunk::SIZE];
|
||||||
let off_pos = Vec3::new(x as f32, height, z as f32);
|
let off_pos = Vec3::new(x as f32, height, z as f32);
|
||||||
let tile_pos = offset3d_to_world(off_pos);
|
let tile_pos = offset3d_to_world(off_pos);
|
||||||
let coord = HexCoord::from_offset(
|
let coord =
|
||||||
IVec2::new(x as i32, z as i32) + (chunk.chunk_offset * Chunk::SIZE as i32),
|
HexCoord::from_offset(IVec2::new(x as i32, z as i32) + (chunk.chunk_offset * Chunk::SIZE as i32));
|
||||||
);
|
|
||||||
let n = map.get_neighbors(&coord);
|
let n = map.get_neighbors(&coord);
|
||||||
let biome = mappers.get(painter.sample_biome(moisture, temperature));
|
let biome = mappers.get(painter.sample_biome(moisture, temperature));
|
||||||
let tile_handle = biome.unwrap().sample_tile(height);
|
let tile_handle = biome.unwrap().sample_tile(height);
|
||||||
@@ -102,7 +68,6 @@ pub fn generate_chunk_mesh(
|
|||||||
return mesh;
|
return mesh;
|
||||||
}
|
}
|
||||||
|
|
||||||
const TEX_MULTI: Vec2 = Vec2::new(1000., 1.);
|
|
||||||
fn create_tile(
|
fn create_tile(
|
||||||
pos: Vec3,
|
pos: Vec3,
|
||||||
neighbors: &[Option<f32>; 6],
|
neighbors: &[Option<f32>; 6],
|
||||||
@@ -118,19 +83,22 @@ fn create_tile(
|
|||||||
let side_tex_off = Vec2::new(side_texture_index as f32, 0.);
|
let side_tex_off = Vec2::new(side_texture_index as f32, 0.);
|
||||||
|
|
||||||
let idx = verts.len() as u32;
|
let idx = verts.len() as u32;
|
||||||
uvs.push((uv_offset / TEX_MULTI) + tex_off);
|
|
||||||
verts.push(pos);
|
|
||||||
normals.push(Vec3::Y);
|
|
||||||
for i in 0..6 {
|
for i in 0..6 {
|
||||||
let p = pos + HEX_CORNERS[i];
|
let p = pos + HEX_CORNERS[i];
|
||||||
verts.push(p);
|
verts.push(p);
|
||||||
let uv = (HEX_CORNERS[i].xz() / 2.) + uv_offset;
|
let uv = (HEX_CORNERS[i].xz() / 2.) + uv_offset;
|
||||||
uvs.push((uv / TEX_MULTI) + tex_off);
|
uvs.push((uv / TEX_MULTI) + tex_off);
|
||||||
indices.push(idx);
|
|
||||||
indices.push(idx + 1 + i as u32);
|
|
||||||
indices.push(idx + 1 + ((i as u32 + 1) % 6));
|
|
||||||
normals.push(Vec3::Y);
|
normals.push(Vec3::Y);
|
||||||
}
|
}
|
||||||
|
for i in 0..3 {
|
||||||
|
let off = i * 2;
|
||||||
|
indices.push(off + idx);
|
||||||
|
indices.push(((off + 1) % 6) + idx);
|
||||||
|
indices.push(((off + 2) % 6) + idx);
|
||||||
|
}
|
||||||
|
indices.push(idx);
|
||||||
|
indices.push(idx + 2);
|
||||||
|
indices.push(idx + 4);
|
||||||
|
|
||||||
for i in 0..neighbors.len() {
|
for i in 0..neighbors.len() {
|
||||||
let cur_n = neighbors[i];
|
let cur_n = neighbors[i];
|
||||||
@@ -167,7 +135,7 @@ fn create_tile_wall(
|
|||||||
verts.push(p3);
|
verts.push(p3);
|
||||||
verts.push(p4);
|
verts.push(p4);
|
||||||
|
|
||||||
let n = HEX_NORMALS[dir].normalize();
|
let n = HEX_NORMALS[dir];
|
||||||
normals.push(n);
|
normals.push(n);
|
||||||
normals.push(n);
|
normals.push(n);
|
||||||
normals.push(n);
|
normals.push(n);
|
||||||
|
|||||||
147
engine/world_generation/src/packed_mesh_generator.rs
Normal file
147
engine/world_generation/src/packed_mesh_generator.rs
Normal file
@@ -0,0 +1,147 @@
|
|||||||
|
use crate::biome_painter::BiomePainterAsset;
|
||||||
|
use crate::hex_utils::HexCoord;
|
||||||
|
use crate::prelude::*;
|
||||||
|
use crate::tile_manager::TileAsset;
|
||||||
|
use crate::tile_mapper::TileMapperAsset;
|
||||||
|
use bevy::{
|
||||||
|
prelude::*,
|
||||||
|
render::{
|
||||||
|
mesh::{Indices, PrimitiveTopology},
|
||||||
|
render_asset::RenderAssetUsages,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn generate_packed_chunk_mesh(
|
||||||
|
chunk: &Chunk,
|
||||||
|
map: &Map,
|
||||||
|
painter: &BiomePainterAsset,
|
||||||
|
tiles: &Res<Assets<TileAsset>>,
|
||||||
|
mappers: &Res<Assets<TileMapperAsset>>,
|
||||||
|
) -> Mesh {
|
||||||
|
let vertex_count: usize = Chunk::SIZE * Chunk::SIZE * 6;
|
||||||
|
let mut packed_data = Vec::with_capacity(vertex_count);
|
||||||
|
let mut indices = Vec::with_capacity(vertex_count);
|
||||||
|
let mut heights = Vec::with_capacity(vertex_count);
|
||||||
|
|
||||||
|
for z in 0..Chunk::SIZE {
|
||||||
|
for x in 0..Chunk::SIZE {
|
||||||
|
let height = chunk.heights[x + z * Chunk::SIZE];
|
||||||
|
let moisture = chunk.moisture[x + z * Chunk::SIZE];
|
||||||
|
let temperature = chunk.temperature[x + z * Chunk::SIZE];
|
||||||
|
let coord =
|
||||||
|
HexCoord::from_offset(IVec2::new(x as i32, z as i32) + (chunk.chunk_offset * Chunk::SIZE as i32));
|
||||||
|
let n = map.get_neighbors(&coord);
|
||||||
|
let biome = mappers.get(painter.sample_biome(moisture, temperature));
|
||||||
|
let tile_handle = biome.unwrap().sample_tile(height);
|
||||||
|
let tile = tiles.get(tile_handle).unwrap();
|
||||||
|
|
||||||
|
create_packed_tile(
|
||||||
|
UVec2::new(x as u32, z as u32),
|
||||||
|
height,
|
||||||
|
&n,
|
||||||
|
&mut packed_data,
|
||||||
|
&mut indices,
|
||||||
|
&mut heights,
|
||||||
|
tile.texture_id,
|
||||||
|
tile.side_texture_id,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mesh = Mesh::new(
|
||||||
|
PrimitiveTopology::TriangleList,
|
||||||
|
RenderAssetUsages::MAIN_WORLD | RenderAssetUsages::RENDER_WORLD,
|
||||||
|
)
|
||||||
|
.with_inserted_attribute(ATTRIBUTE_PACKED_VERTEX_DATA, packed_data)
|
||||||
|
.with_inserted_attribute(ATTRIBUTE_VERTEX_HEIGHT, heights)
|
||||||
|
.with_inserted_indices(Indices::U32(indices));
|
||||||
|
return mesh;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_packed_tile(
|
||||||
|
offset: UVec2,
|
||||||
|
height: f32,
|
||||||
|
neighbors: &[Option<f32>; 6],
|
||||||
|
packed_data: &mut Vec<u32>,
|
||||||
|
indices: &mut Vec<u32>,
|
||||||
|
heights: &mut Vec<f32>,
|
||||||
|
texture_index: u32,
|
||||||
|
side_texture_index: u32,
|
||||||
|
) {
|
||||||
|
let idx = packed_data.len() as u32;
|
||||||
|
|
||||||
|
packed_data.push(pack_vertex_data(offset, 0, texture_index));
|
||||||
|
heights.push(height);
|
||||||
|
for i in 0..6 {
|
||||||
|
packed_data.push(pack_vertex_data(offset, i + 1, texture_index));
|
||||||
|
indices.push(idx);
|
||||||
|
indices.push(idx + 1 + i as u32);
|
||||||
|
indices.push(idx + 1 + ((i as u32 + 1) % 6));
|
||||||
|
heights.push(height);
|
||||||
|
}
|
||||||
|
|
||||||
|
for i in 0..neighbors.len() {
|
||||||
|
let cur_n = neighbors[i];
|
||||||
|
match cur_n {
|
||||||
|
Some(n_height) => {
|
||||||
|
if n_height < height {
|
||||||
|
create_packed_tile_wall(
|
||||||
|
offset,
|
||||||
|
height,
|
||||||
|
n_height,
|
||||||
|
i,
|
||||||
|
packed_data,
|
||||||
|
indices,
|
||||||
|
heights,
|
||||||
|
side_texture_index,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_packed_tile_wall(
|
||||||
|
offset: UVec2,
|
||||||
|
height_top: f32,
|
||||||
|
height_bottom: f32,
|
||||||
|
side: usize,
|
||||||
|
packed_data: &mut Vec<u32>,
|
||||||
|
indices: &mut Vec<u32>,
|
||||||
|
heights: &mut Vec<f32>,
|
||||||
|
side_texture_index: u32,
|
||||||
|
) {
|
||||||
|
let idx = packed_data.len() as u32;
|
||||||
|
|
||||||
|
let side_2 = ((side + 1) % 6) + 1;
|
||||||
|
packed_data.push(pack_vertex_data(offset, side + 1, side_texture_index));
|
||||||
|
packed_data.push(pack_vertex_data(offset, side_2, side_texture_index));
|
||||||
|
packed_data.push(pack_vertex_data(offset, side + 1, side_texture_index));
|
||||||
|
packed_data.push(pack_vertex_data(offset, side_2, side_texture_index));
|
||||||
|
|
||||||
|
heights.push(height_top);
|
||||||
|
heights.push(height_top);
|
||||||
|
heights.push(height_bottom);
|
||||||
|
heights.push(height_bottom);
|
||||||
|
|
||||||
|
indices.push(idx);
|
||||||
|
indices.push(idx + 2);
|
||||||
|
indices.push(idx + 1);
|
||||||
|
|
||||||
|
indices.push(idx + 1);
|
||||||
|
indices.push(idx + 2);
|
||||||
|
indices.push(idx + 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn pack_vertex_data(offset: UVec2, vert: usize, tex: u32) -> u32 {
|
||||||
|
//6 + 6 bits offset
|
||||||
|
//4 bits vert
|
||||||
|
//12 bits texture
|
||||||
|
let mut data = offset.x;
|
||||||
|
data += (offset.y) << 6;
|
||||||
|
data += (vert as u32) << (6 + 6);
|
||||||
|
data += tex << (6 + 6 + 4);
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
[package]
|
|
||||||
name = "camera_system"
|
|
||||||
version = "0.1.0"
|
|
||||||
edition = "2021"
|
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
bevy = "0.13.1"
|
|
||||||
@@ -1,127 +0,0 @@
|
|||||||
use crate::prelude::PhosCamera;
|
|
||||||
use bevy::input::mouse::MouseMotion;
|
|
||||||
use bevy::prelude::*;
|
|
||||||
use bevy::window::CursorGrabMode;
|
|
||||||
|
|
||||||
pub mod prelude {
|
|
||||||
use bevy::prelude::Component;
|
|
||||||
|
|
||||||
#[derive(Component, Default)]
|
|
||||||
pub struct PhosCamera {
|
|
||||||
pub min_height: f32,
|
|
||||||
pub max_height: f32,
|
|
||||||
pub speed: f32,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct PhosCameraPlugin;
|
|
||||||
|
|
||||||
impl Plugin for PhosCameraPlugin {
|
|
||||||
fn build(&self, app: &mut App) {
|
|
||||||
app.add_systems(Startup, setup).add_systems(
|
|
||||||
Update,
|
|
||||||
(grab_mouse, (update_camera, update_camera_mouse).chain()),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn setup(mut commands: Commands) {
|
|
||||||
commands.spawn((
|
|
||||||
Camera3dBundle {
|
|
||||||
transform: Transform::from_xyz(0., 30., 0.)
|
|
||||||
.looking_at(Vec3::new(1000., 0., 1000.), Vec3::Y),
|
|
||||||
..default()
|
|
||||||
},
|
|
||||||
PhosCamera {
|
|
||||||
speed: 100.,
|
|
||||||
..default()
|
|
||||||
},
|
|
||||||
));
|
|
||||||
}
|
|
||||||
fn update_camera(
|
|
||||||
mut cam_query: Query<(&PhosCamera, &mut Transform)>,
|
|
||||||
keyboard_input: Res<ButtonInput<KeyCode>>,
|
|
||||||
time: Res<Time>,
|
|
||||||
windows: Query<&Window>,
|
|
||||||
) {
|
|
||||||
let window = windows.single();
|
|
||||||
if window.cursor.grab_mode != CursorGrabMode::Locked {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let (cam, mut transform) = cam_query.single_mut();
|
|
||||||
|
|
||||||
let mut move_vec = Vec3::ZERO;
|
|
||||||
if keyboard_input.pressed(KeyCode::KeyA) {
|
|
||||||
move_vec += Vec3::NEG_X;
|
|
||||||
}
|
|
||||||
if keyboard_input.pressed(KeyCode::KeyD) {
|
|
||||||
move_vec += Vec3::X;
|
|
||||||
}
|
|
||||||
if keyboard_input.pressed(KeyCode::KeyW) {
|
|
||||||
move_vec += Vec3::NEG_Z;
|
|
||||||
}
|
|
||||||
if keyboard_input.pressed(KeyCode::KeyS) {
|
|
||||||
move_vec += Vec3::Z;
|
|
||||||
}
|
|
||||||
|
|
||||||
let rot = transform.rotation;
|
|
||||||
move_vec = (rot * move_vec.normalize_or_zero()) * cam.speed * time.delta_seconds();
|
|
||||||
|
|
||||||
if keyboard_input.pressed(KeyCode::ShiftLeft) {
|
|
||||||
move_vec += Vec3::from(transform.down());
|
|
||||||
}
|
|
||||||
if keyboard_input.pressed(KeyCode::Space) {
|
|
||||||
move_vec += Vec3::from(transform.up());
|
|
||||||
}
|
|
||||||
|
|
||||||
transform.translation += move_vec.normalize_or_zero() * cam.speed * time.delta_seconds();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn update_camera_mouse(
|
|
||||||
mut cam_query: Query<&mut Transform, With<PhosCamera>>,
|
|
||||||
mut mouse_move: EventReader<MouseMotion>,
|
|
||||||
time: Res<Time>,
|
|
||||||
windows: Query<&Window>,
|
|
||||||
) {
|
|
||||||
let window = windows.single();
|
|
||||||
if window.cursor.grab_mode != CursorGrabMode::Locked {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let mut transform = cam_query.single_mut();
|
|
||||||
|
|
||||||
for ev in mouse_move.read() {
|
|
||||||
let (mut yaw, mut pitch, _) = transform.rotation.to_euler(EulerRot::YXZ);
|
|
||||||
match window.cursor.grab_mode {
|
|
||||||
CursorGrabMode::None => (),
|
|
||||||
_ => {
|
|
||||||
// Using smallest of height or width ensures equal vertical and horizontal sensitivity
|
|
||||||
pitch -= (ev.delta.y * time.delta_seconds() * 5.).to_radians();
|
|
||||||
yaw -= (ev.delta.x * time.delta_seconds() * 5.).to_radians();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pitch = pitch.clamp(-1.54, 1.54);
|
|
||||||
|
|
||||||
// Order is important to prevent unintended roll
|
|
||||||
transform.rotation =
|
|
||||||
Quat::from_axis_angle(Vec3::Y, yaw) * Quat::from_axis_angle(Vec3::X, pitch);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn grab_mouse(
|
|
||||||
mut windows: Query<&mut Window>,
|
|
||||||
mouse: Res<ButtonInput<MouseButton>>,
|
|
||||||
key: Res<ButtonInput<KeyCode>>,
|
|
||||||
) {
|
|
||||||
let mut window = windows.single_mut();
|
|
||||||
|
|
||||||
if mouse.just_pressed(MouseButton::Middle) {
|
|
||||||
window.cursor.visible = false;
|
|
||||||
window.cursor.grab_mode = CursorGrabMode::Locked;
|
|
||||||
}
|
|
||||||
|
|
||||||
if key.just_pressed(KeyCode::Escape) {
|
|
||||||
window.cursor.visible = true;
|
|
||||||
window.cursor.grab_mode = CursorGrabMode::None;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -12,5 +12,9 @@ bevy-inspector-egui = "0.23.4"
|
|||||||
iyes_perf_ui = "0.2.3"
|
iyes_perf_ui = "0.2.3"
|
||||||
noise = "0.8.2"
|
noise = "0.8.2"
|
||||||
world_generation ={path="../../engine/world_generation"}
|
world_generation ={path="../../engine/world_generation"}
|
||||||
camera_system={path = "../camera_system"}
|
bevy_rapier3d = { version = "0.25.0", features = [ "simd-stable", "debug-render-3d","parallel" ] }
|
||||||
bevy_rapier3d = { version = "0.25.0", features = [ "simd-stable", "debug-render-3d" ] }
|
rayon = "1.10.0"
|
||||||
|
|
||||||
|
|
||||||
|
[features]
|
||||||
|
tracing = ["bevy/trace_tracy", "world_generation/tracing"]
|
||||||
Submodule game/main/assets updated: 256b49cc29...896ed4eede
243
game/main/src/camera_system/camera_plugin.rs
Normal file
243
game/main/src/camera_system/camera_plugin.rs
Normal file
@@ -0,0 +1,243 @@
|
|||||||
|
use bevy::core_pipeline::experimental::taa::{TemporalAntiAliasBundle, TemporalAntiAliasPlugin};
|
||||||
|
use bevy::input::mouse::{MouseMotion, MouseScrollUnit, MouseWheel};
|
||||||
|
use bevy::pbr::ScreenSpaceAmbientOcclusionBundle;
|
||||||
|
use bevy::prelude::*;
|
||||||
|
use bevy::window::CursorGrabMode;
|
||||||
|
use bevy_rapier3d::plugin::RapierContext;
|
||||||
|
use world_generation::hex_utils::HexCoord;
|
||||||
|
use world_generation::prelude::Map;
|
||||||
|
|
||||||
|
use super::components::*;
|
||||||
|
|
||||||
|
pub struct PhosCameraPlugin;
|
||||||
|
|
||||||
|
impl Plugin for PhosCameraPlugin {
|
||||||
|
fn build(&self, app: &mut App) {
|
||||||
|
app.register_type::<PhosCamera>();
|
||||||
|
|
||||||
|
app.add_systems(PreStartup, setup);
|
||||||
|
|
||||||
|
app.add_systems(Update, rts_camera_system);
|
||||||
|
app.add_systems(PostUpdate, limit_camera_bounds);
|
||||||
|
//Free Cam
|
||||||
|
//app.add_systems(Update, (grab_mouse, (update_camera, update_camera_mouse).chain()));
|
||||||
|
|
||||||
|
app.add_plugins(TemporalAntiAliasPlugin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn setup(mut commands: Commands, mut msaa: ResMut<Msaa>) {
|
||||||
|
commands
|
||||||
|
.spawn((
|
||||||
|
Camera3dBundle {
|
||||||
|
transform: Transform::from_xyz(0., 30., 0.).looking_to(Vec3::Z, Vec3::Y),
|
||||||
|
..default()
|
||||||
|
},
|
||||||
|
PhosCamera::default(),
|
||||||
|
PhosCameraTargets::default(),
|
||||||
|
))
|
||||||
|
.insert(TemporalAntiAliasBundle::default());
|
||||||
|
|
||||||
|
*msaa = Msaa::Off;
|
||||||
|
}
|
||||||
|
fn update_camera(
|
||||||
|
mut cam_query: Query<(&PhosCamera, &mut Transform)>,
|
||||||
|
keyboard_input: Res<ButtonInput<KeyCode>>,
|
||||||
|
time: Res<Time>,
|
||||||
|
windows: Query<&Window>,
|
||||||
|
) {
|
||||||
|
let window = windows.single();
|
||||||
|
if window.cursor.grab_mode != CursorGrabMode::Locked {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let (cam, mut transform) = cam_query.single_mut();
|
||||||
|
|
||||||
|
let mut move_vec = Vec3::ZERO;
|
||||||
|
if keyboard_input.pressed(KeyCode::KeyA) {
|
||||||
|
move_vec += Vec3::NEG_X;
|
||||||
|
}
|
||||||
|
if keyboard_input.pressed(KeyCode::KeyD) {
|
||||||
|
move_vec += Vec3::X;
|
||||||
|
}
|
||||||
|
if keyboard_input.pressed(KeyCode::KeyW) {
|
||||||
|
move_vec += Vec3::NEG_Z;
|
||||||
|
}
|
||||||
|
if keyboard_input.pressed(KeyCode::KeyS) {
|
||||||
|
move_vec += Vec3::Z;
|
||||||
|
}
|
||||||
|
|
||||||
|
let rot = transform.rotation;
|
||||||
|
move_vec = (rot * move_vec.normalize_or_zero()) * cam.speed * time.delta_seconds();
|
||||||
|
|
||||||
|
if keyboard_input.pressed(KeyCode::ShiftLeft) {
|
||||||
|
move_vec += Vec3::from(transform.down());
|
||||||
|
}
|
||||||
|
if keyboard_input.pressed(KeyCode::Space) {
|
||||||
|
move_vec += Vec3::from(transform.up());
|
||||||
|
}
|
||||||
|
|
||||||
|
transform.translation += move_vec.normalize_or_zero() * cam.speed * time.delta_seconds();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_camera_mouse(
|
||||||
|
mut cam_query: Query<&mut Transform, With<PhosCamera>>,
|
||||||
|
mut mouse_move: EventReader<MouseMotion>,
|
||||||
|
time: Res<Time>,
|
||||||
|
windows: Query<&Window>,
|
||||||
|
) {
|
||||||
|
let window = windows.single();
|
||||||
|
if window.cursor.grab_mode != CursorGrabMode::Locked {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let mut transform = cam_query.single_mut();
|
||||||
|
|
||||||
|
for ev in mouse_move.read() {
|
||||||
|
let (mut yaw, mut pitch, _) = transform.rotation.to_euler(EulerRot::YXZ);
|
||||||
|
match window.cursor.grab_mode {
|
||||||
|
CursorGrabMode::None => (),
|
||||||
|
_ => {
|
||||||
|
// Using smallest of height or width ensures equal vertical and horizontal sensitivity
|
||||||
|
pitch -= ev.delta.y.to_radians() * time.delta_seconds() * 5.;
|
||||||
|
yaw -= ev.delta.x.to_radians() * time.delta_seconds() * 5.;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pitch = pitch.clamp(-1.54, 1.54);
|
||||||
|
|
||||||
|
// Order is important to prevent unintended roll
|
||||||
|
transform.rotation = Quat::from_axis_angle(Vec3::Y, yaw) * Quat::from_axis_angle(Vec3::X, pitch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn grab_mouse(mut windows: Query<&mut Window>, mouse: Res<ButtonInput<MouseButton>>, key: Res<ButtonInput<KeyCode>>) {
|
||||||
|
let mut window = windows.single_mut();
|
||||||
|
|
||||||
|
if mouse.just_pressed(MouseButton::Middle) {
|
||||||
|
window.cursor.visible = false;
|
||||||
|
window.cursor.grab_mode = CursorGrabMode::Locked;
|
||||||
|
}
|
||||||
|
|
||||||
|
if key.just_pressed(KeyCode::Escape) {
|
||||||
|
window.cursor.visible = true;
|
||||||
|
window.cursor.grab_mode = CursorGrabMode::None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn rts_camera_system(
|
||||||
|
mut cam_query: Query<(&mut Transform, &PhosCamera, &mut PhosCameraTargets)>,
|
||||||
|
mut wheel: EventReader<MouseWheel>,
|
||||||
|
key: Res<ButtonInput<KeyCode>>,
|
||||||
|
time: Res<Time>,
|
||||||
|
heightmap: Res<Map>,
|
||||||
|
) {
|
||||||
|
let (mut cam, cam_cfg, mut cam_targets) = cam_query.single_mut();
|
||||||
|
let mut cam_move = Vec3::ZERO;
|
||||||
|
let mut cam_pos = cam.translation;
|
||||||
|
|
||||||
|
if key.pressed(KeyCode::KeyA) {
|
||||||
|
cam_move.x = 1.;
|
||||||
|
} else if key.pressed(KeyCode::KeyD) {
|
||||||
|
cam_move.x = -1.;
|
||||||
|
}
|
||||||
|
|
||||||
|
if key.pressed(KeyCode::KeyW) {
|
||||||
|
cam_move.z = 1.;
|
||||||
|
} else if key.pressed(KeyCode::KeyS) {
|
||||||
|
cam_move.z = -1.;
|
||||||
|
}
|
||||||
|
|
||||||
|
let move_speed = if key.pressed(KeyCode::ShiftLeft) {
|
||||||
|
cam_cfg.speed * 2.
|
||||||
|
} else {
|
||||||
|
cam_cfg.speed
|
||||||
|
};
|
||||||
|
|
||||||
|
cam_move = cam_move.normalize_or_zero() * move_speed * time.delta_seconds();
|
||||||
|
cam_pos -= cam_move;
|
||||||
|
|
||||||
|
let mut scroll = 0.0;
|
||||||
|
for e in wheel.read() {
|
||||||
|
match e.unit {
|
||||||
|
MouseScrollUnit::Line => scroll += e.y * 5.,
|
||||||
|
MouseScrollUnit::Pixel => scroll += e.y,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let ground_height = sample_ground(cam.translation, &heightmap);
|
||||||
|
|
||||||
|
cam_targets.height -= scroll;
|
||||||
|
if cam_targets.height > cam_cfg.max_height {
|
||||||
|
cam_targets.height = cam_cfg.max_height;
|
||||||
|
}
|
||||||
|
|
||||||
|
let min_height = ground_height + cam_cfg.min_height;
|
||||||
|
|
||||||
|
if min_height != cam_targets.last_height {
|
||||||
|
cam_targets.last_height = min_height;
|
||||||
|
cam_targets.anim_time = 0.;
|
||||||
|
cam_targets.rotate_time = 0.;
|
||||||
|
}
|
||||||
|
|
||||||
|
if scroll != 0. {
|
||||||
|
cam_targets.anim_time = 0.;
|
||||||
|
cam_targets.rotate_time = 0.;
|
||||||
|
if cam_targets.height < min_height {
|
||||||
|
cam_targets.height = min_height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let desired_height = if cam_targets.height < min_height {
|
||||||
|
min_height
|
||||||
|
} else {
|
||||||
|
cam_targets.height
|
||||||
|
};
|
||||||
|
if cam_targets.anim_time < 1. {
|
||||||
|
cam_targets.anim_time += time.delta_seconds() * cam_cfg.zoom_speed;
|
||||||
|
cam_targets.anim_time = cam_targets.anim_time.min(1.);
|
||||||
|
}
|
||||||
|
cam_pos.y = f32::lerp(cam_pos.y, desired_height, cam_targets.anim_time);
|
||||||
|
let t = cam_pos.y.remap(cam_cfg.min_height, cam_cfg.max_height, 0., 1.);
|
||||||
|
|
||||||
|
if cam_targets.rotate_time < 1. {
|
||||||
|
cam_targets.rotate_time += time.delta_seconds();
|
||||||
|
cam_targets.rotate_time = cam_targets.rotate_time.min(1.);
|
||||||
|
}
|
||||||
|
let angle = cam_cfg.min_angle.lerp(cam_cfg.max_angle, t);
|
||||||
|
let rot = Quat::from_axis_angle(Vec3::X, -angle);
|
||||||
|
cam.rotation = rot;
|
||||||
|
|
||||||
|
cam.translation = cam_pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn sample_ground(pos: Vec3, heightmap: &Map) -> f32 {
|
||||||
|
let tile_under = HexCoord::from_world_pos(pos);
|
||||||
|
let neighbors = heightmap.get_neighbors(&tile_under);
|
||||||
|
let mut ground_height = if heightmap.is_in_bounds(&tile_under) {
|
||||||
|
heightmap.sample_height(&tile_under)
|
||||||
|
} else {
|
||||||
|
heightmap.sea_level
|
||||||
|
};
|
||||||
|
|
||||||
|
for n in neighbors {
|
||||||
|
if let Some(h) = n {
|
||||||
|
if h > ground_height {
|
||||||
|
ground_height = h;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ground_height < heightmap.sea_level {
|
||||||
|
ground_height = heightmap.sea_level;
|
||||||
|
}
|
||||||
|
return ground_height;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn limit_camera_bounds(mut cam_query: Query<(&mut Transform, &CameraBounds)>) {
|
||||||
|
let (mut tranform, bounds) = cam_query.single_mut();
|
||||||
|
|
||||||
|
let mut pos = tranform.translation;
|
||||||
|
|
||||||
|
pos.x = pos.x.clamp(bounds.min.x, bounds.max.x);
|
||||||
|
pos.z = pos.z.clamp(bounds.min.y, bounds.max.y);
|
||||||
|
|
||||||
|
tranform.translation = pos;
|
||||||
|
}
|
||||||
69
game/main/src/camera_system/components.rs
Normal file
69
game/main/src/camera_system/components.rs
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
use bevy::prelude::*;
|
||||||
|
use world_generation::{
|
||||||
|
hex_utils::{tile_to_world_distance, SHORT_DIAGONAL},
|
||||||
|
prelude::Chunk,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Component, Reflect)]
|
||||||
|
#[reflect(Component)]
|
||||||
|
pub struct PhosCamera {
|
||||||
|
pub min_height: f32,
|
||||||
|
pub max_height: f32,
|
||||||
|
pub speed: f32,
|
||||||
|
pub zoom_speed: f32,
|
||||||
|
pub min_angle: f32,
|
||||||
|
pub max_angle: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for PhosCamera {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
min_height: 10.,
|
||||||
|
max_height: 120.,
|
||||||
|
speed: 30.,
|
||||||
|
zoom_speed: 0.3,
|
||||||
|
min_angle: (20. as f32).to_radians(),
|
||||||
|
max_angle: 1.,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Component)]
|
||||||
|
pub struct PhosCameraTargets {
|
||||||
|
pub height: f32,
|
||||||
|
pub forward: Vec3,
|
||||||
|
pub last_height: f32,
|
||||||
|
pub anim_time: f32,
|
||||||
|
pub rotate_time: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for PhosCameraTargets {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
height: Default::default(),
|
||||||
|
forward: Vec3::Z,
|
||||||
|
last_height: Default::default(),
|
||||||
|
anim_time: Default::default(),
|
||||||
|
rotate_time: Default::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Component, Default)]
|
||||||
|
pub struct CameraBounds {
|
||||||
|
pub min: Vec2,
|
||||||
|
pub max: Vec2,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CameraBounds {
|
||||||
|
pub fn from_size(size: UVec2) -> Self {
|
||||||
|
let padding = Chunk::WORLD_SIZE;
|
||||||
|
return Self {
|
||||||
|
min: Vec2::ZERO - padding,
|
||||||
|
max: Vec2::new(
|
||||||
|
(size.x as usize * Chunk::SIZE) as f32 * SHORT_DIAGONAL,
|
||||||
|
(size.y * Chunk::SIZE as u32) as f32 * 1.5,
|
||||||
|
) + padding,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
2
game/main/src/camera_system/mod.rs
Normal file
2
game/main/src/camera_system/mod.rs
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
pub mod camera_plugin;
|
||||||
|
pub mod components;
|
||||||
@@ -1,35 +1,42 @@
|
|||||||
|
use bevy::pbr::wireframe::WireframePlugin;
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use bevy::render::texture::{ImageAddressMode, ImageFilterMode, ImageSamplerDescriptor};
|
use bevy::render::texture::{ImageAddressMode, ImageFilterMode, ImageSamplerDescriptor};
|
||||||
use bevy::window::PresentMode;
|
use bevy::window::PresentMode;
|
||||||
use bevy_inspector_egui::quick::WorldInspectorPlugin;
|
use bevy_inspector_egui::quick::WorldInspectorPlugin;
|
||||||
|
use phos::PhosGamePlugin;
|
||||||
|
|
||||||
|
mod camera_system;
|
||||||
|
mod map_rendering;
|
||||||
mod phos;
|
mod phos;
|
||||||
mod prelude;
|
mod prelude;
|
||||||
mod shader_extensions;
|
mod shader_extensions;
|
||||||
use phos::PhosGamePlugin;
|
mod utlis;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
App::new()
|
App::new()
|
||||||
.add_plugins((
|
.add_plugins((
|
||||||
DefaultPlugins.set(WindowPlugin {
|
DefaultPlugins
|
||||||
primary_window: Some(Window {
|
.set(WindowPlugin {
|
||||||
title: "Phos".into(),
|
primary_window: Some(Window {
|
||||||
name: Some("phos".into()),
|
title: "Phos".into(),
|
||||||
resolution: (1920.0, 1080.0).into(),
|
name: Some("phos".into()),
|
||||||
resizable: true,
|
// resolution: (1920., 1080.).into(),
|
||||||
present_mode: PresentMode::AutoNoVsync,
|
present_mode: PresentMode::AutoNoVsync,
|
||||||
|
mode: bevy::window::WindowMode::BorderlessFullscreen,
|
||||||
|
..default()
|
||||||
|
}),
|
||||||
..default()
|
..default()
|
||||||
|
})
|
||||||
|
.set(ImagePlugin {
|
||||||
|
default_sampler: ImageSamplerDescriptor {
|
||||||
|
address_mode_u: ImageAddressMode::Repeat,
|
||||||
|
address_mode_v: ImageAddressMode::Repeat,
|
||||||
|
mag_filter: ImageFilterMode::Nearest,
|
||||||
|
..default()
|
||||||
|
},
|
||||||
}),
|
}),
|
||||||
..default()
|
|
||||||
}).set(ImagePlugin {
|
|
||||||
default_sampler: ImageSamplerDescriptor {
|
|
||||||
address_mode_u: ImageAddressMode::Repeat,
|
|
||||||
address_mode_v: ImageAddressMode::Repeat,
|
|
||||||
mag_filter: ImageFilterMode::Nearest,
|
|
||||||
..default()
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
WorldInspectorPlugin::new(),
|
WorldInspectorPlugin::new(),
|
||||||
|
WireframePlugin,
|
||||||
PhosGamePlugin,
|
PhosGamePlugin,
|
||||||
))
|
))
|
||||||
.run();
|
.run();
|
||||||
|
|||||||
98
game/main/src/map_rendering/chunk_rebuild.rs
Normal file
98
game/main/src/map_rendering/chunk_rebuild.rs
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
use bevy::prelude::*;
|
||||||
|
use bevy_rapier3d::geometry::{Collider, TriMeshFlags};
|
||||||
|
use rayon::iter::{IntoParallelRefIterator, ParallelIterator};
|
||||||
|
use world_generation::{
|
||||||
|
biome_painter::BiomePainterAsset,
|
||||||
|
chunk_colliders::generate_chunk_collider,
|
||||||
|
hex_utils::{self, offset_to_world, SHORT_DIAGONAL},
|
||||||
|
mesh_generator::generate_chunk_mesh,
|
||||||
|
prelude::{Chunk, Map},
|
||||||
|
tile_manager::TileAsset,
|
||||||
|
tile_mapper::TileMapperAsset,
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
prelude::{ChunkAtlas, PhosChunk, PhosChunkRegistry},
|
||||||
|
utlis::render_distance_system::RenderDistanceVisibility,
|
||||||
|
};
|
||||||
|
|
||||||
|
use super::prelude::CurrentBiomePainter;
|
||||||
|
pub struct ChunkRebuildPlugin;
|
||||||
|
|
||||||
|
impl Plugin for ChunkRebuildPlugin {
|
||||||
|
fn build(&self, app: &mut App) {
|
||||||
|
app.insert_resource(ChunkRebuildQueue::default());
|
||||||
|
app.init_resource::<PhosChunkRegistry>();
|
||||||
|
app.add_systems(PreUpdate, chunk_rebuilder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Resource, Default)]
|
||||||
|
pub struct ChunkRebuildQueue {
|
||||||
|
pub queue: Vec<usize>,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn chunk_rebuilder(
|
||||||
|
mut commands: Commands,
|
||||||
|
mut queue: ResMut<ChunkRebuildQueue>,
|
||||||
|
mut chunks: ResMut<PhosChunkRegistry>,
|
||||||
|
atlas: Res<ChunkAtlas>,
|
||||||
|
heightmap: Res<Map>,
|
||||||
|
tile_assets: Res<Assets<TileAsset>>,
|
||||||
|
tile_mappers: Res<Assets<TileMapperAsset>>,
|
||||||
|
mut meshes: ResMut<Assets<Mesh>>,
|
||||||
|
biome_painters: Res<Assets<BiomePainterAsset>>,
|
||||||
|
painter: Res<CurrentBiomePainter>,
|
||||||
|
) {
|
||||||
|
if queue.queue.len() == 0 {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
queue.queue.dedup();
|
||||||
|
|
||||||
|
for chunk_index in &queue.queue {
|
||||||
|
let chunk = chunks.chunks[*chunk_index];
|
||||||
|
commands.entity(chunk).despawn();
|
||||||
|
}
|
||||||
|
|
||||||
|
let b_painter = biome_painters.get(painter.handle.clone());
|
||||||
|
|
||||||
|
let cur_painter = b_painter.unwrap();
|
||||||
|
|
||||||
|
let chunk_meshes: Vec<_> = queue
|
||||||
|
.queue
|
||||||
|
.par_iter()
|
||||||
|
.map(|idx| {
|
||||||
|
let chunk = &heightmap.chunks[*idx];
|
||||||
|
let mesh = generate_chunk_mesh(chunk, &heightmap, cur_painter, &tile_assets, &tile_mappers);
|
||||||
|
let (col_verts, col_indicies) = generate_chunk_collider(chunk, &heightmap);
|
||||||
|
let collider =
|
||||||
|
Collider::trimesh_with_flags(col_verts, col_indicies, TriMeshFlags::MERGE_DUPLICATE_VERTICES);
|
||||||
|
return (
|
||||||
|
mesh,
|
||||||
|
collider,
|
||||||
|
offset_to_world(chunk.chunk_offset * Chunk::SIZE as i32, 0.),
|
||||||
|
hex_utils::offset_to_index(chunk.chunk_offset, heightmap.width),
|
||||||
|
);
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
for (mesh, collider, pos, index) in chunk_meshes {
|
||||||
|
let chunk = commands.spawn((
|
||||||
|
MaterialMeshBundle {
|
||||||
|
mesh: meshes.add(mesh),
|
||||||
|
material: atlas.chunk_material_handle.clone(),
|
||||||
|
transform: Transform::from_translation(pos),
|
||||||
|
..default()
|
||||||
|
},
|
||||||
|
PhosChunk::new(index),
|
||||||
|
RenderDistanceVisibility::default().with_offset(Vec3::new(
|
||||||
|
(Chunk::SIZE / 2) as f32 * SHORT_DIAGONAL,
|
||||||
|
0.,
|
||||||
|
(Chunk::SIZE / 2) as f32 * 1.5,
|
||||||
|
)),
|
||||||
|
collider,
|
||||||
|
));
|
||||||
|
chunks.chunks[index] = chunk.id();
|
||||||
|
}
|
||||||
|
queue.queue.clear();
|
||||||
|
}
|
||||||
304
game/main/src/map_rendering/map_init.rs
Normal file
304
game/main/src/map_rendering/map_init.rs
Normal file
@@ -0,0 +1,304 @@
|
|||||||
|
#[cfg(feature = "tracing")]
|
||||||
|
use bevy::log::*;
|
||||||
|
use bevy::{asset::LoadState, pbr::ExtendedMaterial, prelude::*};
|
||||||
|
use bevy_inspector_egui::quick::ResourceInspectorPlugin;
|
||||||
|
use bevy_rapier3d::geometry::Collider;
|
||||||
|
use rayon::iter::{IntoParallelIterator, IntoParallelRefIterator, ParallelIterator};
|
||||||
|
use world_generation::{
|
||||||
|
biome_painter::*,
|
||||||
|
chunk_colliders::generate_chunk_collider,
|
||||||
|
heightmap::generate_heightmap,
|
||||||
|
hex_utils::{self, offset_to_world, OUTER_RADIUS, SHORT_DIAGONAL},
|
||||||
|
mesh_generator::generate_chunk_mesh,
|
||||||
|
prelude::*,
|
||||||
|
tile_manager::*,
|
||||||
|
tile_mapper::*,
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
camera_system::components::*,
|
||||||
|
prelude::{ChunkAtlas, PhosChunk, PhosChunkRegistry, PhosMap},
|
||||||
|
shader_extensions::chunk_material::ChunkMaterial,
|
||||||
|
utlis::render_distance_system::RenderDistanceVisibility,
|
||||||
|
};
|
||||||
|
|
||||||
|
use super::{
|
||||||
|
chunk_rebuild::ChunkRebuildPlugin, prelude::CurrentBiomePainter, terraforming_test::TerraFormingTestPlugin,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct MapInitPlugin;
|
||||||
|
|
||||||
|
impl Plugin for MapInitPlugin {
|
||||||
|
fn build(&self, app: &mut App) {
|
||||||
|
app.add_plugins((
|
||||||
|
ResourceInspectorPlugin::<PhosMap>::default(),
|
||||||
|
ResourceInspectorPlugin::<GenerationConfig>::default(),
|
||||||
|
ChunkRebuildPlugin,
|
||||||
|
TerraFormingTestPlugin,
|
||||||
|
));
|
||||||
|
|
||||||
|
app.add_systems(Startup, (load_textures, load_tiles));
|
||||||
|
app.add_systems(PostStartup, create_map);
|
||||||
|
|
||||||
|
app.add_systems(Update, finalize_texture);
|
||||||
|
app.add_systems(PostUpdate, (despawn_map, spawn_map).chain());
|
||||||
|
app.insert_resource(TileManager::default());
|
||||||
|
app.insert_resource(PhosMap::default());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn load_textures(
|
||||||
|
mut commands: Commands,
|
||||||
|
asset_server: Res<AssetServer>,
|
||||||
|
mut standard_materials: ResMut<Assets<StandardMaterial>>,
|
||||||
|
) {
|
||||||
|
let main_tex = asset_server.load("textures/world/stack.png");
|
||||||
|
|
||||||
|
let water_material = standard_materials.add(StandardMaterial {
|
||||||
|
base_color: Color::AQUAMARINE.with_a(0.5),
|
||||||
|
alpha_mode: AlphaMode::Blend,
|
||||||
|
..default()
|
||||||
|
});
|
||||||
|
commands.insert_resource(ChunkAtlas {
|
||||||
|
handle: main_tex.clone(),
|
||||||
|
is_loaded: false,
|
||||||
|
chunk_material_handle: Handle::default(),
|
||||||
|
water_material: water_material,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn load_tiles(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||||
|
let handle: Handle<BiomePainterAsset> = asset_server.load("biome_painters/terra.biomes.json");
|
||||||
|
commands.insert_resource(CurrentBiomePainter { handle });
|
||||||
|
}
|
||||||
|
|
||||||
|
fn finalize_texture(
|
||||||
|
asset_server: Res<AssetServer>,
|
||||||
|
mut atlas: ResMut<ChunkAtlas>,
|
||||||
|
mut map: ResMut<PhosMap>,
|
||||||
|
mut images: ResMut<Assets<Image>>,
|
||||||
|
painter: Res<CurrentBiomePainter>,
|
||||||
|
painter_load: Res<BiomePainterLoadState>,
|
||||||
|
tile_load: Res<TileAssetLoadState>,
|
||||||
|
mut chunk_materials: ResMut<Assets<ExtendedMaterial<StandardMaterial, ChunkMaterial>>>,
|
||||||
|
mapper_load: Res<TileMapperLoadState>,
|
||||||
|
) {
|
||||||
|
if atlas.is_loaded {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if !painter_load.is_all_loaded() || !tile_load.is_all_loaded() || !mapper_load.is_all_loaded() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if asset_server.load_state(atlas.handle.clone()) != LoadState::Loaded {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if asset_server.load_state(painter.handle.clone()) != LoadState::Loaded {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let image = images.get_mut(&atlas.handle).unwrap();
|
||||||
|
|
||||||
|
let array_layers = 14;
|
||||||
|
image.reinterpret_stacked_2d_as_array(array_layers);
|
||||||
|
|
||||||
|
atlas.is_loaded = true;
|
||||||
|
let chunk_material = chunk_materials.add(ExtendedMaterial {
|
||||||
|
base: StandardMaterial::default(),
|
||||||
|
extension: ChunkMaterial {
|
||||||
|
array_texture: atlas.handle.clone(),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
atlas.chunk_material_handle = chunk_material;
|
||||||
|
map.ready = true;
|
||||||
|
map.regenerate = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_map(mut commands: Commands, mut cam: Query<(&mut Transform, Entity), With<PhosCamera>>) {
|
||||||
|
let config = GenerationConfig {
|
||||||
|
layers: vec![
|
||||||
|
GeneratorLayer {
|
||||||
|
base_roughness: 2.14,
|
||||||
|
roughness: 0.87,
|
||||||
|
strength: 8.3,
|
||||||
|
min_value: -0.2,
|
||||||
|
persistence: 0.77,
|
||||||
|
is_rigid: false,
|
||||||
|
weight: 0.,
|
||||||
|
weight_multi: 0.,
|
||||||
|
layers: 4,
|
||||||
|
first_layer_mask: false,
|
||||||
|
},
|
||||||
|
GeneratorLayer {
|
||||||
|
base_roughness: 2.85,
|
||||||
|
roughness: 2.,
|
||||||
|
strength: -0.23,
|
||||||
|
min_value: -0.,
|
||||||
|
persistence: 1.,
|
||||||
|
is_rigid: false,
|
||||||
|
weight: 0.,
|
||||||
|
weight_multi: 0.,
|
||||||
|
layers: 4,
|
||||||
|
first_layer_mask: false,
|
||||||
|
},
|
||||||
|
GeneratorLayer {
|
||||||
|
base_roughness: 2.6,
|
||||||
|
roughness: 4.,
|
||||||
|
strength: 3.1,
|
||||||
|
min_value: 0.,
|
||||||
|
persistence: 1.57,
|
||||||
|
is_rigid: true,
|
||||||
|
weight: 1.,
|
||||||
|
weight_multi: 0.35,
|
||||||
|
layers: 4,
|
||||||
|
first_layer_mask: true,
|
||||||
|
},
|
||||||
|
GeneratorLayer {
|
||||||
|
base_roughness: 3.87,
|
||||||
|
roughness: 5.8,
|
||||||
|
strength: -1.,
|
||||||
|
min_value: 0.,
|
||||||
|
persistence: 0.,
|
||||||
|
is_rigid: true,
|
||||||
|
weight: 1.,
|
||||||
|
weight_multi: 4.57,
|
||||||
|
layers: 3,
|
||||||
|
first_layer_mask: true,
|
||||||
|
},
|
||||||
|
GeneratorLayer {
|
||||||
|
base_roughness: 3.87,
|
||||||
|
roughness: 5.8,
|
||||||
|
strength: -1.5,
|
||||||
|
min_value: 0.,
|
||||||
|
persistence: 0.3,
|
||||||
|
is_rigid: true,
|
||||||
|
weight: 1.,
|
||||||
|
weight_multi: 4.57,
|
||||||
|
layers: 3,
|
||||||
|
first_layer_mask: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
noise_scale: 450.,
|
||||||
|
sea_level: 8.5,
|
||||||
|
border_size: 64.,
|
||||||
|
size: UVec2::splat(1),
|
||||||
|
// size: UVec2::splat(1),
|
||||||
|
};
|
||||||
|
let heightmap = generate_heightmap(&config, 4);
|
||||||
|
|
||||||
|
let (mut cam_t, cam_entity) = cam.single_mut();
|
||||||
|
cam_t.translation = heightmap.get_center();
|
||||||
|
|
||||||
|
commands.entity(cam_entity).insert(CameraBounds::from_size(config.size));
|
||||||
|
|
||||||
|
commands.insert_resource(heightmap);
|
||||||
|
commands.insert_resource(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn spawn_map(
|
||||||
|
heightmap: Res<Map>,
|
||||||
|
mut commands: Commands,
|
||||||
|
mut meshes: ResMut<Assets<Mesh>>,
|
||||||
|
atlas: Res<ChunkAtlas>,
|
||||||
|
mut map: ResMut<PhosMap>,
|
||||||
|
tile_assets: Res<Assets<TileAsset>>,
|
||||||
|
tile_mappers: Res<Assets<TileMapperAsset>>,
|
||||||
|
biome_painters: Res<Assets<BiomePainterAsset>>,
|
||||||
|
painter: Res<CurrentBiomePainter>,
|
||||||
|
) {
|
||||||
|
if !map.ready || !map.regenerate {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let b_painter = biome_painters.get(painter.handle.clone());
|
||||||
|
map.regenerate = false;
|
||||||
|
|
||||||
|
let cur_painter = b_painter.unwrap();
|
||||||
|
let tile_collider = Collider::cylinder(10., OUTER_RADIUS);
|
||||||
|
let chunk_meshes: Vec<_> = heightmap
|
||||||
|
.chunks
|
||||||
|
.par_iter()
|
||||||
|
.map(|chunk: &Chunk| {
|
||||||
|
#[cfg(feature = "tracing")]
|
||||||
|
let _gen_mesh = info_span!("Generate Chunk").entered();
|
||||||
|
let mesh = generate_chunk_mesh(chunk, &heightmap, cur_painter, &tile_assets, &tile_mappers);
|
||||||
|
|
||||||
|
return (
|
||||||
|
mesh,
|
||||||
|
offset_to_world(chunk.chunk_offset * Chunk::SIZE as i32, 0.),
|
||||||
|
hex_utils::offset_to_index(chunk.chunk_offset, heightmap.width),
|
||||||
|
);
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let mut registry = PhosChunkRegistry::new(chunk_meshes.len());
|
||||||
|
|
||||||
|
{
|
||||||
|
#[cfg(feature = "tracing")]
|
||||||
|
let _spawn_span = info_span!("Spawn Chunks").entered();
|
||||||
|
let visibility_offset = Vec3::new(
|
||||||
|
(Chunk::SIZE / 2) as f32 * SHORT_DIAGONAL,
|
||||||
|
0.,
|
||||||
|
(Chunk::SIZE / 2) as f32 * 1.5,
|
||||||
|
);
|
||||||
|
for (mesh, pos, index) in chunk_meshes {
|
||||||
|
// let mesh_handle = meshes.a
|
||||||
|
let mut chunk = commands.spawn((
|
||||||
|
MaterialMeshBundle {
|
||||||
|
mesh: meshes.add(mesh),
|
||||||
|
material: atlas.chunk_material_handle.clone(),
|
||||||
|
transform: Transform::from_translation(pos),
|
||||||
|
..default()
|
||||||
|
},
|
||||||
|
PhosChunk::new(index),
|
||||||
|
RenderDistanceVisibility::default().with_offset(visibility_offset),
|
||||||
|
));
|
||||||
|
chunk.with_children(|b| {
|
||||||
|
let heights = &heightmap.chunks[index];
|
||||||
|
let mut colliders: Vec<_> = (0..(Chunk::SIZE * Chunk::SIZE))
|
||||||
|
.into_par_iter()
|
||||||
|
.map(|_| Collider::capsule_y(10., OUTER_RADIUS))
|
||||||
|
.collect();
|
||||||
|
for z in 0..Chunk::SIZE {
|
||||||
|
for x in 0..Chunk::SIZE {
|
||||||
|
let h = heights.heights[x + z * Chunk::SIZE];
|
||||||
|
b.spawn((
|
||||||
|
colliders.remove(0),
|
||||||
|
Transform::from_translation(offset_to_world(IVec2::new(x as i32, z as i32), h)),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
registry.chunks.push(chunk.id());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
commands.spawn((PbrBundle {
|
||||||
|
transform: Transform::from_translation(heightmap.get_center()),
|
||||||
|
mesh: meshes.add(
|
||||||
|
Plane3d::default()
|
||||||
|
.mesh()
|
||||||
|
.size(heightmap.get_world_width(), heightmap.get_world_height()),
|
||||||
|
),
|
||||||
|
material: atlas.water_material.clone(),
|
||||||
|
..default()
|
||||||
|
},));
|
||||||
|
|
||||||
|
commands.insert_resource(registry);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn despawn_map(
|
||||||
|
mut commands: Commands,
|
||||||
|
mut heightmap: ResMut<Map>,
|
||||||
|
cfg: Res<GenerationConfig>,
|
||||||
|
map: Res<PhosMap>,
|
||||||
|
chunks: Query<Entity, With<PhosChunk>>,
|
||||||
|
) {
|
||||||
|
if !map.regenerate {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for chunk in chunks.iter() {
|
||||||
|
commands.entity(chunk).despawn();
|
||||||
|
}
|
||||||
|
|
||||||
|
*heightmap = generate_heightmap(&cfg, 4);
|
||||||
|
}
|
||||||
4
game/main/src/map_rendering/mod.rs
Normal file
4
game/main/src/map_rendering/mod.rs
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
pub mod chunk_rebuild;
|
||||||
|
pub mod map_init;
|
||||||
|
pub mod prelude;
|
||||||
|
pub mod terraforming_test;
|
||||||
7
game/main/src/map_rendering/prelude.rs
Normal file
7
game/main/src/map_rendering/prelude.rs
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
use bevy::prelude::*;
|
||||||
|
use world_generation::biome_painter::BiomePainterAsset;
|
||||||
|
|
||||||
|
#[derive(Resource)]
|
||||||
|
pub struct CurrentBiomePainter {
|
||||||
|
pub handle: Handle<BiomePainterAsset>,
|
||||||
|
}
|
||||||
73
game/main/src/map_rendering/terraforming_test.rs
Normal file
73
game/main/src/map_rendering/terraforming_test.rs
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
use bevy::{prelude::*, window::PrimaryWindow};
|
||||||
|
use bevy_rapier3d::{pipeline::QueryFilter, plugin::RapierContext};
|
||||||
|
use world_generation::{hex_utils::HexCoord, prelude::Map};
|
||||||
|
|
||||||
|
use crate::{camera_system::components::PhosCamera, prelude::PhosChunkRegistry};
|
||||||
|
|
||||||
|
use super::chunk_rebuild::ChunkRebuildQueue;
|
||||||
|
|
||||||
|
pub struct TerraFormingTestPlugin;
|
||||||
|
|
||||||
|
impl Plugin for TerraFormingTestPlugin {
|
||||||
|
fn build(&self, app: &mut App) {
|
||||||
|
app.add_systems(Update, deform);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deform(
|
||||||
|
cam_query: Query<(&GlobalTransform, &Camera), With<PhosCamera>>,
|
||||||
|
window: Query<&Window, With<PrimaryWindow>>,
|
||||||
|
mouse: Res<ButtonInput<MouseButton>>,
|
||||||
|
rapier_context: Res<RapierContext>,
|
||||||
|
mut heightmap: ResMut<Map>,
|
||||||
|
mut rebuild: ResMut<ChunkRebuildQueue>,
|
||||||
|
time: Res<Time>,
|
||||||
|
) {
|
||||||
|
let mut multi = 0.;
|
||||||
|
if mouse.pressed(MouseButton::Left) {
|
||||||
|
multi = 1.;
|
||||||
|
} else if mouse.pressed(MouseButton::Right) {
|
||||||
|
multi = -1.;
|
||||||
|
}
|
||||||
|
|
||||||
|
if multi == 0. {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let win = window.single();
|
||||||
|
let (cam_transform, camera) = cam_query.single();
|
||||||
|
let Some(cursor_pos) = win.cursor_position() else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
let Some(cam_ray) = camera.viewport_to_world(cam_transform, cursor_pos) else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
let collision = rapier_context.cast_ray(
|
||||||
|
cam_ray.origin,
|
||||||
|
cam_ray.direction.into(),
|
||||||
|
100.,
|
||||||
|
true,
|
||||||
|
QueryFilter::only_fixed(),
|
||||||
|
);
|
||||||
|
|
||||||
|
if let Some((_, dist)) = collision {
|
||||||
|
let contact_point = cam_ray.get_point(dist);
|
||||||
|
let contact_coord = HexCoord::from_world_pos(contact_point);
|
||||||
|
let cur_height = heightmap.sample_height(&contact_coord);
|
||||||
|
heightmap.set_height(&contact_coord, cur_height + 1. * time.delta_seconds() * multi);
|
||||||
|
let cur_chunk = contact_coord.to_chunk_index(heightmap.width);
|
||||||
|
|
||||||
|
if contact_coord.is_on_chunk_edge() {
|
||||||
|
let neighbors = contact_coord.get_neighbors();
|
||||||
|
let mut other_chunks: Vec<_> = neighbors
|
||||||
|
.iter()
|
||||||
|
.map(|c| c.to_chunk_index(heightmap.width))
|
||||||
|
.filter(|c| c != &cur_chunk)
|
||||||
|
.collect();
|
||||||
|
rebuild.queue.append(&mut other_chunks);
|
||||||
|
}
|
||||||
|
rebuild.queue.push(cur_chunk);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,38 +1,38 @@
|
|||||||
use crate::prelude::*;
|
use crate::camera_system::camera_plugin::PhosCameraPlugin;
|
||||||
|
use crate::camera_system::components::PhosCamera;
|
||||||
|
use crate::map_rendering::chunk_rebuild::ChunkRebuildPlugin;
|
||||||
|
use crate::map_rendering::map_init::MapInitPlugin;
|
||||||
use crate::shader_extensions::chunk_material::ChunkMaterial;
|
use crate::shader_extensions::chunk_material::ChunkMaterial;
|
||||||
use bevy::asset::LoadState;
|
use crate::utlis::render_distance_system::RenderDistancePlugin;
|
||||||
use bevy::core_pipeline::experimental::taa::TemporalAntiAliasPlugin;
|
|
||||||
use bevy::pbr::ExtendedMaterial;
|
use bevy::pbr::ExtendedMaterial;
|
||||||
use bevy::{pbr::CascadeShadowConfig, prelude::*};
|
use bevy::{
|
||||||
|
pbr::{wireframe::WireframeConfig, CascadeShadowConfig},
|
||||||
|
prelude::*,
|
||||||
|
};
|
||||||
|
use bevy_rapier3d::dynamics::{Ccd, RigidBody, Velocity};
|
||||||
|
use bevy_rapier3d::geometry::Collider;
|
||||||
use bevy_rapier3d::plugin::{NoUserData, RapierPhysicsPlugin};
|
use bevy_rapier3d::plugin::{NoUserData, RapierPhysicsPlugin};
|
||||||
use bevy_rapier3d::render::RapierDebugRenderPlugin;
|
|
||||||
use camera_system::PhosCameraPlugin;
|
|
||||||
use iyes_perf_ui::prelude::*;
|
use iyes_perf_ui::prelude::*;
|
||||||
use world_generation::biome_painter::{
|
use world_generation::biome_painter::BiomePainterPlugin;
|
||||||
BiomePainterAsset, BiomePainterLoadState, BiomePainterPlugin,
|
use world_generation::tile_manager::TileAssetPlugin;
|
||||||
};
|
use world_generation::tile_mapper::TileMapperAssetPlugin;
|
||||||
use world_generation::hex_utils::offset_to_world;
|
|
||||||
use world_generation::tile_manager::{TileAsset, TileAssetLoadState, TileAssetPlugin, TileManager};
|
|
||||||
use world_generation::tile_mapper::{TileMapperAsset, TileMapperAssetPlugin, TileMapperLoadState};
|
|
||||||
use world_generation::{
|
|
||||||
heightmap::generate_heightmap, mesh_generator::generate_chunk_mesh, prelude::*,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub struct PhosGamePlugin;
|
pub struct PhosGamePlugin;
|
||||||
|
|
||||||
impl Plugin for PhosGamePlugin {
|
impl Plugin for PhosGamePlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
app.add_plugins(PhosCameraPlugin)
|
app.add_plugins((
|
||||||
.add_plugins(MaterialPlugin::<
|
PhosCameraPlugin,
|
||||||
ExtendedMaterial<StandardMaterial, ChunkMaterial>,
|
MapInitPlugin,
|
||||||
>::default())
|
MaterialPlugin::<ExtendedMaterial<StandardMaterial, ChunkMaterial>>::default(),
|
||||||
.add_plugins(TemporalAntiAliasPlugin);
|
RenderDistancePlugin,
|
||||||
|
));
|
||||||
|
|
||||||
//Systems - Startup
|
//Systems - Startup
|
||||||
app.add_systems(Startup, init_game)
|
app.add_systems(Startup, init_game);
|
||||||
.add_systems(Startup, (load_textures, load_tiles, create_map).chain());
|
|
||||||
//Systems - Update
|
//Systems - Update
|
||||||
app.add_systems(Update, (finalize_texture, spawn_map));
|
app.add_systems(Update, spawn_sphere);
|
||||||
|
|
||||||
//Perf UI
|
//Perf UI
|
||||||
app.add_plugins(bevy::diagnostic::FrameTimeDiagnosticsPlugin)
|
app.add_plugins(bevy::diagnostic::FrameTimeDiagnosticsPlugin)
|
||||||
@@ -45,12 +45,17 @@ impl Plugin for PhosGamePlugin {
|
|||||||
app.add_plugins(TileMapperAssetPlugin);
|
app.add_plugins(TileMapperAssetPlugin);
|
||||||
app.add_plugins(BiomePainterPlugin);
|
app.add_plugins(BiomePainterPlugin);
|
||||||
//Physics
|
//Physics
|
||||||
app.add_plugins(RapierPhysicsPlugin::<NoUserData>::default())
|
app.add_plugins(RapierPhysicsPlugin::<NoUserData>::default());
|
||||||
.add_plugins(RapierDebugRenderPlugin::default());
|
// app.add_plugins(RapierDebugRenderPlugin::default());
|
||||||
|
|
||||||
|
app.insert_resource(WireframeConfig {
|
||||||
|
global: false,
|
||||||
|
default_color: Color::hex("FF0064").unwrap(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn init_game(mut commands: Commands) {
|
fn init_game(mut commands: Commands, mut materials: ResMut<Assets<StandardMaterial>>) {
|
||||||
commands.spawn((
|
commands.spawn((
|
||||||
PerfUiRoot::default(),
|
PerfUiRoot::default(),
|
||||||
PerfUiEntryFPS::default(),
|
PerfUiEntryFPS::default(),
|
||||||
@@ -65,171 +70,44 @@ fn init_game(mut commands: Commands) {
|
|||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
cascade_shadow_config: CascadeShadowConfig {
|
cascade_shadow_config: CascadeShadowConfig {
|
||||||
bounds: vec![500., 1000., 2000., 5000.],
|
bounds: vec![200., 400., 600., 800.],
|
||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
transform: Transform::from_xyz(500., 260.0, 500.).looking_at(Vec3::ZERO, Vec3::Y),
|
transform: Transform::from_xyz(500., 260.0, 500.).looking_at(Vec3::ZERO, Vec3::Y),
|
||||||
..default()
|
..default()
|
||||||
});
|
});
|
||||||
|
|
||||||
commands.insert_resource(PhosMap::default());
|
let sphere_mat = StandardMaterial {
|
||||||
commands.insert_resource(TileManager::default());
|
base_color: Color::CYAN,
|
||||||
|
..default()
|
||||||
|
};
|
||||||
|
let handle = materials.add(sphere_mat);
|
||||||
|
commands.insert_resource(SphereMat(handle));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_textures(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|
||||||
let main_tex = asset_server.load("textures/world/stack.png");
|
|
||||||
commands.insert_resource(ChunkAtlas {
|
|
||||||
handle: main_tex.clone(),
|
|
||||||
is_loaded: false,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
#[derive(Resource)]
|
#[derive(Resource)]
|
||||||
struct Painter(Handle<BiomePainterAsset>);
|
struct SphereMat(Handle<StandardMaterial>);
|
||||||
|
|
||||||
fn load_tiles(mut commands: Commands, asset_server: Res<AssetServer>) {
|
fn spawn_sphere(
|
||||||
let handle: Handle<BiomePainterAsset> = asset_server.load("biome_painters/terra.biomes.json");
|
|
||||||
commands.insert_resource(Painter(handle));
|
|
||||||
}
|
|
||||||
|
|
||||||
fn finalize_texture(
|
|
||||||
asset_server: Res<AssetServer>,
|
|
||||||
mut atlas: ResMut<ChunkAtlas>,
|
|
||||||
mut map: ResMut<PhosMap>,
|
|
||||||
mut images: ResMut<Assets<Image>>,
|
|
||||||
painter: Res<Painter>,
|
|
||||||
painter_load: Res<BiomePainterLoadState>,
|
|
||||||
tile_load: Res<TileAssetLoadState>,
|
|
||||||
mapper_load: Res<TileMapperLoadState>,
|
|
||||||
) {
|
|
||||||
if atlas.is_loaded {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if !painter_load.is_all_loaded() || !tile_load.is_all_loaded() || !mapper_load.is_all_loaded() {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if asset_server.load_state(atlas.handle.clone()) != LoadState::Loaded {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if asset_server.load_state(painter.0.clone()) != LoadState::Loaded {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let image = images.get_mut(&atlas.handle).unwrap();
|
|
||||||
|
|
||||||
let array_layers = 14;
|
|
||||||
image.reinterpret_stacked_2d_as_array(array_layers);
|
|
||||||
|
|
||||||
atlas.is_loaded = true;
|
|
||||||
map.ready = true;
|
|
||||||
map.regenerate = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn create_map(mut commands: Commands) {
|
|
||||||
let heightmap = generate_heightmap(
|
|
||||||
&GenerationConfig {
|
|
||||||
layers: vec![
|
|
||||||
GeneratorLayer {
|
|
||||||
base_roughness: 2.14,
|
|
||||||
roughness: 0.87,
|
|
||||||
strength: 2.93,
|
|
||||||
min_value: -0.2,
|
|
||||||
persistence: 0.77,
|
|
||||||
is_rigid: false,
|
|
||||||
weight: 0.,
|
|
||||||
weight_multi: 0.,
|
|
||||||
layers: 4,
|
|
||||||
first_layer_mask: false,
|
|
||||||
},
|
|
||||||
GeneratorLayer {
|
|
||||||
base_roughness: 2.85,
|
|
||||||
roughness: 2.,
|
|
||||||
strength: -0.23,
|
|
||||||
min_value: -0.,
|
|
||||||
persistence: 1.,
|
|
||||||
is_rigid: false,
|
|
||||||
weight: 0.,
|
|
||||||
weight_multi: 0.,
|
|
||||||
layers: 4,
|
|
||||||
first_layer_mask: false,
|
|
||||||
},
|
|
||||||
GeneratorLayer {
|
|
||||||
base_roughness: 2.6,
|
|
||||||
roughness: 4.,
|
|
||||||
strength: 10.44,
|
|
||||||
min_value: 0.,
|
|
||||||
persistence: 1.57,
|
|
||||||
is_rigid: true,
|
|
||||||
weight: 1.,
|
|
||||||
weight_multi: 0.35,
|
|
||||||
layers: 4,
|
|
||||||
first_layer_mask: true,
|
|
||||||
},
|
|
||||||
GeneratorLayer {
|
|
||||||
base_roughness: 3.87,
|
|
||||||
roughness: 5.8,
|
|
||||||
strength: -1.,
|
|
||||||
min_value: 0.,
|
|
||||||
persistence: 0.,
|
|
||||||
is_rigid: true,
|
|
||||||
weight: 1.,
|
|
||||||
weight_multi: 4.57,
|
|
||||||
layers: 3,
|
|
||||||
first_layer_mask: true,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
noise_scale: 350.,
|
|
||||||
sea_level: 4.,
|
|
||||||
border_size: 64.,
|
|
||||||
size: UVec2::splat(1024 / Chunk::SIZE as u32),
|
|
||||||
},
|
|
||||||
4,
|
|
||||||
);
|
|
||||||
|
|
||||||
commands.insert_resource(heightmap);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn spawn_map(
|
|
||||||
heightmap: Res<Map>,
|
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
mut materials: ResMut<Assets<ExtendedMaterial<StandardMaterial, ChunkMaterial>>>,
|
cam: Query<&Transform, With<PhosCamera>>,
|
||||||
|
keyboard_input: Res<ButtonInput<KeyCode>>,
|
||||||
mut meshes: ResMut<Assets<Mesh>>,
|
mut meshes: ResMut<Assets<Mesh>>,
|
||||||
atlas: Res<ChunkAtlas>,
|
mat: Res<SphereMat>,
|
||||||
mut map: ResMut<PhosMap>,
|
|
||||||
tile_assets: Res<Assets<TileAsset>>,
|
|
||||||
tile_mappers: Res<Assets<TileMapperAsset>>,
|
|
||||||
biome_painters: Res<Assets<BiomePainterAsset>>,
|
|
||||||
painter: Res<Painter>,
|
|
||||||
) {
|
) {
|
||||||
if !map.ready || !map.regenerate {
|
if keyboard_input.just_pressed(KeyCode::KeyF) {
|
||||||
return;
|
let cam_transform = cam.single();
|
||||||
}
|
|
||||||
let b_painter = biome_painters.get(painter.0.clone());
|
|
||||||
map.regenerate = false;
|
|
||||||
let chunk_material = materials.add(ExtendedMaterial {
|
|
||||||
base: StandardMaterial::default(),
|
|
||||||
extension: ChunkMaterial {
|
|
||||||
array_texture: atlas.handle.clone(),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
for chunk in &heightmap.chunks {
|
|
||||||
let mesh = generate_chunk_mesh(
|
|
||||||
&chunk,
|
|
||||||
&heightmap,
|
|
||||||
b_painter.unwrap(),
|
|
||||||
&tile_assets,
|
|
||||||
&tile_mappers,
|
|
||||||
);
|
|
||||||
let pos = offset_to_world(chunk.chunk_offset * Chunk::SIZE as i32, 0.);
|
|
||||||
commands.spawn((
|
commands.spawn((
|
||||||
MaterialMeshBundle {
|
MaterialMeshBundle {
|
||||||
mesh: meshes.add(mesh),
|
mesh: meshes.add(Sphere::new(0.3)),
|
||||||
material: chunk_material.clone(),
|
material: mat.0.clone(),
|
||||||
transform: Transform::from_translation(pos),
|
transform: Transform::from_translation(cam_transform.translation),
|
||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
PhosChunk,
|
Collider::ball(0.3),
|
||||||
|
RigidBody::Dynamic,
|
||||||
|
Ccd::enabled(),
|
||||||
|
Velocity::linear(cam_transform.forward() * 50.),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +1,46 @@
|
|||||||
use bevy::asset::Handle;
|
use bevy::asset::Handle;
|
||||||
|
use bevy::pbr::ExtendedMaterial;
|
||||||
|
use bevy::prelude::*;
|
||||||
use bevy::prelude::{Component, Image, Resource};
|
use bevy::prelude::{Component, Image, Resource};
|
||||||
|
use bevy::reflect::Reflect;
|
||||||
|
|
||||||
|
use crate::shader_extensions::chunk_material::ChunkMaterial;
|
||||||
|
|
||||||
#[derive(Resource)]
|
#[derive(Resource)]
|
||||||
pub struct ChunkAtlas {
|
pub struct ChunkAtlas {
|
||||||
pub handle: Handle<Image>,
|
pub handle: Handle<Image>,
|
||||||
|
pub chunk_material_handle: Handle<ExtendedMaterial<StandardMaterial, ChunkMaterial>>,
|
||||||
|
pub water_material: Handle<StandardMaterial>,
|
||||||
pub is_loaded: bool,
|
pub is_loaded: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Resource, Default)]
|
#[derive(Resource, Default, Reflect)]
|
||||||
|
#[reflect(Resource)]
|
||||||
pub struct PhosMap {
|
pub struct PhosMap {
|
||||||
pub ready: bool,
|
pub ready: bool,
|
||||||
pub regenerate: bool,
|
pub regenerate: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Component)]
|
#[derive(Component)]
|
||||||
pub struct PhosChunk;
|
pub struct PhosChunk {
|
||||||
|
pub index: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PhosChunk {
|
||||||
|
pub fn new(index: usize) -> Self {
|
||||||
|
return Self { index };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Resource, Default)]
|
||||||
|
pub struct PhosChunkRegistry {
|
||||||
|
pub chunks: Vec<Entity>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PhosChunkRegistry {
|
||||||
|
pub fn new(size: usize) -> Self {
|
||||||
|
return Self {
|
||||||
|
chunks: Vec::with_capacity(size),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -15,4 +15,25 @@ impl MaterialExtension for ChunkMaterial {
|
|||||||
fn fragment_shader() -> ShaderRef {
|
fn fragment_shader() -> ShaderRef {
|
||||||
"shaders/world/chunk.wgsl".into()
|
"shaders/world/chunk.wgsl".into()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// fn vertex_shader() -> ShaderRef {
|
||||||
|
// "shaders/world/chunk_packed.wgsl".into()
|
||||||
|
// }
|
||||||
|
|
||||||
|
// fn specialize(
|
||||||
|
// _pipeline: &bevy::pbr::MaterialExtensionPipeline,
|
||||||
|
// descriptor: &mut bevy::render::render_resource::RenderPipelineDescriptor,
|
||||||
|
// layout: &bevy::render::mesh::MeshVertexBufferLayout,
|
||||||
|
// _key: bevy::pbr::MaterialExtensionKey<Self>,
|
||||||
|
// ) -> Result<(), bevy::render::render_resource::SpecializedMeshPipelineError> {
|
||||||
|
// let vertex_layout = layout.get_layout(&[
|
||||||
|
// // Mesh::ATTRIBUTE_POSITION.at_shader_location(0),
|
||||||
|
// // Mesh::ATTRIBUTE_UV_0.at_shader_location(1),
|
||||||
|
// // Mesh::ATTRIBUTE_NORMAL.at_shader_location(2),
|
||||||
|
// ATTRIBUTE_PACKED_VERTEX_DATA.at_shader_location(7),
|
||||||
|
// ATTRIBUTE_VERTEX_HEIGHT.at_shader_location(8),
|
||||||
|
// ])?;
|
||||||
|
// descriptor.vertex.buffers = vec![vertex_layout];
|
||||||
|
// Ok(())
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|||||||
1
game/main/src/utlis/mod.rs
Normal file
1
game/main/src/utlis/mod.rs
Normal file
@@ -0,0 +1 @@
|
|||||||
|
pub mod render_distance_system;
|
||||||
76
game/main/src/utlis/render_distance_system.rs
Normal file
76
game/main/src/utlis/render_distance_system.rs
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
use bevy::prelude::*;
|
||||||
|
|
||||||
|
use crate::camera_system::components::PhosCamera;
|
||||||
|
|
||||||
|
pub struct RenderDistancePlugin;
|
||||||
|
|
||||||
|
impl Plugin for RenderDistancePlugin {
|
||||||
|
fn build(&self, app: &mut bevy::prelude::App) {
|
||||||
|
app.register_type::<RenderDistanceSettings>();
|
||||||
|
app.add_systems(PostUpdate, render_distance_system)
|
||||||
|
.insert_resource(RenderDistanceSettings::default());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Resource, Reflect)]
|
||||||
|
#[reflect(Resource)]
|
||||||
|
pub struct RenderDistanceSettings {
|
||||||
|
pub render_distance: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RenderDistanceSettings {
|
||||||
|
pub fn new(distance: f32) -> Self {
|
||||||
|
return Self {
|
||||||
|
render_distance: distance,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for RenderDistanceSettings {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new(500.)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Component)]
|
||||||
|
pub struct RenderDistanceVisibility {
|
||||||
|
pub distance_multiplier: f32,
|
||||||
|
pub offset: Vec3,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RenderDistanceVisibility {
|
||||||
|
pub fn with_offset(mut self, offset: Vec3) -> Self {
|
||||||
|
self.offset = offset;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_multiplier(mut self, distance_multiplier: f32) -> Self {
|
||||||
|
self.distance_multiplier = distance_multiplier;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for RenderDistanceVisibility {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
distance_multiplier: 1.,
|
||||||
|
offset: Vec3::ZERO,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_distance_system(
|
||||||
|
mut objects: Query<(&Transform, &mut Visibility, &RenderDistanceVisibility)>,
|
||||||
|
camera_query: Query<&Transform, With<PhosCamera>>,
|
||||||
|
settings: Res<RenderDistanceSettings>,
|
||||||
|
) {
|
||||||
|
let camera = camera_query.single();
|
||||||
|
for (t, mut vis, r) in objects.iter_mut() {
|
||||||
|
let dist = (camera.translation - (t.translation + r.offset)).length() * r.distance_multiplier;
|
||||||
|
if settings.render_distance < dist {
|
||||||
|
*vis = Visibility::Hidden;
|
||||||
|
} else {
|
||||||
|
*vis = Visibility::Visible;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1 +1,2 @@
|
|||||||
hard_tabs=true
|
hard_tabs=true
|
||||||
|
max_width=120
|
||||||
Reference in New Issue
Block a user