Show toolbar

2013年8月27日 星期二

MFC draw face and lighting using OpenGL

標題:MFC使用OpenGL繪製面並打光
MFC (OpenGLglutLight.cpp):
#include <afxwin.h>
#include "OpenGLglut.h"
#include "glut.h"
 
class DocBoxy : public CDocument {
public:
    CClientDC *m_pDC;
    HGLRC hrc;
    DECLARE_DYNCREATE(DocBoxy) //宣告run-time類別
};
 
IMPLEMENT_DYNCREATE(DocBoxy, CDocument) //宣告DocBoxy為run-time類別
 
class FrameBoxy : public CFrameWnd {
public:
    afx_msg void OnExit() { //宣告關閉檔案事件
        if(MessageBox( TEXT("Are you sure you want to close this window?"), TEXT("DocViewBoxy"), MB_OKCANCEL | MB_ICONQUESTION ) == 1 ) {
            DestroyWindow();
        }
    }
    afx_msg void OnAbout() { //宣告關於事件
        MessageBox( TEXT("DocViewBoxy Version 1.0\nCopyright (C) 2013, By QQBoxy Huang.\nEmail: gs1458@gmail.com"), TEXT("About"), MB_OK );
    }
 
    DECLARE_DYNCREATE(FrameBoxy) //宣告run-time類別
    DECLARE_MESSAGE_MAP() //宣告訊息映射表
};
 
IMPLEMENT_DYNCREATE(FrameBoxy, CFrameWnd) //宣告FrameBoxy為run-time類別
 
BEGIN_MESSAGE_MAP(FrameBoxy, CFrameWnd) //建立訊息映射表
    ON_COMMAND(ID_FILE_EXIT, OnExit)
    ON_COMMAND(ID_HELP_ABOUT, OnAbout)
END_MESSAGE_MAP()
 
class ViewBoxy : public CView {
public:
    void OnDraw(CDC * aDC) { //必須覆寫的虛擬函數
        DocBoxy *doc = (DocBoxy *)GetDocument();
        ASSERT_VALID(doc);
         
        glLoadIdentity();
 
        glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
        glTranslatef(0.0f, 0.0f, -7.0f);
        glRotatef(-35.0f, 1.0f, 0.0f, 0.0f);
        glRotatef(-45.0f, 0.0f, 1.0f, 0.0f);
         
        /*glColor3f(1.0f, 0.0f, 0.0f);
        glBegin(GL_LINES);
            glVertex3f(0.0f, 0.0f, 0.0f);
            glVertex3f(20.0f, 0.0f, 0.0f);
        glEnd();
         */

        glColor3f(1.0f, 1.0f, 1.0f);
        glBegin(GL_TRIANGLES);
         
        glNormal3f(-0.8944272f, 0.4472136f, 0.0f);
        glVertex3f(-1.0f, -1.0f, -1.0f);
        glVertex3f(-1.0f, -1.0f, 1.0f);
        glVertex3f(0.0f, 1.0f, 0.0f);
 
        glNormal3f(0.8944272f, 0.4472136f, 0.0f);
        glVertex3f(0.0f, 1.0f, 0.0f);
        glVertex3f(1.0f, -1.0f, 1.0f);
        glVertex3f(1.0f, -1.0f, -1.0f);
 
        glNormal3f(0.0f, -1.0f, 0.0f);
        glVertex3f(1.0f, -1.0f, 1.0f);
        glVertex3f(-1.0f, -1.0f, 1.0f);
        glVertex3f(1.0f, -1.0f, -1.0f);
 
        glNormal3f(0.0f, -1.0f, 0.0f);
        glVertex3f(1.0f, -1.0f, -1.0f);
        glVertex3f(-1.0f, -1.0f, 1.0f);
        glVertex3f(-1.0f, -1.0f, -1.0f);
 
        glNormal3f(0.0f, 0.4472136f, -0.8944272f);
        glVertex3f(0.0f, 1.0f, 0.0f);
        glVertex3f(1.0f, -1.0f, -1.0f);
        glVertex3f(-1.0f, -1.0f, -1.0f);
 
        glNormal3f(0.0f, 0.4472136f, 0.8944272f);
        glVertex3f(-1.0f, -1.0f, 1.0f);
        glVertex3f(1.0f, -1.0f, 1.0f);
        glVertex3f(0.0f, 1.0f, 0.0f);

        //glutWireTeapot(5.0);
        //glutSolidTeapot(5.0);

        glEnd();
 
        glFinish();
        SwapBuffers( doc->m_pDC->GetSafeHdc() );
    }
 
    BOOL PreCreateWindow(CREATESTRUCT& cs) {
        cs.style |= WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
        return CView::PreCreateWindow(cs);
    }
     
    BOOL OnEraseBkgnd(CDC* pDC) {
        return true;
    }
 
    void OnDestroy() {
        DocBoxy *doc = (DocBoxy *)GetDocument();
        HGLRC hRC;
        hRC= wglGetCurrentContext();
        wglMakeCurrent(NULL, NULL);
        if (doc->hrc)
            wglDeleteContext(hRC);
        if (doc->m_pDC)
            delete doc->m_pDC;
        CView::OnDestroy();
    }
 
    bool bSetupPixelFormat() {
        DocBoxy *doc = (DocBoxy *)GetDocument();
        static PIXELFORMATDESCRIPTOR pfd = {
            sizeof(PIXELFORMATDESCRIPTOR), // size of this pfd
            1,                             // version number
            PFD_DRAW_TO_WINDOW |             // support window
            PFD_SUPPORT_OPENGL |           // support OpenGL
            PFD_DOUBLEBUFFER,              // double buffered
            PFD_TYPE_RGBA,                 // RGBA type
            24,                            // 24-bit color depth
            0, 0, 0, 0, 0, 0,              // color bits ignored
            0,                             // no alpha buffer
            0,                             // shift bit ignored
            0,                             // no accumulation buffer
            0, 0, 0, 0,                    // accum bits ignored
            32,                            // 32-bit z-buffer
            0,                             // no stencil buffer
            0,                             // no auxiliary buffer
            PFD_MAIN_PLANE,                // main layer
            0,                             // reserved
            0, 0, 0                        // layer masks ignored
        };
 
        int pixelformat;
 
        if( (pixelformat = ChoosePixelFormat(doc->m_pDC->GetSafeHdc(), &pfd)) == 0 ) {
            MessageBox(_TEXT("ChoosePixelFormat failed"));
            return false;
        }
 
        if(SetPixelFormat(doc->m_pDC->GetSafeHdc(), pixelformat, &pfd) == FALSE) {
            MessageBox(_TEXT("SetPixelFormat failed"));
            return false;
        }
 
        return true;
    }
 
    void init() {
        DocBoxy *doc = (DocBoxy *)GetDocument();
        PIXELFORMATDESCRIPTOR pfd; //宣告一個PixelFormat物件
        int n;
        doc->m_pDC = new CClientDC(this); //建立一個視窗繪圖物件
        ASSERT(doc->m_pDC != NULL);
        if (!bSetupPixelFormat()) return; //設定應用所需的像素格式
        n = GetPixelFormat(doc->m_pDC->GetSafeHdc()); //從Windows裡找尋符合我們設定的
        DescribePixelFormat(doc->m_pDC->GetSafeHdc(), n, sizeof(pfd), &pfd); //PixelFormat的索引值,並將之指定給pfd
        doc->hrc = wglCreateContext(doc->m_pDC->GetSafeHdc()); //將RC物件給DC物件
        wglMakeCurrent(doc->m_pDC->GetSafeHdc(), doc->hrc); //讓這個RC設定為作用中的物件
        glDepthFunc(GL_GREATER);
        glEnable(GL_DEPTH_TEST);
        glClearDepth(-2.0f);
        glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    }
 
    void setLight() {
        GLfloat LightAmbient[]= { 0.5f, 0.5f, 0.5f, 1.0f };  //環境光強度
        GLfloat LightDiffuse[]= { 1.0f, 1.0f, 1.0f, 1.0f };  //光源漫射強度
        GLfloat LightPosition[]= { 1.0f, 0.0f, 0.0f, 0.0f }; //表示在x方向無限遠
 
        glLightfv(GL_LIGHT0, GL_AMBIENT, LightAmbient);
        glLightfv(GL_LIGHT0, GL_DIFFUSE, LightDiffuse);
        glLightfv(GL_LIGHT0, GL_POSITION,LightPosition);
        glEnable(GL_LIGHT0); //使用光源0
        glEnable(GL_LIGHTING); //打光
        glEnable(GL_COLOR_MATERIAL); //啟用材質顏色
    }
 
    int OnCreate(LPCREATESTRUCT lpCreateStruct) {
        if (CView::OnCreate(lpCreateStruct) == -1)
            return -1;
        init();
        setLight();
        return 0;
    }
     
    void OnSize(UINT nType, int cx, int cy) {
        CView::OnSize(nType, cx, cy);
 
        GLfloat nRange=20.f;
        if(cy == 0)
        {  cy = 1;  }
 
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
 
        if (cx <= cy) {
            glOrtho(-nRange, nRange, -nRange*cy/cx, nRange*cy/cx, -nRange, nRange);
        } else {
            glOrtho(-nRange*cx/cy, nRange*cx/cy, -nRange, nRange, -nRange, nRange);
        }
 
        glMatrixMode(GL_MODELVIEW);
        glViewport(0, 0, cx, cy);
    }
 
    DECLARE_DYNCREATE(ViewBoxy) //宣告run-time類別
    DECLARE_MESSAGE_MAP() //宣告訊息映射表
};
 
IMPLEMENT_DYNCREATE(ViewBoxy, CView) //宣告ViewBoxy為run-time類別
 
BEGIN_MESSAGE_MAP(ViewBoxy, CView) //建立訊息映射表
    ON_WM_DESTROY()
    ON_WM_CREATE()
    ON_WM_SIZE()
END_MESSAGE_MAP()
 
class AppBoxy : public CWinApp {
public:
    BOOL InitInstance() {
        CDocument *doc;    //宣告指向文件的指標
        CSingleDocTemplate* DocTemplate; //宣告指向單文件樣版物件的指標
 
        DocTemplate = new CSingleDocTemplate( //建立具有單文件樣版物件
            IDR_MENU, //用於單文件框架之資源的識別子
            RUNTIME_CLASS(DocBoxy), //單文件視窗的Document
            RUNTIME_CLASS(FrameBoxy),    //單文件視窗的視窗框架
            RUNTIME_CLASS(ViewBoxy)      //單文件視窗的View
        );
 
        AddDocTemplate(DocTemplate);   //將單文件樣版物件設定給MyApp
        doc = DocTemplate->CreateNewDocument();    //建立新的文件
 
        m_pMainWnd = DocTemplate->CreateNewFrame( doc, NULL ); //建立一個視窗框架
        DocTemplate->InitialUpdateFrame ( (CFrameWnd*)m_pMainWnd, doc ); //起始化視窗框架物件,並連結View物件
        m_pMainWnd->ShowWindow(SW_SHOW); //顯示視窗
 
        return true;
    }
};
 
AppBoxy appboxy; //建立應用程式物件

說明:
基礎MFC使用OpenGL繪製面並且打光。

沒有留言:

張貼留言