zoukankan      html  css  js  c++  java
  • 【WPF】用三角形网格构建三维图形

    虽然WPF只能支持部分三维模型,不过从应用功能开发的角度看,也已经够用了(非游戏开发)。WPF 的三维图形,说得简单一点,也就两种而已。

    1、把二维对象放到三维空间中,这个应该较为好办,像 Image 控件,Shape 类型等,或者我们常用的一些控件,都可以放进三维空间中,用这种方式构建模型可能更为实用,也好弄(至少不借助专门的建模工具的前提下)。

    2、完全利用坐标建模。实际上是用 N 个三角形来组合成三维模型。

    虽然你会看到基类型 Visual3D 派生出了好几个类型,但总体上说也就划分为上述两类。Viewport2DVisual3D 类就是专门把二维对象放入三维空间中的,而 ModelVisual3D 和 UIElement3D 差不多,不同的是,UIElement3D 可以捕捉用户输入行为,如鼠标键盘触控等,如果你的三维模型要与用户交互,那么你可以选用这个类。

    本文老周重点介绍第二种建模方法,就是用三角形来组建。为啥要用三角形呢?我们以前都学过几何,你想想,要多少个点才能确定一个面?是三个吧。两个点只能确定一条线,一个点就算了,那是无限射线。正是如此,所以三维图形中的所谓面,至少得要三个点才能确定下来,所以,要使用三角形来作为图形基元。

    在介绍三角形坐标设置之前,老周先用废话来各大伙补充一点东东。

    在WPF中承载三维模型是这样的:首先,你应该声明一个 Viewport3D 对象,它包含我们要建立的模型,前些天,老周写过一篇文章,介绍过三维型中的照相机,就是 Viewport3D 的 Camera 属性,你必须设置一个照相机,这样才能看到三维模型中的东西,它好比我们透过实体相机的取景器来观察客观事物,具体可以点这里查看。

    之后呢,Viewport3D会包含一个子元素集合,每个元素必须是 Visual3D 的子类,由于是集合,你可以在其中添加 N 个。

    用坐标来构建模型,应当用 ModelVisual3D 类,这个类很好玩,它自身又公开一个集合,可以再添加 ModelVisual3D 对象。也就是说,ModelVisual3D 对象是可以像树形结构一样嵌套,这样做可以方便你建立复杂的三维图形,并且可以有效分组。很多人会觉得,WPF 的三维模型很复杂很难懂,除了三维空间本身的复杂性外,估计可能是因为这种可视化元素之间的可嵌套性,刚开始接触时容易头晕。不过不用害怕,这世界上没有谁天生就会的,不要急,学习的时候,不要建太复杂的模型,这样思路也容易适应,只要你熟悉了就很轻松了,再复杂的东西,也是由各种简单的元素构成的。

    ModelVisual3D 类有个Content属性,这个才是真正用来设置模型坐标的,它的类型是Model3D,它是个抽象类,它的派生类有两大块:一是GeometryModel3D,用来定义构成三维图形的坐标点;再者就是Light,表示用于照亮三维模型的灯光,因为三维图形是模拟现实中的事物的,所以会考虑到灯光照射的问题,它的实现类型有比如环境光(AmbientLight),这个像我们房间里的大灯,它可以照亮屋内所有角落;方向光(DirectionalLight),像手电筒的光吧,具有照射方向……

    在GeometryModel3D类,也公开了三个属性:

    Geometry:设置三维图形的坐标点集合,不仅只有点,还有索引、法向量、纹理映射等。

    Material:图形正面的材质,就像金属表面,反射镜面类似的效果。

    BackMaterial:有正面就会有背面,这是指图形背面的材质。

    下面就是建立模型的重点了,即 Geometry属性,WPF 框架只公开了一个实现类——MeshGeometry3D,就是使用三角形网络来建立物体的表面。其中也有三个属性比要重要。

    Positions:这个很重要,组成图形表面的各个坐标点的集合。

    TriangleIndices:这个也很重要,它是一组整数集,从0开始,就是指定哪三个点组成一个三角形。

    TextureCoordinates:纹理映射。之个有点像你把某妹子的照片贴在一块玻璃上,照片相当于纹理,经的每个点与玻璃的对应关系。比如,通常,我们会把照片的左上角的点对准玻璃左上角的点,右上角的点对准玻璃右上角的点。如果把照片左上角的点对准玻璃右下角的点,照片左上角的点对准玻璃左下角的点,这样贴出来的照片就是倒过来的。

    Normals:构成图形的各个坐标点的法向量,默认全是 0,0,1。这个东西还真不知道怎么解释,一般我们可以不指定,用默认值就可以,大概是指面与面之间的关系吧。

    咱们来看看演示吧。

                            <GeometryModel3D>
                                <GeometryModel3D.Geometry>
                                    <MeshGeometry3D Positions="-2,2,0 3,-2,2 5,3,3 7,1,-2" TriangleIndices="0,1,2,1,3,2" TextureCoordinates="0,0 1,0 1,0 1,1" Normals="0,0,1 0,0,1 0,0,1 0,0,1"/>
                                </GeometryModel3D.Geometry>
                                <GeometryModel3D.Material>
                                    <DiffuseMaterial>
                                        <DiffuseMaterial.Brush>
                                            ……
                                        </DiffuseMaterial.Brush>
                                    </DiffuseMaterial>
                                </GeometryModel3D.Material>
                            </GeometryModel3D>

    上面代码中,定义了四个坐标点,注意 TriangleIndices 属性的值,它有六个值,表明这四个点可以构成两个三角形。即它有两个面组成。

    0-1-2 表示第一个点,第二个点和第三个点,这三个点构成了一个三角形。就像这样。

    然后是 1-3-2,即第二个点,第四个点,第三个点又组成了一个三角型。

    大伙要注意一个法则—— 组成三角形的点,如果是按逆时针排序的(就像上面例子),表示的是物体的正面;如果是顺时针的,表示的则是物体的反面。

    再比如,咱们再写成这样,这回有五个点。

    <MeshGeometry3D Positions="0,3,0 -3,-2,0 -1,-3,1 1,-3,1 3,-2,0" TriangleIndices="0,1,2,0,2,3,0,3,4" TextureCoordinates="0,0 1,1 1,1 1,1 1,1" />

    第一个点在顶部,其余四个在下方,构成三个三角形。

    好了,由于剧组严重缺乏资金,老周今天只能说到这里了。为了弄到更多资金来写后面的文章,老周要去玩《狂野撞车》来赚现金。

  • 相关阅读:
    现代软件工程 第一章 概论 第4题——邓琨
    现代软件工程 第一章 概论 第9题——邓琨
    现代软件工程 第一章 概论 第7题——张星星
    现代软件工程 第一章 概论 第5题——韩婧
    hdu 5821 Ball 贪心(多校)
    hdu 1074 Doing Homework 状压dp
    hdu 1074 Doing Homework 状压dp
    hdu 1069 Monkey and Banana LIS变形
    最长上升子序列的初步学习
    hdu 1024 Max Sum Plus Plus(m段最大子列和)
  • 原文地址:https://www.cnblogs.com/tcjiaan/p/6958518.html
Copyright © 2011-2022 走看看