mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Repeat CSG primitive and float line segment
This commit is contained in:
parent
cb45cea6a0
commit
6f99e70cca
@ -12,6 +12,7 @@ use common::{
|
|||||||
},
|
},
|
||||||
vol::ReadVol,
|
vol::ReadVol,
|
||||||
};
|
};
|
||||||
|
use num::cast::AsPrimitive;
|
||||||
use std::{cell::RefCell, sync::Arc};
|
use std::{cell::RefCell, sync::Arc};
|
||||||
use vek::*;
|
use vek::*;
|
||||||
|
|
||||||
@ -41,7 +42,7 @@ pub enum Primitive {
|
|||||||
Sphere(Aabb<i32>),
|
Sphere(Aabb<i32>),
|
||||||
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
|
||||||
Segment(LineSegment3<i32>, f32),
|
Segment(LineSegment3<f32>, f32),
|
||||||
/// A sampling function is always a subset of another primitive to avoid
|
/// A sampling function is always a subset of another primitive to avoid
|
||||||
/// needing infinite bounds
|
/// needing infinite bounds
|
||||||
Sampling(Id<Primitive>, Box<dyn Fn(Vec3<i32>) -> bool>),
|
Sampling(Id<Primitive>, Box<dyn Fn(Vec3<i32>) -> bool>),
|
||||||
@ -56,6 +57,9 @@ pub enum Primitive {
|
|||||||
Rotate(Id<Primitive>, Mat3<i32>),
|
Rotate(Id<Primitive>, Mat3<i32>),
|
||||||
Translate(Id<Primitive>, Vec3<i32>),
|
Translate(Id<Primitive>, Vec3<i32>),
|
||||||
Scale(Id<Primitive>, Vec3<f32>),
|
Scale(Id<Primitive>, Vec3<f32>),
|
||||||
|
/// Repeat a primitive a number of times in a given direction, overlapping
|
||||||
|
/// between repeats are unspecified.
|
||||||
|
Repeat(Id<Primitive>, Vec3<i32>, i32),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Primitive {
|
impl Primitive {
|
||||||
@ -86,6 +90,10 @@ impl Primitive {
|
|||||||
pub fn scale(a: impl Into<Id<Primitive>>, scale: Vec3<f32>) -> Self {
|
pub fn scale(a: impl Into<Id<Primitive>>, scale: Vec3<f32>) -> Self {
|
||||||
Self::Scale(a.into(), scale)
|
Self::Scale(a.into(), scale)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn repeat(a: impl Into<Id<Primitive>>, offset: Vec3<i32>, count: i32) -> Self {
|
||||||
|
Self::Repeat(a.into(), offset, count)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@ -217,7 +225,7 @@ impl Fill {
|
|||||||
&& (segment.start.y..segment.end.y).contains(&pos.y)
|
&& (segment.start.y..segment.end.y).contains(&pos.y)
|
||||||
&& (segment.start.z..segment.end.z).contains(&pos.z)
|
&& (segment.start.z..segment.end.z).contains(&pos.z)
|
||||||
&&*/
|
&&*/
|
||||||
segment.as_().distance_to_point(pos.map(|e| e as f32)) < radius - 0.25
|
segment.distance_to_point(pos.map(|e| e as f32)) < radius - 0.25
|
||||||
},
|
},
|
||||||
Primitive::Sampling(a, f) => self.contains_at(tree, *a, pos) && f(pos),
|
Primitive::Sampling(a, f) => self.contains_at(tree, *a, pos) && f(pos),
|
||||||
Primitive::Prefab(p) => !matches!(p.get(pos), Err(_) | Ok(StructureBlock::None)),
|
Primitive::Prefab(p) => !matches!(p.get(pos), Err(_) | Ok(StructureBlock::None)),
|
||||||
@ -247,6 +255,16 @@ impl Fill {
|
|||||||
.as_::<i32>();
|
.as_::<i32>();
|
||||||
self.contains_at(tree, *prim, spos)
|
self.contains_at(tree, *prim, spos)
|
||||||
},
|
},
|
||||||
|
Primitive::Repeat(prim, offset, count) => {
|
||||||
|
let aabb = self.get_bounds(tree, *prim);
|
||||||
|
let diff = pos - aabb.min;
|
||||||
|
let min = diff
|
||||||
|
.map2(*offset, |a, b| if b == 0 { i32::MAX } else { a / b })
|
||||||
|
.reduce_min()
|
||||||
|
.min(*count);
|
||||||
|
let pos = aabb.min + diff - offset * min;
|
||||||
|
self.contains_at(tree, *prim, pos)
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -329,8 +347,8 @@ impl Fill {
|
|||||||
aabb.made_valid()
|
aabb.made_valid()
|
||||||
},
|
},
|
||||||
Primitive::Segment(segment, radius) => Aabb {
|
Primitive::Segment(segment, radius) => Aabb {
|
||||||
min: segment.start - radius.floor() as i32,
|
min: (segment.start - *radius).floor().as_(),
|
||||||
max: segment.end + radius.ceil() as i32,
|
max: (segment.end + *radius).ceil().as_(),
|
||||||
},
|
},
|
||||||
Primitive::Sampling(a, _) => self.get_bounds_inner(tree, *a)?,
|
Primitive::Sampling(a, _) => self.get_bounds_inner(tree, *a)?,
|
||||||
Primitive::Prefab(p) => p.get_bounds(),
|
Primitive::Prefab(p) => p.get_bounds(),
|
||||||
@ -369,6 +387,13 @@ impl Fill {
|
|||||||
max: center + ((aabb.max - center).as_::<f32>() * vec).as_::<i32>(),
|
max: center + ((aabb.max - center).as_::<f32>() * vec).as_::<i32>(),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
Primitive::Repeat(prim, offset, count) => {
|
||||||
|
let aabb = self.get_bounds_inner(tree, *prim)?;
|
||||||
|
Aabb {
|
||||||
|
min: aabb.min.map2(aabb.min + offset * count, |a, b| a.min(b)),
|
||||||
|
max: aabb.max.map2(aabb.max + offset * count, |a, b| a.max(b)),
|
||||||
|
}
|
||||||
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -386,9 +411,17 @@ pub struct Painter {
|
|||||||
impl Painter {
|
impl Painter {
|
||||||
pub fn aabb(&self, aabb: Aabb<i32>) -> PrimitiveRef { self.prim(Primitive::Aabb(aabb)) }
|
pub fn aabb(&self, aabb: Aabb<i32>) -> PrimitiveRef { self.prim(Primitive::Aabb(aabb)) }
|
||||||
|
|
||||||
pub fn line(&self, a: Vec3<i32>, b: Vec3<i32>, radius: f32) -> PrimitiveRef {
|
pub fn line(
|
||||||
|
&self,
|
||||||
|
a: Vec3<impl AsPrimitive<f32>>,
|
||||||
|
b: Vec3<impl AsPrimitive<f32>>,
|
||||||
|
radius: f32,
|
||||||
|
) -> PrimitiveRef {
|
||||||
self.prim(Primitive::Segment(
|
self.prim(Primitive::Segment(
|
||||||
LineSegment3 { start: a, end: b },
|
LineSegment3 {
|
||||||
|
start: a.as_(),
|
||||||
|
end: b.as_(),
|
||||||
|
},
|
||||||
radius,
|
radius,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
@ -468,6 +501,10 @@ impl<'a> PrimitiveRef<'a> {
|
|||||||
self.painter
|
self.painter
|
||||||
.prim(Primitive::sampling(self, Box::new(sampling)))
|
.prim(Primitive::sampling(self, Box::new(sampling)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn repeat(self, offset: Vec3<i32>, count: i32) -> PrimitiveRef<'a> {
|
||||||
|
self.painter.prim(Primitive::repeat(self, offset, count))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Structure {
|
pub trait Structure {
|
||||||
|
@ -619,21 +619,19 @@ impl Structure for House {
|
|||||||
// something to do with AABBs with min and max not smaller in the right
|
// something to do with AABBs with min and max not smaller in the right
|
||||||
// order. The same thing is true for orientation 3.
|
// order. The same thing is true for orientation 3.
|
||||||
let support = match self.front {
|
let support = match self.front {
|
||||||
0 => painter.prim(Primitive::Segment(
|
0 => painter.line(
|
||||||
LineSegment3 {
|
Vec2::new(
|
||||||
start: Vec2::new(
|
temp.x,
|
||||||
temp.x,
|
self.bounds.max.y + storey_increase - self.overhang + 1,
|
||||||
self.bounds.max.y + storey_increase - self.overhang + 1,
|
)
|
||||||
)
|
.with_z(alt + previous_height - 3),
|
||||||
.with_z(alt + previous_height - 3),
|
Vec2::new(
|
||||||
end: Vec2::new(
|
temp.x,
|
||||||
temp.x,
|
self.bounds.max.y + storey_increase - self.overhang + 2,
|
||||||
self.bounds.max.y + storey_increase - self.overhang + 2,
|
)
|
||||||
)
|
.with_z(alt + previous_height),
|
||||||
.with_z(alt + previous_height),
|
|
||||||
},
|
|
||||||
0.75,
|
0.75,
|
||||||
)),
|
),
|
||||||
//2 => {
|
//2 => {
|
||||||
// painter.prim(Primitive::Segment(LineSegment3 {
|
// painter.prim(Primitive::Segment(LineSegment3 {
|
||||||
// start: Vec2::new(temp.x, self.bounds.min.y - storey_increase -
|
// start: Vec2::new(temp.x, self.bounds.min.y - storey_increase -
|
||||||
@ -669,37 +667,33 @@ impl Structure for House {
|
|||||||
};
|
};
|
||||||
let support = match self.front {
|
let support = match self.front {
|
||||||
0 => painter.prim(Primitive::Empty),
|
0 => painter.prim(Primitive::Empty),
|
||||||
1 => painter.prim(Primitive::Segment(
|
1 => painter.line(
|
||||||
LineSegment3 {
|
Vec2::new(
|
||||||
start: Vec2::new(
|
self.bounds.max.x + storey_increase - self.overhang + 1,
|
||||||
self.bounds.max.x + storey_increase - self.overhang + 1,
|
temp.y,
|
||||||
temp.y,
|
)
|
||||||
)
|
.with_z(alt + previous_height - 3),
|
||||||
.with_z(alt + previous_height - 3),
|
Vec2::new(
|
||||||
end: Vec2::new(
|
self.bounds.max.x + storey_increase - self.overhang + 2,
|
||||||
self.bounds.max.x + storey_increase - self.overhang + 2,
|
temp.y,
|
||||||
temp.y,
|
)
|
||||||
)
|
.with_z(alt + previous_height),
|
||||||
.with_z(alt + previous_height),
|
|
||||||
},
|
|
||||||
0.75,
|
0.75,
|
||||||
)),
|
),
|
||||||
2 => painter.prim(Primitive::Empty),
|
2 => painter.prim(Primitive::Empty),
|
||||||
_ => painter.prim(Primitive::Segment(
|
_ => painter.line(
|
||||||
LineSegment3 {
|
Vec2::new(
|
||||||
start: Vec2::new(
|
self.bounds.min.x - storey_increase + self.overhang - 1,
|
||||||
self.bounds.min.x - storey_increase + self.overhang - 1,
|
temp.y,
|
||||||
temp.y,
|
)
|
||||||
)
|
.with_z(alt + previous_height - 3),
|
||||||
.with_z(alt + previous_height - 3),
|
Vec2::new(
|
||||||
end: Vec2::new(
|
self.bounds.min.x - storey_increase + self.overhang - 2,
|
||||||
self.bounds.min.x - storey_increase + self.overhang - 2,
|
temp.y,
|
||||||
temp.y,
|
)
|
||||||
)
|
.with_z(alt + previous_height),
|
||||||
.with_z(alt + previous_height),
|
|
||||||
},
|
|
||||||
0.75,
|
0.75,
|
||||||
)),
|
),
|
||||||
};
|
};
|
||||||
if temp.y <= self.bounds.max.y && temp.y >= self.bounds.min.y {
|
if temp.y <= self.bounds.max.y && temp.y >= self.bounds.min.y {
|
||||||
overhang_supports =
|
overhang_supports =
|
||||||
|
Loading…
Reference in New Issue
Block a user