学习 WPF 一个多月了,感觉很强大.确切说是 XAML 更强大,简单的 标记语言 让一切变得 可能 既 简单。那现在学到 WPF 的 3D 制作了,虽然没有 XNA 的专业但也能让我小兴奋一把,满足一些需求。比如我做的这个比较实用的小工具 CLOCK 有兴趣的可以下载:http://download.youkuaiyun.com/source/3006343
那下面 开始记录我的 学习笔记。
现在所说的三维处理其实就是在二维的空间上做三维模型,通过一些光和透视效果,产生的立体感。如果有兴趣,推荐部电影:记忆裂痕。里面有真正的 3D 效果(题外话)。
那要想做出三维效果,我们就必须满足几个条件:
1.我们需要一个容器 场景,也就是 Viewport3D 来放置我们后面做的 模型。MSDN 说到:Viewport3D 充当三维场景中的一个窗口(视区)。更准确地说,它是三维场景所投影到的图面。
2. 有了场景,我们就需要一个 照相机 通常用的就是:PerspectiveCamera 。那这个类有个依赖属性:FieldOfViewProperty。它是用来设置照相机的水平视角。还有两个,一个是:FarPlaneDistance 和 NearPlaneDistance。这两个是来限制 照相机的投影范围。根据字面意思呢,一个是限制距离照相机的最远距离,另一个就是限制距离照相机的 最小距离了。如果超出了范围则不再显示。最后要说一说 Position 和 LookDirection。Position它是用来表示照相机的位置 可以通过 Point3DAnimation 这个动画 对它的坐标 进行 动画处理。那 LookDirection 就是设置照相机的拍摄位置。
3.有了以上这些呢,我们需要补充一些 三维 坐标的知识概念。通常做二维界面的时候, 比如WinForm ,我们都是以屏幕的 左上角 为原点,向右是 X轴 递增,向下是 Y 轴 递增 ,反之则递减。而在三维坐标里原点是在图形区域的中心,依然向右是 X轴 递增,Y轴 递增是向上,Z轴是指向屏幕外部,也就是指向观察者,来张图片就很容易理解了,。
4.下面就是要开始 制作 模型了 要用到 < ModelVisual3D > < ModelVisual3D.Content>
<Model3DGroup> 这几个标签 。根据字面意思很容易理解,就不多讲了。讲讲这里面包含的一大堆东西吧。
要有光 于是有了光:DirectionalLight。这个类有个依赖属性 Direction 那它是用来显示光效果的向量 ,向量么,大家都知道 是有方向的量···,那它的限制是 不能为零默认值是:(0,0,-1)。还有一个属性 Color 用来设置 光线 颜色的。
下面要用到GeometryModel3D,几何模型。它是有什么组成的呢,通常它是由创建三维模型的三角形基元(MeshGeometry3D)和 绘制在上面的 纹理(Material)组成。那来讲讲这两个东西。
所谓三角形基元,也就是 MeshGeometry3D 它包含 4个常用依赖属性 .::Normals,<font color="#000066" face=""">Positions,TextureCoordinates,TriangleIndices,最复杂的也就是这几个了,每次看到这么一大坨东西,心里就发颤。第一个表示法向量的集合,第二个表示顶点位置的集合,第三个表示纹理坐标的集合,最后一个表示三角形索引集合。
要说一下的是 在三维空间里通常图形的组成都是由一个一个 小三角形 拼凑成的,这些小三角形 也就是基元,为什么用三角形呢 因为它的三个 顶点 都在一个平面上,那么如何判断它的正反面呢 WPF 采用 右手笛卡尔定律,拇指 指向的方向就是 正面。
通过 Position 来 指定每个三角形的顶点,TriangleIndices 来表示这些三角形的索引的集合。
OK,框架搭好后,要向上面绘制纹理了,Material。要用到 DiffuseMaterial。你可以用 <MaterialGroup> 来绘制更复杂的纹理。DiffuseMaterial 这个类包含一个 Brush 和 Color。Color 用来获取或设置从 Material 发出的颜色。而 Brush 用来绘制。因为是 Brush 所以大部分 Brush 都可以,比如:VisualBrush ,ImageBrush。
几何模型呢,除了正面的 纹理 还有一个 BackMaterial 也就是 背面的 纹理设置,和Material 差不多,就不多讲了。
好了,三维的创建呢 大致 就是这个样子了 剩下的 就是些 Transform 或者Triggers的设置了。就先记录到这里了,来个小例子 先看看效果:
<Viewport3D RenderTransformOrigin="0.5,0.5" Margin="5,0,0,6">
<Viewport3D.Camera>
<PerspectiveCamera Position="-40,40,40" LookDirection="40,-40,-40 "
UpDirection="0,0,1" x:Name="MyCamera"/>
</Viewport3D.Camera>
<ModelVisual3D>
<ModelVisual3D.Content>
<Model3DGroup>
<DirectionalLight Color="White" Direction="-1,-1,-3" />
<GeometryModel3D>
<GeometryModel3D.Geometry>
<MeshGeometry3D Positions="0,0,0 10,0,0 10,10,0 0,10,0 0,0,10
10,0,10 10,10,10 0,10,10"
TriangleIndices="0 1 3 1 2 3 0 4 3 4 7 3 4 6 7 4 5 6
0 4 1 1 4 5 1 2 6 6 5 1 2 3 7 7 6 2"/>
</GeometryModel3D.Geometry>
<GeometryModel3D.Material>
<DiffuseMaterial Brush="Red"/>
</GeometryModel3D.Material>
<GeometryModel3D.Transform>
<RotateTransform3D>
<RotateTransform3D.Rotation >
<AxisAngleRotation3D Axis="3,3,3" Angle="0" x:Name="rotate" />
</RotateTransform3D.Rotation>
</RotateTransform3D>
</GeometryModel3D.Transform>
</GeometryModel3D>
</Model3DGroup>
</ModelVisual3D.Content>
</ModelVisual3D>
<Viewport3D.Triggers>
<EventTrigger RoutedEvent="Viewport3D.MouseEnter">
<BeginStoryboard>
<Storyboard>
<Point3DAnimation Storyboard.TargetName="MyCamera" Storyboard.TargetProperty="Position" To="-40,60,40" Duration="0:0:2" AutoReverse="True" BeginTime="0:0:0.05" DecelerationRatio="0.3"/>
<DoubleAnimation Storyboard.TargetName="rotate" Storyboard.TargetProperty="Angle" To="360" Duration="0:0:2" AutoReverse="True" AccelerationRatio="0.3" DecelerationRatio="0.3"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Viewport3D.Triggers>
</Viewport3D>
把这一坨 扔到 XAMLPad 里 就能看到了。你会发现 你的眼睛被欺骗了 你看到了么。
以上 为本人愚见。