since: 2012/05/23
update: 2012/05/24
reference:
1. Nate Robins - OpenGL - Tutors
2. Loading 3D models with GLM on OpenGL
A. 說明:
1. 在此, 沿用 OpenGL: Basic Setup 所建立的專案, 只會在 main.cpp 中增加新的
程式碼.
2. 這裡將使用
Nate Robins - OpenGL - Tutors 中原始的
GLM library,
並配合
Loading 3D models with GLM on OpenGL 的例子來實作.
3. 3D Models 檔案來源:
GLM: an Alias Wavefront OBJ file library , 下載 Sample data.
----------------------------------------------------------------------------------------
B. 取得原始的 GLM library:
1. 到網站:
Nate Robins - OpenGL - Tutors 下載檔案:
Tutors source code package (tutors-src.zip 920KB).
2. 解壓縮後, 將 glm.h 與 glm.c 加到專案裡; 因為我們所建立的是
C++ 的專案,
因此將
glm.c 更名為:
glm.cpp .
--------------------------------------------------------------------------------------------
C. 加入 3D Models 檔案, 調整專案 Scheme:
1. 在專案根目錄下新增 "
objs" 資料夾, 並將之前下載的 "
3D Models 檔案",
解壓縮後將
f-16.obj 與
f-16.mtl copy 到 "
objs" 資料夾下.
2. 在專案中, 加入剛剛的
f-16.obj 與
f-16.mtl 檔案.
3. 點選專案左上方的
Scheme, 選取: "
Edit Scheme..."
接著, 先選取左邊的 "Run MyOpenGL Debug", 再選取右邊的: "Options":
勾選: Use Custom working directory: /Lanli/RD/Projects/OpenGL/MyOpenGL
> OK
----------------------------------------------------------------------------------------
D. 開啓 main.cpp 檔案, 修改如下:
#include <iostream>
//@add
#include <OpenGL/OpenGL.h> // OpenGL Library
#include <GLUT/GLUT.h> // OpenGL Utility Toolkit
#include "CallbackFunctions.h"
#include "draw.h"
/************************************/
/* start: add for loading 3d modles */
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "glm.h"
#define PI 3.1416
// variaveis
// for 位移: glTranslatef(x,y,z);
float x = 0, y = 0, z = 0;
// for 旋轉: glRotatef(angle, 1.0, 0.0, 0.0);
float angle = 0;
// OpenGL 順序的指令記錄
int displayList = 0;
// 光源位置
GLfloat lightPos[4] = {50.0, 30.0 ,0.0, 0.0};
// 環境光(暗灰色)
GLfloat lightAmb[3] = {0.114, 0.086, 0.031};
// 漫射光(亮黃色)
GLfloat lightDiff[3] = {0.976, 0.902, 0.761};
// 3D model
GLMmodel *f16;
/* end: add for loading 3d modles */
/**********************************/
// 畫出 X, Y, Z 軸
void drawAxis(void)
{
glPushAttrib(GL_CURRENT_BIT); // add: 2012/05/24
glLineWidth( 4.0f );
glBegin(GL_LINES);
// X 軸: 紅色
glColor3f(1, 0, 0);
glVertex3f(5, 0, 0);
glVertex3f(-10, 0, 0);
// Y 軸: 綠色
glColor3f(0, 1, 0);
glVertex3f(0, 10, 0);
glVertex3f(0, -5, 0);
// Z 軸: 藍色
glColor3f(0, 0, 1);
glVertex3f(0, 0, 5);
glVertex3f(0, 0, -10);
// 將顏色恢復為白色
//glColor3f(1, 1, 1);
glEnd();
glPopAttrib(); // add: 2012/05/24
}
// 鍵盤事件
void myKeyboard(unsigned char key, int xx, int yy) {
switch(key) {
// 位移: glTranslatef(x,y,z);
case 'a' : x -= 2; break; // 往負 X 軸移動 2 單位.
case 'd' : x += 2; break; // 往正 X 軸移動 2 單位.
case 's' : z += 2; break; // 往正 Z 軸移動 2 單位.
case 'w' : z -= 2; break; // 往負 Z 軸移動 2 單位.
case '.' : y -= 2; break; // 往負 Y 軸移動 2 單位.
case ',' : y += 2; break; // 往正 Y 軸移動 2 單位.
// 旋轉: glRotatef(angle, 1.0, 0.0, 0.0);
case 'k' : angle -= 2.0; break; // 往正 X 軸旋轉角度減少 2 單位.(順時針)
case 'i' : angle += 2.0; break; // 往正 X 軸旋轉角度增加 2 單位.(逆時針)
case 27 : exit(0); // esc 離開
}
// refresh the screen
glutPostRedisplay();
}
// 更新視窗
void changeSize(int w, int h) {
if(h == 0) h = 1;
float ratio = 1.0* w / h;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glViewport(0, 0, w, h);
gluPerspective(25, ratio, 1, 1000);
glMatrixMode(GL_MODELVIEW);
}
// drawing
void renderScene(void) {
// 畫布背景顏色: 水藍
glClearColor(0.473f, 0.633f, 0.742f, 0.0f);
// clear the color and depth buffers
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
gluLookAt(15.0, 30.0, 15.0, // eye position
0.0, 5.0, 0.0, // look at this point
0.0f, 1.0f, 0.0f); // "up" vector
// 畫出 X, Y, Z 軸
drawAxis();
// 設定光線
glLightfv(GL_LIGHT0, GL_AMBIENT, lightAmb); // 環境光
glLightfv(GL_LIGHT0, GL_DIFFUSE, lightDiff); // 漫射光
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
// 位移
glTranslatef(x,y,z);
// 旋轉
glRotatef(angle, 1.0, 0.0, 0.0);
glCallList(displayList);
// swap the double buffer
glutSwapBuffers();
}
// main function for loading 3d models
int main(int argc, char * argv[])
{
// Init glut
glutInit(&argc, argv);
// Display mode
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
// Init Window
glutInitWindowPosition(100,100);
glutInitWindowSize(800,600);
glutCreateWindow("Loading 3D Models");
// Callback Functions Registration
glutDisplayFunc(renderScene);
glutKeyboardFunc(myKeyboard);
glutIdleFunc(renderScene);
glutReshapeFunc(changeSize);
// enable settings
glLightfv(GL_LIGHT0, GL_POSITION, lightPos);
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_COLOR_MATERIAL);
// Loading Model
f16 = (GLMmodel*)malloc(sizeof(GLMmodel));
f16 = glmReadOBJ((char *)"objs/f-16.obj");
displayList = glGenLists(1);
glNewList(displayList, GL_COMPILE);
//glmList(f16, GLM_SMOOTH);
glmDraw(f16, GLM_SMOOTH);
glEndList();
// enter event processing loop
glutMainLoop();
return 0;
}
----------------------------------------------------------------------------------------
E. 分析專案內容:
1. 執行 "Product" > "Analyze":
2. 修正相關錯誤:
a. 發現錯誤訊息:
glm.cpp => Conversion from string literal to 'char *' is deprecated
b. 修正: 開啓 glm.cpp 檔案, 修改如下:
// line: 448
/* make a default group */
//group = glmAddGroup(model, "default");
//@fixed: Conversion from string literal to 'char *' is deprecated
group = glmAddGroup(model, (char *)"default");
----------------------------------------------------------------------------------------
F. 編譯並執行:
說明: 1. 三軸: X 軸紅色, Y 軸綠色, Z 軸藍色.
2. "位移" 按鍵功能: // glTranslatef(x,y,z);
a: 往負 X 軸移動 2 單位.
d: 往正 X 軸移動 2 單位.
s: 往正 Z 軸移動 2 單位.
w: 往負 Z 軸移動 2 單位.
.: 往負 Y 軸移動 2 單位.
,: 往正 Y 軸移動 2 單位.
3. "旋轉" 按鍵功能: // glRotatef(angle, 1.0, 0.0, 0.0);
k: 往正 X 軸旋轉角度減少 2 單位.(順時針)
i: 往正 X 軸旋轉角度增加 2 單位.(逆時針)
4. "離開" 按鍵功能:
esc: 離開