HelixToolkit.SharpDX 渲染ply点云

发布时间:2026/7/2 4:50:27

HelixToolkit.SharpDX 渲染ply点云 HelixToolkit.SharpDX是HelixToolkit生态中基于DirectXDX底层能力封装的 .NET 开源 3D 可视化库DirectX是微软为 Windows 平台开发的底层多媒体 API可高效调用显卡、声卡等硬件实现高性能图形渲染而该库基于此能力兼容 .NET Framework/.NET Core/.NET 5 全平台专为 Windows 桌面应用提供低门槛、高性能的 3D 渲染完美适配机械臂可视化、点云处理、设备仿真等工业开发场景一、NuGet 包管理器中下载相关包NuGet 依赖安装HelixToolkit.Wpf和HelixToolkit.SharpDX.Core.Wpf二、引入HelixToolkit.SharpDXxmlns:hxhttp://helix-toolkit.org/wpf/SharpDX三、示例工程文件MainWindow.xamlWindow x:ClassHelixToolkit.DX.PointCloud.MainWindow xmlnshttp://schemas.microsoft.com/winfx/2006/xaml/presentation xmlns:xhttp://schemas.microsoft.com/winfx/2006/xaml xmlns:dhttp://schemas.microsoft.com/expression/blend/2008 xmlns:hxhttp://helix-toolkit.org/wpf/SharpDX xmlns:localclr-namespace:HelixToolkit.DX.PointCloud xmlns:mchttp://schemas.openxmlformats.org/markup-compatibility/2006 xmlns:prismhttp://prismlibrary.com/ xmlns:uihttp://schemas.inkore.net/lib/ui/wpf/modern xmlns:vmclr-namespace:HelixToolkit.DX.PointCloud.ViewModels prism:ViewModelLocator.AutoWireViewModelTrue ui:WindowHelper.SystemBackdropTypeMica ui:WindowHelper.UseModernWindowStyleTrue mc:Ignorabled Grid hx:Viewport3DX BackgroundColorBlack EffectsManager{Binding EffectsManager} IsRotationEnabledTrue IsShadowMappingEnabledTrue RotateAroundMouseDownPointTrue ShowCoordinateSystemTrue ShowFrameRateTrue ShowViewCubeTrue ZoomAroundMouseDownPointTrue ZoomExtentsWhenLoadedTrue !-- 视口输入绑定定义鼠标和键盘操作 -- hx:Viewport3DX.InputBindings !-- CtrlE快捷键缩放至整个模型 -- KeyBinding Commandhx:ViewportCommands.ZoomExtents GestureControlE / !-- 鼠标右键旋转视图 -- MouseBinding Commandhx:ViewportCommands.Rotate GestureRightClick / !-- 鼠标中键缩放视图 -- MouseBinding Commandhx:ViewportCommands.Zoom GestureMiddleClick / !-- 鼠标左键平移视图 -- MouseBinding Commandhx:ViewportCommands.Pan GestureLeftClick / /hx:Viewport3DX.InputBindings !-- 相机默认位置 -- hx:Viewport3DX.Camera hx:PerspectiveCamera LookDirection0,0,-10 Position0,0,10 UpDirection0,1,0 / /hx:Viewport3DX.Camera !-- 阴影贴图定义阴影的渲染参数 -- hx:ShadowMap3D OrthoWidth200 / !-- 环境光基础照明 -- hx:AmbientLight3D ColorWhite / !-- 平行光方向性光源光线方向向量 -- hx:DirectionalLight3D Direction100, -100, -150 / hx:PointGeometryModel3D FigureEllipse Geometry{Binding BatchedGeometry} Size1,1 ColorWhite / /hx:Viewport3DX !-- 简单的加载按钮 -- Button Margin20 Padding10,5 HorizontalAlignmentLeft VerticalAlignmentTop Command{Binding LoadPlyCommand} ContentLoad PLY File / /Grid /WindowMainWindowViewModelusing HelixToolkit.SharpDX.Core; using HelixToolkit.SharpDX.Core.Core; using HelixToolkit.Wpf.SharpDX; using Microsoft.Win32; using SharpDX; using System; using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Media3D; using PerspectiveCamera HelixToolkit.Wpf.SharpDX.PerspectiveCamera; namespace HelixToolkit.DX.PointCloud.ViewModels { public class MainWindowViewModel : BindableBase, IDisposable { /// summary /// 消息对话框实例 /// /summary private readonly IDialogHelper _dialogHelper; public MainWindowViewModel(IContainerExtension container) { _dialogHelper container.ResolveIDialogHelper(); } private DefaultEffectsManager _effectsManager new(); /// summary /// 特效管理器 /// 管理渲染管线、着色器等 /// /summary public DefaultEffectsManager EffectsManager { get _effectsManager; set SetProperty(ref _effectsManager, value); } private PointGeometry3D? _batchedGeometry; /// summary /// 点云几何体 /// 定义3D场景中的点云数据 /// /summary public PointGeometry3D? BatchedGeometry { get _batchedGeometry; set SetProperty(ref _batchedGeometry, value); } /// summary /// 选择PLY文件并加载点云事件 /// /summary public ICommand LoadPlyCommand new DelegateCommand(SelectPlyFile); /// summary /// 选择PLY文件并加载点云 /// /summary private void SelectPlyFile() { var openFileDialog new OpenFileDialog { Filter PLY files (*.ply)|*.ply|All files (*.*)|*.*, Title Select a PLY file }; if (openFileDialog.ShowDialog() true) { try { LoadPlyFile(openFileDialog.FileName); } catch (Exception ex) { _dialogHelper.ShowMessageAsync(报错, $Error loading file:\n{ex.Message}); } } } /// summary /// 加载PLY文件并创建点云几何体 /// /summary /// param namefilePath/param private void LoadPlyFile(string filePath) { // 解析PLY获取位置和颜色所有点都包含颜色 var (positions, colors) ParsePly(filePath); if (positions.Count 0) { _dialogHelper.ShowMessageAsync(报错, No points found in the file.); return; } // 创建几何体设置位置和颜色 var geometry new PointGeometry3D { Positions new Vector3Collection(positions), Colors new Color4Collection(colors) // colors 一定存在且数量匹配 }; // 创建点云模型 var pointModel new PointGeometryModel3D { Geometry geometry, Size new Size(1, 1), // 点大小设大一点便于观察 Figure PointFigure.Ellipse, Color Colors.White, }; // 添加到视口 BatchedGeometry geometry; _dialogHelper.ShowMessageAsync(成功, $成功加载 {positions.Count} 个点。); } /// summary /// 解析ASCII PLY文件提取顶点位置和颜色。 /// 假设文件包含x y z red green blue (red/green/blue为uchar 0-255) /// /summary private (ListVector3 positions, ListColor4 colors) ParsePly(string filePath) { var positions new ListVector3(); var colors new ListColor4(); bool readingData false; foreach (string line in File.ReadLines(filePath)) { string trimmed line.Trim(); if (string.IsNullOrEmpty(trimmed)) continue; if (!readingData) { // 查找头部结束标志 if (trimmed end_header) { readingData true; } continue; } // 解析数据行每行至少6个值x y z r g b string[] parts trimmed.Split(new[] { , \t }, StringSplitOptions.RemoveEmptyEntries); if (parts.Length 6) continue; // 不符合要求跳过但你的数据应该都符合 try { float x float.Parse(parts[0], CultureInfo.InvariantCulture); float y float.Parse(parts[1], CultureInfo.InvariantCulture); float z float.Parse(parts[2], CultureInfo.InvariantCulture); positions.Add(new Vector3(x, y, z)); // 解析RGB值0-255转换为0-1范围的float byte r byte.Parse(parts[3], CultureInfo.InvariantCulture); byte g byte.Parse(parts[4], CultureInfo.InvariantCulture); byte b byte.Parse(parts[5], CultureInfo.InvariantCulture); colors.Add(new Color4(r / 255.0f, g / 255.0f, b / 255.0f, 1.0f)); } catch (Exception ex) { // 如果某行解析失败可以选择跳过或报错。这里简单跳过并输出警告 _dialogHelper.ShowMessageAsync(警告, $Skipping line due to error:\n{ex.Message}); continue; } } // 确保颜色数量与顶点数量一致正常情况下应该一致 if (positions.Count ! colors.Count) _dialogHelper.ShowMessageAsync(报错, $Parsed {positions.Count} positions but {colors.Count} colors.); return (positions, colors); } /// summary /// 释放资源 /// /summary public void Dispose() { GC.SuppressFinalize(this); } } }

相关新闻