Skip to content

Latest commit

 

History

History
339 lines (279 loc) · 11.3 KB

File metadata and controls

339 lines (279 loc) · 11.3 KB
Error in user YAML: (<unknown>): could not find expected ':' while scanning a simple key at line 3 column 1
---
- oeasy Python 0738
- 这是 oeasy 系统化 Python 教程,从基础一步步讲,扎实、完整、不跳步。愿意花时间学,就能真正学会。
本教程同步发布在: 

     个人网站: `https://oeasy.org` 
     蓝桥云课: `https://www.lanqiao.cn/courses/3584` 
     GitHub: `https://github.com/overmind1980/oeasy-python-tutorial` 
     Gitee: `https://gitee.com/overmind1980/oeasypython` 
---

效果

图片描述

import bpy
import math

# --- 场景初始化 ---
bpy.ops.object.select_all(action='SELECT')
bpy.ops.object.delete(use_global=False)
bpy.context.scene.frame_set(1)

# --- 材质创建函数 ---
def create_material(name, color, alpha=1.0):
    mat = bpy.data.materials.new(name=name)
    mat.use_nodes = False  # 禁用节点系统
    mat.diffuse_color = (*color, alpha)  # 设置漫反射颜色和透明度
    if alpha < 1.0:
        mat.blend_method = 'BLEND'  # 透明材质需要启用混合模式
    return mat

# --- 全局材质定义 ---
car_body_mat = create_material("CarBody", (1.0, 0.7, 0.85))   # 亮粉色车身
car_roof_mat = create_material("CarRoof", (0.9, 0.5, 0.7))    # 深粉色车顶
wheel_mat = create_material("Wheel", (0.2, 0.2, 0.2))         # 深灰车轮
window_mat = create_material("Window", (0.95, 0.85, 0.9), 0.3)# 浅粉车窗(带透明度)
light_mat = create_material("Light", (1.0, 0.9, 0.3))         # 车灯

road_mat = create_material("Road", (0.08, 0.08, 0.08))        # 近黑色马路
road_line_mat = create_material("RoadLine", (0.9, 0.9, 0.9))  # 白色马路线

tree_trunk_mat = create_material("TreeTrunk", (0.4, 0.2, 0.1))# 棕色树干
tree_leaves_mat = create_material("TreeLeaves", (0.1, 0.6, 0.1))# 绿色树叶
grass_mat = create_material("Grass", (0.2, 0.6, 0.2))         # 草地

# 车窗透明度
# 删除以下两行节点相关代码
# window_mat.blend_method = 'BLEND'
# window_mat.node_tree.nodes["Principled BSDF"].inputs[18].default_value = 0.3

# --- 粉色小车创建 ---
def create_cute_car():
    # 删除此处重复的材质定义代码块
    
    # 车身
    bpy.ops.mesh.primitive_cube_add(size=2, location=(0, 0, 0.5))
    car_body = bpy.context.active_object
    car_body.name = "CarBody"
    car_body.scale = (1.5, 0.8, 0.4)
    bpy.ops.object.transform_apply(location=False, rotation=False, scale=True)
    bpy.ops.object.mode_set(mode='EDIT')
    bpy.ops.mesh.select_all(action='SELECT')
    bpy.ops.mesh.subdivide(number_cuts=2)
    bpy.ops.object.mode_set(mode='OBJECT')
    bpy.ops.object.modifier_add(type='SUBSURF')
    car_body.data.materials.append(car_body_mat)

    # 车顶
    bpy.ops.mesh.primitive_cube_add(size=1, location=(0, 0, 1.2))
    car_roof = bpy.context.active_object
    car_roof.name = "CarRoof"
    car_roof.scale = (1.0, 0.6, 0.5)
    car_roof.data.materials.append(car_roof_mat)

    # 球形车轮
    wheel_positions = [(-1.0, -0.9, 0.3), (1.0, -0.9, 0.3), (-1.0, 0.9, 0.3), (1.0, 0.9, 0.3)]
    wheels = []
    for i, pos in enumerate(wheel_positions):
        bpy.ops.mesh.primitive_uv_sphere_add(radius=0.3, location=pos)
        wheel = bpy.context.active_object
        wheel.name = f"Wheel_{i+1}"
        wheel.data.materials.append(wheel_mat)
        wheels.append(wheel)

    # 车窗、车灯
    bpy.ops.mesh.primitive_cube_add(size=0.8, location=(0, 0, 1.3))
    window = bpy.context.active_object
    window.name = "Window"
    window.scale = (0.8, 0.5, 0.3)
    window.data.materials.append(window_mat)

    bpy.ops.mesh.primitive_uv_sphere_add(radius=0.1, location=(1.4, -0.3, 0.7))
    light1 = bpy.context.active_object
    light1.name = "Headlight1"
    light1.data.materials.append(light_mat)

    bpy.ops.mesh.primitive_uv_sphere_add(radius=0.1, location=(1.4, 0.3, 0.7))
    light2 = bpy.context.active_object
    light2.name = "Headlight2"
    light2.data.materials.append(light_mat)

    # 组合汽车部件
    car_parts = [car_body, car_roof, window, light1, light2] + wheels
    bpy.ops.object.empty_add(location=(0, 0, 0))
    car_parent = bpy.context.active_object
    car_parent.name = "CuteCar"
    for part in car_parts:
        part.parent = car_parent
    return car_parent, wheels

# --- 马路创建 ---
def create_road(road_length):
    # 马路主体
    bpy.ops.mesh.primitive_cube_add(size=2, location=(0, 0, -0.1))
    road = bpy.context.active_object
    road.name = "Road"
    road.scale = (road_length / 2, 4, 0.1)
    road.data.materials.append(road_mat)
    
    # 白色马路线
    bpy.ops.mesh.primitive_cube_add(size=1, location=(0, 0, 0.01))
    road_line = bpy.context.active_object
    road_line.name = "RoadLine"
    road_line.scale = (road_length - 2, 0.1, 0.01)
    road_line.data.materials.append(road_line_mat)
    return road, road_line  # 返回马路对象以便设置父级

# --- 草地创建 ---
def create_grass():
    bpy.ops.mesh.primitive_plane_add(size=300, location=(0, 0, -0.2))
    grass = bpy.context.active_object
    grass.name = "Grass"
    grass.data.materials.append(grass_mat)
    return grass

# --- 场景组合 ---
road_length = 160

# 创建顶级容器
background = bpy.data.objects.new("background", None)
bpy.data.collections["Collection"].objects.link(background)

trees_container = bpy.data.objects.new("trees", None)
trees_container.parent = background
bpy.context.collection.objects.link(trees_container)

lighting = bpy.data.objects.new("照明", None)
bpy.context.collection.objects.link(lighting)

# 创建场景元素并分配父级
grass = create_grass()
grass.parent = background

road, road_line = create_road(road_length)
road.parent = background
road_line.parent = background

car, wheels = create_cute_car()


# --- 树木创建 ---
def create_christmas_tree(location, tree_id):
    # 树干
    bpy.ops.mesh.primitive_cylinder_add(radius=0.2, depth=1.5, location=location)
    trunk = bpy.context.active_object
    trunk.name = f"TreeTrunk_{tree_id}"
    trunk.location[2] += 0.75
    trunk.data.materials.append(tree_trunk_mat)

    tree_parts = [trunk]

    # 树叶
    bpy.ops.mesh.primitive_cone_add(radius1=1.5, radius2=0, depth=2, location=location)
    bottom_layer = bpy.context.active_object
    bottom_layer.name = f"TreeBottom_{tree_id}"
    bottom_layer.location[2] += 2.5
    bottom_layer.data.materials.append(tree_leaves_mat)
    tree_parts.append(bottom_layer)

    bpy.ops.mesh.primitive_cone_add(radius1=1.2, radius2=0, depth=1.8, location=location)
    middle_layer = bpy.context.active_object
    middle_layer.name = f"TreeMiddle_{tree_id}"
    middle_layer.location[2] += 3.2
    middle_layer.data.materials.append(tree_leaves_mat)
    tree_parts.append(middle_layer)

    bpy.ops.mesh.primitive_cone_add(radius1=0.8, radius2=0, depth=1.5, location=location)
    top_layer = bpy.context.active_object
    top_layer.name = f"TreeTop_{tree_id}"
    top_layer.location[2] += 3.8
    top_layer.data.materials.append(tree_leaves_mat)
    tree_parts.append(top_layer)

    # 组合树木
    bpy.ops.object.empty_add(location=location)
    tree_parent = bpy.context.active_object
    tree_parent.name = f"ChristmasTree_{tree_id}"
    for part in tree_parts:
        part.parent = tree_parent

    return tree_parent

# 树木分布
tree_spacing = 4
tree_distance_from_road = 3
num_trees = road_length // tree_spacing + 1

# 左侧树木
for i in range(num_trees):
    x_pos = -road_length//2 + i * tree_spacing
    tree_pos = (x_pos, -tree_distance_from_road, 0)
    tree = create_christmas_tree(tree_pos, f"L_{i}")
    tree.parent = trees_container

# 右侧树木
for i in range(num_trees):
    x_pos = -road_length//2 + i * tree_spacing
    tree_pos = (x_pos, tree_distance_from_road, 0)
    tree = create_christmas_tree(tree_pos, f"R_{i}")
    tree.parent = trees_container

# --- 相机与灯光 ---
camera = bpy.data.cameras.new('Camera')
camera = bpy.data.objects.new('Camera', camera)
bpy.data.collections["Collection"].objects.link(camera)
camera.location = (-20.6, -19.7, 29.3)
camera.rotation_euler = (0.8, 0, 0.8)

# 阳光
bpy.ops.object.light_add(type='SUN', location=(10, 10, 20))
sun = bpy.context.active_object
sun.data.energy = 3
sun.rotation_euler = (math.radians(60), math.radians(30), math.radians(45))
sun.parent = lighting

# 区域光
bpy.ops.object.light_add(type='AREA', location=(0, 0, 15))
area_light = bpy.context.active_object
area_light.data.energy = 2.5
area_light.data.size = 20
area_light.parent = lighting

# --- 动画设置 ---
frame_start = 1
frame_end = 800
bpy.context.scene.frame_start = frame_start
bpy.context.scene.frame_end = frame_end

# 小车移动
bpy.context.scene.frame_set(frame_start)
car.location = (-road_length//2 + 5, 0, 0)
car.keyframe_insert(data_path="location", index=-1, frame=frame_start)

bpy.context.scene.frame_set(frame_end)
car.location = (road_length//2 - 5, 0, 0)
car.keyframe_insert(data_path="location", index=-1, frame=frame_end)

# 车轮旋转
rotation_speed = 32
for wheel in wheels:
    bpy.context.scene.frame_set(frame_start)
    wheel.rotation_euler = (0, 0, 0)
    wheel.keyframe_insert(data_path="rotation_euler", index=-1, frame=frame_start)

    bpy.context.scene.frame_set(frame_end)
    wheel.rotation_euler = (0, rotation_speed * 2 * math.pi, 0)
    wheel.keyframe_insert(data_path="rotation_euler", index=-1, frame=frame_end)

# 线性插值确保匀速
for obj in bpy.data.objects:
    if obj.animation_data and obj.animation_data.action:
        for fcurve in obj.animation_data.action.fcurves:
            for keyframe in fcurve.keyframe_points:
                keyframe.interpolation = 'LINEAR'

# --- 兼容不同Blender版本的视图设置 ---
for area in bpy.context.screen.areas:
    if area.type == 'VIEW_3D':
        area.spaces[0].shading.type = 'SOLID'
        area.spaces[0].shading.color_type = 'MATERIAL'
        area.spaces[0].shading.show_object_outline = False
        
        # 检查属性是否存在,兼容不同Blender版本
        overlay = area.spaces[0].overlay
        if hasattr(overlay, 'show_grid'):
            overlay.show_grid = False  # 旧版本属性
        elif hasattr(overlay, 'grid_scale'):
            overlay.grid_scale = 0     # 新版本替代方案
            
        if hasattr(overlay, 'show_axis_x'):
            overlay.show_axis_x = False
            overlay.show_axis_y = False
            overlay.show_axis_z = False
            
        if hasattr(overlay, 'show_outline_selected'):
            overlay.show_outline_selected = False

bpy.context.scene.frame_set(frame_start)

bpy.context.scene.camera = camera
bpy.context.scene.render.resolution_x = 640
bpy.context.scene.render.resolution_y = 480
bpy.context.scene.render.resolution_percentage = 50

# Set the render engine (e.g., CYCLES, BLENDER_EEVEE)
bpy.context.scene.render.engine = 'EEVEE'

# Set the output file path
bpy.context.scene.render.filepath = '/tmp/render2.png'

# Render the current view
bpy.ops.render.render(write_still=True)
print("已保留白色马路线,移除其他辅助线!")
print("在Layout视图中可看到:")
print("- 黑色马路中间有白色中心线")
print("- 无网格线、坐标轴等干扰元素")
print("- 粉色小车在马路上行驶,两侧是绿色树木")
print("按空格键播放动画查看效果")

设置摄影机

  • 小汽车的
    • 顶视图
    • 正面
    • 背面
    • 侧面
    • 45度

设置摄影机

  • 动画的入画和出画
  • 跟随 效果
  • 跳切效果

  • 本文来自 oeasy Python 系统教程。
  • 想完整、扎实学 Python,
  • 搜索 oeasy 即可。