/src/ogre/OgreMain/include/OgreStaticGeometry.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | ----------------------------------------------------------------------------- |
3 | | This source file is part of OGRE |
4 | | (Object-oriented Graphics Rendering Engine) |
5 | | For the latest info, see http://www.ogre3d.org/ |
6 | | |
7 | | Copyright (c) 2000-2014 Torus Knot Software Ltd |
8 | | |
9 | | Permission is hereby granted, free of charge, to any person obtaining a copy |
10 | | of this software and associated documentation files (the "Software"), to deal |
11 | | in the Software without restriction, including without limitation the rights |
12 | | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
13 | | copies of the Software, and to permit persons to whom the Software is |
14 | | furnished to do so, subject to the following conditions: |
15 | | |
16 | | The above copyright notice and this permission notice shall be included in |
17 | | all copies or substantial portions of the Software. |
18 | | |
19 | | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
20 | | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
21 | | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
22 | | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
23 | | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
24 | | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
25 | | THE SOFTWARE. |
26 | | ----------------------------------------------------------------------------- |
27 | | */ |
28 | | #ifndef __StaticGeometry_H__ |
29 | | #define __StaticGeometry_H__ |
30 | | |
31 | | #include "OgrePrerequisites.h" |
32 | | #include "OgreMovableObject.h" |
33 | | #include "OgreRenderable.h" |
34 | | #include "OgreMesh.h" |
35 | | #include "OgreHeaderPrefix.h" |
36 | | |
37 | | namespace Ogre { |
38 | | |
39 | | /** \addtogroup Core |
40 | | * @{ |
41 | | */ |
42 | | /** \addtogroup Scene |
43 | | * @{ |
44 | | */ |
45 | | /** Pre-transforms and batches up meshes for efficient use as static |
46 | | geometry in a scene. |
47 | | |
48 | | Modern graphics cards (GPUs) prefer to receive geometry in large |
49 | | batches. It is orders of magnitude faster to render 10 batches |
50 | | of 10,000 triangles than it is to render 10,000 batches of 10 |
51 | | triangles, even though both result in the same number of on-screen |
52 | | triangles. |
53 | | @par |
54 | | Therefore it is important when you are rendering a lot of geometry to |
55 | | batch things up into as few rendering calls as possible. This |
56 | | class allows you to build a batched object from a series of entities |
57 | | in order to benefit from this behaviour. |
58 | | Batching has implications of it's own though: |
59 | | @li Batched geometry cannot be subdivided; that means that the whole |
60 | | group will be displayed, or none of it will. This obivously has |
61 | | culling issues. |
62 | | @li A single world transform must apply to the entire batch. Therefore |
63 | | once you have batched things, you can't move them around relative to |
64 | | each other. That's why this class is most useful when dealing with |
65 | | static geometry (hence the name). In addition, geometry is |
66 | | effectively duplicated, so if you add 3 entities based on the same |
67 | | mesh in different positions, they will use 3 times the geometry |
68 | | space than the movable version (which re-uses the same geometry). |
69 | | So you trade memory and flexibility of movement for pure speed when |
70 | | using this class. |
71 | | @li A single material must apply for each batch. In fact this class |
72 | | allows you to use multiple materials, but you should be aware that |
73 | | internally this means that there is one batch per material. |
74 | | Therefore you won't gain as much benefit from the batching if you |
75 | | use many different materials; try to keep the number down. |
76 | | @par |
77 | | In order to retain some sort of culling, this class will batch up |
78 | | meshes in localised regions. The size and shape of these blocks is |
79 | | controlled by the SceneManager which constructs this object, since it |
80 | | makes sense to batch things up in the most appropriate way given the |
81 | | existing partitioning of the scene. |
82 | | @par |
83 | | The LOD settings of both the Mesh and the Materials used in |
84 | | constructing this static geometry will be respected. This means that |
85 | | if you use meshes/materials which have LOD, batches in the distance |
86 | | will have a lower polygon count or material detail to those in the |
87 | | foreground. Since each mesh might have different LOD distances, during |
88 | | build the furthest distance at each LOD level from all meshes |
89 | | in that region is used. This means all the LOD levels change at the |
90 | | same time, but at the furthest distance of any of them (so quality is |
91 | | not degraded). Be aware that using Mesh LOD in this class will |
92 | | further increase the memory required. Only generated LOD |
93 | | is supported for meshes. |
94 | | @par |
95 | | There are 2 ways you can add geometry to this class; you can add |
96 | | Entity objects directly with predetermined positions, scales and |
97 | | orientations, or you can add an entire SceneNode and it's subtree, |
98 | | including all the objects attached to it. Once you've added everything |
99 | | you need to, you have to call build() the fix the geometry in place. |
100 | | @note |
101 | | This class is not a replacement for world geometry (@see |
102 | | SceneManager::setWorldGeometry). The single most efficient way to |
103 | | render large amounts of static geometry is to use a SceneManager which |
104 | | is specialised for dealing with that particular world structure. |
105 | | However, this class does provide you with a good 'halfway house' |
106 | | between generalised movable geometry (Entity) which works with all |
107 | | SceneManagers but isn't efficient when using very large numbers, and |
108 | | highly specialised world geometry which is extremely fast but not |
109 | | generic and typically requires custom world editors. |
110 | | @par |
111 | | You should not construct instances of this class directly; instead, cal |
112 | | SceneManager::createStaticGeometry, which gives the SceneManager the |
113 | | option of providing you with a specialised version of this class if it |
114 | | wishes, and also handles the memory management for you like other |
115 | | classes. |
116 | | @note |
117 | | Warning: this class only works with indexed triangle lists at the moment, |
118 | | do not pass it triangle strips, fans or lines / points, or unindexed geometry. |
119 | | */ |
120 | | class _OgreExport StaticGeometry : public BatchedGeometryAlloc |
121 | | { |
122 | | public: |
123 | | /** Struct holding geometry optimised per SubMesh / LOD level, ready |
124 | | for copying to instances. |
125 | | |
126 | | Since we're going to be duplicating geometry lots of times, it's |
127 | | far more important that we don't have redundant vertex data. If a |
128 | | SubMesh uses shared geometry, or we're looking at a lower LOD, not |
129 | | all the vertices are being referenced by faces on that submesh. |
130 | | Therefore to duplicate them, potentially hundreds or even thousands |
131 | | of times, would be extremely wasteful. Therefore, if a SubMesh at |
132 | | a given LOD has wastage, we create an optimised version of it's |
133 | | geometry which is ready for copying with no wastage. |
134 | | */ |
135 | | class _OgrePrivate OptimisedSubMeshGeometry : public BatchedGeometryAlloc |
136 | | { |
137 | | public: |
138 | 0 | OptimisedSubMeshGeometry() :vertexData(0), indexData(0) {} |
139 | | ~OptimisedSubMeshGeometry() |
140 | 0 | { |
141 | 0 | OGRE_DELETE vertexData; |
142 | 0 | OGRE_DELETE indexData; |
143 | 0 | } |
144 | | VertexData *vertexData; |
145 | | IndexData *indexData; |
146 | | }; |
147 | | typedef std::list<OptimisedSubMeshGeometry*> OptimisedSubMeshGeometryList; |
148 | | /// Saved link between SubMesh at a LOD and vertex/index data |
149 | | /// May point to original or optimised geometry |
150 | | struct SubMeshLodGeometryLink |
151 | | { |
152 | | VertexData* vertexData; |
153 | | IndexData* indexData; |
154 | | }; |
155 | | typedef std::vector<SubMeshLodGeometryLink> SubMeshLodGeometryLinkList; |
156 | | typedef std::map<SubMesh*, SubMeshLodGeometryLinkList*> SubMeshGeometryLookup; |
157 | | /// Structure recording a queued submesh for the build |
158 | | struct QueuedSubMesh : public BatchedGeometryAlloc |
159 | | { |
160 | | SubMesh* submesh; |
161 | | MaterialPtr material; |
162 | | /// Link to LOD list of geometry, potentially optimised |
163 | | SubMeshLodGeometryLinkList* geometryLodList; |
164 | | Vector3 position; |
165 | | Quaternion orientation; |
166 | | Vector3 scale; |
167 | | /// Pre-transformed world AABB |
168 | | AxisAlignedBox worldBounds; |
169 | | }; |
170 | | typedef std::vector<QueuedSubMesh*> QueuedSubMeshList; |
171 | | /// Structure recording a queued geometry for low level builds |
172 | | struct QueuedGeometry : public BatchedGeometryAlloc |
173 | | { |
174 | | SubMeshLodGeometryLink* geometry; |
175 | | Vector3 position; |
176 | | Quaternion orientation; |
177 | | Vector3 scale; |
178 | | }; |
179 | | typedef std::vector<QueuedGeometry*> QueuedGeometryList; |
180 | | |
181 | | // forward declarations |
182 | | class LODBucket; |
183 | | class MaterialBucket; |
184 | | class Region; |
185 | | |
186 | | /** A GeometryBucket is a the lowest level bucket where geometry with |
187 | | the same vertex & index format is stored. It also acts as the |
188 | | renderable. |
189 | | */ |
190 | | class _OgreExport GeometryBucket : public Renderable, public BatchedGeometryAlloc |
191 | | { |
192 | | /// Geometry which has been queued up pre-build (not for deallocation) |
193 | | QueuedGeometryList mQueuedGeometry; |
194 | | /// Pointer to parent bucket |
195 | | MaterialBucket* mParent; |
196 | | /// Vertex information, includes current number of vertices |
197 | | /// committed to be a part of this bucket |
198 | | VertexData* mVertexData; |
199 | | /// Index information, includes index type which limits the max |
200 | | /// number of vertices which are allowed in one bucket |
201 | | IndexData* mIndexData; |
202 | | /// Maximum vertex indexable |
203 | | size_t mMaxVertexIndex; |
204 | | public: |
205 | | GeometryBucket(MaterialBucket* parent, const VertexData* vData, const IndexData* iData); |
206 | | virtual ~GeometryBucket(); |
207 | 0 | MaterialBucket* getParent(void) { return mParent; } |
208 | | /// Get the vertex data for this geometry |
209 | 0 | const VertexData* getVertexData(void) const { return mVertexData; } |
210 | | /// Get the index data for this geometry |
211 | 0 | const IndexData* getIndexData(void) const { return mIndexData; } |
212 | | /// @copydoc Renderable::getMaterial |
213 | | const MaterialPtr& getMaterial(void) const override; |
214 | | Technique* getTechnique(void) const override; |
215 | | void getRenderOperation(RenderOperation& op) override; |
216 | | void getWorldTransforms(Matrix4* xform) const override; |
217 | | Real getSquaredViewDepth(const Camera* cam) const override; |
218 | | const LightList& getLights(void) const override; |
219 | | bool getCastsShadows(void) const override; |
220 | | |
221 | | /** Try to assign geometry to this bucket. |
222 | | @return false if there is no room left in this bucket |
223 | | */ |
224 | | bool assign(QueuedGeometry* qsm); |
225 | | /// Build |
226 | | void build(bool stencilShadows); |
227 | | /// Dump contents for diagnostics |
228 | | _OgreExport friend std::ostream& operator<<(std::ostream& o, const GeometryBucket& b); |
229 | | }; |
230 | | /** A MaterialBucket is a collection of smaller buckets with the same |
231 | | Material (and implicitly the same LOD). */ |
232 | | class _OgreExport MaterialBucket : public BatchedGeometryAlloc |
233 | | { |
234 | | public: |
235 | | /// list of Geometry Buckets in this region |
236 | | typedef std::vector<GeometryBucket*> GeometryBucketList; |
237 | | private: |
238 | | /// Pointer to parent LODBucket |
239 | | LODBucket* mParent; |
240 | | /// Pointer to material being used |
241 | | MaterialPtr mMaterial; |
242 | | /// Active technique |
243 | | Technique* mTechnique; |
244 | | |
245 | | /// list of Geometry Buckets in this region |
246 | | GeometryBucketList mGeometryBucketList; |
247 | | // index to current Geometry Buckets for a given geometry format |
248 | | typedef std::map<uint32, GeometryBucket*> CurrentGeometryMap; |
249 | | CurrentGeometryMap mCurrentGeometryMap; |
250 | | |
251 | | public: |
252 | | MaterialBucket(LODBucket* parent, const MaterialPtr& material); |
253 | | virtual ~MaterialBucket(); |
254 | 0 | LODBucket* getParent(void) { return mParent; } |
255 | | /// Get the material name |
256 | 0 | const String& getMaterialName(void) const { return mMaterial->getName(); } |
257 | | /// Assign geometry to this bucket |
258 | | void assign(QueuedGeometry* qsm); |
259 | | /// Build |
260 | | void build(bool stencilShadows); |
261 | | /// Add children to the render queue |
262 | | void addRenderables(RenderQueue* queue, uint8 group, |
263 | | Real lodValue); |
264 | | /// Get the material for this bucket |
265 | 0 | const MaterialPtr& getMaterial(void) const { return mMaterial; } |
266 | | /// Override Material without changing the partitioning. For advanced use only. |
267 | | void _setMaterial(const MaterialPtr& material); |
268 | | /// Iterator over geometry |
269 | | typedef VectorIterator<GeometryBucketList> GeometryIterator; |
270 | | /// Get a list of the contained geometry |
271 | 0 | const GeometryBucketList& getGeometryList() const { return mGeometryBucketList; } |
272 | | /// @deprecated use getGeometryList() |
273 | | OGRE_DEPRECATED GeometryIterator getGeometryIterator(void); |
274 | | /// Get the current Technique |
275 | 0 | Technique* getCurrentTechnique(void) const { return mTechnique; } |
276 | | /// Dump contents for diagnostics |
277 | | _OgreExport friend std::ostream& operator<<(std::ostream& o, const MaterialBucket& b); |
278 | | void visitRenderables(Renderable::Visitor* visitor, bool debugRenderables); |
279 | | }; |
280 | | /** A LODBucket is a collection of smaller buckets with the same LOD. |
281 | | |
282 | | LOD refers to Mesh LOD here. Material LOD can change separately |
283 | | at the next bucket down from this. |
284 | | */ |
285 | | class _OgreExport LODBucket : public BatchedGeometryAlloc |
286 | | { |
287 | | public: |
288 | | /// Lookup of Material Buckets in this region |
289 | | typedef std::map<String, MaterialBucket*> MaterialBucketMap; |
290 | | private: |
291 | | /// Pointer to parent region |
292 | | Region* mParent; |
293 | | /// LOD level (0 == full LOD) |
294 | | unsigned short mLod; |
295 | | /// LOD value at which this LOD starts to apply (squared) |
296 | | Real mLodValue; |
297 | | /// Lookup of Material Buckets in this region |
298 | | MaterialBucketMap mMaterialBucketMap; |
299 | | /// Geometry queued for a single LOD (deallocated here) |
300 | | QueuedGeometryList mQueuedGeometryList; |
301 | | /// Edge list, used if stencil shadow casting is enabled |
302 | | EdgeData* mEdgeList; |
303 | | /// Is a vertex program in use somewhere in this group? |
304 | | bool mVertexProgramInUse; |
305 | | /// List of shadow renderables |
306 | | ShadowCaster::ShadowRenderableList mShadowRenderables; |
307 | | public: |
308 | | LODBucket(Region* parent, unsigned short lod, Real lodValue); |
309 | | virtual ~LODBucket(); |
310 | 0 | Region* getParent(void) { return mParent; } |
311 | | /// Get the LOD index |
312 | 0 | ushort getLod(void) const { return mLod; } |
313 | | /// Get the LOD value |
314 | 0 | Real getLodValue(void) const { return mLodValue; } |
315 | | /// Assign a queued submesh to this bucket, using specified mesh LOD |
316 | | void assign(QueuedSubMesh* qsm, ushort atLod); |
317 | | /// Build |
318 | | void build(bool stencilShadows); |
319 | | /// Add children to the render queue |
320 | | void addRenderables(RenderQueue* queue, uint8 group, |
321 | | Real lodValue); |
322 | | /// Iterator over the materials in this LOD |
323 | | typedef MapIterator<MaterialBucketMap> MaterialIterator; |
324 | | /// Get an iterator over the materials in this LOD |
325 | 0 | const MaterialBucketMap& getMaterialBuckets() const { return mMaterialBucketMap; } |
326 | | /// @deprecated use getMaterialBuckets() |
327 | | OGRE_DEPRECATED MaterialIterator getMaterialIterator(void); |
328 | | /// Dump contents for diagnostics |
329 | | _OgreExport friend std::ostream& operator<<(std::ostream& o, const LODBucket& b); |
330 | | void visitRenderables(Renderable::Visitor* visitor, bool debugRenderables); |
331 | 0 | EdgeData* getEdgeList() const { return mEdgeList; } |
332 | 0 | ShadowCaster::ShadowRenderableList& getShadowRenderableList() { return mShadowRenderables; } |
333 | 0 | bool isVertexProgramInUse() const { return mVertexProgramInUse; } |
334 | | void updateShadowRenderables(const Vector4& lightPos, const HardwareIndexBufferPtr& indexBuffer, |
335 | | Real extrusionDistance, int flags = 0); |
336 | | }; |
337 | | /** The details of a topological region which is the highest level of |
338 | | partitioning for this class. |
339 | | |
340 | | The size & shape of regions entirely depends on the SceneManager |
341 | | specific implementation. It is a MovableObject since it will be |
342 | | attached to a node based on the local centre - in practice it |
343 | | won't actually move (although in theory it could). |
344 | | */ |
345 | | class _OgreExport Region : public MovableObject |
346 | | { |
347 | | friend class MaterialBucket; |
348 | | friend class GeometryBucket; |
349 | | public: |
350 | | /// list of LOD Buckets in this region |
351 | | typedef std::vector<LODBucket*> LODBucketList; |
352 | | private: |
353 | | /// Parent static geometry |
354 | | StaticGeometry* mParent; |
355 | | /// Local list of queued meshes (not used for deallocation) |
356 | | QueuedSubMeshList mQueuedSubMeshes; |
357 | | /// Unique identifier for the region |
358 | | uint32 mRegionID; |
359 | | /// Center of the region |
360 | | Vector3 mCentre; |
361 | | /// LOD values as built up - use the max at each level |
362 | | Mesh::LodValueList mLodValues; |
363 | | /// Local AABB relative to region centre |
364 | | AxisAlignedBox mAABB; |
365 | | /// Local bounding radius |
366 | | Real mBoundingRadius; |
367 | | /// The current LOD level, as determined from the last camera |
368 | | ushort mCurrentLod; |
369 | | /// Current LOD value, passed on to do material LOD later |
370 | | Real mLodValue; |
371 | | /// List of LOD buckets |
372 | | LODBucketList mLodBucketList; |
373 | | /// List of lights for this region |
374 | | mutable LightList mLightList; |
375 | | /// LOD strategy reference |
376 | | const LodStrategy *mLodStrategy; |
377 | | /// Current camera |
378 | | Camera *mCamera; |
379 | | /// Cached squared view depth value to avoid recalculation by GeometryBucket |
380 | | Real mSquaredViewDepth; |
381 | | |
382 | | public: |
383 | | Region(StaticGeometry* parent, const String& name, SceneManager* mgr, |
384 | | uint32 regionID, const Vector3& centre); |
385 | | virtual ~Region(); |
386 | | // more fields can be added in subclasses |
387 | 0 | StaticGeometry* getParent(void) const { return mParent;} |
388 | | /// Assign a queued mesh to this region, read for final build |
389 | | void assign(QueuedSubMesh* qmesh); |
390 | | /// Build this region |
391 | | void build(bool stencilShadows); |
392 | | /// Get the region ID of this region |
393 | 0 | uint32 getID(void) const { return mRegionID; } |
394 | | /// Get the centre point of the region |
395 | 0 | const Vector3& getCentre(void) const { return mCentre; } |
396 | | const String& getMovableType(void) const override; |
397 | | void _notifyCurrentCamera(Camera* cam) override; |
398 | | const AxisAlignedBox& getBoundingBox(void) const override; |
399 | | Real getBoundingRadius(void) const override; |
400 | | void _updateRenderQueue(RenderQueue* queue) override; |
401 | | /// @copydoc MovableObject::visitRenderables |
402 | | void visitRenderables(Renderable::Visitor* visitor, |
403 | | bool debugRenderables = false) override; |
404 | | bool isVisible(void) const override; |
405 | | uint32 getTypeFlags(void) const override; |
406 | | |
407 | | typedef VectorIterator<LODBucketList> LODIterator; |
408 | | /// @deprecated use getLODBuckets() |
409 | | OGRE_DEPRECATED LODIterator getLODIterator(void); |
410 | | /// Get an list of the LODs in this region |
411 | 0 | const LODBucketList& getLODBuckets() const { return mLodBucketList; } |
412 | | const ShadowRenderableList& |
413 | | getShadowVolumeRenderableList(const Light* light, const HardwareIndexBufferPtr& indexBuffer, |
414 | | size_t& indexBufferUsedSize, float extrusionDistance, |
415 | | int flags = 0) override; |
416 | | EdgeData* getEdgeList(void) override; |
417 | | |
418 | | void _releaseManualHardwareResources() override; |
419 | | void _restoreManualHardwareResources() override; |
420 | | |
421 | | /// Dump contents for diagnostics |
422 | | _OgreExport friend std::ostream& operator<<(std::ostream& o, const Region& r); |
423 | | |
424 | | }; |
425 | | /** Indexed region map based on packed x/y/z region index, 10 bits for |
426 | | each axis. |
427 | | |
428 | | Regions are indexed 0-1023 in all axes, where for example region |
429 | | 0 in the x axis begins at mOrigin.x + (mRegionDimensions.x * -512), |
430 | | and region 1023 ends at mOrigin + (mRegionDimensions.x * 512). |
431 | | */ |
432 | | typedef std::map<uint32, Region*> RegionMap; |
433 | | private: |
434 | | // General state & settings |
435 | | SceneManager* mOwner; |
436 | | String mName; |
437 | | Real mUpperDistance; |
438 | | Real mSquaredUpperDistance; |
439 | | bool mCastShadows; |
440 | | Vector3 mRegionDimensions; |
441 | | Vector3 mHalfRegionDimensions; |
442 | | Vector3 mOrigin; |
443 | | bool mVisible; |
444 | | /// The render queue to use when rendering this object |
445 | | uint8 mRenderQueueID; |
446 | | /// Flags whether the RenderQueue's default should be used. |
447 | | bool mRenderQueueIDSet; |
448 | | /// Stores the visibility flags for the regions |
449 | | uint32 mVisibilityFlags; |
450 | | |
451 | | QueuedSubMeshList mQueuedSubMeshes; |
452 | | |
453 | | /// List of geometry which has been optimised for SubMesh use |
454 | | /// This is the primary storage used for cleaning up later |
455 | | OptimisedSubMeshGeometryList mOptimisedSubMeshGeometryList; |
456 | | |
457 | | /** Cached links from SubMeshes to (potentially optimised) geometry |
458 | | This is not used for deletion since the lookup may reference |
459 | | original vertex data |
460 | | */ |
461 | | SubMeshGeometryLookup mSubMeshGeometryLookup; |
462 | | |
463 | | /// Map of regions |
464 | | RegionMap mRegionMap; |
465 | | |
466 | | /** Virtual method for getting a region most suitable for the |
467 | | passed in bounds. Can be overridden by subclasses. |
468 | | */ |
469 | | virtual Region* getRegion(const AxisAlignedBox& bounds, bool autoCreate); |
470 | | /** Get the region within which a point lies */ |
471 | | virtual Region* getRegion(const Vector3& point, bool autoCreate); |
472 | | /** Get the region using indexes */ |
473 | | virtual Region* getRegion(ushort x, ushort y, ushort z, bool autoCreate); |
474 | | /** Get the region using a packed index, returns null if it doesn't exist. */ |
475 | | virtual Region* getRegion(uint32 index); |
476 | | /** Get the region indexes for a point. |
477 | | */ |
478 | | virtual void getRegionIndexes(const Vector3& point, |
479 | | ushort& x, ushort& y, ushort& z); |
480 | | /** Pack 3 indexes into a single index value |
481 | | */ |
482 | | virtual uint32 packIndex(ushort x, ushort y, ushort z); |
483 | | /** Get the volume intersection for an indexed region with some bounds. |
484 | | */ |
485 | | virtual Real getVolumeIntersection(const AxisAlignedBox& box, |
486 | | ushort x, ushort y, ushort z); |
487 | | /** Get the bounds of an indexed region. |
488 | | */ |
489 | | virtual AxisAlignedBox getRegionBounds(ushort x, ushort y, ushort z); |
490 | | /** Get the centre of an indexed region. |
491 | | */ |
492 | | virtual Vector3 getRegionCentre(ushort x, ushort y, ushort z); |
493 | | /** Calculate world bounds from a set of vertex data. */ |
494 | | virtual AxisAlignedBox calculateBounds(VertexData* vertexData, |
495 | | const Vector3& position, const Quaternion& orientation, |
496 | | const Vector3& scale); |
497 | | /** Look up or calculate the geometry data to use for this SubMesh */ |
498 | | SubMeshLodGeometryLinkList* determineGeometry(SubMesh* sm); |
499 | | /** Split some shared geometry into dedicated geometry. */ |
500 | | void splitGeometry(VertexData* vd, IndexData* id, |
501 | | SubMeshLodGeometryLink* targetGeomLink); |
502 | | |
503 | | typedef std::map<size_t, size_t> IndexRemap; |
504 | | /** Method for figuring out which vertices are used by an index buffer |
505 | | and calculating a remap lookup for a vertex buffer just containing |
506 | | those vertices. |
507 | | */ |
508 | | template <typename T> |
509 | | void buildIndexRemap(T* pBuffer, size_t numIndexes, IndexRemap& remap) |
510 | 0 | { |
511 | 0 | remap.clear(); |
512 | 0 | for (size_t i = 0; i < numIndexes; ++i) |
513 | 0 | { |
514 | | // use insert since duplicates are silently discarded |
515 | 0 | remap.emplace(*pBuffer++, remap.size()); |
516 | | // this will have mapped oldindex -> new index IF oldindex |
517 | | // wasn't already there |
518 | 0 | } |
519 | 0 | } Unexecuted instantiation: void Ogre::StaticGeometry::buildIndexRemap<unsigned int>(unsigned int*, unsigned long, std::__1::map<unsigned long, unsigned long, std::__1::less<unsigned long>, std::__1::allocator<std::__1::pair<unsigned long const, unsigned long> > >&) Unexecuted instantiation: void Ogre::StaticGeometry::buildIndexRemap<unsigned short>(unsigned short*, unsigned long, std::__1::map<unsigned long, unsigned long, std::__1::less<unsigned long>, std::__1::allocator<std::__1::pair<unsigned long const, unsigned long> > >&) |
520 | | /** Method for altering indexes based on a remap. */ |
521 | | template <typename T> |
522 | | void remapIndexes(T* src, T* dst, const IndexRemap& remap, |
523 | | size_t numIndexes) |
524 | 0 | { |
525 | 0 | for (size_t i = 0; i < numIndexes; ++i) |
526 | 0 | { |
527 | | // look up original and map to target |
528 | 0 | IndexRemap::const_iterator ix = remap.find(*src++); |
529 | 0 | assert(ix != remap.end()); |
530 | 0 | *dst++ = static_cast<T>(ix->second); |
531 | 0 | } |
532 | 0 | } Unexecuted instantiation: void Ogre::StaticGeometry::remapIndexes<unsigned int>(unsigned int*, unsigned int*, std::__1::map<unsigned long, unsigned long, std::__1::less<unsigned long>, std::__1::allocator<std::__1::pair<unsigned long const, unsigned long> > > const&, unsigned long) Unexecuted instantiation: void Ogre::StaticGeometry::remapIndexes<unsigned short>(unsigned short*, unsigned short*, std::__1::map<unsigned long, unsigned long, std::__1::less<unsigned long>, std::__1::allocator<std::__1::pair<unsigned long const, unsigned long> > > const&, unsigned long) |
533 | | |
534 | | public: |
535 | | /// Constructor; do not use directly (@see SceneManager::createStaticGeometry) |
536 | | StaticGeometry(SceneManager* owner, const String& name); |
537 | | /// Destructor |
538 | | virtual ~StaticGeometry(); |
539 | | |
540 | | /// Get the name of this object |
541 | 0 | const String& getName(void) const { return mName; } |
542 | | /** Adds an Entity to the static geometry. |
543 | | |
544 | | This method takes an existing Entity and adds its details to the |
545 | | list of elements to include when building. Note that the Entity |
546 | | itself is not copied or referenced in this method; an Entity is |
547 | | passed simply so that you can change the materials of attached |
548 | | SubEntity objects if you want. You can add the same Entity |
549 | | instance multiple times with different material settings |
550 | | completely safely, and destroy the Entity before destroying |
551 | | this StaticGeometry if you like. The Entity passed in is simply |
552 | | used as a definition. |
553 | | @note Must be called before 'build'. |
554 | | @param ent The Entity to use as a definition (the Mesh and Materials |
555 | | referenced will be recorded for the build call). |
556 | | @param position The world position at which to add this Entity |
557 | | @param orientation The world orientation at which to add this Entity |
558 | | @param scale The scale at which to add this entity |
559 | | */ |
560 | | virtual void addEntity(Entity* ent, const Vector3& position, |
561 | | const Quaternion& orientation = Quaternion::IDENTITY, |
562 | | const Vector3& scale = Vector3::UNIT_SCALE); |
563 | | |
564 | | /** Adds all the Entity objects attached to a SceneNode and all it's |
565 | | children to the static geometry. |
566 | | |
567 | | This method performs just like addEntity, except it adds all the |
568 | | entities attached to an entire sub-tree to the geometry. |
569 | | The position / orientation / scale parameters are taken from the |
570 | | node structure instead of being specified manually. |
571 | | @note |
572 | | The SceneNode you pass in will not be automatically detached from |
573 | | it's parent, so if you have this node already attached to the scene |
574 | | graph, you will need to remove it if you wish to avoid the overhead |
575 | | of rendering <i>both</i> the original objects and their new static |
576 | | versions! We don't do this for you in case you are preparing this |
577 | | in advance and so don't want the originals detached yet. |
578 | | @note Must be called before 'build'. |
579 | | @param node Pointer to the node to use to provide a set of Entity |
580 | | templates |
581 | | */ |
582 | | virtual void addSceneNode(const SceneNode* node); |
583 | | |
584 | | /** Build the geometry. |
585 | | |
586 | | Based on all the entities which have been added, and the batching |
587 | | options which have been set, this method constructs the batched |
588 | | geometry structures required. The batches are added to the scene |
589 | | and will be rendered unless you specifically hide them. |
590 | | @note |
591 | | Once you have called this method, you can no longer add any more |
592 | | entities. |
593 | | */ |
594 | | virtual void build(void); |
595 | | |
596 | | /** Destroys all the built geometry state (reverse of build). |
597 | | |
598 | | You can call build() again after this and it will pick up all the |
599 | | same entities / nodes you queued last time. |
600 | | */ |
601 | | void destroy(void); |
602 | | |
603 | | /** Clears any of the entities / nodes added to this geometry and |
604 | | destroys anything which has already been built. |
605 | | */ |
606 | | void reset(void); |
607 | | |
608 | | /** Sets the distance at which batches are no longer rendered. |
609 | | |
610 | | This lets you turn off batches at a given distance. This can be |
611 | | useful for things like detail meshes (grass, foliage etc) and could |
612 | | be combined with a shader which fades the geometry out beforehand |
613 | | to lessen the effect. |
614 | | @param dist Distance beyond which the batches will not be rendered |
615 | | (the default is 0, which means batches are always rendered). |
616 | | */ |
617 | 0 | virtual void setRenderingDistance(Real dist) { |
618 | 0 | mUpperDistance = dist; |
619 | 0 | mSquaredUpperDistance = mUpperDistance * mUpperDistance; |
620 | 0 | } |
621 | | |
622 | | /** Gets the distance at which batches are no longer rendered. */ |
623 | 0 | virtual Real getRenderingDistance(void) const { return mUpperDistance; } |
624 | | |
625 | | /** Gets the squared distance at which batches are no longer rendered. */ |
626 | | virtual Real getSquaredRenderingDistance(void) const |
627 | 0 | { return mSquaredUpperDistance; } |
628 | | |
629 | | /** Hides or shows all the batches. */ |
630 | | virtual void setVisible(bool visible); |
631 | | |
632 | | /** Are the batches visible? */ |
633 | 0 | virtual bool isVisible(void) const { return mVisible; } |
634 | | |
635 | | /** Sets whether this geometry should cast shadows. |
636 | | |
637 | | No matter what the settings on the original entities, |
638 | | the StaticGeometry class defaults to not casting shadows. |
639 | | This is because, being static, unless you have moving lights |
640 | | you'd be better to use precalculated shadows of some sort. |
641 | | However, if you need them, you can enable them using this |
642 | | method. If the SceneManager is set up to use stencil shadows, |
643 | | edge lists will be copied from the underlying meshes on build. |
644 | | It is essential that all meshes support stencil shadows in this |
645 | | case. |
646 | | @note If you intend to use stencil shadows, you must set this to |
647 | | true before calling 'build' as well as making sure you set the |
648 | | scene's shadow type (that should always be the first thing you do |
649 | | anyway). You can turn shadows off temporarily but they can never |
650 | | be turned on if they were not at the time of the build. |
651 | | */ |
652 | | virtual void setCastShadows(bool castShadows); |
653 | | /// Will the geometry from this object cast shadows? |
654 | 0 | virtual bool getCastShadows(void) { return mCastShadows; } |
655 | | |
656 | | /** Sets the size of a single region of geometry. |
657 | | |
658 | | This method allows you to configure the physical world size of |
659 | | each region, so you can balance culling against batch size. Entities |
660 | | will be fitted within the batch they most closely fit, and the |
661 | | eventual bounds of each batch may well be slightly larger than this |
662 | | if they overlap a little. The default is Vector3(1000, 1000, 1000). |
663 | | @note Must be called before 'build'. |
664 | | @param size Vector3 expressing the 3D size of each region. |
665 | | */ |
666 | 0 | virtual void setRegionDimensions(const Vector3& size) { |
667 | 0 | mRegionDimensions = size; |
668 | 0 | mHalfRegionDimensions = size * 0.5; |
669 | 0 | } |
670 | | /** Gets the size of a single batch of geometry. */ |
671 | 0 | virtual const Vector3& getRegionDimensions(void) const { return mRegionDimensions; } |
672 | | /** Sets the origin of the geometry. |
673 | | |
674 | | This method allows you to configure the world centre of the geometry, |
675 | | thus the place which all regions surround. You probably don't need |
676 | | to mess with this unless you have a seriously large world, since the |
677 | | default set up can handle an area 1024 * mRegionDimensions, and |
678 | | the sparseness of population is no issue when it comes to rendering. |
679 | | The default is Vector3(0,0,0). |
680 | | @note Must be called before 'build'. |
681 | | @param origin Vector3 expressing the 3D origin of the geometry. |
682 | | */ |
683 | 0 | virtual void setOrigin(const Vector3& origin) { mOrigin = origin; } |
684 | | /** Gets the origin of this geometry. */ |
685 | 0 | virtual const Vector3& getOrigin(void) const { return mOrigin; } |
686 | | |
687 | | /// Sets the visibility flags of all the regions at once |
688 | | void setVisibilityFlags(uint32 flags); |
689 | | /// Returns the visibility flags of the regions |
690 | | uint32 getVisibilityFlags() const; |
691 | | |
692 | | /** Sets the render queue group this object will be rendered through. |
693 | | |
694 | | Render queues are grouped to allow you to more tightly control the ordering |
695 | | of rendered objects. If you do not call this method, all objects default |
696 | | to the default queue (RenderQueue::getDefaultQueueGroup), which is fine for |
697 | | most objects. You may want to alter this if you want to perform more complex |
698 | | rendering. |
699 | | @par |
700 | | See RenderQueue for more details. |
701 | | @param queueID Enumerated value of the queue group to use. |
702 | | */ |
703 | | virtual void setRenderQueueGroup(uint8 queueID); |
704 | | |
705 | | /** Gets the queue group for this entity, see setRenderQueueGroup for full details. */ |
706 | | virtual uint8 getRenderQueueGroup(void) const; |
707 | | /// @copydoc MovableObject::visitRenderables |
708 | | void visitRenderables(Renderable::Visitor* visitor, |
709 | | bool debugRenderables = false); |
710 | | |
711 | | /// Iterator for iterating over contained regions |
712 | | typedef MapIterator<RegionMap> RegionIterator; |
713 | | /// Get an list of the regions in this geometry |
714 | 0 | const RegionMap& getRegions() const { return mRegionMap; } |
715 | | /// @deprecated use getRegions() |
716 | | OGRE_DEPRECATED RegionIterator getRegionIterator(void); |
717 | | |
718 | | /** Dump the contents of this StaticGeometry for diagnostic |
719 | | purposes. |
720 | | */ |
721 | | _OgreExport friend std::ostream& operator<<(std::ostream& o, const StaticGeometry& g); |
722 | | }; |
723 | | /** @} */ |
724 | | /** @} */ |
725 | | |
726 | | } |
727 | | |
728 | | #include "OgreHeaderSuffix.h" |
729 | | |
730 | | #endif |
731 | | |