made some progress in saving and restoring the state during the simulation, with identical results.
Option to de/serialize btPersistentContactManifolds and fix lossy conversion during btMultiBody de/serialization of base world transform (serialize the quaternion, not the converted 3x3 matrix) There are still several caches not taken into account, and btMultiBody links/constraints are not deserialized yet etc. See examples\pybullet\examples\saveRestoreState.py for an example.
This commit is contained in:
@@ -16,6 +16,7 @@ subject to the following restrictions:
|
||||
|
||||
#include "btCollisionObject.h"
|
||||
#include "LinearMath/btSerializer.h"
|
||||
#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
|
||||
|
||||
btCollisionObject::btCollisionObject()
|
||||
: m_interpolationLinearVelocity(0.f, 0.f, 0.f),
|
||||
@@ -114,10 +115,18 @@ const char* btCollisionObject::serialize(void* dataBuffer, btSerializer* seriali
|
||||
dataOut->m_ccdSweptSphereRadius = m_ccdSweptSphereRadius;
|
||||
dataOut->m_ccdMotionThreshold = m_ccdMotionThreshold;
|
||||
dataOut->m_checkCollideWith = m_checkCollideWith;
|
||||
|
||||
// Fill padding with zeros to appease msan.
|
||||
memset(dataOut->m_padding, 0, sizeof(dataOut->m_padding));
|
||||
|
||||
if (m_broadphaseHandle)
|
||||
{
|
||||
dataOut->m_collisionFilterGroup = m_broadphaseHandle->m_collisionFilterGroup;
|
||||
dataOut->m_collisionFilterMask = m_broadphaseHandle->m_collisionFilterMask;
|
||||
dataOut->m_uniqueId = m_broadphaseHandle->m_uniqueId;
|
||||
}
|
||||
else
|
||||
{
|
||||
dataOut->m_collisionFilterGroup = 0;
|
||||
dataOut->m_collisionFilterMask = 0;
|
||||
dataOut->m_uniqueId = -1;
|
||||
}
|
||||
return btCollisionObjectDataName;
|
||||
}
|
||||
|
||||
|
||||
@@ -621,7 +621,6 @@ struct btCollisionObjectDoubleData
|
||||
double m_hitFraction;
|
||||
double m_ccdSweptSphereRadius;
|
||||
double m_ccdMotionThreshold;
|
||||
|
||||
int m_hasAnisotropicFriction;
|
||||
int m_collisionFlags;
|
||||
int m_islandTag1;
|
||||
@@ -629,8 +628,9 @@ struct btCollisionObjectDoubleData
|
||||
int m_activationState1;
|
||||
int m_internalType;
|
||||
int m_checkCollideWith;
|
||||
|
||||
char m_padding[4];
|
||||
int m_collisionFilterGroup;
|
||||
int m_collisionFilterMask;
|
||||
int m_uniqueId;//m_uniqueId is introduced for paircache. could get rid of this, by calculating the address offset etc.
|
||||
};
|
||||
|
||||
///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
|
||||
@@ -650,13 +650,12 @@ struct btCollisionObjectFloatData
|
||||
float m_deactivationTime;
|
||||
float m_friction;
|
||||
float m_rollingFriction;
|
||||
float m_contactDamping;
|
||||
float m_contactDamping;
|
||||
float m_contactStiffness;
|
||||
float m_restitution;
|
||||
float m_hitFraction;
|
||||
float m_ccdSweptSphereRadius;
|
||||
float m_ccdMotionThreshold;
|
||||
|
||||
int m_hasAnisotropicFriction;
|
||||
int m_collisionFlags;
|
||||
int m_islandTag1;
|
||||
@@ -664,7 +663,9 @@ struct btCollisionObjectFloatData
|
||||
int m_activationState1;
|
||||
int m_internalType;
|
||||
int m_checkCollideWith;
|
||||
char m_padding[4];
|
||||
int m_collisionFilterGroup;
|
||||
int m_collisionFilterMask;
|
||||
int m_uniqueId;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -1654,12 +1654,36 @@ void btCollisionWorld::serializeCollisionObjects(btSerializer* serializer)
|
||||
}
|
||||
|
||||
|
||||
|
||||
void btCollisionWorld::serializeContactManifolds(btSerializer* serializer)
|
||||
{
|
||||
if (serializer->getSerializationFlags() & BT_SERIALIZE_CONTACT_MANIFOLDS)
|
||||
{
|
||||
int numManifolds = getDispatcher()->getNumManifolds();
|
||||
for (int i = 0; i < numManifolds; i++)
|
||||
{
|
||||
const btPersistentManifold* manifold = getDispatcher()->getInternalManifoldPointer()[i];
|
||||
//don't serialize empty manifolds, they just take space
|
||||
//(may have to do it anyway if it destroys determinism)
|
||||
if (manifold->getNumContacts() == 0)
|
||||
continue;
|
||||
|
||||
btChunk* chunk = serializer->allocate(manifold->calculateSerializeBufferSize(), 1);
|
||||
const char* structType = manifold->serialize(manifold, chunk->m_oldPtr, serializer);
|
||||
serializer->finalizeChunk(chunk, structType, BT_CONTACTMANIFOLD_CODE, (void*)manifold);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void btCollisionWorld::serialize(btSerializer* serializer)
|
||||
{
|
||||
|
||||
serializer->startSerialization();
|
||||
|
||||
serializeCollisionObjects(serializer);
|
||||
|
||||
serializeContactManifolds(serializer);
|
||||
|
||||
serializer->finishSerialization();
|
||||
}
|
||||
|
||||
@@ -107,6 +107,9 @@ protected:
|
||||
|
||||
void serializeCollisionObjects(btSerializer* serializer);
|
||||
|
||||
void serializeContactManifolds(btSerializer* serializer);
|
||||
|
||||
|
||||
public:
|
||||
|
||||
//this constructor doesn't own the dispatcher and paircache/broadphase
|
||||
|
||||
@@ -199,6 +199,22 @@ class btPersistentManifoldSortPredicate
|
||||
}
|
||||
};
|
||||
|
||||
class btPersistentManifoldSortPredicateDeterministic
|
||||
{
|
||||
public:
|
||||
|
||||
SIMD_FORCE_INLINE bool operator() (const btPersistentManifold* lhs, const btPersistentManifold* rhs) const
|
||||
{
|
||||
return (
|
||||
(getIslandId(lhs) < getIslandId(rhs))
|
||||
|| ((getIslandId(lhs) == getIslandId(rhs)) && lhs->getBody0()->getBroadphaseHandle()->m_uniqueId < rhs->getBody0()->getBroadphaseHandle()->m_uniqueId)
|
||||
||((getIslandId(lhs) == getIslandId(rhs)) && (lhs->getBody0()->getBroadphaseHandle()->m_uniqueId == rhs->getBody0()->getBroadphaseHandle()->m_uniqueId) &&
|
||||
(lhs->getBody1()->getBroadphaseHandle()->m_uniqueId < rhs->getBody1()->getBroadphaseHandle()->m_uniqueId))
|
||||
);
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void btSimulationIslandManager::buildIslands(btDispatcher* dispatcher,btCollisionWorld* collisionWorld)
|
||||
{
|
||||
@@ -318,7 +334,9 @@ void btSimulationIslandManager::buildIslands(btDispatcher* dispatcher,btCollisio
|
||||
for (i=0;i<maxNumManifolds ;i++)
|
||||
{
|
||||
btPersistentManifold* manifold = dispatcher->getManifoldByIndexInternal(i);
|
||||
|
||||
if (manifold->getNumContacts() == 0)
|
||||
continue;
|
||||
|
||||
const btCollisionObject* colObj0 = static_cast<const btCollisionObject*>(manifold->getBody0());
|
||||
const btCollisionObject* colObj1 = static_cast<const btCollisionObject*>(manifold->getBody1());
|
||||
|
||||
@@ -379,7 +397,13 @@ void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher,
|
||||
|
||||
//tried a radix sort, but quicksort/heapsort seems still faster
|
||||
//@todo rewrite island management
|
||||
m_islandmanifold.quickSort(btPersistentManifoldSortPredicate());
|
||||
|
||||
//m_islandmanifold.quickSort(btPersistentManifoldSortPredicate());
|
||||
|
||||
//btPersistentManifoldSortPredicateDeterministic sorts contact manifolds based on islandid,
|
||||
//but also based on object0 unique id and object1 unique id
|
||||
m_islandmanifold.quickSort(btPersistentManifoldSortPredicateDeterministic());
|
||||
|
||||
//m_islandmanifold.heapSort(btPersistentManifoldSortPredicate());
|
||||
|
||||
//now process all active islands (sets of manifolds for now)
|
||||
|
||||
Reference in New Issue
Block a user