我正在尝试使用标准轨迹球旋转围绕其原点旋转网格。每当我单击 3D 对象时,我都会从鼠标投射光线以找到交点。我测量该交点与 3D 对象原点的距离,以创建一个球体,该球体将用作该旋转中的“弧球”(直到释放鼠标)。我在每次旋转开始时这样做的原因是因为我希望单击的点保持在鼠标下方。对象旋转正确,只是旋转的幅度较小,因此单击的点不会保留在鼠标下方。以下示例尝试旋转立方体。我在纹理上绘制了一个黑色矩形来跟踪最初点击的点。这是该问题的视频:
这是根据鼠标位置和点击时计算的球体半径(arcballRadius)获取轨迹球矢量的函数(我担心这个函数没有考虑立方体对象的位置,尽管它恰好是立方体对象位于 (0,0,z):
/**
* Get a normalized vector from the center of the virtual ball O to a
* point P on the virtual ball surface, such that P is aligned on
* screen's (X,Y) coordinates. If (X,Y) is too far away from the
* sphere, return the nearest point on the virtual ball surface.
*/
glm::vec3 get_arcball_vector(double x, double y) {
glm::vec3 P = glm::vec3(x,y,0);
float OP_squared = P.x * P.x + P.y * P.y;
if (OP_squared <= arcballRadius*arcballRadius)
P.z = sqrt(arcballRadius*arcballRadius - OP_squared); // Pythagore
else
{
static int i;
std::cout << i++ << "Nearest point" << std::endl;
P = glm::normalize(P); // nearest point
}
return P;
}
每当鼠标移动
//get two vectors, one for the previous point and one for the current point
glm::vec3 va = glm::normalize(get_arcball_vector(prevMousePos.x, prevMousePos.y)); //previous point
glm::vec3 vb = glm::normalize(get_arcball_vector(mousePos.x, mousePos.y)); //current point
float angle = acos(glm::dot(va, vb)); //angle between those two vectors based on dot product
//since these axes are in camera coordinates they must be converted before applied to the object
glm::vec3 axis_in_camera_coord = glm::cross(va, vb);
glm::mat3 camera2object = glm::inverse(glm::mat3(viewMatrix) * glm::mat3(cube.modelMatrix));
glm::vec3 axis_in_object_coord = camera2object * axis_in_camera_coord;
//apply rotation to cube's matrix
cube.modelMatrix = glm::rotate(cube.modelMatrix, angle, axis_in_object_coord);
如何使单击的点保持在鼠标下方?