摘要
半吊子出家,没有特别系统的学习过opengl相关的库GLM,遇到一些坑,在这里记录一下一些注意事项。
GLM是基于(GLSL)规范的图形软件的仅头文件C ++数学库。该库可与OpenGL完美配合,但也可确保与其他第三方库和SDK的互操作性。它是软件渲染(光线跟踪/光栅化),图像处理,物理模拟以及任何需要简单方便的数学库的开发环境的理想选择。
GLM库地址
glm库注意事项
glm::mat4
在内存中存储是列优先的。列优先的定义可以看这里glm::vec4
是列向量,应当左边乘以矩阵。但是当右边乘以矩阵时,也能看做行向量。glm::mat4.length()
返回矩阵的列数,glm::mat4[i][j]
返回的是第i列第j行的元素。- glm内置函数进行矩阵变换时,矩阵是连续右乘。例如下面代码中,得到的结果为
glm_point2 = glm_mat * translate * rotate * glm_point
,虽然是先调用了glm::translate
再调用glm::rotate
,但在作用于坐标点上时顺序却是反过来。glm::mat4 glm_mat(1.0f); glm_mat = glm::translate(glm_mat, glm::vec3(0.0f, -25.0f, 0.0f)); // 若矩阵中存在-25这个值,证明是先旋转再平移 glm_mat = glm::rotate(glm_mat2, glm::radians(180.0f), glm::vec3(0.0, 0.0, 1.0)); glm::vec4 glm_point(2, 3, 4, 1); glm::vec4 glm_point2 = glm_mat * glm_point;
glm::mat3x4
表示3列4行的矩阵。注意不是3行4列!
其他验证代码,如果有人有需要可以自己跑一下:
// 注意glm::mat4是列优先的
// 所以这里列出的初始化矩阵是其内存中的存放方式
// 实际上它代表的矩阵应该是这里的转置
glm::mat4 glm_mat(1, 0, 0, 2,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1);
// 下面可以看出是先旋转再平移,相当于变换矩阵一直右乘
glm_mat = glm::translate(glm_mat, glm::vec3(0.0f, -25.0f, 0.0f)); // 若矩阵中存在-25这个值,证明是先旋转再平移
glm_mat = glm::rotate(glm_mat, glm::radians(180.0f), glm::vec3(0.0, 0.0, 1.0));
// glm::vec4为列向量,但是拿矩阵右乘它时,它又可以看做行向量
glm::vec4 glm_point(2, 3, 4, 1);
// glm::vec4 glm_point2 = glm_mat * glm_point; // 根据结果可判断glm::vec4也可以是列向量
glm::vec4 glm_point2 = glm_point * glm_mat; // 根据结果可判断glm::vec4也可以是行向量
// 注意:glm::mat4为列优先存储
cout << "glm_mat:" <<endl;
for(int32_t i=0; i<glm_mat.length(); ++i){// 这是第i列
for(int32_t j=0; j<glm_mat[i].length(); ++j){// 这是第j行
cout << glm_mat[j][i] << ", " ;
}
cout <<endl;
}
cout <<endl;
cout << "glm_point:" <<endl;
for(int32_t i=0; i<glm_point.length(); ++i){
cout << glm_point[i] << ", " ;
}
cout <<endl;
// 从结果看出,glm::mat4确实是列优先存储
cout << "glm_point2:" <<endl;
for(int32_t i=0; i<glm_point2.length(); ++i){
cout << glm_point2[i] << ", ";
}
cout <<endl;