本文主要是介绍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下三维景观的生成及漫游的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!