Jolt Physics
A multi core friendly Game Physics Engine
Loading...
Searching...
No Matches
Body.inl
Go to the documentation of this file.
1// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
2// SPDX-FileCopyrightText: 2021 Jorrit Rouwe
3// SPDX-License-Identifier: MIT
4
5#pragma once
6
8
10{
11 JPH_ASSERT(BodyAccess::sCheckRights(BodyAccess::sPositionAccess(), BodyAccess::EAccess::Read));
12
13 return RMat44::sRotationTranslation(mRotation, mPosition).PreTranslated(-mShape->GetCenterOfMass());
14}
15
17{
18 JPH_ASSERT(BodyAccess::sCheckRights(BodyAccess::sPositionAccess(), BodyAccess::EAccess::Read));
19
20 return RMat44::sRotationTranslation(mRotation, mPosition);
21}
22
24{
25 JPH_ASSERT(BodyAccess::sCheckRights(BodyAccess::sPositionAccess(), BodyAccess::EAccess::Read));
26
27 return RMat44::sInverseRotationTranslation(mRotation, mPosition);
28}
29
30inline bool Body::sFindCollidingPairsCanCollide(const Body &inBody1, const Body &inBody2)
31{
32 // First body should never be a soft body
33 JPH_ASSERT(!inBody1.IsSoftBody());
34
35 // One of these conditions must be true
36 // - We always allow detecting collisions between kinematic and non-dynamic bodies
37 // - One of the bodies must be dynamic to collide
38 // - A kinematic object can collide with a sensor
41 && (!inBody1.IsDynamic() && !inBody2.IsDynamic())
42 && !(inBody1.IsKinematic() && inBody2.IsSensor())
43 && !(inBody2.IsKinematic() && inBody1.IsSensor()))
44 return false;
45
46 // Check that body 1 is active
47 uint32 body1_index_in_active_bodies = inBody1.GetIndexInActiveBodiesInternal();
48 JPH_ASSERT(!inBody1.IsStatic() && body1_index_in_active_bodies != Body::cInactiveIndex, "This function assumes that Body 1 is active");
49
50 // If the pair A, B collides we need to ensure that the pair B, A does not collide or else we will handle the collision twice.
51 // If A is the same body as B we don't want to collide (1)
52 // If A is dynamic / kinematic and B is static we should collide (2)
53 // If A is dynamic / kinematic and B is dynamic / kinematic we should only collide if
54 // - A is active and B is not active (3)
55 // - A is active and B will become active during this simulation step (4)
56 // - A is active and B is active, we require a condition that makes A, B collide and B, A not (5)
57 //
58 // In order to implement this we use the index in the active body list and make use of the fact that
59 // a body not in the active list has Body.Index = 0xffffffff which is the highest possible value for an uint32.
60 //
61 // Because we know that A is active we know that A.Index != 0xffffffff:
62 // (1) Because A.Index != 0xffffffff, if A.Index = B.Index then A = B, so to collide A.Index != B.Index
63 // (2) A.Index != 0xffffffff, B.Index = 0xffffffff (because it's static and cannot be in the active list), so to collide A.Index != B.Index
64 // (3) A.Index != 0xffffffff, B.Index = 0xffffffff (because it's not yet active), so to collide A.Index != B.Index
65 // (4) A.Index != 0xffffffff, B.Index = 0xffffffff currently. But it can activate during the Broad/NarrowPhase step at which point it
66 // will be added to the end of the active list which will make B.Index > A.Index (this holds only true when we don't deactivate
67 // bodies during the Broad/NarrowPhase step), so to collide A.Index < B.Index.
68 // (5) As tie breaker we can use the same condition A.Index < B.Index to collide, this means that if A, B collides then B, A won't
69 static_assert(Body::cInactiveIndex == 0xffffffff, "The algorithm below uses this value");
70 if (!inBody2.IsSoftBody() && body1_index_in_active_bodies >= inBody2.GetIndexInActiveBodiesInternal())
71 return false;
72 JPH_ASSERT(inBody1.GetID() != inBody2.GetID(), "Read the comment above, A and B are the same body which should not be possible!");
73
74 // Check collision group filter
75 if (!inBody1.GetCollisionGroup().CanCollide(inBody2.GetCollisionGroup()))
76 return false;
77
78 return true;
79}
80
81void Body::AddRotationStep(Vec3Arg inAngularVelocityTimesDeltaTime)
82{
84 JPH_ASSERT(BodyAccess::sCheckRights(BodyAccess::sPositionAccess(), BodyAccess::EAccess::ReadWrite));
85
86 // This used to use the equation: d/dt R(t) = 1/2 * w(t) * R(t) so that R(t + dt) = R(t) + 1/2 * w(t) * R(t) * dt
87 // See: Appendix B of An Introduction to Physically Based Modeling: Rigid Body Simulation II-Nonpenetration Constraints
88 // URL: https://www.cs.cmu.edu/~baraff/sigcourse/notesd2.pdf
89 // But this is a first order approximation and does not work well for kinematic ragdolls that are driven to a new
90 // pose if the poses differ enough. So now we split w(t) * dt into an axis and angle part and create a quaternion with it.
91 // Note that the resulting quaternion is normalized since otherwise numerical drift will eventually make the rotation non-normalized.
92 float len = inAngularVelocityTimesDeltaTime.Length();
93 if (len > 1.0e-6f)
94 {
95 mRotation = (Quat::sRotation(inAngularVelocityTimesDeltaTime / len, len) * mRotation).Normalized();
96 JPH_ASSERT(!mRotation.IsNaN());
97 }
98}
99
100void Body::SubRotationStep(Vec3Arg inAngularVelocityTimesDeltaTime)
101{
103 JPH_ASSERT(BodyAccess::sCheckRights(BodyAccess::sPositionAccess(), BodyAccess::EAccess::ReadWrite));
104
105 // See comment at Body::AddRotationStep
106 float len = inAngularVelocityTimesDeltaTime.Length();
107 if (len > 1.0e-6f)
108 {
109 mRotation = (Quat::sRotation(inAngularVelocityTimesDeltaTime / len, -len) * mRotation).Normalized();
110 JPH_ASSERT(!mRotation.IsNaN());
111 }
112}
113
114Vec3 Body::GetWorldSpaceSurfaceNormal(const SubShapeID &inSubShapeID, RVec3Arg inPosition) const
115{
117 return inv_com.Multiply3x3Transposed(mShape->GetSurfaceNormal(inSubShapeID, Vec3(inv_com * inPosition))).Normalized();
118}
119
126
127void Body::AddForce(Vec3Arg inForce, RVec3Arg inPosition)
128{
129 AddForce(inForce);
130 AddTorque(Vec3(inPosition - mPosition).Cross(inForce));
131}
132
134{
136
137 SetLinearVelocityClamped(mMotionProperties->GetLinearVelocity() + inImpulse * mMotionProperties->GetInverseMass());
138}
139
140void Body::AddImpulse(Vec3Arg inImpulse, RVec3Arg inPosition)
141{
143
144 SetLinearVelocityClamped(mMotionProperties->GetLinearVelocity() + inImpulse * mMotionProperties->GetInverseMass());
145
146 SetAngularVelocityClamped(mMotionProperties->GetAngularVelocity() + mMotionProperties->MultiplyWorldSpaceInverseInertiaByVector(mRotation, Vec3(inPosition - mPosition).Cross(inImpulse)));
147}
148
149void Body::AddAngularImpulse(Vec3Arg inAngularImpulse)
150{
152
153 SetAngularVelocityClamped(mMotionProperties->GetAngularVelocity() + mMotionProperties->MultiplyWorldSpaceInverseInertiaByVector(mRotation, inAngularImpulse));
154}
155
156void Body::GetSleepTestPoints(RVec3 *outPoints) const
157{
158 JPH_ASSERT(BodyAccess::sCheckRights(BodyAccess::sPositionAccess(), BodyAccess::EAccess::Read));
159
160 // Center of mass is the first position
161 outPoints[0] = mPosition;
162
163 // The second and third position are on the largest axis of the bounding box
164 Vec3 extent = mShape->GetLocalBounds().GetExtent();
165 int lowest_component = extent.GetLowestComponentIndex();
166 Mat44 rotation = Mat44::sRotation(mRotation);
167 switch (lowest_component)
168 {
169 case 0:
170 outPoints[1] = mPosition + extent.GetY() * rotation.GetColumn3(1);
171 outPoints[2] = mPosition + extent.GetZ() * rotation.GetColumn3(2);
172 break;
173
174 case 1:
175 outPoints[1] = mPosition + extent.GetX() * rotation.GetColumn3(0);
176 outPoints[2] = mPosition + extent.GetZ() * rotation.GetColumn3(2);
177 break;
178
179 case 2:
180 outPoints[1] = mPosition + extent.GetX() * rotation.GetColumn3(0);
181 outPoints[2] = mPosition + extent.GetY() * rotation.GetColumn3(1);
182 break;
183
184 default:
185 JPH_ASSERT(false);
186 break;
187 }
188}
189
191{
192 RVec3 points[3];
193 GetSleepTestPoints(points);
194 mMotionProperties->ResetSleepTestSpheres(points);
195}
196
#define JPH_NAMESPACE_END
Definition Core.h:425
std::uint32_t uint32
Definition Core.h:503
#define JPH_NAMESPACE_BEGIN
Definition Core.h:419
#define JPH_ASSERT(...)
Definition IssueReporting.h:33
const Vec3 Vec3Arg
Definition MathTypes.h:19
Vec3Arg RVec3Arg
Definition Real.h:30
Mat44 RMat44
Definition Real.h:31
Vec3 RVec3
Definition Real.h:29
Vec3 GetExtent() const
Get extent of bounding box (half of the size).
Definition AABox.h:120
const MotionProperties * GetMotionProperties() const
Access to the motion properties.
Definition Body.h:308
Vec3 GetWorldSpaceSurfaceNormal(const SubShapeID &inSubShapeID, RVec3Arg inPosition) const
Get surface normal of a particular sub shape and its world space surface position on this body.
Definition Body.inl:114
bool IsDynamic() const
Check if this body is dynamic, which means that it moves and forces can act on it.
Definition Body.h:67
bool IsSensor() const
Check if this body is a sensor.
Definition Body.h:80
void AddRotationStep(Vec3Arg inAngularVelocityTimesDeltaTime)
Update rotation using an Euler step (used during position integrate & constraint solving).
Definition Body.inl:81
bool IsSoftBody() const
Check if this body is a soft body.
Definition Body.h:53
RMat44 GetWorldTransform() const
Calculates the transform of this body.
Definition Body.inl:9
const CollisionGroup & GetCollisionGroup() const
Collision group and sub-group ID, determines which other objects it collides with.
Definition Body.h:130
void SetLinearVelocityClamped(Vec3Arg inLinearVelocity)
Definition Body.h:158
JPH_TSAN_NO_SANITIZE uint32 GetIndexInActiveBodiesInternal() const
Access to the index in the BodyManager::mActiveBodies list.
Definition Body.h:380
static constexpr uint32 cInactiveIndex
Constant indicating that body is not active.
Definition Body.h:393
static bool sFindCollidingPairsCanCollide(const Body &inBody1, const Body &inBody2)
Definition Body.inl:30
Mat44 GetInverseInertia() const
Get inverse inertia tensor in world space.
Definition Body.inl:120
bool IsRigidBody() const
Check if this body is a rigid body.
Definition Body.h:50
bool IsStatic() const
Check if this body is static (not movable).
Definition Body.h:61
bool GetCollideKinematicVsNonDynamic() const
Check if kinematic objects can generate contact points against other kinematic or static objects.
Definition Body.h:88
void SetAngularVelocityClamped(Vec3Arg inAngularVelocity)
Definition Body.h:169
RMat44 GetCenterOfMassTransform() const
Calculates the transform for this body's center of mass.
Definition Body.inl:16
void ResetSleepTimer()
Resets the sleep timer. This does not wake up the body if it is sleeping, but allows resetting the sy...
Definition Body.inl:190
RMat44 GetInverseCenterOfMassTransform() const
Calculates the inverse of the transform for this body's center of mass.
Definition Body.inl:23
void AddAngularImpulse(Vec3Arg inAngularImpulse)
Definition Body.inl:149
void SubRotationStep(Vec3Arg inAngularVelocityTimesDeltaTime)
Definition Body.inl:100
bool IsKinematic() const
Check if this body is kinematic (keyframed), which means that it will move according to its current v...
Definition Body.h:64
JPH_OVERRIDE_NEW_DELETE const BodyID & GetID() const
Get the id of this body.
Definition Body.h:44
void AddForce(Vec3Arg inForce)
Definition Body.h:179
void AddTorque(Vec3Arg inTorque)
Definition Body.h:187
void AddImpulse(Vec3Arg inImpulse)
Definition Body.inl:133
bool CanCollide(const CollisionGroup &inOther) const
Check if this object collides with another object.
Definition CollisionGroup.h:71
Holds a 4x4 matrix of floats, but supports also operations on the 3x3 upper left part of the matrix.
Definition Mat44.h:13
JPH_INLINE Mat44 PreTranslated(Vec3Arg inTranslation) const
Pre multiply by translation matrix: result = this * Mat44::sTranslation(inTranslation).
Definition Mat44.inl:898
JPH_INLINE Vec3 Multiply3x3Transposed(Vec3Arg inV) const
Multiply vector by only 3x3 part of the transpose of the matrix ( ).
Definition Mat44.inl:336
JPH_INLINE Vec3 GetColumn3(uint inCol) const
Definition Mat44.h:158
static JPH_INLINE Mat44 sRotationTranslation(QuatArg inR, Vec3Arg inT)
Get matrix that rotates and translates.
Definition Mat44.inl:149
static JPH_INLINE Mat44 sRotation(Vec3Arg inAxis, float inAngle)
Rotate around arbitrary axis.
Definition Mat44.inl:139
static JPH_INLINE Mat44 sInverseRotationTranslation(QuatArg inR, Vec3Arg inT)
Get inverse matrix of sRotationTranslation.
Definition Mat44.inl:156
Mat44 GetInverseInertiaForRotation(Mat44Arg inRotation) const
Get inverse inertia matrix ( ) for a given object rotation (translation will be ignored)....
Definition MotionProperties.inl:69
static JPH_INLINE Quat sRotation(Vec3Arg inAxis, float inAngle)
Rotation from axis and angle.
Definition Quat.inl:128
virtual AABox GetLocalBounds() const =0
Get local bounding box including convex radius, this box is centered around the center of mass rather...
A sub shape id contains a path to an element (usually a triangle or other primitive type) of a compou...
Definition SubShapeID.h:23
Definition Vec3.h:17
JPH_INLINE Vec3 Normalized() const
Normalize vector.
Definition Vec3.inl:707
JPH_INLINE float GetX() const
Get individual components.
Definition Vec3.h:127
JPH_INLINE float Length() const
Length of vector.
Definition Vec3.inl:682
JPH_INLINE int GetLowestComponentIndex() const
Get index of component with lowest value.
Definition Vec3.inl:567
JPH_INLINE float GetY() const
Definition Vec3.h:128
JPH_INLINE float GetZ() const
Definition Vec3.h:129