1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048 |
- /*
- ===========================================================================
- Doom 3 GPL Source Code
- Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
- This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
- Doom 3 Source Code is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
- Doom 3 Source Code is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
- In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
- If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
- ===========================================================================
- */
- #ifndef __PHYSICS_AF_H__
- #define __PHYSICS_AF_H__
- /*
- ===================================================================================
- Articulated Figure physics
- Employs a constraint force based dynamic simulation using a lagrangian
- multiplier method to solve for the constraint forces.
- ===================================================================================
- */
- class idAFConstraint;
- class idAFConstraint_Fixed;
- class idAFConstraint_BallAndSocketJoint;
- class idAFConstraint_BallAndSocketJointFriction;
- class idAFConstraint_UniversalJoint;
- class idAFConstraint_UniversalJointFriction;
- class idAFConstraint_CylindricalJoint;
- class idAFConstraint_Hinge;
- class idAFConstraint_HingeFriction;
- class idAFConstraint_HingeSteering;
- class idAFConstraint_Slider;
- class idAFConstraint_Line;
- class idAFConstraint_Plane;
- class idAFConstraint_Spring;
- class idAFConstraint_Contact;
- class idAFConstraint_ContactFriction;
- class idAFConstraint_ConeLimit;
- class idAFConstraint_PyramidLimit;
- class idAFConstraint_Suspension;
- class idAFBody;
- class idAFTree;
- class idPhysics_AF;
- typedef enum {
- CONSTRAINT_INVALID,
- CONSTRAINT_FIXED,
- CONSTRAINT_BALLANDSOCKETJOINT,
- CONSTRAINT_UNIVERSALJOINT,
- CONSTRAINT_HINGE,
- CONSTRAINT_HINGESTEERING,
- CONSTRAINT_SLIDER,
- CONSTRAINT_CYLINDRICALJOINT,
- CONSTRAINT_LINE,
- CONSTRAINT_PLANE,
- CONSTRAINT_SPRING,
- CONSTRAINT_CONTACT,
- CONSTRAINT_FRICTION,
- CONSTRAINT_CONELIMIT,
- CONSTRAINT_PYRAMIDLIMIT,
- CONSTRAINT_SUSPENSION
- } constraintType_t;
- //===============================================================
- //
- // idAFConstraint
- //
- //===============================================================
- // base class for all constraints
- class idAFConstraint {
- friend class idPhysics_AF;
- friend class idAFTree;
- public:
- idAFConstraint( void );
- virtual ~idAFConstraint( void );
- constraintType_t GetType( void ) const { return type; }
- const idStr & GetName( void ) const { return name; }
- idAFBody * GetBody1( void ) const { return body1; }
- idAFBody * GetBody2( void ) const { return body2; }
- void SetPhysics( idPhysics_AF *p ) { physics = p; }
- const idVecX & GetMultiplier( void );
- virtual void SetBody1( idAFBody *body );
- virtual void SetBody2( idAFBody *body );
- virtual void DebugDraw( void );
- virtual void GetForce( idAFBody *body, idVec6 &force );
- virtual void Translate( const idVec3 &translation );
- virtual void Rotate( const idRotation &rotation );
- virtual void GetCenter( idVec3 ¢er );
- virtual void Save( idSaveGame *saveFile ) const;
- virtual void Restore( idRestoreGame *saveFile );
- protected:
- constraintType_t type; // constraint type
- idStr name; // name of constraint
- idAFBody * body1; // first constrained body
- idAFBody * body2; // second constrained body, NULL for world
- idPhysics_AF * physics; // for adding additional constraints like limits
- // simulation variables set by Evaluate
- idMatX J1, J2; // matrix with left hand side of constraint equations
- idVecX c1, c2; // right hand side of constraint equations
- idVecX lo, hi, e; // low and high bounds and lcp epsilon
- idAFConstraint * boxConstraint; // constraint the boxIndex refers to
- int boxIndex[6]; // indexes for special box constrained variables
- // simulation variables used during calculations
- idMatX invI; // transformed inertia
- idMatX J; // transformed constraint matrix
- idVecX s; // temp solution
- idVecX lm; // lagrange multipliers
- int firstIndex; // index of the first constraint row in the lcp matrix
- struct constraintFlags_s {
- bool allowPrimary : 1; // true if the constraint can be used as a primary constraint
- bool frameConstraint : 1; // true if this constraint is added to the frame constraints
- bool noCollision : 1; // true if body1 and body2 never collide with each other
- bool isPrimary : 1; // true if this is a primary constraint
- bool isZero : 1; // true if 's' is zero during calculations
- } fl;
- protected:
- virtual void Evaluate( float invTimeStep );
- virtual void ApplyFriction( float invTimeStep );
- void InitSize( int size );
- };
- // fixed or rigid joint which allows zero degrees of freedom
- // constrains body1 to have a fixed position and orientation relative to body2
- class idAFConstraint_Fixed : public idAFConstraint {
- public:
- idAFConstraint_Fixed( const idStr &name, idAFBody *body1, idAFBody *body2 );
- void SetRelativeOrigin( const idVec3 &origin ) { this->offset = origin; }
- void SetRelativeAxis( const idMat3 &axis ) { this->relAxis = axis; }
- virtual void SetBody1( idAFBody *body );
- virtual void SetBody2( idAFBody *body );
- virtual void DebugDraw( void );
- virtual void Translate( const idVec3 &translation );
- virtual void Rotate( const idRotation &rotation );
- virtual void GetCenter( idVec3 ¢er );
- virtual void Save( idSaveGame *saveFile ) const;
- virtual void Restore( idRestoreGame *saveFile );
- protected:
- idVec3 offset; // offset of body1 relative to body2 in body2 space
- idMat3 relAxis; // rotation of body1 relative to body2
- protected:
- virtual void Evaluate( float invTimeStep );
- virtual void ApplyFriction( float invTimeStep );
- void InitOffset( void );
- };
- // ball and socket or spherical joint which allows 3 degrees of freedom
- // constrains body1 relative to body2 with a ball and socket joint
- class idAFConstraint_BallAndSocketJoint : public idAFConstraint {
- public:
- idAFConstraint_BallAndSocketJoint( const idStr &name, idAFBody *body1, idAFBody *body2 );
- ~idAFConstraint_BallAndSocketJoint( void );
- void SetAnchor( const idVec3 &worldPosition );
- idVec3 GetAnchor( void ) const;
- void SetNoLimit( void );
- void SetConeLimit( const idVec3 &coneAxis, const float coneAngle, const idVec3 &body1Axis );
- void SetPyramidLimit( const idVec3 &pyramidAxis, const idVec3 &baseAxis,
- const float angle1, const float angle2, const idVec3 &body1Axis );
- void SetLimitEpsilon( const float e );
- void SetFriction( const float f ) { friction = f; }
- float GetFriction( void ) const;
- virtual void DebugDraw( void );
- virtual void GetForce( idAFBody *body, idVec6 &force );
- virtual void Translate( const idVec3 &translation );
- virtual void Rotate( const idRotation &rotation );
- virtual void GetCenter( idVec3 ¢er );
- virtual void Save( idSaveGame *saveFile ) const;
- virtual void Restore( idRestoreGame *saveFile );
- protected:
- idVec3 anchor1; // anchor in body1 space
- idVec3 anchor2; // anchor in body2 space
- float friction; // joint friction
- idAFConstraint_ConeLimit *coneLimit; // cone shaped limit
- idAFConstraint_PyramidLimit *pyramidLimit; // pyramid shaped limit
- idAFConstraint_BallAndSocketJointFriction *fc; // friction constraint
- protected:
- virtual void Evaluate( float invTimeStep );
- virtual void ApplyFriction( float invTimeStep );
- };
- // ball and socket joint friction
- class idAFConstraint_BallAndSocketJointFriction : public idAFConstraint {
- public:
- idAFConstraint_BallAndSocketJointFriction( void );
- void Setup( idAFConstraint_BallAndSocketJoint *cc );
- bool Add( idPhysics_AF *phys, float invTimeStep );
- virtual void Translate( const idVec3 &translation );
- virtual void Rotate( const idRotation &rotation );
- protected:
- idAFConstraint_BallAndSocketJoint *joint;
- protected:
- virtual void Evaluate( float invTimeStep );
- virtual void ApplyFriction( float invTimeStep );
- };
- // universal, Cardan or Hooke joint which allows 2 degrees of freedom
- // like a ball and socket joint but also constrains the rotation about the cardan shafts
- class idAFConstraint_UniversalJoint : public idAFConstraint {
- public:
- idAFConstraint_UniversalJoint( const idStr &name, idAFBody *body1, idAFBody *body2 );
- ~idAFConstraint_UniversalJoint( void );
- void SetAnchor( const idVec3 &worldPosition );
- idVec3 GetAnchor( void ) const;
- void SetShafts( const idVec3 &cardanShaft1, const idVec3 &cardanShaft2 );
- void GetShafts( idVec3 &cardanShaft1, idVec3 &cardanShaft2 ) { cardanShaft1 = shaft1; cardanShaft2 = shaft2; }
- void SetNoLimit( void );
- void SetConeLimit( const idVec3 &coneAxis, const float coneAngle );
- void SetPyramidLimit( const idVec3 &pyramidAxis, const idVec3 &baseAxis,
- const float angle1, const float angle2 );
- void SetLimitEpsilon( const float e );
- void SetFriction( const float f ) { friction = f; }
- float GetFriction( void ) const;
- virtual void DebugDraw( void );
- virtual void GetForce( idAFBody *body, idVec6 &force );
- virtual void Translate( const idVec3 &translation );
- virtual void Rotate( const idRotation &rotation );
- virtual void GetCenter( idVec3 ¢er );
- virtual void Save( idSaveGame *saveFile ) const;
- virtual void Restore( idRestoreGame *saveFile );
- protected:
- idVec3 anchor1; // anchor in body1 space
- idVec3 anchor2; // anchor in body2 space
- idVec3 shaft1; // body1 cardan shaft in body1 space
- idVec3 shaft2; // body2 cardan shaft in body2 space
- idVec3 axis1; // cardan axis in body1 space
- idVec3 axis2; // cardan axis in body2 space
- float friction; // joint friction
- idAFConstraint_ConeLimit *coneLimit; // cone shaped limit
- idAFConstraint_PyramidLimit *pyramidLimit; // pyramid shaped limit
- idAFConstraint_UniversalJointFriction *fc; // friction constraint
- protected:
- virtual void Evaluate( float invTimeStep );
- virtual void ApplyFriction( float invTimeStep );
- };
- // universal joint friction
- class idAFConstraint_UniversalJointFriction : public idAFConstraint {
- public:
- idAFConstraint_UniversalJointFriction( void );
- void Setup( idAFConstraint_UniversalJoint *cc );
- bool Add( idPhysics_AF *phys, float invTimeStep );
- virtual void Translate( const idVec3 &translation );
- virtual void Rotate( const idRotation &rotation );
- protected:
- idAFConstraint_UniversalJoint *joint; // universal joint
- protected:
- virtual void Evaluate( float invTimeStep );
- virtual void ApplyFriction( float invTimeStep );
- };
- // cylindrical joint which allows 2 degrees of freedom
- // constrains body1 to lie on a line relative to body2 and allows only translation along and rotation about the line
- class idAFConstraint_CylindricalJoint : public idAFConstraint {
- public:
- idAFConstraint_CylindricalJoint( const idStr &name, idAFBody *body1, idAFBody *body2 );
- virtual void DebugDraw( void );
- virtual void Translate( const idVec3 &translation );
- virtual void Rotate( const idRotation &rotation );
- protected:
- protected:
- virtual void Evaluate( float invTimeStep );
- virtual void ApplyFriction( float invTimeStep );
- };
- // hinge, revolute or pin joint which allows 1 degree of freedom
- // constrains all motion of body1 relative to body2 except the rotation about the hinge axis
- class idAFConstraint_Hinge : public idAFConstraint {
- public:
- idAFConstraint_Hinge( const idStr &name, idAFBody *body1, idAFBody *body2 );
- ~idAFConstraint_Hinge( void );
- void SetAnchor( const idVec3 &worldPosition );
- idVec3 GetAnchor( void ) const;
- void SetAxis( const idVec3 &axis );
- void GetAxis( idVec3 &a1, idVec3 &a2 ) const { a1 = axis1; a2 = axis2; }
- idVec3 GetAxis( void ) const;
- void SetNoLimit( void );
- void SetLimit( const idVec3 &axis, const float angle, const idVec3 &body1Axis );
- void SetLimitEpsilon( const float e );
- float GetAngle( void ) const;
- void SetSteerAngle( const float degrees );
- void SetSteerSpeed( const float speed );
- void SetFriction( const float f ) { friction = f; }
- float GetFriction( void ) const;
- virtual void DebugDraw( void );
- virtual void GetForce( idAFBody *body, idVec6 &force );
- virtual void Translate( const idVec3 &translation );
- virtual void Rotate( const idRotation &rotation );
- virtual void GetCenter( idVec3 ¢er );
- virtual void Save( idSaveGame *saveFile ) const;
- virtual void Restore( idRestoreGame *saveFile );
- protected:
- idVec3 anchor1; // anchor in body1 space
- idVec3 anchor2; // anchor in body2 space
- idVec3 axis1; // axis in body1 space
- idVec3 axis2; // axis in body2 space
- idMat3 initialAxis; // initial axis of body1 relative to body2
- float friction; // hinge friction
- idAFConstraint_ConeLimit *coneLimit; // cone limit
- idAFConstraint_HingeSteering *steering; // steering
- idAFConstraint_HingeFriction *fc; // friction constraint
- protected:
- virtual void Evaluate( float invTimeStep );
- virtual void ApplyFriction( float invTimeStep );
- };
- // hinge joint friction
- class idAFConstraint_HingeFriction : public idAFConstraint {
- public:
- idAFConstraint_HingeFriction( void );
- void Setup( idAFConstraint_Hinge *cc );
- bool Add( idPhysics_AF *phys, float invTimeStep );
- virtual void Translate( const idVec3 &translation );
- virtual void Rotate( const idRotation &rotation );
- protected:
- idAFConstraint_Hinge * hinge; // hinge
- protected:
- virtual void Evaluate( float invTimeStep );
- virtual void ApplyFriction( float invTimeStep );
- };
- // constrains two bodies attached to each other with a hinge to get a specified relative orientation
- class idAFConstraint_HingeSteering : public idAFConstraint {
- public:
- idAFConstraint_HingeSteering( void );
- void Setup( idAFConstraint_Hinge *cc );
- void SetSteerAngle( const float degrees ) { steerAngle = degrees; }
- void SetSteerSpeed( const float speed ) { steerSpeed = speed; }
- void SetEpsilon( const float e ) { epsilon = e; }
- bool Add( idPhysics_AF *phys, float invTimeStep );
- virtual void Translate( const idVec3 &translation );
- virtual void Rotate( const idRotation &rotation );
- virtual void Save( idSaveGame *saveFile ) const;
- virtual void Restore( idRestoreGame *saveFile );
- protected:
- idAFConstraint_Hinge * hinge; // hinge
- float steerAngle; // desired steer angle in degrees
- float steerSpeed; // steer speed
- float epsilon; // lcp epsilon
- protected:
- virtual void Evaluate( float invTimeStep );
- virtual void ApplyFriction( float invTimeStep );
- };
- // slider, prismatic or translational constraint which allows 1 degree of freedom
- // constrains body1 to lie on a line relative to body2, the orientation is also fixed relative to body2
- class idAFConstraint_Slider : public idAFConstraint {
- public:
- idAFConstraint_Slider( const idStr &name, idAFBody *body1, idAFBody *body2 );
- void SetAxis( const idVec3 &ax );
- virtual void DebugDraw( void );
- virtual void Translate( const idVec3 &translation );
- virtual void Rotate( const idRotation &rotation );
- virtual void GetCenter( idVec3 ¢er );
- virtual void Save( idSaveGame *saveFile ) const;
- virtual void Restore( idRestoreGame *saveFile );
- protected:
- idVec3 axis; // axis along which body1 slides in body2 space
- idVec3 offset; // offset of body1 relative to body2
- idMat3 relAxis; // rotation of body1 relative to body2
- protected:
- virtual void Evaluate( float invTimeStep );
- virtual void ApplyFriction( float invTimeStep );
- };
- // line constraint which allows 4 degrees of freedom
- // constrains body1 to lie on a line relative to body2, does not constrain the orientation.
- class idAFConstraint_Line : public idAFConstraint {
- public:
- idAFConstraint_Line( const idStr &name, idAFBody *body1, idAFBody *body2 );
- virtual void DebugDraw( void );
- virtual void Translate( const idVec3 &translation );
- virtual void Rotate( const idRotation &rotation );
- protected:
- protected:
- virtual void Evaluate( float invTimeStep );
- virtual void ApplyFriction( float invTimeStep );
- };
- // plane constraint which allows 5 degrees of freedom
- // constrains body1 to lie in a plane relative to body2, does not constrain the orientation.
- class idAFConstraint_Plane : public idAFConstraint {
- public:
- idAFConstraint_Plane( const idStr &name, idAFBody *body1, idAFBody *body2 );
- void SetPlane( const idVec3 &normal, const idVec3 &anchor );
- virtual void DebugDraw( void );
- virtual void Translate( const idVec3 &translation );
- virtual void Rotate( const idRotation &rotation );
- virtual void Save( idSaveGame *saveFile ) const;
- virtual void Restore( idRestoreGame *saveFile );
- protected:
- idVec3 anchor1; // anchor in body1 space
- idVec3 anchor2; // anchor in body2 space
- idVec3 planeNormal; // plane normal in body2 space
- protected:
- virtual void Evaluate( float invTimeStep );
- virtual void ApplyFriction( float invTimeStep );
- };
- // spring constraint which allows 6 or 5 degrees of freedom based on the spring limits
- // constrains body1 relative to body2 with a spring
- class idAFConstraint_Spring : public idAFConstraint {
- public:
- idAFConstraint_Spring( const idStr &name, idAFBody *body1, idAFBody *body2 );
- void SetAnchor( const idVec3 &worldAnchor1, const idVec3 &worldAnchor2 );
- void SetSpring( const float stretch, const float compress, const float damping, const float restLength );
- void SetLimit( const float minLength, const float maxLength );
- virtual void DebugDraw( void );
- virtual void Translate( const idVec3 &translation );
- virtual void Rotate( const idRotation &rotation );
- virtual void GetCenter( idVec3 ¢er );
- virtual void Save( idSaveGame *saveFile ) const;
- virtual void Restore( idRestoreGame *saveFile );
- protected:
- idVec3 anchor1; // anchor in body1 space
- idVec3 anchor2; // anchor in body2 space
- float kstretch; // spring constant when stretched
- float kcompress; // spring constant when compressed
- float damping; // spring damping
- float restLength; // rest length of spring
- float minLength; // minimum spring length
- float maxLength; // maximum spring length
- protected:
- virtual void Evaluate( float invTimeStep );
- virtual void ApplyFriction( float invTimeStep );
- };
- // constrains body1 to either be in contact with or move away from body2
- class idAFConstraint_Contact : public idAFConstraint {
- public:
- idAFConstraint_Contact( void );
- ~idAFConstraint_Contact( void );
- void Setup( idAFBody *b1, idAFBody *b2, contactInfo_t &c );
- const contactInfo_t & GetContact( void ) const { return contact; }
- virtual void DebugDraw( void );
- virtual void Translate( const idVec3 &translation );
- virtual void Rotate( const idRotation &rotation );
- virtual void GetCenter( idVec3 ¢er );
- protected:
- contactInfo_t contact; // contact information
- idAFConstraint_ContactFriction *fc; // contact friction
- protected:
- virtual void Evaluate( float invTimeStep );
- virtual void ApplyFriction( float invTimeStep );
- };
- // contact friction
- class idAFConstraint_ContactFriction : public idAFConstraint {
- public:
- idAFConstraint_ContactFriction( void );
- void Setup( idAFConstraint_Contact *cc );
- bool Add( idPhysics_AF *phys, float invTimeStep );
- virtual void DebugDraw( void );
- virtual void Translate( const idVec3 &translation );
- virtual void Rotate( const idRotation &rotation );
- protected:
- idAFConstraint_Contact *cc; // contact constraint
- protected:
- virtual void Evaluate( float invTimeStep );
- virtual void ApplyFriction( float invTimeStep );
- };
- // constrains an axis attached to body1 to be inside a cone relative to body2
- class idAFConstraint_ConeLimit : public idAFConstraint {
- public:
- idAFConstraint_ConeLimit( void );
- void Setup( idAFBody *b1, idAFBody *b2, const idVec3 &coneAnchor, const idVec3 &coneAxis,
- const float coneAngle, const idVec3 &body1Axis );
- void SetAnchor( const idVec3 &coneAnchor );
- void SetBody1Axis( const idVec3 &body1Axis );
- void SetEpsilon( const float e ) { epsilon = e; }
- bool Add( idPhysics_AF *phys, float invTimeStep );
- virtual void DebugDraw( void );
- virtual void Translate( const idVec3 &translation );
- virtual void Rotate( const idRotation &rotation );
- virtual void Save( idSaveGame *saveFile ) const;
- virtual void Restore( idRestoreGame *saveFile );
- protected:
- idVec3 coneAnchor; // top of the cone in body2 space
- idVec3 coneAxis; // cone axis in body2 space
- idVec3 body1Axis; // axis in body1 space that should stay within the cone
- float cosAngle; // cos( coneAngle / 2 )
- float sinHalfAngle; // sin( coneAngle / 4 )
- float cosHalfAngle; // cos( coneAngle / 4 )
- float epsilon; // lcp epsilon
- protected:
- virtual void Evaluate( float invTimeStep );
- virtual void ApplyFriction( float invTimeStep );
- };
- // constrains an axis attached to body1 to be inside a pyramid relative to body2
- class idAFConstraint_PyramidLimit : public idAFConstraint {
- public:
- idAFConstraint_PyramidLimit( void );
- void Setup( idAFBody *b1, idAFBody *b2, const idVec3 &pyramidAnchor,
- const idVec3 &pyramidAxis, const idVec3 &baseAxis,
- const float pyramidAngle1, const float pyramidAngle2, const idVec3 &body1Axis );
- void SetAnchor( const idVec3 &pyramidAxis );
- void SetBody1Axis( const idVec3 &body1Axis );
- void SetEpsilon( const float e ) { epsilon = e; }
- bool Add( idPhysics_AF *phys, float invTimeStep );
- virtual void DebugDraw( void );
- virtual void Translate( const idVec3 &translation );
- virtual void Rotate( const idRotation &rotation );
- virtual void Save( idSaveGame *saveFile ) const;
- virtual void Restore( idRestoreGame *saveFile );
- protected:
- idVec3 pyramidAnchor; // top of the pyramid in body2 space
- idMat3 pyramidBasis; // pyramid basis in body2 space with base[2] being the pyramid axis
- idVec3 body1Axis; // axis in body1 space that should stay within the cone
- float cosAngle[2]; // cos( pyramidAngle / 2 )
- float sinHalfAngle[2]; // sin( pyramidAngle / 4 )
- float cosHalfAngle[2]; // cos( pyramidAngle / 4 )
- float epsilon; // lcp epsilon
- protected:
- virtual void Evaluate( float invTimeStep );
- virtual void ApplyFriction( float invTimeStep );
- };
- // vehicle suspension
- class idAFConstraint_Suspension : public idAFConstraint {
- public:
- idAFConstraint_Suspension( void );
- void Setup( const char *name, idAFBody *body, const idVec3 &origin, const idMat3 &axis, idClipModel *clipModel );
- void SetSuspension( const float up, const float down, const float k, const float d, const float f );
- void SetSteerAngle( const float degrees ) { steerAngle = degrees; }
- void EnableMotor( const bool enable ) { motorEnabled = enable; }
- void SetMotorForce( const float force ) { motorForce = force; }
- void SetMotorVelocity( const float vel ) { motorVelocity = vel; }
- void SetEpsilon( const float e ) { epsilon = e; }
- const idVec3 GetWheelOrigin( void ) const;
- virtual void DebugDraw( void );
- virtual void Translate( const idVec3 &translation );
- virtual void Rotate( const idRotation &rotation );
- protected:
- idVec3 localOrigin; // position of suspension relative to body1
- idMat3 localAxis; // orientation of suspension relative to body1
- float suspensionUp; // suspension up movement
- float suspensionDown; // suspension down movement
- float suspensionKCompress; // spring compress constant
- float suspensionDamping; // spring damping
- float steerAngle; // desired steer angle in degrees
- float friction; // friction
- bool motorEnabled; // whether the motor is enabled or not
- float motorForce; // motor force
- float motorVelocity; // desired velocity
- idClipModel * wheelModel; // wheel model
- idVec3 wheelOffset; // wheel position relative to body1
- trace_t trace; // contact point with the ground
- float epsilon; // lcp epsilon
- protected:
- virtual void Evaluate( float invTimeStep );
- virtual void ApplyFriction( float invTimeStep );
- };
- //===============================================================
- //
- // idAFBody
- //
- //===============================================================
- typedef struct AFBodyPState_s {
- idVec3 worldOrigin; // position in world space
- idMat3 worldAxis; // axis at worldOrigin
- idVec6 spatialVelocity; // linear and rotational velocity of body
- idVec6 externalForce; // external force and torque applied to body
- } AFBodyPState_t;
- class idAFBody {
- friend class idPhysics_AF;
- friend class idAFTree;
- public:
- idAFBody( void );
- idAFBody( const idStr &name, idClipModel *clipModel, float density );
- ~idAFBody( void );
- void Init( void );
- const idStr & GetName( void ) const { return name; }
- const idVec3 & GetWorldOrigin( void ) const { return current->worldOrigin; }
- const idMat3 & GetWorldAxis( void ) const { return current->worldAxis; }
- const idVec3 & GetLinearVelocity( void ) const { return current->spatialVelocity.SubVec3(0); }
- const idVec3 & GetAngularVelocity( void ) const { return current->spatialVelocity.SubVec3(1); }
- idVec3 GetPointVelocity( const idVec3 &point ) const;
- const idVec3 & GetCenterOfMass( void ) const { return centerOfMass; }
- void SetClipModel( idClipModel *clipModel );
- idClipModel * GetClipModel( void ) const { return clipModel; }
- void SetClipMask( const int mask ) { clipMask = mask; fl.clipMaskSet = true; }
- int GetClipMask( void ) const { return clipMask; }
- void SetSelfCollision( const bool enable ) { fl.selfCollision = enable; }
- void SetWorldOrigin( const idVec3 &origin ) { current->worldOrigin = origin; }
- void SetWorldAxis( const idMat3 &axis ) { current->worldAxis = axis; }
- void SetLinearVelocity( const idVec3 &linear ) const { current->spatialVelocity.SubVec3(0) = linear; }
- void SetAngularVelocity( const idVec3 &angular ) const { current->spatialVelocity.SubVec3(1) = angular; }
- void SetFriction( float linear, float angular, float contact );
- float GetContactFriction( void ) const { return contactFriction; }
- void SetBouncyness( float bounce );
- float GetBouncyness( void ) const { return bouncyness; }
- void SetDensity( float density, const idMat3 &inertiaScale = mat3_identity );
- float GetInverseMass( void ) const { return invMass; }
- idMat3 GetInverseWorldInertia( void ) const { return current->worldAxis.Transpose() * inverseInertiaTensor * current->worldAxis; }
- void SetFrictionDirection( const idVec3 &dir );
- bool GetFrictionDirection( idVec3 &dir ) const;
- void SetContactMotorDirection( const idVec3 &dir );
- bool GetContactMotorDirection( idVec3 &dir ) const;
- void SetContactMotorVelocity( float vel ) { contactMotorVelocity = vel; }
- float GetContactMotorVelocity( void ) const { return contactMotorVelocity; }
- void SetContactMotorForce( float force ) { contactMotorForce = force; }
- float GetContactMotorForce( void ) const { return contactMotorForce; }
- void AddForce( const idVec3 &point, const idVec3 &force );
- void InverseWorldSpatialInertiaMultiply( idVecX &dst, const float *v ) const;
- idVec6 & GetResponseForce( int index ) { return reinterpret_cast<idVec6 &>(response[ index * 8 ]); }
- void Save( idSaveGame *saveFile );
- void Restore( idRestoreGame *saveFile );
- private:
- // properties
- idStr name; // name of body
- idAFBody * parent; // parent of this body
- idList<idAFBody *> children; // children of this body
- idClipModel * clipModel; // model used for collision detection
- idAFConstraint * primaryConstraint; // primary constraint (this->constraint->body1 = this)
- idList<idAFConstraint *>constraints; // all constraints attached to this body
- idAFTree * tree; // tree structure this body is part of
- float linearFriction; // translational friction
- float angularFriction; // rotational friction
- float contactFriction; // friction with contact surfaces
- float bouncyness; // bounce
- int clipMask; // contents this body collides with
- idVec3 frictionDir; // specifies a single direction of friction in body space
- idVec3 contactMotorDir; // contact motor direction
- float contactMotorVelocity; // contact motor velocity
- float contactMotorForce; // maximum force applied to reach the motor velocity
- // derived properties
- float mass; // mass of body
- float invMass; // inverse mass
- idVec3 centerOfMass; // center of mass of body
- idMat3 inertiaTensor; // inertia tensor
- idMat3 inverseInertiaTensor; // inverse inertia tensor
- // physics state
- AFBodyPState_t state[2];
- AFBodyPState_t * current; // current physics state
- AFBodyPState_t * next; // next physics state
- AFBodyPState_t saved; // saved physics state
- idVec3 atRestOrigin; // origin at rest
- idMat3 atRestAxis; // axis at rest
- // simulation variables used during calculations
- idMatX inverseWorldSpatialInertia; // inverse spatial inertia in world space
- idMatX I, invI; // transformed inertia
- idMatX J; // transformed constraint matrix
- idVecX s; // temp solution
- idVecX totalForce; // total force acting on body
- idVecX auxForce; // force from auxiliary constraints
- idVecX acceleration; // acceleration
- float * response; // forces on body in response to auxiliary constraint forces
- int * responseIndex; // index to response forces
- int numResponses; // number of response forces
- int maxAuxiliaryIndex; // largest index of an auxiliary constraint constraining this body
- int maxSubTreeAuxiliaryIndex; // largest index of an auxiliary constraint constraining this body or one of it's children
- struct bodyFlags_s {
- bool clipMaskSet : 1; // true if this body has a clip mask set
- bool selfCollision : 1; // true if this body can collide with other bodies of this AF
- bool spatialInertiaSparse: 1; // true if the spatial inertia matrix is sparse
- bool useFrictionDir : 1; // true if a single friction direction should be used
- bool useContactMotorDir : 1; // true if a contact motor should be used
- bool isZero : 1; // true if 's' is zero during calculations
- } fl;
- };
- //===============================================================
- //
- // idAFTree
- //
- //===============================================================
- class idAFTree {
- friend class idPhysics_AF;
- public:
- void Factor( void ) const;
- void Solve( int auxiliaryIndex = 0 ) const;
- void Response( const idAFConstraint *constraint, int row, int auxiliaryIndex ) const;
- void CalculateForces( float timeStep ) const;
- void SetMaxSubTreeAuxiliaryIndex( void );
- void SortBodies( void );
- void SortBodies_r( idList<idAFBody*>&sortedList, idAFBody *body );
- void DebugDraw( const idVec4 &color ) const;
- private:
- idList<idAFBody *> sortedBodies;
- };
- //===============================================================
- //
- // idPhysics_AF
- //
- //===============================================================
- typedef struct AFPState_s {
- int atRest; // >= 0 if articulated figure is at rest
- float noMoveTime; // time the articulated figure is hardly moving
- float activateTime; // time since last activation
- float lastTimeStep; // last time step
- idVec6 pushVelocity; // velocity with which the af is pushed
- } AFPState_t;
- typedef struct AFCollision_s {
- trace_t trace;
- idAFBody * body;
- } AFCollision_t;
- class idPhysics_AF : public idPhysics_Base {
- public:
- CLASS_PROTOTYPE( idPhysics_AF );
- idPhysics_AF( void );
- ~idPhysics_AF( void );
- void Save( idSaveGame *savefile ) const;
- void Restore( idRestoreGame *savefile );
- // initialisation
- int AddBody( idAFBody *body ); // returns body id
- void AddConstraint( idAFConstraint *constraint );
- void AddFrameConstraint( idAFConstraint *constraint );
- // force a body to have a certain id
- void ForceBodyId( idAFBody *body, int newId );
- // get body or constraint id
- int GetBodyId( idAFBody *body ) const;
- int GetBodyId( const char *bodyName ) const;
- int GetConstraintId( idAFConstraint *constraint ) const;
- int GetConstraintId( const char *constraintName ) const;
- // number of bodies and constraints
- int GetNumBodies( void ) const;
- int GetNumConstraints( void ) const;
- // retrieve body or constraint
- idAFBody * GetBody( const char *bodyName ) const;
- idAFBody * GetBody( const int id ) const;
- idAFBody * GetMasterBody( void ) const { return masterBody; }
- idAFConstraint * GetConstraint( const char *constraintName ) const;
- idAFConstraint * GetConstraint( const int id ) const;
- // delete body or constraint
- void DeleteBody( const char *bodyName );
- void DeleteBody( const int id );
- void DeleteConstraint( const char *constraintName );
- void DeleteConstraint( const int id );
- // get all the contact constraints acting on the body
- int GetBodyContactConstraints( const int id, idAFConstraint_Contact *contacts[], int maxContacts ) const;
- // set the default friction for bodies
- void SetDefaultFriction( float linear, float angular, float contact );
- // suspend settings
- void SetSuspendSpeed( const idVec2 &velocity, const idVec2 &acceleration );
- // set the time and tolerances used to determine if the simulation can be suspended when the figure hardly moves for a while
- void SetSuspendTolerance( const float noMoveTime, const float translationTolerance, const float rotationTolerance );
- // set minimum and maximum simulation time in seconds
- void SetSuspendTime( const float minTime, const float maxTime );
- // set the time scale value
- void SetTimeScale( const float ts ) { timeScale = ts; }
- // set time scale ramp
- void SetTimeScaleRamp( const float start, const float end );
- // set the joint friction scale
- void SetJointFrictionScale( const float scale ) { jointFrictionScale = scale; }
- // set joint friction dent
- void SetJointFrictionDent( const float dent, const float start, const float end );
- // get the current joint friction scale
- float GetJointFrictionScale( void ) const;
- // set the contact friction scale
- void SetContactFrictionScale( const float scale ) { contactFrictionScale = scale; }
- // set contact friction dent
- void SetContactFrictionDent( const float dent, const float start, const float end );
- // get the current contact friction scale
- float GetContactFrictionScale( void ) const;
- // enable or disable collision detection
- void SetCollision( const bool enable ) { enableCollision = enable; }
- // enable or disable self collision
- void SetSelfCollision( const bool enable ) { selfCollision = enable; }
- // enable or disable coming to a dead stop
- void SetComeToRest( bool enable ) { comeToRest = enable; }
- // call when structure of articulated figure changes
- void SetChanged( void ) { changedAF = true; }
- // enable/disable activation by impact
- void EnableImpact( void );
- void DisableImpact( void );
- // lock of unlock the world constraints
- void LockWorldConstraints( const bool lock ) { worldConstraintsLocked = lock; }
- // set force pushable
- void SetForcePushable( const bool enable ) { forcePushable = enable; }
- // update the clip model positions
- void UpdateClipModels( void );
- public: // common physics interface
- void SetClipModel( idClipModel *model, float density, int id = 0, bool freeOld = true );
- idClipModel * GetClipModel( int id = 0 ) const;
- int GetNumClipModels( void ) const;
- void SetMass( float mass, int id = -1 );
- float GetMass( int id = -1 ) const;
- void SetContents( int contents, int id = -1 );
- int GetContents( int id = -1 ) const;
- const idBounds & GetBounds( int id = -1 ) const;
- const idBounds & GetAbsBounds( int id = -1 ) const;
- bool Evaluate( int timeStepMSec, int endTimeMSec );
- void UpdateTime( int endTimeMSec );
- int GetTime( void ) const;
- void GetImpactInfo( const int id, const idVec3 &point, impactInfo_t *info ) const;
- void ApplyImpulse( const int id, const idVec3 &point, const idVec3 &impulse );
- void AddForce( const int id, const idVec3 &point, const idVec3 &force );
- bool IsAtRest( void ) const;
- int GetRestStartTime( void ) const;
- void Activate( void );
- void PutToRest( void );
- bool IsPushable( void ) const;
- void SaveState( void );
- void RestoreState( void );
- void SetOrigin( const idVec3 &newOrigin, int id = -1 );
- void SetAxis( const idMat3 &newAxis, int id = -1 );
- void Translate( const idVec3 &translation, int id = -1 );
- void Rotate( const idRotation &rotation, int id = -1 );
- const idVec3 & GetOrigin( int id = 0 ) const;
- const idMat3 & GetAxis( int id = 0 ) const;
- void SetLinearVelocity( const idVec3 &newLinearVelocity, int id = 0 );
- void SetAngularVelocity( const idVec3 &newAngularVelocity, int id = 0 );
- const idVec3 & GetLinearVelocity( int id = 0 ) const;
- const idVec3 & GetAngularVelocity( int id = 0 ) const;
- void ClipTranslation( trace_t &results, const idVec3 &translation, const idClipModel *model ) const;
- void ClipRotation( trace_t &results, const idRotation &rotation, const idClipModel *model ) const;
- int ClipContents( const idClipModel *model ) const;
- void DisableClip( void );
- void EnableClip( void );
- void UnlinkClip( void );
- void LinkClip( void );
- bool EvaluateContacts( void );
- void SetPushed( int deltaTime );
- const idVec3 & GetPushedLinearVelocity( const int id = 0 ) const;
- const idVec3 & GetPushedAngularVelocity( const int id = 0 ) const;
- void SetMaster( idEntity *master, const bool orientated = true );
- void WriteToSnapshot( idBitMsgDelta &msg ) const;
- void ReadFromSnapshot( const idBitMsgDelta &msg );
- private:
- // articulated figure
- idList<idAFTree *> trees; // tree structures
- idList<idAFBody *> bodies; // all bodies
- idList<idAFConstraint *>constraints; // all frame independent constraints
- idList<idAFConstraint *>primaryConstraints; // list with primary constraints
- idList<idAFConstraint *>auxiliaryConstraints; // list with auxiliary constraints
- idList<idAFConstraint *>frameConstraints; // constraints that only live one frame
- idList<idAFConstraint_Contact *>contactConstraints; // contact constraints
- idList<int> contactBodies; // body id for each contact
- idList<AFCollision_t> collisions; // collisions
- bool changedAF; // true when the articulated figure just changed
- // properties
- float linearFriction; // default translational friction
- float angularFriction; // default rotational friction
- float contactFriction; // default friction with contact surfaces
- float bouncyness; // default bouncyness
- float totalMass; // total mass of articulated figure
- float forceTotalMass; // force this total mass
- idVec2 suspendVelocity; // simulation may not be suspended if a body has more velocity
- idVec2 suspendAcceleration; // simulation may not be suspended if a body has more acceleration
- float noMoveTime; // suspend simulation if hardly any movement for this many seconds
- float noMoveTranslation; // maximum translation considered no movement
- float noMoveRotation; // maximum rotation considered no movement
- float minMoveTime; // if > 0 the simulation is never suspended before running this many seconds
- float maxMoveTime; // if > 0 the simulation is always suspeded after running this many seconds
- float impulseThreshold; // threshold below which impulses are ignored to avoid continuous activation
- float timeScale; // the time is scaled with this value for slow motion effects
- float timeScaleRampStart; // start of time scale change
- float timeScaleRampEnd; // end of time scale change
- float jointFrictionScale; // joint friction scale
- float jointFrictionDent; // joint friction dives from 1 to this value and goes up again
- float jointFrictionDentStart; // start time of joint friction dent
- float jointFrictionDentEnd; // end time of joint friction dent
- float jointFrictionDentScale; // dent scale
- float contactFrictionScale; // contact friction scale
- float contactFrictionDent; // contact friction dives from 1 to this value and goes up again
- float contactFrictionDentStart; // start time of contact friction dent
- float contactFrictionDentEnd; // end time of contact friction dent
- float contactFrictionDentScale; // dent scale
- bool enableCollision; // if true collision detection is enabled
- bool selfCollision; // if true the self collision is allowed
- bool comeToRest; // if true the figure can come to rest
- bool linearTime; // if true use the linear time algorithm
- bool noImpact; // if true do not activate when another object collides
- bool worldConstraintsLocked; // if true world constraints cannot be moved
- bool forcePushable; // if true can be pushed even when bound to a master
- // physics state
- AFPState_t current;
- AFPState_t saved;
- idAFBody * masterBody; // master body
- idLCP * lcp; // linear complementarity problem solver
- private:
- void BuildTrees( void );
- bool IsClosedLoop( const idAFBody *body1, const idAFBody *body2 ) const;
- void PrimaryFactor( void );
- void EvaluateBodies( float timeStep );
- void EvaluateConstraints( float timeStep );
- void AddFrameConstraints( void );
- void RemoveFrameConstraints( void );
- void ApplyFriction( float timeStep, float endTimeMSec );
- void PrimaryForces( float timeStep );
- void AuxiliaryForces( float timeStep );
- void VerifyContactConstraints( void );
- void SetupContactConstraints( void );
- void ApplyContactForces( void );
- void Evolve( float timeStep );
- idEntity * SetupCollisionForBody( idAFBody *body ) const;
- bool CollisionImpulse( float timeStep, idAFBody *body, trace_t &collision );
- bool ApplyCollisions( float timeStep );
- void CheckForCollisions( float timeStep );
- void ClearExternalForce( void );
- void AddGravity( void );
- void SwapStates( void );
- bool TestIfAtRest( float timeStep );
- void Rest( void );
- void AddPushVelocity( const idVec6 &pushVelocity );
- void DebugDraw( void );
- };
- #endif /* !__PHYSICS_AF_H__ */
|