#ifndef _PHYSICSBASE_H #define _PHYSICSBASE_H #include "Engine.h" #include "EntityBase.h" namespace coll2d { struct CollisionInfo; } /// \todo get rid of this forward declaration somehow struct vector3d; namespace Engine { class Module; class Events; class EntityPhysicState; /** \brief Performs the physical simulation of all Entities * * This class defines how the physical simulation is performed. Especially how * collisions are treated is defined in the function * Physics::ResolveCollision() . This function can be modified to simulate * dynamics effects such as friction, bouncing, stacking etc.. * * \todo When running along multiple boxes that are perfectly aligned one hangs from time to time at the last box */ class PhysicsBase : public Module { public: /** \brief Performs the simulation for the next msec milliseconds * \param msec The amount of time that is to be simulated * \param model A pointer to the model that will be used to pass on collision events.*/ virtual int Simulate (float msec, ModelBase* model = NULL); /** \brief Registers the physical state of an Entity */ virtual void RegisterEntity (EntityPhysicState* entity); /** \brief Unregisters the physical state of an Entity */ virtual void UnregisterEntity (const unsigned int id); /** \brief Calculates the next pair of Entities that will collide */ bool CalcNextCollision (float stepsize, unsigned int &reference_entity_id, unsigned int &incidence_entity_id, coll2d::CollisionInfo &info); /** \brief Modes for warping entities when they reach the world boundaries */ enum WorldWarp { WorldWarpModeX = 0, WorldWarpModeY, WorldWarpModeZ, WorldWarpModeLast }; void EnableWorldWarp (WorldWarp mode) { mWorldWarp.set(mode, true); } void DisableWorldWarp (WorldWarp mode) { mWorldWarp.set(mode, false); } /** \brief Sets world boundaries (needed for Entity warping) */ void SetWorldBounds (const vector3d &min_bound, const vector3d &max_bound) { mWorldMin = min_bound; mWorldMax = max_bound; } protected: /** \brief Initializes the system */ virtual int OnInit (int argc, char* argv[]); /** \brief Destroys the system (must be called!) */ virtual void OnDestroy (); /** \brief Moves all Entities for delta_msec milliseconds (can be * negative!) */ void Move (float delta_msec); /** \brief Checks whether two given Entities can collide */ bool CheckPossibleCollisionPair (EntityPhysicState* entity_a, EntityPhysicState* entity_b); /** \brief Resolves the collision that CalcNextCollision has found * It resolves a found collision and prevents interpenetration of cached contacts. */ void ResolveCollision (float stepsize, unsigned int reference_entity_id, unsigned int incidence_entity_id, coll2d::CollisionInfo &info); /** \brief Contains all Entities with a physical state */ std::map mEntities; private: /** \brief Caches the contact information between two entities */ void ContactCacheAdd (EntityPhysicState* incidence_entity, EntityPhysicState* reference_entity, vector3d normal); /** \brief Removes the contact cache information of two entities in contact */ void ContactCacheRemove (unsigned int entity_a_id, unsigned int entity_b_id); /** \brief Checks whether the entries in the contact cache are still valid */ void CheckContactCache (EntityPhysicState* entity); /** \brief Checks whether the entity has to be warped from one world boundary to the other * * \returns The directions in which the entity should be warped * */ vector3d CheckEntityWarp (EntityPhysicState* entity, float stepsize); /** \brief Performs collision checks for all candidates of warped positions * * \returns >0 for collisions, = 0 for no collisions, < 0 coll2d error */ int PerformWarpedCollisionChecks (float stepsize, EntityPhysicState* entity_a, EntityPhysicState* entity_b, vector3d warp_directions, coll2d::CollisionInfo &info); /** \brief Allows to ignore certain kinds of errors reported by coll2d */ bool HandleColl2dError (int coll2d_result, float stepsize, EntityPhysicState* entity_a, EntityPhysicState* entity_b, coll2d::CollisionInfo &info); std::bitset mWorldWarp; vector3d mWorldMin; vector3d mWorldMax; }; /** \brief Creates an EntityPhysicState with all the required information */ EntityPhysicState* CreateEntityPhysicState (EntityBaseType type, unsigned int id); } #endif // _PHYSICSBASE_H