forked from bartvdbraak/blender
soc-2008-mxcurioni: FRS_glBlendEquation files
This commit is contained in:
parent
5812c494a5
commit
bb8477ec57
1289
extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvt.cpp
vendored
Normal file
1289
extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvt.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1112
extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvt.h
vendored
Normal file
1112
extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvt.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
548
extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp
vendored
Normal file
548
extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp
vendored
Normal file
@ -0,0 +1,548 @@
|
|||||||
|
/*
|
||||||
|
Bullet Continuous Collision Detection and Physics Library
|
||||||
|
Copyright (c) 2003-2007 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
///btDbvtBroadphase implementation by Nathanael Presson
|
||||||
|
|
||||||
|
#include "btDbvtBroadphase.h"
|
||||||
|
|
||||||
|
//
|
||||||
|
// Profiling
|
||||||
|
//
|
||||||
|
|
||||||
|
#if DBVT_BP_PROFILE||DBVT_BP_ENABLE_BENCHMARK
|
||||||
|
#include <stdio.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if DBVT_BP_PROFILE
|
||||||
|
struct ProfileScope
|
||||||
|
{
|
||||||
|
__forceinline ProfileScope(btClock& clock,unsigned long& value) :
|
||||||
|
m_clock(&clock),m_value(&value),m_base(clock.getTimeMicroseconds())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
__forceinline ~ProfileScope()
|
||||||
|
{
|
||||||
|
(*m_value)+=m_clock->getTimeMicroseconds()-m_base;
|
||||||
|
}
|
||||||
|
btClock* m_clock;
|
||||||
|
unsigned long* m_value;
|
||||||
|
unsigned long m_base;
|
||||||
|
};
|
||||||
|
#define SPC(_value_) ProfileScope spc_scope(m_clock,_value_)
|
||||||
|
#else
|
||||||
|
#define SPC(_value_)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//
|
||||||
|
// Helpers
|
||||||
|
//
|
||||||
|
|
||||||
|
//
|
||||||
|
template <typename T>
|
||||||
|
static inline void listappend(T* item,T*& list)
|
||||||
|
{
|
||||||
|
item->links[0]=0;
|
||||||
|
item->links[1]=list;
|
||||||
|
if(list) list->links[0]=item;
|
||||||
|
list=item;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
template <typename T>
|
||||||
|
static inline void listremove(T* item,T*& list)
|
||||||
|
{
|
||||||
|
if(item->links[0]) item->links[0]->links[1]=item->links[1]; else list=item->links[1];
|
||||||
|
if(item->links[1]) item->links[1]->links[0]=item->links[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
template <typename T>
|
||||||
|
static inline int listcount(T* root)
|
||||||
|
{
|
||||||
|
int n=0;
|
||||||
|
while(root) { ++n;root=root->links[1]; }
|
||||||
|
return(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
template <typename T>
|
||||||
|
static inline void clear(T& value)
|
||||||
|
{
|
||||||
|
static const struct ZeroDummy : T {} zerodummy;
|
||||||
|
value=zerodummy;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Colliders
|
||||||
|
//
|
||||||
|
|
||||||
|
/* Tree collider */
|
||||||
|
struct btDbvtTreeCollider : btDbvt::ICollide
|
||||||
|
{
|
||||||
|
btDbvtBroadphase* pbp;
|
||||||
|
btDbvtProxy* proxy;
|
||||||
|
btDbvtTreeCollider(btDbvtBroadphase* p) : pbp(p) {}
|
||||||
|
void Process(const btDbvtNode* na,const btDbvtNode* nb)
|
||||||
|
{
|
||||||
|
if(na!=nb)
|
||||||
|
{
|
||||||
|
btDbvtProxy* pa=(btDbvtProxy*)na->data;
|
||||||
|
btDbvtProxy* pb=(btDbvtProxy*)nb->data;
|
||||||
|
#if DBVT_BP_SORTPAIRS
|
||||||
|
if(pa>pb) btSwap(pa,pb);
|
||||||
|
#endif
|
||||||
|
pbp->m_paircache->addOverlappingPair(pa,pb);
|
||||||
|
++pbp->m_newpairs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void Process(const btDbvtNode* n)
|
||||||
|
{
|
||||||
|
Process(n,proxy->leaf);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// btDbvtBroadphase
|
||||||
|
//
|
||||||
|
|
||||||
|
//
|
||||||
|
btDbvtBroadphase::btDbvtBroadphase(btOverlappingPairCache* paircache)
|
||||||
|
{
|
||||||
|
m_deferedcollide = false;
|
||||||
|
m_needcleanup = true;
|
||||||
|
m_releasepaircache = (paircache!=0)?false:true;
|
||||||
|
m_prediction = 1/(btScalar)2;
|
||||||
|
m_stageCurrent = 0;
|
||||||
|
m_fixedleft = 0;
|
||||||
|
m_fupdates = 1;
|
||||||
|
m_dupdates = 0;
|
||||||
|
m_cupdates = 10;
|
||||||
|
m_newpairs = 1;
|
||||||
|
m_updates_call = 0;
|
||||||
|
m_updates_done = 0;
|
||||||
|
m_updates_ratio = 0;
|
||||||
|
m_paircache = paircache?
|
||||||
|
paircache :
|
||||||
|
new(btAlignedAlloc(sizeof(btHashedOverlappingPairCache),16)) btHashedOverlappingPairCache();
|
||||||
|
m_gid = 0;
|
||||||
|
m_pid = 0;
|
||||||
|
m_cid = 0;
|
||||||
|
for(int i=0;i<=STAGECOUNT;++i)
|
||||||
|
{
|
||||||
|
m_stageRoots[i]=0;
|
||||||
|
}
|
||||||
|
#if DBVT_BP_PROFILE
|
||||||
|
clear(m_profiling);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
btDbvtBroadphase::~btDbvtBroadphase()
|
||||||
|
{
|
||||||
|
if(m_releasepaircache)
|
||||||
|
{
|
||||||
|
m_paircache->~btOverlappingPairCache();
|
||||||
|
btAlignedFree(m_paircache);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
btBroadphaseProxy* btDbvtBroadphase::createProxy( const btVector3& aabbMin,
|
||||||
|
const btVector3& aabbMax,
|
||||||
|
int /*shapeType*/,
|
||||||
|
void* userPtr,
|
||||||
|
short int collisionFilterGroup,
|
||||||
|
short int collisionFilterMask,
|
||||||
|
btDispatcher* /*dispatcher*/,
|
||||||
|
void* /*multiSapProxy*/)
|
||||||
|
{
|
||||||
|
btDbvtProxy* proxy=new(btAlignedAlloc(sizeof(btDbvtProxy),16)) btDbvtProxy( userPtr,
|
||||||
|
collisionFilterGroup,
|
||||||
|
collisionFilterMask);
|
||||||
|
proxy->aabb = btDbvtVolume::FromMM(aabbMin,aabbMax);
|
||||||
|
proxy->stage = m_stageCurrent;
|
||||||
|
proxy->m_uniqueId = ++m_gid;
|
||||||
|
proxy->leaf = m_sets[0].insert(proxy->aabb,proxy);
|
||||||
|
listappend(proxy,m_stageRoots[m_stageCurrent]);
|
||||||
|
if(!m_deferedcollide)
|
||||||
|
{
|
||||||
|
btDbvtTreeCollider collider(this);
|
||||||
|
collider.proxy=proxy;
|
||||||
|
btDbvt::collideTV(m_sets[0].m_root,proxy->aabb,collider);
|
||||||
|
btDbvt::collideTV(m_sets[1].m_root,proxy->aabb,collider);
|
||||||
|
}
|
||||||
|
return(proxy);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
void btDbvtBroadphase::destroyProxy( btBroadphaseProxy* absproxy,
|
||||||
|
btDispatcher* dispatcher)
|
||||||
|
{
|
||||||
|
btDbvtProxy* proxy=(btDbvtProxy*)absproxy;
|
||||||
|
if(proxy->stage==STAGECOUNT)
|
||||||
|
m_sets[1].remove(proxy->leaf);
|
||||||
|
else
|
||||||
|
m_sets[0].remove(proxy->leaf);
|
||||||
|
listremove(proxy,m_stageRoots[proxy->stage]);
|
||||||
|
m_paircache->removeOverlappingPairsContainingProxy(proxy,dispatcher);
|
||||||
|
btAlignedFree(proxy);
|
||||||
|
m_needcleanup=true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
void btDbvtBroadphase::setAabb( btBroadphaseProxy* absproxy,
|
||||||
|
const btVector3& aabbMin,
|
||||||
|
const btVector3& aabbMax,
|
||||||
|
btDispatcher* /*dispatcher*/)
|
||||||
|
{
|
||||||
|
btDbvtProxy* proxy=(btDbvtProxy*)absproxy;
|
||||||
|
ATTRIBUTE_ALIGNED16(btDbvtVolume) aabb=btDbvtVolume::FromMM(aabbMin,aabbMax);
|
||||||
|
#if DBVT_BP_PREVENTFALSEUPDATE
|
||||||
|
if(NotEqual(aabb,proxy->leaf->volume))
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
bool docollide=false;
|
||||||
|
if(proxy->stage==STAGECOUNT)
|
||||||
|
{/* fixed -> dynamic set */
|
||||||
|
m_sets[1].remove(proxy->leaf);
|
||||||
|
proxy->leaf=m_sets[0].insert(aabb,proxy);
|
||||||
|
docollide=true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{/* dynamic set */
|
||||||
|
++m_updates_call;
|
||||||
|
if(Intersect(proxy->leaf->volume,aabb))
|
||||||
|
{/* Moving */
|
||||||
|
const btVector3 delta=aabbMin-proxy->aabb.Mins();
|
||||||
|
btVector3 velocity(aabb.Extents()*m_prediction);
|
||||||
|
if(delta[0]<0) velocity[0]=-velocity[0];
|
||||||
|
if(delta[1]<0) velocity[1]=-velocity[1];
|
||||||
|
if(delta[2]<0) velocity[2]=-velocity[2];
|
||||||
|
if (
|
||||||
|
#ifdef DBVT_BP_MARGIN
|
||||||
|
m_sets[0].update(proxy->leaf,aabb,velocity,DBVT_BP_MARGIN)
|
||||||
|
#else
|
||||||
|
m_sets[0].update(proxy->leaf,aabb,velocity)
|
||||||
|
#endif
|
||||||
|
)
|
||||||
|
{
|
||||||
|
++m_updates_done;
|
||||||
|
docollide=true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{/* Teleporting */
|
||||||
|
m_sets[0].update(proxy->leaf,aabb);
|
||||||
|
++m_updates_done;
|
||||||
|
docollide=true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
listremove(proxy,m_stageRoots[proxy->stage]);
|
||||||
|
proxy->aabb = aabb;
|
||||||
|
proxy->stage = m_stageCurrent;
|
||||||
|
listappend(proxy,m_stageRoots[m_stageCurrent]);
|
||||||
|
if(docollide)
|
||||||
|
{
|
||||||
|
m_needcleanup=true;
|
||||||
|
if(!m_deferedcollide)
|
||||||
|
{
|
||||||
|
btDbvtTreeCollider collider(this);
|
||||||
|
btDbvt::collideTT(m_sets[1].m_root,proxy->leaf,collider);
|
||||||
|
btDbvt::collideTT(m_sets[0].m_root,proxy->leaf,collider);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
void btDbvtBroadphase::calculateOverlappingPairs(btDispatcher* 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_leaves,m_sets[0].m_leaves,m_paircache->getNumOverlappingPairs());
|
||||||
|
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_leaves+m_sets[1].m_leaves)*DBVT_BP_PROFILING_RATE));
|
||||||
|
clear(m_profiling);
|
||||||
|
m_clock.reset();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
void btDbvtBroadphase::collide(btDispatcher* dispatcher)
|
||||||
|
{
|
||||||
|
SPC(m_profiling.m_total);
|
||||||
|
/* optimize */
|
||||||
|
m_sets[0].optimizeIncremental(1+(m_sets[0].m_leaves*m_dupdates)/100);
|
||||||
|
if(m_fixedleft)
|
||||||
|
{
|
||||||
|
const int count=1+(m_sets[1].m_leaves*m_fupdates)/100;
|
||||||
|
m_sets[1].optimizeIncremental(1+(m_sets[1].m_leaves*m_fupdates)/100);
|
||||||
|
m_fixedleft=btMax<int>(0,m_fixedleft-count);
|
||||||
|
}
|
||||||
|
/* dynamic -> fixed set */
|
||||||
|
m_stageCurrent=(m_stageCurrent+1)%STAGECOUNT;
|
||||||
|
btDbvtProxy* current=m_stageRoots[m_stageCurrent];
|
||||||
|
if(current)
|
||||||
|
{
|
||||||
|
btDbvtTreeCollider collider(this);
|
||||||
|
do {
|
||||||
|
btDbvtProxy* next=current->links[1];
|
||||||
|
listremove(current,m_stageRoots[current->stage]);
|
||||||
|
listappend(current,m_stageRoots[STAGECOUNT]);
|
||||||
|
#if DBVT_BP_ACCURATESLEEPING
|
||||||
|
m_paircache->removeOverlappingPairsContainingProxy(current,dispatcher);
|
||||||
|
collider.proxy=current;
|
||||||
|
btDbvt::collideTV(m_sets[0].m_root,current->aabb,collider);
|
||||||
|
btDbvt::collideTV(m_sets[1].m_root,current->aabb,collider);
|
||||||
|
#endif
|
||||||
|
m_sets[0].remove(current->leaf);
|
||||||
|
current->leaf = m_sets[1].insert(current->aabb,current);
|
||||||
|
current->stage = STAGECOUNT;
|
||||||
|
current = next;
|
||||||
|
} while(current);
|
||||||
|
m_fixedleft=m_sets[1].m_leaves;
|
||||||
|
m_needcleanup=true;
|
||||||
|
}
|
||||||
|
/* collide dynamics */
|
||||||
|
{
|
||||||
|
btDbvtTreeCollider collider(this);
|
||||||
|
if(m_deferedcollide)
|
||||||
|
{
|
||||||
|
SPC(m_profiling.m_fdcollide);
|
||||||
|
btDbvt::collideTT(m_sets[0].m_root,m_sets[1].m_root,collider);
|
||||||
|
}
|
||||||
|
if(m_deferedcollide)
|
||||||
|
{
|
||||||
|
SPC(m_profiling.m_ddcollide);
|
||||||
|
btDbvt::collideTT(m_sets[0].m_root,m_sets[0].m_root,collider);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* clean up */
|
||||||
|
if(m_needcleanup)
|
||||||
|
{
|
||||||
|
SPC(m_profiling.m_cleanup);
|
||||||
|
btBroadphasePairArray& pairs=m_paircache->getOverlappingPairArray();
|
||||||
|
if(pairs.size()>0)
|
||||||
|
{
|
||||||
|
const int ci=pairs.size();
|
||||||
|
int ni=btMin(ci,btMax<int>(m_newpairs,(ci*m_cupdates)/100));
|
||||||
|
for(int i=0;i<ni;++i)
|
||||||
|
{
|
||||||
|
btBroadphasePair& p=pairs[(m_cid+i)%ci];
|
||||||
|
btDbvtProxy* pa=(btDbvtProxy*)p.m_pProxy0;
|
||||||
|
btDbvtProxy* pb=(btDbvtProxy*)p.m_pProxy1;
|
||||||
|
if(!Intersect(pa->leaf->volume,pb->leaf->volume))
|
||||||
|
{
|
||||||
|
#if DBVT_BP_SORTPAIRS
|
||||||
|
if(pa>pb) btSwap(pa,pb);
|
||||||
|
#endif
|
||||||
|
m_paircache->removeOverlappingPair(pa,pb,dispatcher);
|
||||||
|
--ni;--i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(pairs.size()>0) m_cid=(m_cid+ni)%pairs.size(); else m_cid=0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
++m_pid;
|
||||||
|
m_newpairs=1;
|
||||||
|
m_needcleanup=false;
|
||||||
|
if(m_updates_call>0)
|
||||||
|
{ m_updates_ratio=m_updates_done/(btScalar)m_updates_call; }
|
||||||
|
else
|
||||||
|
{ m_updates_ratio=0; }
|
||||||
|
m_updates_done/=2;
|
||||||
|
m_updates_call/=2;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
void btDbvtBroadphase::optimize()
|
||||||
|
{
|
||||||
|
m_sets[0].optimizeTopDown();
|
||||||
|
m_sets[1].optimizeTopDown();
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
btOverlappingPairCache* btDbvtBroadphase::getOverlappingPairCache()
|
||||||
|
{
|
||||||
|
return(m_paircache);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
const btOverlappingPairCache* btDbvtBroadphase::getOverlappingPairCache() const
|
||||||
|
{
|
||||||
|
return(m_paircache);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
void btDbvtBroadphase::getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const
|
||||||
|
{
|
||||||
|
|
||||||
|
ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds;
|
||||||
|
|
||||||
|
if(!m_sets[0].empty())
|
||||||
|
if(!m_sets[1].empty()) Merge( m_sets[0].m_root->volume,
|
||||||
|
m_sets[1].m_root->volume,bounds);
|
||||||
|
else
|
||||||
|
bounds=m_sets[0].m_root->volume;
|
||||||
|
else if(!m_sets[1].empty()) bounds=m_sets[1].m_root->volume;
|
||||||
|
else
|
||||||
|
bounds=btDbvtVolume::FromCR(btVector3(0,0,0),0);
|
||||||
|
aabbMin=bounds.Mins();
|
||||||
|
aabbMax=bounds.Maxs();
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
void btDbvtBroadphase::printStats()
|
||||||
|
{}
|
||||||
|
|
||||||
|
//
|
||||||
|
#if DBVT_BP_ENABLE_BENCHMARK
|
||||||
|
|
||||||
|
struct btBroadphaseBenchmark
|
||||||
|
{
|
||||||
|
struct Experiment
|
||||||
|
{
|
||||||
|
const char* name;
|
||||||
|
int object_count;
|
||||||
|
int update_count;
|
||||||
|
int spawn_count;
|
||||||
|
int iterations;
|
||||||
|
btScalar speed;
|
||||||
|
btScalar amplitude;
|
||||||
|
};
|
||||||
|
struct Object
|
||||||
|
{
|
||||||
|
btVector3 center;
|
||||||
|
btVector3 extents;
|
||||||
|
btBroadphaseProxy* proxy;
|
||||||
|
btScalar time;
|
||||||
|
void update(btScalar speed,btScalar amplitude,btBroadphaseInterface* pbi)
|
||||||
|
{
|
||||||
|
time += speed;
|
||||||
|
center[0] = btCos(time*(btScalar)2.17)*amplitude+
|
||||||
|
btSin(time)*amplitude/2;
|
||||||
|
center[1] = btCos(time*(btScalar)1.38)*amplitude+
|
||||||
|
btSin(time)*amplitude;
|
||||||
|
center[2] = btSin(time*(btScalar)0.777)*amplitude;
|
||||||
|
pbi->setAabb(proxy,center-extents,center+extents,0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
static int UnsignedRand(int range=RAND_MAX-1) { return(rand()%(range+1)); }
|
||||||
|
static btScalar UnitRand() { return(UnsignedRand(16384)/(btScalar)16384); }
|
||||||
|
static void OutputTime(const char* name,btClock& c,unsigned count=0)
|
||||||
|
{
|
||||||
|
const unsigned long us=c.getTimeMicroseconds();
|
||||||
|
const unsigned long ms=(us+500)/1000;
|
||||||
|
const btScalar sec=us/(btScalar)(1000*1000);
|
||||||
|
if(count>0)
|
||||||
|
printf("%s : %u us (%u ms), %.2f/s\r\n",name,us,ms,count/sec);
|
||||||
|
else
|
||||||
|
printf("%s : %u us (%u ms)\r\n",name,us,ms);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void btDbvtBroadphase::benchmark(btBroadphaseInterface* pbi)
|
||||||
|
{
|
||||||
|
static const btBroadphaseBenchmark::Experiment experiments[]=
|
||||||
|
{
|
||||||
|
{"1024o.10%",1024,10,0,8192,(btScalar)0.005,(btScalar)100},
|
||||||
|
/*{"4096o.10%",4096,10,0,8192,(btScalar)0.005,(btScalar)100},
|
||||||
|
{"8192o.10%",8192,10,0,8192,(btScalar)0.005,(btScalar)100},*/
|
||||||
|
};
|
||||||
|
static const int nexperiments=sizeof(experiments)/sizeof(experiments[0]);
|
||||||
|
btAlignedObjectArray<btBroadphaseBenchmark::Object*> objects;
|
||||||
|
btClock wallclock;
|
||||||
|
/* Begin */
|
||||||
|
for(int iexp=0;iexp<nexperiments;++iexp)
|
||||||
|
{
|
||||||
|
const btBroadphaseBenchmark::Experiment& experiment=experiments[iexp];
|
||||||
|
const int object_count=experiment.object_count;
|
||||||
|
const int update_count=(object_count*experiment.update_count)/100;
|
||||||
|
const int spawn_count=(object_count*experiment.spawn_count)/100;
|
||||||
|
const btScalar speed=experiment.speed;
|
||||||
|
const btScalar amplitude=experiment.amplitude;
|
||||||
|
printf("Experiment #%u '%s':\r\n",iexp,experiment.name);
|
||||||
|
printf("\tObjects: %u\r\n",object_count);
|
||||||
|
printf("\tUpdate: %u\r\n",update_count);
|
||||||
|
printf("\tSpawn: %u\r\n",spawn_count);
|
||||||
|
printf("\tSpeed: %f\r\n",speed);
|
||||||
|
printf("\tAmplitude: %f\r\n",amplitude);
|
||||||
|
srand(180673);
|
||||||
|
/* Create objects */
|
||||||
|
wallclock.reset();
|
||||||
|
objects.reserve(object_count);
|
||||||
|
for(int i=0;i<object_count;++i)
|
||||||
|
{
|
||||||
|
btBroadphaseBenchmark::Object* po=new btBroadphaseBenchmark::Object();
|
||||||
|
po->center[0]=btBroadphaseBenchmark::UnitRand()*50;
|
||||||
|
po->center[1]=btBroadphaseBenchmark::UnitRand()*50;
|
||||||
|
po->center[2]=btBroadphaseBenchmark::UnitRand()*50;
|
||||||
|
po->extents[0]=btBroadphaseBenchmark::UnitRand()*2+2;
|
||||||
|
po->extents[1]=btBroadphaseBenchmark::UnitRand()*2+2;
|
||||||
|
po->extents[2]=btBroadphaseBenchmark::UnitRand()*2+2;
|
||||||
|
po->time=btBroadphaseBenchmark::UnitRand()*2000;
|
||||||
|
po->proxy=pbi->createProxy(po->center-po->extents,po->center+po->extents,0,po,1,1,0,0);
|
||||||
|
objects.push_back(po);
|
||||||
|
}
|
||||||
|
btBroadphaseBenchmark::OutputTime("\tInitialization",wallclock);
|
||||||
|
/* First update */
|
||||||
|
wallclock.reset();
|
||||||
|
for(int i=0;i<objects.size();++i)
|
||||||
|
{
|
||||||
|
objects[i]->update(speed,amplitude,pbi);
|
||||||
|
}
|
||||||
|
btBroadphaseBenchmark::OutputTime("\tFirst update",wallclock);
|
||||||
|
/* Updates */
|
||||||
|
wallclock.reset();
|
||||||
|
for(int i=0;i<experiment.iterations;++i)
|
||||||
|
{
|
||||||
|
for(int j=0;j<update_count;++j)
|
||||||
|
{
|
||||||
|
objects[j]->update(speed,amplitude,pbi);
|
||||||
|
}
|
||||||
|
pbi->calculateOverlappingPairs(0);
|
||||||
|
}
|
||||||
|
btBroadphaseBenchmark::OutputTime("\tUpdate",wallclock,experiment.iterations);
|
||||||
|
/* Clean up */
|
||||||
|
wallclock.reset();
|
||||||
|
for(int i=0;i<objects.size();++i)
|
||||||
|
{
|
||||||
|
pbi->destroyProxy(objects[i]->proxy,0);
|
||||||
|
delete objects[i];
|
||||||
|
}
|
||||||
|
objects.resize(0);
|
||||||
|
btBroadphaseBenchmark::OutputTime("\tRelease",wallclock);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
void btDbvtBroadphase::benchmark(btBroadphaseInterface*)
|
||||||
|
{}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if DBVT_BP_PROFILE
|
||||||
|
#undef SPC
|
||||||
|
#endif
|
116
extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.h
vendored
Normal file
116
extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.h
vendored
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
/*
|
||||||
|
Bullet Continuous Collision Detection and Physics Library
|
||||||
|
Copyright (c) 2003-2007 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
///btDbvtBroadphase implementation by Nathanael Presson
|
||||||
|
#ifndef BT_DBVT_BROADPHASE_H
|
||||||
|
#define BT_DBVT_BROADPHASE_H
|
||||||
|
|
||||||
|
#include "BulletCollision/BroadphaseCollision/btDbvt.h"
|
||||||
|
#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h"
|
||||||
|
|
||||||
|
//
|
||||||
|
// Compile time config
|
||||||
|
//
|
||||||
|
|
||||||
|
#define DBVT_BP_PROFILE 0
|
||||||
|
#define DBVT_BP_SORTPAIRS 1
|
||||||
|
#define DBVT_BP_PREVENTFALSEUPDATE 0
|
||||||
|
#define DBVT_BP_ACCURATESLEEPING 0
|
||||||
|
#define DBVT_BP_ENABLE_BENCHMARK 0
|
||||||
|
#define DBVT_BP_MARGIN (btScalar)0.05
|
||||||
|
|
||||||
|
#if DBVT_BP_PROFILE
|
||||||
|
#define DBVT_BP_PROFILING_RATE 256
|
||||||
|
#include "LinearMath/btQuickprof.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//
|
||||||
|
// btDbvtProxy
|
||||||
|
//
|
||||||
|
struct btDbvtProxy : btBroadphaseProxy
|
||||||
|
{
|
||||||
|
/* Fields */
|
||||||
|
btDbvtAabbMm aabb;
|
||||||
|
btDbvtNode* leaf;
|
||||||
|
btDbvtProxy* links[2];
|
||||||
|
int stage;
|
||||||
|
/* ctor */
|
||||||
|
btDbvtProxy(void* userPtr,short int collisionFilterGroup, short int collisionFilterMask) :
|
||||||
|
btBroadphaseProxy(userPtr,collisionFilterGroup,collisionFilterMask)
|
||||||
|
{
|
||||||
|
links[0]=links[1]=0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef btAlignedObjectArray<btDbvtProxy*> btDbvtProxyArray;
|
||||||
|
|
||||||
|
///The btDbvtBroadphase implements a broadphase using two dynamic AABB bounding volume hierarchies/trees (see btDbvt).
|
||||||
|
///One tree is used for static/non-moving objects, and another tree is used for dynamic objects. Objects can move from one tree to the other.
|
||||||
|
///This is a very fast broadphase, especially for very dynamic worlds where many objects are moving. Its insert/add and remove of objects is generally faster than the sweep and prune broadphases btAxisSweep3 and bt32BitAxisSweep3.
|
||||||
|
struct btDbvtBroadphase : btBroadphaseInterface
|
||||||
|
{
|
||||||
|
/* Config */
|
||||||
|
enum {
|
||||||
|
DYNAMIC_SET = 0, /* Dynamic set index */
|
||||||
|
FIXED_SET = 1, /* Fixed set index */
|
||||||
|
STAGECOUNT = 2 /* Number of stages */
|
||||||
|
};
|
||||||
|
/* Fields */
|
||||||
|
btDbvt m_sets[2]; // Dbvt sets
|
||||||
|
btDbvtProxy* m_stageRoots[STAGECOUNT+1]; // Stages list
|
||||||
|
btOverlappingPairCache* m_paircache; // Pair cache
|
||||||
|
btScalar m_prediction; // Velocity prediction
|
||||||
|
int m_stageCurrent; // Current stage
|
||||||
|
int m_fupdates; // % of fixed updates per frame
|
||||||
|
int m_dupdates; // % of dynamic updates per frame
|
||||||
|
int m_cupdates; // % of cleanup updates per frame
|
||||||
|
int m_newpairs; // Number of pairs created
|
||||||
|
int m_fixedleft; // Fixed optimization left
|
||||||
|
unsigned m_updates_call; // Number of updates call
|
||||||
|
unsigned m_updates_done; // Number of updates done
|
||||||
|
btScalar m_updates_ratio; // m_updates_done/m_updates_call
|
||||||
|
int m_pid; // Parse id
|
||||||
|
int m_cid; // Cleanup index
|
||||||
|
int m_gid; // Gen id
|
||||||
|
bool m_releasepaircache; // Release pair cache on delete
|
||||||
|
bool m_deferedcollide; // Defere dynamic/static collision to collide call
|
||||||
|
bool m_needcleanup; // Need to run cleanup?
|
||||||
|
#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
|
||||||
|
/* Methods */
|
||||||
|
btDbvtBroadphase(btOverlappingPairCache* paircache=0);
|
||||||
|
~btDbvtBroadphase();
|
||||||
|
void collide(btDispatcher* dispatcher);
|
||||||
|
void optimize();
|
||||||
|
/* btBroadphaseInterface Implementation */
|
||||||
|
btBroadphaseProxy* createProxy(const btVector3& aabbMin,const btVector3& aabbMax,int shapeType,void* userPtr,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher,void* multiSapProxy);
|
||||||
|
void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
|
||||||
|
void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* dispatcher);
|
||||||
|
void calculateOverlappingPairs(btDispatcher* dispatcher);
|
||||||
|
btOverlappingPairCache* getOverlappingPairCache();
|
||||||
|
const btOverlappingPairCache* getOverlappingPairCache() const;
|
||||||
|
void getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const;
|
||||||
|
void printStats();
|
||||||
|
static void benchmark(btBroadphaseInterface*);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
466
extern/bullet2/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.cpp
vendored
Normal file
466
extern/bullet2/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.cpp
vendored
Normal file
@ -0,0 +1,466 @@
|
|||||||
|
/*
|
||||||
|
Bullet Continuous Collision Detection and Physics Library
|
||||||
|
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "btMultiSapBroadphase.h"
|
||||||
|
|
||||||
|
#include "btSimpleBroadphase.h"
|
||||||
|
#include "LinearMath/btAabbUtil2.h"
|
||||||
|
#include "btQuantizedBvh.h"
|
||||||
|
|
||||||
|
/// btSapBroadphaseArray m_sapBroadphases;
|
||||||
|
|
||||||
|
/// btOverlappingPairCache* m_overlappingPairs;
|
||||||
|
extern int gOverlappingPairs;
|
||||||
|
|
||||||
|
/*
|
||||||
|
class btMultiSapSortedOverlappingPairCache : public btSortedOverlappingPairCache
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
|
||||||
|
{
|
||||||
|
return btSortedOverlappingPairCache::addOverlappingPair((btBroadphaseProxy*)proxy0->m_multiSapParentProxy,(btBroadphaseProxy*)proxy1->m_multiSapParentProxy);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
btMultiSapBroadphase::btMultiSapBroadphase(int /*maxProxies*/,btOverlappingPairCache* pairCache)
|
||||||
|
:m_overlappingPairs(pairCache),
|
||||||
|
m_optimizedAabbTree(0),
|
||||||
|
m_ownsPairCache(false),
|
||||||
|
m_invalidPair(0)
|
||||||
|
{
|
||||||
|
if (!m_overlappingPairs)
|
||||||
|
{
|
||||||
|
m_ownsPairCache = true;
|
||||||
|
void* mem = btAlignedAlloc(sizeof(btSortedOverlappingPairCache),16);
|
||||||
|
m_overlappingPairs = new (mem)btSortedOverlappingPairCache();
|
||||||
|
}
|
||||||
|
|
||||||
|
struct btMultiSapOverlapFilterCallback : public btOverlapFilterCallback
|
||||||
|
{
|
||||||
|
virtual ~btMultiSapOverlapFilterCallback()
|
||||||
|
{}
|
||||||
|
// return true when pairs need collision
|
||||||
|
virtual bool needBroadphaseCollision(btBroadphaseProxy* childProxy0,btBroadphaseProxy* childProxy1) const
|
||||||
|
{
|
||||||
|
btBroadphaseProxy* multiProxy0 = (btBroadphaseProxy*)childProxy0->m_multiSapParentProxy;
|
||||||
|
btBroadphaseProxy* multiProxy1 = (btBroadphaseProxy*)childProxy1->m_multiSapParentProxy;
|
||||||
|
|
||||||
|
bool collides = (multiProxy0->m_collisionFilterGroup & multiProxy1->m_collisionFilterMask) != 0;
|
||||||
|
collides = collides && (multiProxy1->m_collisionFilterGroup & multiProxy0->m_collisionFilterMask);
|
||||||
|
|
||||||
|
return collides;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void* mem = btAlignedAlloc(sizeof(btMultiSapOverlapFilterCallback),16);
|
||||||
|
m_filterCallback = new (mem)btMultiSapOverlapFilterCallback();
|
||||||
|
|
||||||
|
m_overlappingPairs->setOverlapFilterCallback(m_filterCallback);
|
||||||
|
// mem = btAlignedAlloc(sizeof(btSimpleBroadphase),16);
|
||||||
|
// m_simpleBroadphase = new (mem) btSimpleBroadphase(maxProxies,m_overlappingPairs);
|
||||||
|
}
|
||||||
|
|
||||||
|
btMultiSapBroadphase::~btMultiSapBroadphase()
|
||||||
|
{
|
||||||
|
if (m_ownsPairCache)
|
||||||
|
{
|
||||||
|
m_overlappingPairs->~btOverlappingPairCache();
|
||||||
|
btAlignedFree(m_overlappingPairs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void btMultiSapBroadphase::buildTree(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax)
|
||||||
|
{
|
||||||
|
m_optimizedAabbTree = new btQuantizedBvh();
|
||||||
|
m_optimizedAabbTree->setQuantizationValues(bvhAabbMin,bvhAabbMax);
|
||||||
|
QuantizedNodeArray& nodes = m_optimizedAabbTree->getLeafNodeArray();
|
||||||
|
for (int i=0;i<m_sapBroadphases.size();i++)
|
||||||
|
{
|
||||||
|
btQuantizedBvhNode node;
|
||||||
|
btVector3 aabbMin,aabbMax;
|
||||||
|
m_sapBroadphases[i]->getBroadphaseAabb(aabbMin,aabbMax);
|
||||||
|
m_optimizedAabbTree->quantize(&node.m_quantizedAabbMin[0],aabbMin,0);
|
||||||
|
m_optimizedAabbTree->quantize(&node.m_quantizedAabbMax[0],aabbMax,1);
|
||||||
|
int partId = 0;
|
||||||
|
node.m_escapeIndexOrTriangleIndex = (partId<<(31-MAX_NUM_PARTS_IN_BITS)) | i;
|
||||||
|
nodes.push_back(node);
|
||||||
|
}
|
||||||
|
m_optimizedAabbTree->buildInternal();
|
||||||
|
}
|
||||||
|
|
||||||
|
btBroadphaseProxy* btMultiSapBroadphase::createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher,void* /*ignoreMe*/)
|
||||||
|
{
|
||||||
|
//void* ignoreMe -> we could think of recursive multi-sap, if someone is interested
|
||||||
|
|
||||||
|
void* mem = btAlignedAlloc(sizeof(btMultiSapProxy),16);
|
||||||
|
btMultiSapProxy* proxy = new (mem)btMultiSapProxy(aabbMin, aabbMax,shapeType,userPtr, collisionFilterGroup,collisionFilterMask);
|
||||||
|
m_multiSapProxies.push_back(proxy);
|
||||||
|
|
||||||
|
///this should deal with inserting/removal into child broadphases
|
||||||
|
setAabb(proxy,aabbMin,aabbMax,dispatcher);
|
||||||
|
return proxy;
|
||||||
|
}
|
||||||
|
|
||||||
|
void btMultiSapBroadphase::destroyProxy(btBroadphaseProxy* /*proxy*/,btDispatcher* /*dispatcher*/)
|
||||||
|
{
|
||||||
|
///not yet
|
||||||
|
btAssert(0);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void btMultiSapBroadphase::addToChildBroadphase(btMultiSapProxy* parentMultiSapProxy, btBroadphaseProxy* childProxy, btBroadphaseInterface* childBroadphase)
|
||||||
|
{
|
||||||
|
void* mem = btAlignedAlloc(sizeof(btBridgeProxy),16);
|
||||||
|
btBridgeProxy* bridgeProxyRef = new(mem) btBridgeProxy;
|
||||||
|
bridgeProxyRef->m_childProxy = childProxy;
|
||||||
|
bridgeProxyRef->m_childBroadphase = childBroadphase;
|
||||||
|
parentMultiSapProxy->m_bridgeProxies.push_back(bridgeProxyRef);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool boxIsContainedWithinBox(const btVector3& amin,const btVector3& amax,const btVector3& bmin,const btVector3& bmax);
|
||||||
|
bool boxIsContainedWithinBox(const btVector3& amin,const btVector3& amax,const btVector3& bmin,const btVector3& bmax)
|
||||||
|
{
|
||||||
|
return
|
||||||
|
amin.getX() >= bmin.getX() && amax.getX() <= bmax.getX() &&
|
||||||
|
amin.getY() >= bmin.getY() && amax.getY() <= bmax.getY() &&
|
||||||
|
amin.getZ() >= bmin.getZ() && amax.getZ() <= bmax.getZ();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//#include <stdio.h>
|
||||||
|
|
||||||
|
void btMultiSapBroadphase::setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher)
|
||||||
|
{
|
||||||
|
btMultiSapProxy* multiProxy = static_cast<btMultiSapProxy*>(proxy);
|
||||||
|
multiProxy->m_aabbMin = aabbMin;
|
||||||
|
multiProxy->m_aabbMax = aabbMax;
|
||||||
|
|
||||||
|
|
||||||
|
// bool fullyContained = false;
|
||||||
|
// bool alreadyInSimple = false;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
struct MyNodeOverlapCallback : public btNodeOverlapCallback
|
||||||
|
{
|
||||||
|
btMultiSapBroadphase* m_multiSap;
|
||||||
|
btMultiSapProxy* m_multiProxy;
|
||||||
|
btDispatcher* m_dispatcher;
|
||||||
|
|
||||||
|
MyNodeOverlapCallback(btMultiSapBroadphase* multiSap,btMultiSapProxy* multiProxy,btDispatcher* dispatcher)
|
||||||
|
:m_multiSap(multiSap),
|
||||||
|
m_multiProxy(multiProxy),
|
||||||
|
m_dispatcher(dispatcher)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void processNode(int /*nodeSubPart*/, int broadphaseIndex)
|
||||||
|
{
|
||||||
|
btBroadphaseInterface* childBroadphase = m_multiSap->getBroadphaseArray()[broadphaseIndex];
|
||||||
|
|
||||||
|
int containingBroadphaseIndex = -1;
|
||||||
|
//already found?
|
||||||
|
for (int i=0;i<m_multiProxy->m_bridgeProxies.size();i++)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (m_multiProxy->m_bridgeProxies[i]->m_childBroadphase == childBroadphase)
|
||||||
|
{
|
||||||
|
containingBroadphaseIndex = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (containingBroadphaseIndex<0)
|
||||||
|
{
|
||||||
|
//add it
|
||||||
|
btBroadphaseProxy* childProxy = childBroadphase->createProxy(m_multiProxy->m_aabbMin,m_multiProxy->m_aabbMax,m_multiProxy->m_shapeType,m_multiProxy->m_clientObject,m_multiProxy->m_collisionFilterGroup,m_multiProxy->m_collisionFilterMask, m_dispatcher,m_multiProxy);
|
||||||
|
m_multiSap->addToChildBroadphase(m_multiProxy,childProxy,childBroadphase);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
MyNodeOverlapCallback myNodeCallback(this,multiProxy,dispatcher);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
m_optimizedAabbTree->reportAabbOverlappingNodex(&myNodeCallback,aabbMin,aabbMax);
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for ( i=0;i<multiProxy->m_bridgeProxies.size();i++)
|
||||||
|
{
|
||||||
|
btVector3 worldAabbMin,worldAabbMax;
|
||||||
|
multiProxy->m_bridgeProxies[i]->m_childBroadphase->getBroadphaseAabb(worldAabbMin,worldAabbMax);
|
||||||
|
bool overlapsBroadphase = TestAabbAgainstAabb2(worldAabbMin,worldAabbMax,multiProxy->m_aabbMin,multiProxy->m_aabbMax);
|
||||||
|
if (!overlapsBroadphase)
|
||||||
|
{
|
||||||
|
//remove it now
|
||||||
|
btBridgeProxy* bridgeProxy = multiProxy->m_bridgeProxies[i];
|
||||||
|
|
||||||
|
btBroadphaseProxy* childProxy = bridgeProxy->m_childProxy;
|
||||||
|
bridgeProxy->m_childBroadphase->destroyProxy(childProxy,dispatcher);
|
||||||
|
|
||||||
|
multiProxy->m_bridgeProxies.swap( i,multiProxy->m_bridgeProxies.size()-1);
|
||||||
|
multiProxy->m_bridgeProxies.pop_back();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
if (1)
|
||||||
|
{
|
||||||
|
|
||||||
|
//find broadphase that contain this multiProxy
|
||||||
|
int numChildBroadphases = getBroadphaseArray().size();
|
||||||
|
for (int i=0;i<numChildBroadphases;i++)
|
||||||
|
{
|
||||||
|
btBroadphaseInterface* childBroadphase = getBroadphaseArray()[i];
|
||||||
|
btVector3 worldAabbMin,worldAabbMax;
|
||||||
|
childBroadphase->getBroadphaseAabb(worldAabbMin,worldAabbMax);
|
||||||
|
bool overlapsBroadphase = TestAabbAgainstAabb2(worldAabbMin,worldAabbMax,multiProxy->m_aabbMin,multiProxy->m_aabbMax);
|
||||||
|
|
||||||
|
// fullyContained = fullyContained || boxIsContainedWithinBox(worldAabbMin,worldAabbMax,multiProxy->m_aabbMin,multiProxy->m_aabbMax);
|
||||||
|
int containingBroadphaseIndex = -1;
|
||||||
|
|
||||||
|
//if already contains this
|
||||||
|
|
||||||
|
for (int i=0;i<multiProxy->m_bridgeProxies.size();i++)
|
||||||
|
{
|
||||||
|
if (multiProxy->m_bridgeProxies[i]->m_childBroadphase == childBroadphase)
|
||||||
|
{
|
||||||
|
containingBroadphaseIndex = i;
|
||||||
|
}
|
||||||
|
alreadyInSimple = alreadyInSimple || (multiProxy->m_bridgeProxies[i]->m_childBroadphase == m_simpleBroadphase);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (overlapsBroadphase)
|
||||||
|
{
|
||||||
|
if (containingBroadphaseIndex<0)
|
||||||
|
{
|
||||||
|
btBroadphaseProxy* childProxy = childBroadphase->createProxy(aabbMin,aabbMax,multiProxy->m_shapeType,multiProxy->m_clientObject,multiProxy->m_collisionFilterGroup,multiProxy->m_collisionFilterMask, dispatcher);
|
||||||
|
childProxy->m_multiSapParentProxy = multiProxy;
|
||||||
|
addToChildBroadphase(multiProxy,childProxy,childBroadphase);
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
if (containingBroadphaseIndex>=0)
|
||||||
|
{
|
||||||
|
//remove
|
||||||
|
btBridgeProxy* bridgeProxy = multiProxy->m_bridgeProxies[containingBroadphaseIndex];
|
||||||
|
|
||||||
|
btBroadphaseProxy* childProxy = bridgeProxy->m_childProxy;
|
||||||
|
bridgeProxy->m_childBroadphase->destroyProxy(childProxy,dispatcher);
|
||||||
|
|
||||||
|
multiProxy->m_bridgeProxies.swap( containingBroadphaseIndex,multiProxy->m_bridgeProxies.size()-1);
|
||||||
|
multiProxy->m_bridgeProxies.pop_back();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///If we are in no other child broadphase, stick the proxy in the global 'simple' broadphase (brute force)
|
||||||
|
///hopefully we don't end up with many entries here (can assert/provide feedback on stats)
|
||||||
|
if (0)//!multiProxy->m_bridgeProxies.size())
|
||||||
|
{
|
||||||
|
///we don't pass the userPtr but our multisap proxy. We need to patch this, before processing an actual collision
|
||||||
|
///this is needed to be able to calculate the aabb overlap
|
||||||
|
btBroadphaseProxy* childProxy = m_simpleBroadphase->createProxy(aabbMin,aabbMax,multiProxy->m_shapeType,multiProxy->m_clientObject,multiProxy->m_collisionFilterGroup,multiProxy->m_collisionFilterMask, dispatcher);
|
||||||
|
childProxy->m_multiSapParentProxy = multiProxy;
|
||||||
|
addToChildBroadphase(multiProxy,childProxy,m_simpleBroadphase);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!multiProxy->m_bridgeProxies.size())
|
||||||
|
{
|
||||||
|
///we don't pass the userPtr but our multisap proxy. We need to patch this, before processing an actual collision
|
||||||
|
///this is needed to be able to calculate the aabb overlap
|
||||||
|
btBroadphaseProxy* childProxy = m_simpleBroadphase->createProxy(aabbMin,aabbMax,multiProxy->m_shapeType,multiProxy->m_clientObject,multiProxy->m_collisionFilterGroup,multiProxy->m_collisionFilterMask, dispatcher);
|
||||||
|
childProxy->m_multiSapParentProxy = multiProxy;
|
||||||
|
addToChildBroadphase(multiProxy,childProxy,m_simpleBroadphase);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
//update
|
||||||
|
for ( i=0;i<multiProxy->m_bridgeProxies.size();i++)
|
||||||
|
{
|
||||||
|
btBridgeProxy* bridgeProxyRef = multiProxy->m_bridgeProxies[i];
|
||||||
|
bridgeProxyRef->m_childBroadphase->setAabb(bridgeProxyRef->m_childProxy,aabbMin,aabbMax,dispatcher);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
bool stopUpdating=false;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class btMultiSapBroadphasePairSortPredicate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
bool operator() ( const btBroadphasePair& a1, const btBroadphasePair& b1 )
|
||||||
|
{
|
||||||
|
btMultiSapBroadphase::btMultiSapProxy* aProxy0 = a1.m_pProxy0 ? (btMultiSapBroadphase::btMultiSapProxy*)a1.m_pProxy0->m_multiSapParentProxy : 0;
|
||||||
|
btMultiSapBroadphase::btMultiSapProxy* aProxy1 = a1.m_pProxy1 ? (btMultiSapBroadphase::btMultiSapProxy*)a1.m_pProxy1->m_multiSapParentProxy : 0;
|
||||||
|
btMultiSapBroadphase::btMultiSapProxy* bProxy0 = b1.m_pProxy0 ? (btMultiSapBroadphase::btMultiSapProxy*)b1.m_pProxy0->m_multiSapParentProxy : 0;
|
||||||
|
btMultiSapBroadphase::btMultiSapProxy* bProxy1 = b1.m_pProxy1 ? (btMultiSapBroadphase::btMultiSapProxy*)b1.m_pProxy1->m_multiSapParentProxy : 0;
|
||||||
|
|
||||||
|
return aProxy0 > bProxy0 ||
|
||||||
|
(aProxy0 == bProxy0 && aProxy1 > bProxy1) ||
|
||||||
|
(aProxy0 == bProxy0 && aProxy1 == bProxy1 && a1.m_algorithm > b1.m_algorithm);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
///calculateOverlappingPairs is optional: incremental algorithms (sweep and prune) might do it during the set aabb
|
||||||
|
void btMultiSapBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher)
|
||||||
|
{
|
||||||
|
|
||||||
|
// m_simpleBroadphase->calculateOverlappingPairs(dispatcher);
|
||||||
|
|
||||||
|
if (!stopUpdating && getOverlappingPairCache()->hasDeferredRemoval())
|
||||||
|
{
|
||||||
|
|
||||||
|
btBroadphasePairArray& overlappingPairArray = getOverlappingPairCache()->getOverlappingPairArray();
|
||||||
|
|
||||||
|
// quicksort(overlappingPairArray,0,overlappingPairArray.size());
|
||||||
|
|
||||||
|
overlappingPairArray.quickSort(btMultiSapBroadphasePairSortPredicate());
|
||||||
|
|
||||||
|
//perform a sort, to find duplicates and to sort 'invalid' pairs to the end
|
||||||
|
// overlappingPairArray.heapSort(btMultiSapBroadphasePairSortPredicate());
|
||||||
|
|
||||||
|
overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair);
|
||||||
|
m_invalidPair = 0;
|
||||||
|
|
||||||
|
|
||||||
|
int i;
|
||||||
|
|
||||||
|
btBroadphasePair previousPair;
|
||||||
|
previousPair.m_pProxy0 = 0;
|
||||||
|
previousPair.m_pProxy1 = 0;
|
||||||
|
previousPair.m_algorithm = 0;
|
||||||
|
|
||||||
|
|
||||||
|
for (i=0;i<overlappingPairArray.size();i++)
|
||||||
|
{
|
||||||
|
|
||||||
|
btBroadphasePair& pair = overlappingPairArray[i];
|
||||||
|
|
||||||
|
btMultiSapProxy* aProxy0 = pair.m_pProxy0 ? (btMultiSapProxy*)pair.m_pProxy0->m_multiSapParentProxy : 0;
|
||||||
|
btMultiSapProxy* aProxy1 = pair.m_pProxy1 ? (btMultiSapProxy*)pair.m_pProxy1->m_multiSapParentProxy : 0;
|
||||||
|
btMultiSapProxy* bProxy0 = previousPair.m_pProxy0 ? (btMultiSapProxy*)previousPair.m_pProxy0->m_multiSapParentProxy : 0;
|
||||||
|
btMultiSapProxy* bProxy1 = previousPair.m_pProxy1 ? (btMultiSapProxy*)previousPair.m_pProxy1->m_multiSapParentProxy : 0;
|
||||||
|
|
||||||
|
bool isDuplicate = (aProxy0 == bProxy0) && (aProxy1 == bProxy1);
|
||||||
|
|
||||||
|
previousPair = pair;
|
||||||
|
|
||||||
|
bool needsRemoval = false;
|
||||||
|
|
||||||
|
if (!isDuplicate)
|
||||||
|
{
|
||||||
|
bool hasOverlap = testAabbOverlap(pair.m_pProxy0,pair.m_pProxy1);
|
||||||
|
|
||||||
|
if (hasOverlap)
|
||||||
|
{
|
||||||
|
needsRemoval = false;//callback->processOverlap(pair);
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
needsRemoval = true;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
//remove duplicate
|
||||||
|
needsRemoval = true;
|
||||||
|
//should have no algorithm
|
||||||
|
btAssert(!pair.m_algorithm);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (needsRemoval)
|
||||||
|
{
|
||||||
|
getOverlappingPairCache()->cleanOverlappingPair(pair,dispatcher);
|
||||||
|
|
||||||
|
// m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1);
|
||||||
|
// m_overlappingPairArray.pop_back();
|
||||||
|
pair.m_pProxy0 = 0;
|
||||||
|
pair.m_pProxy1 = 0;
|
||||||
|
m_invalidPair++;
|
||||||
|
gOverlappingPairs--;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
///if you don't like to skip the invalid pairs in the array, execute following code:
|
||||||
|
#define CLEAN_INVALID_PAIRS 1
|
||||||
|
#ifdef CLEAN_INVALID_PAIRS
|
||||||
|
|
||||||
|
//perform a sort, to sort 'invalid' pairs to the end
|
||||||
|
//overlappingPairArray.heapSort(btMultiSapBroadphasePairSortPredicate());
|
||||||
|
overlappingPairArray.quickSort(btMultiSapBroadphasePairSortPredicate());
|
||||||
|
|
||||||
|
overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair);
|
||||||
|
m_invalidPair = 0;
|
||||||
|
#endif//CLEAN_INVALID_PAIRS
|
||||||
|
|
||||||
|
//printf("overlappingPairArray.size()=%d\n",overlappingPairArray.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool btMultiSapBroadphase::testAabbOverlap(btBroadphaseProxy* childProxy0,btBroadphaseProxy* childProxy1)
|
||||||
|
{
|
||||||
|
btMultiSapProxy* multiSapProxy0 = (btMultiSapProxy*)childProxy0->m_multiSapParentProxy;
|
||||||
|
btMultiSapProxy* multiSapProxy1 = (btMultiSapProxy*)childProxy1->m_multiSapParentProxy;
|
||||||
|
|
||||||
|
return TestAabbAgainstAabb2(multiSapProxy0->m_aabbMin,multiSapProxy0->m_aabbMax,
|
||||||
|
multiSapProxy1->m_aabbMin,multiSapProxy1->m_aabbMax);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void btMultiSapBroadphase::printStats()
|
||||||
|
{
|
||||||
|
/* printf("---------------------------------\n");
|
||||||
|
|
||||||
|
printf("btMultiSapBroadphase.h\n");
|
||||||
|
printf("numHandles = %d\n",m_multiSapProxies.size());
|
||||||
|
//find broadphase that contain this multiProxy
|
||||||
|
int numChildBroadphases = getBroadphaseArray().size();
|
||||||
|
for (int i=0;i<numChildBroadphases;i++)
|
||||||
|
{
|
||||||
|
|
||||||
|
btBroadphaseInterface* childBroadphase = getBroadphaseArray()[i];
|
||||||
|
childBroadphase->printStats();
|
||||||
|
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
}
|
144
extern/bullet2/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.h
vendored
Normal file
144
extern/bullet2/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.h
vendored
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
/*
|
||||||
|
Bullet Continuous Collision Detection and Physics Library
|
||||||
|
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
#ifndef BT_MULTI_SAP_BROADPHASE
|
||||||
|
#define BT_MULTI_SAP_BROADPHASE
|
||||||
|
|
||||||
|
#include "btBroadphaseInterface.h"
|
||||||
|
#include "LinearMath/btAlignedObjectArray.h"
|
||||||
|
#include "btOverlappingPairCache.h"
|
||||||
|
|
||||||
|
|
||||||
|
class btBroadphaseInterface;
|
||||||
|
class btSimpleBroadphase;
|
||||||
|
|
||||||
|
|
||||||
|
typedef btAlignedObjectArray<btBroadphaseInterface*> btSapBroadphaseArray;
|
||||||
|
|
||||||
|
///The btMultiSapBroadphase is a broadphase that contains multiple SAP broadphases.
|
||||||
|
///The user can add SAP broadphases that cover the world. A btBroadphaseProxy can be in multiple child broadphases at the same time.
|
||||||
|
///A btQuantizedBvh acceleration structures finds overlapping SAPs for each btBroadphaseProxy.
|
||||||
|
///See http://www.continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=328
|
||||||
|
///and http://www.continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=1329
|
||||||
|
class btMultiSapBroadphase :public btBroadphaseInterface
|
||||||
|
{
|
||||||
|
btSapBroadphaseArray m_sapBroadphases;
|
||||||
|
|
||||||
|
btSimpleBroadphase* m_simpleBroadphase;
|
||||||
|
|
||||||
|
btOverlappingPairCache* m_overlappingPairs;
|
||||||
|
|
||||||
|
class btQuantizedBvh* m_optimizedAabbTree;
|
||||||
|
|
||||||
|
|
||||||
|
bool m_ownsPairCache;
|
||||||
|
|
||||||
|
btOverlapFilterCallback* m_filterCallback;
|
||||||
|
|
||||||
|
int m_invalidPair;
|
||||||
|
|
||||||
|
struct btBridgeProxy
|
||||||
|
{
|
||||||
|
btBroadphaseProxy* m_childProxy;
|
||||||
|
btBroadphaseInterface* m_childBroadphase;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
struct btMultiSapProxy : public btBroadphaseProxy
|
||||||
|
{
|
||||||
|
|
||||||
|
///array with all the entries that this proxy belongs to
|
||||||
|
btAlignedObjectArray<btBridgeProxy*> m_bridgeProxies;
|
||||||
|
btVector3 m_aabbMin;
|
||||||
|
btVector3 m_aabbMax;
|
||||||
|
|
||||||
|
int m_shapeType;
|
||||||
|
|
||||||
|
/* void* m_userPtr;
|
||||||
|
short int m_collisionFilterGroup;
|
||||||
|
short int m_collisionFilterMask;
|
||||||
|
*/
|
||||||
|
btMultiSapProxy(const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask)
|
||||||
|
:btBroadphaseProxy(userPtr,collisionFilterGroup,collisionFilterMask),
|
||||||
|
m_aabbMin(aabbMin),
|
||||||
|
m_aabbMax(aabbMax),
|
||||||
|
m_shapeType(shapeType)
|
||||||
|
{
|
||||||
|
m_multiSapParentProxy =this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
|
||||||
|
btAlignedObjectArray<btMultiSapProxy*> m_multiSapProxies;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
btMultiSapBroadphase(int maxProxies = 16384,btOverlappingPairCache* pairCache=0);
|
||||||
|
|
||||||
|
|
||||||
|
btSapBroadphaseArray& getBroadphaseArray()
|
||||||
|
{
|
||||||
|
return m_sapBroadphases;
|
||||||
|
}
|
||||||
|
|
||||||
|
const btSapBroadphaseArray& getBroadphaseArray() const
|
||||||
|
{
|
||||||
|
return m_sapBroadphases;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~btMultiSapBroadphase();
|
||||||
|
|
||||||
|
virtual btBroadphaseProxy* createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher,void* multiSapProxy);
|
||||||
|
virtual void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
|
||||||
|
virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher);
|
||||||
|
|
||||||
|
void addToChildBroadphase(btMultiSapProxy* parentMultiSapProxy, btBroadphaseProxy* childProxy, btBroadphaseInterface* childBroadphase);
|
||||||
|
|
||||||
|
///calculateOverlappingPairs is optional: incremental algorithms (sweep and prune) might do it during the set aabb
|
||||||
|
virtual void calculateOverlappingPairs(btDispatcher* dispatcher);
|
||||||
|
|
||||||
|
bool testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1);
|
||||||
|
|
||||||
|
virtual btOverlappingPairCache* getOverlappingPairCache()
|
||||||
|
{
|
||||||
|
return m_overlappingPairs;
|
||||||
|
}
|
||||||
|
virtual const btOverlappingPairCache* getOverlappingPairCache() const
|
||||||
|
{
|
||||||
|
return m_overlappingPairs;
|
||||||
|
}
|
||||||
|
|
||||||
|
///getAabb returns the axis aligned bounding box in the 'global' coordinate frame
|
||||||
|
///will add some transform later
|
||||||
|
virtual void getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const
|
||||||
|
{
|
||||||
|
aabbMin.setValue(-1e30f,-1e30f,-1e30f);
|
||||||
|
aabbMax.setValue(1e30f,1e30f,1e30f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void buildTree(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax);
|
||||||
|
|
||||||
|
virtual void printStats();
|
||||||
|
|
||||||
|
void quicksort (btBroadphasePairArray& a, int lo, int hi);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //BT_MULTI_SAP_BROADPHASE
|
40
extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h
vendored
Normal file
40
extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h
vendored
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
|
||||||
|
/*
|
||||||
|
Bullet Continuous Collision Detection and Physics Library
|
||||||
|
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef OVERLAPPING_PAIR_CALLBACK_H
|
||||||
|
#define OVERLAPPING_PAIR_CALLBACK_H
|
||||||
|
|
||||||
|
class btDispatcher;
|
||||||
|
struct btBroadphasePair;
|
||||||
|
|
||||||
|
///The btOverlappingPairCallback class is an additional optional broadphase user callback for adding/removing overlapping pairs, similar interface to btOverlappingPairCache.
|
||||||
|
class btOverlappingPairCallback
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~btOverlappingPairCallback()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) = 0;
|
||||||
|
|
||||||
|
virtual void* removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1,btDispatcher* dispatcher) = 0;
|
||||||
|
|
||||||
|
virtual void removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy0,btDispatcher* dispatcher) = 0;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //OVERLAPPING_PAIR_CALLBACK_H
|
1025
extern/bullet2/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp
vendored
Normal file
1025
extern/bullet2/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
486
extern/bullet2/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.h
vendored
Normal file
486
extern/bullet2/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.h
vendored
Normal file
@ -0,0 +1,486 @@
|
|||||||
|
/*
|
||||||
|
Bullet Continuous Collision Detection and Physics Library
|
||||||
|
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef QUANTIZED_BVH_H
|
||||||
|
#define QUANTIZED_BVH_H
|
||||||
|
|
||||||
|
//#define DEBUG_CHECK_DEQUANTIZATION 1
|
||||||
|
#ifdef DEBUG_CHECK_DEQUANTIZATION
|
||||||
|
#ifdef __SPU__
|
||||||
|
#define printf spu_printf
|
||||||
|
#endif //__SPU__
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#endif //DEBUG_CHECK_DEQUANTIZATION
|
||||||
|
|
||||||
|
#include "LinearMath/btVector3.h"
|
||||||
|
#include "LinearMath/btAlignedAllocator.h"
|
||||||
|
|
||||||
|
|
||||||
|
//http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclang/html/vclrf__m128.asp
|
||||||
|
|
||||||
|
|
||||||
|
//Note: currently we have 16 bytes per quantized node
|
||||||
|
#define MAX_SUBTREE_SIZE_IN_BYTES 2048
|
||||||
|
|
||||||
|
// 10 gives the potential for 1024 parts, with at most 2^21 (2097152) (minus one
|
||||||
|
// actually) triangles each (since the sign bit is reserved
|
||||||
|
#define MAX_NUM_PARTS_IN_BITS 10
|
||||||
|
|
||||||
|
///btQuantizedBvhNode is a compressed aabb node, 16 bytes.
|
||||||
|
///Node can be used for leafnode or internal node. Leafnodes can point to 32-bit triangle index (non-negative range).
|
||||||
|
ATTRIBUTE_ALIGNED16 (struct) btQuantizedBvhNode
|
||||||
|
{
|
||||||
|
BT_DECLARE_ALIGNED_ALLOCATOR();
|
||||||
|
|
||||||
|
//12 bytes
|
||||||
|
unsigned short int m_quantizedAabbMin[3];
|
||||||
|
unsigned short int m_quantizedAabbMax[3];
|
||||||
|
//4 bytes
|
||||||
|
int m_escapeIndexOrTriangleIndex;
|
||||||
|
|
||||||
|
bool isLeafNode() const
|
||||||
|
{
|
||||||
|
//skipindex is negative (internal node), triangleindex >=0 (leafnode)
|
||||||
|
return (m_escapeIndexOrTriangleIndex >= 0);
|
||||||
|
}
|
||||||
|
int getEscapeIndex() const
|
||||||
|
{
|
||||||
|
btAssert(!isLeafNode());
|
||||||
|
return -m_escapeIndexOrTriangleIndex;
|
||||||
|
}
|
||||||
|
int getTriangleIndex() const
|
||||||
|
{
|
||||||
|
btAssert(isLeafNode());
|
||||||
|
// Get only the lower bits where the triangle index is stored
|
||||||
|
return (m_escapeIndexOrTriangleIndex&~((~0)<<(31-MAX_NUM_PARTS_IN_BITS)));
|
||||||
|
}
|
||||||
|
int getPartId() const
|
||||||
|
{
|
||||||
|
btAssert(isLeafNode());
|
||||||
|
// Get only the highest bits where the part index is stored
|
||||||
|
return (m_escapeIndexOrTriangleIndex>>(31-MAX_NUM_PARTS_IN_BITS));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
/// btOptimizedBvhNode contains both internal and leaf node information.
|
||||||
|
/// Total node size is 44 bytes / node. You can use the compressed version of 16 bytes.
|
||||||
|
ATTRIBUTE_ALIGNED16 (struct) btOptimizedBvhNode
|
||||||
|
{
|
||||||
|
BT_DECLARE_ALIGNED_ALLOCATOR();
|
||||||
|
|
||||||
|
//32 bytes
|
||||||
|
btVector3 m_aabbMinOrg;
|
||||||
|
btVector3 m_aabbMaxOrg;
|
||||||
|
|
||||||
|
//4
|
||||||
|
int m_escapeIndex;
|
||||||
|
|
||||||
|
//8
|
||||||
|
//for child nodes
|
||||||
|
int m_subPart;
|
||||||
|
int m_triangleIndex;
|
||||||
|
int m_padding[5];//bad, due to alignment
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
///btBvhSubtreeInfo provides info to gather a subtree of limited size
|
||||||
|
ATTRIBUTE_ALIGNED16(class) btBvhSubtreeInfo
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
BT_DECLARE_ALIGNED_ALLOCATOR();
|
||||||
|
|
||||||
|
//12 bytes
|
||||||
|
unsigned short int m_quantizedAabbMin[3];
|
||||||
|
unsigned short int m_quantizedAabbMax[3];
|
||||||
|
//4 bytes, points to the root of the subtree
|
||||||
|
int m_rootNodeIndex;
|
||||||
|
//4 bytes
|
||||||
|
int m_subtreeSize;
|
||||||
|
int m_padding[3];
|
||||||
|
|
||||||
|
btBvhSubtreeInfo()
|
||||||
|
{
|
||||||
|
//memset(&m_padding[0], 0, sizeof(m_padding));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void setAabbFromQuantizeNode(const btQuantizedBvhNode& quantizedNode)
|
||||||
|
{
|
||||||
|
m_quantizedAabbMin[0] = quantizedNode.m_quantizedAabbMin[0];
|
||||||
|
m_quantizedAabbMin[1] = quantizedNode.m_quantizedAabbMin[1];
|
||||||
|
m_quantizedAabbMin[2] = quantizedNode.m_quantizedAabbMin[2];
|
||||||
|
m_quantizedAabbMax[0] = quantizedNode.m_quantizedAabbMax[0];
|
||||||
|
m_quantizedAabbMax[1] = quantizedNode.m_quantizedAabbMax[1];
|
||||||
|
m_quantizedAabbMax[2] = quantizedNode.m_quantizedAabbMax[2];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
|
class btNodeOverlapCallback
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~btNodeOverlapCallback() {};
|
||||||
|
|
||||||
|
virtual void processNode(int subPart, int triangleIndex) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
#include "LinearMath/btAlignedAllocator.h"
|
||||||
|
#include "LinearMath/btAlignedObjectArray.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
///for code readability:
|
||||||
|
typedef btAlignedObjectArray<btOptimizedBvhNode> NodeArray;
|
||||||
|
typedef btAlignedObjectArray<btQuantizedBvhNode> QuantizedNodeArray;
|
||||||
|
typedef btAlignedObjectArray<btBvhSubtreeInfo> BvhSubtreeInfoArray;
|
||||||
|
|
||||||
|
|
||||||
|
///The btQuantizedBvh class stores an AABB tree that can be quickly traversed on CPU and Cell SPU.
|
||||||
|
///It is used by the btBvhTriangleMeshShape as midphase, and by the btMultiSapBroadphase.
|
||||||
|
///It is recommended to use quantization for better performance and lower memory requirements.
|
||||||
|
ATTRIBUTE_ALIGNED16(class) btQuantizedBvh
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
|
||||||
|
NodeArray m_leafNodes;
|
||||||
|
NodeArray m_contiguousNodes;
|
||||||
|
|
||||||
|
QuantizedNodeArray m_quantizedLeafNodes;
|
||||||
|
|
||||||
|
QuantizedNodeArray m_quantizedContiguousNodes;
|
||||||
|
|
||||||
|
int m_curNodeIndex;
|
||||||
|
|
||||||
|
|
||||||
|
//quantization data
|
||||||
|
bool m_useQuantization;
|
||||||
|
btVector3 m_bvhAabbMin;
|
||||||
|
btVector3 m_bvhAabbMax;
|
||||||
|
btVector3 m_bvhQuantization;
|
||||||
|
public:
|
||||||
|
BT_DECLARE_ALIGNED_ALLOCATOR();
|
||||||
|
|
||||||
|
enum btTraversalMode
|
||||||
|
{
|
||||||
|
TRAVERSAL_STACKLESS = 0,
|
||||||
|
TRAVERSAL_STACKLESS_CACHE_FRIENDLY,
|
||||||
|
TRAVERSAL_RECURSIVE
|
||||||
|
};
|
||||||
|
protected:
|
||||||
|
|
||||||
|
btTraversalMode m_traversalMode;
|
||||||
|
|
||||||
|
BvhSubtreeInfoArray m_SubtreeHeaders;
|
||||||
|
|
||||||
|
//This is only used for serialization so we don't have to add serialization directly to btAlignedObjectArray
|
||||||
|
int m_subtreeHeaderCount;
|
||||||
|
|
||||||
|
|
||||||
|
///two versions, one for quantized and normal nodes. This allows code-reuse while maintaining readability (no template/macro!)
|
||||||
|
///this might be refactored into a virtual, it is usually not calculated at run-time
|
||||||
|
void setInternalNodeAabbMin(int nodeIndex, const btVector3& aabbMin)
|
||||||
|
{
|
||||||
|
if (m_useQuantization)
|
||||||
|
{
|
||||||
|
quantize(&m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0] ,aabbMin,0);
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
m_contiguousNodes[nodeIndex].m_aabbMinOrg = aabbMin;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void setInternalNodeAabbMax(int nodeIndex,const btVector3& aabbMax)
|
||||||
|
{
|
||||||
|
if (m_useQuantization)
|
||||||
|
{
|
||||||
|
quantize(&m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0],aabbMax,1);
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
m_contiguousNodes[nodeIndex].m_aabbMaxOrg = aabbMax;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
btVector3 getAabbMin(int nodeIndex) const
|
||||||
|
{
|
||||||
|
if (m_useQuantization)
|
||||||
|
{
|
||||||
|
return unQuantize(&m_quantizedLeafNodes[nodeIndex].m_quantizedAabbMin[0]);
|
||||||
|
}
|
||||||
|
//non-quantized
|
||||||
|
return m_leafNodes[nodeIndex].m_aabbMinOrg;
|
||||||
|
|
||||||
|
}
|
||||||
|
btVector3 getAabbMax(int nodeIndex) const
|
||||||
|
{
|
||||||
|
if (m_useQuantization)
|
||||||
|
{
|
||||||
|
return unQuantize(&m_quantizedLeafNodes[nodeIndex].m_quantizedAabbMax[0]);
|
||||||
|
}
|
||||||
|
//non-quantized
|
||||||
|
return m_leafNodes[nodeIndex].m_aabbMaxOrg;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void setInternalNodeEscapeIndex(int nodeIndex, int escapeIndex)
|
||||||
|
{
|
||||||
|
if (m_useQuantization)
|
||||||
|
{
|
||||||
|
m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex = -escapeIndex;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_contiguousNodes[nodeIndex].m_escapeIndex = escapeIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void mergeInternalNodeAabb(int nodeIndex,const btVector3& newAabbMin,const btVector3& newAabbMax)
|
||||||
|
{
|
||||||
|
if (m_useQuantization)
|
||||||
|
{
|
||||||
|
unsigned short int quantizedAabbMin[3];
|
||||||
|
unsigned short int quantizedAabbMax[3];
|
||||||
|
quantize(quantizedAabbMin,newAabbMin,0);
|
||||||
|
quantize(quantizedAabbMax,newAabbMax,1);
|
||||||
|
for (int i=0;i<3;i++)
|
||||||
|
{
|
||||||
|
if (m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[i] > quantizedAabbMin[i])
|
||||||
|
m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[i] = quantizedAabbMin[i];
|
||||||
|
|
||||||
|
if (m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[i] < quantizedAabbMax[i])
|
||||||
|
m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[i] = quantizedAabbMax[i];
|
||||||
|
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
//non-quantized
|
||||||
|
m_contiguousNodes[nodeIndex].m_aabbMinOrg.setMin(newAabbMin);
|
||||||
|
m_contiguousNodes[nodeIndex].m_aabbMaxOrg.setMax(newAabbMax);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void swapLeafNodes(int firstIndex,int secondIndex);
|
||||||
|
|
||||||
|
void assignInternalNodeFromLeafNode(int internalNode,int leafNodeIndex);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void buildTree (int startIndex,int endIndex);
|
||||||
|
|
||||||
|
int calcSplittingAxis(int startIndex,int endIndex);
|
||||||
|
|
||||||
|
int sortAndCalcSplittingIndex(int startIndex,int endIndex,int splitAxis);
|
||||||
|
|
||||||
|
void walkStacklessTree(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const;
|
||||||
|
|
||||||
|
void walkStacklessQuantizedTreeAgainstRay(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax, int startNodeIndex,int endNodeIndex) const;
|
||||||
|
void walkStacklessQuantizedTree(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax,int startNodeIndex,int endNodeIndex) const;
|
||||||
|
|
||||||
|
///tree traversal designed for small-memory processors like PS3 SPU
|
||||||
|
void walkStacklessQuantizedTreeCacheFriendly(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const;
|
||||||
|
|
||||||
|
///use the 16-byte stackless 'skipindex' node tree to do a recursive traversal
|
||||||
|
void walkRecursiveQuantizedTreeAgainstQueryAabb(const btQuantizedBvhNode* currentNode,btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const;
|
||||||
|
|
||||||
|
///use the 16-byte stackless 'skipindex' node tree to do a recursive traversal
|
||||||
|
void walkRecursiveQuantizedTreeAgainstQuantizedTree(const btQuantizedBvhNode* treeNodeA,const btQuantizedBvhNode* treeNodeB,btNodeOverlapCallback* nodeCallback) const;
|
||||||
|
|
||||||
|
|
||||||
|
#define USE_BANCHLESS 1
|
||||||
|
#ifdef USE_BANCHLESS
|
||||||
|
//This block replaces the block below and uses no branches, and replaces the 8 bit return with a 32 bit return for improved performance (~3x on XBox 360)
|
||||||
|
SIMD_FORCE_INLINE unsigned testQuantizedAabbAgainstQuantizedAabb(unsigned short int* aabbMin1,unsigned short int* aabbMax1,const unsigned short int* aabbMin2,const unsigned short int* aabbMax2) const
|
||||||
|
{
|
||||||
|
return static_cast<unsigned int>(btSelect((unsigned)((aabbMin1[0] <= aabbMax2[0]) & (aabbMax1[0] >= aabbMin2[0])
|
||||||
|
& (aabbMin1[2] <= aabbMax2[2]) & (aabbMax1[2] >= aabbMin2[2])
|
||||||
|
& (aabbMin1[1] <= aabbMax2[1]) & (aabbMax1[1] >= aabbMin2[1])),
|
||||||
|
1, 0));
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
SIMD_FORCE_INLINE bool testQuantizedAabbAgainstQuantizedAabb(unsigned short int* aabbMin1,unsigned short int* aabbMax1,const unsigned short int* aabbMin2,const unsigned short int* aabbMax2) const
|
||||||
|
{
|
||||||
|
bool overlap = true;
|
||||||
|
overlap = (aabbMin1[0] > aabbMax2[0] || aabbMax1[0] < aabbMin2[0]) ? false : overlap;
|
||||||
|
overlap = (aabbMin1[2] > aabbMax2[2] || aabbMax1[2] < aabbMin2[2]) ? false : overlap;
|
||||||
|
overlap = (aabbMin1[1] > aabbMax2[1] || aabbMax1[1] < aabbMin2[1]) ? false : overlap;
|
||||||
|
return overlap;
|
||||||
|
}
|
||||||
|
#endif //USE_BANCHLESS
|
||||||
|
|
||||||
|
void updateSubtreeHeaders(int leftChildNodexIndex,int rightChildNodexIndex);
|
||||||
|
|
||||||
|
public:
|
||||||
|
btQuantizedBvh();
|
||||||
|
|
||||||
|
virtual ~btQuantizedBvh();
|
||||||
|
|
||||||
|
|
||||||
|
///***************************************** expert/internal use only *************************
|
||||||
|
void setQuantizationValues(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax,btScalar quantizationMargin=btScalar(1.0));
|
||||||
|
QuantizedNodeArray& getLeafNodeArray() { return m_quantizedLeafNodes; }
|
||||||
|
///buildInternal is expert use only: assumes that setQuantizationValues and LeafNodeArray are initialized
|
||||||
|
void buildInternal();
|
||||||
|
///***************************************** expert/internal use only *************************
|
||||||
|
|
||||||
|
void reportAabbOverlappingNodex(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const;
|
||||||
|
void reportRayOverlappingNodex (btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget) const;
|
||||||
|
void reportBoxCastOverlappingNodex(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin,const btVector3& aabbMax) const;
|
||||||
|
|
||||||
|
SIMD_FORCE_INLINE void quantize(unsigned short* out, const btVector3& point,int isMax) const
|
||||||
|
{
|
||||||
|
|
||||||
|
btAssert(m_useQuantization);
|
||||||
|
|
||||||
|
btAssert(point.getX() <= m_bvhAabbMax.getX());
|
||||||
|
btAssert(point.getY() <= m_bvhAabbMax.getY());
|
||||||
|
btAssert(point.getZ() <= m_bvhAabbMax.getZ());
|
||||||
|
|
||||||
|
btAssert(point.getX() >= m_bvhAabbMin.getX());
|
||||||
|
btAssert(point.getY() >= m_bvhAabbMin.getY());
|
||||||
|
btAssert(point.getZ() >= m_bvhAabbMin.getZ());
|
||||||
|
|
||||||
|
btVector3 v = (point - m_bvhAabbMin) * m_bvhQuantization;
|
||||||
|
///Make sure rounding is done in a way that unQuantize(quantizeWithClamp(...)) is conservative
|
||||||
|
///end-points always set the first bit, so that they are sorted properly (so that neighbouring AABBs overlap properly)
|
||||||
|
///todo: double-check this
|
||||||
|
if (isMax)
|
||||||
|
{
|
||||||
|
out[0] = (unsigned short) (((unsigned short)(v.getX()+btScalar(1.)) | 1));
|
||||||
|
out[1] = (unsigned short) (((unsigned short)(v.getY()+btScalar(1.)) | 1));
|
||||||
|
out[2] = (unsigned short) (((unsigned short)(v.getZ()+btScalar(1.)) | 1));
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
out[0] = (unsigned short) (((unsigned short)(v.getX()) & 0xfffe));
|
||||||
|
out[1] = (unsigned short) (((unsigned short)(v.getY()) & 0xfffe));
|
||||||
|
out[2] = (unsigned short) (((unsigned short)(v.getZ()) & 0xfffe));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef DEBUG_CHECK_DEQUANTIZATION
|
||||||
|
btVector3 newPoint = unQuantize(out);
|
||||||
|
if (isMax)
|
||||||
|
{
|
||||||
|
if (newPoint.getX() < point.getX())
|
||||||
|
{
|
||||||
|
printf("unconservative X, diffX = %f, oldX=%f,newX=%f\n",newPoint.getX()-point.getX(), newPoint.getX(),point.getX());
|
||||||
|
}
|
||||||
|
if (newPoint.getY() < point.getY())
|
||||||
|
{
|
||||||
|
printf("unconservative Y, diffY = %f, oldY=%f,newY=%f\n",newPoint.getY()-point.getY(), newPoint.getY(),point.getY());
|
||||||
|
}
|
||||||
|
if (newPoint.getZ() < point.getZ())
|
||||||
|
{
|
||||||
|
|
||||||
|
printf("unconservative Z, diffZ = %f, oldZ=%f,newZ=%f\n",newPoint.getZ()-point.getZ(), newPoint.getZ(),point.getZ());
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
if (newPoint.getX() > point.getX())
|
||||||
|
{
|
||||||
|
printf("unconservative X, diffX = %f, oldX=%f,newX=%f\n",newPoint.getX()-point.getX(), newPoint.getX(),point.getX());
|
||||||
|
}
|
||||||
|
if (newPoint.getY() > point.getY())
|
||||||
|
{
|
||||||
|
printf("unconservative Y, diffY = %f, oldY=%f,newY=%f\n",newPoint.getY()-point.getY(), newPoint.getY(),point.getY());
|
||||||
|
}
|
||||||
|
if (newPoint.getZ() > point.getZ())
|
||||||
|
{
|
||||||
|
printf("unconservative Z, diffZ = %f, oldZ=%f,newZ=%f\n",newPoint.getZ()-point.getZ(), newPoint.getZ(),point.getZ());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif //DEBUG_CHECK_DEQUANTIZATION
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SIMD_FORCE_INLINE void quantizeWithClamp(unsigned short* out, const btVector3& point2,int isMax) const
|
||||||
|
{
|
||||||
|
|
||||||
|
btAssert(m_useQuantization);
|
||||||
|
|
||||||
|
btVector3 clampedPoint(point2);
|
||||||
|
clampedPoint.setMax(m_bvhAabbMin);
|
||||||
|
clampedPoint.setMin(m_bvhAabbMax);
|
||||||
|
|
||||||
|
quantize(out,clampedPoint,isMax);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
SIMD_FORCE_INLINE btVector3 unQuantize(const unsigned short* vecIn) const
|
||||||
|
{
|
||||||
|
btVector3 vecOut;
|
||||||
|
vecOut.setValue(
|
||||||
|
(btScalar)(vecIn[0]) / (m_bvhQuantization.getX()),
|
||||||
|
(btScalar)(vecIn[1]) / (m_bvhQuantization.getY()),
|
||||||
|
(btScalar)(vecIn[2]) / (m_bvhQuantization.getZ()));
|
||||||
|
vecOut += m_bvhAabbMin;
|
||||||
|
return vecOut;
|
||||||
|
}
|
||||||
|
|
||||||
|
///setTraversalMode let's you choose between stackless, recursive or stackless cache friendly tree traversal. Note this is only implemented for quantized trees.
|
||||||
|
void setTraversalMode(btTraversalMode traversalMode)
|
||||||
|
{
|
||||||
|
m_traversalMode = traversalMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SIMD_FORCE_INLINE QuantizedNodeArray& getQuantizedNodeArray()
|
||||||
|
{
|
||||||
|
return m_quantizedContiguousNodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SIMD_FORCE_INLINE BvhSubtreeInfoArray& getSubtreeInfoArray()
|
||||||
|
{
|
||||||
|
return m_SubtreeHeaders;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/////Calculate space needed to store BVH for serialization
|
||||||
|
unsigned calculateSerializeBufferSize();
|
||||||
|
|
||||||
|
/// Data buffer MUST be 16 byte aligned
|
||||||
|
virtual bool serialize(void *o_alignedDataBuffer, unsigned i_dataBufferSize, bool i_swapEndian);
|
||||||
|
|
||||||
|
///deSerializeInPlace loads and initializes a BVH from a buffer in memory 'in place'
|
||||||
|
static btQuantizedBvh *deSerializeInPlace(void *i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian);
|
||||||
|
|
||||||
|
static unsigned int getAlignmentSerializationPadding();
|
||||||
|
|
||||||
|
SIMD_FORCE_INLINE bool isQuantized()
|
||||||
|
{
|
||||||
|
return m_useQuantization;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Special "copy" constructor that allows for in-place deserialization
|
||||||
|
// Prevents btVector3's default constructor from being called, but doesn't inialize much else
|
||||||
|
// ownsMemory should most likely be false if deserializing, and if you are not, don't call this (it also changes the function signature, which we need)
|
||||||
|
btQuantizedBvh(btQuantizedBvh &other, bool ownsMemory);
|
||||||
|
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
|
#endif //QUANTIZED_BVH_H
|
85
extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp
vendored
Normal file
85
extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp
vendored
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
/*
|
||||||
|
Bullet Continuous Collision Detection and Physics Library
|
||||||
|
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "btBoxBoxCollisionAlgorithm.h"
|
||||||
|
#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
|
||||||
|
#include "BulletCollision/CollisionShapes/btBoxShape.h"
|
||||||
|
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
|
||||||
|
#include "btBoxBoxDetector.h"
|
||||||
|
|
||||||
|
#define USE_PERSISTENT_CONTACTS 1
|
||||||
|
|
||||||
|
btBoxBoxCollisionAlgorithm::btBoxBoxCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* obj0,btCollisionObject* obj1)
|
||||||
|
: btCollisionAlgorithm(ci),
|
||||||
|
m_ownManifold(false),
|
||||||
|
m_manifoldPtr(mf)
|
||||||
|
{
|
||||||
|
if (!m_manifoldPtr && m_dispatcher->needsCollision(obj0,obj1))
|
||||||
|
{
|
||||||
|
m_manifoldPtr = m_dispatcher->getNewManifold(obj0,obj1);
|
||||||
|
m_ownManifold = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
btBoxBoxCollisionAlgorithm::~btBoxBoxCollisionAlgorithm()
|
||||||
|
{
|
||||||
|
if (m_ownManifold)
|
||||||
|
{
|
||||||
|
if (m_manifoldPtr)
|
||||||
|
m_dispatcher->releaseManifold(m_manifoldPtr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void btBoxBoxCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
|
||||||
|
{
|
||||||
|
if (!m_manifoldPtr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
btCollisionObject* col0 = body0;
|
||||||
|
btCollisionObject* col1 = body1;
|
||||||
|
btBoxShape* box0 = (btBoxShape*)col0->getCollisionShape();
|
||||||
|
btBoxShape* box1 = (btBoxShape*)col1->getCollisionShape();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// report a contact. internally this will be kept persistent, and contact reduction is done
|
||||||
|
resultOut->setPersistentManifold(m_manifoldPtr);
|
||||||
|
#ifndef USE_PERSISTENT_CONTACTS
|
||||||
|
m_manifoldPtr->clearManifold();
|
||||||
|
#endif //USE_PERSISTENT_CONTACTS
|
||||||
|
|
||||||
|
btDiscreteCollisionDetectorInterface::ClosestPointInput input;
|
||||||
|
input.m_maximumDistanceSquared = 1e30f;
|
||||||
|
input.m_transformA = body0->getWorldTransform();
|
||||||
|
input.m_transformB = body1->getWorldTransform();
|
||||||
|
|
||||||
|
btBoxBoxDetector detector(box0,box1);
|
||||||
|
detector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw);
|
||||||
|
|
||||||
|
#ifdef USE_PERSISTENT_CONTACTS
|
||||||
|
// refreshContactPoints is only necessary when using persistent contact points. otherwise all points are newly added
|
||||||
|
if (m_ownManifold)
|
||||||
|
{
|
||||||
|
resultOut->refreshContactPoints();
|
||||||
|
}
|
||||||
|
#endif //USE_PERSISTENT_CONTACTS
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
btScalar btBoxBoxCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* /*body0*/,btCollisionObject* /*body1*/,const btDispatcherInfo& /*dispatchInfo*/,btManifoldResult* /*resultOut*/)
|
||||||
|
{
|
||||||
|
//not yet
|
||||||
|
return 1.f;
|
||||||
|
}
|
66
extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h
vendored
Normal file
66
extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h
vendored
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
Bullet Continuous Collision Detection and Physics Library
|
||||||
|
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef BOX_BOX__COLLISION_ALGORITHM_H
|
||||||
|
#define BOX_BOX__COLLISION_ALGORITHM_H
|
||||||
|
|
||||||
|
#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
|
||||||
|
#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
|
||||||
|
#include "BulletCollision/BroadphaseCollision/btDispatcher.h"
|
||||||
|
#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
|
||||||
|
|
||||||
|
class btPersistentManifold;
|
||||||
|
|
||||||
|
///box-box collision detection
|
||||||
|
class btBoxBoxCollisionAlgorithm : public btCollisionAlgorithm
|
||||||
|
{
|
||||||
|
bool m_ownManifold;
|
||||||
|
btPersistentManifold* m_manifoldPtr;
|
||||||
|
|
||||||
|
public:
|
||||||
|
btBoxBoxCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci)
|
||||||
|
: btCollisionAlgorithm(ci) {}
|
||||||
|
|
||||||
|
virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
|
||||||
|
|
||||||
|
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
|
||||||
|
|
||||||
|
btBoxBoxCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1);
|
||||||
|
|
||||||
|
virtual ~btBoxBoxCollisionAlgorithm();
|
||||||
|
|
||||||
|
virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
|
||||||
|
{
|
||||||
|
if (m_manifoldPtr && m_ownManifold)
|
||||||
|
{
|
||||||
|
manifoldArray.push_back(m_manifoldPtr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct CreateFunc :public btCollisionAlgorithmCreateFunc
|
||||||
|
{
|
||||||
|
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
|
||||||
|
{
|
||||||
|
int bbsize = sizeof(btBoxBoxCollisionAlgorithm);
|
||||||
|
void* ptr = ci.m_dispatcher1->allocateCollisionAlgorithm(bbsize);
|
||||||
|
return new(ptr) btBoxBoxCollisionAlgorithm(0,ci,body0,body1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //BOX_BOX__COLLISION_ALGORITHM_H
|
||||||
|
|
683
extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp
vendored
Normal file
683
extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp
vendored
Normal file
@ -0,0 +1,683 @@
|
|||||||
|
|
||||||
|
/*
|
||||||
|
* Box-Box collision detection re-distributed under the ZLib license with permission from Russell L. Smith
|
||||||
|
* Original version is from Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.
|
||||||
|
* All rights reserved. Email: russ@q12.org Web: www.q12.org
|
||||||
|
Bullet Continuous Collision Detection and Physics Library
|
||||||
|
Bullet is Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
///ODE box-box collision detection is adapted to work with Bullet
|
||||||
|
|
||||||
|
#include "btBoxBoxDetector.h"
|
||||||
|
#include "BulletCollision/CollisionShapes/btBoxShape.h"
|
||||||
|
|
||||||
|
#include <float.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
btBoxBoxDetector::btBoxBoxDetector(btBoxShape* box1,btBoxShape* box2)
|
||||||
|
: m_box1(box1),
|
||||||
|
m_box2(box2)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// given two boxes (p1,R1,side1) and (p2,R2,side2), collide them together and
|
||||||
|
// generate contact points. this returns 0 if there is no contact otherwise
|
||||||
|
// it returns the number of contacts generated.
|
||||||
|
// `normal' returns the contact normal.
|
||||||
|
// `depth' returns the maximum penetration depth along that normal.
|
||||||
|
// `return_code' returns a number indicating the type of contact that was
|
||||||
|
// detected:
|
||||||
|
// 1,2,3 = box 2 intersects with a face of box 1
|
||||||
|
// 4,5,6 = box 1 intersects with a face of box 2
|
||||||
|
// 7..15 = edge-edge contact
|
||||||
|
// `maxc' is the maximum number of contacts allowed to be generated, i.e.
|
||||||
|
// the size of the `contact' array.
|
||||||
|
// `contact' and `skip' are the contact array information provided to the
|
||||||
|
// collision functions. this function only fills in the position and depth
|
||||||
|
// fields.
|
||||||
|
struct dContactGeom;
|
||||||
|
#define dDOTpq(a,b,p,q) ((a)[0]*(b)[0] + (a)[p]*(b)[q] + (a)[2*(p)]*(b)[2*(q)])
|
||||||
|
#define dInfinity FLT_MAX
|
||||||
|
|
||||||
|
|
||||||
|
/*PURE_INLINE btScalar dDOT (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,1,1); }
|
||||||
|
PURE_INLINE btScalar dDOT13 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,1,3); }
|
||||||
|
PURE_INLINE btScalar dDOT31 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,3,1); }
|
||||||
|
PURE_INLINE btScalar dDOT33 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,3,3); }
|
||||||
|
*/
|
||||||
|
static btScalar dDOT (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,1,1); }
|
||||||
|
static btScalar dDOT44 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,4,4); }
|
||||||
|
static btScalar dDOT41 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,4,1); }
|
||||||
|
static btScalar dDOT14 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,1,4); }
|
||||||
|
#define dMULTIPLYOP1_331(A,op,B,C) \
|
||||||
|
{\
|
||||||
|
(A)[0] op dDOT41((B),(C)); \
|
||||||
|
(A)[1] op dDOT41((B+1),(C)); \
|
||||||
|
(A)[2] op dDOT41((B+2),(C)); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define dMULTIPLYOP0_331(A,op,B,C) \
|
||||||
|
{ \
|
||||||
|
(A)[0] op dDOT((B),(C)); \
|
||||||
|
(A)[1] op dDOT((B+4),(C)); \
|
||||||
|
(A)[2] op dDOT((B+8),(C)); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define dMULTIPLY1_331(A,B,C) dMULTIPLYOP1_331(A,=,B,C)
|
||||||
|
#define dMULTIPLY0_331(A,B,C) dMULTIPLYOP0_331(A,=,B,C)
|
||||||
|
|
||||||
|
typedef btScalar dMatrix3[4*3];
|
||||||
|
|
||||||
|
void dLineClosestApproach (const btVector3& pa, const btVector3& ua,
|
||||||
|
const btVector3& pb, const btVector3& ub,
|
||||||
|
btScalar *alpha, btScalar *beta);
|
||||||
|
void dLineClosestApproach (const btVector3& pa, const btVector3& ua,
|
||||||
|
const btVector3& pb, const btVector3& ub,
|
||||||
|
btScalar *alpha, btScalar *beta)
|
||||||
|
{
|
||||||
|
btVector3 p;
|
||||||
|
p[0] = pb[0] - pa[0];
|
||||||
|
p[1] = pb[1] - pa[1];
|
||||||
|
p[2] = pb[2] - pa[2];
|
||||||
|
btScalar uaub = dDOT(ua,ub);
|
||||||
|
btScalar q1 = dDOT(ua,p);
|
||||||
|
btScalar q2 = -dDOT(ub,p);
|
||||||
|
btScalar d = 1-uaub*uaub;
|
||||||
|
if (d <= btScalar(0.0001f)) {
|
||||||
|
// @@@ this needs to be made more robust
|
||||||
|
*alpha = 0;
|
||||||
|
*beta = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
d = 1.f/d;
|
||||||
|
*alpha = (q1 + uaub*q2)*d;
|
||||||
|
*beta = (uaub*q1 + q2)*d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// find all the intersection points between the 2D rectangle with vertices
|
||||||
|
// at (+/-h[0],+/-h[1]) and the 2D quadrilateral with vertices (p[0],p[1]),
|
||||||
|
// (p[2],p[3]),(p[4],p[5]),(p[6],p[7]).
|
||||||
|
//
|
||||||
|
// the intersection points are returned as x,y pairs in the 'ret' array.
|
||||||
|
// the number of intersection points is returned by the function (this will
|
||||||
|
// be in the range 0 to 8).
|
||||||
|
|
||||||
|
static int intersectRectQuad2 (btScalar h[2], btScalar p[8], btScalar ret[16])
|
||||||
|
{
|
||||||
|
// q (and r) contain nq (and nr) coordinate points for the current (and
|
||||||
|
// chopped) polygons
|
||||||
|
int nq=4,nr=0;
|
||||||
|
btScalar buffer[16];
|
||||||
|
btScalar *q = p;
|
||||||
|
btScalar *r = ret;
|
||||||
|
for (int dir=0; dir <= 1; dir++) {
|
||||||
|
// direction notation: xy[0] = x axis, xy[1] = y axis
|
||||||
|
for (int sign=-1; sign <= 1; sign += 2) {
|
||||||
|
// chop q along the line xy[dir] = sign*h[dir]
|
||||||
|
btScalar *pq = q;
|
||||||
|
btScalar *pr = r;
|
||||||
|
nr = 0;
|
||||||
|
for (int i=nq; i > 0; i--) {
|
||||||
|
// go through all points in q and all lines between adjacent points
|
||||||
|
if (sign*pq[dir] < h[dir]) {
|
||||||
|
// this point is inside the chopping line
|
||||||
|
pr[0] = pq[0];
|
||||||
|
pr[1] = pq[1];
|
||||||
|
pr += 2;
|
||||||
|
nr++;
|
||||||
|
if (nr & 8) {
|
||||||
|
q = r;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
btScalar *nextq = (i > 1) ? pq+2 : q;
|
||||||
|
if ((sign*pq[dir] < h[dir]) ^ (sign*nextq[dir] < h[dir])) {
|
||||||
|
// this line crosses the chopping line
|
||||||
|
pr[1-dir] = pq[1-dir] + (nextq[1-dir]-pq[1-dir]) /
|
||||||
|
(nextq[dir]-pq[dir]) * (sign*h[dir]-pq[dir]);
|
||||||
|
pr[dir] = sign*h[dir];
|
||||||
|
pr += 2;
|
||||||
|
nr++;
|
||||||
|
if (nr & 8) {
|
||||||
|
q = r;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pq += 2;
|
||||||
|
}
|
||||||
|
q = r;
|
||||||
|
r = (q==ret) ? buffer : ret;
|
||||||
|
nq = nr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
done:
|
||||||
|
if (q != ret) memcpy (ret,q,nr*2*sizeof(btScalar));
|
||||||
|
return nr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#define M__PI 3.14159265f
|
||||||
|
|
||||||
|
// given n points in the plane (array p, of size 2*n), generate m points that
|
||||||
|
// best represent the whole set. the definition of 'best' here is not
|
||||||
|
// predetermined - the idea is to select points that give good box-box
|
||||||
|
// collision detection behavior. the chosen point indexes are returned in the
|
||||||
|
// array iret (of size m). 'i0' is always the first entry in the array.
|
||||||
|
// n must be in the range [1..8]. m must be in the range [1..n]. i0 must be
|
||||||
|
// in the range [0..n-1].
|
||||||
|
|
||||||
|
void cullPoints2 (int n, btScalar p[], int m, int i0, int iret[]);
|
||||||
|
void cullPoints2 (int n, btScalar p[], int m, int i0, int iret[])
|
||||||
|
{
|
||||||
|
// compute the centroid of the polygon in cx,cy
|
||||||
|
int i,j;
|
||||||
|
btScalar a,cx,cy,q;
|
||||||
|
if (n==1) {
|
||||||
|
cx = p[0];
|
||||||
|
cy = p[1];
|
||||||
|
}
|
||||||
|
else if (n==2) {
|
||||||
|
cx = btScalar(0.5)*(p[0] + p[2]);
|
||||||
|
cy = btScalar(0.5)*(p[1] + p[3]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
a = 0;
|
||||||
|
cx = 0;
|
||||||
|
cy = 0;
|
||||||
|
for (i=0; i<(n-1); i++) {
|
||||||
|
q = p[i*2]*p[i*2+3] - p[i*2+2]*p[i*2+1];
|
||||||
|
a += q;
|
||||||
|
cx += q*(p[i*2]+p[i*2+2]);
|
||||||
|
cy += q*(p[i*2+1]+p[i*2+3]);
|
||||||
|
}
|
||||||
|
q = p[n*2-2]*p[1] - p[0]*p[n*2-1];
|
||||||
|
a = 1.f/(btScalar(3.0)*(a+q));
|
||||||
|
cx = a*(cx + q*(p[n*2-2]+p[0]));
|
||||||
|
cy = a*(cy + q*(p[n*2-1]+p[1]));
|
||||||
|
}
|
||||||
|
|
||||||
|
// compute the angle of each point w.r.t. the centroid
|
||||||
|
btScalar A[8];
|
||||||
|
for (i=0; i<n; i++) A[i] = btAtan2(p[i*2+1]-cy,p[i*2]-cx);
|
||||||
|
|
||||||
|
// search for points that have angles closest to A[i0] + i*(2*pi/m).
|
||||||
|
int avail[8];
|
||||||
|
for (i=0; i<n; i++) avail[i] = 1;
|
||||||
|
avail[i0] = 0;
|
||||||
|
iret[0] = i0;
|
||||||
|
iret++;
|
||||||
|
for (j=1; j<m; j++) {
|
||||||
|
a = btScalar(j)*(2*M__PI/m) + A[i0];
|
||||||
|
if (a > M__PI) a -= 2*M__PI;
|
||||||
|
btScalar maxdiff=1e9,diff;
|
||||||
|
#if defined(DEBUG) || defined (_DEBUG)
|
||||||
|
*iret = i0; // iret is not allowed to keep this value
|
||||||
|
#endif
|
||||||
|
for (i=0; i<n; i++) {
|
||||||
|
if (avail[i]) {
|
||||||
|
diff = btFabs (A[i]-a);
|
||||||
|
if (diff > M__PI) diff = 2*M__PI - diff;
|
||||||
|
if (diff < maxdiff) {
|
||||||
|
maxdiff = diff;
|
||||||
|
*iret = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#if defined(DEBUG) || defined (_DEBUG)
|
||||||
|
btAssert (*iret != i0); // ensure iret got set
|
||||||
|
#endif
|
||||||
|
avail[*iret] = 0;
|
||||||
|
iret++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int dBoxBox2 (const btVector3& p1, const dMatrix3 R1,
|
||||||
|
const btVector3& side1, const btVector3& p2,
|
||||||
|
const dMatrix3 R2, const btVector3& side2,
|
||||||
|
btVector3& normal, btScalar *depth, int *return_code,
|
||||||
|
int maxc, dContactGeom * /*contact*/, int /*skip*/,btDiscreteCollisionDetectorInterface::Result& output);
|
||||||
|
int dBoxBox2 (const btVector3& p1, const dMatrix3 R1,
|
||||||
|
const btVector3& side1, const btVector3& p2,
|
||||||
|
const dMatrix3 R2, const btVector3& side2,
|
||||||
|
btVector3& normal, btScalar *depth, int *return_code,
|
||||||
|
int maxc, dContactGeom * /*contact*/, int /*skip*/,btDiscreteCollisionDetectorInterface::Result& output)
|
||||||
|
{
|
||||||
|
const btScalar fudge_factor = btScalar(1.05);
|
||||||
|
btVector3 p,pp,normalC;
|
||||||
|
const btScalar *normalR = 0;
|
||||||
|
btScalar A[3],B[3],R11,R12,R13,R21,R22,R23,R31,R32,R33,
|
||||||
|
Q11,Q12,Q13,Q21,Q22,Q23,Q31,Q32,Q33,s,s2,l;
|
||||||
|
int i,j,invert_normal,code;
|
||||||
|
|
||||||
|
// get vector from centers of box 1 to box 2, relative to box 1
|
||||||
|
p = p2 - p1;
|
||||||
|
dMULTIPLY1_331 (pp,R1,p); // get pp = p relative to body 1
|
||||||
|
|
||||||
|
// get side lengths / 2
|
||||||
|
A[0] = side1[0]*btScalar(0.5);
|
||||||
|
A[1] = side1[1]*btScalar(0.5);
|
||||||
|
A[2] = side1[2]*btScalar(0.5);
|
||||||
|
B[0] = side2[0]*btScalar(0.5);
|
||||||
|
B[1] = side2[1]*btScalar(0.5);
|
||||||
|
B[2] = side2[2]*btScalar(0.5);
|
||||||
|
|
||||||
|
// Rij is R1'*R2, i.e. the relative rotation between R1 and R2
|
||||||
|
R11 = dDOT44(R1+0,R2+0); R12 = dDOT44(R1+0,R2+1); R13 = dDOT44(R1+0,R2+2);
|
||||||
|
R21 = dDOT44(R1+1,R2+0); R22 = dDOT44(R1+1,R2+1); R23 = dDOT44(R1+1,R2+2);
|
||||||
|
R31 = dDOT44(R1+2,R2+0); R32 = dDOT44(R1+2,R2+1); R33 = dDOT44(R1+2,R2+2);
|
||||||
|
|
||||||
|
Q11 = btFabs(R11); Q12 = btFabs(R12); Q13 = btFabs(R13);
|
||||||
|
Q21 = btFabs(R21); Q22 = btFabs(R22); Q23 = btFabs(R23);
|
||||||
|
Q31 = btFabs(R31); Q32 = btFabs(R32); Q33 = btFabs(R33);
|
||||||
|
|
||||||
|
// for all 15 possible separating axes:
|
||||||
|
// * see if the axis separates the boxes. if so, return 0.
|
||||||
|
// * find the depth of the penetration along the separating axis (s2)
|
||||||
|
// * if this is the largest depth so far, record it.
|
||||||
|
// the normal vector will be set to the separating axis with the smallest
|
||||||
|
// depth. note: normalR is set to point to a column of R1 or R2 if that is
|
||||||
|
// the smallest depth normal so far. otherwise normalR is 0 and normalC is
|
||||||
|
// set to a vector relative to body 1. invert_normal is 1 if the sign of
|
||||||
|
// the normal should be flipped.
|
||||||
|
|
||||||
|
#define TST(expr1,expr2,norm,cc) \
|
||||||
|
s2 = btFabs(expr1) - (expr2); \
|
||||||
|
if (s2 > 0) return 0; \
|
||||||
|
if (s2 > s) { \
|
||||||
|
s = s2; \
|
||||||
|
normalR = norm; \
|
||||||
|
invert_normal = ((expr1) < 0); \
|
||||||
|
code = (cc); \
|
||||||
|
}
|
||||||
|
|
||||||
|
s = -dInfinity;
|
||||||
|
invert_normal = 0;
|
||||||
|
code = 0;
|
||||||
|
|
||||||
|
// separating axis = u1,u2,u3
|
||||||
|
TST (pp[0],(A[0] + B[0]*Q11 + B[1]*Q12 + B[2]*Q13),R1+0,1);
|
||||||
|
TST (pp[1],(A[1] + B[0]*Q21 + B[1]*Q22 + B[2]*Q23),R1+1,2);
|
||||||
|
TST (pp[2],(A[2] + B[0]*Q31 + B[1]*Q32 + B[2]*Q33),R1+2,3);
|
||||||
|
|
||||||
|
// separating axis = v1,v2,v3
|
||||||
|
TST (dDOT41(R2+0,p),(A[0]*Q11 + A[1]*Q21 + A[2]*Q31 + B[0]),R2+0,4);
|
||||||
|
TST (dDOT41(R2+1,p),(A[0]*Q12 + A[1]*Q22 + A[2]*Q32 + B[1]),R2+1,5);
|
||||||
|
TST (dDOT41(R2+2,p),(A[0]*Q13 + A[1]*Q23 + A[2]*Q33 + B[2]),R2+2,6);
|
||||||
|
|
||||||
|
// note: cross product axes need to be scaled when s is computed.
|
||||||
|
// normal (n1,n2,n3) is relative to box 1.
|
||||||
|
#undef TST
|
||||||
|
#define TST(expr1,expr2,n1,n2,n3,cc) \
|
||||||
|
s2 = btFabs(expr1) - (expr2); \
|
||||||
|
if (s2 > 0) return 0; \
|
||||||
|
l = btSqrt((n1)*(n1) + (n2)*(n2) + (n3)*(n3)); \
|
||||||
|
if (l > 0) { \
|
||||||
|
s2 /= l; \
|
||||||
|
if (s2*fudge_factor > s) { \
|
||||||
|
s = s2; \
|
||||||
|
normalR = 0; \
|
||||||
|
normalC[0] = (n1)/l; normalC[1] = (n2)/l; normalC[2] = (n3)/l; \
|
||||||
|
invert_normal = ((expr1) < 0); \
|
||||||
|
code = (cc); \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
// separating axis = u1 x (v1,v2,v3)
|
||||||
|
TST(pp[2]*R21-pp[1]*R31,(A[1]*Q31+A[2]*Q21+B[1]*Q13+B[2]*Q12),0,-R31,R21,7);
|
||||||
|
TST(pp[2]*R22-pp[1]*R32,(A[1]*Q32+A[2]*Q22+B[0]*Q13+B[2]*Q11),0,-R32,R22,8);
|
||||||
|
TST(pp[2]*R23-pp[1]*R33,(A[1]*Q33+A[2]*Q23+B[0]*Q12+B[1]*Q11),0,-R33,R23,9);
|
||||||
|
|
||||||
|
// separating axis = u2 x (v1,v2,v3)
|
||||||
|
TST(pp[0]*R31-pp[2]*R11,(A[0]*Q31+A[2]*Q11+B[1]*Q23+B[2]*Q22),R31,0,-R11,10);
|
||||||
|
TST(pp[0]*R32-pp[2]*R12,(A[0]*Q32+A[2]*Q12+B[0]*Q23+B[2]*Q21),R32,0,-R12,11);
|
||||||
|
TST(pp[0]*R33-pp[2]*R13,(A[0]*Q33+A[2]*Q13+B[0]*Q22+B[1]*Q21),R33,0,-R13,12);
|
||||||
|
|
||||||
|
// separating axis = u3 x (v1,v2,v3)
|
||||||
|
TST(pp[1]*R11-pp[0]*R21,(A[0]*Q21+A[1]*Q11+B[1]*Q33+B[2]*Q32),-R21,R11,0,13);
|
||||||
|
TST(pp[1]*R12-pp[0]*R22,(A[0]*Q22+A[1]*Q12+B[0]*Q33+B[2]*Q31),-R22,R12,0,14);
|
||||||
|
TST(pp[1]*R13-pp[0]*R23,(A[0]*Q23+A[1]*Q13+B[0]*Q32+B[1]*Q31),-R23,R13,0,15);
|
||||||
|
|
||||||
|
#undef TST
|
||||||
|
|
||||||
|
if (!code) return 0;
|
||||||
|
|
||||||
|
// if we get to this point, the boxes interpenetrate. compute the normal
|
||||||
|
// in global coordinates.
|
||||||
|
if (normalR) {
|
||||||
|
normal[0] = normalR[0];
|
||||||
|
normal[1] = normalR[4];
|
||||||
|
normal[2] = normalR[8];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
dMULTIPLY0_331 (normal,R1,normalC);
|
||||||
|
}
|
||||||
|
if (invert_normal) {
|
||||||
|
normal[0] = -normal[0];
|
||||||
|
normal[1] = -normal[1];
|
||||||
|
normal[2] = -normal[2];
|
||||||
|
}
|
||||||
|
*depth = -s;
|
||||||
|
|
||||||
|
// compute contact point(s)
|
||||||
|
|
||||||
|
if (code > 6) {
|
||||||
|
// an edge from box 1 touches an edge from box 2.
|
||||||
|
// find a point pa on the intersecting edge of box 1
|
||||||
|
btVector3 pa;
|
||||||
|
btScalar sign;
|
||||||
|
for (i=0; i<3; i++) pa[i] = p1[i];
|
||||||
|
for (j=0; j<3; j++) {
|
||||||
|
sign = (dDOT14(normal,R1+j) > 0) ? btScalar(1.0) : btScalar(-1.0);
|
||||||
|
for (i=0; i<3; i++) pa[i] += sign * A[j] * R1[i*4+j];
|
||||||
|
}
|
||||||
|
|
||||||
|
// find a point pb on the intersecting edge of box 2
|
||||||
|
btVector3 pb;
|
||||||
|
for (i=0; i<3; i++) pb[i] = p2[i];
|
||||||
|
for (j=0; j<3; j++) {
|
||||||
|
sign = (dDOT14(normal,R2+j) > 0) ? btScalar(-1.0) : btScalar(1.0);
|
||||||
|
for (i=0; i<3; i++) pb[i] += sign * B[j] * R2[i*4+j];
|
||||||
|
}
|
||||||
|
|
||||||
|
btScalar alpha,beta;
|
||||||
|
btVector3 ua,ub;
|
||||||
|
for (i=0; i<3; i++) ua[i] = R1[((code)-7)/3 + i*4];
|
||||||
|
for (i=0; i<3; i++) ub[i] = R2[((code)-7)%3 + i*4];
|
||||||
|
|
||||||
|
dLineClosestApproach (pa,ua,pb,ub,&alpha,&beta);
|
||||||
|
for (i=0; i<3; i++) pa[i] += ua[i]*alpha;
|
||||||
|
for (i=0; i<3; i++) pb[i] += ub[i]*beta;
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
//contact[0].pos[i] = btScalar(0.5)*(pa[i]+pb[i]);
|
||||||
|
//contact[0].depth = *depth;
|
||||||
|
btVector3 pointInWorld;
|
||||||
|
|
||||||
|
#ifdef USE_CENTER_POINT
|
||||||
|
for (i=0; i<3; i++)
|
||||||
|
pointInWorld[i] = (pa[i]+pb[i])*btScalar(0.5);
|
||||||
|
output.addContactPoint(-normal,pointInWorld,-*depth);
|
||||||
|
#else
|
||||||
|
output.addContactPoint(-normal,pb,-*depth);
|
||||||
|
#endif //
|
||||||
|
*return_code = code;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// okay, we have a face-something intersection (because the separating
|
||||||
|
// axis is perpendicular to a face). define face 'a' to be the reference
|
||||||
|
// face (i.e. the normal vector is perpendicular to this) and face 'b' to be
|
||||||
|
// the incident face (the closest face of the other box).
|
||||||
|
|
||||||
|
const btScalar *Ra,*Rb,*pa,*pb,*Sa,*Sb;
|
||||||
|
if (code <= 3) {
|
||||||
|
Ra = R1;
|
||||||
|
Rb = R2;
|
||||||
|
pa = p1;
|
||||||
|
pb = p2;
|
||||||
|
Sa = A;
|
||||||
|
Sb = B;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Ra = R2;
|
||||||
|
Rb = R1;
|
||||||
|
pa = p2;
|
||||||
|
pb = p1;
|
||||||
|
Sa = B;
|
||||||
|
Sb = A;
|
||||||
|
}
|
||||||
|
|
||||||
|
// nr = normal vector of reference face dotted with axes of incident box.
|
||||||
|
// anr = absolute values of nr.
|
||||||
|
btVector3 normal2,nr,anr;
|
||||||
|
if (code <= 3) {
|
||||||
|
normal2[0] = normal[0];
|
||||||
|
normal2[1] = normal[1];
|
||||||
|
normal2[2] = normal[2];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
normal2[0] = -normal[0];
|
||||||
|
normal2[1] = -normal[1];
|
||||||
|
normal2[2] = -normal[2];
|
||||||
|
}
|
||||||
|
dMULTIPLY1_331 (nr,Rb,normal2);
|
||||||
|
anr[0] = btFabs (nr[0]);
|
||||||
|
anr[1] = btFabs (nr[1]);
|
||||||
|
anr[2] = btFabs (nr[2]);
|
||||||
|
|
||||||
|
// find the largest compontent of anr: this corresponds to the normal
|
||||||
|
// for the indident face. the other axis numbers of the indicent face
|
||||||
|
// are stored in a1,a2.
|
||||||
|
int lanr,a1,a2;
|
||||||
|
if (anr[1] > anr[0]) {
|
||||||
|
if (anr[1] > anr[2]) {
|
||||||
|
a1 = 0;
|
||||||
|
lanr = 1;
|
||||||
|
a2 = 2;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
a1 = 0;
|
||||||
|
a2 = 1;
|
||||||
|
lanr = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (anr[0] > anr[2]) {
|
||||||
|
lanr = 0;
|
||||||
|
a1 = 1;
|
||||||
|
a2 = 2;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
a1 = 0;
|
||||||
|
a2 = 1;
|
||||||
|
lanr = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// compute center point of incident face, in reference-face coordinates
|
||||||
|
btVector3 center;
|
||||||
|
if (nr[lanr] < 0) {
|
||||||
|
for (i=0; i<3; i++) center[i] = pb[i] - pa[i] + Sb[lanr] * Rb[i*4+lanr];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for (i=0; i<3; i++) center[i] = pb[i] - pa[i] - Sb[lanr] * Rb[i*4+lanr];
|
||||||
|
}
|
||||||
|
|
||||||
|
// find the normal and non-normal axis numbers of the reference box
|
||||||
|
int codeN,code1,code2;
|
||||||
|
if (code <= 3) codeN = code-1; else codeN = code-4;
|
||||||
|
if (codeN==0) {
|
||||||
|
code1 = 1;
|
||||||
|
code2 = 2;
|
||||||
|
}
|
||||||
|
else if (codeN==1) {
|
||||||
|
code1 = 0;
|
||||||
|
code2 = 2;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
code1 = 0;
|
||||||
|
code2 = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// find the four corners of the incident face, in reference-face coordinates
|
||||||
|
btScalar quad[8]; // 2D coordinate of incident face (x,y pairs)
|
||||||
|
btScalar c1,c2,m11,m12,m21,m22;
|
||||||
|
c1 = dDOT14 (center,Ra+code1);
|
||||||
|
c2 = dDOT14 (center,Ra+code2);
|
||||||
|
// optimize this? - we have already computed this data above, but it is not
|
||||||
|
// stored in an easy-to-index format. for now it's quicker just to recompute
|
||||||
|
// the four dot products.
|
||||||
|
m11 = dDOT44 (Ra+code1,Rb+a1);
|
||||||
|
m12 = dDOT44 (Ra+code1,Rb+a2);
|
||||||
|
m21 = dDOT44 (Ra+code2,Rb+a1);
|
||||||
|
m22 = dDOT44 (Ra+code2,Rb+a2);
|
||||||
|
{
|
||||||
|
btScalar k1 = m11*Sb[a1];
|
||||||
|
btScalar k2 = m21*Sb[a1];
|
||||||
|
btScalar k3 = m12*Sb[a2];
|
||||||
|
btScalar k4 = m22*Sb[a2];
|
||||||
|
quad[0] = c1 - k1 - k3;
|
||||||
|
quad[1] = c2 - k2 - k4;
|
||||||
|
quad[2] = c1 - k1 + k3;
|
||||||
|
quad[3] = c2 - k2 + k4;
|
||||||
|
quad[4] = c1 + k1 + k3;
|
||||||
|
quad[5] = c2 + k2 + k4;
|
||||||
|
quad[6] = c1 + k1 - k3;
|
||||||
|
quad[7] = c2 + k2 - k4;
|
||||||
|
}
|
||||||
|
|
||||||
|
// find the size of the reference face
|
||||||
|
btScalar rect[2];
|
||||||
|
rect[0] = Sa[code1];
|
||||||
|
rect[1] = Sa[code2];
|
||||||
|
|
||||||
|
// intersect the incident and reference faces
|
||||||
|
btScalar ret[16];
|
||||||
|
int n = intersectRectQuad2 (rect,quad,ret);
|
||||||
|
if (n < 1) return 0; // this should never happen
|
||||||
|
|
||||||
|
// convert the intersection points into reference-face coordinates,
|
||||||
|
// and compute the contact position and depth for each point. only keep
|
||||||
|
// those points that have a positive (penetrating) depth. delete points in
|
||||||
|
// the 'ret' array as necessary so that 'point' and 'ret' correspond.
|
||||||
|
btScalar point[3*8]; // penetrating contact points
|
||||||
|
btScalar dep[8]; // depths for those points
|
||||||
|
btScalar det1 = 1.f/(m11*m22 - m12*m21);
|
||||||
|
m11 *= det1;
|
||||||
|
m12 *= det1;
|
||||||
|
m21 *= det1;
|
||||||
|
m22 *= det1;
|
||||||
|
int cnum = 0; // number of penetrating contact points found
|
||||||
|
for (j=0; j < n; j++) {
|
||||||
|
btScalar k1 = m22*(ret[j*2]-c1) - m12*(ret[j*2+1]-c2);
|
||||||
|
btScalar k2 = -m21*(ret[j*2]-c1) + m11*(ret[j*2+1]-c2);
|
||||||
|
for (i=0; i<3; i++) point[cnum*3+i] =
|
||||||
|
center[i] + k1*Rb[i*4+a1] + k2*Rb[i*4+a2];
|
||||||
|
dep[cnum] = Sa[codeN] - dDOT(normal2,point+cnum*3);
|
||||||
|
if (dep[cnum] >= 0) {
|
||||||
|
ret[cnum*2] = ret[j*2];
|
||||||
|
ret[cnum*2+1] = ret[j*2+1];
|
||||||
|
cnum++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (cnum < 1) return 0; // this should never happen
|
||||||
|
|
||||||
|
// we can't generate more contacts than we actually have
|
||||||
|
if (maxc > cnum) maxc = cnum;
|
||||||
|
if (maxc < 1) maxc = 1;
|
||||||
|
|
||||||
|
if (cnum <= maxc) {
|
||||||
|
// we have less contacts than we need, so we use them all
|
||||||
|
for (j=0; j < cnum; j++) {
|
||||||
|
|
||||||
|
//AddContactPoint...
|
||||||
|
|
||||||
|
//dContactGeom *con = CONTACT(contact,skip*j);
|
||||||
|
//for (i=0; i<3; i++) con->pos[i] = point[j*3+i] + pa[i];
|
||||||
|
//con->depth = dep[j];
|
||||||
|
|
||||||
|
btVector3 pointInWorld;
|
||||||
|
for (i=0; i<3; i++)
|
||||||
|
pointInWorld[i] = point[j*3+i] + pa[i];
|
||||||
|
output.addContactPoint(-normal,pointInWorld,-dep[j]);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// we have more contacts than are wanted, some of them must be culled.
|
||||||
|
// find the deepest point, it is always the first contact.
|
||||||
|
int i1 = 0;
|
||||||
|
btScalar maxdepth = dep[0];
|
||||||
|
for (i=1; i<cnum; i++) {
|
||||||
|
if (dep[i] > maxdepth) {
|
||||||
|
maxdepth = dep[i];
|
||||||
|
i1 = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int iret[8];
|
||||||
|
cullPoints2 (cnum,ret,maxc,i1,iret);
|
||||||
|
|
||||||
|
for (j=0; j < maxc; j++) {
|
||||||
|
// dContactGeom *con = CONTACT(contact,skip*j);
|
||||||
|
// for (i=0; i<3; i++) con->pos[i] = point[iret[j]*3+i] + pa[i];
|
||||||
|
// con->depth = dep[iret[j]];
|
||||||
|
|
||||||
|
btVector3 posInWorld;
|
||||||
|
for (i=0; i<3; i++)
|
||||||
|
posInWorld[i] = point[iret[j]*3+i] + pa[i];
|
||||||
|
output.addContactPoint(-normal,posInWorld,-dep[iret[j]]);
|
||||||
|
}
|
||||||
|
cnum = maxc;
|
||||||
|
}
|
||||||
|
|
||||||
|
*return_code = code;
|
||||||
|
return cnum;
|
||||||
|
}
|
||||||
|
|
||||||
|
void btBoxBoxDetector::getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* /*debugDraw*/,bool /*swapResults*/)
|
||||||
|
{
|
||||||
|
|
||||||
|
const btTransform& transformA = input.m_transformA;
|
||||||
|
const btTransform& transformB = input.m_transformB;
|
||||||
|
|
||||||
|
int skip = 0;
|
||||||
|
dContactGeom *contact = 0;
|
||||||
|
|
||||||
|
dMatrix3 R1;
|
||||||
|
dMatrix3 R2;
|
||||||
|
|
||||||
|
for (int j=0;j<3;j++)
|
||||||
|
{
|
||||||
|
R1[0+4*j] = transformA.getBasis()[j].x();
|
||||||
|
R2[0+4*j] = transformB.getBasis()[j].x();
|
||||||
|
|
||||||
|
R1[1+4*j] = transformA.getBasis()[j].y();
|
||||||
|
R2[1+4*j] = transformB.getBasis()[j].y();
|
||||||
|
|
||||||
|
|
||||||
|
R1[2+4*j] = transformA.getBasis()[j].z();
|
||||||
|
R2[2+4*j] = transformB.getBasis()[j].z();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
btVector3 normal;
|
||||||
|
btScalar depth;
|
||||||
|
int return_code;
|
||||||
|
int maxc = 4;
|
||||||
|
|
||||||
|
|
||||||
|
dBoxBox2 (transformA.getOrigin(),
|
||||||
|
R1,
|
||||||
|
2.f*m_box1->getHalfExtentsWithMargin(),
|
||||||
|
transformB.getOrigin(),
|
||||||
|
R2,
|
||||||
|
2.f*m_box2->getHalfExtentsWithMargin(),
|
||||||
|
normal, &depth, &return_code,
|
||||||
|
maxc, contact, skip,
|
||||||
|
output
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
44
extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.h
vendored
Normal file
44
extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.h
vendored
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* Box-Box collision detection re-distributed under the ZLib license with permission from Russell L. Smith
|
||||||
|
* Original version is from Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.
|
||||||
|
* All rights reserved. Email: russ@q12.org Web: www.q12.org
|
||||||
|
|
||||||
|
Bullet Continuous Collision Detection and Physics Library
|
||||||
|
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
#ifndef BOX_BOX_DETECTOR_H
|
||||||
|
#define BOX_BOX_DETECTOR_H
|
||||||
|
|
||||||
|
|
||||||
|
class btBoxShape;
|
||||||
|
#include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h"
|
||||||
|
|
||||||
|
|
||||||
|
/// btBoxBoxDetector wraps the ODE box-box collision detector
|
||||||
|
/// re-distributed under the Zlib license with permission from Russell L. Smith
|
||||||
|
struct btBoxBoxDetector : public btDiscreteCollisionDetectorInterface
|
||||||
|
{
|
||||||
|
btBoxShape* m_box1;
|
||||||
|
btBoxShape* m_box2;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
btBoxBoxDetector(btBoxShape* box1,btBoxShape* box2);
|
||||||
|
|
||||||
|
virtual ~btBoxBoxDetector() {};
|
||||||
|
|
||||||
|
virtual void getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw,bool swapResults=false);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //BT_BOX_BOX_DETECTOR_H
|
47
extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionConfiguration.h
vendored
Normal file
47
extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionConfiguration.h
vendored
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
Bullet Continuous Collision Detection and Physics Library
|
||||||
|
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef BT_COLLISION_CONFIGURATION
|
||||||
|
#define BT_COLLISION_CONFIGURATION
|
||||||
|
struct btCollisionAlgorithmCreateFunc;
|
||||||
|
|
||||||
|
class btStackAlloc;
|
||||||
|
class btPoolAllocator;
|
||||||
|
|
||||||
|
///btCollisionConfiguration allows to configure Bullet collision detection
|
||||||
|
///stack allocator size, default collision algorithms and persistent manifold pool size
|
||||||
|
///todo: describe the meaning
|
||||||
|
class btCollisionConfiguration
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual ~btCollisionConfiguration()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
///memory pools
|
||||||
|
virtual btPoolAllocator* getPersistentManifoldPool() = 0;
|
||||||
|
|
||||||
|
virtual btPoolAllocator* getCollisionAlgorithmPool() = 0;
|
||||||
|
|
||||||
|
virtual btStackAlloc* getStackAllocator() = 0;
|
||||||
|
|
||||||
|
virtual btCollisionAlgorithmCreateFunc* getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1) =0;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //BT_COLLISION_CONFIGURATION
|
||||||
|
|
108
extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp
vendored
Normal file
108
extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp
vendored
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
/*
|
||||||
|
Bullet Continuous Collision Detection and Physics Library
|
||||||
|
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "btConvexPlaneCollisionAlgorithm.h"
|
||||||
|
|
||||||
|
#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
|
||||||
|
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
|
||||||
|
#include "BulletCollision/CollisionShapes/btConvexShape.h"
|
||||||
|
#include "BulletCollision/CollisionShapes/btStaticPlaneShape.h"
|
||||||
|
|
||||||
|
//#include <stdio.h>
|
||||||
|
|
||||||
|
btConvexPlaneCollisionAlgorithm::btConvexPlaneCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1, bool isSwapped)
|
||||||
|
: btCollisionAlgorithm(ci),
|
||||||
|
m_ownManifold(false),
|
||||||
|
m_manifoldPtr(mf),
|
||||||
|
m_isSwapped(isSwapped)
|
||||||
|
{
|
||||||
|
btCollisionObject* convexObj = m_isSwapped? col1 : col0;
|
||||||
|
btCollisionObject* planeObj = m_isSwapped? col0 : col1;
|
||||||
|
|
||||||
|
if (!m_manifoldPtr && m_dispatcher->needsCollision(convexObj,planeObj))
|
||||||
|
{
|
||||||
|
m_manifoldPtr = m_dispatcher->getNewManifold(convexObj,planeObj);
|
||||||
|
m_ownManifold = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
btConvexPlaneCollisionAlgorithm::~btConvexPlaneCollisionAlgorithm()
|
||||||
|
{
|
||||||
|
if (m_ownManifold)
|
||||||
|
{
|
||||||
|
if (m_manifoldPtr)
|
||||||
|
m_dispatcher->releaseManifold(m_manifoldPtr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void btConvexPlaneCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
|
||||||
|
{
|
||||||
|
(void)dispatchInfo;
|
||||||
|
(void)resultOut;
|
||||||
|
if (!m_manifoldPtr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
btCollisionObject* convexObj = m_isSwapped? body1 : body0;
|
||||||
|
btCollisionObject* planeObj = m_isSwapped? body0: body1;
|
||||||
|
|
||||||
|
btConvexShape* convexShape = (btConvexShape*) convexObj->getCollisionShape();
|
||||||
|
btStaticPlaneShape* planeShape = (btStaticPlaneShape*) planeObj->getCollisionShape();
|
||||||
|
|
||||||
|
bool hasCollision = false;
|
||||||
|
const btVector3& planeNormal = planeShape->getPlaneNormal();
|
||||||
|
const btScalar& planeConstant = planeShape->getPlaneConstant();
|
||||||
|
btTransform planeInConvex;
|
||||||
|
planeInConvex= convexObj->getWorldTransform().inverse() * planeObj->getWorldTransform();
|
||||||
|
btTransform convexInPlaneTrans;
|
||||||
|
convexInPlaneTrans= planeObj->getWorldTransform().inverse() * convexObj->getWorldTransform();
|
||||||
|
|
||||||
|
btVector3 vtx = convexShape->localGetSupportingVertex(planeInConvex.getBasis()*-planeNormal);
|
||||||
|
btVector3 vtxInPlane = convexInPlaneTrans(vtx);
|
||||||
|
btScalar distance = (planeNormal.dot(vtxInPlane) - planeConstant);
|
||||||
|
|
||||||
|
btVector3 vtxInPlaneProjected = vtxInPlane - distance*planeNormal;
|
||||||
|
btVector3 vtxInPlaneWorld = planeObj->getWorldTransform() * vtxInPlaneProjected;
|
||||||
|
|
||||||
|
hasCollision = distance < m_manifoldPtr->getContactBreakingThreshold();
|
||||||
|
resultOut->setPersistentManifold(m_manifoldPtr);
|
||||||
|
if (hasCollision)
|
||||||
|
{
|
||||||
|
/// report a contact. internally this will be kept persistent, and contact reduction is done
|
||||||
|
btVector3 normalOnSurfaceB = planeObj->getWorldTransform().getBasis() * planeNormal;
|
||||||
|
btVector3 pOnB = vtxInPlaneWorld;
|
||||||
|
resultOut->addContactPoint(normalOnSurfaceB,pOnB,distance);
|
||||||
|
}
|
||||||
|
if (m_ownManifold)
|
||||||
|
{
|
||||||
|
if (m_manifoldPtr->getNumContacts())
|
||||||
|
{
|
||||||
|
resultOut->refreshContactPoints();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
btScalar btConvexPlaneCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
|
||||||
|
{
|
||||||
|
(void)resultOut;
|
||||||
|
(void)dispatchInfo;
|
||||||
|
(void)col0;
|
||||||
|
(void)col1;
|
||||||
|
|
||||||
|
//not yet
|
||||||
|
return btScalar(1.);
|
||||||
|
}
|
71
extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h
vendored
Normal file
71
extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h
vendored
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
/*
|
||||||
|
Bullet Continuous Collision Detection and Physics Library
|
||||||
|
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CONVEX_PLANE_COLLISION_ALGORITHM_H
|
||||||
|
#define CONVEX_PLANE_COLLISION_ALGORITHM_H
|
||||||
|
|
||||||
|
#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
|
||||||
|
#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
|
||||||
|
#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
|
||||||
|
class btPersistentManifold;
|
||||||
|
#include "btCollisionDispatcher.h"
|
||||||
|
|
||||||
|
#include "LinearMath/btVector3.h"
|
||||||
|
|
||||||
|
/// btSphereBoxCollisionAlgorithm provides sphere-box collision detection.
|
||||||
|
/// Other features are frame-coherency (persistent data) and collision response.
|
||||||
|
class btConvexPlaneCollisionAlgorithm : public btCollisionAlgorithm
|
||||||
|
{
|
||||||
|
bool m_ownManifold;
|
||||||
|
btPersistentManifold* m_manifoldPtr;
|
||||||
|
bool m_isSwapped;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
btConvexPlaneCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1, bool isSwapped);
|
||||||
|
|
||||||
|
virtual ~btConvexPlaneCollisionAlgorithm();
|
||||||
|
|
||||||
|
virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
|
||||||
|
|
||||||
|
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
|
||||||
|
|
||||||
|
virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
|
||||||
|
{
|
||||||
|
if (m_manifoldPtr && m_ownManifold)
|
||||||
|
{
|
||||||
|
manifoldArray.push_back(m_manifoldPtr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct CreateFunc :public btCollisionAlgorithmCreateFunc
|
||||||
|
{
|
||||||
|
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
|
||||||
|
{
|
||||||
|
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexPlaneCollisionAlgorithm));
|
||||||
|
if (!m_swapped)
|
||||||
|
{
|
||||||
|
return new(mem) btConvexPlaneCollisionAlgorithm(0,ci,body0,body1,false);
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
return new(mem) btConvexPlaneCollisionAlgorithm(0,ci,body0,body1,true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //CONVEX_PLANE_COLLISION_ALGORITHM_H
|
||||||
|
|
291
extern/bullet2/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp
vendored
Normal file
291
extern/bullet2/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp
vendored
Normal file
@ -0,0 +1,291 @@
|
|||||||
|
/*
|
||||||
|
Bullet Continuous Collision Detection and Physics Library
|
||||||
|
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "btDefaultCollisionConfiguration.h"
|
||||||
|
|
||||||
|
#include "BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h"
|
||||||
|
#include "BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h"
|
||||||
|
#include "BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h"
|
||||||
|
#include "BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h"
|
||||||
|
#include "BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h"
|
||||||
|
#include "BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h"
|
||||||
|
#include "BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h"
|
||||||
|
#ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM
|
||||||
|
#include "BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h"
|
||||||
|
#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM
|
||||||
|
#include "BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h"
|
||||||
|
#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h"
|
||||||
|
#include "BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h"
|
||||||
|
#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include "LinearMath/btStackAlloc.h"
|
||||||
|
#include "LinearMath/btPoolAllocator.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
btDefaultCollisionConfiguration::btDefaultCollisionConfiguration(const btDefaultCollisionConstructionInfo& constructionInfo)
|
||||||
|
//btDefaultCollisionConfiguration::btDefaultCollisionConfiguration(btStackAlloc* stackAlloc,btPoolAllocator* persistentManifoldPool,btPoolAllocator* collisionAlgorithmPool)
|
||||||
|
{
|
||||||
|
|
||||||
|
void* mem = btAlignedAlloc(sizeof(btVoronoiSimplexSolver),16);
|
||||||
|
m_simplexSolver = new (mem)btVoronoiSimplexSolver();
|
||||||
|
|
||||||
|
#define USE_EPA 1
|
||||||
|
#ifdef USE_EPA
|
||||||
|
mem = btAlignedAlloc(sizeof(btGjkEpaPenetrationDepthSolver),16);
|
||||||
|
m_pdSolver = new (mem)btGjkEpaPenetrationDepthSolver;
|
||||||
|
#else
|
||||||
|
mem = btAlignedAlloc(sizeof(btMinkowskiPenetrationDepthSolver),16);
|
||||||
|
m_pdSolver = new (mem)btMinkowskiPenetrationDepthSolver;
|
||||||
|
#endif//USE_EPA
|
||||||
|
|
||||||
|
|
||||||
|
//default CreationFunctions, filling the m_doubleDispatch table
|
||||||
|
mem = btAlignedAlloc(sizeof(btConvexConvexAlgorithm::CreateFunc),16);
|
||||||
|
m_convexConvexCreateFunc = new(mem) btConvexConvexAlgorithm::CreateFunc(m_simplexSolver,m_pdSolver);
|
||||||
|
mem = btAlignedAlloc(sizeof(btConvexConcaveCollisionAlgorithm::CreateFunc),16);
|
||||||
|
m_convexConcaveCreateFunc = new (mem)btConvexConcaveCollisionAlgorithm::CreateFunc;
|
||||||
|
mem = btAlignedAlloc(sizeof(btConvexConcaveCollisionAlgorithm::CreateFunc),16);
|
||||||
|
m_swappedConvexConcaveCreateFunc = new (mem)btConvexConcaveCollisionAlgorithm::SwappedCreateFunc;
|
||||||
|
mem = btAlignedAlloc(sizeof(btCompoundCollisionAlgorithm::CreateFunc),16);
|
||||||
|
m_compoundCreateFunc = new (mem)btCompoundCollisionAlgorithm::CreateFunc;
|
||||||
|
mem = btAlignedAlloc(sizeof(btCompoundCollisionAlgorithm::SwappedCreateFunc),16);
|
||||||
|
m_swappedCompoundCreateFunc = new (mem)btCompoundCollisionAlgorithm::SwappedCreateFunc;
|
||||||
|
mem = btAlignedAlloc(sizeof(btEmptyAlgorithm::CreateFunc),16);
|
||||||
|
m_emptyCreateFunc = new(mem) btEmptyAlgorithm::CreateFunc;
|
||||||
|
|
||||||
|
mem = btAlignedAlloc(sizeof(btSphereSphereCollisionAlgorithm::CreateFunc),16);
|
||||||
|
m_sphereSphereCF = new(mem) btSphereSphereCollisionAlgorithm::CreateFunc;
|
||||||
|
#ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM
|
||||||
|
mem = btAlignedAlloc(sizeof(btSphereBoxCollisionAlgorithm::CreateFunc),16);
|
||||||
|
m_sphereBoxCF = new(mem) btSphereBoxCollisionAlgorithm::CreateFunc;
|
||||||
|
mem = btAlignedAlloc(sizeof(btSphereBoxCollisionAlgorithm::CreateFunc),16);
|
||||||
|
m_boxSphereCF = new (mem)btSphereBoxCollisionAlgorithm::CreateFunc;
|
||||||
|
m_boxSphereCF->m_swapped = true;
|
||||||
|
#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM
|
||||||
|
|
||||||
|
mem = btAlignedAlloc(sizeof(btSphereTriangleCollisionAlgorithm::CreateFunc),16);
|
||||||
|
m_sphereTriangleCF = new (mem)btSphereTriangleCollisionAlgorithm::CreateFunc;
|
||||||
|
mem = btAlignedAlloc(sizeof(btSphereTriangleCollisionAlgorithm::CreateFunc),16);
|
||||||
|
m_triangleSphereCF = new (mem)btSphereTriangleCollisionAlgorithm::CreateFunc;
|
||||||
|
m_triangleSphereCF->m_swapped = true;
|
||||||
|
|
||||||
|
mem = btAlignedAlloc(sizeof(btBoxBoxCollisionAlgorithm::CreateFunc),16);
|
||||||
|
m_boxBoxCF = new(mem)btBoxBoxCollisionAlgorithm::CreateFunc;
|
||||||
|
|
||||||
|
//convex versus plane
|
||||||
|
mem = btAlignedAlloc (sizeof(btConvexPlaneCollisionAlgorithm::CreateFunc),16);
|
||||||
|
m_convexPlaneCF = new (mem) btConvexPlaneCollisionAlgorithm::CreateFunc;
|
||||||
|
mem = btAlignedAlloc (sizeof(btConvexPlaneCollisionAlgorithm::CreateFunc),16);
|
||||||
|
m_planeConvexCF = new (mem) btConvexPlaneCollisionAlgorithm::CreateFunc;
|
||||||
|
m_planeConvexCF->m_swapped = true;
|
||||||
|
|
||||||
|
///calculate maximum element size, big enough to fit any collision algorithm in the memory pool
|
||||||
|
int maxSize = sizeof(btConvexConvexAlgorithm);
|
||||||
|
int maxSize2 = sizeof(btConvexConcaveCollisionAlgorithm);
|
||||||
|
int maxSize3 = sizeof(btCompoundCollisionAlgorithm);
|
||||||
|
int maxSize4 = sizeof(btEmptyAlgorithm);
|
||||||
|
|
||||||
|
int collisionAlgorithmMaxElementSize = btMax(maxSize,maxSize2);
|
||||||
|
collisionAlgorithmMaxElementSize = btMax(collisionAlgorithmMaxElementSize,maxSize3);
|
||||||
|
collisionAlgorithmMaxElementSize = btMax(collisionAlgorithmMaxElementSize,maxSize4);
|
||||||
|
|
||||||
|
if (constructionInfo.m_stackAlloc)
|
||||||
|
{
|
||||||
|
m_ownsStackAllocator = false;
|
||||||
|
this->m_stackAlloc = constructionInfo.m_stackAlloc;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
m_ownsStackAllocator = true;
|
||||||
|
void* mem = btAlignedAlloc(sizeof(btStackAlloc),16);
|
||||||
|
m_stackAlloc = new(mem)btStackAlloc(constructionInfo.m_defaultStackAllocatorSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (constructionInfo.m_persistentManifoldPool)
|
||||||
|
{
|
||||||
|
m_ownsPersistentManifoldPool = false;
|
||||||
|
m_persistentManifoldPool = constructionInfo.m_persistentManifoldPool;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
m_ownsPersistentManifoldPool = true;
|
||||||
|
void* mem = btAlignedAlloc(sizeof(btPoolAllocator),16);
|
||||||
|
m_persistentManifoldPool = new (mem) btPoolAllocator(sizeof(btPersistentManifold),constructionInfo.m_defaultMaxPersistentManifoldPoolSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (constructionInfo.m_collisionAlgorithmPool)
|
||||||
|
{
|
||||||
|
m_ownsCollisionAlgorithmPool = false;
|
||||||
|
m_collisionAlgorithmPool = constructionInfo.m_collisionAlgorithmPool;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
m_ownsCollisionAlgorithmPool = true;
|
||||||
|
void* mem = btAlignedAlloc(sizeof(btPoolAllocator),16);
|
||||||
|
m_collisionAlgorithmPool = new(mem) btPoolAllocator(collisionAlgorithmMaxElementSize,constructionInfo.m_defaultMaxCollisionAlgorithmPoolSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
btDefaultCollisionConfiguration::~btDefaultCollisionConfiguration()
|
||||||
|
{
|
||||||
|
if (m_ownsStackAllocator)
|
||||||
|
{
|
||||||
|
m_stackAlloc->destroy();
|
||||||
|
m_stackAlloc->~btStackAlloc();
|
||||||
|
btAlignedFree(m_stackAlloc);
|
||||||
|
}
|
||||||
|
if (m_ownsCollisionAlgorithmPool)
|
||||||
|
{
|
||||||
|
m_collisionAlgorithmPool->~btPoolAllocator();
|
||||||
|
btAlignedFree(m_collisionAlgorithmPool);
|
||||||
|
}
|
||||||
|
if (m_ownsPersistentManifoldPool)
|
||||||
|
{
|
||||||
|
m_persistentManifoldPool->~btPoolAllocator();
|
||||||
|
btAlignedFree(m_persistentManifoldPool);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_convexConvexCreateFunc->~btCollisionAlgorithmCreateFunc();
|
||||||
|
btAlignedFree( m_convexConvexCreateFunc);
|
||||||
|
|
||||||
|
m_convexConcaveCreateFunc->~btCollisionAlgorithmCreateFunc();
|
||||||
|
btAlignedFree( m_convexConcaveCreateFunc);
|
||||||
|
m_swappedConvexConcaveCreateFunc->~btCollisionAlgorithmCreateFunc();
|
||||||
|
btAlignedFree( m_swappedConvexConcaveCreateFunc);
|
||||||
|
|
||||||
|
m_compoundCreateFunc->~btCollisionAlgorithmCreateFunc();
|
||||||
|
btAlignedFree( m_compoundCreateFunc);
|
||||||
|
|
||||||
|
m_swappedCompoundCreateFunc->~btCollisionAlgorithmCreateFunc();
|
||||||
|
btAlignedFree( m_swappedCompoundCreateFunc);
|
||||||
|
|
||||||
|
m_emptyCreateFunc->~btCollisionAlgorithmCreateFunc();
|
||||||
|
btAlignedFree( m_emptyCreateFunc);
|
||||||
|
|
||||||
|
m_sphereSphereCF->~btCollisionAlgorithmCreateFunc();
|
||||||
|
btAlignedFree( m_sphereSphereCF);
|
||||||
|
|
||||||
|
#ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM
|
||||||
|
m_sphereBoxCF->~btCollisionAlgorithmCreateFunc();
|
||||||
|
btAlignedFree( m_sphereBoxCF);
|
||||||
|
m_boxSphereCF->~btCollisionAlgorithmCreateFunc();
|
||||||
|
btAlignedFree( m_boxSphereCF);
|
||||||
|
#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM
|
||||||
|
|
||||||
|
m_sphereTriangleCF->~btCollisionAlgorithmCreateFunc();
|
||||||
|
btAlignedFree( m_sphereTriangleCF);
|
||||||
|
m_triangleSphereCF->~btCollisionAlgorithmCreateFunc();
|
||||||
|
btAlignedFree( m_triangleSphereCF);
|
||||||
|
m_boxBoxCF->~btCollisionAlgorithmCreateFunc();
|
||||||
|
btAlignedFree( m_boxBoxCF);
|
||||||
|
|
||||||
|
m_convexPlaneCF->~btCollisionAlgorithmCreateFunc();
|
||||||
|
btAlignedFree( m_convexPlaneCF);
|
||||||
|
m_planeConvexCF->~btCollisionAlgorithmCreateFunc();
|
||||||
|
btAlignedFree( m_planeConvexCF);
|
||||||
|
|
||||||
|
m_simplexSolver->~btVoronoiSimplexSolver();
|
||||||
|
btAlignedFree(m_simplexSolver);
|
||||||
|
|
||||||
|
m_pdSolver->~btConvexPenetrationDepthSolver();
|
||||||
|
|
||||||
|
btAlignedFree(m_pdSolver);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
btCollisionAlgorithmCreateFunc* btDefaultCollisionConfiguration::getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1)
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE) && (proxyType1==SPHERE_SHAPE_PROXYTYPE))
|
||||||
|
{
|
||||||
|
return m_sphereSphereCF;
|
||||||
|
}
|
||||||
|
#ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM
|
||||||
|
if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE) && (proxyType1==BOX_SHAPE_PROXYTYPE))
|
||||||
|
{
|
||||||
|
return m_sphereBoxCF;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((proxyType0 == BOX_SHAPE_PROXYTYPE ) && (proxyType1==SPHERE_SHAPE_PROXYTYPE))
|
||||||
|
{
|
||||||
|
return m_boxSphereCF;
|
||||||
|
}
|
||||||
|
#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM
|
||||||
|
|
||||||
|
|
||||||
|
if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE ) && (proxyType1==TRIANGLE_SHAPE_PROXYTYPE))
|
||||||
|
{
|
||||||
|
return m_sphereTriangleCF;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((proxyType0 == TRIANGLE_SHAPE_PROXYTYPE ) && (proxyType1==SPHERE_SHAPE_PROXYTYPE))
|
||||||
|
{
|
||||||
|
return m_triangleSphereCF;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((proxyType0 == BOX_SHAPE_PROXYTYPE) && (proxyType1 == BOX_SHAPE_PROXYTYPE))
|
||||||
|
{
|
||||||
|
return m_boxBoxCF;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (btBroadphaseProxy::isConvex(proxyType0) && (proxyType1 == STATIC_PLANE_PROXYTYPE))
|
||||||
|
{
|
||||||
|
return m_convexPlaneCF;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (btBroadphaseProxy::isConvex(proxyType1) && (proxyType0 == STATIC_PLANE_PROXYTYPE))
|
||||||
|
{
|
||||||
|
return m_planeConvexCF;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (btBroadphaseProxy::isConvex(proxyType0) && btBroadphaseProxy::isConvex(proxyType1))
|
||||||
|
{
|
||||||
|
return m_convexConvexCreateFunc;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (btBroadphaseProxy::isConvex(proxyType0) && btBroadphaseProxy::isConcave(proxyType1))
|
||||||
|
{
|
||||||
|
return m_convexConcaveCreateFunc;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (btBroadphaseProxy::isConvex(proxyType1) && btBroadphaseProxy::isConcave(proxyType0))
|
||||||
|
{
|
||||||
|
return m_swappedConvexConcaveCreateFunc;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (btBroadphaseProxy::isCompound(proxyType0))
|
||||||
|
{
|
||||||
|
return m_compoundCreateFunc;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
if (btBroadphaseProxy::isCompound(proxyType1))
|
||||||
|
{
|
||||||
|
return m_swappedCompoundCreateFunc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//failed to find an algorithm
|
||||||
|
return m_emptyCreateFunc;
|
||||||
|
}
|
118
extern/bullet2/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h
vendored
Normal file
118
extern/bullet2/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h
vendored
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
/*
|
||||||
|
Bullet Continuous Collision Detection and Physics Library
|
||||||
|
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef BT_DEFAULT_COLLISION_CONFIGURATION
|
||||||
|
#define BT_DEFAULT_COLLISION_CONFIGURATION
|
||||||
|
|
||||||
|
#include "btCollisionConfiguration.h"
|
||||||
|
class btVoronoiSimplexSolver;
|
||||||
|
class btConvexPenetrationDepthSolver;
|
||||||
|
|
||||||
|
struct btDefaultCollisionConstructionInfo
|
||||||
|
{
|
||||||
|
btStackAlloc* m_stackAlloc;
|
||||||
|
btPoolAllocator* m_persistentManifoldPool;
|
||||||
|
btPoolAllocator* m_collisionAlgorithmPool;
|
||||||
|
int m_defaultMaxPersistentManifoldPoolSize;
|
||||||
|
int m_defaultMaxCollisionAlgorithmPoolSize;
|
||||||
|
int m_defaultStackAllocatorSize;
|
||||||
|
|
||||||
|
btDefaultCollisionConstructionInfo()
|
||||||
|
:m_stackAlloc(0),
|
||||||
|
m_persistentManifoldPool(0),
|
||||||
|
m_collisionAlgorithmPool(0),
|
||||||
|
m_defaultMaxPersistentManifoldPoolSize(65535),
|
||||||
|
m_defaultMaxCollisionAlgorithmPoolSize(65535),
|
||||||
|
m_defaultStackAllocatorSize(5*1024*1024)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
///btCollisionConfiguration allows to configure Bullet collision detection
|
||||||
|
///stack allocator, pool memory allocators
|
||||||
|
///todo: describe the meaning
|
||||||
|
class btDefaultCollisionConfiguration : public btCollisionConfiguration
|
||||||
|
{
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
int m_persistentManifoldPoolSize;
|
||||||
|
|
||||||
|
btStackAlloc* m_stackAlloc;
|
||||||
|
bool m_ownsStackAllocator;
|
||||||
|
|
||||||
|
btPoolAllocator* m_persistentManifoldPool;
|
||||||
|
bool m_ownsPersistentManifoldPool;
|
||||||
|
|
||||||
|
|
||||||
|
btPoolAllocator* m_collisionAlgorithmPool;
|
||||||
|
bool m_ownsCollisionAlgorithmPool;
|
||||||
|
|
||||||
|
//default simplex/penetration depth solvers
|
||||||
|
btVoronoiSimplexSolver* m_simplexSolver;
|
||||||
|
btConvexPenetrationDepthSolver* m_pdSolver;
|
||||||
|
|
||||||
|
//default CreationFunctions, filling the m_doubleDispatch table
|
||||||
|
btCollisionAlgorithmCreateFunc* m_convexConvexCreateFunc;
|
||||||
|
btCollisionAlgorithmCreateFunc* m_convexConcaveCreateFunc;
|
||||||
|
btCollisionAlgorithmCreateFunc* m_swappedConvexConcaveCreateFunc;
|
||||||
|
btCollisionAlgorithmCreateFunc* m_compoundCreateFunc;
|
||||||
|
btCollisionAlgorithmCreateFunc* m_swappedCompoundCreateFunc;
|
||||||
|
btCollisionAlgorithmCreateFunc* m_emptyCreateFunc;
|
||||||
|
btCollisionAlgorithmCreateFunc* m_sphereSphereCF;
|
||||||
|
#ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM
|
||||||
|
btCollisionAlgorithmCreateFunc* m_sphereBoxCF;
|
||||||
|
btCollisionAlgorithmCreateFunc* m_boxSphereCF;
|
||||||
|
#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM
|
||||||
|
|
||||||
|
btCollisionAlgorithmCreateFunc* m_boxBoxCF;
|
||||||
|
btCollisionAlgorithmCreateFunc* m_sphereTriangleCF;
|
||||||
|
btCollisionAlgorithmCreateFunc* m_triangleSphereCF;
|
||||||
|
btCollisionAlgorithmCreateFunc* m_planeConvexCF;
|
||||||
|
btCollisionAlgorithmCreateFunc* m_convexPlaneCF;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
|
||||||
|
btDefaultCollisionConfiguration(const btDefaultCollisionConstructionInfo& constructionInfo = btDefaultCollisionConstructionInfo());
|
||||||
|
|
||||||
|
virtual ~btDefaultCollisionConfiguration();
|
||||||
|
|
||||||
|
///memory pools
|
||||||
|
virtual btPoolAllocator* getPersistentManifoldPool()
|
||||||
|
{
|
||||||
|
return m_persistentManifoldPool;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual btPoolAllocator* getCollisionAlgorithmPool()
|
||||||
|
{
|
||||||
|
return m_collisionAlgorithmPool;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual btStackAlloc* getStackAllocator()
|
||||||
|
{
|
||||||
|
return m_stackAlloc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual btCollisionAlgorithmCreateFunc* getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1);
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //BT_DEFAULT_COLLISION_CONFIGURATION
|
||||||
|
|
78
extern/bullet2/src/BulletCollision/CollisionShapes/btConvexInternalShape.cpp
vendored
Normal file
78
extern/bullet2/src/BulletCollision/CollisionShapes/btConvexInternalShape.cpp
vendored
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
/*
|
||||||
|
Bullet Continuous Collision Detection and Physics Library
|
||||||
|
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "btConvexInternalShape.h"
|
||||||
|
|
||||||
|
|
||||||
|
btConvexInternalShape::btConvexInternalShape()
|
||||||
|
: m_localScaling(btScalar(1.),btScalar(1.),btScalar(1.)),
|
||||||
|
m_collisionMargin(CONVEX_DISTANCE_MARGIN)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void btConvexInternalShape::setLocalScaling(const btVector3& scaling)
|
||||||
|
{
|
||||||
|
m_localScaling = scaling.absolute();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void btConvexInternalShape::getAabbSlow(const btTransform& trans,btVector3&minAabb,btVector3&maxAabb) const
|
||||||
|
{
|
||||||
|
|
||||||
|
btScalar margin = getMargin();
|
||||||
|
for (int i=0;i<3;i++)
|
||||||
|
{
|
||||||
|
btVector3 vec(btScalar(0.),btScalar(0.),btScalar(0.));
|
||||||
|
vec[i] = btScalar(1.);
|
||||||
|
|
||||||
|
btVector3 sv = localGetSupportingVertex(vec*trans.getBasis());
|
||||||
|
|
||||||
|
btVector3 tmp = trans(sv);
|
||||||
|
maxAabb[i] = tmp[i]+margin;
|
||||||
|
vec[i] = btScalar(-1.);
|
||||||
|
tmp = trans(localGetSupportingVertex(vec*trans.getBasis()));
|
||||||
|
minAabb[i] = tmp[i]-margin;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
btVector3 btConvexInternalShape::localGetSupportingVertex(const btVector3& vec)const
|
||||||
|
{
|
||||||
|
#ifndef __SPU__
|
||||||
|
|
||||||
|
btVector3 supVertex = localGetSupportingVertexWithoutMargin(vec);
|
||||||
|
|
||||||
|
if ( getMargin()!=btScalar(0.) )
|
||||||
|
{
|
||||||
|
btVector3 vecnorm = vec;
|
||||||
|
if (vecnorm .length2() < (SIMD_EPSILON*SIMD_EPSILON))
|
||||||
|
{
|
||||||
|
vecnorm.setValue(btScalar(-1.),btScalar(-1.),btScalar(-1.));
|
||||||
|
}
|
||||||
|
vecnorm.normalize();
|
||||||
|
supVertex+= getMargin() * vecnorm;
|
||||||
|
}
|
||||||
|
return supVertex;
|
||||||
|
|
||||||
|
#else
|
||||||
|
return btVector3(0,0,0);
|
||||||
|
#endif //__SPU__
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
98
extern/bullet2/src/BulletCollision/CollisionShapes/btConvexInternalShape.h
vendored
Normal file
98
extern/bullet2/src/BulletCollision/CollisionShapes/btConvexInternalShape.h
vendored
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
|
||||||
|
#ifndef BT_CONVEX_INTERNAL_SHAPE_H
|
||||||
|
#define BT_CONVEX_INTERNAL_SHAPE_H
|
||||||
|
|
||||||
|
#include "btConvexShape.h"
|
||||||
|
|
||||||
|
///The btConvexInternalShape is an internal base class, shared by most convex shape implementations.
|
||||||
|
class btConvexInternalShape : public btConvexShape
|
||||||
|
{
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
//local scaling. collisionMargin is not scaled !
|
||||||
|
btVector3 m_localScaling;
|
||||||
|
|
||||||
|
btVector3 m_implicitShapeDimensions;
|
||||||
|
|
||||||
|
btScalar m_collisionMargin;
|
||||||
|
|
||||||
|
btScalar m_padding;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
btConvexInternalShape();
|
||||||
|
|
||||||
|
virtual ~btConvexInternalShape()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual btVector3 localGetSupportingVertex(const btVector3& vec)const;
|
||||||
|
#ifndef __SPU__
|
||||||
|
virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec) const= 0;
|
||||||
|
|
||||||
|
//notice that the vectors should be unit length
|
||||||
|
virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const= 0;
|
||||||
|
#endif //#ifndef __SPU__
|
||||||
|
|
||||||
|
const btVector3& getImplicitShapeDimensions() const
|
||||||
|
{
|
||||||
|
return m_implicitShapeDimensions;
|
||||||
|
}
|
||||||
|
|
||||||
|
///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version
|
||||||
|
void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
|
||||||
|
{
|
||||||
|
getAabbSlow(t,aabbMin,aabbMax);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
virtual void getAabbSlow(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
|
||||||
|
|
||||||
|
|
||||||
|
virtual void setLocalScaling(const btVector3& scaling);
|
||||||
|
virtual const btVector3& getLocalScaling() const
|
||||||
|
{
|
||||||
|
return m_localScaling;
|
||||||
|
}
|
||||||
|
|
||||||
|
const btVector3& getLocalScalingNV() const
|
||||||
|
{
|
||||||
|
return m_localScaling;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void setMargin(btScalar margin)
|
||||||
|
{
|
||||||
|
m_collisionMargin = margin;
|
||||||
|
}
|
||||||
|
virtual btScalar getMargin() const
|
||||||
|
{
|
||||||
|
return m_collisionMargin;
|
||||||
|
}
|
||||||
|
|
||||||
|
btScalar getMarginNV() const
|
||||||
|
{
|
||||||
|
return m_collisionMargin;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual int getNumPreferredPenetrationDirections() const
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const
|
||||||
|
{
|
||||||
|
(void)penetrationVector;
|
||||||
|
(void)index;
|
||||||
|
btAssert(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif //BT_CONVEX_INTERNAL_SHAPE_H
|
34
extern/bullet2/src/BulletCollision/CollisionShapes/btMaterial.h
vendored
Normal file
34
extern/bullet2/src/BulletCollision/CollisionShapes/btMaterial.h
vendored
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
Bullet Continuous Collision Detection and Physics Library
|
||||||
|
Copyright (c) 2003-2008 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/// This file was created by Alex Silverman
|
||||||
|
|
||||||
|
#ifndef MATERIAL_H
|
||||||
|
#define MATERIAL_H
|
||||||
|
|
||||||
|
// Material class to be used by btMultimaterialTriangleMeshShape to store triangle properties
|
||||||
|
class btMaterial
|
||||||
|
{
|
||||||
|
// public members so that materials can change due to world events
|
||||||
|
public:
|
||||||
|
btScalar m_friction;
|
||||||
|
btScalar m_restitution;
|
||||||
|
int pad[2];
|
||||||
|
|
||||||
|
btMaterial(){}
|
||||||
|
btMaterial(btScalar fric, btScalar rest) { m_friction = fric; m_restitution = rest; }
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // MATERIAL_H
|
45
extern/bullet2/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.cpp
vendored
Normal file
45
extern/bullet2/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.cpp
vendored
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
Bullet Continuous Collision Detection and Physics Library
|
||||||
|
Copyright (c) 2003-2008 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/// This file was created by Alex Silverman
|
||||||
|
|
||||||
|
#include "BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h"
|
||||||
|
#include "BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.h"
|
||||||
|
//#include "BulletCollision/CollisionShapes/btOptimizedBvh.h"
|
||||||
|
|
||||||
|
|
||||||
|
///Obtains the material for a specific triangle
|
||||||
|
const btMaterial * btMultimaterialTriangleMeshShape::getMaterialProperties(int partID, int triIndex)
|
||||||
|
{
|
||||||
|
const unsigned char * materialBase = 0;
|
||||||
|
int numMaterials;
|
||||||
|
PHY_ScalarType materialType;
|
||||||
|
int materialStride;
|
||||||
|
const unsigned char * triangleMaterialBase = 0;
|
||||||
|
int numTriangles;
|
||||||
|
int triangleMaterialStride;
|
||||||
|
PHY_ScalarType triangleType;
|
||||||
|
|
||||||
|
((btTriangleIndexVertexMaterialArray*)m_meshInterface)->getLockedReadOnlyMaterialBase(&materialBase, numMaterials, materialType, materialStride,
|
||||||
|
&triangleMaterialBase, numTriangles, triangleMaterialStride, triangleType, partID);
|
||||||
|
|
||||||
|
// return the pointer to the place with the friction for the triangle
|
||||||
|
// TODO: This depends on whether it's a moving mesh or not
|
||||||
|
// BUG IN GIMPACT
|
||||||
|
//return (btScalar*)(&materialBase[triangleMaterialBase[(triIndex-1) * triangleMaterialStride] * materialStride]);
|
||||||
|
int * matInd = (int *)(&(triangleMaterialBase[(triIndex * triangleMaterialStride)]));
|
||||||
|
btMaterial *matVal = (btMaterial *)(&(materialBase[*matInd * materialStride]));
|
||||||
|
return (matVal);
|
||||||
|
}
|
124
extern/bullet2/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h
vendored
Normal file
124
extern/bullet2/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h
vendored
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
/*
|
||||||
|
Bullet Continuous Collision Detection and Physics Library
|
||||||
|
Copyright (c) 2003-2008 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/// This file was created by Alex Silverman
|
||||||
|
|
||||||
|
#ifndef BVH_TRIANGLE_MATERIAL_MESH_SHAPE_H
|
||||||
|
#define BVH_TRIANGLE_MATERIAL_MESH_SHAPE_H
|
||||||
|
|
||||||
|
#include "btBvhTriangleMeshShape.h"
|
||||||
|
#include "btMaterial.h"
|
||||||
|
|
||||||
|
///The BvhTriangleMaterialMeshShape extends the btBvhTriangleMeshShape. Its main contribution is the interface into a material array, which allows per-triangle friction and restitution.
|
||||||
|
ATTRIBUTE_ALIGNED16(class) btMultimaterialTriangleMeshShape : public btBvhTriangleMeshShape
|
||||||
|
{
|
||||||
|
btAlignedObjectArray <btMaterial*> m_materialList;
|
||||||
|
int ** m_triangleMaterials;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
BT_DECLARE_ALIGNED_ALLOCATOR();
|
||||||
|
|
||||||
|
btMultimaterialTriangleMeshShape(): btBvhTriangleMeshShape() {}
|
||||||
|
btMultimaterialTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression, bool buildBvh = true):
|
||||||
|
btBvhTriangleMeshShape(meshInterface, useQuantizedAabbCompression, buildBvh)
|
||||||
|
{
|
||||||
|
btVector3 m_triangle[3];
|
||||||
|
const unsigned char *vertexbase;
|
||||||
|
int numverts;
|
||||||
|
PHY_ScalarType type;
|
||||||
|
int stride;
|
||||||
|
const unsigned char *indexbase;
|
||||||
|
int indexstride;
|
||||||
|
int numfaces;
|
||||||
|
PHY_ScalarType indicestype;
|
||||||
|
|
||||||
|
//m_materialLookup = (int**)(btAlignedAlloc(sizeof(int*) * meshInterface->getNumSubParts(), 16));
|
||||||
|
|
||||||
|
for(int i = 0; i < meshInterface->getNumSubParts(); i++)
|
||||||
|
{
|
||||||
|
m_meshInterface->getLockedReadOnlyVertexIndexBase(
|
||||||
|
&vertexbase,
|
||||||
|
numverts,
|
||||||
|
type,
|
||||||
|
stride,
|
||||||
|
&indexbase,
|
||||||
|
indexstride,
|
||||||
|
numfaces,
|
||||||
|
indicestype,
|
||||||
|
i);
|
||||||
|
//m_materialLookup[i] = (int*)(btAlignedAlloc(sizeof(int) * numfaces, 16));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///optionally pass in a larger bvh aabb, used for quantization. This allows for deformations within this aabb
|
||||||
|
btMultimaterialTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression,const btVector3& bvhAabbMin,const btVector3& bvhAabbMax, bool buildBvh = true):
|
||||||
|
btBvhTriangleMeshShape(meshInterface, useQuantizedAabbCompression, bvhAabbMin, bvhAabbMax, buildBvh)
|
||||||
|
{
|
||||||
|
btVector3 m_triangle[3];
|
||||||
|
const unsigned char *vertexbase;
|
||||||
|
int numverts;
|
||||||
|
PHY_ScalarType type;
|
||||||
|
int stride;
|
||||||
|
const unsigned char *indexbase;
|
||||||
|
int indexstride;
|
||||||
|
int numfaces;
|
||||||
|
PHY_ScalarType indicestype;
|
||||||
|
|
||||||
|
//m_materialLookup = (int**)(btAlignedAlloc(sizeof(int*) * meshInterface->getNumSubParts(), 16));
|
||||||
|
|
||||||
|
for(int i = 0; i < meshInterface->getNumSubParts(); i++)
|
||||||
|
{
|
||||||
|
m_meshInterface->getLockedReadOnlyVertexIndexBase(
|
||||||
|
&vertexbase,
|
||||||
|
numverts,
|
||||||
|
type,
|
||||||
|
stride,
|
||||||
|
&indexbase,
|
||||||
|
indexstride,
|
||||||
|
numfaces,
|
||||||
|
indicestype,
|
||||||
|
i);
|
||||||
|
//m_materialLookup[i] = (int*)(btAlignedAlloc(sizeof(int) * numfaces * 2, 16));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~btMultimaterialTriangleMeshShape()
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
for(int i = 0; i < m_meshInterface->getNumSubParts(); i++)
|
||||||
|
{
|
||||||
|
btAlignedFree(m_materialValues[i]);
|
||||||
|
m_materialLookup[i] = NULL;
|
||||||
|
}
|
||||||
|
btAlignedFree(m_materialValues);
|
||||||
|
m_materialLookup = NULL;
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
virtual int getShapeType() const
|
||||||
|
{
|
||||||
|
return MULTIMATERIAL_TRIANGLE_MESH_PROXYTYPE;
|
||||||
|
}
|
||||||
|
|
||||||
|
//debugging
|
||||||
|
virtual const char* getName()const {return "MULTIMATERIALTRIANGLEMESH";}
|
||||||
|
|
||||||
|
///Obtains the material for a specific triangle
|
||||||
|
const btMaterial * getMaterialProperties(int partID, int triIndex);
|
||||||
|
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
#endif //BVH_TRIANGLE_MATERIAL_MESH_SHAPE_H
|
121
extern/bullet2/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.cpp
vendored
Normal file
121
extern/bullet2/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.cpp
vendored
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
/*
|
||||||
|
Bullet Continuous Collision Detection and Physics Library
|
||||||
|
Copyright (c) 2003-2008 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "btScaledBvhTriangleMeshShape.h"
|
||||||
|
|
||||||
|
btScaledBvhTriangleMeshShape::btScaledBvhTriangleMeshShape(btBvhTriangleMeshShape* childShape,btVector3 localScaling)
|
||||||
|
:m_bvhTriMeshShape(childShape),
|
||||||
|
m_localScaling(localScaling)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
btScaledBvhTriangleMeshShape::~btScaledBvhTriangleMeshShape()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class btScaledTriangleCallback : public btTriangleCallback
|
||||||
|
{
|
||||||
|
btTriangleCallback* m_originalCallback;
|
||||||
|
|
||||||
|
btVector3 m_localScaling;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
btScaledTriangleCallback(btTriangleCallback* originalCallback,btVector3 localScaling)
|
||||||
|
:m_originalCallback(originalCallback),
|
||||||
|
m_localScaling(localScaling)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex)
|
||||||
|
{
|
||||||
|
btVector3 newTriangle[3];
|
||||||
|
newTriangle[0] = triangle[0]*m_localScaling;
|
||||||
|
newTriangle[1] = triangle[1]*m_localScaling;
|
||||||
|
newTriangle[2] = triangle[2]*m_localScaling;
|
||||||
|
m_originalCallback->processTriangle(&newTriangle[0],partId,triangleIndex);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void btScaledBvhTriangleMeshShape::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const
|
||||||
|
{
|
||||||
|
btScaledTriangleCallback scaledCallback(callback,m_localScaling);
|
||||||
|
|
||||||
|
btVector3 invLocalScaling(1.f/m_localScaling.getX(),1.f/m_localScaling.getY(),1.f/m_localScaling.getZ());
|
||||||
|
btVector3 scaledAabbMin,scaledAabbMax;
|
||||||
|
|
||||||
|
///support negative scaling
|
||||||
|
scaledAabbMin[0] = m_localScaling.getX() >= 0. ? aabbMin[0] * invLocalScaling[0] : aabbMax[0] * invLocalScaling[0];
|
||||||
|
scaledAabbMin[1] = m_localScaling.getY() >= 0. ? aabbMin[1] * invLocalScaling[1] : aabbMax[1] * invLocalScaling[1];
|
||||||
|
scaledAabbMin[2] = m_localScaling.getZ() >= 0. ? aabbMin[2] * invLocalScaling[2] : aabbMax[2] * invLocalScaling[2];
|
||||||
|
|
||||||
|
scaledAabbMax[0] = m_localScaling.getX() <= 0. ? aabbMin[0] * invLocalScaling[0] : aabbMax[0] * invLocalScaling[0];
|
||||||
|
scaledAabbMax[1] = m_localScaling.getY() <= 0. ? aabbMin[1] * invLocalScaling[1] : aabbMax[1] * invLocalScaling[1];
|
||||||
|
scaledAabbMax[2] = m_localScaling.getZ() <= 0. ? aabbMin[2] * invLocalScaling[2] : aabbMax[2] * invLocalScaling[2];
|
||||||
|
|
||||||
|
|
||||||
|
m_bvhTriMeshShape->processAllTriangles(&scaledCallback,scaledAabbMin,scaledAabbMax);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void btScaledBvhTriangleMeshShape::getAabb(const btTransform& trans,btVector3& aabbMin,btVector3& aabbMax) const
|
||||||
|
{
|
||||||
|
btVector3 localAabbMin = m_bvhTriMeshShape->getLocalAabbMin();
|
||||||
|
btVector3 localAabbMax = m_bvhTriMeshShape->getLocalAabbMax();
|
||||||
|
|
||||||
|
btVector3 tmpLocalAabbMin = localAabbMin * m_localScaling;
|
||||||
|
btVector3 tmpLocalAabbMax = localAabbMax * m_localScaling;
|
||||||
|
|
||||||
|
localAabbMin[0] = (m_localScaling.getX() >= 0.) ? tmpLocalAabbMin[0] : tmpLocalAabbMax[0];
|
||||||
|
localAabbMin[1] = (m_localScaling.getY() >= 0.) ? tmpLocalAabbMin[1] : tmpLocalAabbMax[1];
|
||||||
|
localAabbMin[2] = (m_localScaling.getZ() >= 0.) ? tmpLocalAabbMin[2] : tmpLocalAabbMax[2];
|
||||||
|
localAabbMax[0] = (m_localScaling.getX() <= 0.) ? tmpLocalAabbMin[0] : tmpLocalAabbMax[0];
|
||||||
|
localAabbMax[1] = (m_localScaling.getY() <= 0.) ? tmpLocalAabbMin[1] : tmpLocalAabbMax[1];
|
||||||
|
localAabbMax[2] = (m_localScaling.getZ() <= 0.) ? tmpLocalAabbMin[2] : tmpLocalAabbMax[2];
|
||||||
|
|
||||||
|
btVector3 localHalfExtents = btScalar(0.5)*(localAabbMax-localAabbMin);
|
||||||
|
btScalar margin = m_bvhTriMeshShape->getMargin();
|
||||||
|
localHalfExtents += btVector3(margin,margin,margin);
|
||||||
|
btVector3 localCenter = btScalar(0.5)*(localAabbMax+localAabbMin);
|
||||||
|
|
||||||
|
btMatrix3x3 abs_b = trans.getBasis().absolute();
|
||||||
|
|
||||||
|
btPoint3 center = trans(localCenter);
|
||||||
|
|
||||||
|
btVector3 extent = btVector3(abs_b[0].dot(localHalfExtents),
|
||||||
|
abs_b[1].dot(localHalfExtents),
|
||||||
|
abs_b[2].dot(localHalfExtents));
|
||||||
|
aabbMin = center - extent;
|
||||||
|
aabbMax = center + extent;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void btScaledBvhTriangleMeshShape::setLocalScaling(const btVector3& scaling)
|
||||||
|
{
|
||||||
|
m_localScaling = scaling;
|
||||||
|
}
|
||||||
|
|
||||||
|
const btVector3& btScaledBvhTriangleMeshShape::getLocalScaling() const
|
||||||
|
{
|
||||||
|
return m_localScaling;
|
||||||
|
}
|
||||||
|
|
||||||
|
void btScaledBvhTriangleMeshShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
|
||||||
|
{
|
||||||
|
///don't make this a movable object!
|
||||||
|
// btAssert(0);
|
||||||
|
}
|
67
extern/bullet2/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h
vendored
Normal file
67
extern/bullet2/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h
vendored
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
/*
|
||||||
|
Bullet Continuous Collision Detection and Physics Library
|
||||||
|
Copyright (c) 2003-2008 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SCALED_BVH_TRIANGLE_MESH_SHAPE_H
|
||||||
|
#define SCALED_BVH_TRIANGLE_MESH_SHAPE_H
|
||||||
|
|
||||||
|
#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h"
|
||||||
|
|
||||||
|
|
||||||
|
///The btScaledBvhTriangleMeshShape allows to instance a scaled version of an existing btBvhTriangleMeshShape.
|
||||||
|
///Note that each btBvhTriangleMeshShape still can have its own local scaling, independent from this btScaledBvhTriangleMeshShape 'localScaling'
|
||||||
|
ATTRIBUTE_ALIGNED16(class) btScaledBvhTriangleMeshShape : public btConcaveShape
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
btVector3 m_localScaling;
|
||||||
|
|
||||||
|
btBvhTriangleMeshShape* m_bvhTriMeshShape;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
|
||||||
|
btScaledBvhTriangleMeshShape(btBvhTriangleMeshShape* childShape,btVector3 localScaling);
|
||||||
|
|
||||||
|
virtual ~btScaledBvhTriangleMeshShape();
|
||||||
|
|
||||||
|
virtual int getShapeType() const
|
||||||
|
{
|
||||||
|
//use un-used 'FAST_CONCAVE_MESH_PROXYTYPE' for now, later add SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE to btBroadphaseProxy.h
|
||||||
|
return SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
|
||||||
|
virtual void setLocalScaling(const btVector3& scaling);
|
||||||
|
virtual const btVector3& getLocalScaling() const;
|
||||||
|
virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
|
||||||
|
|
||||||
|
virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const;
|
||||||
|
|
||||||
|
btBvhTriangleMeshShape* getChildShape()
|
||||||
|
{
|
||||||
|
return m_bvhTriMeshShape;
|
||||||
|
}
|
||||||
|
|
||||||
|
const btBvhTriangleMeshShape* getChildShape() const
|
||||||
|
{
|
||||||
|
return m_bvhTriMeshShape;
|
||||||
|
}
|
||||||
|
|
||||||
|
//debugging
|
||||||
|
virtual const char* getName()const {return "SCALEDBVHTRIANGLEMESH";}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //BVH_TRIANGLE_MESH_SHAPE_H
|
164
extern/bullet2/src/BulletCollision/CollisionShapes/btShapeHull.cpp
vendored
Normal file
164
extern/bullet2/src/BulletCollision/CollisionShapes/btShapeHull.cpp
vendored
Normal file
@ -0,0 +1,164 @@
|
|||||||
|
/*
|
||||||
|
btbtShapeHull implemented by John McCutchan.
|
||||||
|
|
||||||
|
Bullet Continuous Collision Detection and Physics Library
|
||||||
|
Copyright (c) 2003-2008 Erwin Coumans http://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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "btShapeHull.h"
|
||||||
|
#include "LinearMath/btConvexHull.h"
|
||||||
|
|
||||||
|
#define NUM_UNITSPHERE_POINTS 42
|
||||||
|
|
||||||
|
static btVector3 btUnitSpherePoints[NUM_UNITSPHERE_POINTS+MAX_PREFERRED_PENETRATION_DIRECTIONS*2] =
|
||||||
|
{
|
||||||
|
btVector3(btScalar(0.000000) , btScalar(-0.000000),btScalar(-1.000000)),
|
||||||
|
btVector3(btScalar(0.723608) , btScalar(-0.525725),btScalar(-0.447219)),
|
||||||
|
btVector3(btScalar(-0.276388) , btScalar(-0.850649),btScalar(-0.447219)),
|
||||||
|
btVector3(btScalar(-0.894426) , btScalar(-0.000000),btScalar(-0.447216)),
|
||||||
|
btVector3(btScalar(-0.276388) , btScalar(0.850649),btScalar(-0.447220)),
|
||||||
|
btVector3(btScalar(0.723608) , btScalar(0.525725),btScalar(-0.447219)),
|
||||||
|
btVector3(btScalar(0.276388) , btScalar(-0.850649),btScalar(0.447220)),
|
||||||
|
btVector3(btScalar(-0.723608) , btScalar(-0.525725),btScalar(0.447219)),
|
||||||
|
btVector3(btScalar(-0.723608) , btScalar(0.525725),btScalar(0.447219)),
|
||||||
|
btVector3(btScalar(0.276388) , btScalar(0.850649),btScalar(0.447219)),
|
||||||
|
btVector3(btScalar(0.894426) , btScalar(0.000000),btScalar(0.447216)),
|
||||||
|
btVector3(btScalar(-0.000000) , btScalar(0.000000),btScalar(1.000000)),
|
||||||
|
btVector3(btScalar(0.425323) , btScalar(-0.309011),btScalar(-0.850654)),
|
||||||
|
btVector3(btScalar(-0.162456) , btScalar(-0.499995),btScalar(-0.850654)),
|
||||||
|
btVector3(btScalar(0.262869) , btScalar(-0.809012),btScalar(-0.525738)),
|
||||||
|
btVector3(btScalar(0.425323) , btScalar(0.309011),btScalar(-0.850654)),
|
||||||
|
btVector3(btScalar(0.850648) , btScalar(-0.000000),btScalar(-0.525736)),
|
||||||
|
btVector3(btScalar(-0.525730) , btScalar(-0.000000),btScalar(-0.850652)),
|
||||||
|
btVector3(btScalar(-0.688190) , btScalar(-0.499997),btScalar(-0.525736)),
|
||||||
|
btVector3(btScalar(-0.162456) , btScalar(0.499995),btScalar(-0.850654)),
|
||||||
|
btVector3(btScalar(-0.688190) , btScalar(0.499997),btScalar(-0.525736)),
|
||||||
|
btVector3(btScalar(0.262869) , btScalar(0.809012),btScalar(-0.525738)),
|
||||||
|
btVector3(btScalar(0.951058) , btScalar(0.309013),btScalar(0.000000)),
|
||||||
|
btVector3(btScalar(0.951058) , btScalar(-0.309013),btScalar(0.000000)),
|
||||||
|
btVector3(btScalar(0.587786) , btScalar(-0.809017),btScalar(0.000000)),
|
||||||
|
btVector3(btScalar(0.000000) , btScalar(-1.000000),btScalar(0.000000)),
|
||||||
|
btVector3(btScalar(-0.587786) , btScalar(-0.809017),btScalar(0.000000)),
|
||||||
|
btVector3(btScalar(-0.951058) , btScalar(-0.309013),btScalar(-0.000000)),
|
||||||
|
btVector3(btScalar(-0.951058) , btScalar(0.309013),btScalar(-0.000000)),
|
||||||
|
btVector3(btScalar(-0.587786) , btScalar(0.809017),btScalar(-0.000000)),
|
||||||
|
btVector3(btScalar(-0.000000) , btScalar(1.000000),btScalar(-0.000000)),
|
||||||
|
btVector3(btScalar(0.587786) , btScalar(0.809017),btScalar(-0.000000)),
|
||||||
|
btVector3(btScalar(0.688190) , btScalar(-0.499997),btScalar(0.525736)),
|
||||||
|
btVector3(btScalar(-0.262869) , btScalar(-0.809012),btScalar(0.525738)),
|
||||||
|
btVector3(btScalar(-0.850648) , btScalar(0.000000),btScalar(0.525736)),
|
||||||
|
btVector3(btScalar(-0.262869) , btScalar(0.809012),btScalar(0.525738)),
|
||||||
|
btVector3(btScalar(0.688190) , btScalar(0.499997),btScalar(0.525736)),
|
||||||
|
btVector3(btScalar(0.525730) , btScalar(0.000000),btScalar(0.850652)),
|
||||||
|
btVector3(btScalar(0.162456) , btScalar(-0.499995),btScalar(0.850654)),
|
||||||
|
btVector3(btScalar(-0.425323) , btScalar(-0.309011),btScalar(0.850654)),
|
||||||
|
btVector3(btScalar(-0.425323) , btScalar(0.309011),btScalar(0.850654)),
|
||||||
|
btVector3(btScalar(0.162456) , btScalar(0.499995),btScalar(0.850654))
|
||||||
|
};
|
||||||
|
|
||||||
|
btShapeHull::btShapeHull (const btConvexShape* shape)
|
||||||
|
{
|
||||||
|
m_shape = shape;
|
||||||
|
m_vertices.clear ();
|
||||||
|
m_indices.clear();
|
||||||
|
m_numIndices = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
btShapeHull::~btShapeHull ()
|
||||||
|
{
|
||||||
|
m_indices.clear();
|
||||||
|
m_vertices.clear ();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
btShapeHull::buildHull (btScalar /*margin*/)
|
||||||
|
{
|
||||||
|
int numSampleDirections = NUM_UNITSPHERE_POINTS;
|
||||||
|
{
|
||||||
|
int numPDA = m_shape->getNumPreferredPenetrationDirections();
|
||||||
|
if (numPDA)
|
||||||
|
{
|
||||||
|
for (int i=0;i<numPDA;i++)
|
||||||
|
{
|
||||||
|
btVector3 norm;
|
||||||
|
m_shape->getPreferredPenetrationDirection(i,norm);
|
||||||
|
btUnitSpherePoints[numSampleDirections] = norm;
|
||||||
|
numSampleDirections++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
btVector3 supportPoints[NUM_UNITSPHERE_POINTS+MAX_PREFERRED_PENETRATION_DIRECTIONS*2];
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < numSampleDirections; i++)
|
||||||
|
{
|
||||||
|
supportPoints[i] = m_shape->localGetSupportingVertex(btUnitSpherePoints[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
HullDesc hd;
|
||||||
|
hd.mFlags = QF_TRIANGLES;
|
||||||
|
hd.mVcount = static_cast<unsigned int>(numSampleDirections);
|
||||||
|
|
||||||
|
#ifdef BT_USE_DOUBLE_PRECISION
|
||||||
|
hd.mVertices = &supportPoints[0];
|
||||||
|
hd.mVertexStride = sizeof(btVector3);
|
||||||
|
#else
|
||||||
|
hd.mVertices = &supportPoints[0];
|
||||||
|
hd.mVertexStride = sizeof (btVector3);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
HullLibrary hl;
|
||||||
|
HullResult hr;
|
||||||
|
if (hl.CreateConvexHull (hd, hr) == QE_FAIL)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_vertices.resize (static_cast<int>(hr.mNumOutputVertices));
|
||||||
|
|
||||||
|
|
||||||
|
for (i = 0; i < static_cast<int>(hr.mNumOutputVertices); i++)
|
||||||
|
{
|
||||||
|
m_vertices[i] = hr.m_OutputVertices[i];
|
||||||
|
}
|
||||||
|
m_numIndices = hr.mNumIndices;
|
||||||
|
m_indices.resize(static_cast<int>(m_numIndices));
|
||||||
|
for (i = 0; i < static_cast<int>(m_numIndices); i++)
|
||||||
|
{
|
||||||
|
m_indices[i] = hr.m_Indices[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
// free temporary hull result that we just copied
|
||||||
|
hl.ReleaseResult (hr);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
btShapeHull::numTriangles () const
|
||||||
|
{
|
||||||
|
return static_cast<int>(m_numIndices / 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
btShapeHull::numVertices () const
|
||||||
|
{
|
||||||
|
return m_vertices.size ();
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
btShapeHull::numIndices () const
|
||||||
|
{
|
||||||
|
return static_cast<int>(m_numIndices);
|
||||||
|
}
|
||||||
|
|
56
extern/bullet2/src/BulletCollision/CollisionShapes/btShapeHull.h
vendored
Normal file
56
extern/bullet2/src/BulletCollision/CollisionShapes/btShapeHull.h
vendored
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
btShapeHull implemented by John McCutchan.
|
||||||
|
|
||||||
|
Bullet Continuous Collision Detection and Physics Library
|
||||||
|
Copyright (c) 2003-2008 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _SHAPE_HULL_H
|
||||||
|
#define _SHAPE_HULL_H
|
||||||
|
|
||||||
|
#include "LinearMath/btAlignedObjectArray.h"
|
||||||
|
#include "BulletCollision/CollisionShapes/btConvexShape.h"
|
||||||
|
|
||||||
|
|
||||||
|
///The btShapeHull class takes a btConvexShape, builds a simplified convex hull using btConvexHull and provides triangle indices and vertices.
|
||||||
|
///It can be useful for to simplify a complex convex object and for visualization of a non-polyhedral convex object.
|
||||||
|
///It approximates the convex hull using the supporting vertex of 42 directions.
|
||||||
|
class btShapeHull
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
btShapeHull (const btConvexShape* shape);
|
||||||
|
~btShapeHull ();
|
||||||
|
|
||||||
|
bool buildHull (btScalar margin);
|
||||||
|
|
||||||
|
int numTriangles () const;
|
||||||
|
int numVertices () const;
|
||||||
|
int numIndices () const;
|
||||||
|
|
||||||
|
const btVector3* getVertexPointer() const
|
||||||
|
{
|
||||||
|
return &m_vertices[0];
|
||||||
|
}
|
||||||
|
const unsigned int* getIndexPointer() const
|
||||||
|
{
|
||||||
|
return &m_indices[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
btAlignedObjectArray<btVector3> m_vertices;
|
||||||
|
btAlignedObjectArray<unsigned int> m_indices;
|
||||||
|
unsigned int m_numIndices;
|
||||||
|
const btConvexShape* m_shape;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //_SHAPE_HULL_H
|
86
extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.cpp
vendored
Normal file
86
extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.cpp
vendored
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
/*
|
||||||
|
Bullet Continuous Collision Detection and Physics Library
|
||||||
|
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
///This file was created by Alex Silverman
|
||||||
|
|
||||||
|
#include "btTriangleIndexVertexMaterialArray.h"
|
||||||
|
|
||||||
|
btTriangleIndexVertexMaterialArray::btTriangleIndexVertexMaterialArray(int numTriangles,int* triangleIndexBase,int triangleIndexStride,
|
||||||
|
int numVertices,btScalar* vertexBase,int vertexStride,
|
||||||
|
int numMaterials, unsigned char* materialBase, int materialStride,
|
||||||
|
int* triangleMaterialsBase, int materialIndexStride) :
|
||||||
|
btTriangleIndexVertexArray(numTriangles, triangleIndexBase, triangleIndexStride, numVertices, vertexBase, vertexStride)
|
||||||
|
{
|
||||||
|
btMaterialProperties mat;
|
||||||
|
|
||||||
|
mat.m_numMaterials = numMaterials;
|
||||||
|
mat.m_materialBase = materialBase;
|
||||||
|
mat.m_materialStride = materialStride;
|
||||||
|
#ifdef BT_USE_DOUBLE_PRECISION
|
||||||
|
mat.m_materialType = PHY_DOUBLE;
|
||||||
|
#else
|
||||||
|
mat.m_materialType = PHY_FLOAT;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
mat.m_numTriangles = numTriangles;
|
||||||
|
mat.m_triangleMaterialsBase = (unsigned char *)triangleMaterialsBase;
|
||||||
|
mat.m_triangleMaterialStride = materialIndexStride;
|
||||||
|
mat.m_triangleType = PHY_INTEGER;
|
||||||
|
|
||||||
|
addMaterialProperties(mat);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void btTriangleIndexVertexMaterialArray::getLockedMaterialBase(unsigned char **materialBase, int& numMaterials, PHY_ScalarType& materialType, int& materialStride,
|
||||||
|
unsigned char ** triangleMaterialBase, int& numTriangles, int& triangleMaterialStride, PHY_ScalarType& triangleType, int subpart)
|
||||||
|
{
|
||||||
|
btAssert(subpart< getNumSubParts() );
|
||||||
|
|
||||||
|
btMaterialProperties& mats = m_materials[subpart];
|
||||||
|
|
||||||
|
numMaterials = mats.m_numMaterials;
|
||||||
|
(*materialBase) = (unsigned char *) mats.m_materialBase;
|
||||||
|
#ifdef BT_USE_DOUBLE_PRECISION
|
||||||
|
materialType = PHY_DOUBLE;
|
||||||
|
#else
|
||||||
|
materialType = PHY_FLOAT;
|
||||||
|
#endif
|
||||||
|
materialStride = mats.m_materialStride;
|
||||||
|
|
||||||
|
numTriangles = mats.m_numTriangles;
|
||||||
|
(*triangleMaterialBase) = (unsigned char *)mats.m_triangleMaterialsBase;
|
||||||
|
triangleMaterialStride = mats.m_triangleMaterialStride;
|
||||||
|
triangleType = mats.m_triangleType;
|
||||||
|
}
|
||||||
|
|
||||||
|
void btTriangleIndexVertexMaterialArray::getLockedReadOnlyMaterialBase(const unsigned char **materialBase, int& numMaterials, PHY_ScalarType& materialType, int& materialStride,
|
||||||
|
const unsigned char ** triangleMaterialBase, int& numTriangles, int& triangleMaterialStride, PHY_ScalarType& triangleType, int subpart)
|
||||||
|
{
|
||||||
|
btMaterialProperties& mats = m_materials[subpart];
|
||||||
|
|
||||||
|
numMaterials = mats.m_numMaterials;
|
||||||
|
(*materialBase) = (const unsigned char *) mats.m_materialBase;
|
||||||
|
#ifdef BT_USE_DOUBLE_PRECISION
|
||||||
|
materialType = PHY_DOUBLE;
|
||||||
|
#else
|
||||||
|
materialType = PHY_FLOAT;
|
||||||
|
#endif
|
||||||
|
materialStride = mats.m_materialStride;
|
||||||
|
|
||||||
|
numTriangles = mats.m_numTriangles;
|
||||||
|
(*triangleMaterialBase) = (const unsigned char *)mats.m_triangleMaterialsBase;
|
||||||
|
triangleMaterialStride = mats.m_triangleMaterialStride;
|
||||||
|
triangleType = mats.m_triangleType;
|
||||||
|
}
|
84
extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.h
vendored
Normal file
84
extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.h
vendored
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
/*
|
||||||
|
Bullet Continuous Collision Detection and Physics Library
|
||||||
|
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
///This file was created by Alex Silverman
|
||||||
|
|
||||||
|
#ifndef BT_MULTIMATERIAL_TRIANGLE_INDEX_VERTEX_ARRAY_H
|
||||||
|
#define BT_MULTIMATERIAL_TRIANGLE_INDEX_VERTEX_ARRAY_H
|
||||||
|
|
||||||
|
#include "btTriangleIndexVertexArray.h"
|
||||||
|
|
||||||
|
|
||||||
|
ATTRIBUTE_ALIGNED16( struct) btMaterialProperties
|
||||||
|
{
|
||||||
|
///m_materialBase ==========> 2 btScalar values make up one material, friction then restitution
|
||||||
|
int m_numMaterials;
|
||||||
|
const unsigned char * m_materialBase;
|
||||||
|
int m_materialStride;
|
||||||
|
PHY_ScalarType m_materialType;
|
||||||
|
///m_numTriangles <=========== This exists in the btIndexedMesh object for the same subpart, but since we're
|
||||||
|
/// padding the structure, it can be reproduced at no real cost
|
||||||
|
///m_triangleMaterials =====> 1 integer value makes up one entry
|
||||||
|
/// eg: m_triangleMaterials[1] = 5; // This will set triangle 2 to use material 5
|
||||||
|
int m_numTriangles;
|
||||||
|
const unsigned char * m_triangleMaterialsBase;
|
||||||
|
int m_triangleMaterialStride;
|
||||||
|
///m_triangleType <========== Automatically set in addMaterialProperties
|
||||||
|
PHY_ScalarType m_triangleType;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef btAlignedObjectArray<btMaterialProperties> MaterialArray;
|
||||||
|
|
||||||
|
///Teh btTriangleIndexVertexMaterialArray is built on TriangleIndexVertexArray
|
||||||
|
///The addition of a material array allows for the utilization of the partID and
|
||||||
|
///triangleIndex that are returned in the ContactAddedCallback. As with
|
||||||
|
///TriangleIndexVertexArray, no duplicate is made of the material data, so it
|
||||||
|
///is the users responsibility to maintain the array during the lifetime of the
|
||||||
|
///TriangleIndexVertexMaterialArray.
|
||||||
|
ATTRIBUTE_ALIGNED16(class) btTriangleIndexVertexMaterialArray : public btTriangleIndexVertexArray
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
MaterialArray m_materials;
|
||||||
|
|
||||||
|
public:
|
||||||
|
BT_DECLARE_ALIGNED_ALLOCATOR();
|
||||||
|
|
||||||
|
btTriangleIndexVertexMaterialArray()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
btTriangleIndexVertexMaterialArray(int numTriangles,int* triangleIndexBase,int triangleIndexStride,
|
||||||
|
int numVertices,btScalar* vertexBase,int vertexStride,
|
||||||
|
int numMaterials, unsigned char* materialBase, int materialStride,
|
||||||
|
int* triangleMaterialsBase, int materialIndexStride);
|
||||||
|
|
||||||
|
virtual ~btTriangleIndexVertexMaterialArray() {}
|
||||||
|
|
||||||
|
void addMaterialProperties(const btMaterialProperties& mat, PHY_ScalarType triangleType = PHY_INTEGER)
|
||||||
|
{
|
||||||
|
m_materials.push_back(mat);
|
||||||
|
m_materials[m_materials.size()-1].m_triangleType = triangleType;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void getLockedMaterialBase(unsigned char **materialBase, int& numMaterials, PHY_ScalarType& materialType, int& materialStride,
|
||||||
|
unsigned char ** triangleMaterialBase, int& numTriangles, int& triangleMaterialStride, PHY_ScalarType& triangleType ,int subpart = 0);
|
||||||
|
|
||||||
|
virtual void getLockedReadOnlyMaterialBase(const unsigned char **materialBase, int& numMaterials, PHY_ScalarType& materialType, int& materialStride,
|
||||||
|
const unsigned char ** triangleMaterialBase, int& numTriangles, int& triangleMaterialStride, PHY_ScalarType& triangleType, int subpart = 0);
|
||||||
|
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
#endif //BT_MULTIMATERIAL_TRIANGLE_INDEX_VERTEX_ARRAY_H
|
114
extern/bullet2/src/BulletCollision/CollisionShapes/btUniformScalingShape.cpp
vendored
Normal file
114
extern/bullet2/src/BulletCollision/CollisionShapes/btUniformScalingShape.cpp
vendored
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
/*
|
||||||
|
Bullet Continuous Collision Detection and Physics Library
|
||||||
|
Copyright (c) 2003-2007 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "btUniformScalingShape.h"
|
||||||
|
|
||||||
|
btUniformScalingShape::btUniformScalingShape( btConvexShape* convexChildShape,btScalar uniformScalingFactor):
|
||||||
|
m_childConvexShape(convexChildShape),
|
||||||
|
m_uniformScalingFactor(uniformScalingFactor)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
btUniformScalingShape::~btUniformScalingShape()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
btVector3 btUniformScalingShape::localGetSupportingVertexWithoutMargin(const btVector3& vec)const
|
||||||
|
{
|
||||||
|
btVector3 tmpVertex;
|
||||||
|
tmpVertex = m_childConvexShape->localGetSupportingVertexWithoutMargin(vec);
|
||||||
|
return tmpVertex*m_uniformScalingFactor;
|
||||||
|
}
|
||||||
|
|
||||||
|
void btUniformScalingShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
|
||||||
|
{
|
||||||
|
m_childConvexShape->batchedUnitVectorGetSupportingVertexWithoutMargin(vectors,supportVerticesOut,numVectors);
|
||||||
|
int i;
|
||||||
|
for (i=0;i<numVectors;i++)
|
||||||
|
{
|
||||||
|
supportVerticesOut[i] = supportVerticesOut[i] * m_uniformScalingFactor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
btVector3 btUniformScalingShape::localGetSupportingVertex(const btVector3& vec)const
|
||||||
|
{
|
||||||
|
btVector3 tmpVertex;
|
||||||
|
tmpVertex = m_childConvexShape->localGetSupportingVertex(vec);
|
||||||
|
return tmpVertex*m_uniformScalingFactor;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void btUniformScalingShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
|
||||||
|
{
|
||||||
|
|
||||||
|
///this linear upscaling is not realistic, but we don't deal with large mass ratios...
|
||||||
|
btVector3 tmpInertia;
|
||||||
|
m_childConvexShape->calculateLocalInertia(mass,tmpInertia);
|
||||||
|
inertia = tmpInertia * m_uniformScalingFactor;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version
|
||||||
|
void btUniformScalingShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
|
||||||
|
{
|
||||||
|
m_childConvexShape->getAabb(t,aabbMin,aabbMax);
|
||||||
|
btVector3 aabbCenter = (aabbMax+aabbMin)*btScalar(0.5);
|
||||||
|
btVector3 scaledAabbHalfExtends = (aabbMax-aabbMin)*btScalar(0.5)*m_uniformScalingFactor;
|
||||||
|
|
||||||
|
aabbMin = aabbCenter - scaledAabbHalfExtends;
|
||||||
|
aabbMax = aabbCenter + scaledAabbHalfExtends;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void btUniformScalingShape::getAabbSlow(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
|
||||||
|
{
|
||||||
|
m_childConvexShape->getAabbSlow(t,aabbMin,aabbMax);
|
||||||
|
btVector3 aabbCenter = (aabbMax+aabbMin)*btScalar(0.5);
|
||||||
|
btVector3 scaledAabbHalfExtends = (aabbMax-aabbMin)*btScalar(0.5)*m_uniformScalingFactor;
|
||||||
|
|
||||||
|
aabbMin = aabbCenter - scaledAabbHalfExtends;
|
||||||
|
aabbMax = aabbCenter + scaledAabbHalfExtends;
|
||||||
|
}
|
||||||
|
|
||||||
|
void btUniformScalingShape::setLocalScaling(const btVector3& scaling)
|
||||||
|
{
|
||||||
|
m_childConvexShape->setLocalScaling(scaling);
|
||||||
|
}
|
||||||
|
|
||||||
|
const btVector3& btUniformScalingShape::getLocalScaling() const
|
||||||
|
{
|
||||||
|
return m_childConvexShape->getLocalScaling();
|
||||||
|
}
|
||||||
|
|
||||||
|
void btUniformScalingShape::setMargin(btScalar margin)
|
||||||
|
{
|
||||||
|
m_childConvexShape->setMargin(margin);
|
||||||
|
}
|
||||||
|
btScalar btUniformScalingShape::getMargin() const
|
||||||
|
{
|
||||||
|
return m_childConvexShape->getMargin() * m_uniformScalingFactor;
|
||||||
|
}
|
||||||
|
|
||||||
|
int btUniformScalingShape::getNumPreferredPenetrationDirections() const
|
||||||
|
{
|
||||||
|
return m_childConvexShape->getNumPreferredPenetrationDirections();
|
||||||
|
}
|
||||||
|
|
||||||
|
void btUniformScalingShape::getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const
|
||||||
|
{
|
||||||
|
m_childConvexShape->getPreferredPenetrationDirection(index,penetrationVector);
|
||||||
|
}
|
88
extern/bullet2/src/BulletCollision/CollisionShapes/btUniformScalingShape.h
vendored
Normal file
88
extern/bullet2/src/BulletCollision/CollisionShapes/btUniformScalingShape.h
vendored
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
/*
|
||||||
|
Bullet Continuous Collision Detection and Physics Library
|
||||||
|
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef BT_UNIFORM_SCALING_SHAPE_H
|
||||||
|
#define BT_UNIFORM_SCALING_SHAPE_H
|
||||||
|
|
||||||
|
#include "btConvexShape.h"
|
||||||
|
#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
|
||||||
|
|
||||||
|
///The btUniformScalingShape allows to re-use uniform scaled instances of btConvexShape in a memory efficient way.
|
||||||
|
///Istead of using btUniformScalingShape, it is better to use the non-uniform setLocalScaling method on convex shapes that implement it.
|
||||||
|
class btUniformScalingShape : public btConvexShape
|
||||||
|
{
|
||||||
|
btConvexShape* m_childConvexShape;
|
||||||
|
|
||||||
|
btScalar m_uniformScalingFactor;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
btUniformScalingShape( btConvexShape* convexChildShape, btScalar uniformScalingFactor);
|
||||||
|
|
||||||
|
virtual ~btUniformScalingShape();
|
||||||
|
|
||||||
|
virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const;
|
||||||
|
|
||||||
|
virtual btVector3 localGetSupportingVertex(const btVector3& vec)const;
|
||||||
|
|
||||||
|
virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const;
|
||||||
|
|
||||||
|
virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
|
||||||
|
|
||||||
|
btScalar getUniformScalingFactor() const
|
||||||
|
{
|
||||||
|
return m_uniformScalingFactor;
|
||||||
|
}
|
||||||
|
|
||||||
|
btConvexShape* getChildShape()
|
||||||
|
{
|
||||||
|
return m_childConvexShape;
|
||||||
|
}
|
||||||
|
|
||||||
|
const btConvexShape* getChildShape() const
|
||||||
|
{
|
||||||
|
return m_childConvexShape;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual const char* getName()const
|
||||||
|
{
|
||||||
|
return "UniformScalingShape";
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual int getShapeType() const { return UNIFORM_SCALING_SHAPE_PROXYTYPE; }
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version
|
||||||
|
void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
|
||||||
|
|
||||||
|
virtual void getAabbSlow(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
|
||||||
|
|
||||||
|
virtual void setLocalScaling(const btVector3& scaling) ;
|
||||||
|
virtual const btVector3& getLocalScaling() const ;
|
||||||
|
|
||||||
|
virtual void setMargin(btScalar margin);
|
||||||
|
virtual btScalar getMargin() const;
|
||||||
|
|
||||||
|
virtual int getNumPreferredPenetrationDirections() const;
|
||||||
|
|
||||||
|
virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const;
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //BT_UNIFORM_SCALING_SHAPE_H
|
943
extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.cpp
vendored
Normal file
943
extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.cpp
vendored
Normal file
@ -0,0 +1,943 @@
|
|||||||
|
/*
|
||||||
|
Bullet Continuous Collision Detection and Physics Library
|
||||||
|
Copyright (c) 2003-2008 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
GJK-EPA collision solver by Nathanael Presson, 2008
|
||||||
|
*/
|
||||||
|
#include "BulletCollision/CollisionShapes/btConvexInternalShape.h"
|
||||||
|
#include "BulletCollision/CollisionShapes/btSphereShape.h"
|
||||||
|
#include "btGjkEpa2.h"
|
||||||
|
|
||||||
|
#if defined(DEBUG) || defined (_DEBUG)
|
||||||
|
#include <stdio.h> //for debug printf
|
||||||
|
#ifdef __SPU__
|
||||||
|
#include <spu_printf.h>
|
||||||
|
#define printf spu_printf
|
||||||
|
#endif //__SPU__
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace gjkepa2_impl
|
||||||
|
{
|
||||||
|
|
||||||
|
// Config
|
||||||
|
|
||||||
|
/* GJK */
|
||||||
|
#define GJK_MAX_ITERATIONS 128
|
||||||
|
#define GJK_ACCURARY ((btScalar)0.0001)
|
||||||
|
#define GJK_MIN_DISTANCE ((btScalar)0.0001)
|
||||||
|
#define GJK_DUPLICATED_EPS ((btScalar)0.0001)
|
||||||
|
#define GJK_SIMPLEX2_EPS ((btScalar)0.0)
|
||||||
|
#define GJK_SIMPLEX3_EPS ((btScalar)0.0)
|
||||||
|
#define GJK_SIMPLEX4_EPS ((btScalar)0.0)
|
||||||
|
|
||||||
|
/* EPA */
|
||||||
|
#define EPA_MAX_VERTICES 64
|
||||||
|
#define EPA_MAX_FACES (EPA_MAX_VERTICES*2)
|
||||||
|
#define EPA_MAX_ITERATIONS 255
|
||||||
|
#define EPA_ACCURACY ((btScalar)0.0001)
|
||||||
|
#define EPA_FALLBACK (10*EPA_ACCURACY)
|
||||||
|
#define EPA_PLANE_EPS ((btScalar)0.00001)
|
||||||
|
#define EPA_INSIDE_EPS ((btScalar)0.01)
|
||||||
|
|
||||||
|
|
||||||
|
// Shorthands
|
||||||
|
typedef unsigned int U;
|
||||||
|
typedef unsigned char U1;
|
||||||
|
|
||||||
|
// MinkowskiDiff
|
||||||
|
struct MinkowskiDiff
|
||||||
|
{
|
||||||
|
const btConvexShape* m_shapes[2];
|
||||||
|
btMatrix3x3 m_toshape1;
|
||||||
|
btTransform m_toshape0;
|
||||||
|
btVector3 (btConvexShape::*Ls)(const btVector3&) const;
|
||||||
|
void EnableMargin(bool enable)
|
||||||
|
{
|
||||||
|
if(enable)
|
||||||
|
Ls=&btConvexShape::localGetSupportingVertex;
|
||||||
|
else
|
||||||
|
Ls=&btConvexShape::localGetSupportingVertexWithoutMargin;
|
||||||
|
}
|
||||||
|
inline btVector3 Support0(const btVector3& d) const
|
||||||
|
{
|
||||||
|
return(((m_shapes[0])->*(Ls))(d));
|
||||||
|
}
|
||||||
|
inline btVector3 Support1(const btVector3& d) const
|
||||||
|
{
|
||||||
|
return(m_toshape0*((m_shapes[1])->*(Ls))(m_toshape1*d));
|
||||||
|
}
|
||||||
|
inline btVector3 Support(const btVector3& d) const
|
||||||
|
{
|
||||||
|
return(Support0(d)-Support1(-d));
|
||||||
|
}
|
||||||
|
btVector3 Support(const btVector3& d,U index) const
|
||||||
|
{
|
||||||
|
if(index)
|
||||||
|
return(Support1(d));
|
||||||
|
else
|
||||||
|
return(Support0(d));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef MinkowskiDiff tShape;
|
||||||
|
|
||||||
|
|
||||||
|
// GJK
|
||||||
|
struct GJK
|
||||||
|
{
|
||||||
|
/* Types */
|
||||||
|
struct sSV
|
||||||
|
{
|
||||||
|
btVector3 d,w;
|
||||||
|
};
|
||||||
|
struct sSimplex
|
||||||
|
{
|
||||||
|
sSV* c[4];
|
||||||
|
btScalar p[4];
|
||||||
|
U rank;
|
||||||
|
};
|
||||||
|
struct eStatus { enum _ {
|
||||||
|
Valid,
|
||||||
|
Inside,
|
||||||
|
Failed };};
|
||||||
|
/* Fields */
|
||||||
|
tShape m_shape;
|
||||||
|
btVector3 m_ray;
|
||||||
|
btScalar m_distance;
|
||||||
|
sSimplex m_simplices[2];
|
||||||
|
sSV m_store[4];
|
||||||
|
sSV* m_free[4];
|
||||||
|
U m_nfree;
|
||||||
|
U m_current;
|
||||||
|
sSimplex* m_simplex;
|
||||||
|
eStatus::_ m_status;
|
||||||
|
/* Methods */
|
||||||
|
GJK()
|
||||||
|
{
|
||||||
|
Initialize();
|
||||||
|
}
|
||||||
|
void Initialize()
|
||||||
|
{
|
||||||
|
m_ray = btVector3(0,0,0);
|
||||||
|
m_nfree = 0;
|
||||||
|
m_status = eStatus::Failed;
|
||||||
|
m_current = 0;
|
||||||
|
m_distance = 0;
|
||||||
|
}
|
||||||
|
eStatus::_ Evaluate(const tShape& shapearg,const btVector3& guess)
|
||||||
|
{
|
||||||
|
U iterations=0;
|
||||||
|
btScalar sqdist=0;
|
||||||
|
btScalar alpha=0;
|
||||||
|
btVector3 lastw[4];
|
||||||
|
U clastw=0;
|
||||||
|
/* Initialize solver */
|
||||||
|
m_free[0] = &m_store[0];
|
||||||
|
m_free[1] = &m_store[1];
|
||||||
|
m_free[2] = &m_store[2];
|
||||||
|
m_free[3] = &m_store[3];
|
||||||
|
m_nfree = 4;
|
||||||
|
m_current = 0;
|
||||||
|
m_status = eStatus::Valid;
|
||||||
|
m_shape = shapearg;
|
||||||
|
m_distance = 0;
|
||||||
|
/* Initialize simplex */
|
||||||
|
m_simplices[0].rank = 0;
|
||||||
|
m_ray = guess;
|
||||||
|
const btScalar sqrl= m_ray.length2();
|
||||||
|
appendvertice(m_simplices[0],sqrl>0?-m_ray:btVector3(1,0,0));
|
||||||
|
m_simplices[0].p[0] = 1;
|
||||||
|
m_ray = m_simplices[0].c[0]->w;
|
||||||
|
sqdist = sqrl;
|
||||||
|
lastw[0] =
|
||||||
|
lastw[1] =
|
||||||
|
lastw[2] =
|
||||||
|
lastw[3] = m_ray;
|
||||||
|
/* Loop */
|
||||||
|
do {
|
||||||
|
const U next=1-m_current;
|
||||||
|
sSimplex& cs=m_simplices[m_current];
|
||||||
|
sSimplex& ns=m_simplices[next];
|
||||||
|
/* Check zero */
|
||||||
|
const btScalar rl=m_ray.length();
|
||||||
|
if(rl<GJK_MIN_DISTANCE)
|
||||||
|
{/* Touching or inside */
|
||||||
|
m_status=eStatus::Inside;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* Append new vertice in -'v' direction */
|
||||||
|
appendvertice(cs,-m_ray);
|
||||||
|
const btVector3& w=cs.c[cs.rank-1]->w;
|
||||||
|
bool found=false;
|
||||||
|
for(U i=0;i<4;++i)
|
||||||
|
{
|
||||||
|
if((w-lastw[i]).length2()<GJK_DUPLICATED_EPS)
|
||||||
|
{ found=true;break; }
|
||||||
|
}
|
||||||
|
if(found)
|
||||||
|
{/* Return old simplex */
|
||||||
|
removevertice(m_simplices[m_current]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{/* Update lastw */
|
||||||
|
lastw[clastw=(clastw+1)&3]=w;
|
||||||
|
}
|
||||||
|
/* Check for termination */
|
||||||
|
const btScalar omega=dot(m_ray,w)/rl;
|
||||||
|
alpha=btMax(omega,alpha);
|
||||||
|
if(((rl-alpha)-(GJK_ACCURARY*rl))<=0)
|
||||||
|
{/* Return old simplex */
|
||||||
|
removevertice(m_simplices[m_current]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* Reduce simplex */
|
||||||
|
btScalar weights[4];
|
||||||
|
U mask=0;
|
||||||
|
switch(cs.rank)
|
||||||
|
{
|
||||||
|
case 2: sqdist=projectorigin( cs.c[0]->w,
|
||||||
|
cs.c[1]->w,
|
||||||
|
weights,mask);break;
|
||||||
|
case 3: sqdist=projectorigin( cs.c[0]->w,
|
||||||
|
cs.c[1]->w,
|
||||||
|
cs.c[2]->w,
|
||||||
|
weights,mask);break;
|
||||||
|
case 4: sqdist=projectorigin( cs.c[0]->w,
|
||||||
|
cs.c[1]->w,
|
||||||
|
cs.c[2]->w,
|
||||||
|
cs.c[3]->w,
|
||||||
|
weights,mask);break;
|
||||||
|
}
|
||||||
|
if(sqdist>=0)
|
||||||
|
{/* Valid */
|
||||||
|
ns.rank = 0;
|
||||||
|
m_ray = btVector3(0,0,0);
|
||||||
|
m_current = next;
|
||||||
|
for(U i=0,ni=cs.rank;i<ni;++i)
|
||||||
|
{
|
||||||
|
if(mask&(1<<i))
|
||||||
|
{
|
||||||
|
ns.c[ns.rank] = cs.c[i];
|
||||||
|
ns.p[ns.rank++] = weights[i];
|
||||||
|
m_ray += cs.c[i]->w*weights[i];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_free[m_nfree++] = cs.c[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(mask==15) m_status=eStatus::Inside;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{/* Return old simplex */
|
||||||
|
removevertice(m_simplices[m_current]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
m_status=((++iterations)<GJK_MAX_ITERATIONS)?m_status:eStatus::Failed;
|
||||||
|
} while(m_status==eStatus::Valid);
|
||||||
|
m_simplex=&m_simplices[m_current];
|
||||||
|
switch(m_status)
|
||||||
|
{
|
||||||
|
case eStatus::Valid: m_distance=m_ray.length();break;
|
||||||
|
case eStatus::Inside: m_distance=0;break;
|
||||||
|
}
|
||||||
|
return(m_status);
|
||||||
|
}
|
||||||
|
bool EncloseOrigin()
|
||||||
|
{
|
||||||
|
switch(m_simplex->rank)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
{
|
||||||
|
for(U i=0;i<3;++i)
|
||||||
|
{
|
||||||
|
btVector3 axis=btVector3(0,0,0);
|
||||||
|
axis[i]=1;
|
||||||
|
appendvertice(*m_simplex, axis);
|
||||||
|
if(EncloseOrigin()) return(true);
|
||||||
|
removevertice(*m_simplex);
|
||||||
|
appendvertice(*m_simplex,-axis);
|
||||||
|
if(EncloseOrigin()) return(true);
|
||||||
|
removevertice(*m_simplex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
{
|
||||||
|
const btVector3 d=m_simplex->c[1]->w-m_simplex->c[0]->w;
|
||||||
|
for(U i=0;i<3;++i)
|
||||||
|
{
|
||||||
|
btVector3 axis=btVector3(0,0,0);
|
||||||
|
axis[i]=1;
|
||||||
|
const btVector3 p=cross(d,axis);
|
||||||
|
if(p.length2()>0)
|
||||||
|
{
|
||||||
|
appendvertice(*m_simplex, p);
|
||||||
|
if(EncloseOrigin()) return(true);
|
||||||
|
removevertice(*m_simplex);
|
||||||
|
appendvertice(*m_simplex,-p);
|
||||||
|
if(EncloseOrigin()) return(true);
|
||||||
|
removevertice(*m_simplex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
{
|
||||||
|
const btVector3 n=cross(m_simplex->c[1]->w-m_simplex->c[0]->w,
|
||||||
|
m_simplex->c[2]->w-m_simplex->c[0]->w);
|
||||||
|
if(n.length2()>0)
|
||||||
|
{
|
||||||
|
appendvertice(*m_simplex,n);
|
||||||
|
if(EncloseOrigin()) return(true);
|
||||||
|
removevertice(*m_simplex);
|
||||||
|
appendvertice(*m_simplex,-n);
|
||||||
|
if(EncloseOrigin()) return(true);
|
||||||
|
removevertice(*m_simplex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
{
|
||||||
|
if(btFabs(det( m_simplex->c[0]->w-m_simplex->c[3]->w,
|
||||||
|
m_simplex->c[1]->w-m_simplex->c[3]->w,
|
||||||
|
m_simplex->c[2]->w-m_simplex->c[3]->w))>0)
|
||||||
|
return(true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return(false);
|
||||||
|
}
|
||||||
|
/* Internals */
|
||||||
|
void getsupport(const btVector3& d,sSV& sv) const
|
||||||
|
{
|
||||||
|
sv.d = d/d.length();
|
||||||
|
sv.w = m_shape.Support(sv.d);
|
||||||
|
}
|
||||||
|
void removevertice(sSimplex& simplex)
|
||||||
|
{
|
||||||
|
m_free[m_nfree++]=simplex.c[--simplex.rank];
|
||||||
|
}
|
||||||
|
void appendvertice(sSimplex& simplex,const btVector3& v)
|
||||||
|
{
|
||||||
|
simplex.p[simplex.rank]=0;
|
||||||
|
simplex.c[simplex.rank]=m_free[--m_nfree];
|
||||||
|
getsupport(v,*simplex.c[simplex.rank++]);
|
||||||
|
}
|
||||||
|
static btScalar det(const btVector3& a,const btVector3& b,const btVector3& c)
|
||||||
|
{
|
||||||
|
return( a.y()*b.z()*c.x()+a.z()*b.x()*c.y()-
|
||||||
|
a.x()*b.z()*c.y()-a.y()*b.x()*c.z()+
|
||||||
|
a.x()*b.y()*c.z()-a.z()*b.y()*c.x());
|
||||||
|
}
|
||||||
|
static btScalar projectorigin( const btVector3& a,
|
||||||
|
const btVector3& b,
|
||||||
|
btScalar* w,U& m)
|
||||||
|
{
|
||||||
|
const btVector3 d=b-a;
|
||||||
|
const btScalar l=d.length2();
|
||||||
|
if(l>GJK_SIMPLEX2_EPS)
|
||||||
|
{
|
||||||
|
const btScalar t(l>0?-dot(a,d)/l:0);
|
||||||
|
if(t>=1) { w[0]=0;w[1]=1;m=2;return(b.length2()); }
|
||||||
|
else if(t<=0) { w[0]=1;w[1]=0;m=1;return(a.length2()); }
|
||||||
|
else { w[0]=1-(w[1]=t);m=3;return((a+d*t).length2()); }
|
||||||
|
}
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
static btScalar projectorigin( const btVector3& a,
|
||||||
|
const btVector3& b,
|
||||||
|
const btVector3& c,
|
||||||
|
btScalar* w,U& m)
|
||||||
|
{
|
||||||
|
static const U imd3[]={1,2,0};
|
||||||
|
const btVector3* vt[]={&a,&b,&c};
|
||||||
|
const btVector3 dl[]={a-b,b-c,c-a};
|
||||||
|
const btVector3 n=cross(dl[0],dl[1]);
|
||||||
|
const btScalar l=n.length2();
|
||||||
|
if(l>GJK_SIMPLEX3_EPS)
|
||||||
|
{
|
||||||
|
btScalar mindist=-1;
|
||||||
|
btScalar subw[2];
|
||||||
|
U subm;
|
||||||
|
for(U i=0;i<3;++i)
|
||||||
|
{
|
||||||
|
if(dot(*vt[i],cross(dl[i],n))>0)
|
||||||
|
{
|
||||||
|
const U j=imd3[i];
|
||||||
|
const btScalar subd(projectorigin(*vt[i],*vt[j],subw,subm));
|
||||||
|
if((mindist<0)||(subd<mindist))
|
||||||
|
{
|
||||||
|
mindist = subd;
|
||||||
|
m = static_cast<U>(((subm&1)?1<<i:0)+((subm&2)?1<<j:0));
|
||||||
|
w[i] = subw[0];
|
||||||
|
w[j] = subw[1];
|
||||||
|
w[imd3[j]] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(mindist<0)
|
||||||
|
{
|
||||||
|
const btScalar d=dot(a,n);
|
||||||
|
const btScalar s=btSqrt(l);
|
||||||
|
const btVector3 p=n*(d/l);
|
||||||
|
mindist = p.length2();
|
||||||
|
m = 7;
|
||||||
|
w[0] = (cross(dl[1],b-p)).length()/s;
|
||||||
|
w[1] = (cross(dl[2],c-p)).length()/s;
|
||||||
|
w[2] = 1-(w[0]+w[1]);
|
||||||
|
}
|
||||||
|
return(mindist);
|
||||||
|
}
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
static btScalar projectorigin( const btVector3& a,
|
||||||
|
const btVector3& b,
|
||||||
|
const btVector3& c,
|
||||||
|
const btVector3& d,
|
||||||
|
btScalar* w,U& m)
|
||||||
|
{
|
||||||
|
static const U imd3[]={1,2,0};
|
||||||
|
const btVector3* vt[]={&a,&b,&c,&d};
|
||||||
|
const btVector3 dl[]={a-d,b-d,c-d};
|
||||||
|
const btScalar vl=det(dl[0],dl[1],dl[2]);
|
||||||
|
const bool ng=(vl*dot(a,cross(b-c,a-b)))<=0;
|
||||||
|
if(ng&&(btFabs(vl)>GJK_SIMPLEX4_EPS))
|
||||||
|
{
|
||||||
|
btScalar mindist=-1;
|
||||||
|
btScalar subw[3];
|
||||||
|
U subm;
|
||||||
|
for(U i=0;i<3;++i)
|
||||||
|
{
|
||||||
|
const U j=imd3[i];
|
||||||
|
const btScalar s=vl*dot(d,cross(dl[i],dl[j]));
|
||||||
|
if(s>0)
|
||||||
|
{
|
||||||
|
const btScalar subd=projectorigin(*vt[i],*vt[j],d,subw,subm);
|
||||||
|
if((mindist<0)||(subd<mindist))
|
||||||
|
{
|
||||||
|
mindist = subd;
|
||||||
|
m = static_cast<U>((subm&1?1<<i:0)+
|
||||||
|
(subm&2?1<<j:0)+
|
||||||
|
(subm&4?8:0));
|
||||||
|
w[i] = subw[0];
|
||||||
|
w[j] = subw[1];
|
||||||
|
w[imd3[j]] = 0;
|
||||||
|
w[3] = subw[2];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(mindist<0)
|
||||||
|
{
|
||||||
|
mindist = 0;
|
||||||
|
m = 15;
|
||||||
|
w[0] = det(c,b,d)/vl;
|
||||||
|
w[1] = det(a,c,d)/vl;
|
||||||
|
w[2] = det(b,a,d)/vl;
|
||||||
|
w[3] = 1-(w[0]+w[1]+w[2]);
|
||||||
|
}
|
||||||
|
return(mindist);
|
||||||
|
}
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// EPA
|
||||||
|
struct EPA
|
||||||
|
{
|
||||||
|
/* Types */
|
||||||
|
typedef GJK::sSV sSV;
|
||||||
|
struct sFace
|
||||||
|
{
|
||||||
|
btVector3 n;
|
||||||
|
btScalar d;
|
||||||
|
btScalar p;
|
||||||
|
sSV* c[3];
|
||||||
|
sFace* f[3];
|
||||||
|
sFace* l[2];
|
||||||
|
U1 e[3];
|
||||||
|
U1 pass;
|
||||||
|
};
|
||||||
|
struct sList
|
||||||
|
{
|
||||||
|
sFace* root;
|
||||||
|
U count;
|
||||||
|
sList() : root(0),count(0) {}
|
||||||
|
};
|
||||||
|
struct sHorizon
|
||||||
|
{
|
||||||
|
sFace* cf;
|
||||||
|
sFace* ff;
|
||||||
|
U nf;
|
||||||
|
sHorizon() : cf(0),ff(0),nf(0) {}
|
||||||
|
};
|
||||||
|
struct eStatus { enum _ {
|
||||||
|
Valid,
|
||||||
|
Touching,
|
||||||
|
Degenerated,
|
||||||
|
NonConvex,
|
||||||
|
InvalidHull,
|
||||||
|
OutOfFaces,
|
||||||
|
OutOfVertices,
|
||||||
|
AccuraryReached,
|
||||||
|
FallBack,
|
||||||
|
Failed };};
|
||||||
|
/* Fields */
|
||||||
|
eStatus::_ m_status;
|
||||||
|
GJK::sSimplex m_result;
|
||||||
|
btVector3 m_normal;
|
||||||
|
btScalar m_depth;
|
||||||
|
sSV m_sv_store[EPA_MAX_VERTICES];
|
||||||
|
sFace m_fc_store[EPA_MAX_FACES];
|
||||||
|
U m_nextsv;
|
||||||
|
sList m_hull;
|
||||||
|
sList m_stock;
|
||||||
|
/* Methods */
|
||||||
|
EPA()
|
||||||
|
{
|
||||||
|
Initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline void bind(sFace* fa,U ea,sFace* fb,U eb)
|
||||||
|
{
|
||||||
|
fa->e[ea]=(U1)eb;fa->f[ea]=fb;
|
||||||
|
fb->e[eb]=(U1)ea;fb->f[eb]=fa;
|
||||||
|
}
|
||||||
|
static inline void append(sList& list,sFace* face)
|
||||||
|
{
|
||||||
|
face->l[0] = 0;
|
||||||
|
face->l[1] = list.root;
|
||||||
|
if(list.root) list.root->l[0]=face;
|
||||||
|
list.root = face;
|
||||||
|
++list.count;
|
||||||
|
}
|
||||||
|
static inline void remove(sList& list,sFace* face)
|
||||||
|
{
|
||||||
|
if(face->l[1]) face->l[1]->l[0]=face->l[0];
|
||||||
|
if(face->l[0]) face->l[0]->l[1]=face->l[1];
|
||||||
|
if(face==list.root) list.root=face->l[1];
|
||||||
|
--list.count;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Initialize()
|
||||||
|
{
|
||||||
|
m_status = eStatus::Failed;
|
||||||
|
m_normal = btVector3(0,0,0);
|
||||||
|
m_depth = 0;
|
||||||
|
m_nextsv = 0;
|
||||||
|
for(U i=0;i<EPA_MAX_FACES;++i)
|
||||||
|
{
|
||||||
|
append(m_stock,&m_fc_store[EPA_MAX_FACES-i-1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
eStatus::_ Evaluate(GJK& gjk,const btVector3& guess)
|
||||||
|
{
|
||||||
|
GJK::sSimplex& simplex=*gjk.m_simplex;
|
||||||
|
if((simplex.rank>1)&&gjk.EncloseOrigin())
|
||||||
|
{
|
||||||
|
|
||||||
|
/* Clean up */
|
||||||
|
while(m_hull.root)
|
||||||
|
{
|
||||||
|
sFace* f = m_hull.root;
|
||||||
|
remove(m_hull,f);
|
||||||
|
append(m_stock,f);
|
||||||
|
}
|
||||||
|
m_status = eStatus::Valid;
|
||||||
|
m_nextsv = 0;
|
||||||
|
/* Orient simplex */
|
||||||
|
if(gjk.det( simplex.c[0]->w-simplex.c[3]->w,
|
||||||
|
simplex.c[1]->w-simplex.c[3]->w,
|
||||||
|
simplex.c[2]->w-simplex.c[3]->w)<0)
|
||||||
|
{
|
||||||
|
btSwap(simplex.c[0],simplex.c[1]);
|
||||||
|
btSwap(simplex.p[0],simplex.p[1]);
|
||||||
|
}
|
||||||
|
/* Build initial hull */
|
||||||
|
sFace* tetra[]={newface(simplex.c[0],simplex.c[1],simplex.c[2],true),
|
||||||
|
newface(simplex.c[1],simplex.c[0],simplex.c[3],true),
|
||||||
|
newface(simplex.c[2],simplex.c[1],simplex.c[3],true),
|
||||||
|
newface(simplex.c[0],simplex.c[2],simplex.c[3],true)};
|
||||||
|
if(m_hull.count==4)
|
||||||
|
{
|
||||||
|
sFace* best=findbest();
|
||||||
|
sFace outer=*best;
|
||||||
|
U pass=0;
|
||||||
|
U iterations=0;
|
||||||
|
bind(tetra[0],0,tetra[1],0);
|
||||||
|
bind(tetra[0],1,tetra[2],0);
|
||||||
|
bind(tetra[0],2,tetra[3],0);
|
||||||
|
bind(tetra[1],1,tetra[3],2);
|
||||||
|
bind(tetra[1],2,tetra[2],1);
|
||||||
|
bind(tetra[2],2,tetra[3],1);
|
||||||
|
m_status=eStatus::Valid;
|
||||||
|
for(;iterations<EPA_MAX_ITERATIONS;++iterations)
|
||||||
|
{
|
||||||
|
if(m_nextsv<EPA_MAX_VERTICES)
|
||||||
|
{
|
||||||
|
sHorizon horizon;
|
||||||
|
sSV* w=&m_sv_store[m_nextsv++];
|
||||||
|
bool valid=true;
|
||||||
|
best->pass = (U1)(++pass);
|
||||||
|
gjk.getsupport(best->n,*w);
|
||||||
|
const btScalar wdist=dot(best->n,w->w)-best->d;
|
||||||
|
if(wdist>EPA_ACCURACY)
|
||||||
|
{
|
||||||
|
for(U j=0;(j<3)&&valid;++j)
|
||||||
|
{
|
||||||
|
valid&=expand( pass,w,
|
||||||
|
best->f[j],best->e[j],
|
||||||
|
horizon);
|
||||||
|
}
|
||||||
|
if(valid&&(horizon.nf>=3))
|
||||||
|
{
|
||||||
|
bind(horizon.cf,1,horizon.ff,2);
|
||||||
|
remove(m_hull,best);
|
||||||
|
append(m_stock,best);
|
||||||
|
best=findbest();
|
||||||
|
if(best->p>=outer.p) outer=*best;
|
||||||
|
} else { m_status=eStatus::InvalidHull;break; }
|
||||||
|
} else { m_status=eStatus::AccuraryReached;break; }
|
||||||
|
} else { m_status=eStatus::OutOfVertices;break; }
|
||||||
|
}
|
||||||
|
const btVector3 projection=outer.n*outer.d;
|
||||||
|
m_normal = outer.n;
|
||||||
|
m_depth = outer.d;
|
||||||
|
m_result.rank = 3;
|
||||||
|
m_result.c[0] = outer.c[0];
|
||||||
|
m_result.c[1] = outer.c[1];
|
||||||
|
m_result.c[2] = outer.c[2];
|
||||||
|
m_result.p[0] = cross( outer.c[1]->w-projection,
|
||||||
|
outer.c[2]->w-projection).length();
|
||||||
|
m_result.p[1] = cross( outer.c[2]->w-projection,
|
||||||
|
outer.c[0]->w-projection).length();
|
||||||
|
m_result.p[2] = cross( outer.c[0]->w-projection,
|
||||||
|
outer.c[1]->w-projection).length();
|
||||||
|
const btScalar sum=m_result.p[0]+m_result.p[1]+m_result.p[2];
|
||||||
|
m_result.p[0] /= sum;
|
||||||
|
m_result.p[1] /= sum;
|
||||||
|
m_result.p[2] /= sum;
|
||||||
|
return(m_status);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Fallback */
|
||||||
|
m_status = eStatus::FallBack;
|
||||||
|
m_normal = -guess;
|
||||||
|
const btScalar nl=m_normal.length();
|
||||||
|
if(nl>0)
|
||||||
|
m_normal = m_normal/nl;
|
||||||
|
else
|
||||||
|
m_normal = btVector3(1,0,0);
|
||||||
|
m_depth = 0;
|
||||||
|
m_result.rank=1;
|
||||||
|
m_result.c[0]=simplex.c[0];
|
||||||
|
m_result.p[0]=1;
|
||||||
|
return(m_status);
|
||||||
|
}
|
||||||
|
sFace* newface(sSV* a,sSV* b,sSV* c,bool forced)
|
||||||
|
{
|
||||||
|
if(m_stock.root)
|
||||||
|
{
|
||||||
|
sFace* face=m_stock.root;
|
||||||
|
remove(m_stock,face);
|
||||||
|
append(m_hull,face);
|
||||||
|
face->pass = 0;
|
||||||
|
face->c[0] = a;
|
||||||
|
face->c[1] = b;
|
||||||
|
face->c[2] = c;
|
||||||
|
face->n = cross(b->w-a->w,c->w-a->w);
|
||||||
|
const btScalar l=face->n.length();
|
||||||
|
const bool v=l>EPA_ACCURACY;
|
||||||
|
face->p = btMin(btMin(
|
||||||
|
dot(a->w,cross(face->n,a->w-b->w)),
|
||||||
|
dot(b->w,cross(face->n,b->w-c->w))),
|
||||||
|
dot(c->w,cross(face->n,c->w-a->w))) /
|
||||||
|
(v?l:1);
|
||||||
|
face->p = face->p>=-EPA_INSIDE_EPS?0:face->p;
|
||||||
|
if(v)
|
||||||
|
{
|
||||||
|
face->d = dot(a->w,face->n)/l;
|
||||||
|
face->n /= l;
|
||||||
|
if(forced||(face->d>=-EPA_PLANE_EPS))
|
||||||
|
{
|
||||||
|
return(face);
|
||||||
|
} else m_status=eStatus::NonConvex;
|
||||||
|
} else m_status=eStatus::Degenerated;
|
||||||
|
remove(m_hull,face);
|
||||||
|
append(m_stock,face);
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
m_status=m_stock.root?eStatus::OutOfVertices:eStatus::OutOfFaces;
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
sFace* findbest()
|
||||||
|
{
|
||||||
|
sFace* minf=m_hull.root;
|
||||||
|
btScalar mind=minf->d*minf->d;
|
||||||
|
btScalar maxp=minf->p;
|
||||||
|
for(sFace* f=minf->l[1];f;f=f->l[1])
|
||||||
|
{
|
||||||
|
const btScalar sqd=f->d*f->d;
|
||||||
|
if((f->p>=maxp)&&(sqd<mind))
|
||||||
|
{
|
||||||
|
minf=f;
|
||||||
|
mind=sqd;
|
||||||
|
maxp=f->p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return(minf);
|
||||||
|
}
|
||||||
|
bool expand(U pass,sSV* w,sFace* f,U e,sHorizon& horizon)
|
||||||
|
{
|
||||||
|
static const U i1m3[]={1,2,0};
|
||||||
|
static const U i2m3[]={2,0,1};
|
||||||
|
if(f->pass!=pass)
|
||||||
|
{
|
||||||
|
const U e1=i1m3[e];
|
||||||
|
if((dot(f->n,w->w)-f->d)<-EPA_PLANE_EPS)
|
||||||
|
{
|
||||||
|
sFace* nf=newface(f->c[e1],f->c[e],w,false);
|
||||||
|
if(nf)
|
||||||
|
{
|
||||||
|
bind(nf,0,f,e);
|
||||||
|
if(horizon.cf) bind(horizon.cf,1,nf,2); else horizon.ff=nf;
|
||||||
|
horizon.cf=nf;
|
||||||
|
++horizon.nf;
|
||||||
|
return(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const U e2=i2m3[e];
|
||||||
|
f->pass = (U1)pass;
|
||||||
|
if( expand(pass,w,f->f[e1],f->e[e1],horizon)&&
|
||||||
|
expand(pass,w,f->f[e2],f->e[e2],horizon))
|
||||||
|
{
|
||||||
|
remove(m_hull,f);
|
||||||
|
append(m_stock,f);
|
||||||
|
return(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
static void Initialize( const btConvexShape* shape0,const btTransform& wtrs0,
|
||||||
|
const btConvexShape* shape1,const btTransform& wtrs1,
|
||||||
|
btGjkEpaSolver2::sResults& results,
|
||||||
|
tShape& shape,
|
||||||
|
bool withmargins)
|
||||||
|
{
|
||||||
|
/* Results */
|
||||||
|
results.witnesses[0] =
|
||||||
|
results.witnesses[1] = btVector3(0,0,0);
|
||||||
|
results.status = btGjkEpaSolver2::sResults::Separated;
|
||||||
|
/* Shape */
|
||||||
|
shape.m_shapes[0] = shape0;
|
||||||
|
shape.m_shapes[1] = shape1;
|
||||||
|
shape.m_toshape1 = wtrs1.getBasis().transposeTimes(wtrs0.getBasis());
|
||||||
|
shape.m_toshape0 = wtrs0.inverseTimes(wtrs1);
|
||||||
|
shape.EnableMargin(withmargins);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Api
|
||||||
|
//
|
||||||
|
|
||||||
|
using namespace gjkepa2_impl;
|
||||||
|
|
||||||
|
//
|
||||||
|
int btGjkEpaSolver2::StackSizeRequirement()
|
||||||
|
{
|
||||||
|
return(sizeof(GJK)+sizeof(EPA));
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
bool btGjkEpaSolver2::Distance( const btConvexShape* shape0,
|
||||||
|
const btTransform& wtrs0,
|
||||||
|
const btConvexShape* shape1,
|
||||||
|
const btTransform& wtrs1,
|
||||||
|
const btVector3& guess,
|
||||||
|
sResults& results)
|
||||||
|
{
|
||||||
|
tShape shape;
|
||||||
|
Initialize(shape0,wtrs0,shape1,wtrs1,results,shape,false);
|
||||||
|
GJK gjk;
|
||||||
|
GJK::eStatus::_ gjk_status=gjk.Evaluate(shape,guess);
|
||||||
|
if(gjk_status==GJK::eStatus::Valid)
|
||||||
|
{
|
||||||
|
btVector3 w0=btVector3(0,0,0);
|
||||||
|
btVector3 w1=btVector3(0,0,0);
|
||||||
|
for(U i=0;i<gjk.m_simplex->rank;++i)
|
||||||
|
{
|
||||||
|
const btScalar p=gjk.m_simplex->p[i];
|
||||||
|
w0+=shape.Support( gjk.m_simplex->c[i]->d,0)*p;
|
||||||
|
w1+=shape.Support(-gjk.m_simplex->c[i]->d,1)*p;
|
||||||
|
}
|
||||||
|
results.witnesses[0] = wtrs0*w0;
|
||||||
|
results.witnesses[1] = wtrs0*w1;
|
||||||
|
results.normal = w0-w1;
|
||||||
|
results.distance = results.normal.length();
|
||||||
|
results.normal /= results.distance>GJK_MIN_DISTANCE?results.distance:1;
|
||||||
|
return(true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
results.status = gjk_status==GJK::eStatus::Inside?
|
||||||
|
sResults::Penetrating :
|
||||||
|
sResults::GJK_Failed ;
|
||||||
|
return(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
bool btGjkEpaSolver2::Penetration( const btConvexShape* shape0,
|
||||||
|
const btTransform& wtrs0,
|
||||||
|
const btConvexShape* shape1,
|
||||||
|
const btTransform& wtrs1,
|
||||||
|
const btVector3& guess,
|
||||||
|
sResults& results,
|
||||||
|
bool usemargins)
|
||||||
|
{
|
||||||
|
tShape shape;
|
||||||
|
Initialize(shape0,wtrs0,shape1,wtrs1,results,shape,usemargins);
|
||||||
|
GJK gjk;
|
||||||
|
GJK::eStatus::_ gjk_status=gjk.Evaluate(shape,-guess);
|
||||||
|
switch(gjk_status)
|
||||||
|
{
|
||||||
|
case GJK::eStatus::Inside:
|
||||||
|
{
|
||||||
|
EPA epa;
|
||||||
|
EPA::eStatus::_ epa_status=epa.Evaluate(gjk,-guess);
|
||||||
|
if(epa_status!=EPA::eStatus::Failed)
|
||||||
|
{
|
||||||
|
btVector3 w0=btVector3(0,0,0);
|
||||||
|
for(U i=0;i<epa.m_result.rank;++i)
|
||||||
|
{
|
||||||
|
w0+=shape.Support(epa.m_result.c[i]->d,0)*epa.m_result.p[i];
|
||||||
|
}
|
||||||
|
results.status = sResults::Penetrating;
|
||||||
|
results.witnesses[0] = wtrs0*w0;
|
||||||
|
results.witnesses[1] = wtrs0*(w0-epa.m_normal*epa.m_depth);
|
||||||
|
results.normal = -epa.m_normal;
|
||||||
|
results.distance = -epa.m_depth;
|
||||||
|
return(true);
|
||||||
|
} else results.status=sResults::EPA_Failed;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case GJK::eStatus::Failed:
|
||||||
|
results.status=sResults::GJK_Failed;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
btScalar btGjkEpaSolver2::SignedDistance(const btVector3& position,
|
||||||
|
btScalar margin,
|
||||||
|
const btConvexShape* shape0,
|
||||||
|
const btTransform& wtrs0,
|
||||||
|
sResults& results)
|
||||||
|
{
|
||||||
|
tShape shape;
|
||||||
|
btSphereShape shape1(margin);
|
||||||
|
btTransform wtrs1(btQuaternion(0,0,0,1),position);
|
||||||
|
Initialize(shape0,wtrs0,&shape1,wtrs1,results,shape,false);
|
||||||
|
GJK gjk;
|
||||||
|
GJK::eStatus::_ gjk_status=gjk.Evaluate(shape,btVector3(1,1,1));
|
||||||
|
if(gjk_status==GJK::eStatus::Valid)
|
||||||
|
{
|
||||||
|
btVector3 w0=btVector3(0,0,0);
|
||||||
|
btVector3 w1=btVector3(0,0,0);
|
||||||
|
for(U i=0;i<gjk.m_simplex->rank;++i)
|
||||||
|
{
|
||||||
|
const btScalar p=gjk.m_simplex->p[i];
|
||||||
|
w0+=shape.Support( gjk.m_simplex->c[i]->d,0)*p;
|
||||||
|
w1+=shape.Support(-gjk.m_simplex->c[i]->d,1)*p;
|
||||||
|
}
|
||||||
|
results.witnesses[0] = wtrs0*w0;
|
||||||
|
results.witnesses[1] = wtrs0*w1;
|
||||||
|
const btVector3 delta= results.witnesses[1]-
|
||||||
|
results.witnesses[0];
|
||||||
|
const btScalar margin= shape0->getMargin()+
|
||||||
|
shape1.getMargin();
|
||||||
|
const btScalar length= delta.length();
|
||||||
|
results.normal = delta/length;
|
||||||
|
results.witnesses[0] += results.normal*margin;
|
||||||
|
return(length-margin);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(gjk_status==GJK::eStatus::Inside)
|
||||||
|
{
|
||||||
|
if(Penetration(shape0,wtrs0,&shape1,wtrs1,gjk.m_ray,results))
|
||||||
|
{
|
||||||
|
const btVector3 delta= results.witnesses[0]-
|
||||||
|
results.witnesses[1];
|
||||||
|
const btScalar length= delta.length();
|
||||||
|
if (length >= SIMD_EPSILON)
|
||||||
|
results.normal = delta/length;
|
||||||
|
return(-length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return(SIMD_INFINITY);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
bool btGjkEpaSolver2::SignedDistance(const btConvexShape* shape0,
|
||||||
|
const btTransform& wtrs0,
|
||||||
|
const btConvexShape* shape1,
|
||||||
|
const btTransform& wtrs1,
|
||||||
|
const btVector3& guess,
|
||||||
|
sResults& results)
|
||||||
|
{
|
||||||
|
if(!Distance(shape0,wtrs0,shape1,wtrs1,guess,results))
|
||||||
|
return(Penetration(shape0,wtrs0,shape1,wtrs1,guess,results,false));
|
||||||
|
else
|
||||||
|
return(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Symbols cleanup */
|
||||||
|
|
||||||
|
#undef GJK_MAX_ITERATIONS
|
||||||
|
#undef GJK_ACCURARY
|
||||||
|
#undef GJK_MIN_DISTANCE
|
||||||
|
#undef GJK_DUPLICATED_EPS
|
||||||
|
#undef GJK_SIMPLEX2_EPS
|
||||||
|
#undef GJK_SIMPLEX3_EPS
|
||||||
|
#undef GJK_SIMPLEX4_EPS
|
||||||
|
|
||||||
|
#undef EPA_MAX_VERTICES
|
||||||
|
#undef EPA_MAX_FACES
|
||||||
|
#undef EPA_MAX_ITERATIONS
|
||||||
|
#undef EPA_ACCURACY
|
||||||
|
#undef EPA_FALLBACK
|
||||||
|
#undef EPA_PLANE_EPS
|
||||||
|
#undef EPA_INSIDE_EPS
|
71
extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.h
vendored
Normal file
71
extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.h
vendored
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
/*
|
||||||
|
Bullet Continuous Collision Detection and Physics Library
|
||||||
|
Copyright (c) 2003-2008 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
GJK-EPA collision solver by Nathanael Presson, 2008
|
||||||
|
*/
|
||||||
|
#ifndef _68DA1F85_90B7_4bb0_A705_83B4040A75C6_
|
||||||
|
#define _68DA1F85_90B7_4bb0_A705_83B4040A75C6_
|
||||||
|
#include "BulletCollision/CollisionShapes/btConvexShape.h"
|
||||||
|
|
||||||
|
///btGjkEpaSolver contributed under zlib by Nathanael Presson
|
||||||
|
struct btGjkEpaSolver2
|
||||||
|
{
|
||||||
|
struct sResults
|
||||||
|
{
|
||||||
|
enum eStatus
|
||||||
|
{
|
||||||
|
Separated, /* Shapes doesnt penetrate */
|
||||||
|
Penetrating, /* Shapes are penetrating */
|
||||||
|
GJK_Failed, /* GJK phase fail, no big issue, shapes are probably just 'touching' */
|
||||||
|
EPA_Failed /* EPA phase fail, bigger problem, need to save parameters, and debug */
|
||||||
|
} status;
|
||||||
|
btVector3 witnesses[2];
|
||||||
|
btVector3 normal;
|
||||||
|
btScalar distance;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int StackSizeRequirement();
|
||||||
|
|
||||||
|
static bool Distance( const btConvexShape* shape0,const btTransform& wtrs0,
|
||||||
|
const btConvexShape* shape1,const btTransform& wtrs1,
|
||||||
|
const btVector3& guess,
|
||||||
|
sResults& results);
|
||||||
|
|
||||||
|
static bool Penetration(const btConvexShape* shape0,const btTransform& wtrs0,
|
||||||
|
const btConvexShape* shape1,const btTransform& wtrs1,
|
||||||
|
const btVector3& guess,
|
||||||
|
sResults& results,
|
||||||
|
bool usemargins=true);
|
||||||
|
|
||||||
|
static btScalar SignedDistance( const btVector3& position,
|
||||||
|
btScalar margin,
|
||||||
|
const btConvexShape* shape,
|
||||||
|
const btTransform& wtrs,
|
||||||
|
sResults& results);
|
||||||
|
|
||||||
|
static bool SignedDistance( const btConvexShape* shape0,const btTransform& wtrs0,
|
||||||
|
const btConvexShape* shape1,const btTransform& wtrs1,
|
||||||
|
const btVector3& guess,
|
||||||
|
sResults& results);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
415
extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp
vendored
Normal file
415
extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp
vendored
Normal file
@ -0,0 +1,415 @@
|
|||||||
|
/*
|
||||||
|
Bullet Continuous Collision Detection and Physics Library
|
||||||
|
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Added by Roman Ponomarev (rponom@gmail.com)
|
||||||
|
April 04, 2008
|
||||||
|
*/
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "btSliderConstraint.h"
|
||||||
|
#include "BulletDynamics/Dynamics/btRigidBody.h"
|
||||||
|
#include "LinearMath/btTransformUtil.h"
|
||||||
|
#include <new>
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void btSliderConstraint::initParams()
|
||||||
|
{
|
||||||
|
m_lowerLinLimit = btScalar(1.0);
|
||||||
|
m_upperLinLimit = btScalar(-1.0);
|
||||||
|
m_lowerAngLimit = btScalar(0.);
|
||||||
|
m_upperAngLimit = btScalar(0.);
|
||||||
|
m_softnessDirLin = SLIDER_CONSTRAINT_DEF_SOFTNESS;
|
||||||
|
m_restitutionDirLin = SLIDER_CONSTRAINT_DEF_RESTITUTION;
|
||||||
|
m_dampingDirLin = btScalar(0.);
|
||||||
|
m_softnessDirAng = SLIDER_CONSTRAINT_DEF_SOFTNESS;
|
||||||
|
m_restitutionDirAng = SLIDER_CONSTRAINT_DEF_RESTITUTION;
|
||||||
|
m_dampingDirAng = btScalar(0.);
|
||||||
|
m_softnessOrthoLin = SLIDER_CONSTRAINT_DEF_SOFTNESS;
|
||||||
|
m_restitutionOrthoLin = SLIDER_CONSTRAINT_DEF_RESTITUTION;
|
||||||
|
m_dampingOrthoLin = SLIDER_CONSTRAINT_DEF_DAMPING;
|
||||||
|
m_softnessOrthoAng = SLIDER_CONSTRAINT_DEF_SOFTNESS;
|
||||||
|
m_restitutionOrthoAng = SLIDER_CONSTRAINT_DEF_RESTITUTION;
|
||||||
|
m_dampingOrthoAng = SLIDER_CONSTRAINT_DEF_DAMPING;
|
||||||
|
m_softnessLimLin = SLIDER_CONSTRAINT_DEF_SOFTNESS;
|
||||||
|
m_restitutionLimLin = SLIDER_CONSTRAINT_DEF_RESTITUTION;
|
||||||
|
m_dampingLimLin = SLIDER_CONSTRAINT_DEF_DAMPING;
|
||||||
|
m_softnessLimAng = SLIDER_CONSTRAINT_DEF_SOFTNESS;
|
||||||
|
m_restitutionLimAng = SLIDER_CONSTRAINT_DEF_RESTITUTION;
|
||||||
|
m_dampingLimAng = SLIDER_CONSTRAINT_DEF_DAMPING;
|
||||||
|
|
||||||
|
m_poweredLinMotor = false;
|
||||||
|
m_targetLinMotorVelocity = btScalar(0.);
|
||||||
|
m_maxLinMotorForce = btScalar(0.);
|
||||||
|
m_accumulatedLinMotorImpulse = btScalar(0.0);
|
||||||
|
|
||||||
|
m_poweredAngMotor = false;
|
||||||
|
m_targetAngMotorVelocity = btScalar(0.);
|
||||||
|
m_maxAngMotorForce = btScalar(0.);
|
||||||
|
m_accumulatedAngMotorImpulse = btScalar(0.0);
|
||||||
|
|
||||||
|
} // btSliderConstraint::initParams()
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
btSliderConstraint::btSliderConstraint()
|
||||||
|
:btTypedConstraint(SLIDER_CONSTRAINT_TYPE),
|
||||||
|
m_useLinearReferenceFrameA(true)
|
||||||
|
{
|
||||||
|
initParams();
|
||||||
|
} // btSliderConstraint::btSliderConstraint()
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
btSliderConstraint::btSliderConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB, bool useLinearReferenceFrameA)
|
||||||
|
: btTypedConstraint(SLIDER_CONSTRAINT_TYPE, rbA, rbB)
|
||||||
|
, m_frameInA(frameInA)
|
||||||
|
, m_frameInB(frameInB),
|
||||||
|
m_useLinearReferenceFrameA(useLinearReferenceFrameA)
|
||||||
|
{
|
||||||
|
initParams();
|
||||||
|
} // btSliderConstraint::btSliderConstraint()
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void btSliderConstraint::buildJacobian()
|
||||||
|
{
|
||||||
|
if(m_useLinearReferenceFrameA)
|
||||||
|
{
|
||||||
|
buildJacobianInt(m_rbA, m_rbB, m_frameInA, m_frameInB);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
buildJacobianInt(m_rbB, m_rbA, m_frameInB, m_frameInA);
|
||||||
|
}
|
||||||
|
} // btSliderConstraint::buildJacobian()
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void btSliderConstraint::buildJacobianInt(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB)
|
||||||
|
{
|
||||||
|
//calculate transforms
|
||||||
|
m_calculatedTransformA = rbA.getCenterOfMassTransform() * frameInA;
|
||||||
|
m_calculatedTransformB = rbB.getCenterOfMassTransform() * frameInB;
|
||||||
|
m_realPivotAInW = m_calculatedTransformA.getOrigin();
|
||||||
|
m_realPivotBInW = m_calculatedTransformB.getOrigin();
|
||||||
|
m_sliderAxis = m_calculatedTransformA.getBasis().getColumn(0); // along X
|
||||||
|
m_delta = m_realPivotBInW - m_realPivotAInW;
|
||||||
|
m_projPivotInW = m_realPivotAInW + m_sliderAxis.dot(m_delta) * m_sliderAxis;
|
||||||
|
m_relPosA = m_projPivotInW - rbA.getCenterOfMassPosition();
|
||||||
|
m_relPosB = m_realPivotBInW - rbB.getCenterOfMassPosition();
|
||||||
|
btVector3 normalWorld;
|
||||||
|
int i;
|
||||||
|
//linear part
|
||||||
|
for(i = 0; i < 3; i++)
|
||||||
|
{
|
||||||
|
normalWorld = m_calculatedTransformA.getBasis().getColumn(i);
|
||||||
|
new (&m_jacLin[i]) btJacobianEntry(
|
||||||
|
rbA.getCenterOfMassTransform().getBasis().transpose(),
|
||||||
|
rbB.getCenterOfMassTransform().getBasis().transpose(),
|
||||||
|
m_relPosA,
|
||||||
|
m_relPosB,
|
||||||
|
normalWorld,
|
||||||
|
rbA.getInvInertiaDiagLocal(),
|
||||||
|
rbA.getInvMass(),
|
||||||
|
rbB.getInvInertiaDiagLocal(),
|
||||||
|
rbB.getInvMass()
|
||||||
|
);
|
||||||
|
m_jacLinDiagABInv[i] = btScalar(1.) / m_jacLin[i].getDiagonal();
|
||||||
|
m_depth[i] = m_delta.dot(normalWorld);
|
||||||
|
}
|
||||||
|
testLinLimits();
|
||||||
|
// angular part
|
||||||
|
for(i = 0; i < 3; i++)
|
||||||
|
{
|
||||||
|
normalWorld = m_calculatedTransformA.getBasis().getColumn(i);
|
||||||
|
new (&m_jacAng[i]) btJacobianEntry(
|
||||||
|
normalWorld,
|
||||||
|
rbA.getCenterOfMassTransform().getBasis().transpose(),
|
||||||
|
rbB.getCenterOfMassTransform().getBasis().transpose(),
|
||||||
|
rbA.getInvInertiaDiagLocal(),
|
||||||
|
rbB.getInvInertiaDiagLocal()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
testAngLimits();
|
||||||
|
btVector3 axisA = m_calculatedTransformA.getBasis().getColumn(0);
|
||||||
|
m_kAngle = btScalar(1.0 )/ (rbA.computeAngularImpulseDenominator(axisA) + rbB.computeAngularImpulseDenominator(axisA));
|
||||||
|
// clear accumulator for motors
|
||||||
|
m_accumulatedLinMotorImpulse = btScalar(0.0);
|
||||||
|
m_accumulatedAngMotorImpulse = btScalar(0.0);
|
||||||
|
} // btSliderConstraint::buildJacobianInt()
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void btSliderConstraint::solveConstraint(btScalar timeStep)
|
||||||
|
{
|
||||||
|
m_timeStep = timeStep;
|
||||||
|
if(m_useLinearReferenceFrameA)
|
||||||
|
{
|
||||||
|
solveConstraintInt(m_rbA, m_rbB);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
solveConstraintInt(m_rbB, m_rbA);
|
||||||
|
}
|
||||||
|
} // btSliderConstraint::solveConstraint()
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void btSliderConstraint::solveConstraintInt(btRigidBody& rbA, btRigidBody& rbB)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
// linear
|
||||||
|
btVector3 velA = rbA.getVelocityInLocalPoint(m_relPosA);
|
||||||
|
btVector3 velB = rbB.getVelocityInLocalPoint(m_relPosB);
|
||||||
|
btVector3 vel = velA - velB;
|
||||||
|
for(i = 0; i < 3; i++)
|
||||||
|
{
|
||||||
|
const btVector3& normal = m_jacLin[i].m_linearJointAxis;
|
||||||
|
btScalar rel_vel = normal.dot(vel);
|
||||||
|
// calculate positional error
|
||||||
|
btScalar depth = m_depth[i];
|
||||||
|
// get parameters
|
||||||
|
btScalar softness = (i) ? m_softnessOrthoLin : (m_solveLinLim ? m_softnessLimLin : m_softnessDirLin);
|
||||||
|
btScalar restitution = (i) ? m_restitutionOrthoLin : (m_solveLinLim ? m_restitutionLimLin : m_restitutionDirLin);
|
||||||
|
btScalar damping = (i) ? m_dampingOrthoLin : (m_solveLinLim ? m_dampingLimLin : m_dampingDirLin);
|
||||||
|
// calcutate and apply impulse
|
||||||
|
btScalar normalImpulse = softness * (restitution * depth / m_timeStep - damping * rel_vel) * m_jacLinDiagABInv[i];
|
||||||
|
btVector3 impulse_vector = normal * normalImpulse;
|
||||||
|
rbA.applyImpulse( impulse_vector, m_relPosA);
|
||||||
|
rbB.applyImpulse(-impulse_vector, m_relPosB);
|
||||||
|
if(m_poweredLinMotor && (!i))
|
||||||
|
{ // apply linear motor
|
||||||
|
if(m_accumulatedLinMotorImpulse < m_maxLinMotorForce)
|
||||||
|
{
|
||||||
|
btScalar desiredMotorVel = m_targetLinMotorVelocity;
|
||||||
|
btScalar motor_relvel = desiredMotorVel + rel_vel;
|
||||||
|
normalImpulse = -motor_relvel * m_jacLinDiagABInv[i];
|
||||||
|
// clamp accumulated impulse
|
||||||
|
btScalar new_acc = m_accumulatedLinMotorImpulse + btFabs(normalImpulse);
|
||||||
|
if(new_acc > m_maxLinMotorForce)
|
||||||
|
{
|
||||||
|
new_acc = m_maxLinMotorForce;
|
||||||
|
}
|
||||||
|
btScalar del = new_acc - m_accumulatedLinMotorImpulse;
|
||||||
|
if(normalImpulse < btScalar(0.0))
|
||||||
|
{
|
||||||
|
normalImpulse = -del;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
normalImpulse = del;
|
||||||
|
}
|
||||||
|
m_accumulatedLinMotorImpulse = new_acc;
|
||||||
|
// apply clamped impulse
|
||||||
|
impulse_vector = normal * normalImpulse;
|
||||||
|
rbA.applyImpulse( impulse_vector, m_relPosA);
|
||||||
|
rbB.applyImpulse(-impulse_vector, m_relPosB);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// angular
|
||||||
|
// get axes in world space
|
||||||
|
btVector3 axisA = m_calculatedTransformA.getBasis().getColumn(0);
|
||||||
|
btVector3 axisB = m_calculatedTransformB.getBasis().getColumn(0);
|
||||||
|
|
||||||
|
const btVector3& angVelA = rbA.getAngularVelocity();
|
||||||
|
const btVector3& angVelB = rbB.getAngularVelocity();
|
||||||
|
|
||||||
|
btVector3 angVelAroundAxisA = axisA * axisA.dot(angVelA);
|
||||||
|
btVector3 angVelAroundAxisB = axisB * axisB.dot(angVelB);
|
||||||
|
|
||||||
|
btVector3 angAorthog = angVelA - angVelAroundAxisA;
|
||||||
|
btVector3 angBorthog = angVelB - angVelAroundAxisB;
|
||||||
|
btVector3 velrelOrthog = angAorthog-angBorthog;
|
||||||
|
//solve orthogonal angular velocity correction
|
||||||
|
btScalar len = velrelOrthog.length();
|
||||||
|
if (len > btScalar(0.00001))
|
||||||
|
{
|
||||||
|
btVector3 normal = velrelOrthog.normalized();
|
||||||
|
btScalar denom = rbA.computeAngularImpulseDenominator(normal) + rbB.computeAngularImpulseDenominator(normal);
|
||||||
|
velrelOrthog *= (btScalar(1.)/denom) * m_dampingOrthoAng * m_softnessOrthoAng;
|
||||||
|
}
|
||||||
|
//solve angular positional correction
|
||||||
|
btVector3 angularError = axisA.cross(axisB) *(btScalar(1.)/m_timeStep);
|
||||||
|
btScalar len2 = angularError.length();
|
||||||
|
if (len2>btScalar(0.00001))
|
||||||
|
{
|
||||||
|
btVector3 normal2 = angularError.normalized();
|
||||||
|
btScalar denom2 = rbA.computeAngularImpulseDenominator(normal2) + rbB.computeAngularImpulseDenominator(normal2);
|
||||||
|
angularError *= (btScalar(1.)/denom2) * m_restitutionOrthoAng * m_softnessOrthoAng;
|
||||||
|
}
|
||||||
|
// apply impulse
|
||||||
|
rbA.applyTorqueImpulse(-velrelOrthog+angularError);
|
||||||
|
rbB.applyTorqueImpulse(velrelOrthog-angularError);
|
||||||
|
btScalar impulseMag;
|
||||||
|
//solve angular limits
|
||||||
|
if(m_solveAngLim)
|
||||||
|
{
|
||||||
|
impulseMag = (angVelB - angVelA).dot(axisA) * m_dampingLimAng + m_angDepth * m_restitutionLimAng / m_timeStep;
|
||||||
|
impulseMag *= m_kAngle * m_softnessLimAng;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
impulseMag = (angVelB - angVelA).dot(axisA) * m_dampingDirAng + m_angDepth * m_restitutionDirAng / m_timeStep;
|
||||||
|
impulseMag *= m_kAngle * m_softnessDirAng;
|
||||||
|
}
|
||||||
|
btVector3 impulse = axisA * impulseMag;
|
||||||
|
rbA.applyTorqueImpulse(impulse);
|
||||||
|
rbB.applyTorqueImpulse(-impulse);
|
||||||
|
//apply angular motor
|
||||||
|
if(m_poweredAngMotor)
|
||||||
|
{
|
||||||
|
if(m_accumulatedAngMotorImpulse < m_maxAngMotorForce)
|
||||||
|
{
|
||||||
|
btVector3 velrel = angVelAroundAxisA - angVelAroundAxisB;
|
||||||
|
btScalar projRelVel = velrel.dot(axisA);
|
||||||
|
|
||||||
|
btScalar desiredMotorVel = m_targetAngMotorVelocity;
|
||||||
|
btScalar motor_relvel = desiredMotorVel - projRelVel;
|
||||||
|
|
||||||
|
btScalar angImpulse = m_kAngle * motor_relvel;
|
||||||
|
// clamp accumulated impulse
|
||||||
|
btScalar new_acc = m_accumulatedAngMotorImpulse + btFabs(angImpulse);
|
||||||
|
if(new_acc > m_maxAngMotorForce)
|
||||||
|
{
|
||||||
|
new_acc = m_maxAngMotorForce;
|
||||||
|
}
|
||||||
|
btScalar del = new_acc - m_accumulatedAngMotorImpulse;
|
||||||
|
if(angImpulse < btScalar(0.0))
|
||||||
|
{
|
||||||
|
angImpulse = -del;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
angImpulse = del;
|
||||||
|
}
|
||||||
|
m_accumulatedAngMotorImpulse = new_acc;
|
||||||
|
// apply clamped impulse
|
||||||
|
btVector3 motorImp = angImpulse * axisA;
|
||||||
|
m_rbA.applyTorqueImpulse(motorImp);
|
||||||
|
m_rbB.applyTorqueImpulse(-motorImp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // btSliderConstraint::solveConstraint()
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void btSliderConstraint::calculateTransforms(void){
|
||||||
|
if(m_useLinearReferenceFrameA)
|
||||||
|
{
|
||||||
|
m_calculatedTransformA = m_rbA.getCenterOfMassTransform() * m_frameInA;
|
||||||
|
m_calculatedTransformB = m_rbB.getCenterOfMassTransform() * m_frameInB;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_calculatedTransformA = m_rbB.getCenterOfMassTransform() * m_frameInB;
|
||||||
|
m_calculatedTransformB = m_rbA.getCenterOfMassTransform() * m_frameInA;
|
||||||
|
}
|
||||||
|
m_realPivotAInW = m_calculatedTransformA.getOrigin();
|
||||||
|
m_realPivotBInW = m_calculatedTransformB.getOrigin();
|
||||||
|
m_sliderAxis = m_calculatedTransformA.getBasis().getColumn(0); // along X
|
||||||
|
m_delta = m_realPivotBInW - m_realPivotAInW;
|
||||||
|
m_projPivotInW = m_realPivotAInW + m_sliderAxis.dot(m_delta) * m_sliderAxis;
|
||||||
|
btVector3 normalWorld;
|
||||||
|
int i;
|
||||||
|
//linear part
|
||||||
|
for(i = 0; i < 3; i++)
|
||||||
|
{
|
||||||
|
normalWorld = m_calculatedTransformA.getBasis().getColumn(i);
|
||||||
|
m_depth[i] = m_delta.dot(normalWorld);
|
||||||
|
}
|
||||||
|
} // btSliderConstraint::calculateTransforms()
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void btSliderConstraint::testLinLimits(void)
|
||||||
|
{
|
||||||
|
m_solveLinLim = false;
|
||||||
|
m_linPos = m_depth[0];
|
||||||
|
if(m_lowerLinLimit <= m_upperLinLimit)
|
||||||
|
{
|
||||||
|
if(m_depth[0] > m_upperLinLimit)
|
||||||
|
{
|
||||||
|
m_depth[0] -= m_upperLinLimit;
|
||||||
|
m_solveLinLim = true;
|
||||||
|
}
|
||||||
|
else if(m_depth[0] < m_lowerLinLimit)
|
||||||
|
{
|
||||||
|
m_depth[0] -= m_lowerLinLimit;
|
||||||
|
m_solveLinLim = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_depth[0] = btScalar(0.);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_depth[0] = btScalar(0.);
|
||||||
|
}
|
||||||
|
} // btSliderConstraint::testLinLimits()
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
void btSliderConstraint::testAngLimits(void)
|
||||||
|
{
|
||||||
|
m_angDepth = btScalar(0.);
|
||||||
|
m_solveAngLim = false;
|
||||||
|
if(m_lowerAngLimit <= m_upperAngLimit)
|
||||||
|
{
|
||||||
|
const btVector3 axisA0 = m_calculatedTransformA.getBasis().getColumn(1);
|
||||||
|
const btVector3 axisA1 = m_calculatedTransformA.getBasis().getColumn(2);
|
||||||
|
const btVector3 axisB0 = m_calculatedTransformB.getBasis().getColumn(1);
|
||||||
|
btScalar rot = btAtan2Fast(axisB0.dot(axisA1), axisB0.dot(axisA0));
|
||||||
|
if(rot < m_lowerAngLimit)
|
||||||
|
{
|
||||||
|
m_angDepth = rot - m_lowerAngLimit;
|
||||||
|
m_solveAngLim = true;
|
||||||
|
}
|
||||||
|
else if(rot > m_upperAngLimit)
|
||||||
|
{
|
||||||
|
m_angDepth = rot - m_upperAngLimit;
|
||||||
|
m_solveAngLim = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // btSliderConstraint::testAngLimits()
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
btVector3 btSliderConstraint::getAncorInA(void)
|
||||||
|
{
|
||||||
|
btVector3 ancorInA;
|
||||||
|
ancorInA = m_realPivotAInW + (m_lowerLinLimit + m_upperLinLimit) * btScalar(0.5) * m_sliderAxis;
|
||||||
|
ancorInA = m_rbA.getCenterOfMassTransform().inverse() * ancorInA;
|
||||||
|
return ancorInA;
|
||||||
|
} // btSliderConstraint::getAncorInA()
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
btVector3 btSliderConstraint::getAncorInB(void)
|
||||||
|
{
|
||||||
|
btVector3 ancorInB;
|
||||||
|
ancorInB = m_frameInB.getOrigin();
|
||||||
|
return ancorInB;
|
||||||
|
} // btSliderConstraint::getAncorInB();
|
218
extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.h
vendored
Normal file
218
extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.h
vendored
Normal file
@ -0,0 +1,218 @@
|
|||||||
|
/*
|
||||||
|
Bullet Continuous Collision Detection and Physics Library
|
||||||
|
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Added by Roman Ponomarev (rponom@gmail.com)
|
||||||
|
April 04, 2008
|
||||||
|
|
||||||
|
TODO:
|
||||||
|
- add clamping od accumulated impulse to improve stability
|
||||||
|
- add conversion for ODE constraint solver
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SLIDER_CONSTRAINT_H
|
||||||
|
#define SLIDER_CONSTRAINT_H
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "LinearMath/btVector3.h"
|
||||||
|
#include "btJacobianEntry.h"
|
||||||
|
#include "btTypedConstraint.h"
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class btRigidBody;
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#define SLIDER_CONSTRAINT_DEF_SOFTNESS (btScalar(1.0))
|
||||||
|
#define SLIDER_CONSTRAINT_DEF_DAMPING (btScalar(1.0))
|
||||||
|
#define SLIDER_CONSTRAINT_DEF_RESTITUTION (btScalar(0.7))
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class btSliderConstraint : public btTypedConstraint
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
btTransform m_frameInA;
|
||||||
|
btTransform m_frameInB;
|
||||||
|
// use frameA fo define limits, if true
|
||||||
|
bool m_useLinearReferenceFrameA;
|
||||||
|
// linear limits
|
||||||
|
btScalar m_lowerLinLimit;
|
||||||
|
btScalar m_upperLinLimit;
|
||||||
|
// angular limits
|
||||||
|
btScalar m_lowerAngLimit;
|
||||||
|
btScalar m_upperAngLimit;
|
||||||
|
// softness, restitution and damping for different cases
|
||||||
|
// DirLin - moving inside linear limits
|
||||||
|
// LimLin - hitting linear limit
|
||||||
|
// DirAng - moving inside angular limits
|
||||||
|
// LimAng - hitting angular limit
|
||||||
|
// OrthoLin, OrthoAng - against constraint axis
|
||||||
|
btScalar m_softnessDirLin;
|
||||||
|
btScalar m_restitutionDirLin;
|
||||||
|
btScalar m_dampingDirLin;
|
||||||
|
btScalar m_softnessDirAng;
|
||||||
|
btScalar m_restitutionDirAng;
|
||||||
|
btScalar m_dampingDirAng;
|
||||||
|
btScalar m_softnessLimLin;
|
||||||
|
btScalar m_restitutionLimLin;
|
||||||
|
btScalar m_dampingLimLin;
|
||||||
|
btScalar m_softnessLimAng;
|
||||||
|
btScalar m_restitutionLimAng;
|
||||||
|
btScalar m_dampingLimAng;
|
||||||
|
btScalar m_softnessOrthoLin;
|
||||||
|
btScalar m_restitutionOrthoLin;
|
||||||
|
btScalar m_dampingOrthoLin;
|
||||||
|
btScalar m_softnessOrthoAng;
|
||||||
|
btScalar m_restitutionOrthoAng;
|
||||||
|
btScalar m_dampingOrthoAng;
|
||||||
|
|
||||||
|
// for interlal use
|
||||||
|
bool m_solveLinLim;
|
||||||
|
bool m_solveAngLim;
|
||||||
|
|
||||||
|
btJacobianEntry m_jacLin[3];
|
||||||
|
btScalar m_jacLinDiagABInv[3];
|
||||||
|
|
||||||
|
btJacobianEntry m_jacAng[3];
|
||||||
|
|
||||||
|
btScalar m_timeStep;
|
||||||
|
btTransform m_calculatedTransformA;
|
||||||
|
btTransform m_calculatedTransformB;
|
||||||
|
|
||||||
|
btVector3 m_sliderAxis;
|
||||||
|
btVector3 m_realPivotAInW;
|
||||||
|
btVector3 m_realPivotBInW;
|
||||||
|
btVector3 m_projPivotInW;
|
||||||
|
btVector3 m_delta;
|
||||||
|
btVector3 m_depth;
|
||||||
|
btVector3 m_relPosA;
|
||||||
|
btVector3 m_relPosB;
|
||||||
|
|
||||||
|
btScalar m_linPos;
|
||||||
|
|
||||||
|
btScalar m_angDepth;
|
||||||
|
btScalar m_kAngle;
|
||||||
|
|
||||||
|
bool m_poweredLinMotor;
|
||||||
|
btScalar m_targetLinMotorVelocity;
|
||||||
|
btScalar m_maxLinMotorForce;
|
||||||
|
btScalar m_accumulatedLinMotorImpulse;
|
||||||
|
|
||||||
|
bool m_poweredAngMotor;
|
||||||
|
btScalar m_targetAngMotorVelocity;
|
||||||
|
btScalar m_maxAngMotorForce;
|
||||||
|
btScalar m_accumulatedAngMotorImpulse;
|
||||||
|
|
||||||
|
//------------------------
|
||||||
|
void initParams();
|
||||||
|
public:
|
||||||
|
// constructors
|
||||||
|
btSliderConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB ,bool useLinearReferenceFrameA);
|
||||||
|
btSliderConstraint();
|
||||||
|
// overrides
|
||||||
|
virtual void buildJacobian();
|
||||||
|
virtual void solveConstraint(btScalar timeStep);
|
||||||
|
// access
|
||||||
|
const btRigidBody& getRigidBodyA() const { return m_rbA; }
|
||||||
|
const btRigidBody& getRigidBodyB() const { return m_rbB; }
|
||||||
|
const btTransform & getCalculatedTransformA() const { return m_calculatedTransformA; }
|
||||||
|
const btTransform & getCalculatedTransformB() const { return m_calculatedTransformB; }
|
||||||
|
const btTransform & getFrameOffsetA() const { return m_frameInA; }
|
||||||
|
const btTransform & getFrameOffsetB() const { return m_frameInB; }
|
||||||
|
btTransform & getFrameOffsetA() { return m_frameInA; }
|
||||||
|
btTransform & getFrameOffsetB() { return m_frameInB; }
|
||||||
|
btScalar getLowerLinLimit() { return m_lowerLinLimit; }
|
||||||
|
void setLowerLinLimit(btScalar lowerLimit) { m_lowerLinLimit = lowerLimit; }
|
||||||
|
btScalar getUpperLinLimit() { return m_upperLinLimit; }
|
||||||
|
void setUpperLinLimit(btScalar upperLimit) { m_upperLinLimit = upperLimit; }
|
||||||
|
btScalar getLowerAngLimit() { return m_lowerAngLimit; }
|
||||||
|
void setLowerAngLimit(btScalar lowerLimit) { m_lowerAngLimit = lowerLimit; }
|
||||||
|
btScalar getUpperAngLimit() { return m_upperAngLimit; }
|
||||||
|
void setUpperAngLimit(btScalar upperLimit) { m_upperAngLimit = upperLimit; }
|
||||||
|
bool getUseLinearReferenceFrameA() { return m_useLinearReferenceFrameA; }
|
||||||
|
btScalar getSoftnessDirLin() { return m_softnessDirLin; }
|
||||||
|
btScalar getRestitutionDirLin() { return m_restitutionDirLin; }
|
||||||
|
btScalar getDampingDirLin() { return m_dampingDirLin ; }
|
||||||
|
btScalar getSoftnessDirAng() { return m_softnessDirAng; }
|
||||||
|
btScalar getRestitutionDirAng() { return m_restitutionDirAng; }
|
||||||
|
btScalar getDampingDirAng() { return m_dampingDirAng; }
|
||||||
|
btScalar getSoftnessLimLin() { return m_softnessLimLin; }
|
||||||
|
btScalar getRestitutionLimLin() { return m_restitutionLimLin; }
|
||||||
|
btScalar getDampingLimLin() { return m_dampingLimLin; }
|
||||||
|
btScalar getSoftnessLimAng() { return m_softnessLimAng; }
|
||||||
|
btScalar getRestitutionLimAng() { return m_restitutionLimAng; }
|
||||||
|
btScalar getDampingLimAng() { return m_dampingLimAng; }
|
||||||
|
btScalar getSoftnessOrthoLin() { return m_softnessOrthoLin; }
|
||||||
|
btScalar getRestitutionOrthoLin() { return m_restitutionOrthoLin; }
|
||||||
|
btScalar getDampingOrthoLin() { return m_dampingOrthoLin; }
|
||||||
|
btScalar getSoftnessOrthoAng() { return m_softnessOrthoAng; }
|
||||||
|
btScalar getRestitutionOrthoAng() { return m_restitutionOrthoAng; }
|
||||||
|
btScalar getDampingOrthoAng() { return m_dampingOrthoAng; }
|
||||||
|
void setSoftnessDirLin(btScalar softnessDirLin) { m_softnessDirLin = softnessDirLin; }
|
||||||
|
void setRestitutionDirLin(btScalar restitutionDirLin) { m_restitutionDirLin = restitutionDirLin; }
|
||||||
|
void setDampingDirLin(btScalar dampingDirLin) { m_dampingDirLin = dampingDirLin; }
|
||||||
|
void setSoftnessDirAng(btScalar softnessDirAng) { m_softnessDirAng = softnessDirAng; }
|
||||||
|
void setRestitutionDirAng(btScalar restitutionDirAng) { m_restitutionDirAng = restitutionDirAng; }
|
||||||
|
void setDampingDirAng(btScalar dampingDirAng) { m_dampingDirAng = dampingDirAng; }
|
||||||
|
void setSoftnessLimLin(btScalar softnessLimLin) { m_softnessLimLin = softnessLimLin; }
|
||||||
|
void setRestitutionLimLin(btScalar restitutionLimLin) { m_restitutionLimLin = restitutionLimLin; }
|
||||||
|
void setDampingLimLin(btScalar dampingLimLin) { m_dampingLimLin = dampingLimLin; }
|
||||||
|
void setSoftnessLimAng(btScalar softnessLimAng) { m_softnessLimAng = softnessLimAng; }
|
||||||
|
void setRestitutionLimAng(btScalar restitutionLimAng) { m_restitutionLimAng = restitutionLimAng; }
|
||||||
|
void setDampingLimAng(btScalar dampingLimAng) { m_dampingLimAng = dampingLimAng; }
|
||||||
|
void setSoftnessOrthoLin(btScalar softnessOrthoLin) { m_softnessOrthoLin = softnessOrthoLin; }
|
||||||
|
void setRestitutionOrthoLin(btScalar restitutionOrthoLin) { m_restitutionOrthoLin = restitutionOrthoLin; }
|
||||||
|
void setDampingOrthoLin(btScalar dampingOrthoLin) { m_dampingOrthoLin = dampingOrthoLin; }
|
||||||
|
void setSoftnessOrthoAng(btScalar softnessOrthoAng) { m_softnessOrthoAng = softnessOrthoAng; }
|
||||||
|
void setRestitutionOrthoAng(btScalar restitutionOrthoAng) { m_restitutionOrthoAng = restitutionOrthoAng; }
|
||||||
|
void setDampingOrthoAng(btScalar dampingOrthoAng) { m_dampingOrthoAng = dampingOrthoAng; }
|
||||||
|
void setPoweredLinMotor(bool onOff) { m_poweredLinMotor = onOff; }
|
||||||
|
bool getPoweredLinMotor() { return m_poweredLinMotor; }
|
||||||
|
void setTargetLinMotorVelocity(btScalar targetLinMotorVelocity) { m_targetLinMotorVelocity = targetLinMotorVelocity; }
|
||||||
|
btScalar getTargetLinMotorVelocity() { return m_targetLinMotorVelocity; }
|
||||||
|
void setMaxLinMotorForce(btScalar maxLinMotorForce) { m_maxLinMotorForce = maxLinMotorForce; }
|
||||||
|
btScalar getMaxLinMotorForce() { return m_maxLinMotorForce; }
|
||||||
|
void setPoweredAngMotor(bool onOff) { m_poweredAngMotor = onOff; }
|
||||||
|
bool getPoweredAngMotor() { return m_poweredAngMotor; }
|
||||||
|
void setTargetAngMotorVelocity(btScalar targetAngMotorVelocity) { m_targetAngMotorVelocity = targetAngMotorVelocity; }
|
||||||
|
btScalar getTargetAngMotorVelocity() { return m_targetAngMotorVelocity; }
|
||||||
|
void setMaxAngMotorForce(btScalar maxAngMotorForce) { m_maxAngMotorForce = maxAngMotorForce; }
|
||||||
|
btScalar getMaxAngMotorForce() { return m_maxAngMotorForce; }
|
||||||
|
btScalar getLinearPos() { return m_linPos; }
|
||||||
|
|
||||||
|
// access for ODE solver
|
||||||
|
bool getSolveLinLimit() { return m_solveLinLim; }
|
||||||
|
btScalar getLinDepth() { return m_depth[0]; }
|
||||||
|
bool getSolveAngLimit() { return m_solveAngLim; }
|
||||||
|
btScalar getAngDepth() { return m_angDepth; }
|
||||||
|
// internal
|
||||||
|
void buildJacobianInt(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB);
|
||||||
|
void solveConstraintInt(btRigidBody& rbA, btRigidBody& rbB);
|
||||||
|
// shared code used by ODE solver
|
||||||
|
void calculateTransforms(void);
|
||||||
|
void testLinLimits(void);
|
||||||
|
void testAngLimits(void);
|
||||||
|
// access for PE Solver
|
||||||
|
btVector3 getAncorInA(void);
|
||||||
|
btVector3 getAncorInB(void);
|
||||||
|
};
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#endif //SLIDER_CONSTRAINT_H
|
||||||
|
|
193
extern/bullet2/src/BulletDynamics/Dynamics/btContinuousDynamicsWorld.cpp
vendored
Normal file
193
extern/bullet2/src/BulletDynamics/Dynamics/btContinuousDynamicsWorld.cpp
vendored
Normal file
@ -0,0 +1,193 @@
|
|||||||
|
/*
|
||||||
|
Bullet Continuous Collision Detection and Physics Library
|
||||||
|
Copyright (c) 2003-2007 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "btContinuousDynamicsWorld.h"
|
||||||
|
#include "LinearMath/btQuickprof.h"
|
||||||
|
|
||||||
|
//collision detection
|
||||||
|
#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
|
||||||
|
#include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h"
|
||||||
|
#include "BulletCollision/CollisionShapes/btCollisionShape.h"
|
||||||
|
#include "BulletCollision/CollisionDispatch/btSimulationIslandManager.h"
|
||||||
|
|
||||||
|
//rigidbody & constraints
|
||||||
|
#include "BulletDynamics/Dynamics/btRigidBody.h"
|
||||||
|
#include "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h"
|
||||||
|
#include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h"
|
||||||
|
#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
btContinuousDynamicsWorld::btContinuousDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration)
|
||||||
|
:btDiscreteDynamicsWorld(dispatcher,pairCache,constraintSolver,collisionConfiguration)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
btContinuousDynamicsWorld::~btContinuousDynamicsWorld()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void btContinuousDynamicsWorld::internalSingleStepSimulation( btScalar timeStep)
|
||||||
|
{
|
||||||
|
|
||||||
|
startProfiling(timeStep);
|
||||||
|
|
||||||
|
|
||||||
|
///update aabbs information
|
||||||
|
updateAabbs();
|
||||||
|
//static int frame=0;
|
||||||
|
// printf("frame %d\n",frame++);
|
||||||
|
|
||||||
|
///apply gravity, predict motion
|
||||||
|
predictUnconstraintMotion(timeStep);
|
||||||
|
|
||||||
|
btDispatcherInfo& dispatchInfo = getDispatchInfo();
|
||||||
|
|
||||||
|
dispatchInfo.m_timeStep = timeStep;
|
||||||
|
dispatchInfo.m_stepCount = 0;
|
||||||
|
dispatchInfo.m_debugDraw = getDebugDrawer();
|
||||||
|
|
||||||
|
///perform collision detection
|
||||||
|
performDiscreteCollisionDetection();
|
||||||
|
|
||||||
|
calculateSimulationIslands();
|
||||||
|
|
||||||
|
|
||||||
|
getSolverInfo().m_timeStep = timeStep;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
///solve contact and other joint constraints
|
||||||
|
solveConstraints(getSolverInfo());
|
||||||
|
|
||||||
|
///CallbackTriggers();
|
||||||
|
calculateTimeOfImpacts(timeStep);
|
||||||
|
|
||||||
|
btScalar toi = dispatchInfo.m_timeOfImpact;
|
||||||
|
// if (toi < 1.f)
|
||||||
|
// printf("toi = %f\n",toi);
|
||||||
|
if (toi < 0.f)
|
||||||
|
printf("toi = %f\n",toi);
|
||||||
|
|
||||||
|
|
||||||
|
///integrate transforms
|
||||||
|
integrateTransforms(timeStep * toi);
|
||||||
|
|
||||||
|
///update vehicle simulation
|
||||||
|
updateVehicles(timeStep);
|
||||||
|
|
||||||
|
|
||||||
|
updateActivationState( timeStep );
|
||||||
|
|
||||||
|
if(0 != m_internalTickCallback) {
|
||||||
|
(*m_internalTickCallback)(this, timeStep);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void btContinuousDynamicsWorld::calculateTimeOfImpacts(btScalar timeStep)
|
||||||
|
{
|
||||||
|
///these should be 'temporal' aabbs!
|
||||||
|
updateTemporalAabbs(timeStep);
|
||||||
|
|
||||||
|
///'toi' is the global smallest time of impact. However, we just calculate the time of impact for each object individually.
|
||||||
|
///so we handle the case moving versus static properly, and we cheat for moving versus moving
|
||||||
|
btScalar toi = 1.f;
|
||||||
|
|
||||||
|
|
||||||
|
btDispatcherInfo& dispatchInfo = getDispatchInfo();
|
||||||
|
dispatchInfo.m_timeStep = timeStep;
|
||||||
|
dispatchInfo.m_timeOfImpact = 1.f;
|
||||||
|
dispatchInfo.m_stepCount = 0;
|
||||||
|
dispatchInfo.m_dispatchFunc = btDispatcherInfo::DISPATCH_CONTINUOUS;
|
||||||
|
|
||||||
|
///calculate time of impact for overlapping pairs
|
||||||
|
|
||||||
|
|
||||||
|
btDispatcher* dispatcher = getDispatcher();
|
||||||
|
if (dispatcher)
|
||||||
|
dispatcher->dispatchAllCollisionPairs(m_broadphasePairCache->getOverlappingPairCache(),dispatchInfo,m_dispatcher1);
|
||||||
|
|
||||||
|
toi = dispatchInfo.m_timeOfImpact;
|
||||||
|
|
||||||
|
dispatchInfo.m_dispatchFunc = btDispatcherInfo::DISPATCH_DISCRETE;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void btContinuousDynamicsWorld::updateTemporalAabbs(btScalar timeStep)
|
||||||
|
{
|
||||||
|
|
||||||
|
btVector3 temporalAabbMin,temporalAabbMax;
|
||||||
|
|
||||||
|
for ( int i=0;i<m_collisionObjects.size();i++)
|
||||||
|
{
|
||||||
|
btCollisionObject* colObj = m_collisionObjects[i];
|
||||||
|
|
||||||
|
btRigidBody* body = btRigidBody::upcast(colObj);
|
||||||
|
if (body)
|
||||||
|
{
|
||||||
|
body->getCollisionShape()->getAabb(m_collisionObjects[i]->getWorldTransform(),temporalAabbMin,temporalAabbMax);
|
||||||
|
const btVector3& linvel = body->getLinearVelocity();
|
||||||
|
|
||||||
|
//make the AABB temporal
|
||||||
|
btScalar temporalAabbMaxx = temporalAabbMax.getX();
|
||||||
|
btScalar temporalAabbMaxy = temporalAabbMax.getY();
|
||||||
|
btScalar temporalAabbMaxz = temporalAabbMax.getZ();
|
||||||
|
btScalar temporalAabbMinx = temporalAabbMin.getX();
|
||||||
|
btScalar temporalAabbMiny = temporalAabbMin.getY();
|
||||||
|
btScalar temporalAabbMinz = temporalAabbMin.getZ();
|
||||||
|
|
||||||
|
// add linear motion
|
||||||
|
btVector3 linMotion = linvel*timeStep;
|
||||||
|
|
||||||
|
if (linMotion.x() > 0.f)
|
||||||
|
temporalAabbMaxx += linMotion.x();
|
||||||
|
else
|
||||||
|
temporalAabbMinx += linMotion.x();
|
||||||
|
if (linMotion.y() > 0.f)
|
||||||
|
temporalAabbMaxy += linMotion.y();
|
||||||
|
else
|
||||||
|
temporalAabbMiny += linMotion.y();
|
||||||
|
if (linMotion.z() > 0.f)
|
||||||
|
temporalAabbMaxz += linMotion.z();
|
||||||
|
else
|
||||||
|
temporalAabbMinz += linMotion.z();
|
||||||
|
|
||||||
|
//add conservative angular motion
|
||||||
|
btScalar angularMotion(0);// = angvel.length() * GetAngularMotionDisc() * timeStep;
|
||||||
|
btVector3 angularMotion3d(angularMotion,angularMotion,angularMotion);
|
||||||
|
temporalAabbMin = btVector3(temporalAabbMinx,temporalAabbMiny,temporalAabbMinz);
|
||||||
|
temporalAabbMax = btVector3(temporalAabbMaxx,temporalAabbMaxy,temporalAabbMaxz);
|
||||||
|
|
||||||
|
temporalAabbMin -= angularMotion3d;
|
||||||
|
temporalAabbMax += angularMotion3d;
|
||||||
|
|
||||||
|
m_broadphasePairCache->setAabb(body->getBroadphaseHandle(),temporalAabbMin,temporalAabbMax,m_dispatcher1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//update aabb (of all moved objects)
|
||||||
|
|
||||||
|
m_broadphasePairCache->calculateOverlappingPairs(m_dispatcher1);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
46
extern/bullet2/src/BulletDynamics/Dynamics/btContinuousDynamicsWorld.h
vendored
Normal file
46
extern/bullet2/src/BulletDynamics/Dynamics/btContinuousDynamicsWorld.h
vendored
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
Bullet Continuous Collision Detection and Physics Library
|
||||||
|
Copyright (c) 2003-2007 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef BT_CONTINUOUS_DYNAMICS_WORLD_H
|
||||||
|
#define BT_CONTINUOUS_DYNAMICS_WORLD_H
|
||||||
|
|
||||||
|
#include "btDiscreteDynamicsWorld.h"
|
||||||
|
|
||||||
|
///btContinuousDynamicsWorld adds optional (per object) continuous collision detection for fast moving objects to the btDiscreteDynamicsWorld.
|
||||||
|
///This copes with fast moving objects that otherwise would tunnel/miss collisions.
|
||||||
|
///Under construction, don't use yet! Please use btDiscreteDynamicsWorld instead.
|
||||||
|
class btContinuousDynamicsWorld : public btDiscreteDynamicsWorld
|
||||||
|
{
|
||||||
|
|
||||||
|
void updateTemporalAabbs(btScalar timeStep);
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
btContinuousDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration);
|
||||||
|
virtual ~btContinuousDynamicsWorld();
|
||||||
|
|
||||||
|
///time stepping with calculation of time of impact for selected fast moving objects
|
||||||
|
virtual void internalSingleStepSimulation( btScalar timeStep);
|
||||||
|
|
||||||
|
virtual void calculateTimeOfImpacts(btScalar timeStep);
|
||||||
|
|
||||||
|
virtual btDynamicsWorldType getWorldType() const
|
||||||
|
{
|
||||||
|
return BT_CONTINUOUS_DYNAMICS_WORLD;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //BT_CONTINUOUS_DYNAMICS_WORLD_H
|
1174
extern/bullet2/src/LinearMath/btConvexHull.cpp
vendored
Normal file
1174
extern/bullet2/src/LinearMath/btConvexHull.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
245
extern/bullet2/src/LinearMath/btConvexHull.h
vendored
Normal file
245
extern/bullet2/src/LinearMath/btConvexHull.h
vendored
Normal file
@ -0,0 +1,245 @@
|
|||||||
|
|
||||||
|
/*
|
||||||
|
Stan Melax Convex Hull Computation
|
||||||
|
Copyright (c) 2008 Stan Melax http://www.melax.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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
///includes modifications/improvements by John Ratcliff, see BringOutYourDead below.
|
||||||
|
|
||||||
|
#ifndef CD_HULL_H
|
||||||
|
#define CD_HULL_H
|
||||||
|
|
||||||
|
#include "LinearMath/btVector3.h"
|
||||||
|
#include "LinearMath/btAlignedObjectArray.h"
|
||||||
|
|
||||||
|
typedef btAlignedObjectArray<unsigned int> TUIntArray;
|
||||||
|
|
||||||
|
class HullResult
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
HullResult(void)
|
||||||
|
{
|
||||||
|
mPolygons = true;
|
||||||
|
mNumOutputVertices = 0;
|
||||||
|
mNumFaces = 0;
|
||||||
|
mNumIndices = 0;
|
||||||
|
}
|
||||||
|
bool mPolygons; // true if indices represents polygons, false indices are triangles
|
||||||
|
unsigned int mNumOutputVertices; // number of vertices in the output hull
|
||||||
|
btAlignedObjectArray<btVector3> m_OutputVertices; // array of vertices
|
||||||
|
unsigned int mNumFaces; // the number of faces produced
|
||||||
|
unsigned int mNumIndices; // the total number of indices
|
||||||
|
btAlignedObjectArray<unsigned int> m_Indices; // pointer to indices.
|
||||||
|
|
||||||
|
// If triangles, then indices are array indexes into the vertex list.
|
||||||
|
// If polygons, indices are in the form (number of points in face) (p1, p2, p3, ..) etc..
|
||||||
|
};
|
||||||
|
|
||||||
|
enum HullFlag
|
||||||
|
{
|
||||||
|
QF_TRIANGLES = (1<<0), // report results as triangles, not polygons.
|
||||||
|
QF_REVERSE_ORDER = (1<<1), // reverse order of the triangle indices.
|
||||||
|
QF_DEFAULT = QF_TRIANGLES
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class HullDesc
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
HullDesc(void)
|
||||||
|
{
|
||||||
|
mFlags = QF_DEFAULT;
|
||||||
|
mVcount = 0;
|
||||||
|
mVertices = 0;
|
||||||
|
mVertexStride = sizeof(btVector3);
|
||||||
|
mNormalEpsilon = 0.001f;
|
||||||
|
mMaxVertices = 4096; // maximum number of points to be considered for a convex hull.
|
||||||
|
mMaxFaces = 4096;
|
||||||
|
};
|
||||||
|
|
||||||
|
HullDesc(HullFlag flag,
|
||||||
|
unsigned int vcount,
|
||||||
|
const btVector3 *vertices,
|
||||||
|
unsigned int stride = sizeof(btVector3))
|
||||||
|
{
|
||||||
|
mFlags = flag;
|
||||||
|
mVcount = vcount;
|
||||||
|
mVertices = vertices;
|
||||||
|
mVertexStride = stride;
|
||||||
|
mNormalEpsilon = btScalar(0.001);
|
||||||
|
mMaxVertices = 4096;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HasHullFlag(HullFlag flag) const
|
||||||
|
{
|
||||||
|
if ( mFlags & flag ) return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetHullFlag(HullFlag flag)
|
||||||
|
{
|
||||||
|
mFlags|=flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClearHullFlag(HullFlag flag)
|
||||||
|
{
|
||||||
|
mFlags&=~flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int mFlags; // flags to use when generating the convex hull.
|
||||||
|
unsigned int mVcount; // number of vertices in the input point cloud
|
||||||
|
const btVector3 *mVertices; // the array of vertices.
|
||||||
|
unsigned int mVertexStride; // the stride of each vertex, in bytes.
|
||||||
|
btScalar mNormalEpsilon; // the epsilon for removing duplicates. This is a normalized value, if normalized bit is on.
|
||||||
|
unsigned int mMaxVertices; // maximum number of vertices to be considered for the hull!
|
||||||
|
unsigned int mMaxFaces;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum HullError
|
||||||
|
{
|
||||||
|
QE_OK, // success!
|
||||||
|
QE_FAIL // failed.
|
||||||
|
};
|
||||||
|
|
||||||
|
class btPlane
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
btVector3 normal;
|
||||||
|
btScalar dist; // distance below origin - the D from plane equasion Ax+By+Cz+D=0
|
||||||
|
btPlane(const btVector3 &n,btScalar d):normal(n),dist(d){}
|
||||||
|
btPlane():normal(),dist(0){}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class ConvexH
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
class HalfEdge
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
short ea; // the other half of the edge (index into edges list)
|
||||||
|
unsigned char v; // the vertex at the start of this edge (index into vertices list)
|
||||||
|
unsigned char p; // the facet on which this edge lies (index into facets list)
|
||||||
|
HalfEdge(){}
|
||||||
|
HalfEdge(short _ea,unsigned char _v, unsigned char _p):ea(_ea),v(_v),p(_p){}
|
||||||
|
};
|
||||||
|
ConvexH()
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
i=0;
|
||||||
|
}
|
||||||
|
~ConvexH()
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
i=0;
|
||||||
|
}
|
||||||
|
btAlignedObjectArray<btVector3> vertices;
|
||||||
|
btAlignedObjectArray<HalfEdge> edges;
|
||||||
|
btAlignedObjectArray<btPlane> facets;
|
||||||
|
ConvexH(int vertices_size,int edges_size,int facets_size);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class int4
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
int x,y,z,w;
|
||||||
|
int4(){};
|
||||||
|
int4(int _x,int _y, int _z,int _w){x=_x;y=_y;z=_z;w=_w;}
|
||||||
|
const int& operator[](int i) const {return (&x)[i];}
|
||||||
|
int& operator[](int i) {return (&x)[i];}
|
||||||
|
};
|
||||||
|
|
||||||
|
class PHullResult
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
PHullResult(void)
|
||||||
|
{
|
||||||
|
mVcount = 0;
|
||||||
|
mIndexCount = 0;
|
||||||
|
mFaceCount = 0;
|
||||||
|
mVertices = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int mVcount;
|
||||||
|
unsigned int mIndexCount;
|
||||||
|
unsigned int mFaceCount;
|
||||||
|
btVector3* mVertices;
|
||||||
|
TUIntArray m_Indices;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
///The HullLibrary class can create a convex hull from a collection of vertices, using the ComputeHull method.
|
||||||
|
///The btShapeHull class uses this HullLibrary to create a approximate convex mesh given a general (non-polyhedral) convex shape.
|
||||||
|
class HullLibrary
|
||||||
|
{
|
||||||
|
|
||||||
|
btAlignedObjectArray<class Tri*> m_tris;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
btAlignedObjectArray<int> m_vertexIndexMapping;
|
||||||
|
|
||||||
|
|
||||||
|
HullError CreateConvexHull(const HullDesc& desc, // describes the input request
|
||||||
|
HullResult& result); // contains the resulst
|
||||||
|
HullError ReleaseResult(HullResult &result); // release memory allocated for this result, we are done with it.
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
bool ComputeHull(unsigned int vcount,const btVector3 *vertices,PHullResult &result,unsigned int vlimit);
|
||||||
|
|
||||||
|
class Tri* allocateTriangle(int a,int b,int c);
|
||||||
|
void deAllocateTriangle(Tri*);
|
||||||
|
void b2bfix(Tri* s,Tri*t);
|
||||||
|
|
||||||
|
void removeb2b(Tri* s,Tri*t);
|
||||||
|
|
||||||
|
void checkit(Tri *t);
|
||||||
|
|
||||||
|
Tri* extrudable(btScalar epsilon);
|
||||||
|
|
||||||
|
int calchull(btVector3 *verts,int verts_count, TUIntArray& tris_out, int &tris_count,int vlimit);
|
||||||
|
|
||||||
|
int calchullgen(btVector3 *verts,int verts_count, int vlimit);
|
||||||
|
|
||||||
|
int4 FindSimplex(btVector3 *verts,int verts_count,btAlignedObjectArray<int> &allow);
|
||||||
|
|
||||||
|
class ConvexH* ConvexHCrop(ConvexH& convex,const btPlane& slice);
|
||||||
|
|
||||||
|
void extrude(class Tri* t0,int v);
|
||||||
|
|
||||||
|
ConvexH* test_cube();
|
||||||
|
|
||||||
|
//BringOutYourDead (John Ratcliff): When you create a convex hull you hand it a large input set of vertices forming a 'point cloud'.
|
||||||
|
//After the hull is generated it give you back a set of polygon faces which index the *original* point cloud.
|
||||||
|
//The thing is, often times, there are many 'dead vertices' in the point cloud that are on longer referenced by the hull.
|
||||||
|
//The routine 'BringOutYourDead' find only the referenced vertices, copies them to an new buffer, and re-indexes the hull so that it is a minimal representation.
|
||||||
|
void BringOutYourDead(const btVector3* verts,unsigned int vcount, btVector3* overts,unsigned int &ocount,unsigned int* indices,unsigned indexcount);
|
||||||
|
|
||||||
|
bool CleanupVertices(unsigned int svcount,
|
||||||
|
const btVector3* svertices,
|
||||||
|
unsigned int stride,
|
||||||
|
unsigned int &vcount, // output number of vertices
|
||||||
|
btVector3* vertices, // location to store the results.
|
||||||
|
btScalar normalepsilon,
|
||||||
|
btVector3& scale);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
303
extern/bullet2/src/LinearMath/btHashMap.h
vendored
Normal file
303
extern/bullet2/src/LinearMath/btHashMap.h
vendored
Normal file
@ -0,0 +1,303 @@
|
|||||||
|
#ifndef BT_HASH_MAP_H
|
||||||
|
#define BT_HASH_MAP_H
|
||||||
|
|
||||||
|
#include "btAlignedObjectArray.h"
|
||||||
|
|
||||||
|
const int BT_HASH_NULL=0xffffffff;
|
||||||
|
|
||||||
|
template <class Value>
|
||||||
|
class btHashKey
|
||||||
|
{
|
||||||
|
int m_uid;
|
||||||
|
public:
|
||||||
|
|
||||||
|
btHashKey(int uid)
|
||||||
|
:m_uid(uid)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int getUid() const
|
||||||
|
{
|
||||||
|
return m_uid;
|
||||||
|
}
|
||||||
|
|
||||||
|
//to our success
|
||||||
|
SIMD_FORCE_INLINE unsigned int getHash()const
|
||||||
|
{
|
||||||
|
int key = m_uid;
|
||||||
|
// Thomas Wang's hash
|
||||||
|
key += ~(key << 15);
|
||||||
|
key ^= (key >> 10);
|
||||||
|
key += (key << 3);
|
||||||
|
key ^= (key >> 6);
|
||||||
|
key += ~(key << 11);
|
||||||
|
key ^= (key >> 16);
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
btHashKey getKey(const Value& value) const
|
||||||
|
{
|
||||||
|
return btHashKey(value.getUid());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template <class Value>
|
||||||
|
class btHashKeyPtr
|
||||||
|
{
|
||||||
|
int m_uid;
|
||||||
|
public:
|
||||||
|
|
||||||
|
btHashKeyPtr(int uid)
|
||||||
|
:m_uid(uid)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int getUid() const
|
||||||
|
{
|
||||||
|
return m_uid;
|
||||||
|
}
|
||||||
|
|
||||||
|
//to our success
|
||||||
|
SIMD_FORCE_INLINE unsigned int getHash()const
|
||||||
|
{
|
||||||
|
int key = m_uid;
|
||||||
|
// Thomas Wang's hash
|
||||||
|
key += ~(key << 15);
|
||||||
|
key ^= (key >> 10);
|
||||||
|
key += (key << 3);
|
||||||
|
key ^= (key >> 6);
|
||||||
|
key += ~(key << 11);
|
||||||
|
key ^= (key >> 16);
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
btHashKeyPtr getKey(const Value& value) const
|
||||||
|
{
|
||||||
|
return btHashKeyPtr(value->getUid());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
///The btHashMap template class implements a generic and lightweight hashmap.
|
||||||
|
///A basic sample of how to use btHashMap is located in Demos\BasicDemo\main.cpp
|
||||||
|
template <class Key, class Value>
|
||||||
|
class btHashMap
|
||||||
|
{
|
||||||
|
|
||||||
|
btAlignedObjectArray<int> m_hashTable;
|
||||||
|
btAlignedObjectArray<int> m_next;
|
||||||
|
btAlignedObjectArray<Value> m_valueArray;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void growTables(const Key& key)
|
||||||
|
{
|
||||||
|
int newCapacity = m_valueArray.capacity();
|
||||||
|
|
||||||
|
if (m_hashTable.size() < newCapacity)
|
||||||
|
{
|
||||||
|
//grow hashtable and next table
|
||||||
|
int curHashtableSize = m_hashTable.size();
|
||||||
|
|
||||||
|
m_hashTable.resize(newCapacity);
|
||||||
|
m_next.resize(newCapacity);
|
||||||
|
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i= 0; i < newCapacity; ++i)
|
||||||
|
{
|
||||||
|
m_hashTable[i] = BT_HASH_NULL;
|
||||||
|
}
|
||||||
|
for (i = 0; i < newCapacity; ++i)
|
||||||
|
{
|
||||||
|
m_next[i] = BT_HASH_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i=0;i<curHashtableSize;i++)
|
||||||
|
{
|
||||||
|
const Value& value = m_valueArray[i];
|
||||||
|
|
||||||
|
int hashValue = key.getKey(value).getHash() & (m_valueArray.capacity()-1); // New hash value with new mask
|
||||||
|
m_next[i] = m_hashTable[hashValue];
|
||||||
|
m_hashTable[hashValue] = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
void insert(const Key& key, const Value& value) {
|
||||||
|
int hash = key.getHash() & (m_valueArray.capacity()-1);
|
||||||
|
//don't add it if it is already there
|
||||||
|
if (find(key))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int count = m_valueArray.size();
|
||||||
|
int oldCapacity = m_valueArray.capacity();
|
||||||
|
m_valueArray.push_back(value);
|
||||||
|
int newCapacity = m_valueArray.capacity();
|
||||||
|
if (oldCapacity < newCapacity)
|
||||||
|
{
|
||||||
|
growTables(key);
|
||||||
|
//hash with new capacity
|
||||||
|
hash = key.getHash() & (m_valueArray.capacity()-1);
|
||||||
|
}
|
||||||
|
m_next[count] = m_hashTable[hash];
|
||||||
|
m_hashTable[hash] = count;
|
||||||
|
}
|
||||||
|
|
||||||
|
void remove(const Key& key) {
|
||||||
|
|
||||||
|
int hash = key.getHash() & (m_valueArray.capacity()-1);
|
||||||
|
|
||||||
|
int pairIndex = findIndex(key);
|
||||||
|
|
||||||
|
if (pairIndex ==BT_HASH_NULL)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove the pair from the hash table.
|
||||||
|
int index = m_hashTable[hash];
|
||||||
|
btAssert(index != BT_HASH_NULL);
|
||||||
|
|
||||||
|
int previous = BT_HASH_NULL;
|
||||||
|
while (index != pairIndex)
|
||||||
|
{
|
||||||
|
previous = index;
|
||||||
|
index = m_next[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (previous != BT_HASH_NULL)
|
||||||
|
{
|
||||||
|
btAssert(m_next[previous] == pairIndex);
|
||||||
|
m_next[previous] = m_next[pairIndex];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_hashTable[hash] = m_next[pairIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
// We now move the last pair into spot of the
|
||||||
|
// pair being removed. We need to fix the hash
|
||||||
|
// table indices to support the move.
|
||||||
|
|
||||||
|
int lastPairIndex = m_valueArray.size() - 1;
|
||||||
|
|
||||||
|
// If the removed pair is the last pair, we are done.
|
||||||
|
if (lastPairIndex == pairIndex)
|
||||||
|
{
|
||||||
|
m_valueArray.pop_back();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove the last pair from the hash table.
|
||||||
|
const Value* lastValue = &m_valueArray[lastPairIndex];
|
||||||
|
int lastHash = key.getKey(*lastValue).getHash() & (m_valueArray.capacity()-1);
|
||||||
|
|
||||||
|
index = m_hashTable[lastHash];
|
||||||
|
btAssert(index != BT_HASH_NULL);
|
||||||
|
|
||||||
|
previous = BT_HASH_NULL;
|
||||||
|
while (index != lastPairIndex)
|
||||||
|
{
|
||||||
|
previous = index;
|
||||||
|
index = m_next[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (previous != BT_HASH_NULL)
|
||||||
|
{
|
||||||
|
btAssert(m_next[previous] == lastPairIndex);
|
||||||
|
m_next[previous] = m_next[lastPairIndex];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_hashTable[lastHash] = m_next[lastPairIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy the last pair into the remove pair's spot.
|
||||||
|
m_valueArray[pairIndex] = m_valueArray[lastPairIndex];
|
||||||
|
|
||||||
|
// Insert the last pair into the hash table
|
||||||
|
m_next[pairIndex] = m_hashTable[lastHash];
|
||||||
|
m_hashTable[lastHash] = pairIndex;
|
||||||
|
|
||||||
|
m_valueArray.pop_back();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int size() const
|
||||||
|
{
|
||||||
|
return m_valueArray.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
const Value* getAtIndex(int index) const
|
||||||
|
{
|
||||||
|
btAssert(index < m_valueArray.size());
|
||||||
|
|
||||||
|
return &m_valueArray[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
Value* getAtIndex(int index)
|
||||||
|
{
|
||||||
|
btAssert(index < m_valueArray.size());
|
||||||
|
|
||||||
|
return &m_valueArray[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
Value* operator[](const Key& key) {
|
||||||
|
return find(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
const Value* find(const Key& key) const
|
||||||
|
{
|
||||||
|
int index = findIndex(key);
|
||||||
|
if (index == BT_HASH_NULL)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return &m_valueArray[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
Value* find(const Key& key)
|
||||||
|
{
|
||||||
|
int index = findIndex(key);
|
||||||
|
if (index == BT_HASH_NULL)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return &m_valueArray[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int findIndex(const Key& key) const
|
||||||
|
{
|
||||||
|
int hash = key.getHash() & (m_valueArray.capacity()-1);
|
||||||
|
|
||||||
|
if (hash >= m_hashTable.size())
|
||||||
|
{
|
||||||
|
return BT_HASH_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int index = m_hashTable[hash];
|
||||||
|
while ((index != BT_HASH_NULL) && (key.getUid() == key.getKey(m_valueArray[index]).getUid()) == false)
|
||||||
|
{
|
||||||
|
index = m_next[index];
|
||||||
|
}
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear()
|
||||||
|
{
|
||||||
|
m_hashTable.clear();
|
||||||
|
m_next.clear();
|
||||||
|
m_valueArray.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //BT_HASH_MAP_H
|
102
extern/bullet2/src/LinearMath/btPoolAllocator.h
vendored
Normal file
102
extern/bullet2/src/LinearMath/btPoolAllocator.h
vendored
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
/*
|
||||||
|
Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef _BT_POOL_ALLOCATOR_H
|
||||||
|
#define _BT_POOL_ALLOCATOR_H
|
||||||
|
|
||||||
|
#include "btScalar.h"
|
||||||
|
#include "btAlignedAllocator.h"
|
||||||
|
|
||||||
|
///The btPoolAllocator class allows to efficiently allocate a large pool of objects, instead of dynamically allocating them separately.
|
||||||
|
class btPoolAllocator
|
||||||
|
{
|
||||||
|
int m_elemSize;
|
||||||
|
int m_maxElements;
|
||||||
|
int m_freeCount;
|
||||||
|
void* m_firstFree;
|
||||||
|
unsigned char* m_pool;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
btPoolAllocator(int elemSize, int maxElements)
|
||||||
|
:m_elemSize(elemSize),
|
||||||
|
m_maxElements(maxElements)
|
||||||
|
{
|
||||||
|
m_pool = (unsigned char*) btAlignedAlloc( static_cast<unsigned int>(m_elemSize*m_maxElements),16);
|
||||||
|
|
||||||
|
unsigned char* p = m_pool;
|
||||||
|
m_firstFree = p;
|
||||||
|
m_freeCount = m_maxElements;
|
||||||
|
int count = m_maxElements;
|
||||||
|
while (--count) {
|
||||||
|
*(void**)p = (p + m_elemSize);
|
||||||
|
p += m_elemSize;
|
||||||
|
}
|
||||||
|
*(void**)p = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
~btPoolAllocator()
|
||||||
|
{
|
||||||
|
btAlignedFree( m_pool);
|
||||||
|
}
|
||||||
|
|
||||||
|
int getFreeCount() const
|
||||||
|
{
|
||||||
|
return m_freeCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* allocate(int size)
|
||||||
|
{
|
||||||
|
// release mode fix
|
||||||
|
(void)size;
|
||||||
|
btAssert(!size || size<=m_elemSize);
|
||||||
|
btAssert(m_freeCount>0);
|
||||||
|
void* result = m_firstFree;
|
||||||
|
m_firstFree = *(void**)m_firstFree;
|
||||||
|
--m_freeCount;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool validPtr(void* ptr)
|
||||||
|
{
|
||||||
|
if (ptr) {
|
||||||
|
if (((unsigned char*)ptr >= m_pool && (unsigned char*)ptr < m_pool + m_maxElements * m_elemSize))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void freeMemory(void* ptr)
|
||||||
|
{
|
||||||
|
if (ptr) {
|
||||||
|
btAssert((unsigned char*)ptr >= m_pool && (unsigned char*)ptr < m_pool + m_maxElements * m_elemSize);
|
||||||
|
|
||||||
|
*(void**)ptr = m_firstFree;
|
||||||
|
m_firstFree = ptr;
|
||||||
|
++m_freeCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int getElementSize() const
|
||||||
|
{
|
||||||
|
return m_elemSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //_BT_POOL_ALLOCATOR_H
|
1461
intern/elbeem/intern/controlparticles.cpp
Normal file
1461
intern/elbeem/intern/controlparticles.cpp
Normal file
File diff suppressed because it is too large
Load Diff
301
intern/elbeem/intern/controlparticles.h
Normal file
301
intern/elbeem/intern/controlparticles.h
Normal file
@ -0,0 +1,301 @@
|
|||||||
|
// --------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// El'Beem - the visual lattice boltzmann freesurface simulator
|
||||||
|
// All code distributed as part of El'Beem is covered by the version 2 of the
|
||||||
|
// GNU General Public License. See the file COPYING for details.
|
||||||
|
//
|
||||||
|
// Copyright 2008 Nils Thuerey , Richard Keiser, Mark Pauly, Ulrich Ruede
|
||||||
|
//
|
||||||
|
// control particle classes
|
||||||
|
//
|
||||||
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef CONTROLPARTICLES_H
|
||||||
|
#define CONTROLPARTICLES_H
|
||||||
|
|
||||||
|
#include "ntl_geometrymodel.h"
|
||||||
|
|
||||||
|
// indicator for LBM inclusion
|
||||||
|
//#ifndef LBMDIM
|
||||||
|
|
||||||
|
//#include <NxFoundation.h>
|
||||||
|
//#include <vector>
|
||||||
|
//class MultisphGUI;
|
||||||
|
//#define NORMALIZE(a) a.normalize()
|
||||||
|
//#define MAGNITUDE(a) a.magnitude()
|
||||||
|
//#define CROSS(a,b,c) a.cross(b,c)
|
||||||
|
//#define ABS(a) (a>0. ? (a) : -(a))
|
||||||
|
//#include "cpdefines.h"
|
||||||
|
|
||||||
|
//#else // LBMDIM
|
||||||
|
|
||||||
|
// use compatibility defines
|
||||||
|
//#define NORMALIZE(a) normalize(a)
|
||||||
|
//#define MAGNITUDE(a) norm(a)
|
||||||
|
//#define CROSS(a,b,c) a=cross(b,c)
|
||||||
|
|
||||||
|
//#endif // LBMDIM
|
||||||
|
|
||||||
|
#define MAGNITUDE(a) norm(a)
|
||||||
|
|
||||||
|
// math.h compatibility
|
||||||
|
#define CP_PI ((LbmFloat)3.14159265358979323846)
|
||||||
|
|
||||||
|
// project 2d test cases onto plane?
|
||||||
|
// if not, 3d distance is used for 2d sim as well
|
||||||
|
#define CP_PROJECT2D 1
|
||||||
|
|
||||||
|
|
||||||
|
// default init for mincpdist, ControlForces::maxDistance
|
||||||
|
#define CPF_MAXDINIT 10000.
|
||||||
|
|
||||||
|
// storage of influence for a fluid cell/particle in lbm/sph
|
||||||
|
class ControlForces
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ControlForces() { };
|
||||||
|
~ControlForces() {};
|
||||||
|
|
||||||
|
// attraction force
|
||||||
|
LbmFloat weightAtt;
|
||||||
|
LbmVec forceAtt;
|
||||||
|
// velocity influence
|
||||||
|
LbmFloat weightVel;
|
||||||
|
LbmVec forceVel;
|
||||||
|
// maximal distance influence,
|
||||||
|
// first is max. distance to first control particle
|
||||||
|
// second attraction strength
|
||||||
|
LbmFloat maxDistance;
|
||||||
|
LbmVec forceMaxd;
|
||||||
|
|
||||||
|
LbmFloat compAvWeight;
|
||||||
|
LbmVec compAv;
|
||||||
|
|
||||||
|
void resetForces() {
|
||||||
|
weightAtt = weightVel = 0.;
|
||||||
|
maxDistance = CPF_MAXDINIT;
|
||||||
|
forceAtt = forceVel = forceMaxd = LbmVec(0.,0.,0.);
|
||||||
|
compAvWeight=0.; compAv=LbmVec(0.);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// single control particle
|
||||||
|
class ControlParticle
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ControlParticle() { reset(); };
|
||||||
|
~ControlParticle() {};
|
||||||
|
|
||||||
|
// control parameters
|
||||||
|
|
||||||
|
// position
|
||||||
|
LbmVec pos;
|
||||||
|
// size (influences influence radius)
|
||||||
|
LbmFloat size;
|
||||||
|
// overall strength of influence
|
||||||
|
LbmFloat influence;
|
||||||
|
// rotation axis
|
||||||
|
LbmVec rotaxis;
|
||||||
|
|
||||||
|
// computed values
|
||||||
|
|
||||||
|
// velocity
|
||||||
|
LbmVec vel;
|
||||||
|
// computed density
|
||||||
|
LbmFloat density;
|
||||||
|
LbmFloat densityWeight;
|
||||||
|
|
||||||
|
LbmVec avgVel;
|
||||||
|
LbmVec avgVelAcc;
|
||||||
|
LbmFloat avgVelWeight;
|
||||||
|
|
||||||
|
// init all zero / defaults
|
||||||
|
void reset();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// container for a particle configuration at time t
|
||||||
|
class ControlParticleSet
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
// time of particle set
|
||||||
|
LbmFloat time;
|
||||||
|
// particle positions
|
||||||
|
std::vector<ControlParticle> particles;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// container & management of control particles
|
||||||
|
class ControlParticles
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ControlParticles();
|
||||||
|
~ControlParticles();
|
||||||
|
|
||||||
|
// reset datastructures for next influence step
|
||||||
|
// if motion object is given, particle 1 of second system is used for overall
|
||||||
|
// position and speed offset
|
||||||
|
void prepareControl(LbmFloat simtime, LbmFloat dt, ControlParticles *motion);
|
||||||
|
// post control operations
|
||||||
|
void finishControl(std::vector<ControlForces> &forces, LbmFloat iatt, LbmFloat ivel, LbmFloat imaxd);
|
||||||
|
// recalculate
|
||||||
|
void calculateKernelWeight();
|
||||||
|
|
||||||
|
// calculate forces at given position, and modify velocity
|
||||||
|
// according to timestep (from initControl)
|
||||||
|
void calculateCpInfluenceOpt (ControlParticle *cp, LbmVec fluidpos, LbmVec fluidvel, ControlForces *force, LbmFloat fillFactor);
|
||||||
|
void calculateMaxdForce (ControlParticle *cp, LbmVec fluidpos, ControlForces *force);
|
||||||
|
|
||||||
|
// no. of particles
|
||||||
|
inline int getSize() { return (int)_particles.size(); }
|
||||||
|
int getTotalSize();
|
||||||
|
// get particle [i]
|
||||||
|
inline ControlParticle* getParticle(int i){ return &_particles[i]; }
|
||||||
|
|
||||||
|
// set influence parameters
|
||||||
|
void setInfluenceTangential(LbmFloat set) { _influenceTangential=set; }
|
||||||
|
void setInfluenceAttraction(LbmFloat set) { _influenceAttraction=set; }
|
||||||
|
void setInfluenceMaxdist(LbmFloat set) { _influenceMaxdist=set; }
|
||||||
|
// calculate for delta t
|
||||||
|
void setInfluenceVelocity(LbmFloat set, LbmFloat dt);
|
||||||
|
// get influence parameters
|
||||||
|
inline LbmFloat getInfluenceAttraction() { return _influenceAttraction; }
|
||||||
|
inline LbmFloat getInfluenceTangential() { return _influenceTangential; }
|
||||||
|
inline LbmFloat getInfluenceVelocity() { return _influenceVelocity; }
|
||||||
|
inline LbmFloat getInfluenceMaxdist() { return _influenceMaxdist; }
|
||||||
|
inline LbmFloat getCurrTimestep() { return _currTimestep; }
|
||||||
|
|
||||||
|
void setRadiusAtt(LbmFloat set) { _radiusAtt=set; }
|
||||||
|
inline LbmFloat getRadiusAtt() { return _radiusAtt; }
|
||||||
|
void setRadiusVel(LbmFloat set) { _radiusVel=set; }
|
||||||
|
inline LbmFloat getRadiusVel() { return _radiusVel; }
|
||||||
|
void setRadiusMaxd(LbmFloat set) { _radiusMaxd=set; }
|
||||||
|
inline LbmFloat getRadiusMaxd() { return _radiusMaxd; }
|
||||||
|
void setRadiusMinMaxd(LbmFloat set) { _radiusMinMaxd=set; }
|
||||||
|
inline LbmFloat getRadiusMinMaxd() { return _radiusMinMaxd; }
|
||||||
|
|
||||||
|
LbmFloat getControlTimStart();
|
||||||
|
LbmFloat getControlTimEnd();
|
||||||
|
|
||||||
|
// set/get characteristic length (and inverse)
|
||||||
|
void setCharLength(LbmFloat set) { _charLength=set; _charLengthInv=1./_charLength; }
|
||||||
|
inline LbmFloat getCharLength() { return _charLength;}
|
||||||
|
inline LbmFloat getCharLengthInv() { return _charLengthInv;}
|
||||||
|
|
||||||
|
// set init parameters
|
||||||
|
void setInitTimeScale(LbmFloat set) { _initTimeScale = set; };
|
||||||
|
void setInitMirror(string set) { _initMirror = set; };
|
||||||
|
string getInitMirror() { return _initMirror; };
|
||||||
|
|
||||||
|
void setLastOffset(LbmVec set) { _initLastPartOffset = set; };
|
||||||
|
void setLastScale(LbmVec set) { _initLastPartScale = set; };
|
||||||
|
void setOffset(LbmVec set) { _initPartOffset = set; };
|
||||||
|
void setScale(LbmVec set) { _initPartScale = set; };
|
||||||
|
|
||||||
|
// set/get cps params
|
||||||
|
void setCPSWith(LbmFloat set) { mCPSWidth = set; };
|
||||||
|
void setCPSTimestep(LbmFloat set) { mCPSTimestep = set; };
|
||||||
|
void setCPSTimeStart(LbmFloat set) { mCPSTimeStart = set; };
|
||||||
|
void setCPSTimeEnd(LbmFloat set) { mCPSTimeEnd = set; };
|
||||||
|
void setCPSMvmWeightFac(LbmFloat set) { mCPSWeightFac = set; };
|
||||||
|
|
||||||
|
LbmFloat getCPSWith() { return mCPSWidth; };
|
||||||
|
LbmFloat getCPSTimestep() { return mCPSTimestep; };
|
||||||
|
LbmFloat getCPSTimeStart() { return mCPSTimeStart; };
|
||||||
|
LbmFloat getCPSTimeEnd() { return mCPSTimeEnd; };
|
||||||
|
LbmFloat getCPSMvmWeightFac() { return mCPSWeightFac; };
|
||||||
|
|
||||||
|
void setDebugInit(int set) { mDebugInit = set; };
|
||||||
|
|
||||||
|
// set init parameters
|
||||||
|
void setFluidSpacing(LbmFloat set) { _fluidSpacing = set; };
|
||||||
|
|
||||||
|
// load positions & timing from text file
|
||||||
|
int initFromTextFile(string filename);
|
||||||
|
int initFromTextFileOld(string filename);
|
||||||
|
// load positions & timing from gzipped binary file
|
||||||
|
int initFromBinaryFile(string filename);
|
||||||
|
int initFromMVCMesh(string filename);
|
||||||
|
// init an example test case
|
||||||
|
int initExampleSet();
|
||||||
|
|
||||||
|
// init for a given time
|
||||||
|
void initTime(LbmFloat t, LbmFloat dt);
|
||||||
|
|
||||||
|
// blender test init
|
||||||
|
void initBlenderTest();
|
||||||
|
|
||||||
|
int initFromObject(ntlGeometryObjModel *model);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// sets influence params
|
||||||
|
friend class MultisphGUI;
|
||||||
|
|
||||||
|
// tangential and attraction influence
|
||||||
|
LbmFloat _influenceTangential, _influenceAttraction;
|
||||||
|
// direct velocity influence
|
||||||
|
LbmFloat _influenceVelocity;
|
||||||
|
// maximal distance influence
|
||||||
|
LbmFloat _influenceMaxdist;
|
||||||
|
|
||||||
|
// influence radii
|
||||||
|
LbmFloat _radiusAtt, _radiusVel, _radiusMinMaxd, _radiusMaxd;
|
||||||
|
|
||||||
|
// currently valid time & timestep
|
||||||
|
LbmFloat _currTime, _currTimestep;
|
||||||
|
// all particles
|
||||||
|
std::vector<ControlParticle> _particles;
|
||||||
|
|
||||||
|
// particle sets
|
||||||
|
std::vector<ControlParticleSet> mPartSets;
|
||||||
|
|
||||||
|
// additional parameters for initing particles
|
||||||
|
LbmFloat _initTimeScale;
|
||||||
|
LbmVec _initPartOffset;
|
||||||
|
LbmVec _initPartScale;
|
||||||
|
LbmVec _initLastPartOffset;
|
||||||
|
LbmVec _initLastPartScale;
|
||||||
|
// mirror particles for loading?
|
||||||
|
string _initMirror;
|
||||||
|
|
||||||
|
// row spacing paramter, e.g. use for approximation of kernel area/volume
|
||||||
|
LbmFloat _fluidSpacing;
|
||||||
|
// save current kernel weight
|
||||||
|
LbmFloat _kernelWeight;
|
||||||
|
// charateristic length in world coordinates for normalizatioon of forces
|
||||||
|
LbmFloat _charLength, _charLengthInv;
|
||||||
|
|
||||||
|
|
||||||
|
/*! do ani mesh CPS */
|
||||||
|
void calculateCPS(string filename);
|
||||||
|
//! ani mesh cps params
|
||||||
|
ntlVec3Gfx mvCPSStart, mvCPSEnd;
|
||||||
|
gfxReal mCPSWidth, mCPSTimestep;
|
||||||
|
gfxReal mCPSTimeStart, mCPSTimeEnd;
|
||||||
|
gfxReal mCPSWeightFac;
|
||||||
|
|
||||||
|
int mDebugInit;
|
||||||
|
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// apply init transformations
|
||||||
|
void applyTrafos();
|
||||||
|
|
||||||
|
// helper function for init -> swap components everywhere
|
||||||
|
void swapCoords(int a,int b);
|
||||||
|
// helper function for init -> mirror time
|
||||||
|
void mirrorTime();
|
||||||
|
|
||||||
|
// helper, init given array
|
||||||
|
void initTimeArray(LbmFloat t, std::vector<ControlParticle> &parts);
|
||||||
|
|
||||||
|
bool checkPointInside(ntlTree *tree, ntlVec3Gfx org, gfxReal &distance);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
25
intern/elbeem/intern/elbeem_control.cpp
Normal file
25
intern/elbeem/intern/elbeem_control.cpp
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
*
|
||||||
|
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
|
||||||
|
* All code distributed as part of El'Beem is covered by the version 2 of the
|
||||||
|
* GNU General Public License. See the file COPYING for details.
|
||||||
|
* Copyright 2003-2006 Nils Thuerey
|
||||||
|
*
|
||||||
|
* Control API header
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "elbeem.h"
|
||||||
|
#include "elbeem_control.h"
|
||||||
|
|
||||||
|
// add mesh as fluidsim object
|
||||||
|
int elbeemControlAddSet(struct elbeemControl*) {
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int elbeemControlComputeMesh(struct elbeemMesh*) {
|
||||||
|
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
62
intern/elbeem/intern/elbeem_control.h
Normal file
62
intern/elbeem/intern/elbeem_control.h
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
*
|
||||||
|
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
|
||||||
|
* All code distributed as part of El'Beem is covered by the version 2 of the
|
||||||
|
* GNU General Public License. See the file COPYING for details.
|
||||||
|
* Copyright 2003-2006 Nils Thuerey
|
||||||
|
*
|
||||||
|
* Control API header
|
||||||
|
*/
|
||||||
|
#ifndef ELBEEMCONTROL_API_H
|
||||||
|
#define ELBEEMCONTROL_API_H
|
||||||
|
|
||||||
|
// a single control particle set
|
||||||
|
typedef struct elbeemControl {
|
||||||
|
/* influence forces */
|
||||||
|
float influenceAttraction;
|
||||||
|
float *channelInfluenceAttraction;
|
||||||
|
float channelSizeInfluenceAttraction;
|
||||||
|
|
||||||
|
float influenceVelocity;
|
||||||
|
float *channelInfluenceVelocity;
|
||||||
|
float channelSizeInfluenceVelocity;
|
||||||
|
|
||||||
|
float influenceMaxdist;
|
||||||
|
float *channelInfluenceMaxdist;
|
||||||
|
float channelSizeInfluenceMaxdist;
|
||||||
|
|
||||||
|
/* influence force radii */
|
||||||
|
float radiusAttraction;
|
||||||
|
float *channelRadiusAttraction;
|
||||||
|
float channelSizeRadiusAttraction;
|
||||||
|
|
||||||
|
float radiusVelocity;
|
||||||
|
float *channelRadiusVelocity;
|
||||||
|
float channelSizeRadiusVelocity;
|
||||||
|
|
||||||
|
float radiusMindist;
|
||||||
|
float *channelRadiusMindist;
|
||||||
|
float channelSizeRadiusMindist;
|
||||||
|
float radiusMaxdist;
|
||||||
|
float *channelRadiusMaxdist;
|
||||||
|
float channelSizeRadiusMaxdist;
|
||||||
|
|
||||||
|
/* control particle positions/scale */
|
||||||
|
float offset[3];
|
||||||
|
float *channelOffset;
|
||||||
|
float channelSizeOffset;
|
||||||
|
|
||||||
|
float scale[3];
|
||||||
|
float *channelScale;
|
||||||
|
float channelSizeScale;
|
||||||
|
|
||||||
|
} elbeemControl;
|
||||||
|
|
||||||
|
|
||||||
|
// add mesh as fluidsim object
|
||||||
|
int elbeemControlAddSet(struct elbeemControl*);
|
||||||
|
|
||||||
|
// sample & track mesh control particles, TODO add return type...
|
||||||
|
int elbeemControlComputeMesh(struct elbeemMesh*);
|
||||||
|
|
||||||
|
#endif // ELBEEMCONTROL_API_H
|
193
intern/elbeem/intern/mvmcoords.cpp
Normal file
193
intern/elbeem/intern/mvmcoords.cpp
Normal file
@ -0,0 +1,193 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
*
|
||||||
|
// El'Beem - the visual lattice boltzmann freesurface simulator
|
||||||
|
// All code distributed as part of El'Beem is covered by the version 2 of the
|
||||||
|
// GNU General Public License. See the file COPYING for details.
|
||||||
|
//
|
||||||
|
// Copyright 2008 Nils Thuerey , Richard Keiser, Mark Pauly, Ulrich Ruede
|
||||||
|
//
|
||||||
|
*
|
||||||
|
* Mean Value Mesh Coords class
|
||||||
|
*
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#include "mvmcoords.h"
|
||||||
|
#include <algorithm>
|
||||||
|
using std::vector;
|
||||||
|
|
||||||
|
void MeanValueMeshCoords::clear()
|
||||||
|
{
|
||||||
|
mVertices.resize(0);
|
||||||
|
mNumVerts = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MeanValueMeshCoords::calculateMVMCs(vector<ntlVec3Gfx> &reference_vertices, vector<ntlTriangle> &tris,
|
||||||
|
vector<ntlVec3Gfx> &points, gfxReal numweights)
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
mvmTransferPoint tds;
|
||||||
|
int mem = 0;
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
mNumVerts = (int)reference_vertices.size();
|
||||||
|
|
||||||
|
for (vector<ntlVec3Gfx>::iterator iter = points.begin(); iter != points.end(); ++iter, ++i) {
|
||||||
|
/*
|
||||||
|
if(i%(points.size()/10)==1) debMsgStd("MeanValueMeshCoords::calculateMVMCs",DM_MSG,"Computing weights, points: "<<i<<"/"<<points.size(),5 );
|
||||||
|
*/
|
||||||
|
tds.lastpos = *iter;
|
||||||
|
tds.weights.resize(0); // clear
|
||||||
|
computeWeights(reference_vertices, tris, tds, numweights);
|
||||||
|
mem += (int)tds.weights.size();
|
||||||
|
mVertices.push_back(tds);
|
||||||
|
}
|
||||||
|
int mbmem = mem * sizeof(mvmFloat) / (1024*1024);
|
||||||
|
debMsgStd("MeanValueMeshCoords::calculateMVMCs",DM_MSG,"vertices:"<<mNumVerts<<" points:"<<points.size()<<" weights:"<<mem<<", wmem:"<<mbmem<<"MB ",7 );
|
||||||
|
}
|
||||||
|
|
||||||
|
// from: mean value coordinates for closed triangular meshes
|
||||||
|
// attention: fails if a point is exactly (or very close) to a vertex
|
||||||
|
void MeanValueMeshCoords::computeWeights(vector<ntlVec3Gfx> &reference_vertices, vector<ntlTriangle>& tris,
|
||||||
|
mvmTransferPoint& tds, gfxReal numweights)
|
||||||
|
{
|
||||||
|
const bool mvmFullDebug=false;
|
||||||
|
//const ntlVec3Gfx cEPS = 1.0e-6;
|
||||||
|
const mvmFloat cEPS = 1.0e-14;
|
||||||
|
|
||||||
|
//mvmFloat d[3], s[3], phi[3],c[3];
|
||||||
|
ntlVec3d u[3],c,d,s,phi;
|
||||||
|
int indices[3];
|
||||||
|
|
||||||
|
for (int i = 0; i < (int)reference_vertices.size(); ++i) {
|
||||||
|
tds.weights.push_back(mvmIndexWeight(i, 0.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
// for each triangle
|
||||||
|
//for (vector<ntlTriangle>::iterator iter = tris.begin(); iter != tris.end();) {
|
||||||
|
for(int t=0; t<(int)tris.size(); t++) {
|
||||||
|
|
||||||
|
for (int i = 0; i < 3; ++i) { //, ++iter) {
|
||||||
|
indices[i] = tris[t].getPoints()[i];
|
||||||
|
u[i] = vec2D(reference_vertices[ indices[i] ]-tds.lastpos);
|
||||||
|
d[i] = normalize(u[i]); //.normalize();
|
||||||
|
//assert(d[i] != 0.);
|
||||||
|
if(mvmFullDebug) errMsg("MeanValueMeshCoords::computeWeights","t"<<t<<" i"<<indices[i] //<<" lp"<<tds.lastpos
|
||||||
|
<<" v"<<reference_vertices[indices[i]]<<" u"<<u[i]<<" ");
|
||||||
|
// on vertex!
|
||||||
|
//? if(d[i]<=0.) continue;
|
||||||
|
}
|
||||||
|
//for (int i = 0; i < 3; ++i) { errMsg("III"," "<<i <<" i"<<indices[i]<<reference_vertices[ indices[i] ] ); }
|
||||||
|
|
||||||
|
// arcsin is not needed, see paper
|
||||||
|
phi[0] = 2.*asin( (mvmFloat)(0.5* norm(u[1]-u[2]) ) );
|
||||||
|
phi[1] = 2.*asin( (mvmFloat)(0.5* norm(u[0]-u[2]) ) );
|
||||||
|
phi[2] = 2.*asin( (mvmFloat)(0.5* norm(u[0]-u[1]) ) );
|
||||||
|
mvmFloat h = (phi[0] + phi[1] + phi[2])*0.5;
|
||||||
|
if (M_PI-h < cEPS) {
|
||||||
|
if(mvmFullDebug) errMsg("MeanValueMeshCoords::computeWeights","point on triangle");
|
||||||
|
tds.weights.resize(0);
|
||||||
|
tds.weights.push_back( mvmIndexWeight(indices[0], sin(phi[0])*d[1]*d[2]));
|
||||||
|
tds.weights.push_back( mvmIndexWeight(indices[1], sin(phi[1])*d[0]*d[2]));
|
||||||
|
tds.weights.push_back( mvmIndexWeight(indices[2], sin(phi[2])*d[1]*d[0]));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
mvmFloat sinh = 2.*sin(h);
|
||||||
|
c[0] = (sinh*sin(h-phi[0]))/(sin(phi[1])*sin(phi[2]))-1.;
|
||||||
|
c[1] = (sinh*sin(h-phi[1]))/(sin(phi[0])*sin(phi[2]))-1.;
|
||||||
|
c[2] = (sinh*sin(h-phi[2]))/(sin(phi[0])*sin(phi[1]))-1.;
|
||||||
|
if(mvmFullDebug) errMsg("MeanValueMeshCoords::computeWeights","c="<<c<<" phi="<<phi<<" d="<<d);
|
||||||
|
//if (c[0] > 1. || c[0] < 0. || c[1] > 1. || c[1] < 0. || c[2] > 1. || c[2] < 0.) continue;
|
||||||
|
|
||||||
|
s[0] = sqrtf((float)(1.-c[0]*c[0]));
|
||||||
|
s[1] = sqrtf((float)(1.-c[1]*c[1]));
|
||||||
|
s[2] = sqrtf((float)(1.-c[2]*c[2]));
|
||||||
|
|
||||||
|
if(mvmFullDebug) errMsg("MeanValueMeshCoords::computeWeights","s");
|
||||||
|
if (s[0] <= cEPS || s[1] <= cEPS || s[2] <= cEPS) {
|
||||||
|
//MSG("position lies outside the triangle on the same plane -> ignore it");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const mvmFloat u0x = u[0][0];
|
||||||
|
const mvmFloat u0y = u[0][1];
|
||||||
|
const mvmFloat u0z = u[0][2];
|
||||||
|
const mvmFloat u1x = u[1][0];
|
||||||
|
const mvmFloat u1y = u[1][1];
|
||||||
|
const mvmFloat u1z = u[1][2];
|
||||||
|
const mvmFloat u2x = u[2][0];
|
||||||
|
const mvmFloat u2y = u[2][1];
|
||||||
|
const mvmFloat u2z = u[2][2];
|
||||||
|
mvmFloat det = u0x*u1y*u2z - u0x*u1z*u2y + u0y*u1z*u2x - u0y*u1x*u2z + u0z*u1x*u2y - u0z*u1y*u2x;
|
||||||
|
//assert(det != 0.);
|
||||||
|
if (det < 0.) {
|
||||||
|
s[0] = -s[0];
|
||||||
|
s[1] = -s[1];
|
||||||
|
s[2] = -s[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
tds.weights[indices[0]].weight += (phi[0]-c[1]*phi[2]-c[2]*phi[1])/(d[0]*sin(phi[1])*s[2]);
|
||||||
|
tds.weights[indices[1]].weight += (phi[1]-c[2]*phi[0]-c[0]*phi[2])/(d[1]*sin(phi[2])*s[0]);
|
||||||
|
tds.weights[indices[2]].weight += (phi[2]-c[0]*phi[1]-c[1]*phi[0])/(d[2]*sin(phi[0])*s[1]);
|
||||||
|
if(mvmFullDebug) { errMsg("MeanValueMeshCoords::computeWeights","i"<<indices[0]<<" o"<<tds.weights[indices[0]].weight);
|
||||||
|
errMsg("MeanValueMeshCoords::computeWeights","i"<<indices[1]<<" o"<<tds.weights[indices[1]].weight);
|
||||||
|
errMsg("MeanValueMeshCoords::computeWeights","i"<<indices[2]<<" o"<<tds.weights[indices[2]].weight);
|
||||||
|
errMsg("MeanValueMeshCoords::computeWeights","\n\n\n"); }
|
||||||
|
}
|
||||||
|
|
||||||
|
//sort weights
|
||||||
|
if((numweights>0.)&& (numweights<1.) ) {
|
||||||
|
//if( ((int)tds.weights.size() > maxNumWeights) && (maxNumWeights > 0) ) {
|
||||||
|
int maxNumWeights = (int)(tds.weights.size()*numweights);
|
||||||
|
if(maxNumWeights<=0) maxNumWeights = 1;
|
||||||
|
std::sort(tds.weights.begin(), tds.weights.end(), std::greater<mvmIndexWeight>());
|
||||||
|
// only use maxNumWeights-th largest weights
|
||||||
|
tds.weights.resize(maxNumWeights);
|
||||||
|
}
|
||||||
|
|
||||||
|
// normalize weights
|
||||||
|
mvmFloat totalWeight = 0.;
|
||||||
|
for (vector<mvmIndexWeight>::const_iterator witer = tds.weights.begin();
|
||||||
|
witer != tds.weights.end(); ++witer) {
|
||||||
|
totalWeight += witer->weight;
|
||||||
|
}
|
||||||
|
mvmFloat invTotalWeight;
|
||||||
|
if (totalWeight == 0.) {
|
||||||
|
if(mvmFullDebug) errMsg("MeanValueMeshCoords::computeWeights","totalWeight == 0");
|
||||||
|
invTotalWeight = 0.0;
|
||||||
|
} else {
|
||||||
|
invTotalWeight = 1.0/totalWeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (vector<mvmIndexWeight>::iterator viter = tds.weights.begin();
|
||||||
|
viter != tds.weights.end(); ++viter) {
|
||||||
|
viter->weight *= invTotalWeight;
|
||||||
|
//assert(finite(viter->weight) != 0);
|
||||||
|
if(!finite(viter->weight)) viter->weight=0.;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MeanValueMeshCoords::transfer(vector<ntlVec3Gfx> &vertices, vector<ntlVec3Gfx>& displacements)
|
||||||
|
{
|
||||||
|
displacements.resize(0);
|
||||||
|
|
||||||
|
//debMsgStd("MeanValueMeshCoords::transfer",DM_MSG,"vertices:"<<mNumVerts<<" curr_verts:"<<vertices.size()<<" ",7 );
|
||||||
|
if((int)vertices.size() != mNumVerts) {
|
||||||
|
errMsg("MeanValueMeshCoords::transfer","Different no of verts: "<<vertices.size()<<" vs "<<mNumVerts);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (vector<mvmTransferPoint>::iterator titer = mVertices.begin(); titer != mVertices.end(); ++titer) {
|
||||||
|
mvmTransferPoint &tds = *titer;
|
||||||
|
ntlVec3Gfx newpos(0.0);
|
||||||
|
|
||||||
|
for (vector<mvmIndexWeight>::iterator witer = tds.weights.begin();
|
||||||
|
witer != tds.weights.end(); ++witer) {
|
||||||
|
newpos += vertices[witer->index] * witer->weight;
|
||||||
|
//errMsg("transfer","np"<<newpos<<" v"<<vertices[witer->index]<<" w"<< witer->weight);
|
||||||
|
}
|
||||||
|
|
||||||
|
displacements.push_back(newpos);
|
||||||
|
//displacements.push_back(newpos - tds.lastpos);
|
||||||
|
//tds.lastpos = newpos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
89
intern/elbeem/intern/mvmcoords.h
Normal file
89
intern/elbeem/intern/mvmcoords.h
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
*
|
||||||
|
// El'Beem - the visual lattice boltzmann freesurface simulator
|
||||||
|
// All code distributed as part of El'Beem is covered by the version 2 of the
|
||||||
|
// GNU General Public License. See the file COPYING for details.
|
||||||
|
//
|
||||||
|
// Copyright 2008 Nils Thuerey , Richard Keiser, Mark Pauly, Ulrich Ruede
|
||||||
|
//
|
||||||
|
*
|
||||||
|
* Mean Value Mesh Coords class
|
||||||
|
*
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef MVMCOORDS_H
|
||||||
|
#define MVMCOORDS_H
|
||||||
|
|
||||||
|
#include "utilities.h"
|
||||||
|
#include "ntl_ray.h"
|
||||||
|
#include <vector>
|
||||||
|
#define mvmFloat double
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
#ifndef FREE_WINDOWS
|
||||||
|
#include "float.h"
|
||||||
|
#define isnan(n) _isnan(n)
|
||||||
|
#define finite _finite
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef sun
|
||||||
|
#include "ieeefp.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// weight and triangle index
|
||||||
|
class mvmIndexWeight {
|
||||||
|
public:
|
||||||
|
|
||||||
|
mvmIndexWeight() : weight(0.0) {}
|
||||||
|
|
||||||
|
mvmIndexWeight(int const& i, mvmFloat const& w) :
|
||||||
|
weight(w), index(i) {}
|
||||||
|
|
||||||
|
// for sorting
|
||||||
|
bool operator> (mvmIndexWeight const& w) const { return this->weight > w.weight; }
|
||||||
|
bool operator< (mvmIndexWeight const& w) const { return this->weight < w.weight; }
|
||||||
|
|
||||||
|
mvmFloat weight;
|
||||||
|
int index;
|
||||||
|
};
|
||||||
|
|
||||||
|
// transfer point with weights
|
||||||
|
class mvmTransferPoint {
|
||||||
|
public:
|
||||||
|
//! position of transfer point
|
||||||
|
ntlVec3Gfx lastpos;
|
||||||
|
//! triangle weights
|
||||||
|
std::vector<mvmIndexWeight> weights;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//! compute mvmcs
|
||||||
|
class MeanValueMeshCoords {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
MeanValueMeshCoords() {}
|
||||||
|
~MeanValueMeshCoords() {
|
||||||
|
clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
void calculateMVMCs(std::vector<ntlVec3Gfx> &reference_vertices,
|
||||||
|
std::vector<ntlTriangle> &tris, std::vector<ntlVec3Gfx> &points, gfxReal numweights);
|
||||||
|
|
||||||
|
void transfer(std::vector<ntlVec3Gfx> &vertices, std::vector<ntlVec3Gfx>& displacements);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
void computeWeights(std::vector<ntlVec3Gfx> &reference_vertices,
|
||||||
|
std::vector<ntlTriangle> &tris, mvmTransferPoint& tds, gfxReal numweights);
|
||||||
|
|
||||||
|
std::vector<mvmTransferPoint> mVertices;
|
||||||
|
int mNumVerts;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
1016
intern/elbeem/intern/solver_control.cpp
Normal file
1016
intern/elbeem/intern/solver_control.cpp
Normal file
File diff suppressed because it is too large
Load Diff
182
intern/elbeem/intern/solver_control.h
Normal file
182
intern/elbeem/intern/solver_control.h
Normal file
@ -0,0 +1,182 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
*
|
||||||
|
* El'Beem - the visual lattice boltzmann freesurface simulator
|
||||||
|
* All code distributed as part of El'Beem is covered by the version 2 of the
|
||||||
|
* GNU General Public License. See the file COPYING for details.
|
||||||
|
* Copyright 2003-2006 Nils Thuerey
|
||||||
|
*
|
||||||
|
* testing extensions
|
||||||
|
*
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef LBM_TESTCLASS_H
|
||||||
|
#define LBM_TESTCLASS_H
|
||||||
|
|
||||||
|
//class IsoSurface;
|
||||||
|
class ParticleObject;
|
||||||
|
class ControlParticles;
|
||||||
|
class ControlForces;
|
||||||
|
|
||||||
|
//#define NUMGRIDS 2
|
||||||
|
//#define MAXNUMSWS 10
|
||||||
|
|
||||||
|
// farfield modes
|
||||||
|
#define FARF_3DONLY -1
|
||||||
|
#define FARF_BOTH 0
|
||||||
|
#define FARF_SWEONLY 1
|
||||||
|
// dont reuse 3d vars/init
|
||||||
|
#define FARF_SEPSWE 2
|
||||||
|
|
||||||
|
// relaxation macros for solver_relax.h
|
||||||
|
|
||||||
|
// WARNING has to match controlparts.h
|
||||||
|
#define CPF_ENTRIES 12
|
||||||
|
#define CPF_FORCE 0
|
||||||
|
#define CPF_VELWEIGHT 3
|
||||||
|
#define CPF_VELOCITY 4
|
||||||
|
#define CPF_FORCEWEIGHT 7
|
||||||
|
#define CPF_MINCPDIST 8
|
||||||
|
#define CPF_MINCPDIR 9
|
||||||
|
|
||||||
|
#include "controlparticles.h"
|
||||||
|
|
||||||
|
#include "ntl_geometrymodel.h"
|
||||||
|
|
||||||
|
// get force entry, set=0 is unused anyway
|
||||||
|
#define LBMGET_FORCE(lev, i,j,k) mpControl->mCpForces[lev][ (LBMGI(lev,i,j,k,0)) ]
|
||||||
|
|
||||||
|
// debug mods off...
|
||||||
|
// same as in src/solver_relax.h!
|
||||||
|
#define __PRECOLLIDE_MODS(rho,ux,uy,uz, grav) \
|
||||||
|
ux += (grav)[0]; \
|
||||||
|
uy += (grav)[1]; \
|
||||||
|
uz += (grav)[2];
|
||||||
|
|
||||||
|
//void testMaxdmod(int i, int j,int k, LbmFloat &ux,LbmFloat &uy,LbmFloat &uz,ControlForces &ff);
|
||||||
|
#if LBMDIM==3
|
||||||
|
#define MAXDGRAV \
|
||||||
|
if(myforce->forceMaxd[0]*ux+myforce->forceMaxd[1]*uy<LBM_EPSILON) { \
|
||||||
|
ux = v2w*myforce->forceVel[0]+ v2wi*ux; \
|
||||||
|
uy = v2w*myforce->forceVel[1]+ v2wi*uy; } \
|
||||||
|
/* movement inverse to g? */ \
|
||||||
|
if((uz>LBM_EPSILON)&&(uz>myforce->forceVel[2])) { \
|
||||||
|
uz = v2w*myforce->forceVel[2]+ v2wi*uz; }
|
||||||
|
#else // LBMDIM==3
|
||||||
|
#define MAXDGRAV \
|
||||||
|
if(myforce->forceMaxd[0]*ux<LBM_EPSILON) { \
|
||||||
|
ux = v2w*myforce->forceVel[0]+ v2wi*ux; } \
|
||||||
|
/* movement inverse to g? */ \
|
||||||
|
if((uy>LBM_EPSILON)&&(uy>myforce->forceVel[1])) { \
|
||||||
|
uy = v2w*myforce->forceVel[1]+ v2wi*uy; }
|
||||||
|
#endif // LBMDIM==3
|
||||||
|
|
||||||
|
// debug modifications of collide vars (testing)
|
||||||
|
// requires: lev,i,j,k
|
||||||
|
#define PRECOLLIDE_MODS(rho,ux,uy,uz, grav) \
|
||||||
|
LbmFloat attforce = 1.; \
|
||||||
|
if(this->mTForceStrength>0.) { \
|
||||||
|
ControlForces* myforce = &LBMGET_FORCE(lev,i,j,k); \
|
||||||
|
const LbmFloat vf = myforce->weightAtt;\
|
||||||
|
const LbmFloat vw = myforce->weightVel;\
|
||||||
|
if(vf!=0.) { attforce = MAX(0., 1.-vf); /* TODO FIXME? use ABS(vf) for repulsion force? */ \
|
||||||
|
ux += myforce->forceAtt[0]; \
|
||||||
|
uy += myforce->forceAtt[1]; \
|
||||||
|
uz += myforce->forceAtt[2]; \
|
||||||
|
\
|
||||||
|
} else if(( myforce->maxDistance>0.) && ( myforce->maxDistance<CPF_MAXDINIT)) {\
|
||||||
|
const LbmFloat v2w = mpControl->mCons[0]->mCparts->getInfluenceMaxdist() * \
|
||||||
|
(myforce->maxDistance-mpControl->mCons[0]->mCparts->getRadiusMinMaxd()) / (mpControl->mCons[0]->mCparts->getRadiusMaxd()-mpControl->mCons[0]->mCparts->getRadiusMinMaxd()); \
|
||||||
|
const LbmFloat v2wi = 1.-v2w; \
|
||||||
|
if(v2w>0.){ MAXDGRAV; \
|
||||||
|
/* errMsg("ERRMDTT","at "<<PRINT_IJK<<" maxd="<<myforce->maxDistance<<", newu"<<PRINT_VEC(ux,uy,uz)<<", org"<<PRINT_VEC(oux,ouy,ouz)<<", fv"<<myforce->forceVel<<" " ); */ \
|
||||||
|
}\
|
||||||
|
} \
|
||||||
|
if(vw>0.) { \
|
||||||
|
const LbmFloat vwi = 1.-vw;\
|
||||||
|
const LbmFloat vwd = mpControl->mDiffVelCon;\
|
||||||
|
ux += vw*(myforce->forceVel[0]-myforce->compAv[0] + vwd*(myforce->compAv[0]-ux) ); \
|
||||||
|
uy += vw*(myforce->forceVel[1]-myforce->compAv[1] + vwd*(myforce->compAv[1]-uy) ); \
|
||||||
|
uz += vw*(myforce->forceVel[2]-myforce->compAv[2] + vwd*(myforce->compAv[2]-uz) ); \
|
||||||
|
/* TODO test!? modify smooth vel by influence of force for each lbm step, to account for force update only each N steps */ \
|
||||||
|
myforce->compAv = (myforce->forceVel*vw+ myforce->compAv*vwi); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
ux += (grav)[0]*attforce; \
|
||||||
|
uy += (grav)[1]*attforce; \
|
||||||
|
uz += (grav)[2]*attforce; \
|
||||||
|
/* end PRECOLLIDE_MODS */
|
||||||
|
|
||||||
|
#define TEST_IF_CHECK \
|
||||||
|
if((!iffilled)&&(LBMGET_FORCE(lev,i,j,k).weightAtt!=0.)) { \
|
||||||
|
errMsg("TESTIFFILL"," at "<<PRINT_IJK<<" "<<mass<<" "<<rho); \
|
||||||
|
iffilled = true; \
|
||||||
|
if(mass<rho*1.0) mass = rho*1.0; myfrac = 1.0; \
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// a single set of control particles and params
|
||||||
|
class LbmControlSet {
|
||||||
|
public:
|
||||||
|
LbmControlSet();
|
||||||
|
~LbmControlSet();
|
||||||
|
void initCparts();
|
||||||
|
|
||||||
|
// control particles
|
||||||
|
ControlParticles *mCparts;
|
||||||
|
// control particle overall motion (for easier manual generation)
|
||||||
|
ControlParticles *mCpmotion;
|
||||||
|
// cp data file
|
||||||
|
string mContrPartFile;
|
||||||
|
string mCpmotionFile;
|
||||||
|
// cp debug displau
|
||||||
|
LbmFloat mDebugCpscale, mDebugVelScale, mDebugCompavScale, mDebugAttScale, mDebugMaxdScale, mDebugAvgVelScale;
|
||||||
|
|
||||||
|
// params
|
||||||
|
AnimChannel<float> mcForceAtt;
|
||||||
|
AnimChannel<float> mcForceVel;
|
||||||
|
AnimChannel<float> mcForceMaxd;
|
||||||
|
|
||||||
|
AnimChannel<float> mcRadiusAtt;
|
||||||
|
AnimChannel<float> mcRadiusVel;
|
||||||
|
AnimChannel<float> mcRadiusMind;
|
||||||
|
AnimChannel<float> mcRadiusMaxd;
|
||||||
|
|
||||||
|
AnimChannel<ntlVec3f> mcCpScale;
|
||||||
|
AnimChannel<ntlVec3f> mcCpOffset;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// main control data storage
|
||||||
|
class LbmControlData
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
LbmControlData();
|
||||||
|
virtual ~LbmControlData();
|
||||||
|
|
||||||
|
// control data
|
||||||
|
|
||||||
|
// contorl params
|
||||||
|
void parseControldataAttrList(AttributeList *attr);
|
||||||
|
|
||||||
|
// control strength, set for solver interface
|
||||||
|
LbmFloat mSetForceStrength;
|
||||||
|
// cp vars
|
||||||
|
std::vector<LbmControlSet*> mCons;
|
||||||
|
// update interval
|
||||||
|
int mCpUpdateInterval;
|
||||||
|
// output
|
||||||
|
string mCpOutfile;
|
||||||
|
// control particle precomputed influence
|
||||||
|
std::vector< std::vector<ControlForces> > mCpForces;
|
||||||
|
std::vector<ControlForces> mCpKernel;
|
||||||
|
std::vector<ControlForces> mMdKernel;
|
||||||
|
// activate differential velcon
|
||||||
|
LbmFloat mDiffVelCon;
|
||||||
|
|
||||||
|
// cp debug displau
|
||||||
|
LbmFloat mDebugCpscale, mDebugVelScale, mDebugCompavScale, mDebugAttScale, mDebugMaxdScale, mDebugAvgVelScale;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // LBM_TESTCLASS_H
|
@ -151,7 +151,7 @@ void *mmap(void *start, size_t len, int prot, int flags, int fd, off_t offset)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* munmap for windows */
|
/* munmap for windows */
|
||||||
long munmap(void *ptr, long size)
|
intptr_t munmap(void *ptr, intptr_t size)
|
||||||
{
|
{
|
||||||
MemMap *mm = mmap_findlink(mmapbase, ptr);
|
MemMap *mm = mmap_findlink(mmapbase, ptr);
|
||||||
if (!mm) {
|
if (!mm) {
|
||||||
|
@ -45,7 +45,10 @@
|
|||||||
|
|
||||||
#define MAP_FAILED ((void *)-1)
|
#define MAP_FAILED ((void *)-1)
|
||||||
|
|
||||||
|
#include "BLO_sys_types.h" // needed for intptr_t
|
||||||
|
|
||||||
void *mmap(void *start, size_t len, int prot, int flags, int fd, off_t offset);
|
void *mmap(void *start, size_t len, int prot, int flags, int fd, off_t offset);
|
||||||
long munmap(void *ptr, long size);
|
intptr_t munmap(void *ptr, intptr_t size);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -118,7 +118,6 @@ install: package
|
|||||||
ifneq ($(OS), darwin)
|
ifneq ($(OS), darwin)
|
||||||
@[ ! -d $(OCGDIR)/bin/.blender ] || \
|
@[ ! -d $(OCGDIR)/bin/.blender ] || \
|
||||||
cp -r $(OCGDIR)/bin/.blender $(DISTDIR)
|
cp -r $(OCGDIR)/bin/.blender $(DISTDIR)
|
||||||
@rm -rf $(DISTDIR)/.svn $(DISTDIR)/*/.svn $(DISTDIR)/*/*/.svn
|
|
||||||
@cp $(NANBLENDERHOME)/bin/.blender/.Blanguages $(CONFDIR)
|
@cp $(NANBLENDERHOME)/bin/.blender/.Blanguages $(CONFDIR)
|
||||||
@cp $(NANBLENDERHOME)/bin/.blender/.bfont.ttf $(CONFDIR)
|
@cp $(NANBLENDERHOME)/bin/.blender/.bfont.ttf $(CONFDIR)
|
||||||
endif
|
endif
|
||||||
@ -144,8 +143,7 @@ ifneq ($(NOPLUGINS),true)
|
|||||||
@cp ../source/blender/blenpluginapi/*.h $(DISTDIR)/plugins/include/
|
@cp ../source/blender/blenpluginapi/*.h $(DISTDIR)/plugins/include/
|
||||||
@chmod 755 $(DISTDIR)/plugins/bmake
|
@chmod 755 $(DISTDIR)/plugins/bmake
|
||||||
@$(MAKE) -C $(DISTDIR)/plugins all > /dev/null || exit 1;
|
@$(MAKE) -C $(DISTDIR)/plugins all > /dev/null || exit 1;
|
||||||
@rm -fr $(DISTDIR)/plugins/.svn $(DISTDIR)/plugins/*/.svn \
|
@rm -f $(DISTDIR)/plugins/*/*.o
|
||||||
$(DISTDIR)/plugins/*/*.o
|
|
||||||
|
|
||||||
#on OS X the plugins move to the installation directory
|
#on OS X the plugins move to the installation directory
|
||||||
ifneq ($(OS),darwin)
|
ifneq ($(OS),darwin)
|
||||||
@ -158,7 +156,6 @@ endif
|
|||||||
|
|
||||||
@echo "----> Copy python infrastructure"
|
@echo "----> Copy python infrastructure"
|
||||||
@[ ! -d scripts ] || cp -r scripts $(CONFDIR)/scripts
|
@[ ! -d scripts ] || cp -r scripts $(CONFDIR)/scripts
|
||||||
@[ ! -d $(CONFDIR)/scripts ] || rm -fr $(CONFDIR)/scripts/.svn $(CONFDIR)/scripts/*/.svn $(CONFDIR)/scripts/*/*/.svn
|
|
||||||
|
|
||||||
ifeq ($(OS),darwin)
|
ifeq ($(OS),darwin)
|
||||||
@echo "----> Move .blender to .app/Contents/MacOS/"
|
@echo "----> Move .blender to .app/Contents/MacOS/"
|
||||||
@ -180,6 +177,8 @@ endif
|
|||||||
@[ ! -x $(CONFIG_GUESS)/specific.sh ] || (\
|
@[ ! -x $(CONFIG_GUESS)/specific.sh ] || (\
|
||||||
echo "**--> Execute specific.sh in $(CONFIG_GUESS)/" && \
|
echo "**--> Execute specific.sh in $(CONFIG_GUESS)/" && \
|
||||||
cd $(CONFIG_GUESS) && ./specific.sh )
|
cd $(CONFIG_GUESS) && ./specific.sh )
|
||||||
|
@echo "----> Cleaning .svn metadata directories"
|
||||||
|
@find $(DISTDIR) -type d -name ".svn" | xargs rm -fr
|
||||||
|
|
||||||
pkg: install
|
pkg: install
|
||||||
@echo "----> Create distribution file $(BLENDNAME)$(EXT1)"
|
@echo "----> Create distribution file $(BLENDNAME)$(EXT1)"
|
||||||
|
@ -69,10 +69,6 @@ def add_mesh_simple(name, verts, edges, faces):
|
|||||||
# Mesh with no data, unlikely
|
# Mesh with no data, unlikely
|
||||||
me.edges.extend(edges)
|
me.edges.extend(edges)
|
||||||
me.faces.extend(faces)
|
me.faces.extend(faces)
|
||||||
|
|
||||||
if is_editmode or Blender.Get('add_editmode'):
|
|
||||||
EditMode(1)
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
|
||||||
# Object mode add new
|
# Object mode add new
|
||||||
@ -96,10 +92,15 @@ def add_mesh_simple(name, verts, edges, faces):
|
|||||||
|
|
||||||
ob_act.loc = cursor
|
ob_act.loc = cursor
|
||||||
|
|
||||||
|
me.calcNormals()
|
||||||
|
|
||||||
if is_editmode or Blender.Get('add_editmode'):
|
if is_editmode or Blender.Get('add_editmode'):
|
||||||
EditMode(1)
|
EditMode(1)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def write_mesh_script(filepath, me):
|
def write_mesh_script(filepath, me):
|
||||||
'''
|
'''
|
||||||
filepath - path to py file
|
filepath - path to py file
|
||||||
@ -112,7 +113,7 @@ def write_mesh_script(filepath, me):
|
|||||||
file.write('#!BPY\n')
|
file.write('#!BPY\n')
|
||||||
file.write('"""\n')
|
file.write('"""\n')
|
||||||
file.write('Name: \'%s\'\n' % name)
|
file.write('Name: \'%s\'\n' % name)
|
||||||
file.write('Blender: 243\n')
|
file.write('Blender: 245\n')
|
||||||
file.write('Group: \'AddMesh\'\n')
|
file.write('Group: \'AddMesh\'\n')
|
||||||
file.write('"""\n\n')
|
file.write('"""\n\n')
|
||||||
file.write('import BPyAddMesh\n')
|
file.write('import BPyAddMesh\n')
|
||||||
|
479
release/scripts/ms3d_import_ascii.py
Normal file
479
release/scripts/ms3d_import_ascii.py
Normal file
@ -0,0 +1,479 @@
|
|||||||
|
#!BPY
|
||||||
|
"""
|
||||||
|
Name: 'MilkShape3D ASCII (.txt)...'
|
||||||
|
Blender: 245
|
||||||
|
Group: 'Import'
|
||||||
|
Tooltip: 'Import from a MilkShape3D ASCII file format (.txt)'
|
||||||
|
"""
|
||||||
|
#
|
||||||
|
# Author: Markus Ilmola
|
||||||
|
# Email: markus.ilmola@pp.inet.fi
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the GNU General Public License
|
||||||
|
# as published by the Free Software Foundation; either version 2
|
||||||
|
# of the License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
#
|
||||||
|
|
||||||
|
# import needed stuff
|
||||||
|
import os.path
|
||||||
|
import re
|
||||||
|
import math
|
||||||
|
from math import *
|
||||||
|
import Blender
|
||||||
|
from Blender import Mathutils
|
||||||
|
from Blender.Mathutils import *
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Converts ms3d euler angles to a rotation matrix
|
||||||
|
def RM(a):
|
||||||
|
sy = sin(a[2])
|
||||||
|
cy = cos(a[2])
|
||||||
|
sp = sin(a[1])
|
||||||
|
cp = cos(a[1])
|
||||||
|
sr = sin(a[0])
|
||||||
|
cr = cos(a[0])
|
||||||
|
return Matrix([cp*cy, cp*sy, -sp], [sr*sp*cy+cr*-sy, sr*sp*sy+cr*cy, sr*cp],[cr*sp*cy+-sr*-sy, cr*sp*sy+-sr*cy, cr*cp])
|
||||||
|
|
||||||
|
|
||||||
|
# Converts ms3d euler angles to a quaternion
|
||||||
|
def RQ(a):
|
||||||
|
angle = a[2] * 0.5;
|
||||||
|
sy = sin(angle);
|
||||||
|
cy = cos(angle);
|
||||||
|
angle = a[1] * 0.5;
|
||||||
|
sp = sin(angle);
|
||||||
|
cp = cos(angle);
|
||||||
|
angle = a[0] * 0.5;
|
||||||
|
sr = sin(angle);
|
||||||
|
cr = cos(angle);
|
||||||
|
return Quaternion(cr*cp*cy+sr*sp*sy, sr*cp*cy-cr*sp*sy, cr*sp*cy+sr*cp*sy, cr*cp*sy-sr*sp*cy)
|
||||||
|
|
||||||
|
|
||||||
|
# takes a texture filename and tries to load it
|
||||||
|
def loadImage(path, filename):
|
||||||
|
image = None
|
||||||
|
try:
|
||||||
|
image = Blender.Image.Load(os.path.abspath(filename))
|
||||||
|
except IOError:
|
||||||
|
print "Warning: Failed to load image: " + filename + ". Trying short path instead...\n"
|
||||||
|
try:
|
||||||
|
image = Blender.Image.Load(os.path.dirname(path) + "/" + os.path.basename(filename))
|
||||||
|
except IOError:
|
||||||
|
print "Warning: Failed to load image: " + os.path.basename(filename) + "!\n"
|
||||||
|
return image
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# returns the next non-empty, non-comment line from the file
|
||||||
|
def getNextLine(file):
|
||||||
|
ready = False
|
||||||
|
while ready==False:
|
||||||
|
line = file.readline()
|
||||||
|
if len(line)==0:
|
||||||
|
print "Warning: End of file reached."
|
||||||
|
return line
|
||||||
|
ready = True
|
||||||
|
line = line.strip()
|
||||||
|
if len(line)==0 or line.isspace():
|
||||||
|
ready = False
|
||||||
|
if len(line)>=2 and line[0]=='/' and line[1]=='/':
|
||||||
|
ready = False
|
||||||
|
return line
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# imports a MilkShape3D ascii file to the current scene
|
||||||
|
def import_ms3d_ascii(path):
|
||||||
|
# limits
|
||||||
|
MAX_NUMMESHES = 1000
|
||||||
|
MAX_NUMVERTS = 100000
|
||||||
|
MAX_NUMNORMALS = 100000
|
||||||
|
MAX_NUMTRIS = 100000
|
||||||
|
MAX_NUMMATS = 16
|
||||||
|
MAX_NUMBONES = 100
|
||||||
|
MAX_NUMPOSKEYS = 1000
|
||||||
|
MAX_NUMROTKEYS = 1000
|
||||||
|
|
||||||
|
# get scene
|
||||||
|
scn = Blender.Scene.GetCurrent()
|
||||||
|
if scn==None:
|
||||||
|
return "No scene to import to!"
|
||||||
|
|
||||||
|
# open the file
|
||||||
|
try:
|
||||||
|
file = open(path, 'r')
|
||||||
|
except IOError:
|
||||||
|
return "Failed to open the file!"
|
||||||
|
|
||||||
|
# Read frame info
|
||||||
|
try:
|
||||||
|
lines = getNextLine(file).split()
|
||||||
|
if len(lines) != 2 or lines[0] != "Frames:":
|
||||||
|
raise ValueError
|
||||||
|
lines = getNextLine(file).split()
|
||||||
|
if len(lines) != 2 or lines[0] != "Frame:":
|
||||||
|
raise ValueError
|
||||||
|
except ValueError:
|
||||||
|
return "Frame information is invalid!"
|
||||||
|
|
||||||
|
# Create the mesh
|
||||||
|
meshOb = Blender.Object.New('Mesh', "MilkShape3D Object")
|
||||||
|
mesh = Blender.Mesh.New("MilkShape3D Mesh")
|
||||||
|
meshOb.link(mesh)
|
||||||
|
scn.objects.link(meshOb)
|
||||||
|
|
||||||
|
# read the number of meshes
|
||||||
|
try:
|
||||||
|
lines = getNextLine(file).split()
|
||||||
|
if len(lines)!=2 or lines[0]!="Meshes:":
|
||||||
|
raise ValueError
|
||||||
|
numMeshes = int(lines[1])
|
||||||
|
if numMeshes < 0 or numMeshes > MAX_NUMMESHES:
|
||||||
|
raise ValueError
|
||||||
|
except ValueError:
|
||||||
|
return "Number of meshes is invalid!"
|
||||||
|
|
||||||
|
# read meshes
|
||||||
|
vertBase = 0
|
||||||
|
faceBase = 0
|
||||||
|
boneIds = []
|
||||||
|
for i in range(numMeshes):
|
||||||
|
# read name, flags and material
|
||||||
|
try:
|
||||||
|
lines = re.findall(r'\".*\"|[^ ]+', getNextLine(file))
|
||||||
|
if len(lines)!=3:
|
||||||
|
raise ValueError
|
||||||
|
material = int(lines[2])
|
||||||
|
except ValueError:
|
||||||
|
return "Name, flags or material in mesh " + str(i+1) + " are invalid!"
|
||||||
|
|
||||||
|
# read the number of vertices
|
||||||
|
try:
|
||||||
|
numVerts = int(getNextLine(file))
|
||||||
|
if numVerts < 0 or numVerts > MAX_NUMVERTS:
|
||||||
|
raise ValueError
|
||||||
|
except ValueError:
|
||||||
|
return "Number of vertices in mesh " + str(i+1) + " is invalid!"
|
||||||
|
|
||||||
|
# read vertices
|
||||||
|
coords = []
|
||||||
|
uvs = []
|
||||||
|
for j in xrange(numVerts):
|
||||||
|
try:
|
||||||
|
lines = getNextLine(file).split()
|
||||||
|
if len(lines)!=7:
|
||||||
|
raise ValueError
|
||||||
|
coords.append([float(lines[1]), float(lines[2]), float(lines[3])])
|
||||||
|
uvs.append([float(lines[4]), 1-float(lines[5])])
|
||||||
|
boneIds.append(int(lines[6]))
|
||||||
|
except ValueError:
|
||||||
|
return "Vertex " + str(j+1) + " in mesh " + str(i+1) + " is invalid!"
|
||||||
|
mesh.verts.extend(coords)
|
||||||
|
|
||||||
|
# read number of normals
|
||||||
|
try:
|
||||||
|
numNormals = int(getNextLine(file))
|
||||||
|
if numNormals < 0 or numNormals > MAX_NUMNORMALS:
|
||||||
|
raise ValueError
|
||||||
|
except ValueError:
|
||||||
|
return "Number of normals in mesh " + str(i+1) + " is invalid!"
|
||||||
|
|
||||||
|
# read normals
|
||||||
|
normals = []
|
||||||
|
for j in xrange(numNormals):
|
||||||
|
try:
|
||||||
|
lines = getNextLine(file).split()
|
||||||
|
if len(lines)!=3:
|
||||||
|
raise ValueError
|
||||||
|
normals.append([float(lines[0]), float(lines[1]), float(lines[2])])
|
||||||
|
except ValueError:
|
||||||
|
return "Normal " + str(j+1) + " in mesh " + str(i+1) + " is invalid!"
|
||||||
|
|
||||||
|
# read the number of triangles
|
||||||
|
try:
|
||||||
|
numTris = int(getNextLine(file))
|
||||||
|
if numTris < 0 or numTris > MAX_NUMTRIS:
|
||||||
|
raise ValueError
|
||||||
|
except ValueError:
|
||||||
|
return "Number of triangles in mesh " + str(i+1) + " is invalid!"
|
||||||
|
|
||||||
|
# read triangles
|
||||||
|
faces = []
|
||||||
|
for j in xrange(numTris):
|
||||||
|
# read the triangle
|
||||||
|
try:
|
||||||
|
lines = getNextLine(file).split()
|
||||||
|
if len(lines)!=8:
|
||||||
|
raise ValueError
|
||||||
|
v1 = int(lines[1])
|
||||||
|
v2 = int(lines[2])
|
||||||
|
v3 = int(lines[3])
|
||||||
|
faces.append([v1+vertBase, v2+vertBase, v3+vertBase])
|
||||||
|
except ValueError:
|
||||||
|
return "Triangle " + str(j+1) + " in mesh " + str(i+1) + " is invalid!"
|
||||||
|
mesh.faces.extend(faces)
|
||||||
|
|
||||||
|
# set texture coordinates and material
|
||||||
|
for j in xrange(faceBase, len(mesh.faces)):
|
||||||
|
face = mesh.faces[j]
|
||||||
|
face.uv = [Vector(uvs[face.verts[0].index-vertBase]), Vector(uvs[face.verts[1].index-vertBase]), Vector(uvs[face.verts[2].index-vertBase])]
|
||||||
|
if material>=0:
|
||||||
|
face.mat = material
|
||||||
|
|
||||||
|
# increase vertex and face base
|
||||||
|
vertBase = len(mesh.verts)
|
||||||
|
faceBase = len(mesh.faces)
|
||||||
|
|
||||||
|
# read the number of materials
|
||||||
|
try:
|
||||||
|
lines = getNextLine(file).split()
|
||||||
|
if len(lines)!=2 or lines[0]!="Materials:":
|
||||||
|
raise ValueError
|
||||||
|
numMats = int(lines[1])
|
||||||
|
if numMats < 0 or numMats > MAX_NUMMATS:
|
||||||
|
raise ValueError
|
||||||
|
except ValueError:
|
||||||
|
return "Number of materials is invalid!"
|
||||||
|
|
||||||
|
# read the materials
|
||||||
|
for i in range(numMats):
|
||||||
|
# read name
|
||||||
|
name = getNextLine(file)[1:-1]
|
||||||
|
|
||||||
|
# create the material
|
||||||
|
mat = Blender.Material.New(name)
|
||||||
|
mesh.materials += [mat]
|
||||||
|
|
||||||
|
# read ambient color
|
||||||
|
try:
|
||||||
|
lines = getNextLine(file).split()
|
||||||
|
if len(lines)!=4:
|
||||||
|
raise ValueError
|
||||||
|
amb = (float(lines[0])+float(lines[1])+float(lines[2]))/3
|
||||||
|
mat.setAmb(amb)
|
||||||
|
except ValueError:
|
||||||
|
return "Ambient color in material " + str(i+1) + " is invalid!"
|
||||||
|
|
||||||
|
# read diffuse color
|
||||||
|
try:
|
||||||
|
lines = getNextLine(file).split()
|
||||||
|
if len(lines)!=4:
|
||||||
|
raise ValueError
|
||||||
|
mat.setRGBCol([float(lines[0]), float(lines[1]), float(lines[2])])
|
||||||
|
except ValueError:
|
||||||
|
return "Diffuse color in material " + str(i+1) + " is invalid!"
|
||||||
|
|
||||||
|
# read specular color
|
||||||
|
try:
|
||||||
|
lines = getNextLine(file).split()
|
||||||
|
if len(lines)!=4:
|
||||||
|
raise ValueError
|
||||||
|
mat.setSpecCol([float(lines[0]), float(lines[1]), float(lines[2])])
|
||||||
|
except ValueError:
|
||||||
|
return "Specular color in material " + str(i+1) + " is invalid!"
|
||||||
|
|
||||||
|
# read emissive color
|
||||||
|
try:
|
||||||
|
lines = getNextLine(file).split()
|
||||||
|
if len(lines)!=4:
|
||||||
|
raise ValueError
|
||||||
|
emit = (float(lines[0])+float(lines[1])+float(lines[2]))/3
|
||||||
|
mat.setEmit(emit)
|
||||||
|
except ValueError:
|
||||||
|
return "Emissive color in material " + str(i+1) + " is invalid!"
|
||||||
|
|
||||||
|
# read shininess
|
||||||
|
try:
|
||||||
|
shi = float(getNextLine(file))
|
||||||
|
#mat.setHardness(int(shi))
|
||||||
|
except ValueError:
|
||||||
|
return "Shininess in material " + str(i+1) + " is invalid!"
|
||||||
|
|
||||||
|
# read transparency
|
||||||
|
try:
|
||||||
|
alpha = float(getNextLine(file))
|
||||||
|
mat.setAlpha(alpha)
|
||||||
|
if alpha < 1:
|
||||||
|
mat.mode |= Blender.Material.Modes.ZTRANSP
|
||||||
|
except ValueError:
|
||||||
|
return "Transparency in material " + str(i+1) + " is invalid!"
|
||||||
|
|
||||||
|
# read texturemap
|
||||||
|
texturemap = getNextLine(file)[1:-1]
|
||||||
|
if len(texturemap)>0:
|
||||||
|
colorTexture = Blender.Texture.New(name + "_texture")
|
||||||
|
colorTexture.setType('Image')
|
||||||
|
colorTexture.setImage(loadImage(path, texturemap))
|
||||||
|
mat.setTexture(0, colorTexture, Blender.Texture.TexCo.UV, Blender.Texture.MapTo.COL)
|
||||||
|
|
||||||
|
# read alphamap
|
||||||
|
alphamap = getNextLine(file)[1:-1]
|
||||||
|
if len(alphamap)>0:
|
||||||
|
alphaTexture = Blender.Texture.New(name + "_alpha")
|
||||||
|
alphaTexture.setType('Image')
|
||||||
|
alphaTexture.setImage(loadImage(path, alphamap))
|
||||||
|
mat.setTexture(1, alphaTexture, Blender.Texture.TexCo.UV, Blender.Texture.MapTo.ALPHA)
|
||||||
|
|
||||||
|
# read the number of bones
|
||||||
|
try:
|
||||||
|
lines = getNextLine(file).split()
|
||||||
|
if len(lines)!=2 or lines[0]!="Bones:":
|
||||||
|
raise ValueError
|
||||||
|
numBones = int(lines[1])
|
||||||
|
if numBones < 0 or numBones > MAX_NUMBONES:
|
||||||
|
raise ValueError
|
||||||
|
except:
|
||||||
|
return "Number of bones is invalid!"
|
||||||
|
|
||||||
|
# create the armature
|
||||||
|
armature = None
|
||||||
|
armOb = None
|
||||||
|
if numBones > 0:
|
||||||
|
armOb = Blender.Object.New('Armature', "MilkShape3D Skeleton")
|
||||||
|
armature = Blender.Armature.New("MilkShape3D Skeleton")
|
||||||
|
armature.drawType = Blender.Armature.STICK
|
||||||
|
armOb.link(armature)
|
||||||
|
scn.objects.link(armOb)
|
||||||
|
armOb.makeParentDeform([meshOb])
|
||||||
|
armature.makeEditable()
|
||||||
|
|
||||||
|
# read bones
|
||||||
|
posKeys = {}
|
||||||
|
rotKeys = {}
|
||||||
|
for i in range(numBones):
|
||||||
|
# read name
|
||||||
|
name = getNextLine(file)[1:-1]
|
||||||
|
|
||||||
|
# create the bone
|
||||||
|
bone = Blender.Armature.Editbone()
|
||||||
|
armature.bones[name] = bone
|
||||||
|
|
||||||
|
# read parent
|
||||||
|
parent = getNextLine(file)[1:-1]
|
||||||
|
if len(parent)>0:
|
||||||
|
bone.parent = armature.bones[parent]
|
||||||
|
|
||||||
|
# read position and rotation
|
||||||
|
try:
|
||||||
|
lines = getNextLine(file).split()
|
||||||
|
if len(lines) != 7:
|
||||||
|
raise ValueError
|
||||||
|
pos = [float(lines[1]), float(lines[2]), float(lines[3])]
|
||||||
|
rot = [float(lines[4]), float(lines[5]), float(lines[6])]
|
||||||
|
except ValueError:
|
||||||
|
return "Invalid position or orientation in a bone!"
|
||||||
|
|
||||||
|
# set position and orientation
|
||||||
|
if bone.hasParent():
|
||||||
|
bone.head = Vector(pos) * bone.parent.matrix + bone.parent.head
|
||||||
|
bone.tail = bone.head + Vector([1,0,0])
|
||||||
|
tempM = RM(rot) * bone.parent.matrix
|
||||||
|
tempM.transpose;
|
||||||
|
bone.matrix = tempM
|
||||||
|
else:
|
||||||
|
bone.head = Vector(pos)
|
||||||
|
bone.tail = bone.head + Vector([1,0,0])
|
||||||
|
bone.matrix = RM(rot)
|
||||||
|
|
||||||
|
# Create vertex group for this bone
|
||||||
|
mesh.addVertGroup(name)
|
||||||
|
vgroup = []
|
||||||
|
for index, v in enumerate(boneIds):
|
||||||
|
if v==i:
|
||||||
|
vgroup.append(index)
|
||||||
|
mesh.assignVertsToGroup(name, vgroup, 1.0, 1)
|
||||||
|
|
||||||
|
# read the number of position key frames
|
||||||
|
try:
|
||||||
|
numPosKeys = int(getNextLine(file))
|
||||||
|
if numPosKeys < 0 or numPosKeys > MAX_NUMPOSKEYS:
|
||||||
|
raise ValueError
|
||||||
|
except ValueError:
|
||||||
|
return "Invalid number of position key frames!"
|
||||||
|
|
||||||
|
# read position key frames
|
||||||
|
posKeys[name] = []
|
||||||
|
for j in range(numPosKeys):
|
||||||
|
# read time and position
|
||||||
|
try:
|
||||||
|
lines = getNextLine(file).split()
|
||||||
|
if len(lines) != 4:
|
||||||
|
raise ValueError
|
||||||
|
time = float(lines[0])
|
||||||
|
pos = [float(lines[1]), float(lines[2]), float(lines[3])]
|
||||||
|
posKeys[name].append([time, pos])
|
||||||
|
except ValueError:
|
||||||
|
return "Invalid position key frame!"
|
||||||
|
|
||||||
|
# read the number of rotation key frames
|
||||||
|
try:
|
||||||
|
numRotKeys = int(getNextLine(file))
|
||||||
|
if numRotKeys < 0 or numRotKeys > MAX_NUMROTKEYS:
|
||||||
|
raise ValueError
|
||||||
|
except ValueError:
|
||||||
|
return "Invalid number of rotation key frames!"
|
||||||
|
|
||||||
|
# read rotation key frames
|
||||||
|
rotKeys[name] = []
|
||||||
|
for j in range(numRotKeys):
|
||||||
|
# read time and rotation
|
||||||
|
try:
|
||||||
|
lines = getNextLine(file).split()
|
||||||
|
if len(lines) != 4:
|
||||||
|
raise ValueError
|
||||||
|
time = float(lines[0])
|
||||||
|
rot = [float(lines[1]), float(lines[2]), float(lines[3])]
|
||||||
|
rotKeys[name].append([time, rot])
|
||||||
|
except ValueError:
|
||||||
|
return "Invalid rotation key frame!"
|
||||||
|
|
||||||
|
# create action and pose
|
||||||
|
action = None
|
||||||
|
pose = None
|
||||||
|
if armature != None:
|
||||||
|
armature.update()
|
||||||
|
pose = armOb.getPose()
|
||||||
|
action = armOb.getAction()
|
||||||
|
if not action:
|
||||||
|
action = Blender.Armature.NLA.NewAction()
|
||||||
|
action.setActive(armOb)
|
||||||
|
|
||||||
|
# create animation key frames
|
||||||
|
for name, pbone in pose.bones.items():
|
||||||
|
# create position keys
|
||||||
|
for key in posKeys[name]:
|
||||||
|
pbone.loc = Vector(key[1])
|
||||||
|
pbone.insertKey(armOb, int(key[0]+0.5), Blender.Object.Pose.LOC, True)
|
||||||
|
|
||||||
|
# create rotation keys
|
||||||
|
for key in rotKeys[name]:
|
||||||
|
pbone.quat = RQ(key[1])
|
||||||
|
pbone.insertKey(armOb, int(key[0]+0.5), Blender.Object.Pose.ROT, True)
|
||||||
|
|
||||||
|
# set the imported object to be the selected one
|
||||||
|
scn.objects.selected = []
|
||||||
|
meshOb.sel= 1
|
||||||
|
Blender.Redraw()
|
||||||
|
|
||||||
|
# The import was a succes!
|
||||||
|
return ""
|
||||||
|
|
||||||
|
|
||||||
|
# load the model
|
||||||
|
def fileCallback(filename):
|
||||||
|
error = import_ms3d_ascii(filename)
|
||||||
|
if error!="":
|
||||||
|
Blender.Draw.PupMenu("An error occured during import: " + error + "|Not all data might have been imported succesfully.", 2)
|
||||||
|
|
||||||
|
Blender.Window.FileSelector(fileCallback, 'Import')
|
93
release/scripts/scripttemplate_gamelogic.py
Normal file
93
release/scripts/scripttemplate_gamelogic.py
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
#!BPY
|
||||||
|
"""
|
||||||
|
Name: 'GameLogic Example'
|
||||||
|
Blender: 245
|
||||||
|
Group: 'ScriptTemplate'
|
||||||
|
Tooltip: 'Script template with examples of how to use game logic'
|
||||||
|
"""
|
||||||
|
|
||||||
|
from Blender import Window
|
||||||
|
import bpy
|
||||||
|
|
||||||
|
script_data = \
|
||||||
|
'''
|
||||||
|
# GameLogic has been added to the global namespace no need to import
|
||||||
|
|
||||||
|
# for keyboard event comparison
|
||||||
|
# import GameKeys
|
||||||
|
|
||||||
|
# support for Vector(), Matrix() types and advanced functions like AngleBetweenVecs(v1,v2) and RotationMatrix(...)
|
||||||
|
# import Mathutils
|
||||||
|
|
||||||
|
# for functions like getWindowWidth(), getWindowHeight()
|
||||||
|
# import Rasterizer
|
||||||
|
|
||||||
|
def main():
|
||||||
|
cont = GameLogic.getCurrentController()
|
||||||
|
|
||||||
|
# The KX_GameObject that owns this controller.
|
||||||
|
own = cont.getOwner()
|
||||||
|
|
||||||
|
# for scripts that deal with spacial logic
|
||||||
|
own_pos = own.getPosition()
|
||||||
|
|
||||||
|
|
||||||
|
# Some example functions, remove to write your own script.
|
||||||
|
# check for a positive sensor, will run on any object without errors.
|
||||||
|
print 'Logic info for KX_GameObject', own.getName()
|
||||||
|
input = False
|
||||||
|
|
||||||
|
for sens in cont.getSensors():
|
||||||
|
# The sensor can be on another object, we may want to use it
|
||||||
|
own_sens = sens.getOwner()
|
||||||
|
print ' sensor:', sens.getName(),
|
||||||
|
if sens.isPositive():
|
||||||
|
print '(true)'
|
||||||
|
input = True
|
||||||
|
else:
|
||||||
|
print '(false)'
|
||||||
|
|
||||||
|
for actu in cont.getActuators():
|
||||||
|
# The actuator can be on another object, we may want to use it
|
||||||
|
own_actu = actu.getOwner()
|
||||||
|
print ' actuator:', sens.getName()
|
||||||
|
|
||||||
|
# This runs the actuator or turns it off
|
||||||
|
# note that actuators will continue to run unless explicitly turned off.
|
||||||
|
if input:
|
||||||
|
GameLogic.addActiveActuator(actu, True)
|
||||||
|
else:
|
||||||
|
GameLogic.addActiveActuator(actu, False)
|
||||||
|
|
||||||
|
# Its also good practice to get sensors and actuators by names
|
||||||
|
# so any changes to their order wont break the script.
|
||||||
|
|
||||||
|
# sens_key = cont.getSensor('key_sensor')
|
||||||
|
# actu_motion = cont.getActuator('motion')
|
||||||
|
|
||||||
|
|
||||||
|
# Loop through all other objects in the scene
|
||||||
|
sce = GameLogic.getCurrentScene()
|
||||||
|
print 'Scene Objects:', sce.getName()
|
||||||
|
for ob in sce.getObjectList():
|
||||||
|
print ' ', ob.getName(), ob.getPosition()
|
||||||
|
|
||||||
|
|
||||||
|
# Example where collision objects are checked for their properties
|
||||||
|
# adding to our objects "life" property
|
||||||
|
"""
|
||||||
|
actu_collide = cont.getSensor('collision_sens')
|
||||||
|
for ob in actu_collide.getHitObjectList():
|
||||||
|
# Check to see the object has this property
|
||||||
|
if hasattr(ob, 'life'):
|
||||||
|
own.life += ob.life
|
||||||
|
ob.life = 0
|
||||||
|
print own.life
|
||||||
|
"""
|
||||||
|
main()
|
||||||
|
'''
|
||||||
|
|
||||||
|
new_text = bpy.data.texts.new('gamelogic_example.py')
|
||||||
|
new_text.write(script_data)
|
||||||
|
bpy.data.texts.active = new_text
|
||||||
|
Window.RedrawAll()
|
33
release/scripts/scripttemplate_gamelogic_basic.py
Normal file
33
release/scripts/scripttemplate_gamelogic_basic.py
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
#!BPY
|
||||||
|
"""
|
||||||
|
Name: 'GameLogic Template'
|
||||||
|
Blender: 245
|
||||||
|
Group: 'ScriptTemplate'
|
||||||
|
Tooltip: 'Basic template for new game logic scripts'
|
||||||
|
"""
|
||||||
|
|
||||||
|
from Blender import Window
|
||||||
|
import bpy
|
||||||
|
|
||||||
|
script_data = \
|
||||||
|
'''
|
||||||
|
def main():
|
||||||
|
|
||||||
|
cont = GameLogic.getCurrentController()
|
||||||
|
own = cont.getOwner()
|
||||||
|
|
||||||
|
sens = cont.getSensor('mySensor')
|
||||||
|
actu = cont.getActuator('myActuator')
|
||||||
|
|
||||||
|
if sens.isPositive():
|
||||||
|
GameLogic.addActiveActuator(actu, True)
|
||||||
|
else:
|
||||||
|
GameLogic.addActiveActuator(actu, False)
|
||||||
|
|
||||||
|
main()
|
||||||
|
'''
|
||||||
|
|
||||||
|
new_text = bpy.data.texts.new('gamelogic_example.py')
|
||||||
|
new_text.write(script_data)
|
||||||
|
bpy.data.texts.active = new_text
|
||||||
|
Window.RedrawAll()
|
92
release/scripts/scripttemplate_ipo_gen.py
Normal file
92
release/scripts/scripttemplate_ipo_gen.py
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
#!BPY
|
||||||
|
"""
|
||||||
|
Name: 'IPO Example'
|
||||||
|
Blender: 245
|
||||||
|
Group: 'ScriptTemplate'
|
||||||
|
Tooltip: 'Script template for setting the IPO'
|
||||||
|
"""
|
||||||
|
|
||||||
|
from Blender import Window
|
||||||
|
import bpy
|
||||||
|
|
||||||
|
script_data = \
|
||||||
|
'''#!BPY
|
||||||
|
"""
|
||||||
|
Name: 'My Ipo Script'
|
||||||
|
Blender: 245
|
||||||
|
Group: 'Animation'
|
||||||
|
Tooltip: 'Put some useful info here'
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Add a licence here if you wish to re-distribute, we recommend the GPL
|
||||||
|
|
||||||
|
from Blender import Ipo, Mathutils, Window
|
||||||
|
import bpy, BPyMessages
|
||||||
|
|
||||||
|
def makeRandomIpo(object, firstFrame, numberOfFrames, frameStep):
|
||||||
|
# Create an new Ipo Curve of name myIpo and type Object
|
||||||
|
myIpo = bpy.data.ipos.new('myIpo', 'Object')
|
||||||
|
|
||||||
|
# Create LocX, LocY, and LocZ Ipo curves in our new Curve Object
|
||||||
|
# and store them so we can access them later
|
||||||
|
myIpo_x = myIpo.addCurve('LocX')
|
||||||
|
myIpo_y = myIpo.addCurve('LocY')
|
||||||
|
myIpo_z = myIpo.addCurve('LocZ')
|
||||||
|
|
||||||
|
# What value we want to scale our random value by
|
||||||
|
ipoScale = 4
|
||||||
|
|
||||||
|
# This Calculates the End Frame for use in an xrange() expression
|
||||||
|
endFrame = firstFrame + (numberOfFrames * frameStep) + frameStep
|
||||||
|
|
||||||
|
for frame in xrange(firstFrame, endFrame, frameStep):
|
||||||
|
|
||||||
|
# Use the Mathutils Rand() function to get random numbers
|
||||||
|
ipoValue_x = Mathutils.Rand(-1, 1) * ipoScale
|
||||||
|
ipoValue_y = Mathutils.Rand(-1, 1) * ipoScale
|
||||||
|
ipoValue_z = Mathutils.Rand(-1, 1) * ipoScale
|
||||||
|
|
||||||
|
# Append to the Ipo curve at location frame, with the value ipoValue_x
|
||||||
|
# Note that we should pass the append function a tuple or a BezTriple
|
||||||
|
myIpo_x.append((frame, ipoValue_x))
|
||||||
|
|
||||||
|
# Similar to above
|
||||||
|
myIpo_y.append((frame, ipoValue_y))
|
||||||
|
myIpo_z.append((frame, ipoValue_z))
|
||||||
|
|
||||||
|
# Link our new Ipo Curve to the passed object
|
||||||
|
object.setIpo(myIpo)
|
||||||
|
print object
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
|
||||||
|
# Get the active scene, since there can be multiple ones
|
||||||
|
sce = bpy.data.scenes.active
|
||||||
|
|
||||||
|
# Get the active object
|
||||||
|
object = sce.objects.active
|
||||||
|
|
||||||
|
# If there is no active object, pop up an error message
|
||||||
|
if not object:
|
||||||
|
BPyMessages.Error_NoActive()
|
||||||
|
|
||||||
|
Window.WaitCursor(1)
|
||||||
|
|
||||||
|
# Call our makeRandomIpo function
|
||||||
|
# Pass it our object, Tell it to keys from the start frame until the end frame, at a step of 10 frames
|
||||||
|
# between them
|
||||||
|
|
||||||
|
makeRandomIpo(object, sce.render.sFrame, sce.render.eFrame, 10)
|
||||||
|
|
||||||
|
Window.WaitCursor(0)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
|
|
||||||
|
'''
|
||||||
|
|
||||||
|
new_text = bpy.data.texts.new('ipo_template.py')
|
||||||
|
new_text.write(script_data)
|
||||||
|
bpy.data.texts.active = new_text
|
||||||
|
Window.RedrawAll()
|
43
source/blender/blenkernel/BKE_bullet.h
Normal file
43
source/blender/blenkernel/BKE_bullet.h
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
* $Id: BKE_bullet.h 16773 2008-09-27 22:01:26Z ben2610 $
|
||||||
|
*
|
||||||
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
*
|
||||||
|
* The Original Code is Copyright (C) Blender Foundation.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* The Original Code is: all of this file.
|
||||||
|
*
|
||||||
|
* Contributor(s): none yet.
|
||||||
|
*
|
||||||
|
* ***** END GPL LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
#ifndef BKE_BULLET_H
|
||||||
|
#define BKE_BULLET_H
|
||||||
|
|
||||||
|
struct BulletSoftBody;
|
||||||
|
|
||||||
|
|
||||||
|
/* allocates and initializes general main data */
|
||||||
|
extern struct BulletSoftBody *bsbNew(void);
|
||||||
|
|
||||||
|
/* frees internal data and softbody itself */
|
||||||
|
extern void bsbFree(struct BulletSoftBody *sb);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
55
source/blender/blenkernel/BKE_fluidsim.h
Normal file
55
source/blender/blenkernel/BKE_fluidsim.h
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
/**
|
||||||
|
* BKE_fluidsim.h
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
*
|
||||||
|
* The Original Code is Copyright (C) Blender Foundation
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* The Original Code is: all of this file.
|
||||||
|
*
|
||||||
|
* Contributor(s): none yet.
|
||||||
|
*
|
||||||
|
* ***** END GPL LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "DNA_modifier_types.h"
|
||||||
|
#include "DNA_object_fluidsim.h" // N_T
|
||||||
|
#include "DNA_object_types.h"
|
||||||
|
|
||||||
|
#include "BKE_DerivedMesh.h"
|
||||||
|
|
||||||
|
/* old interface */
|
||||||
|
FluidsimSettings *fluidsimSettingsNew(Object *srcob);
|
||||||
|
|
||||||
|
void initElbeemMesh(Object *ob, int *numVertices, float **vertices, int *numTriangles, int **triangles, int useGlobalCoords, int modifierIndex);
|
||||||
|
|
||||||
|
|
||||||
|
/* new fluid-modifier interface */
|
||||||
|
void fluidsim_init(FluidsimModifierData *fluidmd);
|
||||||
|
void fluidsim_free(FluidsimModifierData *fluidmd);
|
||||||
|
|
||||||
|
DerivedMesh *fluidsim_read_cache(Object *ob, DerivedMesh *orgdm, FluidsimModifierData *fluidmd, int framenr, int useRenderParams);
|
||||||
|
DerivedMesh *fluidsimModifier_do(FluidsimModifierData *fluidmd, Object *ob, DerivedMesh *dm, int useRenderParams, int isFinalCalc);
|
||||||
|
|
||||||
|
// get bounding box of mesh
|
||||||
|
void fluid_get_bb(MVert *mvert, int totvert, float obmat[][4],
|
||||||
|
/*RET*/ float start[3], /*RET*/ float size[3] );
|
||||||
|
|
||||||
|
|
||||||
|
|
39
source/blender/blenkernel/BKE_simple_deform.h
Normal file
39
source/blender/blenkernel/BKE_simple_deform.h
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
/**
|
||||||
|
* BKE_shrinkwrap.h
|
||||||
|
*
|
||||||
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
*
|
||||||
|
* The Original Code is Copyright (C) Blender Foundation.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* The Original Code is: all of this file.
|
||||||
|
*
|
||||||
|
* Contributor(s): none yet.
|
||||||
|
*
|
||||||
|
* ***** END GPL LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
#ifndef BKE_SIMPLE_DEFORM_H
|
||||||
|
#define BKE_SIMPLE_DEFORM_H
|
||||||
|
|
||||||
|
struct Object;
|
||||||
|
struct DerivedMesh;
|
||||||
|
struct SimpleDeformModifierData;
|
||||||
|
|
||||||
|
void SimpleDeformModifier_do(SimpleDeformModifierData *smd, struct Object *ob, struct DerivedMesh *dm, float (*vertexCos)[3], int numVerts);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
95
source/blender/blenkernel/intern/bullet.c
Normal file
95
source/blender/blenkernel/intern/bullet.c
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
* $Id: bullet.c 16776 2008-09-28 03:07:13Z erwin $
|
||||||
|
*
|
||||||
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
*
|
||||||
|
* The Original Code is Copyright (C) Blender Foundation
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* The Original Code is: all of this file.
|
||||||
|
*
|
||||||
|
* Contributor(s): none yet.
|
||||||
|
*
|
||||||
|
* ***** END GPL LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "MEM_guardedalloc.h"
|
||||||
|
|
||||||
|
/* types */
|
||||||
|
#include "DNA_object_force.h" /* here is the softbody struct */
|
||||||
|
|
||||||
|
#include "BKE_bullet.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* ************ Object level, exported functions *************** */
|
||||||
|
|
||||||
|
/* allocates and initializes general main data */
|
||||||
|
BulletSoftBody *bsbNew(void)
|
||||||
|
{
|
||||||
|
BulletSoftBody *bsb;
|
||||||
|
|
||||||
|
bsb= MEM_callocN(sizeof(BulletSoftBody), "bulletsoftbody");
|
||||||
|
|
||||||
|
bsb->flag = OB_BSB_BENDING_CONSTRAINTS | OB_BSB_SHAPE_MATCHING | OB_BSB_AERO_VPOINT;
|
||||||
|
bsb->linStiff = 0.5f;
|
||||||
|
bsb->angStiff = 1.0f;
|
||||||
|
bsb->volume = 1.0f;
|
||||||
|
|
||||||
|
|
||||||
|
bsb->viterations = 0;
|
||||||
|
bsb->piterations = 2;
|
||||||
|
bsb->diterations = 0;
|
||||||
|
bsb->citerations = 4;
|
||||||
|
|
||||||
|
bsb->kSRHR_CL = 0.1f;
|
||||||
|
bsb->kSKHR_CL = 1.f;
|
||||||
|
bsb->kSSHR_CL = 0.5f;
|
||||||
|
bsb->kSR_SPLT_CL = 0.5f;
|
||||||
|
|
||||||
|
bsb->kSK_SPLT_CL = 0.5f;
|
||||||
|
bsb->kSS_SPLT_CL = 0.5f;
|
||||||
|
bsb->kVCF = 1;
|
||||||
|
bsb->kDP = 0;
|
||||||
|
|
||||||
|
bsb->kDG = 0;
|
||||||
|
bsb->kLF = 0;
|
||||||
|
bsb->kPR = 0;
|
||||||
|
bsb->kVC = 0;
|
||||||
|
|
||||||
|
bsb->kDF = 0.2f;
|
||||||
|
bsb->kMT = 0.05;
|
||||||
|
bsb->kCHR = 1.0f;
|
||||||
|
bsb->kKHR = 0.1f;
|
||||||
|
|
||||||
|
bsb->kSHR = 1.0f;
|
||||||
|
bsb->kAHR = 0.7f;
|
||||||
|
bsb->collisionflags = 0;
|
||||||
|
//bsb->collisionflags = OB_BSB_COL_CL_RS + OB_BSB_COL_CL_SS;
|
||||||
|
bsb->numclusteriterations = 64;
|
||||||
|
|
||||||
|
return bsb;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* frees all */
|
||||||
|
void bsbFree(BulletSoftBody *bsb)
|
||||||
|
{
|
||||||
|
/* no internal data yet */
|
||||||
|
MEM_freeN(bsb);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
642
source/blender/blenkernel/intern/fluidsim.c
Normal file
642
source/blender/blenkernel/intern/fluidsim.c
Normal file
@ -0,0 +1,642 @@
|
|||||||
|
/**
|
||||||
|
* fluidsim.c
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
*
|
||||||
|
* The Original Code is Copyright (C) Blender Foundation
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* The Original Code is: all of this file.
|
||||||
|
*
|
||||||
|
* Contributor(s): none yet.
|
||||||
|
*
|
||||||
|
* ***** END GPL LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "MEM_guardedalloc.h"
|
||||||
|
|
||||||
|
#include "DNA_mesh_types.h"
|
||||||
|
#include "DNA_meshdata_types.h"
|
||||||
|
#include "DNA_object_force.h" // for pointcache
|
||||||
|
#include "DNA_particle_types.h"
|
||||||
|
#include "DNA_scene_types.h" // N_T
|
||||||
|
|
||||||
|
#include "BLI_arithb.h"
|
||||||
|
#include "BLI_blenlib.h"
|
||||||
|
|
||||||
|
#include "BKE_cdderivedmesh.h"
|
||||||
|
#include "BKE_customdata.h"
|
||||||
|
#include "BKE_DerivedMesh.h"
|
||||||
|
#include "BKE_fluidsim.h"
|
||||||
|
#include "BKE_global.h"
|
||||||
|
#include "BKE_modifier.h"
|
||||||
|
#include "BKE_mesh.h"
|
||||||
|
#include "BKE_pointcache.h"
|
||||||
|
#include "BKE_utildefines.h"
|
||||||
|
|
||||||
|
// headers for fluidsim bobj meshes
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "LBM_fluidsim.h"
|
||||||
|
#include "elbeem.h"
|
||||||
|
#include <zlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
/* ************************* fluidsim bobj file handling **************************** */
|
||||||
|
|
||||||
|
// -----------------------------------------
|
||||||
|
// forward decleration
|
||||||
|
// -----------------------------------------
|
||||||
|
|
||||||
|
// -----------------------------------------
|
||||||
|
|
||||||
|
void fluidsim_init(FluidsimModifierData *fluidmd)
|
||||||
|
{
|
||||||
|
#ifndef DISABLE_ELBEEM
|
||||||
|
if(fluidmd)
|
||||||
|
{
|
||||||
|
FluidsimSettings *fss = MEM_callocN(sizeof(FluidsimSettings), "fluidsimsettings");
|
||||||
|
|
||||||
|
fluidmd->fss = fss;
|
||||||
|
|
||||||
|
if(!fss)
|
||||||
|
return;
|
||||||
|
|
||||||
|
fss->type = 0;
|
||||||
|
fss->show_advancedoptions = 0;
|
||||||
|
|
||||||
|
fss->resolutionxyz = 50;
|
||||||
|
fss->previewresxyz = 25;
|
||||||
|
fss->realsize = 0.03;
|
||||||
|
fss->guiDisplayMode = 2; // preview
|
||||||
|
fss->renderDisplayMode = 3; // render
|
||||||
|
|
||||||
|
fss->viscosityMode = 2; // default to water
|
||||||
|
fss->viscosityValue = 1.0;
|
||||||
|
fss->viscosityExponent = 6;
|
||||||
|
|
||||||
|
// dg TODO: change this to []
|
||||||
|
fss->gravx = 0.0;
|
||||||
|
fss->gravy = 0.0;
|
||||||
|
fss->gravz = -9.81;
|
||||||
|
fss->animStart = 0.0;
|
||||||
|
fss->animEnd = 0.30;
|
||||||
|
fss->gstar = 0.005; // used as normgstar
|
||||||
|
fss->maxRefine = -1;
|
||||||
|
// maxRefine is set according to resolutionxyz during bake
|
||||||
|
|
||||||
|
// fluid/inflow settings
|
||||||
|
// fss->iniVel --> automatically set to 0
|
||||||
|
|
||||||
|
/* elubie: changed this to default to the same dir as the render output
|
||||||
|
to prevent saving to C:\ on Windows */
|
||||||
|
BLI_strncpy(fss->surfdataPath, btempdir, FILE_MAX);
|
||||||
|
|
||||||
|
// first init of bounding box
|
||||||
|
// no bounding box needed
|
||||||
|
|
||||||
|
// todo - reuse default init from elbeem!
|
||||||
|
fss->typeFlags = 0;
|
||||||
|
fss->domainNovecgen = 0;
|
||||||
|
fss->volumeInitType = 1; // volume
|
||||||
|
fss->partSlipValue = 0.0;
|
||||||
|
|
||||||
|
fss->generateTracers = 0;
|
||||||
|
fss->generateParticles = 0.0;
|
||||||
|
fss->surfaceSmoothing = 1.0;
|
||||||
|
fss->surfaceSubdivs = 1.0;
|
||||||
|
fss->particleInfSize = 0.0;
|
||||||
|
fss->particleInfAlpha = 0.0;
|
||||||
|
|
||||||
|
// init fluid control settings
|
||||||
|
fss->attractforceStrength = 0.2;
|
||||||
|
fss->attractforceRadius = 0.75;
|
||||||
|
fss->velocityforceStrength = 0.2;
|
||||||
|
fss->velocityforceRadius = 0.75;
|
||||||
|
fss->cpsTimeStart = fss->animStart;
|
||||||
|
fss->cpsTimeEnd = fss->animEnd;
|
||||||
|
fss->cpsQuality = 10.0; // 1.0 / 10.0 => means 0.1 width
|
||||||
|
|
||||||
|
/*
|
||||||
|
BAD TODO: this is done in buttons_object.c in the moment
|
||||||
|
Mesh *mesh = ob->data;
|
||||||
|
// calculate bounding box
|
||||||
|
fluid_get_bb(mesh->mvert, mesh->totvert, ob->obmat, fss->bbStart, fss->bbSize);
|
||||||
|
*/
|
||||||
|
|
||||||
|
fss->lastgoodframe = -1;
|
||||||
|
|
||||||
|
fss->flag = 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void fluidsim_free(FluidsimModifierData *fluidmd)
|
||||||
|
{
|
||||||
|
#ifndef DISABLE_ELBEEM
|
||||||
|
if(fluidmd)
|
||||||
|
{
|
||||||
|
MEM_freeN(fluidmd->fss);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
DerivedMesh *fluidsimModifier_do(FluidsimModifierData *fluidmd, Object *ob, DerivedMesh *dm, int useRenderParams, int isFinalCalc)
|
||||||
|
{
|
||||||
|
#ifndef DISABLE_ELBEEM
|
||||||
|
DerivedMesh *result = NULL;
|
||||||
|
int framenr;
|
||||||
|
FluidsimSettings *fss = NULL;
|
||||||
|
|
||||||
|
framenr= (int)G.scene->r.cfra;
|
||||||
|
|
||||||
|
// only handle fluidsim domains
|
||||||
|
if(fluidmd && fluidmd->fss && (fluidmd->fss->type != OB_FLUIDSIM_DOMAIN))
|
||||||
|
return dm;
|
||||||
|
|
||||||
|
// sanity check
|
||||||
|
if(!fluidmd || (fluidmd && !fluidmd->fss))
|
||||||
|
return dm;
|
||||||
|
|
||||||
|
fss = fluidmd->fss;
|
||||||
|
|
||||||
|
// timescale not supported yet
|
||||||
|
// clmd->sim_parms->timescale= timescale;
|
||||||
|
|
||||||
|
// support reversing of baked fluid frames here
|
||||||
|
if((fss->flag & OB_FLUIDSIM_REVERSE) && (fss->lastgoodframe >= 0))
|
||||||
|
{
|
||||||
|
framenr = fss->lastgoodframe - framenr + 1;
|
||||||
|
CLAMP(framenr, 1, fss->lastgoodframe);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* try to read from cache */
|
||||||
|
if(((fss->lastgoodframe >= framenr) || (fss->lastgoodframe < 0)) && (result = fluidsim_read_cache(ob, dm, fluidmd, framenr, useRenderParams)))
|
||||||
|
{
|
||||||
|
// fss->lastgoodframe = framenr; // set also in src/fluidsim.c
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// display last known good frame
|
||||||
|
if(fss->lastgoodframe >= 0)
|
||||||
|
{
|
||||||
|
if((result = fluidsim_read_cache(ob, dm, fluidmd, fss->lastgoodframe, useRenderParams)))
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// it was supposed to be a valid frame but it isn't!
|
||||||
|
fss->lastgoodframe = framenr - 1;
|
||||||
|
|
||||||
|
|
||||||
|
// this could be likely the case when you load an old fluidsim
|
||||||
|
if((result = fluidsim_read_cache(ob, dm, fluidmd, fss->lastgoodframe, useRenderParams)))
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result = CDDM_copy(dm);
|
||||||
|
|
||||||
|
if(result)
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return dm;
|
||||||
|
#else
|
||||||
|
return NULL;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef DISABLE_ELBEEM
|
||||||
|
/* read .bobj.gz file into a fluidsimDerivedMesh struct */
|
||||||
|
static DerivedMesh *fluidsim_read_obj(char *filename)
|
||||||
|
{
|
||||||
|
int wri,i,j;
|
||||||
|
float wrf;
|
||||||
|
int gotBytes;
|
||||||
|
gzFile gzf;
|
||||||
|
int numverts = 0, numfaces = 0;
|
||||||
|
DerivedMesh *dm = NULL;
|
||||||
|
MFace *mface;
|
||||||
|
MVert *mvert;
|
||||||
|
short *normals;
|
||||||
|
|
||||||
|
// ------------------------------------------------
|
||||||
|
// get numverts + numfaces first
|
||||||
|
// ------------------------------------------------
|
||||||
|
gzf = gzopen(filename, "rb");
|
||||||
|
if (!gzf)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// read numverts
|
||||||
|
gotBytes = gzread(gzf, &wri, sizeof(wri));
|
||||||
|
numverts = wri;
|
||||||
|
|
||||||
|
// skip verts
|
||||||
|
for(i=0; i<numverts*3; i++)
|
||||||
|
{
|
||||||
|
gotBytes = gzread(gzf, &wrf, sizeof( wrf ));
|
||||||
|
}
|
||||||
|
|
||||||
|
// read number of normals
|
||||||
|
gotBytes = gzread(gzf, &wri, sizeof(wri));
|
||||||
|
|
||||||
|
// skip normals
|
||||||
|
for(i=0; i<numverts*3; i++)
|
||||||
|
{
|
||||||
|
gotBytes = gzread(gzf, &wrf, sizeof( wrf ));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get no. of triangles */
|
||||||
|
gotBytes = gzread(gzf, &wri, sizeof(wri));
|
||||||
|
numfaces = wri;
|
||||||
|
|
||||||
|
gzclose( gzf );
|
||||||
|
// ------------------------------------------------
|
||||||
|
|
||||||
|
if(!numfaces || !numverts)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
gzf = gzopen(filename, "rb");
|
||||||
|
if (!gzf)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
dm = CDDM_new(numverts, 0, numfaces);
|
||||||
|
|
||||||
|
if(!dm)
|
||||||
|
{
|
||||||
|
gzclose( gzf );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// read numverts
|
||||||
|
gotBytes = gzread(gzf, &wri, sizeof(wri));
|
||||||
|
|
||||||
|
// read vertex position from file
|
||||||
|
mvert = CDDM_get_verts(dm);
|
||||||
|
for(i=0; i<numverts; i++)
|
||||||
|
{
|
||||||
|
MVert *mv = &mvert[i];
|
||||||
|
|
||||||
|
for(j=0; j<3; j++)
|
||||||
|
{
|
||||||
|
gotBytes = gzread(gzf, &wrf, sizeof( wrf ));
|
||||||
|
mv->co[j] = wrf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// should be the same as numverts
|
||||||
|
gotBytes = gzread(gzf, &wri, sizeof(wri));
|
||||||
|
if(wri != numverts)
|
||||||
|
{
|
||||||
|
if(dm)
|
||||||
|
dm->release(dm);
|
||||||
|
gzclose( gzf );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
normals = MEM_callocN(sizeof(short) * numverts * 3, "fluid_tmp_normals" );
|
||||||
|
if(!normals)
|
||||||
|
{
|
||||||
|
if(dm)
|
||||||
|
dm->release(dm);
|
||||||
|
gzclose( gzf );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// read normals from file (but don't save them yet)
|
||||||
|
for(i=0; i<numverts*3; i++)
|
||||||
|
{
|
||||||
|
gotBytes = gzread(gzf, &wrf, sizeof( wrf ));
|
||||||
|
normals[i] = (short)(wrf*32767.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* read no. of triangles */
|
||||||
|
gotBytes = gzread(gzf, &wri, sizeof(wri));
|
||||||
|
|
||||||
|
if(wri!=numfaces)
|
||||||
|
printf("Fluidsim: error in reading data from file.\n");
|
||||||
|
|
||||||
|
// read triangles from file
|
||||||
|
mface = CDDM_get_faces(dm);
|
||||||
|
for(i=0; i<numfaces; i++)
|
||||||
|
{
|
||||||
|
int face[4];
|
||||||
|
MFace *mf = &mface[i];
|
||||||
|
|
||||||
|
gotBytes = gzread(gzf, &(face[0]), sizeof( face[0] ));
|
||||||
|
gotBytes = gzread(gzf, &(face[1]), sizeof( face[1] ));
|
||||||
|
gotBytes = gzread(gzf, &(face[2]), sizeof( face[2] ));
|
||||||
|
face[3] = 0;
|
||||||
|
|
||||||
|
// check if 3rd vertex has index 0 (not allowed in blender)
|
||||||
|
if(face[2])
|
||||||
|
{
|
||||||
|
mf->v1 = face[0];
|
||||||
|
mf->v2 = face[1];
|
||||||
|
mf->v3 = face[2];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mf->v1 = face[1];
|
||||||
|
mf->v2 = face[2];
|
||||||
|
mf->v3 = face[0];
|
||||||
|
}
|
||||||
|
mf->v4 = face[3];
|
||||||
|
|
||||||
|
test_index_face(mf, NULL, 0, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
gzclose( gzf );
|
||||||
|
|
||||||
|
CDDM_calc_edges(dm);
|
||||||
|
|
||||||
|
CDDM_apply_vert_normals(dm, (short (*)[3])normals);
|
||||||
|
MEM_freeN(normals);
|
||||||
|
|
||||||
|
// CDDM_calc_normals(result);
|
||||||
|
|
||||||
|
return dm;
|
||||||
|
}
|
||||||
|
|
||||||
|
DerivedMesh *fluidsim_read_cache(Object *ob, DerivedMesh *orgdm, FluidsimModifierData *fluidmd, int framenr, int useRenderParams)
|
||||||
|
{
|
||||||
|
int displaymode = 0;
|
||||||
|
int curFrame = framenr - 1 /*G.scene->r.sfra*/; /* start with 0 at start frame */
|
||||||
|
char targetDir[FILE_MAXFILE+FILE_MAXDIR], targetFile[FILE_MAXFILE+FILE_MAXDIR];
|
||||||
|
FluidsimSettings *fss = fluidmd->fss;
|
||||||
|
DerivedMesh *dm = NULL;
|
||||||
|
MFace *mface;
|
||||||
|
int numfaces;
|
||||||
|
int mat_nr, flag, i;
|
||||||
|
|
||||||
|
if(!useRenderParams) {
|
||||||
|
displaymode = fss->guiDisplayMode;
|
||||||
|
} else {
|
||||||
|
displaymode = fss->renderDisplayMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
strncpy(targetDir, fss->surfdataPath, FILE_MAXDIR);
|
||||||
|
|
||||||
|
// use preview or final mesh?
|
||||||
|
if(displaymode==1)
|
||||||
|
{
|
||||||
|
// just display original object
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
else if(displaymode==2)
|
||||||
|
{
|
||||||
|
strcat(targetDir,"fluidsurface_preview_####");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // 3
|
||||||
|
strcat(targetDir,"fluidsurface_final_####");
|
||||||
|
}
|
||||||
|
|
||||||
|
BLI_convertstringcode(targetDir, G.sce);
|
||||||
|
BLI_convertstringframe(targetDir, curFrame); // fixed #frame-no
|
||||||
|
|
||||||
|
strcpy(targetFile,targetDir);
|
||||||
|
strcat(targetFile, ".bobj.gz");
|
||||||
|
|
||||||
|
dm = fluidsim_read_obj(targetFile);
|
||||||
|
|
||||||
|
if(!dm)
|
||||||
|
{
|
||||||
|
// switch, abort background rendering when fluidsim mesh is missing
|
||||||
|
const char *strEnvName2 = "BLENDER_ELBEEMBOBJABORT"; // from blendercall.cpp
|
||||||
|
|
||||||
|
if(G.background==1) {
|
||||||
|
if(getenv(strEnvName2)) {
|
||||||
|
int elevel = atoi(getenv(strEnvName2));
|
||||||
|
if(elevel>0) {
|
||||||
|
printf("Env. var %s set, fluid sim mesh '%s' not found, aborting render...\n",strEnvName2, targetFile);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// display org. object upon failure which is in dm
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// assign material + flags to new dm
|
||||||
|
mface = orgdm->getFaceArray(orgdm);
|
||||||
|
mat_nr = mface[0].mat_nr;
|
||||||
|
flag = mface[0].flag;
|
||||||
|
|
||||||
|
mface = dm->getFaceArray(dm);
|
||||||
|
numfaces = dm->getNumFaces(dm);
|
||||||
|
for(i=0; i<numfaces; i++)
|
||||||
|
{
|
||||||
|
mface[i].mat_nr = mat_nr;
|
||||||
|
mface[i].flag = flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
// load vertex velocities, if they exist...
|
||||||
|
// TODO? use generate flag as loading flag as well?
|
||||||
|
// warning, needs original .bobj.gz mesh loading filename
|
||||||
|
/*
|
||||||
|
if(displaymode==3)
|
||||||
|
{
|
||||||
|
readVelgz(targetFile, srcob);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// no data for preview, only clear...
|
||||||
|
int i,j;
|
||||||
|
for(i=0; i<mesh->totvert;i++) { for(j=0; j<3; j++) { srcob->fluidsimSettings->meshSurfNormals[i].co[j] = 0.; }}
|
||||||
|
}*/
|
||||||
|
|
||||||
|
return dm;
|
||||||
|
}
|
||||||
|
|
||||||
|
void fluid_get_bb(MVert *mvert, int totvert, float obmat[][4],
|
||||||
|
/*RET*/ float start[3], /*RET*/ float size[3] )
|
||||||
|
{
|
||||||
|
float bbsx=0.0, bbsy=0.0, bbsz=0.0;
|
||||||
|
float bbex=1.0, bbey=1.0, bbez=1.0;
|
||||||
|
int i;
|
||||||
|
float vec[3];
|
||||||
|
|
||||||
|
VECCOPY(vec, mvert[0].co);
|
||||||
|
Mat4MulVecfl(obmat, vec);
|
||||||
|
bbsx = vec[0]; bbsy = vec[1]; bbsz = vec[2];
|
||||||
|
bbex = vec[0]; bbey = vec[1]; bbez = vec[2];
|
||||||
|
|
||||||
|
for(i = 1; i < totvert; i++) {
|
||||||
|
VECCOPY(vec, mvert[i].co);
|
||||||
|
Mat4MulVecfl(obmat, vec);
|
||||||
|
|
||||||
|
if(vec[0] < bbsx){ bbsx= vec[0]; }
|
||||||
|
if(vec[1] < bbsy){ bbsy= vec[1]; }
|
||||||
|
if(vec[2] < bbsz){ bbsz= vec[2]; }
|
||||||
|
if(vec[0] > bbex){ bbex= vec[0]; }
|
||||||
|
if(vec[1] > bbey){ bbey= vec[1]; }
|
||||||
|
if(vec[2] > bbez){ bbez= vec[2]; }
|
||||||
|
}
|
||||||
|
|
||||||
|
// return values...
|
||||||
|
if(start) {
|
||||||
|
start[0] = bbsx;
|
||||||
|
start[1] = bbsy;
|
||||||
|
start[2] = bbsz;
|
||||||
|
}
|
||||||
|
if(size) {
|
||||||
|
size[0] = bbex-bbsx;
|
||||||
|
size[1] = bbey-bbsy;
|
||||||
|
size[2] = bbez-bbsz;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// old interface
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// file handling
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void initElbeemMesh(struct Object *ob,
|
||||||
|
int *numVertices, float **vertices,
|
||||||
|
int *numTriangles, int **triangles,
|
||||||
|
int useGlobalCoords, int modifierIndex)
|
||||||
|
{
|
||||||
|
DerivedMesh *dm = NULL;
|
||||||
|
MVert *mvert;
|
||||||
|
MFace *mface;
|
||||||
|
int countTris=0, i, totvert, totface;
|
||||||
|
float *verts;
|
||||||
|
int *tris;
|
||||||
|
|
||||||
|
dm = mesh_create_derived_index_render(ob, CD_MASK_BAREMESH, modifierIndex);
|
||||||
|
//dm = mesh_create_derived_no_deform(ob,NULL);
|
||||||
|
|
||||||
|
mvert = dm->getVertArray(dm);
|
||||||
|
mface = dm->getFaceArray(dm);
|
||||||
|
totvert = dm->getNumVerts(dm);
|
||||||
|
totface = dm->getNumFaces(dm);
|
||||||
|
|
||||||
|
*numVertices = totvert;
|
||||||
|
verts = MEM_callocN( totvert*3*sizeof(float), "elbeemmesh_vertices");
|
||||||
|
for(i=0; i<totvert; i++) {
|
||||||
|
VECCOPY( &verts[i*3], mvert[i].co);
|
||||||
|
if(useGlobalCoords) { Mat4MulVecfl(ob->obmat, &verts[i*3]); }
|
||||||
|
}
|
||||||
|
*vertices = verts;
|
||||||
|
|
||||||
|
for(i=0; i<totface; i++) {
|
||||||
|
countTris++;
|
||||||
|
if(mface[i].v4) { countTris++; }
|
||||||
|
}
|
||||||
|
*numTriangles = countTris;
|
||||||
|
tris = MEM_callocN( countTris*3*sizeof(int), "elbeemmesh_triangles");
|
||||||
|
countTris = 0;
|
||||||
|
for(i=0; i<totface; i++) {
|
||||||
|
int face[4];
|
||||||
|
face[0] = mface[i].v1;
|
||||||
|
face[1] = mface[i].v2;
|
||||||
|
face[2] = mface[i].v3;
|
||||||
|
face[3] = mface[i].v4;
|
||||||
|
|
||||||
|
tris[countTris*3+0] = face[0];
|
||||||
|
tris[countTris*3+1] = face[1];
|
||||||
|
tris[countTris*3+2] = face[2];
|
||||||
|
countTris++;
|
||||||
|
if(face[3]) {
|
||||||
|
tris[countTris*3+0] = face[0];
|
||||||
|
tris[countTris*3+1] = face[2];
|
||||||
|
tris[countTris*3+2] = face[3];
|
||||||
|
countTris++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*triangles = tris;
|
||||||
|
|
||||||
|
dm->release(dm);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* read zipped fluidsim velocities into the co's of the fluidsimsettings normals struct */
|
||||||
|
void readVelgz(char *filename, Object *srcob)
|
||||||
|
{
|
||||||
|
int wri, i, j;
|
||||||
|
float wrf;
|
||||||
|
gzFile gzf;
|
||||||
|
MVert *vverts = srcob->fluidsimSettings->meshSurfNormals;
|
||||||
|
int len = strlen(filename);
|
||||||
|
Mesh *mesh = srcob->data;
|
||||||
|
// mesh and vverts have to be valid from loading...
|
||||||
|
|
||||||
|
// clean up in any case
|
||||||
|
for(i=0; i<mesh->totvert;i++)
|
||||||
|
{
|
||||||
|
for(j=0; j<3; j++)
|
||||||
|
{
|
||||||
|
vverts[i].co[j] = 0.;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(srcob->fluidsimSettings->domainNovecgen>0) return;
|
||||||
|
|
||||||
|
if(len<7)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// .bobj.gz , correct filename
|
||||||
|
// 87654321
|
||||||
|
filename[len-6] = 'v';
|
||||||
|
filename[len-5] = 'e';
|
||||||
|
filename[len-4] = 'l';
|
||||||
|
|
||||||
|
gzf = gzopen(filename, "rb");
|
||||||
|
if (!gzf)
|
||||||
|
return;
|
||||||
|
|
||||||
|
gzread(gzf, &wri, sizeof( wri ));
|
||||||
|
if(wri != mesh->totvert)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i=0; i<mesh->totvert;i++)
|
||||||
|
{
|
||||||
|
for(j=0; j<3; j++)
|
||||||
|
{
|
||||||
|
gzread(gzf, &wrf, sizeof( wrf ));
|
||||||
|
vverts[i].co[j] = wrf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gzclose(gzf);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif // DISABLE_ELBEEM
|
||||||
|
|
248
source/blender/blenkernel/intern/simple_deform.c
Normal file
248
source/blender/blenkernel/intern/simple_deform.c
Normal file
@ -0,0 +1,248 @@
|
|||||||
|
/**
|
||||||
|
* deform_simple.c
|
||||||
|
*
|
||||||
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
*
|
||||||
|
* The Original Code is Copyright (C) Blender Foundation.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* The Original Code is: all of this file.
|
||||||
|
*
|
||||||
|
* Contributor(s): André Pinto
|
||||||
|
*
|
||||||
|
* ***** END GPL LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
#include "DNA_object_types.h"
|
||||||
|
#include "DNA_modifier_types.h"
|
||||||
|
#include "DNA_meshdata_types.h"
|
||||||
|
|
||||||
|
#include "BKE_simple_deform.h"
|
||||||
|
#include "BKE_DerivedMesh.h"
|
||||||
|
#include "BKE_deform.h"
|
||||||
|
#include "BKE_utildefines.h"
|
||||||
|
#include "BLI_arithb.h"
|
||||||
|
#include "BKE_shrinkwrap.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
|
||||||
|
//Clamps/Limits the given coordinate to: limits[0] <= co[axis] <= limits[1]
|
||||||
|
//The ammount of clamp is saved on dcut
|
||||||
|
static void axis_limit(int axis, const float limits[2], float co[3], float dcut[3])
|
||||||
|
{
|
||||||
|
float val = co[axis];
|
||||||
|
if(limits[0] > val) val = limits[0];
|
||||||
|
if(limits[1] < val) val = limits[1];
|
||||||
|
|
||||||
|
dcut[axis] = co[axis] - val;
|
||||||
|
co[axis] = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void simpleDeform_taper(const float factor, const float dcut[3], float *co)
|
||||||
|
{
|
||||||
|
float x = co[0], y = co[1], z = co[2];
|
||||||
|
float scale = z*factor;
|
||||||
|
|
||||||
|
co[0] = x + x*scale;
|
||||||
|
co[1] = y + y*scale;
|
||||||
|
co[2] = z;
|
||||||
|
|
||||||
|
if(dcut)
|
||||||
|
{
|
||||||
|
co[0] += dcut[0];
|
||||||
|
co[1] += dcut[1];
|
||||||
|
co[2] += dcut[2];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void simpleDeform_stretch(const float factor, const float dcut[3], float *co)
|
||||||
|
{
|
||||||
|
float x = co[0], y = co[1], z = co[2];
|
||||||
|
float scale;
|
||||||
|
|
||||||
|
scale = (z*z*factor-factor + 1.0);
|
||||||
|
|
||||||
|
co[0] = x*scale;
|
||||||
|
co[1] = y*scale;
|
||||||
|
co[2] = z*(1.0+factor);
|
||||||
|
|
||||||
|
|
||||||
|
if(dcut)
|
||||||
|
{
|
||||||
|
co[0] += dcut[0];
|
||||||
|
co[1] += dcut[1];
|
||||||
|
co[2] += dcut[2];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void simpleDeform_twist(const float factor, const float *dcut, float *co)
|
||||||
|
{
|
||||||
|
float x = co[0], y = co[1], z = co[2];
|
||||||
|
float theta, sint, cost;
|
||||||
|
|
||||||
|
theta = z*factor;
|
||||||
|
sint = sin(theta);
|
||||||
|
cost = cos(theta);
|
||||||
|
|
||||||
|
co[0] = x*cost - y*sint;
|
||||||
|
co[1] = x*sint + y*cost;
|
||||||
|
co[2] = z;
|
||||||
|
|
||||||
|
if(dcut)
|
||||||
|
{
|
||||||
|
co[0] += dcut[0];
|
||||||
|
co[1] += dcut[1];
|
||||||
|
co[2] += dcut[2];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void simpleDeform_bend(const float factor, const float dcut[3], float *co)
|
||||||
|
{
|
||||||
|
float x = co[0], y = co[1], z = co[2];
|
||||||
|
float theta, sint, cost;
|
||||||
|
|
||||||
|
theta = x*factor;
|
||||||
|
sint = sin(theta);
|
||||||
|
cost = cos(theta);
|
||||||
|
|
||||||
|
if(fabs(factor) > 1e-7f)
|
||||||
|
{
|
||||||
|
co[0] = -(y-1.0f/factor)*sint;
|
||||||
|
co[1] = (y-1.0f/factor)*cost + 1.0f/factor;
|
||||||
|
co[2] = z;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if(dcut)
|
||||||
|
{
|
||||||
|
co[0] += cost*dcut[0];
|
||||||
|
co[1] += sint*dcut[0];
|
||||||
|
co[2] += dcut[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* simple deform modifier */
|
||||||
|
void SimpleDeformModifier_do(SimpleDeformModifierData *smd, struct Object *ob, struct DerivedMesh *dm, float (*vertexCos)[3], int numVerts)
|
||||||
|
{
|
||||||
|
static const float lock_axis[2] = {0.0f, 0.0f};
|
||||||
|
|
||||||
|
int i;
|
||||||
|
int limit_axis = 0;
|
||||||
|
float smd_limit[2], smd_factor;
|
||||||
|
SpaceTransform *transf = NULL, tmp_transf;
|
||||||
|
void (*simpleDeform_callback)(const float factor, const float dcut[3], float *co) = NULL; //Mode callback
|
||||||
|
int vgroup = get_named_vertexgroup_num(ob, smd->vgroup_name);
|
||||||
|
MDeformVert *dvert = NULL;
|
||||||
|
|
||||||
|
//Safe-check
|
||||||
|
if(smd->origin == ob) smd->origin = NULL; //No self references
|
||||||
|
|
||||||
|
if(smd->limit[0] < 0.0) smd->limit[0] = 0.0f;
|
||||||
|
if(smd->limit[0] > 1.0) smd->limit[0] = 1.0f;
|
||||||
|
|
||||||
|
smd->limit[0] = MIN2(smd->limit[0], smd->limit[1]); //Upper limit >= than lower limit
|
||||||
|
|
||||||
|
//Calculate matrixs do convert between coordinate spaces
|
||||||
|
if(smd->origin)
|
||||||
|
{
|
||||||
|
transf = &tmp_transf;
|
||||||
|
|
||||||
|
if(smd->originOpts & MOD_SIMPLEDEFORM_ORIGIN_LOCAL)
|
||||||
|
{
|
||||||
|
space_transform_from_matrixs(transf, ob->obmat, smd->origin->obmat);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Mat4CpyMat4(transf->local2target, smd->origin->obmat);
|
||||||
|
Mat4Invert(transf->target2local, transf->local2target);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Setup vars
|
||||||
|
limit_axis = (smd->mode == MOD_SIMPLEDEFORM_MODE_BEND) ? 0 : 2; //Bend limits on X.. all other modes limit on Z
|
||||||
|
|
||||||
|
//Update limits if needed
|
||||||
|
{
|
||||||
|
float lower = FLT_MAX;
|
||||||
|
float upper = -FLT_MAX;
|
||||||
|
|
||||||
|
for(i=0; i<numVerts; i++)
|
||||||
|
{
|
||||||
|
float tmp[3];
|
||||||
|
VECCOPY(tmp, vertexCos[i]);
|
||||||
|
|
||||||
|
if(transf) space_transform_apply(transf, tmp);
|
||||||
|
|
||||||
|
lower = MIN2(lower, tmp[limit_axis]);
|
||||||
|
upper = MAX2(upper, tmp[limit_axis]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//SMD values are normalized to the BV, calculate the absolut values
|
||||||
|
smd_limit[1] = lower + (upper-lower)*smd->limit[1];
|
||||||
|
smd_limit[0] = lower + (upper-lower)*smd->limit[0];
|
||||||
|
|
||||||
|
smd_factor = smd->factor / MAX2(FLT_EPSILON, smd_limit[1]-smd_limit[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if(dm)
|
||||||
|
dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT);
|
||||||
|
|
||||||
|
|
||||||
|
switch(smd->mode)
|
||||||
|
{
|
||||||
|
case MOD_SIMPLEDEFORM_MODE_TWIST: simpleDeform_callback = simpleDeform_twist; break;
|
||||||
|
case MOD_SIMPLEDEFORM_MODE_BEND: simpleDeform_callback = simpleDeform_bend; break;
|
||||||
|
case MOD_SIMPLEDEFORM_MODE_TAPER: simpleDeform_callback = simpleDeform_taper; break;
|
||||||
|
case MOD_SIMPLEDEFORM_MODE_STRETCH: simpleDeform_callback = simpleDeform_stretch; break;
|
||||||
|
default:
|
||||||
|
return; //No simpledeform mode?
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i=0; i<numVerts; i++)
|
||||||
|
{
|
||||||
|
float weight = vertexgroup_get_vertex_weight(dvert, i, vgroup);
|
||||||
|
|
||||||
|
if(weight != 0.0f)
|
||||||
|
{
|
||||||
|
float co[3], dcut[3] = {0.0f, 0.0f, 0.0f};
|
||||||
|
|
||||||
|
if(transf) space_transform_apply(transf, vertexCos[i]);
|
||||||
|
|
||||||
|
VECCOPY(co, vertexCos[i]);
|
||||||
|
|
||||||
|
//Apply axis limits
|
||||||
|
if(smd->mode != MOD_SIMPLEDEFORM_MODE_BEND) //Bend mode shoulnt have any lock axis
|
||||||
|
{
|
||||||
|
if(smd->axis & MOD_SIMPLEDEFORM_LOCK_AXIS_X) axis_limit(0, lock_axis, co, dcut);
|
||||||
|
if(smd->axis & MOD_SIMPLEDEFORM_LOCK_AXIS_Y) axis_limit(1, lock_axis, co, dcut);
|
||||||
|
}
|
||||||
|
axis_limit(limit_axis, smd_limit, co, dcut);
|
||||||
|
|
||||||
|
simpleDeform_callback(smd_factor, dcut, co); //Apply deform
|
||||||
|
VecLerpf(vertexCos[i], vertexCos[i], co, weight); //Use vertex weight has coef of linear interpolation
|
||||||
|
|
||||||
|
if(transf) space_transform_invert(transf, vertexCos[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,9 @@
|
|||||||
|
#include "GLBlendEquation.h"
|
||||||
|
|
||||||
|
void FRS_glBlendEquation(GLenum mode) {
|
||||||
|
if( glBlendEquation ) {
|
||||||
|
glBlendEquation(mode);
|
||||||
|
} else if ( glBlendEquationEXT ) {
|
||||||
|
glBlendEquationEXT(mode);
|
||||||
|
}
|
||||||
|
}
|
16
source/blender/freestyle/intern/rendering/GLBlendEquation.h
Normal file
16
source/blender/freestyle/intern/rendering/GLBlendEquation.h
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#ifndef GLBLENDEQUATION_H
|
||||||
|
#define GLBLENDEQUATION_H
|
||||||
|
|
||||||
|
#include <GL/glew.h>
|
||||||
|
#ifdef WIN32
|
||||||
|
# include <windows.h>
|
||||||
|
#endif
|
||||||
|
#ifdef __MACH__
|
||||||
|
# include <OpenGL/gl.h>
|
||||||
|
#else
|
||||||
|
# include <GL/gl.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void FRS_glBlendEquation(GLenum mode);
|
||||||
|
|
||||||
|
#endif // GLBLENDEQUATION_H
|
117
source/blender/include/BIF_keyframing.h
Normal file
117
source/blender/include/BIF_keyframing.h
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
/**
|
||||||
|
* $Id: BIF_keyframing.h 14444 2008-04-16 22:40:48Z aligorith $
|
||||||
|
*
|
||||||
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 59 Temple Place * Suite 330, Boston, MA 02111*1307, USA.
|
||||||
|
*
|
||||||
|
* The Original Code is Copyright (C) 2008, Blender Foundation
|
||||||
|
* This is a new part of Blender (with some old code)
|
||||||
|
*
|
||||||
|
* Contributor(s): Joshua Leung
|
||||||
|
*
|
||||||
|
* ***** END GPL LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef BIF_KEYFRAMING_H
|
||||||
|
#define BIF_KEYFRAMING_H
|
||||||
|
|
||||||
|
struct ListBase;
|
||||||
|
struct ID;
|
||||||
|
|
||||||
|
struct IpoCurve;
|
||||||
|
struct BezTriple;
|
||||||
|
|
||||||
|
/* ************ Keyframing Management **************** */
|
||||||
|
|
||||||
|
/* Lesser Keyframing API call:
|
||||||
|
* Use this when validation of necessary animation data isn't necessary as it already
|
||||||
|
* exists, and there is a beztriple that can be directly copied into the array.
|
||||||
|
*/
|
||||||
|
int insert_bezt_icu(struct IpoCurve *icu, struct BezTriple *bezt);
|
||||||
|
|
||||||
|
/* Main Keyframing API call:
|
||||||
|
* Use this when validation of necessary animation data isn't necessary as it
|
||||||
|
* already exists. It will insert a keyframe using the current value being keyframed.
|
||||||
|
*/
|
||||||
|
void insert_vert_icu(struct IpoCurve *icu, float x, float y, short flag);
|
||||||
|
|
||||||
|
|
||||||
|
/* flags for use in insert_key(), and insert_vert_icu() */
|
||||||
|
enum {
|
||||||
|
INSERTKEY_NEEDED = (1<<0), /* only insert keyframes where they're needed */
|
||||||
|
INSERTKEY_MATRIX = (1<<1), /* insert 'visual' keyframes where possible/needed */
|
||||||
|
INSERTKEY_FAST = (1<<2), /* don't recalculate handles,etc. after adding key */
|
||||||
|
INSERTKEY_FASTR = (1<<3), /* don't realloc mem (or increase count, as array has already been set out) */
|
||||||
|
INSERTKEY_REPLACE = (1<<4), /* only replace an existing keyframe (this overrides INSERTKEY_NEEDED) */
|
||||||
|
} eInsertKeyFlags;
|
||||||
|
|
||||||
|
/* -------- */
|
||||||
|
|
||||||
|
/* Main Keyframing API calls:
|
||||||
|
* Use this to create any necessary animation data,, and then insert a keyframe
|
||||||
|
* using the current value being keyframed, in the relevant place. Returns success.
|
||||||
|
*/
|
||||||
|
// TODO: adapt this for new data-api -> this blocktype, etc. stuff is evil!
|
||||||
|
short insertkey(struct ID *id, int blocktype, char *actname, char *constname, int adrcode, short flag);
|
||||||
|
|
||||||
|
/* Main Keyframing API call:
|
||||||
|
* Use this to delete keyframe on current frame for relevant channel. Will perform checks just in case.
|
||||||
|
*/
|
||||||
|
short deletekey(struct ID *id, int blocktype, char *actname, char *constname, int adrcode, short flag);
|
||||||
|
|
||||||
|
|
||||||
|
/* Main Keyframe Management calls:
|
||||||
|
* These handle keyframes management from various spaces. They will handle the menus
|
||||||
|
* required for each space.
|
||||||
|
*/
|
||||||
|
void common_insertkey(void);
|
||||||
|
void common_deletekey(void);
|
||||||
|
|
||||||
|
/* ************ Auto-Keyframing ********************** */
|
||||||
|
/* Notes:
|
||||||
|
* - All the defines for this (User-Pref settings and Per-Scene settings)
|
||||||
|
* are defined in DNA_userdef_types.h
|
||||||
|
* - Scene settings take presidence over those for userprefs, with old files
|
||||||
|
* inheriting userpref settings for the scene settings
|
||||||
|
* - "On/Off + Mode" are stored per Scene, but "settings" are currently stored
|
||||||
|
* as userprefs
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Auto-Keying macros for use by various tools */
|
||||||
|
/* check if auto-keyframing is enabled (per scene takes presidence) */
|
||||||
|
#define IS_AUTOKEY_ON ((G.scene) ? (G.scene->autokey_mode & AUTOKEY_ON) : (U.autokey_mode & AUTOKEY_ON))
|
||||||
|
/* check the mode for auto-keyframing (per scene takes presidence) */
|
||||||
|
#define IS_AUTOKEY_MODE(mode) ((G.scene) ? (G.scene->autokey_mode == AUTOKEY_MODE_##mode) : (U.autokey_mode == AUTOKEY_MODE_##mode))
|
||||||
|
/* check if a flag is set for auto-keyframing (as userprefs only!) */
|
||||||
|
#define IS_AUTOKEY_FLAG(flag) (U.autokey_flag & AUTOKEY_FLAG_##flag)
|
||||||
|
|
||||||
|
/* ************ Keyframe Checking ******************** */
|
||||||
|
|
||||||
|
/* Checks whether a keyframe exists for the given ID-block one the given frame */
|
||||||
|
short id_cfra_has_keyframe(struct ID *id, short filter);
|
||||||
|
|
||||||
|
/* filter flags fr id_cfra_has_keyframe */
|
||||||
|
enum {
|
||||||
|
/* general */
|
||||||
|
ANIMFILTER_ALL = 0, /* include all available animation data */
|
||||||
|
ANIMFILTER_LOCAL = (1<<0), /* only include locally available anim data */
|
||||||
|
|
||||||
|
/* object specific */
|
||||||
|
ANIMFILTER_MAT = (1<<1), /* include material keyframes too */
|
||||||
|
ANIMFILTER_SKEY = (1<<2), /* shape keys (for geometry) */
|
||||||
|
} eAnimFilterFlags;
|
||||||
|
|
||||||
|
#endif /* BIF_KEYFRAMING_H */
|
1870
source/blender/src/keyframing.c
Normal file
1870
source/blender/src/keyframing.c
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user