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 Wed Jan 21 00:10:03 2004