We'll use Blender scripts to construct a simple 'Menger Sponge' fractal - a simple but effective algorithm - we can recursively subdivide a cube into smaller cubes.
A render of the menger sponge fractal of depth 2 using a glass type material.
The first version below is a bit slow - as it uses the boolean modifier to 'cut' holes in the cube. Gradually building up the fractal effect.
import bpy from mathutils import Vector
# === CONFIGURATION === MAX_DEPTH = 2 SIZE = 2.0
# === CLEAN THE SCENE === bpy.ops.object.select_all(action='SELECT') bpy.ops.object.delete()
# === HELPER FUNCTION: Carve Menger Sponge === def create_menger(location, size, depth): # Create the solid cube to start from bpy.ops.mesh.primitive_cube_add(size=size, location=location) sponge = bpy.context.active_object
def recursive_carve(obj, loc, size, depth): if depth == 0: return
step = size / 3 holes = []
for x in range(3): for y in range(3): for z in range(3): # Skip the central cube and centers of each face if (x == 1 and y == 1) or (x == 1 and z == 1) or (y == 1 and z == 1): cube_loc = Vector(( loc[0] + (x - 1) * step, loc[1] + (y - 1) * step, loc[2] + (z - 1) * step )) bpy.ops.mesh.primitive_cube_add(size=step, location=cube_loc) hole = bpy.context.active_object holes.append(hole)
# Now recurse into each sub-cube for x in range(3): for y in range(3): for z in range(3): if (x, y, z) == (1, 1, 1): continue if sum([axis == 1 for axis in (x, y, z)]) >= 2: continue # skip face/center holes sub_loc = Vector(( loc[0] + (x - 1) * step, loc[1] + (y - 1) * step, loc[2] + (z - 1) * step )) recursive_carve(obj, sub_loc, step, depth - 1)
The boolean operation is simple - and it can produce a single mesh effect - however, it's slow! Very slow! If you go past a depth of 3 you'll probably crash your machine - or get it stuck in a loop for a long while - as it does the work.
A cheep and cheerful alternative is to construct the mesh from lots of small cubes.
The menger sponge fractal looks the same as the boolen operation version - but it's made up of lots of small cubes instead of a single mesh.
This version is a lot faster - and lets you do a lot more with your menger fractal.
import bpy from mathutils import Vector
# === CONFIG === MAX_DEPTH = 2 SIZE = 2.0
# === CLEAN SCENE === bpy.ops.object.select_all(action='SELECT') bpy.ops.object.delete()
# === MAKE BASE MESH ONCE === mesh = bpy.data.meshes.new("CubeMesh") bm = bpy.data.objects.new("BaseCube", mesh) bpy.context.collection.objects.link(bm) bpy.ops.object.select_all(action='DESELECT') bm.select_set(True) bpy.context.view_layer.objects.active = bm bpy.ops.object.delete() # remove for instancing use only
# === BUILD SPONGE === def menger(location, size, depth): step = size / 3 for x in range(3): for y in range(3): for z in range(3): if not is_filled(x, y, z): continue offset = Vector(((x - 1) * step, (y - 1) * step, (z - 1) * step)) pos = location + offset if depth > 1: menger(pos, step, depth - 1) else: add_cube(pos, step)
View the boolean version and the mesh version side by side - you'll notice the boolean version is a single mesh while the other version is lots of little cubes.
Visitor:
Copyright (c) 2002-2025 xbdev.net - All rights reserved.
Designated articles, tutorials and software are the property of their respective owners.