Home | History | Annotate | Download | only in BroadphaseCollision
      1 /*
      2 Bullet Continuous Collision Detection and Physics Library
      3 Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
      4 
      5 This software is provided 'as-is', without any express or implied warranty.
      6 In no event will the authors be held liable for any damages arising from the use of this software.
      7 Permission is granted to anyone to use this software for any purpose,
      8 including commercial applications, and to alter it and redistribute it freely,
      9 subject to the following restrictions:
     10 
     11 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
     12 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
     13 3. This notice may not be removed or altered from any source distribution.
     14 */
     15 ///btDbvt implementation by Nathanael Presson
     16 
     17 #include "btDbvt.h"
     18 
     19 //
     20 typedef btAlignedObjectArray<btDbvtNode*>			tNodeArray;
     21 typedef btAlignedObjectArray<const btDbvtNode*>	tConstNodeArray;
     22 
     23 //
     24 struct btDbvtNodeEnumerator : btDbvt::ICollide
     25 {
     26 	tConstNodeArray	nodes;
     27 	void Process(const btDbvtNode* n) { nodes.push_back(n); }
     28 };
     29 
     30 //
     31 static DBVT_INLINE int			indexof(const btDbvtNode* node)
     32 {
     33 	return(node->parent->childs[1]==node);
     34 }
     35 
     36 //
     37 static DBVT_INLINE btDbvtVolume	merge(	const btDbvtVolume& a,
     38 									  const btDbvtVolume& b)
     39 {
     40 #if (DBVT_MERGE_IMPL==DBVT_IMPL_SSE)
     41 	ATTRIBUTE_ALIGNED16( char locals[sizeof(btDbvtAabbMm)]);
     42 	btDbvtVolume* ptr = (btDbvtVolume*) locals;
     43 	btDbvtVolume&	res=*ptr;
     44 #else
     45 		btDbvtVolume	res;
     46 #endif
     47 	Merge(a,b,res);
     48 	return(res);
     49 }
     50 
     51 // volume+edge lengths
     52 static DBVT_INLINE btScalar		size(const btDbvtVolume& a)
     53 {
     54 	const btVector3	edges=a.Lengths();
     55 	return(	edges.x()*edges.y()*edges.z()+
     56 		edges.x()+edges.y()+edges.z());
     57 }
     58 
     59 //
     60 static void						getmaxdepth(const btDbvtNode* node,int depth,int& maxdepth)
     61 {
     62 	if(node->isinternal())
     63 	{
     64 		getmaxdepth(node->childs[0],depth+1,maxdepth);
     65 		getmaxdepth(node->childs[1],depth+1,maxdepth);
     66 	} else maxdepth=btMax(maxdepth,depth);
     67 }
     68 
     69 //
     70 static DBVT_INLINE void			deletenode(	btDbvt* pdbvt,
     71 										   btDbvtNode* node)
     72 {
     73 	btAlignedFree(pdbvt->m_free);
     74 	pdbvt->m_free=node;
     75 }
     76 
     77 //
     78 static void						recursedeletenode(	btDbvt* pdbvt,
     79 												  btDbvtNode* node)
     80 {
     81 	if(!node->isleaf())
     82 	{
     83 		recursedeletenode(pdbvt,node->childs[0]);
     84 		recursedeletenode(pdbvt,node->childs[1]);
     85 	}
     86 	if(node==pdbvt->m_root) pdbvt->m_root=0;
     87 	deletenode(pdbvt,node);
     88 }
     89 
     90 //
     91 static DBVT_INLINE btDbvtNode*	createnode(	btDbvt* pdbvt,
     92 										   btDbvtNode* parent,
     93 										   void* data)
     94 {
     95 	btDbvtNode*	node;
     96 	if(pdbvt->m_free)
     97 	{ node=pdbvt->m_free;pdbvt->m_free=0; }
     98 	else
     99 	{ node=new(btAlignedAlloc(sizeof(btDbvtNode),16)) btDbvtNode(); }
    100 	node->parent	=	parent;
    101 	node->data		=	data;
    102 	node->childs[1]	=	0;
    103 	return(node);
    104 }
    105 
    106 //
    107 static DBVT_INLINE btDbvtNode*	createnode(	btDbvt* pdbvt,
    108 										   btDbvtNode* parent,
    109 										   const btDbvtVolume& volume,
    110 										   void* data)
    111 {
    112 	btDbvtNode*	node=createnode(pdbvt,parent,data);
    113 	node->volume=volume;
    114 	return(node);
    115 }
    116 
    117 //
    118 static DBVT_INLINE btDbvtNode*	createnode(	btDbvt* pdbvt,
    119 										   btDbvtNode* parent,
    120 										   const btDbvtVolume& volume0,
    121 										   const btDbvtVolume& volume1,
    122 										   void* data)
    123 {
    124 	btDbvtNode*	node=createnode(pdbvt,parent,data);
    125 	Merge(volume0,volume1,node->volume);
    126 	return(node);
    127 }
    128 
    129 //
    130 static void						insertleaf(	btDbvt* pdbvt,
    131 										   btDbvtNode* root,
    132 										   btDbvtNode* leaf)
    133 {
    134 	if(!pdbvt->m_root)
    135 	{
    136 		pdbvt->m_root	=	leaf;
    137 		leaf->parent	=	0;
    138 	}
    139 	else
    140 	{
    141 		if(!root->isleaf())
    142 		{
    143 			do	{
    144 				root=root->childs[Select(	leaf->volume,
    145 					root->childs[0]->volume,
    146 					root->childs[1]->volume)];
    147 			} while(!root->isleaf());
    148 		}
    149 		btDbvtNode*	prev=root->parent;
    150 		btDbvtNode*	node=createnode(pdbvt,prev,leaf->volume,root->volume,0);
    151 		if(prev)
    152 		{
    153 			prev->childs[indexof(root)]	=	node;
    154 			node->childs[0]				=	root;root->parent=node;
    155 			node->childs[1]				=	leaf;leaf->parent=node;
    156 			do	{
    157 				if(!prev->volume.Contain(node->volume))
    158 					Merge(prev->childs[0]->volume,prev->childs[1]->volume,prev->volume);
    159 				else
    160 					break;
    161 				node=prev;
    162 			} while(0!=(prev=node->parent));
    163 		}
    164 		else
    165 		{
    166 			node->childs[0]	=	root;root->parent=node;
    167 			node->childs[1]	=	leaf;leaf->parent=node;
    168 			pdbvt->m_root	=	node;
    169 		}
    170 	}
    171 }
    172 
    173 //
    174 static btDbvtNode*				removeleaf(	btDbvt* pdbvt,
    175 										   btDbvtNode* leaf)
    176 {
    177 	if(leaf==pdbvt->m_root)
    178 	{
    179 		pdbvt->m_root=0;
    180 		return(0);
    181 	}
    182 	else
    183 	{
    184 		btDbvtNode*	parent=leaf->parent;
    185 		btDbvtNode*	prev=parent->parent;
    186 		btDbvtNode*	sibling=parent->childs[1-indexof(leaf)];
    187 		if(prev)
    188 		{
    189 			prev->childs[indexof(parent)]=sibling;
    190 			sibling->parent=prev;
    191 			deletenode(pdbvt,parent);
    192 			while(prev)
    193 			{
    194 				const btDbvtVolume	pb=prev->volume;
    195 				Merge(prev->childs[0]->volume,prev->childs[1]->volume,prev->volume);
    196 				if(NotEqual(pb,prev->volume))
    197 				{
    198 					prev=prev->parent;
    199 				} else break;
    200 			}
    201 			return(prev?prev:pdbvt->m_root);
    202 		}
    203 		else
    204 		{
    205 			pdbvt->m_root=sibling;
    206 			sibling->parent=0;
    207 			deletenode(pdbvt,parent);
    208 			return(pdbvt->m_root);
    209 		}
    210 	}
    211 }
    212 
    213 //
    214 static void						fetchleaves(btDbvt* pdbvt,
    215 											btDbvtNode* root,
    216 											tNodeArray& leaves,
    217 											int depth=-1)
    218 {
    219 	if(root->isinternal()&&depth)
    220 	{
    221 		fetchleaves(pdbvt,root->childs[0],leaves,depth-1);
    222 		fetchleaves(pdbvt,root->childs[1],leaves,depth-1);
    223 		deletenode(pdbvt,root);
    224 	}
    225 	else
    226 	{
    227 		leaves.push_back(root);
    228 	}
    229 }
    230 
    231 //
    232 static void						split(	const tNodeArray& leaves,
    233 									  tNodeArray& left,
    234 									  tNodeArray& right,
    235 									  const btVector3& org,
    236 									  const btVector3& axis)
    237 {
    238 	left.resize(0);
    239 	right.resize(0);
    240 	for(int i=0,ni=leaves.size();i<ni;++i)
    241 	{
    242 		if(btDot(axis,leaves[i]->volume.Center()-org)<0)
    243 			left.push_back(leaves[i]);
    244 		else
    245 			right.push_back(leaves[i]);
    246 	}
    247 }
    248 
    249 //
    250 static btDbvtVolume				bounds(	const tNodeArray& leaves)
    251 {
    252 #if DBVT_MERGE_IMPL==DBVT_IMPL_SSE
    253 	ATTRIBUTE_ALIGNED16(char	locals[sizeof(btDbvtVolume)]);
    254 	btDbvtVolume* ptr = (btDbvtVolume*) locals;
    255 	btDbvtVolume&	volume=*ptr;
    256 	volume=leaves[0]->volume;
    257 #else
    258 	btDbvtVolume volume=leaves[0]->volume;
    259 #endif
    260 	for(int i=1,ni=leaves.size();i<ni;++i)
    261 	{
    262 		Merge(volume,leaves[i]->volume,volume);
    263 	}
    264 	return(volume);
    265 }
    266 
    267 //
    268 static void						bottomup(	btDbvt* pdbvt,
    269 										 tNodeArray& leaves)
    270 {
    271 	while(leaves.size()>1)
    272 	{
    273 		btScalar	minsize=SIMD_INFINITY;
    274 		int			minidx[2]={-1,-1};
    275 		for(int i=0;i<leaves.size();++i)
    276 		{
    277 			for(int j=i+1;j<leaves.size();++j)
    278 			{
    279 				const btScalar	sz=size(merge(leaves[i]->volume,leaves[j]->volume));
    280 				if(sz<minsize)
    281 				{
    282 					minsize		=	sz;
    283 					minidx[0]	=	i;
    284 					minidx[1]	=	j;
    285 				}
    286 			}
    287 		}
    288 		btDbvtNode*	n[]	=	{leaves[minidx[0]],leaves[minidx[1]]};
    289 		btDbvtNode*	p	=	createnode(pdbvt,0,n[0]->volume,n[1]->volume,0);
    290 		p->childs[0]		=	n[0];
    291 		p->childs[1]		=	n[1];
    292 		n[0]->parent		=	p;
    293 		n[1]->parent		=	p;
    294 		leaves[minidx[0]]	=	p;
    295 		leaves.swap(minidx[1],leaves.size()-1);
    296 		leaves.pop_back();
    297 	}
    298 }
    299 
    300 //
    301 static btDbvtNode*			topdown(btDbvt* pdbvt,
    302 									tNodeArray& leaves,
    303 									int bu_treshold)
    304 {
    305 	static const btVector3	axis[]={btVector3(1,0,0),
    306 		btVector3(0,1,0),
    307 		btVector3(0,0,1)};
    308 	if(leaves.size()>1)
    309 	{
    310 		if(leaves.size()>bu_treshold)
    311 		{
    312 			const btDbvtVolume	vol=bounds(leaves);
    313 			const btVector3			org=vol.Center();
    314 			tNodeArray				sets[2];
    315 			int						bestaxis=-1;
    316 			int						bestmidp=leaves.size();
    317 			int						splitcount[3][2]={{0,0},{0,0},{0,0}};
    318 			int i;
    319 			for( i=0;i<leaves.size();++i)
    320 			{
    321 				const btVector3	x=leaves[i]->volume.Center()-org;
    322 				for(int j=0;j<3;++j)
    323 				{
    324 					++splitcount[j][btDot(x,axis[j])>0?1:0];
    325 				}
    326 			}
    327 			for( i=0;i<3;++i)
    328 			{
    329 				if((splitcount[i][0]>0)&&(splitcount[i][1]>0))
    330 				{
    331 					const int	midp=(int)btFabs(btScalar(splitcount[i][0]-splitcount[i][1]));
    332 					if(midp<bestmidp)
    333 					{
    334 						bestaxis=i;
    335 						bestmidp=midp;
    336 					}
    337 				}
    338 			}
    339 			if(bestaxis>=0)
    340 			{
    341 				sets[0].reserve(splitcount[bestaxis][0]);
    342 				sets[1].reserve(splitcount[bestaxis][1]);
    343 				split(leaves,sets[0],sets[1],org,axis[bestaxis]);
    344 			}
    345 			else
    346 			{
    347 				sets[0].reserve(leaves.size()/2+1);
    348 				sets[1].reserve(leaves.size()/2);
    349 				for(int i=0,ni=leaves.size();i<ni;++i)
    350 				{
    351 					sets[i&1].push_back(leaves[i]);
    352 				}
    353 			}
    354 			btDbvtNode*	node=createnode(pdbvt,0,vol,0);
    355 			node->childs[0]=topdown(pdbvt,sets[0],bu_treshold);
    356 			node->childs[1]=topdown(pdbvt,sets[1],bu_treshold);
    357 			node->childs[0]->parent=node;
    358 			node->childs[1]->parent=node;
    359 			return(node);
    360 		}
    361 		else
    362 		{
    363 			bottomup(pdbvt,leaves);
    364 			return(leaves[0]);
    365 		}
    366 	}
    367 	return(leaves[0]);
    368 }
    369 
    370 //
    371 static DBVT_INLINE btDbvtNode*	sort(btDbvtNode* n,btDbvtNode*& r)
    372 {
    373 	btDbvtNode*	p=n->parent;
    374 	btAssert(n->isinternal());
    375 	if(p>n)
    376 	{
    377 		const int		i=indexof(n);
    378 		const int		j=1-i;
    379 		btDbvtNode*	s=p->childs[j];
    380 		btDbvtNode*	q=p->parent;
    381 		btAssert(n==p->childs[i]);
    382 		if(q) q->childs[indexof(p)]=n; else r=n;
    383 		s->parent=n;
    384 		p->parent=n;
    385 		n->parent=q;
    386 		p->childs[0]=n->childs[0];
    387 		p->childs[1]=n->childs[1];
    388 		n->childs[0]->parent=p;
    389 		n->childs[1]->parent=p;
    390 		n->childs[i]=p;
    391 		n->childs[j]=s;
    392 		btSwap(p->volume,n->volume);
    393 		return(p);
    394 	}
    395 	return(n);
    396 }
    397 
    398 #if 0
    399 static DBVT_INLINE btDbvtNode*	walkup(btDbvtNode* n,int count)
    400 {
    401 	while(n&&(count--)) n=n->parent;
    402 	return(n);
    403 }
    404 #endif
    405 
    406 //
    407 // Api
    408 //
    409 
    410 //
    411 btDbvt::btDbvt()
    412 {
    413 	m_root		=	0;
    414 	m_free		=	0;
    415 	m_lkhd		=	-1;
    416 	m_leaves	=	0;
    417 	m_opath		=	0;
    418 }
    419 
    420 //
    421 btDbvt::~btDbvt()
    422 {
    423 	clear();
    424 }
    425 
    426 //
    427 void			btDbvt::clear()
    428 {
    429 	if(m_root)
    430 		recursedeletenode(this,m_root);
    431 	btAlignedFree(m_free);
    432 	m_free=0;
    433 	m_lkhd		=	-1;
    434 	m_stkStack.clear();
    435 	m_opath		=	0;
    436 
    437 }
    438 
    439 //
    440 void			btDbvt::optimizeBottomUp()
    441 {
    442 	if(m_root)
    443 	{
    444 		tNodeArray leaves;
    445 		leaves.reserve(m_leaves);
    446 		fetchleaves(this,m_root,leaves);
    447 		bottomup(this,leaves);
    448 		m_root=leaves[0];
    449 	}
    450 }
    451 
    452 //
    453 void			btDbvt::optimizeTopDown(int bu_treshold)
    454 {
    455 	if(m_root)
    456 	{
    457 		tNodeArray	leaves;
    458 		leaves.reserve(m_leaves);
    459 		fetchleaves(this,m_root,leaves);
    460 		m_root=topdown(this,leaves,bu_treshold);
    461 	}
    462 }
    463 
    464 //
    465 void			btDbvt::optimizeIncremental(int passes)
    466 {
    467 	if(passes<0) passes=m_leaves;
    468 	if(m_root&&(passes>0))
    469 	{
    470 		do	{
    471 			btDbvtNode*		node=m_root;
    472 			unsigned	bit=0;
    473 			while(node->isinternal())
    474 			{
    475 				node=sort(node,m_root)->childs[(m_opath>>bit)&1];
    476 				bit=(bit+1)&(sizeof(unsigned)*8-1);
    477 			}
    478 			update(node);
    479 			++m_opath;
    480 		} while(--passes);
    481 	}
    482 }
    483 
    484 //
    485 btDbvtNode*	btDbvt::insert(const btDbvtVolume& volume,void* data)
    486 {
    487 	btDbvtNode*	leaf=createnode(this,0,volume,data);
    488 	insertleaf(this,m_root,leaf);
    489 	++m_leaves;
    490 	return(leaf);
    491 }
    492 
    493 //
    494 void			btDbvt::update(btDbvtNode* leaf,int lookahead)
    495 {
    496 	btDbvtNode*	root=removeleaf(this,leaf);
    497 	if(root)
    498 	{
    499 		if(lookahead>=0)
    500 		{
    501 			for(int i=0;(i<lookahead)&&root->parent;++i)
    502 			{
    503 				root=root->parent;
    504 			}
    505 		} else root=m_root;
    506 	}
    507 	insertleaf(this,root,leaf);
    508 }
    509 
    510 //
    511 void			btDbvt::update(btDbvtNode* leaf,btDbvtVolume& volume)
    512 {
    513 	btDbvtNode*	root=removeleaf(this,leaf);
    514 	if(root)
    515 	{
    516 		if(m_lkhd>=0)
    517 		{
    518 			for(int i=0;(i<m_lkhd)&&root->parent;++i)
    519 			{
    520 				root=root->parent;
    521 			}
    522 		} else root=m_root;
    523 	}
    524 	leaf->volume=volume;
    525 	insertleaf(this,root,leaf);
    526 }
    527 
    528 //
    529 bool			btDbvt::update(btDbvtNode* leaf,btDbvtVolume& volume,const btVector3& velocity,btScalar margin)
    530 {
    531 	if(leaf->volume.Contain(volume)) return(false);
    532 	volume.Expand(btVector3(margin,margin,margin));
    533 	volume.SignedExpand(velocity);
    534 	update(leaf,volume);
    535 	return(true);
    536 }
    537 
    538 //
    539 bool			btDbvt::update(btDbvtNode* leaf,btDbvtVolume& volume,const btVector3& velocity)
    540 {
    541 	if(leaf->volume.Contain(volume)) return(false);
    542 	volume.SignedExpand(velocity);
    543 	update(leaf,volume);
    544 	return(true);
    545 }
    546 
    547 //
    548 bool			btDbvt::update(btDbvtNode* leaf,btDbvtVolume& volume,btScalar margin)
    549 {
    550 	if(leaf->volume.Contain(volume)) return(false);
    551 	volume.Expand(btVector3(margin,margin,margin));
    552 	update(leaf,volume);
    553 	return(true);
    554 }
    555 
    556 //
    557 void			btDbvt::remove(btDbvtNode* leaf)
    558 {
    559 	removeleaf(this,leaf);
    560 	deletenode(this,leaf);
    561 	--m_leaves;
    562 }
    563 
    564 //
    565 void			btDbvt::write(IWriter* iwriter) const
    566 {
    567 	btDbvtNodeEnumerator	nodes;
    568 	nodes.nodes.reserve(m_leaves*2);
    569 	enumNodes(m_root,nodes);
    570 	iwriter->Prepare(m_root,nodes.nodes.size());
    571 	for(int i=0;i<nodes.nodes.size();++i)
    572 	{
    573 		const btDbvtNode* n=nodes.nodes[i];
    574 		int			p=-1;
    575 		if(n->parent) p=nodes.nodes.findLinearSearch(n->parent);
    576 		if(n->isinternal())
    577 		{
    578 			const int	c0=nodes.nodes.findLinearSearch(n->childs[0]);
    579 			const int	c1=nodes.nodes.findLinearSearch(n->childs[1]);
    580 			iwriter->WriteNode(n,i,p,c0,c1);
    581 		}
    582 		else
    583 		{
    584 			iwriter->WriteLeaf(n,i,p);
    585 		}
    586 	}
    587 }
    588 
    589 //
    590 void			btDbvt::clone(btDbvt& dest,IClone* iclone) const
    591 {
    592 	dest.clear();
    593 	if(m_root!=0)
    594 	{
    595 		btAlignedObjectArray<sStkCLN>	stack;
    596 		stack.reserve(m_leaves);
    597 		stack.push_back(sStkCLN(m_root,0));
    598 		do	{
    599 			const int		i=stack.size()-1;
    600 			const sStkCLN	e=stack[i];
    601 			btDbvtNode*			n=createnode(&dest,e.parent,e.node->volume,e.node->data);
    602 			stack.pop_back();
    603 			if(e.parent!=0)
    604 				e.parent->childs[i&1]=n;
    605 			else
    606 				dest.m_root=n;
    607 			if(e.node->isinternal())
    608 			{
    609 				stack.push_back(sStkCLN(e.node->childs[0],n));
    610 				stack.push_back(sStkCLN(e.node->childs[1],n));
    611 			}
    612 			else
    613 			{
    614 				iclone->CloneLeaf(n);
    615 			}
    616 		} while(stack.size()>0);
    617 	}
    618 }
    619 
    620 //
    621 int				btDbvt::maxdepth(const btDbvtNode* node)
    622 {
    623 	int	depth=0;
    624 	if(node) getmaxdepth(node,1,depth);
    625 	return(depth);
    626 }
    627 
    628 //
    629 int				btDbvt::countLeaves(const btDbvtNode* node)
    630 {
    631 	if(node->isinternal())
    632 		return(countLeaves(node->childs[0])+countLeaves(node->childs[1]));
    633 	else
    634 		return(1);
    635 }
    636 
    637 //
    638 void			btDbvt::extractLeaves(const btDbvtNode* node,btAlignedObjectArray<const btDbvtNode*>& leaves)
    639 {
    640 	if(node->isinternal())
    641 	{
    642 		extractLeaves(node->childs[0],leaves);
    643 		extractLeaves(node->childs[1],leaves);
    644 	}
    645 	else
    646 	{
    647 		leaves.push_back(node);
    648 	}
    649 }
    650 
    651 //
    652 #if DBVT_ENABLE_BENCHMARK
    653 
    654 #include <stdio.h>
    655 #include <stdlib.h>
    656 #include "LinearMath/btQuickProf.h"
    657 
    658 /*
    659 q6600,2.4ghz
    660 
    661 /Ox /Ob2 /Oi /Ot /I "." /I "..\.." /I "..\..\src" /D "NDEBUG" /D "_LIB" /D "_WINDOWS" /D "_CRT_SECURE_NO_DEPRECATE" /D "_CRT_NONSTDC_NO_DEPRECATE" /D "WIN32"
    662 /GF /FD /MT /GS- /Gy /arch:SSE2 /Zc:wchar_t- /Fp"..\..\out\release8\build\libbulletcollision\libbulletcollision.pch"
    663 /Fo"..\..\out\release8\build\libbulletcollision\\"
    664 /Fd"..\..\out\release8\build\libbulletcollision\bulletcollision.pdb"
    665 /W3 /nologo /c /Wp64 /Zi /errorReport:prompt
    666 
    667 Benchmarking dbvt...
    668 World scale: 100.000000
    669 Extents base: 1.000000
    670 Extents range: 4.000000
    671 Leaves: 8192
    672 sizeof(btDbvtVolume): 32 bytes
    673 sizeof(btDbvtNode):   44 bytes
    674 [1] btDbvtVolume intersections: 3499 ms (-1%)
    675 [2] btDbvtVolume merges: 1934 ms (0%)
    676 [3] btDbvt::collideTT: 5485 ms (-21%)
    677 [4] btDbvt::collideTT self: 2814 ms (-20%)
    678 [5] btDbvt::collideTT xform: 7379 ms (-1%)
    679 [6] btDbvt::collideTT xform,self: 7270 ms (-2%)
    680 [7] btDbvt::rayTest: 6314 ms (0%),(332143 r/s)
    681 [8] insert/remove: 2093 ms (0%),(1001983 ir/s)
    682 [9] updates (teleport): 1879 ms (-3%),(1116100 u/s)
    683 [10] updates (jitter): 1244 ms (-4%),(1685813 u/s)
    684 [11] optimize (incremental): 2514 ms (0%),(1668000 o/s)
    685 [12] btDbvtVolume notequal: 3659 ms (0%)
    686 [13] culling(OCL+fullsort): 2218 ms (0%),(461 t/s)
    687 [14] culling(OCL+qsort): 3688 ms (5%),(2221 t/s)
    688 [15] culling(KDOP+qsort): 1139 ms (-1%),(7192 t/s)
    689 [16] insert/remove batch(256): 5092 ms (0%),(823704 bir/s)
    690 [17] btDbvtVolume select: 3419 ms (0%)
    691 */
    692 
    693 struct btDbvtBenchmark
    694 {
    695 	struct NilPolicy : btDbvt::ICollide
    696 	{
    697 		NilPolicy() : m_pcount(0),m_depth(-SIMD_INFINITY),m_checksort(true)		{}
    698 		void	Process(const btDbvtNode*,const btDbvtNode*)				{ ++m_pcount; }
    699 		void	Process(const btDbvtNode*)									{ ++m_pcount; }
    700 		void	Process(const btDbvtNode*,btScalar depth)
    701 		{
    702 			++m_pcount;
    703 			if(m_checksort)
    704 			{ if(depth>=m_depth) m_depth=depth; else printf("wrong depth: %f (should be >= %f)\r\n",depth,m_depth); }
    705 		}
    706 		int			m_pcount;
    707 		btScalar	m_depth;
    708 		bool		m_checksort;
    709 	};
    710 	struct P14 : btDbvt::ICollide
    711 	{
    712 		struct Node
    713 		{
    714 			const btDbvtNode*	leaf;
    715 			btScalar			depth;
    716 		};
    717 		void Process(const btDbvtNode* leaf,btScalar depth)
    718 		{
    719 			Node	n;
    720 			n.leaf	=	leaf;
    721 			n.depth	=	depth;
    722 		}
    723 		static int sortfnc(const Node& a,const Node& b)
    724 		{
    725 			if(a.depth<b.depth) return(+1);
    726 			if(a.depth>b.depth) return(-1);
    727 			return(0);
    728 		}
    729 		btAlignedObjectArray<Node>		m_nodes;
    730 	};
    731 	struct P15 : btDbvt::ICollide
    732 	{
    733 		struct Node
    734 		{
    735 			const btDbvtNode*	leaf;
    736 			btScalar			depth;
    737 		};
    738 		void Process(const btDbvtNode* leaf)
    739 		{
    740 			Node	n;
    741 			n.leaf	=	leaf;
    742 			n.depth	=	dot(leaf->volume.Center(),m_axis);
    743 		}
    744 		static int sortfnc(const Node& a,const Node& b)
    745 		{
    746 			if(a.depth<b.depth) return(+1);
    747 			if(a.depth>b.depth) return(-1);
    748 			return(0);
    749 		}
    750 		btAlignedObjectArray<Node>		m_nodes;
    751 		btVector3						m_axis;
    752 	};
    753 	static btScalar			RandUnit()
    754 	{
    755 		return(rand()/(btScalar)RAND_MAX);
    756 	}
    757 	static btVector3		RandVector3()
    758 	{
    759 		return(btVector3(RandUnit(),RandUnit(),RandUnit()));
    760 	}
    761 	static btVector3		RandVector3(btScalar cs)
    762 	{
    763 		return(RandVector3()*cs-btVector3(cs,cs,cs)/2);
    764 	}
    765 	static btDbvtVolume	RandVolume(btScalar cs,btScalar eb,btScalar es)
    766 	{
    767 		return(btDbvtVolume::FromCE(RandVector3(cs),btVector3(eb,eb,eb)+RandVector3()*es));
    768 	}
    769 	static btTransform		RandTransform(btScalar cs)
    770 	{
    771 		btTransform	t;
    772 		t.setOrigin(RandVector3(cs));
    773 		t.setRotation(btQuaternion(RandUnit()*SIMD_PI*2,RandUnit()*SIMD_PI*2,RandUnit()*SIMD_PI*2).normalized());
    774 		return(t);
    775 	}
    776 	static void				RandTree(btScalar cs,btScalar eb,btScalar es,int leaves,btDbvt& dbvt)
    777 	{
    778 		dbvt.clear();
    779 		for(int i=0;i<leaves;++i)
    780 		{
    781 			dbvt.insert(RandVolume(cs,eb,es),0);
    782 		}
    783 	}
    784 };
    785 
    786 void			btDbvt::benchmark()
    787 {
    788 	static const btScalar	cfgVolumeCenterScale		=	100;
    789 	static const btScalar	cfgVolumeExentsBase			=	1;
    790 	static const btScalar	cfgVolumeExentsScale		=	4;
    791 	static const int		cfgLeaves					=	8192;
    792 	static const bool		cfgEnable					=	true;
    793 
    794 	//[1] btDbvtVolume intersections
    795 	bool					cfgBenchmark1_Enable		=	cfgEnable;
    796 	static const int		cfgBenchmark1_Iterations	=	8;
    797 	static const int		cfgBenchmark1_Reference		=	3499;
    798 	//[2] btDbvtVolume merges
    799 	bool					cfgBenchmark2_Enable		=	cfgEnable;
    800 	static const int		cfgBenchmark2_Iterations	=	4;
    801 	static const int		cfgBenchmark2_Reference		=	1945;
    802 	//[3] btDbvt::collideTT
    803 	bool					cfgBenchmark3_Enable		=	cfgEnable;
    804 	static const int		cfgBenchmark3_Iterations	=	512;
    805 	static const int		cfgBenchmark3_Reference		=	5485;
    806 	//[4] btDbvt::collideTT self
    807 	bool					cfgBenchmark4_Enable		=	cfgEnable;
    808 	static const int		cfgBenchmark4_Iterations	=	512;
    809 	static const int		cfgBenchmark4_Reference		=	2814;
    810 	//[5] btDbvt::collideTT xform
    811 	bool					cfgBenchmark5_Enable		=	cfgEnable;
    812 	static const int		cfgBenchmark5_Iterations	=	512;
    813 	static const btScalar	cfgBenchmark5_OffsetScale	=	2;
    814 	static const int		cfgBenchmark5_Reference		=	7379;
    815 	//[6] btDbvt::collideTT xform,self
    816 	bool					cfgBenchmark6_Enable		=	cfgEnable;
    817 	static const int		cfgBenchmark6_Iterations	=	512;
    818 	static const btScalar	cfgBenchmark6_OffsetScale	=	2;
    819 	static const int		cfgBenchmark6_Reference		=	7270;
    820 	//[7] btDbvt::rayTest
    821 	bool					cfgBenchmark7_Enable		=	cfgEnable;
    822 	static const int		cfgBenchmark7_Passes		=	32;
    823 	static const int		cfgBenchmark7_Iterations	=	65536;
    824 	static const int		cfgBenchmark7_Reference		=	6307;
    825 	//[8] insert/remove
    826 	bool					cfgBenchmark8_Enable		=	cfgEnable;
    827 	static const int		cfgBenchmark8_Passes		=	32;
    828 	static const int		cfgBenchmark8_Iterations	=	65536;
    829 	static const int		cfgBenchmark8_Reference		=	2105;
    830 	//[9] updates (teleport)
    831 	bool					cfgBenchmark9_Enable		=	cfgEnable;
    832 	static const int		cfgBenchmark9_Passes		=	32;
    833 	static const int		cfgBenchmark9_Iterations	=	65536;
    834 	static const int		cfgBenchmark9_Reference		=	1879;
    835 	//[10] updates (jitter)
    836 	bool					cfgBenchmark10_Enable		=	cfgEnable;
    837 	static const btScalar	cfgBenchmark10_Scale		=	cfgVolumeCenterScale/10000;
    838 	static const int		cfgBenchmark10_Passes		=	32;
    839 	static const int		cfgBenchmark10_Iterations	=	65536;
    840 	static const int		cfgBenchmark10_Reference	=	1244;
    841 	//[11] optimize (incremental)
    842 	bool					cfgBenchmark11_Enable		=	cfgEnable;
    843 	static const int		cfgBenchmark11_Passes		=	64;
    844 	static const int		cfgBenchmark11_Iterations	=	65536;
    845 	static const int		cfgBenchmark11_Reference	=	2510;
    846 	//[12] btDbvtVolume notequal
    847 	bool					cfgBenchmark12_Enable		=	cfgEnable;
    848 	static const int		cfgBenchmark12_Iterations	=	32;
    849 	static const int		cfgBenchmark12_Reference	=	3677;
    850 	//[13] culling(OCL+fullsort)
    851 	bool					cfgBenchmark13_Enable		=	cfgEnable;
    852 	static const int		cfgBenchmark13_Iterations	=	1024;
    853 	static const int		cfgBenchmark13_Reference	=	2231;
    854 	//[14] culling(OCL+qsort)
    855 	bool					cfgBenchmark14_Enable		=	cfgEnable;
    856 	static const int		cfgBenchmark14_Iterations	=	8192;
    857 	static const int		cfgBenchmark14_Reference	=	3500;
    858 	//[15] culling(KDOP+qsort)
    859 	bool					cfgBenchmark15_Enable		=	cfgEnable;
    860 	static const int		cfgBenchmark15_Iterations	=	8192;
    861 	static const int		cfgBenchmark15_Reference	=	1151;
    862 	//[16] insert/remove batch
    863 	bool					cfgBenchmark16_Enable		=	cfgEnable;
    864 	static const int		cfgBenchmark16_BatchCount	=	256;
    865 	static const int		cfgBenchmark16_Passes		=	16384;
    866 	static const int		cfgBenchmark16_Reference	=	5138;
    867 	//[17] select
    868 	bool					cfgBenchmark17_Enable		=	cfgEnable;
    869 	static const int		cfgBenchmark17_Iterations	=	4;
    870 	static const int		cfgBenchmark17_Reference	=	3390;
    871 
    872 	btClock					wallclock;
    873 	printf("Benchmarking dbvt...\r\n");
    874 	printf("\tWorld scale: %f\r\n",cfgVolumeCenterScale);
    875 	printf("\tExtents base: %f\r\n",cfgVolumeExentsBase);
    876 	printf("\tExtents range: %f\r\n",cfgVolumeExentsScale);
    877 	printf("\tLeaves: %u\r\n",cfgLeaves);
    878 	printf("\tsizeof(btDbvtVolume): %u bytes\r\n",sizeof(btDbvtVolume));
    879 	printf("\tsizeof(btDbvtNode):   %u bytes\r\n",sizeof(btDbvtNode));
    880 	if(cfgBenchmark1_Enable)
    881 	{// Benchmark 1
    882 		srand(380843);
    883 		btAlignedObjectArray<btDbvtVolume>	volumes;
    884 		btAlignedObjectArray<bool>			results;
    885 		volumes.resize(cfgLeaves);
    886 		results.resize(cfgLeaves);
    887 		for(int i=0;i<cfgLeaves;++i)
    888 		{
    889 			volumes[i]=btDbvtBenchmark::RandVolume(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale);
    890 		}
    891 		printf("[1] btDbvtVolume intersections: ");
    892 		wallclock.reset();
    893 		for(int i=0;i<cfgBenchmark1_Iterations;++i)
    894 		{
    895 			for(int j=0;j<cfgLeaves;++j)
    896 			{
    897 				for(int k=0;k<cfgLeaves;++k)
    898 				{
    899 					results[k]=Intersect(volumes[j],volumes[k]);
    900 				}
    901 			}
    902 		}
    903 		const int time=(int)wallclock.getTimeMilliseconds();
    904 		printf("%u ms (%i%%)\r\n",time,(time-cfgBenchmark1_Reference)*100/time);
    905 	}
    906 	if(cfgBenchmark2_Enable)
    907 	{// Benchmark 2
    908 		srand(380843);
    909 		btAlignedObjectArray<btDbvtVolume>	volumes;
    910 		btAlignedObjectArray<btDbvtVolume>	results;
    911 		volumes.resize(cfgLeaves);
    912 		results.resize(cfgLeaves);
    913 		for(int i=0;i<cfgLeaves;++i)
    914 		{
    915 			volumes[i]=btDbvtBenchmark::RandVolume(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale);
    916 		}
    917 		printf("[2] btDbvtVolume merges: ");
    918 		wallclock.reset();
    919 		for(int i=0;i<cfgBenchmark2_Iterations;++i)
    920 		{
    921 			for(int j=0;j<cfgLeaves;++j)
    922 			{
    923 				for(int k=0;k<cfgLeaves;++k)
    924 				{
    925 					Merge(volumes[j],volumes[k],results[k]);
    926 				}
    927 			}
    928 		}
    929 		const int time=(int)wallclock.getTimeMilliseconds();
    930 		printf("%u ms (%i%%)\r\n",time,(time-cfgBenchmark2_Reference)*100/time);
    931 	}
    932 	if(cfgBenchmark3_Enable)
    933 	{// Benchmark 3
    934 		srand(380843);
    935 		btDbvt						dbvt[2];
    936 		btDbvtBenchmark::NilPolicy	policy;
    937 		btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt[0]);
    938 		btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt[1]);
    939 		dbvt[0].optimizeTopDown();
    940 		dbvt[1].optimizeTopDown();
    941 		printf("[3] btDbvt::collideTT: ");
    942 		wallclock.reset();
    943 		for(int i=0;i<cfgBenchmark3_Iterations;++i)
    944 		{
    945 			btDbvt::collideTT(dbvt[0].m_root,dbvt[1].m_root,policy);
    946 		}
    947 		const int time=(int)wallclock.getTimeMilliseconds();
    948 		printf("%u ms (%i%%)\r\n",time,(time-cfgBenchmark3_Reference)*100/time);
    949 	}
    950 	if(cfgBenchmark4_Enable)
    951 	{// Benchmark 4
    952 		srand(380843);
    953 		btDbvt						dbvt;
    954 		btDbvtBenchmark::NilPolicy	policy;
    955 		btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
    956 		dbvt.optimizeTopDown();
    957 		printf("[4] btDbvt::collideTT self: ");
    958 		wallclock.reset();
    959 		for(int i=0;i<cfgBenchmark4_Iterations;++i)
    960 		{
    961 			btDbvt::collideTT(dbvt.m_root,dbvt.m_root,policy);
    962 		}
    963 		const int time=(int)wallclock.getTimeMilliseconds();
    964 		printf("%u ms (%i%%)\r\n",time,(time-cfgBenchmark4_Reference)*100/time);
    965 	}
    966 	if(cfgBenchmark5_Enable)
    967 	{// Benchmark 5
    968 		srand(380843);
    969 		btDbvt								dbvt[2];
    970 		btAlignedObjectArray<btTransform>	transforms;
    971 		btDbvtBenchmark::NilPolicy			policy;
    972 		transforms.resize(cfgBenchmark5_Iterations);
    973 		for(int i=0;i<transforms.size();++i)
    974 		{
    975 			transforms[i]=btDbvtBenchmark::RandTransform(cfgVolumeCenterScale*cfgBenchmark5_OffsetScale);
    976 		}
    977 		btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt[0]);
    978 		btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt[1]);
    979 		dbvt[0].optimizeTopDown();
    980 		dbvt[1].optimizeTopDown();
    981 		printf("[5] btDbvt::collideTT xform: ");
    982 		wallclock.reset();
    983 		for(int i=0;i<cfgBenchmark5_Iterations;++i)
    984 		{
    985 			btDbvt::collideTT(dbvt[0].m_root,dbvt[1].m_root,transforms[i],policy);
    986 		}
    987 		const int time=(int)wallclock.getTimeMilliseconds();
    988 		printf("%u ms (%i%%)\r\n",time,(time-cfgBenchmark5_Reference)*100/time);
    989 	}
    990 	if(cfgBenchmark6_Enable)
    991 	{// Benchmark 6
    992 		srand(380843);
    993 		btDbvt								dbvt;
    994 		btAlignedObjectArray<btTransform>	transforms;
    995 		btDbvtBenchmark::NilPolicy			policy;
    996 		transforms.resize(cfgBenchmark6_Iterations);
    997 		for(int i=0;i<transforms.size();++i)
    998 		{
    999 			transforms[i]=btDbvtBenchmark::RandTransform(cfgVolumeCenterScale*cfgBenchmark6_OffsetScale);
   1000 		}
   1001 		btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
   1002 		dbvt.optimizeTopDown();
   1003 		printf("[6] btDbvt::collideTT xform,self: ");
   1004 		wallclock.reset();
   1005 		for(int i=0;i<cfgBenchmark6_Iterations;++i)
   1006 		{
   1007 			btDbvt::collideTT(dbvt.m_root,dbvt.m_root,transforms[i],policy);
   1008 		}
   1009 		const int time=(int)wallclock.getTimeMilliseconds();
   1010 		printf("%u ms (%i%%)\r\n",time,(time-cfgBenchmark6_Reference)*100/time);
   1011 	}
   1012 	if(cfgBenchmark7_Enable)
   1013 	{// Benchmark 7
   1014 		srand(380843);
   1015 		btDbvt								dbvt;
   1016 		btAlignedObjectArray<btVector3>		rayorg;
   1017 		btAlignedObjectArray<btVector3>		raydir;
   1018 		btDbvtBenchmark::NilPolicy			policy;
   1019 		rayorg.resize(cfgBenchmark7_Iterations);
   1020 		raydir.resize(cfgBenchmark7_Iterations);
   1021 		for(int i=0;i<rayorg.size();++i)
   1022 		{
   1023 			rayorg[i]=btDbvtBenchmark::RandVector3(cfgVolumeCenterScale*2);
   1024 			raydir[i]=btDbvtBenchmark::RandVector3(cfgVolumeCenterScale*2);
   1025 		}
   1026 		btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
   1027 		dbvt.optimizeTopDown();
   1028 		printf("[7] btDbvt::rayTest: ");
   1029 		wallclock.reset();
   1030 		for(int i=0;i<cfgBenchmark7_Passes;++i)
   1031 		{
   1032 			for(int j=0;j<cfgBenchmark7_Iterations;++j)
   1033 			{
   1034 				btDbvt::rayTest(dbvt.m_root,rayorg[j],rayorg[j]+raydir[j],policy);
   1035 			}
   1036 		}
   1037 		const int	time=(int)wallclock.getTimeMilliseconds();
   1038 		unsigned	rays=cfgBenchmark7_Passes*cfgBenchmark7_Iterations;
   1039 		printf("%u ms (%i%%),(%u r/s)\r\n",time,(time-cfgBenchmark7_Reference)*100/time,(rays*1000)/time);
   1040 	}
   1041 	if(cfgBenchmark8_Enable)
   1042 	{// Benchmark 8
   1043 		srand(380843);
   1044 		btDbvt								dbvt;
   1045 		btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
   1046 		dbvt.optimizeTopDown();
   1047 		printf("[8] insert/remove: ");
   1048 		wallclock.reset();
   1049 		for(int i=0;i<cfgBenchmark8_Passes;++i)
   1050 		{
   1051 			for(int j=0;j<cfgBenchmark8_Iterations;++j)
   1052 			{
   1053 				dbvt.remove(dbvt.insert(btDbvtBenchmark::RandVolume(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale),0));
   1054 			}
   1055 		}
   1056 		const int	time=(int)wallclock.getTimeMilliseconds();
   1057 		const int	ir=cfgBenchmark8_Passes*cfgBenchmark8_Iterations;
   1058 		printf("%u ms (%i%%),(%u ir/s)\r\n",time,(time-cfgBenchmark8_Reference)*100/time,ir*1000/time);
   1059 	}
   1060 	if(cfgBenchmark9_Enable)
   1061 	{// Benchmark 9
   1062 		srand(380843);
   1063 		btDbvt										dbvt;
   1064 		btAlignedObjectArray<const btDbvtNode*>	leaves;
   1065 		btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
   1066 		dbvt.optimizeTopDown();
   1067 		dbvt.extractLeaves(dbvt.m_root,leaves);
   1068 		printf("[9] updates (teleport): ");
   1069 		wallclock.reset();
   1070 		for(int i=0;i<cfgBenchmark9_Passes;++i)
   1071 		{
   1072 			for(int j=0;j<cfgBenchmark9_Iterations;++j)
   1073 			{
   1074 				dbvt.update(const_cast<btDbvtNode*>(leaves[rand()%cfgLeaves]),
   1075 					btDbvtBenchmark::RandVolume(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale));
   1076 			}
   1077 		}
   1078 		const int	time=(int)wallclock.getTimeMilliseconds();
   1079 		const int	up=cfgBenchmark9_Passes*cfgBenchmark9_Iterations;
   1080 		printf("%u ms (%i%%),(%u u/s)\r\n",time,(time-cfgBenchmark9_Reference)*100/time,up*1000/time);
   1081 	}
   1082 	if(cfgBenchmark10_Enable)
   1083 	{// Benchmark 10
   1084 		srand(380843);
   1085 		btDbvt										dbvt;
   1086 		btAlignedObjectArray<const btDbvtNode*>	leaves;
   1087 		btAlignedObjectArray<btVector3>				vectors;
   1088 		vectors.resize(cfgBenchmark10_Iterations);
   1089 		for(int i=0;i<vectors.size();++i)
   1090 		{
   1091 			vectors[i]=(btDbvtBenchmark::RandVector3()*2-btVector3(1,1,1))*cfgBenchmark10_Scale;
   1092 		}
   1093 		btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
   1094 		dbvt.optimizeTopDown();
   1095 		dbvt.extractLeaves(dbvt.m_root,leaves);
   1096 		printf("[10] updates (jitter): ");
   1097 		wallclock.reset();
   1098 
   1099 		for(int i=0;i<cfgBenchmark10_Passes;++i)
   1100 		{
   1101 			for(int j=0;j<cfgBenchmark10_Iterations;++j)
   1102 			{
   1103 				const btVector3&	d=vectors[j];
   1104 				btDbvtNode*		l=const_cast<btDbvtNode*>(leaves[rand()%cfgLeaves]);
   1105 				btDbvtVolume		v=btDbvtVolume::FromMM(l->volume.Mins()+d,l->volume.Maxs()+d);
   1106 				dbvt.update(l,v);
   1107 			}
   1108 		}
   1109 		const int	time=(int)wallclock.getTimeMilliseconds();
   1110 		const int	up=cfgBenchmark10_Passes*cfgBenchmark10_Iterations;
   1111 		printf("%u ms (%i%%),(%u u/s)\r\n",time,(time-cfgBenchmark10_Reference)*100/time,up*1000/time);
   1112 	}
   1113 	if(cfgBenchmark11_Enable)
   1114 	{// Benchmark 11
   1115 		srand(380843);
   1116 		btDbvt										dbvt;
   1117 		btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
   1118 		dbvt.optimizeTopDown();
   1119 		printf("[11] optimize (incremental): ");
   1120 		wallclock.reset();
   1121 		for(int i=0;i<cfgBenchmark11_Passes;++i)
   1122 		{
   1123 			dbvt.optimizeIncremental(cfgBenchmark11_Iterations);
   1124 		}
   1125 		const int	time=(int)wallclock.getTimeMilliseconds();
   1126 		const int	op=cfgBenchmark11_Passes*cfgBenchmark11_Iterations;
   1127 		printf("%u ms (%i%%),(%u o/s)\r\n",time,(time-cfgBenchmark11_Reference)*100/time,op/time*1000);
   1128 	}
   1129 	if(cfgBenchmark12_Enable)
   1130 	{// Benchmark 12
   1131 		srand(380843);
   1132 		btAlignedObjectArray<btDbvtVolume>	volumes;
   1133 		btAlignedObjectArray<bool>				results;
   1134 		volumes.resize(cfgLeaves);
   1135 		results.resize(cfgLeaves);
   1136 		for(int i=0;i<cfgLeaves;++i)
   1137 		{
   1138 			volumes[i]=btDbvtBenchmark::RandVolume(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale);
   1139 		}
   1140 		printf("[12] btDbvtVolume notequal: ");
   1141 		wallclock.reset();
   1142 		for(int i=0;i<cfgBenchmark12_Iterations;++i)
   1143 		{
   1144 			for(int j=0;j<cfgLeaves;++j)
   1145 			{
   1146 				for(int k=0;k<cfgLeaves;++k)
   1147 				{
   1148 					results[k]=NotEqual(volumes[j],volumes[k]);
   1149 				}
   1150 			}
   1151 		}
   1152 		const int time=(int)wallclock.getTimeMilliseconds();
   1153 		printf("%u ms (%i%%)\r\n",time,(time-cfgBenchmark12_Reference)*100/time);
   1154 	}
   1155 	if(cfgBenchmark13_Enable)
   1156 	{// Benchmark 13
   1157 		srand(380843);
   1158 		btDbvt								dbvt;
   1159 		btAlignedObjectArray<btVector3>		vectors;
   1160 		btDbvtBenchmark::NilPolicy			policy;
   1161 		vectors.resize(cfgBenchmark13_Iterations);
   1162 		for(int i=0;i<vectors.size();++i)
   1163 		{
   1164 			vectors[i]=(btDbvtBenchmark::RandVector3()*2-btVector3(1,1,1)).normalized();
   1165 		}
   1166 		btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
   1167 		dbvt.optimizeTopDown();
   1168 		printf("[13] culling(OCL+fullsort): ");
   1169 		wallclock.reset();
   1170 		for(int i=0;i<cfgBenchmark13_Iterations;++i)
   1171 		{
   1172 			static const btScalar	offset=0;
   1173 			policy.m_depth=-SIMD_INFINITY;
   1174 			dbvt.collideOCL(dbvt.m_root,&vectors[i],&offset,vectors[i],1,policy);
   1175 		}
   1176 		const int	time=(int)wallclock.getTimeMilliseconds();
   1177 		const int	t=cfgBenchmark13_Iterations;
   1178 		printf("%u ms (%i%%),(%u t/s)\r\n",time,(time-cfgBenchmark13_Reference)*100/time,(t*1000)/time);
   1179 	}
   1180 	if(cfgBenchmark14_Enable)
   1181 	{// Benchmark 14
   1182 		srand(380843);
   1183 		btDbvt								dbvt;
   1184 		btAlignedObjectArray<btVector3>		vectors;
   1185 		btDbvtBenchmark::P14				policy;
   1186 		vectors.resize(cfgBenchmark14_Iterations);
   1187 		for(int i=0;i<vectors.size();++i)
   1188 		{
   1189 			vectors[i]=(btDbvtBenchmark::RandVector3()*2-btVector3(1,1,1)).normalized();
   1190 		}
   1191 		btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
   1192 		dbvt.optimizeTopDown();
   1193 		policy.m_nodes.reserve(cfgLeaves);
   1194 		printf("[14] culling(OCL+qsort): ");
   1195 		wallclock.reset();
   1196 		for(int i=0;i<cfgBenchmark14_Iterations;++i)
   1197 		{
   1198 			static const btScalar	offset=0;
   1199 			policy.m_nodes.resize(0);
   1200 			dbvt.collideOCL(dbvt.m_root,&vectors[i],&offset,vectors[i],1,policy,false);
   1201 			policy.m_nodes.quickSort(btDbvtBenchmark::P14::sortfnc);
   1202 		}
   1203 		const int	time=(int)wallclock.getTimeMilliseconds();
   1204 		const int	t=cfgBenchmark14_Iterations;
   1205 		printf("%u ms (%i%%),(%u t/s)\r\n",time,(time-cfgBenchmark14_Reference)*100/time,(t*1000)/time);
   1206 	}
   1207 	if(cfgBenchmark15_Enable)
   1208 	{// Benchmark 15
   1209 		srand(380843);
   1210 		btDbvt								dbvt;
   1211 		btAlignedObjectArray<btVector3>		vectors;
   1212 		btDbvtBenchmark::P15				policy;
   1213 		vectors.resize(cfgBenchmark15_Iterations);
   1214 		for(int i=0;i<vectors.size();++i)
   1215 		{
   1216 			vectors[i]=(btDbvtBenchmark::RandVector3()*2-btVector3(1,1,1)).normalized();
   1217 		}
   1218 		btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
   1219 		dbvt.optimizeTopDown();
   1220 		policy.m_nodes.reserve(cfgLeaves);
   1221 		printf("[15] culling(KDOP+qsort): ");
   1222 		wallclock.reset();
   1223 		for(int i=0;i<cfgBenchmark15_Iterations;++i)
   1224 		{
   1225 			static const btScalar	offset=0;
   1226 			policy.m_nodes.resize(0);
   1227 			policy.m_axis=vectors[i];
   1228 			dbvt.collideKDOP(dbvt.m_root,&vectors[i],&offset,1,policy);
   1229 			policy.m_nodes.quickSort(btDbvtBenchmark::P15::sortfnc);
   1230 		}
   1231 		const int	time=(int)wallclock.getTimeMilliseconds();
   1232 		const int	t=cfgBenchmark15_Iterations;
   1233 		printf("%u ms (%i%%),(%u t/s)\r\n",time,(time-cfgBenchmark15_Reference)*100/time,(t*1000)/time);
   1234 	}
   1235 	if(cfgBenchmark16_Enable)
   1236 	{// Benchmark 16
   1237 		srand(380843);
   1238 		btDbvt								dbvt;
   1239 		btAlignedObjectArray<btDbvtNode*>	batch;
   1240 		btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
   1241 		dbvt.optimizeTopDown();
   1242 		batch.reserve(cfgBenchmark16_BatchCount);
   1243 		printf("[16] insert/remove batch(%u): ",cfgBenchmark16_BatchCount);
   1244 		wallclock.reset();
   1245 		for(int i=0;i<cfgBenchmark16_Passes;++i)
   1246 		{
   1247 			for(int j=0;j<cfgBenchmark16_BatchCount;++j)
   1248 			{
   1249 				batch.push_back(dbvt.insert(btDbvtBenchmark::RandVolume(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale),0));
   1250 			}
   1251 			for(int j=0;j<cfgBenchmark16_BatchCount;++j)
   1252 			{
   1253 				dbvt.remove(batch[j]);
   1254 			}
   1255 			batch.resize(0);
   1256 		}
   1257 		const int	time=(int)wallclock.getTimeMilliseconds();
   1258 		const int	ir=cfgBenchmark16_Passes*cfgBenchmark16_BatchCount;
   1259 		printf("%u ms (%i%%),(%u bir/s)\r\n",time,(time-cfgBenchmark16_Reference)*100/time,int(ir*1000.0/time));
   1260 	}
   1261 	if(cfgBenchmark17_Enable)
   1262 	{// Benchmark 17
   1263 		srand(380843);
   1264 		btAlignedObjectArray<btDbvtVolume>	volumes;
   1265 		btAlignedObjectArray<int>			results;
   1266 		btAlignedObjectArray<int>			indices;
   1267 		volumes.resize(cfgLeaves);
   1268 		results.resize(cfgLeaves);
   1269 		indices.resize(cfgLeaves);
   1270 		for(int i=0;i<cfgLeaves;++i)
   1271 		{
   1272 			indices[i]=i;
   1273 			volumes[i]=btDbvtBenchmark::RandVolume(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale);
   1274 		}
   1275 		for(int i=0;i<cfgLeaves;++i)
   1276 		{
   1277 			btSwap(indices[i],indices[rand()%cfgLeaves]);
   1278 		}
   1279 		printf("[17] btDbvtVolume select: ");
   1280 		wallclock.reset();
   1281 		for(int i=0;i<cfgBenchmark17_Iterations;++i)
   1282 		{
   1283 			for(int j=0;j<cfgLeaves;++j)
   1284 			{
   1285 				for(int k=0;k<cfgLeaves;++k)
   1286 				{
   1287 					const int idx=indices[k];
   1288 					results[idx]=Select(volumes[idx],volumes[j],volumes[k]);
   1289 				}
   1290 			}
   1291 		}
   1292 		const int time=(int)wallclock.getTimeMilliseconds();
   1293 		printf("%u ms (%i%%)\r\n",time,(time-cfgBenchmark17_Reference)*100/time);
   1294 	}
   1295 	printf("\r\n\r\n");
   1296 }
   1297 #endif
   1298