Main Page Namespace List Class Hierarchy Alphabetical List Compound List File List Namespace Members Compound Members File Members Related Pages

# OgreBspLevel.cpp

Go to the documentation of this file.

    00001 /*
    00002 -----------------------------------------------------------------------------
    00003 This source file is part of OGRE
    00004     (Object-oriented Graphics Rendering Engine)
    00005 For the latest info, see http://www.ogre3d.org/
    00006
    00007 Copyright © 2000-2002 The OGRE Team
    00008 Also see acknowledgements in Readme.html
    00009
    00010 This program is free software; you can redistribute it and/or modify it under
    00011 the terms of the GNU Lesser General Public License as published by the Free Software
    00012 Foundation; either version 2 of the License, or (at your option) any later
    00013 version.
    00014
    00015 This program is distributed in the hope that it will be useful, but WITHOUT
    00016 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    00017 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
    00018
    00019 You should have received a copy of the GNU Lesser General Public License along with
    00020 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
    00021 Place - Suite 330, Boston, MA 02111-1307, USA, or go to
    00022 http://www.gnu.org/copyleft/lesser.txt.
    00023 -----------------------------------------------------------------------------
    00024 */
    00025 #include "OgreBspLevel.h"
    00026 #include "OgreBspResourceManager.h"
    00027 #include "OgreException.h"
    00028 #include "OgreMaterial.h"
    00029 #include "OgreMaterialManager.h"
    00030 #include "OgreMovableObject.h"
    00031 #include "OgreSceneManager.h"
    00032 #include "OgrePatchSurface.h"
    00033 #include "OgreQuake3ShaderManager.h"
    00034 #include "OgreQuake3Shader.h"
    00035 #include "OgreMath.h"
    00036 #include "OgreStringVector.h"
    00037 #include "OgreStringConverter.h"
    00038 #include "OgreLogManager.h"
    00039 #include "OgreSceneManagerEnumerator.h"
    00040 #include "OgreTechnique.h"
    00041 #include "OgrePass.h"
    00042 #include "OgreTextureUnitState.h"
    00043
    00044
    00045 namespace Ogre {
    00046
    00047
    00048     //-----------------------------------------------------------------------
    00049     BspLevel::BspLevel(const String& name)
    00050     {
    00051         mName = name;
    00052         mRootNode = 0;
    00053         mBrushes = 0;
    00054         mVertexData = 0;
    00055         mFaceGroups = 0;
    00056         mLeafFaceGroups = 0;
    00057         mVisData.tableData = 0;
    00058     }
    00059
    00060     //-----------------------------------------------------------------------
    00061     BspLevel::~BspLevel()
    00062     {
    00063         if (mIsLoaded)
    00064         {
    00065             unload();
    00066             mIsLoaded = false;
    00067         }
    00068
    00069     }
    00070
    00071     //-----------------------------------------------------------------------
    00072     void BspLevel::load()
    00073     {
    00074         // Use Quake3 file loader
    00075         Quake3Level q3;
    00076         DataChunk chunk;
    00077         BspResourceManager::getSingleton()._findResourceData(mName, chunk);
    00078
    00079         q3.loadFromChunk(chunk);
    00080
    00081         loadQuake3Level(q3);
    00082
    00083         chunk.clear();
    00084         mIsLoaded = true;
    00085
    00086     }
    00087
    00088     //-----------------------------------------------------------------------
    00089     void BspLevel::unload()
    00090     {
    00091         if (mVertexData)
    00092             delete mVertexData;
    00093         if (mFaceGroups)
    00094             delete [] mFaceGroups;
    00095         if (mLeafFaceGroups)
    00096             delete [] mLeafFaceGroups;
    00097         if (mRootNode)
    00098             delete [] mRootNode;
    00099         if (mVisData.tableData)
    00100             delete [] mVisData.tableData;
    00101         if (mBrushes)
    00102             delete [] mBrushes;
    00103
    00104         mVertexData = 0;
    00105         mRootNode = 0;
    00106         mFaceGroups = 0;
    00107         mLeafFaceGroups = 0;
    00108         mBrushes = 0;
    00109         mVisData.tableData = 0;
    00110     }
    00111
    00112     //-----------------------------------------------------------------------
    00113     void BspLevel::loadQuake3Level(const Quake3Level& q3lvl)
    00114     {
    00115         SceneManager* sm = SceneManagerEnumerator::getSingleton().getSceneManager(ST_INTERIOR);
    00116
    00117         loadEntities(q3lvl);
    00118
    00119         // Parse shaders
    00120         Quake3ShaderManager::getSingleton().parseAllSources(".shader");
    00121         // Extract lightmaps into textures
    00122         q3lvl.extractLightmaps();
    00123
    00124         //-----------------------------------------------------------------------
    00125         // Vertices
    00126         //-----------------------------------------------------------------------
    00127         // Allocate memory for vertices & copy
    00128         mVertexData = new VertexData();
    00129
    00131         VertexDeclaration* decl = mVertexData->vertexDeclaration;
    00132         size_t offset = 0;
    00133         decl->addElement(0, offset, VET_FLOAT3, VES_POSITION);
    00134         offset += VertexElement::getTypeSize(VET_FLOAT3);
    00135         decl->addElement(0, offset, VET_FLOAT3, VES_NORMAL);
    00136         offset += VertexElement::getTypeSize(VET_FLOAT3);
    00137         decl->addElement(0, offset, VET_COLOUR, VES_DIFFUSE);
    00138         offset += VertexElement::getTypeSize(VET_COLOUR);
    00139         decl->addElement(0, offset, VET_FLOAT2, VES_TEXTURE_COORDINATES, 0);
    00140         offset += VertexElement::getTypeSize(VET_FLOAT2);
    00141         decl->addElement(0, offset, VET_FLOAT2, VES_TEXTURE_COORDINATES, 1);
    00142
    00143         // Build initial patches - we need to know how big the vertex buffer needs to be
    00144         // to accommodate the subdivision
    00145         initQuake3Patches(q3lvl, decl);
    00146
    00148         HardwareVertexBufferSharedPtr vbuf = HardwareBufferManager::getSingleton()
    00149             .createVertexBuffer(
    00150                 sizeof(BspVertex),
    00151                 q3lvl.mNumVertices + mPatchVertexCount,
    00152                 HardwareBuffer::HBU_STATIC_WRITE_ONLY);
    00153         //COPY static vertex data - Note that we can't just block-copy the vertex data because we have to reorder
    00154         //    our vertex elements; this is to ensure compatibility with older cards when using
    00155         //    hardware vertex buffers - Direct3D requires that the buffer format maps onto a
    00156         //    FVF in those older drivers.
    00157         // Lock just the non-patch area for now
    00158         BspVertex* pVert = static_cast<BspVertex*>(
    00159             vbuf->lock(0, q3lvl.mNumVertices * sizeof(BspVertex), HardwareBuffer::HBL_DISCARD) );
    00160         // Keep another base pointer for use later in patch building
    00161         for (int v = 0; v < q3lvl.mNumVertices; ++v)
    00162         {
    00163             quakeVertexToBspVertex(&q3lvl.mVertices[v], pVert++);
    00164         }
    00165         vbuf->unlock();
    00166         // Setup binding
    00167         mVertexData->vertexBufferBinding->setBinding(0, vbuf);
    00168         // Set other data
    00169         mVertexData->vertexStart = 0;
    00170         mVertexData->vertexCount = q3lvl.mNumVertices + mPatchVertexCount;
    00171
    00172         //-----------------------------------------------------------------------
    00173         // Faces
    00174         // --------
    00175         mNumLeafFaceGroups = q3lvl.mNumLeafFaces;
    00176         mLeafFaceGroups = new int[mNumLeafFaceGroups];
    00177         memcpy(mLeafFaceGroups, q3lvl.mLeafFaces, sizeof(int)*mNumLeafFaceGroups);
    00178         mNumFaceGroups = q3lvl.mNumFaces;
    00179         mFaceGroups = new StaticFaceGroup[mNumFaceGroups];
    00180         // Set up index buffer
    00181         // NB Quake3 indexes are 32-bit
    00182         // Copy the indexes into a software area for staging
    00183         mNumIndexes = q3lvl.mNumElements + mPatchIndexCount;
    00184         // Create an index buffer manually in system memory, allow space for patches
    00185         mIndexes = new DefaultHardwareIndexBuffer(
    00186             HardwareIndexBuffer::IT_32BIT,
    00187             mNumIndexes,
    00188             HardwareBuffer::HBU_DYNAMIC);
    00189         // Write main indexes
    00190         mIndexes->writeData(0, sizeof(unsigned int) * q3lvl.mNumElements, q3lvl.mElements, true);
    00191
    00192         // now build patch information
    00193         buildQuake3Patches(q3lvl.mNumVertices, q3lvl.mNumElements);
    00194
    00195         //-----------------------------------------------------------------------
    00196         // Create materials for shaders
    00197         //-----------------------------------------------------------------------
    00198         // NB this only works for the 'default' shaders for now
    00199         //  i.e. those that don't have a .shader script and thus default
    00200         //  to just texture + lightmap
    00201         // TODO: pre-parse all .shader files and create lookup for next stage (use ROGL shader_file_t)
    00202
    00203         // Material names are shadername#lightmapnumber
    00204         // This is because I like to define materials up front completely
    00205         //  rather than combine lightmap and shader dynamically (it's
    00206         //  more generic). It results in more materials, but they're small
    00207         //  beer anyway. Texture duplication is prevented by infrastructure.
    00208         // To do this I actually need to parse the faces since they have the
    00209         //  shader/lightmap combo (lightmap number is not in the shader since
    00210         //  it can be used with multiple lightmaps)
    00211         char shaderName[256];
    00212         int face;
    00213         face = q3lvl.mNumFaces;
    00214         int matHandle;
    00215         String meshName;
    00216
    00217         while(face--)
    00218         {
    00219
    00220             // Check to see if existing material
    00221             // Format shader#lightmap
    00222             int shadIdx = q3lvl.mFaces[face].shader;
    00223             sprintf(shaderName, "%s#%d",
    00224                 q3lvl.mShaders[shadIdx].name,
    00225                 q3lvl.mFaces[face].lm_texture);
    00226
    00227             Material *shadMat = sm->getMaterial(shaderName);
    00228             if (shadMat == 0)
    00229             {
    00230                 // Build new material
    00231
    00232                 // Colour layer
    00233                 // NB no extension in Q3A(doh), have to try shader, .jpg, .tga
    00234                 String tryName = q3lvl.mShaders[shadIdx].name;
    00235                 // Try shader first
    00236                 Quake3Shader* pShad = (Quake3Shader*)Quake3ShaderManager::getSingleton().getByName(tryName);
    00237                 if (pShad)
    00238                 {
    00239                     shadMat = pShad->createAsMaterial(sm, q3lvl.mFaces[face].lm_texture);
    00240                 }
    00241                 else
    00242                 {
    00243                     // No shader script, try default type texture
    00244                     shadMat = sm->createMaterial(shaderName);
    00245                     Pass *shadPass = shadMat->getTechnique(0)->getPass(0);
    00246                     // Try jpg
    00247                     TextureUnitState* tex = shadPass->createTextureUnitState(tryName + ".jpg");
    00248                     tex->_load();
    00249                     if (tex->isBlank())
    00250                     {
    00251                         // Try tga
    00252                         tex->setTextureName(tryName + ".tga");
    00253                     }
    00254                     // Set replace on all first layer textures for now
    00255                     tex->setColourOperation(LBO_REPLACE);
    00256                     tex->setTextureAddressingMode(TextureUnitState::TAM_WRAP);
    00257
    00258                     if (q3lvl.mFaces[face].lm_texture != -1)
    00259                     {
    00260                         // Add lightmap, additive blending
    00261                         char lightmapName[16];
    00262                         sprintf(lightmapName, "@lightmap%d",q3lvl.mFaces[face].lm_texture);
    00263                         tex = shadPass->createTextureUnitState(lightmapName);
    00264                         // Blend
    00265                         tex->setColourOperation(LBO_MODULATE);
    00266                         // Use 2nd texture co-ordinate set
    00267                         tex->setTextureCoordSet(1);
    00268                         // Clamp
    00269                         tex->setTextureAddressingMode(TextureUnitState::TAM_CLAMP);
    00270
    00271                     }
    00272                     // Set culling mode to none
    00273                     shadMat->setCullingMode(CULL_NONE);
    00274                     // No dynamic lighting
    00275                     shadMat->setLightingEnabled(false);
    00276
    00277                 }
    00278             }
    00279             matHandle = shadMat->getHandle();
    00280             shadMat->load();
    00281
    00282             // Copy face data
    00283             StaticFaceGroup* dest = &mFaceGroups[face];
    00284             bsp_face_t* src = &q3lvl.mFaces[face];
    00285
    00286             if (q3lvl.mShaders[src->shader].surface_flags & SURF_SKY)
    00287             {
    00288                 dest->isSky = true;
    00289             }
    00290             else
    00291             {
    00292                 dest->isSky = false;
    00293             }
    00294
    00295
    00296             dest->materialHandle = matHandle;
    00297             dest->elementStart = src->elem_start;
    00298             dest->numElements = src->elem_count;
    00299             dest->numVertices = src->vert_count;
    00300             dest->vertexStart = src->vert_start;
    00301             if (src->type == BSP_FACETYPE_NORMAL)
    00302             {
    00303                 dest->fType = FGT_FACE_LIST;
    00304                 // Assign plane
    00305                 dest->plane.normal = Vector3(src->normal);
    00306                 dest->plane.d = -dest->plane.normal.dotProduct(Vector3(src->org));
    00307
    00308                 // Don't rebase indexes here - Quake3 re-uses some indexes for multiple vertex
    00309                 // groups eg repeating small details have the same relative vertex data but
    00310                 // use the same index data.
    00311
    00312             }
    00313             else if (src->type == BSP_FACETYPE_PATCH)
    00314             {
    00315                 // Seems to be some crap in the Q3 level where vertex count = 0 or num control points = 0?
    00316                 if (dest->numVertices == 0 || src->mesh_cp[0] == 0)
    00317                 {
    00318                     dest->fType = FGT_UNKNOWN;
    00319                 }
    00320                 else
    00321                 {
    00322
    00323                     // Set up patch surface
    00324                     dest->fType = FGT_PATCH;
    00325
    00326                     // Locate the patch we already built
    00327                     PatchMap::iterator p = mPatches.find(face);
    00328                     if (p == mPatches.end())
    00329                     {
    00330                         Except(Exception::ERR_INTERNAL_ERROR, "Patch not found from previous built state",
    00331                         "BspLevel::loadQuake3Level");
    00332                     }
    00333
    00334                     dest->patchSurf = p->second;
    00335
    00336                 }
    00337
    00338
    00339             }
    00340             else if (src->type == BSP_FACETYPE_MESH)
    00341             {
    00342                 dest->fType = FGT_FACE_LIST;
    00343                 // Assign plane
    00344                 dest->plane.normal = Vector3(src->normal);
    00345                 dest->plane.d = -dest->plane.normal.dotProduct(Vector3(src->org));
    00346             }
    00347             else
    00348             {
    00349                 LogManager::getSingleton().logMessage("!!! Unknown Face Type !!!", LML_CRITICAL);
    00350             }
    00351
    00352
    00353         }
    00354
    00355         //-----------------------------------------------------------------------
    00356         // Nodes
    00357         //-----------------------------------------------------------------------
    00358         // Allocate memory for all nodes (leaves and splitters)
    00359         mNumNodes = q3lvl.mNumNodes + q3lvl.mNumLeaves;
    00360         mNumLeaves = q3lvl.mNumLeaves;
    00361         mLeafStart = q3lvl.mNumNodes;
    00362         mRootNode = new BspNode[mNumNodes];
    00363         int i;
    00364         // Convert nodes
    00365         // In our array, first q3lvl.mNumNodes are non-leaf, others are leaves
    00366         for (i = 0; i < q3lvl.mNumNodes; ++i)
    00367         {
    00368             BspNode* node = &mRootNode[i];
    00369             bsp_node_t* q3node = &q3lvl.mNodes[i];
    00370
    00371             // Set non-leaf
    00372             node->mIsLeaf = false;
    00373             // Set owner
    00374             node->mOwner = this;
    00375             // Set plane
    00376             node->mSplitPlane.normal = Vector3(q3lvl.mPlanes[q3node->plane].normal);
    00377             node->mSplitPlane.d = -q3lvl.mPlanes[q3node->plane].dist;
    00378             // Set bounding box
    00379             node->mBounds.setMinimum(Vector3(&q3node->bbox[0]));
    00380             node->mBounds.setMaximum(Vector3(&q3node->bbox[3]));
    00381             // Set back pointer
    00382             // Negative indexes in Quake3 mean leaves
    00383             if (q3node->back < 0)
    00384             {
    00385                 // Points to leaf, offset to leaf start and negate index
    00386                 node->mBack = &mRootNode[mLeafStart + (~(q3node->back))];
    00387
    00388             }
    00389             else
    00390             {
    00391                 // Points to node
    00392                 node->mBack = &mRootNode[q3node->back];
    00393             }
    00394             // Set front pointer
    00395             // Negative indexes in Quake3 mean leaves
    00396             if (q3node->front < 0)
    00397             {
    00398                 // Points to leaf, offset to leaf start and negate index
    00399                 node->mFront = &mRootNode[mLeafStart + (~(q3node->front))];
    00400
    00401             }
    00402             else
    00403             {
    00404                 // Points to node
    00405                 node->mFront = &mRootNode[q3node->front];
    00406             }
    00407
    00408
    00409         }
    00410         //-----------------------------------------------------------------------
    00411         // Brushes
    00412         //-----------------------------------------------------------------------
    00413         // Reserve enough memory for all brushes, solid or not (need to maintain indexes)
    00414         mBrushes = new BspNode::Brush[q3lvl.mNumBrushes];
    00415         for (i = 0; i < q3lvl.mNumBrushes; ++i)
    00416         {
    00417             bsp_brush_t* q3brush = &q3lvl.mBrushes[i];
    00418
    00419             // Create a new OGRE brush
    00420             BspNode::Brush *pBrush = &(mBrushes[i]);
    00421             int brushSideIdx, numBrushSides;
    00422             numBrushSides = q3brush->numsides;
    00423             brushSideIdx = q3brush->firstside;
    00424             // Iterate over the sides and create plane for each
    00425             while (numBrushSides--)
    00426             {
    00427                 bsp_brushside_t* q3brushside = &q3lvl.mBrushSides[brushSideIdx];
    00428                 bsp_plane_t* q3brushplane = &q3lvl.mPlanes[q3brushside->planenum];
    00429                 // Notice how we normally invert Q3A plane distances, but here we do not
    00430                 // Because we want plane normals pointing out of solid brushes, not in
    00431                 Plane brushSide(Vector3(q3brushplane->normal), q3brushplane->dist);
    00432                 pBrush->planes.push_back(brushSide);
    00433                 ++brushSideIdx;
    00434             }
    00435             // Build world fragment
    00436             pBrush->fragment.fragmentType = SceneQuery::WFT_PLANE_BOUNDED_REGION;
    00437             pBrush->fragment.planes = &(pBrush->planes);
    00438
    00439         }
    00440
    00441
    00442
    00443         //-----------------------------------------------------------------------
    00444         // Leaves
    00445         //-----------------------------------------------------------------------
    00446         for (i = 0; i < q3lvl.mNumLeaves; ++i)
    00447         {
    00448             BspNode* node = &mRootNode[i + mLeafStart];
    00449             bsp_leaf_t* q3leaf = &q3lvl.mLeaves[i];
    00450
    00451             // Set leaf
    00452             node->mIsLeaf = true;
    00453             // Set owner
    00454             node->mOwner = this;
    00455             // Set bounding box
    00456             node->mBounds.setMinimum(Vector3(&q3leaf->bbox[0]));
    00457             node->mBounds.setMaximum(Vector3(&q3leaf->bbox[3]));
    00458             // Set faces
    00459             node->mFaceGroupStart = q3leaf->face_start;
    00460             node->mNumFaceGroups = q3leaf->face_count;
    00461
    00462             node->mVisCluster = q3leaf->cluster;
    00463
    00464             // Load Brushes for this leaf
    00465             int brushIdx, brushCount, realBrushIdx;
    00466             brushCount = q3leaf->brush_count;
    00467             brushIdx = q3leaf->brush_start;
    00468
    00469             while(brushCount--)
    00470             {
    00471                 realBrushIdx = q3lvl.mLeafBrushes[brushIdx];
    00472                 bsp_brush_t* q3brush = &q3lvl.mBrushes[realBrushIdx];
    00473                 // Only load solid ones, we don't care about any other types
    00474                 // Shader determines this
    00475                 bsp_shader_t* brushShader = &q3lvl.mShaders[q3brush->shaderIndex];
    00476                 if (brushShader->content_flags & CONTENTS_SOLID)
    00477                 {
    00478                     // Get brush
    00479                     BspNode::Brush *pBrush = &(mBrushes[realBrushIdx]);
    00480                     assert(pBrush->fragment.fragmentType == SceneQuery::WFT_PLANE_BOUNDED_REGION);
    00481                     // Assign node pointer
    00482                     node->mSolidBrushes.push_back(pBrush);
    00483                 }
    00484                 ++brushIdx;
    00485             }
    00486
    00487         }
    00488
    00489
    00490
    00491         // Vis - just copy
    00492         mVisData.numClusters = q3lvl.mVis->cluster_count;
    00493         mVisData.rowLength = q3lvl.mVis->row_size;
    00494         mVisData.tableData = new unsigned char[q3lvl.mVis->row_size * q3lvl.mVis->cluster_count];
    00495         memcpy(mVisData.tableData, q3lvl.mVis->data, q3lvl.mVis->row_size * q3lvl.mVis->cluster_count);
    00496
    00497
    00498
    00499     }
    00500
    00501     //-----------------------------------------------------------------------
    00502     void BspLevel::initQuake3Patches(const Quake3Level & q3lvl, VertexDeclaration* decl)
    00503     {
    00504         int face;
    00505
    00506         mPatchVertexCount = 0;
    00507         mPatchIndexCount = 0;
    00508
    00509         // We're just building the patch here to get a hold on the size of the mesh
    00510         // although we'll reuse this information later
    00511         face = q3lvl.mNumFaces;
    00512         while (face--)
    00513         {
    00514
    00515             bsp_face_t* src = &q3lvl.mFaces[face];
    00516
    00517             if (src->type == BSP_FACETYPE_PATCH)
    00518             {
    00519                 // Seems to be some crap in the Q3 level where vertex count = 0 or num control points = 0?
    00520                 if (src->vert_count == 0 || src->mesh_cp[0] == 0)
    00521                 {
    00522                     continue;
    00523                 }
    00524                 PatchSurface* ps = new PatchSurface();
    00525                 // Set up control points & format
    00526                 // Reuse the vertex declaration
    00527                 // Copy control points into a buffer so we can convert their format
    00528                 BspVertex* pControlPoints = new BspVertex[src->vert_count];
    00529                 bsp_vertex_t* pSrc = q3lvl.mVertices + src->vert_start;
    00530                 for (int v = 0; v < src->vert_count; ++v)
    00531                 {
    00532                     quakeVertexToBspVertex(pSrc++, &pControlPoints[v]);
    00533                 }
    00534                 // Define the surface, but don't build it yet (no vertex / index buffer)
    00535                 ps->defineSurface(
    00536                     pControlPoints,
    00537                     decl,
    00538                     src->mesh_cp[0],
    00539                     src->mesh_cp[1],
    00540                     PatchSurface::PST_BEZIER);
    00541                 // Get stats
    00542                 mPatchVertexCount += ps->getRequiredVertexCount();
    00543                 mPatchIndexCount += ps->getRequiredIndexCount();
    00544
    00545                 // Save the surface for later
    00546                 mPatches[face] = ps;
    00547             }
    00548
    00549
    00550         }
    00551
    00552     }
    00553     //-----------------------------------------------------------------------
    00554     void BspLevel::buildQuake3Patches(size_t vertOffset, size_t indexOffset)
    00555     {
    00556         // Loop through the patches
    00557         PatchMap::iterator i, iend;
    00558         iend = mPatches.end();
    00559
    00560         size_t currVertOffset = vertOffset;
    00561         size_t currIndexOffset = indexOffset;
    00562
    00563         HardwareVertexBufferSharedPtr vbuf = mVertexData->vertexBufferBinding->getBuffer(0);
    00564
    00565         for (i = mPatches.begin(); i != iend; ++i)
    00566         {
    00567             PatchSurface* ps = i->second;
    00568
    00569             ps->build(vbuf, currVertOffset, mIndexes, currIndexOffset);
    00570
    00571             // No need for control points anymore
    00572             BspVertex* pCP = static_cast<BspVertex*>(ps->getControlPointBuffer());
    00573             delete [] pCP;
    00574             ps->notifyControlPointBufferDeallocated();
    00575
    00576             currVertOffset += ps->getRequiredVertexCount();
    00577             currIndexOffset += ps->getRequiredIndexCount();
    00578
    00579         }
    00580     }
    00581     //-----------------------------------------------------------------------
    00582     bool BspLevel::isLeafVisible(const BspNode* from, const BspNode* to) const
    00583     {
    00584         if (to->mVisCluster == -1)
    00585             return false;
    00586         if (from->mVisCluster == -1)
    00587             // Camera outside world?
    00588             return true;
    00589
    00590
    00591         if (!from->isLeaf() || !to->isLeaf())
    00592             throw Exception(Exception::ERR_INVALIDPARAMS,
    00593                 "Both nodes must be leaf nodes for visibility testing.",
    00594                 "BspLevel::isLeafVisible");
    00595
    00596         // Use PVS to determine visibility
    00597
    00598         /*
    00599         // In wordier terms, the fairly cryptic (but fast) version is doing this:
    00600         //   Could make it a macro for even more speed?
    00601
    00602         // Row offset = from cluster number * row size
    00603         int offset = from->mVisCluster*mVisData.rowLength;
    00604
    00605         // Column offset (in bytes) = to cluster number divided by 8 (since 8 bits per bytes)
    00606         offset += to->mVisCluster >> 3;
    00607
    00608         // Get the right bit within the byte, i.e. bitwise 'and' with bit at remainder position
    00609         int result = *(mVisData.tableData + offset) & (1 << (to->mVisCluster & 7));
    00610
    00611         return (result != 0);
    00612         */
    00613
    00614         //return ((*(mVisData.tableData + from->mVisCluster * mVisData.rowLength +
    00615         //           ((to->mVisCluster)>>3)) & (1 << ((to->mVisCluster) & 7))) != 0);
    00616
    00617         return (*(mVisData.tableData + from->mVisCluster*mVisData.rowLength +
    00618                    ((to->mVisCluster)>>3)) & (1 << ((to->mVisCluster) & 7))) != 0;
    00619
    00620     }
    00621     //-----------------------------------------------------------------------
    00622     const BspNode* BspLevel::getRootNode(void)
    00623     {
    00624         return mRootNode;
    00625     }
    00626     //-----------------------------------------------------------------------
    00627     BspNode* BspLevel::findLeaf(const Vector3& point) const
    00628     {
    00629         BspNode* node = mRootNode;
    00630
    00631         while (!node->isLeaf())
    00632         {
    00633             node = node->getNextNode(point);
    00634         }
    00635
    00636         return node;
    00637
    00638     }
    00639     //-----------------------------------------------------------------------
    00640     void BspLevel::loadEntities(const Quake3Level& q3lvl)
    00641     {
    00642         char* strEnt;
    00643         String line;
    00644         StringVector vecparams;
    00645         Vector3 origin;
    00646         Radian angle ( 0 );
    00647         size_t pos;
    00648         char* lineend;
    00649         bool isPlayerStart;
    00650
    00651         isPlayerStart = false;
    00652         strEnt = (char*)q3lvl.mEntities;
    00653
    00654         lineend = strchr(strEnt, '\n');
    00655         while (lineend != 0)
    00656         {
    00657             *lineend = '\0';
    00658             line = strEnt;
    00659             strEnt = lineend+1;
    00660             StringUtil::trim(line);
    00661             if (line.length() > 0)
    00662             {
    00663                 StringUtil::toLowerCase(line);
    00664                 // Remove quotes
    00665                 while( ( pos = line.find("\"",0) ) != String::npos )
    00666                 {
    00667                     line = line.substr(0,pos) + line.substr(pos+1,line.length()-(pos+1));
    00668                 }
    00669                 vecparams = StringUtil::split(line);
    00670                 StringVector::iterator params = vecparams.begin();
    00671
    00672                 if (params[0] == "origin")
    00673                 {
    00674                     origin.x = atof(params[1].c_str());
    00675                     origin.y = atof(params[2].c_str());
    00676                     origin.z = atof(params[3].c_str());
    00677                 }
    00678                 if (params[0] == "angle")
    00679                 {
    00680                     angle = Degree(atof(params[1].c_str()));
    00681                 }
    00682                 if (params[0] == "classname" && params[1] == "info_player_deathmatch")
    00683                 {
    00684                     isPlayerStart = true;
    00685                 }
    00686                 if (params[0] == "}")
    00687                 {
    00688                     if (isPlayerStart)
    00689                     {
    00690                         // Save player start
    00691                         ViewPoint vp;
    00692                         vp.position = origin;
    00693                         vp.orientation.FromAngleAxis(angle, Vector3::UNIT_Z);
    00694                         mPlayerStarts.push_back(vp);
    00695                     }
    00696                     isPlayerStart = false;
    00697                 }
    00698             }
    00699
    00700             lineend = strchr(strEnt, '\n');
    00701         }
    00702
    00703
    00704     }
    00705     //-----------------------------------------------------------------------
    00706     void BspLevel::_notifyObjectMoved(const MovableObject* mov,
    00707             const Vector3& pos)
    00708     {
    00709
    00710         // Locate any current nodes the object is supposed to be attached to
    00711         MovableToNodeMap::iterator i = mMovableToNodeMap.find(mov);
    00712         if (i != mMovableToNodeMap.end())
    00713         {
    00714             std::list<BspNode*>::iterator nodeit, nodeitend;
    00715             nodeitend = i->second.end();
    00716             for (nodeit = i->second.begin(); nodeit != nodeitend; ++nodeit)
    00717             {
    00718                 // Tell each node
    00719                 (*nodeit)->_removeMovable(mov);
    00720             }
    00721             // Clear the existing list of nodes because we'll reevaluate it
    00722             i->second.clear();
    00723         }
    00724
    00725         tagNodesWithMovable(mRootNode, mov, pos);
    00726     }
    00727     //-----------------------------------------------------------------------
    00728     void BspLevel::tagNodesWithMovable(BspNode* node, const MovableObject* mov,
    00729         const Vector3& pos)
    00730     {
    00731         if (node->isLeaf())
    00732         {
    00733             // Add to movable->node map
    00734             // Insert all the time, will get current if already there
    00735             std::pair<MovableToNodeMap::iterator, bool> p =
    00736                 mMovableToNodeMap.insert(
    00737                 MovableToNodeMap::value_type(mov, std::list<BspNode*>()));
    00738
    00739             p.first->second.push_back(node);
    00740
    00741             // Add movable to node
    00742             node->_addMovable(mov);
    00743
    00744         }
    00745         else
    00746         {
    00747             // Find distance to dividing plane
    00748             Real dist = node->getDistance(pos);
    00749             if (Math::Abs(dist) < mov->getBoundingRadius())
    00750             {
    00751                 // Bounding sphere crosses the plane, do both
    00752                 tagNodesWithMovable(node->getBack(), mov, pos);
    00753                 tagNodesWithMovable(node->getFront(), mov, pos);
    00754             }
    00755             else if (dist < 0)
    00756             {    //-----------------------------------------------------------------------
    00757
    00758                 // Do back
    00759                 tagNodesWithMovable(node->getBack(), mov, pos);
    00760             }
    00761             else
    00762             {
    00763                 // Do front
    00764                 tagNodesWithMovable(node->getFront(), mov, pos);
    00765             }
    00766         }
    00767     }
    00768     //-----------------------------------------------------------------------
    00769     void BspLevel::_notifyObjectDetached(const MovableObject* mov)
    00770     {
    00771         // Locate any current nodes the object is supposed to be attached to
    00772         MovableToNodeMap::iterator i = mMovableToNodeMap.find(mov);
    00773         if (i != mMovableToNodeMap.end())
    00774         {
    00775             std::list<BspNode*>::iterator nodeit, nodeitend;
    00776             nodeitend = i->second.end();
    00777             for (nodeit = i->second.begin(); nodeit != nodeitend; ++nodeit)
    00778             {
    00779                 // Tell each node
    00780                 (*nodeit)->_removeMovable(mov);
    00781             }
    00782             // delete the entry for this MovableObject
    00783             mMovableToNodeMap.erase(i);
    00784         }
    00785     }
    00786     //-----------------------------------------------------------------------
    00787     void BspLevel::quakeVertexToBspVertex(const bsp_vertex_t* src, BspVertex* dest)
    00788     {
    00789         memcpy(dest->position, src->point, sizeof(Real) * 3);
    00790         memcpy(dest->normal, src->normal,  sizeof(Real) * 3);
    00791         dest->colour = src->color;
    00792         dest->texcoords[0]  = src->texture[0];
    00793         dest->texcoords[1]  = src->texture[1];
    00794         dest->lightmap[0]  = src->lightmap[0];
    00795         dest->lightmap[1]  = src->lightmap[1];
    00796     }
    00797 }

Copyright © 2002-2003 by The OGRE Team
Last modified Sun Nov 28 19:48:16 2004