cloth

changeset 0:92983e143a03

initial commit
author John Tsiombikas <nuclear@member.fsf.org>
date Mon, 11 Feb 2013 19:40:36 +0200
parents
children 76d4b3e8e941
files .hgignore Makefile src/main.cc src/opengl.h src/particle.cc src/particle.h src/plane.cc src/plane.h src/simworld.cc src/simworld.h
diffstat 10 files changed, 646 insertions(+), 0 deletions(-) [+]
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/.hgignore	Mon Feb 11 19:40:36 2013 +0200
     1.3 @@ -0,0 +1,4 @@
     1.4 +\.o$
     1.5 +\.d$
     1.6 +\.swp$
     1.7 +^cloth$
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/Makefile	Mon Feb 11 19:40:36 2013 +0200
     2.3 @@ -0,0 +1,25 @@
     2.4 +src = $(wildcard src/*.cc)
     2.5 +obj = $(src:.cc=.o)
     2.6 +dep = $(obj:.o=.d)
     2.7 +bin = cloth
     2.8 +
     2.9 +CXXFLAGS = -pedantic -Wall -g
    2.10 +LDFLAGS = $(libgl) -limago -lvmath
    2.11 +
    2.12 +ifeq ($(shell uname -s), Darwin)
    2.13 +	libgl = -framework OpenGL -framework GLUT -lGLEW
    2.14 +else
    2.15 +	libgl = -lGL -lGLU -lglut -lGLEW
    2.16 +endif
    2.17 +
    2.18 +$(bin): $(obj)
    2.19 +	$(CXX) -o $@ $(obj) $(LDFLAGS)
    2.20 +
    2.21 +-include $(dep)
    2.22 +
    2.23 +%.d: %.cc
    2.24 +	@$(CPP) $(CXXFLAGS) $< -MM -MT $(@:.d=.o) >$@
    2.25 +
    2.26 +.PHONY: clean
    2.27 +clean:
    2.28 +	rm -f $(obj) $(bin)
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/src/main.cc	Mon Feb 11 19:40:36 2013 +0200
     3.3 @@ -0,0 +1,144 @@
     3.4 +#include <stdio.h>
     3.5 +#include <stdlib.h>
     3.6 +#include "opengl.h"
     3.7 +
     3.8 +static bool init();
     3.9 +static void cleanup();
    3.10 +static void disp();
    3.11 +static void idle();
    3.12 +static void reshape(int x, int y);
    3.13 +static void keyb(unsigned char key, int x, int y);
    3.14 +static void mouse(int bn, int state, int x, int y);
    3.15 +static void motion(int x, int y);
    3.16 +
    3.17 +static float cam_theta, cam_phi, cam_dist = 8.0;
    3.18 +
    3.19 +static bool moving_cloth;
    3.20 +
    3.21 +
    3.22 +int main(int argc, char **argv)
    3.23 +{
    3.24 +	glutInit(&argc, argv);
    3.25 +	glutInitWindowSize(800, 600);
    3.26 +	glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
    3.27 +	glutCreateWindow("cloth");
    3.28 +
    3.29 +	glutDisplayFunc(disp);
    3.30 +	glutReshapeFunc(reshape);
    3.31 +	glutKeyboardFunc(keyb);
    3.32 +	glutMouseFunc(mouse);
    3.33 +	glutMotionFunc(motion);
    3.34 +	glutIdleFunc(idle);
    3.35 +
    3.36 +	if(!init()) {
    3.37 +		return 1;
    3.38 +	}
    3.39 +	atexit(cleanup);
    3.40 +
    3.41 +	glutMainLoop();
    3.42 +	return 0;
    3.43 +}
    3.44 +
    3.45 +
    3.46 +static bool init()
    3.47 +{
    3.48 +	glewInit();
    3.49 +
    3.50 +	glClearColor(0.2, 0.2, 0.2, 1.0);
    3.51 +
    3.52 +	glEnable(GL_DEPTH_TEST);
    3.53 +	glEnable(GL_CULL_FACE);
    3.54 +
    3.55 +	return true;
    3.56 +}
    3.57 +
    3.58 +static void cleanup()
    3.59 +{
    3.60 +}
    3.61 +
    3.62 +static void disp()
    3.63 +{
    3.64 +	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    3.65 +
    3.66 +	glMatrixMode(GL_MODELVIEW);
    3.67 +	glLoadIdentity();
    3.68 +	glTranslatef(0, 0, -cam_dist);
    3.69 +	glRotatef(cam_phi, 1.0, 0.0, 0.0);
    3.70 +	glRotatef(cam_theta, 0.0, 1.0, 0.0);
    3.71 +
    3.72 +	glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
    3.73 +
    3.74 +	glutSolidTeapot(1.0);
    3.75 +
    3.76 +	glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
    3.77 +
    3.78 +	glutSwapBuffers();
    3.79 +}
    3.80 +
    3.81 +static void idle()
    3.82 +{
    3.83 +	glutPostRedisplay();
    3.84 +}
    3.85 +
    3.86 +static void reshape(int x, int y)
    3.87 +{
    3.88 +	glViewport(0, 0, x, y);
    3.89 +
    3.90 +	glMatrixMode(GL_PROJECTION);
    3.91 +	glLoadIdentity();
    3.92 +	gluPerspective(45.0, (float)x / (float)y, 0.5, 500.0);
    3.93 +}
    3.94 +
    3.95 +static void keyb(unsigned char key, int x, int y)
    3.96 +{
    3.97 +	switch(key) {
    3.98 +	case 27:
    3.99 +		exit(0);
   3.100 +	}
   3.101 +}
   3.102 +
   3.103 +static bool bnstate[16];
   3.104 +static int prev_x, prev_y;
   3.105 +
   3.106 +static void mouse(int bn, int state, int x, int y)
   3.107 +{
   3.108 +	int idx = bn - GLUT_LEFT_BUTTON;
   3.109 +	int st = state == GLUT_DOWN ? 1 : 0;
   3.110 +
   3.111 +	if(idx >= 0 && idx < 16) {
   3.112 +		bnstate[idx] = st;
   3.113 +	}
   3.114 +
   3.115 +	prev_x = x;
   3.116 +	prev_y = y;
   3.117 +}
   3.118 +
   3.119 +static void motion(int x, int y)
   3.120 +{
   3.121 +	int dx = x - prev_x;
   3.122 +	int dy = y - prev_y;
   3.123 +	prev_x = x;
   3.124 +	prev_y = y;
   3.125 +
   3.126 +	if(moving_cloth) {
   3.127 +	} else {
   3.128 +		if(bnstate[0]) {
   3.129 +			cam_theta += dx * 0.5;
   3.130 +			cam_phi += dy * 0.5;
   3.131 +
   3.132 +			if(cam_phi < -90.0) {
   3.133 +				cam_phi = -90.0;
   3.134 +			}
   3.135 +			if(cam_phi > 90.0) {
   3.136 +				cam_phi = 90.0;
   3.137 +			}
   3.138 +		}
   3.139 +		if(bnstate[2]) {
   3.140 +			cam_dist += dy * 0.1;
   3.141 +
   3.142 +			if(cam_dist < 0.0) {
   3.143 +				cam_dist = 0.0;
   3.144 +			}
   3.145 +		}
   3.146 +	}
   3.147 +}
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/src/opengl.h	Mon Feb 11 19:40:36 2013 +0200
     4.3 @@ -0,0 +1,12 @@
     4.4 +#ifndef OPENGL_H_
     4.5 +#define OPENGL_H_
     4.6 +
     4.7 +#include <GL/glew.h>
     4.8 +
     4.9 +#ifdef __APPLE__
    4.10 +#include <GLUT/glut.h>
    4.11 +#else
    4.12 +#include <GL/glut.h>
    4.13 +#endif
    4.14 +
    4.15 +#endif	// OPENGL_H_
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/src/particle.cc	Mon Feb 11 19:40:36 2013 +0200
     5.3 @@ -0,0 +1,167 @@
     5.4 +#include <vector>
     5.5 +#include "opengl.h"
     5.6 +#include "particle.h"
     5.7 +#include "simworld.h"
     5.8 +
     5.9 +Particle::Particle()
    5.10 +	: forces(0, 0, 0), pos(0, 0, 0), velocity(0, 0, 0)
    5.11 +{
    5.12 +	rad = 1.0;
    5.13 +	elast = 0.75;
    5.14 +	mass = 1.0;
    5.15 +	friction = 0.0;
    5.16 +}
    5.17 +
    5.18 +void Particle::add_ignore(const Particle *p)
    5.19 +{
    5.20 +	ignorelist.insert(p);
    5.21 +}
    5.22 +
    5.23 +void Particle::set_radius(float rad)
    5.24 +{
    5.25 +	this->rad = rad;
    5.26 +}
    5.27 +
    5.28 +float Particle::get_radius() const
    5.29 +{
    5.30 +	return rad;
    5.31 +}
    5.32 +
    5.33 +void Particle::set_mass(float m)
    5.34 +{
    5.35 +	mass = m;
    5.36 +}
    5.37 +
    5.38 +float Particle::get_mass() const
    5.39 +{
    5.40 +	return mass;
    5.41 +}
    5.42 +
    5.43 +void Particle::set_elasticity(float e)
    5.44 +{
    5.45 +	elast = e;
    5.46 +}
    5.47 +
    5.48 +float Particle::get_elasticity() const
    5.49 +{
    5.50 +	return elast;
    5.51 +}
    5.52 +
    5.53 +void Particle::set_position(const Vector3 &pos)
    5.54 +{
    5.55 +	this->pos = pos;
    5.56 +}
    5.57 +
    5.58 +void Particle::set_velocity(const Vector3 &vel)
    5.59 +{
    5.60 +	velocity = vel;
    5.61 +}
    5.62 +
    5.63 +Vector3 &Particle::get_position()
    5.64 +{
    5.65 +	return pos;
    5.66 +}
    5.67 +
    5.68 +const Vector3 &Particle::get_position() const
    5.69 +{
    5.70 +	return pos;
    5.71 +}
    5.72 +
    5.73 +Vector3 &Particle::get_velocity()
    5.74 +{
    5.75 +	return velocity;
    5.76 +}
    5.77 +
    5.78 +const Vector3 &Particle::get_velocity() const
    5.79 +{
    5.80 +	return velocity;
    5.81 +}
    5.82 +
    5.83 +void Particle::set_friction(float frict)
    5.84 +{
    5.85 +	friction = frict;
    5.86 +}
    5.87 +
    5.88 +float Particle::get_friction() const
    5.89 +{
    5.90 +	return friction;
    5.91 +}
    5.92 +
    5.93 +void Particle::add_force(const Vector3 &fvec)
    5.94 +{
    5.95 +	forces += fvec;
    5.96 +}
    5.97 +
    5.98 +void Particle::step(SimWorld *world, float dt)
    5.99 +{
   5.100 +	Vector3 accel = forces / mass;
   5.101 +	forces.x = forces.y = forces.z = 0.0f;
   5.102 +
   5.103 +	velocity = velocity * world->damping + accel * dt - velocity * friction * dt;
   5.104 +
   5.105 +	Vector3 newpos = pos + velocity * dt;
   5.106 +
   5.107 +	Ray ray(pos, newpos - pos);
   5.108 +	Collision col;
   5.109 +
   5.110 +	if(world->collision(ray, rad, &col)) {
   5.111 +		pos = col.pos;
   5.112 +		velocity = -velocity.reflection(col.normal) * elast;
   5.113 +	} else {
   5.114 +		pos = newpos;
   5.115 +	}
   5.116 +}
   5.117 +
   5.118 +bool Particle::collision(const Particle *p2, Collision *col) const
   5.119 +{
   5.120 +	if(ignorelist.find(p2) != ignorelist.end()) {
   5.121 +		return false;
   5.122 +	}
   5.123 +
   5.124 +	Vector3 v = p2->pos - pos;
   5.125 +	float dist_sq = dot_product(v, v);
   5.126 +	float radsum = rad + p2->rad;
   5.127 +
   5.128 +	if(dist_sq < radsum * radsum) {
   5.129 +		float rad_ratio = rad / p2->rad;
   5.130 +		Vector3 dir = p2->pos - pos;
   5.131 +		col->pos = pos + dir * rad_ratio;
   5.132 +		col->normal = -dir.normalized();
   5.133 +		col->elast = elast * p2->elast;
   5.134 +		return true;
   5.135 +	}
   5.136 +	return false;
   5.137 +}
   5.138 +
   5.139 +void Particle::draw() const
   5.140 +{
   5.141 +	float color[] = {0.3, 0.9, 0.2, 1};
   5.142 +
   5.143 +	glPushMatrix();
   5.144 +	glTranslatef(pos.x, pos.y, pos.z);
   5.145 +
   5.146 +	glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color);
   5.147 +
   5.148 +	glutSolidSphere(rad, 16, 8);
   5.149 +
   5.150 +	glPushAttrib(GL_ENABLE_BIT);
   5.151 +	glDisable(GL_DEPTH_TEST);
   5.152 +	glDisable(GL_LIGHTING);
   5.153 +	glEnable(GL_BLEND);
   5.154 +	glBlendFunc(GL_ONE, GL_ONE);
   5.155 +	glLineWidth(2.0);
   5.156 +
   5.157 +	glBegin(GL_LINES);
   5.158 +	glColor3f(0.3, 0, 0);
   5.159 +	glVertex3f(0, 0, 0);
   5.160 +	glVertex3f(velocity.x, velocity.y, velocity.z);
   5.161 +
   5.162 +	glColor3f(0, 0, 0.8);
   5.163 +	glVertex3f(0, 0, 0);
   5.164 +	glVertex3f(forces.x, forces.y, forces.z);
   5.165 +	glEnd();
   5.166 +
   5.167 +	glPopAttrib();
   5.168 +
   5.169 +	glPopMatrix();
   5.170 +}
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/src/particle.h	Mon Feb 11 19:40:36 2013 +0200
     6.3 @@ -0,0 +1,57 @@
     6.4 +#ifndef PARTICLE_H_
     6.5 +#define PARTICLE_H_
     6.6 +
     6.7 +#include <set>
     6.8 +#include "vmath/vmath.h"
     6.9 +
    6.10 +class SimWorld;
    6.11 +struct Collision;
    6.12 +
    6.13 +class Particle {
    6.14 +private:
    6.15 +	Vector3 forces;
    6.16 +	Vector3 pos, velocity;
    6.17 +	float rad;
    6.18 +	float elast;
    6.19 +	float mass;
    6.20 +	float friction;
    6.21 +
    6.22 +	std::set<const Particle*> ignorelist;
    6.23 +
    6.24 +public:
    6.25 +	Particle();
    6.26 +
    6.27 +	void add_ignore(const Particle *p);
    6.28 +
    6.29 +	void set_radius(float rad);
    6.30 +	float get_radius() const;
    6.31 +
    6.32 +	void set_mass(float m);
    6.33 +	float get_mass() const;
    6.34 +
    6.35 +	void set_elasticity(float e);
    6.36 +	float get_elasticity() const;
    6.37 +
    6.38 +	void set_position(const Vector3 &pos);
    6.39 +	void set_velocity(const Vector3 &vel);
    6.40 +
    6.41 +	Vector3 &get_position();
    6.42 +	const Vector3 &get_position() const;
    6.43 +	Vector3 &get_velocity();
    6.44 +	const Vector3 &get_velocity() const;
    6.45 +
    6.46 +	void set_friction(float frict);
    6.47 +	float get_friction() const;
    6.48 +
    6.49 +	void add_force(const Vector3 &fvec);
    6.50 +
    6.51 +	void step(SimWorld *world, float dt);
    6.52 +
    6.53 +	bool collision(const Particle *p2, Collision *col) const;
    6.54 +
    6.55 +	void draw() const;
    6.56 +
    6.57 +	friend class SimWorld;
    6.58 +};
    6.59 +
    6.60 +#endif	// PARTICLE_H_
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/src/plane.cc	Mon Feb 11 19:40:36 2013 +0200
     7.3 @@ -0,0 +1,72 @@
     7.4 +#include "opengl.h"
     7.5 +#include "plane.h"
     7.6 +#include "simworld.h"
     7.7 +
     7.8 +Plane::Plane()
     7.9 +	: pt(0, 0, 0), normal(0, 1, 0)
    7.10 +{
    7.11 +}
    7.12 +
    7.13 +Plane::Plane(const Vector3 &pt, const Vector3 &norm)
    7.14 +	this->pt(pt), normal(pt)
    7.15 +{
    7.16 +}
    7.17 +
    7.18 +Plane::Plane(const Vector3 &norm, float dist)
    7.19 +	: normal(norm)
    7.20 +{
    7.21 +	pt = Vector3(0, 0, 0) - norm * dist;
    7.22 +}
    7.23 +
    7.24 +bool Plane::collision(const Ray &ray, float rad, Collision *col) const
    7.25 +{
    7.26 +	Vector3 pt = this->pt - normal * rad;
    7.27 +
    7.28 +	float ndotdir = dot_product(ray.dir, normal);
    7.29 +	if(fabs(ndotdir) < 1e-6) {
    7.30 +		return false;
    7.31 +	}
    7.32 +
    7.33 +	float ndotptdir = dot_product((pt - ray.origin), normal);
    7.34 +
    7.35 +	float t = ndotptdir / ndotdir;
    7.36 +	if(t < 1e-6 || t > (1.0 - 1e-6)) {
    7.37 +		return false;
    7.38 +	}
    7.39 +
    7.40 +	col->pos = ray.origin + ray.dir * t;
    7.41 +	col->normal = normal;
    7.42 +	col->elast = 1.0;
    7.43 +	return true;
    7.44 +}
    7.45 +
    7.46 +void Plane::draw(float sz) const
    7.47 +{
    7.48 +	Vector3 up = Vector3(0, 1, 0);
    7.49 +	if(fabs(dot_product(up, normal)) < 1e-6) {
    7.50 +		up = Vector3(0, 0, 1);
    7.51 +	}
    7.52 +
    7.53 +	Vector3 right = cross_product(up, normal);
    7.54 +	up = cross_product(normal, right);
    7.55 +
    7.56 +	Matrix4x4 rot_matrix;
    7.57 +	rot_matrix.set_column_vector(right, 0);
    7.58 +	rot_matrix.set_column_vector(up, 1);
    7.59 +	rot_matrix.set_column_vector(normal, 2);
    7.60 +	rot_matrix.set_row_vector(Vector4(0, 0, 0, 1), 3);
    7.61 +
    7.62 +	glMatrixMode(GL_MODELVIEW);
    7.63 +	glPushMatrix();
    7.64 +	glMultTransposeMatrixf((float*)rot_matrix.m);
    7.65 +
    7.66 +	glBegin(GL_QUADS);
    7.67 +	glNormal3f(normal.x, normal.y, normal.z);
    7.68 +	glVertex2f(-sz, -sz);
    7.69 +	glVertex2f(sz, -sz);
    7.70 +	glVertex2f(sz, sz);
    7.71 +	glVertex2f(-sz, sz);
    7.72 +	glEnd();
    7.73 +
    7.74 +	glPopMatrix();
    7.75 +}
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/src/plane.h	Mon Feb 11 19:40:36 2013 +0200
     8.3 @@ -0,0 +1,22 @@
     8.4 +#ifndef PLANE_H_
     8.5 +#define PLANE_H_
     8.6 +
     8.7 +#include <vmath/vmath.h>
     8.8 +
     8.9 +struct Collision;
    8.10 +
    8.11 +class Plane {
    8.12 +public:
    8.13 +	Vector3 pt;
    8.14 +	Vector3 normal;
    8.15 +
    8.16 +	Plane();
    8.17 +	Plane(const Vector3 &pt, const Vector3 &norm);
    8.18 +	Plane(const Vector3 &norm, float dist);
    8.19 +
    8.20 +	bool collision(const Ray &ray, float rad, Collision *col) const;
    8.21 +
    8.22 +	void draw(float sz) const;
    8.23 +};
    8.24 +
    8.25 +#endif	// PLANE_H_
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/src/simworld.cc	Mon Feb 11 19:40:36 2013 +0200
     9.3 @@ -0,0 +1,104 @@
     9.4 +#include "simworld.h"
     9.5 +
     9.6 +SimWorld::SimWorld()
     9.7 +{
     9.8 +	bbmin = Vector2(-1, -1);
     9.9 +	bbmax = Vector2(1, 1);
    9.10 +	grav = Vector3(0, -9.81, 0);
    9.11 +	damping = 0.99;
    9.12 +}
    9.13 +
    9.14 +void SimWorld::set_bounds(float xmin, float xmax, float ymin, float ymax)
    9.15 +{
    9.16 +	bbmin.x = xmin;
    9.17 +	bbmin.y = ymin;
    9.18 +	bbmax.x = xmax;
    9.19 +	bbmax.y = ymax;
    9.20 +}
    9.21 +
    9.22 +void SimWorld::add_particle(Particle *p)
    9.23 +{
    9.24 +	part.push_back(p);
    9.25 +}
    9.26 +
    9.27 +bool SimWorld::collision(const Ray &ray, float rad, Collision *col) const
    9.28 +{
    9.29 +	bool found = false;
    9.30 +
    9.31 +	Vector2 min = bbmin + Vector2(rad, rad);
    9.32 +	Vector2 max = bbmax - Vector2(rad, rad);
    9.33 +
    9.34 +	// collision with the boundaries
    9.35 +	Vector3 npos = ray.origin + ray.dir;
    9.36 +
    9.37 +	Vector3 col_pos, col_norm;
    9.38 +	float d, col_depth = 0;
    9.39 +
    9.40 +	if((d = min.x - npos.x) > col_depth) {
    9.41 +		col->pos = npos;
    9.42 +		col->pos.x = min.x;
    9.43 +		col->normal = Vector3(1, 0, 0);
    9.44 +		col_depth = d;
    9.45 +		found = true;
    9.46 +	}
    9.47 +	if((d = min.y - npos.z) > col_depth) {
    9.48 +		col->pos = npos;
    9.49 +		col->pos.z = min.y;
    9.50 +		col->normal = Vector3(0, 0, 1);
    9.51 +		col_depth = d;
    9.52 +		found = true;
    9.53 +	}
    9.54 +	if((d = npos.x - max.x) > col_depth) {
    9.55 +		col->pos = npos;
    9.56 +		col->pos.x = max.x;
    9.57 +		col->normal = Vector3(-1, 0, 0);
    9.58 +		col_depth = d;
    9.59 +		found = true;
    9.60 +	}
    9.61 +	if((d = npos.z - max.y) > col_depth) {
    9.62 +		col->pos = npos;
    9.63 +		col->pos.z = max.y;
    9.64 +		col->normal = Vector3(0, 0, -1);
    9.65 +		col_depth = d;
    9.66 +		found = true;
    9.67 +	}
    9.68 +
    9.69 +	return found;
    9.70 +}
    9.71 +
    9.72 +void SimWorld::step(float dt)
    9.73 +{
    9.74 +	for(size_t i=0; i<part.size(); i++) {
    9.75 +		// add gravity
    9.76 +		part[i]->add_force(grav * part[i]->get_mass());
    9.77 +
    9.78 +		part[i]->step(this, dt);
    9.79 +
    9.80 +		// handle collisions with other particles
    9.81 +		for(size_t j=0; j<part.size(); j++) {
    9.82 +			Collision col;
    9.83 +			if(i != j && part[i]->collision(part[j], &col)) {
    9.84 +				Vector3 rel_vel = part[j]->get_velocity() - part[i]->get_velocity();
    9.85 +
    9.86 +				float kn = 1.0 / part[i]->get_mass() + 1.0 / part[j]->get_mass();
    9.87 +				float imp = dot_product(rel_vel, col.normal) * (col.elast + 1) / kn;
    9.88 +
    9.89 +				if(imp < 0.0) imp = 0.0;
    9.90 +
    9.91 +				Vector3 v = part[i]->get_position() - part[j]->get_position();
    9.92 +				float dist_sq = v.length_sq();
    9.93 +				float pen_depth_sq = part[i]->get_radius() + part[j]->get_radius() - dist_sq;
    9.94 +				if(pen_depth_sq < 0.0) pen_depth_sq = 0.0;
    9.95 +
    9.96 +				part[i]->add_force(col.normal * imp * (1.0 / dt * pen_depth_sq + 1));
    9.97 +			}
    9.98 +		}
    9.99 +	}
   9.100 +}
   9.101 +
   9.102 +void SimWorld::draw_particles() const
   9.103 +{
   9.104 +	for(size_t i=0; i<part.size(); i++) {
   9.105 +		part[i]->draw();
   9.106 +	}
   9.107 +}
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/src/simworld.h	Mon Feb 11 19:40:36 2013 +0200
    10.3 @@ -0,0 +1,39 @@
    10.4 +#ifndef SIMWORLD_H_
    10.5 +#define SIMWORLD_H_
    10.6 +
    10.7 +#include <vector>
    10.8 +#include "particle.h"
    10.9 +#include "vmath/vmath.h"
   10.10 +
   10.11 +struct Collision {
   10.12 +	Vector3 pos;
   10.13 +	Vector3 normal;
   10.14 +	float elast;
   10.15 +};
   10.16 +
   10.17 +class SimWorld {
   10.18 +private:
   10.19 +	std::vector<Object*> objects;
   10.20 +	std::vector<Particle*> part;
   10.21 +	Vector3 grav;
   10.22 +	float damping;
   10.23 +
   10.24 +public:
   10.25 +	SimWorld();
   10.26 +
   10.27 +	void set_bounds(float xmin, float xmax, float ymin, float ymax);
   10.28 +
   10.29 +	void set_gravity(const Vector3 &f);
   10.30 +
   10.31 +	void add_particle(Particle *p);
   10.32 +
   10.33 +	bool collision(const Ray &ray, float rad, Collision *col) const;
   10.34 +
   10.35 +	void step(float dt);
   10.36 +
   10.37 +	void draw_particles() const;
   10.38 +
   10.39 +	friend class Particle;
   10.40 +};
   10.41 +
   10.42 +#endif	// SIMWORLD_H_