////////////////////////////////////////////////////////////////////// // // Physics System Interface // // File: physinterface.h // Description : declarations of all physics interfaces and structures // // History: // -:Created by Anton Knyazev // ////////////////////////////////////////////////////////////////////// #ifndef physinterface_h #define physinterface_h #if defined(LINUX) #include "Stream.h" #include "validator.h" #endif enum pe_type { PE_NONE=0, PE_STATIC=1, PE_LIVING=2, PE_RIGID=3, PE_WHEELEDVEHICLE=4, PE_PARTICLE=5, PE_ARTICULATED=6, PE_ROPE=7, PE_SOFT=8 }; enum sim_class { SC_STATIC=0, SC_SLEEPING_RIGID=1, SC_ACTIVE_RIGID=2, SC_LIVING=3, SC_INDEPENDENT=4, SC_TRIGGER=6, SC_DELETED=7 }; class IGeometry; class IPhysicalEntity; class IGeomManager; class IPhysicalWorld; class ICrySizer; struct ILog; IPhysicalEntity *const WORLD_ENTITY = (IPhysicalEntity*)-10; ///////////////////////////////////////////////////////////////////////////////////// //////////////////////////// IPhysicsStreamer Interface ///////////////////////////// ///////////////////////////////////////////////////////////////////////////////////// class IPhysicsStreamer { public: virtual int CreatePhysicalEntity(void *pForeignData,int iForeignData,int iForeignFlags) = 0; virtual int DestroyPhysicalEntity(IPhysicalEntity *pent) = 0; virtual const char *GetForeignName(void *pForeignData,int iForeignData,int iForeignFlags) = 0; }; class CMemStream { // for "fastload" serialization; hopefully it can be made global for the project public: CMemStream() { m_pBuf = new char[m_nSize=0x1000]; m_iPos=0; bDeleteBuf=true; } CMemStream(void *pbuf,int sz) { m_pBuf=(char*)pbuf; m_nSize=sz; m_iPos=0; bDeleteBuf=false; } ~CMemStream() { if (bDeleteBuf) delete[] m_pBuf; } void *GetBuf() { return m_pBuf; } int GetUsedSize() { return m_iPos; } int GetAllocatedSize() { return m_nSize; } template void Write(const ftype &op) { Write(&op, sizeof(op)); } void Write(const void *pbuf, int sz) { if (m_iPos+sz>m_nSize) GrowBuf(sz); if (sz==4) *(int*)m_pBuf = *(int*)pbuf; else memcpy(m_pBuf+m_iPos,pbuf,(unsigned int)sz); m_iPos += sz; } #ifdef _WIN32 _declspec(noinline) //changed by ivo #endif void GrowBuf(int sz) { int prevsz = m_nSize; char *prevbuf = m_pBuf; m_pBuf = new char[m_nSize = (m_iPos+sz-1 & ~0xFFF)+0x1000]; memcpy(m_pBuf, prevbuf, (unsigned int)prevsz); } template void Read(ftype &op) { Read(&op, sizeof(op)); } void Read(void *pbuf, int sz) { if (sz==4) *(int*)pbuf = *(int*)m_pBuf; else memcpy(pbuf,(m_pBuf+m_iPos),(unsigned int)sz); m_iPos += sz; } char *m_pBuf; int m_iPos,m_nSize; bool bDeleteBuf; }; // in physics interface [almost] all parameters are passed via structures // this allows having stable interface methods and flexible default arguments system ////////////////////////// Params structures ///////////////////// ////////// common params struct pe_params { int type; }; struct pe_params_pos : pe_params { // Sets postion and orientation of entity enum entype { type_id=0 }; pe_params_pos() { type=type_id; MARK_UNUSED pos,scale,q,iSimClass; pMtx3x3=0;pMtx3x3T=0;pMtx4x4=0;pMtx4x4T=0; bRecalcBounds=1; } vectorf pos; quaternionf q; float scale; float *pMtx3x3; // optional orientation via 3x3 matrix float *pMtx3x3T; // optional orientation via 3x3 column-major matrix float *pMtx4x4; // optional position and orientation via 4x4 matrix float *pMtx4x4T; // optional position and orientation via 4x4 column-major matrix int iSimClass; int bRecalcBounds; VALIDATORS_START VALIDATOR(pos) VALIDATOR_NORM_MSG(q,"(perhaps non-uniform scaling was used?)",pos) VALIDATOR(scale) VALIDATORS_END }; struct pe_params_bbox : pe_params { enum entype { type_id=14 }; pe_params_bbox() { type=type_id; MARK_UNUSED BBox[0],BBox[1]; } vectorf BBox[2]; VALIDATORS_START VALIDATOR(BBox[0]) VALIDATOR(BBox[1]) VALIDATORS_END }; // If entity represents an interior volume this allows to set outer entity, which will be skipped during tests against // objects that are inside this entity struct pe_params_outer_entity : pe_params { enum entype { type_id=9 }; pe_params_outer_entity() { type=type_id; pOuterEntity=0; pBoundingGeometry=0; } IPhysicalEntity *pOuterEntity; // outer entity for this one (outer entities can form chains) IGeometry *pBoundingGeometry; // optional geometry to test containment }; struct pe_params_part : pe_params { // Sets geometrical parameters of entity part enum entype { type_id=6 }; pe_params_part() { type=type_id; MARK_UNUSED pos,q,scale,partid,ipart,mass,density,pPhysGeom,pPhysGeomProxy; pMtx3x3=0;pMtx3x3T=0;pMtx4x4=0;pMtx4x4T=0; bRecalcBBox=1; flagsOR=flagsColliderOR=0; flagsAND=flagsColliderAND=-1; } int partid; // partid identifier of part int ipart; // optionally, part slot number int bRecalcBBox; // whether entity's bounding box should be recalculated vectorf pos; quaternionf q; float scale; float *pMtx3x3; // optional orientation via 3x3 matrix float *pMtx3x3T; float *pMtx4x4; // optional position and orientation via 4x4 matrix float *pMtx4x4T; unsigned int flagsOR,flagsAND; // new flags = (flags & flagsAND) | flagsOR unsigned int flagsColliderOR,flagsColliderAND; float mass; float density; struct phys_geometry *pPhysGeom,*pPhysGeomProxy; VALIDATORS_START VALIDATOR(pos) VALIDATOR_NORM(q) VALIDATOR(scale) VALIDATORS_END }; struct pe_params_sensors : pe_params { // Attaches optional sensors to entity (sensors raytrace enviroment around entity) enum entype { type_id=7 }; pe_params_sensors() { type=type_id; nSensors=0; pOrigins=0; pDirections=0; } int nSensors; // nSensors number of sensors const vectorf *pOrigins; // pOrigins sensors origins in entity CS const vectorf *pDirections; // pDirections sensors directions (dir*ray length) in entity CS }; struct pe_simulation_params : pe_params { // Sets gravity and maximum time step enum entype { type_id=10 }; pe_simulation_params() { type=type_id; MARK_UNUSED maxTimeStep,gravity,minEnergy,damping,iSimClass, softness,softnessAngular,dampingFreefall,gravityFreefall,mass,density; } int iSimClass; float maxTimeStep; // maximum time step that entity can accept (larger steps will be split) float minEnergy; // minimun of kinetic energy below which entity falls asleep (divided by mass!) float damping; vectorf gravity; float dampingFreefall; // damping and gravity used when there are no collisions, vectorf gravityFreefall; // NOTE: if left unused, gravity value will be substituted (if provided) float mass; float density; float softness,softnessAngular; float softnessGroup,softnessAngularGroup; }; struct pe_params_foreign_data : pe_params { enum entype { type_id=11 }; pe_params_foreign_data() { type=type_id; MARK_UNUSED pForeignData,iForeignData,iForeignFlags; } void *pForeignData; int iForeignData; int iForeignFlags; }; struct pe_params_buoyancy : pe_params { enum entype { type_id=12 }; pe_params_buoyancy() { type=type_id; MARK_UNUSED waterDensity,waterDamping,waterPlane.n,waterPlane.origin,waterEmin,waterResistance,waterFlow; }; float waterDensity; float waterDamping; float waterResistance; vectorf waterFlow; primitives::plane waterPlane; float waterEmin; }; enum phentity_flags { particle_single_contact=0x01,particle_constant_orientation=0x02,particle_no_roll=0x04,particle_no_path_alignment=0x08,particle_no_spin=0x10, lef_push_objects=0x20, lef_push_players=0x40, lef_snap_velocities=0x80, lef_loosen_stuck_checks=0x100, pef_pushable_by_players=0x200, pef_traceable=0x400, particle_traceable=0x400, pef_update=0x800, pef_monitor_state_changes=0x1000, pef_monitor_collisions=0x2000, pef_monitor_impulses=0x4000, pef_never_affect_triggers=0x8000, pef_checksum_received=0x10000, pef_checksum_outofsync=0x20000, pef_fixed_damping=0x40000, pef_custom_poststep=0x80000, pef_always_notify_on_deletion=0x100000, rope_collides=0x200000, rope_traceable=0x400, rope_collides_with_terrain=0x400000, se_skip_longest_edges=0x800000, ref_use_simple_solver=0x1000000 }; struct pe_params_flags : pe_params { enum entype { type_id=15 }; pe_params_flags() { type=type_id; MARK_UNUSED flags,flagsOR,flagsAND; } unsigned int flags; unsigned int flagsOR; unsigned int flagsAND; }; ////////// articulated entity params enum joint_flags { angle0_locked=1, all_angles_locked=7, angle0_limit_reached=010, angle0_auto_kd=0100, joint_no_gravity=01000, joint_isolated_accelerations=02000, joint_expand_hinge=04000, angle0_gimbal_locked=010000 }; struct pe_params_joint : pe_params { enum entype { type_id=5 }; pe_params_joint() { type=type_id; for(int i=0;i<3;i++) MARK_UNUSED limits[0][i],limits[1][i],qdashpot[i],kdashpot[i],bounciness[i],q[i],qext[i],ks[i],kd[i]; bNoUpdate=0; pMtx0=pMtx0T=0; MARK_UNUSED flags,q0,pivot,ranimationTimeStep,nSelfCollidingParts; animationTimeStep = 0.01f; } unsigned int flags; // should be a combination of angle0,1,2_locked, angle0,1,2_auto_kd, joint_no_gravity vectorf pivot; // joint pivot in entity CS quaternionf q0; // orientation of child in parent coordinates that corresponds to angles (0,0,0) float *pMtx0; // same as 3x3 row major matrix float *pMtx0T; // same as 3x3 column major matrix vectorf limits[2]; // limits for each angle vectorf bounciness; // bounciness for each angle (applied when limit is reached) vectorf ks,kd; // stiffness and damping koefficients for each angle angular spring vectorf qdashpot; // limit vicinity where joints starts resisting movement vectorf kdashpot; // when dashpot is activated, this is roughly the angular speed, stopped in 2 sec vectorf q; // angles values vectorf qext; // additional angles values (angle[i] = q[i]+qext[i]; only q[i] is taken into account // while calculating spring torque int op[2]; // body identifiers of parent and child respectively int nSelfCollidingParts,*pSelfCollidingParts; // part ids of only parts that should be checked for self-collision int bNoUpdate; // omit recalculation of body parameters after changing this joint float animationTimeStep; // used to calculate joint velocities of animation float ranimationTimeStep; // 1/animation time step, can be not specified (specifying just saves extra division operation) VALIDATORS_START VALIDATOR(pivot) VALIDATOR_NORM(q0) VALIDATOR(q) VALIDATOR(qext) VALIDATORS_END }; struct pe_params_articulated_body : pe_params { enum entype { type_id=8 }; pe_params_articulated_body() { type=type_id; MARK_UNUSED bGrounded,bInheritVel,bCheckCollisions,bCollisionResp,bExpandHinges; MARK_UNUSED bGrounded,bInheritVel,bCheckCollisions,bCollisionResp, a,wa,w,v,pivot, scaleBounceResponse,posHostPivot; MARK_UNUSED bAwake,pHost,nCollLyingMode, gravityLyingMode,dampingLyingMode,minEnergyLyingMode,iSimType,iSimTypeLyingMode; bApply_dqext=0; bRecalcJoints=1; } int bGrounded; // whether body's pivot is firmly attached to something or free int bCheckCollisions; int bCollisionResp; vectorf pivot; // attachment position for grounded bodies vectorf a; // acceleration of ground for grounded bodies vectorf wa; // angular acceleration of ground for grounded bodies vectorf w; // angular velocity of ground for grounded bodies vectorf v; float scaleBounceResponse; // scales impulsive torque that is applied at a joint that has just reached its limit int bApply_dqext; // adds current dqext to joints velocities. dqext is the speed of external animation and is calculated each time // qext is set for joint (as difference between new value and current value, multiplied by inverse of animation timestep) int bAwake; IPhysicalEntity *pHost; vectorf posHostPivot; int bInheritVel; int nCollLyingMode; vectorf gravityLyingMode; float dampingLyingMode; float minEnergyLyingMode; int iSimType; int iSimTypeLyingMode; int bExpandHinges; int bRecalcJoints; }; ////////// living entity params struct pe_player_dimensions : pe_params { enum entype { type_id=1 }; pe_player_dimensions() { type=type_id; MARK_UNUSED sizeCollider,heightPivot,heightCollider,heightEye,heightHead,headRadius; } float heightPivot; // offset from central ground position that is considered entity center float heightEye; // vertical offset of camera vectorf sizeCollider; // collision cylinder dimensions float heightCollider; // vertical offset of collision geometry center float headRadius; float heightHead; VALIDATORS_START VALIDATOR(heightPivot) VALIDATOR(heightEye) VALIDATOR_RANGE2(sizeCollider,0,100) VALIDATORS_END }; struct pe_player_dynamics : pe_params { enum entype { type_id=4 }; pe_player_dynamics() { type=type_id; MARK_UNUSED kInertia,kAirControl,gravity,nodSpeed,mass, bSwimming,surface_idx,bActive; MARK_UNUSED minSlideAngle,maxClimbAngle,maxJumpAngle,minFallAngle,kAirResistance,bNetwork,maxVelGround; } float kInertia; // inertia koefficient, the more it is, the less inertia is; 0 means no inertia float kAirControl; // air control koefficient 0..1, 1 - special value (total control of movement) float kAirResistance; float gravity; // gravity vector float nodSpeed; int bSwimming; // whether entity is swimming (is not bound to ground plane) float mass; // mass (in kg) int surface_idx; // surface identifier for collisions float minSlideAngle; // if surface slope is more than this angle, player starts sliding (angle is in radians) float maxClimbAngle; // player cannot climb surface which slope is steeper than this angle float maxJumpAngle; // player is not allowed to jump towards ground if this angle is exceeded float minFallAngle; // player starts falling when slope is steeper than this float maxVelGround; // player cannot stand of surfaces that are moving faster than this int bNetwork; int bActive; }; ////////// particle entity params struct pe_params_particle : pe_params { enum entype { type_id=3 }; pe_params_particle() { type=type_id; MARK_UNUSED mass,size,thickness,wspin,accThrust,kAirResistance,kWaterResistance, velocity,heading,accLift,accThrust,gravity,waterGravity; MARK_UNUSED surface_idx, normal,q0,minBounceVel, flags,pColliderToIgnore, iPierceability; } unsigned int flags; // see entity flags float mass; float size; // pseudo-radius float thickness; // thickness when lying on a surface (if left unused, size will be used) vectorf heading; // direction of movement float velocity; // velocity along "heading" float kAirResistance; // air resistance koefficient, F = kv float kWaterResistance; // same for water float accThrust; // acceleration along direction of movement float accLift; // acceleration that lifts particle with the current speed int surface_idx; vectorf wspin; // angular velocity vectorf gravity; vectorf waterGravity; vectorf normal; quaternionf q0; // initial orientation (zero means x along direction of movement, z up) float minBounceVel; IPhysicalEntity *pColliderToIgnore; // physical entity to ignore during collisions int iPierceability; VALIDATORS_START VALIDATOR(mass) VALIDATOR(size) VALIDATOR(thickness) VALIDATOR_NORM(heading) VALIDATOR_NORM(normal) VALIDATOR_NORM(q0) VALIDATORS_END }; ////////// vehicle entity params struct pe_params_car : pe_params { enum entype { type_id=2 }; pe_params_car() { type=type_id; MARK_UNUSED engineMaxRPM,iIntegrationType,axleFriction,enginePower,maxSteer,maxTimeStep,minEnergy,damping,brakeTorque; MARK_UNUSED engineMinRPM,engineShiftUpRPM,engineShiftDownRPM,engineIdleRPM,engineStartRPM,clutchSpeed,nGears,gearRatios,kStabilizer; MARK_UNUSED slipThreshold,gearDirSwitchRPM,kDynFriction,maxBrakingFriction,steerTrackNeutralTurn; } float axleFriction; // friction torque at axes divided by mass of vehicle float enginePower; // power of engine (about 10,000 - 100,000) float maxSteer; // maximum steering angle float engineMaxRPM; // engine torque decreases to 0 after reaching this rotation speed float brakeTorque; int iIntegrationType; // for suspensions; 0-explicit Euler, 1-implicit Euler float maxTimeStep; // maximum time step when vehicle has only wheel contacts float minEnergy; // minimum awake energy when vehicle has only wheel contacts float damping; // damping when vehicle has only wheel contacts float maxBrakingFriction; // limits the the tire friction when handbraked float kStabilizer; // stabilizer force, as a multiplier for kStiffness of respective suspensions int nWheels; // the number of wheels float engineMinRPM; float engineShiftUpRPM; float engineShiftDownRPM; float engineIdleRPM; float engineStartRPM; float clutchSpeed; int nGears; float *gearRatios; float slipThreshold; float gearDirSwitchRPM; float kDynFriction; float steerTrackNeutralTurn; }; struct pe_params_wheel : pe_params { enum entype { type_id=16 }; pe_params_wheel() { type=type_id; iWheel=0; MARK_UNUSED bDriving,iAxle,suspLenMax,minFriction,maxFriction,surface_idx; } int iWheel; int bDriving; int iAxle; float suspLenMax; float minFriction; float maxFriction; int surface_idx; }; ////////// rope entity params struct pe_params_rope : pe_params { enum entype { type_id=13 }; pe_params_rope() { type=type_id; MARK_UNUSED length,mass,bCheckCollisions,collDist,surface_idx,friction,nSegments,pPoints,pVelocities; MARK_UNUSED pEntTiedTo[0],ptTiedTo[0],idPartTiedTo[0],pEntTiedTo[1],ptTiedTo[1],idPartTiedTo[1]; } float length; float mass; int bCheckCollisions; float collDist; int surface_idx; float friction; int nSegments; vectorf *pPoints; vectorf *pVelocities; int iStride; // used in GetParams only IPhysicalEntity *pEntTiedTo[2]; vectorf ptTiedTo[2]; int idPartTiedTo[2]; }; ////////// soft entity params struct pe_params_softbody : pe_params { enum entype { type_id=17 }; pe_params_softbody() { type=type_id; MARK_UNUSED thickness,maxSafeStep,ks,kdRatio,airResistance,wind,nMaxIters, accuracy,friction,impulseScale,explosionScale,collisionImpulseScale,maxCollisionImpulse,collTypes; } float thickness; float maxSafeStep; float ks; float kdRatio; float friction; float airResistance; vectorf wind; int nMaxIters; float accuracy; float impulseScale; float explosionScale; float collisionImpulseScale; float maxCollisionImpulse; int collTypes; }; ////////////////////////// Action structures ///////////////////// ////////// common actions struct pe_action { int type; }; struct pe_action_impulse : pe_action { enum entype { type_id=2 }; pe_action_impulse() { type=type_id; impulse.Set(0,0,0); MARK_UNUSED point,momentum,partid,ipart; iApplyTime=2; iSource=0; } vectorf impulse; vectorf momentum; // r x impulse, optional vectorf point; // point of application, in world CS, optional int partid; // receiver part identifier int ipart; // alternatively, part index can be used int iApplyTime; // 0-apply immediately, 1-apply before the next time step, 2-apply after the next time step int iSource; // reserved for internal use VALIDATORS_START VALIDATOR_RANGE2(impulse,0,1E8f) VALIDATOR_RANGE2(momentum,0,1E8f) VALIDATOR_RANGE2(point,0,1E6f) VALIDATOR_RANGE(ipart,0,10000) VALIDATORS_END }; struct pe_action_reset : pe_action { // Resets dynamic state of an entity enum entype { type_id=4 }; pe_action_reset() { type=type_id; } }; enum constrflags { local_frames=1, world_frames=2 }; struct pe_action_add_constraint : pe_action { enum entype { type_id=5 }; pe_action_add_constraint() { type=type_id; pBuddy=0; MARK_UNUSED pt[0],pt[1],partid[0],partid[1],qframe[0],qframe[1],xlimits[0],yzlimits[0],pConstraintEntity; flags=world_frames; } IPhysicalEntity *pBuddy; vectorf pt[2]; int partid[2]; quaternionf qframe[2]; float xlimits[2]; float yzlimits[2]; unsigned int flags; IPhysicalEntity *pConstraintEntity; }; struct pe_action_remove_constraint : pe_action { enum entype { type_id=6 }; pe_action_remove_constraint() { type=type_id; MARK_UNUSED idConstraint; } int idConstraint; }; struct pe_action_register_coll_event : pe_action { enum entype { type_id=7 }; pe_action_register_coll_event() { type=type_id; } vectorf pt; vectorf n; vectorf v; float collMass; IPhysicalEntity *pCollider; int partid[2]; int idmat[2]; }; struct pe_action_awake : pe_action { enum entype { type_id=8 }; pe_action_awake() { type=type_id; bAwake=1; } int bAwake; }; struct pe_action_remove_all_parts : pe_action { enum entype { type_id=9 }; pe_action_remove_all_parts() { type=type_id; } }; struct pe_action_set_velocity : pe_action { enum entype { type_id=10 }; pe_action_set_velocity() { type=type_id; MARK_UNUSED ipart,partid,v,w; } int ipart; int partid; vectorf v,w; }; ////////// living entity actions struct pe_action_move : pe_action { // movement request for living entities enum entype { type_id=1 }; pe_action_move() { type=type_id; iJump=0; dt=0; MARK_UNUSED dir; } vectorf dir; // dir requested velocity vector int iJump; // jump mode - 1-instant velocity change, 2-just adds to current velocity float dt; // time interval for this action VALIDATORS_START VALIDATOR_RANGE2(dir,0,1000) VALIDATOR_RANGE(dt,0,2) VALIDATORS_END }; ////////// vehicle entity actions struct pe_action_drive : pe_action { enum entype { type_id=3 }; pe_action_drive() { type=type_id; MARK_UNUSED pedal,dpedal,steer,dsteer,bHandBrake,clutch,iGear; } float pedal; // engine pedal absolute value float dpedal; // engine pedal delta float steer; // steering angle absolute value float dsteer; // steering angle delta float clutch; int bHandBrake; int iGear; }; ////////// soft entity actions struct pe_action_attach_points : pe_action { enum entype { type_id=11 }; pe_action_attach_points() { type=type_id; MARK_UNUSED partid,points; nPoints=1; } IPhysicalEntity *pEntity; int partid; int *piVtx; vectorf *points; int nPoints; }; ////////////////////////// Status structures ///////////////////// ////////// common statuses struct pe_status { int type; }; enum status_pos_flags { status_local=1 }; struct pe_status_pos : pe_status { enum entype { type_id=1 }; pe_status_pos() { type=type_id; ipart=partid=-1; flags=0; pMtx3x3=0;pMtx3x3T=0;pMtx4x4=0;pMtx4x4T=0; iSimClass=0; timeBack=0; } int partid; // part identifier, -1 for entire entity int ipart; // optionally, part slot index unsigned int flags; // status_local if part coordinates should be returned in entity CS rather than world CS unsigned int flagsOR; // boolean OR for all parts flags of the object (or just flags for the selected part) unsigned int flagsAND; // boolean AND for all parts flags of the object (or just flags for the selected part) vectorf pos; // position of center vectorf BBox[2]; // bounding box relative to pos (bbox[0]-min, bbox[1]-max) quaternionf q; float scale; int iSimClass; float *pMtx3x3; // optional 3x3 matrix buffer that receives transformation float *pMtx3x3T; // optional 3x3 column-major matrix buffer that receives transformation float *pMtx4x4; // optional 4x4 matrix buffer that receives transformation float *pMtx4x4T; // optional 4x4 column-major matrix buffer that receives transformation IGeometry *pGeom,*pGeomProxy; float timeBack; // can retrieve pervious position; only supported by rigid entities; pos and q; one step back }; struct pe_status_sensors : pe_status { // Requests status of attached to the entity sensors enum entype { type_id=18 }; pe_status_sensors() { type=type_id; } vectorf *pPoints; // pointer to array of points where sensors touch environment (assigned by physical entity) vectorf *pNormals; // pointer to array of surface normals at points where sensors touch environment unsigned int flags; // bitmask of flags, bit==1 - sensor touched environment }; struct pe_status_dynamics : pe_status { enum entype { type_id=8 }; pe_status_dynamics() : v(zero),w(zero),a(zero),wa(zero),centerOfMass(zero) { MARK_UNUSED partid,ipart; type=type_id; time_interval=0; submergedFraction=0; waterResistance=0; } int partid; int ipart; vectorf v; // velocity vectorf w; // angular velocity vectorf a; // linear acceleration vectorf wa; // angular acceleration vectorf centerOfMass; float submergedFraction; float waterResistance; float mass; float time_interval; }; struct coll_history_item { vectorf pt; // collision area center vectorf n; // collision normal in entity CS vectorf v[2]; // velocities of contacting bodies at the point of impact float mass[2]; // masses of contacting bodies float age; // age of collision event int idCollider; // id of collider (not a pointer, since collider can be destroyed before history item is queried) int partid[2]; int idmat[2]; // 0-this body material, 1-collider material }; struct pe_status_collisions : pe_status { enum entype { type_id=9 }; pe_status_collisions() { type=type_id; age=0; len=1; pHistory=0; bClearHistory=0; } coll_history_item *pHistory; // pointer to a user-provided array of history items int len; // length of this array float age; // maximum age of collision events (older events are ignored) int bClearHistory; }; struct pe_status_id : pe_status { enum entype { type_id=10 }; pe_status_id() { type=type_id; ipart=partid=-1; bUseProxy=1; } int ipart; int partid; int iPrim; int iFeature; int bUseProxy; int id; // usually id means material }; struct pe_status_timeslices : pe_status { enum entype { type_id=11 }; pe_status_timeslices() { type=type_id; pTimeSlices=0; sz=1; precision=0.0001f; MARK_UNUSED time_interval; } float *pTimeSlices; int sz; float precision; // time surplus below this threshhold will be discarded float time_interval; // if unused, time elapsed since the last action will be used }; struct pe_status_nparts : pe_status { enum entype { type_id=12 }; pe_status_nparts() { type=type_id; } }; struct pe_status_awake : pe_status { enum entype { type_id=7 }; pe_status_awake() { type=type_id; } }; struct pe_status_contains_point : pe_status { enum entype { type_id=13 }; pe_status_contains_point() { type=type_id; } vectorf pt; }; struct pe_status_placeholder : pe_status { enum entype { type_id=16 }; pe_status_placeholder() { type=type_id; } IPhysicalEntity *pFullEntity; }; struct pe_status_sample_contact_area : pe_status { enum entype { type_id=19 }; pe_status_sample_contact_area() { type=type_id; } vectorf ptTest; vectorf dirTest; }; struct pe_status_caps : pe_status { enum entype { type_id=20 }; pe_status_caps() { type=type_id; } unsigned int bCanAlterOrientation; // can change orientation that is explicitly set from outside }; ////////// living entity statuses struct pe_status_living : pe_status { enum entype { type_id=2 }; pe_status_living() { type=type_id; } int bFlying; // whether entity has no contact with ground float timeFlying; // for how long the entity was flying vectorf camOffset; // camera offset vectorf vel; // actual velocity (as rate of position change) vectorf velUnconstrained; // 'physical' movement velocity vectorf velRequested; // velocity requested in the last action vectorf velGround; // velocity of the object entity is standing on float groundHeight; // position where the last contact with the ground occured vectorf groundSlope; int groundSurfaceIdx; IPhysicalEntity *pGroundCollider; int iGroundColliderPart; float timeSinceStanceChange; int bOnStairs; }; ////////// vehicle entity statuses struct pe_status_vehicle : pe_status { enum entype { type_id=4 }; pe_status_vehicle() { type=type_id; } float steer; // current steering angle float pedal; // current engine pedal int bHandBrake; // nonzero if handbrake is on float footbrake; // nonzero if footbrake is pressed (range 0..1) vectorf vel; int bWheelContact; // nonzero if at least one wheel touches ground int iCurGear; float engineRPM; float clutch; int nActiveColliders; }; struct pe_status_wheel : pe_status { enum entype { type_id=5 }; pe_status_wheel() { type=type_id; iWheel=0; } int iWheel; int bContact; // nonzero if wheel touches ground vectorf ptContact; // point where wheel touches ground float w; // rotation speed int bSlip; vectorf velSlip; // slip velocity int contactSurfaceIdx; float suspLen; // current suspension spring length float suspLenFull; // relaxed suspension spring length float suspLen0; // initial suspension spring length }; struct pe_status_vehicle_abilities : pe_status { enum entype { type_id=15 }; pe_status_vehicle_abilities() { type=type_id; MARK_UNUSED steer; } float steer; // should be set to requested steering angle vectorf rotPivot; // returns turning circle center float maxVelocity; // calculates maximum velocity of forward movement along a plane (steer is ignored) }; ////////// articulated entity statuses struct pe_status_joint : pe_status { enum entype { type_id=6 }; pe_status_joint() { type=type_id; idChildBody=-1; } int idChildBody; // requested joint is identified by child body id unsigned int flags; // joint flags vectorf q; // current joint angles (controlled by physics) vectorf qext; // external angles (from animation) vectorf dq; // current joint angular velocities quaternionf quat0; }; ////////// rope entity statuses struct pe_status_rope : pe_status { enum entype { type_id=14 }; pe_status_rope() { type=type_id; pPoints=pVelocities=0; } int nSegments; vectorf *pPoints; vectorf *pVelocities; }; ////////// soft entity statuses struct pe_status_softvtx : pe_status { enum entype { type_id=17 }; pe_status_softvtx() { type=type_id; pVtx=pNormals=0; } int nVtx; strided_pointer pVtx; strided_pointer pNormals; }; ////////////////////////// Geometry structures ///////////////////// ////////// common geometries enum geom_flags { geom_colltype0=0x0001, geom_colltype1=0x0002, geom_colltype2=0x0004, geom_colltype3=0x0008, geom_colltype4=0x0010, geom_colltype5=0x0020, geom_colltype6=0x0040, geom_colltype7=0x0080, geom_colltype8=0x0100, geom_colltype9=0x0200, geom_colltype10=0x0400,geom_colltype11=0x0800,geom_colltype12=0x1000,geom_colltype13=0x2000,geom_colltype14=0x4000, geom_colltype_ray=0x8000, geom_collides=0xFFFF, geom_floats=0x10000, geom_has_thin_parts=0x20000, geom_colltype_player=geom_colltype1, geom_colltype_explosion=geom_colltype2, geom_proxy=0x40000 }; struct pe_geomparams { enum entype { type_id=0 }; pe_geomparams() { type=type_id; density=mass=0; pos.Set(0,0,0); q.SetIdentity(); bRecalcBBox=1; flags = geom_collides|geom_floats; flagsCollider = geom_colltype0; pMtx3x3=0;pMtx3x3T=0;pMtx4x4=0;pMtx4x4T=0; scale=1.0f; MARK_UNUSED surface_idx,minContactDist; } int type; float density; // 0 if mass is used float mass; // 0 if density is used vectorf pos; // offset from object's geometrical pivot quaternionf q; // orientation relative to object float scale; float *pMtx3x3; // optional 3x3 orintation+scale matrix float *pMtx3x3T; // optional 3x3 column-major orintation+scale matrix float *pMtx4x4; // optional 4x4 transformation matrix float *pMtx4x4T; // optional 4x4 column-major transformation matrix int surface_idx; // surface identifier (used if corresponding CGeometry does not contain materials) unsigned int flags,flagsCollider; float minContactDist; int bRecalcBBox; VALIDATORS_START VALIDATOR_RANGE(density,-1E8,1E8) VALIDATOR_RANGE(mass,-1E8,1E8) VALIDATOR(pos) VALIDATOR_NORM(q) VALIDATORS_END }; ////////// articulated entity geometries struct pe_articgeomparams : pe_geomparams { enum entype { type_id=2 }; pe_articgeomparams() { type=type_id; idbody=0; } pe_articgeomparams(pe_geomparams &src) { type=type_id; density=src.density; mass=src.mass; pos=src.pos; q=src.q; scale=src.scale; surface_idx=src.surface_idx; pMtx3x3=src.pMtx3x3; pMtx3x3T=src.pMtx3x3T; pMtx4x4=src.pMtx4x4; pMtx4x4T=pMtx4x4T; idbody=0; minContactDist=src.minContactDist; bRecalcBBox=src.bRecalcBBox; } int idbody; // id of the subbody this geometry is attached to, the 1st add geometry specifies frame CS of this subbody }; ////////// vehicle entity geometries const int NMAXWHEELS = 16; struct pe_cargeomparams : pe_geomparams { enum entype { type_id=1 }; pe_cargeomparams() : pe_geomparams() { type=type_id; MARK_UNUSED bDriving,minFriction,maxFriction; bCanBrake=1; } pe_cargeomparams(pe_geomparams &src) { type=type_id; density=src.density; mass=src.mass; pos=src.pos; q=src.q; surface_idx=src.surface_idx; MARK_UNUSED bDriving,minFriction,maxFriction; bCanBrake=1; } int bDriving; // whether wheel is driving, -1 - geometry os not a wheel int iAxle; // wheel axle, currently not used int bCanBrake; // whether the wheel is locked during handbrakes vectorf pivot; // upper suspension point in vehicle CS float lenMax; // relaxed suspension length float lenInitial; // current suspension length (assumed to be length in rest state) float kStiffness; // suspension stiffness, if 0 - calculate from lenMax, lenInitial, and vehicle mass and geometry float kDamping; // suspension damping, if <0 - calculate as -kdamping*(approximate zero oscillations damping) float minFriction,maxFriction; // additional friction limits for tire friction }; ///////////////////////////////////////////////////////////////////////////////////// //////////////////////////// IGeometry Interface //////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////// struct geom_world_data { geom_world_data() { v.Set(0,0,0); w.Set(0,0,0); offset.Set(0,0,0); R.SetIdentity(); centerOfMass.Set(0,0,0); scale=1.0f; iStartNode=0; } vectorf offset; matrix3x3f R; float scale; vectorf v,w; vectorf centerOfMass; int iStartNode; }; struct intersection_params { intersection_params() { iUnprojectionMode=0; vrel_min=1E-6f; time_interval=100.0f; maxSurfaceGapAngle=1.0f*float(pi/180); pGlobalContacts=0; minAxisDist=0; bSweepTest=false; centerOfRotation.Set(0,0,0); axisContactNormal.Set(0,0,1); unprojectionPlaneNormal.Set(0,0,0); axisOfRotation.Set(0,0,0); bKeepPrevContacts=false; bStopAtFirstTri=false; ptOutsidePivot[0].Set(1E11f,1E11f,1E11f); ptOutsidePivot[1].Set(1E11f,1E11f,1E11f); maxUnproj=1E10f; bNoAreaContacts=false; bNoBorder=false; bNoIntersection=0; } int iUnprojectionMode; vectorf centerOfRotation; vectorf axisOfRotation; float time_interval; float vrel_min; float maxSurfaceGapAngle; float minAxisDist; vectorf unprojectionPlaneNormal; vectorf axisContactNormal; float maxUnproj; vectorf ptOutsidePivot[2]; bool bSweepTest; bool bKeepPrevContacts; bool bStopAtFirstTri; bool bNoAreaContacts; bool bNoBorder; int bNoIntersection; int bBothConvex; geom_contact *pGlobalContacts; }; struct phys_geometry { IGeometry *pGeom; vectorf Ibody; quaternionf q; vectorf origin; float V; int nRefCount; int surface_idx; }; enum geomtypes { GEOM_TRIMESH=0,GEOM_HEIGHTFIELD=1,GEOM_CYLINDER=2,GEOM_RAY=3,GEOM_SPHERE=4,GEOM_BOX=5 }; class IGeometry { public: virtual int GetType() = 0; virtual void Release() = 0; virtual void GetBBox(primitives::box *pbox) = 0; virtual int CalcPhysicalProperties(phys_geometry *pgeom) = 0; virtual int PointInsideStatus(const vectorf &pt) = 0; virtual int Intersect(IGeometry *pCollider, geom_world_data *pdata1,geom_world_data *pdata2, intersection_params *pparams, geom_contact *&pcontacts) = 0; virtual int FindClosestPoint(geom_world_data *pgwd, int &iPrim,int &iFeature, const vectorf &ptdst0,const vectorf &ptdst1, vectorf *ptres, int nMaxIters=10) = 0; virtual void CalcVolumetricPressure(geom_world_data *gwd, const vectorf &epicenter,float k,float rmin, const vectorf ¢erOfMass, vectorf &P,vectorf &L) = 0; virtual float CalculateBuoyancy(const primitives::plane *pplane, const geom_world_data *pgwd, vectorf &submergedMassCenter) = 0; virtual void CalculateMediumResistance(const primitives::plane *pplane, const geom_world_data *pgwd, vectorf &dPres,vectorf &dLres) = 0; virtual void DrawWireframe(void (*DrawLineFunc)(float*,float*), geom_world_data *gwd, int iLevel) = 0; virtual int GetPrimitiveId(int iPrim,int iFeature) = 0; virtual int GetPrimitive(int iPrim, primitives::primitive *pprim) = 0; virtual int GetFeature(int iPrim,int iFeature, vectorf *pt) = 0; virtual int IsConvex(float tolerance) = 0; virtual void PrepareForRayTest(float raylen) = 0; virtual float BuildOcclusionCubemap(geom_world_data *pgwd, int iMode, int *pGrid0[6],int *pGrid1[6],int nRes, float rmin,float rmax, int nGrow) = 0; virtual void GetMemoryStatistics(ICrySizer *pSizer) = 0; virtual void Save(CMemStream &stm) = 0; virtual void Load(CMemStream &stm) = 0; virtual void RemapFaceIds(short *pMap,int sz) = 0; virtual int GetPrimitiveCount() = 0; }; ///////////////////////////////////////////////////////////////////////////////////// //////////////////////////// IGeometryManager Interface ///////////////////////////// ///////////////////////////////////////////////////////////////////////////////////// enum meshflags { mesh_OBB=1, mesh_AABB=2, mesh_SingleBB=4, mesh_multicontact0=8, mesh_multicontact1=16, mesh_multicontact2=32, mesh_approx_cylinder=0x100, mesh_approx_box=0x200, mesh_approx_sphere=0x400, mesh_uchar_ids=0x1000 }; class IGeomManager { public: virtual void InitGeoman() = 0; virtual void ShutDownGeoman() = 0; virtual IGeometry *CreateMesh(strided_pointer pVertices,index_t *pIndices,const short *pIds,int nTris, int flags,bool bCopyTriangles=true, bool bCopyVertices=true, float approx_tolerance=0.05f, int nMinTrisPerNode=2,int nMaxTrisPerNode=4, float favorAABB=1.0f) = 0; virtual IGeometry *CreatePrimitive(int type, const primitives::primitive *pprim) = 0; virtual void DestroyGeometry(IGeometry *pGeom) = 0; // defSurfaceIdx will be used (until overwritten in entity part) if the geometry doesn't have per-face materials virtual phys_geometry *RegisterGeometry(IGeometry *pGeom,int defSurfaceIdx=0) = 0; virtual int AddRefGeometry(phys_geometry *pgeom) = 0; virtual int UnregisterGeometry(phys_geometry *pgeom) = 0; virtual void SaveGeometry(CMemStream &stm, IGeometry *pGeom) = 0; virtual IGeometry *LoadGeometry(CMemStream &stm) = 0; virtual void SavePhysGeometry(CMemStream &stm, phys_geometry *pgeom) = 0; virtual phys_geometry *LoadPhysGeometry(CMemStream &stm) = 0; virtual void RemapPhysGeometryFaceIds(phys_geometry *pgeom,short *pMap,int sz) = 0; }; ///////////////////////////////////////////////////////////////////////////////////// ////////////////////////////// IPhysUtils Interface ///////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////// class IPhysUtils { public: virtual int BreakPolygon(vector2df *ptSrc,int nPt, int nCellx,int nCelly, int maxPatchTris, vector2df *&ptout,int *&nPtOut, float jointhresh=0.5f,int seed=-1) = 0; virtual int CoverPolygonWithCircles(strided_pointer pt,int npt,bool bConsecutive, const vector2df ¢er, vector2df *¢ers,float *&radii, float minCircleRadius) = 0; virtual void DeletePointer(void *pdata) = 0; }; ///////////////////////////////////////////////////////////////////////////////////// //////////////////////////// IPhysicalEntity Interface ////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////// enum snapshot_flags { ssf_compensate_time_diff=1, ssf_checksum_only=2, ssf_no_update=4 }; class IPhysicalEntity { public: /*! Retrieves entity type @returb entity type enum */ virtual pe_type GetType() = 0; /*! Sets parameters @param params pointer to parameters structure @return nonzero if success */ virtual int SetParams(pe_params* params) = 0; virtual int GetParams(pe_params* params) = 0; /*! Retrieves status @param status pointer to status structure @retuan nonzero if success */ virtual int GetStatus(pe_status* status) = 0; /*! Performes action @param action pointer to action structure @return nonzero if success */ virtual int Action(pe_action*) = 0; /*! Adds geometry @param pgeom geometry identifier (obtained from RegisterXXX function) @param params pointer to geometry parameters structure @param id requested geometry id, if -1 - assign automatically @return geometry id (0..some number), -1 means error */ virtual int AddGeometry(phys_geometry *pgeom, pe_geomparams* params,int id=-1) = 0; /*! Removes geometry @param params pointer to parameters structure @return nonzero if success */ virtual void RemoveGeometry(int id) = 0; /*! Retrieves foreign data passed during creation (can be pointer to the corresponding engine entity, for instance) @param iforeigndata requested foreign data type @return foreign data (void*) if itype==iforeigndata of this entity, 0 otherwise */ virtual void *GetForeignData(int itype=0) = 0; /*! Retrieves iforeigndata of the entity (usually it will be a type identifier for pforeign data @return iforeigndata */ virtual int GetiForeignData() = 0; /*! Writes state into snapshot @param stm stream @param time_back requests previous state (only supported by living entities) @params flags a combination of snapshot_flags @return non0 if successful */ virtual int GetStateSnapshot(class CStream &stm, float time_back=0, int flags=0) = 0; /*! Reads state from snapshot @param stm stream @return size of snapshot */ virtual int SetStateFromSnapshot(class CStream &stm, int flags=0) = 0; virtual int PostSetStateFromSnapshot() = 0; virtual int GetStateSnapshotTxt(char *txtbuf,int szbuf, float time_back=0) = 0; virtual void SetStateFromSnapshotTxt(const char *txtbuf,int szbuf) = 0; virtual unsigned int GetStateChecksum() = 0; /*! StartStep should be called before step with the full time interval (if the step will be split into substeps) */ virtual void StartStep(float time_interval) = 0; /*! Evolves entity in time. Normally this is called from PhysicalWorld::TimeStep @param time_interval time step */ virtual int Step(float time_interval) = 0; /*! Restores previous entity state that corresponds to time -time_interval from now, interpolating when necessary. This can be used for manual client-server synchronization. Outside of PhysicalWorld::TimeStep should be called only for living entities @param time_interval time to trace back */ virtual void StepBack(float time_interval) = 0; /*! Returns physical world this entity belongs to @return physical world interface */ virtual IPhysicalWorld *GetWorld() = 0; virtual void GetMemoryStatistics(ICrySizer *pSizer) = 0; }; ///////////////////////////////////////////////////////////////////////////////////// //////////////////////////// IPhysicsEventClient Interface ////////////////////////// ///////////////////////////////////////////////////////////////////////////////////// class IPhysicsEventClient { public: virtual void OnBBoxOverlap(IPhysicalEntity *pEntity, void *pForeignData,int iForeignData, IPhysicalEntity *pCollider, void *pColliderForeignData,int iColliderForeignData) = 0; virtual void OnStateChange(IPhysicalEntity *pEntity, void *pForeignData,int iForeignData, int iOldSimClass,int iNewSimClass) = 0; virtual void OnCollision(IPhysicalEntity *pEntity, void *pForeignData,int iForeignData, coll_history_item *pCollision) = 0; virtual int OnImpulse(IPhysicalEntity *pEntity, void *pForeignData,int iForeignData, pe_action_impulse *impulse) = 0; virtual void OnPostStep(IPhysicalEntity *pEntity, void *pForeignData,int iForeignData, float dt) = 0; }; ///////////////////////////////////////////////////////////////////////////////////// ///////////////////////////// IPhysicalWorld Interface ////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////// enum draw_helper_flags { pe_helper_collisions=1, pe_helper_geometry=2, pe_helper_bbox=4 }; enum surface_flags { sf_pierceable_mask=0x0F, sf_pierceable0=0, sf_pierceable=1, sf_max_pierceable=0x0F, sf_important=0x200 }; enum rwi_flags { rwi_ignore_terrain_holes=0x20, rwi_ignore_noncolliding=0x40, rwi_ignore_back_faces=0x80, rwi_any_hit=0x100, rwi_pierceability_mask=0x0F, rwi_pierceability0=0, rwi_stop_at_pierceable=0x0F, rwi_separate_important_hits=sf_important, rwi_colltype_bit=16 }; enum entity_query_flags { ent_static=1, ent_sleeping_rigid=2, ent_rigid=4, ent_living=8, ent_independent=16, ent_deleted=128, ent_terrain=0x100, ent_all=ent_static | ent_sleeping_rigid | ent_rigid | ent_living | ent_independent | ent_terrain, ent_flagged_only = pef_update, ent_skip_flagged = pef_update*2, ent_triggers = 64, ent_ignore_noncolliding = 0x10000, ent_sort_by_mass = 0x20000, ent_allocate_list = 0x40000 }; struct phys_profile_info { IPhysicalEntity *pEntity; int nTicks; int nCalls; int id; const char *pName; }; struct SolverSettings { int nMaxStackSizeMC; // def 8 float maxMassRatioMC; // def 50 int nMaxMCiters; // def 1400 int nMaxMCitersHopeless; // def 400 float accuracyMC; // def 0.005 float accuracyLCPCG; // def 0.005 int nMaxContacts; // def 150 int nMaxPlaneContacts; // def 7 int nMaxPlaneContactsDistress; // def 4 int nMaxLCPCGsubiters; // def 120 int nMaxLCPCGsubitersFinal; // def 250 int nMaxLCPCGmicroiters; int nMaxLCPCGmicroitersFinal; int nMaxLCPCGiters; // def 5 float minLCPCGimprovement; // def 0.1 int nMaxLCPCGFruitlessIters; // def 4 float accuracyLCPCGnoimprovement; // def 0.05 float minSeparationSpeed; // def 0.02 float maxvCG; float maxwCG; float maxvUnproj; }; struct PhysicsVars : SolverSettings { int bFlyMode; int iCollisionMode; int bSingleStepMode; int bDoStep; float fixedTimestep; float timeGranularity; float maxWorldStep; int iDrawHelpers; float maxContactGap; float maxContactGapPlayer; float minBounceSpeed; int bProhibitUnprojection; int bUseDistanceContacts; float unprojVelScale; float maxUnprojVel; int bEnforceContacts; int nMaxSubsteps; int nMaxSurfaces; vectorf gravity; int nGroupDamping; float groupDamping; int bBreakOnValidation; int bLogActiveObjects; int bMultiplayer; int bProfileEntities; int nGEBMaxCells; float maxVel; float maxVelPlayers; float maxContactGapSimple; float penaltyScale; int bSkipRedundantColldet; int bLimitSimpleSolverEnergy; }; struct ray_hit { float dist; IPhysicalEntity *pCollider; int ipart; int partid; int surface_idx; vectorf pt; vectorf n; int bTerrain; }; class IPhysicalWorld { public: /*! Inits world @param pconsole pointer of IConsole interace */ virtual void Init() = 0; virtual IGeomManager* GetGeomManager() = 0; virtual IPhysUtils* GetPhysUtils() = 0; /*! Shuts the world down */ virtual void Shutdown(int bDeleteGeometries = 1) = 0; /*! Destroys the world */ virtual void Release() = 0; /*! Initializes entity hash grid @param axisx id of grid x axis (0-world x,1-world y,2-world z) @param axisy id of grid y axis (0-world x,1-world y,2-world z) @param origin grid (0,0) in world CS @param nx number of cells in grid x direciton @param ny number of cells in grid y direciton @param stepx cell x dimension @param stepy cell y dimension */ virtual void SetupEntityGrid(int axisz, vectorf org, int nx,int ny, float stepx,float stepy) = 0; /*! Sets heightfield data @param phf */ virtual void SetHeightfieldData(const primitives::heightfield *phf) = 0; /*! Retrieves heightfield data @param phf @return 0 if no global heightfield, 1 otherwise */ virtual int GetHeightfieldData(primitives::heightfield *phf) = 0; /*! Retrieves pointer to physvars structure @return pointer to physvar structure */ virtual PhysicsVars *GetPhysVars() = 0; /*! Creates physical entity @param type entity type @param params initial params (as in entity SetParams) @param pforeigndata entity foreign data @param iforeigndata entity foreign data type identifier @return pointer to physical entity interface */ virtual IPhysicalEntity* CreatePhysicalEntity(pe_type type, pe_params* params=0, void *pforeigndata=0, int iforeigndata=0, int id=-1) = 0; virtual IPhysicalEntity* CreatePhysicalEntity(pe_type type, float lifeTime, pe_params* params=0, void *pForeignData=0,int iForeignData=0, int id=-1,IPhysicalEntity *pHostPlaceholder=0) = 0; virtual IPhysicalEntity *CreatePhysicalPlaceholder(pe_type type, pe_params* params=0, void *pForeignData=0,int iForeignData=0, int id=-1) = 0; /*! Destroys physical entity @param pent entity @param mode 0-normal destroy, 1-suspend, 2-restore from suspended state @return nonzero if success */ virtual int DestroyPhysicalEntity(IPhysicalEntity *pent, int mode=0) = 0; virtual int SetPhysicalEntityId(IPhysicalEntity *pent, int id, int bReplace=1) = 0; virtual int GetPhysicalEntityId(IPhysicalEntity *pent) = 0; virtual IPhysicalEntity* GetPhysicalEntityById(int id) = 0; /*! Sets surface parameters @param surface_idx surface identifier @param bounciness restitution coefficient (for pair of surfaces k = sum of their coefficients, clamped to [0..1] @param friction friction coefficient (for pair of surfaces k = sum of their coefficients, clamped to [0..inf) @param flags bitmask (see surface_flags enum) @return nonzero if success */ virtual int SetSurfaceParameters(int surface_idx, float bounciness,float friction, unsigned int flags=0) = 0; virtual int GetSurfaceParameters(int surface_idx, float &bounciness,float &friction, unsigned int &flags) = 0; /*! Perfomes a time step @param time_interval time interval @param flags entity types to update (ent_..; ent_deleted to purge deletion physics-on-demand state monitoring) */ virtual void TimeStep(float time_interval,int flags=ent_all|ent_deleted) = 0; /*! Returns current time of the physical world @return current time */ virtual float GetPhysicsTime() = 0; virtual int GetiPhysicsTime() = 0; /*! Sets current time of the physical world @param time new time */ virtual void SetPhysicsTime(float time) = 0; virtual void SetiPhysicsTime(int itime) = 0; /*! Sets physical time that corresponds to the following server state snapshot @param time_snapshot physical time of the following server snapshot */ virtual void SetSnapshotTime(float time_snapshot,int iType=0) = 0; virtual void SetiSnapshotTime(int itime_snapshot,int iType=0) = 0; /*! Retrives list of entities that fall into a box @param ptmix,ptmax - box corners @param pList returned pointer to entity list @param objtypes bitmask 0-static, 1-sleeping, 2-physical, 3-living @return number of entities */ virtual int GetEntitiesInBox(vectorf ptmin,vectorf ptmax, IPhysicalEntity **&pList, int objtypes) = 0; /*! Shoots ray into world @param origin origin @param dir direction*(ray length) @param objtypes bitmask 0-terrain 1-static, 2-sleeping, 3-physical, 4-living @param flags a combination of rwi_flags @param hits destination hits array @param nmaxhits size of this array @param pskipent entity to skip @return number of collisions */ virtual int RayWorldIntersection(vectorf org,vectorf dir, int objtypes, unsigned int flags, ray_hit *hits,int nMaxHits, IPhysicalEntity *pSkipEnt=0,IPhysicalEntity *pSkipEntAux=0) = 0; /*! Freezes (resets velocities of) all physical, living, and detached entities */ virtual void ResetDynamicEntities() = 0; /*! Immediately destroys all physical, living, and detached entities; flushes the deleted entities All subsequent calls to DestroyPhysicalEntity for non-static entities are ignored until the next non-static entity is created */ virtual void DestroyDynamicEntities() = 0; /*! Forces deletion of all entities marked as deleted */ virtual void PurgeDeletedEntities() = 0; /*! Simulates physical explosion with k/(r^2) pressure distribution @param epicenter epicenter used for building the occlusion map @param epicenterImp epicenter used for applying impulse @param rmin all r