2013년 5월 15일

C++ 빌더에서 오픈지엘 사용하기



glskeleton.h

//--------------------------------------------------------------------------- 
#include <vclvcl.h> 

//--------------------------------------------------------------------------- 
#ifndef GLSkeletonH 
#define GLSkeletonH 
//--------------------------------------------------------------------------- 
#include <vclClasses.hpp> 
#include <vclControls.hpp> 
#include <vclStdCtrls.hpp> 
#include <vclForms.hpp> 
#include <gl/gl.h> 
#include <gl/glu.h> 
//--------------------------------------------------------------------------- 
class TForm1 : public TForm 
{ 
published:    // IDE-managed Components 
    void __fastcall FormCreate(TObject *Sender); 
    void __fastcall FormDestroy(TObject *Sender); 
    void __fastcall FormResize(TObject *Sender); 
    void __fastcall FormPaint(TObject *Sender); 
private:    // User declarations 
    HDC hdc;
    HGLRC hrc; 
    int PixelFormat; 
public:        // User declarations 
    fastcall TForm1(TComponent* Owner); 
    void __fastcall IdleLoop(TObject*, bool&); 
    void __fastcall RenderGLScene(); 
    void __fastcall SetPixelFormatDescriptor(); 
}; 

glskeleton.cpp
//--------------------------------------------------------------------------- 
extern TForm1 *Form1; 
//--------------------------------------------------------------------------- 
#endif 

//--------------------------------------------------------------------------- 
#include <vclvcl.h> 
#pragma hdrstop 

#include "GLSkeleton.h" 
//--------------------------------------------------------------------------- 
#pragma resource "*.dfm" 

TForm1 *Form1; 
//--------------------------------------------------------------------------- 
__fastcall TForm1::TForm1(TComponent* Owner) 
    : TForm(Owner) 
{ 
    Application->OnIdle = IdleLoop; 
    _control87(MCW_EM, MCW_EM);
} 
//--------------------------------------------------------------------------- 
void __fastcall TForm1::IdleLoop(TObject*, bool& done) 
{ 
     done = false; 
     RenderGLScene(); 
     SwapBuffers(hdc); 
} 
//--------------------------------------------------------------------------- 
void __fastcall TForm1::RenderGLScene() 
{ 
     //Place your OpenGL drawing code here
} 
//--------------------------------------------------------------------------- 
void __fastcall TForm1::FormCreate(TObject *Sender) 
{ 
    hdc = GetDC(Handle); 
    SetPixelFormatDescriptor(); 
    hrc = wglCreateContext(hdc); 
    wglMakeCurrent(hdc, hrc); 
    SetupRC(); 
} 
//--------------------------------------------------------------------------- 
void __fastcall TForm1::SetupRC() 
{ 
    glClearColor(1.0f, 1.0f, 1.0f, 1.0f); 
    glClear(GL_COLOR_BUFFER_BIT); 
    glFlush(); 
} 
//--------------------------------------------------------------------------- 
void __fastcall TForm1::FormDestroy(TObject *Sender) 
{ 
    ReleaseDC(hdc);
    wglMakeCurrent(hdc, NULL); 
    wglDeleteContext(hrc); 
} 
//--------------------------------------------------------------------------- 
void __fastcall TForm1::SetPixelFormatDescriptor() 
{ 
    PIXELFORMATDESCRIPTOR pfd = { 
        sizeof(PIXELFORMATDESCRIPTOR), 
        1, 
        PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, 
        PFD_TYPE_RGBA, 
        24, 
        0,0,0,0,0,0, 
        0,0, 
        0,0,0,0,0, 
        32, 
        0, 
        0, 
        PFD_MAIN_PLANE, 
        0, 
        0,0,0 
        }; 
    PixelFormat = ChoosePixelFormat(hdc, &pfd); 
    SetPixelFormat(hdc, PixelFormat, &pfd); 
} 
//--------------------------------------------------------------------------- 
void __fastcall TForm1::FormResize(TObject *Sender) 
{ 
    GLfloat nRange = 200.0f; 
    glViewport(0, 0, ClientWidth, ClientHeight); 
    glMatrixMode(GL_PROJECTION); 
    glLoadIdentity(); 
 
    
    if (ClientWidth <= ClientHeight) 
       glOrtho(-nRange, nRange, -nRange*ClientHeight/ClientWidth, 
          nRange*ClientHeight/ClientWidth, -nRange, nRange); 
    else 
       glOrtho(-nRange*ClientWidth/ClientHeight, nRange*ClientWidth/ClientHeight, 
          -nRange, nRange, -nRange, nRange); 

    glMatrixMode(GL_MODELVIEW); 
    glLoadIdentity(); 
} 
//--------------------------------------------------------------------------- 



위 코드는 C++ 빌더의 VCL 을 사용하는 환경에서 OPENGL 을 사용할 경우 기본적인 뼈대가 되는 코드이다
  • 몇몇 환경에서는 부동소수점 예외가 발생하는데 이때는 _control87(MCW_EM, MCW_EM); 을 사용하여 연산과정중 opengl 내부에서 발생한 예외를 지긋이 disable 시키자. 

  • 뷰가 여러개 있을 경우에는 렌더링 타켓이 바뀌는 경우가 있기 때문에 항상 새로그리기 전에는 wglMakeCurrent(hdc, hrc); 을 사용하여 타켓을 변경하도록 하자. 

  • 위 예에서는 IdleLoop 즉 윈도우 메시지 처리할것이 없을때 화면을 주기적으로 갱신하고 있는데, 지속적인 렌더링이 필요없는 경우에는 OnPaint 즉 영역을 다시 그리는것이 필요할때만 그려도 무방하다. 

댓글 없음:

댓글 쓰기

시리우스 라이브러리 홈페이지 오픈

현재 시리우스(Sirius) 라이브러리라는 제품을 개발하고 이를 소개하는 홈페이지를 오픈 하였습니다. 관심있는 분들의 많은 방문 요청드립니다. 앞으로 업데이트 소식및 변경사항은 스파이럴랩 홈페이지를 통해 진행할 예정입니다. 스파이럴랩 홈페이지 :  h...