www.pudn.com > LodFiled.rar > MAIN.CPP


 
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#define INITGUID 
#include  
#include  
#include "mouse.h" 
#include "useful.h" 
#include "bmp_load.h" 
#include "terrain.h" 
#include "lod.h" 
 
// Definitions. 
 
#define TRUE 1 
#define FALSE 0 
#define WIDTH 4.0 
 
#define ZOOMSIZE 4 
 
// Function prototypes. 
LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam ); 
VOID EnableOpenGL( HWND hWnd, HDC * hDC, HGLRC * hRC ); 
VOID DisableOpenGL( HWND hWnd, HDC hDC, HGLRC hRC ); 
 
void triangle1(int , int , int , int , int , int ); 
void triangle2(int , int , int , int , int , int ); 
void (* triangle)(int , int , int , int , int , int ); 
 
 
HWND main_window_handle; 
HINSTANCE main_instance = NULL; // save the instance 
 
int winWidth = 400;   
int winHeight = 300; 
 
int bilinear_filtering = 1; 
int wireframe_mode = -1; 
int flying_mode = 1; 
int detail_texture_mode = -1; 
 
#define texScale 64.0 // This stretches one texture over an 8x8 area. 
 
GLuint texName[100]; 
 
GLfloat xpos, ypos, zpos;  
GLfloat lookx, looky, lookz; // The current direction. 
GLint mapX = 128, mapZ = 128; // The area of the map where the map screen is viewing. 
GLfloat speed = 0.0; // The current forward velocity. 
GLfloat timer = 0.0, wTimer = 0.0; 
GLint mapOffset = 4096; 
 
GLfloat lightPosition[] = {-1.0, 0.0, 0.2, 0.0}; 
 
float sin_t[256]; 
float cos_t[256]; 
 
LPDIRECTINPUT        lpdi      = NULL;    // dinput object 
LPDIRECTINPUTDEVICE  lpdimouse   = NULL;  // dinput mouse 
LPDIRECTINPUTDEVICE  lpdikey   = NULL;  // dinput keyboard 
DIMOUSESTATE mouse_state; 
UCHAR keystate[256]; 
 
LAND_TEX lt; 
 
TEXTURE *detail_texture; 
 
unsigned short int fov = 16; // Field of view. e.g. (-16, -16) to (16, 16) 
 
int fps = 0; 
double c1, c2; 
 
void exitTerrain(void)  
{ 
	delete[] y; 
	delete[] colour_map; 
	destroy_bmp(detail_texture); 
} 
 
__inline float height_w(float x, float z)  
{ 
	return (sin(x+timer)+sin(z+timer))*16 + 32; 
} 
 
void check_height(void)  
{ 
	 
	float x0, x1, lx, lz, x, z, midpoint; 
	int fx, fz; 
	 
	x = xpos/(COMP*1.0); 
	z = zpos/(COMP*1.0); 
	fx = (int)(x); 
	fz = (int)(z); 
	lx = x - fx; 
	lz = z - fz; 
	 
	x0 = y[IX(fx,fz)] + (y[IX(fx,fz+1)] - y[IX(fx,fz)])*lz; 
	x1 = y[IX(fx+1,fz)] + (y[IX(fx+1,fz+1)] - y[IX(fx+1,fz)])*lz; 
	midpoint = x0 + (x1 - x0)*lx; 
 
	if(flying_mode	> 0)  
	{ 
		ypos = (midpoint * 8) + 1024.0f; 
	} 
	else  
	{ 
		ypos = (midpoint * 8) + 16.0f; 
	} 
 
	if(x<0) 
		xpos = 0; 
	else if(x>(M_SIZE)) 
		xpos = ((M_SIZE) << SHIFT); 
	if(z<0) 
		zpos = 0; 
	else if(z>(M_SIZE)) 
		zpos = ((M_SIZE) << SHIFT); 
	 
} 
 
float get_height(float xp, float zp)  
{ 
	 
	float x0, x1, lx, lz, x, z, midpoint; 
	int fx, fz; 
	 
	x = xp/(COMP*1.0); 
	z = zp/(COMP*1.0); 
	fx = (int)(x); 
	fz = (int)(z); 
	lx = x - fx; 
	lz = z - fz; 
	 
	x0 = y[IX(fx,fz)] + (y[IX(fx,fz+1)] - y[IX(fx,fz)])*lz; 
	x1 = y[IX(fx+1,fz)] + (y[IX(fx+1,fz+1)] - y[IX(fx+1,fz)])*lz; 
	midpoint = x0 + (x1 - x0)*lx; 
	 
	if(midpoint < 0.0f)  
	{ 
		return 0.0f; 
	} 
	else  
	{ 
		return midpoint; 
	} 
} 
 
 
// Function that moves the eye / turns the angle of sight. 
// Updates scene if update != 0.  
void move(int type, GLfloat amount, int update) 
{ 
	GLfloat a; 
	switch(type) 
	{ 
	case FORWARD: 
		xpos += lookx * amount; 
		zpos += lookz * amount; 
		break; 
	case ROTATE: 
		lookx = lookx*cos(amount) + lookz*sin(amount); 
		lookz = lookz*cos(amount) - lookx*sin(amount); 
		/* lookx^2 + lookz^2 != 1 for some reason. Fix. */ 
		a = 1/sqrt(lookx*lookx + lookz*lookz); 
		lookx *= a; 
		lookz *= a; 
		break; 
	case LOOKUP: 
		looky += amount; 
		break; 
	} 
	 
	if (update) 
	{ 
		check_height(); 
		glMatrixMode(GL_MODELVIEW);  
		glLoadIdentity(); 
		 
		glLightfv(GL_LIGHT0, GL_POSITION, lightPosition); 
	} 
} 
 
void initTerrain(void)  
{ 
	y = new int[M_SIZE*M_SIZE]; 
	if(!y)  
	{ 
		cout << "ERROR - Unable to allocate memory for height map." << endl; 
	} 
	else  
	{ 
		cout << "Succesfully allocated memory for height map." << endl; 
	} 
	colour_map = new COLOUR[M_SIZE*M_SIZE]; 
	if(!colour_map)  
	{ 
		cout << "ERROR - Unable to allocate memory for shadow map." << endl; 
	} 
	else  
	{ 
		cout << "Succesfully allocated memory for shadow map." << endl; 
	} 
} 
 
__inline int checkRange(int a)  
{ 
	if(a>255)  
	{ 
		a = 255; 
	} 
	else if(a<0)  
	{ 
		a = 0; 
	} 
	 
	return a; 
} 
 
__inline int distance(int x1, int z1, int x2, int z2)  
{ 
	return sqrt((x2-x1)*(x2-x1) + (z2-z1)*(z2-z1)); 
} 
 
void colorTerrain(void)  
{ 
	int x, z; 
	int h; 
	 
	for(x=0; x255) 		 
				h = 255;			 
			else if(h<0)			 
				h = 0;  
									 
			colour_map[IX(x, z)].r = h; 
			colour_map[IX(x, z)].g = h; 
			colour_map[IX(x, z)].b = h; 
		} 
	} 
	 
	lt.NEW_BITMAP(texName, y); 
} 
 
#ifndef f4 
#define f4(a, b, c, d) ((a) + (b) + (c) + (d)) / 4 
#endif 
 
void randomTerrain(void)  
{ 
	int x, z; 
	int i, j; 
	int bsize, csize; 
	int rnd; 
	//  将所有的地形高程数据清零	 
	for(i=0; i<(M_SIZE*M_SIZE); i++)  
	{ 
		y[i] = 0; 
	} 
	bsize = M_SIZE; 
	csize = M_SIZE/2; 
	rnd = 256; 
	//  获取随机高程数据值	 
	while(csize > 0)  
	{ 
		for(x=0; x1.0)  
	{ 
		wTimer = 0.0; 
	} 
	 
	move(FORWARD, speed, 1); 
} 
 
#define GOTO_ERR goto err; 
 
void init(void)  
{ 
	GLfloat fogColor[] = {0.12, 0.27, 0.7, 1.0}; 
	GLfloat lightDiffuse[] = {1.0, 0.75, 0.5, 1.0}; 
	 
	glClearColor(0.12, 0.27, 0.7, 1.0); 
	 
	for(int i=0; i<256; i++)  
	{ 
		sin_t[i] = sin((i/128.0) * PI); 
		cos_t[i] = cos((i/128.0) * PI); 
	} 
	 
	initTerrain(); 
	 
	xpos = (118) * COMP; 
	ypos = 10.0; 
	zpos = (125) * COMP; 
	 
	lookx = (120.0) * COMP; 
	looky = (0.0) * COMP; 
	lookz = (120.0) * COMP; 
	 
	speed = 0; 
	 
	update_world(); 
	 
	glFogi(GL_FOG_MODE, GL_LINEAR); 
	glFogfv(GL_FOG_COLOR, fogColor); 
	glFogf(GL_FOG_DENSITY, 1); 
	glFogf(GL_FOG_START, (M_SIZE/2)*0.1*COMP); 
	glFogf(GL_FOG_END, (M_SIZE/2)*0.5*COMP); 
	 
	glGenTextures(100, texName); 
	 
	srand(1111111); 
 
	randomTerrain(); 
	 
	srand((unsigned)time(NULL)); 
 
	detail_texture = load_bitmap("DETAIL.BMP"); 
 
	glBindTexture(GL_TEXTURE_2D, texName[20]); 
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB5, detail_texture->w, detail_texture->h, 0, GL_RGB, GL_UNSIGNED_BYTE, detail_texture->data); 
	 
	glLightfv(GL_LIGHT0, GL_DIFFUSE, lightDiffuse); 
	glLightfv(GL_LIGHT0, GL_AMBIENT, lightDiffuse); 
	glEnable(GL_NORMALIZE); 
	glEnable(GL_LIGHT0); 
	 
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 
	 
	glShadeModel(GL_SMOOTH); 
	glDisable(GL_ALPHA_TEST); 
	glDisable(GL_BLEND); 
	glDisable(GL_CULL_FACE); 
	glEnable(GL_DEPTH_TEST); 
	 
	glFrontFace(GL_CCW); 
	glCullFace(GL_BACK); 
	glEnable(GL_CULL_FACE); 
	 
	glEnable(GL_TEXTURE_2D); 
	 
	glEnable(GL_DITHER); 
 
	triangle = triangle1; 
 
	move(ROTATE, 2.6, 0); 
	move(LOOKUP, -0.2, 0); 
	 
	c1 = (unsigned)time(NULL); 
	c2 = 0; 
	fps = 0; 
} 
 
__inline void setColor(int x, int z) { 
	glColor3ub(colour_map[IX(x, z)].r, colour_map[IX(x, z)].g, colour_map[IX(x, z)].b); 
} 
 
__inline void setVertex(int x, int z) { 
	glVertex3f((x << SHIFT), y[IX(x, z)] * 8, (z << SHIFT)); 
} 
 
__inline void setVertex0(int x, int z) { 
	glVertex3f((x << SHIFT), (sin(x+timer)+sin(z+timer))*16, (z << SHIFT)); 
} 
 
__inline void setVertex1(int x, int y, int z) { 
	glVertex3f((x << SHIFT), y * 8, (z << SHIFT)); 
} 
 
void triangle1(int x1, int z1, int x2, int z2, int x3, int z3) { 
	glBegin(GL_TRIANGLES); 
	glTexCoord2f(x1/(texScale), z1/(texScale)); 
	setColor(x1, z1); 
	setVertex(x1, z1); 
	 
	glTexCoord2f(x2/(texScale), z2/(texScale)); 
	setColor(x2, z2); 
	setVertex(x2, z2); 
	 
	glTexCoord2f(x3/(texScale), z3/(texScale)); 
	setColor(x3, z3); 
	setVertex(x3, z3); 
	glEnd(); 
} 
 
void triangle2(int x1, int z1, int x2, int z2, int x3, int z3) { 
	glBegin(GL_LINE_LOOP); 
	setVertex(x1, z1); 
	setVertex(x2, z2); 
	setVertex(x3, z3); 
	glEnd(); 
} 
 
void draw_point(int x, int z, int width, int direction) { 
	 
	switch(direction) { 
	case NORTH: 
		triangle(x, z, x + width, z - width, x - width, z - width); 
		return; 
	case SOUTH: 
		triangle(x, z, x - width, z + width, x + width, z + width); 
		return; 
	case EAST: 
		triangle(x, z, x + width, z + width, x + width, z - width); 
		return; 
	case WEST: 
		triangle(x, z, x - width, z - width, x - width, z + width); 
		return;  
	case NORTH_L: 
		triangle(x, z, x, z - width, x - width, z - width); 
		return; 
	case NORTH_R: 
		triangle(x, z, x + width, z - width, x, z - width); 
		return; 
		 
	case SOUTH_L: 
		triangle(x, z, x - width, z + width, x, z + width); 
		return; 
	case SOUTH_R: 
		triangle(x, z, x, z + width, x + width, z + width); 
		return; 
		 
	case EAST_T: 
		triangle(x, z, x + width, z, x + width, z - width); 
		return; 
	case EAST_B: 
		triangle(x, z, x + width, z + width, x + width, z); 
		return; 
		 
	case WEST_T: 
		triangle(x, z, x - width, z - width, x - width, z); 
		return; 
	case WEST_B: 
		triangle(x, z, x - width, z, x - width, z + width); 
		return; 
	default: 
		break; 
	}; 
} 
 
void display(void)  
{ 
	 
	int i; 
	int x, z; 
	int aX, aZ; 
	int r; 
	float v1[3]; 
	float location_f[3]; 
	 
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
	 
	glViewport(0, 0, (GLsizei) winWidth, (GLsizei) winHeight); 
	glMatrixMode(GL_PROJECTION); 
	glLoadIdentity(); 
	 
	gluPerspective(60.0, (GLfloat) winWidth/(GLfloat) winHeight, 1.0, ((M_SIZE + 4) * 2) << SHIFT); 
	 
	// 设置摄像机位置 
	 
	glMatrixMode(GL_MODELVIEW); 
	glLoadIdentity(); 
	gluLookAt (xpos, ypos, zpos, xpos+lookx, ypos+looky, zpos+lookz, 0.0, 1.0, 0.0); 
	 
	reset_quad_tree(); 
	setup_quadtree(128, 128, 128); 
	 
	if(wireframe_mode < 0)  
	{ 
		glEnable(GL_TEXTURE_2D); 
	} 
	else  
	{ 
		glColor3f(0.0, 0.0, 0.0); 
	} 
	 
	draw(128, 128, 128, 0); 
	 
	if((wireframe_mode < 0) && (flying_mode < 0) && (detail_texture_mode > 0))  
	{ 
		 
		glBindTexture(GL_TEXTURE_2D, texName[20]); 
		 
		glColor4f(1.0, 1.0, 1.0, 1.0); 
		 
		glEnable(GL_BLEND); 
		 
		glDisable(GL_DEPTH_TEST); 
		 
		glBegin(GL_QUADS); 
		 
		location_f[0] = xpos / COMP; 
		location_f[2] = zpos / COMP; 
		 
		aX = mapX - mapX%2; 
		aZ = mapZ - mapZ%2; 
		 
		for(x=aX-16; xCreateDevice(GUID_SysKeyboard, &lpdikey, NULL)!=DI_OK) 
		GOTO_ERR; 
	 
	// set cooperation level 
	if (lpdikey->SetCooperativeLevel(hWnd,  
		DISCL_NONEXCLUSIVE | DISCL_BACKGROUND)!=DI_OK) 
		GOTO_ERR; 
	 
	// set data format 
	if (lpdikey->SetDataFormat(&c_dfDIKeyboard)!=DI_OK) 
		GOTO_ERR; 
	 
	// create a mouse device  ////////////////////////////////// 
	if (lpdi->CreateDevice(GUID_SysMouse, &lpdimouse, NULL)!=DI_OK) 
		GOTO_ERR; 
	 
	// set cooperation level 
	if (lpdimouse->SetCooperativeLevel(hWnd,  
		DISCL_NONEXCLUSIVE | DISCL_BACKGROUND)!=DI_OK) 
		GOTO_ERR; 
	 
	// set data format 
	if (lpdimouse->SetDataFormat(&c_dfDIMouse)!=DI_OK) 
		GOTO_ERR; 
	 
	// enable OpenGL for the window 
	EnableOpenGL( hWnd, &hDC, &hRC ); 
	 
	init(); // Load textures, setup OpenGL etc. 
	 
	ShowCursor(FALSE); 
	 
	// acquire the keyboard 
	if (lpdikey->Acquire()!=DI_OK) 
		GOTO_ERR; 
	 
	// acquire the mouse 
	if (lpdimouse->Acquire()!=DI_OK) 
		GOTO_ERR; 
	 
	// program main loop 
	while ( !bQuit ) { 
		 
		// check for messages 
		if ( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) ) { 
			 
			// handle or dispatch messages 
			if ( msg.message == WM_QUIT ) { 
				bQuit = TRUE; 
			} else { 
				TranslateMessage( &msg ); 
				DispatchMessage( &msg ); 
			} 
			 
		} else { 
			 
			// OpenGL animation code goes here	 
			 
			// This following code does some boundary checking. 
			 
			mapX = xpos / COMP; 
			mapZ = zpos / COMP; 
			 
			location[0] = mapX; 
			location[2] = mapZ; 
			 
			// get the keyboard info 
			lpdikey->GetDeviceState(256, keystate); 
			 
			if(keystate[DIK_ESCAPE])  
			{ 
				PostQuitMessage( 0 ); // 退出程序 
			} 
			 
			if(keystate[DIK_W])  
			{ 
				if(flying_mode > 0)  
				{ 
					if(speed < 128)  
					{ 
						speed += 8; 
					} 
				} 
				else  
				{ 
					if(speed < 8)  
					{ 
						speed += 2; 
					} 
				} 
			} 
			else  
			{ 
				if(flying_mode > 0)  
				{ 
					if(speed > 0)  
					{ 
						speed -= 4; 
					} 
				} 
				else  
				{ 
					if(speed > 0)  
					{ 
						speed -= 1; 
					} 
				} 
			} 
			 
			if(keystate[DIK_S])  
			{ 
				speed = 0; 
			} 
			 
			if(keystate[DIK_1])  
			{ 
				lod_level = 8; 
			} 
			if(keystate[DIK_2])  
			{ 
				lod_level = 16; 
			} 
			if(keystate[DIK_3])  
			{ 
				lod_level = 32; 
			} 
			if(keystate[DIK_4])  
			{ 
				lod_level = 64; 
			} 
			 
			if(keystate[DIK_T]) { 
				detail_texture_mode = -detail_texture_mode; 
				Sleep(100); 
			} 
 
			if(keystate[DIK_F]) { 
				flying_mode = -flying_mode; 
				speed = 0; 
				Sleep(100); 
			} 
			 
			if(keystate[DIK_B]) { 
				for(i=0; i<100; i++) { 
					glBindTexture(GL_TEXTURE_2D, texName[i]); 
					if(bilinear_filtering > 0) { 
						glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 
						glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 
					} 
					else { 
						glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
						glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
					} 
				} 
				 
				bilinear_filtering = -bilinear_filtering; 
				 
				Sleep(100); 
			} 
 
			if(keystate[DIK_M]) { 
				if(wireframe_mode > 0) { 
					triangle = triangle1; 
				} 
				else { 
					triangle = triangle2; 
				} 
				 
				wireframe_mode = -wireframe_mode; 
				 
				Sleep(100); 
			} 
			 
			if(keystate[DIK_SPACE])  
			{ 
				randomTerrain(); 
			} 
			 
			// 获得鼠标信息 
			lpdimouse->GetDeviceState(sizeof(DIMOUSESTATE), (LPVOID)&mouse_state); 
			 
			move(ROTATE, (GLfloat)((-mouse_state.lX)/100.0), 0); 
			move(LOOKUP, (GLfloat)((mouse_state.lY)/100.0), 0); 
			 
			update_world(); // 更新地形数据 
			 
			display(); // 绘制地形 
			 
			SwapBuffers( hDC );  
		}		 
	} 
	 
	ShowCursor(TRUE); 
	 
	lpdimouse->Unacquire(); 
	lpdimouse->Release(); 
	 
	lpdikey->Unacquire(); 
	lpdikey->Release(); 
	 
	lpdi->Release(); 
	 
	goto end; 
	 
err: 
	MessageBox(main_window_handle, "Unable to initialise Direct Input\n NOTE: DirectX is unavailable on NT.", "Error", MB_OK | MB_ICONERROR); 
	 
end: 
	 
	// shutdown OpenGL 
	DisableOpenGL( hWnd, hDC, hRC ); 
	 
	// destroy the window explicitly 
	DestroyWindow( hWnd ); 
	 
	return msg.wParam;	 
} 
 
// Window Procedure 
 
LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam ) { 
 
	switch ( message ) { 
		 
	case WM_CREATE: 
		return 0; 
		 
	case WM_CLOSE: 
		PostQuitMessage( 0 ); 
		return 0; 
		 
	case WM_DESTROY: 
		return 0; 
		 
	default: 
		return DefWindowProc( hWnd, message, wParam, lParam );	 
	} 
} 
 
// Enable OpenGL 
 
VOID EnableOpenGL( HWND hWnd, HDC * hDC, HGLRC * hRC ) 
{ 
	PIXELFORMATDESCRIPTOR pfd; 
	int iFormat; 
	 
	// get the device context (DC) 
	*hDC = GetDC( hWnd ); 
	 
	// set the pixel format for the DC 
	ZeroMemory( &pfd, sizeof( pfd ) ); 
	pfd.nSize = sizeof( pfd ); 
	pfd.nVersion = 1; 
	pfd.dwFlags = PFD_DRAW_TO_WINDOW |  
		PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; 
	pfd.iPixelType = PFD_TYPE_RGBA; 
	pfd.cColorBits = 32; 
	pfd.cDepthBits = 16; 
	pfd.iLayerType = PFD_MAIN_PLANE; 
	iFormat = ChoosePixelFormat( *hDC, &pfd ); 
	SetPixelFormat( *hDC, iFormat, &pfd ); 
	 
	// create and enable the render context (RC) 
	*hRC = wglCreateContext( *hDC ); 
	wglMakeCurrent( *hDC, *hRC ); 
} 
 
// Disable OpenGL 
 
VOID DisableOpenGL( HWND hWnd, HDC hDC, HGLRC hRC ) 
{ 
	wglMakeCurrent( NULL, NULL ); 
	wglDeleteContext( hRC ); 
	ReleaseDC( hWnd, hDC ); 
}