1, 数据矩阵的存储区别:
Eigen是按列存储的, glm是按行存储的;
glm::mat4 m1(1);
glm::mat4 m0(0);
m1[2][3] = 23;
m1[3][2] = 32;
Eigen::Matrix4f Result = Eigen::Matrix4f::Identity();
Result(1,2) = 12;
Result(2,3) = 23;
Result(2,1) = 21;
Result(3,2) = 32;
cout << "Result(1) =\n" << Result << std::endl;
Eigen::Matrix4f Result1 = Eigen::Matrix4f::Zero();
cout << "Result1 =\n" << Result1 << endl;
Eigen::Matrix4f Result2 = Eigen::Matrix4f::Ones();
cout << "Result2 =\n" << Result2 << endl;
2, 数据矩阵的重载*运算符的区别(很重要,不好懂):
glm::vec3 eye(0.0f, 0.0f, 1.0f);
glm::vec3 center(0.0f, 0.0f, 0.0f);
glm::vec3 up(0.0f,1.0f, 0.0f);
glm::mat4 proj = glm::perspective(glm::radians(45.0f), 4.0f / 3.0f, 0.1f, 100.f);
glm::mat4 view = glm:: glm::lookAt(eye, center, up );
glm::mvp = view*proj;
Camera camera;
Eigen::Vector3f eye(0.0f, 0.0f, 1.0f);
Eigen::Vector3f center(0.0f, 0.0f, 0.0f);
Eigen::Vector3f up(0.0f, 1.0f, 0.0f);
Eigen::Matrix4f proj = camera.perspective(camera.radians(45.0f), 4.0f / 3.0f, 0.1f, 100.f);
Eigen::Matrix4f view = camera.lookAt(eye, center, up);
Eigen::Matrix4f MVP = view*proj;
上面glm中的proj是Eigen中的proj的转置矩阵,view同理;
3 传入到shader中的方式不同:
glUniformMatrix4fv(mesh.getShader().uniform("model"), 1, GL_FALSE, &mvp[0][0]); // 行地址
glUniformMatrix4fv(mesh.getShader().uniform("model"), 1, GL_FALSE, MVP.data()); // col address
4, 总结
Eigen符合矩阵运算直觉,适用于广泛的科学计算,不仅仅三维图形;glm只适用于opengl空间坐标变换,只为opengl而生,即 便如此,也不如Eigen好用。Eigen不足是没有透视变换,正交变换和相机观察变换,这个可以自己实现,也可以仿照glm改写,但要求对矩阵按列与按行存储方式对矩阵运算的影响以及按列传数据到时shader有根本认识。
本人仿照glm改写的透视变换Perspective(...), 正交变换ortho(...)和相机观察变换lookAt(...)如下:
Eigen::Matrix4f Camera::perspective(float fovy, float aspect, float zNear, float zFar)
{
float const tanHalfFovy = tan(fovy / 2);
Eigen::Matrix4f Result = Eigen::Matrix4f::Zero();
Result(0, 0) = 1 / (aspect * tanHalfFovy);
Result(1, 1) = 1 / (tanHalfFovy);
Result(2, 2) = -(zFar + zNear) / (zFar - zNear);
Result(3, 2) = -1.0;
Result(2, 3) = -(2 * zFar * zNear) / (zFar - zNear);
return Result;
}
Eigen::Matrix4f Camera::ortho(float left, float right, float bottom, float top, float zNear, float zFar)
{
Eigen::Matrix4f Result = Eigen::Matrix4f::Identity();
Result(0, 0) = 2 / (right - left);
Result(1, 1) = 2 / (top - bottom);
Result(2, 2) = -2 / (zFar - zNear);
Result(0, 3) = -(right + left) / (right - left);
Result(1, 3) = -(top + bottom) / (top - bottom);
Result(2, 3) = -(zFar + zNear) / (zFar - zNear);
return Result;
}
Eigen::Matrix4f Camera::lookAt(Eigen::Vector3f const& eye, Eigen::Vector3f const& center, Eigen::Vector3f const& up)
{
Eigen::Vector3f f(center - eye);
Eigen::Vector3f s(f.cross(up));
Eigen::Vector3f u(s.cross(f));
f.normalize();
s.normalize();
u.normalize();
Eigen::Matrix4f Result = Eigen::Matrix4f::Identity();
Result(0, 0) = s.x();
Result(0, 1) = s.y();
Result(0, 2) = s.z();
Result(1, 0) = u.x();
Result(1, 1) = u.y();
Result(1, 2) = u.z();
Result(2, 0) = -f.x();
Result(2, 1) = -f.y();
Result(2, 2) = -f.z();
Result(0, 3) = -s.dot(eye);
Result(1, 3) = -u.dot(eye);
Result(2, 3) = f.dot(eye);
return Result;
}