如何在OpenGL中旋转向量?GLM自定义旋转轴API咨询
绕任意点旋转的实现方法(GLM)
GLM本身没有直接提供绕任意点旋转的单一API,但你可以通过平移-旋转-平移的矩阵组合来实现这个需求,这是3D变换中的标准做法。
核心原理
绕任意点P旋转的本质是把旋转操作“挪”到原点上完成,再还原回去:
- 先平移整个坐标系,让旋转中心
P移动到原点(这样就能用glm::rotate处理绕原点的轴旋转) - 执行绕目标轴的旋转操作
- 把坐标系平移回原来的位置,完成最终旋转
具体实现步骤
假设你要:
- 旋转中心:
glm::vec3 pivot = glm::vec3(0, 4, 0)(你指定的点) - 旋转轴:
glm::vec3 axis = glm::vec3(0, 1, 0)(Y轴,和你之前的例子一致) - 旋转角度:
float angle = glm::radians(180.0f) - 待旋转的点:
glm::vec3 model = glm::vec3(5, 0, 0)
按照以下步骤构建变换矩阵并应用:
- 构建平移到原点的矩阵:
glm::mat4 translateToOrigin = glm::translate(glm::mat4(1.0f), -pivot); - 构建旋转矩阵:
glm::mat4 rotateMat = glm::rotate(glm::mat4(1.0f), angle, axis); - 构建平移回原位置的矩阵:
glm::mat4 translateBack = glm::translate(glm::mat4(1.0f), pivot); - 组合变换矩阵(注意顺序:先平移到原点,再旋转,最后平移回去):
glm::mat4 transform = translateBack * rotateMat * translateToOrigin; - 应用变换到你的点:
glm::vec4 transformed = transform * glm::vec4(model, 1.0f); glm::vec3 result = glm::vec3(transformed.x, transformed.y, transformed.z);
关于你的例子的说明
按照上面的代码,用pivot=(0,4,0)旋转后,(5,0,0)会变成(-5,0,0)——这是因为旋转中心在Y轴上,绕Y轴旋转时,X-Z平面上的点到旋转中心的距离决定了旋转后的位置。
如果你想要得到(3,0,0),说明你的旋转中心应该是(4,4,0)(因为(5,0,0)和(3,0,0)的中点是(4,0,0),加上Y轴的4就是(4,4,0))。把pivot改成glm::vec3(4,4,0),运行上面的代码就能得到你想要的结果。
封装成工具函数
如果你经常需要这个操作,可以封装成一个工具函数,方便调用:
// 针对模型矩阵的版本(适合场景物体旋转) glm::mat4 rotateAroundPivot(glm::mat4 modelMat, float angle, glm::vec3 axis, glm::vec3 pivot) { glm::mat4 translateToOrigin = glm::translate(glm::mat4(1.0f), -pivot); glm::mat4 rotateMat = glm::rotate(glm::mat4(1.0f), angle, axis); glm::mat4 translateBack = glm::translate(glm::mat4(1.0f), pivot); return translateBack * rotateMat * translateToOrigin * modelMat; } // 针对单个点的版本 glm::vec3 rotatePointAroundPivot(glm::vec3 point, float angle, glm::vec3 axis, glm::vec3 pivot) { glm::mat4 transform = glm::translate(glm::mat4(1.0f), pivot) * glm::rotate(glm::mat4(1.0f), angle, axis) * glm::translate(glm::mat4(1.0f), -pivot); return glm::vec3(transform * glm::vec4(point, 1.0f)); }
内容的提问来源于stack exchange,提问作者Kevin Su
相关产品推荐
相关产品推荐

