using System.Linq; using System.Text.Json.Nodes; using System.Windows.Controls; using System.Windows.Media.Media3D; using HelixToolkit.Wpf.SharpDX; using MathNet.Numerics; using SharpDX; using SharpDX.Direct3D11; using SparkClient.Views.Dialog; using SparkClient.Views.UserControl.ViewportData.Entity; using SparkClient.Views.UserControl.ViewportData.Enum; using GeometryModel3D = HelixToolkit.Wpf.SharpDX.GeometryModel3D; namespace SparkClient.Views.UserControl.ViewportData.Helper; public class ViewportManager { /// /// 视图中三角形实体们 /// public static List ViewportTriangle = new List(); public static JsonObject DiamondData = new JsonObject(); /// /// 模型正方向(从模型中心出发的方向) /// public static Vector3 PositiveDirection = new Vector3(0, 0, 0); /// /// 模型中心点 /// public static Vector3 CenterVector = new Vector3(0, 0, 0); /// /// 腰的顶部线 /// public static List GirdleTopLines = new List(); /// /// 腰的底部线 /// public static List GirdleBottomLines = new List(); /// /// 模型盒子 /// public static BoundingBox ModelBounds = new BoundingBox(); /// /// 模型主体 /// public static MeshGeometryModel3D MainModel3D = null; /// /// 模型边框线 /// public static List MainModelLines = new List(); /// /// 网格线 /// public static List MainModelMeshLines_C = new List(); /// /// 网格线(圈) /// public static LineGeometryModel3D MainModelCircleLine_C = new LineGeometryModel3D(); /// /// 网格线 /// public static List MainModelMeshLines_P = new List(); /// /// 网格线(圈) /// public static LineGeometryModel3D MainModelCircleLine_P = new LineGeometryModel3D(); /// /// 腰垂直线 /// public static List> MainModelGirdleLines = new List>(); public static Tuple MainModelGirdleMaxLines = null; public static Tuple MainModelGirdleMinLines = null; public static Tuple MainModelGirdleAvgLines = null; /// /// 模型光照 /// public static List MainModelLighting = new List(); public static List MainModelMeshes = new List(); public static ColorConfigEntity ColorConfig = new ColorConfigEntity(); public static readonly double sacle = 1.875; /// /// 模型控件对象映射 /// private static Viewport3DX _viewport; //模型 private static Viewport3D _viewport3D = null; public static void SetViewport3D(Viewport3DX viewport3D) { if (_viewport != null) { ClearDicModels(); _viewport.Items.Clear(); } _viewport = viewport3D; } public static Viewport3DX GetViewport3D() { if (_viewport == null) throw new Exception("Viewport is not set"); return _viewport; } public static void SetViewport(Viewport3D viewport3D) { if (_viewport != null) { ClearDicModels(); _viewport.Items.Clear(); } _viewport3D = viewport3D; } public static Viewport3D GetViewport() { if (_viewport3D == null) throw new Exception("Viewport is not set"); return _viewport3D; } #region 模型选中交互管理 //是否双击选中 public static bool DoubleClickSelect = true; //开启选中边框线 public static bool DoubleClickSelectShowBorder = true; //选中边框长度文字 public static bool DoubleClickSelectShowBorderLength = false; //选中边框夹角文字 public static bool DoubleClickSelectShowBorderAngle = false; public static bool DoubleClickSelectShowInfoText = true; //选中同类面 public static bool DoubleClickSelectShowPlaneType = true; //选中三角形代码 public static string ChooseTriangleCode = string.Empty; //通过选中添加的元素 public static List ChooseAddModels = new List(); /// /// 重置选中的面 /// public static void ResetChooseAddModels(string valType = "") { if (string.IsNullOrWhiteSpace(ChooseTriangleCode)) { ClearDicModels(); return; } ClearDicModels(); HashSet models = new HashSet(); models.Add(SelShowType.SelPanel); if (DoubleClickSelectShowBorder) models.Add(SelShowType.Border); if (DoubleClickSelectShowInfoText) models.Add(SelShowType.LengthText); // if (DoubleClickSelectShowBorderAngle) models.Add(SelShowType.BorderAngle); if (DoubleClickSelectShowPlaneType) models.Add(SelShowType.IsTypePanel); ChooseAddModels.AddRange(ViewportHelperPro.GentrateChosenView(ChooseTriangleCode, valType, models.ToArray())); ChooseAddModels.ForEach(e => { if (e != null) _viewport.Items.Add(e); }); } /// /// 清除所有的选中效果 /// public static void ClearDicModels() { foreach (var item in ChooseAddModels) { _viewport.Items.Remove(item); } ChooseAddModels.Clear(); } public static void InitMeshLines() { ViewportHelperPro.InitMeshLines(); MainModelMeshLines_C.Clear(); MainModelMeshLines_C.AddRange(ViewportHelperPro.ShowMeshLines()); MainModelCircleLine_C = ViewportHelperPro.ShowCircleLine(); MainModelMeshLines_P.Clear(); MainModelMeshLines_P.AddRange(ViewportHelperPro.ShowMeshLines(false)); MainModelCircleLine_P = ViewportHelperPro.ShowCircleLine(false); } public static void ResetMeshLines() { if (_viewport.Items.Contains(MainModelMeshLines_C[0])) { ViewportManager.ShowMeshLines(false, true); MainModelMeshLines_C.Clear(); MainModelMeshLines_C.AddRange(ViewportHelperPro.ShowMeshLines()); MainModelCircleLine_C = ViewportHelperPro.ShowCircleLine(); ViewportManager.ShowMeshLines(true, true); } if (_viewport.Items.Contains(MainModelMeshLines_P[0])) { ViewportManager.ShowMeshLines(false, false); MainModelMeshLines_P.Clear(); MainModelMeshLines_P.AddRange(ViewportHelperPro.ShowMeshLines(false)); MainModelCircleLine_P = ViewportHelperPro.ShowCircleLine(false); ViewportManager.ShowMeshLines(true, false); } } /// /// 模拟面选中 /// /// public static void MockSelectFacet(string planTypeStr) { if ("GIRDLE".Equals(planTypeStr)) planTypeStr = "GIRDLE_VALLEY"; PlaneType planeType = PlaneType.Crown; if (DicValueParamToFacet.ContainsKey(planTypeStr)) { planeType = DicValueParamToFacet[planTypeStr]; } else { ClearDicModels(); return; } List entities = ViewportHelperPro.GenerateLineTextModelsByType(planeType); if (entities.Count <= 0) { ClearDicModels(); } ChooseTriangleCode = entities[0].TriangleCode; ResetChooseAddModels(planTypeStr); } #region 面 - 数据固定绑定 // 选中面 -> 数据 public static Dictionary DicFacetToValueParam = new Dictionary() { { PlaneType.UpperMainFacet,"CROWN_ANGLE"}, { PlaneType.PavilionMainFacet, "PAV_ANGLE"}, { PlaneType.StarFacet, "STAR"}, { PlaneType.TableFacet, "TABLE"}, { PlaneType.Culet, "COC"}, { PlaneType.LowerGirdleFact, "LOWER_HALVES_RATIO"}, }; // 数据 -> 面 public static Dictionary DicValueParamToFacet = new Dictionary() { {"CROWN_ANGLE", PlaneType.UpperMainFacet}, {"PAV_ANGLE", PlaneType.PavilionMainFacet}, //新加 {"TOTAL_DEPTH", PlaneType.PavilionMainFacet}, {"TABLE", PlaneType.TableFacet}, {"CROWN_HEIGHT", PlaneType.UpperMainFacet}, {"PAV_DEPTH", PlaneType.PavilionMainFacet}, {"STAR", PlaneType.StarFacet}, {"LOWER_HALVES_RATIO", PlaneType.LowerGirdleFact}, {"CULET", PlaneType.Culet}, {"TOC", PlaneType.TableFacet}, {"COC", PlaneType.Culet}, {"TWIST", PlaneType.UpperMainFacet}, {"CULET_TO_TABLE", PlaneType.Culet}, {"DIAMETER", PlaneType.Girdle}, {"GIRDLE_BEZEL", PlaneType.Girdle}, {"GIRDLE_BONE", PlaneType.Girdle}, {"GIRDLE_VALLEY", PlaneType.Girdle}, }; #endregion #endregion #region 统一控制方法 public static MeshGeometryModel3D PointTowardsTheFrontModel = new MeshGeometryModel3D(); public static void PointTowardsTheFront(bool isPoint) { if (isPoint) { var camera = ViewportHelperPro.CalculateCamera(PositiveDirection, ModelBounds); PointTowardsTheFrontModel = ViewportHelperPro.CreateArrow(camera.Position.ToVector3(), ModelBounds.Center, ModelBounds); _viewport.Items.Add(PointTowardsTheFrontModel); } else { _viewport.Items.Remove(PointTowardsTheFrontModel); } } public static MeshGeometryModel3D MarkFacesModel = new MeshGeometryModel3D(); public static void MarkSpecificFaces(bool isMark) { if (isMark) { MarkFacesModel = ViewportHelperPro.GenerateTypePanelHot(PlaneType.Error); _viewport.Items.Add(MarkFacesModel); } else { _viewport.Items.Remove(MarkFacesModel); } } /// /// 初始化加载模型 /// /// /// public static void LoadModelByEntities(List entities) { if (entities.Count == 0 && ViewportTriangle.Count != 0) { entities.AddRange(ViewportTriangle); } //重置 _viewport.Items.Clear(); ChooseTriangleCode = string.Empty; ChooseAddModels.Clear(); ResetChooseAddModels(); //刷新三角形 ViewportTriangle.Clear(); ViewportTriangle.AddRange(entities); //初始化 MainModelLines = ViewportHelperPro.GentrateLineByEntity(_viewport, entities); MainModel3D = ViewportHelperPro.GenerateModelByEntity(_viewport, entities); MainModelLighting = ViewportHelperPro.GenerateLightingForModel(_viewport); MainModelMeshes = ViewportHelperPro.GenerateModelByEntityGroupByType(entities); var gridle = ViewportHelperPro.GentrateLineGirdleByEntity(entities); if (gridle == null) { gridle = new List(); DicValueParamToFacet.Remove("DIAMETER"); DicValueParamToFacet.Remove("GIRDLE_BEZEL"); DicValueParamToFacet.Remove("GIRDLE_BONE"); DicValueParamToFacet.Remove("GIRDLE_VALLEY"); } else { DicValueParamToFacet.TryAdd("DIAMETER", PlaneType.Girdle); DicValueParamToFacet.TryAdd("GIRDLE_BEZEL", PlaneType.Girdle); DicValueParamToFacet.TryAdd("GIRDLE_BONE", PlaneType.Girdle); DicValueParamToFacet.TryAdd("GIRDLE_VALLEY", PlaneType.Girdle); } MainModelLines.AddRange(gridle); //切换相机视角 _viewport.Camera = ViewportHelperPro.CalculateCamera(PositiveDirection, ModelBounds); _viewport.Camera.UpDirection = new Vector3D(0, -1, 0); var center = ViewportManager.ModelBounds.Center; var maxDimension = ViewportManager.ModelBounds.Size.Length(); var distance = maxDimension * 1.2; // 调整相机到模型的距离,保证视野范围内 var camera = _viewport.Camera as HelixToolkit.Wpf.SharpDX.OrthographicCamera; camera.Position = new Point3D(center.X, center.Y - distance, center.Z); // 从底部看,Y轴负方向 camera.UpDirection = new Vector3D(0, 0, -1); camera.LookDirection = new Vector3D(center.X - camera.Position.X, center.Y - camera.Position.Y, center.Z - camera.Position.Z); _viewport.RenderHost.MSAA = MSAALevel.Maximum; // TODO: InitMeshLines(); } /// /// 是否显示主体模型 /// /// public static void ShowMainModel3D(bool isShow) { if (MainModel3D == null) return; if (_viewport == null) return; if (isShow) { if (_viewport.Items.Contains(MainModel3D)) return; else _viewport.Items.Add(MainModel3D); } else { _viewport.Items.Remove(MainModel3D); } } /// /// 是否显示主体模型 /// /// public static void ShowMainModel3DByType(bool isShow) { if (MainModel3D == null) return; if (_viewport == null) return; if (isShow) { MainModelMeshes.ForEach(e => { if (!_viewport.Items.Contains(e)) _viewport.Items.Add(e); }); } else { MainModelMeshes.ForEach(e => { _viewport.Items.Remove(e); }); } } public static void ShowMainModelLines(bool isShow) { if (_viewport == null) return; if (isShow) { MainModelLines.ForEach(e => { if (!_viewport.Items.Contains(e)) _viewport.Items.Add(e); }); } else { MainModelLines.ForEach(e => _viewport.Items.Remove(e)); } } public static void ShowMainModelLighting(bool isShow) { if (_viewport == null) return; if (isShow) { MainModelLighting.ForEach(e => { if (!_viewport.Items.Contains(e)) _viewport.Items.Add(e); }); } else { MainModelLighting.ForEach(e => _viewport.Items.Remove(e)); } } public static void Translucent(bool isShow) { if (_viewport == null) return; if (isShow) { MainModel3D.Material = _glassMaterial; } else { MainModel3D.Material = _material; } } public static void TranslucentTex(bool isShow) { if (_viewport == null) return; if (isShow) { string texturePath2 = "pack://Appliction:,,,/Res/morning_racing_circuit_16k.dds"; var texture2 = TextureModel.Create(texturePath2); var material = new PBRMaterial { AlbedoColor = new SharpDX.Color4(0.0f, 1.0f, 1.0f, 1.0f), // 白色基色 MetallicFactor = 0.0f, RoughnessFactor = 0.5f, ReflectanceFactor = 0.2f, RenderEnvironmentMap = false, // AlbedoMap = texture, IrradianceMap = texture2, RenderIrradianceMap = true, }; MainModel3D.Material = material; } else { MainModel3D.Material = _material; } } public static void LockCameraView(bool isShow) { /*Generate Ruler * FixedPosition:用于静态视角,用户无法互动。 * WalkAround:用于用户自由控制相机位置。 * Inspect:用于观察和检查物体,用户可以旋转和缩放,但不能平移。(默认) */ // Viewport3Dx.CameraMode = CameraMode.Inspect; if (_viewport == null) return; if (isShow) { _viewport.CameraMode = CameraMode.FixedPosition; } else { _viewport.CameraMode = CameraMode.Inspect; } } public static double calCameraWidth() { return ModelBounds.Size.Z * sacle; } public static void ShowMeshLines(bool isShow,bool isCrown) { if (_viewport == null) return; if (isShow) { if (isCrown) { MainModelMeshLines_C.ForEach(e => { if (!_viewport.Items.Contains(e)) _viewport.Items.Add(e); }); if (!_viewport.Items.Contains(MainModelCircleLine_C)) _viewport.Items.Add(MainModelCircleLine_C); } else { MainModelMeshLines_P.ForEach(e => { if (!_viewport.Items.Contains(e)) _viewport.Items.Add(e); }); if (!_viewport.Items.Contains(MainModelCircleLine_P)) _viewport.Items.Add(MainModelCircleLine_P); } } else { MainModelMeshLines_C.ForEach(e => _viewport.Items.Remove(e)); _viewport.Items.Remove(MainModelCircleLine_C); MainModelMeshLines_P.ForEach(e => _viewport.Items.Remove(e)); _viewport.Items.Remove(MainModelCircleLine_P); } } public static void ClearMeshLines() { ViewportManager.ShowMeshLines(false, true); ViewportManager.ShowMeshLines(false, false); ViewportManager.GetViewport().ViewportRightMenuShowMeshLines.IsChecked = false; } #endregion #region 预制颜色 /// /// 材质:半透明蓝 /// private static PBRMaterial _glassMaterial = new PBRMaterial { // 半透明蓝色 AlbedoColor = new Color4(0.0f, 0.0f, 1.0f, 0.5f), // 设置为非金属 MetallicFactor = 0.0, // 光滑表面 RoughnessFactor = 0.05, // 环境光遮蔽 AmbientOcclusionFactor = 1.0, // 强反射 ReflectanceFactor = 0.9, // 清漆效果(类似折射效果) ClearCoatStrength = 0.8, ClearCoatRoughness = 0.05, // 启用环境贴图以增强反射 RenderEnvironmentMap = true, // 启用阴影效果 RenderShadowMap = true }; /// /// 默认灰色自发光 /// private static PBRMaterial _material = new PBRMaterial { AlbedoColor = new Color4(0,0,0,1f), // 黑色,避免其他光照影响 EmissiveColor = ColorConfig.MainFacetColor , // LightGray #D3D3D3 MetallicFactor = 0.0, // 非金属 RoughnessFactor = 1.0, // 高粗糙度,避免反射效果 ReflectanceFactor = 0.0, // 无反射 ClearCoatStrength = 0.0, // 无清漆效果 ClearCoatRoughness = 1.0, // 高粗糙度 SurfaceMapSampler = new SamplerStateDescription { Filter = Filter.MinMagMipLinear, AddressU = TextureAddressMode.Wrap, AddressV = TextureAddressMode.Wrap, AddressW = TextureAddressMode.Wrap } }; #endregion } public enum SelShowType { Border = 0, LengthText = 1, BorderAngle = 2, IsTypePanel = 3, SelPanel = 4, }