我正在尝试创建一个计算模型/网格法线的算法。人们一直在告诉我使用两个向量之间的交叉产品,这些看起来好像是个好主意,直到我发现它可能并不总是有效。例如,想象一个盒子,其正面位于原点,背面朝向Z轴。这是一张图片:
我为写不好的手写道歉,但这不应该有任何意义。如你所见,我越过v和u使法线指向正z轴。但是,如果我使用相同的计算来计算背面的法线,那么显然法线将是指向形状内部的矢量。结果是我有不准确的法线来计算灯光的亮度。我希望法线在任何时候都远离模型。
我知道有更好的方法来计算正常情况,但我不知道它是什么。任何人都可以向我建议另一种计算正常的算法来解决这个问题吗?如果没有,则必须有一种方法来检查法线是否面向对象/模型内部。如果是这样,那么你可以在答案中建议它,我会在哪里找到解释,因为我希望对这些方法的工作方式有直觉。
答案 0 :(得分:1)
大多数软件包遵循三角形索引的可配置循环排序 - 顺时针或逆时针。因此,它们导出的所有网格都具有自洽的排序,只要您的程序使用相同的约定,您就不必担心。
话虽如此,我想你想知道在索引排序不一致的假设(?)情况下该怎么做。
我们可以使用的一种方法是 ray-intersection 。重要的定理是一条光源,它的光源在网格之外只会与网格相交偶数次,如果在内部,则是奇数。
为此,我们可以执行以下操作:
public async Task<ActionResult> DoSomeAsyncStuff()
{
var model = new MyModel();
await Task.Delay(20000);//My long-running process is getting data from an API with "HttpWebRequest".
model.Name = "Something";
//Assigning other model properties
return PartialView("_InnerView", model);
}
N
表示单1e-4
}} for double precision)=&gt; 1e-8
P
与网格中的所有三角形相交(一个好的算法是Möller–Trumbore) 次要(-ish?)题外话题:对于上面的一种天真的方法,循环遍历网格中的所有三角形,将是[dir = N, src = P]
- 因此整个过程会有< em>二次时间复杂度。这对于非常约20个三角形的小网格(例如一个盒子)来说非常好,但对于任何更大的三角形都不是理想的!
您可以使用空间细分技术来降低此交叉步骤的成本:
O(n)
(对于最佳算法,即 - Ingo Wald's paper)来构建,但交叉点保证为{{1如果做得好的话。总体复杂性将是O(n log n)
,这几乎是你能得到的最好的O(log n)
并且内存效率更高。交点时间仍为O(n log n)
,但常数因子 小于天真方法的答案 1 :(得分:0)
交叉产品不可交换,因此v x u
与u x v
不同。事实上,他们恰恰相反。
对于正面,您需要u x v
(假设您在r ight-hand coordinate system中),以及您想要越过v x u
的背面。
有关交叉向量如何工作的详细信息,请参阅right-hand rule。