@@ -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