1 /*************************************************************************/
2 /*  collision_object_sw.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_SW_H
32 #define COLLISION_OBJECT_SW_H
33 
34 #include "broad_phase_sw.h"
35 #include "core/self_list.h"
36 #include "servers/physics_server.h"
37 #include "shape_sw.h"
38 
39 #ifdef DEBUG_ENABLED
40 #define MAX_OBJECT_DISTANCE 3.1622776601683791e+18
41 
42 #define MAX_OBJECT_DISTANCE_X2 (MAX_OBJECT_DISTANCE * MAX_OBJECT_DISTANCE)
43 #endif
44 
45 class SpaceSW;
46 
47 class CollisionObjectSW : public ShapeOwnerSW {
48 public:
49 	enum Type {
50 		TYPE_AREA,
51 		TYPE_BODY
52 	};
53 
54 private:
55 	Type type;
56 	RID self;
57 	ObjectID instance_id;
58 	uint32_t collision_layer;
59 	uint32_t collision_mask;
60 
61 	struct Shape {
62 
63 		Transform xform;
64 		Transform xform_inv;
65 		BroadPhaseSW::ID bpid;
66 		AABB aabb_cache; //for rayqueries
67 		real_t area_cache;
68 		ShapeSW *shape;
69 		bool disabled;
70 
ShapeShape71 		Shape() { disabled = false; }
72 	};
73 
74 	Vector<Shape> shapes;
75 	SpaceSW *space;
76 	Transform transform;
77 	Transform inv_transform;
78 	bool _static;
79 
80 	SelfList<CollisionObjectSW> pending_shape_update_list;
81 
82 	void _update_shapes();
83 
84 protected:
85 	void _update_shapes_with_motion(const Vector3 &p_motion);
86 	void _unregister_shapes();
87 
88 	_FORCE_INLINE_ void _set_transform(const Transform &p_transform, bool p_update_shapes = true) {
89 #ifdef DEBUG_ENABLED
90 
91 		ERR_FAIL_COND_MSG(p_transform.origin.length_squared() > MAX_OBJECT_DISTANCE_X2, "Object went too far away (more than '" + itos(MAX_OBJECT_DISTANCE) + "' units from origin).");
92 #endif
93 
94 		transform = p_transform;
95 		if (p_update_shapes) _update_shapes();
96 	}
_set_inv_transform(const Transform & p_transform)97 	_FORCE_INLINE_ void _set_inv_transform(const Transform &p_transform) { inv_transform = p_transform; }
98 	void _set_static(bool p_static);
99 
100 	virtual void _shapes_changed() = 0;
101 	void _set_space(SpaceSW *p_space);
102 
103 	bool ray_pickable;
104 
105 	CollisionObjectSW(Type p_type);
106 
107 public:
set_self(const RID & p_self)108 	_FORCE_INLINE_ void set_self(const RID &p_self) { self = p_self; }
get_self()109 	_FORCE_INLINE_ RID get_self() const { return self; }
110 
set_instance_id(const ObjectID & p_instance_id)111 	_FORCE_INLINE_ void set_instance_id(const ObjectID &p_instance_id) { instance_id = p_instance_id; }
get_instance_id()112 	_FORCE_INLINE_ ObjectID get_instance_id() const { return instance_id; }
113 
114 	void _shape_changed();
115 
get_type()116 	_FORCE_INLINE_ Type get_type() const { return type; }
117 	void add_shape(ShapeSW *p_shape, const Transform &p_transform = Transform(), bool p_disabled = false);
118 	void set_shape(int p_index, ShapeSW *p_shape);
119 	void set_shape_transform(int p_index, const Transform &p_transform);
get_shape_count()120 	_FORCE_INLINE_ int get_shape_count() const { return shapes.size(); }
is_shape_disabled(int p_index)121 	_FORCE_INLINE_ bool is_shape_disabled(int p_index) const {
122 		CRASH_BAD_INDEX(p_index, shapes.size());
123 		return shapes[p_index].disabled;
124 	}
get_shape(int p_index)125 	_FORCE_INLINE_ ShapeSW *get_shape(int p_index) const { return shapes[p_index].shape; }
get_shape_transform(int p_index)126 	_FORCE_INLINE_ const Transform &get_shape_transform(int p_index) const { return shapes[p_index].xform; }
get_shape_inv_transform(int p_index)127 	_FORCE_INLINE_ const Transform &get_shape_inv_transform(int p_index) const { return shapes[p_index].xform_inv; }
get_shape_aabb(int p_index)128 	_FORCE_INLINE_ const AABB &get_shape_aabb(int p_index) const { return shapes[p_index].aabb_cache; }
get_shape_area(int p_index)129 	_FORCE_INLINE_ real_t get_shape_area(int p_index) const { return shapes[p_index].area_cache; }
130 
get_transform()131 	_FORCE_INLINE_ Transform get_transform() const { return transform; }
get_inv_transform()132 	_FORCE_INLINE_ Transform get_inv_transform() const { return inv_transform; }
get_space()133 	_FORCE_INLINE_ SpaceSW *get_space() const { return space; }
134 
set_ray_pickable(bool p_enable)135 	_FORCE_INLINE_ void set_ray_pickable(bool p_enable) { ray_pickable = p_enable; }
is_ray_pickable()136 	_FORCE_INLINE_ bool is_ray_pickable() const { return ray_pickable; }
137 
138 	void set_shape_as_disabled(int p_idx, bool p_enable);
is_shape_set_as_disabled(int p_idx)139 	_FORCE_INLINE_ bool is_shape_set_as_disabled(int p_idx) const {
140 		CRASH_BAD_INDEX(p_idx, shapes.size());
141 		return shapes[p_idx].disabled;
142 	}
143 
set_collision_layer(uint32_t p_layer)144 	_FORCE_INLINE_ void set_collision_layer(uint32_t p_layer) {
145 		collision_layer = p_layer;
146 		_shape_changed();
147 	}
get_collision_layer()148 	_FORCE_INLINE_ uint32_t get_collision_layer() const { return collision_layer; }
149 
set_collision_mask(uint32_t p_mask)150 	_FORCE_INLINE_ void set_collision_mask(uint32_t p_mask) {
151 		collision_mask = p_mask;
152 		_shape_changed();
153 	}
get_collision_mask()154 	_FORCE_INLINE_ uint32_t get_collision_mask() const { return collision_mask; }
155 
test_collision_mask(CollisionObjectSW * p_other)156 	_FORCE_INLINE_ bool test_collision_mask(CollisionObjectSW *p_other) const {
157 		return collision_layer & p_other->collision_mask || p_other->collision_layer & collision_mask;
158 	}
159 
160 	void remove_shape(ShapeSW *p_shape);
161 	void remove_shape(int p_index);
162 
163 	virtual void set_space(SpaceSW *p_space) = 0;
164 
is_static()165 	_FORCE_INLINE_ bool is_static() const { return _static; }
166 
~CollisionObjectSW()167 	virtual ~CollisionObjectSW() {}
168 };
169 
170 #endif // COLLISION_OBJECT_SW_H
171