import bpy # Delete default cube if present # Our delete all function would have worked fine too if "Cube" in bpy.data.objects: bpy.data.objects["Cube"].select_set(True) bpy.ops.object.delete() bpy.ops.mesh.primitive_cube_add(size=5) cube = bpy.context.active_object # We'll need one material per texture # Since our textures are in different images materials = [] for i in range(6): mat = bpy.data.materials.new(name=f"FaceMaterial_{i}") mat.use_nodes = True materials.append(mat) # Did I end up with more than two fish? # If not, I guess we just get two textures = [ "clownfish.jpg", "yellowtang.jpg", "clownfish.jpg", "yellowtang.jpg", "bluetang.jpg", "bluetang.jpg" ] # We can load all the files here # Does it matter compared to later? Probably not. loaded_textures = [] for tex_path in textures: loaded_textures.append(bpy.data.images.load(tex_path)) bpy.ops.object.mode_set(mode='EDIT') # We're not going to use the coordinates unwrap generates anyway # Just need a uv attribute bpy.ops.uv.unwrap(method='ANGLE_BASED') bpy.ops.object.mode_set(mode='OBJECT') # The materials need to be attached to the cube cube.data.materials.clear() # Clear any existing materials on the cube for mat in materials: cube.data.materials.append(mat) # Define UV mapping coordinates (one per face of the cube) face_uvs = [ [(1, 0), (1, 1), (0, 1), (0, 0)], # Back face [(1, 0), (1, 1), (0, 1), (0, 0)], # Right face [(1, 0), (1, 1), (0, 1), (0, 0)], # Front face [(1, 0), (1, 1), (0, 1), (0, 0)], # Left face [(0, 0), (1, 0), (1, 1), (0, 1)], # Bottom face [(0, 0), (1, 0), (1, 1), (0, 1)], # Top face ] # In the bmesh, we had faces # We don't seem to have faces in cube.data # "polygon" seems to be a synonym for "face" # Apparently older versions of the API used the term "face" for i, poly in enumerate(cube.data.polygons): # This is the same process we've been using for materials # Get the Principled BSDF shader bsdf_node = materials[i].node_tree.nodes.get("Principled BSDF") # Create the texture node and assign the image texture_node = materials[i].node_tree.nodes.new(type="ShaderNodeTexImage") texture_node.image = loaded_textures[i] # Link the texture to the BSDF shader materials[i].node_tree.links.new(texture_node.outputs["Color"], bsdf_node.inputs["Base Color"]) # Set the material index for this polygon # Since we have a list of 6 materials for the cube poly.material_index = i # Get the UV layer for the face uv_layer = cube.data.uv_layers.active.data # Copy over uv values for j, loop_index in enumerate(poly.loop_indices): uv_layer[loop_index].uv = face_uvs[i][j]