Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
OpenDAS
cubvh
Commits
22e3e37f
Commit
22e3e37f
authored
Apr 06, 2025
by
ashawkey
Browse files
better watertight mesh extraction example
parent
8f0c777c
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
39 additions
and
19 deletions
+39
-19
.gitignore
.gitignore
+2
-2
readme.md
readme.md
+1
-1
test/extract_mesh_watertight.py
test/extract_mesh_watertight.py
+36
-16
No files found.
.gitignore
View file @
22e3e37f
...
@@ -3,5 +3,5 @@ build/
...
@@ -3,5 +3,5 @@ build/
*.egg-info/
*.egg-info/
*.so
*.so
.vs/
.vs/
*.ply
eigen*/
eigen*/
output/
\ No newline at end of file
\ No newline at end of file
readme.md
View file @
22e3e37f
...
@@ -93,7 +93,7 @@ occ = udf < 2 / resolution # tolerance 2 voxels
...
@@ -93,7 +93,7 @@ occ = udf < 2 / resolution # tolerance 2 voxels
empty_mask
=
morphology
.
flood
(
occ
,
(
0
,
0
,
0
),
connectivity
=
1
)
# flood from the corner, which is for sure empty
empty_mask
=
morphology
.
flood
(
occ
,
(
0
,
0
,
0
),
connectivity
=
1
)
# flood from the corner, which is for sure empty
occ
=
~
empty_mask
occ
=
~
empty_mask
```
```
Check
[
`test/extract_mesh_
occupancy
.py`
](
test/extract_mesh_
occupancy
.py
)
for more details.
Check
[
`test/extract_mesh_
watertight
.py`
](
test/extract_mesh_
watertight
.py
)
for more details.
**Renderer:**
**Renderer:**
...
...
test/extract_mesh_
occupancy
.py
→
test/extract_mesh_
watertight
.py
View file @
22e3e37f
import
os
import
os
import
zlib
import
zlib
import
glob
import
tqdm
import
time
import
time
import
numpy
as
np
import
torch
import
cubvh
import
mcubes
import
mcubes
import
trimesh
import
trimesh
import
argparse
import
argparse
import
numpy
as
np
from
skimage
import
morphology
import
torch
import
cubvh
import
kiui
import
kiui
from
kiui.mesh
import
Mesh
from
kiui.mesh
import
Mesh
from
skimage
import
morphology
"""
Extract watertight mesh from a arbitrary mesh by UDF expansion and floodfill.
"""
parser
=
argparse
.
ArgumentParser
()
parser
=
argparse
.
ArgumentParser
()
parser
.
add_argument
(
'
m
esh'
,
type
=
str
)
parser
.
add_argument
(
'
t
es
t_pat
h'
,
type
=
str
)
parser
.
add_argument
(
'--res'
,
type
=
int
,
default
=
512
)
parser
.
add_argument
(
'--res'
,
type
=
int
,
default
=
512
)
parser
.
add_argument
(
'--workspace'
,
type
=
str
,
default
=
'output'
)
opt
=
parser
.
parse_args
()
opt
=
parser
.
parse_args
()
device
=
torch
.
device
(
'cuda'
)
device
=
torch
.
device
(
'cuda'
)
...
@@ -37,6 +42,7 @@ def run(path):
...
@@ -37,6 +42,7 @@ def run(path):
t0
=
time
.
time
()
t0
=
time
.
time
()
BVH
=
cubvh
.
cuBVH
(
mesh
.
v
,
mesh
.
f
)
BVH
=
cubvh
.
cuBVH
(
mesh
.
v
,
mesh
.
f
)
print
(
'BVH build time:'
,
time
.
time
()
-
t0
)
print
(
'BVH build time:'
,
time
.
time
()
-
t0
)
eps
=
2
/
opt
.
res
# naive sdf
# naive sdf
# sdf, _, _ = BVH.signed_distance(points.view(-1, 3), return_uvw=False, mode='raystab') # some mesh may not be watertight...
# sdf, _, _ = BVH.signed_distance(points.view(-1, 3), return_uvw=False, mode='raystab') # some mesh may not be watertight...
...
@@ -48,13 +54,20 @@ def run(path):
...
@@ -48,13 +54,20 @@ def run(path):
udf
,
_
,
_
=
BVH
.
unsigned_distance
(
points
.
view
(
-
1
,
3
),
return_uvw
=
False
)
udf
,
_
,
_
=
BVH
.
unsigned_distance
(
points
.
view
(
-
1
,
3
),
return_uvw
=
False
)
print
(
'UDF time:'
,
time
.
time
()
-
t0
)
print
(
'UDF time:'
,
time
.
time
()
-
t0
)
udf
=
udf
.
cpu
().
numpy
().
reshape
(
opt
.
res
,
opt
.
res
,
opt
.
res
)
udf
=
udf
.
cpu
().
numpy
().
reshape
(
opt
.
res
,
opt
.
res
,
opt
.
res
)
occ
=
udf
<
2
/
opt
.
r
es
# tolerance 2 voxels
occ
=
udf
<
e
p
s
# tolerance 2 voxels
t0
=
time
.
time
()
t0
=
time
.
time
()
empty_mask
=
morphology
.
flood
(
occ
,
(
0
,
0
,
0
),
connectivity
=
1
)
# flood from the corner, which is for sure empty
empty_mask
=
morphology
.
flood
(
occ
,
(
0
,
0
,
0
),
connectivity
=
1
)
# flood from the corner, which is for sure empty
print
(
'Floodfill time:'
,
time
.
time
()
-
t0
)
print
(
'Floodfill time:'
,
time
.
time
()
-
t0
)
# binary occupancy
occ
=
~
empty_mask
occ
=
~
empty_mask
# truncated SDF
sdf
=
udf
-
eps
# inner is negative
inner_mask
=
occ
&
(
sdf
>
0
)
sdf
[
inner_mask
]
*=
-
1
# # packbits and compress
# # packbits and compress
# occ = occ.astype(np.uint8).reshape(-1)
# occ = occ.astype(np.uint8).reshape(-1)
# occ = np.packbits(occ)
# occ = np.packbits(occ)
...
@@ -70,15 +83,22 @@ def run(path):
...
@@ -70,15 +83,22 @@ def run(path):
# occ = np.unpackbits(occ, count=opt.res**3).reshape(opt.res, opt.res, opt.res)
# occ = np.unpackbits(occ, count=opt.res**3).reshape(opt.res, opt.res, opt.res)
# marching cubes
# marching cubes
occ
=
occ
.
reshape
(
opt
.
res
,
opt
.
res
,
opt
.
res
)
t0
=
time
.
time
()
t0
=
time
.
time
()
verts
,
faces
=
mcubes
.
marching_cubes
(
occ
,
0.5
)
vertices
,
triangles
=
mcubes
.
marching_cubes
(
sdf
,
0
)
# smoothed_occ = mcubes.smooth(occ, method='constrained') # very slow
vertices
=
vertices
/
(
sdf
.
shape
[
-
1
]
-
1.0
)
*
2
-
1
# verts, faces = mcubes.marching_cubes(smoothed_occ, 0)
vertices
=
vertices
.
astype
(
np
.
float32
)
triangles
=
triangles
.
astype
(
np
.
int32
)
watertight_mesh
=
trimesh
.
Trimesh
(
vertices
,
triangles
)
print
(
'MC time:'
,
time
.
time
()
-
t0
)
print
(
'MC time:'
,
time
.
time
()
-
t0
)
verts
=
verts
/
(
opt
.
res
-
1
)
*
2
-
1
name
=
os
.
path
.
splitext
(
os
.
path
.
basename
(
path
))[
0
]
mesh
=
trimesh
.
Trimesh
(
vertices
=
verts
,
faces
=
faces
)
watertight_mesh
.
export
(
f
'
{
opt
.
workspace
}
/
{
name
}
.obj'
)
mesh
.
export
(
os
.
path
.
basename
(
path
).
split
(
'.'
)[
0
]
+
'.ply'
)
os
.
makedirs
(
opt
.
workspace
,
exist_ok
=
True
)
run
(
opt
.
mesh
)
if
os
.
path
.
isdir
(
opt
.
test_path
):
\ No newline at end of file
file_paths
=
glob
.
glob
(
os
.
path
.
join
(
opt
.
test_path
,
"*"
))
for
path
in
tqdm
.
tqdm
(
file_paths
):
run
(
path
)
else
:
run
(
opt
.
test_path
)
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment