前言
HelixToolkit 是一个基于 .NET 平台的开源3D图形库,专注于 WPF 应用开发。其功能强大且灵活,支持3D视图、模型、场景渲染、动画等核心功能,并遵循 MIT 许可证,允许在商业项目中免费使用。本文将通过一个完整的示例代码,介绍如何利用 HelixToolkit 快速开发3D场景,并解析其核心功能。
环境配置
通过 NuGet 安装 HelixToolkit:
Install-Package HelixToolkit.Wpf
核心功能
HelixToolkit 提供以下核心功能:
3D视图控制:支持旋转、平移、缩放交互。
光源系统:支持环境光、平行光、点光源等。
材质与网格:支持贴图、颜色材质及复杂几何体构建。
2D与3D混合:可在3D场景中嵌入2D控件(如按钮)。
运行效果
代码步骤
1、视图与坐标系统配置
通过 HelixViewport3D 控件配置3D视图,控制 ViewCube(视角立方体)和坐标系统:
<h:HelixViewport3D
ShowViewCube="True"
ViewCubeWidth="100"
ViewCubeHeight="100"
ViewCubeHorizontalPosition="Right"
ViewCubeVerticalPosition="Bottom"
ViewCubeFrontText="前"
ViewCubeBackText="后"
ShowCoordinateSystem="True"
CoordinateSystemLabelForeground="#5000">
2、相机配置
使用 PerspectiveCamera 定义透视相机,控制视角位置、方向及渲染范围:
<h:HelixViewport3D.Camera>
<PerspectiveCamera
Position="10,10,10"
LookDirection="-2,-2,-2"
FieldOfView="50"
UpDirection="0,1,0"
FarPlaneDistance="1000"
NearPlaneDistance="1">
<PerspectiveCamera.Transform>
<Transform3DGroup>
<!-- 旋转、平移、缩放变换 -->
<RotateTransform3D CenterX="3" CenterY="0" CenterZ="0">
<RotateTransform3D.Rotation>
<AxisAngleRotation3D Angle="0" Axis="0 1 0" x:Name="aar"/>
</RotateTransform3D.Rotation>
</RotateTransform3D>
<TranslateTransform3D OffsetX="0" OffsetY="0" OffsetZ="0" x:Name="tt"/>
<ScaleTransform3D ScaleX="1" ScaleY="1" ScaleZ="1"/>
</Transform3DGroup>
</PerspectiveCamera.Transform>
</PerspectiveCamera>
</h:HelixViewport3D.Camera>
3、光源系统
支持多种光源类型(环境光、平行光、点光源):
<ModelVisual3D>
<ModelVisual3D.Content>
<Model3DGroup>
<!-- 环境光 -->
<AmbientLight Color="White"/>
<!-- 平行光 -->
<!-- <DirectionalLight Color="White" Direction="-1,-1,-1"/> -->
<!-- 点光源 -->
<!-- <PointLight Color="White" Position="100,100,100" Range="200"/> -->
</Model3DGroup>
</ModelVisual3D.Content>
</ModelVisual3D>
4、3D对象与材质
通过 MeshGeometry3D 定义几何体,结合材质实现复杂效果:
<!-- 定义带贴图的3D平面 -->
<ModelUIElement3D MouseLeftButtonDown="ModelUIElement3D_MouseLeftButtonDown">
<ModelUIElement3D.Model>
<GeometryModel3D>
<GeometryModel3D.Material>
<MaterialGroup>
<DiffuseMaterial>
<DiffuseMaterial.Brush>
<ImageBrush ImageSource="Arrow.png"/>
</DiffuseMaterial.Brush>
</DiffuseMaterial>
</MaterialGroup>
</GeometryModel3D.Material>
<GeometryModel3D.Geometry>
<MeshGeometry3D
Positions="0,0,0 3,0,0 3,2,0 0,2,0"
TriangleIndices="0,2,3 0,1,2"
TextureCoordinates="1,1 1,0 0,0 0,1"/>
</GeometryModel3D.Geometry>
</GeometryModel3D>
</ModelUIElement3D.Model>
</ModelUIElement3D>
5、在3D场景中嵌入2D控件
使用 Viewport2DVisual3D 在3D空间中嵌入按钮等2D控件:
<Viewport2DVisual3D>
<Viewport2DVisual3D.Geometry>
<MeshGeometry3D
Positions="0,0,1 3,0,1 3,2,1 0,2,1"
TriangleIndices="0,2,3 0,1,2"
TextureCoordinates="0,1 1,1 1,0 0,0"/>
</Viewport2DVisual3D.Geometry>
<Viewport2DVisual3D.Material>
<DiffuseMaterial Viewport2DVisual3D.IsVisualHostMaterial="True"/>
</Viewport2DVisual3D.Material>
<Border>
<Button Content="Hello" Click="Button_Click"/>
</Border>
</Viewport2DVisual3D>
6、交互事件处理
通过事件绑定实现点击交互:
private void ModelUIElement3D_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
// 处理3D对象的鼠标点击事件
}
private void Button_Click(object sender, RoutedEventArgs e)
{
// 处理2D按钮的点击事件
}
完整代码
<Grid>
<!--ShowViewCube="True" 属性用于关闭旋转控制3D互动的图标-->
<!--ViewCubeWidth="200" 设置旋转图标的宽度-->
<!--ViewCubeHeight="200" 设置旋转图标的高度-->
<!--ViewCubeHorizontalPosition="Left" 设置旋转图标的水平位置-->
<!--ViewCubeVerticalPosition="Top" 设置垂直图标的位置-->
<!--ViewCubeFrontText="前" 设置旋转图标前文本-->
<!--ViewCubeTopText="上" 设置旋转图标上文本-->
<!--ShowCoordinateSystem="True" 设置显示坐标轴-->
<!--CoordinateSystemLabelForeground="#5000" 设置坐标系统的字体颜色-->
<!--CoordinateSystemHorizontalPosition="Center" 设置坐标系的水平位置-->
<!--CoordinateSystemVerticalPosition="Center" 设置坐标系的垂直位置-->
<h:HelixViewport3D ShowViewCube="True"
ViewCubeWidth="100"
ViewCubeHeight="100"
ViewCubeHorizontalPosition="Right"
ViewCubeVerticalPosition="Bottom"
ViewCubeFrontText="前"
ViewCubeTopText="上"
ViewCubeBackText="后"
ViewCubeLeftText="左"
ViewCubeRightText="右"
ViewCubeBottomText="下"
ShowCoordinateSystem="True"
CoordinateSystemLabelForeground="#5000"
CoordinateSystemHorizontalPosition="Left"
CoordinateSystemVerticalPosition="Bottom" Margin="-10,0,10,0"
>
<!--相机-->
<h:HelixViewport3D.Camera>
<!-- PerspectiveCamera标签-透视相机(近比例长远比例小,符合我们正常观察事物的视觉-常用)-->
<!--Position="100,100,100" 设置视角x,y,z-->
<!--LookDirection="-2,-2,-2" 设置相机的观看视角-相机观察的方向-->
<!--FieldOfView="90" 调整相机焦距 设置相机与观看物体的距离,离得远观看物体区域范围大,离得近观看物体区域范围小 -->
<!--UpDirection="0,1,0" (x, y,z)设置相机视口的旋转角度,斜着拍还是正着拍 -->
<!--FarPlaneDistance="1000" 设置相机远处景色的渲染范围,如果值设置的比较小,远处景色是模糊的-->
<!--NearPlaneDistance="1" 设置相机近处的晶圆渲染范围,如果值越大,近处景色是模糊的-->
<PerspectiveCamera Position="10,10,10"
LookDirection="-2,-2,-2"
FieldOfView="50"
UpDirection="0,1,0"
FarPlaneDistance="1000"
NearPlaneDistance="1">
<!--设置相机旋转标签-->
<PerspectiveCamera.Transform>
<!--分组标签,在分组标签内可以有多个变形标签-->
<Transform3DGroup>
<!--CenterX="0" CenterY="0" CenterZ="0" 设置相机旋转中心点-->
<RotateTransform3D CenterX="3" CenterY="0" CenterZ="0">
<!--设置相机旋转方式标签-->
<RotateTransform3D.Rotation>
<!--AxisAngleRotation3D 设置相机按照轴的方式旋转标签-->
<!--Angle="45" 设置相机按照45度角旋转-->
<!--Axis="0 1 0" 设置以那个轴进行旋转 (x y z)-->
<AxisAngleRotation3D Angle="0" Axis="0 1 0" x:Name="aar"/>
</RotateTransform3D.Rotation>
</RotateTransform3D>
<!--平移标签-->
<!--OffsetX="1" OffsetY="1" OffsetZ="1" 设置 x y z 三个方向的移动距离-->
<TranslateTransform3D OffsetX="0" OffsetY="0" OffsetZ="0" x:Name="tt"/>
<!--缩放标签-->
<!--ScaleX="1" ScaleY="1" ScaleZ="1" 设置图像缩放大小 1是原始大小 小于1是相机尺寸变小,图像变大 大于1是相机尺寸变大,图像变小 -->
<!--一般很少使用相机平移调整图像放大缩小,可以使用相机视野调整图像放大与缩小-->
<ScaleTransform3D ScaleX="1" ScaleY="1" ScaleZ="1"/>
</Transform3DGroup>
</PerspectiveCamera.Transform>
</PerspectiveCamera>
<!--正交相机(远近比例都一样-很少用)-->
<!--Width="50" 相当与透视相机的视野范围属性-->
<!--<OrthographicCamera Position="100,100,100"
LookDirection="-2,-2,-2"
Width="50"
UpDirection="0,1,0"
FarPlaneDistance="1000"
NearPlaneDistance="1"/>-->
</h:HelixViewport3D.Camera>
<!--设置旋转动作靠什么来操作-->
<h:HelixViewport3D.RotateGesture>
<!--设置鼠标操作旋转动作-->
<!--MouseAction="LeftClick" 设置鼠标左键旋转-->
<MouseGesture MouseAction="LeftClick"/>
</h:HelixViewport3D.RotateGesture>
<!--设置3D图像移动操作-->
<h:HelixViewport3D.PanGesture>
<!--设置鼠标右键移动3D图像-->
<MouseGesture MouseAction="RightClick"/>
</h:HelixViewport3D.PanGesture>
<!--第二步在3D世界设置光源进来,没有光源全是黑的呀-->
<!--光源标签-设置光源的相关属性-->
<ModelVisual3D>
<!--光源内容标签-->
<ModelVisual3D.Content>
<!--多个光源可以组合使用-会出现不同的效果-->
<Model3DGroup>
<!--环境光标签 -->
<!--Color="White"-设置环境光颜色 -->
<AmbientLight Color="White"/>
<!--平行光-设置某一个方向上照射的光-平行光不发散 -->
<!--Direction="-1,-1,-1" (x,y,z)三个方向照射的光 设置平行光的照射方向-->
<!--<DirectionalLight Color="White" Direction="-1,-1,-1"/>-->
<!--点光源-点光源是向四面八方发散的光源 -->
<!--Position="100,100,100" (x,y,z) 设置光源点-->
<!--Range="200" 设置光源的照射范围-->
<!--<PointLight Color="White" Position="100,100,100" Range="200"/>-->
<!--射灯光源(聚光灯,手电筒)-某一个方向去发射光源-相当于手电筒有一个中心的光柱(比较亮的)以及两遍发散的光源(相对较暗) -->
<!--InnerConeAngle="100" 设置中心范围光柱的角度-->
<!--OuterConeAngle="40" 设置两遍光源的范围角度-->
<!--Position="50,50,50" 设置光源的中心位置-->
<!--Direction="-1,-1,-1" (x,y,z)三个方向照射的光 设置光源的照射方向-->
<!--<SpotLight Color="Orange" InnerConeAngle="100"
OuterConeAngle="40"
Position="50,50,50"
Direction="-1,-1,-1"/>-->
</Model3DGroup>
</ModelVisual3D.Content>
</ModelVisual3D>
<!--动态库提供的光源-比较全-建议使用这个-当然自己写也可以 -->
<!--<h:DefaultLights/>-->
<!--3D图形的第一个面 可以把所有的面放在一起写-->
<!--3DUIElement标签-固定写法-->
<!--MouseLeftButtonDown 鼠标左键点击事件-->
<ModelUIElement3D MouseLeftButtonDown="ModelUIElement3D_MouseLeftButtonDown">
<ModelUIElement3D.Model>
<!--GeometryModel3D网格标签-->
<GeometryModel3D>
<!--第三步物体需要呈现出来需要材质-->
<!--3D的材质 标签-->
<GeometryModel3D.Material>
<MaterialGroup>
<!--漫反射的一种材质 材质是与网格属性标签组合在一起使用的-->
<!--DiffuseMaterial 慢反射材质标签-->
<!--Brush 设置材质颜色或图片-->
<!--<DiffuseMaterial Brush="Orange"/>-->
<!--3D面设置背景图-需要在网格标签中设置TextureCoordinates="0,1 0,0 1,0 1,1"属性,背景图显示方向,才能显示出背景图 -->
<DiffuseMaterial>
<DiffuseMaterial.Brush>
<ImageBrush ImageSource="Arrow.png"/>
</DiffuseMaterial.Brush>
</DiffuseMaterial>
<!--自发光-->
<!--<EmissiveMaterial Brush="Red"/>-->
<!--<SpecularMaterial Brush="Blue"/>-->
</MaterialGroup>
</GeometryModel3D.Material>
<!--BackMaterial 异面材质标签-->
<GeometryModel3D.BackMaterial>
<DiffuseMaterial Brush="Green"/>
</GeometryModel3D.BackMaterial>
<!--网格标签-->
<GeometryModel3D.Geometry>
<!-- MeshGeometry3D呈现3D图形的标签 Positions="0,0,0(x,y,z) 3,0,0 3,2,0 0,2,0" 一个面的4个点-->
<!--TriangleIndices ="0,2,3(第一组-这里的坐标点需要逆时针顺序) 0,1,2(第二组)" 设置Positions的3个点组成一个三角行 -->
<!--这里如果呈现的是三角行而不是四边行的画,是因为TriangleIndices="0,2,3 0,1,2"的画点顺序需要逆时针顺序-->
<!--TextureCoordinates 设置平面对象与3D对象的映射关系-用来解决平面设置背景图显示问题-如果不设置这个属性平面设置的背景图不显示-->
<MeshGeometry3D Positions="0,0,0 3,0,0 3,2,0 0,2,0"
TriangleIndices="0,2,3 0,1,2"
TextureCoordinates="1,1 1,0 0,0 0,1"/>
<!--箭头向下-->
<!--TextureCoordinates="1,1 0,1 0,0 1,0"/> 箭头向左-->
<!--TextureCoordinates="0,1 1,1 1,0 0,0"/> 箭头向右-->
<!--TextureCoordinates="0,1 0,0 1,0 1,1"/>-->
<!-- 箭头向上-->
</GeometryModel3D.Geometry>
</GeometryModel3D>
</ModelUIElement3D.Model>
</ModelUIElement3D>
<!--Viewport2DVisual3D 平面对象加载标签用于在3D对象中呈现2D控件-->
<Viewport2DVisual3D>
<!--网格标签-->
<Viewport2DVisual3D.Geometry>
<!-- MeshGeometry3D呈现3D图形的标签 Positions="0,0,0(x,y,z) 3,0,0 3,2,0 0,2,0" 一个面的4个点-->
<!--TriangleIndices ="0,2,3(第一组-这里的坐标点需要逆时针顺序) 0,1,2(第二组)" 设置Positions的3个点组成一个三角行 -->
<!--这里如果呈现的是三角行而不是四边行的画,是因为TriangleIndices="0,2,3 0,1,2"的画点顺序需要逆时针顺序-->
<!--TextureCoordinates 设置平面对象与3D对象的映射关系-用来解决平面设置背景图显示问题-如果不设置这个属性平面设置的背景图不显示-->
<MeshGeometry3D Positions="0,0,1 3,0,1 3,2,1 0,2,1"
TriangleIndices="0,2,3 0,1,2"
TextureCoordinates="0,1 1,1 1,0 0,0"/>
</Viewport2DVisual3D.Geometry>
<!--Material设置3D的材质 标签-->
<Viewport2DVisual3D.Material>
<!--IsVisualHostMaterial 属性是将DiffuseMaterial材质设置成2D平面的盒子 - 用于解决将Button按钮显示出来 -->
<DiffuseMaterial Viewport2DVisual3D.IsVisualHostMaterial="True"/>
</Viewport2DVisual3D.Material>
<Border>
<Button Content="Hello" Click="Button_Click"/>
</Border>
</Viewport2DVisual3D>
<!--3D图形的第二个面 可以把所有的面放在一起写 这里没有放在一起写是因为可以给每个面设置不同的颜色-->
<!--3DUIElement标签-固定写法-->
<ModelUIElement3D>
<ModelUIElement3D.Model>
<!--GeometryModel3D网格标签-->
<GeometryModel3D>
<!--第三步物体需要呈现出来需要材质-->
<!--3D的材质 标签-->
<GeometryModel3D.Material>
<MaterialGroup>
<!--漫反射的一种材质 材质是与网格属性标签组合在一起使用的-->
<!--DiffuseMaterial 慢反射材质标签-->
<!--Brush 设置材质颜色或图片-->
<DiffuseMaterial Brush="Red"/>
<!--<DiffuseMaterial>
<DiffuseMaterial.Brush>
<ImageBrush ImageSource="Arrow.png"/>
</DiffuseMaterial.Brush>
</DiffuseMaterial>-->
<!--自发光 标签-用于设置在没有光源的情况下可以看见自发光颜色-在有光源的情况下自发光颜色会影响到材质颜色的显示 -->
<!--<EmissiveMaterial Brush="Green"/>-->
<!--全反射标签 目前只是了解一下-->
<!--<SpecularMaterial Brush="Blue"/>-->
</MaterialGroup>
</GeometryModel3D.Material>
<!--BackMaterial 异面材质标签-->
<GeometryModel3D.BackMaterial>
<DiffuseMaterial Brush="Blue"/>
</GeometryModel3D.BackMaterial>
<!--网格标签-->
<GeometryModel3D.Geometry>
<!-- 呈现3D图形的标签 Positions="0,0,0(x,y,z) 3,0,0 3,2,0 0,2,0" 一个面的4个点-->
<!--TriangleIndices ="0,2,3(第一组-这里的坐标点需要逆时针顺序) 0,1,2(第二组)" 设置Positions的3个点组成一个三角行 -->
<!--这里如果呈现的是三角行而不是四边行的画,是因为TriangleIndices="0,2,3 0,1,2"的画点顺序需要逆时针顺序-->
<MeshGeometry3D Positions="3,2,1 3,2,0 3,0,0 3,0,1"
TriangleIndices="0,3,1 1,3,2"/>
</GeometryModel3D.Geometry>
</GeometryModel3D>
</ModelUIElement3D.Model>
</ModelUIElement3D>
</h:HelixViewport3D>
</Grid>
适用场景
工业设计软件中的3D模型展示
教育领域的3D交互教学工具
游戏开发中的简单3D场景构建
项目源码
GitHub :github.com/helix-toolk…
总结
功能全面:支持3D视图、光源、材质、动画等核心功能。
开源免费:MIT 许可证允许商业项目自由使用。
跨平台:支持 WPF、UWP 及 .NET Core。
易用性:提供默认光源、ViewCube 等开箱即用组件。
最后
如果你觉得这篇文章对你有帮助,不妨点个赞支持一下!你的支持是我继续分享知识的动力。如果有任何疑问或需要进一步的帮助,欢迎随时留言。
也可以加入微信公众号 [DotNet技术匠] 社区,与其他热爱技术的同行一起交流心得,共同成长!
优秀是一种习惯,欢迎大家留言学习!
作者:我家有个小鸡仔
出处:cnblogs.com/wjygxjz/p/17766612.html
声明:网络内容,仅供学习,尊重版权,侵权速删,歉意致谢!