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