⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 oglwindow.cpp

📁 游戏编程精粹6中关于用自适度二叉树进行空间剖分
💻 CPP
字号:
#include "OGLWindow.h"

/* ***************************************************************** *\
|  CONSTRUCTION / DESTRUCTION
\* ***************************************************************** */
cOGLWindow::cOGLWindow(HINSTANCE p_Instance)
	: m_hInstance(p_Instance),
 	  m_hWnd(NULL),
	  m_hDC(NULL),
	  m_hRC(NULL),
	  m_bIsFullScreen(false),
	  m_bIsVisible(true),
	  m_iFrames(0),
	  m_iNumTriangles(0),
	  m_iHeight(0),
	  m_iWidth(0)
{
	memset(m_bKeyDown, 0, sizeof(m_bKeyDown));
}

cOGLWindow::~cOGLWindow()
{
	// cleanup and destroy window
	destroy();
}

/* ***************************************************************** *\
|  create
|  *****************************************************************
|  Creates a window ready to be used for rendering.
\* ***************************************************************** */
boolean cOGLWindow::create(TCHAR *p_Title, int32 p_Width, int32 p_Height, boolean p_Fullscreen)
{
	DWORD windowStyle = WS_OVERLAPPEDWINDOW;
	DWORD windowExtendedStyle = WS_EX_APPWINDOW;

	PIXELFORMATDESCRIPTOR pfd = { sizeof (PIXELFORMATDESCRIPTOR), 1, 
		PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, 
		PFD_TYPE_RGBA, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
		24, 0, 0, PFD_MAIN_PLANE, 0, 0, 0, 0 };

	RECT windowRect = {0, 0, p_Width, p_Height};
	GLuint PixelFormat;

	if(p_Fullscreen)
	{
		if(!changeScreenResolution(p_Width, p_Height))
		{
			// Fullscreen Mode Failed.  Run In Windowed Mode Instead
			MessageBox (HWND_DESKTOP, "Mode Switch Failed.\nRunning In Windowed Mode.", "Error", MB_OK | MB_ICONEXCLAMATION);
			p_Fullscreen = false;
		}
		else
		{
			ShowCursor(FALSE);
			windowStyle = WS_POPUP;
			windowExtendedStyle |= WS_EX_TOPMOST;
		}
	}
	else
	{
		// Adjust Window, Account For Window Borders
		AdjustWindowRectEx (&windowRect, windowStyle, 0, windowExtendedStyle);
	}

	// Create The OpenGL Window
	m_hWnd = CreateWindowEx (windowExtendedStyle, m_szClassName, p_Title, windowStyle, 0, 0,
		windowRect.right - windowRect.left, windowRect.bottom - windowRect.top, HWND_DESKTOP,
		NULL, m_hInstance, this);

	if(!m_hWnd)
		return false;

	// get device context from this window
	m_hDC = GetDC(m_hWnd);
	if(!m_hDC)
	{
		// Failed
		DestroyWindow(m_hWnd);
		m_hWnd = NULL;
		return false;
	}

	// find a comp. pixel format
	PixelFormat = ChoosePixelFormat(m_hDC, &pfd);
	if(!PixelFormat)
	{
		// Failed
		ReleaseDC (m_hWnd, m_hDC);
		m_hDC = NULL;
		DestroyWindow(m_hWnd);
		m_hWnd = NULL;
		return false;
	}

	// set the pixel format
	if(!SetPixelFormat(m_hDC, PixelFormat, &pfd))		// Try To Set The Pixel Format
	{
		// Failed
		ReleaseDC (m_hWnd, m_hDC);
		m_hDC = NULL;
		DestroyWindow(m_hWnd);
		m_hWnd = NULL;
		return false;
	}

	// get an ogl rendering context
	m_hRC = wglCreateContext(m_hDC);
	if(!m_hRC)
	{
		// Failed
		ReleaseDC (m_hWnd, m_hDC);
		m_hDC = NULL;
		DestroyWindow(m_hWnd);
		m_hWnd = NULL;
		return false;
	}

	// set current rendering context
	if(!wglMakeCurrent(m_hDC, m_hRC))
	{
		// Failed
		wglDeleteContext (m_hRC);
		m_hRC = NULL;
		ReleaseDC (m_hWnd, m_hDC);
		m_hDC = NULL;
		DestroyWindow(m_hWnd);
		m_hWnd = NULL;
		return false;
	}

	// create a console for error/status output
	if(!AllocConsole())
		MessageBox(NULL, _T("Failed to create a console!"), _T("Error"), MB_OK | MB_ICONERROR);
	else
		_tfreopen(_T("CONOUT$"), _T("wb"), stdout);

	// show our window
	ShowWindow(m_hWnd, SW_NORMAL);	
	m_bIsVisible = true;

	// save window properties
	m_iWidth  = p_Width;
	m_iHeight = p_Height;
	m_bIsFullScreen = p_Fullscreen;

	return true;
}

/* ***************************************************************** *\
|  destroy
|  *****************************************************************
|  Destroys a previously created window.
\* ***************************************************************** */
void cOGLWindow::destroy()
{
	// destroy ab-tree
	m_ABT.release();

	if(m_hWnd)
	{
		if(m_hDC)
		{
			// reset rendering context
			wglMakeCurrent(m_hDC, 0);
			if(m_hRC)
			{
				// delete rendering context
				wglDeleteContext (m_hRC);
				m_hRC = NULL;

			}
			// release the device context
			ReleaseDC(m_hWnd, m_hDC);
			m_hDC = NULL;
		} 

		// destroy the window
		DestroyWindow(m_hWnd);
		m_hWnd = NULL;
	}

	// don't forget to restore the mouse cursor!
	if(m_bIsFullScreen)
	{
		// reset display settings (resolution)
		ChangeDisplaySettings(NULL,0);
		ShowCursor(TRUE);
	}	

	// free the console
	fclose(stdout);
	FreeConsole();
}


/* ***************************************************************** *\
|  registerClass
|  *****************************************************************
|  Registers our window's class.
\* ***************************************************************** */
boolean cOGLWindow::registerClass()
{
	// Register A Window Class
	WNDCLASSEX windowClass;
	ZeroMemory (&windowClass, sizeof (WNDCLASSEX));
	windowClass.cbSize			= sizeof (WNDCLASSEX);
	windowClass.style			= CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
	windowClass.lpfnWndProc		= (WNDPROC)(WindowProc);
	windowClass.hInstance		= m_hInstance;
	windowClass.hbrBackground	= (HBRUSH)NULL;
	windowClass.hCursor			= LoadCursor(NULL, IDC_ARROW);
	windowClass.lpszClassName	= m_szClassName;

	// register class
	if(RegisterClassEx(&windowClass) == 0)
	{
		// NOTE: Failure, Should Never Happen
		MessageBox(HWND_DESKTOP, _T("RegisterClassEx Failed!"), _T("Error"), MB_OK | MB_ICONERROR);
		return false;
	}
	return true;
}

/* ***************************************************************** *\
|  unregisterClass
|  *****************************************************************
|  Unregisters a previously registered class
\* ***************************************************************** */
void cOGLWindow::unregisterClass()
{
	// UnRegister Window Class
	UnregisterClass(m_szClassName, m_hInstance);
}

/* ***************************************************************** *\
|  init
|  *****************************************************************
|  Initializes the OpenGL rendering context
\* ***************************************************************** */
boolean cOGLWindow::init()
{
	// init our ABT
	m_ABT.create();

	// init gl states
	glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
	glClearDepth(1.0f);
	glDepthFunc(GL_LEQUAL);
	glEnable(GL_DEPTH_TEST);
	glShadeModel(GL_SMOOTH);
	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
	glDisable(GL_TEXTURE_2D);
	glColor4f(1.0f, 1.0f, 1.0f, 1.0f);

	GLfloat lightDiffuse[]= { 0.8f, 0.8f, 0.8f, 1.0f };					 // Diffuse Light Values 
	GLfloat	lightPosition[]= { 0.0f, 0.0f, 2.0f, 1.0f };				 // Light Position   

	glLightfv(GL_LIGHT0, GL_DIFFUSE, lightDiffuse);
	glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);
	glEnable(GL_LIGHT0);
	glEnable(GL_LIGHTING);

	// init viewport and matrices
	resizeGL(m_iWidth, m_iHeight);

	// init fps counter
	m_iLastFPS = GetTickCount();

	return true;
}

/* ***************************************************************** *\
|  update
|  *****************************************************************
|  Updates the scene
\* ***************************************************************** */
void cOGLWindow::update(uint32 p_Milliseconds)
{
	float32 fTransX = 0.0f;
	float32 fTransY = 0.0f;
	float32 fTransZ = 0.0f;
	float32 fRotX = 0.0f;
	float32 fRotY = 0.0f;

	if(m_bKeyDown[VK_UP])
	{
		fTransZ = ((float) ( p_Milliseconds ) / 10.0f * 25.0f);
	}
	if(m_bKeyDown[VK_DOWN])
	{
		fTransZ = -(float) ( p_Milliseconds ) / 10.0f * 25.0f;
	}

	if(m_bKeyDown[VK_RIGHT])
	{
		fTransX = -((float) ( p_Milliseconds ) / 10.0f * 25.0f);
	}
	if(m_bKeyDown[VK_LEFT])
	{
		fTransX = (float) ( p_Milliseconds ) / 10.0f * 25.0f;
	}

	if(m_bKeyDown[VK_PRIOR])
	{
		fTransY = -((float) ( p_Milliseconds ) / 10.0f * 25.0f);
	}
	if(m_bKeyDown[VK_NEXT])
	{
		fTransY = (float) ( p_Milliseconds ) / 10.0f * 25.0f;
	}

	if(m_bKeyDown['W'])
	{
		fRotX = -(float) ( p_Milliseconds ) / 1000.0f * 25.0f;
	}
	if(m_bKeyDown['S'])
	{
		fRotX = ((float) ( p_Milliseconds ) / 1000.0f * 25.0f);
	}

	if(m_bKeyDown['D'])
	{
		fRotY = ((float) ( p_Milliseconds ) / 1000.0f * 25.0f);
	}
	if(m_bKeyDown['A'])
	{
		fRotY = -((float) ( p_Milliseconds ) / 1000.0f * 25.0f);
	}
	// on escape close the application
	if(m_bKeyDown[VK_ESCAPE])
	{
		PostMessage(m_hWnd, WM_QUIT, 0, 0);
	}

	// update the camera pos/orientation
	GLfloat	curMat[16];

	glGetFloatv(GL_MODELVIEW_MATRIX, curMat);
    
	glLoadIdentity();
	glRotatef(fRotY, 0.0f, 1.0f, 0.0f);
	glTranslatef(fTransX, fTransY, fTransZ);
	glRotatef(fRotX, 1.0f, 0.0f, 0.0f);
	glMultMatrixf(curMat);
}

/* ***************************************************************** *\
|  draw
|  *****************************************************************
|  Draws the current scene
\* ***************************************************************** */
void cOGLWindow::draw()
{
	// clear screen
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	// render the ABT
	int iNumRenderedTris = m_ABT.render();

	// determine FPS
	if(GetTickCount() - m_iLastFPS >= 1000) // When A Second Has Passed...
	{
		m_iLastFPS = GetTickCount();
		TCHAR szTitle[256];
		_stprintf(szTitle, _T("GPG6 - ABT (%d FPS, %d Tris)"), m_iFrames, iNumRenderedTris);
		SetWindowText(m_hWnd, szTitle);
		m_iFrames = 0;
	}
	m_iFrames++;

	// draw the scene
	SwapBuffers(m_hDC);
}

/* ***************************************************************** *\
|  changeScreenResolution
|  *****************************************************************
|  Changes the screen resolution
\* ***************************************************************** */
boolean cOGLWindow::changeScreenResolution(uint32 p_Width, uint32 p_Height)
{
	DEVMODE dmScreenSettings;

	// init new screen settings
	ZeroMemory (&dmScreenSettings, sizeof(DEVMODE));
	dmScreenSettings.dmSize			= sizeof(DEVMODE);
	dmScreenSettings.dmPelsWidth	= p_Width;
	dmScreenSettings.dmPelsHeight	= p_Height;
	dmScreenSettings.dmBitsPerPel	= 32;
	dmScreenSettings.dmFields		= DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;

	// change resolution
	if(ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL)
		return false;

	return true;
}

/* ***************************************************************** *\
|  resizeGL
|  *****************************************************************
|  Initializes the opengl matrices
\* ***************************************************************** */
void cOGLWindow::resizeGL(uint32 p_Width, uint32 p_Height)
{
	glViewport(0, 0, (GLsizei)(p_Width), (GLsizei)(p_Height));
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	// this projection matrix maybe seems akward ... but we get problems with z-fighting
	// otherwise (when using the powerplant model)
	gluPerspective(45.0f, (GLfloat)(p_Width)/(GLfloat)(p_Height), 100.0f, 100000.0f);		
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	glRotatef(180.0f, 0.0f, 1.0f, 0.0f);
	glTranslatef(0.0f, 300.0f, 300.0f);
	glScalef(0.5f, 0.5f, 0.5f);
}

/* ***************************************************************** *\
|  WindowProc
|  *****************************************************************
|  Window message procedure
\* ***************************************************************** */
LRESULT CALLBACK cOGLWindow::WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	// Get The Window Context
	cOGLWindow* window = (cOGLWindow*)(GetWindowLongPtr(hWnd, GWL_USERDATA));

	switch (uMsg)														
	{
		case WM_SYSCOMMAND:
			{
				switch (wParam)
				{
					case SC_SCREENSAVE:		// Screensaver Trying To Start?
					case SC_MONITORPOWER:	// Monitor Trying To Enter Powersave?
						return 0;			// Prevent From Happening
				}
				break;
			}
			return 0;

		case WM_CREATE:
			{
				// store a reference to our window class ...
				CREATESTRUCT* creation = (CREATESTRUCT*)(lParam);
				window = (cOGLWindow*)(creation->lpCreateParams);
				SetWindowLongPtr(hWnd, GWL_USERDATA, (LONG_PTR)window);
			}
			return 0;

		case WM_CLOSE:
			PostMessage(window->m_hWnd, WM_QUIT, 0, 0);
			return 0;

			// window resized
		case WM_SIZE:
			switch(wParam)
			{
				case SIZE_MINIMIZED:
					window->m_bIsVisible = false;
					return 0;

				case SIZE_MAXIMIZED:
					window->m_bIsVisible = true;
					window->resizeGL(LOWORD(lParam), HIWORD(lParam));
					return 0;

				case SIZE_RESTORED:
					window->m_bIsVisible = true;
					window->resizeGL(LOWORD(lParam), HIWORD(lParam));
					return 0;
			}
			break;

		case WM_KEYDOWN:
			if ((wParam >= 0) && (wParam <= 255))
			{
				// Set The Selected Key (wParam) To True
				window->m_bKeyDown[wParam] = true;
				return 0;
			}
			break;

		case WM_KEYUP:
			if ((wParam >= 0) && (wParam <= 255))
			{
				window->m_bKeyDown[wParam] = false;
				return 0;
			}
			break;
	}

	// forward to default window proc ...
	return DefWindowProc (hWnd, uMsg, wParam, lParam);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -