Ejemplo n.º 1
0
 //--
 void
 KDTree::VAddObjects(const std::vector<ISpatialObject*>& refObjects)
 {        
     ISpatialObject* pObjectList = NULL;
     ISpatialObject* pObjectTemp;
     
     
     std::vector<ISpatialObject*>::const_iterator iter_object;
     for(iter_object = refObjects.begin(); iter_object != refObjects.end(); iter_object++)
     {
         pObjectTemp = (*iter_object);
         
         
         pObjectTemp->VSetNext(pObjectList);
         pObjectList = pObjectTemp;
         
         
         // [rad] Store objects locally for fast update / iteration
         m_vecObjects.push_back((*iter_object));
     }
     
     
     // [rad] Pre-allocate the tree
     Preallocate(s_i32MaxDepth);
     
     
     Vector3 vec3Min(m_vec3Center.x - m_f32HalfWidth, m_vec3Center.y - m_f32HalfWidth, m_vec3Center.z - m_f32HalfWidth);
     Vector3 vec3Max(m_vec3Center.x + m_f32HalfWidth, m_vec3Center.y + m_f32HalfWidth, m_vec3Center.z + m_f32HalfWidth);
 
 
     // [rad] Based on this info, construct recursively, starting at root
     m_pRootNode->Construct(pObjectTemp, refObjects.size(), vec3Min, vec3Max);
 }
Ejemplo n.º 2
0
 //--
 void
 KDTreeNode::RemoveObject(ISpatialObject* pObject)
 {
     if(m_pObjects == pObject)
     {
         m_pObjects = m_pObjects->VGetNext();
     }
     else
     {
         // [rad] traverse list and remove
         ISpatialObject* pIter = m_pObjects;
         ISpatialObject* pPrev;
                 
         while(pIter)
         {
             pPrev = pIter;
             pIter = pIter->VGetNext();
                     
             if(pObject == pIter)
             {
                 // [rad] Remove node and decrement node count
                 pPrev->VSetNext(pObject->VGetNext());
                         
                 break;
             }
         }
     }
     
     // [rad] Decrement counts
     m_i32ObjectCount--;
     m_i32ObjectTotal--;
     
     // [rad] Traverse up and decrement parent total counts
     KDTreeNode* pNode = m_pParent;
             
     // [rad] Check if this node still contains this object
     while(pNode)
     {
         pNode->m_i32ObjectTotal--;
         
         // [rad] Go up
         pNode = pNode->m_pParent;
     }
 }
    //--
    void
    UniformGridHashBucket::RemoveObject(ISpatialObject* pObject)
    {
        /*
        // [rad] Iterate over all objects in this bucket
        std::vector<ISpatialObject*>::iterator iter_object;
        for(iter_object = m_vecObjects.begin(); iter_object != m_vecObjects.end(); iter_object++)
        {
            if(pObject == (*iter_object))
            {
                // [rad] Remove this object
                m_vecObjects.erase(iter_object);
                return;
            }
        }
        */

        if(m_pObjects == pObject)
        {
            m_pObjects = m_pObjects->VGetNext();
        }
        else
        {
            // [rad] traverse list and remove
            ISpatialObject* pIter = m_pObjects;
            ISpatialObject* pPrev;
                    
            while(pIter)
            {
                pPrev = pIter;
                pIter = pIter->VGetNext();
                        
                if(pIter == pObject)
                {
                    pPrev->VSetNext(pIter->VGetNext());
                    break;
                }
            }
        }

    }
    //--
    void
    LooseOctree::VUpdate()
    {   
        // [rad] We are completely rebuilding this loose octree
        if(m_i32Rebuild)
        {
        
            // [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++)
            {
                m_pRootNode->AddObject((*iter_object));
            }
        }
        else
        {      
            LooseOctreeNode* pNode;
            ISpatialObject* pObject;
            ISpatialObject* pPrev;
        
            std::vector<ISpatialObject*>::iterator iter_object;
            for(iter_object = m_vecObjects.begin(); iter_object != m_vecObjects.end(); iter_object++)
            {
                pNode = static_cast<LooseOctreeNode*>((*iter_object)->VGetCell());
                
                // [rad] Check if this node still contains the element
                if(pNode->CheckContains(*iter_object))
                {
                    continue;
                }
                else
                {
                    // [rad] Remove element
                    if(pNode->m_pObjects == (*iter_object))
                    {
                        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 == (*iter_object))
                            {
                                pPrev->VSetNext(pObject->VGetNext());
                                break;
                            }
                        }
                    }
                    
                    
                    
                    // [rad] Go up one node
                    pNode = pNode->m_pParent;
                
                    // [rad] Check if this node still contains this object
                    while(pNode)
                    {
                        // [rad] Check if contains, here we use non-loose 
                        // check, because it's possible that object will be
                        // stuck in the parent's node (since it might happen
                        // that object will be in it's loose dimensions)
                        if(pNode->CheckContainsNonLoose(*iter_object))
                        {
                            pNode->AddObject((*iter_object));
                            break;
                        }
                        else
                        {
                            pNode = pNode->m_pParent;
                        }
                    }   
                    
                    
                    //m_pRootNode->AddObject(*iter_object);     
                }
            }
            
        }
        

                
        // [rad] Do top-down collision testing
        std::vector<ISpatialObject*>::iterator iter_object;
        for(iter_object = m_vecObjects.begin(); iter_object != m_vecObjects.end(); iter_object++)
        {
            m_pRootNode->CheckCollisions((*iter_object));
        }
        
    }
Ejemplo n.º 5
0
    //--
    void
    KDTreeNode::Construct(ISpatialObject* pObjectList, int i32ObjectCount,
                                         const Vector3& refVectorMin, const Vector3& refVectorMax)
    {        
        
        // [rad] Store voxel info
        m_vec3Max = refVectorMax;
        m_vec3Min = refVectorMin;
        
        // [rad] Split plane position is already stored
        
        
        ISpatialObject* pIter = pObjectList;  
        ISpatialObject* pObjectTemp;
        ISpatialObject* pObject;
                       
        // [rad] If there are no children, or there's less objects than bins,
        // store everything in this node
        if(!m_pChildLeft || !m_pChildRight || i32ObjectCount < s_i32BinCount)
        {
            // [rad] There's no splitpane and position is not important
            m_f32SplitPosition = 0.0f;
            //m_i32SplitPane = -1;
            
            // [rad] Copy elements...
            m_pObjects = pObjectList;
            m_i32ObjectCount = i32ObjectCount;
            m_i32ObjectTotal = i32ObjectCount;
            
            
            // [rad] Iterate through all elements and set this node as a containing cell
            pIter = m_pObjects;   
            while(pIter)
            {
                pIter->VSetCell(this);
                pIter = pIter->VGetNext();
            }
            
            return;
        }
        


        // [rad] Compute sizes
        float f32Span = m_vec3Max[m_i32SplitPane] - m_vec3Min[m_i32SplitPane];
        float f32BucketSize = f32Span / static_cast<float>(s_i32BinCount);
        float f32Offset = -m_vec3Min[m_i32SplitPane];
                
        int i32BinIndex;        
        int i32Index;
      

        
        // [rad] Clean prefix sums and previous values
        for(i32Index = 0; i32Index < s_i32BinCount; i32Index++)
        {
            s_vecBins.at(i32Index).first = 0;
            s_vecBins.at(i32Index).second = 0;
            
            s_vecSums.at(i32Index).first = 0;
            s_vecSums.at(i32Index).second = 0;
        }
        
        
        
        
        // [rad] Go linearly through the list and do binning
        pIter = pObjectList;        
        Vector3 vec3Center;
        float f32Radius;
        
        while(pIter)
        {
            // [rad] Get center and radius of this object
            vec3Center = pIter->VGetPosition();
            f32Radius = pIter->VGetRadius();
            
            // [rad] Increment proper bins
            i32BinIndex = static_cast<int>(floorf((f32Offset + vec3Center[m_i32SplitPane] - f32Radius) * s_i32BinCount / f32Span));
            s_vecBins[i32BinIndex].first++;
            
            i32BinIndex = static_cast<int>(floorf((f32Offset + vec3Center[m_i32SplitPane] + f32Radius) * s_i32BinCount / f32Span));
            s_vecBins[i32BinIndex].second++;
                        
           
            // [rad] iterate to next element in list
            pIter = pIter->VGetNext();
        }
        
        
        
        
        // [rad] Compute prefix sums
        int i32SumMin = 0;
        int i32SumMax = 0;

        
        for(i32Index = 0; i32Index < s_i32BinCount; i32Index++)
        {
            i32SumMin += s_vecBins.at(i32Index).first;
            i32SumMax += s_vecBins.at(i32Index).second;
            
            s_vecSums.at(i32Index).first = i32SumMin;
            s_vecSums.at(i32Index).second = i32SumMax;
        }
        
        
        
        // [rad] Compute split candidate
        int i32MinDiff = std::numeric_limits<int>::max();
        int i32BinDiff;
        int i32SplitPosition = 0;
        
        for(i32Index = 0; i32Index < s_i32BinCount; i32Index++)
        {
            i32BinDiff = abs(s_vecSums.at(i32Index).first - s_vecSums.at(s_i32BinCount - i32Index - 1).second);
            
            if(i32BinDiff < i32MinDiff)
            {
                // [rad] This is a good candidate
                i32MinDiff = i32BinDiff;
                i32SplitPosition = i32Index;
            }
        }
    
    
        
        // [rad] Find real split position
        //m_f32SplitPosition = ((i32SplitPosition * f32Span) / f32BucketSize) - f32Offset;
        m_f32SplitPosition = m_vec3Min[m_i32SplitPane] + i32SplitPosition * f32BucketSize;
        
        
        // [rad] Now go insert objects into child nodes
        ISpatialObject* pObjectListLeft = NULL;
        ISpatialObject* pObjectListRight = NULL;
        
        int i32CountLeft = 0;
        int i32CountRight = 0;
        
        pIter = pObjectList;        
        while(pIter)
        {
            pObject = pIter->VGetNext();
            
            // [rad] Get center and radius of this object
            vec3Center = pIter->VGetPosition();
            f32Radius = pIter->VGetRadius();
            
            
            // [rad] Check where this object belongs
            if(vec3Center[m_i32SplitPane] + f32Radius <= m_f32SplitPosition)
            {
                // [rad] Left child

                pIter->VSetNext(pObjectListLeft);
                pObjectListLeft = pIter;
                
                i32CountLeft++;
            }
            else if(vec3Center[m_i32SplitPane] - f32Radius >= m_f32SplitPosition)
            {
                // [rad] Right child
                
                pIter->VSetNext(pObjectListRight);
                pObjectListRight = pIter;
                
                i32CountRight++;
            }
            else
            {
                
                pIter->VSetCell(this);
                pIter->VSetNext(m_pObjects);
                m_pObjects = pIter;
                
                m_i32ObjectCount++;
            }
            
            pIter = pObject;
        }
        
        
        // [rad] We'll keep track of how many objects we have in this node 
        // and in children
        m_i32ObjectTotal += i32ObjectCount;
        
        
        Vector3 vec3Min = refVectorMin;
        vec3Min[m_i32SplitPane] = m_f32SplitPosition;
        
        Vector3 vec3Max = refVectorMax;
        vec3Max[m_i32SplitPane] = m_f32SplitPosition;
        
        // [rad] Recurse into left child
        m_pChildLeft->Construct(pObjectListLeft, i32CountLeft,
                                            refVectorMin, vec3Max);
                                            
                                            
        // [rad] Recurse into right child
        m_pChildRight->Construct(pObjectListRight, i32CountRight,
                                            vec3Min, refVectorMax);
    }
Ejemplo n.º 6
0
    //--
    ISpatialObject*
    KDTreeNode::Invalidate()
    {
        ISpatialObject* pIter;
        ISpatialObject* pTemp;
        ISpatialObject* pObjects = NULL;

        int i32ObjectCount;
        
        // [rad] If this is a leaf
        if(!m_pChildLeft || !m_pChildRight)
        {
            pObjects = m_pObjects;
            i32ObjectCount = m_i32ObjectCount;
            
            m_i32ObjectCount = 0;
            m_i32ObjectTotal = 0;
            m_pObjects = NULL;
            
            return(pObjects);
        }
        
    
        ISpatialObject* pObjectsLeft = NULL;
        if(m_pChildLeft->m_i32ObjectTotal)
        {
            pObjectsLeft = m_pChildLeft->Invalidate();
        }
        
        ISpatialObject* pObjectsRight = NULL;
        if(m_pChildRight->m_i32ObjectTotal)
        {
            pObjectsRight = m_pChildRight->Invalidate();
        }


        
        pIter = pObjectsLeft;
        while(pIter)
        {
            pTemp = pIter->VGetNext();
            
            pIter->VSetNext(pObjects);
            pObjects = pIter;
            
            pIter = pTemp;
        }
        
        
        pIter = pObjectsRight;
        while(pIter)
        {
            pTemp = pIter->VGetNext();
            
            pIter->VSetNext(pObjects);
            pObjects = pIter;
            
            pIter = pTemp;
        }
        
        
        pIter = m_pObjects;
        while(pIter)
        {
            pTemp = pIter->VGetNext();
            
            pIter->VSetNext(pObjects);
            pObjects = pIter;
            
            pIter = pTemp;
        }

        
        /*
        ISpatialObject* pIterLeft = NULL;
        ISpatialObject* pIterParent = NULL;
        ISpatialObject* pTemp;
    
        
        // [rad] traverse left link list looking for end
        if(pObjectsLeft)
        {
            pIterLeft = pObjectsLeft;
            while(1)
            {
                pTemp = pIterLeft->VGetNext();
                
                if(!pTemp)
                {
                    break;
                }
                
                pIterLeft = pTemp;
            }
        }
        
        
        // [rad] traverse straddling collection (stored at this node) looking for end
        if(m_pObjects)
        {
            pIterParent = m_pObjects;
            while(1)
            {
                pTemp = pIterParent->VGetNext();
                
                if(!pTemp)
                {
                    break;
                }
                
                pIterParent = pTemp;
            }
        }

        
        // [rad] Glue 3 single link lists together
        if(pIterLeft && pIterParent)
        {
            pIterParent->VSetNext(pObjectsRight);
            pIterLeft->VSetNext(pIterParent);
        
            pObjects = pIterLeft;
        }
        else if(pIterLeft)
        {
            pIterLeft->VSetNext(pObjectsRight);
            
            pObjects = pIterLeft;
            
        }
        else if(pIterParent)
        {
            pIterParent->VSetNext(pObjectsRight);
            
            pObjects = pIterParent;
        }
        else
        {
            pObjects = pObjectsRight;
        }
        */
        
        m_i32ObjectCount = 0;
        m_i32ObjectTotal = 0;
        m_pObjects = NULL;
        
        return(pObjects);
    }
    //--
    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
 OctreeNode::AddObjects(ISpatialObject* pObjectList, int i32ObjectCount)
 {
     ISpatialObject* pIter;
     ISpatialObject* pObject;
     
     // [rad] Check if we can stop splitting
     if(i32ObjectCount < s_i32MinSplitCount)
     {
         m_pObjects = pObjectList;
         
         pIter = m_pObjects;   
         while(pIter)
         {
             pIter->VSetCell(this);
             pIter = pIter->VGetNext();
         }
         
         
         m_i32ObjectCount = i32ObjectCount;
         
         return;
     }
     
     
     
     int i32Index = 0;
     ISpatialObject* apChildObjects[8];
     int aiChildCounts[8];
     
     for(i32Index = 0; i32Index < 8; i32Index++)
     {
         apChildObjects[i32Index] = NULL;
         aiChildCounts[i32Index] = 0;
     }
     
     
     pIter = pObjectList;
     while(pIter)
     {
         pObject = pIter->VGetNext();
         
         int i32Position = 0;
         int i32Straddle = 0;
 
         float f32Radius = pIter->VGetRadius();
         Vector3 vec3Center = pIter->VGetPosition();
         
         
         for(i32Index = 0; i32Index < 3; i32Index++)
         {
             if(m_vec3Center[i32Index] < vec3Center[i32Index])
             {
                 if(m_vec3Center[i32Index] > vec3Center[i32Index] - f32Radius)
                 {
                     // [rad] Straddle occurs
                     i32Straddle = 1;
                     break;
                 }
                 else
                 {
                     i32Position |= (1 << i32Index);
                 }
             }
             else
             {
                 if(m_vec3Center[i32Index] < vec3Center[i32Index] + f32Radius)
                 {
                     // [rad] Straddle occurs
                     i32Straddle = 1;
                     break;
                 }
             }
         }
     
     
         if(!i32Straddle && m_pChildren[i32Position])
         {
             // [rad] Contained in existing child node
             //m_pChildren[i32Position]->AddObject(pObject);
             
             pIter->VSetNext(apChildObjects[i32Position]);
             apChildObjects[i32Position] = pIter;
         
             aiChildCounts[i32Position]++;
             
         }
         else
         {
             // [rad] Store this node for fast back-link
             pIter->VSetCell(this);
     
             // [rad] Straddling or no child node available
             pIter->VSetNext(m_pObjects);
             m_pObjects = pIter;
             
             m_i32ObjectCount++;
         }
         
         
         pIter = pObject;
     }
     
     
     // [rad] At this point
     for(i32Index = 0; i32Index < 8; i32Index++)
     {            
         // [rad] Delegate to children
         if(m_pChildren[i32Index] && aiChildCounts[i32Index])
         {
             m_pChildren[i32Index]->AddObjects(apChildObjects[i32Index], aiChildCounts[i32Index]);
         }
     }    
 }
    //--
    void
    Octree::VAddObjects(const std::vector<ISpatialObject*>& refObjects)
    {        
        float f32MinDiameter = 1.0e38f;
        float f32CellSize = 2.0f * m_f32HalfWidth;
        float f32Diameter;

        int i32Depth = 0;
        int i32Divisions = 1;

        std::vector<ISpatialObject*>::const_iterator iter_object;
        for(iter_object = refObjects.begin(); iter_object != refObjects.end(); iter_object++)
        {
            f32Diameter = (*iter_object)->VGetRadius();
            
            if(f32Diameter < f32MinDiameter)
            {
                // [rad] Found a smaller object, update
                f32MinDiameter = f32Diameter;
            }
        }
        
        // [rad] Make cell size 'x' times as big as the smallest diameter 
        f32MinDiameter *= s_f32MaxObjectNodeRatio;
        
        
        // [rad] Calculate depth
        f32CellSize = 2.0f * m_f32HalfWidth;
        
        while(f32MinDiameter <= f32CellSize)
        {
            // [rad] Don't make more than max depth 
            if(s_i32MaxDepth == i32Depth)
            {
                break;
            }
            
            i32Divisions *= 2;                        
            f32CellSize = 2.0f * m_f32HalfWidth / static_cast<float>(i32Divisions);        
            
            i32Depth++;
        }
        
        
        // [rad] Delete everything but the root
        m_pRootNode->Free();
        
        // [rad] Pre-allocate the tree
        Preallocate(i32Depth);


        ISpatialObject* pObjectList = NULL;
        ISpatialObject* pObjectTemp;

        
        // [rad] Insert the elements into the tree
        for(iter_object = refObjects.begin(); iter_object != refObjects.end(); iter_object++)
        {
            if(m_i32Rebuild)
            {
                m_pRootNode->AddObject((*iter_object));
            }
            else
            {
                pObjectTemp = (*iter_object);
            
                pObjectTemp->VSetNext(pObjectList);
                pObjectList = pObjectTemp;
            }
            
            
            // [rad] Store locally in a list, for fast iteration
            m_vecObjects.push_back((*iter_object));
        }
        
        
        if(!m_i32Rebuild)
        {
            // [rad] Add objects
            m_pRootNode->AddObjects(pObjectList, m_vecObjects.size());
        }
    }