com.bulletphysics.collision.broadphase.DbvtBroadphase Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jbullet Show documentation
Show all versions of jbullet Show documentation
JBullet - Java port of Bullet Physics Library
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() {
}
}