|
|
//========= Copyright � 1996-2005, 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; }
void Init( IPhysicsObject *pRef, IPhysicsObject *pAttached, float flLength, bool rigid = false ) { objectPosition[0] = vec3_origin; objectPosition[1] = vec3_origin; totalLength = flLength; 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
|