2012年4月4日 星期三

OpenGL ES 入門: 二. 簡單繪圖之五

since: 2012/04/04
update: 2012/04/04

reference:
1. 原文:
iPhone Development: OpenGL ES From the Ground Up, Part 2: A Look at Simple Drawing

2. 翻譯:
從零開始學習OpenGL ES之二 – 簡單繪圖概述


簡單繪圖之五: 繪製二十面體

A. 說明
      當處理複雜的幾何體時, 有一種方法可以避免多次傳遞同一個頂點, 就是使用通過
      頂點對應於頂點陣列中的索引的方法, 此方法稱之為元素 (elements).

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

B. 繪製多面體的前置作業
     1. 開啓 GLView.h 檔案, 修改如下:
....
@protocol GLViewDelegate

@required
- (void)setupView:(GLView *)view;

@optional
//@update for drawing
- (void)drawView:(GLView *)view;
- (void)drawTriangle3D; // 畫三角形
- (void)drawSquare; // 畫正方形
- (void)drawVertexColor; // 畫頂點顏色
- (void)drawIcosahedron; // 畫二十面體

@end

     2. 開啓 ViewController.m 檔案, 修改如下:
....
// 畫二十面體
- (void)drawIcosahedron
{
    NSLog(@"ViewController => drawIcosahedron");
    // Draw code here
}
....

     3. 開啓 GLView.m 檔案, 修改如下:
....
- (void)drawView
{
....
    //@update for drawing
    //[self.delegate drawTriangle3D]; // 畫三角形
    //[self.delegate drawSquare]; // 畫正方形
    //[self.delegate drawVertexColor]; // 畫頂點顏色
    [self.delegate drawIcosahedron]; // 畫二十面體
....
    //@add for Rendering Frequency
    int intCount = [self.currentRunCount intValue] + 1;
    self.currentRunCount = [NSNumber numberWithInt:intCount];
   
    if (intCount >= self.totalRunTime * kRenderingFrequency) {

        [self stopAnimation];
    }
    //@update for run once
    //[self stopAnimation];
}
....

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

C. 開啓 ViewController.m 檔案, 修改如下:
....
// 畫二十面體
- (void)drawIcosahedron
{
    NSLog(@"ViewController => drawIcosahedron");
    // Draw code here
    //@update
    //
    // 1. 建立了一個靜態變數來跟蹤物體的旋轉
    static GLfloat rot = 0.0;
   
    // This is the same result as using Vertex3D, just faster to type and
    // can be made const this way
    //
    // 2. 定義頂點陣列:
    //
    // 使用了一個與前不同的方法, 但結果是一樣的. 由於我們的幾何體根本不會變化,
    // 所以我們將其定義為 const, 這樣就不需要每一 frame 都分配/清除記憶體:
    static const Vertex3D vertices[]= {
        {0, -0.525731, 0.850651},             // vertices[0]
        {0.850651, 0, 0.525731},              // vertices[1]
        {0.850651, 0, -0.525731},             // vertices[2]
        {-0.850651, 0, -0.525731},            // vertices[3]
        {-0.850651, 0, 0.525731},             // vertices[4]
        {-0.525731, 0.850651, 0},             // vertices[5]
        {0.525731, 0.850651, 0},              // vertices[6]
        {0.525731, -0.850651, 0},             // vertices[7]
        {-0.525731, -0.850651, 0},            // vertices[8]
        {0, -0.525731, -0.850651},            // vertices[9]
        {0, 0.525731, -0.850651},             // vertices[10]
        {0, 0.525731, 0.850651}               // vertices[11]
    };
   
    // 3. 建立一個顏色陣列:
    //
    // 創建一個 Color3D 物件陣列, 每項對應於前一個陣列的頂點:
    static const Color3D colors[] = {
        {1.0, 0.0, 0.0, 1.0},
        {1.0, 0.5, 0.0, 1.0},
        {1.0, 1.0, 0.0, 1.0},
        {0.5, 1.0, 0.0, 1.0},
        {0.0, 1.0, 0.0, 1.0},
        {0.0, 1.0, 0.5, 1.0},
        {0.0, 1.0, 1.0, 1.0},
        {0.0, 0.5, 1.0, 1.0},
        {0.0, 0.0, 1.0, 1.0},
        {0.5, 0.0, 1.0, 1.0},
        {1.0, 0.0, 1.0, 1.0},
        {1.0, 0.0, 0.5, 1.0}
    };
   
    // 4. 建立二十面體:
    //
    // 上述十二個頂點本身並未描述形狀. OpenGL 需要知道怎樣將它們聯繫在一起,
    // 所以我們建立了一個整數陣列 (GLubyte) 指向構成各三角形的頂點.
    //
    // 二十面體的第一個面的三個數是 1,2,6 代表繪製處於索引1 (0.850651, 0, 0.525731),
    // 2 (0.850651, 0, 0.525731), 和 6 (0.525731, 0.850651, 0) 之間的三角形.
    static const GLubyte icosahedronFaces[] = {
        1, 2, 6,
        1, 7, 2,
        3, 4, 5,
        4, 3, 8,
        6, 5, 11,
        5, 6, 10,
        9, 10, 2,
        10, 9, 3,
        7, 8, 9,
        8, 7, 0,
        11, 0, 1,
        0, 11, 4,
        6, 2, 10,
        1, 6, 11,
        3, 5, 10,
        5, 4, 11,
        2, 7, 9,
        7, 1, 0,
        3, 9, 8,
        4, 8, 0,
    };
   
    // 5.
    //
    // 加載單元矩陣
    glLoadIdentity();
   
    // 移動
    glTranslatef(0.0f,0.0f,-3.0f);
   
    // 旋轉
    glRotatef(rot,1.0f,1.0f,1.0f);
   
    // 設置背景色
    glClearColor(0.7, 0.7, 0.7, 1.0);
   
    // 清除緩存
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
   
    // 啟動頂點陣列
    glEnableClientState(GL_VERTEX_ARRAY);
   
    // 啟動顏色陣列
    glEnableClientState(GL_COLOR_ARRAY);
   
    // 提供頂點陣列內容給 OpenGL
    glVertexPointer(3, GL_FLOAT, 0, vertices);
   
    // 提供顏色陣列內容給 OpenGL
    glColorPointer(4, GL_FLOAT, 0, colors);
   
   
    // 6. 不使用 glDrawArrays(), 而是使用 glDrawElements():
    //
    // 備註: 如果你按繪製的正確次序提供頂點, 那麼你應該使用 glDrawArrays(),
    //           但是如果你提供一個陣列然後用另一個以索引值區分頂點次序的陣列的話,
    //           那麼你應該使用 glDrawElements().
    glDrawElements(GL_TRIANGLES, 60, GL_UNSIGNED_BYTE, icosahedronFaces);
   
    // 7. 執行禁止功能
    glDisableClientState(GL_VERTEX_ARRAY);
    glDisableClientState(GL_COLOR_ARRAY);
   
    // 8. 根據上一個 frame 繪製的時間增加旋轉變量值:
    static NSTimeInterval lastDrawTime;
    if (lastDrawTime)
    {
        NSTimeInterval timeSinceLastDraw = [NSDate timeIntervalSinceReferenceDate] - lastDrawTime;

        rot += 50 * timeSinceLastDraw;
    }
    lastDrawTime = [NSDate timeIntervalSinceReferenceDate];
}
....

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

D. 編譯並執行
      漂亮旋轉的二十面體


沒有留言:

張貼留言

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