summaryrefslogtreecommitdiff
path: root/modules/bullet/space_bullet.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'modules/bullet/space_bullet.cpp')
-rw-r--r--modules/bullet/space_bullet.cpp98
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();