I'm writing the code in C++ on a Linux machine.
Here's the source code:
Code: Select all
using namespace std;
#ifdef __APPLE__
#include "OpenGL/gl.h"
#include "OpenGL/glu.h"
#include <GLUT/glut.h>
#else
#include <GL/gl.h>
#include <GL/glext.h>
#include <GL/glu.h>
#include <GL/glut.h>
#endif
#include "chipmunk/chipmunk.h"
#include <cmath>
#include <iostream>
#include <vector>
static cpSpace* space;
static cpBody* staticBody;
static vector<cpShape*> shapes;
static vector<cpBody*> bodies;
void drawCircle(cpFloat x, cpFloat y, cpFloat r, cpFloat a)
{
const int segs = 15;
const cpFloat coef = 2.0*M_PI/(cpFloat)segs;
int n;
glBegin(GL_POLYGON); {
for(n = 0; n < segs; n++){
cpFloat rads = n*coef;
glVertex2f(r*cos(rads + a) + x, r*sin(rads + a) + y);
}
glVertex2f(x,y);
} glEnd();
}
void drawCircleShape(cpShape *shape)
{
cpBody *body = shape->body;
cpCircleShape *circle = (cpCircleShape *)shape;
cpVect c = cpvadd(body->p, cpvrotate(circle->c, body->rot));
drawCircle(c.x, c.y, circle->r, body->a);
}
void drawSegmentShape(cpShape *shape)
{
cpBody *body = shape->body;
cpSegmentShape *seg = (cpSegmentShape *)shape;
cpVect a = cpvadd(body->p, cpvrotate(seg->a, body->rot));
cpVect b = cpvadd(body->p, cpvrotate(seg->b, body->rot));
glBegin(GL_LINES); {
glVertex2f(a.x, a.y);
glVertex2f(b.x, b.y);
} glEnd();
}
void drawPolyShape(cpShape *shape)
{
cpBody *body = shape->body;
cpPolyShape *poly = (cpPolyShape *)shape;
int num = poly->numVerts;
cpVect *verts = poly->verts;
int i;
glBegin(GL_POLYGON);
for(i=0; i<num; i++){
cpVect v = cpvadd(body->p, cpvrotate(verts[i], body->rot));
glVertex2f(v.x, v.y);
} glEnd();
}
void drawObject(void *ptr, void *unused)
{
cpShape *shape = (cpShape*)ptr;
switch(shape->type){
case CP_CIRCLE_SHAPE:
drawCircleShape(shape);
break;
case CP_SEGMENT_SHAPE:
drawSegmentShape(shape);
break;
case CP_POLY_SHAPE:
drawPolyShape(shape);
break;
default:
printf("Bad enumeration in drawObject().\n");
}
}
void display(void)
{
int i;
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
glColor3f(1.0, 1.0, 1.0);
cpSpaceHashEach(space->activeShapes, &drawObject, NULL);
cpSpaceHashEach(space->staticShapes, &drawObject, NULL);
glutSwapBuffers();
float dt = .001f;
int intervals = 10;
for ( int a = 0; a < intervals; a++ ) {
for ( int b = 0; b < bodies.size(); b++ ) {
cpBodyResetForces( bodies[b] );
}
cpSpaceStep( space, dt / intervals );
}
glutPostRedisplay();
}
void addBoundingBox() {
//infinite mass, infinite moment of inertia
staticBody = cpBodyNew( INFINITY, INFINITY );
cpVect p1 = cpv(10,10), p2 = cpv(90,10), p3 = cpv(90,90), p4 = cpv(10,90);
cpShape *seg1, *seg2, *seg3, *seg4;
seg1 = cpSegmentShapeNew( staticBody, p1, p2, 1 );
seg2 = cpSegmentShapeNew( staticBody, p2, p3, 1 );
seg3 = cpSegmentShapeNew( staticBody, p3, p4, 1 );
seg4 = cpSegmentShapeNew( staticBody, p4, p1, 1 );
//bodies.push_back( staticBody );
shapes.push_back( seg1 );
shapes.push_back( seg2 );
shapes.push_back( seg3 );
shapes.push_back( seg4 );
//friction
seg1->u = 1;
seg2->u = 1;
seg3->u = 1;
seg4->u = 1;
//elasticity
seg1->e = .95f;
seg2->e = .95f;
seg3->e = .95f;
seg4->e = .95f;
cpSpaceAddStaticShape( space, seg1 );
cpSpaceAddStaticShape( space, seg2 );
cpSpaceAddStaticShape( space, seg3 );
cpSpaceAddStaticShape( space, seg4 );
}
void addPolygon( float x, float y, int sides=4, float radius=.1f, float rotation=.0001f, float mass = 1, float friction=1, float elasticity=.95f ) {
//mass, moment of inertia
cpBody* polygon = cpBodyNew( mass, 1 );
cpVect points[sides];
for ( int a = 0; a < sides; a++ ) {
float angle = rotation + a * 2 * M_PI / sides;
float px = x + radius * cos( -angle );
float py = y + radius * sin( -angle );
points[a] = cpv(px, py);
//cout << px << ", " << py << "." << endl;
}
cpShape *segments[sides];
for ( int a = 0; a < sides; a++ ) {
segments[a] = cpSegmentShapeNew( polygon, points[a], points[(a+1)%sides], 0 );
segments[a]->u = friction;
segments[a]->e = elasticity;
cpSpaceAddShape( space, segments[a] );
shapes.push_back( segments[a] );
}
cpSpaceAddBody( space, polygon );
bodies.push_back( polygon );
//moment of inertia stuff
cpFloat moment = cpMomentForPoly( mass, sides, points, cpvzero );
cpBodySetMoment( polygon, moment );
}
int collide( cpShape* s1, cpShape* s2, cpContact* contact, int a, cpFloat f, void* data ) {
cout << "Collision!!!" << endl;
return 1;
}
void initObjects() {
space = cpSpaceNew();
space->gravity = cpv( 0.f, -100.f);
cpSpaceResizeStaticHash(space, 50.f, 10);
cpSpaceResizeActiveHash(space, 50.f, 100);
addBoundingBox();
addPolygon( 50.f, 100.f, 4, 5.f );
//addPolygon( 60.f, 100.f, 4, 5.f );
cpSpaceSetDefaultCollisionPairFunc(space, &collide, NULL);
}
void glInit() {
glClearColor(0,0,0,1);
glPointSize( 1 );
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho( 0, 100, 0, 100, -1, 1 );
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glColor3f( 0, 0, 0 );
}
void glutInit(int argc, char** argv) {
glutInit( &argc, argv );
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowSize( 500, 500 );
glutCreateWindow("Chipmunk Experiment");
glutDisplayFunc( display );
}
int main(int argc, char** argv) {
cpInitChipmunk();
//main window
glutInit( argc, argv );
//gl stuff
glInit();
//objects in world
initObjects();
glutMainLoop();
return 0;
}