TGLLightSet.cxx

Go to the documentation of this file.
00001 // @(#)root/gl:$Id: TGLLightSet.cxx 34006 2010-06-21 10:36:05Z matevz $
00002 // Author:  Matevz Tadel, Feb 2007
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2004, Rene Brun and Fons Rademakers.               *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010  *************************************************************************/
00011 
00012 #include "TGLLightSet.h"
00013 
00014 #include "TGLBoundingBox.h"
00015 #include "TGLOrthoCamera.h"
00016 
00017 #include "TGLIncludes.h"
00018 
00019 //______________________________________________________________________
00020 // TGLLightSet
00021 //
00022 // Encapsulates a set of lights for OpenGL.
00023 //
00024 
00025 ClassImp(TGLLightSet)
00026 
00027 TGLLightSet::TGLLightSet() :
00028    TObject(),
00029 
00030    fLightState(kLightMask), // All on
00031    fUseSpecular(kTRUE),
00032 
00033    fFrontPower(0.4), fSidePower(0.7), fSpecularPower(0.8)
00034 {
00035    // Constructor.
00036 }
00037 
00038 //______________________________________________________________________________
00039 void TGLLightSet::ToggleLight(ELight light)
00040 {
00041    // Toggle light on/off.
00042 
00043    if (light == kLightSpecular) {
00044       fUseSpecular = !fUseSpecular;
00045    } else if (light >= kLightMask) {
00046       Error("TGLLightSet::ToggleLight", "invalid light type");
00047       return;
00048    } else {
00049       fLightState ^= light;
00050    }
00051 }
00052 
00053 //______________________________________________________________________________
00054 void TGLLightSet::SetLight(ELight light, Bool_t on)
00055 {
00056    // Set a light on/off.
00057 
00058    if (light == kLightSpecular) {
00059       fUseSpecular = on;
00060    } else if (light >= kLightMask) {
00061       Error("TGLViewer::ToggleLight", "invalid light type");
00062       return;
00063    }
00064 
00065    if (on) {
00066       fLightState |=  light;
00067    } else {
00068       fLightState &= ~light;
00069    }
00070 }
00071 
00072 //______________________________________________________________________________
00073 void TGLLightSet::StdSetupLights(const TGLBoundingBox& bbox,
00074                                  const TGLCamera     & camera, Bool_t debug)
00075 {
00076    // Setup lights for current given bounding box and camera.
00077    // This is called by standard GL viewer.
00078    // Expects matrix-mode to be model-view.
00079 
00080    glPushMatrix();
00081 
00082    if (!bbox.IsEmpty())
00083    {
00084       // Calculate a sphere radius to arrange lights round
00085       Double_t lightRadius = bbox.Extents().Mag() * 2.9;
00086       Double_t sideLightsZ, frontLightZ;
00087 
00088       const TGLOrthoCamera* orthoCamera = dynamic_cast<const TGLOrthoCamera*>(&camera);
00089       if (orthoCamera) {
00090          // Find distance from near clip plane to furstum center - i.e. vector of half
00091          // clip depth. Ortho lights placed this distance from eye point
00092          sideLightsZ =
00093             camera.FrustumPlane(TGLCamera::kNear).DistanceTo(camera.FrustumCenter())*0.7;
00094          frontLightZ = sideLightsZ;
00095       } else {
00096          // Perspective camera
00097          // Extract vector from camera eye point to center.
00098          // Camera must have been applied already.
00099          TGLVector3 eyeVector = camera.EyePoint() - camera.FrustumCenter();
00100 
00101          // Pull forward slightly (0.85) to avoid to sharp a cutoff
00102          sideLightsZ = eyeVector.Mag() * -0.85;
00103          frontLightZ = 0.2 * lightRadius;
00104       }
00105 
00106       // Reset the modelview so static lights are placed in fixed eye space
00107       // This will destroy camera application.
00108       glLoadIdentity();
00109 
00110       // 0: Front, 1: Top, 2: Bottom, 3: Left, 4: Right
00111       TGLVertex3 c = bbox.Center();
00112       TGLVector3 center(c.X(), c.Y(), c.Z());
00113       camera.RefModelViewMatrix().MultiplyIP(center);
00114       // Float_t pos0[] = { center.X(), center.Y(), frontLightZ, 1.0 };
00115       Float_t pos0[] = { 0.0,        0.0,                      frontLightZ, 1.0 };
00116       Float_t pos1[] = { center.X(), center.Y() + lightRadius, sideLightsZ, 1.0 };
00117       Float_t pos2[] = { center.X(), center.Y() - lightRadius, sideLightsZ, 1.0 };
00118       Float_t pos3[] = { center.X() - lightRadius, center.Y(), sideLightsZ, 1.0 };
00119       Float_t pos4[] = { center.X() + lightRadius, center.Y(), sideLightsZ, 1.0 };
00120 
00121       Float_t specular = fUseSpecular ? fSpecularPower : 0.0f;
00122       const Float_t frontLightColor[] = { fFrontPower, fFrontPower, fFrontPower, 1.0f };
00123       const Float_t sideLightColor[]  = { fSidePower,  fSidePower,  fSidePower,  1.0f };
00124       const Float_t specLightColor[]  = { specular,    specular,    specular,    1.0f };
00125 
00126       glLightfv(GL_LIGHT0, GL_POSITION, pos0);
00127       glLightfv(GL_LIGHT0, GL_DIFFUSE,  frontLightColor);
00128       glLightfv(GL_LIGHT0, GL_SPECULAR, specLightColor);
00129 
00130       glLightfv(GL_LIGHT1, GL_POSITION, pos1);
00131       glLightfv(GL_LIGHT1, GL_DIFFUSE,  sideLightColor);
00132       glLightfv(GL_LIGHT2, GL_POSITION, pos2);
00133       glLightfv(GL_LIGHT2, GL_DIFFUSE,  sideLightColor);
00134       glLightfv(GL_LIGHT3, GL_POSITION, pos3);
00135       glLightfv(GL_LIGHT3, GL_DIFFUSE,  sideLightColor);
00136       glLightfv(GL_LIGHT4, GL_POSITION, pos4);
00137       glLightfv(GL_LIGHT4, GL_DIFFUSE,  sideLightColor);
00138    }
00139 
00140    // Set light states everytime - must be defered until now when we know we
00141    // are in the correct thread for GL context
00142    // TODO: Could detect state change and only adjust if a change
00143    for (UInt_t light = 0; (1<<light) < kLightMask; light++)
00144    {
00145       if ((1<<light) & fLightState)
00146       {
00147          glEnable(GLenum(GL_LIGHT0 + light));
00148 
00149          // Debug mode - show active lights in yellow
00150          if (debug)
00151          {
00152             // Lighting itself needs to be disable so a single one can show...!
00153             glDisable(GL_LIGHTING);
00154             Float_t position[4]; // Only float parameters for lights (no double)....
00155             glGetLightfv(GLenum(GL_LIGHT0 + light), GL_POSITION, position);
00156             Double_t size = bbox.Extents().Mag() / 10.0;
00157             TGLVertex3 dPosition(position[0], position[1], position[2]);
00158             TGLUtil::DrawSphere(dPosition, size, TGLUtil::fgYellow);
00159             glEnable(GL_LIGHTING);
00160          }
00161       }
00162       else
00163       {
00164          glDisable(GLenum(GL_LIGHT0 + light));
00165       }
00166    }
00167 
00168    // Restore camera which was applied before we were called, and is disturbed
00169    // by static light positioning above.
00170    glPopMatrix();
00171 }

Generated on Tue Jul 5 14:18:07 2011 for ROOT_528-00b_version by  doxygen 1.5.1