import bpy
import math
def setup_clear_scene():
"""Clears all mesh objects from the initial scene safely, avoiding lights and cameras."""
if bpy.context.object and bpy.context.object.mode != 'OBJECT':
bpy.ops.object.mode_set(mode='OBJECT')
bpy.ops.object.select_all(action='DESELECT')
for obj in bpy.context.scene.objects:
if obj.type == 'MESH':
obj.select_set(True)
bpy.ops.object.delete()
def get_or_create_collection(collection_name):
"""Creates a custom collection if it doesn't exist and links it to the scene."""
if collection_name in bpy.data.collections:
return bpy.data.collections[collection_name]
new_collection = bpy.data.collections.new(collection_name)
bpy.context.scene.collection.children.link(new_collection)
return new_collection
def get_or_create_material(name, color):
"""Reuses an existing material if it matches the name to prevent duplicate blocks."""
if name in bpy.data.materials:
return bpy.data.materials[name]
mat = bpy.data.materials.new(name=name)
mat.use_nodes = True
nodes = mat.node_tree.nodes
nodes["Principled BSDF"].inputs[0].default_value = color
return mat
def apply_subdivision_and_smooth(obj, levels=2):
"""Applies Subdivision Surface modifier and enables smooth shading natively."""
if hasattr(obj.data, "polygons"):
for poly in obj.data.polygons:
poly.use_smooth = True
subsurf = obj.modifiers.new(name="Subdivision", type='SUBSURF')
subsurf.levels = levels
subsurf.render_levels = levels
def set_parent_keep_transform(child, parent):
"""Establishes a robust parent-child relationship while safely preserving world transform offsets."""
child.parent = parent
child.matrix_parent_inverse = parent.matrix_world.inverted()
def create_bear_model_perfect_v3():
# Safe pipeline initialization
setup_clear_scene()
# Collection Setup for Better Asset Management
bear_collection = get_or_create_collection("Collection_Bear")
# Safely backup and set active layer collection context using proper Blender API properties
original_layer_collection = bpy.context.view_layer.active_layer_collection
bear_layer_collection = bpy.context.view_layer.layer_collection.children.get(bear_collection.name)
if bear_layer_collection:
bpy.context.view_layer.active_layer_collection = bear_layer_collection
# Material palette definition with duplicate prevention logic
mat_dark_brown = get_or_create_material("Mat_DarkBrown", (0.05, 0.02, 0.01, 1))
mat_light_brown = get_or_create_material("Mat_LightBrown", (0.2, 0.1, 0.05, 1))
mat_black = get_or_create_material("Mat_Black", (0.01, 0.01, 0.01, 1))
# --- 1. Main Parent Body ---
bpy.ops.mesh.primitive_uv_sphere_add(radius=1.5, location=(0, 0, 1.5))
body = bpy.context.active_object
body.name = "Bear_Body"
body.scale = (1, 1.4, 1.1)
body.data.materials.append(mat_dark_brown)
apply_subdivision_and_smooth(body, levels=2)
bpy.context.view_layer.update()
# --- 2. Shoulder Hump ---
bpy.ops.mesh.primitive_uv_sphere_add(radius=0.9, location=(0, 0.5, 2.7))
hump = bpy.context.active_object
hump.name = "Bear_Hump"
hump.scale = (1, 0.9, 0.7)
hump.data.materials.append(mat_dark_brown)
apply_subdivision_and_smooth(hump, levels=2)
set_parent_keep_transform(hump, body)
# --- 3. Head ---
bpy.ops.mesh.primitive_uv_sphere_add(radius=0.7, location=(0, 1.8, 2.3))
head = bpy.context.active_object
head.name = "Bear_Head"
head.data.materials.append(mat_light_brown)
apply_subdivision_and_smooth(head, levels=2)
set_parent_keep_transform(head, body)
bpy.context.view_layer.update()
# --- 4. Snout ---
bpy.ops.mesh.primitive_uv_sphere_add(radius=0.4, location=(0, 2.3, 2.2))
snout = bpy.context.active_object
snout.name = "Bear_Snout"
snout.scale = (0.8, 1, 0.7)
snout.data.materials.append(mat_light_brown)
apply_subdivision_and_smooth(snout, levels=2)
set_parent_keep_transform(snout, head)
# --- 5. Nose Tip ---
bpy.ops.mesh.primitive_uv_sphere_add(radius=0.1, location=(0, 2.7, 2.2))
nose = bpy.context.active_object
nose.name = "Bear_Nose_Tip"
nose.data.materials.append(mat_black)
apply_subdivision_and_smooth(nose, levels=2)
set_parent_keep_transform(nose, head)
# --- 6. Ears with Subdivided Multi-Material Mapping ---
ear_locations = [(-0.4, 1.8, 2.9), (0.4, 1.8, 2.9)]
for i, loc in enumerate(ear_locations):
side = "L" if i == 0 else "R"
bpy.ops.mesh.primitive_uv_sphere_add(radius=0.2, location=loc)
ear = bpy.context.active_object
ear.name = f"Bear_Ear_{side}"
ear.scale = (1, 0.5, 1)
# Assign multiple materials to the mesh data slot
ear.data.materials.append(mat_dark_brown) # Index 0
ear.data.materials.append(mat_light_brown) # Index 1
# Enter edit mode context and return to update structures safely
bpy.ops.object.mode_set(mode='EDIT')
bpy.ops.mesh.select_all(action='DESELECT')
bpy.ops.object.mode_set(mode='OBJECT')
# Dynamic Material Indexing via Y-axis Normal check
for poly in ear.data.polygons:
if poly.normal.y > 0.15:
poly.material_index = 1 # Assign Mat_LightBrown to the front/inner side
bpy.ops.object.mode_set(mode='OBJECT')
apply_subdivision_and_smooth(ear, levels=2)
set_parent_keep_transform(ear, head)
# --- 7. Legs ---
leg_locations = [(-0.7, 1.0, 0.7), (0.7, 1.0, 0.7), (-0.7, -0.8, 0.7), (0.7, -0.8, 0.7)]
for i, loc in enumerate(leg_locations):
bpy.ops.mesh.primitive_cylinder_add(radius=0.4, depth=1.5, location=loc)
leg = bpy.context.active_object
leg.name = f"Bear_Leg_{i}"
leg.data.materials.append(mat_dark_brown)
apply_subdivision_and_smooth(leg, levels=2)
set_parent_keep_transform(leg, body)
# --- 8. Eyes with Beautiful Curved Conformance ---
# Right Eye (Eye_R)
bpy.ops.mesh.primitive_uv_sphere_add(radius=0.1, location=(0.3, 2.4, 2.5))
eye_r = bpy.context.active_object
eye_r.name = "Bear_Eye_R"
eye_r.scale = (0.9, 0.25, 0.8)
eye_r.rotation_euler = (math.radians(10), math.radians(15), math.radians(-22))
eye_r.data.materials.append(mat_black)
apply_subdivision_and_smooth(eye_r, levels=2)
set_parent_keep_transform(eye_r, head)
# Left Eye (Eye_L)
bpy.ops.mesh.primitive_uv_sphere_add(radius=0.1, location=(-0.3, 2.4, 2.5))
eye_l = bpy.context.active_object
eye_l.name = "Bear_Eye_L"
eye_l.scale = (0.9, 0.25, 0.8)
eye_l.rotation_euler = (math.radians(10), math.radians(-15), math.radians(22))
eye_l.data.materials.append(mat_black)
apply_subdivision_and_smooth(eye_l, levels=2)
set_parent_keep_transform(eye_l, head)
# --- 9. Tail ---
bpy.ops.mesh.primitive_uv_sphere_add(radius=0.25, location=(0, -1.9, 1.6))
tail = bpy.context.active_object
tail.name = "Bear_Tail"
tail.data.materials.append(mat_dark_brown)
apply_subdivision_and_smooth(tail, levels=2)
set_parent_keep_transform(tail, body)
# Restore the original active layer collection context safely
bpy.context.view_layer.active_layer_collection = original_layer_collection
if __name__ == "__main__":
create_bear_model_perfect_v3()
Comments
Post a Comment