Commit a3bf8ade authored by Leon's avatar Leon

Delete Bodies when they leave the scene; further optimizations

parent 2e44ec17
......@@ -60,7 +60,6 @@ void Mouse(int button, int state, int x, int y)
{
case GLUT_LEFT_BUTTON:
{
RenderString(1, 6, "Spawning Polygon");
unsigned int count = (unsigned int)rand(3.f, (float)MAX_POLY_COUNT);
vector<duodim::Vector2D> vertices;
float random = rand(5.f, 10.f);
......@@ -69,16 +68,16 @@ void Mouse(int button, int state, int x, int y)
vertices.push_back(duodim::Vector2D(rand(-random, random), rand(-random, random)));
}
duodim::ConvexPolygon* cp = new duodim::ConvexPolygon(vertices);
duodim::Texture tex = duodim::Texture::red();
duodim::Body* b = new duodim::Body((float) x, (float) y, &duodim::Material::wood(), cp, &tex);
duodim::Texture* tex = duodim::Texture::red();
duodim::Body* b = new duodim::Body((float) x, (float) y, duodim::Material::wood(), cp, tex);
s->bodies.push_back(b);
}
break;
case GLUT_RIGHT_BUTTON:
{
duodim::Circle* cs = new duodim::Circle(rand(1.f, 3.f));
duodim::Texture tex = duodim::Texture::green();
duodim::Body* c = new duodim::Body((float) x, (float) y, &duodim::Material::bouncyBall(), cs, &tex);
duodim::Texture* tex = duodim::Texture::green();
duodim::Body* c = new duodim::Body((float) x, (float) y, duodim::Material::bouncyBall(), cs, tex);
s->bodies.push_back(c);
}
break;
......@@ -105,8 +104,9 @@ void Keyboard(unsigned char key, int x, int y)
void PhysicsLoop(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
RenderString(1, 2, "Left click to spawn a polygon");
RenderString(1, 4, "Right click to spawn a circle");
RenderString(1, 2, "DuoDim Engine");
RenderString(1, 4, "Left click to spawn a polygon");
RenderString(1, 6, "Right click to spawn a circle");
e->iterate();
glutSwapBuffers();
}
......@@ -139,6 +139,8 @@ int main(int argc, char** argv)
{
e = duodim::Engine::getInstance(); // fire up engine
s = duodim::Scene::getInstance();
s->sceneHeight = 800;
s->sceneWidth = 600;
checkArgs(argc, argv);
if (initGui(argc, argv) == -1)
{
......@@ -149,8 +151,8 @@ int main(int argc, char** argv)
{
duodim::ConvexPolygon* poly = new duodim::ConvexPolygon();
poly->setBox(30.0f, 1.0f);
duodim::Texture tex = duodim::Texture::blue();
duodim::Body* b = new duodim::Body(40.f, 55.f, &duodim::Material::wood(), poly, &tex);
duodim::Texture* tex = duodim::Texture::blue();
duodim::Body* b = new duodim::Body(40.f, 55.f, duodim::Material::wood(), poly, tex);
b->setStatic();
s->bodies.push_back(b);
......
......@@ -8,16 +8,16 @@ namespace duodim
public:
Vector2D min;
Vector2D max;
static AxisAlignedBoundingBox fromCenterAndExtents(Vector2D center, const Vector2D extents);
static AxisAlignedBoundingBox asUnion(AxisAlignedBoundingBox a, AxisAlignedBoundingBox b);
static AxisAlignedBoundingBox* fromCenterAndExtents(Vector2D center, const Vector2D extents);
static AxisAlignedBoundingBox* asUnion(AxisAlignedBoundingBox a, AxisAlignedBoundingBox b);
AxisAlignedBoundingBox();
AxisAlignedBoundingBox(Vector2D min, Vector2D max);
Vector2D getCenter();
Vector2D getExtents();
AxisAlignedBoundingBox expandBy(const float factor);
AxisAlignedBoundingBox* expandBy(const float factor);
float getPerimeter();
bool intersects(AxisAlignedBoundingBox o);
bool contains(AxisAlignedBoundingBox o);
bool intersects(AxisAlignedBoundingBox* o);
bool contains(AxisAlignedBoundingBox* o);
};
}
#endif
\ No newline at end of file
......@@ -26,7 +26,6 @@ namespace duodim
float inv_mass;
float inv_inertia;
Body(Vector2D position, Material* material, Shape* shape, Texture* texture);
Body(float posX, float posY, Material* material, Shape* shape, Texture* texture);
~Body();
......@@ -44,8 +43,6 @@ namespace duodim
void nullifyVelocity();
void setStatic();
void unsetStatic();
private:
void initialize();
};
}
#endif
\ No newline at end of file
......@@ -11,6 +11,7 @@ namespace duodim
{
public:
static vector<CollisionPair> getNarrowPhaseCandidates(vector<Body*> bodies);
static bool isBodyLeftScene(Body* t, float x, float y);
};
}
#endif
\ No newline at end of file
......@@ -12,7 +12,7 @@ namespace duodim
Circle(float radius);
~Circle();
AxisAlignedBoundingBox getBounds();
AxisAlignedBoundingBox* getBounds();
MassAndInertia getMassAndInertia();
ShapeType getType();
void draw();
......
......@@ -18,7 +18,7 @@ namespace duodim
ConvexPolygon(vector<Vector2D> vertices);
~ConvexPolygon();
AxisAlignedBoundingBox getBounds();
AxisAlignedBoundingBox* getBounds();
MassAndInertia getMassAndInertia();
ShapeType getType();
Vector2D getSupport(Vector2D& direction);
......
......@@ -9,11 +9,12 @@ namespace duodim
float staticFriction;
float restitution;
float density;
static Material wood();
static Material bouncyBall();
static Material superBall();
static Material* wood();
static Material* bouncyBall();
static Material* superBall();
Material();
Material(float dynamicfriction, float staticFriction, float restitution, float density);
~Material();
private:
};
......
......@@ -14,7 +14,9 @@ namespace duodim
static Scene* getInstance();
const float gravityConst;
void addBody(Body* b);
int sceneHeight = 0;
int sceneWidth = 0;
void step();
void render();
private:
......
......@@ -19,10 +19,11 @@ namespace duodim
{
public:
Body* body = nullptr;
virtual AxisAlignedBoundingBox getBounds() = 0;
virtual AxisAlignedBoundingBox* getBounds() = 0;
virtual MassAndInertia getMassAndInertia() = 0;
virtual ShapeType getType() = 0;
virtual void draw() = 0;
virtual ~Shape();
string getName();
void setName(string n);
......
......@@ -11,10 +11,10 @@ namespace duodim
class Texture
{
public:
static Texture red();
static Texture green();
static Texture blue();
static Texture random();
static Texture* red();
static Texture* green();
static Texture* blue();
static Texture* random();
Texture(float r, float g, float b);
ColorCode getColor();
private:
......
......@@ -2,14 +2,14 @@
#include "Vector2D.hpp"
using namespace duodim;
AxisAlignedBoundingBox AxisAlignedBoundingBox::fromCenterAndExtents(Vector2D center, const Vector2D extents)
AxisAlignedBoundingBox* AxisAlignedBoundingBox::fromCenterAndExtents(Vector2D center, const Vector2D extents)
{
return AxisAlignedBoundingBox((center - extents), (center + extents));
return new AxisAlignedBoundingBox((center - extents), (center + extents));
}
AxisAlignedBoundingBox AxisAlignedBoundingBox::asUnion(AxisAlignedBoundingBox a, AxisAlignedBoundingBox b)
AxisAlignedBoundingBox* AxisAlignedBoundingBox::asUnion(AxisAlignedBoundingBox a, AxisAlignedBoundingBox b)
{
return AxisAlignedBoundingBox(Vector2D::min(a.min, b.min), Vector2D::max(a.max, b.max));
return new AxisAlignedBoundingBox(Vector2D::min(a.min, b.min), Vector2D::max(a.max, b.max));
}
AxisAlignedBoundingBox::AxisAlignedBoundingBox() : min(Vector2D()), max(Vector2D()) {}
......@@ -25,7 +25,7 @@ Vector2D AxisAlignedBoundingBox::getExtents()
return (max - min) * .5f;
}
AxisAlignedBoundingBox AxisAlignedBoundingBox::expandBy(const float factor)
AxisAlignedBoundingBox* AxisAlignedBoundingBox::expandBy(const float factor)
{
return AxisAlignedBoundingBox::fromCenterAndExtents(getCenter(), (getExtents() * factor));
}
......@@ -35,20 +35,20 @@ float AxisAlignedBoundingBox::getPerimeter()
return 2.f * (max.x - min.x + max.y - min.y);
}
bool AxisAlignedBoundingBox::intersects(AxisAlignedBoundingBox o)
bool AxisAlignedBoundingBox::intersects(AxisAlignedBoundingBox* o)
{
if (max.x < o.min.x || min.x > o.max.x)
if (max.x < o->min.x || min.x > o->max.x)
{
return false;
}
else if (max.y < o.min.y || min.y > o.max.y)
else if (max.y < o->min.y || min.y > o->max.y)
{
return false;
}
return true;
}
bool AxisAlignedBoundingBox::contains(AxisAlignedBoundingBox o)
bool AxisAlignedBoundingBox::contains(AxisAlignedBoundingBox* o)
{
return Vector2D::min(min, o.min) == min && Vector2D::max(max, o.max) == max;
return Vector2D::min(min, o->min) == min && Vector2D::max(max, o->max) == max;
}
\ No newline at end of file
......@@ -9,16 +9,11 @@
using namespace duodim;
Body::Body(Vector2D position, Material* material, Shape* shape, Texture* texture)
: transform(new Transform(position, 0.f)), material(material), shape(shape), texture(texture)
{
initialize();
}
Body::Body(float posX, float posY, Material* material, Shape* shape, Texture* texture)
: transform(new Transform(Vector2D(posX, posY))), material(material), shape(shape), texture(texture)
{
initialize();
shape->body = this;
unsetStatic();
}
Body::~Body()
......@@ -112,10 +107,4 @@ void Body::unsetStatic()
inertia = mai.inertia;
inv_mass = mass != 0.f ? 1.f / mass : 0.f;
inv_inertia = inertia != 0.f ? 1.f / inertia : 0.f;
}
void Body::initialize()
{
shape->body = this;
unsetStatic();
}
\ No newline at end of file
......@@ -11,23 +11,40 @@ vector<CollisionPair> BroadPhase::getNarrowPhaseCandidates(vector<Body*> bodies)
vector<CollisionPair> pairs;
for (auto i = 0; i < bodies.size(); i++)
{
for (auto j = 0; j != bodies.size(); j++)
for (auto j = i + 1; j != bodies.size(); j++)
{
if (j == i)
{
continue; // Prevent identical bodies
}
Body* a = bodies[i];
Body* b = bodies[j];
if (a->isStatic() && b->isStatic())
{
continue;
}
else if (a->shape->getBounds().intersects(b->shape->getBounds()))
else
{
pairs.push_back({a, b});
AxisAlignedBoundingBox* aabbA = a->shape->getBounds();
AxisAlignedBoundingBox* aabbB = b->shape->getBounds();
if (aabbA->intersects(aabbB))
{
pairs.push_back({ a, b });
}
delete aabbA;
delete aabbB;
}
}
}
return pairs;
}
bool BroadPhase::isBodyLeftScene(Body* a, float x, float y)
{
if (a->isStatic())
{
return false;
}
AxisAlignedBoundingBox* aabb = a->shape->getBounds();
AxisAlignedBoundingBox* scene = new AxisAlignedBoundingBox(Vector2D(), Vector2D(x, y));
bool result = !scene->contains(aabb);
delete aabb;
delete scene;
return result;
}
\ No newline at end of file
......@@ -21,7 +21,7 @@ Circle::Circle(float radius) : radius(radius)
Circle::~Circle() {}
AxisAlignedBoundingBox Circle::getBounds()
AxisAlignedBoundingBox* Circle::getBounds()
{
return AxisAlignedBoundingBox::fromCenterAndExtents(body->transform->position, (Vector2D::one() * radius));
}
......
......@@ -17,8 +17,8 @@ bool Collision::solve()
Material* bm = b->material;
averageRestitution = min(am->restitution, bm->restitution);
mixedStaticFriction = (float) sqrt(am->staticFriction * bm->staticFriction);
mixedDynamicFriction = (float) sqrt(am->dynamicFriction * bm->dynamicFriction);
mixedStaticFriction = (float) sqrt((double) am->staticFriction * bm->staticFriction);
mixedDynamicFriction = (float) sqrt((double) am->dynamicFriction * bm->dynamicFriction);
for (auto cPoint : contactPoints)
{
Vector2D ra = cPoint - a->transform->position;
......@@ -106,8 +106,8 @@ void Collision::correctPositions()
const float kSlop = .05f; // Penetration allowance
const float percent = .4f; // Penetration correction percentage
Vector2D correction = (normal * percent * (max((penetration - kSlop), 0.f) / (a->inv_mass + b->inv_mass))) * a->inv_mass;
a->transform->position -= correction;
b->transform->position += correction;
a->transform->position = a->transform->position - correction;
b->transform->position = b->transform->position + correction;
}
void Collision::performNarrowPhase()
......
......@@ -22,16 +22,16 @@ ConvexPolygon::ConvexPolygon(vector<Vector2D> vertices) : vertices(vertices)
auto i = 0u;
for (auto v : vertices)
{
auto j = (i + 1) % vertices.size();
auto j = ((__int64) i + 1u) % vertices.size();
auto it = vertices.begin();
advance(it, j);
centroid += ((v + *it) * v.crossMult(*it) / 6.f * area);
centroid = centroid + ((v + *it) * v.crossMult(*it) / 6.f * area);
i++;
}
for (auto v : vertices)
{
v -= centroid;
v = v - centroid;
}
calculateNormals();
......@@ -40,7 +40,7 @@ ConvexPolygon::ConvexPolygon(vector<Vector2D> vertices) : vertices(vertices)
ConvexPolygon::~ConvexPolygon() {}
AxisAlignedBoundingBox ConvexPolygon::getBounds()
AxisAlignedBoundingBox* ConvexPolygon::getBounds()
{
Vector2D min = Vector2D::one() * INFINITY;
Vector2D max = Vector2D::one() * (-1.f) * INFINITY;
......@@ -50,7 +50,7 @@ AxisAlignedBoundingBox ConvexPolygon::getBounds()
min = Vector2D::min(min, vertex);
max = Vector2D::max(max, vertex);
}
return AxisAlignedBoundingBox(min, max);
return new AxisAlignedBoundingBox(min, max);
}
MassAndInertia ConvexPolygon::getMassAndInertia()
......@@ -60,7 +60,7 @@ MassAndInertia ConvexPolygon::getMassAndInertia()
auto i = 0u;
for (auto v : vertices)
{
auto j = (i + 1) % vertices.size();
auto j = ((__int64) i + 1) % vertices.size();
auto it = vertices.begin();
advance(it, j);
Vector2D atJ = *it;
......@@ -135,7 +135,7 @@ void ConvexPolygon::calculateNormals()
unsigned int i = 0u;
for (auto v : vertices)
{
auto j = (i + 1) % vertices.size();
auto j = ((__int64) i + 1) % vertices.size();
auto it = vertices.begin();
advance(it, j);
anormals.push_back((v - *it).normalized().crossMult(1.f));
......
#include "Material.hpp"
using namespace duodim;
Material Material::wood()
Material* Material::wood()
{
return Material(.3f, .2f, .2f, .3f);
return new Material(.3f, .2f, .2f, .3f);
}
Material Material::bouncyBall()
Material* Material::bouncyBall()
{
return Material(1.f, .8f, .8f, .3f);
return new Material(1.f, .8f, .8f, .3f);
}
Material Material::superBall()
Material* Material::superBall()
{
return Material(1.f ,.95f, .95f, .3f);
return new Material(1.f ,.95f, .95f, .3f);
}
Material::Material() : dynamicFriction(.4f), staticFriction(.4f), restitution(.4f), density(.4f) {}
Material::Material(float dynamicfriction, float staticFriction, float restitution, float density)
: dynamicFriction(dynamicFriction), staticFriction(staticFriction), restitution(restitution), density(density) {}
\ No newline at end of file
: dynamicFriction(dynamicFriction), staticFriction(staticFriction), restitution(restitution), density(density) {}
Material::~Material() {}
\ No newline at end of file
......@@ -31,7 +31,7 @@ void NarrowPhase::twoCircles(Collision* c, Body* a, Body* b)
else
{
c->penetration = rSum - dist;
c->normal /= dist;
c->normal = c->normal / dist;
c->addContactPosition(c->normal * ca->radius + a->transform->position);
}
}
......@@ -74,7 +74,7 @@ void NarrowPhase::circlePolygon(Collision* c, Body* a, Body* b)
// Grab face's vertices
Vector2D v1 = bVertices[faceNormal];
unsigned int i2 = faceNormal + 1 < bVertices.size() ? faceNormal + 1 : 0;
unsigned int i2 = ((__int64) faceNormal + 1 < bVertices.size() ? faceNormal + 1u: 0u);
Vector2D v2 = bVertices[i2];
// Check to see if center is within polygon
......@@ -132,13 +132,13 @@ void NarrowPhase::circlePolygon(Collision* c, Body* a, Body* b)
void NarrowPhase::polygonCircle(Collision* c, Body* a, Body* b)
{
circlePolygon(c, b, a);
c->normal *= -1.f;
c->normal = c->normal * -1.f;
}
float NarrowPhase::findAxisLeastPenetration(unsigned int* faceIdx, Body* a, ConvexPolygon* cpa, Body* b, ConvexPolygon* cpb)
{
float bestDist = -FLT_MAX;
unsigned int bestIdx;
unsigned int bestIdx = -1;
vector<Vector2D> cpaVertices = cpa->vertices;
vector<Vector2D> cpaNormals = cpa->normals;
......@@ -205,7 +205,7 @@ int NarrowPhase::clip(Vector2D n, float c, Vector2D* face)
{
unsigned int sp = 0;
Vector2D out[2] = { face[0], face[1] };
Vector2D out[3] = { face[0], face[1], Vector2D() };
// Retrieve distances from each endpoint to the line
// d = ax + by - c
......@@ -227,8 +227,8 @@ int NarrowPhase::clip(Vector2D n, float c, Vector2D* face)
{
// Push interesection point
float alpha = d1 / (d1 - d2);
out[sp] = face[0] + ((face[1] - face[0]) * alpha);
++sp;
Vector2D newFace1 = ((face[1] - face[0]) * alpha) + face[0];
out[sp++] = newFace1;
}
// Assign our new converted values
......@@ -290,11 +290,11 @@ void NarrowPhase::twoPolygons(Collision* c, Body* a, Body* b)
Vector2D v1 = flip ? cpb->vertices[faceB] : cpa->vertices[faceA];
if (flip)
{
faceB = faceB + 1 == cpb->vertices.size() ? 0 : faceB + 1;
faceB = (__int64) faceB + 1 == cpb->vertices.size() ? 0 : faceB + 1;
}
else
{
faceB = faceA + 1 == cpa->vertices.size() ? 0 : faceA + 1;
faceB = (__int64) faceA + 1 == cpa->vertices.size() ? 0 : faceA + 1;
}
Vector2D v2 = flip ? cpb->vertices[faceB] : cpa->vertices[faceA];
......
......@@ -19,14 +19,22 @@ Scene* Scene::getInstance()
return _sceneInstance;
}
void Scene::addBody(Body* b)
{
bodies.push_back(b);
}
void Scene::step()
{
contacts.clear();
Body* tested;
for (unsigned int i = 0; i < bodies.size(); ++i)
{
tested = bodies[i];
if (BroadPhase::isBodyLeftScene(tested, sceneWidth / 10, sceneHeight / 10))
{
// Body has left the scene, scrap it
bodies.erase(bodies.begin() + i);
delete tested;
}
}
tested = NULL;
if (!Engine::getInstance()->skipCollisions)
{
// Broad phase:
......@@ -108,8 +116,8 @@ void Scene::render()
for (auto pt : c.contactPoints)
{
glVertex2f(pt.x, pt.y);
n *= .75f;
pt += n;
n = n * .75f;
pt = pt + n;
glVertex2f(pt.x, pt.y);
}
}
......
......@@ -4,6 +4,11 @@
using namespace duodim;
using namespace std;
Shape::~Shape()
{
body = NULL;
}
string Shape::getName()
{
return name;
......
......@@ -2,24 +2,24 @@
#include "MathUtil.hpp"
using namespace duodim;
Texture Texture::random()
Texture* Texture::random()
{
return Texture(rand(0.f, 1.f), rand(0.f, 1.f), rand(0.f, 1.f));
return new Texture(rand(0.f, 1.f), rand(0.f, 1.f), rand(0.f, 1.f));
}
Texture Texture::red()
Texture* Texture::red()
{
return Texture(1.f, 0.f, 0.f);
return new Texture(1.f, 0.f, 0.f);
}
Texture Texture::green()
Texture* Texture::green()
{
return Texture(0.f, 1.f, 0.f);
return new Texture(0.f, 1.f, 0.f);
}
Texture Texture::blue()
Texture* Texture::blue()
{
return Texture(0.f, 0.f, 1.f);
return new Texture(0.f, 0.f, 1.f);
}
Texture::Texture(float r, float g, float b) : r(r), g(g), b(b) {}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment