在三維軟體中,用滑鼠控制三維模型旋轉是很必要的,可以友善使用者觀察模型,具有諸多優勢,那麼如何實作呢?
有兩種方案,一種是控制模型旋轉,這種方法将着色器中的model進行旋轉變換即可;另一種是旋轉攝像頭,這種方法其實利用了相對運動的原理,要讓模型旋轉,其實也就是讓觀察者在以機器人模型為原點的球面坐标系中運動,當然運動之後,觀察者也要旋轉相應的角度。
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsISN2UTOzgDN2EzMwQDM4EDMy8CX0Vmbu4GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.jpg)
這樣一看是第一種方法簡單,但是當模型位置不能動時(如要進行仿真,模型有确定的坐标),移動觀察者變成唯一的選擇。
要實作旋轉三維模型,第一步是定義一個滑鼠的回報函數,這個函數要将滑鼠在螢幕中橫向移動值轉換為方位角,縱向移動值轉換為天頂角,函數的調用需要按鈕回報函數以及滑鼠移動函數的輔助。
按下滑鼠右鍵的回報:
void mouse_button_callback(GLFWwindow* window, int button, int action, int mods)
{
if (action == GLFW_PRESS) switch(button)
{
case GLFW_MOUSE_BUTTON_RIGHT:
glfwSetCursorPosCallback(window, mouse_callback2);
break;
default:
return;
}
if (action != GLFW_PRESS)
glfwSetCursorPosCallback(window, mouse_callback1);
return;
}
void mouse_callback2(GLFWwindow* window, double xpos, double ypos)
{
if (firstMouse)
{
lastX = xpos;
lastY = ypos;
firstMouse = false;
}
float xoffset = 0.1*(xpos - lastX);
float yoffset = 0.1*(lastY - ypos); // reversed since y-coordinates go from bottom to top
lastX = xpos;
lastY = ypos;
//camera.ProcessMouseMovement(xoffset, yoffset);
float r = sqrt(camera.Position.x * camera.Position.x + camera.Position.y * camera.Position.y + camera.Position.z * camera.Position.z);
float x,y,z,afa,fi;
if(camera.Position.x>=0)
{
afa = atan(camera.Position.z/camera.Position.x);
}
else
{
afa = atan(camera.Position.z/camera.Position.x)+3.1415926;
}
if(camera.Position.y>0)
{
fi = atan(camera.Position.x/(camera.Position.y*cos(afa)));
}
else
{
fi = atan(camera.Position.x/(camera.Position.y*cos(afa)))+3.1415926;
}
x = r*sin(fi+(yoffset)/180.0f*3.1415926)*cos(afa+(xoffset)/180.0f*3.1415926);
y = r*cos(fi+(yoffset)/180.0f*3.1415926);
z = r*sin(fi+(yoffset)/180.0f*3.1415926)*sin(afa+(xoffset)/180.0f*3.1415926);
camera.update(glm::vec3(x, y, z),glm::vec3(0.0f, 1.0f, 0.0f), -90.0f+afa/3.1415926*180.0+xoffset-83.6598f, 0.0f+fi/3.1415926*180.0+yoffset-69.7911f);
}
firstMouse提前設為true。
afa、fi是原始位置對應的方位角和天頂角,由于存在tan的反三角函數,需要讨論正負,并在值發生跳躍的時候補上180度,讓選擇連續。