glut-model.h

Go to the documentation of this file.
00001 /*
00002  * glut-model.h
00003  *
00004  * Copyright (C) 2008,2009  Thomas A. Vaughan
00005  * All rights reserved.
00006  *
00007  *
00008  * Redistribution and use in source and binary forms, with or without
00009  * modification, are permitted provided that the following conditions are met:
00010  *     * Redistributions of source code must retain the above copyright
00011  *       notice, this list of conditions and the following disclaimer.
00012  *     * Redistributions in binary form must reproduce the above copyright
00013  *       notice, this list of conditions and the following disclaimer in the
00014  *       documentation and/or other materials provided with the distribution.
00015  *     * Neither the name of the <organization> nor the
00016  *       names of its contributors may be used to endorse or promote products
00017  *       derived from this software without specific prior written permission.
00018  *
00019  * THIS SOFTWARE IS PROVIDED BY THOMAS A. VAUGHAN ''AS IS'' AND ANY
00020  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00021  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00022  * DISCLAIMED. IN NO EVENT SHALL THOMAS A. VAUGHAN BE LIABLE FOR ANY
00023  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00024  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00025  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00026  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00027  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00028  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00029  *
00030  * Basic 3D models built on glut
00031  */
00032 
00033 #ifndef WAVE_GLUT_GLUT_MODEL_H__
00034 #define WAVE_GLUT_GLUT_MODEL_H__
00035 
00036 // includes --------------------------------------------------------------------
00037 #include "common/common.h"
00038 
00039 #include "geometry/geometry_3d.h"
00040 #include "threadsafe/smart_ptr.h"
00041 #include "wave-glut/camera.h"
00042 #include "wave-glut/renderable.h"
00043 
00044 
00045 namespace glut {
00046 
00047 
00048 ////////////////////////////////////////////////////////////////////////////////
00049 ///
00050 /// \ingroup models
00051 /// \defgroup glut_model Glut 3D Model Library
00052 ///
00053 /// A homegrown 3D model format.  This is a simple reference implementation of
00054 /// OpenGL-enabled 3D models.
00055 ///
00056 ////////////////////////////////////////////////////////////////////////////////
00057 
00058 /*@{*/
00059 
00060 
00061 ////////////////////////////////////////////////////////////////////////////////
00062 //
00063 //      public API
00064 //
00065 ////////////////////////////////////////////////////////////////////////////////
00066 
00067 /// material (used for rendering polygons)
00068 struct material_t {
00069         // constructor, manipulators
00070         material_t(void) throw() : texture_id(0) { this->clear(); }
00071         ~material_t(void) throw() { this->clear(); }
00072         void clear(void) throw() {
00073                         isTransparent = false;
00074                         if (texture_id) {
00075                                 glDeleteTextures(1, (GLuint *) &texture_id);
00076                                 texture_id = 0;
00077                         }
00078                 }
00079 
00080         // data fields
00081         int             texture_id;     ///< openGL texture if nonzero
00082         bool            isTransparent;  ///< does texture contain non-1 alpha?
00083         glut_color_t    color;          ///< use color if no texture ID
00084 };
00085 
00086 
00087 
00088 /// Clients of the parsing APIs must implement this interface themselves.
00089 /// Typically, this is an object that can load materials as needed, and keep
00090 /// them in a map.  Needs to be threadsafe!
00091 class MaterialRegistry {
00092 public:
00093         // virtual destructor --------------------------------------------------
00094         virtual ~MaterialRegistry(void) throw();
00095 
00096         // glut::MaterialRegistry class interface methods ----------------------
00097         virtual smart_ptr<material_t> getMaterial(IN const char * id) = 0;
00098 };
00099 
00100 
00101 
00102 /// polygon object.  There is a single normal for the entire polygon,
00103 /// and an arbitrary number of points (vertices)
00104 struct polygon_t {
00105         // constructor, manipulators
00106         polygon_t(void) throw() {
00107                                 nVertices = 0;
00108                                 indices = NULL;
00109                                 u = v = NULL;
00110                         }
00111         ~polygon_t(void) throw() { this->clear(); }
00112         void clear(void) throw() {
00113                         nVertices = 0;
00114                         if (indices) {
00115                                 delete[] indices;
00116                                 indices = NULL;
00117                         }
00118                         if (u) {
00119                                 delete[] u;
00120                                 u = NULL;
00121                         }
00122                         if (v) {
00123                                 delete[] v;
00124                                 v = NULL;
00125                         }
00126                         material = NULL;
00127                 }
00128 
00129         // data fields
00130         int             nVertices;      ///< number of vertices in the polygon
00131         int *           indices;        ///< array of vertex indices
00132         float *         u;              ///< array of vertex texture u-coords
00133         float *         v;              ///< array of vertex texture v-coords
00134         smart_ptr<material_t> material; ///< material (texture etc)
00135         point3d_t       normal;         ///< polygon normal
00136 };
00137 
00138 
00139 
00140 /// model object.  This contains all of the vertices in a single flat
00141 /// list, and then a list of polygons that use the vertices.
00142 class model_t : public Renderable {
00143 public:
00144         // constructor, manipulators
00145         model_t(void) throw() : nVertices(0), vertices(NULL),
00146                                 nPolygons(0), polygons(NULL) { }
00147         ~model_t(void) throw() { this->clear(); }
00148         void clear(void) throw() {
00149                         nVertices = nPolygons = 0;
00150                         if (vertices) {
00151                                 delete[] vertices;
00152                                 vertices = NULL;
00153                         }
00154                         if (polygons) {
00155                                 delete[] polygons;
00156                                 polygons = NULL;
00157                         }
00158                         boundingBox.clear();
00159                 }
00160 
00161         // glut::Renderable class interface methods ----------------------------
00162         void render(IN const render_context_t& rc,
00163                                 IN RenderQueue * rq);
00164         rect3d_t getBoundingBox(void) const throw() { return boundingBox; }
00165 
00166         // data fields
00167         int             nVertices;      ///< number of vertices in model
00168         point3d_t *     vertices;       ///< array of vertices
00169         int             nPolygons;      ///< number of polygons in model
00170         polygon_t *     polygons;       ///< array of polygons
00171         rect3d_t        boundingBox;    ///< bounding box
00172 };
00173 
00174 
00175 
00176 /// level-of-detail entry.  contains a model and distance information
00177 struct lod_entry_t {
00178         void clear(void) throw() {
00179                         distance = 0.0;
00180                         model.clear();
00181                 }
00182 
00183         // data fields
00184         model_t         model;          ///< model to use for this entry
00185         float           distance;       ///< distance at which to use model
00186 };
00187 
00188 
00189 
00190 /// level-of-detail model.  Contains multiple level-of-detail entries (models)
00191 struct lod_model_t : public Renderable {
00192 public:
00193         // constructor, manipulators
00194         lod_model_t(void) throw() : nEntries(0), entries(NULL) { }
00195         ~lod_model_t(void) throw() { this->clear(); }
00196         void clear(void) throw() {
00197                         nEntries = 0;
00198                         if (entries) {
00199                                 delete[] entries;
00200                                 entries = NULL;
00201                         }
00202                         boundingBox.clear();
00203                 }
00204 
00205         // glut::Renderable class interface methods ----------------------------
00206         void render(IN const render_context_t& rc,
00207                                 IN RenderQueue * rq);
00208         rect3d_t getBoundingBox(void) const throw() { return boundingBox; }
00209 
00210         // data fields
00211         int             nEntries;       ///< number of level-of-detail entries
00212         lod_entry_t *   entries;        ///< array of level-of-detail entries
00213         rect3d_t        boundingBox;    ///< bounding box
00214 };
00215 
00216 
00217 
00218 ////////////////////////////////////////////////////////////////////////////////
00219 //
00220 //      parsing (loading) methods
00221 //
00222 ////////////////////////////////////////////////////////////////////////////////
00223 
00224 void parseColor(IO std::istream& stream,
00225                                 OUT img_color_t& color);
00226 
00227 void parseMaterial(IO std::istream& stream,
00228                                 IN const char * parentDir,
00229                                 OUT material_t& material);
00230 
00231 void parsePolygon(IN MaterialRegistry * mreg,
00232                                 IO std::istream& stream,
00233                                 OUT polygon_t& polygon);
00234 
00235 void parseModel(IN MaterialRegistry * mreg,
00236                                 IO std::istream& stream,
00237                                 OUT model_t& model);
00238 
00239 void parseLodEntry(IN MaterialRegistry * mreg,
00240                                 IO std::istream& stream,
00241                                 OUT lod_entry_t& entry);
00242 
00243 void parseLodModel(IN MaterialRegistry * mreg,
00244                                 IO std::istream& stream,
00245                                 OUT lod_model_t& lod_model);
00246 
00247 
00248 /// get a simple implementation of a material registry.  Intended for testing
00249 /// only.  Caller must provide root of material directory tree.
00250 smart_ptr<MaterialRegistry> getSimpleRegistry(IN const char * materialDir);
00251 
00252 
00253 /// load a model from a Wavepacket Glut Model file (.wgm extension, normally)
00254 smart_ptr<Renderable> loadModel(IN const char * filename,
00255                                 IN MaterialRegistry * reg);
00256 
00257 
00258 ////////////////////////////////////////////////////////////////////////////////
00259 //
00260 //      writing methods
00261 //
00262 ////////////////////////////////////////////////////////////////////////////////
00263 
00264 /// assumes you have already written the key name, this will write
00265 ///   the opening and closing brackets
00266 void writeModelToStream(IO std::ostream& stream,
00267                                 IN const model_t& model);
00268 
00269 
00270 
00271 };      // glut namespace
00272 
00273 
00274 #endif  // WAVE_GLUT_GLUT_MODEL_H__
00275