VC++(MFC) and OpenGL

Hello,
I have written a program to draw a cube using MFC and OpenGL.
I have also written few functions to rotate the cube on mouse movement using Leftbutton down etc…
Everything is working fine .
But the only problem seems to be that every time I move the mouse over the view,the whole view is redrawn again as a result there is some sort of flickering effect.
I am appending the code…please tell me what I am doing wrong…and how can i rectify it…

void CSim_4_26_02View::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
m_lcapture=true;
m_pt=point;

SetCapture();
//CView::OnLButtonDown(nFlags, point);

}

void CSim_4_26_02View::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
if(m_lcapture)
{
m_dz = float(point.y - m_pt.y);
m_dx = float(point.x - m_pt.x);

m_angy += m_dz;
m_angx += m_dx;


}
if(m_rcapture)
{
	m_tz = float(point.y - m_pt1.y)/40.0f;
m_tx = float(point.x - m_pt1.x)/40.0f;

m_inx+=m_tx;
m_iny+=m_tz;

m_inz += (m_dx + m_dz)/2.f;

}
Invalidate(FALSE);
//CallView();

// CView::OnMouseMove(nFlags, point);

}

void CSim_4_26_02View::OnLButtonUp(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
m_lcapture=false;
//CView::OnLButtonUp(nFlags, point);
ReleaseCapture();
}

void CSim_4_26_02View::OnRButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
m_pt1=point;
m_rcapture=true;
ReleaseCapture();
//CView::OnRButtonDown(nFlags, point);
}

void CSim_4_26_02View::OnRButtonUp(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
m_rcapture=false;
// CView::OnRButtonUp(nFlags, point);
}

int CSim_4_26_02View::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_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
} ;
m_d = new CClientDC ( this ) ;

int pixformat = ChoosePixelFormat ( m_d -> m_hDC, &pfd ) ;
SetPixelFormat ( m_d -> m_hDC, pixformat, &pfd ) ;

DescribePixelFormat ( m_d -> m_hDC, pixformat, sizeof ( pfd ), &pfd ) ;


m_hGRC = wglCreateContext ( m_d -> m_hDC ) ;
wglMakeCurrent ( m_d -> m_hDC, m_hGRC ) ;

glShadeModel(GL_SMOOTH);

glClearDepth(1.0f);
glEnable(GL_DEPTH_TEST);

return 1;
}

Bascially I want smooth movement of the cube(on mouse move)…

Thanks,
aus

You must to use a doublebuffered window. You can do it setting in pdfpixelformatdescriptor structure:

pfd.dwFlags = PFD_DRAW_TO_WINDOW |PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;

Also, when you go to draw you must to call:

SwapBuffers (hDC);

Hi !

If that does not help, then you have the background erasing enabled, overload the OnEraseBkgnd() (I think that’s the name on it) and return, hmmm I think it is TRUE to stop Windows from erasing the background every time, this can cause lot’s of flickering.

Mikael

Actually the OnEraseBkgnd() funciton avoids the flickery background, and the returning value does ot matter…

So, if you are using MFC you add

afx_msg BOOL OnEraseBkgnd(CDC* pDC);

to your list of message functions… The implementation of it simply resturns true or false; it does not matter for our OGL purposes…

BOOL view::OnEraseBkgnd(CDC* pDC)
{
return true;
}

If you are using Win32, you simply add

case WM_ERASEBKGND:
{
break;
}

Good luck…

Originally posted by mikael_aronsson:
[b]Hi !

If that does not help, then you have the background erasing enabled, overload the OnEraseBkgnd() (I think that’s the name on it) and return, hmmm I think it is TRUE to stop Windows from erasing the background every time, this can cause lot’s of flickering.

Mikael[/b]

Thanks for your replies.
I have now written the code for BOOL view::OnEraseBkgnd(CDC* pDC)
{
return true;
}

I have also tried what chicho told me
PIXELFORMATDESCRIPTOR pfd = // Structure used to describe the format
{
sizeof(PIXELFORMATDESCRIPTOR),
1, // Version
PFD_DRAW_TO_WINDOW | // Supports GDI
PFD_SUPPORT_OPENGL | // Supports OpenGL
PFD_DOUBLEBUFFER, // Use double buffering (more efficient drawing)
PFD_TYPE_RGBA, // No pallettes
24, // Number of color planes
// in each color buffer
24, 0, // for Red-component
24, 0, // for Green-component
24, 0, // for Blue-component
24, 0, // for Alpha-component
0, // Number of planes
// of Accumulation buffer
0, // for Red-component
0, // for Green-component
0, // for Blue-component
0, // for Alpha-component
32, // Depth of Z-buffer
0, // Depth of Stencil-buffer
0, // Depth of Auxiliary-buffer
0, // Now is ignored
0, // Number of planes
0, // Now is ignored
0, // Color of transparent mask
0 // Now is ignored
};
I have tried using this code in int COGView::OnCreate(LPCREATESTRUCT lpCreateStruct) but now the window is not erased at all as a result I don’t see any object…Do I need to add something else to my code also…

Thanks
aus

Hi
It seems there is a problem whenever i add
PFD_DOUBLEBUFFER to my code.
When i add this statement I cannot see the object infact window is not earsed at all …means the view remains the same like blank or some thing else.
When i remove this line ,I can see the cube …but there is flickering effect…

aus

Are you using SwapBuffers after you draw your scene?

Hi,
Yes I am using Swapbuffer after I have drawn the scene…
void CSim_4_26_02View::OnDraw(CDC* pDC)
{
CSim_4_26_02Doc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here

 	draw3dobject();
	
	SwapBuffers(m_hdc);

}

Thanks,
aus

Instead of using m_hdc, (did you store that, I don’t seem to rmember that being on the basic CView class), maybe you should use the HDC that you are given in the CDC*

SwapBuffers(pDC->GetSafeHdc());

Edit: Changed GetSafeDC to the correct function GetSafeHdc().

[This message has been edited by Deiussum (edited 06-06-2002).]

Hi
I changed it to
SwapBuffers(pDC->GetSafeHdc());
But still no change…
My view is not getting cleared at all…

Is there anything else I need to do…?

Thanks,
aus

I’m not quite sure I understand… you say it’s not getting cleared, but you also say it remains blank, which to me suggests nothing drawing.

Anyway, some other things to check.

  1. Are you clearing both the color buffer bit and the depth buffer bit.
  2. Did you set the view to have a class with the CS_OWNDC style?

(To do this, I do something like so in PreCreateWindow…)

cs.lpszClass = AfxRegisterWndClass(CS_HREDRAW|CS_VREDRAW|CS_OWNDC,
::LoadCursor(NULL, IDC_ARROW), HBRUSH(COLOR_WINDOW+1), NULL);

What i want to say is that ,Before putting doublebuffer statement I can see the cube…but after putting that statement in setpixelformat function i don’t see any thing.
Infact when i move my application my view is filled with the previous view as if it hasn’t been erased.
I hope now you can understand what I am trying to say…

This what I have in precreate window
BOOL CSim_4_26_02View::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs
cs.style |= WS_CLIPSIBLINGS | WS_CLIPCHILDREN;

return CView::PreCreateWindow(cs);

}

also I am using
glClear ( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT ) ;

I think , there is somewhere a small mistake in my code…don’t know where… (I mean I can see the cube but then there is flickering)

Thanks for your help
aus

Try adding the line of code I gave you above to your PreCreateWindow. I’ve had weird effects at times when the CS_OWNDC wasn’t set on the CView-derived class.

Since you say it works when you don’t enabled double buffering, it really sounds like the SwapBuffer isn’t working right. From your code, it should be, though. Maybe just a weird anomaly from not having CS_OWNDC specified, though…

Hi !

Actually the return value from OnEraseBkgnd is very important, if don’t return TRUE, then the Win32 API will not mark it as erased, so it will be erased anyway later on, so please do return TRUE.

Mikael

Thanks for you help,
I did manage to find out the problem…
I have OnDraw as well as OnPaint event in my code.
I had written swapbuffer in ondraw …but not in onpaint…
Now i have added it to onpaint …and its working fine…

Once again thanks for all your help
aus

Why do you have both? Typically MFC codes use one or the other. There are subtle differences. The ondraw is usually used with the MFC Doc/View architecture. I would think you should have only one, either onpaint or ondraw unless you have an indepth understanding of MFC and have ruled out the possibility of further conflict, this could lead to more problems.

See
www.mfcogl.com

Thanks,
I am still learning MFC…
So can anybody clearly explain to me what is the differ in OnPaint and OnDraw and …which should be used and when?

Aus

Have you tried www.mfcogl.com? If that doesn’t satisfy you, you could do some reading in the compiler help, MSDN and some books. Check the references given at mfcogl.

Without going to a lot of work, I think a safe bet would be to use what the App Wizard creates for you or if you create your own MFC program use OnPaint.