2012年10月11日 星期四

Use OpenGL in Windows Form

since: 2012/10/11
update: 2012/10/11

reference:
1. 將OpenGL加入Windows Forms(C++/CLI)
2. (VS2005,OpenGL)WinForm建立OpenGL视场

A. 說明:
     本篇文章參考上面的二篇文章, 擷取不同的特點:

      1. OpenGL 的繪圖作業, 獨立成一個類別來處理.

      2.Form 加入以下的元件:
          a. Panel: 作為 Device Context,  之後提供給 OpenGL 來建立 Render Context.
          b. Timer: 計時器, 藉著啟用 Tick 事件, 定時作繪製的動作, 來達到動畫的效果.

     3.Form 加入以下的事件:
          a. Paint: 首次的繪製. (如果不需要動畫的話, 可將 Timer 停用, 只畫此一次)
          b. ClientSizeChanged: 當 Form 的大小改變時, 需要再重新繪製.

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

B. 前置作業:
     1. 安裝 GLUT  與 GLEW: 參考這篇CD.

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

C. 新增專案:
     1. Visual Studio 2010 > 檔案 > 新增 > 專案

     2. Visual C++ > CLR > Windows Form 應用程式
         名稱: GLForm_Hello
         位置: C:\Lanli\projects\WindowsForm_My\
         為方案建立目錄: 取消勾選
          > 確定

     3. 新增給 OpenGL 使用的類別檔案:

         點選 "GLForm_Hello" 專案 >  原始程式檔 > 滑鼠右鍵 > 加入 > 新增項目:

         Visual C++ > 標頭檔 (.h)
         名稱: OpenGL.h
          > 新增

         Visual C++ > C++ 檔 (.cpp)
         名稱: OpenGL.cpp
          > 新增

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

D. 專案屬性設定:
     點選 "GLForm_Hello" 專案 > 滑鼠右鍵
     > 屬性
     > 組態屬性

     1. > 一般: (Debug Release)
         字元集: 使用 Unicode 字元集
         Common Language Runtime 支援: Common Language Runtime 支援 (/clr)
          > 確定

     2. > 連結器 > 輸入 > 其他相依性: (Debug Release)
             opengl32.lib
             glut32.lib
             glew32.lib
             glew32s.lib
             glu32.lib


            > 確定

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

E. 撰寫 OpenGL 類別檔案
     1. 開啟 OpenGL.h 檔案, 加入以下程式碼:
#pragma once

#include <windows.h>
#include <GL/glut.h>


// OpenGL 繪圖類別
class OpenGL
{
public:
    OpenGL(); // 建構子
    bool Init(HDC hdc); // 傳入參數: device context, 來建立 render context
    void InitOpenGL(); // 初始化 OpenGL 環境
    void InitScene(int x, int y, int width, int height); // 初始化場景
    void RenderScene(); // 繪製場景

public:
    ~OpenGL(void); // 解構子

private:
    HDC m_hDC; // device context handler
    HGLRC m_rc; // render context handler

    // -------------------- lights(光源)
    GLfloat gLightDiffuse[4]; // light diffuse (散射光)
    GLfloat gLightPosition[4]; // light position

    // -------------------- rotate angle(旋轉角度)
    float m_rAngle;
};


***************************************************

     2. 開啟 OpenGL.cpp 檔案, 加入以下程式碼:
#include "stdafx.h"
#include <iostream>
#include "OpenGL.h"


// 建構子
OpenGL::OpenGL()
{
    m_rc = NULL;
}

// 解構子
OpenGL::~OpenGL(void)

    wglMakeCurrent(0,0);
    wglDeleteContext(m_rc);
}

// 傳入參數: device context, 來建立 Render Context
bool OpenGL::Init(HDC hdc)
{  
    m_hDC = hdc;

    // Set pixel format
    PIXELFORMATDESCRIPTOR pfd;
    memset(&pfd, 0, sizeof(PIXELFORMATDESCRIPTOR));
    pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
    pfd.nVersion = 1;
    pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;

    pfd.iPixelType = PFD_TYPE_RGBA;
    pfd.cColorBits = 32;
    pfd.cDepthBits = 32;
    pfd.iLayerType = PFD_MAIN_PLANE;

    int cpf = ChoosePixelFormat(m_hDC, &pfd);
    if(!cpf)
    {
        std::cerr << "Choose Pixel Format Error\n";
        return false;
    }

    SetPixelFormat(m_hDC, cpf, &pfd);

    m_rc = wglCreateContext(m_hDC);
    if(!m_rc)
    {
        std::cerr << "Create Render Context Error\n";
        return false;
    }

    if(!wglMakeCurrent(m_hDC, m_rc))
    {
        std::cerr << "wglMakeCurrent Error\n";
        return false;
    }

    return true;
}

// 初始化 OpenGL 環境
void OpenGL::InitOpenGL()
{
    glClearColor(1.0f, 1.0f, 1.0f, 1.0f); // White Background
    //glColor3f(0.0, 0.0, 0.0); // 筆畫顏色: 黑

    /*******************************************************/
    // 光源設定
    // light diffuse (散射光): 紅色

    gLightDiffuse[0] = 1.0;
    gLightDiffuse[1] = 0.0;
    gLightDiffuse[2] = 0.0;
    gLightDiffuse[3] = 1.0;

    // light position (光源位置)
    gLightPosition[0] = 1.0;
    gLightPosition[1] = 1.0;
    gLightPosition[2] = 0.0;
    gLightPosition[3] = 1.0;

    // 啟用第一個光源設定
    glLightfv(GL_LIGHT0, GL_DIFFUSE, gLightDiffuse);
    glLightfv(GL_LIGHT0, GL_POSITION, gLightPosition);
    glEnable(GL_LIGHT0);
    /*******************************************************/

    glClearDepth(1.0f); // Depth Buffer Setup
    glEnable(GL_DEPTH_TEST); // Enables Depth Testing
    glEnable(GL_AUTO_NORMAL);
    glEnable(GL_NORMALIZE);
    glShadeModel(GL_SMOOTH); // Enable Smooth Shading

    glDepthFunc(GL_LEQUAL); // The Type Of Depth Testing To Do
    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
}

// 初始化場景
void OpenGL::InitScene(int x, int y, int width, int height)
{
    glViewport(x, y, width, height);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
    glLoadIdentity(); // Reset The Projection Matrix

    // 透視投影
    /*
    gluPerspective(
        45.0f, // field of view in degree
        (GLfloat)width/(GLfloat)height, // aspect ratio
        0.1f, // Z near
        100.0f); // Z far
    */

    // 正交投影
    //glOrtho(-5, 5, -5, 5, 5, 15);


    glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
    glLoadIdentity(); // Reset The Modelview Matrix

    // 眼睛(攝影機) 位置與觀看方向
    gluLookAt(
        0.0, 0.0, 10.0, // eye is at (0,0,10.0)
        0.0, 0.0, 0.0, // eye look at (0,0,0)
        0.0, 1.0, 0.0); // up is in positive Y direction

}

// 繪製場景
void OpenGL::RenderScene()
{

    // Clear Screen And Depth Buffer   
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);   
    glLoadIdentity(); // Reset The Current Modelview Matrix

    // -------------------- 啟用光源設定
    glEnable(GL_LIGHTING);

    // render the 2D/3D object
   
    /*
    glBegin(xxx);   
    ....
    glEnd();   
    */


    // 3. 再位移
    //glTranslatef(3.0f,0.0f,0.0f);    // Move Right 3 Units


    // 2. 再旋轉角度
    m_rAngle = m_rAngle + 1;
    if(360 < m_rAngle) m_rAngle -= 360;
    glRotatef(m_rAngle, 0.0f, 1.0f, 0.0f); // 對 Y 軸(垂直軸)作旋轉

    // 1. 先畫圖
    //glPointSize(1.0f);
    glColor3f(0.4, 0.6, 0.7);
    glutWireTeapot(0.5);

    // -------------------- 停用光源設定
    glDisable(GL_LIGHTING);

    SwapBuffers(m_hDC);
}


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

F. 為專案的 Form 添加成員變數
    開啟 Form1.h 檔案 ( Form1.h > 滑鼠右鍵 > 檢視程式碼), 修改如下:

// step 01:
#pragma once


#include "OpenGL.h"
OpenGL w_openGL; // w: 代表由 wgl 所建立的 GL
....

// step 02:
    private:
        /// <summary>
        /// 設計工具所需的變數。
        /// </summary>
        System::ComponentModel::Container ^components;

        //@add for OpenGL handle

        HDC  m_hDC; // Device Context Handler
        int m_width;
        int m_height;


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

G.為專案的 Form 加入新元件與事件:
     開啟 Form1.h 設計工具 ( Form1.h > 滑鼠右鍵 > 設計工具檢視):

     1. 更改 Form 的顯示名稱:
          > 屬性 > Text: GLForm Hello
                           Size: 400, 400

     2. 幫 Form 加入 Paint 事件:
          > 屬性 > 事件(閃電圖示):
          點二下 Paint 事件

     3. 幫 Form 加入 ClientSizeChanged 事件:
         > 屬性 > 事件(閃電圖示):
         點二下 ClientSizeChanged 事件

     4. 幫 Form 加入 Panel 元件:
         > 工具箱 > 將 Panel 拖拉到 Form 上
         > 屬性:
            (Name): OpenGLPanel
            Duck: Fill (填滿)

     5. 幫 Form 加入 Timer 元件與 Tick 事件:
         > 工具箱 > 將 Timer 拖拉到 Form 上
         > 點二下 Tick 事件

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

H. 為專案的 Form 加入 OpenGL 的處理:
      開啟 Form1.h 檔案 ( Form1.h > 滑鼠右鍵 > 檢視程式碼), 修改如下:
....
// step 01:
    public:
        Form1(void)
        {
            InitializeComponent();
            //
            //TODO: 在此加入建構函式程式碼
            //


            //@add for OpenGL
            OpenGLInit();

        }

        //@add for OpenGL
        void OpenGLInit(void)
        {
            // Get Device Context
            //m_hDC = GetDC((HWND)(this->Handle.ToInt32()));

            m_hDC = GetDC((HWND)(this->OpenGLPanel->Handle.ToInt32()));

            if(!w_openGL.Init(m_hDC))
            {
                MessageBox::Show("OpenGL Init Error");
            }

            w_openGL.InitOpenGL();

            m_width = this->ClientSize.Width;
            m_height = this->ClientSize.Height;
            w_openGL.InitScene(0, 0, m_width, m_height);

            // 下面二行註解的話, 就不會產生動畫效果,
            // 只會執行一次 Form1_Paint 事件裡的 w_openGL.RenderScene();

            timer1->Interval = 20;
            timer1->Enabled = true;
        }

....

// step 02:
    private: System::Void Form1_Paint(System::Object^  sender, System::Windows::Forms::PaintEventArgs^  e) {
                 //@add for OpenGL
                 w_openGL.RenderScene();

             }
   
    private: System::Void Form1_ClientSizeChanged(System::Object^  sender, System::EventArgs^  e) {
                 //@add for OpenGL
                 int width=this->ClientSize.Width;
                 int height=this->ClientSize.Height;
                 w_openGL.InitScene(0,0,width,height);
                 w_openGL.RenderScene();

             }

    private: System::Void timer1_Tick(System::Object^  sender, System::EventArgs^  e) {
                 //@add for OpenGL
                 w_openGL.RenderScene();

             }
    };

....

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

I. 建置並啟動::

    繞著 Y 軸(垂直軸)旋轉的 Teapot

2012年10月7日 星期日

Read mesh file and display wireframe in OpenGL

since: 2012/10/07
update: 2012/10/07

reference:
1. Openmesh 读入off文件并用opengl显示

A. 說明:
     1. 主要參考上方的資料, 並作適度的簡化與調整.
     2. 調整為: 不加入光源效果, 只顯示線框圖(wireframe), 採用正交投影.

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

B. 前置作業:
     1. 安裝 GLUT  與 GLEW: 參考這篇CD.

     2. 取得 OpenMesh Libraries: 參考這篇, 在此會使用 C. 方式二所產生的
         Libraries, 即:        
          OpenMesh Libraries 目錄位置
          C:\Lanli\projects\OpenMesh-2.2\lib
          內含: libOpenMeshCore.lib
                    libOpenMeshCored.lib
                    libOpenMeshTools.lib
                    libOpenMeshToolsd.lib
                    (有 d 的為 debug 版本)

          OpenMesh Headers 目錄位置
          C:\Lanli\projects\OpenMesh-2.2\src

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

C. 新增專案:
     1. Visual Studio 2010 > 檔案 > 新增 > 專案

     2. Visual C++ > Win32 > Win32 主控台應用程式
         名稱: OpenMesh_Hello
         位置: C:\Lanli\projects
         為方案建立目錄: 取消勾選
          > 確定

     3. 下一步
          > 空專案: 勾選
          > 完成

     4. 新增主程式檔案
         點選 "OpenMesh_Hello" 專案 > 滑鼠右鍵 > 加入 > 新增項目:
         Visual C++ > C++ 檔 (.cpp)
         名稱: main.cpp
          > 新增

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

D. 為專案加入 OpenMesh 的 Libraries 與 Header Files:
     1. OpenMesh_Hello 專案的根目錄, 新增 meshlib 資料夾.

     2. B. 前置作業2. 的:
         a. OpenMesh Libraries 目錄下所有檔案 copy 到 lib 目錄下.
              即 lib 目錄下的檔案為:
              ----------------------------
              libOpenMeshCore.lib
              libOpenMeshCored.lib
              libOpenMeshTools.lib
              libOpenMeshToolsd.lib
              (有 d 的為 debug 版本)

         b. OpenMesh Headers 目錄下所有檔案 copy 到 mesh 目錄下.
             即 mesh 目錄下的檔案為:
             ----------------------------
             OpenMesh 資料夾
             Unittests 資料夾

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

E. 專案屬性設定:
     點選 "OpenMesh_Hello" 專案 > 滑鼠右鍵
     > 屬性
     > 組態屬性

     1. > 一般: (Debug Release)
         字元集: 使用 Unicode 字元集
         Common Language Runtime 支援: Common Language Runtime 支援 (/clr)
          > 確定

     2. > VC++ 目錄: (Debug Release)
            Include 目錄: mesh
            程式庫目錄: lib
            > 確定

            備註: 也可以使用以下的方式
            Include 目錄: C:\Lanli\projects\OpenMesh-2.2\include
            程式庫目錄: C:\Lanli\projects\OpenMesh-2.2\lib


     3. > C/C++ 前置處理器: (Debug Release)
             前置處理器定義: _USE_MATH_DEFINES

     4. > 連結器 > 輸入 > 其他相依性:
             Debug: (檔案有 d 的版本)
             -----------------------------------
             libOpenMeshCored.lib
             libOpenMeshToolsd.lib
             glut32.lib
             glew32.lib
             glew32s.lib
            > 確定

             Release:
             -----------------------------------
             libOpenMeshCore.lib
             libOpenMeshTools.lib
             glut32.lib
             glew32.lib
             glew32s.lib
            > 確定

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

F.下載模型檔:
     網址: models
     檔名: teapot.off
     下載後, copy 到 OpenMesh_Hello 專案的根目錄下.
     用 MeshLab 看一下模型檔:

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

G. 撰寫程式碼:
     開啟 main.cpp 檔案, 修改如下:
#include <iostream>
#include <vector>
#include <math.h>
#include <stdio.h>
#include <string.h>


// -------------------- OpenMesh
#include <OpenMesh/Core/IO/MeshIO.hh>
#include <OpenMesh/Core/Mesh/PolyMesh_ArrayKernelT.hh>


// -------------------- OpenGL
#include <GL/glut.h>

// -------------------- typedef
typedef OpenMesh::PolyMesh_ArrayKernelT<> MyMesh;
MyMesh mesh;

// -------------------- global variables
float gWidth; // width of the render window
float gHeight; // height of the render window

// -------------------- lights
//GLfloat gLightDiffuse[] = {0.0, 0.0, 1.0, 1.0}; // light diffuse
//GLfloat gLightPosition[] = {0.0, 0.0, 1.0, 1.0}; // light position

// -------------------- function declare
void display();
void drawFace();
void drawLine();
void glInit();
void idle();
void render();
void reshape(GLint width, GLint height);

// ----------------------------------------------------------------------------

int main(int argc, char* argv[])
{
    // read mesh object file
    if (!OpenMesh::IO::read_mesh(mesh, "teapot.off"))
    {
        std::cerr << "read error\n";
        exit(1);
    }

    // initialize the render window
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
    glutInitWindowPosition(0, 0);
    glutInitWindowSize(640, 640);
    glutCreateWindow("Hello, OpenMesh!");

    // initialize the render environment
    glInit();

    // callback function
    glutDisplayFunc(display);
    glutReshapeFunc(reshape);
    glutIdleFunc(idle);

    glutMainLoop();

    return 0;
}

// initialize the render environment
void glInit()
{
    // set color
    glClearColor(0.8, 0.8, 0.8, 1.0); // 背景: 灰色
    glColor3f(0.0, 0.0, 0.0); // 筆畫顏色: 黑

    // 光源設定
    /*
    glLightfv(GL_LIGHT0, GL_DIFFUSE, gLightDiffuse);
    glLightfv(GL_LIGHT0, GL_POSITION, gLightPosition);
    glEnable(GL_LIGHT0);
    */


    glEnable(GL_DEPTH_TEST); // 深度測試
    glEnable(GL_AUTO_NORMAL);
    glEnable(GL_NORMALIZE);
    glShadeModel(GL_SMOOTH);

    // set OpenGL projection mode
    glMatrixMode(GL_PROJECTION);
   
    // 透視投影
    /*
    gluPerspective(
        45.0, // field of view in degree
        1.0, // aspect ratio
        1.0, // Z near
        10.0); // Z far
    */
    // 正交投影

    glOrtho(-5, 5, -5, 5, 5, 15);

    // set OpenGL nodel view mode
    glMatrixMode(GL_MODELVIEW);

    // 眼睛(攝影機) 位置與觀看方向
    gluLookAt(
        0.0, 0.0, 10.0, // eye is at (0,0,10.0)
        0.0, 0.0, 0.0, // eye look at (0,0,0)
        0.0, 1.0, 0.0); // up is in positive Y direction
}

void display()
{
    glViewport(0, 0, gWidth, gHeight);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    render();

    glutSwapBuffers();
}

void render()
{
    //glEnable(GL_LIGHTING);

    //drawFace();

    drawLine();

    //glDisable(GL_LIGHTING);
}

void reshape(GLint width, GLint height)
{
    // record the width and height of the current render window
    gWidth = width;
    gHeight = height;
}

void idle()
{
    // refresh the screen
    glutPostRedisplay();
}

void drawFace()
{
    glPointSize(1.0f);
    glColor3f(1.0, 1.0, 0.0);

    for (MyMesh::FaceIter f_it = mesh.faces_begin(); f_it != mesh.faces_end(); ++f_it)
    {
        glBegin(GL_TRIANGLES);
        for(MyMesh::FaceVertexIter fv_it = mesh.fv_iter(f_it); fv_it; ++fv_it)
        {
            glVertex3fv(mesh.point(fv_it).data());
        }
        glEnd();
    }
}

void drawLine()
{
    glPointSize(1.0f);
    glColor3f(0.0, 0.0, 0.0);
    for (MyMesh::FaceIter f_it = mesh.faces_begin(); f_it != mesh.faces_end(); ++f_it)
    {
        glBegin(GL_LINE_LOOP);
        for(MyMesh::FaceVertexIter fv_it = mesh.fv_iter(f_it); fv_it; ++fv_it)
        {
            glVertex3fv(mesh.point(fv_it).data());
        }
        glEnd();
    }
}


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

H. 建置並啟動:
     

2012年10月2日 星期二

OpenMesh: First Steps - Building a cube

since: 2012/10/02
update: 2012/10/03

reference:
1. OpenMesh: First Steps - Building a cube

A. 新增專案
     1. Visual Studio 2010 > 檔案 > 新增 > 專案

     2. Visual C++ > Win32 > Win32 主控台應用程式
         名稱: OpenMesh_Cube
         位置: C:\Lanli\projects
         為方案建立目錄: 取消勾選
          > 確定

     3. 下一步
          > 空專案: 勾選
          > 完成

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

B. 專案屬性設定
     1. 點選 "OpenMesh_Cube" 專案 > 滑鼠右鍵 > 屬性:
         組態屬性 > VC++ 目錄 >
         Include 目錄: C:\Program Files (x86)\OpenMesh 2.2\include
         程式庫目錄: C:\Program Files (x86)\OpenMesh 2.2\lib
          > 確定

     2. 點選 "OpenMesh_Cube" 專案 > 滑鼠右鍵 > 屬性:
         組態屬性 > 連結器 > 輸入:
         其他相依性: OpenMeshCored.lib
                             OpenMeshToolsd.lib
           > 確定


     3. Debug 模式的設定好後, 換設定 Release 模式1. 2.
          其中 2. 的 "其他相依性", 改成: (沒有 d 的版本)
           OpenMeshCore.lib
           OpenMeshTools.lib

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

C. 撰寫程式碼
     1. 點選 "OpenMesh_Cube" 專案 > 滑鼠右鍵 > 加入 > 新增項目:
         Visual C++ > C++ 檔 (.cpp)
         名稱: main.cpp
          > 新增

     2. main.cpp 加入以下的程式碼:
#include <iostream>
// -------------------- OpenMesh
#include <OpenMesh/Core/IO/MeshIO.hh>
#include <OpenMesh/Core/Mesh/PolyMesh_ArrayKernelT.hh>

// ----------------------------------------------------------------------------
typedef OpenMesh::PolyMesh_ArrayKernelT<> MyMesh;
// ----------------------------------------------------------------------------
// Build a simple cube and write it to std::cout


int main()
{
    MyMesh mesh;

    // generate vertices
    MyMesh::VertexHandle vhandle[8];

    vhandle[0] = mesh.add_vertex(MyMesh::Point(-1, -1, 1));
    vhandle[1] = mesh.add_vertex(MyMesh::Point( 1, -1, 1));
    vhandle[2] = mesh.add_vertex(MyMesh::Point( 1, 1, 1));
    vhandle[3] = mesh.add_vertex(MyMesh::Point(-1, 1, 1));
    vhandle[4] = mesh.add_vertex(MyMesh::Point(-1, -1, -1));
    vhandle[5] = mesh.add_vertex(MyMesh::Point( 1, -1, -1));
    vhandle[6] = mesh.add_vertex(MyMesh::Point( 1, 1, -1));
    vhandle[7] = mesh.add_vertex(MyMesh::Point(-1, 1, -1));


    // generate (quadrilateral) faces
    std::vector<MyMesh::VertexHandle> face_vhandles;

    face_vhandles.clear();
    face_vhandles.push_back(vhandle[0]);
    face_vhandles.push_back(vhandle[1]);
    face_vhandles.push_back(vhandle[2]);
    face_vhandles.push_back(vhandle[3]);
    mesh.add_face(face_vhandles);

    face_vhandles.clear();
    face_vhandles.push_back(vhandle[7]);
    face_vhandles.push_back(vhandle[6]);
    face_vhandles.push_back(vhandle[5]);
    face_vhandles.push_back(vhandle[4]);
    mesh.add_face(face_vhandles);

    face_vhandles.clear();
    face_vhandles.push_back(vhandle[1]);
    face_vhandles.push_back(vhandle[0]);
    face_vhandles.push_back(vhandle[4]);
    face_vhandles.push_back(vhandle[5]);
    mesh.add_face(face_vhandles);

    face_vhandles.clear();
    face_vhandles.push_back(vhandle[2]);
    face_vhandles.push_back(vhandle[1]);
    face_vhandles.push_back(vhandle[5]);
    face_vhandles.push_back(vhandle[6]);
    mesh.add_face(face_vhandles);

    face_vhandles.clear();
    face_vhandles.push_back(vhandle[3]);
    face_vhandles.push_back(vhandle[2]);
    face_vhandles.push_back(vhandle[6]);
    face_vhandles.push_back(vhandle[7]);
    mesh.add_face(face_vhandles);

    face_vhandles.clear();
    face_vhandles.push_back(vhandle[0]);
    face_vhandles.push_back(vhandle[3]);
    face_vhandles.push_back(vhandle[7]);
    face_vhandles.push_back(vhandle[4]);
    mesh.add_face(face_vhandles);


    // write mesh to output.off
    try
    {
        if ( !OpenMesh::IO::write_mesh(mesh, "output.off") )
        {
            std::cerr << "Cannot write mesh to file 'output.off'" << std::endl;
            return 1;
        }
    }
    catch( std::exception& x )
    {
        std::cerr << x.what() << std::endl;
        return 1;
    }

    return 0;
}


     3. 建置 > 建置方案
         錯誤訊息:
          "You have to define _USE_MATH_DEFINES in the compiler settings!"   

     4. 解決方式: (同時對 Debug Release 版本作修改)
         點選 "OpenMesh_Cube" 專案 > 滑鼠右鍵 > 屬性:
         組態屬性 > C/C++ > 前置處理器:
         _USE_MATH_DEFINES
         > 確定

     5. 建置 > 建置方案
         偵錯 > 啟動但不偵錯
         (Debug 與 Release 版皆成功)

     6.檢視結果:
        用文字編輯器開啟專案根目錄下的 output.off 檔案, 如下所示:
OFF
8 6 0
-1 -1 1
1 -1 1
1 1 1
-1 1 1
-1 -1 -1
1 -1 -1
1 1 -1
-1 1 -1
4 0 1 2 3
4 7 6 5 4
4 1 0 4 5
4 2 1 5 6
4 3 2 6 7
4 0 3 7 4


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

D. 檢視 3D 圖形 (update: 2012/09/03)
     1. 下載: MeshLab 並安裝.

     2. 用 MeshLab 開啟 output.off 檔案.

Get OpenMesh Libraries for Visual Studio 2010

since: 2012/10/02
update: 2012/10/02

reference:
1. RWTH Graphics: OpenMesh
2. OpenMesh: Compiling OpenMesh

A. 說明:
     1. 從 OpenMesh 官網取得 OpenMesh Libraries 的方式有三個:
         a. RWTH Graphics: Download 下載最新的 Precompiled Binaries
              (Windows Binary setups) 來安裝.(目前為: OpenMesh 2.2)

         b. RWTH Graphics: Download 下載最新的 Source Code
             (目前為: OpenMesh 2.2), 解壓縮後開啟內附的 Visual Studio 專案檔,
             在 Visual Studio 裡進行編譯的工作.

         c. RWTH Graphics: Download 下載最新的 Source Code
             (目前為: OpenMesh 2.2), 解壓縮後先進行編譯來產生  Visual Studio 專案檔,
             然後再開啟該 Visual Studio 專案檔 來進行編譯的工作.

     2. 以下會記錄這三種方式, 並且記錄其產生的 LibrariesHeaders 目錄位置,
         以提供之後的專案使用; a. 是最容易的方式且似乎看不到錯誤訊息, b. 次之,
          c. 是較不易處理的方式.

     3. 之後有使用到 OpenMesh 的專案, 會先使用 a. Precompiled Binaries 的檔案,
         如果有問題的話, 再改用 b. 所產生的檔案. (c. 算是沒有完全成功的)

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

B. 方式一: 安裝 Precompiled Binaries
     1. RWTH Graphics: Download 下載:
         Precompiled Binaries (Windows Binary setups):
         OpenMesh 2.2 (32-bit VS2010)
         檔名: OpenMesh-2.2-VS2010.exe

     2. 安裝後, 預設位置為: C:\Program Files (x86)\OpenMesh 2.2

     3. OpenMesh Libraries 目錄位置
         C:\Program Files (x86)\OpenMesh 2.2\lib
          內含: OpenMeshCore.lib
                    OpenMeshCored.lib
                    OpenMeshTools.lib
                    OpenMeshToolsd.lib
                    (有 d 的為 debug 版本)

     4. OpenMesh Headers 目錄位置
          C:\Program Files (x86)\OpenMesh 2.2\include

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

C. 方式二: 使用預設的  Visual Studio 專案檔來編譯
     1. RWTH Graphics: Download 下載最新的 Source Code:
         OpenMesh 2.2 ( zip ), 檔名: OpenMesh-2.2.zip

     2. OpenMesh-2.2.zip 解壓縮後(在此為 C:\Lanli\projects\OpenMesh-2.2),
         開啟 VS2008OpenMesh.sln 檔案, 由於我安裝的是 Visual Studio 2010,
         因此會啟動 "轉換精靈" 進行轉換.(在此, 選擇: 轉換前不建立備份)

     3. 接著, 將轉換後的方案, 分別建置 Debug Release 的版本.
         Debug 版: 建置: 3 成功、0 失敗、0 最新、0 略過
         Release 版: 建置: 3 成功、0 失敗、0 最新、0 略過

     4. OpenMesh Libraries 目錄位置
          C:\Lanli\projects\OpenMesh-2.2\lib
          內含: libOpenMeshCore.lib
                    libOpenMeshCored.lib
                    libOpenMeshTools.lib
                    libOpenMeshToolsd.lib
                    (有 d 的為 debug 版本)

     5. OpenMesh Headers 目錄位置
         C:\Lanli\projects\OpenMesh-2.2\src

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

D. 方式三: 編譯 Source Code
     1. RWTH Graphics: Download 下載最新的 Source Code:
         OpenMesh 2.2 ( zip ), 檔名: OpenMesh-2.2.zip

     2.OpenMesh-2.2.zip 解壓縮後更名
        
(在此為 C:\Lanli\projects\OpenMesh-2.2-build)

*******************************************************************

     3. 安裝以下軟體:
          a. CMake - Cross Platform Make:
              Binary distributions: Windows (Win32 Installer) > cmake-2.8.9-win32-x86.exe             
          b. Qt framework:
              Qt libraries 4.8.3 for Windows (VS 2010, 235 MB)
              檔名: qt-win-opensource-4.8.3-vs2010.exe

          c. Doxygen:
              A binary distribution for Windows: doxygen-1.8.2-setup.exe

          d. GLUT:
              GLUT 3.7 Source Code Download for Win32
              檔名: glut37.zip
               (1). 先用文字編輯器開啟以下檔案:
                      C:\Lanli\projects\OpenMesh-2.2-build\cmake\FindGLUT.cmake
                      可以看到 glut 預設的目錄位置是在 C:/libs 下:
IF (WIN32)
  FIND_PATH( GLUT_INCLUDE_DIR NAMES GL/glut.h
    PATHS  ${GLUT_ROOT_PATH}/include
           "C:/libs/glut-3.7/include" )
  FIND_LIBRARY( GLUT_glut_LIBRARY NAMES glut32 glut
    PATHS
    ${OPENGL_LIBRARY_DIR}
    ${GLUT_ROOT_PATH}/Release
    "C:/libs/glut-3.7/lib"
    )
ELSE (WIN32)


               (2). 先在 C:/ 下建立 libs 資料夾, 然後將 glut37.zip 解壓縮到其下.

               (3). 可以看到 include lib 的目錄位置, 但是 lib 目錄內卻沒有 .lib 檔案.
                      C:\libs\glut-3.7\include
                      C:\libs\glut-3.7\lib

               (4). 所以需要自行編譯來產生 .lib 檔案, 編譯方式如下:
                      (說明: 在此, 我還沒有編譯成功)
                      (a). 先看 C:\libs\glut-3.7\README.win 檔案的說明.
                      (b). 將 C:\libs\glut-3.7\glutwin32.mak  檔案, 取消唯讀屬性.
                      (c). 用文字編輯器開啟 glutwin32.mak 檔案, 修改如下:
                            (可能還要修改其它項目)
# Win95 dll directory
DLLINSTALL     = \windows\system

# WinNT dll directory
#DLLINSTALL     = \winnt\system32


                      (d). 由於 glutmake.bat 使用了 nmake 來編譯; 而 nmake 是屬於 VisualC++
                             編譯器系統的一部分. 因此, 必須要讓目前的環境能在 Visual Studio 的
                             外部來使用 VisualC++ 的編譯器系統, 方式如下:

                             將 C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin 下的
                             vcvars32.bat 檔 copy 到 C:\libs\glut-3.7 目錄下.
                             進入 "命令提示字元" :
                              C:\>cd libs\glut-3.7
                              C:\libs\glut-3.7>vcvars32.bat
                               Setting environment for using Microsoft Visual Studio 2010 x86 tools.

                      (e). 進行編譯:
                             C:\libs\glut-3.7>glutmake.bat

               (5). 由於編譯失敗, 因此改成如下的方式:
                      (a). 到 Nate Robins - OpenGL - GLUT for Win32 下載:
                             glut-3.7.6-bin.zip (117 KB) , 檔名: glut-3.7.6-bin.zip  
                      (6). 解壓縮後, 將 glut32.lib copy 到 C:\libs\glut-3.7\lib 目錄下.

*******************************************************************

     4. 執行 cmake-gui 程式
         a. 設定 source code 的位置: (OpenMesh 最上層的目錄)
             C:/Lanli/projects/OpenMesh-2.2-build

         b. 設定 build 的位置: (先在 OpenMesh 最上層的目錄, 建立 build 資料夾)
             C:\Lanli\projects\OpenMesh-2.2-build\build

         c. 按下 "Configure"
             Specify the generator for this project:
              Visual Studio 10
              Use default native compilers
               > Finish

         d. 按下 "Generate"
************************************************************
* ACG Buildsystem *
* *
* Package : OpenMesh *
* Version : 2.2 *
************************************************************
Configuring done
Generating done
// 完成

     5. 開啟 C:\Lanli\projects\OpenMesh-2.2-build\build\OpenMesh.sln 檔案
         (Visual Studio 的專案檔)

     6. 對開啟的方案, 分別建置 Debug Release 的版本.
         Debug 版: 建置: 17 成功、2 失敗、0 最新、5 略過
         Release 版: 全部重建: 15 成功、4 失敗、 5 略過

     7. OpenMesh Libraries 目錄位置:
         C:\Lanli\projects\OpenMesh-2.2-build\build\Build\lib
          內含:
                    OpenMeshCored.lib
                    OpenMeshToolsd.lib
                    (有 d 的為 debug 版本)

     8. OpenMesh Headers 目錄位置
         C:\Lanli\projects\OpenMesh-2.2-build\src

2012年9月23日 星期日

Create a Windows Forms Application in Visual C++

since: 2012/09/23
update: 2012/09/23

reference:
1. 使用 .NET Framework 建立 Windows Form 應用程式 (C++)
2. CPP_CLI_tutorial

A. 說明:
     1. 前學習的環境已不偏重在 iOS 平台上, 近期內應該大多會在 Windows 上,
         學習的內容為: 電腦圖學, 影像處理網格(Mesh)處理.

     2. 開發環境:  Windows 7 (64bit) + Visual Studio 2010 + Visual Assist X

     3. 如果遇到有版權的問題, 可能就不會記錄完整的程式碼.

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

B. 建立新專案:
     1. VS 2010 > 檔案 > 新增 > 專案

     2. Visual C++ > CLR > .Net Framework4 >
         Windows Form 應用程式 >
         名稱: winformsapp
         位置: C:\Lanli\projects\
         為方案建立目錄: 取消勾選
          > 確定

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

C. 為工具箱加入 "索引標籤" 與 "客製化控制項":
    1. 加入 "索引標籤":
        展開工具箱 > 滑鼠右鍵 > 加入索引標籤 >
        輸入標籤名稱: (ex: OpenGL)

    2. 加入 "客製化控制項":
         a. 搜尋網路上的資源, 下載 "客製化控制項" 的 .dll 檔(ex: MyPanel.dll),
             將其複製到某個目錄下, ex: C:\Lanli\GL_LIB\
                        
         b. 在剛剛新增好的 "索引標籤" 上: 滑鼠右鍵 > 選擇項目

         c. .NET Framework 元件 >瀏覽
          > 選取剛剛存放 MyPanel.dll 檔案的位置 (C:\Lanli\GL_LIB\MyPanel.dll)
          > 開啟舊檔
          > 確定

         d. 完成後, 即可在工具箱內看到該元件.

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

D. 專案屬性
     點選該專案(ex: winformsapp) > 滑鼠右鍵 > 屬性:

     1. 通用屬性 > 架構和參考 > 加入新參考

      > 瀏覽 > (元件檔類型檔案) > 確定

     2. 組態屬性 > 一般:
         字元集: 使用 Unicode 字元集
         Common Language Runtime 支援: Common Language Runtime 支援 (/clr)
          > 確定

     3. 組態屬性 > C/C++ > 一般:
         Common Language Runtime 支援: Common Language Runtime 支援 (/clr)
          > 確定


     4. 組態屬性 > C/C++ > 程式碼產生:
          執行階段程式庫: 多執行緒偵錯 DLL (/MDd)
          > 確定

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

E. 其它

     1. 可由專案中的 Form1.h 來切換 Form 的 "程式碼" 與 "設計工具".
         備註: 當專案日漸龐大時, 開啟 "設計工具" 前, 可先執行:
                   建置 > 清除 "該專案" , 以獲得較好的執行效率.

     2. 從 "工具箱" 將某個 "控制項" 拖拉放到 "設計工具" 上,
         點選 "控制項" 元件 > 滑鼠右鍵 > 屬性 > Dock
          ---> 調整該控制項元件的 Dock 位置.

     3. 工具箱 > 事件(閃電符號):
         Mousexxx Event
         ....
         Paint