2013年8月29日 星期四

Rendering 3D Anaglyph in OpenGL - 6

since: 2013/08/26
update: 2013/08/29

reference:
0. 原文: Rendering 3D Anaglyph in OpenGL
1. I touchs: Rendering 3D Anaglyph in OpenGL - 1
2. I touchs: Rendering 3D Anaglyph in OpenGL - 2
3. I touchs: Rendering 3D Anaglyph in OpenGL - 3
4. I touchs: Rendering 3D Anaglyph in OpenGL - 4
5. I touchs: Rendering 3D Anaglyph in OpenGL - 5

I.
Mac OS X 實作

    1. 新增專案:
        Xcode > File > New > Project... > OS X > Application >
        Command Line Tool > Next

       Product Name: 3DAnaglyph       
       Company Identifier: com.blogspot
       Type: C++
       Use Automatic Reference Counting: checked
       > Next > Create

    2. 新增 Framework:
       OpenGL
        - OpenGL is the premier environment for developing portable,
           interactive 2D and 3D graphics applications.

       GLUT
        - OpenGL Utility Toolkit

    3. 新增檔案:
        a. 立體攝影機類別:
            Xcode > File > New > File...
            > OS X > C and C++ > C++ Class > Next


              Save As: StereoCamera.cpp
              Targets: 3DAnaglyph (勾選)
              > Create

        b. 繪圖函式:
            Xcode > File > New > File...
            > OS X > C and C++ > C++ Class > Next


              Save As: draw.cpp
              Targets: 3DAnaglyph (勾選)
              > Create

    4. 整個專案檔案架構如下:

    5. 新增: 立體攝影機
        a. 開啓 StereoCamera.h 檔案, 修改如下:
#ifndef ___DAnaglyph__StereoCamera__
#define ___DAnaglyph__StereoCamera__

#include <iostream>

//@add
#include <OpenGL/OpenGL.h> // OpenGL Library
#include <GLUT/GLUT.h> // OpenGL Utility Toolkit
#include <math.h>


#endif /* defined(___DAnaglyph__StereoCamera__) */

        b. 開啓 StereoCamera.cpp 檔案, 修改如下:
#include "StereoCamera.h"

//@add
class StereoCamera
{
public:
   
    // 建構子
    StereoCamera(
                 float Convergence, // 收斂距離
                 float EyeSeparation, // 二眼間隔
                 float AspectRatio, // 寬高比
                 float FOV, // 視野角度
                 float NearClippingDistance, // 近截距
                 float FarClippingDistance // 遠截距
                 )
    {
        mConvergence            = Convergence;
        mEyeSeparation          = EyeSeparation;
        mAspectRatio            = AspectRatio;
        //mFOV                    = FOV * PI / 180.0f;
        //@update
        mFOV                    = FOV * M_PI / 180.0f;
        mNearClippingDistance   = NearClippingDistance;
        mFarClippingDistance    = FarClippingDistance;
    }
   
    // 套用左視錐
    void ApplyLeftFrustum()
    {
        float top, bottom, left, right;
        top     = mNearClippingDistance * tan(mFOV/2);
        bottom  = -top;
        float a = mAspectRatio * tan(mFOV/2) * mConvergence;
        float b = a - mEyeSeparation/2;
        float c = a + mEyeSeparation/2;
        left    = -b * mNearClippingDistance/mConvergence;
        right   =  c * mNearClippingDistance/mConvergence;
       
        // 設置投影矩陣 (會後做)
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        glFrustum(left, right, bottom, top, mNearClippingDistance, mFarClippingDistance);
       
        // 設置 模型/視野 矩陣 (會先做)
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
        // 將世界座標往右位移: 二眼間隔的一半距離
        glTranslatef(mEyeSeparation/2, 0.0f, 0.0f);
    }
   
    // 套用右視錐
    void ApplyRightFrustum()
    {
        float top, bottom, left, right;
        top     = mNearClippingDistance * tan(mFOV/2);
        bottom  = -top;
        float a = mAspectRatio * tan(mFOV/2) * mConvergence;
        float b = a - mEyeSeparation/2;
        float c = a + mEyeSeparation/2;
        left    =  -c * mNearClippingDistance/mConvergence;
        right   =   b * mNearClippingDistance/mConvergence;
       
        // 設置投影矩陣 (會後做)
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity(); 
        glFrustum(left, right, bottom, top, mNearClippingDistance, mFarClippingDistance);
       
        // 設置 模型/視野 矩陣 (會先做)
        glMatrixMode(GL_MODELVIEW);                   
        glLoadIdentity(); 
        // 將世界座標往左位移: 二眼間隔的一半距離
        glTranslatef(-mEyeSeparation/2, 0.0f, 0.0f);
    }
   
    // 內部變數
private:
    float mConvergence;
    float mEyeSeparation;
    float mAspectRatio;
    float mFOV;
    float mNearClippingDistance;
    float mFarClippingDistance;
};


    6. 新增: 繪圖函式
        a. 開啓 draw.h 檔案, 修改如下:
#ifndef ___DAnaglyph__draw__
#define ___DAnaglyph__draw__

//#include <iostream>
//@add
#include "StereoCamera.cpp"

#endif /* defined(___DAnaglyph__draw__) */

//@add

void DrawGLScene();
void PlaceSceneElements();


        b. 開啓 draw.cpp 檔案, 修改如下:
//@add
// 主要的繪圖函式

void DrawGLScene()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
   
    // 設定立體攝影機系統
    StereoCamera cam(
                     2000.0f,     // Convergence (收斂距離)
                     35.0f,       // Eye Separation (二眼間隔)
                     1.3333f,     // Aspect Ratio (寬高比)
                     45.0f,       // FOV along Y in degrees (沿著 Y 軸的視野角度)
                     10.0f,       // Near Clipping Distance (近截距)
                     20000.0f);   // Far Clipping Distance (遠截距)
   
    cam.ApplyLeftFrustum();
    glColorMask(true, false, false, false); // 只將紅色寫入緩沖區(紅色遮罩)
    PlaceSceneElements(); // 在場景中放入物體
   
    glClear(GL_DEPTH_BUFFER_BIT) ;
   
    cam.ApplyRightFrustum();
    glColorMask(false, true, true, false); // 只將綠色及藍色寫入緩沖區(綠藍色遮罩)
    PlaceSceneElements(); // 在場景中放入物體
   
    glColorMask(true, true, true, true); // 恢復將所有色彩寫入緩沖區
   
    //@add: flush!
    glFlush();
   
    //@add: swap the double buffer
    glutSwapBuffers();
}

//@add
// 在場景中放入物體

void PlaceSceneElements()
{
    // 沿著負 Z 軸, 位移到適當的深度
    glTranslatef(0.0f, 0.0f, -1800.0f);
   
    // 旋囀場景以便觀看
    glRotatef(-60.0f, 1.0f, 0.0f, 0.0f);
    glRotatef(-45.0f, 0.0f, 0.0f, 1.0f);
   
    // 繪製相交的環形圓紋曲面(tori)
    glPushMatrix();
    glTranslatef(0.0f, 0.0f, 240.0f);
    glRotatef(90.0f, 1.0f, 0.0f, 0.0f);
    glColor3f(0.2, 0.2, 0.6);
    glutSolidTorus(40, 200, 20, 30);
    glColor3f(0.7f, 0.7f, 0.7f);
    glutWireTorus(40, 200, 20, 30);
    glPopMatrix();
   
    glPushMatrix();
    glTranslatef(240.0f, 0.0f, 240.0f);
    glColor3f(0.2, 0.2, 0.6);
    glutSolidTorus(40, 200, 20, 30);
    glColor3f(0.7f, 0.7f, 0.7f);
    glutWireTorus(40, 200, 20, 30);
    glPopMatrix();
}


    7. 修改主程式:
        開啓 main.cpp 檔案, 修改如下:
//#include <iostream>
//@add

#include "draw.h"

//@add: initialize OpenGL state
void init()
{
    // This determines the background color, in this case: gray
    // state: current clear color

    glClearColor(0.5, 0.5, 0.5, 1.0); // R, G, B, A
   
    // Determines which matrix to apply operations to.
    // value: GL_PROJECTION or GL_MODELVIEW

    glMatrixMode(GL_PROJECTION); // default
   
    // Loads the Identity matrix
    glLoadIdentity();
   
    // 投影(Projection)
    //
    // default: 正投影(Orthographic Projection)

}


//int main(int argc, const char * argv[])
//@update: just remove "const"
int main(int argc, char * argv[])
{
    // insert code here...
    //std::cout << "Hello, World!\n";

   
    // Init glut
    glutInit(&argc, argv);
   
    // Display mode
    int mode = GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH;
    glutInitDisplayMode(mode);
   
    // Init Window
    glutInitWindowSize(800, 600);
    glutInitWindowPosition(100, 100);
    glutCreateWindow("3D Anaglyph");
   
    // initialize: set OpenGL state
    init();
   
    // Callback Functions Registration
    glutDisplayFunc(DrawGLScene); // drawing
   
    // enter event processing loop
    glutMainLoop();
   
    // will not be executed
    return 0;
}


    8. 編譯並執行:

沒有留言:

張貼留言

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