Blender 中使用 Python 生成名单动画

532 阅读3分钟

效果图

Rot.gif

操作简析

工程与素材资源目录路径为

image.png

然后我们导入相应的资源,注意还需要开启以下插件

image.png

否则脚本会报 bpy.ops.import_image.to_plane 找不到的 错误

image.png

接着我们复制以下脚本并运行,结果如下

  • Outline 生成的各个对象

image.png

  • Timeline 上相机的关键帧

image.png

小知识点

在 Timeline 上按 Ctrl+Tab 可以切换为 Graph Edit 界面

image.png

然后按 空格键 启动动画,则我们可以看到相机在缓缓下滑的效果

Rot.gif

完整代码与注释

 # 我们需要它与 Blender Python API 一起工作
 import bpy
  
 # 我们需要它来处理目录和文件
 import os
  
 ### 函数 ###
  
 # 更改到一个目录,并获得当前的工作目录。另外,创建一个所有视频和所有图像的列表。为了实现后者,我们使用列表推导式。
 def change_directory(directory):
     # 这里我们使用了 global 语句,这样我们就可以访问函数外部的变量
     global folder, videos, images
     os.chdir(directory) # 改变当前工作目录
     folder = os.getcwd() # 返回当前工作目录
     
     # 视频
     videos = [vid for vid in os.listdir(folder) if vid.endswith('.mp4')]
     
     # 图像
     images = [img for img in os.listdir(folder) if img.endswith('.jpg') or img.endswith('.png')]
  
 # 重置 3D 光标回到世界原点。
 def reset_cursor():
     bpy.context.scene.cursor.location = (0.0, 0.0, 0.0)
         
 # 添加文本
 def add_text(text, scale, centered=False):
     global pos
     
     # 如果文本包含 jpg, png 或 mp4 扩展名,让我们删除它。我们可以通过切片来做。
     if text.endswith('.jpg') or text.endswith('.png') or text.endswith('.mp4'):
         text = text[:-4]
     
     bpy.ops.object.text_add()
     ob = bpy.context.object
     ob.data.body = text
     
     # 记录文本的位置,这样你就知道最后一项在哪里。我们需要知道在动画中相机应该向下移动多少。
     pos = ob.location
     
     # 对文本进行变换 
     bpy.ops.transform.rotate(value=1.5708, constraint_axis=(True, False, False))
     bpy.ops.transform.resize(value=(scale, scale, scale))
     if centered:
         bpy.context.object.data.align_x = 'CENTER'
     bpy.context.object.data.extrude = 0.05
  
     # 文本材质
     mat = bpy.data.materials.get("Material")
     if mat is None:
         # 创建材质
         mat = bpy.data.materials.new(name="Material")
         bpy.data.materials["Material"].node_tree.nodes["Principled BSDF"].inputs[17].default_value = (0.0469195, 1, 0.971278, 1)     
  
     # 分配材质        
     if ob.data.materials:
         # 分配到第一个材质槽
         ob.data.materials[0] = mat
     else:
         # 无材质槽的话
         ob.data.materials.append(mat)
         
 # 显示条目 (视频或者图像).
 def show_items(item_list):
     for item in item_list:
         bpy.ops.import_image.to_plane(files=[{"name":item}], directory=folder)
         bpy.ops.transform.rotate(value=1.5708, constraint_axis=(True, False, False))
         
         # 添加光源
         bpy.ops.object.light_add(type='POINT', align='WORLD', scale=(1, 1, 1))
         bpy.context.object.data.shadow_soft_size = 1
         bpy.context.object.data.energy = 100
         
         # 添加文本
         bpy.context.scene.cursor.location.x += 2
         add_text(item, .25)        
         
         # 移动游标
         bpy.context.scene.cursor.location.x -= 2
         bpy.context.scene.cursor.location.z -= 2
  
 ### 主入口代码 ###
  
 # 切换到图像和视频所在的目录。
 change_directory(r'D:\Projects\BlenderProjects\PY\blend files\Animated Credits in Blender with Python\images and videos')
  
 # 设置世界颜色为黑色。
 bpy.data.worlds["World"].node_tree.nodes["Background"].inputs[0].default_value = (0, 0, 0, 1)
  
 # 重置 3D 游标
 reset_cursor()
  
 # 如果有任何视频,添加 'Videos' 文本。
 if videos:
     add_text('Videos', .5, centered=True)
  
     # 游标下移
     bpy.context.scene.cursor.location.z -= 2
  
     # 显示所有视频
     show_items(videos)
  
 # 如果有任何图像,添加 'Images' 文本。
 if images:
     add_text('Images', .5, centered=True)
  
     # 游标下移
     bpy.context.scene.cursor.location.z -= 2
  
     # 显示所有图像.
     show_items(images)
  
 # 重置游标
 reset_cursor()
  
 # 添加并设置相机
 bpy.ops.object.camera_add(location=(4, -10, 0), rotation=(1.5708, -0, -0))
 bpy.context.object.data.lens = 30
  
 # 设置时间轴的结束帧为 480 (动画持续时间 - 20s)。
 bpy.context.scene.frame_end = 480
  
 # 转到第 1 帧
 bpy.context.scene.frame_current = 1
  
 # 关键帧相机(插入一个 ·位置· 关键帧)。
 bpy.ops.anim.keyframe_insert_menu(type='Location')
  
 # 转到第 480 帧.
 bpy.context.scene.frame_current = 480
  
 # 移动相机到最后一张图片的下方。这里我们使用了 pos 变量,它保存了最后一个文本元素的位置。
 bpy.ops.transform.translate(value=(-0, -0, pos.z - 4), constraint_axis=(False, False, True))
  
 # 再给相机(位置)设定关键帧。
 bpy.ops.anim.keyframe_insert_menu(type='Location')
  
 # 回转到第 1 帧
 bpy.context.scene.frame_current = 1 

bpy.ops.anim.keyframe_insert_menu 为指定的键控集 (Keying Set) 插入关键帧,如果未指定则提供可用的键控集菜单