NL3D::CZoneLighter Class Reference

#include <zone_lighter.h>


Static PointLights mgt.

void compilePointLightRT (uint gridSize, float gridCellSize, std::vector< CTriangle > &obstacles, bool doShadow)
 Fill CubeGrid, and set PointLightRT in _StaticPointLightQuadGrid.

void processZonePointLightRT (std::vector< CPointLightNamed > &listPointLight)
CQuadGrid< CPointLightRT * > _StaticPointLightQuadGrid
 QuadGrid of PointLights. Builded from _StaticPointLights.

std::vector< CPointLightRT_StaticPointLights
 List of PointLights.


Public Member Functions

void addLightableShape (IShape *shape, const NLMISC::CMatrix &modelMT)
void addTriangles (const IShape &shape, const NLMISC::CMatrix &modelMT, std::vector< CTriangle > &triangleArray)
void addTriangles (CLandscape &landscape, std::vector< uint > &listZone, uint order, std::vector< CTriangle > &triangleArray)
void addWaterShape (CWaterShape *shape, const NLMISC::CMatrix &MT)
 Add a water shape. This is needed to decide wether tiles are above / below water.

float attenuation (const CVector &pos, const CZoneLighter::CLightDesc &description)
 CZoneLighter ()
void init ()
void light (CLandscape &landscape, CZone &output, uint zoneToLight, const CLightDesc &description, std::vector< CTriangle > &obstacles, std::vector< uint > &listZone)
virtual void progress (const char *message, float progress)
virtual ~CZoneLighter ()
Static PointLights mgt.
void addStaticPointLight (const CPointLightNamed &pln)
 Append a static point light to compute. call at setup stage (before light() ).


Static Public Member Functions

bool isLightableShape (IShape &shape)
 check wether a shape is lightable.


Data Fields

std::vector< CZBuffer_ZBufferLandscape
CZBuffer _ZBufferObject

Private Types

typedef std::vector< CShapeInfoTShapeVect
 A vector of lightable shapes.

typedef CQuadGrid< CWaterShape * > TWaterShapeQuadGrid

Private Member Functions

void addTriangles (const CMeshBase &meshBase, const CMeshMRMGeom &meshGeom, const CMatrix &modelMT, std::vector< CTriangle > &triangleArray)
void addTriangles (const CMeshBase &meshBase, const CMeshGeom &meshGeom, const NLMISC::CMatrix &modelMT, std::vector< CTriangle > &triangleArray)
void buildZoneInformation (CLandscape &landscape, const std::vector< uint > &listZone, const CLightDesc &lightDesc)
float calcSkyContribution (sint s, sint t, float height, float skyIntensity, const CVector &normal) const
void computeTileFlagsForPositionTowardWater (const CLightDesc &lightDesc, std::vector< const CTessFace * > &tessFaces)
void excludeAllPatchFromRefineAll (CLandscape &landscape, std::vector< uint > &listZone, bool exclude)
uint getAPatch (uint process)
uint8 getMaxPhi (sint s, sint t, sint deltaS, sint deltaT, float heightPos) const
void getNormal (const NL3D::CPatch *pPatch, sint16 lumelS, sint16 lumelT, std::vector< NL3D::CPatchUVLocator > &locator, const std::vector< NL3D::CPatch::CBindInfo > &bindInfo, const std::vector< bool > &binded, std::set< uint64 > &visited, float deltaS, float deltaT, uint rotation, const NL3D::CBezierPatch &bezierPatch, uint lastEdge=5)
void getPatchNormalAndPositions (std::vector< CLumelDescriptor > &lumels, CLandscape &landscape, uint zoneToLight, uint patch, CPatchUVLocator *locator, bool *binded)
float getSkyContribution (const CVector &pos, const CVector &normal, float SkyIntensity) const
 compute the sky contribution at the given position

bool getTexture (const CMaterial &material, NLMISC::CBitmap *&result, bool &clampU, bool &clampV, uint8 &alphaTestThreshold, bool &doubleSided)
bool isLumelOnEdgeMustBeOversample (uint patch, uint edge, sint s, sint t, const std::vector< bool > &binded, const std::vector< bool > &oversampleEdges, std::vector< CPatchUVLocator > &locator, uint8 shadowed, std::vector< std::vector< uint8 > > &shadowBuffer)
void lightShapes (uint zoneID, const CLightDesc &description)
 Launch a set of threads to perform lighting of lightable shapes.

void lightSingleShape (CShapeInfo &lsi, const CLightDesc &description, uint cpu)
 Compute the lighting for a single lightable shape.

void lightWater (CWaterShape &ws, const CMatrix &MT, const CLightDesc &description, uint cpu)
 Compute the lighting for a water shape.

void makeQuadGridFromWaterShapes (NLMISC::CAABBox zoneBBox)
void processCalc (uint process, const CLightDesc &description)
void processLightableShapeCalc (uint process, TShapeVect *shapeToLit, uint firstShape, uint lastShape, const CLightDesc &description)
 Process lighting for a set of lightable shapes. This is called by the threads created by lightShapes().

void setTileFlagsToDefault (std::vector< const CTessFace * > &tessFaces)

Static Private Member Functions

void copyTileFlags (CZone &destZone, const CZone &srcZone)

Private Attributes

std::vector< std::vector<
CBezierPatch > > 
_BezierPatch
std::vector< std::vector<
std::vector< bool > > > 
_Binded
std::vector< std::vector<
std::vector< CPatch::CBindInfo > > > 
_BindInfo
std::map< std::string, NLMISC::CBitmap_Bitmaps
std::vector< CBorderVertex_BorderVertices
uint64 _CPUMask
NLMISC::CVector _GetNormalNormal
const NL3D::CPatch_GetNormalPatch
uint _GetNormalRadius
uint _GetNormalSqRadius
std::vector< float > _HeightField
sint _HeightFieldCellCount
float _HeightfieldCellSize
NLMISC::CVector _K [256][8]
NL3D::CLandscape_Landscape
std::vector< uint_LastPatchComputed
TShapeVect _LightableShapes
 lightable shapes

std::vector< std::vector<
std::vector< CPatchUVLocator > > > 
_Locator
std::vector< std::vector<
CLumelDescriptor > > 
_Lumels
NLMISC::CFastMutex _Mutex
uint _NumberOfPatchComputed
uint _NumLightableShapesProcessed
NLMISC::CVector _OrigineHeightField
std::vector< std::vector<
bool > > 
_OversampleEdges
NLMISC::CSynchronized< std::vector<
bool > > 
_PatchComputed
std::vector< CPatchInfo_PatchInfo
uint _ProcessCount
volatile uint _ProcessExited
CQuadGrid< const CTriangle * > _QuadGrid [10]
NLMISC::CRandom _Random
NLMISC::CMatrix _RayBasis
std::vector< std::vector<
uint8 > > 
_ShadowArray
float _ShadowBias
bool _Softshadow
NLMISC::CVector _SunDirection
TWaterShapeQuadGrid _WaterShapeQuadGrid
TShapeVect _WaterShapes
bool _ZBufferOverflow
std::map< uint, uint_ZoneId
uint _ZoneToLight

Static Private Attributes

sint16 _GetNormalDeltaS [4] = { -1, 0, 1, 0 }
sint16 _GetNormalDeltaT [4] = { 0, 1, 0, -1 }

Friends

class CCalcLightableShapeRunnable
class NL3D::CLightRunnable
class NL3D::CRenderZBuffer


Member Typedef Documentation

typedef std::vector<CShapeInfo> NL3D::CZoneLighter::TShapeVect [private]
 

A vector of lightable shapes.

Definition at line 403 of file zone_lighter.h.

Referenced by NL3D::CCalcLightableShapeRunnable::CCalcLightableShapeRunnable(), and processLightableShapeCalc().

typedef CQuadGrid<CWaterShape *> NL3D::CZoneLighter::TWaterShapeQuadGrid [private]
 

Definition at line 605 of file zone_lighter.h.


Constructor & Destructor Documentation

CZoneLighter::CZoneLighter  ) 
 

Definition at line 245 of file zone_lighter.cpp.

00245                             : _PatchComputed ("PatchComputed")
00246 {
00247 }

virtual NL3D::CZoneLighter::~CZoneLighter  )  [inline, virtual]
 

Definition at line 70 of file zone_lighter.h.

00070 {}


Member Function Documentation

void CZoneLighter::addLightableShape IShape shape,
const NLMISC::CMatrix modelMT
 

Some shape (water shapes for now) can be lit. This add such a shape to the process of lighting.

See also:
isLightableShape()

Definition at line 2773 of file zone_lighter.cpp.

References _LightableShapes, NL3D::CZoneLighter::CShapeInfo::MT, and NL3D::CZoneLighter::CShapeInfo::Shape.

02774 {
02775         CShapeInfo lsi;
02776         lsi.MT = MT;
02777         lsi.Shape = shape;
02778         _LightableShapes.push_back(lsi);
02779 }

void CZoneLighter::addStaticPointLight const CPointLightNamed pln  ) 
 

Append a static point light to compute. call at setup stage (before light() ).

Definition at line 3179 of file zone_lighter.cpp.

References NL3D::CZoneLighter::CPointLightRT::BSphere, NLMISC::CBSphere::Center, NL3D::CPointLight::getAttenuationBegin(), NL3D::CPointLight::getAttenuationEnd(), NL3D::CPointLight::getPosition(), NL3D::CZoneLighter::CPointLightRT::OODeltaAttenuation, NL3D::CZoneLighter::CPointLightRT::PointLight, and NLMISC::CBSphere::Radius.

03180 {
03181         // build the plRT.
03182         CPointLightRT   plRT;
03183         plRT.PointLight= pln;
03184         // compute plRT.OODeltaAttenuation
03185         plRT.OODeltaAttenuation= pln.getAttenuationEnd() - pln.getAttenuationBegin();
03186         if(plRT.OODeltaAttenuation <=0 )
03187                 plRT.OODeltaAttenuation= 0;
03188         else
03189                 plRT.OODeltaAttenuation= 1.0f / plRT.OODeltaAttenuation;
03190         // compute plRT.BSphere
03191         plRT.BSphere.Center= pln.getPosition();
03192         plRT.BSphere.Radius= pln.getAttenuationEnd();
03193         // NB: FaceCubeGrid will be computed during light()
03194 
03195         // add the plRT
03196         _StaticPointLights.push_back(plRT);
03197 
03198 }

void CZoneLighter::addTriangles const CMeshBase meshBase,
const CMeshMRMGeom meshGeom,
const CMatrix modelMT,
std::vector< CTriangle > &  triangleArray
[private]
 

Definition at line 1887 of file zone_lighter.cpp.

References NL3D::CMeshBase::getMaterial(), NL3D::CMeshMRMGeom::getNbRdrPass(), NL3D::CPrimitiveBlock::getNumQuad(), NL3D::CPrimitiveBlock::getNumTri(), NL3D::CPrimitiveBlock::getQuadPointer(), NL3D::CMeshMRMGeom::getRdrPassMaterial(), NL3D::CMeshMRMGeom::getRdrPassPrimitiveBlock(), NL3D::CVertexBuffer::getTexCoordPointer(), getTexture(), NL3D::CPrimitiveBlock::getTriPointer(), NL3D::CMeshMRMGeom::getVertexBuffer(), NL3D::CVertexBuffer::getVertexCoordPointer(), uint, uint32, uint8, and v.

01888 {
01889         // Get the vertex buffer
01890         const CVertexBuffer &vb=meshGeom.getVertexBuffer();
01891 
01892         // For each render pass
01893         uint numRenderPass=meshGeom.getNbRdrPass(0);
01894         for (uint pass=0; pass<numRenderPass; pass++)
01895         {
01896                 // Get the primitive block
01897                 const CPrimitiveBlock &primitive=meshGeom.getRdrPassPrimitiveBlock ( 0, pass);
01898 
01899                 // Get the material
01900                 const CMaterial &material = meshBase.getMaterial (meshGeom.getRdrPassMaterial (0, pass));
01901 
01902                 // ** Get the bitmap
01903 
01904                 // Texture informations, not NULL only if texture is used for alpha test
01905                 CBitmap *texture;
01906                 bool clampU;
01907                 bool clampV;
01908                 uint8 alphaTestThreshold;
01909                 bool doubleSided;
01910                 if (getTexture (material, texture, clampU, clampV, alphaTestThreshold, doubleSided))
01911                 {
01912                         // Dump triangles
01913                         const uint32* triIndex=primitive.getTriPointer ();
01914                         uint numTri=primitive.getNumTri ();
01915                         uint tri;
01916                         for (tri=0; tri<numTri; tri++)
01917                         {
01918                                 // Vertex
01919                                 CVector v0=modelMT*(*(CVector*)vb.getVertexCoordPointer (triIndex[tri*3]));
01920                                 CVector v1=modelMT*(*(CVector*)vb.getVertexCoordPointer (triIndex[tri*3+1]));
01921                                 CVector v2=modelMT*(*(CVector*)vb.getVertexCoordPointer (triIndex[tri*3+2]));
01922 
01923                                 // UV
01924                                 float u[3];
01925                                 float v[3];
01926                                 for (uint i=0; i<3; i++)
01927                                 {
01928                                         // Get UV coordinates
01929                                         float *uv = (float*)vb.getTexCoordPointer (triIndex[tri*3+i], 0);
01930                                         if (uv)
01931                                         {
01932                                                 // Copy it
01933                                                 u[i] = uv[0];
01934                                                 v[i] = uv[1];
01935                                         }
01936                                 }
01937 
01938                                 // Make a triangle
01939                                 triangleArray.push_back (CTriangle (NLMISC::CTriangle (v0, v1, v2), doubleSided, texture, clampU, clampV, u, v, 
01940                                         alphaTestThreshold));
01941                         }
01942 
01943                         // Dump quad
01944                         triIndex=primitive.getQuadPointer ();
01945                         numTri=primitive.getNumQuad ();
01946                         for (tri=0; tri<numTri; tri++)
01947                         {
01948                                 // Vertex
01949                                 CVector v0=modelMT*(*(CVector*)vb.getVertexCoordPointer (triIndex[tri*4]));
01950                                 CVector v1=modelMT*(*(CVector*)vb.getVertexCoordPointer (triIndex[tri*4+1]));
01951                                 CVector v2=modelMT*(*(CVector*)vb.getVertexCoordPointer (triIndex[tri*4+2]));
01952                                 CVector v3=modelMT*(*(CVector*)vb.getVertexCoordPointer (triIndex[tri*4+3]));
01953 
01954                                 // UV
01955                                 float u[4];
01956                                 float v[4];
01957                                 for (uint i=0; i<4; i++)
01958                                 {
01959                                         // Get UV coordinates
01960                                         float *uv = (float*)vb.getTexCoordPointer (triIndex[tri*4+i], 0);
01961                                         if (uv)
01962                                         {
01963                                                 // Copy it
01964                                                 u[i] = uv[0];
01965                                                 v[i] = uv[1];
01966                                         }
01967                                 }
01968 
01969                                 // Make 2 triangles
01970                                 triangleArray.push_back (CTriangle (NLMISC::CTriangle (v0, v1, v2), doubleSided, texture, clampU, clampV, u, v, 
01971                                         alphaTestThreshold));
01972                                 u[1] = u[2];
01973                                 u[2] = u[3];
01974                                 v[1] = v[2];
01975                                 v[2] = v[3];
01976                                 triangleArray.push_back (CTriangle (NLMISC::CTriangle (v0, v2, v3), doubleSided, texture, clampU, clampV, u, v, 
01977                                         alphaTestThreshold));
01978                         }
01979                 }
01980         }
01981 }

void CZoneLighter::addTriangles const CMeshBase meshBase,
const CMeshGeom meshGeom,
const NLMISC::CMatrix modelMT,
std::vector< CTriangle > &  triangleArray
[private]
 

Definition at line 1717 of file zone_lighter.cpp.

References NL3D::CMeshBase::getMaterial(), NL3D::CMeshGeom::getNbMatrixBlock(), NL3D::CMeshGeom::getNbRdrPass(), NL3D::CPrimitiveBlock::getNumQuad(), NL3D::CPrimitiveBlock::getNumTri(), NL3D::CPrimitiveBlock::getQuadPointer(), NL3D::CMeshGeom::getRdrPassMaterial(), NL3D::CMeshGeom::getRdrPassPrimitiveBlock(), NL3D::CVertexBuffer::getTexCoordPointer(), getTexture(), NL3D::CPrimitiveBlock::getTriPointer(), NL3D::CMeshGeom::getVertexBuffer(), NL3D::CVertexBuffer::getVertexCoordPointer(), uint, uint32, uint8, and v.

01718 {
01719         // Get the vertex buffer
01720         const CVertexBuffer &vb=meshGeom.getVertexBuffer();
01721 
01722         // For each matrix block
01723         uint numBlock=meshGeom.getNbMatrixBlock();
01724         for (uint block=0; block<numBlock; block++)
01725         {
01726                 // For each render pass
01727                 uint numRenderPass=meshGeom.getNbRdrPass(block);
01728                 for (uint pass=0; pass<numRenderPass; pass++)
01729                 {
01730                         // Get the primitive block
01731                         const CPrimitiveBlock &primitive=meshGeom.getRdrPassPrimitiveBlock ( block, pass);
01732 
01733                         // Get the material
01734                         const CMaterial &material = meshBase.getMaterial (meshGeom.getRdrPassMaterial ( block, pass));
01735 
01736                         // ** Get the bitmap
01737 
01738                         // Texture informations, not NULL only if texture is used for alpha test
01739                         CBitmap *texture;
01740                         bool clampU;
01741                         bool clampV;
01742                         uint8 alphaTestThreshold;
01743                         bool doubleSided;
01744                         if (getTexture (material, texture, clampU, clampV, alphaTestThreshold, doubleSided))
01745                         {
01746                                 // Dump triangles
01747                                 const uint32* triIndex=primitive.getTriPointer ();
01748                                 uint numTri=primitive.getNumTri ();
01749                                 uint tri;
01750                                 for (tri=0; tri<numTri; tri++)
01751                                 {
01752                                         // Vertex
01753                                         CVector v0=modelMT*(*(CVector*)vb.getVertexCoordPointer (triIndex[tri*3]));
01754                                         CVector v1=modelMT*(*(CVector*)vb.getVertexCoordPointer (triIndex[tri*3+1]));
01755                                         CVector v2=modelMT*(*(CVector*)vb.getVertexCoordPointer (triIndex[tri*3+2]));
01756 
01757                                         // UV
01758                                         float u[3];
01759                                         float v[3];
01760                                         for (uint i=0; i<3; i++)
01761                                         {
01762                                                 // Get UV coordinates
01763                                                 float *uv = (float*)vb.getTexCoordPointer (triIndex[tri*3+i], 0);
01764                                                 if (uv)
01765                                                 {
01766                                                         // Copy it
01767                                                         u[i] = uv[0];
01768                                                         v[i] = uv[1];
01769                                                 }
01770                                         }
01771 
01772                                         // Make a triangle
01773                                         triangleArray.push_back (CTriangle (NLMISC::CTriangle (v0, v1, v2), doubleSided, texture, clampU, clampV, u, v, 
01774                                                 alphaTestThreshold));
01775                                 }
01776 
01777                                 // Dump quad
01778                                 triIndex=primitive.getQuadPointer ();
01779                                 numTri=primitive.getNumQuad ();
01780                                 for (tri=0; tri<numTri; tri++)
01781                                 {
01782                                         // Vertex
01783                                         CVector v0=modelMT*(*(CVector*)vb.getVertexCoordPointer (triIndex[tri*4]));
01784                                         CVector v1=modelMT*(*(CVector*)vb.getVertexCoordPointer (triIndex[tri*4+1]));
01785                                         CVector v2=modelMT*(*(CVector*)vb.getVertexCoordPointer (triIndex[tri*4+2]));
01786                                         CVector v3=modelMT*(*(CVector*)vb.getVertexCoordPointer (triIndex[tri*4+3]));
01787 
01788                                         // UV
01789                                         float u[4];
01790                                         float v[4];
01791                                         for (uint i=0; i<4; i++)
01792                                         {
01793                                                 // Get UV coordinates
01794                                                 float *uv = (float*)vb.getTexCoordPointer (triIndex[tri*4+i], 0);
01795                                                 if (uv)
01796                                                 {
01797                                                         // Copy it
01798                                                         u[i] = uv[0];
01799                                                         v[i] = uv[1];
01800                                                 }
01801                                         }
01802 
01803                                         // Make 2 triangles
01804                                         triangleArray.push_back (CTriangle (NLMISC::CTriangle (v0, v1, v2), doubleSided, texture, clampU, clampV, u, v, 
01805                                                 alphaTestThreshold));
01806                                         u[1] = u[2];
01807                                         u[2] = u[3];
01808                                         v[1] = v[2];
01809                                         v[2] = v[3];
01810                                         triangleArray.push_back (CTriangle (NLMISC::CTriangle (v0, v2, v3), doubleSided, texture, clampU, clampV, u, v, 
01811                                                 alphaTestThreshold));
01812                                 }
01813                         }
01814                 }
01815         }
01816 }

void CZoneLighter::addTriangles const IShape shape,
const NLMISC::CMatrix modelMT,
std::vector< CTriangle > &  triangleArray
 

Definition at line 1670 of file zone_lighter.cpp.

References addTriangles(), NL3D::CMeshMRM::getMeshGeom(), NL3D::CMeshMultiLod::getMeshGeom(), and NL3D::CMesh::getMeshGeom().

01671 {
01672         // Cast to CMesh
01673         const CMesh *mesh=dynamic_cast<const CMesh*>(&shape);
01674 
01675         // Cast to CMeshMultiLod
01676         const CMeshMultiLod *meshMulti=dynamic_cast<const CMeshMultiLod*>(&shape);
01677 
01678         // Cast to CMeshMultiLod
01679         const CMeshMRM *meshMRM=dynamic_cast<const CMeshMRM*>(&shape);
01680 
01681         // It is a mesh ?
01682         if (mesh)
01683         {
01684                 // Add its triangles
01685                 addTriangles (*mesh, mesh->getMeshGeom (), modelMT, triangleArray);
01686         }
01687         // It is a CMeshMultiLod ?
01688         else if (meshMulti)
01689         {
01690                 // Get the first geommesh
01691                 const IMeshGeom *meshGeom=&meshMulti->getMeshGeom (0);
01692 
01693                 // Dynamic cast
01694                 const CMeshGeom *geomMesh=dynamic_cast<const CMeshGeom*>(meshGeom);
01695                 if (geomMesh)
01696                 {
01697                         addTriangles (*meshMulti, *geomMesh, modelMT, triangleArray);
01698                 }
01699 
01700                 // Dynamic cast
01701                 const CMeshMRMGeom *mrmGeomMesh=dynamic_cast<const CMeshMRMGeom*>(meshGeom);
01702                 if (mrmGeomMesh)
01703                 {
01704                         addTriangles (*meshMulti, *mrmGeomMesh, modelMT, triangleArray);
01705                 }
01706         }
01707         // It is a CMeshMultiLod ?
01708         else if (meshMRM)
01709         {
01710                 // Get the first lod mesh geom
01711                 addTriangles (*meshMRM, meshMRM->getMeshGeom (), modelMT, triangleArray);
01712         }
01713 }

void CZoneLighter::addTriangles CLandscape landscape,
std::vector< uint > &  listZone,
uint  order,
std::vector< CTriangle > &  triangleArray
 

Definition at line 1613 of file zone_lighter.cpp.

References NL3D::CTessVertex::EndPos, excludeAllPatchFromRefineAll(), NL3D::CParamCoord::getS(), NL3D::CParamCoord::getT(), NL3D::CLandscape::getTessellationLeaves(), min, NL3D::CTessFace::PVBase, NL3D::CTessFace::PVLeft, NL3D::CTessFace::PVRight, NL3D::CLandscape::refineAll(), NL3D::CLandscape::setThreshold(), NL3D::CLandscape::setTileMaxSubdivision(), uint, NL3D::CTessFace::VBase, NL3D::CTessFace::VLeft, and NL3D::CTessFace::VRight.

Referenced by addTriangles().

01614 {
01615         // Set all to refine
01616         excludeAllPatchFromRefineAll (landscape, listZone, false);
01617 
01618         // Setup the landscape
01619         landscape.setThreshold (0);
01620         landscape.setTileMaxSubdivision (order);
01621 
01622         // Refine it
01623         landscape.refineAll (CVector (0, 0, 0));
01624 
01625         // Dump tesselated triangles
01626         std::vector<const CTessFace*> leaves;
01627         landscape.getTessellationLeaves(leaves);
01628 
01629         // Number of leaves
01630         uint leavesCount=leaves.size();
01631 
01632         // Reserve the array
01633         triangleArray.reserve (triangleArray.size()+leavesCount);
01634 
01635         // Scan each leaves
01636         for (uint leave=0; leave<leavesCount; leave++)
01637         {
01638                 // Leave
01639                 const CTessFace *face=leaves[leave];
01640 
01641                 // Start and end coordinate
01642                 float startS=min (min (face->PVBase.getS(), face->PVLeft.getS()), face->PVRight.getS());
01643                 float endS=max (max (face->PVBase.getS(), face->PVLeft.getS()), face->PVRight.getS());
01644                 float startT=min (min (face->PVBase.getT(), face->PVLeft.getT()), face->PVRight.getT());
01645                 float endT=max (max (face->PVBase.getT(), face->PVLeft.getT()), face->PVRight.getT());
01646 
01647                 // Add a triangle
01648                 triangleArray.push_back (CTriangle (NLMISC::CTriangle (face->VBase->EndPos, face->VLeft->EndPos, face->VRight->EndPos)));
01649         }
01650 
01651         // Setup the landscape
01652         landscape.setThreshold (1000);
01653         landscape.setTileMaxSubdivision (0);
01654 
01655         // Remove all triangles
01656         landscape.refineAll (CVector (0, 0, 0));
01657         landscape.refineAll (CVector (0, 0, 0));
01658         landscape.refineAll (CVector (0, 0, 0));
01659         landscape.refineAll (CVector (0, 0, 0));
01660         landscape.refineAll (CVector (0, 0, 0));
01661         landscape.refineAll (CVector (0, 0, 0));
01662         landscape.refineAll (CVector (0, 0, 0));
01663         landscape.refineAll (CVector (0, 0, 0));
01664         landscape.refineAll (CVector (0, 0, 0));
01665         landscape.refineAll (CVector (0, 0, 0));
01666 }

void CZoneLighter::addWaterShape CWaterShape shape,
const NLMISC::CMatrix MT
 

Add a water shape. This is needed to decide wether tiles are above / below water.

make sure it hasn't been inserted twice

Definition at line 3057 of file zone_lighter.cpp.

References NL3D::CZoneLighter::CShapeInfo::MT, and NL3D::CZoneLighter::CShapeInfo::Shape.

03058 {
03060         CShapeInfo ci;
03061         ci.Shape = shape;
03062         ci.MT = MT;
03063         _WaterShapes.push_back(ci);
03064 }

float CZoneLighter::attenuation const CVector pos,
const CZoneLighter::CLightDesc description
 

Definition at line 3767 of file zone_lighter.cpp.

References _Random, _ZBufferLandscape, _ZBufferObject, _ZBufferOverflow, NL3D::CZoneLighter::CZBuffer::LocalZBufferXMin, NL3D::CZoneLighter::CZBuffer::LocalZBufferYMin, min, NLMISC::CRandom::rand(), NLMISC::CRandom::RandMax, sint, NL3D::CZoneLighter::CLightDesc::SoftShadowJitter, NL3D::CZoneLighter::CLightDesc::SoftShadowSamplesSqrt, testZPercentageCloserFilter(), transformVectorToZBuffer(), uint, NLMISC::CVector::x, x, NLMISC::CVector::y, y, and NLMISC::CVector::z.

Referenced by lightWater(), and processCalc().

03768 {
03769         // Clipped ?
03770 
03771         // *** Landscape attenuation
03772 
03773         // Current value
03774         float averageAttenuation = 0;
03775         float randomSum = 0;
03776 
03777         // For each sample
03778         uint sample;
03779         const uint samples = description.SoftShadowSamplesSqrt*description.SoftShadowSamplesSqrt;
03780         for (sample=0; sample<samples; sample++)
03781         {
03782                 // The zbuffer
03783                 CZBuffer &zbuffer = _ZBufferLandscape[sample];
03784 
03785                 // Get position in z buffer
03786                 CVector zPos;
03787                 transformVectorToZBuffer (zbuffer, pos, zPos);
03788 
03789                 sint x = (sint)floor (zPos.x);
03790                 sint y = (sint)floor (zPos.y);
03791 
03792                 // Get the z
03793                 float random = (float)_Random.rand () * description.SoftShadowJitter + _Random.RandMax * (1.f - description.SoftShadowJitter);
03794                 averageAttenuation += random * testZPercentageCloserFilter (zPos.x-(float)zbuffer.LocalZBufferXMin, zPos.y-(float)zbuffer.LocalZBufferYMin, zPos.z, zbuffer, description, _ZBufferOverflow);
03795                 randomSum += random;
03796         }
03797 
03798         // Average landscape attenuation
03799         averageAttenuation /= randomSum;
03800 
03801 
03802         
03803         // *** Attenuation in the object zbuffer
03804 
03805         // Get position in z buffer
03806         CVector zPos;
03807         transformVectorToZBuffer (_ZBufferObject, pos, zPos);
03808 
03809         const sint x = (sint)floor (zPos.x);
03810         const sint y = (sint)floor (zPos.y);
03811 
03812         const float objectAttenuation = testZPercentageCloserFilter (zPos.x-(float)_ZBufferObject.LocalZBufferXMin, zPos.y-(float)_ZBufferObject.LocalZBufferYMin, zPos.z, _ZBufferObject, description, _ZBufferOverflow);
03813 
03814 
03815         // *** Return the min of the both
03816         return std::min (objectAttenuation, averageAttenuation);
03817 }

void CZoneLighter::buildZoneInformation CLandscape landscape,
const std::vector< uint > &  listZone,
const CLightDesc lightDesc
[private]
 

make a quad grid of each water shape

check for each tile if it is above / below water

Definition at line 2045 of file zone_lighter.cpp.

References _BezierPatch, _Binded, _BindInfo, _GetNormalNormal, _Locator, _Lumels, _OversampleEdges, _ZoneId, _ZoneToLight, BLUR_SIZE, computeTileFlagsForPositionTowardWater(), count, easineasout(), NL3D::CTessVertex::EndPos, NL3D::CBezierPatch::evalNormal(), NL3D::CLandscape::excludePatchFromRefineAll(), NLMISC::CAABBoxExt::getAABBox(), NL3D::CPatch::getBindNeighbor(), getNormal(), NLMISC::CPlane::getNormal(), NL3D::CZone::getNumPatchs(), NL3D::CPatch::getOrderS(), NL3D::CPatch::getOrderT(), NL3D::CPatch::getPatchId(), NLMISC::getPowerOf2(), NL3D::CParamCoord::getS(), NL3D::CParamCoord::getT(), NL3D::CLandscape::getTessellationLeaves(), NL3D::CPatch::getZone(), NL3D::CLandscape::getZone(), NL3D::CZone::getZoneBB(), NL3D::CZone::getZoneId(), index, NLMISC::isPowerOf2(), NLMISC::CPlane::make(), makeQuadGridFromWaterShapes(), NL_LUMEL_BY_TILE, NL_MAX_TILES_BY_PATCH_EDGE, nlassert, NL3D::CZoneLighter::CLumelDescriptor::Normal, NLMISC::CVector::normalize(), NL3D::CTessFace::Patch, NL3D::CZoneLighter::CLumelDescriptor::Position, progress(), NL3D::CTessFace::PVBase, NL3D::CTessFace::PVLeft, NL3D::CTessFace::PVRight, NL3D::CLandscape::refineAll(), s, NL3D::CZoneLighter::CLumelDescriptor::S, NLMISC::CVector::set(), NL3D::CLandscape::setThreshold(), setTileFlagsToDefault(), NL3D::CLandscape::setTileMaxSubdivision(), sint, t, NL3D::CZoneLighter::CLumelDescriptor::T, uint, NL3D::CPatch::unpackIntoCache(), value, NL3D::CTessFace::VBase, NL3D::CTessFace::VLeft, and NL3D::CTessFace::VRight.

Referenced by light().

02046 {
02047         // Bool visit
02048         vector<vector<uint> > visited;
02049 
02050         // Zone count
02051         uint zoneCount=listZone.size();
02052 
02053         // Resize arries
02054         _Locator.resize (zoneCount);
02055         _Binded.resize (zoneCount);
02056         _BindInfo.resize (zoneCount);
02057         _BezierPatch.resize (zoneCount);
02058 
02059         // For each zone
02060         for (uint zone=0; zone<zoneCount; zone++)
02061         {
02062                 // Get num patches
02063                 uint patchCount=landscape.getZone(listZone[zone])->getNumPatchs();
02064 
02065                 // Insert zone id
02066                 _ZoneId.insert (map<uint, uint>::value_type (listZone[zone], zone));
02067 
02068                 // This is the zone to light ?
02069                 if (listZone[zone]==_ZoneToLight)
02070                 {
02071                         // Resize the arraies
02072                         _Lumels.resize(patchCount);
02073 //                      _LumelCorners.resize(patchCount);
02074 //                      _BezierPatch.resize(patchCount);
02075                         _OversampleEdges.resize(patchCount);
02076                         visited.resize(patchCount);
02077                 }
02078 
02079                 // Common arries
02080                 _Locator[zone].resize(patchCount);
02081                 _Binded[zone].resize(patchCount);
02082                 _BindInfo[zone].resize(patchCount);
02083                 _BezierPatch[zone].resize(patchCount);
02084 
02085                 // For each patch
02086                 uint patch;
02087                 for (patch=0; patch<patchCount; patch++)
02088                 {
02089                         // Get a patch pointer
02090                         const CPatch* pPatch=(const_cast<const CZone*>(landscape.getZone(listZone[zone])))->getPatch (patch);
02091 
02092                         // Progress bar
02093                         progress ("Scan all patches", (float)patch/(float)patchCount);
02094 
02095                         // Get pointer on arries
02096                         vector<bool> &binded=_Binded[zone][patch];
02097                         vector<CPatch::CBindInfo> &bindInfo=_BindInfo[zone][patch];
02098                         vector<CPatchUVLocator> &locator=_Locator[zone][patch];
02099                         CBezierPatch &bezierPatch=_BezierPatch[zone][patch];
02100                         binded.resize (4, false);
02101                         bindInfo.resize (4);
02102                         locator.resize (4);
02103 
02104                         // Contruct the patch
02105                         bezierPatch=*pPatch->unpackIntoCache();
02106 
02107                         // Same zone ?
02108                         if (listZone[zone]==_ZoneToLight)
02109                         {
02110                                 // oversample this edge
02111                                 _OversampleEdges[patch].resize (4, false);
02112                         }
02113 
02114                         // *** Build bind info
02115 
02116                         // *** Build neighboorhood information
02117                         uint edge;
02118                         for (edge=0; edge<4; edge++)
02119                         {
02120                                 // Bond neighbor
02121                                 pPatch->getBindNeighbor (edge, bindInfo[edge]);
02122 
02123                                 // Patch binded
02124                                 if (bindInfo[edge].NPatchs>0)
02125                                 {
02126                                         // This edeg is binded
02127                                         binded[edge]=true;
02128 
02129                                         // Same zone ?
02130                                         if ((listZone[zone]==_ZoneToLight)&&(bindInfo[edge].Zone->getZoneId()!=_ZoneToLight))
02131                                         {
02132                                                 // oversample this edge
02133                                                 _OversampleEdges[patch][edge]=true;
02134                                         }
02135                                         locator[edge].build (pPatch, edge, bindInfo[edge]);
02136                                 }
02137                                 else
02138                                 {
02139                                         if (listZone[zone]==_ZoneToLight)
02140                                         {
02141                                                 // oversample this edge
02142                                                 _OversampleEdges[patch][edge]=true;
02143                                         }
02144                                 }
02145                         }
02146 
02147                         // This is the zone to light ?
02148                         if (listZone[zone]==_ZoneToLight)
02149                         {
02150                                 // *** Resize lumel array for this patch
02151 
02152                                 // Get patch order
02153                                 uint orderS=pPatch->getOrderS();
02154                                 uint orderT=pPatch->getOrderT();
02155 
02156                                 // Number of lumels
02157                                 uint lumelCount = orderS*orderT*16;
02158                                 uint lumelCornerCount = (orderS*4+1)*(orderT*4+1);
02159 
02160                                 // Resize the lumel descriptor
02161                                 CLumelDescriptor descriptor;
02162                                 descriptor.Normal.set (0,0,0);
02163                                 descriptor.Position.set (0,0,0);
02164                                 descriptor.S=0;
02165                                 descriptor.T=0;
02166                                 _Lumels[patch].resize (lumelCount, descriptor);
02167                                 visited[patch].resize (lumelCount, 0);
02168 //                              _LumelCorners[patch].resize (lumelCornerCount);
02169 
02170 
02171                                 // *** Unexclude this patch
02172 
02173                                 // Exclude all the patches from refine all
02174                                 landscape.excludePatchFromRefineAll (listZone[zone], patch, false);
02175                         }
02176                         else
02177                         {
02178                                 // Exclude all the patches from refine all
02179                                 landscape.excludePatchFromRefineAll (listZone[zone], patch, true);
02180                         }
02181                 }
02182         }
02183 
02184         // *** Now tesselate this zone to shadow casters accuracy
02185 
02186         // Setup the landscape
02187         landscape.setThreshold (0);
02188         landscape.setTileMaxSubdivision (0);
02189 
02190         // Refine all
02191         progress ("Refine landscape to shadow accuracy", 0.5f);
02192         landscape.refineAll (CVector (0, 0, 0));
02193 
02194         // Get tesselated faces
02195         std::vector<const CTessFace*> leaves;
02196         landscape.getTessellationLeaves(leaves);
02197         
02198 
02199         
02200         
02201         if (_WaterShapes.size() != 0) // any water shape in this zone ?
02202         {
02204                 makeQuadGridFromWaterShapes(landscape.getZone(_ZoneToLight)->getZoneBB().getAABBox());
02205 
02207                 computeTileFlagsForPositionTowardWater(lightDesc, leaves);
02208         }
02209         else
02210         {
02211                 setTileFlagsToDefault(leaves);
02212         }
02213         
02214 
02215         // Id of this zone in the array
02216         uint zoneNumber=_ZoneId[_ZoneToLight];
02217 
02218         // Scan each leaves
02219         uint leavesCount=leaves.size();
02220         uint leave;
02221         for (leave=0; leave<leavesCount; leave++)
02222         {
02223                 // Progress bar
02224                 if ( (leave&0xff) == 0)
02225                         progress ("Precompute lumel position", (float)leave/(float)leavesCount);
02226 
02227                 // Leave
02228                 const CTessFace *face=leaves[leave];
02229 
02230                 // Get zone id
02231                 if (face->Patch->getZone()->getZoneId()==_ZoneToLight)
02232                 {
02233                         // Get a patch pointer
02234                         const CPatch* pPatch=face->Patch;
02235 
02236                         // Get order
02237                         uint orderS=pPatch->getOrderS();
02238                         uint orderT=pPatch->getOrderT();
02239 
02240                         // *** Base Coordinates
02241 
02242                         CVector pos[15];
02243                         pos[0]=face->VBase->EndPos;             // p0
02244                         pos[1]=face->VRight->EndPos;
02245                         pos[2]=face->VLeft->EndPos;             // p2
02246                         pos[3]=(pos[1]+pos[2])/2;
02247                         pos[4]=(pos[0]+pos[1])/2;                               // p4
02248                         pos[5]=(pos[0]+pos[2])/2;
02249                         pos[6]=(pos[0]+pos[3])/2;                               // p6
02250                         pos[7]=(pos[2]+pos[3])/2;
02251                         pos[8]=(pos[1]+pos[3])/2;                               // p8
02252                         pos[9]=(pos[0]+pos[4])/2;
02253                         pos[10]=(pos[1]+pos[4])/2;                              // p10
02254                         pos[11]=(pos[0]+pos[5])/2;
02255                         pos[12]=(pos[2]+pos[5])/2;                              // p12
02256                         pos[13]=(pos[3]+pos[5])/2;
02257                         pos[14]=(pos[3]+pos[4])/2;                              // p14
02258 
02259                         float s0=face->PVBase.getS();
02260                         float s1=face->PVRight.getS();
02261                         float s2=face->PVLeft.getS();
02262                         float s3=(s1+s2)/2;
02263                         float s4=(s0+s1)/2;
02264                         float s5=(s0+s2)/2;
02265                         float s6=(s4+s5)/2;
02266                         float s7=(s2+s3)/2;
02267                         float s8=(s1+s3)/2;
02268 
02269                         float t0=face->PVBase.getT();
02270                         float t1=face->PVRight.getT();
02271                         float t2=face->PVLeft.getT();
02272                         float t3=(t1+t2)/2;
02273                         float t4=(t0+t1)/2;
02274                         float t5=(t0+t2)/2;
02275                         float t6=(t4+t5)/2;
02276                         float t7=(t2+t3)/2;
02277                         float t8=(t1+t3)/2;
02278 
02279                         // *** Interpolated value
02280                         CVector interpolatedP[10]=
02281                         {
02282                                 (pos[0]+pos[6])/2,
02283                                 (pos[4]+pos[6])/2,
02284                                 (pos[4]+pos[8])/2,
02285                                 (pos[1]+pos[8])/2,
02286                                 (pos[5]+pos[6])/2,
02287                                 (pos[3]+pos[6])/2,
02288                                 (pos[3]+pos[8])/2,
02289                                 (pos[5]+pos[7])/2,
02290                                 (pos[3]+pos[7])/2,
02291                                 (pos[2]+pos[7])/2,
02292                         };
02293 
02294                         // Does the border are snapped ?
02295                         uint sBase = (uint)floor ((float)orderS * face->PVBase.getS() + 0.5);
02296                         uint tBase = (uint)floor ((float)orderT * face->PVBase.getT() + 0.5);
02297                         uint sLeft = (uint)floor ((float)orderS * face->PVLeft.getS() + 0.5);
02298                         uint tLeft = (uint)floor ((float)orderT * face->PVLeft.getT() + 0.5);
02299                         uint sRight = (uint)floor ((float)orderS * face->PVRight.getS() + 0.5);
02300                         uint tRight = (uint)floor ((float)orderT * face->PVRight.getT() + 0.5);
02301                         bool snapedLeft[2]=
02302                         {
02303                                 (sBase == 0) && (sRight == 0),
02304                                 (sBase == 0) && (sLeft == 0),
02305                         };
02306                         bool snapedRight[2]=
02307                         {
02308                                 (sBase == orderS) && (sRight == orderS),
02309                                 (sBase == orderS) && (sLeft == orderS),
02310                         };
02311                         bool snapedTop[2]=
02312                         {
02313                                 (tBase == 0) && (tRight == 0),
02314                                 (tBase == 0) && (tLeft == 0),
02315                         };
02316                         bool snapedBottom[2]=
02317                         {
02318                                 (tBase == orderT) && (tRight == orderT),
02319                                 (tBase == orderT) && (tLeft == orderT),
02320                         };
02321                         bool snapedBorder[2]=
02322                         {
02323                                 snapedLeft[0]||snapedRight[0]||snapedTop[0]||snapedBottom[0],
02324                                 snapedLeft[1]||snapedRight[1]||snapedTop[1]||snapedBottom[1],
02325                         };
02326 
02327                         bool snapedCorner[3]=
02328                         {
02329                                 ((sBase == 0) && ((tBase == 0) || (tBase == orderT))) || 
02330                                 ((sBase == orderS) && ((tBase == 0) || (tBase == orderT))),
02331                                 ((sRight == 0) && ((tRight == 0) || (tRight == orderT))) || 
02332                                 ((sRight == orderS) && ((tRight == 0) || (tRight == orderT))),
02333                                 ((sLeft == 0) && ((tLeft == 0) || (tLeft == orderT))) || 
02334                                 ((sLeft == orderS) && ((tLeft == 0) || (tLeft == orderT))),
02335                         };
02336 
02337                         // Snap on the border
02338                         uint i;
02339                         for (i=0; i<8; i++)
02340                         {
02341                                 // Snaped on left ?
02342                                 if (snapedBorder[VertexThanCanBeSnappedOnABorder[i][1]])
02343                                 {
02344                                         // Compute the border vertex
02345                                         interpolatedP[VertexThanCanBeSnappedOnABorder[i][0]] = (pos[VertexThanCanBeSnappedOnABorder[i][2]]
02346                                                 + pos[VertexThanCanBeSnappedOnABorder[i][3]])/2;
02347                                 }
02348                         }
02349 
02350                         // Snap on the corner
02351                         for (i=0; i<3; i++)
02352                         {
02353                                 // Snaped on a corner ?
02354                                 uint tesselCornerIndex = VertexThanCanBeSnappedOnACorner[i][1];
02355                                 if ( snapedCorner[tesselCornerIndex] )
02356                                 {
02357                                         // Compute the border vertex
02358                                         interpolatedP[VertexThanCanBeSnappedOnACorner[i][0]] = pos[tesselCornerIndex];
02359                                 }
02360                         }
02361 
02362                         float interpolatedS[10]=
02363                         {
02364                                 (s0+s6)/2,
02365                                 (s4+s6)/2,
02366                                 (s4+s8)/2,
02367                                 (s1+s8)/2,
02368                                 (s5+s6)/2,
02369                                 (s3+s6)/2,
02370                                 (s3+s8)/2,
02371                                 (s5+s7)/2,
02372                                 (s3+s7)/2,
02373                                 (s2+s7)/2,
02374                         };
02375                         
02376                         float interpolatedT[10]=
02377                         {
02378                                 (t0+t6)/2,
02379                                 (t4+t6)/2,
02380                                 (t4+t8)/2,
02381                                 (t1+t8)/2,
02382                                 (t5+t6)/2,
02383                                 (t3+t6)/2,
02384                                 (t3+t8)/2,
02385                                 (t5+t7)/2,
02386                                 (t3+t7)/2,
02387                                 (t2+t7)/2,
02388                         };
02389 
02390                         for (i=0; i<10; i++)
02391                         {
02392                                 sint s=(sint)((float)orderS*4*interpolatedS[i]);
02393                                 sint t=(sint)((float)orderT*4*interpolatedT[i]);
02394 
02395                                 if ((s>=0)&&(s<(sint)orderS*4)&&(t>=0)&&(t<(sint)orderT*4))
02396                                 {
02397                                         // Triangle index
02398                                         uint index=s+t*orderS*4;
02399 
02400                                         // Ge tthe patch id
02401                                         uint patchId=pPatch->getPatchId();
02402 
02403                                         // Get lumel array
02404                                         vector<CLumelDescriptor> &lumels=_Lumels[patchId];
02405 
02406                                         // Visited
02407                                         visited[patchId][index]++;
02408 
02409                                         // Position
02410                                         lumels[index].Position+=interpolatedP[i];
02411                                 }
02412                         }
02413                 }
02414         }
02415 
02416         // *** Now, finalise patch informations for shadow source positions
02417 
02418         // For each patches
02419         uint patchCount=landscape.getZone(_ZoneToLight)->getNumPatchs();
02420         uint patch;
02421         for (patch=0; patch<patchCount; patch++)
02422         {
02423                 // Info
02424                 progress ("Finalize lumel positions", (float)patch/(float)patchCount);
02425 
02426                 // *** Resize lumel array for this patch
02427 
02428                 // Get a patch pointer
02429                 const CPatch* pPatch=(const_cast<const CZone*>(landscape.getZone(_ZoneToLight)))->getPatch (patch);
02430                 uint orderS=pPatch->getOrderS();
02431                 uint orderT=pPatch->getOrderT();
02432 
02433                 // Get lumel array
02434                 vector<CLumelDescriptor> &lumels=_Lumels[patch];
02435 
02436                 // *** Average position
02437 
02438                 // Renormalize
02439                 nlassert (isPowerOf2 (orderS));
02440                 nlassert (isPowerOf2 (orderT));
02441                 uint lumelS=4<<getPowerOf2 (orderS);
02442                 uint lumelT=4<<getPowerOf2 (orderT);
02443 
02444                 for (uint t=0; t<lumelT; t++)
02445                 for (uint s=0; s<lumelS; s++)
02446                 {
02447                         // Lumel index
02448                         uint lumelIndex=s+t*lumelS;
02449 
02450                         // *** Number of visit
02451                         uint visitedCount=visited[patch][lumelIndex];
02452                         
02453                         // If visited, renormalise other values
02454                         if (visitedCount)
02455                         {
02456                                 // Normalise position
02457                                 lumels[lumelIndex].Position/=(float)visitedCount;
02458                         }
02459 
02460                         // Not visited for next pass
02461                         visited[patch][lumelIndex]=false;
02462                 }
02463         }
02464         
02465         // *** Now tesselate this zone to shadow receivers accuracy
02466 
02467         // Setup the landscape
02468         landscape.setThreshold (0);
02469         landscape.setTileMaxSubdivision (4);
02470 
02471         // Refine all
02472         progress ("Refine landscape to lumels", 0.5f);
02473         landscape.refineAll (CVector (0, 0, 0));
02474 
02475         // Get tesselated faces
02476         leaves.clear ();
02477         landscape.getTessellationLeaves(leaves);
02478 
02479         // Scan each leaves
02480         leavesCount=leaves.size();
02481         for (leave=0; leave<leavesCount; leave++)
02482         {
02483                 // Progress bar
02484                 if ( (leave&0xff) == 0)
02485                         progress ("Precompute tesselation", (float)leave/(float)leavesCount);
02486 
02487                 // Leave
02488                 const CTessFace *face=leaves[leave];
02489 
02490                 // Get zone id
02491                 if (face->Patch->getZone()->getZoneId()==_ZoneToLight)
02492                 {
02493                         // Get a patch pointer
02494                         const CPatch* pPatch=face->Patch;
02495 
02496                         // Get order
02497                         uint orderS=pPatch->getOrderS();
02498                         uint orderT=pPatch->getOrderT();
02499 
02500                         // Coordinates
02501                         float fS=(face->PVBase.getS()+face->PVLeft.getS()+face->PVRight.getS())/3.f;
02502                         float fT=(face->PVBase.getT()+face->PVLeft.getT()+face->PVRight.getT())/3.f;
02503                         uint s=(uint)((float)orderS*4*fS);
02504                         uint t=(uint)((float)orderT*4*fT);
02505                         nlassert (s>=0);
02506                         nlassert (s<orderS*4);
02507                         nlassert (t>=0);
02508                         nlassert (t<orderT*4);
02509 
02510                         // Triangle index
02511                         uint index=s+t*orderS*4;
02512 
02513                         // Ge tthe patch id
02514                         uint patchId=pPatch->getPatchId();
02515 
02516                         // Get lumel array
02517                         vector<CLumelDescriptor> &lumels=_Lumels[patchId];
02518 
02519                         // Visited
02520                         visited[patchId][index]++;
02521 
02522                         // Lumel s and t
02523                         lumels[index].S+=fS;
02524                         lumels[index].T+=fT;
02525 
02526                         // Normal
02527                         CPlane plane;
02528                         plane.make (face->VBase->EndPos, face->VLeft->EndPos, face->VRight->EndPos);
02529                         lumels[index].Normal+=plane.getNormal();
02530                 }
02531         }
02532 
02533         // *** Now, finalise patch informations
02534 
02535         // For each patches
02536         patchCount=landscape.getZone(_ZoneToLight)->getNumPatchs();
02537         for (patch=0; patch<patchCount; patch++)
02538         {
02539                 // Info
02540                 progress ("Finalize patches", (float)patch/(float)patchCount);
02541 
02542                 // *** Resize lumel array for this patch
02543 
02544                 // Get a patch pointer
02545                 const CPatch* pPatch=(const_cast<const CZone*>(landscape.getZone(_ZoneToLight)))->getPatch (patch);
02546                 uint orderS=pPatch->getOrderS();
02547                 uint orderT=pPatch->getOrderT();
02548 
02549                 // Get lumel array
02550                 vector<CLumelDescriptor> &lumels=_Lumels[patch];
02551 
02552                 // *** Compute an interpolated normal
02553 
02554                 // Get pointer on arries
02555                 vector<bool> &binded=_Binded[zoneNumber][patch];
02556                 vector<CPatchUVLocator> &locator=_Locator[zoneNumber][patch];
02557                 vector<CPatch::CBindInfo> &bindInfo=_BindInfo[zoneNumber][patch];
02558                 CBezierPatch &bezierPatch=_BezierPatch[zoneNumber][patch];
02559 
02560                 // Renormalize
02561                 nlassert (isPowerOf2 (orderS));
02562                 nlassert (isPowerOf2 (orderT));
02563                 uint powerS=getPowerOf2 (orderS);
02564                 uint powerT=getPowerOf2 (orderT);
02565                 uint lumelS=4<<powerS;
02566                 uint lumelT=4<<powerT;
02567 
02568                 // Sample edge normal
02569                 CVector normals[NL_MAX_TILES_BY_PATCH_EDGE*NL_LUMEL_BY_TILE+1][4];
02570                 uint sFixed[4] = { 0, 0xffffffff, lumelS-1, 0xffffffff };
02571                 uint tFixed[4] = { 0xffffffff, lumelT-1, 0xffffffff, 0 };
02572                 float sOri[4] = { 0, -1, (float)lumelS, -1 };
02573                 float tOri[4] = { -1, (float)lumelT, -1, 0 };
02574                 for (uint edge=0; edge<4; edge++)
02575                 {
02576                         // s and t
02577                         uint count=(edge&1)?lumelS:lumelT;
02578                         for (uint lumel=0; lumel<=count; lumel++)
02579                         {
02580                                 // Start coordinates
02581                                 float origineS;
02582                                 float origineT;
02583                                 uint startS;
02584                                 uint startT;
02585                                 if (edge&1)
02586                                 {
02587                                         if (lumel==count)
02588                                                 startS=count-1;
02589                                         else
02590                                                 startS=lumel;
02591                                         startT=tFixed[edge];
02592                                         origineS=(float)lumel;
02593                                         origineT=tOri[edge];
02594                                 }
02595                                 else
02596                                 {
02597                                         if (lumel==count)
02598                                                 startT=count-1;
02599                                         else
02600                                                 startT=lumel;
02601                                         startS=sFixed[edge];
02602                                         origineT=(float)lumel;
02603                                         origineS=sOri[edge];
02604                                 }
02605                                 _GetNormalNormal=CVector::Null;
02606                                 set<uint64> visitedLumels;
02607                                 getNormal (pPatch, startS, startT, locator, bindInfo, binded, visitedLumels, 
02608                                         startS+0.5f-origineS, startT+0.5f-origineT, 0, bezierPatch);
02609                                 _GetNormalNormal.normalize ();
02610                                 normals[lumel][edge]=_GetNormalNormal;
02611                         }
02612 
02613                         // Smooth the corners
02614 #define BLUR_SIZE 4
02615                         for (uint i=1; i<BLUR_SIZE; i++)
02616                         {
02617                                 float value=(float)i/BLUR_SIZE;
02618                                 value=easineasout(value);
02619                                 normals[i][edge]=normals[0][edge]*(1-value)+normals[i][edge]*value;
02620                                 normals[i][edge].normalize();
02621                                 normals[count-i][edge]=normals[count][edge]*(1-value)+normals[count-i][edge]*value;
02622                                 normals[count-i][edge].normalize();
02623                         }
02624                 }
02625                 
02626                 for (uint t=0; t<lumelT; t++)
02627                 for (uint s=0; s<lumelS; s++)
02628                 {
02629                         // Lumel index
02630                         uint lumelIndex=s+t*lumelS;
02631 
02632                         // *** Calc the smoothed normal
02633                         
02634                         // For each edge
02635                         CVector normalS=bezierPatch.evalNormal (((float)s+0.5f)/(float)lumelS, ((float)t+0.5f)/(float)lumelT);
02636                         float sFactor=0;
02637                         CVector normalT=normalS;
02638                         float tFactor=0;
02639                         bool sGood=false, tGood=false;
02640                         if (s<BLUR_SIZE)
02641                         {
02642                                 sGood=true;
02643                                 // Average the two normals
02644                                 CVector average=normals[t][0];
02645                                 average+=normals[t+1][0];
02646                                 average/=2;
02647 
02648                                 // Blend
02649                                 float value=s+0.5f;
02650                                 sFactor=BLUR_SIZE-value;
02651                                 value/=BLUR_SIZE;
02652                                 value=easineasout(value);
02653                                 normalS=(normalS*value+average*(1-value));
02654                                 normalS.normalize();
02655                         }
02656                         if (s>=lumelS-BLUR_SIZE)
02657                         {
02658                                 sGood=true;
02659                                 // Average the two normals
02660                                 CVector average=normals[t][2];
02661                                 average+=normals[t+1][2];
02662                                 average/=2;
02663 
02664                                 // Blend
02665                                 float value=s+0.5f;
02666                                 sFactor=BLUR_SIZE-(lumelS-value);
02667                                 value=(lumelS-value)/BLUR_SIZE;
02668                                 value=easineasout(value);
02669                                 normalS=(normalS*value+average*(1-value));
02670                                 normalS.normalize();
02671                         }
02672                         if (t<BLUR_SIZE)
02673                         {
02674                                 tGood=true;
02675                                 // Average the two normals
02676                                 CVector average=normals[s][3];
02677                                 average+=normals[s+1][3];
02678                                 average/=2;
02679 
02680                                 // Blend
02681                                 float value=t+0.5f;
02682                                 tFactor=BLUR_SIZE-value;
02683                                 value/=BLUR_SIZE;
02684                                 value=easineasout(value);
02685                                 normalT=(normalT*value+average*(1-value));
02686                                 normalT.normalize();
02687                         }
02688                         if (t>=lumelT-BLUR_SIZE)
02689                         {
02690                                 tGood=true;
02691                                 // Average the two normals
02692                                 CVector average=normals[s][1];
02693                                 average+=normals[s+1][1];
02694                                 average/=2;
02695 
02696                                 // Blend
02697                                 float value=t+0.5f;
02698                                 tFactor=BLUR_SIZE-(lumelT-value);
02699                                 value=((lumelT)-value)/BLUR_SIZE;
02700                                 value=easineasout(value);
02701                                 normalT=(normalT*value+average*(1-value));
02702                                 normalT.normalize();
02703                         }
02704 
02705                         // The smooth normal
02706                         CVector smoothNormal;
02707 
02708                         if ((sGood)&&(tGood))
02709                         {
02710                                 if ((sFactor!=BLUR_SIZE)||(tFactor!=BLUR_SIZE))
02711                                         smoothNormal=normalS*(BLUR_SIZE-tFactor)+normalT*(BLUR_SIZE-sFactor);
02712                                 else
02713                                         smoothNormal=normalS+normalT;
02714                         }
02715                         else if (sGood)
02716                                 smoothNormal=normalS;
02717                         else
02718                                 smoothNormal=normalT;
02719 
02720                         // Normalize it
02721                         smoothNormal.normalize();
02722 
02723                         // The pure normal
02724                         CVector purNormal=bezierPatch.evalNormal (((float)s+0.5f)/(float)lumelS, ((float)t+0.5f)/(float)lumelT);
02725 
02726                         // Normalize the noisy normal
02727                         lumels[lumelIndex].Normal.normalize();
02728 
02729                         // Final normal
02730                         lumels[lumelIndex].Normal=lumels[lumelIndex].Normal-purNormal+smoothNormal;
02731                         lumels[lumelIndex].Normal.normalize ();
02732 
02733                         // *** Number of visit
02734                         uint visitedCount=visited[patch][lumelIndex];
02735                         
02736                         // Some lumel have not been found in tesselation
02737                         //nlassert (visitedCount==2);
02738 
02739                         // If visited, renormalise other values
02740                         if (visitedCount)
02741                         {
02742                                 // Normalise position
02743                                 lumels[lumelIndex].S/=(float)visitedCount;
02744                                 lumels[lumelIndex].T/=(float)visitedCount;
02745                         }
02746                 }
02747         }
02748 }

float CZoneLighter::calcSkyContribution sint  s,
sint  t,
float  height,
float  skyIntensity,
const CVector normal
const [private]
 

Definition at line 296 of file zone_lighter.cpp.

References NLMISC::clamp(), deltaDirection, getMaxPhi(), height, NLMISC::Pi, s, sint, t, uint, and uint8.

Referenced by getSkyContribution().

00297 {
00298         // Sky contribution
00299         float skyContribution;
00300 
00301         // Calc k
00302         CVector k (0, 0, 0);
00303 
00304         // For the height direction
00305         for (uint i=0; i<8; i++)
00306         {
00307                 // Get phi for this point
00308                 uint8 phi=getMaxPhi (s, t, deltaDirection[i][0], deltaDirection[i][1], height);
00309 
00310                 // Add to k
00311                 k+=_K[phi][i];
00312         }
00313 
00314         // Finalize sky contribution
00315         skyContribution=(float)(skyIntensity*(normal*k)/(2*Pi));
00316         skyContribution=(float)(skyIntensity*(normal*k)/(2*Pi));
00317         clamp (skyContribution, 0.f, 1.f);
00318         return skyContribution;
00319 }

void CZoneLighter::compilePointLightRT uint  gridSize,
float  gridCellSize,
std::vector< CTriangle > &  obstacles,
bool  doShadow
[private]
 

Fill CubeGrid, and set PointLightRT in _StaticPointLightQuadGrid.

Definition at line 3202 of file zone_lighter.cpp.

References NL3D::CQuadGrid< T >::begin(), NL3D::CZoneLighter::CPointLightRT::BSphere, NLMISC::CBSphere::Center, NL3D::CCubeGrid< const CTriangle * >::compile(), NL3D::CCubeGrid< const CTriangle * >::create(), NL3D::CQuadGrid< T >::create(), NL3D::CQuadGrid< CPointLightRT * >::create(), NL3D::CQuadGrid< T >::end(), NLMISC::CAABBox::extend(), NL3D::CZoneLighter::CPointLightRT::FaceCubeGrid, NL3D::CPointLight::getAttenuationEnd(), NLMISC::CAABBox::getMax(), NLMISC::CAABBox::getMin(), NL3D::CZoneLighter::CTriangle::getPlane(), NL3D::CPointLight::getPosition(), NL3D::CPointLight::getType(), NL3D::CCubeGrid< const CTriangle * >::insert(), NL3D::CQuadGrid< T >::insert(), NL3D::CQuadGrid< CPointLightRT * >::insert(), NLMISC::CAABBox::intersect(), NL3D_ZONE_LIGHTER_CUBE_GRID_SIZE, NL3D::CZoneLighter::CPointLightRT::PointLight, progress(), NLMISC::CBSphere::Radius, NL3D::CZoneLighter::CPointLightRT::RefCount, NL3D::CQuadGrid< T >::select(), NLMISC::CAABBox::setCenter(), NLMISC::CAABBox::setHalfSize(), size, NL3D::CZoneLighter::CTriangle::Triangle, uint, NLMISC::CTriangle::V0, NLMISC::CTriangle::V1, and NLMISC::CTriangle::V2.

Referenced by light().

03203 {
03204         uint    i;
03205 
03206         // Fill the quadGrid of Lights.
03207         // ===========
03208         _StaticPointLightQuadGrid.create(gridSize, gridCellSize);
03209         for(i=0; i<_StaticPointLights.size();i++)
03210         {
03211                 CPointLightRT   &plRT= _StaticPointLights[i];
03212 
03213                 // Compute the bbox of the light
03214                 CAABBox         bbox;
03215                 bbox.setCenter(plRT.BSphere.Center);
03216                 float   hl= plRT.BSphere.Radius;
03217                 bbox.setHalfSize(CVector(hl,hl,hl));
03218 
03219                 // Insert the pointLight in the quadGrid.
03220                 _StaticPointLightQuadGrid.insert(bbox.getMin(), bbox.getMax(), &plRT);
03221         }
03222 
03223 
03224         // Append triangles to cubeGrid ??
03225         if(doShadow)
03226         {
03227                 // Point lights ?
03228                 if (!_StaticPointLights.empty ())
03229                 {
03230                         // For all obstacles, Fill a quadGrid.
03231                         // ===========
03232                         CQuadGrid<CTriangle*>   obstacleGrid;
03233                         obstacleGrid.create(gridSize, gridCellSize);
03234                         uint    size= obstacles.size();
03235                         for(i=0; i<size; i++)
03236                         {
03237                                 // bbox of triangle
03238                                 CAABBox bbox;
03239                                 bbox.setCenter(obstacles[i].Triangle.V0);
03240                                 bbox.extend(obstacles[i].Triangle.V1);
03241                                 bbox.extend(obstacles[i].Triangle.V2);
03242                                 // insert triangle in quadGrid.
03243                                 obstacleGrid.insert(bbox.getMin(), bbox.getMax(), &obstacles[i]);
03244                         }
03245 
03246 
03247                         // For all PointLights, fill his CubeGrid
03248                         // ===========
03249                         for(i=0; i<_StaticPointLights.size();i++)
03250                         {
03251                                 // progress
03252                                 progress ("Compute Influences of PointLights", 0.5f*i / (float)(_StaticPointLights.size()-1));
03253 
03254                                 CPointLightRT   &plRT= _StaticPointLights[i];
03255                                 // Create the cubeGrid
03256                                 plRT.FaceCubeGrid.create(plRT.PointLight.getPosition(), NL3D_ZONE_LIGHTER_CUBE_GRID_SIZE);
03257 
03258                                 // AmbiantLIghts: do nothing.
03259                                 if(plRT.PointLight.getType()!=CPointLight::AmbientLight)
03260                                 {
03261                                         // Select only obstacle Faces around the light. Other are not usefull
03262                                         CAABBox bbox;
03263                                         bbox.setCenter(plRT.PointLight.getPosition());
03264                                         float   hl= plRT.PointLight.getAttenuationEnd();
03265                                         bbox.setHalfSize(CVector(hl,hl,hl));
03266                                         obstacleGrid.select(bbox.getMin(), bbox.getMax());
03267 
03268                                         // For all faces, fill the cubeGrid.
03269                                         CQuadGrid<CTriangle*>::CIterator        itObstacle;
03270                                         itObstacle= obstacleGrid.begin();
03271                                         while( itObstacle!=obstacleGrid.end() )
03272                                         {
03273                                                 CTriangle       &tri= *(*itObstacle);
03274 
03275                                                 // Triangle bounding box
03276                                                 CAABBox triBbox;
03277                                                 triBbox.setCenter (tri.Triangle.V0);
03278                                                 triBbox.extend (tri.Triangle.V1);
03279                                                 triBbox.extend (tri.Triangle.V2);
03280 
03281                                                 // Triangle in the light
03282                                                 if (triBbox.intersect (bbox))
03283                                                 {
03284                                                         // Test BackFace culling. Only faces which are BackFace the point light are inserted.
03285                                                         // This is to avoid AutoOccluding problems
03286                                                         if( tri.getPlane() * plRT.BSphere.Center < 0)
03287                                                         {
03288                                                                 // Insert the triangle in the CubeGrid
03289                                                                 plRT.FaceCubeGrid.insert( tri.Triangle, &tri);
03290                                                         }
03291                                                 }
03292 
03293                                                 itObstacle++;
03294                                         }
03295                                 }
03296 
03297                                 // Compile the CubeGrid.
03298                                 plRT.FaceCubeGrid.compile();
03299 
03300                                 // And Reset RefCount.
03301                                 plRT.RefCount= 0;
03302                         }
03303                 }
03304         }
03305         // else, just build empty grid
03306         else
03307         {
03308                 for(i=0; i<_StaticPointLights.size();i++)
03309                 {
03310                         // progress
03311                         progress ("Compute Influences of PointLights", 0.5f*i / (float)(_StaticPointLights.size()-1));
03312 
03313                         CPointLightRT   &plRT= _StaticPointLights[i];
03314                         // Create a dummy empty cubeGrid => no rayTrace :)
03315                         plRT.FaceCubeGrid.create(plRT.PointLight.getPosition(), 4);
03316 
03317                         // Compile the CubeGrid.
03318                         plRT.FaceCubeGrid.compile();
03319 
03320                         // And Reset RefCount.
03321                         plRT.RefCount= 0;
03322                 }
03323         }
03324 
03325 }

void CZoneLighter::computeTileFlagsForPositionTowardWater const CLightDesc lightDesc,
std::vector< const CTessFace * > &  tessFaces
[private]
 

For each tile of the current zone, check wether it below or above water. The result is stored in the flags of the tile. The quadtree is removed then.

Definition at line 3563 of file zone_lighter.cpp.

References _WaterShapeQuadGrid, _ZoneToLight, NL3D::CQuadGrid< T >::begin(), NL3D::CQuadGrid< T >::clearSelection(), NLMISC::contReset(), NL3D::CQuadGrid< T >::end(), NLMISC::CAABBox::extend(), NLMISC::CAABBox::getMax(), NLMISC::CPolygon2D::intersect(), nlinfo, progress(), NL3D::CQuadGrid< T >::select(), NLMISC::CAABBox::setMinMax(), NL3D::CTileElement::setVegetableState(), TTileOfPatchMap, uint, NL3D::CZoneLighter::CLightDesc::VegetableHeight, NLMISC::CPolygon::Vertices, NLMISC::CPolygon2D::Vertices, NLMISC::CVector::x, NLMISC::CVector::y, z, and NLMISC::CVector::z.

Referenced by buildZoneInformation().

03566 {       
03567         uint numTileAbove     = 0;
03568         uint numTileBelow     = 0;
03569         uint numTileIntersect = 0;
03570         
03572         TTileOfPatchMap tiles;
03573 
03575         //  First, build the bbox for all tiles  //
03577 
03578         uint triCount = 0, totalTriCount = tessFaces.size();    
03579 
03580         nlinfo("Dealing with %d tessFaces", tessFaces.size());
03581         for (std::vector<const CTessFace*>::iterator it = tessFaces.begin(); it != tessFaces.end(); ++it, ++triCount)
03582         {
03584                 if ((*it)->Patch->getZone()->getZoneId() != _ZoneToLight) continue;
03586                 if ((*it)->Patch->Tiles[(*it)->TileId].getVegetableState() == CTileElement::VegetableDisabled)
03587                         continue;
03588 
03589                 CTileOfPatch top((*it)->TileId, (*it)->Patch);
03590                 TTileOfPatchMap::iterator tileIt = tiles.find(top);
03591 
03593                 if (tileIt == tiles.end()) // first time ?
03594                 {
03596                         NLMISC::CAABBox b;
03597                         b.setMinMax((*it)->VBase->EndPos, (*it)->VLeft->EndPos);
03598                         b.extend((*it)->VRight->EndPos);
03599                         b.extend(b.getMax() + lightDesc.VegetableHeight * NLMISC::CVector::K); // adds vegetable height                 
03600                         tiles[top] = b;
03601                 }
03602                 else // extends the bbox with the given face
03603                 {
03604                         NLMISC::CAABBox &b = tileIt->second;                    
03605                         b.extend((*it)->VBase->EndPos);
03606                         b.extend((*it)->VRight->EndPos);
03607                         b.extend((*it)->VLeft->EndPos);
03608                 }
03609 
03610                 if ((triCount % 100) == 0)
03611                 {
03612                         progress("Building bbox from tiles", (float) triCount / totalTriCount);
03613                 }
03614         }
03615 
03616         progress("Building bbox from tiles", 1.f);
03617 
03618 
03619 
03621         // Now, check each tile bbox against water shapes //
03623         NLMISC::CPolygon   waterPoly;
03624         NLMISC::CPolygon2D tilePoly;
03625         tilePoly.Vertices.resize(4);
03626 
03627         uint tileCount = 0, totalTileCount = tiles.size();      
03628 
03629         for (TTileOfPatchMap::iterator tileIt = tiles.begin(); tileIt != tiles.end(); ++tileIt, ++tileCount)
03630         {
03631                 const NLMISC::CVector v0 = tileIt->second.getMin();
03632                 const NLMISC::CVector v1 = tileIt->second.getMax();
03633 
03635                 tilePoly.Vertices[0].set(v0.x, v0.y); 
03636                 tilePoly.Vertices[1].set(v1.x, v0.y); 
03637                 tilePoly.Vertices[2].set(v1.x, v1.y); 
03638                 tilePoly.Vertices[3].set(v0.x, v1.y); 
03639 
03641                 _WaterShapeQuadGrid.clearSelection();
03642                 _WaterShapeQuadGrid.select(tileIt->second.getMin(), tileIt->second.getMax());
03643 
03644                 CTileElement &te = tileIt->first.Patch->Tiles[tileIt->first.TileId]; // alias to the current tile element
03645 
03647                 TWaterShapeQuadGrid::CIterator qgIt;
03648                 for (qgIt = _WaterShapeQuadGrid.begin(); qgIt != _WaterShapeQuadGrid.end(); ++qgIt)
03649                 {
03650                         
03651                         (*qgIt)->getShapeInWorldSpace(waterPoly);
03652                         NLMISC::CPolygon2D poly(waterPoly);
03653                         if (poly.intersect(tilePoly)) // above or below a water surface ?               
03654                         {
03656                                 float waterHeight = waterPoly.Vertices[0].z;
03657 
03658                                 if (v1.z < waterHeight)
03659                                 {
03660                                         // below
03661                                         te.setVegetableState(CTileElement::UnderWater);
03662                                         //nlassert(te.getVegetableState() == CTileElement::UnderWater);
03663                                         ++ numTileBelow;
03664                                 }
03665                                 else if (v0. z > waterHeight)
03666                                 {
03667                                         // above
03668                                         te.setVegetableState(CTileElement::AboveWater);
03669                                         //nlassert(te.getVegetableState() == CTileElement::AboveWater);
03670                                         ++ numTileAbove;
03671                                 }
03672                                 else
03673                                 {
03674                                         // intersect water
03675                                         te.setVegetableState(CTileElement::IntersectWater);
03676                                         //nlassert(te.getVegetableState() == CTileElement::IntersectWater);
03677                                         ++ numTileIntersect;
03678                                 }
03679                                 break;
03680                         }
03681                 }
03682 
03683                 if (qgIt == _WaterShapeQuadGrid.end()) // no intersection found ? if yes it's above water
03684                 {
03685                         te.setVegetableState(CTileElement::AboveWater); 
03686                         //nlassert(te.getVegetableState() == CTileElement::AboveWater);
03687                         ++ numTileAbove;
03688                 }
03689 
03690                 if ((tileCount % 50) == 0)
03691                 {
03692                         progress("Computing tile position towards water", (float) tileCount / totalTileCount);
03693                 }
03694         }
03695 
03696         progress("Computing tile position towards water", 1.f);
03697 
03698         nlinfo(" %d tiles are above water.", numTileAbove);
03699         nlinfo(" %d tiles are below water.", numTileBelow);
03700         nlinfo(" %d tiles intersect water.", numTileIntersect);
03701 
03702 
03703 
03705         NLMISC::contReset(_WaterShapeQuadGrid);
03706 }

void CZoneLighter::copyTileFlags CZone destZone,
const CZone srcZone
[static, private]
 

This copy the flags of the tiles from the source zone to a dest zone (result of the lighting). This is needed beacuse these flags are updated to say wether a given tile is above / below water IMPORTANT : the source and destination zones must match of course...

Definition at line 1261 of file zone_lighter.cpp.

References NL3D::CZone::copyTilesFlags(), NL3D::CZone::getNumPatchs(), NL3D::CZone::getPatch(), NL3D::CZone::getZoneId(), nlassert, and sint.

Referenced by light().

01262 {
01263         nlassert(destZone.getZoneId() == srcZone.getZoneId());
01264         for (sint k = 0; k < srcZone.getNumPatchs(); ++k)
01265         {
01266                 destZone.copyTilesFlags(k, srcZone.getPatch(k));
01267         }
01268 }

void CZoneLighter::excludeAllPatchFromRefineAll CLandscape landscape,
std::vector< uint > &  listZone,
bool  exclude
[private]
 

Definition at line 1985 of file zone_lighter.cpp.

References NL3D::CLandscape::excludePatchFromRefineAll(), NL3D::CZone::getNumPatchs(), NL3D::CLandscape::getZone(), and uint.

Referenced by addTriangles().

01986 {
01987         // For each zone
01988         for (uint zone=0; zone<listZone.size(); zone++)
01989         {
01990                 // Get num patches
01991                 uint patchCount=landscape.getZone(listZone[zone])->getNumPatchs();
01992 
01993                 // For each patches
01994                 for (uint patch=0; patch<patchCount; patch++)
01995                 {
01996                         // Exclude all the patches from refine all
01997                         landscape.excludePatchFromRefineAll (listZone[zone], patch, exclude);
01998                 }
01999         }
02000 }

uint CZoneLighter::getAPatch uint  process  )  [private]
 

Definition at line 3726 of file zone_lighter.cpp.

References _LastPatchComputed, _NumberOfPatchComputed, _PatchComputed, _PatchInfo, index, and uint.

Referenced by processCalc().

03727 {
03728         // Accessor
03729         CSynchronized<std::vector<bool> >::CAccessor access (&_PatchComputed);
03730 
03731         // Current index
03732         uint index = _LastPatchComputed[process];
03733         uint firstIndex = index;
03734 
03735         if (access.value().size() == 0)
03736                 // no more patches
03737                 return 0xffffffff;
03738 
03739         while (access.value()[index])
03740         {
03741                 // Next patch
03742                 index++;
03743 
03744                 // Last patch ?
03745                 if (index == _PatchInfo.size())
03746                         index = 0;
03747 
03748                 // First ?
03749                 if (firstIndex == index)
03750                         // no more patches
03751                         return 0xffffffff;
03752         }
03753 
03754         // Visited
03755         access.value()[index] = true;
03756 
03757         // Last index
03758         _LastPatchComputed[process] = index;
03759         _NumberOfPatchComputed++;
03760 
03761         // Return the index
03762         return index;
03763 }

uint8 CZoneLighter::getMaxPhi sint  s,
sint  t,
sint  deltaS,
sint  deltaT,
float  heightPos
const [private]
 

Definition at line 1390 of file zone_lighter.cpp.

References _HeightFieldCellCount, _HeightfieldCellSize, NLMISC::clamp(), height, nlassert, NLMISC::Pi, res, s, sint, t, and uint8.

Referenced by calcSkyContribution().

01391 {
01392         // Start position
01393         s+=deltaS;
01394         t+=deltaT;
01395 
01396         // Distance increment
01397         float stepDistance=CVector (deltaS*_HeightfieldCellSize, deltaT*_HeightfieldCellSize,0).norm ();
01398 
01399         // Current distance
01400         float distance=stepDistance;
01401 
01402         // Max height
01403         float maxHeight=0;
01404         float maxTanTeta=0;
01405 
01406         // For all the line
01407         while ((s<_HeightFieldCellCount)&&(t<_HeightFieldCellCount)&&(s>=0)&&(t>=0))
01408         {
01409                 // Get height
01410                 float height=_HeightField[s+t*_HeightFieldCellCount];
01411                 height-=heightPos;
01412 
01413                 // Better ?
01414                 if (height>maxHeight)
01415                 {
01416                         // Calc sin teta
01417                         float tanTeta=height/distance;
01418                         nlassert (tanTeta>=0);
01419 
01420                         // Better ?
01421                         if (tanTeta>maxTanTeta)
01422                         {
01423                                 // New max height
01424                                 maxHeight=height;
01425                                 maxTanTeta=tanTeta;
01426                         }
01427                 }
01428                 s+=deltaS;
01429                 t+=deltaT;
01430                 distance+=stepDistance;
01431         }
01432 
01433         // return phi
01434         float teta=(float)atan (maxTanTeta);
01435         nlassert (teta>=0);
01436         nlassert (teta<=Pi/2);
01437         clamp (teta, 0.f, (float)Pi/2);
01438         sint res=(sint)((Pi/2-teta)*256/(Pi/2));
01439         clamp (res, 0, 255);
01440         return (uint8)res;
01441 }

void CZoneLighter::getNormal const NL3D::CPatch pPatch,
sint16  lumelS,
sint16  lumelT,
std::vector< NL3D::CPatchUVLocator > &  locator,
const std::vector< NL3D::CPatch::CBindInfo > &  bindInfo,
const std::vector< bool > &  binded,
std::set< uint64 > &  visited,
float  deltaS,
float  deltaT,
uint  rotation,
const NL3D::CBezierPatch bezierPatch,
uint  lastEdge = 5
[private]
 

Definition at line 1506 of file zone_lighter.cpp.

References _BezierPatch, _Binded, _BindInfo, _GetNormalDeltaS, _GetNormalDeltaT, _GetNormalNormal, _Locator, _ZoneId, NL3D::CBezierPatch::evalNormal(), NL3D::CPatch::getOrderS(), NL3D::CPatch::getOrderT(), NL3D::CPatch::getPatchId(), NL3D::CPatch::getSmoothFlag(), NL3D::CPatch::getZone(), NL3D::CZone::getZoneId(), nlassert, sint, sint16, uint, uint16, uint64, NLMISC::CVector2f::x, and NLMISC::CVector2f::y.

Referenced by buildZoneInformation().

01509 {
01510         // Build a desc srructure
01511         uint64 id=(uint64)lumelS|(((uint64)lumelT)<<16)|(((uint64)pPatch->getPatchId())<<32)|(((uint64)pPatch->getZone()->getZoneId())<<48);
01512 
01513         // Insert it
01514         if (visited.insert (id).second)
01515         {
01516                 // Clip
01517                 float sqDist=deltaS*deltaS+deltaT*deltaT;
01518                 if ( sqDist < 1 )
01519                 {
01520                         // Continue...
01521 
01522                         sint orderSx4=pPatch->getOrderS()<<2;
01523                         sint orderTx4=pPatch->getOrderT()<<2;
01524 
01525                         sint16 _GetNormalBorderS[4]={ 0, -10, 1, -10 };
01526                         sint16 _GetNormalBorderT[4]={ -10, 1, -10, 0 };
01527                         _GetNormalBorderS[2]=orderSx4-1;
01528                         _GetNormalBorderT[1]=orderTx4-1;
01529 
01530                         // Add normal
01531                         _GetNormalNormal+=bezierPatch.evalNormal ( ((float)lumelS+0.5f)/(float)orderSx4, ((float)lumelT+0.5f)/(float)orderTx4 );
01532 
01533                         // For the four neighbors
01534                         for (uint edge=0; edge<4; edge++)
01535                         {
01536                                 // Not last edge ?
01537                                 if (edge!=lastEdge)
01538                                 {
01539                                         // Direction
01540                                         uint globalDirection=(edge+(4-rotation))&0x3;
01541 
01542                                         // Neighbor
01543                                         if ( (lumelS==_GetNormalBorderS[edge]) || (lumelT==_GetNormalBorderT[edge]) )
01544                                         {
01545                                                 // Binded ?
01546                                                 bool bind=binded[edge];
01547                                                 bool smooth=pPatch->getSmoothFlag (edge);
01548                                                 if (bind&&smooth)
01549                                                 {
01550                                                         // Lumel coord
01551                                                         CVector2f lumelCoord ( ((float)(lumelS+_GetNormalDeltaS[edge])+0.5f)/4, 
01552                                                                 ((float)(lumelT+_GetNormalDeltaT[edge])+0.5f)/4 );
01553 
01554                                                         // Get neighbor pixel
01555                                                         uint otherPatch=locator[edge].selectPatch(lumelCoord);
01556 
01557                                                         // Get uv
01558                                                         CVector2f neighborUV;
01559                                                         CPatch *patchOut;
01560                                                         locator[edge].locateUV (lumelCoord, otherPatch, patchOut, neighborUV);
01561 
01562                                                         // New coordinates
01563                                                         sint16 newLumelS=(sint16)(4.f*neighborUV.x);
01564                                                         sint16 newLumelT=(sint16)(4.f*neighborUV.y);
01565 
01566                                                         // Zone id
01567                                                         uint16 patchId=patchOut->getPatchId();
01568                                                         uint16 zoneId=_ZoneId[patchOut->getZone()->getZoneId ()];
01569 
01570                                                         // Get edge
01571                                                         uint newEdge=0;
01572                                                         uint i;
01573                                                         for (i=0; i<=(uint)bindInfo[edge].NPatchs; i++)
01574                                                         {
01575                                                                 // Good patch ?
01576                                                                 if (bindInfo[edge].Next[i]==patchOut)
01577                                                                 {
01578                                                                         // Get its edge
01579                                                                         newEdge=bindInfo[edge].Edge[i];
01580                                                                         break;
01581                                                                 }
01582                                                         }
01583                                                         
01584                                                         // Rotation 
01585                                                         uint newRotation=(2-edge+rotation+newEdge)&0x3;
01586 
01587                                                         // Must found it
01588                                                         nlassert (i!=(uint)bindInfo[edge].NPatchs);
01589 
01590                                                         // Get the bezier patch
01591                                                         CBezierPatch &NewBezierPatch=_BezierPatch[zoneId][patchId];
01592 
01593                                                         // Next lumel
01594                                                         getNormal (patchOut, newLumelS, newLumelT, _Locator[zoneId][patchId], _BindInfo[zoneId][patchId], 
01595                                                                 _Binded[zoneId][patchId], visited, deltaS+_GetNormalDeltaS[globalDirection], 
01596                                                                 deltaT+_GetNormalDeltaT[globalDirection], newRotation, NewBezierPatch, newEdge);
01597                                                 }
01598                                         }
01599                                         else
01600                                         {
01601                                                 // Left internal
01602                                                 getNormal (pPatch, lumelS+_GetNormalDeltaS[edge], lumelT+_GetNormalDeltaT[edge], locator, bindInfo, binded, visited, 
01603                                                         deltaS+_GetNormalDeltaS[globalDirection], deltaT+_GetNormalDeltaT[globalDirection], rotation, bezierPatch, (edge+2)&0x3);
01604                                         }
01605                                 }
01606                         }
01607                 }
01608         }
01609 }

void NL3D::CZoneLighter::getPatchNormalAndPositions std::vector< CLumelDescriptor > &  lumels,
CLandscape landscape,
uint  zoneToLight,
uint  patch,
CPatchUVLocator locator,
bool *  binded
[private]
 

float CZoneLighter::getSkyContribution const CVector pos,
const CVector normal,
float  SkyIntensity
const [private]
 

compute the sky contribution at the given position

Definition at line 1271 of file zone_lighter.cpp.

References _HeightfieldCellSize, _OrigineHeightField, calcSkyContribution(), s, sint, t, NLMISC::CVector::x, NLMISC::CVector::y, and NLMISC::CVector::z.

Referenced by lightWater(), and processCalc().

01272 {       
01273         float s=(pos.x-_OrigineHeightField.x)/_HeightfieldCellSize;
01274         float t=(pos.y-_OrigineHeightField.y)/_HeightfieldCellSize;
01275         sint sInt=(sint)(floor (s+0.5f));
01276         sint tInt=(sint)(floor (t+0.5f));
01277 
01278         // Bilinear
01279         float skyContributionTab[2][2];
01280         skyContributionTab[0][0] = calcSkyContribution (sInt-1, tInt-1, pos.z, skyIntensity, normal);
01281         skyContributionTab[1][0] = calcSkyContribution (sInt, tInt-1, pos.z, skyIntensity, normal);
01282         skyContributionTab[1][1] = calcSkyContribution (sInt, tInt, pos.z, skyIntensity, normal);
01283         skyContributionTab[0][1] = calcSkyContribution (sInt-1, tInt, pos.z, skyIntensity, normal);
01284         
01285         float sFact=s+0.5f-sInt;
01286         float tFact=t+0.5f-tInt;
01287         return (skyContributionTab[0][0]*(1.f-sFact) + skyContributionTab[1][0]*sFact)*(1.f-tFact) +
01288                 (skyContributionTab[0][1]*(1.f-sFact) + skyContributionTab[1][1]*sFact)*tFact;  
01289 }

bool CZoneLighter::getTexture const CMaterial material,
NLMISC::CBitmap *&  result,
bool &  clampU,
bool &  clampV,
uint8 alphaTestThreshold,
bool &  doubleSided
[private]
 

Definition at line 1820 of file zone_lighter.cpp.

References _Bitmaps, NLMISC::clamp(), NLMISC::CBitmap::convertToType(), NL3D::ITexture::generate(), NL3D::CMaterial::getAlphaTest(), NL3D::CMaterial::getAlphaTestThreshold(), NL3D::CMaterial::getBlend(), NL3D::CMaterial::getDoubleSided(), NL3D::ITexture::getShareName(), NL3D::CMaterial::getTexture(), NL3D::ITexture::getWrapS(), NL3D::ITexture::getWrapT(), NL3D::ITexture::release(), NL3D::ITexture::supportSharing(), and uint8.

Referenced by addTriangles().

01821 {
01822         // Texture informations, not NULL only if texture is used for alpha test
01823         result = NULL;
01824         clampU = false;
01825         clampV = false;
01826 
01827         // Alpha test threashold
01828         float alphaTestThresholdF = material.getAlphaTestThreshold () * 255;
01829         clamp (alphaTestThresholdF, 0.f, 255.f);
01830         alphaTestThreshold = (uint8)alphaTestThresholdF;
01831 
01832         // Drawable material ?
01833         if (material.getBlend ())
01834                 return false;
01835 
01836         // Use alpha test ?
01837         if (material.getAlphaTest ())
01838         {
01839                 // Get the texture
01840                 ITexture *texture = material.getTexture (0);
01841 
01842                 // Is texture shared ?
01843                 if (texture && texture->supportSharing ())
01844                 {
01845                         // Share name
01846                         string name = texture->getShareName();
01847 
01848                         // Texture exist ?
01849                         std::map<string, NLMISC::CBitmap>::iterator ite = _Bitmaps.find (name);
01850                         if (ite != _Bitmaps.end ())
01851                         {
01852                                 // Yes
01853                                 result = &(ite->second);
01854                         }
01855                         else
01856                         {
01857                                 // No, add it
01858                                 ite = _Bitmaps.insert (std::map<string, NLMISC::CBitmap>::value_type (name, CBitmap())).first;
01859                                 result = &(ite->second);
01860 
01861                                 // Generate the texture
01862                                 texture->generate ();
01863 
01864                                 // Convert to RGBA
01865                                 texture->convertToType (CBitmap::RGBA);
01866 
01867                                 // Copy it
01868                                 *result = *texture;
01869 
01870                                 // Release the texture
01871                                 texture->release ();
01872                         }
01873 
01874                         // Wrap flags
01875                         clampU = texture->getWrapS () == ITexture::Clamp;
01876                         clampV = texture->getWrapT () == ITexture::Clamp;
01877                 }
01878         }
01879 
01880         // Get double sided flag
01881         doubleSided = material.getDoubleSided ();
01882         return true;
01883 }

void CZoneLighter::init  ) 
 

Definition at line 251 of file zone_lighter.cpp.

References _Bitmaps, _ZBufferOverflow, NLMISC::Pi, NLMISC::CVector::set(), and uint.

00252 {
00253         // Precalc some values
00254         for (uint i=0; i<8; i++)
00255         {
00256                 // Precalc sinP and cosP
00257                 float sinP=(float)(sin((Pi/4)*(i+0.5))-sin((Pi/4)*(i-0.5)));
00258                 float cosP=(float)(cos((Pi/4)*(i-0.5))-cos((Pi/4)*(i+0.5)));
00259 
00260                 for (uint phi=0; phi<256; phi++)
00261                 {
00262                         // Real phi
00263                         float fPhi=(float)((Pi/2)*phi/256.0);
00264 
00265                         // Tmp result
00266                         float tmp0=(float)(fPhi-sin(2*fPhi)/2);
00267                         float tmp1=(float)sin(fPhi);
00268 
00269                         // Calc K
00270                         _K[phi][i].set (tmp0*sinP, tmp0*cosP, (float)((Pi/4)*tmp1*tmp1));
00271                 }
00272         }
00273 
00274         // Init some containers
00275         _ZBufferOverflow = false;
00276         _Bitmaps.clear ();
00277 }

bool CZoneLighter::isLightableShape IShape shape  )  [static]
 

check wether a shape is lightable.

for now, the only shape that we lit are water shapes

Definition at line 2783 of file zone_lighter.cpp.

References NL3D::CWaterShape::getColorMap(), and NL3D::CWaterShape::isLightMappingEnabled().

Referenced by processLightableShapeCalc().

02784 {
02786         if (dynamic_cast<CWaterShape *>(&shape) != NULL)
02787         {
02788                 // check that this water surface has a diffuse map that is a CTextureFile (we must be able to save it !)
02789                 CWaterShape *ws = static_cast<CWaterShape *>(&shape);
02790                 const ITexture *tex = ws->getColorMap();
02791                 if (dynamic_cast<const CTextureFile *>(tex) != NULL)
02792                 {
02793                         return ws->isLightMappingEnabled();
02794                 }
02795         }
02796         return false;
02797 }

bool CZoneLighter::isLumelOnEdgeMustBeOversample uint  patch,
uint  edge,
sint  s,
sint  t,
const std::vector< bool > &  binded,
const std::vector< bool > &  oversampleEdges,
std::vector< CPatchUVLocator > &  locator,
uint8  shadowed,
std::vector< std::vector< uint8 > > &  shadowBuffer
[private]
 

Definition at line 1451 of file zone_lighter.cpp.

References _GetNormalDeltaS, _GetNormalDeltaT, NL3D::CPatch::getOrderS(), NL3D::CPatch::getPatchId(), s, sint, t, uint, uint8, NLMISC::CVector2f::x, and NLMISC::CVector2f::y.

01454 {
01455         // Must force oversampling of this edge ?
01456         if (oversampleEdges[edge])
01457                 return true;
01458         else
01459         {
01460                 // binded ?
01461                 if (binded[edge])
01462                 {
01463                         // Lumel coord
01464                         CVector2f lumelCoord (((float)(s+_GetNormalDeltaS[edge])+0.5f)/4.f, ((float)(t+_GetNormalDeltaT[edge])+0.5f)/4.f);
01465                         uint otherPatch=locator[edge].selectPatch(lumelCoord);
01466 
01467                         // Get uv
01468                         CVector2f neighborUV;
01469                         CPatch *patchOut;
01470                         locator[edge].locateUV (lumelCoord, otherPatch, patchOut, neighborUV);
01471                         
01472                         // Is the same shadowed flag ?
01473                         sint ss=(sint)(neighborUV.x*4.f);
01474                         sint tt=(sint)(neighborUV.y*4.f);
01475                         return (shadowBuffer[patchOut->getPatchId()][ss+(patchOut->getOrderS()<<2)*tt]!=shadowed);
01476                 }
01477                 else
01478                 {
01479                         // Not oversample if not binded
01480                         return false;
01481                 }
01482         }
01483 }

void CZoneLighter::light CLandscape landscape,
CZone output,
uint  zoneToLight,
const CLightDesc description,
std::vector< CTriangle > &  obstacles,
std::vector< uint > &  listZone
 

copy the tiles flags from the zone to light to the output zone

Perform lightning of some ig's of the current zone (if any)

Definition at line 920 of file zone_lighter.cpp.

References _BorderVertices, _CPUMask, _HeightFieldCellCount, _HeightfieldCellSize, _LastPatchComputed, _NumberOfPatchComputed, _OrigineHeightField, _PatchComputed, _PatchInfo, NL3D::CZoneLighter::CTriangle::_Plane, _ProcessCount, _ProcessExited, _RayBasis, _ShadowArray, _ZBufferLandscape, _ZBufferObject, _ZBufferOverflow, _ZoneToLight, NL3D::CZoneInfo::BorderVertices, NL3D::CZone::build(), buildZoneInformation(), compilePointLightRT(), copyTileFlags(), FilterZBuffer(), NL3D::CZoneLighter::CTriangle::Flags, NLMISC::CAABBoxExt::getCenter(), NLMISC::IProcess::getCPUMask(), NLMISC::IThread::getCPUMask(), NLMISC::CMatrix::getI(), NLMISC::CMatrix::getJ(), NL3D::CZone::getZoneBB(), NL3D::CZoneLighter::CLightDesc::GridCellSize, NL3D::CZoneLighter::CLightDesc::GridSize, NL3D::CZoneLighter::CLightDesc::HeightfieldCellSize, NL3D::CZoneLighter::CLightDesc::HeightfieldSize, InitZBuffer(), NLMISC::CMatrix::invert(), lightShapes(), NL3D::CZoneLighter::CZBuffer::LocalZBufferHeight, NL3D::CZoneLighter::CZBuffer::LocalZBufferWidth, NLMISC::CPlane::make(), MAX_CPU_PROCESS, NLMISC::CVector::maxof(), min, NLMISC::CVector::minof(), NL3D::NEL3DCalcBase(), nlassert, NLMISC::nlSleep(), nlwarning, NL3D::CZoneLighter::CLightDesc::NumCPU, NL3D::CZoneInfo::Patchs, NL3D::CZoneInfo::PointLights, processZonePointLightRT(), progress(), NL3D::CZone::retrieve(), NLMISC::IThread::setCPUMask(), NL3D::CZoneLighter::CLightDesc::Shadow, sint, size, NL3D::CZoneLighter::CLightDesc::SoftShadowSamplesSqrt, NLMISC::IThread::start(), NL3D::CZoneLighter::CLightDesc::SunCenter, NL3D::CZoneLighter::CLightDesc::SunDirection, NL3D::CZoneLighter::CLightDesc::SunDistance, NL3D::CZoneLighter::CLightDesc::SunRadius, NL3D::CLightRunnable::Thread, NL3D::CRenderZBuffer::Thread, NLMISC::toString(), NL3D::CZoneLighter::CTriangle::Triangle, uint, uint64, NLMISC::CTriangle::V0, NLMISC::CTriangle::V1, NLMISC::CTriangle::V2, x, NLMISC::CVector::x, y, NLMISC::CVector::y, NLMISC::CVector::z, NL3D::CZoneLighter::CLightDesc::ZBufferLandscapeSize, NL3D::CZoneLighter::CLightDesc::ZBufferObjectSize, and NL3D::CZoneInfo::ZoneId.

00921 {
00922         /*
00923          * Lighting algorithm
00924          * ------------------
00925          *
00926          * - Create a quad grid to store shadow casting triangles
00927          * - Create a heightfield used for global illumination. Cells are initialized with -FLT_MAX
00928          * - Insert each shadow casting triangles in the quad grid and fill the heightfield's cells overlapped by the bounding box of the triangle with
00929          * the max height of the triangle if its height is > than the current height in the heightfield's cell.
00930          * - 
00931          */
00932 
00933         // Backup thread mask
00934         IThread *currentThread = IThread::getCurrentThread ();
00935         uint64 threadMask = currentThread->getCPUMask();
00936         currentThread->setCPUMask (1);
00937 
00938         // Calc the ray basis
00939         _SunDirection=description.SunDirection;
00940         NEL3DCalcBase (_SunDirection, _RayBasis);
00941 
00942         // Zone to light
00943         _ZoneToLight=zoneToLight;
00944 
00945         // Landscape 
00946         _Landscape=&landscape;
00947 
00948         // Process count
00949         _ProcessCount=description.NumCPU;
00950         if (_ProcessCount==0)
00951         {
00952                 // Create a doomy thread
00953                 IProcess *pProcess=IProcess::getCurrentProcess ();
00954                 _CPUMask = pProcess->getCPUMask();
00955                 _ProcessCount = 0;
00956                 uint64 i;
00957                 for (i=0; i<64; i++)
00958                 {
00959                         if (_CPUMask&((uint64)1<<i))
00960                                 _ProcessCount++;
00961                 }
00962         }
00963         if (_ProcessCount>MAX_CPU_PROCESS)
00964                 _ProcessCount=MAX_CPU_PROCESS;
00965 
00966         // Number of obstacle polygones
00967         printf ("Obstacle polygones : %d\n", obstacles.size ());
00968 
00969         // Number of CPUS used
00970         printf ("Number of CPU used: %d\n", _ProcessCount);
00971 
00972         // Zone pointer
00973         CZone *pZone=landscape.getZone (_ZoneToLight);
00974         if (pZone)
00975         {
00976                 // *** Compute center of the object
00977 
00978                 // Get the zone bounding box
00979                 const CAABBoxExt &zoneBB=pZone->getZoneBB();
00980 
00981                 // Get the center
00982                 CVector center = zoneBB.getCenter ();
00983 
00984                 // *** Compute planes
00985                 const uint size=obstacles.size();
00986                 uint triangleId;
00987                 for (triangleId=0; triangleId<size; triangleId++)
00988                 {
00989                         // Triangle ref
00990                         CZoneLighter::CTriangle& triangle=obstacles[triangleId];
00991 
00992                         // Calc the plane
00993                         triangle._Plane.make (triangle.Triangle.V0, triangle.Triangle.V1, triangle.Triangle.V2);
00994                 }
00995 
00996                 // Create landscape zbuffers
00997                 _ZBufferLandscape.resize (description.SoftShadowSamplesSqrt*description.SoftShadowSamplesSqrt);
00998 
00999                 uint sampleX;
01000                 uint sampleY;
01001                 for (sampleY=0; sampleY<description.SoftShadowSamplesSqrt; sampleY++)
01002                 for (sampleX=0; sampleX<description.SoftShadowSamplesSqrt; sampleX++)
01003                 {
01004                         // *** Render the light zbuffer
01005                         CZBuffer &zbuffer = _ZBufferLandscape[sampleX + sampleY*description.SoftShadowSamplesSqrt];
01006 
01007                         // Delta pos for area light
01008                         float deltaX = ( (float)sampleX + 0.5f  - (float)description.SoftShadowSamplesSqrt / 2.f) / (float)description.SoftShadowSamplesSqrt;
01009                         float deltaY = ( (float)sampleY + 0.5f  - (float)description.SoftShadowSamplesSqrt / 2.f) / (float)description.SoftShadowSamplesSqrt;
01010                         CVector lightPos = _RayBasis.getI () * ((float)description.SunRadius * deltaX) + _RayBasis.getJ () * ((float)description.SunRadius * deltaY);
01011                         lightPos = description.SunCenter - (description.SunDirection * description.SunDistance) + lightPos;
01012 
01013                         InitZBuffer (zbuffer, lightPos, _RayBasis, zoneBB, description.ZBufferLandscapeSize, description);
01014                         printf ("Zbuffer %d size : %d x %d\n", sampleX+sampleY*description.SoftShadowSamplesSqrt, zbuffer.LocalZBufferWidth, zbuffer.LocalZBufferHeight);
01015                 }
01016 
01017 
01018                 // *** Init the zbuffer for the vegetation
01019                 CVector lightPos = description.SunCenter - (description.SunDirection * description.SunDistance);
01020                 InitZBuffer (_ZBufferObject, lightPos, _RayBasis, zoneBB, description.ZBufferObjectSize, description);
01021                 printf ("Zbuffer object size : %d x %d\n", _ZBufferObject.LocalZBufferWidth, _ZBufferObject.LocalZBufferHeight);
01022                 
01023                 
01024                 // Compute the zbuffer in multi thread
01025                 _ProcessExited = 0;
01026 
01027                 // Number of triangle to render per thread
01028                 uint numTriangle = (obstacles.size () / _ProcessCount) + 1;
01029 
01030                 // First triangle for the thread
01031                 uint firstTriangle = 0;
01032 
01033                 // Count
01034                 _NumberOfPatchComputed = 0;
01035 
01036                 for (uint process=0; process<_ProcessCount; process++)
01037                 {
01038                         // Get list of triangles to render
01039                         uint lastTriangle=firstTriangle+numTriangle;
01040                         if (lastTriangle>obstacles.size ())
01041                                 lastTriangle=obstacles.size ();
01042 
01043                         // Create a thread
01044                         CRenderZBuffer *runnable = new CRenderZBuffer (process, this, &description, firstTriangle, lastTriangle - firstTriangle, &obstacles);
01045                         IThread *pThread=IThread::create (runnable);
01046                         runnable->Thread = pThread;
01047                         
01048                         // New first patch
01049                         firstTriangle = lastTriangle;
01050 
01051                         // Launch
01052                         pThread->start();
01053                 }
01054 
01055                 // Wait for others processes
01056                 while (_ProcessExited!=_ProcessCount)
01057                 {
01058                         nlSleep (1000);
01059 
01060                         // Call the progress callback
01061                         progress ("Render triangles", (float)_NumberOfPatchComputed/(float)obstacles.size());
01062                 }
01063 
01064                 // * Save the zbuffer
01065                 uint sample;
01066                 const uint samples = description.SoftShadowSamplesSqrt*description.SoftShadowSamplesSqrt;
01067 #ifdef SAVE_ZBUFFER
01068                 for (sample=0; sample<samples; sample++)
01069                 {
01070                         // *** The zbuffer
01071                         CZBuffer &zbuffer = _ZBufferLandscape[sample];
01072 
01073                         string zbufferFilename = SAVE_ZBUFFER"/zbuffer_landscape_" + toString (sample) + ".jpg";
01074 
01075                         SaveZBuffer (zbuffer, zbufferFilename.c_str ());
01076                 }
01077 
01078                 // Save the object zbuffer
01079                 SaveZBuffer (_ZBufferObject, SAVE_ZBUFFER"/zbuffer_object.jpg");
01080 #endif // SAVE_ZBUFFER
01081 
01082                 // *** Filter the zbuffer
01083                 for (sample=0; sample<samples; sample++)
01084                 {
01085                         // For landscape zbuffer, expand the z to neighbor
01086                         FilterZBuffer (_ZBufferLandscape[sample], 5);
01087                 }
01088 
01089                 // Change the quadGrid basis
01090                 CMatrix invRayBasis=_RayBasis;
01091                 invRayBasis.invert ();
01092                 
01093                 // Init the heightfield
01094                 _HeightfieldCellSize=description.HeightfieldCellSize;
01095                 _HeightFieldCellCount=(sint)(description.HeightfieldSize/_HeightfieldCellSize);
01096                 nlassert (_HeightFieldCellCount!=0);
01097                 _OrigineHeightField=zoneBB.getCenter ()-CVector (description.HeightfieldSize/2, description.HeightfieldSize/2, 0);
01098                 _HeightField.resize (_HeightFieldCellCount*_HeightFieldCellCount, -FLT_MAX);
01099 
01100                 // Fill the quadGrid and the heightField
01101                 for (triangleId=0; triangleId<size; triangleId++)
01102                 {
01103                         // Progress bar
01104                         if ( (triangleId&0xff) == 0)
01105                                 progress ("Build quadtree and heightfield", (float)triangleId/(float)size);
01106 
01107                         // Triangle ref
01108                         CZoneLighter::CTriangle& triangle=obstacles[triangleId];
01109 
01110                         // Look for the min coordinate, in World Basis
01111                         CVector minv;
01112                         minv.minof (triangle.Triangle.V0, triangle.Triangle.V1);
01113                         minv.minof (minv, triangle.Triangle.V2);
01114 
01115                         // Look for the max coordinate, in World Basis
01116                         CVector maxv;
01117                         maxv.maxof (triangle.Triangle.V0, triangle.Triangle.V1);
01118                         maxv.maxof (maxv, triangle.Triangle.V2);
01119 
01120                         // Lanscape tri ?
01121                         if (triangle.Flags & CTriangle::Landscape)
01122                         {
01123                                 // Fill the heightfield
01124                                 sint minX=std::max (0, (sint)floor (0.5f+(minv.x-_OrigineHeightField.x)/_HeightfieldCellSize));
01125                                 sint maxX=std::min (_HeightFieldCellCount, (sint)floor (0.5f+(maxv.x-_OrigineHeightField.x)/_HeightfieldCellSize));
01126                                 sint minY=std::max (0, (sint)floor (0.5f+(minv.y-_OrigineHeightField.y)/_HeightfieldCellSize));
01127                                 sint maxY=std::min (_HeightFieldCellCount, (sint)floor (0.5f+(maxv.y-_OrigineHeightField.y)/_HeightfieldCellSize));
01128 
01129                                 // Calc position in the heightfield
01130                                 for (sint y=minY; y<maxY; y++)
01131                                 for (sint x=minX; x<maxX; x++)
01132                                 {
01133                                         // Valid position, try to insert it
01134                                         if (maxv.z>_HeightField[x+y*_HeightFieldCellCount])
01135                                         {
01136                                                 // New height in this cell
01137                                                 _HeightField[x+y*_HeightFieldCellCount]=maxv.z;
01138                                         }
01139                                 }
01140                         }
01141                 }
01142 
01143                 // Retrieve the zone to fill its shaded value
01144                 pZone->retrieve (_PatchInfo, _BorderVertices);
01145 
01146                 // Number of patch
01147                 uint patchCount=_PatchInfo.size();
01148 
01149                 // Bit array to know if the lumel is shadowed
01150                 if (description.Shadow)
01151                         _ShadowArray.resize (patchCount);
01152 
01153                 // A lumel vector by patch
01154                 vector<vector<CLumelDescriptor> > lumels;
01155                 lumels.resize (patchCount);
01156 
01157                 // Build zone informations
01158                 buildZoneInformation (landscape,
01159                                                           listZone,
01160                                                           description);
01161 
01162         }
01163 
01164         // Number of patch
01165         uint patchCount=_PatchInfo.size();
01166 
01167         // Reset patch count
01168         {
01169                 CSynchronized<std::vector<bool> >::CAccessor access (&_PatchComputed);
01170                 access.value().resize (0);
01171                 access.value().resize (patchCount, false);
01172         }
01173 
01174         // Patch by thread
01175         uint patchCountByThread = patchCount/_ProcessCount;
01176         patchCountByThread++;
01177 
01178         // Patch to allocate
01179         uint firstPatch=0;
01180         _NumberOfPatchComputed = 0;
01181 
01182         // Reset exited process
01183         _ProcessExited=0;
01184 
01185         // Set the thread state
01186         _LastPatchComputed.resize (_ProcessCount);
01187 
01188         // Launch threads
01189         uint process;
01190         for (process=0; process<_ProcessCount; process++)
01191         {
01192                 // Last patch
01193                 uint lastPatch=firstPatch+patchCountByThread;
01194                 if (lastPatch>patchCount)
01195                         lastPatch=patchCount;
01196 
01197                 // Last patch computed
01198                 _LastPatchComputed[process] = firstPatch;
01199 
01200                 // Create a thread
01201                 CLightRunnable *runnable = new CLightRunnable (process, this, &description);
01202                 IThread *pThread=IThread::create (runnable);
01203                 runnable->Thread = pThread;
01204                 
01205                 // New first patch
01206                 firstPatch=lastPatch;
01207 
01208                 // Launch
01209                 pThread->start();
01210         }
01211 
01212         // Wait for others processes
01213         while (_ProcessExited!=_ProcessCount)
01214         {
01215                 nlSleep (1000);
01216 
01217                 // Call the progress callback
01218                 progress ("Lighting patches", (float)_NumberOfPatchComputed/(float)_PatchInfo.size());
01219         }
01220 
01221         // Reset old thread mask
01222         currentThread->setCPUMask (threadMask);
01223         
01224         // overflow ?
01225         if (_ZBufferOverflow)
01226                 nlwarning ("Error : zbuffer overflow");
01227 
01228         // Progress bar
01229         progress ("Compute Influences of PointLights", 0.f);
01230 
01231         // Compute PointLight influences on zone.
01232         // Some precalc.
01233         compilePointLightRT(description.GridSize, description.GridCellSize, obstacles, description.Shadow);
01234         // Influence patchs and get light list of interest
01235         std::vector<CPointLightNamed>   listPointLight;
01236         processZonePointLightRT(listPointLight);
01237 
01238 
01239         // Rebuild the zone
01240 
01241         // Progress bar
01242         progress ("Compress the lightmap", 0.6f);
01243 
01244         // Build, with list of lights.
01245         CZoneInfo       zinfo;
01246         zinfo.ZoneId= _ZoneToLight;
01247         zinfo.Patchs= _PatchInfo;
01248         zinfo.BorderVertices= _BorderVertices;
01249         zinfo.PointLights= listPointLight;
01250         output.build (zinfo);
01251 
01253         copyTileFlags(output, *(landscape.getZone(zoneToLight)));
01254 
01256         lightShapes(zoneToLight, description);
01257 }

void CZoneLighter::lightShapes uint  zoneID,
const CLightDesc description
[private]
 

Launch a set of threads to perform lighting of lightable shapes.

compute light for the lightable shapes in the given zone

wait for other process

Definition at line 2800 of file zone_lighter.cpp.

References _LightableShapes, _NumLightableShapesProcessed, _ProcessCount, _ProcessExited, CCalcLightableShapeRunnable, min, NLMISC::nlSleep(), progress(), NLMISC::IThread::start(), and uint.

Referenced by light().

02801 {
02803         if (_LightableShapes.size() == 0) return;       
02804 
02805         uint numShapePerThread = 1 + (_LightableShapes.size() / _ProcessCount);
02806         uint currShapeIndex = 0;
02807         uint process = 0;
02808         _ProcessExited = 0;
02809 
02810         _NumLightableShapesProcessed = 0;
02811 
02812 
02813         progress("Processing lightable shapes", 0);
02814         
02815         for (uint k = 0; k < _LightableShapes.size(); ++k, ++process)
02816         {
02817                 uint lastShapeIndex = currShapeIndex + numShapePerThread;
02818                 lastShapeIndex = std::min((uint)_LightableShapes.size(), lastShapeIndex);               
02819                 IThread *pThread = IThread::create (new CCalcLightableShapeRunnable(process, this, &description, &_LightableShapes, currShapeIndex, lastShapeIndex));
02820                 pThread->start();
02821                 currShapeIndex = lastShapeIndex;
02822         }
02823 
02825         while (_ProcessExited != _ProcessCount)
02826         {
02827                 nlSleep (10);
02828         }
02829 
02830 }

void CZoneLighter::lightSingleShape CShapeInfo si,
const CLightDesc description,
uint  cpu
[private]
 

Compute the lighting for a single lightable shape.

we compute the lighting for one single shape

Definition at line 2852 of file zone_lighter.cpp.

References _LightableShapes, _NumLightableShapesProcessed, lightWater(), NL3D::CZoneLighter::CShapeInfo::MT, progress(), NL3D::CZoneLighter::CShapeInfo::Shape, and uint.

Referenced by processLightableShapeCalc().

02853 {
02855         if (dynamic_cast<CWaterShape *>(si.Shape))
02856         {
02857                 lightWater(* static_cast<CWaterShape *>(si.Shape), si.MT, description, cpu);
02858         }
02859         ++_NumLightableShapesProcessed;
02860         progress("Processing lightable shapes", (float) _NumLightableShapesProcessed / _LightableShapes.size());
02861         return; 
02862 }

void CZoneLighter::lightWater CWaterShape ws,
const CMatrix MT,
const CLightDesc description,
uint  cpu
[private]
 

Compute the lighting for a water shape.

get the diffuse map

build a matrix to convert from water space to uv space

get min and max uvs

raytrace each texel

now, save the result

Definition at line 2927 of file zone_lighter.cpp.

References attenuation(), NLMISC::clamp(), NLMISC::COFile::close(), NL3D::ITexture::generate(), NL3D::CWaterShape::getColorMap(), NL3D::CWaterShape::getColorMapMat(), getExt(), NL3D::CTextureFile::getFileName(), NLMISC::CBitmap::getHeight(), NLMISC::CPolygon::getNumVertices(), NLMISC::CBitmap::getPixels(), NL3D::CWaterShape::getShapeInWorldSpace(), getSkyContribution(), NLMISC::CBitmap::getWidth(), height, NLMISC::CMatrix::inverted(), min, NLMISC::CRGBA::modulateFromColor(), NL3D::CZoneLighter::CLightDesc::ModulateWaterColor, nlwarning, NLMISC::COFile::open(), NLMISC::CMatrix::setPos(), NLMISC::CMatrix::setRot(), NL3D::CZoneLighter::CLightDesc::Shadow, sint, NL3D::CZoneLighter::CLightDesc::SkyContributionForWater, NL3D::CZoneLighter::CLightDesc::SkyIntensity, NL3D::CZoneLighter::CLightDesc::SunDirection, uint, uint8, NLMISC::CPolygon::Vertices, NL3D::CZoneLighter::CLightDesc::WaterAmbient, NL3D::CZoneLighter::CLightDesc::WaterDiffuse, NL3D::CZoneLighter::CLightDesc::WaterShadowBias, width, NLMISC::CBitmap::writeTGA(), x, NLMISC::CVector::x, NLMISC::CVector2f::x, y, NLMISC::CVector::y, and NLMISC::CVector2f::y.

Referenced by lightSingleShape().

02928 {       
02929         try
02930         {       
02932                 CTextureFile *diffuseTex = NLMISC::safe_cast<CTextureFile *>(ws.getColorMap());
02933                 std::string texFileName = CPath::lookup(diffuseTex->getFileName());
02934                 diffuseTex->generate();
02935                 const uint width = diffuseTex->getWidth();
02936                 const uint height = diffuseTex->getHeight();    
02937                 
02939                 NLMISC::CMatrix worldSpaceToUVs;
02940                 NLMISC::CVector2f col0, col1, pos;
02941                 ws.getColorMapMat(col0, col1, pos);
02942                 worldSpaceToUVs.setRot(NLMISC::CVector(col0.x * width, col0.y * height, 0),
02943                                                            NLMISC::CVector(col1.x * width, col1.y * height, 0),
02944                                                            NLMISC::CVector::K);
02945                 worldSpaceToUVs.setPos(NLMISC::CVector(pos.x * width, pos.y * height, 0));              
02946 
02948                 NLMISC::CPolygon p;
02949                 ws.getShapeInWorldSpace(p);
02950 
02951                 float minU, maxU;
02952                 float minV, maxV;
02953 
02954                 NLMISC::CVector uvs = worldSpaceToUVs * p.Vertices[0];
02955                 minU = maxU = uvs.x;
02956                 minV = maxV = uvs.y;
02957 
02958 
02959                 for (uint k = 1; k < (uint) p.getNumVertices(); ++k)
02960                 {
02961                         uvs = worldSpaceToUVs * p.Vertices[k];
02962                         minU = std::min(uvs.x, minU);
02963                         minV = std::min(uvs.y, minV);
02964                         maxU = std::max(uvs.x, maxU);
02965                         maxV = std::max(uvs.y, maxV);   
02966                 }
02967                 
02968                 
02969         
02970 
02971                 sint iMinU = (sint) minU;
02972                 sint iMaxU = (sint) maxU;
02973                 sint iMinV = (sint) minV;
02974                 sint iMaxV = (sint) maxV;
02975 
02976                 NLMISC::clamp(iMinU, 0, (sint) width);
02977                 NLMISC::clamp(iMaxU, 0, (sint) width);
02978                 NLMISC::clamp(iMinV, 0, (sint) height);
02979                 NLMISC::clamp(iMaxV, 0, (sint) height);
02980 
02981                 // matrix to go from uv space to worldspace
02982                 NLMISC::CMatrix UVSpaceToWorldSpace = worldSpaceToUVs.inverted();
02983 
02984                 CObjectVector<uint8> &pixs8 = diffuseTex->getPixels();
02985                 NLMISC::CRGBA *rgbPixs = (NLMISC::CRGBA *) &pixs8[0];
02986 
02987         
02989                 for (sint x = iMinU; x < iMaxU; ++x)
02990                 {
02991                         for (sint y = iMinV; y < iMaxV; ++y)
02992                         {
02993                                 float factor;
02994                                 NLMISC::CVector pos = UVSpaceToWorldSpace * NLMISC::CVector( x + 0.5f, y + 0.5f, 0 ) 
02995                                         + description.WaterShadowBias * NLMISC::CVector::K;
02996                                 if (description.Shadow)
02997                                 {
02998                                         factor = attenuation (pos, description);
02999                                 }
03000                                 else
03001                                 {
03002                                         factor = - NLMISC::CVector::K * description.SunDirection;
03003                                 }
03004                                 clamp(factor, 0.f, 1.f);
03005                                 factor = factor * description.WaterDiffuse + description.WaterAmbient;
03006                                 if (description.SkyContributionForWater)
03007                                 {
03008                                         factor += getSkyContribution(pos, NLMISC::CVector::K, description.SkyIntensity);
03009                                 }
03010                                 clamp(factor, 0.f, 1.f);
03011                                 uint intensity = (uint8) (255 * factor);
03012                                 NLMISC::CRGBA srcCol(intensity,
03013                                                                          intensity,
03014                                                                          intensity,
03015                                                                           255);
03016 
03017                                 if (!description.ModulateWaterColor)
03018                                 {
03019                                         rgbPixs[x + y * width] = srcCol;
03020                                 }
03021                                 else
03022                                 {
03023                                         NLMISC::CRGBA &col = rgbPixs[x + y * width];
03024                                         col.modulateFromColor(col, srcCol);
03025                                 }
03026                         }
03027                 }
03028         
03030                 if (getExt(texFileName) != ".tga")
03031                 {
03032                         nlwarning("Zone lighter : error when lighting a water surface : input bitmap is not a tga file");
03033                 }
03034                 else
03035                 {
03036                         try
03037                         {
03038                                 COFile of;
03039                                 of.open(texFileName);
03040                                 diffuseTex->writeTGA(of, 24);
03041                                 of.close();
03042                         }
03043                         catch (NLMISC::Exception &)
03044                         {
03045                                 nlwarning("Zone lighter : while lighting a water shape, writing %s failed! ", texFileName.c_str());
03046                         }
03047                 }
03048         }
03049         catch(NLMISC::Exception &e)
03050         {
03051                 nlwarning("Water shape lighting failed !");
03052                 nlwarning(e.what());
03053         }
03054 }

void CZoneLighter::makeQuadGridFromWaterShapes NLMISC::CAABBox  zoneBBox  )  [private]
 

Make a quad grid of all the water shapes that where registered by calling addWaterShape() The vector of water shapes is released then

Parameters:
bbox the bbox of the zone containing the water shapes

Definition at line 3067 of file zone_lighter.cpp.

References _WaterShapeQuadGrid, NLMISC::contReset(), count, NL3D::CQuadGrid< T >::create(), NLMISC::CAABBox::getMax(), NLMISC::CAABBox::getMin(), height, NL3D::CQuadGrid< T >::insert(), NLMISC::CAABBox::intersect(), progress(), NLMISC::CAABBox::transformAABBox(), uint, width, NLMISC::CVector::x, and NLMISC::CVector::y.

Referenced by buildZoneInformation().

03068 {
03069         if (!_WaterShapes.size()) return;
03070 
03071         NLMISC::CAABBox tmpBox;
03072 
03074         const uint numCells = 16;
03075 
03077         float width  = zoneBBox.getMax().x - zoneBBox.getMin().x;
03078         float height = zoneBBox.getMax().y - zoneBBox.getMin().y;
03079 
03080         float dim = std::max(width, height);
03081 
03082 
03084         _WaterShapeQuadGrid.create(numCells, dim / numCells);
03085         
03086 
03087         uint count = 0, totalCount = _WaterShapes.size();
03088 
03090         for (TShapeVect::iterator it = _WaterShapes.begin(); it != _WaterShapes.end(); ++it, ++count)
03091         {
03093                 it->Shape->getAABBox(tmpBox);
03094                 NLMISC::CAABBox currBB = NLMISC::CAABBox::transformAABBox(it->MT, tmpBox);
03095 
03097                 if (zoneBBox.intersect(currBB))
03098                 {
03099                         _WaterShapeQuadGrid.insert(currBB.getMin(), currBB.getMax(), NLMISC::safe_cast<CWaterShape *>(it->Shape));
03100                 }
03101                 progress("Building quadtree from water surfaces", (float) count / totalCount);
03102         }
03103 
03105         NLMISC::contReset(_WaterShapes);
03106 }

void CZoneLighter::processCalc uint  process,
const CLightDesc description
[private]
 

Definition at line 1293 of file zone_lighter.cpp.

References _Lumels, _PatchInfo, _ShadowArray, _ZoneToLight, attenuation(), NLMISC::clamp(), getAPatch(), getSkyContribution(), NL3D::CLandscape::getZone(), NL3D::CPatchInfo::Lumels, nlassert, NL3D::CZoneLighter::CLightDesc::Shadow, sint, NL3D::CZoneLighter::CLightDesc::SkyContribution, NL3D::CZoneLighter::CLightDesc::SkyIntensity, NL3D::CZoneLighter::CLightDesc::SunContribution, and uint.

01294 {
01295         // *** Raytrace each patches
01296 
01297         // Pointer on the zone
01298         CZone *pZone=_Landscape->getZone (_ZoneToLight);
01299 
01300         // Get a patch
01301         uint patch = getAPatch (process);
01302         while (patch != 0xffffffff)
01303         {
01304                 // For each patch
01305                 if (description.Shadow)
01306                 {
01307                         // Lumels
01308                         std::vector<CLumelDescriptor> &lumels=_Lumels[patch];
01309                 
01310                         // Lumel count
01311                         uint lumelCount=lumels.size();
01312                         CPatchInfo &patchInfo=_PatchInfo[patch];
01313                         nlassert (patchInfo.Lumels.size()==lumelCount);
01314 
01315                         // Resize shadow array
01316                         _ShadowArray[patch].resize (lumelCount);
01317 
01318                         // For each lumel
01319                         for (uint lumel=0; lumel<lumelCount; lumel++)
01320                         {
01321                                 float factor=0;
01322                                 factor = attenuation (lumels[lumel].Position, description);
01323                                 patchInfo.Lumels[lumel]=(uint)(factor*255);
01324                         }
01325                 }
01326                 else
01327                 {
01328                         // Lumels
01329                         std::vector<CLumelDescriptor> &lumels=_Lumels[patch];
01330                 
01331                         // Lumel count
01332                         uint lumelCount=lumels.size();
01333                         CPatchInfo &patchInfo=_PatchInfo[patch];
01334                         nlassert (patchInfo.Lumels.size()==lumelCount);
01335 
01336                         // For each lumel
01337                         for (uint lumel=0; lumel<lumelCount; lumel++)
01338                         {
01339                                 // Not shadowed
01340                                 patchInfo.Lumels[lumel]=255;
01341                         }
01342                 }
01343 
01344                 // *** Lighting
01345                 
01346                 // Get the patch info
01347                 CPatchInfo &patchInfo=_PatchInfo[patch];
01348 
01349                 // ** Pointer on arries
01350                 std::vector<CLumelDescriptor> &lumels=_Lumels[patch];
01351 
01352                 // Go for light each lumel
01353                 for (uint lumel=0; lumel<lumels.size(); lumel++)
01354                 {
01355                         // Sky contribution
01356                         float skyContribution;
01357                         
01358                         if (description.SkyContribution)
01359                         {                                                               
01360                                 skyContribution = getSkyContribution(lumels[lumel].Position, lumels[lumel].Normal, description.SkyIntensity);
01361                         }
01362                         else
01363                         {
01364                                 skyContribution = 0.f;
01365                         }
01366 
01367                         // Sun contribution
01368                         float sunContribution;
01369                         if (description.SunContribution)
01370                         {
01371                                 sunContribution=(-lumels[lumel].Normal*_SunDirection)-skyContribution;
01372                                 clamp (sunContribution, 0.f, 1.f);
01373                         }
01374                         else
01375                                 sunContribution=0;
01376 
01377                         // Final lighting
01378                         sint finalLighting=(sint)(255.f*(((float)patchInfo.Lumels[lumel])*sunContribution/255.f+skyContribution));
01379                         clamp (finalLighting, 0, 255);
01380                         patchInfo.Lumels[lumel]=finalLighting;
01381                 }
01382 
01383                 // Next patch
01384                 patch = getAPatch (process);
01385         }
01386 }

void CZoneLighter::processLightableShapeCalc uint  process,
TShapeVect shapeToLit,
uint  firstShape,
uint  lastShape,
const CLightDesc description
[private]
 

Process lighting for a set of lightable shapes. This is called by the threads created by lightShapes().

Definition at line 2836 of file zone_lighter.cpp.

References isLightableShape(), lightSingleShape(), nlassert, TShapeVect, and uint.

02841 {
02842         // for each lightable shape
02843         for (uint k = firstShape; k < lastShape; ++k)
02844         {               
02845                 nlassert(isLightableShape(* (*shapesToLit)[k].Shape)); // make sure it is a lightable shape             
02846                 lightSingleShape((*shapesToLit)[k], description, process);      
02847         }
02848 }

void CZoneLighter::processZonePointLightRT std::vector< CPointLightNamed > &  listPointLight  )  [private]
 

Process the zone, ie process _PatchInfo. MultiCPU: not done for now. Be aware of CPointLightRT::RefCount!!!!

Definition at line 3346 of file zone_lighter.cpp.

References _PatchInfo, _ZoneToLight, NL3D::CQuadGrid< CPointLightRT * >::begin(), NL3D::CZoneLighter::CPointLightRT::BSphere, NLMISC::CBSphere::Center, NLMISC::clamp(), NL3D::CPointLight::computeLinearAttenuation(), NL3D::CPatch::computeVertex(), NL3D::CZoneLighter::CPointLightRT::DstId, NL3D::CQuadGrid< CPointLightRT * >::end(), NL3D::CBezierPatch::evalNormal(), NL3D::CLandscape::getZone(), NL3D::CZoneLighter::CPatchForPL::HeightTLI, NL3D::CTileLightInfluence::Light, NL3D::CZoneLighter::CTileLightInfUnpack::Light, NL3D::CZoneLighter::CTileLightInfUnpack::LightFactor, min, NLMISC::CVector::normalize(), NL3D::CZoneLighter::CPredPointLightToPoint::Point, NL3D::CZoneLighter::CPointLightRT::PointLight, progress(), NL3D::CZoneLighter::CPointLightRT::RefCount, s, NL3D::CQuadGrid< CPointLightRT * >::select(), NL3D::CTileLightInfluence::setDiffuseLightFactor(), t, NL3D::CZoneLighter::CPointLightRT::testRaytrace(), NL3D::CPatchInfo::TileLightInfluences, NL3D::CZoneLighter::CPatchForPL::TileLightInfluences, uint, uint8, NL3D::CPatch::unpackIntoCache(), w, NL3D::CZoneLighter::CPatchForPL::WidthTLI, x, and y.

Referenced by light().

03347 {
03348         uint    i;
03349         vector<CPointLightRT*>          lightInfs;
03350         lightInfs.reserve(1024);
03351 
03352         // clear result list
03353         listPointLight.clear();
03354 
03355         // zoneToLight
03356         CZone   *zoneToLight= _Landscape->getZone(_ZoneToLight);
03357         if(!zoneToLight)
03358                 return;
03359 
03360         // Build patchForPLs
03361         //===========
03362         vector<CPatchForPL>             patchForPLs;
03363         patchForPLs.resize(_PatchInfo.size());
03364         for(i=0; i<patchForPLs.size(); i++)
03365         {
03366                 // Get OrderS/OrderT
03367                 patchForPLs[i].OrderS= _PatchInfo[i].OrderS;
03368                 patchForPLs[i].OrderT= _PatchInfo[i].OrderT;
03369                 // resize TileLightInfluences
03370                 uint    w= patchForPLs[i].WidthTLI= patchForPLs[i].OrderS/2 +1 ;
03371                 uint    h= patchForPLs[i].HeightTLI= patchForPLs[i].OrderT/2 +1;
03372                 patchForPLs[i].TileLightInfluences.resize(w*h);
03373         }
03374 
03375 
03376         // compute each TileLightInfluence
03377         //===========
03378         for(i=0; i<patchForPLs.size(); i++)
03379         {
03380                 // progress
03381                 progress ("Compute Influences of PointLights", 0.5f + 0.5f*i / (float)patchForPLs.size());
03382 
03383                 CPatchForPL             &pfpl= patchForPLs[i];
03384                 const CPatch    *patch= const_cast<const CZone*>(zoneToLight)->getPatch(i);
03385 
03386                 uint    x, y;
03387                 for(y= 0; y<pfpl.HeightTLI; y++)
03388                 {
03389                         for(x= 0; x<pfpl.WidthTLI; x++)
03390                         {
03391                                 // compute the point and normal (normalized) where the TLI lies.
03392                                 //---------
03393                                 CVector         pos, normal;
03394                                 float           s, t;
03395                                 s= (float)x / (pfpl.WidthTLI-1);
03396                                 t= (float)y / (pfpl.HeightTLI-1);
03397                                 // Compute the Vertex, with Noise information (important for accurate raytracing).
03398                                 pos= patch->computeVertex(s, t);
03399                                 // Use UnNoised normal from BezierPatch, because the lighting does not need to be so precise.
03400                                 CBezierPatch    *bp= patch->unpackIntoCache();
03401                                 normal= bp->evalNormal(s, t);
03402                                 
03403 
03404                                 // Compute Which light influences him.
03405                                 //---------
03406                                 lightInfs.clear();
03407                                 // Search possible lights around the position.
03408                                 _StaticPointLightQuadGrid.select(pos, pos);
03409                                 // For all of them, get the ones which touch this point.
03410                                 CQuadGrid<CPointLightRT*>::CIterator    it= _StaticPointLightQuadGrid.begin();
03411                                 while(it != _StaticPointLightQuadGrid.end())
03412                                 {
03413                                         CPointLightRT   *pl= *it;
03414 
03415                                         // a light influence a TLI only if this one is FrontFaced to the light !!
03416                                         if( ( pl->BSphere.Center - pos ) * normal > 0)
03417                                         {
03418                                                 // Add 5cm else it fails in some case where ( pl->BSphere.Center - pos ) * normal is 
03419                                                 // nearly 0 and the point should be occluded.
03420                                                 const float     deltaY= 0.05f;
03421                                                 CVector posToRT= pos + normal * deltaY;
03422                                                 // Test if really in the radius of the light, if no occlusion, and if in SpotAngle
03423                                                 if( pl->testRaytrace(posToRT) )
03424                                                 {
03425                                                         // Ok, add the light to the lights which influence the TLI 
03426                                                         lightInfs.push_back(pl);
03427                                                 }
03428                                         }
03429 
03430                                         // next
03431                                         it++;
03432                                 }
03433 
03434                                 // Choose the Best ones.
03435                                 //---------
03436                                 CPredPointLightToPoint  predPLTP;
03437                                 predPLTP.Point= pos;
03438                                 // sort.
03439                                 sort(lightInfs.begin(), lightInfs.end(), predPLTP);
03440                                 // truncate.
03441                                 lightInfs.resize( min((uint)lightInfs.size(), (uint)CTileLightInfluence::NumLightPerCorner) );
03442 
03443 
03444                                 // For each of them, fill TLI
03445                                 //---------
03446                                 CTileLightInfUnpack             tli;
03447                                 uint                                    lightInfId;
03448                                 for(lightInfId=0; lightInfId<lightInfs.size(); lightInfId++)
03449                                 {
03450                                         CPointLightRT   *pl= lightInfs[lightInfId];
03451 
03452                                         // copy light.
03453                                         tli.Light[lightInfId]= pl;
03454                                         // Compute light Diffuse factor.
03455                                         CVector         dir= pl->BSphere.Center - pos;
03456                                         dir.normalize();
03457                                         tli.LightFactor[lightInfId]= dir * normal;
03458                                         clamp(tli.LightFactor[lightInfId], 0.f, 1.f);
03459                                         // modulate by light attenuation.
03460                                         tli.LightFactor[lightInfId]*= pl->PointLight.computeLinearAttenuation(pos);
03461 
03462                                         // Inc RefCount of the light.
03463                                         pl->RefCount++;
03464                                 }
03465                                 // Reset any empty slot to NULL.
03466                                 for(; lightInfId<CTileLightInfluence::NumLightPerCorner; lightInfId++)
03467                                 {
03468                                         tli.Light[lightInfId]= NULL;
03469                                 }
03470 
03471 
03472                                 // Set TLI in patch.
03473                                 //---------
03474                                 pfpl.TileLightInfluences[y*pfpl.WidthTLI + x]= tli;
03475                         }
03476                 }
03477         }
03478 
03479 
03480         // compress and setup _PatchInfo with compressed data.
03481         //===========
03482         uint    plId= 0;
03483         // Process each pointLights
03484         for(i=0; i<_StaticPointLights.size(); i++)
03485         {
03486                 CPointLightRT   &plRT= _StaticPointLights[i];
03487                 // If this light is used.
03488                 if(plRT.RefCount > 0)
03489                 {
03490                         // Must Copy it into Zone.
03491                         listPointLight.push_back(plRT.PointLight);
03492                         plRT.DstId= plId++;
03493                         // If index >= 255, too many lights (NB: => because 255 is a NULL code).
03494                         if(plId>=0xFF)
03495                         {
03496                                 throw Exception("Too many Static Point Lights influence the zone!!");
03497                         }
03498                 }
03499         }
03500 
03501         // For each patch, compress TLI in PatchInfo.
03502         for(i=0; i<patchForPLs.size(); i++)
03503         {
03504                 CPatchForPL             &pfpl= patchForPLs[i];
03505                 CPatchInfo              &pInfo= _PatchInfo[i];
03506 
03507                 uint    w= pfpl.WidthTLI;
03508                 uint    h= pfpl.HeightTLI;
03509 
03510                 // Fill  pInfo.TileLightInfluences
03511                 pInfo.TileLightInfluences.resize(w*h);
03512                 uint    x, y;
03513                 for(y= 0; y<h; y++)
03514                 {
03515                         for(x= 0; x<w; x++)
03516                         {
03517                                 uint    tliId= y*w + x;
03518                                 // For all light slot
03519                                 for(uint lightId= 0; lightId<CTileLightInfluence::NumLightPerCorner; lightId++)
03520                                 {
03521                                         CTileLightInfUnpack             &tliSrc= pfpl.TileLightInfluences[tliId];
03522                                         CTileLightInfluence             &tliDst= pInfo.TileLightInfluences[tliId];
03523                                         if(tliSrc.Light[lightId] == NULL)
03524                                         {
03525                                                 // Mark as unused.
03526                                                 tliDst.Light[lightId]= 0xFF;
03527                                         }
03528                                         else
03529                                         {
03530                                                 // Get index.
03531                                                 tliDst.Light[lightId]= tliSrc.Light[lightId]->DstId;
03532                                                 // Get Diffuse Factor.
03533                                                 tliDst.setDiffuseLightFactor(lightId, (uint8)(tliSrc.LightFactor[lightId]*255));
03534                                         }
03535                                 }
03536                         }
03537                 }
03538 
03539         }
03540 
03541 }

virtual void NL3D::CZoneLighter::progress const char *  message,
float  progress
[inline, virtual]
 

Definition at line 342 of file zone_lighter.h.

Referenced by buildZoneInformation(), compilePointLightRT(), computeTileFlagsForPositionTowardWater(), light(), lightShapes(), lightSingleShape(), makeQuadGridFromWaterShapes(), and processZonePointLightRT().

00342 {};

void CZoneLighter::setTileFlagsToDefault std::vector< const CTessFace * > &  tessFaces  )  [private]
 

If no water surface overlap the zone, so we set all the flags to 'AboveWater", or don't change them if they were set to 'DisableVegetable'

Definition at line 3710 of file zone_lighter.cpp.

References _ZoneToLight, NL3D::CTileElement::getVegetableState(), and NL3D::CTileElement::setVegetableState().

Referenced by buildZoneInformation().

03711 {
03713         for (std::vector<const CTessFace*>::iterator it = tessFaces.begin(); it != tessFaces.end(); ++it)
03714         {
03715                 if ((*it)->Patch->getZone()->getZoneId() != _ZoneToLight) continue;
03716                 CTileElement &te = (*it)->Patch->Tiles[(*it)->TileId];
03717                 if (te.getVegetableState() != CTileElement::VegetableDisabled)
03718                 {
03719                         te.setVegetableState(CTileElement::AboveWater);
03720                 }
03721         }
03722 }


Friends And Related Function Documentation

friend class CCalcLightableShapeRunnable [friend]
 

Definition at line 356 of file zone_lighter.h.

Referenced by lightShapes().

friend class NL3D::CLightRunnable [friend]
 

Definition at line 66 of file zone_lighter.h.

friend class NL3D::CRenderZBuffer [friend]
 

Definition at line 67 of file zone_lighter.h.


Field Documentation

std::vector<std::vector<CBezierPatch> > NL3D::CZoneLighter::_BezierPatch [private]
 

Definition at line 508 of file zone_lighter.h.

Referenced by buildZoneInformation(), and getNormal().

std::vector<std::vector<std::vector<bool> > > NL3D::CZoneLighter::_Binded [private]
 

Definition at line 511 of file zone_lighter.h.

Referenced by buildZoneInformation(), and getNormal().

std::vector<std::vector<std::vector<CPatch::CBindInfo> > > NL3D::CZoneLighter::_BindInfo [private]
 

Definition at line 510 of file zone_lighter.h.

Referenced by buildZoneInformation(), and getNormal().

std::map<std::string, NLMISC::CBitmap> NL3D::CZoneLighter::_Bitmaps [private]
 

Definition at line 474 of file zone_lighter.h.

Referenced by getTexture(), and init().

std::vector<CBorderVertex> NL3D::CZoneLighter::_BorderVertices [private]
 

Definition at line 505 of file zone_lighter.h.

Referenced by light().

uint64 NL3D::CZoneLighter::_CPUMask [private]
 

Definition at line 470 of file zone_lighter.h.

Referenced by light().

sint16 CZoneLighter::_GetNormalDeltaS = { -1, 0, 1, 0 } [static, private]
 

Definition at line 1501 of file zone_lighter.cpp.

Referenced by getNormal(), and isLumelOnEdgeMustBeOversample().

sint16 CZoneLighter::_GetNormalDeltaT = { 0, 1, 0, -1 } [static, private]
 

Definition at line 1502 of file zone_lighter.cpp.

Referenced by getNormal(), and isLumelOnEdgeMustBeOversample().

NLMISC::CVector NL3D::CZoneLighter::_GetNormalNormal [private]
 

Definition at line 517 of file zone_lighter.h.

Referenced by buildZoneInformation(), and getNormal().

const NL3D::CPatch* NL3D::CZoneLighter::_GetNormalPatch [private]
 

Definition at line 516 of file zone_lighter.h.

uint NL3D::CZoneLighter::_GetNormalRadius [private]
 

Definition at line 518 of file zone_lighter.h.

uint NL3D::CZoneLighter::_GetNormalSqRadius [private]
 

Definition at line 519 of file zone_lighter.h.

std::vector<float> NL3D::CZoneLighter::_HeightField [private]
 

Definition at line 494 of file zone_lighter.h.

sint NL3D::CZoneLighter::_HeightFieldCellCount [private]
 

Definition at line 495 of file zone_lighter.h.

Referenced by getMaxPhi(), and light().

float NL3D::CZoneLighter::_HeightfieldCellSize [private]
 

Definition at line 497 of file zone_lighter.h.

Referenced by getMaxPhi(), getSkyContribution(), and light().

NLMISC::CVector NL3D::CZoneLighter::_K[256][8] [private]
 

Definition at line 524 of file zone_lighter.h.

NL3D::CLandscape* NL3D::CZoneLighter::_Landscape [private]
 

Definition at line 460 of file zone_lighter.h.

std::vector<uint> NL3D::CZoneLighter::_LastPatchComputed [private]
 

Definition at line 467 of file zone_lighter.h.

Referenced by getAPatch(), and light().

TShapeVect NL3D::CZoneLighter::_LightableShapes [private]
 

lightable shapes

Definition at line 598 of file zone_lighter.h.

Referenced by addLightableShape(), lightShapes(), and lightSingleShape().

std::vector<std::vector<std::vector<CPatchUVLocator> > > NL3D::CZoneLighter::_Locator [private]
 

Definition at line 509 of file zone_lighter.h.

Referenced by buildZoneInformation(), and getNormal().

std::vector<std::vector<CLumelDescriptor> > NL3D::CZoneLighter::_Lumels [private]
 

Definition at line 506 of file zone_lighter.h.

Referenced by buildZoneInformation(), and processCalc().

NLMISC::CFastMutex NL3D::CZoneLighter::_Mutex [private]
 

Definition at line 479 of file zone_lighter.h.

Referenced by NL3D::CRenderZBuffer::run().

uint NL3D::CZoneLighter::_NumberOfPatchComputed [private]
 

Definition at line 468 of file zone_lighter.h.

Referenced by getAPatch(), light(), and NL3D::CRenderZBuffer::run().

uint NL3D::CZoneLighter::_NumLightableShapesProcessed [private]
 

Definition at line 599 of file zone_lighter.h.

Referenced by lightShapes(), and lightSingleShape().

NLMISC::CVector NL3D::CZoneLighter::_OrigineHeightField [private]
 

Definition at line 496 of file zone_lighter.h.

Referenced by getSkyContribution(), and light().

std::vector<std::vector<bool> > NL3D::CZoneLighter::_OversampleEdges [private]
 

Definition at line 512 of file zone_lighter.h.

Referenced by buildZoneInformation().

NLMISC::CSynchronized<std::vector<bool> > NL3D::CZoneLighter::_PatchComputed [private]
 

Definition at line 466 of file zone_lighter.h.

Referenced by getAPatch(), and light().

std::vector<CPatchInfo> NL3D::CZoneLighter::_PatchInfo [private]
 

Definition at line 504 of file zone_lighter.h.

Referenced by getAPatch(), light(), processCalc(), and processZonePointLightRT().

uint NL3D::CZoneLighter::_ProcessCount [private]
 

Definition at line 469 of file zone_lighter.h.

Referenced by light(), and lightShapes().

volatile uint NL3D::CZoneLighter::_ProcessExited [private]
 

Definition at line 471 of file zone_lighter.h.

Referenced by light(), lightShapes(), and NL3D::CRenderZBuffer::run().

CQuadGrid<const CTriangle*> NL3D::CZoneLighter::_QuadGrid[ 10 ] [private]
 

Definition at line 456 of file zone_lighter.h.

NLMISC::CRandom NL3D::CZoneLighter::_Random [private]
 

Definition at line 491 of file zone_lighter.h.

Referenced by attenuation().

NLMISC::CMatrix NL3D::CZoneLighter::_RayBasis [private]
 

Definition at line 457 of file zone_lighter.h.

Referenced by light().

std::vector<std::vector<uint8> > NL3D::CZoneLighter::_ShadowArray [private]
 

Definition at line 463 of file zone_lighter.h.

Referenced by light(), and processCalc().

float NL3D::CZoneLighter::_ShadowBias [private]
 

Definition at line 461 of file zone_lighter.h.

bool NL3D::CZoneLighter::_Softshadow [private]
 

Definition at line 462 of file zone_lighter.h.

CQuadGrid<CPointLightRT*> NL3D::CZoneLighter::_StaticPointLightQuadGrid [private]
 

QuadGrid of PointLights. Builded from _StaticPointLights.

Definition at line 582 of file zone_lighter.h.

std::vector<CPointLightRT> NL3D::CZoneLighter::_StaticPointLights [private]
 

List of PointLights.

Definition at line 580 of file zone_lighter.h.

NLMISC::CVector NL3D::CZoneLighter::_SunDirection [private]
 

Definition at line 458 of file zone_lighter.h.

Referenced by NL3D::CRenderZBuffer::run().

TWaterShapeQuadGrid NL3D::CZoneLighter::_WaterShapeQuadGrid [private]
 

Definition at line 607 of file zone_lighter.h.

Referenced by computeTileFlagsForPositionTowardWater(), and makeQuadGridFromWaterShapes().

TShapeVect NL3D::CZoneLighter::_WaterShapes [private]
 

List of all the water shapes in the zone. We need them to check wether the tiles are above / below water, or if theyr intersect water

Definition at line 603 of file zone_lighter.h.

std::vector<CZBuffer> NL3D::CZoneLighter::_ZBufferLandscape
 

Definition at line 483 of file zone_lighter.h.

Referenced by attenuation(), light(), and NL3D::CRenderZBuffer::run().

CZBuffer NL3D::CZoneLighter::_ZBufferObject
 

Definition at line 484 of file zone_lighter.h.

Referenced by attenuation(), light(), and NL3D::CRenderZBuffer::run().

bool NL3D::CZoneLighter::_ZBufferOverflow [private]
 

Definition at line 488 of file zone_lighter.h.

Referenced by attenuation(), init(), and light().

std::map<uint, uint> NL3D::CZoneLighter::_ZoneId [private]
 

Definition at line 513 of file zone_lighter.h.

Referenced by buildZoneInformation(), and getNormal().

uint NL3D::CZoneLighter::_ZoneToLight [private]
 

Definition at line 459 of file zone_lighter.h.

Referenced by buildZoneInformation(), computeTileFlagsForPositionTowardWater(), light(), processCalc(), processZonePointLightRT(), and setTileFlagsToDefault().


The documentation for this class was generated from the following files:
Generated on Tue Mar 16 08:35:04 2004 for NeL by doxygen 1.3.6