source: GTP/trunk/App/Demos/Geom/OgreStuff/include/opt/OgreBspLevel.h @ 1812

Revision 1812, 11.6 KB checked in by gumbau, 18 years ago (diff)
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-2005 The OGRE Team
8Also see acknowledgements in Readme.html
9
10This program is free software; you can redistribute it and/or modify it under
11the terms of the GNU Lesser General Public License as published by the Free Software
12Foundation; either version 2 of the License, or (at your option) any later
13version.
14
15This program is distributed in the hope that it will be useful, but WITHOUT
16ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
18
19You should have received a copy of the GNU Lesser General Public License along with
20this program; if not, write to the Free Software Foundation, Inc., 59 Temple
21Place - Suite 330, Boston, MA 02111-1307, USA, or go to
22http://www.gnu.org/copyleft/lesser.txt.
23-----------------------------------------------------------------------------
24*/
25#ifndef _BspLevel_H__
26#define _BspLevel_H__
27
28#include "OgreBspPrerequisites.h"
29#include "OgreResource.h"
30#include "OgreStaticFaceGroup.h"
31#include "OgreSceneManager.h"
32#include "OgreBspNode.h"
33#include "OgreHardwareBufferManager.h"
34#include "OgreDefaultHardwareBufferManager.h"
35#include "OgreQuake3Level.h"
36
37
38namespace Ogre {
39
40    /** Holds all the data associated with a Binary Space Parition
41        (BSP) based indoor level.
42        The data used here is populated by loading level files via
43        the BspLevelManager::load method, although application users
44        are more likely to call SceneManager::setWorldGeometry which will
45        automatically arrange the loading of the level. Note that this assumes
46        that you have asked for an indoor-specialised SceneManager (specify
47        ST_INDOOR when calling Root::getSceneManager).</p>
48        Ogre currently only supports loading from Quake3 Arena level files,
49        although any source that can be converted into this classes structure
50        could also be used. The Quake3 level load process is in a different
51        class called Quake3Level to keep the specifics separate.</p>
52    */
53    class BspLevel : public Resource
54    {
55        friend class BspSceneManager;
56    public:
57        /** Default constructor - used by BspResourceManager (do not call directly) */
58        BspLevel(ResourceManager* creator, const String& name, ResourceHandle handle,
59            const String& group, bool isManual = false, ManualResourceLoader* loader = 0);
60        ~BspLevel();
61
62        /** Determines if one leaf node is visible from another. */
63        bool isLeafVisible(const BspNode* from, const BspNode* to) const;
64
65        /** Returns a pointer to the root node (BspNode) of the BSP tree. */
66        const BspNode* getRootNode(void);
67
68        /** Walks the entire BSP tree and returns the leaf
69            which contains the given point.
70        */
71        BspNode* findLeaf(const Vector3& point) const;
72
73        /** Ensures that the MovableObject is attached to the right leaves of the
74            BSP tree.
75        */
76        void _notifyObjectMoved(const MovableObject* mov,
77            const Vector3& pos);
78                /** Internal method, makes sure an object is removed from the leaves when detached from a node. */
79                void _notifyObjectDetached(const MovableObject* mov);
80        /** Gets a pointer to the start of the leaf nodes. */
81        BspNode* getLeafStart(void) {return &mRootNode[mLeafStart]; }
82        /** Gets the number of leaf nodes */
83        int getNumLeaves(void) const { return mNumLeaves; }
84
85        /** Calculate the number of loading stages required for a given level */
86        static size_t calculateLoadingStages(const String& levelName);
87        /** Calculate the number of loading stages required for a given level */
88        static size_t calculateLoadingStages(DataStreamPtr& stream);
89
90                /** Load direct from stream */
91                void load(DataStreamPtr& stream);
92
93                /** Is sky enabled? */
94                bool isSkyEnabled(void) const;
95                /** Get Sky material name */
96                const String& getSkyMaterialName(void) const;
97                /** Get sky curvature */
98                Real getSkyCurvature(void) const;
99
100        /** Utility class just to enable queueing of patches */
101    protected:
102        /** @copydoc Resource::loadImpl. */
103        void loadImpl(void);
104        /** @copydoc Resource::unloadImpl. */
105        void unloadImpl(void);
106        /** @copydoc Resource::calculateSize. */
107        size_t calculateSize(void) const;
108        /** Pointer to the root node of the BSP tree;
109            This pointer actually has a dual purpose; to avoid allocating lots of small chunks of
110            memory, the BspLevel actually allocates all nodes required through this pointer. So this
111            pointer is the handle for the allocation of memory for all nodes. It also happens to point
112            to the root node, since the first one in the memory chunk is the root node.
113        */
114        BspNode* mRootNode;
115        int mNumNodes;
116        int mNumLeaves;
117        int mLeafStart; // the index at which leaf nodes begin
118
119        /** Vertex format for fixed geometry.
120            Note that in this case vertex components (position, normal, texture coords etc)
121            are held interleaved in the same buffer. However, the format here is different from
122            the format used by Quake because older Direct3d drivers like the vertex elements
123            to be in a particular order within the buffer. See VertexDeclaration for full
124            details of this marvellous(not) feature.
125        */
126        struct BspVertex
127        {
128            float position[3];
129            float normal[3];
130            int colour;
131            float texcoords[2];
132            float lightmap[2];
133        };
134        /*
135        /// Array of vertices for whole level.
136        BspVertex* mVertices;
137        int mNumVertices;
138        */
139        /// Vertex data holding all the data for the level, but able to render parts of it
140        VertexData* mVertexData;
141
142        /** Array of indexes into the mFaceGroups array. This buffer is organised
143            by leaf node so leaves can just use contiguous chunks of it and
144            get repointed to the actual entries in mFaceGroups. */
145        int* mLeafFaceGroups;
146        int mNumLeafFaceGroups;
147
148        /** Array of face groups, indexed into by contents of mLeafFaceGroups. */
149        StaticFaceGroup* mFaceGroups;
150        int mNumFaceGroups;
151
152
153        /*
154        /// Array of elements i.e. vertex indexes as used by face groups.
155        int* mElements;
156        int mNumElements;
157        */
158
159        /// indexes for the whole level, will be copied to the real indexdata per frame
160        size_t mNumIndexes;
161        // system-memory buffer
162        HardwareIndexBufferSharedPtr mIndexes;
163
164        /// Brushes as used for collision, main memory is here
165        BspNode::Brush *mBrushes;
166
167        /** Vector of player start points */
168        std::vector<ViewPoint> mPlayerStarts;
169
170        /** Internal utility function for loading data from Quake3. */
171        void loadQuake3Level(const Quake3Level& q3lvl);
172        /** Internal lookup table to determine visibility between leaves.
173            Leaf nodes are assigned to 'clusters' of nodes, which are used to group nodes together for
174            visibility testing. This data holds a lookup table which is used to determine if one cluster of leaves
175            is visible from another cluster. Whilst it would be possible to expand all this out so that
176            each node had a list of pointers to other visible nodes, this would be very expensive in terms
177            of storage (using the cluster method there is a table which is 1-bit squared per cluster, rounded
178            up to the nearest byte obviously, which uses far less space than 4-bytes per linked node per source
179            node). Of course the limitation here is that you have to each leaf in turn to determine if it is visible
180            rather than just following a list, but since this is only done once per frame this is not such a big
181            overhead.</p>
182            Each row in the table is a 'from' cluster, with each bit in the row corresponding to a 'to' cluster,
183            both ordered based on cluster index. A 0 in the bit indicates the 'to' cluster is not visible from the
184            'from' cluster, whilst a 1 indicates it is.</p>
185            As many will notice, this is lifted directly from the Quake implementation of PVS.
186        */
187        struct VisData
188        {
189            unsigned char *tableData;
190            int numClusters;            // Number of clusters, therefore number of rows
191            int rowLength;                // Length in bytes of each row (num clusters / 8 rounded up)
192        };
193
194        VisData mVisData;
195
196
197        /** Internal method for parsing chosen entities. */
198        void loadEntities(const Quake3Level& q3lvl);
199
200        typedef std::map<const MovableObject*, std::list<BspNode*> > MovableToNodeMap;
201        /// Map for locating the nodes a movable is currently a member of
202        MovableToNodeMap mMovableToNodeMap;
203
204        void tagNodesWithMovable(BspNode* node, const MovableObject* mov, const Vector3& pos);
205
206        // Storage of patches
207        typedef std::map<int, PatchSurface*> PatchMap;
208        PatchMap mPatches;
209        // Total number of vertices required for all patches
210        size_t mPatchVertexCount;
211        // Total number of indexes required for all patches
212        size_t mPatchIndexCount;
213                // Sky enabled?
214                bool mSkyEnabled;
215                // Sky material
216                String mSkyMaterial;
217                // Sky details
218                Real mSkyCurvature;
219
220
221        void initQuake3Patches(const Quake3Level & q3lvl, VertexDeclaration* decl);
222        void buildQuake3Patches(size_t vertOffset, size_t indexOffset);
223
224        void quakeVertexToBspVertex(const bsp_vertex_t* src, BspVertex* dest);
225
226
227    };
228    /** Specialisation of SharedPtr to allow SharedPtr to be assigned to BspLevelPtr
229    @note Has to be a subclass since we need operator=.
230    We could templatise this instead of repeating per Resource subclass,
231    except to do so requires a form VC6 does not support i.e.
232    ResourceSubclassPtr<T> : public SharedPtr<T>
233    */
234    class BspLevelPtr : public SharedPtr<BspLevel>
235    {
236    public:
237        BspLevelPtr() : SharedPtr<BspLevel>() {}
238        explicit BspLevelPtr(BspLevel* rep) : SharedPtr<BspLevel>(rep) {}
239        BspLevelPtr(const BspLevelPtr& r) : SharedPtr<BspLevel>(r) {}
240        BspLevelPtr(const ResourcePtr& r) : SharedPtr<BspLevel>()
241        {
242                        // lock & copy other mutex pointer
243                        OGRE_LOCK_MUTEX(*r.OGRE_AUTO_MUTEX_NAME)
244                        OGRE_COPY_AUTO_SHARED_MUTEX(r.OGRE_AUTO_MUTEX_NAME)
245            pRep = static_cast<BspLevel*>(r.getPointer());
246            pUseCount = r.useCountPointer();
247            if (pUseCount)
248            {
249                ++(*pUseCount);
250            }
251        }
252
253        /// Operator used to convert a ResourcePtr to a BspLevelPtr
254        BspLevelPtr& operator=(const ResourcePtr& r)
255        {
256            if (pRep == static_cast<BspLevel*>(r.getPointer()))
257                return *this;
258            release();
259                        // lock & copy other mutex pointer
260                        OGRE_LOCK_MUTEX(*r.OGRE_AUTO_MUTEX_NAME)
261                        OGRE_COPY_AUTO_SHARED_MUTEX(r.OGRE_AUTO_MUTEX_NAME)
262            pRep = static_cast<BspLevel*>(r.getPointer());
263            pUseCount = r.useCountPointer();
264            if (pUseCount)
265            {
266                ++(*pUseCount);
267            }
268            return *this;
269        }
270    };
271
272}
273
274#endif
Note: See TracBrowser for help on using the repository browser.