Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/ogre_src_v1-9-0/OgreMain/include/OgreInstanceBatch.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: 17.1 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 __InstanceBatch_H__
29#define __InstanceBatch_H__
30
31#include "OgrePrerequisites.h"
32#include "OgreRenderOperation.h"
33#include "OgreRenderable.h"
34#include "OgreMovableObject.h"
35#include "OgreMesh.h"
36#include "OgreHeaderPrefix.h"
37
38namespace Ogre
39{
40    /** \addtogroup Core
41    *  @{
42    */
43    /** \addtogroup Scene
44    *  @{
45    */
46
47    /** InstanceBatch forms part of the new Instancing system
48        This is an abstract class that must be derived to implement different instancing techniques
49        (@see InstanceManager::InstancingTechnique)
50        OGRE wasn't truly thought for instancing. OGRE assumes that either:
51            a. One MovableObject -> No Renderable
52            b. One MovableObject -> One Renderable
53            c. One MovableObject -> Many Renderable.
54        However, instances work on reverse: Many MovableObject have the same Renderable.
55        <b>Instancing is already difficult to cull by a CPU</b>, but the main drawback from this assumption
56        is that it makes it even harder to take advantage from OGRE's culling capabilities
57        (i.e. @see OctreeSceneManager)
58    @par
59        To workaround this problem, InstanceBatch updates on almost every frame,
60        growing the bounding box to fit all instances that are not being culled individually.
61        This helps by avoiding a huge bbox that may cover the whole scene, which decreases shadow
62        quality considerably (as it is seen as large shadow receiver)
63        Furthermore, if no individual instance is visible, the InstanceBatch switches it's visibility
64        (@see MovableObject::setVisible) to avoid sending this Renderable to the GPU. This happens because
65        even when no individual instance is visible, their merged bounding box may cause OGRE to think
66        the batch is visible (i.e. the camera is looking between object A & B, but A & B aren't visible)
67    @par
68        <b>As it happens with instancing in general, all instanced entities from the same batch will share
69        the same textures and materials</b>
70    @par
71        Each InstanceBatch preallocates a fixed amount of mInstancesPerBatch instances once it's been
72        built (@see build, @see buildFrom).
73        @see createInstancedEntity and @see removeInstancedEntity on how to retrieve those instances
74        remove them from scene.
75        Note that, on GPU side, removing an instance from scene doesn't save GPU cycles on what
76        respects vertex shaders, but saves a little fillrate and pixel shaders; unless all instances
77        are removed, which saves GPU.
78        For more information, @see InstancedEntity
79        For information on how Ogre manages multiple Instance batches, @see InstanceManager
80
81    @remarks
82        Design discussion webpage
83    @author
84        Matias N. Goldberg ("dark_sylinc")
85    @version
86        1.0
87    */
88    class _OgreExport InstanceBatch : public Renderable, public MovableObject
89    {
90    public:
91        typedef vector<InstancedEntity*>::type  InstancedEntityVec;
92        typedef vector<Vector4>::type           CustomParamsVec;
93    protected:
94        RenderOperation     mRenderOperation;
95        size_t              mInstancesPerBatch;
96
97        InstanceManager     *mCreator;
98
99        MaterialPtr         mMaterial;
100
101        MeshPtr             mMeshReference;
102        Mesh::IndexMap const *mIndexToBoneMap;
103
104        //InstancedEntities are all allocated at build time and kept as "unused"
105        //when they're requested, they're removed from there when requested,
106        //and put back again when they're no longer needed
107        //Note each InstancedEntity has a unique ID ranging from [0; mInstancesPerBatch)
108        InstancedEntityVec  mInstancedEntities;
109        InstancedEntityVec  mUnusedEntities;
110
111        ///@see InstanceManager::setNumCustomParams(). Because this may not even be used,
112        ///our implementations keep the params separate from the InstancedEntity to lower
113        ///the memory overhead. They default to Vector4::ZERO
114        CustomParamsVec         mCustomParams;
115
116        /// This bbox contains all (visible) instanced entities
117        AxisAlignedBox      mFullBoundingBox;
118        Real                mBoundingRadius;
119        bool                mBoundsDirty;
120        bool                mBoundsUpdated; //Set to false by derived classes that need it
121        Camera              *mCurrentCamera;
122
123        unsigned short      mMaterialLodIndex;
124
125        bool                mDirtyAnimation; //Set to false at start of each _updateRenderQueue
126
127        /// False if a technique doesn't support skeletal animation
128        bool                mTechnSupportsSkeletal;
129
130        /// Cached distance to last camera for getSquaredViewDepth
131        mutable Real mCachedCameraDist;
132        /// The camera for which the cached distance is valid
133        mutable const Camera *mCachedCamera;
134
135        /// Tells that the list of entity instances with shared transforms has changed
136        bool mTransformSharingDirty;
137
138        /// When true remove the memory of the VertexData we've created because no one else will
139        bool mRemoveOwnVertexData;
140        /// When true remove the memory of the IndexData we've created because no one else will
141        bool mRemoveOwnIndexData;
142
143        virtual void setupVertices( const SubMesh* baseSubMesh ) = 0;
144        virtual void setupIndices( const SubMesh* baseSubMesh ) = 0;
145        virtual void createAllInstancedEntities(void);
146        virtual void deleteAllInstancedEntities(void);
147        virtual void deleteUnusedInstancedEntities(void);
148        /// Creates a new InstancedEntity instance
149        virtual InstancedEntity* generateInstancedEntity(size_t num);
150
151        /** Takes an array of 3x4 matrices and makes it camera relative. Note the second argument
152            takes number of floats in the array, not number of matrices. Assumes mCachedCamera
153            contains the camera which is about to be rendered to.
154        */
155        void makeMatrixCameraRelative3x4( float *mat3x4, size_t numFloats );
156
157        /// Returns false on errors that would prevent building this batch from the given submesh
158        virtual bool checkSubMeshCompatibility( const SubMesh* baseSubMesh );
159
160        void updateVisibility(void);
161
162        /** @see _defragmentBatch */
163        void defragmentBatchNoCull( InstancedEntityVec &usedEntities, CustomParamsVec &usedParams );
164
165        /** @see _defragmentBatch
166            This one takes the entity closest to the minimum corner of the bbox, then starts
167            gathering entities closest to this entity. There might be much better algorithms (i.e.
168            involving space partition), but this one is simple and works well enough
169        */
170        void defragmentBatchDoCull( InstancedEntityVec &usedEntities, CustomParamsVec &usedParams );
171
172    public:
173        InstanceBatch( InstanceManager *creator, MeshPtr &meshReference, const MaterialPtr &material,
174                       size_t instancesPerBatch, const Mesh::IndexMap *indexToBoneMap,
175                       const String &batchName );
176        virtual ~InstanceBatch();
177
178        MeshPtr& _getMeshRef() { return mMeshReference; }
179
180        /** Raises an exception if trying to change it after being built
181        */
182        void _setInstancesPerBatch( size_t instancesPerBatch );
183
184        const Mesh::IndexMap* _getIndexToBoneMap() const { return mIndexToBoneMap; }
185
186        /** Returns true if this technique supports skeletal animation
187        @remarks
188            A virtual function could have been used, but using a simple variable overridden
189            by the derived class is faster than virtual call overhead. And both are clean
190            ways of implementing it.
191        */
192        bool _supportsSkeletalAnimation() const { return mTechnSupportsSkeletal; }
193
194        /** @see InstanceManager::updateDirtyBatches */
195        void _updateBounds(void);
196
197        /** Some techniques have a limit on how many instances can be done.
198            Sometimes even depends on the material being used.
199        @par
200            Note this is a helper function, as such it takes a submesh base to compute
201            the parameters, instead of using the object's own. This allows
202            querying for a technique without requiering to actually build it.
203        @param baseSubMesh The base submesh that will be using to build it.
204        @param flags Flags to pass to the InstanceManager. @see InstanceManagerFlags
205        @return The max instances limit
206        */
207        virtual size_t calculateMaxNumInstances( const SubMesh *baseSubMesh, uint16 flags ) const = 0;
208
209        /** Constructs all the data needed to use this batch, as well as the
210            InstanceEntities. Placed here because in the constructor virtual
211            tables may not have been yet filled.
212        @param baseSubMesh A sub mesh which the instances will be based upon from.
213        @remarks
214            Call this only ONCE. This is done automatically by Ogre::InstanceManager
215            Caller is responsable for freeing buffers in this RenderOperation
216            Buffers inside the RenderOp may be null if the built failed.
217        @return
218            A render operation which is very useful to pass to other InstanceBatches
219            (@see buildFrom) so that they share the same vertex buffers and indices,
220            when possible
221        */
222        virtual RenderOperation build( const SubMesh* baseSubMesh );
223
224        /** Instancing consumes significantly more GPU memory than regular rendering
225            methods. However, multiple batches can share most, if not all, of the
226            vertex & index buffers to save memory.
227            Derived classes are free to overload this method to manipulate what to
228            reference from Render Op.
229            For example, Hardware based instancing uses it's own vertex buffer for the
230            last source binding, but shares the other sources.
231        @param renderOperation The RenderOp to reference.
232        @remarks
233            Caller is responsable for freeing buffers passed as input arguments
234            This function replaces the need to call build()
235        */
236        virtual void buildFrom( const SubMesh *baseSubMesh, const RenderOperation &renderOperation );
237
238        const Ogre::MeshPtr& _getMeshReference(void) const { return mMeshReference; }
239
240        /** @return true if it can not create more InstancedEntities
241            (Num InstancedEntities == mInstancesPerBatch)
242        */
243        bool isBatchFull(void) const { return mUnusedEntities.empty(); }
244
245        /** Returns true if it no instanced entity has been requested or all of them have been removed
246        */
247        bool isBatchUnused(void) const { return mUnusedEntities.size() == mInstancedEntities.size(); }
248
249        /** Fills the input vector with the instances that are currently being used or were requested.
250            Used for defragmentation, @see InstanceManager::defragmentBatches
251        */
252                void getInstancedEntitiesInUse( InstancedEntityVec &outEntities, CustomParamsVec &outParams );
253
254        /** @see InstanceManager::defragmentBatches
255            This function takes InstancedEntities and pushes back all entities it can fit here
256            Extra entities in mUnusedEntities are destroyed
257            (so that used + unused = mInstancedEntities.size())
258        @param optimizeCulling true will call the DoCull version, false the NoCull
259        @param usedEntities Array of InstancedEntities to parent with this batch. Those reparented
260            are removed from this input vector
261        @param usedParams Array of Custom parameters correlated with the InstancedEntities in usedEntities.
262                        They follow the fate of the entities in that vector.
263                @remarks:
264                        This function assumes caller holds data to mInstancedEntities! Otherwise
265                        you can get memory leaks. Don't call this directly if you don't know what you're doing!
266                */
267                void _defragmentBatch( bool optimizeCulling, InstancedEntityVec &usedEntities,
268                                                                CustomParamsVec &usedParams );
269
270                /** @see InstanceManager::_defragmentBatchDiscard
271                        Destroys unused entities and clears the mInstancedEntity container which avoids leaving
272                        dangling pointers from reparented InstancedEntities
273                        Usually called before deleting this pointer. Don't call directly!
274                */
275                void _defragmentBatchDiscard(void);
276
277                /** Called by InstancedEntity(s) to tell us we need to update the bounds
278                        (we touch the SceneNode so the SceneManager aknowledges such change)
279        */
280                virtual void _boundsDirty(void);
281
282                /** Tells this batch to stop updating animations, positions, rotations, and display
283                        all it's active instances. Currently only InstanceBatchHW & InstanceBatchHW_VTF support it.
284                        This option makes the batch behave pretty much like Static Geometry, but with the GPU RAM
285                        memory advantages (less VRAM, less bandwidth) and not LOD support. Very useful for
286                        billboards of trees, repeating vegetation, etc.
287                        @remarks
288                                This function moves a lot of processing time from the CPU to the GPU. If the GPU
289                                is already a bottleneck, you may see a decrease in performance instead!
290                                Call this function again (with bStatic=true) if you've made a change to an
291                                InstancedEntity and wish this change to take effect.
292                                Be sure to call this after you've set all your instances
293                                @see InstanceBatchHW::setStaticAndUpdate
294                */
295                virtual void setStaticAndUpdate( bool bStatic )         {}
296
297                /** Returns true if this batch was set as static. @see setStaticAndUpdate
298                */
299                virtual bool isStatic() const                                           { return false; }
300
301                /** Returns a pointer to a new InstancedEntity ready to use
302                        Note it's actually preallocated, so no memory allocation happens at
303                        this point.
304                        @remarks
305                                Returns NULL if all instances are being used
306        */
307                InstancedEntity* createInstancedEntity();
308
309                /** Removes an InstancedEntity from the scene retrieved with
310                        getNewInstancedEntity, putting back into a queue
311                        @remarks
312                                Throws an exception if the instanced entity wasn't created by this batch
313                                Removed instanced entities save little CPU time, but _not_ GPU
314        */
315                void removeInstancedEntity( InstancedEntity *instancedEntity );
316
317                /** Tells whether world bone matrices need to be calculated.
318                        This does not include bone matrices which are calculated regardless
319        */
320                virtual bool useBoneWorldMatrices() const { return true; }
321
322                /** Tells that the list of entity instances with shared transforms has changed */
323                void _markTransformSharingDirty() { mTransformSharingDirty = true; }
324
325                /** @see InstancedEntity::setCustomParam */
326                void _setCustomParam( InstancedEntity *instancedEntity, unsigned char idx, const Vector4 &newParam );
327
328                /** @see InstancedEntity::getCustomParam */
329                const Vector4& _getCustomParam( InstancedEntity *instancedEntity, unsigned char idx );
330
331                //Renderable overloads
332        /** @copydoc Renderable::getMaterial. */
333                const MaterialPtr& getMaterial(void) const              { return mMaterial; }
334        /** @copydoc Renderable::getRenderOperation. */
335                void getRenderOperation( RenderOperation& op )  { op = mRenderOperation; }
336
337        /** @copydoc Renderable::getSquaredViewDepth. */
338                Real getSquaredViewDepth( const Camera* cam ) const;
339        /** @copydoc Renderable::getLights. */
340        const LightList& getLights( void ) const;
341        /** @copydoc Renderable::getTechnique. */
342                Technique* getTechnique(void) const;
343
344        /** @copydoc MovableObject::getMovableType. */
345                const String& getMovableType(void) const;
346        /** @copydoc MovableObject::_notifyCurrentCamera. */
347                void _notifyCurrentCamera( Camera* cam );
348        /** @copydoc MovableObject::getBoundingBox. */
349                const AxisAlignedBox& getBoundingBox(void) const;
350        /** @copydoc MovableObject::getBoundingRadius. */
351                Real getBoundingRadius(void) const;
352
353                virtual void _updateRenderQueue(RenderQueue* queue);
354                void visitRenderables( Renderable::Visitor* visitor, bool debugRenderables = false );
355
356        // resolve ambiguity of get/setUserAny due to inheriting from Renderable and MovableObject
357        using Renderable::getUserAny;
358        using Renderable::setUserAny;
359        };
360} // namespace Ogre
361
362#include "OgreHeaderSuffix.h"
363
364#endif // __InstanceBatch_H__
Note: See TracBrowser for help on using the repository browser.