c# - 在 Unity C# 中修复拉伸网格法线?
问题描述
在 Unity C# 中,我使用基于平面多边形的 2D 矢量点的程序网格挤压。使用下面的代码效果很好,除了一个细节:似乎每隔一个三角形连接挤出网格的正面和背面,如图所示(使用双面着色器,我可以看到所有三角形存在很好,虽然)。我将如何修复这些桥接法线的翻转?谢谢!
// Extrusion functionality via
// https://forum.unity.com/threads/trying-extrude-a-2d-polygon-to-create-a-mesh.102629/
// with Triangulator based on
// http://wiki.unity3d.com/index.php?title=Triangulator
public static Mesh GetExtrudedMeshFromPoints(Vector2[] points, float depth)
{
const float frontVertex = 0f;
Triangulator triangulator = new Triangulator(points);
int[] tris = triangulator.Triangulate();
Mesh m = new Mesh();
Vector3[] vertices = new Vector3[points.Length*2];
for (int i = 0; i < points.Length; i++)
{
vertices[i].x = points[i].x;
vertices[i].y = points[i].y;
vertices[i].z = frontVertex;
vertices[i+points.Length].x = points[i].x;
vertices[i+points.Length].y = points[i].y;
vertices[i+points.Length].z = depth;
}
int[] triangles = new int[tris.Length*2+points.Length*6];
int count_tris = 0;
// Front vertices
for (int i = 0; i < tris.Length; i += 3)
{
triangles[i] = tris[i];
triangles[i+1] = tris[i+1];
triangles[i+2] = tris[i+2];
}
count_tris += tris.Length;
// Back vertices
for (int i = 0; i < tris.Length; i += 3)
{
triangles[count_tris+i] = tris[i+2] + points.Length;
triangles[count_tris+i+1] = tris[i+1] + points.Length;
triangles[count_tris+i+2] = tris[i] + points.Length;
}
count_tris += tris.Length;
// Triangles around the perimeter of the object
for (int i = 0; i < points.Length; i++)
{
int n = (i+1) % points.Length;
triangles[count_tris] = i;
triangles[count_tris+1] = i + points.Length;
triangles[count_tris+2] = n;
triangles[count_tris+3] = n;
triangles[count_tris+4] = n + points.Length;
triangles[count_tris+5] = i + points.Length;
count_tris += 6;
}
m.vertices = vertices;
m.triangles = triangles;
m.RecalculateNormals();
m.RecalculateBounds();
m.Optimize();
return m;
}
解决方案
如果一个面没有显示出来,它就像你已经注意到翻转的那样,这是由于绕组顺序统一是顺时针的。您的 triangluator 的链接已经在疑难解答下声明:“如果您看不到使用此实用程序创建的多边形,请记住检查多边形是否面向相反的方向。如果是,您可以通过使用倒序的顶点索引。”
编辑:
进一步澄清:在您的代码中,这意味着您必须切换
// Triangles around the perimeter of the object
for (int i = 0; i < points.Length; i++)
{
int n = (i + 1) % points.Length;
triangles[count_tris] = i;
triangles[count_tris + 1] = i + points.Length;
triangles[count_tris + 2] = n;
triangles[count_tris + 3] = n;
triangles[count_tris + 4] = n + points.Length;
triangles[count_tris + 5] = i + points.Length;
count_tris += 6;
}
至
// Triangles around the perimeter of the object
for (int i = 0; i < points.Length; i++)
{
int n = (i + 1) % points.Length;
triangles[count_tris] = n;
triangles[count_tris + 1] = i + points.Length;
triangles[count_tris + 2] = i;
triangles[count_tris + 3] = n;
triangles[count_tris + 4] = n + points.Length;
triangles[count_tris + 5] = i + points.Length;
count_tris += 6;
}
但要小心,因为顺序取决于你的深度(如果它高于或低于你的frontVertex)
第二次编辑:
三角形的法线取决于缠绕顺序,这意味着顺序有所不同。
一个例子:
1: Vector2(1f, 1f);
2: Vector2(1f, 0f);
3: Vector2(0f, 0f);
的三角形
Triangle 1,2,3
和
Triangle 1,3,2
有不同的常态。
您必须确保绘制的每个三角形的缠绕顺序都是一致的。或者,您可以告诉您的着色器禁用剔除(使用Cull Off
),正如您在上面已经说过的。但这会带来计算时间的成本。在大多数情况下,这无关紧要,但这始终取决于您的目的。除了大多数时候你不希望禁用剔除的副作用。
推荐阅读
- python - 如何收集具有未知第一(批量)维度的张量?
- dart - Flutter基于间隔设置floatingactionbutton文本
- ssh - Dask-ssh 与本地调度程序?
- python-3.x - 是否可以提供两个位置参数的选择,其中必须选择两个位置参数之一?
- javascript - 如何创建一个返回 html 的 javascript 函数
- angular - 显示多列数据的 ag-grid 单元格渲染器
- sql-server - 如何从 RDP 会话到 Azure SQL Server 查找主机或公共 IP?
- python - 如何对嵌套的 pandas DataFrames 中的分组数组进行操作?
- excel - 循环遍历每个工作表以获取单元格值以传输到另一个工作表,其中列出了所有获得的值?
- angular - 使用 Angular 在 Firestore 中获取文档中的特定字段