00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
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
00044 #define NL3D_INSTANCE_LIGHTER_CUBE_GRID_SIZE 16
00045
00046
00047
00048
00049
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
00080
00081 excludeAllPatchFromRefineAll (landscape, listZone, false);
00082
00083
00084 landscape.setThreshold (0);
00085 landscape.setTileMaxSubdivision (order);
00086
00087
00088 landscape.refineAll (CVector (0, 0, 0));
00089
00090
00091 std::vector<const CTessFace*> leaves;
00092 landscape.getTessellationLeaves(leaves);
00093
00094
00095 uint leavesCount=leaves.size();
00096
00097
00098 triangleArray.reserve (triangleArray.size()+leavesCount);
00099
00100
00101 for (uint leave=0; leave<leavesCount; leave++)
00102 {
00103
00104 const CTessFace *face=leaves[leave];
00105
00106
00107 triangleArray.push_back (CTriangle (NLMISC::CTriangle (face->VBase->EndPos, face->VLeft->EndPos, face->VRight->EndPos), -1 ));
00108 }
00109
00110
00111 landscape.setThreshold (1000);
00112 landscape.setTileMaxSubdivision (0);
00113
00114
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
00132
00133
00134 const CMesh *mesh=dynamic_cast<const CMesh*>(&shape);
00135
00136
00137 const CMeshMultiLod *meshMulti=dynamic_cast<const CMeshMultiLod*>(&shape);
00138
00139
00140 const CMeshMRM *meshMRM=dynamic_cast<const CMeshMRM*>(&shape);
00141
00142
00143 if (mesh)
00144 {
00145
00146 addTriangles (mesh->getMeshGeom (), modelMT, triangleArray, instanceId);
00147 }
00148
00149 else if (meshMulti)
00150 {
00151
00152 const IMeshGeom *meshGeom=&meshMulti->getMeshGeom (0);
00153
00154
00155 const CMeshGeom *geomMesh=dynamic_cast<const CMeshGeom*>(meshGeom);
00156 if (geomMesh)
00157 {
00158 addTriangles (*geomMesh, modelMT, triangleArray, instanceId);
00159 }
00160
00161
00162 const CMeshMRMGeom *mrmGeomMesh=dynamic_cast<const CMeshMRMGeom*>(meshGeom);
00163 if (mrmGeomMesh)
00164 {
00165 addTriangles (*mrmGeomMesh, modelMT, triangleArray, instanceId);
00166 }
00167 }
00168
00169 else if (meshMRM)
00170 {
00171
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
00182 const CVertexBuffer &vb=meshGeom.getVertexBuffer();
00183
00184
00185 uint numBlock=meshGeom.getNbMatrixBlock();
00186 for (uint block=0; block<numBlock; block++)
00187 {
00188
00189 uint numRenderPass=meshGeom.getNbRdrPass(block);
00190 for (uint pass=0; pass<numRenderPass; pass++)
00191 {
00192
00193 const CPrimitiveBlock &primitive=meshGeom.getRdrPassPrimitiveBlock ( block, pass);
00194
00195
00196 const uint32* triIndex=primitive.getTriPointer ();
00197 uint numTri=primitive.getNumTri ();
00198 uint tri;
00199 for (tri=0; tri<numTri; tri++)
00200 {
00201
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
00207 triangleArray.push_back (CTriangle (NLMISC::CTriangle (v0, v1, v2), instanceId));
00208 }
00209
00210
00211 triIndex=primitive.getQuadPointer ();
00212 numTri=primitive.getNumQuad ();
00213 for (tri=0; tri<numTri; tri++)
00214 {
00215
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
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
00234 const CVertexBuffer &vb=meshGeom.getVertexBuffer();
00235
00236
00237 uint numRenderPass=meshGeom.getNbRdrPass(0);
00238 for (uint pass=0; pass<numRenderPass; pass++)
00239 {
00240
00241 const CPrimitiveBlock &primitive=meshGeom.getRdrPassPrimitiveBlock ( 0, pass);
00242
00243
00244 const uint32* triIndex=primitive.getTriPointer ();
00245 uint numTri=primitive.getNumTri ();
00246 uint tri;
00247 for (tri=0; tri<numTri; tri++)
00248 {
00249
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
00255 triangleArray.push_back (CTriangle (NLMISC::CTriangle (v0, v1, v2), instanceId));
00256 }
00257
00258
00259 triIndex=primitive.getQuadPointer ();
00260 numTri=primitive.getNumQuad ();
00261 for (tri=0; tri<numTri; tri++)
00262 {
00263
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
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
00281 for (uint zone=0; zone<listZone.size(); zone++)
00282 {
00283
00284 uint patchCount=landscape.getZone(listZone[zone])->getNumPatchs();
00285
00286
00287 for (uint patch=0; patch<patchCount; patch++)
00288 {
00289
00290 landscape.excludePatchFromRefineAll (listZone[zone], patch, exclude);
00291 }
00292 }
00293 }
00294
00295
00296
00297
00298
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
00318
00319
00320
00321
00322
00323 _IGSurfaceLightBuild= igSurfaceLightBuild;
00324
00325 _IGRetrieverGridMap.clear();
00326 if(_IGSurfaceLightBuild)
00327 {
00328 _TotalCellNumber= 0;
00329 CIGSurfaceLightBuild::ItRetrieverGridMap itSrc;
00330 itSrc= _IGSurfaceLightBuild->RetrieverGridMap.begin();
00331
00332 while(itSrc!=_IGSurfaceLightBuild->RetrieverGridMap.end())
00333 {
00334 uint numSurfaces= itSrc->second.Grids.size();
00335
00336 if(numSurfaces>0)
00337 {
00338
00339 CIGSurfaceLight::CRetrieverLightGrid &rlgDst= _IGRetrieverGridMap[itSrc->first];
00340
00341 rlgDst.Grids.resize(numSurfaces);
00342
00343 for(uint i=0; i<numSurfaces; i++)
00344 {
00345 CIGSurfaceLightBuild::CSurface &surfSrc= itSrc->second.Grids[i];
00346 CSurfaceLightGrid &surfDst= rlgDst.Grids[i];
00347
00348 CSurfaceLightGrid::CCellCorner defaultCellCorner;
00349 defaultCellCorner.SunContribution= 0;
00350 defaultCellCorner.Light[0]= 0xFF;
00351 defaultCellCorner.LocalAmbientId= 0xFF;
00352
00353
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
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
00369 itSrc++;
00370 }
00371 }
00372
00373 _IsEndCell= true;
00374
00375
00376
00377
00378 igIn.retrieve (outGlobalPos, _Instances, outClusters, outPortals, pointLightList);
00379
00380
00381
00382
00383
00384 std::map<string, IShape*> shapeMap;
00385 _InstanceInfos.resize(_Instances.size());
00386 for(i=0; i<(sint)_Instances.size();i++)
00387 {
00388
00389 if(_Instances[i].AvoidStaticLightPreCompute)
00390 {
00391 _Instances[i].StaticLightEnabled= false;
00392
00393 continue;
00394 }
00395
00396
00397 _Instances[i].StaticLightEnabled= true;
00398
00399
00400
00401
00402 CVector shapeCenterPos;
00403 CVector overSamples[MaxOverSamples];
00404
00405
00406 string name= _Instances[i].Name;
00407 bool shapeFound= true;
00408
00409
00410 std::map<string, IShape*>::const_iterator iteMap= lightDesc.UserShapeMap.find (name);
00411
00412
00413 if( iteMap == lightDesc.UserShapeMap.end() )
00414 {
00415
00416 if (name.find('.') == std::string::npos)
00417 name += ".shape";
00418
00419
00420 string nameLookup = CPath::lookup (name, false, false);
00421 if (!nameLookup.empty())
00422 name = nameLookup;
00423
00424
00425 iteMap= shapeMap.find (name);
00426 if (iteMap==shapeMap.end())
00427 {
00428
00429 CIFile inputFile;
00430
00431 if (!name.empty() && inputFile.open (name))
00432 {
00433
00434 CShapeStream stream;
00435 stream.serial (inputFile);
00436
00437
00438 iteMap=shapeMap.insert (std::map<string, IShape*>::value_type (name, stream.getShapePointer ())).first;
00439 }
00440 else
00441 {
00442
00443 nlwarning ("WARNING can't load shape %s\n", name.c_str());
00444 shapeFound= false;
00445 }
00446 }
00447 }
00448
00449
00450
00451
00452 if(shapeFound)
00453 {
00454 CMeshBase *mesh= dynamic_cast<CMeshBase*>(iteMap->second);
00455 if(mesh)
00456 {
00457
00458 if(!mesh->isLightable())
00459 {
00460
00461 _Instances[i].AvoidStaticLightPreCompute= true;
00462
00463 _Instances[i].StaticLightEnabled= false;
00464
00465 continue;
00466 }
00467 }
00468 }
00469
00470
00471
00472
00473 {
00474
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
00486 shapeCenterPos= bbox.getCenter();
00487
00488
00489
00490 float qx= bbox.getHalfSize().x/2;
00491 float qy= bbox.getHalfSize().y/2;
00492 float qz= bbox.getHalfSize().z/2;
00493
00494 if(lightDesc.OverSampling==0)
00495 overSamples[0]= shapeCenterPos;
00496 else if(lightDesc.OverSampling==2)
00497 {
00498
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
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
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
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
00529 overSamples[sample+8]= overSamples[sample] + decal;
00530
00531 overSamples[sample]-= decal;
00532 }
00533 }
00534 }
00535 }
00536
00537
00538
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
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
00554
00555 std::map<string, IShape*>::iterator iteMap;
00556 iteMap= shapeMap.begin();
00557 while(iteMap!= shapeMap.end())
00558 {
00559
00560 delete iteMap->second;
00561
00562 shapeMap.erase(iteMap);
00563
00564 iteMap= shapeMap.begin();
00565 }
00566
00567
00568
00569 for(i=0; i<(sint)obstacles.size();i++)
00570 {
00571 CInstanceLighter::CTriangle& triangle=obstacles[i];
00572
00573 triangle.Plane.make (triangle.Triangle.V0, triangle.Triangle.V1, triangle.Triangle.V2);
00574 }
00575
00576
00577
00578
00579
00580
00581 computeSunContribution(lightDesc, obstacles, landscape);
00582
00583
00584
00585 compilePointLightRT(lightDesc.GridSize, lightDesc.GridCellSize, obstacles, lightDesc.Shadow);
00586
00587 pointLightList.clear();
00588
00589
00590 processIGPointLightRT(pointLightList);
00591
00592
00593 if(_IGSurfaceLightBuild)
00594 {
00595 dilateLightingOnSurfaceCells();
00596 }
00597
00598
00599
00600
00601 if(_IGSurfaceLightBuild)
00602 {
00603
00604 igOut.build(outGlobalPos, _Instances, outClusters, outPortals, pointLightList,
00605 &_IGRetrieverGridMap, _IGSurfaceLightBuild->CellSize);
00606 }
00607 else
00608 {
00609
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
00637 CVisualCollisionManager *VCM= NULL;
00638 CVisualCollisionEntity *VCE= NULL;
00639 if(landscape)
00640 {
00641
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
00651 if(lightDesc.DisableSunContribution)
00652 {
00653
00654
00655 for(i=0; i<(sint)_Instances.size(); i++)
00656 {
00657
00658 if( !_Instances[i].StaticLightEnabled )
00659 continue;
00660
00661
00662 _Instances[i].SunContribution= 0;
00663 }
00664
00665
00666
00667 if(_IGSurfaceLightBuild)
00668 {
00669
00670 beginCell();
00671
00672 while( !isEndCell() )
00673 {
00674
00675 CIGSurfaceLightBuild::CCellCorner &cellInfo= getCurrentCellInfo();
00676 CSurfaceLightGrid::CCellCorner &cell= getCurrentCell();
00677
00678
00679 if(cellInfo.InSurface)
00680 {
00681
00682 cell.SunContribution= 0;
00683
00684 cellInfo.SunContribution= cell.SunContribution;
00685 }
00686
00687
00688 nextCell();
00689 }
00690 }
00691 }
00692
00693 else if(!lightDesc.Shadow)
00694 {
00695
00696
00697 for(i=0; i<(sint)_Instances.size(); i++)
00698 {
00699 progress ("Compute SunContribution on Instances", i / float(_Instances.size()) );
00700
00701
00702 if( !_Instances[i].StaticLightEnabled )
00703 continue;
00704
00705
00706 _Instances[i].SunContribution= 255;
00707
00708 if(landscape)
00709 {
00710 CVector pos= _InstanceInfos[i].CenterPos;
00711 uint8 landSunContribution;
00712 dummyPointLightFromLandscape.clear();
00713
00714 NLMISC::CRGBA dummyAmbient;
00715 if(VCE->getStaticLightSetup(pos, dummyPointLightFromLandscape, landSunContribution, dummyAmbient) )
00716 {
00717 _Instances[i].SunContribution= landSunContribution;
00718 }
00719 }
00720 }
00721
00722
00723
00724 if(_IGSurfaceLightBuild)
00725 {
00726
00727 beginCell();
00728
00729 while( !isEndCell() )
00730 {
00731 progressCell("Compute SunContribution on Surfaces");
00732
00733
00734 CIGSurfaceLightBuild::CCellCorner &cellInfo= getCurrentCellInfo();
00735 CSurfaceLightGrid::CCellCorner &cell= getCurrentCell();
00736
00737
00738 if(cellInfo.InSurface)
00739 {
00740
00741 cell.SunContribution= 255;
00742
00743 cellInfo.SunContribution= cell.SunContribution;
00744 }
00745
00746
00747 nextCell();
00748 }
00749 }
00750 }
00751 else
00752 {
00753
00754 CVector rayDir= lightDesc.LightDirection;
00755 CMatrix rayBasis;
00756 rayDir.normalize();
00757 NEL3DCalcBase(rayDir, rayBasis);
00758 CMatrix invRayBasis;
00759 invRayBasis= rayBasis.inverted();
00760
00761
00762
00763
00764 CQuadGrid<const CTriangle*> quadGrid;
00765 quadGrid.changeBase (invRayBasis);
00766 quadGrid.create(lightDesc.GridSize, lightDesc.GridCellSize);
00767
00768 for(i=0; i<(sint)obstacles.size(); i++)
00769 {
00770 CAABBox triBBox;
00771
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
00776 quadGrid.insert(rayBasis * triBBox.getMin(), rayBasis * triBBox.getMax(), &obstacles[i]);
00777 }
00778
00779
00780
00781 for(i=0; i<(sint)_Instances.size(); i++)
00782 {
00783 progress ("Compute SunContribution on Instances", i / float(_Instances.size()) );
00784
00785
00786 if( !_Instances[i].StaticLightEnabled )
00787 continue;
00788
00789
00790 bool landUsed= false;
00791 if(landscape)
00792 {
00793 CVector pos= _InstanceInfos[i].CenterPos;
00794 uint8 landSunContribution;
00795 dummyPointLightFromLandscape.clear();
00796
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
00806 if(!landUsed)
00807 {
00808
00809 uint nSamples= max(1U, lightDesc.OverSampling);
00810
00811
00812 uint sunAccum= 255*nSamples;
00813
00814
00815 for(uint sample=0; sample<nSamples; sample++)
00816 {
00817
00818 CVector pos= _InstanceInfos[i].OverSamples[sample];
00819
00820
00821 CVector lightPos= pos-(rayDir*1000.f);
00822
00823 quadGrid.select (lightPos, lightPos);
00824
00825 CQuadGrid<const CTriangle*>::CIterator it=quadGrid.begin();
00826 while (it!=quadGrid.end())
00827 {
00828 const CTriangle *tri= *it;
00829
00830
00831 if(tri->InstanceId != i)
00832 {
00833 CVector hit;
00834
00835 if(tri->Triangle.intersect(lightPos, pos, hit, tri->Plane))
00836 {
00837
00838 sunAccum-= 255;
00839
00840 break;
00841 }
00842 }
00843
00844 it++;
00845 }
00846 }
00847
00848
00849 _Instances[i].SunContribution= sunAccum / nSamples;
00850 }
00851
00852 }
00853
00854
00855
00856
00857 if(_IGSurfaceLightBuild)
00858 {
00859
00860 _CurrentInstanceComputed= -1;
00861
00862
00863 beginCell();
00864
00865 while( !isEndCell() )
00866 {
00867 progressCell("Compute SunContribution on Surfaces");
00868
00869
00870 CIGSurfaceLightBuild::CCellCorner &cellInfo= getCurrentCellInfo();
00871 CSurfaceLightGrid::CCellCorner &cell= getCurrentCell();
00872
00873
00874 if(cellInfo.InSurface)
00875 {
00876
00877 uint nSamples= cellInfo.NumOverSamples;
00878 nlassert(nSamples>=1);
00879
00880
00881 uint sunAccum= 255*nSamples;
00882
00883
00884 for(uint sample=0; sample<nSamples; sample++)
00885 {
00886
00887 CVector pos= cellInfo.OverSamples[sample];
00888
00889
00890 CVector lightPos= pos-(rayDir*1000.f);
00891
00892 quadGrid.select (lightPos, lightPos);
00893
00894 CQuadGrid<const CTriangle*>::CIterator it=quadGrid.begin();
00895 while (it!=quadGrid.end())
00896 {
00897 const CTriangle *tri= *it;
00898
00899 CVector hit;
00900
00901 if(tri->Triangle.intersect(lightPos, pos, hit, tri->Plane))
00902 {
00903
00904 sunAccum-= 255;
00905
00906 break;
00907 }
00908
00909 it++;
00910 }
00911 }
00912
00913
00914 cell.SunContribution= sunAccum / nSamples;
00915
00916
00917 cellInfo.SunContribution= cell.SunContribution;
00918 }
00919
00920
00921 nextCell();
00922 }
00923 }
00924 }
00925
00926
00927
00928 if(landscape)
00929 {
00930
00931 VCM->deleteEntity(VCE);
00932 delete VCM;
00933 }
00934
00935 }
00936
00937
00938
00939
00940
00941
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
00962 if(PointLight.getType()== CPointLight::AmbientLight)
00963 return false;
00964
00965
00966 if(PointLight.getType()== CPointLight::SpotLight)
00967 {
00968 float att= PointLight.computeLinearAttenuation(v);
00969 if (att==0)
00970 return false;
00971 }
00972
00973
00974
00975 FaceCubeGrid.select(v);
00976
00977 while(!FaceCubeGrid.isEndSel())
00978 {
00979 const CTriangle *tri= FaceCubeGrid.getSel();
00980
00981
00982 if( instanceComputed<0 || tri->InstanceId != instanceComputed )
00983 {
00984
00985 if( tri->Triangle.intersect(BSphere.Center, v, dummy, tri->getPlane()) )
00986 return false;
00987 }
00988
00989
00990 FaceCubeGrid.nextSel();
00991 }
00992
00993
00994 return true;
00995 }
00996
00997
00998
00999 void CInstanceLighter::addStaticPointLight(const CPointLightNamed &pln)
01000 {
01001
01002 CPointLightRT plRT;
01003 plRT.PointLight= pln;
01004
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
01011 plRT.BSphere.Center= pln.getPosition();
01012 plRT.BSphere.Radius= pln.getAttenuationEnd();
01013
01014
01015
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
01027
01028 _StaticPointLightQuadGrid.create(gridSize, gridCellSize);
01029 for(i=0; i<_StaticPointLights.size();i++)
01030 {
01031 CPointLightRT &plRT= _StaticPointLights[i];
01032
01033
01034 CAABBox bbox;
01035 bbox.setCenter(plRT.BSphere.Center);
01036 float hl= plRT.BSphere.Radius;
01037 bbox.setHalfSize(CVector(hl,hl,hl));
01038
01039
01040 _StaticPointLightQuadGrid.insert(bbox.getMin(), bbox.getMax(), &plRT);
01041 }
01042
01043
01044
01045 if(doShadow)
01046 {
01047
01048
01049 CQuadGrid<CTriangle*> obstacleGrid;
01050 obstacleGrid.create(gridSize, gridCellSize);
01051 uint size= obstacles.size();
01052 for(i=0; i<size; i++)
01053 {
01054
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
01060 obstacleGrid.insert(bbox.getMin(), bbox.getMax(), &obstacles[i]);
01061 }
01062
01063
01064
01065
01066 for(i=0; i<_StaticPointLights.size();i++)
01067 {
01068
01069 progress ("Compute Influences of PointLights 1/2", i / (float)_StaticPointLights.size());
01070
01071 CPointLightRT &plRT= _StaticPointLights[i];
01072
01073 plRT.FaceCubeGrid.create(plRT.PointLight.getPosition(), NL3D_INSTANCE_LIGHTER_CUBE_GRID_SIZE);
01074
01075
01076 if(plRT.PointLight.getType()!=CPointLight::AmbientLight)
01077 {
01078
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
01086 CQuadGrid<CTriangle*>::CIterator itObstacle;
01087 itObstacle= obstacleGrid.begin();
01088 while( itObstacle!=obstacleGrid.end() )
01089 {
01090 CTriangle &tri= *(*itObstacle);
01091
01092
01093
01094
01095
01096
01097
01098
01099
01100
01101
01102 plRT.FaceCubeGrid.insert( tri.Triangle, &tri);
01103
01104 itObstacle++;
01105 }
01106 }
01107
01108
01109 plRT.FaceCubeGrid.compile();
01110
01111
01112 plRT.RefCount= 0;
01113 }
01114 }
01115
01116 else
01117 {
01118 for(i=0; i<_StaticPointLights.size();i++)
01119 {
01120
01121 progress ("Compute Influences of PointLights 1/2", i / (float)_StaticPointLights.size());
01122
01123 CPointLightRT &plRT= _StaticPointLights[i];
01124
01125 plRT.FaceCubeGrid.create(plRT.PointLight.getPosition(), 4);
01126
01127
01128 plRT.FaceCubeGrid.compile();
01129
01130
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
01146 clamp(infA, 0.f, 1.f);
01147 clamp(infB, 0.f, 1.f);
01148
01149
01150 if(infA==infB)
01151
01152 return ra < rb;
01153 else
01154
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
01167 listPointLight.clear();
01168
01169
01170
01171
01172 for(i=0; i<_InstanceInfos.size(); i++)
01173 {
01174
01175 if( !_Instances[i].StaticLightEnabled )
01176 continue;
01177
01178 CInstanceInfo &inst= _InstanceInfos[i];
01179
01180 _CurrentInstanceComputed= i;
01181
01182
01183 progress ("Compute Influences of PointLights 2/2", i / (float)_InstanceInfos.size());
01184
01185
01186 CVector pos= inst.CenterPos;
01187
01188
01189 inst.LocalAmbientLight= NULL;
01190 float furtherAmbLight= 0;
01191
01192
01193
01194 lightInfs.clear();
01195
01196 _StaticPointLightQuadGrid.select(pos, pos);
01197
01198 CQuadGrid<CPointLightRT*>::CIterator it= _StaticPointLightQuadGrid.begin();
01199 while(it != _StaticPointLightQuadGrid.end())
01200 {
01201 CPointLightRT *pl= *it;
01202
01203
01204 if( pl->testRaytrace(pos, _CurrentInstanceComputed) )
01205 {
01206
01207 lightInfs.push_back(pl);
01208 }
01209
01210
01211 if( pl->PointLight.getType() == CPointLight::AmbientLight )
01212 {
01213
01214 float dRadius= pl->BSphere.Radius - (pl->BSphere.Center - pos).norm();
01215 if(dRadius>0)
01216 {
01217
01218 if(dRadius > furtherAmbLight)
01219 {
01220 furtherAmbLight= dRadius;
01221 inst.LocalAmbientLight= pl;
01222 }
01223 }
01224 }
01225
01226
01227 it++;
01228 }
01229
01230
01231 if(inst.LocalAmbientLight)
01232 inst.LocalAmbientLight->RefCount++;
01233
01234
01235
01236 CPredPointLightToPoint predPLTP;
01237 predPLTP.Point= pos;
01238
01239 sort(lightInfs.begin(), lightInfs.end(), predPLTP);
01240
01241 lightInfs.resize( min(lightInfs.size(), (uint)CInstanceGroup::NumStaticLightPerInstance) );
01242
01243
01244
01245
01246 uint lightInfId;
01247 for(lightInfId=0; lightInfId<lightInfs.size(); lightInfId++)
01248 {
01249 CPointLightRT *pl= lightInfs[lightInfId];
01250
01251
01252 inst.Light[lightInfId]= pl;
01253
01254
01255 pl->RefCount++;
01256 }
01257
01258 for(; lightInfId<CInstanceGroup::NumStaticLightPerInstance; lightInfId++)
01259 {
01260 inst.Light[lightInfId]= NULL;
01261 }
01262
01263 }
01264
01265
01266
01267
01268
01269
01270 if(_IGSurfaceLightBuild)
01271 {
01272
01273 _CurrentInstanceComputed= -1;
01274
01275
01276 beginCell();
01277
01278 while( !isEndCell() )
01279 {
01280 progressCell("Compute PointLights on Surfaces");
01281
01282
01283 CIGSurfaceLightBuild::CCellCorner &cellInfo= getCurrentCellInfo();
01284
01285
01286 if(cellInfo.InSurface)
01287 {
01288
01289 CVector pos= cellInfo.CenterPos;
01290
01291
01292 cellInfo.LocalAmbientLight= NULL;
01293 float furtherAmbLight= 0;
01294
01295
01296
01297 lightInfs.clear();
01298
01299 _StaticPointLightQuadGrid.select(pos, pos);
01300
01301 CQuadGrid<CPointLightRT*>::CIterator it= _StaticPointLightQuadGrid.begin();
01302 while(it != _StaticPointLightQuadGrid.end())
01303 {
01304 CPointLightRT *pl= *it;
01305
01306
01307 if( pl->testRaytrace(pos, _CurrentInstanceComputed) )
01308 {
01309
01310 lightInfs.push_back(pl);
01311 }
01312
01313
01314 if( pl->PointLight.getType() == CPointLight::AmbientLight )
01315 {
01316
01317 float dRadius= pl->BSphere.Radius - (pl->BSphere.Center - pos).norm();
01318 if(dRadius>0)
01319 {
01320
01321 if(dRadius > furtherAmbLight)
01322 {
01323 furtherAmbLight= dRadius;
01324 cellInfo.LocalAmbientLight= pl;
01325 }
01326 }
01327 }
01328
01329
01330 it++;
01331 }
01332
01333
01334 if(cellInfo.LocalAmbientLight)
01335 ((CPointLightRT*)cellInfo.LocalAmbientLight)->RefCount++;
01336
01337
01338
01339
01340 CPredPointLightToPoint predPLTP;
01341 predPLTP.Point= pos;
01342
01343 sort(lightInfs.begin(), lightInfs.end(), predPLTP);
01344
01345 lightInfs.resize( min(lightInfs.size(), (uint)CSurfaceLightGrid::NumLightPerCorner) );
01346
01347
01348
01349
01350 uint lightInfId;
01351 for(lightInfId=0; lightInfId<lightInfs.size(); lightInfId++)
01352 {
01353 CPointLightRT *pl= lightInfs[lightInfId];
01354
01355
01356 cellInfo.LightInfo[lightInfId]= pl;
01357
01358
01359 pl->RefCount++;
01360 }
01361
01362 for(; lightInfId<CSurfaceLightGrid::NumLightPerCorner; lightInfId++)
01363 {
01364 cellInfo.LightInfo[lightInfId]= NULL;
01365 }
01366
01367 }
01368
01369
01370 nextCell();
01371 }
01372 }
01373
01374
01375
01376
01377
01378 uint plId= 0;
01379
01380 for(i=0; i<_StaticPointLights.size(); i++)
01381 {
01382 CPointLightRT &plRT= _StaticPointLights[i];
01383
01384 if(plRT.RefCount > 0)
01385 {
01386
01387 listPointLight.push_back(plRT.PointLight);
01388 plRT.DstId= plId++;
01389
01390 if(plId>=0xFF)
01391 {
01392 throw Exception("Too many Static Point Lights influence the IG!!");
01393 }
01394 }
01395 }
01396
01397
01398 for(i=0; i<_Instances.size(); i++)
01399 {
01400
01401 if( !_Instances[i].StaticLightEnabled )
01402 continue;
01403
01404 CInstanceInfo &instSrc= _InstanceInfos[i];
01405 CInstanceGroup::CInstance &instDst= _Instances[i];
01406
01407
01408 for(uint lightId= 0; lightId<CInstanceGroup::NumStaticLightPerInstance; lightId++)
01409 {
01410 if(instSrc.Light[lightId] == NULL)
01411 {
01412
01413 instDst.Light[lightId]= 0xFF;
01414 }
01415 else
01416 {
01417
01418 instDst.Light[lightId]= instSrc.Light[lightId]->DstId;
01419 }
01420 }
01421
01422
01423 if(instSrc.LocalAmbientLight == NULL)
01424 instDst.LocalAmbientId= 0xFF;
01425 else
01426 instDst.LocalAmbientId= instSrc.LocalAmbientLight->DstId;
01427 }
01428
01429
01430 if(_IGSurfaceLightBuild)
01431 {
01432
01433 beginCell();
01434
01435 while( !isEndCell() )
01436 {
01437
01438 CIGSurfaceLightBuild::CCellCorner &cellInfo= getCurrentCellInfo();
01439 CSurfaceLightGrid::CCellCorner &cell= getCurrentCell();
01440
01441 if(cellInfo.InSurface)
01442 {
01443
01444 for(uint lightId= 0; lightId<CSurfaceLightGrid::NumLightPerCorner; lightId++)
01445 {
01446 if(cellInfo.LightInfo[lightId] == NULL)
01447 {
01448
01449 cell.Light[lightId]= 0xFF;
01450 }
01451 else
01452 {
01453
01454 cell.Light[lightId]= reinterpret_cast<CPointLightRT*>(cellInfo.LightInfo[lightId])->DstId;
01455 }
01456 }
01457
01458
01459 if(cellInfo.LocalAmbientLight == NULL)
01460 cell.LocalAmbientId= 0xFF;
01461 else
01462 cell.LocalAmbientId= ((CPointLightRT*)cellInfo.LocalAmbientLight)->DstId;
01463 }
01464
01465
01466 nextCell();
01467 }
01468 }
01469
01470
01471 }
01472
01473
01474
01475
01476
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
01488
01489
01490 instLighter.init();
01491
01492
01493 std::vector<CInstanceLighter::CTriangle> obstacles;
01494
01495 if(lightDesc.Shadow)
01496 {
01497
01498 std::map<string, IShape*> shapeMap;
01499
01500
01501 for(i=0; i<(sint)igIn.getNumInstance();i++)
01502 {
01503
01504 instLighter.progress("Loading Shapes obstacles", float(i)/igIn.getNumInstance());
01505
01506
01507 if(igIn.getInstance(i).DontCastShadow)
01508 continue;
01509
01510
01511 string name= igIn.getShapeName(i);
01512 bool shapeFound= true;
01513
01514
01515 std::map<string, IShape*>::const_iterator iteMap= lightDesc.UserShapeMap.find (name);
01516
01517
01518 if( iteMap == lightDesc.UserShapeMap.end() )
01519 {
01520
01521 if (name.find('.') == std::string::npos)
01522 name += ".shape";
01523
01524
01525 string nameLookup = CPath::lookup (name, false, false);
01526 if (!nameLookup.empty())
01527 name = nameLookup;
01528
01529
01530 iteMap= shapeMap.find (name);
01531 if (iteMap==shapeMap.end())
01532 {
01533
01534 CIFile inputFile;
01535
01536 if (!name.empty() && inputFile.open (name))
01537 {
01538
01539 CShapeStream stream;
01540 stream.serial (inputFile);
01541
01542
01543 iteMap=shapeMap.insert (std::map<string, IShape*>::value_type (name, stream.getShapePointer ())).first;
01544 }
01545 else
01546 {
01547
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
01561 CInstanceLighter::addTriangles(*iteMap->second, matInst, obstacles, i);
01562 }
01563
01564 }
01565
01566
01567
01568 std::map<string, IShape*>::iterator iteMap;
01569 iteMap= shapeMap.begin();
01570 while(iteMap!= shapeMap.end())
01571 {
01572
01573 delete iteMap->second;
01574
01575 shapeMap.erase(iteMap);
01576
01577 iteMap= shapeMap.begin();
01578 }
01579 }
01580
01581
01582 for(i=0; i<(sint)igIn.getPointLightList().size();i++)
01583 {
01584 instLighter.addStaticPointLight( igIn.getPointLightList()[i] );
01585 }
01586
01587
01588
01589
01590 instLighter.light(igIn, igOut, lightDesc, obstacles);
01591
01592 }
01593
01594
01595
01596
01597
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
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
01648 _ItCellId++;
01649 _ItCurrentCellNumber++;
01650
01651
01652 if(_ItCellId >= _ItRetriever->second.Grids[_ItSurfId].Cells.size() )
01653 {
01654 _ItCellId= 0;
01655 _ItSurfId ++;
01656 }
01657
01658
01659 if(_ItSurfId >= _ItRetriever->second.Grids.size() )
01660 {
01661 _ItSurfId= 0;
01662 _ItRetriever++;
01663 if(_ItRetriever != _IGRetrieverGridMap.end())
01664 {
01665
01666 _ItRetrieverInfo= _IGSurfaceLightBuild->RetrieverGridMap.find(_ItRetriever->first);
01667 nlassert(_ItRetrieverInfo != _IGSurfaceLightBuild->RetrieverGridMap.end() );
01668 }
01669 }
01670
01671
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
01690 return _ItRetriever->second.Grids[_ItSurfId].Cells[_ItCellId];
01691 }
01692
01693
01694 CIGSurfaceLightBuild::CCellCorner &CInstanceLighter::getCurrentCellInfo()
01695 {
01696 nlassert(!isEndCell());
01697
01698
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
01709 CSurfaceLightGrid &surfGrid= _ItRetriever->second.Grids[_ItSurfId];
01710
01711 sint xCell, yCell;
01712 xCell= _ItCellId%surfGrid.Width;
01713 yCell= _ItCellId/surfGrid.Width;
01714
01715 xCell+= xnb;
01716 yCell+= ynb;
01717
01718
01719 if(xCell<0 || xCell>=(sint)surfGrid.Width)
01720 return false;
01721 if(yCell<0 || yCell>=(sint)surfGrid.Height)
01722 return false;
01723
01724
01725 uint nbId= yCell*surfGrid.Width + xCell;
01726
01727
01728 if( !_ItRetrieverInfo->second.Grids[_ItSurfId].Cells[nbId].InSurface )
01729 return false;
01730
01731
01732
01733 return true;
01734 }
01735
01736
01737 CSurfaceLightGrid::CCellCorner &CInstanceLighter::getCurrentNeighborCell(sint xnb, sint ynb)
01738 {
01739 nlassert(isCurrentNeighborCellInSurface(xnb, ynb));
01740
01741
01742 CSurfaceLightGrid &surfGrid= _ItRetriever->second.Grids[_ItSurfId];
01743
01744 sint xCell, yCell;
01745 xCell= _ItCellId%surfGrid.Width;
01746 yCell= _ItCellId/surfGrid.Width;
01747
01748 xCell+= xnb;
01749 yCell+= ynb;
01750
01751 uint nbId= yCell*surfGrid.Width + xCell;
01752
01753
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
01764 CIGSurfaceLightBuild::CSurface &surfGrid= _ItRetrieverInfo->second.Grids[_ItSurfId];
01765
01766 sint xCell, yCell;
01767 xCell= _ItCellId%surfGrid.Width;
01768 yCell= _ItCellId/surfGrid.Width;
01769
01770 xCell+= xnb;
01771 yCell+= ynb;
01772
01773 uint nbId= yCell*surfGrid.Width + xCell;
01774
01775
01776 return surfGrid.Cells[nbId];
01777 }
01778
01779
01780
01781 void CInstanceLighter::dilateLightingOnSurfaceCells()
01782 {
01783
01784 beginCell();
01785
01786 while( !isEndCell() )
01787 {
01788 progressCell("Dilate Surfaces grids");
01789
01790
01791 CIGSurfaceLightBuild::CCellCorner &cellInfo= getCurrentCellInfo();
01792 CSurfaceLightGrid::CCellCorner &cell= getCurrentCell();
01793
01794
01795 if(!cellInfo.InSurface)
01796 {
01797
01798 uint wgtSunContribution= 0;
01799 uint wgtSunCount= 0;
01800
01801 for(sint ynb= -1; ynb<= 1; ynb++)
01802 {
01803 for(sint xnb= -1; xnb<= 1; xnb++)
01804 {
01805
01806 if( xnb==0 && ynb==0 )
01807 continue;
01808
01809 if( isCurrentNeighborCellInSurface(xnb, ynb) )
01810 {
01811
01812 CIGSurfaceLightBuild::CCellCorner &nbCellInfo= getCurrentNeighborCellInfo(xnb, ynb);
01813 CSurfaceLightGrid::CCellCorner &nbCell= getCurrentNeighborCell(xnb, ynb);
01814
01815 wgtSunContribution+= nbCell.SunContribution;
01816 wgtSunCount++;
01817
01818 for(uint lightId= 0; lightId<CSurfaceLightGrid::NumLightPerCorner; lightId++)
01819 cell.Light[lightId]= nbCell.Light[lightId];
01820
01821 cell.LocalAmbientId= nbCell.LocalAmbientId;
01822
01823
01824
01825 cellInfo.CenterPos.z= nbCellInfo.CenterPos.z;
01826 }
01827 }
01828 }
01829
01830 if(wgtSunCount>0)
01831 {
01832 cell.SunContribution= wgtSunContribution / wgtSunCount;
01833
01834
01835 cellInfo.SunContribution= cell.SunContribution;
01836 cellInfo.Dilated= true;
01837 }
01838 }
01839
01840
01841 nextCell();
01842 }
01843 }
01844
01845
01846
01847 }