BtDbvt dynamic aabb tree

From Physics Simulation Wiki

Jump to: navigation, search

Dynamic AABB tree (btDbvt)

The btDbvt dynamic AABB tree is a fast dynamic general purpose aabb tree. It is currently used in Bullet to accelerate collision detection between soft bodies. Also, the btDbvtBroadphase uses two btDbvt trees: one for static/non-moving and one for dynamic/moving objects. The btDbvt has very fast insertion, removal and update of nodes, and it exploits temporal coherence.

btDbvt dynamic AABB tree supports the following queries:

  • enumerate leafs from a root, 'enumLeafs'.
  • Tree/tree collision, 'collideTT'.
  • Tree/Volume collision, 'collideTV'.
  • Ray cast, 'collideRAY'
  • KDOP culling, 'collideKDOP'
  • Occlusion parse, (KDOP + front to back + call to ::Descent for each nodes), 'collideOCL'.
  • Tree/user collision, 'collideTU'
Some information about the btDbvt inner workings:

Insert:
    
    let 'L' be the leaf to insert
    let 'R' the current root of insertion
    while 'R' is an internal node
        if cost(L,R->left) < cost(L,R->right) [!]
            'R'	=	R->left
        else
            'R'	=	R->right
        end
    end	
    create new internal node 'N'
    'N'->left	=	'L'
    'N'->right	=	'R'
    return 'L'
    
    Notes:
    [!]-	Using Manhattan distance (|x|+|y|+...) between nodes as a cost function greatly speed up insertion.
            Doesn't take in account volume,	but work well in practice even for scales heterogenous setup.
        
Remove:

    let SIDE(n) be a function returning left or right depending on which side 'n' is.
    let 'L' be the leaf to remove
    let 'S' be 'L' sibling node
    let 'P' be 'L' parent node
    let 'Q' be 'P' parent node
    'Q'->SIDE(P)	=	'S'
    'S'->parent		=	'Q'
    delete node 'P'
    while 'Q' != null
        'V0'		=	Q->volume
        'Q'->volume	=	union of 'Q'->left and 'Q'->right
        if 'Q'->volume == 'V0' [!]
            return 'Q'
        else
            'S'	=	'Q'
            'Q'	=	'Q'->parent
        end
    end
    return 'Q'
    
    Notes:	
    [!]-	We stop as soon as 'Q'->volume == 'V0', compare for strict equality (memcmp like)
    
Update (with velocity and margin):
    let 'L' be the leaf to update
    let 'V' be the new volume of 'L'
    let 'D' be the the velocity of 'L' [*]
    let 'M' be the margin of 'L'
    if 'L'->volume containt 'V' [!]
        return
    else
        expand 'V' with margin 'M'		[!!]
        expand 'V' with velocity 'D'	[!!!]
        'R'			=	Remove('L')
        'L'->volume	=	'V'
        Insert('L') at 'R'				[!!!!]
    end
    
    Notes:
    [*]-	'D' can be implicitly calculated as follow: 'D' = ('L'->center - 'V'->center) * predicted frames.
    [!]-	We do nothing if the new volume 'V' is contained in the old one.
    [!!]-	Using a non-zero margin handle the case of jitter or small random motions.
    [!!!]-	Using a non-zero velocity handle the case of linear motion over few frames.
    [!!!!]-	We re-insert 'L' at 'R' so we do not have to walk all the tree from the root.
    
Personal tools