Source code for redeclipse.voxel

"""
We can't work with octrees. Just... no.

So we work in a voxel world, and then convert this to an octree with the small
resolution cube that makes sense, and then let RE optimise the map when need be.
"""
from redeclipse.objects import cube
from redeclipse.enums import OCT
import logging
log = logging.getLogger(__name__)


[docs]class VoxelWorld: def __init__(self, size=2**7): # Size defines number of cubes from left to right. self.size = size self.world = {} # Boundaries self.xmax = 0 self.xmin = size self.ymax = 0 self.ymin = size self.zmax = 0 self.zmin = size def _update_boundaries(self, x, y, z): if x > self.xmax: self.xmax = x if x < self.xmin: self.xmin = x if y > self.ymax: self.ymax = y if y < self.ymin: self.ymin = y if z > self.zmax: self.zmax = z if z < self.zmin: self.zmin = z
[docs] def set_point(self, x, y, z, data): log.debug("set_point (%d, %d, %d)", x, y, z) self._update_boundaries(x, y, z) self.world[x, y, z] = data
[docs] def set_pointv(self, xyz, data): log.debug("set_point %s", xyz) self._update_boundaries(xyz.x, xyz.y, xyz.z) self.world[tuple(xyz)] = data
[docs] def del_point(self, x, y, z): log.debug("del_point (%d, %d, %d)", x, y, z) if (x, y, z) in self.world: del self.world[x, y, z]
[docs] def del_pointv(self, xyz): (x, y, z) = xyz if (x, y, z) in self.world: del self.world[x, y, z]
[docs] def get_point(self, x, y, z): if (x, y, z) in self.world: return self.world[x, y, z] else: return None
[docs] def to_octree(self, x_bounds=None, y_bounds=None, z_bounds=None, layers=False): if x_bounds is None: x_bounds = ( 0, self.size ) y_bounds = ( 0, self.size ) z_bounds = ( 0, self.size ) # If it is the smallest possible cube, just return the cube # structure. Since we always go in perfect cubes, only need to # check one. if x_bounds[1] - x_bounds[0] == 1: return self.get_point(x_bounds[0], y_bounds[0], z_bounds[0]) # Otherwise, split into 8 smaller cubes current_level_cubes = [ self.to_octree( (x_bounds[0], (sum(x_bounds) // 2)), (y_bounds[0], (sum(y_bounds) // 2)), (z_bounds[0], (sum(z_bounds) // 2)) ), self.to_octree( ((sum(x_bounds) // 2), x_bounds[1]), (y_bounds[0], (sum(y_bounds) // 2)), (z_bounds[0], (sum(z_bounds) // 2)) ), self.to_octree( (x_bounds[0], (sum(x_bounds) // 2)), ((sum(y_bounds) // 2), y_bounds[1]), (z_bounds[0], (sum(z_bounds) // 2)) ), self.to_octree( ((sum(x_bounds) // 2), x_bounds[1]), ((sum(y_bounds) // 2), y_bounds[1]), (z_bounds[0], (sum(z_bounds) // 2)) ), self.to_octree( (x_bounds[0], (sum(x_bounds) // 2)), (y_bounds[0], (sum(y_bounds) // 2)), ((sum(z_bounds) // 2), z_bounds[1]) ), self.to_octree( ((sum(x_bounds) // 2), x_bounds[1]), (y_bounds[0], (sum(y_bounds) // 2)), ((sum(z_bounds) // 2), z_bounds[1]) ), self.to_octree( (x_bounds[0], (sum(x_bounds) // 2)), ((sum(y_bounds) // 2), y_bounds[1]), ((sum(z_bounds) // 2), z_bounds[1]) ), self.to_octree( ((sum(x_bounds) // 2), x_bounds[1]), ((sum(y_bounds) // 2), y_bounds[1]), ((sum(z_bounds) // 2), z_bounds[1]) ) # new cube * 8 ] # Worldroot is an array not a cube if x_bounds[0] == 0 and x_bounds[1] == self.size: return [cube.newcube() if x is None else x for x in current_level_cubes] elif all([x is None for x in current_level_cubes]): # If they're all empty, return return None else: # Some of them are non-empty, replace the others with empty cubes. c = cube.newcube() c.children = [cube.newcube() if x is None else x for x in current_level_cubes] c.octsav = OCT.OCTSAV_CHILDREN.value return c