27
27
from .types import GeomType
28
28
from .types import Model
29
29
from .types import vec5
30
+ from .types import vec8f
31
+ from .types import vec8i
30
32
from .util_misc import halton
31
33
from .warp_util import event_scope
32
34
@@ -47,9 +49,12 @@ class AABB:
47
49
48
50
@wp .struct
49
51
class VolumeData :
50
- volume_id : wp .uint64
51
52
center : wp .vec3
52
53
half_size : wp .vec3
54
+ oct_aabb : wp .array2d (dtype = wp .vec3 )
55
+ oct_child : wp .array (dtype = vec8i )
56
+ oct_coeff : wp .array (dtype = vec8f )
57
+ valid : bool = False
53
58
54
59
55
60
@wp .struct
@@ -68,20 +73,12 @@ class MeshData:
68
73
valid : bool = False
69
74
70
75
71
- @wp .func
72
- def get_volume_data (volume_id : wp .uint64 , center : wp .vec3 , half_size : wp .vec3 ) -> VolumeData :
73
- volume_data = VolumeData ()
74
- volume_data .volume_id = volume_id
75
- volume_data .center = center
76
- volume_data .half_size = half_size
77
- return volume_data
78
-
79
-
80
76
@wp .func
81
77
def get_sdf_params (
82
78
# Model:
83
- volume_ids : wp .array (dtype = wp .uint64 ),
84
79
oct_aabb : wp .array2d (dtype = wp .vec3 ),
80
+ oct_child : wp .array (dtype = vec8i ),
81
+ oct_coeff : wp .array (dtype = vec8f ),
85
82
plugin : wp .array (dtype = int ),
86
83
plugin_attr : wp .array (dtype = wp .vec3f ),
87
84
# In:
@@ -92,17 +89,19 @@ def get_sdf_params(
92
89
) -> Tuple [wp .vec3 , int , VolumeData , MeshData ]:
93
90
attributes = g_size
94
91
plugin_index = - 1
95
- volume_data = get_volume_data ( wp . uint64 ( 0 ), wp . vec3 ( 0.0 ), wp . vec3 ( 0.0 ) )
92
+ volume_data = VolumeData ( )
96
93
97
94
if g_type == int (GeomType .SDF .value ) and plugin_id != - 1 :
98
95
attributes = plugin_attr [plugin_id ]
99
96
plugin_index = plugin [plugin_id ]
100
97
101
98
elif g_type == int (GeomType .SDF .value ) and mesh_id != - 1 :
102
- volume_id = volume_ids [mesh_id ]
103
- center = oct_aabb [mesh_id , 0 ]
104
- half_size = oct_aabb [mesh_id , 1 ]
105
- volume_data = get_volume_data (volume_id , center , half_size )
99
+ volume_data .center = oct_aabb [mesh_id , 0 ]
100
+ volume_data .half_size = oct_aabb [mesh_id , 1 ]
101
+ volume_data .oct_aabb = oct_aabb
102
+ volume_data .oct_child = oct_child
103
+ volume_data .oct_coeff = oct_coeff
104
+ volume_data .valid = True
106
105
107
106
return attributes , plugin_index , volume_data , MeshData ()
108
107
@@ -223,22 +222,73 @@ def user_sdf_grad(p: wp.vec3, attr: wp.vec3, sdf_type: int) -> wp.vec3:
223
222
224
223
225
224
@wp .func
226
- def sample_volume_sdf (xyz : wp .vec3 , volume_data : VolumeData ) -> float :
227
- center = volume_data .center
228
- half_size = volume_data .half_size
225
+ def find_oct (
226
+ oct_aabb : wp .array2d (dtype = wp .vec3 ), oct_child : wp .array (dtype = vec8i ), p : wp .vec3 , grad : bool
227
+ ) -> Tuple [int , Tuple [vec8f , vec8f , vec8f ]]:
228
+ stack = int (0 )
229
+ niter = int (100 )
230
+ rx = vec8f (0.0 )
231
+ ry = vec8f (0.0 )
232
+ rz = vec8f (0.0 )
233
+
234
+ while niter > 0 :
235
+ niter -= 1
236
+ node = stack
237
+
238
+ if node == - 1 :
239
+ wp .printf ("ERROR: Invalid node number\n " )
240
+ return - 1 , (rx , ry , rz )
241
+
242
+ vmin = oct_aabb [node , 0 ] - oct_aabb [node , 1 ]
243
+ vmax = oct_aabb [node , 0 ] + oct_aabb [node , 1 ]
244
+ coord = wp .cw_div (p - vmin , vmax - vmin )
245
+
246
+ # check if the node is a leaf
247
+ if (
248
+ oct_child [node ][0 ] == - 1
249
+ and oct_child [node ][1 ] == - 1
250
+ and oct_child [node ][2 ] == - 1
251
+ and oct_child [node ][3 ] == - 1
252
+ and oct_child [node ][4 ] == - 1
253
+ and oct_child [node ][5 ] == - 1
254
+ and oct_child [node ][6 ] == - 1
255
+ and oct_child [node ][7 ] == - 1
256
+ ):
257
+ for j in range (8 ):
258
+ if not grad :
259
+ rx [j ] = (
260
+ (coord [0 ] if j & 1 else 1.0 - coord [0 ])
261
+ * (coord [1 ] if j & 2 else 1.0 - coord [1 ])
262
+ * (coord [2 ] if j & 4 else 1.0 - coord [2 ])
263
+ )
264
+ else :
265
+ rx [j ] = (1.0 if j & 1 else - 1.0 ) * (coord [1 ] if j & 2 else 1.0 - coord [1 ]) * (coord [2 ] if j & 4 else 1.0 - coord [2 ])
266
+ ry [j ] = (coord [0 ] if j & 1 else 1.0 - coord [0 ]) * (1.0 if j & 2 else - 1.0 ) * (coord [2 ] if j & 4 else 1.0 - coord [2 ])
267
+ rz [j ] = (coord [0 ] if j & 1 else 1.0 - coord [0 ]) * (coord [1 ] if j & 2 else 1.0 - coord [1 ]) * (1.0 if j & 4 else - 1.0 )
268
+ return node , (rx , ry , rz )
269
+
270
+ # compute which of 8 children to visit next
271
+ x = 1 if coord [0 ] < 0.5 else 0
272
+ y = 1 if coord [1 ] < 0.5 else 0
273
+ z = 1 if coord [2 ] < 0.5 else 0
274
+ stack = oct_child [node ][4 * z + 2 * y + x ]
275
+
276
+ wp .print ("ERROR: Node not found\n " )
277
+ return - 1 , (rx , ry , rz )
229
278
279
+
280
+ @wp .func
281
+ def box_project (center : wp .vec3 , half_size : wp .vec3 , xyz : wp .vec3 ) -> Tuple [float , wp .vec3 ]:
230
282
r = xyz - center
231
283
q = wp .vec3 (wp .abs (r [0 ]) - half_size [0 ], wp .abs (r [1 ]) - half_size [1 ], wp .abs (r [2 ]) - half_size [2 ])
232
284
233
285
if q [0 ] <= 0.0 and q [1 ] <= 0.0 and q [2 ] <= 0.0 :
234
- uvw = wp .volume_world_to_index (volume_data .volume_id , xyz )
235
- sdf = wp .volume_sample_f (volume_data .volume_id , uvw , wp .Volume .LINEAR )
236
- return sdf
286
+ return 0.0 , xyz
237
287
238
288
else :
239
- point = wp .vec3 (xyz [0 ], xyz [1 ], xyz [2 ])
240
289
dist_sqr = 0.0
241
290
eps = 1e-4
291
+ point = wp .vec3 (xyz [0 ], xyz [1 ], xyz [2 ])
242
292
243
293
if q [0 ] >= 0.0 :
244
294
dist_sqr += q [0 ] * q [0 ]
@@ -261,23 +311,33 @@ def sample_volume_sdf(xyz: wp.vec3, volume_data: VolumeData) -> float:
261
311
else :
262
312
point = wp .vec3 (point [0 ], point [1 ], point [2 ] + (q [2 ] + eps ))
263
313
264
- dist0 = wp .sqrt (dist_sqr )
314
+ return wp .sqrt (dist_sqr ), point
265
315
266
- uvw = wp .volume_world_to_index (volume_data .volume_id , point )
267
- sdf = wp .volume_sample_f (volume_data .volume_id , uvw , wp .Volume .LINEAR )
268
- return dist0 + sdf
316
+
317
+ @wp .func
318
+ def sample_volume_sdf (xyz : wp .vec3 , volume_data : VolumeData ) -> float :
319
+ dist0 , point = box_project (volume_data .center , volume_data .half_size , xyz )
320
+ node , weights = find_oct (volume_data .oct_aabb , volume_data .oct_child , point , grad = False )
321
+ return dist0 + wp .dot (weights [0 ], volume_data .oct_coeff [node ])
269
322
270
323
271
324
@wp .func
272
325
def sample_volume_grad (xyz : wp .vec3 , volume_data : VolumeData ) -> wp .vec3 :
273
- h = 1e-4
274
- dx = wp .vec3 (h , 0.0 , 0.0 )
275
- dy = wp .vec3 (0.0 , h , 0.0 )
276
- dz = wp .vec3 (0.0 , 0.0 , h )
277
- f = sample_volume_sdf (xyz , volume_data )
278
- grad_x = (sample_volume_sdf (xyz + dx , volume_data ) - f ) / h
279
- grad_y = (sample_volume_sdf (xyz + dy , volume_data ) - f ) / h
280
- grad_z = (sample_volume_sdf (xyz + dz , volume_data ) - f ) / h
326
+ dist0 , point = box_project (volume_data .center , volume_data .half_size , xyz )
327
+ if dist0 > 0 :
328
+ h = 1e-4
329
+ dx = wp .vec3 (h , 0.0 , 0.0 )
330
+ dy = wp .vec3 (0.0 , h , 0.0 )
331
+ dz = wp .vec3 (0.0 , 0.0 , h )
332
+ f = sample_volume_sdf (xyz , volume_data )
333
+ grad_x = (sample_volume_sdf (xyz + dx , volume_data ) - f ) / h
334
+ grad_y = (sample_volume_sdf (xyz + dy , volume_data ) - f ) / h
335
+ grad_z = (sample_volume_sdf (xyz + dz , volume_data ) - f ) / h
336
+ return wp .vec3 (grad_x , grad_y , grad_z )
337
+ node , weights = find_oct (volume_data .oct_aabb , volume_data .oct_child , point , grad = True )
338
+ grad_x = wp .dot (weights [0 ], volume_data .oct_coeff [node ])
339
+ grad_y = wp .dot (weights [1 ], volume_data .oct_coeff [node ])
340
+ grad_z = wp .dot (weights [2 ], volume_data .oct_coeff [node ])
281
341
return wp .vec3 (grad_x , grad_y , grad_z )
282
342
283
343
@@ -579,8 +639,9 @@ def _sdf_narrowphase(
579
639
mesh_polymapadr : wp .array (dtype = int ),
580
640
mesh_polymapnum : wp .array (dtype = int ),
581
641
mesh_polymap : wp .array (dtype = int ),
582
- volume_ids : wp .array (dtype = wp .uint64 ),
583
642
oct_aabb : wp .array2d (dtype = wp .vec3 ),
643
+ oct_child : wp .array (dtype = vec8i ),
644
+ oct_coeff : wp .array (dtype = vec8f ),
584
645
pair_dim : wp .array (dtype = int ),
585
646
pair_solref : wp .array2d (dtype = wp .vec2 ),
586
647
pair_solreffriction : wp .array2d (dtype = wp .vec2 ),
@@ -732,11 +793,11 @@ def _sdf_narrowphase(
732
793
rot1 = geom1 .rot
733
794
734
795
attr1 , g1_plugin_id , volume_data1 , mesh_data1 = get_sdf_params (
735
- volume_ids , oct_aabb , plugin , plugin_attr , type1 , geom1 .size , g1_plugin , geom_dataid [g1 ]
796
+ oct_aabb , oct_child , oct_coeff , plugin , plugin_attr , type1 , geom1 .size , g1_plugin , geom_dataid [g1 ]
736
797
)
737
798
738
799
attr2 , g2_plugin_id , volume_data2 , mesh_data2 = get_sdf_params (
739
- volume_ids , oct_aabb , plugin , plugin_attr , type2 , geom2 .size , g2_plugin , geom_dataid [g2 ]
800
+ oct_aabb , oct_child , oct_coeff , plugin , plugin_attr , type2 , geom2 .size , g2_plugin , geom_dataid [g2 ]
740
801
)
741
802
742
803
mesh_data1 .nmeshface = nmeshface
@@ -857,8 +918,9 @@ def sdf_narrowphase(m: Model, d: Data):
857
918
m .mesh_polymapadr ,
858
919
m .mesh_polymapnum ,
859
920
m .mesh_polymap ,
860
- m .volume_ids ,
861
921
m .oct_aabb ,
922
+ m .oct_child ,
923
+ m .oct_coeff ,
862
924
m .pair_dim ,
863
925
m .pair_solref ,
864
926
m .pair_solreffriction ,
0 commit comments