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
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
|
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef CONSTRAINTS_H
#define CONSTRAINTS_H
#ifdef _WIN32
#pragma once
#endif
#include "vphysics_interface.h"
#include "mathlib/mathlib.h"
// constraint groups
struct constraint_groupparams_t
{
int additionalIterations; // additional solver iterations make the constraint system more stable
int minErrorTicks; // minimum number of ticks with an error before it's reported
float errorTolerance; // error tolerance in HL units
inline void Defaults()
{
additionalIterations = 0;
minErrorTicks = 15;
errorTolerance = 3.0f;
}
};
// Breakable constraints;
//
// forceLimit - kg * in / s limit (N * conversion(in/m))
// torqueLimit - kg * in^2 / s (Nm * conversion(in^2/m^2))
//
// strength 0 - 1
struct constraint_breakableparams_t
{
float strength; // strength of the constraint 0.0 - 1.0
float forceLimit; // constraint force limit to break (0 means never break)
float torqueLimit; // constraint torque limit to break (0 means never break)
float bodyMassScale[2]; // scale applied to mass of reference/attached object before solving constriant
bool isActive;
inline void Defaults()
{
forceLimit = 0.0f;
torqueLimit = 0.0f;
strength = 1.0f;
bodyMassScale[0] = 1.0f;
bodyMassScale[1] = 1.0f;
isActive = true;
}
};
//-----------------------------------------------------------------------------
// Purpose: constraint limit on a single rotation axis
//-----------------------------------------------------------------------------
struct constraint_axislimit_t
{
float minRotation;
float maxRotation;
float angularVelocity; // desired angular velocity around hinge
float torque; // torque to achieve angular velocity (use 0, torque for "friction")
inline void SetAxisFriction( float rmin, float rmax, float friction )
{
minRotation = rmin;
maxRotation = rmax;
angularVelocity = 0;
torque = friction;
}
inline void Defaults()
{
SetAxisFriction(0,0,0);
}
};
// Builds a transform which maps points in the input object's local space
// to the output object's local space
inline void BuildObjectRelativeXform( IPhysicsObject *pOutputSpace, IPhysicsObject *pInputSpace, matrix3x4_t &xformInToOut )
{
matrix3x4_t outInv, tmp, input;
pOutputSpace->GetPositionMatrix( &tmp );
MatrixInvert( tmp, outInv );
pInputSpace->GetPositionMatrix( &input );
ConcatTransforms( outInv, input, xformInToOut );
}
//-----------------------------------------------------------------------------
// Purpose: special limited ballsocket constraint for ragdolls.
// Has axis limits for all 3 axes.
//-----------------------------------------------------------------------------
struct constraint_ragdollparams_t
{
constraint_breakableparams_t constraint;
matrix3x4_t constraintToReference;// xform constraint space to refobject space
matrix3x4_t constraintToAttached; // xform constraint space to attached object space
int parentIndex; // NOTE: only used for parsing. NEED NOT BE SET for create
int childIndex; // NOTE: only used for parsing. NEED NOT BE SET for create
constraint_axislimit_t axes[3];
bool onlyAngularLimits; // only angular limits (not translation as well?)
bool isActive;
bool useClockwiseRotations; // HACKHACK: Did this wrong in version one. Fix in the future.
inline void Defaults()
{
constraint.Defaults();
isActive = true;
SetIdentityMatrix( constraintToReference );
SetIdentityMatrix( constraintToAttached );
parentIndex = -1;
childIndex = -1;
axes[0].Defaults();
axes[1].Defaults();
axes[2].Defaults();
onlyAngularLimits = false;
useClockwiseRotations = false;
}
};
//-----------------------------------------------------------------------------
// Purpose: Used to init a hinge restricting the relative position and orientation
// of two objects to rotation around a single axis
//-----------------------------------------------------------------------------
struct constraint_hingeparams_t
{
Vector worldPosition; // position in world space on the hinge axis
Vector worldAxisDirection; // unit direction vector of the hinge axis in world space
constraint_axislimit_t hingeAxis;
constraint_breakableparams_t constraint;
inline void Defaults()
{
worldPosition.Init();
worldAxisDirection.Init();
hingeAxis.Defaults();
constraint.Defaults();
}
};
struct constraint_limitedhingeparams_t : public constraint_hingeparams_t
{
Vector referencePerpAxisDirection; // unit direction vector vector perpendicular to the hinge axis in world space
Vector attachedPerpAxisDirection; // unit direction vector vector perpendicular to the hinge axis in world space
constraint_limitedhingeparams_t() {}
constraint_limitedhingeparams_t( const constraint_hingeparams_t &hinge )
{
static_cast<constraint_hingeparams_t &>(*this) = hinge;
referencePerpAxisDirection.Init();
attachedPerpAxisDirection.Init();
}
inline void Defaults()
{
this->constraint_hingeparams_t::Defaults();
referencePerpAxisDirection.Init();
attachedPerpAxisDirection.Init();
}
};
//-----------------------------------------------------------------------------
// Purpose: Used to init a constraint that fixes the position and orientation
// of two objects relative to each other (like glue)
//-----------------------------------------------------------------------------
struct constraint_fixedparams_t
{
matrix3x4_t attachedRefXform; // xform attached object space to ref object space
constraint_breakableparams_t constraint;
inline void InitWithCurrentObjectState( IPhysicsObject *pRef, IPhysicsObject *pAttached )
{
BuildObjectRelativeXform( pRef, pAttached, attachedRefXform );
}
inline void Defaults()
{
SetIdentityMatrix( attachedRefXform );
constraint.Defaults();
}
};
//-----------------------------------------------------------------------------
// Purpose: Same parameters as fixed constraint, but torqueLimit has no effect
//-----------------------------------------------------------------------------
struct constraint_ballsocketparams_t
{
Vector constraintPosition[2]; // position of the constraint in each object's space
constraint_breakableparams_t constraint;
inline void Defaults()
{
constraint.Defaults();
constraintPosition[0].Init();
constraintPosition[1].Init();
}
void InitWithCurrentObjectState( IPhysicsObject *pRef, IPhysicsObject *pAttached, const Vector &ballsocketOrigin )
{
pRef->WorldToLocal( &constraintPosition[0], ballsocketOrigin );
pAttached->WorldToLocal( &constraintPosition[1], ballsocketOrigin );
}
};
struct constraint_slidingparams_t
{
matrix3x4_t attachedRefXform; // xform attached object space to ref object space
Vector slideAxisRef; // unit direction vector of the slide axis in ref object space
constraint_breakableparams_t constraint;
// NOTE: if limitMin == limitMax there is NO limit set!
float limitMin; // minimum limit coordinate refAxisDirection space
float limitMax; // maximum limit coordinate refAxisDirection space
float friction; // friction on sliding
float velocity; // desired velocity
inline void Defaults()
{
SetIdentityMatrix( attachedRefXform );
slideAxisRef.Init();
limitMin = limitMax = 0;
friction = 0;
velocity = 0;
constraint.Defaults();
}
inline void SetFriction( float inputFriction )
{
friction = inputFriction;
velocity = 0;
}
inline void SetLinearMotor( float inputVelocity, float maxForce )
{
friction = maxForce;
velocity = inputVelocity;
}
inline void InitWithCurrentObjectState( IPhysicsObject *pRef, IPhysicsObject *pAttached, const Vector &slideDirWorldspace )
{
BuildObjectRelativeXform( pRef, pAttached, attachedRefXform );
matrix3x4_t tmp;
pRef->GetPositionMatrix( &tmp );
VectorIRotate( slideDirWorldspace, tmp, slideAxisRef );
}
};
struct constraint_pulleyparams_t
{
constraint_breakableparams_t constraint;
Vector pulleyPosition[2]; // These are the pulley positions for the reference and attached objects in world space
Vector objectPosition[2]; // local positions of attachments to the ref,att objects
float totalLength; // total rope length (include gearing!)
float gearRatio; // gearing affects attached object ALWAYS
bool isRigid;
inline void Defaults()
{
constraint.Defaults();
totalLength = 1.0;
gearRatio = 1.0;
pulleyPosition[0].Init();
pulleyPosition[1].Init();
objectPosition[0].Init();
objectPosition[1].Init();
isRigid = false;
}
};
struct constraint_lengthparams_t
{
constraint_breakableparams_t constraint;
Vector objectPosition[2]; // These are the positions for the reference and attached objects in local space
float totalLength; // Length of rope/spring/constraint. Distance to maintain
float minLength; // if rigid, objects are not allowed to move closer than totalLength either
void InitWorldspace( IPhysicsObject *pRef, IPhysicsObject *pAttached, const Vector &refPosition, const Vector &attachedPosition, bool rigid = false )
{
pRef->WorldToLocal( &objectPosition[0], refPosition );
pAttached->WorldToLocal( &objectPosition[1], attachedPosition );
totalLength = (refPosition - attachedPosition).Length();
minLength = rigid ? totalLength : 0;
}
inline void Defaults()
{
constraint.Defaults();
objectPosition[0].Init();
objectPosition[1].Init();
totalLength = 1;
minLength = 0;
}
};
class IPhysicsConstraint
{
public:
virtual ~IPhysicsConstraint( void ) {}
// NOTE: Constraints are active when created. You can temporarily enable/disable them with these functions
virtual void Activate( void ) = 0;
virtual void Deactivate( void ) = 0;
// set a pointer to the game object
virtual void SetGameData( void *gameData ) = 0;
// get a pointer to the game object
virtual void *GetGameData( void ) const = 0;
// Get the parent/referenced object
virtual IPhysicsObject *GetReferenceObject( void ) const = 0;
// Get the attached object
virtual IPhysicsObject *GetAttachedObject( void ) const = 0;
virtual void SetLinearMotor( float speed, float maxLinearImpulse ) = 0;
virtual void SetAngularMotor( float rotSpeed, float maxAngularImpulse ) = 0;
virtual void UpdateRagdollTransforms( const matrix3x4_t &constraintToReference, const matrix3x4_t &constraintToAttached ) = 0;
virtual bool GetConstraintTransform( matrix3x4_t *pConstraintToReference, matrix3x4_t *pConstraintToAttached ) const = 0;
virtual bool GetConstraintParams( constraint_breakableparams_t *pParams ) const = 0;
virtual void OutputDebugInfo() = 0;
};
class IPhysicsConstraintGroup
{
public:
virtual ~IPhysicsConstraintGroup( void ) {}
virtual void Activate() = 0;
virtual bool IsInErrorState() = 0;
virtual void ClearErrorState() = 0;
virtual void GetErrorParams( constraint_groupparams_t *pParams ) = 0;
virtual void SetErrorParams( const constraint_groupparams_t ¶ms ) = 0;
virtual void SolvePenetration( IPhysicsObject *pObj0, IPhysicsObject *pObj1 ) = 0;
};
#endif // CONSTRAINTS_H
|