CrystalSpace

Public API Reference

Main Page | Modules | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | File Members | Related Pages

vertexlight.h

00001 /*
00002   Copyright (C) 2005 by Marten Svanfeldt
00003 
00004   This library is free software; you can redistribute it and/or
00005   modify it under the terms of the GNU Library General Public
00006   License as published by the Free Software Foundation; either
00007   version 2 of the License, or (at your option) any later version.
00008 
00009   This library is distributed in the hope that it will be useful,
00010   but WITHOUT ANY WARRANTY; without even the implied warranty of
00011   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012   Library General Public License for more details.
00013 
00014   You should have received a copy of the GNU Library General Public
00015   License along with this library; if not, write to the Free
00016   Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00017 */
00018 
00019 #ifndef __CS_VERTEXLIGHT_H__
00020 #define __CS_VERTEXLIGHT_H__
00021 
00022 #include "csgeom/math.h"
00023 #include "csgeom/vector3.h"
00024 #include "iengine/movable.h"
00025 #include "iengine/light.h"
00026 
00027 // Attenuation functors
00028 
00032 struct CS_CSGFX_EXPORT csNoAttenuation
00033 {
00034   csNoAttenuation (iLight *light)
00035   {}
00036 
00037   CS_FORCEINLINE void operator() (float distance, float &dp) const
00038   {}
00039 };
00040 
00045 struct CS_CSGFX_EXPORT csLinearAttenuation
00046 {
00047   csLinearAttenuation (iLight *light)
00048   {
00049     invrad = 1/light->GetAttenuationConstants ().x;
00050   }
00051 
00052   CS_FORCEINLINE void operator() (float distance, float& dp) const
00053   {
00054     dp = dp * (1 - distance * invrad);
00055   }
00056 
00057   float invrad;
00058 };
00059 
00064 struct CS_CSGFX_EXPORT csInverseAttenuation
00065 {
00066   csInverseAttenuation (iLight *light)
00067   {}
00068 
00069   CS_FORCEINLINE void operator() (float distance, float& dp) const
00070   {
00071     dp = dp / distance;
00072   }
00073 };
00074 
00075 
00080 struct CS_CSGFX_EXPORT csRealisticAttenuation
00081 {
00082   csRealisticAttenuation (iLight *light)
00083   {}
00084 
00085   CS_FORCEINLINE void operator() (float distance, float& dp) const
00086   {
00087     dp = dp / (distance*distance);
00088   }
00089 };
00090 
00095 struct CS_CSGFX_EXPORT csCLQAttenuation
00096 {
00097   csCLQAttenuation (iLight *light)
00098     : attnVec (light->GetAttenuationConstants ())
00099   {}
00100 
00101   CS_FORCEINLINE void operator() (float distance, float& dp) const
00102   {
00103     dp = dp/(csVector3 (1.0, distance, distance*distance)*attnVec);
00104   }
00105 
00106   csVector3 attnVec;
00107 };
00108 
00114 template<class AttenuationProc>
00115 class csPointLightProc
00116 {
00117 public:
00118   csPointLightProc (iLight *light, iMovable *objectMovable,
00119     float blackLimit = 0.0001f)
00120     : attn (light), nullColor (0.0f, 0.0f, 0.0f), blackLimit (blackLimit)
00121   {
00122     csReversibleTransform objT = objectMovable->GetFullTransform ();
00123     lightPos = objT.Other2This (light->GetMovable ()->GetFullPosition ());
00124     lightCol = light->GetColor ();
00125   }
00126 
00127   CS_FORCEINLINE
00128   csColor ProcessVertex (const csVector3 &v,const csVector3 &n) const
00129   {
00130     //compute gouraud shading..
00131     csVector3 direction = v-lightPos;
00132     float distance = csQsqrt(direction.SquaredNorm ());
00133     float dp = direction*n/distance;
00134     if (dp > blackLimit)
00135     {
00136       attn (distance, dp);
00137       return lightCol*dp;
00138     }
00139     return nullColor;
00140   }
00141 
00142 private:
00143   AttenuationProc attn;
00144   csVector3 lightPos; //localspace
00145   csColor lightCol;
00146   csColor nullColor;
00147   float blackLimit;
00148 };
00149 
00155 template<class AttenuationProc>
00156 class csDirectionalLightProc
00157 {
00158 public:
00159   csDirectionalLightProc (iLight *light, iMovable *objectMovable,
00160     float blackLimit = 0.0001f)
00161     : attn (light), nullColor (0.0f, 0.0f, 0.0f), blackLimit (blackLimit)
00162   {
00163     csReversibleTransform objT = objectMovable->GetFullTransform ();
00164     csReversibleTransform lightT = light->GetMovable ()->GetFullTransform ();
00165     lightPos = objT.Other2This (lightT.GetOrigin ());
00166     lightDir = objT.Other2ThisRelative (lightT.This2OtherRelative (
00167       light->GetDirection ()));
00168     lightDir = lightDir.Unit ();
00169     lightCol = light->GetColor ();
00170   }
00171 
00172   CS_FORCEINLINE
00173   csColor ProcessVertex (const csVector3 &v,const csVector3 &n) const
00174   {
00175     //compute gouraud shading..
00176     float dp = lightDir*n;
00177     if (dp > blackLimit)
00178     {
00179       csVector3 direction = v-lightPos;
00180       float distance = csQsqrt(direction.SquaredNorm ());
00181       attn (distance, dp);
00182       return lightCol*dp;
00183     }
00184     return nullColor;
00185   }
00186 
00187 private:
00188   AttenuationProc attn;
00189   csVector3 lightPos; //localspace
00190   csVector3 lightDir; //localspace
00191   csColor lightCol;
00192   csColor nullColor;
00193   float blackLimit;
00194 };
00195 
00201 template<class AttenuationProc>
00202 class csSpotLightProc
00203 {
00204 public:
00205   csSpotLightProc (iLight *light, iMovable *objectMovable,
00206     float blackLimit = 0.0001f)
00207     : attn (light), nullColor (0.0f, 0.0f, 0.0f), blackLimit (blackLimit)
00208   {
00209     csReversibleTransform objT = objectMovable->GetFullTransform ();
00210     csReversibleTransform lightT = light->GetMovable ()->GetFullTransform ();
00211     lightPos = objT.Other2This (lightT.GetOrigin ());
00212     lightDir = objT.Other2ThisRelative (lightT.This2OtherRelative (
00213       light->GetDirection ()));
00214     lightDir = lightDir.Unit ();
00215 
00216     lightCol = light->GetColor ();
00217     light->GetSpotLightFalloff (falloffInner, falloffOuter);
00218   }
00219 
00220   CS_FORCEINLINE
00221   csColor ProcessVertex (const csVector3 &v,const csVector3 &n) const
00222   {
00223     csVector3 direction = (v-lightPos).Unit ();
00224 
00225     //compute gouraud shading..
00226     float dp = direction*n;
00227     if (dp > blackLimit)
00228     {
00229       float cosfact =
00230         csSmoothStep (-(direction*lightDir), falloffOuter, falloffInner);
00231       float distance = csQsqrt(direction.SquaredNorm ());
00232       if (cosfact > 0)
00233       {
00234         attn (distance, dp);
00235         return lightCol*dp*cosfact;
00236       }
00237     }
00238     return nullColor;
00239   }
00240 
00241 private:
00242   AttenuationProc attn;
00243   csVector3 lightPos; //localspace
00244   csVector3 lightDir; //localspace
00245   csColor lightCol;
00246   csColor nullColor;
00247   float blackLimit;
00248   float falloffInner, falloffOuter;
00249 };
00250 
00251 template<class LightProc, class VertexType = csVector3,
00252   class ColorType = csColor>
00253 class csVertexLightCalculator
00254 {
00255 public:
00256   csVertexLightCalculator ()
00257   {
00258   }
00259 
00260   void CalculateLighting (iLight *light, iMovable *objectMovable,
00261     size_t numvert, VertexType *vb, csVector3 *nb, ColorType *litColor) const
00262   {
00263     // setup the light calculator
00264     LightProc lighter (light, objectMovable);
00265 
00266     for (size_t n = 0; n < numvert; n++)
00267     {
00268       litColor[n] = lighter.ProcessVertex (vb[n], nb[n]);
00269     }
00270   }
00271 
00272   void CalculateLightingAdd (iLight *light, iMovable *objectMovable,
00273     size_t numvert, VertexType *vb, csVector3 *nb, ColorType *litColor) const
00274   {
00275     // setup the light calculator
00276     LightProc lighter (light, objectMovable);
00277 
00278     for (size_t n = 0; n < numvert; n++)
00279     {
00280       litColor[n] += lighter.ProcessVertex (vb[n], nb[n]);
00281     }
00282   }
00283 
00284   void CalculateLightingMul (iLight *light, iMovable *objectMovable,
00285     size_t numvert, VertexType *vb, csVector3 *nb, ColorType *litColor) const
00286   {
00287     // setup the light calculator
00288     LightProc lighter (light, objectMovable);
00289 
00290     for (size_t n = 0; n < numvert; n++)
00291     {
00292       litColor[n] *= lighter.ProcessVertex (vb[n], nb[n]);
00293     }
00294   }
00295 };
00296 
00297 #endif //__CS_VERTEXLIGHT_H__

Generated for Crystal Space by doxygen 1.3.9.1