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

相关文章

hdu1240、hdu1253(三维搜索题)

1、从后往前输入,(x,y,z); 2、从下往上输入,(y , z, x); 3、从左往右输入,(z,x,y); hdu1240代码如下: #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#inc

AI一键生成 PPT

AI一键生成 PPT 操作步骤 作为一名打工人,是不是经常需要制作各种PPT来分享我的生活和想法。但是,你们知道,有时候灵感来了,时间却不够用了!😩直到我发现了Kimi AI——一个能够自动生成PPT的神奇助手!🌟 什么是Kimi? 一款月之暗面科技有限公司开发的AI办公工具,帮助用户快速生成高质量的演示文稿。 无论你是职场人士、学生还是教师,Kimi都能够为你的办公文

hdu4826(三维DP)

这是一个百度之星的资格赛第四题 题目链接:http://acm.hdu.edu.cn/contests/contest_showproblem.php?pid=1004&cid=500 题意:从左上角的点到右上角的点,每个点只能走一遍,走的方向有三个:向上,向下,向右,求最大值。 咋一看像搜索题,先暴搜,TLE,然后剪枝,还是TLE.然后我就改方法,用DP来做,这题和普通dp相比,多个个向上

pdfmake生成pdf的使用

实际项目中有时会有根据填写的表单数据或者其他格式的数据,将数据自动填充到pdf文件中根据固定模板生成pdf文件的需求 文章目录 利用pdfmake生成pdf文件1.下载安装pdfmake第三方包2.封装生成pdf文件的共用配置3.生成pdf文件的文件模板内容4.调用方法生成pdf 利用pdfmake生成pdf文件 1.下载安装pdfmake第三方包 npm i pdfma

poj 1258 Agri-Net(最小生成树模板代码)

感觉用这题来当模板更适合。 题意就是给你邻接矩阵求最小生成树啦。~ prim代码:效率很高。172k...0ms。 #include<stdio.h>#include<algorithm>using namespace std;const int MaxN = 101;const int INF = 0x3f3f3f3f;int g[MaxN][MaxN];int n

poj 1287 Networking(prim or kruscal最小生成树)

题意给你点与点间距离,求最小生成树。 注意点是,两点之间可能有不同的路,输入的时候选择最小的,和之前有道最短路WA的题目类似。 prim代码: #include<stdio.h>const int MaxN = 51;const int INF = 0x3f3f3f3f;int g[MaxN][MaxN];int P;int prim(){bool vis[MaxN];

poj 2349 Arctic Network uva 10369(prim or kruscal最小生成树)

题目很麻烦,因为不熟悉最小生成树的算法调试了好久。 感觉网上的题目解释都没说得很清楚,不适合新手。自己写一个。 题意:给你点的坐标,然后两点间可以有两种方式来通信:第一种是卫星通信,第二种是无线电通信。 卫星通信:任何两个有卫星频道的点间都可以直接建立连接,与点间的距离无关; 无线电通信:两个点之间的距离不能超过D,无线电收发器的功率越大,D越大,越昂贵。 计算无线电收发器D

hdu 1102 uva 10397(最小生成树prim)

hdu 1102: 题意: 给一个邻接矩阵,给一些村庄间已经修的路,问最小生成树。 解析: 把已经修的路的权值改为0,套个prim()。 注意prim 最外层循坏为n-1。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstri

【生成模型系列(初级)】嵌入(Embedding)方程——自然语言处理的数学灵魂【通俗理解】

【通俗理解】嵌入(Embedding)方程——自然语言处理的数学灵魂 关键词提炼 #嵌入方程 #自然语言处理 #词向量 #机器学习 #神经网络 #向量空间模型 #Siri #Google翻译 #AlexNet 第一节:嵌入方程的类比与核心概念【尽可能通俗】 嵌入方程可以被看作是自然语言处理中的“翻译机”,它将文本中的单词或短语转换成计算机能够理解的数学形式,即向量。 正如翻译机将一种语言

poj 3723 kruscal,反边取最大生成树。

题意: 需要征募女兵N人,男兵M人。 每征募一个人需要花费10000美元,但是如果已经招募的人中有一些关系亲密的人,那么可以少花一些钱。 给出若干的男女之间的1~9999之间的亲密关系度,征募某个人的费用是10000 - (已经征募的人中和自己的亲密度的最大值)。 要求通过适当的招募顺序使得征募所有人的费用最小。 解析: 先设想无向图,在征募某个人a时,如果使用了a和b之间的关系