美文网首页
OpenGL 向量/矩阵

OpenGL 向量/矩阵

作者: _涼城 | 来源:发表于2020-07-22 13:33 被阅读0次
    向量
    什么是向量

      在3D笛卡坐标系中,基本上,一个顶点就是XYZ坐标空间上的一个位置。而在空间中给定的一个位置,恰恰是由一个单独的XYZ定义的。而这样的XYZ就是向量。长度为1的的向量为单位向量向量长度计算公式为,

    \sqrt[2]{x^2+y^2+z^2}

      如果一个向量不是单位向量,而我们把它缩放到1,这个过程叫做标准化,将一个向量进行标准化就是将它缩为1;也叫做单位化向量。使用一个非零向量除以它的模(向量的长度),就可以得到方向相同的单位向量。

      如下图所示,点A的坐标为(1,0,0) ,这个向量A在X轴上为+1,其它两个方向为0,向量长度为1,则点A为单位向量

    坐标系.jpg
    向量的定义

      在math3d库中,有两个数据类型,能够表示一个三维或四维向量。M3DVector3f表示一个三维向量(x,y,z)M3DVector4f表示一个四维向量(x,y,z,w)

      OpenGL 中这两个数据类型本质上是一个一维浮点型数组,代码示例如下:

    typedef float M3DVector3f[3];
    typedef float M3DVector4f[4];
    //声明一个三维变量
    M3DVector3f vVector;
    //初始化一个四维变量
    M3DVector4f vVertex = {0,0,1,1};
    //声明一个三分量顶点数组
    M3DVector3f vVerts[] = {
                  -0.5f,0.0f,0.0f,
                  0.5f,0.0f,0.0f,
                  0.0f,0.5f,0.0f
    }
    
    点乘

      点乘只能发生在两个向量之间。两个三维单位向量之间进行点乘将得到一个标量(数值),它表示两个向量之间的夹角(余弦值)。math3d库中关于点乘的函数:

    //获得两个向量之间点乘的结果
    float m3dDotProduct3(const M3DVector3f u,const M3DVector3f v);
    //获得两个向量之间夹角的弧度值
    float m3dGetAngleBetweenVector3(const M3DVector3f u,const M3DVector3f v);
    
    叉乘

      两个向量(不必为单位向量)之间叉乘所得的结果是另外一个向量,这个新向量与原来两个向量定义的平面垂直。math3d库中关于叉乘的函数:

    void m3dCrossProduct3(M3DVector3f result,const);
    
    矩阵

      在数学上,矩阵只不过是一组排列在统一的行和列中的数字。用程序设计语言的语言来说就是一个二维数组。如果在空间中有一个点,由x,y和z坐标定义,将它围绕任意点沿任意方向旋转一定角度后,我们需要这个点现在的位置,就要用到矩阵

      矩阵之间可以进行乘法和加法,也能与向量或者标量相乘。用一个向量乘以一个矩阵(一次变化)结果得到一个新的变化点(向量)。math3d库中关于矩阵的定义:

    //3维矩阵
    typedef float M3DMatrix33f[9];
    //4维矩阵
    typedef float M3DMatrix44f[16];
    
    矩阵的构造

      在其他编程标准中,许多矩阵库定义一个矩阵时,使用二维数组;在OpenGL里,更多倾向于使用一维数组;这样做的原因是OpenGL使用的是Column-Major(以列为主)矩阵排序的约定。

      在4*4矩阵中,这16个值表示了空间中的一个特点位置,以及相对于视觉坐标系的3个轴的方向。这4列中每一列都代表一个由4个元素组成的向量。前3列的前3个元素只是方向向量,他们表示空间中x轴、y轴和z轴上的方向,第4列包含变换后的坐标系原点的x、y和z值。

      特别地,矩阵的最后一行都为0,只有最后一个元素为1。

    4*4矩阵.png

      如果将一个对象所有的顶点向量乘以这个矩阵,就能让整个对象变换到空间中给定的位置和方向。

    单元矩阵

      将一个向量乘以一个单位矩阵,就等与用这个向量乘以1,不会发生任何改变。

    • 初始化方式①

      GLFloat m[] = {
          1,0,0,0,
          0,1,0,0,
          0,0,1,0,
          0,0,0,1
      }
      
    • 初始化方式②

      M3DMatrix44f m = {
          1,0,0,0
          0,1,0,0,
          0,0,1,0,
          0,0,0,1
      }
      
    • 初始化方式③

      void m3dLoadIdentity44f(M3DMatrix44f)
      
    理解变换
    变化 解释
    视图变换 指定观察者位置
    模型变换 在场景中移动物体
    模型视图 描述视图/模型变化的二元性
    投影 改变视景体大小和它的投影方式
    视口 伪变化,对窗口上最终输出进行缩放
    • 视图变换

      视图变换将观察者放在希望的任何位置,并允许在任何方向上观察场景,确定视图变换就像在场景中放置照相机并让它指向某个方向。

    • 模型变换

      模型变化用于操纵模型和其中的特定对象。这些变换将对象移动到需要的位置,然后在对它们进行旋转和缩放。

      • 平移

        void m3dTranslationMatrix44(M3DMatrix44f m ,float x,float y,float z)
        
      • 旋转

        void m3dRotationMatrix44(M3DMatrix44f m ,float angle,float x,float y,float z)
        
      • 缩放

        void m3dScaleMatrix44(M3DMatrix44f m ,float xScale,float yScale,float zScale
        
      • 综合变换

         void m3dMatrixMultiply44(M3DMatrix44f product,const M3DMatrix44f a,const M3DMatrix44f b)
        
    几何图形
    创建一个球体
      /*
          gltMakeSphere(GLTriangleBatch& sphereBatch, GLfloat fRadius, GLint iSlices, GLint iStacks);
         参数1:sphereBatch,三角形批次类对象
         参数2:fRadius,球体半径
         参数3:iSlices,从球体底部堆叠到顶部的三角形带的数量;其实球体是一圈一圈三角形带组成
         参数4:iStacks,围绕球体一圈排列的三角形对数
    
         建议:一个对称性较好的球体的片段数量是堆叠数量的2倍,就是iStacks = 2 * iSlices;
         绘制球体都是围绕Z轴,这样+z就是球体的顶点,-z就是球体的底部。
         */
        gltMakeSphere(sphereBatch, 3.0, 10, 20);
    
    创建一个环面
    // 环面
        /*
         gltMakeTorus(GLTriangleBatch& torusBatch, GLfloat majorRadius, GLfloat minorRadius, GLint numMajor, GLint numMinor);
         参数1:torusBatch,三角形批次类对象
         参数2:majorRadius,甜甜圈中心到外边缘的半径
         参数3:minorRadius,甜甜圈中心到内边缘的半径
         参数4:numMajor,沿着主半径的三角形数量
         参数5:numMinor,沿着内部较小半径的三角形数量
         */
        gltMakeTorus(torusBatch, 3.0f, 0.75f, 15, 15);
    
    创建一个圆锥
    /*
         void gltMakeCylinder(GLTriangleBatch& cylinderBatch, GLfloat baseRadius, GLfloat topRadius, GLfloat fLength, GLint numSlices, GLint numStacks);
         参数1:cylinderBatch,三角形批次类对象
         参数2:baseRadius,底部半径
         参数3:topRadius,头部半径
         参数4:fLength,圆形长度
         参数5:numSlices,围绕Z轴的三角形对的数量
         参数6:numStacks,圆柱底部堆叠到顶部圆环的三角形数量
         */
        gltMakeCylinder(cylinderBatch, 2.0f, 2.0f, 3.0f, 15, 2);
    
    创建一个锥
     /*
         void gltMakeCylinder(GLTriangleBatch& cylinderBatch, GLfloat baseRadius, GLfloat topRadius, GLfloat fLength, GLint numSlices, GLint numStacks);
         参数1:cylinderBatch,三角形批次类对象
         参数2:baseRadius,底部半径
         参数3:topRadius,头部半径
         参数4:fLength,圆形长度
         参数5:numSlices,围绕Z轴的三角形对的数量
         参数6:numStacks,圆柱底部堆叠到顶部圆环的三角形数量
         */
        //圆柱体,从0开始向Z轴正方向延伸。
        //圆锥体,是一端的半径为0,另一端半径可指定。
        gltMakeCylinder(coneBatch, 2.0f, 0.0f, 3.0f, 13, 2);
    
    创建一个磁盘
     /*
        void gltMakeDisk(GLTriangleBatch& diskBatch, GLfloat innerRadius, GLfloat outerRadius, GLint nSlices, GLint nStacks);
         参数1:diskBatch,三角形批次类对象
         参数2:innerRadius,内圆半径
         参数3:outerRadius,外圆半径
         参数4:nSlices,圆盘围绕Z轴的三角形对的数量
         参数5:nStacks,圆盘外网到内围的三角形数量
         */
        gltMakeDisk(diskBatch, 1.5f, 3.0f, 13, 3);
    
    矩阵堆栈

    在GLTools库中有一个矩阵堆栈来帮助完成矩阵变换,这个类称为GLMatrixStack

    堆栈操作
    • 初始化

      这个类的构造函数允许指定堆栈的最大深度,默认的堆栈深度为64。在初始化堆栈时,已经包含了单位矩阵

      GLMatrixStack::GLMatrixStack(int iStackDepth = 64);
      
    • 栈顶载入矩阵

      • 单位矩阵

        void GLMatrixStack::LoadIdentity(void);
        
      • 任一矩阵

        void GLMatrixStack::LoadMatrix(const M3DMatrix44f m);
        
    • 矩阵栈顶元素与新元素相乘后的结果存储在堆栈顶部

      void GLMatrixStack::MultMatrix(const M3DMatrix44f);
      
    • 获取栈顶元素

      • 获取值

        const M3DMatrix44f & GLMatrixStaxk::GetMatrix(void);
        
      • 获取副本

        void  GLMatrixStaxk::GetMatrix(M3DMatrix44f mMatrix);
        
    • 压栈

      • 栈顶矩阵Copy到栈顶

        void GLMatrixStack::PushMatrix(void);
        
      • 将M3DMatrix44f 矩阵对象压入当前矩阵堆栈

        void PushMatrix(const M3DMatrix44f mMatrix);
        
      • 将GLFrame对象压入堆栈

        void PushMatrix(GLFrame &frame);
        
    • 出栈

      void GLMatrixStack::PopMatrix(void);
      

    相关文章

      网友评论

          本文标题:OpenGL 向量/矩阵

          本文链接:https://www.haomeiwen.com/subject/qfwzkktx.html