WPF中3D控件的使用
wpf使用了Directx,所有才能够进行3D编程。
比较方便的是,3D模型也是声明式的,就像普通控件一样。
由于3D控件也是声明式的,所以还可以利用binding
改变其属性
控件
- Viewport3D
这是一个3D视口,所有的3D控件都要放在这里面。
3D空间的基本元素是 相机、 光源、 对象。
<!--空间-->
<Viewport3D>
<!--相机-->
<Viewport3D.Camera>
<PerspectiveCamera Position="1,0,10" LookDirection="-1,0,-10" UpDirection="0,0,1" FieldOfView="90" />
</Viewport3D.Camera>
<!--光源-->
<ModelVisual3D>
<ModelVisual3D.Content>
<AmbientLight Color="White"/>
</ModelVisual3D.Content>
</ModelVisual3D>
<!--可视对象-->
<ModelVisual3D>
<ModelVisual3D.Content>
<!--几何对象-->
<GeometryModel3D>
<!--对象网格-->
<GeometryModel3D.Geometry>
<MeshGeometry3D Positions="0,0,0 0,1,0 1,1,0 1,0,0" TriangleIndices="1,3,0 2,3,1"/>
</GeometryModel3D.Geometry>
<!--对象材质-->
<GeometryModel3D.Material>
<DiffuseMaterial Brush="Blue"/>
</GeometryModel3D.Material>
<GeometryModel3D.BackMaterial>
<DiffuseMaterial Brush="Black"/>
</GeometryModel3D.BackMaterial>
</GeometryModel3D>
</ModelVisual3D.Content>
</ModelVisual3D>
</Viewport3D>
-
PerspectiveCamera
透视相机,这是最常用的相机。主要属性是- Position 位置
- LookDirection 朝向点
- UpDirection 垂直方向
- FieldOfView 视场角
- 远近裁剪面
-
ModelVisual3D
可视对象- GeometryModel3D
代表一个几何对象,比如矩形、正方体、球体- MeshGeometry3D
几何体的网格由 点云 和使用点的索引声明的 三角形 构成,三角形的正面由右手定则确定 - Material
材质,一般有漫反射材质、镜面反射、自发光。还可以自己写shader导入为材质
- MeshGeometry3D
- GeometryModel3D
-
Model3DGroup
可以将多个可视对象当作子对象,整体上表现为一个对象
变换
ModelVisual3D
可以进行3D变换,比如平移、旋转、缩放、仿射。通过ModelVisual3D.Transform
为其定义
纹理,在3D空间显示2D控件
2D控件比如Button
以纹理的方式映射到几何体网格上
对于平面的纹理坐标
纹理坐标的起点是左上角
映射的方式是把原图片压缩成11的图片
然后用一个小于11的纹理坐标系在这个这个图片上移动,截取图片
至于非平面的正方体的纹理映射则更复杂
比如墨卡托投影出来的地球地图,要贴在一个球体上。我们得计算出球体上每个顶点通过这种方式投影在圆柱体侧面上的顶点坐标,然后把侧面展开为一个矩形,在压缩成1*1的正方形,刚好和纹理贴图对应上。
- Viewport2DVisual3D
这个3D控件是2D控件的容器,其子元素是Button
等2D控件
为这个控件设置材质、变换、网格,然后通过纹理的形式把2D控件画这个控件上
<Viewport2DVisual3D>
<Viewport2DVisual3D.Material>
<DiffuseMaterial Viewport2DVisual3D.IsVisualHostMaterial="True"/>
</Viewport2DVisual3D.Material>
<Viewport2DVisual3D.Geometry>
<MeshGeometry3D Positions="1,0,0 1,0,1 1,1,1 1,1,0" TriangleIndices="0,3,1 1,3,2"
TextureCoordinates="0,1 0,0 1,0 1,1"/>
</Viewport2DVisual3D.Geometry>
<StackPanel Orientation="Horizontal" Background="#eeeeee">
<Button Content="+" Margin="8"/>
<Button Content="门" Margin="0,2,0,0"/>
<Button Content="+" Margin="8"/>
</StackPanel>
</Viewport2DVisual3D>
控制对象生成位置
这个和角动量计算差不多,用叉乘来做。法向量和控制向量叉乘获得一个垂直于两个向量平面所在的向量,其大小随控制向量模长变化而变换。
场景漫游
为了方便鼠标控制相机在场景中移动,
可以通过变换+事件来控制,但不如直接用现成的包。HelixToolkit