Using array modifier
Using array modifiers will speed up the processing because it will lower the overall io between Blender and Python and also lower bpy.ops usage:
Create a base cube object.
Create and apply three array modifiers on it.
The code is commented below, but if not clear enough, please ask in the comments.
import bpy
import bmesh
def apply_modifier( obj, count, vector ):
# Add an array modifier with its wanted parameters
m = obj.modifiers.new( name = "Array", type = 'ARRAY' )
m.use_relative_offset = False
m.use_constant_offset = True
m.constant_offset_displace = vector
m.count = count
# Apply it
bpy.ops.object.modifier_apply( modifier = m.name )
def create_base_cube( context, name, size ):
# Create an object
mesh = bpy.data.meshes.new( name )
obj = bpy.data.objects.new( name, mesh )
# Add a cube
bm = bmesh.new()
bm.from_mesh( mesh )
bmesh.ops.create_cube( bm, size = size, calc_uvs = False )
bm.to_mesh( mesh )
bm.free()
# Link the object to the scene and set it active
context.scene.collection.objects.link( obj )
context.view_layer.objects.active = obj
return obj
name = "CubeMap"
size = 2
obj = create_base_cube( bpy.context, name, size )
N=100;
interval = 3
apply_modifier( obj, N, (interval, 0, 0) )
apply_modifier( obj, N, (0, interval, 0) )
apply_modifier( obj, N, (0, 0, interval) )
Using dupliverts (proposed by Jackdaw in the comments)
An alternative is to use dupliverts, which seems to be faster and allows to define any patterns (not only cubic).
The principle is to create an object with vertices at the positions you want, then make it parent to a cube and use dupliverts as instancing method.
import bpy
import bmesh
from itertools import product
def create_base_cube( context, name, size ):
# Create an object
mesh = bpy.data.meshes.new( name )
obj = bpy.data.objects.new( name, mesh )
# Add a cube
bm = bmesh.new()
bm.from_mesh( mesh )
bmesh.ops.create_cube( bm, size = size, calc_uvs = False )
bm.to_mesh( mesh )
bm.free()
# Link the object to the scene and set it active
context.scene.collection.objects.link( obj )
context.view_layer.objects.active = obj
return obj
def make_result_object( context, name, cube, vertices ):
mesh = bpy.data.meshes.new( name )
obj = bpy.data.objects.new( name, mesh )
# Associate the vertices
obj.data.from_pydata( vertices, [], [] )
# Link the object to the scene and set it active
context.scene.collection.objects.link( obj )
context.view_layer.objects.active = obj
# Make the object parent of the cube
cube.parent = obj
# Make the object dupliverts
obj.instance_type = 'VERTS'
return obj
name = "CubeMap"
size = 2
cube = create_base_cube( bpy.context, name, size )
N=3*100
interval = 3
vertices = [(x, y, z) for x, y, z in product( range(0,N,interval), range(0,N,interval), range(0,N,interval) )]
result = make_result_object( bpy.context, "result", cube, vertices )