Commit c0b56520 authored by Leon's avatar Leon
Browse files

Add OpenGL Utility Toolkit

parent a357ce2f
...@@ -2,4 +2,6 @@ ...@@ -2,4 +2,6 @@
*.vcxproj.* *.vcxproj.*
.vs/ .vs/
.vscode/ .vscode/
x64/ x64/
\ No newline at end of file build/
!glut/build/
\ No newline at end of file
#include <algorithm>
#include "Body.hpp"
#include "ConvexPolygon.hpp"
#include "Engine.hpp"
#include "glut.h"
#include "MathUtils.hpp"
#include "Scene.hpp"
#include "Vector2D.hpp"
#define ESC_KEY 27
#define MAX_POLY_COUNT 32
using namespace duodim;
using namespace std;
using namespace chrono;
Engine engine;
Scene scene;
bool frameStepping = false;
bool canStep = false;
void Mouse( int button, int state, int x, int y )
{
x /= 10.f;
y /= 10.f;
if (state == GLUT_DOWN)
{
switch(button)
{
case GLUT_LEFT_BUTTON:
{
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)));
}
ConvexPolygon poly(vertices);
Body *b = scene.Add(&poly, x, y);
b->SetOrient( Random( -PI, PI ) );
b->restitution = 0.2f;
b->dynamicFriction = 0.2f;
b->staticFriction = 0.4f;
delete [] vertices;
}
break;
case GLUT_RIGHT_BUTTON:
{
Circle c(rand(1.f, 3.f));
Body *b = scene.Add(&c, x, y);
}
break;
}
}
}
void Keyboard(unsigned char key, int x, int y)
{
switch(key)
{
case ESC_KEY:
exit(0);
break;
case 's':
{
//Circle c( 25.0f );
//scene.Add( &c, 400 + (rand( ) % 250) * ((rand( ) % 2 == 1) ? 1 : -1), 50 );
//OBB obb;
//real e = Random( 10.0f, 35.0f );
//obb.extents.Set( e, e );
//Body *b = scene.Add( &obb, 400 + (rand( ) % 250) * ((rand( ) % 2 == 1) ? 1 : -1), 50 );
//b->SetOrient( PI / 4.0f );
//b->restitution = 0.2f;
//b->dynamicFriction = 0.2f;
//b->staticFriction = 0.4f;
}
break;
case 'd':
{
//Circle c( 25.0f );
//scene.Add( &c, 420, 50 );
}
break;
case 'f':
frameStepping = frameStepping ? false : true;
break;
case ' ':
canStep = true;
break;
}
}
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" );
static double accumulator = 0;
// Different time mechanisms for Linux and Windows
#ifdef WIN32
accumulator += engine.getElapsedTime();
#else
accumulator += engine.getElapsedTime() / static_cast<double>(duration_cast<nanoseconds>(seconds(1)).count());
#endif
engine.start();
accumulator = clamp(0., .1, accumulator);
while(accumulator >= engine.dt)
{
if(!frameStepping)
{
scene.Step();
}
else
{
if(canStep)
{
scene.Step();
canStep = false;
}
}
accumulator -= engine.dt;
}
engine.stop();
scene.Render();
glutSwapBuffers();
}
void RenderString(int x, int y, const char *s)
{
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));
}
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
glutInitWindowSize(800, 600);
glutCreateWindow("Duodim demo");
glutDisplayFunc(PhysicsLoop);
glutKeyboardFunc(Keyboard);
glutMouseFunc(Mouse);
glutIdleFunc(PhysicsLoop);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
gluOrtho2D(0, 80, 60, 0);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
Circle c(5.f);
Body *b = scene.Add(&c, 40, 40);
b->setStatic();
PolygonShape poly;
poly.SetBox(30.f, 1.f);
b = scene.Add(&poly, 40, 55);
b->setStatic();
srand(1);
glutMainLoop();
return 0;
}
\ No newline at end of file
#ifndef INCLUDE_ENGINE_H #ifndef INCLUDE_ENGINE_H
#define INCLUDE_ENGINE_H #define INCLUDE_ENGINE_H
#include <optional> #include <optional>
#ifndef WIN32
#include <chrono>
#endif
using namespace std; using namespace std;
namespace duodim namespace duodim
{ {
class Engine class Engine
{ {
const float fps = 75.f;
const float dt = 1 / fps;
public: public:
const float fps = 75.f;
const float dt = 1 / fps;
static Engine& getInstance(); static Engine& getInstance();
Engine(); Engine();
Engine(Engine const&) = delete; Engine(Engine const&) = delete;
int run(); ~Engine();
void start();
void stop(); void stop();
#ifdef WIN32
float getElapsedTime();
float getTimeDifference();
LONGLONG getCurrentTime();
#else
long long getElapsedTime();
long long getTimeDifference();
long long getCurrentTime();
#endif
void operator =(Engine const&) = delete; void operator =(Engine const&) = delete;
private: private:
float accumulator = 0; float accumulator = 0;
bool running = false; bool running = false;
#ifdef WIN32
LARGE_INTEGER mFreq;
LARGE_INTEGER mStart, mStop, mCurrent;
void query(LARGE_INTEGER& q);
#else
chrono::high_resolution_clock::time_point mStart;
chrono::high_resolution_clock::time_point mStop;
chrono::high_resolution_clock::time_point mCurrent;
#endif
}; };
} }
#endif #endif
\ No newline at end of file
...@@ -49,7 +49,6 @@ namespace duodim ...@@ -49,7 +49,6 @@ namespace duodim
void addForce(Vector2D<float> f, Vector2D<float> pos); void addForce(Vector2D<float> f, Vector2D<float> pos);
void addImpulse(Vector2D<float> i, Vector2D<float> pos); void addImpulse(Vector2D<float> i, Vector2D<float> pos);
void addTorque(float t); void addTorque(float t);
void setPosition(Vector2D<float> p);
void setShape(Shape* s); void setShape(Shape* s);
void setDensity(const float d); void setDensity(const float d);
void setId(const unsigned int i); void setId(const unsigned int i);
......
...@@ -9,12 +9,14 @@ namespace duodim ...@@ -9,12 +9,14 @@ namespace duodim
static Material bouncyBall(); static Material bouncyBall();
static Material superBall(); static Material superBall();
Material(); Material();
Material(float friction, float restitution, float density); Material(float dynamicfriction, float staticFriction, float restitution, float density);
float getFriction(); float getDynamicFriction();
float getStaticFriction();
float getRestitution(); float getRestitution();
float getDensity(); float getDensity();
private: private:
float friction; float dynamicFriction;
float staticFriction;
float restitution; float restitution;
float density; float density;
}; };
......
...@@ -12,18 +12,16 @@ namespace duodim ...@@ -12,18 +12,16 @@ namespace duodim
Transform(Vector2D<float> position, float rotation); Transform(Vector2D<float> position, float rotation);
~Transform(); ~Transform();
Vector2D<float> getPosition(); Vector2D<float> position;
Vector2D<float> getWorldPosition(Vector2D<float> localPosition); Vector2D<float> getWorldPosition(Vector2D<float> localPosition);
Vector2D<float> getWorldDirection(Vector2D<float> localDirection); Vector2D<float> getWorldDirection(Vector2D<float> localDirection);
Vector2D<float> getLocalPosition(Vector2D<float> worldPosition); Vector2D<float> getLocalPosition(Vector2D<float> worldPosition);
Vector2D<float> getLocalDirection(Vector2D<float> worldDirection); Vector2D<float> getLocalDirection(Vector2D<float> worldDirection);
float getRotation(); float getRotation();
void setPosition(const Vector2D<float> p);
void setRotation(const float r); void setRotation(const float r);
private: private:
Matrix2<float> rotMatrix; Matrix2<float> rotMatrix;
Vector2D<float> position;
float rotation; float rotation;
}; };
} }
......
#ifndef INCLUDE_MATH_UTIL_H
#define INCLUDE_MATH_UTIL_H
#include <cstdlib>
inline float rand(float a, float b)
{
float r = (float) rand();
r /= RAND_MAX;
return (b - a) * r + a;
}
#endif
\ No newline at end of file
...@@ -22,6 +22,9 @@ namespace duodim ...@@ -22,6 +22,9 @@ namespace duodim
Vector2D<T> operator -(const Vector2D<T> b); Vector2D<T> operator -(const Vector2D<T> b);
Vector2D<T> operator *(const T a); Vector2D<T> operator *(const T a);
Vector2D<T> operator /(const T a); Vector2D<T> operator /(const T a);
Vector2D<T> operator +=(const Vector2D<T> b);
Vector2D<T> operator -=(const Vector2D<T> b);
Vector2D<T> crossMult(const T a); Vector2D<T> crossMult(const T a);
Vector2D<T> iCrossMult(const T a); Vector2D<T> iCrossMult(const T a);
Vector2D<T> normalized(); Vector2D<T> normalized();
......
...@@ -3,15 +3,29 @@ ...@@ -3,15 +3,29 @@
#include "Scene.hpp" #include "Scene.hpp"
using namespace duodim; using namespace duodim;
using namespace std; using namespace std;
using namespace chrono;
Engine& Engine::getInstance() Engine& Engine::getInstance()
{ {
static Engine instance; static Engine instance;
return instance; return instance;
} }
Engine::Engine() {} Engine::Engine()
{
#ifdef WIN32
SetThreadAffinityMask(GetCurrentThread(), 1);
_Query_perf_frequency(&mFreq);
_Query_perf_counter(&mStart);
_Query_perf_counter(&mStop);
#else
mStart = high_resolution_clock::now();
mStop = high_resolution_clock::now();
#endif
}
Engine::~Engine() {}
int Engine::run() void Engine::start()
{ {
running = true; running = true;
Scene& world = Scene::getInstance(); Scene& world = Scene::getInstance();
...@@ -43,4 +57,40 @@ int Engine::run() ...@@ -43,4 +57,40 @@ int Engine::run()
void Engine::stop() void Engine::stop()
{ {
running = false; running = false;
} }
\ No newline at end of file
#ifdef WIN32
float Engine::getElapsedTime()
{
_Query_perf_counter(&mCurrent);
return (mCurrent.QuadPart - mStart.QuadPart) / (float) mFreq.QuadPart;
}
float Engine::getTimeDifference()
{
return (mStop.QuadPart - mStart.QuadPart) / (float) mFreq.QuadPart;
}
LONGLONG Engine::getCurrentTime()
{
_Query_perf_counter(&mCurrent);
return mCurrent.QuadPart;
}
#else
long long Engine::getElapsedTime()
{
mCurrent = high_resolution_clock::now();
return duration_cast<nanoseconds>(mCurrent - mStart).count();
}
long long Engine::getTimeDifference()
{
return duration_cast<nanoseconds>(mStop - mStart).count();
}
long long Engine::getCurrentTime()
{
mCurrent = high_resolution_clock::now();
return duration_cast<nanoseconds>(mCurrent.time_since_epoch()).count();
}
#endif
\ No newline at end of file
#include "Collision.hpp" #include "Collision.hpp"
#include "NarrowPhase.hpp"
#include "Vector2D.hpp" #include "Vector2D.hpp"
using namespace duodim; using namespace duodim;
...@@ -25,4 +26,9 @@ Vector2D<float> Collision::getTangent() ...@@ -25,4 +26,9 @@ Vector2D<float> Collision::getTangent()
float Collision::getPenetration() float Collision::getPenetration()
{ {
return penetration; return penetration;
}
void Collision::solve()
{
Dispatch[a->getShape()->getType()][b->getShape()->getType()](this, a, b);
} }
\ No newline at end of file
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
#include <math.h> #include <math.h>
#include <vector> #include <vector>
#include "Body.hpp" #include "Body.hpp"
#include "Contact.hpp" #include "Collision.hpp"
#include "ContactConstraint.hpp" #include "ContactConstraint.hpp"
#include "Vector2D.hpp" #include "Vector2D.hpp"
using namespace duodim; using namespace duodim;
...@@ -43,8 +43,8 @@ void ContactConstraint::initializeVelocity(Body a, Body b) ...@@ -43,8 +43,8 @@ void ContactConstraint::initializeVelocity(Body a, Body b)
{ {
// Retrieve difference vectors between the contact position and the bodies centroid positions // Retrieve difference vectors between the contact position and the bodies centroid positions
Vector2D<float> diffContactApos = contact.getPosition() - a.getTransform().getPosition(); Vector2D<float> diffContactApos = contact.getPosition() - a.getTransform().position;
Vector2D<float> diffContactBpos = contact.getPosition() - b.getTransform().getPosition(); Vector2D<float> diffContactBpos = contact.getPosition() - b.getTransform().position;
// Calculate the squared normal scalar from the difference vectors and the contact's normal // Calculate the squared normal scalar from the difference vectors and the contact's normal
...@@ -73,8 +73,8 @@ void ContactConstraint::warmStartVelocity(Body a, Body b) ...@@ -73,8 +73,8 @@ void ContactConstraint::warmStartVelocity(Body a, Body b)
{ {
// Retrieve difference vectors between the contact position and the bodies centroid positions // Retrieve difference vectors between the contact position and the bodies centroid positions
Vector2D<float> diffContactApos = contact.getPosition() - a.getTransform().getPosition(); Vector2D<float> diffContactApos = contact.getPosition() - a.getTransform().position;
Vector2D<float> diffContactBpos = contact.getPosition() - b.getTransform().getPosition(); Vector2D<float> diffContactBpos = contact.getPosition() - b.getTransform().position;
// Calculate an impulse vector that will push the bodies away from each other // Calculate an impulse vector that will push the bodies away from each other
...@@ -90,8 +90,8 @@ void ContactConstraint::solveVelocity(Body a, Body b) ...@@ -90,8 +90,8 @@ void ContactConstraint::solveVelocity(Body a, Body b)
{ {
// Retrieve difference vectors between the contact position and the bodies centroid positions // Retrieve difference vectors between the contact position and the bodies centroid positions
Vector2D<float> diffContactApos = contact.getPosition() - a.getTransform().getPosition(); Vector2D<float> diffContactApos = contact.getPosition() - a.getTransform().position;
Vector2D<float> diffContactBpos = contact.getPosition() - b.getTransform().getPosition(); Vector2D<float> diffContactBpos = contact.getPosition() - b.getTransform().position;
// Calculate a relative velocity vector: Sum of difference between velocities and difference between cross products of difference vectors and angular velocities // Calculate a relative velocity vector: Sum of difference between velocities and difference between cross products of difference vectors and angular velocities
...@@ -127,8 +127,8 @@ void ContactConstraint::solvePosition(Body a, Body b) ...@@ -127,8 +127,8 @@ void ContactConstraint::solvePosition(Body a, Body b)
{ {
// Retrieve difference vectors between the contact position and the bodies centroid positions // Retrieve difference vectors between the contact position and the bodies centroid positions
Vector2D<float> diffContactApos = contact.getPosition() - a.getTransform().getPosition(); Vector2D<float> diffContactApos = contact.getPosition() - a.getTransform().position;
Vector2D<float> diffContactBpos = contact.getPosition() - b.getTransform().getPosition(); Vector2D<float> diffContactBpos = contact.getPosition() - b.getTransform().position;
// Calculate the squared normal scalar from the difference vectors and the contact's tangent // Calculate the squared normal scalar from the difference vectors and the contact's tangent
...@@ -146,8 +146,8 @@ void ContactConstraint::solvePosition(Body a, Body b) ...@@ -146,8 +146,8 @@ void ContactConstraint::solvePosition(Body a, Body b)
float correction = max(0.f, BAUMGARTE * (contact.getPenetration() - PENETRATION_SLOP)); float correction = max(0.f, BAUMGARTE * (contact.getPenetration() - PENETRATION_SLOP));
Vector2D<float> posImpulse = contact.getNormal() * normalMass * correction; Vector2D<float> posImpulse = contact.getNormal() * normalMass * correction;
a.getTransform().setPosition(a.getTransform().getPosition() - posImpulse * a.getInverseMass()); a.getTransform().position -= (posImpulse * a.getInverseMass());
b.getTransform().setPosition(b.getTransform().getPosition() + posImpulse * b.getInverseMass()); b.getTransform().position += (posImpulse * b.getInverseMass());
a.getTransform().setRotation(a.getTransform().getRotation() - diffContactApos.crossMult(posImpulse) * a.getInverseInertia()); a.getTransform().setRotation(a.getTransform().getRotation() - diffContactApos.crossMult(posImpulse) * a.getInverseInertia());
b.getTransform().setRotation(b.getTransform().getRotation() + diffContactBpos.crossMult(posImpulse) * b.getInverseInertia()); b.getTransform().setRotation(b.getTransform().getRotation() + diffContactBpos.crossMult(posImpulse) * b.getInverseInertia());
......
#include "NarrowPhase.hpp" #include "NarrowPhase.hpp"
#include "Circle.hpp" #include "Circle.hpp"
#include "ConvexPolygon.hpp" #include "ConvexPolygon.hpp"
#include "Rectangle.hpp"
#include "Shape.hpp" #include "Shape.hpp"
using namespace duodim; using namespace duodim;
...@@ -21,7 +20,7 @@ void NarrowPhase::twoCircles(Collision* c, Body* a, Body* b) ...@@ -21,7 +20,7 @@ void NarrowPhase::twoCircles(Collision* c, Body* a, Body* b)
Circle* ca = reinterpret_cast<Circle*>(a->getShape()); Circle* ca = reinterpret_cast<Circle*>(a->getShape());
Circle* cb = reinterpret_cast<Circle*>(b->getShape()); Circle* cb = reinterpret_cast<Circle*>(b->getShape());
Vector2D<float> normal = a->getTransform().getPosition() - b->getTransform().getPosition(); Vector2D<float> normal = a->getTransform().position - b->getTransform().position;
float sqDist = normal.squaredMagnitude(); float sqDist = normal.squaredMagnitude();
float rSum = ca->getRadius() + cb->getRadius(); float rSum = ca->getRadius() + cb->getRadius();
if (sqDist >= pow(rSum, 2)) if (sqDist >= pow(rSum, 2))
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
#include "Shape.hpp" #include "Shape.hpp"
#include "Transform.hpp" #include "Transform.hpp"
#include "Vector2D.hpp" #include "Vector2D.hpp"
#include "World.hpp" #include "Scene.hpp"
using namespace duodim; using namespace duodim;
...@@ -148,7 +148,7 @@ bool Body::operator ==(Body o) ...@@ -148,7 +148,7 @@ bool Body::operator ==(Body o)
void Body::addForce(Vector2D<float> f) void Body::addForce(Vector2D<float> f)
{ {
force = force + f; force +=