From 3915aa7aace77331f6290e23a6c4d6de5eabe9dd Mon Sep 17 00:00:00 2001 From: jshipsey Date: Fri, 24 Sep 2021 00:28:17 -0400 Subject: [PATCH] support for hollow voxels ty zesterer --- common/src/figure/cell.rs | 23 +++++++++++++++++------ common/src/figure/mod.rs | 20 +++++++++++++++----- voxygen/src/scene/figure/load.rs | 6 +++--- 3 files changed, 35 insertions(+), 14 deletions(-) diff --git a/common/src/figure/cell.rs b/common/src/figure/cell.rs index 2cb7ad6e4c..63ddb3d81d 100644 --- a/common/src/figure/cell.rs +++ b/common/src/figure/cell.rs @@ -5,24 +5,28 @@ use vek::*; const GLOWY: u8 = 1 << 1; const SHINY: u8 = 1 << 2; +const HOLLOW: u8 = 1 << 3; #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub struct CellData { pub col: Rgb, - pub attr: NonZeroU8, // 1 = glowy, 2 = shiny + pub attr: NonZeroU8, // 1 = glowy, 2 = shiny, 3 = hollow } impl CellData { - pub(super) fn new(col: Rgb, glowy: bool, shiny: bool) -> Self { + pub(super) fn new(col: Rgb, glowy: bool, shiny: bool, hollow: bool) -> Self { CellData { col, - attr: NonZeroU8::new(1 + glowy as u8 * GLOWY + shiny as u8 * SHINY).unwrap(), + attr: NonZeroU8::new( + 1 + glowy as u8 * GLOWY + shiny as u8 * SHINY + hollow as u8 * HOLLOW, + ) + .unwrap(), } } } impl Default for CellData { - fn default() -> Self { Self::new(Rgb::broadcast(255), false, false) } + fn default() -> Self { Self::new(Rgb::broadcast(255), false, false, false) } } /// A type representing a single voxel in a figure. @@ -33,8 +37,8 @@ pub enum Cell { } impl Cell { - pub fn new(col: Rgb, glowy: bool, shiny: bool) -> Self { - Cell::Filled(CellData::new(col, glowy, shiny)) + pub fn new(col: Rgb, glowy: bool, shiny: bool, hollow: bool) -> Self { + Cell::Filled(CellData::new(col, glowy, shiny, hollow)) } pub fn get_color(&self) -> Option> { @@ -57,6 +61,13 @@ impl Cell { Cell::Empty => false, } } + + pub fn is_hollow(&self) -> bool { + match self { + Cell::Filled(data) => data.attr.get() & HOLLOW != 0, + Cell::Empty => false, + } + } } impl Vox for Cell { diff --git a/common/src/figure/mod.rs b/common/src/figure/mod.rs index b16d43730f..c9475b807c 100644 --- a/common/src/figure/mod.rs +++ b/common/src/figure/mod.rs @@ -67,6 +67,7 @@ impl Segment { color, (13..16).contains(&voxel.i), // Glowy (8..13).contains(&voxel.i), // Shiny + voxel.i == 16, // Hollow ), ) .unwrap(); @@ -93,8 +94,14 @@ impl Segment { /// Transform cell colors pub fn map_rgb(self, transform: impl Fn(Rgb) -> Rgb) -> Self { self.map(|cell| { - cell.get_color() - .map(|rgb| Cell::new(transform(rgb), cell.is_glowy(), cell.is_shiny())) + cell.get_color().map(|rgb| { + Cell::new( + transform(rgb), + cell.is_glowy(), + cell.is_shiny(), + cell.is_hollow(), + ) + }) }) } } @@ -119,7 +126,9 @@ impl DynaUnionizer { } } - pub fn unify(self) -> (Dyna, Vec3) { + pub fn unify(self) -> (Dyna, Vec3) { self.unify_with(|v| v) } + + pub fn unify_with(self, mut f: impl FnMut(V) -> V) -> (Dyna, Vec3) { if self.0.is_empty() { return (Dyna::filled(Vec3::zero(), V::empty(), ()), Vec3::zero()); } @@ -140,7 +149,7 @@ impl DynaUnionizer { for (dyna, offset) in self.0 { for (pos, vox) in dyna.full_vol_iter() { if !vox.is_empty() { - combined.set(origin + offset + pos, *vox).unwrap(); + combined.set(origin + offset + pos, f(*vox)).unwrap(); } } } @@ -157,7 +166,7 @@ impl MatSegment { for (pos, vox) in self.full_vol_iter() { let data = match vox { MatCell::None => continue, - MatCell::Mat(mat) => CellData::new(map(*mat), false, false), + MatCell::Mat(mat) => CellData::new(map(*mat), false, false, false), MatCell::Normal(data) => *data, }; vol.set(pos, Cell::Filled(data)).unwrap(); @@ -221,6 +230,7 @@ impl MatSegment { color, (13..16).contains(&index), (8..13).contains(&index), + index == 16, // Hollow )) }, }; diff --git a/voxygen/src/scene/figure/load.rs b/voxygen/src/scene/figure/load.rs index eefe2780b7..a249148052 100644 --- a/voxygen/src/scene/figure/load.rs +++ b/voxygen/src/scene/figure/load.rs @@ -22,7 +22,8 @@ use common::{ }, theropod::{self, BodyType as TBodyType, Species as TSpecies}, }, - figure::{DynaUnionizer, MatSegment, Material, Segment}, + figure::{Cell, DynaUnionizer, MatSegment, Material, Segment}, + vol::Vox, }; use hashbrown::HashMap; use serde::Deserialize; @@ -317,8 +318,7 @@ impl HumHeadSpec { .maybe_add(beard) .maybe_add(accessory) .maybe_add(helmet) - .unify(); - + .unify_with(|v| if v.is_hollow() { Cell::empty() } else { v }); ( head, Vec3::from(spec.offset) + origin_offset.map(|e| e as f32 * -1.0),