using System.IO; using System.Text; using SharpDX; using SparkClient.Views.UserControl.ViewportData.Entity; using SparkClient.Views.UserControl.ViewportData.Enum; namespace SparkClient.Views.UserControl.ViewportData.Helper; public class ObjExporter { public static void ExportToObj2(List entities, string outputPath) { //分组 Dictionary> feactList = entities .Where(entity => entity.PlaneType != PlaneType.Girdle) .GroupBy(entity => entity.PlaneCode) .ToDictionary(group => group.Key, group => group.ToList()); //腰 单组 List waistList = entities .Where(entity => entity.PlaneType == PlaneType.Girdle) .ToList(); //同一个面只保留外边框(除了腰) Dictionary> resultPoints = new Dictionary>(); foreach (var dic in feactList) { List tempPoints = new List(); foreach (var entity in dic.Value) { tempPoints.Add(entity.Point1); tempPoints.Add(entity.Point2); tempPoints.Add(entity.Point3); } resultPoints.Add(dic.Key, ViewportHelperPro.VectorClockwiseSort(new HashSet(tempPoints).ToList())); } List selFaceVector = new List(); if (waistList.Count > 0) { foreach (var entity in waistList) { selFaceVector.Add(entity.Point1); selFaceVector.Add(entity.Point2); selFaceVector.Add(entity.Point3); } } resultPoints.Add("yao", selFaceVector); StringBuilder sb = new StringBuilder(); // 顶点列表 List uniqueVertices = new List(); Dictionary vertexIndexMap = new Dictionary(); // 1. 对每个面生成顶点和面 foreach (var face in resultPoints) { // 对每个面,获取它的顶点列表 List faceVertices = face.Value; // 去重顶点 foreach (var vertex in faceVertices) { if (!vertexIndexMap.ContainsKey(vertex)) { vertexIndexMap[vertex] = uniqueVertices.Count; uniqueVertices.Add(vertex); } } } // 2. 写入顶点数据 foreach (var vertex in uniqueVertices) { sb.AppendLine($"v {vertex.X} {vertex.Y} {vertex.Z}"); } // 3. 写入每个面(f行),包括正面和反面 foreach (var face in resultPoints) { sb.AppendLine($"# Face: {face.Key}"); // 获取面上的所有顶点并排序 List faceVertices = face.Value; // Vector3 center = GetCenterOfVertices(faceVertices); // faceVertices.Sort((v1, v2) => GetAngle(v1, center).CompareTo(GetAngle(v2, center))); // 正面:按顺时针顺序输出 sb.Append("f"); foreach (var vertex in faceVertices) { sb.Append($" {vertexIndexMap[vertex] + 1}"); } sb.AppendLine(); // 反面:按逆时针顺序输出(反转顶点顺序) sb.Append("f"); for (int i = faceVertices.Count - 1; i >= 0; i--) { sb.Append($" {vertexIndexMap[faceVertices[i]] + 1}"); } sb.AppendLine(); } // 4. 写入文件 File.WriteAllText(outputPath, sb.ToString()); } // 计算一组顶点的中心点(用于排序) private static Vector3 GetCenterOfVertices(List vertices) { float centerX = 0, centerY = 0, centerZ = 0; foreach (var vertex in vertices) { centerX += vertex.X; centerY += vertex.Y; centerZ += vertex.Z; } return new Vector3(centerX / vertices.Count, centerY / vertices.Count, centerZ / vertices.Count); } private static float GetAngle(Vector3 vertex, Vector3 center) { // 计算顶点与中心的方向向量 Vector3 direction = vertex - center; // 在XY平面上计算角度 float angle = (float)Math.Atan2(direction.Y, direction.X); // 返回的是弧度,[-π, π] // 如果你想要角度范围 [0, 2π],可以做如下处理 if (angle < 0) { angle += MathF.PI * 2; } return angle; } }