GLM 中的mat4

GLM 中的mat4

mat4中内存的排列方式

mat4的类定义在type_mat4x4.hpp中,下面是对整个类代码的部分截取:

struct tmat4x4
{
   typedef tvec4<T, P> col_type;
   private:
   col_type value[4];
   publictemplate <typename T, precision P>
       GLM_FUNC_QUALIFIER typename tmat4x4<T, P>::col_type &    tmat4x4<T, P>::operator[](typename tmat4x4<T, P>::length_type i)
  {
     assert(i < this->length());
     return this->value[i];
  }
}

从类代码的实现我们可以看出,mat4中4行4列的元素是按照列的方式排列的,在内存中的排列方式为:
mat4的内存排列方式
当然我们可以使用[ ]操作符来访问mat4的第几列,并使用二级[ ]来访问某一列的第几个元素,下面是一个简单的给mat4每个元素赋值的例子:

    glm::mat4 View;
    View[0][0] = 0.0f; View[0][1] = 0.0f; View[0][2] = 0.0f; View[0][3] = 0.0f;
    View[1][0] = 0.0f; View[1][1] = 0.0f; View[1][2] = 0.0f; View[1][3] = 0.0f;
    View[2][0] = 0.0f; View[2][1] = 0.0f; View[2][2] = 0.0f; View[2][3] = 0.0f;
    View[3][0] = 0.0f; View[3][1] = 0.0f; View[3][2] = 0.0f; View[3][3] = 0.0f;

但是为什么glm要把mat4按照列进行内存排列呢?主要是因为opengl在显存中是按列存储的,所以在准备好数据后可以直接将mat4复制到现存中,下面是一个简单的给现存传输mat4的示例代码:

void setMat4(const std::string &name, const glm::mat4 &mat) const
{
    glUniformMatrix4fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, &mat[0][0]);
}

glm::mat4单位矩阵

glm::mat4 Model = glm::mat4(1.0f);//创建一个单位矩阵

glm::frustum视锥体

glm::mat4 Projection = glm::frustum(-1.234897f*0.1f, 1.234897f*0.1f, -1.234897f*0.1f, 1.2/34897f*0.1f, 0.1f, 1000.0f);

glm::frustum用于生成一个透视矩阵,其中六个入参分别为视锥体的 left, right, bottom, top, nearVal, farVal。

glm四元数转mat4

glm::fquat poseQuat = glm::fquat(qw,qx,qy,qz);
glm::mat4 poseMat = glm::mat4_cast(poseQuat);

代码如上不做详述。

glm::translate

glm::mat4 AA = glm::mat4(1.0f,2.0f,3.0f,4.0f,
                         5.0f,7.0f,8.0f,9.0f,
                         4.0f,6.0f,3.0f,2.0f,
                         9.0f,1.0f,2.0f,3.0f);
LOGCATE("WZJ1029 AA: {%f, %f, %f, %f;  %f, %f, %f, %f;  %f, %f, %f, %f;  %f, %f, %f, %f}",
        AA[0][0],AA[0][1],AA[0][2],AA[0][3],
        AA[1][0],AA[1][1],AA[1][2],AA[1][3],
        AA[2][0],AA[2][1],AA[2][2],AA[2][3],
        AA[3][0],AA[3][1],AA[3][2],AA[3][3]);
glm::mat4 BB = glm::translate(AA, glm::vec3(1.0f, 2.0f, 3.0f));
LOGCATE("WZJ1029 BB: {%f, %f, %f, %f;  %f, %f, %f, %f;  %f, %f, %f, %f;  %f, %f, %f, %f}",
        BB[0][0],BB[0][1],BB[0][2],BB[0][3],
        BB[1][0],BB[1][1],BB[1][2],BB[1][3],
        BB[2][0],BB[2][1],BB[2][2],BB[2][3],
        BB[3][0],BB[3][1],BB[3][2],BB[3][3]);
// AA: {1.000000, 2.000000, 3.000000, 4.000000;  
//     5.000000, 7.000000, 8.000000, 9.000000;  
//     4.000000, 6.000000, 3.000000, 2.000000;  
//     9.000000, 1.000000, 2.000000, 3.000000}
//BB: {1.000000, 2.000000, 3.000000, 4.000000;  
//     5.000000, 7.000000, 8.000000, 9.000000;  
//     4.000000, 6.000000, 3.000000, 2.000000;  
//     32.000000, 35.000000, 30.000000, 31.000000}

首先介绍下运算规则:BB的第一列等于AA第一列,BB的第二列等于AA第二列,BB的第三列等于AA第三列,
BB的第四列 = AA第一列乘以vec3(1) + AA第二列乘以vec3(2) + AA第三列乘以vec3(3) + AA第四列
只看运算规则,并不能很好的理解translate的实际用处,如果考虑如下情景:已知旋转R和位移t组成的转换矩阵 [ R t 0 1 ] \begin{bmatrix} R & t\\ 0 & 1 \end{bmatrix} [R0t1],要求逆变换 [ R − 1 − R − 1 t 0 1 ] \begin{bmatrix} R^{-1} & -R^{-1}t\\ 0 & 1 \end{bmatrix} [R10R1t1],可以用如下代码实现:

glm::fquat poseQuat = glm::fquat(rw,-rx,-ry,-rz);
glm::mat4 poseMat = glm::mat4_cast(poseQuat);
glm::mat4 View = glm::translate(poseMat, glm::vec3(-px,-py,-pz));

glm::mat4的矩阵相乘

LOGCATE("WZJ1029 AA: {%f, %f, %f, %f;  %f, %f, %f, %f;  %f, %f, %f, %f;  %f, %f, %f, %f}",
        AA[0][0],AA[0][1],AA[0][2],AA[0][3],
        AA[1][0],AA[1][1],AA[1][2],AA[1][3],
        AA[2][0],AA[2][1],AA[2][2],AA[2][3],
        AA[3][0],AA[3][1],AA[3][2],AA[3][3]);
LOGCATE("WZJ1029 BB: {%f, %f, %f, %f;  %f, %f, %f, %f;  %f, %f, %f, %f;  %f, %f, %f, %f}",
        BB[0][0],BB[0][1],BB[0][2],BB[0][3],
        BB[1][0],BB[1][1],BB[1][2],BB[1][3],
        BB[2][0],BB[2][1],BB[2][2],BB[2][3],
        BB[3][0],BB[3][1],BB[3][2],BB[3][3]);
        glm::mat4 AB = AA * BB;
LOGCATE("WZJ1029 AB: {%f, %f, %f, %f;  %f, %f, %f, %f;  %f, %f, %f, %f;  %f, %f, %f, %f}",
        AB[0][0],AB[0][1],AB[0][2],AB[0][3],
        AB[1][0],AB[1][1],AB[1][2],AB[1][3],
        AB[2][0],AB[2][1],AB[2][2],AB[2][3],
        AB[3][0],AB[3][1],AB[3][2],AB[3][3]);
//AA: {1.000000, 2.000000, 3.000000, 4.000000;  
//     5.000000, 7.000000, 8.000000, 9.000000;  
//     4.000000, 6.000000, 3.000000, 2.000000;  
//     9.000000, 1.000000, 2.000000, 3.000000}
//BB: {1.000000, 2.000000, 3.000000, 4.000000;  
//     5.000000, 7.000000, 8.000000, 9.000000;  
//     4.000000, 6.000000, 3.000000, 2.000000;  
//     32.000000, 35.000000, 30.000000, 31.000000}
//AB: {59.000000, 38.000000, 36.000000, 40.000000;  
//     153.000000, 116.000000, 113.000000, 126.000000;  
//     64.000000, 70.000000, 73.000000, 82.000000;  
//     606.000000, 520.000000, 528.000000, 596.000000}

glm::mat4矩阵相乘还是行列相乘,唯一需要注意的就是矩阵的排列方式是列存储,最后计算出的结果也是列存储。

glm::scale

glm::rotate

glm::scale,glm::rotate,glm::translate,通常会组合在一起形成对模型坐标系的缩放旋转偏移:

   glm::mat4 Model = glm::mat4(1.0f);
   Model = glm::scale(Model, glm::vec3(0.001f, 0.001f, 0.001f));
   Model = glm::rotate(Model, 0.0f, glm::vec3(1.0f, 0.0f, 0.0f));
   Model = glm::rotate(Model, 0.0f, glm::vec3(0.0f, 1.0f, 0.0f));
   Model = glm::translate(Model, -m_pModel->GetAdjustModelPosVec());
   glm::mat4 modelMatrix = Model;
   glm::mat4 mvpMatrix = Projection * View * Model;

上述代码中GetAdjustModelPosVec用于获取当前模型点云的质心坐标,并将模型移动到世界坐标系的原点位置处。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值