| 
									
										
										
										
											2017-11-04 20:52:59 +01:00
										 |  |  | /*************************************************************************/ | 
					
						
							|  |  |  | /*  collision_object_bullet.cpp                                          */ | 
					
						
							|  |  |  | /*************************************************************************/ | 
					
						
							|  |  |  | /*                       This file is part of:                           */ | 
					
						
							|  |  |  | /*                           GODOT ENGINE                                */ | 
					
						
							| 
									
										
										
										
											2018-01-05 00:50:27 +01:00
										 |  |  | /*                      https://godotengine.org                          */ | 
					
						
							| 
									
										
										
										
											2017-11-04 20:52:59 +01:00
										 |  |  | /*************************************************************************/ | 
					
						
							| 
									
										
										
										
											2021-01-01 20:13:46 +01:00
										 |  |  | /* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */ | 
					
						
							|  |  |  | /* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */ | 
					
						
							| 
									
										
										
										
											2017-11-04 20:52:59 +01:00
										 |  |  | /*                                                                       */ | 
					
						
							|  |  |  | /* Permission is hereby granted, free of charge, to any person obtaining */ | 
					
						
							|  |  |  | /* a copy of this software and associated documentation files (the       */ | 
					
						
							|  |  |  | /* "Software"), to deal in the Software without restriction, including   */ | 
					
						
							|  |  |  | /* without limitation the rights to use, copy, modify, merge, publish,   */ | 
					
						
							|  |  |  | /* distribute, sublicense, and/or sell copies of the Software, and to    */ | 
					
						
							|  |  |  | /* permit persons to whom the Software is furnished to do so, subject to */ | 
					
						
							|  |  |  | /* the following conditions:                                             */ | 
					
						
							|  |  |  | /*                                                                       */ | 
					
						
							|  |  |  | /* The above copyright notice and this permission notice shall be        */ | 
					
						
							|  |  |  | /* included in all copies or substantial portions of the Software.       */ | 
					
						
							|  |  |  | /*                                                                       */ | 
					
						
							|  |  |  | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */ | 
					
						
							|  |  |  | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */ | 
					
						
							|  |  |  | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ | 
					
						
							|  |  |  | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */ | 
					
						
							|  |  |  | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */ | 
					
						
							|  |  |  | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */ | 
					
						
							|  |  |  | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */ | 
					
						
							|  |  |  | /*************************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "collision_object_bullet.h"
 | 
					
						
							| 
									
										
										
										
											2018-01-05 00:50:27 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-04 20:52:59 +01:00
										 |  |  | #include "area_bullet.h"
 | 
					
						
							|  |  |  | #include "bullet_physics_server.h"
 | 
					
						
							|  |  |  | #include "bullet_types_converter.h"
 | 
					
						
							|  |  |  | #include "bullet_utilities.h"
 | 
					
						
							|  |  |  | #include "shape_bullet.h"
 | 
					
						
							|  |  |  | #include "space_bullet.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-05 00:50:27 +01:00
										 |  |  | #include <btBulletCollisionCommon.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							|  |  |  | 	@author AndreaCatania | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-25 22:46:26 +01:00
										 |  |  | // We enable dynamic AABB tree so that we can actually perform a broadphase on bodies with compound collision shapes.
 | 
					
						
							|  |  |  | // This is crucial for the performance of kinematic bodies and for bodies with transforming shapes.
 | 
					
						
							|  |  |  | #define enableDynamicAabbTree true
 | 
					
						
							| 
									
										
										
										
											2017-11-04 20:52:59 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | CollisionObjectBullet::ShapeWrapper::~ShapeWrapper() {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void CollisionObjectBullet::ShapeWrapper::set_transform(const Transform &p_transform) { | 
					
						
							| 
									
										
										
										
											2018-04-14 15:53:25 -04:00
										 |  |  | 	G_TO_B(p_transform.get_basis().get_scale_abs(), scale); | 
					
						
							| 
									
										
										
										
											2017-11-04 20:52:59 +01:00
										 |  |  | 	G_TO_B(p_transform, transform); | 
					
						
							| 
									
										
										
										
											2018-01-08 01:22:54 +01:00
										 |  |  | 	UNSCALE_BT_BASIS(transform); | 
					
						
							| 
									
										
										
										
											2017-11-04 20:52:59 +01:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2018-09-06 18:19:05 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-04 20:52:59 +01:00
										 |  |  | void CollisionObjectBullet::ShapeWrapper::set_transform(const btTransform &p_transform) { | 
					
						
							|  |  |  | 	transform = p_transform; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-25 13:03:48 +10:00
										 |  |  | btTransform CollisionObjectBullet::ShapeWrapper::get_adjusted_transform() const { | 
					
						
							| 
									
										
										
										
											2020-03-27 15:21:27 -03:00
										 |  |  | 	if (shape->get_type() == PhysicsServer3D::SHAPE_HEIGHTMAP) { | 
					
						
							| 
									
										
										
										
											2019-04-25 13:03:48 +10:00
										 |  |  | 		const HeightMapShapeBullet *hm_shape = (const HeightMapShapeBullet *)shape; // should be safe to cast now
 | 
					
						
							|  |  |  | 		btTransform adjusted_transform; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// Bullet centers our heightmap:
 | 
					
						
							|  |  |  | 		// https://github.com/bulletphysics/bullet3/blob/master/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h#L33
 | 
					
						
							|  |  |  | 		// This is really counter intuitive so we're adjusting for it
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		adjusted_transform.setIdentity(); | 
					
						
							|  |  |  | 		adjusted_transform.setOrigin(btVector3(0.0, hm_shape->min_height + ((hm_shape->max_height - hm_shape->min_height) * 0.5), 0.0)); | 
					
						
							|  |  |  | 		adjusted_transform *= transform; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return adjusted_transform; | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		return transform; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-06 18:19:05 +02:00
										 |  |  | void CollisionObjectBullet::ShapeWrapper::claim_bt_shape(const btVector3 &body_scale) { | 
					
						
							| 
									
										
										
										
											2020-10-08 12:22:59 +02:00
										 |  |  | 	if (!bt_shape) { | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 		if (active) { | 
					
						
							| 
									
										
										
										
											2018-10-06 16:50:10 +02:00
										 |  |  | 			bt_shape = shape->create_bt_shape(scale * body_scale); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2018-10-06 16:50:10 +02:00
										 |  |  | 			bt_shape = ShapeBullet::create_shape_empty(); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2018-09-06 18:19:05 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-06 21:36:34 +01:00
										 |  |  | CollisionObjectBullet::CollisionObjectBullet(Type p_type) : | 
					
						
							|  |  |  | 		RIDBullet(), | 
					
						
							| 
									
										
										
										
											2020-05-12 17:01:17 +02:00
										 |  |  | 		type(p_type) {} | 
					
						
							| 
									
										
										
										
											2017-11-04 20:52:59 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | CollisionObjectBullet::~CollisionObjectBullet() { | 
					
						
							| 
									
										
										
										
											2018-04-06 07:48:30 +02:00
										 |  |  | 	// Remove all overlapping, notify is not required since godot take care of it
 | 
					
						
							| 
									
										
										
										
											2017-11-04 20:52:59 +01:00
										 |  |  | 	for (int i = areasOverlapped.size() - 1; 0 <= i; --i) { | 
					
						
							| 
									
										
										
										
											2018-04-09 09:33:29 +02:00
										 |  |  | 		areasOverlapped[i]->remove_overlap(this, /*Notify*/ false); | 
					
						
							| 
									
										
										
										
											2017-11-04 20:52:59 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	destroyBulletCollisionObject(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool equal(real_t first, real_t second) { | 
					
						
							|  |  |  | 	return Math::abs(first - second) <= 0.001f; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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])) { | 
					
						
							| 
									
										
										
										
											2017-12-02 18:10:36 +01:00
										 |  |  | 		body_scale = p_new_scale; | 
					
						
							| 
									
										
										
										
											2018-10-06 16:50:10 +02:00
										 |  |  | 		body_scale_changed(); | 
					
						
							| 
									
										
										
										
											2017-11-04 20:52:59 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-02 18:10:36 +01:00
										 |  |  | btVector3 CollisionObjectBullet::get_bt_body_scale() const { | 
					
						
							|  |  |  | 	btVector3 s; | 
					
						
							|  |  |  | 	G_TO_B(body_scale, s); | 
					
						
							|  |  |  | 	return s; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-06 16:50:10 +02:00
										 |  |  | void CollisionObjectBullet::body_scale_changed() { | 
					
						
							| 
									
										
										
										
											2017-12-23 18:23:12 +01:00
										 |  |  | 	force_shape_reset = true; | 
					
						
							| 
									
										
										
										
											2017-11-04 20:52:59 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void CollisionObjectBullet::destroyBulletCollisionObject() { | 
					
						
							|  |  |  | 	bulletdelete(bt_collision_object); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void CollisionObjectBullet::setupBulletCollisionObject(btCollisionObject *p_collisionObject) { | 
					
						
							|  |  |  | 	bt_collision_object = p_collisionObject; | 
					
						
							|  |  |  | 	bt_collision_object->setUserPointer(this); | 
					
						
							|  |  |  | 	bt_collision_object->setUserIndex(type); | 
					
						
							|  |  |  | 	// Force the enabling of collision and avoid problems
 | 
					
						
							|  |  |  | 	set_collision_enabled(collisionsEnabled); | 
					
						
							| 
									
										
										
										
											2018-08-31 09:40:50 +02:00
										 |  |  | 	p_collisionObject->setCollisionFlags(p_collisionObject->getCollisionFlags() | btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK); | 
					
						
							| 
									
										
										
										
											2017-11-04 20:52:59 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void CollisionObjectBullet::add_collision_exception(const CollisionObjectBullet *p_ignoreCollisionObject) { | 
					
						
							|  |  |  | 	exceptions.insert(p_ignoreCollisionObject->get_self()); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	if (!bt_collision_object) { | 
					
						
							| 
									
										
										
										
											2017-11-21 01:36:32 +01:00
										 |  |  | 		return; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-11-04 20:52:59 +01:00
										 |  |  | 	bt_collision_object->setIgnoreCollisionCheck(p_ignoreCollisionObject->bt_collision_object, true); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	if (space) { | 
					
						
							| 
									
										
										
										
											2017-11-07 17:20:58 +01:00
										 |  |  | 		space->get_broadphase()->getOverlappingPairCache()->cleanProxyFromPairs(bt_collision_object->getBroadphaseHandle(), space->get_dispatcher()); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-11-04 20:52:59 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void CollisionObjectBullet::remove_collision_exception(const CollisionObjectBullet *p_ignoreCollisionObject) { | 
					
						
							|  |  |  | 	exceptions.erase(p_ignoreCollisionObject->get_self()); | 
					
						
							| 
									
										
										
										
											2021-03-06 12:01:09 +01:00
										 |  |  | 	if (!bt_collision_object) { | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-11-04 20:52:59 +01:00
										 |  |  | 	bt_collision_object->setIgnoreCollisionCheck(p_ignoreCollisionObject->bt_collision_object, false); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	if (space) { | 
					
						
							| 
									
										
										
										
											2017-11-07 17:20:58 +01:00
										 |  |  | 		space->get_broadphase()->getOverlappingPairCache()->cleanProxyFromPairs(bt_collision_object->getBroadphaseHandle(), space->get_dispatcher()); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-11-04 20:52:59 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool CollisionObjectBullet::has_collision_exception(const CollisionObjectBullet *p_otherCollisionObject) const { | 
					
						
							| 
									
										
										
										
											2021-03-06 12:01:09 +01:00
										 |  |  | 	return exceptions.has(p_otherCollisionObject->get_self()); | 
					
						
							| 
									
										
										
										
											2017-11-04 20:52:59 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void CollisionObjectBullet::set_collision_enabled(bool p_enabled) { | 
					
						
							|  |  |  | 	collisionsEnabled = p_enabled; | 
					
						
							| 
									
										
										
										
											2021-03-06 12:01:09 +01:00
										 |  |  | 	if (!bt_collision_object) { | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-11-04 20:52:59 +01:00
										 |  |  | 	if (collisionsEnabled) { | 
					
						
							|  |  |  | 		bt_collision_object->setCollisionFlags(bt_collision_object->getCollisionFlags() & (~btCollisionObject::CF_NO_CONTACT_RESPONSE)); | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		bt_collision_object->setCollisionFlags(bt_collision_object->getCollisionFlags() | btCollisionObject::CF_NO_CONTACT_RESPONSE); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool CollisionObjectBullet::is_collisions_response_enabled() { | 
					
						
							|  |  |  | 	return collisionsEnabled; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void CollisionObjectBullet::notify_new_overlap(AreaBullet *p_area) { | 
					
						
							|  |  |  | 	areasOverlapped.push_back(p_area); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void CollisionObjectBullet::on_exit_area(AreaBullet *p_area) { | 
					
						
							|  |  |  | 	areasOverlapped.erase(p_area); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void CollisionObjectBullet::set_godot_object_flags(int flags) { | 
					
						
							|  |  |  | 	bt_collision_object->setUserIndex2(flags); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int CollisionObjectBullet::get_godot_object_flags() const { | 
					
						
							|  |  |  | 	return bt_collision_object->getUserIndex2(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void CollisionObjectBullet::set_transform(const Transform &p_global_transform) { | 
					
						
							| 
									
										
										
										
											2018-04-14 15:53:25 -04:00
										 |  |  | 	set_body_scale(p_global_transform.basis.get_scale_abs()); | 
					
						
							| 
									
										
										
										
											2017-11-04 20:52:59 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-16 12:53:01 +01:00
										 |  |  | 	btTransform bt_transform; | 
					
						
							|  |  |  | 	G_TO_B(p_global_transform, bt_transform); | 
					
						
							|  |  |  | 	UNSCALE_BT_BASIS(bt_transform); | 
					
						
							| 
									
										
										
										
											2017-11-04 20:52:59 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-16 12:53:01 +01:00
										 |  |  | 	set_transform__bullet(bt_transform); | 
					
						
							| 
									
										
										
										
											2017-11-04 20:52:59 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Transform CollisionObjectBullet::get_transform() const { | 
					
						
							|  |  |  | 	Transform t; | 
					
						
							|  |  |  | 	B_TO_G(get_transform__bullet(), t); | 
					
						
							| 
									
										
										
										
											2017-12-02 18:10:36 +01:00
										 |  |  | 	t.basis.scale(body_scale); | 
					
						
							| 
									
										
										
										
											2017-11-04 20:52:59 +01:00
										 |  |  | 	return t; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void CollisionObjectBullet::set_transform__bullet(const btTransform &p_global_transform) { | 
					
						
							|  |  |  | 	bt_collision_object->setWorldTransform(p_global_transform); | 
					
						
							| 
									
										
										
										
											2018-10-07 07:14:38 +02:00
										 |  |  | 	notify_transform_changed(); | 
					
						
							| 
									
										
										
										
											2017-11-04 20:52:59 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const btTransform &CollisionObjectBullet::get_transform__bullet() const { | 
					
						
							|  |  |  | 	return bt_collision_object->getWorldTransform(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-07 07:14:38 +02:00
										 |  |  | void CollisionObjectBullet::notify_transform_changed() { | 
					
						
							|  |  |  | 	isTransformChanged = true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-04 20:52:59 +01:00
										 |  |  | RigidCollisionObjectBullet::~RigidCollisionObjectBullet() { | 
					
						
							| 
									
										
										
										
											2018-10-07 07:14:38 +02:00
										 |  |  | 	remove_all_shapes(true, true); | 
					
						
							| 
									
										
										
										
											2018-09-06 18:19:05 +02:00
										 |  |  | 	if (mainShape && mainShape->isCompound()) { | 
					
						
							|  |  |  | 		bulletdelete(mainShape); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-11-04 20:52:59 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-24 10:38:31 +01:00
										 |  |  | void RigidCollisionObjectBullet::add_shape(ShapeBullet *p_shape, const Transform &p_transform, bool p_disabled) { | 
					
						
							|  |  |  | 	shapes.push_back(ShapeWrapper(p_shape, p_transform, !p_disabled)); | 
					
						
							| 
									
										
										
										
											2017-11-04 20:52:59 +01:00
										 |  |  | 	p_shape->add_owner(this); | 
					
						
							| 
									
										
										
										
											2018-10-06 16:50:10 +02:00
										 |  |  | 	reload_shapes(); | 
					
						
							| 
									
										
										
										
											2017-11-04 20:52:59 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void RigidCollisionObjectBullet::set_shape(int p_index, ShapeBullet *p_shape) { | 
					
						
							| 
									
										
										
										
											2020-10-08 12:16:12 +02:00
										 |  |  | 	ShapeWrapper &shp = shapes.write[p_index]; | 
					
						
							| 
									
										
										
										
											2017-11-04 20:52:59 +01:00
										 |  |  | 	shp.shape->remove_owner(this); | 
					
						
							|  |  |  | 	p_shape->add_owner(this); | 
					
						
							|  |  |  | 	shp.shape = p_shape; | 
					
						
							| 
									
										
										
										
											2018-10-06 16:50:10 +02:00
										 |  |  | 	reload_shapes(); | 
					
						
							| 
									
										
										
										
											2017-11-04 20:52:59 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-06 16:50:10 +02:00
										 |  |  | int RigidCollisionObjectBullet::get_shape_count() const { | 
					
						
							|  |  |  | 	return shapes.size(); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2017-11-04 20:52:59 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-06 16:50:10 +02:00
										 |  |  | ShapeBullet *RigidCollisionObjectBullet::get_shape(int p_index) const { | 
					
						
							|  |  |  | 	return shapes[p_index].shape; | 
					
						
							| 
									
										
										
										
											2017-11-04 20:52:59 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-06 16:50:10 +02:00
										 |  |  | 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) { | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 		if (shapes[i].shape == p_shape) { | 
					
						
							| 
									
										
										
										
											2018-10-06 16:50:10 +02:00
										 |  |  | 			return i; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2018-10-06 16:50:10 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	return -1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void RigidCollisionObjectBullet::remove_shape_full(ShapeBullet *p_shape) { | 
					
						
							| 
									
										
										
										
											2017-11-04 20:52:59 +01:00
										 |  |  | 	// Remove the shape, all the times it appears
 | 
					
						
							|  |  |  | 	// Reverse order required for delete.
 | 
					
						
							|  |  |  | 	for (int i = shapes.size() - 1; 0 <= i; --i) { | 
					
						
							|  |  |  | 		if (p_shape == shapes[i].shape) { | 
					
						
							|  |  |  | 			internal_shape_destroy(i); | 
					
						
							|  |  |  | 			shapes.remove(i); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-10-06 16:50:10 +02:00
										 |  |  | 	reload_shapes(); | 
					
						
							| 
									
										
										
										
											2017-11-04 20:52:59 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-06 16:50:10 +02:00
										 |  |  | void RigidCollisionObjectBullet::remove_shape_full(int p_index) { | 
					
						
							| 
									
										
										
										
											2017-11-04 20:52:59 +01:00
										 |  |  | 	ERR_FAIL_INDEX(p_index, get_shape_count()); | 
					
						
							|  |  |  | 	internal_shape_destroy(p_index); | 
					
						
							|  |  |  | 	shapes.remove(p_index); | 
					
						
							| 
									
										
										
										
											2018-10-06 16:50:10 +02:00
										 |  |  | 	reload_shapes(); | 
					
						
							| 
									
										
										
										
											2017-11-04 20:52:59 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-07 07:14:38 +02:00
										 |  |  | void RigidCollisionObjectBullet::remove_all_shapes(bool p_permanentlyFromThisBody, bool p_force_not_reload) { | 
					
						
							| 
									
										
										
										
											2017-11-04 20:52:59 +01:00
										 |  |  | 	// Reverse order required for delete.
 | 
					
						
							|  |  |  | 	for (int i = shapes.size() - 1; 0 <= i; --i) { | 
					
						
							|  |  |  | 		internal_shape_destroy(i, p_permanentlyFromThisBody); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	shapes.clear(); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	if (!p_force_not_reload) { | 
					
						
							| 
									
										
										
										
											2018-10-07 07:14:38 +02:00
										 |  |  | 		reload_shapes(); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-11-04 20:52:59 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-06 16:50:10 +02:00
										 |  |  | void RigidCollisionObjectBullet::set_shape_transform(int p_index, const Transform &p_transform) { | 
					
						
							|  |  |  | 	ERR_FAIL_INDEX(p_index, get_shape_count()); | 
					
						
							| 
									
										
										
										
											2017-11-04 20:52:59 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-08 12:16:12 +02:00
										 |  |  | 	shapes.write[p_index].set_transform(p_transform); | 
					
						
							| 
									
										
										
										
											2019-06-20 16:12:58 -04:00
										 |  |  | 	shape_changed(p_index); | 
					
						
							| 
									
										
										
										
											2017-11-04 20:52:59 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-06 18:19:05 +02:00
										 |  |  | const btTransform &RigidCollisionObjectBullet::get_bt_shape_transform(int p_index) const { | 
					
						
							|  |  |  | 	return shapes[p_index].transform; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-04 20:52:59 +01:00
										 |  |  | Transform RigidCollisionObjectBullet::get_shape_transform(int p_index) const { | 
					
						
							|  |  |  | 	Transform trs; | 
					
						
							|  |  |  | 	B_TO_G(shapes[p_index].transform, trs); | 
					
						
							|  |  |  | 	return trs; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-06 16:50:10 +02:00
										 |  |  | void RigidCollisionObjectBullet::set_shape_disabled(int p_index, bool p_disabled) { | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	if (shapes[p_index].active != p_disabled) { | 
					
						
							| 
									
										
										
										
											2019-03-24 10:38:31 +01:00
										 |  |  | 		return; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-10-08 12:16:12 +02:00
										 |  |  | 	shapes.write[p_index].active = !p_disabled; | 
					
						
							| 
									
										
										
										
											2018-10-06 16:50:10 +02:00
										 |  |  | 	shape_changed(p_index); | 
					
						
							| 
									
										
										
										
											2017-11-04 20:52:59 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-06 16:50:10 +02:00
										 |  |  | bool RigidCollisionObjectBullet::is_shape_disabled(int p_index) { | 
					
						
							|  |  |  | 	return !shapes[p_index].active; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2017-12-23 18:23:12 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-06 16:50:10 +02:00
										 |  |  | void RigidCollisionObjectBullet::shape_changed(int p_shape_index) { | 
					
						
							| 
									
										
										
										
											2020-10-08 12:16:12 +02:00
										 |  |  | 	ShapeWrapper &shp = shapes.write[p_shape_index]; | 
					
						
							| 
									
										
										
										
											2018-11-16 14:20:09 +00:00
										 |  |  | 	if (shp.bt_shape == mainShape) { | 
					
						
							| 
									
										
										
										
											2020-04-02 01:20:12 +02:00
										 |  |  | 		mainShape = nullptr; | 
					
						
							| 
									
										
										
										
											2018-11-16 14:20:09 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-10-08 12:22:59 +02:00
										 |  |  | 	bulletdelete(shp.bt_shape); | 
					
						
							| 
									
										
										
										
											2018-10-06 16:50:10 +02:00
										 |  |  | 	reload_shapes(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void RigidCollisionObjectBullet::reload_shapes() { | 
					
						
							| 
									
										
										
										
											2018-10-07 22:47:10 +02:00
										 |  |  | 	if (mainShape && mainShape->isCompound()) { | 
					
						
							| 
									
										
										
										
											2018-10-06 16:50:10 +02:00
										 |  |  | 		// Destroy compound
 | 
					
						
							| 
									
										
										
										
											2018-09-06 18:19:05 +02:00
										 |  |  | 		bulletdelete(mainShape); | 
					
						
							| 
									
										
										
										
											2018-10-07 22:47:10 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-10-06 16:50:10 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-02 01:20:12 +02:00
										 |  |  | 	mainShape = nullptr; | 
					
						
							| 
									
										
										
										
											2017-11-04 20:52:59 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-08 12:22:59 +02:00
										 |  |  | 	ShapeWrapper *shpWrapper; | 
					
						
							| 
									
										
										
										
											2018-09-06 18:19:05 +02:00
										 |  |  | 	const int shape_count = shapes.size(); | 
					
						
							| 
									
										
										
										
											2017-12-23 18:23:12 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-08 12:22:59 +02:00
										 |  |  | 	// Reset shape if required
 | 
					
						
							| 
									
										
										
										
											2017-12-23 18:23:12 +01:00
										 |  |  | 	if (force_shape_reset) { | 
					
						
							| 
									
										
										
										
											2018-09-06 18:19:05 +02:00
										 |  |  | 		for (int i(0); i < shape_count; ++i) { | 
					
						
							| 
									
										
										
										
											2020-10-08 12:22:59 +02:00
										 |  |  | 			shpWrapper = &shapes.write[i]; | 
					
						
							|  |  |  | 			bulletdelete(shpWrapper->bt_shape); | 
					
						
							| 
									
										
										
										
											2017-12-23 18:23:12 +01:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		force_shape_reset = false; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-06 16:50:10 +02:00
										 |  |  | 	const btVector3 body_scale(get_bt_body_scale()); | 
					
						
							| 
									
										
										
										
											2018-09-06 18:19:05 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-08 12:22:59 +02:00
										 |  |  | 	// Try to optimize by not using compound
 | 
					
						
							| 
									
										
										
										
											2018-09-06 18:19:05 +02:00
										 |  |  | 	if (1 == shape_count) { | 
					
						
							| 
									
										
										
										
											2020-10-08 12:22:59 +02:00
										 |  |  | 		shpWrapper = &shapes.write[0]; | 
					
						
							|  |  |  | 		btTransform transform = shpWrapper->get_adjusted_transform(); | 
					
						
							| 
									
										
										
										
											2019-04-25 13:03:48 +10:00
										 |  |  | 		if (transform.getOrigin().isZero() && transform.getBasis() == transform.getBasis().getIdentity()) { | 
					
						
							| 
									
										
										
										
											2020-10-08 12:22:59 +02:00
										 |  |  | 			shpWrapper->claim_bt_shape(body_scale); | 
					
						
							|  |  |  | 			mainShape = shpWrapper->bt_shape; | 
					
						
							| 
									
										
										
										
											2018-10-06 16:50:10 +02:00
										 |  |  | 			main_shape_changed(); | 
					
						
							| 
									
										
										
										
											2018-09-06 18:19:05 +02:00
										 |  |  | 			return; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-08 12:22:59 +02:00
										 |  |  | 	// Optimization not possible use a compound shape
 | 
					
						
							| 
									
										
										
										
											2018-10-06 16:50:10 +02:00
										 |  |  | 	btCompoundShape *compoundShape = bulletnew(btCompoundShape(enableDynamicAabbTree, shape_count)); | 
					
						
							| 
									
										
										
										
											2018-09-06 18:19:05 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	for (int i(0); i < shape_count; ++i) { | 
					
						
							| 
									
										
										
										
											2020-10-08 12:22:59 +02:00
										 |  |  | 		shpWrapper = &shapes.write[i]; | 
					
						
							|  |  |  | 		shpWrapper->claim_bt_shape(body_scale); | 
					
						
							|  |  |  | 		btTransform scaled_shape_transform(shpWrapper->get_adjusted_transform()); | 
					
						
							| 
									
										
										
										
											2018-10-06 16:50:10 +02:00
										 |  |  | 		scaled_shape_transform.getOrigin() *= body_scale; | 
					
						
							| 
									
										
										
										
											2020-10-08 12:22:59 +02:00
										 |  |  | 		compoundShape->addChildShape(scaled_shape_transform, shpWrapper->bt_shape); | 
					
						
							| 
									
										
										
										
											2017-11-04 20:52:59 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	compoundShape->recalculateLocalAabb(); | 
					
						
							| 
									
										
										
										
											2018-09-06 18:19:05 +02:00
										 |  |  | 	mainShape = compoundShape; | 
					
						
							| 
									
										
										
										
											2018-10-06 16:50:10 +02:00
										 |  |  | 	main_shape_changed(); | 
					
						
							| 
									
										
										
										
											2017-11-04 20:52:59 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-06 16:50:10 +02:00
										 |  |  | void RigidCollisionObjectBullet::body_scale_changed() { | 
					
						
							|  |  |  | 	CollisionObjectBullet::body_scale_changed(); | 
					
						
							|  |  |  | 	reload_shapes(); | 
					
						
							| 
									
										
										
										
											2017-11-04 20:52:59 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void RigidCollisionObjectBullet::internal_shape_destroy(int p_index, bool p_permanentlyFromThisBody) { | 
					
						
							| 
									
										
										
										
											2020-10-08 12:16:12 +02:00
										 |  |  | 	ShapeWrapper &shp = shapes.write[p_index]; | 
					
						
							| 
									
										
										
										
											2017-11-04 20:52:59 +01:00
										 |  |  | 	shp.shape->remove_owner(this, p_permanentlyFromThisBody); | 
					
						
							| 
									
										
										
										
											2018-11-16 14:20:09 +00:00
										 |  |  | 	if (shp.bt_shape == mainShape) { | 
					
						
							| 
									
										
										
										
											2020-04-02 01:20:12 +02:00
										 |  |  | 		mainShape = nullptr; | 
					
						
							| 
									
										
										
										
											2018-11-16 14:20:09 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-10-08 12:22:59 +02:00
										 |  |  | 	bulletdelete(shp.bt_shape); | 
					
						
							| 
									
										
										
										
											2017-11-04 20:52:59 +01:00
										 |  |  | } |