-
Notifications
You must be signed in to change notification settings - Fork 0
Open
Labels
Description
bevy_zeroverse/src/scene/semantic_room.rs
Line 675 in c696609
// TODO: support similar windows across adjacent room faces |
SemanticLabel::Door,
));
}
}
{ // humans
for _ in 0..room_settings.human_count.sample() {
let human_scale = room_settings.human_settings.scale_sampler.sample();
let human_scale = Vec3::new(human_scale.x, human_scale.y, human_scale.x);
let center_sampler = PositionSampler::Cube {
extents: Vec3::new(
room_scale.x / 2.0 - room_settings.human_wall_padding - human_scale.x / 2.0,
0.00001,
room_scale.z / 2.0 - room_settings.human_wall_padding - human_scale.z / 2.0,
),
};
if !center_sampler.is_valid() {
continue;
}
let human_scale_sampler = ScaleSampler::Exact(human_scale);
let height_offset = Vec3::new(
0.0,
0.0,
0.0,
);
let mut position = center_sampler.sample() + height_offset;
let mut max_attempts = 100;
while check_aabb_collision(position, human_scale, &aabb_colliders) && max_attempts > 0 {
position = center_sampler.sample() + height_offset;
max_attempts -= 1;
}
if max_attempts == 0 {
continue;
}
aabb_colliders.push((position, human_scale));
commands.spawn((
ZeroversePrimitiveSettings {
position_sampler: PositionSampler::Exact {
position,
},
scale_sampler: human_scale_sampler.clone(),
..room_settings.human_settings.clone()
},
Transform::from_translation(position),
Name::new("human"),
SemanticLabel::Human,
));
}
}
}
const MAX_SHRINK_ITERS: usize = 8;
const MIN_FRACTION: f32 = 0.20;
const ROOM_GAP: f32 = 0.05;
#[inline]
fn overlaps(a_pos: Vec3, a_scale: Vec3, b_pos: Vec3, b_scale: Vec3) -> bool {
let dx = (a_pos.x - b_pos.x).abs();
let dz = (a_pos.z - b_pos.z).abs();
dx + ROOM_GAP < (a_scale.x + b_scale.x) * 0.5 &&
dz + ROOM_GAP < (a_scale.z + b_scale.z) * 0.5
}
#[allow(clippy::too_many_arguments)]
fn spawn_room_rec(
commands: &mut ChildSpawnerCommands,
coord: (i32, i32),
parent_coord: (i32, i32),
dir: (i32, i32),
depth_left: i32,
base_scale: Vec3,
rooms: &mut HashMap<(i32, i32), (Vec3, Vec3)>,
settings: &ZeroverseSemanticRoomSettings,
) {
let mut my_scale = settings.room_size.sample();
my_scale.y = base_scale.y;
let update_pos = |scale: Vec3| {
let (parent_pos, parent_scale) = rooms[&parent_coord];
let mut p = parent_pos;
if dir.0 != 0 {
p.x += dir.0 as f32 * ((parent_scale.x + scale.x) * 0.5 + ROOM_GAP);
}
if dir.1 != 0 {
p.z += dir.1 as f32 * ((parent_scale.z + scale.z) * 0.5 + ROOM_GAP);
}
p
};
let mut my_pos = update_pos(my_scale);
// TODO: fix overlaps (at depth >2, rooms overlap more frequently)
for _ in 0..MAX_SHRINK_ITERS {
let mut shrink_x: f32 = 0.0;
let mut shrink_z: f32 = 0.0;
for &(other_pos, other_scale) in rooms.values() {
if overlaps(my_pos, my_scale, other_pos, other_scale) {
let dx = (my_pos.x - other_pos.x).abs();
let dz = (my_pos.z - other_pos.z).abs();
shrink_x = shrink_x.max((my_scale.x + other_scale.x) * 0.5 - dx + ROOM_GAP);
shrink_z = shrink_z.max((my_scale.z + other_scale.z) * 0.5 - dz + ROOM_GAP);
}
}
if shrink_x == 0.0 && shrink_z == 0.0 {
break;
}
if shrink_x > 0.0 {
my_scale.x = (my_scale.x - shrink_x).max(base_scale.x * MIN_FRACTION);
}
if shrink_z > 0.0 {
my_scale.z = (my_scale.z - shrink_z).max(base_scale.z * MIN_FRACTION);
}
my_pos = update_pos(my_scale);
}
rooms.insert(coord, (my_pos, my_scale));
commands
.spawn((
Name::new(format!("room_{}_{}", coord.0, coord.1)),
Transform::from_translation(my_pos),
InheritedVisibility::default(),
Visibility::default(),
))
.with_children(|c| spawn_room(c, &my_scale, settings));
if depth_left > 0 {
for &(sx, sz) in &[(1, 0), (-1, 0), (0, 1), (0, -1)] {
let next = (coord.0 + sx, coord.1 + sz);
if !rooms.contains_key(&next) {
spawn_room_rec(
commands,
next,
coord,
(sx, sz),
depth_left - 1,
base_scale,
rooms,
settings,
);
}
}
}
}
// TODO: support similar windows across adjacent room faces
fn spawn_room_neighborhood(
commands: &mut ChildSpawnerCommands,
base_scale: &Vec3,
settings: &ZeroverseSemanticRoomSettings,
) {
commands
.spawn((
InheritedVisibility::default(),
Name::new("room"),
SceneAabbNode,
Transform::default(),
Visibility::default(),
))
.with_children(|commands| {
spawn_room(commands, base_scale, settings);
});
let mut rooms: HashMap<(i32, i32), (Vec3, Vec3)> = HashMap::new();
rooms.insert((0, 0), (Vec3::ZERO, *base_scale));
for &(dx, dz) in &[(1, 0), (-1, 0), (0, 1), (0, -1)] {
spawn_room_rec(
commands,
(dx, dz),
(0, 0),
(dx, dz),
settings.neighborhood_depth as i32 - 1,
*base_scale,
&mut rooms,
settings,
);
}
}
fn setup_scene(
mut commands: Commands,
mut load_event: EventWriter<SceneLoadedEvent>,
room_settings: Res<ZeroverseSemanticRoomSettings>,
scene_settings: Res<ZeroverseSceneSettings>,
) {
let room_scale = room_settings.room_size.sample();
// TODO: set global Y rotation to prevent wall aligned plucker embeddings
commands.spawn((
Name::new("rooms"),
RotationAugment,
ZeroverseSceneRoot,
ZeroverseScene,
))
.with_children(|commands| {
spawn_room_neighborhood(
commands,
&room_scale,
&room_settings,
);
{ // cameras
let size: Vec3 = Vec3::new(