//-- void Octree::VUpdate() { ISpatialObject* pElement; // [rad] We are rebuilding octree every frame if(m_i32Rebuild) { ISpatialObject* pObjectList = NULL; // [rad] We are going to rebuild octree (without dealocating space) m_pRootNode->Rebuild(); // [rad] Populate the octree std::vector<ISpatialObject*>::iterator iter_object; for(iter_object = m_vecObjects.begin(); iter_object != m_vecObjects.end(); iter_object++) { pElement = (*iter_object); //m_pRootNode->AddObject((*iter_object)); pElement->VSetNext(pObjectList); pObjectList = pElement; } m_pRootNode->AddObjects(pObjectList, m_vecObjects.size()); } else { // [rad] Instead of rebuilding octree every frame we will remove objects // bottom-up OctreeNode* pNode; ISpatialObject* pObject; ISpatialObject* pPrev; std::vector<ISpatialObject*>::iterator iter_object; for(iter_object = m_vecObjects.begin(); iter_object != m_vecObjects.end(); iter_object++) { pElement = (*iter_object); pNode = static_cast<OctreeNode*>(pElement->VGetCell()); // [rad] Remove element if(pNode->m_pObjects == pElement) { // [rad] Remove object from the list (first position) pNode->m_pObjects = pNode->m_pObjects->VGetNext(); } else { // [rad] traverse list and remove pObject = pNode->m_pObjects; while(pObject) { pPrev = pObject; pObject = pObject->VGetNext(); if(pObject == pElement) { // [rad] Remove object from the list pPrev->VSetNext(pObject->VGetNext()); break; } } } // [rad] Decrement node's object count pNode->m_i32ObjectCount--; // [rad] Attempt to re-insert element if(pNode->CheckContains(pElement)) { pNode->AddObject(pElement); } else { // [rad] Go up one node pNode = pNode->m_pParent; // [rad] Check if this node still contains this object while(pNode) { // [rad] Check if contains if(pNode->CheckContains(pElement)) { pNode->AddObject(pElement); break; } else { pNode = pNode->m_pParent; } } } } } // [rad] Check collisionsgdb1 std::vector<OctreeNode*> vecAncestors; m_pRootNode->CheckCollisions(vecAncestors); }
//-- void KDTree::VUpdate() { // [rad] Remove / Insert elements KDTreeNode* pNode; ISpatialObject* pObject; ISpatialObject* pIter; ISpatialObject* pPrev; std::vector<ISpatialObject*>::iterator iter_object; for(iter_object = m_vecObjects.begin(); iter_object != m_vecObjects.end(); iter_object++) { pIter = (*iter_object); pNode = static_cast<KDTreeNode*>(pIter->VGetCell()); // [rad] Check if this node still contains the element // Also need to make sure that object is straddling (if children exist) if(pNode->CheckContains(pIter) && pNode->CheckStraddle(pIter)) { // [rad] If so, do nothing continue; } else { pNode->RemoveObject(pIter); /* // [rad] We need to insert the object // [rad] Go up one node pNode = pNode->m_pParent; pObject = (*iter_object); // [rad] Check if this node still contains this object while(pNode) { // [rad] Check if contains if(pNode->CheckContains(pObject)) { // [rad] If so, add this object pNode->AddObject(pObject); break; } else { // [rad] If not, iterate up pNode = pNode->m_pParent; } } */ m_pRootNode->AddObject(pIter); } } // [rad] Traverse the tree and check if any of the nodes are invalidated // If they are, rebuild that portion of the tree m_pRootNode->Rebuild(); // [rad] Do collision detection // [rad] Do top-down collision testing for(iter_object = m_vecObjects.begin(); iter_object != m_vecObjects.end(); iter_object++) { m_pRootNode->CheckCollisions((*iter_object)); } }
//-- void UniformGrid::VUpdate() { int i32X1, i32X2; int i32Y1, i32Y2; int i32Z1, i32Z2; int i32Hash; float f32Delta; UniformGridHashBucket* pBucket; std::vector<ISpatialObject*>::iterator iter_object; for(iter_object = m_vecObjects.begin(); iter_object != m_vecObjects.end(); iter_object++) { ISpatialObject* pObject = (*iter_object); // [rad] Retrieve the bucket in which this object is stored pBucket = static_cast<UniformGridHashBucket*>(pObject->VGetCell()); // [rad] Retrieve new object position const Vector3& vec3Position = pObject->VGetPosition(); // [rad] Check if we need bucket update (compute hash) i32Hash = ComputeHashValue(m_i32HashBuckets, static_cast<int>(vec3Position.x / m_f32GridSize), static_cast<int>(vec3Position.y / m_f32GridSize), static_cast<int>(vec3Position.z / m_f32GridSize)); // [rad] Check if we need to switch buckets if(m_vecHashBuckets[i32Hash] != pBucket) { // [rad] Remove from old bucket pBucket->RemoveObject(pObject); // [rad] Add to new (other) bucket (m_vecHashBuckets[i32Hash])->InsertObject(pObject); } // [rad] Update frame ++m_i32FrameCount; // [rad] Check collisions within the current bucket pBucket->CheckCollisions(m_i32FrameCount, pObject); // [rad] Now we need to check adjacent buckets: // compute all cells which this object might overlap. // Because initially we picked size for our cells big enough to // encompass any object, we have to check at most 8 cells (3D). f32Delta = pObject->VGetRadius() + m_f32GridSize / s_f32ObjectCellRatio + s_f32Epsilon; i32X1 = static_cast<int>(floorf((vec3Position.x - f32Delta) / m_f32GridSize)); i32X2 = static_cast<int>(ceilf((vec3Position.x + f32Delta) / m_f32GridSize)); i32Y1 = static_cast<int>(floorf((vec3Position.y - f32Delta) / m_f32GridSize)); i32Y2 = static_cast<int>(ceilf((vec3Position.y + f32Delta) / m_f32GridSize)); i32Z1 = static_cast<int>(floorf((vec3Position.z - f32Delta) / m_f32GridSize)); i32Z2 = static_cast<int>(ceilf((vec3Position.z + f32Delta) / m_f32GridSize)); // [rad] Check all grid cells for(int i32XIndex = i32X1; i32XIndex <= i32X2; i32XIndex++) { for(int i32YIndex = i32Y1; i32YIndex <= i32Y2; i32YIndex++) { for(int i32ZIndex = i32Z1; i32ZIndex <= i32Z2; i32ZIndex++) { i32Hash = ComputeHashValue(m_i32HashBuckets, i32XIndex, i32YIndex, i32ZIndex); // [rad] Check if we have checked this bucket already if(m_vecHashBuckets[i32Hash]->GetLastFrame() == m_i32FrameCount) { continue; } // [rad] Otherwise check collisions (m_vecHashBuckets[i32Hash])->CheckCollisions(m_i32FrameCount, pObject); } } } } }