我如何确定我是否只是在正确的方向上计算了法线?
How do I determine if i just calculated the normal in the correct direction?
为了解释上下文,我在 C# 中按程序生成了统一的建筑物。我创建了一个网格并填充了顶点和三角形,然后我计算了不同点的法线。我生成了数百个建筑物,但有些面的方向不正确,法线指向内部而不是外部。
法线很好
法线不好
为了计算法线,我创建了一个具有构成三角形的不同顶点的平面,然后检索该平面的法线。我还测试了给出相同结果的叉积。
Plane plane = new Plane(v1, v2, v3);
normals.Add(plane.normal);
如何生成三角形?
例如:我在建筑物底部的点上创建了一个 for 循环。
vectors.Add(v1);
vectors.Add(v2);
vectors.Add(v3); //v3 = v1+height
vectors.Add(v4); //v4 = v2+height
// index values
int idx1, idx2, idx3, idx4;
idx4 = vectors.Count - 1;
idx3 = vectors.Count - 2;
idx2 = vectors.Count - 3;
idx1 = vectors.Count - 4;
// Triangle 1
indices.Add(idx1);
indices.Add(idx3);
indices.Add(idx2);
...
mesh.triangles = indices.ToArray();
所以我的问题是:如何确定法线方向是否正确(内部或外部)?如果我能确定这一点,我就可以翻转法线,通常它会起作用。
我不完全理解你的问题,但是对于简单的形状一个简单的算法是..
- 只取对象的“中心”(CG 很好)并从那里制作一个矢量到您的顶点或三角形。那个方向是“外面”。如果你指向的角度超过 90°,那么你指向的是物体的内部
下一个更复杂的方法...
沿着你的正常说“一米”移动。将该点称为“测试点”。你应该现在“外面”你的大楼,对吗?
现在您只需要检查 testPoint 是在您的 3D 形状内部还是外部。
简而言之,要确定您是在 3D 对象内部还是外部,您只需投射光线并计算与墙壁相交的次数。 奇数在里面,偶数在外面
您可以 google 在 www 上对此进行数百次讨论,例如
请注意,这有很多变体,也有很多问题。在某些情况下,您从正常的“内部”开始(即向后退一点);有时最好从对象的中间开始(如果这样的事情是可知的);有时会有关于光线投射系统在边缘情况下如何工作的问题(比如“就在”表面上,这就是你的顶点)
the first solution seems to me to be the right one
它可能是。有时是没用的。这取决于你的形状的性质。
I wanted to avoid having to do raycast ..
可以向您保证 - 在任何构建过程中您都必须不断进行光线投射!如果你想“避免”铸造,把这个想法放在一边。你会一直铸造直到你厌倦它:)
I wanted to avoid having to do raycast to limit the generation time
好消息是这是完全错误的。与 3D 场景中发生的一切相比,投射是极其微不足道的,也是一个非常小的负担。当您播放任何 3D 场景时,每帧都会进行 100 次和 1000 次投射。
but if I have two buildings that are close to each other, the ray will find the wall but from the second building so I couldn't determine the normal is "inside" or "outside", right?
我描述的简单系统中的TBC。你肯定只会针对你正在建设的同一栋建筑进行投射!这就是要走的路。
但确实与您所问的内容无关。假设您在“城市”中。你确实可以穿过“所有墙壁”,奇偶校验(即:奇数或偶数)会让你知道你是在室内还是室外。虽然这有问题,与边缘、角落等有关。但在某些情况下它与该问题有关。
如本回答所述 最终您可以研究凸包等。话题很大!
请注意,当您构建动态 buildings/shapes 时,您通常会得到每个“墙”的数据结构,并且确实 它知道 哪一面在里面,哪一面在外面.当您首先这样做时,就可以很容易地以正确的方式绘制三角形。话题很大!
为了解释上下文,我在 C# 中按程序生成了统一的建筑物。我创建了一个网格并填充了顶点和三角形,然后我计算了不同点的法线。我生成了数百个建筑物,但有些面的方向不正确,法线指向内部而不是外部。
法线很好
法线不好
为了计算法线,我创建了一个具有构成三角形的不同顶点的平面,然后检索该平面的法线。我还测试了给出相同结果的叉积。
Plane plane = new Plane(v1, v2, v3);
normals.Add(plane.normal);
如何生成三角形?
例如:我在建筑物底部的点上创建了一个 for 循环。
vectors.Add(v1);
vectors.Add(v2);
vectors.Add(v3); //v3 = v1+height
vectors.Add(v4); //v4 = v2+height
// index values
int idx1, idx2, idx3, idx4;
idx4 = vectors.Count - 1;
idx3 = vectors.Count - 2;
idx2 = vectors.Count - 3;
idx1 = vectors.Count - 4;
// Triangle 1
indices.Add(idx1);
indices.Add(idx3);
indices.Add(idx2);
...
mesh.triangles = indices.ToArray();
所以我的问题是:如何确定法线方向是否正确(内部或外部)?如果我能确定这一点,我就可以翻转法线,通常它会起作用。
我不完全理解你的问题,但是对于简单的形状一个简单的算法是..
- 只取对象的“中心”(CG 很好)并从那里制作一个矢量到您的顶点或三角形。那个方向是“外面”。如果你指向的角度超过 90°,那么你指向的是物体的内部
下一个更复杂的方法...
沿着你的正常说“一米”移动。将该点称为“测试点”。你应该现在“外面”你的大楼,对吗?
现在您只需要检查 testPoint 是在您的 3D 形状内部还是外部。
简而言之,要确定您是在 3D 对象内部还是外部,您只需投射光线并计算与墙壁相交的次数。 奇数在里面,偶数在外面
您可以 google 在 www 上对此进行数百次讨论,例如
请注意,这有很多变体,也有很多问题。在某些情况下,您从正常的“内部”开始(即向后退一点);有时最好从对象的中间开始(如果这样的事情是可知的);有时会有关于光线投射系统在边缘情况下如何工作的问题(比如“就在”表面上,这就是你的顶点)
the first solution seems to me to be the right one
它可能是。有时是没用的。这取决于你的形状的性质。
I wanted to avoid having to do raycast ..
可以向您保证 - 在任何构建过程中您都必须不断进行光线投射!如果你想“避免”铸造,把这个想法放在一边。你会一直铸造直到你厌倦它:)
I wanted to avoid having to do raycast to limit the generation time
好消息是这是完全错误的。与 3D 场景中发生的一切相比,投射是极其微不足道的,也是一个非常小的负担。当您播放任何 3D 场景时,每帧都会进行 100 次和 1000 次投射。
but if I have two buildings that are close to each other, the ray will find the wall but from the second building so I couldn't determine the normal is "inside" or "outside", right?
我描述的简单系统中的TBC。你肯定只会针对你正在建设的同一栋建筑进行投射!这就是要走的路。
但确实与您所问的内容无关。假设您在“城市”中。你确实可以穿过“所有墙壁”,奇偶校验(即:奇数或偶数)会让你知道你是在室内还是室外。虽然这有问题,与边缘、角落等有关。但在某些情况下它与该问题有关。
如本回答所述 最终您可以研究凸包等。话题很大!
请注意,当您构建动态 buildings/shapes 时,您通常会得到每个“墙”的数据结构,并且确实 它知道 哪一面在里面,哪一面在外面.当您首先这样做时,就可以很容易地以正确的方式绘制三角形。话题很大!