Unity中如何将一些3D点都在同一平面上降维为2D?
How to reduce the dimensionality of some 3D points, which are all on the same plane, to 2D in Unity?
我有一个包含四个 3D 点 (Vector3[]
) 的数组,它们都在同一平面上。我将 Unity
与 C#
一起使用,目的是将 2D Traingulator
用于这 4 个点。
using UnityEngine;
Vector3[] vertices3D = new Vector3[] {
new Vector3(0,10,0),
new Vector3(50,20,0),
new Vector3(0,10,30),
new Vector3(50,20,30)
};
由于Triangulator只适用于二维,所有的点都在同一个平面上,所以方法应该是计算基向量或平面的主成分,但我找不到如何.我想将点的维数减少到 2D,以便以生成的三角形位于平面上的方式为它们使用 Triangulator
。
所以我想要的输出只有三角形。
Triangulator
的源代码在here, and my goal is to create a mesh for the given points, but as you see the following sample code,三角测量仪的输入点应该是二维的:
using UnityEngine;
public class PolygonTester : MonoBehaviour {
void Start () {
// Create Vector2 vertices
Vector2[] vertices2D = new Vector2[] {
new Vector2(0,0),
new Vector2(0,50),
new Vector2(50,50),
new Vector2(50,100)
};
// Use the triangulator to get indices for creating triangles
Triangulator tr = new Triangulator(vertices2D);
int[] indices = tr.Triangulate();
// Create the Vector3 vertices
Vector3[] vertices = new Vector3[vertices2D.Length];
for (int i=0; i<vertices.Length; i++) {
vertices[i] = new Vector3(vertices2D[i].x, vertices2D[i].y, 0);
}
// Create the mesh
Mesh msh = new Mesh();
msh.vertices = vertices;
msh.triangles = indices;
msh.RecalculateNormals();
msh.RecalculateBounds();
// Set up game object with mesh;
gameObject.AddComponent(typeof(MeshRenderer));
MeshFilter filter = gameObject.AddComponent(typeof(MeshFilter)) as MeshFilter;
filter.mesh = msh;
}
}
解决方案 1 - 平凡
如果四边形是凸的并且您知道顶点的顺序,请使用indices = new double[6]{0,1,2,0,2,3};
解决方案 2 - 手动三角测量
如果四边形是凸的,但您不确定顺序,请测试方向并调整索引。
edge1 = vertices3D[1] - vertices3D[0];
edge2 = vertices3D[2] - vertices3D[0];
edge3 = vertices3D[3] - vertices3D[0];
normal12 = Vector3.Cross(edge1, edge2);
normal23 = Vector3.Cross(edge2, edge3);
if (Vector3.Dot(normal12, normal23) > 0)
indices = new double[6]{0,1,2,0,2,3};
else
indices = new double[6]{0,1,3,0,3,2};
解决方案 3 - 使用三角测量器
如果四边形不是凸的,或者您确实必须使用库 Triangulator,请变换所有顶点,使它们位于 XY 平面上,第一个顶点位于 (0,0,0)
。
edge1 = vertices3D[1] - vertices3D[0];
edge2 = vertices3D[2] - vertices3D[0];
normal = Vector3.Cross(edge1, edge2).normalized;
rotation = Quaternion.FromToRotation(normal, new Vector3(0,0,1));
Vector2[] vertices2D = new Vector2[vertices3D.Length];
for (int i=0; i<vertices3D.Length; i++) {
rotatedVertex = rotation * (vertices3D[i]-vertices3D[0]);
vertices2D[i] = new Vector2(rotatedVertex.x, rotatedVertex.y);
}
我不建议只用 4 个点形成一堵墙使用 Triangulator。但是,它对于复杂的多边形和非凸形状应该会很方便。
我有一个包含四个 3D 点 (Vector3[]
) 的数组,它们都在同一平面上。我将 Unity
与 C#
一起使用,目的是将 2D Traingulator
用于这 4 个点。
using UnityEngine;
Vector3[] vertices3D = new Vector3[] {
new Vector3(0,10,0),
new Vector3(50,20,0),
new Vector3(0,10,30),
new Vector3(50,20,30)
};
由于Triangulator只适用于二维,所有的点都在同一个平面上,所以方法应该是计算基向量或平面的主成分,但我找不到如何.我想将点的维数减少到 2D,以便以生成的三角形位于平面上的方式为它们使用 Triangulator
。
所以我想要的输出只有三角形。
Triangulator
的源代码在here, and my goal is to create a mesh for the given points, but as you see the following sample code,三角测量仪的输入点应该是二维的:
using UnityEngine;
public class PolygonTester : MonoBehaviour {
void Start () {
// Create Vector2 vertices
Vector2[] vertices2D = new Vector2[] {
new Vector2(0,0),
new Vector2(0,50),
new Vector2(50,50),
new Vector2(50,100)
};
// Use the triangulator to get indices for creating triangles
Triangulator tr = new Triangulator(vertices2D);
int[] indices = tr.Triangulate();
// Create the Vector3 vertices
Vector3[] vertices = new Vector3[vertices2D.Length];
for (int i=0; i<vertices.Length; i++) {
vertices[i] = new Vector3(vertices2D[i].x, vertices2D[i].y, 0);
}
// Create the mesh
Mesh msh = new Mesh();
msh.vertices = vertices;
msh.triangles = indices;
msh.RecalculateNormals();
msh.RecalculateBounds();
// Set up game object with mesh;
gameObject.AddComponent(typeof(MeshRenderer));
MeshFilter filter = gameObject.AddComponent(typeof(MeshFilter)) as MeshFilter;
filter.mesh = msh;
}
}
解决方案 1 - 平凡
如果四边形是凸的并且您知道顶点的顺序,请使用indices = new double[6]{0,1,2,0,2,3};
解决方案 2 - 手动三角测量
如果四边形是凸的,但您不确定顺序,请测试方向并调整索引。
edge1 = vertices3D[1] - vertices3D[0];
edge2 = vertices3D[2] - vertices3D[0];
edge3 = vertices3D[3] - vertices3D[0];
normal12 = Vector3.Cross(edge1, edge2);
normal23 = Vector3.Cross(edge2, edge3);
if (Vector3.Dot(normal12, normal23) > 0)
indices = new double[6]{0,1,2,0,2,3};
else
indices = new double[6]{0,1,3,0,3,2};
解决方案 3 - 使用三角测量器
如果四边形不是凸的,或者您确实必须使用库 Triangulator,请变换所有顶点,使它们位于 XY 平面上,第一个顶点位于 (0,0,0)
。
edge1 = vertices3D[1] - vertices3D[0];
edge2 = vertices3D[2] - vertices3D[0];
normal = Vector3.Cross(edge1, edge2).normalized;
rotation = Quaternion.FromToRotation(normal, new Vector3(0,0,1));
Vector2[] vertices2D = new Vector2[vertices3D.Length];
for (int i=0; i<vertices3D.Length; i++) {
rotatedVertex = rotation * (vertices3D[i]-vertices3D[0]);
vertices2D[i] = new Vector2(rotatedVertex.x, rotatedVertex.y);
}
我不建议只用 4 个点形成一堵墙使用 Triangulator。但是,它对于复杂的多边形和非凸形状应该会很方便。