//--
    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);
        
    }
Ejemplo n.º 2
0
    //--
    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);
                 }
             }
         }
     }
 }