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