Jump to content
  • Advertisement
Sign in to follow this  
Endar

OGL window problems

This topic is 4820 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I'm not sure its an OGL specific problem, so, its here instead of the OGL forum. I have a simple graphics engine being written (as of today, I have a scene graph with a mesh scene node and a transformation node working!!!) clicky, and here it is, with a rotating quad made from 2 triangles. Try re-sizing the window. Isn't the scene supposed to re-size so it'll fit in the available window? So, what is it that I've left out? Possibly something in the WndProc function?
/**
 * Window message processing function called by windows.
 */
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch(message){
	case WM_PAINT:
		{
			PAINTSTRUCT ps;
			HDC hDC = BeginPaint(hWnd, &ps);
			EndPaint(hWnd, &ps);
		}
		return 0;

	case WM_DESTROY:
		PostQuitMessage(0);
		return 0;

	}

	return DefWindowProc(hWnd, message, wParam, lParam);
}




class CEngine;      // handles window creation
class COpenGLVideo; // inits the window for OGL




Is it WM_SIZE? Okay, if I'm right so far, is there a standard way of getting a pointer to something like one of these objects, without having a global? I hope this post made sense. It's fairly late.

Share this post


Link to post
Share on other sites
Advertisement
Yes, WM_SIZE is what you are looking for. You need to process this message so your viewport gets recalculated. Namely, call glViewport and gluPerspective with values matching the new ones.

Like:
glViewport(0, 0, width, height);

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(fov, (float)width / (float)height, near_clipping, far_clipping);

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

You can store/retreive a pointer using SetWindowLongPtr and GetWindowLongPtr functions.
SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)your_pointer);
your_pointer = (YourPointer*)GetWindowLongPtr(hWnd, GWLP_USERDATA);
Oxyd

Share this post


Link to post
Share on other sites
Quote:
Original post by Endar
Is it WM_SIZE? Okay, if I'm right so far, is there a standard way of getting a pointer to something like one of these objects, without having a global?

I hope this post made sense. It's fairly late.


Yes it's WM_SIZE.

What I do to solve the 'global' issue, is to implement the whole win32 message handling in what I call a Win32Device (I also have a X11Device for linux). Interested classes can subscribe to a device to get updated on certain events. These events are independant from the specific OS, and implented through function callbacks. In case of a window resize (WM_SIZE message) the Win32Device calls Resize(uint x, uint y) on all subscribed classes (obviously these classes must implement the required callback API).

To get resize working in your app, you should call glViewport with the new window size. Also you might want to adjust your frustum. If you don't adjust your frustum, the image will just be stretched. EDIT: as Oxyd said :)

Tom

Share this post


Link to post
Share on other sites

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
// retreive special data, in this case, a pointer to the CEngine object that created the window
core::CEngine* engine = (core::CEngine*)GetWindowLong(hWnd, GWL_USERDATA);


switch(message){
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hDC = BeginPaint(hWnd, &ps);
EndPaint(hWnd, &ps);
}
return 0;

case WM_SIZE:
{
/* wParam == SIZE_RESTORED: The window has been resized, but neither
* the SIZE_MINIMIZED nor SIZE_MAXIMIZED value applies. */

if( wParam == SIZE_RESTORED ){
video::IVideoDriver* d = engine->getVideoDriver();
if( d != NULL )
d->resizeWindow( video::dimension2d(LOWORD(lParam), HIWORD(lParam)) );
}
}
return 0;

case WM_DESTROY:
PostQuitMessage(0);
return 0;

}

return DefWindowProc(hWnd, message, wParam, lParam);
}



Okay, I'm trying to do it this way, but for some reason, the wndProc function is called before I can see the window created, and when I step through, I'm getting an error because 'engine' is NULL.

I'm assuming this is because WndProc is called to create the window and perform whatever is user-defined for WM_CREATE, but then why is it going into WM_SIZE? Because the window has been re-sized from whatever default to what I've specified in the CreateWindow function? Okay, sure, I can see that working, but then, how am I supposed to differentiate between the time that the window is created, but my info hasn't been put in, to when my info is in? I could always check if 'engine' != NULL, but then, release mode doens't NULL memory for you does it?

In case you wanted to know, here's the window creation bit (not the actual CreateWindowEx function, we all know what that looks like):


CEngine::CEngine(const video::dimension2d& screenSize)
: m_videoDriver(NULL), m_hwnd(NULL)
{
if( !createWindow(screenSize) ){ // inits 'm_hwnd' to a valid window handle
util::Message::print("CEngine::CEngine: window could not be created.");
}
else{
util::Message::print("CEngine::CEngine: window creation was successful at %dx%d",
(int)screenSize.width, (int)screenSize.height);

m_videoDriver = new video::COpenGLDriver(screenSize, m_hwnd);
m_sceneManager = new scene::CSceneGraph(m_videoDriver);

// store pointer to this CEngine object for later retrieval in the WndProc function
SetWindowLong(m_hwnd, GWL_USERDATA, (long)this);
}
}




Should I just move the SetWindowLong function to inside the 'createWindow' (CEngine member function) function?

Share this post


Link to post
Share on other sites
I believe WM_SIZE is called early on when a window is created, to set the initial size of the window. Simply do a check against the pointer to your engine and do nothing on a WM_SIZE if the pointer is NULL. I believe I have to do this in my own program.

Share this post


Link to post
Share on other sites
Will that still work in the release build? I thought that memory was only zero'd out when you compiled and ran the debug build.

Or does the CreateWindow function zero out the memory for the window before creating it?

Share this post


Link to post
Share on other sites
Quote:
Original post by Endar
Will that still work in the release build? I thought that memory was only zero'd out when you compiled and ran the debug build.


Yes, it will. You are right about zeroing memory only in debug build, but it's defined that GWL_USERDATA field is set to zero until you assign it some other value.

Quote:
MSDN
GWLP_USERDATA
Retrieves the user data associated with the window. This data is intended for use by the application that created the window. Its value is initially zero.


Oxyd

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!