www.pudn.com > MYLOD.rar > MYLODVIEW.CPP


// MyLODView.cpp : implementation of the CMyLODView class 
// 
 
#include "stdafx.h" 
#include "MyLOD.h" 
 
#include "MyLODDoc.h" 
#include "MyLODView.h" 
#include  
 
#ifdef _DEBUG 
#define new DEBUG_NEW 
#undef THIS_FILE 
static char THIS_FILE[] = __FILE__; 
#endif 
 
CLandTex lt; 
int quadtree[QUAD_MAP * QUAD_MAP]; 
int location[3]; 
int lod_level=8; 
int *y; // 保存地形的高程数组 
COLOUR *colour_map; // 保存地形的颜色数值 
 
///////////////////////////////////////////////////////////////////////////// 
// CMyLODView 
 
IMPLEMENT_DYNCREATE(CMyLODView, CView) 
 
BEGIN_MESSAGE_MAP(CMyLODView, CView) 
	//{{AFX_MSG_MAP(CMyLODView) 
	ON_WM_CREATE() 
	ON_WM_DESTROY() 
	ON_WM_SIZE() 
	ON_WM_TIMER() 
	ON_WM_KEYDOWN() 
	//}}AFX_MSG_MAP 
	// Standard printing commands 
	ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint) 
	ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint) 
	ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview) 
END_MESSAGE_MAP() 
 
///////////////////////////////////////////////////////////////////////////// 
// CMyLODView construction/destruction 
 
CMyLODView::CMyLODView() 
{ 
	// TODO: add construction code here 
	bilinear_filtering = 1; 
	wireframe_mode = -1; 
	flying_mode = 1; 
	detail_texture_mode = -1; 
	mapX = 128, mapZ = 128;  
	speed = 0.0; // 移动速度初始化 
	timer = 0.0, wTimer = 0.0; 
} 
 
CMyLODView::~CMyLODView() 
{ 
} 
 
BOOL CMyLODView::PreCreateWindow(CREATESTRUCT& cs) 
{ 
	// TODO: Modify the Window class or styles here by modifying 
	//  the CREATESTRUCT cs 
//////////////////////////////////////////////////////////////// 
//设置窗口类型 
	cs.style |=WS_CLIPCHILDREN | WS_CLIPSIBLINGS; 
//////////////////////////////////////////////////////////////// 
	return CView::PreCreateWindow(cs); 
} 
 
///////////////////////////////////////////////////////////////////////////// 
// CMyLODView drawing 
 
void CMyLODView::OnDraw(CDC* pDC) 
{ 
	CMyLODDoc* pDoc = GetDocument(); 
	ASSERT_VALID(pDoc); 
	// TODO: add draw code for native data here 
////////////////////////////////////////////////////////////////// 
	RenderScene();	//渲染场景 
////////////////////////////////////////////////////////////////// 
 
} 
 
///////////////////////////////////////////////////////////////////////////// 
// CMyLODView printing 
 
BOOL CMyLODView::OnPreparePrinting(CPrintInfo* pInfo) 
{ 
	// default preparation 
	return DoPreparePrinting(pInfo); 
} 
 
void CMyLODView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) 
{ 
	// TODO: add extra initialization before printing 
} 
 
void CMyLODView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) 
{ 
	// TODO: add cleanup after printing 
} 
 
///////////////////////////////////////////////////////////////////////////// 
// CMyLODView diagnostics 
 
#ifdef _DEBUG 
void CMyLODView::AssertValid() const 
{ 
	CView::AssertValid(); 
} 
 
void CMyLODView::Dump(CDumpContext& dc) const 
{ 
	CView::Dump(dc); 
} 
 
CMyLODDoc* CMyLODView::GetDocument() // non-debug version is inline 
{ 
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CMyLODDoc))); 
	return (CMyLODDoc*)m_pDocument; 
} 
#endif //_DEBUG 
 
///////////////////////////////////////////////////////////////////////////// 
// CMyLODView message handlers 
 
int CMyLODView::OnCreate(LPCREATESTRUCT lpCreateStruct)  
{ 
	if (CView::OnCreate(lpCreateStruct) == -1) 
		return -1; 
	 
	// TODO: Add your specialized creation code here 
////////////////////////////////////////////////////////////////// 
//初始化OpenGL和设置定时器 
	m_pDC = new CClientDC(this); 
	SetTimer(1, 20, NULL); 
	InitializeOpenGL(m_pDC); 
////////////////////////////////////////////////////////////////// 
	Init();	 
	return 0; 
} 
 
void CMyLODView::OnDestroy()  
{ 
	CView::OnDestroy(); 
	 
	// TODO: Add your message handler code here 
///////////////////////////////////////////////////////////////// 
//删除调色板和渲染上下文、定时器 
	::wglMakeCurrent(0,0); 
	::wglDeleteContext( m_hRC); 
	if (m_hPalette) 
	    DeleteObject(m_hPalette); 
	if ( m_pDC ) 
	{ 
		delete m_pDC; 
	} 
	KillTimer(1);		 
///////////////////////////////////////////////////////////////// 
	delete[] y; 
	delete[] colour_map; 
	m_Bmpload.destroy_bmp(detail_texture); 
} 
 
void CMyLODView::OnSize(UINT nType, int cx, int cy)  
{ 
	CView::OnSize(nType, cx, cy); 
	 
	// TODO: Add your message handler code here 
///////////////////////////////////////////////////////////////// 
//添加窗口缩放时的图形变换函数 
	glViewport(0,0,cx,cy); 
///////////////////////////////////////////////////////////////// 
	winWidth=cx; 
	winHeight=cy; 
	 
} 
 
void CMyLODView::OnTimer(UINT nIDEvent)  
{ 
	// TODO: Add your message handler code here and/or call default 
///////////////////////////////////////////////////////////////// 
//添加定时器响应函数和场景更新函数 
	Invalidate(FALSE);	 
///////////////////////////////////////////////////////////////// 
	update_world(); 	 
	CView::OnTimer(nIDEvent); 
} 
 
///////////////////////////////////////////////////////////////////// 
//	                  设置逻辑调色板 
////////////////////////////////////////////////////////////////////// 
void CMyLODView::SetLogicalPalette(void) 
{ 
    struct 
    { 
        WORD Version; 
        WORD NumberOfEntries; 
        PALETTEENTRY aEntries[256]; 
    } logicalPalette = { 0x300, 256 }; 
 
	BYTE reds[] = {0, 36, 72, 109, 145, 182, 218, 255}; 
	BYTE greens[] = {0, 36, 72, 109, 145, 182, 218, 255}; 
	BYTE blues[] = {0, 85, 170, 255}; 
 
    for (int colorNum=0; colorNum<256; ++colorNum) 
    { 
        logicalPalette.aEntries[colorNum].peRed = 
            reds[colorNum & 0x07]; 
        logicalPalette.aEntries[colorNum].peGreen = 
            greens[(colorNum >> 0x03) & 0x07]; 
        logicalPalette.aEntries[colorNum].peBlue = 
            blues[(colorNum >> 0x06) & 0x03]; 
        logicalPalette.aEntries[colorNum].peFlags = 0; 
    } 
 
    m_hPalette = CreatePalette ((LOGPALETTE*)&logicalPalette); 
} 
 
 
////////////////////////////////////////////////////////// 
//						初始化openGL场景 
////////////////////////////////////////////////////////// 
BOOL CMyLODView::InitializeOpenGL(CDC* pDC) 
{ 
	m_pDC = pDC; 
	SetupPixelFormat(); 
	//生成绘制描述表 
	m_hRC = ::wglCreateContext(m_pDC->GetSafeHdc()); 
	//置当前绘制描述表 
	::wglMakeCurrent(m_pDC->GetSafeHdc(), m_hRC); 
 
	return TRUE; 
} 
 
////////////////////////////////////////////////////////// 
//						设置像素格式 
////////////////////////////////////////////////////////// 
BOOL CMyLODView::SetupPixelFormat() 
{ 
	PIXELFORMATDESCRIPTOR pfd = {  
	    sizeof(PIXELFORMATDESCRIPTOR),    // pfd结构的大小  
	    1,                                // 版本号  
	    PFD_DRAW_TO_WINDOW |              // 支持在窗口中绘图  
	    PFD_SUPPORT_OPENGL |              // 支持 OpenGL  
	    PFD_DOUBLEBUFFER,                 // 双缓存模式  
	    PFD_TYPE_RGBA,                    // RGBA 颜色模式  
	    24,                               // 24 位颜色深度  
	    0, 0, 0, 0, 0, 0,                 // 忽略颜色位  
	    0,                                // 没有非透明度缓存  
	    0,                                // 忽略移位位  
	    0,                                // 无累加缓存  
	    0, 0, 0, 0,                       // 忽略累加位  
	    32,                               // 32 位深度缓存      
	    0,                                // 无模板缓存  
	    0,                                // 无辅助缓存  
	    PFD_MAIN_PLANE,                   // 主层  
	    0,                                // 保留  
	    0, 0, 0                           // 忽略层,可见性和损毁掩模  
	}; 	 
	int pixelformat; 
	pixelformat = ::ChoosePixelFormat(m_pDC->GetSafeHdc(), &pfd);//选择像素格式 
	::SetPixelFormat(m_pDC->GetSafeHdc(), pixelformat, &pfd);	//设置像素格式 
	if(pfd.dwFlags & PFD_NEED_PALETTE) 
		SetLogicalPalette();	//设置逻辑调色板 
	return TRUE; 
} 
 
 
 
////////////////////////////////////////////////////////// 
//						场景绘制与渲染 
////////////////////////////////////////////////////////// 
BOOL CMyLODView::RenderScene()  
{ 
	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); 
	 
	m_Lod.reset_quad_tree(); 
	m_Lod.setup_quadtree(128, 128, 128); 
	 
	if(wireframe_mode < 0) { 
		glEnable(GL_TEXTURE_2D); 
	} 
	else { 
		glColor3f(0.0, 0.0, 0.0); 
	} 
	 
	m_Lod.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; xGetSafeHdc());		//交互缓冲区 
	return TRUE; 
} 
 
void CMyLODView::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 = m_Bmpload.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); 
 
	m_Lod.m_bFlag=true; 
 
	move(ROTATE, 2.6, 0); 
	move(LOOKUP, -0.2, 0); 
	 
 
} 
 
void CMyLODView::initTerrain(void)  
{ 
	y = new int[M_SIZE*M_SIZE]; 
	if(!y)  
	{ 
		MessageBox("Unable to allocate memory for height map.","Error",MB_OK); 
	} 
	else  
	{ 
		MessageBox("Succesfully allocated memory for height map.","OK",MB_OK); 
	} 
	colour_map = new COLOUR[M_SIZE*M_SIZE]; 
	if(!colour_map)  
	{ 
		MessageBox("Unable to allocate memory for shadow map.","Error",MB_OK); 
	} 
	else  
	{ 
		MessageBox("Succesfully allocated memory for shadow map.","OK",MB_OK); 
	} 
} 
 
 
void CMyLODView::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); 
} 
 
void CMyLODView::move(int type, GLfloat amount, int update) 
{ 
	GLfloat lightPosition[] = {-1.0, 0.0, 0.2, 0.0}; 
	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); 
		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 CMyLODView::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); 
	 
} 
 
 
void CMyLODView::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); 
} 
 
void CMyLODView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)  
{ 
	// TODO: Add your message handler code here and/or call default 
			if(nChar==0x57) //VK_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(nChar==0x53) //VK_S 
			{ 
				speed = 0; 
			} 
			 
			if(nChar==0x31) //VK_1 
			{ 
				lod_level = 8; 
			} 
			if(nChar==0x32) //VK_2 
			{ 
				lod_level = 16; 
			} 
			if(nChar==0x33) //VK_3 
			{ 
				lod_level = 32; 
			} 
			if(nChar==0x34) //VK_4 
			{ 
				lod_level = 64; 
			} 
			 
			if(nChar==0x54) //VK_T 
			{ 
				detail_texture_mode = -detail_texture_mode; 
				Sleep(100); 
			} 
 
			if(nChar==0x46) //VK_F 
			{ 
				flying_mode = -flying_mode;  //视点运动模式开关 
				speed = 0; 
				Sleep(100); 
			} 
			 
			if(nChar==0x42) //VK_B 
			{ 
				for(int 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(nChar==0x4D) //VK_M 
			{ 
				if(wireframe_mode > 0)  
				{ 
					m_Lod.m_bFlag = true;  //线框模式 
				} 
				else  
				{ 
					m_Lod.m_bFlag = false;   //纹理模式 
				} 
				 
				wireframe_mode = -wireframe_mode; 
				 
				Sleep(100); 
			} 
			 
			if(nChar==VK_SPACE)  
			{ 
				randomTerrain();  // 生成随机地形 
			} 
 
	CView::OnKeyDown(nChar, nRepCnt, nFlags); 
}