/src/ogre/PlugIns/BSPSceneManager/include/OgreBspNode.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 _BspNode_H__ |
29 | | #define _BspNode_H__ |
30 | | |
31 | | #include "OgreBspPrerequisites.h" |
32 | | #include "OgrePlane.h" |
33 | | #include "OgreAxisAlignedBox.h" |
34 | | #include "OgreSceneQuery.h" |
35 | | |
36 | | namespace Ogre { |
37 | | class BspLevel; |
38 | | |
39 | | /** \addtogroup Plugins |
40 | | * @{ |
41 | | */ |
42 | | /** \addtogroup BSPSceneManager |
43 | | * @{ |
44 | | */ |
45 | | |
46 | | /** This type can be used by collaborating applications & SceneManagers to |
47 | | agree on the type of world geometry to be returned from queries. Not all |
48 | | these types will be supported by all SceneManagers; once the application |
49 | | has decided which SceneManager specialisation to use, it is expected that |
50 | | it will know which type of world geometry abstraction is available to it. |
51 | | */ |
52 | | enum WorldFragmentType { |
53 | | /// Return no world geometry hits at all |
54 | | WFT_NONE, |
55 | | /// Return pointers to convex plane-bounded regions |
56 | | WFT_PLANE_BOUNDED_REGION, |
57 | | /// Return a single intersection point (typically RaySceneQuery only) |
58 | | WFT_SINGLE_INTERSECTION, |
59 | | /// Custom geometry as defined by the SceneManager |
60 | | WFT_CUSTOM_GEOMETRY, |
61 | | /// General RenderOperation structure |
62 | | WFT_RENDER_OPERATION |
63 | | }; |
64 | | |
65 | | /** Represents part of the world geometry that is a result of a SceneQuery. |
66 | | |
67 | | Since world geometry is normally vast and sprawling, we need a way of |
68 | | retrieving parts of it based on a query. That is what this struct is for; |
69 | | note there are potentially as many data structures for world geometry as there |
70 | | are SceneManagers, however this structure includes a few common abstractions as |
71 | | well as a more general format. |
72 | | @par |
73 | | The type of world fragment that is returned from a query depends on the |
74 | | SceneManager, and the option set using SceneQuery::setWorldFragmentType. |
75 | | You can see what fragment types are supported on the query in question by |
76 | | calling SceneQuery::getSupportedWorldFragmentTypes(). |
77 | | */ |
78 | | struct WorldFragment { |
79 | | /// The type of this world fragment |
80 | | WorldFragmentType fragmentType; |
81 | | /// Single intersection point, only applicable for WFT_SINGLE_INTERSECTION |
82 | | Vector3 singleIntersection; |
83 | | /// Planes bounding a convex region, only applicable for WFT_PLANE_BOUNDED_REGION |
84 | | std::vector<Plane>* planes; |
85 | | /// Custom geometry block, only applicable for WFT_CUSTOM_GEOMETRY |
86 | | void* geometry; |
87 | | /// General render operation structure, fallback if nothing else is available |
88 | | RenderOperation* renderOp; |
89 | | }; |
90 | | |
91 | | /** Encapsulates a node in a BSP tree. |
92 | | A BSP tree represents space partitioned by planes . The space which is |
93 | | partitioned is either the world (in the case of the root node) or the space derived |
94 | | from their parent node. Each node can have elements which are in front or behind it, which are |
95 | | it's children and these elements can either be further subdivided by planes, |
96 | | or they can be undivided spaces or 'leaf nodes' - these are the nodes which actually contain |
97 | | objects and world geometry.The leaves of the tree are the stopping point of any tree walking algorithm, |
98 | | both for rendering and collision detection etc. |
99 | | Ogre chooses not to represent splitting nodes and leaves as separate structures, but to merge the two for simplicity |
100 | | of the walking algorithm. If a node is a leaf, the isLeaf() method returns true and both getFront() and |
101 | | getBack() return null pointers. If the node is a partitioning plane isLeaf() returns false and getFront() |
102 | | and getBack() will return the corresponding BspNode objects. |
103 | | */ |
104 | | class BspNode : public NodeAlloc |
105 | | { |
106 | | friend class BspLevel; |
107 | | |
108 | | public: |
109 | | /** Constructor, only to be used by BspLevel. */ |
110 | | BspNode(BspLevel* owner, bool isLeaf); |
111 | | |
112 | | BspNode(); |
113 | | ~BspNode(); |
114 | | |
115 | | /** Returns true if this node is a leaf (i.e. contains geometry) or false if it is a splitting plane. |
116 | | A BspNode can either be a splitting plane (the typical representation of a BSP node) or an undivided |
117 | | region contining geometry (a leaf node). Ogre represents both using the same class for simplicity |
118 | | of tree walking. However it is important that you use this method to determine which type you are dealing |
119 | | with, since certain methods are only supported with one of the subtypes. Details are given in the individual methods. |
120 | | Note that I could have represented splitting / leaf nodes as a class hierarchy but the |
121 | | virtual methods / run-time type identification would have a performance hit, and it would not make the |
122 | | code much (any?) simpler anyway. I think this is a fair trade-off in this case. |
123 | | */ |
124 | | bool isLeaf(void) const; |
125 | | |
126 | | /** Returns a pointer to a BspNode containing the subspace on the positive side of the splitting plane. |
127 | | This method should only be called on a splitting node, i.e. where isLeaf() returns false. Calling this |
128 | | method on a leaf node will throw an exception. |
129 | | */ |
130 | | BspNode* getFront(void) const; |
131 | | |
132 | | /** Returns a pointer to a BspNode containing the subspace on the negative side of the splitting plane. |
133 | | This method should only be called on a splitting node, i.e. where isLeaf() returns false. Calling this |
134 | | method on a leaf node will throw an exception. |
135 | | */ |
136 | | BspNode* getBack(void) const; |
137 | | |
138 | | /** Determines which side of the splitting plane a worldspace point is. |
139 | | This method should only be called on a splitting node, i.e. where isLeaf() returns false. Calling this |
140 | | method on a leaf node will throw an exception. |
141 | | */ |
142 | | Plane::Side getSide (const Vector3& point) const; |
143 | | |
144 | | /** Gets the next node down in the tree, with the intention of |
145 | | locating the leaf containing the given point. |
146 | | This method should only be called on a splitting node, i.e. where isLeaf() returns false. Calling this |
147 | | method on a leaf node will throw an exception. |
148 | | */ |
149 | | BspNode* getNextNode(const Vector3& point) const; |
150 | | |
151 | | |
152 | | /** Returns details of the plane which is used to subdivide the space of his node's children. |
153 | | This method should only be called on a splitting node, i.e. where isLeaf() returns false. Calling this |
154 | | method on a leaf node will throw an exception. |
155 | | */ |
156 | | const Plane& getSplitPlane(void) const; |
157 | | |
158 | | /** Returns the axis-aligned box which contains this node if it is a leaf. |
159 | | This method should only be called on a leaf node. It returns a box which can be used in calls like |
160 | | Camera::isVisible to determine if the leaf node is visible in the view. |
161 | | */ |
162 | | const AxisAlignedBox& getBoundingBox(void) const; |
163 | | |
164 | | /** Returns the number of faces contained in this leaf node. |
165 | | Should only be called on a leaf node. |
166 | | */ |
167 | | int getNumFaceGroups(void) const; |
168 | | /** Returns the index to the face group index list for this leaf node. |
169 | | The contents of this buffer is a list of indexes which point to the |
170 | | actual face groups held in a central buffer in the BspLevel class (in |
171 | | actual fact for efficiency the indexes themselves are also held in a single |
172 | | buffer in BspLevel too). The reason for this indirection is that the buffer |
173 | | of indexes to face groups is organised in chunks relative to nodes, whilst the |
174 | | main buffer of face groups may not be. |
175 | | Should only be called on a leaf node. |
176 | | */ |
177 | | int getFaceGroupStart(void) const; |
178 | | |
179 | | /** Determines if the passed in node (must also be a leaf) is visible from this leaf. |
180 | | Must only be called on a leaf node, and the parameter must also be a leaf node. If |
181 | | this method returns true, then the leaf passed in is visible from this leaf. |
182 | | Note that internally this uses the Potentially Visible Set (PVS) which is precalculated |
183 | | and stored with the BSP level. |
184 | | */ |
185 | | bool isLeafVisible(const BspNode* leaf) const; |
186 | | |
187 | | friend std::ostream& operator<< (std::ostream& o, BspNode& n); |
188 | | |
189 | | /// Internal method for telling the node that a movable intersects it |
190 | | void _addMovable(const MovableObject* mov); |
191 | | |
192 | | /// Internal method for telling the node that a movable no longer intersects it |
193 | | void _removeMovable(const MovableObject* mov); |
194 | | |
195 | | /// Gets the signed distance to the dividing plane |
196 | | Real getDistance(const Vector3& pos) const; |
197 | | |
198 | | typedef std::set<const MovableObject*> IntersectingObjectSet; |
199 | | |
200 | | struct Brush |
201 | | { |
202 | | std::vector<Plane> planes; |
203 | | SceneQuery::WorldFragment fragment; /// For query reporting |
204 | | }; |
205 | | typedef std::vector<Brush*> NodeBrushList; /// Main brush memory held on level |
206 | | |
207 | | /** Get the list of solid Brushes for this node. |
208 | | @remarks Only applicable for leaf nodes. |
209 | | */ |
210 | | const NodeBrushList& getSolidBrushes(void) const; |
211 | | protected: |
212 | | BspLevel* mOwner; /// Back-reference to containing level |
213 | | bool mIsLeaf; |
214 | | |
215 | | // Node-only members |
216 | | /** The plane which splits space in a non-leaf node. |
217 | | Note that nodes do not allocate the memory for other nodes - for simplicity and bulk-allocation |
218 | | of memory the BspLevel is responsible for assigning enough memory for all nodes in one go. |
219 | | */ |
220 | | Plane mSplitPlane; |
221 | | /** Pointer to the node in front of this non-leaf node. */ |
222 | | BspNode* mFront; |
223 | | /** Pointer to the node behind this non-leaf node. */ |
224 | | BspNode* mBack; |
225 | | |
226 | | // Leaf-only members |
227 | | /** The cluster number of this leaf. |
228 | | Leaf nodes are assigned to 'clusters' of nodes, which are used to group nodes together for |
229 | | visibility testing. There is a lookup table which is used to determine if one cluster of leaves |
230 | | is visible from another cluster. Whilst it would be possible to expand all this out so that |
231 | | each node had a list of pointers to other visible nodes, this would be very expensive in terms |
232 | | of storage (using the cluster method there is a table which is 1-bit squared per cluster, rounded |
233 | | up to the nearest byte obviously, which uses far less space than 4-bytes per linked node per source |
234 | | node). Of course the limitation here is that you have to each leaf in turn to determine if it is visible |
235 | | rather than just following a list, but since this is only done once per frame this is not such a big |
236 | | overhead. |
237 | | */ |
238 | | int mVisCluster; |
239 | | |
240 | | /** The axis-aligned box which bounds node if it is a leaf. */ |
241 | | AxisAlignedBox mBounds; |
242 | | /** Number of face groups in this node if it is a leaf. */ |
243 | | int mNumFaceGroups; |
244 | | /** Index to the part of the main leaf facegroup index buffer(held in BspLevel) for this leaf. |
245 | | This leaf uses mNumFaceGroups from this pointer onwards. From here you use the index |
246 | | in this buffer to look up the actual face. |
247 | | Note that again for simplicity and bulk memory allocation the face |
248 | | group list itself is allocated by the BspLevel for all nodes, and each leaf node is given a section of it to |
249 | | work on. This saves lots of small memory allocations / deallocations which limits memory fragmentation. |
250 | | */ |
251 | | int mFaceGroupStart; |
252 | | |
253 | | IntersectingObjectSet mMovables; |
254 | | |
255 | | NodeBrushList mSolidBrushes; |
256 | | public: |
257 | 0 | const IntersectingObjectSet& getObjects(void) const { return mMovables; } |
258 | | |
259 | | |
260 | | }; |
261 | | /** @} */ |
262 | | /** @} */ |
263 | | |
264 | | } |
265 | | |
266 | | #endif |