diff options
Diffstat (limited to 'modules/bullet/space_bullet.cpp')
-rw-r--r-- | modules/bullet/space_bullet.cpp | 98 |
1 files changed, 70 insertions, 28 deletions
diff --git a/modules/bullet/space_bullet.cpp b/modules/bullet/space_bullet.cpp index 1b6ccbcef4..9dc307c629 100644 --- a/modules/bullet/space_bullet.cpp +++ b/modules/bullet/space_bullet.cpp @@ -123,10 +123,11 @@ int BulletPhysicsDirectSpaceState::intersect_shape(const RID &p_shape, const Tra } ShapeBullet *shape = space->get_physics_server()->get_shape_owner()->getornull(p_shape); + ERR_FAIL_COND_V(!shape, 0); btCollisionShape *btShape = shape->create_bt_shape(p_xform.basis.get_scale_abs(), p_margin); if (!btShape->isConvex()) { - bulletdelete(btShape); + shape->destroy_bt_shape(btShape); ERR_PRINT("The shape is not a convex shape, then is not supported: shape type: " + itos(shape->get_type())); return 0; } @@ -146,7 +147,7 @@ int BulletPhysicsDirectSpaceState::intersect_shape(const RID &p_shape, const Tra btQuery.m_closestDistanceThreshold = 0; space->dynamicsWorld->contactTest(&collision_object, btQuery); - bulletdelete(btConvex); + shape->destroy_bt_shape(btShape); return btQuery.m_count; } @@ -157,15 +158,12 @@ bool BulletPhysicsDirectSpaceState::cast_motion(const RID &p_shape, const Transf btVector3 bt_motion; G_TO_B(p_motion, bt_motion); - if (bt_motion.fuzzyZero()) { - return false; - } - ShapeBullet *shape = space->get_physics_server()->get_shape_owner()->getornull(p_shape); + ERR_FAIL_COND_V(!shape, false); btCollisionShape *btShape = shape->create_bt_shape(p_xform.basis.get_scale(), p_margin); if (!btShape->isConvex()) { - bulletdelete(btShape); + shape->destroy_bt_shape(btShape); ERR_PRINT("The shape is not a convex shape, then is not supported: shape type: " + itos(shape->get_type())); return false; } @@ -178,6 +176,10 @@ bool BulletPhysicsDirectSpaceState::cast_motion(const RID &p_shape, const Transf btTransform bt_xform_to(bt_xform_from); bt_xform_to.getOrigin() += bt_motion; + if ((bt_xform_to.getOrigin() - bt_xform_from.getOrigin()).fuzzyZero()) { + return false; + } + GodotClosestConvexResultCallback btResult(bt_xform_from.getOrigin(), bt_xform_to.getOrigin(), &p_exclude, p_collide_with_bodies, p_collide_with_areas); btResult.m_collisionFilterGroup = 0; btResult.m_collisionFilterMask = p_collision_mask; @@ -204,7 +206,7 @@ bool BulletPhysicsDirectSpaceState::cast_motion(const RID &p_shape, const Transf r_closest_unsafe = 1.0f; } - bulletdelete(bt_convex_shape); + shape->destroy_bt_shape(btShape); return true; // Mean success } @@ -215,10 +217,11 @@ bool BulletPhysicsDirectSpaceState::collide_shape(RID p_shape, const Transform & } ShapeBullet *shape = space->get_physics_server()->get_shape_owner()->getornull(p_shape); + ERR_FAIL_COND_V(!shape, false); btCollisionShape *btShape = shape->create_bt_shape(p_shape_xform.basis.get_scale_abs(), p_margin); if (!btShape->isConvex()) { - bulletdelete(btShape); + shape->destroy_bt_shape(btShape); ERR_PRINT("The shape is not a convex shape, then is not supported: shape type: " + itos(shape->get_type())); return false; } @@ -239,17 +242,18 @@ bool BulletPhysicsDirectSpaceState::collide_shape(RID p_shape, const Transform & space->dynamicsWorld->contactTest(&collision_object, btQuery); r_result_count = btQuery.m_count; - bulletdelete(btConvex); + shape->destroy_bt_shape(btShape); return btQuery.m_count; } bool BulletPhysicsDirectSpaceState::rest_info(RID p_shape, const Transform &p_shape_xform, float p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) { ShapeBullet *shape = space->get_physics_server()->get_shape_owner()->getornull(p_shape); + ERR_FAIL_COND_V(!shape, false); btCollisionShape *btShape = shape->create_bt_shape(p_shape_xform.basis.get_scale_abs(), p_margin); if (!btShape->isConvex()) { - bulletdelete(btShape); + shape->destroy_bt_shape(btShape); ERR_PRINT("The shape is not a convex shape, then is not supported: shape type: " + itos(shape->get_type())); return false; } @@ -269,7 +273,7 @@ bool BulletPhysicsDirectSpaceState::rest_info(RID p_shape, const Transform &p_sh btQuery.m_closestDistanceThreshold = 0; space->dynamicsWorld->contactTest(&collision_object, btQuery); - bulletdelete(btConvex); + shape->destroy_bt_shape(btShape); if (btQuery.m_collided) { if (btCollisionObject::CO_RIGID_BODY == btQuery.m_rest_info_collision_object->getInternalType()) { @@ -282,7 +286,7 @@ bool BulletPhysicsDirectSpaceState::rest_info(RID p_shape, const Transform &p_sh } Vector3 BulletPhysicsDirectSpaceState::get_closest_point_to_object_volume(RID p_object, const Vector3 p_point) const { - RigidCollisionObjectBullet *rigid_object = space->get_physics_server()->get_rigid_collisin_object(p_object); + RigidCollisionObjectBullet *rigid_object = space->get_physics_server()->get_rigid_collision_object(p_object); ERR_FAIL_COND_V(!rigid_object, Vector3()); btVector3 out_closest_point(0, 0, 0); @@ -345,9 +349,11 @@ SpaceBullet::~SpaceBullet() { } void SpaceBullet::flush_queries() { - const btCollisionObjectArray &colObjArray = dynamicsWorld->getCollisionObjectArray(); - for (int i = colObjArray.size() - 1; 0 <= i; --i) { - static_cast<CollisionObjectBullet *>(colObjArray[i]->getUserPointer())->dispatch_callbacks(); + const int size = collision_objects.size(); + CollisionObjectBullet **objects = collision_objects.ptrw(); + for (int i = 0; i < size; i += 1) { + objects[i]->prepare_object_for_dispatch(); + objects[i]->dispatch_callbacks(); } } @@ -444,16 +450,30 @@ real_t SpaceBullet::get_param(PhysicsServer3D::SpaceParameter p_param) { } void SpaceBullet::add_area(AreaBullet *p_area) { +#ifdef TOOLS_ENABLED + // This never happen, and there is no way for the user to trigger it. + // If in future a bug is introduced into this bullet integration and this + // function is called twice, the crash will notify the developer that will + // fix it even before do the eventual PR. + CRASH_COND(p_area->is_in_world); +#endif areas.push_back(p_area); dynamicsWorld->addCollisionObject(p_area->get_bt_ghost(), p_area->get_collision_layer(), p_area->get_collision_mask()); + p_area->is_in_world = true; } void SpaceBullet::remove_area(AreaBullet *p_area) { - areas.erase(p_area); - dynamicsWorld->removeCollisionObject(p_area->get_bt_ghost()); + if (p_area->is_in_world) { + areas.erase(p_area); + dynamicsWorld->removeCollisionObject(p_area->get_bt_ghost()); + p_area->is_in_world = false; + } } void SpaceBullet::reload_collision_filters(AreaBullet *p_area) { + if (p_area->is_in_world == false) { + return; + } btGhostObject *ghost_object = p_area->get_bt_ghost(); btBroadphaseProxy *ghost_proxy = ghost_object->getBroadphaseHandle(); @@ -463,24 +483,46 @@ void SpaceBullet::reload_collision_filters(AreaBullet *p_area) { dynamicsWorld->refreshBroadphaseProxy(ghost_object); } +void SpaceBullet::register_collision_object(CollisionObjectBullet *p_object) { + collision_objects.push_back(p_object); +} + +void SpaceBullet::unregister_collision_object(CollisionObjectBullet *p_object) { + collision_objects.erase(p_object); +} + void SpaceBullet::add_rigid_body(RigidBodyBullet *p_body) { +#ifdef TOOLS_ENABLED + // This never happen, and there is no way for the user to trigger it. + // If in future a bug is introduced into this bullet integration and this + // function is called twice, the crash will notify the developer that will + // fix it even before do the eventual PR. + CRASH_COND(p_body->is_in_world); +#endif if (p_body->is_static()) { dynamicsWorld->addCollisionObject(p_body->get_bt_rigid_body(), p_body->get_collision_layer(), p_body->get_collision_mask()); } else { dynamicsWorld->addRigidBody(p_body->get_bt_rigid_body(), p_body->get_collision_layer(), p_body->get_collision_mask()); p_body->scratch_space_override_modificator(); } + p_body->is_in_world = true; } void SpaceBullet::remove_rigid_body(RigidBodyBullet *p_body) { - if (p_body->is_static()) { - dynamicsWorld->removeCollisionObject(p_body->get_bt_rigid_body()); - } else { - dynamicsWorld->removeRigidBody(p_body->get_bt_rigid_body()); + if (p_body->is_in_world) { + if (p_body->is_static()) { + dynamicsWorld->removeCollisionObject(p_body->get_bt_rigid_body()); + } else { + dynamicsWorld->removeRigidBody(p_body->get_bt_rigid_body()); + } + p_body->is_in_world = false; } } void SpaceBullet::reload_collision_filters(RigidBodyBullet *p_body) { + if (p_body->is_in_world == false) { + return; + } btRigidBody *rigid_body = p_body->get_bt_rigid_body(); btBroadphaseProxy *body_proxy = rigid_body->getBroadphaseProxy(); @@ -537,10 +579,6 @@ void SpaceBullet::remove_all_collision_objects() { } } -void onBulletPreTickCallback(btDynamicsWorld *p_dynamicsWorld, btScalar timeStep) { - static_cast<SpaceBullet *>(p_dynamicsWorld->getWorldUserInfo())->flush_queries(); -} - void onBulletTickCallback(btDynamicsWorld *p_dynamicsWorld, btScalar timeStep) { const btCollisionObjectArray &colObjArray = p_dynamicsWorld->getCollisionObjectArray(); @@ -608,7 +646,6 @@ void SpaceBullet::create_empty_world(bool p_create_soft_world) { dynamicsWorld->setWorldUserInfo(this); - dynamicsWorld->setInternalTickCallback(onBulletPreTickCallback, this, true); dynamicsWorld->setInternalTickCallback(onBulletTickCallback, this, false); dynamicsWorld->getBroadphase()->getOverlappingPairCache()->setInternalGhostPairCallback(ghostPairCallback); // Setup ghost check dynamicsWorld->getPairCache()->setOverlapFilterCallback(godotFilterCallback); @@ -945,7 +982,7 @@ bool SpaceBullet::test_body_motion(RigidBodyBullet *p_body, const Transform &p_f motionVec->end(); #endif - for (int shIndex = 0; shIndex < shape_count && !motion.fuzzyZero(); ++shIndex) { + for (int shIndex = 0; shIndex < shape_count; ++shIndex) { if (p_body->is_shape_disabled(shIndex)) { continue; } @@ -967,6 +1004,11 @@ bool SpaceBullet::test_body_motion(RigidBodyBullet *p_body, const Transform &p_f btTransform shape_world_to(shape_world_from); shape_world_to.getOrigin() += motion; + if ((shape_world_to.getOrigin() - shape_world_from.getOrigin()).fuzzyZero()) { + motion = btVector3(0, 0, 0); + break; + } + GodotKinClosestConvexResultCallback btResult(shape_world_from.getOrigin(), shape_world_to.getOrigin(), p_body, p_infinite_inertia); btResult.m_collisionFilterGroup = p_body->get_collision_layer(); btResult.m_collisionFilterMask = p_body->get_collision_mask(); |