如何计算盒子的法线?

4
我正在尝试创建一个算法来计算模型/网格的法线。人们告诉我可以使用两个向量之间的叉积来实现,这起初似乎是个好主意,但后来我发现它可能并不总是有效。例如,想象一个正方体,其前面置于原点,背面朝下沿着Z轴。如下图所示:
https://istack.dev59.com/lInpC.webp 我很抱歉我的手写不太好,但这没有任何意义。如您所见,我将v和u进行叉积运算以获得指向正Z轴的法线。然而,如果我使用相同的计算方法来计算后面的法线,那么显然法线将指向形状内部。结果是我需要计算光的亮度时有不准确的法线。我希望法线始终指向远离模型的方向。
我知道肯定有更好的方法来计算法线,但我不知道它是什么。有人能向我建议另一种算法来解决这个问题吗?如果不行,那么肯定有一种检查法线是否朝向对象/模型内部的方法。如果可以的话,在答案中提供一下并告诉我在哪里可以找到相关解释,因为我很想了解这些方法的原理。

1
叉积始终具有方向性。记住你的右手法则。如果 u x v 给出了一个指向意外方向的向量,那么 v x u 将给出相同大小但方向相反的向量。 - SandPiper
叉积具有方向性,看起来你只是得到了错误方向的正确向量。也许这只是你存储表示面的点的顺序的问题? - templatetypedef
是的,存储我的脸部顺序错误确实会出现问题,但我不知道如何检测它是否在平面后面,然后以不同的顺序存储。我认为这就是一开始的整个问题所在。您有任何建议吗?如果该点在另一个平面后面,那么也许我们只需反转叉积? - Wowzer
我曾认为可能有其他计算法线的方法,这些方法可以知道如果法线朝向模型,则需要反转法线。 - Wowzer
这是一个奇怪的问题,我首先想到的是使用圆形封装对象,并检查哪个法线(面的前后)会首先与其相交。然而,对于复杂的形状,这种方法行不通。对于它们,我将尝试将它们导入到3DMax或Blender中。 - Hakes
似乎你的向量有误,应该是U=V1-V2和V=V3-V2,这样VxU才会指向z方向。请注意顶点的顺序很重要。这个链接可能会对你有所帮助:https://dev59.com/S2Ik5IYBdhLWcg3wWtBz - Jean-Baptiste Yunès
2个回答

2
大多数软件包遵循可配置的三角形索引的循环顺序 - 顺时针或逆时针。因此,它们导出的所有网格都具有自洽的排序方式,只要您的程序使用相同的约定,您就不必担心任何问题。
说到这里,我想你想知道在指数排序不一致的假设情况下该怎么办。
我们可以使用一种方法叫做射线相交。重要的定理是,一条从网格外部发出的射线只会与网格相交偶数次,而从内部发出则是奇数次。
为了实现这个方法,我们可以执行以下步骤:
  • 通过叉积计算三角形的“法向量”(并进行标准化) => N
  • 选取三角形上的任意点(最好是中点)
  • 将此点沿着法线方向增加一些小值epsilon(取决于浮点数格式和模型大小 - 对于单精度浮点数我建议取1e-4,对于双精度浮点数我建议取1e-8) => P
  • 使用Möller–Trumbore算法,将此射线 [dir = N, src = P] 与模型中所有三角形求交
  • 如果交点数为偶数,则该射线从模型外部开始;这意味着法线指向模型外部(因为你将其起点从表面上的一个点增加了)。 - 反之亦然。

一个小的(-ish?)离题:对于上述问题的天真方法,通过循环遍历网格中所有三角形,其时间复杂度为O(n),因此整个过程的时间复杂度是二次的。这对于大约20个三角形(例如一个盒子)的非常小的网格来说完全没有问题,但对于任何更大的网格都不理想!
您可以使用空间子分割技术来降低此交点步骤的成本:
  • K-D树/Octrees:构建需要O(n log n)的时间(对于最佳算法而言,即参见Ingo Wald的论文),但如果正确地进行交点计算,则交点的复杂度保证为O(log n)。总体复杂度将是O(n log n),这几乎是您可以获得的最佳结果。
  • 网格:这只是将搜索空间和三角形分成较小的盒子。构建的时间为O(n),并且使用的内存更加高效。交点计算时间仍然为O(n),但常数因子比朴素方法要小得多。

0

叉积不满足交换律,所以 v x u 不等于 u x v。实际上它们是完全相反的。

对于正面,你需要取 u x v(假定你在一个 右手坐标系 中),而对于背面,你需要做 v x u 的叉积。

有关向量叉积运算的详细信息,请参见 右手定则


嘿,感谢您的回答,但那绝对不是我遇到的问题。我知道叉积不是可交换的,也知道可以通过反转背面的叉积来解决问题。然而,这不是我的关注点。我的关注点在于,如果我只收到构成模型的三角形的位置数据,我必须根据该位置数据决定法线,但它也必须面向远离模型的方向。这意味着我必须知道叉积将使我得到一个面向模型或背向模型的法线。 - Wowzer
通常三角形只会以一种方式绘制。听起来背面的三角形正在以错误的顶点顺序绘制。https://en.wikipedia.org/wiki/Triangle_strip - Jason
哇,这个评论真是改变了游戏规则。像Blender这样的建模软件是否遵循这个约定?如果是的话,也许我就不需要再担心了。我只需要在生成自己的内容时小心遵循这个约定即可。 - Wowzer
通常建模软件会导出索引,我在想这些索引的顺序是否按照上述方式进行。上述内容描述了三角带而不是索引,因此我在想它是否会按正确顺序导出索引,以便在进行点积计算时可以使面部远离模型。 - Wowzer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接