1、效果图:
2、部分程序。
// TESTView.cpp : implementation of the CTESTView class
//
#include "stdafx.h"
#include "TEST.h"
#include "TESTDoc.h"
#include "TESTView.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/
// CTESTView
IMPLEMENT_DYNCREATE(CTESTView, CView)
BEGIN_MESSAGE_MAP(CTESTView, CView)
//{{AFX_MSG_MAP(CTESTView)
ON_WM_SIZE()
ON_WM_ERASEBKGND()
ON_WM_CREATE()
ON_WM_DESTROY()
ON_COMMAND(ID_TexturewrapGlclamp, OnTexturewrapGlclamp)
ON_WM_KEYDOWN()
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_MOUSEMOVE()
ON_COMMAND(ID_TREE_IN, OnTreeIn)
ON_COMMAND(ID_TREE_OUT, OnTreeOut)
ON_COMMAND(ID_WENLI2, OnWenli2)
ON_COMMAND(ID_WENLI3, OnWenli3)
ON_COMMAND(ID_WENLI4, OnWenli4)
ON_COMMAND(ID_3DS, On3ds)
ON_COMMAND(ID_3DS_OUT, On3dsOut)
ON_WM_TIMER()
//}}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()
/
// CTESTView construction/destruction
CTESTView::CTESTView()
{
// TODO: add construction code here
//控制变量
m_tree=false;
m_show3ds=false;
m_image=2;
speed=3.0f;
//旋转平移
/* m_xPos = 0.0f;
m_yPos = 0.0f;
m_xAngle = 0.0f;
m_yAngle = 0.0f;
m_xRot = 0.0f;
m_yRot = 0.0f;*/
// GetCurrentDirectory(256,appdir);
g_eye[0]= -MAP*2;
g_eye[2]=MAP/2;
g_Angle=0;
g_elev=-0;
gao=1.8f;
//3ds
m_3ds=new CLoad3DS();
// load3dobj("data/3ds/","航天发射台.3DS",0);
load3dobj("data/3ds/","1.3DS",0);
load3dobj("data/3ds/","直升机0.3ds",1);
load3dobj("data/3ds/","飞机1.3ds",2);
load3dobj("data/3ds/","铲车.3ds",3);
}
CTESTView::~CTESTView()
{
for(int i=0;i<16;i++) glDeleteTextures(1, &m_Texture[i]);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
BOOL CTESTView::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs
cs.style |= WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
return CView::PreCreateWindow(cs);
}
/
// CTESTView drawing
void CTESTView::OnDraw(CDC* pDC)
{
CTESTDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
// Clear out the color & depth buffers
::glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glLoadIdentity();
//glTranslatef(0.0f,0.0f,-5.0f);
// glRotatef(-30.0f,1.0f,1.0f,0.0f);
RenderScene();
// Tell OpenGL to flush its pipeline
::glFinish();
// Now Swap the buffers
::SwapBuffers( m_pDC->GetSafeHdc() );
}
void CTESTView::RenderScene ()
{
glEnable(GL_TEXTURE_2D);
/* glLoadIdentity();
glTranslatef(m_xPos, m_yPos, -5.0f);
glRotatef(m_xAngle, 1.0f,0.0f,0.0f);
glRotatef(m_yAngle, 0.0f,1.0f,0.0f);*/
InitTerrain(5);
DisplayScene();
DrawSand();
CreateSkyBox(3,6,3,6);
if (m_tree)
{
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+11;
ShowTree(x,z,size,h,cactus);
}
}
if (m_show3ds)
{
Scene(0,MAP+50,-0.6f,-MAP/2, 0, -180,0.15f);
Scene(1,MAP+60,25.0f,-MAP/2+50, 120, r/10,0.2f);
Scene(2,MAP+60,22.0f,-MAP/2+50, 135,r/10+90,0.5f);
//Scene(3,MAP-200,0.0f,-MAP/2+50, 0,0,0.2f);
}
}
void CTESTView::CreateSkyBox(int a, int wi, int he, int le)
{
float width =MAP*wi;
float height=MAP*he;
float length=MAP*le;
float x = MAP -width /2;
float y = MAP/a-height/2;
float z = -MAP -length/2;
///
texture(m_Texture[2]);
glBegin(GL_QUADS);
glTexCoord2f(1,0); glVertex3f(x+width,y, z);//glTexCoord2f(1,1);
glTexCoord2f(1,1); glVertex3f(x+width,y+height,z);
glTexCoord2f(0,1); glVertex3f(x, y+height,z);
glTexCoord2f(0,0); glVertex3f(x, y, z);
glEnd();
texture(m_Texture[3]);
glBegin(GL_QUADS);
glTexCoord2f(1.0f,0.0f); glVertex3f(x, y, z+length);
glTexCoord2f(1.0f,1.0f); glVertex3f(x, y+height,z+length);
glTexCoord2f(0.0f,1.0f); glVertex3f(x+width,y+height,z+length);
glTexCoord2f(0.0f,0.0f); glVertex3f(x+width,y, z+length);
glEnd();
texture(m_Texture[4]);
glBegin(GL_QUADS);
glTexCoord2f(0.0f,1.0f); glVertex3f(x+width,y+height,z);
glTexCoord2f(0.0f,0.0f); glVertex3f(x+width,y+height,z+length);
glTexCoord2f(1.0f,0.0f); glVertex3f(x, y+height,z+length);
glTexCoord2f(1.0f,1.0f); glVertex3f(x, y+height,z);
glEnd();
texture(m_Texture[5]);
glBegin(GL_QUADS);
glTexCoord2f(1.0f,1.0f); glVertex3f(x, y+height,z);
glTexCoord2f(0.0f,1.0f); glVertex3f(x, y+height,z+length);
glTexCoord2f(0.0f,0.0f); glVertex3f(x, y, z+length);
glTexCoord2f(1.0f,0.0f); glVertex3f(x, y, z);
glEnd();
texture(m_Texture[6]);
glBegin(GL_QUADS);
glTexCoord2f(0.0f,0.0f); glVertex3f(x+width,y, z);
glTexCoord2f(1.0f,0.0f); glVertex3f(x+width,y, z+length);
glTexCoord2f(1.0f,1.0f); glVertex3f(x+width,y+height,z+length);
glTexCoord2f(0.0f,1.0f); glVertex3f(x+width,y+height,z);
glEnd();
}
/
// CTESTView printing
BOOL CTESTView::OnPreparePrinting(CPrintInfo* pInfo)
{
// default preparation
return DoPreparePrinting(pInfo);
}
void CTESTView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: add extra initialization before printing
}
void CTESTView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: add cleanup after printing
}
/
// CTESTView diagnostics
#ifdef _DEBUG
void CTESTView::AssertValid() const
{
CView::AssertValid();
}
void CTESTView::Dump(CDumpContext& dc) const
{
CView::Dump(dc);
}
CTESTDoc* CTESTView::GetDocument() // non-debug version is inline
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CTESTDoc)));
return (CTESTDoc*)m_pDocument;
}
#endif //_DEBUG
/
// CTESTView message handlers
void CTESTView::OnSize(UINT nType, int cx, int cy)
{
CView::OnSize(nType, cx, cy);
// TODO: Add your message handler code here
GLdouble aspect_ratio; // width/height ratio
if ( 0 >= cx || 0 >= cy )
{
return;
}
// select the full client area
::glViewport(0, 0, cx, cy);
// compute the aspect ratio
// this will keep all dimension scales equal
aspect_ratio = (GLdouble)cx/(GLdouble)cy;
// select the projection matrix and clear it
::glMatrixMode(GL_PROJECTION);
// glMatrixMode(GL_PROJECTION);
::glLoadIdentity();
// select the viewing volume
//::gluPerspective(45.0f, aspect_ratio, .01f, 200.0f);
::gluPerspective(45.0f, aspect_ratio, .1f, 3000.0f);
// switch back to the modelview matrix and clear it
::glMatrixMode(GL_MODELVIEW);
::glLoadIdentity();
}
BOOL CTESTView::OnEraseBkgnd(CDC* pDC)
{
// TODO: Add your message handler code here and/or call default
return TRUE;
}
int CTESTView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CView::OnCreate(lpCreateStruct) == -1)
return -1;
// TODO: Add your specialized creation code here
SetTimer(1,1,NULL);//启动定时器1,定时时间是1秒
InitializeOpenGL();
return 0;
}
void CTESTView::OnDestroy()
{
CView::OnDestroy();
// TODO: Add your message handler code here
if(::wglMakeCurrent (0,0) == FALSE)
{
MessageBox("Could not make RC non-current");
}
//Delete the rendering context
if(::wglDeleteContext (m_hRC)==FALSE)
{
MessageBox("Could not delete RC");
}
//Delete the DC
if(m_pDC)
{
delete m_pDC;
}
//Set it to NULL
m_pDC = NULL;
}
BOOL CTESTView::InitializeOpenGL()
{
//Get a DC for the Client Area
m_pDC = new CClientDC(this);
//Failure to Get DC
if(m_pDC == NULL)
{
MessageBox("Error Obtaining DC");
return FALSE;
}
//Failure to set the pixel format
if(!SetupPixelFormat())
{
return FALSE;
}
//Create Rendering Context
m_hRC = ::wglCreateContext (m_pDC->GetSafeHdc ());
//Failure to Create Rendering Context
if(m_hRC == 0)
{
MessageBox("Error Creating RC");
return FALSE;
}
//Make the RC Current
if(::wglMakeCurrent (m_pDC->GetSafeHdc (), m_hRC)==FALSE)
{
MessageBox("Error making RC Current");
return FALSE;
}
//Specify Black as the clear color
::glClearColor(0.0f,0.0f,0.0f,0.0f);
//Specify the back of the buffer as clear depth
::glClearDepth(1.0f);
light0();
LoadGLTextures();
//Enable Depth Testing
::glEnable(GL_DEPTH_TEST);
return TRUE;
}
//Setup Pixel Format
BOOL CTESTView::SetupPixelFormat()
{
static PIXELFORMATDESCRIPTOR pfd =
{
sizeof(PIXELFORMATDESCRIPTOR), // size of this pfd
1, // version number
PFD_DRAW_TO_WINDOW | // support window
PFD_SUPPORT_OPENGL | // support OpenGL
PFD_DOUBLEBUFFER, // double buffered
PFD_TYPE_RGBA, // RGBA type
24, // 24-bit color depth
0, 0, 0, 0, 0, 0, // color bits ignored
0, // no alpha buffer
0, // shift bit ignored
0, // no accumulation buffer
0, 0, 0, 0, // accum bits ignored
16, // 16-bit z-buffer
0, // no stencil buffer
0, // no auxiliary buffer
PFD_MAIN_PLANE, // main layer
0, // reserved
0, 0, 0 // layer masks ignored
};
int m_nPixelFormat = ::ChoosePixelFormat(m_pDC->GetSafeHdc(), &pfd);
if ( m_nPixelFormat == 0 )
{
return FALSE;
}
if ( ::SetPixelFormat(m_pDC->GetSafeHdc(), m_nPixelFormat, &pfd)== FALSE)
{
return FALSE;
}
return TRUE;
}
void CTESTView::LoadGLTextures()
{
glGenTextures(16, m_Texture);
if (m_image==0)
{
g_imageData = LoadBit("images/Terrain0.bmp",&g_bit);//调等高线势图
LoadT8("images/sand0.bmp", m_Texture[0]);
LoadT8("images/0RBack.bmp", m_Texture[2]);
LoadT8("images/0Front.bmp", m_Texture[3]);
LoadT8("images/0Top.bmp", m_Texture[4]);
LoadT8("images/0Left.bmp", m_Texture[5]);
LoadT8("images/0Right.bmp", m_Texture[6]);
}
if (m_image==1)
{
g_imageData = LoadBit("images/Terrain1.bmp",&g_bit);//调等高线势图
LoadT8("images/sand1.bmp", m_Texture[0]);
LoadT8("images/1RBack.bmp", m_Texture[2]);
LoadT8("images/1Front.bmp", m_Texture[3]);
LoadT8("images/1Top.bmp", m_Texture[4]);
LoadT8("images/1Left.bmp", m_Texture[5]);
LoadT8("images/1Right.bmp", m_Texture[6]);
}
if (m_image==2)
{
g_imageData = LoadBit("images/Terrain2.bmp",&g_bit);//调等高线势图
LoadT8("images/sand2.bmp", m_Texture[0]);
LoadT8("images/2RBack.bmp", m_Texture[2]);
LoadT8("images/2Front.bmp", m_Texture[3]);
LoadT8("images/2Top.bmp", m_Texture[4]);
LoadT8("images/2Left.bmp", m_Texture[5]);
LoadT8("images/2Right.bmp", m_Texture[6]);
}
if (m_image==3)
{
g_imageData = LoadBit("images/Terrain3.bmp",&g_bit);//调等高线势图
LoadT8("images/sand3.bmp", m_Texture[0]);
LoadT8("images/3RBack.bmp", m_Texture[2]);
LoadT8("images/3Front.bmp", m_Texture[3]);
LoadT8("images/3Top.bmp", m_Texture[4]);
LoadT8("images/3Left.bmp", m_Texture[5]);
LoadT8("images/3Right.bmp", m_Texture[6]);
}
LoadT16("images/CACTUS0.BMP",m_Texture[11]); //树1帖图
LoadT16("images/CACTUS1.BMP",m_Texture[12]); //树2帖图
LoadT16("images/CACTUS2.BMP",m_Texture[13]); //树3帖图
LoadT16("images/CACTUS3.BMP",m_Texture[14]); //树4帖图
}
void CTESTView::LoadT8(char *filename, GLuint &texture)
{
AUX_RGBImageRec *pImage = NULL;
pImage = auxDIBImageLoad(filename);
if(pImage == NULL)
{
MessageBox("Picture could not be loaded");
exit(1);
}
glGenTextures(1, &texture);
glBindTexture (GL_TEXTURE_2D,texture);
gluBuild2DMipmaps(GL_TEXTURE_2D,4, pImage->sizeX,
pImage->sizeY,GL_RGB, GL_UNSIGNED_BYTE,pImage->data);
free(pImage->data);
free(pImage);
/* AUX_RGBImageRec *pImage = NULL;
pImage = auxDIBImageLoad(filename);
if(pImage == NULL) return false;
glGenTextures(1, &texture);
glBindTexture (GL_TEXTURE_2D,texture);
gluBuild2DMipmaps(GL_TEXTURE_2D,4, pImage->sizeX,
pImage->sizeY,GL_RGB, GL_UNSIGNED_BYTE,pImage->data);
free(pImage->data);
free(pImage);
return true;*/
}
void CTESTView::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);
// */
}
void CTESTView::OnTexturewrapGlclamp()
{
// TODO: Add your command handler code here
m_image=0;
LoadGLTextures();
InvalidateRect(NULL,FALSE);
}
void CTESTView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
// TODO: Add your message handler code here and/or call default
switch (nChar)
{
case VK_UP:
{
g_eye[2]+=(float)sin(rad_xz)*speed;
g_eye[0]+=(float)cos(rad_xz)*speed;
}//key=nChar;//m_yPos = m_yPos - 10.0f;
break;
case VK_DOWN:
{
g_eye[2]-=(float)sin(rad_xz)*speed;
g_eye[0]-=(float)cos(rad_xz)*speed;
}// key=nChar;//m_yPos = m_yPos + 10.0f;
break;
case VK_LEFT: g_Angle-=speed*2;//key=nChar;//m_xPos = m_xPos + 10.0f;
break;
case VK_RIGHT:g_Angle+=speed*2;//key=nChar;// m_xPos = m_xPos - 10.0f;
break;
default: MessageBox("Press the arrow keys only");
break;
}
InvalidateRect(NULL,FALSE);
CView::OnKeyDown(nChar, nRepCnt, nFlags);
}
void CTESTView::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
m_MouseDownPoint=point;
SetCapture();
CView::OnLButtonDown(nFlags, point);
}
void CTESTView::OnLButtonUp(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
m_MouseDownPoint=CPoint(0,0);
ReleaseCapture();
CView::OnLButtonUp(nFlags, point);
}
void CTESTView::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
if (GetCapture()==this)
{
//Increment the object rotation angles
// m_xAngle+=(point.y-m_MouseDownPoint.y)/3.6;
g_elev+=(point.y-m_MouseDownPoint.y);
g_Angle+=(point.x-m_MouseDownPoint.x);
//Redraw the view
InvalidateRect(NULL,FALSE);
//Set the mouse point
m_MouseDownPoint=point;
};
CView::OnMouseMove(nFlags, point);
}
void CTESTView::texture(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_MAG_FILTER, GL_LINEAR);//纹理过滤函数
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
}
void CTESTView::DrawSand()
{
glBindTexture(GL_TEXTURE_2D, m_Texture[0]);//贴图函数
//texture(m_Texture[0]);
glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
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]);//面贴图,GL_TRIANGLE_STRIP决定面的显示方式
}
void CTESTView::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] = (float)(g_imageData[(z*MAP_W+x)*3]/3);//高度Y
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);//载入索引数组
}
unsigned char * CTESTView::LoadBit(char *filename, BITMAPINFOHEADER *bitmap)//调等高线势图
{
FILE *filePtr;
BITMAPFILEHEADER Header;
unsigned char *Image;
unsigned int imageIdx = 0;
unsigned char tempRGB;
filePtr = fopen(filename, "rb");
if (filePtr == NULL) return NULL;
fread(&Header, sizeof(BITMAPFILEHEADER), 1, filePtr);
if (Header.bfType != BITMAP_ID)
{ fclose(filePtr);
return NULL;
}
fread(bitmap, sizeof(BITMAPINFOHEADER), 1, filePtr);
fseek(filePtr, Header.bfOffBits, SEEK_SET);
Image = (unsigned char*)malloc(bitmap->biSizeImage);
if (!Image)
{ free(Image);
fclose(filePtr);
return NULL;
}
fread(Image, 1, bitmap->biSizeImage, filePtr);
if (Image == NULL)
{ fclose(filePtr);
return NULL;
}
for (imageIdx = 0; imageIdx < bitmap->biSizeImage; imageIdx+=3)
{ tempRGB = Image[imageIdx];
Image[imageIdx] = Image[imageIdx + 2];
Image[imageIdx + 2] = tempRGB;
}
fclose(filePtr);
return Image;
}
bool CTESTView::DisplayScene()
{
float x=g_eye[0],y=g_eye[2],z=g_eye[2];
// if (KEY_DOWN(VK_SHIFT)) speed =speed*2;
//if (key==(VK_LEFT)) g_Angle-=speed*2;
// if (key==(VK_RIGHT)) g_Angle+=speed*2;
rad_xz = float (3.13149* g_Angle/180.0f);
// if (key==(33)) g_elev +=speed;//调节俯仰角
// if (key==(34)) g_elev -=speed;//调节俯仰角
if (g_elev<-360) g_elev =-360;
if (g_elev> 360) g_elev = 360;
/* if (key==(VK_UP))
{ g_eye[2]+=(float)sin(rad_xz)*speed;
g_eye[0]+=(float)cos(rad_xz)*speed;
}
if (key==(VK_DOWN))
{ g_eye[2]-=(float)sin(rad_xz)*speed;
g_eye[0]-=(float)cos(rad_xz)*speed;
}*/
//防止漫游出界
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] =GetHeight((float)g_eye[0],(float)g_eye[2])+gao;//获取地形高度,实现随地形漫游
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);//视点、目标点、视点方向
return TRUE;
}
float CTESTView::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);//求块内X偏移位置
float ty =CameraZ - int(CameraZ);//求块内z偏移位置
float txty = tx * ty;//以下为双线性内插
return h00*(1.0f-ty-tx+txty)
+ h01*(tx-txty)
+ h11*txty
+ h10*(ty-txty);
}
void CTESTView::light0()
{
GLfloat light_position[] = {1.0,5.0,1.0,1.0};
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_DEPTH_TEST);
glEnable(GL_COLOR_MATERIAL);
}
void CTESTView::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]);//场景矩阵X方向矢量
vector3_t Z(mat[1], mat[5], mat[9]); //场景矩阵z方向矢量
glBindTexture(GL_TEXTURE_2D, m_Texture[cactus]);//选择树
vector3_t pos(x,0.0,-z);//树的位置 x,z矩阵变换
pos.y = GetHeight(x, -z) + h + s;//树的Y分量
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 CTESTView::OnTreeIn()
{
// TODO: Add your command handler code here
m_tree=true;
InvalidateRect(NULL,FALSE);
}
void CTESTView::OnTreeOut()
{
// TODO: Add your command handler code here
m_tree=false;
InvalidateRect(NULL,FALSE);
}
void CTESTView::OnWenli2()
{
// TODO: Add your command handler code here
m_image=1;
LoadGLTextures();
InvalidateRect(NULL,FALSE);
}
void CTESTView::OnWenli3()
{
// TODO: Add your command handler code here
m_image=2;
LoadGLTextures();
InvalidateRect(NULL,FALSE);
}
void CTESTView::OnWenli4()
{
// TODO: Add your command handler code here
m_image=3;
LoadGLTextures();
InvalidateRect(NULL,FALSE);
}
void CTESTView::load3dobj(char *dir, char *cn, int a)//调入3DS模型
{
char appdir[256];
GetCurrentDirectory(256,appdir);//取当前目录
SetCurrentDirectory(dir);//置当前目录为DIR指定的目录
m_3ds->Init(cn,a);//调用模型调入函数
SetCurrentDirectory(appdir);//恢复目录
}
void CTESTView::Scene(int obj, float x, float h, float z, float r, int re, float size)//3ds模型的显示
{
glPushMatrix();//压入堆栈
int y=GetHeight(x,z)+h;
glTranslatef(x,y,z);
glRotatef(re, 0.0, 1.0, 0.0);
if(obj>0) glRotatef(-20, 1.0, 0.0, 0.0);
m_3ds->show3ds(obj,0,0.0f,r,size);
glPopMatrix();
}
void CTESTView::On3ds()
{
// TODO: Add your command handler code here
m_show3ds=true;
LoadGLTextures();
InvalidateRect(NULL,FALSE);
}
void CTESTView::On3dsOut()
{
// TODO: Add your command handler code here
m_show3ds=false;
LoadGLTextures();
InvalidateRect(NULL,FALSE);
}
void CTESTView::OnTimer(UINT nIDEvent)
{
// TODO: Add your message handler code here and/or call default
if(r<360)
r+=20;
else
r=0;
InvalidateRect(NULL,FALSE);
CView::OnTimer(nIDEvent);
}
3、程序下载(时间太久了,这个应该这VC++6.0下编译的)https://download.csdn.net/download/sailingw/16781412