Main Page   Modules   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members  

lighting.cpp

Go to the documentation of this file.
00001 /*        Copyright (C) 2000,2001,2002  Sony Computer Entertainment America
00002           
00003           This file is subject to the terms and conditions of the GNU Lesser
00004           General Public License Version 2.1. See the file "COPYING" in the
00005           main directory of this archive for more details.                             */
00006 
00007 #include "ps2gl/lighting.h"
00008 #include "ps2gl/glcontext.h"
00009 #include "ps2gl/matrix.h"
00010 #include "ps2gl/dlist.h"
00011 #include "ps2gl/material.h"
00012 
00013 /********************************************
00014  * CImmLight
00015  */
00016 
00017 // static data
00018 
00019 int CImmLight::NumLights[3] = {0, 0, 0};
00020 
00021 CImmLight::CImmLight( CGLContext &context, int lightNum )
00022    : CLight(context, lightNum),
00023      Ambient( 0.0f, 0.0f, 0.0f, 1.0f ),
00024      Diffuse( 0.0f, 0.0f, 0.0f, 0.0f ),
00025      Specular( 0.0f, 0.0f, 0.0f, 0.0f ),
00026      Position( 0.0f, 0.0f, 1.0f, 0.0f ),
00027      SpotDirection( 0.0f, 0.0f, -1.0f, 0.0f ),
00028      SpotCutoff(180.0f), SpotExponent(0.0f),
00029      ConstantAtten(1.0f), LinearAtten(0.0f), QuadAtten(0.0f),
00030      bIsEnabled(false),
00031      Type(kDirectional)
00032 {
00033 }
00034 
00035 void
00036 CImmLight::CheckTypeChange( tLightType oldType )
00037 {
00038    if ( oldType != Type && bIsEnabled ) {
00039       CRendererManager &rm = GLContext.GetImmGeomManager().GetRendererManager();
00040       NumLights[oldType]--;
00041       NumLights[Type]++;
00042       rm.NumLightsChanged( oldType, NumLights[oldType] );
00043       rm.NumLightsChanged( Type, NumLights[Type] );
00044    }
00045 }
00046 
00047 void
00048 CImmLight::SetEnabled( bool enabled )
00049 {
00050    if ( bIsEnabled != enabled ) {
00051       bIsEnabled = enabled;
00052       if (enabled) NumLights[Type]++;
00053       else NumLights[Type]--;
00054 
00055       GLContext.GetImmLighting().SpecularChanged();
00056 
00057       CRendererManager &rm = GLContext.GetImmGeomManager().GetRendererManager();
00058       rm.NumLightsChanged( Type, NumLights[Type] );
00059    }
00060 }
00061 
00062 void
00063 CImmLight::SetSpecular( cpu_vec_xyzw specular )
00064 {
00065    cpu_vec_4 zero(0,0,0,0);
00066    if (specular == zero ^ Specular == zero) {
00067       Specular = specular;
00068       GLContext.GetImmLighting().SpecularChanged();
00069    }
00070    else
00071       Specular = specular;
00072 
00073    TellRendererLightPropChanged();
00074 }
00075 
00076 void
00077 CImmLight::SetPosition( cpu_vec_xyzw position )
00078 {
00079    CImmMatrixStack &modelView = GLContext.GetModelViewStack();
00080    
00081    Position = modelView.GetTop() * position;
00082    TellRendererLightPropChanged();
00083 
00084    tLightType oldType = Type;
00085    Type = (SpotCutoff == 180.0f) ? kPoint : kSpot;
00086    CheckTypeChange(oldType);
00087 }
00088 
00089 void
00090 CImmLight::SetDirection( cpu_vec_xyzw direction )
00091 {
00092    CImmMatrixStack &modelView = GLContext.GetModelViewStack();
00093    
00094    Position = modelView.GetTop() * direction.normalize();
00095    TellRendererLightPropChanged();
00096 
00097    tLightType oldType = Type;
00098    Type = kDirectional;
00099    CheckTypeChange(oldType);
00100 }
00101 
00102 /********************************************
00103  * CDListLight
00104  */
00105 
00106 class CLightPropCmd : public CDListCmd {
00107       GLenum    LightNum, Property;
00108       cpu_vec_xyzw      Value;
00109    public:
00110       CLightPropCmd( GLenum lightNum, GLenum prop, cpu_vec_xyzw value )
00111          : LightNum(lightNum), Property(prop), Value(value) {}
00112       CDListCmd* Play() {
00113          glLightfv( LightNum, Property, reinterpret_cast<float*>(&Value) );
00114          return CDListCmd::GetNextCmd(this);
00115       }
00116 };
00117 
00118 void
00119 CDListLight::SetAmbient( cpu_vec_xyzw ambient )
00120 {
00121    GLContext.GetDListManager().GetOpenDList()
00122       += CLightPropCmd( GL_LIGHT0 | LightNum, GL_AMBIENT, ambient );
00123    TellRendererLightPropChanged();
00124 }
00125 
00126 void
00127 CDListLight::SetDiffuse( cpu_vec_xyzw diffuse )
00128 {
00129    GLContext.GetDListManager().GetOpenDList()
00130       += CLightPropCmd( GL_LIGHT0 | LightNum, GL_DIFFUSE, diffuse );
00131    TellRendererLightPropChanged();
00132 }
00133 
00134 void
00135 CDListLight::SetSpecular( cpu_vec_xyzw specular )
00136 {
00137    GLContext.GetDListManager().GetOpenDList()
00138       += CLightPropCmd( GL_LIGHT0 | LightNum, GL_SPECULAR, specular );
00139    TellRendererLightPropChanged();
00140    GLContext.SpecularEnabledChanged(); // maybe
00141 }
00142 
00143 void
00144 CDListLight::SetPosition( cpu_vec_xyzw position )
00145 {
00146    GLContext.GetDListManager().GetOpenDList()
00147       += CLightPropCmd( GL_LIGHT0 | LightNum, GL_POSITION, position );
00148    TellRendererLightPropChanged();
00149 }
00150 
00151 void
00152 CDListLight::SetDirection( cpu_vec_xyzw direction )
00153 {
00154    GLContext.GetDListManager().GetOpenDList()
00155       += CLightPropCmd( GL_LIGHT0 | LightNum, GL_POSITION, direction );
00156    TellRendererLightPropChanged();
00157 }
00158 
00159 void
00160 CDListLight::SetSpotDirection( cpu_vec_xyzw dir )
00161 {
00162    GLContext.GetDListManager().GetOpenDList()
00163       += CLightPropCmd( GL_LIGHT0 | LightNum, GL_SPOT_DIRECTION, dir );
00164    TellRendererLightPropChanged();
00165 }
00166 
00167 void
00168 CDListLight::SetSpotCutoff( float cutoff )
00169 {
00170    GLContext.GetDListManager().GetOpenDList()
00171       += CLightPropCmd( GL_LIGHT0 | LightNum, GL_SPOT_CUTOFF, cpu_vec_xyzw(cutoff, 0, 0, 0) );
00172    TellRendererLightPropChanged();
00173 }
00174 
00175 void
00176 CDListLight::SetSpotExponent( float exp )
00177 {
00178    GLContext.GetDListManager().GetOpenDList()
00179       += CLightPropCmd( GL_LIGHT0 | LightNum, GL_AMBIENT, cpu_vec_xyzw(exp, 0, 0, 0) );
00180    TellRendererLightPropChanged();
00181 }
00182 
00183 void
00184 CDListLight::SetConstantAtten( float atten )
00185 {
00186    GLContext.GetDListManager().GetOpenDList()
00187       += CLightPropCmd( GL_LIGHT0 | LightNum, GL_CONSTANT_ATTENUATION, cpu_vec_xyzw(atten, 0, 0, 0) );
00188    TellRendererLightPropChanged();
00189 }
00190 
00191 void
00192 CDListLight::SetLinearAtten( float atten )
00193 {
00194    GLContext.GetDListManager().GetOpenDList()
00195       += CLightPropCmd( GL_LIGHT0 | LightNum, GL_LINEAR_ATTENUATION, cpu_vec_xyzw(atten, 0, 0, 0) );
00196    TellRendererLightPropChanged();
00197 }
00198 
00199 void
00200 CDListLight::SetQuadAtten( float atten )
00201 {
00202    GLContext.GetDListManager().GetOpenDList()
00203       += CLightPropCmd( GL_LIGHT0 | LightNum, GL_QUADRATIC_ATTENUATION, cpu_vec_xyzw(atten, 0, 0, 0) );
00204    TellRendererLightPropChanged();
00205 }
00206 
00207 
00208 void
00209 CDListLight::SetEnabled( bool yesNo )
00210 {
00211    GLContext.GetDListManager().GetOpenDList()
00212       += CEnableCmd( GL_LIGHT0 | LightNum );
00213    TellRendererLightsEnabledChanged();
00214 }
00215 
00216 
00217 /********************************************
00218  * CLighting
00219  */
00220 
00221 CImmLighting::CImmLighting( CGLContext &context )
00222    : CLighting(context),
00223      CurrentColor( 0.0f, 0.0f, 0.0f, 0.0f ),
00224      GlobalAmbient( 0.0f, 0.0f, 0.0f, 0.0f ),
00225      Light0(context, 0), Light1(context, 1), Light2(context, 2), Light3(context, 3),
00226      Light4(context, 4), Light5(context, 5), Light6(context, 6), Light7(context, 7),
00227      IsEnabled(false),
00228      NumLightsWithNonzeroSpecular(0)
00229 {
00230    Lights[0] = &Light0;
00231    Lights[1] = &Light1;
00232    Lights[2] = &Light2;
00233    Lights[3] = &Light3;
00234    Lights[4] = &Light4;
00235    Lights[5] = &Light5;
00236    Lights[6] = &Light6;
00237    Lights[7] = &Light7;
00238 }
00239 
00240 void
00241 CImmLighting::SpecularChanged()
00242 {
00243    int count = 0;
00244    cpu_vec_4 zero(0,0,0,0);
00245    for ( int i = 0; i < 8; i++ )
00246       if ( Lights[i]->IsEnabled() && Lights[i]->GetSpecular() != zero )
00247          count++;
00248 
00249    NumLightsWithNonzeroSpecular = count;
00250    if ( NumLightsWithNonzeroSpecular == 0 ) {
00251       GLContext.SpecularEnabledChanged();
00252       GLContext.GetImmGeomManager().GetRendererManager().SpecularEnabledChanged(false);
00253    }
00254    else
00255       GLContext.GetMaterialManager().GetImmMaterial().LightsHaveSpecular();
00256 }
00257 
00258 void
00259 CImmLighting::MaterialHasSpecular()
00260 {
00261    if ( NumLightsWithNonzeroSpecular > 0 ) {
00262       GLContext.SpecularEnabledChanged();
00263       GLContext.GetImmGeomManager().GetRendererManager().SpecularEnabledChanged(true);
00264    }
00265 }
00266 
00267 
00268 CDListLighting::CDListLighting( CGLContext &context )
00269    : CLighting(context),
00270      Light0(context, 0), Light1(context, 1), Light2(context, 2), Light3(context, 3),
00271      Light4(context, 4), Light5(context, 5), Light6(context, 6), Light7(context, 7)
00272 {
00273    Lights[0] = &Light0;
00274    Lights[1] = &Light1;
00275    Lights[2] = &Light2;
00276    Lights[3] = &Light3;
00277    Lights[4] = &Light4;
00278    Lights[5] = &Light5;
00279    Lights[6] = &Light6;
00280    Lights[7] = &Light7;
00281 }
00282 
00283 class CSetLightingEnabledCmd : public CDListCmd {
00284       bool      IsEnabled;
00285    public:
00286       CSetLightingEnabledCmd( bool enabled ) : IsEnabled(enabled) {}
00287       CDListCmd* Play() {
00288          pGLContext->GetImmLighting().SetLightingEnabled(IsEnabled);
00289          return CDListCmd::GetNextCmd(this);
00290       }
00291 };
00292 
00293 void
00294 CDListLighting::SetLightingEnabled( bool enabled )
00295 {
00296    GLContext.GetDListManager().GetOpenDList() += CSetLightingEnabledCmd(enabled);
00297    GLContext.LightingEnabledChanged();
00298 }
00299 
00300 class CSetGlobalAmbientCmd : public CDListCmd {
00301       cpu_vec_xyzw      Ambient;
00302    public:
00303       CSetGlobalAmbientCmd( cpu_vec_xyzw newAmb ) : Ambient(newAmb) {}
00304       CDListCmd* Play() {
00305          pGLContext->GetImmLighting().SetGlobalAmbient( Ambient );
00306          return CDListCmd::GetNextCmd(this);
00307       }
00308 };
00309 
00310 void
00311 CDListLighting::SetGlobalAmbient( cpu_vec_xyzw newAmb )
00312 {
00313    GLContext.GetDListManager().GetOpenDList() += CSetGlobalAmbientCmd(newAmb);
00314    TellRendererLightPropChanged();
00315 }
00316 
00317 /********************************************
00318  * gl interface
00319  */
00320 
00321 void
00322 setPosition( CLight &light, float x, float y, float z, float w )
00323 {
00324    cpu_vec_xyzw pos(x, y, z, w);
00325    if ( w == 0.0f )
00326       light.SetDirection( pos );
00327    else
00328       light.SetPosition( pos );
00329 }
00330 
00331 void glLightfv( GLenum lightNum,
00332                 GLenum pname,
00333                 const GLfloat *params )
00334 {
00335    CLighting& lighting = pGLContext->GetLighting();
00336    CLight& light = lighting.GetLight(0x7 & lightNum);
00337 
00338    switch (pname) {
00339       case GL_AMBIENT:
00340          light.SetAmbient( cpu_vec_xyzw(params[0], params[1], params[2], params[3]) );
00341          break;
00342       case GL_DIFFUSE:
00343          light.SetDiffuse( cpu_vec_xyzw(params[0], params[1], params[2], params[3]) );
00344          break;
00345       case GL_SPECULAR:
00346          light.SetSpecular( cpu_vec_xyzw(params[0], params[1], params[2], params[3]) );
00347          break;
00348       case GL_POSITION:
00349          setPosition(light, params[0], params[1], params[2], params[3]);
00350          break;
00351       case GL_SPOT_DIRECTION:
00352          light.SetPosition( cpu_vec_xyzw(params[0], params[1], params[2], 0.0f).normalize() );
00353          break;
00354       case GL_SPOT_EXPONENT:
00355          light.SetSpotExponent( *params );
00356          break;
00357       case GL_SPOT_CUTOFF:
00358          light.SetSpotCutoff( *params );
00359          break;
00360       case GL_CONSTANT_ATTENUATION:
00361          light.SetConstantAtten( *params );
00362          break;
00363       case GL_LINEAR_ATTENUATION:
00364          light.SetLinearAtten( *params );
00365          break;
00366       case GL_QUADRATIC_ATTENUATION:
00367          light.SetQuadAtten( *params );
00368          break;
00369       default:
00370          mError("Shouldn't get here." );
00371    }
00372 }
00373 
00374 void glLightf( GLenum lightNum, GLenum pname, GLfloat param )
00375 {
00376    CLighting& lighting = pGLContext->GetLighting();
00377    CLight& light = lighting.GetLight(0x7 & lightNum);
00378 
00379    switch (pname) {
00380       case GL_SPOT_EXPONENT:
00381          light.SetSpotExponent( param );
00382          break;
00383       case GL_SPOT_CUTOFF:
00384          light.SetSpotCutoff( param );
00385          break;
00386       case GL_CONSTANT_ATTENUATION:
00387          light.SetConstantAtten( param );
00388          break;
00389       case GL_LINEAR_ATTENUATION:
00390          light.SetLinearAtten( param );
00391          break;
00392       case GL_QUADRATIC_ATTENUATION:
00393          light.SetQuadAtten( param );
00394          break;
00395       default:
00396          mError("Shouldn't get here." );
00397    }   
00398 }
00399 
00400 void glLightModelfv( GLenum pname, const GLfloat *params )
00401 {
00402    switch (pname) {
00403       case GL_LIGHT_MODEL_AMBIENT:
00404          pGLContext->GetLighting().SetGlobalAmbient( cpu_vec_xyzw( params[0],
00405                                                                    params[1],
00406                                                                    params[2],
00407                                                                    params[3] ) );
00408          break;
00409       case GL_LIGHT_MODEL_COLOR_CONTROL:
00410          if ( (int)*params == GL_SEPARATE_SPECULAR_COLOR ) {
00411             mNotImplemented( "separate specular color computation" );
00412          }
00413          break;
00414       case GL_LIGHT_MODEL_LOCAL_VIEWER:
00415          if ( (int)*params != 0 ) {
00416             mNotImplemented( "local viewer" );
00417          }
00418          break;
00419       case GL_LIGHT_MODEL_TWO_SIDE:
00420          if ( (int)*params != 0 ) {
00421             mNotImplemented( "two-sided lighting" );
00422          }
00423          break;
00424       default:
00425          mError("shouldn't get here");
00426    }
00427 }
00428 
00429 void glLightModeli( GLenum pname, int param )
00430 {
00431    mNotImplemented( );
00432 }
00433 
00434 void glGetLightfv( GLenum light, GLenum pname, float *params )
00435 {
00436    mNotImplemented( );
00437 }
00438 
00439 void glFogf( GLenum pname, GLfloat param )
00440 {
00441    mNotImplemented( );
00442 }
00443 
00444 void glFogfv( GLenum pname, const GLfloat *params )
00445 {
00446    mNotImplemented( );
00447 }

ps2gl version cvs