Skip to content

Commit cd711d2

Browse files
committed
Implemented voxel-mesh interaction
1 parent b54013b commit cd711d2

File tree

1 file changed

+88
-10
lines changed

1 file changed

+88
-10
lines changed

xlb/operator/boundary_masker/mesh_boundary_masker.py

+88-10
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,88 @@ def index_to_position(index: wp.vec3i):
5959
pos = ijk + wp.vec3(0.5, 0.5, 0.5) # cell center
6060
return pos
6161

62+
# Function to precompute useful values per triangle, assuming spacing is (1,1,1)
63+
@wp.func
64+
def pre_compute(
65+
verts: wp.mat33f, # triangle vertices
66+
normal: wp.vec3f, # triangle normal
67+
):
68+
corner = wp.vec3f(float(normal[0] > 0.0), float(normal[1] > 0.0), float(normal[2] > 0.0))
69+
70+
dist1 = wp.dot(normal, corner - verts[0])
71+
dist2 = wp.dot(normal, wp.vec3f(1.0, 1.0, 1.0) - corner - verts[0])
72+
73+
edges = wp.transpose(wp.mat33(verts[1] - verts[0], verts[2] - verts[1], verts[0] - verts[2]))
74+
normal_edge0 = wp.mat33f(0.0)
75+
normal_edge1 = wp.mat33f(0.0)
76+
dist_edge = wp.mat33f(0.0)
77+
78+
for axis0 in range(0, 3):
79+
axis2 = (axis0 + 2) % 3
80+
81+
sgn = 1.0
82+
if normal[axis2] < 0.0:
83+
sgn = -1.0
84+
85+
for i in range(0, 3):
86+
normal_edge0[i][axis0] = -1.0 * sgn * edges[i][axis0]
87+
normal_edge1[i][axis0] = sgn * edges[i][axis0]
88+
89+
dist_edge[i][axis0] = (
90+
-1.0 * (normal_edge0[i][axis0] * verts[i][axis0] + normal_edge1[i][axis0] * verts[i][axis0])
91+
+ wp.max(0.0, normal_edge0[i][axis0])
92+
+ wp.max(0.0, normal_edge1[i][axis0])
93+
)
94+
95+
return dist1, dist2, normal_edge0, normal_edge1, dist_edge
96+
97+
# Check whether this triangle intersects the unit cube at position low
98+
@wp.func
99+
def triangle_box_intersect(
100+
low: wp.vec3f,
101+
normal: wp.vec3f,
102+
dist1: wp.float32,
103+
dist2: wp.float32,
104+
normal_edge0: wp.mat33f,
105+
normal_edge1: wp.mat33f,
106+
dist_edge: wp.mat33f,
107+
):
108+
if (wp.dot(normal, low) + dist1) * (wp.dot(normal, low) + dist2) <= 0.0:
109+
intersect = True
110+
# Loop over primary axis for projection
111+
for axis0 in range(0, 3):
112+
axis1 = (axis0 + 1) % 3
113+
for i in range(0, 3):
114+
intersect = intersect and (
115+
normal_edge0[i][axis0] * low[axis0] + normal_edge1[i][axis0] * low[axis1] + dist_edge[i][axis0] >= 0.0
116+
)
117+
118+
return intersect
119+
else:
120+
return False
121+
122+
@wp.func
123+
def mesh_voxel_intersect(mesh_id: wp.uint64, low: wp.vec3):
124+
query = wp.mesh_query_aabb(mesh_id, low, low + wp.vec3f(1.0, 1.0, 1.0))
125+
126+
for f in query:
127+
v0 = wp.mesh_eval_position(mesh_id, f, 1.0, 0.0)
128+
v1 = wp.mesh_eval_position(mesh_id, f, 0.0, 1.0)
129+
v2 = wp.mesh_eval_position(mesh_id, f, 0.0, 0.0)
130+
normal = wp.mesh_eval_face_normal(mesh_id, f)
131+
132+
verts = wp.transpose(wp.mat33f(v0, v1, v2))
133+
134+
# TODO: run this on triangles in advance
135+
dist1, dist2, normal_edge0, normal_edge1, dist_edge = pre_compute(verts=verts, normal=normal)
136+
137+
if triangle_box_intersect(
138+
low=low, normal=normal, dist1=dist1, dist2=dist2, normal_edge0=normal_edge0, normal_edge1=normal_edge1, dist_edge=dist_edge
139+
):
140+
return True
141+
142+
return False
143+
62144
# Construct the warp kernel
63145
# Do voxelization mesh query (warp.mesh_query_aabb) to find solid voxels
64146
# - this gives an approximate 1 voxel thick surface around mesh
@@ -79,20 +161,16 @@ def kernel(
79161
pos_bc_cell = index_to_position(index)
80162
half = wp.vec3(0.5, 0.5, 0.5)
81163

82-
vox_query = wp.mesh_query_aabb(mesh_id, pos_bc_cell - half, pos_bc_cell + half)
83-
face = wp.int32(0)
84-
if wp.mesh_query_aabb_next(vox_query, face):
164+
if mesh_voxel_intersect(mesh_id=mesh_id, low=pos_bc_cell - half):
85165
# Make solid voxel
86166
bc_mask[0, index[0], index[1], index[2]] = wp.uint8(255)
87167
else:
88168
# Find the fractional distance to the mesh in each direction
89169
for l in range(1, _q):
90170
_dir = wp.vec3f(_c_float[0, l], _c_float[1, l], _c_float[2, l])
91171

92-
# Check to see if this neighbor is solid
93-
vox_query_dir = wp.mesh_query_aabb(mesh_id, pos_bc_cell + _dir - half, pos_bc_cell + _dir + half)
94-
face = wp.int32(0)
95-
if wp.mesh_query_aabb_next(vox_query_dir, face):
172+
# Check to see if this neighbor is solid - this is super inefficient TODO: make it way better
173+
if mesh_voxel_intersect(mesh_id=mesh_id, low=pos_bc_cell + _dir - half):
96174
# We know we have a solid neighbor
97175
# Set the boundary id and missing_mask
98176
bc_mask[0, index[0], index[1], index[2]] = wp.uint8(id_number)
@@ -109,9 +187,9 @@ def warp_implementation(
109187
):
110188
assert bc.mesh_vertices is not None, f'Please provide the mesh vertices for {bc.__class__.__name__} BC using keyword "mesh_vertices"!'
111189
assert bc.indices is None, f"Please use IndicesBoundaryMasker operator if {bc.__class__.__name__} is imposed on known indices of the grid!"
112-
assert (
113-
bc.mesh_vertices.shape[1] == self.velocity_set.d
114-
), "Mesh points must be reshaped into an array (N, 3) where N indicates number of points!"
190+
assert bc.mesh_vertices.shape[1] == self.velocity_set.d, (
191+
"Mesh points must be reshaped into an array (N, 3) where N indicates number of points!"
192+
)
115193
mesh_vertices = bc.mesh_vertices
116194
id_number = bc.id
117195

0 commit comments

Comments
 (0)