【问题标题】:Transforming a 3D plane using a 4x4 matrix使用 4x4 矩阵变换 3D 平面
【发布时间】:2011-12-02 21:13:52
【问题描述】:

我有一个由几个三角形组成的形状,它位于世界空间中的某个位置,具有缩放、旋转、平移功能。我还有一个平面,我想在上面投影(正交)形状。

我可以将形状中每个三角形的每个顶点与对象变换矩阵相乘,以找出它在世界坐标中的位置,然后将该点投影到平面上。

但是我不需要绘制投影,而是想用形状的逆变换矩阵变换平面,然后将所有顶点投影到(逆变换)平面上。因为它只需要我变换一次平面而不是每个顶点。

我的飞机有一个法线 (xyz) 和一个距离 (d)。我如何将它与 4x4 变换矩阵相乘,这样它就可以了?

你能创建一个 vec4 作为 xyzd 并将其相乘吗?或者也许创建一个向量 xyz1 然后用 d 做什么?

【问题讨论】:

    标签: transform 3d plane


    【解决方案1】:

    符号

    • n 是表示为 (1x3) 行向量的法线
    • n' 是 n 根据变换矩阵 T 变换后的法线
    • (n|d) 是表示为 (1x4) 行向量的平面(n 平面的法线和 d 平面到原点的距离)
    • (n'|d')(n|d)根据变换矩阵T的变换平面
    • T 是一个 (4x4)(仿射)列主变换矩阵(即,变换列向量 t 定义为 t' = T t)。

    转换一个正常的 n

    n' = n adj(T)
    

    变换平面(n|d)

    (n'|d') = (n|d) adj(T)
    

    这里,adj是矩阵的对数,根据矩阵的逆和行列式定义如下:

    T^-1 = adj(T)/det(T)
    

    注意

    • adjugate 通常不等于变换矩阵 T 的逆矩阵。如果 T 包含反射,则 det(T) = -1,反转缠绕顺序!

    • 重新归一化 n' 在数学上不是必需的(但可能在数值上取决于实现),因为缩放是由行列式处理的。 感谢 Adrian Leonhard。

    • 您可以直接变换平面,而无需先分解和重组平面(法线和点)。

    【讨论】:

    • @Leonhard 我将法线和平面表示为行向量,而我将点和方向表示为列向量,因为我使用列优先变换矩阵(参见“符号”的第 5 个点)。如果您想在任何地方使用列向量,只需对n' = n adj(T) 的两侧进行转置,这将导致伴随的转置或转置的伴随。如果您使用逆而不是伴随,您将需要在之后重新规范化以防缩放分量。或者您可以除以衡量大小变化的行列式。
    • @AdrianLeonhard 有关更详细的解释/推导,请参阅Foundations of Game Engine Development: Volume 1: Mathematics。但是请注意,在这种情况下,伴随词是一些数学糖,用于获得精确和通用的单行表达式。在实践中(游戏/渲染引擎),将乘以逆转置(甚至消除非均匀缩放,乘以只是变换矩阵本身的转置转置+由于均匀缩放而导致的重新归一化)。
    • @AdrianLeonhard 此外,在使用变换/场景图时,既不会计算行列式,也不会计算倒数。
    • 感谢您的澄清,但给出了 2* 比例转换 T = [2 0 0 0 | 0 2 0 0 | 0 0 2 0 | 0 0 0 1], adj(T) = T^-1 * det(T) = [4 0 0 0 | 0 4 0 0 | 0 0 4 0 | 0 0 0 8]。对于 X = 0 平面:(1 0 0 0) * adj(T) = (4 0 0 0),还需要归一化吗?
    • @AdrianLeonhard 感谢您的示例。你是对的规范化不是由行列式处理的。 (事实上​​,逆向和对等向量都不知道法向向量有额外的非线性(sqrt)限制。)所以我重读了FGED 1 的一部分。有两种不同的推导:1)如果您的法线向量被计算为梯度,那么您最终会得到逆向量。由于普通向量(维数:米)经过T从A变换到B,而法向向量(维数:逆米)经过T从B变换到A。
    【解决方案2】:

    这个问题有点老了,但我想更正接受的答案。
    您不需要转换平面表示。

    任何点 位于平面上 如果
    可以写成点积:

    您正在寻找由您的 4x4 矩阵 转换的平面 。
    同理,你必须有

    所以 和一些安排


    TLDR : 如果p=(a,b,c,d), p' = transpose(inverse(M))*p

    【讨论】:

    • 谢谢,但恐怕我没有正确判断您的答案的知识。我的数学技能仍然很垃圾,自从这个问题发布后不久,我就没有参与任何相关的事情。我认为我唯一能做的就是接受你的回答,看看人们是否会因为这样做而对我大喊大叫......但这不也是马蒂亚斯早些时候试图用他的回答来解释的吗?
    • 在执行此操作后对平面方程进行归一化可能是个好主意,尤其是当矩阵包含非单位基向量(缩放)时。
    【解决方案3】:

    您需要将您的飞机转换为不同的表示形式。其中 N 是法线,O 是平面上的任意点。您已经知道的正常情况是您的(xyz)。平面上的一个点也很简单,它是您的正常 N 倍距离 d

    O以正常方式通过4x4矩阵变换,这将成为你的新O。您将需要一个 Vector4 与 4x4 矩阵相乘,将 W 分量设置为 1 (x, y, z, 1)。

    同样通过 4x4 矩阵变换 N,但将 W 分量设置为 0 (x, y, z, 0)。将 W 组件设置为 0 意味着您的法线不会被翻译。如果您的矩阵不仅仅是平移和旋转,那么这一步就不是那么简单了。而不是乘以你的变换矩阵,你必须乘以矩阵的转置,即Matrix4.Transpose(Matrix4.Invert(Transform)),有一个很好的解释为什么here

    您现在有了一个新的法线向量 N 和一个新的位置向量 O。但是我想你想要它再次以 xyzd 形式出现?没问题。和以前一样,xyz 是您的正常N,剩下的就是计算 d。 d 是平面到原点的距离,沿法线向量。因此,它只是 ON 的点积。

    你有它!如果你告诉我你用什么语言做这个,我也很乐意用代码输入。

    编辑,伪代码:

    平面是vector3 xyznumber d,矩阵是matrix4x4 M

    vector4 O = (xyz * d, 1)
    vector4 N = (xyz, 0)
    O = M * O
    N = transpose(invert(M)) * N
    xyz = N.xyz
    d = dot(O.xyz, N.xyz)
    

    xyzd 代表新飞机

    【讨论】:

    • 嗨,Hannesh,非常感谢您的清晰解释!我同时使用不同的库在 Lua 和 C++ 中执行此操作,但代码不会成为问题。这是我遇到麻烦的概念,我认为您已经说得很清楚了。干杯
    • 谢谢,我已经为此苦苦挣扎了几个晚上。
    • 有人能以更容易理解的方式重写这个答案吗?最好使用一些 GLM 代码?
    • 如果您涉及缩放,请不要忘记之后对您的飞机进行标准化
    • 在计算机图形学中的大多数情况下,如果使用列向量,则可以使用反转置,如果使用行向量,则可以使用逆转置,但这通常在数学上是不正确的(请参阅下面的答案)。
    猜你喜欢
    • 2014-11-13
    • 1970-01-01
    • 2012-05-24
    • 1970-01-01
    • 2017-11-28
    • 1970-01-01
    • 2021-03-24
    • 1970-01-01
    • 2011-02-07
    相关资源
    最近更新 更多