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 
29 #ifndef __Ogre_TerrainQuadTreeNode_H__
30 #define __Ogre_TerrainQuadTreeNode_H__
31 
32 #include "OgreTerrainPrerequisites.h"
33 #include "OgreCommon.h"
34 #include "OgreMovableObject.h"
35 #include "OgreRenderable.h"
36 
37 namespace Ogre
38 {
39     /** \addtogroup Optional
40     *  @{
41     */
42     /** \addtogroup Terrain
43     *  Some details on the terrain component
44     *  @{
45     */
46 
47 
48     /** A node in a quad tree used to store a patch of terrain.
49     @remarks
50         <b>Algorithm overview:</b>
51     @par
52         Our goal is to perform traditional chunked LOD with geomorphing. But,
53         instead of just dividing the terrain into tiles, we will divide them into
54         a hierarchy of tiles, a quadtree, where any level of the quadtree can
55         be a rendered tile (to the exclusion of its children). The idea is to
56         collect together children into a larger batch with their siblings as LOD
57         decreases, to improve performance.
58     @par
59         The minBatchSize and maxBatchSize parameters on Terrain a key to
60         defining this behaviour. Both values are expressed in vertices down one axis.
61         maxBatchSize determines the number of tiles on one side of the terrain,
62         which is numTiles = (terrainSize-1) / (maxBatchSize-1). This in turn determines the depth
63         of the quad tree, which is sqrt(numTiles). The minBatchSize determines
64         the 'floor' of how low the number of vertices can go in a tile before it
65         has to be grouped together with its siblings to drop any lower. We also do not group
66         a tile with its siblings unless all of them are at this minimum batch size,
67         rather than trying to group them when they all end up on the same 'middle' LOD;
68         this is for several reasons; firstly, tiles hitting the same 'middle' LOD is
69         less likely and more transient if they have different levels of 'roughness',
70         and secondly since we're sharing a vertex / index pool between all tiles,
71         only grouping at the min level means that the number of combinations of
72         buffer sizes for any one tile is greatly simplified, making it easier to
73         pool data. To be more specific, any tile / quadtree node can only have
74         log2(maxBatchSize-1) - log2(minBatchSize-1) + 1 LOD levels (and if you set them
75         to the same value, LOD can only change by going up/down the quadtree).
76         The numbers of vertices / indices in each of these levels is constant for
77         the same (relative) LOD index no matter where you are in the tree, therefore
78         buffers can potentially be reused more easily.
79     */
80     class _OgreTerrainExport TerrainQuadTreeNode : public TerrainAlloc
81     {
82     public:
83         /** Constructor.
84         @param terrain The ultimate parent terrain
85         @param parent Optional parent node (in which case xoff, yoff are 0 and size must be entire terrain)
86         @param xoff, yoff Offsets from the start of the terrain data in 2D
87         @param size The size of the node in vertices at the highest LOD
88         @param lod The base LOD level
89         @param depth The depth that this node is at in the tree (or convenience)
90         @param quadrant The index of the quadrant (0, 1, 2, 3)
91         */
92         TerrainQuadTreeNode(Terrain* terrain, TerrainQuadTreeNode* parent,
93             uint16 xoff, uint16 yoff, uint16 size, uint16 lod, uint16 depth, uint16 quadrant);
94         virtual ~TerrainQuadTreeNode();
95 
96         /// Get the horizontal offset into the main terrain data of this node
getXOffset()97         uint16 getXOffset() const { return mOffsetX; }
98         /// Get the vertical offset into the main terrain data of this node
getYOffset()99         uint16 getYOffset() const { return mOffsetY; }
100         /// Is this a leaf node (no children)
101         bool isLeaf() const;
102         /// Get the base LOD level this node starts at (the highest LOD it handles)
getBaseLod()103         uint16 getBaseLod() const { return mBaseLod; }
104         /// Get the number of LOD levels this node can represent itself (only > 1 for leaf nodes)
105         uint16 getLodCount() const;
106         /// Get child node
107         TerrainQuadTreeNode* getChild(unsigned short child) const;
108         /// Get parent node
109         TerrainQuadTreeNode* getParent() const;
110         /// Get ultimate parent terrain
111         Terrain* getTerrain() const;
112 
113         /// Prepare node and children (perform CPU tasks, may be background thread)
114         void prepare();
115         /// Prepare node from a stream
116         void prepare(StreamSerialiser& stream);
117         /// Load node and children (perform GPU tasks, will be render thread)
118         void load();
119         /// Load node and children in a depth range (perform GPU tasks, will be render thread)
120         void load(uint16 depthStart, uint16 depthEnd);
121         void loadSelf();
122         /// Unload node and children (perform GPU tasks, will be render thread)
123         void unload();
124         /// Unload node and children in a depth range (perform GPU tasks, will be render thread)
125         void unload(uint16 depthStart, uint16 depthEnd);
126         /// Unprepare node and children (perform CPU tasks, may be background thread)
127         void unprepare();
128         /// Save node to a stream
129         void save(StreamSerialiser& stream);
130 
131         struct _OgreTerrainExport LodLevel : public TerrainAlloc
132         {
133             /// Number of vertices rendered down one side (not including skirts)
134             uint16 batchSize;
135             /// Index data on the gpu
136             IndexData* gpuIndexData;
137             /// Maximum delta height between this and the next lower lod
138             Real maxHeightDelta;
139             /// Temp calc area for max height delta
140             Real calcMaxHeightDelta;
141             /// The most recently calculated transition distance
142             Real lastTransitionDist;
143             /// The cFactor value used to calculate transitionDist
144             Real lastCFactor;
145 
LodLevelLodLevel146             LodLevel() : batchSize(0), gpuIndexData(0), maxHeightDelta(0), calcMaxHeightDelta(0),
147                 lastTransitionDist(0), lastCFactor(0) {}
148         };
149         typedef std::vector<LodLevel*> LodLevelList;
150 
151         /** Get the LodLevel information for a given lod.
152         @param lod The lod level index relative to this classes own list; if you
153             want to use a global lod level, subtract getBaseLod() first. Higher
154             LOD levels are lower detail.
155         */
156         const LodLevel* getLodLevel(uint16 lod);
157 
158         /** Notify the node (and children) that deltas are going to be calculated for a given range.
159         @remarks
160             Based on this call, we can know whether or not to reset the max height.
161         */
162         void preDeltaCalculation(const Rect& rect);
163 
164         /** Notify the node (and children) of a height delta value. */
165         void notifyDelta(uint16 x, uint16 y, uint16 lod, Real delta);
166 
167         /** Notify the node (and children) that deltas have finished being calculated.
168         */
169         void postDeltaCalculation(const Rect& rect);
170 
171         /** Promote the delta values calculated to the runtime ones (this must
172             be called in the main thread).
173         */
174         void finaliseDeltaValues(const Rect& rect);
175 
176         /** Assign vertex data to the tree, from a depth and at a given resolution.
177         @param treeDepthStart The first depth of tree that should use this data, owns the data
178         @param treeDepthEnd The end of the depth that should use this data (exclusive)
179         @param resolution The resolution of the data to use (compared to full terrain)
180         @param sz The size of the data along one edge
181         */
182         void assignVertexData(uint16 treeDepthStart, uint16 treeDepthEnd, uint16 resolution, uint sz);
183 
184         /** Tell a node that it should use an anscestor's vertex data.
185         @param treeDepthEnd The end of the depth that should use this data (exclusive)
186         @param resolution The resolution of the data to use
187         */
188         void useAncestorVertexData(TerrainQuadTreeNode* owner, uint16 treeDepthEnd, uint16 resolution);
189 
190         /** Tell the node to update its vertex data for a given region.
191         */
192         void updateVertexData(bool positions, bool deltas, const Rect& rect, bool cpuData);
193 
194 
195 
196         /** Merge a point (relative to terrain node) into the local bounds,
197             and that of children if applicable.
198         @param x,y The point on the terrain to which this position corresponds
199             (affects which nodes update their bounds)
200         @param pos The position relative to the terrain centre
201         */
202         void mergeIntoBounds(long x, long y, const Vector3& pos);
203         /** Reset the bounds of this node and all its children for the region given.
204         @param rect The region for which bounds should be reset, in top-level terrain coords
205         */
206         void resetBounds(const Rect& rect);
207 
208         /** Returns true if the given rectangle overlaps the terrain area that
209             this node references.
210          @param rect The region in top-level terrain coords
211         */
212         bool rectIntersectsNode(const Rect& rect);
213         /** Returns true if the given rectangle completely contains the terrain area that
214         this node references.
215         @param rect The region in top-level terrain coords
216         */
217         bool rectContainsNode(const Rect& rect);
218         /** Returns true if the given point is in the terrain area that
219          this node references.
220          @param x,y The point in top-level terrain coords
221          */
222         bool pointIntersectsNode(long x, long y);
223 
224         /// Get the AABB (local coords) of this node
225         const AxisAlignedBox& getAABB() const;
226         /// Get the bounding radius of this node
227         Real getBoundingRadius() const;
228         /// Get the local centre of this node, relative to parent terrain centre
getLocalCentre()229         const Vector3& getLocalCentre() const { return mLocalCentre; }
230         /// Get the minimum height of the node
231         Real getMinHeight() const;
232         /// Get the maximum height of the node
233         Real getMaxHeight() const;
234 
235         /** Calculate appropriate LOD for this node and children
236         @param cam The camera to be used (this should already be the LOD camera)
237         @param cFactor The cFactor which incorporates the viewport size, max pixel error and lod bias
238         @return true if this node or any of its children were selected for rendering
239         */
240         bool calculateCurrentLod(const Camera* cam, Real cFactor);
241 
242         /// Get the current LOD index (only valid after calculateCurrentLod)
getCurrentLod()243         int getCurrentLod() const { return mCurrentLod; }
244         /// Returns whether this node is rendering itself at the current LOD level
245         bool isRenderedAtCurrentLod() const;
246         /// Returns whether this node or its children are being rendered at the current LOD level
247         bool isSelfOrChildRenderedAtCurrentLod() const;
248         /// Manually set the current LOD, intended for internal use only
249         void setCurrentLod(int lod);
250         /// Get the transition state between the current LOD and the next lower one (only valid after calculateCurrentLod)
getLodTransition()251         float getLodTransition() const { return mLodTransition; }
252         /// Manually set the current LOD transition state, intended for internal use only
253         void setLodTransition(float t);
254 
255         /// Buffer binding used for holding positions
256         static unsigned short POSITION_BUFFER;
257         /// Buffer binding used for holding delta values
258         static unsigned short DELTA_BUFFER;
259 
260         /// Returns the internal renderable object for this node
261         Renderable *_getRenderable();
262     protected:
263         Terrain* mTerrain;
264         TerrainQuadTreeNode* mParent;
265         TerrainQuadTreeNode* mChildren[4];
266         LodLevelList mLodLevels;
267 
268         uint16 mOffsetX, mOffsetY;
269         uint16 mBoundaryX, mBoundaryY;
270         /// The number of vertices at the original terrain resolution this node encompasses
271         uint16 mSize;
272         uint16 mBaseLod;
273         uint16 mDepth;
274         uint16 mQuadrant;
275         Vector3 mLocalCentre; /// Relative to terrain centre
276         AxisAlignedBox mAABB; /// Relative to mLocalCentre
277         Real mBoundingRadius; /// Relative to mLocalCentre
278         int mCurrentLod; /// -1 = none (do not render)
279         unsigned short mMaterialLodIndex;
280         float mLodTransition; /// 0-1 transition to lower LOD
281         /// The child with the largest height delta
282         TerrainQuadTreeNode* mChildWithMaxHeightDelta;
283         bool mSelfOrChildRendered;
284 
285         struct VertexDataRecord : public TerrainAlloc
286         {
287             VertexData* cpuVertexData;
288             VertexData* gpuVertexData;
289             /// Resolution of the data compared to the base terrain data (NOT number of vertices!)
290             uint16 resolution;
291             /// Size of the data along one edge
292             uint16 size;
293             /// Number of quadtree levels (including this one) this data applies to
294             uint16 treeLevels;
295             /// Number of rows and columns of skirts
296             uint16 numSkirtRowsCols;
297             /// The number of rows / cols to skip in between skirts
298             uint16 skirtRowColSkip;
299             /// Is the GPU vertex data out of date?
300             bool gpuVertexDataDirty;
301 
VertexDataRecordVertexDataRecord302             VertexDataRecord(uint16 res, uint16 sz, uint16 lvls)
303                 : cpuVertexData(0), gpuVertexData(0), resolution(res), size(sz),
304                 treeLevels(lvls), numSkirtRowsCols(0),
305                 skirtRowColSkip(0), gpuVertexDataDirty(false) {}
306         };
307 
308         TerrainQuadTreeNode* mNodeWithVertexData;
309         VertexDataRecord* mVertexDataRecord;
310 
311         /** MovableObject implementation to provide the hook to the scene.
312         @remarks
313             In one sense, it would be most convenient to have a single MovableObject
314             to represent the whole Terrain object, and then internally perform
315             some quadtree frustum culling to narrow down which specific tiles are rendered.
316             However, the one major flaw with that is that exposing the bounds to
317             the SceneManager at that level prevents it from doing anything smarter
318             in terms of culling - for example a portal or occlusion culling SceneManager
319             would have no opportunity to process the leaf nodes in those terms, and
320             a simple frustum cull may give significantly poorer results.
321         @par
322             Therefore, we in fact register a MovableObject at every node, and
323             use the LOD factor to determine which one is currently active. LODs
324             must be mutually exclusive and to deal with precision errors, we really
325             need to evaluate them all at once, rather than as part of the
326             _notifyCurrentCamera function. Therefore the root Terrain registers
327             a SceneManager::Listener to precalculate which nodes will be displayed
328             when it comes to purely a LOD basis.
329         */
330         class _OgreTerrainExport Movable : public MovableObject
331         {
332         protected:
333             TerrainQuadTreeNode* mParent;
334         public:
335             Movable(TerrainQuadTreeNode* parent);
336             virtual ~Movable();
337 
338             // necessary overrides
339             const String& getMovableType(void) const;
340             const AxisAlignedBox& getBoundingBox(void) const;
341             Real getBoundingRadius(void) const;
342             void _updateRenderQueue(RenderQueue* queue);
343             void visitRenderables(Renderable::Visitor* visitor,  bool debugRenderables = false);
344             bool isVisible(void) const;
345             uint32 getVisibilityFlags(void) const;
346             uint32 getQueryFlags(void) const;
347             bool getCastShadows(void) const;
348 
349         };
350         Movable* mMovable;
351         friend class Movable;
352         SceneNode* mLocalNode;
353 
354         /// Hook to the render queue
355         class _OgreTerrainExport Rend : public Renderable, public TerrainAlloc
356         {
357         protected:
358             TerrainQuadTreeNode* mParent;
359         public:
360             Rend(TerrainQuadTreeNode* parent);
361             virtual ~Rend();
362 
363             const MaterialPtr& getMaterial(void) const;
364             Technique* getTechnique(void) const;
365             void getRenderOperation(RenderOperation& op);
366             void getWorldTransforms(Matrix4* xform) const;
367             Real getSquaredViewDepth(const Camera* cam) const;
368             const LightList& getLights(void) const;
369             bool getCastsShadows(void) const;
370 
371         };
372         Rend* mRend;
373         friend class Rend;
374 
375         // actual implementation of MovableObject methods
376         void updateRenderQueue(RenderQueue* queue);
377         void visitRenderables(Renderable::Visitor* visitor,  bool debugRenderables = false);
378         // actual implementations of Renderable methods
379         const MaterialPtr& getMaterial(void) const;
380         Technique* getTechnique(void) const;
381         void getRenderOperation(RenderOperation& op);
382         void getWorldTransforms(Matrix4* xform) const;
383         Real getSquaredViewDepth(const Camera* cam) const;
384         const LightList& getLights(void) const;
385         bool getCastsShadows(void) const;
386 
387 
388         const VertexDataRecord* getVertexDataRecord() const;
389         void createCpuVertexData();
390         /* Update the vertex buffers - the rect in question is relative to the whole terrain,
391             not the local vertex data (which may use a subset)
392         */
393         void updateVertexBuffer(HardwareVertexBufferSharedPtr& posbuf, HardwareVertexBufferSharedPtr& deltabuf, const Rect& rect);
394         void destroyCpuVertexData();
395 
396         void createGpuVertexData();
397         void destroyGpuVertexData();
398         void updateGpuVertexData();
399         void createGpuIndexData();
400         void destroyGpuIndexData();
401 
402         void populateIndexData(uint16 batchSize, IndexData* destData);
403         void writePosVertex(bool compress, uint16 x, uint16 y, float height, const Vector3& pos, float uvScale, float** ppPos);
404         void writeDeltaVertex(bool compress, uint16 x, uint16 y, float delta, float deltaThresh, float** ppDelta);
405 
406         uint16 calcSkirtVertexIndex(uint16 mainIndex, bool isCol);
407 
408     };
409 
410     /** @} */
411     /** @} */
412 }
413 
414 #endif
415