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 { /// /// 3D 预览控件: Viewport3D + 鼠标左键拖拽旋转 + 滚轮缩放。 /// 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(); 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); } /// 加载圆柱列表并自动取景。 public void Load(List 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); } } }