109 lines
3.9 KiB
C#
109 lines
3.9 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Windows;
|
|
using System.Windows.Controls;
|
|
using System.Windows.Input;
|
|
using System.Windows.Media;
|
|
using System.Windows.Media.Media3D;
|
|
using Ounibo.Catalog.Viewer3D;
|
|
|
|
namespace Ounibo.Catalog.App
|
|
{
|
|
/// <summary>
|
|
/// 3D 预览控件: Viewport3D + 鼠标左键拖拽旋转 + 滚轮缩放。
|
|
/// </summary>
|
|
public class ViewerControl : UserControl
|
|
{
|
|
Viewport3D _vp;
|
|
PerspectiveCamera _cam;
|
|
Model3DGroup _root;
|
|
Point _last;
|
|
double _theta = 0.6, _phi = 0.9, _dist = 300;
|
|
bool _dragging;
|
|
|
|
public ViewerControl()
|
|
{
|
|
_root = new Model3DGroup();
|
|
_root.Children.Add(new DirectionalLight(Colors.White, new Vector3D(-1, -1, -2)));
|
|
_root.Children.Add(new DirectionalLight(Colors.White, new Vector3D(1, 0.5, 1)));
|
|
|
|
_cam = new PerspectiveCamera
|
|
{
|
|
Position = new Point3D(0, 0, 300),
|
|
LookDirection = new Vector3D(0, 0, -1),
|
|
UpDirection = new Vector3D(0, 1, 0),
|
|
FieldOfView = 45
|
|
};
|
|
_vp = new Viewport3D { Camera = _cam };
|
|
_vp.Children.Add(new ModelVisual3D { Content = _root });
|
|
Content = new Border { Background = Brushes.White, Child = _vp };
|
|
|
|
_vp.MouseLeftButtonDown += (s, e) => { _dragging = true; _last = e.GetPosition(_vp); _vp.CaptureMouse(); };
|
|
_vp.MouseMove += (s, e) =>
|
|
{
|
|
if (!_dragging) return;
|
|
var p = e.GetPosition(_vp);
|
|
var dx = p.X - _last.X;
|
|
var dy = p.Y - _last.Y;
|
|
_last = p;
|
|
_theta -= dx * 0.01;
|
|
_phi = Math.Max(-1.45, Math.Min(1.45, _phi + dy * 0.01));
|
|
UpdateCamera();
|
|
};
|
|
_vp.MouseLeftButtonUp += (s, e) => { _dragging = false; _vp.ReleaseMouseCapture(); };
|
|
_vp.MouseWheel += (s, e) =>
|
|
{
|
|
_dist *= (e.Delta > 0) ? 0.88 : 1.13;
|
|
_dist = Math.Max(20, Math.Min(4000, _dist));
|
|
UpdateCamera();
|
|
};
|
|
}
|
|
|
|
public void Clear()
|
|
{
|
|
var lights = new List<Light>();
|
|
foreach (var m in _root.Children)
|
|
if (m is Light) lights.Add((Light)m);
|
|
_root.Children.Clear();
|
|
foreach (var l in lights) _root.Children.Add(l);
|
|
}
|
|
|
|
/// <summary>加载圆柱列表并自动取景。</summary>
|
|
public void Load(List<Cyl> cyls)
|
|
{
|
|
Clear();
|
|
if (cyls == null || cyls.Count == 0) return;
|
|
|
|
// 颜色: 0 后盖 / 1 缸体 / 2 前盖 / 3 活塞杆
|
|
var brushes = new[]
|
|
{
|
|
new SolidColorBrush(Color.FromRgb(0x8C, 0x8C, 0x8C)),
|
|
new SolidColorBrush(Color.FromRgb(0x2F, 0x6F, 0xB3)),
|
|
new SolidColorBrush(Color.FromRgb(0x8C, 0x8C, 0x8C)),
|
|
new SolidColorBrush(Color.FromRgb(0xC8, 0xC8, 0xC8))
|
|
};
|
|
for (int i = 0; i < cyls.Count; i++)
|
|
{
|
|
var mesh = StepMesh.BuildMesh(cyls[i]);
|
|
var mat = new DiffuseMaterial(brushes[i % brushes.Length]);
|
|
_root.Children.Add(new GeometryModel3D(mesh, mat) { BackMaterial = mat });
|
|
}
|
|
|
|
double cx, cy, cz, r, h;
|
|
StepMesh.Bounds(cyls, out cx, out cy, out cz, out r, out h);
|
|
_dist = Math.Max(120, Math.Max(r * 5.0, h * 1.6));
|
|
_theta = 0.55; _phi = 0.85;
|
|
UpdateCamera();
|
|
}
|
|
|
|
void UpdateCamera()
|
|
{
|
|
double x = _dist * Math.Sin(_theta) * Math.Cos(_phi);
|
|
double y = _dist * Math.Sin(_phi);
|
|
double z = _dist * Math.Cos(_theta) * Math.Cos(_phi);
|
|
_cam.Position = new Point3D(x, y, z);
|
|
_cam.LookDirection = new Vector3D(-x, -y, -z);
|
|
}
|
|
}
|
|
}
|