由于自己对WIN API不熟悉,所以把Nehe例程改成了“纯”C++实现,当然,windows下编程还是用到了<windows.h>里定义的一些宏、结构体.....
NeHe教程10是用一张.bmp位图实现了一个三维世界,可以键盘控制视角。
(PS.本人用例程里自带的图片会出问题, 于是我把原图片打开用截图工具重新截取就没问题,猜想是原图存储的方式跟读取的方式不一致导致。)
Lesson10Main.cpp;
#include <math.h> #include <stdio.h> #include <cstdlib> #include <vector>
#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; }