00001
00002
00003
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
00013
00014
00015
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
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();
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
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
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 }