import bpy import math # Clear existing objects to ensure a clean start bpy.ops.object.select_all(action='SELECT') bpy.ops.object.delete(use_global=False) # --- Helper Functions --- def create_cube(name, loc, size, color, bevel=0.01): """Creates a low-poly cube with a small bevel.""" obj = bpy.data.objects.new(name, bpy.data.meshes.new(name)) obj.location = loc obj.rotation_euler = (math.radians(45), math.radians(45), 0) # Isometric view rotation bpy.context.collection.objects.link(obj) mesh = obj.data vertices = [(0,0,0), (size[0],0,0), (size[0],size[1],0), (0,size[1],0), (0,0,size[2]), (size[0],0,size[2]), (size[0],size[1],size[2]), (0,size[1],size[2])] faces = [(0,1,2,3), (4,5,6,7), (0,1,5,4), (2,3,7,6), (0,3,7,4), (1,2,6,5)] mesh.from_pydata(vertices, [], faces) mesh.update() # Apply bevel for face in mesh.polygons: for edge_idx in face.loop_indices: edge = mesh.edges[edge_idx] edge.bevel_weight = 1.0 mat = bpy.data.materials.new(name=f"{name}_mat") mat.use_nodes = True bsdf = mat.node_tree.nodes["Principled BSDF"] bsdf.inputs["Base Color"].default_value = color bsdf.inputs["Roughness"].default_value = 0.8 bsdf.inputs["Metallic"].default_value = 0.0 obj.data.materials.append(mat) return obj def create_cylinder(name, loc, radius, height, color, segments=8, bevel=0.01): """Creates a low-poly cylinder.""" obj = bpy.data.objects.new(name, bpy.data.meshes.new(name)) obj.location = loc obj.rotation_euler = (math.radians(45), math.radians(45), 0) bpy.context.collection.objects.link(obj) mesh = obj.data vertices = [] faces = [] verts_count = 0 # Top and Bottom for i in range(segments): angle = math.radians(i * 360 / segments) x = radius * math.cos(angle) z = radius * math.sin(angle) vertices.append((x, 0, z)) # Bottom vertices.append((x, 0, z + height)) # Top verts_count += 2 # Bottom Face faces.append([0, 1, 2]) for i in range(1, segments): faces.append([i, i+1, i+2]) faces.append([segments, 0, segments+1]) # Top Face (inverted) for i in range(segments): idx = i * 2 + 1 next_idx = ((i + 1) * 2 + 1) % (segments * 2) faces.append([idx, next_idx, idx + segments]) # Side Faces for i in range(segments): idx = i * 2 next_idx = ((i + 1) * 2) % (segments * 2) top_idx = idx + 1 next_top_idx = next_idx + 1 faces.append([idx, next_idx, next_top_idx, top_idx]) mesh.from_pydata(vertices, [], faces) mesh.update() for face in mesh.polygons: for edge_idx in face.loop_indices: edge = mesh.edges[edge_idx] edge.bevel_weight = 1.0 mat = bpy.data.materials.new(name=f"{name}_mat") mat.use_nodes = True bsdf = mat.node_tree.nodes["Principled BSDF"] bsdf.inputs["Base Color"].default_value = color bsdf.inputs["Roughness"].default_value = 0.8 obj.data.materials.append(mat) return obj # --- Materials Definition --- # Palette: 859eae (Dusty Blue), ece3d0 (Cream), 9b7359 (Warm Wood), cb8d74 (Accent) COLORS = { 'blue': (0.529, 0.620, 0.549), 'cream': (0.929, 0.902, 0.824), 'wood': (0.604, 0.451, 0.345), 'accent': (0.796, 0.545, 0.459) } # --- Scene Setup --- # Floor floor = create_cube("floor", (0, 0, 0.1), (5.6, 5.6, 0.2), COLORS['cream']) # Walls wall_back = create_cube("wall_back", (0, 2.7, 1.7), (5.6, 0.15, 3.0), COLORS['blue']) wall_side = create_cube("wall_side", (-2.7, 0, 1.7), (0.15, 5.6, 3.0), COLORS['blue']) # --- Furniture Generation --- # 1. Bed (1.6m wide) # Frame bed_frame = create_cube("bed_frame", (0.8, 1.0, 0.2), (1.6, 2.0, 0.2), COLORS['wood']) # Mattress bed_mattress = create_cube("bed_mattress", (0.8, 1.0, 0.9), (1.6, 2.0, 0.2), COLORS['cream']) # Pillow Left pillow_l = create_cube("pillow_l", (0.4, 1.0, 1.0), (0.5, 0.6, 0.2), COLORS['blue']) # Pillow Right pillow_r = create_cube("pillow_r", (1.2, 1.0, 1.0), (0.5, 0.6, 0.2), COLORS['blue']) # Blanket (Folded) blanket = create_cube("blanket", (0.8, 1.0, 0.9), (1.4, 1.8, 0.2), COLORS['accent']) # 2. Bedside Cabinet cabinet = create_cube("cabinet", (2.2, 0.5, 0.2), (0.6, 0.6, 0.6), COLORS['wood']) # Cabinet Top cabinet_top = create_cube("cabinet_top", (2.2, 0.5, 0.8), (0.6, 0.6, 0.1), COLORS['cream']) # Lamp Base lamp_base = create_cylinder("lamp_base", (2.4, 0.5, 0.8), 0.08, 0.1, COLORS['wood']) # Lamp Shade lamp_shade = create_cylinder("lamp_shade", (2.4, 0.5, 1.0), 0.12, 0.15, COLORS['cream']) # 3. Two-Door Wardrobe wardrobe_base = create_cube("wardrobe_base", (-1.0, 0.5, 0.2), (1.2, 1.8, 0.2), COLORS['wood']) # Wardrobe Doors (Left) door_l = create_cube("wardrobe_door_l", (-1.0, 0.5, 0.9), (0.6, 1.8, 0.05), COLORS['cream']) # Wardrobe Doors (Right) door_r = create_cube("wardrobe_door_r", (-0.4, 0.5, 0.9), (0.6, 1.8, 0.05), COLORS['cream']) # Handles handle_l = create_cylinder("handle_l", (-0.8, 0.5, 1.0), 0.01, 0.1, COLORS['wood']) handle_r = create_cylinder("handle_r", (-0.2, 0.5, 1.0), 0.01, 0.1, COLORS['wood']) # 4. Rug rug = create_cube("rug", (0.0, 0.0, 0.2), (2.0, 1.5, 0.02), COLORS['blue']) # 5. Potted Plant pot = create_cube("pot", (2.8, 1.2, 0.2), (0.3, 0.3, 0.3), COLORS['wood']) plant_stem = create_cube("plant_stem", (2.8, 1.2, 0.5), (0.05, 0.05, 0.4), COLORS['cream']) plant_leaves = create_cube("plant_leaves", (2.8, 1.2, 0.8), (0.2, 0.2, 0.2), COLORS['blue']) # 6. Framed Art frame = create_cube("frame", (0.0, 2.5, 1.7), (0.8, 0.6, 0.02), COLORS['wood']) canvas = create_cube("canvas", (0.0, 2.5, 1.7), (0.7, 0.5, 0.01), COLORS['accent']) # --- Final Cleanup and Optimization --- # Ensure all objects are in the main collection for obj in bpy.data.objects: if obj.name not in ['floor', 'wall_back', 'wall_side']: bpy.context.collection.objects.link(obj) # Merge geometry where appropriate to reduce polygon count if needed, # but keeping them separate allows for semantic naming as requested. # The bevels are small (0.01) to maintain low poly count while adding detail. print("Low-poly bedroom scene created successfully.")