Merge branch 'infrandomness/worldgen/giant_trees_modifications' into 'master'

Add new primitive to draw giant trees

See merge request veloren/veloren!3267
This commit is contained in:
Samuel Keiffer 2022-03-24 15:13:54 +00:00
commit a81baee7ac
2 changed files with 44 additions and 15 deletions

View File

@ -52,10 +52,12 @@ pub enum Primitive {
degree: f32, degree: f32,
}, },
Plane(Aabr<i32>, Vec3<i32>, Vec2<f32>), Plane(Aabr<i32>, Vec3<i32>, Vec2<f32>),
/// A line segment from start to finish point with a given radius /// A line segment from start to finish point with a given radius for both
/// points
Segment { Segment {
segment: LineSegment3<f32>, segment: LineSegment3<f32>,
radius: f32, r0: f32,
r1: f32,
}, },
/// A prism created by projecting a line segment with a given radius along /// A prism created by projecting a line segment with a given radius along
/// the z axis up to a provided height /// the z axis up to a provided height
@ -117,10 +119,11 @@ impl std::fmt::Debug for Primitive {
.field(&origin) .field(&origin)
.field(&gradient) .field(&gradient)
.finish(), .finish(),
Primitive::Segment { segment, radius } => f Primitive::Segment { segment, r0, r1 } => f
.debug_tuple("Segment") .debug_tuple("Segment")
.field(&segment) .field(&segment)
.field(&radius) .field(&r0)
.field(&r1)
.finish(), .finish(),
Primitive::SegmentPrism { Primitive::SegmentPrism {
segment, segment,
@ -333,8 +336,13 @@ impl Fill {
.as_() .as_()
.dot(*gradient) as i32) .dot(*gradient) as i32)
}, },
Primitive::Segment { segment, radius } => { // TODO: Aabb calculation could be improved here by only considering the relevant radius
segment.distance_to_point(pos.map(|e| e as f32)) < radius - 0.25 Primitive::Segment { segment, r0, r1 } => {
let distance = segment.end - segment.start;
let length = pos - segment.start.as_();
let t =
(length.as_().dot(distance) / distance.magnitude_squared()).clamped(0.0, 1.0);
segment.distance_to_point(pos.map(|e| e as f32)) < Lerp::lerp(r0, r1, t) - 0.25
}, },
Primitive::SegmentPrism { Primitive::SegmentPrism {
segment, segment,
@ -507,15 +515,15 @@ impl Fill {
}; };
vec![aabb.made_valid()] vec![aabb.made_valid()]
}, },
Primitive::Segment { segment, radius } => { Primitive::Segment { segment, r0, r1 } => {
let aabb = Aabb { let aabb = Aabb {
min: segment.start, min: segment.start,
max: segment.end, max: segment.end,
} }
.made_valid(); .made_valid();
vec![Aabb { vec![Aabb {
min: (aabb.min - *radius).floor().as_(), min: (aabb.min - r0.max(*r1)).floor().as_(),
max: (aabb.max + *radius).ceil().as_(), max: (aabb.max + r0.max(*r1)).ceil().as_(),
}] }]
}, },
Primitive::SegmentPrism { Primitive::SegmentPrism {
@ -815,7 +823,27 @@ impl Painter {
start: a.as_(), start: a.as_(),
end: b.as_(), end: b.as_(),
}, },
radius, r0: radius,
r1: radius,
})
}
/// Returns a `PrimitiveRef` of a 3-dimensional line segment with two
/// radius.
pub fn line_two_radius(
&self,
a: Vec3<impl AsPrimitive<f32>>,
b: Vec3<impl AsPrimitive<f32>>,
r0: f32,
r1: f32,
) -> PrimitiveRef {
self.prim(Primitive::Segment {
segment: LineSegment3 {
start: a.as_(),
end: b.as_(),
},
r0,
r1,
}) })
} }

View File

@ -21,7 +21,7 @@ impl GiantTree {
let wpos = site.tile_center_wpos(center_tile); let wpos = site.tile_center_wpos(center_tile);
Self { Self {
name: format!("Tree of {}", NameGen::location(rng).generate()), name: format!("Tree of {}", NameGen::location(rng).generate()),
// Find the tree's altitude // Get the tree's altitude
wpos: wpos.with_z(land.get_alt_approx(wpos) as i32), wpos: wpos.with_z(land.get_alt_approx(wpos) as i32),
tree: { tree: {
let config = TreeConfig::giant(rng, 4.0, true); let config = TreeConfig::giant(rng, 4.0, true);
@ -48,17 +48,17 @@ impl Structure for GiantTree {
light, light,
fast_noise.get((self.wpos.map(|e| e as f64) * 0.05) * 0.5 + 0.5), fast_noise.get((self.wpos.map(|e| e as f64) * 0.05) * 0.5 + 0.5),
); );
self.tree.walk(|branch, _| { self.tree.walk(|branch, parent| {
let aabr = Aabr { let aabr = Aabr {
min: self.wpos.xy() + branch.get_aabb().min.xy().as_(), min: self.wpos.xy() + branch.get_aabb().min.xy().as_(),
max: self.wpos.xy() + branch.get_aabb().max.xy().as_(), max: self.wpos.xy() + branch.get_aabb().max.xy().as_(),
}; };
if aabr.collides_with_aabr(painter.render_aabr().as_()) { if aabr.collides_with_aabr(painter.render_aabr().as_()) {
// TODO : Migrate to using Painter#line() instead
painter painter
.line( .line_two_radius(
self.wpos + branch.get_line().start.as_(), self.wpos + branch.get_line().start.as_(),
self.wpos + branch.get_line().end.as_(), self.wpos + branch.get_line().end.as_(),
parent.get_wood_radius(),
branch.get_wood_radius(), branch.get_wood_radius(),
) )
.fill(Fill::Block(Block::new( .fill(Fill::Block(Block::new(
@ -67,9 +67,10 @@ impl Structure for GiantTree {
))); )));
if branch.get_leaf_radius() > branch.get_wood_radius() { if branch.get_leaf_radius() > branch.get_wood_radius() {
painter painter
.line( .line_two_radius(
self.wpos + branch.get_line().start.as_(), self.wpos + branch.get_line().start.as_(),
self.wpos + branch.get_line().end.as_(), self.wpos + branch.get_line().end.as_(),
parent.get_leaf_radius(),
branch.get_leaf_radius(), branch.get_leaf_radius(),
) )
.fill(Fill::Block(Block::new( .fill(Fill::Block(Block::new(