00001 /********************************************************************* 00002 * lescegra * 00003 * * 00004 * http://geeky.kicks-ass.org/projects/lescegra.html * 00005 * * 00006 * Copyright 2003 by Enno Cramer <uebergeek@web.de> * 00007 * * 00008 * This library is free software; you can redistribute it and/or * 00009 * modify it under the terms of the GNU Library General Public * 00010 * License as published by the Free Software Foundation; either * 00011 * version 2 of the License, or (at your option) any later version. * 00012 * * 00013 * This library is distributed in the hope that it will be useful, * 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * 00016 * Library General Public License for more details. * 00017 * * 00018 * You should have received a copy of the GNU Library General Public * 00019 * License along with this library; if not, write to the Free * 00020 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * 00021 *********************************************************************/ 00022 00023 #ifndef LESCEGRA_H 00024 #define LESCEGRA_H 1 00025 00026 /** 00027 * \file lescegra.h 00028 * \brief lescegra - an OpenGL scene graph (3d graphics engine) 00029 */ 00030 00031 /** 00032 * \mainpage lescegra - a 3D graphics engine 00033 * \version 1.0 (beta) 00034 * \author Enno Cramer <uebergeek@web.de> 00035 * \date 2003 00036 * 00037 * \section main_about About 00038 * Lescegra is an object oriented 3D graphics engine based on the OpenGL API. 00039 * It is written in strict ANSI C and brings no dependencies beyond an OpenGL 00040 * implementation. 00041 * 00042 * \section main_docs Documentation 00043 * - \ref usage 00044 * - \ref extending 00045 * - \ref style 00046 */ 00047 00048 /** 00049 * \page usage Usage 00050 * 00051 * \section usage_basic Basic 00052 * Using lescegra in your application involves the following steps: 00053 * -# initialize the display mode 00054 * -# set up the scene graph 00055 * -# run the update-display loop 00056 * -# update the scene graph 00057 * -# display the scene 00058 * 00059 * \note When using callback driven toolkits like GLUT the update-display loop 00060 * is replaced by a timeout handler repeatedly updating the scene graph and 00061 * triggering the redisplay of the scene. 00062 * 00063 * \section usage_initvideo Initialize the Display Mode 00064 * Before you can start using lescegra, you have to set up the OpenGL display 00065 * mode. This mostly means creating a window for your application and enabling 00066 * some OpenGL features you want to use. 00067 * 00068 * Example: 00069 * \code 00070 * void init_display(void) { 00071 * glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); 00072 * glutCreateWindow("lescegra sample"); 00073 * 00074 * glClearColor(0.0, 0.0, 0.0, 0.0); 00075 * 00076 * glEnable(GL_DEPTH_TEST); 00077 * glEnable(GL_LIGHTING); 00078 * glEnable(GL_TEXTURE_2D); 00079 * glEnable(GL_CULL_FACE); 00080 * 00081 * glCullFace(GL_BACK); 00082 * } 00083 * \endcode 00084 * 00085 * \section usage_setupscene Setting up the Scene 00086 * The first thing to do, after initializing the display mode, is to create 00087 * your scene representation. This mostly involves creating a suitable camera 00088 * and all the objects that will be visible. 00089 * 00090 * Example: 00091 * \code 00092 * static LsgCamera* camera; 00093 * static LsgNode* scene; 00094 * 00095 * void init_scene(void) { 00096 * LsgPerspectiveCam* pcam; 00097 * LsgCoords* coords; 00098 * 00099 * pcam = LsgPerspectiveCam_create(); 00100 * vertex_assign(pcam->location, 3.0, 4.0, 2.0); 00101 * vertex_assign(pcam->lookat, 0.0, 0.0, 0.0); 00102 * vertex_assign(pcam->up, 0.0, 1.0, 0.0); 00103 * pcam->fovy = 45.0; 00104 * pcam->aspect = 1.0; 00105 * pcam->dmin = 0.1; 00106 * pcam->dmax = 10.0; 00107 * 00108 * coords = LsgCoords_create(1.0); 00109 * 00110 * camera = (LsgCamera*)pcam; 00111 * scene = (LsgNode*)coords; 00112 * } 00113 * \endcode 00114 * 00115 * \section usage_display Display the Scene 00116 * To display your scene you have to do the following steps: 00117 * -# clear the screen 00118 * -# initialize the modelview and projection matrix 00119 * -# create the correct view frustum 00120 * -# render the scene with a camera 00121 * -# flush the OpenGL pipeline 00122 * -# swap the display buffers 00123 * 00124 * \note Steps 2 and 3 can mostly be moved into the program initialization phase 00125 * as the display process should restore the transformation matrizes and the 00126 * view frustum. 00127 * 00128 * Example: 00129 * \code 00130 * void display(void) { 00131 * LsgFrustum viewfrustum; 00132 * 00133 * LsgFrustum_init(&viewfrustum, matrix_identity, matrix_identity); 00134 * 00135 * glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 00136 * 00137 * glMatrixMode(GL_PROJECTION); 00138 * glLoadIdentity(); 00139 * glMatrixMode(GL_MODELVIEW); 00140 * glLoadIdentity(); 00141 * 00142 * camera->display(camera, &viewfrustum, scene); 00143 * 00144 * glFlush(); 00145 * glutSwapBuffers(); 00146 * } 00147 * \endcode 00148 * 00149 * \section usage_animation Animation 00150 * To get a time based animation, you have to repeatedly update your scene 00151 * representation: 00152 * -# update the scene graph (using an increasing time) 00153 * -# mark all nodes as updated 00154 * -# trigger redisplay 00155 * 00156 * \note You should call the \c clean method \b after calling \c update to allow 00157 * external changes, for example from keyboard handler functions, to propagate 00158 * up the scene graph. 00159 * 00160 * Example: 00161 * \code 00162 * void animate(int ignore) { 00163 * float now; 00164 * 00165 * now = (float)glutGet(GLUT_ELAPSED_TIME) / 1000.0; 00166 * 00167 * scene->update(scene, now); 00168 * scene->clean(scene); 00169 * 00170 * glutPostRedisplay(); 00171 * } 00172 * \endcode 00173 */ 00174 00175 /** 00176 * \page style Coding Style 00177 * 00178 * \section style_indention Sourcecode Indention 00179 * - Use space for indention (no tabs) 00180 * - Block indention is 4 spaces 00181 * - No space after parenthesis 00182 * - No space after function names 00183 * - No line break before braces 00184 * 00185 * Example: 00186 * \code 00187 * void foo(float x, float y) { 00188 * if (x > y) { 00189 * bar(x); 00190 * } else { 00191 * bar(y); 00192 * } 00193 * } 00194 * \endcode 00195 * 00196 * \section style_naming Naming Conventions 00197 * Classes are named Lsg<real class name>. Class names start with a capital 00198 * letter. If multiple words form a class name, they are combined with every 00199 * word starting with a capital letter. 00200 * 00201 * Class methods are named <Classname>_<method name>. Method names start with a 00202 * lower-case letter. If multiple words form a method name, all except the first 00203 * start with a capital letter. 00204 * 00205 * Examples: 00206 * - Classes 00207 * - LsgObject 00208 * - LsgNode 00209 * - LsgHTerrain 00210 * - LsgMD2Model 00211 * - Methods 00212 * - LsgObject_destroy 00213 * - LsgNode_display 00214 * - LsgList_hasNext 00215 * 00216 * \section style_classes Classes 00217 * Classes mostly consist of two files, a header and a source file. Extremely 00218 * large classes my use more than one source file. The filenames should not 00219 * contain the \a lsg prefix. 00220 * 00221 * The header file defines the class structure and all non-static function 00222 * prototypes. For any virtual method that is not overriden, a define mapping 00223 * the method to the parent classes implementation, should be included. 00224 * 00225 */ 00226 00227 /** 00228 * \page extending Extending the Scene Graph 00229 * 00230 * \section extending_struct Class Struct 00231 * A class is defined by a \c typedef to an (if possible) anonymous \c struct. 00232 * The first struct member must be the parent class and should be named \c 00233 * super. Following are the classes fields and possibly newly defined virtual 00234 * methods. 00235 * 00236 * Virtual methods are defined as function pointers in the class \c struct. 00237 * 00238 * Example: 00239 * \code 00240 * typedef struct { 00241 * LsgNode super; 00242 * void (*foobar)(float x); 00243 * int visible; 00244 * } LsgSample; 00245 * \endcode 00246 * 00247 * \section extending_constructor The Constructor 00248 * The constructor for a scene graph class is divided into two functions. The 00249 * first is responsible for allocating memory for a new class instance, the 00250 * second for initializing the newly allocated memory. 00251 * 00252 * This division is necessary to allow the initializer being reused in 00253 * descendant classes. Also it allows the creation of abstract classes by 00254 * omitting the memory allocating part of the constructor. 00255 * 00256 * \subsection extending_create The Memory Allocator 00257 * The memory allocator is quite trivial and looks almost the same for every 00258 * class. It does the following three steps: 00259 * -# allocate memory for the new instance 00260 * -# call the initializer passing the new instance and all parameters 00261 * -# return the new instance 00262 * 00263 * \note This method should return \c NULL if an error is encountered while 00264 * initializing the instance. 00265 * 00266 * Example: 00267 * \code 00268 * LsgSample* LsgSample_create(void) { 00269 * LsgSample* self = (LsgSample*)malloc(sizeof(LsgSample)); 00270 * 00271 * LsgSample_init(self); 00272 * 00273 * return self; 00274 * } 00275 * \endcode 00276 * 00277 * \subsection extending_init The Initializer 00278 * The initializer is the part of the constructor that does the actual work. It 00279 * is responsible for correctly initializing the memory and setting the right 00280 * virtual method pointers. The initializer method can roughly be divided into 00281 * three sections: 00282 * -# call the parent classes initializer 00283 * -# set any overridden virtual method 00284 * -# initialize members 00285 * 00286 * Example: 00287 * \code 00288 * void LsgSample_init(LsgSample* self) { 00289 * LsgNode_init(&self->super); 00290 * 00291 * ((LsgObject*)self)->destroy = (void (*)(LsgObject*))LsgSample_destroy; 00292 * ((LsgNode*)self)->display = (void (*)(LsgNode*, LsgFrustum*))LsgSample_display; 00293 * 00294 * self->foobar = LsgSample_foobar; 00295 * self->show = 1; 00296 * } 00297 * \endcode 00298 * 00299 * \section extending_destroy The Destructor 00300 * The virtual destructor method is called by \c LsgObject_free to free any 00301 * allocated resources prior to destroying an object instance. The general 00302 * structure of the destructor method is: 00303 * -# free any allocated resources 00304 * -# call the parent classes destructor 00305 * 00306 * Example: 00307 * \code 00308 * void LsgSample_destroy(LsgSample* self) { 00309 * // free any allocated resources 00310 * 00311 * LsgNode_destroy(&self->super); 00312 * } 00313 * \endcode 00314 * 00315 * \section extending_display The Display Method 00316 * The method of the most interest is probably the virtual display method. It 00317 * is called whenever the scene is rendered to screen (or selection buffer for 00318 * that matter). 00319 * 00320 * The second parameter defines the current view frustum in object coordinates. 00321 * You can use it to speed up rendering if part of the node are outside the 00322 * visible area. 00323 * 00324 * \warning Be careful to always restore the OpenGL state before returning from 00325 * this method. Failing to do so may affect the bahavior (or the look) of any 00326 * node displayed afterwards. 00327 * 00328 * \note You should use \c glPushAttrib and \c glPopAttrib to save and restore 00329 * the OpenGL state rather then \c glGet or \c glIsEnabled. The latter may 00330 * require the rendering pipeline to be flushed in order to determine the 00331 * current state, which can have an impact on the display performance. 00332 * 00333 * Example: 00334 * \code 00335 * void LsgSample_display(LsgSample* self, Frustum* frustum) { 00336 * glPushAttrib(GL_ENABLE_BIT); 00337 * 00338 * glDisable(GL_LIGHTING); 00339 * glDisable(GL_TEXTURE_2D); 00340 * 00341 * glBegin(GL_LINE_STRIP); 00342 * glVertex2f(-1.0, -1.0); 00343 * glVertex2f(-1.0, 1.0); 00344 * glVertex2f( 1.0, 1.0); 00345 * glVertex2f( 1.0, -1.0); 00346 * glVertex2f(-1.0, -1.0); 00347 * glEnd(); 00348 * 00349 * glPopAttrib(); 00350 * 00351 * // not strictly necessary; displays a neat bounding box if node.c has 00352 * // been compiled with -DDEBUG_BBOX 00353 * LsgNode_display(&self->super); 00354 * } 00355 * \endcode 00356 * 00357 * \section extending_update The Update Method 00358 * The update method provides the framework for any time based behavior. 00359 * 00360 * \note Don't forget to set the dirty flag when changing the objects bounding 00361 * box. 00362 * 00363 * Example: 00364 * \code 00365 * void LsgSample_update(LsgSample* self, float now) { 00366 * // hide the object after 60 seconds 00367 * self->visible = now < 60.0; 00368 * 00369 * LsgNode_update(&self->super); 00370 * } 00371 * \endcode 00372 * 00373 * \section extending_clean The Clean Method 00374 * The clean method is responsible for resetting the dirty flag. It does not 00375 * need to be overridden other than for propagating the method call to sub nodes. 00376 * 00377 * Example (LsgGroup): 00378 * \code 00379 * void LsgGroup_clean(LsgGroup* self) { 00380 * LsgIterator* it; 00381 * 00382 * it = LsgIterator_create(self->children); 00383 * while (LsgIterator_hasNext(it)) { 00384 * LsgNode* child = (LsgNode*)LsgIterator_next(it); 00385 * child->clean(child); 00386 * } 00387 * LsgObject_free((LsgObject*)it); 00388 * 00389 * LsgNode_clean(&self->super); 00390 * } 00391 * \endcode 00392 */ 00393 00394 /** 00395 * \defgroup scene Scene Representation 00396 */ 00397 00398 /** 00399 * \ingroup scene 00400 * \defgroup geometry Geometry 00401 */ 00402 00403 /** 00404 * \ingroup scene 00405 * \defgroup particle Particle Systems 00406 */ 00407 00408 /** 00409 * \defgroup util Utilities 00410 */ 00411 00412 #include <lescegra/util.h> 00413 #include <lescegra/sg.h> 00414 #include <lescegra/particle.h> 00415 00416 #endif