Hello,
It could be very nice to add a Shift feature into the Bullet world, so this one would shift bodies silently, contact points & entire broadphase in one call without moving bodies one by one (which would remove/add non needed overlaps during shifting). I have started an implementation which shift the broadphase directly and returns discretized shifted value (as the broadphase is quantified, it does not support all shift values), contact points are shifted too. But the raycast broadphase accelerator is missing as shifting this one seems to be more complicated. Tell me if you need this peace of code so then you can add it in a future release (and correct it if needed). Perhaps I missed to update some data.
Thanks.
World Shifting
-
- Posts: 15
- Joined: Tue Jan 06, 2009 10:04 am
Re: World Shifting
ShiftWorld feature can be added to a future release ?
-
- Site Admin
- Posts: 4221
- Joined: Sun Jun 26, 2005 6:43 pm
- Location: California, USA
Re: World Shifting
We welcome contributions, please keep them concise (don't change thousands lines of code).
Cheers,
Erwin
Cheers,
Erwin
-
- Posts: 2
- Joined: Tue Jan 05, 2010 3:23 pm
Re: World Shifting
World Shifting is exactly the problem I've been trying to solve! Romain Daize, is there any chance I could see your solution? Is it already merged into a trunk somewhere?
Thanks!
Thanks!
-
- Posts: 15
- Joined: Tue Jan 06, 2009 10:04 am
Re: World Shifting
Hi guys,
For now I just implemented btAxisSweep3 broadphase, tell me if you have any question or if you disagree with this. I tried to add some checks in some places to ensure coherency. Maybe there is still some bugs (just by reading the code), tell me if this is the case.
Moreover you will have to shift contact points :
Tell me if I'm missing something, constraints should not need any shift (all data are in local space), but maybe I'm wrong with this.
For now I didn't add anything into Bullet source code, is there some documentation for doing this properly ? Any convention ?
I have tested this code many times and it seems to work well, for now...
Don't forget that the raycast broadphase accelerator is missing as shifting this one seems to be more complicated (I really need some help for this), so you will have to disable this feature from the broadphase: when instantiating your btAxisSweep3 broadphase, simply setup disableRaycastAccelerator to TRUE.
For now I just implemented btAxisSweep3 broadphase, tell me if you have any question or if you disagree with this. I tried to add some checks in some places to ensure coherency. Maybe there is still some bugs (just by reading the code), tell me if this is the case.
Code: Select all
template <typename BP_FP_INT_TYPE>
void btAxisSweep3Internal<BP_FP_INT_TYPE>::ShiftAllObjects(btVector3 const& a_rf3ShiftDistance, btVector3& a_rf3RealShiftDistance)
{
// Quantize the shift distance
BP_FP_INT_TYPE i3DistanceQuant[3];
int i3signs[3];
QuantizeShiftDistance(i3DistanceQuant, i3signs, a_rf3ShiftDistance);
// Compute real shift distance
a_rf3RealShiftDistance.setValue(
i3signs[0] > 0 ? (btScalar)(i3DistanceQuant[0]) / (m_quantize.getX()) : -(btScalar)(i3DistanceQuant[0]) / (m_quantize.getX()) ,
i3signs[1] > 0 ? (btScalar)(i3DistanceQuant[1]) / (m_quantize.getY()) : -(btScalar)(i3DistanceQuant[1]) / (m_quantize.getY()) ,
i3signs[2] > 0 ? (btScalar)(i3DistanceQuant[2]) / (m_quantize.getZ()) : -(btScalar)(i3DistanceQuant[2]) / (m_quantize.getZ()));
// Iterate over edges, first and last edges are reserved for the sentinel and will not being shifted
for (BP_FP_INT_TYPE axis=0; axis<3; axis++)
{
Edge* pCurEdge = m_pEdges[axis] + 1;
for (BP_FP_INT_TYPE i=1; i<m_numHandles*2+1; i++)
{
// Update current edge position
BP_FP_INT_TYPE& rPos = pCurEdge->m_pos;
// Add some checks
#ifdef BT_DEBUG
btScalar fInitRealPos = (btScalar)rPos / m_quantize.m_floats[axis];
BP_FP_INT_TYPE bEdgeType = pCurEdge->IsMax();
btAssert(bEdgeType == 0 || bEdgeType == 1);
#endif // BT_DEBUG
if(i3signs[axis] < 0)
{
// Make sure edge won't go out of broadphase
btAssert((rPos & m_bpHandleMask) >= i3DistanceQuant[axis]);
btAssert((rPos & m_bpHandleMask) >= i3DistanceQuant[axis]);
rPos = rPos - i3DistanceQuant[axis];
}
else
{
// Make sure proxy won't go out of broadphase
btAssert(m_handleSentinel - (rPos & m_bpHandleMask) > i3DistanceQuant[axis]);
btAssert(m_handleSentinel - (rPos & m_bpHandleMask) > i3DistanceQuant[axis]);
rPos = rPos + i3DistanceQuant[axis];
}
btAssert(pCurEdge->IsMax() == bEdgeType);
// Check update is valid
#ifdef BT_DEBUG
btScalar fCurRealPos = (btScalar)rPos / m_quantize.m_floats[axis];
btScalar fDist = fabsf((fInitRealPos + a_rf3RealShiftDistance.m_floats[axis]) - fCurRealPos);
btAssert(fDist < 1e-4f);
#endif // BT_DEBUG
// Update handle if we finished updating all its edges
if((pCurEdge->IsMax() == 1) && (axis == 2))
{
Handle* pCurHandle = getHandle(pCurEdge->m_handle);
pCurHandle->m_aabbMin += a_rf3RealShiftDistance;
pCurHandle->m_aabbMax += a_rf3RealShiftDistance;
}
// Switch to next edge
pCurEdge++;
}
}
}
template <typename BP_FP_INT_TYPE>
void btAxisSweep3Internal<BP_FP_INT_TYPE>::QuantizeShiftDistance(BP_FP_INT_TYPE* a_i3Out, int* a_i3Signs, btVector3 const& a_rf3ShiftDistance) const
{
btVector3 v = a_rf3ShiftDistance.absolute() * m_quantize;
btAssert(v[0] >= 0.f && v[0] < m_handleSentinel);
btAssert(v[1] >= 0.f && v[1] < m_handleSentinel);
btAssert(v[2] >= 0.f && v[2] < m_handleSentinel);
a_i3Out[0]=(BP_FP_INT_TYPE)v[0] & m_bpHandleMask;
a_i3Out[1]=(BP_FP_INT_TYPE)v[1] & m_bpHandleMask;
a_i3Out[2]=(BP_FP_INT_TYPE)v[2] & m_bpHandleMask;
for (int i=0; i<3; i++)
{
a_i3Signs[i] = (a_rf3ShiftDistance[i] < 0.f) ? -1 : 1;
}
}
Code: Select all
int iManifoldsCount = m_pCollisionDispatcherBT->getNumManifolds();
for(int iManifold = 0; iManifold < iManifoldsCount, iManifold++)
{
btPersistentManifold* pManifold = m_pCollisionDispatcherBT->getManifoldByIndexInternal(iManifold);
btAssert(pManifold != NULL);
int iContactCount = pManifold->getNumContacts();
for(int iContact = 0; iContact < iContactCount; iContact++)
{
btManifoldPoint& rContactPoint = pManifold->getContactPoint(iContact);
rContactPoint.m_positionWorldOnA = rContactPoint.m_positionWorldOnA + f3ShiftValue;
rContactPoint.m_positionWorldOnB = rContactPoint.m_positionWorldOnB + f3ShiftValue;
}
}
For now I didn't add anything into Bullet source code, is there some documentation for doing this properly ? Any convention ?
I have tested this code many times and it seems to work well, for now...
Don't forget that the raycast broadphase accelerator is missing as shifting this one seems to be more complicated (I really need some help for this), so you will have to disable this feature from the broadphase: when instantiating your btAxisSweep3 broadphase, simply setup disableRaycastAccelerator to TRUE.
-
- Posts: 2
- Joined: Tue Jan 05, 2010 3:23 pm
Re: World Shifting
Thank Romain,
I've tried using your code to shift, but for me it doesn't appear to change bodies' positions. When I use try to use it, the only thing that happens is my bodies' collisions seem to stop.
Do I also need to manually set the position transform for all of my bodies?
Any ideas?
I've tried using your code to shift, but for me it doesn't appear to change bodies' positions. When I use try to use it, the only thing that happens is my bodies' collisions seem to stop.
Do I also need to manually set the position transform for all of my bodies?
Any ideas?
-
- Posts: 15
- Joined: Tue Jan 06, 2009 10:04 am
Re: World Shifting
Here we simply shift broadphase and contact points, but you need to shift bodies too, translate your rigid body by the real shift distance computed by ShiftAllObjects method : void btRigidBody::translate(const btVector3& v). You need to translate all others objects if any (characters, phantoms etc...)