update
This commit is contained in:
parent
07ccac9c2a
commit
e83da3156b
63
Cargo.lock
generated
63
Cargo.lock
generated
@ -1502,6 +1502,28 @@ dependencies = [
|
|||||||
"winit",
|
"winit",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "big_space"
|
||||||
|
version = "0.10.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0237c788129417fab794b74c8d67a7bda3a967e19f530d3b03e17e36576ffe6a"
|
||||||
|
dependencies = [
|
||||||
|
"bevy_app",
|
||||||
|
"bevy_color",
|
||||||
|
"bevy_ecs",
|
||||||
|
"bevy_input",
|
||||||
|
"bevy_log",
|
||||||
|
"bevy_math",
|
||||||
|
"bevy_platform",
|
||||||
|
"bevy_reflect",
|
||||||
|
"bevy_render",
|
||||||
|
"bevy_tasks",
|
||||||
|
"bevy_time",
|
||||||
|
"bevy_transform",
|
||||||
|
"bevy_utils",
|
||||||
|
"smallvec",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bindgen"
|
name = "bindgen"
|
||||||
version = "0.70.1"
|
version = "0.70.1"
|
||||||
@ -1984,6 +2006,25 @@ dependencies = [
|
|||||||
"crossbeam-utils",
|
"crossbeam-utils",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-deque"
|
||||||
|
version = "0.8.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51"
|
||||||
|
dependencies = [
|
||||||
|
"crossbeam-epoch",
|
||||||
|
"crossbeam-utils",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-epoch"
|
||||||
|
version = "0.9.18"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
|
||||||
|
dependencies = [
|
||||||
|
"crossbeam-utils",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossbeam-queue"
|
name = "crossbeam-queue"
|
||||||
version = "0.3.12"
|
version = "0.3.12"
|
||||||
@ -4505,6 +4546,26 @@ version = "0.6.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539"
|
checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rayon"
|
||||||
|
version = "1.11.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f"
|
||||||
|
dependencies = [
|
||||||
|
"either",
|
||||||
|
"rayon-core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rayon-core"
|
||||||
|
version = "1.13.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91"
|
||||||
|
dependencies = [
|
||||||
|
"crossbeam-deque",
|
||||||
|
"crossbeam-utils",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "read-fonts"
|
name = "read-fonts"
|
||||||
version = "0.29.3"
|
version = "0.29.3"
|
||||||
@ -5106,9 +5167,11 @@ dependencies = [
|
|||||||
"bevy",
|
"bevy",
|
||||||
"bevy-inspector-egui",
|
"bevy-inspector-egui",
|
||||||
"bevy_panorbit_camera",
|
"bevy_panorbit_camera",
|
||||||
|
"big_space",
|
||||||
"chrono",
|
"chrono",
|
||||||
"futures",
|
"futures",
|
||||||
"iyes_perf_ui",
|
"iyes_perf_ui",
|
||||||
|
"rayon",
|
||||||
"regex",
|
"regex",
|
||||||
"reqwest 0.12.23",
|
"reqwest 0.12.23",
|
||||||
"rhorizons",
|
"rhorizons",
|
||||||
|
|||||||
@ -7,9 +7,11 @@ edition = "2024"
|
|||||||
bevy = "0.16"
|
bevy = "0.16"
|
||||||
bevy-inspector-egui = "0.33.1"
|
bevy-inspector-egui = "0.33.1"
|
||||||
bevy_panorbit_camera = "0.26"
|
bevy_panorbit_camera = "0.26"
|
||||||
|
big_space = { version = "0.10.0", features = ["camera"] }
|
||||||
chrono = "0.4.41"
|
chrono = "0.4.41"
|
||||||
futures = "0.3.31"
|
futures = "0.3.31"
|
||||||
iyes_perf_ui = "0.5.0"
|
iyes_perf_ui = "0.5.0"
|
||||||
|
rayon = "1.11.0"
|
||||||
regex = "1.11.1"
|
regex = "1.11.1"
|
||||||
reqwest = { version = "0.12", features = ["json"] }
|
reqwest = { version = "0.12", features = ["json"] }
|
||||||
rhorizons = "0.5.0"
|
rhorizons = "0.5.0"
|
||||||
|
|||||||
@ -11,6 +11,10 @@
|
|||||||
radius: 695700.0,
|
radius: 695700.0,
|
||||||
position: (0.0, 0.0, 0.0),
|
position: (0.0, 0.0, 0.0),
|
||||||
velocity: (0.0, 0.0, 0.0),
|
velocity: (0.0, 0.0, 0.0),
|
||||||
|
model: (
|
||||||
|
path: "sun.glb",
|
||||||
|
scale: (4.016625881e-2, 4.016625881e-2, 4.016625881e-2),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
name: "Mercury",
|
name: "Mercury",
|
||||||
@ -18,6 +22,10 @@
|
|||||||
radius: 2439.4,
|
radius: 2439.4,
|
||||||
position: (-3.873030085256687e-01, -1.617241946342014e-01, 2.230772540124238e-02),
|
position: (-3.873030085256687e-01, -1.617241946342014e-01, 2.230772540124238e-02),
|
||||||
velocity: (5.024430196457658e-03, -2.474345331076241e-02, -2.482923861184285e-03),
|
velocity: (5.024430196457658e-03, -2.474345331076241e-02, -2.482923861184285e-03),
|
||||||
|
model: (
|
||||||
|
path: "mercury.glb",
|
||||||
|
scale: (1.409040560e-4, 1.407730015e-4, 1.409040560e-4),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
name: "Venus",
|
name: "Venus",
|
||||||
@ -25,6 +33,10 @@
|
|||||||
radius: 6051.84,
|
radius: 6051.84,
|
||||||
position: (4.534187654737982e-01, 5.622160792960551e-01, -1.844136025242647e-02),
|
position: (4.534187654737982e-01, 5.622160792960551e-01, -1.844136025242647e-02),
|
||||||
velocity: (-1.580627428004959e-02, 1.261006264179427e-02, 1.085217883057661e-03),
|
velocity: (-1.580627428004959e-02, 1.261006264179427e-02, 1.085217883057661e-03),
|
||||||
|
model: (
|
||||||
|
path: "venus.glb",
|
||||||
|
scale: (3.494008561e-4, 3.494008561e-4, 3.494008561e-4),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
name: "Earth",
|
name: "Earth",
|
||||||
@ -32,6 +44,10 @@
|
|||||||
radius: 6371.01,
|
radius: 6371.01,
|
||||||
position: (-1.786834409731047e-01, 9.669827953774551e-01, -5.109423915082682e-05),
|
position: (-1.786834409731047e-01, 9.669827953774551e-01, -5.109423915082682e-05),
|
||||||
velocity: (-1.720473858166942e-02, -3.193533189307208e-03, 5.457174067040888e-09),
|
velocity: (-1.720473858166942e-02, -3.193533189307208e-03, 5.457174067040888e-09),
|
||||||
|
model: (
|
||||||
|
path: "earth.glb",
|
||||||
|
scale: (3.686534474e-4, 3.674174368e-4, 3.686534474e-4),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
name: "Mars",
|
name: "Mars",
|
||||||
@ -39,6 +55,10 @@
|
|||||||
radius: 3389.92,
|
radius: 3389.92,
|
||||||
position: (-5.216858665681381e-01, 1.525234576802456e+00, 4.475559803760917e-02),
|
position: (-5.216858665681381e-01, 1.525234576802456e+00, 4.475559803760917e-02),
|
||||||
velocity: (-1.271183490340250e-02, -3.338839586395265e-03, 2.417788175776839e-04),
|
velocity: (-1.271183490340250e-02, -3.338839586395265e-03, 2.417788175776839e-04),
|
||||||
|
model: (
|
||||||
|
path: "mars.glb",
|
||||||
|
scale: (1.964640105e-4, 1.953076135e-4, 1.964640105e-4),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
name: "Jupiter",
|
name: "Jupiter",
|
||||||
@ -46,6 +66,10 @@
|
|||||||
radius: 69911.0,
|
radius: 69911.0,
|
||||||
position: (1.056033545576702e+00, 4.971452162023883e+00, -4.427806378454757e-02),
|
position: (1.056033545576702e+00, 4.971452162023883e+00, -4.427806378454757e-02),
|
||||||
velocity: (-7.476272400979211e-03, 1.924466075080766e-03, 1.592575331437652e-04),
|
velocity: (-7.476272400979211e-03, 1.924466075080766e-03, 1.592575331437652e-04),
|
||||||
|
model: (
|
||||||
|
path: "jupiter.glb",
|
||||||
|
scale: (4.216764122e-3, 3.943203948e-3, 4.216764122e-3),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
name: "Saturn",
|
name: "Saturn",
|
||||||
@ -53,6 +77,10 @@
|
|||||||
radius: 58232.0,
|
radius: 58232.0,
|
||||||
position: (9.461067271500818e+00, -1.764614720843175e+00, -3.458764004169705e-01),
|
position: (9.461067271500818e+00, -1.764614720843175e+00, -3.458764004169705e-01),
|
||||||
velocity: (7.093807804551229e-04, 5.475097536527790e-03, -1.232345969963958e-04),
|
velocity: (7.093807804551229e-04, 5.475097536527790e-03, -1.232345969963958e-04),
|
||||||
|
model: (
|
||||||
|
path: "saturn.glb",
|
||||||
|
scale: (1.828302280e-3, 1.649197191e-3, 1.828302280e-3),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
name: "Uranus",
|
name: "Uranus",
|
||||||
@ -60,6 +88,10 @@
|
|||||||
radius: 25362.0,
|
radius: 25362.0,
|
||||||
position: (1.110362881512566e+01, 1.609448391218202e+01, -8.419833258524990e-02),
|
position: (1.110362881512566e+01, 1.609448391218202e+01, -8.419833258524990e-02),
|
||||||
velocity: (-3.273728238819980e-03, 2.053528328895527e-03, 5.008589052969062e-05),
|
velocity: (-3.273728238819980e-03, 2.053528328895527e-03, 5.008589052969062e-05),
|
||||||
|
model: (
|
||||||
|
path: "uranus.glb",
|
||||||
|
scale: (1.486925757e-3, 1.452834462e-3, 1.486925757e-3),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
name: "Neptune",
|
name: "Neptune",
|
||||||
@ -67,6 +99,10 @@
|
|||||||
radius: 24624.0,
|
radius: 24624.0,
|
||||||
position: (2.987992735576156e+01, -6.341879950443392e-01, -6.754997950415415e-01),
|
position: (2.987992735576156e+01, -6.341879950443392e-01, -6.754997950415415e-01),
|
||||||
velocity: (3.941595250081164e-05, 3.160389775728832e-03, -6.636996572427530e-05),
|
velocity: (3.941595250081164e-05, 3.160389775728832e-03, -6.636996572427530e-05),
|
||||||
|
model: (
|
||||||
|
path: "neptune.glb",
|
||||||
|
scale: (1.437890343e-3, 1.413329272e-3, 1.437890343e-3),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
name: "Moon",
|
name: "Moon",
|
||||||
@ -74,6 +110,10 @@
|
|||||||
radius: 1737.53,
|
radius: 1737.53,
|
||||||
position: (-1.776670337217189e-01, 9.646511868801392e-01, -2.560710414773878e-04),
|
position: (-1.776670337217189e-01, 9.646511868801392e-01, -2.560710414773878e-04),
|
||||||
velocity: (-1.666610342674751e-02, -2.935662211368250e-03, 2.214641479437884e-05),
|
velocity: (-1.666610342674751e-02, -2.935662211368250e-03, 2.214641479437884e-05),
|
||||||
|
model: (
|
||||||
|
path: "moon.glb",
|
||||||
|
scale: (1.003505604e-4, 1.003505604e-4, 1.003505604e-4),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
name: "Phobos",
|
name: "Phobos",
|
||||||
@ -81,6 +121,10 @@
|
|||||||
radius: 11.1,
|
radius: 11.1,
|
||||||
position: (-5.216607506283159e-01, 1.525290094552813e+00, 4.474552444674667e-02),
|
position: (-5.216607506283159e-01, 1.525290094552813e+00, 4.474552444674667e-02),
|
||||||
velocity: (-1.371531677510715e-02, -2.797359927923991e-03, 7.604209362929195e-04),
|
velocity: (-1.371531677510715e-02, -2.797359927923991e-03, 7.604209362929195e-04),
|
||||||
|
model: (
|
||||||
|
path: "phobos.glb",
|
||||||
|
scale: (3.111071419e-5, 2.177749957e-5, 2.728170512e-5),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
name: "Deimos",
|
name: "Deimos",
|
||||||
@ -88,6 +132,10 @@
|
|||||||
radius: 6.2,
|
radius: 6.2,
|
||||||
position: (-5.215476623931578e-01, 1.525280501692070e+00, 4.469744727198185e-02),
|
position: (-5.215476623931578e-01, 1.525280501692070e+00, 4.469744727198185e-02),
|
||||||
velocity: (-1.290124900899404e-02, -2.594527535740538e-03, 3.799855876623048e-04),
|
velocity: (-1.290124900899404e-02, -2.594527535740538e-03, 3.799855876623048e-04),
|
||||||
|
model: (
|
||||||
|
path: "deimos.glb",
|
||||||
|
scale: (3.572769492e-5, 2.336041507e-5, 2.748284533e-5),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
name: "Io",
|
name: "Io",
|
||||||
@ -95,6 +143,10 @@
|
|||||||
radius: 1821.49,
|
radius: 1821.49,
|
||||||
position: (1.053815818667817e+00, 4.969715993299296e+00, -4.437108516416628e-02),
|
position: (1.053815818667817e+00, 4.969715993299296e+00, -4.437108516416628e-02),
|
||||||
velocity: (-1.329530996368361e-03, -5.983335980023409e-03, -3.295420474951598e-05),
|
velocity: (-1.329530996368361e-03, -5.983335980023409e-03, -3.295420474951598e-05),
|
||||||
|
model: (
|
||||||
|
path: "io.glb",
|
||||||
|
scale: (1.056204637e-4, 1.048294944e-4, 1.050431092e-4),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
name: "Europa",
|
name: "Europa",
|
||||||
@ -102,6 +154,10 @@
|
|||||||
radius: 1560.8,
|
radius: 1560.8,
|
||||||
position: (1.060479105966296e+00, 4.971193788432235e+00, -4.418907806556983e-02),
|
position: (1.060479105966296e+00, 4.971193788432235e+00, -4.418907806556983e-02),
|
||||||
velocity: (-6.967074192246404e-03, 9.896683771810605e-03, 4.296001484155991e-04),
|
velocity: (-6.967074192246404e-03, 9.896683771810605e-03, 4.296001484155991e-04),
|
||||||
|
model: (
|
||||||
|
path: "europa.glb",
|
||||||
|
scale: (9.021675214e-5, 9.003777086e-5, 9.008396592e-5),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
name: "Ganymede",
|
name: "Ganymede",
|
||||||
@ -109,6 +165,10 @@
|
|||||||
radius: 2631.2,
|
radius: 2631.2,
|
||||||
position: (1.062520398626604e+00, 4.968458682597362e+00, -4.429967587277176e-02),
|
position: (1.062520398626604e+00, 4.968458682597362e+00, -4.429967587277176e-02),
|
||||||
velocity: (-4.841408463186764e-03, 7.634290231598638e-03, 4.147177169244575e-04),
|
velocity: (-4.841408463186764e-03, 7.634290231598638e-03, 4.147177169244575e-04),
|
||||||
|
model: (
|
||||||
|
path: "ganymede.glb",
|
||||||
|
scale: (1.519124053e-4, 1.519124053e-4, 1.519124053e-4),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
name: "Callisto",
|
name: "Callisto",
|
||||||
@ -116,6 +176,10 @@
|
|||||||
radius: 2410.3,
|
radius: 2410.3,
|
||||||
position: (1.046927187861326e+00, 4.980213520221207e+00, -4.412635447845523e-02),
|
position: (1.046927187861326e+00, 4.980213520221207e+00, -4.412635447845523e-02),
|
||||||
velocity: (-1.076662893789138e-02, -1.453153071657253e-03, 9.400054299331563e-06),
|
velocity: (-1.076662893789138e-02, -1.453153071657253e-03, 9.400054299331563e-06),
|
||||||
|
model: (
|
||||||
|
path: "callisto.glb",
|
||||||
|
scale: (1.391587430e-4, 1.391587430e-4, 1.391587430e-4),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
name: "Mimas",
|
name: "Mimas",
|
||||||
@ -123,6 +187,10 @@
|
|||||||
radius: 198.8,
|
radius: 198.8,
|
||||||
position: (9.462113317387443e+00, -1.764120396234732e+00, -3.462575454806998e-01),
|
position: (9.462113317387443e+00, -1.764120396234732e+00, -3.462575454806998e-01),
|
||||||
velocity: (-3.600569225193193e-03, 1.195945377622506e-02, -3.321658418910402e-03),
|
velocity: (-3.600569225193193e-03, 1.195945377622506e-02, -3.321658418910402e-03),
|
||||||
|
model: (
|
||||||
|
path: "mimas.glb",
|
||||||
|
scale: (3.022084638e-5, 2.771941035e-5, 2.860654604e-5),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
name: "Enceladus",
|
name: "Enceladus",
|
||||||
@ -130,6 +198,10 @@
|
|||||||
radius: 252.3,
|
radius: 252.3,
|
||||||
position: (9.462107070733344e+00, -1.763590731315564e+00, -3.465134777458668e-01),
|
position: (9.462107070733344e+00, -1.763590731315564e+00, -3.465134777458668e-01),
|
||||||
velocity: (-4.799068161710644e-03, 9.904458072213898e-03, -1.910803547584920e-03),
|
velocity: (-4.799068161710644e-03, 9.904458072213898e-03, -1.910803547584920e-03),
|
||||||
|
model: (
|
||||||
|
path: "enceladus.glb",
|
||||||
|
scale: (1.481480831e-5, 1.433560737e-5, 1.451458593e-5),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
name: "Tethys",
|
name: "Tethys",
|
||||||
@ -137,6 +209,10 @@
|
|||||||
radius: 536.3,
|
radius: 536.3,
|
||||||
position: (9.463028141754283e+00, -1.764725184828637e+00, -3.460263238634043e-01),
|
position: (9.463028141754283e+00, -1.764725184828637e+00, -3.460263238634043e-01),
|
||||||
velocity: (8.124741088132637e-04, 1.132977234261396e-02, -3.072248079372077e-03),
|
velocity: (8.124741088132637e-04, 1.132977234261396e-02, -3.072248079372077e-03),
|
||||||
|
model: (
|
||||||
|
path: "tethys.glb",
|
||||||
|
scale: (3.129428660e-5, 3.059098162e-5, 3.070722960e-5),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
name: "Dione",
|
name: "Dione",
|
||||||
@ -144,6 +220,10 @@
|
|||||||
radius: 562.5,
|
radius: 562.5,
|
||||||
position: (9.460669031566509e+00, -1.762393870120674e+00, -3.470001695782450e-01),
|
position: (9.460669031566509e+00, -1.762393870120674e+00, -3.470001695782450e-01),
|
||||||
velocity: (-4.995042476514132e-03, 4.898468069198046e-03, 7.315317142172153e-04),
|
velocity: (-4.995042476514132e-03, 4.898468069198046e-03, 7.315317142172153e-04),
|
||||||
|
model: (
|
||||||
|
path: "dione.glb",
|
||||||
|
scale: (3.252791430e-5, 3.230852235e-5, 3.240667138e-5),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
name: "Rhea",
|
name: "Rhea",
|
||||||
@ -151,6 +231,10 @@
|
|||||||
radius: 764.5,
|
radius: 764.5,
|
||||||
position: (9.463441058546145e+00, -1.766997606737125e+00, -3.448366300385151e-01),
|
position: (9.463441058546145e+00, -1.766997606737125e+00, -3.448366300385151e-01),
|
||||||
velocity: (4.307393238751094e-03, 8.273257376182423e-03, -1.932435874857194e-03),
|
velocity: (4.307393238751094e-03, 8.273257376182423e-03, -1.932435874857194e-03),
|
||||||
|
model: (
|
||||||
|
path: "rhea.glb",
|
||||||
|
scale: (4.416729644e-5, 4.401718616e-5, 4.405760046e-5),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
name: "Titan",
|
name: "Titan",
|
||||||
@ -158,6 +242,10 @@
|
|||||||
radius: 2575.5,
|
radius: 2575.5,
|
||||||
position: (9.468440328490537e+00, -1.762284834421733e+00, -3.478122131916790e-01),
|
position: (9.468440328490537e+00, -1.762284834421733e+00, -3.478122131916790e-01),
|
||||||
velocity: (-4.611400435334967e-04, 8.260265884102586e-03, -1.443082816825538e-03),
|
velocity: (-4.611400435334967e-04, 8.260265884102586e-03, -1.443082816825538e-03),
|
||||||
|
model: (
|
||||||
|
path: "titan.glb",
|
||||||
|
scale: (1.486763649e-4, 1.486371038e-4, 1.486549882e-4),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
name: "Iapetus",
|
name: "Iapetus",
|
||||||
@ -165,6 +253,10 @@
|
|||||||
radius: 734.5,
|
radius: 734.5,
|
||||||
position: (9.454548058738080e+00, -1.786906158368561e+00, -3.394196336672040e-01),
|
position: (9.454548058738080e+00, -1.786906158368561e+00, -3.394196336672040e-01),
|
||||||
velocity: (2.477125925502744e-03, 4.942920731685813e-03, -3.564738618756286e-04),
|
velocity: (2.477125925502744e-03, 4.942920731685813e-03, -3.564738618756286e-04),
|
||||||
|
model: (
|
||||||
|
path: "iapetus.glb",
|
||||||
|
scale: (4.305300899e-5, 4.111311500e-5, 4.305300899e-5),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
name: "Miranda",
|
name: "Miranda",
|
||||||
@ -172,6 +264,10 @@
|
|||||||
radius: 235.8,
|
radius: 235.8,
|
||||||
position: (1.110338075481133e+01, 1.609470886437212e+01, -8.339848717695617e-02),
|
position: (1.110338075481133e+01, 1.609470886437212e+01, -8.339848717695617e-02),
|
||||||
velocity: (2.787135511093017e-04, 1.302160355796409e-03, 1.366210183434322e-03),
|
velocity: (2.787135511093017e-04, 1.302160355796409e-03, 1.366210183434322e-03),
|
||||||
|
model: (
|
||||||
|
path: "miranda.glb",
|
||||||
|
scale: (1.387950124e-5, 1.344648808e-5, 1.352154413e-5),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
name: "Ariel",
|
name: "Ariel",
|
||||||
@ -179,6 +275,10 @@
|
|||||||
radius: 578.9,
|
radius: 578.9,
|
||||||
position: (1.110453239435098e+01, 1.609416926126415e+01, -8.504238243640228e-02),
|
position: (1.110453239435098e+01, 1.609416926126415e+01, -8.504238243640228e-02),
|
||||||
velocity: (-5.417334967749265e-03, 2.196892645955784e-03, -2.298152372242362e-03),
|
velocity: (-5.417334967749265e-03, 2.196892645955784e-03, -2.298152372242362e-03),
|
||||||
|
model: (
|
||||||
|
path: "ariel.glb",
|
||||||
|
scale: (3.354982618e-5, 3.335352449e-5, 3.336507143e-5),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
name: "Umbriel",
|
name: "Umbriel",
|
||||||
@ -186,6 +286,10 @@
|
|||||||
radius: 584.7,
|
radius: 584.7,
|
||||||
position: (1.110253678329407e+01, 1.609490555702174e+01, -8.286998450094619e-02),
|
position: (1.110253678329407e+01, 1.609490555702174e+01, -8.286998450094619e-02),
|
||||||
velocity: (-1.219602563560983e-03, 1.849034126664038e-03, 1.801100761916168e-03),
|
velocity: (-1.219602563560983e-03, 1.849034126664038e-03, 1.801100761916168e-03),
|
||||||
|
model: (
|
||||||
|
path: "umbriel.glb",
|
||||||
|
scale: (3.375767119e-5, 3.375767119e-5, 3.375767119e-5),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
name: "Titania",
|
name: "Titania",
|
||||||
@ -193,6 +297,10 @@
|
|||||||
radius: 788.9,
|
radius: 788.9,
|
||||||
position: (1.110510884778205e+01, 1.609382177197045e+01, -8.661833178512783e-02),
|
position: (1.110510884778205e+01, 1.609382177197045e+01, -8.661833178512783e-02),
|
||||||
velocity: (-5.032495225759578e-03, 2.280002002691279e-03, -1.088327315015861e-03),
|
velocity: (-5.032495225759578e-03, 2.280002002691279e-03, -1.088327315015861e-03),
|
||||||
|
model: (
|
||||||
|
path: "titania.glb",
|
||||||
|
scale: (4.554716361e-5, 4.554716361e-5, 4.554716361e-5),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
name: "Oberon",
|
name: "Oberon",
|
||||||
@ -200,6 +308,10 @@
|
|||||||
radius: 761.4,
|
radius: 761.4,
|
||||||
position: (1.110301190463219e+01, 1.609515778477002e+01, -8.040210462613612e-02),
|
position: (1.110301190463219e+01, 1.609515778477002e+01, -8.040210462613612e-02),
|
||||||
velocity: (-1.519780917379062e-03, 1.720169702110850e-03, 3.926675849694972e-04),
|
velocity: (-1.519780917379062e-03, 1.720169702110850e-03, 3.926675849694972e-04),
|
||||||
|
model: (
|
||||||
|
path: "oberon.glb",
|
||||||
|
scale: (4.395945143e-5, 4.395945143e-5, 4.395945143e-5),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
name: "Triton",
|
name: "Triton",
|
||||||
@ -207,6 +319,10 @@
|
|||||||
radius: 1352.6,
|
radius: 1352.6,
|
||||||
position: (2.987802053077272e+01, -6.355569689698364e-01, -6.751627943073906e-01),
|
position: (2.987802053077272e+01, -6.355569689698364e-01, -6.751627943073906e-01),
|
||||||
velocity: (-6.787804924900204e-04, 4.636375429506899e-03, 1.865945736548040e-03),
|
velocity: (-6.787804924900204e-04, 4.636375429506899e-03, 1.865945736548040e-03),
|
||||||
|
model: (
|
||||||
|
path: "triton.glb",
|
||||||
|
scale: (7.809240196e-5, 7.809240196e-5, 7.809240196e-5),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
BIN
assets/models/ariel.glb
Normal file
BIN
assets/models/ariel.glb
Normal file
Binary file not shown.
BIN
assets/models/callisto.glb
Normal file
BIN
assets/models/callisto.glb
Normal file
Binary file not shown.
BIN
assets/models/ceres.glb
Normal file
BIN
assets/models/ceres.glb
Normal file
Binary file not shown.
BIN
assets/models/charon.glb
Normal file
BIN
assets/models/charon.glb
Normal file
Binary file not shown.
BIN
assets/models/deimos.glb
Normal file
BIN
assets/models/deimos.glb
Normal file
Binary file not shown.
BIN
assets/models/dione.glb
Normal file
BIN
assets/models/dione.glb
Normal file
Binary file not shown.
BIN
assets/models/earth.glb
Normal file
BIN
assets/models/earth.glb
Normal file
Binary file not shown.
BIN
assets/models/enceladus.glb
Normal file
BIN
assets/models/enceladus.glb
Normal file
Binary file not shown.
BIN
assets/models/eris.glb
Normal file
BIN
assets/models/eris.glb
Normal file
Binary file not shown.
BIN
assets/models/europa.glb
Normal file
BIN
assets/models/europa.glb
Normal file
Binary file not shown.
BIN
assets/models/ganymede.glb
Normal file
BIN
assets/models/ganymede.glb
Normal file
Binary file not shown.
BIN
assets/models/hubble.glb
Normal file
BIN
assets/models/hubble.glb
Normal file
Binary file not shown.
BIN
assets/models/iapetus.glb
Normal file
BIN
assets/models/iapetus.glb
Normal file
Binary file not shown.
BIN
assets/models/io.glb
Normal file
BIN
assets/models/io.glb
Normal file
Binary file not shown.
BIN
assets/models/iss.glb
Normal file
BIN
assets/models/iss.glb
Normal file
Binary file not shown.
BIN
assets/models/jupiter.glb
Normal file
BIN
assets/models/jupiter.glb
Normal file
Binary file not shown.
BIN
assets/models/makemake.glb
Normal file
BIN
assets/models/makemake.glb
Normal file
Binary file not shown.
BIN
assets/models/mars.glb
Normal file
BIN
assets/models/mars.glb
Normal file
Binary file not shown.
BIN
assets/models/mercury.glb
Normal file
BIN
assets/models/mercury.glb
Normal file
Binary file not shown.
BIN
assets/models/mimas.glb
Normal file
BIN
assets/models/mimas.glb
Normal file
Binary file not shown.
BIN
assets/models/miranda.glb
Normal file
BIN
assets/models/miranda.glb
Normal file
Binary file not shown.
BIN
assets/models/moon.glb
Normal file
BIN
assets/models/moon.glb
Normal file
Binary file not shown.
BIN
assets/models/neptune.glb
Normal file
BIN
assets/models/neptune.glb
Normal file
Binary file not shown.
BIN
assets/models/oberon.glb
Normal file
BIN
assets/models/oberon.glb
Normal file
Binary file not shown.
BIN
assets/models/phobos.glb
Normal file
BIN
assets/models/phobos.glb
Normal file
Binary file not shown.
BIN
assets/models/pluto.glb
Normal file
BIN
assets/models/pluto.glb
Normal file
Binary file not shown.
BIN
assets/models/rhea.glb
Normal file
BIN
assets/models/rhea.glb
Normal file
Binary file not shown.
BIN
assets/models/saturn.glb
Normal file
BIN
assets/models/saturn.glb
Normal file
Binary file not shown.
BIN
assets/models/sun.glb
Normal file
BIN
assets/models/sun.glb
Normal file
Binary file not shown.
BIN
assets/models/tethys.glb
Normal file
BIN
assets/models/tethys.glb
Normal file
Binary file not shown.
BIN
assets/models/titan.glb
Normal file
BIN
assets/models/titan.glb
Normal file
Binary file not shown.
BIN
assets/models/titania.glb
Normal file
BIN
assets/models/titania.glb
Normal file
Binary file not shown.
BIN
assets/models/triton.glb
Normal file
BIN
assets/models/triton.glb
Normal file
Binary file not shown.
BIN
assets/models/umbriel.glb
Normal file
BIN
assets/models/umbriel.glb
Normal file
Binary file not shown.
BIN
assets/models/uranus.glb
Normal file
BIN
assets/models/uranus.glb
Normal file
Binary file not shown.
BIN
assets/models/venus.glb
Normal file
BIN
assets/models/venus.glb
Normal file
Binary file not shown.
BIN
assets/models/voyager.glb
Normal file
BIN
assets/models/voyager.glb
Normal file
Binary file not shown.
30
assets/scale.txt
Normal file
30
assets/scale.txt
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
Applied scale to Deimos: 3.572769492e-5, 2.336041507e-5, 2.748284533e-5
|
||||||
|
Applied scale to Umbriel: 3.375767119e-5, 3.375767119e-5, 3.375767119e-5
|
||||||
|
Applied scale to Phobos: 3.111071419e-5, 2.177749957e-5, 2.728170512e-5
|
||||||
|
Applied scale to Titania: 4.554716361e-5, 4.554716361e-5, 4.554716361e-5
|
||||||
|
Applied scale to Oberon: 4.395945143e-5, 4.395945143e-5, 4.395945143e-5
|
||||||
|
Applied scale to Mercury: 1.409040560e-4, 1.407730015e-4, 1.409040560e-4
|
||||||
|
Applied scale to Callisto: 1.391587430e-4, 1.391587430e-4, 1.391587430e-4
|
||||||
|
Applied scale to Venus: 3.494008561e-4, 3.494008561e-4, 3.494008561e-4
|
||||||
|
Applied scale to Uranus: 1.486925757e-3, 1.452834462e-3, 1.486925757e-3
|
||||||
|
Applied scale to Ariel: 3.354982618e-5, 3.335352449e-5, 3.336507143e-5
|
||||||
|
Applied scale to Europa: 9.021675214e-5, 9.003777086e-5, 9.008396592e-5
|
||||||
|
Applied scale to Pluto: 6.860653230e-5, 6.860653230e-5, 6.860653230e-5
|
||||||
|
Applied scale to Enceladus: 1.481480831e-5, 1.433560737e-5, 1.451458593e-5
|
||||||
|
Applied scale to Dione: 3.252791430e-5, 3.230852235e-5, 3.240667138e-5
|
||||||
|
Applied scale to Titan: 1.486763649e-4, 1.486371038e-4, 1.486549882e-4
|
||||||
|
Applied scale to Miranda: 1.387950124e-5, 1.344648808e-5, 1.352154413e-5
|
||||||
|
Applied scale to Neptune: 1.437890343e-3, 1.413329272e-3, 1.437890343e-3
|
||||||
|
Applied scale to Moon: 1.003505604e-4, 1.003505604e-4, 1.003505604e-4
|
||||||
|
Applied scale to Rhea: 4.416729644e-5, 4.401718616e-5, 4.405760046e-5
|
||||||
|
Applied scale to Sol: 4.016625881e-2, 4.016625881e-2, 4.016625881e-2
|
||||||
|
Applied scale to Iapetus: 4.305300899e-5, 4.111311500e-5, 4.305300899e-5
|
||||||
|
Applied scale to Jupiter: 4.216764122e-3, 3.943203948e-3, 4.216764122e-3
|
||||||
|
Applied scale to Ganymede: 1.519124053e-4, 1.519124053e-4, 1.519124053e-4
|
||||||
|
Applied scale to Earth: 3.686534474e-4, 3.674174368e-4, 3.686534474e-4
|
||||||
|
Applied scale to Saturn: 1.828302280e-3, 1.649197191e-3, 1.828302280e-3
|
||||||
|
Applied scale to Mimas: 3.022084638e-5, 2.771941035e-5, 2.860654604e-5
|
||||||
|
Applied scale to Triton: 7.809240196e-5, 7.809240196e-5, 7.809240196e-5
|
||||||
|
Applied scale to Mars: 1.964640105e-4, 1.953076135e-4, 1.964640105e-4
|
||||||
|
Applied scale to Tethys: 3.129428660e-5, 3.059098162e-5, 3.070722960e-5
|
||||||
|
Applied scale to Io: 1.056204637e-4, 1.048294944e-4, 1.050431092e-4
|
||||||
154
examples/big_space.rs
Normal file
154
examples/big_space.rs
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
//! This example demonstrates what floating point error in rendering looks like. You can press
|
||||||
|
//! space bar to smoothly switch between enabling and disabling the floating origin.
|
||||||
|
//!
|
||||||
|
//! Instead of disabling the plugin outright, this example simply moves the floating origin
|
||||||
|
//! independently of the camera, which is equivalent to what would happen when moving far from the
|
||||||
|
//! origin when not using this plugin.
|
||||||
|
|
||||||
|
use bevy::prelude::*;
|
||||||
|
use big_space::prelude::*;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
App::new()
|
||||||
|
.add_plugins((
|
||||||
|
DefaultPlugins.build().disable::<TransformPlugin>(),
|
||||||
|
BigSpaceDefaultPlugins,
|
||||||
|
))
|
||||||
|
.add_systems(Startup, (setup_scene, setup_ui))
|
||||||
|
.add_systems(Update, (rotator_system, toggle_plugin))
|
||||||
|
.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// You can put things really, really far away from the origin. The distance we use here is actually
|
||||||
|
/// quite small, because we want the mesh to still be visible when the floating origin is far from
|
||||||
|
/// the camera. If you go much further than this, the mesh will simply disappear in a *POOF* of
|
||||||
|
/// floating point error when we disable this plugin.
|
||||||
|
///
|
||||||
|
/// This plugin can function much further from the origin without any issues. Try setting this to:
|
||||||
|
/// `10_000_000_000_000_000` with the default i64 feature, or
|
||||||
|
/// `10_000_000_000_000_000_000_000_000_000_000_000_000` with the i128 feature.
|
||||||
|
const DISTANCE: GridPrecision = 2_000_000;
|
||||||
|
|
||||||
|
/// Move the floating origin back to the "true" origin when the user presses the spacebar to emulate
|
||||||
|
/// disabling the plugin. Normally you would make your active camera the floating origin to avoid
|
||||||
|
/// this issue.
|
||||||
|
fn toggle_plugin(
|
||||||
|
input: Res<ButtonInput<KeyCode>>,
|
||||||
|
grids: Grids,
|
||||||
|
mut text: Query<&mut Text>,
|
||||||
|
mut disabled: Local<bool>,
|
||||||
|
mut floating_origin: Query<(Entity, &mut CellCoord), With<FloatingOrigin>>,
|
||||||
|
) -> Result {
|
||||||
|
if input.just_pressed(KeyCode::Space) {
|
||||||
|
*disabled = !*disabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
let this_grid = grids
|
||||||
|
.parent_grid(floating_origin.single().unwrap().0)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let mut origin_cell = floating_origin.single_mut()?.1;
|
||||||
|
let index_max = DISTANCE / this_grid.cell_edge_length() as GridPrecision;
|
||||||
|
let increment = index_max / 100;
|
||||||
|
|
||||||
|
let msg = if *disabled {
|
||||||
|
if origin_cell.x > 0 {
|
||||||
|
origin_cell.x = 0.max(origin_cell.x - increment);
|
||||||
|
origin_cell.y = 0.max(origin_cell.y - increment);
|
||||||
|
origin_cell.z = 0.max(origin_cell.z - increment);
|
||||||
|
|
||||||
|
"Disabling..."
|
||||||
|
} else {
|
||||||
|
"Floating Origin Disabled"
|
||||||
|
}
|
||||||
|
} else if origin_cell.x < index_max {
|
||||||
|
origin_cell.x = index_max.min(origin_cell.x.saturating_add(increment));
|
||||||
|
origin_cell.y = index_max.min(origin_cell.y.saturating_add(increment));
|
||||||
|
origin_cell.z = index_max.min(origin_cell.z.saturating_add(increment));
|
||||||
|
"Enabling..."
|
||||||
|
} else {
|
||||||
|
"Floating Origin Enabled"
|
||||||
|
};
|
||||||
|
|
||||||
|
let dist =
|
||||||
|
index_max.saturating_sub(origin_cell.x) * this_grid.cell_edge_length() as GridPrecision;
|
||||||
|
|
||||||
|
let thousands = |num: GridPrecision| {
|
||||||
|
num.to_string()
|
||||||
|
.as_bytes()
|
||||||
|
.rchunks(3)
|
||||||
|
.rev()
|
||||||
|
.map(core::str::from_utf8)
|
||||||
|
.collect::<Result<Vec<&str>, _>>()
|
||||||
|
.unwrap()
|
||||||
|
.join(",") // separator
|
||||||
|
};
|
||||||
|
|
||||||
|
text.single_mut()?.0 = format!(
|
||||||
|
"Press Spacebar to toggle: {msg}\nCamera distance to floating origin: {}\nMesh distance from origin: {}",
|
||||||
|
thousands(dist),
|
||||||
|
thousands(DISTANCE)
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Component)]
|
||||||
|
struct Rotator;
|
||||||
|
|
||||||
|
fn rotator_system(time: Res<Time>, mut query: Query<&mut Transform, With<Rotator>>) {
|
||||||
|
for mut transform in &mut query {
|
||||||
|
transform.rotate_y(time.delta_secs());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn setup_ui(mut commands: Commands) {
|
||||||
|
commands.spawn((
|
||||||
|
Text::default(),
|
||||||
|
TextFont {
|
||||||
|
font_size: 30.0,
|
||||||
|
..default()
|
||||||
|
},
|
||||||
|
Node {
|
||||||
|
position_type: PositionType::Absolute,
|
||||||
|
top: Val::Px(12.0),
|
||||||
|
left: Val::Px(12.0),
|
||||||
|
..default()
|
||||||
|
},
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn setup_scene(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||||
|
commands.spawn_big_space_default(|root| {
|
||||||
|
let d = DISTANCE / root.grid().cell_edge_length() as GridPrecision;
|
||||||
|
let distant_grid_cell = CellCoord::new(d, d, d);
|
||||||
|
|
||||||
|
// Normally, we would put the floating origin on the camera. However in this example, we
|
||||||
|
// want to show what happens as the camera is far from the origin, to emulate what
|
||||||
|
// happens when this plugin isn't used.
|
||||||
|
root.spawn_spatial((distant_grid_cell, FloatingOrigin));
|
||||||
|
|
||||||
|
root.spawn_spatial((
|
||||||
|
SceneRoot(asset_server.load("models/low_poly_spaceship/scene.gltf#Scene0")),
|
||||||
|
Transform::from_scale(Vec3::splat(0.2)),
|
||||||
|
distant_grid_cell,
|
||||||
|
Rotator,
|
||||||
|
))
|
||||||
|
.with_child((
|
||||||
|
SceneRoot(asset_server.load("models/low_poly_spaceship/scene.gltf#Scene0")),
|
||||||
|
Transform::from_xyz(0.0, 0.0, 20.0),
|
||||||
|
));
|
||||||
|
// light
|
||||||
|
root.spawn_spatial((
|
||||||
|
DirectionalLight::default(),
|
||||||
|
Transform::from_xyz(4.0, -10.0, -4.0),
|
||||||
|
distant_grid_cell,
|
||||||
|
));
|
||||||
|
// camera
|
||||||
|
root.spawn_spatial((
|
||||||
|
Camera3d::default(),
|
||||||
|
Transform::from_xyz(8.0, 8.0, 0.0).looking_at(Vec3::ZERO, Vec3::Y),
|
||||||
|
distant_grid_cell,
|
||||||
|
));
|
||||||
|
});
|
||||||
|
}
|
||||||
98
examples/model.rs
Normal file
98
examples/model.rs
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
use bevy::{
|
||||||
|
core_pipeline::{bloom::Bloom, tonemapping::Tonemapping},
|
||||||
|
prelude::*,
|
||||||
|
window::WindowMode,
|
||||||
|
};
|
||||||
|
use bevy_inspector_egui::{bevy_egui::EguiPlugin, quick::WorldInspectorPlugin};
|
||||||
|
use bevy_panorbit_camera::{PanOrbitCamera, PanOrbitCameraPlugin};
|
||||||
|
use solar_sim::InitialState;
|
||||||
|
|
||||||
|
fn camera(mut commands: Commands) {
|
||||||
|
commands.spawn((
|
||||||
|
PanOrbitCamera {
|
||||||
|
focus: Vec3::new(0., 0.0, 0.0),
|
||||||
|
zoom_lower_limit: SCALE,
|
||||||
|
radius: Some(SCALE * 10.),
|
||||||
|
..default()
|
||||||
|
},
|
||||||
|
Camera {
|
||||||
|
hdr: true,
|
||||||
|
clear_color: ClearColorConfig::Custom(Color::BLACK),
|
||||||
|
..default()
|
||||||
|
},
|
||||||
|
Projection::Perspective(PerspectiveProjection {
|
||||||
|
near: 1e-9, // Very close near plane for extreme zooming
|
||||||
|
..default()
|
||||||
|
}),
|
||||||
|
Tonemapping::TonyMcMapface,
|
||||||
|
Bloom::NATURAL,
|
||||||
|
));
|
||||||
|
|
||||||
|
commands.spawn(DirectionalLight {
|
||||||
|
shadows_enabled: true,
|
||||||
|
illuminance: 50_000.0,
|
||||||
|
..default()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const SCALE: f32 = 1.;
|
||||||
|
|
||||||
|
fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||||
|
// Load initial state from RON file
|
||||||
|
let initial_state_content = match std::fs::read_to_string("assets/initial_state.ron") {
|
||||||
|
Ok(content) => content,
|
||||||
|
Err(err) => {
|
||||||
|
error!("Failed to read initial_state.ron: {}", err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let initial_state: InitialState = match ron::from_str(&initial_state_content) {
|
||||||
|
Ok(state) => state,
|
||||||
|
Err(err) => {
|
||||||
|
error!("Failed to parse initial_state.ron: {}", err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
initial_state
|
||||||
|
.bodies
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.for_each(|(i, body)| {
|
||||||
|
commands
|
||||||
|
.spawn(Transform::from_translation(Vec3::new(
|
||||||
|
(i) as f32 * SCALE * 10 as f32,
|
||||||
|
0.,
|
||||||
|
0.,
|
||||||
|
)))
|
||||||
|
.with_children(|parent| {
|
||||||
|
let scene = asset_server.load(format!("models/{}#Scene0", body.model.path));
|
||||||
|
parent.spawn((
|
||||||
|
SceneRoot(scene),
|
||||||
|
Transform::from_scale(Vec3::new(
|
||||||
|
body.model.scale.0,
|
||||||
|
body.model.scale.1,
|
||||||
|
body.model.scale.2,
|
||||||
|
)),
|
||||||
|
));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
App::new()
|
||||||
|
.add_plugins(DefaultPlugins.set(WindowPlugin {
|
||||||
|
primary_window: Some(Window {
|
||||||
|
title: "Solar Sim".to_string(),
|
||||||
|
mode: WindowMode::BorderlessFullscreen(MonitorSelection::Primary),
|
||||||
|
..default()
|
||||||
|
}),
|
||||||
|
..default()
|
||||||
|
}))
|
||||||
|
.add_plugins(EguiPlugin::default())
|
||||||
|
.add_plugins(WorldInspectorPlugin::new())
|
||||||
|
.add_plugins(PanOrbitCameraPlugin)
|
||||||
|
.add_systems(Startup, (camera, setup))
|
||||||
|
.run();
|
||||||
|
}
|
||||||
23
src/lib.rs
Normal file
23
src/lib.rs
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
use serde::Deserialize;
|
||||||
|
|
||||||
|
// Data structures for deserializing initial_state.ron
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub struct InitialState {
|
||||||
|
pub bodies: Vec<CelestialBodyData>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub struct CelestialBodyData {
|
||||||
|
pub name: String,
|
||||||
|
pub mass: f64, // kg
|
||||||
|
pub radius: f64, // km
|
||||||
|
pub position: (f64, f64, f64), // AU
|
||||||
|
pub velocity: (f64, f64, f64), // AU/day
|
||||||
|
pub model: ModelInfo,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub struct ModelInfo {
|
||||||
|
pub path: String,
|
||||||
|
pub scale: (f32, f32, f32),
|
||||||
|
}
|
||||||
564
src/main.rs
564
src/main.rs
@ -1,66 +1,55 @@
|
|||||||
use bevy::{
|
use bevy::{
|
||||||
core_pipeline::{bloom::Bloom, tonemapping::Tonemapping},
|
core_pipeline::{bloom::Bloom, tonemapping::Tonemapping},
|
||||||
input::mouse::{MouseScrollUnit, MouseWheel},
|
|
||||||
math::DVec3,
|
math::DVec3,
|
||||||
prelude::*,
|
prelude::*,
|
||||||
window::{WindowMode, WindowResolution},
|
window::{WindowMode, WindowResolution},
|
||||||
};
|
};
|
||||||
use bevy_inspector_egui::{bevy_egui::EguiPlugin, quick::WorldInspectorPlugin};
|
use bevy_inspector_egui::{bevy_egui::EguiPlugin, quick::WorldInspectorPlugin};
|
||||||
|
use bevy_panorbit_camera::{PanOrbitCamera, PanOrbitCameraPlugin};
|
||||||
|
use big_space::{
|
||||||
|
plugin::BigSpaceDefaultPlugins,
|
||||||
|
prelude::{BigSpaceCommands, FloatingOrigin},
|
||||||
|
};
|
||||||
use iyes_perf_ui::{PerfUiPlugin, prelude::*};
|
use iyes_perf_ui::{PerfUiPlugin, prelude::*};
|
||||||
use serde::Deserialize;
|
use solar_sim::InitialState;
|
||||||
|
|
||||||
mod jpl_horizon;
|
mod jpl_horizon;
|
||||||
|
|
||||||
// Data structures for deserializing initial_state.ron
|
|
||||||
#[derive(Deserialize)]
|
|
||||||
struct InitialState {
|
|
||||||
bodies: Vec<CelestialBodyData>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
|
||||||
struct CelestialBodyData {
|
|
||||||
name: String,
|
|
||||||
mass: f64, // kg
|
|
||||||
radius: f64, // km
|
|
||||||
position: (f64, f64, f64), // AU
|
|
||||||
velocity: (f64, f64, f64), // AU/day
|
|
||||||
}
|
|
||||||
|
|
||||||
// Scaling factor to convert AU to game units
|
// Scaling factor to convert AU to game units
|
||||||
// Neptune is approximately 30.1 astronomical units (AU) from the Sun
|
// Neptune is approximately 30.1 astronomical units (AU) from the Sun
|
||||||
// Point light effective range is about 10 game units, so 10 game units = ~30 AU
|
// Point light effective range is about 10 game units, so 10 game units = ~30 AU
|
||||||
const AU_TO_GAME_UNITS: f64 = 0.3;
|
const AU_TO_GAME_UNITS: f64 = 1. / 3.;
|
||||||
|
|
||||||
// Unit wrapper types - all distances in AU
|
// Unit wrapper types - all distances in AU
|
||||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
#[derive(Clone, Copy, Debug, PartialEq, Reflect)]
|
||||||
pub struct DistanceAu(pub f64);
|
pub struct DistanceAu(pub f64);
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
#[derive(Clone, Copy, Debug, PartialEq, Reflect)]
|
||||||
pub struct PositionAu(pub DVec3);
|
pub struct PositionAu(pub DVec3);
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
#[derive(Clone, Copy, Debug, PartialEq, Reflect)]
|
||||||
pub struct VelocityAuPerDay(pub DVec3);
|
pub struct VelocityAuPerDay(pub DVec3);
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
#[derive(Clone, Copy, Debug, PartialEq, Reflect)]
|
||||||
pub struct MassSolarMass(pub f64);
|
pub struct MassSolarMass(pub f64);
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq, Reflect)]
|
||||||
pub struct ObjectName(pub String);
|
pub struct ObjectName(pub String);
|
||||||
|
|
||||||
// Component wrappers
|
// Component wrappers
|
||||||
#[derive(Component)]
|
#[derive(Component, Reflect)]
|
||||||
struct Position(PositionAu);
|
struct Position(PositionAu);
|
||||||
|
|
||||||
#[derive(Component)]
|
#[derive(Component, Reflect)]
|
||||||
struct Velocity(VelocityAuPerDay);
|
struct Velocity(VelocityAuPerDay);
|
||||||
|
|
||||||
#[derive(Component)]
|
#[derive(Component, Reflect)]
|
||||||
struct Mass(MassSolarMass);
|
struct Mass(MassSolarMass);
|
||||||
|
|
||||||
#[derive(Component)]
|
#[derive(Component, Reflect)]
|
||||||
struct Radius(DistanceAu);
|
struct Radius(DistanceAu);
|
||||||
|
|
||||||
#[derive(Component)]
|
#[derive(Component, Reflect)]
|
||||||
struct Name(ObjectName);
|
struct Name(ObjectName);
|
||||||
|
|
||||||
#[derive(Bundle)]
|
#[derive(Bundle)]
|
||||||
@ -74,6 +63,19 @@ struct ObjectBundle {
|
|||||||
|
|
||||||
#[derive(Component)]
|
#[derive(Component)]
|
||||||
struct Star;
|
struct Star;
|
||||||
|
|
||||||
|
#[derive(Component)]
|
||||||
|
struct EmissiveEnhanced;
|
||||||
|
|
||||||
|
#[derive(Component)]
|
||||||
|
struct NeedsEmissiveEnhancement;
|
||||||
|
|
||||||
|
#[derive(Component)]
|
||||||
|
struct EmissiveEnhancementAttempts {
|
||||||
|
attempts: u32,
|
||||||
|
max_attempts: u32,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Component)]
|
#[derive(Component)]
|
||||||
struct Earth;
|
struct Earth;
|
||||||
|
|
||||||
@ -91,127 +93,58 @@ struct LabelVisible(bool);
|
|||||||
#[derive(Component)]
|
#[derive(Component)]
|
||||||
struct Trackable {}
|
struct Trackable {}
|
||||||
|
|
||||||
// Resource to track which entity the camera should follow
|
|
||||||
#[derive(Resource)]
|
#[derive(Resource)]
|
||||||
struct CameraFollow {
|
struct Origin {
|
||||||
target: Option<Entity>,
|
target: Option<Entity>,
|
||||||
distance: f32, // Current zoom distance from target
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct SolarRenderingPlugin;
|
pub struct SolarRenderingPlugin;
|
||||||
|
|
||||||
impl Plugin for SolarRenderingPlugin {
|
impl Plugin for SolarRenderingPlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
app.insert_resource(CameraFollow {
|
app.insert_resource(Origin { target: None })
|
||||||
target: None,
|
.add_systems(Startup, (setup_rendering, setup_ui))
|
||||||
distance: 10.0,
|
.add_systems(
|
||||||
})
|
FixedPostUpdate,
|
||||||
.add_systems(Startup, (setup_rendering, setup_ui))
|
(
|
||||||
.add_systems(
|
sync_position_to_transform,
|
||||||
FixedPostUpdate,
|
sync_name_labels,
|
||||||
(
|
manage_label_overlaps
|
||||||
sync_radius_to_mesh,
|
.after(sync_position_to_transform)
|
||||||
sync_position_to_transform,
|
.after(sync_name_labels),
|
||||||
sync_name_labels,
|
),
|
||||||
manage_label_overlaps.after(sync_position_to_transform).after(sync_name_labels),
|
)
|
||||||
camera_follow_system.after(sync_position_to_transform),
|
.add_systems(
|
||||||
),
|
PostUpdate,
|
||||||
)
|
(update_label_positions.after(manage_label_overlaps),),
|
||||||
.add_systems(PostUpdate, update_label_positions.after(manage_label_overlaps))
|
)
|
||||||
.add_systems(
|
.add_systems(
|
||||||
Update,
|
Update,
|
||||||
(
|
(
|
||||||
handle_label_clicks,
|
handle_label_clicks,
|
||||||
handle_scroll_zoom,
|
handle_speed_controls,
|
||||||
handle_speed_controls,
|
enhance_sun_emissive_with_retry,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn sync_radius_to_mesh(
|
|
||||||
mut commands: Commands,
|
|
||||||
mut meshes: ResMut<Assets<Mesh>>,
|
|
||||||
mut materials: ResMut<Assets<StandardMaterial>>,
|
|
||||||
query: Query<(Entity, &Radius, Option<&Star>, Option<&Mesh3d>), Changed<Radius>>,
|
|
||||||
) {
|
|
||||||
for (entity, radius, star, existing_mesh) in query.iter() {
|
|
||||||
// Convert AU to game units for rendering
|
|
||||||
let render_radius = radius.0.0 * AU_TO_GAME_UNITS;
|
|
||||||
|
|
||||||
// Create or update sphere mesh
|
|
||||||
let sphere_mesh = meshes.add(Sphere::new(render_radius as f32));
|
|
||||||
let material = materials.add(if star.is_none() {
|
|
||||||
StandardMaterial {
|
|
||||||
base_color: Color::WHITE,
|
|
||||||
..default()
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
StandardMaterial {
|
|
||||||
base_color: Color::WHITE, // Sun-like color for stars
|
|
||||||
emissive: LinearRgba::rgb(200.0, 200.0, 200.0),
|
|
||||||
..default()
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if existing_mesh.is_none() {
|
|
||||||
// Add mesh and material components if they don't exist
|
|
||||||
commands
|
|
||||||
.entity(entity)
|
|
||||||
.insert((Mesh3d(sphere_mesh), MeshMaterial3d(material)));
|
|
||||||
} else {
|
|
||||||
// Update existing mesh
|
|
||||||
commands.entity(entity).insert(Mesh3d(sphere_mesh));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sync_position_to_transform(
|
fn sync_position_to_transform(
|
||||||
mut commands: Commands,
|
mut query: Query<(Entity, &Position, &mut Transform)>,
|
||||||
mut query: Query<(Entity, &Position, Option<&mut Transform>), Changed<Position>>,
|
origin: Res<Origin>,
|
||||||
) {
|
) {
|
||||||
for (entity, position, transform) in query.iter_mut() {
|
// let offset = origin.target.map_or(DVec3::ZERO, |target| {
|
||||||
// Convert AU to game units for rendering
|
// query
|
||||||
let scaled_position = position.0.0 * AU_TO_GAME_UNITS;
|
// .get(target)
|
||||||
match transform {
|
// .map_or(DVec3::ZERO, |(_, position, _)| position.0.0)
|
||||||
Some(mut t) => {
|
// });
|
||||||
// Update existing transform
|
let offset = DVec3::ZERO;
|
||||||
t.translation = scaled_position.as_vec3();
|
for (_, position, mut transform) in query.iter_mut() {
|
||||||
}
|
transform.translation = ((position.0.0 - offset) * AU_TO_GAME_UNITS).as_vec3();
|
||||||
None => {
|
|
||||||
// Insert a new Transform if it doesn't exist
|
|
||||||
commands
|
|
||||||
.entity(entity)
|
|
||||||
.insert(Transform::from_translation(scaled_position.as_vec3()));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setup_rendering(mut commands: Commands) {
|
fn setup_rendering(mut commands: Commands) {
|
||||||
// Spawn camera with pan/orbit/zoom controls
|
|
||||||
// Place it at a good distance to view the solar system
|
|
||||||
commands.spawn((
|
|
||||||
Camera3d::default(),
|
|
||||||
Camera {
|
|
||||||
hdr: true,
|
|
||||||
clear_color: ClearColorConfig::Custom(Color::BLACK),
|
|
||||||
..default()
|
|
||||||
},
|
|
||||||
Projection::Perspective(PerspectiveProjection {
|
|
||||||
near: 1e-9, // Very close near plane for extreme zooming
|
|
||||||
..default()
|
|
||||||
}),
|
|
||||||
Tonemapping::TonyMcMapface,
|
|
||||||
Transform::from_translation(Vec3::new(0., 0., 10.0)),
|
|
||||||
Bloom::NATURAL,
|
|
||||||
));
|
|
||||||
|
|
||||||
commands.spawn(PointLight {
|
|
||||||
color: Color::WHITE,
|
|
||||||
shadows_enabled: true,
|
|
||||||
..default()
|
|
||||||
});
|
|
||||||
commands.spawn(PerfUiAllEntries::default());
|
commands.spawn(PerfUiAllEntries::default());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -273,7 +206,7 @@ fn manage_label_overlaps(
|
|||||||
|
|
||||||
// Collect all on-screen objects with their screen positions and radii
|
// Collect all on-screen objects with their screen positions and radii
|
||||||
let mut visible_objects: Vec<(Entity, Vec2, f64, String)> = Vec::new();
|
let mut visible_objects: Vec<(Entity, Vec2, f64, String)> = Vec::new();
|
||||||
|
|
||||||
for (label, _) in label_query.iter() {
|
for (label, _) in label_query.iter() {
|
||||||
if let Ok((global_transform, name, radius)) = objects_query.get(label.target_entity) {
|
if let Ok((global_transform, name, radius)) = objects_query.get(label.target_entity) {
|
||||||
let world_pos = global_transform.translation();
|
let world_pos = global_transform.translation();
|
||||||
@ -295,12 +228,12 @@ fn manage_label_overlaps(
|
|||||||
|
|
||||||
// Check for overlaps and hide smaller objects
|
// Check for overlaps and hide smaller objects
|
||||||
const OVERLAP_THRESHOLD: f32 = 50.0; // pixels
|
const OVERLAP_THRESHOLD: f32 = 50.0; // pixels
|
||||||
|
|
||||||
for i in 0..visible_objects.len() {
|
for i in 0..visible_objects.len() {
|
||||||
for j in (i + 1)..visible_objects.len() {
|
for j in (i + 1)..visible_objects.len() {
|
||||||
let (entity_a, pos_a, radius_a, name_a) = &visible_objects[i];
|
let (entity_a, pos_a, radius_a, name_a) = &visible_objects[i];
|
||||||
let (entity_b, pos_b, radius_b, name_b) = &visible_objects[j];
|
let (entity_b, pos_b, radius_b, name_b) = &visible_objects[j];
|
||||||
|
|
||||||
let distance = pos_a.distance(*pos_b);
|
let distance = pos_a.distance(*pos_b);
|
||||||
if distance < OVERLAP_THRESHOLD {
|
if distance < OVERLAP_THRESHOLD {
|
||||||
// Determine which label to hide based on radius (larger wins)
|
// Determine which label to hide based on radius (larger wins)
|
||||||
@ -310,7 +243,11 @@ fn manage_label_overlaps(
|
|||||||
*entity_a
|
*entity_a
|
||||||
} else {
|
} else {
|
||||||
// If radii are equal, prefer alphabetically first name
|
// If radii are equal, prefer alphabetically first name
|
||||||
if name_a < name_b { *entity_b } else { *entity_a }
|
if name_a < name_b {
|
||||||
|
*entity_b
|
||||||
|
} else {
|
||||||
|
*entity_a
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Hide the smaller object's label
|
// Hide the smaller object's label
|
||||||
@ -371,76 +308,25 @@ fn handle_label_clicks(
|
|||||||
(Changed<Interaction>, With<ObjectLabel>),
|
(Changed<Interaction>, With<ObjectLabel>),
|
||||||
>,
|
>,
|
||||||
trackable_objects: Query<(&Transform, &Trackable, &Radius)>,
|
trackable_objects: Query<(&Transform, &Trackable, &Radius)>,
|
||||||
mut camera_query: Query<&mut Transform, (With<Camera>, Without<Trackable>)>,
|
mut camera: Single<&mut PanOrbitCamera>,
|
||||||
mut camera_follow: ResMut<CameraFollow>,
|
mut origin: ResMut<Origin>,
|
||||||
) {
|
) {
|
||||||
for (interaction, label) in interaction_query.iter() {
|
for (interaction, label) in interaction_query.iter() {
|
||||||
if *interaction == Interaction::Pressed {
|
if *interaction == Interaction::Pressed {
|
||||||
if let Ok((target_transform, _trackable, radius)) =
|
if let Ok((_target_transform, _trackable, radius)) =
|
||||||
trackable_objects.get(label.target_entity)
|
trackable_objects.get(label.target_entity)
|
||||||
{
|
{
|
||||||
if let Ok(mut camera_transform) = camera_query.single_mut() {
|
// Calculate appropriate distance based on entity radius (with some padding)
|
||||||
let target_world_pos = target_transform.translation;
|
let entity_radius = (radius.0.0 * AU_TO_GAME_UNITS) as f32;
|
||||||
|
camera.target_radius = entity_radius * 10.;
|
||||||
// Calculate appropriate distance based on entity radius (with some padding)
|
camera.zoom_lower_limit = entity_radius * 4.;
|
||||||
let entity_radius = (radius.0.0 * AU_TO_GAME_UNITS) as f32;
|
camera.target_focus = Vec3::ZERO;
|
||||||
let desired_distance = entity_radius * 16.0; // 8x radius
|
origin.target = Some(label.target_entity);
|
||||||
|
|
||||||
// Position camera at desired distance from target
|
|
||||||
let camera_direction =
|
|
||||||
(camera_transform.translation - target_world_pos).normalize();
|
|
||||||
let new_camera_pos = target_world_pos + camera_direction * desired_distance;
|
|
||||||
|
|
||||||
camera_transform.translation = new_camera_pos;
|
|
||||||
camera_transform.look_at(target_world_pos, Vec3::Y);
|
|
||||||
|
|
||||||
// Set the follow target and initial distance
|
|
||||||
camera_follow.target = Some(label.target_entity);
|
|
||||||
camera_follow.distance = desired_distance;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn camera_follow_system(
|
|
||||||
camera_follow: Res<CameraFollow>,
|
|
||||||
objects_query: Query<&Transform, With<Trackable>>,
|
|
||||||
mut camera_query: Query<&mut Transform, (With<Camera>, Without<Trackable>)>,
|
|
||||||
) {
|
|
||||||
if let Some(target_entity) = camera_follow.target {
|
|
||||||
if let Ok(target_transform) = objects_query.get(target_entity) {
|
|
||||||
if let Ok(mut camera_transform) = camera_query.single_mut() {
|
|
||||||
// Fixed camera direction relative to tracked object (stationary relative position)
|
|
||||||
let fixed_direction = Vec3::new(0.0, 0.0, 1.0);
|
|
||||||
|
|
||||||
// Position camera at the specified distance from target in fixed direction
|
|
||||||
let new_camera_pos =
|
|
||||||
target_transform.translation + fixed_direction * camera_follow.distance;
|
|
||||||
camera_transform.translation = new_camera_pos;
|
|
||||||
|
|
||||||
// Keep camera looking at the target entity
|
|
||||||
camera_transform.look_at(target_transform.translation, Vec3::Y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn handle_scroll_zoom(
|
|
||||||
mut scroll_events: EventReader<MouseWheel>,
|
|
||||||
mut camera_follow: ResMut<CameraFollow>,
|
|
||||||
) {
|
|
||||||
for event in scroll_events.read() {
|
|
||||||
let zoom_delta = match event.unit {
|
|
||||||
MouseScrollUnit::Line => event.y * 0.1,
|
|
||||||
MouseScrollUnit::Pixel => event.y * 0.01,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Update zoom distance with limits
|
|
||||||
camera_follow.distance = (camera_follow.distance * (1.0 - zoom_delta)).clamp(1e-9, 100.0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn handle_speed_controls(
|
fn handle_speed_controls(
|
||||||
keyboard_input: Res<ButtonInput<KeyCode>>,
|
keyboard_input: Res<ButtonInput<KeyCode>>,
|
||||||
mut time: ResMut<Time<Virtual>>,
|
mut time: ResMut<Time<Virtual>>,
|
||||||
@ -456,13 +342,13 @@ fn handle_speed_controls(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Speed up with + or = key (double current speed, max 64x)
|
// Speed up with + or = key (double current speed, max 32x)
|
||||||
if keyboard_input.just_pressed(KeyCode::Equal)
|
if keyboard_input.just_pressed(KeyCode::Equal)
|
||||||
|| keyboard_input.just_pressed(KeyCode::NumpadAdd)
|
|| keyboard_input.just_pressed(KeyCode::NumpadAdd)
|
||||||
{
|
{
|
||||||
if !time.is_paused() {
|
if !time.is_paused() {
|
||||||
let current_speed = time.relative_speed();
|
let current_speed = time.relative_speed();
|
||||||
let new_speed = (current_speed * 2.0).min(64.0);
|
let new_speed = (current_speed * 2.0).min(32.0);
|
||||||
time.set_relative_speed(new_speed);
|
time.set_relative_speed(new_speed);
|
||||||
println!("Speed: {}x", new_speed);
|
println!("Speed: {}x", new_speed);
|
||||||
}
|
}
|
||||||
@ -488,75 +374,208 @@ fn handle_speed_controls(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn initialize_camera_follow(
|
fn enhance_sun_emissive_with_retry(
|
||||||
earth_query: Query<Entity, (With<Earth>, With<Trackable>)>,
|
mut commands: Commands,
|
||||||
mut camera_follow: ResMut<CameraFollow>,
|
mesh_query: Query<&MeshMaterial3d<StandardMaterial>>,
|
||||||
|
mut sun_query: Query<
|
||||||
|
(Entity, &Children, Option<&mut EmissiveEnhancementAttempts>),
|
||||||
|
(
|
||||||
|
With<Star>,
|
||||||
|
With<NeedsEmissiveEnhancement>,
|
||||||
|
Without<EmissiveEnhanced>,
|
||||||
|
),
|
||||||
|
>,
|
||||||
|
children_query: Query<&Children>,
|
||||||
|
mut materials: ResMut<Assets<StandardMaterial>>,
|
||||||
) {
|
) {
|
||||||
if let Ok(earth) = earth_query.single() {
|
for (sun_entity, children, attempts_opt) in sun_query.iter_mut() {
|
||||||
camera_follow.target = Some(earth);
|
// Initialize attempts tracking if not present
|
||||||
camera_follow.distance = 1e-3;
|
let mut attempts = if let Some(mut att) = attempts_opt {
|
||||||
|
att.attempts += 1;
|
||||||
|
att.attempts
|
||||||
|
} else {
|
||||||
|
// First attempt, add the component
|
||||||
|
commands
|
||||||
|
.entity(sun_entity)
|
||||||
|
.insert(EmissiveEnhancementAttempts {
|
||||||
|
attempts: 1,
|
||||||
|
max_attempts: 300, // Try for ~5 seconds at 60fps
|
||||||
|
});
|
||||||
|
1
|
||||||
|
};
|
||||||
|
|
||||||
|
// Only try every 10 frames to avoid spam
|
||||||
|
if attempts % 10 != 0 {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
info!("Attempting sun emissive enhancement (attempt {})", attempts);
|
||||||
|
|
||||||
|
// Try to enhance the sun's emissive material
|
||||||
|
let enhanced =
|
||||||
|
enhance_emissive_for_children(children, &children_query, &mesh_query, &mut materials);
|
||||||
|
|
||||||
|
if enhanced {
|
||||||
|
info!("Successfully enhanced sun emissive material!");
|
||||||
|
// Mark this sun as enhanced to avoid repeated processing
|
||||||
|
commands.entity(sun_entity).insert(EmissiveEnhanced);
|
||||||
|
commands
|
||||||
|
.entity(sun_entity)
|
||||||
|
.remove::<NeedsEmissiveEnhancement>();
|
||||||
|
commands
|
||||||
|
.entity(sun_entity)
|
||||||
|
.remove::<EmissiveEnhancementAttempts>();
|
||||||
|
} else if attempts >= 300 {
|
||||||
|
// Give up after max attempts
|
||||||
|
info!(
|
||||||
|
"Giving up on sun emissive enhancement after {} attempts",
|
||||||
|
attempts
|
||||||
|
);
|
||||||
|
commands
|
||||||
|
.entity(sun_entity)
|
||||||
|
.remove::<NeedsEmissiveEnhancement>();
|
||||||
|
commands
|
||||||
|
.entity(sun_entity)
|
||||||
|
.remove::<EmissiveEnhancementAttempts>();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setup_solar_system(mut commands: Commands) {
|
fn enhance_emissive_for_children(
|
||||||
// Load initial state from RON file
|
children: &Children,
|
||||||
let initial_state_content = match std::fs::read_to_string("assets/initial_state.ron") {
|
children_query: &Query<&Children>,
|
||||||
Ok(content) => content,
|
mesh_query: &Query<&MeshMaterial3d<StandardMaterial>>,
|
||||||
Err(err) => {
|
materials: &mut ResMut<Assets<StandardMaterial>>,
|
||||||
error!("Failed to read initial_state.ron: {}", err);
|
) -> bool {
|
||||||
return;
|
let mut enhanced_any = false;
|
||||||
|
|
||||||
|
for child in children.iter() {
|
||||||
|
// Try to enhance material for this child if it has a mesh
|
||||||
|
if let Ok(material_handle) = mesh_query.get(child) {
|
||||||
|
if let Some(material) = materials.get_mut(&material_handle.0) {
|
||||||
|
// Enhance emissive properties while preserving existing textures
|
||||||
|
// Set emissive to bright white to enhance the existing emissive texture
|
||||||
|
info!("Enhanced material for child entity!");
|
||||||
|
material.emissive = LinearRgba::rgb(200.0, 200.0, 200.0);
|
||||||
|
// Keep all existing textures (base_color_texture, emissive_texture, etc.)
|
||||||
|
enhanced_any = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
let initial_state: InitialState = match ron::from_str(&initial_state_content) {
|
// Recursively check this child's children
|
||||||
Ok(state) => state,
|
if let Ok(grandchildren) = children_query.get(child) {
|
||||||
Err(err) => {
|
if enhance_emissive_for_children(grandchildren, children_query, mesh_query, materials) {
|
||||||
error!("Failed to parse initial_state.ron: {}", err);
|
enhanced_any = true;
|
||||||
return;
|
}
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
// Spawn all celestial bodies from the initial state
|
enhanced_any
|
||||||
for body_data in initial_state.bodies {
|
}
|
||||||
// Convert radius from km to AU
|
|
||||||
let radius_au = body_data.radius / 149597870.691; // km to AU conversion
|
|
||||||
|
|
||||||
// Convert mass from kg to solar masses
|
|
||||||
let mass_solar = body_data.mass / SOLAR_MASS_KG;
|
|
||||||
|
|
||||||
// Create base bundle
|
const AU_TO_KM: f64 = 149597870.691;
|
||||||
let mut entity_commands = commands.spawn((
|
|
||||||
ObjectBundle {
|
fn setup_solar_system(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||||
name: Name(ObjectName(body_data.name.clone())),
|
commands.spawn_big_space_default(|commands| {
|
||||||
position: Position(PositionAu(DVec3::new(
|
commands.spawn((
|
||||||
body_data.position.0,
|
PanOrbitCamera {
|
||||||
body_data.position.1,
|
zoom_lower_limit: 1e-6,
|
||||||
body_data.position.2,
|
..default()
|
||||||
))),
|
|
||||||
velocity: Velocity(VelocityAuPerDay(DVec3::new(
|
|
||||||
body_data.velocity.0,
|
|
||||||
body_data.velocity.1,
|
|
||||||
body_data.velocity.2,
|
|
||||||
))),
|
|
||||||
mass: Mass(MassSolarMass(mass_solar)),
|
|
||||||
radius: Radius(DistanceAu(radius_au)),
|
|
||||||
},
|
},
|
||||||
Trackable {},
|
Camera {
|
||||||
|
hdr: true,
|
||||||
|
clear_color: ClearColorConfig::Custom(Color::BLACK),
|
||||||
|
..default()
|
||||||
|
},
|
||||||
|
Projection::Perspective(PerspectiveProjection {
|
||||||
|
near: 1e-8, // Very close near plane for extreme zooming
|
||||||
|
far: 1e-2,
|
||||||
|
..default()
|
||||||
|
}),
|
||||||
|
Tonemapping::TonyMcMapface,
|
||||||
|
Transform::from_translation(Vec3::new(0., 0., 10.0)),
|
||||||
|
Bloom::NATURAL,
|
||||||
|
FloatingOrigin,
|
||||||
));
|
));
|
||||||
|
|
||||||
// Add special components for Sun and Earth
|
// Load initial state from RON file
|
||||||
match body_data.name.as_str() {
|
let initial_state_content = match std::fs::read_to_string("assets/initial_state.ron") {
|
||||||
"Sun" => {
|
Ok(content) => content,
|
||||||
entity_commands.insert(Star);
|
Err(err) => {
|
||||||
|
error!("Failed to read initial_state.ron: {}", err);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
"Earth" => {
|
};
|
||||||
entity_commands.insert(Earth);
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
|
|
||||||
info!("Spawned celestial body: {}", body_data.name);
|
let initial_state: InitialState = match ron::from_str(&initial_state_content) {
|
||||||
}
|
Ok(state) => state,
|
||||||
|
Err(err) => {
|
||||||
|
error!("Failed to parse initial_state.ron: {}", err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
for body_data in initial_state.bodies {
|
||||||
|
// Convert radius from km to AU
|
||||||
|
let radius_au = body_data.radius / AU_TO_KM; // km to AU conversion
|
||||||
|
|
||||||
|
// Convert mass from kg to solar masses
|
||||||
|
let mass_solar = body_data.mass / SOLAR_MASS_KG;
|
||||||
|
|
||||||
|
// Create base bundle
|
||||||
|
let mut entity_commands = commands.spawn((
|
||||||
|
ObjectBundle {
|
||||||
|
name: Name(ObjectName(body_data.name.clone())),
|
||||||
|
position: Position(PositionAu(DVec3::new(
|
||||||
|
body_data.position.0,
|
||||||
|
body_data.position.1,
|
||||||
|
body_data.position.2,
|
||||||
|
))),
|
||||||
|
velocity: Velocity(VelocityAuPerDay(DVec3::new(
|
||||||
|
body_data.velocity.0,
|
||||||
|
body_data.velocity.1,
|
||||||
|
body_data.velocity.2,
|
||||||
|
))),
|
||||||
|
mass: Mass(MassSolarMass(mass_solar)),
|
||||||
|
radius: Radius(DistanceAu(radius_au)),
|
||||||
|
},
|
||||||
|
Trackable {},
|
||||||
|
Transform::default(),
|
||||||
|
Visibility::default(),
|
||||||
|
));
|
||||||
|
let scene_handle = asset_server.load(format!("models/{}#Scene0", body_data.model.path));
|
||||||
|
entity_commands.with_child((
|
||||||
|
SceneRoot(scene_handle.clone()),
|
||||||
|
Transform::from_scale(
|
||||||
|
Vec3::new(
|
||||||
|
body_data.model.scale.0,
|
||||||
|
body_data.model.scale.1,
|
||||||
|
body_data.model.scale.2,
|
||||||
|
) / AU_TO_KM as f32
|
||||||
|
* 10000.,
|
||||||
|
),
|
||||||
|
));
|
||||||
|
|
||||||
|
// Add special components for Sun and Earth
|
||||||
|
match body_data.name.as_str() {
|
||||||
|
"Sun" => {
|
||||||
|
entity_commands.insert(Star);
|
||||||
|
entity_commands.insert(NeedsEmissiveEnhancement);
|
||||||
|
entity_commands.insert(PointLight {
|
||||||
|
color: Color::WHITE,
|
||||||
|
shadows_enabled: true,
|
||||||
|
..default()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
"Earth" => {
|
||||||
|
entity_commands.insert(Earth);
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
info!("Spawned celestial body: {}", body_data.name);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// High precision constants
|
// High precision constants
|
||||||
@ -570,10 +589,9 @@ const K_GAUSS: f64 = 0.01720209895; // AU^(3/2) / (solar_mass^(1/2) × day)
|
|||||||
// This gives G×M_sun in AU³/day² units, and since we use solar mass units (M_sun = 1), G_AU = k²
|
// This gives G×M_sun in AU³/day² units, and since we use solar mass units (M_sun = 1), G_AU = k²
|
||||||
const G_AU: f64 = K_GAUSS * K_GAUSS;
|
const G_AU: f64 = K_GAUSS * K_GAUSS;
|
||||||
|
|
||||||
const STEPS: usize = 100;
|
const STEPS: usize = 20; // Number of steps per fixed update
|
||||||
// If FixedUpdate is 64 Hz and you want 1 day per game second: DT = 1/(64*STEPS) day/step
|
// If FixedUpdate is 64 Hz and you want 1 day per game second: DT = 1/(64*STEPS) day/step
|
||||||
const DT: f64 = 1.0 / (64.0 * STEPS as f64);
|
const DT: f64 = 1.0 / (64.0 * STEPS as f64);
|
||||||
|
|
||||||
fn n_body(mut query: Query<(&Mass, &mut Position, &mut Velocity)>) {
|
fn n_body(mut query: Query<(&Mass, &mut Position, &mut Velocity)>) {
|
||||||
// Pull data out once. This copy lets us integrate freely without borrow issues.
|
// Pull data out once. This copy lets us integrate freely without borrow issues.
|
||||||
// (If you want zero copies, use a Resource scratch buffer and reuse it across frames.)
|
// (If you want zero copies, use a Resource scratch buffer and reuse it across frames.)
|
||||||
@ -655,16 +673,27 @@ fn n_body(mut query: Query<(&Mass, &mut Position, &mut Velocity)>) {
|
|||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
App::new()
|
App::new()
|
||||||
.add_plugins(DefaultPlugins.set(WindowPlugin {
|
.add_plugins(
|
||||||
primary_window: Some(Window {
|
DefaultPlugins
|
||||||
title: "Solar Sim".to_string(),
|
.set(WindowPlugin {
|
||||||
mode: WindowMode::BorderlessFullscreen(MonitorSelection::Primary),
|
primary_window: Some(Window {
|
||||||
resolution: WindowResolution::default().with_scale_factor_override(2.0),
|
title: "Solar Sim".to_string(),
|
||||||
..default()
|
mode: WindowMode::BorderlessFullscreen(MonitorSelection::Primary),
|
||||||
}),
|
resolution: WindowResolution::default().with_scale_factor_override(2.0),
|
||||||
..default()
|
..default()
|
||||||
}))
|
}),
|
||||||
|
..default()
|
||||||
|
})
|
||||||
|
.disable::<TransformPlugin>(),
|
||||||
|
)
|
||||||
|
.add_plugins(BigSpaceDefaultPlugins)
|
||||||
.add_plugins(EguiPlugin::default())
|
.add_plugins(EguiPlugin::default())
|
||||||
|
.add_plugins(PanOrbitCameraPlugin)
|
||||||
|
.register_type::<Name>()
|
||||||
|
.register_type::<Radius>()
|
||||||
|
.register_type::<DistanceAu>()
|
||||||
|
.register_type::<Mass>()
|
||||||
|
.register_type::<MassSolarMass>()
|
||||||
.add_plugins(WorldInspectorPlugin::new())
|
.add_plugins(WorldInspectorPlugin::new())
|
||||||
.add_plugins(SolarRenderingPlugin) // we want Bevy to measure these values for us:
|
.add_plugins(SolarRenderingPlugin) // we want Bevy to measure these values for us:
|
||||||
.add_plugins(bevy::diagnostic::FrameTimeDiagnosticsPlugin::default())
|
.add_plugins(bevy::diagnostic::FrameTimeDiagnosticsPlugin::default())
|
||||||
@ -672,10 +701,7 @@ fn main() {
|
|||||||
.add_plugins(bevy::diagnostic::SystemInformationDiagnosticsPlugin)
|
.add_plugins(bevy::diagnostic::SystemInformationDiagnosticsPlugin)
|
||||||
.add_plugins(bevy::render::diagnostic::RenderDiagnosticsPlugin)
|
.add_plugins(bevy::render::diagnostic::RenderDiagnosticsPlugin)
|
||||||
.add_plugins(PerfUiPlugin)
|
.add_plugins(PerfUiPlugin)
|
||||||
.add_systems(
|
.add_systems(Startup, (setup_solar_system).chain())
|
||||||
Startup,
|
.add_systems(FixedUpdate, n_body) // Use the optimized n-body system
|
||||||
(setup_solar_system, initialize_camera_follow).chain(),
|
|
||||||
)
|
|
||||||
.add_systems(FixedUpdate, n_body)
|
|
||||||
.run();
|
.run();
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user