Skip to content

Latest commit

 

History

History
1237 lines (975 loc) · 39 KB

File metadata and controls

1237 lines (975 loc) · 39 KB
Error in user YAML: (<unknown>): did not find expected key while parsing a block mapping at line 1 column 1
---
show: step
version: 1.0 
enable_checker: true
- 本教程同步发布在: 
	- 个人网站: `https://oeasy.org` 
	- 蓝桥云课: `https://www.lanqiao.cn/courses/3584` 
	- GitHub: `https://github.com/overmind1980/oeasy-python-tutorial` 
	- Gitee: `https://gitee.com/overmind1980/oeasypython` 
---

  • oeasy Python 0724
  • 这是 oeasy 系统化 Python 教程,从基础一步步讲,扎实、完整、不跳步。愿意花时间学,就能真正学会。

python_blender

汽车

图片描述

  • 汽车
import bpy

def delete_all():
    # clear current scene
    bpy.ops.object.select_all(action="SELECT") # 选择所有物体
    bpy.ops.object.delete() # 删除选定的物体

def create_car_body():
    bpy.ops.mesh.primitive_cube_add(size=2, location=(0, 0, 1))
    car_body = bpy.context.object
    car_body.name = "CarBody"
    return car_body

def create_wheel(location):
    bpy.ops.mesh.primitive_cylinder_add(radius=0.5, depth=0.3, location=location)
    wheel = bpy.context.object
    wheel.rotation_euler[0] = 1.5708 # 旋转90度使轮子正确对齐
    wheel.name = "Wheel"
    return wheel

def create_car():
    car_body = create_car_body()
    wheel_locations = [
    (-0.8, -1.2, 0.3),
    (0.8, -1.2, 0.3),
    (-0.8, 1.2, 0.3),
    (0.8, 1.2, 0.3)
    ]
    wheels = [create_wheel(loc) for loc in wheel_locations]
    return car_body, wheels

def apply_material(obj, name, color):
    material = bpy.data.materials.new(name=name)
    material.node_tree.nodes["Principled BSDF"].inputs['Base Color'].default_value = color
    obj.data.materials.append(material)

def set_lighting():
    bpy.ops.object.light_add(type='SPOT', location=(4, 3.26, 2.89))
    spot_light = bpy.context.object
    spot_light.data.energy = 1000
    spot_light.data.spot_size = 0.7854 # 45 degrees
    spot_light.data.spot_blend = 0.15
    spot_light.rotation_euler = (71/360.0*6.28, 0, 125.4/360.0*6.28) # 45 degrees

def set_camera():
    bpy.ops.object.camera_add(location=(6, -6, 4))
    camera = bpy.context.object
    camera.rotation_euler = (1.2, 0, 0.7854) # 设置适当的角度
    bpy.context.scene.camera = camera

def render_image(filepath):
    bpy.context.scene.render.filepath = filepath
    bpy.ops.render.render(write_still=True)


# Step 1: Delete all existing objects
delete_all()
# Step 2: Create the car model (素模)
car_body, wheels = create_car()
# Set lighting and camera
set_lighting()
set_camera()
# Render and save 素模
render_image('/tmp/car_plain.png')
# Step 3: Apply materials for 彩模
apply_material(car_body, "CarBodyMaterial", (0.8, 0.1, 0.1, 1)) # Red color
for wheel in wheels:
    apply_material(wheel, "WheelMaterial", (0.1, 0.1, 0.1, 1)) # Black color
# Render and save 彩模
render_image('car_colored.png')

tank

图片描述

  • tank
# 创建一个材质
import bpy
import math
# 清除场景中的默认物体

bpy.ops.object.select_all(action='SELECT')
bpy.ops.object.delete()

bpy.ops.mesh.primitive_cube_add(size=2)
tank_body = bpy.context.object
tank_body.location = (0, 0, 0)
tank_body.scale = (1, 1, 0.5)

# 炮筒
bpy.ops.mesh.primitive_cylinder_add(radius=0.2, depth=1.5)
tank_cannon = bpy.context.object
tank_cannon.location = (0, -1.5, 0)
tank_cannon.rotation_euler = (0, math.radians(-90), math.radians(90))

# 轮子(简单示例,实际需要多个并合理布局)
bpy.ops.mesh.primitive_cylinder_add(radius=0.3, depth=0.2)
tank_wheel_a = bpy.context.object
tank_wheel_a.location = (0.7, -0.5, -0.5)
tank_wheel_a.rotation_euler = (0, math.radians(90), 0)

bpy.ops.mesh.primitive_cylinder_add(radius=0.3, depth=0.2)
tank_wheel_b = bpy.context.object
tank_wheel_b.location = (0.7, 0.5, -0.5)
tank_wheel_b.rotation_euler = (0, math.radians(90), 0)

bpy.ops.mesh.primitive_cylinder_add(radius=0.3, depth=0.2)
tank_wheel_c = bpy.context.object
tank_wheel_c.location = (-0.7, -0.5, -0.5)
tank_wheel_c.rotation_euler = (0, math.radians(90), 0)


bpy.ops.mesh.primitive_cylinder_add(radius=0.3, depth=0.2)
tank_wheel_d = bpy.context.object
tank_wheel_d.location = (-0.7, 0.5, -0.5)
tank_wheel_d.rotation_euler = (0, math.radians(90), 0)

# 设置材质函数
def set_material(obj, color, name):
    mat = bpy.data.materials.new(name=name)
    mat.use_nodes = True
    mat.node_tree.nodes["Principled BSDF"].inputs['Base Color'].default_value = color
    obj.data.materials.append(mat)

set_material(tank_cannon, (0.8, 0.2, 0.2, 1.0), "CannonMaterial")
set_material(tank_body, (1, 1, 0.5, 1.0), "BodyMaterial")
set_material(tank_wheel_a, (0.8, 0.3, 0.8, 1.0), "WheelMaterialA")
set_material(tank_wheel_b, (0.8, 0.2, 0.9, 1.0), "WheelMaterialB")
set_material(tank_wheel_c, (0.8, 0.1, 0.5, 1.0), "WheelMaterialC")
set_material(tank_wheel_d, (0.1, 0.3, 0.9, 1.0), "WheelMaterialD")

# 设置渲染引擎为Cycles
bpy.context.scene.render.engine = 'CYCLES'

# 设置渲染分辨率
bpy.context.scene.render.resolution_x = 640
bpy.context.scene.render.resolution_y = 480
light_data = bpy.data.lights.new(name="Light", type='SUN')
light_data.energy = 10  # 设置光的强度
light_object = bpy.data.objects.new(name="LightObject", object_data=light_data)
bpy.context.collection.objects.link(light_object)
# 设置光源的位置
light_object.location = (5, 5, 5)

# 创建一个摄像机
bpy.ops.object.camera_add(location=(2.94, -4.78, 0.53))
camera = bpy.context.object
camera.rotation_euler = (83/180*3.14,0,29.6/180*3.14)
# 设置摄像机的方向
bpy.context.scene.camera = camera
bpy.ops.object.select_all(action='DESELECT')
camera.select_set(True)
bpy.ops.object.constraint_add(type='TRACK_TO')
bpy.context.object.constraints["Track To"].target = tank_body
bpy.context.object.constraints["Track To"].track_axis = 'TRACK_NEGATIVE_Z'
bpy.context.object.constraints["Track To"].up_axis = 'UP_Y'
bpy.context.scene.render.engine = 'CYCLES'
bpy.context.scene.render.filepath = '/tmp/tank.png'
bpy.ops.render.render(write_still=True)

大脚车

图片描述

import bpy
from math import pi

bpy.ops.object.select_all(action="SELECT") # 选择所有物体
bpy.ops.object.delete() # 删除选定的物

bpy.ops.mesh.primitive_cube_add( )
bpy.context.object.scale=(3, 5, 2)
mat = bpy.data.materials.new('mat_car')
color = (4,0.3,0.3,1)
mat.use_nodes = True
mat.node_tree.nodes["Principled BSDF"].inputs['Base Color'].default_value = color
bpy.context.object.data.materials.append(mat)

bpy.ops.mesh.primitive_cylinder_add(radius=3, depth=1)
bpy.context.object.rotation_euler[1] = pi /2
bpy.context.object.location = (4, 4 ,0)
mat = bpy.data.materials.new('mat_car1')
mat.use_nodes = True
color = (1,1.1,2,1)
mat.node_tree.nodes["Principled BSDF"].inputs['Base Color'].default_value = color
bpy.context.object.data.materials.append(mat)

bpy.ops.mesh.primitive_cylinder_add(radius=3, depth=1)
bpy.context.object.rotation_euler[1] = pi /2
bpy.context.object.location = (-4, 4 ,0)
mat = bpy.data.materials.new('mat_car1')
mat.use_nodes = True
color = (1,1.1,2,1)
mat.node_tree.nodes["Principled BSDF"].inputs['Base Color'].default_value = color
bpy.context.object.data.materials.append(mat)

bpy.ops.mesh.primitive_cylinder_add(radius=2, depth=1)
bpy.context.object.rotation_euler[1] = pi /2
bpy.context.object.location = (-4, -4 ,-1)
mat = bpy.data.materials.new('mat_car2')
mat.use_nodes = True
color = (1,2,2,1)
mat.node_tree.nodes["Principled BSDF"].inputs['Base Color'].default_value = color
bpy.context.object.data.materials.append(mat)

bpy.ops.mesh.primitive_cylinder_add(radius=2, depth=1)
bpy.context.object.rotation_euler[1] = pi /2
bpy.context.object.location = (4, -4 ,-1)
mat = bpy.data.materials.new('mat_car2')
mat.use_nodes = True
color = (1,2,2,1)
mat.node_tree.nodes["Principled BSDF"].inputs['Base Color'].default_value = color
bpy.context.object.data.materials.append(mat)

bpy.ops.mesh.primitive_cylinder_add(radius=0.1, depth=1)
bpy.context.object.rotation_euler[1] = pi /2
bpy.context.object.location = (3, -4 ,-0.5)
mat = bpy.data.materials.new('mat_car3')
mat.use_nodes = True
color = (0,0,0,1)
mat.node_tree.nodes["Principled BSDF"].inputs['Base Color'].default_value = color
bpy.context.object.data.materials.append(mat)


bpy.ops.mesh.primitive_cylinder_add(radius=0.1, depth=1)
bpy.context.object.rotation_euler[1] = pi /2
bpy.context.object.location = (-3, -4 ,-0.5)
mat = bpy.data.materials.new('mat_car3')
mat.use_nodes = True
color = (0,0,0,1)
mat.node_tree.nodes["Principled BSDF"].inputs['Base Color'].default_value = color
bpy.context.object.data.materials.append(mat)

bpy.ops.mesh.primitive_cylinder_add(radius=0.1, depth=1)
bpy.context.object.rotation_euler[1] = pi /2
bpy.context.object.location = (-3, 4 ,0)
mat = bpy.data.materials.new('mat_car3')
mat.use_nodes = True
color = (0,0,0,1)
mat.node_tree.nodes["Principled BSDF"].inputs['Base Color'].default_value = color
bpy.context.object.data.materials.append(mat)

bpy.ops.mesh.primitive_cylinder_add(radius=0.1, depth=1)
bpy.context.object.rotation_euler[1] = pi /2
bpy.context.object.location = (3, 4 ,0)
mat = bpy.data.materials.new('mat_car3')
mat.use_nodes = True
color = (0,0,0,1)
mat.node_tree.nodes["Principled BSDF"].inputs['Base Color'].default_value = color
bpy.context.object.data.materials.append(mat)

bpy.ops.mesh.primitive_plane_add(size=30)
bpy.context.object.location = (0,0,-3)

camera = bpy.data.cameras.new('MyCamera')
camera_obj = bpy.data.objects.new('CameraObj', camera)
bpy.context.scene.collection.objects.link(camera_obj)
camera.lens = 24  # Focal length in millimeters
camera_obj.location = (13,8,9)  # X, Y, Z coordinates
camera_obj.rotation_euler = (4,-9.5,5.3)
bpy.context.scene.camera = camera_obj

bpy.ops.object.light_add(type='SPOT', radius=3)    
light = bpy.context.object  
light.data.energy = 10000
light.location = (30.8, -14.4,33)  
light.rotation_euler = (6.98, 0, 0.98)  

bpy.context.scene.render.engine = 'CYCLES'  
bpy.context.scene.render.resolution_x = 640  
bpy.context.scene.render.resolution_y = 480  
bpy.context.scene.render.resolution_percentage = 50  
bpy.context.scene.render.filepath = "/tmp/xuanran.png"
bpy.context.scene.render.image_settings.file_format = 'PNG'  
bpy.context.scene.render.image_settings.color_mode = 'RGBA'  
  
bpy.ops.render.render(write_still=True)

汽车生命

  • 给汽车以生命
    • Animate the car

图片描述

  • animate这个词怎么来的?

animate

  • animate
    • 核心词根:anim- / anima-
      • 本义是呼吸、灵魂、生命
  • 古代人认为
    • 呼吸是生命的象征
    • 灵魂赋予事物生命
英文单词 英/美音标 核心词义
animate /ˈænɪmeɪt/(动)
/ˈænɪmət/(形)
v. 使生动;使活跃;制作动画
adj. 有生命的;鲜活的
animal /ˈænɪml/ n. 动物
adj. 动物的;肉体的
animation /ˌænɪˈmeɪʃn/ 动画;动画片;活力;生气
inanimate /ɪnˈænɪmət/ 无生命的;无生气的;呆板的
unanimous /juˈnænɪməs/ 全体一致的;意见统一的
animosity /ˌænɪˈmɒsəti/(英)
/ˌænɪˈmɑːsəti/(美)
敌意;仇恨;憎恶
magnanimous /mæɡˈnænɪməs/ 宽宏大量的;大度的;高尚的
pusillanimous /ˌpjuːsɪˈlænɪməs/ 胆小的;怯懦的;优柔寡断的
reanimate /riːˈænɪmeɪt/ 使复活;使恢复生机;重振
animus /ˈænɪməs/ 敌意;恶意;偏见(正式/书面)

开始

  • 上次通过python设置了舞台基本要素
    • 灯光
    • 物体
    • 摄像机
  • 并且将结果渲染为一张png
  • 可以让物体动起来吗?🤔

手动运动

  • 设置结束帧为10

图片描述

  • 通过调整滑杆
    • 控制时间轴范围

设置开始帧

  • 选中第1帧
    • 选中立方体
    • 设置属性
    • 并点击关键帧

图片描述

设置结束帧

  • 选中第10帧
    • 选中立方体
    • 设置属性
    • 并点击关键帧

图片描述

颜色作用

图片描述

点击播放

  • 观看效果

图片描述

  • 可以把这10帧导出吗?

导出设置

  • 控制输出大小
    • 宽度
    • 高度
    • 时间范围

图片描述

  • 输出结果

图片描述

  • 可以用代码
    • 完成上述操作吗?

动画设置

  • 新建工程
import bpy

obj = bpy.data.objects["Cube"]
obj.location = (0, 0, 0) 
obj.keyframe_insert(data_path="location", frame=1)  
obj.location = (10, 0, 0)
obj.keyframe_insert(data_path="location", frame=10) 
  • 执行后可以运动

图片描述

渲染设置

import bpy
bpy.context.scene.frame_end = 10
bpy.context.scene.render.resolution_x = 400
bpy.context.scene.render.resolution_y = 300
bpy.context.scene.render.engine = 'CYCLES'
bpy.context.scene.render.filepath = "/tmp/r"
bpy.ops.render.render(animation=True)
  • 可以渲染动画

图片描述

整合代码

  • 执行后可以运动
import bpy

obj = bpy.data.objects["Cube"]
obj.location = (0, 0, 0) 
obj.keyframe_insert(data_path="location")  
obj.location = (10, 0, 0)
obj.keyframe_insert(data_path="location", frame=10) 
bpy.context.scene.frame_end = 10
bpy.context.scene.render.resolution_x = 400
bpy.context.scene.render.resolution_y = 300
bpy.context.scene.render.engine = 'CYCLES'
bpy.ops.render.render(animation=True)
  • 设置并渲染成功

图片描述

  • 可以只设置location.x 上的关键帧吗?

手动过程

  • 新建工程

图片描述

  • 只设置了location.x在第1帧的数值

插入关键帧

  • 对于Cube设置
    • location.x
    • 在第10帧的关键帧

图片描述

  • 点击播放
    • 物体运动
  • 可以用代码来设置吗?

代码设置

  • 新建工程
obj = bpy.data.objects["Cube"]
obj.keyframe_insert(
  • 按下 tab

图片描述

  • 可以控制
    • 第index个分量的动画

代码

  • 新建工程
import bpy

obj = bpy.data.objects["Cube"]
obj.location[0] = 0
obj.keyframe_insert('location', index=0)  
obj.location[0] = 10
obj.keyframe_insert(data_path="location",index=0,frame=10) 
bpy.context.scene.frame_end = 10
bpy.context.scene.render.resolution_x = 200
bpy.context.scene.render.resolution_y = 150
bpy.context.scene.render.engine = 'CYCLES'
bpy.context.scene.render.filepath = "/home/shiyanlou/Code/o"
bpy.ops.render.render(animation=True)
  • 观察

图片描述

  • 有没有能够看图片序列的应用呢?

安装应用

sudo apt update
yes | sudo apt install feh
feh /home/shiyanlou/Code

  • 上下控制缩放
  • 左右控制帧号

图片描述

  • 最终图片序列
    • 可以下载得到

图片描述

  • 但是目前有个问题

看不见了

  • 从6到10
    • 这几帧都看不到了

图片描述

  • 摄影机位置
    • 需要调整

重修调整摄影机

  • 先调整当前活跃视角
    • active view

图片描述

  • 再将摄影机视角
    • 对齐到
    • 活跃视角
    • active view

图片描述

  • 可以直接渲染成视频文件吗?

渲染成视频

  • 控制分辨率
    • 帧数
import bpy

# 设置渲染路径和渲染动画
bpy.context.scene.render.filepath = "/tmp/house_animation"
bpy.context.scene.render.image_settings.file_format = 'FFMPEG'
bpy.ops.render.render(animation=True)
  • 做一个晴天娃娃的动画吧

晴天娃娃

import bpy

bpy.ops.object.select_all(action="SELECT") 
bpy.ops.object.delete() 
bpy.ops.mesh.primitive_uv_sphere_add()
head = bpy.context.object
bpy.context.object.name  = "head"
r_eye = bpy.ops.mesh.primitive_uv_sphere_add()
bpy.context.object.name = "r_eye"
bpy.context.object.location = (0.7, 0.5, 0.3)
bpy.context.object.scale = (0.3, 0.3, 0.3)
mat = bpy.data.materials.new('mat_eye')
color = (0, 0, 0, 1)
mat.diffuse_color = color
bpy.context.object.data.materials.append(mat)
bpy.context.object.parent = head
l_eye = bpy.ops.mesh.primitive_uv_sphere_add()
bpy.context.object.name = "l_eye"
bpy.context.object.location = (0.7, -0.5, 0.3)
bpy.context.object.scale = (0.3, 0.3, 0.3)
bpy.context.object.data.materials.append(mat)
bpy.context.object.parent = head
bpy.ops.mesh.primitive_cone_add()
body = bpy.context.object
body.name  = "body"
body.location = (0,0,-1)
body.scale = (1,1,2)
character = bpy.data.objects.new("character", None)
bpy.data.collections["Collection"].objects.link(character)
head.parent = character
body.parent = character
bpy.ops.mesh.primitive_plane_add(size=20)
bpy.context.object.location = (0,0,-3)

camera = bpy.data.cameras.new('Camera')
camera_obj = bpy.data.objects.new('Camera', camera)
bpy.data.collections["Collection"].objects.link(camera_obj)
camera.lens = 50  # Focal length in millimeters
camera.sensor_width = 36  # Sensor width in millimeters
camera.sensor_height = 24  # Sensor height in millimeters
camera_obj.location = (13.6, 5, 10.5)  # X, Y, Z coordinates
camera_obj.rotation_euler = (-2.233,3.14,-1.047)
bpy.context.scene.camera = camera_obj
bpy.ops.object.light_add(type='SPOT', radius=1)
bpy.data.lights["Spot"].energy = 1000
bpy.context.object.location = (6.27,-3.4,2.83)
bpy.context.object.rotation_euler = (1.172,0,0.907)

character.location = (0, 0, 0) 
character.keyframe_insert(data_path="location")  
character.location = (10, 0, 0)
character.keyframe_insert(data_path="location", frame=10) 

bpy.context.scene.frame_end = 10
bpy.context.scene.render.resolution_x = 200
bpy.context.scene.render.resolution_y = 150
bpy.context.scene.render.resolution_percentage = 50
bpy.context.scene.render.engine = 'CYCLES'
bpy.ops.render.render(animation=True)
  • 渲染成功

图片描述

  • 角色真的跑了

动画综合案例

图片描述

import bpy
from math import pi,cos,sin
import random

bpy.ops.object.select_all(action="SELECT")
bpy.ops.object.delete()

#制作土地
bpy.ops.mesh.primitive_plane_add(size=100, enter_editmode=False, align='WORLD', location=(25, 25, -2.5), scale=(1, 1, 20))
black = bpy.data.materials.new('black')
color = (0.1, 0.1, 0.1 ,1 )
black.diffuse_color = color
bpy.context.object.data.materials.append(black)

        
#选择花田的花朵的数量
size = 10
for n1 in range(size):
    for n2 in range(size):
        flower = bpy.data.objects.new("flower", None)
        bpy.data.collections["Collection"].objects.link(flower)
        '''
        #history version
        #如何实现多层封装,这样可以控制花的上部分随机方向转动
        #flower_ban = bpy.data.objects.new("flower_ban", None)
        #bpy.data.collections["Collection"].objects.link(flower_ban)
        #bpy.context.object.parent = flower
        '''


        #制作花心、花杆、花叶1、花叶2
        h = random.random()
        h = h + 3
        bpy.ops.mesh.primitive_uv_sphere_add(radius=1, enter_editmode=False, align='WORLD', location=(0, 0, h), scale=(1.5, 1.5, 0.3))
        bpy.context.object.name = "flower_xin"
        brown = bpy.data.materials.new('brown')
        color = (0.7 ,0.3 ,0.06 ,1 )
        brown.diffuse_color = color
        bpy.context.object.data.materials.append(brown)
        bpy.context.object.active_material.metallic = 1
        bpy.context.object.active_material.specular_intensity = 1
        bpy.context.object.active_material.roughness = 1        
        bpy.context.object.parent = flower
        
        bpy.ops.mesh.primitive_cylinder_add(radius=1, depth=2, enter_editmode=False, align='WORLD', location=(0, 0, 0), scale=(0.2, 0.2, h))
        bpy.context.object.name = "flower_gan"
        green_dark = bpy.data.materials.new('green_dark')
        color = (0,0.5,0.02,1 )
        green_dark.diffuse_color = color
        bpy.context.object.data.materials.append(green_dark)
        bpy.context.object.active_material.metallic = 1
        bpy.context.object.active_material.specular_intensity = 1
        bpy.context.object.active_material.roughness = 1
        bpy.context.object.parent = flower
        
        '''
        #没法选择融球
        #bpy.ops.object.metaball_add(type='ELLIPSOID', enter_editmode=False, align='WORLD', location=(0, 0.8, 1), scale=(0.4, 0.1, 1))
        '''
        
        bpy.ops.mesh.primitive_uv_sphere_add(enter_editmode=False, align='WORLD', location=(0, 0.8, 0.8), scale=(0.5, 0.1, 1.2))
        bpy.context.object.rotation_euler[0] = -40/360 * 2* pi
        bpy.context.object.name = "flower_ye1"
        green = bpy.data.materials.new('green')
        color = (0.2,0.6,0.05,1 )
        green.diffuse_color = color
        bpy.context.object.data.materials.append(green)
        bpy.context.object.active_material.metallic = 1
        bpy.context.object.active_material.specular_intensity = 1
        bpy.context.object.active_material.roughness = 1
        bpy.context.object.parent = flower
        
        '''
        #bpy.ops.object.metaball_add(type='ELLIPSOID', enter_editmode=False, align='WORLD', location=(0, -0.8, 1), scale=(0.4, 0.1, 1))
        '''
        
        bpy.ops.mesh.primitive_uv_sphere_add(enter_editmode=False, align='WORLD', location=(0, -0.8, 0.8), scale=(0.5, 0.1, 1.2))
        bpy.context.object.rotation_euler[0] = 40/360 * 2* pi
        bpy.context.object.name = "flower_ye2"
        bpy.context.object.data.materials.append(green)
        bpy.context.object.active_material.metallic = 1
        bpy.context.object.active_material.specular_intensity = 1
        bpy.context.object.active_material.roughness = 1
        bpy.context.object.parent = flower

        #制作花瓣
        r = 2
        num = 11
        w = random.random()
        for i in range(num):
            theta = i * pi * 2/num
            pos = (r*cos(theta) , r*sin(theta) , h)
            bpy.ops.mesh.primitive_cone_add(enter_editmode=False, align='WORLD', location=pos, scale=(1, 0.3, 0.6))
            bpy.context.object.name = "flower_ban"
            bpy.context.object.parent = flower
            #根据与花朵中心的位置关系,每个花瓣z轴方向旋转不同度
            bpy.context.object.rotation_euler[2] = (i * pi * 2/num) + 1.57
            #每个花瓣x轴旋转随机角度使之平躺 #所有的操作都是以自己为中心的
            bpy.context.object.rotation_euler[0] = 1.57-0.2*(w+1)
            yellow = bpy.data.materials.new('yellow')
            color = (1 ,0.8 ,0 ,1 )
            yellow.diffuse_color = color
            bpy.context.object.data.materials.append(yellow)
            bpy.context.object.active_material.metallic = 1
            bpy.context.object.active_material.specular_intensity = 1
            bpy.context.object.active_material.roughness = 1




        l1 = random.random()
        '''
        #l2 = random.random()# history version
        #位置随机离太近会穿模,应该使用粒子模型
        '''
        flower.location.x = n1 * (r * 1.8 + 1) #-(l1-0.5)
        flower.location.y = n2 * (r * 1.8 + 1) #-(l2-0.5)
        #随机转角度
        flower.rotation_euler[2] = (w-0.5)*pi
        #随即大小,花的长度与花的大小成正比
        flower.scale = (l1*0.4+0.8 ,l1*0.4+0.8,l1*0.4+0.8)
        
        # 插入关键帧,制作动画
        key_point = 20
        for t in range(key_point):
            bpy.context.scene.frame_set(20*t)
            s = random.random()
            rotation_angle_x = (s - 0.5) * 0.02 * pi
            rotation_angle_y = (s - 0.5) * 0.02 * pi
            flower.rotation_euler.rotate_axis('X', rotation_angle_x)
            flower.rotation_euler.rotate_axis('Y', rotation_angle_y)
            flower.keyframe_insert(data_path="rotation_euler", index=0)  # X轴
            flower.keyframe_insert(data_path="rotation_euler", index=1)  # Y轴
            

bpy.ops.object.light_add(type='SPOT', align='WORLD', location=(20, -8, 25), scale=(1, 1, 1))
bpy.context.object.rotation_euler[0] = 0.785
bpy.context.object.rotation_euler = (0.785, 0.785 ,0)
bpy.ops.object.camera_add(enter_editmode=False, align='VIEW', location=(4, 9, 15), rotation=(0.872, 0, -1.046), scale=(1, 1, 1))
bpy.context.object.data.type = 'ORTHO'
bpy.context.object.data.ortho_scale = 35

化学小实验

import bpy

bpy.ops.object.select_all(action='DESELECT')
bpy.ops.object.select_by_type(type='MESH')
bpy.ops.object.delete(use_global=False)


bpy.ops.mesh.primitive_uv_sphere_add(radius=0.5, location=(0, 0, 0))
oxygen = bpy.context.view_layer.objects.active
oxygen.name = 'Oxygen'

white_mat = bpy.data.materials.new(name='WhiteMat')
white_mat.diffuse_color = (1, 1, 1, 1) 
oxygen.data.materials.append(white_mat)


bpy.ops.mesh.primitive_uv_sphere_add(radius=0.25, location=(1, -1, 0))
hydrogen1 = bpy.context.view_layer.objects.active
hydrogen1.name = 'Hydrogen1'
hydrogen1.parent = oxygen

red_mat = bpy.data.materials.new(name='RedMat')
red_mat.diffuse_color = (1, 0, 0, 1) 
hydrogen1.data.materials.append(red_mat)

bpy.ops.mesh.primitive_uv_sphere_add(radius=0.25, location=(-1, -1, 0))
hydrogen2 = bpy.context.view_layer.objects.active
hydrogen2.name = 'Hydrogen2'
hydrogen2.parent = oxygen

hydrogen2.data.materials.append(red_mat)

bpy.ops.mesh.primitive_uv_sphere_add(radius=0.5, location=(0, 1, 0))
oxygen = bpy.context.view_layer.objects.active
oxygen.name = 'Oxygen'

white_mat = bpy.data.materials.new(name='WhiteMat')
white_mat.diffuse_color = (1, 1, 1, 1)  # 设置为白色
oxygen.data.materials.append(white_mat)

bpy.ops.mesh.primitive_uv_sphere_add(radius=0.25, location=(-1, 1, 0))
hydrogen1 = bpy.context.view_layer.objects.active
hydrogen1.name = 'Hydrogen1'
hydrogen1.parent = oxygen

red_mat = bpy.data.materials.new(name='RedMat')
red_mat.diffuse_color = (1, 0, 0, 1)  # 设置为红色
hydrogen1.data.materials.append(red_mat)

bpy.ops.mesh.primitive_uv_sphere_add(radius=0.25, location=(1, 1, 0))
hydrogen2 = bpy.context.view_layer.objects.active
hydrogen2.name = 'Hydrogen2'
hydrogen2.parent = oxygen

hydrogen2.data.materials.append(red_mat)

camera = bpy.data.cameras.new('MyCamera')
camera_obj = bpy.data.objects.new('CameraObj', camera)
bpy.context.scene.collection.objects.link(camera_obj)
camera.lens = 50  # Focal length in millimeters
camera.sensor_width = 36  # Sensor width in millimeters
camera.sensor_height = 24  # Sensor height in millimeters
camera_obj.location = (13.6, 5, 10.5)  # X, Y, Z coordinates
camera_obj.rotation_euler = (-128*0.0174444444,180*0.0174444444,-60*0.0174444444)  
bpy.ops.object.light_add(type='SPOT', radius=1)
bpy.context.object.data.energy = 10000
bpy.context.object.location = (7.54607,-6.91221,3.67353)
bpy.context.object.rotation_euler = (1.172,0,0.907)
bpy.context.scene.render.resolution_x = 640
bpy.context.scene.render.resolution_y = 480
bpy.context.scene.render.resolution_percentage = 50

hydrogen1.location = (-1,1,0)
hydrogen1.keyframe_insert(data_path="location", frame=1)
hydrogen1.location = (-0.5,-2,0)
hydrogen1.keyframe_insert(data_path="location",frame=50)

hydrogen2.location = (1,1,0)
hydrogen2.keyframe_insert(data_path="location", frame=1)
hydrogen2.location = (0.5,-2,0)
hydrogen2.keyframe_insert(data_path="location",frame=50)

oxygen.location = (0,1,0)
oxygen.keyframe_insert(data_path="location", frame=1)
oxygen.location = (0,1,0)
oxygen.keyframe_insert(data_path="location",frame=50)

苹果落地

from math import pi
# 删除现有的所有对象
bpy.ops.object.select_all(action="SELECT")
bpy.ops.object.delete()

collection = bpy.data.collections["Collection"]
tree = bpy.data.objects.new("tree", None)
collection.objects.link(tree)

bpy.ops.mesh.primitive_cylinder_add(radius=1, depth=8, location=(0, 0, 4))
bpy.context.object.parent = tree
bpy.context.object.name = "shugan"
brown_material = bpy.data.materials.new('BrownMaterial')
color = (0.4, 0.26, 0.13, 1)
brown_material.diffuse_color = color
bpy.context.object.data.materials.append(brown_material)

bpy.ops.mesh.primitive_cube_add(size=6,location=(0, 0, 7))
bpy.context.object.parent = tree
bpy.context.object.name = "shuye"
green_material = bpy.data.materials.new('GreenMaterial')
color = (0, 1, 0, 1)
green_material.diffuse_color = color
bpy.context.object.data.materials.append(green_material)
bpy.context.object.parent = tree

neuton = bpy.data.objects.new("neuton", None)
collection.objects.link(neuton)

bpy.ops.mesh.primitive_uv_sphere_add(radius=0.5, location=(-1.5, 0, 0.5))
bpy.context.object.parent = neuton
bpy.context.object.name = "head"
blue_material = bpy.data.materials.new('BlueMaterial')
color = (0.2, 0.2, 0.7, 1.0)  
blue_material.diffuse_color = color
bpy.context.object.data.materials.append(blue_material)

bpy.ops.mesh.primitive_cube_add(size=1)
bpy.context.object.location = (-2.5, 0, 0.35)
bpy.context.object.parent = neuton
bpy.context.object.name = "body"
bpy.context.object.scale = (1, 1, 0.7)
black_material = bpy.data.materials.new('BlueMaterial')
color = (0.2, 0.2, 0.7, 1.0)
blue_material.diffuse_color = color
bpy.context.object.data.materials.append(blue_material)

bpy.ops.mesh.primitive_cube_add(size=1)
bpy.context.object.location = (-2.5,0.6,0.5)
bpy.context.object.scale = (0.6, 0.3, 0.3)
bpy.context.object.parent = neuton
bpy.context.object.name = "gebo1"
black_material = bpy.data.materials.new('BlackMaterial')
color = (0, 0, 0, 1)
black_material.diffuse_color = color
bpy.context.object.data.materials.append(black_material)

bpy.ops.mesh.primitive_cube_add(size=1)
bpy.context.object.location = (-2.5,-0.6,0.5)
bpy.context.object.scale = (0.6, 0.3, 0.3)
bpy.context.object.parent = neuton
bpy.context.object.name = "gebo2"
black_material = bpy.data.materials.new('BlackMaterial')
color = (0, 0, 0, 1)
black_material.diffuse_color = color
bpy.context.object.data.materials.append(black_material)


bpy.ops.mesh.primitive_cube_add(size=1)
bpy.context.object.location = (-3.3,-0.15, 0.2)
bpy.context.object.scale = (0.6, 0.3, 0.3)
bpy.context.object.parent = neuton
bpy.context.object.name = "leg1"
black_material = bpy.data.materials.new('BlackMaterial')
color = (0, 0, 0, 1)
black_material.diffuse_color = color
bpy.context.object.data.materials.append(black_material)

bpy.ops.mesh.primitive_cube_add(size=1)
bpy.context.object.location = (-3.3,0.15, 0.2)
bpy.context.object.scale = (0.6, 0.3, 0.3)
bpy.context.object.parent = neuton
bpy.context.object.name = "leg2"
black_material = bpy.data.materials.new('BlackMaterial')
color = (0, 0, 0, 1)
black_material.diffuse_color = color
bpy.context.object.data.materials.append(black_material)


bpy.ops.mesh.primitive_uv_sphere_add(radius=0.3, location=(-1.5, 0, 8))
bpy.context.object.name = "apple"
red_material = bpy.data.materials.new('redMaterial')
color = (1, 0, 0, 1.0)  
red_material.diffuse_color = color
bpy.context.object.data.materials.append(red_material)

bpy.ops.object.light_add(type='SPOT', radius=20, location=(-16.02, 9, 10))
light = bpy.context.object
light.data.energy = 8000
light.data.spot_size = pi / 4 
light.data.spot_blend = 0.5  
light.rotation_euler = (-5*pi / 180, -58*pi / 180, -27*pi / 180)

# create camera
camera = bpy.data.cameras.new('MyCamera')
camera4 = bpy.data.objects.new('Camera4', camera)
bpy.context.scene.collection.objects.link(camera4)
camera4.location = (-7.12, 14.48, 7.06)
camera4.rotation_euler = (73 * pi / 180, 0, -517 * pi / 180)
bpy.context.scene.camera = camera4

apple = bpy.data.objects['apple']
apple.location= (-1.5, 0, 8)
apple.keyframe_insert(data_path="location", frame=0)
apple.location= (-1.5, 0, 1.3)
apple.keyframe_insert(data_path="location", frame=20)
apple.location= (-1.5, 0, 1.3)
apple.keyframe_insert(data_path="location", frame=30)
apple.location= (-1.5, 1, 0.5)
apple.keyframe_insert(data_path="location", frame=40)

head = bpy.data.objects['head']
head.location= (-1.5, 0, 0.5)
head.keyframe_insert(data_path="location", frame=40)
head.location= (-1.7, 0, 1)
head.keyframe_insert(data_path="location", frame=50)


逐帧设置关键帧

  • 尝试做正弦曲线运动
import bpy  # 导入 Blender 的 Python API
import math  # 导入数学模块,以便使用正弦函数

# 删除默认场景中的所有对象
bpy.ops.object.select_all(action='SELECT')
bpy.ops.object.delete(use_global=False)

# 添加一个立方体
bpy.ops.mesh.primitive_cube_add(size=2, location=(0, 0, 0))
cube = bpy.context.object  # 获取刚刚添加的立方体对象

# 设置动画的帧数
frame_start = 1
frame_end = 50

# 将帧数设置到时间轴上
bpy.context.scene.frame_start = frame_start
bpy.context.scene.frame_end = frame_end

# 为每一帧添加关键帧
for frame in range(frame_start, frame_end + 1):
    # 设置当前帧
    bpy.context.scene.frame_set(frame)
    
    # 计算立方体的新位置
    new_location = 5 * math.sin(frame * 0.1)
    cube.location[2] = new_location
    
    # 为立方体的位置添加关键帧
    cube.keyframe_insert(data_path="location", index=2)

# 设置摄像机
bpy.ops.object.camera_add(location=(10, -10, 10), rotation=(math.radians(60), 0, math.radians(45)))
camera = bpy.context.object
bpy.context.scene.camera = camera

# 设置灯光
bpy.ops.object.light_add(type='SUN', location=(10, 10, 10))
light = bpy.context.object
light.rotation_euler = (math.radians(50), math.radians(50), 0)

# 设置渲染参数
bpy.context.scene.render.engine = 'CYCLES'  # 使用 Cycles 渲染引擎
bpy.context.scene.cycles.samples = 64  # 设置采样数
bpy.context.scene.render.filepath = '/tmp/animation'  # 设置渲染输出路径
bpy.context.scene.render.image_settings.file_format = 'FFMPEG'  # 设置输出格式为视频
bpy.context.scene.render.ffmpeg.format = 'MPEG4'  # 使用 MPEG4 编码

# 渲染动画
bpy.ops.render.render(animation=True)

  • 尝试制作自由落体运动

尝试制作可爱的动画

import bpy
import mathutils

if __name__=="__main__":
    bpy.ops.object.select_all(action="SELECT")
    bpy.ops.object.delete()
    scene = bpy.context.scene.collection
    # 创建模型
    model = bpy.data.objects.new("model",None)
    scene.objects.link(model)
    # 身体
    bpy.ops.mesh.primitive_ico_sphere_add(subdivisions=6, radius=5.0,location=(0.0, 0.0, 0.0), rotation=(0.0, 0.0, 0.0), scale=(1.0, 1.0, 1.0))
    bpy.context.object.parent = model
    bpy.context.object.name = "body"
    main_material = bpy.data.materials.new("MainMat")
    main_material.diffuse_color = [0.8,0.5,0.6,1]
    bpy.context.object.active_material = main_material

    # 左耳朵
    bpy.ops.mesh.primitive_ico_sphere_add(subdivisions=6, radius=1.0,location=(-2.2, 0.0, 5), rotation=(0.0, -0.43, 0.0), scale=(1.0, 1.0, 1.5))
    bpy.context.object.parent = model
    bpy.context.object.name = "ear_left"
    ear_material = bpy.data.materials.new("EarMat")
    ear_material.diffuse_color = [0.8,0.3,0.47,1]
    bpy.context.object.active_material = ear_material

    # 右耳朵
    bpy.ops.mesh.primitive_ico_sphere_add(subdivisions=6, radius=1.0,location=(2.2, 0.0, 5), rotation=(0.0, 0.43, 0.0), scale=(1.0, 1.0, 1.5))
    bpy.context.object.parent = model
    bpy.context.object.name = "ear_right"
    bpy.context.object.active_material = ear_material

    # 左手
    bpy.ops.mesh.primitive_ico_sphere_add(subdivisions=6, radius=1.0,location=(-2, -4, -2), rotation=(0.0, 0, 0.0), scale=(1.0, 1.0, 1.0))
    bpy.context.object.parent = model
    bpy.context.object.name = "hand_left"
    hand_material = bpy.data.materials.new("HandMat")
    hand_material.diffuse_color = [0.8,0.57,0.3,1]
    bpy.context.object.active_material = hand_material

    # 右手
    bpy.ops.mesh.primitive_ico_sphere_add(subdivisions=6, radius=1.0,location=(2, -4, -2), rotation=(0.0, 0, 0.0), scale=(1.0, 1.0, 1.0))
    bpy.context.object.parent = model
    bpy.context.object.name = "hand_right"
    bpy.context.object.active_material = hand_material

    # 左鼻子
    bpy.ops.mesh.primitive_ico_sphere_add(subdivisions=6, radius=1.0,location=(-0.5, -4.7, 1.2), rotation=(0.0, 0, 0.0), scale=(0.6,0.6,0.6))
    bpy.context.object.parent = model
    bpy.context.object.name = "nose_left"
    nose_material = bpy.data.materials.new("NoseMat")
    nose_material.diffuse_color = [0.8,0.58,0.58,1]
    bpy.context.object.active_material = nose_material

    # 右鼻子
    bpy.ops.mesh.primitive_ico_sphere_add(subdivisions=6, radius=1.0,location=(0.5, -4.7, 1.2), rotation=(0.0, 0, 0.0), scale=(0.6,0.6,0.6))
    bpy.context.object.parent = model
    bpy.context.object.name = "nose_right"
    bpy.context.object.active_material = nose_material

    # 左眼睛
    bpy.ops.mesh.primitive_ico_sphere_add(subdivisions=6, radius=1.0,location=(-1.6, -3.7, 2.8), rotation=(0.0, 0, 0.0), scale=(0.57,0.57,0.57))
    bpy.context.object.parent = model
    bpy.context.object.name = "eye_left"
    eye_material = bpy.data.materials.new("EyeMat")
    eye_material.diffuse_color = [0,0,0,1]
    eye_material.roughness = 0
    bpy.context.object.active_material = eye_material

    # 右眼睛
    bpy.ops.mesh.primitive_ico_sphere_add(subdivisions=6, radius=1.0,location=(1.6, -3.7, 2.8), rotation=(0.0, 0, 0.0), scale=(0.57,0.57,0.57))
    bpy.context.object.parent = model
    bpy.context.object.name = "eye_right"
    bpy.context.object.active_material = eye_material

    # 地面
    bpy.ops.mesh.primitive_plane_add(location=(0,0,-5), size=20)

    # 灯光
    bpy.ops.object.light_add(type='SUN',radius=20,location=(0,20,0), rotation=(-1.57,0,0))

    bpy.ops.object.light_add(type='AREA',radius=20,location=(-13, -8, 10), rotation=(0.0, -0.84, 0.58))
    bpy.context.object.data.energy = 2000

    bpy.ops.object.light_add(type='AREA',radius=20,location=(13, -8, 10), rotation=(0.0, -0.84, 2.8))
    bpy.context.object.data.energy = 2000

    # 相机
    bpy.ops.object.camera_add()
    bpy.context.object.location = (21,-51,19.3)
    bpy.context.object.rotation_euler = (1.25,0,0.38)


    # 动画
    bpy.context.scene.frame_end = 120
    bpy.context.scene.frame_current = 1

    for i in range(11):
        if i % 2 == 0:
            model.location = (0,0,0)
        else:
            model.location = (0,0,6)
        model.keyframe_insert(data_path="location",frame=1+i*12,index=2)

    model.keyframe_insert(data_path="rotation_euler",frame=1,index=2)
    for i in range(1,6):
        if i % 2 == 0:
            model.rotation_euler[2] = 0.785
        else:
            model.rotation_euler[2] = -0.785
        model.keyframe_insert(data_path="rotation_euler",frame=1+i*24,index=2)

图片描述

尝试 把序列渲染为mp4

from moviepy.editor import ImageSequenceClip, AudioFileClip

image_folder = "frames"
fps = 24  # 帧率,可根据需要调整
 
clip = ImageSequenceClip(image_folder, fps=fps)
audio = AudioFileClip("final_audio.wav")
clip = clip.set_audio(audio)
clip.write_videofile("final_video.mp4", codec="libx264", audio_codec="aac") 

总结 🤔

  • 这次 我们
    • 设置了 关键帧
    • 制作了 动画
    • 并且渲染出了 动画序列
  • 我们可以设置变化的灯光吗?🤔

图片描述

  • 我们下次再说!👋

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