You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
345 lines
11 KiB
345 lines
11 KiB
//========= 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() = default; |
|
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
|
|
|