1 /*************************************************************************/
2 /*  collision_object_bullet.h                                            */
3 /*************************************************************************/
4 /*                       This file is part of:                           */
5 /*                           GODOT ENGINE                                */
6 /*                      https://godotengine.org                          */
7 /*************************************************************************/
8 /* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur.                 */
9 /* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md).   */
10 /*                                                                       */
11 /* Permission is hereby granted, free of charge, to any person obtaining */
12 /* a copy of this software and associated documentation files (the       */
13 /* "Software"), to deal in the Software without restriction, including   */
14 /* without limitation the rights to use, copy, modify, merge, publish,   */
15 /* distribute, sublicense, and/or sell copies of the Software, and to    */
16 /* permit persons to whom the Software is furnished to do so, subject to */
17 /* the following conditions:                                             */
18 /*                                                                       */
19 /* The above copyright notice and this permission notice shall be        */
20 /* included in all copies or substantial portions of the Software.       */
21 /*                                                                       */
22 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
23 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
24 /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
25 /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
26 /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
27 /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
28 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
29 /*************************************************************************/
30 
31 #ifndef COLLISION_OBJECT_BULLET_H
32 #define COLLISION_OBJECT_BULLET_H
33 
34 #include "core/math/transform.h"
35 #include "core/math/vector3.h"
36 #include "core/object.h"
37 #include "core/vset.h"
38 #include "shape_owner_bullet.h"
39 
40 #include <LinearMath/btTransform.h>
41 
42 /**
43 	@author AndreaCatania
44 */
45 
46 class AreaBullet;
47 class ShapeBullet;
48 class btCollisionObject;
49 class btCompoundShape;
50 class btCollisionShape;
51 class SpaceBullet;
52 
53 class CollisionObjectBullet : public RIDBullet {
54 public:
55 	enum GodotObjectFlags {
56 		GOF_IS_MONITORING_AREA = 1 << 0
57 		// FLAG2 = 1 << 1,
58 		// FLAG3 = 1 << 2,
59 		// FLAG4 = 1 << 3,
60 		// FLAG5 = 1 << 4,
61 		// FLAG6 = 1 << 5
62 		// etc..
63 	};
64 	enum Type {
65 		TYPE_AREA = 0,
66 		TYPE_RIGID_BODY,
67 		TYPE_SOFT_BODY,
68 		TYPE_KINEMATIC_GHOST_BODY
69 	};
70 
71 	struct ShapeWrapper {
72 		ShapeBullet *shape;
73 		btCollisionShape *bt_shape;
74 		btTransform transform;
75 		btVector3 scale;
76 		bool active;
77 
ShapeWrapperShapeWrapper78 		ShapeWrapper() :
79 				shape(NULL),
80 				bt_shape(NULL),
81 				active(true) {}
82 
ShapeWrapperShapeWrapper83 		ShapeWrapper(ShapeBullet *p_shape, const btTransform &p_transform, bool p_active) :
84 				shape(p_shape),
85 				bt_shape(NULL),
86 				active(p_active) {
87 			set_transform(p_transform);
88 		}
89 
ShapeWrapperShapeWrapper90 		ShapeWrapper(ShapeBullet *p_shape, const Transform &p_transform, bool p_active) :
91 				shape(p_shape),
92 				bt_shape(NULL),
93 				active(p_active) {
94 			set_transform(p_transform);
95 		}
96 		~ShapeWrapper();
97 
ShapeWrapperShapeWrapper98 		ShapeWrapper(const ShapeWrapper &otherShape) {
99 			operator=(otherShape);
100 		}
101 
102 		void operator=(const ShapeWrapper &otherShape) {
103 			shape = otherShape.shape;
104 			bt_shape = otherShape.bt_shape;
105 			transform = otherShape.transform;
106 			scale = otherShape.scale;
107 			active = otherShape.active;
108 		}
109 
110 		void set_transform(const Transform &p_transform);
111 		void set_transform(const btTransform &p_transform);
112 		btTransform get_adjusted_transform() const;
113 
114 		void claim_bt_shape(const btVector3 &body_scale);
115 	};
116 
117 protected:
118 	Type type;
119 	ObjectID instance_id;
120 	uint32_t collisionLayer;
121 	uint32_t collisionMask;
122 	bool collisionsEnabled;
123 	bool m_isStatic;
124 	bool ray_pickable;
125 	btCollisionObject *bt_collision_object;
126 	Vector3 body_scale;
127 	bool force_shape_reset;
128 	SpaceBullet *space;
129 
130 	VSet<RID> exceptions;
131 
132 	/// This array is used to know all areas where this Object is overlapped in
133 	/// New area is added when overlap with new area (AreaBullet::addOverlap), then is removed when it exit (CollisionObjectBullet::onExitArea)
134 	/// This array is used mainly to know which area hold the pointer of this object
135 	Vector<AreaBullet *> areasOverlapped;
136 	bool isTransformChanged;
137 
138 public:
139 	CollisionObjectBullet(Type p_type);
140 	virtual ~CollisionObjectBullet();
141 
getType()142 	Type getType() { return type; }
143 
144 protected:
145 	void destroyBulletCollisionObject();
146 	void setupBulletCollisionObject(btCollisionObject *p_collisionObject);
147 
148 public:
get_bt_collision_object()149 	_FORCE_INLINE_ btCollisionObject *get_bt_collision_object() { return bt_collision_object; }
150 
set_instance_id(const ObjectID & p_instance_id)151 	_FORCE_INLINE_ void set_instance_id(const ObjectID &p_instance_id) { instance_id = p_instance_id; }
get_instance_id()152 	_FORCE_INLINE_ ObjectID get_instance_id() const { return instance_id; }
153 
is_static()154 	_FORCE_INLINE_ bool is_static() const { return m_isStatic; }
155 
set_ray_pickable(bool p_enable)156 	_FORCE_INLINE_ void set_ray_pickable(bool p_enable) { ray_pickable = p_enable; }
is_ray_pickable()157 	_FORCE_INLINE_ bool is_ray_pickable() const { return ray_pickable; }
158 
159 	void set_body_scale(const Vector3 &p_new_scale);
get_body_scale()160 	const Vector3 &get_body_scale() const { return body_scale; }
161 	btVector3 get_bt_body_scale() const;
162 	virtual void body_scale_changed();
163 
164 	void add_collision_exception(const CollisionObjectBullet *p_ignoreCollisionObject);
165 	void remove_collision_exception(const CollisionObjectBullet *p_ignoreCollisionObject);
166 	bool has_collision_exception(const CollisionObjectBullet *p_otherCollisionObject) const;
get_exceptions()167 	_FORCE_INLINE_ const VSet<RID> &get_exceptions() const { return exceptions; }
168 
set_collision_layer(uint32_t p_layer)169 	_FORCE_INLINE_ void set_collision_layer(uint32_t p_layer) {
170 		if (collisionLayer != p_layer) {
171 			collisionLayer = p_layer;
172 			on_collision_filters_change();
173 		}
174 	}
get_collision_layer()175 	_FORCE_INLINE_ uint32_t get_collision_layer() const { return collisionLayer; }
176 
set_collision_mask(uint32_t p_mask)177 	_FORCE_INLINE_ void set_collision_mask(uint32_t p_mask) {
178 		if (collisionMask != p_mask) {
179 			collisionMask = p_mask;
180 			on_collision_filters_change();
181 		}
182 	}
get_collision_mask()183 	_FORCE_INLINE_ uint32_t get_collision_mask() const { return collisionMask; }
184 
185 	virtual void on_collision_filters_change() = 0;
186 
test_collision_mask(CollisionObjectBullet * p_other)187 	_FORCE_INLINE_ bool test_collision_mask(CollisionObjectBullet *p_other) const {
188 		return collisionLayer & p_other->collisionMask || p_other->collisionLayer & collisionMask;
189 	}
190 
191 	virtual void reload_body() = 0;
192 	virtual void set_space(SpaceBullet *p_space) = 0;
get_space()193 	_FORCE_INLINE_ SpaceBullet *get_space() const { return space; }
194 
195 	virtual void on_collision_checker_start() = 0;
196 	virtual void on_collision_checker_end() = 0;
197 
198 	virtual void dispatch_callbacks() = 0;
199 
200 	void set_collision_enabled(bool p_enabled);
201 	bool is_collisions_response_enabled();
202 
203 	void notify_new_overlap(AreaBullet *p_area);
204 	virtual void on_enter_area(AreaBullet *p_area) = 0;
205 	virtual void on_exit_area(AreaBullet *p_area);
206 
207 	void set_godot_object_flags(int flags);
208 	int get_godot_object_flags() const;
209 
210 	void set_transform(const Transform &p_global_transform);
211 	Transform get_transform() const;
212 	virtual void set_transform__bullet(const btTransform &p_global_transform);
213 	virtual const btTransform &get_transform__bullet() const;
214 
is_transform_changed()215 	bool is_transform_changed() const { return isTransformChanged; }
216 	virtual void notify_transform_changed();
217 };
218 
219 class RigidCollisionObjectBullet : public CollisionObjectBullet, public ShapeOwnerBullet {
220 protected:
221 	btCollisionShape *mainShape;
222 	Vector<ShapeWrapper> shapes;
223 
224 public:
225 	RigidCollisionObjectBullet(Type p_type);
226 	~RigidCollisionObjectBullet();
227 
get_shapes_wrappers()228 	_FORCE_INLINE_ const Vector<ShapeWrapper> &get_shapes_wrappers() const { return shapes; }
229 
get_main_shape()230 	_FORCE_INLINE_ btCollisionShape *get_main_shape() const { return mainShape; }
231 
232 	void add_shape(ShapeBullet *p_shape, const Transform &p_transform = Transform(), bool p_disabled = false);
233 	void set_shape(int p_index, ShapeBullet *p_shape);
234 
235 	int get_shape_count() const;
236 	ShapeBullet *get_shape(int p_index) const;
237 	btCollisionShape *get_bt_shape(int p_index) const;
238 
239 	int find_shape(ShapeBullet *p_shape) const;
240 
241 	virtual void remove_shape_full(ShapeBullet *p_shape);
242 	void remove_shape_full(int p_index);
243 	void remove_all_shapes(bool p_permanentlyFromThisBody = false, bool p_force_not_reload = false);
244 
245 	void set_shape_transform(int p_index, const Transform &p_transform);
246 
247 	const btTransform &get_bt_shape_transform(int p_index) const;
248 	Transform get_shape_transform(int p_index) const;
249 
250 	void set_shape_disabled(int p_index, bool p_disabled);
251 	bool is_shape_disabled(int p_index);
252 
253 	virtual void shape_changed(int p_shape_index);
254 	virtual void reload_shapes();
255 
256 	virtual void main_shape_changed() = 0;
257 	virtual void body_scale_changed();
258 
259 private:
260 	void internal_shape_destroy(int p_index, bool p_permanentlyFromThisBody = false);
261 };
262 
263 #endif
264