mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Re-organzied code relating to tower and wall generation.
This commit is contained in:
parent
643713d8b1
commit
466a02e1cf
@ -12,10 +12,8 @@ pub struct GnarlingFortification {
|
|||||||
origin: Vec2<i32>,
|
origin: Vec2<i32>,
|
||||||
radius: i32,
|
radius: i32,
|
||||||
wall_radius: i32,
|
wall_radius: i32,
|
||||||
// Vec2 is relative position of wall relative to site origin, bool indicates whether it is a
|
wall_segments: Vec<(Vec2<i32>, Vec2<i32>)>,
|
||||||
// corner, and thus whether a tower gets constructed
|
wall_towers: Vec<Vec2<i32>>,
|
||||||
ordered_wall_points: Vec<(Vec2<i32>, bool)>,
|
|
||||||
gate_index: usize,
|
|
||||||
// Structure indicates the kind of structure it is, vec2 is relative position of a hut compared
|
// Structure indicates the kind of structure it is, vec2 is relative position of a hut compared
|
||||||
// to origin, ori tells which way structure should face
|
// to origin, ori tells which way structure should face
|
||||||
structure_locations: Vec<(GnarlingStructure, Vec2<i32>, Ori)>,
|
structure_locations: Vec<(GnarlingStructure, Vec2<i32>, Ori)>,
|
||||||
@ -36,8 +34,6 @@ impl GnarlingStructure {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const SECTIONS_PER_WALL_SEGMENT: usize = 3;
|
|
||||||
|
|
||||||
impl GnarlingFortification {
|
impl GnarlingFortification {
|
||||||
pub fn generate(wpos: Vec2<i32>, land: &Land, rng: &mut impl Rng) -> Self {
|
pub fn generate(wpos: Vec2<i32>, land: &Land, rng: &mut impl Rng) -> Self {
|
||||||
let name = String::from("Gnarling Fortification");
|
let name = String::from("Gnarling Fortification");
|
||||||
@ -70,26 +66,20 @@ impl GnarlingFortification {
|
|||||||
|
|
||||||
let gate_index = rng.gen_range(0..wall_corners.len());
|
let gate_index = rng.gen_range(0..wall_corners.len());
|
||||||
|
|
||||||
// This adds additional points for the wall on the line between two points,
|
let wall_segments = wall_corners
|
||||||
// allowing the wall to better handle slopes
|
|
||||||
let ordered_wall_points = wall_corners
|
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.flat_map(|(i, point)| {
|
.filter_map(|(i, point)| {
|
||||||
let next_point = if let Some(point) = wall_corners.get(i + 1) {
|
if i == gate_index {
|
||||||
*point
|
None
|
||||||
} else {
|
} else {
|
||||||
wall_corners[0]
|
let next_point = if let Some(point) = wall_corners.get(i + 1) {
|
||||||
};
|
*point
|
||||||
(0..(SECTIONS_PER_WALL_SEGMENT as i32))
|
} else {
|
||||||
.into_iter()
|
wall_corners[0]
|
||||||
.map(move |a| {
|
};
|
||||||
let is_start_segment = a == 0;
|
Some((*point, next_point))
|
||||||
(
|
}
|
||||||
point + (next_point - point) * a / (SECTIONS_PER_WALL_SEGMENT as i32),
|
|
||||||
is_start_segment,
|
|
||||||
)
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
@ -161,8 +151,8 @@ impl GnarlingFortification {
|
|||||||
origin,
|
origin,
|
||||||
radius,
|
radius,
|
||||||
wall_radius,
|
wall_radius,
|
||||||
ordered_wall_points,
|
wall_towers: wall_corners,
|
||||||
gate_index,
|
wall_segments,
|
||||||
structure_locations,
|
structure_locations,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -175,211 +165,209 @@ impl GnarlingFortification {
|
|||||||
impl Structure for GnarlingFortification {
|
impl Structure for GnarlingFortification {
|
||||||
fn render(&self, _site: &Site, land: &Land, painter: &Painter) {
|
fn render(&self, _site: &Site, land: &Land, painter: &Painter) {
|
||||||
// Create outer wall
|
// Create outer wall
|
||||||
for (i, (point, _is_tower)) in self.ordered_wall_points.iter().enumerate() {
|
for (point, next_point) in self.wall_segments.iter() {
|
||||||
// If wall section is a gate, skip rendering the wall
|
// This adds additional points for the wall on the line between two points,
|
||||||
if ((self.gate_index * SECTIONS_PER_WALL_SEGMENT)
|
// allowing the wall to better handle slopes
|
||||||
..((self.gate_index + 1) * SECTIONS_PER_WALL_SEGMENT))
|
const SECTIONS_PER_WALL_SEGMENT: usize = 3;
|
||||||
.contains(&i)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Other point of wall segment
|
(0..(SECTIONS_PER_WALL_SEGMENT as i32))
|
||||||
let (next_point, _is_tower) = if let Some(point) = self.ordered_wall_points.get(i + 1) {
|
.into_iter()
|
||||||
*point
|
.map(move |a| {
|
||||||
} else {
|
let get_point =
|
||||||
self.ordered_wall_points[0]
|
|a| point + (next_point - point) * a / (SECTIONS_PER_WALL_SEGMENT as i32);
|
||||||
};
|
(get_point(a), get_point(a + 1))
|
||||||
// 2d world positions of each point in wall segment
|
})
|
||||||
let start_wpos = point + self.origin;
|
.for_each(|(point, next_point)| {
|
||||||
let end_wpos = next_point + self.origin;
|
// 2d world positions of each point in wall segment
|
||||||
|
let start_wpos = point + self.origin;
|
||||||
|
let end_wpos = next_point + self.origin;
|
||||||
|
|
||||||
// Wall base
|
// Wall base
|
||||||
let wall_depth = 3.0;
|
let wall_depth = 3.0;
|
||||||
let start = start_wpos
|
let start = start_wpos
|
||||||
.as_()
|
.as_()
|
||||||
.with_z(land.get_alt_approx(start_wpos) - wall_depth);
|
.with_z(land.get_alt_approx(start_wpos) - wall_depth);
|
||||||
let end = end_wpos
|
let end = end_wpos
|
||||||
.as_()
|
.as_()
|
||||||
.with_z(land.get_alt_approx(end_wpos) - wall_depth);
|
.with_z(land.get_alt_approx(end_wpos) - wall_depth);
|
||||||
|
|
||||||
let wall_base_thickness = 3.0;
|
let wall_base_thickness = 3.0;
|
||||||
let wall_base_height = 3.0;
|
let wall_base_height = 3.0;
|
||||||
|
|
||||||
painter
|
painter
|
||||||
.segment_prism(
|
.segment_prism(
|
||||||
start,
|
start,
|
||||||
end,
|
end,
|
||||||
wall_base_thickness,
|
wall_base_thickness,
|
||||||
wall_base_height + wall_depth as f32,
|
wall_base_height + wall_depth as f32,
|
||||||
)
|
)
|
||||||
.fill(Fill::Block(Block::new(
|
.fill(Fill::Block(Block::new(
|
||||||
BlockKind::Wood,
|
BlockKind::Wood,
|
||||||
Rgb::new(55, 25, 8),
|
Rgb::new(55, 25, 8),
|
||||||
)));
|
)));
|
||||||
|
|
||||||
// Middle of wall
|
// Middle of wall
|
||||||
let start = start_wpos.as_().with_z(land.get_alt_approx(start_wpos));
|
let start = start_wpos.as_().with_z(land.get_alt_approx(start_wpos));
|
||||||
let end = end_wpos.as_().with_z(land.get_alt_approx(end_wpos));
|
let end = end_wpos.as_().with_z(land.get_alt_approx(end_wpos));
|
||||||
|
|
||||||
let wall_mid_thickness = 1.0;
|
let wall_mid_thickness = 1.0;
|
||||||
let wall_mid_height = 5.0 + wall_base_height;
|
let wall_mid_height = 5.0 + wall_base_height;
|
||||||
|
|
||||||
painter
|
painter
|
||||||
.segment_prism(start, end, wall_mid_thickness, wall_mid_height)
|
.segment_prism(start, end, wall_mid_thickness, wall_mid_height)
|
||||||
.fill(Fill::Block(Block::new(
|
.fill(Fill::Block(Block::new(
|
||||||
BlockKind::Wood,
|
BlockKind::Wood,
|
||||||
Rgb::new(55, 25, 8),
|
Rgb::new(55, 25, 8),
|
||||||
)));
|
)));
|
||||||
|
|
||||||
// Top of wall
|
// Top of wall
|
||||||
let start = start_wpos
|
let start = start_wpos
|
||||||
.as_()
|
.as_()
|
||||||
.with_z(land.get_alt_approx(start_wpos) + wall_mid_height);
|
.with_z(land.get_alt_approx(start_wpos) + wall_mid_height);
|
||||||
let end = end_wpos
|
let end = end_wpos
|
||||||
.as_()
|
.as_()
|
||||||
.with_z(land.get_alt_approx(end_wpos) + wall_mid_height);
|
.with_z(land.get_alt_approx(end_wpos) + wall_mid_height);
|
||||||
|
|
||||||
let wall_top_thickness = 2.0;
|
let wall_top_thickness = 2.0;
|
||||||
let wall_top_height = 1.0;
|
let wall_top_height = 1.0;
|
||||||
|
|
||||||
painter
|
painter
|
||||||
.segment_prism(start, end, wall_top_thickness, wall_top_height)
|
.segment_prism(start, end, wall_top_thickness, wall_top_height)
|
||||||
.fill(Fill::Block(Block::new(
|
.fill(Fill::Block(Block::new(
|
||||||
BlockKind::Wood,
|
BlockKind::Wood,
|
||||||
Rgb::new(55, 25, 8),
|
Rgb::new(55, 25, 8),
|
||||||
)));
|
)));
|
||||||
|
|
||||||
// Wall parapets
|
// Wall parapets
|
||||||
let parapet_z_offset = 1.0;
|
let parapet_z_offset = 1.0;
|
||||||
|
|
||||||
let start = Vec3::new(
|
let start = Vec3::new(
|
||||||
point.x as f32 * (self.wall_radius as f32 + 1.0) / (self.wall_radius as f32)
|
point.x as f32 * (self.wall_radius as f32 + 1.0)
|
||||||
+ self.origin.x as f32,
|
/ (self.wall_radius as f32)
|
||||||
point.y as f32 * (self.wall_radius as f32 + 1.0) / (self.wall_radius as f32)
|
+ self.origin.x as f32,
|
||||||
+ self.origin.y as f32,
|
point.y as f32 * (self.wall_radius as f32 + 1.0)
|
||||||
land.get_alt_approx(start_wpos) + wall_mid_height + wall_top_height
|
/ (self.wall_radius as f32)
|
||||||
- parapet_z_offset,
|
+ self.origin.y as f32,
|
||||||
);
|
land.get_alt_approx(start_wpos) + wall_mid_height + wall_top_height
|
||||||
let end = Vec3::new(
|
- parapet_z_offset,
|
||||||
next_point.x as f32 * (self.wall_radius as f32 + 1.0) / (self.wall_radius as f32)
|
);
|
||||||
+ self.origin.x as f32,
|
let end = Vec3::new(
|
||||||
next_point.y as f32 * (self.wall_radius as f32 + 1.0) / (self.wall_radius as f32)
|
next_point.x as f32 * (self.wall_radius as f32 + 1.0)
|
||||||
+ self.origin.y as f32,
|
/ (self.wall_radius as f32)
|
||||||
land.get_alt_approx(end_wpos) + wall_mid_height + wall_top_height
|
+ self.origin.x as f32,
|
||||||
- parapet_z_offset,
|
next_point.y as f32 * (self.wall_radius as f32 + 1.0)
|
||||||
);
|
/ (self.wall_radius as f32)
|
||||||
|
+ self.origin.y as f32,
|
||||||
|
land.get_alt_approx(end_wpos) + wall_mid_height + wall_top_height
|
||||||
|
- parapet_z_offset,
|
||||||
|
);
|
||||||
|
|
||||||
let wall_par_thickness = tweak!(0.8);
|
let wall_par_thickness = tweak!(0.8);
|
||||||
let wall_par_height = 1.0;
|
let wall_par_height = 1.0;
|
||||||
|
|
||||||
painter
|
painter
|
||||||
.segment_prism(
|
.segment_prism(
|
||||||
start,
|
start,
|
||||||
end,
|
end,
|
||||||
wall_par_thickness,
|
wall_par_thickness,
|
||||||
wall_par_height + parapet_z_offset as f32,
|
wall_par_height + parapet_z_offset as f32,
|
||||||
)
|
)
|
||||||
.fill(Fill::Block(Block::new(
|
.fill(Fill::Block(Block::new(
|
||||||
BlockKind::Wood,
|
BlockKind::Wood,
|
||||||
Rgb::new(55, 25, 8),
|
Rgb::new(55, 25, 8),
|
||||||
)));
|
)));
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create towers
|
// Create towers
|
||||||
self.ordered_wall_points
|
self.wall_towers.iter().for_each(|point| {
|
||||||
.iter()
|
let wpos = point + self.origin;
|
||||||
.filter_map(|(point, is_tower)| is_tower.then_some(point))
|
|
||||||
.for_each(|point| {
|
|
||||||
let wpos = point + self.origin;
|
|
||||||
|
|
||||||
// Tower base
|
// Tower base
|
||||||
let tower_depth = 3;
|
let tower_depth = 3;
|
||||||
let tower_base_pos = wpos.with_z(land.get_alt_approx(wpos) as i32 - tower_depth);
|
let tower_base_pos = wpos.with_z(land.get_alt_approx(wpos) as i32 - tower_depth);
|
||||||
let tower_radius = 5.;
|
let tower_radius = 5.;
|
||||||
let tower_height = 20.0;
|
let tower_height = 20.0;
|
||||||
|
|
||||||
painter
|
painter
|
||||||
.prim(Primitive::cylinder(
|
.prim(Primitive::cylinder(
|
||||||
tower_base_pos,
|
tower_base_pos,
|
||||||
tower_radius,
|
tower_radius,
|
||||||
tower_depth as f32 + tower_height,
|
tower_depth as f32 + tower_height,
|
||||||
))
|
))
|
||||||
.fill(Fill::Block(Block::new(
|
.fill(Fill::Block(Block::new(
|
||||||
BlockKind::Wood,
|
BlockKind::Wood,
|
||||||
Rgb::new(55, 25, 8),
|
Rgb::new(55, 25, 8),
|
||||||
)));
|
)));
|
||||||
|
|
||||||
// Tower cylinder
|
// Tower cylinder
|
||||||
let tower_floor_pos = wpos.with_z(land.get_alt_approx(wpos) as i32);
|
let tower_floor_pos = wpos.with_z(land.get_alt_approx(wpos) as i32);
|
||||||
|
|
||||||
painter
|
painter
|
||||||
.prim(Primitive::cylinder(
|
.prim(Primitive::cylinder(
|
||||||
tower_floor_pos,
|
tower_floor_pos,
|
||||||
tower_radius - 1.0,
|
tower_radius - 1.0,
|
||||||
tower_height,
|
tower_height,
|
||||||
))
|
))
|
||||||
.fill(Fill::Block(Block::empty()));
|
.fill(Fill::Block(Block::empty()));
|
||||||
|
|
||||||
// Tower top floor
|
// Tower top floor
|
||||||
let top_floor_z = (land.get_alt_approx(wpos) + tower_height - 2.0) as i32;
|
let top_floor_z = (land.get_alt_approx(wpos) + tower_height - 2.0) as i32;
|
||||||
let tower_top_floor_pos = wpos.with_z(top_floor_z);
|
let tower_top_floor_pos = wpos.with_z(top_floor_z);
|
||||||
|
|
||||||
painter
|
painter
|
||||||
.prim(Primitive::cylinder(tower_top_floor_pos, tower_radius, 1.0))
|
.prim(Primitive::cylinder(tower_top_floor_pos, tower_radius, 1.0))
|
||||||
.fill(Fill::Block(Block::new(
|
.fill(Fill::Block(Block::new(
|
||||||
BlockKind::Wood,
|
BlockKind::Wood,
|
||||||
Rgb::new(55, 25, 8),
|
Rgb::new(55, 25, 8),
|
||||||
)));
|
)));
|
||||||
|
|
||||||
// Tower roof poles
|
// Tower roof poles
|
||||||
let roof_pole_height = 5;
|
let roof_pole_height = 5;
|
||||||
let relative_pole_positions = [
|
let relative_pole_positions = [
|
||||||
Vec2::new(-4, -4),
|
Vec2::new(-4, -4),
|
||||||
Vec2::new(-4, 3),
|
Vec2::new(-4, 3),
|
||||||
Vec2::new(3, -4),
|
Vec2::new(3, -4),
|
||||||
Vec2::new(3, 3),
|
Vec2::new(3, 3),
|
||||||
];
|
];
|
||||||
relative_pole_positions
|
relative_pole_positions
|
||||||
.iter()
|
.iter()
|
||||||
.map(|rpos| wpos + rpos)
|
.map(|rpos| wpos + rpos)
|
||||||
.for_each(|pole_pos| {
|
.for_each(|pole_pos| {
|
||||||
painter
|
painter
|
||||||
.line(
|
.line(
|
||||||
pole_pos.with_z(top_floor_z),
|
pole_pos.with_z(top_floor_z),
|
||||||
pole_pos.with_z(top_floor_z + roof_pole_height),
|
pole_pos.with_z(top_floor_z + roof_pole_height),
|
||||||
1.,
|
1.,
|
||||||
)
|
)
|
||||||
.fill(Fill::Block(Block::new(
|
.fill(Fill::Block(Block::new(
|
||||||
BlockKind::Wood,
|
BlockKind::Wood,
|
||||||
Rgb::new(55, 25, 8),
|
Rgb::new(55, 25, 8),
|
||||||
)));
|
)));
|
||||||
});
|
});
|
||||||
|
|
||||||
// Tower roof
|
// Tower roof
|
||||||
let roof_sphere_radius = 10;
|
let roof_sphere_radius = 10;
|
||||||
let roof_radius = tower_radius + 1.0;
|
let roof_radius = tower_radius + 1.0;
|
||||||
let roof_height = 3;
|
let roof_height = 3;
|
||||||
|
|
||||||
let roof_cyl = painter.prim(Primitive::cylinder(
|
let roof_cyl = painter.prim(Primitive::cylinder(
|
||||||
wpos.with_z(top_floor_z + roof_pole_height),
|
wpos.with_z(top_floor_z + roof_pole_height),
|
||||||
roof_radius,
|
roof_radius,
|
||||||
roof_height as f32,
|
roof_height as f32,
|
||||||
));
|
));
|
||||||
|
|
||||||
painter
|
painter
|
||||||
.prim(Primitive::sphere(
|
.prim(Primitive::sphere(
|
||||||
wpos.with_z(
|
wpos.with_z(top_floor_z + roof_pole_height + roof_height - roof_sphere_radius),
|
||||||
top_floor_z + roof_pole_height + roof_height - roof_sphere_radius,
|
roof_sphere_radius as f32,
|
||||||
),
|
))
|
||||||
roof_sphere_radius as f32,
|
.intersect(roof_cyl)
|
||||||
))
|
.fill(Fill::Block(Block::new(
|
||||||
.intersect(roof_cyl)
|
BlockKind::Wood,
|
||||||
.fill(Fill::Block(Block::new(
|
Rgb::new(55, 25, 8),
|
||||||
BlockKind::Wood,
|
)));
|
||||||
Rgb::new(55, 25, 8),
|
});
|
||||||
)));
|
|
||||||
});
|
|
||||||
|
|
||||||
self.structure_locations
|
self.structure_locations
|
||||||
.iter()
|
.iter()
|
||||||
|
Loading…
Reference in New Issue
Block a user