Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
90da431
[BUG FIX] Preserve external forces across sub-steps. (#1290)
LeonLiu4 Jun 20, 2025
0864103
[MISC] Reduce warning messages. (#1294)
YilingQiao Jun 20, 2025
8d07248
[MISC] Update default FEM damping 45.0 -> 0.0 (#1288)
Milotrince Jun 20, 2025
6d9f319
bvh query
Libero0809 Jun 4, 2025
197453b
Wrap aabb with python AABB class
Libero0809 Jun 5, 2025
bf0ee25
move query result batch dim
Libero0809 Jun 6, 2025
d385da6
init
Libero0809 Jun 10, 2025
fe432f0
Update bvh.py
duburcqa Jun 10, 2025
b1a7d2d
tet plane detection
Libero0809 Jun 11, 2025
82ffb7e
worked but far from good
Libero0809 Jun 14, 2025
0d564a2
add damping
Libero0809 Jun 16, 2025
1241c5b
add test
Libero0809 Jun 16, 2025
bd5aa0f
change test fem to sapcoupler
Libero0809 Jun 18, 2025
122e221
change test name
Libero0809 Jun 18, 2025
2778529
code cleanup & bug fix
Libero0809 Jun 18, 2025
54d5646
fix test
Libero0809 Jun 19, 2025
e74be79
fix test
Libero0809 Jun 20, 2025
bf60281
update doc for sap
Libero0809 Jun 20, 2025
604aef5
corotated
Libero0809 Jun 19, 2025
3845104
init
Libero0809 Jun 20, 2025
5cc72a0
fix bug in bvh
Libero0809 Jun 21, 2025
281dac3
debugging
Libero0809 Jun 24, 2025
2d38888
tet tet intersection
Libero0809 Jun 25, 2025
d5208f8
framework for ipc
Libero0809 Jun 25, 2025
f498d0f
remove the ipc part for cleaness
Libero0809 Jun 25, 2025
07e2112
Merge branch 'main' into bvh
Libero0809 Jun 25, 2025
d6ca8e0
pair detect ready
Libero0809 Jun 26, 2025
2c24e59
add gpu test
Libero0809 Jun 26, 2025
d7889fd
change compute bound to layered reduction
Libero0809 Jun 26, 2025
593892b
Merge branch 'main' into bvh
Libero0809 Jun 26, 2025
d33f8dc
make tests faster
Libero0809 Jun 26, 2025
624eed4
code clean up
Libero0809 Jun 26, 2025
98d30ab
removed unused field
Libero0809 Jun 26, 2025
d701966
Merge branch 'bvh' into self_collision
Libero0809 Jun 26, 2025
1d14882
refactor
Libero0809 Jun 27, 2025
bf3e08a
optimize performance
Libero0809 Jun 28, 2025
ed4c241
exact linesearch
Libero0809 Jul 4, 2025
83374ff
refactor
Libero0809 Jul 8, 2025
5013d26
add tests
Libero0809 Jul 8, 2025
94b84ba
Merge branch 'main' into self_collision
Libero0809 Jul 8, 2025
35dc136
small bug
Libero0809 Jul 8, 2025
995cb7c
code cleanup
Libero0809 Jul 10, 2025
8195566
remove debug functions
Libero0809 Jul 10, 2025
669881d
Merge branch 'main' into self_collision
Libero0809 Jul 10, 2025
00a491d
performance drop
Libero0809 Jul 11, 2025
3031a78
code cleanup
Libero0809 Jul 11, 2025
6c97c76
[MISC] Minor cleanup and bug fixes. (#1398)
duburcqa Jul 11, 2025
1438172
[MIGRATION] Collider migration (#1376)
SonSang Jul 11, 2025
ef1696c
Merge branch 'main' into self_collision
Libero0809 Jul 11, 2025
54b9137
small bug fix
Libero0809 Jul 11, 2025
7e0be8e
code cleanup
Libero0809 Jul 14, 2025
97072c8
Merge branch 'main' into self_collision
Libero0809 Jul 14, 2025
8129163
fix bvh
Libero0809 Jul 14, 2025
b9b2d20
Merge branch 'main' into self_collision
duburcqa Jul 16, 2025
06cb131
option bug fix
Libero0809 Jul 16, 2025
b0a68ff
[BUG FIX] Fix broken interactive viewer. (#1426)
duburcqa Jul 16, 2025
3df03e9
[Migration] Some setter and getter kernels (#1424)
YilingQiao Jul 16, 2025
a0c229e
Merge branch 'main' into self_collision
duburcqa Jul 16, 2025
51f4630
remove duplicate
Libero0809 Jul 16, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 108 additions & 6 deletions genesis/engine/bvh.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ class LBVH(RBC):
https://research.nvidia.com/sites/default/files/pubs/2012-06_Maximizing-Parallelism-in/karras2012hpg_paper.pdf
"""

def __init__(self, aabb: AABB, max_n_query_result_per_aabb: int = 8):
def __init__(self, aabb: AABB, max_n_query_result_per_aabb: int = 8, n_radix_sort_groups: int = 256):
self.aabbs = aabb.aabbs
self.n_aabbs = aabb.n_aabbs
self.n_batches = aabb.n_batches
Expand All @@ -130,12 +130,18 @@ def __init__(self, aabb: AABB, max_n_query_result_per_aabb: int = 8):
# Histogram for radix sort
self.hist = ti.field(ti.u32, shape=(self.n_batches, 256))
# Prefix sum for histogram
self.prefix_sum = ti.field(ti.u32, shape=(self.n_batches, 256))
self.prefix_sum = ti.field(ti.u32, shape=(self.n_batches, 256 + 1))
# Offset for radix sort
self.offset = ti.field(ti.u32, shape=(self.n_batches, self.n_aabbs))
# Temporary storage for radix sort
self.tmp_morton_codes = ti.field(ti.types.vector(2, ti.u32), shape=(self.n_batches, self.n_aabbs))

self.n_radix_sort_groups = n_radix_sort_groups
self.hist_group = ti.field(ti.u32, shape=(self.n_batches, self.n_radix_sort_groups, 256 + 1))
self.prefix_sum_group = ti.field(ti.u32, shape=(self.n_batches, self.n_radix_sort_groups + 1, 256))
self.group_size = self.n_aabbs // self.n_radix_sort_groups
self.visited = ti.field(ti.u8, shape=(self.n_aabbs,))

@ti.dataclass
class Node:
"""
Expand Down Expand Up @@ -176,6 +182,19 @@ def build(self):
self.build_radix_tree()
self.compute_bounds()

@ti.func
def filter(self, i_a, i_q):
"""
Filter function that always returns False.

This function does not filter out any AABB by default.
It can be overridden in subclasses to implement custom filtering logic.

i_a: index of the found AABB
i_q: index of the query AABB
"""
return False

@ti.kernel
def compute_aabb_centers_and_scales(self):
for i_b, i_a in ti.ndrange(self.n_batches, self.n_aabbs):
Expand Down Expand Up @@ -230,8 +249,12 @@ def radix_sort_morton_codes(self):
"""
Radix sort the morton codes, using 8 bits at a time.
"""
for i in range(8):
self._kernel_radix_sort_morton_codes_one_round(i)
# The last 32 bits are the index of the AABB which are already sorted, no need to sort
for i in range(4, 8):
if self.n_radix_sort_groups == 1:
self._kernel_radix_sort_morton_codes_one_round(i)
else:
self._kernel_radix_sort_morton_codes_one_round_group(i)

@ti.kernel
def _kernel_radix_sort_morton_codes_one_round(self, i: int):
Expand Down Expand Up @@ -262,6 +285,50 @@ def _kernel_radix_sort_morton_codes_one_round(self, i: int):
for i_b, i_a in ti.ndrange(self.n_batches, self.n_aabbs):
self.morton_codes[i_b, i_a] = self.tmp_morton_codes[i_b, i_a]

@ti.kernel
def _kernel_radix_sort_morton_codes_one_round_group(self, i: int):
# Clear histogram
self.hist_group.fill(0)

# Fill histogram
for i_b, i_g in ti.ndrange(self.n_batches, self.n_radix_sort_groups):
start = i_g * self.group_size
end = ti.select(
i_g == self.n_radix_sort_groups - 1,
self.n_aabbs,
(i_g + 1) * self.group_size,
)
for i_a in range(start, end):
code = (self.morton_codes[i_b, i_a][1 - (i // 4)] >> ((i % 4) * 8)) & 0xFF
self.offset[i_b, i_a] = self.hist_group[i_b, i_g, code]
self.hist_group[i_b, i_g, code] = self.hist_group[i_b, i_g, code] + 1

# Compute prefix sum
for i_b, i_c in ti.ndrange(self.n_batches, 256):
self.prefix_sum_group[i_b, 0, i_c] = 0
for i_g in range(1, self.n_radix_sort_groups + 1): # sequential prefix sum
self.prefix_sum_group[i_b, i_g, i_c] = (
self.prefix_sum_group[i_b, i_g - 1, i_c] + self.hist_group[i_b, i_g - 1, i_c]
)
for i_b in range(self.n_batches):
self.prefix_sum[i_b, 0] = 0
for i_c in range(1, 256 + 1): # sequential prefix sum
self.prefix_sum[i_b, i_c] = (
self.prefix_sum[i_b, i_c - 1] + self.prefix_sum_group[i_b, self.n_radix_sort_groups, i_c - 1]
)

# Reorder morton codes
for i_b, i_a in ti.ndrange(self.n_batches, self.n_aabbs):
code = (self.morton_codes[i_b, i_a][1 - (i // 4)] >> ((i % 4) * 8)) & 0xFF
i_g = ti.min(i_a // self.group_size, self.n_radix_sort_groups - 1)
idx = ti.i32(self.prefix_sum[i_b, code] + self.prefix_sum_group[i_b, i_g, code] + self.offset[i_b, i_a])
# Use the group prefix sum to find the correct index
self.tmp_morton_codes[i_b, idx] = self.morton_codes[i_b, i_a]

# Swap the temporary and original morton codes
for i_b, i_a in ti.ndrange(self.n_batches, self.n_aabbs):
self.morton_codes[i_b, i_a] = self.tmp_morton_codes[i_b, i_a]

@ti.kernel
def build_radix_tree(self):
"""
Expand Down Expand Up @@ -396,10 +463,13 @@ def query(self, aabbs: ti.template()):
if aabbs[i_b, i_q].intersects(node.bound):
# If it's a leaf node, add the AABB index to the query results
if node.left == -1 and node.right == -1:
i_a = ti.i32(self.morton_codes[i_b, node_idx - (self.n_aabbs - 1)][1])
# Check if the filter condition is met
if self.filter(i_a, i_q):
continue
idx = ti.atomic_add(self.query_result_count[None], 1)
if idx < self.max_n_query_results:
code = self.morton_codes[i_b, node_idx - (self.n_aabbs - 1)][1]
self.query_result[idx] = gs.ti_ivec3(i_b, ti.i32(code), i_q) # Store the AABB index
self.query_result[idx] = gs.ti_ivec3(i_b, i_a, i_q) # Store the AABB index
else:
# Push children onto the stack
if node.right != -1:
Expand All @@ -408,3 +478,35 @@ def query(self, aabbs: ti.template()):
if node.left != -1:
query_stack[stack_depth] = node.left
stack_depth += 1


@ti.data_oriented
class FEMSurfaceTetLBVH(LBVH):
"""
FEMSurfaceTetLBVH is a specialized Linear BVH for FEM surface tetrahedrals.

It extends the LBVH class to support filtering based on FEM surface tetrahedral elements.
"""

def __init__(self, fem_solver, aabb: AABB, max_n_query_result_per_aabb: int = 8, n_radix_sort_groups: int = 256):
super().__init__(aabb, max_n_query_result_per_aabb, n_radix_sort_groups)
self.fem_solver = fem_solver

@ti.func
def filter(self, i_a, i_q):
"""
Filter function for FEM surface tets. Filter out tet that share vertices.

This is used to avoid self-collisions in FEM surface tets.

i_a: index of the found AABB
i_q: index of the query AABB
"""

result = i_a >= i_q
i_av = self.fem_solver.elements_i[self.fem_solver.surface_elements[i_a]].el2v
i_qv = self.fem_solver.elements_i[self.fem_solver.surface_elements[i_q]].el2v
for i, j in ti.static(ti.ndrange(4, 4)):
if i_av[i] == i_qv[j]:
result = True
return result
Loading