1 | /**************************************************************************/ |
2 | /* physics_body_3d.h */ |
3 | /**************************************************************************/ |
4 | /* This file is part of: */ |
5 | /* GODOT ENGINE */ |
6 | /* https://godotengine.org */ |
7 | /**************************************************************************/ |
8 | /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ |
9 | /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ |
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 PHYSICS_BODY_3D_H |
32 | #define PHYSICS_BODY_3D_H |
33 | |
34 | #include "core/templates/vset.h" |
35 | #include "scene/3d/collision_object_3d.h" |
36 | #include "scene/resources/physics_material.h" |
37 | #include "servers/physics_server_3d.h" |
38 | #include "skeleton_3d.h" |
39 | |
40 | class KinematicCollision3D; |
41 | |
42 | class PhysicsBody3D : public CollisionObject3D { |
43 | GDCLASS(PhysicsBody3D, CollisionObject3D); |
44 | |
45 | protected: |
46 | static void _bind_methods(); |
47 | PhysicsBody3D(PhysicsServer3D::BodyMode p_mode); |
48 | |
49 | Ref<KinematicCollision3D> motion_cache; |
50 | |
51 | uint16_t locked_axis = 0; |
52 | |
53 | Ref<KinematicCollision3D> _move(const Vector3 &p_motion, bool p_test_only = false, real_t p_margin = 0.001, bool p_recovery_as_collision = false, int p_max_collisions = 1); |
54 | |
55 | public: |
56 | bool move_and_collide(const PhysicsServer3D::MotionParameters &p_parameters, PhysicsServer3D::MotionResult &r_result, bool p_test_only = false, bool p_cancel_sliding = true); |
57 | bool test_move(const Transform3D &p_from, const Vector3 &p_motion, const Ref<KinematicCollision3D> &r_collision = Ref<KinematicCollision3D>(), real_t p_margin = 0.001, bool p_recovery_as_collision = false, int p_max_collisions = 1); |
58 | |
59 | void set_axis_lock(PhysicsServer3D::BodyAxis p_axis, bool p_lock); |
60 | bool get_axis_lock(PhysicsServer3D::BodyAxis p_axis) const; |
61 | |
62 | virtual Vector3 get_linear_velocity() const; |
63 | virtual Vector3 get_angular_velocity() const; |
64 | virtual real_t get_inverse_mass() const; |
65 | |
66 | TypedArray<PhysicsBody3D> get_collision_exceptions(); |
67 | void add_collision_exception_with(Node *p_node); //must be physicsbody |
68 | void remove_collision_exception_with(Node *p_node); |
69 | |
70 | virtual ~PhysicsBody3D(); |
71 | }; |
72 | |
73 | class StaticBody3D : public PhysicsBody3D { |
74 | GDCLASS(StaticBody3D, PhysicsBody3D); |
75 | |
76 | private: |
77 | Vector3 constant_linear_velocity; |
78 | Vector3 constant_angular_velocity; |
79 | |
80 | Ref<PhysicsMaterial> physics_material_override; |
81 | |
82 | protected: |
83 | static void _bind_methods(); |
84 | |
85 | public: |
86 | void set_physics_material_override(const Ref<PhysicsMaterial> &p_physics_material_override); |
87 | Ref<PhysicsMaterial> get_physics_material_override() const; |
88 | |
89 | void set_constant_linear_velocity(const Vector3 &p_vel); |
90 | void set_constant_angular_velocity(const Vector3 &p_vel); |
91 | |
92 | Vector3 get_constant_linear_velocity() const; |
93 | Vector3 get_constant_angular_velocity() const; |
94 | |
95 | StaticBody3D(PhysicsServer3D::BodyMode p_mode = PhysicsServer3D::BODY_MODE_STATIC); |
96 | |
97 | private: |
98 | void _reload_physics_characteristics(); |
99 | }; |
100 | |
101 | class AnimatableBody3D : public StaticBody3D { |
102 | GDCLASS(AnimatableBody3D, StaticBody3D); |
103 | |
104 | private: |
105 | Vector3 linear_velocity; |
106 | Vector3 angular_velocity; |
107 | |
108 | bool sync_to_physics = true; |
109 | |
110 | Transform3D last_valid_transform; |
111 | |
112 | static void _body_state_changed_callback(void *p_instance, PhysicsDirectBodyState3D *p_state); |
113 | void _body_state_changed(PhysicsDirectBodyState3D *p_state); |
114 | |
115 | protected: |
116 | void _notification(int p_what); |
117 | static void _bind_methods(); |
118 | |
119 | public: |
120 | virtual Vector3 get_linear_velocity() const override; |
121 | virtual Vector3 get_angular_velocity() const override; |
122 | |
123 | AnimatableBody3D(); |
124 | |
125 | private: |
126 | void _update_kinematic_motion(); |
127 | |
128 | void set_sync_to_physics(bool p_enable); |
129 | bool is_sync_to_physics_enabled() const; |
130 | }; |
131 | |
132 | class RigidBody3D : public PhysicsBody3D { |
133 | GDCLASS(RigidBody3D, PhysicsBody3D); |
134 | |
135 | public: |
136 | enum FreezeMode { |
137 | FREEZE_MODE_STATIC, |
138 | FREEZE_MODE_KINEMATIC, |
139 | }; |
140 | |
141 | enum CenterOfMassMode { |
142 | CENTER_OF_MASS_MODE_AUTO, |
143 | CENTER_OF_MASS_MODE_CUSTOM, |
144 | }; |
145 | |
146 | enum DampMode { |
147 | DAMP_MODE_COMBINE, |
148 | DAMP_MODE_REPLACE, |
149 | }; |
150 | |
151 | private: |
152 | bool can_sleep = true; |
153 | bool lock_rotation = false; |
154 | bool freeze = false; |
155 | FreezeMode freeze_mode = FREEZE_MODE_STATIC; |
156 | |
157 | real_t mass = 1.0; |
158 | Vector3 inertia; |
159 | CenterOfMassMode center_of_mass_mode = CENTER_OF_MASS_MODE_AUTO; |
160 | Vector3 center_of_mass; |
161 | |
162 | Ref<PhysicsMaterial> physics_material_override; |
163 | |
164 | Vector3 linear_velocity; |
165 | Vector3 angular_velocity; |
166 | Basis inverse_inertia_tensor; |
167 | real_t gravity_scale = 1.0; |
168 | |
169 | DampMode linear_damp_mode = DAMP_MODE_COMBINE; |
170 | DampMode angular_damp_mode = DAMP_MODE_COMBINE; |
171 | |
172 | real_t linear_damp = 0.0; |
173 | real_t angular_damp = 0.0; |
174 | |
175 | bool sleeping = false; |
176 | bool ccd = false; |
177 | |
178 | int max_contacts_reported = 0; |
179 | |
180 | bool custom_integrator = false; |
181 | |
182 | struct ShapePair { |
183 | int body_shape = 0; |
184 | int local_shape = 0; |
185 | bool tagged = false; |
186 | bool operator<(const ShapePair &p_sp) const { |
187 | if (body_shape == p_sp.body_shape) { |
188 | return local_shape < p_sp.local_shape; |
189 | } else { |
190 | return body_shape < p_sp.body_shape; |
191 | } |
192 | } |
193 | |
194 | ShapePair() {} |
195 | ShapePair(int p_bs, int p_ls) { |
196 | body_shape = p_bs; |
197 | local_shape = p_ls; |
198 | tagged = false; |
199 | } |
200 | }; |
201 | struct RigidBody3D_RemoveAction { |
202 | RID rid; |
203 | ObjectID body_id; |
204 | ShapePair pair; |
205 | }; |
206 | struct BodyState { |
207 | RID rid; |
208 | //int rc; |
209 | bool in_tree = false; |
210 | VSet<ShapePair> shapes; |
211 | }; |
212 | |
213 | struct ContactMonitor { |
214 | bool locked = false; |
215 | HashMap<ObjectID, BodyState> body_map; |
216 | }; |
217 | |
218 | ContactMonitor *contact_monitor = nullptr; |
219 | void _body_enter_tree(ObjectID p_id); |
220 | void _body_exit_tree(ObjectID p_id); |
221 | |
222 | void _body_inout(int p_status, const RID &p_body, ObjectID p_instance, int p_body_shape, int p_local_shape); |
223 | static void _body_state_changed_callback(void *p_instance, PhysicsDirectBodyState3D *p_state); |
224 | |
225 | void _sync_body_state(PhysicsDirectBodyState3D *p_state); |
226 | |
227 | protected: |
228 | void _notification(int p_what); |
229 | static void _bind_methods(); |
230 | |
231 | void _validate_property(PropertyInfo &p_property) const; |
232 | |
233 | GDVIRTUAL1(_integrate_forces, PhysicsDirectBodyState3D *) |
234 | |
235 | virtual void _body_state_changed(PhysicsDirectBodyState3D *p_state); |
236 | |
237 | void _apply_body_mode(); |
238 | |
239 | public: |
240 | void set_lock_rotation_enabled(bool p_lock_rotation); |
241 | bool is_lock_rotation_enabled() const; |
242 | |
243 | void set_freeze_enabled(bool p_freeze); |
244 | bool is_freeze_enabled() const; |
245 | |
246 | void set_freeze_mode(FreezeMode p_freeze_mode); |
247 | FreezeMode get_freeze_mode() const; |
248 | |
249 | void set_mass(real_t p_mass); |
250 | real_t get_mass() const; |
251 | |
252 | virtual real_t get_inverse_mass() const override { return 1.0 / mass; } |
253 | |
254 | void set_inertia(const Vector3 &p_inertia); |
255 | const Vector3 &get_inertia() const; |
256 | |
257 | void set_center_of_mass_mode(CenterOfMassMode p_mode); |
258 | CenterOfMassMode get_center_of_mass_mode() const; |
259 | |
260 | void set_center_of_mass(const Vector3 &p_center_of_mass); |
261 | const Vector3 &get_center_of_mass() const; |
262 | |
263 | void set_physics_material_override(const Ref<PhysicsMaterial> &p_physics_material_override); |
264 | Ref<PhysicsMaterial> get_physics_material_override() const; |
265 | |
266 | void set_linear_velocity(const Vector3 &p_velocity); |
267 | Vector3 get_linear_velocity() const override; |
268 | |
269 | void set_axis_velocity(const Vector3 &p_axis); |
270 | |
271 | void set_angular_velocity(const Vector3 &p_velocity); |
272 | Vector3 get_angular_velocity() const override; |
273 | |
274 | Basis get_inverse_inertia_tensor() const; |
275 | |
276 | void set_gravity_scale(real_t p_gravity_scale); |
277 | real_t get_gravity_scale() const; |
278 | |
279 | void set_linear_damp_mode(DampMode p_mode); |
280 | DampMode get_linear_damp_mode() const; |
281 | |
282 | void set_angular_damp_mode(DampMode p_mode); |
283 | DampMode get_angular_damp_mode() const; |
284 | |
285 | void set_linear_damp(real_t p_linear_damp); |
286 | real_t get_linear_damp() const; |
287 | |
288 | void set_angular_damp(real_t p_angular_damp); |
289 | real_t get_angular_damp() const; |
290 | |
291 | void set_use_custom_integrator(bool p_enable); |
292 | bool is_using_custom_integrator(); |
293 | |
294 | void set_sleeping(bool p_sleeping); |
295 | bool is_sleeping() const; |
296 | |
297 | void set_can_sleep(bool p_active); |
298 | bool is_able_to_sleep() const; |
299 | |
300 | void set_contact_monitor(bool p_enabled); |
301 | bool is_contact_monitor_enabled() const; |
302 | |
303 | void set_max_contacts_reported(int p_amount); |
304 | int get_max_contacts_reported() const; |
305 | int get_contact_count() const; |
306 | |
307 | void set_use_continuous_collision_detection(bool p_enable); |
308 | bool is_using_continuous_collision_detection() const; |
309 | |
310 | TypedArray<Node3D> get_colliding_bodies() const; |
311 | |
312 | void apply_central_impulse(const Vector3 &p_impulse); |
313 | void apply_impulse(const Vector3 &p_impulse, const Vector3 &p_position = Vector3()); |
314 | void apply_torque_impulse(const Vector3 &p_impulse); |
315 | |
316 | void apply_central_force(const Vector3 &p_force); |
317 | void apply_force(const Vector3 &p_force, const Vector3 &p_position = Vector3()); |
318 | void apply_torque(const Vector3 &p_torque); |
319 | |
320 | void add_constant_central_force(const Vector3 &p_force); |
321 | void add_constant_force(const Vector3 &p_force, const Vector3 &p_position = Vector3()); |
322 | void add_constant_torque(const Vector3 &p_torque); |
323 | |
324 | void set_constant_force(const Vector3 &p_force); |
325 | Vector3 get_constant_force() const; |
326 | |
327 | void set_constant_torque(const Vector3 &p_torque); |
328 | Vector3 get_constant_torque() const; |
329 | |
330 | virtual PackedStringArray get_configuration_warnings() const override; |
331 | |
332 | RigidBody3D(); |
333 | ~RigidBody3D(); |
334 | |
335 | private: |
336 | void _reload_physics_characteristics(); |
337 | }; |
338 | |
339 | VARIANT_ENUM_CAST(RigidBody3D::FreezeMode); |
340 | VARIANT_ENUM_CAST(RigidBody3D::CenterOfMassMode); |
341 | VARIANT_ENUM_CAST(RigidBody3D::DampMode); |
342 | |
343 | class KinematicCollision3D; |
344 | |
345 | class CharacterBody3D : public PhysicsBody3D { |
346 | GDCLASS(CharacterBody3D, PhysicsBody3D); |
347 | |
348 | public: |
349 | enum MotionMode { |
350 | MOTION_MODE_GROUNDED, |
351 | MOTION_MODE_FLOATING, |
352 | }; |
353 | enum PlatformOnLeave { |
354 | PLATFORM_ON_LEAVE_ADD_VELOCITY, |
355 | PLATFORM_ON_LEAVE_ADD_UPWARD_VELOCITY, |
356 | PLATFORM_ON_LEAVE_DO_NOTHING, |
357 | }; |
358 | bool move_and_slide(); |
359 | void apply_floor_snap(); |
360 | |
361 | const Vector3 &get_velocity() const; |
362 | void set_velocity(const Vector3 &p_velocity); |
363 | |
364 | bool is_on_floor() const; |
365 | bool is_on_floor_only() const; |
366 | bool is_on_wall() const; |
367 | bool is_on_wall_only() const; |
368 | bool is_on_ceiling() const; |
369 | bool is_on_ceiling_only() const; |
370 | const Vector3 &get_last_motion() const; |
371 | Vector3 get_position_delta() const; |
372 | const Vector3 &get_floor_normal() const; |
373 | const Vector3 &get_wall_normal() const; |
374 | const Vector3 &get_real_velocity() const; |
375 | real_t get_floor_angle(const Vector3 &p_up_direction = Vector3(0.0, 1.0, 0.0)) const; |
376 | const Vector3 &get_platform_velocity() const; |
377 | const Vector3 &get_platform_angular_velocity() const; |
378 | |
379 | virtual Vector3 get_linear_velocity() const override; |
380 | |
381 | int get_slide_collision_count() const; |
382 | PhysicsServer3D::MotionResult get_slide_collision(int p_bounce) const; |
383 | |
384 | CharacterBody3D(); |
385 | ~CharacterBody3D(); |
386 | |
387 | private: |
388 | real_t margin = 0.001; |
389 | MotionMode motion_mode = MOTION_MODE_GROUNDED; |
390 | PlatformOnLeave platform_on_leave = PLATFORM_ON_LEAVE_ADD_VELOCITY; |
391 | union CollisionState { |
392 | uint32_t state = 0; |
393 | struct { |
394 | bool floor; |
395 | bool wall; |
396 | bool ceiling; |
397 | }; |
398 | |
399 | CollisionState() { |
400 | } |
401 | |
402 | CollisionState(bool p_floor, bool p_wall, bool p_ceiling) { |
403 | floor = p_floor; |
404 | wall = p_wall; |
405 | ceiling = p_ceiling; |
406 | } |
407 | }; |
408 | |
409 | CollisionState collision_state; |
410 | bool floor_constant_speed = false; |
411 | bool floor_stop_on_slope = true; |
412 | bool floor_block_on_wall = true; |
413 | bool slide_on_ceiling = true; |
414 | int max_slides = 6; |
415 | int platform_layer = 0; |
416 | RID platform_rid; |
417 | ObjectID platform_object_id; |
418 | uint32_t platform_floor_layers = UINT32_MAX; |
419 | uint32_t platform_wall_layers = 0; |
420 | real_t floor_snap_length = 0.1; |
421 | real_t floor_max_angle = Math::deg_to_rad((real_t)45.0); |
422 | real_t wall_min_slide_angle = Math::deg_to_rad((real_t)15.0); |
423 | Vector3 up_direction = Vector3(0.0, 1.0, 0.0); |
424 | Vector3 velocity; |
425 | Vector3 floor_normal; |
426 | Vector3 wall_normal; |
427 | Vector3 ceiling_normal; |
428 | Vector3 last_motion; |
429 | Vector3 platform_velocity; |
430 | Vector3 platform_angular_velocity; |
431 | Vector3 platform_ceiling_velocity; |
432 | Vector3 previous_position; |
433 | Vector3 real_velocity; |
434 | |
435 | Vector<PhysicsServer3D::MotionResult> motion_results; |
436 | Vector<Ref<KinematicCollision3D>> slide_colliders; |
437 | |
438 | void set_safe_margin(real_t p_margin); |
439 | real_t get_safe_margin() const; |
440 | |
441 | bool is_floor_stop_on_slope_enabled() const; |
442 | void set_floor_stop_on_slope_enabled(bool p_enabled); |
443 | |
444 | bool is_floor_constant_speed_enabled() const; |
445 | void set_floor_constant_speed_enabled(bool p_enabled); |
446 | |
447 | bool is_floor_block_on_wall_enabled() const; |
448 | void set_floor_block_on_wall_enabled(bool p_enabled); |
449 | |
450 | bool is_slide_on_ceiling_enabled() const; |
451 | void set_slide_on_ceiling_enabled(bool p_enabled); |
452 | |
453 | int get_max_slides() const; |
454 | void set_max_slides(int p_max_slides); |
455 | |
456 | real_t get_floor_max_angle() const; |
457 | void set_floor_max_angle(real_t p_radians); |
458 | |
459 | real_t get_floor_snap_length(); |
460 | void set_floor_snap_length(real_t p_floor_snap_length); |
461 | |
462 | real_t get_wall_min_slide_angle() const; |
463 | void set_wall_min_slide_angle(real_t p_radians); |
464 | |
465 | uint32_t get_platform_floor_layers() const; |
466 | void set_platform_floor_layers(const uint32_t p_exclude_layer); |
467 | |
468 | uint32_t get_platform_wall_layers() const; |
469 | void set_platform_wall_layers(const uint32_t p_exclude_layer); |
470 | |
471 | void set_motion_mode(MotionMode p_mode); |
472 | MotionMode get_motion_mode() const; |
473 | |
474 | void set_platform_on_leave(PlatformOnLeave p_on_leave_velocity); |
475 | PlatformOnLeave get_platform_on_leave() const; |
476 | |
477 | void _move_and_slide_floating(double p_delta); |
478 | void _move_and_slide_grounded(double p_delta, bool p_was_on_floor); |
479 | |
480 | Ref<KinematicCollision3D> _get_slide_collision(int p_bounce); |
481 | Ref<KinematicCollision3D> _get_last_slide_collision(); |
482 | const Vector3 &get_up_direction() const; |
483 | bool _on_floor_if_snapped(bool p_was_on_floor, bool p_vel_dir_facing_up); |
484 | void set_up_direction(const Vector3 &p_up_direction); |
485 | void _set_collision_direction(const PhysicsServer3D::MotionResult &p_result, CollisionState &r_state, CollisionState p_apply_state = CollisionState(true, true, true)); |
486 | void _set_platform_data(const PhysicsServer3D::MotionCollision &p_collision); |
487 | void _snap_on_floor(bool p_was_on_floor, bool p_vel_dir_facing_up); |
488 | |
489 | protected: |
490 | void _notification(int p_what); |
491 | static void _bind_methods(); |
492 | void _validate_property(PropertyInfo &p_property) const; |
493 | }; |
494 | |
495 | VARIANT_ENUM_CAST(CharacterBody3D::MotionMode); |
496 | VARIANT_ENUM_CAST(CharacterBody3D::PlatformOnLeave); |
497 | |
498 | class KinematicCollision3D : public RefCounted { |
499 | GDCLASS(KinematicCollision3D, RefCounted); |
500 | |
501 | PhysicsBody3D *owner = nullptr; |
502 | friend class PhysicsBody3D; |
503 | friend class CharacterBody3D; |
504 | PhysicsServer3D::MotionResult result; |
505 | |
506 | protected: |
507 | static void _bind_methods(); |
508 | |
509 | public: |
510 | Vector3 get_travel() const; |
511 | Vector3 get_remainder() const; |
512 | int get_collision_count() const; |
513 | real_t get_depth() const; |
514 | Vector3 get_position(int p_collision_index = 0) const; |
515 | Vector3 get_normal(int p_collision_index = 0) const; |
516 | real_t get_angle(int p_collision_index = 0, const Vector3 &p_up_direction = Vector3(0.0, 1.0, 0.0)) const; |
517 | Object *get_local_shape(int p_collision_index = 0) const; |
518 | Object *get_collider(int p_collision_index = 0) const; |
519 | ObjectID get_collider_id(int p_collision_index = 0) const; |
520 | RID get_collider_rid(int p_collision_index = 0) const; |
521 | Object *get_collider_shape(int p_collision_index = 0) const; |
522 | int get_collider_shape_index(int p_collision_index = 0) const; |
523 | Vector3 get_collider_velocity(int p_collision_index = 0) const; |
524 | }; |
525 | |
526 | class PhysicalBone3D : public PhysicsBody3D { |
527 | GDCLASS(PhysicalBone3D, PhysicsBody3D); |
528 | |
529 | public: |
530 | enum DampMode { |
531 | DAMP_MODE_COMBINE, |
532 | DAMP_MODE_REPLACE, |
533 | }; |
534 | |
535 | enum JointType { |
536 | JOINT_TYPE_NONE, |
537 | JOINT_TYPE_PIN, |
538 | JOINT_TYPE_CONE, |
539 | JOINT_TYPE_HINGE, |
540 | JOINT_TYPE_SLIDER, |
541 | JOINT_TYPE_6DOF |
542 | }; |
543 | |
544 | struct JointData { |
545 | virtual JointType get_joint_type() { return JOINT_TYPE_NONE; } |
546 | |
547 | /// "j" is used to set the parameter inside the PhysicsServer3D |
548 | virtual bool _set(const StringName &p_name, const Variant &p_value, RID j); |
549 | virtual bool _get(const StringName &p_name, Variant &r_ret) const; |
550 | virtual void _get_property_list(List<PropertyInfo> *p_list) const; |
551 | |
552 | virtual ~JointData() {} |
553 | }; |
554 | |
555 | struct PinJointData : public JointData { |
556 | virtual JointType get_joint_type() { return JOINT_TYPE_PIN; } |
557 | |
558 | virtual bool _set(const StringName &p_name, const Variant &p_value, RID j); |
559 | virtual bool _get(const StringName &p_name, Variant &r_ret) const; |
560 | virtual void _get_property_list(List<PropertyInfo> *p_list) const; |
561 | |
562 | real_t bias = 0.3; |
563 | real_t damping = 1.0; |
564 | real_t impulse_clamp = 0.0; |
565 | }; |
566 | |
567 | struct ConeJointData : public JointData { |
568 | virtual JointType get_joint_type() { return JOINT_TYPE_CONE; } |
569 | |
570 | virtual bool _set(const StringName &p_name, const Variant &p_value, RID j); |
571 | virtual bool _get(const StringName &p_name, Variant &r_ret) const; |
572 | virtual void _get_property_list(List<PropertyInfo> *p_list) const; |
573 | |
574 | real_t swing_span = Math_PI * 0.25; |
575 | real_t twist_span = Math_PI; |
576 | real_t bias = 0.3; |
577 | real_t softness = 0.8; |
578 | real_t relaxation = 1.; |
579 | }; |
580 | |
581 | struct HingeJointData : public JointData { |
582 | virtual JointType get_joint_type() { return JOINT_TYPE_HINGE; } |
583 | |
584 | virtual bool _set(const StringName &p_name, const Variant &p_value, RID j); |
585 | virtual bool _get(const StringName &p_name, Variant &r_ret) const; |
586 | virtual void _get_property_list(List<PropertyInfo> *p_list) const; |
587 | |
588 | bool angular_limit_enabled = false; |
589 | real_t angular_limit_upper = Math_PI * 0.5; |
590 | real_t angular_limit_lower = -Math_PI * 0.5; |
591 | real_t angular_limit_bias = 0.3; |
592 | real_t angular_limit_softness = 0.9; |
593 | real_t angular_limit_relaxation = 1.; |
594 | }; |
595 | |
596 | struct SliderJointData : public JointData { |
597 | virtual JointType get_joint_type() { return JOINT_TYPE_SLIDER; } |
598 | |
599 | virtual bool _set(const StringName &p_name, const Variant &p_value, RID j); |
600 | virtual bool _get(const StringName &p_name, Variant &r_ret) const; |
601 | virtual void _get_property_list(List<PropertyInfo> *p_list) const; |
602 | |
603 | real_t linear_limit_upper = 1.0; |
604 | real_t linear_limit_lower = -1.0; |
605 | real_t linear_limit_softness = 1.0; |
606 | real_t linear_limit_restitution = 0.7; |
607 | real_t linear_limit_damping = 1.0; |
608 | real_t angular_limit_upper = 0.0; |
609 | real_t angular_limit_lower = 0.0; |
610 | real_t angular_limit_softness = 1.0; |
611 | real_t angular_limit_restitution = 0.7; |
612 | real_t angular_limit_damping = 1.0; |
613 | }; |
614 | |
615 | struct SixDOFJointData : public JointData { |
616 | struct SixDOFAxisData { |
617 | bool linear_limit_enabled = true; |
618 | real_t linear_limit_upper = 0.0; |
619 | real_t linear_limit_lower = 0.0; |
620 | real_t linear_limit_softness = 0.7; |
621 | real_t linear_restitution = 0.5; |
622 | real_t linear_damping = 1.0; |
623 | bool linear_spring_enabled = false; |
624 | real_t linear_spring_stiffness = 0.0; |
625 | real_t linear_spring_damping = 0.0; |
626 | real_t linear_equilibrium_point = 0.0; |
627 | bool angular_limit_enabled = true; |
628 | real_t angular_limit_upper = 0.0; |
629 | real_t angular_limit_lower = 0.0; |
630 | real_t angular_limit_softness = 0.5; |
631 | real_t angular_restitution = 0.0; |
632 | real_t angular_damping = 1.0; |
633 | real_t erp = 0.5; |
634 | bool angular_spring_enabled = false; |
635 | real_t angular_spring_stiffness = 0.0; |
636 | real_t angular_spring_damping = 0.0; |
637 | real_t angular_equilibrium_point = 0.0; |
638 | }; |
639 | |
640 | virtual JointType get_joint_type() { return JOINT_TYPE_6DOF; } |
641 | |
642 | virtual bool _set(const StringName &p_name, const Variant &p_value, RID j); |
643 | virtual bool _get(const StringName &p_name, Variant &r_ret) const; |
644 | virtual void _get_property_list(List<PropertyInfo> *p_list) const; |
645 | |
646 | SixDOFAxisData axis_data[3]; |
647 | |
648 | SixDOFJointData() {} |
649 | }; |
650 | |
651 | private: |
652 | #ifdef TOOLS_ENABLED |
653 | // if false gizmo move body |
654 | bool gizmo_move_joint = false; |
655 | #endif |
656 | |
657 | JointData *joint_data = nullptr; |
658 | Transform3D joint_offset; |
659 | RID joint; |
660 | |
661 | Skeleton3D *parent_skeleton = nullptr; |
662 | Transform3D body_offset; |
663 | Transform3D body_offset_inverse; |
664 | bool simulate_physics = false; |
665 | bool _internal_simulate_physics = false; |
666 | int bone_id = -1; |
667 | |
668 | String bone_name; |
669 | real_t bounce = 0.0; |
670 | real_t mass = 1.0; |
671 | real_t friction = 1.0; |
672 | Vector3 linear_velocity; |
673 | Vector3 angular_velocity; |
674 | real_t gravity_scale = 1.0; |
675 | bool can_sleep = true; |
676 | |
677 | bool custom_integrator = false; |
678 | |
679 | DampMode linear_damp_mode = DAMP_MODE_COMBINE; |
680 | DampMode angular_damp_mode = DAMP_MODE_COMBINE; |
681 | |
682 | real_t linear_damp = 0.0; |
683 | real_t angular_damp = 0.0; |
684 | |
685 | protected: |
686 | bool _set(const StringName &p_name, const Variant &p_value); |
687 | bool _get(const StringName &p_name, Variant &r_ret) const; |
688 | void _get_property_list(List<PropertyInfo> *p_list) const; |
689 | void _notification(int p_what); |
690 | GDVIRTUAL1(_integrate_forces, PhysicsDirectBodyState3D *) |
691 | static void _body_state_changed_callback(void *p_instance, PhysicsDirectBodyState3D *p_state); |
692 | void _body_state_changed(PhysicsDirectBodyState3D *p_state); |
693 | |
694 | static void _bind_methods(); |
695 | |
696 | private: |
697 | void _sync_body_state(PhysicsDirectBodyState3D *p_state); |
698 | static Skeleton3D *find_skeleton_parent(Node *p_parent); |
699 | |
700 | void _update_joint_offset(); |
701 | void _fix_joint_offset(); |
702 | void _reload_joint(); |
703 | |
704 | public: |
705 | void _on_bone_parent_changed(); |
706 | |
707 | void set_linear_velocity(const Vector3 &p_velocity); |
708 | Vector3 get_linear_velocity() const override; |
709 | |
710 | void set_angular_velocity(const Vector3 &p_velocity); |
711 | Vector3 get_angular_velocity() const override; |
712 | |
713 | void set_use_custom_integrator(bool p_enable); |
714 | bool is_using_custom_integrator(); |
715 | |
716 | #ifdef TOOLS_ENABLED |
717 | void _set_gizmo_move_joint(bool p_move_joint); |
718 | virtual Transform3D get_global_gizmo_transform() const override; |
719 | virtual Transform3D get_local_gizmo_transform() const override; |
720 | #endif |
721 | |
722 | const JointData *get_joint_data() const; |
723 | Skeleton3D *find_skeleton_parent(); |
724 | |
725 | int get_bone_id() const { |
726 | return bone_id; |
727 | } |
728 | |
729 | void set_joint_type(JointType p_joint_type); |
730 | JointType get_joint_type() const; |
731 | |
732 | void set_joint_offset(const Transform3D &p_offset); |
733 | const Transform3D &get_joint_offset() const; |
734 | |
735 | void set_joint_rotation(const Vector3 &p_euler_rad); |
736 | Vector3 get_joint_rotation() const; |
737 | |
738 | void set_body_offset(const Transform3D &p_offset); |
739 | const Transform3D &get_body_offset() const; |
740 | |
741 | void set_simulate_physics(bool p_simulate); |
742 | bool get_simulate_physics(); |
743 | bool is_simulating_physics(); |
744 | |
745 | void set_bone_name(const String &p_name); |
746 | const String &get_bone_name() const; |
747 | |
748 | void set_mass(real_t p_mass); |
749 | real_t get_mass() const; |
750 | |
751 | void set_friction(real_t p_friction); |
752 | real_t get_friction() const; |
753 | |
754 | void set_bounce(real_t p_bounce); |
755 | real_t get_bounce() const; |
756 | |
757 | void set_gravity_scale(real_t p_gravity_scale); |
758 | real_t get_gravity_scale() const; |
759 | |
760 | void set_linear_damp_mode(DampMode p_mode); |
761 | DampMode get_linear_damp_mode() const; |
762 | |
763 | void set_angular_damp_mode(DampMode p_mode); |
764 | DampMode get_angular_damp_mode() const; |
765 | |
766 | void set_linear_damp(real_t p_linear_damp); |
767 | real_t get_linear_damp() const; |
768 | |
769 | void set_angular_damp(real_t p_angular_damp); |
770 | real_t get_angular_damp() const; |
771 | |
772 | void set_can_sleep(bool p_active); |
773 | bool is_able_to_sleep() const; |
774 | |
775 | void apply_central_impulse(const Vector3 &p_impulse); |
776 | void apply_impulse(const Vector3 &p_impulse, const Vector3 &p_position = Vector3()); |
777 | |
778 | void reset_physics_simulation_state(); |
779 | void reset_to_rest_position(); |
780 | |
781 | PhysicalBone3D(); |
782 | ~PhysicalBone3D(); |
783 | |
784 | private: |
785 | void update_bone_id(); |
786 | void update_offset(); |
787 | |
788 | void _start_physics_simulation(); |
789 | void _stop_physics_simulation(); |
790 | }; |
791 | |
792 | VARIANT_ENUM_CAST(PhysicalBone3D::JointType); |
793 | VARIANT_ENUM_CAST(PhysicalBone3D::DampMode); |
794 | |
795 | #endif // PHYSICS_BODY_3D_H |
796 | |