最近,我想实现交互式旋转操作,就像在meshlab中一样:
基本上,它实现了三个自由度的旋转。我在GLFW的帮助下将这些操作可视化为以下代码:
static void mouse_move_callback(GLFWwindow* window, double xpos, double ypos){
...
do{
//perform rotation operations only if keeping the right mouse key pressed
if(glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_RIGHT) == GLFW_RELEASE) {
g_clr_right_mouse = true;
break;
}
/*clear mouse state once transferred from release state
to pressed state to prevent from a instant flicker*/
if(g_clr_right_mouse){
g_lastX = xpos;
g_lastY = ypos;
g_clr_right_mouse = false;
}
float xoffset = xpos - g_lastX; //let movement from down to top positive
float yoffset = g_lastY - ypos;
g_lastX = xpos;
g_lastY = ypos;
//do counterclockwise rotation around x-asis with movement in y direction
glm::mat4 r1 = glm::rotate(glm::mat4(), glm::radians(-yoffset * 0.5f), glm::vec3(1.0f,0.0f,0.0f));
//do counterclockwise rotation around y-asis with movement in x direction
glm::mat4 r2 = glm::rotate(glm::mat4(), glm::radians( xoffset * 0.5f), glm::vec3(0.0f,1.0f,0.0f));
glm::mat4 tmp = r2 * r1 * g_model;
for(int i=0; i<3; i++)
g_model[i] = tmp[i];
return ;
}while(false);
}
这些代码都在这里,整个项目可以在here中找到,可以下载构建,最后执行如下:
但是,我的实现只能实现2个DOF的旋转操作,我添加了一个键盘回调函数来实现绕z轴的旋转:
void keyboard_callback(GLFWwindow* window, int key, int scancode, int action, int mod){
if(glfwGetKey(window, GLFW_KEY_LEFT) == GLFW_PRESS){
glm::mat4 r3 = glm::rotate(glm::mat4(), glm::radians(3.0f), glm::vec3(0,0,1.0f));
glm::mat4 tmp = r3 * g_model;
for(int i=0; i<3; i++)
g_model[i] = tmp[i];
}else if(glfwGetKey(window, GLFW_KEY_RIGHT) == GLFW_PRESS){
glm::mat4 r3 = glm::rotate(glm::mat4(), glm::radians(-3.0f), glm::vec3(0,0,1.0f));
glm::mat4 tmp = r3 * g_model;
for(int i=0; i<3; i++)
g_model[i] = tmp[i];
}
}
因此,我的问题是如何体面地实现交互式旋转操作的三个自由度只与鼠标移动?
2条答案
按热度按时间jpfvwuh41#
当拖动鼠标时,对象必须绕着垂直于鼠标移动方向的轴旋转。枢轴是模型的原点。
在视图的XY平面上将鼠标移动矢量旋转90 °。由于这是视图空间中的矢量,因此必须将该矢量从视图空间转换到世界空间。将矢量从视图空间转换到世界空间的矩阵是视图矩阵左上方3x3的逆矩阵:
第一个
创建一个围绕轴的旋转矩阵。Angular 取决于矢量的长度(
height
是以像素为单位的视口高度):拖动鼠标时计算旋转矩阵。拖动结束后将旋转矩阵与模型矩阵连接:
模型矩阵是
drag_rotation
和model_rotation
的级联:另请参阅环转
完整示例:
atmip9wb2#
你需要把球画出来才能让它直观。
当鼠标按下时,您在鼠标指针正下方的球上放置一个锚。如果单击是在球的外部,则使用球上最近的点。
当鼠标移动时,您可以旋转球,使锚点沿着最短路径移动,从而使其保持在鼠标指针的正下方。如果鼠标指针离开球,则使用球上最近的点。
也许this会有帮助。