Commit c0b56520 authored by Leon's avatar Leon

Add OpenGL Utility Toolkit

parent a357ce2f
......@@ -2,4 +2,6 @@
*.vcxproj.*
.vs/
.vscode/
x64/
\ No newline at end of file
x64/
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
#define INCLUDE_ENGINE_H
#include <optional>
#ifndef WIN32
#include <chrono>
#endif
using namespace std;
namespace duodim
{
class Engine
{
const float fps = 75.f;
const float dt = 1 / fps;
public:
const float fps = 75.f;
const float dt = 1 / fps;
static Engine& getInstance();
Engine();
Engine(Engine const&) = delete;
int run();
~Engine();
void start();
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;
private:
float accumulator = 0;
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
\ No newline at end of file
......@@ -49,7 +49,6 @@ namespace duodim
void addForce(Vector2D<float> f, Vector2D<float> pos);
void addImpulse(Vector2D<float> i, Vector2D<float> pos);
void addTorque(float t);
void setPosition(Vector2D<float> p);
void setShape(Shape* s);
void setDensity(const float d);
void setId(const unsigned int i);
......
......@@ -9,12 +9,14 @@ namespace duodim
static Material bouncyBall();
static Material superBall();
Material();
Material(float friction, float restitution, float density);
float getFriction();
Material(float dynamicfriction, float staticFriction, float restitution, float density);
float getDynamicFriction();
float getStaticFriction();
float getRestitution();
float getDensity();
private:
float friction;
float dynamicFriction;
float staticFriction;
float restitution;
float density;
};
......
......@@ -12,18 +12,16 @@ namespace duodim
Transform(Vector2D<float> position, float rotation);
~Transform();
Vector2D<float> getPosition();
Vector2D<float> position;
Vector2D<float> getWorldPosition(Vector2D<float> localPosition);
Vector2D<float> getWorldDirection(Vector2D<float> localDirection);
Vector2D<float> getLocalPosition(Vector2D<float> worldPosition);
Vector2D<float> getLocalDirection(Vector2D<float> worldDirection);
float getRotation();
void setPosition(const Vector2D<float> p);
void setRotation(const float r);
private:
Matrix2<float> rotMatrix;
Vector2D<float> position;
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
Vector2D<T> operator -(const Vector2D<T> b);
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> iCrossMult(const T a);
Vector2D<T> normalized();
......
......@@ -3,15 +3,29 @@
#include "Scene.hpp"
using namespace duodim;
using namespace std;
using namespace chrono;
Engine& Engine::getInstance()
{
static Engine 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;
Scene& world = Scene::getInstance();
......@@ -43,4 +57,40 @@ int Engine::run()
void Engine::stop()
{
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 "NarrowPhase.hpp"
#include "Vector2D.hpp"
using namespace duodim;
......@@ -25,4 +26,9 @@ Vector2D<float> Collision::getTangent()
float Collision::getPenetration()
{
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 @@
#include <math.h>
#include <vector>
#include "Body.hpp"
#include "Contact.hpp"
#include "Collision.hpp"
#include "ContactConstraint.hpp"
#include "Vector2D.hpp"
using namespace duodim;
......@@ -43,8 +43,8 @@ void ContactConstraint::initializeVelocity(Body a, Body b)
{
// Retrieve difference vectors between the contact position and the bodies centroid positions
Vector2D<float> diffContactApos = contact.getPosition() - a.getTransform().getPosition();
Vector2D<float> diffContactBpos = contact.getPosition() - b.getTransform().getPosition();
Vector2D<float> diffContactApos = contact.getPosition() - a.getTransform().position;
Vector2D<float> diffContactBpos = contact.getPosition() - b.getTransform().position;
// 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)
{
// Retrieve difference vectors between the contact position and the bodies centroid positions
Vector2D<float> diffContactApos = contact.getPosition() - a.getTransform().getPosition();
Vector2D<float> diffContactBpos = contact.getPosition() - b.getTransform().getPosition();
Vector2D<float> diffContactApos = contact.getPosition() - a.getTransform().position;
Vector2D<float> diffContactBpos = contact.getPosition() - b.getTransform().position;
// Calculate an impulse vector that will push the bodies away from each other
......@@ -90,8 +90,8 @@ void ContactConstraint::solveVelocity(Body a, Body b)
{
// Retrieve difference vectors between the contact position and the bodies centroid positions
Vector2D<float> diffContactApos = contact.getPosition() - a.getTransform().getPosition();
Vector2D<float> diffContactBpos = contact.getPosition() - b.getTransform().getPosition();
Vector2D<float> diffContactApos = contact.getPosition() - a.getTransform().position;
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
......@@ -127,8 +127,8 @@ void ContactConstraint::solvePosition(Body a, Body b)
{
// Retrieve difference vectors between the contact position and the bodies centroid positions
Vector2D<float> diffContactApos = contact.getPosition() - a.getTransform().getPosition();
Vector2D<float> diffContactBpos = contact.getPosition() - b.getTransform().getPosition();
Vector2D<float> diffContactApos = contact.getPosition() - a.getTransform().position;
Vector2D<float> diffContactBpos = contact.getPosition() - b.getTransform().position;
// 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)
float correction = max(0.f, BAUMGARTE * (contact.getPenetration() - PENETRATION_SLOP));
Vector2D<float> posImpulse = contact.getNormal() * normalMass * correction;
a.getTransform().setPosition(a.getTransform().getPosition() - posImpulse * a.getInverseMass());
b.getTransform().setPosition(b.getTransform().getPosition() + posImpulse * b.getInverseMass());
a.getTransform().position -= (posImpulse * a.getInverseMass());
b.getTransform().position += (posImpulse * b.getInverseMass());
a.getTransform().setRotation(a.getTransform().getRotation() - diffContactApos.crossMult(posImpulse) * a.getInverseInertia());
b.getTransform().setRotation(b.getTransform().getRotation() + diffContactBpos.crossMult(posImpulse) * b.getInverseInertia());
......
#include "NarrowPhase.hpp"
#include "Circle.hpp"
#include "ConvexPolygon.hpp"
#include "Rectangle.hpp"
#include "Shape.hpp"
using namespace duodim;
......@@ -21,7 +20,7 @@ void NarrowPhase::twoCircles(Collision* c, Body* a, Body* b)
Circle* ca = reinterpret_cast<Circle*>(a->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 rSum = ca->getRadius() + cb->getRadius();
if (sqDist >= pow(rSum, 2))
......
......@@ -5,7 +5,7 @@
#include "Shape.hpp"
#include "Transform.hpp"
#include "Vector2D.hpp"
#include "World.hpp"
#include "Scene.hpp"
using namespace duodim;
......@@ -148,7 +148,7 @@ bool Body::operator ==(Body o)
void Body::addForce(Vector2D<float> f)
{
force = force + f;
force += f;
}
void Body::addForce(Vector2D<float> f, Vector2D<float> pos)
......@@ -159,7 +159,7 @@ void Body::addForce(Vector2D<float> f, Vector2D<float> pos)
void Body::addImpulse(Vector2D<float> i, Vector2D<float> pos)
{
velocity = velocity + i * inv_mass;
velocity += (i * inv_mass);
angularVelocity = pos.crossMult(i) * inv_inertia;
}
......@@ -168,11 +168,6 @@ void Body::addTorque(float t)
torque += t;
}
void Body::setPosition(Vector2D<float> p)
{
transform.setPosition(p);
}
void Body::setShape(Shape* s)
{
shape = s;
......@@ -201,11 +196,8 @@ void Body::integrateForce(const float deltaTime)
return;
}
auto g = Vector2D<float>::gravity();
velocity = (g + force * inv_mass) * deltaTime;
angularVelocity = torque * inv_inertia * deltaTime;
force = Vector2D<float>();
torque = 0.f;
velocity += (force * inv_mass + g) * (deltaTime / 2.f);
angularVelocity += torque * inv_inertia * (deltaTime / 2.f);
}
void Body::integrateVelocity(const float deltaTime)
......@@ -214,7 +206,7 @@ void Body::integrateVelocity(const float deltaTime)
{
return;
}
transform.setPosition(transform.getPosition() + velocity * deltaTime);
transform.position += (velocity * deltaTime);
transform.setRotation(transform.getRotation() + angularVelocity * deltaTime);
}
......
......@@ -3,25 +3,31 @@ using namespace duodim;
Material Material::wood()
{
return Material(0.f, .2f, .3f);
return Material(.3f, .2f, .2f, .3f);
}
Material Material::bouncyBall()
{
return Material(0.f, .8f, .3f);
return Material(1.f, .8f, .8f, .3f);
}
Material Material::superBall()
{
return Material(0.f, .95f, .3f);
return Material(1.f ,.95f, .95f, .3f);
}
Material::Material() : friction(1.f), restitution(1.f), density(1.f) {}
Material::Material(float friction, float restitution, float density) : friction(friction), restitution(restitution), density(density) {}
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) {}
float Material::getFriction()
float Material::getDynamicFriction()
{
return friction;
return dynamicFriction;
}
float Material::getStaticFriction()
{
return staticFriction;
}
float Material::getRestitution()
......
......@@ -10,11 +10,6 @@ Transform::Transform(Vector2D<float> position)
Transform::Transform(Vector2D<float> position, float rotation)
: position(position), rotation(rotation), rotMatrix(Matrix2<float>::fromRadians(rotation)) {}
Vector2D<float> Transform::getPosition()
{
return position;
}
Vector2D<float> Transform::getWorldPosition(Vector2D<float> localPosition)
{
return rotMatrix * localPosition + position;
......@@ -32,7 +27,7 @@ Vector2D<float> Transform::getLocalPosition(Vector2D<float> worldPosition)
Vector2D<float> Transform::getLocalDirection(Vector2D<float> worldDirection)
{
return rotMatrix.transpose * worldDirection;
return rotMatrix.transpose() * worldDirection;
}
float Transform::getRotation()
......@@ -40,11 +35,6 @@ float Transform::getRotation()
return rotation;
}
void Transform::setPosition(const Vector2D<float> p)
{
position = p;
}
void Transform::setRotation(const float r)
{
rotation = r;
......
......@@ -23,13 +23,13 @@ ConvexPolygon::ConvexPolygon(list<Vector2D<float>> vertices) : vertices(vertices
auto j = (i + 1) % vertices.size();
auto it = vertices.begin();
advance(it, j);
centroid = centroid + ((v + *it) * v.crossMult(*it) / 6.f * area);
centroid += ((v + *it) * v.crossMult(*it) / 6.f * area);
i++;
}
for (auto v : vertices)
{
v = v - centroid;
v -= centroid;
}
auto anormals = list<Vector2D<float>>();
......
......@@ -67,6 +67,18 @@ Vector2D<T> Vector2D<T>::operator /(const T a)
return Vector2D<T>(T(x / a), T(y / a));
}
template <typename T>
Vector2D<T> Vector2D<T>::operator +=(const Vector2D<T> b)
{
return this + b;
}
template <typename T>
Vector2D<T> Vector2D<T>::operator -=(const Vector2D<T> b)
{
return this - b;
}
template <typename T>
Vector2D<T> Vector2D<T>::crossMult(const T a)
{
......
This diff is collapsed.
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