rendered paste body// http://nehe.gamedev.net/data/lessons/lesson.asp?lesson=45#include <GL/glew.h>#include "SDL.h"#include "sdl-timer.hpp"#define SCREEN_WIDTH 1024#define SCREEN_HEIGHT 768#define SCREEN_BPP 32#define FRAMES_PER_SECOND 60#define MESH_RESOLUTION 4.0f#define MESH_HEIGHTSCALE 1.0f//#define GL_ARRAY_BUFFER_ARB 0x8892//#define GL_STATIC_DRAW_ARB 0x88E4class CVert{public: float x; float y; float z;};typedef CVert CVec;class CTexCoord{public: float u; float v;};class CMesh{public: int m_nVertexCount; CVert * m_pVertices; CTexCoord* m_pTexCoords; GLuint m_nTextureId; GLuint m_nVBOVertices; GLuint m_nVBOTexCoords; SDL_Surface* m_pTextureImage;public: CMesh(); ~CMesh(); bool LoadHeightmap(char* czPath, float flHeightScale, float flResolution); float PtHeight(int nX, int nY); void BuildVBOs();};bool g_fVGOSupported = true;CMesh* g_pMesh = NULL;bool g_fVBOSupported = false;float g_flYRot = 0.0f;bool CMesh :: LoadHeightmap(char* szPath, float flHeightScale, float flResolution){ SDL_Surface *surface; Uint32 rmask, gmask, bmask, amask;#if SDL_BYTEORDER == SDL_BIG_ENDIAN //Check Endianess and set rgba masks accordingly rmask = 0xff000000; gmask = 0x00ff0000; bmask = 0x0000ff00; amask = 0x00000000;#else rmask = 0x000000ff; gmask = 0x0000ff00; bmask = 0x00ff0000; amask = 0x00000000;#endif m_pTextureImage = SDL_LoadBMP(szPath); surface = SDL_CreateRGBSurface(SDL_SWSURFACE, m_pTextureImage->w, m_pTextureImage->h, 24, rmask, gmask, bmask, amask); m_pTextureImage = SDL_ConvertSurface(m_pTextureImage, surface->format, SDL_SWSURFACE); // generate vertex field m_nVertexCount = (int) (m_pTextureImage->w * m_pTextureImage->h * 6/(flResolution * flResolution)); printf("vertex count=%d\n",m_nVertexCount); printf("image width=%d, height=%d\n", m_pTextureImage->w, m_pTextureImage->h); m_pVertices = new CVec[m_nVertexCount]; m_pTexCoords = new CTexCoord[m_nVertexCount]; int nX, nZ, nTri, nIndex = 0; float flX, flZ; for (nZ = 0; nZ < m_pTextureImage->h; nZ +=(int) flResolution) { for (nX = 0; nX < m_pTextureImage->w; nX +=(int) flResolution) { for (nTri = 0; nTri < 6; nTri++) { flX=(float) nX + ((nTri == 1 || nTri == 2 || nTri == 5) ? flResolution : 0.0f); flZ=(float) nZ + ((nTri == 2 || nTri == 4 || nTri == 5) ? flResolution : 0.0f); m_pVertices[nIndex].x = flX - (m_pTextureImage->w/2); m_pVertices[nIndex].y = PtHeight((int) flX, (int) flZ)*flHeightScale; m_pVertices[nIndex].z = flZ - (m_pTextureImage->h/2); m_pTexCoords[nIndex].u = flX/m_pTextureImage->w; m_pTexCoords[nIndex].v = flZ/m_pTextureImage->h;#if 0 printf("%d (%f,%f,%f) [%f %f]\n", nIndex, m_pVertices[nIndex].x, m_pVertices[nIndex].y, m_pVertices[nIndex].z, m_pTexCoords[nIndex].u, m_pTexCoords[nIndex].v);#endif nIndex++; } } } glGenTextures(1, &m_nTextureId); glBindTexture(GL_TEXTURE_2D, m_nTextureId); glTexImage2D(GL_TEXTURE_2D, 0, 3, m_pTextureImage->w, m_pTextureImage->h, 0, GL_RGB, GL_UNSIGNED_BYTE, m_pTextureImage->pixels); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); if(m_pTextureImage) { SDL_FreeSurface(m_pTextureImage); } if(surface) { SDL_FreeSurface(surface); } return true;}CMesh :: CMesh(){ // Set Pointers To NULL m_pTextureImage = NULL; m_pVertices = NULL; m_pTexCoords = NULL; m_nVertexCount = 0; m_nVBOVertices = m_nVBOTexCoords = m_nTextureId = 0;}CMesh :: ~CMesh(){ // Delete VBOs if( g_fVBOSupported ) { GLuint nBuffers[2] = { m_nVBOVertices, m_nVBOTexCoords }; glDeleteBuffers( 2, nBuffers ); // Free The Memory } // Delete Data if( m_pVertices ) // Deallocate Vertex Data delete [] m_pVertices; m_pVertices = NULL; if( m_pTexCoords ) // Deallocate Texture Coord Data delete [] m_pTexCoords; m_pTexCoords = NULL; if(m_nVBOTexCoords) // Deallocate Vertex Buffer glDeleteBuffers( 1, &m_nVBOTexCoords); if(m_nVBOVertices) glDeleteBuffers( 1, &m_nVBOVertices);}float CMesh :: PtHeight (int nX, int nY){ SDL_Color color; Uint32 col=0; char* offset = (char*) m_pTextureImage->pixels; offset += (m_pTextureImage->pitch * nY); offset += (m_pTextureImage->format->BytesPerPixel * nX); memcpy(&col, offset, m_pTextureImage->format->BytesPerPixel); SDL_GetRGB(col, m_pTextureImage->format, &color.r, &color.g, &color.b); return (0.299f * color.r + 0.587f * color.g + 0.114f * color.b);}void CMesh::BuildVBOs(){ printf("building VBOs\n"); glGenBuffers(1, &m_nVBOVertices); glBindBuffer(GL_ARRAY_BUFFER, m_nVBOVertices); glBufferData(GL_ARRAY_BUFFER, m_nVertexCount * 3 * sizeof(float), m_pVertices, GL_STATIC_DRAW); glGenBuffers(1, &m_nVBOTexCoords); glBindBuffer(GL_ARRAY_BUFFER, m_nVBOTexCoords); glBufferData(GL_ARRAY_BUFFER, m_nVertexCount * 2 * sizeof(float), m_pTexCoords, GL_STATIC_DRAW); delete [] m_pVertices; m_pVertices = NULL; delete [] m_pTexCoords; m_pTexCoords = NULL;}// straight from tutorial#if 0bool IsExtensionSupported( char* szTargetExtension ){ const unsigned char *pszExtensions = NULL; const unsigned char *pszStart; unsigned char *pszWhere, *pszTerminator; // Extension names should not have spaces pszWhere = (unsigned char *) strchr( szTargetExtension, ' ' ); if( pszWhere || *szTargetExtension == '\0' ) return false; // Get Extensions String pszExtensions = glGetString( GL_EXTENSIONS ); // Search The Extensions String For An Exact Copy pszStart = pszExtensions; for(;;) { pszWhere = (unsigned char *) strstr( (const char *) pszStart, szTargetExtension ); if( !pszWhere ) break; pszTerminator = pszWhere + strlen( szTargetExtension ); if( pszWhere == pszStart || *( pszWhere - 1 ) == ' ' ) if( *pszTerminator == ' ' || *pszTerminator == '\0' ) return true; pszStart = pszTerminator; } return false;}#endifbool Initialize (void){ g_pMesh = new CMesh(); printf("loading data/terrain.bmp\n"); if(!g_pMesh->LoadHeightmap("data/terrain.bmp", MESH_HEIGHTSCALE, MESH_RESOLUTION)) { fprintf(stderr, "failed to load data/terrain.bmp\n"); return false; }#if 0 printf("checking for VBO support..."); g_fVBOSupported = glewIsExtensionSupported("GL_vertex_buffer_object"); if(g_fVBOSupported) { printf("supported!\n"); g_pMesh->BuildVBOs(); }else{ printf("NOT supported :(\n"); }#endif printf("about to build VBOs\n"); g_pMesh->BuildVBOs(); printf("done building VBOs\n"); return true;}bool init_GL();SDL_Event event;GLuint texture[1];class Square{private: int x, y, width, height; int xVel, yVel;public: Square(); void handle_input(); void move();};Square::Square(){ x = 5; y = 5; width = 256; height = 256; xVel = 0; yVel = 0;}void Square::move(){ x += xVel; if ((x < 0) || (x + width > SCREEN_WIDTH)) { x -= xVel; } y += yVel; if ((y < 0) || (y + width > SCREEN_HEIGHT)) { y -= yVel; }}void Square::handle_input(){ if (event.type == SDL_KEYDOWN) { switch (event.key.keysym.sym) { case SDLK_UP: yVel -= height / 2; break; case SDLK_DOWN: yVel += height / 2; break; case SDLK_LEFT: xVel -= width / 2; break; case SDLK_RIGHT: xVel += width / 2; break; default: break; } } else { switch (event.key.keysym.sym) { case SDLK_UP: yVel += height / 2; break; case SDLK_DOWN: yVel -= height / 2; break; case SDLK_LEFT: xVel += width / 2; break; case SDLK_RIGHT: xVel -= width / 2; break; default: break; } }}bool init(){ if (SDL_Init(SDL_INIT_EVERYTHING) < 0) { return false; } if (SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SDL_OPENGL) == NULL) { return false; } if (init_GL() == false) { return false; } if (Initialize() == false) { return false; } SDL_WM_SetCaption("OpenGL Test", NULL); return true;}bool init_GL(){ glEnable(GL_TEXTURE_2D); glShadeModel(GL_SMOOTH); glClearDepth(1.0f); glDepthFunc(GL_LEQUAL); glEnable(GL_DEPTH_TEST); glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); glClearColor(0.0f, 0.5f, 1.0f, 0.5f); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); if (glGetError() != GL_NO_ERROR) { return false; } return true;}void clean_up(){ SDL_Quit();}void draw(void){ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); glTranslatef(0.0f, -220.0f, 0.0f); glRotatef(10.0f, 1.0f, 0.0f, 0.0f); glEnableClientState( GL_VERTEX_ARRAY ); glEnableClientState( GL_TEXTURE_COORD_ARRAY ); if(g_fVBOSupported) { glBindBuffer(GL_ARRAY_BUFFER, g_pMesh->m_nVBOVertices); glVertexPointer(3, GL_FLOAT, 0, (char *) NULL); glBindBuffer(GL_ARRAY_BUFFER, g_pMesh->m_nVBOTexCoords); glTexCoordPointer(2, GL_FLOAT, 0, (char *) NULL); }else { glVertexPointer(3, GL_FLOAT, 0, g_pMesh->m_pVertices); glTexCoordPointer(2, GL_FLOAT, 0, g_pMesh->m_pTexCoords); } glDrawArrays(GL_TRIANGLES, 0, g_pMesh->m_nVertexCount); glDisableClientState( GL_VERTEX_ARRAY ); glDisableClientState( GL_TEXTURE_COORD_ARRAY ); SDL_GL_SwapBuffers();}int main(int argc, char* args[]){ Square square; Timer fps; // make sure the program waits for a quit bool quit = false; if (init() == false) { fprintf(stderr, "init failed\n"); return 1; } while (quit == false) { fps.start(); while (SDL_PollEvent(&event)) { // square.handle_input(); if (event.type == SDL_QUIT) { quit = true; } } draw(); if (fps.get_ticks() < 1000 / FRAMES_PER_SECOND) { SDL_Delay((1000/FRAMES_PER_SECOND) - fps.get_ticks()); } } clean_up(); return 0;}