【问题标题】:How do you determine the view-up vector?您如何确定向上查看的矢量?
【发布时间】:2022-02-19 04:32:47
【问题描述】:

这是 Peter Shirley 的 计算机图形学基础 的节选。在第 114 页(在第 3 版中,内容如下:

我们希望能够在 3D 中更改视点并查看任何 方向。有许多用于指定查看器的约定 位置和方向。我们将使用以下一个:

  • 眼睛位置e
  • 注视方向g
  • 向上视图向量 t

眼睛位置是眼睛“看到”的位置。如果你认为 图形作为一个摄影过程,它是镜头的中心。 注视方向是观察者所在方向上的任意向量 看着。 上视向量是平面上的任意向量 将观众的头部分成左右两半,并指向“ 天空”代表一个站在地上的人。这些向量为我们提供了 有足够的信息来建立一个原点e的坐标系 和uvw基础.....

粗体字是最让我困惑的一句话。不幸的是,这本书只提供了非常基本和粗略的图表,并没有提供任何示例。

这句话是不是表示所有的view-up vector都只是(0, 1, 0)

我在一些示例上进行了尝试,但它与给定的解决方案不太匹配(尽管有时很接近)。

【问题讨论】:

    标签: graphics linear-algebra


    【解决方案1】:

    简短的回答:向上视图向量不是从其他组件派生的:相反,它是用户输入,选择以确保相机正面朝上。或者,换一种说法,向上查看向量是如何告诉您的相机系统“向上”的方向是什么,以便确定相机的方向。


    您需要向上视图向量的原因是相机的位置和注视方向不足以完全确定其姿势:您仍然可以围绕位置/注视轴旋转相机。需要上视向量才能完成锁定相机;而且由于人们通常更喜欢正面朝上看事物,因此向上查看的矢量通常是一个固定方向,由场景在您的坐标空间中的方向决定。

    理论上,向上查看向量可以是任何方向,但实际上“向上”通常是坐标方向。哪个坐标“向上”是一个约定问题:在您的情况下,Y 轴似乎是“向上”的,但有些系统更喜欢 Z 轴。

    也就是说,我要重申:您可以选择几乎任何您想要的方向。如果您希望您的第一人称 POV “倾斜”(例如,环顾四周,或表示醉酒),您可以调整您的向上视图向量来完成此操作。另外,考虑一下《超级马里奥银河》等游戏中的摄像头控制...

    【讨论】:

      【解决方案2】:

      我去年参加了图形课,但我已经很生疏了。我引用了一些旧笔记,所以这里。

      我认为粗体线只是试图解释视图向量 (VUP) 在一种情况下的含义是为了介绍,而不是在所有情况下都必须如此。措辞有点奇怪。这里有一个改写:“考虑一个人站在地上。VUP 在这种情况下将是平分观众头部并指向天空的向量。”

      要确定标准向上向量,请执行以下操作:

      1. 规范化g
      2. g_norm x (0,1,0) 为您提供 view-right,或您的相机视图右侧的矢量
      3. view-right x g 给你VUP

      然后,如果您愿意,您可以应用轮换。

      【讨论】:

      • 据我了解,上视向量不知何故自然地遵循我们设置的两个主要向量:相机的位置和它正在看的东西(注视)。目标是使用egv 生成相机坐标系的基础。
      • v?是VUP 吗?还是错字?你原来的帖子说VUPt
      • 对不起,你是对的 - 它应该是 t。原因是因为v被用作相机空间的基础之一u, v, w
      • 知道了。我写了别的东西,然后意识到这是完全错误的。事情是这样的:使用两个方向向量,您可以生成第三个向量。 e 在这里对我们没有帮助,因为位置与观察轴无关。剩下的只有g,不足以判断t。您可以确定t 是否要将其锁定到平面,方法是使用已知轴,例如world-down(或您想称呼它的任何名称. But to have actual camera freedom, you need to determine VUP`,至少自己一次。
      • 接下来。唯一的“自然”部分来自转换矩阵的力量。一旦你确定了你的初始视图,你可以简单地对你的观察矩阵应用变换(旋转、平移),以编程方式移动它。尽管如果您想将相机“跳转”到特定位置或视图,则必须再次指定VUP/t
      【解决方案3】:

      这句话是不是表示所有的view-up向量都是简单的(0, 1, 0)?

      不,(0,1,0) 是世界向上向量。我们正在寻找相机的向上向量。

      其他人已经写了深入的解释。我将提供下面的代码,这主要是自我记录。示例是 DirectX C++。

      DirectX::XMVECTOR Camera::getDirection() const noexcept
      {
          // camDirection = camPosition - camTarget
          const dx::XMVECTOR forwardVector{0.0f, 0.0f, 1.0f, 0.0f};
          const auto lookVector = dx::XMVector3Transform( forwardVector,
              dx::XMMatrixRotationRollPitchYaw( m_pitch, m_yaw, 0.0f ) );
          const auto camPosition = dx::XMLoadFloat3( &m_position );
          const auto camTarget = dx::XMVectorAdd( camPosition,
              lookVector );
          return dx::XMVector3Normalize( dx::XMVectorSubtract( camPosition,
              camTarget ) );
      }
      
      DirectX::XMVECTOR Camera::getRight() const noexcept
      {
          const dx::XMVECTOR upVector{0.0f, 1.0f, 0.0f, 0.0f};
          return dx::XMVector3Cross( upVector,
              getDirection() );
      }
      
      DirectX::XMVECTOR Camera::getUp() const noexcept
      {
          return dx::XMVector3Cross( getDirection(),
              getRight() );
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-05-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-07-23
        相关资源
        最近更新 更多