GSplatSorter¶
from acron.gsplat import GSplatSorter
- class GSplatSorter¶
Bases:
Bases:
TypedReferenceCountThe back-to-front draw order of a set of Gaussian splats, as a native counting sort.
Alpha-blended splats composite correctly only drawn far-to-near, and a scan has millions of them, so every view change wants a fresh order and the sort is on the frame’s critical path. This class owns three arrays sized to the splat count –
depths(one view-space depth per splat, filled by the caller – Python writes straight into it through the buffer protocol),visible(one byte per splat, 1 = draw; the culled tail is left out of the order entirely, which is what keeps a telephoto view over a large scan cheap), andorder(the result: splat indices as float32, farthest first, which is the format an R32F order texture wants) – andsort()fills the third from the first two.The sort quantises the depth range to 2^bits buckets (bits = clamp( log2(n / 4), 10, 20) unless set) and counting-sorts on the key, stable, so ties keep index order. It is O(n) and releases the GIL (BLOCKING), so a Python worker thread can call it while the frame loop renders.
load_depths()fillsdepthsandvisiblefrom a “depth plane”: an RGBA32F texture with one texel per splat (texel i = (i % width, i / width)) whose red channel is the splat’s view depth and whose green channel is 1 for a splat worth drawing – the plane a GPU decode pass writes, so the depths of splats the GPU has deformed never have to be recomputed on the CPU. The texture must hold a RAM image (a render target copied to RAM).load_depth_image()reads the same texels from a copy of such an image (a snapshot taken while a sort was running).Indices travel as float32 (the R32F order texture), exact up to 2^24, so a sorter and an order texture hold at most
get_max_count()= 2^24 splats (16.7 M): the constructor clamps to it andmake_order_texture()refuses more. The arrays are handed out as PTAs so Python can write them in place; every method checks their sizes against the count before touching them, so a resized array (push_back / pop_back) cannot be over-read. Resizing one whilesort()runs on another thread is not supported.This is the only sort: the engine always builds it, so there is no fallback in the Python tier.
Inheritance diagram
digraph inheritance84d508b83c { bgcolor=transparent; rankdir=BT; size="8.0, 12.0"; "DTOOL_SUPER_BASE" [fillcolor=white,fontname="Vera Sans, DejaVu Sans, Liberation Sans, Arial, Helvetica, sans",fontsize=11,height=0.25,shape=box,style=""]; "GSplatSorter" [URL="acron.gsplat.GSplatSorter.html#acron.gsplat.GSplatSorter",fillcolor=white,fontname="Vera Sans, DejaVu Sans, Liberation Sans, Arial, Helvetica, sans",fontsize=11,height=0.25,shape=box,style="",target="_top",tooltip="/**"]; "TypedReferenceCount" -> "GSplatSorter" [arrowsize=0.75,style=""]; "ReferenceCount" [URL="acron.core.ReferenceCount.html#acron.core.ReferenceCount",fillcolor=white,fontname="Vera Sans, DejaVu Sans, Liberation Sans, Arial, Helvetica, sans",fontsize=11,height=0.25,shape=box,style="",target="_top",tooltip="/**"]; "DTOOL_SUPER_BASE" -> "ReferenceCount" [arrowsize=0.75,style=""]; "TypedObject" [URL="acron.core.TypedObject.html#acron.core.TypedObject",fillcolor=white,fontname="Vera Sans, DejaVu Sans, Liberation Sans, Arial, Helvetica, sans",fontsize=11,height=0.25,shape=box,style="",target="_top",tooltip="/**"]; "DTOOL_SUPER_BASE" -> "TypedObject" [arrowsize=0.75,style=""]; "TypedReferenceCount" [URL="acron.core.TypedReferenceCount.html#acron.core.TypedReferenceCount",fillcolor=white,fontname="Vera Sans, DejaVu Sans, Liberation Sans, Arial, Helvetica, sans",fontsize=11,height=0.25,shape=box,style="",target="_top",tooltip="/**"]; "TypedObject" -> "TypedReferenceCount" [arrowsize=0.75,style=""]; "ReferenceCount" -> "TypedReferenceCount" [arrowsize=0.75,style=""]; }- __init__()¶
Allocates the three per-splat arrays for
countsplats.visiblestarts all-ones (everything drawn),depthsandorderzero.
- static depth_along()¶
The plain view-space depth of undeformed splats: for every centre (xyz triplets), dot(centre - origin, direction).
depthsreceives one value per centre and must be at least that long.
- get_bits()¶
- static get_class_type()¶
- get_count()¶
- get_depths()¶
- static get_max_count()¶
- get_num_sorted()¶
- get_order()¶
- get_visible()¶
- load_depth_image()¶
As
load_depths(), from a depth plane’s RAM image (BGRA float texels) – typically a copy taken while the sorter was busy. Returns false if the image holds fewer texels than the splat count.
- load_depths()¶
Reads
depthsandvisiblefrom a depth plane (see the class description): texel i’s red channel is the depth, its green channel > 0.5 marks it visible. Returns false if the texture has no RAM image, is not a four-component float image, or holds fewer texels than the splat count.Acron keeps RGBA RAM images in BGRA order, so red is the third float of a texel and green the second.
- static make_order_texture()¶
An R32F order texture of width x height texels holding the identity order (texel i = i), nearest-filtered: what a draw uses until its first sort. Null for an empty size or more than
get_max_count()texels (float32 holds every index exactly only up to 2^24).
- set_bits()¶
- sort()¶
Fills
orderwith the indices of the visible splats (all of them whenuse_visibleis false), farthest depth first, ties in index order. Returns how many indices were written; the rest oforderis untouched.
- write_order()¶
Copies the sorted indices into the texture’s RAM image as float32 (an R32F order texture of at least
num_sortedtexels). Returns false if the texture has no RAM image or is too small.