From 0ea5fc66924303d1bf73ba283a383e2aadee02f2 Mon Sep 17 00:00:00 2001 From: neodarz Date: Sat, 11 Aug 2018 20:21:34 +0200 Subject: Initial commit --- .../doxygen/nel/lighting__manager_8cpp-source.html | 559 +++++++++++++++++++++ 1 file changed, 559 insertions(+) create mode 100644 docs/doxygen/nel/lighting__manager_8cpp-source.html (limited to 'docs/doxygen/nel/lighting__manager_8cpp-source.html') diff --git a/docs/doxygen/nel/lighting__manager_8cpp-source.html b/docs/doxygen/nel/lighting__manager_8cpp-source.html new file mode 100644 index 00000000..5ac12d9b --- /dev/null +++ b/docs/doxygen/nel/lighting__manager_8cpp-source.html @@ -0,0 +1,559 @@ + + + + nevrax.org : docs + + + + + + + + + + + + + + +
# Home   # nevrax.com   
+ + + + +
Nevrax
+ + + + + + + + + + +
+ + +
+ Nevrax.org
+ + + + + + + +
#News
#Mailing-list
#Documentation
#CVS
#Bugs
#License
+
+ + +
+ + +
+Docs + +
+  + + + + + +
Documentation 
+ +
+Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages   Search  
+

lighting_manager.cpp

Go to the documentation of this file.
00001 
+00007 /* Copyright, 2001 Nevrax Ltd.
+00008  *
+00009  * This file is part of NEVRAX NEL.
+00010  * NEVRAX NEL is free software; you can redistribute it and/or modify
+00011  * it under the terms of the GNU General Public License as published by
+00012  * the Free Software Foundation; either version 2, or (at your option)
+00013  * any later version.
+00014 
+00015  * NEVRAX NEL is distributed in the hope that it will be useful, but
+00016  * WITHOUT ANY WARRANTY; without even the implied warranty of
+00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+00018  * General Public License for more details.
+00019 
+00020  * You should have received a copy of the GNU General Public License
+00021  * along with NEVRAX NEL; see the file COPYING. If not, write to the
+00022  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+00023  * MA 02111-1307, USA.
+00024  */
+00025 
+00026 #include "std3d.h"
+00027 
+00028 #include "3d/lighting_manager.h"
+00029 #include "3d/point_light.h"
+00030 #include "3d/transform.h"
+00031 #include "3d/fast_floor.h"
+00032 #include "nel/3d/logic_info.h"
+00033 #include "nel/misc/aabbox.h"
+00034 
+00035 
+00036 using namespace NLMISC;
+00037 using namespace std;
+00038 
+00039 
+00040 namespace NL3D {
+00041 
+00042 
+00043 // ***************************************************************************
+00044 /* LightQuadGrid setup. This is the same setup for StaticLightedModelQuadGrid setup.
+00045         NB: with this setup, a light will lies into 4*4=16 squares of a quadGrid at max.
+00046 */
+00047 #define NL3D_LIGHT_QUAD_GRID_SIZE                               256
+00048 #define NL3D_LIGHT_QUAD_GRID_ELTSIZE                    10.f
+00049 #define NL3D_LIGHT_QUAD_GRID_RADIUS_LIMIT               20.f
+00050 // Factor for a level to the next: size/=factor, eltSize*=factor, and radiusLimit*=factor.
+00051 #define NL3D_LIGHT_QUAD_GRID_FACTOR                             4
+00052 
+00053 
+00054 // this is a big radius for light that don't have attenuation
+00055 #define NL3D_DEFAULT_NOATT_LIGHT_RADIUS                                 1000.f
+00056 // this is used when the model is out of attBegin/attEnd, to modulate the influence
+00057 #define NL3D_DEFAULT_OUT_OF_ATT_LIGHT_INF_FACTOR                0.1f
+00058 // Defualt LightTransitionThreshold
+00059 #define NL3D_DEFAULT_LIGHT_TRANSITION_THRESHOLD                 0.1f
+00060 
+00061 
+00062 // ***************************************************************************
+00063 CLightingManager::CLightingManager()
+00064 {
+00065         // Init the lightQuadGrids and StaticLightedModelQuadGrid
+00066         // finer level.
+00067         uint    qgSize= NL3D_LIGHT_QUAD_GRID_SIZE;
+00068         float   eltSize= NL3D_LIGHT_QUAD_GRID_ELTSIZE;
+00069         float   radiusLimit= NL3D_LIGHT_QUAD_GRID_RADIUS_LIMIT;
+00070         // for all levels
+00071         for(uint i=0;i<NL3D_QUADGRID_LIGHT_NUM_LEVEL;i++)
+00072         {
+00073                 // init _LightQuadGrid and _StaticLightedModelQuadGrid
+00074                 _LightQuadGrid[i].create(qgSize, eltSize);
+00075                 _StaticLightedModelQuadGrid[i].create(qgSize, eltSize);
+00076                 _LightQuadGridRadiusLimit[i]= radiusLimit;
+00077 
+00078                 // coarser quadGrid level
+00079                 qgSize/= NL3D_LIGHT_QUAD_GRID_FACTOR;
+00080                 qgSize= max(qgSize, 1U);
+00081                 eltSize*= NL3D_LIGHT_QUAD_GRID_FACTOR;
+00082                 radiusLimit*= NL3D_LIGHT_QUAD_GRID_FACTOR;
+00083         }
+00084 
+00085 
+00086         // default paramters
+00087         _NoAttLightRadius= NL3D_DEFAULT_NOATT_LIGHT_RADIUS;
+00088         _OutOfAttLightInfFactor= NL3D_DEFAULT_OUT_OF_ATT_LIGHT_INF_FACTOR;
+00089         _LightTransitionThreshold= NL3D_DEFAULT_LIGHT_TRANSITION_THRESHOLD;
+00090 
+00091 
+00092         // Default number of pointLight on an object.
+00093         setMaxLightContribution(3);
+00094 }
+00095 
+00096 
+00097 // ***************************************************************************
+00098 void            CLightingManager::setMaxLightContribution(uint nlights)
+00099 {
+00100         _MaxLightContribution= min(nlights, (uint)NL3D_MAX_LIGHT_CONTRIBUTION);
+00101 }
+00102 
+00103 
+00104 // ***************************************************************************
+00105 void            CLightingManager::setNoAttLightRadius(float noAttLightRadius)
+00106 {
+00107         nlassert(noAttLightRadius>0);
+00108         _NoAttLightRadius= noAttLightRadius;
+00109 }
+00110 
+00111 
+00112 // ***************************************************************************
+00113 void            CLightingManager::setOutOfAttLightInfFactor(float outOfAttLightInfFactor)
+00114 {
+00115         outOfAttLightInfFactor= max(0.f, outOfAttLightInfFactor);
+00116         _OutOfAttLightInfFactor= outOfAttLightInfFactor;
+00117 }
+00118 
+00119 
+00120 // ***************************************************************************
+00121 void            CLightingManager::setLightTransitionThreshold(float lightTransitionThreshold)
+00122 {
+00123         clamp(lightTransitionThreshold, 0.f, 1.f);
+00124         _LightTransitionThreshold= lightTransitionThreshold;
+00125 }
+00126 
+00127 
+00128         
+00129 // ***************************************************************************
+00130 void            CLightingManager::clearDynamicLights()
+00131 {
+00132         // for all levels
+00133         for(uint i=0;i<NL3D_QUADGRID_LIGHT_NUM_LEVEL;i++)
+00134         {
+00135                 // clear all the lights in the quadGrid.
+00136                 _LightQuadGrid[i].clear();
+00137         }
+00138 
+00139         // clear the list.
+00140         _DynamicLightList.clear();
+00141 }
+00142 
+00143 // ***************************************************************************
+00144 void            CLightingManager::addDynamicLight(CPointLight *light)
+00145 {
+00146 
+00147         // Insert the light in the quadGrid.
+00148         //----------
+00149         CPointLightInfo         plInfo;
+00150         plInfo.Light= light;
+00151 
+00152         // build the bounding sphere for this light, with the AttenuationEnd of the light
+00153         float   radius=light->getAttenuationEnd();
+00154         // if attenuation is disabled (ie getAttenuationEnd() return 0), then have a dummy radius
+00155         if(radius==0)
+00156                 radius= _NoAttLightRadius;
+00157         plInfo.Sphere.Center= light->getPosition();
+00158         plInfo.Sphere.Radius= radius;
+00159 
+00160         // build a bbox, so it includes the sphere
+00161         CVector bbmin= light->getPosition();
+00162         bbmin-= CVector(radius, radius, radius);
+00163         CVector bbmax= light->getPosition();
+00164         bbmax+= CVector(radius, radius, radius);
+00165 
+00166         // choose the correct quadgrid according to the radius of the light.
+00167         uint qgId;
+00168         for(qgId= 0; qgId<NL3D_QUADGRID_LIGHT_NUM_LEVEL-1; qgId++)
+00169         {
+00170                 // if radius is inferior to the requested radius for this quadGrid, ok!
+00171                 if(radius<_LightQuadGridRadiusLimit[qgId])
+00172                         break;
+00173         }
+00174         // insert this light in the correct quadgrid.
+00175         _LightQuadGrid[qgId].insert(bbmin, bbmax, plInfo);
+00176 
+00177 
+00178         // touch the objects around the lights.
+00179         //----------
+00180 
+00181         // Select the static lightedModels to update around this light.
+00182         // Use the same level of _StaticLightedModelQuadGrid than me to not select too many squares in the quadGrid
+00183         _StaticLightedModelQuadGrid[qgId].select(bbmin, bbmax);
+00184         // For all those models.
+00185         CQuadGrid<CTransform*>::CIterator       itModel= _StaticLightedModelQuadGrid[qgId].begin();
+00186         while(itModel != _StaticLightedModelQuadGrid[qgId].end() )
+00187         {
+00188                 CTransform      *model= *itModel;
+00189                 const CVector &modelPos= model->getWorldMatrix().getPos();
+00190 
+00191                 // test first if this model is in the area of the light.
+00192                 if( plInfo.Sphere.include(modelPos) )
+00193                 {
+00194                         // yes, then this model must recompute his lighting, because a dynamic light touch him.
+00195                         model->resetLighting();
+00196                 }
+00197 
+00198                 // next.
+00199                 itModel++;
+00200         }
+00201 
+00202 
+00203         // insert the light in the list.
+00204         //----------
+00205         _DynamicLightList.push_back(light);
+00206 
+00207 }
+00208 
+00209 // ***************************************************************************
+00210 CLightingManager::CQGItLightedModel     CLightingManager::eraseStaticLightedModel(CQGItLightedModel ite)
+00211 {
+00212         // Erase the iterator for all levels
+00213         for(uint i=0;i<NL3D_QUADGRID_LIGHT_NUM_LEVEL;i++)
+00214         {
+00215                 // NB: it is possible here that the iterator is NULL (ie end()).
+00216                 _StaticLightedModelQuadGrid[i].erase(ite.QgItes[i]);
+00217         }
+00218 
+00219         // return end(), ie NULL iterators
+00220         return CQGItLightedModel();
+00221 }
+00222 
+00223 // ***************************************************************************
+00224 CLightingManager::CQGItLightedModel     CLightingManager::insertStaticLightedModel(CTransform *model)
+00225 {
+00226         CQGItLightedModel       ite;
+00227         const CVector &worldPos= model->getWorldMatrix().getPos();
+00228 
+00229         // Insert the models in all levels, because addDynamicLight() may choose the best suited level to select
+00230         for(uint i=0;i<NL3D_QUADGRID_LIGHT_NUM_LEVEL;i++)
+00231         {
+00232                 ite.QgItes[i]= _StaticLightedModelQuadGrid[i].insert(worldPos, worldPos, model);
+00233         }
+00234 
+00235         // return the iterator
+00236         return ite;
+00237 }
+00238 
+00239 
+00240 // ***************************************************************************
+00241 struct  CSortLight
+00242 {
+00243         CPointLight             *PointLight;
+00244         float                   Influence;
+00245 
+00246 };
+00247 
+00248 // ***************************************************************************
+00249 void            CLightingManager::computeModelLightContributions(CTransform *model, CLightContribution &lightContrib, 
+00250         ILogicInfo *logicInfo)
+00251 {
+00252         sint    i;
+00253 
+00254         // This is the list of light which touch this model.
+00255         static std::vector<CPointLightInfluence>        lightList;
+00256         // static, for malloc perf.
+00257         lightList.clear();
+00258 
+00259         // the position of the model.
+00260         CVector modelPos;
+00261         float   modelRadius;
+00262 
+00263         // get the untransformed bbox from the model.
+00264         CAABBox         bbox;
+00265         model->getAABBox(bbox);
+00266         // get transformed center pos of bbox
+00267         modelPos= model->getWorldMatrix() * bbox.getCenter();
+00268         // If the model is a big lightable, must take radius from aabbox, else suppose 0 radius.
+00269         if(model->isBigLightable())
+00270         {
+00271                 // get size of the bbox (bounding sphere)
+00272                 modelRadius= bbox.getRadius();
+00273         }
+00274         else
+00275         {
+00276                 // Assume 0 radius => faster computeLinearAttenuation()
+00277                 modelRadius= 0;
+00278         }
+00279 
+00280 
+00281         // First pass, fill the list of light which touch this model.
+00282         //=========
+00283         // get the dynamic lights around the model
+00284         getDynamicPointLightList(modelPos, lightList);
+00285 
+00286         // if not already precomputed, append staticLights to this list.
+00287         if( !lightContrib.FrozenStaticLightSetup )
+00288         {
+00289                 // If no logicInfo provided
+00290                 if(!logicInfo)
+00291                 {
+00292                         // Default: suppose full SunLight and no PointLights.
+00293                         lightContrib.SunContribution= 255;
+00294                         // Take full SunAmbient.
+00295                         lightContrib.LocalAmbient.set(0,0,0,0);
+00296                         // do not append any pointLight to the setup
+00297                 }
+00298                 else
+00299                 {
+00300                         // NB: SunContribution is computed by logicInfo
+00301                         logicInfo->getStaticLightSetup(lightList, lightContrib.SunContribution, lightContrib.LocalAmbient);
+00302                 }
+00303         }
+00304 
+00305         // Second pass, in the lightList, choose the best suited light to lit this model
+00306         //=========
+00307 
+00308         // for each light, modulate the factor of influence
+00309         for(i=0; i<(sint)lightList.size();i++)
+00310         {
+00311                 CPointLight     *pl= lightList[i].PointLight;
+00312 
+00313                 // get the distance from the light to the model
+00314                 float   dist= (pl->getPosition() - modelPos).norm();
+00315                 float   distMinusRadius= dist - modelRadius;
+00316 
+00317                 // modulate the factor by the distance and the attenuation distance.
+00318                 float    inf;
+00319                 float   attBegin= pl->getAttenuationBegin();
+00320                 float   attEnd= pl->getAttenuationEnd();
+00321                 // if no attenuation
+00322                 if( attEnd==0 )
+00323                 {
+00324                         // influence is awlays 1.
+00325                         inf= 1;
+00326 
+00327                         // If SpotLight, must modulate with SpotAttenuation.
+00328                         if(pl->getType() == CPointLight::SpotLight)
+00329                                 inf*= pl->computeLinearAttenuation(modelPos, dist, modelRadius);
+00330                 }
+00331                 else
+00332                 {
+00333                         // if correct attenuation radius
+00334                         if(distMinusRadius<attBegin)
+00335                         {
+00336                                 // NB: we are sure that attBegin>0, because dist>=0.
+00337                                 // if < attBegin, inf should be ==1, but must select the nearest lights; for better
+00338                                 // understanding of the scene
+00339                                 inf= 1 + _OutOfAttLightInfFactor * (attBegin - distMinusRadius);        // inf E [1, +oo[
+00340                                 // NB: this formula favour big lights (ie light with big attBegin).
+00341 
+00342                                 // If SpotLight, must modulate with SpotAttenuation.
+00343                                 if(pl->getType() == CPointLight::SpotLight)
+00344                                         inf*= pl->computeLinearAttenuation(modelPos, dist, modelRadius);
+00345                         }
+00346                         else if(distMinusRadius<attEnd)
+00347                         {
+00348                                 // we are sure attEnd-attBegin>0 because of the test
+00349                                 // compute influence of the light: attenuation and SpotAttenuation
+00350                                 inf= pl->computeLinearAttenuation(modelPos, dist, modelRadius);
+00351                         }
+00352                         else
+00353                         {
+00354                                 // if >= attEnd, inf should be ==0, but must select the nearest lights; for better
+00355                                 // understanding of the scene
+00356                                 inf= _OutOfAttLightInfFactor * (attEnd - distMinusRadius);              // inf E ]-oo, 0]
+00357                         }
+00358                 }
+00359 
+00360                 // modulate the influence with this factor
+00361                 lightList[i].BkupInfluence= lightList[i].Influence;
+00362                 lightList[i].Influence*= inf;
+00363 
+00364                 // Bkup distance to model.
+00365                 lightList[i].DistanceToModel= dist;
+00366         }
+00367 
+00368         // sort the light by influence
+00369         sort(lightList.begin(), lightList.end());
+00370 
+00371 
+00372         // and choose only max light.
+00373         uint    startId= 0;
+00374         uint    ligthSrcId= 0;
+00375         // skip already setuped light (statically)
+00376         if(lightContrib.FrozenStaticLightSetup)
+00377                 startId= lightContrib.NumFrozenStaticLight;
+00378 
+00379         // If there is still place for Dynamic lights.
+00380         if(startId < _MaxLightContribution)
+00381         {
+00382                 // setup the transition.
+00383                 float   deltaMinInfluence= _LightTransitionThreshold;
+00384                 float   minInfluence= 0;
+00385                 // If there is more light that we can accept, 
+00386                 if(lightList.size() > _MaxLightContribution-startId)
+00387                 {
+00388                         // the minInfluence is the influence of the first light not taken.
+00389                         minInfluence= lightList[_MaxLightContribution-startId].Influence;
+00390                         // but must still be >=0.
+00391                         minInfluence= max(minInfluence, 0.f);
+00392                 }
+00393                 // Any light under this minInfluence+deltaMinInfluence will be smoothly darken.
+00394                 float   minInfluenceStart = minInfluence + deltaMinInfluence;
+00395                 float   OOdeltaMinInfluencex255= 255.f / deltaMinInfluence;
+00396 
+00397                 // fill maxLight at max.
+00398                 for(i=startId;i<(sint)_MaxLightContribution; i++)
+00399                 {
+00400                         // if not so many pointLights found, end!!
+00401                         if(ligthSrcId>=lightList.size())
+00402                                 break;
+00403                         else
+00404                         {
+00405                                 CPointLight     *pl= lightList[ligthSrcId].PointLight;
+00406                                 float           inf= lightList[ligthSrcId].Influence;
+00407                                 float           bkupInf= lightList[ligthSrcId].BkupInfluence;
+00408                                 float           distToModel= lightList[ligthSrcId].DistanceToModel;
+00409                                 // else fill it.
+00410                                 lightContrib.PointLight[i]= pl;
+00411 
+00412                                 // Compute the Final factor of influence of the light.
+00413                                 if(inf >= minInfluenceStart)
+00414                                 {
+00415                                         // For Static LightSetup BiLinear to work correctly, modulate with BkupInfluence
+00416                                         // don't worry about the precision of floor, because of *255.
+00417                                         lightContrib.Factor[i]= (uint8)OptFastFloor(bkupInf*255);
+00418                                 }
+00419                                 else
+00420                                 {
+00421                                         float   f= (inf-minInfluence) * OOdeltaMinInfluencex255;
+00422                                         sint    fi;
+00423                                         // For Static LightSetup BiLinear to work correctly, modulate with BkupInfluence
+00424                                         // don't worry about the precision of floor, because of *255.
+00425                                         fi= OptFastFloor( bkupInf*f );
+00426                                         clamp(fi, 0, 255);
+00427                                         lightContrib.Factor[i]= fi;
+00428                                 }
+00429 
+00430                                 // Compute the Final Att factor for models using Global Attenuation. NB: modulate with Factor
+00431                                 // don't worry about the precision of floor, because of *255.
+00432                                 // NB: compute att on the center of the model => modelRadius==0
+00433                                 sint    attFactor= OptFastFloor( lightContrib.Factor[i] * pl->computeLinearAttenuation(modelPos, distToModel) );
+00434                                 lightContrib.AttFactor[i]= (uint8)attFactor;
+00435 
+00436                                 // must append this lightedModel to the list in the light.
+00437                                 lightContrib.TransformIterator[i]= pl->appendLightedModel(model);
+00438 
+00439                                 // next light.
+00440                                 ligthSrcId++;
+00441                         }
+00442                 }
+00443         }
+00444         else
+00445         {
+00446                 // point to end the list
+00447                 i= startId;
+00448         }
+00449 
+00450         // End the list.
+00451         if(i<NL3D_MAX_LIGHT_CONTRIBUTION)
+00452         {
+00453                 lightContrib.PointLight[i]= NULL;
+00454         }
+00455 
+00456 }
+00457 
+00458 
+00459 // ***************************************************************************
+00460 void            CLightingManager::getDynamicPointLightList(const CVector &worldPos, std::vector<CPointLightInfluence>   &lightList)
+00461 {
+00462         // For all quadGrids.
+00463         for(uint qgId=0; qgId<NL3D_QUADGRID_LIGHT_NUM_LEVEL; qgId++)
+00464         {
+00465                 CQuadGrid<CPointLightInfo>      &quadGrid= _LightQuadGrid[qgId];
+00466 
+00467                 // select the lights around this position in the quadGrids.
+00468                 quadGrid.select(worldPos, worldPos);
+00469 
+00470                 // for all possible found lights
+00471                 CQuadGrid<CPointLightInfo>::CIterator   itLight;
+00472                 for(itLight= quadGrid.begin(); itLight!=quadGrid.end(); itLight++)
+00473                 {
+00474                         // verify it includes the entity
+00475                         if( (*itLight).Sphere.include(worldPos) )
+00476                         {
+00477                                 // ok, insert in list.
+00478                                 CPointLightInfluence    pli;
+00479                                 pli.PointLight= (*itLight).Light;
+00480                                 // No special Influence degradation scheme for Dynamic lighting
+00481                                 pli.Influence= 1;
+00482                                 lightList.push_back( pli );
+00483                         }
+00484                 }
+00485         }
+00486 }
+00487 
+00488 
+00489 
+00490 } // NL3D
+
+ + +
                                                                                                                                                                    +
+ + -- cgit v1.2.1