如何实现适配Entity类的vec3旋转向量版glm::lookat功能
解决方案:直接计算相机朝向的欧拉角(vec3)
不用从glm::lookAt的矩阵逆向提取旋转信息,直接根据输入参数计算对应Entity所需的orientation(欧拉角向量),避免复杂的矩阵逆运算。
核心思路
glm::lookAt的本质是通过相机位置、目标点、上方向构建正交的相机坐标系,我们可以直接从这个坐标系推导欧拉角,完全复刻lookAt的朝向逻辑。
实现步骤与代码
1. 计算正交坐标系向量
先推导相机的前向、右向、校正上向向量,确保三者严格正交:
glm::vec3 calculateCameraOrientation(glm::vec3 eye, glm::vec3 center, glm::vec3 up) { // 计算相机前向向量(指向目标点,glm右手系中相机前向对应世界空间-z方向) glm::vec3 forward = glm::normalize(center - eye); // 处理极端情况:当up向量与前向向量共线时,重置为默认Y轴上方向 if (glm::length(glm::cross(forward, up)) < 1e-6f) { up = glm::vec3(0.0f, 1.0f, 0.0f); } // 计算右向向量 glm::vec3 right = glm::normalize(glm::cross(forward, glm::normalize(up))); // 校正上向向量,确保与前向、右向完全正交 glm::vec3 correctedUp = glm::normalize(glm::cross(right, forward));
2. 转欧拉角适配Entity架构
根据正交向量构建旋转矩阵,再转换为与EntitygetMatrix()匹配的欧拉角:
// 构建本地空间到世界空间的旋转矩阵(列向量对应右、上、反向前向) glm::mat4 rotationMat(1.0f); rotationMat[0] = glm::vec4(right, 0.0f); rotationMat[1] = glm::vec4(correctedUp, 0.0f); rotationMat[2] = glm::vec4(-forward, 0.0f); // 反向前向匹配glm相机的-z前向规则 // 旋转矩阵转四元数,再转欧拉角(弧度) glm::quat rotQuat = glm::quat_cast(rotationMat); glm::vec3 orientation = glm::eulerAngles(rotQuat); return orientation; }
关键注意事项
- 旋转顺序匹配:必须保证欧拉角的旋转顺序与Entity
getMatrix()生成旋转矩阵的顺序一致(glm默认是YXZ顺序,即先绕Y轴偏航,再绕X轴俯仰,最后绕Z轴滚转),否则生成的矩阵会和glm::lookAt结果不符。 - 单位转换:返回的欧拉角是弧度,若Entity的orientation存储为角度,需要用
glm::degrees()转换。 - 浮点精度:极端场景下的阈值(1e-6f)可根据项目精度需求调整。
验证方法
将计算出的orientation赋值给相机Entity的orientation属性,设置position为eye,调用getMatrix()后取其逆矩阵,结果应与glm::lookAt(eye, center, up)的输出在浮点精度范围内完全一致。
内容的提问来源于stack exchange,提问作者Bob
相关产品推荐
相关产品推荐

