From 00836b4e3454f45e34decbaed00f7cde4445ec1e Mon Sep 17 00:00:00 2001 From: Porteries Tristan Date: Thu, 27 Apr 2017 21:56:37 +0200 Subject: [PATCH] UPBGE: Fix removed constraints when suspending physics. Previously when we was suspending physics of an object using constraints, they were removed. This behaviour could be needed in some rare case but for the most case where the user just want to optimize physics computation the engine should keep the constraints. To do so the constraints have to be removed from the dynamic world but not removed from the controller or deleted in RemoveCcdPhysicsController. In the same time AddCcdPhysicsController iterate over all the constraint in the activated controller and add they in the dynamic world. Unfortunately there's some limitation, first we could not do redundant operation in removing and adding of the constraint in the world, second we have to keep the disable collision between bodies flag used when adding a constraint into world. To solve both of these issues the user pointer of the constraint are used to store a new type: CcdConstraint (in CcdPhysicsController). This new type only store the disable collision flag and a boolean named m_active set to true when the constraint is added in world else to false when removed. Two functions are added to clean the code: RemoveConstraint and RestoreConstraint. On python API side the user could specify to remove or not the constraints when calling KX_GameObject.suspendPhysics(freeConstraints=False). --- .../rst/bge_types/bge.types.KX_GameObject.rst | 6 +- source/gameengine/Ketsji/KX_GameObject.cpp | 12 +- source/gameengine/Ketsji/KX_GameObject.h | 2 +- .../Ketsji/KX_PyConstraintBinding.cpp | 2 +- .../Ketsji/KX_SCA_DynamicActuator.cpp | 2 +- .../Physics/Bullet/CcdPhysicsController.cpp | 17 +- .../Physics/Bullet/CcdPhysicsController.h | 13 +- .../Physics/Bullet/CcdPhysicsEnvironment.cpp | 219 ++++++++---------- .../Physics/Bullet/CcdPhysicsEnvironment.h | 21 +- .../Physics/Common/PHY_IPhysicsController.h | 2 +- .../Physics/Common/PHY_IPhysicsEnvironment.h | 2 +- .../Physics/Dummy/DummyPhysicsEnvironment.cpp | 2 +- .../Physics/Dummy/DummyPhysicsEnvironment.h | 2 +- source/tools | 2 +- 14 files changed, 146 insertions(+), 158 deletions(-) diff --git a/doc/python_api/rst/bge_types/bge.types.KX_GameObject.rst b/doc/python_api/rst/bge_types/bge.types.KX_GameObject.rst index 451cbe612616..fe93b76adb55 100644 --- a/doc/python_api/rst/bge_types/bge.types.KX_GameObject.rst +++ b/doc/python_api/rst/bge_types/bge.types.KX_GameObject.rst @@ -741,10 +741,14 @@ base class --- :class:`SCA_IObject` :arg angular_damping: Angular ("rotational") damping factor. :type angular_damping: float ∈ [0, 1] - .. method:: suspendPhysics() + .. method:: suspendPhysics([freeConstraints]) Suspends physics for this object. + :arg freeConstraints: When set to `True` physics constraints used by the object are deleted. + Else when `False` (the default) constraints are restored when restoring physics. + :type freeConstraints: bool + .. method:: restorePhysics() Resumes physics for this object. Also reinstates collisions. diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp index 9be383b4c578..9cab4999be5c 100644 --- a/source/gameengine/Ketsji/KX_GameObject.cpp +++ b/source/gameengine/Ketsji/KX_GameObject.cpp @@ -1911,7 +1911,7 @@ PyMethodDef KX_GameObject::Methods[] = { {"getReactionForce", (PyCFunction) KX_GameObject::sPyGetReactionForce, METH_NOARGS}, {"alignAxisToVect",(PyCFunction) KX_GameObject::sPyAlignAxisToVect, METH_VARARGS}, {"getAxisVect",(PyCFunction) KX_GameObject::sPyGetAxisVect, METH_O}, - {"suspendPhysics", (PyCFunction)KX_GameObject::sPySuspendPhysics, METH_NOARGS}, + {"suspendPhysics", (PyCFunction)KX_GameObject::sPySuspendPhysics, METH_VARARGS}, {"restorePhysics", (PyCFunction)KX_GameObject::sPyRestorePhysics,METH_NOARGS}, {"suspendDynamics", (PyCFunction)KX_GameObject::sPySuspendDynamics, METH_VARARGS}, {"restoreDynamics", (PyCFunction)KX_GameObject::sPyRestoreDynamics,METH_NOARGS}, @@ -3561,10 +3561,16 @@ PyObject *KX_GameObject::PyApplyImpulse(PyObject *args) return nullptr; } -PyObject *KX_GameObject::PySuspendPhysics() +PyObject *KX_GameObject::PySuspendPhysics(PyObject *args) { + int freeConstraints = false; + + if (!PyArg_ParseTuple(args, "|i:suspendPhysics", &freeConstraints)) { + return nullptr; + } + if (GetPhysicsController()) { - GetPhysicsController()->SuspendPhysics(); + GetPhysicsController()->SuspendPhysics((bool)freeConstraints); } Py_RETURN_NONE; } diff --git a/source/gameengine/Ketsji/KX_GameObject.h b/source/gameengine/Ketsji/KX_GameObject.h index 75561b963733..f2b2729d30a3 100644 --- a/source/gameengine/Ketsji/KX_GameObject.h +++ b/source/gameengine/Ketsji/KX_GameObject.h @@ -952,7 +952,7 @@ class KX_GameObject : public SCA_IObject KX_PYMETHOD_O(KX_GameObject,SetState); KX_PYMETHOD_VARARGS(KX_GameObject,AlignAxisToVect); KX_PYMETHOD_O(KX_GameObject,GetAxisVect); - KX_PYMETHOD_NOARGS(KX_GameObject,SuspendPhysics); + KX_PYMETHOD_VARARGS(KX_GameObject,SuspendPhysics); KX_PYMETHOD_NOARGS(KX_GameObject,RestorePhysics); KX_PYMETHOD_VARARGS(KX_GameObject,SuspendDynamics); KX_PYMETHOD_NOARGS(KX_GameObject,RestoreDynamics); diff --git a/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp b/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp index 23d4ed2a0659..aa5998e7025e 100644 --- a/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp +++ b/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp @@ -584,7 +584,7 @@ static PyObject *gPyRemoveConstraint(PyObject *self, { if (PHY_GetActiveEnvironment()) { - PHY_GetActiveEnvironment()->RemoveConstraintById(constraintid); + PHY_GetActiveEnvironment()->RemoveConstraintById(constraintid, true); } } else { diff --git a/source/gameengine/Ketsji/KX_SCA_DynamicActuator.cpp b/source/gameengine/Ketsji/KX_SCA_DynamicActuator.cpp index c97263ef976f..76859f77eb36 100644 --- a/source/gameengine/Ketsji/KX_SCA_DynamicActuator.cpp +++ b/source/gameengine/Ketsji/KX_SCA_DynamicActuator.cpp @@ -144,7 +144,7 @@ bool KX_SCA_DynamicActuator::Update() } case KX_DYN_DISABLE_PHYSICS: { - controller->SuspendPhysics(); + controller->SuspendPhysics(false); break; } } diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp index c0dfc5403e01..94981d4b2e40 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp @@ -231,6 +231,13 @@ class BlenderBulletMotionState : public btMotionState } }; +CcdPhysicsController::CcdConstraint::CcdConstraint(bool disableCollision) + :m_disableCollision(disableCollision), + m_active(false) +{ +} + + btRigidBody *CcdPhysicsController::GetRigidBody() { return btRigidBody::upcast(m_object); @@ -650,7 +657,7 @@ CcdPhysicsController::~CcdPhysicsController() { //will be reference counted, due to sharing if (m_cci.m_physicsEnv) - m_cci.m_physicsEnv->RemoveCcdPhysicsController(this); + m_cci.m_physicsEnv->RemoveCcdPhysicsController(this, true); if (m_MotionState) delete m_MotionState; @@ -833,7 +840,7 @@ void CcdPhysicsController::SetPhysicsEnvironment(class PHY_IPhysicsEnvironment * // since the environment is changing, we must also move the controler to the // new environment. Note that we don't handle sensor explicitly: this // function can be called on sensor but only when they are not registered - if (m_cci.m_physicsEnv->RemoveCcdPhysicsController(this)) + if (m_cci.m_physicsEnv->RemoveCcdPhysicsController(this, true)) { physicsEnv->AddCcdPhysicsController(this); @@ -1015,9 +1022,9 @@ void CcdPhysicsController::RefreshCollisions() GetPhysicsEnvironment()->UpdateCcdPhysicsController(this, GetMass(), m_object->getCollisionFlags(), handle->m_collisionFilterGroup, handle->m_collisionFilterMask); } -void CcdPhysicsController::SuspendPhysics() +void CcdPhysicsController::SuspendPhysics(bool freeConstraints) { - GetPhysicsEnvironment()->RemoveCcdPhysicsController(this); + GetPhysicsEnvironment()->RemoveCcdPhysicsController(this, freeConstraints); } void CcdPhysicsController::RestorePhysics() @@ -1508,7 +1515,7 @@ void CcdPhysicsController::AddCompoundChild(PHY_IPhysicsController *child) // must update the broadphase cache, GetPhysicsEnvironment()->RefreshCcdPhysicsController(this); // remove the children - GetPhysicsEnvironment()->RemoveCcdPhysicsController(childCtrl); + GetPhysicsEnvironment()->RemoveCcdPhysicsController(childCtrl, true); } /* Reverse function of the above, it will remove a shape from a compound shape diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.h b/source/gameengine/Physics/Bullet/CcdPhysicsController.h index 24662e7b71a4..81cc25a01638 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsController.h +++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.h @@ -515,6 +515,17 @@ class CleanPairCallback : public btOverlapCallback /// CcdPhysicsController is a physics object that supports continuous collision detection and time of impact based physics resolution. class CcdPhysicsController : public PHY_IPhysicsController { +public: + /// Constraint user data. + struct CcdConstraint + { + CcdConstraint(bool m_disableCollision); + /// Disable collision between constrained objects? + bool m_disableCollision; + /// The constraint is added in dynamic world? + bool m_active; + }; + protected: btCollisionObject *m_object; BlenderBulletCharacterController *m_characterController; @@ -683,7 +694,7 @@ class CcdPhysicsController : public PHY_IPhysicsController virtual void ResolveCombinedVelocities(float linvelX, float linvelY, float linvelZ, float angVelX, float angVelY, float angVelZ); virtual void RefreshCollisions(); - virtual void SuspendPhysics(); + virtual void SuspendPhysics(bool freeConstraints); virtual void RestorePhysics(); virtual void SuspendDynamics(bool ghost); virtual void RestoreDynamics(); diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp index 2a41c74a93aa..323600216399 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp @@ -509,6 +509,20 @@ void CcdPhysicsEnvironment::AddCcdPhysicsController(CcdPhysicsController *ctrl) body->setSleepingThresholds(m_linearDeactivationThreshold, m_angularDeactivationThreshold); //use explicit group/filter for finer control over collision in bullet => near/radar sensor m_dynamicsWorld->addRigidBody(body, ctrl->GetCollisionFilterGroup(), ctrl->GetCollisionFilterMask()); + + // Restore constraints in case of physics restore. + for (unsigned short i = 0, size = ctrl->getNumCcdConstraintRefs(); i < size; ++i) { + btTypedConstraint *con = ctrl->getCcdConstraintRef(i); + RestoreConstraint(ctrl, con); + } + + // Handle potential vehicle constraints + for (WrapperVehicle *wrapperVehicle : m_wrapperVehicles) { + if (wrapperVehicle->GetChassis() == ctrl) { + btRaycastVehicle *vehicle = wrapperVehicle->GetVehicle(); + m_dynamicsWorld->addVehicle(vehicle); + } + } } else { if (ctrl->GetSoftBody()) { @@ -531,28 +545,65 @@ void CcdPhysicsEnvironment::AddCcdPhysicsController(CcdPhysicsController *ctrl) BLI_assert(obj->getBroadphaseHandle()); } -void CcdPhysicsEnvironment::RemoveConstraint(btTypedConstraint *con) +void CcdPhysicsEnvironment::RemoveConstraint(btTypedConstraint *con, bool free) { + CcdPhysicsController::CcdConstraint *userData = (CcdPhysicsController::CcdConstraint *)con->getUserConstraintPtr(); + if (!userData->m_active) { + return; + } + btRigidBody &rbA = con->getRigidBodyA(); btRigidBody &rbB = con->getRigidBodyB(); rbA.activate(); rbB.activate(); + + userData->m_active = false; m_dynamicsWorld->removeConstraint(con); - if (rbA.getUserPointer()) { - ((CcdPhysicsController *)rbA.getUserPointer())->removeCcdConstraintRef(con); + if (free) { + 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 userData; + delete con; } +} - if (rbB.getUserPointer()) { - ((CcdPhysicsController *)rbB.getUserPointer())->removeCcdConstraintRef(con); +void CcdPhysicsEnvironment::RestoreConstraint(CcdPhysicsController *ctrl, btTypedConstraint *con) +{ + CcdPhysicsController::CcdConstraint *userData = (CcdPhysicsController::CcdConstraint *)con->getUserConstraintPtr(); + if (userData->m_active) { + return; } - /* 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; + btRigidBody &rbA = con->getRigidBodyA(); + btRigidBody &rbB = con->getRigidBodyB(); + + CcdPhysicsController *other = nullptr; + + if (rbA.getUserPointer() && rbB.getUserPointer()) { + CcdPhysicsController *ctrl0 = (CcdPhysicsController *)rbA.getUserPointer(); + CcdPhysicsController *ctrl1 = (CcdPhysicsController *)rbB.getUserPointer(); + other = (ctrl0 != ctrl) ? ctrl0 : ctrl1; + } + + BLI_assert(other != nullptr); + + // Avoid add constraint if one of the objects are not available. + if (IsActiveCcdPhysicsController(other)) { + userData->m_active = true; + m_dynamicsWorld->addConstraint(con, userData->m_disableCollision); + } } -bool CcdPhysicsEnvironment::RemoveCcdPhysicsController(CcdPhysicsController *ctrl) +bool CcdPhysicsEnvironment::RemoveCcdPhysicsController(CcdPhysicsController *ctrl, bool freeConstraints) { // if the physics controller is already removed we do nothing if (!m_controllers.erase(ctrl)) { @@ -571,7 +622,7 @@ bool CcdPhysicsEnvironment::RemoveCcdPhysicsController(CcdPhysicsController *ctr for (int i = ctrl->getNumCcdConstraintRefs() - 1; i >= 0; i--) { btTypedConstraint *con = ctrl->getCcdConstraintRef(i); - RemoveConstraint(con); + RemoveConstraint(con, freeConstraints); } m_dynamicsWorld->removeRigidBody(ctrl->GetRigidBody()); @@ -585,7 +636,7 @@ bool CcdPhysicsEnvironment::RemoveCcdPhysicsController(CcdPhysicsController *ctr } if (vehicle_constraint > 0) - RemoveConstraintById(vehicle_constraint); + RemoveConstraintById(vehicle_constraint, freeConstraints); } else { //if a softbody @@ -1025,56 +1076,7 @@ void CcdPhysicsEnvironment::SetGravity(float x, float y, float z) static int gConstraintUid = 1; -//Following the COLLADA physics specification for constraints -int CcdPhysicsEnvironment::CreateUniversalD6Constraint( - class PHY_IPhysicsController *ctrlRef, class PHY_IPhysicsController *ctrlOther, - btTransform& frameInA, - btTransform& frameInB, - const btVector3& linearMinLimits, - const btVector3& linearMaxLimits, - const btVector3& angularMinLimits, - const btVector3& angularMaxLimits, int flags) -{ - bool disableCollisionBetweenLinkedBodies = (0 != (flags & CCD_CONSTRAINT_DISABLE_LINKED_COLLISION)); - - //we could either add some logic to recognize ball-socket and hinge, or let that up to the user - //perhaps some warning or hint that hinge/ball-socket is more efficient? - - btGeneric6DofConstraint *genericConstraint = nullptr; - CcdPhysicsController *ctrl0 = (CcdPhysicsController *)ctrlRef; - CcdPhysicsController *ctrl1 = (CcdPhysicsController *)ctrlOther; - - btRigidBody *rb0 = ctrl0->GetRigidBody(); - btRigidBody *rb1 = ctrl1->GetRigidBody(); - - if (rb1) { - bool useReferenceFrameA = true; - genericConstraint = new btGeneric6DofSpringConstraint( - *rb0, *rb1, - frameInA, frameInB, useReferenceFrameA); - genericConstraint->setLinearLowerLimit(linearMinLimits); - genericConstraint->setLinearUpperLimit(linearMaxLimits); - genericConstraint->setAngularLowerLimit(angularMinLimits); - genericConstraint->setAngularUpperLimit(angularMaxLimits); - } - else { - // TODO: Implement single body case... - //No, we can use a fixed rigidbody in above code, rather than unnecessary duplation of code - } - - if (genericConstraint) { - // m_constraints.push_back(genericConstraint); - m_dynamicsWorld->addConstraint(genericConstraint, disableCollisionBetweenLinkedBodies); - - genericConstraint->setUserConstraintId(gConstraintUid++); - genericConstraint->setUserConstraintType(PHY_GENERIC_6DOF_CONSTRAINT); - //64 bit systems can't cast pointer to int. could use size_t instead. - return genericConstraint->getUserConstraintId(); - } - return 0; -} - -void CcdPhysicsEnvironment::RemoveConstraintById(int constraintId) +void CcdPhysicsEnvironment::RemoveConstraintById(int constraintId, bool free) { // For soft body constraints if (constraintId == 0) @@ -1086,7 +1088,7 @@ void CcdPhysicsEnvironment::RemoveConstraintById(int constraintId) btTypedConstraint *constraint = m_dynamicsWorld->getConstraint(i); if (constraint->getUserConstraintId() == constraintId) { - RemoveConstraint(constraint); + RemoveConstraint(constraint, free); break; } } @@ -1095,8 +1097,10 @@ void CcdPhysicsEnvironment::RemoveConstraintById(int constraintId) if ((vehicle = (WrapperVehicle *)GetVehicleConstraint(constraintId))) { m_dynamicsWorld->removeVehicle(vehicle->GetVehicle()); - m_wrapperVehicles.erase(std::remove(m_wrapperVehicles.begin(), m_wrapperVehicles.end(), vehicle)); - delete vehicle; + if (free) { + m_wrapperVehicles.erase(std::remove(m_wrapperVehicles.begin(), m_wrapperVehicles.end(), vehicle)); + delete vehicle; + } } } @@ -2002,7 +2006,7 @@ void CcdPhysicsEnvironment::MergeEnvironment(PHY_IPhysicsEnvironment *other_env) it = other->m_controllers.begin(); CcdPhysicsController *ctrl = (*it); - other->RemoveCcdPhysicsController(ctrl); + other->RemoveCcdPhysicsController(ctrl, true); this->AddCcdPhysicsController(ctrl); } } @@ -2234,7 +2238,7 @@ bool CcdPhysicsEnvironment::RemoveCollisionCallback(PHY_IPhysicsController *ctrl void CcdPhysicsEnvironment::RemoveSensor(PHY_IPhysicsController *ctrl) { - RemoveCcdPhysicsController((CcdPhysicsController *)ctrl); + RemoveCcdPhysicsController((CcdPhysicsController *)ctrl, true); } void CcdPhysicsEnvironment::AddCollisionCallback(int response_class, PHY_ResponseCallback callback, void *user) @@ -2508,6 +2512,13 @@ int CcdPhysicsEnvironment::CreateConstraint(class PHY_IPhysicsController *ctrl0, if (!rb0) return 0; + // If either of the controllers is missing, we can't do anything. + if (!c0 || !c1) { + return 0; + } + + btTypedConstraint *con = nullptr; + btVector3 pivotInB = rb1 ? rb1->getCenterOfMassTransform().inverse()(rb0->getCenterOfMassTransform()(pivotInA)) : rb0->getCenterOfMassTransform() * pivotInA; btVector3 axisInA(axisX, axisY, axisZ); @@ -2519,11 +2530,6 @@ int CcdPhysicsEnvironment::CreateConstraint(class PHY_IPhysicsController *ctrl0, { case PHY_POINT2POINT_CONSTRAINT: { - // If either of the controllers is missing, we can't do anything. - if (!c0 || !c1) { - return 0; - } - btPoint2PointConstraint *p2p = nullptr; if (rb1) { @@ -2533,26 +2539,13 @@ int CcdPhysicsEnvironment::CreateConstraint(class PHY_IPhysicsController *ctrl0, p2p = new btPoint2PointConstraint(*rb0, pivotInA); } - c0->addCcdConstraintRef(p2p); - c1->addCcdConstraintRef(p2p); - m_dynamicsWorld->addConstraint(p2p, disableCollisionBetweenLinkedBodies); -// m_constraints.push_back(p2p); - - p2p->setUserConstraintId(gConstraintUid++); - p2p->setUserConstraintType(type); - //64 bit systems can't cast pointer to int. could use size_t instead. - return p2p->getUserConstraintId(); + con = p2p; break; } case PHY_GENERIC_6DOF_CONSTRAINT: { - // If either of the controllers is missing, we can't do anything. - if (!c0 || !c1) { - return 0; - } - btGeneric6DofConstraint *genericConstraint = nullptr; if (rb1) { @@ -2604,26 +2597,12 @@ int CcdPhysicsEnvironment::CreateConstraint(class PHY_IPhysicsController *ctrl0, 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); - //64 bit systems can't cast pointer to int. could use size_t instead. - return genericConstraint->getUserConstraintId(); - } + con = genericConstraint; break; } case PHY_CONE_TWIST_CONSTRAINT: { - // If either of the controllers is missing, we can't do anything. - if (!c0 || !c1) { - return 0; - } - btConeTwistConstraint *coneTwistContraint = nullptr; if (rb1) { @@ -2672,16 +2651,7 @@ int CcdPhysicsEnvironment::CreateConstraint(class PHY_IPhysicsController *ctrl0, 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); - //64 bit systems can't cast pointer to int. could use size_t instead. - return coneTwistContraint->getUserConstraintId(); - } + con = coneTwistContraint; break; } @@ -2690,11 +2660,6 @@ int CcdPhysicsEnvironment::CreateConstraint(class PHY_IPhysicsController *ctrl0, case PHY_LINEHINGE_CONSTRAINT: { - // If either of the controllers is missing, we can't do anything. - if (!c0 || !c1) { - return 0; - } - btHingeConstraint *hinge = nullptr; if (rb1) { @@ -2745,14 +2710,8 @@ int CcdPhysicsEnvironment::CreateConstraint(class PHY_IPhysicsController *ctrl0, } 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); - //64 bit systems can't cast pointer to int. could use size_t instead. - return hinge->getUserConstraintId(); + con = hinge; + break; } #ifdef NEW_BULLET_VEHICLE_SUPPORT @@ -2766,9 +2725,6 @@ int CcdPhysicsEnvironment::CreateConstraint(class PHY_IPhysicsController *ctrl0, WrapperVehicle *wrapperVehicle = new WrapperVehicle(vehicle, raycaster, ctrl0); m_wrapperVehicles.push_back(wrapperVehicle); m_dynamicsWorld->addVehicle(vehicle); - vehicle->setUserConstraintId(gConstraintUid++); - vehicle->setUserConstraintType(type); - return vehicle->getUserConstraintId(); break; }; @@ -2779,6 +2735,17 @@ int CcdPhysicsEnvironment::CreateConstraint(class PHY_IPhysicsController *ctrl0, } }; + if (con) { + c0->addCcdConstraintRef(con); + c1->addCcdConstraintRef(con); + con->setUserConstraintId(gConstraintUid++); + con->setUserConstraintType(type); + CcdPhysicsController::CcdConstraint *userData = new CcdPhysicsController::CcdConstraint(disableCollisionBetweenLinkedBodies); + con->setUserConstraintPtr(userData); + userData->m_active = true; + m_dynamicsWorld->addConstraint(con, disableCollisionBetweenLinkedBodies); + } + return 0; } diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h index f6f98f92dec4..a870480021df 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h +++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h @@ -25,10 +25,11 @@ #include "KX_KetsjiEngine.h" #include "KX_Globals.h" +#include "CcdPhysicsController.h" + #include #include #include -class CcdPhysicsController; class CcdGraphicController; #include "LinearMath/btVector3.h" #include "LinearMath/btTransform.h" @@ -66,7 +67,9 @@ class CcdPhysicsEnvironment : public PHY_IPhysicsEnvironment btVector3 m_gravity; /// Removes the constraint and his references from the owner and the target. - void RemoveConstraint(btTypedConstraint *con); + void RemoveConstraint(btTypedConstraint *con, bool free); + /// Restore the constraint if the owner and target are presents. + void RestoreConstraint(CcdPhysicsController *ctrl, btTypedConstraint *con); protected: btIDebugDraw *m_debugDrawer; @@ -172,21 +175,11 @@ class CcdPhysicsEnvironment : public PHY_IPhysicsEnvironment float axis1X = 0, float axis1Y = 0, float axis1Z = 0, float axis2X = 0, float axis2Y = 0, float axis2Z = 0, int flag = 0); - //Following the COLLADA physics specification for constraints - virtual int CreateUniversalD6Constraint( - class PHY_IPhysicsController *ctrlRef, class PHY_IPhysicsController *ctrlOther, - btTransform& localAttachmentFrameRef, - btTransform& localAttachmentOther, - const btVector3& linearMinLimits, - const btVector3& linearMaxLimits, - const btVector3& angularMinLimits, - const btVector3& angularMaxLimits, int flags); - virtual void SetConstraintParam(int constraintId, int param, float value, float value1); virtual float GetConstraintParam(int constraintId, int param); - virtual void RemoveConstraintById(int constraintid); + virtual void RemoveConstraintById(int constraintid, bool free); virtual float getAppliedImpulse(int constraintid); @@ -230,7 +223,7 @@ class CcdPhysicsEnvironment : public PHY_IPhysicsEnvironment void AddCcdPhysicsController(CcdPhysicsController *ctrl); - bool RemoveCcdPhysicsController(CcdPhysicsController *ctrl); + bool RemoveCcdPhysicsController(CcdPhysicsController *ctrl, bool freeConstraints); void UpdateCcdPhysicsController(CcdPhysicsController *ctrl, btScalar newMass, int newCollisionFlags, short int newCollisionGroup, short int newCollisionMask); diff --git a/source/gameengine/Physics/Common/PHY_IPhysicsController.h b/source/gameengine/Physics/Common/PHY_IPhysicsController.h index 3aff2e5828de..26091ebac813 100644 --- a/source/gameengine/Physics/Common/PHY_IPhysicsController.h +++ b/source/gameengine/Physics/Common/PHY_IPhysicsController.h @@ -98,7 +98,7 @@ class PHY_IPhysicsController : public PHY_IController virtual void SetDamping(float linear, float angular) = 0; virtual void RefreshCollisions() = 0; - virtual void SuspendPhysics() = 0; + virtual void SuspendPhysics(bool freeConstraints) = 0; virtual void RestorePhysics() = 0; virtual void SuspendDynamics(bool ghost = false) = 0; virtual void RestoreDynamics() = 0; diff --git a/source/gameengine/Physics/Common/PHY_IPhysicsEnvironment.h b/source/gameengine/Physics/Common/PHY_IPhysicsEnvironment.h index 28b6c07b928d..b5578421f956 100644 --- a/source/gameengine/Physics/Common/PHY_IPhysicsEnvironment.h +++ b/source/gameengine/Physics/Common/PHY_IPhysicsEnvironment.h @@ -191,7 +191,7 @@ class PHY_IPhysicsEnvironment float axis0X, float axis0Y, float axis0Z, float axis1X = 0, float axis1Y = 0, float axis1Z = 0, float axis2X = 0, float axis2Y = 0, float axis2Z = 0, int flag = 0) = 0; - virtual void RemoveConstraintById(int constraintid) = 0; + virtual void RemoveConstraintById(int constraintid, bool free) = 0; virtual float GetAppliedImpulse(int constraintid) { return 0.0f; diff --git a/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.cpp b/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.cpp index ea36bb428661..bc2774ff9c8d 100644 --- a/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.cpp +++ b/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.cpp @@ -97,7 +97,7 @@ int DummyPhysicsEnvironment::CreateConstraint(class PHY_IPhysicsController *ctrl return constraintid; } -void DummyPhysicsEnvironment::RemoveConstraintById(int constraintid) +void DummyPhysicsEnvironment::RemoveConstraintById(int constraintid, bool free) { if (constraintid) { } diff --git a/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h b/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h index 7caf7da8ea88..4ea0bc0379d3 100644 --- a/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h +++ b/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h @@ -66,7 +66,7 @@ class DummyPhysicsEnvironment : public PHY_IPhysicsEnvironment float axis1X = 0, float axis1Y = 0, float axis1Z = 0, float axis2X = 0, float axis2Y = 0, float axis2Z = 0, int flag = 0); - virtual void RemoveConstraintById(int constraintid); + virtual void RemoveConstraintById(int constraintid, bool free); //complex constraint for vehicles virtual PHY_IVehicle *GetVehicleConstraint(int constraintId) diff --git a/source/tools b/source/tools index 4ace84b09b04..b11375e89061 160000 --- a/source/tools +++ b/source/tools @@ -1 +1 @@ -Subproject commit 4ace84b09b04f62192c0cdf4f3b87a68f45aabe9 +Subproject commit b11375e89061303401376f7aeae42ac2fd64692a