khanat-opennel-code/code/nel/include/nel/3d/instance_lighter.h

299 lines
9.3 KiB
C++

// NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef NL_INSTANCE_LIGHTER_H
#define NL_INSTANCE_LIGHTER_H
#include "nel/misc/types_nl.h"
#include "nel/misc/vector.h"
#include "nel/misc/triangle.h"
#include "nel/misc/plane.h"
#include "nel/misc/matrix.h"
#include "nel/3d/scene_group.h"
#include "nel/3d/landscape.h"
#include "nel/3d/shape.h"
#include "nel/3d/mesh.h"
#include "nel/3d/mesh_mrm.h"
#include "nel/3d/cube_grid.h"
#include "nel/3d/ig_surface_light_build.h"
namespace NL3D
{
// ***************************************************************************
/**
* A class to precompute "StaticSetup" lighting for instances in an InstanceGroup.
* Class "inspired" from CZoneLighter :)
* \author Lionel Berenguier
* \author Nevrax France
* \date 2001
*/
class CInstanceLighter
{
public:
enum {MaxOverSamples= 16};
public:
// Light Options decription structure
class CLightDesc
{
public:
// Default Ctor
CLightDesc ();
// Disable Sun contribution: ie set 0 to all contributions of sun on instances and surfaces?? false by default
bool DisableSunContribution;
// Sun direction
NLMISC::CVector LightDirection;
// Grid size
uint GridSize;
// Grid size
float GridCellSize;
// Project shadows on instances.
bool Shadow;
// Number of samples For sun shadowing only. Must be: 0 (disable), 2, 4, 8, 16
uint OverSampling;
// This is a user shapeMap.
std::map<std::string, IShape*> UserShapeMap;
};
// A triangle used to light the zone
class CTriangle
{
friend class CInstanceLighter;
public:
// Ctors
CTriangle (const NLMISC::CTriangle& triangle, sint instanceId)
{
Triangle=triangle;
InstanceId= instanceId;
}
// The triangle
NLMISC::CTriangle Triangle;
// which instance owns this triangle. -1 if none (landscape or others ig).
sint InstanceId;
// Other info
const NLMISC::CPlane &getPlane() const {return Plane;}
private:
NLMISC::CPlane Plane;
};
public:
/** Tool method which take a single IG, and do all the god job to light this one, with no other dependencies
* NB: it uses instLighter passed, init() ing it. It use lightDesc.UserShapeMap or it load Shape in directory lightDesc.ShapePath
*/
static void lightIgSimple(CInstanceLighter &instLighter, const CInstanceGroup &igIn, CInstanceGroup &igOut, const CLightDesc &lightDesc, const char *igName);
public:
/// Constructor
CInstanceLighter();
/// Destructor
virtual ~CInstanceLighter() {}
// Init the system
void init ();
/** Light an InstanceGroup
* igOut has different PointLights than igIn. eg: if a pointLight do not light anything, then it is not
* present in igOut.
* NB: shapes are used to retrieve useful info on them (center of AABBox ...) . They are taken from
* lightDesc.UserShapeMap, or loaded from lightDesc.ShapePath if not found.
* \param landscape if !NULL use this Landscape SunContribution, looking landscape faces under each instance,
* for faster computing, and to get influence of Sky. NB: this landscape does not have to be tesselated,
* but all Zones that lies under igIn should be loaded in.
* \param igSurfaceLightBuild if !NULL, light() will compute igOut.IGSurfaceLight, else it is just cleared.
*/
void light (const CInstanceGroup &igIn, CInstanceGroup &igOut, const CLightDesc &lightDesc, std::vector<CTriangle>& obstacles,
CLandscape *landscape= NULL, CIGSurfaceLightBuild *igSurfaceLightBuild= NULL);
// Add triangles from a landscape
static void addTriangles (CLandscape &landscape, std::vector<uint> &listZone, uint order, std::vector<CTriangle>& triangleArray);
/** Add triangles from a transform shape. Work only for CMesh, CMultiMesh and CMeshMRM all without skinning.
* Give An instanceId!=-1 only for instances of the IG to compute. This is to avoid auto-shadowing.
*/
static void addTriangles (const IShape &shape, const NLMISC::CMatrix& modelMT, std::vector<CTriangle>& triangleArray, sint instanceId);
// Progress callback
virtual void progress (const char * /* message */, float /* progress */) {}
/// \name Static PointLights mgt.
//@{
/** Append a static point light to compute. call at setup stage (before light() ).
* NB: you must append all PointLights of intersets, even ones from the IG to compute.
*/
void addStaticPointLight(const CPointLightNamed &pln, const char *igName);
//@}
// ********************************
private:
static void addTriangles (const CMeshGeom &meshGeom, const NLMISC::CMatrix& modelMT, std::vector<CTriangle>& triangleArray, sint instanceId);
static void addTriangles (const CMeshMRMGeom &meshGeom, const NLMISC::CMatrix& modelMT, std::vector<CTriangle>& triangleArray, sint instanceId);
static void excludeAllPatchFromRefineAll (CLandscape &landscape, std::vector<uint> &listZone, bool exclude);
// light / rayTrace against sun.
void computeSunContribution(const CLightDesc &lightDesc, std::vector<CTriangle>& obstacles, CLandscape *landscape);
void dilateLightingOnSurfaceCells();
private:
struct CPointLightRT;
struct CInstanceInfo
{
// Center of the mesh to compute lighting.
CVector CenterPos;
// Pos of samples, for overSampling. if none, OverSamples[0]== CenterPos
CVector OverSamples[MaxOverSamples];
// Temp light which influence this instance.
CPointLightRT *Light[CInstanceGroup::NumStaticLightPerInstance];
// Temp Ambient light which influence this instance.
CPointLightRT *LocalAmbientLight;
};
// Instance of the current ig to be lighted.
std::vector<CInstanceGroup::CInstance> _Instances;
// Instance Lighting Info of the current ig to be lighted.
std::vector<CInstanceInfo> _InstanceInfos;
// The current instance computed. Used to skip it in raytracing
sint _CurrentInstanceComputed;
// CIGSurfaceLight Info.
CIGSurfaceLightBuild *_IGSurfaceLightBuild;
// The RetrieverGridMap currently builded.
CIGSurfaceLight::TRetrieverGridMap _IGRetrieverGridMap;
/// A PointLight struct to test raytracing.
struct CPointLightRT
{
CPointLightNamed PointLight;
float OODeltaAttenuation;
// BBox of the pointLight
NLMISC::CBSphere BSphere;
// Faces that may occlude the light. Only Back Faces (from the light pov) are inserted
CCubeGrid<const CTriangle*> FaceCubeGrid;
// Number of TileLightInfluences which use this PointLight.
uint RefCount;
// Final id of the pointLight in the Ig.
uint DstId;
CPointLightRT();
/** Tells if a point is visible from this light. NB: test first if in BSphere.
* If occluded or out of radius, return false, else return true.
* if instanceComputed>=0, then skip obstacles with InstanceId==instanceComputed.
* Also Skip if the light is an Ambient, and skip if the light is a spot and if the position is out of the cone
*/
bool testRaytrace(const CVector &v, sint instanceComputed= -1);
};
/// For sort()
struct CPredPointLightToPoint
{
CVector Point;
bool operator() (CPointLightRT *pla, CPointLightRT *plb) const;
};
/// List of PointLights
std::vector<CPointLightRT> _StaticPointLights;
/// QuadGrid of PointLights. Builded from _StaticPointLights
CQuadGrid<CPointLightRT*> _StaticPointLightQuadGrid;
/// Fill CubeGrid, and set PointLightRT in _StaticPointLightQuadGrid.
void compilePointLightRT(uint gridSize, float gridCellSize, std::vector<CTriangle>& obstacles, bool doShadow);
/** Process the IG, ie process _InstanceInfos. Also process SurfaceLightGrid
* MultiCPU: not done for now. Be aware of CPointLightRT::RefCount!!!!
*/
void processIGPointLightRT(std::vector<CPointLightNamed> &listPointLight);
private:
/// \name Cell Iteration. ie iteration on _IGRetrieverGridMap cells and _IGSurfaceLightBuild cells
// @{
void beginCell();
void nextCell();
bool isEndCell();
// get current cell iterated.
CSurfaceLightGrid::CCellCorner &getCurrentCell();
// get current cellInfo iterated.
CIGSurfaceLightBuild::CCellCorner &getCurrentCellInfo();
// Neighboring of the cell
bool isCurrentNeighborCellInSurface(sint xnb, sint ynb);
CSurfaceLightGrid::CCellCorner &getCurrentNeighborCell(sint xnb, sint ynb);
CIGSurfaceLightBuild::CCellCorner &getCurrentNeighborCellInfo(sint xnb, sint ynb);
uint getCurrentCellNumber() const {return _ItCurrentCellNumber;}
uint getTotalCellNumber() const {return _TotalCellNumber;}
void progressCell(const char *message);
// Iteration Data.
CIGSurfaceLight::ItRetrieverGridMap _ItRetriever;
CIGSurfaceLightBuild::ItRetrieverGridMap _ItRetrieverInfo;
uint _ItSurfId;
uint _ItCellId;
bool _IsEndCell;
uint _ItCurrentCellNumber;
uint _TotalCellNumber;
float _LastCellProgress;
// @}
};
} // NL3D
#endif // NL_INSTANCE_LIGHTER_H
/* End of instance_lighter.h */