天天看點

GLFW+OpenGL三維空間旋轉模型的算法

在三維軟體中,用滑鼠控制三維模型旋轉是很必要的,可以友善使用者觀察模型,具有諸多優勢,那麼如何實作呢?

有兩種方案,一種是控制模型旋轉,這種方法将着色器中的model進行旋轉變換即可;另一種是旋轉攝像頭,這種方法其實利用了相對運動的原理,要讓模型旋轉,其實也就是讓觀察者在以機器人模型為原點的球面坐标系中運動,當然運動之後,觀察者也要旋轉相應的角度。

GLFW+OpenGL三維空間旋轉模型的算法
GLFW+OpenGL三維空間旋轉模型的算法

這樣一看是第一種方法簡單,但是當模型位置不能動時(如要進行仿真,模型有确定的坐标),移動觀察者變成唯一的選擇。

要實作旋轉三維模型,第一步是定義一個滑鼠的回報函數,這個函數要将滑鼠在螢幕中橫向移動值轉換為方位角,縱向移動值轉換為天頂角,函數的調用需要按鈕回報函數以及滑鼠移動函數的輔助。

按下滑鼠右鍵的回報:

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度,讓選擇連續。

繼續閱讀