summaryrefslogtreecommitdiff
path: root/modules/bullet
diff options
context:
space:
mode:
Diffstat (limited to 'modules/bullet')
-rw-r--r--modules/bullet/SCsub8
-rw-r--r--modules/bullet/area_bullet.cpp19
-rw-r--r--modules/bullet/area_bullet.h2
-rw-r--r--modules/bullet/btRayShape.cpp2
-rw-r--r--modules/bullet/bullet_physics_server.cpp86
-rw-r--r--modules/bullet/bullet_physics_server.h23
-rw-r--r--modules/bullet/bullet_types_converter.cpp2
-rw-r--r--modules/bullet/bullet_utilities.h9
-rw-r--r--modules/bullet/collision_object_bullet.cpp201
-rw-r--r--modules/bullet/collision_object_bullet.h51
-rw-r--r--modules/bullet/cone_twist_joint_bullet.cpp27
-rw-r--r--modules/bullet/cone_twist_joint_bullet.h8
-rw-r--r--modules/bullet/generic_6dof_joint_bullet.cpp109
-rw-r--r--modules/bullet/generic_6dof_joint_bullet.h7
-rw-r--r--modules/bullet/godot_collision_configuration.cpp56
-rw-r--r--modules/bullet/godot_collision_configuration.h13
-rw-r--r--modules/bullet/godot_collision_dispatcher.h2
-rw-r--r--modules/bullet/godot_motion_state.h2
-rw-r--r--modules/bullet/godot_ray_world_algorithm.cpp2
-rw-r--r--modules/bullet/godot_result_callbacks.cpp92
-rw-r--r--modules/bullet/godot_result_callbacks.h67
-rw-r--r--modules/bullet/hinge_joint_bullet.cpp13
-rw-r--r--modules/bullet/pin_joint_bullet.cpp3
-rw-r--r--modules/bullet/register_types.cpp4
-rw-r--r--modules/bullet/rigid_body_bullet.cpp133
-rw-r--r--modules/bullet/rigid_body_bullet.h36
-rw-r--r--modules/bullet/shape_bullet.cpp68
-rw-r--r--modules/bullet/shape_bullet.h26
-rw-r--r--modules/bullet/shape_owner_bullet.h9
-rw-r--r--modules/bullet/slider_joint_bullet.cpp1
-rw-r--r--modules/bullet/soft_body_bullet.cpp14
-rw-r--r--modules/bullet/soft_body_bullet.h7
-rw-r--r--modules/bullet/space_bullet.cpp352
-rw-r--r--modules/bullet/space_bullet.h23
34 files changed, 951 insertions, 526 deletions
diff --git a/modules/bullet/SCsub b/modules/bullet/SCsub
index d8d0b930a5..11ce18449b 100644
--- a/modules/bullet/SCsub
+++ b/modules/bullet/SCsub
@@ -68,11 +68,13 @@ if env['builtin_bullet']:
, "BulletCollision/CollisionShapes/btEmptyShape.cpp"
, "BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp"
, "BulletCollision/CollisionShapes/btMinkowskiSumShape.cpp"
+ , "BulletCollision/CollisionShapes/btMiniSDF.cpp"
, "BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.cpp"
, "BulletCollision/CollisionShapes/btMultiSphereShape.cpp"
, "BulletCollision/CollisionShapes/btOptimizedBvh.cpp"
, "BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp"
, "BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.cpp"
+ , "BulletCollision/CollisionShapes/btSdfCollisionShape.cpp"
, "BulletCollision/CollisionShapes/btShapeHull.cpp"
, "BulletCollision/CollisionShapes/btSphereShape.cpp"
, "BulletCollision/CollisionShapes/btStaticPlaneShape.cpp"
@@ -184,8 +186,12 @@ if env['builtin_bullet']:
thirdparty_sources = [thirdparty_dir + file for file in bullet2_src]
- env_bullet.add_source_files(env.modules_sources, thirdparty_sources)
env_bullet.Append(CPPPATH=[thirdparty_dir])
+ env_thirdparty = env_bullet.Clone()
+ env_thirdparty.disable_warnings()
+ env_thirdparty.add_source_files(env.modules_sources, thirdparty_sources)
+
+
# Godot source files
env_bullet.add_source_files(env.modules_sources, "*.cpp")
diff --git a/modules/bullet/area_bullet.cpp b/modules/bullet/area_bullet.cpp
index b004641838..a0486443c2 100644
--- a/modules/bullet/area_bullet.cpp
+++ b/modules/bullet/area_bullet.cpp
@@ -30,6 +30,7 @@
#include "area_bullet.h"
+#include "bullet_physics_server.h"
#include "bullet_types_converter.h"
#include "bullet_utilities.h"
#include "collision_object_bullet.h"
@@ -45,7 +46,6 @@
AreaBullet::AreaBullet() :
RigidCollisionObjectBullet(CollisionObjectBullet::TYPE_AREA),
monitorable(true),
- isScratched(false),
spOv_mode(PhysicsServer::AREA_SPACE_OVERRIDE_DISABLED),
spOv_gravityPoint(false),
spOv_gravityPointDistanceScale(0),
@@ -54,10 +54,11 @@ AreaBullet::AreaBullet() :
spOv_gravityMag(10),
spOv_linearDump(0.1),
spOv_angularDump(1),
- spOv_priority(0) {
+ spOv_priority(0),
+ isScratched(false) {
btGhost = bulletnew(btGhostObject);
- btGhost->setCollisionShape(compoundShape);
+ reload_shapes();
setupBulletCollisionObject(btGhost);
/// Collision objects with a callback still have collision response with dynamic rigid bodies.
/// In order to use collision objects as trigger, you have to disable the collision response.
@@ -93,6 +94,9 @@ void AreaBullet::dispatch_callbacks() {
otherObj.object->on_exit_area(this);
overlappingObjects.remove(i); // Remove after callback
break;
+ case OVERLAP_STATE_DIRTY:
+ case OVERLAP_STATE_INSIDE:
+ break;
}
}
}
@@ -162,6 +166,11 @@ bool AreaBullet::is_monitoring() const {
return get_godot_object_flags() & GOF_IS_MONITORING_AREA;
}
+void AreaBullet::main_shape_changed() {
+ CRASH_COND(!get_main_shape())
+ btGhost->setCollisionShape(get_main_shape());
+}
+
void AreaBullet::reload_body() {
if (space) {
space->remove_area(this);
@@ -236,7 +245,7 @@ void AreaBullet::set_param(PhysicsServer::AreaParameter p_param, const Variant &
set_spOv_gravityPointAttenuation(p_value);
break;
default:
- print_line("The Bullet areas doesn't suppot this param: " + itos(p_param));
+ WARN_PRINTS("Area doesn't support this parameter in the Bullet backend: " + itos(p_param));
}
}
@@ -259,7 +268,7 @@ Variant AreaBullet::get_param(PhysicsServer::AreaParameter p_param) const {
case PhysicsServer::AREA_PARAM_GRAVITY_POINT_ATTENUATION:
return spOv_gravityPointAttenuation;
default:
- print_line("The Bullet areas doesn't suppot this param: " + itos(p_param));
+ WARN_PRINTS("Area doesn't support this parameter in the Bullet backend: " + itos(p_param));
return Variant();
}
}
diff --git a/modules/bullet/area_bullet.h b/modules/bullet/area_bullet.h
index b2046c684e..1c5962cfe3 100644
--- a/modules/bullet/area_bullet.h
+++ b/modules/bullet/area_bullet.h
@@ -142,6 +142,7 @@ public:
_FORCE_INLINE_ void set_spOv_priority(int p_priority) { spOv_priority = p_priority; }
_FORCE_INLINE_ int get_spOv_priority() { return spOv_priority; }
+ virtual void main_shape_changed();
virtual void reload_body();
virtual void set_space(SpaceBullet *p_space);
@@ -156,6 +157,7 @@ public:
virtual void on_collision_filters_change();
virtual void on_collision_checker_start() {}
+ virtual void on_collision_checker_end() { isTransformChanged = false; }
void add_overlap(CollisionObjectBullet *p_otherObject);
void put_overlap_as_exit(int p_index);
diff --git a/modules/bullet/btRayShape.cpp b/modules/bullet/btRayShape.cpp
index 8707096038..6cc63d79ce 100644
--- a/modules/bullet/btRayShape.cpp
+++ b/modules/bullet/btRayShape.cpp
@@ -30,7 +30,7 @@
#include "btRayShape.h"
-#include "math/math_funcs.h"
+#include "core/math/math_funcs.h"
#include <LinearMath/btAabbUtil2.h>
diff --git a/modules/bullet/bullet_physics_server.cpp b/modules/bullet/bullet_physics_server.cpp
index 9263a9ba6d..7bc731e75e 100644
--- a/modules/bullet/bullet_physics_server.cpp
+++ b/modules/bullet/bullet_physics_server.cpp
@@ -31,8 +31,8 @@
#include "bullet_physics_server.h"
#include "bullet_utilities.h"
-#include "class_db.h"
#include "cone_twist_joint_bullet.h"
+#include "core/class_db.h"
#include "core/error_macros.h"
#include "core/ustring.h"
#include "generic_6dof_joint_bullet.h"
@@ -74,12 +74,6 @@
body->get_space()->add_constraint(joint, joint->is_disabled_collisions_between_bodies());
// <--------------- Joint creation asserts
-btEmptyShape *BulletPhysicsServer::emptyShape(ShapeBullet::create_shape_empty());
-
-btEmptyShape *BulletPhysicsServer::get_empty_shape() {
- return emptyShape;
-}
-
void BulletPhysicsServer::_bind_methods() {
//ClassDB::bind_method(D_METHOD("DoTest"), &BulletPhysicsServer::DoTest);
}
@@ -89,9 +83,7 @@ BulletPhysicsServer::BulletPhysicsServer() :
active(true),
active_spaces_count(0) {}
-BulletPhysicsServer::~BulletPhysicsServer() {
- bulletdelete(emptyShape);
-}
+BulletPhysicsServer::~BulletPhysicsServer() {}
RID BulletPhysicsServer::shape_create(ShapeType p_shape) {
ShapeBullet *shape = NULL;
@@ -163,6 +155,18 @@ Variant BulletPhysicsServer::shape_get_data(RID p_shape) const {
return shape->get_data();
}
+void BulletPhysicsServer::shape_set_margin(RID p_shape, real_t p_margin) {
+ ShapeBullet *shape = shape_owner.get(p_shape);
+ ERR_FAIL_COND(!shape);
+ shape->set_margin(p_margin);
+}
+
+real_t BulletPhysicsServer::shape_get_margin(RID p_shape) const {
+ ShapeBullet *shape = shape_owner.get(p_shape);
+ ERR_FAIL_COND_V(!shape, 0.0);
+ return shape->get_margin();
+}
+
real_t BulletPhysicsServer::shape_get_custom_solver_bias(RID p_shape) const {
//WARN_PRINT("Bias not supported by Bullet physics engine");
return 0.;
@@ -326,7 +330,7 @@ Transform BulletPhysicsServer::area_get_shape_transform(RID p_area, int p_shape_
void BulletPhysicsServer::area_remove_shape(RID p_area, int p_shape_idx) {
AreaBullet *area = area_owner.get(p_area);
ERR_FAIL_COND(!area);
- return area->remove_shape(p_shape_idx);
+ return area->remove_shape_full(p_shape_idx);
}
void BulletPhysicsServer::area_clear_shapes(RID p_area) {
@@ -334,7 +338,7 @@ void BulletPhysicsServer::area_clear_shapes(RID p_area) {
ERR_FAIL_COND(!area);
for (int i = area->get_shape_count(); 0 < i; --i)
- area->remove_shape(0);
+ area->remove_shape_full(0);
}
void BulletPhysicsServer::area_set_shape_disabled(RID p_area, int p_shape_idx, bool p_disabled) {
@@ -555,7 +559,7 @@ void BulletPhysicsServer::body_remove_shape(RID p_body, int p_shape_idx) {
RigidBodyBullet *body = rigid_body_owner.get(p_body);
ERR_FAIL_COND(!body);
- body->remove_shape(p_shape_idx);
+ body->remove_shape_full(p_shape_idx);
}
void BulletPhysicsServer::body_clear_shapes(RID p_body) {
@@ -644,20 +648,6 @@ float BulletPhysicsServer::body_get_param(RID p_body, BodyParameter p_param) con
return body->get_param(p_param);
}
-void BulletPhysicsServer::body_set_combine_mode(RID p_body, BodyParameter p_param, CombineMode p_mode) {
- RigidBodyBullet *body = rigid_body_owner.get(p_body);
- ERR_FAIL_COND(!body);
-
- body->set_combine_mode(p_param, p_mode);
-}
-
-PhysicsServer::CombineMode BulletPhysicsServer::body_get_combine_mode(RID p_body, BodyParameter p_param) const {
- RigidBodyBullet *body = rigid_body_owner.get(p_body);
- ERR_FAIL_COND_V(!body, COMBINE_MODE_INHERIT);
-
- return body->get_combine_mode(p_param);
-}
-
void BulletPhysicsServer::body_set_kinematic_safe_margin(RID p_body, real_t p_margin) {
RigidBodyBullet *body = rigid_body_owner.get(p_body);
ERR_FAIL_COND(!body);
@@ -875,12 +865,20 @@ PhysicsDirectBodyState *BulletPhysicsServer::body_get_direct_state(RID p_body) {
return BulletPhysicsDirectBodyState::get_singleton(body);
}
-bool BulletPhysicsServer::body_test_motion(RID p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, MotionResult *r_result) {
+bool BulletPhysicsServer::body_test_motion(RID p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, MotionResult *r_result, bool p_exclude_raycast_shapes) {
RigidBodyBullet *body = rigid_body_owner.get(p_body);
ERR_FAIL_COND_V(!body, false);
ERR_FAIL_COND_V(!body->get_space(), false);
- return body->get_space()->test_body_motion(body, p_from, p_motion, p_infinite_inertia, r_result);
+ return body->get_space()->test_body_motion(body, p_from, p_motion, p_infinite_inertia, r_result, p_exclude_raycast_shapes);
+}
+
+int BulletPhysicsServer::body_test_ray_separation(RID p_body, const Transform &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, SeparationResult *r_results, int p_result_max, float p_margin) {
+ RigidBodyBullet *body = rigid_body_owner.get(p_body);
+ ERR_FAIL_COND_V(!body, 0);
+ ERR_FAIL_COND_V(!body->get_space(), 0);
+
+ return body->get_space()->test_ray_separation(body, p_transform, p_infinite_inertia, r_recover_motion, r_results, p_result_max, p_margin);
}
RID BulletPhysicsServer::soft_body_create(bool p_init_sleeping) {
@@ -995,11 +993,13 @@ void BulletPhysicsServer::soft_body_get_collision_exceptions(RID p_body, List<RI
}
void BulletPhysicsServer::soft_body_set_state(RID p_body, BodyState p_state, const Variant &p_variant) {
- print_line("TODO MUST BE IMPLEMENTED");
+ // FIXME: Must be implemented.
+ WARN_PRINT("soft_body_state is not implemented yet in Bullet backend.");
}
Variant BulletPhysicsServer::soft_body_get_state(RID p_body, BodyState p_state) const {
- print_line("TODO MUST BE IMPLEMENTED");
+ // FIXME: Must be implemented.
+ WARN_PRINT("soft_body_state is not implemented yet in Bullet backend.");
return Variant();
}
@@ -1433,7 +1433,7 @@ RID BulletPhysicsServer::joint_create_generic_6dof(RID p_body_A, const Transform
ERR_FAIL_COND_V(body_A == body_B, RID());
- JointBullet *joint = bulletnew(Generic6DOFJointBullet(body_A, body_B, p_local_frame_A, p_local_frame_B, true));
+ JointBullet *joint = bulletnew(Generic6DOFJointBullet(body_A, body_B, p_local_frame_A, p_local_frame_B));
AddJointToSpace(body_A, joint);
CreateThenReturnRID(joint_owner, joint);
@@ -1471,6 +1471,22 @@ bool BulletPhysicsServer::generic_6dof_joint_get_flag(RID p_joint, Vector3::Axis
return generic_6dof_joint->get_flag(p_axis, p_flag);
}
+void BulletPhysicsServer::generic_6dof_joint_set_precision(RID p_joint, int p_precision) {
+ JointBullet *joint = joint_owner.get(p_joint);
+ ERR_FAIL_COND(!joint);
+ ERR_FAIL_COND(joint->get_type() != JOINT_6DOF);
+ Generic6DOFJointBullet *generic_6dof_joint = static_cast<Generic6DOFJointBullet *>(joint);
+ generic_6dof_joint->set_precision(p_precision);
+}
+
+int BulletPhysicsServer::generic_6dof_joint_get_precision(RID p_joint) {
+ JointBullet *joint = joint_owner.get(p_joint);
+ ERR_FAIL_COND_V(!joint, 0);
+ ERR_FAIL_COND_V(joint->get_type() != JOINT_6DOF, 0);
+ Generic6DOFJointBullet *generic_6dof_joint = static_cast<Generic6DOFJointBullet *>(joint);
+ return generic_6dof_joint->get_precision();
+}
+
void BulletPhysicsServer::free(RID p_rid) {
if (shape_owner.owns(p_rid)) {
@@ -1478,7 +1494,7 @@ void BulletPhysicsServer::free(RID p_rid) {
// Notify the shape is configured
for (Map<ShapeOwnerBullet *, int>::Element *element = shape->get_owners().front(); element; element = element->next()) {
- static_cast<ShapeOwnerBullet *>(element->key())->remove_shape(shape);
+ static_cast<ShapeOwnerBullet *>(element->key())->remove_shape_full(shape);
}
shape_owner.free(p_rid);
@@ -1489,7 +1505,7 @@ void BulletPhysicsServer::free(RID p_rid) {
body->set_space(NULL);
- body->remove_all_shapes(true);
+ body->remove_all_shapes(true, true);
rigid_body_owner.free(p_rid);
bulletdelete(body);
@@ -1509,7 +1525,7 @@ void BulletPhysicsServer::free(RID p_rid) {
area->set_space(NULL);
- area->remove_all_shapes(true);
+ area->remove_all_shapes(true, true);
area_owner.free(p_rid);
bulletdelete(area);
diff --git a/modules/bullet/bullet_physics_server.h b/modules/bullet/bullet_physics_server.h
index 2c5b7e51cf..0cea3f5ba6 100644
--- a/modules/bullet/bullet_physics_server.h
+++ b/modules/bullet/bullet_physics_server.h
@@ -32,8 +32,8 @@
#define BULLET_PHYSICS_SERVER_H
#include "area_bullet.h"
+#include "core/rid.h"
#include "joint_bullet.h"
-#include "rid.h"
#include "rigid_body_bullet.h"
#include "servers/physics_server.h"
#include "shape_bullet.h"
@@ -60,13 +60,6 @@ class BulletPhysicsServer : public PhysicsServer {
mutable RID_Owner<SoftBodyBullet> soft_body_owner;
mutable RID_Owner<JointBullet> joint_owner;
-private:
- /// This is used when a collision shape is not active, so the bullet compound shapes index are always sync with godot index
- static btEmptyShape *emptyShape;
-
-public:
- static btEmptyShape *get_empty_shape();
-
protected:
static void _bind_methods();
@@ -99,6 +92,9 @@ public:
virtual ShapeType shape_get_type(RID p_shape) const;
virtual Variant shape_get_data(RID p_shape) const;
+ virtual void shape_set_margin(RID p_shape, real_t p_margin);
+ virtual real_t shape_get_margin(RID p_shape) const;
+
/// Not supported
virtual void shape_set_custom_solver_bias(RID p_shape, real_t p_bias);
/// Not supported
@@ -213,9 +209,6 @@ public:
virtual void body_set_param(RID p_body, BodyParameter p_param, float p_value);
virtual float body_get_param(RID p_body, BodyParameter p_param) const;
- virtual void body_set_combine_mode(RID p_body, BodyParameter p_param, CombineMode p_mode);
- virtual CombineMode body_get_combine_mode(RID p_body, BodyParameter p_param) const;
-
virtual void body_set_kinematic_safe_margin(RID p_body, real_t p_margin);
virtual real_t body_get_kinematic_safe_margin(RID p_body) const;
@@ -261,7 +254,8 @@ public:
// this function only works on physics process, errors and returns null otherwise
virtual PhysicsDirectBodyState *body_get_direct_state(RID p_body);
- virtual bool body_test_motion(RID p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, MotionResult *r_result = NULL);
+ virtual bool body_test_motion(RID p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, MotionResult *r_result = NULL, bool p_exclude_raycast_shapes = true);
+ virtual int body_test_ray_separation(RID p_body, const Transform &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, SeparationResult *r_results, int p_result_max, float p_margin = 0.001);
/* SOFT BODY API */
@@ -381,6 +375,9 @@ public:
virtual void generic_6dof_joint_set_flag(RID p_joint, Vector3::Axis p_axis, G6DOFJointAxisFlag p_flag, bool p_enable);
virtual bool generic_6dof_joint_get_flag(RID p_joint, Vector3::Axis p_axis, G6DOFJointAxisFlag p_flag);
+ virtual void generic_6dof_joint_set_precision(RID p_joint, int precision);
+ virtual int generic_6dof_joint_get_precision(RID p_joint);
+
/* MISC */
virtual void free(RID p_rid);
@@ -403,6 +400,8 @@ public:
virtual void flush_queries();
virtual void finish();
+ virtual bool is_flushing_queries() const { return false; }
+
virtual int get_process_info(ProcessInfo p_info);
CollisionObjectBullet *get_collisin_object(RID p_object) const;
diff --git a/modules/bullet/bullet_types_converter.cpp b/modules/bullet/bullet_types_converter.cpp
index a0fe598227..f9b7126173 100644
--- a/modules/bullet/bullet_types_converter.cpp
+++ b/modules/bullet/bullet_types_converter.cpp
@@ -28,8 +28,6 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#pragma once
-
#include "bullet_types_converter.h"
/**
diff --git a/modules/bullet/bullet_utilities.h b/modules/bullet/bullet_utilities.h
index 2841dfbe69..553c1d0384 100644
--- a/modules/bullet/bullet_utilities.h
+++ b/modules/bullet/bullet_utilities.h
@@ -35,13 +35,12 @@
@author AndreaCatania
*/
-#pragma once
-
#define bulletnew(cl) \
new cl
#define bulletdelete(cl) \
- delete cl; \
- cl = NULL;
-
+ { \
+ delete cl; \
+ cl = NULL; \
+ }
#endif
diff --git a/modules/bullet/collision_object_bullet.cpp b/modules/bullet/collision_object_bullet.cpp
index 271cdb0223..441fa7c8af 100644
--- a/modules/bullet/collision_object_bullet.cpp
+++ b/modules/bullet/collision_object_bullet.cpp
@@ -43,8 +43,7 @@
@author AndreaCatania
*/
-#define enableDynamicAabbTree true
-#define initialChildCapacity 1
+#define enableDynamicAabbTree false
CollisionObjectBullet::ShapeWrapper::~ShapeWrapper() {}
@@ -53,19 +52,30 @@ void CollisionObjectBullet::ShapeWrapper::set_transform(const Transform &p_trans
G_TO_B(p_transform, transform);
UNSCALE_BT_BASIS(transform);
}
+
void CollisionObjectBullet::ShapeWrapper::set_transform(const btTransform &p_transform) {
transform = p_transform;
}
+void CollisionObjectBullet::ShapeWrapper::claim_bt_shape(const btVector3 &body_scale) {
+ if (!bt_shape) {
+ if (active)
+ bt_shape = shape->create_bt_shape(scale * body_scale);
+ else
+ bt_shape = ShapeBullet::create_shape_empty();
+ }
+}
+
CollisionObjectBullet::CollisionObjectBullet(Type p_type) :
RIDBullet(),
- space(NULL),
type(p_type),
collisionsEnabled(true),
m_isStatic(false),
bt_collision_object(NULL),
body_scale(1., 1., 1.),
- force_shape_reset(false) {}
+ force_shape_reset(false),
+ space(NULL),
+ isTransformChanged(false) {}
CollisionObjectBullet::~CollisionObjectBullet() {
// Remove all overlapping, notify is not required since godot take care of it
@@ -83,7 +93,7 @@ bool equal(real_t first, real_t second) {
void CollisionObjectBullet::set_body_scale(const Vector3 &p_new_scale) {
if (!equal(p_new_scale[0], body_scale[0]) || !equal(p_new_scale[1], body_scale[1]) || !equal(p_new_scale[2], body_scale[2])) {
body_scale = p_new_scale;
- on_body_scale_changed();
+ body_scale_changed();
}
}
@@ -93,7 +103,7 @@ btVector3 CollisionObjectBullet::get_bt_body_scale() const {
return s;
}
-void CollisionObjectBullet::on_body_scale_changed() {
+void CollisionObjectBullet::body_scale_changed() {
force_shape_reset = true;
}
@@ -107,6 +117,7 @@ void CollisionObjectBullet::setupBulletCollisionObject(btCollisionObject *p_coll
bt_collision_object->setUserIndex(type);
// Force the enabling of collision and avoid problems
set_collision_enabled(collisionsEnabled);
+ p_collisionObject->setCollisionFlags(p_collisionObject->getCollisionFlags() | btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK);
}
void CollisionObjectBullet::add_collision_exception(const CollisionObjectBullet *p_ignoreCollisionObject) {
@@ -178,48 +189,33 @@ Transform CollisionObjectBullet::get_transform() const {
void CollisionObjectBullet::set_transform__bullet(const btTransform &p_global_transform) {
bt_collision_object->setWorldTransform(p_global_transform);
+ notify_transform_changed();
}
const btTransform &CollisionObjectBullet::get_transform__bullet() const {
return bt_collision_object->getWorldTransform();
}
+void CollisionObjectBullet::notify_transform_changed() {
+ isTransformChanged = true;
+}
+
RigidCollisionObjectBullet::RigidCollisionObjectBullet(Type p_type) :
CollisionObjectBullet(p_type),
- compoundShape(bulletnew(btCompoundShape(enableDynamicAabbTree, initialChildCapacity))) {
+ mainShape(NULL) {
}
RigidCollisionObjectBullet::~RigidCollisionObjectBullet() {
- remove_all_shapes(true);
- bt_collision_object->setCollisionShape(NULL);
- bulletdelete(compoundShape);
-}
-
-/* Not used
-void RigidCollisionObjectBullet::_internal_replaceShape(btCollisionShape *p_old_shape, btCollisionShape *p_new_shape) {
- bool at_least_one_was_changed = false;
- btTransform old_transf;
- // Inverse because I need remove the shapes
- // Fetch all shapes to be sure to remove all shapes
- for (int i = compoundShape->getNumChildShapes() - 1; 0 <= i; --i) {
- if (compoundShape->getChildShape(i) == p_old_shape) {
-
- old_transf = compoundShape->getChildTransform(i);
- compoundShape->removeChildShapeByIndex(i);
- compoundShape->addChildShape(old_transf, p_new_shape);
- at_least_one_was_changed = true;
- }
+ remove_all_shapes(true, true);
+ if (mainShape && mainShape->isCompound()) {
+ bulletdelete(mainShape);
}
-
- if (at_least_one_was_changed) {
- on_shapes_changed();
- }
-}*/
+}
void RigidCollisionObjectBullet::add_shape(ShapeBullet *p_shape, const Transform &p_transform) {
shapes.push_back(ShapeWrapper(p_shape, p_transform, true));
p_shape->add_owner(this);
- on_shapes_changed();
+ reload_shapes();
}
void RigidCollisionObjectBullet::set_shape(int p_index, ShapeBullet *p_shape) {
@@ -227,17 +223,31 @@ void RigidCollisionObjectBullet::set_shape(int p_index, ShapeBullet *p_shape) {
shp.shape->remove_owner(this);
p_shape->add_owner(this);
shp.shape = p_shape;
- on_shapes_changed();
+ reload_shapes();
}
-void RigidCollisionObjectBullet::set_shape_transform(int p_index, const Transform &p_transform) {
- ERR_FAIL_INDEX(p_index, get_shape_count());
+int RigidCollisionObjectBullet::get_shape_count() const {
+ return shapes.size();
+}
- shapes.write[p_index].set_transform(p_transform);
- on_shape_changed(shapes.write[p_index].shape);
+ShapeBullet *RigidCollisionObjectBullet::get_shape(int p_index) const {
+ return shapes[p_index].shape;
+}
+
+btCollisionShape *RigidCollisionObjectBullet::get_bt_shape(int p_index) const {
+ return shapes[p_index].bt_shape;
+}
+
+int RigidCollisionObjectBullet::find_shape(ShapeBullet *p_shape) const {
+ const int size = shapes.size();
+ for (int i = 0; i < size; ++i) {
+ if (shapes[i].shape == p_shape)
+ return i;
+ }
+ return -1;
}
-void RigidCollisionObjectBullet::remove_shape(ShapeBullet *p_shape) {
+void RigidCollisionObjectBullet::remove_shape_full(ShapeBullet *p_shape) {
// Remove the shape, all the times it appears
// Reverse order required for delete.
for (int i = shapes.size() - 1; 0 <= i; --i) {
@@ -246,35 +256,36 @@ void RigidCollisionObjectBullet::remove_shape(ShapeBullet *p_shape) {
shapes.remove(i);
}
}
- on_shapes_changed();
+ reload_shapes();
}
-void RigidCollisionObjectBullet::remove_shape(int p_index) {
+void RigidCollisionObjectBullet::remove_shape_full(int p_index) {
ERR_FAIL_INDEX(p_index, get_shape_count());
internal_shape_destroy(p_index);
shapes.remove(p_index);
- on_shapes_changed();
+ reload_shapes();
}
-void RigidCollisionObjectBullet::remove_all_shapes(bool p_permanentlyFromThisBody) {
+void RigidCollisionObjectBullet::remove_all_shapes(bool p_permanentlyFromThisBody, bool p_force_not_reload) {
// Reverse order required for delete.
for (int i = shapes.size() - 1; 0 <= i; --i) {
internal_shape_destroy(i, p_permanentlyFromThisBody);
}
shapes.clear();
- on_shapes_changed();
+ if (!p_force_not_reload)
+ reload_shapes();
}
-int RigidCollisionObjectBullet::get_shape_count() const {
- return shapes.size();
-}
+void RigidCollisionObjectBullet::set_shape_transform(int p_index, const Transform &p_transform) {
+ ERR_FAIL_INDEX(p_index, get_shape_count());
-ShapeBullet *RigidCollisionObjectBullet::get_shape(int p_index) const {
- return shapes[p_index].shape;
+ shapes.write[p_index].set_transform(p_transform);
+ // Note, enableDynamicAabbTree is false because on transform change compound is destroyed
+ reload_shapes();
}
-btCollisionShape *RigidCollisionObjectBullet::get_bt_shape(int p_index) const {
- return shapes[p_index].bt_shape;
+const btTransform &RigidCollisionObjectBullet::get_bt_shape_transform(int p_index) const {
+ return shapes[p_index].transform;
}
Transform RigidCollisionObjectBullet::get_shape_transform(int p_index) const {
@@ -283,72 +294,84 @@ Transform RigidCollisionObjectBullet::get_shape_transform(int p_index) const {
return trs;
}
-void RigidCollisionObjectBullet::on_shape_changed(const ShapeBullet *const p_shape) {
- const int size = shapes.size();
- for (int i = 0; i < size; ++i) {
- if (shapes[i].shape == p_shape) {
- bulletdelete(shapes.write[i].bt_shape);
- }
+void RigidCollisionObjectBullet::set_shape_disabled(int p_index, bool p_disabled) {
+ shapes.write[p_index].active = !p_disabled;
+ shape_changed(p_index);
+}
+
+bool RigidCollisionObjectBullet::is_shape_disabled(int p_index) {
+ return !shapes[p_index].active;
+}
+
+void RigidCollisionObjectBullet::shape_changed(int p_shape_index) {
+ ShapeWrapper &shp = shapes.write[p_shape_index];
+ if (shp.bt_shape == mainShape) {
+ mainShape = NULL;
}
- on_shapes_changed();
+ bulletdelete(shp.bt_shape);
+ reload_shapes();
}
-void RigidCollisionObjectBullet::on_shapes_changed() {
- int i;
+void RigidCollisionObjectBullet::reload_shapes() {
- // Remove all shapes, reverse order for performance reason (Array resize)
- for (i = compoundShape->getNumChildShapes() - 1; 0 <= i; --i) {
- compoundShape->removeChildShapeByIndex(i);
+ if (mainShape && mainShape->isCompound()) {
+ // Destroy compound
+ bulletdelete(mainShape);
}
+ mainShape = NULL;
+
ShapeWrapper *shpWrapper;
- const int shapes_size = shapes.size();
+ const int shape_count = shapes.size();
// Reset shape if required
if (force_shape_reset) {
- for (i = 0; i < shapes_size; ++i) {
+ for (int i(0); i < shape_count; ++i) {
shpWrapper = &shapes.write[i];
bulletdelete(shpWrapper->bt_shape);
}
force_shape_reset = false;
}
- // Insert all shapes
- btVector3 body_scale(get_bt_body_scale());
- for (i = 0; i < shapes_size; ++i) {
- shpWrapper = &shapes.write[i];
- if (shpWrapper->active) {
- if (!shpWrapper->bt_shape) {
- shpWrapper->bt_shape = shpWrapper->shape->create_bt_shape(shpWrapper->scale * body_scale);
- }
-
- btTransform scaled_shape_transform(shpWrapper->transform);
- scaled_shape_transform.getOrigin() *= body_scale;
- compoundShape->addChildShape(scaled_shape_transform, shpWrapper->bt_shape);
- } else {
- compoundShape->addChildShape(btTransform(), BulletPhysicsServer::get_empty_shape());
+ const btVector3 body_scale(get_bt_body_scale());
+
+ // Try to optimize by not using compound
+ if (1 == shape_count) {
+ shpWrapper = &shapes.write[0];
+ if (shpWrapper->transform.getOrigin().isZero() && shpWrapper->transform.getBasis() == shpWrapper->transform.getBasis().getIdentity()) {
+ shpWrapper->claim_bt_shape(body_scale);
+ mainShape = shpWrapper->bt_shape;
+ main_shape_changed();
+ return;
}
}
- compoundShape->recalculateLocalAabb();
-}
+ // Optimization not possible use a compound shape
+ btCompoundShape *compoundShape = bulletnew(btCompoundShape(enableDynamicAabbTree, shape_count));
-void RigidCollisionObjectBullet::set_shape_disabled(int p_index, bool p_disabled) {
- shapes.write[p_index].active = !p_disabled;
- on_shapes_changed();
-}
+ for (int i(0); i < shape_count; ++i) {
+ shpWrapper = &shapes.write[i];
+ shpWrapper->claim_bt_shape(body_scale);
+ btTransform scaled_shape_transform(shpWrapper->transform);
+ scaled_shape_transform.getOrigin() *= body_scale;
+ compoundShape->addChildShape(scaled_shape_transform, shpWrapper->bt_shape);
+ }
-bool RigidCollisionObjectBullet::is_shape_disabled(int p_index) {
- return !shapes[p_index].active;
+ compoundShape->recalculateLocalAabb();
+ mainShape = compoundShape;
+ main_shape_changed();
}
-void RigidCollisionObjectBullet::on_body_scale_changed() {
- CollisionObjectBullet::on_body_scale_changed();
- on_shapes_changed();
+void RigidCollisionObjectBullet::body_scale_changed() {
+ CollisionObjectBullet::body_scale_changed();
+ reload_shapes();
}
void RigidCollisionObjectBullet::internal_shape_destroy(int p_index, bool p_permanentlyFromThisBody) {
ShapeWrapper &shp = shapes.write[p_index];
shp.shape->remove_owner(this, p_permanentlyFromThisBody);
+ if (shp.bt_shape == mainShape) {
+ mainShape = NULL;
+ }
bulletdelete(shp.bt_shape);
}
diff --git a/modules/bullet/collision_object_bullet.h b/modules/bullet/collision_object_bullet.h
index 506976eabf..4a0c805ce5 100644
--- a/modules/bullet/collision_object_bullet.h
+++ b/modules/bullet/collision_object_bullet.h
@@ -31,11 +31,11 @@
#ifndef COLLISION_OBJECT_BULLET_H
#define COLLISION_OBJECT_BULLET_H
+#include "core/math/transform.h"
+#include "core/math/vector3.h"
+#include "core/object.h"
#include "core/vset.h"
-#include "object.h"
#include "shape_owner_bullet.h"
-#include "transform.h"
-#include "vector3.h"
#include <LinearMath/btTransform.h>
@@ -109,6 +109,8 @@ public:
void set_transform(const Transform &p_transform);
void set_transform(const btTransform &p_transform);
+
+ void claim_bt_shape(const btVector3 &body_scale);
};
protected:
@@ -130,6 +132,7 @@ protected:
/// New area is added when overlap with new area (AreaBullet::addOverlap), then is removed when it exit (CollisionObjectBullet::onExitArea)
/// This array is used mainly to know which area hold the pointer of this object
Vector<AreaBullet *> areasOverlapped;
+ bool isTransformChanged;
public:
CollisionObjectBullet(Type p_type);
@@ -155,7 +158,7 @@ public:
void set_body_scale(const Vector3 &p_new_scale);
const Vector3 &get_body_scale() const { return body_scale; }
btVector3 get_bt_body_scale() const;
- virtual void on_body_scale_changed();
+ virtual void body_scale_changed();
void add_collision_exception(const CollisionObjectBullet *p_ignoreCollisionObject);
void remove_collision_exception(const CollisionObjectBullet *p_ignoreCollisionObject);
@@ -183,8 +186,9 @@ public:
virtual void reload_body() = 0;
virtual void set_space(SpaceBullet *p_space) = 0;
_FORCE_INLINE_ SpaceBullet *get_space() const { return space; }
- /// This is an event that is called when a collision checker starts
+
virtual void on_collision_checker_start() = 0;
+ virtual void on_collision_checker_end() = 0;
virtual void dispatch_callbacks() = 0;
@@ -195,7 +199,6 @@ public:
virtual void on_enter_area(AreaBullet *p_area) = 0;
virtual void on_exit_area(AreaBullet *p_area);
- /// GodotObjectFlags
void set_godot_object_flags(int flags);
int get_godot_object_flags() const;
@@ -203,14 +206,14 @@ public:
Transform get_transform() const;
virtual void set_transform__bullet(const btTransform &p_global_transform);
virtual const btTransform &get_transform__bullet() const;
+
+ bool is_transform_changed() const { return isTransformChanged; }
+ virtual void notify_transform_changed();
};
class RigidCollisionObjectBullet : public CollisionObjectBullet, public ShapeOwnerBullet {
protected:
- /// This is required to combine some shapes together.
- /// Since Godot allow to have multiple shapes for each body with custom relative location,
- /// each body will attach the shapes using this class even if there is only one shape.
- btCompoundShape *compoundShape;
+ btCollisionShape *mainShape;
Vector<ShapeWrapper> shapes;
public:
@@ -219,28 +222,34 @@ public:
_FORCE_INLINE_ const Vector<ShapeWrapper> &get_shapes_wrappers() const { return shapes; }
- /// This is used to set new shape or replace existing
- //virtual void _internal_replaceShape(btCollisionShape *p_old_shape, btCollisionShape *p_new_shape) = 0;
+ _FORCE_INLINE_ btCollisionShape *get_main_shape() const { return mainShape; }
+
void add_shape(ShapeBullet *p_shape, const Transform &p_transform = Transform());
void set_shape(int p_index, ShapeBullet *p_shape);
- void set_shape_transform(int p_index, const Transform &p_transform);
- virtual void remove_shape(ShapeBullet *p_shape);
- void remove_shape(int p_index);
- void remove_all_shapes(bool p_permanentlyFromThisBody = false);
-
- virtual void on_shape_changed(const ShapeBullet *const p_shape);
- virtual void on_shapes_changed();
- _FORCE_INLINE_ btCompoundShape *get_compound_shape() const { return compoundShape; }
int get_shape_count() const;
ShapeBullet *get_shape(int p_index) const;
btCollisionShape *get_bt_shape(int p_index) const;
+
+ int find_shape(ShapeBullet *p_shape) const;
+
+ virtual void remove_shape_full(ShapeBullet *p_shape);
+ void remove_shape_full(int p_index);
+ void remove_all_shapes(bool p_permanentlyFromThisBody = false, bool p_force_not_reload = false);
+
+ void set_shape_transform(int p_index, const Transform &p_transform);
+
+ const btTransform &get_bt_shape_transform(int p_index) const;
Transform get_shape_transform(int p_index) const;
void set_shape_disabled(int p_index, bool p_disabled);
bool is_shape_disabled(int p_index);
- virtual void on_body_scale_changed();
+ virtual void shape_changed(int p_shape_index);
+ virtual void reload_shapes();
+
+ virtual void main_shape_changed() = 0;
+ virtual void body_scale_changed();
private:
void internal_shape_destroy(int p_index, bool p_permanentlyFromThisBody = false);
diff --git a/modules/bullet/cone_twist_joint_bullet.cpp b/modules/bullet/cone_twist_joint_bullet.cpp
index 472ad3b52c..ecacce0bee 100644
--- a/modules/bullet/cone_twist_joint_bullet.cpp
+++ b/modules/bullet/cone_twist_joint_bullet.cpp
@@ -64,26 +64,6 @@ ConeTwistJointBullet::ConeTwistJointBullet(RigidBodyBullet *rbA, RigidBodyBullet
setup(coneConstraint);
}
-void ConeTwistJointBullet::set_angular_only(bool angularOnly) {
- coneConstraint->setAngularOnly(angularOnly);
-}
-
-void ConeTwistJointBullet::set_limit(real_t _swingSpan1, real_t _swingSpan2, real_t _twistSpan, real_t _softness, real_t _biasFactor, real_t _relaxationFactor) {
- coneConstraint->setLimit(_swingSpan1, _swingSpan2, _twistSpan, _softness, _biasFactor, _relaxationFactor);
-}
-
-int ConeTwistJointBullet::get_solve_twist_limit() {
- return coneConstraint->getSolveTwistLimit();
-}
-
-int ConeTwistJointBullet::get_solve_swing_limit() {
- return coneConstraint->getSolveSwingLimit();
-}
-
-real_t ConeTwistJointBullet::get_twist_limit_sign() {
- return coneConstraint->getTwistLimitSign();
-}
-
void ConeTwistJointBullet::set_param(PhysicsServer::ConeTwistJointParam p_param, real_t p_value) {
switch (p_param) {
case PhysicsServer::CONE_TWIST_JOINT_SWING_SPAN:
@@ -103,7 +83,9 @@ void ConeTwistJointBullet::set_param(PhysicsServer::ConeTwistJointParam p_param,
coneConstraint->setLimit(coneConstraint->getSwingSpan1(), coneConstraint->getSwingSpan2(), coneConstraint->getTwistSpan(), coneConstraint->getLimitSoftness(), coneConstraint->getBiasFactor(), p_value);
break;
default:
- WARN_PRINT("This parameter is not supported by Bullet engine");
+ ERR_EXPLAIN("This parameter " + itos(p_param) + " is deprecated");
+ WARN_DEPRECATED
+ break;
}
}
@@ -120,7 +102,8 @@ real_t ConeTwistJointBullet::get_param(PhysicsServer::ConeTwistJointParam p_para
case PhysicsServer::CONE_TWIST_JOINT_RELAXATION:
return coneConstraint->getRelaxationFactor();
default:
- WARN_PRINT("This parameter is not supported by Bullet engine");
+ ERR_EXPLAIN("This parameter " + itos(p_param) + " is deprecated");
+ WARN_DEPRECATED;
return 0;
}
}
diff --git a/modules/bullet/cone_twist_joint_bullet.h b/modules/bullet/cone_twist_joint_bullet.h
index bd6eb49196..d6040fd6ec 100644
--- a/modules/bullet/cone_twist_joint_bullet.h
+++ b/modules/bullet/cone_twist_joint_bullet.h
@@ -47,14 +47,6 @@ public:
virtual PhysicsServer::JointType get_type() const { return PhysicsServer::JOINT_CONE_TWIST; }
- void set_angular_only(bool angularOnly);
-
- void set_limit(real_t _swingSpan1, real_t _swingSpan2, real_t _twistSpan, real_t _softness = 0.8f, real_t _biasFactor = 0.3f, real_t _relaxationFactor = 1.0f);
- int get_solve_twist_limit();
-
- int get_solve_swing_limit();
- real_t get_twist_limit_sign();
-
void set_param(PhysicsServer::ConeTwistJointParam p_param, real_t p_value);
real_t get_param(PhysicsServer::ConeTwistJointParam p_param) const;
};
diff --git a/modules/bullet/generic_6dof_joint_bullet.cpp b/modules/bullet/generic_6dof_joint_bullet.cpp
index adfad7803f..812dcd2d56 100644
--- a/modules/bullet/generic_6dof_joint_bullet.cpp
+++ b/modules/bullet/generic_6dof_joint_bullet.cpp
@@ -34,13 +34,13 @@
#include "bullet_utilities.h"
#include "rigid_body_bullet.h"
-#include <BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h>
+#include <BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.h>
/**
@author AndreaCatania
*/
-Generic6DOFJointBullet::Generic6DOFJointBullet(RigidBodyBullet *rbA, RigidBodyBullet *rbB, const Transform &frameInA, const Transform &frameInB, bool useLinearReferenceFrameA) :
+Generic6DOFJointBullet::Generic6DOFJointBullet(RigidBodyBullet *rbA, RigidBodyBullet *rbB, const Transform &frameInA, const Transform &frameInB) :
JointBullet() {
Transform scaled_AFrame(frameInA.scaled(rbA->get_body_scale()));
@@ -58,9 +58,9 @@ Generic6DOFJointBullet::Generic6DOFJointBullet(RigidBodyBullet *rbA, RigidBodyBu
btTransform btFrameB;
G_TO_B(scaled_BFrame, btFrameB);
- sixDOFConstraint = bulletnew(btGeneric6DofConstraint(*rbA->get_bt_rigid_body(), *rbB->get_bt_rigid_body(), btFrameA, btFrameB, useLinearReferenceFrameA));
+ sixDOFConstraint = bulletnew(btGeneric6DofSpring2Constraint(*rbA->get_bt_rigid_body(), *rbB->get_bt_rigid_body(), btFrameA, btFrameB));
} else {
- sixDOFConstraint = bulletnew(btGeneric6DofConstraint(*rbA->get_bt_rigid_body(), btFrameA, useLinearReferenceFrameA));
+ sixDOFConstraint = bulletnew(btGeneric6DofSpring2Constraint(*rbA->get_bt_rigid_body(), btFrameA));
}
setup(sixDOFConstraint);
@@ -123,20 +123,11 @@ void Generic6DOFJointBullet::set_param(Vector3::Axis p_axis, PhysicsServer::G6DO
switch (p_param) {
case PhysicsServer::G6DOF_JOINT_LINEAR_LOWER_LIMIT:
limits_lower[0][p_axis] = p_value;
- set_flag(p_axis, PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_LIMIT, flags[p_axis][p_param]); // Reload bullet parameter
+ set_flag(p_axis, PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_LIMIT, flags[p_axis][PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_LIMIT]); // Reload bullet parameter
break;
case PhysicsServer::G6DOF_JOINT_LINEAR_UPPER_LIMIT:
limits_upper[0][p_axis] = p_value;
- set_flag(p_axis, PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_LIMIT, flags[p_axis][p_param]); // Reload bullet parameter
- break;
- case PhysicsServer::G6DOF_JOINT_LINEAR_LIMIT_SOFTNESS:
- sixDOFConstraint->getTranslationalLimitMotor()->m_limitSoftness = p_value;
- break;
- case PhysicsServer::G6DOF_JOINT_LINEAR_RESTITUTION:
- sixDOFConstraint->getTranslationalLimitMotor()->m_restitution = p_value;
- break;
- case PhysicsServer::G6DOF_JOINT_LINEAR_DAMPING:
- sixDOFConstraint->getTranslationalLimitMotor()->m_damping = p_value;
+ set_flag(p_axis, PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_LIMIT, flags[p_axis][PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_LIMIT]); // Reload bullet parameter
break;
case PhysicsServer::G6DOF_JOINT_LINEAR_MOTOR_TARGET_VELOCITY:
sixDOFConstraint->getTranslationalLimitMotor()->m_targetVelocity.m_floats[p_axis] = p_value;
@@ -144,26 +135,26 @@ void Generic6DOFJointBullet::set_param(Vector3::Axis p_axis, PhysicsServer::G6DO
case PhysicsServer::G6DOF_JOINT_LINEAR_MOTOR_FORCE_LIMIT:
sixDOFConstraint->getTranslationalLimitMotor()->m_maxMotorForce.m_floats[p_axis] = p_value;
break;
+ case PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_DAMPING:
+ sixDOFConstraint->getTranslationalLimitMotor()->m_springDamping.m_floats[p_axis] = p_value;
+ break;
+ case PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_STIFFNESS:
+ sixDOFConstraint->getTranslationalLimitMotor()->m_springStiffness.m_floats[p_axis] = p_value;
+ break;
+ case PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_EQUILIBRIUM_POINT:
+ sixDOFConstraint->getTranslationalLimitMotor()->m_equilibriumPoint.m_floats[p_axis] = p_value;
+ break;
case PhysicsServer::G6DOF_JOINT_ANGULAR_LOWER_LIMIT:
limits_lower[1][p_axis] = p_value;
- set_flag(p_axis, PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT, flags[p_axis][p_param]); // Reload bullet parameter
+ set_flag(p_axis, PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT, flags[p_axis][PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT]); // Reload bullet parameter
break;
case PhysicsServer::G6DOF_JOINT_ANGULAR_UPPER_LIMIT:
limits_upper[1][p_axis] = p_value;
- set_flag(p_axis, PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_LIMIT, flags[p_axis][p_param]); // Reload bullet parameter
- break;
- case PhysicsServer::G6DOF_JOINT_ANGULAR_LIMIT_SOFTNESS:
- sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_limitSoftness = p_value;
- break;
- case PhysicsServer::G6DOF_JOINT_ANGULAR_DAMPING:
- sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_damping = p_value;
+ set_flag(p_axis, PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT, flags[p_axis][PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT]); // Reload bullet parameter
break;
case PhysicsServer::G6DOF_JOINT_ANGULAR_RESTITUTION:
sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_bounce = p_value;
break;
- case PhysicsServer::G6DOF_JOINT_ANGULAR_FORCE_LIMIT:
- sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_maxLimitForce = p_value;
- break;
case PhysicsServer::G6DOF_JOINT_ANGULAR_ERP:
sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_stopERP = p_value;
break;
@@ -171,10 +162,21 @@ void Generic6DOFJointBullet::set_param(Vector3::Axis p_axis, PhysicsServer::G6DO
sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_targetVelocity = p_value;
break;
case PhysicsServer::G6DOF_JOINT_ANGULAR_MOTOR_FORCE_LIMIT:
- sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_maxLimitForce = p_value;
+ sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_maxMotorForce = p_value;
+ break;
+ case PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_STIFFNESS:
+ sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_springStiffness = p_value;
+ break;
+ case PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_DAMPING:
+ sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_springDamping = p_value;
+ break;
+ case PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_EQUILIBRIUM_POINT:
+ sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_equilibriumPoint = p_value;
break;
default:
- WARN_PRINT("This parameter is not supported");
+ ERR_EXPLAIN("This parameter " + itos(p_param) + " is deprecated");
+ WARN_DEPRECATED
+ break;
}
}
@@ -185,37 +187,38 @@ real_t Generic6DOFJointBullet::get_param(Vector3::Axis p_axis, PhysicsServer::G6
return limits_lower[0][p_axis];
case PhysicsServer::G6DOF_JOINT_LINEAR_UPPER_LIMIT:
return limits_upper[0][p_axis];
- case PhysicsServer::G6DOF_JOINT_LINEAR_LIMIT_SOFTNESS:
- return sixDOFConstraint->getTranslationalLimitMotor()->m_limitSoftness;
- case PhysicsServer::G6DOF_JOINT_LINEAR_RESTITUTION:
- return sixDOFConstraint->getTranslationalLimitMotor()->m_restitution;
- case PhysicsServer::G6DOF_JOINT_LINEAR_DAMPING:
- return sixDOFConstraint->getTranslationalLimitMotor()->m_damping;
case PhysicsServer::G6DOF_JOINT_LINEAR_MOTOR_TARGET_VELOCITY:
return sixDOFConstraint->getTranslationalLimitMotor()->m_targetVelocity.m_floats[p_axis];
case PhysicsServer::G6DOF_JOINT_LINEAR_MOTOR_FORCE_LIMIT:
return sixDOFConstraint->getTranslationalLimitMotor()->m_maxMotorForce.m_floats[p_axis];
+ case PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_DAMPING:
+ return sixDOFConstraint->getTranslationalLimitMotor()->m_springDamping.m_floats[p_axis];
+ case PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_STIFFNESS:
+ return sixDOFConstraint->getTranslationalLimitMotor()->m_springStiffness.m_floats[p_axis];
+ case PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_EQUILIBRIUM_POINT:
+ return sixDOFConstraint->getTranslationalLimitMotor()->m_equilibriumPoint.m_floats[p_axis];
case PhysicsServer::G6DOF_JOINT_ANGULAR_LOWER_LIMIT:
return limits_lower[1][p_axis];
case PhysicsServer::G6DOF_JOINT_ANGULAR_UPPER_LIMIT:
return limits_upper[1][p_axis];
- case PhysicsServer::G6DOF_JOINT_ANGULAR_LIMIT_SOFTNESS:
- return sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_limitSoftness;
- case PhysicsServer::G6DOF_JOINT_ANGULAR_DAMPING:
- return sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_damping;
case PhysicsServer::G6DOF_JOINT_ANGULAR_RESTITUTION:
return sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_bounce;
- case PhysicsServer::G6DOF_JOINT_ANGULAR_FORCE_LIMIT:
- return sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_maxLimitForce;
case PhysicsServer::G6DOF_JOINT_ANGULAR_ERP:
return sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_stopERP;
case PhysicsServer::G6DOF_JOINT_ANGULAR_MOTOR_TARGET_VELOCITY:
return sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_targetVelocity;
case PhysicsServer::G6DOF_JOINT_ANGULAR_MOTOR_FORCE_LIMIT:
- return sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_maxLimitForce;
+ return sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_maxMotorForce;
+ case PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_STIFFNESS:
+ return sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_springStiffness;
+ case PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_DAMPING:
+ return sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_springDamping;
+ case PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_EQUILIBRIUM_POINT:
+ return sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_equilibriumPoint;
default:
- WARN_PRINT("This parameter is not supported");
- return 0.;
+ ERR_EXPLAIN("This parameter " + itos(p_param) + " is deprecated");
+ WARN_DEPRECATED;
+ return 0;
}
}
@@ -245,14 +248,28 @@ void Generic6DOFJointBullet::set_flag(Vector3::Axis p_axis, PhysicsServer::G6DOF
case PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_MOTOR:
sixDOFConstraint->getTranslationalLimitMotor()->m_enableMotor[p_axis] = flags[p_axis][p_flag];
break;
+ case PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_SPRING:
+ sixDOFConstraint->getTranslationalLimitMotor()->m_enableSpring[p_axis] = p_value;
+ break;
+ case PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_SPRING:
+ sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_enableSpring = p_value;
+ break;
default:
- WARN_PRINT("This flag is not supported by Bullet engine");
- return;
+ ERR_EXPLAIN("This flag " + itos(p_flag) + " is deprecated");
+ WARN_DEPRECATED
+ break;
}
}
bool Generic6DOFJointBullet::get_flag(Vector3::Axis p_axis, PhysicsServer::G6DOFJointAxisFlag p_flag) const {
ERR_FAIL_INDEX_V(p_axis, 3, false);
-
return flags[p_axis][p_flag];
}
+
+void Generic6DOFJointBullet::set_precision(int p_precision) {
+ sixDOFConstraint->setOverrideNumSolverIterations(MAX(1, p_precision));
+}
+
+int Generic6DOFJointBullet::get_precision() const {
+ return sixDOFConstraint->getOverrideNumSolverIterations();
+}
diff --git a/modules/bullet/generic_6dof_joint_bullet.h b/modules/bullet/generic_6dof_joint_bullet.h
index ad06582eac..848c3a10cd 100644
--- a/modules/bullet/generic_6dof_joint_bullet.h
+++ b/modules/bullet/generic_6dof_joint_bullet.h
@@ -40,7 +40,7 @@
class RigidBodyBullet;
class Generic6DOFJointBullet : public JointBullet {
- class btGeneric6DofConstraint *sixDOFConstraint;
+ class btGeneric6DofSpring2Constraint *sixDOFConstraint;
// First is linear second is angular
Vector3 limits_lower[2];
@@ -48,7 +48,7 @@ class Generic6DOFJointBullet : public JointBullet {
bool flags[3][PhysicsServer::G6DOF_JOINT_FLAG_MAX];
public:
- Generic6DOFJointBullet(RigidBodyBullet *rbA, RigidBodyBullet *rbB, const Transform &frameInA, const Transform &frameInB, bool useLinearReferenceFrameA);
+ Generic6DOFJointBullet(RigidBodyBullet *rbA, RigidBodyBullet *rbB, const Transform &frameInA, const Transform &frameInB);
virtual PhysicsServer::JointType get_type() const { return PhysicsServer::JOINT_6DOF; }
@@ -68,6 +68,9 @@ public:
void set_flag(Vector3::Axis p_axis, PhysicsServer::G6DOFJointAxisFlag p_flag, bool p_value);
bool get_flag(Vector3::Axis p_axis, PhysicsServer::G6DOFJointAxisFlag p_flag) const;
+
+ void set_precision(int p_precision);
+ int get_precision() const;
};
#endif
diff --git a/modules/bullet/godot_collision_configuration.cpp b/modules/bullet/godot_collision_configuration.cpp
index f4bb9acbd7..919c3152d7 100644
--- a/modules/bullet/godot_collision_configuration.cpp
+++ b/modules/bullet/godot_collision_configuration.cpp
@@ -94,3 +94,59 @@ btCollisionAlgorithmCreateFunc *GodotCollisionConfiguration::getClosestPointsAlg
return btDefaultCollisionConfiguration::getClosestPointsAlgorithmCreateFunc(proxyType0, proxyType1);
}
}
+
+GodotSoftCollisionConfiguration::GodotSoftCollisionConfiguration(const btDiscreteDynamicsWorld *world, const btDefaultCollisionConstructionInfo &constructionInfo) :
+ btSoftBodyRigidBodyCollisionConfiguration(constructionInfo) {
+
+ void *mem = NULL;
+
+ mem = btAlignedAlloc(sizeof(GodotRayWorldAlgorithm::CreateFunc), 16);
+ m_rayWorldCF = new (mem) GodotRayWorldAlgorithm::CreateFunc(world);
+
+ mem = btAlignedAlloc(sizeof(GodotRayWorldAlgorithm::SwappedCreateFunc), 16);
+ m_swappedRayWorldCF = new (mem) GodotRayWorldAlgorithm::SwappedCreateFunc(world);
+}
+
+GodotSoftCollisionConfiguration::~GodotSoftCollisionConfiguration() {
+ m_rayWorldCF->~btCollisionAlgorithmCreateFunc();
+ btAlignedFree(m_rayWorldCF);
+
+ m_swappedRayWorldCF->~btCollisionAlgorithmCreateFunc();
+ btAlignedFree(m_swappedRayWorldCF);
+}
+
+btCollisionAlgorithmCreateFunc *GodotSoftCollisionConfiguration::getCollisionAlgorithmCreateFunc(int proxyType0, int proxyType1) {
+
+ if (CUSTOM_CONVEX_SHAPE_TYPE == proxyType0 && CUSTOM_CONVEX_SHAPE_TYPE == proxyType1) {
+
+ // This collision is not supported
+ return m_emptyCreateFunc;
+ } else if (CUSTOM_CONVEX_SHAPE_TYPE == proxyType0) {
+
+ return m_rayWorldCF;
+ } else if (CUSTOM_CONVEX_SHAPE_TYPE == proxyType1) {
+
+ return m_swappedRayWorldCF;
+ } else {
+
+ return btSoftBodyRigidBodyCollisionConfiguration::getCollisionAlgorithmCreateFunc(proxyType0, proxyType1);
+ }
+}
+
+btCollisionAlgorithmCreateFunc *GodotSoftCollisionConfiguration::getClosestPointsAlgorithmCreateFunc(int proxyType0, int proxyType1) {
+
+ if (CUSTOM_CONVEX_SHAPE_TYPE == proxyType0 && CUSTOM_CONVEX_SHAPE_TYPE == proxyType1) {
+
+ // This collision is not supported
+ return m_emptyCreateFunc;
+ } else if (CUSTOM_CONVEX_SHAPE_TYPE == proxyType0) {
+
+ return m_rayWorldCF;
+ } else if (CUSTOM_CONVEX_SHAPE_TYPE == proxyType1) {
+
+ return m_swappedRayWorldCF;
+ } else {
+
+ return btSoftBodyRigidBodyCollisionConfiguration::getClosestPointsAlgorithmCreateFunc(proxyType0, proxyType1);
+ }
+}
diff --git a/modules/bullet/godot_collision_configuration.h b/modules/bullet/godot_collision_configuration.h
index 9b30ad0c62..11012c5f6d 100644
--- a/modules/bullet/godot_collision_configuration.h
+++ b/modules/bullet/godot_collision_configuration.h
@@ -32,6 +32,7 @@
#define GODOT_COLLISION_CONFIGURATION_H
#include <BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h>
+#include <BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h>
/**
@author AndreaCatania
@@ -50,4 +51,16 @@ public:
virtual btCollisionAlgorithmCreateFunc *getCollisionAlgorithmCreateFunc(int proxyType0, int proxyType1);
virtual btCollisionAlgorithmCreateFunc *getClosestPointsAlgorithmCreateFunc(int proxyType0, int proxyType1);
};
+
+class GodotSoftCollisionConfiguration : public btSoftBodyRigidBodyCollisionConfiguration {
+ btCollisionAlgorithmCreateFunc *m_rayWorldCF;
+ btCollisionAlgorithmCreateFunc *m_swappedRayWorldCF;
+
+public:
+ GodotSoftCollisionConfiguration(const btDiscreteDynamicsWorld *world, const btDefaultCollisionConstructionInfo &constructionInfo = btDefaultCollisionConstructionInfo());
+ virtual ~GodotSoftCollisionConfiguration();
+
+ virtual btCollisionAlgorithmCreateFunc *getCollisionAlgorithmCreateFunc(int proxyType0, int proxyType1);
+ virtual btCollisionAlgorithmCreateFunc *getClosestPointsAlgorithmCreateFunc(int proxyType0, int proxyType1);
+};
#endif
diff --git a/modules/bullet/godot_collision_dispatcher.h b/modules/bullet/godot_collision_dispatcher.h
index 2e5a6c2732..1faaa68626 100644
--- a/modules/bullet/godot_collision_dispatcher.h
+++ b/modules/bullet/godot_collision_dispatcher.h
@@ -31,7 +31,7 @@
#ifndef GODOT_COLLISION_DISPATCHER_H
#define GODOT_COLLISION_DISPATCHER_H
-#include "int_types.h"
+#include "core/int_types.h"
#include <btBulletDynamicsCommon.h>
diff --git a/modules/bullet/godot_motion_state.h b/modules/bullet/godot_motion_state.h
index fa58e86589..5844ef8bf3 100644
--- a/modules/bullet/godot_motion_state.h
+++ b/modules/bullet/godot_motion_state.h
@@ -82,7 +82,7 @@ public:
virtual void setWorldTransform(const btTransform &worldTrans) {
bodyCurrentWorldTransform = worldTrans;
- owner->scratch();
+ owner->notify_transform_changed();
}
public:
diff --git a/modules/bullet/godot_ray_world_algorithm.cpp b/modules/bullet/godot_ray_world_algorithm.cpp
index 53d0ab7e3c..27ee44d1bd 100644
--- a/modules/bullet/godot_ray_world_algorithm.cpp
+++ b/modules/bullet/godot_ray_world_algorithm.cpp
@@ -49,9 +49,9 @@ GodotRayWorldAlgorithm::SwappedCreateFunc::SwappedCreateFunc(const btDiscreteDyn
GodotRayWorldAlgorithm::GodotRayWorldAlgorithm(const btDiscreteDynamicsWorld *world, btPersistentManifold *mf, const btCollisionAlgorithmConstructionInfo &ci, const btCollisionObjectWrapper *body0Wrap, const btCollisionObjectWrapper *body1Wrap, bool isSwapped) :
btActivatingCollisionAlgorithm(ci, body0Wrap, body1Wrap),
+ m_world(world),
m_manifoldPtr(mf),
m_ownManifold(false),
- m_world(world),
m_isSwapped(isSwapped) {}
GodotRayWorldAlgorithm::~GodotRayWorldAlgorithm() {
diff --git a/modules/bullet/godot_result_callbacks.cpp b/modules/bullet/godot_result_callbacks.cpp
index 197550d686..0117bb375f 100644
--- a/modules/bullet/godot_result_callbacks.cpp
+++ b/modules/bullet/godot_result_callbacks.cpp
@@ -30,14 +30,23 @@
#include "godot_result_callbacks.h"
+#include "area_bullet.h"
#include "bullet_types_converter.h"
#include "collision_object_bullet.h"
#include "rigid_body_bullet.h"
+#include <BulletCollision/CollisionDispatch/btInternalEdgeUtility.h>
/**
@author AndreaCatania
*/
+bool godotContactAddedCallback(btManifoldPoint &cp, const btCollisionObjectWrapper *colObj0Wrap, int partId0, int index0, const btCollisionObjectWrapper *colObj1Wrap, int partId1, int index1) {
+ if (!colObj1Wrap->getCollisionObject()->getCollisionShape()->isCompound()) {
+ btAdjustInternalEdgeContacts(cp, colObj1Wrap, colObj0Wrap, partId1, index1);
+ }
+ return true;
+}
+
bool GodotFilterCallback::test_collision_filters(uint32_t body0_collision_layer, uint32_t body0_collision_mask, uint32_t body1_collision_layer, uint32_t body1_collision_mask) {
return body0_collision_layer & body1_collision_mask || body1_collision_layer & body0_collision_mask;
}
@@ -51,11 +60,23 @@ bool GodotClosestRayResultCallback::needsCollision(btBroadphaseProxy *proxy0) co
if (needs) {
btCollisionObject *btObj = static_cast<btCollisionObject *>(proxy0->m_clientObject);
CollisionObjectBullet *gObj = static_cast<CollisionObjectBullet *>(btObj->getUserPointer());
- if (m_pickRay && gObj->is_ray_pickable()) {
- return true;
- } else if (m_exclude->has(gObj->get_self())) {
+
+ if (CollisionObjectBullet::TYPE_AREA == gObj->getType()) {
+ if (!collide_with_areas)
+ return false;
+ } else {
+ if (!collide_with_bodies)
+ return false;
+ }
+
+ if (m_pickRay && !gObj->is_ray_pickable()) {
+ return false;
+ }
+
+ if (m_exclude->has(gObj->get_self())) {
return false;
}
+
return true;
} else {
return false;
@@ -81,6 +102,9 @@ bool GodotAllConvexResultCallback::needsCollision(btBroadphaseProxy *proxy0) con
}
btScalar GodotAllConvexResultCallback::addSingleResult(btCollisionWorld::LocalConvexResult &convexResult, bool normalInWorldSpace) {
+ if (count >= m_resultMax)
+ return 1; // not used by bullet
+
CollisionObjectBullet *gObj = static_cast<CollisionObjectBullet *>(convexResult.m_hitCollisionObject->getUserPointer());
PhysicsDirectSpaceState::ShapeResult &result = m_results[count];
@@ -124,6 +148,15 @@ bool GodotClosestConvexResultCallback::needsCollision(btBroadphaseProxy *proxy0)
if (needs) {
btCollisionObject *btObj = static_cast<btCollisionObject *>(proxy0->m_clientObject);
CollisionObjectBullet *gObj = static_cast<CollisionObjectBullet *>(btObj->getUserPointer());
+
+ if (CollisionObjectBullet::TYPE_AREA == gObj->getType()) {
+ if (!collide_with_areas)
+ return false;
+ } else {
+ if (!collide_with_bodies)
+ return false;
+ }
+
if (m_exclude->has(gObj->get_self())) {
return false;
}
@@ -134,16 +167,30 @@ bool GodotClosestConvexResultCallback::needsCollision(btBroadphaseProxy *proxy0)
}
btScalar GodotClosestConvexResultCallback::addSingleResult(btCollisionWorld::LocalConvexResult &convexResult, bool normalInWorldSpace) {
- btScalar res = btCollisionWorld::ClosestConvexResultCallback::addSingleResult(convexResult, normalInWorldSpace);
- m_shapeId = convexResult.m_localShapeInfo->m_triangleIndex; // "m_triangleIndex" Is a odd name but contains the compound shape ID
- return res;
+ if (convexResult.m_localShapeInfo)
+ m_shapeId = convexResult.m_localShapeInfo->m_triangleIndex; // "m_triangleIndex" Is a odd name but contains the compound shape ID
+ else
+ m_shapeId = 0;
+ return btCollisionWorld::ClosestConvexResultCallback::addSingleResult(convexResult, normalInWorldSpace);
}
bool GodotAllContactResultCallback::needsCollision(btBroadphaseProxy *proxy0) const {
+ if (m_count >= m_resultMax)
+ return false;
+
const bool needs = GodotFilterCallback::test_collision_filters(m_collisionFilterGroup, m_collisionFilterMask, proxy0->m_collisionFilterGroup, proxy0->m_collisionFilterMask);
if (needs) {
btCollisionObject *btObj = static_cast<btCollisionObject *>(proxy0->m_clientObject);
CollisionObjectBullet *gObj = static_cast<CollisionObjectBullet *>(btObj->getUserPointer());
+
+ if (CollisionObjectBullet::TYPE_AREA == gObj->getType()) {
+ if (!collide_with_areas)
+ return false;
+ } else {
+ if (!collide_with_bodies)
+ return false;
+ }
+
if (m_exclude->has(gObj->get_self())) {
return false;
}
@@ -189,6 +236,15 @@ bool GodotContactPairContactResultCallback::needsCollision(btBroadphaseProxy *pr
if (needs) {
btCollisionObject *btObj = static_cast<btCollisionObject *>(proxy0->m_clientObject);
CollisionObjectBullet *gObj = static_cast<CollisionObjectBullet *>(btObj->getUserPointer());
+
+ if (CollisionObjectBullet::TYPE_AREA == gObj->getType()) {
+ if (!collide_with_areas)
+ return false;
+ } else {
+ if (!collide_with_bodies)
+ return false;
+ }
+
if (m_exclude->has(gObj->get_self())) {
return false;
}
@@ -199,6 +255,8 @@ bool GodotContactPairContactResultCallback::needsCollision(btBroadphaseProxy *pr
}
btScalar GodotContactPairContactResultCallback::addSingleResult(btManifoldPoint &cp, const btCollisionObjectWrapper *colObj0Wrap, int partId0, int index0, const btCollisionObjectWrapper *colObj1Wrap, int partId1, int index1) {
+ if (m_count >= m_resultMax)
+ return 1; // not used by bullet
if (m_self_object == colObj0Wrap->getCollisionObject()) {
B_TO_G(cp.m_localPointA, m_results[m_count * 2 + 0]); // Local contact
@@ -218,6 +276,15 @@ bool GodotRestInfoContactResultCallback::needsCollision(btBroadphaseProxy *proxy
if (needs) {
btCollisionObject *btObj = static_cast<btCollisionObject *>(proxy0->m_clientObject);
CollisionObjectBullet *gObj = static_cast<CollisionObjectBullet *>(btObj->getUserPointer());
+
+ if (CollisionObjectBullet::TYPE_AREA == gObj->getType()) {
+ if (!collide_with_areas)
+ return false;
+ } else {
+ if (!collide_with_bodies)
+ return false;
+ }
+
if (m_exclude->has(gObj->get_self())) {
return false;
}
@@ -260,10 +327,19 @@ void GodotDeepPenetrationContactResultCallback::addContactPoint(const btVector3
if (m_penetration_distance > depth) { // Has penetration?
- bool isSwapped = m_manifoldPtr->getBody0() != m_body0Wrap->getCollisionObject();
+ const bool isSwapped = m_manifoldPtr->getBody0() != m_body0Wrap->getCollisionObject();
m_penetration_distance = depth;
m_other_compound_shape_index = isSwapped ? m_index0 : m_index1;
- m_pointNormalWorld = isSwapped ? normalOnBInWorld * -1 : normalOnBInWorld;
m_pointWorld = isSwapped ? (pointInWorldOnB + (normalOnBInWorld * depth)) : pointInWorldOnB;
+
+ const btCollisionObjectWrapper *bw0 = m_body0Wrap;
+ if (isSwapped)
+ bw0 = m_body1Wrap;
+
+ if (bw0->getCollisionShape()->getShapeType() == CUSTOM_CONVEX_SHAPE_TYPE) {
+ m_pointNormalWorld = bw0->m_worldTransform.getBasis().transpose() * btVector3(0, 0, 1);
+ } else {
+ m_pointNormalWorld = isSwapped ? normalOnBInWorld * -1 : normalOnBInWorld;
+ }
}
}
diff --git a/modules/bullet/godot_result_callbacks.h b/modules/bullet/godot_result_callbacks.h
index 363051f24c..73e1fc9627 100644
--- a/modules/bullet/godot_result_callbacks.h
+++ b/modules/bullet/godot_result_callbacks.h
@@ -42,6 +42,9 @@
class RigidBodyBullet;
+/// This callback is injected inside bullet server and allow me to smooth contacts against trimesh
+bool godotContactAddedCallback(btManifoldPoint &cp, const btCollisionObjectWrapper *colObj0Wrap, int partId0, int index0, const btCollisionObjectWrapper *colObj1Wrap, int partId1, int index1);
+
/// This class is required to implement custom collision behaviour in the broadphase
struct GodotFilterCallback : public btOverlapFilterCallback {
static bool test_collision_filters(uint32_t body0_collision_layer, uint32_t body0_collision_mask, uint32_t body1_collision_layer, uint32_t body1_collision_mask);
@@ -56,17 +59,25 @@ struct GodotClosestRayResultCallback : public btCollisionWorld::ClosestRayResult
bool m_pickRay;
int m_shapeId;
+ bool collide_with_bodies;
+ bool collide_with_areas;
+
public:
- GodotClosestRayResultCallback(const btVector3 &rayFromWorld, const btVector3 &rayToWorld, const Set<RID> *p_exclude) :
+ GodotClosestRayResultCallback(const btVector3 &rayFromWorld, const btVector3 &rayToWorld, const Set<RID> *p_exclude, bool p_collide_with_bodies, bool p_collide_with_areas) :
btCollisionWorld::ClosestRayResultCallback(rayFromWorld, rayToWorld),
m_exclude(p_exclude),
m_pickRay(false),
- m_shapeId(0) {}
+ m_shapeId(0),
+ collide_with_bodies(p_collide_with_bodies),
+ collide_with_areas(p_collide_with_areas) {}
virtual bool needsCollision(btBroadphaseProxy *proxy0) const;
virtual btScalar addSingleResult(btCollisionWorld::LocalRayResult &rayResult, bool normalInWorldSpace) {
- m_shapeId = rayResult.m_localShapeInfo->m_triangleIndex; // "m_triangleIndex" Is a odd name but contains the compound shape ID
+ if (rayResult.m_localShapeInfo)
+ m_shapeId = rayResult.m_localShapeInfo->m_triangleIndex; // "m_triangleIndex" Is a odd name but contains the compound shape ID
+ else
+ m_shapeId = 0;
return btCollisionWorld::ClosestRayResultCallback::addSingleResult(rayResult, normalInWorldSpace);
}
};
@@ -76,13 +87,13 @@ struct GodotAllConvexResultCallback : public btCollisionWorld::ConvexResultCallb
public:
PhysicsDirectSpaceState::ShapeResult *m_results;
int m_resultMax;
- int count;
const Set<RID> *m_exclude;
+ int count;
GodotAllConvexResultCallback(PhysicsDirectSpaceState::ShapeResult *p_results, int p_resultMax, const Set<RID> *p_exclude) :
m_results(p_results),
- m_exclude(p_exclude),
m_resultMax(p_resultMax),
+ m_exclude(p_exclude),
count(0) {}
virtual bool needsCollision(btBroadphaseProxy *proxy0) const;
@@ -108,9 +119,15 @@ public:
const Set<RID> *m_exclude;
int m_shapeId;
- GodotClosestConvexResultCallback(const btVector3 &convexFromWorld, const btVector3 &convexToWorld, const Set<RID> *p_exclude) :
+ bool collide_with_bodies;
+ bool collide_with_areas;
+
+ GodotClosestConvexResultCallback(const btVector3 &convexFromWorld, const btVector3 &convexToWorld, const Set<RID> *p_exclude, bool p_collide_with_bodies, bool p_collide_with_areas) :
btCollisionWorld::ClosestConvexResultCallback(convexFromWorld, convexToWorld),
- m_exclude(p_exclude) {}
+ m_exclude(p_exclude),
+ m_shapeId(0),
+ collide_with_bodies(p_collide_with_bodies),
+ collide_with_areas(p_collide_with_areas) {}
virtual bool needsCollision(btBroadphaseProxy *proxy0) const;
@@ -122,15 +139,20 @@ public:
const btCollisionObject *m_self_object;
PhysicsDirectSpaceState::ShapeResult *m_results;
int m_resultMax;
- int m_count;
const Set<RID> *m_exclude;
+ int m_count;
- GodotAllContactResultCallback(btCollisionObject *p_self_object, PhysicsDirectSpaceState::ShapeResult *p_results, int p_resultMax, const Set<RID> *p_exclude) :
+ bool collide_with_bodies;
+ bool collide_with_areas;
+
+ GodotAllContactResultCallback(btCollisionObject *p_self_object, PhysicsDirectSpaceState::ShapeResult *p_results, int p_resultMax, const Set<RID> *p_exclude, bool p_collide_with_bodies, bool p_collide_with_areas) :
m_self_object(p_self_object),
m_results(p_results),
- m_exclude(p_exclude),
m_resultMax(p_resultMax),
- m_count(0) {}
+ m_exclude(p_exclude),
+ m_count(0),
+ collide_with_bodies(p_collide_with_bodies),
+ collide_with_areas(p_collide_with_areas) {}
virtual bool needsCollision(btBroadphaseProxy *proxy0) const;
@@ -143,15 +165,20 @@ public:
const btCollisionObject *m_self_object;
Vector3 *m_results;
int m_resultMax;
- int m_count;
const Set<RID> *m_exclude;
+ int m_count;
- GodotContactPairContactResultCallback(btCollisionObject *p_self_object, Vector3 *p_results, int p_resultMax, const Set<RID> *p_exclude) :
+ bool collide_with_bodies;
+ bool collide_with_areas;
+
+ GodotContactPairContactResultCallback(btCollisionObject *p_self_object, Vector3 *p_results, int p_resultMax, const Set<RID> *p_exclude, bool p_collide_with_bodies, bool p_collide_with_areas) :
m_self_object(p_self_object),
m_results(p_results),
- m_exclude(p_exclude),
m_resultMax(p_resultMax),
- m_count(0) {}
+ m_exclude(p_exclude),
+ m_count(0),
+ collide_with_bodies(p_collide_with_bodies),
+ collide_with_areas(p_collide_with_areas) {}
virtual bool needsCollision(btBroadphaseProxy *proxy0) const;
@@ -162,18 +189,22 @@ struct GodotRestInfoContactResultCallback : public btCollisionWorld::ContactResu
public:
const btCollisionObject *m_self_object;
PhysicsDirectSpaceState::ShapeRestInfo *m_result;
+ const Set<RID> *m_exclude;
bool m_collided;
real_t m_min_distance;
const btCollisionObject *m_rest_info_collision_object;
btVector3 m_rest_info_bt_point;
- const Set<RID> *m_exclude;
+ bool collide_with_bodies;
+ bool collide_with_areas;
- GodotRestInfoContactResultCallback(btCollisionObject *p_self_object, PhysicsDirectSpaceState::ShapeRestInfo *p_result, const Set<RID> *p_exclude) :
+ GodotRestInfoContactResultCallback(btCollisionObject *p_self_object, PhysicsDirectSpaceState::ShapeRestInfo *p_result, const Set<RID> *p_exclude, bool p_collide_with_bodies, bool p_collide_with_areas) :
m_self_object(p_self_object),
m_result(p_result),
m_exclude(p_exclude),
m_collided(false),
- m_min_distance(0) {}
+ m_min_distance(0),
+ collide_with_bodies(p_collide_with_bodies),
+ collide_with_areas(p_collide_with_areas) {}
virtual bool needsCollision(btBroadphaseProxy *proxy0) const;
diff --git a/modules/bullet/hinge_joint_bullet.cpp b/modules/bullet/hinge_joint_bullet.cpp
index 97ea7ca3df..3a4459a581 100644
--- a/modules/bullet/hinge_joint_bullet.cpp
+++ b/modules/bullet/hinge_joint_bullet.cpp
@@ -95,11 +95,6 @@ real_t HingeJointBullet::get_hinge_angle() {
void HingeJointBullet::set_param(PhysicsServer::HingeJointParam p_param, real_t p_value) {
switch (p_param) {
- case PhysicsServer::HINGE_JOINT_BIAS:
- if (0 < p_value) {
- print_line("The Bullet Hinge Joint doesn't support bias, So it's always 0");
- }
- break;
case PhysicsServer::HINGE_JOINT_LIMIT_UPPER:
hingeConstraint->setLimit(hingeConstraint->getLowerLimit(), p_value, hingeConstraint->getLimitSoftness(), hingeConstraint->getLimitBiasFactor(), hingeConstraint->getLimitRelaxationFactor());
break;
@@ -122,7 +117,9 @@ void HingeJointBullet::set_param(PhysicsServer::HingeJointParam p_param, real_t
hingeConstraint->setMaxMotorImpulse(p_value);
break;
default:
- WARN_PRINTS("The Bullet Hinge Joint doesn't support this parameter: " + itos(p_param) + ", value: " + itos(p_value));
+ ERR_EXPLAIN("The HingeJoint parameter " + itos(p_param) + " is deprecated.");
+ WARN_DEPRECATED
+ break;
}
}
@@ -146,7 +143,8 @@ real_t HingeJointBullet::get_param(PhysicsServer::HingeJointParam p_param) const
case PhysicsServer::HINGE_JOINT_MOTOR_MAX_IMPULSE:
return hingeConstraint->getMaxMotorImpulse();
default:
- WARN_PRINTS("The Bullet Hinge Joint doesn't support this parameter: " + itos(p_param));
+ ERR_EXPLAIN("The HingeJoint parameter " + itos(p_param) + " is deprecated.");
+ WARN_DEPRECATED;
return 0;
}
}
@@ -161,6 +159,7 @@ void HingeJointBullet::set_flag(PhysicsServer::HingeJointFlag p_flag, bool p_val
case PhysicsServer::HINGE_JOINT_FLAG_ENABLE_MOTOR:
hingeConstraint->enableMotor(p_value);
break;
+ case PhysicsServer::HINGE_JOINT_FLAG_MAX: break; // Can't happen, but silences warning
}
}
diff --git a/modules/bullet/pin_joint_bullet.cpp b/modules/bullet/pin_joint_bullet.cpp
index c4e5b8cdbe..183a7e75b9 100644
--- a/modules/bullet/pin_joint_bullet.cpp
+++ b/modules/bullet/pin_joint_bullet.cpp
@@ -85,7 +85,8 @@ real_t PinJointBullet::get_param(PhysicsServer::PinJointParam p_param) const {
case PhysicsServer::PIN_JOINT_IMPULSE_CLAMP:
return p2pConstraint->m_setting.m_impulseClamp;
default:
- WARN_PRINTS("This get parameter is not supported");
+ ERR_EXPLAIN("This parameter " + itos(p_param) + " is deprecated");
+ WARN_DEPRECATED
return 0;
}
}
diff --git a/modules/bullet/register_types.cpp b/modules/bullet/register_types.cpp
index a76b0438b4..31e5f6784e 100644
--- a/modules/bullet/register_types.cpp
+++ b/modules/bullet/register_types.cpp
@@ -31,8 +31,8 @@
#include "register_types.h"
#include "bullet_physics_server.h"
-#include "class_db.h"
-#include "project_settings.h"
+#include "core/class_db.h"
+#include "core/project_settings.h"
/**
@author AndreaCatania
diff --git a/modules/bullet/rigid_body_bullet.cpp b/modules/bullet/rigid_body_bullet.cpp
index 81a62edba6..9dd04100ed 100644
--- a/modules/bullet/rigid_body_bullet.cpp
+++ b/modules/bullet/rigid_body_bullet.cpp
@@ -259,31 +259,31 @@ RigidBodyBullet::RigidBodyBullet() :
RigidCollisionObjectBullet(CollisionObjectBullet::TYPE_RIGID_BODY),
kinematic_utilities(NULL),
locked_axis(0),
- gravity_scale(1),
mass(1),
+ gravity_scale(1),
linearDamp(0),
angularDamp(0),
can_sleep(true),
omit_forces_integration(false),
- restitution_combine_mode(PhysicsServer::COMBINE_MODE_INHERIT),
- friction_combine_mode(PhysicsServer::COMBINE_MODE_INHERIT),
- force_integration_callback(NULL),
- isTransformChanged(false),
- previousActiveState(true),
+ can_integrate_forces(false),
maxCollisionsDetection(0),
collisionsCount(0),
+ prev_collision_count(0),
maxAreasWhereIam(10),
areaWhereIamCount(0),
countGravityPointSpaces(0),
- isScratchedSpaceOverrideModificator(false) {
+ isScratchedSpaceOverrideModificator(false),
+ previousActiveState(true),
+ force_integration_callback(NULL) {
godotMotionState = bulletnew(GodotMotionState(this));
// Initial properties
const btVector3 localInertia(0, 0, 0);
- btRigidBody::btRigidBodyConstructionInfo cInfo(mass, godotMotionState, compoundShape, localInertia);
+ btRigidBody::btRigidBodyConstructionInfo cInfo(mass, godotMotionState, NULL, localInertia);
btBody = bulletnew(btRigidBody(cInfo));
+ reload_shapes();
setupBulletCollisionObject(btBody);
set_mode(PhysicsServer::BODY_MODE_RIGID);
@@ -294,6 +294,9 @@ RigidBodyBullet::RigidBodyBullet() :
areasWhereIam.write[i] = NULL;
}
btBody->setSleepingThresholds(0.2, 0.2);
+
+ prev_collision_traces = &collision_traces_1;
+ curr_collision_traces = &collision_traces_2;
}
RigidBodyBullet::~RigidBodyBullet() {
@@ -316,17 +319,24 @@ void RigidBodyBullet::destroy_kinematic_utilities() {
}
}
+void RigidBodyBullet::main_shape_changed() {
+ CRASH_COND(!get_main_shape())
+ btBody->setCollisionShape(get_main_shape());
+ set_continuous_collision_detection(is_continuous_collision_detection_enabled()); // Reset
+}
+
void RigidBodyBullet::reload_body() {
if (space) {
space->remove_rigid_body(this);
- space->add_rigid_body(this);
+ if (get_main_shape())
+ space->add_rigid_body(this);
}
}
void RigidBodyBullet::set_space(SpaceBullet *p_space) {
// Clear the old space if there is one
if (space) {
- isTransformChanged = false;
+ can_integrate_forces = false;
// Remove all eventual constraints
assert_no_constraints();
@@ -343,8 +353,8 @@ void RigidBodyBullet::set_space(SpaceBullet *p_space) {
}
void RigidBodyBullet::dispatch_callbacks() {
- /// The check isTransformChanged is necessary in order to call integrated forces only when the first transform is sent
- if ((btBody->isActive() || previousActiveState != btBody->isActive()) && force_integration_callback && isTransformChanged) {
+ /// The check isFirstTransformChanged is necessary in order to call integrated forces only when the first transform is sent
+ if ((btBody->isKinematicObject() || btBody->isActive() || previousActiveState != btBody->isActive()) && force_integration_callback && can_integrate_forces) {
if (omit_forces_integration)
btBody->clearForces();
@@ -393,10 +403,6 @@ void RigidBodyBullet::set_force_integration_callback(ObjectID p_id, const String
}
}
-void RigidBodyBullet::scratch() {
- isTransformChanged = true;
-}
-
void RigidBodyBullet::scratch_space_override_modificator() {
isScratchedSpaceOverrideModificator = true;
}
@@ -408,7 +414,19 @@ void RigidBodyBullet::on_collision_filters_change() {
}
void RigidBodyBullet::on_collision_checker_start() {
+
+ prev_collision_count = collisionsCount;
collisionsCount = 0;
+
+ // Swap array
+ Vector<RigidBodyBullet *> *s = prev_collision_traces;
+ prev_collision_traces = curr_collision_traces;
+ curr_collision_traces = s;
+}
+
+void RigidBodyBullet::on_collision_checker_end() {
+ // Always true if active and not a static or kinematic body
+ isTransformChanged = btBody->isActive() && !btBody->isStaticOrKinematicObject();
}
bool RigidBodyBullet::add_collision_object(RigidBodyBullet *p_otherObject, const Vector3 &p_hitWorldLocation, const Vector3 &p_hitLocalLocation, const Vector3 &p_hitNormal, const float &p_appliedImpulse, int p_other_shape_index, int p_local_shape_index) {
@@ -426,10 +444,20 @@ bool RigidBodyBullet::add_collision_object(RigidBodyBullet *p_otherObject, const
cd.other_object_shape = p_other_shape_index;
cd.local_shape = p_local_shape_index;
+ curr_collision_traces->write[collisionsCount] = p_otherObject;
+
++collisionsCount;
return true;
}
+bool RigidBodyBullet::was_colliding(RigidBodyBullet *p_other_object) {
+ for (int i = prev_collision_count - 1; 0 <= i; --i) {
+ if ((*prev_collision_traces)[i] == p_other_object)
+ return true;
+ }
+ return false;
+}
+
void RigidBodyBullet::assert_no_constraints() {
if (btBody->getNumConstraintRefs()) {
WARN_PRINT("A body with a joints is destroyed. Please check the implementation in order to destroy the joint before the body.");
@@ -513,7 +541,7 @@ real_t RigidBodyBullet::get_param(PhysicsServer::BodyParameter p_param) const {
void RigidBodyBullet::set_mode(PhysicsServer::BodyMode p_mode) {
// This is necessary to block force_integration untile next move
- isTransformChanged = false;
+ can_integrate_forces = false;
destroy_kinematic_utilities();
// The mode change is relevant to its mass
switch (p_mode) {
@@ -528,20 +556,18 @@ void RigidBodyBullet::set_mode(PhysicsServer::BodyMode p_mode) {
reload_axis_lock();
_internal_set_mass(0);
break;
- case PhysicsServer::BODY_MODE_RIGID: {
+ case PhysicsServer::BODY_MODE_RIGID:
mode = PhysicsServer::BODY_MODE_RIGID;
reload_axis_lock();
_internal_set_mass(0 == mass ? 1 : mass);
scratch_space_override_modificator();
break;
- }
- case PhysicsServer::BODY_MODE_CHARACTER: {
+ case PhysicsServer::BODY_MODE_CHARACTER:
mode = PhysicsServer::BODY_MODE_CHARACTER;
reload_axis_lock();
_internal_set_mass(0 == mass ? 1 : mass);
scratch_space_override_modificator();
break;
- }
}
btBody->setAngularVelocity(btVector3(0, 0, 0));
@@ -713,15 +739,19 @@ void RigidBodyBullet::set_continuous_collision_detection(bool p_enable) {
if (p_enable) {
// This threshold enable CCD if the object moves more than
// 1 meter in one simulation frame
- btBody->setCcdMotionThreshold(1);
+ btBody->setCcdMotionThreshold(0.1);
/// Calculate using the rule writte below the CCD swept sphere radius
/// CCD works on an embedded sphere of radius, make sure this radius
/// is embedded inside the convex objects, preferably smaller:
/// for an object of dimensions 1 meter, try 0.2
- btVector3 center;
btScalar radius;
- btBody->getCollisionShape()->getBoundingSphere(center, radius);
+ if (btBody->getCollisionShape()) {
+ btVector3 center;
+ btBody->getCollisionShape()->getBoundingSphere(center, radius);
+ } else {
+ radius = 0;
+ }
btBody->setCcdSweptSphereRadius(radius * 0.2);
} else {
btBody->setCcdMotionThreshold(0.);
@@ -730,7 +760,7 @@ void RigidBodyBullet::set_continuous_collision_detection(bool p_enable) {
}
bool RigidBodyBullet::is_continuous_collision_detection_enabled() const {
- return 0. != btBody->getCcdMotionThreshold();
+ return 0. < btBody->getCcdMotionThreshold();
}
void RigidBodyBullet::set_linear_velocity(const Vector3 &p_velocity) {
@@ -761,28 +791,14 @@ Vector3 RigidBodyBullet::get_angular_velocity() const {
return gVec;
}
-void RigidBodyBullet::set_combine_mode(const PhysicsServer::BodyParameter p_param, const PhysicsServer::CombineMode p_mode) {
- if (p_param == PhysicsServer::BODY_PARAM_BOUNCE) {
- restitution_combine_mode = p_mode;
- } else {
- friction_combine_mode = p_mode;
- }
-}
-
-PhysicsServer::CombineMode RigidBodyBullet::get_combine_mode(PhysicsServer::BodyParameter p_param) const {
- if (p_param == PhysicsServer::BODY_PARAM_BOUNCE) {
- return restitution_combine_mode;
- } else {
- return friction_combine_mode;
- }
-}
-
void RigidBodyBullet::set_transform__bullet(const btTransform &p_global_transform) {
if (mode == PhysicsServer::BODY_MODE_KINEMATIC) {
+ if (space)
+ btBody->setLinearVelocity((p_global_transform.getOrigin() - btBody->getWorldTransform().getOrigin()) / space->get_delta_time());
// The kinematic use MotionState class
godotMotionState->moveBody(p_global_transform);
}
- btBody->setWorldTransform(p_global_transform);
+ CollisionObjectBullet::set_transform__bullet(p_global_transform);
}
const btTransform &RigidBodyBullet::get_transform__bullet() const {
@@ -795,15 +811,20 @@ const btTransform &RigidBodyBullet::get_transform__bullet() const {
}
}
-void RigidBodyBullet::on_shapes_changed() {
- RigidCollisionObjectBullet::on_shapes_changed();
+void RigidBodyBullet::reload_shapes() {
+ RigidCollisionObjectBullet::reload_shapes();
const btScalar invMass = btBody->getInvMass();
const btScalar mass = invMass == 0 ? 0 : 1 / invMass;
- btVector3 inertia;
- btBody->getCollisionShape()->calculateLocalInertia(mass, inertia);
- btBody->setMassProps(mass, inertia);
+ if (mainShape) {
+ // inertia initialised zero here because some of bullet's collision
+ // shapes incorrectly do not set the vector in calculateLocalIntertia.
+ // Arbitrary zero is preferable to undefined behaviour.
+ btVector3 inertia(0, 0, 0);
+ mainShape->calculateLocalInertia(mass, inertia);
+ btBody->setMassProps(mass, inertia);
+ }
btBody->updateInertiaTensor();
reload_kinematic_shapes();
@@ -852,7 +873,7 @@ void RigidBodyBullet::on_exit_area(AreaBullet *p_area) {
bool wasTheAreaFound = false;
for (int i = 0; i < areaWhereIamCount; ++i) {
if (p_area == areasWhereIam[i]) {
- // The area was fount, just shift down all elements
+ // The area was found, just shift down all elements
for (int j = i; j < areaWhereIamCount; ++j) {
areasWhereIam.write[j] = areasWhereIam[j + 1];
}
@@ -927,10 +948,10 @@ void RigidBodyBullet::reload_space_override_modificator() {
}
switch (currentArea->get_spOv_mode()) {
- ///case PhysicsServer::AREA_SPACE_OVERRIDE_DISABLED:
- /// This area does not affect gravity/damp. These are generally areas
- /// that exist only to detect collisions, and objects entering or exiting them.
- /// break;
+ case PhysicsServer::AREA_SPACE_OVERRIDE_DISABLED:
+ /// This area does not affect gravity/damp. These are generally areas
+ /// that exist only to detect collisions, and objects entering or exiting them.
+ break;
case PhysicsServer::AREA_SPACE_OVERRIDE_COMBINE:
/// This area adds its gravity/damp values to whatever has been
/// calculated so far. This way, many overlapping areas can combine
@@ -989,6 +1010,11 @@ void RigidBodyBullet::reload_kinematic_shapes() {
kinematic_utilities->copyAllOwnerShapes();
}
+void RigidBodyBullet::notify_transform_changed() {
+ RigidCollisionObjectBullet::notify_transform_changed();
+ can_integrate_forces = true;
+}
+
void RigidBodyBullet::_internal_set_mass(real_t p_mass) {
btVector3 localInertia(0, 0, 0);
@@ -1004,7 +1030,8 @@ void RigidBodyBullet::_internal_set_mass(real_t p_mass) {
return;
m_isStatic = false;
- compoundShape->calculateLocalInertia(p_mass, localInertia);
+ if (mainShape)
+ mainShape->calculateLocalInertia(p_mass, localInertia);
if (PhysicsServer::BODY_MODE_RIGID == mode) {
diff --git a/modules/bullet/rigid_body_bullet.h b/modules/bullet/rigid_body_bullet.h
index 35af3b90d8..0696073d21 100644
--- a/modules/bullet/rigid_body_bullet.h
+++ b/modules/bullet/rigid_body_bullet.h
@@ -202,14 +202,18 @@ private:
real_t angularDamp;
bool can_sleep;
bool omit_forces_integration;
-
- PhysicsServer::CombineMode restitution_combine_mode;
- PhysicsServer::CombineMode friction_combine_mode;
+ bool can_integrate_forces;
Vector<CollisionData> collisions;
+ Vector<RigidBodyBullet *> collision_traces_1;
+ Vector<RigidBodyBullet *> collision_traces_2;
+ Vector<RigidBodyBullet *> *prev_collision_traces;
+ Vector<RigidBodyBullet *> *curr_collision_traces;
+
// these parameters are used to avoid vector resize
int maxCollisionsDetection;
int collisionsCount;
+ int prev_collision_count;
Vector<AreaBullet *> areasWhereIam;
// these parameters are used to avoid vector resize
@@ -219,7 +223,6 @@ private:
int countGravityPointSpaces;
bool isScratchedSpaceOverrideModificator;
- bool isTransformChanged;
bool previousActiveState; // Last check state
ForceIntegrationCallback *force_integration_callback;
@@ -230,24 +233,34 @@ public:
void init_kinematic_utilities();
void destroy_kinematic_utilities();
- _FORCE_INLINE_ class KinematicUtilities *get_kinematic_utilities() const { return kinematic_utilities; }
+ _FORCE_INLINE_ KinematicUtilities *get_kinematic_utilities() const { return kinematic_utilities; }
_FORCE_INLINE_ btRigidBody *get_bt_rigid_body() { return btBody; }
+ virtual void main_shape_changed();
virtual void reload_body();
virtual void set_space(SpaceBullet *p_space);
virtual void dispatch_callbacks();
void set_force_integration_callback(ObjectID p_id, const StringName &p_method, const Variant &p_udata = Variant());
- void scratch();
void scratch_space_override_modificator();
virtual void on_collision_filters_change();
virtual void on_collision_checker_start();
+ virtual void on_collision_checker_end();
+
void set_max_collisions_detection(int p_maxCollisionsDetection) {
+
+ ERR_FAIL_COND(0 > p_maxCollisionsDetection);
+
maxCollisionsDetection = p_maxCollisionsDetection;
+
collisions.resize(p_maxCollisionsDetection);
+ collision_traces_1.resize(p_maxCollisionsDetection);
+ collision_traces_2.resize(p_maxCollisionsDetection);
+
collisionsCount = 0;
+ prev_collision_count = MIN(prev_collision_count, p_maxCollisionsDetection);
}
int get_max_collisions_detection() {
return maxCollisionsDetection;
@@ -255,6 +268,7 @@ public:
bool can_add_collision() { return collisionsCount < maxCollisionsDetection; }
bool add_collision_object(RigidBodyBullet *p_otherObject, const Vector3 &p_hitWorldLocation, const Vector3 &p_hitLocalLocation, const Vector3 &p_hitNormal, const float &p_appliedImpulse, int p_other_shape_index, int p_local_shape_index);
+ bool was_colliding(RigidBodyBullet *p_other_object);
void assert_no_constraints();
@@ -301,16 +315,10 @@ public:
void set_angular_velocity(const Vector3 &p_velocity);
Vector3 get_angular_velocity() const;
- void set_combine_mode(const PhysicsServer::BodyParameter p_param, const PhysicsServer::CombineMode p_mode);
- PhysicsServer::CombineMode get_combine_mode(PhysicsServer::BodyParameter p_param) const;
-
- _FORCE_INLINE_ PhysicsServer::CombineMode get_restitution_combine_mode() const { return restitution_combine_mode; }
- _FORCE_INLINE_ PhysicsServer::CombineMode get_friction_combine_mode() const { return friction_combine_mode; }
-
virtual void set_transform__bullet(const btTransform &p_global_transform);
virtual const btTransform &get_transform__bullet() const;
- virtual void on_shapes_changed();
+ virtual void reload_shapes();
virtual void on_enter_area(AreaBullet *p_area);
virtual void on_exit_area(AreaBullet *p_area);
@@ -319,6 +327,8 @@ public:
/// Kinematic
void reload_kinematic_shapes();
+ virtual void notify_transform_changed();
+
private:
void _internal_set_mass(real_t p_mass);
};
diff --git a/modules/bullet/shape_bullet.cpp b/modules/bullet/shape_bullet.cpp
index b05a3015a9..2027d8e1eb 100644
--- a/modules/bullet/shape_bullet.cpp
+++ b/modules/bullet/shape_bullet.cpp
@@ -34,8 +34,10 @@
#include "bullet_physics_server.h"
#include "bullet_types_converter.h"
#include "bullet_utilities.h"
+#include "core/project_settings.h"
#include "shape_owner_bullet.h"
+#include <BulletCollision/CollisionDispatch/btInternalEdgeUtility.h>
#include <BulletCollision/CollisionShapes/btConvexPointCloudShape.h>
#include <BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h>
#include <btBulletCollisionCommon.h>
@@ -44,25 +46,27 @@
@author AndreaCatania
*/
-ShapeBullet::ShapeBullet() {}
+ShapeBullet::ShapeBullet() :
+ margin(0.04) {}
ShapeBullet::~ShapeBullet() {}
-btCollisionShape *ShapeBullet::create_bt_shape(const Vector3 &p_implicit_scale, real_t p_margin) {
+btCollisionShape *ShapeBullet::create_bt_shape(const Vector3 &p_implicit_scale, real_t p_extra_edge) {
btVector3 s;
G_TO_B(p_implicit_scale, s);
- return create_bt_shape(s, p_margin);
+ return create_bt_shape(s, p_extra_edge);
}
btCollisionShape *ShapeBullet::prepare(btCollisionShape *p_btShape) const {
p_btShape->setUserPointer(const_cast<ShapeBullet *>(this));
- p_btShape->setMargin(0.);
+ p_btShape->setMargin(margin);
return p_btShape;
}
void ShapeBullet::notifyShapeChanged() {
for (Map<ShapeOwnerBullet *, int>::Element *E = owners.front(); E; E = E->next()) {
- static_cast<ShapeOwnerBullet *>(E->key())->on_shape_changed(this);
+ ShapeOwnerBullet *owner = static_cast<ShapeOwnerBullet *>(E->key());
+ owner->shape_changed(owner->find_shape(this));
}
}
@@ -93,6 +97,15 @@ const Map<ShapeOwnerBullet *, int> &ShapeBullet::get_owners() const {
return owners;
}
+void ShapeBullet::set_margin(real_t p_margin) {
+ margin = p_margin;
+ notifyShapeChanged();
+}
+
+real_t ShapeBullet::get_margin() const {
+ return margin;
+}
+
btEmptyShape *ShapeBullet::create_shape_empty() {
return bulletnew(btEmptyShape);
}
@@ -166,7 +179,7 @@ void PlaneShapeBullet::setup(const Plane &p_plane) {
notifyShapeChanged();
}
-btCollisionShape *PlaneShapeBullet::create_bt_shape(const btVector3 &p_implicit_scale, real_t p_margin) {
+btCollisionShape *PlaneShapeBullet::create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge) {
btVector3 btPlaneNormal;
G_TO_B(plane.normal, btPlaneNormal);
return prepare(PlaneShapeBullet::create_shape_plane(btPlaneNormal, plane.d));
@@ -194,8 +207,8 @@ void SphereShapeBullet::setup(real_t p_radius) {
notifyShapeChanged();
}
-btCollisionShape *SphereShapeBullet::create_bt_shape(const btVector3 &p_implicit_scale, real_t p_margin) {
- return prepare(ShapeBullet::create_shape_sphere(radius * p_implicit_scale[0] + p_margin));
+btCollisionShape *SphereShapeBullet::create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge) {
+ return prepare(ShapeBullet::create_shape_sphere(radius * p_implicit_scale[0] + p_extra_edge));
}
/* Box */
@@ -221,8 +234,8 @@ void BoxShapeBullet::setup(const Vector3 &p_half_extents) {
notifyShapeChanged();
}
-btCollisionShape *BoxShapeBullet::create_bt_shape(const btVector3 &p_implicit_scale, real_t p_margin) {
- return prepare(ShapeBullet::create_shape_box((half_extents * p_implicit_scale) + btVector3(p_margin, p_margin, p_margin)));
+btCollisionShape *BoxShapeBullet::create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge) {
+ return prepare(ShapeBullet::create_shape_box((half_extents * p_implicit_scale) + btVector3(p_extra_edge, p_extra_edge, p_extra_edge)));
}
/* Capsule */
@@ -254,8 +267,8 @@ void CapsuleShapeBullet::setup(real_t p_height, real_t p_radius) {
notifyShapeChanged();
}
-btCollisionShape *CapsuleShapeBullet::create_bt_shape(const btVector3 &p_implicit_scale, real_t p_margin) {
- return prepare(ShapeBullet::create_shape_capsule(radius * p_implicit_scale[0] + p_margin, height * p_implicit_scale[1] + p_margin));
+btCollisionShape *CapsuleShapeBullet::create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge) {
+ return prepare(ShapeBullet::create_shape_capsule(radius * p_implicit_scale[0] + p_extra_edge, height * p_implicit_scale[1] + p_extra_edge));
}
/* Cylinder */
@@ -329,11 +342,13 @@ void ConvexPolygonShapeBullet::setup(const Vector<Vector3> &p_vertices) {
notifyShapeChanged();
}
-btCollisionShape *ConvexPolygonShapeBullet::create_bt_shape(const btVector3 &p_implicit_scale, real_t p_margin) {
+btCollisionShape *ConvexPolygonShapeBullet::create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge) {
+ if (!vertices.size())
+ // This is necessary since 0 vertices
+ return prepare(ShapeBullet::create_shape_empty());
btCollisionShape *cs(ShapeBullet::create_shape_convex(vertices));
cs->setLocalScaling(p_implicit_scale);
prepare(cs);
- cs->setMargin(p_margin);
return cs;
}
@@ -346,7 +361,8 @@ ConcavePolygonShapeBullet::ConcavePolygonShapeBullet() :
ConcavePolygonShapeBullet::~ConcavePolygonShapeBullet() {
if (meshShape) {
delete meshShape->getMeshInterface();
- delete meshShape;
+ delete meshShape->getTriangleInfoMap();
+ bulletdelete(meshShape);
}
faces = PoolVector<Vector3>();
}
@@ -368,6 +384,7 @@ void ConcavePolygonShapeBullet::setup(PoolVector<Vector3> p_faces) {
if (meshShape) {
/// Clear previous created shape
delete meshShape->getMeshInterface();
+ delete meshShape->getTriangleInfoMap();
bulletdelete(meshShape);
}
int src_face_count = faces.size();
@@ -385,16 +402,22 @@ void ConcavePolygonShapeBullet::setup(PoolVector<Vector3> p_faces) {
btVector3 supVec_1;
btVector3 supVec_2;
for (int i = 0; i < src_face_count; ++i) {
- G_TO_B(facesr[i * 3], supVec_0);
+ G_TO_B(facesr[i * 3 + 0], supVec_0);
G_TO_B(facesr[i * 3 + 1], supVec_1);
G_TO_B(facesr[i * 3 + 2], supVec_2);
- shapeInterface->addTriangle(supVec_0, supVec_1, supVec_2);
+ // Inverted from standard godot otherwise btGenerateInternalEdgeInfo generates wrong edge info
+ shapeInterface->addTriangle(supVec_2, supVec_1, supVec_0);
}
const bool useQuantizedAabbCompression = true;
meshShape = bulletnew(btBvhTriangleMeshShape(shapeInterface, useQuantizedAabbCompression));
+
+ if (GLOBAL_DEF("physics/3d/smooth_trimesh_collision", false)) {
+ btTriangleInfoMap *triangleInfoMap = new btTriangleInfoMap();
+ btGenerateInternalEdgeInfo(meshShape, triangleInfoMap);
+ }
} else {
meshShape = NULL;
ERR_PRINT("The faces count are 0, the mesh shape cannot be created");
@@ -402,14 +425,14 @@ void ConcavePolygonShapeBullet::setup(PoolVector<Vector3> p_faces) {
notifyShapeChanged();
}
-btCollisionShape *ConcavePolygonShapeBullet::create_bt_shape(const btVector3 &p_implicit_scale, real_t p_margin) {
+btCollisionShape *ConcavePolygonShapeBullet::create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge) {
btCollisionShape *cs = ShapeBullet::create_shape_concave(meshShape);
if (!cs)
// This is necessary since if 0 faces the creation of concave return NULL
cs = ShapeBullet::create_shape_empty();
cs->setLocalScaling(p_implicit_scale);
prepare(cs);
- cs->setMargin(p_margin);
+ cs->setMargin(0);
return cs;
}
@@ -524,11 +547,10 @@ void HeightMapShapeBullet::setup(PoolVector<real_t> &p_heights, int p_width, int
notifyShapeChanged();
}
-btCollisionShape *HeightMapShapeBullet::create_bt_shape(const btVector3 &p_implicit_scale, real_t p_margin) {
+btCollisionShape *HeightMapShapeBullet::create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge) {
btCollisionShape *cs(ShapeBullet::create_shape_height_field(heights, width, depth, min_height, max_height));
cs->setLocalScaling(p_implicit_scale);
prepare(cs);
- cs->setMargin(p_margin);
return cs;
}
@@ -562,6 +584,6 @@ void RayShapeBullet::setup(real_t p_length, bool p_slips_on_slope) {
notifyShapeChanged();
}
-btCollisionShape *RayShapeBullet::create_bt_shape(const btVector3 &p_implicit_scale, real_t p_margin) {
- return prepare(ShapeBullet::create_shape_ray(length * p_implicit_scale[1] + p_margin, slips_on_slope));
+btCollisionShape *RayShapeBullet::create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge) {
+ return prepare(ShapeBullet::create_shape_ray(length * p_implicit_scale[1] + p_extra_edge, slips_on_slope));
}
diff --git a/modules/bullet/shape_bullet.h b/modules/bullet/shape_bullet.h
index 16a5ac1fc6..9a1c8f5bfa 100644
--- a/modules/bullet/shape_bullet.h
+++ b/modules/bullet/shape_bullet.h
@@ -31,8 +31,8 @@
#ifndef SHAPE_BULLET_H
#define SHAPE_BULLET_H
+#include "core/math/geometry.h"
#include "core/variant.h"
-#include "geometry.h"
#include "rid_bullet.h"
#include "servers/physics_server.h"
@@ -52,6 +52,7 @@ class btBvhTriangleMeshShape;
class ShapeBullet : public RIDBullet {
Map<ShapeOwnerBullet *, int> owners;
+ real_t margin;
protected:
/// return self
@@ -62,14 +63,17 @@ public:
ShapeBullet();
virtual ~ShapeBullet();
- btCollisionShape *create_bt_shape(const Vector3 &p_implicit_scale, real_t p_margin = 0);
- virtual btCollisionShape *create_bt_shape(const btVector3 &p_implicit_scale, real_t p_margin = 0) = 0;
+ btCollisionShape *create_bt_shape(const Vector3 &p_implicit_scale, real_t p_extra_edge = 0);
+ virtual btCollisionShape *create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge = 0) = 0;
void add_owner(ShapeOwnerBullet *p_owner);
void remove_owner(ShapeOwnerBullet *p_owner, bool p_permanentlyFromThisBody = false);
bool is_owner(ShapeOwnerBullet *p_owner) const;
const Map<ShapeOwnerBullet *, int> &get_owners() const;
+ void set_margin(real_t p_margin);
+ real_t get_margin() const;
+
/// Setup the shape
virtual void set_data(const Variant &p_data) = 0;
virtual Variant get_data() const = 0;
@@ -100,7 +104,7 @@ public:
virtual void set_data(const Variant &p_data);
virtual Variant get_data() const;
virtual PhysicsServer::ShapeType get_type() const;
- virtual btCollisionShape *create_bt_shape(const btVector3 &p_implicit_scale, real_t p_margin = 0);
+ virtual btCollisionShape *create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge = 0);
private:
void setup(const Plane &p_plane);
@@ -117,7 +121,7 @@ public:
virtual void set_data(const Variant &p_data);
virtual Variant get_data() const;
virtual PhysicsServer::ShapeType get_type() const;
- virtual btCollisionShape *create_bt_shape(const btVector3 &p_implicit_scale, real_t p_margin = 0);
+ virtual btCollisionShape *create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge = 0);
private:
void setup(real_t p_radius);
@@ -134,7 +138,7 @@ public:
virtual void set_data(const Variant &p_data);
virtual Variant get_data() const;
virtual PhysicsServer::ShapeType get_type() const;
- virtual btCollisionShape *create_bt_shape(const btVector3 &p_implicit_scale, real_t p_margin = 0);
+ virtual btCollisionShape *create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge = 0);
private:
void setup(const Vector3 &p_half_extents);
@@ -153,7 +157,7 @@ public:
virtual void set_data(const Variant &p_data);
virtual Variant get_data() const;
virtual PhysicsServer::ShapeType get_type() const;
- virtual btCollisionShape *create_bt_shape(const btVector3 &p_implicit_scale, real_t p_margin = 0);
+ virtual btCollisionShape *create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge = 0);
private:
void setup(real_t p_height, real_t p_radius);
@@ -189,7 +193,7 @@ public:
void get_vertices(Vector<Vector3> &out_vertices);
virtual Variant get_data() const;
virtual PhysicsServer::ShapeType get_type() const;
- virtual btCollisionShape *create_bt_shape(const btVector3 &p_implicit_scale, real_t p_margin = 0);
+ virtual btCollisionShape *create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge = 0);
private:
void setup(const Vector<Vector3> &p_vertices);
@@ -207,7 +211,7 @@ public:
virtual void set_data(const Variant &p_data);
virtual Variant get_data() const;
virtual PhysicsServer::ShapeType get_type() const;
- virtual btCollisionShape *create_bt_shape(const btVector3 &p_implicit_scale, real_t p_margin = 0);
+ virtual btCollisionShape *create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge = 0);
private:
void setup(PoolVector<Vector3> p_faces);
@@ -227,7 +231,7 @@ public:
virtual void set_data(const Variant &p_data);
virtual Variant get_data() const;
virtual PhysicsServer::ShapeType get_type() const;
- virtual btCollisionShape *create_bt_shape(const btVector3 &p_implicit_scale, real_t p_margin = 0);
+ virtual btCollisionShape *create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge = 0);
private:
void setup(PoolVector<real_t> &p_heights, int p_width, int p_depth, real_t p_min_height, real_t p_max_height);
@@ -244,7 +248,7 @@ public:
virtual void set_data(const Variant &p_data);
virtual Variant get_data() const;
virtual PhysicsServer::ShapeType get_type() const;
- virtual btCollisionShape *create_bt_shape(const btVector3 &p_implicit_scale, real_t p_margin = 0);
+ virtual btCollisionShape *create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge = 0);
private:
void setup(real_t p_length, bool p_slips_on_slope);
diff --git a/modules/bullet/shape_owner_bullet.h b/modules/bullet/shape_owner_bullet.h
index 29d42d12f2..72ddbc482c 100644
--- a/modules/bullet/shape_owner_bullet.h
+++ b/modules/bullet/shape_owner_bullet.h
@@ -45,11 +45,10 @@ class CollisionObjectBullet;
/// E.G. BodyShape is a child of this
class ShapeOwnerBullet {
public:
- /// This is used to set new shape or replace existing
- //virtual void _internal_replaceShape(btCollisionShape *p_old_shape, btCollisionShape *p_new_shape) = 0;
- virtual void on_shape_changed(const ShapeBullet *const p_shape) = 0;
- virtual void on_shapes_changed() = 0;
- virtual void remove_shape(class ShapeBullet *p_shape) = 0;
+ virtual int find_shape(ShapeBullet *p_shape) const = 0;
+ virtual void shape_changed(int p_shape_index) = 0;
+ virtual void reload_shapes() = 0;
+ virtual void remove_shape_full(class ShapeBullet *p_shape) = 0;
virtual ~ShapeOwnerBullet() {}
};
#endif
diff --git a/modules/bullet/slider_joint_bullet.cpp b/modules/bullet/slider_joint_bullet.cpp
index 9e1cd23989..9016ec3bf5 100644
--- a/modules/bullet/slider_joint_bullet.cpp
+++ b/modules/bullet/slider_joint_bullet.cpp
@@ -366,6 +366,7 @@ void SliderJointBullet::set_param(PhysicsServer::SliderJointParam p_param, real_
case PhysicsServer::SLIDER_JOINT_ANGULAR_ORTHOGONAL_SOFTNESS: setSoftnessOrthoAng(p_value); break;
case PhysicsServer::SLIDER_JOINT_ANGULAR_ORTHOGONAL_RESTITUTION: setRestitutionOrthoAng(p_value); break;
case PhysicsServer::SLIDER_JOINT_ANGULAR_ORTHOGONAL_DAMPING: setDampingOrthoAng(p_value); break;
+ case PhysicsServer::SLIDER_JOINT_MAX: break; // Can't happen, but silences warning
}
}
diff --git a/modules/bullet/soft_body_bullet.cpp b/modules/bullet/soft_body_bullet.cpp
index 9fc7230f91..94f350210f 100644
--- a/modules/bullet/soft_body_bullet.cpp
+++ b/modules/bullet/soft_body_bullet.cpp
@@ -37,17 +37,17 @@
SoftBodyBullet::SoftBodyBullet() :
CollisionObjectBullet(CollisionObjectBullet::TYPE_SOFT_BODY),
- total_mass(1),
+ bt_soft_body(NULL),
+ isScratched(false),
simulation_precision(5),
+ total_mass(1.),
linear_stiffness(0.5),
areaAngular_stiffness(0.5),
volume_stiffness(0.5),
pressure_coefficient(0.),
pose_matching_coefficient(0.),
damping_coefficient(0.01),
- drag_coefficient(0.),
- bt_soft_body(NULL),
- isScratched(false) {}
+ drag_coefficient(0.) {}
SoftBodyBullet::~SoftBodyBullet() {
}
@@ -72,12 +72,6 @@ void SoftBodyBullet::set_space(SpaceBullet *p_space) {
}
}
-void SoftBodyBullet::dispatch_callbacks() {}
-
-void SoftBodyBullet::on_collision_filters_change() {}
-
-void SoftBodyBullet::on_collision_checker_start() {}
-
void SoftBodyBullet::on_enter_area(AreaBullet *p_area) {}
void SoftBodyBullet::on_exit_area(AreaBullet *p_area) {}
diff --git a/modules/bullet/soft_body_bullet.h b/modules/bullet/soft_body_bullet.h
index c775193584..d04bfca046 100644
--- a/modules/bullet/soft_body_bullet.h
+++ b/modules/bullet/soft_body_bullet.h
@@ -91,9 +91,10 @@ public:
virtual void reload_body();
virtual void set_space(SpaceBullet *p_space);
- virtual void dispatch_callbacks();
- virtual void on_collision_filters_change();
- virtual void on_collision_checker_start();
+ virtual void dispatch_callbacks() {}
+ virtual void on_collision_filters_change() {}
+ virtual void on_collision_checker_start() {}
+ virtual void on_collision_checker_end() {}
virtual void on_enter_area(AreaBullet *p_area);
virtual void on_exit_area(AreaBullet *p_area);
diff --git a/modules/bullet/space_bullet.cpp b/modules/bullet/space_bullet.cpp
index 8454bea4eb..fed12cd5ed 100644
--- a/modules/bullet/space_bullet.cpp
+++ b/modules/bullet/space_bullet.cpp
@@ -34,13 +34,13 @@
#include "bullet_types_converter.h"
#include "bullet_utilities.h"
#include "constraint_bullet.h"
+#include "core/project_settings.h"
+#include "core/ustring.h"
#include "godot_collision_configuration.h"
#include "godot_collision_dispatcher.h"
-#include "project_settings.h"
#include "rigid_body_bullet.h"
#include "servers/physics_server.h"
#include "soft_body_bullet.h"
-#include "ustring.h"
#include <BulletCollision/CollisionDispatch/btCollisionObject.h>
#include <BulletCollision/CollisionDispatch/btGhostObject.h>
@@ -61,7 +61,7 @@ BulletPhysicsDirectSpaceState::BulletPhysicsDirectSpaceState(SpaceBullet *p_spac
PhysicsDirectSpaceState(),
space(p_space) {}
-int BulletPhysicsDirectSpaceState::intersect_point(const Vector3 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask) {
+int BulletPhysicsDirectSpaceState::intersect_point(const Vector3 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) {
if (p_result_max <= 0)
return 0;
@@ -69,13 +69,13 @@ int BulletPhysicsDirectSpaceState::intersect_point(const Vector3 &p_point, Shape
btVector3 bt_point;
G_TO_B(p_point, bt_point);
- btSphereShape sphere_point(0.f);
+ btSphereShape sphere_point(0.001f);
btCollisionObject collision_object_point;
collision_object_point.setCollisionShape(&sphere_point);
collision_object_point.setWorldTransform(btTransform(btQuaternion::getIdentity(), bt_point));
// Setup query
- GodotAllContactResultCallback btResult(&collision_object_point, r_results, p_result_max, &p_exclude);
+ GodotAllContactResultCallback btResult(&collision_object_point, r_results, p_result_max, &p_exclude, p_collide_with_bodies, p_collide_with_areas);
btResult.m_collisionFilterGroup = 0;
btResult.m_collisionFilterMask = p_collision_mask;
space->dynamicsWorld->contactTest(&collision_object_point, btResult);
@@ -84,7 +84,7 @@ int BulletPhysicsDirectSpaceState::intersect_point(const Vector3 &p_point, Shape
return btResult.m_count;
}
-bool BulletPhysicsDirectSpaceState::intersect_ray(const Vector3 &p_from, const Vector3 &p_to, RayResult &r_result, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_pick_ray) {
+bool BulletPhysicsDirectSpaceState::intersect_ray(const Vector3 &p_from, const Vector3 &p_to, RayResult &r_result, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas, bool p_pick_ray) {
btVector3 btVec_from;
btVector3 btVec_to;
@@ -93,7 +93,7 @@ bool BulletPhysicsDirectSpaceState::intersect_ray(const Vector3 &p_from, const V
G_TO_B(p_to, btVec_to);
// setup query
- GodotClosestRayResultCallback btResult(btVec_from, btVec_to, &p_exclude);
+ GodotClosestRayResultCallback btResult(btVec_from, btVec_to, &p_exclude, p_collide_with_bodies, p_collide_with_areas);
btResult.m_collisionFilterGroup = 0;
btResult.m_collisionFilterMask = p_collision_mask;
btResult.m_pickRay = p_pick_ray;
@@ -117,7 +117,7 @@ bool BulletPhysicsDirectSpaceState::intersect_ray(const Vector3 &p_from, const V
}
}
-int BulletPhysicsDirectSpaceState::intersect_shape(const RID &p_shape, const Transform &p_xform, float p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask) {
+int BulletPhysicsDirectSpaceState::intersect_shape(const RID &p_shape, const Transform &p_xform, float p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) {
if (p_result_max <= 0)
return 0;
@@ -139,7 +139,7 @@ int BulletPhysicsDirectSpaceState::intersect_shape(const RID &p_shape, const Tra
collision_object.setCollisionShape(btConvex);
collision_object.setWorldTransform(bt_xform);
- GodotAllContactResultCallback btQuery(&collision_object, r_results, p_result_max, &p_exclude);
+ GodotAllContactResultCallback btQuery(&collision_object, r_results, p_result_max, &p_exclude, p_collide_with_bodies, p_collide_with_areas);
btQuery.m_collisionFilterGroup = 0;
btQuery.m_collisionFilterMask = p_collision_mask;
btQuery.m_closestDistanceThreshold = 0;
@@ -150,14 +150,14 @@ int BulletPhysicsDirectSpaceState::intersect_shape(const RID &p_shape, const Tra
return btQuery.m_count;
}
-bool BulletPhysicsDirectSpaceState::cast_motion(const RID &p_shape, const Transform &p_xform, const Vector3 &p_motion, float p_margin, float &p_closest_safe, float &p_closest_unsafe, const Set<RID> &p_exclude, uint32_t p_collision_mask, ShapeRestInfo *r_info) {
+bool BulletPhysicsDirectSpaceState::cast_motion(const RID &p_shape, const Transform &p_xform, const Vector3 &p_motion, float p_margin, float &r_closest_safe, float &r_closest_unsafe, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas, ShapeRestInfo *r_info) {
ShapeBullet *shape = space->get_physics_server()->get_shape_owner()->get(p_shape);
btCollisionShape *btShape = shape->create_bt_shape(p_xform.basis.get_scale(), p_margin);
if (!btShape->isConvex()) {
bulletdelete(btShape);
ERR_PRINTS("The shape is not a convex shape, then is not supported: shape type: " + itos(shape->get_type()));
- return 0;
+ return false;
}
btConvexShape *bt_convex_shape = static_cast<btConvexShape *>(btShape);
@@ -171,14 +171,19 @@ bool BulletPhysicsDirectSpaceState::cast_motion(const RID &p_shape, const Transf
btTransform bt_xform_to(bt_xform_from);
bt_xform_to.getOrigin() += bt_motion;
- GodotClosestConvexResultCallback btResult(bt_xform_from.getOrigin(), bt_xform_to.getOrigin(), &p_exclude);
+ 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;
- space->dynamicsWorld->convexSweepTest(bt_convex_shape, bt_xform_from, bt_xform_to, btResult, 0.002);
+ space->dynamicsWorld->convexSweepTest(bt_convex_shape, bt_xform_from, bt_xform_to, btResult, space->dynamicsWorld->getDispatchInfo().m_allowedCcdPenetration);
+
+ r_closest_unsafe = 1.0;
+ r_closest_safe = 1.0;
if (btResult.hasHit()) {
- p_closest_safe = p_closest_unsafe = btResult.m_closestHitFraction;
+ const btScalar l = bt_motion.length();
+ r_closest_unsafe = btResult.m_closestHitFraction;
+ r_closest_safe = MAX(r_closest_unsafe - (1 - ((l - 0.01) / l)), 0);
if (r_info) {
if (btCollisionObject::CO_RIGID_BODY == btResult.m_hitCollisionObject->getInternalType()) {
B_TO_G(static_cast<const btRigidBody *>(btResult.m_hitCollisionObject)->getVelocityInLocalPoint(btResult.m_hitPointWorld), r_info->linear_velocity);
@@ -193,11 +198,11 @@ bool BulletPhysicsDirectSpaceState::cast_motion(const RID &p_shape, const Transf
}
bulletdelete(bt_convex_shape);
- return btResult.hasHit();
+ return true; // Mean success
}
/// Returns the list of contacts pairs in this order: Local contact, other body contact
-bool BulletPhysicsDirectSpaceState::collide_shape(RID p_shape, const Transform &p_shape_xform, float p_margin, Vector3 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude, uint32_t p_collision_mask) {
+bool BulletPhysicsDirectSpaceState::collide_shape(RID p_shape, const Transform &p_shape_xform, float p_margin, Vector3 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) {
if (p_result_max <= 0)
return 0;
@@ -219,7 +224,7 @@ bool BulletPhysicsDirectSpaceState::collide_shape(RID p_shape, const Transform &
collision_object.setCollisionShape(btConvex);
collision_object.setWorldTransform(bt_xform);
- GodotContactPairContactResultCallback btQuery(&collision_object, r_results, p_result_max, &p_exclude);
+ GodotContactPairContactResultCallback btQuery(&collision_object, r_results, p_result_max, &p_exclude, p_collide_with_bodies, p_collide_with_areas);
btQuery.m_collisionFilterGroup = 0;
btQuery.m_collisionFilterMask = p_collision_mask;
btQuery.m_closestDistanceThreshold = 0;
@@ -231,7 +236,7 @@ bool BulletPhysicsDirectSpaceState::collide_shape(RID p_shape, const Transform &
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 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()->get(p_shape);
@@ -251,7 +256,7 @@ bool BulletPhysicsDirectSpaceState::rest_info(RID p_shape, const Transform &p_sh
collision_object.setCollisionShape(btConvex);
collision_object.setWorldTransform(bt_xform);
- GodotRestInfoContactResultCallback btQuery(&collision_object, r_info, &p_exclude);
+ GodotRestInfoContactResultCallback btQuery(&collision_object, r_info, &p_exclude, p_collide_with_bodies, p_collide_with_areas);
btQuery.m_collisionFilterGroup = 0;
btQuery.m_collisionFilterMask = p_collision_mask;
btQuery.m_closestDistanceThreshold = 0;
@@ -293,11 +298,10 @@ Vector3 BulletPhysicsDirectSpaceState::get_closest_point_to_object_volume(RID p_
bool shapes_found = false;
- btCompoundShape *compound = rigid_object->get_compound_shape();
- for (int i = compound->getNumChildShapes() - 1; 0 <= i; --i) {
- shape = compound->getChildShape(i);
+ for (int i = rigid_object->get_shape_count() - 1; 0 <= i; --i) {
+ shape = rigid_object->get_bt_shape(i);
if (shape->isConvex()) {
- child_transform = compound->getChildTransform(i);
+ child_transform = rigid_object->get_bt_shape_transform(i);
convex_shape = static_cast<btConvexShape *>(shape);
input.m_transformB = body_transform * child_transform;
@@ -328,16 +332,17 @@ Vector3 BulletPhysicsDirectSpaceState::get_closest_point_to_object_volume(RID p_
SpaceBullet::SpaceBullet() :
broadphase(NULL),
+ collisionConfiguration(NULL),
dispatcher(NULL),
solver(NULL),
- collisionConfiguration(NULL),
dynamicsWorld(NULL),
soft_body_world_info(NULL),
ghostPairCallback(NULL),
godotFilterCallback(NULL),
gravityDirection(0, -1, 0),
gravityMagnitude(10),
- contactDebugCount(0) {
+ contactDebugCount(0),
+ delta_time(0.) {
create_empty_world(GLOBAL_DEF("physics/3d/active_soft_world", true));
direct_access = memnew(BulletPhysicsDirectSpaceState(this));
@@ -535,17 +540,20 @@ void onBulletPreTickCallback(btDynamicsWorld *p_dynamicsWorld, btScalar timeStep
void onBulletTickCallback(btDynamicsWorld *p_dynamicsWorld, btScalar timeStep) {
- // Notify all Collision objects the collision checker is started
const btCollisionObjectArray &colObjArray = p_dynamicsWorld->getCollisionObjectArray();
+
+ // Notify all Collision objects the collision checker is started
for (int i = colObjArray.size() - 1; 0 <= i; --i) {
- CollisionObjectBullet *colObj = static_cast<CollisionObjectBullet *>(colObjArray[i]->getUserPointer());
- assert(NULL != colObj);
- colObj->on_collision_checker_start();
+ static_cast<CollisionObjectBullet *>(colObjArray[i]->getUserPointer())->on_collision_checker_start();
}
SpaceBullet *sb = static_cast<SpaceBullet *>(p_dynamicsWorld->getWorldUserInfo());
sb->check_ghost_overlaps();
sb->check_body_collision();
+
+ for (int i = colObjArray.size() - 1; 0 <= i; --i) {
+ static_cast<CollisionObjectBullet *>(colObjArray[i]->getUserPointer())->on_collision_checker_end();
+ }
}
BulletPhysicsDirectSpaceState *SpaceBullet::get_direct_state() {
@@ -554,49 +562,18 @@ BulletPhysicsDirectSpaceState *SpaceBullet::get_direct_state() {
btScalar calculateGodotCombinedRestitution(const btCollisionObject *body0, const btCollisionObject *body1) {
- const PhysicsServer::CombineMode cm = static_cast<RigidBodyBullet *>(body0->getUserPointer())->get_restitution_combine_mode();
-
- switch (cm) {
- case PhysicsServer::COMBINE_MODE_INHERIT:
- if (static_cast<RigidBodyBullet *>(body1->getUserPointer())->get_restitution_combine_mode() != PhysicsServer::COMBINE_MODE_INHERIT)
- return calculateGodotCombinedRestitution(body1, body0);
- // else use MAX [This is used when the two bodies doesn't use physical material]
- case PhysicsServer::COMBINE_MODE_MAX:
- return MAX(body0->getRestitution(), body1->getRestitution());
- case PhysicsServer::COMBINE_MODE_MIN:
- return MIN(body0->getRestitution(), body1->getRestitution());
- case PhysicsServer::COMBINE_MODE_MULTIPLY:
- return body0->getRestitution() * body1->getRestitution();
- default: // Is always PhysicsServer::COMBINE_MODE_AVERAGE:
- return (body0->getRestitution() + body1->getRestitution()) / 2;
- }
+ return CLAMP(body0->getRestitution() + body1->getRestitution(), 0, 1);
}
btScalar calculateGodotCombinedFriction(const btCollisionObject *body0, const btCollisionObject *body1) {
- const PhysicsServer::CombineMode cm = static_cast<RigidBodyBullet *>(body0->getUserPointer())->get_friction_combine_mode();
-
- switch (cm) {
- case PhysicsServer::COMBINE_MODE_INHERIT:
- if (static_cast<RigidBodyBullet *>(body1->getUserPointer())->get_friction_combine_mode() != PhysicsServer::COMBINE_MODE_INHERIT)
- return calculateGodotCombinedFriction(body1, body0);
- // else use MULTIPLY [This is used when the two bodies doesn't use physical material]
- case PhysicsServer::COMBINE_MODE_MULTIPLY:
- return body0->getFriction() * body1->getFriction();
- case PhysicsServer::COMBINE_MODE_MAX:
- return MAX(body0->getFriction(), body1->getFriction());
- case PhysicsServer::COMBINE_MODE_MIN:
- return MIN(body0->getFriction(), body1->getFriction());
- default: // Is always PhysicsServer::COMBINE_MODE_AVERAGE:
- return (body0->getFriction() * body1->getFriction()) / 2;
- }
+ return ABS(MIN(body0->getFriction(), body1->getFriction()));
}
void SpaceBullet::create_empty_world(bool p_create_soft_world) {
gjk_epa_pen_solver = bulletnew(btGjkEpaPenetrationDepthSolver);
gjk_simplex_solver = bulletnew(btVoronoiSimplexSolver);
- gjk_simplex_solver->setEqualVertexThreshold(0.f);
void *world_mem;
if (p_create_soft_world) {
@@ -606,7 +583,7 @@ void SpaceBullet::create_empty_world(bool p_create_soft_world) {
}
if (p_create_soft_world) {
- collisionConfiguration = bulletnew(btSoftBodyRigidBodyCollisionConfiguration);
+ collisionConfiguration = bulletnew(GodotSoftCollisionConfiguration(static_cast<btDiscreteDynamicsWorld *>(world_mem)));
} else {
collisionConfiguration = bulletnew(GodotCollisionConfiguration(static_cast<btDiscreteDynamicsWorld *>(world_mem)));
}
@@ -626,6 +603,7 @@ void SpaceBullet::create_empty_world(bool p_create_soft_world) {
godotFilterCallback = bulletnew(GodotFilterCallback);
gCalculateCombinedRestitutionCallback = &calculateGodotCombinedRestitution;
gCalculateCombinedFrictionCallback = &calculateGodotCombinedFriction;
+ gContactAddedCallback = &godotContactAddedCallback;
dynamicsWorld->setWorldUserInfo(this);
@@ -670,11 +648,10 @@ void SpaceBullet::destroy_world() {
void SpaceBullet::check_ghost_overlaps() {
/// Algorithm support variables
- btConvexShape *other_body_shape;
+ btCollisionShape *other_body_shape;
btConvexShape *area_shape;
btGjkPairDetector::ClosestPointInput gjk_input;
AreaBullet *area;
- RigidCollisionObjectBullet *otherObject;
int x(-1), i(-1), y(-1), z(-1), indexOverlap(-1);
/// For each areas
@@ -701,41 +678,67 @@ void SpaceBullet::check_ghost_overlaps() {
// For each overlapping
for (i = ghostOverlaps.size() - 1; 0 <= i; --i) {
- if (ghostOverlaps[i]->getUserIndex() == CollisionObjectBullet::TYPE_AREA) {
- if (!static_cast<AreaBullet *>(ghostOverlaps[i]->getUserPointer())->is_monitorable())
- continue;
- } else if (ghostOverlaps[i]->getUserIndex() != CollisionObjectBullet::TYPE_RIGID_BODY)
+ btCollisionObject *overlapped_bt_co = ghostOverlaps[i];
+ RigidCollisionObjectBullet *otherObject = static_cast<RigidCollisionObjectBullet *>(overlapped_bt_co->getUserPointer());
+
+ if (!area->is_transform_changed() && !otherObject->is_transform_changed())
continue;
- otherObject = static_cast<RigidCollisionObjectBullet *>(ghostOverlaps[i]->getUserPointer());
+ if (overlapped_bt_co->getUserIndex() == CollisionObjectBullet::TYPE_AREA) {
+ if (!static_cast<AreaBullet *>(overlapped_bt_co->getUserPointer())->is_monitorable())
+ continue;
+ } else if (overlapped_bt_co->getUserIndex() != CollisionObjectBullet::TYPE_RIGID_BODY)
+ continue;
bool hasOverlap = false;
// For each area shape
- for (y = area->get_compound_shape()->getNumChildShapes() - 1; 0 <= y; --y) {
- if (!area->get_compound_shape()->getChildShape(y)->isConvex())
+ for (y = area->get_shape_count() - 1; 0 <= y; --y) {
+ if (!area->get_bt_shape(y)->isConvex())
continue;
- gjk_input.m_transformA = area->get_transform__bullet() * area->get_compound_shape()->getChildTransform(y);
- area_shape = static_cast<btConvexShape *>(area->get_compound_shape()->getChildShape(y));
+ gjk_input.m_transformA = area->get_transform__bullet() * area->get_bt_shape_transform(y);
+ area_shape = static_cast<btConvexShape *>(area->get_bt_shape(y));
// For each other object shape
- for (z = otherObject->get_compound_shape()->getNumChildShapes() - 1; 0 <= z; --z) {
+ for (z = otherObject->get_shape_count() - 1; 0 <= z; --z) {
+
+ other_body_shape = static_cast<btCollisionShape *>(otherObject->get_bt_shape(z));
+ gjk_input.m_transformB = otherObject->get_transform__bullet() * otherObject->get_bt_shape_transform(z);
+
+ if (other_body_shape->isConvex()) {
- if (!otherObject->get_compound_shape()->getChildShape(z)->isConvex())
- continue;
+ btPointCollector result;
+ btGjkPairDetector gjk_pair_detector(area_shape, static_cast<btConvexShape *>(other_body_shape), gjk_simplex_solver, gjk_epa_pen_solver);
+ gjk_pair_detector.getClosestPoints(gjk_input, result, 0);
+
+ if (0 >= result.m_distance) {
+ hasOverlap = true;
+ goto collision_found;
+ }
+
+ } else {
- other_body_shape = static_cast<btConvexShape *>(otherObject->get_compound_shape()->getChildShape(z));
- gjk_input.m_transformB = otherObject->get_transform__bullet() * otherObject->get_compound_shape()->getChildTransform(z);
+ btCollisionObjectWrapper obA(NULL, area_shape, area->get_bt_ghost(), gjk_input.m_transformA, -1, y);
+ btCollisionObjectWrapper obB(NULL, other_body_shape, otherObject->get_bt_collision_object(), gjk_input.m_transformB, -1, z);
- btPointCollector result;
- btGjkPairDetector gjk_pair_detector(area_shape, other_body_shape, gjk_simplex_solver, gjk_epa_pen_solver);
- gjk_pair_detector.getClosestPoints(gjk_input, result, 0);
+ btCollisionAlgorithm *algorithm = dispatcher->findAlgorithm(&obA, &obB, NULL, BT_CONTACT_POINT_ALGORITHMS);
- if (0 >= result.m_distance) {
- hasOverlap = true;
- goto collision_found;
+ if (!algorithm)
+ continue;
+
+ GodotDeepPenetrationContactResultCallback contactPointResult(&obA, &obB);
+ algorithm->processCollision(&obA, &obB, dynamicsWorld->getDispatchInfo(), &contactPointResult);
+
+ algorithm->~btCollisionAlgorithm();
+ dispatcher->freeCollisionAlgorithm(algorithm);
+
+ if (contactPointResult.hasHit()) {
+ hasOverlap = true;
+ goto collision_found;
+ }
}
+
} // ~For each other object shape
} // ~For each area shape
@@ -783,39 +786,47 @@ void SpaceBullet::check_body_collision() {
}
const int numContacts = contactManifold->getNumContacts();
+
+ /// Since I don't need report all contacts for these objects,
+ /// So report only the first
#define REPORT_ALL_CONTACTS 0
#if REPORT_ALL_CONTACTS
for (int j = 0; j < numContacts; j++) {
btManifoldPoint &pt = contactManifold->getContactPoint(j);
#else
- // Since I don't need report all contacts for these objects, I'll report only the first
if (numContacts) {
btManifoldPoint &pt = contactManifold->getContactPoint(0);
#endif
- Vector3 collisionWorldPosition;
- Vector3 collisionLocalPosition;
- Vector3 normalOnB;
- float appliedImpulse = pt.m_appliedImpulse;
- B_TO_G(pt.m_normalWorldOnB, normalOnB);
-
- if (bodyA->can_add_collision()) {
- B_TO_G(pt.getPositionWorldOnB(), collisionWorldPosition);
- /// pt.m_localPointB Doesn't report the exact point in local space
- B_TO_G(pt.getPositionWorldOnB() - contactManifold->getBody1()->getWorldTransform().getOrigin(), collisionLocalPosition);
- bodyA->add_collision_object(bodyB, collisionWorldPosition, collisionLocalPosition, normalOnB, appliedImpulse, pt.m_index1, pt.m_index0);
- }
- if (bodyB->can_add_collision()) {
- B_TO_G(pt.getPositionWorldOnA(), collisionWorldPosition);
- /// pt.m_localPointA Doesn't report the exact point in local space
- B_TO_G(pt.getPositionWorldOnA() - contactManifold->getBody0()->getWorldTransform().getOrigin(), collisionLocalPosition);
- bodyB->add_collision_object(bodyA, collisionWorldPosition, collisionLocalPosition, normalOnB * -1, appliedImpulse * -1, pt.m_index0, pt.m_index1);
- }
+ if (
+ pt.getDistance() <= 0.0 ||
+ bodyA->was_colliding(bodyB) ||
+ bodyB->was_colliding(bodyA)) {
+
+ Vector3 collisionWorldPosition;
+ Vector3 collisionLocalPosition;
+ Vector3 normalOnB;
+ float appliedImpulse = pt.m_appliedImpulse;
+ B_TO_G(pt.m_normalWorldOnB, normalOnB);
+
+ if (bodyA->can_add_collision()) {
+ B_TO_G(pt.getPositionWorldOnB(), collisionWorldPosition);
+ /// pt.m_localPointB Doesn't report the exact point in local space
+ B_TO_G(pt.getPositionWorldOnB() - contactManifold->getBody1()->getWorldTransform().getOrigin(), collisionLocalPosition);
+ bodyA->add_collision_object(bodyB, collisionWorldPosition, collisionLocalPosition, normalOnB, appliedImpulse, pt.m_index1, pt.m_index0);
+ }
+ if (bodyB->can_add_collision()) {
+ B_TO_G(pt.getPositionWorldOnA(), collisionWorldPosition);
+ /// pt.m_localPointA Doesn't report the exact point in local space
+ B_TO_G(pt.getPositionWorldOnA() - contactManifold->getBody0()->getWorldTransform().getOrigin(), collisionLocalPosition);
+ bodyB->add_collision_object(bodyA, collisionWorldPosition, collisionLocalPosition, normalOnB * -1, appliedImpulse * -1, pt.m_index0, pt.m_index1);
+ }
#ifdef DEBUG_ENABLED
- if (is_debugging_contacts()) {
- add_debug_contact(collisionWorldPosition);
- }
+ if (is_debugging_contacts()) {
+ add_debug_contact(collisionWorldPosition);
+ }
#endif
+ }
}
}
}
@@ -849,7 +860,7 @@ static Ref<SpatialMaterial> red_mat;
static Ref<SpatialMaterial> blue_mat;
#endif
-bool SpaceBullet::test_body_motion(RigidBodyBullet *p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, PhysicsServer::MotionResult *r_result) {
+bool SpaceBullet::test_body_motion(RigidBodyBullet *p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, PhysicsServer::MotionResult *r_result, bool p_exclude_raycast_shapes) {
#if debug_test_motion
/// Yes I know this is not good, but I've used it as fast debugging hack.
@@ -924,6 +935,12 @@ bool SpaceBullet::test_body_motion(RigidBodyBullet *p_body, const Transform &p_f
// Skip no convex shape
continue;
}
+
+ if (p_exclude_raycast_shapes && p_body->get_bt_shape(shIndex)->getShapeType() == CUSTOM_CONVEX_SHAPE_TYPE) {
+ // Skip rayshape in order to implement custom separation process
+ continue;
+ }
+
btConvexShape *convex_shape_test(static_cast<btConvexShape *>(p_body->get_bt_shape(shIndex)));
btTransform shape_world_from = body_transform * p_body->get_kinematic_utilities()->shapes[shIndex].transform;
@@ -954,11 +971,11 @@ bool SpaceBullet::test_body_motion(RigidBodyBullet *p_body, const Transform &p_f
btVector3 __rec(0, 0, 0);
RecoverResult r_recover_result;
- has_penetration = recover_from_penetration(p_body, body_transform, 0, p_infinite_inertia, __rec, &r_recover_result);
+ has_penetration = recover_from_penetration(p_body, body_transform, 1, p_infinite_inertia, __rec, &r_recover_result);
// Parse results
if (r_result) {
- B_TO_G(motion + initial_recover_motion, r_result->motion);
+ B_TO_G(motion + initial_recover_motion + __rec, r_result->motion);
if (has_penetration) {
@@ -994,6 +1011,39 @@ bool SpaceBullet::test_body_motion(RigidBodyBullet *p_body, const Transform &p_f
return has_penetration;
}
+int SpaceBullet::test_ray_separation(RigidBodyBullet *p_body, const Transform &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, PhysicsServer::SeparationResult *r_results, int p_result_max, float p_margin) {
+
+ btTransform body_transform;
+ G_TO_B(p_transform, body_transform);
+ UNSCALE_BT_BASIS(body_transform);
+
+ btVector3 recover_motion(0, 0, 0);
+
+ int rays_found = 0;
+
+ for (int t(RECOVERING_MOVEMENT_CYCLES); 0 < t; --t) {
+ int last_ray_index = recover_from_penetration_ray(p_body, body_transform, RECOVERING_MOVEMENT_SCALE, p_infinite_inertia, p_result_max, recover_motion, r_results);
+
+ rays_found = MAX(last_ray_index, rays_found);
+ if (!rays_found) {
+ break;
+ } else {
+ body_transform.getOrigin() += recover_motion;
+ }
+ }
+
+ //optimize results (remove non colliding)
+ for (int i = 0; i < rays_found; i++) {
+ if (r_results[i].collision_depth >= 0) {
+ rays_found--;
+ SWAP(r_results[i], r_results[rays_found]);
+ }
+ }
+
+ B_TO_G(recover_motion, r_recover_motion);
+ return rays_found;
+}
+
struct RecoverPenetrationBroadPhaseCallback : public btBroadphaseAabbCallback {
private:
const btCollisionObject *self_collision_object;
@@ -1050,6 +1100,11 @@ bool SpaceBullet::recover_from_penetration(RigidBodyBullet *p_body, const btTran
continue;
}
+ if (kin_shape.shape->getShapeType() == CUSTOM_CONVEX_SHAPE_TYPE) {
+ // Skip rayshape in order to implement custom separation process
+ continue;
+ }
+
body_shape_position = p_body_position * kin_shape.transform;
body_shape_position_recovered = body_shape_position;
body_shape_position_recovered.getOrigin() += r_delta_recover_movement;
@@ -1152,7 +1207,6 @@ bool SpaceBullet::RFP_convex_world_test(const btConvexShape *p_shapeA, const btC
if (contactPointResult.hasHit()) {
r_delta_recover_movement += contactPointResult.m_pointNormalWorld * (contactPointResult.m_penetration_distance * -1 * p_recover_movement_scale);
-
if (r_recover_result) {
if (contactPointResult.m_penetration_distance < r_recover_result->penetration_distance) {
r_recover_result->hasPenetration = true;
@@ -1168,3 +1222,79 @@ bool SpaceBullet::RFP_convex_world_test(const btConvexShape *p_shapeA, const btC
}
return false;
}
+
+int SpaceBullet::recover_from_penetration_ray(RigidBodyBullet *p_body, const btTransform &p_body_position, btScalar p_recover_movement_scale, bool p_infinite_inertia, int p_result_max, btVector3 &r_delta_recover_movement, PhysicsServer::SeparationResult *r_results) {
+
+ RecoverPenetrationBroadPhaseCallback recover_broad_result(p_body->get_bt_collision_object(), p_body->get_collision_layer(), p_body->get_collision_mask());
+
+ btTransform body_shape_position;
+ btTransform body_shape_position_recovered;
+
+ // Broad phase support
+ btVector3 minAabb, maxAabb;
+
+ int ray_index = 0;
+
+ // For each shape
+ for (int kinIndex = p_body->get_kinematic_utilities()->shapes.size() - 1; 0 <= kinIndex; --kinIndex) {
+
+ recover_broad_result.reset();
+
+ if (ray_index >= p_result_max) {
+ break;
+ }
+
+ const RigidBodyBullet::KinematicShape &kin_shape(p_body->get_kinematic_utilities()->shapes[kinIndex]);
+ if (!kin_shape.is_active()) {
+ continue;
+ }
+
+ if (kin_shape.shape->getShapeType() != CUSTOM_CONVEX_SHAPE_TYPE) {
+ continue;
+ }
+
+ body_shape_position = p_body_position * kin_shape.transform;
+ body_shape_position_recovered = body_shape_position;
+ body_shape_position_recovered.getOrigin() += r_delta_recover_movement;
+
+ kin_shape.shape->getAabb(body_shape_position_recovered, minAabb, maxAabb);
+ dynamicsWorld->getBroadphase()->aabbTest(minAabb, maxAabb, recover_broad_result);
+
+ for (int i = recover_broad_result.result_collision_objects.size() - 1; 0 <= i; --i) {
+ btCollisionObject *otherObject = recover_broad_result.result_collision_objects[i];
+ if (p_infinite_inertia && !otherObject->isStaticOrKinematicObject()) {
+ otherObject->activate(); // Force activation of hitten rigid, soft body
+ continue;
+ } else if (!p_body->get_bt_collision_object()->checkCollideWith(otherObject) || !otherObject->checkCollideWith(p_body->get_bt_collision_object()))
+ continue;
+
+ if (otherObject->getCollisionShape()->isCompound()) {
+
+ // Each convex shape
+ btCompoundShape *cs = static_cast<btCompoundShape *>(otherObject->getCollisionShape());
+ for (int x = cs->getNumChildShapes() - 1; 0 <= x; --x) {
+
+ RecoverResult r_recover_result;
+ if (RFP_convex_world_test(kin_shape.shape, cs->getChildShape(x), p_body->get_bt_collision_object(), otherObject, kinIndex, x, body_shape_position, otherObject->getWorldTransform() * cs->getChildTransform(x), p_recover_movement_scale, r_delta_recover_movement, &r_recover_result)) {
+
+ const btRigidBody *btRigid = static_cast<const btRigidBody *>(otherObject);
+ CollisionObjectBullet *collisionObject = static_cast<CollisionObjectBullet *>(otherObject->getUserPointer());
+
+ r_results[ray_index].collision_depth = r_recover_result.penetration_distance;
+ B_TO_G(r_recover_result.pointWorld, r_results[ray_index].collision_point);
+ B_TO_G(r_recover_result.normal, r_results[ray_index].collision_normal);
+ B_TO_G(btRigid->getVelocityInLocalPoint(r_recover_result.pointWorld - btRigid->getWorldTransform().getOrigin()), r_results[ray_index].collider_velocity);
+ r_results[ray_index].collision_local_shape = kinIndex;
+ r_results[ray_index].collider_id = collisionObject->get_instance_id();
+ r_results[ray_index].collider = collisionObject->get_self();
+ r_results[ray_index].collider_shape = r_recover_result.other_compound_shape_index;
+ }
+ }
+ }
+ }
+
+ ++ray_index;
+ }
+
+ return ray_index;
+}
diff --git a/modules/bullet/space_bullet.h b/modules/bullet/space_bullet.h
index 6b86fc2f03..c3d55cbbb1 100644
--- a/modules/bullet/space_bullet.h
+++ b/modules/bullet/space_bullet.h
@@ -57,7 +57,7 @@ class btDiscreteDynamicsWorld;
class btEmptyShape;
class btGhostPairCallback;
class btSoftRigidDynamicsWorld;
-class btSoftBodyWorldInfo;
+struct btSoftBodyWorldInfo;
class ConstraintBullet;
class CollisionObjectBullet;
class RigidBodyBullet;
@@ -65,6 +65,8 @@ class SpaceBullet;
class SoftBodyBullet;
class btGjkEpaPenetrationDepthSolver;
+extern ContactAddedCallback gContactAddedCallback;
+
class BulletPhysicsDirectSpaceState : public PhysicsDirectSpaceState {
GDCLASS(BulletPhysicsDirectSpaceState, PhysicsDirectSpaceState)
private:
@@ -73,13 +75,13 @@ private:
public:
BulletPhysicsDirectSpaceState(SpaceBullet *p_space);
- virtual int intersect_point(const Vector3 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF);
- virtual bool intersect_ray(const Vector3 &p_from, const Vector3 &p_to, RayResult &r_result, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_pick_ray = false);
- virtual int intersect_shape(const RID &p_shape, const Transform &p_xform, float p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF);
- virtual bool cast_motion(const RID &p_shape, const Transform &p_xform, const Vector3 &p_motion, float p_margin, float &p_closest_safe, float &p_closest_unsafe, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, ShapeRestInfo *r_info = NULL);
+ virtual int intersect_point(const Vector3 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false);
+ virtual bool intersect_ray(const Vector3 &p_from, const Vector3 &p_to, RayResult &r_result, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, bool p_pick_ray = false);
+ virtual int intersect_shape(const RID &p_shape, const Transform &p_xform, float p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false);
+ virtual bool cast_motion(const RID &p_shape, const Transform &p_xform, const Vector3 &p_motion, float p_margin, float &r_closest_safe, float &r_closest_unsafe, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, ShapeRestInfo *r_info = NULL);
/// Returns the list of contacts pairs in this order: Local contact, other body contact
- virtual bool collide_shape(RID p_shape, const Transform &p_shape_xform, float p_margin, Vector3 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF);
- virtual bool rest_info(RID p_shape, const Transform &p_shape_xform, float p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF);
+ virtual bool collide_shape(RID p_shape, const Transform &p_shape_xform, float p_margin, Vector3 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false);
+ virtual bool rest_info(RID p_shape, const Transform &p_shape_xform, float p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false);
virtual Vector3 get_closest_point_to_object_volume(RID p_object, const Vector3 p_point) const;
};
@@ -94,9 +96,9 @@ class SpaceBullet : public RIDBullet {
btCollisionDispatcher *dispatcher;
btConstraintSolver *solver;
btDiscreteDynamicsWorld *dynamicsWorld;
+ btSoftBodyWorldInfo *soft_body_world_info;
btGhostPairCallback *ghostPairCallback;
GodotFilterCallback *godotFilterCallback;
- btSoftBodyWorldInfo *soft_body_world_info;
btGjkEpaPenetrationDepthSolver *gjk_epa_pen_solver;
btVoronoiSimplexSolver *gjk_simplex_solver;
@@ -174,7 +176,8 @@ public:
void update_gravity();
- bool test_body_motion(RigidBodyBullet *p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, PhysicsServer::MotionResult *r_result);
+ bool test_body_motion(RigidBodyBullet *p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, PhysicsServer::MotionResult *r_result, bool p_exclude_raycast_shapes);
+ int test_ray_separation(RigidBodyBullet *p_body, const Transform &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, PhysicsServer::SeparationResult *r_results, int p_result_max, float p_margin);
private:
void create_empty_world(bool p_create_soft_world);
@@ -208,5 +211,7 @@ private:
/// This is an API that recover a kinematic object from penetration
/// Using this we leave Bullet to select the best algorithm, For example GJK in case we have Convex Convex, or a Bullet accelerated algorithm
bool RFP_convex_world_test(const btConvexShape *p_shapeA, const btCollisionShape *p_shapeB, btCollisionObject *p_objectA, btCollisionObject *p_objectB, int p_shapeId_A, int p_shapeId_B, const btTransform &p_transformA, const btTransform &p_transformB, btScalar p_recover_movement_scale, btVector3 &r_delta_recover_movement, RecoverResult *r_recover_result = NULL);
+
+ int recover_from_penetration_ray(RigidBodyBullet *p_body, const btTransform &p_body_position, btScalar p_recover_movement_scale, bool p_infinite_inertia, int p_result_max, btVector3 &r_delta_recover_movement, PhysicsServer::SeparationResult *r_results);
};
#endif