mirror of
https://github.com/id-Software/DOOM-3-BFG.git
synced 2024-12-02 17:02:17 +00:00
1246 lines
43 KiB
C++
1246 lines
43 KiB
C++
/*
|
|
===========================================================================
|
|
|
|
Doom 3 BFG Edition GPL Source Code
|
|
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
|
|
|
|
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
|
|
|
|
Doom 3 BFG Edition 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 BFG Edition 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 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
In addition, the Doom 3 BFG Edition 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 BFG Edition 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();
|
|
virtual ~idAFConstraint();
|
|
constraintType_t GetType() const
|
|
{
|
|
return type;
|
|
}
|
|
const idStr& GetName() const
|
|
{
|
|
return name;
|
|
}
|
|
idAFBody* GetBody1() const
|
|
{
|
|
return body1;
|
|
}
|
|
idAFBody* GetBody2() const
|
|
{
|
|
return body2;
|
|
}
|
|
void SetPhysics( idPhysics_AF* p )
|
|
{
|
|
physics = p;
|
|
}
|
|
const idVecX& GetMultiplier();
|
|
virtual void SetBody1( idAFBody* body );
|
|
virtual void SetBody2( idAFBody* body );
|
|
virtual void DebugDraw();
|
|
virtual void GetForce( idAFBody* body, idVec6& force );
|
|
virtual void Translate( const idVec3& translation );
|
|
virtual void Rotate( const idRotation& rotation );
|
|
virtual void GetCenter( idVec3& center );
|
|
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();
|
|
virtual void Translate( const idVec3& translation );
|
|
virtual void Rotate( const idRotation& rotation );
|
|
virtual void GetCenter( idVec3& center );
|
|
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();
|
|
};
|
|
|
|
// 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 SetAnchor( const idVec3& worldPosition );
|
|
idVec3 GetAnchor() const;
|
|
void SetNoLimit();
|
|
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() const;
|
|
virtual void DebugDraw();
|
|
virtual void GetForce( idAFBody* body, idVec6& force );
|
|
virtual void Translate( const idVec3& translation );
|
|
virtual void Rotate( const idRotation& rotation );
|
|
virtual void GetCenter( idVec3& center );
|
|
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 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 SetAnchor( const idVec3& worldPosition );
|
|
idVec3 GetAnchor() const;
|
|
void SetShafts( const idVec3& cardanShaft1, const idVec3& cardanShaft2 );
|
|
void GetShafts( idVec3& cardanShaft1, idVec3& cardanShaft2 )
|
|
{
|
|
cardanShaft1 = shaft1;
|
|
cardanShaft2 = shaft2;
|
|
}
|
|
void SetNoLimit();
|
|
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() const;
|
|
virtual void DebugDraw();
|
|
virtual void GetForce( idAFBody* body, idVec6& force );
|
|
virtual void Translate( const idVec3& translation );
|
|
virtual void Rotate( const idRotation& rotation );
|
|
virtual void GetCenter( idVec3& center );
|
|
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 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();
|
|
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 SetAnchor( const idVec3& worldPosition );
|
|
idVec3 GetAnchor() const;
|
|
void SetAxis( const idVec3& axis );
|
|
void GetAxis( idVec3& a1, idVec3& a2 ) const
|
|
{
|
|
a1 = axis1;
|
|
a2 = axis2;
|
|
}
|
|
idVec3 GetAxis() const;
|
|
void SetNoLimit();
|
|
void SetLimit( const idVec3& axis, const float angle, const idVec3& body1Axis );
|
|
void SetLimitEpsilon( const float e );
|
|
float GetAngle() const;
|
|
void SetSteerAngle( const float degrees );
|
|
void SetSteerSpeed( const float speed );
|
|
void SetFriction( const float f )
|
|
{
|
|
friction = f;
|
|
}
|
|
float GetFriction() const;
|
|
virtual void DebugDraw();
|
|
virtual void GetForce( idAFBody* body, idVec6& force );
|
|
virtual void Translate( const idVec3& translation );
|
|
virtual void Rotate( const idRotation& rotation );
|
|
virtual void GetCenter( idVec3& center );
|
|
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 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 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();
|
|
virtual void Translate( const idVec3& translation );
|
|
virtual void Rotate( const idRotation& rotation );
|
|
virtual void GetCenter( idVec3& center );
|
|
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();
|
|
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();
|
|
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();
|
|
virtual void Translate( const idVec3& translation );
|
|
virtual void Rotate( const idRotation& rotation );
|
|
virtual void GetCenter( idVec3& center );
|
|
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();
|
|
~idAFConstraint_Contact();
|
|
void Setup( idAFBody* b1, idAFBody* b2, contactInfo_t& c );
|
|
const contactInfo_t& GetContact() const
|
|
{
|
|
return contact;
|
|
}
|
|
virtual void DebugDraw();
|
|
virtual void Translate( const idVec3& translation );
|
|
virtual void Rotate( const idRotation& rotation );
|
|
virtual void GetCenter( idVec3& center );
|
|
|
|
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 Setup( idAFConstraint_Contact* cc );
|
|
bool Add( idPhysics_AF* phys, float invTimeStep );
|
|
virtual void DebugDraw();
|
|
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 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();
|
|
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 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();
|
|
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 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() const;
|
|
|
|
virtual void DebugDraw();
|
|
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();
|
|
idAFBody( const idStr& name, idClipModel* clipModel, float density );
|
|
~idAFBody();
|
|
|
|
void Init();
|
|
const idStr& GetName() const
|
|
{
|
|
return name;
|
|
}
|
|
const idVec3& GetWorldOrigin() const
|
|
{
|
|
return current->worldOrigin;
|
|
}
|
|
const idMat3& GetWorldAxis() const
|
|
{
|
|
return current->worldAxis;
|
|
}
|
|
const idVec3& GetLinearVelocity() const
|
|
{
|
|
return current->spatialVelocity.SubVec3( 0 );
|
|
}
|
|
const idVec3& GetAngularVelocity() const
|
|
{
|
|
return current->spatialVelocity.SubVec3( 1 );
|
|
}
|
|
idVec3 GetPointVelocity( const idVec3& point ) const;
|
|
const idVec3& GetCenterOfMass() const
|
|
{
|
|
return centerOfMass;
|
|
}
|
|
void SetClipModel( idClipModel* clipModel );
|
|
idClipModel* GetClipModel() const
|
|
{
|
|
return clipModel;
|
|
}
|
|
void SetClipMask( const int mask )
|
|
{
|
|
clipMask = mask;
|
|
fl.clipMaskSet = true;
|
|
}
|
|
int GetClipMask() 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() const
|
|
{
|
|
return contactFriction;
|
|
}
|
|
void SetBouncyness( float bounce );
|
|
float GetBouncyness() const
|
|
{
|
|
return bouncyness;
|
|
}
|
|
void SetDensity( float density, const idMat3& inertiaScale = mat3_identity );
|
|
float GetInverseMass() const
|
|
{
|
|
return invMass;
|
|
}
|
|
idMat3 GetInverseWorldInertia() 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() const
|
|
{
|
|
return contactMotorVelocity;
|
|
}
|
|
void SetContactMotorForce( float force )
|
|
{
|
|
contactMotorForce = force;
|
|
}
|
|
float GetContactMotorForce() 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*, TAG_IDLIB_LIST_PHYSICS> children; // children of this body
|
|
idClipModel* clipModel; // model used for collision detection
|
|
idAFConstraint* primaryConstraint; // primary constraint (this->constraint->body1 = this)
|
|
idList<idAFConstraint*, TAG_IDLIB_LIST_PHYSICS>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() 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 SortBodies();
|
|
void SortBodies_r( idList<idAFBody*>& sortedList, idAFBody* body );
|
|
void DebugDraw( const idVec4& color ) const;
|
|
|
|
private:
|
|
idList<idAFBody*, TAG_IDLIB_LIST_PHYSICS> 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();
|
|
~idPhysics_AF();
|
|
|
|
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() const;
|
|
int GetNumConstraints() const;
|
|
// retrieve body or constraint
|
|
idAFBody* GetBody( const char* bodyName ) const;
|
|
idAFBody* GetBody( const int id ) const;
|
|
idAFBody* GetMasterBody() 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() 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() 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()
|
|
{
|
|
changedAF = true;
|
|
}
|
|
// enable/disable activation by impact
|
|
void EnableImpact();
|
|
void DisableImpact();
|
|
// 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();
|
|
|
|
public: // common physics interface
|
|
void SetClipModel( idClipModel* model, float density, int id = 0, bool freeOld = true );
|
|
idClipModel* GetClipModel( int id = 0 ) const;
|
|
int GetNumClipModels() 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() 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() const;
|
|
int GetRestStartTime() const;
|
|
void Activate();
|
|
void PutToRest();
|
|
bool IsPushable() const;
|
|
|
|
void SaveState();
|
|
void RestoreState();
|
|
|
|
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 EnableClip();
|
|
|
|
void UnlinkClip();
|
|
void LinkClip();
|
|
|
|
bool EvaluateContacts();
|
|
|
|
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( idBitMsg& msg ) const;
|
|
void ReadFromSnapshot( const idBitMsg& msg );
|
|
|
|
private:
|
|
// articulated figure
|
|
idList<idAFTree*, TAG_IDLIB_LIST_PHYSICS> trees; // tree structures
|
|
idList<idAFBody*, TAG_IDLIB_LIST_PHYSICS> bodies; // all bodies
|
|
idList<idAFConstraint*, TAG_IDLIB_LIST_PHYSICS>constraints; // all frame independent constraints
|
|
idList<idAFConstraint*, TAG_IDLIB_LIST_PHYSICS>primaryConstraints; // list with primary constraints
|
|
idList<idAFConstraint*, TAG_IDLIB_LIST_PHYSICS>auxiliaryConstraints; // list with auxiliary constraints
|
|
idList<idAFConstraint*, TAG_IDLIB_LIST_PHYSICS>frameConstraints; // constraints that only live one frame
|
|
idList<idAFConstraint_Contact*, TAG_IDLIB_LIST_PHYSICS>contactConstraints; // contact constraints
|
|
idList<int, TAG_IDLIB_LIST_PHYSICS> contactBodies; // body id for each contact
|
|
idList<AFCollision_t, TAG_IDLIB_LIST_PHYSICS> 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();
|
|
bool IsClosedLoop( const idAFBody* body1, const idAFBody* body2 ) const;
|
|
void PrimaryFactor();
|
|
void EvaluateBodies( float timeStep );
|
|
void EvaluateConstraints( float timeStep );
|
|
void AddFrameConstraints();
|
|
void RemoveFrameConstraints();
|
|
void ApplyFriction( float timeStep, float endTimeMSec );
|
|
void PrimaryForces( float timeStep );
|
|
void AuxiliaryForces( float timeStep );
|
|
void VerifyContactConstraints();
|
|
void SetupContactConstraints();
|
|
void ApplyContactForces();
|
|
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 AddGravity();
|
|
void SwapStates();
|
|
bool TestIfAtRest( float timeStep );
|
|
void Rest();
|
|
void AddPushVelocity( const idVec6& pushVelocity );
|
|
void DebugDraw();
|
|
};
|
|
|
|
#endif /* !__PHYSICS_AF_H__ */
|