Coverage Report

Created: 2025-10-12 07:23

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ogre/PlugIns/BSPSceneManager/include/OgreBspSceneManager.h
Line
Count
Source
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 __BspSceneManager_H__
29
#define __BspSceneManager_H__
30
31
32
#include "OgreBspPrerequisites.h"
33
#include "OgreSceneManager.h"
34
#include "OgreStaticFaceGroup.h"
35
#include "OgreRenderOperation.h"
36
#include "OgreBspLevel.h"
37
#include <set>
38
39
40
namespace Ogre {
41
    /** \addtogroup Plugins
42
    *  @{
43
    */
44
    /** \addtogroup BSPSceneManager
45
    *  @{
46
    */
47
48
    /** Specialisation of the SceneManager class to deal with indoor scenes
49
        based on a BSP tree.
50
        This class refines the behaviour of the default SceneManager to manage
51
        a scene whose bulk of geometry is made up of an indoor environment which
52
        is organised by a Binary Space Partition (BSP) tree.
53
        A BSP tree progressively subdivides the space using planes which are the nodes of the tree.
54
        At some point we stop subdividing and everything in the remaining space is part of a 'leaf' which
55
        contains a number of polygons. Typically we traverse the tree to locate the leaf in which a
56
        point in space is (say the camera origin) and work from there. A second structure, the
57
        Potentially Visible Set, tells us which other leaves can been seen from this
58
        leaf, and we test their bounding boxes against the camera frustum to see which
59
        we need to draw. Leaves are also a good place to start for collision detection since
60
        they divide the level into discrete areas for testing.
61
        This BSP and PVS technique has been made famous by engines such as Quake and Unreal. Ogre
62
        provides support for loading Quake3 level files to populate your world through this class,
63
        by calling the BspSceneManager::setWorldGeometry. Note that this interface is made
64
        available at the top level of the SceneManager class so you don't have to write your code
65
        specifically for this class - just call Root::getSceneManager passing a SceneType of ST_INTERIOR
66
        and in the current implementation you will get a BspSceneManager silently disguised as a
67
        standard SceneManager.
68
    */
69
    class BspSceneManager : public SceneManager
70
    {
71
        /** Comparator for material map, for sorting materials into render order (e.g. transparent last).
72
        */
73
        struct materialLess
74
        {
75
            bool operator()(const Material* x, const Material* y) const
76
0
            {
77
                // If x transparent and y not, x > y (since x has to overlap y)
78
0
                if (x->isTransparent() && !y->isTransparent())
79
0
                {
80
0
                    return false;
81
0
                }
82
                // If y is transparent and x not, x < y
83
0
                else if (!x->isTransparent() && y->isTransparent())
84
0
                {
85
0
                    return true;
86
0
                }
87
0
                else
88
0
                {
89
                    // Otherwise don't care (both transparent or both solid)
90
                    // Just arbitrarily use pointer
91
0
                    return x < y;
92
0
                }
93
0
            }
94
        };
95
96
        /// World geometry
97
        BspLevelPtr mLevel;
98
99
        // State variables for rendering WIP
100
        // Set of face groups (by index) already included
101
        typedef std::set<int> FaceGroupSet;
102
        FaceGroupSet mFaceGroupSet;
103
        // Material -> face group hashmap
104
        typedef std::map<Material*, std::vector<StaticFaceGroup*>, materialLess > MaterialFaceGroupMap;
105
        MaterialFaceGroupMap mMatFaceGroupMap;
106
107
        // Debugging features
108
        bool mShowNodeAABs;
109
        RenderOperation mAABGeometry;
110
111
        /** Walks the BSP tree looking for the node which the camera
112
            is in, and tags any geometry which is in a visible leaf for
113
            later processing.
114
            @param camera Pointer to the viewpoint.
115
            @return The BSP node the camera was found in, for info.
116
        */
117
        BspNode* walkTree(Camera* camera, VisibleObjectsBoundsInfo* visibleBounds, bool onlyShadowCasters);
118
        /** Tags geometry in the leaf specified for later rendering. */
119
        void processVisibleLeaf(BspNode* leaf, Camera* cam, 
120
            VisibleObjectsBoundsInfo* visibleBounds, bool onlyShadowCasters);
121
122
        /** Adds a bounding box to draw if turned on. */
123
        void addBoundingBox(const AxisAlignedBox& aab, bool visible);
124
125
        /** Renders the static level geometry tagged in walkTree. */
126
        void renderStaticGeometry(void);
127
128
        /** @copydoc SceneManager::clearScene */
129
        void clearScene(void) override;
130
131
        // Overridden so we can manually render world geometry
132
        bool fireRenderQueueEnded(uint8 id, const String& invocation) override;
133
134
        typedef std::set<const MovableObject*> MovablesForRendering;
135
        MovablesForRendering mMovablesForRendering;
136
137
    public:
138
        BspSceneManager(const String& name);
139
        ~BspSceneManager();
140
141
142
        /// @copydoc SceneManager::getTypeName
143
        const String& getTypeName(void) const override;
144
145
        /** Specialised from SceneManager to support Quake3 bsp files. */
146
        void setWorldGeometry(const String& filename) override;
147
148
        /** Specialised from SceneManager to support Quake3 bsp files. */
149
        size_t estimateWorldGeometry(const String& filename) override;
150
        
151
        /** Specialised from SceneManager to support Quake3 bsp files. */
152
        void setWorldGeometry(DataStreamPtr& stream, 
153
            const String& typeName = BLANKSTRING) override;
154
155
        /** Specialised from SceneManager to support Quake3 bsp files. */
156
        size_t estimateWorldGeometry(DataStreamPtr& stream, 
157
            const String& typeName = BLANKSTRING) override;
158
159
        /** Tells the manager whether to draw the axis-aligned boxes that surround
160
            nodes in the Bsp tree. For debugging purposes.
161
        */
162
        void showNodeBoxes(bool show);
163
164
        /** Specialised to suggest viewpoints. */
165
        ViewPoint getSuggestedViewpoint(bool random = false) override;
166
167
0
        const BspLevelPtr& getLevel(void) {return mLevel; }
168
169
        void setLevel(const BspLevelPtr& level);
170
171
        /** Overridden from SceneManager. */
172
        void _findVisibleObjects(Camera* cam, VisibleObjectsBoundsInfo* visibleBounds, 
173
            bool onlyShadowCasters) override;
174
175
        /** Creates a specialized BspSceneNode */
176
        SceneNode * createSceneNodeImpl ( void ) override;
177
        /** Creates a specialized BspSceneNode */
178
        SceneNode * createSceneNodeImpl ( const String &name ) override;
179
180
        /** Internal method for tagging BspNodes with objects which intersect them. */
181
        void _notifyObjectMoved(const MovableObject* mov, const Vector3& pos);
182
        /** Internal method for notifying the level that an object has been detached from a node */
183
        void _notifyObjectDetached(const MovableObject* mov);
184
185
        /* Creates an AxisAlignedBoxSceneQuery for this scene manager. 
186
187
            This method creates a new instance of a query object for this scene manager, 
188
            for an axis aligned box region. See SceneQuery and AxisAlignedBoxSceneQuery 
189
            for full details.
190
        @par
191
            The instance returned from this method must be destroyed by calling
192
            SceneManager::destroyQuery when it is no longer required.
193
        @param box Details of the box which describes the region for this query.
194
        @param mask The query mask to apply to this query; can be used to filter out
195
            certain objects; see SceneQuery for details.
196
        */
197
        /*
198
        virtual AxisAlignedBoxSceneQuery* 
199
            createAABBQuery(const AxisAlignedBox& box, uint32 mask = 0xFFFFFFFF);
200
        */
201
        /* Creates a SphereSceneQuery for this scene manager. 
202
203
            This method creates a new instance of a query object for this scene manager, 
204
            for a spherical region. See SceneQuery and SphereSceneQuery 
205
            for full details.
206
        @par
207
            The instance returned from this method must be destroyed by calling
208
            SceneManager::destroyQuery when it is no longer required.
209
        @param sphere Details of the sphere which describes the region for this query.
210
        @param mask The query mask to apply to this query; can be used to filter out
211
            certain objects; see SceneQuery for details.
212
        */
213
        /*
214
        virtual SphereSceneQuery* 
215
            createSphereQuery(const Sphere& sphere, uint32 mask = 0xFFFFFFFF);
216
        */
217
        /** Creates a RaySceneQuery for this scene manager. 
218
219
            This method creates a new instance of a query object for this scene manager, 
220
            looking for objects which fall along a ray. See SceneQuery and RaySceneQuery 
221
            for full details.
222
        @par
223
            The instance returned from this method must be destroyed by calling
224
            SceneManager::destroyQuery when it is no longer required.
225
        @param ray Details of the ray which describes the region for this query.
226
        @param mask The query mask to apply to this query; can be used to filter out
227
            certain objects; see SceneQuery for details.
228
        */
229
        RaySceneQuery*
230
            createRayQuery(const Ray& ray, uint32 mask = 0xFFFFFFFF) override;
231
        /** Creates an IntersectionSceneQuery for this scene manager. 
232
233
            This method creates a new instance of a query object for locating
234
            intersecting objects. See SceneQuery and IntersectionSceneQuery
235
            for full details.
236
        @par
237
            The instance returned from this method must be destroyed by calling
238
            SceneManager::destroyQuery when it is no longer required.
239
        @param mask The query mask to apply to this query; can be used to filter out
240
            certain objects; see SceneQuery for details.
241
        */
242
        IntersectionSceneQuery*
243
            createIntersectionQuery(uint32 mask = 0xFFFFFFFF) override;
244
245
    };
246
247
    /** BSP specialisation of IntersectionSceneQuery */
248
    class BspIntersectionSceneQuery : public DefaultIntersectionSceneQuery
249
    {
250
        std::set<WorldFragmentType> mSupportedWorldFragments;
251
        WorldFragmentType mWorldFragmentType;
252
    public:
253
        BspIntersectionSceneQuery(SceneManager* creator);
254
255
        /** See IntersectionSceneQuery. */
256
        void execute(IntersectionSceneQueryListener* listener) override;
257
258
        /** Tells the query what kind of world geometry to return from queries;
259
            often the full renderable geometry is not what is needed.
260
261
            The application receiving the world geometry is expected to know
262
            what to do with it; inevitably this means that the application must
263
            have knowledge of at least some of the structures
264
            used by the custom SceneManager.
265
        @par
266
            The default setting is WFT_NONE.
267
        */
268
        void setWorldFragmentType(enum WorldFragmentType wft)
269
0
        {
270
0
            // Check supported
271
0
            OgreAssert(mSupportedWorldFragments.find(wft) != mSupportedWorldFragments.end(),
272
0
                       "This world fragment type is not supported.");
273
0
            mWorldFragmentType = wft;
274
0
        }
275
276
        /** Gets the current world fragment types to be returned from the query. */
277
0
        WorldFragmentType getWorldFragmentType(void) const { return mWorldFragmentType; }
278
279
        /** Returns the types of world fragments this query supports. */
280
0
        const std::set<WorldFragmentType>* getSupportedWorldFragmentTypes() const { return &mSupportedWorldFragments; }
281
    };
282
283
    /** BSP specialisation of RaySceneQuery */
284
    class BspRaySceneQuery : public DefaultRaySceneQuery
285
    {
286
        std::set<WorldFragmentType> mSupportedWorldFragments;
287
        WorldFragmentType mWorldFragmentType;
288
    public:
289
        BspRaySceneQuery(SceneManager* creator);
290
        ~BspRaySceneQuery();
291
292
        /// @copydoc BspIntersectionSceneQuery::setWorldFragmentType
293
        void setWorldFragmentType(enum WorldFragmentType wft)
294
0
        {
295
0
            // Check supported
296
0
            OgreAssert(mSupportedWorldFragments.find(wft) != mSupportedWorldFragments.end(),
297
0
                       "This world fragment type is not supported.");
298
0
            mWorldFragmentType = wft;
299
0
        }
300
301
        /// @copydoc BspIntersectionSceneQuery::getWorldFragmentType
302
0
        WorldFragmentType getWorldFragmentType(void) const { return mWorldFragmentType; }
303
304
        /// @copydoc BspIntersectionSceneQuery::getSupportedWorldFragmentTypes
305
0
        const std::set<WorldFragmentType>* getSupportedWorldFragmentTypes() const { return &mSupportedWorldFragments; }
306
307
        /** See RaySceneQuery. */
308
        void execute(RaySceneQueryListener* listener) override;
309
    protected:
310
        /// Set for eliminating duplicates since objects can be in > 1 node
311
        std::set<MovableObject*> mObjsThisQuery;
312
        /// list of the last single intersection world fragments (derived)
313
        std::vector<SceneQuery::WorldFragment*> mSingleIntersections;
314
315
        void clearTemporaries(void);
316
        /** Internal processing of a single node.
317
        @return true if we should continue tracing, false otherwise
318
        */
319
        bool processNode(const BspNode* node, const Ray& tracingRay, RaySceneQueryListener* listener,
320
            Real maxDistance = Math::POS_INFINITY, Real traceDistance = 0.0f);
321
        /** Internal processing of a single leaf.
322
        @return true if we should continue tracing, false otherwise
323
        */
324
        bool processLeaf(const BspNode* node, const Ray& tracingRay, RaySceneQueryListener* listener,
325
            Real maxDistance = Math::POS_INFINITY, Real traceDistance = 0.0f);
326
327
    };
328
329
    /// Factory for BspSceneManager
330
    class BspSceneManagerFactory : public SceneManagerFactory
331
    {
332
    public:
333
        /// Factory type name
334
        static const String FACTORY_TYPE_NAME;
335
        SceneManager* createInstance(const String& instanceName) override;
336
0
        const String& getTypeName(void) const override { return FACTORY_TYPE_NAME; }
337
    };
338
    /** @} */
339
    /** @} */
340
}
341
342
#endif