www.pudn.com > OpenGL32.rar > OpenGL1View.cpp


// OpenGL1View.cpp : implementation of the COpenGL1View class 
// 
 
#include "stdafx.h" 
#include "OpenGL1.h" 
 
#include "OpenGL1Doc.h" 
#include "OpenGL1View.h" 
#include "math.h" 
#ifdef _DEBUG 
#define new DEBUG_NEW 
#undef THIS_FILE 
static char THIS_FILE[] = __FILE__; 
#endif 
 
///////////////////////////////////////////////////////////////////////////// 
// COpenGL1View 
 
IMPLEMENT_DYNCREATE(COpenGL1View, CView) 
 
BEGIN_MESSAGE_MAP(COpenGL1View, CView) 
	//{{AFX_MSG_MAP(COpenGL1View) 
	ON_WM_CREATE() 
	ON_WM_DESTROY() 
	ON_WM_SIZE() 
	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() 
 
///////////////////////////////////////////////////////////////////////////// 
// COpenGL1View construction/destruction 
 
COpenGL1View::COpenGL1View() 
{ 
	angleX=0; 
	angleY=0; 
	m_pDC = NULL; 
	g_eye[0]= MAP;// 
	g_eye[2]=-MAP;// 
	g_Angle=0;// 
	g_elev=-0;// 
} 
 
COpenGL1View::~COpenGL1View() 
{ 
} 
 
BOOL COpenGL1View::PreCreateWindow(CREATESTRUCT& cs) 
{ 
	// TODO: Modify the Window class or styles here by modifying 
	//  the CREATESTRUCT cs 
	//设定opengl风格 
	cs.style |= WS_CLIPCHILDREN|WS_CLIPSIBLINGS; 
	return CView::PreCreateWindow(cs); 
} 
 
///////////////////////////////////////////////////////////////////////////// 
// COpenGL1View drawing 
 
void COpenGL1View::OnDraw(CDC* pDC) 
{ 
	COpenGL1Doc* pDoc = GetDocument(); 
	ASSERT_VALID(pDoc); 
	DrawScene(); 
} 
 
///////////////////////////////////////////////////////////////////////////// 
// COpenGL1View printing 
 
BOOL COpenGL1View::OnPreparePrinting(CPrintInfo* pInfo) 
{ 
	// default preparation 
	return DoPreparePrinting(pInfo); 
} 
 
void COpenGL1View::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) 
{ 
	// TODO: add extra initialization before printing 
} 
 
void COpenGL1View::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) 
{ 
	// TODO: add cleanup after printing 
} 
 
///////////////////////////////////////////////////////////////////////////// 
// COpenGL1View diagnostics 
 
#ifdef _DEBUG 
void COpenGL1View::AssertValid() const 
{ 
	CView::AssertValid(); 
} 
 
void COpenGL1View::Dump(CDumpContext& dc) const 
{ 
	CView::Dump(dc); 
} 
 
COpenGL1Doc* COpenGL1View::GetDocument() // non-debug version is inline 
{ 
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(COpenGL1Doc))); 
	return (COpenGL1Doc*)m_pDocument; 
} 
#endif //_DEBUG 
 
///////////////////////////////////////////////////////////////////////////// 
// COpenGL1View message handlers 
 
int COpenGL1View::OnCreate(LPCREATESTRUCT lpCreateStruct)  
{ 
	if (CView::OnCreate(lpCreateStruct) == -1) 
		return -1; 
	Init(); 
 
	return 0; 
} 
 
void COpenGL1View::Init() 
{ 
	PIXELFORMATDESCRIPTOR pfd; 
	m_pDC = new CClientDC(this); 
	ASSERT(m_pDC !=NULL); 
 
	///必须,设置像素 
	if(!bSetupPixelFormat()) 
		return ; 
	int n; 
	HGLRC m_hrc; 
	//------------测试像素格式 
	n = ::GetPixelFormat(m_pDC->GetSafeHdc()); 
	::DescribePixelFormat(m_pDC->GetSafeHdc(),n,sizeof(pfd),&pfd); 
	------------// 
	//创建着色描述表 
	m_hrc = wglCreateContext(m_pDC->GetSafeHdc()); 
	//设置为当前着色描述表 
	wglMakeCurrent(m_pDC->GetSafeHdc(), m_hrc); 
	//获取客户区域大小 
	GetClientRect(&m_OldRect); 
	for(int i = 0;i< 6;i++) 
	{ 
		LoadT8 ( filename[i],texture[i] ); 
	} 
	LoadT16("CACTUS0.BMP",g_cactus[0]);   
	LoadT16("CACTUS1.BMP",g_cactus[1]);   
	LoadT16("CACTUS2.BMP",g_cactus[2]);     
	LoadT16("CACTUS3.BMP",g_cactus[3]);   
	InitTerrain(-3); 
} 
 
BOOL COpenGL1View::bSetupPixelFormat() 
{ 
	//设置像素结构体 
	static PIXELFORMATDESCRIPTOR pfd = 
	{ 
		//大小 
		sizeof(PIXELFORMATDESCRIPTOR), 
		//版本 
		1, 
		//输出模式 
		PFD_DRAW_TO_WINDOW| 
		PFD_SUPPORT_OPENGL| 
		PFD_DOUBLEBUFFER, 
		//像素模式 
		PFD_TYPE_RGBA, 
		//颜色深度 
		24, 
		0,0,0,0,0,0, 
		0, 
		0, 
		0, 
		0,0,0,0, 
		32, 
		0, 
		0, 
		PFD_MAIN_PLANE, 
		0, 
		0,0,0 
	}; 
	 int iPixelFormat = 0; 
	 //选择一个符合的像素格式 
	 if(!(iPixelFormat = ChoosePixelFormat(m_pDC->GetSafeHdc(),&pfd))) 
	 { 
		AfxMessageBox("选择像素失败"); 
		return FALSE; 
	 } 
	 //设置像素模式 
	 if(!(SetPixelFormat(m_pDC->GetSafeHdc(),iPixelFormat,&pfd))) 
	 { 
		AfxMessageBox("设置像素失败"); 
		return FALSE; 
	 } 
	return TRUE; 
} 
 
void COpenGL1View::OnDestroy()  
{ 
	CView::OnDestroy(); 
	HGLRC m_hrc; 
	//获取当前的着色描述表 
	m_hrc = wglGetCurrentContext(); 
	if(m_hrc) 
		//删除着色描述表必须 
		wglDeleteContext(m_hrc); 
	wglMakeCurrent(NULL,NULL); 
	if(m_pDC) 
		delete m_pDC; 
} 
 
void COpenGL1View::OnSize(UINT nType, int cx, int cy)  
{ 
	CView::OnSize(nType, cx, cy); 
	m_OldRect.right = cx; 
	m_OldRect.bottom = cy; 
	glViewport(0,0,cx,cy);		 
	glMatrixMode(GL_PROJECTION);		 
	glLoadIdentity();					 
	gluPerspective						 
	( 54.0f,						 
	  (GLfloat)cx/(GLfloat)cy, 
	  0.1f,							 
	  3000.0f						 
	); 
glMatrixMode(GL_MODELVIEW);	 
glLoadIdentity();				 
	 
} 
float  gao=1.8f; 
void COpenGL1View::DrawScene() 
{ 
	//设置背景颜色 
	glClearColor(0.0f, 0.0f, 0.1f, 0.3f); 
	//清楚颜色缓存和深度缓存 
	glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); 
	//向量单位化 
	glLoadIdentity(); 
	///////////////////////////////////////////////// 
   rad_xz = float (3.13149* g_Angle/180.0f); 
   if(g_eye[0]<  MAP_SCALE)			g_eye[0]=  MAP_SCALE; 
   if(g_eye[0]> (MAP_W-2)*MAP_SCALE)	g_eye[0]= (MAP_W-2)*MAP_SCALE; 
   if(g_eye[2]<-(MAP_W-2)*MAP_SCALE)	g_eye[2]=-(MAP_W-2)*MAP_SCALE; 
   if(g_eye[2]> -MAP_SCALE)			g_eye[2]= -MAP_SCALE; 
   g_eye[1] =0; 
 
   g_look[0] = (float)(g_eye[0] +100*cos(rad_xz)); 
   g_look[2] = (float)(g_eye[2] +100*sin(rad_xz)); 
   g_look[1] = g_eye[1] +g_elev;	 
 
   gluLookAt(g_eye[0],g_eye[1],g_eye[2],	 
			g_look[0],g_look[1],g_look[2], 
			0.0,1.0,0.0	 
		   ); 
	    
  //////////////////////////////////////////// 
	glEnable(GL_TEXTURE_2D); 
	//设置绘制颜色 
	//选择纹理(每一个三角形都可以有不同的纹理) 
	glPushMatrix(); 
	//绘制一条线 
	texture0(texture[0]); 
	glBegin ( GL_QUADS  );//开始绘制 
		glNormal3f( 0.0f, 0.0f, 1.0f); 
		glTexCoord2f(0.0f, 1.0f);glVertex3f(-768.0f,704.0f,-1536.0f); 
		glTexCoord2f(1.0f, 1.0f);glVertex3f(1536.0f,704.0f,-1536.0f); 
		glTexCoord2f(1.0f, 0.0f);glVertex3f(1536.0f,-448.0f,-1536.0f); 
		glTexCoord2f(0.0f, 0.0f);glVertex3f(-768.0f,-448.0f,-1536.0f); 
	glEnd();//结束绘制 
	 
	texture0( texture[3]); 
	glBegin ( GL_QUADS  );//开始绘制 
		glNormal3f( 0.0f, 0.0f, 1.0f); 
		glTexCoord2f(1.0f,1.0f);glVertex3f(-768.0f,704.0f,-1536.0f); 
		glTexCoord2f(0.0f, 1.0f);glVertex3f(-768.0f,704.0f,768.0f); 
		glTexCoord2f(0.0f, 0.0f);glVertex3f(-768.0f,-448.0f,768.0f); 
		glTexCoord2f(1.0f, 0.0f);glVertex3f(-768.0f,-448.0f,-1536.0f); 
	glEnd();//结束绘制 
 
	texture0( texture[2]); 
	glBegin ( GL_QUADS  );//开始绘制 
		glNormal3f( 0.0f, 0.0f, 1.0f); 
		glTexCoord2f(1.0f,1.0f);glVertex3f(-768.0f,704.0f,768.0f); 
		glTexCoord2f(0.0f, 1.0f);glVertex3f(1536.0f,704.0f,768.0f); 
		glTexCoord2f(0.0f, 0.0f);glVertex3f(1536.0f,-448.0f,768.0f); 
		glTexCoord2f(1.0f, 0.0f);glVertex3f(-768.0f,-448.0f,768.0f); 
	glEnd();//结束绘制 
 
	texture0( texture[1]); 
	glBegin ( GL_QUADS  );//开始绘制 
		glNormal3f( 0.0f, 0.0f, 1.0f); 
		glTexCoord2f(0.0f, 1.0f);glVertex3f(1536.0f,704.0f,-1536.0f); 
		glTexCoord2f(1.0f, 1.0f);glVertex3f(1536.0f,704.0f,768.0f); 
		glTexCoord2f(1.0f, 0.0f);glVertex3f(1536.0f,-448.0f,768.0f); 
		glTexCoord2f(0.0f, 0.0f);glVertex3f(1536.0f,-448.0f,-1536.0f); 
	glEnd();//结束绘制 
	 
 
	texture0( texture[4]); 
	glBegin ( GL_QUADS  );//开始绘制 
		glNormal3f( 0.0f, 0.0f, 1.0f); 
		glTexCoord2f(0.0f, 1.0f);glVertex3f(-768.0f,704.0f,768.0f); 
		glTexCoord2f(1.0f, 1.0f);glVertex3f(1536.0f,704.0f,768.0f); 
		glTexCoord2f(1.0f, 0.0f);glVertex3f(1536.0f,704.0f,-1536.0f); 
		glTexCoord2f(0.0f, 0.0f);glVertex3f(-768.0f,704.0f,-1536.0f); 
	glEnd();//结束绘制 
	 
/*	texture0( texture[5]); 
	glBegin ( GL_QUADS  );//开始绘制 
		glTexCoord2f(1.0f, 0.0f);glVertex3f(-768.0f,-448.0f,768.5f); 
		glTexCoord2f(1.0f, 1.0f);glVertex3f(1536.0f,-448.0f,768.5f); 
		glTexCoord2f(0.0f, 0.0f);glVertex3f(1536.0f,-448.0f,-1536.5f); 
		glTexCoord2f(0.0f, 0.0f);glVertex3f(-768.0f,-448.0f,-1536.5f); 
	glEnd();//结束绘制 
	*/ 
	glBindTexture(GL_TEXTURE_2D, texture[5]); 
    glTexEnvf    (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); 
    for (int z = 0; z < MAP_W-1; z++) 
		glDrawElements(GL_TRIANGLE_STRIP,MAP_W*2,GL_UNSIGNED_INT,&g_index[z*MAP_W*2]); 
	glPopMatrix(); 
	srand(100); 
	for(int i=0;i<300;i++)			 
	{float x= RAND_COORD((MAP_W-1)*MAP_SCALE); 
	 float z= RAND_COORD((MAP_W-1)*MAP_SCALE); 
	 float size=4.0f+rand()%4;			 
	 float h=-size/10;				 
	 int   cactus=rand()%4;		 
	 ShowTree(x,z,size,h,cactus); 
	} 
	glFinish();//必须有,没有则不会显示 
	::SwapBuffers(m_pDC->GetSafeHdc());		//交互缓冲区 
} 
 
void COpenGL1View::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)  
{ 
	float speed=8.5f;					 
    float x=g_eye[0],y=g_eye[2],z=g_eye[2]; 
	switch(nChar) 
	{ 
		case VK_UP: 
			/*angleY+=10; 
			if(angleY>360) 
				angleY = 0; 
				*/ 
			{ 
				rad_xz = float (3.13149* g_Angle/180.0f);	 
				g_eye[2]+=(float)sin(rad_xz)*speed;	 
				g_eye[0]+=(float)cos(rad_xz)*speed;	 
				InvalidateRect(NULL,FALSE); 
			} 
		break; 
		case VK_DOWN: 
			{ 
			rad_xz = float (3.13149* g_Angle/180.0f);	 
			g_eye[2]-=(float)sin(rad_xz)*speed;	 
			g_eye[0]-=(float)cos(rad_xz)*speed; 
			InvalidateRect(NULL,FALSE); 
			} 
		break; 
		case VK_RIGHT: 
			{ 
			   g_Angle+=speed*2; 
			   InvalidateRect(NULL,FALSE); 
			} 
		break; 
		case VK_LEFT: 
			{ 
				g_Angle-=speed*2; 
				InvalidateRect(NULL,FALSE); 
			   
			} 
		break; 
		case 33: 
			g_elev +=speed; 
			InvalidateRect(NULL,FALSE); 
		break; 
		case 34: 
			g_elev -=speed; 
			InvalidateRect(NULL,FALSE); 
		break; 
	} 
	CView::OnKeyDown(nChar, nRepCnt, nFlags); 
} 
bool COpenGL1View::LoadT8(char *filename, GLuint &texture) 
{	 
	AUX_RGBImageRec *pImage = NULL; 
	pImage = auxDIBImageLoad(filename);			 
	if(pImage == NULL)	return false; 
	glGenTextures(1, &texture);		 
	glBindTexture    (GL_TEXTURE_2D,texture); 
	gluBuild2DMipmaps(GL_TEXTURE_2D,3,   
					  pImage->sizeX,    
					  pImage->sizeY,   
					  GL_RGB, GL_UNSIGNED_BYTE, 
					  pImage->data     
					 ); 
	free(pImage->data);               
	free(pImage);	 
	return true;                
} 
 
void COpenGL1View::InitTerrain(float h) 
{ 
  int index = 0; 
  int Vertex; 
  for (int z = 0; z < MAP_W; z++) 
   for (int x = 0; x < MAP_W; x++) 
    { Vertex = z * MAP_W + x; 
      g_terrain [Vertex][0] = float(x)*MAP_SCALE; 
	  g_terrain [Vertex][1] = h + FRAND * h;	 
      g_terrain [Vertex][2] = -float(z)*MAP_SCALE; 
      g_texcoord[Vertex][0] = (float) x;		 
     g_texcoord[Vertex][1] = (float) z;		 
     g_index [index++] = Vertex;		 
     g_index [index++] = Vertex+ MAP_W; 
   } 
  //启动 
  glEnableClientState(GL_VERTEX_ARRAY); 
  //确定顶点	 
  glVertexPointer    (3,GL_FLOAT,0,g_terrain);	 
  //启动文理队列 
  glEnableClientState(GL_TEXTURE_COORD_ARRAY); 
  glTexCoordPointer  (2,GL_FLOAT,0,g_texcoord);	 
} 
 
void COpenGL1View::texture0(UINT textur) 
{ 
	glBindTexture  (GL_TEXTURE_2D, textur); 
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); 
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); 
//	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_LINEAR);  
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); 
} 
 
void COpenGL1View::ShowTree(float x, float z, float h, float s, int cactus) 
{ 
	glEnable(GL_BLEND); 
  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 
  glEnable(GL_ALPHA_TEST); 
  glAlphaFunc(GL_GREATER, 0); 
  float mat[16]; 
  glGetFloatv(GL_MODELVIEW_MATRIX, mat); 
  vector3_t X(mat[0], mat[4], mat[8]); 
  vector3_t Z(mat[1], mat[5], mat[9]);  
  glBindTexture(GL_TEXTURE_2D, g_cactus[cactus]); 
  vector3_t pos(x,0.0,-z); 
  pos.y = GetHeight(x, -z) + h + s; 
  glBegin(GL_QUADS); 
	 glTexCoord2f(0.0,0.0);glVertex3fv((pos+(X+Z)*-h).v);//左下点 
	 glTexCoord2f(1.0,0.0);glVertex3fv((pos+(X-Z)* h).v);//右下点 
	 glTexCoord2f(1.0,1.0);glVertex3fv((pos+(X+Z)* h).v);//右上点 
	 glTexCoord2f(0.0,1.0);glVertex3fv((pos+(Z-X)* h).v);//左上点 
  glEnd(); 
  glDisable(GL_ALPHA); 
  glDisable(GL_BLEND); 
} 
 
void COpenGL1View::LoadT16(char *filename, GLuint &texture) 
{ 
	glGenTextures(1, &texture);           
  glBindTexture(GL_TEXTURE_2D, texture);  
  BITMAPINFOHEADER bitHeader;		 
  unsigned char *buffer;             
  buffer=LoadBitmapFileWithAlpha(filename,&bitHeader); 
  gluBuild2DMipmaps	( GL_TEXTURE_2D,     
					  4,                 
					  bitHeader.biWidth, 
					  bitHeader.biHeight, 
					  GL_RGBA,          
					  GL_UNSIGNED_BYTE,   
					  buffer          
					);           
  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_MIN_FILTER,GL_LINEAR);  
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); 
  free(buffer);             
} 
 
float COpenGL1View::GetHeight(float x, float z) 
{ 
	float CameraX = x/MAP_SCALE;       
	float CameraZ =-z/MAP_SCALE;          
	int Col0 = int(CameraX);            
	int Row0 = int(CameraZ);       
	int Col1 = Col0 + 1;                 
	int Row1 = Row0 + 1;            
	if (Col1 > MAP_W)	Col1 = 0;         
	if (Row1 > MAP_W)	Row1 = 0;           
	float h00=g_terrain[Col0 + Row0*MAP_W][1]; 
	float h01=g_terrain[Col1 + Row0*MAP_W][1]; 
	float h11=g_terrain[Col1 + Row1*MAP_W][1]; 
	float h10=g_terrain[Col0 + Row1*MAP_W][1]; 
	float tx =CameraX - int(CameraX);      
	float ty =CameraZ - int(CameraZ);      
	float txty = tx * ty;                
	return h00*(1.0f-ty-tx+txty)  
			+ h01*(tx-txty) 
			+ h11*txty 
			+ h10*(ty-txty);      
}