Let us just say you have a 100x100 cubes 2d grid and each cube will be assigned its own individual material. How can you do this? My code below worked initially when I created all the cubes as individual objects but it took a very very long time to create that many cubes. I was then told I can speed up this process by just copying over the mesh from the first cube to help create the next cube. This speeded up the process but when I tried to run my coloring functions all the cubes now shares the same color material. I assume this is because the new cubes inherited it's material from the creation of the first cube. I think its has something to do with the last else statement below but I am not sure.
How can I keep the speed gain from copying cube mesh to create cubes without inheriting the initial material color from the first cube as well? I asked this question in the Blender official chat a whiles ago and was told to use MaterialSlot(bpy_struct) and I have no idea how it works.
Full relevant code
class Create(Animation):
def __init__(self, collection_name, H, W, y_axis):
self.collection_name = collection_name
self.H = H
self.W = W
self.master_collection = bpy.context.scene.collection
self.myCol = bpy.data.collections.new(self.collection_name) # Automatically create the correct layer
bpy.context.scene.collection.children.link(self.myCol)
def create_block(self, x_axis, y_axis, z_axis):
"""
1) Takes the Height and Width and create a 3D wall in Blender
2) Center it in the middle, assign it to the given collection
3) Translate corresponding pixel values to the correct mat color
Args:
H -- The height(int)
W -- The width(int)
collection -- The collection this block belongs too(str)
"""
if self.collection_name == "input_image": # try mycol flag
self.x = x_axis
self.y = y_axis
self.z = z_axis
elif self.collection_name == "filters":
self.x = x_axis + 69
self.y = y_axis
self.z = z_axis + 69
pixel_idx = 0 # corresponding pixel value index from the tensor
bpy.ops.mesh.primitive_cube_add(size=2, view_align=False, enter_editmode=False, location=(self.x, self.y, self.z)) #create initial cube
cube = bpy.context.scene.objects[0] # remove the duplicate cube from initbpy.ops
for height in range(self.H): # z-axis
for width in range(self.W): # # x-axis
new_cube = bpy.data.objects.new(self.collection_name + "cube", cube.data) #cube.data = mesh struct
new_cube.location = (self.x, self.y, self.z)
self.myCol.objects.link(new_cube)
#self.master_collection.objects.unlink(new_cube)
self.x += 3
if self.collection_name == "filters":
self.x = x_axis + 69
elif self.collection_name == "input_image":
self.x = x_axis
self.z += 3
bpy.ops.object.delete()
def fill_pixel_value(self, tensor_img):
self.image_flatten = tensor_img
self.obs = bpy.context.scene.objects
for i, o in enumerate(self.obs):
name = o.name #grab the cube's name
mat = bpy.data.materials.get("Material")
if mat is None:
mat = bpy.data.materials.new( name + "_Material" )
#Change the mat color to the corresponding image_flatten tensor values
# This used to work but now the first cube I made has the dominate material.
mat.diffuse_color = ( self.image_flatten[i], self.image_flatten[i], self.image_flatten[i], 1 ) #RGBA
# Assign it to object
if o.data.materials:
# assign to 1st material slot
o.data.materials[0] = mat
else:
# no slots
o.data.materials.append(mat)