mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
better flat
This commit is contained in:
parent
6d2b39c254
commit
179c6dab8f
@ -189,10 +189,7 @@ impl Civs {
|
|||||||
SiteKind::GiantTree => (12i32, 8.0),
|
SiteKind::GiantTree => (12i32, 8.0),
|
||||||
SiteKind::Gnarling => (16i32, 10.0),
|
SiteKind::Gnarling => (16i32, 10.0),
|
||||||
SiteKind::Citadel => (16i32, 0.0),
|
SiteKind::Citadel => (16i32, 0.0),
|
||||||
SiteKind::Bridge(start, end) => {
|
SiteKind::Bridge(_, _) => (0, 0.0),
|
||||||
let e = (end - start).map(|e| e.abs()).reduce_max();
|
|
||||||
((e + 1) / 2, ((e + 1) / 2) as f32 / 2.0)
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let (raise, raise_dist, make_waypoint): (f32, i32, bool) = match &site.kind {
|
let (raise, raise_dist, make_waypoint): (f32, i32, bool) = match &site.kind {
|
||||||
@ -1264,9 +1261,9 @@ fn walk_in_dir(
|
|||||||
3.0 // + (1.0 - b_chunk.tree_density) * 20.0 // Prefer going through forests, for aesthetics
|
3.0 // + (1.0 - b_chunk.tree_density) * 20.0 // Prefer going through forests, for aesthetics
|
||||||
};
|
};
|
||||||
Some((a + dir, 1.0 + hill_cost + water_cost + wild_cost))
|
Some((a + dir, 1.0 + hill_cost + water_cost + wild_cost))
|
||||||
} else if dir.x == 0 || dir.y == 0 {
|
} else if NEIGHBORS.iter().all(|p| get_bridge(a + p).is_none()) && (dir.x == 0 || dir.y == 0) {
|
||||||
(4..=5).find_map(|i| {
|
(4..=5).find_map(|i| {
|
||||||
loc_suitable_for_walking(sim, a + dir * i).then(|| (a + dir * i, i as f32 * 30.0))
|
loc_suitable_for_walking(sim, a + dir * i).then(|| (a + dir * i, 400.0 + (i - 4) as f32 * 10.0))
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
@ -1276,13 +1273,10 @@ fn walk_in_dir(
|
|||||||
/// Return true if a position is suitable for walking on
|
/// Return true if a position is suitable for walking on
|
||||||
fn loc_suitable_for_walking(sim: &WorldSim, loc: Vec2<i32>) -> bool {
|
fn loc_suitable_for_walking(sim: &WorldSim, loc: Vec2<i32>) -> bool {
|
||||||
if sim.get(loc).is_some() {
|
if sim.get(loc).is_some() {
|
||||||
NEIGHBORS
|
!NEIGHBORS.iter().any(|n| {
|
||||||
.iter()
|
sim.get(loc + *n)
|
||||||
.find(|n| {
|
.map_or(false, |chunk| chunk.river.near_water())
|
||||||
sim.get(loc + *n)
|
})
|
||||||
.map_or(false, |chunk| chunk.river.near_water())
|
|
||||||
})
|
|
||||||
.is_none()
|
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
@ -1626,7 +1620,7 @@ impl Site {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_castle(&self) -> bool { matches!(self.kind, SiteKind::Castle) }
|
pub fn is_castle(&self) -> bool { matches!(self.kind, SiteKind::Castle) }
|
||||||
|
|
||||||
pub fn is_bridge(&self) -> bool { matches!(self.kind, SiteKind::Bridge(_, _)) }
|
pub fn is_bridge(&self) -> bool { matches!(self.kind, SiteKind::Bridge(_, _)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
column::ColumnSample,
|
column::ColumnSample,
|
||||||
sim::{RiverKind, WorldSim},
|
sim::{RiverKind, WorldSim},
|
||||||
CONFIG, IndexRef, site::SiteKind,
|
site::SiteKind,
|
||||||
|
IndexRef, CONFIG,
|
||||||
};
|
};
|
||||||
use common::{
|
use common::{
|
||||||
terrain::{
|
terrain::{
|
||||||
@ -118,17 +119,21 @@ pub fn sample_pos(
|
|||||||
sample.river.river_kind,
|
sample.river.river_kind,
|
||||||
sample.river.spline_derivative,
|
sample.river.spline_derivative,
|
||||||
sample.path.0.is_way(),
|
sample.path.0.is_way(),
|
||||||
sample.sites.iter().any(|site| match &index.sites.get(*site).kind {
|
sample
|
||||||
SiteKind::Bridge(bridge) => if let Some(plot) = bridge.wpos_tile(TerrainChunkSize::center_wpos(pos)).plot {
|
.sites
|
||||||
match bridge.plot(plot).kind {
|
.iter()
|
||||||
crate::site2::PlotKind::Bridge(_) => true,
|
.any(|site| match &index.sites.get(*site).kind {
|
||||||
_ => false
|
SiteKind::Bridge(bridge) => {
|
||||||
}
|
if let Some(plot) =
|
||||||
} else {
|
bridge.wpos_tile(TerrainChunkSize::center_wpos(pos)).plot
|
||||||
false
|
{
|
||||||
},
|
matches!(bridge.plot(plot).kind, crate::site2::PlotKind::Bridge(_))
|
||||||
_ => false,
|
} else {
|
||||||
}),
|
false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => false,
|
||||||
|
}),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.unwrap_or((
|
.unwrap_or((
|
||||||
|
@ -15,7 +15,7 @@ use common::{
|
|||||||
vol::ReadVol,
|
vol::ReadVol,
|
||||||
};
|
};
|
||||||
use num::cast::AsPrimitive;
|
use num::cast::AsPrimitive;
|
||||||
use std::{cell::RefCell, sync::Arc, ops::RangeBounds};
|
use std::{cell::RefCell, ops::RangeBounds, sync::Arc};
|
||||||
use vek::*;
|
use vek::*;
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
@ -386,8 +386,7 @@ impl Fill {
|
|||||||
Self::contains_at(tree, *prim, pos.map2(*vec, i32::saturating_sub))
|
Self::contains_at(tree, *prim, pos.map2(*vec, i32::saturating_sub))
|
||||||
},
|
},
|
||||||
Primitive::Scale(prim, vec) => {
|
Primitive::Scale(prim, vec) => {
|
||||||
let center =
|
let center = Self::get_bounds(tree, *prim).as_::<f32>().center();
|
||||||
Self::get_bounds(tree, *prim).as_::<f32>().center();
|
|
||||||
let fpos = pos.as_::<f32>();
|
let fpos = pos.as_::<f32>();
|
||||||
let spos = (center + ((fpos - center) / vec))
|
let spos = (center + ((fpos - center) / vec))
|
||||||
.map(|x| x.round())
|
.map(|x| x.round())
|
||||||
@ -779,9 +778,8 @@ impl Painter {
|
|||||||
self.prim(Primitive::Cylinder(aabb.made_valid()))
|
self.prim(Primitive::Cylinder(aabb.made_valid()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns a `PrimitiveRef` of the largest horizontal cylinder that fits in
|
||||||
/// Returns a `PrimitiveRef` of the largest horizontal cylinder that fits in the
|
/// the provided Aabb.
|
||||||
/// provided Aabb.
|
|
||||||
pub fn horizontal_cylinder(&self, aabb: Aabb<i32>, dir: Dir) -> PrimitiveRef {
|
pub fn horizontal_cylinder(&self, aabb: Aabb<i32>, dir: Dir) -> PrimitiveRef {
|
||||||
let aabr = Aabr::from(aabb);
|
let aabr = Aabr::from(aabb);
|
||||||
let length = dir.select(aabr.size());
|
let length = dir.select(aabr.size());
|
||||||
@ -790,7 +788,8 @@ impl Painter {
|
|||||||
min: (aabr.min - dir.abs().to_vec2() * height).with_z(aabb.min.z),
|
min: (aabr.min - dir.abs().to_vec2() * height).with_z(aabb.min.z),
|
||||||
max: (dir.abs().select_with(aabr.min, aabr.max)).with_z(aabb.min.z + length),
|
max: (dir.abs().select_with(aabr.min, aabr.max)).with_z(aabb.min.z + length),
|
||||||
};
|
};
|
||||||
self.cylinder(aabb).rotate_about((-dir.abs()).from_z_mat3(), aabr.min.with_z(aabb.min.z))
|
self.cylinder(aabb)
|
||||||
|
.rotate_about((-dir.abs()).from_z_mat3(), aabr.min.with_z(aabb.min.z))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a `PrimitiveRef` of a cylinder using a radius check where a
|
/// Returns a `PrimitiveRef` of a cylinder using a radius check where a
|
||||||
@ -1072,40 +1071,21 @@ impl Painter {
|
|||||||
/// |_____|/
|
/// |_____|/
|
||||||
/// ```
|
/// ```
|
||||||
pub fn vault(&self, aabb: Aabb<i32>, dir: Dir) -> PrimitiveRef {
|
pub fn vault(&self, aabb: Aabb<i32>, dir: Dir) -> PrimitiveRef {
|
||||||
let aabr = Aabr::from(aabb);
|
let h = dir.orthogonal().select(Vec3::from(aabb.size()).xy());
|
||||||
let a = dir.select_aabr(aabr);
|
|
||||||
let b = (-dir).select_aabr(aabr);
|
|
||||||
let dmin = a.min(b);
|
|
||||||
let dmax = a.max(b);
|
|
||||||
let length = dmax - dmin;
|
|
||||||
|
|
||||||
let c = dir.rotated_cw().select_aabr(aabr);
|
let mut prim = self.horizontal_cylinder(Aabb {
|
||||||
let d = dir.rotated_ccw().select_aabr(aabr);
|
min: aabb.min.with_z(aabb.max.z - h),
|
||||||
let omin = c.min(d);
|
max: aabb.max,
|
||||||
let omax = c.max(d);
|
}, dir);
|
||||||
let diameter = omax - omin;
|
|
||||||
let radius = (diameter + 1) / 2;
|
|
||||||
let min = (a * dir.to_vec2() + c * dir.orthogonal().to_vec2()).with_z(aabb.max.z);
|
|
||||||
|
|
||||||
self.cylinder(
|
if aabb.size().d < h {
|
||||||
Aabb {
|
prim = prim.intersect(self.aabb(aabb));
|
||||||
min,
|
}
|
||||||
max: (a * dir.to_vec2()
|
|
||||||
+ diameter * (-dir).to_vec2()
|
self.aabb(Aabb {
|
||||||
+ d * dir.orthogonal().to_vec2())
|
|
||||||
.with_z(aabb.max.z + length),
|
|
||||||
}
|
|
||||||
.made_valid(),
|
|
||||||
)
|
|
||||||
.rotate_about(dir.abs().from_z_mat3(), min)
|
|
||||||
.without(self.aabb(Aabb {
|
|
||||||
min: aabb.min.with_z(aabb.min.z - radius),
|
|
||||||
max: aabb.max.with_z(aabb.min.z),
|
|
||||||
}))
|
|
||||||
.union(self.aabb(Aabb {
|
|
||||||
min: aabb.min,
|
min: aabb.min,
|
||||||
max: aabb.max.with_z(aabb.max.z - radius),
|
max: aabb.max.with_z(aabb.max.z - h / 2),
|
||||||
}))
|
}).union(prim)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Place aabbs around another aabb in a symmetric and distributed manner.
|
/// Place aabbs around another aabb in a symmetric and distributed manner.
|
||||||
@ -1293,7 +1273,9 @@ impl<'a> PrimitiveTransform for PrimitiveRef<'a> {
|
|||||||
self.painter.prim(Primitive::rotate_about(self, rot, point))
|
self.painter.prim(Primitive::rotate_about(self, rot, point))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn scale(self, scale: Vec3<impl AsPrimitive<f32>>) -> Self { self.painter.prim(Primitive::scale(self, scale.as_())) }
|
fn scale(self, scale: Vec3<impl AsPrimitive<f32>>) -> Self {
|
||||||
|
self.painter.prim(Primitive::scale(self, scale.as_()))
|
||||||
|
}
|
||||||
|
|
||||||
fn repeat(self, offset: Vec3<i32>, count: u32) -> Self {
|
fn repeat(self, offset: Vec3<i32>, count: u32) -> Self {
|
||||||
self.painter.prim(Primitive::repeat(self, offset, count))
|
self.painter.prim(Primitive::repeat(self, offset, count))
|
||||||
|
@ -1018,7 +1018,6 @@ impl Site {
|
|||||||
max: start_tile.map2(end_tile, |a, b| a.max(b)) + 1 + orth * width,
|
max: start_tile.map2(end_tile, |a, b| a.max(b)) + 1 + orth * width,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
let bridge = plot::Bridge::generate(land, index, &mut rng, &site, start_tile, end_tile);
|
let bridge = plot::Bridge::generate(land, index, &mut rng, &site, start_tile, end_tile);
|
||||||
|
|
||||||
let start_tile = site.wpos_tile_pos(bridge.start.xy());
|
let start_tile = site.wpos_tile_pos(bridge.start.xy());
|
||||||
@ -1044,7 +1043,7 @@ impl Site {
|
|||||||
(-bridge.dir).select_aabr_with(start_aabr, aabr.center()),
|
(-bridge.dir).select_aabr_with(start_aabr, aabr.center()),
|
||||||
2,
|
2,
|
||||||
);
|
);
|
||||||
|
|
||||||
let plot = site.create_plot(Plot {
|
let plot = site.create_plot(Plot {
|
||||||
kind: PlotKind::Bridge(bridge),
|
kind: PlotKind::Bridge(bridge),
|
||||||
root_tile: start_tile,
|
root_tile: start_tile,
|
||||||
|
@ -25,16 +25,20 @@ struct HeightenedViaduct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl HeightenedViaduct {
|
impl HeightenedViaduct {
|
||||||
fn random(rng: &mut impl Rng) -> Self {
|
fn random(rng: &mut impl Rng, height: i32) -> Self {
|
||||||
|
let vault_spacing = *[3, 4, 5, 7].choose(rng).unwrap();
|
||||||
Self {
|
Self {
|
||||||
slope_inv: rng.gen_range(6..=8),
|
slope_inv: rng.gen_range(6..=8),
|
||||||
bridge_start_offset: rng.gen_range(5..=12),
|
bridge_start_offset: rng.gen_range({
|
||||||
vault_spacing: rng.gen_range(3..=4),
|
let min = (5 - height / 3).max(0);
|
||||||
|
min..=(12 - height).max(min)
|
||||||
|
}),
|
||||||
|
vault_spacing,
|
||||||
vault_size: *[(3, 16), (1, 4), (1, 4), (1, 4), (5, 32), (5, 32)]
|
vault_size: *[(3, 16), (1, 4), (1, 4), (1, 4), (5, 32), (5, 32)]
|
||||||
.choose(rng)
|
.choose(rng)
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
side_vault_size: *[(4, 5), (7, 10), (7, 10), (13, 20)].choose(rng).unwrap(),
|
side_vault_size: *[(4, 5), (7, 10), (7, 10), (13, 20)].choose(rng).unwrap(),
|
||||||
holes: rng.gen_bool(0.5),
|
holes: vault_spacing > 4 && rng.gen_bool(0.8),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -53,25 +57,32 @@ impl BridgeKind {
|
|||||||
start: Vec3<i32>,
|
start: Vec3<i32>,
|
||||||
center: Vec3<i32>,
|
center: Vec3<i32>,
|
||||||
end: Vec3<i32>,
|
end: Vec3<i32>,
|
||||||
|
|
||||||
|
name: &str,
|
||||||
) -> BridgeKind {
|
) -> BridgeKind {
|
||||||
let len = (start.xy() - end.xy()).map(|e| e.abs()).reduce_max();
|
let len = (start.xy() - end.xy()).map(|e| e.abs()).reduce_max();
|
||||||
|
let height = end.z - start.z;
|
||||||
|
let down = start.z - center.z;
|
||||||
(0..=3)
|
(0..=3)
|
||||||
.filter_map(|bridge| match bridge {
|
.filter_map(|bridge| match bridge {
|
||||||
0 if end.z - start.z > 17 => Some(BridgeKind::Tower(match rng.gen_range(0..=2) {
|
0 if height >= 16 => Some(BridgeKind::Tower(match rng.gen_range(0..=2) {
|
||||||
0 => RoofKind::Crenelated,
|
0 => RoofKind::Crenelated,
|
||||||
_ => RoofKind::Hipped,
|
_ => RoofKind::Hipped,
|
||||||
})),
|
})),
|
||||||
1 if len < 40 => Some(BridgeKind::Short),
|
1 if len < 40 => Some(BridgeKind::Short),
|
||||||
2 if end.z - start.z < 5 && start.z - center.z < 16 => Some(
|
2 if height < 15 && down < 16 => Some(BridgeKind::HeightenedViaduct(
|
||||||
BridgeKind::HeightenedViaduct(HeightenedViaduct::random(rng)),
|
HeightenedViaduct::random(rng, height),
|
||||||
),
|
)),
|
||||||
3 if end.z - start.z < 9 && start.z - center.z > 10 => Some(BridgeKind::HangBridge),
|
3 if height < 9 && down > 10 => Some(BridgeKind::HangBridge),
|
||||||
_ => None,
|
_ => None,
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.choose(rng)
|
.choose(rng)
|
||||||
.unwrap_or(BridgeKind::Flat)
|
.unwrap_or_else(|| {
|
||||||
|
println!("Pick: {name}\n\tlen: {len}\n\theight: {height}\n\tdown: {down}\n");
|
||||||
|
BridgeKind::Flat
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn width(&self) -> i32 {
|
fn width(&self) -> i32 {
|
||||||
@ -190,59 +201,89 @@ fn render_short(bridge: &Bridge, painter: &Painter) {
|
|||||||
|
|
||||||
fn render_flat(bridge: &Bridge, painter: &Painter) {
|
fn render_flat(bridge: &Bridge, painter: &Painter) {
|
||||||
let rock = Fill::Block(Block::new(BlockKind::Rock, Rgb::gray(50)));
|
let rock = Fill::Block(Block::new(BlockKind::Rock, Rgb::gray(50)));
|
||||||
|
let light_rock = Fill::Block(Block::new(BlockKind::Rock, Rgb::gray(130)));
|
||||||
|
|
||||||
let dz = bridge.end.z - bridge.start.z;
|
let orth_dir = bridge.dir.orthogonal();
|
||||||
let orthogonal = bridge.dir.orthogonal().to_vec2();
|
|
||||||
|
let orthogonal = orth_dir.to_vec2();
|
||||||
let forward = bridge.dir.to_vec2();
|
let forward = bridge.dir.to_vec2();
|
||||||
let inset = 5;
|
|
||||||
|
|
||||||
let len = (bridge.end.xy() - bridge.start.xy())
|
let height = bridge.end.z - bridge.start.z;
|
||||||
.map(|e| e.abs())
|
|
||||||
.reduce_max();
|
|
||||||
let upset = bridge.end.z - bridge.start.z;
|
|
||||||
|
|
||||||
let size = tweak!(8);
|
let bridge_width = bridge.width();
|
||||||
let hole = painter
|
let side = orthogonal * bridge_width;
|
||||||
.cylinder(aabb(
|
|
||||||
bridge.center.with_z(bridge.end.z - 3 - bridge.width() * 2) - Vec2::broadcast(size),
|
let aabr = Aabr {
|
||||||
bridge.center.with_z(bridge.end.z + 2) + Vec2::broadcast(size),
|
min: bridge.start.xy() - side,
|
||||||
))
|
max: bridge.end.xy() + side,
|
||||||
.rotate_about(
|
}
|
||||||
bridge.dir.orthogonal().from_z_mat3(),
|
.made_valid();
|
||||||
bridge
|
|
||||||
.center
|
let [ramp_aabr, aabr] = bridge.dir.split_aabr(aabr, height);
|
||||||
.as_()
|
|
||||||
.with_z(bridge.end.z as f32 - 1.5 - bridge.width() as f32),
|
let ramp_prim = |ramp_aabr: Aabr<i32>, offset: i32| {
|
||||||
|
painter
|
||||||
|
.aabb(aabb(
|
||||||
|
ramp_aabr.min.with_z(bridge.start.z - 10 + offset),
|
||||||
|
ramp_aabr.max.with_z(bridge.start.z - 1 + offset),
|
||||||
|
))
|
||||||
|
.union(painter.ramp(
|
||||||
|
aabb(
|
||||||
|
ramp_aabr.min.with_z(bridge.start.z + offset),
|
||||||
|
ramp_aabr.max.with_z(bridge.end.z + offset),
|
||||||
|
),
|
||||||
|
height + 1,
|
||||||
|
bridge.dir,
|
||||||
|
))
|
||||||
|
};
|
||||||
|
|
||||||
|
ramp_prim(ramp_aabr, 1).fill(light_rock.clone());
|
||||||
|
|
||||||
|
let ramp_aabr = orth_dir.trim_aabr(ramp_aabr, 1);
|
||||||
|
ramp_prim(ramp_aabr, 5).clear();
|
||||||
|
ramp_prim(ramp_aabr, 0).fill(rock.clone());
|
||||||
|
|
||||||
|
let vault_width = 12;
|
||||||
|
let vault_offset = 5;
|
||||||
|
let bridge_thickness = 4;
|
||||||
|
|
||||||
|
let [vault, _] = bridge.dir.split_aabr(aabr, vault_width);
|
||||||
|
|
||||||
|
let len = bridge.dir.select(aabr.size());
|
||||||
|
let true_offset = vault_width + vault_offset;
|
||||||
|
let n = len / true_offset;
|
||||||
|
let p = len / n;
|
||||||
|
|
||||||
|
let holes = painter
|
||||||
|
.vault(
|
||||||
|
aabb(
|
||||||
|
vault.min.with_z(bridge.center.z - 20),
|
||||||
|
vault.max.with_z(bridge.end.z - bridge_thickness - 1),
|
||||||
|
),
|
||||||
|
orth_dir,
|
||||||
)
|
)
|
||||||
.scale(
|
.repeat((forward * p).with_z(0), n as u32);
|
||||||
bridge.dir.abs().to_vec3().as_()
|
|
||||||
* ((len as f32 - upset as f32 * tweak!(2.0)) / (size as f32 * 2.0) - 1.0)
|
|
||||||
+ 1.0,
|
|
||||||
);
|
|
||||||
|
|
||||||
painter
|
painter
|
||||||
.ramp(
|
.aabb(aabb(
|
||||||
aabb(
|
aabr.min.with_z(bridge.center.z - 10),
|
||||||
bridge.start.with_z(bridge.start.z - inset)
|
aabr.max.with_z(bridge.end.z + 1),
|
||||||
- orthogonal * bridge.width()
|
))
|
||||||
- forward * inset,
|
.without(holes)
|
||||||
bridge.start.with_z(bridge.end.z) + orthogonal * bridge.width() + forward * dz,
|
.fill(light_rock);
|
||||||
),
|
|
||||||
dz + inset + 1,
|
let aabr = orth_dir.trim_aabr(aabr, 1);
|
||||||
bridge.dir,
|
painter
|
||||||
)
|
.aabb(aabb(
|
||||||
.union(
|
aabr.min.with_z(bridge.end.z + 1),
|
||||||
painter
|
aabr.max.with_z(bridge.end.z + 8),
|
||||||
.aabb(aabb(
|
)).clear();
|
||||||
bridge.start.with_z(bridge.end.z - 3 - size) - orthogonal * bridge.width()
|
|
||||||
+ forward * dz,
|
painter
|
||||||
bridge.start.with_z(bridge.end.z)
|
.aabb(aabb(
|
||||||
+ orthogonal * bridge.width()
|
aabr.min.with_z(bridge.end.z),
|
||||||
+ forward * forward * (bridge.end.xy() - bridge.start.xy()),
|
aabr.max.with_z(bridge.end.z),
|
||||||
))
|
)).fill(rock);
|
||||||
.without(hole),
|
|
||||||
)
|
|
||||||
.fill(rock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_heightened_viaduct(bridge: &Bridge, painter: &Painter, data: &HeightenedViaduct) {
|
fn render_heightened_viaduct(bridge: &Bridge, painter: &Painter, data: &HeightenedViaduct) {
|
||||||
@ -262,12 +303,6 @@ fn render_heightened_viaduct(bridge: &Bridge, painter: &Painter, data: &Heighten
|
|||||||
let bridge_start_z = bridge.end.z + data.bridge_start_offset;
|
let bridge_start_z = bridge.end.z + data.bridge_start_offset;
|
||||||
let bridge_top = bridge_start_z + len / slope_inv / 2;
|
let bridge_top = bridge_start_z + len / slope_inv / 2;
|
||||||
|
|
||||||
// painter.ramp(aabb(
|
|
||||||
// bridge.start - side,
|
|
||||||
// (bridge.start.xy() + side + forward * (bridge_start_z -
|
|
||||||
// bridge.start.z)).with_z(bridge_start_z), ), bridge_start_z -
|
|
||||||
// bridge.start.z, bridge.dir).fill(rock);
|
|
||||||
|
|
||||||
let bridge_width = bridge.width();
|
let bridge_width = bridge.width();
|
||||||
let side = orthogonal * bridge_width;
|
let side = orthogonal * bridge_width;
|
||||||
|
|
||||||
@ -415,8 +450,8 @@ fn render_heightened_viaduct(bridge: &Bridge, painter: &Painter, data: &Heighten
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bridge_prim(bridge_width).without(remove).fill(rock.clone());
|
bridge_prim(bridge_width).without(remove).fill(rock);
|
||||||
b.translate(-Vec3::unit_z()).fill(light_rock.clone());
|
b.translate(-Vec3::unit_z()).fill(light_rock);
|
||||||
|
|
||||||
br.translate(Vec3::unit_z() * 5)
|
br.translate(Vec3::unit_z() * 5)
|
||||||
.without(br.translate(-Vec3::unit_z()))
|
.without(br.translate(-Vec3::unit_z()))
|
||||||
@ -625,7 +660,7 @@ fn render_tower(bridge: &Bridge, painter: &Painter, roof_kind: &RoofKind) {
|
|||||||
(tower_aabr.min - 1).with_z(tower_end + 1),
|
(tower_aabr.min - 1).with_z(tower_end + 1),
|
||||||
(tower_aabr.max + 1).with_z(tower_end + 2 + tower_size),
|
(tower_aabr.max + 1).with_z(tower_end + 2 + tower_size),
|
||||||
))
|
))
|
||||||
.fill(wood.clone());
|
.fill(wood);
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -650,14 +685,14 @@ fn render_tower(bridge: &Bridge, painter: &Painter, roof_kind: &RoofKind) {
|
|||||||
painter
|
painter
|
||||||
.vault(
|
.vault(
|
||||||
aabb(
|
aabb(
|
||||||
(start + offset - size).with_z(bridge.center.z - 10),
|
(start + offset / 2 - size).with_z(bridge.center.z - 10),
|
||||||
(start + offset + size).with_z(bridge.end.z - 3),
|
(start + offset / 2 + size).with_z(bridge.end.z - 3),
|
||||||
),
|
),
|
||||||
orth_dir,
|
orth_dir,
|
||||||
)
|
)
|
||||||
.repeat(offset.with_z(0), n as u32),
|
.repeat(offset.with_z(0), n as u32),
|
||||||
)
|
)
|
||||||
.fill(rock.clone());
|
.fill(rock);
|
||||||
|
|
||||||
painter
|
painter
|
||||||
.aabb(aabb(
|
.aabb(aabb(
|
||||||
@ -740,8 +775,10 @@ fn render_hang(bridge: &Bridge, painter: &Painter) {
|
|||||||
|
|
||||||
let xsqr = (x * x) as f32;
|
let xsqr = (x * x) as f32;
|
||||||
let hsqr = (h * h) as f32;
|
let hsqr = (h * h) as f32;
|
||||||
let w = ((xsqr + (xsqr * (4.0 * hsqr + xsqr)).sqrt()) / 2.0).sqrt().ceil() + 1.0;
|
let w = ((xsqr + (xsqr * (4.0 * hsqr + xsqr)).sqrt()) / 2.0)
|
||||||
|
.sqrt()
|
||||||
|
.ceil()
|
||||||
|
+ 1.0;
|
||||||
|
|
||||||
let bottom = top - (h - (hsqr - hsqr * x as f32 / w).sqrt().ceil() as i32);
|
let bottom = top - (h - (hsqr - hsqr * x as f32 / w).sqrt().ceil() as i32);
|
||||||
|
|
||||||
@ -756,7 +793,10 @@ fn render_hang(bridge: &Bridge, painter: &Painter) {
|
|||||||
),
|
),
|
||||||
orth_dir,
|
orth_dir,
|
||||||
)
|
)
|
||||||
.intersect(painter.aabb(aabb(aabr.min.with_z(bottom), aabr.max.with_z(bottom + h * 2))));
|
.intersect(painter.aabb(aabb(
|
||||||
|
aabr.min.with_z(bottom),
|
||||||
|
aabr.max.with_z(bottom + h * 2),
|
||||||
|
)));
|
||||||
|
|
||||||
cylinder.fill(wood.clone());
|
cylinder.fill(wood.clone());
|
||||||
|
|
||||||
@ -773,14 +813,34 @@ fn render_hang(bridge: &Bridge, painter: &Painter) {
|
|||||||
.translate(Vec3::unit_z())
|
.translate(Vec3::unit_z())
|
||||||
.fill(Fill::Sprite(SpriteKind::Rope));
|
.fill(Fill::Sprite(SpriteKind::Rope));
|
||||||
|
|
||||||
edges.translate(Vec3::unit_z() * 2).fill(wood.clone());
|
edges.translate(Vec3::unit_z() * 2).fill(wood);
|
||||||
|
|
||||||
let column_height = 3;
|
let column_height = 3;
|
||||||
let column_range = top..=top + column_height;
|
let column_range = top..=top + column_height;
|
||||||
painter.column(bridge.dir.select_aabr_with(ramp_f, ramp_f.min), column_range.clone()).fill(rock.clone());
|
painter
|
||||||
painter.column(bridge.dir.select_aabr_with(ramp_f, ramp_f.max), column_range.clone()).fill(rock.clone());
|
.column(
|
||||||
painter.column((-bridge.dir).select_aabr_with(ramp_b, ramp_b.min), column_range.clone()).fill(rock.clone());
|
bridge.dir.select_aabr_with(ramp_f, ramp_f.min),
|
||||||
painter.column((-bridge.dir).select_aabr_with(ramp_b, ramp_b.max), column_range.clone()).fill(rock.clone());
|
column_range.clone(),
|
||||||
|
)
|
||||||
|
.fill(rock.clone());
|
||||||
|
painter
|
||||||
|
.column(
|
||||||
|
bridge.dir.select_aabr_with(ramp_f, ramp_f.max),
|
||||||
|
column_range.clone(),
|
||||||
|
)
|
||||||
|
.fill(rock.clone());
|
||||||
|
painter
|
||||||
|
.column(
|
||||||
|
(-bridge.dir).select_aabr_with(ramp_b, ramp_b.min),
|
||||||
|
column_range.clone(),
|
||||||
|
)
|
||||||
|
.fill(rock.clone());
|
||||||
|
painter
|
||||||
|
.column(
|
||||||
|
(-bridge.dir).select_aabr_with(ramp_b, ramp_b.max),
|
||||||
|
column_range,
|
||||||
|
)
|
||||||
|
.fill(rock);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Bridge {
|
pub struct Bridge {
|
||||||
@ -852,7 +912,7 @@ impl Bridge {
|
|||||||
|
|
||||||
let center = (start.xy() + end.xy()) / 2;
|
let center = (start.xy() + end.xy()) / 2;
|
||||||
let center = center.with_z(land.get_alt_approx(center) as i32);
|
let center = center.with_z(land.get_alt_approx(center) as i32);
|
||||||
let bridge = BridgeKind::random(rng, start, center, end);
|
let bridge = BridgeKind::random(rng, start, center, end, site.name());
|
||||||
Self {
|
Self {
|
||||||
start,
|
start,
|
||||||
end,
|
end,
|
||||||
|
@ -221,7 +221,10 @@ impl Dir {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn split_aabr<T>(self, aabr: Aabr<T>, offset: T) -> [Aabr<T>; 2] where T: Copy + PartialOrd + Add<T, Output = T> + Sub<T, Output = T> {
|
pub fn split_aabr<T>(self, aabr: Aabr<T>, offset: T) -> [Aabr<T>; 2]
|
||||||
|
where
|
||||||
|
T: Copy + PartialOrd + Add<T, Output = T> + Sub<T, Output = T>,
|
||||||
|
{
|
||||||
match self {
|
match self {
|
||||||
Dir::X => aabr.split_at_x(aabr.min.x + offset),
|
Dir::X => aabr.split_at_x(aabr.min.x + offset),
|
||||||
Dir::Y => aabr.split_at_y(aabr.min.y + offset),
|
Dir::Y => aabr.split_at_y(aabr.min.y + offset),
|
||||||
@ -236,6 +239,13 @@ impl Dir {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn trim_aabr(self, aabr: Aabr<i32>, offset: i32) -> Aabr<i32> {
|
||||||
|
Aabr {
|
||||||
|
min: aabr.min + self.abs().to_vec2() * offset,
|
||||||
|
max: aabr.max - self.abs().to_vec2() * offset,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn extend_aabr(self, aabr: Aabr<i32>, amount: i32) -> Aabr<i32> {
|
pub fn extend_aabr(self, aabr: Aabr<i32>, amount: i32) -> Aabr<i32> {
|
||||||
match self {
|
match self {
|
||||||
Dir::X => Aabr {
|
Dir::X => Aabr {
|
||||||
|
Loading…
Reference in New Issue
Block a user