假设现在我有一个物体,初始朝向为下(沿z轴负方向),位置为(0,0,0),位姿为单位矩阵,该物体在自旋,自旋轴为z轴。经过位姿T变换后,改变了位置和朝向,我想让该物体以朝向为轴进行自旋,并按一定自旋间隔记录位姿。使用blender软件,python脚本,获取相机对象当前的位姿T,并设置关键帧让相机自旋
以下是一个Blender Python脚本示例,用于让相机绕当前朝向轴自旋并记录关键帧:
import bpy
from math import radians
from mathutils import Quaternion
# 配置参数
total_rotation = 360 # 总旋转角度(度)
num_frames = 30 # 总帧数
start_frame = 1 # 起始帧
fps = 24 # 帧率
# 获取当前相机对象
cam = bpy.context.object['Camera.001']
if not cam or cam.type != 'CAMERA':
raise Exception("请先选择相机对象")
# 设置旋转模式为四元数
cam.rotation_mode = 'QUATERNION'
# 存储初始变换
initial_quat = cam.rotation_quaternion.copy()
initial_loc = cam.location.copy()
# 计算每帧旋转量
angle_per_frame = radians(total_rotation) / (num_frames - 1)
# 创建动画关键帧
for frame in range(num_frames):
# 计算当前帧号
current_frame = start_frame + frame
# 计算旋转四元数(绕局部Z轴旋转)
delta_quat = Quaternion((0, 0, 1), angle_per_frame * frame)
# 应用组合旋转(保持初始朝向)
cam.rotation_quaternion = initial_quat @ delta_quat
# 保持初始位置
cam.location = initial_loc
# 插入关键帧
cam.keyframe_insert(data_path="rotation_quaternion", frame=current_frame)
cam.keyframe_insert(data_path="location", frame=current_frame)
# 设置时间轴范围
bpy.context.scene.frame_start = start_frame
bpy.context.scene.frame_end = start_frame + num_frames - 1
bpy.context.scene.render.fps = fps
print(f"已创建{num_frames}帧动画,从帧{start_frame}到{start_frame + num_frames - 1}")
使用说明:
在Blender中选择要动画的相机对象
将脚本复制到Blender的文本编辑器
按需调整参数(总旋转角度、帧数等)
运行脚本
关键点说明:
使用四元数旋转来避免万向节锁问题
保持初始位置不变,只改变旋转
通过矩阵组合保持初始朝向
同时记录位置和旋转关键帧以保证稳定性
使用局部坐标系确保绕自身轴旋转
注意:
确保相机没有父级对象,否则需要额外处理坐标系转换
可以通过调整total_rotation参数设置顺时针/逆时针旋转(正负值)
最终动画速度由帧率和总帧数共同决定
如果相机有动画曲线,建议先清除现有动画数据
我想要保存位姿到特定的文件夹中,每一帧保存一个txt文件,保存格式如上,应该如何编写脚本?
以下是一个 Python 脚本示例,用于将每一帧相机的位姿矩阵保存到特定文件夹中,每个帧对应一个单独的 txt
文件,保存格式与你提供的示例一致。
import bpy
import os
# 指定保存位姿矩阵的文件夹路径
output_folder = "path/to/your/output/folder"
# 确保输出文件夹存在,如果不存在则创建
if not os.path.exists(output_folder):
os.makedirs(output_folder)
# 获取相机对象
camera = bpy.data.objects['Camera']
# 获取场景的起始帧和结束帧
start_frame = bpy.context.scene.frame_start
end_frame = bpy.context.scene.frame_end
# 遍历每一帧
for frame in range(start_frame, end_frame + 1):
# 设置当前帧
bpy.context.scene.frame_set(frame)
# 获取相机的位姿矩阵
matrix_world = camera.matrix_world
# 构建输出文件的路径
output_file_path = os.path.join(output_folder, f"frame_{frame}.txt")
# 打开文件以写入模式
with open(output_file_path, 'w') as f:
f.write("extrinsic:\n")
for row in matrix_world:
# 将矩阵行的元素转换为字符串,并用逗号分隔
row_str = ", ".join(map(str, row))
f.write(row_str + "\n")
print(f"位姿矩阵已保存到 {output_folder} 文件夹中。")
可以根据生成的txt位姿文件,在blender中生成位姿路径吗?
以下是实现该功能的详细步骤和示例代码:
import bpy
import os
# 读取单个 txt 文件中的位姿矩阵
def read_pose_from_txt(file_path):
with open(file_path, 'r') as f:
lines = f.readlines()
# 跳过第一行 "extrinsic:"
lines = lines[1:]
matrix = []
for line in lines:
row = [float(x) for x in line.strip().split(',')[:-1]]
matrix.append(row)
return matrix
# 根据位姿矩阵设置相机位姿并设置关键帧
def set_camera_pose(camera, matrix, frame):
from mathutils import Matrix
# 将列表形式的矩阵转换为 Blender 的 Matrix 对象
pose_matrix = Matrix(matrix)
camera.matrix_world = pose_matrix
# 设置位置和旋转的关键帧
camera.keyframe_insert(data_path="location", frame=frame)
camera.keyframe_insert(data_path="rotation_euler", frame=frame)
# 主函数,根据 txt 文件生成相机轨迹
def generate_camera_path_from_txt(folder_path):
# 获取相机对象
camera = bpy.data.objects['Camera']
# 获取文件夹中的所有 txt 文件,并按帧号排序
txt_files = sorted([f for f in os.listdir(folder_path) if f.endswith('.txt')])
for i, txt_file in enumerate(txt_files):
file_path = os.path.join(folder_path, txt_file)
matrix = read_pose_from_txt(file_path)
# 帧号从 1 开始
frame = i + 1
set_camera_pose(camera, matrix, frame)
# 设置场景的起始和结束帧
bpy.context.scene.frame_start = 1
bpy.context.scene.frame_end = len(txt_files)
# 指定保存位姿矩阵的文件夹路径
txt_folder = "path/to/your/txt/folder"
generate_camera_path_from_txt(txt_folder)