Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/jolt_physics/Jolt/Physics/Body/BodyInterface.cpp
9912 views
1
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
2
// SPDX-FileCopyrightText: 2021 Jorrit Rouwe
3
// SPDX-License-Identifier: MIT
4
5
#include <Jolt/Jolt.h>
6
7
#include <Jolt/Physics/Body/BodyInterface.h>
8
#include <Jolt/Physics/Collision/BroadPhase/BroadPhase.h>
9
#include <Jolt/Physics/Collision/CollisionCollectorImpl.h>
10
#include <Jolt/Physics/Body/Body.h>
11
#include <Jolt/Physics/Body/BodyManager.h>
12
#include <Jolt/Physics/Body/BodyCreationSettings.h>
13
#include <Jolt/Physics/Body/BodyLock.h>
14
#include <Jolt/Physics/Body/BodyLockMulti.h>
15
#include <Jolt/Physics/Collision/PhysicsMaterial.h>
16
#include <Jolt/Physics/Constraints/TwoBodyConstraint.h>
17
18
JPH_NAMESPACE_BEGIN
19
20
void BodyInterface::ActivateBodyInternal(Body &ioBody) const
21
{
22
// Activate body or reset its sleep timer.
23
// Note that BodyManager::ActivateBodies also resets the sleep timer internally, but we avoid a mutex lock if the body is already active by calling ResetSleepTimer directly.
24
if (!ioBody.IsActive())
25
mBodyManager->ActivateBodies(&ioBody.GetID(), 1);
26
else
27
ioBody.ResetSleepTimer();
28
}
29
30
Body *BodyInterface::CreateBody(const BodyCreationSettings &inSettings)
31
{
32
Body *body = mBodyManager->AllocateBody(inSettings);
33
if (!mBodyManager->AddBody(body))
34
{
35
mBodyManager->FreeBody(body);
36
return nullptr;
37
}
38
return body;
39
}
40
41
Body *BodyInterface::CreateSoftBody(const SoftBodyCreationSettings &inSettings)
42
{
43
Body *body = mBodyManager->AllocateSoftBody(inSettings);
44
if (!mBodyManager->AddBody(body))
45
{
46
mBodyManager->FreeBody(body);
47
return nullptr;
48
}
49
return body;
50
}
51
52
Body *BodyInterface::CreateBodyWithID(const BodyID &inBodyID, const BodyCreationSettings &inSettings)
53
{
54
Body *body = mBodyManager->AllocateBody(inSettings);
55
if (!mBodyManager->AddBodyWithCustomID(body, inBodyID))
56
{
57
mBodyManager->FreeBody(body);
58
return nullptr;
59
}
60
return body;
61
}
62
63
Body *BodyInterface::CreateSoftBodyWithID(const BodyID &inBodyID, const SoftBodyCreationSettings &inSettings)
64
{
65
Body *body = mBodyManager->AllocateSoftBody(inSettings);
66
if (!mBodyManager->AddBodyWithCustomID(body, inBodyID))
67
{
68
mBodyManager->FreeBody(body);
69
return nullptr;
70
}
71
return body;
72
}
73
74
Body *BodyInterface::CreateBodyWithoutID(const BodyCreationSettings &inSettings) const
75
{
76
return mBodyManager->AllocateBody(inSettings);
77
}
78
79
Body *BodyInterface::CreateSoftBodyWithoutID(const SoftBodyCreationSettings &inSettings) const
80
{
81
return mBodyManager->AllocateSoftBody(inSettings);
82
}
83
84
void BodyInterface::DestroyBodyWithoutID(Body *inBody) const
85
{
86
mBodyManager->FreeBody(inBody);
87
}
88
89
bool BodyInterface::AssignBodyID(Body *ioBody)
90
{
91
return mBodyManager->AddBody(ioBody);
92
}
93
94
bool BodyInterface::AssignBodyID(Body *ioBody, const BodyID &inBodyID)
95
{
96
return mBodyManager->AddBodyWithCustomID(ioBody, inBodyID);
97
}
98
99
Body *BodyInterface::UnassignBodyID(const BodyID &inBodyID)
100
{
101
Body *body = nullptr;
102
mBodyManager->RemoveBodies(&inBodyID, 1, &body);
103
return body;
104
}
105
106
void BodyInterface::UnassignBodyIDs(const BodyID *inBodyIDs, int inNumber, Body **outBodies)
107
{
108
mBodyManager->RemoveBodies(inBodyIDs, inNumber, outBodies);
109
}
110
111
void BodyInterface::DestroyBody(const BodyID &inBodyID)
112
{
113
mBodyManager->DestroyBodies(&inBodyID, 1);
114
}
115
116
void BodyInterface::DestroyBodies(const BodyID *inBodyIDs, int inNumber)
117
{
118
mBodyManager->DestroyBodies(inBodyIDs, inNumber);
119
}
120
121
void BodyInterface::AddBody(const BodyID &inBodyID, EActivation inActivationMode)
122
{
123
BodyLockWrite lock(*mBodyLockInterface, inBodyID);
124
if (lock.Succeeded())
125
{
126
const Body &body = lock.GetBody();
127
128
// Add to broadphase
129
BodyID id = inBodyID;
130
BroadPhase::AddState add_state = mBroadPhase->AddBodiesPrepare(&id, 1);
131
mBroadPhase->AddBodiesFinalize(&id, 1, add_state);
132
133
// Optionally activate body
134
if (inActivationMode == EActivation::Activate && !body.IsStatic())
135
mBodyManager->ActivateBodies(&inBodyID, 1);
136
}
137
}
138
139
void BodyInterface::RemoveBody(const BodyID &inBodyID)
140
{
141
BodyLockWrite lock(*mBodyLockInterface, inBodyID);
142
if (lock.Succeeded())
143
{
144
const Body &body = lock.GetBody();
145
146
// Deactivate body
147
if (body.IsActive())
148
mBodyManager->DeactivateBodies(&inBodyID, 1);
149
150
// Remove from broadphase
151
BodyID id = inBodyID;
152
mBroadPhase->RemoveBodies(&id, 1);
153
}
154
}
155
156
bool BodyInterface::IsAdded(const BodyID &inBodyID) const
157
{
158
BodyLockRead lock(*mBodyLockInterface, inBodyID);
159
return lock.SucceededAndIsInBroadPhase();
160
}
161
162
BodyID BodyInterface::CreateAndAddBody(const BodyCreationSettings &inSettings, EActivation inActivationMode)
163
{
164
const Body *b = CreateBody(inSettings);
165
if (b == nullptr)
166
return BodyID(); // Out of bodies
167
AddBody(b->GetID(), inActivationMode);
168
return b->GetID();
169
}
170
171
BodyID BodyInterface::CreateAndAddSoftBody(const SoftBodyCreationSettings &inSettings, EActivation inActivationMode)
172
{
173
const Body *b = CreateSoftBody(inSettings);
174
if (b == nullptr)
175
return BodyID(); // Out of bodies
176
AddBody(b->GetID(), inActivationMode);
177
return b->GetID();
178
}
179
180
BodyInterface::AddState BodyInterface::AddBodiesPrepare(BodyID *ioBodies, int inNumber)
181
{
182
return mBroadPhase->AddBodiesPrepare(ioBodies, inNumber);
183
}
184
185
void BodyInterface::AddBodiesFinalize(BodyID *ioBodies, int inNumber, AddState inAddState, EActivation inActivationMode)
186
{
187
BodyLockMultiWrite lock(*mBodyLockInterface, ioBodies, inNumber);
188
189
// Add to broadphase
190
mBroadPhase->AddBodiesFinalize(ioBodies, inNumber, inAddState);
191
192
// Optionally activate bodies
193
if (inActivationMode == EActivation::Activate)
194
mBodyManager->ActivateBodies(ioBodies, inNumber);
195
}
196
197
void BodyInterface::AddBodiesAbort(BodyID *ioBodies, int inNumber, AddState inAddState)
198
{
199
mBroadPhase->AddBodiesAbort(ioBodies, inNumber, inAddState);
200
}
201
202
void BodyInterface::RemoveBodies(BodyID *ioBodies, int inNumber)
203
{
204
BodyLockMultiWrite lock(*mBodyLockInterface, ioBodies, inNumber);
205
206
// Deactivate bodies
207
mBodyManager->DeactivateBodies(ioBodies, inNumber);
208
209
// Remove from broadphase
210
mBroadPhase->RemoveBodies(ioBodies, inNumber);
211
}
212
213
void BodyInterface::ActivateBody(const BodyID &inBodyID)
214
{
215
BodyLockWrite lock(*mBodyLockInterface, inBodyID);
216
if (lock.Succeeded())
217
{
218
Body &body = lock.GetBody();
219
ActivateBodyInternal(body);
220
}
221
}
222
223
void BodyInterface::ActivateBodies(const BodyID *inBodyIDs, int inNumber)
224
{
225
BodyLockMultiWrite lock(*mBodyLockInterface, inBodyIDs, inNumber);
226
227
mBodyManager->ActivateBodies(inBodyIDs, inNumber);
228
}
229
230
void BodyInterface::ActivateBodiesInAABox(const AABox &inBox, const BroadPhaseLayerFilter &inBroadPhaseLayerFilter, const ObjectLayerFilter &inObjectLayerFilter)
231
{
232
AllHitCollisionCollector<CollideShapeBodyCollector> collector;
233
mBroadPhase->CollideAABox(inBox, collector, inBroadPhaseLayerFilter, inObjectLayerFilter);
234
ActivateBodies(collector.mHits.data(), (int)collector.mHits.size());
235
}
236
237
void BodyInterface::DeactivateBody(const BodyID &inBodyID)
238
{
239
BodyLockWrite lock(*mBodyLockInterface, inBodyID);
240
if (lock.Succeeded())
241
{
242
const Body &body = lock.GetBody();
243
244
if (body.IsActive())
245
mBodyManager->DeactivateBodies(&inBodyID, 1);
246
}
247
}
248
249
void BodyInterface::DeactivateBodies(const BodyID *inBodyIDs, int inNumber)
250
{
251
BodyLockMultiWrite lock(*mBodyLockInterface, inBodyIDs, inNumber);
252
253
mBodyManager->DeactivateBodies(inBodyIDs, inNumber);
254
}
255
256
bool BodyInterface::IsActive(const BodyID &inBodyID) const
257
{
258
BodyLockRead lock(*mBodyLockInterface, inBodyID);
259
return lock.Succeeded() && lock.GetBody().IsActive();
260
}
261
262
void BodyInterface::ResetSleepTimer(const BodyID &inBodyID)
263
{
264
BodyLockWrite lock(*mBodyLockInterface, inBodyID);
265
if (lock.Succeeded())
266
lock.GetBody().ResetSleepTimer();
267
}
268
269
TwoBodyConstraint *BodyInterface::CreateConstraint(const TwoBodyConstraintSettings *inSettings, const BodyID &inBodyID1, const BodyID &inBodyID2)
270
{
271
BodyID constraint_bodies[] = { inBodyID1, inBodyID2 };
272
BodyLockMultiWrite lock(*mBodyLockInterface, constraint_bodies, 2);
273
274
Body *body1 = lock.GetBody(0);
275
Body *body2 = lock.GetBody(1);
276
277
JPH_ASSERT(body1 != body2);
278
JPH_ASSERT(body1 != nullptr || body2 != nullptr);
279
280
return inSettings->Create(body1 != nullptr? *body1 : Body::sFixedToWorld, body2 != nullptr? *body2 : Body::sFixedToWorld);
281
}
282
283
void BodyInterface::ActivateConstraint(const TwoBodyConstraint *inConstraint)
284
{
285
BodyID bodies[] = { inConstraint->GetBody1()->GetID(), inConstraint->GetBody2()->GetID() };
286
ActivateBodies(bodies, 2);
287
}
288
289
RefConst<Shape> BodyInterface::GetShape(const BodyID &inBodyID) const
290
{
291
RefConst<Shape> shape;
292
BodyLockRead lock(*mBodyLockInterface, inBodyID);
293
if (lock.Succeeded())
294
shape = lock.GetBody().GetShape();
295
return shape;
296
}
297
298
void BodyInterface::SetShape(const BodyID &inBodyID, const Shape *inShape, bool inUpdateMassProperties, EActivation inActivationMode) const
299
{
300
BodyLockWrite lock(*mBodyLockInterface, inBodyID);
301
if (lock.Succeeded())
302
{
303
Body &body = lock.GetBody();
304
305
// Check if shape actually changed
306
if (body.GetShape() != inShape)
307
{
308
// Update the shape
309
body.SetShapeInternal(inShape, inUpdateMassProperties);
310
311
// Flag collision cache invalid for this body
312
mBodyManager->InvalidateContactCacheForBody(body);
313
314
// Notify broadphase of change
315
if (body.IsInBroadPhase())
316
{
317
BodyID id = body.GetID();
318
mBroadPhase->NotifyBodiesAABBChanged(&id, 1);
319
320
// Optionally activate body
321
if (inActivationMode == EActivation::Activate && !body.IsStatic())
322
ActivateBodyInternal(body);
323
}
324
}
325
}
326
}
327
328
void BodyInterface::NotifyShapeChanged(const BodyID &inBodyID, Vec3Arg inPreviousCenterOfMass, bool inUpdateMassProperties, EActivation inActivationMode) const
329
{
330
BodyLockWrite lock(*mBodyLockInterface, inBodyID);
331
if (lock.Succeeded())
332
{
333
Body &body = lock.GetBody();
334
335
// Update center of mass, mass and inertia
336
body.UpdateCenterOfMassInternal(inPreviousCenterOfMass, inUpdateMassProperties);
337
338
// Recalculate bounding box
339
body.CalculateWorldSpaceBoundsInternal();
340
341
// Flag collision cache invalid for this body
342
mBodyManager->InvalidateContactCacheForBody(body);
343
344
// Notify broadphase of change
345
if (body.IsInBroadPhase())
346
{
347
BodyID id = body.GetID();
348
mBroadPhase->NotifyBodiesAABBChanged(&id, 1);
349
350
// Optionally activate body
351
if (inActivationMode == EActivation::Activate && !body.IsStatic())
352
ActivateBodyInternal(body);
353
}
354
}
355
}
356
357
void BodyInterface::SetObjectLayer(const BodyID &inBodyID, ObjectLayer inLayer)
358
{
359
BodyLockWrite lock(*mBodyLockInterface, inBodyID);
360
if (lock.Succeeded())
361
{
362
Body &body = lock.GetBody();
363
364
// Check if layer actually changed, updating the broadphase is rather expensive
365
if (body.GetObjectLayer() != inLayer)
366
{
367
// Update the layer on the body
368
mBodyManager->SetBodyObjectLayerInternal(body, inLayer);
369
370
// Notify broadphase of change
371
if (body.IsInBroadPhase())
372
{
373
BodyID id = body.GetID();
374
mBroadPhase->NotifyBodiesLayerChanged(&id, 1);
375
}
376
}
377
}
378
}
379
380
ObjectLayer BodyInterface::GetObjectLayer(const BodyID &inBodyID) const
381
{
382
BodyLockRead lock(*mBodyLockInterface, inBodyID);
383
if (lock.Succeeded())
384
return lock.GetBody().GetObjectLayer();
385
else
386
return cObjectLayerInvalid;
387
}
388
389
void BodyInterface::SetPositionAndRotation(const BodyID &inBodyID, RVec3Arg inPosition, QuatArg inRotation, EActivation inActivationMode)
390
{
391
BodyLockWrite lock(*mBodyLockInterface, inBodyID);
392
if (lock.Succeeded())
393
{
394
Body &body = lock.GetBody();
395
396
// Update the position
397
body.SetPositionAndRotationInternal(inPosition, inRotation);
398
399
// Notify broadphase of change
400
if (body.IsInBroadPhase())
401
{
402
BodyID id = body.GetID();
403
mBroadPhase->NotifyBodiesAABBChanged(&id, 1);
404
405
// Optionally activate body
406
if (inActivationMode == EActivation::Activate && !body.IsStatic())
407
ActivateBodyInternal(body);
408
}
409
}
410
}
411
412
void BodyInterface::SetPositionAndRotationWhenChanged(const BodyID &inBodyID, RVec3Arg inPosition, QuatArg inRotation, EActivation inActivationMode)
413
{
414
BodyLockWrite lock(*mBodyLockInterface, inBodyID);
415
if (lock.Succeeded())
416
{
417
Body &body = lock.GetBody();
418
419
// Check if there is enough change
420
if (!body.GetPosition().IsClose(inPosition)
421
|| !body.GetRotation().IsClose(inRotation))
422
{
423
// Update the position
424
body.SetPositionAndRotationInternal(inPosition, inRotation);
425
426
// Notify broadphase of change
427
if (body.IsInBroadPhase())
428
{
429
BodyID id = body.GetID();
430
mBroadPhase->NotifyBodiesAABBChanged(&id, 1);
431
432
// Optionally activate body
433
if (inActivationMode == EActivation::Activate && !body.IsStatic())
434
ActivateBodyInternal(body);
435
}
436
}
437
}
438
}
439
440
void BodyInterface::GetPositionAndRotation(const BodyID &inBodyID, RVec3 &outPosition, Quat &outRotation) const
441
{
442
BodyLockRead lock(*mBodyLockInterface, inBodyID);
443
if (lock.Succeeded())
444
{
445
const Body &body = lock.GetBody();
446
outPosition = body.GetPosition();
447
outRotation = body.GetRotation();
448
}
449
else
450
{
451
outPosition = RVec3::sZero();
452
outRotation = Quat::sIdentity();
453
}
454
}
455
456
void BodyInterface::SetPosition(const BodyID &inBodyID, RVec3Arg inPosition, EActivation inActivationMode)
457
{
458
BodyLockWrite lock(*mBodyLockInterface, inBodyID);
459
if (lock.Succeeded())
460
{
461
Body &body = lock.GetBody();
462
463
// Update the position
464
body.SetPositionAndRotationInternal(inPosition, body.GetRotation());
465
466
// Notify broadphase of change
467
if (body.IsInBroadPhase())
468
{
469
BodyID id = body.GetID();
470
mBroadPhase->NotifyBodiesAABBChanged(&id, 1);
471
472
// Optionally activate body
473
if (inActivationMode == EActivation::Activate && !body.IsStatic())
474
ActivateBodyInternal(body);
475
}
476
}
477
}
478
479
RVec3 BodyInterface::GetPosition(const BodyID &inBodyID) const
480
{
481
BodyLockRead lock(*mBodyLockInterface, inBodyID);
482
if (lock.Succeeded())
483
return lock.GetBody().GetPosition();
484
else
485
return RVec3::sZero();
486
}
487
488
RVec3 BodyInterface::GetCenterOfMassPosition(const BodyID &inBodyID) const
489
{
490
BodyLockRead lock(*mBodyLockInterface, inBodyID);
491
if (lock.Succeeded())
492
return lock.GetBody().GetCenterOfMassPosition();
493
else
494
return RVec3::sZero();
495
}
496
497
void BodyInterface::SetRotation(const BodyID &inBodyID, QuatArg inRotation, EActivation inActivationMode)
498
{
499
BodyLockWrite lock(*mBodyLockInterface, inBodyID);
500
if (lock.Succeeded())
501
{
502
Body &body = lock.GetBody();
503
504
// Update the position
505
body.SetPositionAndRotationInternal(body.GetPosition(), inRotation);
506
507
// Notify broadphase of change
508
if (body.IsInBroadPhase())
509
{
510
BodyID id = body.GetID();
511
mBroadPhase->NotifyBodiesAABBChanged(&id, 1);
512
513
// Optionally activate body
514
if (inActivationMode == EActivation::Activate && !body.IsStatic())
515
ActivateBodyInternal(body);
516
}
517
}
518
}
519
520
Quat BodyInterface::GetRotation(const BodyID &inBodyID) const
521
{
522
BodyLockRead lock(*mBodyLockInterface, inBodyID);
523
if (lock.Succeeded())
524
return lock.GetBody().GetRotation();
525
else
526
return Quat::sIdentity();
527
}
528
529
RMat44 BodyInterface::GetWorldTransform(const BodyID &inBodyID) const
530
{
531
BodyLockRead lock(*mBodyLockInterface, inBodyID);
532
if (lock.Succeeded())
533
return lock.GetBody().GetWorldTransform();
534
else
535
return RMat44::sIdentity();
536
}
537
538
RMat44 BodyInterface::GetCenterOfMassTransform(const BodyID &inBodyID) const
539
{
540
BodyLockRead lock(*mBodyLockInterface, inBodyID);
541
if (lock.Succeeded())
542
return lock.GetBody().GetCenterOfMassTransform();
543
else
544
return RMat44::sIdentity();
545
}
546
547
void BodyInterface::MoveKinematic(const BodyID &inBodyID, RVec3Arg inTargetPosition, QuatArg inTargetRotation, float inDeltaTime)
548
{
549
BodyLockWrite lock(*mBodyLockInterface, inBodyID);
550
if (lock.Succeeded())
551
{
552
Body &body = lock.GetBody();
553
554
body.MoveKinematic(inTargetPosition, inTargetRotation, inDeltaTime);
555
556
if (!body.IsActive() && (!body.GetLinearVelocity().IsNearZero() || !body.GetAngularVelocity().IsNearZero()))
557
mBodyManager->ActivateBodies(&inBodyID, 1);
558
}
559
}
560
561
void BodyInterface::SetLinearAndAngularVelocity(const BodyID &inBodyID, Vec3Arg inLinearVelocity, Vec3Arg inAngularVelocity)
562
{
563
BodyLockWrite lock(*mBodyLockInterface, inBodyID);
564
if (lock.Succeeded())
565
{
566
Body &body = lock.GetBody();
567
if (!body.IsStatic())
568
{
569
body.SetLinearVelocityClamped(inLinearVelocity);
570
body.SetAngularVelocityClamped(inAngularVelocity);
571
572
if (!body.IsActive() && (!inLinearVelocity.IsNearZero() || !inAngularVelocity.IsNearZero()))
573
mBodyManager->ActivateBodies(&inBodyID, 1);
574
}
575
}
576
}
577
578
void BodyInterface::GetLinearAndAngularVelocity(const BodyID &inBodyID, Vec3 &outLinearVelocity, Vec3 &outAngularVelocity) const
579
{
580
BodyLockRead lock(*mBodyLockInterface, inBodyID);
581
if (lock.Succeeded())
582
{
583
const Body &body = lock.GetBody();
584
if (!body.IsStatic())
585
{
586
outLinearVelocity = body.GetLinearVelocity();
587
outAngularVelocity = body.GetAngularVelocity();
588
return;
589
}
590
}
591
592
outLinearVelocity = outAngularVelocity = Vec3::sZero();
593
}
594
595
void BodyInterface::SetLinearVelocity(const BodyID &inBodyID, Vec3Arg inLinearVelocity)
596
{
597
BodyLockWrite lock(*mBodyLockInterface, inBodyID);
598
if (lock.Succeeded())
599
{
600
Body &body = lock.GetBody();
601
if (!body.IsStatic())
602
{
603
body.SetLinearVelocityClamped(inLinearVelocity);
604
605
if (!body.IsActive() && !inLinearVelocity.IsNearZero())
606
mBodyManager->ActivateBodies(&inBodyID, 1);
607
}
608
}
609
}
610
611
Vec3 BodyInterface::GetLinearVelocity(const BodyID &inBodyID) const
612
{
613
BodyLockRead lock(*mBodyLockInterface, inBodyID);
614
if (lock.Succeeded())
615
{
616
const Body &body = lock.GetBody();
617
if (!body.IsStatic())
618
return body.GetLinearVelocity();
619
}
620
621
return Vec3::sZero();
622
}
623
624
void BodyInterface::AddLinearVelocity(const BodyID &inBodyID, Vec3Arg inLinearVelocity)
625
{
626
BodyLockWrite lock(*mBodyLockInterface, inBodyID);
627
if (lock.Succeeded())
628
{
629
Body &body = lock.GetBody();
630
if (!body.IsStatic())
631
{
632
body.SetLinearVelocityClamped(body.GetLinearVelocity() + inLinearVelocity);
633
634
if (!body.IsActive() && !body.GetLinearVelocity().IsNearZero())
635
mBodyManager->ActivateBodies(&inBodyID, 1);
636
}
637
}
638
}
639
640
void BodyInterface::AddLinearAndAngularVelocity(const BodyID &inBodyID, Vec3Arg inLinearVelocity, Vec3Arg inAngularVelocity)
641
{
642
BodyLockWrite lock(*mBodyLockInterface, inBodyID);
643
if (lock.Succeeded())
644
{
645
Body &body = lock.GetBody();
646
if (!body.IsStatic())
647
{
648
body.SetLinearVelocityClamped(body.GetLinearVelocity() + inLinearVelocity);
649
body.SetAngularVelocityClamped(body.GetAngularVelocity() + inAngularVelocity);
650
651
if (!body.IsActive() && (!body.GetLinearVelocity().IsNearZero() || !body.GetAngularVelocity().IsNearZero()))
652
mBodyManager->ActivateBodies(&inBodyID, 1);
653
}
654
}
655
}
656
657
void BodyInterface::SetAngularVelocity(const BodyID &inBodyID, Vec3Arg inAngularVelocity)
658
{
659
BodyLockWrite lock(*mBodyLockInterface, inBodyID);
660
if (lock.Succeeded())
661
{
662
Body &body = lock.GetBody();
663
if (!body.IsStatic())
664
{
665
body.SetAngularVelocityClamped(inAngularVelocity);
666
667
if (!body.IsActive() && !inAngularVelocity.IsNearZero())
668
mBodyManager->ActivateBodies(&inBodyID, 1);
669
}
670
}
671
}
672
673
Vec3 BodyInterface::GetAngularVelocity(const BodyID &inBodyID) const
674
{
675
BodyLockRead lock(*mBodyLockInterface, inBodyID);
676
if (lock.Succeeded())
677
{
678
const Body &body = lock.GetBody();
679
if (!body.IsStatic())
680
return body.GetAngularVelocity();
681
}
682
683
return Vec3::sZero();
684
}
685
686
Vec3 BodyInterface::GetPointVelocity(const BodyID &inBodyID, RVec3Arg inPoint) const
687
{
688
BodyLockRead lock(*mBodyLockInterface, inBodyID);
689
if (lock.Succeeded())
690
{
691
const Body &body = lock.GetBody();
692
if (!body.IsStatic())
693
return body.GetPointVelocity(inPoint);
694
}
695
696
return Vec3::sZero();
697
}
698
699
void BodyInterface::AddForce(const BodyID &inBodyID, Vec3Arg inForce, EActivation inActivationMode)
700
{
701
BodyLockWrite lock(*mBodyLockInterface, inBodyID);
702
if (lock.Succeeded())
703
{
704
Body &body = lock.GetBody();
705
if (body.IsDynamic() && (inActivationMode == EActivation::Activate || body.IsActive()))
706
{
707
body.AddForce(inForce);
708
709
if (inActivationMode == EActivation::Activate)
710
ActivateBodyInternal(body);
711
}
712
}
713
}
714
715
void BodyInterface::AddForce(const BodyID &inBodyID, Vec3Arg inForce, RVec3Arg inPoint, EActivation inActivationMode)
716
{
717
BodyLockWrite lock(*mBodyLockInterface, inBodyID);
718
if (lock.Succeeded())
719
{
720
Body &body = lock.GetBody();
721
if (body.IsDynamic() && (inActivationMode == EActivation::Activate || body.IsActive()))
722
{
723
body.AddForce(inForce, inPoint);
724
725
if (inActivationMode == EActivation::Activate)
726
ActivateBodyInternal(body);
727
}
728
}
729
}
730
731
void BodyInterface::AddTorque(const BodyID &inBodyID, Vec3Arg inTorque, EActivation inActivationMode)
732
{
733
BodyLockWrite lock(*mBodyLockInterface, inBodyID);
734
if (lock.Succeeded())
735
{
736
Body &body = lock.GetBody();
737
if (body.IsDynamic() && (inActivationMode == EActivation::Activate || body.IsActive()))
738
{
739
body.AddTorque(inTorque);
740
741
if (inActivationMode == EActivation::Activate)
742
ActivateBodyInternal(body);
743
}
744
}
745
}
746
747
void BodyInterface::AddForceAndTorque(const BodyID &inBodyID, Vec3Arg inForce, Vec3Arg inTorque, EActivation inActivationMode)
748
{
749
BodyLockWrite lock(*mBodyLockInterface, inBodyID);
750
if (lock.Succeeded())
751
{
752
Body &body = lock.GetBody();
753
if (body.IsDynamic() && (inActivationMode == EActivation::Activate || body.IsActive()))
754
{
755
body.AddForce(inForce);
756
body.AddTorque(inTorque);
757
758
if (inActivationMode == EActivation::Activate)
759
ActivateBodyInternal(body);
760
}
761
}
762
}
763
764
void BodyInterface::AddImpulse(const BodyID &inBodyID, Vec3Arg inImpulse)
765
{
766
BodyLockWrite lock(*mBodyLockInterface, inBodyID);
767
if (lock.Succeeded())
768
{
769
Body &body = lock.GetBody();
770
if (body.IsDynamic())
771
{
772
body.AddImpulse(inImpulse);
773
774
if (!body.IsActive())
775
mBodyManager->ActivateBodies(&inBodyID, 1);
776
}
777
}
778
}
779
780
void BodyInterface::AddImpulse(const BodyID &inBodyID, Vec3Arg inImpulse, RVec3Arg inPoint)
781
{
782
BodyLockWrite lock(*mBodyLockInterface, inBodyID);
783
if (lock.Succeeded())
784
{
785
Body &body = lock.GetBody();
786
if (body.IsDynamic())
787
{
788
body.AddImpulse(inImpulse, inPoint);
789
790
if (!body.IsActive())
791
mBodyManager->ActivateBodies(&inBodyID, 1);
792
}
793
}
794
}
795
796
void BodyInterface::AddAngularImpulse(const BodyID &inBodyID, Vec3Arg inAngularImpulse)
797
{
798
BodyLockWrite lock(*mBodyLockInterface, inBodyID);
799
if (lock.Succeeded())
800
{
801
Body &body = lock.GetBody();
802
if (body.IsDynamic())
803
{
804
body.AddAngularImpulse(inAngularImpulse);
805
806
if (!body.IsActive())
807
mBodyManager->ActivateBodies(&inBodyID, 1);
808
}
809
}
810
}
811
812
bool BodyInterface::ApplyBuoyancyImpulse(const BodyID &inBodyID, RVec3Arg inSurfacePosition, Vec3Arg inSurfaceNormal, float inBuoyancy, float inLinearDrag, float inAngularDrag, Vec3Arg inFluidVelocity, Vec3Arg inGravity, float inDeltaTime)
813
{
814
BodyLockWrite lock(*mBodyLockInterface, inBodyID);
815
if (lock.Succeeded())
816
{
817
Body &body = lock.GetBody();
818
if (body.IsDynamic()
819
&& body.ApplyBuoyancyImpulse(inSurfacePosition, inSurfaceNormal, inBuoyancy, inLinearDrag, inAngularDrag, inFluidVelocity, inGravity, inDeltaTime))
820
{
821
ActivateBodyInternal(body);
822
return true;
823
}
824
}
825
826
return false;
827
}
828
829
void BodyInterface::SetPositionRotationAndVelocity(const BodyID &inBodyID, RVec3Arg inPosition, QuatArg inRotation, Vec3Arg inLinearVelocity, Vec3Arg inAngularVelocity)
830
{
831
BodyLockWrite lock(*mBodyLockInterface, inBodyID);
832
if (lock.Succeeded())
833
{
834
Body &body = lock.GetBody();
835
836
// Update the position
837
body.SetPositionAndRotationInternal(inPosition, inRotation);
838
839
// Notify broadphase of change
840
if (body.IsInBroadPhase())
841
{
842
BodyID id = body.GetID();
843
mBroadPhase->NotifyBodiesAABBChanged(&id, 1);
844
}
845
846
if (!body.IsStatic())
847
{
848
body.SetLinearVelocityClamped(inLinearVelocity);
849
body.SetAngularVelocityClamped(inAngularVelocity);
850
851
// Optionally activate body
852
if (!body.IsActive() && (!inLinearVelocity.IsNearZero() || !inAngularVelocity.IsNearZero()))
853
mBodyManager->ActivateBodies(&inBodyID, 1);
854
}
855
}
856
}
857
858
void BodyInterface::SetMotionType(const BodyID &inBodyID, EMotionType inMotionType, EActivation inActivationMode)
859
{
860
BodyLockWrite lock(*mBodyLockInterface, inBodyID);
861
if (lock.Succeeded())
862
{
863
Body &body = lock.GetBody();
864
865
// Deactivate if we're making the body static
866
if (body.IsActive() && inMotionType == EMotionType::Static)
867
mBodyManager->DeactivateBodies(&inBodyID, 1);
868
869
body.SetMotionType(inMotionType);
870
871
// Activate body if requested
872
if (inMotionType != EMotionType::Static && inActivationMode == EActivation::Activate)
873
ActivateBodyInternal(body);
874
}
875
}
876
877
EBodyType BodyInterface::GetBodyType(const BodyID &inBodyID) const
878
{
879
BodyLockRead lock(*mBodyLockInterface, inBodyID);
880
if (lock.Succeeded())
881
return lock.GetBody().GetBodyType();
882
else
883
return EBodyType::RigidBody;
884
}
885
886
EMotionType BodyInterface::GetMotionType(const BodyID &inBodyID) const
887
{
888
BodyLockRead lock(*mBodyLockInterface, inBodyID);
889
if (lock.Succeeded())
890
return lock.GetBody().GetMotionType();
891
else
892
return EMotionType::Static;
893
}
894
895
void BodyInterface::SetMotionQuality(const BodyID &inBodyID, EMotionQuality inMotionQuality)
896
{
897
BodyLockWrite lock(*mBodyLockInterface, inBodyID);
898
if (lock.Succeeded())
899
mBodyManager->SetMotionQuality(lock.GetBody(), inMotionQuality);
900
}
901
902
EMotionQuality BodyInterface::GetMotionQuality(const BodyID &inBodyID) const
903
{
904
BodyLockRead lock(*mBodyLockInterface, inBodyID);
905
if (lock.Succeeded() && !lock.GetBody().IsStatic())
906
return lock.GetBody().GetMotionProperties()->GetMotionQuality();
907
else
908
return EMotionQuality::Discrete;
909
}
910
911
Mat44 BodyInterface::GetInverseInertia(const BodyID &inBodyID) const
912
{
913
BodyLockRead lock(*mBodyLockInterface, inBodyID);
914
if (lock.Succeeded())
915
return lock.GetBody().GetInverseInertia();
916
else
917
return Mat44::sIdentity();
918
}
919
920
void BodyInterface::SetRestitution(const BodyID &inBodyID, float inRestitution)
921
{
922
BodyLockWrite lock(*mBodyLockInterface, inBodyID);
923
if (lock.Succeeded())
924
lock.GetBody().SetRestitution(inRestitution);
925
}
926
927
float BodyInterface::GetRestitution(const BodyID &inBodyID) const
928
{
929
BodyLockRead lock(*mBodyLockInterface, inBodyID);
930
if (lock.Succeeded())
931
return lock.GetBody().GetRestitution();
932
else
933
return 0.0f;
934
}
935
936
void BodyInterface::SetFriction(const BodyID &inBodyID, float inFriction)
937
{
938
BodyLockWrite lock(*mBodyLockInterface, inBodyID);
939
if (lock.Succeeded())
940
lock.GetBody().SetFriction(inFriction);
941
}
942
943
float BodyInterface::GetFriction(const BodyID &inBodyID) const
944
{
945
BodyLockRead lock(*mBodyLockInterface, inBodyID);
946
if (lock.Succeeded())
947
return lock.GetBody().GetFriction();
948
else
949
return 0.0f;
950
}
951
952
void BodyInterface::SetGravityFactor(const BodyID &inBodyID, float inGravityFactor)
953
{
954
BodyLockWrite lock(*mBodyLockInterface, inBodyID);
955
if (lock.Succeeded() && lock.GetBody().GetMotionPropertiesUnchecked() != nullptr)
956
lock.GetBody().GetMotionPropertiesUnchecked()->SetGravityFactor(inGravityFactor);
957
}
958
959
float BodyInterface::GetGravityFactor(const BodyID &inBodyID) const
960
{
961
BodyLockRead lock(*mBodyLockInterface, inBodyID);
962
if (lock.Succeeded() && lock.GetBody().GetMotionPropertiesUnchecked() != nullptr)
963
return lock.GetBody().GetMotionPropertiesUnchecked()->GetGravityFactor();
964
else
965
return 1.0f;
966
}
967
968
void BodyInterface::SetUseManifoldReduction(const BodyID &inBodyID, bool inUseReduction)
969
{
970
BodyLockWrite lock(*mBodyLockInterface, inBodyID);
971
if (lock.Succeeded())
972
{
973
Body &body = lock.GetBody();
974
if (body.GetUseManifoldReduction() != inUseReduction)
975
{
976
body.SetUseManifoldReduction(inUseReduction);
977
978
// Flag collision cache invalid for this body
979
mBodyManager->InvalidateContactCacheForBody(body);
980
}
981
}
982
}
983
984
bool BodyInterface::GetUseManifoldReduction(const BodyID &inBodyID) const
985
{
986
BodyLockRead lock(*mBodyLockInterface, inBodyID);
987
if (lock.Succeeded())
988
return lock.GetBody().GetUseManifoldReduction();
989
else
990
return true;
991
}
992
993
void BodyInterface::SetCollisionGroup(const BodyID &inBodyID, const CollisionGroup &inCollisionGroup)
994
{
995
BodyLockWrite lock(*mBodyLockInterface, inBodyID);
996
if (lock.Succeeded())
997
lock.GetBody().SetCollisionGroup(inCollisionGroup);
998
}
999
1000
const CollisionGroup &BodyInterface::GetCollisionGroup(const BodyID &inBodyID) const
1001
{
1002
BodyLockRead lock(*mBodyLockInterface, inBodyID);
1003
if (lock.Succeeded())
1004
return lock.GetBody().GetCollisionGroup();
1005
else
1006
return CollisionGroup::sInvalid;
1007
}
1008
1009
TransformedShape BodyInterface::GetTransformedShape(const BodyID &inBodyID) const
1010
{
1011
BodyLockRead lock(*mBodyLockInterface, inBodyID);
1012
if (lock.Succeeded())
1013
return lock.GetBody().GetTransformedShape();
1014
else
1015
return TransformedShape();
1016
}
1017
1018
uint64 BodyInterface::GetUserData(const BodyID &inBodyID) const
1019
{
1020
BodyLockRead lock(*mBodyLockInterface, inBodyID);
1021
if (lock.Succeeded())
1022
return lock.GetBody().GetUserData();
1023
else
1024
return 0;
1025
}
1026
1027
void BodyInterface::SetUserData(const BodyID &inBodyID, uint64 inUserData) const
1028
{
1029
BodyLockWrite lock(*mBodyLockInterface, inBodyID);
1030
if (lock.Succeeded())
1031
lock.GetBody().SetUserData(inUserData);
1032
}
1033
1034
const PhysicsMaterial *BodyInterface::GetMaterial(const BodyID &inBodyID, const SubShapeID &inSubShapeID) const
1035
{
1036
BodyLockRead lock(*mBodyLockInterface, inBodyID);
1037
if (lock.Succeeded())
1038
return lock.GetBody().GetShape()->GetMaterial(inSubShapeID);
1039
else
1040
return PhysicsMaterial::sDefault;
1041
}
1042
1043
void BodyInterface::InvalidateContactCache(const BodyID &inBodyID)
1044
{
1045
BodyLockWrite lock(*mBodyLockInterface, inBodyID);
1046
if (lock.Succeeded())
1047
mBodyManager->InvalidateContactCacheForBody(lock.GetBody());
1048
}
1049
1050
JPH_NAMESPACE_END
1051
1052