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

2023-10-25 17:08

本文主要是介绍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/
// CTESTViewIMPLEMENT_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 commandsON_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/destructionCTESTView::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;//3dsm_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 cscs.style |= WS_CLIPSIBLINGS | WS_CLIPCHILDREN;return CView::PreCreateWindow(cs);
}/
// CTESTView drawingvoid 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 printingBOOL CTESTView::OnPreparePrinting(CPrintInfo* pInfo)
{// default preparationreturn 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 handlersvoid CTESTView::OnSize(UINT nType, int cx, int cy) 
{CView::OnSize(nType, cx, cy);// TODO: Add your message handler code hereGLdouble aspect_ratio; // width/height ratioif ( 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 equalaspect_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 defaultreturn TRUE;
}int CTESTView::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{if (CView::OnCreate(lpCreateStruct) == -1)return -1;// TODO: Add your specialized creation code hereSetTimer(1,1,NULL);//启动定时器1,定时时间是1秒InitializeOpenGL();return 0;
}void CTESTView::OnDestroy() 
{CView::OnDestroy();// TODO: Add your message handler code hereif(::wglMakeCurrent (0,0) == FALSE){MessageBox("Could not make RC non-current");}//Delete the rendering contextif(::wglDeleteContext (m_hRC)==FALSE){MessageBox("Could not delete RC");}//Delete the DCif(m_pDC){delete m_pDC;}//Set it to NULLm_pDC = NULL;}
BOOL CTESTView::InitializeOpenGL()
{//Get a DC for the Client Aream_pDC = new CClientDC(this);//Failure to Get DCif(m_pDC == NULL){MessageBox("Error Obtaining DC");return FALSE;}//Failure to set the pixel formatif(!SetupPixelFormat()){return FALSE;}//Create Rendering Contextm_hRC = ::wglCreateContext (m_pDC->GetSafeHdc ());//Failure to Create Rendering Contextif(m_hRC == 0){MessageBox("Error Creating RC");return FALSE;}//Make the RC Currentif(::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 pfd1, // version numberPFD_DRAW_TO_WINDOW | // support windowPFD_SUPPORT_OPENGL | // support OpenGLPFD_DOUBLEBUFFER, // double bufferedPFD_TYPE_RGBA, // RGBA type24, // 24-bit color depth0, 0, 0, 0, 0, 0, // color bits ignored0, // no alpha buffer0, // shift bit ignored0, // no accumulation buffer0, 0, 0, 0, // accum bits ignored16, // 16-bit z-buffer0, // no stencil buffer0, // no auxiliary bufferPFD_MAIN_PLANE, // main layer0, // reserved0, 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 herem_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 defaultswitch (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 defaultm_MouseDownPoint=point;SetCapture();CView::OnLButtonDown(nFlags, point);
}void CTESTView::OnLButtonUp(UINT nFlags, CPoint point) 
{// TODO: Add your message handler code here and/or call defaultm_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 defaultif (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 viewInvalidateRect(NULL,FALSE);//Set the mouse pointm_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);//高度Yg_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 herem_tree=true;InvalidateRect(NULL,FALSE);}void CTESTView::OnTreeOut() 
{// TODO: Add your command handler code herem_tree=false;InvalidateRect(NULL,FALSE);}void CTESTView::OnWenli2() 
{// TODO: Add your command handler code herem_image=1;LoadGLTextures();InvalidateRect(NULL,FALSE);}void CTESTView::OnWenli3() 
{// TODO: Add your command handler code herem_image=2;LoadGLTextures();InvalidateRect(NULL,FALSE);}void CTESTView::OnWenli4() 
{// TODO: Add your command handler code herem_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 herem_show3ds=true;LoadGLTextures();InvalidateRect(NULL,FALSE);
}void CTESTView::On3dsOut() 
{// TODO: Add your command handler code herem_show3ds=false;LoadGLTextures();InvalidateRect(NULL,FALSE);
}void CTESTView::OnTimer(UINT nIDEvent) 
{// TODO: Add your message handler code here and/or call defaultif(r<360)r+=20;elser=0;InvalidateRect(NULL,FALSE);CView::OnTimer(nIDEvent);
}

3、程序下载(时间太久了,这个应该这VC++6.0下编译的)https://download.csdn.net/download/sailingw/16781412

这篇关于OpenGL下三维景观的生成及漫游的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/283973

相关文章

Java编译生成多个.class文件的原理和作用

《Java编译生成多个.class文件的原理和作用》作为一名经验丰富的开发者,在Java项目中执行编译后,可能会发现一个.java源文件有时会产生多个.class文件,从技术实现层面详细剖析这一现象... 目录一、内部类机制与.class文件生成成员内部类(常规内部类)局部内部类(方法内部类)匿名内部类二、

使用Jackson进行JSON生成与解析的新手指南

《使用Jackson进行JSON生成与解析的新手指南》这篇文章主要为大家详细介绍了如何使用Jackson进行JSON生成与解析处理,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1. 核心依赖2. 基础用法2.1 对象转 jsON(序列化)2.2 JSON 转对象(反序列化)3.

java中使用POI生成Excel并导出过程

《java中使用POI生成Excel并导出过程》:本文主要介绍java中使用POI生成Excel并导出过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录需求说明及实现方式需求完成通用代码版本1版本2结果展示type参数为atype参数为b总结注:本文章中代码均为

在java中如何将inputStream对象转换为File对象(不生成本地文件)

《在java中如何将inputStream对象转换为File对象(不生成本地文件)》:本文主要介绍在java中如何将inputStream对象转换为File对象(不生成本地文件),具有很好的参考价... 目录需求说明问题解决总结需求说明在后端中通过POI生成Excel文件流,将输出流(outputStre

C/C++随机数生成的五种方法

《C/C++随机数生成的五种方法》C++作为一种古老的编程语言,其随机数生成的方法已经经历了多次的变革,早期的C++版本使用的是rand()函数和RAND_MAX常量,这种方法虽然简单,但并不总是提供... 目录C/C++ 随机数生成方法1. 使用 rand() 和 srand()2. 使用 <random

Flask 验证码自动生成的实现示例

《Flask验证码自动生成的实现示例》本文主要介绍了Flask验证码自动生成的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习... 目录生成图片以及结果处理验证码蓝图html页面展示想必验证码大家都有所了解,但是可以自己定义图片验证码

Python如何在Word中生成多种不同类型的图表

《Python如何在Word中生成多种不同类型的图表》Word文档中插入图表不仅能直观呈现数据,还能提升文档的可读性和专业性,本文将介绍如何使用Python在Word文档中创建和自定义各种图表,需要的... 目录在Word中创建柱形图在Word中创建条形图在Word中创建折线图在Word中创建饼图在Word

nginx生成自签名SSL证书配置HTTPS的实现

《nginx生成自签名SSL证书配置HTTPS的实现》本文主要介绍在Nginx中生成自签名SSL证书并配置HTTPS,包括安装Nginx、创建证书、配置证书以及测试访问,具有一定的参考价值,感兴趣的可... 目录一、安装nginx二、创建证书三、配置证书并验证四、测试一、安装nginxnginx必须有"-

Java实战之利用POI生成Excel图表

《Java实战之利用POI生成Excel图表》ApachePOI是Java生态中处理Office文档的核心工具,这篇文章主要为大家详细介绍了如何在Excel中创建折线图,柱状图,饼图等常见图表,需要的... 目录一、环境配置与依赖管理二、数据源准备与工作表构建三、图表生成核心步骤1. 折线图(Line Ch

浅析如何使用Swagger生成带权限控制的API文档

《浅析如何使用Swagger生成带权限控制的API文档》当涉及到权限控制时,如何生成既安全又详细的API文档就成了一个关键问题,所以这篇文章小编就来和大家好好聊聊如何用Swagger来生成带有... 目录准备工作配置 Swagger权限控制给 API 加上权限注解查看文档注意事项在咱们的开发工作里,API