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:
authorMartin Felke <martin.felke@googlemail.com>2018-07-27 18:04:42 +0300
committerMartin Felke <martin.felke@googlemail.com>2018-07-27 18:04:42 +0300
commit0f155702664bd488c869556f5c42d84982b6950c (patch)
tree0340ab0033580d9f01f3fe887a22bb2eaa24393f
parentb82de8463bf767376f664a17e663b08eb7bb23d0 (diff)
attempt to fix incorrect (bbox) triggering behavior
-rw-r--r--intern/rigidbody/rb_bullet_api.cpp113
-rw-r--r--source/blender/blenkernel/intern/rigidbody.c26
2 files changed, 67 insertions, 72 deletions
diff --git a/intern/rigidbody/rb_bullet_api.cpp b/intern/rigidbody/rb_bullet_api.cpp
index e26c1307b97..9871b4751c2 100644
--- a/intern/rigidbody/rb_bullet_api.cpp
+++ b/intern/rigidbody/rb_bullet_api.cpp
@@ -672,13 +672,15 @@ void TickDiscreteDynamicsWorld::debugDrawConstraints(rbConstraint* con , draw_st
return;
}
+struct rbFilterCallback;
+
struct rbDynamicsWorld {
TickDiscreteDynamicsWorld *dynamicsWorld;
btDefaultCollisionConfiguration *collisionConfiguration;
btDispatcher *dispatcher;
btBroadphaseInterface *pairCache;
btConstraintSolver *constraintSolver;
- btOverlapFilterCallback *filterCallback;
+ rbFilterCallback *filterCallback;
void *blenderWorld;
//struct rbContactCallback *contactCallback;
IdOutCallback idOutCallback;
@@ -735,52 +737,12 @@ struct rbFilterCallback : public btOverlapFilterCallback
return collides;
collides = collides && (rb0->col_groups & rb1->col_groups);
- if (this->callback != NULL) {
-
- int stype0 = rb0->body->getCollisionShape()->getShapeType();
- int stype1 = rb1->body->getCollisionShape()->getShapeType();
- bool meshShape0 = (stype0 == GIMPACT_SHAPE_PROXYTYPE) || (stype0 == TRIANGLE_MESH_SHAPE_PROXYTYPE);
- bool meshShape1 = (stype1 == GIMPACT_SHAPE_PROXYTYPE) || (stype1 == TRIANGLE_MESH_SHAPE_PROXYTYPE);
-
- if ((rb0->blenderOb != rb1->blenderOb) && (meshShape0 && meshShape1))
- {
- btVector3 v0, v1, min0, max0, min1, max1, min, max;
- v0 = rb0->body->getWorldTransform().getOrigin();
- v1 = rb1->body->getWorldTransform().getOrigin();
-
- rb0->body->getAabb(min0, max0);
- rb1->body->getAabb(min1, max1);
+ if (this->callback != NULL && collides) {
- min = min1;
- max = max1;
-
- if ((max0-min0).length2() < (max1-min1).length2())
- {
- min = min0;
- max = max0;
- }
-
- myResultCallback cb(v0, v1);
- rb0->world->dynamicsWorld->rayTest(v0, v1, cb);
- if (cb.m_collisionObject && TestPointAgainstAabb2(min, max, cb.m_hitPointWorld))
- {
- int result = this->callback(rb0->world->blenderWorld, rb0->meshIsland, rb1->meshIsland,
- rb0->blenderOb, rb1->blenderOb,
- activate && (cb.m_collisionObject == (btCollisionObject*)rb1->body));
+ int result = this->callback(rb0->world->blenderWorld, rb0->meshIsland, rb1->meshIsland,
+ rb0->blenderOb, rb1->blenderOb, activate);
- collides = collides && (bool)result;
-
- }
- else {
- collides = false;
- }
- }
- else {
- int result = this->callback(rb0->world->blenderWorld, rb0->meshIsland, rb1->meshIsland,
- rb0->blenderOb, rb1->blenderOb, activate);
-
- collides = collides && (bool)result;
- }
+ collides = collides && (bool)result;
}
return collides;
@@ -799,6 +761,11 @@ struct rbFilterCallback : public btOverlapFilterCallback
(proxy0->m_collisionFilterMask | btBroadphaseProxy::StaticFilter |
btBroadphaseProxy::KinematicFilter));
+ //no self collisions between kinematic shards in own object allowed
+ collides = collides && ((!rb0->body->isStaticOrKinematicObject() || !rb1->body->isStaticOrKinematicObject()) ||
+ ((rb0->body->isStaticOrKinematicObject() && rb1->body->isStaticOrKinematicObject()) &&
+ (rb0->blenderOb != rb1->blenderOb)));
+
//only apply to trigger and triggered, to improve performance, but do not actually activate
return this->check_collision(rb0, rb1, false, collides);
}
@@ -907,7 +874,7 @@ bool CollisionFilterDispatcher::needsCollision(const btCollisionObject *body0, c
{
if (this->filterCallback)
{
- return this->filterCallback->check_collision(rb0, rb1, true, true);
+ return this->filterCallback->check_collision(rb0, rb1, false, true);
}
return true;
@@ -916,22 +883,70 @@ bool CollisionFilterDispatcher::needsCollision(const btCollisionObject *body0, c
return false;
}
+/*taken from btCollisionDispatcher defaultNearCallback */
+static void nearCallback(btBroadphasePair &collisionPair, btCollisionDispatcher &dispatcher, const btDispatcherInfo &dispatchInfo)
+{
+ btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject;
+ btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject;
+
+ if (dispatcher.needsCollision(colObj0, colObj1)) {
+ btCollisionObjectWrapper obj0Wrap(0, colObj0->getCollisionShape(), colObj0,colObj0->getWorldTransform(), -1, -1);
+ btCollisionObjectWrapper obj1Wrap(0, colObj1->getCollisionShape(), colObj1,colObj1->getWorldTransform(), -1, -1);
+
+ //dispatcher will keep algorithms persistent in the collision pair
+ if (!collisionPair.m_algorithm) {
+ collisionPair.m_algorithm = dispatcher.findAlgorithm(&obj0Wrap, &obj1Wrap);
+ }
+ if (collisionPair.m_algorithm) {
+ btManifoldResult contactPointResult(&obj0Wrap, &obj1Wrap);
+
+ if (dispatchInfo.m_dispatchFunc == btDispatcherInfo::DISPATCH_DISCRETE) {
+ //discrete collision detection query
+
+ collisionPair.m_algorithm->processCollision(&obj0Wrap, &obj1Wrap, dispatchInfo, &contactPointResult);
+ }
+ else
+ {
+ //continuous collision detection query, time of impact (toi)
+ btScalar toi = collisionPair.m_algorithm->calculateTimeOfImpact(colObj0, colObj1, dispatchInfo, &contactPointResult);
+ if (dispatchInfo.m_timeOfImpact > toi)
+ dispatchInfo.m_timeOfImpact = toi;
+ }
+
+ btPersistentManifold *manifold = contactPointResult.getPersistentManifold();
+ if (manifold && manifold->getNumContacts() > 0) {
+ rbRigidBody *rb0 = (rbRigidBody *)((btRigidBody *)collisionPair.m_pProxy0->m_clientObject)->getUserPointer();
+ rbRigidBody *rb1 = (rbRigidBody *)((btRigidBody *)collisionPair.m_pProxy1->m_clientObject)->getUserPointer();
+
+ //handle_activation(manifold, rb0, rb1);
+ //handle_activation(manifold, rb1, rb0);
+ ((rbFilterCallback*)(rb0->world->filterCallback))->callback(rb0->world->blenderWorld, rb0->meshIsland, rb1->meshIsland,
+ rb0->blenderOb, rb1->blenderOb, true);
+ }
+ }
+ }
+}
+
//yuck, but need a handle for the world somewhere for collision callback...
rbDynamicsWorld *RB_dworld_new(const float gravity[3], void* blenderWorld, void* blenderScene, int (*callback)(void *, void *, void *, void *, void *, bool),
void (*contactCallback)(rbContactPoint* cp, void *bworld), void (*idCallbackOut)(void*, void*, int*, int*),
void (*tickCallback)(float timestep, void *bworld))
{
rbDynamicsWorld *world = new rbDynamicsWorld;
-
+
/* collision detection/handling */
world->collisionConfiguration = new btDefaultCollisionConfiguration();
world->filterCallback = new rbFilterCallback(callback);
- world->dispatcher = new CollisionFilterDispatcher(world->collisionConfiguration, (rbFilterCallback*)world->filterCallback);
+ world->dispatcher = new CollisionFilterDispatcher(world->collisionConfiguration, world->filterCallback);
+ ((btCollisionDispatcher*)world->dispatcher)->setNearCallback(nearCallback);
+
btGImpactCollisionAlgorithm::registerAlgorithm((btCollisionDispatcher *)world->dispatcher);
world->pairCache = new btDbvtBroadphase();
- world->pairCache->getOverlappingPairCache()->setOverlapFilterCallback(world->filterCallback);
+
+ /*necessary for needsBroadphaseCollision of kinematic triggers */
+ world->pairCache->getOverlappingPairCache()->setOverlapFilterCallback((btOverlapFilterCallback*)world->filterCallback);
/* constraint solving */
world->constraintSolver = new btSequentialImpulseConstraintSolver();
diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c
index 468f6ce3151..e4622dd57ca 100644
--- a/source/blender/blenkernel/intern/rigidbody.c
+++ b/source/blender/blenkernel/intern/rigidbody.c
@@ -4315,20 +4315,12 @@ static int filterCallback(void* world, void* island1, void* island2, void *blend
if (ob1->rigidbody_object->flag & RBO_FLAG_USE_KINEMATIC_DEACTIVATION)
{
- bool override = activate || (!mi1 && !mi2 && (ob2->rigidbody_object->flag & RBO_FLAG_IS_GHOST) &&
- (ob2->rigidbody_object->flag & RBO_FLAG_IS_TRIGGER)) ||
- ((ob2->rigidbody_object->flag & RBO_FLAG_IS_GHOST) && (ob2->rigidbody_object->flag & RBO_FLAG_ANTI_TRIGGER));
-
- check_activate = do_activate(ob1, ob2, mi1, rbw, mi2, override);
+ check_activate = do_activate(ob1, ob2, mi1, rbw, mi2, activate);
}
if (ob2->rigidbody_object->flag & RBO_FLAG_USE_KINEMATIC_DEACTIVATION)
{
- bool override = activate || (!mi1 && !mi2 && (ob1->rigidbody_object->flag & RBO_FLAG_IS_GHOST) &&
- (ob1->rigidbody_object->flag & RBO_FLAG_IS_TRIGGER)) ||
- ((ob1->rigidbody_object->flag & RBO_FLAG_IS_GHOST) && (ob1->rigidbody_object->flag & RBO_FLAG_ANTI_TRIGGER));
-
- check_activate = do_activate(ob2, ob1, mi2, rbw, mi1, override);
+ check_activate = do_activate(ob2, ob1, mi2, rbw, mi1, activate);
}
}
@@ -4336,20 +4328,8 @@ static int filterCallback(void* world, void* island1, void* island2, void *blend
fake_dynamic_collide(ob1, ob2, mi1, mi2, rbw);
fake_dynamic_collide(ob2, ob1, mi2, mi1, rbw);
- if (activate)
- {
- validOb = ((ob1->rigidbody_object->flag & RBO_FLAG_KINEMATIC) == 0) || ((ob2->rigidbody_object->flag & RBO_FLAG_KINEMATIC) == 0);
- validOb = validOb || ((ob1->rigidbody_object->flag & RBO_FLAG_KINEMATIC) == 0) || (mi2 && (mi2->rigidbody->flag & RBO_FLAG_KINEMATIC) == 0);
- validOb = validOb || ((mi1 && (mi1->rigidbody->flag & RBO_FLAG_KINEMATIC) == 0)) || ((ob2->rigidbody_object->flag & RBO_FLAG_KINEMATIC) == 0);
- validOb = validOb || ((mi1 && (mi1->rigidbody->flag & RBO_FLAG_KINEMATIC) == 0)) || (mi2 && (mi2->rigidbody->flag & RBO_FLAG_KINEMATIC) == 0);
-
- validOb = validOb && (check_colgroup_ghost(ob1, ob2) && ((check_constraint_island(fmd1, mi1, mi2) &&
+ validOb = (check_colgroup_ghost(ob1, ob2) && ((check_constraint_island(fmd1, mi1, mi2) &&
check_constraint_island(fmd2, mi2, mi1)) || (ob1 != ob2)));
- }
- else {
- validOb = (check_colgroup_ghost(ob1, ob2) && ((check_constraint_island(fmd1, mi1, mi2) &&
- check_constraint_island(fmd2, mi2, mi1)) || (ob1 != ob2)));
- }
return activate ? validOb : check_activate || validOb;
}