如何不将枢轴对齐物体中心,实现相机围绕该物体旋转
实现思路
核心逻辑非常简单:你要的效果本质是临时用选中物体作为旋转枢轴执行轨道旋转,全程不修改全局枢轴参数,旋转结束后全局枢轴仍保持原有值,自然就满足「无需将旋转枢轴移至物体中心」的要求。
你只需要在原有代码基础上做很小的改动:
- 首先在点击物体触发旋转的瞬间,新增两个仅用于本次旋转的临时变量,不要覆盖你的全局枢轴参数:
- 临时枢轴点:取选中物体的世界坐标
objWorldPos = selectedObj.position - 临时旋转距离:计算初始相机位置到该物体的直线距离
tempPivotDist = glm::length(mInitialCam.getEyePoint() - objWorldPos)
- 临时枢轴点:取选中物体的世界坐标
- 原有旋转逻辑几乎不用改,只需要把原代码中用到全局
mInitialPivotDistance的地方替换为上面的tempPivotDist,位置计算时用物体坐标当临时枢轴即可。
修改后的参考代码如下:
void HandleUICameraRotate() { // selectedObj 为选中的物体,已提前拿到其世界坐标 // 旋转开始时已提前存储 mInitialCam(初始相机位姿)、objWorldPos(选中物体世界坐标)、tempPivotDist(初始相机到物体的距离) float deltaX = (mMousePos.x - mInitialMousePos.x) / -100.0f; float deltaY = (mMousePos.y - mInitialMousePos.y) / 100.0f; // 相机方向向量 glm::vec3 mW = glm::normalize(mInitialCam.getViewDirection()); bool invertMotion = (mInitialCam.getOrientation() * mInitialCam.getWorldUp()).y < 0.0f; // 右轴向量 vec3 mU = normalize(cross(mInitialCam.getWorldUp(), mW)); if (invertMotion) { deltaX = -deltaX; deltaY = -deltaY; } // 这里把原来的mInitialPivotDistance替换为临时计算的tempPivotDist glm::vec3 rotatedVec = glm::angleAxis(deltaY, mU) * (-mInitialCam.getViewDirection() * tempPivotDist); rotatedVec = glm::angleAxis(deltaX, mInitialCam.getWorldUp()) * rotatedVec; // 这里原来的枢轴位置替换为选中物体的世界坐标objWorldPos mCamera.setEyePoint(objWorldPos + rotatedVec); mCamera.setOrientation(glm::angleAxis(deltaX, mInitialCam.getWorldUp()) * glm::angleAxis(deltaY, mU) * mInitialCam.getOrientation()); }
修改后旋转过程中,选中物体始终会保持你点击时它在屏幕上的位置,且全程不会改动你的全局相机枢轴参数,完全符合需求。
内容的提问来源于stack exchange,提问作者ashesofphoenix
相关产品推荐
相关产品推荐

