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         Real 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             line.trim();
00661             if (line.length() > 0)
00662             {
00663                 line = line.toLowerCase();
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 = line.split();
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 = 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(Math::DegreesToRadians(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 Fri May 14 23:21:55 2004