void Quake3BSP_GL::RenderLevel(unsigned int bufferID) { // Get the number of faces in our level int i = m_numOfLeafs; int leafIndex; if(!Camera::GetInstance().getVisibilityState()){ // Finding the leaf the camera is in m_cameraPos = Camera::GetInstance().GetCamEye(); leafIndex = FindLeaf(0,m_cameraPos); // Once the leaf is found, reset the bools for leaf searching m_foundLeaf=false; m_foundIndex=0; } else { // We are in a frozen state for visibility, so use the last stored camera position, // don't get the updated one. leafIndex = FindLeaf(0,m_cameraPos); // Once the leaf is found, reset the bools for leaf searching m_foundLeaf=false; m_foundIndex=0; } // Getting the cluster that leaf is assigned to int cluster = m_pLeafs[leafIndex].cluster; // Go through the BSP tree checking to draw only what is visible from our // current cluster and what is visible within the frustum while(i--) { // Getting the current leaf to check with our camera's leaf BSPLeaf *pLeaf = &(m_pLeafs[i]); // Cluster Visiblity check if(!IsClusterValid(cluster, pLeaf->cluster)) continue; // Frustum visibility check if(!ViewFrustum::GetInstance().RectangleIntersect((float)pLeaf->min.x, (float)pLeaf->min.y, (float)pLeaf->min.z, (float)pLeaf->max.x, (float)pLeaf->max.y, (float)pLeaf->max.z)){ continue; } // The leaf must be valid to draw, set the counter for his number // of faces, then call RenderFaces to draw them all. int faceTotal = pLeaf->numOfLeafFaces; // Loop through and render all of the faces in this leaf while(faceTotal--) { int faceIndex = m_pLeafFaces[pLeaf->leafface + faceTotal]; // Check if this is a valid face to draw if(m_pFaces[faceIndex].type != FACE_POLYGON) continue; RenderFace(bufferID, faceIndex); } } }
status_t SNode::RenameEntry(const SString& name, const SString& rename) const { if (name.FindFirst(*name.PathDelimiter()) < 0) { if (m_catalog != NULL) return m_catalog->RenameEntry(name, rename); get_catalog(); return (m_catalog != NULL) ? m_catalog->RenameEntry(name, rename) : B_UNSUPPORTED; } SString parentName,parentRename; name.PathGetParent(&parentName); rename.PathGetParent(&parentRename); if (parentName != parentRename) { /* We don't "yet" support renaming (really moving) entries across different nodes. */ return B_UNSUPPORTED; } sptr<INode> node = m_node; SString path(name); if (node != NULL) { status_t err = FindLeaf(&node,&path); if (err != B_OK) return err; sptr<ICatalog> catalog = ICatalog::AsInterface(m_node->AsBinder()); return (catalog != NULL) ? catalog->RenameEntry(path, SString(rename.PathLeaf())) : B_UNSUPPORTED; } return B_UNSUPPORTED; // We don't yet support renaming values in an SValue... }
//===================================================================================== // PlaceEntities //===================================================================================== geBoolean PlaceEntities(GBSP_Node *RootNode) { int32 i; GBSP_Node *Node; geBoolean Empty; Empty = GE_FALSE; for (i=1; i< NumEntities; i++) { if (!(Entities[i].Flags & ENTITY_HAS_ORIGIN)) // No "Origin" in entity continue; Node = FindLeaf(RootNode, &Entities[i].Origin); if (!Node) return GE_FALSE; if (!(Node->Contents & BSP_CONTENTS_SOLID2)) { Node->Entity = i; Empty = GE_TRUE; } } if (!Empty) { GHook.Error("PlaceEntities: No valid entities for operation %i.\n", NumEntities); return GE_FALSE; } return GE_TRUE; }
//===================================================================================== // FillFromEntities //===================================================================================== geBoolean FillFromEntities(GBSP_Node *RootNode) { int32 i; GBSP_Node *Node; geBoolean Empty; Empty = GE_FALSE; for (i=1; i< NumEntities; i++) // Don't use the world as an entity (skip 0)!! { if (!(Entities[i].Flags & ENTITY_HAS_ORIGIN)) // No "Origin" in entity continue; Node = FindLeaf(RootNode, &Entities[i].Origin); if (Node->Contents & BSP_CONTENTS_SOLID2) continue; // There is at least one entity in empty space... Empty = GE_TRUE; if (!FillLeafs2_r(Node)) return GE_FALSE; } if (!Empty) { GHook.Error("FillFromEntities: No valid entities for operation.\n"); return GE_FALSE; } return GE_TRUE; }
t_rc INXM_IndexHandle::InsertEntry(void *pData, const REM_RecordID &rid) { t_rc rc; /* Tree does not exist yet. * Start a new tree. */ if (this->inxmFileHeader.treeRoot == 0) { return StartNewTree(pData, rid); } /* If tree already exists. */ /* If key exists, append. */ rc = FindAndAppend(this->inxmFileHeader.treeRoot, pData, rid); if (rc == OK) { return rc; } /* Else add new node and data to b+ tree. */ STORM_PageHandle leafPageHandle; rc = FindLeaf(this->inxmFileHeader.treeRoot, pData, leafPageHandle); if (rc != OK) { return rc; } /* Case: leaf has room for key and pointer. */ if (LeafHasRoom(leafPageHandle)) { return InsertIntoLeaf(leafPageHandle, pData, rid); } /* Case: leaf must be split. */ return InsertIntoLeafAfterSplitting(this->inxmFileHeader.treeRoot, leafPageHandle, pData, rid); return(OK); }
void CQuake3BSP::RenderLevel(const CVector3 &vPos) { // Reset our bitset so all the slots are zero. m_FacesDrawn.ClearAll(); // Grab the leaf index that our camera is in int leafIndex = FindLeaf(vPos); // Grab the cluster that is assigned to the leaf int cluster = m_pLeafs[leafIndex].cluster; // Initialize our counter variables (start at the last leaf and work down) int i = m_numOfLeafs; g_VisibleFaces = 0; // Go through all the leafs and check their visibility while(i--) { // Get the current leaf that is to be tested for visibility from our camera's leaf tBSPLeaf *pLeaf = &(m_pLeafs[i]); // If the current leaf can't be seen from our cluster, go to the next leaf if(!IsClusterVisible(cluster, pLeaf->cluster)) continue; // If the current leaf is not in the camera's frustum, go to the next leaf if(!g_Frustum.BoxInFrustum((float)pLeaf->min.x, (float)pLeaf->min.y, (float)pLeaf->min.z, (float)pLeaf->max.x, (float)pLeaf->max.y, (float)pLeaf->max.z)) continue; // If we get here, the leaf we are testing must be visible in our camera's view. // Get the number of faces that this leaf is in charge of. int faceCount = pLeaf->numOfLeafFaces; // Loop through and render all of the faces in this leaf while(faceCount--) { // Grab the current face index from our leaf faces array int faceIndex = m_pLeafFaces[pLeaf->leafface + faceCount]; // Before drawing this face, make sure it's a normal polygon if(m_pFaces[faceIndex].type != FACE_POLYGON) continue; // Since many faces are duplicated in other leafs, we need to // make sure this face already hasn't been drawn. if(!m_FacesDrawn.On(faceIndex)) { // Increase the rendered face count to display for fun g_VisibleFaces++; // Set this face as drawn and render it m_FacesDrawn.Set(faceIndex); RenderFace(faceIndex); } } } }
void FindLeaf(std::ostream& output, Tree& node, Graph& g) { if((node.m_son == NULL) || (node.m_weight == -1)) output << " {\"leaf\":" << g.m_switch[node.m_id] << "},\n"; Tree* son = node.m_son; while(son != NULL) { FindLeaf(output, *son, g); son = son->m_brother; } }
void showLeaf(BinTree bt) { int i,j; BinTree p[16]; FindLeaf(bt,p); for(i=0;p[i];i++) { j=0; while(p[i]!=BTXY[j].bt&&j<31)j++; SignFilledCircle(BTXY[j].x,BTXY[j].y,BTXY[j].bt->data); delay(200); } }
static u_long * FindCounter( struct dyn_counter **ppdc, u_long ix, int fcreate) { struct dyn_counter *pdc; struct node *pnode; u_long *pcounter; if (ldebug) fprintf(stderr,"FindCounter(p, %lu) called\n", ix); /* if the counter tree doesn't exist yet, create it */ if (*ppdc == NULL) { *ppdc = MakeCounterStruct(); } pdc = *ppdc; /* track MAX and MIN */ if (ix > pdc->maxix) pdc->maxix = ix; if (ix < pdc->minix) pdc->minix = ix; if (ldebug>1) PrintTree(pdc->tree); /* scale (TRUNCATE) the index by the granularity */ ix /= (*ppdc)->gran; /* find the leaf node */ pnode = FindLeaf(pdc, &pdc->tree, pdc->tree?pdc->tree->depth:1, ix, fcreate); if (pnode == NULL) return(NULL); /* find the right counter */ pcounter = FindTwig(pnode, ix); return(pcounter); }
status_t SNode::RemoveEntry(const SString& name) const { if (name.FindFirst(*name.PathDelimiter()) < 0) { if (m_catalog != NULL) return m_catalog->RemoveEntry(name); get_catalog(); return (m_catalog != NULL) ? m_catalog->RemoveEntry(name) : B_UNSUPPORTED; } sptr<INode> node = m_node; SString path(name); if (node != NULL) { status_t err = FindLeaf(&node,&path); if (err != B_OK) return err; sptr<ICatalog> catalog = ICatalog::AsInterface(m_node->AsBinder()); return (catalog != NULL) ? catalog->RemoveEntry(path) : B_UNSUPPORTED; } return B_UNSUPPORTED; // We don't yet support removing values in an SValue... }
/* the heart of the routines, a 10-ary recursize search */ static struct node * FindLeaf( struct dyn_counter *pdc, struct node **ptree, u_long depth, u_long value, int fcreate) { u_long hidigit; u_long lowdigits; u_long valdepth; u_long valunits; u_long temp_value; if (ldebug) fprintf(stderr,"FindLeaf(%p(depth %lu), %lu, %s) called\n", *ptree, *ptree?((*ptree)->depth):0, value, fcreate?"CREATE":"NOCREATE"); /* if the tree is empty and we haven't asked to "create", then not found */ if ((*ptree == NULL) && (!fcreate)) return(NULL); /* determine the units of the MSDigit (the depth) */ valdepth = 1; valunits = 1; temp_value = value; while (temp_value >= CARDINALITY) { temp_value /= CARDINALITY; ++valdepth; valunits *= CARDINALITY; } if (ldebug) fprintf(stderr,"FindLeaf: value:%lu depth:%lu units:%lu\n", value, valdepth, valunits); /* is the tree deep enough? */ if ((*ptree == NULL) || (valdepth > (*ptree)->depth)) { u_long correct_depth; /* the correct depth is the MAX of: */ /* - the depth of the number we're looking for */ /* - the value of "depth" passed down */ correct_depth = depth; if (valdepth > correct_depth) correct_depth = valdepth; /* if the tree isn't that deep and we haven't asked to create, then not found */ if (!fcreate) return(NULL); /* increase the depth of this branch */ *ptree = MakeDepth((*ptree), correct_depth); /* linked list of leaves no longer valid! */ pdc->firstleaf = NULL; /* adjust */ depth = correct_depth; } /* if we're at the leaf depth, then we're done */ if ((*ptree)->depth == 1) return(*ptree); /* if the "depth" of val is less than the depth of this node, recurse down the "0" branch without changing the number */ if (valdepth < (*ptree)->depth) { return(FindLeaf(pdc, &(*ptree)->un.down[0], depth-1, value, fcreate)); } /* (else), already the correct level */ /* break the number into the MSDigit and LSDigits */ hidigit = value / valunits; lowdigits = value % valunits; if (ldebug) fprintf(stderr,"for value %lu, depth:%lu units:%lu hidigit:%lu lowdigits:%lu\n", value, valdepth, valunits, hidigit, lowdigits); /* recurse */ return(FindLeaf(pdc, &(*ptree)->un.down[hidigit], depth-1, lowdigits, fcreate)); }
int Quake3BSP_GL::FindLeaf(int nodeIndex, const Vector &vPos) { float distance = 0.0f; int currentIndex = 0; // This is the recursive function to sort through our BSP tree and find which leaf // the camera is residing in. Ideally, we would want to optimize our search by // checking the camera direction with the plane normal, thus reducing more checks // but for the moment, we'll just check the position with the splitting planes // to decide which side of the node we are on till we reach the leaf. Node side indexes // are always positive, but for a leaf, it's negative, which is our indicator we are at a // leaf, not another node, so we'll check that first, which would end the recursion. if(nodeIndex < 0 ){ return nodeIndex; } else { // Still have not found the leaf, keep looking. First we get the node, and it's splitter plane. // From there, we check the distance from the camera position to the splitter plane. So, // if it is positive, we are on the front of the plane, negative, back of the plane. const BSPNode& node = m_pNodes[nodeIndex]; const BSPPlane& plane = m_pPlanes[node.plane]; // Plane equation to check distance. distance = plane.vNormal.x * vPos.x + plane.vNormal.y * vPos.y + plane.vNormal.z * vPos.z - plane.d; // Camera in front of the plane if(distance >= 0){ // We treat sitting on the plane as being in front. currentIndex = FindLeaf(node.front, vPos); if(currentIndex < 0){ m_foundLeaf = true; m_foundIndex = ~currentIndex; } if(!m_foundLeaf){ currentIndex = FindLeaf(node.back, vPos); if(currentIndex < 0){ m_foundLeaf = true; m_foundIndex = ~currentIndex; } } } else { // Behind the plane if(!m_foundLeaf){ currentIndex = FindLeaf(node.back, vPos); if(currentIndex < 0){ m_foundLeaf = true; m_foundIndex = ~currentIndex; } } if(!m_foundLeaf){ currentIndex = FindLeaf(node.front, vPos); if(currentIndex < 0){ m_foundLeaf = true; m_foundIndex = ~currentIndex; } } } // Either a leaf was found or not, we are just exiting out of our recursion passing back the index. return m_foundIndex; } }
t_rc INXM_IndexHandle::FindAndAppend(int rootPageID, void *key, const REM_RecordID &rid) { t_rc rc; STORM_PageHandle leafPageHandle; rc = FindLeaf(rootPageID, key, leafPageHandle); if (rc != OK) { return rc; } INXM_InitPageHeader initPageHeader; rc = LoadInitHeaders(leafPageHandle, initPageHeader); if (rc != OK) { return rc; } INXM_Node node; int i; for (i=0; i < initPageHeader.nItems; i++) { rc = ReadNode(leafPageHandle, i, node); if (rc != OK) { return rc; } if (KeyCmp(key, node.key) == 0) { break; } } if (i == initPageHeader.nItems) { return(INXM_KEY_NOT_FOUND); } else { int slotOfNewData; STORM_PageHandle lastDataPageHandle; rc = this->sfh.GetPage(this->inxmFileHeader.lastDataPage, lastDataPageHandle); if (rc != OK) { return rc; } /* Check if last data page has room. */ INXM_InitPageHeader initPageHeader; rc = LoadInitHeaders(lastDataPageHandle, initPageHeader); if (rc != OK) { return rc; } int room = PAGE_DATA_SIZE-(INXM_INITPAGEHEADER_SIZE+(initPageHeader.nItems+1)*INXM_DATA_SIZE); /* If no room. Reserve new last data page. */ if (room < 0 ) { CreateLastDataPage(lastDataPageHandle); /* Write last data. */ WriteData(lastDataPageHandle, rid, slotOfNewData); } else if (room == 0) { /* Write last data. */ WriteData(lastDataPageHandle, rid, slotOfNewData); CreateLastDataPage(lastDataPageHandle); } else { /* Write last data. */ WriteData(lastDataPageHandle, rid, slotOfNewData); } /* Update last-1 link data. */ STORM_PageHandle listDataPageHandle; this->sfh.GetPage(node.left, listDataPageHandle); INXM_Data data; ReadData(listDataPageHandle, node.slot, data); int fromWhere = node.slot; while (data.nextPageID != 0) { this->sfh.GetPage(data.nextPageID, listDataPageHandle); fromWhere = data.nextSlot; ReadData(listDataPageHandle, data.nextSlot, data); } data.nextPageID=this->inxmFileHeader.lastDataPage; data.nextSlot=slotOfNewData; /* Write updated last-1 data of list. */ EditData(listDataPageHandle, fromWhere, data); return(OK); } }
void Output_Data(Graph& g) { srand((unsigned)time(NULL)); ofstream output("MusicDoubanGraph.js"); output << "var graph = {\n" " \"nodes\":[\n"; int temp = 0; for(int i = 0;i < g.m_v;i++) if(g.m_hash[i]) { temp = rand() % 19 + 1; output << " {\"name\":\"" << g.m_name[i] << "\",\"group\":" << temp << "},\n"; } output << "],\n\"links\":[\n"; int num = 0; int* switch_ = new int[g.m_e]; for(int i = 0;i < g.m_v;i++) if(g.m_hash[i]) for(int j = g.m_p[i];j < g.m_p[i+1];j++) if(g.m_hash[g.m_q[j]]) { switch_[j] = num; num++; output << " {\"source\":" << g.m_switch[i] << ",\"target\":" << g.m_switch[g.m_q[j]] << ",\"value\":" << (int)(g.m_r[j] / (double)30)+2 << "},\n"; } //output << "],\n\"minpath\":[\n"; //for(int i = 0;i < g.m_v;i++) // if(g.m_hash[i]) // { // vector<vector<int>> path; // vector<vector<int>> epath; // for(int j = 0;j < g.m_v;j++) // if((i != j) && (g.m_hash[j])) // { // Path p; // Enquire_MinPath(i, j, g, p); // Add(path, epath, p); // } // int n = path.size(); // char s[500]; // IntToStr(g.m_switch[i], s); // char* ss = s; // while(*ss != 0)ss++; // *ss = ' '; // ss++; // *ss = 0; // for(int j = 0;j < n;j++) // { // PathToStr(g, epath[j], switch_, ss); // output << " {\"epath\":\"" << s << "\",\"path\":\""; // *s = 0; // PathToStr(g, path[j], s); // output << s << "\"},\n"; // } // } output << "],\n\"mst_edge\":[\n"; Tree tree; Enquire_MST(g, tree); TreeShow(output, tree, switch_); output << "],\n\"mst_leaf\":[\n"; FindLeaf(output, tree, g); output << " ]\n}"; }
void CBspMapMeshProvider::GetMeshes(Palleon::MeshArray& meshes, const Palleon::CCamera* camera) { const Bsp::LeafArray& leaves(m_bspFile->GetLeaves()); const Bsp::LeafFaceArray& leafFaces(m_bspFile->GetLeafFaces()); const Bsp::FaceArray& faces(m_bspFile->GetFaces()); const Bsp::VISDATA& visData(m_bspFile->GetVisData()); CMatrix4 invViewMatrix = camera->GetViewMatrix().Inverse(); CVector3 cameraPosition = CVector3(invViewMatrix(3, 0), invViewMatrix(3, 1), invViewMatrix(3, 2)); int32 leafIndex = FindLeaf(cameraPosition); const Bsp::LEAF& leaf(leaves[leafIndex]); CFrustum cameraFrustum = camera->GetFrustum(); memset(m_faceVisibleSet, 0, m_faceVisibleSetSize); if(leaf.cluster != -1) { const uint8* visVector = &visData.vectors[leaf.cluster * visData.vectorSize]; for(uint32 i = 0; i < leaves.size(); i++) { const Bsp::LEAF& testLeaf = leaves[i]; uint32 testCluster = testLeaf.cluster; if(static_cast<int32>(testCluster) < 0) continue; uint8 visByte = visVector[testCluster / 8]; bool visible = (visByte & (1 << (testCluster & 7))) != 0; if(visible) { CVector3 leafBoxMin = Bsp::ConvertToAthenaCoord(static_cast<float>(testLeaf.mins[0]), static_cast<float>(testLeaf.mins[1]), static_cast<float>(testLeaf.mins[2])); CVector3 leafBoxMax = Bsp::ConvertToAthenaCoord(static_cast<float>(testLeaf.maxs[0]), static_cast<float>(testLeaf.maxs[1]), static_cast<float>(testLeaf.maxs[2])); if(cameraFrustum.Intersects(leafBoxMin, leafBoxMax)) { for(unsigned int i = 0; i < testLeaf.leafFaceCount; i++) { unsigned int faceIndex = leafFaces[i + testLeaf.leafFaceIndex]; unsigned int faceByte = faceIndex / 8; assert(faceByte < m_faceVisibleSetSize); m_faceVisibleSet[faceByte] |= (1 << (faceIndex & 7)); } } } } } m_visibleFaceIndices.clear(); for(unsigned int i = 0; i < faces.size(); i++) { const Bsp::FACE& currentFace = faces[i]; if(currentFace.textureIndex != -1) { BspMapMaterialPtr faceMaterial = m_bspMapResourceProvider->GetMaterial(currentFace.textureIndex); if(faceMaterial->GetIsSky()) continue; } unsigned int faceByte = i / 8; if(m_faceVisibleSet[faceByte] & (1 << (i & 7))) { m_visibleFaceIndices.push_back(i); } } if(m_visibleFaceIndices.size() == 0) return; std::sort(m_visibleFaceIndices.begin(), m_visibleFaceIndices.end(), FaceSorter(faces)); uint32 currentTextureIdx = -2; uint32 currentLightMapIdx = -2; BatchMeshPtr currentBatch; unsigned int currentBatchIndex = 0; for(unsigned int i = 0; i < m_visibleFaceIndices.size(); i++) { uint32 faceIndex = m_visibleFaceIndices[i]; const Bsp::FACE& currentFace = faces[faceIndex]; BspFaceMeshPtr faceMesh = m_faceMeshes[faceIndex]; if(!faceMesh) continue; bool needNewBatch = false; needNewBatch |= (currentFace.textureIndex != currentTextureIdx); needNewBatch |= (currentFace.lightMapIndex != currentLightMapIdx); needNewBatch |= (currentBatch && !currentBatch->CanWriteMesh(faceMesh->GetVertexCount(), faceMesh->GetIndexCount())); if(needNewBatch) { //Switch to new batch if(currentBatch) { currentBatch->EndBatch(); } currentBatch = m_batches[currentBatchIndex++]; meshes.push_back(currentBatch.get()); currentBatch->BeginBatch(); currentTextureIdx = currentFace.textureIndex; currentLightMapIdx = currentFace.lightMapIndex; //Prepare material Palleon::MaterialPtr batchMaterial = currentBatch->GetMaterial(); BspMapMaterialPtr faceMaterial = m_bspMapResourceProvider->GetMaterial(currentTextureIdx); for(unsigned int i = 0; i < Palleon::CMaterial::MAX_TEXTURE_SLOTS; i++) { batchMaterial->SetTexture(i, Palleon::TexturePtr()); } for(unsigned int i = 0; i < faceMaterial->GetPassCount(); i++) { const BspMapPassPtr& pass(faceMaterial->GetPass(i)); Palleon::TEXTURE_COMBINE_MODE combineMode = pass->GetBlendingFunction(); if(pass->GetTextureSource() == CBspMapPass::TEXTURE_SOURCE_DIFFUSE) { batchMaterial->SetTexture(i, pass->GetTexture()); batchMaterial->SetTextureMatrix(i, pass->GetUvMatrix()); batchMaterial->SetTextureCoordSource(i, Palleon::TEXTURE_COORD_UV0); batchMaterial->SetTextureCombineMode(i, combineMode); } else { batchMaterial->SetTexture(i, m_bspMapResourceProvider->GetLightMap(currentLightMapIdx)); batchMaterial->SetTextureMatrix(i, CMatrix4::MakeIdentity()); batchMaterial->SetTextureCoordSource(i, Palleon::TEXTURE_COORD_UV1); batchMaterial->SetTextureCombineMode(i, combineMode); } batchMaterial->SetTextureAddressModeU(i, Palleon::TEXTURE_ADDRESS_REPEAT); batchMaterial->SetTextureAddressModeV(i, Palleon::TEXTURE_ADDRESS_REPEAT); } } assert(currentBatch->CanWriteMesh(faceMesh->GetVertexCount(), faceMesh->GetIndexCount())); currentBatch->WriteMesh(faceMesh->GetVertices(), faceMesh->GetVertexCount(), faceMesh->GetIndices(), faceMesh->GetIndexCount()); } if(currentBatch) { currentBatch->EndBatch(); } }
// this will filter all the faces that should be drawn void TSRBSPTree::FilterFaces( TSRCamera* _pCamera, TSRBSPFace** m_ppFaces, vector< TSRBSPDoor* >& AllDoors ) { // Reset our bit set so all the slots are Zero. m_FacesDrawn.ClearAll(); // Grab the leaf index that our camera is in int leafIndex = FindLeaf( _pCamera->m_Loc ); // Grab the cluster that is Assigned to the leaf int cluster = Leafs[ leafIndex ].cluster; // clear everything to be refilled again m_apDoors.clear(); m_apTransparentFaces.clear(); m_apPunchThroughFaces.clear(); m_apOpaqueFaces.clear(); TSRFrustum frustum; frustum.Update( _pCamera->GetProjectionMatrix().d, _pCamera->GetViewMatrix().d ); for ( unsigned int j = 0; j < AllDoors.size(); j++ ) { if ( !frustum.CanViewBox( AllDoors[ j ]->m_Box.m_vMin.x, AllDoors[ j ]->m_Box.m_vMin.y, AllDoors[ j ]->m_Box.m_vMin.z, AllDoors[ j ]->m_Box.m_vMax.x, AllDoors[ j ]->m_Box.m_vMax.y, AllDoors[ j ]->m_Box.m_vMax.z ) ) { continue; } m_apDoors.push_back( AllDoors[ j ] ); } int i = NumLeafs; // Go through all the leafs and check their visibility while ( i-- ) { // Get the current leaf that is to be tested for visibility from our camera's leaf tBSPLeaf *pLeaf = &( Leafs[ i ] ); // If the current leaf can't be seen from our cluster, go to the next leaf if ( !IsVisible( cluster, pLeaf->cluster ) ) { continue; } // If the current leaf is not in the camera's frustum, go to the next leaf if ( !frustum.CanViewBox( ( float ) pLeaf->min.x, ( float ) pLeaf->min.y, ( float ) pLeaf->min.z, ( float ) pLeaf->max.x, ( float ) pLeaf->max.y, ( float )pLeaf->max.z ) ) { continue; } // If we get here, the leaf we are testing must be visible in our camera's view. // Get the number of faces that this leaf is in charge of. int faceCount = pLeaf->numOfLeafFaces; // Loop through and Render all of the faces in this leaf while ( faceCount-- ) { // Grab the current face index from our leaf faces array int faceIndex = LeafFaces[ pLeaf->leafface + faceCount ]; // Since many faces are duplicated in other leafs, we need to // make sure this face already hasn't been drawn. if ( !m_FacesDrawn.On( faceIndex ) ) { // Set this face as drawn and Render it m_FacesDrawn.Set( faceIndex ); // only static faces are Added if ( m_ppFaces[ faceIndex ]->m_Owner == FACE_STATIC ) { switch(m_ppFaces[faceIndex]->m_RenderMode) { case FACE_NONE: break; case FACE_NORMAL: m_apOpaqueFaces.push_back(m_ppFaces[faceIndex]); break; case FACE_BLENDED: m_apTransparentFaces.push_back(m_ppFaces[faceIndex]); break; case FACE_ALPHA: m_apPunchThroughFaces.push_back(m_ppFaces[faceIndex]); break; } } } } } }
void CQuake3BSP::RenderLevel(const CVector3 &vPos) { // Reset our bitset so all the slots are zero. m_FacesDrawn.ClearAll(); /////// * /////////// * /////////// * NEW * /////// * /////////// * /////////// * // In this new revision of RenderLevel(), we do things a bit differently. // Instead of looping through all the faces, we now want to loop through // all of the leafs. Each leaf stores a list of faces assign to it. // We call FindLeaf() to find the current leaf index that our camera is // in. This leaf will then give us the cluster that the camera is in. The // cluster is then used to test visibility between our current cluster // and other leaf clusters. If another leaf's cluster is visible from our // current cluster, the leaf's bounding box is checked against our frustum. // Assuming the bounding box is inside of our frustum, we draw all the faces // stored in that leaf. // Grab the leaf index that our camera is in int leafIndex = FindLeaf(vPos); // Grab the cluster that is assigned to the leaf int cluster = m_pLeafs[leafIndex].cluster; // Initialize our counter variables (start at the last leaf and work down) int i = m_numOfLeafs; g_VisibleFaces = 0; // Go through all the leafs and check their visibility while(i--) { // Get the current leaf that is to be tested for visibility from our camera's leaf tBSPLeaf *pLeaf = &(m_pLeafs[i]); // If the current leaf can't be seen from our cluster, go to the next leaf if(!IsClusterVisible(cluster, pLeaf->cluster)) continue; // If the current leaf is not in the camera's frustum, go to the next leaf if(!g_Frustum.BoxInFrustum((float)pLeaf->min.x, (float)pLeaf->min.y, (float)pLeaf->min.z, (float)pLeaf->max.x, (float)pLeaf->max.y, (float)pLeaf->max.z)) continue; // If we get here, the leaf we are testing must be visible in our camera's view. // Get the number of faces that this leaf is in charge of. int faceCount = pLeaf->numOfLeafFaces; // Loop through and render all of the faces in this leaf while(faceCount--) { // Grab the current face index from our leaf faces array int faceIndex = m_pLeafFaces[pLeaf->leafface + faceCount]; // Before drawing this face, make sure it's a normal polygon if(m_pFaces[faceIndex].type != FACE_POLYGON) continue; // Since many faces are duplicated in other leafs, we need to // make sure this face already hasn't been drawn. if(!m_FacesDrawn.On(faceIndex)) { // Increase the rendered face count to display for fun g_VisibleFaces++; // Set this face as drawn and render it m_FacesDrawn.Set(faceIndex); RenderFace(faceIndex); } } } /////// * /////////// * /////////// * NEW * /////// * /////////// * /////////// * }