Opengl GLM:旋转网格时如何保持鼠标下的同一点?

Opengl GLM:旋转网格时如何保持鼠标下的同一点?,opengl,graphics,3d,mesh,glm-math,Opengl,Graphics,3d,Mesh,Glm Math,我试图通过单击网格来旋转网格(但不是传统的)。其思想是,当您单击并拖动鼠标时,您单击的网格上的点将绝对保留在鼠标下(网格将围绕其原点旋转)。不幸的是,按照我现在的方式,当鼠标移动时,点击的点不会停留在鼠标下 为了投射光线并查看其是否与网格相交,我按以下方式计算鼠标世界坐标: //mousePos is normalized -1 .. 1 glm::vec4 mouse_clip = vec4(mousePos.x,mousePos.y,0

我试图通过单击网格来旋转网格(但不是传统的)。其思想是,当您单击并拖动鼠标时,您单击的网格上的点将绝对保留在鼠标下(网格将围绕其原点旋转)。不幸的是,按照我现在的方式,当鼠标移动时,点击的点不会停留在鼠标下

为了投射光线并查看其是否与网格相交,我按以下方式计算鼠标世界坐标:

                           //mousePos is normalized -1 .. 1
 glm::vec4 mouse_clip = vec4(mousePos.x,mousePos.y,0,1);
 glm::vec4 mouse_world = glm::inverse(viewMatrix) * glm::inverse(projectionMatrix) * mouse_clip;
用于测试鼠标的光线是否与网格相交的代码工作正常。当我旋转时问题就开始了。这是一张解释旋转算法的图表。在下图中,假设您正在从顶部查看3d场景:

我存储第一次单击与网格相交的世界坐标,然后在鼠标移动时通过平移该点获得第二个点。从茶壶原点到第一次单击的向量为v1,到第二个点的向量为v2

通过做一个v1 x v2的叉积,我得到了旋转轴。 通过做v1点v2,我得到了它们之间夹角的余弦。我使用glm::acos查找角度(以弧度为单位?)

以下是鼠标移动后立即计算旋转的代码:

//this is a function that receives a vec3 translation. 
//Translation is a vector that describes the translation of the mouse
//in world coordinates (as calculated earlier).

//pick up teapot position from the model matrix
//it will serve as origin of the 2 vectors
vec3 origin = vec3(modelMatrix[3]);

//translate the point the mesh was hit previously
//by the same amount the mouse moved (normally no Z translation)
vec3 newPoint = previousPoint + translation;

vec3 v1 = glm::normalize(previousPoint - origin);  //unit vector from teapot center to first point
vec3 v2 = glm::normalize(newPoint - origin);   //unit vector from teapot center to translated point

vec3 axis = glm::normalize(glm::cross(v1,v2));  //find rotation axis
float angle = glm::acos(glm::dot(v1,v2));       //find rotation angle

modelMatrix = glm::rotate(modelMatrix,angle,axis); //rotate the modelMatrix accordingly

//store point for next mouse movement
previousPoint = newPoint;
但是,当我移动鼠标时,发生的旋转比应该发生的旋转小。单击的点不会停留在鼠标下。下面是一段关于这个问题的视频:


如何使单击的点保持在鼠标下方?

第二个点(V2)不应使用光线投射,而应在仍处于鼠标下方时将其设置为与V1中心相同的距离

从概念上讲,将弧球半径=
dist(center,V1)
和光线投射V2置于其上。(光线-球体相交解决方案可用)


除此之外,我发现您可以执行
glm::normalize(glm::fquat(1+glm::dot(v1,v2),glm::cross(v1,v2))
在不影响
acos
和轴角度的情况下获得旋转(无论如何,这将立即产生
cos

V2与中心的距离应与V1(预标准化)相同,因为它是V1的终点at@ratchetfreak如果它们都要正常化,为什么它们需要有相同的距离?如果图表不清楚,我很抱歉。没有第二个光线投射。第二个点是通过平移第一个点来获得的,第一个点等于鼠标指针在world coords中的移动。这是你的问题,旋转后V1应该在V2点结束,但是如果你只是平行于屏幕平移,这是不可能发生的。使用更传统的弧球方法得到V2,将球体的半径调整为V1将解决这个问题。