Commit 6650d62a authored by Leon's avatar Leon

Add freeglut lib source

parent 6d473df6
cmake_minimum_required(VERSION 3.6.2)
project(DuodimEngine VERSION 1.0
DESCRIPTION "2D physics engine implementation for the 2019/2020 course \"Computer science basics for visual computing\", made by Leon Willens"
LANGUAGES CXX)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -I")
set(CXX_STANDARD 17)
project(DuodimDemo_Engine VERSION 1.0 DESCRIPTION "2D physics engine" LANGUAGES CXX)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
add_subdirectory(freeglut)
add_subdirectory(engine)
add_subdirectory(demo)
\ No newline at end of file
cmake_minimum_required(VERSION 3.6.2)
project(DuodimDemo_DemoExec VERSION 1.0
DESCRIPTION "Executable demonstration of the 2D physics engine."
LANGUAGES CXX)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -I")
set(CXX_STANDARD 17)
add_executable(demo "./src/main.cpp")
target_link_libraries(demo duodim_engine glut32.dll)
\ No newline at end of file
project(DuodimDemo_Exec VERSION 1.0 DESCRIPTION "2D physics engine" LANGUAGES CXX)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
file(GLOB SRC "src/*.cpp")
add_definitions(-DBUILD_VTI -DFREEGLUT_STATIC)
add_executable(exec ${SRC})
target_include_directories(exec PUBLIC "../engine/include" "../freeglut/include/GL")
target_link_libraries(exec PUBLIC engine freeglut_static)
\ No newline at end of file
#define FREEGLUT_STATIC
#define _LIB
#define FREEGLUT_LIB_PRAGMAS 0
#include <algorithm>
#include <iostream>
#include <vector>
#include "freeglut.h"
#include "Body.hpp"
#include "Circle.hpp"
#include "ConvexPolygon.hpp"
#include "Engine.hpp"
#include "glut.h"
#include "MathUtil.hpp"
#include "Scene.hpp"
#include "Vector2D.hpp"
#define ESC_KEY 27
#define MAX_POLY_COUNT 32
constexpr auto ESC_KEY = 27;
constexpr auto MAX_POLY_COUNT = 32;
using namespace duodim;
using namespace std;
using namespace chrono;
void Mouse( int button, int state, int x, int y )
void RenderString(int x, int y, const char* s)
{
x /= 10.f;
y /= 10.f;
glColor3f(.5f, .5f, .9f);
glRasterPos2i(x, y);
unsigned int l = (unsigned int)strlen(s);
for (unsigned i = 0; i < l; ++i)
{
glutBitmapCharacter(GLUT_BITMAP_9_BY_15, *(s + i));
}
}
void Mouse(int button, int state, int x, int y)
{
x /= 10.0f;
y /= 10.0f;
if (state == GLUT_DOWN)
{
switch(button)
switch (button)
{
case GLUT_LEFT_BUTTON:
{
RenderString(1, 6, "Spawning Polygon");
unsigned int count = (unsigned int)rand(3.f, (float)MAX_POLY_COUNT);
vector<Vector2D> vertices;
float e = rand(5.f, 10.f);
for (unsigned int i = 0; i < count; ++i)
{
unsigned int count = (unsigned int) rand(3.f, (float) MAX_POLY_COUNT);
list<Vector2D<float>> vertices;
float e = rand(5.f, 10.f);
for (unsigned int i = 0; i < count; ++i)
{
vertices.push_back(Vector2D<float>(rand(-e, e), rand(-e, e)));
}
Scene::getInstance()->addBody(Body((float) x, (float) y, &Material::wood(), &ConvexPolygon(vertices), &Texture::random()));
}
break;
case GLUT_RIGHT_BUTTON:
{
Scene::getInstance()->addBody(Body((float) x, (float) y, &Material::bouncyBall(), &Circle(rand(1.f, 3.f)), &Texture::random()));
vertices.push_back(Vector2D(rand(-e, e), rand(-e, e)));
}
break;
ConvexPolygon* cp = new ConvexPolygon(vertices);
Texture tex = Texture::red();
Body* b = new Body((float) x, (float) y, &Material::wood(), cp, &tex);
Scene::getInstance()->bodies.push_back(b);
}
break;
case GLUT_RIGHT_BUTTON:
{
Circle* cs = new Circle(rand(1.f, 3.f));
Texture tex = Texture::green();
Body* c = new Body((float) x, (float) y, &Material::bouncyBall(), cs, &tex);
Scene::getInstance()->bodies.push_back(c);
}
break;
}
}
}
}
void Keyboard(unsigned char key, int x, int y)
{
switch(key)
switch (key)
{
case ESC_KEY:
exit(0);
......@@ -61,42 +85,26 @@ void Keyboard(unsigned char key, int x, int y)
}
}
void PhysicsLoop( void )
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" );
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");
Engine::getInstance()->iterate();
glutSwapBuffers();
}
void RenderString(int x, int y, const char *s)
int initGui(int argc, char** argv)
{
glColor3f(.5f, .5f, .9f);
glRasterPos2i(x, y);
unsigned int l = (unsigned int) strlen(s);
for (unsigned i = 0; i < l; ++i)
{
glutBitmapCharacter(GLUT_BITMAP_9_BY_15, *(s + i));
}
}
void setupGlut(int* argc, char** argv)
{
glutInit(argc, argv);
glutInitDisplayMode(GLUT_RGBA|GLUT_DOUBLE);
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
glutInitWindowSize(800, 600);
glutCreateWindow("Duodim demo");
glutCreateWindow("Duodim Engine demo");
glutDisplayFunc(PhysicsLoop);
glutKeyboardFunc(Keyboard);
glutMouseFunc(Mouse);
glutIdleFunc(PhysicsLoop);
}
void setupGlutView()
{
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
......@@ -104,6 +112,7 @@ void setupGlutView()
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
return 0;
}
/**
......@@ -111,12 +120,26 @@ void setupGlutView()
*/
int main(int argc, char** argv)
{
setupGlut(&argc, argv);
setupGlutView();
if (initGui(argc, argv) == -1)
{
return -1;
}
ConvexPolygon* poly = new ConvexPolygon();
poly->setBox(30.0f, 1.0f);
Texture tex = Texture::blue();
Body* b = new Body(40.f, 55.f, &Material::wood(), poly, &tex);
b->setStatic();
Scene::getInstance()->bodies.push_back(b);
Engine::getInstance(); // Fire up engine
/* Circle* cs = new Circle(rand(1.f, 3.f));
Texture ctex = Texture::green();
Body* c = new Body(75.f, 20.f, &Material::bouncyBall(), cs, &ctex);
Scene::getInstance()->bodies.push_back(c);*/
srand(1);
glutMainLoop();
return 0;
}
\ No newline at end of file
cmake_minimum_required(VERSION 3.6.2)
project(DuodimDemo_Engine VERSION 1.0
DESCRIPTION "2D physics engine core"
LANGUAGES CXX)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -I")
set(CXX_STANDARD 17)
project(DuodimDemo_Engine VERSION 1.0 DESCRIPTION "2D physics engine" LANGUAGES CXX)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
file(GLOB SRC "src/*.cpp")
file(GLOB INCLUDE "include/*.hpp")
add_library(engine STATIC ${SRC})
target_link_directories(engine PUBLIC ${INCLUDE})
target_link_libraries(engine PUBLIC "../glut/build/glut32.dll")
add_library(engine ${SRC})
target_include_directories(engine PUBLIC include)
target_include_directories(engine PUBLIC "../freeglut/include/GL")
target_link_libraries(engine PUBLIC freeglut_static)
target_compile_features(engine PUBLIC cxx_std_17)
\ No newline at end of file
......@@ -6,21 +6,18 @@ namespace duodim
class AxisAlignedBoundingBox
{
public:
static AxisAlignedBoundingBox fromCenterAndExtents(Vector2D<float> center, const Vector2D<float> extents);
Vector2D min;
Vector2D max;
static AxisAlignedBoundingBox fromCenterAndExtents(Vector2D center, const Vector2D extents);
static AxisAlignedBoundingBox asUnion(AxisAlignedBoundingBox a, AxisAlignedBoundingBox b);
AxisAlignedBoundingBox();
AxisAlignedBoundingBox(Vector2D<float> min, Vector2D<float> max);
Vector2D<float> getMin();
Vector2D<float> getMax();
Vector2D<float> getCenter();
Vector2D<float> getExtents();
AxisAlignedBoundingBox(Vector2D min, Vector2D max);
Vector2D getCenter();
Vector2D getExtents();
AxisAlignedBoundingBox expandBy(const float factor);
float getPerimeter();
bool intersects(AxisAlignedBoundingBox o);
bool contains(AxisAlignedBoundingBox o);
private:
Vector2D<float> min;
Vector2D<float> max;
};
}
#endif
\ No newline at end of file
......@@ -6,67 +6,45 @@
#include "Transform.hpp"
namespace duodim
{
struct BodyPair {
unsigned int aId;
unsigned int bId;
};
class Body
{
public:
Body(Vector2D<float> position, Material* material, Shape* shape, Texture* texture);
Body(float posX, float posY, Material* material, Shape* shape, Texture* texture);
~Body();
Material* getMaterial();
Shape* getShape();
Texture* getTexture();
Transform* getTransform();
Vector2D<float> getVelocity();
float getAngularVelocity();
float getMass();
float getInverseMass();
float getInverseInertia();
unsigned int getId();
bool isStatic();
bool operator ==(Body o);
void addForce(Vector2D<float> f);
void addForce(Vector2D<float> f, Vector2D<float> pos);
void addImpulse(Vector2D<float> i, Vector2D<float> pos);
void addTorque(float t);
void setId(const unsigned int i);
void integrateForce();
void integrateVelocity();
void nullifyVelocity();
void setStatic();
void unsetStatic();
private:
AxisAlignedBoundingBox* bounds;
Texture* texture;
Material* material;
Transform* transform;
Shape* shape;
Vector2D<float> velocity = Vector2D<float>();
Vector2D<float> force = Vector2D<float>();
Vector2D velocity = Vector2D();
Vector2D force = Vector2D();
float angularVelocity = 0.f;
float torque = 0.f;
float mass;
float inertia;
float inv_mass;
float inv_inertia;
unsigned int id = 0u;
Body(Vector2D position, Material* material, Shape* shape, Texture* texture);
Body(float posX, float posY, Material* material, Shape* shape, Texture* texture);
~Body();
bool isStatic();
void draw();
void addForce(Vector2D f);
void addForce(Vector2D f, Vector2D pos);
void addImpulse(Vector2D i, Vector2D pos);
void addTorque(float t);
void integrateForce();
void integrateVelocity();
void nullifyVelocity();
void setStatic();
void unsetStatic();
private:
void initialize();
};
}
......
#ifndef INCLUDE_BROAD_PHASE_H
#define INCLUDE_BROAD_PHASE_H
#include <unordered_map>
#include <vector>
#include "AxisAlignedBoundingBox.hpp"
#include "Body.hpp"
using namespace std;
namespace duodim
......@@ -12,7 +10,7 @@ namespace duodim
class BroadPhase
{
public:
static vector<CollisionPair> getNarrowPhaseCandidates(vector<unsigned int> mapKeys, unordered_map<unsigned int, Body*> bodies);
static vector<CollisionPair> getNarrowPhaseCandidates(vector<Body*> bodies);
};
}
#endif
\ No newline at end of file
#ifndef INCLUDE_CIRCLE_HPP
#define INCLUDE_CIRCLE_HPP
#include "AxisAlignedBoundingBox.hpp"
#include "Shape.hpp"
namespace duodim
{
class Circle : public Shape
{
public:
float radius;
Circle();
Circle(float radius);
~Circle();
......@@ -14,14 +15,10 @@ namespace duodim
AxisAlignedBoundingBox getBounds();
MassAndInertia getMassAndInertia();
ShapeType getType();
float getRadius();
void setRadius(float r);
void draw();
protected:
void updateName();
private:
float radius;
};
}
#endif
\ No newline at end of file
......@@ -11,43 +11,23 @@ namespace duodim
class Collision
{
public:
vector<Vector2D> contactPoints;
Vector2D normal;
Vector2D tangent;
float penetration;
unsigned int contactCount = 0u;
Collision(Body* a, Body* b);
Collision(Vector2D<float> position, Vector2D<float> normal, float penetration);
vector<Vector2D<float>> getContactPoints();
/**
*
*/
Vector2D<float> getNormal();
/**
*
*/
Vector2D<float> getTangent();
/**
*
*/
float getPenetration();
unsigned int getContacts();
Collision(Vector2D position, Vector2D normal, float penetration);
bool solve();
void setContactCount(const unsigned int cnt);
void setPenetration(const float pen);
void setNormal(const Vector2D<float> n);
void addContactPosition(const Vector2D<float> p);
void addContactPosition(const Vector2D p);
void applyImpulse();
void clearContactPoints();
void correctPositions();
private:
Body* a;
Body* b;
vector<Vector2D<float>> contactPoints;
Vector2D<float> normal;
Vector2D<float> tangent;
float penetration;
float averageRestitution;
float mixedStaticFriction;
float mixedDynamicFriction;
unsigned int contactCount = 0;
bool initialized = false;
};
}
......
#ifndef INCLUDE_CONVEX_POLYGON_HPP
#define INCLUDE_CONVEX_POLYGON_HPP
#include <vector>
#include "AxisAlignedBoundingBox.hpp"
#include "Shape.hpp"
#include "Transform.hpp"
......@@ -11,27 +12,25 @@ namespace duodim
class ConvexPolygon : public Shape
{
public:
vector<Vector2D> vertices;
vector<Vector2D> normals;
ConvexPolygon();
ConvexPolygon(vector<Vector2D<float>> vertices);
ConvexPolygon(vector<Vector2D> vertices);
~ConvexPolygon();
vector<Vector2D<float>> getVertices();
vector<Vector2D<float>> getNormals();
AxisAlignedBoundingBox getBounds();
MassAndInertia getMassAndInertia();
ShapeType getType();
Vector2D<float> getSupport(Vector2D<float>& direction);
Vector2D getSupport(Vector2D& direction);
void setVertices(vector<Vector2D<float>> v);
void setBox(float hw, float hh);
void init();
void draw();
protected:
void calculateNormals();
void updateName();
private:
vector<Vector2D<float>> vertices;
vector<Vector2D<float>> normals;
};
}
#endif
\ No newline at end of file
#ifndef INCLUDE_ENGINE_H
#define INCLUDE_ENGINE_H
#include <optional>
#include <chrono>
using namespace std;
......
......@@ -5,20 +5,17 @@ namespace duodim
class Material
{
public:
float dynamicFriction;
float staticFriction;
float restitution;
float density;
static Material wood();
static Material bouncyBall();
static Material superBall();
Material();
Material(float dynamicfriction, float staticFriction, float restitution, float density);
float getDynamicFriction();
float getStaticFriction();
float getRestitution();
float getDensity();
private:
float dynamicFriction;
float staticFriction;
float restitution;
float density;
};
}
#endif
\ No newline at end of file
......@@ -16,4 +16,20 @@ inline bool BiasGreaterThan(float a, float b)
const float k_biasAbsolute = 0.01f;
return a >= (b * k_biasRelative) + (a * k_biasAbsolute);
}
inline float Clamp(float min, float max, float a)
{
if (a < min)
{
return min;
}
else if (a > max)
{
return max;
}
else
{
return a;
}
}
#endif
\ No newline at end of file
......@@ -3,24 +3,21 @@
#include "Vector2D.hpp"
namespace duodim
{
template <typename T>
class Matrix2
{
static_assert(std::is_floating_point<T>::value, "Matrix2 must be instantiated with a floating-point template argument.");
public:
static Matrix2<T> fromRadians(const T a);
Matrix2(const T x0, const T x1, const T y0, const T y1);
Matrix2(const Matrix2<T>& a);
static Matrix2 fromRadians(const float a);
Matrix2(const float x0, const float x1, const float y0, const float y1);
Matrix2(const Matrix2& a);
Matrix2();
~Matrix2();
Vector2D<T> operator *(const Vector2D<T> b);
Matrix2<T> operator *(const Matrix2<T> b);
Matrix2<T> transpose();
Vector2D operator *(const Vector2D b);
Matrix2 operator *(const Matrix2 b);
Matrix2 transpose();
T operator [](const int x);
float* operator [](const int x);
private:
T[2][2] fields;
float fields[2][2];
};
}
#endif
\ No newline at end of file
#ifndef INCLUDE_NARROW_PHASE_H
#define INCLUDE_NARROW_PHASE_H
#include "Body.hpp"
#include "ConvexPolygon.hpp"
#include "Collision.hpp"