栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

正确处理相机旋转的方法

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

正确处理相机旋转的方法

我建议围绕视图空间中的轴进行旋转

您必须知道视图矩阵(

V
)。由于视图矩阵被编码在
self.eye
self.target
并且
self.up
,它必须由计算
lookAt

V = glm.lookAt(self.eye, self.target, self.up)

计算

pivot
视图空间,旋转角度和旋转轴。在这种情况下,轴是向右旋转的方向,其中y轴必须翻转:

pivot = glm.vec3(V * glm.vec4(target.x, target.y, target.z, 1))axis  = glm.vec3(-delta.y, -delta.x, 0)angle = glm.length(delta)

设置旋转矩阵

R
并计算围绕枢轴的比率矩阵
RP
。最后
V
通过旋转矩阵变换视图矩阵()。结果是新的视图矩阵
NV

R  = glm.rotate( glm.mat4(1), angle, axis )RP = glm.translate(glm.mat4(1), pivot) * R * glm.translate(glm.mat4(1), -pivot)NV = RP * V

解码

self.eye
self.target
然后
self.up
从新的视图矩阵中进行解码
NV

C = glm.inverse(NV)targetDist  = glm.length(self.target - self.eye)self.eye    = glm.vec3(C[3])self.target = self.eye - glm.vec3(C[2]) * targetDist self.up     = glm.vec3(C[1])

该方法的完整编码

rotate_around_target_view

def rotate_around_target_view(self, target, delta):    V = glm.lookAt(self.eye, self.target, self.up)    pivot = glm.vec3(V * glm.vec4(target.x, target.y, target.z, 1))    axis  = glm.vec3(-delta.y, -delta.x, 0)    angle = glm.length(delta)    R  = glm.rotate( glm.mat4(1), angle, axis )    RP = glm.translate(glm.mat4(1), pivot) * R * glm.translate(glm.mat4(1), -pivot)    NV = RP * V    C = glm.inverse(NV)    targetDist  = glm.length(self.target - self.eye)    self.eye    = glm.vec3(C[3])    self.target = self.eye - glm.vec3(C[2]) * targetDist     self.up     = glm.vec3(C[1])

最终,它可以绕世界原点和眼睛位置甚至任何其他点旋转。

def rotate_around_origin(self, delta):    return self.rotate_around_target_view(glm.vec3(0), delta)def rotate_target(self, delta):    return self.rotate_around_target_view(self.eye, delta)

或者,可以在模型的世界空间中执行旋转。解决方案非常相似。旋转是在世界空间中完成的,因此不必将轴转换为视图空间,并且将旋转应用于视图矩阵(

NV = V *RP
)之前:

def rotate_around_target_world(self, target, delta):    V = glm.lookAt(self.eye, self.target, self.up)    pivot = target    axis  = glm.vec3(-delta.y, -delta.x, 0)    angle = glm.length(delta)    R  = glm.rotate( glm.mat4(1), angle, axis )    RP = glm.translate(glm.mat4(1), pivot) * R * glm.translate(glm.mat4(1), -pivot)    NV = V * RP    C = glm.inverse(NV)    targetDist  = glm.length(self.target - self.eye)    self.eye    = glm.vec3(C[3])    self.target = self.eye - glm.vec3(C[2]) * targetDist     self.up     = glm.vec3(C[1])def rotate_around_origin(self, delta):    return self.rotate_around_target_world(glm.vec3(0), delta)


当然,两种解决方案都可以结合使用。通过垂直(上下)拖动,视图可以在其水平轴上旋转。通过水平拖动(左右),模型(世界)可以绕其(上)轴旋转:

def rotate_around_target(self, target, delta):    if abs(delta.x) > 0:        self.rotate_around_target_world(target, glm.vec3(delta.x, 0.0, 0.0))    if abs(delta.y) > 0: self.rotate_around_target_view(target, glm.vec3(0.0, delta.y, 0.0))

考虑到问题的原始代码,为了实现最小程度的侵入性方法,我将提出以下建议:

  • 操作之后,视图的目标应该是

    target
    函数的输入参数
    rotate_around_target

  • 鼠标水平移动应使视图围绕世界的向上矢量旋转

  • 垂直鼠标移动应使视图围绕当前水平轴倾斜

我想出了以下方法:

  1. 计算当前视线(

    los
    ),向上矢量(
    up
    )和水平轴(
    right

  2. 通过将向上矢量投影到由原始向上矢量和当前视线给定的平面上,将向上矢量垂直放置。这是通过Gram–Schmidt正交化得到的。

  3. 绕当前水平轴倾斜。这意味着

    los
    up
    right
    轴旋转。

  4. 围绕上向量旋转。

    los
    right
    旋转
    up

  5. 计算设置向上并计算眼睛和目标位置,其中目标由输入参数target设置:

    def rotate_around_target(self, target, delta):

    # get directionslos    = self.target - self.eyelosLen = glm.length(los)right  = glm.normalize(glm.cross(los, self.up))up     = glm.cross(right, los)# upright up vector (Gram–Schmidt orthogonalization)fix_right = glm.normalize(glm.cross(los, self.original_up))UPdotX    = glm.dot(fix_right, up)up        = glm.normalize(up - UPdotX * fix_right)right     = glm.normalize(glm.cross(los, up))los       = glm.cross(up, right)# tilt around horizontal axisRHor = glm.rotate(glm.mat4(1), delta.y, right)up   = glm.vec3(RHor * glm.vec4(up, 0.0))los  = glm.vec3(RHor * glm.vec4(los, 0.0))# rotate around up vectorRUp   = glm.rotate(glm.mat4(1), delta.x, up)right = glm.vec3(RUp * glm.vec4(right, 0.0))los   = glm.vec3(RUp * glm.vec4(los, 0.0))# set eye, target and upself.eye    = target - los * losLen self.target = targetself.up     = up


转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/385603.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号