Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

Scene.cpp

Go to the documentation of this file.
00001 
00002 /*
00003     TEDDY - General graphics application library
00004     Copyright (C) 1999-2002  Timo Suoranta
00005     tksuoran@cc.helsinki.fi
00006 
00007     This library is free software; you can redistribute it and/or
00008     modify it under the terms of the GNU Lesser General Public
00009     License as published by the Free Software Foundation; either
00010     version 2.1 of the License, or (at your option) any later version.
00011 
00012     This library is distributed in the hope that it will be useful,
00013     but WITHOUT ANY WARRANTY; without even the implied warranty of
00014     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015     Lesser General Public License for more details.
00016 
00017     You should have received a copy of the GNU Lesser General Public
00018     License along with this library; if not, write to the Free Software
00019     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00020     
00021     $Id: Scene.cpp,v 1.7 2002/02/16 12:41:39 tksuoran Exp $
00022 */
00023 
00024 
00025 #include "Teddy/Graphics/View.h"
00026 #include "Teddy/Materials/Light.h"
00027 #include "Teddy/Materials/Material.h"
00028 #include "Teddy/Models/Geometry.h"
00029 #include "Teddy/PhysicalComponents/Projection.h"
00030 #include "Teddy/Scenes/Camera.h"
00031 #include "Teddy/Scenes/PostElement.h"
00032 #include "Teddy/Scenes/Scene.h"
00033 #include "Teddy/SysSupport/Messages.h"
00034 #include "Teddy/SysSupport/StdMaths.h"
00035 #include "Teddy/SysSupport/StdIO.h"
00036 #ifndef SWIG
00037 #include <cstdlib>
00038 #include <algorithm>
00039 #endif
00040 using namespace Teddy::Graphics;
00041 using namespace Teddy::Materials;
00042 using namespace Teddy::Models;
00043 using namespace Teddy::PhysicalComponents;
00044 using namespace std;
00045 
00046 
00047 namespace Teddy  {
00048 namespace Scenes {
00049 
00050 
00052 Scene::Scene( const std::string &name )
00053 :
00054     Named( name )
00055 {
00056     cull_count      = 0;
00057     draw_count      = 0;
00058     last_draw_count = 0;
00059     ambient_color   = Color::GRAY_25;
00060 }
00061 
00062 
00063 int Scene::getDrawCount(){
00064     return last_draw_count;
00065 }
00066 
00067 
00069 void Scene::add( Light *l ){
00070     lights.push_back( l );
00071 }
00072 
00073 
00075 void Scene::add( PostElement *p ){
00076     post_elements.push_back( p );
00077 }
00078 
00079 
00081 void Scene::add( Model *m ){
00082     models.push_back( m );
00083 }
00084 
00085 
00086 void Scene::remove( Light *l ){
00087     lights.remove( l );
00088 }
00089 
00090 void Scene::remove( PostElement *p ){
00091     post_elements.remove( p );
00092 }
00093 
00094 void Scene::remove( Model *m ){
00095     models.remove( m );
00096 }
00097 
00098 
00103 void Scene::update( Projection *p ){
00104 //  Disabled; not needed in immediate drawing
00105 /*  list<ModelInstance*>::iterator i_it = instances.begin();
00106     while( i_it != instances.end() ){
00107         (*i_it)->update( p );
00108         i_it++;
00109     }*/
00110 }
00111 
00112 
00114 list<Model*> &Scene::getModels(){
00115     return models;
00116 }
00117 
00118 
00119 void Scene::setAmbientColor( Teddy::Graphics::Color ambient_color ){
00120     this->ambient_color = ambient_color;
00121 }
00122 
00123 
00125 void Scene::draw( Camera *c, Projection *p ){
00126     View                         *view   = p->getView();
00127     list<Light      *>::iterator  l_it;
00128     list<PostElement*>::iterator  p_it;
00129     list<Model      *>::iterator  m_it;
00130     cull_count = 0;
00131 
00132     //  Apply lights 
00133     glLightModelfv( GL_LIGHT_MODEL_AMBIENT, ambient_color.rgba );
00134     switch( p->getMaster()->getLighting() ){
00135 
00136     case 1/*RENDER_LIGHTING_COLOR*/:
00137         //  No lights appleid
00138         break;
00139 
00140     case 2/*RENDER_LIGHTING_CUSTOM*/:
00141         //  FIX Not yet implemented
00142         break;
00143 
00144     case 3/*RENDER_LIGHTING_PRIMARY_LIGHT_ONLY*/:
00145         //  Only OpenGL primary light is applied
00146         l_it = lights.begin();
00147         if( l_it != lights.end() ){
00148             (*l_it)->applyLight( p );
00149         }
00150         break;
00151 
00152     case 5/*RENDER_LIGHTING_FULL*/:
00153         //  FIX Not yet implemented; fall through
00154     case 4/*RENDER_LIGHTING_SIMPLE*/:
00155         //  Render all enabled OpenGL lights
00156         l_it = lights.begin();
00157         while( l_it != lights.end() ){
00158             (*l_it)->applyLight( p );
00159             l_it++;
00160         }
00161         break;
00162 
00163 
00164     default:
00165         //  Unknown lighting mode
00166         break;
00167     }
00168 
00169     //  Render objects
00170     m_it = models.begin();
00171     while( m_it != models.end() ){
00172         Model *m = *m_it;
00173         if( m != c ){
00174             m->draw( p );
00175         }
00176         m_it++;
00177     }
00178     last_draw_count = Geometry::draw_count;
00179 
00180     drawPostElements( c, p );
00181 }
00182 
00183 
00184 int Scene::getCullCount(){
00185     return cull_count;
00186 }
00187 
00188 
00190 void Scene::drawPostElements( Camera *c, Projection *p ){
00191     View                         *view   = p->getView();
00192     list<PostElement*>::iterator  p_it;
00193 
00194     //  Render PostElements
00195     c->doProjection     ( p, true );
00196 //  c->doCamera         ( p, false );
00197     view->enable        ( View::BLEND );
00198     view->setShadeModel ( GL_SMOOTH );
00199     view->setPolygonMode( GL_FILL );
00200     view->setBlendFunc  ( GL_ONE, GL_ONE );
00201     view->disable       ( View::LIGHTING      );
00202     view->disable       ( View::DEPTH_TEST     );
00203     view->disable       ( View::CULL_FACE      );
00204     view->disable       ( View::POLYGON_OFFSET );
00205 
00206 //  view->setProjectionMatrix( Matrix::Identity );
00207     view->setModelViewMatrix ( Matrix::IDENTITY );
00208 
00209     p_it = post_elements.begin();
00210     while( p_it != post_elements.end() ){
00211         (*p_it)->draw( p );
00212         p_it++;
00213     }
00214 }
00215 
00216 
00218 Model  *Scene::pick( Camera *c, Projection *p ){
00219     Model                  *m_lookup[1024];
00220     Model                  *pick = NULL;
00221     View                   *view;
00222     GLuint                  hits[1024];
00223     list<Model*>::iterator  m_it;
00224 
00225     glSelectBuffer( 1024, hits );
00226 
00227     glRenderMode( GL_SELECT );
00228     view = p->getView();    
00229     p->pickState( true );
00230 //  view->setPolygonMode( GL_FILL );
00231 //  view->setPolygonMode( GL_FILL );
00232 //  view->enable( CULL_FACE );
00233     glInitNames();
00234     glPushName( 0 );
00235 
00236     int name        = 1;
00237     int pick_drawn  = 0;
00238     int pick_culled = 0;
00239     int pick_hidden = 0;
00240 
00241     m_it = models.begin();
00242     while( m_it != models.end() ){
00243         Model *m = (*m_it);
00244         m_lookup[name] = m;
00245         glLoadName( name++ );
00246 //      real r2 = mi->distanceSqr( Vector::NullVector );
00247 //      if( r2 < mi->getClipRange() ){
00248         if( m != c ){
00249 /*          if( c->cull( mi ) ){
00250                 pick_culled++;
00251             }else{
00252                 mi->draw( p );
00253                 pick_drawn++;
00254             }*/
00255             m->draw( p );
00256             pick_drawn++;
00257         }else{
00258             pick_hidden++;
00259         }
00260 
00261         m_it++;
00262     }
00263     GLuint  num_hits = glRenderMode( GL_RENDER );
00264     GLuint *ptr      = hits;
00265     GLuint  names;
00266     GLuint  z_min;
00267     GLuint  z_max;
00268     GLuint  hit_name;
00269     GLuint  nearest = 0xffffffff;
00270     //printf( "Pick: drawn %d culled %d hidden %d hits %d\n", pick_drawn, pick_culled, pick_hidden, num_hits );
00271     for( GLuint i=0; i<num_hits; i++ ){
00272         names = *ptr++;
00273         z_min = *ptr++;
00274         z_max = *ptr++;
00275         for( GLuint j=0; j<names; j++ ){
00276             hit_name = *ptr++;
00277             if( z_min<nearest ){
00278                 nearest = z_min;
00279                 pick    = m_lookup[hit_name];
00280             }
00281         }       
00282     }
00283     p->pickState( false );
00284 /*  if( pick != NULL ){
00285         printf( "Picked %s\n", pick->getName().c_str() );
00286     }else{
00287         printf( "NULL pick\n" );
00288     }*/
00289     return pick;
00290 }
00291 
00292 
00293 //  FIX works because/even though model clip radius is not correct
00294 float Scene::getMaxObSize(){
00295     float                  max_ob_size = 0.0f;
00296     list<Model*>::iterator m_it        = models.begin();
00297     while( m_it != models.end() ){
00298         Model *model = *m_it;
00299         max_ob_size = MAX(
00300             max_ob_size,
00301             model->getClipRadius() 
00302         );
00303         m_it++;
00304     }
00305     return max_ob_size;
00306 }
00307 
00308 
00309 //  Approximation, does not consider children
00310 float Scene::getMaxObDistance(){
00311     float                  max_ob_dist = 0.0f;
00312     list<Model*>::iterator m_it        = models.begin();
00313     while( m_it != models.end() ){
00314         Model        *model   = *m_it;
00315         DoubleVector  ob_pos  = model->getPosition();
00316         float         ob_dist = (float)ob_pos.magnitude();
00317         max_ob_dist = MAX(
00318             max_ob_dist,
00319             ob_dist 
00320         );
00321         m_it++;
00322     }
00323     return max_ob_dist;
00324 }
00325 
00326 
00327 };  //  namespace Scenes
00328 };  //  namespace Teddy
00329 
00330