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/instance__lighter_8cpp-source.html | 1916 ++++++++++++++++++++ 1 file changed, 1916 insertions(+) create mode 100644 docs/doxygen/nel/instance__lighter_8cpp-source.html (limited to 'docs/doxygen/nel/instance__lighter_8cpp-source.html') diff --git a/docs/doxygen/nel/instance__lighter_8cpp-source.html b/docs/doxygen/nel/instance__lighter_8cpp-source.html new file mode 100644 index 00000000..c5e2b885 --- /dev/null +++ b/docs/doxygen/nel/instance__lighter_8cpp-source.html @@ -0,0 +1,1916 @@ + + + + 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  
+

instance_lighter.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/instance_lighter.h"
+00029 #include "3d/mesh_multi_lod.h"
+00030 #include "nel/misc/file.h"
+00031 #include "nel/misc/path.h"
+00032 #include "3d/visual_collision_manager.h"
+00033 #include "3d/visual_collision_entity.h"
+00034 #include "3d/ig_surface_light_build.h"
+00035 
+00036 
+00037 using namespace std;
+00038 using namespace NLMISC;
+00039 
+00040 namespace NL3D {
+00041 
+00042 
+00043 // Bad coded: don't set too big else it allocates too much memory.
+00044 #define NL3D_INSTANCE_LIGHTER_CUBE_GRID_SIZE    16
+00045 
+00046 
+00047 // ***************************************************************************
+00048 // ***************************************************************************
+00049 // Setup part
+00050 // ***************************************************************************
+00051 // ***************************************************************************
+00052 
+00053 
+00054 // ***************************************************************************
+00055 CInstanceLighter::CLightDesc::CLightDesc ()
+00056 {
+00057         LightDirection.set (1, 1, -1);
+00058         GridSize=512;
+00059         GridCellSize=4;
+00060         Shadow= true;
+00061         OverSampling= 0;
+00062         DisableSunContribution= false;
+00063 }
+00064 
+00065 // ***************************************************************************
+00066 CInstanceLighter::CInstanceLighter()
+00067 {
+00068         _IGSurfaceLightBuild= NULL;
+00069 }
+00070 
+00071 // ***************************************************************************
+00072 void CInstanceLighter::init ()
+00073 {
+00074 }
+00075 
+00076 // ***************************************************************************
+00077 void CInstanceLighter::addTriangles (CLandscape &landscape, std::vector<uint> &listZone, uint order, std::vector<CTriangle>& triangleArray)
+00078 {
+00079         // Lamed from CZoneLighter.
+00080         // Set all to refine
+00081         excludeAllPatchFromRefineAll (landscape, listZone, false);
+00082 
+00083         // Setup the landscape
+00084         landscape.setThreshold (0);
+00085         landscape.setTileMaxSubdivision (order);
+00086 
+00087         // Refine it
+00088         landscape.refineAll (CVector (0, 0, 0));
+00089 
+00090         // Dump tesselated triangles
+00091         std::vector<const CTessFace*> leaves;
+00092         landscape.getTessellationLeaves(leaves);
+00093 
+00094         // Number of leaves
+00095         uint leavesCount=leaves.size();
+00096 
+00097         // Reserve the array
+00098         triangleArray.reserve (triangleArray.size()+leavesCount);
+00099 
+00100         // Scan each leaves
+00101         for (uint leave=0; leave<leavesCount; leave++)
+00102         {
+00103                 // Leave
+00104                 const CTessFace *face=leaves[leave];
+00105 
+00106                 // Add a triangle. -1 because not an instance from an IG
+00107                 triangleArray.push_back (CTriangle (NLMISC::CTriangle (face->VBase->EndPos, face->VLeft->EndPos, face->VRight->EndPos), -1 ));
+00108         }
+00109 
+00110         // Setup the landscape
+00111         landscape.setThreshold (1000);
+00112         landscape.setTileMaxSubdivision (0);
+00113 
+00114         // Remove all triangles
+00115         landscape.refineAll (CVector (0, 0, 0));
+00116         landscape.refineAll (CVector (0, 0, 0));
+00117         landscape.refineAll (CVector (0, 0, 0));
+00118         landscape.refineAll (CVector (0, 0, 0));
+00119         landscape.refineAll (CVector (0, 0, 0));
+00120         landscape.refineAll (CVector (0, 0, 0));
+00121         landscape.refineAll (CVector (0, 0, 0));
+00122         landscape.refineAll (CVector (0, 0, 0));
+00123         landscape.refineAll (CVector (0, 0, 0));
+00124         landscape.refineAll (CVector (0, 0, 0));
+00125 
+00126 }
+00127 
+00128 // ***************************************************************************
+00129 void CInstanceLighter::addTriangles (const IShape &shape, const NLMISC::CMatrix& modelMT, std::vector<CTriangle>& triangleArray, sint instanceId)
+00130 {
+00131         // Lamed from CZoneLighter.
+00132 
+00133         // Cast to CMesh
+00134         const CMesh *mesh=dynamic_cast<const CMesh*>(&shape);
+00135 
+00136         // Cast to CMeshMultiLod
+00137         const CMeshMultiLod *meshMulti=dynamic_cast<const CMeshMultiLod*>(&shape);
+00138 
+00139         // Cast to CMeshMultiLod
+00140         const CMeshMRM *meshMRM=dynamic_cast<const CMeshMRM*>(&shape);
+00141 
+00142         // It is a mesh ?
+00143         if (mesh)
+00144         {
+00145                 // Add its triangles
+00146                 addTriangles (mesh->getMeshGeom (), modelMT, triangleArray, instanceId);
+00147         }
+00148         // It is a CMeshMultiLod ?
+00149         else if (meshMulti)
+00150         {
+00151                 // Get the first geommesh
+00152                 const IMeshGeom *meshGeom=&meshMulti->getMeshGeom (0);
+00153 
+00154                 // Dynamic cast
+00155                 const CMeshGeom *geomMesh=dynamic_cast<const CMeshGeom*>(meshGeom);
+00156                 if (geomMesh)
+00157                 {
+00158                         addTriangles (*geomMesh, modelMT, triangleArray, instanceId);
+00159                 }
+00160 
+00161                 // Dynamic cast
+00162                 const CMeshMRMGeom *mrmGeomMesh=dynamic_cast<const CMeshMRMGeom*>(meshGeom);
+00163                 if (mrmGeomMesh)
+00164                 {
+00165                         addTriangles (*mrmGeomMesh, modelMT, triangleArray, instanceId);
+00166                 }
+00167         }
+00168         // It is a CMeshMultiLod ?
+00169         else if (meshMRM)
+00170         {
+00171                 // Get the first lod mesh geom
+00172                 addTriangles (meshMRM->getMeshGeom (), modelMT, triangleArray, instanceId);
+00173         }
+00174 }
+00175 
+00176 
+00177 // ***************************************************************************
+00178 
+00179 void CInstanceLighter::addTriangles (const CMeshGeom &meshGeom, const CMatrix& modelMT, std::vector<CTriangle>& triangleArray, sint instanceId)
+00180 {
+00181         // Get the vertex buffer
+00182         const CVertexBuffer &vb=meshGeom.getVertexBuffer();
+00183 
+00184         // For each matrix block
+00185         uint numBlock=meshGeom.getNbMatrixBlock();
+00186         for (uint block=0; block<numBlock; block++)
+00187         {
+00188                 // For each render pass
+00189                 uint numRenderPass=meshGeom.getNbRdrPass(block);
+00190                 for (uint pass=0; pass<numRenderPass; pass++)
+00191                 {
+00192                         // Get the primitive block
+00193                         const CPrimitiveBlock &primitive=meshGeom.getRdrPassPrimitiveBlock ( block, pass);
+00194 
+00195                         // Dump triangles
+00196                         const uint32* triIndex=primitive.getTriPointer ();
+00197                         uint numTri=primitive.getNumTri ();
+00198                         uint tri;
+00199                         for (tri=0; tri<numTri; tri++)
+00200                         {
+00201                                 // Vertex
+00202                                 CVector v0=modelMT*(*(CVector*)vb.getVertexCoordPointer (triIndex[tri*3]));
+00203                                 CVector v1=modelMT*(*(CVector*)vb.getVertexCoordPointer (triIndex[tri*3+1]));
+00204                                 CVector v2=modelMT*(*(CVector*)vb.getVertexCoordPointer (triIndex[tri*3+2]));
+00205 
+00206                                 // Make a triangle
+00207                                 triangleArray.push_back (CTriangle (NLMISC::CTriangle (v0, v1, v2), instanceId));
+00208                         }
+00209 
+00210                         // Dump quad
+00211                         triIndex=primitive.getQuadPointer ();
+00212                         numTri=primitive.getNumQuad ();
+00213                         for (tri=0; tri<numTri; tri++)
+00214                         {
+00215                                 // Vertex
+00216                                 CVector v0=modelMT*(*(CVector*)vb.getVertexCoordPointer (triIndex[tri*4]));
+00217                                 CVector v1=modelMT*(*(CVector*)vb.getVertexCoordPointer (triIndex[tri*4+1]));
+00218                                 CVector v2=modelMT*(*(CVector*)vb.getVertexCoordPointer (triIndex[tri*4+2]));
+00219                                 CVector v3=modelMT*(*(CVector*)vb.getVertexCoordPointer (triIndex[tri*4+3]));
+00220 
+00221                                 // Make 2 triangles
+00222                                 triangleArray.push_back (CTriangle (NLMISC::CTriangle (v0, v1, v2), instanceId));
+00223                                 triangleArray.push_back (CTriangle (NLMISC::CTriangle (v0, v2, v3), instanceId));
+00224                         }
+00225                 }
+00226         }
+00227 }
+00228 
+00229 // ***************************************************************************
+00230 
+00231 void CInstanceLighter::addTriangles (const CMeshMRMGeom &meshGeom, const CMatrix& modelMT, std::vector<CTriangle>& triangleArray, sint instanceId)
+00232 {
+00233         // Get the vertex buffer
+00234         const CVertexBuffer &vb=meshGeom.getVertexBuffer();
+00235 
+00236         // For each render pass
+00237         uint numRenderPass=meshGeom.getNbRdrPass(0);
+00238         for (uint pass=0; pass<numRenderPass; pass++)
+00239         {
+00240                 // Get the primitive block
+00241                 const CPrimitiveBlock &primitive=meshGeom.getRdrPassPrimitiveBlock ( 0, pass);
+00242 
+00243                 // Dump triangles
+00244                 const uint32* triIndex=primitive.getTriPointer ();
+00245                 uint numTri=primitive.getNumTri ();
+00246                 uint tri;
+00247                 for (tri=0; tri<numTri; tri++)
+00248                 {
+00249                         // Vertex
+00250                         CVector v0=modelMT*(*(CVector*)vb.getVertexCoordPointer (triIndex[tri*3]));
+00251                         CVector v1=modelMT*(*(CVector*)vb.getVertexCoordPointer (triIndex[tri*3+1]));
+00252                         CVector v2=modelMT*(*(CVector*)vb.getVertexCoordPointer (triIndex[tri*3+2]));
+00253 
+00254                         // Make a triangle
+00255                         triangleArray.push_back (CTriangle (NLMISC::CTriangle (v0, v1, v2), instanceId));
+00256                 }
+00257 
+00258                 // Dump quad
+00259                 triIndex=primitive.getQuadPointer ();
+00260                 numTri=primitive.getNumQuad ();
+00261                 for (tri=0; tri<numTri; tri++)
+00262                 {
+00263                         // Vertex
+00264                         CVector v0=modelMT*(*(CVector*)vb.getVertexCoordPointer (triIndex[tri*4]));
+00265                         CVector v1=modelMT*(*(CVector*)vb.getVertexCoordPointer (triIndex[tri*4+1]));
+00266                         CVector v2=modelMT*(*(CVector*)vb.getVertexCoordPointer (triIndex[tri*4+2]));
+00267                         CVector v3=modelMT*(*(CVector*)vb.getVertexCoordPointer (triIndex[tri*4+3]));
+00268 
+00269                         // Make 2 triangles
+00270                         triangleArray.push_back (CTriangle (NLMISC::CTriangle (v0, v1, v2), instanceId));
+00271                         triangleArray.push_back (CTriangle (NLMISC::CTriangle (v0, v2, v3), instanceId));
+00272                 }
+00273         }
+00274 }
+00275 
+00276 // ***************************************************************************
+00277 
+00278 void CInstanceLighter::excludeAllPatchFromRefineAll (CLandscape &landscape, vector<uint> &listZone, bool exclude)
+00279 {
+00280         // For each zone
+00281         for (uint zone=0; zone<listZone.size(); zone++)
+00282         {
+00283                 // Get num patches
+00284                 uint patchCount=landscape.getZone(listZone[zone])->getNumPatchs();
+00285 
+00286                 // For each patches
+00287                 for (uint patch=0; patch<patchCount; patch++)
+00288                 {
+00289                         // Exclude all the patches from refine all
+00290                         landscape.excludePatchFromRefineAll (listZone[zone], patch, exclude);
+00291                 }
+00292         }
+00293 }
+00294 
+00295 
+00296 // ***************************************************************************
+00297 // ***************************************************************************
+00298 // light part
+00299 // ***************************************************************************
+00300 // ***************************************************************************
+00301 
+00302 
+00303 
+00304 // ***************************************************************************
+00305 void CInstanceLighter::light (const CInstanceGroup &igIn, CInstanceGroup &igOut, const CLightDesc &lightDesc, 
+00306         std::vector<CTriangle>& obstacles, CLandscape *landscape, CIGSurfaceLightBuild *igSurfaceLightBuild)
+00307 {
+00308         sint                                    i;
+00309         CVector                                 outGlobalPos;
+00310         std::vector<CCluster>   outClusters;
+00311         std::vector<CPortal>    outPortals;
+00312         std::vector<CPointLightNamed>   pointLightList;
+00313 
+00314         nlassert(lightDesc.OverSampling==0 || lightDesc.OverSampling==2 || lightDesc.OverSampling==4
+00315                 || lightDesc.OverSampling==8 || lightDesc.OverSampling==16);
+00316 
+00317         // Setup.
+00318         //========
+00319 
+00320         // Prepare IGSurfaceLight lighting
+00321         //-----------
+00322         // Bkup SurfaceLightBuild to know if must light the surfaces, in differents part of the process.
+00323         _IGSurfaceLightBuild= igSurfaceLightBuild;
+00324         // Prepare _IGRetrieverGridMap.
+00325         _IGRetrieverGridMap.clear();
+00326         if(_IGSurfaceLightBuild)
+00327         {
+00328                 _TotalCellNumber= 0;
+00329                 CIGSurfaceLightBuild::ItRetrieverGridMap        itSrc;
+00330                 itSrc= _IGSurfaceLightBuild->RetrieverGridMap.begin();
+00331                 // For all retrievers Infos in _IGSurfaceLightBuild
+00332                 while(itSrc!=_IGSurfaceLightBuild->RetrieverGridMap.end())
+00333                 {
+00334                         uint    numSurfaces= itSrc->second.Grids.size();
+00335                         // If !empty retriever.
+00336                         if(numSurfaces>0)
+00337                         {
+00338                                 // Add it to the map, 
+00339                                 CIGSurfaceLight::CRetrieverLightGrid            &rlgDst= _IGRetrieverGridMap[itSrc->first];
+00340                                 // resize Array of surfaces.
+00341                                 rlgDst.Grids.resize(numSurfaces);
+00342                                 // For all surfaces, init them in rlgDst.
+00343                                 for(uint i=0; i<numSurfaces; i++)
+00344                                 {
+00345                                         CIGSurfaceLightBuild::CSurface          &surfSrc= itSrc->second.Grids[i];
+00346                                         CSurfaceLightGrid                                       &surfDst= rlgDst.Grids[i];
+00347                                         // Init Cells with a default CellCorner
+00348                                         CSurfaceLightGrid::CCellCorner          defaultCellCorner;
+00349                                         defaultCellCorner.SunContribution= 0;
+00350                                         defaultCellCorner.Light[0]= 0xFF;
+00351                                         defaultCellCorner.LocalAmbientId= 0xFF;
+00352                                         
+00353                                         // Init the grid.
+00354                                         surfDst.Origin= surfSrc.Origin;
+00355                                         surfDst.Width= surfSrc.Width;
+00356                                         surfDst.Height= surfSrc.Height;
+00357                                         surfDst.Cells.resize(surfSrc.Cells.size());
+00358                                         surfDst.Cells.fill(defaultCellCorner);
+00359                                         // The grid must be valid an not empty
+00360                                         nlassert( surfDst.Cells.size() == surfDst.Width*surfDst.Height );
+00361                                         nlassert( surfDst.Width>= 2 );
+00362                                         nlassert( surfDst.Height>= 2 );
+00363 
+00364                                         _TotalCellNumber+= surfDst.Cells.size();
+00365                                 }
+00366                         }
+00367 
+00368                         // Next localRetriever info.
+00369                         itSrc++;
+00370                 }
+00371         }
+00372         // Reset cell iteration.
+00373         _IsEndCell= true;
+00374 
+00375 
+00376         // Retrieve info from igIn.
+00377         //-----------
+00378         igIn.retrieve (outGlobalPos, _Instances, outClusters, outPortals, pointLightList);
+00379 
+00380 
+00381         // set All Instances StaticLightEnabled= true, and Build _InstanceInfos.
+00382         //-----------
+00383         // Map of shape
+00384         std::map<string, IShape*> shapeMap;
+00385         _InstanceInfos.resize(_Instances.size());
+00386         for(i=0; i<(sint)_Instances.size();i++)
+00387         {
+00388                 // Avoid StaticLight precomputing??
+00389                 if(_Instances[i].AvoidStaticLightPreCompute)
+00390                 {
+00391                         _Instances[i].StaticLightEnabled= false;
+00392                         // Next instance.
+00393                         continue;
+00394                 }
+00395 
+00396                 // Else let's do it.
+00397                 _Instances[i].StaticLightEnabled= true;
+00398 
+00399 
+00400                 // Get the shape centerPos;
+00401                 //------------
+00402                 CVector shapeCenterPos;
+00403                 CVector overSamples[MaxOverSamples];
+00404 
+00405                 // Get the instance shape name
+00406                 string name= _Instances[i].Name;
+00407                 bool    shapeFound= true;
+00408 
+00409                 // Try to find the shape in the UseShapeMap.
+00410                 std::map<string, IShape*>::const_iterator iteMap= lightDesc.UserShapeMap.find (name);
+00411 
+00412                 // If not found in userShape map, try to load it from the temp loaded ShapeBank.
+00413                 if( iteMap == lightDesc.UserShapeMap.end() )
+00414                 {
+00415                         // Add a .shape at the end ?
+00416                         if (name.find('.') == std::string::npos)
+00417                                 name += ".shape";
+00418 
+00419                         // Get the instance shape name
+00420                         string nameLookup = CPath::lookup (name, false, false);
+00421                         if (!nameLookup.empty())
+00422                                 name = nameLookup;
+00423 
+00424                         // Find the shape in the bank
+00425                         iteMap= shapeMap.find (name);
+00426                         if (iteMap==shapeMap.end())
+00427                         {
+00428                                 // Input file
+00429                                 CIFile inputFile;
+00430 
+00431                                 if (!name.empty() && inputFile.open (name))
+00432                                 {
+00433                                         // Load it
+00434                                         CShapeStream stream;
+00435                                         stream.serial (inputFile);
+00436 
+00437                                         // Get the pointer
+00438                                         iteMap=shapeMap.insert (std::map<string, IShape*>::value_type (name, stream.getShapePointer ())).first;
+00439                                 }
+00440                                 else
+00441                                 {
+00442                                         // Error
+00443                                         nlwarning ("WARNING can't load shape %s\n", name.c_str());
+00444                                         shapeFound= false;
+00445                                 }
+00446                         }
+00447                 }
+00448 
+00449 
+00450                 // Last chance to skip it: fully LightMapped ??
+00451                 //-----------
+00452                 if(shapeFound)
+00453                 {
+00454                         CMeshBase       *mesh= dynamic_cast<CMeshBase*>(iteMap->second);
+00455                         if(mesh)
+00456                         {
+00457                                 // If this mesh is not lightable (fully lightMapped)
+00458                                 if(!mesh->isLightable())
+00459                                 {
+00460                                         // Force Avoid StaticLight precomputing
+00461                                         _Instances[i].AvoidStaticLightPreCompute= true;
+00462                                         // Disable static lighting.
+00463                                         _Instances[i].StaticLightEnabled= false;
+00464                                         // Next instance.
+00465                                         continue;
+00466                                 }
+00467                         }
+00468                 }
+00469 
+00470 
+00471                 // Compute pos and OverSamples
+00472                 //-----------
+00473                 {
+00474                         // Compute bbox, or default bbox
+00475                         CAABBox         bbox;
+00476                         if(!shapeFound)
+00477                         {
+00478                                 bbox.setCenter(CVector::Null);
+00479                                 bbox.setHalfSize(CVector::Null);
+00480                         }
+00481                         else
+00482                         {
+00483                                 iteMap->second->getAABBox(bbox);
+00484                         }
+00485                         // get pos
+00486                         shapeCenterPos= bbox.getCenter();
+00487 
+00488 
+00489                         // Compute overSamples
+00490                         float   qx= bbox.getHalfSize().x/2;
+00491                         float   qy= bbox.getHalfSize().y/2;
+00492                         float   qz= bbox.getHalfSize().z/2;
+00493                         // No OverSampling => just copy.
+00494                         if(lightDesc.OverSampling==0)
+00495                                 overSamples[0]= shapeCenterPos;
+00496                         else if(lightDesc.OverSampling==2)
+00497                         {
+00498                                 // Prefer Z Axis.
+00499                                 overSamples[0]= shapeCenterPos + CVector(0, 0, qz);
+00500                                 overSamples[1]= shapeCenterPos - CVector(0, 0, qz);
+00501                         }
+00502                         else if(lightDesc.OverSampling==4)
+00503                         {
+00504                                 // Apply an overSampling such that we see 4 points if we look on each side of the bbox.
+00505                                 overSamples[0]= shapeCenterPos + CVector(-qx, -qy, -qz);
+00506                                 overSamples[1]= shapeCenterPos + CVector(+qx, -qy, +qz);
+00507                                 overSamples[2]= shapeCenterPos + CVector(-qx, +qy, +qz);
+00508                                 overSamples[3]= shapeCenterPos + CVector(+qx, +qy, -qz);
+00509                         }
+00510                         else if(lightDesc.OverSampling==8 || lightDesc.OverSampling==16)
+00511                         {
+00512                                 // 8x is the best overSampling shceme for bbox
+00513                                 overSamples[0]= shapeCenterPos + CVector(-qx, -qy, -qz);
+00514                                 overSamples[1]= shapeCenterPos + CVector(+qx, -qy, -qz);
+00515                                 overSamples[2]= shapeCenterPos + CVector(-qx, +qy, -qz);
+00516                                 overSamples[3]= shapeCenterPos + CVector(+qx, +qy, -qz);
+00517                                 overSamples[4]= shapeCenterPos + CVector(-qx, -qy, +qz);
+00518                                 overSamples[5]= shapeCenterPos + CVector(+qx, -qy, +qz);
+00519                                 overSamples[6]= shapeCenterPos + CVector(-qx, +qy, +qz);
+00520                                 overSamples[7]= shapeCenterPos + CVector(+qx, +qy, +qz);
+00521 
+00522                                 // 16x => use this setup, and decal from 1/8
+00523                                 if(lightDesc.OverSampling==16)
+00524                                 {
+00525                                         CVector         decal(qx/2, qy/2, qz/2);
+00526                                         for(uint sample=0; sample<8; sample++)
+00527                                         {
+00528                                                 // Copy and decal
+00529                                                 overSamples[sample+8]= overSamples[sample] + decal;
+00530                                                 // neg decal me
+00531                                                 overSamples[sample]-= decal;
+00532                                         }
+00533                                 }
+00534                         }
+00535                 }
+00536 
+00537 
+00538                 // Compute pos of the instance
+00539                 //------------
+00540                 CMatrix         matInst;
+00541                 matInst.setPos(_Instances[i].Pos);
+00542                 matInst.setRot(_Instances[i].Rot);
+00543                 matInst.scale(_Instances[i].Scale);
+00544                 _InstanceInfos[i].CenterPos= matInst * shapeCenterPos;
+00545                 // Apply matInst to samples.
+00546                 uint    nSamples= max(1U, lightDesc.OverSampling);
+00547                 for(uint sample=0; sample<nSamples; sample++)
+00548                 {
+00549                         _InstanceInfos[i].OverSamples[sample]= matInst * overSamples[sample];
+00550                 }
+00551         }
+00552 
+00553         // Clean Up shapes.
+00554         //-----------
+00555         std::map<string, IShape*>::iterator iteMap;
+00556         iteMap= shapeMap.begin();
+00557         while(iteMap!= shapeMap.end())
+00558         {
+00559                 // delte shape
+00560                 delete  iteMap->second;
+00561                 // delete entry in map
+00562                 shapeMap.erase(iteMap);
+00563                 // next
+00564                 iteMap= shapeMap.begin();
+00565         }
+00566 
+00567         // Build all obstacles plane.
+00568         //-----------
+00569         for(i=0; i<(sint)obstacles.size();i++)
+00570         {
+00571                 CInstanceLighter::CTriangle& triangle=obstacles[i];
+00572                 // Calc the plane
+00573                 triangle.Plane.make (triangle.Triangle.V0, triangle.Triangle.V1, triangle.Triangle.V2);
+00574         }
+00575 
+00576 
+00577         // Lighting
+00578         //========
+00579         // Light With Sun: build the grid, and do it on all _Instances, using _InstanceInfos
+00580         // Compute also Lighting on surface.
+00581         computeSunContribution(lightDesc, obstacles, landscape);
+00582 
+00583         // Light With PointLights
+00584         // build the cubeGrids
+00585         compilePointLightRT(lightDesc.GridSize, lightDesc.GridCellSize, obstacles, lightDesc.Shadow);
+00586         // kill pointLightList, because will use mine.
+00587         pointLightList.clear();
+00588         // Light for all _Instances, using _InstanceInfos
+00589         // Compute also Lighting on surface.
+00590         processIGPointLightRT(pointLightList);
+00591 
+00592         // If _IGSurfaceLightBuild, then dilate lighting
+00593         if(_IGSurfaceLightBuild)
+00594         {
+00595                 dilateLightingOnSurfaceCells();
+00596         }
+00597 
+00598 
+00599         // Build result.
+00600         //========
+00601         if(_IGSurfaceLightBuild)
+00602         {
+00603                 // build with IGSurfaceLight lighting
+00604                 igOut.build(outGlobalPos, _Instances, outClusters, outPortals, pointLightList, 
+00605                         &_IGRetrieverGridMap, _IGSurfaceLightBuild->CellSize);
+00606         }
+00607         else
+00608         {
+00609                 // build without IGSurfaceLight lighting
+00610                 igOut.build(outGlobalPos, _Instances, outClusters, outPortals, pointLightList);
+00611         }
+00612 
+00613 }
+00614 
+00615 
+00616 // ***************************************************************************
+00617 static void NEL3DCalcBase (CVector &direction, CMatrix& matrix)
+00618 {
+00619         direction.normalize();
+00620         CVector         I=(fabs(direction*CVector(1.f,0,0))>0.99)?CVector(0.f,1.f,0.f):CVector(1.f,0.f,0.f);
+00621         CVector         K=-direction;
+00622         CVector         J=K^I;
+00623         J.normalize();
+00624         I=J^K;
+00625         I.normalize();
+00626         matrix.identity();
+00627         matrix.setRot(I,J,K, true);
+00628 }
+00629 
+00630 
+00631 
+00632 // ***************************************************************************
+00633 void    CInstanceLighter::computeSunContribution(const CLightDesc &lightDesc, std::vector<CTriangle>& obstacles, CLandscape *landscape)
+00634 {
+00635         sint    i;
+00636         // Use precoputed landscape SunContribution
+00637         CVisualCollisionManager         *VCM= NULL;
+00638         CVisualCollisionEntity          *VCE= NULL;
+00639         if(landscape)
+00640         {
+00641                 // create a CVisualCollisionManager and a CVisualCollisionEntity
+00642                 VCM= new CVisualCollisionManager;
+00643                 VCM->setLandscape(landscape);
+00644                 VCE= VCM->createEntity();
+00645         }
+00646         std::vector<CPointLightInfluence>       dummyPointLightFromLandscape;
+00647         dummyPointLightFromLandscape.reserve(1024);
+00648 
+00649 
+00650         // If DisableSunContribution, easy, 
+00651         if(lightDesc.DisableSunContribution)
+00652         {
+00653                 // Light all instances.
+00654                 //==========
+00655                 for(i=0; i<(sint)_Instances.size(); i++)
+00656                 {
+00657                         // If staticLight not enabled, skip.
+00658                         if( !_Instances[i].StaticLightEnabled )
+00659                                 continue;
+00660 
+00661                         // fill SunContribution to 0
+00662                         _Instances[i].SunContribution= 0;
+00663                 }
+00664 
+00665                 // Light SurfaceGrid Cells.
+00666                 //==========
+00667                 if(_IGSurfaceLightBuild)
+00668                 {
+00669                         // Begin cell iteration
+00670                         beginCell();
+00671                         // For all surface cell corners
+00672                         while( !isEndCell() )
+00673                         {
+00674                                 // get the current cell and cellInfo iterated.
+00675                                 CIGSurfaceLightBuild::CCellCorner       &cellInfo= getCurrentCellInfo();
+00676                                 CSurfaceLightGrid::CCellCorner          &cell= getCurrentCell();
+00677 
+00678                                 // if the cell corner lies in the polygon surface.
+00679                                 if(cellInfo.InSurface)
+00680                                 {
+00681                                         // fill SunContribution to 0
+00682                                         cell.SunContribution= 0;
+00683                                         // copy it to cellInfo
+00684                                         cellInfo.SunContribution= cell.SunContribution;
+00685                                 }
+00686 
+00687                                 // next cell
+00688                                 nextCell();
+00689                         }
+00690                 }
+00691         }
+00692         // If no Raytrace Shadow, easy, 
+00693         else if(!lightDesc.Shadow)
+00694         {
+00695                 // Light all instances.
+00696                 //==========
+00697                 for(i=0; i<(sint)_Instances.size(); i++)
+00698                 {
+00699                         progress ("Compute SunContribution on Instances", i / float(_Instances.size()) );
+00700 
+00701                         // If staticLight not enabled, skip.
+00702                         if( !_Instances[i].StaticLightEnabled )
+00703                                 continue;
+00704 
+00705                         // by default, fill SunContribution to 255
+00706                         _Instances[i].SunContribution= 255;
+00707                         // Try to get landscape SunContribution (better)
+00708                         if(landscape)
+00709                         {
+00710                                 CVector         pos= _InstanceInfos[i].CenterPos;
+00711                                 uint8   landSunContribution;
+00712                                 dummyPointLightFromLandscape.clear();
+00713                                 // If find faces under me
+00714                                 NLMISC::CRGBA   dummyAmbient;
+00715                                 if(VCE->getStaticLightSetup(pos, dummyPointLightFromLandscape, landSunContribution, dummyAmbient) )
+00716                                 {
+00717                                         _Instances[i].SunContribution= landSunContribution;
+00718                                 }
+00719                         }
+00720                 }
+00721 
+00722                 // Light SurfaceGrid Cells.
+00723                 //==========
+00724                 if(_IGSurfaceLightBuild)
+00725                 {
+00726                         // Begin cell iteration
+00727                         beginCell();
+00728                         // For all surface cell corners
+00729                         while( !isEndCell() )
+00730                         {
+00731                                 progressCell("Compute SunContribution on Surfaces");
+00732 
+00733                                 // get the current cell and cellInfo iterated.
+00734                                 CIGSurfaceLightBuild::CCellCorner       &cellInfo= getCurrentCellInfo();
+00735                                 CSurfaceLightGrid::CCellCorner          &cell= getCurrentCell();
+00736 
+00737                                 // if the cell corner lies in the polygon surface.
+00738                                 if(cellInfo.InSurface)
+00739                                 {
+00740                                         // Just init SunContribution to 255, since no shadowing.
+00741                                         cell.SunContribution= 255;
+00742                                         // copy it to cellInfo
+00743                                         cellInfo.SunContribution= cell.SunContribution;
+00744                                 }
+00745 
+00746                                 // next cell
+00747                                 nextCell();
+00748                         }
+00749                 }
+00750         }
+00751         else
+00752         {
+00753                 // Compute rayBasis
+00754                 CVector rayDir= lightDesc.LightDirection;
+00755                 CMatrix rayBasis;
+00756                 rayDir.normalize();
+00757                 NEL3DCalcBase(rayDir, rayBasis);
+00758                 CMatrix invRayBasis;
+00759                 invRayBasis= rayBasis.inverted();
+00760 
+00761                 // Build QuadGrid of obstacles.
+00762                 //=========
+00763                 // setup quadGrid
+00764                 CQuadGrid<const CTriangle*>             quadGrid;
+00765                 quadGrid.changeBase (invRayBasis);
+00766                 quadGrid.create(lightDesc.GridSize, lightDesc.GridCellSize);
+00767                 // Insert all obstacles in quadGrid
+00768                 for(i=0; i<(sint)obstacles.size(); i++)
+00769                 {
+00770                         CAABBox triBBox;
+00771                         // Compute the bbox in rayBasis.
+00772                         triBBox.setCenter(invRayBasis * obstacles[i].Triangle.V0);
+00773                         triBBox.extend(invRayBasis * obstacles[i].Triangle.V1);
+00774                         triBBox.extend(invRayBasis * obstacles[i].Triangle.V2);
+00775                         // And set the coord in our world, because will be multiplied with invRayBasis in insert()
+00776                         quadGrid.insert(rayBasis * triBBox.getMin(), rayBasis * triBBox.getMax(), &obstacles[i]);
+00777                 }
+00778 
+00779                 // For all instances, light them.
+00780                 //=========
+00781                 for(i=0; i<(sint)_Instances.size(); i++)
+00782                 {
+00783                         progress ("Compute SunContribution on Instances", i / float(_Instances.size()) );
+00784 
+00785                         // If staticLight not enabled, skip.
+00786                         if( !_Instances[i].StaticLightEnabled )
+00787                                 continue;
+00788 
+00789                         // try to use landscape SunContribution.
+00790                         bool    landUsed= false;
+00791                         if(landscape)
+00792                         {
+00793                                 CVector         pos= _InstanceInfos[i].CenterPos;
+00794                                 uint8   landSunContribution;
+00795                                 dummyPointLightFromLandscape.clear();
+00796                                 // If find faces under me
+00797                                 NLMISC::CRGBA   dummyAmbient;
+00798                                 if(VCE->getStaticLightSetup(pos, dummyPointLightFromLandscape, landSunContribution, dummyAmbient) )
+00799                                 {
+00800                                         _Instances[i].SunContribution= landSunContribution;
+00801                                         landUsed= true;
+00802                                 }
+00803                         }
+00804 
+00805                         // If failed to use landscape SunContribution, rayTrace
+00806                         if(!landUsed)
+00807                         {
+00808                                 // number of samples (1 if no overSampling)
+00809                                 uint    nSamples= max(1U, lightDesc.OverSampling);
+00810 
+00811                                 // Default is full lighted.
+00812                                 uint    sunAccum= 255*nSamples;
+00813 
+00814                                 // For all samples
+00815                                 for(uint sample=0; sample<nSamples; sample++)
+00816                                 {
+00817                                         // pos to rayTrace against
+00818                                         CVector         pos= _InstanceInfos[i].OverSamples[sample];
+00819 
+00820                                         // rayTrace from this pos.
+00821                                         CVector         lightPos= pos-(rayDir*1000.f);
+00822                                         // Select an element with the X axis as a 3d ray
+00823                                         quadGrid.select (lightPos, lightPos);
+00824                                         // For each triangle selected
+00825                                         CQuadGrid<const CTriangle*>::CIterator  it=quadGrid.begin();
+00826                                         while (it!=quadGrid.end())
+00827                                         {
+00828                                                 const CTriangle *tri= *it;
+00829 
+00830                                                 // If same instanceId, skip
+00831                                                 if(tri->InstanceId != i)
+00832                                                 {
+00833                                                         CVector         hit;
+00834                                                         // If triangle occlude the ray, no sun Contribution
+00835                                                         if(tri->Triangle.intersect(lightPos, pos, hit, tri->Plane))
+00836                                                         {
+00837                                                                 // The sample is not touched by sun. sub his contribution
+00838                                                                 sunAccum-= 255;
+00839                                                                 // End
+00840                                                                 break;
+00841                                                         }
+00842                                                 }
+00843                                                 
+00844                                                 it++;
+00845                                         }
+00846                                 }
+00847 
+00848                                 // Average samples
+00849                                 _Instances[i].SunContribution= sunAccum / nSamples;
+00850                         }
+00851 
+00852                 }
+00853 
+00854 
+00855                 // Light SurfaceGrid Cells.
+00856                 //==========
+00857                 if(_IGSurfaceLightBuild)
+00858                 {
+00859                         // No instance currenlty computed, since we compute surface cells.
+00860                         _CurrentInstanceComputed= -1;
+00861 
+00862                         // Begin cell iteration
+00863                         beginCell();
+00864                         // For all surface cell corners
+00865                         while( !isEndCell() )
+00866                         {
+00867                                 progressCell("Compute SunContribution on Surfaces");
+00868 
+00869                                 // get the current cell and cellInfo iterated.
+00870                                 CIGSurfaceLightBuild::CCellCorner       &cellInfo= getCurrentCellInfo();
+00871                                 CSurfaceLightGrid::CCellCorner          &cell= getCurrentCell();
+00872 
+00873                                 // if the cell corner lies in the polygon surface.
+00874                                 if(cellInfo.InSurface)
+00875                                 {
+00876                                         // number of samples (at least 1 if no overSampling)
+00877                                         uint    nSamples= cellInfo.NumOverSamples;
+00878                                         nlassert(nSamples>=1);
+00879 
+00880                                         // Default is full lighted.
+00881                                         uint    sunAccum= 255*nSamples;
+00882 
+00883                                         // For all samples
+00884                                         for(uint sample=0; sample<nSamples; sample++)
+00885                                         {
+00886                                                 // Get pos to rayTrace.
+00887                                                 CVector pos= cellInfo.OverSamples[sample];
+00888 
+00889                                                 // rayTrace from the pos of this Cell sample.
+00890                                                 CVector         lightPos= pos-(rayDir*1000.f);
+00891                                                 // Select an element with the X axis as a 3d ray
+00892                                                 quadGrid.select (lightPos, lightPos);
+00893                                                 // For each triangle selected
+00894                                                 CQuadGrid<const CTriangle*>::CIterator  it=quadGrid.begin();
+00895                                                 while (it!=quadGrid.end())
+00896                                                 {
+00897                                                         const CTriangle *tri= *it;
+00898 
+00899                                                         CVector         hit;
+00900                                                         // If triangle occlude the ray, no sun Contribution
+00901                                                         if(tri->Triangle.intersect(lightPos, pos, hit, tri->Plane))
+00902                                                         {
+00903                                                                 // The cell sample is not touched by sun. sub his contribution
+00904                                                                 sunAccum-= 255;
+00905                                                                 // End
+00906                                                                 break;
+00907                                                         }
+00908                                                         
+00909                                                         it++;
+00910                                                 }
+00911                                         }
+00912 
+00913                                         // Average SunContribution
+00914                                         cell.SunContribution= sunAccum / nSamples;
+00915 
+00916                                         // copy it to cellInfo
+00917                                         cellInfo.SunContribution= cell.SunContribution;
+00918                                 }
+00919 
+00920                                 // next cell
+00921                                 nextCell();
+00922                         }
+00923                 }
+00924         }
+00925 
+00926 
+00927         // Clean VCM and VCE
+00928         if(landscape)
+00929         {
+00930                 // delete CVisualCollisionManager and CVisualCollisionEntity
+00931                 VCM->deleteEntity(VCE);
+00932                 delete VCM;
+00933         }
+00934 
+00935 }
+00936 
+00937 
+00938 
+00939 // ***************************************************************************
+00940 // ***************************************************************************
+00941 // PointLights part
+00942 // ***************************************************************************
+00943 // ***************************************************************************
+00944 
+00945 
+00946 // ***************************************************************************
+00947 CInstanceLighter::CPointLightRT::CPointLightRT()
+00948 {
+00949         RefCount= 0;
+00950 }
+00951 
+00952 
+00953 // ***************************************************************************
+00954 bool    CInstanceLighter::CPointLightRT::testRaytrace(const CVector &v, sint instanceComputed)
+00955 {
+00956         CVector dummy;
+00957 
+00958         if(!BSphere.include(v))
+00959                 return false;
+00960 
+00961         // If Ambient light, just skip
+00962         if(PointLight.getType()== CPointLight::AmbientLight)
+00963                 return false;
+00964 
+00965         // If SpotLight verify in angle radius.
+00966         if(PointLight.getType()== CPointLight::SpotLight)
+00967         {
+00968                 float   att= PointLight.computeLinearAttenuation(v);
+00969                 if (att==0)
+00970                         return false;
+00971         }
+00972 
+00973 
+00974         // Select in the cubeGrid
+00975         FaceCubeGrid.select(v);
+00976         // For all faces selected
+00977         while(!FaceCubeGrid.isEndSel())
+00978         {
+00979                 const CTriangle *tri= FaceCubeGrid.getSel();
+00980 
+00981                 // If the triangle is not a triangle of the instance currenlty lighted
+00982                 if( instanceComputed<0 || tri->InstanceId != instanceComputed )
+00983                 {
+00984                         // If intersect, the point is occluded.
+00985                         if( tri->Triangle.intersect(BSphere.Center, v, dummy, tri->getPlane()) )
+00986                                 return false;
+00987                 }
+00988 
+00989                 // next
+00990                 FaceCubeGrid.nextSel();
+00991         }
+00992 
+00993         // Ok the point is visilbe from the light
+00994         return true;
+00995 }
+00996 
+00997 
+00998 // ***************************************************************************
+00999 void                    CInstanceLighter::addStaticPointLight(const CPointLightNamed &pln)
+01000 {
+01001         // build the plRT.
+01002         CPointLightRT   plRT;
+01003         plRT.PointLight= pln;
+01004         // compute plRT.OODeltaAttenuation
+01005         plRT.OODeltaAttenuation= pln.getAttenuationEnd() - pln.getAttenuationBegin();
+01006         if(plRT.OODeltaAttenuation <=0 )
+01007                 plRT.OODeltaAttenuation= 1e10f;
+01008         else
+01009                 plRT.OODeltaAttenuation= 1.0f / plRT.OODeltaAttenuation;
+01010         // compute plRT.BSphere
+01011         plRT.BSphere.Center= pln.getPosition();
+01012         plRT.BSphere.Radius= pln.getAttenuationEnd();
+01013         // NB: FaceCubeGrid will be computed during light()
+01014 
+01015         // add the plRT
+01016         _StaticPointLights.push_back(plRT);
+01017 
+01018 }
+01019 
+01020 
+01021 // ***************************************************************************
+01022 void                    CInstanceLighter::compilePointLightRT(uint gridSize, float gridCellSize, std::vector<CTriangle>& obstacles, bool doShadow)
+01023 {
+01024         uint    i;
+01025 
+01026         // Fill the quadGrid of Lights.
+01027         // ===========
+01028         _StaticPointLightQuadGrid.create(gridSize, gridCellSize);
+01029         for(i=0; i<_StaticPointLights.size();i++)
+01030         {
+01031                 CPointLightRT   &plRT= _StaticPointLights[i];
+01032 
+01033                 // Compute the bbox of the light
+01034                 CAABBox         bbox;
+01035                 bbox.setCenter(plRT.BSphere.Center);
+01036                 float   hl= plRT.BSphere.Radius;
+01037                 bbox.setHalfSize(CVector(hl,hl,hl));
+01038 
+01039                 // Insert the pointLight in the quadGrid.
+01040                 _StaticPointLightQuadGrid.insert(bbox.getMin(), bbox.getMax(), &plRT);
+01041         }
+01042 
+01043 
+01044         // Append triangles to cubeGrid ??
+01045         if(doShadow)
+01046         {
+01047                 // For all obstacles, Fill a quadGrid.
+01048                 // ===========
+01049                 CQuadGrid<CTriangle*>   obstacleGrid;
+01050                 obstacleGrid.create(gridSize, gridCellSize);
+01051                 uint    size= obstacles.size();
+01052                 for(i=0; i<size; i++)
+01053                 {
+01054                         // bbox of triangle
+01055                         CAABBox bbox;
+01056                         bbox.setCenter(obstacles[i].Triangle.V0);
+01057                         bbox.extend(obstacles[i].Triangle.V1);
+01058                         bbox.extend(obstacles[i].Triangle.V2);
+01059                         // insert triangle in quadGrid.
+01060                         obstacleGrid.insert(bbox.getMin(), bbox.getMax(), &obstacles[i]);
+01061                 }
+01062 
+01063 
+01064                 // For all PointLights, fill his CubeGrid
+01065                 // ===========
+01066                 for(i=0; i<_StaticPointLights.size();i++)
+01067                 {
+01068                         // progress
+01069                         progress ("Compute Influences of PointLights 1/2", i / (float)_StaticPointLights.size());
+01070 
+01071                         CPointLightRT   &plRT= _StaticPointLights[i];
+01072                         // Create the cubeGrid
+01073                         plRT.FaceCubeGrid.create(plRT.PointLight.getPosition(), NL3D_INSTANCE_LIGHTER_CUBE_GRID_SIZE);
+01074 
+01075                         // AmbiantLIghts: do nothing.
+01076                         if(plRT.PointLight.getType()!=CPointLight::AmbientLight)
+01077                         {
+01078                                 // Select only obstacle Faces around the light. Other are not usefull
+01079                                 CAABBox bbox;
+01080                                 bbox.setCenter(plRT.PointLight.getPosition());
+01081                                 float   hl= plRT.PointLight.getAttenuationEnd();
+01082                                 bbox.setHalfSize(CVector(hl,hl,hl));
+01083                                 obstacleGrid.select(bbox.getMin(), bbox.getMax());
+01084 
+01085                                 // For all faces, fill the cubeGrid.
+01086                                 CQuadGrid<CTriangle*>::CIterator        itObstacle;
+01087                                 itObstacle= obstacleGrid.begin();
+01088                                 while( itObstacle!=obstacleGrid.end() )
+01089                                 {
+01090                                         CTriangle       &tri= *(*itObstacle);
+01091                                         /* Don't Test BackFace culling Here (unlike in CZoneLighter !!).
+01092                                            For objects:
+01093                                                 AutoOccluding problem is avoided with _CurrentInstanceComputed scheme.
+01094                                                 Also, With pointLights, there is no multiSampling (since no factor stored)
+01095                                                 Hence we are sure that no Object samples will lies under floor, and that the center of the 
+01096                                                 object is far away.
+01097                                            For IGSurface lighting:
+01098                                                 notice that we already add 20cm in height because of "stairs problem" so
+01099                                                 floor/surface auto_shadowing is not a problem here...
+01100                                         */
+01101                                         // Insert the triangle in the CubeGrid
+01102                                         plRT.FaceCubeGrid.insert( tri.Triangle, &tri);
+01103 
+01104                                         itObstacle++;
+01105                                 }
+01106                         }
+01107 
+01108                         // Compile the CubeGrid.
+01109                         plRT.FaceCubeGrid.compile();
+01110 
+01111                         // And Reset RefCount.
+01112                         plRT.RefCount= 0;
+01113                 }
+01114         }
+01115         // else, just build empty grid
+01116         else
+01117         {
+01118                 for(i=0; i<_StaticPointLights.size();i++)
+01119                 {
+01120                         // progress
+01121                         progress ("Compute Influences of PointLights 1/2", i / (float)_StaticPointLights.size());
+01122 
+01123                         CPointLightRT   &plRT= _StaticPointLights[i];
+01124                         // Create a dummy empty cubeGrid => no rayTrace :)
+01125                         plRT.FaceCubeGrid.create(plRT.PointLight.getPosition(), 4);
+01126 
+01127                         // Compile the CubeGrid.
+01128                         plRT.FaceCubeGrid.compile();
+01129 
+01130                         // And Reset RefCount.
+01131                         plRT.RefCount= 0;
+01132                 }
+01133         }
+01134 
+01135 }
+01136 
+01137 
+01138 // ***************************************************************************
+01139 bool    CInstanceLighter::CPredPointLightToPoint::operator() (CPointLightRT *pla, CPointLightRT *plb) const
+01140 {
+01141         float   ra= (pla->BSphere.Center - Point).norm();
+01142         float   rb= (plb->BSphere.Center - Point).norm();
+01143         float   infA= (pla->PointLight.getAttenuationEnd() - ra) * pla->OODeltaAttenuation;
+01144         float   infB= (plb->PointLight.getAttenuationEnd() - rb) * plb->OODeltaAttenuation;
+01145         // It is important to clamp, else strange results...
+01146         clamp(infA, 0.f, 1.f);
+01147         clamp(infB, 0.f, 1.f);
+01148         // return which light impact the most.
+01149         // If same impact
+01150         if(infA==infB)
+01151                 // return nearest
+01152                 return ra < rb;
+01153         else
+01154                 // return better impact
+01155                 return  infA > infB;
+01156 }
+01157 
+01158 
+01159 // ***************************************************************************
+01160 void                    CInstanceLighter::processIGPointLightRT(std::vector<CPointLightNamed> &listPointLight)
+01161 {
+01162         uint    i;
+01163         vector<CPointLightRT*>          lightInfs;
+01164         lightInfs.reserve(1024);
+01165 
+01166         // clear result list
+01167         listPointLight.clear();
+01168 
+01169 
+01170         // Compute each Instance
+01171         //===========
+01172         for(i=0; i<_InstanceInfos.size(); i++)
+01173         {
+01174                 // If staticLight not enabled, skip.
+01175                 if( !_Instances[i].StaticLightEnabled )
+01176                         continue;
+01177 
+01178                 CInstanceInfo   &inst= _InstanceInfos[i];
+01179                 // Avoid autoShadowing
+01180                 _CurrentInstanceComputed= i;
+01181 
+01182                 // progress
+01183                 progress ("Compute Influences of PointLights 2/2", i / (float)_InstanceInfos.size());
+01184 
+01185                 // get the point of the instance.
+01186                 CVector         pos= inst.CenterPos;
+01187                 
+01188                 // Default: takes no LocalAmbientLight;
+01189                 inst.LocalAmbientLight= NULL;
+01190                 float   furtherAmbLight= 0;
+01191 
+01192                 // Compute Which light influences him.
+01193                 //---------
+01194                 lightInfs.clear();
+01195                 // Search possible lights around the position.
+01196                 _StaticPointLightQuadGrid.select(pos, pos);
+01197                 // For all of them, get the ones which touch this point.
+01198                 CQuadGrid<CPointLightRT*>::CIterator    it= _StaticPointLightQuadGrid.begin();
+01199                 while(it != _StaticPointLightQuadGrid.end())
+01200                 {
+01201                         CPointLightRT   *pl= *it;
+01202 
+01203                         // Test if really in the radius of the light, no occlusion, not an ambient, and in Spot Angle setup
+01204                         if( pl->testRaytrace(pos, _CurrentInstanceComputed) )
+01205                         {
+01206                                 // Ok, add the light to the lights which influence the instance
+01207                                 lightInfs.push_back(pl);
+01208                         }
+01209 
+01210                         // Ambient Light ??
+01211                         if( pl->PointLight.getType() == CPointLight::AmbientLight )
+01212                         {
+01213                                 // If the instance is in radius of the ambiant light.
+01214                                 float   dRadius= pl->BSphere.Radius - (pl->BSphere.Center - pos).norm();
+01215                                 if(dRadius>0)
+01216                                 {
+01217                                         // Take the best ambient light: the one which is further from the circumference
+01218                                         if(dRadius > furtherAmbLight)
+01219                                         {
+01220                                                 furtherAmbLight= dRadius;
+01221                                                 inst.LocalAmbientLight= pl;
+01222                                         }
+01223                                 }
+01224                         }
+01225 
+01226                         // next
+01227                         it++;
+01228                 }
+01229 
+01230                 // If ambientLight chosen, inc Ref count of it
+01231                 if(inst.LocalAmbientLight)
+01232                         inst.LocalAmbientLight->RefCount++;
+01233 
+01234                 // Choose the Best ones.
+01235                 //---------
+01236                 CPredPointLightToPoint  predPLTP;
+01237                 predPLTP.Point= pos;
+01238                 // sort.
+01239                 sort(lightInfs.begin(), lightInfs.end(), predPLTP);
+01240                 // truncate.
+01241                 lightInfs.resize( min(lightInfs.size(), (uint)CInstanceGroup::NumStaticLightPerInstance) );
+01242 
+01243 
+01244                 // For each of them, fill instance
+01245                 //---------
+01246                 uint                                    lightInfId;
+01247                 for(lightInfId=0; lightInfId<lightInfs.size(); lightInfId++)
+01248                 {
+01249                         CPointLightRT   *pl= lightInfs[lightInfId];
+01250 
+01251                         // copy light.
+01252                         inst.Light[lightInfId]= pl;
+01253 
+01254                         // Inc RefCount of the light.
+01255                         pl->RefCount++;
+01256                 }
+01257                 // Reset any empty slot to NULL.
+01258                 for(; lightInfId<CInstanceGroup::NumStaticLightPerInstance; lightInfId++)
+01259                 {
+01260                         inst.Light[lightInfId]= NULL;
+01261                 }
+01262 
+01263         }
+01264 
+01265 
+01266         // Compute Lighting on SurfaceLightGrid
+01267         //===========
+01268         // Must do it before compression !!
+01269         // NB: big copy/Past from above
+01270         if(_IGSurfaceLightBuild)
+01271         {
+01272                 // No instance currenlty computed, since we compute surface cells.
+01273                 _CurrentInstanceComputed= -1;
+01274 
+01275                 // Begin cell iteration
+01276                 beginCell();
+01277                 // For all surface cell corners
+01278                 while( !isEndCell() )
+01279                 {
+01280                         progressCell("Compute PointLights on Surfaces");
+01281 
+01282                         // get the current cellInfo iterated.
+01283                         CIGSurfaceLightBuild::CCellCorner       &cellInfo= getCurrentCellInfo();
+01284 
+01285                         // if the cell corner lies in the polygon surface.
+01286                         if(cellInfo.InSurface)
+01287                         {
+01288                                 // get the point of the cell.
+01289                                 CVector         pos= cellInfo.CenterPos;
+01290                                 
+01291                                 // Default: takes no LocalAmbientLight;
+01292                                 cellInfo.LocalAmbientLight= NULL;
+01293                                 float   furtherAmbLight= 0;
+01294 
+01295                                 // Compute Which light influences him.
+01296                                 //---------
+01297                                 lightInfs.clear();
+01298                                 // Search possible lights around the position.
+01299                                 _StaticPointLightQuadGrid.select(pos, pos);
+01300                                 // For all of them, get the ones which touch this point.
+01301                                 CQuadGrid<CPointLightRT*>::CIterator    it= _StaticPointLightQuadGrid.begin();
+01302                                 while(it != _StaticPointLightQuadGrid.end())
+01303                                 {
+01304                                         CPointLightRT   *pl= *it;
+01305 
+01306                                         // Test if really in the radius of the light, no occlusion, not an ambient, and in Spot Angle setup
+01307                                         if( pl->testRaytrace(pos, _CurrentInstanceComputed) )
+01308                                         {
+01309                                                 // Ok, add the light to the lights which influence the cell
+01310                                                 lightInfs.push_back(pl);
+01311                                         }
+01312 
+01313                                         // Ambient Light ??
+01314                                         if( pl->PointLight.getType() == CPointLight::AmbientLight )
+01315                                         {
+01316                                                 // If the instance is in radius of the ambiant light.
+01317                                                 float   dRadius= pl->BSphere.Radius - (pl->BSphere.Center - pos).norm();
+01318                                                 if(dRadius>0)
+01319                                                 {
+01320                                                         // Take the best ambient light: the one which is further from the circumference
+01321                                                         if(dRadius > furtherAmbLight)
+01322                                                         {
+01323                                                                 furtherAmbLight= dRadius;
+01324                                                                 cellInfo.LocalAmbientLight= pl;
+01325                                                         }
+01326                                                 }
+01327                                         }
+01328 
+01329                                         // next
+01330                                         it++;
+01331                                 }
+01332 
+01333                                 // If ambientLight chosen, inc Ref count of it
+01334                                 if(cellInfo.LocalAmbientLight)
+01335                                         ((CPointLightRT*)cellInfo.LocalAmbientLight)->RefCount++;
+01336 
+01337 
+01338                                 // Choose the Best ones.
+01339                                 //---------
+01340                                 CPredPointLightToPoint  predPLTP;
+01341                                 predPLTP.Point= pos;
+01342                                 // sort.
+01343                                 sort(lightInfs.begin(), lightInfs.end(), predPLTP);
+01344                                 // truncate.
+01345                                 lightInfs.resize( min(lightInfs.size(), (uint)CSurfaceLightGrid::NumLightPerCorner) );
+01346 
+01347 
+01348                                 // For each of them, fill cellInfo
+01349                                 //---------
+01350                                 uint                                    lightInfId;
+01351                                 for(lightInfId=0; lightInfId<lightInfs.size(); lightInfId++)
+01352                                 {
+01353                                         CPointLightRT   *pl= lightInfs[lightInfId];
+01354 
+01355                                         // copy light.
+01356                                         cellInfo.LightInfo[lightInfId]= pl;
+01357 
+01358                                         // Inc RefCount of the light.
+01359                                         pl->RefCount++;
+01360                                 }
+01361                                 // Reset any empty slot to NULL.
+01362                                 for(; lightInfId<CSurfaceLightGrid::NumLightPerCorner; lightInfId++)
+01363                                 {
+01364                                         cellInfo.LightInfo[lightInfId]= NULL;
+01365                                 }
+01366 
+01367                         }
+01368 
+01369                         // next cell
+01370                         nextCell();
+01371                 }
+01372         }
+01373 
+01374 
+01375 
+01376         // Compress and setup _Instances with compressed data.
+01377         //===========
+01378         uint    plId= 0;
+01379         // Process each pointLights
+01380         for(i=0; i<_StaticPointLights.size(); i++)
+01381         {
+01382                 CPointLightRT   &plRT= _StaticPointLights[i];
+01383                 // If this light is used.
+01384                 if(plRT.RefCount > 0)
+01385                 {
+01386                         // Must Copy it into Ig.
+01387                         listPointLight.push_back(plRT.PointLight);
+01388                         plRT.DstId= plId++;
+01389                         // If index >= 255, too many lights (NB: => because 255 is a NULL code).
+01390                         if(plId>=0xFF)
+01391                         {
+01392                                 throw Exception("Too many Static Point Lights influence the IG!!");
+01393                         }
+01394                 }
+01395         }
+01396 
+01397         // For each instance, compress Point light info
+01398         for(i=0; i<_Instances.size(); i++)
+01399         {
+01400                 // If staticLight not enabled, skip.
+01401                 if( !_Instances[i].StaticLightEnabled )
+01402                         continue;
+01403 
+01404                 CInstanceInfo                           &instSrc= _InstanceInfos[i];
+01405                 CInstanceGroup::CInstance       &instDst= _Instances[i];
+01406 
+01407                 // Do it for PointLights
+01408                 for(uint lightId= 0; lightId<CInstanceGroup::NumStaticLightPerInstance; lightId++)
+01409                 {
+01410                         if(instSrc.Light[lightId] == NULL)
+01411                         {
+01412                                 // Mark as unused.
+01413                                 instDst.Light[lightId]= 0xFF;
+01414                         }
+01415                         else
+01416                         {
+01417                                 // Get index.
+01418                                 instDst.Light[lightId]= instSrc.Light[lightId]->DstId;
+01419                         }
+01420                 }
+01421 
+01422                 // Do it for Ambientlight
+01423                 if(instSrc.LocalAmbientLight == NULL)
+01424                         instDst.LocalAmbientId= 0xFF;
+01425                 else
+01426                         instDst.LocalAmbientId= instSrc.LocalAmbientLight->DstId;
+01427         }
+01428 
+01429         // For each cell, compress Point light info
+01430         if(_IGSurfaceLightBuild)
+01431         {
+01432                 // Begin cell iteration
+01433                 beginCell();
+01434                 // For all surface cell corners
+01435                 while( !isEndCell() )
+01436                 {
+01437                         // get the current cell and cellInfo iterated.
+01438                         CIGSurfaceLightBuild::CCellCorner       &cellInfo= getCurrentCellInfo();
+01439                         CSurfaceLightGrid::CCellCorner          &cell= getCurrentCell();
+01440 
+01441                         if(cellInfo.InSurface)
+01442                         {
+01443                                 // Do it for PointLights
+01444                                 for(uint lightId= 0; lightId<CSurfaceLightGrid::NumLightPerCorner; lightId++)
+01445                                 {
+01446                                         if(cellInfo.LightInfo[lightId] == NULL)
+01447                                         {
+01448                                                 // Mark as unused.
+01449                                                 cell.Light[lightId]= 0xFF;
+01450                                         }
+01451                                         else
+01452                                         {
+01453                                                 // Get index.
+01454                                                 cell.Light[lightId]= reinterpret_cast<CPointLightRT*>(cellInfo.LightInfo[lightId])->DstId;
+01455                                         }
+01456                                 }
+01457 
+01458                                 // Do it for Ambientlight
+01459                                 if(cellInfo.LocalAmbientLight == NULL)
+01460                                         cell.LocalAmbientId= 0xFF;
+01461                                 else
+01462                                         cell.LocalAmbientId= ((CPointLightRT*)cellInfo.LocalAmbientLight)->DstId;
+01463                         }
+01464 
+01465                         // next cell
+01466                         nextCell();
+01467                 }
+01468         }
+01469 
+01470 
+01471 }
+01472 
+01473 
+01474 // ***************************************************************************
+01475 // ***************************************************************************
+01476 // lightIgSimple
+01477 // ***************************************************************************
+01478 // ***************************************************************************
+01479 
+01480 
+01481 // ***************************************************************************
+01482 void    CInstanceLighter::lightIgSimple(CInstanceLighter &instLighter, const CInstanceGroup &igIn, CInstanceGroup &igOut, const CLightDesc &lightDesc)
+01483 {
+01484         sint                            i;
+01485 
+01486 
+01487         // Setup.
+01488         //=======
+01489         // Init
+01490         instLighter.init();
+01491 
+01492         // Add obstacles.
+01493         std::vector<CInstanceLighter::CTriangle>        obstacles;
+01494         // only if Shadowing On.
+01495         if(lightDesc.Shadow)
+01496         {
+01497                 // Map of shape to load
+01498                 std::map<string, IShape*> shapeMap;
+01499 
+01500                 // For all instances of igIn.
+01501                 for(i=0; i<(sint)igIn.getNumInstance();i++)
+01502                 {
+01503                         // progress
+01504                         instLighter.progress("Loading Shapes obstacles", float(i)/igIn.getNumInstance());
+01505 
+01506                         // Skip it??
+01507                         if(igIn.getInstance(i).DontCastShadow)
+01508                                 continue;
+01509 
+01510                         // Get the instance shape name
+01511                         string name= igIn.getShapeName(i);
+01512                         bool    shapeFound= true;
+01513 
+01514                         // Try to find the shape in the UseShapeMap.
+01515                         std::map<string, IShape*>::const_iterator iteMap= lightDesc.UserShapeMap.find (name);
+01516 
+01517                         // If not found in userShape map, try to load it from the temp loaded ShapeBank.
+01518                         if( iteMap == lightDesc.UserShapeMap.end() )
+01519                         {
+01520                                 // Add a .shape at the end ?
+01521                                 if (name.find('.') == std::string::npos)
+01522                                         name += ".shape";
+01523 
+01524                                 // Get the instance shape name
+01525                                 string nameLookup = CPath::lookup (name, false, false);
+01526                                 if (!nameLookup.empty())
+01527                                         name = nameLookup;
+01528 
+01529                                 // Find the shape in the bank
+01530                                 iteMap= shapeMap.find (name);
+01531                                 if (iteMap==shapeMap.end())
+01532                                 {
+01533                                         // Input file
+01534                                         CIFile inputFile;
+01535 
+01536                                         if (!name.empty() && inputFile.open (name))
+01537                                         {
+01538                                                 // Load it
+01539                                                 CShapeStream stream;
+01540                                                 stream.serial (inputFile);
+01541 
+01542                                                 // Get the pointer
+01543                                                 iteMap=shapeMap.insert (std::map<string, IShape*>::value_type (name, stream.getShapePointer ())).first;
+01544                                         }
+01545                                         else
+01546                                         {
+01547                                                 // Error
+01548                                                 nlwarning ("WARNING can't load shape %s\n", name.c_str());
+01549                                                 shapeFound= false;
+01550                                         }
+01551                                 }
+01552                         }
+01553                         
+01554                         if(shapeFound)
+01555                         {
+01556                                 CMatrix         matInst;
+01557                                 matInst.setPos(igIn.getInstancePos(i));
+01558                                 matInst.setRot(igIn.getInstanceRot(i));
+01559                                 matInst.scale(igIn.getInstanceScale(i));
+01560                                 // Add triangles of this shape
+01561                                 CInstanceLighter::addTriangles(*iteMap->second, matInst, obstacles, i);
+01562                         }
+01563 
+01564                 }
+01565 
+01566                 // Clean Up shapes.
+01567                 //-----------
+01568                 std::map<string, IShape*>::iterator iteMap;
+01569                 iteMap= shapeMap.begin();
+01570                 while(iteMap!= shapeMap.end())
+01571                 {
+01572                         // delte shape
+01573                         delete  iteMap->second;
+01574                         // delete entry in map
+01575                         shapeMap.erase(iteMap);
+01576                         // next
+01577                         iteMap= shapeMap.begin();
+01578                 }
+01579         }
+01580 
+01581         // Add pointLights of the IG.
+01582         for(i=0; i<(sint)igIn.getPointLightList().size();i++)
+01583         {
+01584                 instLighter.addStaticPointLight( igIn.getPointLightList()[i] );
+01585         }
+01586 
+01587 
+01588         // Run.
+01589         //=======
+01590         instLighter.light(igIn, igOut, lightDesc, obstacles);
+01591 
+01592 }
+01593 
+01594 
+01595 // ***************************************************************************
+01596 // ***************************************************************************
+01597 // Cell Iteration
+01598 // ***************************************************************************
+01599 // ***************************************************************************
+01600 
+01601 
+01602 // ***************************************************************************
+01603 void                    CInstanceLighter::progressCell(const char *message)
+01604 {
+01605         float   cp= getCurrentCellNumber() / float(getTotalCellNumber());
+01606         if( cp > _LastCellProgress+0.05f)
+01607         {
+01608                 progress(message, cp);
+01609                 _LastCellProgress= cp;
+01610         }
+01611 }
+01612 
+01613 
+01614 // ***************************************************************************
+01615 void                    CInstanceLighter::beginCell()
+01616 {
+01617         if(_IGSurfaceLightBuild)
+01618         {
+01619                 _ItRetriever= _IGRetrieverGridMap.begin();
+01620                 if(_ItRetriever != _IGRetrieverGridMap.end() )
+01621                 {
+01622                         _ItRetrieverInfo= _IGSurfaceLightBuild->RetrieverGridMap.find(_ItRetriever->first);
+01623                         nlassert(_ItRetrieverInfo != _IGSurfaceLightBuild->RetrieverGridMap.end() );
+01624                         // We are suze here that the retriever is not empty, and that the grid herself is not empty too
+01625                         _ItSurfId= 0;
+01626                         _ItCellId= 0;
+01627                         _ItCurrentCellNumber= 0;
+01628                         _IsEndCell= false;
+01629                         _LastCellProgress= 0;
+01630                 }
+01631                 else
+01632                 {
+01633                         _IsEndCell= true;
+01634                 }
+01635         }
+01636         else
+01637         {
+01638                 _IsEndCell= true;
+01639         }
+01640 }
+01641 
+01642 // ***************************************************************************
+01643 void                    CInstanceLighter::nextCell()
+01644 {
+01645         nlassert(!isEndCell());
+01646 
+01647         // Next Cell.
+01648         _ItCellId++;
+01649         _ItCurrentCellNumber++;
+01650 
+01651         // If end of Cells, next surface.
+01652         if(_ItCellId >= _ItRetriever->second.Grids[_ItSurfId].Cells.size() )
+01653         {
+01654                 _ItCellId= 0;
+01655                 _ItSurfId ++;
+01656         }
+01657 
+01658         // If end of surface, next retriever.
+01659         if(_ItSurfId >= _ItRetriever->second.Grids.size() )
+01660         {
+01661                 _ItSurfId= 0;
+01662                 _ItRetriever++;
+01663                 if(_ItRetriever != _IGRetrieverGridMap.end())
+01664                 {
+01665                         // Get info.
+01666                         _ItRetrieverInfo= _IGSurfaceLightBuild->RetrieverGridMap.find(_ItRetriever->first);
+01667                         nlassert(_ItRetrieverInfo != _IGSurfaceLightBuild->RetrieverGridMap.end() );
+01668                 }
+01669         }
+01670 
+01671         // If end of retreiver, End.
+01672         if(_ItRetriever == _IGRetrieverGridMap.end())
+01673         {
+01674                 _IsEndCell= true;
+01675         }
+01676 }
+01677 
+01678 // ***************************************************************************
+01679 bool                    CInstanceLighter::isEndCell()
+01680 {
+01681         return _IsEndCell;
+01682 }
+01683 
+01684 // ***************************************************************************
+01685 CSurfaceLightGrid::CCellCorner          &CInstanceLighter::getCurrentCell()
+01686 {
+01687         nlassert(!isEndCell());
+01688 
+01689         // return ref on Cell.
+01690         return  _ItRetriever->second.Grids[_ItSurfId].Cells[_ItCellId];
+01691 }
+01692 
+01693 // ***************************************************************************
+01694 CIGSurfaceLightBuild::CCellCorner       &CInstanceLighter::getCurrentCellInfo()
+01695 {
+01696         nlassert(!isEndCell());
+01697 
+01698         // return ref on CellInfo.
+01699         return _ItRetrieverInfo->second.Grids[_ItSurfId].Cells[_ItCellId];
+01700 }
+01701 
+01702 
+01703 // ***************************************************************************
+01704 bool                    CInstanceLighter::isCurrentNeighborCellInSurface(sint xnb, sint ynb)
+01705 {
+01706         nlassert(!isEndCell());
+01707 
+01708         // get a ref on the current grid.
+01709         CSurfaceLightGrid       &surfGrid= _ItRetriever->second.Grids[_ItSurfId];
+01710         // copute coordinate of the current cellCorner.
+01711         sint    xCell, yCell;
+01712         xCell= _ItCellId%surfGrid.Width;
+01713         yCell= _ItCellId/surfGrid.Width;
+01714         // compute coordinate of the neighbor cell corner
+01715         xCell+= xnb;
+01716         yCell+= ynb;
+01717 
+01718         // check if in the surfaceGrid
+01719         if(xCell<0 || xCell>=(sint)surfGrid.Width)
+01720                 return false;
+01721         if(yCell<0 || yCell>=(sint)surfGrid.Height)
+01722                 return false;
+01723 
+01724         // compute the neighbor id
+01725         uint    nbId= yCell*surfGrid.Width + xCell;
+01726 
+01727         // Now check in the cellInfo if this cell is InSurface.
+01728         if( !_ItRetrieverInfo->second.Grids[_ItSurfId].Cells[nbId].InSurface )
+01729                 return false;
+01730 
+01731         // Ok, the neighbor cell is valid.
+01732 
+01733         return true;
+01734 }
+01735 
+01736 // ***************************************************************************
+01737 CSurfaceLightGrid::CCellCorner          &CInstanceLighter::getCurrentNeighborCell(sint xnb, sint ynb)
+01738 {
+01739         nlassert(isCurrentNeighborCellInSurface(xnb, ynb));
+01740 
+01741         // get a ref on the current grid.
+01742         CSurfaceLightGrid       &surfGrid= _ItRetriever->second.Grids[_ItSurfId];
+01743         // copute coordinate of the current cellCorner.
+01744         sint    xCell, yCell;
+01745         xCell= _ItCellId%surfGrid.Width;
+01746         yCell= _ItCellId/surfGrid.Width;
+01747         // compute coordinate of the neighbor cell corner
+01748         xCell+= xnb;
+01749         yCell+= ynb;
+01750         // compute the neighbor id
+01751         uint    nbId= yCell*surfGrid.Width + xCell;
+01752 
+01753         // then return a ref on it
+01754         return surfGrid.Cells[nbId];
+01755 }
+01756 
+01757 
+01758 // ***************************************************************************
+01759 CIGSurfaceLightBuild::CCellCorner       &CInstanceLighter::getCurrentNeighborCellInfo(sint xnb, sint ynb)
+01760 {
+01761         nlassert(isCurrentNeighborCellInSurface(xnb, ynb));
+01762 
+01763         // get a ref on the current grid.
+01764         CIGSurfaceLightBuild::CSurface  &surfGrid= _ItRetrieverInfo->second.Grids[_ItSurfId];
+01765         // copute coordinate of the current cellCorner.
+01766         sint    xCell, yCell;
+01767         xCell= _ItCellId%surfGrid.Width;
+01768         yCell= _ItCellId/surfGrid.Width;
+01769         // compute coordinate of the neighbor cell corner
+01770         xCell+= xnb;
+01771         yCell+= ynb;
+01772         // compute the neighbor id
+01773         uint    nbId= yCell*surfGrid.Width + xCell;
+01774 
+01775         // then return a ref on it
+01776         return surfGrid.Cells[nbId];
+01777 }
+01778 
+01779 
+01780 // ***************************************************************************
+01781 void                    CInstanceLighter::dilateLightingOnSurfaceCells()
+01782 {
+01783         // Begin cell iteration
+01784         beginCell();
+01785         // For all surface cell corners
+01786         while( !isEndCell() )
+01787         {
+01788                 progressCell("Dilate Surfaces grids");
+01789 
+01790                 // get the current cell and cellInfo iterated.
+01791                 CIGSurfaceLightBuild::CCellCorner       &cellInfo= getCurrentCellInfo();
+01792                 CSurfaceLightGrid::CCellCorner          &cell= getCurrentCell();
+01793 
+01794                 // if the cell is not in the polygon surface, try to get from his neighbors.
+01795                 if(!cellInfo.InSurface)
+01796                 {
+01797                         // Add Weighted influence of SunContribution, and get one of the PointLightContribution (random).
+01798                         uint    wgtSunContribution= 0;
+01799                         uint    wgtSunCount= 0;
+01800                         // search if one of 8 neighbors is InSurface.
+01801                         for(sint ynb= -1; ynb<= 1; ynb++)
+01802                         {
+01803                                 for(sint xnb= -1; xnb<= 1; xnb++)
+01804                                 {
+01805                                         // center => skip.
+01806                                         if( xnb==0 && ynb==0 )
+01807                                                 continue;
+01808                                         // If the neighbor point is not out of the grid, and if in Surface.
+01809                                         if( isCurrentNeighborCellInSurface(xnb, ynb) )
+01810                                         {
+01811                                                 // get the neighbor cell
+01812                                                 CIGSurfaceLightBuild::CCellCorner       &nbCellInfo= getCurrentNeighborCellInfo(xnb, ynb);
+01813                                                 CSurfaceLightGrid::CCellCorner          &nbCell= getCurrentNeighborCell(xnb, ynb);
+01814                                                 // Add SunContribution.
+01815                                                 wgtSunContribution+= nbCell.SunContribution;
+01816                                                 wgtSunCount++;
+01817                                                 // Just Copy PointLight info.
+01818                                                 for(uint lightId= 0; lightId<CSurfaceLightGrid::NumLightPerCorner; lightId++)
+01819                                                         cell.Light[lightId]= nbCell.Light[lightId];
+01820                                                 // Just Copy AmbientLight info.
+01821                                                 cell.LocalAmbientId= nbCell.LocalAmbientId;
+01822 
+01823 
+01824                                                 // For debug mesh only, copy z from nb cellInfo
+01825                                                 cellInfo.CenterPos.z= nbCellInfo.CenterPos.z;
+01826                                         }
+01827                                 }
+01828                         }
+01829                         // average SunContribution.
+01830                         if(wgtSunCount>0)
+01831                         {
+01832                                 cell.SunContribution= wgtSunContribution / wgtSunCount;
+01833 
+01834                                 // For debug mesh only, copy SunContribution into cellInfo
+01835                                 cellInfo.SunContribution= cell.SunContribution;
+01836                                 cellInfo.Dilated= true;
+01837                         }
+01838                 }
+01839 
+01840                 // next cell
+01841                 nextCell();
+01842         }
+01843 }
+01844 
+01845 
+01846 
+01847 } // NL3D
+
+ + +
                                                                                                                                                                    +
+ + -- cgit v1.2.1