forked from bartvdbraak/blender
BGE: Optimize Soft body conversion: don't create BVH structure.
A btBvhTriangleMeshShape object is created when converting a mesh to physics, also in case of Soft body although the soft body will not use it (it only uses the mesh interface). This patch keeps this system for compatibility with the KX converter but avoids the creation of the BVH structure, which consumes a lots of CPU. This should speed up significantly the conversion of large mesh to softbody. A secondary optimization is that the sharing of shapeInfo is extended to rigid body using gImpact. Before it was only active between static body and soft body.
This commit is contained in:
parent
02d9da1d5d
commit
0020de72e4
@ -279,13 +279,15 @@ void KX_BulletPhysicsController::AddCompoundChild(KX_IPhysicsController* chil
|
||||
// we will need this to make sure that we remove the right proxy later when unparenting
|
||||
proxyShapeInfo->m_userData = childCtrl;
|
||||
proxyShapeInfo->SetProxy(childCtrl->GetShapeInfo()->AddRef());
|
||||
// add to parent compound shapeinfo
|
||||
// add to parent compound shapeinfo (increments ref count)
|
||||
GetShapeInfo()->AddShape(proxyShapeInfo);
|
||||
// create new bullet collision shape from the object shapeinfo and set scaling
|
||||
btCollisionShape* newChildShape = proxyShapeInfo->CreateBulletShape(childCtrl->GetMargin());
|
||||
btCollisionShape* newChildShape = proxyShapeInfo->CreateBulletShape(childCtrl->GetMargin(), childCtrl->getConstructionInfo().m_bGimpact, true);
|
||||
newChildShape->setLocalScaling(relativeScale);
|
||||
// add bullet collision shape to parent compound collision shape
|
||||
compoundShape->addChildShape(proxyShapeInfo->m_childTrans,newChildShape);
|
||||
// proxyShapeInfo is not needed anymore, release it
|
||||
proxyShapeInfo->Release();
|
||||
// remember we created this shape
|
||||
childCtrl->m_bulletChildShape = newChildShape;
|
||||
// recompute inertia of parent
|
||||
|
@ -97,6 +97,7 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj,
|
||||
|
||||
bool isbulletdyna = false;
|
||||
bool isbulletsensor = false;
|
||||
bool useGimpact = false;
|
||||
CcdConstructionInfo ci;
|
||||
class PHY_IMotionState* motionstate = new KX_MotionState(gameobj->GetSGNode());
|
||||
class CcdShapeConstructionInfo *shapeInfo = new CcdShapeConstructionInfo();
|
||||
@ -121,7 +122,8 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj,
|
||||
shapeInfo->m_radius = objprop->m_radius;
|
||||
isbulletdyna = objprop->m_dyna;
|
||||
isbulletsensor = objprop->m_sensor;
|
||||
|
||||
useGimpact = ((isbulletdyna || isbulletsensor) && !objprop->m_softbody);
|
||||
|
||||
ci.m_localInertiaTensor = btVector3(ci.m_mass/3.f,ci.m_mass/3.f,ci.m_mass/3.f);
|
||||
|
||||
btCollisionShape* bm = 0;
|
||||
@ -178,24 +180,22 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj,
|
||||
}
|
||||
case KX_BOUNDPOLYTOPE:
|
||||
{
|
||||
shapeInfo->SetMesh(meshobj, dm,true,false);
|
||||
shapeInfo->SetMesh(meshobj, dm,true);
|
||||
bm = shapeInfo->CreateBulletShape(ci.m_margin);
|
||||
break;
|
||||
}
|
||||
case KX_BOUNDMESH:
|
||||
{
|
||||
bool useGimpact = ((ci.m_mass || isbulletsensor) && !objprop->m_softbody);
|
||||
|
||||
// mesh shapes can be shared, check first if we already have a shape on that mesh
|
||||
class CcdShapeConstructionInfo *sharedShapeInfo = CcdShapeConstructionInfo::FindMesh(meshobj, dm, false,useGimpact);
|
||||
class CcdShapeConstructionInfo *sharedShapeInfo = CcdShapeConstructionInfo::FindMesh(meshobj, dm, false);
|
||||
if (sharedShapeInfo != NULL)
|
||||
{
|
||||
delete shapeInfo;
|
||||
shapeInfo->Release();
|
||||
shapeInfo = sharedShapeInfo;
|
||||
shapeInfo->AddRef();
|
||||
} else
|
||||
{
|
||||
shapeInfo->SetMesh(meshobj, dm, false,useGimpact);
|
||||
shapeInfo->SetMesh(meshobj, dm, false);
|
||||
}
|
||||
|
||||
// Soft bodies require welding. Only avoid remove doubles for non-soft bodies!
|
||||
@ -204,7 +204,7 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj,
|
||||
shapeInfo->setVertexWeldingThreshold1(objprop->m_soft_welding); //todo: expose this to the UI
|
||||
}
|
||||
|
||||
bm = shapeInfo->CreateBulletShape(ci.m_margin);
|
||||
bm = shapeInfo->CreateBulletShape(ci.m_margin, useGimpact, !objprop->m_softbody);
|
||||
//should we compute inertia for dynamic shape?
|
||||
//bm->calculateLocalInertia(ci.m_mass,ci.m_localInertiaTensor);
|
||||
|
||||
@ -218,7 +218,7 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj,
|
||||
if (!bm)
|
||||
{
|
||||
delete motionstate;
|
||||
delete shapeInfo;
|
||||
shapeInfo->Release();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -268,6 +268,7 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj,
|
||||
compoundShape->calculateLocalInertia(mass,localInertia);
|
||||
rigidbody->setMassProps(mass,localInertia);
|
||||
}
|
||||
shapeInfo->Release();
|
||||
// delete motionstate as it's not used
|
||||
delete motionstate;
|
||||
return;
|
||||
@ -284,6 +285,7 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj,
|
||||
compoundShape->addChildShape(shapeInfo->m_childTrans,bm);
|
||||
// now replace the shape
|
||||
bm = compoundShape;
|
||||
shapeInfo->Release();
|
||||
shapeInfo = compoundShapeInfo;
|
||||
}
|
||||
|
||||
@ -395,6 +397,7 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj,
|
||||
ci.m_contactProcessingThreshold = objprop->m_contactProcessingThreshold;//todo: expose this in advanced settings, just like margin, default to 10000 or so
|
||||
ci.m_bSoft = objprop->m_softbody;
|
||||
ci.m_bSensor = isbulletsensor;
|
||||
ci.m_bGimpact = useGimpact;
|
||||
MT_Vector3 scaling = gameobj->NodeGetWorldScaling();
|
||||
ci.m_scaling.setValue(scaling[0], scaling[1], scaling[2]);
|
||||
KX_BulletPhysicsController* physicscontroller = new KX_BulletPhysicsController(ci,isbulletdyna,isbulletsensor,objprop->m_hasCompoundChildren);
|
||||
@ -544,7 +547,8 @@ bool KX_ReInstanceBulletShapeFromMesh(KX_GameObject *gameobj, KX_GameObject *fro
|
||||
shapeInfo->UpdateMesh(from_gameobj, from_meshobj);
|
||||
|
||||
/* create the new bullet mesh */
|
||||
btCollisionShape* bm= shapeInfo->CreateBulletShape(spc->getConstructionInfo().m_margin);
|
||||
CcdConstructionInfo& cci = spc->getConstructionInfo();
|
||||
btCollisionShape* bm= shapeInfo->CreateBulletShape(cci.m_margin, cci.m_bGimpact, !cci.m_bSoft);
|
||||
|
||||
spc->ReplaceControllerShape(bm);
|
||||
return true;
|
||||
|
@ -236,7 +236,7 @@ bool CcdPhysicsController::CreateSoftbody()
|
||||
}
|
||||
} else
|
||||
{
|
||||
btBvhTriangleMeshShape* trimeshshape = (btBvhTriangleMeshShape*) m_cci.m_collisionShape;
|
||||
btTriangleMeshShape* trimeshshape = (btTriangleMeshShape*) m_cci.m_collisionShape;
|
||||
///only deal with meshes that have 1 sub part/component, for now
|
||||
if (trimeshshape->getMeshInterface()->getNumSubParts()==1)
|
||||
{
|
||||
@ -682,7 +682,7 @@ void CcdPhysicsController::PostProcessReplica(class PHY_IMotionState* motionsta
|
||||
if (m_shapeInfo)
|
||||
{
|
||||
m_shapeInfo->AddRef();
|
||||
m_collisionShape = m_shapeInfo->CreateBulletShape(m_cci.m_margin);
|
||||
m_collisionShape = m_shapeInfo->CreateBulletShape(m_cci.m_margin, m_cci.m_bGimpact, !m_cci.m_bSoft);
|
||||
|
||||
if (m_collisionShape)
|
||||
{
|
||||
@ -1276,7 +1276,7 @@ PHY_IPhysicsController* CcdPhysicsController::GetReplica()
|
||||
if (m_shapeInfo)
|
||||
{
|
||||
// This situation does not normally happen
|
||||
cinfo.m_collisionShape = m_shapeInfo->CreateBulletShape(m_cci.m_margin);
|
||||
cinfo.m_collisionShape = m_shapeInfo->CreateBulletShape(m_cci.m_margin, m_cci.m_bGimpact, !m_cci.m_bSoft);
|
||||
}
|
||||
else if (m_collisionShape)
|
||||
{
|
||||
@ -1379,9 +1379,9 @@ void DefaultMotionState::calculateWorldTransformations()
|
||||
// Shape constructor
|
||||
std::map<RAS_MeshObject*, CcdShapeConstructionInfo*> CcdShapeConstructionInfo::m_meshShapeMap;
|
||||
|
||||
CcdShapeConstructionInfo* CcdShapeConstructionInfo::FindMesh(RAS_MeshObject* mesh, struct DerivedMesh* dm, bool polytope, bool gimpact)
|
||||
CcdShapeConstructionInfo* CcdShapeConstructionInfo::FindMesh(RAS_MeshObject* mesh, struct DerivedMesh* dm, bool polytope)
|
||||
{
|
||||
if (polytope || dm || gimpact)
|
||||
if (polytope || dm)
|
||||
// not yet supported
|
||||
return NULL;
|
||||
|
||||
@ -1391,12 +1391,10 @@ CcdShapeConstructionInfo* CcdShapeConstructionInfo::FindMesh(RAS_MeshObject* mes
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, DerivedMesh* dm, bool polytope,bool useGimpact)
|
||||
bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, DerivedMesh* dm, bool polytope)
|
||||
{
|
||||
int numpolys, numverts;
|
||||
|
||||
m_useGimpact = useGimpact;
|
||||
|
||||
// assume no shape information
|
||||
// no support for dynamic change of shape yet
|
||||
assert(IsUnused());
|
||||
@ -1656,7 +1654,7 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, DerivedMesh* dm,
|
||||
}
|
||||
|
||||
// sharing only on static mesh at present, if you change that, you must also change in FindMesh
|
||||
if (!polytope && !dm && !useGimpact)
|
||||
if (!polytope && !dm)
|
||||
{
|
||||
// triangle shape can be shared, store the mesh object in the map
|
||||
m_meshShapeMap.insert(std::pair<RAS_MeshObject*,CcdShapeConstructionInfo*>(meshobj,this));
|
||||
@ -1991,13 +1989,13 @@ bool CcdShapeConstructionInfo::SetProxy(CcdShapeConstructionInfo* shapeInfo)
|
||||
return true;
|
||||
}
|
||||
|
||||
btCollisionShape* CcdShapeConstructionInfo::CreateBulletShape(btScalar margin)
|
||||
btCollisionShape* CcdShapeConstructionInfo::CreateBulletShape(btScalar margin, bool useGimpact, bool useBvh)
|
||||
{
|
||||
btCollisionShape* collisionShape = 0;
|
||||
btCompoundShape* compoundShape = 0;
|
||||
|
||||
if (m_shapeType == PHY_SHAPE_PROXY && m_shapeProxy != NULL)
|
||||
return m_shapeProxy->CreateBulletShape(margin);
|
||||
return m_shapeProxy->CreateBulletShape(margin, useGimpact, useBvh);
|
||||
|
||||
switch (m_shapeType)
|
||||
{
|
||||
@ -2037,7 +2035,7 @@ btCollisionShape* CcdShapeConstructionInfo::CreateBulletShape(btScalar margin)
|
||||
// 9 multiplications/additions and one function call for each triangle that passes the mid phase filtering
|
||||
// One possible optimization is to use directly the btBvhTriangleMeshShape when the scale is 1,1,1
|
||||
// and btScaledBvhTriangleMeshShape otherwise.
|
||||
if (m_useGimpact)
|
||||
if (useGimpact)
|
||||
{
|
||||
btTriangleIndexVertexArray* indexVertexArrays = new btTriangleIndexVertexArray(
|
||||
m_polygonIndexArray.size(),
|
||||
@ -2095,14 +2093,14 @@ btCollisionShape* CcdShapeConstructionInfo::CreateBulletShape(btScalar margin)
|
||||
if(m_unscaledShape) {
|
||||
DeleteBulletShape(m_unscaledShape, false);
|
||||
m_unscaledShape->~btBvhTriangleMeshShape();
|
||||
|
||||
m_unscaledShape = new(m_unscaledShape) btBvhTriangleMeshShape( indexVertexArrays, true );
|
||||
m_unscaledShape = new(m_unscaledShape) btBvhTriangleMeshShape( indexVertexArrays, true, useBvh );
|
||||
} else {
|
||||
m_unscaledShape = new btBvhTriangleMeshShape( indexVertexArrays, true );
|
||||
m_unscaledShape = new btBvhTriangleMeshShape( indexVertexArrays, true, useBvh );
|
||||
}
|
||||
|
||||
m_forceReInstance= false;
|
||||
m_unscaledShape->recalcLocalAabb();
|
||||
} else if (useBvh && m_unscaledShape->getOptimizedBvh() == NULL) {
|
||||
// the existing unscaledShape was not build with Bvh, do it now
|
||||
m_unscaledShape->buildOptimizedBvh();
|
||||
}
|
||||
collisionShape = new btScaledBvhTriangleMeshShape(m_unscaledShape, btVector3(1.0f,1.0f,1.0f));
|
||||
collisionShape->setMargin(margin);
|
||||
@ -2117,7 +2115,7 @@ btCollisionShape* CcdShapeConstructionInfo::CreateBulletShape(btScalar margin)
|
||||
sit != m_shapeArray.end();
|
||||
sit++)
|
||||
{
|
||||
collisionShape = (*sit)->CreateBulletShape(margin);
|
||||
collisionShape = (*sit)->CreateBulletShape(margin, useGimpact, useBvh);
|
||||
if (collisionShape)
|
||||
{
|
||||
collisionShape->setLocalScaling((*sit)->m_childScale);
|
||||
@ -2133,6 +2131,7 @@ btCollisionShape* CcdShapeConstructionInfo::CreateBulletShape(btScalar margin)
|
||||
void CcdShapeConstructionInfo::AddShape(CcdShapeConstructionInfo* shapeInfo)
|
||||
{
|
||||
m_shapeArray.push_back(shapeInfo);
|
||||
shapeInfo->AddRef();
|
||||
}
|
||||
|
||||
CcdShapeConstructionInfo::~CcdShapeConstructionInfo()
|
||||
|
@ -62,7 +62,7 @@ public:
|
||||
float uv[2];
|
||||
};
|
||||
|
||||
static CcdShapeConstructionInfo* FindMesh(class RAS_MeshObject* mesh, struct DerivedMesh* dm, bool polytope, bool gimpact);
|
||||
static CcdShapeConstructionInfo* FindMesh(class RAS_MeshObject* mesh, struct DerivedMesh* dm, bool polytope);
|
||||
|
||||
CcdShapeConstructionInfo() :
|
||||
m_shapeType(PHY_SHAPE_NONE),
|
||||
@ -74,7 +74,6 @@ public:
|
||||
m_refCount(1),
|
||||
m_meshObject(NULL),
|
||||
m_unscaledShape(NULL),
|
||||
m_useGimpact(false),
|
||||
m_forceReInstance(false),
|
||||
m_weldingThreshold1(0.f),
|
||||
m_shapeProxy(NULL)
|
||||
@ -143,7 +142,7 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SetMesh(class RAS_MeshObject* mesh, struct DerivedMesh* dm, bool polytope,bool useGimpact);
|
||||
bool SetMesh(class RAS_MeshObject* mesh, struct DerivedMesh* dm, bool polytope);
|
||||
RAS_MeshObject* GetMesh(void)
|
||||
{
|
||||
return m_meshObject;
|
||||
@ -158,7 +157,7 @@ public:
|
||||
return m_shapeProxy;
|
||||
}
|
||||
|
||||
btCollisionShape* CreateBulletShape(btScalar margin);
|
||||
btCollisionShape* CreateBulletShape(btScalar margin, bool useGimpact=false, bool useBvh=true);
|
||||
|
||||
// member variables
|
||||
PHY_ShapeType m_shapeType;
|
||||
@ -193,7 +192,6 @@ protected:
|
||||
btBvhTriangleMeshShape* m_unscaledShape;// holds the shared unscale BVH mesh shape,
|
||||
// the actual shape is of type btScaledBvhTriangleMeshShape
|
||||
std::vector<CcdShapeConstructionInfo*> m_shapeArray; // for compound shapes
|
||||
bool m_useGimpact; //use gimpact for concave dynamic/moving collision detection
|
||||
bool m_forceReInstance; //use gimpact for concave dynamic/moving collision detection
|
||||
float m_weldingThreshold1; //welding closeby vertices together can improve softbody stability etc.
|
||||
CcdShapeConstructionInfo* m_shapeProxy; // only used for PHY_SHAPE_PROXY, pointer to actual shape info
|
||||
@ -240,6 +238,7 @@ struct CcdConstructionInfo
|
||||
m_bRigid(false),
|
||||
m_bSoft(false),
|
||||
m_bSensor(false),
|
||||
m_bGimpact(false),
|
||||
m_collisionFilterGroup(DefaultFilter),
|
||||
m_collisionFilterMask(AllFilter),
|
||||
m_collisionShape(0),
|
||||
@ -308,6 +307,7 @@ struct CcdConstructionInfo
|
||||
bool m_bRigid;
|
||||
bool m_bSoft;
|
||||
bool m_bSensor;
|
||||
bool m_bGimpact; // use Gimpact for mesh body
|
||||
|
||||
///optional use of collision group/mask:
|
||||
///only collision with object goups that match the collision mask.
|
||||
|
Loading…
Reference in New Issue
Block a user