OpenGL下三维景观的生成及漫游

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

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

海亲王

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值