[WPF VTK]三维图形开发基础(一)

前言:

本人在这方面也是了解皮毛,因此里面一些内容可能存在错误;

自己的代码风格不佳,效率不好,如有看不下去的还请见谅。

0.他山之石

学习过程中借鉴下载了很多资源先公布一些(附下载地址):

三维相关一章

http://pan.baidu.com/share/link?shareid=233384&uk=3859191502

共享的所有资源文件夹

(里面有很多电子书籍,说实在的算是盗版,作为IT民工本人盗版狂人版权意识太差,不做推荐,看不下去的请提示我删除,谢谢,对原作者们说声sorry)

(为什么有这么两个链接呢,因为算是初次在这里使用共享,因此将文件上传到了百度yun,一开始也只想到了一个个文件的共享后来发觉可以共享文件夹,然后!没得说啊)

(里面有一个“WPF 3D实例安装程序”强烈推荐安装,安装后里面有许多WPF3D实例可以学习参考,很实用效果可以安装后用浏览器打开!)

http://pan.baidu.com/share/link?shareid=233388&uk=3859191502

1.天地之初

由于程序中需要用到针对序列图像轮廓点进行三维重建,因此学习了一些三维开发的基本概念。

在说了解的图像开发库中,Direct3D、OpenGL是比较成熟、功能强大的,不过相对来说其也拥有一定开发复杂度,

鉴于实验室师兄有用WPF进行过一个三维展示的实验,而本人当时感觉自己说需要的三维功能也是很基础的三维显示功能,

同时WPF三维制作具有这一能力,是基于D3D的封装(D3D本就是微软技术),在此基础上进行了一些简化,因此相对来说

学习、使用的速度较快,于是选择了WPF(当然后来改用VTK,此乃后话)。

WPF中3D绘图可以使用XAML也可以在CS页面中定义或者使用混合设置的方法。

对于XAML方法,网上的例子大多是这种模式,也就是单一的一个xaml页面生成了说要显示的模型、动画等。但这需要事先就把所有该设置的值都求取出来。

如果用CS方式就跟定义变量一样,先定义个变量,再用算法生成值再赋值给她之类。

WPF3D基本要素有(其他三维开发库要素应该也是一致的):

Geometry-Geometry定义了在屏幕中所要显示的物体及其位置。

Camera-就跟人类视野一样,camera决定了你观察物体的位置以及角度。

Lighting-关上灯神马都一样,光明的影响不用多解释。但Light的类型、位置、颜色等在不同的场景下会有迥异的效果。

Materials-物体外观通常由灯光以及物体本身材质Materials说决定,比如说物体本身是白色的,用红色光照射or物体本身是红色的,用白色光照射之类。

2.管中窥豹

对于上面所述基本要素,其中Camera、Lighting、Materials算是便于理解,因为与现实世界互通,相似较大。所以择其重点介绍一番:

Camera属性有三要:

Position-Gives the camera's coordinates in 3D space.

LookDirection-Gives the direction in which the camera should be pointed relative to its current position.也就是说,基于相机本身所处的position

以及相机说看的位置,指示出其镜头的方向。举例说来:camera的位置是“1,1,1”而LookDirection是“1,2,3”,那么相机所pointed at 的位置就是

“1+1,1 + 2,1+ 3”=“2,3,4” 

在这里请注意一点:LookDirection、Pointed At Point也就是看的方向以及看的位置。因此如果你看的位置无法观察到你说要展示的物体,那么即使你朝着正确的方向你也无法在屏幕中显示出物体来,而Pointed At Point=Position+LookDirection。所以如果你要观察放置在“0,0,0”上的物体,而相机在“1,1,1”那么lookDirection该如何设置呢?是一个减法吧!

UpDirection-比如说对于屏幕你希望设置成Z轴在上那么可以是UpDirection=(0,0,1),也就是正对屏幕的平面是ZX或ZY而如果设置成(0,1,0),那么就是Y轴朝上,也就是说YX,YZ这种情况,当然还可有其他复杂一些设置,成角度之类,就自己去理解了.

比如下图是UpDirection分别设置成‘‘1 0 0’’、‘“0 1 0”、“0 0 1”

从下图看出貌似是个对称的所以我猜测对于第一个图是X轴指向屏幕上方、Y轴指向屏幕左边;

对于中间图是Y轴指向屏幕上方,X轴指向屏幕右边,因此显示就如此了。

(注意这里只显示出了2个图,第三个不是没上传而是空白!也就是说作为一个xy平面上物体,在ZX\ZY面上就看不出来了)

注意我这里虽然都是设置成“0 1 0” “1 0 0 ” “0 0 1”之类,但并不代表就不可以有其他值比如“1 1 1” “1 5 1” “15 5 1”

FieldOfView-观察的角度,嗯这该如何解释呢,比如说你设置成90或者30度代表你说关注的范围一个大一个小,那么物体所显示的大小或者多少就体现出来了.

下图左右两边其他参数一样,只有FiledOfView左边是90;右边是60

<Viewport3D.Camera><PerspectiveCamera Position="0 0 4" LookDirection="0 0 -1" UpDirection="0 1 0" FieldOfView="90" /></Viewport3D.Camera>

<Viewport3D.Camera><PerspectiveCamera Position="0 0 4" LookDirection="0 0 -1" UpDirection="0 1 0" FieldOfView="60" /></Viewport3D.Camera>

对于Lighting请看下图并对照日常生活中的光源加以区别

Materials请参考

http://www.silverlightchina.net/html/study/WPF/2012/0301/14172_2.html

http://www.cnblogs.com/Clingingboy/archive/2010/12/23/1914745.html
下面是一个完整代码示例,可以进行参数修改以查看对应效果:

<Window
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" x:Class="_3DUI.MainWindow"
        Title="MainWindow" Height="500" Width="500">
    <Grid>
      <Viewport3D x:Name="Rectangle">
            <ModelVisual3D>
                <ModelVisual3D.Content>
                    <Model3DGroup>
                        <GeometryModel3D>
                            <GeometryModel3D.Geometry>
                                <!--Positions="0 1 -4, 0 0 -4, 0 1 0, 0 0 0"-->
                                <!-- Rectangle. -->
                                <MeshGeometry3D
                                    Positions="0 0 0, 2 0 0, 0 2 0, 2 2 0"
                                    TriangleIndices=" 0 1 2" />
                            </GeometryModel3D.Geometry>
    
                            <GeometryModel3D.Material>
                                <DiffuseMaterial Brush="Cyan" />
                            </GeometryModel3D.Material>
    
                            <GeometryModel3D.BackMaterial>
                                <DiffuseMaterial Brush="Red" />
                            </GeometryModel3D.BackMaterial>
                        </GeometryModel3D>
                        <GeometryModel3D>
                            <GeometryModel3D.Geometry>
                                <!--Positions="0 1 -4, 0 0 -4, 0 1 0, 0 0 0"-->
                                <!-- Rectangle. -->
                                <MeshGeometry3D
                                    Positions="-2 -2 -2, 0 -2 -2, -2 0 -2, 0 0 -2"
                                    TriangleIndices=" 0 1 2" />
                            </GeometryModel3D.Geometry>

                            <GeometryModel3D.Material>
                                <DiffuseMaterial Brush="Cyan" />
                            </GeometryModel3D.Material>

                            <GeometryModel3D.BackMaterial>
                                <DiffuseMaterial Brush="Red" />
                            </GeometryModel3D.BackMaterial>
                        </GeometryModel3D>
                        <!-- Light source. -->
                        <AmbientLight Color="White" />

                    </Model3DGroup>
                    
                </ModelVisual3D.Content>
            </ModelVisual3D>

            <!-- Camera. -->
            <!--Position="-1 0.5 4"
            LookDirection="0 0 -1"-->
            <Viewport3D.Camera>
                <PerspectiveCamera Position="0 0 4"
                                   LookDirection="0 0 -1"
                                   UpDirection="0 1 0"
                                   FieldOfView="60" />
            </Viewport3D.Camera>
        </Viewport3D>
    </Grid>
</Window>
原文地址:https://www.cnblogs.com/dawnWind/p/3D_01.html