Merge branch 'isse/primitive-fixes' into 'master'

Primitive fixes

See merge request veloren/veloren!3016
This commit is contained in:
Treeco 2021-11-27 19:02:12 +00:00
commit 3a998ca5b9
4 changed files with 87 additions and 82 deletions

View File

@ -47,11 +47,10 @@ pub enum Primitive {
Prefab(Box<PrefabStructure>),
// Combinators
And(Id<Primitive>, Id<Primitive>),
Or(Id<Primitive>, Id<Primitive>),
Xor(Id<Primitive>, Id<Primitive>),
Intersect(Id<Primitive>, Id<Primitive>),
Union(Id<Primitive>, Id<Primitive>),
// Not commutative
Diff(Id<Primitive>, Id<Primitive>),
Without(Id<Primitive>, Id<Primitive>),
// Operators
Rotate(Id<Primitive>, Mat3<i32>),
Translate(Id<Primitive>, Vec3<i32>),
@ -59,20 +58,16 @@ pub enum Primitive {
}
impl Primitive {
pub fn and(a: impl Into<Id<Primitive>>, b: impl Into<Id<Primitive>>) -> Self {
Self::And(a.into(), b.into())
pub fn intersect(a: impl Into<Id<Primitive>>, b: impl Into<Id<Primitive>>) -> Self {
Self::Intersect(a.into(), b.into())
}
pub fn or(a: impl Into<Id<Primitive>>, b: impl Into<Id<Primitive>>) -> Self {
Self::Or(a.into(), b.into())
pub fn union(a: impl Into<Id<Primitive>>, b: impl Into<Id<Primitive>>) -> Self {
Self::Union(a.into(), b.into())
}
pub fn xor(a: impl Into<Id<Primitive>>, b: impl Into<Id<Primitive>>) -> Self {
Self::Xor(a.into(), b.into())
}
pub fn diff(a: impl Into<Id<Primitive>>, b: impl Into<Id<Primitive>>) -> Self {
Self::Diff(a.into(), b.into())
pub fn without(a: impl Into<Id<Primitive>>, b: impl Into<Id<Primitive>>) -> Self {
Self::Without(a.into(), b.into())
}
pub fn sampling(a: impl Into<Id<Primitive>>, f: Box<dyn Fn(Vec3<i32>) -> bool>) -> Self {
@ -224,16 +219,13 @@ impl Fill {
},
Primitive::Sampling(a, f) => self.contains_at(tree, *a, pos) && f(pos),
Primitive::Prefab(p) => !matches!(p.get(pos), Err(_) | Ok(StructureBlock::None)),
Primitive::And(a, b) => {
Primitive::Intersect(a, b) => {
self.contains_at(tree, *a, pos) && self.contains_at(tree, *b, pos)
},
Primitive::Or(a, b) => {
Primitive::Union(a, b) => {
self.contains_at(tree, *a, pos) || self.contains_at(tree, *b, pos)
},
Primitive::Xor(a, b) => {
self.contains_at(tree, *a, pos) ^ self.contains_at(tree, *b, pos)
},
Primitive::Diff(a, b) => {
Primitive::Without(a, b) => {
self.contains_at(tree, *a, pos) && !self.contains_at(tree, *b, pos)
},
Primitive::Rotate(prim, mat) => {
@ -338,17 +330,17 @@ impl Fill {
},
Primitive::Sampling(a, _) => self.get_bounds_inner(tree, *a)?,
Primitive::Prefab(p) => p.get_bounds(),
Primitive::And(a, b) => or_zip_with(
Primitive::Intersect(a, b) => or_zip_with(
self.get_bounds_inner(tree, *a),
self.get_bounds_inner(tree, *b),
|a, b| a.intersection(b),
)?,
Primitive::Or(a, b) | Primitive::Xor(a, b) => or_zip_with(
Primitive::Union(a, b) => or_zip_with(
self.get_bounds_inner(tree, *a),
self.get_bounds_inner(tree, *b),
|a, b| a.union(b),
)?,
Primitive::Diff(a, _) => self.get_bounds_inner(tree, *a)?,
Primitive::Without(a, _) => self.get_bounds_inner(tree, *a)?,
Primitive::Rotate(prim, mat) => {
let aabb = self.get_bounds_inner(tree, *prim)?;
let extent = *mat * Vec3::from(aabb.size());
@ -412,17 +404,17 @@ impl Painter {
inset,
dir: 0,
})
.union(self.prim(Primitive::Ramp {
.intersect(self.prim(Primitive::Ramp {
aabb,
inset,
dir: 1,
}))
.union(self.prim(Primitive::Ramp {
.intersect(self.prim(Primitive::Ramp {
aabb,
inset,
dir: 2,
}))
.union(self.prim(Primitive::Ramp {
.intersect(self.prim(Primitive::Ramp {
aabb,
inset,
dir: 3,
@ -453,7 +445,15 @@ impl<'a> From<PrimitiveRef<'a>> for Id<Primitive> {
impl<'a> PrimitiveRef<'a> {
pub fn union(self, other: impl Into<Id<Primitive>>) -> PrimitiveRef<'a> {
self.painter.prim(Primitive::and(self, other))
self.painter.prim(Primitive::union(self, other))
}
pub fn intersect(self, other: impl Into<Id<Primitive>>) -> PrimitiveRef<'a> {
self.painter.prim(Primitive::intersect(self, other))
}
pub fn without(self, other: impl Into<Id<Primitive>>) -> PrimitiveRef<'a> {
self.painter.prim(Primitive::without(self, other))
}
pub fn fill(self, fill: Fill) { self.painter.fill(self, fill); }
@ -498,7 +498,7 @@ pub fn aabb_corners<F: FnMut(Primitive) -> Id<Primitive>>(
min: aabb.min + vec,
max: aabb.max - vec,
}));
prim(Primitive::Diff(ret, sub))
prim(Primitive::Without(ret, sub))
};
let mut ret = prim(Primitive::Aabb(aabb));
ret = f(prim, ret, Vec3::new(1, 0, 0));

View File

@ -103,7 +103,7 @@ impl Structure for Castle {
}));
painter.fill(wall, Fill::Brick(BlockKind::Rock, wall_rgb, 12));
let sides = painter.prim(Primitive::or(parapet, parapet2));
let sides = painter.prim(Primitive::union(parapet, parapet2));
painter.fill(sides, Fill::Brick(BlockKind::Rock, wall_rgb, 12));
if (x + y).is_odd() {
painter.fill(
@ -163,7 +163,7 @@ impl Structure for Castle {
}));
painter.fill(
painter.prim(Primitive::or(tower_upper, tower_upper2)),
painter.prim(Primitive::union(tower_upper, tower_upper2)),
Fill::Brick(BlockKind::Rock, wall_rgb, 12),
);
@ -198,10 +198,10 @@ impl Structure for Castle {
.with_z(tower_total_height + parapet_height),
}));
painter.fill(
painter.prim(Primitive::xor(tower_top_outer, tower_top_inner)),
Fill::Brick(BlockKind::Rock, wall_rgb, 12),
);
tower_top_outer
.union(tower_top_inner)
.without(tower_top_outer.intersect(tower_top_inner))
.fill(Fill::Brick(BlockKind::Rock, wall_rgb, 12));
for x in (wpos.x..wpos.x + ts).step_by(2 * parapet_gap as usize) {
painter.fill(

View File

@ -1137,7 +1137,7 @@ impl Floor {
min: floor_aabb.min.with_x(j - 1),
max: floor_aabb.max.with_x(j),
}));
lighting_mask_x = painter.prim(Primitive::or(plane, lighting_mask_x));
lighting_mask_x = painter.prim(Primitive::union(plane, lighting_mask_x));
}
let mut lighting_mask_y = painter.prim(Primitive::Empty);
let floor_h = floor_aabb.max.y - floor_aabb.min.y;
@ -1147,9 +1147,11 @@ impl Floor {
min: floor_aabb.min.with_y(j - 1),
max: floor_aabb.max.with_y(j),
}));
lighting_mask_y = painter.prim(Primitive::or(plane, lighting_mask_y));
lighting_mask_y = painter.prim(Primitive::union(plane, lighting_mask_y));
}
painter.prim(Primitive::xor(lighting_mask_x, lighting_mask_y))
lighting_mask_x
.union(lighting_mask_y)
.without(lighting_mask_x.intersect(lighting_mask_y))
};
// Declare collections of various disjoint primitives that need postprocessing
@ -1182,14 +1184,14 @@ impl Floor {
tile_aabr,
floor_z..floor_z + 1,
)));
let sprite_layer = painter.prim(Primitive::diff(sprite_layer, wall_contours));
let sprite_layer = painter.prim(Primitive::without(sprite_layer, wall_contours));
// Lights are 2 units above the floor, and aligned with the `lighting_mask` grid
let lighting_plane = painter.prim(Primitive::Aabb(aabr_with_z(
tile_aabr,
floor_z + 1..floor_z + 2,
)));
let lighting_plane = painter.prim(Primitive::and(lighting_plane, lighting_mask));
let lighting_plane = painter.prim(Primitive::intersect(lighting_plane, lighting_mask));
let mut chests = None;
@ -1224,11 +1226,11 @@ impl Floor {
max: (aabb.max - Vec3::new(1, 1, 0)).with_z(floor_z + i + 1),
}));
light = painter.prim(Primitive::diff(light, inner));
lights = painter.prim(Primitive::or(light, lights));
light = painter.prim(Primitive::without(light, inner));
lights = painter.prim(Primitive::union(light, lights));
}
}
lights = painter.prim(Primitive::and(lights, lighting_mask));
lights = painter.prim(Primitive::intersect(lights, lighting_mask));
stairs_bb.push(bb);
stairs.push((stair, lights));
}
@ -1261,7 +1263,7 @@ impl Floor {
tile_aabr,
floor_z - 7..floor_z,
)));
let tile_pit = painter.prim(Primitive::diff(tile_pit, wall_contours));
let tile_pit = painter.prim(Primitive::without(tile_pit, wall_contours));
painter.fill(tile_pit, Fill::Block(vacant));
// Fill with lava
@ -1269,7 +1271,7 @@ impl Floor {
tile_aabr,
floor_z - 7..floor_z - 5,
)));
let tile_lava = painter.prim(Primitive::diff(tile_lava, wall_contours));
let tile_lava = painter.prim(Primitive::without(tile_lava, wall_contours));
//pits.push(tile_pit);
//pits.push(tile_lava);
painter.fill(tile_lava, Fill::Block(lava));
@ -1323,12 +1325,12 @@ impl Floor {
let scale = (pillar_thickness + 2) as f32 / pillar_thickness as f32;
let mut lights = painter
.prim(Primitive::scale(pillar, Vec2::broadcast(scale).with_z(1.0)));
lights = painter.prim(Primitive::and(lighting_plane, lights));
lights = painter.prim(Primitive::intersect(lighting_plane, lights));
// Only add the base (and shift the lights up)
// for boss-rooms pillars
if room.kind == RoomKind::Boss {
lights = painter.prim(Primitive::translate(lights, 3 * Vec3::unit_z()));
pillar = painter.prim(Primitive::or(pillar, base));
pillar = painter.prim(Primitive::union(pillar, base));
}
pillars.push((tile_center, pillar, lights));
}
@ -1346,21 +1348,22 @@ impl Floor {
tile_aabr,
floor_z..floor_z + height,
)));
let tile_air = painter.prim(Primitive::diff(tile_air, wall_contours));
let tile_air = painter.prim(Primitive::without(tile_air, wall_contours));
painter.fill(tile_air, Fill::Block(vacant));
// Place torches on the walls with the aforementioned spacing
let sconces_layer = painter.prim(Primitive::and(tile_air, lighting_plane));
let sconces_layer = painter.prim(Primitive::and(sconces_layer, wall_contour_surface));
let sconces_layer = painter.prim(Primitive::intersect(tile_air, lighting_plane));
let sconces_layer =
painter.prim(Primitive::intersect(sconces_layer, wall_contour_surface));
painter.fill(sconces_layer, sconces_wall.clone());
// Defer chest/floor sprite placement
if let Some((chest_sprite, chest_sprite_fill)) = chests {
let chest_sprite = painter.prim(Primitive::diff(chest_sprite, wall_contours));
let chest_sprite = painter.prim(Primitive::without(chest_sprite, wall_contours));
sprites.push((chest_sprite, chest_sprite_fill));
}
let floor_sprite = painter.prim(Primitive::and(sprite_layer, floor_sprite));
let floor_sprite = painter.prim(Primitive::intersect(sprite_layer, floor_sprite));
sprites.push((floor_sprite, floor_sprite_fill.clone()));
}
@ -1394,7 +1397,7 @@ impl Floor {
// Prevent sprites from floating above the stairs
let stair_bb_up = painter.prim(Primitive::translate(*stair_bb, Vec3::unit_z()));
for (sprite, _) in sprites.iter_mut() {
*sprite = painter.prim(Primitive::diff(*sprite, stair_bb_up));
*sprite = painter.prim(Primitive::without(*sprite, stair_bb_up));
}
}
// Place the stairs themselves, and lights within the stairwells

View File

@ -320,14 +320,14 @@ impl Structure for House {
})),
),
};
let roof_front = painter.prim(Primitive::and(roof_empty, roof_front_wall));
let roof_rear = painter.prim(Primitive::and(roof_empty, roof_rear_wall));
let roof_front = painter.prim(Primitive::intersect(roof_empty, roof_front_wall));
let roof_rear = painter.prim(Primitive::intersect(roof_empty, roof_rear_wall));
painter.fill(
roof_primitive,
Fill::Block(Block::new(BlockKind::Wood, self.roof_color)),
);
painter.fill(roof_empty, Fill::Block(Block::empty()));
let roof_walls = painter.prim(Primitive::or(roof_front, roof_rear));
let roof_walls = painter.prim(Primitive::union(roof_front, roof_rear));
painter.fill(
roof_walls,
Fill::Brick(BlockKind::Wood, Rgb::new(200, 180, 150), 24),
@ -474,19 +474,19 @@ impl Structure for House {
Vec2::new(0.0, 1.0),
))
};
let rafters1 = painter.prim(Primitive::or(left_rafter, right_rafter));
let rafters2 = painter.prim(Primitive::or(rafters1, top_rafter));
let rafters1 = painter.prim(Primitive::union(left_rafter, right_rafter));
let rafters2 = painter.prim(Primitive::union(rafters1, top_rafter));
painter.fill(
painter.prim(Primitive::and(roof_beam, roof_walls)),
painter.prim(Primitive::intersect(roof_beam, roof_walls)),
Fill::Block(Block::new(BlockKind::Wood, Rgb::new(55, 25, 8))),
);
painter.fill(
painter.prim(Primitive::or(roof_beam_left, roof_beam_right)),
painter.prim(Primitive::union(roof_beam_left, roof_beam_right)),
Fill::Block(Block::new(BlockKind::Wood, Rgb::new(55, 25, 8))),
);
painter.fill(
painter.prim(Primitive::and(rafters2, roof_walls)),
painter.prim(Primitive::intersect(rafters2, roof_walls)),
Fill::Block(Block::new(BlockKind::Wood, Rgb::new(55, 25, 8))),
);
@ -598,7 +598,9 @@ impl Structure for House {
painter.fill(outer_level, wall_block_fill);
painter.fill(inner_level, Fill::Block(Block::empty()));
let walls = painter.prim(Primitive::xor(outer_level, inner_level));
let walls = outer_level
.union(inner_level)
.without(outer_level.intersect(inner_level));
// Wall Pillars
// Only upper non-stone floors have wooden beams in the walls
@ -643,7 +645,7 @@ impl Structure for House {
};
if temp.x <= self.bounds.max.x && temp.x >= self.bounds.min.x {
overhang_supports =
painter.prim(Primitive::or(overhang_supports, support));
painter.prim(Primitive::union(overhang_supports, support));
}
}
let pillar = painter.prim(Primitive::Aabb(Aabb {
@ -654,7 +656,7 @@ impl Structure for House {
+ Vec2::unit_x())
.with_z(alt + height),
}));
pillars_y = painter.prim(Primitive::or(pillars_y, pillar));
pillars_y = painter.prim(Primitive::union(pillars_y, pillar));
}
let mut pillars_x = painter.prim(Primitive::Empty);
for y in self.tile_aabr.min.y - 2..self.tile_aabr.max.y + 2 {
@ -701,7 +703,7 @@ impl Structure for House {
};
if temp.y <= self.bounds.max.y && temp.y >= self.bounds.min.y {
overhang_supports =
painter.prim(Primitive::or(overhang_supports, support));
painter.prim(Primitive::union(overhang_supports, support));
}
}
let pillar = painter.prim(Primitive::Aabb(Aabb {
@ -712,7 +714,7 @@ impl Structure for House {
+ Vec2::unit_y())
.with_z(alt + height),
}));
pillars_x = painter.prim(Primitive::or(pillars_x, pillar));
pillars_x = painter.prim(Primitive::union(pillars_x, pillar));
}
let front_wall = if self.overhang < -4 && i > 1 {
painter.prim(Primitive::Empty)
@ -769,12 +771,12 @@ impl Structure for House {
}
};
let pillars1 = if self.front % 2 == 0 {
painter.prim(Primitive::and(pillars_y, front_wall))
painter.prim(Primitive::intersect(pillars_y, front_wall))
} else {
painter.prim(Primitive::and(pillars_x, front_wall))
painter.prim(Primitive::intersect(pillars_x, front_wall))
};
let pillars2 = painter.prim(Primitive::and(pillars_x, pillars_y));
let pillars3 = painter.prim(Primitive::or(pillars1, pillars2));
let pillars2 = painter.prim(Primitive::intersect(pillars_x, pillars_y));
let pillars3 = painter.prim(Primitive::union(pillars1, pillars2));
let pillars4 = match self.front {
0 => painter.prim(Primitive::Aabb(Aabb {
min: Vec2::new(self.bounds.min.x - 1, self.bounds.min.y - 1)
@ -813,9 +815,9 @@ impl Structure for House {
.with_z(alt + previous_height + 1),
})),
};
let pillars = painter.prim(Primitive::or(pillars3, pillars4));
let pillars = painter.prim(Primitive::union(pillars3, pillars4));
painter.fill(
painter.prim(Primitive::and(walls, pillars)),
painter.prim(Primitive::intersect(walls, pillars)),
Fill::Block(Block::new(BlockKind::Wood, Rgb::new(55, 25, 8))),
);
@ -847,11 +849,11 @@ impl Structure for House {
_ => max.y < self.bounds.max.y && min.y > self.bounds.min.y,
};
if add_windows {
windows = painter.prim(Primitive::or(windows, window));
windows = painter.prim(Primitive::union(windows, window));
}
}
painter.fill(
painter.prim(Primitive::and(walls, windows)),
painter.prim(Primitive::intersect(walls, windows)),
Fill::Block(Block::air(SpriteKind::Window1).with_ori(2).unwrap()),
);
}
@ -877,11 +879,11 @@ impl Structure for House {
},
};
if add_windows {
windows = painter.prim(Primitive::or(windows, window));
windows = painter.prim(Primitive::union(windows, window));
};
}
painter.fill(
painter.prim(Primitive::and(walls, windows)),
painter.prim(Primitive::intersect(walls, windows)),
Fill::Block(Block::air(SpriteKind::Window1).with_ori(0).unwrap()),
);
}
@ -1157,13 +1159,13 @@ impl Structure for House {
.with_z(alt + previous_height + 1),
})),
};
let shed_walls = painter.prim(Primitive::or(shed_left_wall, shed_right_wall));
let shed_walls = painter.prim(Primitive::union(shed_left_wall, shed_right_wall));
painter.fill(
painter.prim(Primitive::and(shed_walls, shed_empty)),
painter.prim(Primitive::intersect(shed_walls, shed_empty)),
Fill::Brick(BlockKind::Wood, Rgb::new(200, 180, 150), 24),
);
painter.fill(
painter.prim(Primitive::and(shed_wall_beams, shed_walls)),
painter.prim(Primitive::intersect(shed_wall_beams, shed_walls)),
Fill::Block(Block::new(BlockKind::Wood, Rgb::new(55, 25, 8))),
);
@ -1366,11 +1368,11 @@ impl Structure for House {
let window_ori = if self.front % 2 == 0 { 0 } else { 2 };
if valid_dormer {
painter.fill(
painter.prim(Primitive::diff(dormer_box, shed)),
painter.prim(Primitive::without(dormer_box, shed)),
Fill::Brick(BlockKind::Wood, Rgb::new(200, 180, 150), 24),
);
painter.fill(
painter.prim(Primitive::diff(dormer_roof, shed)),
painter.prim(Primitive::without(dormer_roof, shed)),
Fill::Block(Block::new(BlockKind::Wood, self.roof_color)),
);
painter.fill(window_cavity, Fill::Block(Block::empty()));
@ -1561,7 +1563,7 @@ impl Structure for House {
// 1), }))
//},
};
painter.prim(Primitive::or(ramp, support))
painter.prim(Primitive::union(ramp, support))
} else {
let ramp = /*match self.front */{
//0 => {
@ -1641,7 +1643,7 @@ impl Structure for House {
// previous_height + 1), }))
//},
};
painter.prim(Primitive::or(ramp, support))
painter.prim(Primitive::union(ramp, support))
};
let stairwell = if i < 2 {
painter.prim(Primitive::Empty)