Code:
#ifndef objects_h
#define objects_h
#include "vector2d.h"
class Event;
class Sphere;
class Rect;
class Segment;
class Body
{
public:
vect2 Position;
vect2 Velocity;
float Mass, InvMass;
Body(){}
void Initialize(const vect2& Pos, const vect2& Vel, float o_Mass) //take object's position, Velocity, and mass
{
Position = Pos;
Velocity = Vel;
Mass = o_Mass;
InvMass = (Mass > 0.0f)? 1.0f/Mass : 0.0f;
}
virtual void Update(float dt)
{
Position += Velocity * dt;
}
virtual void ComputeVelocity(float mouse_X, float mouse_Y, float dt)
{
Velocity = (vect2(mouse_X, mouse_Y) - Position) / dt;
}
virtual bool Collision(const Body& bBody, Event& eEvent, float tMax)const = 0;
virtual bool Collision(const Sphere& bBall, Event& eEvent, float tMax) const = 0;
virtual bool Collision(const Rect& rRect, Event& eEvent, float tMax) const = 0;
};
class Event
{
public:
vect2 Pcoll, Ncoll, Vcoll;
Body* pBody[2];
union
{
float tcoll, dcoll;
};
void RunCollision()
{
vect2 Vel = pBody[0]->Velocity - pBody[1]->Velocity;
float mass1 = pBody[0]->InvMass;
float mass2 = pBody[1]->InvMass;
float totalMass = mass1 + mass2;
float vn = Vel.Dot(Ncoll);
float elasticity = 1.0f;
float grip = 0.0f;
vect2 Vn = vn * Ncoll;
vect2 Vt = Vel - Vn;
Vel = -(1.0f + elasticity) * Vn - Vt * (grip);
if(mass1 > 0.0f) pBody[0]->Velocity += Vel*(mass1/totalMass);
if(mass2 > 0.0f) pBody[1]->Velocity -= Vel*(mass2/totalMass);
//make the object seperate
vect2 rPosition = pBody[0]->Position - pBody[1]->Position;
float sgn = sign(rPosition.Dot(Ncoll));
float threshold = 0.1f;
if(mass1 > 0.0f) pBody[0]->Position += sgn * threshold * Ncoll;
if(mass2 > 0.0f) pBody[1]->Position -= sgn * threshold * Ncoll;
}
};
class Segment
{
public:
vect2 Vertex[2];
vect2 Dir;
vect2 Perp;
float length;
Body* bBody;
Segment(){ bBody = NULL; }
Segment(const vect2& P0, const vect2& P1, Body *b_Body)
{
Vertex[0] = P0;
Vertex[1] = P1;
bBody = b_Body;
Dir = Vertex[0] - Vertex[1];
length = Dir.Normalize();
Perp = Dir.Perp();
}
};
class Sphere : public Body
{
public:
float Radius;
int numVer;
vect2* Vertices;
Sphere(){}
void Initialize(const vect2& Pos, const vect2& Vel, float radius)
{
Body::Initialize(Pos, Vel, 1.0f);
Radius = radius;
numVer = 32;
Vertices = new vect2[numVer];
}
bool Collision(const Segment& sSegment, Event& eEvent, float& tMax) const;
bool Collision(const Segment& sSegment, int i, Event& eEvent, float& tMax) const;
bool Collision(const Body& bBody, Event& eEvent, float& tMax) const
{
return bBody.Collision(*this, eEvent, tMax);
}
bool Collision(Sphere& sSphere, Event& eEvent, float& tMax) const{ return false; }
bool Collision(const Rect& rRect, Event& eEvent, float& tMax) const;
void Render() const
{
glBegin(GL_TRIANGLE_FAN);
for(int j=0; j<numVer; j++)
{
float a = 2*PI*(j/numVer);
Vertices[j] = vect2(cos(a)*Radius + Position.x, sin(a)*Radius + Position.y);
glVertex2f(Vertices[j].x, Vertices[j].y);
}
glEnd();
}
};
class Rect : public Body
{
public:
Segment Seg[4];
vect2 Extent;
Rect(){}
void Initialize(const vect2& Pos, const vect2& Ext, float mass)
{
Body::Initialize(Pos, vect2(0, 0), 10.0f);
Extent = Ext;
UpdateSegment();
}
void UpdateSegment()
{
vect2 Min = Position - Extent;
vect2 Max = Position + Extent;
Seg[0] = Segment(vect2(Min.x, Min.y), vect2(Max.x, Min.y), this);
Seg[1] = Segment(vect2(Max.x, Min.y), vect2(Max.x, Max.y), this);
Seg[2] = Segment(vect2(Max.x, Max.y), vect2(Min.x, Max.y), this);
Seg[3] = Segment(vect2(Min.x, Max.y), vect2(Min.x, Min.y), this);
}
void Update(float dt)
{
Body::Update(dt);
UpdateSegment();
}
void Render() const
{
vect2 V[4] = {Seg[0].Vertex[0], Seg[1].Vertex[0], Seg[2].Vertex[0], Seg[3].Vertex[0] };
glBegin(GL_QUADS);
glVertex2fv(&V[0].x);
glVertex2fv(&V[1].x);
glVertex2fv(&V[2].x);
glVertex2fv(&V[3].x);
glEnd();
}
bool Collision(const Body& bBody, Event& eEvent, float tMax)const
{
return bBody.Collision(*this, eEvent, tMax);
}
bool Collision(const Rect& rRect, Event& eEvent, float tMax)const{ return false; }
bool Collision(const Sphere& sSphere, Event& eEvent, float tMax) const
{
bool Collide = false;
Collide |= sSphere.Collision(Seg[0], eEvent, tMax);
Collide |= sSphere.Collision(Seg[1], eEvent, tMax);
Collide |= sSphere.Collision(Seg[2], eEvent, tMax);
Collide |= sSphere.Collision(Seg[3], eEvent, tMax);
return Collide;
}
};
Logically, there would be no problem when declare a Sphere object, but somehow this is getting so weird