All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.bulletphysics.collision.broadphase.DbvtBroadphase Maven / Gradle / Ivy

The newest version!
/*
 * Java port of Bullet (c) 2008 Martin Dvorak 
 *
 * Bullet Continuous Collision Detection and Physics Library
 * Copyright (c) 2003-2008 Erwin Coumans  http://www.bulletphysics.com/
 *
 * This software is provided 'as-is', without any express or implied warranty.
 * In no event will the authors be held liable for any damages arising from
 * the use of this software.
 *
 * Permission is granted to anyone to use this software for any purpose,
 * including commercial applications, and to alter it and redistribute it
 * freely, subject to the following restrictions:
 *
 * 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.
 * 2. Altered source versions must be plainly marked as such, and must not be
 *    misrepresented as being the original software.
 * 3. This notice may not be removed or altered from any source distribution.
 */

// Dbvt implementation by Nathanael Presson

package com.bulletphysics.collision.broadphase;

import com.bulletphysics.util.ObjectArrayList;
import cz.advel.stack.Stack;
import javax.vecmath.Vector3f;

/**
 *
 * @author jezek2
 */
public class DbvtBroadphase extends BroadphaseInterface {

	public static final float DBVT_BP_MARGIN = 0.05f;

	public static final int DYNAMIC_SET = 0; // Dynamic set index
	public static final int FIXED_SET   = 1; // Fixed set index
	public static final int STAGECOUNT  = 2; // Number of stages

	public final Dbvt[] sets = new Dbvt[2];                        // Dbvt sets
	public DbvtProxy[] stageRoots = new DbvtProxy[STAGECOUNT + 1]; // Stages list
	public OverlappingPairCache paircache;                         // Pair cache
	public float predictedframes;                                  // Frames predicted
	public int stageCurrent;                                       // Current stage
	public int fupdates;                                           // % of fixed updates per frame
	public int dupdates;                                           // % of dynamic updates per frame
	public int pid;                                                // Parse id
	public int gid;                                                // Gen id
	public boolean releasepaircache;                               // Release pair cache on delete

	//#if DBVT_BP_PROFILE
	//btClock					m_clock;
	//struct	{
	//		unsigned long		m_total;
	//		unsigned long		m_ddcollide;
	//		unsigned long		m_fdcollide;
	//		unsigned long		m_cleanup;
	//		unsigned long		m_jobcount;
	//		}				m_profiling;
	//#endif

	public DbvtBroadphase() {
		this(null);
	}

	public DbvtBroadphase(OverlappingPairCache paircache) {
		sets[0] = new Dbvt();
		sets[1] = new Dbvt();

		//Dbvt.benchmark();
		releasepaircache = (paircache != null? false : true);
		predictedframes = 2;
		stageCurrent = 0;
		fupdates = 1;
		dupdates = 1;
		this.paircache = (paircache != null? paircache : new HashedOverlappingPairCache());
		gid = 0;
		pid = 0;

		for (int i=0; i<=STAGECOUNT; i++) {
			stageRoots[i] = null;
		}
		//#if DBVT_BP_PROFILE
		//clear(m_profiling);
		//#endif
	}

	public void collide(Dispatcher dispatcher) {
		//SPC(m_profiling.m_total);

		// optimize:
		sets[0].optimizeIncremental(1 + (sets[0].leaves * dupdates) / 100);
		sets[1].optimizeIncremental(1 + (sets[1].leaves * fupdates) / 100);

		// dynamic -> fixed set:
		stageCurrent = (stageCurrent + 1) % STAGECOUNT;
		DbvtProxy current = stageRoots[stageCurrent];
		if (current != null) {
			DbvtTreeCollider collider = new DbvtTreeCollider(this);
			do {
				DbvtProxy next = current.links[1];
				stageRoots[current.stage] = listremove(current, stageRoots[current.stage]);
				stageRoots[STAGECOUNT] = listappend(current, stageRoots[STAGECOUNT]);
				Dbvt.collideTT(sets[1].root, current.leaf, collider);
				sets[0].remove(current.leaf);
				current.leaf = sets[1].insert(current.aabb, current);
				current.stage = STAGECOUNT;
				current = next;
			} while (current != null);
		}

		// collide dynamics:
		{
			DbvtTreeCollider collider = new DbvtTreeCollider(this);
			{
				//SPC(m_profiling.m_fdcollide);
				Dbvt.collideTT(sets[0].root, sets[1].root, collider);
			}
			{
				//SPC(m_profiling.m_ddcollide);
				Dbvt.collideTT(sets[0].root, sets[0].root, collider);
			}
		}

		// clean up:
		{
			//SPC(m_profiling.m_cleanup);
			ObjectArrayList pairs = paircache.getOverlappingPairArray();
			if (pairs.size() > 0) {
				for (int i=0, ni=pairs.size(); ipb) btSwap(pa,pb);
						if (pa.hashCode() > pb.hashCode()) {
							DbvtProxy tmp = pa;
							pa = pb;
							pb = tmp;
						}
						paircache.removeOverlappingPair(pa, pb, dispatcher);
						ni--;
						i--;
					}
				}
			}
		}
		pid++;
	}

	private static DbvtProxy listappend(DbvtProxy item, DbvtProxy list) {
		item.links[0] = null;
		item.links[1] = list;
		if (list != null) list.links[0] = item;
		list = item;
		return list;
	}

	private static DbvtProxy listremove(DbvtProxy item, DbvtProxy list) {
		if (item.links[0] != null) {
			item.links[0].links[1] = item.links[1];
		}
		else {
			list = item.links[1];
		}
		
		if (item.links[1] != null) {
			item.links[1].links[0] = item.links[0];
		}
		return list;
	}

	public BroadphaseProxy createProxy(Vector3f aabbMin, Vector3f aabbMax, BroadphaseNativeType shapeType, Object userPtr, short collisionFilterGroup, short collisionFilterMask, Dispatcher dispatcher, Object multiSapProxy) {
		DbvtProxy proxy = new DbvtProxy(userPtr, collisionFilterGroup, collisionFilterMask);
		DbvtAabbMm.FromMM(aabbMin, aabbMax, proxy.aabb);
		proxy.leaf = sets[0].insert(proxy.aabb, proxy);
		proxy.stage = stageCurrent;
		proxy.uniqueId = ++gid;
		stageRoots[stageCurrent] = listappend(proxy, stageRoots[stageCurrent]);
		return (proxy);
	}

	public void destroyProxy(BroadphaseProxy absproxy, Dispatcher dispatcher) {
		DbvtProxy proxy = (DbvtProxy)absproxy;
		if (proxy.stage == STAGECOUNT) {
			sets[1].remove(proxy.leaf);
		}
		else {
			sets[0].remove(proxy.leaf);
		}
		stageRoots[proxy.stage] = listremove(proxy, stageRoots[proxy.stage]);
		paircache.removeOverlappingPairsContainingProxy(proxy, dispatcher);
		//btAlignedFree(proxy);
	}

	public void setAabb(BroadphaseProxy absproxy, Vector3f aabbMin, Vector3f aabbMax, Dispatcher dispatcher) {
		DbvtProxy proxy = (DbvtProxy)absproxy;
		DbvtAabbMm aabb = DbvtAabbMm.FromMM(aabbMin, aabbMax, new DbvtAabbMm());
		if (proxy.stage == STAGECOUNT) {
			// fixed -> dynamic set
			sets[1].remove(proxy.leaf);
			proxy.leaf = sets[0].insert(aabb, proxy);
		}
		else {
			// dynamic set:
			if (DbvtAabbMm.Intersect(proxy.leaf.volume, aabb)) {/* Moving				*/
				Vector3f delta = Stack.alloc(Vector3f.class);
				delta.add(aabbMin, aabbMax);
				delta.scale(0.5f);
				delta.sub(proxy.aabb.Center(Stack.alloc(Vector3f.class)));
				//#ifdef DBVT_BP_MARGIN
				delta.scale(predictedframes);
				sets[0].update(proxy.leaf, aabb, delta, DBVT_BP_MARGIN);
				//#else
				//m_sets[0].update(proxy->leaf,aabb,delta*m_predictedframes);
				//#endif
			}
			else {
				// teleporting:
				sets[0].update(proxy.leaf, aabb);
			}
		}
		
		stageRoots[proxy.stage] = listremove(proxy, stageRoots[proxy.stage]);
		proxy.aabb.set(aabb);
		proxy.stage = stageCurrent;
		stageRoots[stageCurrent] = listappend(proxy, stageRoots[stageCurrent]);
	}

	public void calculateOverlappingPairs(Dispatcher dispatcher) {
		collide(dispatcher);
		
		//#if DBVT_BP_PROFILE
		//if(0==(m_pid%DBVT_BP_PROFILING_RATE))
		//	{
		//	printf("fixed(%u) dynamics(%u) pairs(%u)\r\n",m_sets[1].m_leafs,m_sets[0].m_leafs,m_paircache->getNumOverlappingPairs());
		//	printf("mode:    %s\r\n",m_mode==MODE_FULL?"full":"incremental");
		//	printf("cleanup: %s\r\n",m_cleanupmode==CLEANUP_FULL?"full":"incremental");
		//	unsigned int	total=m_profiling.m_total;
		//	if(total<=0) total=1;
		//	printf("ddcollide: %u%% (%uus)\r\n",(50+m_profiling.m_ddcollide*100)/total,m_profiling.m_ddcollide/DBVT_BP_PROFILING_RATE);
		//	printf("fdcollide: %u%% (%uus)\r\n",(50+m_profiling.m_fdcollide*100)/total,m_profiling.m_fdcollide/DBVT_BP_PROFILING_RATE);
		//	printf("cleanup:   %u%% (%uus)\r\n",(50+m_profiling.m_cleanup*100)/total,m_profiling.m_cleanup/DBVT_BP_PROFILING_RATE);
		//	printf("total:     %uus\r\n",total/DBVT_BP_PROFILING_RATE);
		//	const unsigned long	sum=m_profiling.m_ddcollide+
		//							m_profiling.m_fdcollide+
		//							m_profiling.m_cleanup;
		//	printf("leaked: %u%% (%uus)\r\n",100-((50+sum*100)/total),(total-sum)/DBVT_BP_PROFILING_RATE);
		//	printf("job counts: %u%%\r\n",(m_profiling.m_jobcount*100)/((m_sets[0].m_leafs+m_sets[1].m_leafs)*DBVT_BP_PROFILING_RATE));
		//	clear(m_profiling);
		//	m_clock.reset();
		//	}
		//#endif
	}

	public OverlappingPairCache getOverlappingPairCache() {
		return paircache;
	}

	public void getBroadphaseAabb(Vector3f aabbMin, Vector3f aabbMax) {
		DbvtAabbMm bounds = new DbvtAabbMm();
		if (!sets[0].empty()) {
			if (!sets[1].empty()) {
				DbvtAabbMm.Merge(sets[0].root.volume, sets[1].root.volume, bounds);
			}
			else {
				bounds.set(sets[0].root.volume);
			}
		}
		else if (!sets[1].empty()) {
			bounds.set(sets[1].root.volume);
		}
		else {
			DbvtAabbMm.FromCR(new Vector3f(0f, 0f, 0f), 0f, bounds);
		}
		aabbMin.set(bounds.Mins());
		aabbMax.set(bounds.Maxs());
	}

	public void printStats() {
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy