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

ps2gl version 0.2