This page collects information on the GSOC project about the overhaul of the collision and physics systems.
API proposition
Main objects are:
For the collision system:
- iCollisionSystem: main plugin, can create sectors/objects/colliders (objects are destroyed when no one has any reference on them)
- iCollisionSector: holder for a set of colliders (to be mapped with a iSector), can add/remove portals/objects
- iCollisionObject: a list of colliders holding together, can be ghost/solid, can add/remove colliders
- iCollider: methods to define the type of the collider (sphere, box, etc)
- iCollisionActor, inherits from iCollisionObject: dynamic object (see csColliderActor and Bullet's character controller)
- iCollisionCallback: to be set on a iCollisionObject (and soft bodies?) // TODO
For the physical system:
- iPhysicalSystem: also exposed when this is the Bullet plugin
- iPhysicalSector: also exposed when this is the Bullet plugin
- iPhysicalObject: implements iCollisionObject?
- iRigidBody, inherits from iPhysicalObject, iCollisionObject
- iSoftBody, inherits from iPhysicalObject
- iJoint
API proposition
Here is the current proposition of the API made by Lulu.
- collision.h
#ifndef __CS_IVARIA_COLLISION_H__ #define __CS_IVARIA_COLLISION_H__ namespace CS { namespace Collision { struct csConvexResult; typedef size_t CollisionGroupMask; enum ColliderType { COLLIDER_INVALID = 0, COLLIDER_BOX, COLLIDER_SPHERE, COLLIDER_CYLINDER, COLLIDER_CAPSULE, COLLIDER_CONE, COLLIDER_PLANE, COLLIDER_CONVEX_MESH, COLLIDER_CONCAVE_MESH, COLLIDER_CONCAVE_MESH_SCALED, COLLIDER_TERRAIN, }; enum CollisionObjectType { COLLISION_OBJECT_BASE = 0, COLLISION_OBJECT_GHOST, COLLISION_OBJECT_ACTOR }; struct CollisionGroup { csString name; CollisionGroupMask value; }; struct MoveResult { bool hasHit; csVector3 hitNormalWorld; csVector3 hitPointWorld; csVector3 hitNormalLocal; csVector3 hitPointLocal; }; struct HitBeamResult { HitBeamResult () : hasHit (false), body (0), isect (0.0f), normal (0.0f), vertexIndex (0) {} /** * Whether the beam has hit a body or not. */ bool hasHit; /** * The collision object that was hit, or \a nullptr if no object was hit. */ iCollisionObject* object; /** * Intersection point in world space. */ csVector3 isect; /** * Normal to the surface of the body at the intersection point. */ csVector3 normal; /** * The index of the closest vertex of the soft body to be hit. This is only valid * if it is a soft body which is hit. */ size_t vertexIndex; }; struct CollisionData { csVector3 position; // in world coordinates? in object coordinates for both bodies? csVector3 penetration; }; struct iCollisionCallback: public virtual iBase { SCF_INTERFACE (iCollisionCallback, 1, 0, 0); /** * A collision occurred. * \param thisbody The body that received a collision. * \param otherbody The body that collided with \a thisBody. * \param collisions The list of collisions between the two bodies. * \param timesteps Since how many simulation time steps this collision occured. */ virtual void OnCollision (iCollisionObject *thisbody, iCollisionObject *otherbody, const csArray<CollisionData>& collisions, size_t timesteps) = 0; }; /** * A base interface for colliders. * Other colliders will be derived from this one. */ struct iCollider : public virtual iBase { SCF_INTERFACE (CS::Collision::iCollider, 1, 0, 0); /** * Get the geometry type of this collider. */ virtual ColliderType GetGeometryType () const = 0; virtual void SetLocalScale (const csVector3& scale) = 0; virtual const csVector3& GetLocalScale () const = 0; /** * Set the margin of this collision shape. */ virtual void SetMargin (float margin) = 0; virtual float GetMargin () const = 0; } /** * A box collider. * * Main creators of instances implementing this interface: * - iCollisionSystem::CreateColliderBox() * * Main ways to get pointers to this interface: * - iCollisionObject::GetCollider() * * Main users of this interface: * - iCollisionObject */ struct iColliderBox : public virtual iCollider { SCF_INTERFACE (CS::Collision::iColliderBox, 1, 0, 0); /** * Get the box geometry of this collider. */ virtual csVector3 GetBoxGeometry () = 0; // + methods to change the geometry? }; /** * A sphere collider. * * Main creators of instances implementing this interface: * - iCollisionSystem::CreateColliderSphere() * * Main ways to get pointers to this interface: * - iCollisionObject::GetCollider() * * Main users of this interface: * - iCollisionObject */ struct iColliderSphere : public virtual iCollider { SCF_INTERFACE (CS::Collision::iColliderSphere, 1, 0, 0); /** * Get the sphere geometry of this collider. */ virtual float GetSphereGeometry () = 0; }; /** * A cylinder collider. * * Main creators of instances implementing this interface: * - iCollisionSystem::CreateColliderCylinder() * * Main ways to get pointers to this interface: * - iCollisionObject::GetCollider() * * Main users of this interface: * - iCollisionObject */ struct iColliderCylinder : public virtual iCollider { SCF_INTERFACE (CS::Collision::iColliderCylinder, 1, 0, 0); /** * Get the cylinder geometry of this collider. */ virtual void GetCylinderGeometry (float& length, float& radius) = 0; }; /** * A capsule collider. * * Main creators of instances implementing this interface: * - iCollisionSystem::CreateColliderCapsule() * * Main ways to get pointers to this interface: * - iCollisionObject::GetCollider() * * Main users of this interface: * - iCollisionObject */ struct iColliderCapsule : public virtual iCollider { SCF_INTERFACE (CS::Collision::iColliderCapsule, 1, 0, 0); /** * Get the capsule geometry of this collider. */ virtual void GetCapsuleGeometry (float& length, float& radius) = 0; }; /** * A cone collider. * * Main creators of instances implementing this interface: * - iCollisionSystem::CreateColliderCone() * * Main ways to get pointers to this interface: * - iCollisionObject::GetCollider() * * Main users of this interface: * - iCollisionObject */ struct iColliderCone : public virtual iCollider { SCF_INTERFACE (CS::Collision::iColliderCone, 1, 0, 0); /// Get the capsule geometry of this collider. virtual void GetConeGeometry (float& length, float& radius) = 0; }; /** * A plane collider. * * Main creators of instances implementing this interface: * - iCollisionSystem::CreateColliderPlane() * * Main ways to get pointers to this interface: * - iCollisionObject::GetCollider() * * Main users of this interface: * - iCollisionObject */ struct iColliderPlane : public virtual iCollider { SCF_INTERFACE (CS::Collision::iColliderPlane, 1, 0, 0); /** * Get the plane geometry of this collider. */ virtual csPlane3 GetPlaneGeometry () = 0; }; /** * A convex mesh collider. * * Main creators of instances implementing this interface: * - iCollisionSystem::CreateColliderConvexMesh() * * Main ways to get pointers to this interface: * - iCollisionObject::GetCollider() * * Main users of this interface: * - iCollisionObject */ struct iColliderConvexMesh : public virtual iCollider { SCF_INTERFACE (CS::Collision::iColliderConvexMesh, 1, 0, 0); /** * Get the mesh factory of this collider. */ virtual iMeshFactoryWrapper* GetMeshFactory () = 0; }; /** * A concave mesh collider. * * Main creators of instances implementing this interface: * - iCollisionSystem::CreateColliderConcaveMesh() * * Main ways to get pointers to this interface: * - iCollisionObject::GetCollider() * * Main users of this interface: * - iCollisionObject */ struct iColliderConcaveMesh : public virtual iCollider { SCF_INTERFACE (CS::Collision::iColliderConcaveMesh, 1, 0, 0); /** * Get the mesh factory of this collider. */ virtual iMeshFactoryWrapper* GetMeshFactory () = 0; }; /** * A scaled concave mesh collider. * * Main creators of instances implementing this interface: * - iCollisionSystem::CreateColliderConcaveMeshScaled() * * Main ways to get pointers to this interface: * - iCollisionObject::GetCollider() * * Main users of this interface: * - iCollisionObject */ struct iColliderConcaveMeshScaled : public virtual iCollider { SCF_INTERFACE (CS::Collision::iColliderConcaveMeshScaled, 1, 0, 0); /** * Get the concave collider scaled by this collider. */ virtual iColliderConcaveMesh* GetCollider () = 0; }; /** * A terrain collider. * * Main creators of instances implementing this interface: * - iCollisionSystem::CreateColliderTerrain() * * Main ways to get pointers to this interface: * - iCollisionObject::GetCollider() * * Main users of this interface: * - iCollisionObject */ struct iColliderTerrain : public virtual iCollider { SCF_INTERFACE (CS::Collision::iColliderTerrain, 1, 0, 0); virtual iTerrainSystem* GetTerrain () const = 0; }; /** * A iCollisionActor is a kinematic collision object. It has a faster collision detection and response. * You can use it to create a player or character model with gravity handling. * * Main creators of instances implementing this interface: * - iCollisionSystem::CreateCollisionActor() * * Main ways to get pointers to this interface: * - iCollisionSystem::GetCollisionActor() * * Main users of this interface: * - iCollisionSystem */ // kickvb: most of this would have to be redesigned, let's do it later struct iCollisionActor : public virtual iCollisionObject { SCF_INTERFACE (CS::Collision::iCollisionActor, 1, 0, 0); /** * Check if we are on the ground. */ virtual bool IsOnGround () = 0; /** * Set the onground status. */ //virtual void SetOnGround (bool og) = 0; /** * Get current rotation in angles around every axis. */ virtual csVector3 GetRotation () const = 0; /** * Set current rotation in angles around every axis and set to actor. * If a camera is used, set it to camera too. */ virtual void SetRotation (const csVector3& rot) = 0; /** * Move the actor. */ virtual void UpdateAction (float delta) = 0; /** * Draw the debug informations of this actor. */ // really? //virtual void DebugDraw (iView* rview) = 0; /** * Set the up axis of the actor. */ virtual void SetUpAxis (int axis) = 0; /** * Set the walking velocity of the actor. */ virtual void SetVelocity (const csVector3& dir) = 0; /** * Set the walking velocity with which the character should move for * the given time period. After the time period, velocity is reset to zero. * Negative time intervals will result in no motion. */ virtual void SetVelocityForTimeInterval (const csVector3& velo, float timeInterval) = 0; /** * This is used by UpdateAction() but you can also call it manually. * It will adjust the new position to match with collision * detection. */ virtual void PreStep () = 0; /** * This is used by UpdateAction() but you can also call it manually. * Move the actor to proper target position. */ virtual void PlayerStep (float delta) = 0; /** * Set the falling speed. */ virtual void SetFallSpeed (float fallSpeed) = 0; /** * Set the jumping speed. */ virtual void SetJumpSpeed (float jumpSpeed) = 0; /** * Set the max jump height an actor can have. */ virtual void setMaxJumpHeight (float maxJumpHeight) = 0; /** * Let the actor jump. */ virtual void Jump () = 0; /** * The max slope determines the maximum angle that the actor can walk up. * The slope angle is measured in radians. */ virtual void SetMaxSlope (float slopeRadians) = 0; /** * Get the max slope. */ virtual float GetMaxSlope () const = 0; }; /** * This is the interface of a collision object. * It contains the collision information of the object. * * Main creators of instances implementing this interface: * - iCollisionSystem::CreateCollisionObject() * * Main ways to get pointers to this interface: * - iCollisionSystem::GetCollisionObject() * * Main users of this interface: * - iCollisionSystem */ struct iCollisionObject : public virtual iBase { SCF_INTERFACE (CS::Collision::iCollisionObject, 1, 0, 0); /** * Set the type of the collision object. */ virtual void SetObjectType (CollisionObjectType type) = 0; /** * Return the type of the collision object. */ virtual CollisionObjectType GetObjectType () = 0; /** * Set the movable attached to this collision object. Its position will be updated * automatically when this object is moved. */ virtual void SetAttachedMovable (iMovable* movable) = 0; /** * Get the movable attached to this collision object. */ virtual iMovable* GetAttachedMovable () = 0; /** * Set the transform. */ virtual void SetTransform (const csOrthoTransform& trans) = 0; /** * Get the transform. */ virtual csOrthoTransform GetTransform () = 0; /** * Add a collider to this collision body. */ virtual void AddCollider (iCollider* collider, const csOrthoTransform& trans) = 0; /** * Remove the given collider from this collision object. */ virtual void RemoveCollider (iCollider* collider) = 0; /** * Remove the collider with the given index from this collision object. */ virtual void RemoveCollider (size_t index) = 0; /** * Get the collider with the given index. */ virtual iCollider* GetCollider (size_t index) = 0; /** * Get the count of colliders in this collision object. */ virtual size_t GetColliderCount () = 0; /** * Rebuild this collision object. */ virtual void RebuildObject () = 0; /** * Set the collision group this object belongs to. */ virtual void SetCollisionGroup (const char* name); /** * Get the collision group this object belongs to. */ virtual const char* GetCollisionGroup () const; /** * Set a callback to be executed when this body collides with another. * If 0, no callback is executed. */ virtual void SetCollisionCallback (iCollisionCallback* cb) = 0; // + methods to get the current list of collisions with other objects? // + functionalities to filter the collisions we would like to listen to? /** * Get the collision response callback. */ virtual iCollisionCallback* GetCollisionCallback () = 0; /** * Test collision with another collision objects. */ virtual bool Collide (iCollisionObject* otherObject) = 0; /** * Follow a beam from start to end and return whether this body was hit. */ virtual HitBeamResult HitBeam ( const csVector3& start, const csVector3& end) = 0; }; struct iCollisionSector : public virtual iBase { SCF_INTERFACE (CS::Collision::iCollisionSector, 1, 0, 0); virtual void SetInternalScale (float scale) = 0; /** * Set the global gravity. */ virtual void SetGravity (const csVector3& v) = 0; /** * Get the global gravity. */ virtual csVector3 GetGravity () const = 0; /** * Add a collision object into the sector. * The collision object has to be initialized. */ virtual void AddCollisionObject (iCollisionObject* object) = 0; /** * Remove a collision object by pointer. */ virtual void RemoveCollisionObject (iCollisionObject* object) = 0; /** * Add a portal into the sector. Collision objects crossing a portal will be switched from iCollisionSector's. */ virtual void AddPortal (iPortal* portal); /** * Remove the given portal from this sector. */ virtual void RemovePortal (iPortal* portal); /** * Set the engine iSector related to this collison sector. The iMovable that are * attached to a iCollisionObject present in this collision sector will be put automatically in the given engine sector. */ virtual void SetSector (iSector* sector) = 0; /** * Get the engine iSector related to this collison sector. */ virtual iSector* GetSector () = 0; /** * Follow a beam from start to end and return the first body that is hit. */ virtual HitBeamResult HitBeam ( const csVector3& start, const csVector3& end) = 0; /** * Follow a beam from start to end and return the first body that is hit. */ //Lulu: What's this? return the first portal that is hit? Or cast a ray from a portal? // see iSector::HitBeam/HitBeamPortal: the first won't cross the portals, the second will virtual HitBeamResult HitBeamPortal ( const csVector3& start, const csVector3& end) = 0; /** * Performs a discrete collision test against all objects in this iCollisionSector. * it reports one or more contact points for every overlapping object */ virtual bool CollisionTest (iCollisionObject* object, csArray<CollisionData>& collisions) = 0; /** * Try to move the given object from \a fromWorld to \a toWorld and return the first collision occured if any. */ // kickvb: a test only on convex colliders is probably not interesting, so remove this method if not possible to do on any collision object //virtual MoveResult MoveTest (iCollisionObject* object, const csOrthoTransform& fromWorld, const csOrthoTransform& toWorld) = 0; }; /** * This is the Collision plug-in. This plugin is a factory for creating * iCollider, iCollisionObject, iCollisionSector and iCollisionActor * entities. * * Main creators of instances implementing this interface: * - OPCODE plugin (crystalspace.collisiondetection.opcode) * - Bullet plugin (crystalspace.dynamics.bullet) * * Main ways to get pointers to this interface: * - csQueryRegistry() */ struct iCollisionSystem : public virtual iBase { SCF_INTERFACE (CS::Collision::iCollisionSystem, 2, 2, 2); /** * Create a convex mesh collider. */ virtual csPtr<iColliderConvexMesh> CreateColliderConvexMesh (iMeshWrapper* mesh) = 0; /** * Create a concave mesh collider. */ virtual csPtr<iColliderConcaveMesh> CreateColliderConcaveMesh (iMeshWrapper* mesh) = 0; /** * Create a scaled concave mesh collider. */ virtual csPtr<iColliderConcaveMeshScaled> CreateColliderConcaveMeshScaled (iColliderConcaveMesh* collider, float scale) = 0; /** * Create a cylinder collider. */ virtual csPtr<iColliderCylinder> CreateColliderCylinder (float length, float radius) = 0; /** * Create a box collider. */ virtual csPtr<iColliderBox> CreateColliderBox (const csVector3& size) = 0; /** * Create a sphere collider. */ virtual csPtr<iColliderSphere> CreateColliderSphere (float radius) = 0; /** * Create a capsule collider. */ virtual csPtr<iColliderCapsule> CreateColliderCapsule (float length, float radius) = 0; /** * Create a plane collider. */ virtual csPtr<iColliderPlane> CreateColliderPlane (const csPlane3& plain) = 0; /** * Create a terrain collider. */ virtual csPtr<iColliderTerrain> CreateColliderTerrain (const iTerrainSystem* terrain, float minHeight = 0, float maxHeight = 0) = 0; /** * Create a collision object. Without any initialization. * Need to call iCollisionObject::RebuildObject. */ virtual csPtr<iCollisionObject> CreateCollisionObject ( CollisionObjectType type = COLLISION_OBJECT_BASE) = 0; /** * Decompose a concave mesh in convex parts. Each convex part will be added to * the collision object as a separate iColliderConvexMesh. */ virtual void DecomposeConcaveMesh (iCollisionObject* object, iMeshWrapper* mesh) = 0; /** * Create a collision actor. * Need to call iCollisionObject::RebuildObject. */ virtual csPtr<iCollisionActor> CreateCollisionActor () = 0; /** * Create a collision group. */ virtual CollisionGroup& CreateCollisionGroup (const char* name) = 0; /** * Find a collision group by name. */ virtual CollisionGroup& FindCollisionGroup (const char* name) = 0; virtual void SetGroupCollision (CollisionGroup& group1, CollisionGroup& group2, bool collide) = 0; virtual bool GetGroupCollision (CollisionGroup& group1, CollisionGroup& group2) = 0; /** * Create a collision sector. */ virtual csPtr<iCollisionSector> CreateCollisionSector () = 0; }; } } #endif
- physical.h
#ifndef __IVARIA_PHYSICS_H__ #define __IVARIA_PHYSICS_H__ namespace CS { namespace Collision { struct iCollisionCallback; struct iCollisionObject; struct CollisionGroup; struct iCollisionObject; } } namespace CS { namespace Physics { struct iJoint; struct iObject; struct iRigidBody; struct iSoftBody; struct iKinematicCallback; struct iPhysicalSystem; enum PhysicalBodyType { BODY_RIGID = 0, BODY_SOFT }; enum RigidBodyState { STATE_STATIC = 0, STATE_DYNAMIC, STATE_KINEMATIC }; /* enum JointType { JOINT_P2P; JOINT_CONETWIST; JOINT_6DOF; JOINT_SPRING; }; struct iJointHelper : public virtual iBase { SCF_INTERFACE (CS::Physics::iJointHelper ,1, 0, 0); virtual csPtr<iJoint> CreateP2PJoint (); virtual csPtr<iJoint> CreateConeTwistJoint (); virtual csPtr<iJoint> Create6DOFJoint (); virtual csPtr<iJoint> CreateSpringJoint (); }; */ /** * A base interface of physical bodies. * iRigidBody and iSoftBody will be derived from this one. */ struct iPhysicalBody : public virtual iCollisionObject { SCF_INTERFACE (CS::Physics::iPhysicalBody, 1, 0, 0); virtual PhysicalBodyType GetType () const = 0; virtual iRigidBody* QueryRigidBody () = 0; virtual iSoftBody* QuerySoftBody () = 0; /** * Disable this collision object. */ virtual bool Disable () = 0; /** * Enable this collision object. */ virtual bool Enable () = 0; /** * Check if the collision object is enabled. */ virtual bool isEnabled () = 0; // move "virtual iRigidBody::RigidBodyState GetState () = 0;" here and implement it for soft bodies by switching to rigid bodies when static/dynamic? //Lulu: If soft body can switch to rigid body, what about the parameters? Dose user have to call functions to set the parameters of rigid body? // If iPhysicalSystem create a new rigidbody, it's based on the softbody's current shape or original shape? // And the collision system will create a collision shape for the mesh? How to decide which type of collider is appropriate? /** * Get the mass of this body. */ virtual float GetMass () const = 0; /** * Set the mass of this body. */ virtual void SetMass (float mass) = 0; virtual float GetDensity () const = 0; virtual void SetDensity (float density) = 0; /** * Return the volume of this body. */ virtual float GetVolume () = 0; // AddForce/Torque? Velocities? //Lulu: soft body doesn't support AddTorque. /** * Add a force to the whole body. */ virtual void AddForce (const csVector3& force) = 0; /** * Set the linear velocity (movement). */ virtual void SetLinearVelocity (const csVector3& vel) = 0; /** * Get the linear velocity (movement). */ virtual csVector3 GetLinearVelocity (size_t index = 0) const = 0; /** * Set the friction of this body. * [0,1] for soft body. */ virtual void SetFriction (float friction) = 0; /** * Get the friction of this rigid body. */ virtual void GetFriction (float& friction) = 0; } /** * This is the interface for a rigid body. * It keeps all properties for the body. * It can also be attached to a movable or a bone, * to automatically update it. * * Main creators of instances implementing this interface: * - iPhysicalSystem::CreateRigidBody() * * Main ways to get pointers to this interface: * - iPhysicalSystem::GetRigidBody() * * Main users of this interface: * - iPhysicalSystem * * \sa iSoftBody */ struct iRigidBody : public iPhysicalBody { SCF_INTERFACE (CS::Physics::iRigidBody, 1, 0, 2); /** * Get the iCollisionObject pointer of this body. */ virtual iCollisionObject* QueryCollisionObject () = 0; /** * Get the current state of the body. */ virtual RigidBodyState GetState () = 0; /** * Set the current state of the body. */ virtual void SetState (RigidBodyState state) = 0; /** * Set the elasticity of this rigid body. */ virtual void SetElasticity (float elasticity) = 0; /** * Get the elasticity of this rigid body. */ virtual void GetElasticity (float elasticity) = 0; /** * Set the angular velocity (rotation). */ virtual void SetAngularVelocity (const csVector3& vel) = 0; /** * Get the angular velocity (rotation) */ virtual csVector3 GetAngularVelocity () const = 0; /** * Add a torque (world space) (active for one timestep). */ virtual void AddTorque (const csVector3& force) = 0; /** * Add a force (local space) (active for one timestep). */ virtual void AddRelForce (const csVector3& force) = 0; /** * Add a torque (local space) (active for one timestep). */ virtual void AddRelTorque (const csVector3& force) = 0; /** * Add a force (world space) at a specific position (world space) * (active for one timestep) */ virtual void AddForceAtPos (const csVector3& force, const csVector3& pos) = 0; /** * Add a force (world space) at a specific position (local space) * (active for one timestep) */ virtual void AddForceAtRelPos (const csVector3& force, const csVector3& pos) = 0; /** * Add a force (local space) at a specific position (world space) * (active for one timestep) */ virtual void AddRelForceAtPos (const csVector3& force, const csVector3& pos) = 0; /** * Add a force (local space) at a specific position (local space) * (active for one timestep) */ virtual void AddRelForceAtRelPos (const csVector3& force, const csVector3& pos) = 0; /** * Get total force (world space). */ virtual csVector3 GetForce () const = 0; /** * Get total torque (world space). */ virtual csVector3 GetTorque () const = 0; /** * Set the callback to be used to update the transform of the kinematic body. * If no callback are provided then the dynamic system will use a default one. */ virtual void SetKinematicCallback (iKinematicCallback* cb) = 0; /** * Get the callback used to update the transform of the kinematic body. */ virtual iKinematicCallback* GetKinematicCallback () = 0; /** * Set the linear dampener for this rigid body. The dampening correspond to * how much the movements of the objects will be reduced. It is a value * between 0 and 1, giving the ratio of speed that will be reduced * in one second. 0 means that the movement will not be reduced, while * 1 means that the object will not move. * The default value is 0. * \sa iDynamicSystem::SetLinearDampener() */ virtual void SetLinearDampener (float d) = 0; /** * Get the linear dampener for this rigid body. */ virtual float GetLinearDampener () = 0; /** * Set the angular dampener for this rigid body. The dampening correspond to * how much the movements of the objects will be reduced. It is a value * between 0 and 1, giving the ratio of speed that will be reduced * in one second. 0 means that the movement will not be reduced, while * 1 means that the object will not move. * The default value is 0. * \sa iDynamicSystem::SetRollingDampener() */ virtual void SetRollingDampener (float d) = 0; /** * Get the angular dampener for this rigid body. */ virtual float GetRollingDampener () = 0; }; /** * A soft body is a physical body that can be deformed by the physical * simulation. It can be used to simulate eg ropes, clothes or any soft * volumetric object. * * A soft body does not have a positional transform by itself, but the * position of every vertex of the body can be queried through GetVertexPosition(). * * A soft body can neither be static or kinematic, it is always dynamic. * \sa iRigidBody */ struct iSoftBody : public iPhysicalBody { SCF_INTERFACE (CS::Physics::iSoftBody, 2, 0, 3); /** * Set the mass of a node by index. */ virtual void SetVertexMass (float mass, size_t index) = 0; /** * Get the mass of a node by index. */ virtual float GetVertexMass (size_t index) = 0; /** * Return the count of vertices of this soft body. */ virtual size_t GetVertexCount () = 0; /** * Return the position in world coordinates of the given vertex. */ virtual csVector3 GetVertexPosition (size_t index) const = 0; /** * Anchor the given vertex to its current position. This vertex will no more move. */ virtual void AnchorVertex (size_t vertexIndex) = 0; /** * Anchor the given vertex to the given rigid body. The relative position of the * vertex and the body will remain constant. */ virtual void AnchorVertex (size_t vertexIndex, iRigidBody* body) = 0; /** * Anchor the given vertex to the given controller. The relative position of the * vertex and the controller will remain constant. */ virtual void AnchorVertex (size_t vertexIndex, iAnchorAnimationControl* controller) = 0; /** * Update the position of the anchor of the given vertex relatively to the anchored * rigid body. This can be used to have a finer control of the anchor position * relatively to the rigid body. * * This would work only if you called AnchorVertex (size_t,iRigidBody*) before. * The position to be provided is in world coordinates. * * \warning The stability of the simulation can be lost if you move the position too far * from the previous position. * \sa CS::Animation::iSoftBodyAnimationControl::CreateAnimatedMeshAnchor () */ virtual void UpdateAnchor (size_t vertexIndex, csVector3& position) = 0; /** * Remove the given anchor. This won't work if you anchored the vertex to a rigid body, due * to a limitation in the Bullet library. */ virtual void RemoveAnchor (size_t vertexIndex) = 0; /** * Set the rigidity of this body. The value should be in the 0 to 1 range, with * 0 meaning soft and 1 meaning rigid. */ virtual void SetRigidity (float rigidity) = 0; /** * Get the rigidity of this body. */ virtual float GetRidigity () = 0; /** * Set the linear velocity of the given vertex of the body. */ virtual void SetLinearVelocity (const csVector3& velocity, size_t vertexIndex) = 0; /** * Set the wind velocity of the whole body. */ // kickvb: in iPhysicalSector instead? virtual void SetWindVelocity (const csVector3& velocity) = 0; /** * Get the wind velocity of the whole body. */ virtual const csVector3& GetWindVelocity () const = 0; /** * Add a force at the given vertex of the body. */ virtual void AddForce (const csVector3& force, size_t vertexIndex) = 0; /** * Return the count of triangles of this soft body. */ virtual size_t GetTriangleCount () = 0; /** * Return the triangle with the given index. */ virtual csTriangle GetTriangle (size_t index) const = 0; /** * Return the normal vector in world coordinates for the given vertex. */ virtual csVector3 GetVertexNormal (size_t index) const = 0; /** * Currently Blender set this to 0 when creating a soft body. * Used to create a btTriangleMesh for soft body. */ //virtual void SetWelding (float welding) = 0; }; /** * A joint that can constrain the relative motion between two iRigidBody. * For instance if all motion in along the local X axis is constrained * then the bodies will stay motionless relative to each other * along an x axis rotated and positioned by the joint's transform. * * Main creators of instances implementing this interface: * - iPhysicalSystem::CreateJoint() * * Main users of this interface: * - iPhysicalSystem */ struct iJoint : public virtual iBase { SCF_INTERFACE (CS::Physics::iJoint, 1, 0, 0); /** * Set the rigid bodies that will be affected by this joint. Set force_update to true if * you want to apply the changes right away. */ virtual void Attach (iPhysicalBody* body1, iPhysicalBody* body2, const csOrthoTransform& trans1, const csOrthoTransform& trans2, bool forceUpdate = true) = 0; /** * Get the attached body with the given index (valid values for body are 0 and 1). */ virtual iPhysicalBody* GetAttachedBody (int index) = 0; /** * Set the local transformation of the joint. * * Set force_update to true if you want to apply the changes right away. */ virtual void SetTransform (const csOrthoTransform& trans, bool forceUpdate = true) = 0; /** * Get the local transformation of the joint. */ virtual csOrthoTransform GetTransform () const = 0; /** * Set the new position of the joint, in world coordinates. */ virtual void SetPosition (const csVector3& position) = 0; /** * Get the current position of the joint, in world coordinates. */ virtual csVector3 GetPosition () const = 0; /** * Set the translation constraints on the 3 axes. If true is * passed for an axis then the Joint will constrain all motion along * that axis (ie no motion will be allowed). If false is passed in then all motion along that * axis is free, but bounded by the minimum and maximum distance * if set. Set force_update to true if you want to apply the changes * right away. */ virtual void SetTransConstraints (bool X, bool Y, bool Z, bool forceUpdate = true) = 0; /** * True if this axis' translation is constrained. */ virtual bool IsXTransConstrained () = 0; /** * True if this axis' translation is constrained. */ virtual bool IsYTransConstrained () = 0; /** * True if this axis' translation is constrained. */ virtual bool IsZTransConstrained () = 0; /** * Set the minimum allowed distance between the two bodies. Set force_update to true if * you want to apply the changes right away. */ virtual void SetMinimumDistance (const csVector3& dist, bool forceUpdate = true) = 0; /** * Get the minimum allowed distance between the two bodies. */ virtual csVector3 GetMinimumDistance () const = 0; /** * Set the maximum allowed distance between the two bodies. Set force_update to true if * you want to apply the changes right away. */ virtual void SetMaximumDistance (const csVector3& dist, bool forceUpdate = true) = 0; /** * Get the maximum allowed distance between the two bodies. */ virtual csVector3 GetMaximumDistance () const = 0; /** * Set the rotational constraints on the 3 axes. If true is * passed for an axis then the Joint will constrain all rotation around * that axis (ie no motion will be allowed). If false is passed in then all rotation around that * axis is free, but bounded by the minimum and maximum angle * if set. Set force_update to true if you want to apply the changes * right away. */ virtual void SetRotConstraints (bool X, bool Y, bool Z, bool forceUpdate = true) = 0; /** * True if this axis' rotation is constrained. */ virtual bool IsXRotConstrained () = 0; /** * True if this axis' rotation is constrained. */ virtual bool IsYRotConstrained () = 0; /** * True if this axis' rotation is constrained. */ virtual bool IsZRotConstrained () = 0; /** * Set the minimum allowed angle between the two bodies, in radian. Set force_update to true if * you want to apply the changes right away. */ virtual void SetMinimumAngle (const csVector3& angle, bool forceUpdate = true) = 0; /** * Get the minimum allowed angle between the two bodies (in radian). */ virtual csVector3 GetMinimumAngle () const = 0; /** * Set the maximum allowed angle between the two bodies (in radian). Set force_update to true if * you want to apply the changes right away. */ virtual void SetMaximumAngle (const csVector3& dist, bool forceUpdate = true) = 0; /** * Get the maximum allowed angle between the two bodies (in radian). */ virtual csVector3 GetMaximumAngle () const = 0; /** * Set the restitution of the joint's stop point (this is the * elasticity of the joint when say throwing open a door how * much it will bounce the door back closed when it hits). */ virtual void SetBounce (const csVector3& bounce, bool forceUpdate = true) = 0; /** * Get the joint restitution. */ virtual csVector3 GetBounce () const = 0; /** * Apply a motor velocity to joint (for instance on wheels). Set force_update to true if * you want to apply the changes right away. */ virtual void SetDesiredVelocity (const csVector3& velo, bool forceUpdate = true) = 0; /** * Get the desired velocity of the joint motor. */ virtual csVector3 GetDesiredVelocity () const = 0; /** * Set the maximum force that can be applied by the joint motor to reach the desired velocity. * Set force_update to true if you want to apply the changes right away. */ virtual void SetMaxForce (const csVector3& force, bool forceUpdate = true) = 0; /** * Get the maximum force that can be applied by the joint motor to reach the desired velocity. */ virtual csVector3 GetMaxForce () const = 0; /** * Set a custom angular constraint axis (have sense only with rotation free minimum along 2 axis). * Set force_update to true if you want to apply the changes right away. */ virtual void SetAngularConstraintAxis (const csVector3& axis, bool forceUpdate = true) = 0; /** * Get the custom angular constraint axis. */ virtual csVector3 GetAngularConstraintAxis () const = 0; /** * Rebuild the joint using the current setup. Return true if the rebuilding operation was successful * (otherwise the joint won't be active). */ virtual bool RebuildJoint () = 0; /** * Set the spring constraints on the 3 axes. If true is * passed for an axis then the Joint will have a spring constraint on * that axis. If false is passed in then no spring constraint on the * axis. Set force_update to true if you want to apply the changes * right away. */ virtual void SetSpringConstraints (bool X, bool Y, bool Z, bool forceUpdate = true) = 0; /** * True if this axis has a spring constraint. */ virtual bool IsXSpringConstrained () = 0; /** * True if this axis has a spring constraint. */ virtual bool IsYSpringConstrained () = 0; /** * True if this axis has a spring constraint. */ virtual bool IsZSpringConstrained () = 0; /** * Set the stiffness of the spring. */ virtual void SetStiffness (float stiff) = 0; /** * Set the damping of the spring. */ virtual void SetDamping (float damp) = 0; /** * Set the current constraint position/orientation as an equilibrium point. * If index = -1, then set equilibrium point for all DOF, else set it for given DOF. */ virtual void SetEquilibriumPoint (int index = -1); /** * Set the value to an equilibrium point for given DOF. */ virtual void SetEquilibriumPoint (int index, float value); virtual void SetBreakingImpulseThreshold (float threshold) = 0; virtual float GetBreakingImpulseThreshold () = 0; }; struct iPhysicalSystem : public virtual iBase { SCF_INTERFACE (CS::Physics::iPhysicalSystem, 1, 0, 0); /** * Create a rigid body, if there's an iCollisionObject pointer, * Need to call iCollisionObject::RebuildObject. */ virtual csPtr<iRigidBody> CreateRigidBody () = 0; /** * Create a joint and add it to the simulation. */ virtual csPtr<iJoint> CreateJoint () = 0; /** * Create a soft body rope. * \param start Start position of the rope. * \param end End position of the rope. * \param segmentCount Number of segments in the rope. * \remark You must call SetSoftBodyWorld() prior to this. */ virtual iSoftBody* CreateRope (csVector3 start, csVector3 end, size_t segmentCount) = 0; /** * Create a soft body rope with explicit positions of the vertices. * \param vertices The array of positions to use for the vertices. * \param vertexCount The amount of vertices for the rope. * \remark You must call SetSoftBodyWorld() prior to this. */ virtual iSoftBody* CreateRope (csVector3* vertices, size_t vertexCount) = 0; /** * Create a soft body cloth. * \param corner1 The position of the top left corner. * \param corner2 The position of the top right corner. * \param corner3 The position of the bottom left corner. * \param corner4 The position of the bottom right corner. * \param segmentCount1 Number of horizontal segments in the cloth. * \param segmentCount2 Number of vertical segments in the cloth. * \param withDiagonals Whether there must be diagonal segments in the cloth * or not. Diagonal segments will make the cloth more rigid. * \remark You must call SetSoftBodyWorld() prior to this. */ virtual iSoftBody* CreateCloth (csVector3 corner1, csVector3 corner2, csVector3 corner3, csVector3 corner4, size_t segmentCount1, size_t segmentCount2, bool withDiagonals = false) = 0; /** * Create a volumetric soft body from a genmesh. * \param genmeshFactory The genmesh factory to use. * \param if there's an iCollisionObject pointer, attach the iCollisionObject to it. * \remark You must call SetSoftBodyWorld() prior to this. */ virtual csPtr<iSoftBody> CreateSoftBody (iGeneralFactoryState* genmeshFactory) = 0; /** * Create a custom volumetric soft body. * \param vertices The vertices of the soft body. The position is absolute. * \param vertexCount The count of vertices of the soft body. * \param triangles The faces of the soft body. * \param triangleCount The count of faces of the soft body. \param if there's an iCollisionObject pointer, attach the iCollisionObject to it. * \remark You must call SetSoftBodyWorld() prior to this. */ virtual csPtr<iSoftBody> CreateSoftBody (csVector3* vertices, size_t vertexCount, csTriangle* triangles, size_t triangleCount) = 0; }; struct iPhysicalSector : public virtual iBase { SCF_INTERFACE (CS::Physics::iPhysicalSector, 1, 0, 0); /** * Set the simulation speed. A value of 0 means that the simulation is not made * automatically (but it can still be made manually through Step()) */ virtual void SetSimulationSpeed (float speed) = 0; /** * Step the simulation forward by the given duration, in second */ virtual void Step (float duration) = 0; /** * Set the global linear dampener. The dampening correspond to how * much the movements of the objects will be reduced. It is a value * between 0 and 1, giving the ratio of speed that will be reduced * in one second. 0 means that the movement will not be reduced, while * 1 means that the object will not move. * The default value is 0. * \sa CS::Physics::Bullet::iRigidBody::SetLinearDampener() */ virtual void SetLinearDampener (float d) = 0; /** * Get the global linear dampener setting. */ virtual float GetLinearDampener () const = 0; /** * Set the global angular dampener. The dampening correspond to how * much the movements of the objects will be reduced. It is a value * between 0 and 1, giving the ratio of speed that will be reduced * in one second. 0 means that the movement will not be reduced, while * 1 means that the object will not move. * The default value is 0. * \sa CS::Physics::Bullet::iRigidBody::SetRollingDampener() */ virtual void SetRollingDampener (float d) = 0; /** * Get the global rolling dampener setting. */ virtual float GetRollingDampener () const = 0; /** * Turn on/off AutoDisable functionality. * AutoDisable will stop moving objects if they are stable in order * to save processing time. By default this is enabled. */ // always enabled? //virtual void EnableAutoDisable (bool enable) = 0; /** * Return whether the AutoDisable is on or off. */ //virtual bool AutoDisableEnabled () = 0; /** * Set the parameters for AutoDisable. * \param linear Maximum linear movement to disable a body. Default value is 0.8. * \param angular Maximum angular movement to disable a body. Default value is 1.0. * \param steps Minimum number of steps the body meets linear and angular * requirements before it is disabled. Default value is 0. * \param time Minimum time the body needs to meet linear and angular * movement requirements before it is disabled. Default value is 0.0. * \remark With the Bullet plugin, the 'steps' parameter is ignored. * \remark With the Bullet plugin, calling this method will not affect bodies already * created. */ virtual void SetAutoDisableParams (float linear, float angular, int steps, float time) = 0; /** * Add a rigid body into the sector. * The rigid body has to be initialized. */ virtual void AddRidigBody (iRigidBody* body) = 0; /** * Remove a rigid body by pointer. */ virtual void RemoveRigidBody (iRigidBody* body) = 0; /** * Add a soft body into the sector. */ virtual void AddSoftBody (iSoftBody* body) = 0; /** * Remove a soft body by pointer. */ virtual void RemoveSoftBody (iSoftBody* body) = 0; virtual void SetStepParameters (float timeStep, size_t maxSteps, size_t iterations) = 0; }; } } #endif
- bullet.h
#ifndef __IVARIA_PHYSICS_BULLET_H__ #define __IVARIA_PHYSICS_BULLET_H__ namespace CS { namespace Physics { namespace Bullet { enum DebugMode { DEBUG_NOTHING = 0, /*!< Nothing will be displayed. */ DEBUG_COLLIDERS = 1, /*!< Display the colliders of the bodies. */ DEBUG_AABB = 2, /*!< Display the axis aligned bounding boxes of the bodies. */ DEBUG_JOINTS = 4 /*!< Display the joint positions and limits. */ }; struct iSoftBody : public virtual iBase { SCF_INTERFACE (CS::Physics::Bullet::iSoftBody, 1, 0, 0); /** * Draw the debug informations of this soft body. This has to be called * at each frame, and will add 2D lines on top of the rendered scene. */ virtual void DebugDraw (iView* rView) = 0; /// Set linear stiffness coefficient [0,1]. virtual void SetLinearStiff (float stiff) = 0; /// Set area/angular stiffness coefficient [0,1]. virtual void SetAngularStiff (float stiff) = 0; /// Set volume stiffness coefficient [0,1]. virtual void SetVolumeStiff (float vol) = 0; /// Reset the collision flag to 0. virtual void ResetCollisionFlag () = 0; /// Set true if use cluster vs convex handling for rigid vs soft collision detection. virtual void SetClusterCollisionRS (bool cluster) = 0; /// Set true if use cluster vs cluster handling for soft vs soft collision detection. virtual void SetClusterCollisionSS (bool cluster) = 0; /// Set soft vs rigid hardness [0,1] (cluster only). virtual void SetSRHardness (float hardness) = 0; /// Set soft vs kinetic hardness [0,1] (cluster only). virtual void SetSKHardness (float hardness) = 0; /// Set soft vs soft hardness [0,1] (cluster only). virtual void SetSSHardness (float hardness) = 0; /// Set soft vs rigid impulse split [0,1] (cluster only). virtual void SetSRImpulse (float impulse) = 0; /// Set soft vs rigid impulse split [0,1] (cluster only). virtual void SetSKImpulse (float impulse) = 0; /// Set soft vs rigid impulse split [0,1] (cluster only). virtual void SetSSImpulse (float impulse) = 0; /// Set velocities correction factor (Baumgarte). virtual void SetVeloCorrectionFactor (float factor) = 0; /// Set damping coefficient [0,1]. virtual void SetDamping (float damping) = 0; /// Set drag coefficient [0,+inf]. virtual void SetDrag (float drag) = 0; /// Set lift coefficient [0,+inf]. virtual void SetLift (float lift) = 0; /// Set pressure coefficient [-inf,+inf]. virtual void SetPressure (float pressure) = 0; /// Set volume conversation coefficient [0,+inf]. virtual void SetVolumeConversationCoefficient (float conversation) = 0; /// Set pose matching coefficient [0,1]. virtual void SetShapeMatchThreshold (float matching) = 0; /// Set rigid contacts hardness [0,1]. virtual void SetRContactsHardness (float hardness) = 0; /// Set kinetic contacts hardness [0,1]. virtual void SetKContactsHardness (float hardness) = 0; /// Set soft contacts hardness [0,1]. virtual void SetSContactsHardness (float hardness) = 0; /// Set anchors hardness [0,1]. virtual void SetAnchorsHardness (float hardness) = 0; /// Set velocities solver iterations. virtual void SetVeloSolverIterations (int iter) = 0; /// Set positions solver iterations. virtual void SetPositionIterations (int iter) = 0; /// Set drift solver iterations. virtual void SetDriftIterations (int iter) = 0; /// Set cluster solver iterations. virtual void SetClusterIterations (int iter) = 0; /// Set true if use pose matching. virtual void SetShapeMatching (bool match) = 0; /** * Configure the soft body with parameters set above. * If bending constraint is used set it with true. */ //virtual void ConfigureSoftBody (bool bending) = 0; }; struct iPhysicalSystem : public virtual iBase { SCF_INTERFACE (CS::Physics::Bullet::iPhysicalSystem, 1, 0, 0); virtual void StartProfile () = 0; virtual void StopProfile () = 0; virtual void DumpProfile (bool resetProfile = true) = 0; }; struct iPhysicalSector : public virtual iBase { SCF_INTERFACE (CS::Physics::Bullet::iPhysicalSector, 1, 0, 0); /** * Set whether this dynamic world can handle soft bodies or not. * \warning You have to call this method before adding any objects in the * dynamic world. */ virtual void SetSoftBodyEnabled (bool enabled) = 0; /** * Return whether this dynamic world can handle soft bodies or not. */ virtual bool GetSoftBodyEnabled () = 0; virtual void SetGimpactEnabled (bool enabled) = 0; virtual bool GetGimpactEnabled () = 0; /** * Save the current state of the dynamic world in a file. * \return True if the operation succeeds, false otherwise. */ virtual void SaveWorld (const char* filename) = 0; /** * Draw the debug informations of the dynamic system. This has to be called * at each frame, and will add 2D lines on top of the rendered scene. The * objects to be displayed are defined by SetDebugMode(). */ // probably Bullet specific -> CS::Physics::Bullet::iPhysicalSector //Lulu: PhysX supports Debug Rendering. And Havok has a Visual Debugger, but it's client/server architecture. It's quite different from Bullet. // I don't know how to implement visual debugger using these API. Should I move these to Bullet namespace? // kickvb: let's see that later virtual void DebugDraw (iView* rview) = 0; /** * Set the mode to be used when displaying debug informations. The default value * is 'CS::Physics::Bullet::DEBUG_COLLIDERS | CS::Physics::Bullet::DEBUG_JOINTS'. * \remark Don't forget to call DebugDraw() at each frame to effectively display * the debug informations. */ virtual void SetDebugMode (DebugMode mode) = 0; /** * Get the current mode used when displaying debug informations. */ virtual DebugMode GetDebugMode () = 0; }; } } } #endif
Example of use
- the creation of the plugin gives an iCollisionSystem object. If this is the Bullet plugin then this object also implements the iPhysicalSystem interface.
- the user uses the iCollisionSystem interface to create one or more iCollisionSector's and portals connecting them. If this is the Bullet plugin then the sectors also implements the iPhysicalSector interface.
- creation of an object: either through iCollisionSystem for ghost/actor/static collider objects, or through iPhysicalSystem for rigid or soft bodies.
- create colliders through the iCollisionSystem interface and add them to the body. Use the specific object interface to setup the remaining properties.
- call iCollisionObject::RebuildObject () to apply all changes
- add the object in a iCollisionSector, now it is active
Ideas & open questions
- Remove all collision stuff from terrain2. This should go in the iColliderTerrain class.
- Add an higher-level plugin iCollisionManager: mapping a mesh factory/portal to a iCollisionObject/iCollisionPortal + building a iCollisionSector from a iSector + building a collision world from the engine content
-> how to keep it in sync with the engine content? Either iEngine needs the addition of callbacks for sector/mesh/portal added/removed, or the user would have to add/position meshes using the collision manager and no more the engine
