Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
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;
00024 int vertex;
00025 int start;
00026 int N;
00027 };
00028
00029
00030 struct vertex_t {
00031 point3d_t pos;
00032 glut_color_t color;
00033 };
00034
00035
00036
00037
00038
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
00056 float getDelta(void) { return 25; }
00057
00058 void onInit(void) {
00059 perf::Timer timer("bsp load and parse");
00060
00061
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
00070 smart_ptr<nstream::Stream> stream =
00071 nstream::openNamedStream(mgr, GetFilename(filename));
00072 ASSERT(stream, "failed to open stream");
00073
00074
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
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
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
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
00147
00148
00149
00150
00151
00152
00153 if (1 == face->type || 3 == face->type) {
00154
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
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
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
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
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
00230 std::string title = "BSP map viewer: ";
00231 title += filename;
00232
00233
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
00243 return -1;
00244 }
00245