• 【WPF】三维模型中的“照相机”


    WPF 部分支持三维模型,为啥说是部分支持?毕竟 WPF 的侧重点还是在应用开发上,虽然也有些游戏是用 WPF 开发的,不过,老周想啊,如果真要开发游戏,最好用专门的框架,WPF 应当用于开发应用功能的。不过,动画、三维建模这些支持可以作为辅助,尤其是在 UI 上,适当地,可以增强一下。当然,不要为了装逼,弄得不伦不类的,那样就是主次不分了,现在有不少软件就是主次不分的。

    在 WPF 中,要呈现三维模型,需要用到 Viewport3D ,它是三维对象的总容器,所有三维对象都应该放在这个容器中。本文老周不介绍三维对象的树结构,而是重点说说 Viewport3D 的一个重要配件——照相机。

    其实,这个“照相机”,与我们现实世界中的照相机差不多,它是我们观察三维模型的一个入口,就好比我们从真实相机中的取景器去观察被摄对象一样,由于相机的视角广度有限(哪怕是广角镜头也是有限的),现实的被摄物体可以无限延展,但是,你在取景器中看到的只能是局部。道理也是一样的,在 WPF 的三维模型中,Camara 只是设定我们能看到三维对象的局部,而维对象本身也可能是无限延展的。

    Viewport3D 对象有个 Camera 属性,用来设置一个合适的相机实例。照相机可以分为两大类:

    第一类,MatrixCamera,它通过一个矩阵来描述照相机的参数,这个估计用得不多,因为挺复杂的,反正老周是不知道怎么用的。

    第二类,ProjectionCamera,即带投影透视效果的照相机,它派生出两款相机,注意啊,不是佳能和尼康,是 PerspectiveCamera 和 OrthographicCamera。PerspectiveCamera相机比较好解,因为它是带透视效果的,这也符合我们灵长目类动物的视觉特征——离得近的物体看起来会大一些,离得远的物体会小一些,当然了,前提是物体大小接近,不然,这太阳比月球大太多了,所以,哪怕太阳离我们更远,看起来也比月亮大。而 OrthographicCamera 呢,它不太符合咱们灵长目动物的视觉特征,因为使用这个照相机后,所视物体就变成了正交,即不存在透视效果,没有距离之别,不管远的还是近的,都一样大。人要是能做到像正交镜头这样就好了,不管亲疏都一视同仁。有时候,人真的还不如代码友好,因为有些人会算计你,但代码不会,虽然有时候,代码会耍性子,让你又爱又恨,但是,它待你是真诚的,而人呢,也许只有少部分人能做得到,社会太缺诚信。

    嗯,介绍完了几类照相机,相信大伙一定想看看效果。行,老周也想,要不,咱们试试。

    为了简单,老周只建了一个正方体,而且这个正方体是衣裳不整的,只围了一条裙子,仅仅声明了左、前、右三个面。

            <Viewport3D>
                ……
                <!-- 模型,三个面 -->
                <ModelVisual3D>
                    <ModelVisual3D>
                        <ModelVisual3D.Content>
                            <GeometryModel3D>
                                <GeometryModel3D.Geometry>
                                    <MeshGeometry3D Positions="-2,4,0 -2,0,0 -2,0,4 -2,4,4" TriangleIndices="0,1,2,0,2,3"/>
                                </GeometryModel3D.Geometry>
                                <GeometryModel3D.Material>
                                    <DiffuseMaterial Brush="Green"/>
                                </GeometryModel3D.Material>
                            </GeometryModel3D>
                        </ModelVisual3D.Content>
                    </ModelVisual3D>
                    <ModelVisual3D>
                        <ModelVisual3D.Content>
                            <GeometryModel3D>
                                <GeometryModel3D.Geometry>
                                    <MeshGeometry3D Positions="-2,4,4 -2,0,4 2,0,4 2,4,4" TriangleIndices="0,1,2,0,2,3"/>
                                </GeometryModel3D.Geometry>
                                <GeometryModel3D.Material>
                                    <DiffuseMaterial Brush="Blue"/>
                                </GeometryModel3D.Material>
                            </GeometryModel3D>
                        </ModelVisual3D.Content>
                    </ModelVisual3D>
                    <ModelVisual3D>
                        <ModelVisual3D.Content>
                            <GeometryModel3D>
                                <GeometryModel3D.Geometry>
                                    <MeshGeometry3D Positions="2,4,4 2,0,4 2,0,0 2,4,0" TriangleIndices="0,1,2,0,2,3"/>
                                </GeometryModel3D.Geometry>
                                <GeometryModel3D.Material>
                                    <DiffuseMaterial Brush="Red"/>
                                </GeometryModel3D.Material>
                            </GeometryModel3D>
                        </ModelVisual3D.Content>
                    </ModelVisual3D>
                </ModelVisual3D>
                <!-- 灯光,用来照亮模型,不然就全黑一片了 -->
                <ModelVisual3D>
                    <ModelVisual3D.Content>
                        <AmbientLight Color="Purple"  />
                    </ModelVisual3D.Content>
                </ModelVisual3D>
            </Viewport3D>

    AmbientLight 指的是环境光,即可以照亮整个模型的光,如果用 PointLight ,就是点光,类似于一个小灯泡,小蜡烛,只能照亮一点点空间。Color属性指定了这灯光是紫色的,紫光可以诱捕害虫,所以就用紫光了。

    好,重点来了,我们先看看正交照相机。

            <Viewport3D>
                <Viewport3D.Camera>
                    <OrthographicCamera Position="16,2,18" LookDirection="-1,0,-1" Width="10" />
                </Viewport3D.Camera>
               ……
            </Viewport3D>

    Position 是指定照相机的位置,注意Z轴的坐标,如果Z轴值大于模型的Z轴值,那么镜头就在物体前面,反之在物体后面。因此,你可以设置 LookDirection 来调整相机的方向,Position是相机的位置,就好比你站在某个点拍照;而LookDirection是相机看的方向,就像你拿着相机可以拍你前面的妹子,也可以拍你左边的大爷,或者拍与你成30度夹角处的大叔。LookDirection指定你朝哪儿看。

    如果相机位于物体前方,LookDirection 的Z轴值要小于0,因为Z轴的负方向是指向屏幕内部的,只有朝着负方向,才能看到物体;如果相机位于物体背面,那么Z轴的值就要大于0,就样才会朝向屏幕外部,看到物体。

    正交相机看到的正方体如下图所示。

    这是正方体的前面和侧面,但是,你都看到了,两个面一样大,按理说,正面应该要离我们近一些,但是,正交相机是不考虑这个的,在它眼中,世界都是平的。

    下面我们再换一个透视效果的相机。

            <Viewport3D>
                <Viewport3D.Camera>
                    <PerspectiveCamera Position="10,5,10" LookDirection="-2.5,-1,-2" />
                </Viewport3D.Camera>
                ……
            </Viewport3D>

    相机位于物体的左前方,并且朝着物体的右下方观察。

    此时,如下图所示,你会看到透视效果。

     也许,这个更符合我们在现实世界中的观察效果。

    好了,又是开饭时间,今天就聊到这里吧,有空,改天咱们泡上一壶龙井茶,继续聊。

  • 相关阅读:
    Java序列化的机制和原理
    范型练习
    Java范型
    Hadoop之HelloWorld
    IEnumerable和IEnumerator
    浅谈静态变量和类
    MVC中的Startup.Auth.cs、BundleConfig.cs、FilterConfig.cs和RouteConfig.cs
    "ApplicationDbContext"(泛指之类的数据库上下文模型)上下文的模型已在数据库创建后发生更改。请考虑使用 Code First 迁移更新数据库。
    C#.NET的微信功能开发学习
    本地Fiddler传递XML格式数据,调试微信功能。
  • 原文地址:https://www.cnblogs.com/tcjiaan/p/6877676.html
Copyright © 2020-2023  润新知