initial commit
This commit is contained in:
@@ -0,0 +1,346 @@
|
||||
#ifndef _COLL2D_H
|
||||
#define _COLL2D_H
|
||||
|
||||
/** \brief Coll2d - A 2d collision detection library
|
||||
* \author Martin Felis <martin@silef.de>
|
||||
*
|
||||
* This library provides functions to detect collisions between polygons and
|
||||
* spheres.
|
||||
*
|
||||
* Notes:
|
||||
* - vertices of polygons are described in local coordinates
|
||||
* - return values of check_collision are in global coordinates
|
||||
* - all Shapes get copied to a temporary instance which will then get
|
||||
* transferred into global coordinates
|
||||
* - Polygons are assumed to be convex and the vertices are stored
|
||||
* counter clockwise.
|
||||
* - The transformation of the global position and velocities towards
|
||||
* relative position and velocities happens in the
|
||||
* int check_collision_<type>_<type> functions!
|
||||
*/
|
||||
|
||||
#include <mathlib.h>
|
||||
#include <iostream>
|
||||
#include <cstring>
|
||||
|
||||
#include <coll2d_errors.h>
|
||||
|
||||
namespace coll2d {
|
||||
|
||||
/** \brief Contains the information of a collision
|
||||
*
|
||||
* \param normal The normal of the reference plane
|
||||
* \param point The actual point where the collision happens in global
|
||||
* cooldinates
|
||||
* \param time If both objects move for this amount of time the contact
|
||||
* will occur.
|
||||
* \param reference_shape
|
||||
* If 0, the first shape passed to he check_collision function
|
||||
* is the reference shape, otherwise the second.
|
||||
*/
|
||||
struct CollisionInfo {
|
||||
vector3d normal;
|
||||
vector3d point;
|
||||
float time;
|
||||
int reference_shape;
|
||||
|
||||
CollisionInfo () : normal (0., 0., 0.), point (0., 0., 0.), time (-1.), reference_shape (-1) {
|
||||
}
|
||||
|
||||
CollisionInfo& operator= (const CollisionInfo& info) {
|
||||
if (this != &info) {
|
||||
normal = info.normal;
|
||||
point = info.point;
|
||||
time = info.time;
|
||||
reference_shape = info.reference_shape;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
void doPrint (const char* msg) {
|
||||
std::cout << msg;
|
||||
std::cout << "Time = " << time << std::endl;
|
||||
normal.print ("Normal = ");
|
||||
point.print ( "Point = ");
|
||||
std::cout << "Reference = " << reference_shape << std::endl;
|
||||
}
|
||||
};
|
||||
|
||||
/** \brief Base class for all shapes
|
||||
*
|
||||
*/
|
||||
class Shape {
|
||||
protected:
|
||||
vector3d mPosition;
|
||||
vector3d mVelocity;
|
||||
float mAngle;
|
||||
float mAngleVelocity;
|
||||
|
||||
virtual void dummy() {
|
||||
}
|
||||
public:
|
||||
Shape():
|
||||
mPosition (0., 0., 0.),
|
||||
mVelocity (0., 0., 0.),
|
||||
mAngle (0.),
|
||||
mAngleVelocity (0.) {
|
||||
}
|
||||
Shape (const Shape &shape):
|
||||
mPosition (shape.mPosition),
|
||||
mVelocity (shape.mVelocity),
|
||||
mAngle (shape.mAngle),
|
||||
mAngleVelocity (shape.mAngleVelocity)
|
||||
{ }
|
||||
|
||||
virtual ~Shape () {};
|
||||
|
||||
/** \brief Creates and returns a copy of itself */
|
||||
virtual Shape* getCopy () = 0;
|
||||
|
||||
void setPosition(vector3d position) {
|
||||
mPosition = position;
|
||||
}
|
||||
vector3d getPosition() {
|
||||
return mPosition;
|
||||
}
|
||||
void setVelocity(vector3d velocity) {
|
||||
mVelocity = velocity;
|
||||
}
|
||||
vector3d getVelocity() {
|
||||
return mVelocity;
|
||||
}
|
||||
|
||||
void setAngle (const float &angle) {
|
||||
mAngle = angle;
|
||||
}
|
||||
float getAngle () {
|
||||
return mAngle;
|
||||
}
|
||||
void setAngleVelocity (float angle_velocity) {
|
||||
mAngleVelocity = angle_velocity;
|
||||
}
|
||||
float getAngleVelocity () {
|
||||
return mAngleVelocity;
|
||||
}
|
||||
|
||||
virtual void doPrintType() {
|
||||
std::cout << "Shape" << std::endl;
|
||||
}
|
||||
virtual void doPrint (const char* name) {
|
||||
std::cout << name << "<unknown shape>" << std::endl;
|
||||
}
|
||||
friend int check_collision_rel(Shape *shape_a, Shape *shape_b,
|
||||
vector3d *velocity_b, CollisionInfo* info);
|
||||
};
|
||||
|
||||
class Polygon: public Shape {
|
||||
private:
|
||||
unsigned int mVerticeCount;
|
||||
vector3d *mVertices;
|
||||
bool mFreeVertices;
|
||||
public:
|
||||
Polygon() {
|
||||
mVerticeCount = 0;
|
||||
mVertices = NULL;
|
||||
mFreeVertices = false;
|
||||
}
|
||||
Polygon(unsigned int n) {
|
||||
mVerticeCount = n;
|
||||
mVertices = new vector3d[n];
|
||||
mFreeVertices = true;
|
||||
}
|
||||
Polygon(unsigned int n, vector3d *vertices) {
|
||||
mVerticeCount = n;
|
||||
mFreeVertices = false;
|
||||
|
||||
if (vertices == NULL && n > 0) {
|
||||
mVertices = new vector3d [n];
|
||||
mFreeVertices = true;
|
||||
}
|
||||
|
||||
mVertices = vertices;
|
||||
}
|
||||
Polygon (const Polygon &polygon) : Shape (polygon) {
|
||||
mVerticeCount = polygon.mVerticeCount;
|
||||
mFreeVertices = true;
|
||||
|
||||
mVertices = new vector3d[mVerticeCount];
|
||||
memcpy (mVertices, polygon.mVertices, sizeof (vector3d) * mVerticeCount);
|
||||
}
|
||||
virtual ~Polygon () {
|
||||
if (mFreeVertices == true && mVertices)
|
||||
delete[] mVertices;
|
||||
}
|
||||
|
||||
virtual Polygon* getCopy () {
|
||||
Polygon *copy = new Polygon (*this);
|
||||
|
||||
assert (copy);
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
||||
virtual void doPrintType() {
|
||||
std::cout << "Polygon" << std::endl;
|
||||
}
|
||||
|
||||
virtual void doPrint (const char* name) {
|
||||
std::cout << name << " (Polygon)" << std::endl;
|
||||
|
||||
std::cout << "mVerticeCount = " << mVerticeCount << std::endl;
|
||||
unsigned int i;
|
||||
for (i = 0; i < mVerticeCount; i ++) {
|
||||
std::cout << i << " = " << mVertices[i][0] << ", " <<
|
||||
mVertices[i][1] << ", " <<
|
||||
mVertices[i][2] << std::endl;
|
||||
}
|
||||
std::cout << "mPosition = " << mPosition[0] <<", " <<
|
||||
mPosition[1] << ", " <<
|
||||
mPosition[2] << std::endl;
|
||||
|
||||
std::cout << "mVelocity = " << mVelocity[0] <<", " <<
|
||||
mVelocity[1] << ", " <<
|
||||
mVelocity[2] << std::endl;
|
||||
|
||||
std::cout << "mAngle = " << mAngle << std::endl;
|
||||
std::cout << "mAngleVelocity = " << mAngleVelocity << std::endl;
|
||||
}
|
||||
|
||||
unsigned int getVerticeCount () {
|
||||
return mVerticeCount;
|
||||
}
|
||||
|
||||
vector3d& getVertice (unsigned int i) {
|
||||
assert (i >= 0 && i < mVerticeCount);
|
||||
return mVertices [i];
|
||||
}
|
||||
|
||||
void setVertice (unsigned int i, const vector3d &vertice) {
|
||||
assert (i >= 0 && i < mVerticeCount);
|
||||
mVertices[i] = vertice;
|
||||
}
|
||||
|
||||
friend int check_collision_polygon_sphere(Shape *polygon_a,
|
||||
Shape *sphere_b, CollisionInfo* info);
|
||||
};
|
||||
|
||||
class Sphere: public Shape {
|
||||
private:
|
||||
float mRadius;
|
||||
public:
|
||||
Sphere (float radius) {
|
||||
mRadius = radius;
|
||||
Shape::setPosition (vector3d (0., 0., 0.));
|
||||
}
|
||||
|
||||
Sphere(float radius, const vector3d &position) {
|
||||
mRadius = radius;
|
||||
Shape::setPosition(position);
|
||||
}
|
||||
|
||||
Sphere (const Sphere &sphere):
|
||||
Shape (sphere),
|
||||
mRadius (sphere.mRadius) { }
|
||||
|
||||
virtual Sphere* getCopy() {
|
||||
Sphere* copy = new Sphere (*this);
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
||||
virtual void doPrintType() {
|
||||
std::cout << "Sphere" << std::endl;
|
||||
}
|
||||
|
||||
virtual void doPrint (const char* name) {
|
||||
std::cout << name << " (Sphere)" << std::endl;
|
||||
|
||||
std::cout << "mRadius = " << mRadius << std::endl;
|
||||
std::cout << "mPosition = " << mPosition[0] <<", " <<
|
||||
mPosition[1] << ", " <<
|
||||
mPosition[2] << std::endl;
|
||||
|
||||
std::cout << "mVelocity = " << mVelocity[0] <<", " <<
|
||||
mVelocity[1] << ", " <<
|
||||
mVelocity[2] << std::endl;
|
||||
|
||||
std::cout << "mAngle = " << mAngle << std::endl;
|
||||
std::cout << "mAngleVelocity = " << mAngleVelocity << std::endl;
|
||||
}
|
||||
|
||||
|
||||
void setRadius (float radius) {
|
||||
mRadius = radius;
|
||||
}
|
||||
|
||||
float getRadius () {
|
||||
return mRadius;
|
||||
}
|
||||
|
||||
friend int check_collision_polygon_sphere(Shape *polygon_a,
|
||||
Shape *sphere_b, CollisionInfo* info);
|
||||
};
|
||||
|
||||
/** \brief The higher level function to call for collision detection
|
||||
*
|
||||
* \param stepsize the timestep within we want to check for the collision
|
||||
* \param shape_a first shape
|
||||
* \param shape_b second shape
|
||||
* \param info information about the collision will be to info
|
||||
*
|
||||
* \returns 0 - no collision, negative on error, positive on collision
|
||||
*/
|
||||
int check_collision(float timestep, Shape *shape_a, Shape *shape_b, CollisionInfo* info);
|
||||
|
||||
/** \brief The higher level function to call for collision detection
|
||||
*
|
||||
* \param shape_a first shape
|
||||
* \param shape_b second shape
|
||||
* \param velocity_b relative velocity of b to a
|
||||
* \param info information about the collision will be to info
|
||||
*
|
||||
* \returns 0 - no collision, negative on error, positive on collision
|
||||
*/
|
||||
int check_collision_rel(float timestep, Shape *shape_a, Shape *shape_b, vector3d *velocity_b,
|
||||
CollisionInfo* info);
|
||||
|
||||
/** \brief Callback signature for the check functions */
|
||||
typedef int (*check_cb)(float timestep, Shape *shape_a, Shape *shape_b, CollisionInfo* info);
|
||||
|
||||
/** \brief Returns the check functions which performs the checks depending
|
||||
* on their types. */
|
||||
check_cb get_check(Shape *shape_a, Shape *shape_b);
|
||||
|
||||
/** \brief Performs a check between a polygon and a sphere
|
||||
*/
|
||||
int check_collision_polygon_sphere(float timestep, Shape *shape_a, Shape *shape_b,
|
||||
CollisionInfo* info);
|
||||
|
||||
/** \brief Performs a check between a sphere and a sphere
|
||||
*/
|
||||
int check_collision_sphere_sphere(float timestep, Shape *shape_a, Shape *shape_b,
|
||||
CollisionInfo* info);
|
||||
|
||||
|
||||
/** \brief Calculates the time it takes for a point to touch a plane
|
||||
*
|
||||
* \param normal normal vector of the plane
|
||||
* \param plane_point point on the vector
|
||||
* \param point point that is moving
|
||||
* \param velocity velocity of the point
|
||||
*
|
||||
* \returns -1 if point is moving away from the plane (or is below and
|
||||
* moves even further below
|
||||
* >= 0 if point is moving along the plane or towards the plane
|
||||
*
|
||||
* This function depends on the scale of velocity. It is assumed
|
||||
* that velocity represents the displacement in one frame. In this
|
||||
* case a return value > 1 means there will not be a contact
|
||||
* within this frame.
|
||||
*/
|
||||
float calculate_contact_plane_point(vector3d &normal, vector3d &plane_point, vector3d &point, vector3d &velocity);
|
||||
|
||||
}
|
||||
|
||||
#endif /* _COLL2D_H */
|
||||
@@ -0,0 +1,9 @@
|
||||
#ifndef _COLL2D_ERRORS
|
||||
#define _COLL2D_ERRORS
|
||||
|
||||
#define CHECK_ERROR_UNKNOWN -9999
|
||||
#define CHECK_ERROR_NOT_IMPLEMENTED -1
|
||||
#define CHECK_ERROR_INVALID_TYPES -2
|
||||
#define CHECK_ERROR_OVERLAP -3
|
||||
|
||||
#endif /* _COLL2D_ERRORS */
|
||||
Reference in New Issue
Block a user