MFC에서 OpenGL 사용하는 방법에 대한 설명입니다.
설명과 함께 샘플 파일을 업로드 합니다.
MainFrame Class
Step 1: In the Mainframe Class override the initial dimensions of the default Window. Using the CREATESTRUCT we change the dimensions of the window to 400 x 400
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs
cs.cx=400;
cs.cy=400;
return CFrameWnd::PreCreateWindow(cs);
}
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs
cs.cx=400;
cs.cy=400;
return CFrameWnd::PreCreateWindow(cs);
}
BOOL CMainFrame::OnQueryNewPalette()
{
// TODO: Add your message handler code here and/or call default
CView *pView=GetActiveView();
pView->Invalidate(FALSE);
return CFrameWnd::OnQueryNewPalette();
}
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs
cs.cx=400;
cs.cy=400;
return CFrameWnd::PreCreateWindow(cs);
}
View Class
Step 1: Step up the pixel format and create a rendering context
int CMfc_cubeView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CView::OnCreate(lpCreateStruct) == -1)
return -1;
// TODO: Add your specialized creation code here
PIXELFORMATDESCRIPTOR pfd=
{
sizeof(PIXELFORMATDESCRIPTOR),
1,
PFD_DRAW_TO_WINDOW|
PFD_SUPPORT_OPENGL|
PFD_DOUBLEBUFFER,
PFD_TYPE_RGBA,
24, //24-bit color
0,0,0,0,0,0,
0,0,0,0,0,0,0,
32, //32 bit depth buffer
0,0,
PFD_MAIN_PLANE, //Main layer type
0,
0,0,0
};
CClientDC clientDC(this);
/*
ChoosePixelFormat
Requests a pixel-format index for a pixel format that most closely
matches the format requested. This function's two arguments are a
handle to the DC for which to select the pixel format and the
address of the PIXELFORMATDESCRIPTOR structure that holds the attributes
of the requested pixel format
*/
int pixelFormat =ChoosePixelFormat(clientDC.m_hDC,&pfd);
BOOL success = SetPixelFormat(clientDC.m_hDC,pixelFormat,&pfd);
/*
DescribePixelFormat
Fills a PIXELFORMATDESCRIPTOR structure with information about the given
pixel format. This function's four arguments are a handle to the DC, the
pixel index to examine, and the size and address of PIXELFORMATDESCRIPTOR structure.
*/
DescribePixelFormat(clientDC.m_hDC,pixelFormat, sizeof(pfd),&pfd);
if (pfd.dwFlags & PFD_NEED_PALETTE)
SetupLogicalPalette();
/*
wglCreateContext
Creates a rendering context compatible with the given DC.
*/
m_hRC=wglCreateContext(clientDC.m_hDC);
/*
wglMakeCurrent
Makes a rendering context current, which binds the rendering
context to the given DC. This function's two arguments
are a handle to a DC and the handle to the rendering context.
*/
wglMakeCurrent(clientDC.m_hDC,m_hRC);
//Texture Mapping
//Once you have your DIB loaded and its color tables created, you can
// actually start thinking about your texture mapping
//GL_TEXTURE_2D equates to a two-dimensional texture
//GL_CLAMP for a single image
//GL_REPEAT for a repeating pattern
//GL_TEXTURE_MAG_FILTER determines how a texture is magnified when
// the destination is larger than the texture.
//GL_TEXTURE_MIN_FILTER determines how a texture is reduced
//glTexEnvi set the texturing environment
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_DECAL);
glEnable(GL_DEPTH);
glEnable(GL_TEXTURE_2D);
glClearColor(1.0f,1.0f,1.0f,1.0f);
wglMakeCurrent(clientDC.m_hDC,NULL);
/* CDib is a class used to read Device Independant Bitmaps */
m_pDib = new CDib("snake.BMP");
CreateColorTables(m_pDib);
SetupColorTables();
/* The timer determines the rendering refresh rate in milliseconds*/
SetTimer(1,1,0);
return 0;
}
Step 2: Cleanup resources: Bitmaps, Timers, and device contexts
void CMfc_cubeView::OnDestroy()
{
CView::OnDestroy();
// TODO: Add your message handler code here
KillTimer(1);
delete m_pDib;
/*Frees the Rendering Context. Cleanup of resources*/
wglDeleteContext(m_hRC);
if (m_hPalette)
DeleteObject(m_hPalette);
}
Step 3: Modify the Class style
BOOL CMfc_cubeView::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs
cs.style |= WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
return CView::PreCreateWindow(cs);
}
Step 4: When Invalidate(TRUE) is invoked the OnDraw event is fired. The OnDraw method contains the rendering code portion.
void CMfc_cubeView::OnDraw(CDC* pDC)
{
CMfc_cubeDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
if (m_hPalette)
{
SelectPalette(pDC->m_hDC,m_hPalette, FALSE);
RealizePalette(pDC->m_hDC);
}
wglMakeCurrent(pDC->m_hDC,m_hRC);
DrawWithOpenGL();
SwapBuffers(pDC->m_hDC);
wglMakeCurrent(pDC->m_hDC,NULL);
}
Step 5: The OnSize method defines the current viewport, defines the PROJECTION Model and Object Model, and light sources.
void CMfc_cubeView::OnSize(UINT nType, int cx, int cy)
{
CView::OnSize(nType, cx, cy);
// TODO: Add your message handler code here
CClientDC clientDC(this);
wglMakeCurrent(clientDC.m_hDC,m_hRC);
glViewport(0,0,cx,cy);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-1.0,1.0,-1.0,1.0,2.0,9.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
GLfloat light0Ambient[]={0.0f,0.0f,0.0f,1.0f};
GLfloat light0Diffuse[]={1.0f,1.0f,1.0f,1.0f};
GLfloat light0Position[]={0.0f,0.0f,0.0f,1.0f};
glLightfv(GL_LIGHT0,GL_AMBIENT,light0Ambient);
glLightfv(GL_LIGHT0,GL_DIFFUSE, light0Diffuse);
glLightfv(GL_LIGHT0,GL_POSITION,light0Position);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glTranslatef(0.0f,0.0f,-6.0f);
wglMakeCurrent(NULL,NULL);
}
Step 6: On Timer event is invoke every X predefine miliseconds
void CMfc_cubeView::OnTimer(UINT nIDEvent)
{
// TODO: Add your message handler code here and/or call default
if (m_cube_animate==1 )
{
m_cube_spin+=2;
}
if (m_icosa_animate==1)
{
m_icosa_spin+=2;
}
Invalidate(FALSE);
CView::OnTimer(nIDEvent);
}
Step 7: Your Rendering Code
void CMfc_cubeView::DrawWithOpenGL()
{
glShadeModel(GL_SMOOTH);
glEnable(GL_DEPTH_TEST);
glClearColor(0.0f,0.0f,0.0f,1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
AnimateCube();
}
Step 8: The Animated Cube Example
void CMfc_cubeView::AnimateCube()
{
GLfloat glfMaterialColor[]={0.2f,0.8f,0.5f,1.0f};
GLvoid* pTextureBits = (GLvoid*) m_pDib->GetDibBitsPtr();
GLint width = m_pDib->GetDibWidth();
GLint height = m_pDib->GetDibHeight();
glPushMatrix();
glTexImage2D(GL_TEXTURE_2D,0,3,width,height,0,GL_COLOR_INDEX,
GL_UNSIGNED_BYTE,pTextureBits);
glClear(GL_COLOR_INDEX|GL_DEPTH_BUFFER_BIT);
glRotatef(m_cube_spin,1.0,1.0,1.0);
glScalef (0.5,0.5,0.5); /* modeling transformation */
//glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,glfMaterialColor);
glBegin(GL_POLYGON);
//glNormal3f(0.0f,0.0f,1.0f);
//vertice 1
glTexCoord2f(0.0f,1.0f);
glVertex3f(1.0f,1.0f,1.0f);
//vertice 2
glTexCoord2f(0.0f,0.0f);
glVertex3f(-1.0f,1.0f,1.0f);
//vertice 3
glTexCoord2f(1.0f,0.0f);
glVertex3f(-1.0f,-1.0f,1.0f);
//vertice 4
glTexCoord2f(1.0f,1.0f);
glVertex3f(1.0f,-1.0f,1.0f);
glEnd();
glBegin(GL_POLYGON);
//glNormal3f(0.0f,0.0f,-1.0f);
//vertice 1
glTexCoord2f(0.0f,1.0f);
glVertex3f(1.0f,1.0f,-1.0f);
//vertice 2
glTexCoord2f(0.0f,0.0f);
glVertex3f(1.0f,-1.0f,-1.0f);
//vertice 3
glTexCoord2f(1.0f,0.0f);
glVertex3f(-1.0f,-1.0f,-1.0f);
//vertice 4
glTexCoord2f(0.0f,0.0f);
glVertex3f(-1.0f,1.0f,-1.0f);
glEnd();
glBegin(GL_POLYGON);
//glNormal3f(-1.0f,0.0f,0.0f);
//vertice 1
glTexCoord2f(0.0f,1.0f);
glVertex3f(-1.0f,1.0f,1.0f);
//vertice 2
glTexCoord2f(0.0f,0.0f);
glVertex3f(-1.0f,1.0f,-1.0f);
//vertice 3
glTexCoord2f(1.0f,0.0f);
glVertex3f(-1.0f,-1.0f,-1.0f);
//vertice 4
glTexCoord2f(1.0f,1.0f);
glVertex3f(-1.0f,-1.0f,1.0f);
glEnd();
glBegin(GL_POLYGON);
//glNormal3f(1.0f,0.0f,0.0f);
//vertice 1
glTexCoord2f(0.0f,1.0f);
glVertex3f(1.0f,1.0f,1.0f);
//vertice 2
glTexCoord2f(0.0f,0.0f);
glVertex3f(1.0f,-1.0f,1.0f);
//vertice 3
glTexCoord2f(1.0f,0.0f);
glVertex3f(1.0f,-1.0f,-1.0f);
//vertice 4
glTexCoord2f(1.0f,1.0f);
glVertex3f(1.0f,1.0f,-1.0f);
glEnd();
glBegin(GL_POLYGON);
//glNormal3f(0.0f,1.0f,0.0f);
//vertice 1
glTexCoord2f(0.0f,1.0f);
glVertex3f(-1.0f,1.0f,-1.0f);
//vertice 2
glTexCoord2f(0.0f,0.0f);
glVertex3f(-1.0f,1.0f,1.0f);
//vertice 3
glTexCoord2f(1.0f,0.0f);
glVertex3f(1.0f,1.0f,1.0f);
//vertice 4
glTexCoord2f(1.0f,1.0f);
glVertex3f(1.0f,1.0f,-1.0f);
glEnd();
glBegin(GL_POLYGON);
//glNormal3f(0.0f,-1.0f,0.0f);
//vertice 1
glTexCoord2f(0.0f,1.0f);
glVertex3f(-1.0f,-1.0f,-1.0f);
//vertice 2
glTexCoord2f(0.0f,0.0f);
glVertex3f(1.0f,-1.0f,-1.0f);
//vertice 3
glTexCoord2f(1.0f,0.0f);
glVertex3f(1.0f,-1.0f,1.0f);
//vertice 4
glTexCoord2f(1.0f,1.0f);
glVertex3f(-1.0f,-1.0f,1.0f);
glEnd();
glPopMatrix();
}
void CMfc_cubeView::CreateColorTables(CDib *pDib)
{
LPRGBQUAD pColorTable = pDib->GetDibRGBTablePtr();
for(UINT i=0; i<256; ++i)
{
m_red[i]=(GLfloat) pColorTable[i].rgbRed/255;
m_green[i]=(GLfloat) pColorTable[i].rgbGreen/255;
m_blue[i]=(GLfloat) pColorTable[i].rgbBlue/255;
}
}
void CMfc_cubeView::SetupColorTables()
{
CClientDC clientDC(this);
wglMakeCurrent(clientDC.m_hDC,m_hRC);
glPixelMapfv(GL_PIXEL_MAP_I_TO_R,256,m_red);
glPixelMapfv(GL_PIXEL_MAP_I_TO_G,256,m_green);
glPixelMapfv(GL_PIXEL_MAP_I_TO_B,256,m_blue);
glPixelTransferi(GL_MAP_COLOR,TRUE);
wglMakeCurrent(clientDC.m_hDC,m_hRC);
}
void CMfc_cubeView::SetupLogicalPalette()
{
struct
{
WORD Version;
WORD NumberOfEntries;
PALETTEENTRY aEntries[256];
}logicalPalette={0x300,256};
BYTE reds[]={0,36,72,109,145,182,218,255};
BYTE greens[]={0,36,72,109,145,182,218,255};
BYTE blues[]={0,85,170,255};
for(int colorNum=0; colorNum<256; ++colorNum)
{
logicalPalette.aEntries[colorNum].peRed=reds[colorNum&0x07];
logicalPalette.aEntries[colorNum].peGreen=greens[(colorNum>>0x03)&0x07];
logicalPalette.aEntries[colorNum].peBlue=blues[(colorNum>>0x06)&0x03];
logicalPalette.aEntries[colorNum].peFlags=0;
}
m_hPalette=CreatePalette ((LOGPALETTE*)&logicalPalette);
}
'Robotics > Software Tech.' 카테고리의 다른 글
멀티쓰레드 프로그래밍.. OpenMP로 처리해보자. (12) | 2008.12.28 |
---|---|
UML 2.0을 위한 Microsoft Visio 스텐실 (0) | 2008.12.15 |
표준 라이브러리 (0) | 2008.12.13 |
Sequential Monte Carlo Template Class (0) | 2008.12.09 |
개발자를 위한 객체지향 패러다임 (0) | 2008.12.06 |