PDA

View Full Version : VC++(MFC) and OpenGL



aus79er
06-04-2002, 08:57 AM
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

chicho
06-04-2002, 10:19 PM
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);

mikael_aronsson
06-05-2002, 03:20 AM
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

Miguel_dup1
06-05-2002, 11:39 AM
Actually the OnEraseBkgnd() funciton avoids the flickery background, and the returning value does ot matter... http://www.opengl.org/discussion_boards/ubb/smile.gif

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:
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

aus79er
06-05-2002, 02:39 PM
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

aus79er
06-05-2002, 02:47 PM
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

Deiussum
06-06-2002, 05:08 AM
Are you using SwapBuffers after you draw your scene?

aus79er
06-06-2002, 07:44 AM
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

Deiussum
06-06-2002, 10:09 AM
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(). http://www.opengl.org/discussion_boards/ubb/smile.gif

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

aus79er
06-06-2002, 10:21 AM
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

Deiussum
06-06-2002, 12:00 PM
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);

aus79er
06-06-2002, 02:03 PM
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.. http://www.opengl.org/discussion_boards/ubb/smile.gif(I mean I can see the cube but then there is flickering)


Thanks for your help
aus

Deiussum
06-07-2002, 05:15 AM
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...

mikael_aronsson
06-07-2002, 06:05 AM
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

aus79er
06-07-2002, 10:26 AM
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

J P
06-08-2002, 07:14 AM
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 (http://www.mfcogl.com)

aus79er
06-08-2002, 09:50 AM
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

J P
06-09-2002, 03:52 AM
Have you tried www.mfcogl.com? (http://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.