本文介绍了给定表面法线,找到 3D 平面的旋转的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我有一个由 2 个向量描述的 3D 平面:

So I have a 3D Plane described by 2 Vectors:

P : 平面上的一个点
N : 平面的表面法线

我有一个非常大的扁平方形多边形,我想渲染它来代表这个平面.我可以轻松地将多边形转换为给定的点,但随后我需要找到适当的旋转来使表面法线实际上成为表面法线.

And i have a very large, flat square Polygon, which I want to render to represent this Plane. I can easily translate the polygon to the given point, but then I need to find the proper rotation to apply to make the surface normal actually be the surface normal.

我尝试了其他地方提到的方法:

I tried a method mentioned else where which was:

1) 取法线 (N) 的任意非平行向量 (V),并取叉积 (W1)
2)现在取(W1)和(N)的叉积(W2),这是一个位于平面上的向量(V')

然后,我根据平面上的 (V') 生成旋转矩阵,以便我的多边形与 (V') 对齐.那行得通,但很明显,这种方法整体上无法正常工作.多边形并不完全垂直于表面法线.

I then generate a rotation matrix based on (V') laying on the Plane, so that my polygon would be aligned with (V'). that worked, but it's clear that this method is not working correctly as a whole. The Polygon is not perfectly perpendicular to the surface normal.

有关如何生成正确旋转的任何想法?

Any ideas on how to generate the proper rotation?

推荐答案

关于旋转的一些有用的东西:

Some useful things about rotations:

  • 按行排列的任何三个正交向量定义了到新基的变换(旋转到该基).
  • 任何旋转的转置都是它的逆.
  • 因此,排列成列的任何三个正交向量定义了从某个基础到您的世界"参考系的旋转.

所以,问题是找到任意一组三个正交向量并将它们排列为

So, the problem is to find any set of three orthonormal vectors and arrange them as

| x1 x2 x3  0 |
| y1 y2 y3  0 |
| z1 z2 z3  0 |
|  0  0  0  1 |

这正是你描述的方法试图做的,如果它不起作用,那么你的实现就有问题.

this is exactly what the method you described tries to do, if it doesn't work then there is a problem with your implementation.

我们显然可以使用你的法线作为 (x1,y1,z1),但问题是系统对剩下的两个向量有无限多个解(尽管知道其中一个可以给你另一个,作为叉积).下面的代码应该给出一个垂直于 (x1,y1,z1) 的稳定向量:

We can obviously use your normal as (x1,y1,z1), but the problem is the system has infinitely many solutions for the remaining two vectors (although knowing one of them gives you the other, as the cross product). The following code ought to give a stable vector perpendicular to (x1,y1,z1):

float normal[3] = { ... };

int imin = 0;
for(int i=0; i<3; ++i)
    if(std::abs(normal[i]) < std::abs(normal[imin]))
        imin = i;

float v2[3] = {0,0,0};
float dt    = normal[imin];

v2[imin] = 1;
for(int i=0;i<3;i++)
    v2[i] -= dt*normal[i];

这基本上使用 Gram-Schmidt 正交化,其维度已经与法向量最正交.然后可以通过取normalv2 的叉积来获得v3.

This basically uses Gram-Schmidt orthogonalisation with the dimension that is already most orthogonal to the normal vector. v3 can then be obtained by taking the cross product of normal and v2.

您可能需要小心设置旋转,它是关于原点的,因此您需要在旋转后应用平移,它用于列向量而不是行向量.如果您使用 OpenGL,请注意 OpenGL 以列主要顺序(而不是 C 的行主要顺序)获取数组,因此您可能需要转置.

You may need to take some care setting up the rotation, it's about the origin so you need to apply the translation after the rotation and it's for column vectors rather than row vectors. If you're using OpenGL watch that OpenGL takes arrays in column major order (rather than C's row major order) so you may need to transpose.

恐怕我还没有测试过上面的内容,我只是从我不久前编写的一些代码中获取了它并对其进行了调整以适应您的问题!希望我没有忘记任何细节.

I'm afraid I haven't tested the above, I've merely nabbed it from some code I wrote a while ago and adapted it to your problem! Hopefully I haven't forgotten any details.

我确实忘记了一些东西:)

I did forget something :)

上面的矩阵假设多边形的法线沿着 x 轴,我偷偷怀疑它不会,您需要做的就是将法线"向量放在旋转的正确列中矩阵,以及其他两列中的 v2/v3.因此,如果多边形的法线沿 z 轴,则法线位于第 3 列,而 v2/v3 位于前两列.

The matrix above assumes your normal to the polygon is along the x-axis, and I have a sneaking suspicion it won't be, all you need to do is put the "normal" vector in the correct column of the rotation matrix, and v2/v3 in the other two columns. So if the normal to your polygon is along the z axis, then the normal goes in the 3rd column and v2/v3 go in the first two columns.

抱歉,如果这引起了任何混淆.

Sorry if that causes any confusion.

这篇关于给定表面法线,找到 3D 平面的旋转的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-23 12:46