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

245 lines
8.9 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_SHAPE_BANK_H
#define NL_SHAPE_BANK_H
#include "nel/3d/shape.h"
#include "nel/misc/smart_ptr.h"
#include <map>
#include <list>
#include "nel/3d/async_file_manager_3d.h"
namespace NLMISC
{
class IProgressCallback;
}
namespace NL3D
{
class IDriver;
class ITexture;
// ***************************************************************************
/**
* A CShapeBank handle all the instance of the shapes and the cache management
* system.
* There is a default cache. If the shape is not linked explicitly to any cache
* it is linked to the default cache. The comportement of this cache is to not
* do any cache. When the release is called on the last reference to a shape
* linked to this cache, the shape is removed instantly. This is the behavior
* of all newly created cache before we call the setShapeCacheSize method.
*
* NB: ShapeCacheName is case-sensitive but shapeName are not (all entry are lwrcased)
*
* \author Matthieu Besson
* \author Nevrax France
* \date 2000
*/
class CShapeBank
{
public:
/// \name State of a shape
//@{
/** NotPresent : Not present in the bank
* Present : Present in the bank and ready to be used
* AsyncLoad_Error : Asynchronous loading failed
* AsyncLoad_Shape : Asynchronous loading is currently loading the .shape file, textures and lightmaps
* AsyncLoad_Texture : Asynchronous loading is currently uploading textures and lightmaps to VRAM
*/
enum TShapeState { NotPresent, Present,
AsyncLoad_Error, AsyncLoad_Shape, AsyncLoad_Texture, AsyncLoad_Ready, AsyncLoad_Delete };
//@}
CShapeBank();
~CShapeBank();
/// \name Instance Management
//@{
/// Add a reference to a shape and return the instance created. NB: getPresentState()==Present must be tested first.
IShape* addRef (const std::string &shapeName);
/**
* Release a reference to a shape by its instance. If the shape has no more reference it is added to
* its own shape cache. When the shape cache is full the last entry is deleted.
*/
void release (IShape* pShp);
/// Return the shape state. Process the waiting shapes.
TShapeState getPresentState (const std::string &shapeName);
/** Return the IShape from the bank. Unlike addRef, no reference is added.
* Thus the returning shape sould be used temporarily
* \return NULL if shape not found or not loaded (if being async loaded still return NULL)
*/
IShape *getShape (const std::string &shapeName);
/// Load the corresponding file from disk and add it to the bank.
void load (const std::string &shapeName);
/** Load the corresponding file from disk asynchronously and add it to the bank.
* The driver passed to this function is used to know if we have to load the textures.
*/
void loadAsync (const std::string &shapeName, IDriver *pDriver, const NLMISC::CVector &position, bool *bSignal, uint selectedTexture);
void cancelLoadAsync (const std::string &shapeName);
bool isShapeWaiting ();
/// processWaitingShapes must be done one time per frame
void processWaitingShapes ();
/// Setup the maximum number of bytes to upload for a frame (texture upload from RAM to VRAM)
void setMaxBytesToUpload (uint32 MaxUploadPerFrame);
/// Add directly a shape to the bank. If the shape name is already used do nothing.
void add (const std::string &shapeName, IShape* shape);
//@}
/// \name Shape cache management
//@{
/// Add a new ShapeCache. If already exist do nothing.
void addShapeCache (const std::string &shapeCacheName);
/**
* Remove a ShapeCache. All shapes in the shape cache are deleted. All links are redirected to
* the default ShapeCache
*/
void removeShapeCache (const std::string &shapeCacheName);
/// true if the shape cache exist
bool isShapeCache(const std::string &shapeCacheName) const;
/**
* Remove all ShapeCache and suppress all links (even the link to the default cache are removed)
*/
void reset ();
/// Set the shapeCache shapeCacheName the new size.(delete shapes if maxsize<shapeCacheSize).
void setShapeCacheSize (const std::string &shapeCacheName, sint32 maxSize);
/// return free cache space (maxSize-nbCurrentInCache)
sint getShapeCacheFreeSpace(const std::string &shapeCacheName) const;
/// Link a shape to a ShapeCache. The ShapeCache must exist and must not contains the shape.
void linkShapeToShapeCache (const std::string &shapeName, const std::string &shapeCacheName);
//@}
/// \name Tools
// @{
/** PreLoad all shapes (.shape, .ps, .skel...) files from a list of files
* Shapes are Loaded if not present, assigned to the given cache, and fit in the cache Size as max possible.
* NB: crash if you try to load a non shape file (eg: a .dds etc...)
* \param shapeCacheName name of a shapeCache created with addShapeCache()/setShapeCacheSize(). no-op if don't exist
* \param fileList a list of file names. NB: CPath is used to load the shapes.
* \param wildcard a filter string like: "*.shape", "??_HOM*.shape". NB: toLower-ed internally
* \param flushTextures if true, then textures are flushed in the driver drv
*/
void preLoadShapes(const std::string &shapeCacheName,
const std::vector<std::string> &listFile, const std::string &wildCardNotLwr, NLMISC::IProgressCallback *progress = NULL, bool flushTextures = false, IDriver *drv = NULL);
/** Mark this shape name as needing a buildSystemGeometry() (typically used for selection)
* NB: this will take effect only for shapes on a subsequent add(), load() or loadAsync()
*/
void buildSystemGeometryForshape(const std::string &shapeName);
// @}
// get the shape Name from the shape Ptr. return NULL if not found
const std::string* getShapeNameFromShapePtr(IShape* pShp) const;
private:
/// \name Shape/Instances.
//@{
typedef NLMISC::CSmartPtr<IShape> PShape;
typedef std::map<std::string, PShape> TShapeMap;
TShapeMap ShapeMap;
struct CWaitingShape
{
IShape *ShapePtr; // Do not work with this value that is shared between threads
uint32 RefCnt; // Counter if multiple instance wants the same shape
TShapeState State; // State of the waiting shape (shape in loading mode)
std::set<bool *> Signal; // To signal when all is done
// Upload piece by piece part
uint32 UpTextProgress; // Upload Texture progress current texture or lightmap
uint8 UpTextMipMap; // Upload Texture progress current mipmap
uint32 UpTextLine; // Upload Texture progress current line in mipmap
// ---------------------------------
CWaitingShape ()
{
State = AsyncLoad_Shape;
RefCnt = 0;
ShapePtr = NULL;
UpTextProgress = 0;
UpTextMipMap = 0;
UpTextLine = 0;
}
};
typedef std::map< std::string, CWaitingShape > TWaitingShapesMap;
TWaitingShapesMap WaitingShapes;
uint32 _MaxUploadPerFrame;
private:
/// return true if the texture is entirely uploaded
bool processWSUploadTexture (CWaitingShape &rWS, uint32 &nTotalUploaded, ITexture *pText);
private:
IDriver *_pDriver;
//@}
/// \name Shape/Caches.
//@{
struct CShapeCache
{
std::list<IShape*> Elements;
sint32 MaxSize;
CShapeCache() { MaxSize = 0; }
};
struct CShapeInfo
{
CShapeCache* pShpCache;
std::string sShpName;
bool isAdded;
CShapeInfo() { isAdded = false; pShpCache = NULL; }
};
private:
IShape* getShapePtrFromShapeName(const std::string &pShpName);
CShapeCache* getShapeCachePtrFromShapePtr(IShape* pShp);
CShapeCache* getShapeCachePtrFromShapeCacheName(const std::string &shapeCacheName);
CShapeCache* getShapeCachePtrFromShapeName(const std::string &shapeName);
void checkShapeCache(CShapeCache* pShpCache);
typedef std::map<std::string,std::string> TShapeCacheNameMap;
typedef std::map<std::string,CShapeCache> TShapeCacheMap;
typedef std::map<IShape*,CShapeInfo> TShapeInfoMap;
TShapeCacheNameMap ShapeNameToShapeCacheName;
TShapeCacheMap ShapeCacheNameToShapeCache;
TShapeInfoMap ShapePtrToShapeInfo;
// Special for buildSystemGeometryForshape
std::set<std::string> _ShapeNeedingSystemGeometryCopy;
//@}
};
}
#endif // NL_SHAPE_BANK_H
/* End of shape_bank.h */