2012年5月23日 星期三

OpenGL: Loading 3D Models

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.hglm.c 加到專案裡; 因為我們所建立的是 C++ 的專案,
          因此將 glm.c 更名為: glm.cpp .

--------------------------------------------------------------------------------------------

C. 加入 3D Models 檔案, 調整專案 Scheme:
     1. 在專案根目錄下新增 "objs" 資料夾, 並將之前下載的 "3D Models 檔案",
         解壓縮後將 f-16.objf-16.mtl copy 到 "objs" 資料夾下.

     2. 在專案中, 加入剛剛的 f-16.objf-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: 離開
  

沒有留言:

張貼留言

注意:只有此網誌的成員可以留言。