| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402 |
- #ifndef PHYSICSCONTROLLER_H_
- #define PHYSICSCONTROLLER_H_
- #include "PhysicsConstraint.h"
- #include "PhysicsFixedConstraint.h"
- #include "PhysicsGenericConstraint.h"
- #include "PhysicsHingeConstraint.h"
- #include "PhysicsSocketConstraint.h"
- #include "PhysicsSpringConstraint.h"
- #include "PhysicsCollisionObject.h"
- #include "MeshBatch.h"
- namespace gameplay
- {
- /**
- * Defines a class for controlling game physics.
- */
- class PhysicsController : public btCollisionWorld::ContactResultCallback
- {
- friend class Game;
- friend class PhysicsConstraint;
- friend class PhysicsRigidBody;
- friend class PhysicsCharacter;
- friend class PhysicsCollisionObject;
- friend class PhysicsGhostObject;
- public:
- /**
- * Status listener interface.
- */
- class Listener
- {
- public:
- /**
- * The type of physics status event.
- */
- enum EventType
- {
- /**
- * Event fired when there were no active physics objects and at least one is now active.
- */
- ACTIVATED,
- /**
- * Event fired when there are no more active physics objects in the world.
- */
- DEACTIVATED
- };
- /**
- * Handles when a physics world status event occurs.
- */
- virtual void statusEvent(EventType type) = 0;
- };
- /**
- * Stucture that stores hit test results for ray and sweep tests.
- */
- struct HitResult
- {
- /**
- * The collision object that was hit.
- */
- PhysicsCollisionObject* object;
- /**
- * The point where the collision occurred, in world space.
- */
- Vector3 point;
- /**
- * The fraction (0-1) of the test distance to the collision point.
- */
- float fraction;
- /**
- * The normal vector of the collision surface, in world space.
- */
- Vector3 normal;
- };
- /**
- * Adds a listener to the physics controller.
- *
- * @param listener The listener to add.
- */
- void addStatusListener(PhysicsController::Listener* listener);
- /**
- * Creates a fixed constraint.
- *
- * @param a The first (possibly only) rigid body to constrain. If this is the only rigid
- * body specified the constraint applies between it and the global physics world object.
- * @param b The second rigid body to constrain (optional).
- */
- PhysicsFixedConstraint* createFixedConstraint(PhysicsRigidBody* a, PhysicsRigidBody* b = NULL);
- /**
- * Creates a generic constraint so that the rigid body (or bodies) is
- * (are) constrained to its (their) current world position(s).
- *
- * @param a The first (possibly only) rigid body to constrain. If this is the only rigid
- * body specified the constraint applies between it and the global physics world object.
- * @param b The second rigid body to constrain (optional).
- */
- PhysicsGenericConstraint* createGenericConstraint(PhysicsRigidBody* a, PhysicsRigidBody* b = NULL);
- /**
- * Creates a generic constraint.
- *
- * @param a The first (possibly only) rigid body to constrain. If this is the only rigid
- * body specified the constraint applies between it and the global physics world object.
- * @param rotationOffsetA The rotation offset for the first rigid body
- * (in its local space) with respect to the constraint joint.
- * @param translationOffsetA The translation offset for the first rigid body
- * (in its local space) with respect to the constraint joint.
- * @param b The second rigid body to constrain (optional).
- * @param rotationOffsetB The rotation offset for the second rigid body
- * (in its local space) with respect to the constraint joint (optional).
- * @param translationOffsetB The translation offset for the second rigid body
- * (in its local space) with respect to the constraint joint (optional).
- */
- PhysicsGenericConstraint* createGenericConstraint(PhysicsRigidBody* a, const Quaternion& rotationOffsetA, const Vector3& translationOffsetA,
- PhysicsRigidBody* b = NULL, const Quaternion& rotationOffsetB = Quaternion(), const Vector3& translationOffsetB = Vector3());
- /**
- * Creates a hinge constraint.
- *
- * @param a The first (possibly only) rigid body to constrain. If this is the only rigid
- * body specified the constraint applies between it and the global physics world object.
- * @param rotationOffsetA The rotation offset for the first rigid body
- * (in its local space) with respect to the constraint joint.
- * @param translationOffsetA The translation offset for the first rigid body
- * (in its local space) with respect to the constraint joint.
- * @param b The second rigid body to constrain (optional).
- * @param rotationOffsetB The rotation offset for the second rigid body
- * (in its local space) with respect to the constraint joint (optional).
- * @param translationOffsetB The translation offset for the second rigid body
- * (in its local space) with respect to the constraint joint (optional).
- */
- PhysicsHingeConstraint* createHingeConstraint(PhysicsRigidBody* a, const Quaternion& rotationOffsetA, const Vector3& translationOffsetA,
- PhysicsRigidBody* b = NULL, const Quaternion& rotationOffsetB = Quaternion(), const Vector3& translationOffsetB = Vector3());
- /**
- * Creates a socket constraint so that the rigid body (or bodies) is
- * (are) constrained using its (their) current world position(s) for
- * the translation offset(s) to the constraint.
- *
- * @param a The first (possibly only) rigid body to constrain. If this is the only rigid
- * body specified the constraint applies between it and the global physics world object.
- * @param b The second rigid body to constrain (optional).
- */
- PhysicsSocketConstraint* createSocketConstraint(PhysicsRigidBody* a, PhysicsRigidBody* b = NULL);
- /**
- * Creates a socket constraint.
- *
- * @param a The first (possibly only) rigid body to constrain. If this is the only rigid
- * body specified the constraint applies between it and the global physics world object.
- * @param translationOffsetA The translation offset for the first rigid body
- * (in its local space) with respect to the constraint joint.
- * @param b The second rigid body to constrain (optional).
- * @param translationOffsetB The translation offset for the second rigid body
- * (in its local space) with respect to the constraint joint (optional).
- */
- PhysicsSocketConstraint* createSocketConstraint(PhysicsRigidBody* a, const Vector3& translationOffsetA,
- PhysicsRigidBody* b = NULL, const Vector3& translationOffsetB = Vector3());
- /**
- * Creates a spring constraint so that the rigid body (or bodies) is
- * (are) constrained using its (their) current world position(s) for
- * the translation offset(s) to the constraint.
- *
- * @param a The first (possibly only) rigid body to constrain. If this is the only rigid
- * body specified the constraint applies between it and the global physics world object.
- * @param b The second rigid body to constrain (optional).
- */
- PhysicsSpringConstraint* createSpringConstraint(PhysicsRigidBody* a, PhysicsRigidBody* b);
- /**
- * Creates a spring constraint.
- *
- * @param a The first (possibly only) rigid body to constrain. If this is the only rigid
- * body specified the constraint applies between it and the global physics world object.
- * @param rotationOffsetA The rotation offset for the first rigid body
- * (in its local space) with respect to the constraint joint.
- * @param translationOffsetA The translation offset for the first rigid body
- * (in its local space) with respect to the constraint joint.
- * @param b The second rigid body to constrain (optional).
- * @param rotationOffsetB The rotation offset for the second rigid body
- * (in its local space) with respect to the constraint joint (optional).
- * @param translationOffsetB The translation offset for the second rigid body
- * (in its local space) with respect to the constraint joint (optional).
- */
- PhysicsSpringConstraint* createSpringConstraint(PhysicsRigidBody* a, const Quaternion& rotationOffsetA, const Vector3& translationOffsetA,
- PhysicsRigidBody* b, const Quaternion& rotationOffsetB, const Vector3& translationOffsetB);
- /**
- * Gets the gravity vector for the simulated physics world.
- *
- * @return The gravity vector.
- */
- const Vector3& getGravity() const;
- /**
- * Sets the gravity vector for the simulated physics world.
- *
- * @param gravity The gravity vector.
- */
- void setGravity(const Vector3& gravity);
- /**
- * Draws debugging information (rigid body outlines, etc.) using the given view projection matrix.
- *
- * @param viewProjection The view projection matrix to use when drawing.
- */
- void drawDebug(const Matrix& viewProjection);
- /**
- * Performs a ray test on the physics world.
- *
- * @param ray The ray to test intersection with.
- * @param distance How far along the given ray to test for intersections.
- * @param result Optioanl pointer to a HitTest structure to store hit test result information in.
- * @return True if the ray test collided with a physics object, false otherwise.
- */
- bool rayTest(const Ray& ray, float distance, PhysicsController::HitResult* result = NULL);
- /**
- * Performs a sweep test of the given collision object on the physics world.
- *
- * The start position of the sweep test is defined by the current world position
- * of the specified collision object.
- *
- * @param object The collision object to test.
- * @param endPosition The end position of the sweep test, in world space.
- * @return True if the object intersects any other physics objects, false otherwise.
- */
- bool sweepTest(PhysicsCollisionObject* object, const Vector3& endPosition, PhysicsController::HitResult* result = NULL);
- protected:
- /**
- * Internal function used for Bullet integration (do not use or override).
- */
- btScalar addSingleResult(btManifoldPoint& cp, const btCollisionObject* a, int partIdA, int indexA, const btCollisionObject* b, int partIdB, int indexB);
- private:
- // Internal constants for the collision status cache.
- static const int DIRTY;
- static const int COLLISION;
- static const int REGISTERED;
- static const int REMOVE;
- // Represents the collision listeners and status for a given collision pair (used by the collision status cache).
- struct CollisionInfo
- {
- CollisionInfo() : _status(0) { }
- std::vector<PhysicsCollisionObject::CollisionListener*> _listeners;
- int _status;
- };
- /**
- * Constructor.
- */
- PhysicsController();
- /**
- * Destructor.
- */
- ~PhysicsController();
- /**
- * Controller initialize.
- */
- void initialize();
- /**
- * Controller finalize.
- */
- void finalize();
- /**
- * Controller pause.
- */
- void pause();
- /**
- * Controller resume.
- */
- void resume();
- /**
- * Controller update.
- */
- void update(long elapsedTime);
- // Adds the given collision listener for the two given collision objects.
- void addCollisionListener(PhysicsCollisionObject::CollisionListener* listener, PhysicsCollisionObject* objectA, PhysicsCollisionObject* objectB);
- // Removes the given collision listener.
- void removeCollisionListener(PhysicsCollisionObject::CollisionListener* listener, PhysicsCollisionObject* objectA, PhysicsCollisionObject* objectB);
- // Adds the given collision object to the world.
- void addCollisionObject(PhysicsCollisionObject* object);
-
- // Removes the given collision object from the simulated physics world.
- void removeCollisionObject(PhysicsCollisionObject* object);
-
- // Gets the corresponding GamePlay object for the given Bullet object.
- PhysicsCollisionObject* getCollisionObject(const btCollisionObject* collisionObject) const;
- // Creates a collision shape for the given node and gameplay shape definition.
- // Populates 'centerOfMassOffset' with the correct calculated center of mass offset.
- PhysicsCollisionShape* createShape(Node* node, const PhysicsCollisionShape::Definition& shape, Vector3* centerOfMassOffset);
-
- // Creates a box collision shape.
- PhysicsCollisionShape* createBox(const Vector3& extents, const Vector3& scale);
- // Creates a sphere collision shape.
- PhysicsCollisionShape* createSphere(float radius, const Vector3& scale);
- // Creates a capsule collision shape.
- PhysicsCollisionShape* createCapsule(float radius, float height, const Vector3& scale);
- // Creates a heightfield collision shape.
- PhysicsCollisionShape* createHeightfield(Node* node, Image* image, Vector3* centerOfMassOffset);
- // Creates a triangle mesh collision shape.
- PhysicsCollisionShape* createMesh(Mesh* mesh, const Vector3& scale);
- // Destroys a collision shape created through PhysicsController
- void destroyShape(PhysicsCollisionShape* shape);
- // Helper function for calculating heights from heightmap (image) or heightfield data.
- static float calculateHeight(float* data, unsigned int width, unsigned int height, float x, float y);
- // Sets up the given constraint for the given two rigid bodies.
- void addConstraint(PhysicsRigidBody* a, PhysicsRigidBody* b, PhysicsConstraint* constraint);
- // Checks whether constraints are supported for the given rigid bodies and emits a warning if they are not.
- bool checkConstraintRigidBodies(PhysicsRigidBody* a, PhysicsRigidBody* b);
-
- // Removes the given constraint from the simulated physics world.
- void removeConstraint(PhysicsConstraint* constraint);
-
- // Draws Bullet debug information.
- class DebugDrawer : public btIDebugDraw
- {
- public:
- struct DebugVertex
- {
- float x, y, z;
- float r, g, b, a;
- };
- DebugDrawer();
- ~DebugDrawer();
-
- void begin(const Matrix& viewProjection);
- void end();
- // Overridden Bullet functions from btIDebugDraw.
- void drawLine(const btVector3& from, const btVector3& to, const btVector3& fromColor, const btVector3& toColor);
- void drawLine(const btVector3& from, const btVector3& to, const btVector3& color);
- void drawContactPoint(const btVector3& pointOnB, const btVector3& normalOnB, btScalar distance, int lifeTime, const btVector3& color);
- void reportErrorWarning(const char* warningString);
- void draw3dText(const btVector3& location, const char* textString);
- void setDebugMode(int mode);
- int getDebugMode() const;
-
- private:
-
- int _mode;
- const Matrix* _viewProjection;
- MeshBatch* _meshBatch;
- };
- btDefaultCollisionConfiguration* _collisionConfiguration;
- btCollisionDispatcher* _dispatcher;
- btBroadphaseInterface* _overlappingPairCache;
- btSequentialImpulseConstraintSolver* _solver;
- btDynamicsWorld* _world;
- btGhostPairCallback* _ghostPairCallback;
- std::vector<PhysicsCollisionShape*> _shapes;
- DebugDrawer* _debugDrawer;
- Listener::EventType _status;
- std::vector<Listener*>* _listeners;
- Vector3 _gravity;
- std::map<PhysicsCollisionObject::CollisionPair, CollisionInfo> _collisionStatus;
- };
- }
- #endif
|