1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
|
#ifndef RIGIDBODY_H
#define RIGIDBODY_H
#include "Runtime/GameCode/Behaviour.h"
#include "Runtime/Math/Vector3.h"
#include "Runtime/Math/Quaternion.h"
#include "Runtime/Math/Matrix4x4.h"
#include "PhysicsManager.h"
class Transform;
class Quaternionf;
struct RootMotionData;
namespace Unity { class Joint; }
enum RigidbodyInterpolation { kNoInterpolation = 0, kInterpolate = 1, kExtrapolate = 2 };
class Rigidbody : public Unity::Component {
public:
REGISTER_DERIVED_CLASS (Rigidbody, Component)
DECLARE_OBJECT_SERIALIZE (Rigidbody)
Rigidbody (MemLabelId label, ObjectCreationMode mode);
// virtual ~Rigidbody(); declared-by-macro
virtual void Reset ();
virtual void AwakeFromLoad (AwakeFromLoadMode awakeMode);
virtual void Deactivate (DeactivateOperation operation);
static void InitializeClass ();
static void CleanupClass () {}
// Is the rigid body affected by gravity?
void SetUseGravity (bool gravity);
bool GetUseGravity () const;
// Mass of the rigid body
void SetMass (float mass);
float GetMass () const;
// Center of Mass of the rigid body in local space
void SetCenterOfMass (const Vector3f& centerOfMass);
Vector3f GetCenterOfMass () const;
// Center of Mass of the rigid body in world space
Vector3f GetWorldCenterOfMass () const;
// The rotation of the inertia tensor
void SetInertiaTensorRotation (const Quaternionf& inertia);
Quaternionf GetInertiaTensorRotation () const;
// The diagonal inertia tensor of mass relative to the center of mass and inertia rotation
void SetInertiaTensor (const Vector3f& inertia);
Vector3f GetInertiaTensor () const;
// Does the rigid body modify the rotation?
void SetFreezeRotation (bool freezeRotation);
bool GetFreezeRotation () const;
void SetConstraints (int flags);
int GetConstraints () const;
void SetIsKinematic (bool isKinematic);
bool GetIsKinematic () const;
void SetCollisionDetectionMode (int ccd);
int GetCollisionDetectionMode () const { return m_CollisionDetection; }
void SetDensity (float density);
// Get Position and rotation - This can be different from transform state when using interpolation
Vector3f GetPosition () const;
Quaternionf GetRotation () const;
// Set pos&rot this will cause transform.position/rotation to be updated delayed after the next fixed step
void SetPosition (const Vector3f& p);
void SetRotation (const Quaternionf& q);
/// Move to a position
/// This happens one frame delayed.
void MovePosition (const Vector3f& pos);
void MoveRotation (const Quaternionf& rot);
// Velocity
Vector3f GetVelocity () const;
void SetVelocity (const Vector3f& velocity);
// Angular velocity
Vector3f GetAngularVelocity () const;
void SetAngularVelocity (const Vector3f& velocity);
/// The linear drag coefficient. 0 means no drag. range { 0, infinity }
float GetDrag () const;
void SetDrag (float damping);
// The angular drag coefficient. 0 means no drag. range { 0, infinity }
void SetAngularDrag (float damping);
float GetAngularDrag () const;
/// Lets you set the maximum angular velocity permitted for this rigid body. Because for various computations, the rotation
/// of an object is linearized, quickly rotating actors introduce error into the simulation, which leads to bad things.
///
/// However, because some rigid bodies, such as car wheels, should be able to rotate quickly, you can override the default setting
/// on a per-rigid body basis with the below call. Note that objects such as wheels which are approximated with spherical or
/// other smooth collision primitives can be simulated with stability at a much higher angular velocity than, say, a box that
/// has corners.
void SetMaxAngularVelocity (float maxAngularVelocity);
float GetMaxAngularVelocity () const;
// The velocity of a point given in world coordinates
// if it were attached to the actor and moving with it.
Vector3f GetPointVelocity (const Vector3f& worldPoint) const;
// The velocity of a point given in world coordinates
// if it were attached to the actor and moving with it.
Vector3f GetRelativePointVelocity (const Vector3f& localPoint) const;
enum ForceMode
{
FORCE, ///< parameter has unit of mass * distance/ time^2, i.e. a force
IMPULSE, ///< parameter has unit of mass * distance /time
VELOCITY_CHANGE, ///< parameter has unit of distance / time, i.e. the effect is mass independent: a velocity change.
SMOOTH_IMPULSE, ///< same as NX_IMPULSE but the effect is applied over all substeps. Use this for motion controllers that repeatedly apply an impulse.
SMOOTH_VELOCITY_CHANGE, ///< same as NX_VELOCITY_CHANGE but the effect is applied over all substeps. Use this for motion controllers that repeatedly apply an impulse.
ACCELERATION ///< parameter has unit of distance/ time^2, i.e. an acceleration. It gets treated just like a force except the mass is not divided out before integration.
};
enum { kCCDModeOff = 0, kCCDModeNormal = 1, kCCDModeDynamic = 2 };
enum {
kFreezeNone = 0,
kFreezePositionX = (1<<1),
kFreezePositionY = (1<<2),
kFreezePositionZ = (1<<3),
kFreezeRotationX = (1<<4),
kFreezeRotationY = (1<<5),
kFreezeRotationZ = (1<<6),
kFreezePosition = kFreezePositionX | kFreezePositionY | kFreezePositionZ,
kFreezeRotation = kFreezeRotationX | kFreezeRotationY | kFreezeRotationZ,
kFreezeAll = kFreezePosition | kFreezeRotation,
};
// Applies a force (or impulse) defined in the global coordinate frame,
// acting at a particular point in global coordinates on the rigid body.
// Note that if the force does not act along the center of mass of the actor, this
// will also add the corresponding torque.
// Forces should be applied inside FixedUpdate only, because forces are reset at the end of every fixed timestep.
void AddForceAtPosition (const Vector3f& force, const Vector3f& position, int mode = FORCE);
// Applies a force (or impulse) defined in the global coordinate frame,
// This will not induce torque.
// Forces should be applied inside FixedUpdate only, because forces are reset at the end of every fixed timestep.
void AddForce (const Vector3f& force, int mode = FORCE);
// Applies a force (or impulse) defined in the local coordinate frame,
// This will not induce torque.
// Forces should be applied inside FixedUpdate only, because forces are reset at the end of every fixed timestep.
void AddRelativeForce (const Vector3f& force, int mode = FORCE);
// Applies an (eventually impulsive) torque defined in the global coordinate frame to the actor.
// Torques should be applied inside FixedUpdate only, because forces are reset at the end of every fixed timestep.
void AddTorque (const Vector3f& torque, int mode = FORCE);
// Applies an (eventually impulsive) torque defined in the local coordinate frame to the actor.
// Torques should be applied inside FixedUpdate only, because forces are reset at the end of every fixed timestep.
void AddRelativeTorque (const Vector3f& torque, int mode = FORCE);
void AddExplosionForce (float force, const Vector3f& position, float radius, float upwardsModifier, int forceMode = FORCE);
void ClosestPointOnBounds (const Vector3f& position, Vector3f& outPosition, float& outSqrDistance);
bool GetDetectCollisions() const;
void SetDetectCollisions(bool enable);
RigidbodyInterpolation GetInterpolation () { return (RigidbodyInterpolation)m_Interpolate; }
void SetInterpolation (RigidbodyInterpolation interpolation);
bool GetUseConeFriction () const;
void SetUseConeFriction (bool cone);
bool IsSleeping ();
void Sleep ();
void WakeUp ();
void SetSolverIterationCount (int iterationCount);
int GetSolverIterationCount () const;
void SetSleepVelocity (float value);
float GetSleepVelocity () const;
void SetSleepAngularVelocity (float value);
float GetSleepAngularVelocity () const;
void TransformChanged (int mask);
void ApplyRootMotionBuiltin (RootMotionData* rootMotion);
bool SweepTest (const Vector3f &direction, float distance, RaycastHit& outHit);
const PhysicsManager::RaycastHits& SweepTestAll (const Vector3f &direction, float distance);
virtual void CheckConsistency ();
// Testing API
NxActor* GetActor() { return m_Actor; }
private:
void SortParentedRigidbodies ();
void FetchPoseFromTransform ();
virtual void SupportedMessagesDidChange (int supported);
void UpdateSortedBody ();
void Create (bool active);
void CleanupInternal (bool recreateColliders);
void UpdateInterpolationNode ();
void UpdateMassDistribution ();
ListNode<Rigidbody> m_SortedNode;
class NxActor* m_Actor;
float m_Mass;///< The mass of the body. range { 0.0000001, 1000000000 }
float m_Drag;///< The linear drag coefficient. 0 means no damping. range { 0, infinity }
float m_AngularDrag; ///< The angular drag coefficient. 0 means no damping. range { 0, infinity }
UInt8 m_ActiveScene;
UInt8 m_ImplicitTensor;
bool m_UseGravity;
bool m_IsKinematic;
int m_Constraints;
int m_CollisionDetection;///< enum { Discrete = 0, Continuous = 1, Continuous Dynamic = 2 }
int m_CachedCollisionDetection;
public:
/// This is used to prevent read back from kinematic rigidbodies.
/// * setGlobalPosition sets the position immediately. No triggers will be activated.
/// No velocity applied -> thus no friction for rigidbodies sitting on animated objects.
/// * moveGlobalPosition sets the position delayed during simulate. Simply calling moveGlobalPosition for all kinematic objects
/// doesn't work because then the physics update loop will update delayed, causing small epsilon precision errors to accumulate
/// from the local to world, then world to local transformation. If the transform which has the kinematic rigidbody attached
/// is not actually animated, the ragdoll will slowly drift apart.
/// On top of that, it is slow since we read back the position twice for animated ragdolls and characters.
/// ->> The solution is to store if we should read back the update.
/// If we are setting the position directly from a Transform update, there is no reason to update the transform
/// Also the world position wont change during simulation since it is kinematic rigidbody.
UInt8 m_Interpolate;///< enum { None = 0, Interpolate = 1, Extrapolate = 2 }
int m_DisableReadUpdateTransform;
int m_DisableInterpolation;
RigidbodyInterpolationInfo* m_InterpolationInfo;
friend class Collider;
friend class Unity::Joint;
friend class PhysicsManager;
};
/// Notifications:
/// bool RigidbodyChanged (const Rigidbody& b);
extern MessageIdentifier kRigidbodyChanged;
#endif
|