www.pudn.com > Gimcrack-v0.0051-Source.zip > opengl.cpp


 #include "opengl.h" 
#include "../global.h" 
 
//////////////////////////////////////////////////////////////////////////////////// 
 
GcOpenGL::GcOpenGL(): 
hRC(NULL), 
hDC(NULL), 
m_hWnd(NULL), 
m_multiTextureSupport(false), 
m_vertexArraySupport(false), 
m_fogSupport(false) 
{ 
	// Constructing the OpenGL object 
} 
 
//////////////////////////////////////////////////////////////////////////////////// 
 
GcOpenGL::~GcOpenGL() 
{ 
	// Destroying the OpenGL object 
} 
 
//////////////////////////////////////////////////////////////////////////////////// 
 
bool GcOpenGL::Init( HWND hParent, int width, int height, int depth ) 
{ 
	m_screenWidth = width; 
	m_screenHeight = height; 
	m_screenDepth = depth; 
 
	// Check for a legal window handle 
	if(!hParent) { 
		return false; 
	} 
 
	m_hWnd = hParent; 
		 
 
	// Set the pixel format 
	if(!SetupPixelFormat())	 
	{ 
		Close(); 
		return false; 
	} 
 
	// Set up the OpenGL window 
	if(!SetupGLWindow())  
	{ 
		Close(); 
		return false; 
	} 
 
	// Set up the OpenGL state machine 
	SetupGLState(); 
 
	return true; 
} 
 
//////////////////////////////////////////////////////////////////////////////////// 
 
bool GcOpenGL::Close() 
{ 
	/* Do We Have A Rendering Context? */ 
	if(hRC) 
	{ 
		/* Are We Able To Release The DC And RC Contexts? */ 
		if(!wglMakeCurrent(NULL, NULL)) 
		{ 
			MessageBox(NULL, "Release of DC and RC failed.", "SHUTDOWN ERROR",  
					   MB_OK | MB_ICONINFORMATION ); 
 
			g_Debug->Log("Release of DC and RC failed.\n"); 
		} 
 
		// Are We Able To Delete The RC? 
		if(!wglDeleteContext(hRC)) 
		{ 
			MessageBox(NULL, "Release rendering context failed.", "SHUTDOWN ERROR",  
					   MB_OK | MB_ICONINFORMATION ); 
 
			g_Debug->Log("Release rendering context failed.\n"); 
		} 
 
		// Set RC To NULL 
		hRC = NULL; 
	} 
 
	/* Are We Able To Release The DC */ 
	if(hDC && m_hWnd) 
	{ 
		if(!ReleaseDC(m_hWnd, hDC)) 
		{ 
			MessageBox(NULL, "Release device context failed.", "SHUTDOWN ERROR",  
					   MB_OK | MB_ICONINFORMATION ); 
 
			g_Debug->Log("Release device context failed.\n"); 
 
			// Set DC To NULL 
			hDC = NULL; 
			m_hWnd = NULL; 
		} 
	} 
 
	return true; 
} 
 
//////////////////////////////////////////////////////////////////////////////////// 
 
void GcOpenGL::SetPerspective(int iWidth, int iHeight) 
{ 
	m_screenWidth = iWidth; 
	m_screenHeight = iHeight; 
 
	/* Reset The Current Viewport */ 
	glViewport( 0, 0, iWidth, iHeight ); 
 
	/* Select The Projection Matrix */ 
	glMatrixMode(GL_PROJECTION); 
	 
	/* Reset The Projection Matrix */ 
	glLoadIdentity(); 
 
	/* Calculate The Aspect Ratio Of The Window */ 
	gluPerspective(45.0f, (GLfloat)iWidth / (GLfloat)iHeight, 4.0f, 15000.0f); 
 
	/* Select The Modelview Matrix */ 
	glMatrixMode(GL_MODELVIEW); 
	glLoadIdentity(); 
} 
 
//////////////////////////////////////////////////////////////////////////////////// 
 
bool GcOpenGL::SetupPixelFormat() 
{ 
	/* Setup the PIXELFORMATDESCRIPTOR */ 
	m_pfd.nSize = sizeof( PIXELFORMATDESCRIPTOR );		/* Size Of This Pixel Format Descriptor */ 
  	m_pfd.nVersion = 1;							/* Version Number */ 
	m_pfd.dwFlags =	PFD_DRAW_TO_WINDOW			/* Format Must Support Window */ 
					| PFD_SUPPORT_OPENGL		/* Format Must Support OpenGL */ 
					| PFD_DOUBLEBUFFER;			/* Must Support Double Buffering */ 
	m_pfd.iPixelType = PFD_TYPE_RGBA;			/* Request An RGBA Format */ 
	m_pfd.cColorBits = m_screenDepth;		/* Select Our Color Depth */ 
	m_pfd.cRedBits = 0;							/* Color Bits Ignored */ 
	m_pfd.cRedShift = 0; 
	m_pfd.cGreenBits = 0; 
	m_pfd.cGreenShift = 0; 
	m_pfd.cBlueBits = 0; 
	m_pfd.cBlueShift = 0; 
	m_pfd.cAlphaBits = 0;					/* No Alpha Buffer */ 
	m_pfd.cAlphaShift = 0;					/* Shift Bit Ignored */ 
	m_pfd.cAccumBits = 0;					/* No Accumulation Buffer */ 
	m_pfd.cAccumRedBits = 0;				/* Accumulation Bits Ignored */ 
	m_pfd.cAccumGreenBits = 0; 
	m_pfd.cAccumBlueBits = 0; 
	m_pfd.cAccumAlphaBits = 0; 
	m_pfd.cDepthBits = 16;					/* 16Bit Z-Buffer (Depth Buffer) */ 
	m_pfd.cStencilBits = 0;					/* No Stencil Buffer */ 
	m_pfd.cAuxBuffers = 0;					/* No Auxiliary Buffer */ 
	m_pfd.iLayerType = PFD_MAIN_PLANE;		/* Main Drawing Layer */ 
	m_pfd.bReserved = 0;					/* Reserved */ 
	m_pfd.dwLayerMask = 0;					/* Layer Masks Ignored */ 
	m_pfd.dwVisibleMask = 0; 
	m_pfd.dwDamageMask = 0; 
		 
	if(!(hDC = GetDC(m_hWnd))) 
	{ 
		Close(); 
		MessageBox(NULL, "Can't create a gl device context.", "ERROR", MB_OK | MB_ICONEXCLAMATION ); 
		g_Debug->Log("Can't create a gl device context.\n"); 
		return false; 
	} 
 
	/* Did Windows Find A Matching Pixel Format? */ 
	if(!( iPixelFormat = ChoosePixelFormat( hDC, &m_pfd))) 
	{ 
		Close(); 
		MessageBox(NULL, "Can't find a suitable pixel format.", "ERROR", MB_OK | MB_ICONEXCLAMATION ); 
		g_Debug->Log("Can't find a suitable pixel format.\n"); 
		return false; 
	} 
 
	/* Are We Able To Set The Pixel Format? */ 
	if(!SetPixelFormat(hDC, iPixelFormat, &m_pfd)) 
	{ 
		Close(); 
		MessageBox(NULL, "Can't set the pixel format.", "ERROR", MB_OK | MB_ICONEXCLAMATION ); 
		g_Debug->Log("Can't set the pixel format.\n"); 
		return false; 
	} 
 
	return true; 
} 
 
//////////////////////////////////////////////////////////////////////////////////// 
 
bool GcOpenGL::SetupGLWindow() 
{ 
		/* Are We Able To Get A Rendering Context? */ 
	if(!(hRC = wglCreateContext(hDC))) 
	{ 
		Close(); 
 
		MessageBox(NULL, "Can't create a GL Rendering context.", "ERROR",  
				   MB_OK | MB_ICONEXCLAMATION ); 
 
		g_Debug->Log("Can't create a GL Rendering context.\n"); 
		return false; 
	} 
 
	/* Try To Activate The Rendering Context */ 
	if(!wglMakeCurrent(hDC, hRC)) 
	{ 
		Close(); 
 
		MessageBox(NULL, "Can't activate the GL Rendering context.", "ERROR",  
				   MB_OK | MB_ICONEXCLAMATION ); 
 
		g_Debug->Log("Can't activate the GL Rendering context.\n"); 
		return false; 
	} 
 
	// Set Up Our Perspective GL Screen 
	SetPerspective(m_screenWidth, m_screenHeight); 
 
	return true; 
} 
 
//////////////////////////////////////////////////////////////////////////////////// 
 
void GcOpenGL::SetupGLState() 
{ 
	// Clear background to black 
	glClearColor(0.0f, 0.0f, 0.0f, 0.0f); 
 
	// Use smooth shading 
	glShadeModel(GL_SMOOTH); 
 
	glEnable(GL_DEPTH_TEST); 
 
	// Don't calculate inside of polys 
	glEnable(GL_CULL_FACE); 
 
	// Counter clockwise polygones cut 
	glFrontFace(GL_CCW); 
 
	// Enable the "colorkey" 
	glEnable(GL_ALPHA_TEST); 
	glAlphaFunc(GL_GREATER, 0.0f); 
 
	// Enable 2D texturing 
	glEnable(GL_TEXTURE_2D); 
 
	// Enable detail texturing if suported 
	SetupMultitexturing(); 
 
	// Enable volumetric fog if suported and desiered 
	SetupFog(); 
 
	// Eanble video memory if suported 
	SetupVertexArrayRange(); 
 
	// Enable vertex and texture coord arrays 
	if(GcSettings::Light()) { 
		glEnableClientState(GL_NORMAL_ARRAY); 
 
		glEnable(GL_LIGHT0);					// Turn on a light with defaults set 
		glEnable(GL_LIGHTING);					// Turn on lighting 
		glEnable(GL_COLOR_MATERIAL);			// Allow color 
	} 
 
	if(GcSettings::ColorArray()) { 
		glEnableClientState(GL_COLOR_ARRAY); 
	} 
} 
 
//////////////////////////////////////////////////////////////////////////////////// 
 
void GcOpenGL::SetupMultitexturing() 
{ 
	// Find out if the card suport multitexturing 
	GcSettings::MultiTexture(CheckSupport("GL_ARB_multitexture",  
						 (char*)glGetString(GL_EXTENSIONS))); 
	m_multiTextureSupport = CheckSupport("GL_ARB_multitexture", (char *)glGetString(GL_EXTENSIONS)); 
 
	// Initialize the multi texturing 
	if(GcSettings::MultiTexture()) // FIX ME: Multitexture? 
	{ 
		glMultiTexCoord2fARB	 = (PFNGLMULTITEXCOORD2FARBPROC) 
									wglGetProcAddress("glMultiTexCoord2fARB"); 
 
		glActiveTextureARB		 = (PFNGLACTIVETEXTUREARBPROC) 
									wglGetProcAddress("glActiveTextureARB"); 
 
		glClientActiveTextureARB = (PFNGLCLIENTACTIVETEXTUREARBPROC) 
									wglGetProcAddress("glClientActiveTextureARB"); 
	} 
	else { 
		g_Debug->Log("Multitexturing not suported\n"); 
	} 
} 
 
//////////////////////////////////////////////////////////////////////////////////// 
 
void GcOpenGL::SetupFog() 
{ 
	// Find out if volumetric fog is supported 
	m_fogSupport = CheckSupport("GL_EXT_fog_coord", (char*)glGetString(GL_EXTENSIONS)); 
 
	// Use fog? 
	if(GcSettings::Fog() && m_fogSupport) 
	{ 
 
		// Get the extension for the volumetric fog 
		glFogCoordPointerEXT = (PFNGLFOGCOORDPOINTEREXTPROC) 
								wglGetProcAddress("glFogCoordPointerEXT"); 
 
		glFogCoordfEXT		 = (PFNGLFOGCOORDFEXTPROC) 
								wglGetProcAddress("glFogCoordfEXT"); 
 
		float color[4] = { 0.8f, 0.8f, 0.8f, 1.0f }; 
		glClearColor(0.8f, 0.8f, 0.8f, 1.0f); 
 
		glEnable(GL_FOG); 
		glFogfv(GL_FOG_COLOR, color); 
		glFogf(GL_FOG_MODE, GL_LINEAR); 
		glFogf(GL_FOG_START, 0.0f); 
		glFogf(GL_FOG_END, 1000.0f); 
		glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT); 
 
		glEnableClientState(GL_FOG_COORDINATE_ARRAY_EXT); 
	} 
	else 
	{ 
		GcSettings::Fog(false); 
	} 
} 
 
//////////////////////////////////////////////////////////////////////////////////// 
 
void GcOpenGL::SetupVertexArrayRange() 
{ 
	// Find out if the vertex data can be stored on the gfx card 
	//settings.VideoMemory(); 
	m_vertexArraySupport = CheckSupport("GL_NV_vertex_array_range", (char *)glGetString(GL_EXTENSIONS)); 
	GcSettings::VideoMemory(m_vertexArraySupport); 
 
	if(m_vertexArraySupport) 
	{ 
		glFlushVertexArrayRangeNV = (PFNGLFLUSHVERTEXARRAYRANGENVPROC) 
									wglGetProcAddress("glFlushVertexArrayRangeNV"); 
 
		glVertexArrayRangeNV	  = (PFNGLVERTEXARRAYRANGENVPROC) 
									wglGetProcAddress("glVertexArrayRangeNV"); 
 
		wglAllocateMemoryNV		  = (PFNWGLALLOCATEMEMORYNVPROC) 
									wglGetProcAddress("wglAllocateMemoryNV"); 
 
		wglFreeMemoryNV			  = (PFNWGLFREEMEMORYNVPROC) 
									wglGetProcAddress("wglFreeMemoryNV"); 
	} 
 
	glEnableClientState(GL_VERTEX_ARRAY); 
	glEnableClientState(GL_TEXTURE_COORD_ARRAY); 
} 
 
//////////////////////////////////////////////////////////////////////////////////// 
 
bool GcOpenGL::CheckSupport(char *check, char *str) 
{ 
	char *endOfStr; 
	uint  i = 0; 
 
	// Last char of the string 
	endOfStr = str + strlen(str); 
 
	while(str < endOfStr) 
	{ 
		// Find a space 
		i = strcspn(str, " "); 
 
		// Check to see if the string match the one looked for 
		if((strlen(check) == i) && (strncmp(check, str, i) == 0)) { 
			return true; 
		} 
 
		str += i + 1; 
	} 
 
	return false; 
} 
 
////////////////////////////////////////////////////////////////////////////////////