]> git.cworth.org Git - akamaru/commitdiff
Generalize offset constraint to work on a number of points.
authorKristian Høgsberg <krh@redhat.com>
Tue, 23 May 2006 05:29:04 +0000 (01:29 -0400)
committerKristian Høgsberg <krh@dinky.bitplanet.net>
Tue, 23 May 2006 05:29:04 +0000 (01:29 -0400)
This is useful for implementing a rigid line of points, useful for a
title bar, for example.

akamaru.c

index af0a0f19bc66550ad0d94fd8970da51e1fa4c2d0..b26adea7b176450d6c82b528b89d4f2382164313 100644 (file)
--- a/akamaru.c
+++ b/akamaru.c
 #include <sys/time.h>
 #include <math.h>
 
-const double ground_friction = 0.1, ground_level = 400;
-const double box_left = 200, box_top = 200, box_bottom = 210;
+const double ground_level = 500;
 const double elasticity = 0.7;
-const double edge_fuzz = 1;
 
 typedef struct _xy_pair Point;
 typedef struct _xy_pair Vector;
@@ -66,7 +64,8 @@ struct _String {
 };
 
 struct _Offset {
-  Object *a, *b;
+  int num_objects;
+  Object **objects;
   int dx, dy;
 };
 
@@ -249,10 +248,15 @@ model_init_curtain (Model *model)
   model->num_objects = num_objects;
   model->sticks = g_new (Stick, num_sticks);
   model->num_sticks = num_sticks;
-  model->offsets = g_new (Offset, num_ropes - 1);
-  model->num_offsets = num_ropes - 1;
+  model->offsets = g_new (Offset, 1);
+  model->num_offsets = 1;
   model_init_polygons (model);
 
+  model->offsets[0].num_objects = num_ropes;
+  model->offsets[0].objects = g_new (Object *, num_ropes);
+  model->offsets[0].dx = rope_offset;
+  model->offsets[0].dy = 0;
+
   for (i = 0; i < num_ropes; i++) {
     for (j = 0; j < num_rope_objects; j++) {
       x = 200 + i * rope_offset;
@@ -271,12 +275,7 @@ model_init_curtain (Model *model)
       }
     }
 
-    if (i + 1 < num_ropes) {
-      model->offsets[i].a = &model->objects[i * num_rope_objects];
-      model->offsets[i].b = &model->objects[(i + 1) * num_rope_objects];
-      model->offsets[i].dx = rope_offset;
-      model->offsets[i].dy = 0;
-    }
+    model->offsets[0].objects[i] = &model->objects[i * num_rope_objects];
   }
 
   model->anchor_object = NULL;
@@ -300,10 +299,15 @@ model_init_grid (Model *model)
   model->num_objects = num_objects;
   model->strings = g_new (String, num_strings);
   model->num_strings = num_strings;
-  model->offsets = g_new (Offset, num_ropes - 1);
-  model->num_offsets = num_ropes - 1;
+  model->offsets = g_new (Offset, 1);
+  model->num_offsets = 1;
   model_init_polygons (model);
 
+  model->offsets[0].num_objects = num_ropes;
+  model->offsets[0].objects = g_new (Object *, num_ropes);
+  model->offsets[0].dx = rope_offset;
+  model->offsets[0].dy = 0;
+
   for (i = 0; i < num_ropes; i++) {
     for (j = 0; j < num_rope_objects; j++) {
       x = 200 + i * rope_offset;
@@ -330,12 +334,7 @@ model_init_grid (Model *model)
       }
     }
 
-    if (i + 1 < num_ropes) {
-      model->offsets[i].a = &model->objects[i * num_rope_objects];
-      model->offsets[i].b = &model->objects[(i + 1) * num_rope_objects];
-      model->offsets[i].dx = rope_offset;
-      model->offsets[i].dy = 0;
-    }
+    model->offsets[0].objects[i] = &model->objects[i * num_rope_objects];
   }
 
   model->anchor_object = NULL;
@@ -466,6 +465,28 @@ model_constrain_polygon (Model *model, Polygon *polygon)
   }
 }
 
+static void
+model_constrain_offset (Model *model, Offset *offset)
+{
+  double x, y;
+  int i;
+
+  x = 0;
+  y = 0;
+  for (i = 0; i < offset->num_objects; i++) {
+    x += offset->objects[i]->position.x;
+    y += offset->objects[i]->position.y;
+  }
+
+  x = x / offset->num_objects - offset->dx * (offset->num_objects - 1) / 2;
+  y = y / offset->num_objects - offset->dy * (offset->num_objects - 1) / 2;
+    
+  for (i = 0; i < offset->num_objects; i++) {
+    offset->objects[i]->position.x = x + offset->dx * i;
+    offset->objects[i]->position.y = y + offset->dy * i;
+  }
+}
+
 static void
 model_constrain (Model *model)
 {
@@ -480,16 +501,6 @@ model_constrain (Model *model)
     model->anchor_object->previous_position.y = model->anchor_position.y;
   }
 
-  /* Offset constraints. */
-  for (i = 0; i < model->num_offsets; i++) {
-    x = (model->offsets[i].a->position.x + model->offsets[i].b->position.x) / 2;
-    y = (model->offsets[i].a->position.y + model->offsets[i].b->position.y) / 2;
-    model->offsets[i].a->position.x = x - model->offsets[i].dx / 2;
-    model->offsets[i].a->position.y = y - model->offsets[i].dy / 2;
-    model->offsets[i].b->position.x = x + model->offsets[i].dx / 2;
-    model->offsets[i].b->position.y = y + model->offsets[i].dy / 2;
-  }
-
   /* String constraints. */
   for (i = 0; i < model->num_strings; i++) {
     x = model->strings[i].a->position.x;
@@ -520,6 +531,10 @@ model_constrain (Model *model)
     model->sticks[i].b->position.y = y + dy * (1 - fraction);
   }
 
+  /* Offset constraints. */
+  for (i = 0; i < model->num_offsets; i++)
+    model_constrain_offset (model, &model->offsets[i]);
+
   /* Polygon constraints. */
   for (i = 0; i < model->num_polygons; i++)
     model_constrain_polygon (model, &model->polygons[i]);
@@ -533,7 +548,7 @@ model_step (Model *model, double delta_t)
   model_accumulate_forces (model);
   model_integrate (model, delta_t);
 
-  for (i = 0; i < 100; i++)
+  for (i = 0; i < 500; i++)
     model_constrain (model);
 
   model->theta += delta_t;
@@ -628,7 +643,7 @@ draw_offsets (cairo_t *cr,
              Model   *model,
              Color   *color)
 {
-  int i;
+  int i, j;
 
   cairo_set_source_rgba (cr, color->red, color->green, color->blue, 0.5);
   cairo_new_path (cr);
@@ -637,15 +652,14 @@ draw_offsets (cairo_t *cr,
   cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
 
   for (i = 0; i < model->num_offsets; i++) {
-    cairo_move_to (cr,
-                  model->offsets[i].a->position.x,
-                  model->offsets[i].a->position.y);
-    cairo_line_to (cr,
-                  model->offsets[i].b->position.x,
-                  model->offsets[i].b->position.y);
+    for (j = 0; j < model->offsets[i].num_objects; j++) {
+      cairo_line_to (cr,
+                    model->offsets[i].objects[j]->position.x,
+                    model->offsets[i].objects[j]->position.y);
+    }
+    cairo_stroke (cr);
   }
 
-  cairo_stroke (cr);
 }
 
 static void
@@ -692,12 +706,9 @@ struct _Closure {
   struct timeval start;
 };
 
-static gboolean
-expose_event (GtkWidget      *widget,
-             GdkEventExpose *event,
-             gpointer        data)
+static void
+draw_model (GtkWidget *widget, Model *model)
 {
-  Closure *closure = data;
   cairo_t *cr;
 
   cr = gdk_cairo_create (widget->window);
@@ -705,13 +716,23 @@ expose_event (GtkWidget      *widget,
   cairo_set_source_rgb (cr, 1, 1, 1);
   cairo_paint (cr);
 
-  draw_polygons (cr, closure->model, &blue);
-  draw_sticks (cr, closure->model, &black);
-  draw_strings (cr, closure->model, &green);
-  draw_offsets (cr, closure->model, &blue);
-  draw_objects (cr, closure->model, &white);
+  draw_polygons (cr, model, &blue);
+  draw_sticks (cr, model, &black);
+  draw_strings (cr, model, &green);
+  draw_offsets (cr, model, &blue);
+  draw_objects (cr, model, &white);
 
   cairo_destroy (cr);
+}
+
+static gboolean
+expose_event (GtkWidget      *widget,
+             GdkEventExpose *event,
+             gpointer        data)
+{
+  Closure *closure = data;
+
+  draw_model (widget, closure->model);
 
   return TRUE;
 }
@@ -759,7 +780,7 @@ motion_notify_event (GtkWidget          *widget,
   GdkModifierType state;
 
   gdk_window_get_pointer (event->window, &x, &y, &state);
-
+  
   closure->model->anchor_position.x = x + 0.5;
   closure->model->anchor_position.y = y + 0.5;
 
@@ -884,7 +905,7 @@ create_window (Closure *closure)
       
   da = gtk_drawing_area_new ();
   /* set a minimum size */
-  gtk_widget_set_size_request (da, 600, 500);
+  gtk_widget_set_size_request (da, 200, 200);
 
   gtk_container_add (GTK_CONTAINER (frame), da);
 
@@ -973,7 +994,7 @@ main (int argc, char *argv[])
   closure.model = &model;
   closure.frame_count = 0;
   gettimeofday (&closure.start, NULL);
-  g_timeout_add (50, timeout_callback, &closure);
+  g_timeout_add (100, timeout_callback, &closure);
   gtk_main ();
 
   return 0;