Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/gameengine/Physics')
-rw-r--r--source/gameengine/Physics/Bullet/CMakeLists.txt3
-rw-r--r--source/gameengine/Physics/Bullet/CcdPhysicsController.cpp848
-rw-r--r--source/gameengine/Physics/Bullet/CcdPhysicsController.h101
-rw-r--r--source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp585
-rw-r--r--source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h44
-rw-r--r--source/gameengine/Physics/Bullet/SConscript4
-rw-r--r--source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.cpp2
-rw-r--r--source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h2
-rw-r--r--source/gameengine/Physics/common/PHY_IPhysicsController.h16
-rw-r--r--source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h6
-rw-r--r--source/gameengine/Physics/common/PHY_Pro.h2
11 files changed, 989 insertions, 624 deletions
diff --git a/source/gameengine/Physics/Bullet/CMakeLists.txt b/source/gameengine/Physics/Bullet/CMakeLists.txt
index fbaa7bb59ba..e52dc1ba052 100644
--- a/source/gameengine/Physics/Bullet/CMakeLists.txt
+++ b/source/gameengine/Physics/Bullet/CMakeLists.txt
@@ -40,6 +40,7 @@ set(INC
../../../blender/makesdna
../../../../intern/container
../../../../intern/guardedalloc
+ ../../../../intern/glew-mx
../../../../intern/string
)
@@ -66,4 +67,6 @@ if(WITH_BULLET)
add_definitions(-DWITH_BULLET)
endif()
+add_definitions(${GL_DEFINITIONS})
+
blender_add_lib(ge_phys_bullet "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp
index 72c3b13e301..dbaa925db08 100644
--- a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp
+++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp
@@ -39,7 +39,6 @@ subject to the following restrictions:
#include "LinearMath/btConvexHull.h"
#include "BulletCollision/Gimpact/btGImpactShape.h"
-
#include "BulletSoftBody/btSoftRigidDynamicsWorld.h"
#include "DNA_mesh_types.h"
@@ -65,7 +64,6 @@ extern bool gDisableDeactivation;
float gLinearSleepingTreshold;
float gAngularSleepingTreshold;
-
BlenderBulletCharacterController::BlenderBulletCharacterController(btMotionState *motionState, btPairCachingGhostObject *ghost, btConvexShape* shape, float stepHeight)
: btKinematicCharacterController(ghost,shape,stepHeight,2),
m_motionState(motionState),
@@ -118,6 +116,18 @@ const btVector3& BlenderBulletCharacterController::getWalkDirection()
return m_walkDirection;
}
+bool CleanPairCallback::processOverlap(btBroadphasePair &pair)
+{
+ if ((pair.m_pProxy0 == m_cleanProxy) || (pair.m_pProxy1 == m_cleanProxy)) {
+ m_pairCache->cleanOverlappingPair(pair, m_dispatcher);
+ CcdPhysicsController *ctrl0 = (CcdPhysicsController*)(((btCollisionObject*)pair.m_pProxy0->m_clientObject)->getUserPointer());
+ CcdPhysicsController *ctrl1 = (CcdPhysicsController*)(((btCollisionObject*)pair.m_pProxy1->m_clientObject)->getUserPointer());
+ ctrl0->GetCollisionObject()->activate(false);
+ ctrl1->GetCollisionObject()->activate(false);
+ }
+ return false;
+}
+
CcdPhysicsController::CcdPhysicsController (const CcdConstructionInfo& ci)
:m_cci(ci)
{
@@ -148,11 +158,34 @@ CcdPhysicsController::CcdPhysicsController (const CcdConstructionInfo& ci)
m_savedCollisionFilterGroup = 0;
m_savedCollisionFilterMask = 0;
m_savedMass = 0.0;
+ m_savedDyna = false;
m_suspended = false;
CreateRigidbody();
}
+void CcdPhysicsController::addCcdConstraintRef(btTypedConstraint* c)
+{
+ int index = m_ccdConstraintRefs.findLinearSearch(c);
+ if (index == m_ccdConstraintRefs.size())
+ m_ccdConstraintRefs.push_back(c);
+}
+
+void CcdPhysicsController::removeCcdConstraintRef(btTypedConstraint* c)
+{
+ m_ccdConstraintRefs.remove(c);
+}
+
+btTypedConstraint* CcdPhysicsController::getCcdConstraintRef(int index)
+{
+ return m_ccdConstraintRefs[index];
+}
+
+int CcdPhysicsController::getNumCcdConstraintRefs() const
+{
+ return m_ccdConstraintRefs.size();
+}
+
btTransform& CcdPhysicsController::GetTransformFromMotionState(PHY_IMotionState* motionState)
{
static btTransform trans;
@@ -207,6 +240,11 @@ btRigidBody* CcdPhysicsController::GetRigidBody()
{
return btRigidBody::upcast(m_object);
}
+const btRigidBody* CcdPhysicsController::GetRigidBody() const
+{
+ return btRigidBody::upcast(m_object);
+}
+
btCollisionObject* CcdPhysicsController::GetCollisionObject()
{
return m_object;
@@ -560,20 +598,13 @@ void CcdPhysicsController::CreateRigidbody()
static void DeleteBulletShape(btCollisionShape* shape, bool free)
{
- if (shape->getShapeType() == TRIANGLE_MESH_SHAPE_PROXYTYPE)
- {
- // shapes based on meshes use an interface that contains the vertices.
- btTriangleMeshShape* meshShape = static_cast<btTriangleMeshShape*>(shape);
- btStridingMeshInterface* meshInterface = meshShape->getMeshInterface();
- if (meshInterface)
- delete meshInterface;
- }
- else if (shape->getShapeType() == GIMPACT_SHAPE_PROXYTYPE)
- {
- btGImpactMeshShape* meshShape = static_cast<btGImpactMeshShape*>(shape);
- btStridingMeshInterface* meshInterface = meshShape->getMeshInterface();
- if (meshInterface)
- delete meshInterface;
+ if (shape->getShapeType() == SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE) {
+ /* If we use Bullet scaled shape (btScaledBvhTriangleMeshShape) we have to
+ * free the child of the unscaled shape (btTriangleMeshShape) here.
+ */
+ btTriangleMeshShape *meshShape = ((btScaledBvhTriangleMeshShape *)shape)->getChildShape();
+ if (meshShape)
+ delete meshShape;
}
if (free) {
delete shape;
@@ -606,48 +637,41 @@ bool CcdPhysicsController::DeleteControllerShape( )
bool CcdPhysicsController::ReplaceControllerShape(btCollisionShape *newShape)
{
-
- /* Note, deleting the previous collision shape must be done already */
- /* if (m_collisionShape) DeleteControllerShape(); */
+ if (m_collisionShape)
+ DeleteControllerShape();
+
+ // If newShape is NULL it means to create a new Bullet shape.
+ if (!newShape)
+ newShape = m_shapeInfo->CreateBulletShape(m_cci.m_margin, m_cci.m_bGimpact, !m_cci.m_bSoft);
m_object->setCollisionShape(newShape);
- m_collisionShape= newShape;
- m_cci.m_collisionShape= newShape;
-
- if (GetSoftBody()) {
+ m_collisionShape = newShape;
+ m_cci.m_collisionShape = newShape;
+
+ btSoftBody *softBody = GetSoftBody();
+ if (softBody) {
+ btSoftRigidDynamicsWorld *world = GetPhysicsEnvironment()->GetDynamicsWorld();
+ // remove the old softBody
+ world->removeSoftBody(softBody);
+
// soft body must be recreated
- m_cci.m_physicsEnv->RemoveCcdPhysicsController(this);
delete m_object;
m_object = NULL;
// force complete reinitialization
m_softbodyMappingDone = false;
m_prototypeTransformInitialized = false;
m_softBodyTransformInitialized = false;
+
CreateSoftbody();
assert(m_object);
- // reinsert the new body
- m_cci.m_physicsEnv->AddCcdPhysicsController(this);
- }
-
- /* Copied from CcdPhysicsEnvironment::addCcdPhysicsController() */
-
- /* without this, an object can rest on the old physics mesh
- * and not move to account for the physics mesh, even with 'nosleep' */
- btSoftRigidDynamicsWorld* dw= GetPhysicsEnvironment()->GetDynamicsWorld();
- btCollisionObjectArray &obarr= dw->getCollisionObjectArray();
- btCollisionObject *ob;
- btBroadphaseProxy* proxy;
-
- for (int i= 0; i < obarr.size(); i++) {
- ob= obarr[i];
- if (ob->getCollisionShape() == newShape) {
- proxy = ob->getBroadphaseHandle();
-
- if (proxy)
- dw->getPairCache()->cleanProxyFromPairs(proxy,dw->getDispatcher());
- }
+
+ btSoftBody *newSoftBody = GetSoftBody();
+ // set the user
+ newSoftBody->setUserPointer(this);
+ // add the new softbody
+ world->addSoftBody(newSoftBody);
}
-
+
return true;
}
@@ -673,6 +697,35 @@ CcdPhysicsController::~CcdPhysicsController()
}
}
+void CcdPhysicsController::SimulationTick(float timestep)
+{
+ btRigidBody *body = GetRigidBody();
+ if (!body || body->isStaticObject())
+ return;
+
+ // Clamp linear velocity
+ if (m_cci.m_clamp_vel_max > 0.0f || m_cci.m_clamp_vel_min > 0.0f) {
+ const btVector3 &linvel = body->getLinearVelocity();
+ btScalar len = linvel.length();
+
+ if (m_cci.m_clamp_vel_max > 0.0f && len > m_cci.m_clamp_vel_max)
+ body->setLinearVelocity(linvel * (m_cci.m_clamp_vel_max / len));
+ else if (m_cci.m_clamp_vel_min > 0.0f && !btFuzzyZero(len) && len < m_cci.m_clamp_vel_min)
+ body->setLinearVelocity(linvel * (m_cci.m_clamp_vel_min / len));
+ }
+
+ // Clamp angular velocity
+ if (m_cci.m_clamp_angvel_max > 0.0f || m_cci.m_clamp_angvel_min > 0.0f) {
+ const btVector3 &angvel = body->getAngularVelocity();
+ btScalar len = angvel.length();
+
+ if (m_cci.m_clamp_angvel_max > 0.0f && len > m_cci.m_clamp_angvel_max)
+ body->setAngularVelocity(angvel * (m_cci.m_clamp_angvel_max / len));
+ else if (m_cci.m_clamp_angvel_min > 0.0f && !btFuzzyZero(len) && len < m_cci.m_clamp_angvel_min)
+ body->setAngularVelocity(angvel * (m_cci.m_clamp_angvel_min / len));
+ }
+}
+
/**
* SynchronizeMotionStates ynchronizes dynas, kinematic and deformable entities (and do 'late binding')
@@ -708,19 +761,6 @@ bool CcdPhysicsController::SynchronizeMotionStates(float time)
if (body && !body->isStaticObject())
{
-
- if ((m_cci.m_clamp_vel_max>0.0) || (m_cci.m_clamp_vel_min>0.0))
- {
- const btVector3& linvel = body->getLinearVelocity();
- float len= linvel.length();
-
- if ((m_cci.m_clamp_vel_max>0.0) && (len > m_cci.m_clamp_vel_max))
- body->setLinearVelocity(linvel * (m_cci.m_clamp_vel_max / len));
-
- else if ((m_cci.m_clamp_vel_min>0.0) && btFuzzyZero(len)==0 && (len < m_cci.m_clamp_vel_min))
- body->setLinearVelocity(linvel * (m_cci.m_clamp_vel_min / len));
- }
-
const btTransform& xform = body->getCenterOfMassTransform();
const btMatrix3x3& worldOri = xform.getBasis();
const btVector3& worldPos = xform.getOrigin();
@@ -780,6 +820,9 @@ void CcdPhysicsController::PostProcessReplica(class PHY_IMotionState* motionsta
m_registerCount = 0;
m_collisionShape = NULL;
+ // Clear all old constraints.
+ m_ccdConstraintRefs.clear();
+
// always create a new shape to avoid scaling bug
if (m_shapeInfo)
{
@@ -822,36 +865,6 @@ void CcdPhysicsController::PostProcessReplica(class PHY_IMotionState* motionsta
m_cci.m_physicsEnv->AddCcdPhysicsController(this);
-/* SM_Object* dynaparent=0;
- SumoPhysicsController* sumoparentctrl = (SumoPhysicsController* )parentctrl;
-
- if (sumoparentctrl)
- {
- dynaparent = sumoparentctrl->GetSumoObject();
- }
-
- SM_Object* orgsumoobject = m_sumoObj;
-
-
- m_sumoObj = new SM_Object(
- orgsumoobject->getShapeHandle(),
- orgsumoobject->getMaterialProps(),
- orgsumoobject->getShapeProps(),
- dynaparent);
-
- m_sumoObj->setRigidBody(orgsumoobject->isRigidBody());
-
- m_sumoObj->setMargin(orgsumoobject->getMargin());
- m_sumoObj->setPosition(orgsumoobject->getPosition());
- m_sumoObj->setOrientation(orgsumoobject->getOrientation());
- //if it is a dyna, register for a callback
- m_sumoObj->registerCallback(*this);
-
- m_sumoScene->add(* (m_sumoObj));
- */
-
-
-
}
void CcdPhysicsController::SetPhysicsEnvironment(class PHY_IPhysicsEnvironment *env)
@@ -899,12 +912,6 @@ void CcdPhysicsController::SetCenterOfMassTransform(btTransform& xform)
{
m_object->setInterpolationWorldTransform(xform);
}
- if (body)
- {
- body->setInterpolationLinearVelocity(body->getLinearVelocity());
- body->setInterpolationAngularVelocity(body->getAngularVelocity());
- body->updateInertiaTensor();
- }
m_object->setWorldTransform(xform);
}
}
@@ -1054,15 +1061,35 @@ void CcdPhysicsController::ResolveCombinedVelocities(float linvelX,float linvel
{
}
+void CcdPhysicsController::RefreshCollisions()
+{
+ // the object is in an inactive layer so it's useless to update it and can cause problems
+ if (!GetPhysicsEnvironment()->IsActiveCcdPhysicsController(this))
+ return;
+
+ btSoftRigidDynamicsWorld *dw = GetPhysicsEnvironment()->GetDynamicsWorld();
+ btBroadphaseProxy *proxy = m_object->getBroadphaseHandle();
+ btDispatcher *dispatcher = dw->getDispatcher();
+ btOverlappingPairCache *pairCache = dw->getPairCache();
+
+ CleanPairCallback cleanPairs(proxy, pairCache, dispatcher);
+ pairCache->processAllOverlappingPairs(&cleanPairs, dispatcher);
+
+ // Forcibly recreate the physics object
+ btBroadphaseProxy* handle = m_object->getBroadphaseHandle();
+ GetPhysicsEnvironment()->UpdateCcdPhysicsController(this, GetMass(), m_object->getCollisionFlags(), handle->m_collisionFilterGroup, handle->m_collisionFilterMask);
+}
+
void CcdPhysicsController::SuspendDynamics(bool ghost)
{
btRigidBody *body = GetRigidBody();
- if (body && !m_suspended && !GetConstructionInfo().m_bSensor)
+ if (body && !m_suspended && !GetConstructionInfo().m_bSensor && GetPhysicsEnvironment()->IsActiveCcdPhysicsController(this))
{
btBroadphaseProxy* handle = body->getBroadphaseHandle();
m_savedCollisionFlags = body->getCollisionFlags();
m_savedMass = GetMass();
+ m_savedDyna = m_cci.m_bDyna;
m_savedCollisionFilterGroup = handle->m_collisionFilterGroup;
m_savedCollisionFilterMask = handle->m_collisionFilterMask;
m_suspended = true;
@@ -1071,13 +1098,14 @@ void CcdPhysicsController::SuspendDynamics(bool ghost)
btCollisionObject::CF_STATIC_OBJECT|((ghost)?btCollisionObject::CF_NO_CONTACT_RESPONSE:(m_savedCollisionFlags&btCollisionObject::CF_NO_CONTACT_RESPONSE)),
btBroadphaseProxy::StaticFilter,
btBroadphaseProxy::AllFilter ^ btBroadphaseProxy::StaticFilter);
+ m_cci.m_bDyna = false;
}
}
void CcdPhysicsController::RestoreDynamics()
{
btRigidBody *body = GetRigidBody();
- if (body && m_suspended)
+ if (body && m_suspended && GetPhysicsEnvironment()->IsActiveCcdPhysicsController(this))
{
// before make sure any position change that was done in this logic frame are accounted for
SetTransform();
@@ -1087,6 +1115,7 @@ void CcdPhysicsController::RestoreDynamics()
m_savedCollisionFilterGroup,
m_savedCollisionFilterMask);
body->activate();
+ m_cci.m_bDyna = m_savedDyna;
m_suspended = false;
}
}
@@ -1354,6 +1383,42 @@ void CcdPhysicsController::Jump()
void CcdPhysicsController::SetActive(bool active)
{
}
+
+float CcdPhysicsController::GetLinearDamping() const
+{
+ const btRigidBody* body = GetRigidBody();
+ if (body)
+ return body->getLinearDamping();
+ return 0;
+}
+
+float CcdPhysicsController::GetAngularDamping() const
+{
+ const btRigidBody* body = GetRigidBody();
+ if (body)
+ return body->getAngularDamping();
+ return 0;
+}
+
+void CcdPhysicsController::SetLinearDamping(float damping)
+{
+ SetDamping(damping, GetAngularDamping());
+}
+
+void CcdPhysicsController::SetAngularDamping(float damping)
+{
+ SetDamping(GetLinearDamping(), damping);
+}
+
+void CcdPhysicsController::SetDamping(float linear, float angular)
+{
+ btRigidBody* body = GetRigidBody();
+ if (!body) return;
+
+ body->setDamping(linear, angular);
+}
+
+
// reading out information from physics
MT_Vector3 CcdPhysicsController::GetLinearVelocity()
{
@@ -1479,8 +1544,7 @@ void CcdPhysicsController::AddCompoundChild(PHY_IPhysicsController* child)
const btCollisionShape* childShape = childBody->getCollisionShape();
if (!rootShape ||
!childShape ||
- rootShape->getShapeType() != COMPOUND_SHAPE_PROXYTYPE ||
- childShape->getShapeType() == COMPOUND_SHAPE_PROXYTYPE)
+ rootShape->getShapeType() != COMPOUND_SHAPE_PROXYTYPE)
return;
btCompoundShape* compoundShape = (btCompoundShape*)rootShape;
// compute relative transformation between parent and child
@@ -1530,7 +1594,7 @@ void CcdPhysicsController::AddCompoundChild(PHY_IPhysicsController* child)
// must update the broadphase cache,
GetPhysicsEnvironment()->RefreshCcdPhysicsController(this);
// remove the children
- GetPhysicsEnvironment()->DisableCcdPhysicsController(childCtrl);
+ GetPhysicsEnvironment()->RemoveCcdPhysicsController(childCtrl);
}
/* Reverse function of the above, it will remove a shape from a compound shape
@@ -1586,7 +1650,7 @@ void CcdPhysicsController::RemoveCompoundChild(PHY_IPhysicsController* child)
// must update the broadphase cache,
GetPhysicsEnvironment()->RefreshCcdPhysicsController(this);
// reactivate the children
- GetPhysicsEnvironment()->EnableCcdPhysicsController(childCtrl);
+ GetPhysicsEnvironment()->AddCcdPhysicsController(childCtrl);
}
PHY_IPhysicsController* CcdPhysicsController::GetReplica()
@@ -1646,33 +1710,50 @@ PHY_IPhysicsController* CcdPhysicsController::GetReplicaForSensors()
* 2) from_gameobj - creates the phys mesh from the DerivedMesh where possible, else the RAS_MeshObject
* 3) this - update the phys mesh from DerivedMesh or RAS_MeshObject
*
- * Most of the logic behind this is in shapeInfo->UpdateMesh(...)
+ * Most of the logic behind this is in m_shapeInfo->UpdateMesh(...)
*/
bool CcdPhysicsController::ReinstancePhysicsShape(KX_GameObject *from_gameobj, RAS_MeshObject *from_meshobj)
{
- CcdShapeConstructionInfo *shapeInfo;
-
- shapeInfo = this->GetShapeInfo();
-
- if (shapeInfo->m_shapeType != PHY_SHAPE_MESH/* || spc->GetSoftBody()*/)
+ if (m_shapeInfo->m_shapeType != PHY_SHAPE_MESH)
return false;
- this->DeleteControllerShape();
-
- if (from_gameobj==NULL && from_meshobj==NULL)
- from_gameobj = KX_GameObject::GetClientObject((KX_ClientObjectInfo*)this->GetNewClientInfo());
+ if (!from_gameobj && !from_meshobj)
+ from_gameobj = KX_GameObject::GetClientObject((KX_ClientObjectInfo*)GetNewClientInfo());
/* updates the arrays used for making the new bullet mesh */
- shapeInfo->UpdateMesh(from_gameobj, from_meshobj);
+ m_shapeInfo->UpdateMesh(from_gameobj, from_meshobj);
/* create the new bullet mesh */
- CcdConstructionInfo& cci = this->GetConstructionInfo();
- btCollisionShape* bm= shapeInfo->CreateBulletShape(cci.m_margin, cci.m_bGimpact, !cci.m_bSoft);
+ GetPhysicsEnvironment()->UpdateCcdPhysicsControllerShape(m_shapeInfo);
- this->ReplaceControllerShape(bm);
return true;
}
+void CcdPhysicsController::ReplicateConstraints(KX_GameObject *replica, std::vector<KX_GameObject*> constobj)
+{
+ if (replica->GetConstraints().size() == 0 || !replica->GetPhysicsController())
+ return;
+
+ PHY_IPhysicsEnvironment *physEnv = GetPhysicsEnvironment();
+
+ vector<bRigidBodyJointConstraint*> constraints = replica->GetConstraints();
+ vector<bRigidBodyJointConstraint*>::iterator consit;
+
+ /* Object could have some constraints, iterate over all of theme to ensure that every constraint is recreated. */
+ for (consit = constraints.begin(); consit != constraints.end(); ++consit) {
+ /* Try to find the constraint targets in the list of group objects. */
+ bRigidBodyJointConstraint *dat = (*consit);
+ vector<KX_GameObject*>::iterator memit;
+ for (memit = constobj.begin(); memit != constobj.end(); ++memit) {
+ KX_GameObject *member = (*memit);
+ /* If the group member is the actual target for the constraint. */
+ if (dat->tar->id.name + 2 == member->GetName() && member->GetPhysicsController())
+ physEnv->SetupObjectConstraints(replica, member, dat);
+ }
+ }
+
+}
+
///////////////////////////////////////////////////////////
///A small utility class, DefaultMotionState
///
@@ -1754,7 +1835,7 @@ CcdShapeConstructionInfo* CcdShapeConstructionInfo::FindMesh(RAS_MeshObject* mes
return NULL;
}
-bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, DerivedMesh* dm, bool polytope)
+bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject *meshobj, DerivedMesh *dm, bool polytope)
{
int numpolys, numverts;
@@ -1766,7 +1847,7 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, DerivedMesh* dm,
bool free_dm = false;
// No mesh object or mesh has no polys
- if (!meshobj || meshobj->HasColliderPolygon()==false) {
+ if (!meshobj || !meshobj->HasColliderPolygon()) {
m_vertexArray.clear();
m_polygonIndexArray.clear();
m_triFaceArray.clear();
@@ -1789,80 +1870,83 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, DerivedMesh* dm,
/* double lookup */
const int *index_mf_to_mpoly = (const int *)dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
const int *index_mp_to_orig = (const int *)dm->getPolyDataArray(dm, CD_ORIGINDEX);
- if (index_mf_to_mpoly == NULL) {
+ if (!index_mf_to_mpoly) {
index_mp_to_orig = NULL;
}
m_shapeType = (polytope) ? PHY_SHAPE_POLYTOPE : PHY_SHAPE_MESH;
/* Convert blender geometry into bullet mesh, need these vars for mapping */
- vector<bool> vert_tag_array(numverts, false);
- unsigned int tot_bt_verts= 0;
+ std::vector<bool> vert_tag_array(numverts, false);
+ unsigned int tot_bt_verts = 0;
- if (polytope)
- {
+ if (polytope) {
// Tag verts we're using
- for (int p2=0; p2<numpolys; p2++)
- {
- MFace* mf = &mface[p2];
+ for (int p2 = 0; p2 < numpolys; p2++) {
+ MFace *mf = &mface[p2];
const int origi = index_mf_to_mpoly ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, p2) : p2;
- RAS_Polygon* poly = meshobj->GetPolygon(origi);
+ RAS_Polygon *poly = meshobj->GetPolygon(origi);
// only add polygons that have the collision flag set
- if (poly->IsCollider())
- {
- if (vert_tag_array[mf->v1] == false) {vert_tag_array[mf->v1] = true; tot_bt_verts++;}
- if (vert_tag_array[mf->v2] == false) {vert_tag_array[mf->v2] = true; tot_bt_verts++;}
- if (vert_tag_array[mf->v3] == false) {vert_tag_array[mf->v3] = true; tot_bt_verts++;}
- if (mf->v4 && vert_tag_array[mf->v4] == false) {vert_tag_array[mf->v4] = true; tot_bt_verts++;}
+ if (poly->IsCollider()) {
+ if (!vert_tag_array[mf->v1]) {
+ vert_tag_array[mf->v1] = true;
+ tot_bt_verts++;
+ }
+ if (!vert_tag_array[mf->v2]) {
+ vert_tag_array[mf->v2] = true;
+ tot_bt_verts++;
+ }
+ if (!vert_tag_array[mf->v3]) {
+ vert_tag_array[mf->v3] = true;
+ tot_bt_verts++;
+ }
+ if (mf->v4 && !vert_tag_array[mf->v4]) {
+ vert_tag_array[mf->v4] = true;
+ tot_bt_verts++;
+ }
}
}
-
+
/* Can happen with ngons */
if (!tot_bt_verts) {
goto cleanup_empty_mesh;
}
- m_vertexArray.resize(tot_bt_verts*3);
+ m_vertexArray.resize(tot_bt_verts * 3);
- btScalar *bt= &m_vertexArray[0];
+ btScalar *bt = &m_vertexArray[0];
- for (int p2=0; p2<numpolys; p2++)
- {
- MFace* mf = &mface[p2];
+ for (int p2 = 0; p2 < numpolys; p2++) {
+ MFace *mf = &mface[p2];
const int origi = index_mf_to_mpoly ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, p2) : p2;
- RAS_Polygon* poly= meshobj->GetPolygon(origi);
+ RAS_Polygon *poly = meshobj->GetPolygon(origi);
// only add polygons that have the collisionflag set
- if (poly->IsCollider())
- {
- if (vert_tag_array[mf->v1]==true)
- {
- const float* vtx = mvert[mf->v1].co;
+ if (poly->IsCollider()) {
+ if (vert_tag_array[mf->v1]) {
+ const float *vtx = mvert[mf->v1].co;
vert_tag_array[mf->v1] = false;
*bt++ = vtx[0];
*bt++ = vtx[1];
*bt++ = vtx[2];
}
- if (vert_tag_array[mf->v2]==true)
- {
- const float* vtx = mvert[mf->v2].co;
+ if (vert_tag_array[mf->v2]) {
+ const float *vtx = mvert[mf->v2].co;
vert_tag_array[mf->v2] = false;
*bt++ = vtx[0];
*bt++ = vtx[1];
*bt++ = vtx[2];
}
- if (vert_tag_array[mf->v3]==true)
- {
- const float* vtx = mvert[mf->v3].co;
+ if (vert_tag_array[mf->v3]) {
+ const float *vtx = mvert[mf->v3].co;
vert_tag_array[mf->v3] = false;
*bt++ = vtx[0];
*bt++ = vtx[1];
*bt++ = vtx[2];
}
- if (mf->v4 && vert_tag_array[mf->v4]==true)
- {
- const float* vtx = mvert[mf->v4].co;
+ if (mf->v4 && vert_tag_array[mf->v4]) {
+ const float *vtx = mvert[mf->v4].co;
vert_tag_array[mf->v4] = false;
*bt++ = vtx[0];
*bt++ = vtx[1];
@@ -1872,28 +1956,38 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, DerivedMesh* dm,
}
}
else {
- unsigned int tot_bt_tris= 0;
- vector<int> vert_remap_array(numverts, 0);
-
+ unsigned int tot_bt_tris = 0;
+ std::vector<int> vert_remap_array(numverts, 0);
+
// Tag verts we're using
- for (int p2=0; p2<numpolys; p2++)
- {
- MFace* mf = &mface[p2];
+ for (int p2 = 0; p2 < numpolys; p2++) {
+ MFace *mf = &mface[p2];
const int origi = index_mf_to_mpoly ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, p2) : p2;
- RAS_Polygon* poly= meshobj->GetPolygon(origi);
+ RAS_Polygon *poly = meshobj->GetPolygon(origi);
// only add polygons that have the collision flag set
- if (poly->IsCollider())
- {
- if (vert_tag_array[mf->v1]==false)
- {vert_tag_array[mf->v1] = true;vert_remap_array[mf->v1] = tot_bt_verts;tot_bt_verts++;}
- if (vert_tag_array[mf->v2]==false)
- {vert_tag_array[mf->v2] = true;vert_remap_array[mf->v2] = tot_bt_verts;tot_bt_verts++;}
- if (vert_tag_array[mf->v3]==false)
- {vert_tag_array[mf->v3] = true;vert_remap_array[mf->v3] = tot_bt_verts;tot_bt_verts++;}
- if (mf->v4 && vert_tag_array[mf->v4]==false)
- {vert_tag_array[mf->v4] = true;vert_remap_array[mf->v4] = tot_bt_verts;tot_bt_verts++;}
- tot_bt_tris += (mf->v4 ? 2:1); /* a quad or a tri */
+ if (poly->IsCollider()) {
+ if (!vert_tag_array[mf->v1]) {
+ vert_tag_array[mf->v1] = true;
+ vert_remap_array[mf->v1] = tot_bt_verts;
+ tot_bt_verts++;
+ }
+ if (!vert_tag_array[mf->v2]) {
+ vert_tag_array[mf->v2] = true;
+ vert_remap_array[mf->v2] = tot_bt_verts;
+ tot_bt_verts++;
+ }
+ if (!vert_tag_array[mf->v3]) {
+ vert_tag_array[mf->v3] = true;
+ vert_remap_array[mf->v3] = tot_bt_verts;
+ tot_bt_verts++;
+ }
+ if (mf->v4 && !vert_tag_array[mf->v4]) {
+ vert_tag_array[mf->v4] = true;
+ vert_remap_array[mf->v4] = tot_bt_verts;
+ tot_bt_verts++;
+ }
+ tot_bt_tris += (mf->v4 ? 2 : 1); /* a quad or a tri */
}
}
@@ -1902,43 +1996,39 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, DerivedMesh* dm,
goto cleanup_empty_mesh;
}
- m_vertexArray.resize(tot_bt_verts*3);
+ m_vertexArray.resize(tot_bt_verts * 3);
m_polygonIndexArray.resize(tot_bt_tris);
- m_triFaceArray.resize(tot_bt_tris*3);
- btScalar *bt= &m_vertexArray[0];
- int *poly_index_pt= &m_polygonIndexArray[0];
- int *tri_pt= &m_triFaceArray[0];
+ m_triFaceArray.resize(tot_bt_tris * 3);
+ btScalar *bt = &m_vertexArray[0];
+ int *poly_index_pt = &m_polygonIndexArray[0];
+ int *tri_pt = &m_triFaceArray[0];
UVco *uv_pt = NULL;
- if (tface)
- {
- m_triFaceUVcoArray.resize(tot_bt_tris*3);
+ if (tface) {
+ m_triFaceUVcoArray.resize(tot_bt_tris * 3);
uv_pt = &m_triFaceUVcoArray[0];
- }
- else
+ }
+ else
m_triFaceUVcoArray.clear();
- for (int p2=0; p2<numpolys; p2++)
- {
- MFace* mf = &mface[p2];
- MTFace* tf = (tface) ? &tface[p2] : NULL;
+ for (int p2 = 0; p2 < numpolys; p2++) {
+ MFace *mf = &mface[p2];
+ MTFace *tf = (tface) ? &tface[p2] : NULL;
const int origi = index_mf_to_mpoly ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, p2) : p2;
- RAS_Polygon* poly= meshobj->GetPolygon(origi);
+ RAS_Polygon *poly = meshobj->GetPolygon(origi);
// only add polygons that have the collisionflag set
- if (poly->IsCollider())
- {
- MVert *v1= &mvert[mf->v1];
- MVert *v2= &mvert[mf->v2];
- MVert *v3= &mvert[mf->v3];
+ if (poly->IsCollider()) {
+ MVert *v1 = &mvert[mf->v1];
+ MVert *v2 = &mvert[mf->v2];
+ MVert *v3 = &mvert[mf->v3];
// the face indices
tri_pt[0] = vert_remap_array[mf->v1];
tri_pt[1] = vert_remap_array[mf->v2];
tri_pt[2] = vert_remap_array[mf->v3];
- tri_pt= tri_pt+3;
- if (tf)
- {
+ tri_pt = tri_pt + 3;
+ if (tf) {
uv_pt[0].uv[0] = tf->uv[0][0];
uv_pt[0].uv[1] = tf->uv[0][1];
uv_pt[1].uv[0] = tf->uv[1][0];
@@ -1953,19 +2043,19 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, DerivedMesh* dm,
poly_index_pt++;
// the vertex location
- if (vert_tag_array[mf->v1]==true) { /* *** v1 *** */
+ if (vert_tag_array[mf->v1]) { /* *** v1 *** */
vert_tag_array[mf->v1] = false;
*bt++ = v1->co[0];
*bt++ = v1->co[1];
*bt++ = v1->co[2];
}
- if (vert_tag_array[mf->v2]==true) { /* *** v2 *** */
+ if (vert_tag_array[mf->v2]) { /* *** v2 *** */
vert_tag_array[mf->v2] = false;
*bt++ = v2->co[0];
*bt++ = v2->co[1];
*bt++ = v2->co[2];
}
- if (vert_tag_array[mf->v3]==true) { /* *** v3 *** */
+ if (vert_tag_array[mf->v3]) { /* *** v3 *** */
vert_tag_array[mf->v3] = false;
*bt++ = v3->co[0];
*bt++ = v3->co[1];
@@ -1974,12 +2064,12 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, DerivedMesh* dm,
if (mf->v4)
{
- MVert *v4= &mvert[mf->v4];
+ MVert *v4 = &mvert[mf->v4];
tri_pt[0] = vert_remap_array[mf->v1];
tri_pt[1] = vert_remap_array[mf->v3];
tri_pt[2] = vert_remap_array[mf->v4];
- tri_pt= tri_pt+3;
+ tri_pt = tri_pt + 3;
if (tf)
{
uv_pt[0].uv[0] = tf->uv[0][0];
@@ -1996,7 +2086,7 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, DerivedMesh* dm,
poly_index_pt++;
// the vertex location
- if (vert_tag_array[mf->v4] == true) { /* *** v4 *** */
+ if (vert_tag_array[mf->v4]) { /* *** v4 *** */
vert_tag_array[mf->v4] = false;
*bt++ = v4->co[0];
*bt++ = v4->co[1];
@@ -2010,27 +2100,27 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, DerivedMesh* dm,
/* If this ever gets confusing, print out an OBJ file for debugging */
#if 0
printf("# vert count %d\n", m_vertexArray.size());
- for (i=0; i<m_vertexArray.size(); i+=1) {
+ for (i = 0; i < m_vertexArray.size(); i += 1) {
printf("v %.6f %.6f %.6f\n", m_vertexArray[i].x(), m_vertexArray[i].y(), m_vertexArray[i].z());
}
printf("# face count %d\n", m_triFaceArray.size());
- for (i=0; i<m_triFaceArray.size(); i+=3) {
- printf("f %d %d %d\n", m_triFaceArray[i]+1, m_triFaceArray[i+1]+1, m_triFaceArray[i+2]+1);
+ for (i = 0; i < m_triFaceArray.size(); i += 3) {
+ printf("f %d %d %d\n", m_triFaceArray[i] + 1, m_triFaceArray[i + 1] + 1, m_triFaceArray[i + 2] + 1);
}
#endif
}
#if 0
- if (validpolys==false)
+ if (validpolys == false)
{
// should not happen
m_shapeType = PHY_SHAPE_NONE;
return false;
}
#endif
-
+
m_meshObject = meshobj;
if (free_dm) {
dm->release(dm);
@@ -2038,10 +2128,9 @@ 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)
- {
+ 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));
+ m_meshShapeMap.insert(std::pair<RAS_MeshObject *, CcdShapeConstructionInfo *>(meshobj, this));
}
return true;
@@ -2064,51 +2153,50 @@ cleanup_empty_mesh:
/* Updates the arrays used by CreateBulletShape(),
* take care that recalcLocalAabb() runs after CreateBulletShape is called.
* */
-bool CcdShapeConstructionInfo::UpdateMesh(class KX_GameObject* gameobj, class RAS_MeshObject* meshobj)
+bool CcdShapeConstructionInfo::UpdateMesh(class KX_GameObject *gameobj, class RAS_MeshObject *meshobj)
{
int numpolys;
int numverts;
- unsigned int tot_bt_tris= 0;
- unsigned int tot_bt_verts= 0;
+ unsigned int tot_bt_tris = 0;
+ unsigned int tot_bt_verts = 0;
int i, j;
int v_orig;
/* Use for looping over verts in a face as a try or 2 tris */
- const int quad_verts[7]= {0,1,2, 0,2,3, -1};
- const int tri_verts[4]= {0,1,2, -1};
+ const int quad_verts[7] = {0, 1, 2, 0, 2, 3, -1};
+ const int tri_verts[4] = {0, 1, 2, -1};
const int *fv_pt;
- if (gameobj==NULL && meshobj==NULL)
+ if (!gameobj && !meshobj)
return false;
-
+
if (m_shapeType != PHY_SHAPE_MESH)
return false;
- RAS_Deformer *deformer= gameobj ? gameobj->GetDeformer():NULL;
- DerivedMesh* dm = NULL;
+ RAS_Deformer *deformer = gameobj ? gameobj->GetDeformer() : NULL;
+ DerivedMesh *dm = NULL;
if (deformer)
dm = deformer->GetPhysicsMesh();
-
+
/* get the mesh from the object if not defined */
- if (meshobj==NULL) {
-
+ if (!meshobj) {
/* modifier mesh */
if (dm)
- meshobj= deformer->GetRasMesh();
-
+ meshobj = deformer->GetRasMesh();
+
/* game object first mesh */
- if (meshobj==NULL) {
+ if (!meshobj) {
if (gameobj->GetMeshCount() > 0) {
- meshobj= gameobj->GetMesh(0);
+ meshobj = gameobj->GetMesh(0);
}
}
}
-
- if (dm && deformer->GetRasMesh() == meshobj)
- { /*
+
+ if (dm && deformer->GetRasMesh() == meshobj) {
+ /*
* Derived Mesh Update
*
* */
@@ -2120,41 +2208,38 @@ bool CcdShapeConstructionInfo::UpdateMesh(class KX_GameObject* gameobj, class RA
/* double lookup */
const int *index_mf_to_mpoly = (const int *)dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
- const int *index_mp_to_orig = (const int *)dm->getPolyDataArray(dm, CD_ORIGINDEX);
- if (index_mf_to_mpoly == NULL) {
+ const int *index_mp_to_orig = (const int *)dm->getPolyDataArray(dm, CD_ORIGINDEX);
+ if (!index_mf_to_mpoly) {
index_mp_to_orig = NULL;
}
MFace *mf;
MVert *mv;
- int flen;
-
- if (CustomData_has_layer(&dm->faceData, CD_MTFACE))
- {
+ if (CustomData_has_layer(&dm->faceData, CD_MTFACE)) {
MTFace *tface = (MTFace *)dm->getTessFaceDataArray(dm, CD_MTFACE);
MTFace *tf;
- vector<bool> vert_tag_array(numverts, false);
- vector<int> vert_remap_array(numverts, 0);
+ std::vector<bool> vert_tag_array(numverts, false);
+ std::vector<int> vert_remap_array(numverts, 0);
+
+ for (mf = mface, tf = tface, i = 0; i < numpolys; mf++, tf++, i++) {
+ if (tf->mode & TF_DYNAMIC) {
+ int flen;
- for (mf= mface, tf= tface, i=0; i < numpolys; mf++, tf++, i++) {
- if (tf->mode & TF_DYNAMIC)
- {
if (mf->v4) {
- tot_bt_tris+= 2;
- flen= 4;
- } else {
+ tot_bt_tris += 2;
+ flen = 4;
+ }
+ else {
tot_bt_tris++;
- flen= 3;
+ flen = 3;
}
- for (j=0; j<flen; j++)
- {
+ for (j = 0; j < flen; j++) {
v_orig = (*(&mf->v1 + j));
- if (vert_tag_array[v_orig]==false)
- {
+ if (!vert_tag_array[v_orig]) {
vert_tag_array[v_orig] = true;
vert_remap_array[v_orig] = tot_bt_verts;
tot_bt_verts++;
@@ -2163,42 +2248,38 @@ bool CcdShapeConstructionInfo::UpdateMesh(class KX_GameObject* gameobj, class RA
}
}
- m_vertexArray.resize(tot_bt_verts*3);
- btScalar *bt= &m_vertexArray[0];
+ m_vertexArray.resize(tot_bt_verts * 3);
+ btScalar *bt = &m_vertexArray[0];
- m_triFaceArray.resize(tot_bt_tris*3);
- int *tri_pt= &m_triFaceArray[0];
+ m_triFaceArray.resize(tot_bt_tris * 3);
+ int *tri_pt = &m_triFaceArray[0];
- m_triFaceUVcoArray.resize(tot_bt_tris*3);
- UVco *uv_pt= &m_triFaceUVcoArray[0];
+ m_triFaceUVcoArray.resize(tot_bt_tris * 3);
+ UVco *uv_pt = &m_triFaceUVcoArray[0];
m_polygonIndexArray.resize(tot_bt_tris);
- int *poly_index_pt= &m_polygonIndexArray[0];
+ int *poly_index_pt = &m_polygonIndexArray[0];
- for (mf= mface, tf= tface, i=0; i < numpolys; mf++, tf++, i++)
- {
- if (tf->mode & TF_DYNAMIC)
- {
+ for (mf = mface, tf = tface, i = 0; i < numpolys; mf++, tf++, i++) {
+ if (tf->mode & TF_DYNAMIC) {
int origi = index_mf_to_mpoly ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, i) : i;
if (mf->v4) {
- fv_pt= quad_verts;
+ fv_pt = quad_verts;
*poly_index_pt++ = origi;
*poly_index_pt++ = origi;
- flen= 4;
- } else {
- fv_pt= tri_verts;
+ }
+ else {
+ fv_pt = tri_verts;
*poly_index_pt++ = origi;
- flen= 3;
}
- for (; *fv_pt > -1; fv_pt++)
- {
+ for (; *fv_pt > -1; fv_pt++) {
v_orig = (*(&mf->v1 + (*fv_pt)));
if (vert_tag_array[v_orig])
{
- mv= mvert + v_orig;
+ mv = mvert + v_orig;
*bt++ = mv->co[0];
*bt++ = mv->co[1];
*bt++ = mv->co[2];
@@ -2216,37 +2297,37 @@ bool CcdShapeConstructionInfo::UpdateMesh(class KX_GameObject* gameobj, class RA
else {
/* no need for a vertex mapping. simple/fast */
- tot_bt_verts= numverts;
+ tot_bt_verts = numverts;
- for (mf= mface, i=0; i < numpolys; mf++, i++) {
- tot_bt_tris += (mf->v4 ? 2:1);
+ for (mf = mface, i = 0; i < numpolys; mf++, i++) {
+ tot_bt_tris += (mf->v4 ? 2 : 1);
}
- m_vertexArray.resize(tot_bt_verts*3);
- btScalar *bt= &m_vertexArray[0];
+ m_vertexArray.resize(tot_bt_verts * 3);
+ btScalar *bt = &m_vertexArray[0];
- m_triFaceArray.resize(tot_bt_tris*3);
- int *tri_pt= &m_triFaceArray[0];
+ m_triFaceArray.resize(tot_bt_tris * 3);
+ int *tri_pt = &m_triFaceArray[0];
m_polygonIndexArray.resize(tot_bt_tris);
- int *poly_index_pt= &m_polygonIndexArray[0];
+ int *poly_index_pt = &m_polygonIndexArray[0];
m_triFaceUVcoArray.clear();
- for (mv= mvert, i=0; i < numverts; mv++, i++) {
+ for (mv = mvert, i = 0; i < numverts; mv++, i++) {
*bt++ = mv->co[0]; *bt++ = mv->co[1]; *bt++ = mv->co[2];
}
- for (mf= mface, i=0; i < numpolys; mf++, i++) {
+ for (mf = mface, i = 0; i < numpolys; mf++, i++) {
int origi = index_mf_to_mpoly ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, i) : i;
if (mf->v4) {
- fv_pt= quad_verts;
+ fv_pt = quad_verts;
*poly_index_pt++ = origi;
*poly_index_pt++ = origi;
}
else {
- fv_pt= tri_verts;
+ fv_pt = tri_verts;
*poly_index_pt++ = origi;
}
@@ -2255,51 +2336,46 @@ bool CcdShapeConstructionInfo::UpdateMesh(class KX_GameObject* gameobj, class RA
}
}
}
- else { /*
- * RAS Mesh Update
- *
- * */
-
+ else { /*
+ * RAS Mesh Update
+ *
+ * */
/* Note!, gameobj can be NULL here */
/* transverts are only used for deformed RAS_Meshes, the RAS_TexVert data
* is too hard to get at, see below for details */
- float (*transverts)[3] = NULL;
- int transverts_tot= 0; /* with deformed meshes - should always be greater then the max orginal index, or we get crashes */
+ float(*transverts)[3] = NULL;
+ int transverts_tot = 0; /* with deformed meshes - should always be greater than the max orginal index, or we get crashes */
if (deformer) {
/* map locations from the deformed array
*
* Could call deformer->Update(); but rely on redraw updating.
* */
- transverts= deformer->GetTransVerts(&transverts_tot);
+ transverts = deformer->GetTransVerts(&transverts_tot);
}
// Tag verts we're using
- numpolys= meshobj->NumPolygons();
- numverts= meshobj->m_sharedvertex_map.size();
+ numpolys = meshobj->NumPolygons();
+ numverts = meshobj->m_sharedvertex_map.size();
const float *xyz;
- vector<bool> vert_tag_array(numverts, false);
- vector<int> vert_remap_array(numverts, 0);
+ std::vector<bool> vert_tag_array(numverts, false);
+ std::vector<int> vert_remap_array(numverts, 0);
- for (int p=0; p<numpolys; p++)
- {
- RAS_Polygon* poly= meshobj->GetPolygon(p);
- if (poly->IsCollider())
- {
- for (i=0; i < poly->VertexCount(); i++)
- {
- v_orig= poly->GetVertex(i)->getOrigIndex();
- if (vert_tag_array[v_orig]==false)
- {
+ for (int p = 0; p < numpolys; p++) {
+ RAS_Polygon *poly = meshobj->GetPolygon(p);
+ if (poly->IsCollider()) {
+ for (i = 0; i < poly->VertexCount(); i++) {
+ v_orig = poly->GetVertex(i)->getOrigIndex();
+ if (!vert_tag_array[v_orig]) {
vert_tag_array[v_orig] = true;
vert_remap_array[v_orig] = tot_bt_verts;
tot_bt_verts++;
}
}
- tot_bt_tris += (poly->VertexCount()==4 ? 2:1);
+ tot_bt_tris += (poly->VertexCount() == 4 ? 2 : 1);
}
}
@@ -2307,32 +2383,29 @@ bool CcdShapeConstructionInfo::UpdateMesh(class KX_GameObject* gameobj, class RA
if (tot_bt_tris == 0 || tot_bt_verts == 0)
return false;
- m_vertexArray.resize(tot_bt_verts*3);
- btScalar *bt= &m_vertexArray[0];
+ m_vertexArray.resize(tot_bt_verts * 3);
+ btScalar *bt = &m_vertexArray[0];
- m_triFaceArray.resize(tot_bt_tris*3);
- int *tri_pt= &m_triFaceArray[0];
+ m_triFaceArray.resize(tot_bt_tris * 3);
+ int *tri_pt = &m_triFaceArray[0];
/* cant be used for anything useful in this case, since we don't rely on the original mesh
* will just be an array like pythons range(tot_bt_tris) */
m_polygonIndexArray.resize(tot_bt_tris);
- for (int p=0; p<numpolys; p++)
- {
- RAS_Polygon* poly= meshobj->GetPolygon(p);
+ int p = 0;
+ int t = 0;
+ while (t < tot_bt_tris) {
+ RAS_Polygon *poly = meshobj->GetPolygon(p);
- if (poly->IsCollider())
- {
+ if (poly->IsCollider()) {
/* quad or tri loop */
- fv_pt= (poly->VertexCount()==3 ? tri_verts:quad_verts);
-
- for (; *fv_pt > -1; fv_pt++)
- {
- v_orig= poly->GetVertex(*fv_pt)->getOrigIndex();
+ fv_pt = (poly->VertexCount() == 3 ? tri_verts : quad_verts);
- if (vert_tag_array[v_orig])
- {
+ for (; *fv_pt > -1; fv_pt++) {
+ v_orig = poly->GetVertex(*fv_pt)->getOrigIndex();
+ if (vert_tag_array[v_orig]) {
if (transverts) {
/* deformed mesh, using RAS_TexVert locations would be too troublesome
* because they are use the gameob as a hash in the material slot */
@@ -2342,55 +2415,60 @@ bool CcdShapeConstructionInfo::UpdateMesh(class KX_GameObject* gameobj, class RA
}
else {
/* static mesh python may have modified */
- xyz= meshobj->GetVertexLocation( v_orig );
+ xyz = meshobj->GetVertexLocation(v_orig);
*bt++ = xyz[0];
*bt++ = xyz[1];
*bt++ = xyz[2];
}
-
vert_tag_array[v_orig] = false;
}
-
*tri_pt++ = vert_remap_array[v_orig];
}
}
-
- m_polygonIndexArray[p] = p; /* dumb counting */
+ // first triangle
+ m_polygonIndexArray[t] = p;
+
+ // if the poly is a quad we transform it in two triangles
+ if (poly->VertexCount() == 4) {
+ t++;
+ // second triangle
+ m_polygonIndexArray[t] = p;
+ }
+ t++;
+ p++;
}
}
-
+
#if 0
/* needs #include <cstdio> */
printf("# vert count %d\n", m_vertexArray.size());
- for (int i=0; i<m_vertexArray.size(); i+=3) {
- printf("v %.6f %.6f %.6f\n", m_vertexArray[i], m_vertexArray[i+1], m_vertexArray[i+2]);
+ for (int i = 0; i < m_vertexArray.size(); i += 3) {
+ printf("v %.6f %.6f %.6f\n", m_vertexArray[i], m_vertexArray[i + 1], m_vertexArray[i + 2]);
}
printf("# face count %d\n", m_triFaceArray.size());
- for (int i=0; i<m_triFaceArray.size(); i+=3) {
- printf("f %d %d %d\n", m_triFaceArray[i]+1, m_triFaceArray[i+1]+1, m_triFaceArray[i+2]+1);
+ for (int i = 0; i < m_triFaceArray.size(); i += 3) {
+ printf("f %d %d %d\n", m_triFaceArray[i] + 1, m_triFaceArray[i + 1] + 1, m_triFaceArray[i + 2] + 1);
}
#endif
- /* force recreation of the m_unscaledShape.
+ /* force recreation of the m_triangleIndexVertexArray.
* If this has multiple users we cant delete */
- if (m_unscaledShape) {
- // don't free now so it can re-allocate under the same location and not break pointers.
- // DeleteBulletShape(m_unscaledShape);
- m_forceReInstance= true;
+ if (m_triangleIndexVertexArray) {
+ m_forceReInstance = true;
}
// Make sure to also replace the mesh in the shape map! Otherwise we leave dangling references when we free.
// Note, this whole business could cause issues with shared meshes. If we update one mesh, do we replace
// them all?
- std::map<RAS_MeshObject*,CcdShapeConstructionInfo*>::iterator mit = m_meshShapeMap.find(m_meshObject);
+ std::map<RAS_MeshObject *, CcdShapeConstructionInfo *>::iterator mit = m_meshShapeMap.find(m_meshObject);
if (mit != m_meshShapeMap.end()) {
m_meshShapeMap.erase(mit);
m_meshShapeMap[meshobj] = this;
}
- m_meshObject= meshobj;
-
+ m_meshObject = meshobj;
+
if (dm) {
dm->needsFree = 1;
dm->release(dm);
@@ -2398,8 +2476,6 @@ bool CcdShapeConstructionInfo::UpdateMesh(class KX_GameObject* gameobj, class RA
return true;
}
-
-
bool CcdShapeConstructionInfo::SetProxy(CcdShapeConstructionInfo* shapeInfo)
{
if (shapeInfo == NULL)
@@ -2462,74 +2538,61 @@ btCollisionShape* CcdShapeConstructionInfo::CreateBulletShape(btScalar margin, b
// 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 (useGimpact)
- {
- btTriangleIndexVertexArray* indexVertexArrays = new btTriangleIndexVertexArray(
+ if (useGimpact) {
+ if (!m_triangleIndexVertexArray || m_forceReInstance) {
+ if (m_triangleIndexVertexArray)
+ delete m_triangleIndexVertexArray;
+
+ m_triangleIndexVertexArray = new btTriangleIndexVertexArray(
m_polygonIndexArray.size(),
- &m_triFaceArray[0],
- 3*sizeof(int),
- m_vertexArray.size()/3,
+ m_triFaceArray.data(),
+ 3 * sizeof(int),
+ m_vertexArray.size() / 3,
&m_vertexArray[0],
- 3*sizeof(btScalar)
- );
- btGImpactMeshShape* gimpactShape = new btGImpactMeshShape(indexVertexArrays);
- gimpactShape->setMargin(margin);
- gimpactShape->updateBound();
- collisionShape = gimpactShape;
-
-
- } else
- {
- if (!m_unscaledShape || m_forceReInstance)
- {
-
- btTriangleIndexVertexArray* indexVertexArrays = 0;
+ 3 * sizeof(btScalar));
+ m_forceReInstance = false;
+ }
+ btGImpactMeshShape *gimpactShape = new btGImpactMeshShape(m_triangleIndexVertexArray);
+ gimpactShape->setMargin(margin);
+ gimpactShape->updateBound();
+ collisionShape = gimpactShape;
+ }
+ else {
+ if (!m_triangleIndexVertexArray || m_forceReInstance) {
///enable welding, only for the objects that need it (such as soft bodies)
- if (0.f != m_weldingThreshold1)
- {
- btTriangleMesh* collisionMeshData = new btTriangleMesh(true,false);
+ if (0.0f != m_weldingThreshold1) {
+ btTriangleMesh *collisionMeshData = new btTriangleMesh(true, false);
collisionMeshData->m_weldingThreshold = m_weldingThreshold1;
- bool removeDuplicateVertices=true;
+ bool removeDuplicateVertices = true;
// m_vertexArray not in multiple of 3 anymore, use m_triFaceArray
- for (unsigned int i=0; i<m_triFaceArray.size(); i+=3) {
- btScalar *bt = &m_vertexArray[3*m_triFaceArray[i]];
+ for (unsigned int i = 0; i < m_triFaceArray.size(); i += 3) {
+ btScalar *bt = &m_vertexArray[3 * m_triFaceArray[i]];
btVector3 v1(bt[0], bt[1], bt[2]);
- bt = &m_vertexArray[3*m_triFaceArray[i+1]];
+ bt = &m_vertexArray[3 * m_triFaceArray[i + 1]];
btVector3 v2(bt[0], bt[1], bt[2]);
- bt = &m_vertexArray[3*m_triFaceArray[i+2]];
+ bt = &m_vertexArray[3 * m_triFaceArray[i + 2]];
btVector3 v3(bt[0], bt[1], bt[2]);
collisionMeshData->addTriangle(v1, v2, v3, removeDuplicateVertices);
}
- indexVertexArrays = collisionMeshData;
-
- } else
- {
- indexVertexArrays = new btTriangleIndexVertexArray(
+ m_triangleIndexVertexArray = collisionMeshData;
+ }
+ else {
+ m_triangleIndexVertexArray = new btTriangleIndexVertexArray(
m_polygonIndexArray.size(),
- &m_triFaceArray[0],
- 3*sizeof(int),
- m_vertexArray.size()/3,
+ m_triFaceArray.data(),
+ 3 * sizeof(int),
+ m_vertexArray.size() / 3,
&m_vertexArray[0],
- 3*sizeof(btScalar));
+ 3 * sizeof(btScalar));
}
-
- // this shape will be shared and not deleted until shapeInfo is deleted
-
- // for UpdateMesh, reuse the last memory location so instancing wont crash.
- if (m_unscaledShape) {
- DeleteBulletShape(m_unscaledShape, false);
- m_unscaledShape->~btBvhTriangleMeshShape();
- m_unscaledShape = new(m_unscaledShape) btBvhTriangleMeshShape( indexVertexArrays, true, useBvh );
- } else {
- m_unscaledShape = new btBvhTriangleMeshShape( indexVertexArrays, true, useBvh );
- }
- m_forceReInstance= false;
- } else if (useBvh && m_unscaledShape->getOptimizedBvh() == NULL) {
- // the existing unscaledShape was not build with Bvh, do it now
- m_unscaledShape->buildOptimizedBvh();
+
+ m_forceReInstance = false;
}
- collisionShape = new btScaledBvhTriangleMeshShape(m_unscaledShape, btVector3(1.0f,1.0f,1.0f));
+
+ btBvhTriangleMeshShape *unscaledShape = new btBvhTriangleMeshShape(m_triangleIndexVertexArray, true, useBvh);
+ unscaledShape->setMargin(margin);
+ collisionShape = new btScaledBvhTriangleMeshShape(unscaledShape, btVector3(1.0f, 1.0f, 1.0f));
collisionShape->setMargin(margin);
}
break;
@@ -2571,10 +2634,9 @@ CcdShapeConstructionInfo::~CcdShapeConstructionInfo()
(*sit)->Release();
}
m_shapeArray.clear();
- if (m_unscaledShape)
- {
- DeleteBulletShape(m_unscaledShape, true);
- }
+
+ if (m_triangleIndexVertexArray)
+ delete m_triangleIndexVertexArray;
m_vertexArray.clear();
if (m_shapeType == PHY_SHAPE_MESH && m_meshObject != NULL)
{
diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.h b/source/gameengine/Physics/Bullet/CcdPhysicsController.h
index 4d0d96e07c6..c49ae8d20e1 100644
--- a/source/gameengine/Physics/Bullet/CcdPhysicsController.h
+++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.h
@@ -79,7 +79,7 @@ public:
m_userData(NULL),
m_refCount(1),
m_meshObject(NULL),
- m_unscaledShape(NULL),
+ m_triangleIndexVertexArray(NULL),
m_forceReInstance(false),
m_weldingThreshold1(0.f),
m_shapeProxy(NULL)
@@ -110,10 +110,11 @@ public:
void AddShape(CcdShapeConstructionInfo* shapeInfo);
- btTriangleMeshShape* GetMeshShape(void)
+ btStridingMeshInterface *GetMeshInterface()
{
- return (m_unscaledShape);
+ return m_triangleIndexVertexArray;
}
+
CcdShapeConstructionInfo* GetChildShape(int i)
{
if (i < 0 || i >= (int)m_shapeArray.size())
@@ -195,8 +196,8 @@ protected:
int m_refCount; // this class is shared between replicas
// keep track of users so that we can release it
RAS_MeshObject* m_meshObject; // Keep a pointer to the original mesh
- btBvhTriangleMeshShape* m_unscaledShape;// holds the shared unscale BVH mesh shape,
- // the actual shape is of type btScaledBvhTriangleMeshShape
+ // The list of vertexes and indexes for the triangle mesh, shared between Bullet shape.
+ btTriangleIndexVertexArray *m_triangleIndexVertexArray;
std::vector<CcdShapeConstructionInfo*> m_shapeArray; // for compound shapes
bool m_forceReInstance; //use gimpact for concave dynamic/moving collision detection
float m_weldingThreshold1; //welding closeby vertices together can improve softbody stability etc.
@@ -235,6 +236,8 @@ struct CcdConstructionInfo
m_mass(0.f),
m_clamp_vel_min(-1.f),
m_clamp_vel_max(-1.f),
+ m_clamp_angvel_min(0.0f),
+ m_clamp_angvel_max(0.0f),
m_restitution(0.1f),
m_friction(0.5f),
m_linearDamping(0.1f),
@@ -301,6 +304,8 @@ struct CcdConstructionInfo
btScalar m_mass;
btScalar m_clamp_vel_min;
btScalar m_clamp_vel_max;
+ btScalar m_clamp_angvel_min; // Minimum angular velocity, in radians/sec.
+ btScalar m_clamp_angvel_max; // Maximum angular velocity, in radians/sec.
btScalar m_restitution;
btScalar m_friction;
btScalar m_linearDamping;
@@ -447,6 +452,23 @@ public:
#endif
};
+class CleanPairCallback : public btOverlapCallback
+{
+ btBroadphaseProxy *m_cleanProxy;
+ btOverlappingPairCache *m_pairCache;
+ btDispatcher *m_dispatcher;
+
+public:
+ CleanPairCallback(btBroadphaseProxy *cleanProxy, btOverlappingPairCache *pairCache, btDispatcher *dispatcher)
+ :m_cleanProxy(cleanProxy),
+ m_pairCache(pairCache),
+ m_dispatcher(dispatcher)
+ {
+ }
+
+ virtual bool processOverlap(btBroadphasePair &pair);
+};
+
///CcdPhysicsController is a physics object that supports continuous collision detection and time of impact based physics resolution.
class CcdPhysicsController : public PHY_IPhysicsController
{
@@ -461,6 +483,7 @@ protected:
class CcdShapeConstructionInfo* m_shapeInfo;
btCollisionShape* m_bulletChildShape;
+ btAlignedObjectArray<btTypedConstraint*> m_ccdConstraintRefs; // keep track of typed constraints referencing this rigid body
friend class CcdPhysicsEnvironment; // needed when updating the controller
//some book keeping for replication
@@ -480,6 +503,7 @@ protected:
short m_savedCollisionFilterGroup;
short m_savedCollisionFilterMask;
MT_Scalar m_savedMass;
+ bool m_savedDyna;
bool m_suspended;
@@ -496,6 +520,16 @@ protected:
return (--m_registerCount == 0) ? true : false;
}
+ bool Registered() const
+ {
+ return (m_registerCount != 0);
+ }
+
+ void addCcdConstraintRef(btTypedConstraint* c);
+ void removeCcdConstraintRef(btTypedConstraint* c);
+ btTypedConstraint* getCcdConstraintRef(int index);
+ int getNumCcdConstraintRefs() const;
+
void SetWorldOrientation(const btMatrix3x3& mat);
void ForceWorldTransform(const btMatrix3x3& mat, const btVector3& pos);
@@ -506,7 +540,15 @@ protected:
CcdPhysicsController (const CcdConstructionInfo& ci);
+ /**
+ * Delete the current Bullet shape used in the rigid body.
+ */
bool DeleteControllerShape();
+
+ /**
+ * Delete the old Bullet shape and set the new Bullet shape : newShape
+ * \param newShape The new Bullet shape to set, if is NULL we create a new Bullet shape
+ */
bool ReplaceControllerShape(btCollisionShape *newShape);
virtual ~CcdPhysicsController();
@@ -522,6 +564,7 @@ protected:
btRigidBody* GetRigidBody();
+ const btRigidBody* GetRigidBody() const;
btCollisionObject* GetCollisionObject();
btSoftBody* GetSoftBody();
btKinematicCharacterController* GetCharacterController();
@@ -540,6 +583,13 @@ protected:
* SynchronizeMotionStates ynchronizes dynas, kinematic and deformable entities (and do 'late binding')
*/
virtual bool SynchronizeMotionStates(float time);
+
+ /**
+ * Called for every physics simulation step. Use this method for
+ * things like limiting linear and angular velocity.
+ */
+ void SimulationTick(float timestep);
+
/**
* WriteMotionStateToDynamics ynchronizes dynas, kinematic and deformable entities (and do 'late binding')
*/
@@ -573,6 +623,12 @@ protected:
virtual void Jump();
virtual void SetActive(bool active);
+ virtual float GetLinearDamping() const;
+ virtual float GetAngularDamping() const;
+ virtual void SetLinearDamping(float damping);
+ virtual void SetAngularDamping(float damping);
+ virtual void SetDamping(float linear, float angular);
+
// reading out information from physics
virtual MT_Vector3 GetLinearVelocity();
virtual MT_Vector3 GetAngularVelocity();
@@ -584,7 +640,7 @@ protected:
virtual void ResolveCombinedVelocities(float linvelX,float linvelY,float linvelZ,float angVelX,float angVelY,float angVelZ);
-
+ virtual void RefreshCollisions();
virtual void SuspendDynamics(bool ghost);
virtual void RestoreDynamics();
@@ -612,8 +668,12 @@ protected:
virtual void CalcXform() {}
virtual void SetMargin(float margin)
{
- if (m_collisionShape)
- m_collisionShape->setMargin(btScalar(margin));
+ if (m_collisionShape) {
+ m_collisionShape->setMargin(margin);
+ // if the shape use a unscaled shape we have also to set the correct margin in it
+ if (m_collisionShape->getShapeType() == SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE)
+ ((btScaledBvhTriangleMeshShape *)m_collisionShape)->getChildShape()->setMargin(margin);
+ }
}
virtual float GetMargin() const
{
@@ -652,6 +712,23 @@ protected:
return m_cci.m_clamp_vel_max;
}
+ virtual void SetAngularVelocityMin(float val)
+ {
+ m_cci.m_clamp_angvel_min = val;
+ }
+ virtual float GetAngularVelocityMin() const
+ {
+ return m_cci.m_clamp_angvel_min;
+ }
+ virtual void SetAngularVelocityMax(float val)
+ {
+ m_cci.m_clamp_angvel_max = val;
+ }
+ virtual float GetAngularVelocityMax() const
+ {
+ return m_cci.m_clamp_angvel_max;
+ }
+
bool WantsSleeping();
void UpdateDeactivation(float timeStep);
@@ -698,6 +775,11 @@ protected:
return GetConstructionInfo().m_bDyna;
}
+ virtual bool IsSuspended() const
+ {
+ return m_suspended;
+ }
+
virtual bool IsCompound()
{
return GetConstructionInfo().m_shapeInfo->m_shapeType == PHY_SHAPE_COMPOUND;
@@ -705,6 +787,9 @@ protected:
virtual bool ReinstancePhysicsShape(KX_GameObject *from_gameobj, RAS_MeshObject* from_meshobj);
+ /* Method to replicate rigid body joint contraints for group instances. */
+ virtual void ReplicateConstraints(KX_GameObject *gameobj, std::vector<KX_GameObject*> constobj);
+
#ifdef WITH_CXX_GUARDEDALLOC
MEM_CXX_CLASS_ALLOC_FUNCS("GE:CcdPhysicsController")
#endif
diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp
index e17d4402556..eec579158cc 100644
--- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp
+++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp
@@ -174,26 +174,27 @@ public:
virtual void GetWheelPosition(int wheelIndex,float& posX,float& posY,float& posZ) const
{
- btTransform trans = m_vehicle->getWheelTransformWS(wheelIndex);
- posX = trans.getOrigin().x();
- posY = trans.getOrigin().y();
- posZ = trans.getOrigin().z();
+ if ((wheelIndex>=0) && (wheelIndex< m_vehicle->getNumWheels()))
+ {
+ btVector3 origin = m_vehicle->getWheelTransformWS(wheelIndex).getOrigin();
+
+ posX = origin.x();
+ posY = origin.y();
+ posZ = origin.z();
+ }
}
+
virtual void GetWheelOrientationQuaternion(int wheelIndex,float& quatX,float& quatY,float& quatZ,float& quatW) const
{
- btTransform trans = m_vehicle->getWheelTransformWS(wheelIndex);
- btQuaternion quat = trans.getRotation();
- btMatrix3x3 orn2(quat);
-
- quatX = trans.getRotation().x();
- quatY = trans.getRotation().y();
- quatZ = trans.getRotation().z();
- quatW = trans.getRotation()[3];
-
-
- //printf("test");
-
+ if ((wheelIndex>=0) && (wheelIndex< m_vehicle->getNumWheels()))
+ {
+ btQuaternion quat = m_vehicle->getWheelTransformWS(wheelIndex).getRotation();
+ quatX = quat.x();
+ quatY = quat.y();
+ quatZ = quat.z();
+ quatW = quat.w();
+ }
}
virtual float GetWheelRotation(int wheelIndex) const
@@ -205,8 +206,8 @@ public:
btWheelInfo& info = m_vehicle->getWheelInfo(wheelIndex);
rotation = info.m_rotation;
}
- return rotation;
+ return rotation;
}
@@ -223,12 +224,16 @@ public:
virtual void SetSteeringValue(float steering,int wheelIndex)
{
- m_vehicle->setSteeringValue(steering,wheelIndex);
+ if ((wheelIndex>=0) && (wheelIndex< m_vehicle->getNumWheels())) {
+ m_vehicle->setSteeringValue(steering,wheelIndex);
+ }
}
virtual void ApplyEngineForce(float force,int wheelIndex)
{
- m_vehicle->applyEngineForce(force,wheelIndex);
+ if ((wheelIndex>=0) && (wheelIndex< m_vehicle->getNumWheels())) {
+ m_vehicle->applyEngineForce(force,wheelIndex);
+ }
}
virtual void ApplyBraking(float braking,int wheelIndex)
@@ -405,6 +410,10 @@ m_ccdMode(0),
m_solverType(-1),
m_profileTimings(0),
m_enableSatCollisionDetection(false),
+m_deactivationTime(2.0f),
+m_linearDeactivationThreshold(0.8f),
+m_angularDeactivationThreshold(1.0f),
+m_contactBreakingThreshold(0.02f),
m_solver(NULL),
m_ownPairCache(NULL),
m_filterCallback(NULL),
@@ -447,6 +456,7 @@ m_scalingPropagated(false)
SetSolverType(1);//issues with quickstep and memory allocations
// m_dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher,m_broadphase,m_solver,m_collisionConfiguration);
m_dynamicsWorld = new btSoftRigidDynamicsWorld(dispatcher,m_broadphase,m_solver,m_collisionConfiguration);
+ m_dynamicsWorld->setInternalTickCallback(&CcdPhysicsEnvironment::StaticSimulationSubtickCallback, this);
//m_dynamicsWorld->getSolverInfo().m_linearSlop = 0.01f;
//m_dynamicsWorld->getSolverInfo().m_solverMode= SOLVER_USE_WARMSTARTING + SOLVER_USE_2_FRICTION_DIRECTIONS + SOLVER_RANDMIZE_ORDER + SOLVER_USE_FRICTION_WARMSTARTING;
@@ -456,15 +466,20 @@ m_scalingPropagated(false)
void CcdPhysicsEnvironment::AddCcdPhysicsController(CcdPhysicsController* ctrl)
{
+ // the controller is already added we do nothing
+ if (!m_controllers.insert(ctrl).second) {
+ return;
+ }
+
btRigidBody* body = ctrl->GetRigidBody();
btCollisionObject* obj = ctrl->GetCollisionObject();
//this m_userPointer is just used for triggers, see CallbackTriggers
obj->setUserPointer(ctrl);
- if (body)
- body->setGravity( m_gravity );
-
- m_controllers.insert(ctrl);
+ if (body) {
+ body->setGravity(m_gravity);
+ body->setSleepingThresholds(m_linearDeactivationThreshold, m_angularDeactivationThreshold);
+ }
if (body)
{
@@ -496,20 +511,49 @@ void CcdPhysicsEnvironment::AddCcdPhysicsController(CcdPhysicsController* ctrl)
assert(obj->getBroadphaseHandle());
}
-
+void CcdPhysicsEnvironment::RemoveConstraint(btTypedConstraint *con)
+{
+ btRigidBody rbA = con->getRigidBodyA();
+ btRigidBody rbB = con->getRigidBodyB();
+ rbA.activate();
+ rbB.activate();
+ m_dynamicsWorld->removeConstraint(con);
+
+ if (rbA.getUserPointer()) {
+ ((CcdPhysicsController *)rbA.getUserPointer())->removeCcdConstraintRef(con);
+ }
+
+ if (rbB.getUserPointer()) {
+ ((CcdPhysicsController *)rbB.getUserPointer())->removeCcdConstraintRef(con);
+ }
+
+ /* Since we remove the constraint in the onwer and the target, we can delete it,
+ * KX_ConstraintWrapper keep the constraint id not the pointer, so no problems. */
+ delete con;
+}
bool CcdPhysicsEnvironment::RemoveCcdPhysicsController(CcdPhysicsController* ctrl)
{
+ // if the physics controller is already removed we do nothing
+ if (!m_controllers.erase(ctrl)) {
+ return false;
+ }
+
//also remove constraint
btRigidBody* body = ctrl->GetRigidBody();
if (body)
{
- for (int i=body->getNumConstraintRefs()-1;i>=0;i--)
+ btBroadphaseProxy *proxy = ctrl->GetCollisionObject()->getBroadphaseHandle();
+ btDispatcher *dispatcher = m_dynamicsWorld->getDispatcher();
+ btOverlappingPairCache *pairCache = m_dynamicsWorld->getPairCache();
+
+ CleanPairCallback cleanPairs(proxy, pairCache, dispatcher);
+ pairCache->processAllOverlappingPairs(&cleanPairs, dispatcher);
+
+ for (int i = ctrl->getNumCcdConstraintRefs() - 1; i >= 0; i--)
{
- btTypedConstraint* con = body->getConstraintRef(i);
- m_dynamicsWorld->removeConstraint(con);
- body->removeConstraintRef(con);
- //delete con; //might be kept by python KX_ConstraintWrapper
+ btTypedConstraint* con = ctrl->getCcdConstraintRef(i);
+ RemoveConstraint(con);
}
m_dynamicsWorld->removeRigidBody(ctrl->GetRigidBody());
@@ -524,7 +568,7 @@ bool CcdPhysicsEnvironment::RemoveCcdPhysicsController(CcdPhysicsController* ctr
}
if (vehicle_constraint > 0)
- RemoveConstraint(vehicle_constraint);
+ RemoveConstraintById(vehicle_constraint);
} else
{
//if a softbody
@@ -541,13 +585,8 @@ bool CcdPhysicsEnvironment::RemoveCcdPhysicsController(CcdPhysicsController* ctr
}
}
}
- if (ctrl->m_registerCount != 0)
- printf("Warning: removing controller with non-zero m_registerCount: %d\n", ctrl->m_registerCount);
- //remove it from the triggers
- m_triggerControllers.erase(ctrl);
-
- return (m_controllers.erase(ctrl) != 0);
+ return true;
}
void CcdPhysicsEnvironment::UpdateCcdPhysicsController(CcdPhysicsController* ctrl, btScalar newMass, int newCollisionFlags, short int newCollisionGroup, short int newCollisionMask)
@@ -555,6 +594,7 @@ void CcdPhysicsEnvironment::UpdateCcdPhysicsController(CcdPhysicsController* ctr
// this function is used when the collisionning group of a controller is changed
// remove and add the collistioning object
btRigidBody* body = ctrl->GetRigidBody();
+ btSoftBody *softBody = ctrl->GetSoftBody();
btCollisionObject* obj = ctrl->GetCollisionObject();
if (obj)
{
@@ -568,6 +608,9 @@ void CcdPhysicsEnvironment::UpdateCcdPhysicsController(CcdPhysicsController* ctr
body->setMassProps(newMass, inertia);
m_dynamicsWorld->addRigidBody(body, newCollisionGroup, newCollisionMask);
}
+ else if (softBody) {
+ m_dynamicsWorld->addSoftBody(softBody);
+ }
else {
m_dynamicsWorld->addCollisionObject(obj, newCollisionGroup, newCollisionMask);
}
@@ -579,43 +622,6 @@ void CcdPhysicsEnvironment::UpdateCcdPhysicsController(CcdPhysicsController* ctr
ctrl->m_cci.m_collisionFlags = newCollisionFlags;
}
-void CcdPhysicsEnvironment::EnableCcdPhysicsController(CcdPhysicsController* ctrl)
-{
- if (m_controllers.insert(ctrl).second)
- {
- btCollisionObject* obj = ctrl->GetCollisionObject();
- obj->setUserPointer(ctrl);
- // update the position of the object from the user
- if (ctrl->GetMotionState())
- {
- btTransform xform = CcdPhysicsController::GetTransformFromMotionState(ctrl->GetMotionState());
- ctrl->SetCenterOfMassTransform(xform);
- }
- m_dynamicsWorld->addCollisionObject(obj,
- ctrl->GetCollisionFilterGroup(), ctrl->GetCollisionFilterMask());
- }
-}
-
-void CcdPhysicsEnvironment::DisableCcdPhysicsController(CcdPhysicsController* ctrl)
-{
- if (m_controllers.erase(ctrl))
- {
- btRigidBody* body = ctrl->GetRigidBody();
- if (body)
- {
- m_dynamicsWorld->removeRigidBody(body);
- } else
- {
- if (ctrl->GetSoftBody())
- {
- } else
- {
- m_dynamicsWorld->removeCollisionObject(ctrl->GetCollisionObject());
- }
- }
- }
-}
-
void CcdPhysicsEnvironment::RefreshCcdPhysicsController(CcdPhysicsController* ctrl)
{
btCollisionObject* obj = ctrl->GetCollisionObject();
@@ -629,6 +635,11 @@ void CcdPhysicsEnvironment::RefreshCcdPhysicsController(CcdPhysicsController* ct
}
}
+bool CcdPhysicsEnvironment::IsActiveCcdPhysicsController(CcdPhysicsController *ctrl)
+{
+ return (m_controllers.find(ctrl) != m_controllers.end());
+}
+
void CcdPhysicsEnvironment::AddCcdGraphicController(CcdGraphicController* ctrl)
{
if (m_cullingTree && !ctrl->GetBroadphaseHandle())
@@ -664,6 +675,19 @@ void CcdPhysicsEnvironment::RemoveCcdGraphicController(CcdGraphicController* ctr
}
}
+void CcdPhysicsEnvironment::UpdateCcdPhysicsControllerShape(CcdShapeConstructionInfo *shapeInfo)
+{
+ for (std::set<CcdPhysicsController *>::iterator it = m_controllers.begin(); it != m_controllers.end(); ++it) {
+ CcdPhysicsController *ctrl = *it;
+
+ if (ctrl->GetShapeInfo() != shapeInfo)
+ continue;
+
+ ctrl->ReplaceControllerShape(NULL);
+ RefreshCcdPhysicsController(ctrl);
+ }
+}
+
void CcdPhysicsEnvironment::BeginFrame()
{
@@ -675,11 +699,31 @@ void CcdPhysicsEnvironment::DebugDrawWorld()
m_dynamicsWorld->debugDrawWorld();
}
+void CcdPhysicsEnvironment::StaticSimulationSubtickCallback(btDynamicsWorld *world, btScalar timeStep)
+{
+ // Get the pointer to the CcdPhysicsEnvironment associated with this Bullet world.
+ CcdPhysicsEnvironment *this_ = static_cast<CcdPhysicsEnvironment*>(world->getWorldUserInfo());
+ this_->SimulationSubtickCallback(timeStep);
+}
+
+void CcdPhysicsEnvironment::SimulationSubtickCallback(btScalar timeStep)
+{
+ std::set<CcdPhysicsController*>::iterator it;
+
+ for (it = m_controllers.begin(); it != m_controllers.end(); it++) {
+ (*it)->SimulationTick(timeStep);
+ }
+}
+
bool CcdPhysicsEnvironment::ProceedDeltaTime(double curTime,float timeStep,float interval)
{
std::set<CcdPhysicsController*>::iterator it;
int i;
+ // Update Bullet global variables.
+ gDeactivationTime = m_deactivationTime;
+ gContactBreakingThreshold = m_contactBreakingThreshold;
+
for (it=m_controllers.begin(); it!=m_controllers.end(); it++)
{
(*it)->SynchronizeMotionStates(timeStep);
@@ -745,8 +789,8 @@ public:
void CcdPhysicsEnvironment::ProcessFhSprings(double curTime,float interval)
{
std::set<CcdPhysicsController*>::iterator it;
- // dynamic of Fh spring is based on a timestep of 1/60
- int numIter = (int)(interval*60.0001f);
+ // Add epsilon to the tick rate for numerical stability
+ int numIter = (int)(interval*(KX_KetsjiEngine::GetTicRate() + 0.001f));
for (it=m_controllers.begin(); it!=m_controllers.end(); it++)
{
@@ -899,21 +943,32 @@ void CcdPhysicsEnvironment::SetNumIterations(int numIter)
}
void CcdPhysicsEnvironment::SetDeactivationTime(float dTime)
{
- gDeactivationTime = dTime;
+ m_deactivationTime = dTime;
}
void CcdPhysicsEnvironment::SetDeactivationLinearTreshold(float linTresh)
{
- gLinearSleepingTreshold = linTresh;
+ m_linearDeactivationThreshold = linTresh;
+
+ // Update from all controllers.
+ for (std::set<CcdPhysicsController*>::iterator it = m_controllers.begin(); it != m_controllers.end(); it++) {
+ if ((*it)->GetRigidBody())
+ (*it)->GetRigidBody()->setSleepingThresholds(m_linearDeactivationThreshold, m_angularDeactivationThreshold);
+ }
}
void CcdPhysicsEnvironment::SetDeactivationAngularTreshold(float angTresh)
{
- gAngularSleepingTreshold = angTresh;
+ m_angularDeactivationThreshold = angTresh;
+
+ // Update from all controllers.
+ for (std::set<CcdPhysicsController*>::iterator it = m_controllers.begin(); it != m_controllers.end(); it++) {
+ if ((*it)->GetRigidBody())
+ (*it)->GetRigidBody()->setSleepingThresholds(m_linearDeactivationThreshold, m_angularDeactivationThreshold);
+ }
}
void CcdPhysicsEnvironment::SetContactBreakingTreshold(float contactBreakingTreshold)
{
- gContactBreakingThreshold = contactBreakingTreshold;
-
+ m_contactBreakingThreshold = contactBreakingTreshold;
}
@@ -1059,11 +1114,12 @@ int CcdPhysicsEnvironment::CreateUniversalD6Constraint(
return 0;
}
-
-
-void CcdPhysicsEnvironment::RemoveConstraint(int constraintId)
+void CcdPhysicsEnvironment::RemoveConstraintById(int constraintId)
{
-
+ // For soft body constraints
+ if (constraintId == 0)
+ return;
+
int i;
int numConstraints = m_dynamicsWorld->getNumConstraints();
for (i=0;i<numConstraints;i++)
@@ -1071,9 +1127,7 @@ void CcdPhysicsEnvironment::RemoveConstraint(int constraintId)
btTypedConstraint* constraint = m_dynamicsWorld->getConstraint(i);
if (constraint->getUserConstraintId() == constraintId)
{
- constraint->getRigidBodyA().activate();
- constraint->getRigidBodyB().activate();
- m_dynamicsWorld->removeConstraint(constraint);
+ RemoveConstraint(constraint);
break;
}
}
@@ -1149,17 +1203,8 @@ static bool GetHitTriangle(btCollisionShape* shape, CcdShapeConstructionInfo* sh
int indexstride;
int numfaces;
PHY_ScalarType indicestype;
- btStridingMeshInterface* meshInterface = NULL;
- btTriangleMeshShape* triangleShape = shapeInfo->GetMeshShape();
+ btStridingMeshInterface* meshInterface = shapeInfo->GetMeshInterface();
- if (triangleShape)
- meshInterface = triangleShape->getMeshInterface();
- else
- {
- // other possibility is gImpact
- if (shape->getShapeType() == GIMPACT_SHAPE_PROXYTYPE)
- meshInterface = (static_cast<btGImpactMeshShape*>(shape))->getMeshInterface();
- }
if (!meshInterface)
return false;
@@ -2016,6 +2061,9 @@ CcdPhysicsEnvironment::~CcdPhysicsEnvironment()
float CcdPhysicsEnvironment::GetConstraintParam(int constraintId,int param)
{
btTypedConstraint* typedConstraint = GetConstraintById(constraintId);
+ if (!typedConstraint)
+ return 0.0f;
+
switch (typedConstraint->getUserConstraintType())
{
case PHY_GENERIC_6DOF_CONSTRAINT:
@@ -2055,6 +2103,9 @@ float CcdPhysicsEnvironment::GetConstraintParam(int constraintId,int param)
void CcdPhysicsEnvironment::SetConstraintParam(int constraintId,int param,float value0,float value1)
{
btTypedConstraint* typedConstraint = GetConstraintById(constraintId);
+ if (!typedConstraint)
+ return;
+
switch (typedConstraint->getUserConstraintType())
{
case PHY_GENERIC_6DOF_CONSTRAINT:
@@ -2164,6 +2215,9 @@ void CcdPhysicsEnvironment::SetConstraintParam(int constraintId,int param,float
btTypedConstraint* CcdPhysicsEnvironment::GetConstraintById(int constraintId)
{
+ // For soft body constraints
+ if (constraintId == 0)
+ return NULL;
int numConstraints = m_dynamicsWorld->getNumConstraints();
int i;
@@ -2181,30 +2235,20 @@ btTypedConstraint* CcdPhysicsEnvironment::GetConstraintById(int constraintId)
void CcdPhysicsEnvironment::AddSensor(PHY_IPhysicsController* ctrl)
{
-
CcdPhysicsController* ctrl1 = (CcdPhysicsController* )ctrl;
- // addSensor() is a "light" function for bullet because it is used
- // dynamically when the sensor is activated. Use enableCcdPhysicsController() instead
- //if (m_controllers.insert(ctrl1).second)
- //{
- // addCcdPhysicsController(ctrl1);
- //}
- EnableCcdPhysicsController(ctrl1);
+ AddCcdPhysicsController(ctrl1);
}
bool CcdPhysicsEnvironment::RemoveCollisionCallback(PHY_IPhysicsController* ctrl)
{
CcdPhysicsController* ccdCtrl = (CcdPhysicsController*)ctrl;
- if (!ccdCtrl->Unregister())
- return false;
- m_triggerControllers.erase(ccdCtrl);
- return true;
+ return ccdCtrl->Unregister();
}
void CcdPhysicsEnvironment::RemoveSensor(PHY_IPhysicsController* ctrl)
{
- DisableCcdPhysicsController((CcdPhysicsController*)ctrl);
+ RemoveCcdPhysicsController((CcdPhysicsController*)ctrl);
}
void CcdPhysicsEnvironment::AddTouchCallback(int response_class, PHY_ResponseCallback callback, void *user)
@@ -2242,73 +2286,83 @@ void CcdPhysicsEnvironment::AddTouchCallback(int response_class, PHY_ResponseCal
bool CcdPhysicsEnvironment::RequestCollisionCallback(PHY_IPhysicsController* ctrl)
{
CcdPhysicsController* ccdCtrl = static_cast<CcdPhysicsController*>(ctrl);
-
- if (!ccdCtrl->Register())
- return false;
- m_triggerControllers.insert(ccdCtrl);
- return true;
+ return ccdCtrl->Register();
}
void CcdPhysicsEnvironment::CallbackTriggers()
{
- if (m_triggerCallbacks[PHY_OBJECT_RESPONSE] || (m_debugDrawer && (m_debugDrawer->getDebugMode() & btIDebugDraw::DBG_DrawContactPoints)))
- {
- //walk over all overlapping pairs, and if one of the involved bodies is registered for trigger callback, perform callback
- btDispatcher* dispatcher = m_dynamicsWorld->getDispatcher();
- int numManifolds = dispatcher->getNumManifolds();
- for (int i=0;i<numManifolds;i++)
- {
- btPersistentManifold* manifold = dispatcher->getManifoldByIndexInternal(i);
- int numContacts = manifold->getNumContacts();
- if (numContacts)
- {
- const btRigidBody* rb0 = static_cast<const btRigidBody*>(manifold->getBody0());
- const btRigidBody* rb1 = static_cast<const btRigidBody*>(manifold->getBody1());
- if (m_debugDrawer && (m_debugDrawer->getDebugMode() & btIDebugDraw::DBG_DrawContactPoints))
- {
- for (int j=0;j<numContacts;j++)
- {
- btVector3 color(1,0,0);
- const btManifoldPoint& cp = manifold->getContactPoint(j);
- if (m_debugDrawer)
- m_debugDrawer->drawContactPoint(cp.m_positionWorldOnB,cp.m_normalWorldOnB,cp.getDistance(),cp.getLifeTime(),color);
- }
- }
- const btRigidBody* obj0 = rb0;
- const btRigidBody* obj1 = rb1;
+ bool draw_contact_points = m_debugDrawer && (m_debugDrawer->getDebugMode() & btIDebugDraw::DBG_DrawContactPoints);
- //m_internalOwner is set in 'addPhysicsController'
- CcdPhysicsController* ctrl0 = static_cast<CcdPhysicsController*>(obj0->getUserPointer());
- CcdPhysicsController* ctrl1 = static_cast<CcdPhysicsController*>(obj1->getUserPointer());
+ if (!m_triggerCallbacks[PHY_OBJECT_RESPONSE] && !draw_contact_points)
+ return;
- std::set<CcdPhysicsController*>::const_iterator i = m_triggerControllers.find(ctrl0);
- if (i == m_triggerControllers.end())
- {
- i = m_triggerControllers.find(ctrl1);
- }
+ //walk over all overlapping pairs, and if one of the involved bodies is registered for trigger callback, perform callback
+ btDispatcher* dispatcher = m_dynamicsWorld->getDispatcher();
+ int numManifolds = dispatcher->getNumManifolds();
+ for (int i=0;i<numManifolds;i++)
+ {
+ bool colliding_ctrl0 = true;
+ btPersistentManifold* manifold = dispatcher->getManifoldByIndexInternal(i);
+ int numContacts = manifold->getNumContacts();
+ if (!numContacts) continue;
- if (!(i == m_triggerControllers.end()))
- {
- m_triggerCallbacks[PHY_OBJECT_RESPONSE](m_triggerCallbacksUserPtrs[PHY_OBJECT_RESPONSE],
- ctrl0,ctrl1,0);
- }
- // Bullet does not refresh the manifold contact point for object without contact response
- // may need to remove this when a newer Bullet version is integrated
- if (!dispatcher->needsResponse(rb0, rb1))
- {
- // Refresh algorithm fails sometimes when there is penetration
- // (usuall the case with ghost and sensor objects)
- // Let's just clear the manifold, in any case, it is recomputed on each frame.
- manifold->clearManifold(); //refreshContactPoints(rb0->getCenterOfMassTransform(),rb1->getCenterOfMassTransform());
- }
+ const btRigidBody* rb0 = static_cast<const btRigidBody*>(manifold->getBody0());
+ const btRigidBody* rb1 = static_cast<const btRigidBody*>(manifold->getBody1());
+ if (draw_contact_points)
+ {
+ for (int j=0;j<numContacts;j++)
+ {
+ btVector3 color(1,1,0);
+ const btManifoldPoint& cp = manifold->getContactPoint(j);
+ m_debugDrawer->drawContactPoint(cp.m_positionWorldOnB,
+ cp.m_normalWorldOnB,
+ cp.getDistance(),
+ cp.getLifeTime(),
+ color);
}
}
+ //m_internalOwner is set in 'addPhysicsController'
+ CcdPhysicsController* ctrl0 = static_cast<CcdPhysicsController*>(rb0->getUserPointer());
+ CcdPhysicsController* ctrl1 = static_cast<CcdPhysicsController*>(rb1->getUserPointer());
+ bool usecallback = false;
+ // Test if one of the controller is registered and use collision callback.
+ if (ctrl0->Registered())
+ usecallback = true;
+ else if (ctrl1->Registered()) {
+ colliding_ctrl0 = false;
+ usecallback = true;
+ }
- }
+ if (usecallback) {
+ static PHY_CollData coll_data;
+ const btManifoldPoint &cp = manifold->getContactPoint(0);
+
+ /* Make sure that "point1" is always on the object we report on, and
+ * "point2" on the other object. Also ensure the normal is oriented
+ * correctly. */
+ btVector3 point1 = colliding_ctrl0 ? cp.m_positionWorldOnA : cp.m_positionWorldOnB;
+ btVector3 point2 = colliding_ctrl0 ? cp.m_positionWorldOnB : cp.m_positionWorldOnA;
+ btVector3 normal = colliding_ctrl0 ? -cp.m_normalWorldOnB : cp.m_normalWorldOnB;
+ coll_data.m_point1 = MT_Vector3(point1.m_floats);
+ coll_data.m_point2 = MT_Vector3(point2.m_floats);
+ coll_data.m_normal = MT_Vector3(normal.m_floats);
+ m_triggerCallbacks[PHY_OBJECT_RESPONSE](m_triggerCallbacksUserPtrs[PHY_OBJECT_RESPONSE],
+ ctrl0, ctrl1, &coll_data);
+ }
+ // Bullet does not refresh the manifold contact point for object without contact response
+ // may need to remove this when a newer Bullet version is integrated
+ if (!dispatcher->needsResponse(rb0, rb1))
+ {
+ // Refresh algorithm fails sometimes when there is penetration
+ // (usuall the case with ghost and sensor objects)
+ // Let's just clear the manifold, in any case, it is recomputed on each frame.
+ manifold->clearManifold(); //refreshContactPoints(rb0->getCenterOfMassTransform(),rb1->getCenterOfMassTransform());
+ }
+ }
}
// This call back is called before a pair is added in the cache
@@ -2624,7 +2678,6 @@ int CcdPhysicsEnvironment::CreateConstraint(class PHY_IPhysicsController* ctrl
if (!rb0)
return 0;
-
btVector3 pivotInB = rb1 ? rb1->getCenterOfMassTransform().inverse()(rb0->getCenterOfMassTransform()(pivotInA)) :
rb0->getCenterOfMassTransform() * pivotInA;
btVector3 axisInA(axisX,axisY,axisZ);
@@ -2636,6 +2689,8 @@ int CcdPhysicsEnvironment::CreateConstraint(class PHY_IPhysicsController* ctrl
{
case PHY_POINT2POINT_CONSTRAINT:
{
+ // If either of the controllers is missing, we can't do anything.
+ if (!c0 || !c1) return 0;
btPoint2PointConstraint* p2p = 0;
@@ -2649,6 +2704,8 @@ int CcdPhysicsEnvironment::CreateConstraint(class PHY_IPhysicsController* ctrl
pivotInA);
}
+ c0->addCcdConstraintRef(p2p);
+ c1->addCcdConstraintRef(p2p);
m_dynamicsWorld->addConstraint(p2p,disableCollisionBetweenLinkedBodies);
// m_constraints.push_back(p2p);
@@ -2662,6 +2719,9 @@ int CcdPhysicsEnvironment::CreateConstraint(class PHY_IPhysicsController* ctrl
case PHY_GENERIC_6DOF_CONSTRAINT:
{
+ // If either of the controllers is missing, we can't do anything.
+ if (!c0 || !c1) return 0;
+
btGeneric6DofConstraint* genericConstraint = 0;
if (rb1)
@@ -2715,10 +2775,12 @@ int CcdPhysicsEnvironment::CreateConstraint(class PHY_IPhysicsController* ctrl
*rb0,s_fixedObject2,
frameInA,frameInB,useReferenceFrameA);
}
-
+
if (genericConstraint)
{
//m_constraints.push_back(genericConstraint);
+ c0->addCcdConstraintRef(genericConstraint);
+ c1->addCcdConstraintRef(genericConstraint);
m_dynamicsWorld->addConstraint(genericConstraint,disableCollisionBetweenLinkedBodies);
genericConstraint->setUserConstraintId(gConstraintUid++);
genericConstraint->setUserConstraintType(type);
@@ -2730,6 +2792,9 @@ int CcdPhysicsEnvironment::CreateConstraint(class PHY_IPhysicsController* ctrl
}
case PHY_CONE_TWIST_CONSTRAINT:
{
+ // If either of the controllers is missing, we can't do anything.
+ if (!c0 || !c1) return 0;
+
btConeTwistConstraint* coneTwistContraint = 0;
@@ -2781,10 +2846,12 @@ int CcdPhysicsEnvironment::CreateConstraint(class PHY_IPhysicsController* ctrl
*rb0,s_fixedObject2,
frameInA,frameInB);
}
-
+
if (coneTwistContraint)
{
//m_constraints.push_back(genericConstraint);
+ c0->addCcdConstraintRef(coneTwistContraint);
+ c1->addCcdConstraintRef(coneTwistContraint);
m_dynamicsWorld->addConstraint(coneTwistContraint,disableCollisionBetweenLinkedBodies);
coneTwistContraint->setUserConstraintId(gConstraintUid++);
coneTwistContraint->setUserConstraintType(type);
@@ -2802,6 +2869,9 @@ int CcdPhysicsEnvironment::CreateConstraint(class PHY_IPhysicsController* ctrl
case PHY_LINEHINGE_CONSTRAINT:
{
+ // If either of the controllers is missing, we can't do anything.
+ if (!c0 || !c1) return 0;
+
btHingeConstraint* hinge = 0;
if (rb1)
@@ -2858,6 +2928,8 @@ int CcdPhysicsEnvironment::CreateConstraint(class PHY_IPhysicsController* ctrl
hinge->setAngularOnly(angularOnly);
//m_constraints.push_back(hinge);
+ c0->addCcdConstraintRef(hinge);
+ c1->addCcdConstraintRef(hinge);
m_dynamicsWorld->addConstraint(hinge,disableCollisionBetweenLinkedBodies);
hinge->setUserConstraintId(gConstraintUid++);
hinge->setUserConstraintType(type);
@@ -2926,6 +2998,10 @@ PHY_IPhysicsController* CcdPhysicsEnvironment::CreateConeController(float conera
float CcdPhysicsEnvironment::getAppliedImpulse(int constraintid)
{
+ // For soft body constraints
+ if (constraintid == 0)
+ return 0.0f;
+
int i;
int numConstraints = m_dynamicsWorld->getNumConstraints();
for (i=0;i<numConstraints;i++)
@@ -2999,7 +3075,8 @@ struct BlenderDebugDraw : public btIDebugDraw
virtual void drawContactPoint(const btVector3& PointOnB,const btVector3& normalOnB,float distance,int lifeTime,const btVector3& color)
{
- //not yet
+ drawLine(PointOnB, PointOnB + normalOnB, color);
+ drawSphere(PointOnB, 0.1, color);
}
virtual void setDebugMode(int debugMode)
@@ -3036,7 +3113,7 @@ void CcdPhysicsEnvironment::ConvertObject(KX_GameObject *gameobj, RAS_MeshObject
{
Object* blenderobject = gameobj->GetBlenderObject();
- bool isbulletdyna = (blenderobject->gameflag & OB_DYNAMIC) != 0;;
+ bool isbulletdyna = (blenderobject->gameflag & OB_DYNAMIC) != 0;
bool isbulletsensor = (blenderobject->gameflag & OB_SENSOR) != 0;
bool isbulletchar = (blenderobject->gameflag & OB_CHARACTER) != 0;
bool isbulletsoftbody = (blenderobject->gameflag & OB_SOFT_BODY) != 0;
@@ -3056,9 +3133,7 @@ void CcdPhysicsEnvironment::ConvertObject(KX_GameObject *gameobj, RAS_MeshObject
{
KX_BlenderSceneConverter *converter = (KX_BlenderSceneConverter*)KX_GetActiveEngine()->GetSceneConverter();
parent = converter->FindGameObject(blenderparent);
- isbulletdyna = false;
isbulletsoftbody = false;
- shapeprops->m_mass = 0.f;
}
if (!isbulletdyna)
@@ -3082,6 +3157,8 @@ void CcdPhysicsEnvironment::ConvertObject(KX_GameObject *gameobj, RAS_MeshObject
ci.m_mass = isbulletdyna ? shapeprops->m_mass : 0.f;
ci.m_clamp_vel_min = shapeprops->m_clamp_vel_min;
ci.m_clamp_vel_max = shapeprops->m_clamp_vel_max;
+ ci.m_clamp_angvel_min = shapeprops->m_clamp_angvel_min;
+ ci.m_clamp_angvel_max = shapeprops->m_clamp_angvel_max;
ci.m_stepHeight = isbulletchar ? shapeprops->m_step_height : 0.f;
ci.m_jumpSpeed = isbulletchar ? shapeprops->m_jump_speed : 0.f;
ci.m_fallSpeed = isbulletchar ? shapeprops->m_fall_speed : 0.f;
@@ -3339,46 +3416,50 @@ void CcdPhysicsEnvironment::ConvertObject(KX_GameObject *gameobj, RAS_MeshObject
//take relative transform into account!
CcdPhysicsController* parentCtrl = (CcdPhysicsController*)parent->GetPhysicsController();
assert(parentCtrl);
- CcdShapeConstructionInfo* parentShapeInfo = parentCtrl->GetShapeInfo();
- btRigidBody* rigidbody = parentCtrl->GetRigidBody();
- btCollisionShape* colShape = rigidbody->getCollisionShape();
- assert(colShape->isCompound());
- btCompoundShape* compoundShape = (btCompoundShape*)colShape;
-
- // compute the local transform from parent, this may include several node in the chain
- SG_Node* gameNode = gameobj->GetSGNode();
- SG_Node* parentNode = parent->GetSGNode();
- // relative transform
- MT_Vector3 parentScale = parentNode->GetWorldScaling();
- parentScale[0] = MT_Scalar(1.0)/parentScale[0];
- parentScale[1] = MT_Scalar(1.0)/parentScale[1];
- parentScale[2] = MT_Scalar(1.0)/parentScale[2];
- MT_Vector3 relativeScale = gameNode->GetWorldScaling() * parentScale;
- MT_Matrix3x3 parentInvRot = parentNode->GetWorldOrientation().transposed();
- MT_Vector3 relativePos = parentInvRot*((gameNode->GetWorldPosition()-parentNode->GetWorldPosition())*parentScale);
- MT_Matrix3x3 relativeRot = parentInvRot*gameNode->GetWorldOrientation();
-
- shapeInfo->m_childScale.setValue(relativeScale[0],relativeScale[1],relativeScale[2]);
- bm->setLocalScaling(shapeInfo->m_childScale);
- shapeInfo->m_childTrans.getOrigin().setValue(relativePos[0],relativePos[1],relativePos[2]);
- float rot[12];
- relativeRot.getValue(rot);
- shapeInfo->m_childTrans.getBasis().setFromOpenGLSubMatrix(rot);
-
- parentShapeInfo->AddShape(shapeInfo);
- compoundShape->addChildShape(shapeInfo->m_childTrans,bm);
- //do some recalc?
- //recalc inertia for rigidbody
- if (!rigidbody->isStaticOrKinematicObject())
- {
- btVector3 localInertia;
- float mass = 1.f/rigidbody->getInvMass();
- compoundShape->calculateLocalInertia(mass,localInertia);
- rigidbody->setMassProps(mass,localInertia);
+
+ // only makes compound shape if parent has a physics controller (i.e not an empty, etc)
+ if (parentCtrl) {
+ CcdShapeConstructionInfo* parentShapeInfo = parentCtrl->GetShapeInfo();
+ btRigidBody* rigidbody = parentCtrl->GetRigidBody();
+ btCollisionShape* colShape = rigidbody->getCollisionShape();
+ assert(colShape->isCompound());
+ btCompoundShape* compoundShape = (btCompoundShape*)colShape;
+
+ // compute the local transform from parent, this may include several node in the chain
+ SG_Node* gameNode = gameobj->GetSGNode();
+ SG_Node* parentNode = parent->GetSGNode();
+ // relative transform
+ MT_Vector3 parentScale = parentNode->GetWorldScaling();
+ parentScale[0] = MT_Scalar(1.0)/parentScale[0];
+ parentScale[1] = MT_Scalar(1.0)/parentScale[1];
+ parentScale[2] = MT_Scalar(1.0)/parentScale[2];
+ MT_Vector3 relativeScale = gameNode->GetWorldScaling() * parentScale;
+ MT_Matrix3x3 parentInvRot = parentNode->GetWorldOrientation().transposed();
+ MT_Vector3 relativePos = parentInvRot*((gameNode->GetWorldPosition()-parentNode->GetWorldPosition())*parentScale);
+ MT_Matrix3x3 relativeRot = parentInvRot*gameNode->GetWorldOrientation();
+
+ shapeInfo->m_childScale.setValue(relativeScale[0],relativeScale[1],relativeScale[2]);
+ bm->setLocalScaling(shapeInfo->m_childScale);
+ shapeInfo->m_childTrans.getOrigin().setValue(relativePos[0],relativePos[1],relativePos[2]);
+ float rot[12];
+ relativeRot.getValue(rot);
+ shapeInfo->m_childTrans.getBasis().setFromOpenGLSubMatrix(rot);
+
+ parentShapeInfo->AddShape(shapeInfo);
+ compoundShape->addChildShape(shapeInfo->m_childTrans,bm);
+ //do some recalc?
+ //recalc inertia for rigidbody
+ if (!rigidbody->isStaticOrKinematicObject())
+ {
+ btVector3 localInertia;
+ float mass = 1.f/rigidbody->getInvMass();
+ compoundShape->calculateLocalInertia(mass,localInertia);
+ rigidbody->setMassProps(mass,localInertia);
+ }
+ shapeInfo->Release();
+ // delete motionstate as it's not used
+ delete motionstate;
}
- shapeInfo->Release();
- // delete motionstate as it's not used
- delete motionstate;
return;
}
@@ -3482,20 +3563,23 @@ void CcdPhysicsEnvironment::ConvertObject(KX_GameObject *gameobj, RAS_MeshObject
if (isbulletdyna)
gameobj->SetRecordAnimation(true);
+ physicscontroller->SetNewClientInfo(gameobj->getClientInfo());
+
// don't add automatically sensor object, they are added when a collision sensor is registered
if (!isbulletsensor && (blenderobject->lay & activeLayerBitInfo) != 0)
{
this->AddCcdPhysicsController( physicscontroller);
}
- physicscontroller->SetNewClientInfo(gameobj->getClientInfo());
+
{
btRigidBody* rbody = physicscontroller->GetRigidBody();
if (rbody)
{
+ rbody->setLinearFactor(ci.m_linearFactor);
+
if (isbulletrigidbody)
{
- rbody->setLinearFactor(ci.m_linearFactor);
rbody->setAngularFactor(ci.m_angularFactor);
}
@@ -3506,6 +3590,9 @@ void CcdPhysicsEnvironment::ConvertObject(KX_GameObject *gameobj, RAS_MeshObject
}
}
+ if (parent)
+ physicscontroller->SuspendDynamics(false);
+
CcdPhysicsController* parentCtrl = parent ? (CcdPhysicsController*)parent->GetPhysicsController() : 0;
physicscontroller->SetParentCtrl(parentCtrl);
@@ -3556,3 +3643,79 @@ void CcdPhysicsEnvironment::ConvertObject(KX_GameObject *gameobj, RAS_MeshObject
}
#endif
}
+
+
+void CcdPhysicsEnvironment::SetupObjectConstraints(KX_GameObject *obj_src, KX_GameObject *obj_dest,
+ bRigidBodyJointConstraint *dat)
+{
+ PHY_IPhysicsController *phy_src = obj_src->GetPhysicsController();
+ PHY_IPhysicsController *phy_dest = obj_dest->GetPhysicsController();
+ PHY_IPhysicsEnvironment *phys_env = obj_src->GetScene()->GetPhysicsEnvironment();
+
+ /* We need to pass a full constraint frame, not just axis. */
+ MT_Matrix3x3 localCFrame(MT_Vector3(dat->axX,dat->axY,dat->axZ));
+ MT_Vector3 axis0 = localCFrame.getColumn(0);
+ MT_Vector3 axis1 = localCFrame.getColumn(1);
+ MT_Vector3 axis2 = localCFrame.getColumn(2);
+ MT_Vector3 scale = obj_src->NodeGetWorldScaling();
+
+ /* Apply not only the pivot and axis values, but also take scale into count
+ * this is not working well, if only one or two axis are scaled, but works ok on
+ * homogeneous scaling. */
+ int constraintId = phys_env->CreateConstraint(
+ phy_src, phy_dest, (PHY_ConstraintType)dat->type,
+ (float)(dat->pivX * scale.x()), (float)(dat->pivY * scale.y()), (float)(dat->pivZ * scale.z()),
+ (float)(axis0.x() * scale.x()), (float)(axis0.y() * scale.y()), (float)(axis0.z() * scale.z()),
+ (float)(axis1.x() * scale.x()), (float)(axis1.y() * scale.y()), (float)(axis1.z() * scale.z()),
+ (float)(axis2.x() * scale.x()), (float)(axis2.y() * scale.y()), (float)(axis2.z() * scale.z()),
+ dat->flag);
+
+ /* PHY_POINT2POINT_CONSTRAINT = 1,
+ * PHY_LINEHINGE_CONSTRAINT = 2,
+ * PHY_ANGULAR_CONSTRAINT = 3,
+ * PHY_CONE_TWIST_CONSTRAINT = 4,
+ * PHY_VEHICLE_CONSTRAINT = 11,
+ * PHY_GENERIC_6DOF_CONSTRAINT = 12 */
+
+ if (!constraintId)
+ return;
+
+ int dof = 0;
+ int dof_max = 0;
+ int dofbit = 0;
+
+ switch (dat->type) {
+ /* Set all the limits for generic 6DOF constraint. */
+ case PHY_GENERIC_6DOF_CONSTRAINT:
+ dof_max = 6;
+ dofbit = 1;
+ break;
+ /* Set XYZ angular limits for cone twist constraint. */
+ case PHY_CONE_TWIST_CONSTRAINT:
+ dof = 3;
+ dof_max = 6;
+ dofbit = 1 << 3;
+ break;
+ /* Set only X angular limits for line hinge and angular constraint. */
+ case PHY_LINEHINGE_CONSTRAINT:
+ case PHY_ANGULAR_CONSTRAINT:
+ dof = 3;
+ dof_max = 4;
+ dofbit = 1 << 3;
+ break;
+ default:
+ break;
+ }
+
+ for (; dof < dof_max; dof++) {
+ if (dat->flag & dofbit) {
+ phys_env->SetConstraintParam(constraintId, dof, dat->minLimit[dof], dat->maxLimit[dof]);
+ }
+ else {
+ /* minLimit > maxLimit means free (no limit) for this degree of freedom. */
+ phys_env->SetConstraintParam(constraintId, dof, 1.0f, -1.0f);
+ }
+ dofbit <<= 1;
+ }
+
+}
diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h
index ff8a3f4f9f9..86f663959f1 100644
--- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h
+++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h
@@ -22,6 +22,8 @@ subject to the following restrictions:
#define __CCDPHYSICSENVIRONMENT_H__
#include "PHY_IPhysicsEnvironment.h"
+#include "KX_KetsjiEngine.h"
+
#include <vector>
#include <set>
#include <map>
@@ -50,8 +52,10 @@ class btBroadphaseInterface;
struct btDbvtBroadphase;
class btOverlappingPairCache;
class btIDebugDraw;
+class btDynamicsWorld;
class PHY_IVehicle;
class CcdOverlapFilterCallBack;
+class CcdShapeConstructionInfo;
/** CcdPhysicsEnvironment is an experimental mainloop for physics simulation using optional continuous collision detection.
* Physics Environment takes care of stepping the simulation and is a container for physics entities.
@@ -63,6 +67,9 @@ class CcdPhysicsEnvironment : public PHY_IPhysicsEnvironment
friend class CcdOverlapFilterCallBack;
btVector3 m_gravity;
+ // Removes the constraint and his references from the owner and the target.
+ void RemoveConstraint(btTypedConstraint *con);
+
protected:
btIDebugDraw* m_debugDrawer;
@@ -84,6 +91,11 @@ protected:
int m_profileTimings;
bool m_enableSatCollisionDetection;
+ float m_deactivationTime;
+ float m_linearDeactivationThreshold;
+ float m_angularDeactivationThreshold;
+ float m_contactBreakingThreshold;
+
void ProcessFhSprings(double curTime,float timeStep);
public:
@@ -126,13 +138,20 @@ protected:
/// Perform an integration step of duration 'timeStep'.
virtual bool ProceedDeltaTime(double curTime,float timeStep,float interval);
+ /**
+ * Called by Bullet for every physical simulation (sub)tick.
+ * Our constructor registers this callback to Bullet, which stores a pointer to 'this' in
+ * the btDynamicsWorld::getWorldUserInfo() pointer.
+ */
+ static void StaticSimulationSubtickCallback(btDynamicsWorld *world, btScalar timeStep);
+ void SimulationSubtickCallback(btScalar timeStep);
+
virtual void DebugDrawWorld();
// virtual bool proceedDeltaTimeOneStep(float timeStep);
virtual void SetFixedTimeStep(bool useFixedTimeStep,float fixedTimeStep)
{
- //based on DEFAULT_PHYSICS_TIC_RATE of 60 hertz
- SetNumTimeSubSteps((int)(fixedTimeStep / 60.f));
+ SetNumTimeSubSteps((int)(fixedTimeStep / KX_KetsjiEngine::GetTicRate()));
}
//returns 0.f if no fixed timestep is used
@@ -169,7 +188,7 @@ protected:
virtual float GetConstraintParam(int constraintId,int param);
- virtual void RemoveConstraint(int constraintid);
+ virtual void RemoveConstraintById(int constraintid);
virtual float getAppliedImpulse(int constraintid);
@@ -220,16 +239,22 @@ protected:
void UpdateCcdPhysicsController(CcdPhysicsController* ctrl, btScalar newMass, int newCollisionFlags, short int newCollisionGroup, short int newCollisionMask);
- void DisableCcdPhysicsController(CcdPhysicsController* ctrl);
-
- void EnableCcdPhysicsController(CcdPhysicsController* ctrl);
-
void RefreshCcdPhysicsController(CcdPhysicsController* ctrl);
+ bool IsActiveCcdPhysicsController(CcdPhysicsController *ctrl);
+
void AddCcdGraphicController(CcdGraphicController* ctrl);
void RemoveCcdGraphicController(CcdGraphicController* ctrl);
+ /**
+ * Update all physics controllers shape which use the same shape construction info.
+ * Call RecreateControllerShape on controllers which use the same shape
+ * construction info that argument shapeInfo.
+ * You need to call this function when the shape construction info changed.
+ */
+ void UpdateCcdPhysicsControllerShape(CcdShapeConstructionInfo *shapeInfo);
+
btBroadphaseInterface* GetBroadphase();
btDbvtBroadphase* GetCullingTree() { return m_cullingTree; }
@@ -274,12 +299,15 @@ protected:
bool isCompoundChild,
bool hasCompoundChildren);
+ /* Set the rigid body joints constraints values for converted objects and replicated group instances. */
+ virtual void SetupObjectConstraints(KX_GameObject *obj_src, KX_GameObject *obj_dest,
+ bRigidBodyJointConstraint *dat);
+
protected:
std::set<CcdPhysicsController*> m_controllers;
- std::set<CcdPhysicsController*> m_triggerControllers;
PHY_ResponseCallback m_triggerCallbacks[PHY_NUM_RESPONSE];
void* m_triggerCallbacksUserPtrs[PHY_NUM_RESPONSE];
diff --git a/source/gameengine/Physics/Bullet/SConscript b/source/gameengine/Physics/Bullet/SConscript
index 2a8249b9558..5c5b1fe6ea6 100644
--- a/source/gameengine/Physics/Bullet/SConscript
+++ b/source/gameengine/Physics/Bullet/SConscript
@@ -34,7 +34,8 @@ incs = [
'#intern/container',
'#intern/guardedalloc',
'#intern/string',
- '#extern/glew/include',
+ env['BF_GLEW_INC'],
+ '#/intern/glew-mx',
'#intern/moto/include',
'#source/blender/blenkernel',
'#source/blender/blenlib',
@@ -52,6 +53,7 @@ incs = ' '.join(incs)
incs += ' ' + env['BF_BULLET_INC']
defs = []
+defs += env['BF_GL_DEFINITIONS']
if env['WITH_BF_PYTHON']:
incs += ' ' + env['BF_PYTHON_INC']
diff --git a/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.cpp b/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.cpp
index 979128370ee..99db56bfcef 100644
--- a/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.cpp
+++ b/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.cpp
@@ -106,7 +106,7 @@ int DummyPhysicsEnvironment::CreateConstraint(class PHY_IPhysicsController* ct
}
-void DummyPhysicsEnvironment::RemoveConstraint(int constraintid)
+void DummyPhysicsEnvironment::RemoveConstraintById(int constraintid)
{
if (constraintid)
{
diff --git a/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h b/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h
index cfc8841cac2..929345d7161 100644
--- a/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h
+++ b/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h
@@ -68,7 +68,7 @@ public:
float axis2X=0,float axis2Y=0,float axis2Z=0,int flag=0
);
- virtual void RemoveConstraint(int constraintid);
+ virtual void RemoveConstraintById(int constraintid);
//complex constraint for vehicles
virtual PHY_IVehicle* GetVehicleConstraint(int constraintId)
diff --git a/source/gameengine/Physics/common/PHY_IPhysicsController.h b/source/gameengine/Physics/common/PHY_IPhysicsController.h
index f9975484fa7..62b163536dd 100644
--- a/source/gameengine/Physics/common/PHY_IPhysicsController.h
+++ b/source/gameengine/Physics/common/PHY_IPhysicsController.h
@@ -32,6 +32,7 @@
#ifndef __PHY_IPHYSICSCONTROLLER_H__
#define __PHY_IPHYSICSCONTROLLER_H__
+#include <vector>
#include "PHY_IController.h"
class PHY_IMotionState;
@@ -89,6 +90,13 @@ class PHY_IPhysicsController : public PHY_IController
virtual void SetLinearVelocity(const MT_Vector3& lin_vel,bool local)=0;
virtual void ResolveCombinedVelocities(float linvelX,float linvelY,float linvelZ,float angVelX,float angVelY,float angVelZ) = 0;
+ virtual float GetLinearDamping() const=0;
+ virtual float GetAngularDamping() const=0;
+ virtual void SetLinearDamping(float damping)=0;
+ virtual void SetAngularDamping(float damping)=0;
+ virtual void SetDamping(float linear, float angular)=0;
+
+ virtual void RefreshCollisions() = 0;
virtual void SuspendDynamics(bool ghost=false)=0;
virtual void RestoreDynamics()=0;
@@ -117,6 +125,11 @@ class PHY_IPhysicsController : public PHY_IController
virtual float GetLinVelocityMax() const=0;
virtual void SetLinVelocityMax(float val) = 0;
+ virtual void SetAngularVelocityMin(float val) = 0;
+ virtual float GetAngularVelocityMin() const = 0;
+ virtual void SetAngularVelocityMax(float val) = 0;
+ virtual float GetAngularVelocityMax() const = 0;
+
MT_Vector3 GetWorldPosition(MT_Vector3& localpos);
// Shape control
@@ -126,9 +139,12 @@ class PHY_IPhysicsController : public PHY_IController
virtual bool IsDynamic() = 0;
virtual bool IsCompound() = 0;
+ virtual bool IsSuspended() const = 0;
virtual bool ReinstancePhysicsShape(KX_GameObject *from_gameobj, RAS_MeshObject* from_meshobj) = 0;
+ /* Method to replicate rigid body joint contraints for group instances. */
+ virtual void ReplicateConstraints(KX_GameObject *gameobj, std::vector<KX_GameObject*> constobj) = 0;
#ifdef WITH_CXX_GUARDEDALLOC
MEM_CXX_CLASS_ALLOC_FUNCS("GE:PHY_IPhysicsController")
diff --git a/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h b/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h
index dd762b02b4e..4b8d36285be 100644
--- a/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h
+++ b/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h
@@ -55,6 +55,7 @@ class KX_Scene;
struct PHY_ShapeProps;
struct PHY_MaterialProps;
class PHY_IMotionState;
+struct bRigidBodyJointConstraint;
/**
* pass back information from rayTest
@@ -167,7 +168,7 @@ class PHY_IPhysicsEnvironment
float axis1X=0,float axis1Y=0,float axis1Z=0,
float axis2X=0,float axis2Y=0,float axis2Z=0,int flag=0
)=0;
- virtual void RemoveConstraint(int constraintid)=0;
+ virtual void RemoveConstraintById(int constraintid) = 0;
virtual float GetAppliedImpulse(int constraintid) { return 0.0f; }
@@ -213,6 +214,9 @@ class PHY_IPhysicsEnvironment
bool isCompoundChild,
bool hasCompoundChildren) = 0;
+ /* Set the rigid body joints constraints values for converted objects and replicated group instances. */
+ virtual void SetupObjectConstraints(KX_GameObject *obj_src, KX_GameObject *obj_dest,
+ bRigidBodyJointConstraint *dat) {}
#ifdef WITH_CXX_GUARDEDALLOC
MEM_CXX_CLASS_ALLOC_FUNCS("GE:PHY_IPhysicsEnvironment")
diff --git a/source/gameengine/Physics/common/PHY_Pro.h b/source/gameengine/Physics/common/PHY_Pro.h
index 7c5d9c9638e..c9b91b06a3c 100644
--- a/source/gameengine/Physics/common/PHY_Pro.h
+++ b/source/gameengine/Physics/common/PHY_Pro.h
@@ -43,6 +43,8 @@ struct PHY_ShapeProps {
MT_Scalar m_friction_scaling[3]; // Scaling for anisotropic friction. Component in range [0, 1]
MT_Scalar m_clamp_vel_min; // Clamp the minimum velocity, this ensures an object moves at a minimum speed unless its stationary
MT_Scalar m_clamp_vel_max; // Clamp max velocity
+ MT_Scalar m_clamp_angvel_min; // Clamp the minimum angular velocity.
+ MT_Scalar m_clamp_angvel_max; // Clamp the maximum angular velocity.
bool m_do_anisotropic; // Should I do anisotropic friction?
bool m_do_fh; // Should the object have a linear Fh spring?
bool m_do_rot_fh; // Should the object have an angular Fh spring?