mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Significantly improved house variation
This commit is contained in:
parent
c1945a1445
commit
a5ccfe3bc9
@ -7,6 +7,7 @@ use common::{
|
||||
use crate::util::{RandomField, Sampler};
|
||||
use super::{
|
||||
Archetype,
|
||||
BlockMask,
|
||||
super::skeleton::*,
|
||||
};
|
||||
|
||||
@ -17,16 +18,45 @@ pub struct House {
|
||||
roof_ribbing: bool,
|
||||
}
|
||||
|
||||
enum RoofStyle {
|
||||
Hip,
|
||||
Gable,
|
||||
Rounded,
|
||||
}
|
||||
|
||||
enum StoreyFill {
|
||||
None,
|
||||
Upper,
|
||||
All,
|
||||
}
|
||||
|
||||
impl StoreyFill {
|
||||
fn has_lower(&self) -> bool { !if let StoreyFill::None = self { true } else { false } }
|
||||
fn has_upper(&self) -> bool { if let StoreyFill::None = self { false } else { true } }
|
||||
}
|
||||
|
||||
pub struct Attr {
|
||||
central_supports: bool,
|
||||
lower_walls: bool,
|
||||
storey_fill: StoreyFill,
|
||||
roof_style: RoofStyle,
|
||||
mansard: i32,
|
||||
}
|
||||
|
||||
impl Attr {
|
||||
fn generate<R: Rng>(rng: &mut R) -> Self {
|
||||
Self {
|
||||
central_supports: rng.gen(),
|
||||
lower_walls: rng.gen(),
|
||||
storey_fill: match rng.gen_range(0, 2) {
|
||||
//0 => StoreyFill::None,
|
||||
0 => StoreyFill::Upper,
|
||||
_ => StoreyFill::All,
|
||||
},
|
||||
roof_style: match rng.gen_range(0, 3) {
|
||||
0 => RoofStyle::Hip,
|
||||
1 => RoofStyle::Gable,
|
||||
_ => RoofStyle::Rounded,
|
||||
},
|
||||
mansard: rng.gen_range(-8, 6).max(0),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -35,38 +65,31 @@ impl Archetype for House {
|
||||
type Attr = Attr;
|
||||
|
||||
fn generate<R: Rng>(rng: &mut R) -> (Self, Skeleton<Self::Attr>) {
|
||||
let this = Self {
|
||||
roof_color: Rgb::new(
|
||||
rng.gen_range(50, 200),
|
||||
rng.gen_range(50, 200),
|
||||
rng.gen_range(50, 200),
|
||||
),
|
||||
noise: RandomField::new(rng.gen()),
|
||||
chimney: if rng.gen() { Some(rng.gen_range(1, 6)) } else { None },
|
||||
roof_ribbing: rng.gen(),
|
||||
};
|
||||
|
||||
let len = rng.gen_range(-8, 20).clamped(0, 16);
|
||||
let branches_per_side = 1 + len as usize / 16;
|
||||
let len = rng.gen_range(-8, 24).clamped(0, 20);
|
||||
let locus = 6 + rng.gen_range(0, 5);
|
||||
let branches_per_side = 1 + len as usize / 20;
|
||||
let skel = Skeleton {
|
||||
offset: -rng.gen_range(0, len + 7).clamped(0, len),
|
||||
ori: if rng.gen() { Ori::East } else { Ori::North },
|
||||
root: Branch {
|
||||
len,
|
||||
attr: Attr {
|
||||
central_supports: rng.gen(),
|
||||
lower_walls: true,
|
||||
storey_fill: StoreyFill::All,
|
||||
mansard: 0,
|
||||
..Attr::generate(rng)
|
||||
},
|
||||
locus: 8 + rng.gen_range(0, 5),
|
||||
locus,
|
||||
border: 4,
|
||||
children: [1, -1]
|
||||
.iter()
|
||||
.map(|flip| (0..branches_per_side).map(move |i| (i, *flip)))
|
||||
.flatten()
|
||||
.filter_map(move |(i, flip)| if rng.gen() {
|
||||
.filter_map(|(i, flip)| if rng.gen() {
|
||||
Some((i as i32 * len / (branches_per_side - 1).max(1) as i32, Branch {
|
||||
len: rng.gen_range(0, 12) * flip,
|
||||
len: rng.gen_range(5, 16) * flip,
|
||||
attr: Attr::generate(rng),
|
||||
locus: 8 + rng.gen_range(0, 3),
|
||||
locus: (6 + rng.gen_range(0, 3)).min(locus),
|
||||
border: 4,
|
||||
children: Vec::new(),
|
||||
}))
|
||||
} else {
|
||||
@ -76,6 +99,17 @@ impl Archetype for House {
|
||||
},
|
||||
};
|
||||
|
||||
let this = Self {
|
||||
roof_color: Rgb::new(
|
||||
rng.gen_range(50, 200),
|
||||
rng.gen_range(50, 200),
|
||||
rng.gen_range(50, 200),
|
||||
),
|
||||
noise: RandomField::new(rng.gen()),
|
||||
chimney: if rng.gen() { Some(8 + skel.root.locus + rng.gen_range(1, 5)) } else { None },
|
||||
roof_ribbing: rng.gen(),
|
||||
};
|
||||
|
||||
(this, skel)
|
||||
}
|
||||
|
||||
@ -86,44 +120,45 @@ impl Archetype for House {
|
||||
center_offset: Vec2<i32>,
|
||||
z: i32,
|
||||
branch: &Branch<Self::Attr>,
|
||||
) -> Option<Option<Block>> {
|
||||
) -> BlockMask {
|
||||
let profile = Vec2::new(bound_offset.x, z);
|
||||
|
||||
let make_block = |r, g, b| {
|
||||
let nz = self.noise.get(Vec3::new(center_offset.x, center_offset.y, z * 8));
|
||||
Some(Some(Block::new(BlockKind::Normal, Rgb::new(r, g, b) + (nz & 0x0F) as u8 - 8)))
|
||||
BlockMask::new(Block::new(BlockKind::Normal, Rgb::new(r, g, b) + (nz & 0x0F) as u8 - 8), 2)
|
||||
};
|
||||
|
||||
let foundation = make_block(100, 100, 100);
|
||||
let log = make_block(60, 45, 30);
|
||||
let floor = make_block(100, 75, 50);
|
||||
let floor = make_block(100, 75, 50).with_priority(3);
|
||||
let wall = make_block(200, 180, 150);
|
||||
let roof = make_block(self.roof_color.r, self.roof_color.g, self.roof_color.b);
|
||||
let empty = Some(Some(Block::empty()));
|
||||
let fire = Some(Some(Block::new(BlockKind::Ember, Rgb::white())));
|
||||
let empty = BlockMask::nothing();
|
||||
let internal = BlockMask::new(Block::empty(), 4);
|
||||
let fire = BlockMask::new(Block::new(BlockKind::Ember, Rgb::white()), 2);
|
||||
|
||||
let ceil_height = 6;
|
||||
let lower_width = -3 + branch.locus;
|
||||
let upper_width = -2 + branch.locus;
|
||||
let lower_width = branch.locus - 1;
|
||||
let upper_width = branch.locus;
|
||||
let width = if profile.y >= ceil_height { upper_width } else { lower_width };
|
||||
let foundation_height = 0 - (dist - width - 1).max(0);
|
||||
let roof_height = 8 + width;
|
||||
let roof_top = 8 + width;
|
||||
|
||||
if let Some(chimney_height) = self.chimney {
|
||||
if let Some(chimney_top) = self.chimney {
|
||||
// Chimney shaft
|
||||
if center_offset.map(|e| e.abs()).reduce_max() == 0 && profile.y >= foundation_height + 1 {
|
||||
return if profile.y == foundation_height + 1 {
|
||||
fire
|
||||
} else {
|
||||
empty
|
||||
internal
|
||||
};
|
||||
}
|
||||
|
||||
// Chimney
|
||||
if center_offset.map(|e| e.abs()).reduce_max() <= 1 && profile.y < roof_height + chimney_height {
|
||||
if center_offset.map(|e| e.abs()).reduce_max() <= 1 && profile.y < chimney_top {
|
||||
// Fireplace
|
||||
if center_offset.product() == 0 && profile.y > foundation_height + 1 && profile.y <= foundation_height + 3 {
|
||||
return empty;
|
||||
return internal;
|
||||
} else {
|
||||
return foundation;
|
||||
}
|
||||
@ -131,7 +166,7 @@ impl Archetype for House {
|
||||
}
|
||||
|
||||
if profile.y <= foundation_height && dist < width + 3 { // Foundations
|
||||
if branch.attr.lower_walls {
|
||||
if branch.attr.storey_fill.has_lower() {
|
||||
if dist == width - 1 { // Floor lining
|
||||
return log;
|
||||
} else if dist < width - 1 && profile.y == foundation_height { // Floor
|
||||
@ -140,88 +175,103 @@ impl Archetype for House {
|
||||
}
|
||||
|
||||
if dist < width && profile.y < foundation_height && profile.y >= foundation_height - 3 { // Basement
|
||||
return empty;
|
||||
return internal;
|
||||
} else {
|
||||
return foundation;
|
||||
return foundation.with_priority(1);
|
||||
}
|
||||
}
|
||||
|
||||
let do_roof = |profile: Vec2<i32>, dist, roof_height, roof_width| {
|
||||
if profile.y > roof_height - profile.x { // Air above roof
|
||||
return Some(Some(None));
|
||||
let do_roof = |profile: Vec2<i32>, dist, roof_top, roof_width, mansard| {
|
||||
if profile.y > roof_top - profile.x.max(mansard) && profile.y >= roof_top - roof_width { // Air above roof
|
||||
return Some(empty);
|
||||
}
|
||||
|
||||
// Roof
|
||||
if profile.y == roof_height - profile.x
|
||||
if profile.y == roof_top - profile.x.max(mansard)
|
||||
&& dist <= roof_width
|
||||
{
|
||||
let is_ribbing = (roof_height - profile.y) % 3 == 0 && self.roof_ribbing;
|
||||
if profile.x == 0 || dist == roof_width|| is_ribbing { // Eaves
|
||||
return Some(log);
|
||||
let is_ribbing = (profile.y - ceil_height) % 3 == 0 && self.roof_ribbing;
|
||||
if (profile.x == 0 && mansard == 0) || dist == roof_width|| is_ribbing { // Eaves
|
||||
return Some(log.with_priority(1));
|
||||
} else {
|
||||
return Some(roof);
|
||||
return Some(roof.with_priority(1));
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
};
|
||||
|
||||
if let Some(block) = do_roof(profile, dist, roof_height, width + 2) {
|
||||
if let Some(block) = match &branch.attr.roof_style {
|
||||
RoofStyle::Hip => do_roof(Vec2::new(dist, profile.y), dist, roof_top, width + 2, branch.attr.mansard),
|
||||
RoofStyle::Gable => do_roof(profile, dist, roof_top, width + 2, branch.attr.mansard),
|
||||
RoofStyle::Rounded => {
|
||||
let circular_dist = (bound_offset.map(|e| e.pow(4) as f32).sum().powf(0.25) + 0.5).ceil() as i32;
|
||||
do_roof(Vec2::new(circular_dist, profile.y), circular_dist, roof_top, width + 2, branch.attr.mansard)
|
||||
},
|
||||
} {
|
||||
return block;
|
||||
}
|
||||
|
||||
// Walls
|
||||
if dist == width && (
|
||||
bound_offset.x == bound_offset.y ||
|
||||
(profile.x == 0 && branch.attr.central_supports) ||
|
||||
profile.y == ceil_height
|
||||
) { // Support beams
|
||||
return log;
|
||||
} else if !branch.attr.lower_walls && profile.y < ceil_height {
|
||||
return None;
|
||||
} else if dist == width {
|
||||
let frame_bounds = if profile.y >= ceil_height {
|
||||
Aabr {
|
||||
min: Vec2::new(-1, ceil_height + 2),
|
||||
max: Vec2::new(1, ceil_height + 5),
|
||||
}
|
||||
if dist == width {
|
||||
if bound_offset.x == bound_offset.y || profile.y == ceil_height { // Support beams
|
||||
return log;
|
||||
} else if !branch.attr.storey_fill.has_lower() && profile.y < ceil_height {
|
||||
return empty;
|
||||
} else if !branch.attr.storey_fill.has_upper() {
|
||||
return empty;
|
||||
} else {
|
||||
Aabr {
|
||||
min: Vec2::new(2, foundation_height + 2),
|
||||
max: Vec2::new(width - 2, ceil_height - 2),
|
||||
}
|
||||
};
|
||||
let window_bounds = Aabr {
|
||||
min: (frame_bounds.min + 1).map2(frame_bounds.center(), |a, b| a.min(b)),
|
||||
max: (frame_bounds.max - 1).map2(frame_bounds.center(), |a, b| a.max(b)),
|
||||
};
|
||||
let frame_bounds = if profile.y >= ceil_height {
|
||||
Aabr {
|
||||
min: Vec2::new(-1, ceil_height + 2),
|
||||
max: Vec2::new(1, ceil_height + 5),
|
||||
}
|
||||
} else {
|
||||
Aabr {
|
||||
min: Vec2::new(2, foundation_height + 2),
|
||||
max: Vec2::new(width - 2, ceil_height - 2),
|
||||
}
|
||||
};
|
||||
let window_bounds = Aabr {
|
||||
min: (frame_bounds.min + 1).map2(frame_bounds.center(), |a, b| a.min(b)),
|
||||
max: (frame_bounds.max - 1).map2(frame_bounds.center(), |a, b| a.max(b)),
|
||||
};
|
||||
|
||||
// Window
|
||||
if (frame_bounds.size() + 1).reduce_min() > 2 { // Window frame is large enough for a window
|
||||
let surface_pos = Vec2::new(bound_offset.x, profile.y);
|
||||
if window_bounds.contains_point(surface_pos) {
|
||||
return empty;
|
||||
} else if frame_bounds.contains_point(surface_pos) {
|
||||
return log;
|
||||
// Window
|
||||
if (frame_bounds.size() + 1).reduce_min() > 2 { // Window frame is large enough for a window
|
||||
let surface_pos = Vec2::new(bound_offset.x, profile.y);
|
||||
if window_bounds.contains_point(surface_pos) {
|
||||
return internal;
|
||||
} else if frame_bounds.contains_point(surface_pos) {
|
||||
return log.with_priority(3);
|
||||
};
|
||||
}
|
||||
|
||||
// Wall
|
||||
return if branch.attr.central_supports && profile.x == 0 { // Support beams
|
||||
log.with_priority(4)
|
||||
} else {
|
||||
wall
|
||||
};
|
||||
}
|
||||
|
||||
// Wall
|
||||
return wall;
|
||||
}
|
||||
|
||||
if dist < width { // Internals
|
||||
return if profile.y == ceil_height {
|
||||
if profile.y == ceil_height {
|
||||
if profile.x == 0 {// Rafters
|
||||
log
|
||||
} else { // Ceiling
|
||||
floor
|
||||
return log;
|
||||
} else if branch.attr.storey_fill.has_upper() { // Ceiling
|
||||
return floor;
|
||||
}
|
||||
} else if (!branch.attr.storey_fill.has_lower() && profile.y < ceil_height)
|
||||
|| (!branch.attr.storey_fill.has_upper() && profile.y >= ceil_height)
|
||||
{
|
||||
return empty;
|
||||
} else {
|
||||
empty
|
||||
};
|
||||
return internal;
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
empty
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ use common::{
|
||||
};
|
||||
use super::{
|
||||
Archetype,
|
||||
BlockMask,
|
||||
super::skeleton::*,
|
||||
};
|
||||
|
||||
@ -22,12 +23,14 @@ impl Archetype for Keep {
|
||||
root: Branch {
|
||||
len,
|
||||
attr: Self::Attr::default(),
|
||||
locus: 8 + rng.gen_range(0, 5),
|
||||
locus: 5 + rng.gen_range(0, 5),
|
||||
border: 3,
|
||||
children: (0..rng.gen_range(0, 4))
|
||||
.map(|_| (rng.gen_range(-5, len + 5).clamped(0, len.max(1) - 1), Branch {
|
||||
len: rng.gen_range(5, 12) * if rng.gen() { 1 } else { -1 },
|
||||
attr: Self::Attr::default(),
|
||||
locus: 8 + rng.gen_range(0, 3),
|
||||
locus: 5 + rng.gen_range(0, 3),
|
||||
border: 3,
|
||||
children: Vec::new(),
|
||||
}))
|
||||
.collect(),
|
||||
@ -44,20 +47,20 @@ impl Archetype for Keep {
|
||||
center_offset: Vec2<i32>,
|
||||
z: i32,
|
||||
branch: &Branch<Self::Attr>,
|
||||
) -> Option<Option<Block>> {
|
||||
) -> BlockMask {
|
||||
let profile = Vec2::new(bound_offset.x, z);
|
||||
|
||||
let make_block = |r, g, b| {
|
||||
Some(Some(Block::new(BlockKind::Normal, Rgb::new(r, g, b))))
|
||||
BlockMask::new(Block::new(BlockKind::Normal, Rgb::new(r, g, b)), 2)
|
||||
};
|
||||
|
||||
let foundation = make_block(100, 100, 100);
|
||||
let log = make_block(60, 45, 30);
|
||||
let wall = make_block(75, 100, 125);
|
||||
let roof = make_block(150, 120, 50);
|
||||
let empty = Some(Some(Block::empty()));
|
||||
let empty = BlockMask::new(Block::empty(), 2);
|
||||
|
||||
let width = 3 + branch.locus;
|
||||
let width = branch.locus;
|
||||
let rampart_width = 5 + branch.locus;
|
||||
let roof_height = 12 + width;
|
||||
let ceil_height = 16;
|
||||
|
@ -3,9 +3,55 @@ pub mod keep;
|
||||
|
||||
use vek::*;
|
||||
use rand::prelude::*;
|
||||
use common::terrain::Block;
|
||||
use common::{terrain::Block, vol::Vox};
|
||||
use super::skeleton::*;
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct BlockMask {
|
||||
block: Block,
|
||||
priority: i32,
|
||||
}
|
||||
|
||||
impl BlockMask {
|
||||
pub fn new(block: Block, priority: i32) -> Self {
|
||||
Self { block, priority }
|
||||
}
|
||||
|
||||
pub fn nothing() -> Self {
|
||||
Self {
|
||||
block: Block::empty(),
|
||||
priority: 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_priority(mut self, priority: i32) -> Self {
|
||||
self.priority = priority;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn resolve_with(self, dist_self: i32, other: Self, dist_other: i32) -> Self {
|
||||
if self.priority == other.priority {
|
||||
if dist_self <= dist_other {
|
||||
self
|
||||
} else {
|
||||
other
|
||||
}
|
||||
} else if self.priority >= other.priority {
|
||||
self
|
||||
} else {
|
||||
other
|
||||
}
|
||||
}
|
||||
|
||||
pub fn finish(self) -> Option<Block> {
|
||||
if self.priority > 0 {
|
||||
Some(self.block)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Archetype {
|
||||
type Attr;
|
||||
|
||||
@ -17,5 +63,5 @@ pub trait Archetype {
|
||||
center_offset: Vec2<i32>,
|
||||
z: i32,
|
||||
branch: &Branch<Self::Attr>,
|
||||
) -> Option<Option<Block>>;
|
||||
) -> BlockMask;
|
||||
}
|
||||
|
@ -48,8 +48,8 @@ impl<A: Archetype> Building<A> {
|
||||
|
||||
pub fn sample(&self, pos: Vec3<i32>) -> Option<Block> {
|
||||
let rpos = pos - self.origin;
|
||||
self.skel.closest(rpos.into(), |dist, bound_offset, center_offset, branch| {
|
||||
self.skel.sample_closest(rpos.into(), |dist, bound_offset, center_offset, branch| {
|
||||
self.archetype.draw(dist, bound_offset, center_offset, rpos.z, branch)
|
||||
}).flatten()
|
||||
}).finish()
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
use vek::*;
|
||||
use super::archetype::BlockMask;
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||
pub enum Ori {
|
||||
@ -26,14 +27,15 @@ pub struct Branch<T> {
|
||||
pub len: i32,
|
||||
pub attr: T,
|
||||
pub locus: i32,
|
||||
pub border: i32,
|
||||
pub children: Vec<(i32, Branch<T>)>,
|
||||
}
|
||||
|
||||
impl<T> Branch<T> {
|
||||
fn for_each<'a>(&'a self, node: Vec2<i32>, ori: Ori, f: &mut impl FnMut(Vec2<i32>, Ori, &'a Branch<T>)) {
|
||||
f(node, ori, self);
|
||||
fn for_each<'a>(&'a self, node: Vec2<i32>, ori: Ori, is_child: bool, parent_locus: i32, f: &mut impl FnMut(Vec2<i32>, Ori, &'a Branch<T>, bool, i32)) {
|
||||
f(node, ori, self, is_child, parent_locus);
|
||||
for (offset, child) in &self.children {
|
||||
child.for_each(node + ori.dir() * *offset, ori.flip(), f);
|
||||
child.for_each(node + ori.dir() * *offset, ori.flip(), true, self.locus, f);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -45,27 +47,28 @@ pub struct Skeleton<T> {
|
||||
}
|
||||
|
||||
impl<T> Skeleton<T> {
|
||||
pub fn for_each<'a>(&'a self, mut f: impl FnMut(Vec2<i32>, Ori, &'a Branch<T>)) {
|
||||
self.root.for_each(self.ori.dir() * self.offset, self.ori, &mut f);
|
||||
pub fn for_each<'a>(&'a self, mut f: impl FnMut(Vec2<i32>, Ori, &'a Branch<T>, bool, i32)) {
|
||||
self.root.for_each(self.ori.dir() * self.offset, self.ori, false, 0, &mut f);
|
||||
}
|
||||
|
||||
pub fn bounds(&self) -> Aabr<i32> {
|
||||
let mut bounds = Aabr::new_empty(self.ori.dir() * self.offset);
|
||||
self.for_each(|node, ori, branch| {
|
||||
self.for_each(|node, ori, branch, _, _| {
|
||||
let node2 = node + ori.dir() * branch.len;
|
||||
|
||||
let a = node.map2(node2, |a, b| a.min(b)) - branch.locus;
|
||||
let b = node.map2(node2, |a, b| a.max(b)) + branch.locus;
|
||||
let a = node.map2(node2, |a, b| a.min(b)) - (branch.locus + branch.border);
|
||||
let b = node.map2(node2, |a, b| a.max(b)) + (branch.locus + branch.border);
|
||||
bounds.expand_to_contain_point(a);
|
||||
bounds.expand_to_contain_point(b);
|
||||
});
|
||||
bounds
|
||||
}
|
||||
|
||||
pub fn closest<R: Clone>(&self, pos: Vec2<i32>, mut f: impl FnMut(i32, Vec2<i32>, Vec2<i32>, &Branch<T>) -> Option<R>) -> Option<R> {
|
||||
let mut min = None;
|
||||
self.for_each(|node, ori, branch| {
|
||||
pub fn sample_closest(&self, pos: Vec2<i32>, mut f: impl FnMut(i32, Vec2<i32>, Vec2<i32>, &Branch<T>) -> BlockMask) -> BlockMask {
|
||||
let mut min = None::<(_, BlockMask)>;
|
||||
self.for_each(|node, ori, branch, is_child, parent_locus| {
|
||||
let node2 = node + ori.dir() * branch.len;
|
||||
let node = node + if is_child { ori.dir() * branch.len.signum() * (branch.locus - parent_locus).clamped(0, branch.len.abs()) } else { Vec2::zero() };
|
||||
let bounds = Aabr::new_empty(node)
|
||||
.expanded_to_contain_point(node2);
|
||||
let bound_offset = if ori == Ori::East {
|
||||
@ -86,10 +89,16 @@ impl<T> Skeleton<T> {
|
||||
};
|
||||
let dist = bound_offset.reduce_max();
|
||||
let dist_locus = dist - branch.locus;
|
||||
if min.as_ref().map(|(min_dist_locus, _)| dist_locus < *min_dist_locus).unwrap_or(true) {
|
||||
min = f(dist, bound_offset, center_offset, branch).map(|r| (dist_locus, r)).or(min.clone());
|
||||
if !is_child || match ori {
|
||||
Ori::East => (pos.x - node.x) * branch.len.signum() >= 0,
|
||||
Ori::North => (pos.y - node.y) * branch.len.signum() >= 0,
|
||||
} || true {
|
||||
let new_bm = f(dist, bound_offset, center_offset, branch);
|
||||
min = min
|
||||
.map(|(min_dist_locus, bm)| (dist_locus, bm.resolve_with(min_dist_locus, new_bm, dist_locus)))
|
||||
.or(Some((dist_locus, new_bm)));
|
||||
}
|
||||
});
|
||||
min.map(|(_, r)| r)
|
||||
min.map(|(_, bm)| bm).unwrap_or(BlockMask::nothing())
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user