Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/modules/jolt_physics/joints/jolt_generic_6dof_joint_3d.cpp
10278 views
1
/**************************************************************************/
2
/* jolt_generic_6dof_joint_3d.cpp */
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
#include "jolt_generic_6dof_joint_3d.h"
32
33
#include "../misc/jolt_type_conversions.h"
34
#include "../objects/jolt_body_3d.h"
35
#include "../spaces/jolt_space_3d.h"
36
37
#include "Jolt/Physics/Constraints/SixDOFConstraint.h"
38
39
namespace {
40
41
constexpr double G6DOF_DEFAULT_LINEAR_LIMIT_SOFTNESS = 0.7;
42
constexpr double G6DOF_DEFAULT_LINEAR_RESTITUTION = 0.5;
43
constexpr double G6DOF_DEFAULT_LINEAR_DAMPING = 1.0;
44
45
constexpr double G6DOF_DEFAULT_ANGULAR_LIMIT_SOFTNESS = 0.5;
46
constexpr double G6DOF_DEFAULT_ANGULAR_DAMPING = 1.0;
47
constexpr double G6DOF_DEFAULT_ANGULAR_RESTITUTION = 0.0;
48
constexpr double G6DOF_DEFAULT_ANGULAR_FORCE_LIMIT = 0.0;
49
constexpr double G6DOF_DEFAULT_ANGULAR_ERP = 0.5;
50
51
} // namespace
52
53
JPH::Constraint *JoltGeneric6DOFJoint3D::_build_6dof(JPH::Body *p_jolt_body_a, JPH::Body *p_jolt_body_b, const Transform3D &p_shifted_ref_a, const Transform3D &p_shifted_ref_b) const {
54
JPH::SixDOFConstraintSettings constraint_settings;
55
56
for (int axis = 0; axis < AXIS_COUNT; ++axis) {
57
double lower = limit_lower[axis];
58
double upper = limit_upper[axis];
59
60
if (axis >= AXIS_ANGULAR_X && axis <= AXIS_ANGULAR_Z) {
61
const double temp = lower;
62
lower = -upper;
63
upper = -temp;
64
}
65
66
if (!limit_enabled[axis] || lower > upper) {
67
constraint_settings.MakeFreeAxis((JoltAxis)axis);
68
} else {
69
constraint_settings.SetLimitedAxis((JoltAxis)axis, (float)lower, (float)upper);
70
}
71
}
72
73
constraint_settings.mSpace = JPH::EConstraintSpace::LocalToBodyCOM;
74
constraint_settings.mPosition1 = to_jolt_r(p_shifted_ref_a.origin);
75
constraint_settings.mAxisX1 = to_jolt(p_shifted_ref_a.basis.get_column(Vector3::AXIS_X));
76
constraint_settings.mAxisY1 = to_jolt(p_shifted_ref_a.basis.get_column(Vector3::AXIS_Y));
77
constraint_settings.mPosition2 = to_jolt_r(p_shifted_ref_b.origin);
78
constraint_settings.mAxisX2 = to_jolt(p_shifted_ref_b.basis.get_column(Vector3::AXIS_X));
79
constraint_settings.mAxisY2 = to_jolt(p_shifted_ref_b.basis.get_column(Vector3::AXIS_Y));
80
constraint_settings.mSwingType = JPH::ESwingType::Pyramid;
81
82
if (p_jolt_body_a == nullptr) {
83
return constraint_settings.Create(JPH::Body::sFixedToWorld, *p_jolt_body_b);
84
} else if (p_jolt_body_b == nullptr) {
85
return constraint_settings.Create(*p_jolt_body_a, JPH::Body::sFixedToWorld);
86
} else {
87
return constraint_settings.Create(*p_jolt_body_a, *p_jolt_body_b);
88
}
89
}
90
91
void JoltGeneric6DOFJoint3D::_update_limit_spring_parameters(int p_axis) {
92
JPH::SixDOFConstraint *constraint = static_cast<JPH::SixDOFConstraint *>(jolt_ref.GetPtr());
93
if (unlikely(constraint == nullptr)) {
94
return;
95
}
96
97
JPH::SpringSettings settings = constraint->GetLimitsSpringSettings((JoltAxis)p_axis);
98
99
settings.mMode = JPH::ESpringMode::FrequencyAndDamping;
100
101
if (limit_spring_enabled[p_axis]) {
102
settings.mFrequency = (float)limit_spring_frequency[p_axis];
103
settings.mDamping = (float)limit_spring_damping[p_axis];
104
} else {
105
settings.mFrequency = 0.0f;
106
settings.mDamping = 0.0f;
107
}
108
109
constraint->SetLimitsSpringSettings((JoltAxis)p_axis, settings);
110
}
111
112
void JoltGeneric6DOFJoint3D::_update_motor_state(int p_axis) {
113
if (JPH::SixDOFConstraint *constraint = static_cast<JPH::SixDOFConstraint *>(jolt_ref.GetPtr())) {
114
if (motor_enabled[p_axis]) {
115
constraint->SetMotorState((JoltAxis)p_axis, JPH::EMotorState::Velocity);
116
} else if (spring_enabled[p_axis]) {
117
constraint->SetMotorState((JoltAxis)p_axis, JPH::EMotorState::Position);
118
} else {
119
constraint->SetMotorState((JoltAxis)p_axis, JPH::EMotorState::Off);
120
}
121
}
122
}
123
124
void JoltGeneric6DOFJoint3D::_update_motor_velocity(int p_axis) {
125
JPH::SixDOFConstraint *constraint = static_cast<JPH::SixDOFConstraint *>(jolt_ref.GetPtr());
126
if (unlikely(constraint == nullptr)) {
127
return;
128
}
129
130
if (p_axis >= AXIS_LINEAR_X && p_axis <= AXIS_LINEAR_Z) {
131
constraint->SetTargetVelocityCS(JPH::Vec3(
132
(float)motor_speed[AXIS_LINEAR_X],
133
(float)motor_speed[AXIS_LINEAR_Y],
134
(float)motor_speed[AXIS_LINEAR_Z]));
135
} else {
136
// We flip the direction since Jolt is CCW but Godot is CW.
137
constraint->SetTargetAngularVelocityCS(JPH::Vec3(
138
(float)-motor_speed[AXIS_ANGULAR_X],
139
(float)-motor_speed[AXIS_ANGULAR_Y],
140
(float)-motor_speed[AXIS_ANGULAR_Z]));
141
}
142
}
143
144
void JoltGeneric6DOFJoint3D::_update_motor_limit(int p_axis) {
145
JPH::SixDOFConstraint *constraint = static_cast<JPH::SixDOFConstraint *>(jolt_ref.GetPtr());
146
if (unlikely(constraint == nullptr)) {
147
return;
148
}
149
150
JPH::MotorSettings &motor_settings = constraint->GetMotorSettings((JoltAxis)p_axis);
151
152
float limit = FLT_MAX;
153
154
if (motor_enabled[p_axis]) {
155
limit = (float)motor_limit[p_axis];
156
} else if (spring_enabled[p_axis]) {
157
limit = (float)spring_limit[p_axis];
158
}
159
160
if (p_axis >= AXIS_LINEAR_X && p_axis <= AXIS_LINEAR_Z) {
161
motor_settings.SetForceLimit(limit);
162
} else {
163
motor_settings.SetTorqueLimit(limit);
164
}
165
}
166
167
void JoltGeneric6DOFJoint3D::_update_spring_parameters(int p_axis) {
168
JPH::SixDOFConstraint *constraint = static_cast<JPH::SixDOFConstraint *>(jolt_ref.GetPtr());
169
if (unlikely(constraint == nullptr)) {
170
return;
171
}
172
173
JPH::MotorSettings &motor_settings = constraint->GetMotorSettings((JoltAxis)p_axis);
174
175
if (spring_use_frequency[p_axis]) {
176
motor_settings.mSpringSettings.mMode = JPH::ESpringMode::FrequencyAndDamping;
177
motor_settings.mSpringSettings.mFrequency = (float)spring_frequency[p_axis];
178
} else {
179
motor_settings.mSpringSettings.mMode = JPH::ESpringMode::StiffnessAndDamping;
180
motor_settings.mSpringSettings.mStiffness = (float)spring_stiffness[p_axis];
181
}
182
183
motor_settings.mSpringSettings.mDamping = (float)spring_damping[p_axis];
184
}
185
186
void JoltGeneric6DOFJoint3D::_update_spring_equilibrium(int p_axis) {
187
JPH::SixDOFConstraint *constraint = static_cast<JPH::SixDOFConstraint *>(jolt_ref.GetPtr());
188
if (unlikely(constraint == nullptr)) {
189
return;
190
}
191
192
if (p_axis >= AXIS_LINEAR_X && p_axis <= AXIS_LINEAR_Z) {
193
const Vector3 target_position = Vector3(
194
(float)spring_equilibrium[AXIS_LINEAR_X],
195
(float)spring_equilibrium[AXIS_LINEAR_Y],
196
(float)spring_equilibrium[AXIS_LINEAR_Z]);
197
198
constraint->SetTargetPositionCS(to_jolt(target_position));
199
} else {
200
// We flip the direction since Jolt is CCW but Godot is CW.
201
const Basis target_orientation = Basis::from_euler(
202
Vector3((float)-spring_equilibrium[AXIS_ANGULAR_X],
203
(float)-spring_equilibrium[AXIS_ANGULAR_Y],
204
(float)-spring_equilibrium[AXIS_ANGULAR_Z]),
205
EulerOrder::ZYX);
206
207
constraint->SetTargetOrientationCS(to_jolt(target_orientation));
208
}
209
}
210
211
void JoltGeneric6DOFJoint3D::_limits_changed() {
212
rebuild();
213
_wake_up_bodies();
214
}
215
216
void JoltGeneric6DOFJoint3D::_limit_spring_parameters_changed(int p_axis) {
217
_update_limit_spring_parameters(p_axis);
218
_wake_up_bodies();
219
}
220
221
void JoltGeneric6DOFJoint3D::_motor_state_changed(int p_axis) {
222
_update_motor_state(p_axis);
223
_update_motor_limit(p_axis);
224
_wake_up_bodies();
225
}
226
227
void JoltGeneric6DOFJoint3D::_motor_speed_changed(int p_axis) {
228
_update_motor_velocity(p_axis);
229
_wake_up_bodies();
230
}
231
232
void JoltGeneric6DOFJoint3D::_motor_limit_changed(int p_axis) {
233
_update_motor_limit(p_axis);
234
_wake_up_bodies();
235
}
236
237
void JoltGeneric6DOFJoint3D::_spring_state_changed(int p_axis) {
238
_update_motor_state(p_axis);
239
_wake_up_bodies();
240
}
241
242
void JoltGeneric6DOFJoint3D::_spring_parameters_changed(int p_axis) {
243
_update_spring_parameters(p_axis);
244
_wake_up_bodies();
245
}
246
247
void JoltGeneric6DOFJoint3D::_spring_equilibrium_changed(int p_axis) {
248
_update_spring_equilibrium(p_axis);
249
_wake_up_bodies();
250
}
251
252
void JoltGeneric6DOFJoint3D::_spring_limit_changed(int p_axis) {
253
_update_motor_limit(p_axis);
254
_wake_up_bodies();
255
}
256
257
JoltGeneric6DOFJoint3D::JoltGeneric6DOFJoint3D(const JoltJoint3D &p_old_joint, JoltBody3D *p_body_a, JoltBody3D *p_body_b, const Transform3D &p_local_ref_a, const Transform3D &p_local_ref_b) :
258
JoltJoint3D(p_old_joint, p_body_a, p_body_b, p_local_ref_a, p_local_ref_b) {
259
rebuild();
260
}
261
262
double JoltGeneric6DOFJoint3D::get_param(Axis p_axis, Param p_param) const {
263
const int axis_lin = AXES_LINEAR + (int)p_axis;
264
const int axis_ang = AXES_ANGULAR + (int)p_axis;
265
266
switch ((int)p_param) {
267
case PhysicsServer3D::G6DOF_JOINT_LINEAR_LOWER_LIMIT: {
268
return limit_lower[axis_lin];
269
}
270
case PhysicsServer3D::G6DOF_JOINT_LINEAR_UPPER_LIMIT: {
271
return limit_upper[axis_lin];
272
}
273
case PhysicsServer3D::G6DOF_JOINT_LINEAR_LIMIT_SOFTNESS: {
274
return G6DOF_DEFAULT_LINEAR_LIMIT_SOFTNESS;
275
}
276
case PhysicsServer3D::G6DOF_JOINT_LINEAR_RESTITUTION: {
277
return G6DOF_DEFAULT_LINEAR_RESTITUTION;
278
}
279
case PhysicsServer3D::G6DOF_JOINT_LINEAR_DAMPING: {
280
return G6DOF_DEFAULT_LINEAR_DAMPING;
281
}
282
case PhysicsServer3D::G6DOF_JOINT_LINEAR_MOTOR_TARGET_VELOCITY: {
283
return motor_speed[axis_lin];
284
}
285
case PhysicsServer3D::G6DOF_JOINT_LINEAR_MOTOR_FORCE_LIMIT: {
286
return motor_limit[axis_lin];
287
}
288
case JoltPhysicsServer3D::G6DOF_JOINT_LINEAR_SPRING_STIFFNESS: {
289
return spring_stiffness[axis_lin];
290
}
291
case JoltPhysicsServer3D::G6DOF_JOINT_LINEAR_SPRING_DAMPING: {
292
return spring_damping[axis_lin];
293
}
294
case JoltPhysicsServer3D::G6DOF_JOINT_LINEAR_SPRING_EQUILIBRIUM_POINT: {
295
return spring_equilibrium[axis_lin];
296
}
297
case PhysicsServer3D::G6DOF_JOINT_ANGULAR_LOWER_LIMIT: {
298
return limit_lower[axis_ang];
299
}
300
case PhysicsServer3D::G6DOF_JOINT_ANGULAR_UPPER_LIMIT: {
301
return limit_upper[axis_ang];
302
}
303
case PhysicsServer3D::G6DOF_JOINT_ANGULAR_LIMIT_SOFTNESS: {
304
return G6DOF_DEFAULT_ANGULAR_LIMIT_SOFTNESS;
305
}
306
case PhysicsServer3D::G6DOF_JOINT_ANGULAR_DAMPING: {
307
return G6DOF_DEFAULT_ANGULAR_DAMPING;
308
}
309
case PhysicsServer3D::G6DOF_JOINT_ANGULAR_RESTITUTION: {
310
return G6DOF_DEFAULT_ANGULAR_RESTITUTION;
311
}
312
case PhysicsServer3D::G6DOF_JOINT_ANGULAR_FORCE_LIMIT: {
313
return G6DOF_DEFAULT_ANGULAR_FORCE_LIMIT;
314
}
315
case PhysicsServer3D::G6DOF_JOINT_ANGULAR_ERP: {
316
return G6DOF_DEFAULT_ANGULAR_ERP;
317
}
318
case PhysicsServer3D::G6DOF_JOINT_ANGULAR_MOTOR_TARGET_VELOCITY: {
319
return motor_speed[axis_ang];
320
}
321
case PhysicsServer3D::G6DOF_JOINT_ANGULAR_MOTOR_FORCE_LIMIT: {
322
return motor_limit[axis_ang];
323
}
324
case JoltPhysicsServer3D::G6DOF_JOINT_ANGULAR_SPRING_STIFFNESS: {
325
return spring_stiffness[axis_ang];
326
}
327
case JoltPhysicsServer3D::G6DOF_JOINT_ANGULAR_SPRING_DAMPING: {
328
return spring_damping[axis_ang];
329
}
330
case JoltPhysicsServer3D::G6DOF_JOINT_ANGULAR_SPRING_EQUILIBRIUM_POINT: {
331
return spring_equilibrium[axis_ang];
332
}
333
default: {
334
ERR_FAIL_V_MSG(0.0, vformat("Unhandled parameter: '%d'. This should not happen. Please report this.", p_param));
335
}
336
}
337
}
338
339
void JoltGeneric6DOFJoint3D::set_param(Axis p_axis, Param p_param, double p_value) {
340
const int axis_lin = AXES_LINEAR + (int)p_axis;
341
const int axis_ang = AXES_ANGULAR + (int)p_axis;
342
343
switch ((int)p_param) {
344
case PhysicsServer3D::G6DOF_JOINT_LINEAR_LOWER_LIMIT: {
345
limit_lower[axis_lin] = p_value;
346
_limits_changed();
347
} break;
348
case PhysicsServer3D::G6DOF_JOINT_LINEAR_UPPER_LIMIT: {
349
limit_upper[axis_lin] = p_value;
350
_limits_changed();
351
} break;
352
case PhysicsServer3D::G6DOF_JOINT_LINEAR_LIMIT_SOFTNESS: {
353
if (!Math::is_equal_approx(p_value, G6DOF_DEFAULT_LINEAR_LIMIT_SOFTNESS)) {
354
WARN_PRINT(vformat("6DOF joint linear limit softness is not supported when using Jolt Physics. Any such value will be ignored. This joint connects %s.", _bodies_to_string()));
355
}
356
} break;
357
case PhysicsServer3D::G6DOF_JOINT_LINEAR_RESTITUTION: {
358
if (!Math::is_equal_approx(p_value, G6DOF_DEFAULT_LINEAR_RESTITUTION)) {
359
WARN_PRINT(vformat("6DOF joint linear restitution is not supported when using Jolt Physics. Any such value will be ignored. This joint connects %s.", _bodies_to_string()));
360
}
361
} break;
362
case PhysicsServer3D::G6DOF_JOINT_LINEAR_DAMPING: {
363
if (!Math::is_equal_approx(p_value, G6DOF_DEFAULT_LINEAR_DAMPING)) {
364
WARN_PRINT(vformat("6DOF joint linear damping is not supported when using Jolt Physics. Any such value will be ignored. This joint connects %s.", _bodies_to_string()));
365
}
366
} break;
367
case PhysicsServer3D::G6DOF_JOINT_LINEAR_MOTOR_TARGET_VELOCITY: {
368
motor_speed[axis_lin] = p_value;
369
_motor_speed_changed(axis_lin);
370
} break;
371
case PhysicsServer3D::G6DOF_JOINT_LINEAR_MOTOR_FORCE_LIMIT: {
372
motor_limit[axis_lin] = p_value;
373
_motor_limit_changed(axis_lin);
374
} break;
375
case JoltPhysicsServer3D::G6DOF_JOINT_LINEAR_SPRING_STIFFNESS: {
376
spring_stiffness[axis_lin] = p_value;
377
_spring_parameters_changed(axis_lin);
378
} break;
379
case JoltPhysicsServer3D::G6DOF_JOINT_LINEAR_SPRING_DAMPING: {
380
spring_damping[axis_lin] = p_value;
381
_spring_parameters_changed(axis_lin);
382
} break;
383
case JoltPhysicsServer3D::G6DOF_JOINT_LINEAR_SPRING_EQUILIBRIUM_POINT: {
384
spring_equilibrium[axis_lin] = p_value;
385
_spring_equilibrium_changed(axis_lin);
386
} break;
387
case PhysicsServer3D::G6DOF_JOINT_ANGULAR_LOWER_LIMIT: {
388
limit_lower[axis_ang] = p_value;
389
_limits_changed();
390
} break;
391
case PhysicsServer3D::G6DOF_JOINT_ANGULAR_UPPER_LIMIT: {
392
limit_upper[axis_ang] = p_value;
393
_limits_changed();
394
} break;
395
case PhysicsServer3D::G6DOF_JOINT_ANGULAR_LIMIT_SOFTNESS: {
396
if (!Math::is_equal_approx(p_value, G6DOF_DEFAULT_ANGULAR_LIMIT_SOFTNESS)) {
397
WARN_PRINT(vformat("6DOF joint angular limit softness is not supported when using Jolt Physics. Any such value will be ignored. This joint connects %s.", _bodies_to_string()));
398
}
399
} break;
400
case PhysicsServer3D::G6DOF_JOINT_ANGULAR_DAMPING: {
401
if (!Math::is_equal_approx(p_value, G6DOF_DEFAULT_ANGULAR_DAMPING)) {
402
WARN_PRINT(vformat("6DOF joint angular damping is not supported when using Jolt Physics. Any such value will be ignored. This joint connects %s.", _bodies_to_string()));
403
}
404
} break;
405
case PhysicsServer3D::G6DOF_JOINT_ANGULAR_RESTITUTION: {
406
if (!Math::is_equal_approx(p_value, G6DOF_DEFAULT_ANGULAR_RESTITUTION)) {
407
WARN_PRINT(vformat("6DOF joint angular restitution is not supported when using Jolt Physics. Any such value will be ignored. This joint connects %s.", _bodies_to_string()));
408
}
409
} break;
410
case PhysicsServer3D::G6DOF_JOINT_ANGULAR_FORCE_LIMIT: {
411
if (!Math::is_equal_approx(p_value, G6DOF_DEFAULT_ANGULAR_FORCE_LIMIT)) {
412
WARN_PRINT(vformat("6DOF joint angular force limit is not supported when using Jolt Physics. Any such value will be ignored. This joint connects %s.", _bodies_to_string()));
413
}
414
} break;
415
case PhysicsServer3D::G6DOF_JOINT_ANGULAR_ERP: {
416
if (!Math::is_equal_approx(p_value, G6DOF_DEFAULT_ANGULAR_ERP)) {
417
WARN_PRINT(vformat("6DOF joint angular ERP is not supported when using Jolt Physics. Any such value will be ignored. This joint connects %s.", _bodies_to_string()));
418
}
419
} break;
420
case PhysicsServer3D::G6DOF_JOINT_ANGULAR_MOTOR_TARGET_VELOCITY: {
421
motor_speed[axis_ang] = p_value;
422
_motor_speed_changed(axis_ang);
423
} break;
424
case PhysicsServer3D::G6DOF_JOINT_ANGULAR_MOTOR_FORCE_LIMIT: {
425
motor_limit[axis_ang] = p_value;
426
_motor_limit_changed(axis_ang);
427
} break;
428
case JoltPhysicsServer3D::G6DOF_JOINT_ANGULAR_SPRING_STIFFNESS: {
429
spring_stiffness[axis_ang] = p_value;
430
_spring_parameters_changed(axis_ang);
431
} break;
432
case JoltPhysicsServer3D::G6DOF_JOINT_ANGULAR_SPRING_DAMPING: {
433
spring_damping[axis_ang] = p_value;
434
_spring_parameters_changed(axis_ang);
435
} break;
436
case JoltPhysicsServer3D::G6DOF_JOINT_ANGULAR_SPRING_EQUILIBRIUM_POINT: {
437
spring_equilibrium[axis_ang] = p_value;
438
_spring_equilibrium_changed(axis_ang);
439
} break;
440
default: {
441
ERR_FAIL_MSG(vformat("Unhandled parameter: '%d'. This should not happen. Please report this.", p_param));
442
} break;
443
}
444
}
445
446
bool JoltGeneric6DOFJoint3D::get_flag(Axis p_axis, Flag p_flag) const {
447
const int axis_lin = AXES_LINEAR + (int)p_axis;
448
const int axis_ang = AXES_ANGULAR + (int)p_axis;
449
450
switch ((int)p_flag) {
451
case PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_LINEAR_LIMIT: {
452
return limit_enabled[axis_lin];
453
}
454
case PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT: {
455
return limit_enabled[axis_ang];
456
}
457
case JoltPhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_SPRING: {
458
return spring_enabled[axis_ang];
459
}
460
case JoltPhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_LINEAR_SPRING: {
461
return spring_enabled[axis_lin];
462
}
463
case PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_MOTOR: {
464
return motor_enabled[axis_ang];
465
}
466
case PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_LINEAR_MOTOR: {
467
return motor_enabled[axis_lin];
468
}
469
default: {
470
ERR_FAIL_V_MSG(false, vformat("Unhandled flag: '%d'. This should not happen. Please report this.", p_flag));
471
}
472
}
473
}
474
475
void JoltGeneric6DOFJoint3D::set_flag(Axis p_axis, Flag p_flag, bool p_enabled) {
476
const int axis_lin = AXES_LINEAR + (int)p_axis;
477
const int axis_ang = AXES_ANGULAR + (int)p_axis;
478
479
switch ((int)p_flag) {
480
case PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_LINEAR_LIMIT: {
481
limit_enabled[axis_lin] = p_enabled;
482
_limits_changed();
483
} break;
484
case PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT: {
485
limit_enabled[axis_ang] = p_enabled;
486
_limits_changed();
487
} break;
488
case JoltPhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_SPRING: {
489
spring_enabled[axis_ang] = p_enabled;
490
_spring_state_changed(axis_ang);
491
} break;
492
case JoltPhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_LINEAR_SPRING: {
493
spring_enabled[axis_lin] = p_enabled;
494
_spring_state_changed(axis_lin);
495
} break;
496
case PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_MOTOR: {
497
motor_enabled[axis_ang] = p_enabled;
498
_motor_state_changed(axis_ang);
499
} break;
500
case PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_LINEAR_MOTOR: {
501
motor_enabled[axis_lin] = p_enabled;
502
_motor_state_changed(axis_lin);
503
} break;
504
default: {
505
ERR_FAIL_MSG(vformat("Unhandled flag: '%d'. This should not happen. Please report this.", p_flag));
506
} break;
507
}
508
}
509
510
double JoltGeneric6DOFJoint3D::get_jolt_param(Axis p_axis, JoltParam p_param) const {
511
const int axis_lin = AXES_LINEAR + (int)p_axis;
512
const int axis_ang = AXES_ANGULAR + (int)p_axis;
513
514
switch ((int)p_param) {
515
case JoltPhysicsServer3D::G6DOF_JOINT_LINEAR_SPRING_FREQUENCY: {
516
return spring_frequency[axis_lin];
517
}
518
case JoltPhysicsServer3D::G6DOF_JOINT_LINEAR_SPRING_MAX_FORCE: {
519
return spring_limit[axis_lin];
520
}
521
case JoltPhysicsServer3D::G6DOF_JOINT_LINEAR_LIMIT_SPRING_FREQUENCY: {
522
return limit_spring_frequency[axis_lin];
523
}
524
case JoltPhysicsServer3D::G6DOF_JOINT_LINEAR_LIMIT_SPRING_DAMPING: {
525
return limit_spring_damping[axis_lin];
526
}
527
case JoltPhysicsServer3D::G6DOF_JOINT_ANGULAR_SPRING_FREQUENCY: {
528
return spring_frequency[axis_ang];
529
}
530
case JoltPhysicsServer3D::G6DOF_JOINT_ANGULAR_SPRING_MAX_TORQUE: {
531
return spring_limit[axis_ang];
532
}
533
default: {
534
ERR_FAIL_V_MSG(0.0, vformat("Unhandled parameter: '%d'. This should not happen. Please report this.", p_param));
535
}
536
}
537
}
538
539
void JoltGeneric6DOFJoint3D::set_jolt_param(Axis p_axis, JoltParam p_param, double p_value) {
540
const int axis_lin = AXES_LINEAR + (int)p_axis;
541
const int axis_ang = AXES_ANGULAR + (int)p_axis;
542
543
switch ((int)p_param) {
544
case JoltPhysicsServer3D::G6DOF_JOINT_LINEAR_SPRING_FREQUENCY: {
545
spring_frequency[axis_lin] = p_value;
546
_spring_parameters_changed(axis_lin);
547
} break;
548
case JoltPhysicsServer3D::G6DOF_JOINT_LINEAR_SPRING_MAX_FORCE: {
549
spring_limit[axis_lin] = p_value;
550
_spring_limit_changed(axis_lin);
551
} break;
552
case JoltPhysicsServer3D::G6DOF_JOINT_LINEAR_LIMIT_SPRING_FREQUENCY: {
553
limit_spring_frequency[axis_lin] = p_value;
554
_limit_spring_parameters_changed(axis_lin);
555
} break;
556
case JoltPhysicsServer3D::G6DOF_JOINT_LINEAR_LIMIT_SPRING_DAMPING: {
557
limit_spring_damping[axis_lin] = p_value;
558
_limit_spring_parameters_changed(axis_lin);
559
} break;
560
case JoltPhysicsServer3D::G6DOF_JOINT_ANGULAR_SPRING_FREQUENCY: {
561
spring_frequency[axis_ang] = p_value;
562
_spring_parameters_changed(axis_ang);
563
} break;
564
case JoltPhysicsServer3D::G6DOF_JOINT_ANGULAR_SPRING_MAX_TORQUE: {
565
spring_limit[axis_ang] = p_value;
566
_spring_limit_changed(axis_ang);
567
} break;
568
default: {
569
ERR_FAIL_MSG(vformat("Unhandled parameter: '%d'. This should not happen. Please report this.", p_param));
570
} break;
571
}
572
}
573
574
bool JoltGeneric6DOFJoint3D::get_jolt_flag(Axis p_axis, JoltFlag p_flag) const {
575
const int axis_lin = AXES_LINEAR + (int)p_axis;
576
const int axis_ang = AXES_ANGULAR + (int)p_axis;
577
578
switch ((int)p_flag) {
579
case JoltPhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_LINEAR_LIMIT_SPRING: {
580
return limit_spring_enabled[axis_lin];
581
}
582
case JoltPhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_LINEAR_SPRING_FREQUENCY: {
583
return spring_use_frequency[axis_lin];
584
}
585
case JoltPhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_SPRING_FREQUENCY: {
586
return spring_use_frequency[axis_ang];
587
}
588
default: {
589
ERR_FAIL_V_MSG(false, vformat("Unhandled flag: '%d'. This should not happen. Please report this.", p_flag));
590
}
591
}
592
}
593
594
void JoltGeneric6DOFJoint3D::set_jolt_flag(Axis p_axis, JoltFlag p_flag, bool p_enabled) {
595
const int axis_lin = AXES_LINEAR + (int)p_axis;
596
const int axis_ang = AXES_ANGULAR + (int)p_axis;
597
598
switch ((int)p_flag) {
599
case JoltPhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_LINEAR_LIMIT_SPRING: {
600
limit_spring_enabled[axis_lin] = p_enabled;
601
_limit_spring_parameters_changed(axis_lin);
602
} break;
603
case JoltPhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_LINEAR_SPRING_FREQUENCY: {
604
spring_use_frequency[axis_lin] = p_enabled;
605
_spring_parameters_changed(axis_lin);
606
} break;
607
case JoltPhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_SPRING_FREQUENCY: {
608
spring_use_frequency[axis_ang] = p_enabled;
609
_spring_parameters_changed(axis_ang);
610
} break;
611
default: {
612
ERR_FAIL_MSG(vformat("Unhandled flag: '%d'. This should not happen. Please report this.", p_flag));
613
} break;
614
}
615
}
616
617
float JoltGeneric6DOFJoint3D::get_applied_force() const {
618
JPH::SixDOFConstraint *constraint = static_cast<JPH::SixDOFConstraint *>(jolt_ref.GetPtr());
619
ERR_FAIL_NULL_V(constraint, 0.0f);
620
621
JoltSpace3D *space = get_space();
622
ERR_FAIL_NULL_V(space, 0.0f);
623
624
const float last_step = space->get_last_step();
625
if (unlikely(last_step == 0.0f)) {
626
return 0.0f;
627
}
628
629
const JPH::Vec3 total_lambda = constraint->GetTotalLambdaPosition() + constraint->GetTotalLambdaMotorTranslation();
630
631
return total_lambda.Length() / last_step;
632
}
633
634
float JoltGeneric6DOFJoint3D::get_applied_torque() const {
635
JPH::SixDOFConstraint *constraint = static_cast<JPH::SixDOFConstraint *>(jolt_ref.GetPtr());
636
ERR_FAIL_NULL_V(constraint, 0.0f);
637
638
JoltSpace3D *space = get_space();
639
ERR_FAIL_NULL_V(space, 0.0f);
640
641
const float last_step = space->get_last_step();
642
if (unlikely(last_step == 0.0f)) {
643
return 0.0f;
644
}
645
646
const JPH::Vec3 total_lambda = constraint->GetTotalLambdaRotation() + constraint->GetTotalLambdaMotorRotation();
647
648
return total_lambda.Length() / last_step;
649
}
650
651
void JoltGeneric6DOFJoint3D::rebuild() {
652
destroy();
653
654
JoltSpace3D *space = get_space();
655
if (space == nullptr) {
656
return;
657
}
658
659
JPH::Body *jolt_body_a = body_a != nullptr ? body_a->get_jolt_body() : nullptr;
660
JPH::Body *jolt_body_b = body_b != nullptr ? body_b->get_jolt_body() : nullptr;
661
ERR_FAIL_COND(jolt_body_a == nullptr && jolt_body_b == nullptr);
662
663
Transform3D shifted_ref_a;
664
Transform3D shifted_ref_b;
665
666
_shift_reference_frames(Vector3(), Vector3(), shifted_ref_a, shifted_ref_b);
667
668
jolt_ref = _build_6dof(jolt_body_a, jolt_body_b, shifted_ref_a, shifted_ref_b);
669
670
space->add_joint(this);
671
672
_update_enabled();
673
_update_iterations();
674
675
_update_limit_spring_parameters(AXIS_LINEAR_X);
676
_update_limit_spring_parameters(AXIS_LINEAR_Y);
677
_update_limit_spring_parameters(AXIS_LINEAR_Z);
678
679
for (int axis = 0; axis < AXIS_COUNT; ++axis) {
680
_update_motor_state(axis);
681
_update_motor_velocity(axis);
682
_update_motor_limit(axis);
683
_update_spring_parameters(axis);
684
_update_spring_equilibrium(axis);
685
}
686
}
687
688