fix: OBJ文件导出

master
tongg 5 months ago
parent fb92d74587
commit 55241d544b
  1. 6
      Views/UserControl/Viewport3D.xaml.cs
  2. 116
      Views/UserControl/ViewportData/Helper/ObjExporter.cs

@ -17,6 +17,7 @@ using SharpDX.Direct3D11;
using SharpDX.DXGI;
using MathNet.Numerics;
using System.Windows.Media;
using ObjExporter = SparkClient.Views.UserControl.ViewportData.Helper.ObjExporter;
namespace SparkClient.Views.UserControl;
@ -46,7 +47,7 @@ public partial class Viewport3D
ViewportManager.LoadModelByEntities(new List<Viewport3DTriangleEntity>());
#if DEBUG
#else
BtnShow3DView.Visibility = Visibility.Hidden;
// BtnShow3DView.Visibility = Visibility.Hidden;
#endif
//选项初始化 显示-后端-管理类 一致
@ -218,7 +219,8 @@ public partial class Viewport3D
ViewportManager.DoubleClickSelect = !false;
break;
case "BtnShow3DView":
UnityHelper.GenerateRender(ViewportManager.ViewportTriangle.First().TriangleCode, "123");
ObjExporter.ExportToObj2(ViewportManager.ViewportTriangle, @"D:\id03.obj");
//UnityHelper.GenerateRender(ViewportManager.ViewportTriangle.First().TriangleCode, "123");
break;
}

@ -0,0 +1,116 @@
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<Viewport3DTriangleEntity> entities, string outputPath)
{
//分组
Dictionary<string, List<Viewport3DTriangleEntity>> feactList = entities
.Where(entity => entity.PlaneType != PlaneType.Girdle)
.GroupBy(entity => entity.PlaneCode)
.ToDictionary(group => group.Key, group => group.ToList());
//腰 单组
List<Viewport3DTriangleEntity> waistList = entities
.Where(entity => entity.PlaneType == PlaneType.Girdle)
.ToList();
//同一个面只保留外边框(除了腰)
Dictionary<string, List<Vector3>> resultPoints = new Dictionary<string, List<Vector3>>();
foreach (var dic in feactList)
{
List<Vector3> tempPoints = new List<Vector3>();
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<Vector3>(tempPoints).ToList()));
}
List<Vector3> selFaceVector = new List<Vector3>();
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<Vector3> uniqueVertices = new List<Vector3>();
Dictionary<Vector3, int> vertexIndexMap = new Dictionary<Vector3, int>();
// 1. 对每个面生成顶点和面
foreach (var face in resultPoints)
{
// 对每个面,获取它的顶点列表
List<Vector3> 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<Vector3> faceVertices = face.Value;
// Vector3 center = GetCenterOfVertices(faceVertices);
// faceVertices.Sort((v1, v2) => v1.AngleWithCenter(center).CompareTo(v2.AngleWithCenter(center)));
// center
// 输出面
sb.Append("f");
foreach (var vertex in faceVertices)
{
// 获取顶点的索引,OBJ格式从1开始
sb.Append($" {vertexIndexMap[vertex] + 1}");
}
sb.AppendLine();
}
// 4. 写入文件
File.WriteAllText(outputPath, sb.ToString());
}
// 计算一组顶点的中心点(用于排序)
private static Vector3 GetCenterOfVertices(List<Vector3> 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);
}
}
Loading…
Cancel
Save