public Triangle(Vector3 vertexPosition0, Vector3 vertexPosition1, Vector3 vertexPosition2, Vector2 uv0, Vector2 uv1, Vector2 uv2) { this.m_vertexPos0 = vertexPosition0; this.m_vertexPos1 = vertexPosition1; this.m_vertexPos2 = vertexPosition2; this.m_uv0 = uv0; this.m_uv1 = uv1; this.m_uv2 = uv2; this.m_windingOrder = GeometryUtility.GetTriangleWindingOrder(vertexPosition0, vertexPosition1, vertexPosition2); }
/// <summary> /// 通过triangleList创建Unity的Mesh /// </summary> /// <param name="triangleList"></param> /// <param name="windingOrder"></param> /// <returns></returns> public static Mesh CreateUnityMeshByTriangleList(List <Triangle> triangleList, TriangleWindingOrder windingOrder = TriangleWindingOrder.CounterClockWise) { Mesh unityMesh = new Mesh(); Vector3[] vertices = new Vector3[triangleList.Count * 3]; Vector2[] uvs = new Vector2[triangleList.Count * 3]; int[] triangles = new int[triangleList.Count * 3]; int triangleIndices = 0; for (int i = 0; i < triangleList.Count; ++i) { int index0 = triangleIndices; int index1 = triangleIndices + 1; int index2 = triangleIndices + 2; Triangle triangle = triangleList[i]; triangle.WindingOrder = windingOrder; vertices[index0] = triangle.VertexPosition0; vertices[index1] = triangle.VertexPosition1; vertices[index2] = triangle.VertexPosition2; uvs[index0] = triangle.UV0; uvs[index1] = triangle.UV1; uvs[index2] = triangle.UV2; triangles[index0] = index0; triangles[index1] = index1; triangles[index2] = index2; triangleIndices += 3; } unityMesh.vertices = vertices; unityMesh.uv = uvs; unityMesh.triangles = triangles; unityMesh.RecalculateNormals(); unityMesh.RecalculateTangents(); return(unityMesh); }
/// <summary> /// Andrew monotone chain算法,计算凸边形 /// </summary> /// <param name="inVertices">输入的无序3维点</param> /// <param name="uAxis">降维x方向</param> /// <param name="vAxis">降维y方向</param> /// <param name="convexHullVertices">输出凸边形顶点</param> /// <param name="triangles">triangle indices</param> /// <param name="uvs">输出uv</param> /// <returns></returns> public static bool CreateConvexHullByMonotoneChain(List <Vector3> inVertices, Vector3 uAxis, Vector3 vAxis, out Vector3[] convexHullVertices, out Vector2[] uvs, out int[] triangles, TriangleWindingOrder triangleWindingOrder = TriangleWindingOrder.CounterClockWise) { convexHullVertices = new Vector3[0]; uvs = new Vector2[0]; triangles = new int[0]; if (inVertices.Count < 3) { return(false); } float uMax = float.MinValue; float uMin = float.MaxValue; float vMax = float.MinValue; float vMin = float.MaxValue; //3D降维到2D Dictionary <Vector2, Mapped2DVector> vector2DAndMappedDict = new Dictionary <Vector2, Mapped2DVector>(); for (int i = 0; i < inVertices.Count; ++i) { Mapped2DVector mappedVector = new Mapped2DVector(inVertices[i], uAxis, vAxis); if (!vector2DAndMappedDict.ContainsKey(mappedVector.MappedVector2)) { vector2DAndMappedDict.Add(mappedVector.MappedVector2, mappedVector); uMax = Mathf.Max(uMax, mappedVector.MappedVector2.x); uMin = Mathf.Min(uMin, mappedVector.MappedVector2.x); vMax = Mathf.Max(vMax, mappedVector.MappedVector2.y); vMin = Mathf.Min(vMin, mappedVector.MappedVector2.y); } } List <Vector2> inVertexPoints = vector2DAndMappedDict.Keys.ToList(); List <Vector2> convexHullByMonotoneChain = MonotoneChain(inVertexPoints.ToArray()).ToList(); convexHullVertices = new Vector3[convexHullByMonotoneChain.Count]; uvs = new Vector2[convexHullByMonotoneChain.Count]; //计算uv for (int i = 0; i < convexHullByMonotoneChain.Count; ++i) { Vector2 point2D = convexHullByMonotoneChain[i]; convexHullVertices[i] = vector2DAndMappedDict[point2D].OriginalVector; Vector2 pointUV = new Vector2(); pointUV.x = MathUtils.Remap(point2D.x, uMax, uMin, 1, 0); pointUV.y = MathUtils.Remap(point2D.y, vMax, vMin, 1, 0); uvs[i] = pointUV; } //根据WindingOrder计算triangle int index = 1; triangles = new int[(convexHullByMonotoneChain.Count - 2) * 3]; for (int i = 0; i < triangles.Length; i += 3) { triangles[i] = 0; if (triangleWindingOrder == TriangleWindingOrder.CounterClockWise) { triangles[i + 1] = index; triangles[i + 2] = index + 1; } else { triangles[i + 1] = index + 1; triangles[i + 2] = index; } index++; } return(true); }
/// <summary> /// 构建凸包模型 /// </summary> /// <param name="points"></param> /// <param name="normal">维度方向</param> /// <returns></returns> /// <remarks>基于Andrew monotone chain 算法,时间复杂度nlogn 在几个凸包算法中表现比较好</remarks> public static Mesh CreateConvexhullMeshByMonotoneChain(List <Vector3> points, Vector3 normal, TriangleWindingOrder windingOrder = TriangleWindingOrder.CounterClockWise) { Vector3 planeRight = Mathf.Abs(normal.x) > Mathf.Abs(normal.y) ? new Vector3(0, 1, 0) : new Vector3(1, 0, 0); Vector3 vAxis = Vector3.Cross(planeRight, normal).normalized; Vector3 uAxis = Vector3.Cross(normal, vAxis).normalized; Vector3[] meshVertices; Vector2[] meshUVs; int[] meshTriangles; bool isValid = CreateConvexHullByMonotoneChain(points, uAxis, vAxis, out meshVertices, out meshUVs, out meshTriangles, windingOrder); if (!isValid) { return(null); } Mesh convexHullMesh = new Mesh(); convexHullMesh.vertices = meshVertices; convexHullMesh.uv = meshUVs; convexHullMesh.triangles = meshTriangles; convexHullMesh.RecalculateNormals(); convexHullMesh.RecalculateTangents(); return(convexHullMesh); }