wave-glut/lib/glut-demo/test/bsp.cpp

Go to the documentation of this file.
00001 /*
00002  * bsp.cpp
00003  *
00004  * Copyright (C) 2010  Thomas A. Vaughan
00005  * All rights reserved.
00006  *
00007  * Program to test the glut-demo and quake/bsp libraries.
00008  */
00009 
00010 // includes --------------------------------------------------------------------
00011 #include <iostream>
00012 #include <fstream>
00013 
00014 #include "glut-demo/glut-demo.h"
00015 #include "nstream/nstream.h"
00016 #include "perf/perf.h"
00017 #include "quake/bsp/bsp.h"
00018 #include "util/file.h"
00019 
00020 
00021 
00022 struct face_t {
00023         int             type;   // 1 == polygon, 2 == mesh
00024         int             vertex; // always vertex
00025         int             start;  // start index (vertex, meshvert)
00026         int             N;      // number of points (polygon, mesh)
00027 };
00028 
00029 
00030 struct vertex_t {
00031         point3d_t       pos;    // position
00032         glut_color_t    color;  // color
00033 };
00034 
00035 
00036 ////////////////////////////////////////////////////////////////////////////////
00037 //
00038 //      static helper methods
00039 //
00040 ////////////////////////////////////////////////////////////////////////////////
00041 
00042 class Drawer : public glut::DemoHost {
00043 public:
00044         Drawer(IN const char * file) {
00045                         m_vertices = NULL;
00046                         ASSERT(file, "null");
00047                         m_file = file;
00048                 }
00049         ~Drawer(void) throw() { 
00050                         if (m_vertices) {
00051                                 delete[] m_vertices;
00052                         }
00053                 }
00054 
00055         // glut::Host class interface methods ----------------------------------
00056         float getDelta(void) { return 25; }
00057 
00058         void onInit(void) {
00059                         perf::Timer timer("bsp load and parse");
00060 
00061                         // get named stream manager
00062                         const char * filename = m_file.c_str();
00063                         std::string dir;
00064                         GetParentDirectory(filename, dir);
00065                         smart_ptr<nstream::Manager> mgr =
00066                             nstream::getFilesystemManager(dir.c_str());
00067                         ASSERT(mgr, "failed to create filesystem manager");
00068 
00069                         // get named stream
00070                         smart_ptr<nstream::Stream> stream =
00071                             nstream::openNamedStream(mgr, GetFilename(filename));
00072                         ASSERT(stream, "failed to open stream");
00073 
00074                         // load bsp!
00075                         smart_ptr<quake::Bsp> bsp = quake::Bsp::load(stream);
00076                         ASSERT(bsp, "failed to load bsp");
00077                         m_nVertices = bsp->getLumpObjectCount(quake::eLump_Vertices);
00078                         DPRINTF("BSP contains %d vertices", m_nVertices);
00079                         m_vertices = new vertex_t[m_nVertices];
00080                         ASSERT(m_vertices, "out of memory");
00081 
00082                         // load vertices
00083                         bsp->startLumpIteration(quake::eLump_Vertices);
00084                         for (int i = 0; i < m_nVertices; ++i) {
00085                                 const quake::lump_object_t * obj =
00086                                     bsp->getNextLumpObject();
00087                                 ASSERT(obj, "null vertex");
00088                                 ASSERT(obj->index == i, "bad index: %d", obj->index);
00089                                 ASSERT(quake::eLump_Vertices == obj->getType(),
00090                                     "wrong object type");
00091 
00092                                 const quake::vertex_t * vtx =
00093                                     dynamic_cast<const quake::vertex_t *>(obj);
00094                                 ASSERT(vtx, "failed to upcast?");
00095 
00096                                 vertex_t * v = m_vertices + i;
00097                                 v->pos = vtx->position;
00098                                 v->color.red = vtx->color.red;
00099                                 v->color.green = vtx->color.green;
00100                                 v->color.blue = vtx->color.blue;
00101                                 v->color.alpha = vtx->color.alpha;
00102                         }
00103 
00104                         // load meshvertices
00105                         m_nMeshverts = bsp->getLumpObjectCount(quake::eLump_Meshverts);
00106                         DPRINTF("BSP contains %d meshverts", m_nMeshverts);
00107                         m_meshverts = new int[m_nMeshverts];
00108                         ASSERT(m_meshverts, "out of memory");
00109 
00110                         bsp->startLumpIteration(quake::eLump_Meshverts);
00111                         for (int i = 0; i < m_nMeshverts; ++i) {
00112                                 const quake::lump_object_t * obj =
00113                                     bsp->getNextLumpObject();
00114                                 ASSERT(obj, "null vertex");
00115                                 ASSERT(obj->index == i, "bad index: %d", obj->index);
00116                                 ASSERT(quake::eLump_Meshverts == obj->getType(),
00117                                     "wrong object type");
00118 
00119                                 const quake::meshvert_t * vtx =
00120                                     dynamic_cast<const quake::meshvert_t *>(obj);
00121                                 ASSERT(vtx, "failed to upcast?");
00122 
00123                                 m_meshverts[i] = vtx->vertex;
00124                         }
00125 
00126                         // load faces
00127                         m_nFaces = bsp->getLumpObjectCount(quake::eLump_Faces);
00128                         DPRINTF("BSP contains %d faces", m_nFaces);
00129                         m_faces = new face_t[m_nFaces];
00130                         ASSERT(m_faces, "out of memory");
00131 
00132                         face_t * pFace = m_faces;
00133                         bsp->startLumpIteration(quake::eLump_Faces);
00134                         for (int i = 0; i < m_nFaces; ++i, ++pFace) {
00135                                 const quake::lump_object_t * obj =
00136                                     bsp->getNextLumpObject();
00137                                 ASSERT(obj, "null vertex");
00138                                 ASSERT(obj->index == i, "bad index: %d", obj->index);
00139                                 ASSERT(quake::eLump_Faces == obj->getType(),
00140                                     "wrong object type");
00141 
00142                                 const quake::face_t * face =
00143                                     dynamic_cast<const quake::face_t *>(obj);
00144                                 ASSERT(face, "failed to upcast");
00145 
00146 //                              if (1 == face->type) {
00147                                         // standard polygon face
00148 //                                      pFace->type = 1;
00149 //                                      pFace->vertex = face->vertex;
00150 //                                      pFace->start = face->vertex;
00151 //                                      pFace->N = face->nVertices;
00152 //                              } else if (3 == face->type) {
00153                                 if (1 == face->type || 3 == face->type) {
00154                                         // triangle mesh
00155                                         pFace->type = 2;
00156                                         pFace->vertex = face->vertex;
00157                                         pFace->start = face->meshvert;
00158                                         pFace->N = face->nMeshverts;
00159                                         ASSERT_THROW(0 == (pFace->N % 3),
00160                                             "Mesh should have exact number of triangles");
00161                                 } else {
00162                                         pFace->type = 0;
00163                                         pFace->start = 0;
00164                                         pFace->N = 0;
00165                                 }
00166                         }
00167                 }
00168 
00169         void display3D(IN const glut::render_context_t& rc,
00170                                 IN glut::RenderQueue * rq) {
00171                         ASSERT(rq, "null");
00172                         // display all faces
00173                         const face_t * p = m_faces;
00174                         for (int i = 0; i < m_nFaces; ++i, ++p) {
00175                                 int N = p->N;
00176                                 if (19 == p->type) {
00177                                         // polygon face!
00178                                         const vertex_t * v = m_vertices + p->start;
00179                                         glBegin(GL_POLYGON);
00180                                         for (int j = 0; j < N; ++j, ++v) {
00181                                                 glColor4bv((const GLbyte *) &v->color.red);
00182                                                 glVertex3fv((const GLfloat *) &v->pos.x);
00183                                         }
00184                                         glEnd();
00185                                 } else if (3 & p->type) {
00186                                         // triangle mesh face
00187                                         int idx = p->vertex;
00188                                         glBegin(GL_TRIANGLES);
00189                                         for (int j = 0; j < N; ++j) {
00190                                                 int q = idx + m_meshverts[p->start + j];
00191                                                 const vertex_t * v = m_vertices + q;
00192                                                 glColor4bv((const GLbyte *) &v->color.red);
00193                                                 glVertex3fv((const GLfloat *) &v->pos.x);
00194                                         }
00195                                         glEnd();
00196                                 }
00197                         }
00198                 }
00199 
00200 private:
00201         std::string                     m_file;
00202         int                             m_nVertices;
00203         int                             m_nFaces;
00204         int                             m_nMeshverts;
00205         vertex_t *                      m_vertices;
00206         face_t *                        m_faces;
00207         int *                           m_meshverts;
00208 };
00209 
00210 
00211 
00212 ////////////////////////////////////////////////////////////////////////////////
00213 //
00214 //      entry point
00215 //
00216 ////////////////////////////////////////////////////////////////////////////////
00217 
00218 int
00219 main
00220 (
00221 IN int argc,
00222 IN const char * argv[]
00223 )
00224 {
00225         ASSERT(2 == argc, "Usage: glut-demo-bsp <bsp-path>");
00226         const char * filename = argv[1];
00227 
00228         try {
00229                 // title
00230                 std::string title = "BSP map viewer: ";
00231                 title += filename;
00232 
00233                 // main loop
00234                 smart_ptr<glut::DemoHost> host = new Drawer(filename);
00235                 ASSERT(host, "out of memory");
00236                 glut::startDemo(argc, argv, title.c_str(), host);
00237 
00238         } catch (std::exception& e) {
00239                 DPRINTF("Exception: %s", e.what());
00240         }
00241 
00242         // only reach here on error
00243         return -1;
00244 }
00245