zoukankan      html  css  js  c++  java
  • Managed DirectX +C# 开发(入门篇)(六)

    第五章 矩阵变换
    一:为什么使用4×4矩阵?
    在3D中进行编程时,使用的是4×4矩阵来进行矩阵变换。初学者往往认为既然是三维空间,为何不使用3×3的矩阵来表示呢?这是因为3×3的矩阵不能表示有些变换,比如比如*移、投影、反射,因此,增大到4×4,这样,就可以描述更多的变换了。但是矩阵变成了4×4,为了做向量与矩阵的相乘,所以需要把向量增加为1×4,因为1×3的行矩阵和4×4的矩阵是无法相乘的;
    那么,如何使用第四个成员(用w来表示)呢?当把一个点放置到一个1×4的行矩阵中时,设置w=1,表示可以对点进行适当的*移,如果w=0,表示不可以对向量进行*移。比如:把点p = (1, 2, 3)放置到一个行向量中就象这样[1, 2, 3, 1],同样把向量v = (21, 32, 33) 放置到一个行向量中就象这样[21, 32, 33, 0];
    二、矩阵*移
    对图形进行*行移动是最基本的操作:
    使用下面的矩阵可以把向量(x, y, z, 1)沿x轴移动px个单位,沿y轴移动py个单位,沿z轴移动pz个单位:
    以下代码为设置一个向量,对它应用一个*移变换后,得到新的向量,完整的代码参见程序:
    private void button1_Click(object sender, System.EventArgs e)
            {
                Clear();
                //定义一个测试的向量;
                         Vector3 myVect=new Vector3(3,6,8);
    //用此向量来保存后来的结果;
                         Vector4 resultVect =new Vector4();
    //生成一个*移矩阵,XYZ方向均增加4个单位
                Matrix MatrixA=Matrix.Translation(4,4,4);
    //对向量应用*移变换;
                resultVect=Vector3.Transform(myVect,MatrixA);
    //将返回的向量显示出来;
                label9.Text =resultVect.ToString();
    //将矩阵也显示出来;
                DisplayMatrix(MatrixA,label1);
            }
    程序执行结果,执行程序,点击按钮,执行结果如下:
    下面应用一个具体的实例:
    1:新建一个工程,生成一个XOZ水*面(代码略):
    2:定义二个Mesh对象:Mesh mesh1=null,mesh2=null;
    3:在图形的初始化函数中对它进行实例化,在这里是生成两个半径一样大小的小球:
    public bool InitializeGraphics()
                  {
    ……
                                mesh1=Mesh.Sphere(device,0.5f,20,20);
                                mesh2=Mesh.Sphere(device,0.5f,20,20);
    …….
                  }
    4:在渲染场景函数里:一个小球进行*移变换,另一个则不进行任何变换:
    private void Render()
            {
                         if (device == null)
                                return;
               
                device.Clear(ClearFlags.Target, System.Drawing.Color.Black , 1.0f, 0);
                SetupCamera();
                device.BeginScene();
                displayPlane();
                device.Transform.World=Matrix.Translation(10,0,0);
                mesh1.DrawSubset(0);
                device.Transform.World=Matrix.Identity;
                mesh2.DrawSubset(0);
                device.EndScene();
                device.Present();
               
             }
    程序执行结果如下:
    三、矩阵旋转
    如果对一个图形绕一个固定点或一条线进行旋转,结果示意如下:
    图9
           下面的矩阵把一个向量围绕x,y 和z轴旋转一个角度。注意这里应当为弧度值, 当俯视绕轴原点时,角度是指顺时针方向的角度。
    示例一:
    下面测试一向量应用旋转变换后的结果:
           private void button2_Click(object sender, System.EventArgs e)
            {
                Clear();
                         Vector3 myVect=new Vector3(3,6,8);
                         Vector4 resultVect =new Vector4();
                         Matrix MatrixA=Matrix.RotationX((float)Math.PI/2);
                resultVect=Vector3.Transform(myVect,MatrixA);
                label9.Text =resultVect.ToString();
                DisplayMatrix(MatrixA,label1);
             }
    在这里,我们是让此向量绕X轴旋转90度,可以想像成直线OA绕X轴旋转90度,得到直线OB,B点值即为所求向量值;
    执行结果如下:
    示例二:
    下面应用一个具体的实例:
    1:新建一个工程,生成一个XOZ水*面(代码略):
    2:定义二个Mesh对象:Mesh mesh1=null,mesh2=null;
    3:在图形的初始化函数中对它进行实例化,在这里是生成两个长方体:
    public bool InitializeGraphics()
                  {
    ……
                                mesh1=Mesh.Box(device,0.5f,0.5f,16);
                                mesh2=Mesh.Box(device,0.5f,0.5f,16);
    ……
                  }
    4:在渲染场景函数里:对一个长方体绕X轴旋转45度,另一个长方体则在原点绘出:
    private void Render()
            {
    ……
                         device.Transform.World=Matrix.RotationX((float)Math.PI/4);
                mesh1.DrawSubset(0);
                device.Transform.World=Matrix.Identity;
                mesh2.DrawSubset(0);
    ……
             }
    程序执行结果如下:
    以上介绍的是绕X轴旋转,绕Y,Z轴旋转类似,矩阵是:
    四、矩阵缩放
    对物体进行缩放的示意图如下:
    下面的矩阵即为把向量沿x轴缩放qx个单位,沿y轴缩放qy个单位,沿z轴缩放qz个单位:
    注意,如果在每个方向上的值大于1为放大,小于1则为缩小;
    示例一:
                  private void button3_Click_1(object sender, System.EventArgs e)
            {
                Clear();
                         Vector3 myVect=new Vector3(3,6,8);
                         Vector4 resultVect =new Vector4();
                Matrix MatrixA=Matrix.Scaling(2,0.5f,0.5F);
                resultVect=Vector3.Transform(myVect,MatrixA);
                label9.Text =resultVect.ToString();
                DisplayMatrix(MatrixA,label1);
             }
    代码中,将向量X方向扩大为2倍,Y和Z方向分别缩小为2倍;
    得到结果向量值为:
    示例二:
    以下代码将前面创建的两个长方体其中一个应用缩放变换,其中在X,Y方向上放大为原来的2倍,Z方向上缩小为原来的2倍,相关代码如下:
    ……                     device.Transform.World=Matrix.Scaling(2,2,0.5f)*Matrix.RotationX((float)Math.PI/4);
                mesh1.DrawSubset(0);
                device.Transform.World=Matrix.Identity;
                  mesh2.DrawSubset(0);
    ……
    程序执行结果如下:
    五、组合变换
           一般情况下,需要对向量进行一系列的变换。比如,前面显示的长方体,为了不使两者叠在一起,先进行了缩放,再进行了旋转,其实还可以再应用其它变换,比如*移;
    假设把向量p = [5, 0, 0, 1] 在所有轴上缩小为原来的1/5,然后沿着y轴旋转π/4,最后把它在x轴上移动1个单位,在y轴上移动2个单位,在z轴上移动3个单位。
    设缩放、旋转、移动的变换矩阵分别是S, Ry, T,如下:
    因此:
    这样就得到了最后的结果,另一种简便的方法是通过使用矩阵相乘把3个变换矩阵合成一个矩阵。注意次序不要颠倒,否则结果会不一样。
    那么 pQ = [1.707, 2, –3.707, 1]。
    和第一种方法得到的结果是一样的;
    六、其它常用变换
    有两个矩阵,常常用来设置场影及摄像机:
    1:device.Transform.Projection用来获取或者设置投影变换矩阵,它本身也是一个Matrix型的变量。
    2:Matrix.PerspectiveFovLH方法:
    public static Matrix PerspectiveFovLH(
        float fieldOfViewY, //Y方向的视觉范围,弧度表示,即Y方向的视域角
        float aspectRatio, //视觉范围的长宽比
        float znearPlane, //*裁剪*面    
        float zfarPlane//远裁剪*面
    );
    定义长宽比的作用是,如果用户改变了窗口的大小,那么仍然就可以正确的显示物体的大小。最后两个参数是远及*裁剪*面,必须为这两个*面指定2个Z值,一般来说,假设物体将在Z轴的1.0f和1000f之间运动时,就分别把这两个参数设为1.0f,1000.0f。
    3:Matrix.LookAtLH方法。 在使用观察矩阵来建立一个立体的照相机模型后,需要设置不同的观察点,可以使用这种方法来设置相机。
    public static Matrix LookAtLH(
        Vector3 cameraPosition,//相机位置
        Vector3 cameraTarget,   //相机的方向
        Vector3 cameraUpVector //相机的Up向量
    );
    其中第二个参数为相机的面对方向,假设相机面对的是Z轴的方向,那么就设置为(0,0,1)。
  • 相关阅读:
    Java蛇形数组的简单实现代码
    Android Studio生成javadoc出错的解决办法
    AngularJS指令嵌套时link函数执行顺序的问题
    [转]如果我有jQuery背景,我应该如何切换到AngularJS的思维模式?
    扩展ViewFlow避免和ViewPager滑动冲突,同时支持无限循环,并完美和CircleFlowIndicator结合
    人机交互的新方向:智能聊天机器人
    利用python自动清除Android工程中的多余资源
    巧用svn create patch(打补丁)方案解决定制版需求
    【Android开发坑系列】之经常被忽略的背景图片内存泄露
    【Android开发坑系列】之try-catch
  • 原文地址:https://www.cnblogs.com/lcxu2/p/2004035.html
Copyright © 2011-2022 走看看