+ add option to set pre-tick callback, called at the beginning of each internal simulation step
+ use real-time for soft body demo (using this pre-tick callback) + optimize the generation of bending constraints for the special case where the distance is 2
This commit is contained in:
@@ -98,6 +98,41 @@ void SoftDemo::createStack( btCollisionShape* boxShape, float halfCubeSize, int
|
|||||||
extern int gNumManifold;
|
extern int gNumManifold;
|
||||||
extern int gOverlappingPairs;
|
extern int gOverlappingPairs;
|
||||||
|
|
||||||
|
///for mouse picking
|
||||||
|
void pickingPreTickCallback (btDynamicsWorld *world, btScalar timeStep)
|
||||||
|
{
|
||||||
|
SoftDemo* softDemo = (SoftDemo*)world->getWorldUserInfo();
|
||||||
|
|
||||||
|
if(softDemo->m_drag)
|
||||||
|
{
|
||||||
|
const int x=softDemo->m_lastmousepos[0];
|
||||||
|
const int y=softDemo->m_lastmousepos[1];
|
||||||
|
const btVector3 rayFrom=softDemo->getCameraPosition();
|
||||||
|
const btVector3 rayTo=softDemo->getRayTo(x,y);
|
||||||
|
const btVector3 rayDir=(rayTo-rayFrom).normalized();
|
||||||
|
const btVector3 N=(softDemo->getCameraTargetPosition()-softDemo->getCameraPosition()).normalized();
|
||||||
|
const btScalar O=btDot(softDemo->m_impact,N);
|
||||||
|
const btScalar den=btDot(N,rayDir);
|
||||||
|
if((den*den)>0)
|
||||||
|
{
|
||||||
|
const btScalar num=O-btDot(N,rayFrom);
|
||||||
|
const btScalar hit=num/den;
|
||||||
|
if((hit>0)&&(hit<1500))
|
||||||
|
{
|
||||||
|
softDemo->m_goal=rayFrom+rayDir*hit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
btVector3 delta=softDemo->m_goal-softDemo->m_node->m_x;
|
||||||
|
static const btScalar maxdrag=10;
|
||||||
|
if(delta.length2()>(maxdrag*maxdrag))
|
||||||
|
{
|
||||||
|
delta=delta.normalized()*maxdrag;
|
||||||
|
}
|
||||||
|
softDemo->m_node->m_v+=delta/timeStep;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void SoftDemo::clientMoveAndDisplay()
|
void SoftDemo::clientMoveAndDisplay()
|
||||||
{
|
{
|
||||||
@@ -106,39 +141,17 @@ void SoftDemo::clientMoveAndDisplay()
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
float dt = 1.0/60.;
|
float ms = getDeltaTimeMicroseconds();
|
||||||
|
float dt = ms / 1000000.f;//1.0/60.;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (m_dynamicsWorld)
|
if (m_dynamicsWorld)
|
||||||
{
|
{
|
||||||
if(m_drag)
|
|
||||||
{
|
|
||||||
const int x=m_lastmousepos[0];
|
|
||||||
const int y=m_lastmousepos[1];
|
|
||||||
const btVector3 rayFrom=m_cameraPosition;
|
|
||||||
const btVector3 rayTo=getRayTo(x,y);
|
|
||||||
const btVector3 rayDir=(rayTo-rayFrom).normalized();
|
|
||||||
const btVector3 N=(m_cameraTargetPosition-m_cameraPosition).normalized();
|
|
||||||
const btScalar O=btDot(m_impact,N);
|
|
||||||
const btScalar den=btDot(N,rayDir);
|
|
||||||
if((den*den)>0)
|
|
||||||
{
|
|
||||||
const btScalar num=O-btDot(N,rayFrom);
|
|
||||||
const btScalar hit=num/den;
|
|
||||||
if((hit>0)&&(hit<1500))
|
|
||||||
{
|
|
||||||
m_goal=rayFrom+rayDir*hit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
btVector3 delta=m_goal-m_node->m_x;
|
|
||||||
static const btScalar maxdrag=10;
|
|
||||||
if(delta.length2()>(maxdrag*maxdrag))
|
|
||||||
{
|
|
||||||
delta=delta.normalized()*maxdrag;
|
|
||||||
}
|
|
||||||
m_node->m_v+=delta/dt;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define FIXED_STEP
|
|
||||||
|
|
||||||
|
//#define FIXED_STEP
|
||||||
#ifdef FIXED_STEP
|
#ifdef FIXED_STEP
|
||||||
m_dynamicsWorld->stepSimulation(dt=1.0f/60.f,0);
|
m_dynamicsWorld->stepSimulation(dt=1.0f/60.f,0);
|
||||||
|
|
||||||
@@ -1246,7 +1259,7 @@ static void Init_ClusterStackMixed(SoftDemo* pdemo)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned current_demo=18;
|
unsigned current_demo=19;
|
||||||
|
|
||||||
void SoftDemo::clientResetScene()
|
void SoftDemo::clientResetScene()
|
||||||
{
|
{
|
||||||
@@ -1711,6 +1724,7 @@ void SoftDemo::initPhysics()
|
|||||||
|
|
||||||
btDiscreteDynamicsWorld* world = new btSoftRigidDynamicsWorld(m_dispatcher,m_broadphase,m_solver,m_collisionConfiguration);
|
btDiscreteDynamicsWorld* world = new btSoftRigidDynamicsWorld(m_dispatcher,m_broadphase,m_solver,m_collisionConfiguration);
|
||||||
m_dynamicsWorld = world;
|
m_dynamicsWorld = world;
|
||||||
|
m_dynamicsWorld->setInternalTickCallback(pickingPreTickCallback,this,true);
|
||||||
|
|
||||||
|
|
||||||
m_dynamicsWorld->getDispatchInfo().m_enableSPU = true;
|
m_dynamicsWorld->getDispatchInfo().m_enableSPU = true;
|
||||||
|
|||||||
@@ -48,6 +48,10 @@ void btContinuousDynamicsWorld::internalSingleStepSimulation( btScalar timeStep)
|
|||||||
|
|
||||||
startProfiling(timeStep);
|
startProfiling(timeStep);
|
||||||
|
|
||||||
|
if(0 != m_internalPreTickCallback) {
|
||||||
|
(*m_internalPreTickCallback)(this, timeStep);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
///update aabbs information
|
///update aabbs information
|
||||||
updateAabbs();
|
updateAabbs();
|
||||||
|
|||||||
@@ -362,6 +362,10 @@ void btDiscreteDynamicsWorld::internalSingleStepSimulation(btScalar timeStep)
|
|||||||
|
|
||||||
BT_PROFILE("internalSingleStepSimulation");
|
BT_PROFILE("internalSingleStepSimulation");
|
||||||
|
|
||||||
|
if(0 != m_internalPreTickCallback) {
|
||||||
|
(*m_internalPreTickCallback)(this, timeStep);
|
||||||
|
}
|
||||||
|
|
||||||
///apply gravity, predict motion
|
///apply gravity, predict motion
|
||||||
predictUnconstraintMotion(timeStep);
|
predictUnconstraintMotion(timeStep);
|
||||||
|
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ class btDynamicsWorld : public btCollisionWorld
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
btInternalTickCallback m_internalTickCallback;
|
btInternalTickCallback m_internalTickCallback;
|
||||||
|
btInternalTickCallback m_internalPreTickCallback;
|
||||||
void* m_worldUserInfo;
|
void* m_worldUserInfo;
|
||||||
|
|
||||||
btContactSolverInfo m_solverInfo;
|
btContactSolverInfo m_solverInfo;
|
||||||
@@ -49,7 +50,7 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
btDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* broadphase,btCollisionConfiguration* collisionConfiguration)
|
btDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* broadphase,btCollisionConfiguration* collisionConfiguration)
|
||||||
:btCollisionWorld(dispatcher,broadphase,collisionConfiguration), m_internalTickCallback(0), m_worldUserInfo(0)
|
:btCollisionWorld(dispatcher,broadphase,collisionConfiguration), m_internalTickCallback(0),m_internalPreTickCallback(0), m_worldUserInfo(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -102,9 +103,15 @@ public:
|
|||||||
virtual void clearForces() = 0;
|
virtual void clearForces() = 0;
|
||||||
|
|
||||||
/// Set the callback for when an internal tick (simulation substep) happens, optional user info
|
/// Set the callback for when an internal tick (simulation substep) happens, optional user info
|
||||||
void setInternalTickCallback(btInternalTickCallback cb, void* worldUserInfo=0)
|
void setInternalTickCallback(btInternalTickCallback cb, void* worldUserInfo=0,bool isPreTick=false)
|
||||||
{
|
{
|
||||||
m_internalTickCallback = cb;
|
if (isPreTick)
|
||||||
|
{
|
||||||
|
m_internalPreTickCallback = cb;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
m_internalTickCallback = cb;
|
||||||
|
}
|
||||||
m_worldUserInfo = worldUserInfo;
|
m_worldUserInfo = worldUserInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -704,6 +704,9 @@ void btSoftBody::clusterDCImpulse(Cluster* cluster,const btVector3& impulse)
|
|||||||
cluster->m_ndimpulses++;
|
cluster->m_ndimpulses++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
int btSoftBody::generateBendingConstraints(int distance,Material* mat)
|
int btSoftBody::generateBendingConstraints(int distance,Material* mat)
|
||||||
{
|
{
|
||||||
@@ -715,14 +718,21 @@ int btSoftBody::generateBendingConstraints(int distance,Material* mat)
|
|||||||
const int n=m_nodes.size();
|
const int n=m_nodes.size();
|
||||||
const unsigned inf=(~(unsigned)0)>>1;
|
const unsigned inf=(~(unsigned)0)>>1;
|
||||||
unsigned* adj=new unsigned[n*n];
|
unsigned* adj=new unsigned[n*n];
|
||||||
|
|
||||||
|
|
||||||
#define IDX(_x_,_y_) ((_y_)*n+(_x_))
|
#define IDX(_x_,_y_) ((_y_)*n+(_x_))
|
||||||
for(j=0;j<n;++j)
|
for(j=0;j<n;++j)
|
||||||
{
|
{
|
||||||
for(i=0;i<n;++i)
|
for(i=0;i<n;++i)
|
||||||
{
|
{
|
||||||
if(i!=j) adj[IDX(i,j)]=adj[IDX(j,i)]=inf;
|
if(i!=j)
|
||||||
|
{
|
||||||
|
adj[IDX(i,j)]=adj[IDX(j,i)]=inf;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
adj[IDX(i,j)]=adj[IDX(j,i)]=0;
|
adj[IDX(i,j)]=adj[IDX(j,i)]=0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for( i=0;i<m_links.size();++i)
|
for( i=0;i<m_links.size();++i)
|
||||||
@@ -732,20 +742,76 @@ int btSoftBody::generateBendingConstraints(int distance,Material* mat)
|
|||||||
adj[IDX(ia,ib)]=1;
|
adj[IDX(ia,ib)]=1;
|
||||||
adj[IDX(ib,ia)]=1;
|
adj[IDX(ib,ia)]=1;
|
||||||
}
|
}
|
||||||
for(int k=0;k<n;++k)
|
|
||||||
|
|
||||||
|
//special optimized case for distance == 2
|
||||||
|
if (distance == 2)
|
||||||
{
|
{
|
||||||
for(j=0;j<n;++j)
|
|
||||||
|
struct NodeLinks
|
||||||
{
|
{
|
||||||
for(i=j+1;i<n;++i)
|
btAlignedObjectArray<int> m_links;
|
||||||
|
};
|
||||||
|
|
||||||
|
btAlignedObjectArray<NodeLinks> nodeLinks;
|
||||||
|
|
||||||
|
|
||||||
|
/* Build node links */
|
||||||
|
nodeLinks.resize(m_nodes.size());
|
||||||
|
|
||||||
|
for( i=0;i<m_links.size();++i)
|
||||||
|
{
|
||||||
|
const int ia=(int)(m_links[i].m_n[0]-&m_nodes[0]);
|
||||||
|
const int ib=(int)(m_links[i].m_n[1]-&m_nodes[0]);
|
||||||
|
if (nodeLinks[ia].m_links.findLinearSearch(ib)==nodeLinks[ia].m_links.size())
|
||||||
|
nodeLinks[ia].m_links.push_back(ib);
|
||||||
|
|
||||||
|
if (nodeLinks[ib].m_links.findLinearSearch(ia)==nodeLinks[ib].m_links.size())
|
||||||
|
nodeLinks[ib].m_links.push_back(ia);
|
||||||
|
}
|
||||||
|
for (int ii=0;ii<nodeLinks.size();ii++)
|
||||||
|
{
|
||||||
|
int i=ii;
|
||||||
|
|
||||||
|
for (int jj=0;jj<nodeLinks[ii].m_links.size();jj++)
|
||||||
{
|
{
|
||||||
const unsigned sum=adj[IDX(i,k)]+adj[IDX(k,j)];
|
int k = nodeLinks[ii].m_links[jj];
|
||||||
if(adj[IDX(i,j)]>sum)
|
for (int kk=0;kk<nodeLinks[k].m_links.size();kk++)
|
||||||
{
|
{
|
||||||
adj[IDX(i,j)]=adj[IDX(j,i)]=sum;
|
int j = nodeLinks[k].m_links[kk];
|
||||||
|
if (i!=j)
|
||||||
|
{
|
||||||
|
const unsigned sum=adj[IDX(i,k)]+adj[IDX(k,j)];
|
||||||
|
btAssert(sum==2);
|
||||||
|
if(adj[IDX(i,j)]>sum)
|
||||||
|
{
|
||||||
|
adj[IDX(i,j)]=adj[IDX(j,i)]=sum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
///generic Floyd's algorithm
|
||||||
|
for(int k=0;k<n;++k)
|
||||||
|
{
|
||||||
|
for(j=0;j<n;++j)
|
||||||
|
{
|
||||||
|
for(i=j+1;i<n;++i)
|
||||||
|
{
|
||||||
|
const unsigned sum=adj[IDX(i,k)]+adj[IDX(k,j)];
|
||||||
|
if(adj[IDX(i,j)]>sum)
|
||||||
|
{
|
||||||
|
adj[IDX(i,j)]=adj[IDX(j,i)]=sum;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Build links */
|
/* Build links */
|
||||||
int nlinks=0;
|
int nlinks=0;
|
||||||
for(j=0;j<n;++j)
|
for(j=0;j<n;++j)
|
||||||
|
|||||||
Reference in New Issue
Block a user