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);
}