Skip to content

Commit

Permalink
Improve performance for empty or full grids
Browse files Browse the repository at this point in the history
  • Loading branch information
AstrorEnales committed May 6, 2022
1 parent 4a9dbc7 commit a2e48e8
Showing 1 changed file with 58 additions and 34 deletions.
92 changes: 58 additions & 34 deletions blender_magicavoxel.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,8 @@ def __init__(self, default_value, default_map: Dict or None = None):
self.map = default_map if default_map is not None else {}

def __delitem__(self, key):
del self.map[key]
if key in self.map:
del self.map[key]

def __getitem__(self, item):
return self.map[item] if item in self.map else self.default_value
Expand Down Expand Up @@ -202,40 +203,49 @@ def reduce_voxel_grid_to_hull(self, voxels: SparseArray, outside: SparseArray or
if DEBUG_OUTPUT:
print('[DEBUG] reduce_voxel_grid_to_hull')
timer_start = time.time()
for z in range(0, self.height):
last_z = z == self.last_index_z
first_z = z == 0
for y in range(0, self.depth):
last_y = y == self.last_index_y
first_y = y == 0
for x in range(0, self.width):
index = self.get_index(x, y, z)
if voxels[index] is not None:
# Left
if x == 0 or (outside is not None and outside[index - 1]):
continue
# Right
if x == self.last_index_x or (outside is not None and outside[index + 1]):
continue
# Down
if first_y or (outside is not None and outside[index - self.y_multiplier]):
continue
# Up
if last_y or (outside is not None and outside[index + self.y_multiplier]):
continue
# Back
if first_z or (outside is not None and outside[index - self.z_multiplier]):
continue
# Front
if last_z or (outside is not None and outside[index + self.z_multiplier]):
continue
# If not connected to the outside space, delete the voxel(inside hull)
del voxels[index]
if outside is None:
for z in range(1, self.height - 1):
for y in range(1, self.depth - 1):
for x in range(1, self.width - 1):
del voxels[self.get_index(x, y, z)]
else:
for z in range(0, self.height):
last_z = z == self.last_index_z
first_z = z == 0
for y in range(0, self.depth):
last_y = y == self.last_index_y
first_y = y == 0
for x in range(0, self.width):
index = self.get_index(x, y, z)
if voxels[index] is not None:
# Left
if x == 0 or (outside is not None and outside[index - 1]):
continue
# Right
if x == self.last_index_x or (outside is not None and outside[index + 1]):
continue
# Down
if first_y or (outside is not None and outside[index - self.y_multiplier]):
continue
# Up
if last_y or (outside is not None and outside[index + self.y_multiplier]):
continue
# Back
if first_z or (outside is not None and outside[index - self.z_multiplier]):
continue
# Front
if last_z or (outside is not None and outside[index + self.z_multiplier]):
continue
# If not connected to the outside space, delete the voxel(inside hull)
del voxels[index]
timer_end = time.time()
if DEBUG_OUTPUT:
print('[DEBUG] took %s sec' % (timer_end - timer_start))

def create_outside_grid(self, voxels: SparseArray) -> SparseArray or None:
def create_outside_grid(self, voxels: SparseArray, num_voxels: int) -> SparseArray or None:
if num_voxels == self.size:
# If we have a filled grid we already know there to exist no outside
return None
outside_indices = self.find_outside_indices(voxels)
if outside_indices is None:
# All is marked as outside to prevent any faces to be removed
Expand Down Expand Up @@ -597,7 +607,8 @@ def mesh_axis(grid: VoxelGrid, voxels: SparseArray, outside: SparseArray or None
# ...or different color...
start_voxel != iter_voxel or
# ... or not connected to the outside space
(has_offset[visited_index] and (outside is None or not outside[get_index(a_back, i, c)]))
(has_offset[visited_index] and (
outside is None or not outside[get_index(a_back, i, c)]))
):
end_index_axis1 = i - 1
found_end_axis1 = True
Expand All @@ -621,7 +632,8 @@ def mesh_axis(grid: VoxelGrid, voxels: SparseArray, outside: SparseArray or None
# ...or different color...
start_voxel != iter_voxel or
# ... or not connected to the outside space
(has_offset[visited_index] and (outside is None or not outside[get_index(a_back, i, j)]))
(has_offset[visited_index] and (
outside is None or not outside[get_index(a_back, i, j)]))
):
any_mismatch_in_row = True
break
Expand Down Expand Up @@ -740,6 +752,7 @@ def __str__(self):
class VoxMesh:
def __init__(self, model_id: int, width: int, depth: int, height: int):
self.model_id = model_id
self.num_voxels = 0
self.grid: VoxelGrid = VoxelGrid(width, depth, height)
self.voxels = SparseArray(None)
self.used_color_indices: Set[int] = set()
Expand Down Expand Up @@ -1055,7 +1068,13 @@ def execute(self, context):
)
total_timer_start = time.time()
filepath = keywords['filepath']
if DEBUG_OUTPUT:
print('[DEBUG] load raw data')
timer_start = time.time()
result = self.load_vox(filepath)
timer_end = time.time()
if DEBUG_OUTPUT:
print('[DEBUG] took %s sec' % (timer_end - timer_start))
if result is not None:
collection_name = os.path.basename(filepath)
view_layer = context.view_layer
Expand Down Expand Up @@ -1120,7 +1139,11 @@ def execute(self, context):
mesh.model_id, mesh.grid.width, mesh.grid.depth, mesh.grid.height))
generated_mesh_models = []
mesh_index += 1
outside = mesh.grid.create_outside_grid(mesh.voxels)
# Skip empty models
if mesh.num_voxels == 0:
model_id_object_lookup[mesh_index] = []
continue
outside = mesh.grid.create_outside_grid(mesh.voxels, mesh.num_voxels)
# =====================================================
# CUBES_AS_OBJ
# =====================================================
Expand Down Expand Up @@ -1403,6 +1426,7 @@ def read_size_chunk(f: IO, model: VoxModel):
@staticmethod
def read_xyzi_chunk(f: IO, model: VoxModel):
num_voxels = ImportVOX.read_int32(f)
model.meshes[-1].num_voxels = num_voxels
for i in range(0, num_voxels):
model.meshes[-1].set_voxel_color_index(
ImportVOX.read_uint8(f),
Expand Down

0 comments on commit a2e48e8

Please sign in to comment.