From 0f155702664bd488c869556f5c42d84982b6950c Mon Sep 17 00:00:00 2001 From: Martin Felke Date: Fri, 27 Jul 2018 17:04:42 +0200 Subject: attempt to fix incorrect (bbox) triggering behavior --- intern/rigidbody/rb_bullet_api.cpp | 113 +++++++++++++++------------ source/blender/blenkernel/intern/rigidbody.c | 26 +----- 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; } -- cgit v1.2.3