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<bitmapheader.bfSize)
{
for(int j=0;j<ImageWidth;j++)
for(int k=0;k<ImageHeight;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\glext.h>
這是因爲後面的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; 
  int   cactus=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;
 HDC  hDC;   // GDI設備描述表
 HGLRC hRC;      // 永久着色描述表
 BOOL SetupPixelFormat(HDC hDC);
 void init(int Width, int Height);
 void Render();
 void CleanUp();
/////////////////////////////////////////////////////////////////////////
 CGLFont* Font;
 int  m_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());
 int   nListNum; 
 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:
 float  g_terrain [MAP_W*MAP_W][3];
 GLuint  g_index  [MAP_W*MAP_W* 2];
 float  g_texcoord [MAP_W*MAP_W][2];
 void  InitTerrain(float h); 
 void  DrawSand(); 
 float  GetHeight(float x, float z);

 float     g_eye [3];
 float     g_look[3];
 float     rad_xz; 
 float     g_Angle;
 float     g_elev; 
 BOOL  DisplayScene(); 

 UINT  g_cactus[16];
 BITMAPINFOHEADER  g_bit;
 unsigned char    *g_imageData;
 void  CreateSkyBox(int a,int wi,int he,int le);
 void  texture(UINT textur);
 void  light0();   

 void  picter(float x,float y,float z);
 bool  LoadT8(char *filename, GLuint &texture);
 void  LoadT16(char *filename, GLuint &texture);
 unsigned char* LoadBit(char *filename, BITMAPINFOHEADER *bitmap);

 void  ShowTree(float x,float z,float h,float s,int cactus);
 void  ShowTree0(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;
float  gao=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 = 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]<  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 
     );
  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; 
  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;
}
/////////////////////////////////////////////////////////////////////////////
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;
HDC  hDC;  // GDI設備句柄,將窗口連接到 GDI( 圖形設備接口)
HGLRC hRC=NULL; // 渲染描述句柄,將OpenGL調用連接到設備描述表
HWND hWnd=NULL; // 保存 Windows 分配給程序的窗口句柄
int  Width = 800;// 窗口寬
int  Height= 600;// 窗口高
int  bits  = 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);
   }
        else  m_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;  // 窗口尺寸
 int  nX=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;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章