Renderer.cpp

Go to the documentation of this file.
00001 // Copyright (C) 2005 Dave Griffiths
00002 //
00003 // This program is free software; you can redistribute it and/or modify
00004 // it under the terms of the GNU General Public License as published by
00005 // the Free Software Foundation; either version 2 of the License, or
00006 // (at your option) any later version.
00007 //
00008 // This program is distributed in the hope that it will be useful,
00009 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00010 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00011 // GNU General Public License for more details.
00012 //
00013 // You should have received a copy of the GNU General Public License
00014 // along with this program; if not, write to the Free Software
00015 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00016 
00017 #include "Renderer.h"
00018 #include "State.h"
00019 #include "Primitive.h"
00020 #include "PNGLoader.h"
00021 #include "Trace.h"
00022 #include <sys/time.h>
00023 #include <stdio.h>
00024 #include <unistd.h>
00025 
00026 using namespace Fluxus;
00027 
00028 //#define DEBUG_TRACE
00029 
00030 // should use glew for this?
00031 #ifndef GL_POLYGON_OFFSET
00032 #define GL_POLYGON_OFFSET GL_POLYGON_OFFSET_EXT
00033 #endif
00034 
00035 static const int FRAMES_PER_TIME = 10;
00036 static int TimeCounter = 0;
00037 static timeval StartTime;
00038 static float FPS;
00039 
00040 static const int MAXLIGHTS = 8;
00041 
00042 Renderer::Renderer() :
00043 m_Initialised(false),
00044 m_InitLights(false),
00045 m_Width(640),
00046 m_Height(480),
00047 m_MotionBlur(false),
00048 m_Fade(0.02f),
00049 m_ShowAxis(false),
00050 m_Grabbed(NULL),
00051 m_ClearFrame(true),
00052 m_ClearZBuffer(true),
00053 m_ClearAccum(false),
00054 m_BackFaceCull(true),
00055 m_FaceOrderClockwise(false),
00056 m_FogDensity(0), 
00057 m_FogStart(0),
00058 m_FogEnd(100),  
00059 m_ShadowLight(0),
00060 m_StereoMode(noStereo),
00061 m_MaskRed(true),
00062 m_MaskGreen(true),
00063 m_MaskBlue(true),
00064 m_MaskAlpha(true),
00065 m_Deadline(1/25.0f),
00066 m_FPSDisplay(false),
00067 m_Time(0),
00068 m_Delta(0)
00069 {
00070     State InitialState;
00071     m_StateStack.push_back(InitialState);
00072     
00073     // stop valgrind complaining
00074     m_LastTime.tv_sec=0;
00075     m_LastTime.tv_usec=0;
00076 }
00077 
00078 Renderer::~Renderer()
00079 {
00080     TexturePainter::Shutdown();
00081 }
00082 
00084 
00085 void Renderer::Render()
00086 {           
00088     if (m_ClearFrame && !m_MotionBlur)
00089     {
00090         glClearColor(m_BGColour.r,m_BGColour.g,m_BGColour.b,m_BGColour.a);  
00091         glClear(GL_COLOR_BUFFER_BIT);   
00092     }
00093     
00094     if (m_ClearZBuffer)
00095     {
00096         glClear(GL_DEPTH_BUFFER_BIT);
00097     }
00098 
00099     if (m_ClearAccum)
00100     {
00101         glClear(GL_ACCUM_BUFFER_BIT);
00102     }
00103     
00104     // need to clear this even if we aren't using shadows
00105     m_World.GetShadowVolumeGen()->Clear();
00106     
00107     if (m_ShadowLight!=0)
00108     {       
00109         RenderStencilShadows();
00110     }
00111     else
00112     {
00113         PreRender();
00114         m_World.Render();
00115         m_ImmediateMode.Render();
00116         m_ImmediateMode.Clear();
00117         PostRender();
00118     }       
00119             
00120     timeval ThisTime;
00121     // stop valgrind complaining
00122     ThisTime.tv_sec=0;
00123     ThisTime.tv_usec=0;
00124     
00125     gettimeofday(&ThisTime,NULL);
00126     m_Delta=(ThisTime.tv_sec-m_LastTime.tv_sec)+
00127             (ThisTime.tv_usec-m_LastTime.tv_usec)*0.000001f;
00128 
00129     if (m_Delta<m_Deadline)
00130     {
00131         //min 1 hz
00132         if(m_Deadline-m_Delta<1.0f)
00133         {
00134             usleep((int)((m_Deadline-m_Delta)*1000000.0f));
00135         }
00136     }
00137     
00138     m_LastTime=ThisTime;
00139     //if (m_Delta>0) m_Time=ThisTime.tv_sec+ThisTime.tv_usec*0.000001f;
00140     if (m_Delta>0.0f && m_Delta<100.0f) m_Time+=m_Delta;
00141 }
00142 
00143 void Renderer::RenderStencilShadows()
00144 {
00145     if (m_LightVec.size()>m_ShadowLight)
00146     {
00147         m_World.GetShadowVolumeGen()->SetLightPosition(m_LightVec[m_ShadowLight]->GetPosition());
00148     }
00149     
00150     PreRender();
00151     glDisable(GL_LIGHT0+m_ShadowLight); 
00152     m_World.Render();
00153     m_ImmediateMode.Render();
00154 
00155     glClear(GL_STENCIL_BUFFER_BIT);
00156     glEnable(GL_STENCIL_TEST);
00157     glStencilFunc(GL_ALWAYS, 0, ~0);
00158     glEnable(GL_DEPTH_TEST);
00159     glDepthFunc(GL_LESS);
00160     glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
00161     glDepthMask(GL_FALSE);
00162     glEnable(GL_CULL_FACE);
00163 
00164     glCullFace(GL_BACK);
00165     glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
00166     m_World.GetShadowVolumeGen()->GetVolume()->Render();
00167 
00168     glCullFace(GL_FRONT);
00169     glStencilOp(GL_KEEP, GL_KEEP, GL_DECR);
00170     m_World.GetShadowVolumeGen()->GetVolume()->Render();
00171 
00172     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
00173     glDepthFunc(GL_EQUAL);
00174     glStencilFunc(GL_EQUAL, 0, ~0);
00175     glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
00176 
00177     glEnable(GL_BLEND);
00178     glBlendFunc(GL_ONE, GL_ONE);
00179     glCullFace(GL_BACK);
00180 
00181     glEnable(GL_LIGHT0+m_ShadowLight);
00182 
00183     m_World.Render();
00184     m_ImmediateMode.Render();
00185 
00186     glDepthMask(GL_TRUE);
00187     glDepthFunc(GL_LEQUAL);
00188     glStencilFunc(GL_ALWAYS, 0, ~0);
00189 
00190     if (m_World.GetShadowVolumeGen()->GetDebug())
00191     {
00192         m_World.GetShadowVolumeGen()->GetVolume()->GetState()->Hints=HINT_WIRE;
00193         m_World.GetShadowVolumeGen()->GetVolume()->Render();
00194         m_World.GetShadowVolumeGen()->GetVolume()->GetState()->Hints=HINT_SOLID;
00195     }
00196 
00197     PostRender();
00198 }
00199 
00200 void Renderer::PreRender(bool PickMode)
00201 {
00202     if (!m_Initialised || PickMode || m_Camera.NeedsInit())
00203     {
00204         glViewport(0,0,m_Width,m_Height);
00205 
00206         glMatrixMode (GL_PROJECTION);
00207         glLoadIdentity();
00208         
00209         if (PickMode) 
00210         {       
00211             GLint viewport[4]={0,0,m_Width,m_Height};
00212             gluPickMatrix(m_SelectInfo.x,m_Height-m_SelectInfo.y,
00213                         m_SelectInfo.size,m_SelectInfo.size,viewport);
00214         }
00215         
00216         m_Camera.DoProjection();
00217         
00218         glEnable(GL_BLEND);
00219         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);  
00220         glEnable(GL_LIGHTING);
00221         
00222         if (m_BackFaceCull)
00223         {
00224             glEnable(GL_CULL_FACE);
00225             glCullFace(GL_BACK);
00226         }
00227         else
00228         {
00229             glDisable(GL_CULL_FACE);
00230         }
00231         
00232         if (m_FaceOrderClockwise) glFrontFace(GL_CW);
00233         else glFrontFace(GL_CCW);
00234                  
00235         glEnable(GL_RESCALE_NORMAL);
00236         glDisable(GL_COLOR_MATERIAL);
00237 
00238         glEnableClientState(GL_VERTEX_ARRAY);
00239         glEnableClientState(GL_NORMAL_ARRAY);
00240         glEnableClientState(GL_TEXTURE_COORD_ARRAY);
00241         glEnableClientState(GL_COLOR_ARRAY);
00242         glEnable(GL_POLYGON_OFFSET);
00243         
00244         if (m_FogDensity>0)
00245         {
00246             glEnable(GL_FOG);
00247             glFogf(GL_FOG_MODE, GL_EXP);
00248             glFogfv(GL_FOG_COLOR, m_FogColour.arr());
00249             glFogf(GL_FOG_DENSITY, m_FogDensity);
00250             glFogf(GL_FOG_HINT, GL_DONT_CARE);
00251             glFogf(GL_FOG_START, m_FogStart);
00252             glFogf(GL_FOG_END, m_FogEnd);
00253         }
00254         else
00255         {
00256             glDisable(GL_FOG);
00257         }   
00258             
00259         glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR);
00260     
00261         TexturePainter::Get()->Initialise();
00262         
00263         m_Initialised=true;
00264     }
00265     
00266     if (!m_InitLights)
00267     {
00268         // builds the default camera light
00269         ClearLights();
00270         m_InitLights=true;
00271     }
00272     
00273     
00274     glMatrixMode (GL_MODELVIEW);
00275     glLoadIdentity();
00276     
00277     PushState();
00278     
00279     if (m_MotionBlur)
00280     {
00281         glEnable(GL_COLOR_MATERIAL);
00282         glPolygonMode(GL_FRONT,GL_FILL);
00283         glDisable(GL_DEPTH_TEST);
00284         glPushMatrix();
00285         glTranslatef(0,0,-10);
00286         glBegin(GL_QUADS);
00287             glColor4f(m_BGColour.r,m_BGColour.g,m_BGColour.b,m_Fade);
00288             glVertex3f(-10,-10,0);
00289             glVertex3f(10,-10,0);
00290             glVertex3f(10,10,0);
00291             glVertex3f(-10,10,0);
00292         glEnd();
00293         glPopMatrix();
00294         glEnable(GL_DEPTH_TEST);
00295         glDisable(GL_COLOR_MATERIAL);
00296     }
00297         
00298     if (m_FPSDisplay && !PickMode)
00299     {
00300         PushState();
00301         GetState()->Transform.translate(m_Camera.GetUp(),m_Camera.GetLeft(),0);
00302         GetState()->Colour=dColour(0,0,1);
00303         char s[32];
00304         sprintf(s,"%f fps",FPS);
00305         DrawText(s);
00306         PopState();
00307     }
00308 
00309     RenderLights(true); // camera locked
00310     m_Camera.DoCamera();
00311     RenderLights(false); // world space
00312     
00313     glColorMask(m_MaskRed,m_MaskGreen,m_MaskBlue,m_MaskAlpha);
00314         
00316     /* ???
00317     RenderLights(true); // camera locked
00318     
00319     glMultMatrixf(m_Camera.arr());
00320     
00321     RenderLights(false); // world space
00322     
00323     if (m_LockedCamera)
00324     {
00325         Primitive *p = GetPrimitive(m_CameraAttached);
00326         if (p)
00327         {
00328             if (m_CameraLag!=0)
00329             {
00330                 m_LockedMatrix.blend(p->GetState()->Transform.inverse(),m_CameraLag);
00331             }
00332             else
00333             {
00334                 m_LockedMatrix=p->GetState()->Transform.inverse();
00335             }
00336             
00337             glMultMatrixf(m_LockedMatrix.arr());        
00338         }
00339         else m_LockedCamera=false;
00340     }*/
00341 
00342     //m_World.GetShadowVolumeGen()->SetLightPosition(m_Camera.inverse().transform((*m_LightVec.begin())->GetPosition()));
00343 
00344 }
00345 
00346 
00347 void Renderer::PostRender()
00348 {
00349     // clear the texture, if the last primitive assigned one...
00350     glDisable(GL_TEXTURE_2D);
00351     GLSLShader::Unapply();
00352 
00353     glDisable(GL_DEPTH_TEST);
00354     if (m_ShowAxis) Primitive::RenderAxes();
00355     glEnable(GL_DEPTH_TEST);
00356     glColorMask(true,true,true,true);
00357     
00358     PopState();
00359     
00360     if (m_FPSDisplay)
00361     {
00362         if (!(TimeCounter%FRAMES_PER_TIME))
00363         {
00364             timeval TimeNow;
00365             gettimeofday(&TimeNow,NULL);    
00366             FPS = (TimeNow.tv_sec-StartTime.tv_sec)+(TimeNow.tv_usec-StartTime.tv_usec)*0.000001f;
00367             FPS/=(float)FRAMES_PER_TIME;
00368             FPS=1/FPS;  
00369             gettimeofday(&StartTime,NULL);
00370         }
00371         TimeCounter++;
00372     }
00373     
00374     //if (m_StateStack.size()!=1)
00375     //{
00376     //  Trace::Stream<<"State mismatch: stack size "<<m_StateStack.size()<<" at end scene"<<endl;
00377     //}
00378 }
00379 
00380 void Renderer::RenderLights(bool camera)
00381 {
00382     int n=0;
00383     for (vector<Light*>::iterator i=m_LightVec.begin(); i!=m_LightVec.end(); i++)
00384     {
00385         if (n<MAXLIGHTS && (*i)->GetCameraLock()==camera) 
00386         {
00387             (*i)->Render();
00388         }
00389         n++;
00390     }
00391 }
00392 
00393 int Renderer::AddLight(Light *l)
00394 {
00395     l->SetIndex(m_LightVec.size());
00396     m_LightVec.push_back(l);
00397     return m_LightVec.size()-1;
00398 }
00399 
00400 Light *Renderer::GetLight(int id)
00401 {
00402     if (id<(int)m_LightVec.size()) return m_LightVec[id];
00403     else return NULL;
00404 }
00405 
00406 void Renderer::ClearLights()
00407 {
00408     for (unsigned int n=0; n<m_LightVec.size(); n++)
00409     {
00410         glDisable(GL_LIGHT0+n);
00411     }
00412     
00413     m_LightVec.clear();
00414     
00415     // add a default light
00416     Light *light=new Light;
00417     light->SetPosition(dVector(0,0,0));
00418     light->SetCameraLock(true);
00419     AddLight(light);
00420 }
00421 
00422 int Renderer::Select(int x, int y, int size)
00423 {
00424     static const int SELECT_SIZE=512;
00425     unsigned int IDs[SELECT_SIZE];
00426     memset(IDs,0,SELECT_SIZE);
00427     GLuint ID=0;
00428     glSelectBuffer(SELECT_SIZE,(GLuint*)IDs);
00429     glRenderMode(GL_SELECT);
00430     glInitNames();
00431     
00432     m_SelectInfo.x=x;
00433     m_SelectInfo.y=y;
00434     m_SelectInfo.size=size;
00435     
00436     // the problem here is that select is called mid-scene, so we have to set up for 
00437     // picking mode here...
00438     PreRender(true);
00439     
00440     // render the scene for picking
00441     m_World.Render(SceneGraph::SELECT);
00442     
00443     int hits=glRenderMode(GL_RENDER);
00444     unsigned int *ptr=IDs, numnames;
00445     float minz,maxz,closest=1000000;
00446 
00447     // process the hit records
00448     for (int n=0; n<hits; n++)
00449     {
00450         numnames=*ptr;
00451         ptr++;
00452         minz = (float) *ptr++/0x7fffffff;
00453         maxz = (float) *ptr++/0x7fffffff;
00454                 
00455         // find the closest one
00456         if (closest>minz) 
00457         {
00458             closest=minz;
00459             ID=*ptr;
00460         }
00461         for (unsigned int i=0; i<numnames; i++) *ptr++;
00462     }
00463     
00464     // ... and reset the scene back here so we can carry on afterwards as if nothing
00465     // has happened...
00466     m_Initialised=false;
00467     PreRender();
00468     
00469     return ID;
00470 }
00471 
00472 void Renderer::Clear()
00473 {
00474     m_World.Clear();
00475     m_StateStack.clear();
00476     UnGrab();
00477     State InitialState;
00478     m_StateStack.push_back(InitialState);
00479 }   
00480 
00481 int Renderer::AddPrimitive(Primitive *Prim)
00482 {
00483     Prim->SetState(GetState());
00484     SceneNode *node = new SceneNode(Prim);
00485     return m_World.AddNode(GetState()->Parent,node);
00486 }
00487 
00488 Primitive *Renderer::GetPrimitive(int ID)
00489 {
00490     SceneNode *node = (SceneNode*)m_World.FindNode(ID);
00491     if (node==NULL) return NULL;
00492     return node->Prim;
00493 }
00494 
00495 void Renderer::RemovePrimitive(int ID)
00496 {
00497     SceneNode *node = (SceneNode*)m_World.FindNode(ID);
00498     if (node!=NULL)
00499     {
00500         if (node->Prim==m_Grabbed) UnGrab();
00501         m_World.RemoveNode(node);
00502     }
00503 }
00504 
00505 void Renderer::DetachPrimitive(int ID)
00506 {
00507     SceneNode *node=(SceneNode*)m_World.FindNode(ID);
00508     if (node) m_World.Detach(node);
00509 }
00510 
00511 // immediate mode
00512 void Renderer::RenderPrimitive(Primitive *Prim)
00513 {   
00514     m_ImmediateMode.Add(Prim,GetState());
00515 }
00516 
00517 dMatrix Renderer::GetGlobalTransform(int ID)
00518 {
00519     dMatrix mat;
00520     SceneNode *node=(SceneNode*)m_World.FindNode(ID);
00521     if (node) mat=m_World.GetGlobalTransform(node);
00522     return mat;
00523 }
00524 
00525 dBoundingBox Renderer::GetBoundingBox(int ID)
00526 {
00527     dBoundingBox bbox;
00528     SceneNode *node=(SceneNode*)m_World.FindNode(ID);
00529     if (node) m_World.GetBoundingBox(node,bbox);
00530     return bbox;
00531 }
00532 
00534 // state accessors
00535 State *Renderer::GetState()
00536 {
00537     if (m_StateStack.empty())
00538     {
00539         Trace::Stream<<"Renderer::GetState : State stack is empty"<<endl;
00540         return NULL;
00541     }
00542     
00543     return &(*m_StateStack.begin());
00544 }
00545 
00546 void Renderer::ApplyState()
00547 {
00548     GetState()->Apply();
00549 }
00550 
00551 void Renderer::PushState()
00552 {
00553     #ifdef DEBUG_TRACE
00554     Trace::Stream<<"Renderer::PushState"<<endl;
00555     #endif
00556     
00557     m_StateStack.push_front(*GetState());
00558 }
00559 
00560 void Renderer::PopState()
00561 {
00562     #ifdef DEBUG_TRACE
00563     Trace::Stream<<"Renderer::PopState"<<endl;
00564     #endif
00565     
00566     if (m_StateStack.size()<2)
00567     {
00568         Trace::Stream<<"Renderer::PopState : only one state left, not popping"<<endl;
00569     }
00570     else
00571     {
00572         m_StateStack.pop_front();
00573     }
00574 }
00575 
00576 void Renderer::Grab(int ID)
00577 {
00578     SceneNode *n=(SceneNode *)m_World.FindNode(ID);
00579     if (n)
00580     {
00581         Primitive *p=n->Prim;
00582         if (p)
00583         {
00584             m_Grabbed=p;
00585         }
00586     }
00587 }
00588 
00589 void Renderer::UnGrab()
00590 {
00591     m_Grabbed=NULL;
00592 }
00593 
00594 //void Renderer::Apply(int id)
00595 //{
00596 //  Primitive *p = GetPrimitive(id);
00597 //  if (p) p->ApplyTransform();
00598 //}
00599 
00600 void Renderer::DrawText(const string &Text)
00601 {
00602     glPushMatrix(); 
00603     GetState()->Apply();
00604     //glDisable(GL_DEPTH_TEST);
00605     glDisable(GL_LIGHTING);
00606     glPushMatrix();
00607     glRasterPos3f(0.0, 0.0, -1.1);
00608     for (unsigned int n=0; n<Text.length(); n++)
00609     {
00610         glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, Text.c_str()[n]);
00611         glTranslatef(1.0f,0.0f,0.0f);
00612     }
00613     glPopMatrix();
00614     glEnable(GL_LIGHTING);
00615     //glEnable(GL_DEPTH_TEST);
00616     glPopMatrix();  
00617 }
00618 
00619 void Renderer::ShowCursor(bool s)
00620 {
00621     if (s)
00622     {
00623         glutSetCursor(GLUT_CURSOR_INHERIT); 
00624     }
00625     else 
00626     {
00627         glutSetCursor(GLUT_CURSOR_NONE); 
00628     }
00629 
00630 }
00631 
00632 void Renderer::DrawBuffer(GLenum mode)
00633 {
00634     glDrawBuffer(mode);
00635 }
00636 
00637 void Renderer::ReadBuffer(GLenum mode)
00638 {
00639     glReadBuffer(mode);
00640 }
00641 
00642 bool Renderer::SetStereoMode(stereo_mode_t mode)
00643 {
00644     GLboolean stereoWindowTest;
00645     switch(mode){
00646         case noStereo: m_StereoMode = noStereo;
00647             return true;
00648         case crystalEyes:
00649             //test for a stereo window
00650             glGetBooleanv (GL_STEREO, &stereoWindowTest);
00651             if(stereoWindowTest){
00652                 m_StereoMode = crystalEyes;
00653                 return true;
00654             } else {
00655                 m_StereoMode = noStereo;
00656                 return false;
00657             }
00658         case colourStereo:
00659             m_StereoMode = colourStereo;
00660             return true;
00661     };
00662     return false;
00663 }
00664 
00665 void Renderer::SetColourMask(bool inred, bool ingreen, bool inblue, bool inalpha)
00666 {
00667     m_MaskRed=inred;
00668     m_MaskGreen=ingreen;
00669     m_MaskBlue=inblue;
00670     m_MaskAlpha=inalpha;
00671 }
00672 
00673 void Renderer::Accum(int mode, float factor)
00674 {
00675     glAccum(mode,factor);
00676 }

Generated on Tue Sep 4 23:22:18 2007 for The Fluxus Renderer (libfluxus) by  doxygen 1.5.1