2 // Written and (C) by Francois Fleuret
3 // Contact <francois.fleuret@idiap.ch> for comments & bug reports
9 Universe::Universe(int nb_max_polygons,
10 scalar_t width, scalar_t height) : _width(width), _height(height),
11 _nb_max_polygons(nb_max_polygons), _nb_polygons(0) {
12 _polygons = new Polygon *[_nb_max_polygons];
13 for(int n = 0; n < _nb_max_polygons; n++) _polygons[n] = 0;
16 Universe::~Universe() {
17 for(int n = 0; n < _nb_polygons; n++) if(_polygons[n]) delete _polygons[n];
21 void Universe::initialize(Polygon *p) {
22 p->initialize(_nb_max_polygons);
25 void Universe::clear() {
26 for(int n = 0; n < _nb_polygons; n++) if(_polygons[n]) delete _polygons[n];
30 void Universe::add_polygon(Polygon *p) {
31 if(_nb_polygons < _nb_max_polygons) {
32 if(!p->_initialized) {
33 cerr << "You can not add a non-initialized polygon." << endl;
36 _polygons[_nb_polygons++] = p;
38 cerr << "Too many polygons!" << endl;
43 bool Universe::collide(Polygon *p) {
44 for(int n = 0; n < _nb_polygons; n++)
45 if(_polygons[n] && _polygons[n]->collide(p)) return true;
50 void Universe::compute_pseudo_collisions(int nb_axis, int *nb_colliding_axis) {
51 Couple couples[_nb_polygons * 2];
53 memset((void *) nb_colliding_axis, 0, _nb_polygons * _nb_polygons * sizeof(int));
55 for(int a = 0; a < nb_axis; a++) {
56 scalar_t alpha = M_PI * scalar_t(a) / scalar_t(nb_axis);
57 scalar_t vx = cos(alpha), vy = sin(alpha);
59 for(int n = 0; n < _nb_polygons; n++) {
60 scalar_t *x = _polygons[n]->_x, *y = _polygons[n]->_y;
61 scalar_t min = x[0] * vx + y[0] * vy, max = min;
63 for(int v = 1; v < _polygons[n]->_nb_vertices; v++) {
64 scalar_t s = x[v] * vx + y[v] * vy;
69 couples[2 * n + 0].value = min;
70 couples[2 * n + 0].index = n;
71 couples[2 * n + 1].value = max;
72 couples[2 * n + 1].index = n;
75 qsort((void *) couples, 2 * _nb_polygons, sizeof(Couple), compare_couple);
78 memset((void *) in, 0, _nb_polygons * sizeof(int));
79 for(int k = 0; k < 2 * _nb_polygons; k++) {
80 int i = couples[k].index;
85 for(int j = 0; j < i; j++)
86 if(j != i && in[j]) nb_colliding_axis[j + i * _nb_polygons]++;
87 for(int j = i+1; j < _nb_polygons; j++)
88 if(j != i && in[j]) nb_colliding_axis[i + j * _nb_polygons]++;
94 for(int i = 0; i < _nb_polygons; i++) {
95 for(int j = 0; j < i; j++) {
96 if(nb_colliding_axis[j + i * _nb_polygons] > nb_colliding_axis[i + i * _nb_polygons])
97 nb_colliding_axis[i + i * _nb_polygons] = nb_colliding_axis[j + i * _nb_polygons];
98 nb_colliding_axis[i + j * _nb_polygons] = nb_colliding_axis[j + i * _nb_polygons];
103 bool Universe::update(scalar_t dt) {
105 apply_collision_forces(dt);
106 for(int n = 0; n < _nb_polygons; n++) if(_polygons[n]) {
107 _polygons[n]->apply_border_forces(dt, _width, _height);
108 result |= _polygons[n]->update(dt);
113 Polygon *Universe::pick_polygon(scalar_t x, scalar_t y) {
114 for(int n = 0; n < _nb_polygons; n++)
115 if(_polygons[n] && _polygons[n]->contain(x, y)) return _polygons[n];
119 void Universe::print_xfig(XFigTracer *tracer) {
120 for(int n = 0; n < _nb_polygons; n++) {
122 _polygons[n]->color_xfig(tracer);
125 for(int n = 0; n < _nb_polygons; n++) {
127 _polygons[n]->print_xfig(tracer);
133 void Universe::draw(SimpleWindow *window) {
134 for(int n = 0; n < _nb_polygons; n++) {
136 _polygons[n]->draw(window);
140 for(int n = 0; n < _nb_polygons; n++) {
142 _polygons[n]->draw_contours(window);
149 void Universe::draw(cairo_t *context_resource) {
150 for(int n = 0; n < _nb_polygons; n++) {
152 _polygons[n]->draw(context_resource);
156 for(int n = 0; n < _nb_polygons; n++) {
158 _polygons[n]->draw_contours(context_resource);
164 void Universe::apply_collision_forces(scalar_t dt) {
165 const int nb_axis = 2;
166 int nb_collision[_nb_polygons * _nb_polygons];
168 compute_pseudo_collisions(nb_axis, nb_collision);
170 for(int n = 0; n < _nb_polygons; n++) if(_polygons[n])
171 for(int m = 0; m < _nb_polygons; m++)
172 if(m != n && _polygons[m] && nb_collision[n + _nb_polygons * m] == nb_axis)
173 _polygons[n]->apply_collision_forces(dt, m, _polygons[m]);