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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy