text: //===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======//
  //
  // Purpose: Public interfaces to vphysics DLL
  //
  // $NoKeywords: $
  //===========================================================================//
  
  #ifndef VPHYSICS_INTERFACE_H
  #define VPHYSICS_INTERFACE_H
  #ifdef _WIN32
  #pragma once
  #endif
  
  
  #include "tier1/interface.h"
  #include "mathlib/vector.h"
  #include "mathlib/vector4d.h"
  #include "vcollide.h"
  #include "SoundEmitterSystem/isoundemittersystembase.h"
  
  // ------------------------------------------------------------------------------------
  // UNITS:
  // ------------------------------------------------------------------------------------
  // NOTE:  Coordinates are in HL units.  1 unit == 1 inch.  X is east (forward), Y is north (left), Z is up (up)
  // QAngle are pitch (around y), Yaw (around Z), Roll (around X)
  // AngularImpulse are exponetial maps (an axis in HL units scaled by a "twist" angle in degrees)
  //		They can be transformed like normals/covectors and added linearly
  // mass is kg, volume is in^3, acceleration is in/s^2, velocity is in/s
  
  // density is kg/m^3 (water ~= 998 at room temperature)
  // preferably, these would be in kg/in^3, but the range of those numbers makes them not very human readable
  // having water be about 1000 is really convenient for data entry.
  // Since volume is in in^3 and density is in kg/m^3: 
  //	density = (mass / volume) * CUBIC_METERS_PER_CUBIC_INCH
  // Force is applied using impulses (kg*in/s)
  // Torque is applied using impulses (kg*degrees/s)
  // ------------------------------------------------------------------------------------
  
  #define METERS_PER_INCH					(0.0254f)
  #define CUBIC_METERS_PER_CUBIC_INCH		(METERS_PER_INCH*METERS_PER_INCH*METERS_PER_INCH)
  // 2.2 lbs / kg
  #define POUNDS_PER_KG	(2.2f)
  #define KG_PER_POUND	(1.0f/POUNDS_PER_KG)
  
  // convert from pounds to kg
  #define lbs2kg(x)		((x)*KG_PER_POUND)
  #define kg2lbs(x)		((x)*POUNDS_PER_KG)
  
  const float VPHYSICS_MIN_MASS = 0.1f;
  const float VPHYSICS_MAX_MASS = 5e4f;
  
  class IPhysicsObject;
  class IPhysicsEnvironment;
  class IPhysicsSurfaceProps;
  class IPhysicsConstraint;
  class IPhysicsConstraintGroup;
  class IPhysicsFluidController;
  class IPhysicsSpring;
  class IPhysicsVehicleController;
  class IConvexInfo;
  class IPhysicsObjectPairHash;
  class IPhysicsCollisionSet;
  class IPhysicsPlayerController;
  class IPhysicsFrictionSnapshot;
  
  struct Ray_t;
  struct constraint_ragdollparams_t;
  struct constraint_hingeparams_t;
  struct constraint_fixedparams_t;
  struct constraint_ballsocketparams_t;
  struct constraint_slidingparams_t;
  struct constraint_pulleyparams_t;
  struct constraint_lengthparams_t;
  struct constraint_groupparams_t;
  
  struct vehicleparams_t;
  struct matrix3x4_t;
  
  struct fluidparams_t;
  struct springparams_t;
  struct objectparams_t;
  struct debugcollide_t;
  class CGameTrace;
  typedef CGameTrace trace_t;
  struct physics_stats_t;
  struct physics_performanceparams_t;
  struct virtualmeshparams_t;
  
  //enum PhysInterfaceId_t;
  struct physsaveparams_t;
  struct physrestoreparams_t;
  struct physprerestoreparams_t;
  
  enum PhysInterfaceId_t 
  {
  	PIID_UNKNOWN,
  	PIID_IPHYSICSOBJECT,
  	PIID_IPHYSICSFLUIDCONTROLLER,
  	PIID_IPHYSICSSPRING,
  	PIID_IPHYSICSCONSTRAINTGROUP,
  	PIID_IPHYSICSCONSTRAINT,
  	PIID_IPHYSICSSHADOWCONTROLLER,
  	PIID_IPHYSICSPLAYERCONTROLLER,
  	PIID_IPHYSICSMOTIONCONTROLLER,
  	PIID_IPHYSICSVEHICLECONTROLLER,
  	PIID_IPHYSICSGAMETRACE,
  
  	PIID_NUM_TYPES
  };
  
  
  class ISave;
  class IRestore;
  
  
  #define VPHYSICS_DEBUG_OVERLAY_INTERFACE_VERSION	"VPhysicsDebugOverlay001"
  
  #define PRINTF_FORMAT_STRING
  
  abstract_class IVPhysicsDebugOverlay
  {
  public:
  	virtual void AddEntityTextOverlay(int ent_index, int line_offset, float duration, int r, int g, int b, int a, PRINTF_FORMAT_STRING const char *format, ...) = 0;
  	virtual void AddBoxOverlay(const Vector& origin, const Vector& mins, const Vector& max, QAngle const& orientation, int r, int g, int b, int a, float duration) = 0;
  	virtual void AddTriangleOverlay(const Vector& p1, const Vector& p2, const Vector& p3, int r, int g, int b, int a, bool noDepthTest, float duration) = 0;
  	virtual void AddLineOverlay(const Vector& origin, const Vector& dest, int r, int g, int b,bool noDepthTest, float duration) = 0;
  	virtual void AddTextOverlay(const Vector& origin, float duration, PRINTF_FORMAT_STRING const char *format, ...) = 0;
  	virtual void AddTextOverlay(const Vector& origin, int line_offset, float duration, PRINTF_FORMAT_STRING const char *format, ...) = 0;
  	virtual void AddScreenTextOverlay(float flXPos, float flYPos,float flDuration, int r, int g, int b, int a, const char *text) = 0;
  	virtual void AddSweptBoxOverlay(const Vector& start, const Vector& end, const Vector& mins, const Vector& max, const QAngle & angles, int r, int g, int b, int a, float flDuration) = 0;
  	virtual void AddTextOverlayRGB(const Vector& origin, int line_offset, float duration, float r, float g, float b, float alpha, PRINTF_FORMAT_STRING const char *format, ...) = 0;
  };
  
  #define VPHYSICS_INTERFACE_VERSION	"VPhysics031"
  
  abstract_class IPhysics : public IAppSystem
  {
  public:
  	virtual	IPhysicsEnvironment		*CreateEnvironment( void ) = 0;
  	virtual void DestroyEnvironment( IPhysicsEnvironment * ) = 0;
  	virtual IPhysicsEnvironment		*GetActiveEnvironmentByIndex( int index ) = 0;
  
  	// Creates a fast hash of pairs of objects
  	// Useful for maintaining a table of object relationships like pairs that do not collide.
  	virtual IPhysicsObjectPairHash		*CreateObjectPairHash() = 0;
  	virtual void						DestroyObjectPairHash( IPhysicsObjectPairHash *pHash ) = 0;
  
  	// holds a cache of these by id.  So you can get by id to search for the previously created set
  	// UNDONE: Sets are currently limited to 32 elements.  More elements will return NULL in create.
  	// NOTE: id is not allowed to be zero.
  	virtual IPhysicsCollisionSet		*FindOrCreateCollisionSet( unsigned int id, int maxElementCount ) = 0;
  	virtual IPhysicsCollisionSet		*FindCollisionSet( unsigned int id ) = 0;
  	virtual void						DestroyAllCollisionSets() = 0;
  };
  
  
  // CPhysConvex is a single convex solid
  class CPhysConvex;
  // CPhysPolysoup is an abstract triangle soup mesh
  class CPhysPolysoup;
  class ICollisionQuery;
  class IVPhysicsKeyParser;
  struct convertconvexparams_t;
  class CPackedPhysicsDescription;
  
  class CPolyhedron;
  
  // UNDONE: Find a better place for this?  Should be in collisionutils, but it's needs VPHYSICS' solver.
  struct truncatedcone_t
  {
  	Vector	origin;
  	Vector	normal;
  	float	h;			// height of the cone (hl units)
  	float	theta;		// cone angle (degrees)
  };
  
  
  abstract_class IPhysicsCollision
  {
  public:
  	virtual ~IPhysicsCollision( void ) {}
  
  	// produce a convex element from verts (convex hull around verts)
  	virtual CPhysConvex		*ConvexFromVerts( Vector **pVerts, int vertCount ) = 0;
  	// produce a convex element from planes (csg of planes)
  	virtual CPhysConvex		*ConvexFromPlanes( float *pPlanes, int planeCount, float mergeDistance ) = 0;
  	// calculate volume of a convex element
  	virtual float			ConvexVolume( CPhysConvex *pConvex ) = 0;
  
  	virtual float			ConvexSurfaceArea( CPhysConvex *pConvex ) = 0;
  	// store game-specific data in a convex solid
  	virtual void			SetConvexGameData( CPhysConvex *pConvex, unsigned int gameData ) = 0;
  	// If not converted, free the convex elements with this call
  	virtual void			ConvexFree( CPhysConvex *pConvex ) = 0;
  	virtual CPhysConvex		*BBoxToConvex( const Vector &mins, const Vector &maxs ) = 0;
  	// produce a convex element from a convex polyhedron
  	virtual CPhysConvex		*ConvexFromConvexPolyhedron( const CPolyhedron &ConvexPolyhedron ) = 0;
  	// produce a set of convex triangles from a convex polygon, normal is assumed to be on the side with forward point ordering, which should be clockwise, output will need to be able to hold exactly (iPointCount-2) convexes
  	virtual void			ConvexesFromConvexPolygon( const Vector &vPolyNormal, const Vector *pPoints, int iPointCount, CPhysConvex **pOutput ) = 0;
  
  	// concave objects
  	// create a triangle soup
  	virtual CPhysPolysoup	*PolysoupCreate( void ) = 0;
  	// destroy the container and memory
  	virtual void			PolysoupDestroy( CPhysPolysoup *pSoup ) = 0;
  	// add a triangle to the soup
  	virtual void			PolysoupAddTriangle( CPhysPolysoup *pSoup, const Vector &a, const Vector &b, const Vector &c, int materialIndex7bits ) = 0;
  	// convert the convex into a compiled collision model
  	virtual CPhysCollide *ConvertPolysoupToCollide( CPhysPolysoup *pSoup, bool useMOPP ) = 0;
  	
  	// Convert an array of convex elements to a compiled collision model (this deletes the convex elements)
  	virtual CPhysCollide	*ConvertConvexToCollide( CPhysConvex **pConvex, int convexCount ) = 0;
  	virtual CPhysCollide	*ConvertConvexToCollideParams( CPhysConvex **pConvex, int convexCount, const convertconvexparams_t &convertParams ) = 0;
  	// Free a collide that was created with ConvertConvexToCollide()
  	virtual void			DestroyCollide( CPhysCollide *pCollide ) = 0;
  
  	// Get the memory size in bytes of the collision model for serialization
  	virtual int				CollideSize( CPhysCollide *pCollide ) = 0;
  	// serialize the collide to a block of memory
  	virtual int				CollideWrite( char *pDest, CPhysCollide *pCollide, bool bSwap = false ) = 0;
  	// unserialize the collide from a block of memory
  	virtual CPhysCollide	*UnserializeCollide( char *pBuffer, int size, int index ) = 0;
  
  	// compute the volume of a collide
  	virtual float			CollideVolume( CPhysCollide *pCollide ) = 0;
  	// compute surface area for tools
  	virtual float			CollideSurfaceArea( CPhysCollide *pCollide ) = 0;
  
  	// Get the support map for a collide in the given direction
  	virtual Vector			CollideGetExtent( const CPhysCollide *pCollide, const Vector &collideOrigin, const QAngle &collideAngles, const Vector &direction ) = 0;
  
  	// Get an AABB for an oriented collision model
  	virtual void			CollideGetAABB( Vector *pMins, Vector *pMaxs, const CPhysCollide *pCollide, const Vector &collideOrigin, const QAngle &collideAngles ) = 0;
  
  	virtual void			CollideGetMassCenter( CPhysCollide *pCollide, Vector *pOutMassCenter ) = 0;
  	virtual void			CollideSetMassCenter( CPhysCollide *pCollide, const Vector &massCenter ) = 0;
  	// get the approximate cross-sectional area projected orthographically on the bbox of the collide
  	// NOTE: These are fractional areas - unitless.  Basically this is the fraction of the OBB on each axis that
  	// would be visible if the object were rendered orthographically.
  	// NOTE: This has been precomputed when the collide was built or this function will return 1,1,1
  	virtual Vector			CollideGetOrthographicAreas( const CPhysCollide *pCollide ) = 0;
  	virtual void			CollideSetOrthographicAreas( CPhysCollide *pCollide, const Vector &areas ) = 0;
  
  	// query the vcollide index in the physics model for the instance
  	virtual int				CollideIndex( const CPhysCollide *pCollide ) = 0;
  
  	// Convert a bbox to a collide
  	virtual CPhysCollide	*BBoxToCollide( const Vector &mins, const Vector &maxs ) = 0;
  	virtual int				GetConvexesUsedInCollideable( const CPhysCollide *pCollideable, CPhysConvex **pOutputArray, int iOutputArrayLimit ) = 0;
  
  
  	// Trace an AABB against a collide
  	virtual void TraceBox( const Vector &start, const Vector &end, const Vector &mins, const Vector &maxs, const CPhysCollide *pCollide, const Vector &collideOrigin, const QAngle &collideAngles, trace_t *ptr ) = 0;
  	virtual void TraceBox( const Ray_t &ray, const CPhysCollide *pCollide, const Vector &collideOrigin, const QAngle &collideAngles, trace_t *ptr ) = 0;
  	virtual void TraceBox( const Ray_t &ray, unsigned int contentsMask, IConvexInfo *pConvexInfo, const CPhysCollide *pCollide, const Vector &collideOrigin, const QAngle &collideAngles, trace_t *ptr ) = 0;
  
  	// Trace one collide against another
  	virtual void TraceCollide( const Vector &start, const Vector &end, const CPhysCollide *pSweepCollide, const QAngle &sweepAngles, const CPhysCollide *pCollide, const Vector &collideOrigin, const QAngle &collideAngles, trace_t *ptr ) = 0;
  
  	// relatively slow test for box vs. truncated cone
  	virtual bool			IsBoxIntersectingCone( const Vector &boxAbsMins, const Vector &boxAbsMaxs, const truncatedcone_t &cone ) = 0;
  
  	// loads a set of solids into a vcollide_t
  	virtual void			VCollideLoad( vcollide_t *pOutput, int solidCount, const char *pBuffer, int size, bool swap = false ) = 0;
  	// destroyts the set of solids created by VCollideLoad
  	virtual void			VCollideUnload( vcollide_t *pVCollide ) = 0;
  
  	// begins parsing a vcollide.  NOTE: This keeps pointers to the text
  	// If you free the text and call members of IVPhysicsKeyParser, it will crash
  	virtual IVPhysicsKeyParser	*VPhysicsKeyParserCreate( const char *pKeyData ) = 0;
  	virtual IVPhysicsKeyParser *VPhysicsKeyParserCreate( vcollide_t *pVCollide ) = 0;
  	// Free the parser created by VPhysicsKeyParserCreate
  	virtual void			VPhysicsKeyParserDestroy( IVPhysicsKeyParser *pParser ) = 0;
  
  	// creates a list of verts from a collision mesh
  	virtual int				CreateDebugMesh( CPhysCollide const *pCollisionModel, Vector **outVerts ) = 0;
  	// destroy the list of verts created by CreateDebugMesh
  	virtual void			DestroyDebugMesh( int vertCount, Vector *outVerts ) = 0;
  
  	// create a queryable version of the collision model
  	virtual ICollisionQuery *CreateQueryModel( CPhysCollide *pCollide ) = 0;
  	// destroy the queryable version
  	virtual void			DestroyQueryModel( ICollisionQuery *pQuery ) = 0;
  
  	virtual IPhysicsCollision *ThreadContextCreate( void ) = 0;
  	virtual void			ThreadContextDestroy( IPhysicsCollision *pThreadContex ) = 0;
  
  	virtual CPhysCollide	*CreateVirtualMesh( const virtualmeshparams_t &params ) = 0;
  	virtual bool			SupportsVirtualMesh() = 0;
  
  
  	virtual bool			GetBBoxCacheSize( int *pCachedSize, int *pCachedCount ) = 0;
  
  	
  	// extracts a polyhedron that defines a CPhysConvex's shape
  	virtual CPolyhedron		*PolyhedronFromConvex( CPhysConvex * const pConvex, bool bUseTempPolyhedron ) = 0;
  
  	// dumps info about the collide to Msg()
  	virtual void			OutputDebugInfo( const CPhysCollide *pCollide ) = 0;
  	virtual unsigned int	ReadStat( int statID ) = 0;
  
  	// Get an AABB for an oriented collision model
  	virtual float			CollideGetRadius( const CPhysCollide *pCollide ) = 0;
  
  	virtual void			*VCollideAllocUserData( vcollide_t *pVCollide, size_t userDataSize ) = 0;
  	virtual void			VCollideFreeUserData( vcollide_t *pVCollide ) = 0;
  	virtual void			VCollideCheck( vcollide_t *pVCollide, const char *pName ) = 0;
  	virtual bool			TraceBoxAA( const Ray_t &ray, const CPhysCollide *pCollide, trace_t *ptr ) = 0;
  };
  
  
  
  // this can be used to post-process a collision model
  abstract_class ICollisionQuery
  {
  public:
  	virtual ~ICollisionQuery() {}
  	// number of convex pieces in the whole solid
  	virtual int		ConvexCount( void ) = 0;
  	// triangle count for this convex piece
  	virtual int		TriangleCount( int convexIndex ) = 0;
  	// get the stored game data
  	virtual unsigned int GetGameData( int convexIndex ) = 0;
  	// Gets the triangle's verts to an array
  	virtual void	GetTriangleVerts( int convexIndex, int triangleIndex, Vector *verts ) = 0;
  	
  	// UNDONE: This doesn't work!!!
  	virtual void	SetTriangleVerts( int convexIndex, int triangleIndex, const Vector *verts ) = 0;
  	
  	// returns the 7-bit material index
  	virtual int		GetTriangleMaterialIndex( int convexIndex, int triangleIndex ) = 0;
  	// sets a 7-bit material index for this triangle
  	virtual void	SetTriangleMaterialIndex( int convexIndex, int triangleIndex, int index7bits ) = 0;
  };
  
  //-----------------------------------------------------------------------------
  // Purpose: Ray traces from game engine.
  //-----------------------------------------------------------------------------
  abstract_class IPhysicsGameTrace
  {
  public:
  	virtual void VehicleTraceRay( const Ray_t &ray, void *pVehicle, trace_t *pTrace ) = 0;
  	virtual	void VehicleTraceRayWithWater( const Ray_t &ray, void *pVehicle, trace_t *pTrace ) = 0;
  	virtual bool VehiclePointInWater( const Vector &vecPoint ) = 0;
  };
  
  // The caller should implement this to return contents masks per convex on a collide
  abstract_class IConvexInfo
  {
  public:
  	virtual unsigned int GetContents( int convexGameData ) = 0;
  };
  
  class CPhysicsEventHandler;
  abstract_class IPhysicsCollisionData
  {
  public:
  	virtual void GetSurfaceNormal( Vector &out ) = 0;		// normal points toward second object (object index 1)
  	virtual void GetContactPoint( Vector &out ) = 0;		// contact point of collision (in world space)
  	virtual void GetContactSpeed( Vector &out ) = 0;		// speed of surface 1 relative to surface 0 (in world space)
  };
  
  
  struct vcollisionevent_t
  {
  	IPhysicsObject	*pObjects[2];
  	int				surfaceProps[2];
  	bool			isCollision;
  	bool			isShadowCollision;
  	float			deltaCollisionTime;
  
  	float			collisionSpeed;				// only valid at postCollision
  	IPhysicsCollisionData *pInternalData;		// may change pre/post collision
  };
  
  abstract_class IPhysicsCollisionEvent
  {
  public:
  	// returns the two objects that collided, time between last collision of these objects
  	// and an opaque data block of collision information
  	// NOTE: PreCollision/PostCollision ALWAYS come in matched pairs!!!
  	virtual void PreCollision( vcollisionevent_t *pEvent ) = 0;
  	virtual void PostCollision( vcollisionevent_t *pEvent ) = 0;
  
  	// This is a scrape event.  The object has scraped across another object consuming the indicated energy
  	virtual void Friction( IPhysicsObject *pObject, float energy, int surfaceProps, int surfacePropsHit, IPhysicsCollisionData *pData ) = 0;
  
  	virtual void StartTouch( IPhysicsObject *pObject1, IPhysicsObject *pObject2, IPhysicsCollisionData *pTouchData ) = 0;
  	virtual void EndTouch( IPhysicsObject *pObject1, IPhysicsObject *pObject2, IPhysicsCollisionData *pTouchData ) = 0;
  
  	virtual void FluidStartTouch( IPhysicsObject *pObject, IPhysicsFluidController *pFluid ) = 0;
  	virtual void FluidEndTouch( IPhysicsObject *pObject, IPhysicsFluidController *pFluid ) = 0;
  
  	virtual void PostSimulationFrame() = 0;
  
  	virtual void ObjectEnterTrigger( IPhysicsObject *pTrigger, IPhysicsObject *pObject ) {}
  	virtual void ObjectLeaveTrigger( IPhysicsObject *pTrigger, IPhysicsObject *pObject ) {}
  };
  
  
  abstract_class IPhysicsObjectEvent
  {
  public:
  	// these can be used to optimize out queries on sleeping objects
  	// Called when an object is woken after sleeping
  	virtual void ObjectWake( IPhysicsObject *pObject ) = 0;
  	// called when an object goes to sleep (no longer simulating)
  	virtual void ObjectSleep( IPhysicsObject *pObject ) = 0;
  };
  
  abstract_class IPhysicsConstraintEvent
  {
  public:
  	// the constraint is now inactive, the game code is required to delete it or re-activate it.
  	virtual void ConstraintBroken( IPhysicsConstraint * ) = 0;
  };
  
  struct hlshadowcontrol_params_t
  {
  	Vector			targetPosition;
  	QAngle			targetRotation;
  	float			maxAngular;
  	float			maxDampAngular;
  	float			maxSpeed;
  	float			maxDampSpeed;
  	float			dampFactor;
  	float			teleportDistance;
  };
  
  // UNDONE: At some point allow this to be parameterized using hlshadowcontrol_params_t.
  // All of the infrastructure is in place to do that.
  abstract_class IPhysicsShadowController
  {
  public:
  	virtual ~IPhysicsShadowController( void ) {}
  
  	virtual void Update( const Vector &position, const QAngle &angles, float timeOffset ) = 0;
  	virtual void MaxSpeed( float maxSpeed, float maxAngularSpeed ) = 0;
  	virtual void StepUp( float height ) = 0;
  	
  	// If the teleport distance is non-zero, the object will be teleported to 
  	// the target location when the error exceeds this quantity.
  	virtual void SetTeleportDistance( float teleportDistance ) = 0;
  	virtual bool AllowsTranslation() = 0;
  	virtual bool AllowsRotation() = 0;
  
  	// There are two classes of shadow objects:
  	// 1) Game physics controlled, shadow follows game physics (this is the default)
  	// 2) Physically controlled - shadow position is a target, but the game hasn't guaranteed that the space can be occupied by this object
  	virtual void SetPhysicallyControlled( bool isPhysicallyControlled ) = 0;
  	virtual bool IsPhysicallyControlled() = 0;
  	virtual void GetLastImpulse( Vector *pOut ) = 0;
  	virtual void UseShadowMaterial( bool bUseShadowMaterial ) = 0;
  	virtual void ObjectMaterialChanged( int materialIndex ) = 0;
  
  
  	//Basically get the last inputs to IPhysicsShadowController::Update(), returns last input to timeOffset in Update()
  	virtual float GetTargetPosition( Vector *pPositionOut, QAngle *pAnglesOut ) = 0;
  	
  	virtual float GetTeleportDistance( void ) = 0;
  	virtual void GetMaxSpeed( float *pMaxSpeedOut, float *pMaxAngularSpeedOut ) = 0;
  };
  
  class CPhysicsSimObject;
  class IPhysicsMotionController;
  
  // Callback for simulation
  class IMotionEvent
  {
  public:
  	// These constants instruct the simulator as to how to apply the values copied to linear & angular
  	// GLOBAL/LOCAL refer to the coordinate system of the values, whereas acceleration/force determine whether or not
  	// mass is divided out (forces must be divided by mass to compute acceleration)
  	enum simresult_e { SIM_NOTHING = 0, SIM_LOCAL_ACCELERATION, SIM_LOCAL_FORCE, SIM_GLOBAL_ACCELERATION, SIM_GLOBAL_FORCE };
  	virtual simresult_e	Simulate( IPhysicsMotionController *pController, IPhysicsObject *pObject, float deltaTime, Vector &linear, AngularImpulse &angular ) = 0;
  };
  
  
  
  abstract_class IPhysicsMotionController
  {
  public:
  	virtual ~IPhysicsMotionController( void ) {}
  	virtual void SetEventHandler( IMotionEvent *handler ) = 0;
  	virtual void AttachObject( IPhysicsObject *pObject, bool checkIfAlreadyAttached ) = 0;
  	virtual void DetachObject( IPhysicsObject *pObject ) = 0;
  
  	// returns the number of objects currently attached to the controller
  	virtual int CountObjects( void ) = 0;
  	// NOTE: pObjectList is an array with at least CountObjects() allocated
  	virtual void GetObjects( IPhysicsObject **pObjectList ) = 0;
  	// detaches all attached objects
  	virtual void ClearObjects( void ) = 0;
  	// wakes up all attached objects
  	virtual void WakeObjects( void ) = 0;
  
  	enum priority_t
  	{
  		LOW_PRIORITY = 0,
  		MEDIUM_PRIORITY = 1,
  		HIGH_PRIORITY = 2,
  	};
  	virtual void SetPriority( priority_t priority ) = 0;
  };
  
  // -------------------
  // Collision filter function.  Return 0 if objects should not be tested for collisions, nonzero otherwise
  // Install with IPhysicsEnvironment::SetCollisionFilter()
  // -------------------
  abstract_class IPhysicsCollisionSolver
  {
  public:
  	virtual int ShouldCollide( IPhysicsObject *pObj0, IPhysicsObject *pObj1, void *pGameData0, void *pGameData1 ) = 0;
  	virtual int ShouldSolvePenetration( IPhysicsObject *pObj0, IPhysicsObject *pObj1, void *pGameData0, void *pGameData1, float dt ) = 0;
  	
  	// pObject has already done the max number of collisions this tick, should we freeze it to save CPU?
  	virtual bool ShouldFreezeObject( IPhysicsObject *pObject ) = 0;
  
  	// The system has already done too many collision checks, performance will suffer.
  	// How many more should it do?
  	virtual int AdditionalCollisionChecksThisTick( int currentChecksDone ) = 0;
  
  	// This list of objects is in a connected contact graph that is too large to solve quickly
  	// return true to freeze the system, false to solve it
  	virtual bool ShouldFreezeContacts( IPhysicsObject **pObjectList, int objectCount ) = 0;
  };
  
  enum PhysicsTraceType_t
  {
  	VPHYSICS_TRACE_EVERYTHING = 0,
  	VPHYSICS_TRACE_STATIC_ONLY,
  	VPHYSICS_TRACE_MOVING_ONLY,
  	VPHYSICS_TRACE_TRIGGERS_ONLY,
  	VPHYSICS_TRACE_STATIC_AND_MOVING,
  };
  
  abstract_class IPhysicsTraceFilter
  {
  public:
  	virtual bool ShouldHitObject( IPhysicsObject *pObject, int contentsMask ) = 0;
  	virtual PhysicsTraceType_t	GetTraceType() const = 0;
  };
  
  abstract_class IPhysicsEnvironment
  {
  public:
  	virtual ~IPhysicsEnvironment( void ) {}
  
  	virtual void SetDebugOverlay( CreateInterfaceFn debugOverlayFactory ) = 0;
  	virtual IVPhysicsDebugOverlay *GetDebugOverlay( void ) = 0;
  
  	// gravity is a 3-vector in in/s^2
  	virtual void			SetGravity( const Vector &gravityVector ) = 0;
  	virtual void			GetGravity( Vector *pGravityVector ) const = 0;
  
  	// air density is in kg / m^3 (water is 1000)
  	// This controls drag, air that is more dense has more drag.
  	virtual void			SetAirDensity( float density ) = 0;
  	virtual float			GetAirDensity( void ) const = 0;
  	
  	// object creation
  	// create a polygonal object.  pCollisionModel was created by the physics builder DLL in a pre-process.
  	virtual IPhysicsObject	*CreatePolyObject( const CPhysCollide *pCollisionModel, int materialIndex, const Vector &position, const QAngle &angles, objectparams_t *pParams ) = 0;
  	// same as above, but this one cannot move or rotate (infinite mass/inertia)
  	virtual IPhysicsObject	*CreatePolyObjectStatic( const CPhysCollide *pCollisionModel, int materialIndex, const Vector &position, const QAngle &angles, objectparams_t *pParams ) = 0;
  	// Create a perfectly spherical object
  	virtual IPhysicsObject *CreateSphereObject( float radius, int materialIndex, const Vector &position, const QAngle &angles, objectparams_t *pParams, bool isStatic ) = 0;
  	// destroy an object created with CreatePolyObject() or CreatePolyObjectStatic()
  	virtual void DestroyObject( IPhysicsObject * ) = 0;
  
  	// Create a polygonal fluid body out of the specified collision model
  	// This object will affect any other objects that collide with the collision model
  	virtual IPhysicsFluidController	*CreateFluidController( IPhysicsObject *pFluidObject, fluidparams_t *pParams ) = 0;
  	// Destroy an object created with CreateFluidController()
  	virtual void DestroyFluidController( IPhysicsFluidController * ) = 0;
  
  	// Create a simulated spring that connects 2 objects
  	virtual IPhysicsSpring	*CreateSpring( IPhysicsObject *pObjectStart, IPhysicsObject *pObjectEnd, springparams_t *pParams ) = 0;
  	virtual void DestroySpring( IPhysicsSpring * ) = 0;
  
  	// Create a constraint in the space of pReferenceObject which is attached by the constraint to pAttachedObject
  	virtual IPhysicsConstraint	*CreateRagdollConstraint( IPhysicsObject *pReferenceObject, IPhysicsObject *pAttachedObject, IPhysicsConstraintGroup *pGroup, const constraint_ragdollparams_t &ragdoll ) = 0;
  	virtual IPhysicsConstraint	*CreateHingeConstraint( IPhysicsObject *pReferenceObject, IPhysicsObject *pAttachedObject, IPhysicsConstraintGroup *pGroup, const constraint_hingeparams_t &hinge ) = 0;
  	virtual IPhysicsConstraint	*CreateFixedConstraint( IPhysicsObject *pReferenceObject, IPhysicsObject *pAttachedObject, IPhysicsConstraintGroup *pGroup, const constraint_fixedparams_t &fixed ) = 0;
  	virtual IPhysicsConstraint	*CreateSlidingConstraint( IPhysicsObject *pReferenceObject, IPhysicsObject *pAttachedObject, IPhysicsConstraintGroup *pGroup, const constraint_slidingparams_t &sliding ) = 0;
  	virtual IPhysicsConstraint	*CreateBallsocketConstraint( IPhysicsObject *pReferenceObject, IPhysicsObject *pAttachedObject, IPhysicsConstraintGroup *pGroup, const constraint_ballsocketparams_t &ballsocket ) = 0;
  	virtual IPhysicsConstraint *CreatePulleyConstraint( IPhysicsObject *pReferenceObject, IPhysicsObject *pAttachedObject, IPhysicsConstraintGroup *pGroup, const constraint_pulleyparams_t &pulley ) = 0;
  	virtual IPhysicsConstraint *CreateLengthConstraint( IPhysicsObject *pReferenceObject, IPhysicsObject *pAttachedObject, IPhysicsConstraintGroup *pGroup, const constraint_lengthparams_t &length ) = 0;
  
  	virtual void DestroyConstraint( IPhysicsConstraint * ) = 0;
  
  	virtual IPhysicsConstraintGroup *CreateConstraintGroup( const constraint_groupparams_t &groupParams ) = 0;
  	virtual void DestroyConstraintGroup( IPhysicsConstraintGroup *pGroup ) = 0;
  
  	virtual IPhysicsShadowController *CreateShadowController( IPhysicsObject *pObject, bool allowTranslation, bool allowRotation ) = 0;
  	virtual void						DestroyShadowController( IPhysicsShadowController * ) = 0;
  
  	virtual IPhysicsPlayerController	*CreatePlayerController( IPhysicsObject *pObject ) = 0;
  	virtual void						DestroyPlayerController( IPhysicsPlayerController * ) = 0;
  
  	virtual IPhysicsMotionController	*CreateMotionController( IMotionEvent *pHandler ) = 0;
  	virtual void						DestroyMotionController( IPhysicsMotionController *pController ) = 0;
  
  	virtual IPhysicsVehicleController	*CreateVehicleController( IPhysicsObject *pVehicleBodyObject, const vehicleparams_t &params, unsigned int nVehicleType, IPhysicsGameTrace *pGameTrace ) = 0;
  	virtual void						DestroyVehicleController( IPhysicsVehicleController * ) = 0;
  
  	// install a function to filter collisions/penentration
  	virtual void			SetCollisionSolver( IPhysicsCollisionSolver *pSolver ) = 0;
  
  	// run the simulator for deltaTime seconds
  	virtual void			Simulate( float deltaTime ) = 0;
  	// true if currently running the simulator (i.e. in a callback during physenv->Simulate())
  	virtual bool			IsInSimulation() const = 0;
  
  	// Manage the timestep (period) of the simulator.  The main functions are all integrated with
  	// this period as dt.
  	virtual float			GetSimulationTimestep() const = 0;
  	virtual void			SetSimulationTimestep( float timestep ) = 0;
  
  	// returns the current simulation clock's value.  This is an absolute time.
  	virtual float			GetSimulationTime() const = 0;
  	virtual void			ResetSimulationClock() = 0;
  	// returns the current simulation clock's value at the next frame.  This is an absolute time.
  	virtual float			GetNextFrameTime( void ) const = 0;
  
  	// Collision callbacks (game code collision response)
  	virtual void			SetCollisionEventHandler( IPhysicsCollisionEvent *pCollisionEvents ) = 0;
  	virtual void			SetObjectEventHandler( IPhysicsObjectEvent *pObjectEvents ) = 0;
  	virtual	void			SetConstraintEventHandler( IPhysicsConstraintEvent *pConstraintEvents ) = 0;
  
  	virtual void			SetQuickDelete( bool bQuick ) = 0;
  
  	virtual int				GetActiveObjectCount() const = 0;
  	virtual void			GetActiveObjects( IPhysicsObject **pOutputObjectList ) const = 0;
  	virtual const IPhysicsObject **GetObjectList( int *pOutputObjectCount ) const = 0;
  	virtual bool			TransferObject( IPhysicsObject *pObject, IPhysicsEnvironment *pDestinationEnvironment ) = 0;
  
  	virtual void			CleanupDeleteList( void ) = 0;
  	virtual void			EnableDeleteQueue( bool enable ) = 0;
  
  	// Save/Restore methods
  	virtual bool			Save( const physsaveparams_t &params ) = 0;
  	virtual void			PreRestore( const physprerestoreparams_t &params ) = 0;
  	virtual bool			Restore( const physrestoreparams_t &params ) = 0;
  	virtual void			PostRestore() = 0;
  
  	// Debugging:
  	virtual bool IsCollisionModelUsed( CPhysCollide *pCollide ) const = 0;
  	
  	// Physics world version of the enginetrace API:
  	virtual void TraceRay( const Ray_t &ray, unsigned int fMask, IPhysicsTraceFilter *pTraceFilter, trace_t *pTrace ) = 0;
  	virtual void SweepCollideable( const CPhysCollide *pCollide, const Vector &vecAbsStart, const Vector &vecAbsEnd, 
  		const QAngle &vecAngles, unsigned int fMask, IPhysicsTraceFilter *pTraceFilter, trace_t *pTrace ) = 0;
  
  	// performance tuning
  	virtual void GetPerformanceSettings( physics_performanceparams_t *pOutput ) const = 0;
  	virtual void SetPerformanceSettings( const physics_performanceparams_t *pSettings ) = 0;
  
  	// perf/cost statistics
  	virtual void ReadStats( physics_stats_t *pOutput ) = 0;
  	virtual void ClearStats() = 0;
  
  	virtual unsigned int	GetObjectSerializeSize( IPhysicsObject *pObject ) const = 0;
  	virtual void			SerializeObjectToBuffer( IPhysicsObject *pObject, unsigned char *pBuffer, unsigned int bufferSize ) = 0;
  	virtual IPhysicsObject *UnserializeObjectFromBuffer( void *pGameData, unsigned char *pBuffer, unsigned int bufferSize, bool enableCollisions ) = 0;
  
  
  	virtual void EnableConstraintNotify( bool bEnable ) = 0;
  	virtual void DebugCheckContacts(void) = 0;
  
  	virtual void			SetAlternateGravity( const Vector &gravityVector ) = 0;
  	virtual void			GetAlternateGravity( Vector *pGravityVector ) const = 0;
  
  	virtual float			GetDeltaFrameTime( int maxTicks ) const = 0;
  	virtual void			ForceObjectsToSleep( IPhysicsObject **pList, int listCount ) = 0;
  	
  	//Network prediction related functions
  	virtual void			SetPredicted( bool bPredicted ) = 0; //Interaction with this system and it's objects may not always march forward, sometimes it will get/set data in the past.
  	virtual bool			IsPredicted( void ) = 0;
  	virtual void			SetPredictionCommandNum( int iCommandNum ) = 0; //what command the client is working on right now
  	virtual int				GetPredictionCommandNum( void ) = 0;
  	virtual void			DoneReferencingPreviousCommands( int iCommandNum ) = 0; //won't need data from commands before this one any more
  	virtual void			RestorePredictedSimulation( void ) = 0; //called to restore results from a previous simulation with the same predicted timestamp set
  
  	// destroy a CPhysCollide used in CreatePolyObject()/CreatePolyObjectStatic() when any owning IPhysicsObject is flushed from the queued deletion list.
  	virtual void DestroyCollideOnDeadObjectFlush( CPhysCollide * ) = 0; //should only be used after calling DestroyObject() on all IPhysicsObjects created with it.
  };
  
  enum callbackflags
  {
  	CALLBACK_GLOBAL_COLLISION	= 0x0001,
  	CALLBACK_GLOBAL_FRICTION	= 0x0002,
  	CALLBACK_GLOBAL_TOUCH		= 0x0004,
  	CALLBACK_GLOBAL_TOUCH_STATIC = 0x0008,
  	CALLBACK_SHADOW_COLLISION	= 0x0010,
  	CALLBACK_GLOBAL_COLLIDE_STATIC = 0x0020,
  	CALLBACK_IS_VEHICLE_WHEEL	= 0x0040,
  	CALLBACK_FLUID_TOUCH		= 0x0100,
  	CALLBACK_NEVER_DELETED		= 0x0200,	// HACKHACK: This means this object will never be deleted (set on the world)
  	CALLBACK_MARKED_FOR_DELETE	= 0x0400,	// This allows vphysics to skip some work for this object since it will be
  											// deleted later this frame. (Set automatically by destroy calls)
  	CALLBACK_ENABLING_COLLISION = 0x0800,	// This is active during the time an object is enabling collisions
  											// allows us to skip collisions between "new" objects and objects marked for delete
  	CALLBACK_DO_FLUID_SIMULATION = 0x1000,  // remove this to opt out of fluid simulations
  	CALLBACK_IS_PLAYER_CONTROLLER= 0x2000,	// HACKHACK: Set this on players until player cotrollers are unified with shadow controllers
  	CALLBACK_CHECK_COLLISION_DISABLE = 0x4000,
  	CALLBACK_MARKED_FOR_TEST	= 0x8000,	// debug -- marked object is being debugged
  };
  
  enum collisionhints
  {
  	COLLISION_HINT_DEBRIS		= 0x0001,
  	COLLISION_HINT_STATICSOLID	= 0x0002,
  };
  
  class IPredictedPhysicsObject;
  
  abstract_class IPhysicsObject
  {
  public:
  	virtual ~IPhysicsObject( void ) {}
  
  	// returns true if this object is static/unmoveable
  	// NOTE: returns false for objects that are not created static, but set EnableMotion(false);
  	// Call IsMoveable() to find if the object is static OR has motion disabled
  	virtual bool			IsStatic() const = 0;
  	virtual bool			IsAsleep() const = 0;
  	virtual bool			IsTrigger() const = 0;
  	virtual bool			IsFluid() const = 0;		// fluids are special triggers with fluid controllers attached, they return true to IsTrigger() as well!
  	virtual bool			IsHinged() const = 0;
  	virtual bool			IsCollisionEnabled() const = 0;
  	virtual bool			IsGravityEnabled() const = 0;
  	virtual bool			IsDragEnabled() const = 0;
  	virtual bool			IsMotionEnabled() const = 0;
  	virtual bool			IsMoveable() const = 0;	 // legacy: IsMotionEnabled() && !IsStatic()
  	virtual bool			IsAttachedToConstraint(bool bExternalOnly) const = 0;
  
  	// Enable / disable collisions for this object
  	virtual void			EnableCollisions( bool enable ) = 0;
  	// Enable / disable gravity for this object
  	virtual void			EnableGravity( bool enable ) = 0;
  	// Enable / disable air friction / drag for this object
  	virtual void			EnableDrag( bool enable ) = 0;
  	// Enable / disable motion (pin / unpin the object)
  	virtual void			EnableMotion( bool enable ) = 0;
  
  	// Game can store data in each object (link back to game object)
  	virtual void			SetGameData( void *pGameData ) = 0;
  	virtual void			*GetGameData( void ) const = 0;
  	// This flags word can be defined by the game as well
  	virtual void			SetGameFlags( unsigned short userFlags ) = 0;
  	virtual unsigned short	GetGameFlags( void ) const = 0;
  	virtual void			SetGameIndex( unsigned short gameIndex ) = 0;
  	virtual unsigned short	GetGameIndex( void ) const = 0;
  
  	// setup various callbacks for this object
  	virtual void			SetCallbackFlags( unsigned short callbackflags ) = 0;
  	// get the current callback state for this object
  	virtual unsigned short	GetCallbackFlags( void ) const = 0;
  
  	// "wakes up" an object
  	// NOTE: ALL OBJECTS ARE "Asleep" WHEN CREATED
  	virtual void			Wake( void ) = 0;
  	virtual void			Sleep( void ) = 0;
  	// call this when the collision filter conditions change due to this 
  	// object's state (e.g. changing solid type or collision group)
  	virtual void			RecheckCollisionFilter() = 0;
  	// NOTE: Contact points aren't updated when collision rules change, call this to force an update
  	// UNDONE: Force this in RecheckCollisionFilter() ?
  	virtual void			RecheckContactPoints( bool bSearchForNewContacts = false ) = 0;
  
  	// mass accessors
  	virtual void			SetMass( float mass ) = 0;
  	virtual float			GetMass( void ) const = 0;
  	// get 1/mass (it's cached)
  	virtual float			GetInvMass( void ) const = 0;
  	virtual Vector			GetInertia( void ) const = 0;
  	virtual Vector			GetInvInertia( void ) const = 0;
  	virtual void			SetInertia( const Vector &inertia ) = 0;
  
  	virtual void			SetDamping( const float *speed, const float *rot ) = 0;
  	virtual void			GetDamping( float *speed, float *rot ) const = 0;
  
  	// coefficients are optional, pass either
  	virtual void			SetDragCoefficient( float *pDrag, float *pAngularDrag ) = 0;
  	virtual void			SetBuoyancyRatio( float ratio ) = 0;			// Override bouyancy
  
  	// material index
  	virtual int				GetMaterialIndex() const = 0;
  	virtual void			SetMaterialIndex( int materialIndex ) = 0;
  
  	// contents bits
  	virtual unsigned int	GetContents() const = 0;
  	virtual void			SetContents( unsigned int contents ) = 0;
  
  	// Get the radius if this is a sphere object (zero if this is a polygonal mesh)
  	virtual float			GetSphereRadius() const = 0;
  	// Set the radius on a sphere. May need to force recalculation of contact points
  	virtual void			SetSphereRadius(float radius) = 0;
  	virtual float			GetEnergy() const = 0;
  	virtual Vector			GetMassCenterLocalSpace() const = 0;
  
  	// NOTE: This will teleport the object
  	virtual void			SetPosition( const Vector &worldPosition, const QAngle &angles, bool isTeleport ) = 0;
  	virtual void			SetPositionMatrix( const matrix3x4_t&matrix, bool isTeleport ) = 0;
  
  	virtual void			GetPosition( Vector *worldPosition, QAngle *angles ) const = 0;
  	virtual void			GetPositionMatrix( matrix3x4_t *positionMatrix ) const = 0;
  	// force the velocity to a new value
  	// NOTE: velocity is in worldspace, angularVelocity is relative to the object's 
  	// local axes (just like pev->velocity, pev->avelocity)
  	virtual void			SetVelocity( const Vector *velocity, const AngularImpulse *angularVelocity ) = 0;
  
  	// like the above, but force the change into the simulator immediately
  	virtual void			SetVelocityInstantaneous( const Vector *velocity, const AngularImpulse *angularVelocity ) = 0;
  
  	// NOTE: velocity is in worldspace, angularVelocity is relative to the object's 
  	// local axes (just like pev->velocity, pev->avelocity)
  	virtual void			GetVelocity( Vector *velocity, AngularImpulse *angularVelocity ) const = 0;
  
  	// NOTE: These are velocities, not forces.  i.e. They will have the same effect regardless of
  	// the object's mass or inertia
  	virtual void			AddVelocity( const Vector *velocity, const AngularImpulse *angularVelocity ) = 0;
  	// gets a velocity in the object's local frame of reference at a specific point
  	virtual void			GetVelocityAtPoint( const Vector &worldPosition, Vector *pVelocity ) const = 0;
  	// gets the velocity actually moved by the object in the last simulation update
  	virtual void			GetImplicitVelocity( Vector *velocity, AngularImpulse *angularVelocity ) const = 0;
  	// NOTE:	These are here for convenience, but you can do them yourself by using the matrix
  	//			returned from GetPositionMatrix()
  	// convenient coordinate system transformations (params - dest, src)
  	virtual void			LocalToWorld( Vector *worldPosition, const Vector &localPosition ) const = 0;
  	virtual void			WorldToLocal( Vector *localPosition, const Vector &worldPosition ) const = 0;
  
  	// transforms a vector (no translation) from object-local to world space
  	virtual void			LocalToWorldVector( Vector *worldVector, const Vector &localVector ) const = 0;
  	// transforms a vector (no translation) from world to object-local space
  	virtual void			WorldToLocalVector( Vector *localVector, const Vector &worldVector ) const = 0;
  	
  	// push on an object
  	// force vector is direction & magnitude of impulse kg in / s
  	virtual void			ApplyForceCenter( const Vector &forceVector ) = 0;
  	virtual void			ApplyForceOffset( const Vector &forceVector, const Vector &worldPosition ) = 0;
  	// apply torque impulse.  This will change the angular velocity on the object.
  	// HL Axes, kg degrees / s
  	virtual void			ApplyTorqueCenter( const AngularImpulse &torque ) = 0;
  
  	// Calculates the force/torque on the center of mass for an offset force impulse (pass output to ApplyForceCenter / ApplyTorqueCenter)
  	virtual void			CalculateForceOffset( const Vector &forceVector, const Vector &worldPosition, Vector *centerForce, AngularImpulse *centerTorque ) const = 0;
  	// Calculates the linear/angular velocities on the center of mass for an offset force impulse (pass output to AddVelocity)
  	virtual void			CalculateVelocityOffset( const Vector &forceVector, const Vector &worldPosition, Vector *centerVelocity, AngularImpulse *centerAngularVelocity ) const = 0;
  	// calculate drag scale
  	virtual float			CalculateLinearDrag( const Vector &unitDirection ) const = 0;
  	virtual float			CalculateAngularDrag( const Vector &objectSpaceRotationAxis ) const = 0;
  
  	// returns true if the object is in contact with another object
  	// if true, puts a point on the contact surface in contactPoint, and
  	// a pointer to the object in contactObject
  	// NOTE: You can pass NULL for either to avoid computations
  	// BUGBUG: Use CreateFrictionSnapshot instead of this - this is a simple hack
  	virtual bool			GetContactPoint( Vector *contactPoint, IPhysicsObject **contactObject ) const = 0;
  
  	// refactor this a bit - move some of this to IPhysicsShadowController
  	virtual void			SetShadow( float maxSpeed, float maxAngularSpeed, bool allowPhysicsMovement, bool allowPhysicsRotation ) = 0;
  	virtual void			UpdateShadow( const Vector &targetPosition, const QAngle &targetAngles, bool tempDisableGravity, float timeOffset ) = 0;
  	
  	// returns number of ticks since last Update() call
  	virtual int				GetShadowPosition( Vector *position, QAngle *angles ) const = 0;
  	virtual IPhysicsShadowController *GetShadowController( void ) const = 0;
  	virtual void			RemoveShadowController() = 0;
  	// applies the math of the shadow controller to this object.
  	// for use in your own controllers
  	// returns the new value of secondsToArrival with dt time elapsed
  	virtual float			ComputeShadowControl( const hlshadowcontrol_params_t &params, float secondsToArrival, float dt ) = 0;
  
  
  	virtual const CPhysCollide	*GetCollide( void ) const = 0;
  	virtual const char			*GetName() const = 0;
  
  	virtual void			BecomeTrigger() = 0;
  	virtual void			RemoveTrigger() = 0;
  
  	// sets the object to be hinged.  Fixed it place, but able to rotate around one axis.
  	virtual void			BecomeHinged( int localAxis ) = 0;
  	// resets the object to original state
  	virtual void			RemoveHinged() = 0;
  
  	// used to iterate the contact points of an object
  	virtual IPhysicsFrictionSnapshot *CreateFrictionSnapshot() = 0;
  	virtual void DestroyFrictionSnapshot( IPhysicsFrictionSnapshot *pSnapshot ) = 0;
  
  	// dumps info about the object to Msg()
  	virtual void			OutputDebugInfo() const = 0;
  
  #if OBJECT_WELDING
  	virtual void			WeldToObject( IPhysicsObject *pParent ) = 0;
  	virtual void			RemoveWeld( IPhysicsObject *pOther ) = 0;
  	virtual void			RemoveAllWelds( void ) = 0;
  #endif
  
  	// EnableGravity still determines whether to apply gravity
  	// This flag determines which gravity constant to use for an alternate gravity effect
  	virtual void			SetUseAlternateGravity( bool bSet ) = 0;
  	virtual void			SetCollisionHints( uint32 collisionHints ) = 0;
  	virtual uint32			GetCollisionHints() const = 0;
  
  	inline bool				IsPredicted( void ) const { return GetPredictedInterface() != NULL; } //true if class has an IPredictedPhysicsObject interface
  	virtual IPredictedPhysicsObject *GetPredictedInterface( void ) const = 0;
  	virtual void			SyncWith( IPhysicsObject *pOther ) = 0;
  };
  
  abstract_class IPredictedPhysicsObject : public IPhysicsObject
  {
  public:
  	virtual ~IPredictedPhysicsObject( void ) {}
  
  	virtual void SetErrorDelta_Position( const Vector &vPosition ) = 0;
  	virtual void SetErrorDelta_Velocity( const Vector &vVelocity ) = 0;
  };
  
  
  abstract_class IPhysicsSpring
  {
  public:
  	virtual ~IPhysicsSpring( void ) {}
  	virtual void			GetEndpoints( Vector *worldPositionStart, Vector *worldPositionEnd ) = 0;
  	virtual void			SetSpringConstant( float flSpringContant) = 0;
  	virtual void			SetSpringDamping( float flSpringDamping) = 0;
  	virtual void			SetSpringLength( float flSpringLenght) = 0;
  
  	// Get the starting object
  	virtual IPhysicsObject *GetStartObject( void ) = 0;
  
  	// Get the end object
  	virtual IPhysicsObject *GetEndObject( void ) = 0;
  };
  
  
  //-----------------------------------------------------------------------------
  // Purpose: These properties are defined per-material.  This is accessible at 
  //			each triangle in a collision mesh
  //-----------------------------------------------------------------------------
  struct surfacephysicsparams_t
  {
  // vphysics physical properties
  	float			friction;
  	float			elasticity;				// collision elasticity - used to compute coefficient of restitution
  	float			density;				// physical density (in kg / m^3)
  	float			thickness;				// material thickness if not solid (sheet materials) in inches
  	float			dampening;
  };
  
  struct surfaceaudioparams_t
  {
  // sounds / audio data
  	float			reflectivity;		// like elasticity, but how much sound should be reflected by this surface
  	float			hardnessFactor;	// like elasticity, but only affects impact sound choices
  	float			roughnessFactor;	// like friction, but only affects scrape sound choices
  
  // audio thresholds
  	float			roughThreshold;	// surface roughness > this causes "rough" scrapes, < this causes "smooth" scrapes
  	float			hardThreshold;	// surface hardness > this causes "hard" impacts, < this causes "soft" impacts
  	float			hardVelocityThreshold;	// collision velocity > this causes "hard" impacts, < this causes "soft" impacts
  									// NOTE: Hard impacts must meet both hardnessFactor AND velocity thresholds
  
  	float			highPitchOcclusion;
  	float			midPitchOcclusion;
  	float			lowPitchOcclusion;
  };
  
  struct surfacesoundnames_t
  {
  	unsigned short	walkStepLeft;
  	unsigned short	walkStepRight;
  	unsigned short	runStepLeft;
  	unsigned short	runStepRight;
  
  	unsigned short	impactSoft;
  	unsigned short	impactHard;
  
  	unsigned short	scrapeSmooth;
  	unsigned short	scrapeRough;
  
  	unsigned short	bulletImpact;
  	unsigned short	rolling;
  
  	unsigned short	breakSound;
  	unsigned short	strainSound;
  };
  
  struct surfacesoundhandles_t
  {
  	HSOUNDSCRIPTHASH	walkStepLeft;
  	HSOUNDSCRIPTHASH	walkStepRight;
  	HSOUNDSCRIPTHASH	runStepLeft;
  	HSOUNDSCRIPTHASH	runStepRight;
  
  	HSOUNDSCRIPTHASH	impactSoft;
  	HSOUNDSCRIPTHASH	impactHard;
  
  	HSOUNDSCRIPTHASH	scrapeSmooth;
  	HSOUNDSCRIPTHASH	scrapeRough;
  
  	HSOUNDSCRIPTHASH	bulletImpact;
  	HSOUNDSCRIPTHASH	rolling;
  
  	HSOUNDSCRIPTHASH	breakSound;
  	HSOUNDSCRIPTHASH	strainSound;
  };
  
  struct surfacegameprops_t
  {
  // game movement data
  	float			maxSpeedFactor;			// Modulates player max speed when walking on this surface
  	float			jumpFactor;				// Indicates how much higher the player should jump when on the surface
  // Game-specific data
  	float			penetrationModifier;
  	float			damageModifier;
  	unsigned short	material;
  	// Indicates whether or not the player is on a ladder.
  	unsigned char	climbable;
  	unsigned char	pad;
  
  	unsigned char	hidetargetid;
  
  	float			damageLossPercentPerPenetration;
  };
  
  //-----------------------------------------------------------------------------
  // Purpose: Each different material has an entry like this
  //-----------------------------------------------------------------------------
  struct surfacedata_t
  {
  	surfacephysicsparams_t	physics;	// physics parameters
  	surfaceaudioparams_t	audio;		// audio parameters
  	surfacesoundnames_t		sounds;		// names of linked sounds
  	surfacegameprops_t		game;		// Game data / properties
  
  	surfacesoundhandles_t		soundhandles;
  };
  
  class ISaveRestoreOps;
  
  #define VPHYSICS_SURFACEPROPS_INTERFACE_VERSION	"VPhysicsSurfaceProps001"
  abstract_class IPhysicsSurfaceProps
  {
  public:
  	virtual ~IPhysicsSurfaceProps( void ) {}
  
  	// parses a text file containing surface prop keys
  	virtual int		ParseSurfaceData( const char *pFilename, const char *pTextfile ) = 0;
  	// current number of entries in the database
  	virtual int		SurfacePropCount( void ) const = 0;
  
  	virtual int		GetSurfaceIndex( const char *pSurfacePropName ) const = 0;
  	virtual void	GetPhysicsProperties( int surfaceDataIndex, float *density, float *thickness, float *friction, float *elasticity ) const = 0;
  
  	virtual surfacedata_t	*GetSurfaceData( int surfaceDataIndex ) = 0;
  	virtual const char		*GetString( unsigned short stringTableIndex ) const = 0;
  
  
  	virtual const char		*GetPropName( int surfaceDataIndex ) const = 0;
  
  	// sets the global index table for world materials
  	// UNDONE: Make this per-CPhysCollide
  	virtual void	SetWorldMaterialIndexTable( int *pMapArray, int mapSize ) = 0;
  
  	// NOTE: Same as GetPhysicsProperties, but maybe more convenient
  	virtual void	GetPhysicsParameters( int surfaceDataIndex, surfacephysicsparams_t *pParamsOut ) const = 0;
  
  	virtual ISaveRestoreOps* GetMaterialIndexDataOps() const = 0;
  };
  
  abstract_class IPhysicsFluidController
  {
  public:
  	virtual ~IPhysicsFluidController( void ) {}
  
  	virtual void	SetGameData( void *pGameData ) = 0;
  	virtual void	*GetGameData( void ) const = 0;
  
  	virtual void	GetSurfacePlane( Vector *pNormal, float *pDist ) const = 0;
  	virtual float	GetDensity() const = 0;
  	virtual void	WakeAllSleepingObjects() = 0;
  	virtual int		GetContents() const = 0;
  };
  
  
  //-----------------------------------------------------------------------------
  // Purpose: parameter block for creating fluid dynamic motion
  // UNDONE: Expose additional fluid model paramters?
  //-----------------------------------------------------------------------------
  struct fluidparams_t
  {
  	Vector4D	surfacePlane;	// x,y,z normal, dist (plane constant) fluid surface
  	Vector		currentVelocity; // velocity of the current in inches/second
  	float		damping;		// damping factor for buoyancy (tweak)
  	float		torqueFactor;
  	float		viscosityFactor;
  	void		*pGameData;
  	bool		useAerodynamics;// true if this controller should calculate surface pressure
  	int			contents;
  
  	fluidparams_t() {}
  	fluidparams_t( fluidparams_t const& src )
  	{
  		Vector4DCopy( src.surfacePlane, surfacePlane );
  		VectorCopy( src.currentVelocity, currentVelocity );
  		damping = src.damping;
  		torqueFactor = src.torqueFactor;
  		viscosityFactor = src.viscosityFactor;
  		contents = src.contents;
  	}
  };
  
  //-----------------------------------------------------------------------------
  // Purpose: parameter block for creating linear springs
  // UNDONE: Expose additional spring model paramters?
  //-----------------------------------------------------------------------------
  struct springparams_t
  {
  	springparams_t()
  	{
  		memset( this, 0, sizeof(*this) );
  	}
  	float	constant;		// spring constant
  	float	naturalLength;// relaxed length
  	float	damping;		// damping factor
  	float	relativeDamping;	// relative damping (damping proportional to the change in the relative position of the objects)
  	Vector	startPosition;
  	Vector	endPosition;
  	bool	useLocalPositions;	// start & end Position are in local space to start and end objects if this is true
  	bool	onlyStretch;		// only apply forces when the length is greater than the natural length
  };
  
  //-----------------------------------------------------------------------------
  // Purpose: parameter block for creating polygonal objects
  //-----------------------------------------------------------------------------
  struct objectparams_t
  {
  	Vector		*massCenterOverride;
  	float		mass;
  	float		inertia;
  	float		damping;
  	float		rotdamping;
  	float		rotInertiaLimit;
  	const char	*pName;				// used only for debugging
  	void		*pGameData;
  	float		volume;
  	float		dragCoefficient;
  	bool		enableCollisions;
  };
  
  struct convertconvexparams_t
  {
  	bool		buildOuterConvexHull;
  	bool		buildDragAxisAreas;
  	bool		buildOptimizedTraceTables;
  	bool		checkOptimalTracing;
  	bool		bUseFastApproximateInertiaTensor;
  	bool		bBuildAABBTree;
  	float		dragAreaEpsilon;
  	CPhysConvex *pForcedOuterHull;
  
  	void Defaults()
  	{
  		dragAreaEpsilon = 0.25f; // 0.5in x 0.5in square
  		buildOuterConvexHull = false;
  		buildDragAxisAreas = false;
  		buildOptimizedTraceTables = false;
  		checkOptimalTracing = false;
  		bUseFastApproximateInertiaTensor = false;
  		bBuildAABBTree = false;
  		pForcedOuterHull = NULL;
  	}
  };
  
  //-----------------------------------------------------------------------------
  // Physics interface IDs
  //
  // Note that right now the order of the enum also defines the order of save/load
  
  
  //-----------------------------------------------------------------------------
  // Purpose: parameter blocks for save and load operations
  //-----------------------------------------------------------------------------
  struct physsaveparams_t
  {
  	ISave 				*pSave;
  	void 				*pObject;
  	PhysInterfaceId_t 	type;
  };
  
  struct physrestoreparams_t
  {
  	IRestore 			*pRestore;
  	void 				**ppObject;
  	PhysInterfaceId_t 	type;
  	void 				*pGameData;
  	const char			*pName;				// used only for debugging
  	const CPhysCollide 	*pCollisionModel;
  	IPhysicsEnvironment *pEnvironment;
  	IPhysicsGameTrace	*pGameTrace;
  };
  
  struct physrecreateparams_t
  {
  	void *pOldObject;
  	void *pNewObject;
  };
  
  struct physprerestoreparams_t
  {
  	int recreatedObjectCount;
  	physrecreateparams_t recreatedObjectList[1];
  };
  
  //-------------------------------------
  
  #define DEFINE_PIID( type, enumval ) \
  	template <> inline PhysInterfaceId_t GetPhysIID<type>( type ** ) { return enumval; }
  
  template <class PHYSPTR> inline PhysInterfaceId_t GetPhysIID(PHYSPTR **); // will get link error if no match
  
  DEFINE_PIID( IPhysicsObject, 			PIID_IPHYSICSOBJECT );
  DEFINE_PIID( IPhysicsFluidController, 	PIID_IPHYSICSFLUIDCONTROLLER );
  DEFINE_PIID( IPhysicsSpring, 			PIID_IPHYSICSSPRING );
  DEFINE_PIID( IPhysicsConstraintGroup, 	PIID_IPHYSICSCONSTRAINTGROUP );
  DEFINE_PIID( IPhysicsConstraint, 		PIID_IPHYSICSCONSTRAINT );
  DEFINE_PIID( IPhysicsShadowController, 	PIID_IPHYSICSSHADOWCONTROLLER );
  DEFINE_PIID( IPhysicsPlayerController,	PIID_IPHYSICSPLAYERCONTROLLER );
  DEFINE_PIID( IPhysicsMotionController,	PIID_IPHYSICSMOTIONCONTROLLER );
  DEFINE_PIID( IPhysicsVehicleController,	PIID_IPHYSICSVEHICLECONTROLLER );
  DEFINE_PIID( IPhysicsGameTrace,			PIID_IPHYSICSGAMETRACE );
  
  //-----------------------------------------------------------------------------
  
  #endif // VPHYSICS_INTERFACE_H
  