为何glm::make_mat4无法正常工作?附自定义aLookAt函数代码
问题分析与解决
你的aLookAt函数配合glm::make_mat4失效,主要是矩阵存储顺序不匹配和矩阵未完整初始化这两个核心问题导致的,下面具体拆解并给出修复方案:
核心问题1:行主序 vs 列主序的存储差异
GLM的mat4采用列主序存储(这是OpenGL的标准存储方式),但你手动创建的Matrix[4][4]是按行主序来赋值的——直接把这个二维数组传给glm::make_mat4,会导致矩阵元素的顺序完全错乱。
举个直观的例子:
你代码里把X向量的分量放在Matrix[0][0]、Matrix[1][0]、Matrix[2][0](对应矩阵的第一列、各行元素),但make_mat4会把这些值解析为矩阵的第一行、各列元素,相当于把整个矩阵转置了,最终生成的观察矩阵自然无法正确工作。
核心问题2:矩阵未完整初始化
你的代码里Matrix[0][2]...没有写完,而且矩阵的第四行元素(应该是0, 0, 0, 1)也没有赋值。未初始化的内存会包含随机垃圾值,这也会导致make_mat4生成错误的矩阵。
修复方案
方案1:直接构造GLM矩阵(推荐)
完全避开手动数组操作,直接用GLM的API构造矩阵,既简洁又不会出错:
glm::mat4 aLookAt(const glm::vec3& Eye, const glm::vec3& Center, const glm::vec3& Up) { glm::vec3 Z = glm::normalize(Eye - Center); glm::vec3 X = glm::normalize(glm::cross(Up, Z)); glm::vec3 Y = glm::normalize(glm::cross(Z, X)); // 按列填充观察矩阵的旋转部分 glm::mat4 viewMatrix; viewMatrix[0] = glm::vec4(X, 0.0f); // 第一列 viewMatrix[1] = glm::vec4(Y, 0.0f); // 第二列 viewMatrix[2] = glm::vec4(Z, 0.0f); // 第三列 viewMatrix[3] = glm::vec4(0.0f, 0.0f, 0.0f, 1.0f); // 第四列(初始平移为0) // 叠加平移分量:将相机原点移到世界原点 viewMatrix = viewMatrix * glm::translate(glm::mat4(1.0f), -Eye); return viewMatrix; }
方案2:手动按列主序填充数组
如果你坚持要用glm::make_mat4,需要把数组按列主序排列(即先填第一列的所有元素,再填第二列,以此类推):
glm::mat4 aLookAt(const glm::vec3& Eye, const glm::vec3& Center, const glm::vec3& Up) { glm::vec3 Z = glm::normalize(Eye - Center); glm::vec3 X = glm::normalize(glm::cross(Up, Z)); glm::vec3 Y = glm::normalize(glm::cross(Z, X)); float matrixData[16]; // 列主序的一维数组 // 第一列 matrixData[0] = X.x; matrixData[1] = X.y; matrixData[2] = X.z; matrixData[3] = 0.0f; // 第二列 matrixData[4] = Y.x; matrixData[5] = Y.y; matrixData[6] = Y.z; matrixData[7] = 0.0f; // 第三列 matrixData[8] = Z.x; matrixData[9] = Z.y; matrixData[10] = Z.z; matrixData[11] = 0.0f; // 第四列(平移分量) matrixData[12] = -glm::dot(X, Eye); matrixData[13] = -glm::dot(Y, Eye); matrixData[14] = -glm::dot(Z, Eye); matrixData[15] = 1.0f; return glm::make_mat4(matrixData); }
内容的提问来源于stack exchange,提问作者user8539043
相关产品推荐
相关产品推荐

