2011-11-22 21:28:15 +00:00
|
|
|
/*
|
|
|
|
===========================================================================
|
|
|
|
|
|
|
|
Doom 3 GPL Source Code
|
2011-12-06 18:20:15 +00:00
|
|
|
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
|
2011-11-22 21:28:15 +00:00
|
|
|
|
2011-12-06 16:14:59 +00:00
|
|
|
This file is part of the Doom 3 GPL Source Code ("Doom 3 Source Code").
|
2011-11-22 21:28:15 +00:00
|
|
|
|
|
|
|
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__
|
|
|
|
|
2011-12-16 22:28:29 +00:00
|
|
|
#include "idlib/math/Lcp.h"
|
|
|
|
|
|
|
|
#include "physics/Physics_Base.h"
|
|
|
|
|
2011-11-22 21:28:15 +00:00
|
|
|
/*
|
|
|
|
===================================================================================
|
|
|
|
|
|
|
|
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__ */
|