diff --git a/apps/game/src/gameplay/galaxy/mod.rs b/apps/game/src/gameplay/galaxy/mod.rs index d573c1d..5cb3d11 100644 --- a/apps/game/src/gameplay/galaxy/mod.rs +++ b/apps/game/src/gameplay/galaxy/mod.rs @@ -221,7 +221,6 @@ fn generate_system_positions(params: &GalaxyParams, rng: &mut StdRng) -> Vec, rng: &mut StdRng, @@ -325,26 +322,8 @@ fn generate_disk( base_spacing: f32, next_index: &mut usize, disk_index: usize, - core_radius: f32, ) { let arm_count = disk.arms.max(1); - // Effective outer radius: explicit value if set, else galaxy size. - let outer = if disk.outer_radius > 0.0 { - disk.outer_radius - } else { - galaxy_size - }; - // Anchor disk arms to the core: when inner_radius is 0 (auto), start - // systems inside the core zone so arms visually emerge from the core - // boundary rather than appearing detached. The 0.4 factor places the - // density peak well inside the core sphere, producing overlap that - // creates a seamless core-to-arm transition. - let inner = if disk.inner_radius > 0.0 { - disk.inner_radius - } else { - core_radius * 0.4 - }; - let span = (outer - inner).max(1.0); // Pre-compute the rotation quaternion for this disk's tilt + Y rotation. // Tilt is applied first (around X), then the Y rotation offset. @@ -368,12 +347,9 @@ fn generate_disk( let mut position = Option::::None; let mut final_radius = 0.0f32; for attempt in 0..SPACING_ATTEMPTS { - // powf(0.45) concentrates ~60% of systems in the inner 30% of the - // radial span, ensuring arms are dense near the core boundary and - // fade naturally toward the edge. - let r = inner + rng.gen::().powf(0.45) * span; + let r = rng.gen::().powf(0.62) * galaxy_size; let angle = std::f32::consts::TAU * arm as f32 / arm_count as f32 - + ((r - inner) / span) * disk.twist + + (r / galaxy_size) * disk.twist + (rng.gen::() - 0.5) * arm_scatter(arm_count); let y = (rng.gen::() - 0.5) * 20.0; let mut candidate = Vec3::new(angle.cos() * r, y, angle.sin() * r); diff --git a/apps/game/src/gameplay/galaxy/params.rs b/apps/game/src/gameplay/galaxy/params.rs index 1910bf6..5684d09 100644 --- a/apps/game/src/gameplay/galaxy/params.rs +++ b/apps/game/src/gameplay/galaxy/params.rs @@ -81,13 +81,6 @@ pub const DISK_ROTATION_MAX: f32 = std::f32::consts::TAU; /// 30° steps. pub const DISK_ROTATION_STEP: f32 = std::f32::consts::TAU / 12.0; -pub const DISK_INNER_RADIUS_MIN: f32 = 0.0; -pub const DISK_INNER_RADIUS_MAX: f32 = 400.0; -pub const DISK_INNER_RADIUS_STEP: f32 = 10.0; -pub const DISK_OUTER_RADIUS_MIN: f32 = 40.0; -pub const DISK_OUTER_RADIUS_MAX: f32 = 420.0; -pub const DISK_OUTER_RADIUS_STEP: f32 = 10.0; - pub const BEAM_COUNT_MIN: usize = 0; pub const BEAM_COUNT_MAX: usize = 120; pub const BEAM_COUNT_STEP: usize = 4; @@ -139,11 +132,12 @@ impl Default for CoreParams { /// One independent disk layer of spiral arms. /// -/// Disks are generated in the XZ plane and then tilted by [`Self::tilt`] -/// (rotation around the X axis) and rotated by [`Self::rotation_offset`] -/// (around the Y axis). Systems are placed between [`Self::inner_radius`] -/// and [`Self::outer_radius`]; if `outer_radius` is 0 the galaxy-wide -/// [`GalaxyParams::size`] is used instead. +/// Disks are generated in the XZ plane with systems sweeping continuously +/// from the origin to `galaxy_size` (no inner/outer radius gap), then +/// tilted by [`Self::tilt`] (rotation around X) and rotated by +/// [`Self::rotation_offset`] (around Y). The `powf(0.62)` density bias +/// packs systems near the origin so arms flow naturally from the dense +/// core cluster outward. #[derive(Debug, Clone)] pub struct DiskParams { pub count: usize, @@ -157,11 +151,6 @@ pub struct DiskParams { /// Rotates the disk in the horizontal plane, determining where the /// tilted disk's "high side" points. pub rotation_offset: f32, - /// Minimum distance from the origin for systems in this disk. - /// 0 = systems can start at the origin (overlapping the core). - pub inner_radius: f32, - /// Maximum distance from the origin. 0 = use [`GalaxyParams::size`]. - pub outer_radius: f32, } impl Default for DiskParams { @@ -172,8 +161,6 @@ impl Default for DiskParams { twist: DEFAULT_DISK_TWIST, tilt: 0.0, rotation_offset: 0.0, - inner_radius: 0.0, - outer_radius: 0.0, // means "use galaxy size" } } } diff --git a/apps/game/src/gameplay/galaxy/ui.rs b/apps/game/src/gameplay/galaxy/ui.rs index b5cb452..5838394 100644 --- a/apps/game/src/gameplay/galaxy/ui.rs +++ b/apps/game/src/gameplay/galaxy/ui.rs @@ -61,10 +61,6 @@ pub enum ParamButton { DiskTiltIncr, DiskRotationDecr, DiskRotationIncr, - DiskInnerRadiusDecr, - DiskInnerRadiusIncr, - DiskOuterRadiusDecr, - DiskOuterRadiusIncr, // Top beam (+Y) BeamTopEnabled, BeamTopThicknessDecr, @@ -585,30 +581,7 @@ pub fn param_button_handler( .min(DISK_ROTATION_MAX); params.bump_generation(); } - ParamButton::DiskInnerRadiusDecr => { - let disk = selected_disk_mut(&mut params, selected_disk.0); - disk.inner_radius = - (disk.inner_radius - DISK_INNER_RADIUS_STEP).max(DISK_INNER_RADIUS_MIN); - params.bump_generation(); - } - ParamButton::DiskInnerRadiusIncr => { - let disk = selected_disk_mut(&mut params, selected_disk.0); - disk.inner_radius = - (disk.inner_radius + DISK_INNER_RADIUS_STEP).min(DISK_INNER_RADIUS_MAX); - params.bump_generation(); - } - ParamButton::DiskOuterRadiusDecr => { - let disk = selected_disk_mut(&mut params, selected_disk.0); - disk.outer_radius = - (disk.outer_radius - DISK_OUTER_RADIUS_STEP).max(DISK_OUTER_RADIUS_MIN); - params.bump_generation(); - } - ParamButton::DiskOuterRadiusIncr => { - let disk = selected_disk_mut(&mut params, selected_disk.0); - disk.outer_radius = - (disk.outer_radius + DISK_OUTER_RADIUS_STEP).min(DISK_OUTER_RADIUS_MAX); - params.bump_generation(); - } + // ── Top Beam (+Y) ───────────────────────────────────────────── ParamButton::BeamTopEnabled => { params.beam_top.enabled = !params.beam_top.enabled; @@ -814,20 +787,7 @@ pub fn refresh_control_panel_values( "disk_twist" => format!("{:.1}", disk.twist), "disk_tilt" => format!("{:.0}°", disk.tilt.to_degrees()), "disk_rotation" => format!("{:.0}°", disk.rotation_offset.to_degrees()), - "disk_inner_radius" => { - if disk.inner_radius > 0.0 { - format!("{:.0}", disk.inner_radius) - } else { - "0".to_string() - } - } - "disk_outer_radius" => { - if disk.outer_radius > 0.0 { - format!("{:.0}", disk.outer_radius) - } else { - "auto".to_string() - } - } + // Top beam "beam_top_enabled" => { format!( @@ -1092,21 +1052,6 @@ fn spawn_scroll_contents_with_tabs( ParamButton::DiskRotationDecr, ParamButton::DiskRotationIncr, ); - spawn_param_row( - scroll, - "Inner Rad", - "disk_inner_radius", - ParamButton::DiskInnerRadiusDecr, - ParamButton::DiskInnerRadiusIncr, - ); - spawn_param_row( - scroll, - "Outer Rad", - "disk_outer_radius", - ParamButton::DiskOuterRadiusDecr, - ParamButton::DiskOuterRadiusIncr, - ); - // Remove button — only show if more than one disk. if params.disks.len() > 1 { scroll @@ -1334,22 +1279,6 @@ fn randomize_disk(rng: &mut impl rand::Rng) -> DiskParams { disk.rotation_offset = rng.gen_range(DISK_ROTATION_MIN..=DISK_ROTATION_MAX); disk.rotation_offset = (disk.rotation_offset / DISK_ROTATION_STEP).round() * DISK_ROTATION_STEP; - // Bias inner_radius toward 0 (auto) ~70% of the time so randomized disks - // are always anchored to the core by default. - if rng.gen_bool(0.7) { - disk.inner_radius = 0.0; - } else { - disk.inner_radius = rng.gen_range(DISK_INNER_RADIUS_MIN..=DISK_INNER_RADIUS_MAX); - disk.inner_radius = - (disk.inner_radius / DISK_INNER_RADIUS_STEP).round() * DISK_INNER_RADIUS_STEP; - } - disk.outer_radius = rng.gen_range(DISK_OUTER_RADIUS_MIN..=DISK_OUTER_RADIUS_MAX); - disk.outer_radius = - (disk.outer_radius / DISK_OUTER_RADIUS_STEP).round() * DISK_OUTER_RADIUS_STEP; - // Allow 0 (auto) ~60% of the time so disks fill the galaxy by default. - if rng.gen_bool(0.6) { - disk.outer_radius = 0.0; - } disk }