Added sparse voxel octree system.
This commit is contained in:
parent
800e7f306d
commit
5a9224bdae
1 changed files with 80 additions and 0 deletions
80
math/spvo.py
Normal file
80
math/spvo.py
Normal 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)
|
Loading…
Reference in a new issue