math - 给定表面法线,找到 3D 平面的旋转

标签 math 3d

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

P : a point which lies on the Plane
N : the surface normal for the Plane



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

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

1) Take any none parallel vector (V) to the normal (N), and take the cross product (W1)
2) Take the cross product of (W1) and (N) now (W2) and that is a Vector (V') which lies on the Plane



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

关于如何产生正确的旋转的任何想法?

最佳答案

关于旋转的一些有用的事情:

  • 任何三个排列成行的正交向量都定义了到新基的变换(到该基的旋转)。
  • 任何旋转的转置都是它的逆。
  • 因此,排列为列的任何三个正交向量定义了从某个基础到您的“世界”引用框架的旋转。

  • 所以,问题是找到任何三个正交向量的集合并将它们排列为
    | x1 x2 x3  0 |
    | y1 y2 y3  0 |
    | z1 z2 z3  0 |
    |  0  0  0  1 |
    

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

    我们显然可以将您的法线用作 (x1,y1,z1),但问题是系统对剩余的两个向量有无限多的解决方案(尽管知道其中一个会给您另一个,作为叉积)。下面的代码应该给出一个垂直于 (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];
    

    这基本上使用了格拉姆-施密特正交化,其维度已经与法线向量最正交。然后可以通过取 normal 的叉积来获得 v3和 v2 .

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

    恐怕我还没有测试过上面的内容,我只是从我不久前写的一些代码中找到了它,并根据你的问题进行了调整!希望我没有忘记任何细节。

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

    上面的矩阵假设你的多边形法线是沿着 x 轴的,我有一个偷偷摸摸的怀疑它不会,你需要做的就是把“法线”向量放在旋转矩阵的正确列中,并且其他两列中的 v2/v3。因此,如果多边形的法线沿 z 轴,则法线位于第三列,v2/v3 位于前两列。

    抱歉,如果这引起任何困惑。

    关于math - 给定表面法线,找到 3D 平面的旋转,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2096474/

    相关文章:

    javascript - 数字运算

    opengl - 如何将 3D 图像输出到 3D 电视?

    python - 从 C 访问 Numpy 矩阵作为 3D 数组

    c++ - 用于将文件中的字符串读入 3D 数组的 For 循环

    javascript - 如何找到圆弧切片的中点?

    c# - 如何将8个方向映射到一维数组

    java - 倒置计数(大输入问题)

    python - 如何在 Python 中评估自定义数学表达式

    c - 如何显示这些小三角形或快速识别它们?

    opengl - 在类似 Minecraft 的游戏中渲染每一面具有不同纹理的立方体的有效方法是什么?