mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Primitive fixes
This commit is contained in:
parent
87b139d32b
commit
7621a21560
@ -13,7 +13,7 @@ use rayon::ThreadPoolBuilder;
|
||||
use vek::{Vec2, Vec3};
|
||||
use veloren_world::{
|
||||
sim::{FileOpts, WorldOpts, DEFAULT_WORLD_MAP},
|
||||
site2::{plot::PlotKind, Structure},
|
||||
site2::{plot::PlotKind, Fill, Structure},
|
||||
CanvasInfo, Land, World,
|
||||
};
|
||||
|
||||
@ -47,7 +47,7 @@ fn main() -> Result {
|
||||
let (prim_tree, fills, _entities) = dungeon.render_collect(&site, canvas);
|
||||
|
||||
for (prim, fill) in fills {
|
||||
let aabb = fill.get_bounds(&prim_tree, prim);
|
||||
let aabb = Fill::get_bounds(&prim_tree, prim);
|
||||
|
||||
for x in aabb.min.x..aabb.max.x {
|
||||
for y in aabb.min.y..aabb.max.y {
|
||||
|
@ -75,10 +75,9 @@ pub enum Primitive {
|
||||
// Not commutative
|
||||
Without(Id<Primitive>, Id<Primitive>),
|
||||
// Operators
|
||||
Rotate(Id<Primitive>, Mat3<i32>),
|
||||
Translate(Id<Primitive>, Vec3<i32>),
|
||||
Scale(Id<Primitive>, Vec3<f32>),
|
||||
RotateAbout(Id<Primitive>, Mat3<i32>, Vec3<i32>),
|
||||
RotateAbout(Id<Primitive>, Mat3<i32>, Vec3<f32>),
|
||||
/// Repeat a primitive a number of times in a given direction, overlapping
|
||||
/// between repeats are unspecified.
|
||||
Repeat(Id<Primitive>, Vec3<i32>, u32),
|
||||
@ -138,13 +137,12 @@ impl std::fmt::Debug for Primitive {
|
||||
Primitive::Intersect(a, b) => f.debug_tuple("Intersect").field(&a).field(&b).finish(),
|
||||
Primitive::Union(a, b) => f.debug_tuple("Union").field(&a).field(&b).finish(),
|
||||
Primitive::Without(a, b) => f.debug_tuple("Without").field(&a).field(&b).finish(),
|
||||
Primitive::Rotate(a, mat) => f.debug_tuple("Rotate").field(&a).field(&mat).finish(),
|
||||
Primitive::Translate(a, vec) => {
|
||||
f.debug_tuple("Translate").field(&a).field(&vec).finish()
|
||||
},
|
||||
Primitive::Scale(a, vec) => f.debug_tuple("Scale").field(&a).field(&vec).finish(),
|
||||
Primitive::RotateAbout(a, mat, vec) => f
|
||||
.debug_tuple("RotateAround")
|
||||
.debug_tuple("RotateAbout")
|
||||
.field(&a)
|
||||
.field(&mat)
|
||||
.field(&vec)
|
||||
@ -176,10 +174,6 @@ impl Primitive {
|
||||
Self::Sampling(a.into(), f)
|
||||
}
|
||||
|
||||
pub fn rotate(a: impl Into<Id<Primitive>>, rot: Mat3<i32>) -> Self {
|
||||
Self::Rotate(a.into(), rot)
|
||||
}
|
||||
|
||||
pub fn translate(a: impl Into<Id<Primitive>>, trans: Vec3<i32>) -> Self {
|
||||
Self::Translate(a.into(), trans)
|
||||
}
|
||||
@ -188,8 +182,12 @@ impl Primitive {
|
||||
Self::Scale(a.into(), scale)
|
||||
}
|
||||
|
||||
pub fn rotate_about(a: impl Into<Id<Primitive>>, rot: Mat3<i32>, point: Vec3<i32>) -> Self {
|
||||
Self::RotateAbout(a.into(), rot, point)
|
||||
pub fn rotate_about(
|
||||
a: impl Into<Id<Primitive>>,
|
||||
rot: Mat3<i32>,
|
||||
point: Vec3<impl AsPrimitive<f32>>,
|
||||
) -> Self {
|
||||
Self::RotateAbout(a.into(), rot, point.as_())
|
||||
}
|
||||
|
||||
pub fn repeat(a: impl Into<Id<Primitive>>, offset: Vec3<i32>, count: u32) -> Self {
|
||||
@ -212,7 +210,7 @@ pub enum Fill {
|
||||
}
|
||||
|
||||
impl Fill {
|
||||
fn contains_at(&self, tree: &Store<Primitive>, prim: Id<Primitive>, pos: Vec3<i32>) -> bool {
|
||||
fn contains_at(tree: &Store<Primitive>, prim: Id<Primitive>, pos: Vec3<i32>) -> bool {
|
||||
// Custom closure because vek's impl of `contains_point` is inclusive :(
|
||||
let aabb_contains = |aabb: Aabb<i32>, pos: Vec3<i32>| {
|
||||
(aabb.min.x..aabb.max.x).contains(&pos.x)
|
||||
@ -369,51 +367,53 @@ impl Fill {
|
||||
let z_check = (projected_z..=(projected_z + height)).contains(&(pos.z as f32));
|
||||
xy_check && z_check
|
||||
},
|
||||
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::Intersect(a, b) => {
|
||||
self.contains_at(tree, *a, pos) && self.contains_at(tree, *b, pos)
|
||||
Self::contains_at(tree, *a, pos) && Self::contains_at(tree, *b, pos)
|
||||
},
|
||||
Primitive::Union(a, b) => {
|
||||
self.contains_at(tree, *a, pos) || self.contains_at(tree, *b, pos)
|
||||
Self::contains_at(tree, *a, pos) || Self::contains_at(tree, *b, pos)
|
||||
},
|
||||
Primitive::Without(a, b) => {
|
||||
self.contains_at(tree, *a, pos) && !self.contains_at(tree, *b, pos)
|
||||
},
|
||||
Primitive::Rotate(prim, mat) => {
|
||||
let aabb = self.get_bounds(tree, *prim);
|
||||
let diff = pos - (aabb.min + mat.cols.map(|x| x.reduce_min()));
|
||||
self.contains_at(tree, *prim, aabb.min + mat.transposed() * diff)
|
||||
Self::contains_at(tree, *a, pos) && !Self::contains_at(tree, *b, pos)
|
||||
},
|
||||
Primitive::Translate(prim, vec) => {
|
||||
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) => {
|
||||
let center =
|
||||
self.get_bounds(tree, *prim).center().as_::<f32>() - Vec3::broadcast(0.5);
|
||||
Self::get_bounds(tree, *prim).center().as_::<f32>() - Vec3::broadcast(0.5);
|
||||
let fpos = pos.as_::<f32>();
|
||||
let spos = (center + ((center - fpos) / vec))
|
||||
.map(|x| x.round())
|
||||
.as_::<i32>();
|
||||
self.contains_at(tree, *prim, spos)
|
||||
Self::contains_at(tree, *prim, spos)
|
||||
},
|
||||
Primitive::RotateAbout(prim, mat, vec) => {
|
||||
self.contains_at(tree, *prim, vec + *mat * (pos - vec))
|
||||
let mat = mat.as_::<f32>().transposed();
|
||||
let vec = vec - 0.5;
|
||||
Self::contains_at(tree, *prim, (vec + mat * (pos.as_::<f32>() - vec)).as_())
|
||||
},
|
||||
Primitive::Repeat(prim, offset, count) => {
|
||||
let aabb = self.get_bounds(tree, *prim);
|
||||
let aabb_corner = {
|
||||
let min_red = aabb.min.map2(*offset, |a, b| if b < 0 { 0 } else { a });
|
||||
let max_red = aabb.max.map2(*offset, |a, b| if b < 0 { a } else { 0 });
|
||||
min_red + max_red
|
||||
};
|
||||
let diff = pos - aabb_corner;
|
||||
let min = diff
|
||||
.map2(*offset, |a, b| if b == 0 { i32::MAX } else { a / b })
|
||||
.reduce_min()
|
||||
.clamp(0, *count as i32);
|
||||
let pos = pos - offset * min;
|
||||
self.contains_at(tree, *prim, pos)
|
||||
if count == &0 {
|
||||
false
|
||||
} else {
|
||||
let count = count - 1;
|
||||
let aabb = Self::get_bounds(tree, *prim);
|
||||
let aabb_corner = {
|
||||
let min_red = aabb.min.map2(*offset, |a, b| if b < 0 { 0 } else { a });
|
||||
let max_red = aabb.max.map2(*offset, |a, b| if b < 0 { a } else { 0 });
|
||||
min_red + max_red
|
||||
};
|
||||
let diff = pos - aabb_corner;
|
||||
let min = diff
|
||||
.map2(*offset, |a, b| if b == 0 { i32::MAX } else { a / b })
|
||||
.reduce_min()
|
||||
.clamp(0, count as i32);
|
||||
let pos = pos - offset * min;
|
||||
Self::contains_at(tree, *prim, pos)
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -426,7 +426,7 @@ impl Fill {
|
||||
canvas_info: &crate::CanvasInfo,
|
||||
old_block: Block,
|
||||
) -> Option<Block> {
|
||||
if self.contains_at(tree, prim, pos) {
|
||||
if Self::contains_at(tree, prim, pos) {
|
||||
match self {
|
||||
Fill::Block(block) => Some(*block),
|
||||
Fill::Sprite(sprite) => Some(if old_block.is_filled() {
|
||||
@ -471,7 +471,7 @@ impl Fill {
|
||||
}
|
||||
}
|
||||
|
||||
fn get_bounds_inner(&self, tree: &Store<Primitive>, prim: Id<Primitive>) -> Vec<Aabb<i32>> {
|
||||
fn get_bounds_inner(tree: &Store<Primitive>, prim: Id<Primitive>) -> Vec<Aabb<i32>> {
|
||||
fn or_zip_with<T, F: FnOnce(T, T) -> T>(a: Option<T>, b: Option<T>, f: F) -> Option<T> {
|
||||
match (a, b) {
|
||||
(Some(a), Some(b)) => Some(f(a, b)),
|
||||
@ -538,11 +538,11 @@ impl Fill {
|
||||
};
|
||||
vec![Aabb { min, max }]
|
||||
},
|
||||
Primitive::Sampling(a, _) => self.get_bounds_inner(tree, *a),
|
||||
Primitive::Sampling(a, _) => Self::get_bounds_inner(tree, *a),
|
||||
Primitive::Prefab(p) => vec![p.get_bounds()],
|
||||
Primitive::Intersect(a, b) => or_zip_with(
|
||||
self.get_bounds_opt(tree, *a),
|
||||
self.get_bounds_opt(tree, *b),
|
||||
Self::get_bounds_opt(tree, *a),
|
||||
Self::get_bounds_opt(tree, *b),
|
||||
|a, b| a.intersection(b),
|
||||
)
|
||||
.into_iter()
|
||||
@ -555,8 +555,8 @@ impl Fill {
|
||||
s_intersection / s_union
|
||||
}
|
||||
let mut inputs = Vec::new();
|
||||
inputs.extend(self.get_bounds_inner(tree, *a));
|
||||
inputs.extend(self.get_bounds_inner(tree, *b));
|
||||
inputs.extend(Self::get_bounds_inner(tree, *a));
|
||||
inputs.extend(Self::get_bounds_inner(tree, *b));
|
||||
let mut results = Vec::new();
|
||||
if let Some(aabb) = inputs.pop() {
|
||||
results.push(aabb);
|
||||
@ -579,29 +579,15 @@ impl Fill {
|
||||
results
|
||||
}
|
||||
},
|
||||
Primitive::Without(a, _) => self.get_bounds_inner(tree, *a),
|
||||
Primitive::Rotate(prim, mat) => self
|
||||
.get_bounds_inner(tree, *prim)
|
||||
.into_iter()
|
||||
.map(|aabb| {
|
||||
let extent = *mat * Vec3::from(aabb.size());
|
||||
let new_aabb: Aabb<i32> = Aabb {
|
||||
min: aabb.min,
|
||||
max: aabb.min + extent,
|
||||
};
|
||||
new_aabb.made_valid()
|
||||
})
|
||||
.collect(),
|
||||
Primitive::Translate(prim, vec) => self
|
||||
.get_bounds_inner(tree, *prim)
|
||||
Primitive::Without(a, _) => Self::get_bounds_inner(tree, *a),
|
||||
Primitive::Translate(prim, vec) => Self::get_bounds_inner(tree, *prim)
|
||||
.into_iter()
|
||||
.map(|aabb| Aabb {
|
||||
min: aabb.min.map2(*vec, i32::saturating_add),
|
||||
max: aabb.max.map2(*vec, i32::saturating_add),
|
||||
})
|
||||
.collect(),
|
||||
Primitive::Scale(prim, vec) => self
|
||||
.get_bounds_inner(tree, *prim)
|
||||
Primitive::Scale(prim, vec) => Self::get_bounds_inner(tree, *prim)
|
||||
.into_iter()
|
||||
.map(|aabb| {
|
||||
let center = aabb.center();
|
||||
@ -611,55 +597,58 @@ impl Fill {
|
||||
}
|
||||
})
|
||||
.collect(),
|
||||
Primitive::RotateAbout(prim, mat, vec) => self
|
||||
.get_bounds_inner(tree, *prim)
|
||||
Primitive::RotateAbout(prim, mat, vec) => Self::get_bounds_inner(tree, *prim)
|
||||
.into_iter()
|
||||
.map(|aabb| {
|
||||
let mut new_aabb: Aabb<i32> = Aabb {
|
||||
min: vec + *mat * (aabb.min - vec),
|
||||
max: vec + *mat * (aabb.max - 1 - vec),
|
||||
let mat = mat.as_::<f32>();
|
||||
// - 0.5 because we want the point to be at the minimum of the voxel
|
||||
let vec = vec - 0.5;
|
||||
let new_aabb = Aabb::<f32> {
|
||||
min: vec + mat * (aabb.min.as_() - vec),
|
||||
// - 1 becuase we want the AABB to be inclusive when we rotate it, we then
|
||||
// add 1 back to make it exclusive again
|
||||
max: vec + mat * ((aabb.max - 1).as_() - vec),
|
||||
}
|
||||
.made_valid();
|
||||
new_aabb.max += 1;
|
||||
new_aabb
|
||||
})
|
||||
.collect(),
|
||||
Primitive::Repeat(prim, offset, count) => self
|
||||
.get_bounds_inner(tree, *prim)
|
||||
.into_iter()
|
||||
.map(|aabb| Aabb {
|
||||
min: aabb
|
||||
.min
|
||||
.map2(aabb.min + offset * *count as i32, |a, b| a.min(b)),
|
||||
max: aabb
|
||||
.max
|
||||
.map2(aabb.max + offset * *count as i32, |a, b| a.max(b)),
|
||||
Aabb::<i32> {
|
||||
min: new_aabb.min.as_(),
|
||||
max: new_aabb.max.as_() + 1,
|
||||
}
|
||||
})
|
||||
.collect(),
|
||||
Primitive::Repeat(prim, offset, count) => {
|
||||
if count == &0 {
|
||||
vec![]
|
||||
} else {
|
||||
let count = count - 1;
|
||||
Self::get_bounds_inner(tree, *prim)
|
||||
.into_iter()
|
||||
.map(|aabb| Aabb {
|
||||
min: aabb
|
||||
.min
|
||||
.map2(aabb.min + offset * count as i32, |a, b| a.min(b)),
|
||||
max: aabb
|
||||
.max
|
||||
.map2(aabb.max + offset * count as i32, |a, b| a.max(b)),
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_bounds_disjoint(
|
||||
&self,
|
||||
tree: &Store<Primitive>,
|
||||
prim: Id<Primitive>,
|
||||
) -> Vec<Aabb<i32>> {
|
||||
self.get_bounds_inner(tree, prim)
|
||||
pub fn get_bounds_disjoint(tree: &Store<Primitive>, prim: Id<Primitive>) -> Vec<Aabb<i32>> {
|
||||
Self::get_bounds_inner(tree, prim)
|
||||
}
|
||||
|
||||
pub fn get_bounds_opt(
|
||||
&self,
|
||||
tree: &Store<Primitive>,
|
||||
prim: Id<Primitive>,
|
||||
) -> Option<Aabb<i32>> {
|
||||
self.get_bounds_inner(tree, prim)
|
||||
pub fn get_bounds_opt(tree: &Store<Primitive>, prim: Id<Primitive>) -> Option<Aabb<i32>> {
|
||||
Self::get_bounds_inner(tree, prim)
|
||||
.into_iter()
|
||||
.reduce(|a, b| a.union(b))
|
||||
}
|
||||
|
||||
pub fn get_bounds(&self, tree: &Store<Primitive>, prim: Id<Primitive>) -> Aabb<i32> {
|
||||
self.get_bounds_opt(tree, prim)
|
||||
.unwrap_or_else(|| Aabb::new_empty(Vec3::zero()))
|
||||
pub fn get_bounds(tree: &Store<Primitive>, prim: Id<Primitive>) -> Aabb<i32> {
|
||||
Self::get_bounds_opt(tree, prim).unwrap_or_else(|| Aabb::new_empty(Vec3::zero()))
|
||||
}
|
||||
}
|
||||
|
||||
@ -689,7 +678,6 @@ impl Painter {
|
||||
| Primitive::SegmentPrism { .. }
|
||||
| Primitive::Prefab(_) => prev_depth,
|
||||
Primitive::Sampling(a, _)
|
||||
| Primitive::Rotate(a, _)
|
||||
| Primitive::Translate(a, _)
|
||||
| Primitive::Scale(a, _)
|
||||
| Primitive::RotateAbout(a, _, _)
|
||||
@ -1097,6 +1085,13 @@ impl<'a> PrimitiveRef<'a> {
|
||||
self.painter
|
||||
.prim(Primitive::sampling(self, Box::new(sampling)))
|
||||
}
|
||||
|
||||
/// Rotates a primitive about it's own's bounds minimum point,
|
||||
#[must_use]
|
||||
pub fn rotate_about_min(self, mat: Mat3<i32>) -> PrimitiveRef<'a> {
|
||||
let point = Fill::get_bounds(&self.painter.prims.borrow(), self.into()).min;
|
||||
self.rotate_about(mat, point)
|
||||
}
|
||||
}
|
||||
|
||||
/// A trait to more easily manipulate groups of primitives.
|
||||
@ -1104,14 +1099,10 @@ pub trait PrimitiveTransform {
|
||||
/// Translates the primitive along the vector `trans`.
|
||||
#[must_use]
|
||||
fn translate(self, trans: Vec3<i32>) -> Self;
|
||||
/// Rotates the primitive about the minimum position of the primitive by
|
||||
/// multiplying each block position by the provided rotation matrix.
|
||||
#[must_use]
|
||||
fn rotate(self, rot: Mat3<i32>) -> Self;
|
||||
/// Rotates the primitive about the given point of the primitive by
|
||||
/// multiplying each block position by the provided rotation matrix.
|
||||
#[must_use]
|
||||
fn rotate_about(self, rot: Mat3<i32>, point: Vec3<i32>) -> Self;
|
||||
fn rotate_about(self, rot: Mat3<i32>, point: Vec3<impl AsPrimitive<f32>>) -> Self;
|
||||
/// Scales the primitive along each axis by the x, y, and z components of
|
||||
/// the `scale` vector respectively.
|
||||
#[must_use]
|
||||
@ -1128,9 +1119,7 @@ impl<'a> PrimitiveTransform for PrimitiveRef<'a> {
|
||||
self.painter.prim(Primitive::translate(self, trans))
|
||||
}
|
||||
|
||||
fn rotate(self, rot: Mat3<i32>) -> Self { self.painter.prim(Primitive::rotate(self, rot)) }
|
||||
|
||||
fn rotate_about(self, rot: Mat3<i32>, point: Vec3<i32>) -> Self {
|
||||
fn rotate_about(self, rot: Mat3<i32>, point: Vec3<impl AsPrimitive<f32>>) -> Self {
|
||||
self.painter.prim(Primitive::rotate_about(self, rot, point))
|
||||
}
|
||||
|
||||
@ -1149,14 +1138,7 @@ impl<'a, const N: usize> PrimitiveTransform for [PrimitiveRef<'a>; N] {
|
||||
self
|
||||
}
|
||||
|
||||
fn rotate(mut self, rot: Mat3<i32>) -> Self {
|
||||
for prim in &mut self {
|
||||
*prim = prim.rotate(rot);
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
fn rotate_about(mut self, rot: Mat3<i32>, point: Vec3<i32>) -> Self {
|
||||
fn rotate_about(mut self, rot: Mat3<i32>, point: Vec3<impl AsPrimitive<f32>>) -> Self {
|
||||
for prim in &mut self {
|
||||
*prim = prim.rotate_about(rot, point);
|
||||
}
|
||||
|
@ -999,7 +999,7 @@ impl Site {
|
||||
}
|
||||
|
||||
for (prim, fill) in fills {
|
||||
for mut aabb in fill.get_bounds_disjoint(&prim_tree, prim) {
|
||||
for mut aabb in Fill::get_bounds_disjoint(&prim_tree, prim) {
|
||||
aabb.min = Vec2::max(aabb.min.xy(), chunk_aabr.min).with_z(aabb.min.z);
|
||||
aabb.max = Vec2::min(aabb.max.xy(), chunk_aabr.max).with_z(aabb.max.z);
|
||||
|
||||
|
@ -887,16 +887,16 @@ impl Structure for GnarlingFortification {
|
||||
(wpos - 19).with_z(alt + raise),
|
||||
2.0,
|
||||
)
|
||||
.repeat(Vec3::new(37, 0, 0), 1)
|
||||
.repeat(Vec3::new(0, 37, 0), 1);
|
||||
.repeat(Vec3::new(37, 0, 0), 2)
|
||||
.repeat(Vec3::new(0, 37, 0), 2);
|
||||
|
||||
let supports_inner = painter
|
||||
.aabb(Aabb {
|
||||
min: (wpos - 19).with_z(alt - 10) + Vec3::unit_y() * 17,
|
||||
max: (wpos - 15).with_z(alt + raise) + Vec3::unit_y() * 17,
|
||||
})
|
||||
.repeat(Vec3::new(17, 17, 0), 1)
|
||||
.repeat(Vec3::new(17, -17, 0), 1);
|
||||
.repeat(Vec3::new(17, 17, 0), 2)
|
||||
.repeat(Vec3::new(17, -17, 0), 2);
|
||||
// let support_inner_2 = support_inner_1.translate(Vec3::new(34, 0, 0));
|
||||
// let support_inner_3 = support_inner_1.translate(Vec3::new(17, 17, 0));
|
||||
// let support_inner_4 = support_inner_1.translate(Vec3::new(17, -17, 0));
|
||||
@ -970,11 +970,11 @@ impl Structure for GnarlingFortification {
|
||||
.union(wall2roof);
|
||||
|
||||
let roof_support_2 =
|
||||
roof_support_1.rotate(Mat3::new(1, 0, 0, 0, -1, 0, 0, 0, 1));
|
||||
roof_support_1.rotate_about_min(Mat3::new(1, 0, 0, 0, -1, 0, 0, 0, 1));
|
||||
let roof_support_3 =
|
||||
roof_support_1.rotate(Mat3::new(-1, 0, 0, 0, 1, 0, 0, 0, 1));
|
||||
roof_support_1.rotate_about_min(Mat3::new(-1, 0, 0, 0, 1, 0, 0, 0, 1));
|
||||
let roof_support_4 =
|
||||
roof_support_1.rotate(Mat3::new(-1, 0, 0, 0, -1, 0, 0, 0, 1));
|
||||
roof_support_1.rotate_about_min(Mat3::new(-1, 0, 0, 0, -1, 0, 0, 0, 1));
|
||||
let roof_support = roof_support_1
|
||||
.union(roof_support_2)
|
||||
.union(roof_support_3)
|
||||
@ -989,12 +989,13 @@ impl Structure for GnarlingFortification {
|
||||
(wpos + rad_2 as i32).with_z(alt + raise + height_1 as i32 + 8),
|
||||
1.3,
|
||||
);
|
||||
let spike_low = spike_high.rotate(Mat3::new(1, 0, 0, 0, 1, 0, 0, 0, -1));
|
||||
let spike_low =
|
||||
spike_high.rotate_about_min(Mat3::new(1, 0, 0, 0, 1, 0, 0, 0, -1));
|
||||
let spike_1 = centerspot.union(spike_low).union(spike_high);
|
||||
|
||||
let spike_2 = spike_1.rotate(Mat3::new(1, 0, 0, 0, -1, 0, 0, 0, 1));
|
||||
let spike_3 = spike_1.rotate(Mat3::new(-1, 0, 0, 0, 1, 0, 0, 0, 1));
|
||||
let spike_4 = spike_1.rotate(Mat3::new(-1, 0, 0, 0, -1, 0, 0, 0, 1));
|
||||
let spike_2 = spike_1.rotate_about_min(Mat3::new(1, 0, 0, 0, -1, 0, 0, 0, 1));
|
||||
let spike_3 = spike_1.rotate_about_min(Mat3::new(-1, 0, 0, 0, 1, 0, 0, 0, 1));
|
||||
let spike_4 = spike_1.rotate_about_min(Mat3::new(-1, 0, 0, 0, -1, 0, 0, 0, 1));
|
||||
let spikes = spike_1.union(spike_2).union(spike_3).union(spike_4);
|
||||
|
||||
painter.fill(
|
||||
@ -1219,13 +1220,13 @@ impl Structure for GnarlingFortification {
|
||||
let leg3 = leg1.translate(Vec3::new(width * 2 - 2, 0, 0));
|
||||
let leg4 = leg1.translate(Vec3::new(width * 2 - 2, width * 2 - 2, 0));
|
||||
let legsupport2 = legsupport1
|
||||
.rotate(Mat3::new(0, 1, 0, -1, 0, 0, 0, 0, 1))
|
||||
.rotate_about_min(Mat3::new(0, 1, 0, -1, 0, 0, 0, 0, 1))
|
||||
.translate(Vec3::new(1, width * 2 + 1, 0));
|
||||
let legsupport3 = legsupport1
|
||||
.rotate(Mat3::new(0, -1, 0, 1, 0, 0, 0, 0, 1))
|
||||
.rotate_about_min(Mat3::new(0, -1, 0, 1, 0, 0, 0, 0, 1))
|
||||
.translate(Vec3::new(width * 2 + 1, 1, 0));
|
||||
let legsupport4 = legsupport1
|
||||
.rotate(Mat3::new(-1, 0, 0, 0, -1, 0, 0, 0, 1))
|
||||
.rotate_about_min(Mat3::new(-1, 0, 0, 0, -1, 0, 0, 0, 1))
|
||||
.translate(Vec3::new(width * 2 + 2, width * 2 + 2, 0));
|
||||
|
||||
let legsupports = legsupport1
|
||||
@ -1249,11 +1250,11 @@ impl Structure for GnarlingFortification {
|
||||
);
|
||||
let spikes = spike1.union(spike2);
|
||||
let spikesalt = spikes
|
||||
.rotate(Mat3::new(-1, 0, 0, 0, -1, 0, 0, 0, 1))
|
||||
.rotate_about_min(Mat3::new(-1, 0, 0, 0, -1, 0, 0, 0, 1))
|
||||
.translate(Vec3::new(26, 8, 0));
|
||||
let spikeshalf = spikes.union(spikesalt);
|
||||
let spikesotherhalf = spikeshalf
|
||||
.rotate(Mat3::new(0, -1, 0, 1, 0, 0, 0, 0, 1))
|
||||
.rotate_about_min(Mat3::new(0, -1, 0, 1, 0, 0, 0, 0, 1))
|
||||
.translate(Vec3::new(16, -9, 0));
|
||||
let spikesall = spikeshalf.union(spikesotherhalf);
|
||||
|
||||
@ -1423,13 +1424,13 @@ impl Structure for GnarlingFortification {
|
||||
1.0,
|
||||
);
|
||||
let support_2 = support_1
|
||||
.rotate(Mat3::new(1, 0, 0, 0, -1, 0, 0, 0, 1))
|
||||
.rotate_about_min(Mat3::new(1, 0, 0, 0, -1, 0, 0, 0, 1))
|
||||
.translate(Vec3::new(0, 13, 0));
|
||||
let support_3 = support_1
|
||||
.rotate(Mat3::new(-1, 0, 0, 0, 1, 0, 0, 0, 1))
|
||||
.rotate_about_min(Mat3::new(-1, 0, 0, 0, 1, 0, 0, 0, 1))
|
||||
.translate(Vec3::new(13, 0, 0));
|
||||
let support_4 = support_1
|
||||
.rotate(Mat3::new(-1, 0, 0, 0, -1, 0, 0, 0, 1))
|
||||
.rotate_about_min(Mat3::new(-1, 0, 0, 0, -1, 0, 0, 0, 1))
|
||||
.translate(Vec3::new(13, 13, 0));
|
||||
|
||||
let supports = support_1.union(support_2).union(support_3).union(support_4);
|
||||
@ -1607,22 +1608,22 @@ impl Structure for GnarlingFortification {
|
||||
));
|
||||
let skirt2 = skirt1
|
||||
.translate(Vec3::new(6, 0, 0))
|
||||
.rotate(Mat3::new(-1, 0, 0, 0, 1, 0, 0, 0, 1));
|
||||
.rotate_about_min(Mat3::new(-1, 0, 0, 0, 1, 0, 0, 0, 1));
|
||||
let skirt3 = skirt2.translate(Vec3::new(3, 0, 0));
|
||||
|
||||
let skirtside1 = skirt1.union(skirt2).union(skirt3);
|
||||
let skirtside2 = skirtside1
|
||||
.rotate(Mat3::new(0, -1, 0, 1, 0, 0, 0, 0, 1))
|
||||
.translate(Vec3::new(-1, 2, 0));
|
||||
.rotate_about_min(Mat3::new(0, -1, 0, 1, 0, 0, 0, 0, 1))
|
||||
.translate(Vec3::new(0, 1, 0));
|
||||
|
||||
let skirtcorner1 = skirtside1.union(skirtside2);
|
||||
let skirtcorner2 = skirtcorner1
|
||||
.rotate(Mat3::new(-1, 0, 0, 0, -1, 0, 0, 0, 1))
|
||||
.translate(Vec3::new(13, 11, 0));
|
||||
.rotate_about_min(Mat3::new(-1, 0, 0, 0, -1, 0, 0, 0, 1))
|
||||
.translate(Vec3::new(11, 11, 0));
|
||||
|
||||
let skirt1 = skirtcorner1.union(skirtcorner2);
|
||||
let skirt2 = skirt1
|
||||
.rotate(Mat3::new(1, 0, 0, 0, -1, 0, 0, 0, 1))
|
||||
.rotate_about_min(Mat3::new(1, 0, 0, 0, -1, 0, 0, 0, 1))
|
||||
.translate(Vec3::new(0, 11, 6));
|
||||
|
||||
let skirt = skirt1.union(skirt2).union(roof);
|
||||
|
Loading…
Reference in New Issue
Block a user