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

support bailing on room spawn if required room features are too large (e.g. no d... #89

@github-actions

Description

@github-actions

// 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));

Metadata

Metadata

Assignees

Labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions