如何沿坐标轴旋转90度后获取相机位姿并保持朝向?
绕坐标轴旋转90度并保持相机朝向的简便方法
核心思路
绕目标点(camera.center)旋转相机位置(camera.eye),同时同步旋转并正交化相机上向量(camera.up)——这种方式天然保证旋转后相机始终看向目标,同时避免手动计算角度偏移的繁琐操作。
具体实现步骤
1. 计算相机相对于目标的偏移向量
先算出相机位置到目标点的相对偏移:
offset = camera.eye - camera.center
2. 构建对应轴的90度旋转矩阵
根据要旋转的轴(x/y/z),生成3x3旋转矩阵(以右手坐标系逆时针旋转90度为例):
- 绕X轴旋转90度:
[1, 0, 0] [0, 0, -1] [0, 1, 0] - 绕Y轴旋转90度:
[0, 0, 1] [0, 1, 0] [-1, 0, 0] - 绕Z轴旋转90度:
[0, -1, 0] [1, 0, 0] [0, 0, 1]
若需顺时针旋转,只需将矩阵中sin值对应的元素取反即可。
3. 计算旋转后的相机位置
用旋转矩阵乘以偏移向量,得到新的偏移量,再加上目标点坐标就是新的相机位置:
new_offset = 旋转矩阵 × offset new_eye = camera.center + new_offset
4. 调整并正交化Up向量
旋转后的Up向量可能与新视线方向不垂直,需做正交化修正:
- 计算新视线方向:
new_view_dir = normalize(camera.center - new_eye) - 计算右向量:
right = normalize(cross(new_view_dir, 旋转后的临时Up)) - 重新生成正交化的Up向量:
new_up = normalize(cross(right, new_view_dir))
完整伪代码示例
import math def rotate_camera_90(eye, center, up, axis): # 计算相机相对目标的偏移 offset = [eye[i] - center[i] for i in range(3)] theta = math.radians(90) cos_t = math.cos(theta) sin_t = math.sin(theta) # 初始化对应轴的旋转矩阵 rot = [[0]*3 for _ in range(3)] if axis == "x": rot = [[1, 0, 0], [0, cos_t, -sin_t], [0, sin_t, cos_t]] elif axis == "y": rot = [[cos_t, 0, sin_t], [0, 1, 0], [-sin_t, 0, cos_t]] elif axis == "z": rot = [[cos_t, -sin_t, 0], [sin_t, cos_t, 0], [0, 0, 1]] # 计算旋转后的偏移与新相机位置 new_offset = [ rot[0][0]*offset[0] + rot[0][1]*offset[1] + rot[0][2]*offset[2], rot[1][0]*offset[0] + rot[1][1]*offset[1] + rot[1][2]*offset[2], rot[2][0]*offset[0] + rot[2][1]*offset[1] + rot[2][2]*offset[2] ] new_eye = [center[i] + new_offset[i] for i in range(3)] # 旋转Up向量得到临时值 temp_up = [ rot[0][0]*up[0] + rot[0][1]*up[1] + rot[0][2]*up[2], rot[1][0]*up[0] + rot[1][1]*up[1] + rot[1][2]*up[2], rot[2][0]*up[0] + rot[2][1]*up[1] + rot[2][2]*up[2] ] # 正交化Up向量,确保与视线方向垂直 view_dir = [center[i] - new_eye[i] for i in range(3)] view_dir_len = math.sqrt(sum(v**2 for v in view_dir)) view_dir = [v/view_dir_len for v in view_dir] # 计算右向量 right = [ view_dir[1]*temp_up[2] - view_dir[2]*temp_up[1], view_dir[2]*temp_up[0] - view_dir[0]*temp_up[2], view_dir[0]*temp_up[1] - view_dir[1]*temp_up[0] ] right_len = math.sqrt(sum(v**2 for v in right)) right = [v/right_len for v in right] # 生成最终正交化的Up向量 new_up = [ right[1]*view_dir[2] - right[2]*view_dir[1], right[2]*view_dir[0] - right[0]*view_dir[2], right[0]*view_dir[1] - right[1]*view_dir[0] ] new_up_len = math.sqrt(sum(v**2 for v in new_up)) new_up = [v/new_up_len for v in new_up] return new_eye, center, new_up
关键注意事项
- 坐标系适配:如果场景用左手坐标系,调整旋转矩阵中sin值的符号即可修正旋转方向。
- 旋转方向调整:若旋转后相机位置不符合预期,将旋转矩阵中的
sin_t替换为-sin_t即可切换顺时针/逆时针方向。
内容的提问来源于stack exchange,提问作者David Botsko
相关产品推荐
相关产品推荐

