3D游戏引擎开发工具OpenGL

OpenGL(全写Open Graphics Library)是个定义了一个跨 编程语言 、跨平台的 编程接口 的规格,它用于三维图象(二维的亦可)。OpenGL是个专业的图形 程序接口 ,是一个功能强大,调用方便的底层图形库。 Silicon Graphics,Microsoft, HP,Intel达成协议联合开发下一代3D API——Fahrenheit。但不了了之,因为 微软 的打算是把OpenGL的技术用到D3D里并且以此之名驱除OpenGL的威胁。(估计DirectX 8 Graphics即是剩下 微软 独自开发的Fahrenheit,吸收了OpenGL的很多东西。) OpenGL豪气不减当年! OpenGL依然是唯一能与微软单独控制的D3D对立的API,尽管 Silicon Graphics 不再以任何微软不能接受的方式推行OpenGL。游戏开发这是独立的,并且很多关键人物在用OpenGL,因此,硬件厂商正努力提高对其支持。D3D仍不能支持高端 图像 和专业应用,而OpenGL主宰着这些土地。在开放原码社区,Mesa项目正提供独立于微软的OpenGL驱动。 OpenGL开发游戏引擎 方法一:
首先获取位图句柄 HBITMAP hBmp = (HBITMAP) ::LoadImage (AfxGetResourceHandle(),MAKEINTRESOURCE(IDB_BITMAP1), IMAGE_BITMAP, 0, 0,LR_CREATEDIBSECTION); 然后根据位图句柄得到位图信息 BITMAP BM; ::GetObject (hBmp, sizeof (BM), &BM); 最后根据位图信息中的RGB值建立纹理 gluBuild2DMipmaps( GL_TEXTURE_2D, 3, BM.bmWidth, BM.bmHeight,GL_BGR_EXT, GL_UNSIGNED_BYTE,BM.bmBits); 方法二:
首先用OpenGL辅助库获得位图信息 AUX_RGBImageRec* TextureImage[1]; TextureImage[0]=auxDIBImageLoad("1.bmp"); 然后建立纹理 gluBuild2DMipmaps(GL_TEXTURE_2D, 3, TextureImage[0]->sizeX, TextureImage[0]->sizeY, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data); 方法三: 从底层做,需要了解bmp文件的结构,首先读取bmp文件结构,包括文件头、信息头和数据,数据用于后面定义纹理; long ImageWidth=256;
long ImageHeight=256;
GLubyte Image[256][256][3];
void ReadHeader(FILE *fp , BITMAPFH * p_bitmapheader , BITMAPIH *p_bitmapinfo)
{
fseek(fp, 0, SEEK_SET);
fread( &p_bitmapheader->bfType,sizeof(unsigned short), 1, fp );
fseek(fp, 2, SEEK_SET);
fread( &p_bitmapheader->bfSize,sizeof(unsigned long), 1, fp );
fseek(fp, 6, SEEK_SET);
fread( &p_bitmapheader->bfReserved1,sizeof(unsigned short), 1, fp );
fseek(fp, 8, SEEK_SET);
fread( &p_bitmapheader->bfReserved2,sizeof(unsigned short), 1, fp );
fseek(fp, 10, SEEK_SET);
fread( &p_bitmapheader->bfOffBits,sizeof(unsigned long), 1, fp );
fseek(fp, 14, SEEK_SET);
fread( &p_bitmapinfo->biSize, sizeof(unsigned long), 1, fp );
fseek(fp, 18, SEEK_SET);
fread( &p_bitmapinfo->biWidth, sizeof(unsigned long), 1, fp );
fseek(fp, 22, SEEK_SET);
fread( &p_bitmapinfo->biHeight, sizeof(unsigned long), 1, fp );
fseek(fp, 26, SEEK_SET);
fread( &p_bitmapinfo->biPlanes, sizeof(unsigned short), 1, fp );
fseek(fp, 28, SEEK_SET);
fread( &p_bitmapinfo->biBitCount, sizeof(unsigned short), 1, fp );
fseek(fp, 30, SEEK_SET);
fread( &p_bitmapinfo->biCompression, sizeof(unsigned long), 1, fp );
fseek(fp, 34, SEEK_SET);
fread( &p_bitmapinfo->biSizeImage, sizeof(unsigned long), 1, fp );
fseek(fp, 38, SEEK_SET);
fread( &p_bitmapinfo->biXPelsPerMeter, sizeof(unsigned long), 1, fp );
fseek(fp, 42, SEEK_SET);
fread( &p_bitmapinfo->biYPelsPerMeter, sizeof(unsigned long), 1, fp );
fseek(fp, 46, SEEK_SET);
fread( &p_bitmapinfo->biClrUsed, sizeof(unsigned long), 1, fp );
fseek(fp, 50, SEEK_SET);
fread( &p_bitmapinfo->biClrImportant, sizeof(unsigned long), 1, fp );
}
void ReadBitmapFile()
{
BITMAPFH bitmapheader;
BITMAPIH bitmapinfo;
FILE *fp;
fp = fopen("6.bmp" , "r");
if(!fp)
{
puts("Read file failed.");
return;
}
ReadHeader(fp, &bitmapheader , &bitmapinfo);
if(bitmapinfo.biBitCount != 24)
{
puts("UNSUPPORT") ;
return;
}
ImageWidth = bitmapinfo.biWidth;
ImageHeight = bitmapinfo.biHeight;
int i=bitmapheader.bfOffBits;
while(i {
for(int j=0; j for(int k=0; k {
fseek(fp, i, SEEK_SET) ;
fread(Image[j][k]+2, 1, 1, fp);
fseek(fp, i+1, SEEK_SET) ;
fread(Image[j][k]+1, 1, 1, fp);
fseek(fp, i+2, SEEK_SET) ;
fread(Image[j][k], 1, 1, fp);
i=i+3;
}
}
fclose(fp) ;
}
90 glTexImage2D(GL_TEXTURE_2D,0,3,ImageWidth,ImageHeight,0,GL_RGB,GL_UNSIGNED_BYTE,&Image[0][0][0]);
#include 这是因为后面的GL_BGR_EXT是定义在这个头文件里的,因为BMP格式是按Blue,Green,Red顺序储存图像数据的,这与OpenGL中正好相反。GL_BGR_EXT就是完成两者之间的转换的。
下面就是不用AUX库来加载BMP图片作为纹理的函数: bool LoadTexture(LPTSTR szFileName, GLuint &texid)// Creates Texture From A Bitmap File
{
HBITMAP hBMP; // Handle Of The Bitmap
BITMAP BMP; // Bitmap Structure

glGenTextures(1, &texid); // Create The Texture
hBMP=(HBITMAP)LoadImage(GetModuleHandle(NULL), szFileName, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION | LR_LOADFROMFILE );

if (!hBMP)// Does The Bitmap Exist?
return FALSE; // If Not Return False
GetObject(hBMP, sizeof(BMP), &BMP); // Get The Object
// hBMP:Handle To Graphics Object
// sizeof(BMP): Size Of Buffer For Object Information
// &BMP:Buffer For Object Information
glPixelStorei(GL_UNPACK_ALIGNMENT, 4); // Pixel Storage Mode (Word Alignment / 4 Bytes)
// Typical Texture Generation Using Data From The Bitmap
glBindTexture(GL_TEXTURE_2D, texid); // Bind To The Texture ID
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); // Linear Min Filter
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // Linear Mag Filter
glTexImage2D(GL_TEXTURE_2D, 0, 3, BMP.bmWidth, BMP.bmHeight, 0, GL_BGR_EXT, GL_UNSIGNED_BYTE, BMP.bmBits);
DeleteObject(hBMP); // Delete The Object
return TRUE; // Loading Was Successful
}


OpenGL加载3d模型: OpenGL.cpp //
#include "stdafx.h"
#include "OpenGL.h"
//
GLfloat r;
CString test;
//
OpenGL::OpenGL()
{ hFont=CreateFont(-12,0,0,0,400,0,0,0,GB2312_CHARSET,0,0,0,FF_MODERN,"Arial");
hFont0 =CreateFont(-48,0,0,0,800,0,0,0,GB2312_CHARSET,0,0,0,FF_MODERN,"黑体");
m_Fram=0; //
m_Time = timeGetTime(); //
tim=0; //刷屏速度
Font=new CGLFont() ;
}
OpenGL::~OpenGL()
{ CleanUp();
}
BOOL OpenGL::SetupPixelFormat(HDC hDC0)//检测安装OpenGL
{ int nPixelFormat; // 象素点格式
hDC=hDC0;
PIXELFORMATDESCRIPTOR pfd = {
sizeof(PIXELFORMATDESCRIPTOR),// pfd结构的大小
1,// 版本号
PFD_DRAW_TO_WINDOW |// 支持在窗口中绘图
PFD_SUPPORT_OPENGL |// 支持 OpenGL
PFD_DOUBLEBUFFER,// 双缓存模式
PFD_TYPE_RGBA,// RGBA 颜色模式
16,// 24 位颜色深度
0, 0, 0, 0, 0, 0,// 忽略颜色位
0,// 没有非透明度缓存
0,// 忽略移位位
0,// 无累加缓存
0, 0, 0, 0,// 忽略累加位
16,// 32 位深度缓存
0,// 无模板缓存
0,// 无辅助缓存
PFD_MAIN_PLANE,// 主层
0,// 保留
0, 0, 0// 忽略层,可见性和损毁掩模
};
if (!(nPixelFormat = ChoosePixelFormat(hDC, &pfd)))
{ MessageBox(NULL,"没找到合适的显示模式","Error",MB_OK|MB_ICONEXCLAMATION);
return FALSE;
}
SetPixelFormat(hDC,nPixelFormat,&pfd); //设置当前设备的像素点格式
hRC = wglCreateContext(hDC); //获取渲染描述句柄
wglMakeCurrent(hDC, hRC); //激活渲染描述句柄
m_baiscobj=new baiscobj();
m_baiscobj->light0();
return TRUE;
}
void OpenGL::init(int Width, int Height)
{ glViewport(0,0,Width,Height); // 设置OpenGL视口大小。
glMatrixMode(GL_PROJECTION); // 设置当前矩阵为投影矩阵。
glLoadIdentity(); // 重置当前指定的矩阵为单位矩阵
gluPerspective// 设置透视图
( 54.0f,// 透视角设置为 45 度
(GLfloat)Width/(GLfloat)Height, // 窗口的宽与高比
0.1f,// 视野透视深度:近点1.0f
3000.0f// 视野透视深度:始点0.1f远点1000.0f
);
// 这和照象机很类似,第一个参数设置镜头广角度,第二个参数是长宽比,后面是远近剪切。
glMatrixMode(GL_MODELVIEW); // 设置当前矩阵为模型视图矩阵
glLoadIdentity(); // 重置当前指定的矩阵为单位矩阵
//
//====================================================
}
void OpenGL::Render()//OpenGL图形处理
{ glClearColor(0.0f, 0.0f, 0.3f, 1.0f); // 设置刷新背景色
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); // 刷新背景
glLoadIdentity(); // 重置当前的模型观察矩阵
//
m_baiscobj->DisplayScene();
m_baiscobj->CreateSkyBox(3,6,3,6);
m_baiscobj->DrawSand();
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;
intcactus=rand()%4+11;
m_baiscobj->ShowTree(x,z,size,h,cactus);
}
m_baiscobj->picter(MAP+10,0,-MAP);
m_baiscobj->Scene(0,MAP+30,13.6f,-MAP-20, 0,0,0.35f);
m_baiscobj->Scene(1,MAP+30,19.0f,-MAP,100,r,0.2f);
m_baiscobj->Scene(2,MAP+30,20.0f,-MAP,165,r+90,0.5f);
//
text();
SwapBuffers(hDC); // 切换缓冲区
}
void OpenGL::CleanUp()
{wglMakeCurrent(hDC, NULL); //清除OpenGL
wglDeleteContext(hRC); //清除OpenGL
}
///
void OpenGL::text()
{ DWORD Dura =(timeGetTime()-m_Time)/1000;
if(Dura>0) tim=m_Fram/Dura;
m_Fram++;
char str[128];
sprintf(str, "刷屏: %2d 帧/秒 %s",tim,test);
Font->settext(350,550,str,hFont,1,1,1.0f);
Font->settext(419,258,"+",hFont,1,0,0);
}
OpenGL.h // OpenGL.h: interface for the OpenGL class.
//
//
#if !defined(AFX_OPENGL_H__17B7289C_7956_41C5_89B9_621E3C435389__INCLUDED_)
#define AFX_OPENGL_H__17B7289C_7956_41C5_89B9_621E3C435389__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include "baiscobj.h"
#include "GLFont.h"
class OpenGL
{ public: OpenGL();
virtual ~OpenGL();
public:
baiscobj* m_baiscobj;
HDChDC; // GDI设备描述表
HGLRC hRC; // 永久着色描述表
BOOL SetupPixelFormat(HDC hDC);
void init(int Width, int Height);
void Render();
void CleanUp();
/
CGLFont* Font;
intm_Time,m_Fram,tim;
HFONT hFont,hFont0;
void text();
};
#endif // !defined(AFX_OPENGL_H__17B7289C_7956_41C5_89B9_621E3C435389__INCLUDED_)

GLFont.h

// GLFont.h: interface for the CGLFont class.
#if !defined(AFX_GLFONT_H__88F1F000_50F5_452A_B95E_60ED83712FA5__INCLUDED_)
#define AFX_GLFONT_H__88F1F000_50F5_452A_B95E_60ED83712FA5__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
class CGLFont
{
public:
void entext(float x,float y, LPCTSTR str,HFONT hFont,float r,float g,float b);
void c3dtext(LPCTSTR str,HFONT hFont,float z);
void Printfc3d(CString strText,HFONT hFont,float z=0.05f);
void Printftext(int x, int y, LPCTSTR lpszText,HFONT hFont);
void settext(float x,float y,CString str,HFONT Font,float r,float g,float b);
CGLFont();
virtual ~CGLFont();
protected:
HFONT hFont;
};
#endif // !defined(AFX_GLFONT_H__88F1F000_50F5_452A_B95E_60ED83712FA5__INCLUDED_)


GLFont.cpp #include "stdafx.h"
#include "GLFont.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//
//unsigned int Base;
//
CGLFont::CGLFont()
{
}
CGLFont::~CGLFont()
{
}
void CGLFont::entext( float x,float y, LPCTSTR str, HFONT hFont,
float r, float g, float b)
{HDC hdc = wglGetCurrentDC();
SelectObject(hdc, hFont);
unsigned int Base = glGenLists(96);
wglUseFontBitmaps(hdc, 32, 96,Base);
glDisable(GL_TEXTURE_2D);
glDisable(GL_LIGHTING);
glPushAttrib(GL_LIST_BIT);
glColor3f(r,g,b);
glRasterPos2f(x/100, y/100);
glListBase(Base - 32);
glCallLists(strlen(str), GL_UNSIGNED_BYTE, str);
glPopAttrib();
glEnable(GL_LIGHTING);
glEnable(GL_TEXTURE_2D);
glDeleteLists(Base, 96);
}
//
void CGLFont::c3dtext(LPCTSTR str,HFONT hFont,float z)
{ glDisable(GL_TEXTURE_2D);
glDisable(GL_LIGHTING);
Printfc3d("立体汉字",hFont,z);
glEnable(GL_LIGHTING);
glEnable(GL_TEXTURE_2D);
}
void CGLFont::Printfc3d(CString strText,HFONT hFont,float z)
{ HDC hdc = wglGetCurrentDC();
HFONT hOldFont=(HFONT)::SelectObject(hdc,hFont);
UCHAR * pChar=(UCHAR*)strText.GetBuffer(strText.GetLength());
intnListNum;
DWORD dwChar;
GLYPHMETRICSFLOAT pgmf[1];
glPushMatrix();
for(int i = 0; i < strText.GetLength(); i++)
{ if(IsDBCSLeadByte((BYTE)pChar[i]))
{ dwChar=(DWORD)((pChar[i]<<8)|pChar[i+1]);
i++;
}
else dwChar = pChar[i];
nListNum = glGenLists(1);
wglUseFontOutlines( hdc,
dwChar,
1,
nListNum,
0.0f,
z,
WGL_FONT_POLYGONS,
pgmf
);
glCallList(nListNum);
glDeleteLists(nListNum, 1);
}
glPopMatrix();
strText.ReleaseBuffer();
::SelectObject(hdc,hOldFont);
}

void CGLFont:: settext (float x,float y,CString str,HFONT Font,float r,float g,float b)

{glLoadIdentity();
glPushAttrib(GL_CURRENT_BIT);
glDisable(GL_TEXTURE_2D);
glDisable(GL_LIGHTING);
glColor3f(r,g,b);
glTranslatef(-(420-x)/800,(260-y)/600,-1.0f);
Printftext (0,0, str,Font);
glEnable(GL_LIGHTING);
glEnable(GL_TEXTURE_2D);
glPopAttrib();
}
void CGLFont:: Printftext (int x, int y, LPCTSTR lpszText,HFONT hFont)
{ CBitmap bitmap;
BITMAP bm;
SIZE size;
HDC MDC = ::CreateCompatibleDC(0);
SelectObject(MDC,hFont);
::GetTextExtentPoint32(MDC,lpszText,strlen(lpszText),&size);
bitmap.CreateBitmap(size.cx, size.cy, 1, 1, NULL);
HBITMAP oldBmp=(HBITMAP)SelectObject(MDC,bitmap);
SetBkColor(MDC, RGB(0,0,0));
SetTextColor(MDC, RGB(255, 255, 255));
TextOut(MDC, 0, 0, lpszText, strlen(lpszText));
bitmap.GetBitmap(&bm);
size.cx = (bm.bmWidth + 31) & (~31);
int bufsize =size.cy * size.cx;
struct {BITMAPINFOHEADER bih;
RGBQUAD col[2];
}bic;
BITMAPINFO *binf = (BITMAPINFO *)&bic;
binf->bmiHeader.biSize= sizeof(binf->bmiHeader); //
binf->bmiHeader.biWidth= bm.bmWidth;
binf->bmiHeader.biHeight= bm.bmHeight;
binf->bmiHeader.biPlanes= 1;
binf->bmiHeader.biBitCount = 1;
binf->bmiHeader.biCompression = BI_RGB;
binf->bmiHeader.biSizeImage= bufsize;
UCHAR* Bits = new UCHAR[bufsize];
::GetDIBits(MDC,bitmap,0,bm.bmHeight,Bits,binf,DIB_RGB_COLORS);

glPixelStorei(GL_UNPACK_ALIGNMENT ,1);
glRasterPos2i(x,y);
glBitmap(size.cx,size.cy,0,0,0,0,Bits);
delete Bits;
SelectObject(MDC, oldBmp);
::DeleteDC(MDC);
}

BAISCOBJ.H // baiscobj.h: interface for the baiscobj class.
//
//
#if !defined(AFX_BAISCOBJ_H__6F90C6A0_F5E4_4482_BA6B_136D5C922B31__INCLUDED_)
#define AFX_BAISCOBJ_H__6F90C6A0_F5E4_4482_BA6B_136D5C922B31__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
class baiscobj
{
public:
baiscobj();
virtual ~baiscobj();
public:
floatg_terrain [MAP_W*MAP_W][3];
GLuintg_index[MAP_W*MAP_W* 2];
floatg_texcoord [MAP_W*MAP_W][2];
voidInitTerrain(float h);
voidDrawSand();
floatGetHeight(float x, float z);
floatg_eye [3];
floatg_look[3];
floatrad_xz;
floatg_Angle;
floatg_elev;
BOOLDisplayScene();
【3D游戏引擎开发工具OpenGL】 UINTg_cactus[16];
BITMAPINFOHEADERg_bit;
unsigned char*g_imageData;
voidCreateSkyBox(int a,int wi,int he,int le);
voidtexture(UINT textur);
voidlight0();
voidpicter(float x,float y,float z);
boolLoadT8(char *filename, GLuint &texture);
voidLoadT16(char *filename, GLuint &texture);
unsigned char* LoadBit(char *filename, BITMAPINFOHEADER *bitmap);
voidShowTree(float x,float z,float h,float s,int cactus);
voidShowTree0(float x,float z,float h,float s,int cactus);
CLoad3DS* m_3ds;
void load3dobj(char* dir,char* cn,int a);
void Scene(int obj,float x,float h,float z,float r,int re,float size);
};
#endif // !defined(AFX_BAISCOBJ_H__6F90C6A0_F5E4_4482_BA6B_136D5C922B31__INCLUDED_)
BAISCOBJ.CPP #include "stdafx.h"
#include "baiscobj.h"
#include "../include/BITMAP.H"
extern GLfloat r;
floatgao=1.8f;
extern CString test;
//
baiscobj::baiscobj()
{ g_eye[0]= MAP; //
g_eye[2]=-MAP; //
g_Angle=0; //
g_elev=-0; //

char appdir[256];
GetCurrentDirectory(256,appdir);
CString dir=appdir;
if(dir.Right(8)!="运行程序")
SetCurrentDirectory("../运行程序");

g_imageData = https://www.it610.com/article/LoadBit("data/images/Terrain1.bmp",&g_bit); //调等高地形图
LoadT8("data/images/sand0.bmp",g_cactus[0]); //地面帖图
LoadT8("data/images/4RBack.bmp",g_cactus[2]); //天空贴图后
LoadT8("data/images/4Front.bmp",g_cactus[3]); //天空贴图前
LoadT8("data/images/4Top.bmp",g_cactus[4]); //天空贴图顶
LoadT8("data/images/4Left.bmp", g_cactus[5]); //天空贴图左
LoadT8("data/images/4Right.bmp",g_cactus[6]); //天空贴图右
LoadT16("data/images/CACTUS0.BMP",g_cactus[11]); //树1帖图
LoadT16("data/images/CACTUS1.BMP",g_cactus[12]); //树2帖图
LoadT16("data/images/CACTUS2.BMP",g_cactus[13]); //树3帖图
LoadT16("data/images/CACTUS3.BMP",g_cactus[14]); //树4帖图
InitTerrain(5); //初始化地面
m_3ds=new CLoad3DS();
load3dobj("data/3ds/","航天发射台.3DS",0);
load3dobj("data/3ds/","直升机0.3ds",1); //car.3ds
load3dobj("data/3ds/","飞机1.3ds",2); //car.3ds
glEnable(GL_TEXTURE_2D);
}
baiscobj::~baiscobj()
{ for(int i=0; i<16; i++) glDeleteTextures(1, &g_cactus[i]);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
void baiscobj::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);
}
BOOL baiscobj::DisplayScene()
{ float speed=0.5f;
float x=g_eye[0],y=g_eye[2],z=g_eye[2];
if (KEY_DOWN(VK_SHIFT))speed=speed*2;
if (KEY_DOWN(VK_LEFT))g_Angle-=speed*2;
if (KEY_DOWN(VK_RIGHT))g_Angle+=speed*2;
rad_xz = float (3.13149* g_Angle/180.0f);
if (KEY_DOWN(33))g_elev +=speed;
if (KEY_DOWN(34))g_elev -=speed;
if (g_elev<-360)g_elev=-360;
if (g_elev> 360)g_elev= 360;
if (KEY_DOWN(VK_UP))
{ g_eye[2]+=(float)sin(rad_xz)*speed;
g_eye[0]+=(float)cos(rad_xz)*speed;
}
if (KEY_DOWN(VK_DOWN))
{ g_eye[2]-=(float)sin(rad_xz)*speed;
g_eye[0]-=(float)cos(rad_xz)*speed;
}
if(g_eye[0]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
);
int r0=abs((int)g_Angle);
test.Format("[方位=%03d X=%3.0f y=%3.0f 高=%2.1f 俯仰角=%2.0f,re=%03.0f]",
r0%360,g_eye[0],-g_eye[2],g_eye[1],g_elev,r);
return TRUE;
}
//==========================================================================
void baiscobj::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);
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);
}
void baiscobj::DrawSand()
{ glBindTexture(GL_TEXTURE_2D, g_cactus[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]);
}
float baiscobj::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);
float ty =CameraZ - int(CameraZ);
float txty = tx * ty;
return h00*(1.0f-ty-tx+txty)
+ h01*(tx-txty)
+ h11*txty
+ h10*(ty-txty);
}
void baiscobj::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(g_cactus[2]);
glBegin(GL_QUADS);
glTexCoord2f(1.0f,0.0f); glVertex3f(x+width,y,z);
glTexCoord2f(1.0f,1.0f); glVertex3f(x+width,y+height,z);
glTexCoord2f(0.0f,1.0f); glVertex3f(x,y+height,z);
glTexCoord2f(0.0f,0.0f); glVertex3f(x,y,z);
glEnd();
texture(g_cactus[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(g_cactus[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(g_cactus[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(g_cactus[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();
}
void baiscobj::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 baiscobj::picter(float x,float y,float z)
{y=GetHeight(x,z);
glDisable(GL_TEXTURE_2D);
glPushAttrib(GL_CURRENT_BIT);
glPushMatrix();
glTranslatef(x,y+0.5f,z);
glColor3f(0.0f,1.0f,0.2f);
auxSolidCube(1);
glTranslatef(0.0f,0.8f,0.0f);
glColor3f(0.0f,0.0f,1.0f);
auxSolidBox(.2f,1.3f,.2f);
glPopMatrix();
glPushMatrix();
glTranslatef(x,y+2.5f,z);
glRotatef(r-90,0.0,1.0,0.0);
//=======================================
glColor3f(1.0f,1.0f,1.0f);
glRotatef(45, 1.0, 0.0, 0.0);
auxWireCone(1.5,0.6f);
//=======================================
glRotatef(180, 1.0, 0.0, 0.0);
glTranslatef(0.0f,0.0f,-0.7f);
auxWireCone(0.2f,2.0f);
glColor3f(FRAND,0,0);
glTranslatef(0.0f,0.0f,2.0f);
auxSolidSphere(0.1f);
glPopMatrix();
glPushMatrix();
glTranslatef(x,y+10.0f,z);
glRotatef(r, 0.0, 1.0, 0.0);
glTranslatef(x/15,0,0);
//=============================================
glColor3f(1.0f,0.0f,0.0f);
glRotatef(180, 0.0, 1.0, 0.0);
auxSolidCone(.2,0.6);
//=============================================
glColor3f(1.0f,1.0f,1.0f);
glRotatef(90, 1.0, 0.0, 0.0);
glTranslatef(0.0f,-1.0f,0);
auxSolidCylinder(.2f,1);
glRotatef(-270, 1.0, 0.0, 0.0);
glColor3f(FRAND+.6f,0.2f,0.0f);
glTranslatef(0.0f,-0.0f,-0.2f);
auxSolidCone(.2,1.5);
glPopMatrix();
glEnable(GL_TEXTURE_2D);
glPopAttrib();
r+=1.0f; if(r>360) r=0;
glEnable(GL_TEXTURE_2D);
}
bool baiscobj::LoadT8(char *filename, GLuint &texture)
{ 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 baiscobj::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);
}
unsigned char * baiscobj::LoadBit(char *filename, BITMAPINFOHEADER *bitmap)
{ FILE *filePtr;
BITMAPFILEHEADERHeader;
unsigned char*Image;
unsigned intimageIdx = 0;
unsigned chartempRGB;
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;
}
/
void baiscobj::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]);
vector3_t Z(mat[1], mat[5], mat[9]);
glBindTexture(GL_TEXTURE_2D, g_cactus[cactus]);
vector3_t pos(x,0.0,-z);
pos.y = GetHeight(x, -z) + h + s;
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 baiscobj::ShowTree0(float x,float z,float h,float s,int cactus)
{ glPushMatrix(); //
float y = GetHeight(x,-z) + h + s;
glTranslatef(x,y, -z);
glRotatef(180, 1.0, 0.0, 0.0);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_ALPHA_TEST);
glAlphaFunc(GL_GREATER, 0);
glBindTexture(GL_TEXTURE_2D, g_cactus[cactus]);
// glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); //
glBegin(GL_QUADS);
glTexCoord2f(1.0f, 0.0f); glVertex3f(-h, h, 0.0f); // 右上点
glTexCoord2f(0.0f, 0.0f); glVertex3f( h, h, 0.0f); // 右上点
glTexCoord2f(0.0f, 1.0f); glVertex3f( h,-h, 0.0f); // 右下点
glTexCoord2f(1.0f, 1.0f); glVertex3f(-h,-h, 0.0f); // 左下点
glEnd();
glDisable(GL_ALPHA);
glDisable(GL_BLEND);
glPopMatrix();
}

void baiscobj::load3dobj(char* dir,char* cn,int a)
{ char appdir[256];
GetCurrentDirectory(256,appdir);
SetCurrentDirectory(dir);
m_3ds->Init(cn,a);
SetCurrentDirectory(appdir);
}
void baiscobj::Scene(int obj,float x,float h,float z,float r,int re,float size)
{
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();
}
main.cpp #include "stdafx.h"
#include "OpenGL.h"
//
OpenGL* m_OpenGL;
HDChDC; // GDI设备句柄,将窗口连接到 GDI( 图形设备接口)
HGLRC hRC=NULL; // 渲染描述句柄,将OpenGL调用连接到设备描述表
HWND hWnd=NULL; // 保存 Windows 分配给程序的窗口句柄
intWidth = 800; // 窗口宽
intHeight= 600; // 窗口高
intbits= 16; // 颜色深度

void GameLoop()
{MSG msg;
BOOL fMessage;
PeekMessage(&msg, NULL, 0U, 0U, PM_NOREMOVE);
while(msg.message != WM_QUIT) // 消息循环
{fMessage = PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE);
if(fMessage)//有消息
{ TranslateMessage(&msg);
DispatchMessage(&msg);
}
elsem_OpenGL->Render(); //无消息
}
}
LRESULT WINAPI MsgProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam )// 消息处理
{ switch(message)
{ case WM_CREATE:// 建立窗口
hDC = GetDC(hWnd); // 获取当前窗口的设备句柄
m_OpenGL->SetupPixelFormat(hDC); // 调用显示模式安装功能
return 0; break;
case WM_CLOSE:// 关闭窗口
m_OpenGL->CleanUp(); // 结束处理
PostQuitMessage(0);
return 0; break;
case WM_SIZE:// 窗口尺寸变化
Height = HIWORD(lParam); // 窗口的高
Width= LOWORD(lParam); // 窗口的宽
if (Height==0) Height=1; // 防止被0 除
m_OpenGL->init(Width,Height);
return 0; break;
case WM_DESTROY:// 退出消息
PostQuitMessage(0);
return 0; break;
case WM_KEYUP:// 按ESC退出,全屏模式必需要加入的退出方式。
switch (wParam)
{ case VK_ESCAPE:
m_OpenGL->CleanUp(); // 结束处理
PostQuitMessage(0);
return 0; break;
}
default:break;
}
return (DefWindowProc(hWnd, message, wParam, lParam));
}
INT WINAPI WinMain(HINSTANCE hInst,HINSTANCE,LPSTR,INT )// WinMain程序入口
{// 注册窗口类
bool fullScreen =TRUE;
DWORD dwExStyle; // Window 扩展风格
DWORD dwStyle; // Window 窗口风格
RECT windowRect; // 窗口尺寸
intnX=0,nY=0;
/* if (MessageBox(NULL,"使用全屏模式吗?", "将进入OpenGL,选择显示模式",
MB_YESNO|MB_ICONQUESTION|MB_SYSTEMMODAL)==IDNO)
{fullScreen =false; }// 选择窗口模式
if (fullScreen)// 选择全屏模式
{ DEVMODE dmScr; // 设备模式
memset(&dmScr,0,sizeof(dmScr)); // 确保内存分配
dmScr.dmSize=sizeof(dmScr); // Devmode 结构的大小
dmScr.dmPelsWidth = Width; // 屏幕宽
dmScr.dmPelsHeight= Height; // 屏幕高
dmScr.dmBitsPerPel= 16; // 色彩深度
dmScr.dmDisplayFrequency=75; // 刷屏速度
dmScr.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT|DM_DISPLAYFREQUENCY;
if (ChangeDisplaySettings(&dmScr, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL)
{fullScreen=FALSE; }
dwExStyle=WS_EX_APPWINDOW; // Window 扩展风格
dwStyle=WS_POPUP; // Window 窗口风格
ShowCursor(FALSE); // 隐藏鼠标
}
else*/
{ dwExStyle=WS_EX_APPWINDOW|WS_EX_WINDOWEDGE; // 使窗口具有3D外观
dwStyle=WS_OVERLAPPEDWINDOW; // 使用标准窗口
//WS_OVERLAPPEDWINDOW是有标题栏,窗口菜单,最大、小化按钮和可调整尺寸的窗口
int wid=GetSystemMetrics(SM_CXSCREEN); // 获取当前屏幕宽
int hei=GetSystemMetrics(SM_CYSCREEN); // 获取当前屏幕高
nX=(wid-Width)/2; nY=(hei-Height)/2; // 计算窗口居中用
}
//-------------------------------------------------------------------
AdjustWindowRectEx(&windowRect,dwStyle,FALSE,dwExStyle);
//根据窗口风格来调整窗口尺寸达到要求的大小
char cc[]="tml";
WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L,
GetModuleHandle(NULL), NULL, NULL, NULL, NULL,
cc, NULL };
RegisterClassEx( &wc );
m_OpenGL=new OpenGL(); //
hWnd = CreateWindowEx(NULL,cc,"学OpenGL编3D游戏 [ 8.显示3D模型 ]键盘(↑进 ↓退 →右 ←左 UP仰 DOWM俯)",
dwStyle|WS_CLIPCHILDREN|WS_CLIPSIBLINGS,
nX, nY,Width, Height,
NULL,NULL,hInst,NULL); // 创建窗口
ShowWindow( hWnd, SW_SHOWDEFAULT ); // 显示窗口
UpdateWindow( hWnd ); // 刷新窗口
GameLoop(); // 进入消息循环
return 0;
}

    推荐阅读