@@ -59,6 +59,88 @@ def index_to_position(index: wp.vec3i):
59
59
pos = ijk + wp .vec3 (0.5 , 0.5 , 0.5 ) # cell center
60
60
return pos
61
61
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
+
62
144
# Construct the warp kernel
63
145
# Do voxelization mesh query (warp.mesh_query_aabb) to find solid voxels
64
146
# - this gives an approximate 1 voxel thick surface around mesh
@@ -79,20 +161,16 @@ def kernel(
79
161
pos_bc_cell = index_to_position (index )
80
162
half = wp .vec3 (0.5 , 0.5 , 0.5 )
81
163
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 ):
85
165
# Make solid voxel
86
166
bc_mask [0 , index [0 ], index [1 ], index [2 ]] = wp .uint8 (255 )
87
167
else :
88
168
# Find the fractional distance to the mesh in each direction
89
169
for l in range (1 , _q ):
90
170
_dir = wp .vec3f (_c_float [0 , l ], _c_float [1 , l ], _c_float [2 , l ])
91
171
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 ):
96
174
# We know we have a solid neighbor
97
175
# Set the boundary id and missing_mask
98
176
bc_mask [0 , index [0 ], index [1 ], index [2 ]] = wp .uint8 (id_number )
@@ -109,9 +187,9 @@ def warp_implementation(
109
187
):
110
188
assert bc .mesh_vertices is not None , f'Please provide the mesh vertices for { bc .__class__ .__name__ } BC using keyword "mesh_vertices"!'
111
189
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
+ )
115
193
mesh_vertices = bc .mesh_vertices
116
194
id_number = bc .id
117
195
0 commit comments