You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
502 lines
16 KiB
502 lines
16 KiB
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.UserControl.ViewportData.Entity; |
|
using SparkClient.Views.UserControl.ViewportData.Enum; |
|
using GeometryModel3D = HelixToolkit.Wpf.SharpDX.GeometryModel3D; |
|
|
|
namespace SparkClient.Views.UserControl.ViewportData.Helper; |
|
|
|
public class ViewportManager |
|
{ |
|
/// <summary> |
|
/// 视图中三角形实体们 |
|
/// </summary> |
|
public static List<Viewport3DTriangleEntity> ViewportTriangle = new List<Viewport3DTriangleEntity>(); |
|
|
|
public static JsonObject DiamondData = new JsonObject(); |
|
/// <summary> |
|
/// 模型正方向(从模型中心出发的方向) |
|
/// </summary> |
|
public static Vector3 PositiveDirection = new Vector3(0, 0, 0); |
|
/// <summary> |
|
/// 模型中心点 |
|
/// </summary> |
|
public static Vector3 CenterVector = new Vector3(0, 0, 0); |
|
/// <summary> |
|
/// 腰的顶部线 |
|
/// </summary> |
|
public static List<Vector3> GirdleTopLines = new List<Vector3>(); |
|
/// <summary> |
|
/// 腰的底部线 |
|
/// </summary> |
|
public static List<Vector3> GirdleBottomLines = new List<Vector3>(); |
|
/// <summary> |
|
/// 模型盒子 |
|
/// </summary> |
|
public static BoundingBox ModelBounds = new BoundingBox(); |
|
/// <summary> |
|
/// 模型主体 |
|
/// </summary> |
|
public static MeshGeometryModel3D MainModel3D = null; |
|
/// <summary> |
|
/// 模型边框线 |
|
/// </summary> |
|
public static List<LineGeometryModel3D> MainModelLines = new List<LineGeometryModel3D>(); |
|
/// <summary> |
|
/// 网格线 |
|
/// </summary> |
|
public static List<LineGeometryModel3D> MainModelMeshLines = new List<LineGeometryModel3D>(); |
|
/// <summary> |
|
/// 网格线(圈) |
|
/// </summary> |
|
public static LineGeometryModel3D MainModelCircleLine = new LineGeometryModel3D(); |
|
/// <summary> |
|
/// 腰垂直线 |
|
/// </summary> |
|
public static List<Tuple<Vector3, Vector3>> MainModelGirdleLines = new List<Tuple<Vector3, Vector3>>(); |
|
public static Tuple<Vector3, Vector3> MainModelGirdleMaxLines = null; |
|
public static Tuple<Vector3, Vector3> MainModelGirdleMinLines = null; |
|
public static Tuple<Vector3, Vector3> MainModelGirdleAvgLines = null; |
|
|
|
/// <summary> |
|
/// 模型光照 |
|
/// </summary> |
|
public static List<Light3D> MainModelLighting = new List<Light3D>(); |
|
|
|
public static List<MeshGeometryModel3D> MainModelMeshes = new List<MeshGeometryModel3D>(); |
|
|
|
|
|
public static ColorConfigEntity ColorConfig = new ColorConfigEntity(); |
|
|
|
/// <summary> |
|
/// 模型控件对象映射 |
|
/// </summary> |
|
private static Viewport3DX _viewport; |
|
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; |
|
|
|
} |
|
#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<GeometryModel3D> ChooseAddModels = new List<GeometryModel3D>(); |
|
/// <summary> |
|
/// 重置选中的面 |
|
/// </summary> |
|
public static void ResetChooseAddModels(string valType = "") |
|
{ |
|
if (string.IsNullOrWhiteSpace(ChooseTriangleCode)) |
|
{ |
|
ClearDicModels(); |
|
return; |
|
} |
|
|
|
ClearDicModels(); |
|
HashSet<SelShowType> models = new HashSet<SelShowType>(); |
|
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 => _viewport.Items.Add(e)); |
|
} |
|
/// <summary> |
|
/// 清除所有的选中效果 |
|
/// </summary> |
|
public static void ClearDicModels() |
|
{ |
|
foreach (var item in ChooseAddModels) |
|
{ |
|
_viewport.Items.Remove(item); |
|
} |
|
ChooseAddModels.Clear(); |
|
} |
|
|
|
/// <summary> |
|
/// 模拟面选中 |
|
/// </summary> |
|
/// <param name="planTypeStr"></param> |
|
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<Viewport3DTriangleEntity> entities = ViewportHelperPro.GenerateLineTextModelsByType(planeType); |
|
if (entities.Count <= 0) |
|
{ |
|
ClearDicModels(); |
|
} |
|
ChooseTriangleCode = entities[0].TriangleCode; |
|
ResetChooseAddModels(planTypeStr); |
|
} |
|
|
|
#region 面 - 数据固定绑定 |
|
// 选中面 -> 数据 |
|
public static Dictionary<PlaneType, string> DicFacetToValueParam = new Dictionary<PlaneType, string>() |
|
{ |
|
{ 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<string, PlaneType> DicValueParamToFacet = new Dictionary<string, PlaneType>() |
|
{ |
|
{"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); |
|
} |
|
} |
|
|
|
/// <summary> |
|
/// 初始化加载模型 |
|
/// </summary> |
|
/// <param name="viewport"></param> |
|
/// <param name="entities"></param> |
|
public static void LoadModelByEntities(List<Viewport3DTriangleEntity> 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); |
|
MainModelLines.AddRange(ViewportHelperPro.GentrateLineGirdleByEntity(entities)); |
|
|
|
//切换相机视角 |
|
_viewport.Camera = ViewportHelperPro.CalculateCamera(PositiveDirection, ModelBounds); |
|
_viewport.Camera.UpDirection = new Vector3D(0, -1, 0); |
|
_viewport.RenderHost.MSAA = MSAALevel.Maximum; |
|
// TODO: |
|
MainModelMeshLines.AddRange(ViewportHelperPro.ShowMeshLines(entities)); |
|
MainModelCircleLine = ViewportHelperPro.ShowCircleLine(); |
|
} |
|
|
|
/// <summary> |
|
/// 是否显示主体模型 |
|
/// </summary> |
|
/// <param name="isShow"></param> |
|
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); |
|
} |
|
} |
|
|
|
/// <summary> |
|
/// 是否显示主体模型 |
|
/// </summary> |
|
/// <param name="isShow"></param> |
|
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 void ShowMeshLines(bool isShow) { |
|
|
|
if (_viewport == null) return; |
|
if (isShow) |
|
{ |
|
MainModelMeshLines.ForEach(e => |
|
{ |
|
if (!_viewport.Items.Contains(e)) |
|
_viewport.Items.Add(e); |
|
}); |
|
if (!_viewport.Items.Contains(MainModelCircleLine)) |
|
_viewport.Items.Add(MainModelCircleLine); |
|
|
|
} |
|
else |
|
{ |
|
MainModelMeshLines.ForEach(e => _viewport.Items.Remove(e)); |
|
_viewport.Items.Remove(MainModelCircleLine); |
|
} |
|
} |
|
#endregion |
|
|
|
|
|
#region 预制颜色 |
|
/// <summary> |
|
/// 材质:半透明蓝 |
|
/// </summary> |
|
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 |
|
}; |
|
|
|
/// <summary> |
|
/// 默认灰色自发光 |
|
/// </summary> |
|
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, |
|
} |