Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/ogre_src_v1-9-0/OgreMain/include/OgreInstanceManager.h @ 148

Last change on this file since 148 was 148, checked in by patricwi, 6 years ago

Added new dependencies for ogre1.9 and cegui0.8

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