//============================================================================== // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Library General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. //============================================================================== //============================================================================== // File: cMap.cpp // Project: Shooting Star // Author: Jarmo Hekkanen // Copyrights (c) 2003 2ndPoint ry (www.2ndpoint.fi) //------------------------------------------------------------------------------ // Revision history //============================================================================== //============================================================================== // Includes #include "cMap.hpp" #include #include #include #include #include "MapFile.hpp" #include "cTextureManager.hpp" #include "Debug.hpp" //------------------------------------------------------------------------------ // Namespaces using namespace ShootingStar; //============================================================================== //! Constructor cMap::cMap (void): mBelowList (0), mAboveList (0), mNumberOfVertices (0), mNumberOfTriangles (0), mNumberOfQuads (0), mpVertices (NULL), mpTriangles (NULL), mpQuads (NULL) { // Empty }; //! Destructor cMap::~cMap (void) { Free (); }; void cMap::Free (void) { FreeDisplayLists (); FreeMapGeometry (); } void cMap::Load (string filename) { Free (); ifstream fin; try { fin.open (filename.c_str (), ios::binary); if ( !fin ) { dbgError () << "Unable to open file " << filename << " for reading\n"; throw runtime_error ("Unable to open the map file"); } // Read the map file header tMapFile_Header header; fin.read ((char *)&header, sizeof (tMapFile_Header)); if ( !fin ) throw runtime_error ("Unable to read header from file"); // Validate the file char tmp[6]; memcpy (tmp, header.id, 5); tmp[5] = '\0'; if ( strcmp (tmp, "ssMAP") != 0 ) { dbgError () << "File " << filename << " isn't a valid Shooting Star map file\n"; dbgError () << tmp << '\n'; throw runtime_error ("Invalid map file"); } // Check map file version if ( header.version != 1 ) throw runtime_error ("Wrong map file version"); // Create a new map mWidth = header.width; mHeight = header.height; dbgInfo () << "Number of vertices " << header.numVertices << '\n'; dbgInfo () << "Number of triangles " << header.numTriangles << '\n'; dbgInfo () << "Number of quads " << header.numQuads << '\n'; dbgInfo () << "Number of textures " << header.numTextures << '\n'; dbg::assertion (dbg::error, DBG_ASSERTION (header.numVertices != 0)); mpVertices = new tMapVertex[header.numVertices]; if ( header.numTriangles != 0) mpTriangles = new tMapTriangle[header.numTriangles]; if ( header.numQuads != 0) mpQuads = new tMapQuad[header.numQuads]; mNumberOfVertices = header.numVertices; mNumberOfTriangles = header.numTriangles; mNumberOfQuads = header.numQuads; // Read vertex data for ( int i = 0; i < header.numVertices; i++ ) { // Read vertex tMapFile_Vertex vertex; fin.read ((char *)&vertex, sizeof (tMapFile_Vertex)); mpVertices[i].mPosition.mX = vertex.position[0]; mpVertices[i].mPosition.mY = vertex.position[1]; mpVertices[i].mTexCoord[0] = vertex.texCoord[0]; mpVertices[i].mTexCoord[1] = vertex.texCoord[1]; mpVertices[i].mColor[0] = vertex.color[0]; mpVertices[i].mColor[1] = vertex.color[1]; mpVertices[i].mColor[2] = vertex.color[2]; mpVertices[i].mColor[3] = vertex.color[3]; } if ( !fin ) throw runtime_error ("Unable to read vertex data from file"); // Read triangle data for ( int i = 0; i < header.numTriangles; i++ ) { // Read triangle tMapFile_Triangle triangle; fin.read ((char *)&triangle, sizeof (tMapFile_Triangle)); mpTriangles[i].mLayer = triangle.layer; mpTriangles[i].mTextureID = triangle.texture; // TEMP mpTriangles[i].mFlags = triangle.flags; mpTriangles[i].mVertexIndices[0] = triangle.vertexIndices[0]; mpTriangles[i].mVertexIndices[1] = triangle.vertexIndices[1]; mpTriangles[i].mVertexIndices[2] = triangle.vertexIndices[2]; mpTriangles[i].mVertexIndices[3] = triangle.vertexIndices[3]; } if ( !fin ) throw runtime_error ("Unable to read triangle data from file"); // Read quad data for ( int i = 0; i < header.numQuads; i++ ) { // Quad triangle tMapFile_Quad quad; fin.read ((char *)&quad, sizeof (tMapFile_Quad)); mpQuads[i].mLayer = quad.layer; mpQuads[i].mTextureID = quad.texture; // TEMP mpQuads[i].mFlags = quad.flags; mpQuads[i].mVertexIndices[0] = quad.vertexIndices[0]; mpQuads[i].mVertexIndices[1] = quad.vertexIndices[1]; mpQuads[i].mVertexIndices[2] = quad.vertexIndices[2]; mpQuads[i].mVertexIndices[3] = quad.vertexIndices[3]; } if ( !fin ) throw runtime_error ("Unable to read quad data from file"); // Read the texture data cTextureManager &texManager = cTextureManager::GetInstance (); map textureIDs; char buffer[160]; for ( int i = 1; i <= header.numTextures; i++ ) { fin.getline (buffer, 160, '\0'); if ( !fin ) throw runtime_error ("Unable to read texture data from file"); textureIDs[i] = texManager.LoadTexture (buffer); } // Map texture IDs for ( int i = 0; i < mNumberOfTriangles; i++ ) { if ( mpTriangles[i].mTextureID != 0 ) mpTriangles[i].mTextureID = textureIDs[mpTriangles[i].mTextureID]; } for ( int i = 0; i < mNumberOfQuads; i++ ) { if ( mpQuads[i].mTextureID != 0 ) mpQuads[i].mTextureID = textureIDs[mpQuads[i].mTextureID]; } // Close the file fin.close (); } catch ( ... ) { fin.close (); throw; } GenerateWallList (); GenerateDisplayLists (); FreeMapGeometry (); } void cMap::GenerateWallList (void) { mWallList.clear (); // Get blocking triangles for ( Uint16 i = 0; i < mNumberOfTriangles; i++ ) { if ( !(mpTriangles[i].mFlags & FaceFlags_BlocksMovement) && !(mpTriangles[i].mFlags & FaceFlags_BlocksShooting) ) continue; for ( int j = 0; j < 3; j++ ) { tWall wall; wall.flags = mpTriangles[i].mFlags; // Get vertices wall.begin = mpVertices[mpTriangles[i].mVertexIndices[j]].mPosition; if ( j == 2 ) wall.end = mpVertices[mpTriangles[i].mVertexIndices[0]].mPosition; else wall.end = mpVertices[mpTriangles[i].mVertexIndices[j + 1]].mPosition; mWallList.push_back (wall); } } // Get blocking quads for ( Uint16 i = 0; i < mNumberOfQuads; i++ ) { if ( !(mpQuads[i].mFlags & FaceFlags_BlocksMovement) && !(mpQuads[i].mFlags & FaceFlags_BlocksShooting) ) continue; for ( int j = 0; j < 4; j++ ) { tWall wall; wall.flags = mpQuads[i].mFlags; // Get vertices wall.begin = mpVertices[mpQuads[i].mVertexIndices[j]].mPosition; if ( j == 3 ) wall.end = mpVertices[mpQuads[i].mVertexIndices[0]].mPosition; else wall.end = mpVertices[mpQuads[i].mVertexIndices[j + 1]].mPosition; mWallList.push_back (wall); } } } void cMap::GenerateDisplayLists (void) { FreeDisplayLists (); // Generate below list dbgInfo () << "cMap::Generating below list\n"; mBelowList = glGenLists (1); dbg::assertion (DBG_ASSERTION (mBelowList != 0)); glNewList (mBelowList, GL_COMPILE); RenderBelow2 (); glEndList (); // Generate alove list dbgInfo () << "cMap::Generating above list\n"; mAboveList = glGenLists (1); dbg::assertion (DBG_ASSERTION (mAboveList != 0)); glNewList (mAboveList, GL_COMPILE); RenderAbove2 (); glEndList (); GLenum error = glGetError (); while ( error != GL_NO_ERROR ) { dbgError () << "cMap: OpenGL error: " << gluErrorString (error) << '\n'; error = glGetError (); } } /*void cMap::Render (void) { // Temp rendering code (SLOW) glPushMatrix (); glScalef (1.0f, 1.0f, 1.0f / 255.0f); for ( Uint16 i = 0; i < mNumberOfTriangles; i++ ) { if ( mpTriangles[i].mTextureID != 0 ) { glEnable (GL_TEXTURE_2D); glBindTexture (GL_TEXTURE_2D, mpTriangles[i].mTextureID); } else glDisable (GL_TEXTURE_2D); glPushMatrix (); glTranslatef (0.0f, 0.0f, mpTriangles[i].mLayer); glBegin (GL_TRIANGLES); for ( int j = 0; j < 3; j++ ) { glColor4fv (mpVertices[mpTriangles[i].mVertexIndices[j]].mColor); glTexCoord2fv (mpVertices[mpTriangles[i].mVertexIndices[j]].mTexCoord); glVertex2fv ((float *)&mpVertices[mpTriangles[i].mVertexIndices[j]].mPosition); } glEnd (); glPopMatrix (); } // Render quads for ( Uint16 i = 0; i < mNumberOfQuads; i++ ) { if ( mpQuads[i].mTextureID != 0 ) { glEnable (GL_TEXTURE_2D); glBindTexture (GL_TEXTURE_2D, mpQuads[i].mTextureID); } else glDisable (GL_TEXTURE_2D); glPushMatrix (); glTranslatef (0.0f, 0.0f, mpQuads[i].mLayer); glBegin (GL_QUADS); for ( int j = 0; j < 4; j++ ) { glColor4fv (mpVertices[mpQuads[i].mVertexIndices[j]].mColor); glTexCoord2fv (mpVertices[mpQuads[i].mVertexIndices[j]].mTexCoord); glVertex2fv ((float *)&mpVertices[mpQuads[i].mVertexIndices[j]].mPosition); } glEnd (); glPopMatrix (); } glPopMatrix (); }*/ void cMap::FreeDisplayLists (void) { glDeleteLists (mBelowList, 1); glDeleteLists (mAboveList, 1); mBelowList = mAboveList = 0; } void cMap::FreeMapGeometry (void) { if ( mpVertices == NULL ) return; unsigned int size = mNumberOfVertices * sizeof (tMapVertex) + mNumberOfTriangles * sizeof (tMapTriangle) + mNumberOfQuads * sizeof (tMapQuad); dbgInfo () << "Freeing map geometry (" << size << " bytes)\n"; delete [] mpVertices; delete [] mpTriangles; delete [] mpQuads; mpVertices = NULL; mpTriangles = NULL; mpQuads = NULL; mNumberOfVertices = mNumberOfTriangles = mNumberOfQuads = 0; } void cMap::RenderAbove2 (void) { // Temp rendering code (SLOW) glPushMatrix (); glScalef (1.0f, 1.0f, 1.0f / 255.0f); for ( Uint16 i = 0; i < mNumberOfTriangles; i++ ) { if ( mpTriangles[i].mLayer < 128 ) continue; if ( mpTriangles[i].mTextureID != 0 ) { glEnable (GL_TEXTURE_2D); glBindTexture (GL_TEXTURE_2D, mpTriangles[i].mTextureID); } else glDisable (GL_TEXTURE_2D); glPushMatrix (); glTranslatef (0.0f, 0.0f, mpTriangles[i].mLayer); glBegin (GL_TRIANGLES); for ( int j = 0; j < 3; j++ ) { glColor4fv (mpVertices[mpTriangles[i].mVertexIndices[j]].mColor); glTexCoord2fv (mpVertices[mpTriangles[i].mVertexIndices[j]].mTexCoord); glVertex2fv ((float *)&mpVertices[mpTriangles[i].mVertexIndices[j]].mPosition); } glEnd (); glPopMatrix (); } // Render quads for ( Uint16 i = 0; i < mNumberOfQuads; i++ ) { if ( mpQuads[i].mLayer < 128 ) continue; if ( mpQuads[i].mTextureID != 0 ) { glEnable (GL_TEXTURE_2D); glBindTexture (GL_TEXTURE_2D, mpQuads[i].mTextureID); } else glDisable (GL_TEXTURE_2D); glPushMatrix (); glTranslatef (0.0f, 0.0f, mpQuads[i].mLayer); glBegin (GL_QUADS); for ( int j = 0; j < 4; j++ ) { glColor4fv (mpVertices[mpQuads[i].mVertexIndices[j]].mColor); glTexCoord2fv (mpVertices[mpQuads[i].mVertexIndices[j]].mTexCoord); glVertex2fv ((float *)&mpVertices[mpQuads[i].mVertexIndices[j]].mPosition); } glEnd (); glPopMatrix (); } glPopMatrix (); } void cMap::RenderBelow2 (void) { // Temp rendering code (SLOW) glPushMatrix (); glScalef (1.0f, 1.0f, 1.0f / 255.0f); for ( Uint16 i = 0; i < mNumberOfTriangles; i++ ) { if ( mpTriangles[i].mLayer > 128 ) continue; if ( mpTriangles[i].mTextureID != 0 ) { glEnable (GL_TEXTURE_2D); glBindTexture (GL_TEXTURE_2D, mpTriangles[i].mTextureID); } else glDisable (GL_TEXTURE_2D); glPushMatrix (); glTranslatef (0.0f, 0.0f, mpTriangles[i].mLayer); glBegin (GL_TRIANGLES); for ( int j = 0; j < 3; j++ ) { glColor4fv (mpVertices[mpTriangles[i].mVertexIndices[j]].mColor); glTexCoord2fv (mpVertices[mpTriangles[i].mVertexIndices[j]].mTexCoord); glVertex2fv ((float *)&mpVertices[mpTriangles[i].mVertexIndices[j]].mPosition); } glEnd (); glPopMatrix (); } // Render quads for ( Uint16 i = 0; i < mNumberOfQuads; i++ ) { if ( mpQuads[i].mLayer > 128 ) continue; if ( mpQuads[i].mTextureID != 0 ) { glEnable (GL_TEXTURE_2D); glBindTexture (GL_TEXTURE_2D, mpQuads[i].mTextureID); } else glDisable (GL_TEXTURE_2D); glPushMatrix (); glTranslatef (0.0f, 0.0f, mpQuads[i].mLayer); glBegin (GL_QUADS); for ( int j = 0; j < 4; j++ ) { glColor4fv (mpVertices[mpQuads[i].mVertexIndices[j]].mColor); glTexCoord2fv (mpVertices[mpQuads[i].mVertexIndices[j]].mTexCoord); glVertex2fv ((float *)&mpVertices[mpQuads[i].mVertexIndices[j]].mPosition); } glEnd (); glPopMatrix (); } glPopMatrix (); } //============================================================================== // EOF //==============================================================================