这是indexloc提供的服务,不要输入任何密码
Skip to content

support similar windows across adjacent room faces #92

@github-actions

Description

@github-actions

// 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(

Metadata

Metadata

Assignees

Labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions