OpenGL 3D 漫游實現:鍵盤控制視角移動與旋轉完整指南
核心原理:gluLookAt 視圖矩陣
void gluLookAt(GLdouble eyex, GLdouble eyey, GLdouble eyez,
GLdouble centerx, GLdouble centery, GLdouble centerz,
GLdouble upx, GLdouble upy, GLdouble upz);
- Eye (eyex, eyey, eyez):攝像機/眼睛在世界坐標系中的位置。
- Center (centerx, centery, centerz):攝像機看向的目標點位置。
- Up (upx, upy, upz):攝像機「頭頂」朝向,決定畫面旋轉方向 (通常
0,1,0 表示 Y 軸向上)。
漫游本質:根據用戶輸入實時修改 Eye 和 Center,重繪場景。
算法設計:極坐標控制
將攝像機水平旋轉映射為角度 angle,半徑 R 固定:
Center.x = Eye.x + R * sin(rad)
Center.z = Eye.z - R * cos(rad) (OpenGL 右手坐標系,Z 軸向內)
rad = angle * PI / 180.0 角度轉弧度。
鍵盤交互邏輯
| 按鍵 | 動作 | 數學實現 |
| ↑ 前進 | 沿視線方向移動 | Eye.x += speed * sin(rad); Eye.z -= speed * cos(rad); |
| ↓ 後退 | 沿視線反方向移動 | Eye.x -= speed * sin(rad); Eye.z += speed * cos(rad); |
| ← 左轉 | 減小水平角度 | angle -= turn_speed; rad = angle * PI/180; |
| → 右轉 | 增加水平角度 | angle += turn_speed; rad = angle * PI/180; |
核心代碼框架
#define PI 3.141592653
#define R 100.0f
static GLfloat eye[] = {0, 0, 1}; // 初始位置
static GLfloat center[] = {0, 0, 0}; // 初始看向原點
static GLfloat angle = 0.0f; // 水平旋轉角度
float speed = 0.1f; // 移動速度
void update_view() {
float rad = angle * PI / 180.0f;
center[0] = eye[0] + R * sin(rad);
center[2] = eye[2] - R * cos(rad);
center[1] = eye[1]; // Y 不變
gluLookAt(eye[0], eye[1], eye[2],
center[0], center[1], center[2],
0.0, 1.0, 0.0);
}
void keyboard_handler(int key) {
float rad = angle * PI / 180.0f;
switch (key) {
case VK_UP:
eye[0] += speed * sin(rad);
eye[2] -= speed * cos(rad);
break;
case VK_DOWN:
eye[0] -= speed * sin(rad);
eye[2] += speed * cos(rad);
break;
case VK_LEFT:
angle -= 0.1f;
break;
case VK_RIGHT:
angle += 0.1f;
break;
}
update_view();
glutPostRedisplay(); // 請求重繪
}
進階優化建議
- 幀率無關移動:用
delta_time 乘速度,保證不同性能硬件上移動速度一致。
- 俯仰角控制:添加
pitch 角控制上下視角,需限制範圍 (如 -89°~89°) 避免萬向鎖。
- 碰撞檢測:移動前檢測新位置是否穿模,配合場景包圍盒/導航網格。
- 平滑插值:目標位置/角度與當前值線性插值 (
lerp) 實現平滑過渡。
- 現代 OpenGL:棄用
gluLookAt,手動構建 View 矩陣 (glm::lookAt) 傳遞給 Shader Uniform。
- 上一篇文章: C語言遞歸實現冪函數:n^k 計算與靜態變量陷阱
- 下一篇文章: C語言深度解析:手把手教你實現 memcmp 並辨析 strcmp、strncmp 差異
Copyright ©
程式碼之家 All Rights Reserved