/usr/include/OGRE/OgreInstanceManager.h is in libogre-1.8-dev 1.8.1+dfsg-0ubuntu3.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 | /*
-----------------------------------------------------------------------------
This source file is part of OGRE
(Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/
Copyright (c) 2000-2012 Torus Knot Software Ltd
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-----------------------------------------------------------------------------
*/
#ifndef __InstanceManager_H__
#define __InstanceManager_H__
#include "OgrePrerequisites.h"
#include "OgreMesh.h"
#include "OgreRenderOperation.h"
namespace Ogre
{
/** \addtogroup Core
* @{
*/
/** \addtogroup Scene
* @{
*/
/** This is the main starting point for the new instancing system.
Each InstanceManager can control one technique and one mesh, but it can manage
multiple materials at the same time.
@see SceneManager::createInstanceManager, which creates this InstanceManager. Each one
must have a unique name. It's wasteless to create two InstanceManagers with the same
mesh reference, instancing technique and instances per batch count.
This class takes care of managing batches automatically, so that more are created when
needed, and reuse existing ones as much as posible; thus the user doesn't have to worry
of managing all those low level issues.
@see InstanceBatch & @see InstanceEntity for more information.
@remarks
Design discussion webpage: http://www.ogre3d.org/forums/viewtopic.php?f=4&t=59902
@author
Matias N. Goldberg ("dark_sylinc")
@version
1.0
*/
class _OgreExport InstanceManager : public FactoryAlloc
{
public:
enum InstancingTechnique
{
ShaderBased, //Any SM 2.0+ @See InstanceBatchShader
TextureVTF, //Needs Vertex Texture Fetch & SM 3.0+ @See InstanceBatchVTF
HWInstancingBasic, //Needs SM 3.0+ and HW instancing support @See InstanceBatchHW
HWInstancingVTF, //Needs SM 3.0+, HW instancing support & VTF @See InstanceBatchHW_VTF
InstancingTechniquesCount
};
/** Values to be used in setSetting() & BatchSettings::setting */
enum BatchSettingId
{
/// Makes all batches from same material cast shadows
CAST_SHADOWS = 0,
/// Makes each batch to display it's bounding box. Useful for debugging or profiling
SHOW_BOUNDINGBOX,
NUM_SETTINGS
};
private:
struct BatchSettings
{
//These are all per material
bool setting[NUM_SETTINGS];
BatchSettings()
{
setting[CAST_SHADOWS] = true;
setting[SHOW_BOUNDINGBOX] = false;
}
};
typedef vector<InstanceBatch*>::type InstanceBatchVec; //vec[batchN] = Batch
typedef map<String, InstanceBatchVec>::type InstanceBatchMap; //map[materialName] = Vec
typedef map<String, BatchSettings>::type BatchSettingsMap;
const String mName; //Not the name of the mesh
MeshPtr mMeshReference;
InstanceBatchMap mInstanceBatches;
size_t mIdCount;
InstanceBatchVec mDirtyBatches;
RenderOperation mSharedRenderOperation;
size_t mInstancesPerBatch;
InstancingTechnique mInstancingTechnique;
uint16 mInstancingFlags; //@see InstanceManagerFlags
unsigned short mSubMeshIdx;
BatchSettingsMap mBatchSettings;
SceneManager* mSceneManager;
size_t mMaxLookupTableInstances;
/** Finds a batch with at least one free instanced entity we can use.
If none found, creates one.
*/
inline InstanceBatch* getFreeBatch( const String &materialName );
/** Called when batches are fully exhausted (can't return more instances) so a new batch
is created.
For the first time use, it can take big build time.
It takes care of getting the render operation which will be shared by further batches,
which decreases their build time, and prevents GPU RAM from skyrocketing.
@param materialName The material name, to know where to put this batch in the map
@param firstTime True if this is the first time it is called
@return The created InstancedManager for convenience
*/
InstanceBatch* buildNewBatch( const String &materialName, bool firstTime );
/** @see defragmentBatches overload, this takes care of an array of batches
for a specific material */
void defragmentBatches( bool optimizeCull, vector<InstancedEntity*>::type &entities,
InstanceBatchVec &fragmentedBatches );
/** @see setSetting. This function helps it by setting the given parameter to all batches
in container.
*/
void applySettingToBatches( BatchSettingId id, bool value, const InstanceBatchVec &container );
/** Called when we you use a mesh which has shared vertices, the function creates separate
vertex/index buffers and also recreates the bone assignments.
*/
void unshareVertices(const Ogre::MeshPtr &mesh);
public:
InstanceManager( const String &customName, SceneManager *sceneManager,
const String &meshName, const String &groupName,
InstancingTechnique instancingTechnique, uint16 instancingFlags,
size_t instancesPerBatch, unsigned short subMeshIdx, bool useBoneMatrixLookup = false);
virtual ~InstanceManager();
const String& getName() const { return mName; }
/** Raises an exception if trying to change it after creating the first InstancedEntity
@remarks The actual value may be less if the technique doesn't support having so much
@see getMaxOrBestNumInstancesPerBatches for the usefulness of this function
@param instancesPerBatch New instances per batch number
*/
void setInstancesPerBatch( size_t instancesPerBatch );
/** Sets the size of the lookup table for techniques supporting bone lookup table.
Raises an exception if trying to change it after creating the first InstancedEntity.
Setting this value below the number of unique (non-sharing) entity instance animations
will produce a crash during runtime. Setting this value above will increase memory
consumption and reduce framerate.
@remarks The value should be as close but not below the actual value.
@param maxLookupTableInstances New size of the lookup table
*/
void setMaxLookupTableInstances( size_t maxLookupTableInstances );
/** Calculates the maximum (or the best amount, depending on flags) of instances
per batch given the suggested size for the technique this manager was created for.
@remarks
This is done automatically when creating an instanced entity, but this function in conjunction
with @see setInstancesPerBatch allows more flexible control over the amount of instances
per batch
@param materialName Name of the material to base on
@param suggestedSize Suggested amount of instances per batch
@param flags @see InstanceManagerFlags
@return The max/best amount of instances per batch given the suggested size and flags
*/
size_t getMaxOrBestNumInstancesPerBatch( String materialName, size_t suggestedSize, uint16 flags );
/** @copydoc SceneManager::createInstancedEntity */
InstancedEntity* createInstancedEntity( const String &materialName );
/** This function can be useful to improve CPU speed after having too many instances
created, which where now removed, thus freeing many batches with zero used Instanced Entities
However the batches aren't automatically removed from memory until the InstanceManager is
destroyed, or this function is called. This function removes those batches which are completely
unused (only wasting memory).
*/
void cleanupEmptyBatches(void);
/** After creating many entities (which turns in many batches) and then removing entities that
are in the middle of these batches, there might be many batches with many free entities.
Worst case scenario, there could be left one batch per entity. Imagine there can be
80 entities per batch, there are 80 batches, making a total of 6400 entities. Then
6320 of those entities are removed in a very specific way, which leads to having
80 batches, 80 entities, and GPU vertex shader still needs to process 6400!
This is called fragmentation. This function reparents the InstancedEntities
to fewer batches, in this case leaving only one batch with 80 entities
@remarks
This function takes time. Make sure to call this only when you're sure there's
too much of fragmentation and you won't be creating more InstancedEntities soon
Also in many cases cleanupEmptyBatches() ought to be enough
Defragmentation is done per material
Static batches won't be defragmented. If you want to degragment them, set them
to dynamic again, and switch back to static after calling this function.
@param optimizeCulling When true, entities close together will be reorganized
in the same batch for more efficient CPU culling. This can take more CPU
time. You want this to be false if you now you're entities are moving very
randomly which tends them to get separated and spread all over the scene
(which nullifies any CPU culling)
*/
void defragmentBatches( bool optimizeCulling );
/** Applies a setting for all batches using the same material_ existing ones and
those that will be created in the future.
@par
For example setSetting( BatchSetting::CAST_SHADOWS, false ) disables shadow
casting for all instanced entities (@see MovableObject::setCastShadow)
@par
For example setSetting( BatchSetting::SHOW_BOUNDINGBOX, true, "MyMat" )
will display the bounding box of the batch (not individual InstancedEntities)
from all batches using material "MyMat"
@note If the material name hasn't been used, the settings are still stored
This allows setting up batches before they get even created.
@param id Setting Id to setup, @see BatchSettings::BatchSettingId
@param enabled Boolean value. It's meaning depends on the id.
@param materialName When Blank, the setting is applied to all existing materials
*/
void setSetting( BatchSettingId id, bool value, const String &materialName = StringUtil::BLANK );
/// If settings for the given material didn't exist, default value is returned
bool getSetting( BatchSettingId id, const String &materialName ) const;
/** Returns true if settings were already created for the given material name.
If false is returned, it means getSetting will return default settings.
*/
bool hasSettings( const String &materialName ) const
{ return mBatchSettings.find( materialName ) != mBatchSettings.end(); }
/** @copydoc InstanceBatch::setStaticAndUpdate */
void setBatchesAsStaticAndUpdate( bool bStatic );
/** Called by an InstanceBatch when it requests their bounds to be updated for proper culling
@param dirtyBatch The batch which is dirty, usually same as caller.
*/
void _addDirtyBatch( InstanceBatch *dirtyBatch );
/** Called by SceneManager when we told it we have at least one dirty batch */
void _updateDirtyBatches(void);
typedef ConstMapIterator<InstanceBatchMap> InstanceBatchMapIterator;
typedef ConstVectorIterator<InstanceBatchVec> InstanceBatchIterator;
/// Get non-updateable iterator over instance batches per material
InstanceBatchMapIterator getInstanceBatchMapIterator(void) const
{ return InstanceBatchMapIterator( mInstanceBatches.begin(), mInstanceBatches.end() ); }
/** Get non-updateable iterator over instance batches for given material
@remarks
Each InstanceBatch pointer may be modified for low level usage (i.e.
setCustomParameter), but there's no synchronization mechanism when
multithreading or creating more instances, that's up to the user.
*/
InstanceBatchIterator getInstanceBatchIterator( const String &materialName ) const
{
InstanceBatchMap::const_iterator it = mInstanceBatches.find( materialName );
return InstanceBatchIterator( it->second.begin(), it->second.end() );
}
};
}
#endif
|