由于自己对WIN API不熟悉,所以把Nehe例程改成了“纯”C++实现,当然,windows下编程还是用到了
NeHe教程10是用一张.bmp位图实现了一个三维世界,可以键盘控制视角。
(PS.本人用例程里自带的图片会出问题, 于是我把原图片打开用截图工具重新截取就没问题,猜想是原图存储的方式跟读取的方式不一致导致。)
Lesson10Main.cpp;
#include
#include
#include
#include
#include "../../TE/TEApplication.h"
#include "../../TE/TEGlutWindow.h"
#include "../../TE/TETexture.h";
#include "../../TE/TEFileBitmap.h"
#include "../../TE/TELog.h"
#include "../../TE/TEMacros.h"
using namespace std;
class Lesson10Win : public TEGlutWindow
{
private:
float m_fHeading, m_fXpos, m_fZpos;
GLfloat m_fYrot, m_fWalkBias, m_fWalkbiasAngle, m_fLookupDown, m_fZoom;
GLuint m_uiFilter;
GLuint m_vecTexture[3];
typedef struct tagVERTEX
{
float x, y, z;
float u, v;
} VERTEX;
typedef struct tagTRIANGLE
{
VERTEX vertex[3];
} TRIANGLE;
typedef struct tagSECTOR
{
int numtriangles;
TRIANGLE* triangle;
} SECTOR;
SECTOR sector1;
public:
Lesson10Win();
~Lesson10Win();
//! Read the world's coordinate information;
void readStr(FILE* f, char* string);
//! Write the coordinate to the array;
void setUpWorld(void);
//! Created 3 texutures;
int loadGLTextures(void);
//! Window init;
void onInit();
//! Render the window;
void onRender();
//! Change display when program idle;
void onIdle();
//! Deal with key event;
void onKeyDown(int iKey, char cAscii);
};
Lesson10Win::Lesson10Win()
{
}
Lesson10Win::~Lesson10Win()
{
}
void Lesson10Win::readStr( FILE* f, char* string )
{
do
{
fgets(string, 255, f);
} while ((string[0] == '/') || (string[0] == '\n'));
return;
}
void Lesson10Win::setUpWorld( void )
{
float x, y, z, u, v;
int numtriangles;
FILE* filein;
char oneline[255];
filein = fopen("../run/res/World.txt", "rt");
readStr(filein, oneline);
sscanf(oneline, "NUMPOLLIES %d\n", &numtriangles);
sector1.triangle = new TRIANGLE[numtriangles];
sector1.numtriangles = numtriangles;
for (int i = 0; i < numtriangles; i++)
{
for (int vert = 0; vert < 3; vert++)
{
readStr(filein, oneline);
sscanf(oneline, "%f %f %f %f %f", &x, &y, &z, &u, &v);
sector1.triangle[i].vertex[vert].x = x;
sector1.triangle[i].vertex[vert].y = y;
sector1.triangle[i].vertex[vert].z = z;
sector1.triangle[i].vertex[vert].u = u;
sector1.triangle[i].vertex[vert].v = v;
}
}
fclose(filein);
return;
}
void Lesson10Win::onInit()
{
m_fHeading = 0, m_fXpos = 0, m_fZpos = 0;
m_fYrot = 0, m_fWalkBias = 0, m_fWalkbiasAngle = 0, m_fLookupDown = 0 , m_fZoom = 0;
m_uiFilter = 0;
if (!loadGLTextures())
{
return;
}
glEnable(GL_TEXTURE_2D);
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClearDepth(1.0f);
glDepthFunc(GL_LESS);
glEnable(GL_DEPTH_TEST);
glShadeModel(GL_SMOOTH);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
setUpWorld();
}
void Lesson10Win::onRender()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
GLfloat x_m, y_m, z_m, u_m, v_m;
GLfloat xtrans = -m_fXpos;
GLfloat ztrans = -m_fZpos;
GLfloat ytrans = -m_fWalkBias - 0.25f;
GLfloat sceneroty = 360.0f - m_fYrot;
int numtriangles;
glRotatef(m_fLookupDown, 1.0f, 0.0f, 0.0f);
glRotatef(sceneroty, 0, 1.0f, 0.0f);
glTranslatef(xtrans, ytrans, ztrans);
glBindTexture(GL_TEXTURE_2D, m_vecTexture[m_uiFilter]);
numtriangles = sector1.numtriangles;
for (int loop_m = 0; loop_m < numtriangles; loop_m++)
{
glBegin(GL_TRIANGLES);
glNormal3f(0.0f, 0.0f, 1.0f);
for (int i = 0; i < 3; i++)
{
x_m = sector1.triangle[loop_m].vertex[i].x;
y_m = sector1.triangle[loop_m].vertex[i].y;
z_m = sector1.triangle[loop_m].vertex[i].z;
u_m = sector1.triangle[loop_m].vertex[i].u;
v_m = sector1.triangle[loop_m].vertex[i].v;
glTexCoord2f(u_m,v_m); glVertex3f(x_m,y_m,z_m);
}
glEnd();
}
glutSwapBuffers();
}
void Lesson10Win::onIdle()
{
glutPostRedisplay();
}
int Lesson10Win::loadGLTextures( void )
{
int iStatus = FALSE;
AUX_RGBImageRec* textureImage[1];
memset(textureImage, 0, sizeof(void *)*1);
if ( textureImage[0] = TE::loadAuxBMP("../run/res/Mud.bmp"))
{
iStatus = TRUE;
glGenTextures(3, &m_vecTexture[0]);
//Nearst Filtered texture;
glBindTexture(GL_TEXTURE_2D, m_vecTexture[0]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, 3, textureImage[0]->sizeX, textureImage[0]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, textureImage[0]->data);
//Linear filtered texture;
glBindTexture(GL_TEXTURE_2D, m_vecTexture[1]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, 3, textureImage[0]->sizeX, textureImage[0]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, textureImage[0]->data);
//MipMapped texture;
glBindTexture(GL_TEXTURE_2D, m_vecTexture[2]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
gluBuild2DMipmaps(GL_TEXTURE_2D, 3, textureImage[0]->sizeX, textureImage[0]->sizeY, GL_RGB, GL_UNSIGNED_BYTE, textureImage[0]->data);
}
if (textureImage[0])
{
if (textureImage[0]->data)
{
free(textureImage[0]->data);
}
free(textureImage[0]);
}
return iStatus;
}
void Lesson10Win::onKeyDown( int iKey, char cAscii )
{
TE::log(TE::numToString(iKey));
switch (iKey)
{
case 100://left;
m_fHeading += 1.0f;
m_fYrot = m_fHeading;
break;
case 101://up;
m_fXpos -= (float)sin(m_fHeading*TE_PI_DIV_180)*0.05f;
m_fZpos -= (float)cos(m_fHeading*TE_PI_DIV_180)*0.05f;
if (m_fWalkbiasAngle >= 359.0f)
{
m_fWalkbiasAngle = 0.0f;
}
else
{
m_fWalkbiasAngle += 10.0f;
}
m_fWalkBias = (float)sin(m_fWalkbiasAngle*TE_PI_DIV_180)*0.05f;
break;
case 102://right;
m_fHeading -= 1.0f;
m_fYrot = m_fHeading;
break;
case 103://down;
m_fXpos += (float)sin(m_fHeading*TE_PI_DIV_180)*0.05f;
m_fZpos += (float)cos(m_fHeading*TE_PI_DIV_180)*0.05f;
if (m_fWalkbiasAngle <= 1.0f)
{
m_fWalkbiasAngle = 359.0f;
}
else
{
m_fWalkbiasAngle -= 10.0f;
}
m_fWalkBias = (float)sin(m_fWalkbiasAngle*TE_PI_DIV_180)*0.05f;
break;
default:
break;
}
switch (cAscii)
{
case '\r'://enter;
glutFullScreen();
break;
case '\x1b'://esc;
glutReshapeWindow(640, 480);
break;
default:
break;
}
}
int main() {
TEApplication* pApp = new TEApplication();
Lesson10Win* pWin = new Lesson10Win();
pApp->run();
delete pApp;
delete pWin;
return 0;
}