当前位置:网站首页 / WPF / 正文

[精品]AY拨云见日-WPF3D开发补充笔记1

时间:2015年04月17日 | 作者 : aaronyang | 分类 : WPF | 浏览: 4560次 | 评论 0

 1. WPF 3D  三角形的顶点 逆时针顺序才能呈现,怎样决定逆时针? 

    右手握拳,大拇指指向正值得方向,遵循右手定律

    WPF的坐标系是 xy正常,然后一个z轴是面向你,相机的z轴决定了 可视的元素的大和小

  

2.MeshGeometry3D的一些属性理解

 A图我们在 颜色渐变画刷 StartPoint和EndPoint就知道的坐标系,左上角是0,0坐标

 B图是我们的WPF 3d坐标系,箭头方向为正值的方向

看代码:

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

 Positions指定3维坐标点,然后使用TriangleIndices像StringFormat那样 显示出点的顺序, 这里假设你学过 数学知识的向量知识,向量有方向的. 这里遵循逆时针出点.

TextureCoordinates遵循 A图的坐标系,这里的MeshGeometry3D就是画了一个面,    是x轴和y轴组成的面, 一个三维空间 由x,y,z组成,所以根据排列组合 C(3,2)有3种可能,所有就是3个面,xy,xz,yz面,这里画好了面,然后就是指定纹理,TextureCoordinates指定纹理出点方向. xz组成的面可以理解为地平面.

到这里,有个Positions和TriangleIndices好确定,就是一个提供一组顶点,一个按逆时针组成三角形使用点

我下面有2组代码,都是创建一个正方体的一个面

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

这个代码共用一条三角形边,提供了4个顶点,在Triangleindices中创建了2个三角形,分别使用了 0 1 2和0 2 3     这里0代表 0,1,0这个顶点.    这里 0 1 2 还是 201还是120,都没关系,只要保证逆时针的一个三角形即可.我们知道一个正方形最少由2个三角形组成.这里,我Positions 第一个点是0,1,0  是y轴上的一个点,然后画到 0,0,0 然后 1,0,0    ,如下图画下2个三角形.

1.gif.

接下来填充纹理,TextureCoordinates  遵循画刷那个坐标系,左上角是0,0   y轴向下是正值,x轴右边是正值, 是百分比的,   最大值是1,代表是原长度的1倍,0.5就是中心的位置

这里真巧,这个矩形的平面的第一个点0,1,0 如果对应画刷的坐标系的0,0 ,那么 0,0,0远点就是 0,1     所以TextureCoordinates  就是0,0 0,1 1,1 1,0

好的,很多人喜欢从原点0,0,0出发画矩形,好吧,第一步,定义顶点

Positions="0,0,0 1,0,0 1,1,0 0,1,0"

很简单的,从0,0,0 然后 → ↑ ←↓ 一个矩形出来了

接下来定义三角形,第一个, 假设从 0,0,0出发,逆时针,毫无疑问第二点就2个可能,正好是2个三角形

2.gif

所以 Triangleindices就能确定下来了. 每3个点是一个整体,一个三角形   不管是0,2,3还是302还是230都可以,只要是逆时针

TriangleIndices="0 2 3  0 1 2"

接着最难的一个纹理的值,因为纹理值不对, 我们假如使用了Viewport2DVisual3D,在3维空间显示2维界面就会出现问题,甚至有时候不显示,不指定肯定不显示

这里怎样TextureCoordinates  和 Position怎样对上点呢?

画面肯定从上往下,从左往右显示,而 0,0,0如果对应  二维坐标系的0,0 那么他的下面就没有显示的了,在 xz的面下面没有任何可以显示的,所以 0,0,0对应的只能是 0,1,好了接下来简单了,逆时针,下一个点就是 1,1 然后↑ 就是1,0 然后0,0

Image 7.png

所以最终代码:

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

假如不共用面,就是6个点,现在很好理解了吧

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

假设一个二维图片显示的

Image 8.png

别把二维控件当成整体

如上 2个三角形    第一个纹理0 1, 1 0, 0 0 ,如果我更改第二个三角形的纹理绘制,从 1 0,0 1,1 1,虽然效果是切掉了,但是 控件的响应没有切掉,比如按钮,看似不是一个整体,但是鼠标移上去,还是一个整体,同时都有mouseover事件

Image 9.png

现在理解了纹理的绘制顺序的重要性了吗



3. 相机代码部分解释

<PerspectiveCamera FarPlaneDistance="50" LookDirection="0,0,-1" UpDirection="0,1,0" NearPlaneDistance="1" Position="2,2,15" FieldOfView="45" />

关于UpDirection,可以想象一下,你现在的位置是确定的,你也是往电脑的方向看的,但如果你倒立着看屏幕,你眼睛里呈现的图像就倒过来了。因此要规定一下观察者的“上方”是哪方

你站在哪里(一个三维坐标),如何站立(向上和向量),观察哪儿(lookat),此时观察到的结果是唯一的,这就是UpDirection和LookDirection

其中FarPlaneDistance和NearPlaneDistance属性限定视觉范围,由于照相机可以位于场景中的任何位置,因此照相机实际上可能会位于模型内部或者紧靠模型,这使得很难正确区分对象。使用 NearPlaneDistance,可以指定一个距离照相机的最小距离,即,在超过该距离后将不绘制对象。 相反,使用 FarPlaneDistance,可以指定一个距离照相机的距离(即,在超过该距离后将不绘制对象),从而确保因距离太远而无法识别的对象将不包括在场景中

.Position属性定义相机的位置,LookDirection属性定义相机的朝向,UpDirection定义相机正上方的方向, FieldOfView顾名思义就是相机的视角了,好比一只手遮在你的眼睛上方,拿掉一点,你看到的将更多.


4.灯光的问题

WPF支持如下几种不同的光源:AmbientLight (自然光),DirectionalLight (方向光)PointLight (点光源),SpotLight (聚光源)。你需要确定光源的方向(Direction),颜色(color)等属性

AmbientLight是不自然的光,会近似照亮整个场景。使用这种光看不到边界。DirectionalLight定义了定向光。太阳光就是一种定向光,光线来自一边,此时可以看到边界和阴影。PointLight是一种位于指定位置的光,会照亮所有的方向。SpotLight照亮指定的方向。这个光定义了一个圆锥,会得到一个发出光亮的区域


5.一个 三维中二维界面模板--   Viewport3D   -> Camera -> PerspectiveCamera  ->    ModelVisual3D指定灯光

 <Viewport3D x:Name="view" ClipToBounds="True" RenderOptions.EdgeMode="Aliased">
    
            <!--3D Scene-->
            <Viewport3D.Camera>
                <PerspectiveCamera x:Name="camera" FieldOfView="59" Position="0.5,0.5,2" LookDirection="0,0,-1">
                    <PerspectiveCamera.Transform>
                        <RotateTransform3D x:Name="rot" CenterY="0.5" CenterX="0.5" CenterZ="-0.5">
                            <RotateTransform3D.Rotation>
                                <!-- rotation -->
                                <AxisAngleRotation3D x:Name="camRotation" Axis="0,1,0" Angle="0"/>
                            </RotateTransform3D.Rotation>
                        </RotateTransform3D>
                    </PerspectiveCamera.Transform>
                </PerspectiveCamera>
            </Viewport3D.Camera>
            <!--Light-->
            <ModelVisual3D>
                <ModelVisual3D.Content>
                    <AmbientLight Color="White" />
                </ModelVisual3D.Content>
            </ModelVisual3D>

然后指定材质,指定Viewport2DVisual3D.IsVisualHostMaterial="True",定义绘制面,指定怎么贴上纹理(这里就是等于怎么显示2维界面了)

<DiffuseMaterial x:Key="CubeSideMaterial" Viewport2DVisual3D.IsVisualHostMaterial="True" Brush="White"/>
   <Viewport2DVisual3D Material="{StaticResource  CubeSideMaterial }">
                <Viewport2DVisual3D.Geometry>
             
                    <!--<MeshGeometry3D Positions="0,1,0 0,0,0 1,0,0 1,1,0"
                                    TextureCoordinates="0,0 0,1 1,1 1,0"
                                    TriangleIndices="0 1 2  0 2 3"/>
                    <MeshGeometry3D Positions="0 0 0, 1 1 0, 0 1 0, 0 0 0, 1 0 0, 1 1 0"
                           TriangleIndices="0 1 2 3 4 5"
                           TextureCoordinates="0 1, 1 0, 0 0,0 1, 1 1, 1 0"/>-->

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


                    
                </Viewport2DVisual3D.Geometry>

接下来   写 xaml的 二维界面代码

           <!--二维界面的常见代码-->
        </Viewport2DVisual3D>   </Viewport3D>

通过移动相机  ,让2维的界面产生3d的效果

推荐您阅读更多有关于“WPF4.5,”的文章

猜你喜欢

额 本文暂时没人评论 来添加一个吧

发表评论

必填

选填

选填

必填

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

  查看权限

抖音:wpfui 工作wpf,目前主maui

招聘合肥一枚WPF工程师,跟我一个开发组,10-15K,欢迎打扰

目前在合肥市企迈科技就职

AYUI8全源码 Github地址:前往获取

杨洋(AaronYang简称AY,安徽六安人)AY唯一QQ:875556003和AY交流

高中学历,2010年开始web开发,2015年1月17日开始学习WPF

声明:AYUI7个人与商用免费,源码可购买。部分DEMO不免费

不是从我处购买的ayui7源码,我不提供任何技术服务,如果你举报从哪里买的,我可以帮你转正为我的客户,并送demo

查看捐赠

AYUI7.X MVC教程 更新如下:

第一课 第二课 程序加密教程

标签列表