具有局部y方向的向量与另一个向量的叉积

问题描述 投票:0回答:2

所以我有一个由glm::mat4 m_yellow_mat表示的立方体

enter image description here

[我围绕30 degree进行了z-axis旋转

m_yellow_mat = glm::rotate(m_yellow_mat, glm::radians(30), glm::vec3(0, 0, 1));

现在参考下图

enter image description here

我想找到蓝色矢量和红色矢量之间的叉积

我知道蓝色矢量,但不确定如何找到红色矢量?红色矢量代表立方体局部y轴的方向吗?

cross( ?????? , blue_vector);
c++ vector glm-math cross-product
2个回答
3
投票

世界空间中的局部y轴存储在矩阵的第二行中:

vec3 yaxis_world = normalize(m_yellow_mat[1][0], m_yellow_mat[1][1], m_yellow_mat[1][2]);

说明:

根据定义,对象空间中的y轴(我们称为yaxis)为[0,1,0]。为了将向量从对象空间转换为世界空间,我们将向量与模型矩阵相乘。由于我们对某个方向感兴趣,因此齐次坐标必须为0:

axisy_world = modelMatrix * yaxis

axisy_world = modelMatrix * [0,1,0,0]

[当看矩阵乘法时,我们注意到它会恰好返回矩阵的第二行。

注意,必须对结果进行归一化,以从矩阵中消除比例因子。如果保证只包含平移/旋转,则可以跳过归一化。


0
投票

来自BDL的答案已经明确指出,您可以从第二列转换矩阵中获得这样的up vector来表示对象在场景中的局部坐标。


我想走得更远,因为从另一个角度来看为什么我们可以从变换矩阵本身中提取这样的向量,这可能对其他读者有好处。

首先,我们可以从变换矩阵(矩阵运算的结果矩阵,即平移,旋转,缩放)中提取以下方向矢量

  • 其第一列表示对象的左向量
  • 其第二列表示对象的上矢量
  • 其第三列代表对象的前向向量

这在某种程度上与view matrix的构造有关。这将有助于回答为什么这些信息位于其中。

对于立即使用,如果我们有4x4矩阵,我们可以忽略最后一列是位置分量,如果您知道这样的矩阵已缩放,或者只是想确保然后再进行标准化,然后再使用从矩阵中提取的列向量。

构造视图矩阵

通过构造视图矩阵,我们知道它只是我们通常对世界上某个对象所做的反向。因为在OpenGL中没有像照相机这样的东西,也可能没有任何渲染API,所以这只是一个虚拟的东西。

为了获得摄影机的效果,并能够模拟玩家的运动或观察特定方向,我们做的恰恰相反(此处使用世界空间中OpenGL使用的右手规则,默认情况下使用GLM)

  1. 使摄像机移动dx,dy,dz => 0,0,10:我们要做的是通过0,0,-10转换场景中的所有对象。
  2. 对于旋转,这有点棘手,但它只是旋转矩阵的逆。

通过将上面的两个数相乘,我们将得到

view_matrix = inverse(M_rotation) * M_translation

您可以read more对此进行撰写,因为它由Song Ho写得很好。

从他的文章中摘录,我们会得到

enter image description here

其中有

Notice Leftupforward矢量。总而言之,视图矩阵就像操纵或模拟世界来满足相机交互一样,从某种意义上说,它仍在与世界空间交互。

现在呢?

我们看到了视图矩阵的构造,也应用了类似的概念。我们可以将其与场景中具有3个差异的对象一起使用

  1. 前向矢量现在从对象本身指向目标(与视图矩阵构造相反),因为现在将旋转的是该对象而不是其他对象。
  2. 我们不需要位置矩阵(本身是位置信息),我们只关心方向(因此不需要调整位置分量,因为我们在位置分量之前不需要负数)
  3. 我们不需要将逆矩阵应用于旋转矩阵,因为我们不是在相机上操作,而是在对象本身上操作

    1. 和3.结合起来,我们可以得出一个3x3旋转矩阵,或在最后一列中带有0,0,0,1的4x4矩阵。

简而言之,m_yellow_mat,您可以使用表示对象局部轴的leftupforward矢量打包。您可以直接将其提取出来,如下所示

  • glm::vec3 left = glm::vec3(m_yellow_mat[0]);
  • glm::vec3 up = glm::vec3(m_yellow_mat[1]);
  • glm::vec3 forward = glm::vec3(m_yellow_mat[2]);

(额外):一个向量可以代表物体的方向

了解视图矩阵]的构造方式的进一步好处。单个方向矢量可以表示对象的方向,而无需我们保持每个轴3个矩阵旋转,但是它会丢失一个单独的信息(该信息大部分围绕z轴滚动)仅当此时的up vector;但对于像gizmo,平面或本身这样的简单对象而言,大多数情况下它并不重要,只要您知道它的初始起始方向必须朝向+ z轴(在y-方向),就可以将其定向为正确的方向轴。

这样做的代码是我从Song Ho的实现中学到的,它是构造视图矩阵的简单形式,并做了一些修改以适合我的示例。

glm::mat4 computeLookAtForObject(const glm::vec3& pos, const glm::vec3& target)
{
    glm::vec3 forward = glm::normalize(target - pos);
    glm::vec3 up = glm::vec3(0.0f, 1.0f, 0.0f);

    // handle if forward is nearly the same as up vector
    // then we choose another direction for forward
    if (std::abs(forward.x) < kEpsilon && std::abs(forward.z) < kEpsilon)
    {
        if (forward.y > 0.0f)
        {
            up.x = 0.0f;
            up.y = 0.0f;
            up.z = -1.0f;
        }
        else
        {
            up.x = 0.0f;
            up.y = 0.0f;
            up.z = 1.0f;
        }
    }

    glm::vec3 left = glm::normalize(glm::cross(up, forward));
    up = glm::cross(forward, left);

    glm::mat4 m = glm::mat4(1.0f);
    m[0] = glm::vec4(left, 0.0f);
    m[1] = glm::vec4(up, 0.0f);
    m[2] = glm::vec4(forward, 0.0f);
    //m[3] = glm::vec4(pos, 1.0f);  // <--- (optional) we can completely ignore this, or build up full-feature matrix from this function as well by uncommenting this line
    return m;
}

在我的示例中也使用了这种功能。

示例

我创建了两个示例对此进行验证。

  1. 使用矩阵运算获得结果矩阵,然后提取其3个方向向量以将其绘制在屏幕上。这使用平面作为几何。检查haxpor/lgl - 1
  2. enter image description here

  1. 使用单个lookAt向量在不维护多个矩阵的情况下定向平面。利用上面的computeLookAtForObject()。检查haxpor/lgl - 2
  2. enter image description here

两个示例,都可以直接在此类目录中单击make。在Ubuntu 18.04和Linux上进行了测试。

学分
  • 感谢Song Ho为这些主题提供了丰富的文章。

最新问题
© www.soinside.com 2019 - 2024. All rights reserved.