Skip to content

Commit f182162

Browse files
committed
fix: sort children nodes by morton code
1 parent f547b88 commit f182162

File tree

1 file changed

+39
-19
lines changed

1 file changed

+39
-19
lines changed

pychunkedgraph/meshing/manifest/multiscale.py

Lines changed: 39 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -70,10 +70,34 @@ def _get_node_coords_and_layers_map(
7070
return node_coords, dict(zip(node_ids, node_layers))
7171

7272

73-
def _normalize_coordinates(coords, layer, bfs_depth, max_layer):
74-
node_depth = max_layer - layer
75-
depth_diff = node_depth - bfs_depth
76-
return coords // 2**depth_diff
73+
def sort_octree_row(coords):
74+
"""
75+
Sort children by their morton code.
76+
"""
77+
coords = np.array(coords, dtype=int, copy=False)
78+
if coords.size == 0:
79+
return empty_1d
80+
81+
def z_order(x, y, z):
82+
result = 0
83+
for i in range(10):
84+
result |= (
85+
((x & (1 << i)) << (2 * i))
86+
| ((y & (1 << i)) << ((2 * i) + 1))
87+
| ((z & (1 << i)) << ((2 * i) + 2))
88+
)
89+
return result
90+
91+
x_coords = coords[:, 0]
92+
y_coords = coords[:, 1]
93+
z_coords = coords[:, 2]
94+
z_order_values = np.array(
95+
[z_order(x, y, z) for x, y, z in zip(x_coords, y_coords, z_coords)],
96+
dtype=np.uint32,
97+
)
98+
99+
sorted_indices = np.argsort(z_order_values)
100+
return sorted_indices
77101

78102

79103
def build_octree(
@@ -91,7 +115,7 @@ def build_octree(
91115
requested/rendered.
92116
"""
93117
node_ids = np.fromiter(mesh_fragments.keys(), dtype=NODE_ID)
94-
node_coords_d, node_layers_d = _get_node_coords_and_layers_map(cg, node_children)
118+
node_coords_d, _ = _get_node_coords_and_layers_map(cg, node_children)
95119
skipped, leaves = _get_skipped_and_missing_leaf_nodes(node_children, mesh_fragments)
96120

97121
OCTREE_NODE_SIZE = 5
@@ -105,24 +129,15 @@ def build_octree(
105129

106130
que = deque()
107131
rows_used = 1
108-
que.append((node_id, 0))
132+
que.append(node_id)
109133

110134
while len(que) > 0:
111135
row_counter -= 1
112-
current_node, depth = que.popleft()
136+
current_node = que.popleft()
113137
children = node_children[current_node]
114-
node_layer = node_layers_d[current_node]
115138
node_coords = node_coords_d[current_node]
116139

117-
# node_coords = _normalize_coordinates(
118-
# coords=node_coords,
119-
# layer=node_layer,
120-
# bfs_depth=depth,
121-
# max_layer=cg.meta.layer_count,
122-
# )
123-
124140
x, y, z = node_coords
125-
# x, y, z = node_coords * np.array(cg.meta.graph_config.CHUNK_SIZE, dtype=int)
126141
offset = OCTREE_NODE_SIZE * row_counter
127142
octree[offset + 0] = x
128143
octree[offset + 1] = y
@@ -138,17 +153,22 @@ def build_octree(
138153
octree_node_ids[row_counter] = current_node
139154
try:
140155
if children.size == 1:
141-
# map to child fragment
142-
# octree_fragments[row_counter] = mesh_fragments[children[0]]
156+
# mark node virtual
143157
octree[offset + 3] |= 1 << 31
144158
else:
145159
octree_fragments[row_counter] = mesh_fragments[current_node]
146160
except KeyError:
147161
# no mesh, mark node empty
148162
octree[offset + 4] |= 1 << 31
149163

164+
children_coords = []
165+
for child in children:
166+
children_coords.append(cg.get_chunk_coordinates(child))
167+
168+
indices = sort_octree_row(children_coords)
169+
children = children[indices]
150170
for child in children:
151-
que.append((child, depth + 1))
171+
que.append(child)
152172
return octree, octree_node_ids, octree_fragments
153173

154174

0 commit comments

Comments
 (0)