Added sparse voxel octree system.

This commit is contained in:
The Wobbler 2024-08-29 15:18:15 +02:00
parent 800e7f306d
commit 5a9224bdae

80
math/spvo.py Normal file
View file

@ -0,0 +1,80 @@
#!/usr/bin/python3
"""
SPVO = Sparse Voxel Octree
A Sparse Voxel Octree is a way of storing multidimensional data. (In this case it is 3D Data.)
It works similarly to a Sparse Voxel Matrix, but it is a bit compressed.
In a Sparse Voxel Octree, you have a root-node. The root node gets split up into 8 child nodes,
which can be all split up into 8 more child nodes which can be split up too and so on.
Thanks to this "compression", there are no zero values on places where there is just air unlike as in a normal matrix.
"""
class Node:
def __init__(self):
self.children = [None] * 8
self.leaf = True
class SparseVoxelOctree:
def __init__(self, data=None):
self.root_node = Node()
self.origin = (0, 0, 0)
self.data = data
def _get_child_index(self, x, y, z, size):
index = 0
if x >= size // 2:
index |= 1
x -= size // 2
if y >= size // 2:
index |= 2
y -= size // 2
if z >= size // 2:
index |= 4
z -= size // 2
return index, x, y, z
def _extend_tree(self, x, y, z):
new_root = Node()
new_root.leaf = False
index, nx, ny, nz = self._get_child_index(x, y, z, 2)
new_root.children[index] = self.root_node
self.root_node = new_root
self.origin = (
self.origin[0] - (x >= 0) * 2 + 1,
self.origin[1] - (y >= 0) * 2 + 1,
self.origin[2] - (z >= 0) * 2 + 1
)
def _insert(self, node, x, y, z, size):
while not size == 1:
index, x, y, z = self._get_child_index(x, y, z, size)
if node.children[index] is None:
node.children[index] = Node()
size //= 2
node.leaf = True
def insert(self, x, y, z):
# move origin if necessary
while not (0 <= x < 2 ** 30 and 0 <= y < 2 ** 30 and 0 <= z < 2 ** 30):
self._extend_tree(x, y, z)
x, y, z = (
x - self.origin[0],
y - self.origin[1],
z - self.origin[2]
)
self._insert(self.root_node, x, y, z, 2 ** 30)