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 bool isUglyDiamond = false;
///
/// 视图中三角形实体们
///
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,
}