OpenGL(二)

向量

  • 我们知道在OpenGL中所有图形都是由图元,组成的,而每个图元都是根据指定的坐标所定义的,常用的坐标由XYZ三元组成,然而,一组XYZ还能表示一个向量。在使用向量来操作3D几何图形时,向量可能就变成了最重要的基本概念了,一个向量表示了两个重要的值——方向和数量。
  • 在3D笛卡尔坐标中,从坐标原点到某个顶点组成的一条带箭头的线段(- -!带箭头只是为了方便理解,不是真的会带箭头)可以视为一个向量。
  • 一个向量首先是空间中从原点指向这个点的方向。
  • 然后是数量,一个向量的数量就是这个向量的长度。
  • 通常有两个向量数据类型,分别是三维和四维。三维向量是(X,Y,Z),四维向量(X,Y,Z,W)。W为缩放因子,XYZ的值通过除以W来进行缩放,典型情况下W的坐标为1.0,因此默认除以1.0表示没有缩放。
  • 大多数情况我们发给OpenGL的顶点坐标都是三分量的顶点,大多数情况下一个三分量顶点也是足够的,但是,当进行3D顶点变换,这时我们就必须用它乘以一个4x4的变换矩阵了(不要问我为什么是4x4,我也想知道)。这里的规则是,我们必须用一个四分量向量乘以一个4x4矩阵,因此如果我们使用的是三分量实际上OpenGL计算时还是用的是四分量,只不过W分量上默认为1.0

变换

  • 视图变换

    • 正如我们观察某个物体,由于站的位置和角度的不同所观察到的视觉效果也是不同的,视图变换就是应用观察点到场景中的一种变换,它用来确定场景中的有利观察位置。在默认情况下,透视投影中的观察点位于原点(0,0,0),并沿着轴的负方向进行观察。

    • 在正投影中,观察者被认为是在Z轴正方向无穷远的位置,能够看到是视景体中的任何东西。

    • 视图变换允许我们把观察点防灾所希望的任何位置,并允许在任何方向上观察场景。

    • 确定视图变换就像在场景中放置照相机并让它指向某个方向。

    • 从大局上考虑,在应用其他任何模型变换之前,必须先应用视图变换。这样做是因为,对于视觉坐标系而言,视觉变换改变了当前的坐标系标准,所有后续的变换随后都会基于新调整的坐标系进行。举个例子,当你拍照时,所做的第一件事一定是先确定好照相机的位置,之后才是摆出各种pose。

    • 通过以下代码创建视图变换矩阵

    Matrix.setLookAtM (float[] rm,      //接收相机变换矩阵
                    int rmOffset,       //变换矩阵的起始位置(偏移量)
                    float eyeX,float eyeY, float eyeZ,   //相机位置
                    float centerX,float centerY,float centerZ,  //观测点位置
                    float upX,float upY,float upZ)  //up向量在xyz上的分量

  • 模型变换

    • 模型变换是操作模型和其中的特定对象。这些变换将对象移动到需要的位置,然后再对他们进行旋转和缩放。也就是我们拍张中所说的”摆pose“。

      Matrix.multiplyMM (float[] result, //接收相乘结果
                    int resultOffset,  //接收矩阵的起始位置(偏移量)
                    float[] lhs,       //左矩阵
                    int lhsOffset,     //左矩阵的起始位置(偏移量)
                    float[] rhs,       //右矩阵
                    int rhsOffset)     //右矩阵的起始位置(偏移量)
      其实是将两个矩阵相乘,也可以看成两个矩阵的复合效果,使用视图矩阵、投影矩阵、变换矩阵相乘作为模型变换矩阵。

  • 模型视图的二元性

    • 实际上,视图和模型变换按照它们内部效果和对场景的最终外观(最终呈现出来的效果)来说是一样的。之所以将两者分离出来仅仅是为了程序员方便,因为这样更符合我们现实生活中的物理现象,这样就使得我们在制作一些复杂场景时更加的容易。

  • 投影变换

    投影变换在视图变换之后应用到定点之上。这种投影实际上定义了视景体并创建了裁剪平面。

    • 正交投影

      • 在正交投影中,所有多边形都是精确地按照指定的相对大小在屏幕上绘制的,线和多边形使用平行线来直接映射到2D屏幕上,这就意味着,无论某个物体的位置有多远,它都会按照同样的大小来进行绘制。
              Matrix.orthoM (float[] m,           //接收正交投影的变换矩阵
                      int mOffset,        //变换矩阵的起始位置(偏移量)
                      float left,         //相对观察点近面的左边距
                      float right,        //相对观察点近面的右边距
                      float bottom,       //相对观察点近面的下边距
                      float top,          //相对观察点近面的上边距
                      float near,         //相对观察点近面距离
                      float far)          //相对观察点远面距离
      • 正交投影大多在进行2D绘制时使用,不过就个人理解的话,如果是2d绘制那为什么还要做出空间感和距离感呢,直接绘制在同一个平面不就好了。所以只要需要空间和深度的场景都是使用的透视投影而不是正投影。
    • 透视投影

      • 透视投影所显示的场景与现实生活中更加接近,而不是一张蓝图。透视投影的特点就是透视缩短foreshortening。这种特性使得同样大小的物体在远处显得比近处要小一些。
      Matrix.frustumM (float[] m,         //接收透视投影的变换矩阵
                      int mOffset,        //变换矩阵的起始位置(偏移量)
                      float left,         //相对观察点近面的左边距
                      float right,        //相对观察点近面的右边距
                      float bottom,       //相对观察点近面的下边距
                      float top,          //相对观察点近面的上边距
                      float near,         //相对观察点近面距离
                      float far)          //相对观察点远面距离
      
                      //计算宽高比
                      float ratio = (float) width / height;
                      //设置透视投影 避免图像拉伸变形 因为我们默认坐标系为1:1而实际画布并不是
                      Matrix.frustumM(mProjectMatrix, 0, -ratio, ratio, -1, 1, 3, 8f);

      OpenGL Perspective Frustum

矩阵

  • 矩形构造
    • OpenGL并不是将一个4x4矩阵表示为一个浮点值的二维数组,而是将它表示为一个由16位浮点值组成的单个数组。 这种方式与我们正常想法中的二维数组的实现方式不同,虽然OpenGL也是可以使用二维数组的方式的,但是第一种会更为高效
  • 模型矩阵
    • 模型试图矩阵是一个4x4的矩阵,它表示一个变换后的坐标系,我们可以用来放置对象和确定对象的方向。我们为图元提供的顶点将作为一个单列矩阵(也就是一个向量)的形式来使用,并乘以一个模型视图矩阵来获得相对视觉坐标系的经过变换的新坐标。
    • 简单来说就是把图元的顶点乘以模型变换矩阵,得到变换之后的新坐标,就实现了模型变换的效果。
    • 常见的变换有:平移、旋转、缩放等。除了可以使用单独的变换之外还可以将两种变换矩阵相乘得到综合变换矩阵,但是有时候两个矩阵相乘的先后顺序的不同是会影响结果的不同的。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值