Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 92e3ca6

Browse files
authored
Merge pull request #9 from swiftcoder/improvements
Improvements
2 parents 9fdde73 + 82fed2e commit 92e3ca6

File tree

3 files changed

+82
-6
lines changed

3 files changed

+82
-6
lines changed

src/linear_hashed_marching_cubes.rs

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use crate::marching_cubes_impl::{get_offset, interpolate, march_cube};
1717
use crate::marching_cubes_tables::EDGE_CONNECTION;
1818
use crate::math::Vec3;
1919
use crate::morton::Morton;
20-
use crate::source::{HermiteSource, Source};
20+
use crate::source::{HermiteSource, Norm, Source};
2121
use std::collections::HashMap;
2222

2323
// Morton cube corners are ordered differently to the marching cubes tables, so remap them to match.
@@ -43,15 +43,29 @@ impl Edge {
4343
/// Extracts meshes from distance fields using marching cubes over a linear hashed octree.
4444
pub struct LinearHashedMarchingCubes {
4545
max_depth: usize,
46+
norm: Norm,
4647
}
4748

4849
impl LinearHashedMarchingCubes {
4950
/// Create a new LinearHashedMarchingCubes.
5051
///
5152
/// The depth of the internal octree will be at most `max_depth`, causing the tree to span the
52-
/// equivalent of a cubic grid at most `2.pow(max_depth)` in either direction.
53+
/// equivalent of a cubic grid at most `2.pow(max_depth)` in either direction. Distances
54+
/// will be evaluated in Euclidean space.
5355
pub fn new(max_depth: usize) -> Self {
54-
Self { max_depth }
56+
Self {
57+
max_depth,
58+
norm: Norm::Euclidean,
59+
}
60+
}
61+
62+
/// Create a new LinearHashedMarchingCubes.
63+
///
64+
/// The depth of the internal octree will be at most `max_depth`, causing the tree to span the
65+
/// equivalent of a cubic grid at most `2.pow(max_depth)` in either direction. Distances will
66+
/// be evaluated in accordance with the provided Norm.
67+
pub fn with_norm(max_depth: usize, norm: Norm) -> Self {
68+
Self { max_depth, norm }
5569
}
5670

5771
/// Extracts a mesh from the given [`Source`](../source/trait.Source.html).
@@ -119,6 +133,13 @@ impl LinearHashedMarchingCubes {
119133
self.extract_surface(&octree, &primal_vertices, indices, &mut base_index, extract);
120134
}
121135

136+
fn diagonal(&self, distance: f32) -> f32 {
137+
match self.norm {
138+
Norm::Euclidean => distance * SQRT_OF_3,
139+
Norm::Max => distance,
140+
}
141+
}
142+
122143
fn build_octree<S>(&mut self, source: &S) -> LinearHashedOctree<f32>
123144
where
124145
S: Source,
@@ -130,7 +151,7 @@ impl LinearHashedMarchingCubes {
130151
|key: Morton, distance: &f32| {
131152
let level = key.level();
132153
let size = key.size();
133-
level < 2 || (level < max_depth && distance.abs() <= size * SQRT_OF_3)
154+
level < 2 || (level < max_depth && distance.abs() <= self.diagonal(size))
134155
},
135156
|key: Morton| {
136157
let p = key.center();

src/math.rs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,30 @@ impl Vec3 {
4848
z: 1.0,
4949
}
5050
}
51+
52+
/// Create a vector by taking the absolute value of each component in this vector
53+
pub fn abs(&self) -> Self {
54+
Self {
55+
x: self.x.abs(),
56+
y: self.y.abs(),
57+
z: self.z.abs(),
58+
}
59+
}
60+
61+
/// Sum all of the components in this vector
62+
pub fn component_sum(&self) -> f32 {
63+
self.x + self.y + self.z
64+
}
65+
66+
/// Find the maximum value out of all components in this vector
67+
pub fn component_max(&self) -> f32 {
68+
self.x.max(self.y.max(self.z))
69+
}
70+
71+
/// Find the minimum value out of all components in this vector
72+
pub fn component_min(&self) -> f32 {
73+
self.x.min(self.y.min(self.z))
74+
}
5175
}
5276

5377
impl std::ops::Add for Vec3 {
@@ -81,6 +105,13 @@ impl std::ops::Mul<f32> for Vec3 {
81105
Vec3::new(self.x * other, self.y * other, self.z * other)
82106
}
83107
}
108+
impl std::ops::Mul<Vec3> for f32 {
109+
type Output = Vec3;
110+
111+
fn mul(self, other: Vec3) -> Vec3 {
112+
Vec3::new(self * other.x, self * other.y, self * other.z)
113+
}
114+
}
84115

85116
impl std::ops::Div for Vec3 {
86117
type Output = Vec3;
@@ -89,3 +120,19 @@ impl std::ops::Div for Vec3 {
89120
Vec3::new(self.x / other.x, self.y / other.y, self.z / other.z)
90121
}
91122
}
123+
124+
impl std::ops::Div<f32> for Vec3 {
125+
type Output = Vec3;
126+
127+
fn div(self, other: f32) -> Vec3 {
128+
Vec3::new(self.x / other, self.y / other, self.z / other)
129+
}
130+
}
131+
132+
impl std::ops::Div<Vec3> for f32 {
133+
type Output = Vec3;
134+
135+
fn div(self, other: Vec3) -> Vec3 {
136+
Vec3::new(self / other.x, self / other.y, self / other.z)
137+
}
138+
}

src/source.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,19 @@
1414

1515
use crate::math::Vec3;
1616

17+
/// The context in which signed distance fields should be evaluated
18+
pub enum Norm {
19+
/// The L^2 or Euclidean norm is the one you are used to, i.e. where l = sqrt(x^2 + y^2 + z^2).
20+
Euclidean,
21+
/// The L^∞ or Max norm represents Manhattan/Taxicab distance, i.e. l = max(|x|, |y|, |z|).
22+
Max,
23+
}
24+
1725
/// A source capable of sampling a signed distance field at discrete coordinates.
1826
pub trait Source {
1927
/// Samples the distance field at the given (x, y, z) coordinates.
2028
///
21-
/// Must return the signed distance (i.e. negative for coodinates inside the surface),
29+
/// Must return the signed distance (i.e. negative for coordinates inside the surface),
2230
/// as our Marching Cubes implementation will evaluate the surface at the zero-crossing.
2331
fn sample(&self, x: f32, y: f32, z: f32) -> f32;
2432
}
@@ -33,7 +41,7 @@ pub trait HermiteSource: Source {
3341

3442
/// Adapts a `Source` to a `HermiteSource` by deriving normals from the surface via central differencing
3543
pub struct CentralDifference<S: Source> {
36-
source: S,
44+
pub source: S,
3745
epsilon: f32,
3846
}
3947

0 commit comments

Comments
 (0)