-
Notifications
You must be signed in to change notification settings - Fork 0
Open
Labels
Description
bevy_zeroverse/src/scene/semantic_room.rs
Line 307 in c696609
// TODO: support bailing on room spawn if required room features are too large (e.g. no door) |
}
const CLEARANCE: f32 = 1e-4;
#[allow(clippy::too_many_arguments)]
fn spawn_face(
commands: &mut ChildSpawnerCommands,
room_settings: &ZeroverseSemanticRoomSettings,
origin: Vec3,
basis: Quat,
half_extents: Vec3,
cull_mode: Option<Face>,
invert_normals: bool,
label: SemanticLabel,
name: &str,
wall: bool,
) {
let mut rng = rand::thread_rng();
let base = ZeroversePrimitiveSettings {
cull_mode,
invert_normals,
available_types: vec![ZeroversePrimitives::Plane],
components: CountSampler::Exact(1),
wireframe_probability: 0.0,
noise_probability: 0.0,
cast_shadows: false,
rotation_sampler: RotationSampler::Exact(basis),
..default()
};
let mut spawn_segment = |pos: Vec3, half_size: Vec3, suffix: &str| {
commands.spawn((
ZeroversePrimitiveSettings {
position_sampler: PositionSampler::Exact { position: origin + basis * pos },
scale_sampler: ScaleSampler::Exact(half_size),
..base.clone()
},
Name::new(format!("{name}{suffix}")),
label.clone(),
));
};
let make_window = wall && rng.gen_bool(room_settings.window_probability as f64);
if !make_window {
spawn_segment(Vec3::ZERO, half_extents, "");
return;
}
let hx = half_extents.x;
let hz = half_extents.z;
let max_w_frac = 1.0 - CLEARANCE / hx;
let max_h_frac = 1.0 - CLEARANCE / hz;
let min_w_frac = room_settings.window_size_min.x.clamp(0.0, max_w_frac);
let max_w_frac = room_settings.window_size_max.x.clamp(min_w_frac, max_w_frac);
let min_h_frac = room_settings.window_size_min.y.clamp(0.0, max_h_frac);
let max_h_frac = room_settings.window_size_max.y.clamp(min_h_frac, max_h_frac);
let w_frac = rng.gen_range(min_w_frac..=max_w_frac);
let h_frac = rng.gen_range(min_h_frac..=max_h_frac);
let half_win_w = hx * w_frac;
let half_win_h = hz * h_frac;
let win_cx = rng.gen_range((-hx + half_win_w + CLEARANCE)..=(hx - half_win_w - CLEARANCE));
let win_cz = rng.gen_range((-hz + half_win_h + CLEARANCE)..=(hz - half_win_h - CLEARANCE));
let top_half_h = (hz - (win_cz + half_win_h)) / 2.0;
spawn_segment(
Vec3::new(0.0, 0.0, win_cz + half_win_h + top_half_h),
Vec3::new(hx, half_extents.y, top_half_h),
"_top",
);
let bottom_half_h = (win_cz - half_win_h + hz) / 2.0;
spawn_segment(
Vec3::new(0.0, 0.0, win_cz - half_win_h - bottom_half_h),
Vec3::new(hx, half_extents.y, bottom_half_h),
"_bottom",
);
let left_half_w = (win_cx - half_win_w + hx) / 2.0;
spawn_segment(
Vec3::new(-hx + left_half_w, 0.0, win_cz),
Vec3::new(left_half_w, half_extents.y, half_win_h),
"_left",
);
let right_half_w = (hx - (win_cx + half_win_w)) / 2.0;
spawn_segment(
Vec3::new(hx - right_half_w, 0.0, win_cz),
Vec3::new(right_half_w, half_extents.y, half_win_h),
"_right",
);
}
// TODO: support bailing on room spawn if required room features are too large (e.g. no door)
fn spawn_room(
commands: &mut ChildSpawnerCommands,
room_scale: &Vec3,
room_settings: &ZeroverseSemanticRoomSettings,
) {
let mut rng = rand::thread_rng();
{// outer walls
let hx = room_scale.x / 2.0;
let hy = room_scale.y;
let hz = room_scale.z / 2.0;
let faces = [
(Vec3::new(0.0, hy, 0.0), Quat::IDENTITY, Vec3::new(hx, 1.0, hz), Some(Face::Front), true, SemanticLabel::Ceiling, "top", false),
(Vec3::new(0.0, 0.0, 0.0), Quat::IDENTITY, Vec3::new(hx, 1.0, hz), Some(Face::Back), false, SemanticLabel::Floor, "bottom", false),
(Vec3::new(0.0, hy / 2.0, hz), Quat::from_rotation_x(90_f32.to_radians()), Vec3::new(hx, 1.0, hy / 2.0), Some(Face::Front), true, SemanticLabel::Wall, "front", true),
(Vec3::new(0.0, hy / 2.0, -hz),Quat::from_rotation_x(90_f32.to_radians()), Vec3::new(hx, 1.0, hy / 2.0), Some(Face::Back), false, SemanticLabel::Wall, "back", true),
(Vec3::new(-hx, hy / 2.0, 0.0),Quat::from_rotation_z(90_f32.to_radians()), Vec3::new(hy / 2.0, 1.0, hz), Some(Face::Front), true, SemanticLabel::Wall, "left", true),
(Vec3::new(hx, hy / 2.0, 0.0), Quat::from_rotation_z(90_f32.to_radians()), Vec3::new(hy / 2.0, 1.0, hz), Some(Face::Back), false, SemanticLabel::Wall, "right", true),
];
faces.iter().for_each(|(
origin,
basis,
half,
cull,
invert,
label,
name,
wall,
)| {
// TODO: if spawning adjacent room, use the same wall
spawn_face(
commands,
room_settings,
*origin,
*basis,
*half,
*cull,
*invert,
label.clone(),
name,
*wall,
);
});
}
let mut aabb_colliders: Vec<(Vec3, Vec3)> = Vec::new();
{ // table
let mut table_scale = room_settings.table_settings.scale_sampler.sample();
let room_half_x = room_scale.x / 2.0;
let room_half_z = room_scale.z / 2.0;
let max_half_table_scale_x = room_half_x - room_settings.table_wall_padding;
let max_half_table_scale_z = room_half_z - room_settings.table_wall_padding;
let max_half_table_scale_x = if max_half_table_scale_x > 0.0 {
max_half_table_scale_x
} else {
0.1
};
let max_half_table_scale_z = if max_half_table_scale_z > 0.0 {
max_half_table_scale_z
} else {
0.1
};
table_scale.x = table_scale.x.min(max_half_table_scale_x * 2.0);
table_scale.z = table_scale.z.min(max_half_table_scale_z * 2.0);
let half_table_scale = table_scale * 0.5;
let height_offset = Vec3::new(
0.0,
table_scale.y / 4.0,
0.0,
);
let center_sampler = PositionSampler::Cube {
extents: Vec3::new(
room_half_x - room_settings.table_wall_padding - half_table_scale.x,
0.00001,
room_half_z - room_settings.table_wall_padding - half_table_scale.z,
),
};
if center_sampler.is_valid() {
let position = center_sampler.sample() + height_offset;
aabb_colliders.push((position, table_scale));