khanat-code-old/code/nel/include/nel/3d/scene_group.h
2010-06-12 12:17:29 +02:00

443 lines
14 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_SCENE_GROUP_H
#define NL_SCENE_GROUP_H
#include "nel/misc/types_nl.h"
#include "nel/misc/vector.h"
#include "nel/misc/quat.h"
#include "nel/misc/smart_ptr.h"
#include "nel/3d/portal.h"
#include "nel/3d/cluster.h"
#include "nel/3d/transform.h"
#include "nel/3d/point_light_named.h"
#include "nel/3d/point_light_named_array.h"
#include "nel/3d/ig_surface_light.h"
#include "nel/3d/clip_trav.h"
#include <vector>
namespace NLMISC
{
class CRGBA;
class IStream;
struct EStream;
class CMatrix;
}
namespace NL3D {
class CScene;
class CTransformShape;
class IDriver;
class ITransformName;
struct IAddRemoveInstance;
struct IIGAddBegin;
/**
* A CInstanceGroup is a group of mesh instance and so composed by
* - A reference to a mesh (refered by the name)
* - The transformations to get it to the world
* - The parent
*
* This class can initialize a scene and be serialized.
*
* \author Matthieu Besson
* \author Nevrax France
* \date 2001
*/
class CInstanceGroup : public NLMISC::CRefCount
{
/* ***********************************************
* WARNING: This Class/Method must be thread-safe (ctor/dtor/serial): no static access for instance
* It can be loaded/called through CAsyncFileManager for instance
* ***********************************************/
public:
/// Should Never be changed
enum {NumStaticLightPerInstance= 2};
enum TState { StateNotAdded = 0, StateAdding, StateAdded, StateError };
public:
/**
* Instance part
*/
/// An element of the group.
class CInstance
{
public:
/// Name of the Shape Instance
std::string Name;
/// The parent instance (-1 if root)
sint32 nParent;
/// The clusters the instance belongs to
std::vector<uint32> Clusters;
/// Transformations
NLMISC::CQuat Rot;
NLMISC::CVector Pos;
NLMISC::CVector Scale;
// Name of the instance
std::string InstanceName;
/// If true, then the shape is even not loaded/displayed (used for shadow casting?)
bool DontAddToScene;
/// If false, the shape is load but hid by default (NB: can be used for camera collision)
bool Visible;
/// Precomputed Lighting.
// If true (false by default), then the instance don't cast shadow (used by ig_lighter.exe).
bool DontCastShadow;
// If true (false by default), then the instance's lighting will not be precomputed.
bool AvoidStaticLightPreCompute;
// This part is precomputed.
bool StaticLightEnabled; // If false, then the instance 's lighting is not pre-computed.
uint8 SunContribution; // Contribution of the Sun.
// Ids of the lights. FF == disabled. if Lights[i]==FF, then all lights >=i are considered disabled.
uint8 Light[NumStaticLightPerInstance];
/** Id of the ambiant Light to take for this instance. Ambient light are stored too in ig->getPointLigths()
* If 0xFF => take Ambient of the sun.
*/
uint8 LocalAmbientId;
/** if true (false by default), the instance don't cast shadow, but ONLY FOR ig_lighter.exe (ig_lighter_lib)
* (zone_lighter and zone_ig_lighter ignore it).
* This is a special trick for the "Matis Serre" where the exterior mesh cast shadow in the interior, but
* is not visible in the interior in realTime because of cluster clipping.... omg :(
*/
bool DontCastShadowForInterior;
/** This is the opposite of DontCastShadowForInterior. zone_lighter or zone_ig_lighter test it and if true,
* assume this instance dont cast shadow
*/
bool DontCastShadowForExterior;
/// Constructor
CInstance ();
/// Serial the instance
void serial (NLMISC::IStream& f);
};
/// A vector of instance.
typedef std::vector<CInstance> TInstanceArray;
/// Remove all of these methods. For the moment DO NOT USE THEM !!!
/// Get number of instance in this group
uint getNumInstance () const;
/// Get the name of the mesh referenced
const std::string& getShapeName (uint instanceNb) const;
/// Get the instance name
const std::string& getInstanceName (uint instanceNb) const;
/// Get an instance position
const NLMISC::CVector& getInstancePos (uint instanceNb) const;
/// Get an instance rotation
const NLMISC::CQuat& getInstanceRot (uint instanceNb) const;
// Get an instance scale
const NLMISC::CVector& getInstanceScale (uint instanceNb) const;
// Get instance matrix (no pivot added)
void getInstanceMatrix(uint instanceNb, NLMISC::CMatrix &dest) const;
// Get the instance father (-1 if this is a root)
sint32 getInstanceParent (uint instanceNb) const;
// Get a const ref on the instance
const CInstance &getInstance(uint instanceNb) const;
// Get a mutable ref on the instance
CInstance &getInstance(uint instanceNb);
// Get the ig global pos
const NLMISC::CVector &getGlobalPos() const { return _GlobalPos; }
/** Get the instance added to the scene. NULL if instanceNb too big, if addToScene not called,
* or if instance is DontAddToScene
*/
CTransformShape *getTransformShape(uint instanceNb) const;
/**
* Construct, serialize and link to scene
*/
CInstanceGroup();
~CInstanceGroup();
/** Build the group
* Build with an empty list of light
*/
void build (const CVector &vGlobalPos, const TInstanceArray& array,
const std::vector<CCluster>& Clusters,
const std::vector<CPortal>& Portals);
/** Build the group
* Build also the list of light. NB: sort by LightGroupName the array.
* Give also a ptr on a retrieverGridMap to build surfaces (if not NULL).
*/
void build (const CVector &vGlobalPos, const TInstanceArray& array,
const std::vector<CCluster>& Clusters,
const std::vector<CPortal>& Portals,
const std::vector<CPointLightNamed> &pointLightList,
const CIGSurfaceLight::TRetrieverGridMap *retrieverGridMap= NULL,
float igSurfaceLightCellSize= 0);
/** Retreive group information. NB: data may have changed, eg: order of lights.
*/
void retrieve (CVector &vGlobalPos, TInstanceArray& array,
std::vector<CCluster>& Clusters,
std::vector<CPortal>& Portals,
std::vector<CPointLightNamed> &pointLightList) const;
/// Serial the group
void serial (NLMISC::IStream& f);
/// Add all the instances to the scene
void createRoot (CScene& scene);
/// Setup the callback in charge of changing name at the addToScene moment
void setTransformNameCallback (ITransformName *pTN);
/// Set a callback to know when an instance has been added / removed
void setAddRemoveInstanceCallback(IAddRemoveInstance *callback);
/// Set a callback to know when an instance group is being created, and how many instances it contains
void setIGAddBeginCallback(IIGAddBegin *callback);
/**
* Add all the instances to the scene. By default, freezeHRC() those instances and the root.
*
* \param scene is the scene in which you want to add the instance group.
* \param driver is a pointer to a driver. If this pointer is not NULL, the textures used by
* the shapes will be preloaded in this driver. If the pointer is NULL (default), textures
* will ve loaded when the shape will be used.
*/
bool addToScene (CScene& scene, IDriver *driver=NULL, uint selectedTexture=0);
bool addToSceneAsync (CScene& scene, IDriver *driver=NULL, uint selectedTexture=0);
void stopAddToSceneAsync ();
TState getAddToSceneState ();
/**
* Get the instance name to create as written in the instance group.
*/
void getShapeName (uint instanceIndex, std::string &shapeName) const;
/// User Interface related: yes it is ugly....
void setUserInterface(class UInstanceGroup *uig) {_UserIg= uig;}
class UInstanceGroup *getUserInterface() const {return _UserIg;}
/** For Debug Display of clusters. The view matrix and frustum should have been setuped
* NB: the ModelMatrix is modified by this method
*/
void displayDebugClusters(IDriver *drv, class CTextContext *txtCtx);
private:
bool addToSceneWhenAllShapesLoaded (CScene& scene, IDriver *driver, uint selectedTexture);
public:
/// Remove all the instances from the scene
bool removeFromScene (CScene& scene);
/**
* LightMap part
*/
/// Get all lights (lightmaps) from an instance group
void getLights (std::set<std::string> &LightNames);
/**
* BlendShape part
*/
/// Get all the blendshapes from an instance group
void getBlendShapes (std::set<std::string> &BlendShapeNames);
/// Set the blendshape factor for the whole instance group (-100 -> 100)
void setBlendShapeFactor (const std::string &BlendShapeName, float rFactor);
/**
* Cluster/Portal system part
*/
/// To construct the cluster system by hand
void addCluster (CCluster *pCluster);
/// Set the cluster system to test for instances that are not in a cluster of this IG
void setClusterSystemForInstances (CInstanceGroup *pIG);
/// Get all dynamic portals of an instance group
void getDynamicPortals (std::vector<std::string> &names);
/// Set the state of a dynamic portal (true=opened, false=closed)
void setDynamicPortal (std::string& name, bool opened);
/// Get the state of a dynamic portal (true=opened, false=closed)
bool getDynamicPortal (std::string& name);
/**
* Transformation part
*/
/// link the root of the ig to a node. No-op if not added to scene. Pass NULL to reset by default
void linkRoot (CScene &scene, CTransform *father);
/// Set the position of the IG
void setPos (const CVector &pos);
/// Set the rotation of the IG
void setRotQuat (const CQuat &quat);
/// Get the position of the IG
CVector getPos ();
/// Get the rotation of the IG
CQuat getRotQuat ();
/// see CTransform::freezeHRC(). Do it for all instances (not clusters), and for the root of the IG.
void freezeHRC();
/// see CTransform::unfreezeHRC(). Do it for all instances (not clusters), and for the root of the IG.
void unfreezeHRC();
public:
/// \name RealTime lighting part
// @{
/// get the list of light. NB: the array is sorted by LightGroupName.
const std::vector<CPointLightNamed> &getPointLightList() const {return _PointLightArray.getPointLights();}
/// Get the number of point lights
uint getNumPointLights() const { return (uint)_PointLightArray.getPointLights().size(); }
/// Get a mutable ref on a point light named
CPointLightNamed &getPointLightNamed(uint index)
{
return _PointLightArray.getPointLights()[index];
}
/// set the Light factor for all pointLights "lightGroupName".
void setPointLightFactor(const CScene &scene);
/// See CIGSurfaceLight::getStaticLightSetup()
bool getStaticLightSetup(NLMISC::CRGBA sunAmbient, uint retrieverIdentifier, sint surfaceId, const CVector &localPos,
std::vector<CPointLightInfluence> &pointLightList, uint8 &sunContribution, NLMISC::CRGBA &localAmbient)
{
return _IGSurfaceLight.getStaticLightSetup(sunAmbient, retrieverIdentifier, surfaceId, localPos,
pointLightList, sunContribution, localAmbient);
}
/// Get the SurfaceLight info, for debug purposes.
const CIGSurfaceLight &getIGSurfaceLight() const {return _IGSurfaceLight;}
/// Setuped at export, tells if the ig is touched by the sun. true by default.
void enableRealTimeSunContribution(bool enable);
bool getRealTimeSunContribution() const {return _RealTimeSunContribution;}
// @}
/** Look through all hierarchy our clusters that must be linked to our parent
*/
bool linkToParent (CInstanceGroup*pFather);
/** Get the parent ClusterSystem
*/
CInstanceGroup *getParentClusterSystem() const {return _ParentClusterSystem;}
public:
TInstanceArray _InstancesInfos;
std::vector<CTransformShape*> _Instances;
std::vector<CPortal> _Portals;
std::vector<CCluster> _ClusterInfos;
std::vector<CCluster*> _ClusterInstances;
CTransform *_Root;
CClipTrav *_ClipTrav;
// The cluster system used to link unclustered instances (setClusterSystemForInstances)
CInstanceGroup *_ClusterSystemForInstances;
// The cluster system parent of us (linkToParent() call)
CInstanceGroup *_ParentClusterSystem;
NLMISC::CVector _GlobalPos;
private:
/// \name PointLight part
// @{
/// RealTimeSunContribution. Used for ig_lighter and zone_ig_lighter
bool _RealTimeSunContribution;
/// Array of pointLights
CPointLightNamedArray _PointLightArray;
/// Build the list of light. NB: sort by LightGroupName the array, and return index remap.
void buildPointLightList(const std::vector<CPointLightNamed> &pointLightList,
std::vector<uint> &plRemap);
/// The object used to light dynamic models in town and buildings
CIGSurfaceLight _IGSurfaceLight;
// @}
/// \name Async loading part
// @{
bool _AddToSceneSignal;
TState _AddToSceneState;
CScene *_AddToSceneTempScene;
IDriver *_AddToSceneTempDriver;
uint _AddToSceneTempSelectTexture;
// @}
ITransformName *_TransformName;
IAddRemoveInstance *_AddRemoveInstance;
IIGAddBegin *_IGAddBeginCallback;
// Yes this is ugly, but impossible otherwise with the actual user interface system...
UInstanceGroup *_UserIg;
};
} // NL3D
#endif // NL_SCENE_GROUP_H
/* End of scene_group.h */