Commit 1d90e5ef authored by Leon's avatar Leon

Resolve polygon shape bug

parent 74e2a6c5
......@@ -19,7 +19,7 @@ namespace duodim
vector<Vector2D> normals;
ConvexPolygon();
ConvexPolygon(const float x, const float y);
ConvexPolygon(vector<Vector2D> vertices);
ConvexPolygon(vector<Vector2D> vertices, const int maxPolyCount);
~ConvexPolygon();
AxisAlignedBoundingBox* getBounds();
......
......@@ -19,14 +19,14 @@ namespace duodim
{
public:
Body* body = nullptr;
string getName();
void setName(string n);
virtual ~Shape();
virtual AxisAlignedBoundingBox* getBounds() = 0;
virtual MassAndInertia getMassAndInertia() = 0;
virtual ShapeType getType() = 0;
virtual void draw() = 0;
virtual ~Shape();
string getName();
void setName(string n);
protected:
string name;
virtual void updateName() = 0;
......
#include <algorithm>
#include <cassert>
#include <string>
#include <vector>
#include "glut.h"
......@@ -20,7 +22,7 @@ ConvexPolygon* ConvexPolygon::random(const int maxPolyCount)
{
vertices.push_back(Vector2D(rand(-random, random), rand(-random, random)));
}
return new ConvexPolygon(vertices);
return new ConvexPolygon(vertices, maxPolyCount);
}
ConvexPolygon* ConvexPolygon::box(const float hw, const float hh)
......@@ -39,25 +41,91 @@ ConvexPolygon::ConvexPolygon(const float x, const float y) : vertices({}), norma
updateName();
}
ConvexPolygon::ConvexPolygon(vector<Vector2D> vertices) : vertices(vertices)
ConvexPolygon::ConvexPolygon(vector<Vector2D> verts, const int maxPolyCount)
{
Vector2D centroid;
float area = 0.f;
auto i = 0u;
for (auto v : vertices)
unsigned int size = verts.size();
// No hulls with less than 3 vertices (ensure actual polygon)
assert(size > 2 && size <= maxPolyCount);
size = min((int)size, maxPolyCount);
// Find the right most point on the hull
int rightMost = 0;
float highestXCoord = verts[0].x;
for (unsigned int i = 1; i < size; ++i)
{
auto j = ((__int64) i + 1u) % vertices.size();
auto it = vertices.begin();
advance(it, j);
centroid = centroid + ((v + *it) * v.crossMult(*it) / 6.f * area);
i++;
float x = verts[i].x;
if (x > highestXCoord)
{
highestXCoord = x;
rightMost = i;
}
else if (x == highestXCoord) // If matching x then take farthest negative y
{
if (verts[i].y < verts[rightMost].y)
{
rightMost = i;
}
}
}
for (auto v : vertices)
int* hull = new int[maxPolyCount];
int outCount = 0;
int indexHull = rightMost;
for (;;)
{
v = v - centroid;
hull[outCount] = indexHull;
// Search for next index that wraps around the hull
// by computing cross products to find the most counter-clockwise
// vertex in the set, given the previos hull index
int nextHullIndex = 0;
for (int i = 1; i < (int)size; ++i)
{
// Skip if same coordinate as we need three unique
// points in the set to perform a cross product
if (nextHullIndex == indexHull)
{
nextHullIndex = i;
continue;
}
// Cross every set of three unique vertices
// Record each counter clockwise third vertex and add
// to the output hull
// See : http://www.oocities.org/pcgpe/math2d.html
Vector2D e1 = verts[nextHullIndex] - verts[hull[outCount]];
Vector2D e2 = verts[i] - verts[hull[outCount]];
float c = e1.crossMult(e2);
if (c < 0.0f)
{
nextHullIndex = i;
}
// Cross product is zero then e vectors are on same line
// therefor want to record vertex farthest along that line
if (c == 0.0f && e2.squaredMagnitude() > e1.squaredMagnitude())
{
nextHullIndex = i;
}
}
++outCount;
indexHull = nextHullIndex;
// Conclude algorithm upon wrap-around
if (nextHullIndex == rightMost)
{
size = outCount;
break;
}
}
// Copy vertices into shape's vertices
for (unsigned int i = 0; i < size; ++i)
{
vertices.push_back(verts[hull[i]]);
}
calculateNormals();
updateName();
}
......@@ -154,19 +222,18 @@ void ConvexPolygon::draw()
void ConvexPolygon::calculateNormals()
{
auto anormals = vector<Vector2D>();
unsigned int i = 0u;
for (auto v : vertices)
normals.clear();
// Compute face normals
for (unsigned i1 = 0; i1 < vertices.size(); ++i1)
{
auto j = ((__int64) i + 1) % vertices.size();
auto it = vertices.begin();
advance(it, j);
anormals.push_back((v - *it).normalized().crossMult(1.f));
i++;
}
unsigned int i2 = i1 + 1 < vertices.size() ? i1 + 1 : 0;
Vector2D face = vertices[i2] - vertices[i1];
normals = anormals;
// Ensure no zero-length edges, because that's bad
assert(face.squaredMagnitude() > EPSILON* EPSILON);
normals.push_back(Vector2D(face.y, -face.x).normalized());
}
}
void ConvexPolygon::updateName()
......
......@@ -12,8 +12,8 @@ bool NarrowPhase::twoCircles(Collision* c, Body* a, Body* b)
{
bool result = false;
Circle* sa = dynamic_cast<Circle*>(a->shape);
Circle* sb = dynamic_cast<Circle*>(b->shape);
Circle* sa = reinterpret_cast<Circle*>(a->shape);
Circle* sb = reinterpret_cast<Circle*>(b->shape);
Vector2D betweenCenters = b->transform->position - a->transform->position;
float sqBetweenCentersDistance = betweenCenters.squaredMagnitude();
......@@ -40,8 +40,8 @@ bool NarrowPhase::twoCircles(Collision* c, Body* a, Body* b)
bool NarrowPhase::circlePolygon(Collision* c, Body* a, Body* b)
{
Circle* sa = dynamic_cast<Circle*>(a->shape);
ConvexPolygon* sb = dynamic_cast<ConvexPolygon*>(b->shape);
Circle* sa = reinterpret_cast<Circle*>(a->shape);
ConvexPolygon* sb = reinterpret_cast<ConvexPolygon*>(b->shape);
Transform* at = a->transform;
Transform* bt = b->transform;
......@@ -254,8 +254,8 @@ unsigned int NarrowPhase::clip(Vector2D n, float c, Vector2D* face)
bool NarrowPhase::twoPolygons(Collision* c, Body* a, Body* b)
{
ConvexPolygon* sa = dynamic_cast<ConvexPolygon*>(a->shape);
ConvexPolygon* sb = dynamic_cast<ConvexPolygon*>(b->shape);
ConvexPolygon* sa = reinterpret_cast<ConvexPolygon*>(a->shape);
ConvexPolygon* sb = reinterpret_cast<ConvexPolygon*>(b->shape);
c->contactCount = 0u;
// Check for a separating axis with A's face planes
......
#include <string>
#include "Shape.hpp"
using namespace duodim;
using namespace std;
Shape::~Shape()
duodim::Shape::~Shape()
{
body = NULL;
}
string Shape::getName()
std::string duodim::Shape::getName()
{
return name;
}
void Shape::setName(string n)
void duodim::Shape::setName(std::string n)
{
name = n;
}
\ No newline at end of file
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