diff options
author | Kristian Høgsberg <krh@redhat.com> | 2006-07-12 15:36:55 -0400 |
---|---|---|
committer | Kristian Høgsberg <krh@redhat.com> | 2006-07-12 15:36:55 -0400 |
commit | 1df47d291542a5afd474a31e7df2066cfd92b08d (patch) | |
tree | 7fd52c7cfed8a375d460bc05f92431a239af2ab3 | |
parent | 6fc8f83a50b04d40ebd38e79f1954b8f05889255 (diff) |
Finish dynamic model rewrite, port all of main.c over.
-rw-r--r-- | akamaru.c | 261 | ||||
-rw-r--r-- | akamaru.h | 55 | ||||
-rw-r--r-- | main.c | 541 |
3 files changed, 413 insertions, 444 deletions
@@ -54,10 +54,13 @@ list_init (List *list, size_t offset) static void list_for_each (List *list, ListFunc func, void *data) { - Link *l; + Link *l, *next; - for (l = list->head.next; l != &list->head; l = l->next) - func ((char *) l - list->offset, data); + for (l = list->head.next; l != &list->head; l = next) + { + next = l->next; + func ((char *) l - list->offset, data); + } } static void @@ -102,6 +105,12 @@ model_add_spring (Model *model, Object *a, Object *b, double length) } void +model_for_each_spring (Model *model, SpringFunc func, void *data) +{ + list_for_each (&model->spring_list, (ListFunc) func, data); +} + +void stick_init (Stick *stick, Object *a, Object *b, double length) { stick->a = a; @@ -124,6 +133,12 @@ model_add_stick (Model *model, Object *a, Object *b, double length) } void +model_for_each_stick (Model *model, StickFunc func, void *data) +{ + list_for_each (&model->stick_list, (ListFunc) func, data); +} + +void string_init (String *string, Object *a, Object *b, double length) { string->a = a; @@ -146,13 +161,31 @@ model_add_string (Model *model, Object *a, Object *b, double length) } void -offset_spring_init (OffsetSpring *spring, Object *a, Object *b, - double dx, double dy) +model_for_each_string (Model *model, StringFunc func, void *data) { + list_for_each (&model->string_list, (ListFunc) func, data); +} + +OffsetSpring * +model_add_offset_spring (Model *model, Object *a, Object *b, + double dx, double dy) +{ + OffsetSpring *spring; + + spring = g_new (OffsetSpring, 1); spring->a = a; spring->b = b; spring->dx = dx; spring->dy = dy; + list_append (&model->offset_spring_list, spring); + + return spring; +} + +void +model_for_each_offset_spring (Model *model, OffsetSpringFunc func, void *data) +{ + list_for_each (&model->offset_spring_list, (ListFunc) func, data); } void @@ -178,6 +211,12 @@ model_add_spacer (Model *model, Object *a, Object *b, double length) } void +model_for_each_spacer (Model *model, SpacerFunc func, void *data) +{ + list_for_each (&model->spacer_list, (ListFunc) func, data); +} + +void anchor_init (Anchor *anchor, Object *object, double x, double y) { anchor->object = object; @@ -200,6 +239,19 @@ model_add_anchor (Model *model, Object *object, double x, double y) } void +model_delete_anchor (Model *model, Anchor *anchor) +{ + link_remove (&anchor->link); + g_free (anchor); +} + +void +model_for_each_anchor (Model *model, AnchorFunc func, void *data) +{ + list_for_each (&model->anchor_list, (ListFunc) func, data); +} + +void polygon_init_from_va_list (Polygon *p, int enclosing, int num_points, va_list ap) { @@ -257,28 +309,26 @@ model_add_polygon (Model *model, int enclosing, int num_points, ...) } void -polygon_init_diamond (Polygon *polygon, double x, double y) +model_for_each_polygon (Model *model, PolygonFunc func, void *data) { - return polygon_init (polygon, FALSE, 5, - x, y, - x + 10, y + 40, - x + 90, y + 40, - x + 100, y, - x + 50, y - 20); + list_for_each (&model->polygon_list, (ListFunc) func, data); } -void -polygon_init_rectangle (Polygon *polygon, double x0, double y0, - double x1, double y1) +Polygon * +model_add_diamond (Model *model, double x, double y) { - return polygon_init (polygon, FALSE, 4, x0, y0, x0, y1, x1, y1, x1, y0); + return model_add_polygon (model, FALSE, 5, + x, y, + x + 10, y + 40, + x + 90, y + 40, + x + 100, y, + x + 50, y - 20); } -void -polygon_init_enclosing_rectangle (Polygon *polygon, double x0, double y0, - double x1, double y1) +Polygon * +model_add_rectangle (Model *model, double x0, double y0, double x1, double y1) { - return polygon_init (polygon, TRUE, 4, x0, y0, x0, y1, x1, y1, x1, y0); + return model_add_polygon (model, FALSE, 4, x0, y0, x0, y1, x1, y1, x1, y0); } Polygon * @@ -288,18 +338,41 @@ model_add_enclosing_rectangle (Model *model, double x0, double y0, return model_add_polygon (model, TRUE, 4, x0, y0, x0, y1, x1, y1, x1, y0); } +Offset * +model_add_offset (Model *model, int num_objects, double dx, double dy) +{ + Offset *offset; + + offset = g_new (Offset, 1); + offset->num_objects = num_objects; + offset->objects = g_new (Object *, num_objects); + offset->dx = dx; + offset->dy = dy; + list_append (&model->offset_list, offset); + + return offset; +} + +void +model_for_each_offset (Model *model, OffsetFunc func, void *data) +{ + list_for_each (&model->offset_list, (ListFunc) func, data); +} + void model_init (Model *model) { memset (model, 0, sizeof *model); list_init (&model->object_list, G_STRUCT_OFFSET (Object, link)); list_init (&model->spacer_list, G_STRUCT_OFFSET (Spacer, link)); - list_init (&model->spring_list, G_STRUCT_OFFSET (Spring, link)); - list_init (&model->stick_list, G_STRUCT_OFFSET (Stick, link)); list_init (&model->string_list, G_STRUCT_OFFSET (String, link)); + list_init (&model->stick_list, G_STRUCT_OFFSET (Stick, link)); + list_init (&model->spring_list, G_STRUCT_OFFSET (Spring, link)); list_init (&model->anchor_list, G_STRUCT_OFFSET (Anchor, link)); list_init (&model->polygon_list, G_STRUCT_OFFSET (Polygon, link)); list_init (&model->offset_list, G_STRUCT_OFFSET (Offset, link)); + list_init (&model->offset_spring_list, + G_STRUCT_OFFSET (OffsetSpring, link)); } Object * @@ -325,24 +398,39 @@ model_for_each_object (Model *model, ObjectFunc func, void *data) list_for_each (&model->object_list, (ListFunc) func, data); } -void -model_fini (Model *model) +static void +free_element (void *element, void *data) { - int i; + g_free (element); +} - g_free (model->objects); - g_free (model->sticks); - g_free (model->strings); - for (i = 0; i < model->num_offsets; i++) - g_free (model->offsets[i].objects); - g_free (model->springs); - g_free (model->offset_springs); - g_free (model->spacers); - for (i = 0; i < model->num_polygons; i++) - g_free (model->polygons[i].points); - g_free (model->polygons); +static void +free_polygon (Polygon *polygon, void *data) +{ + g_free (polygon->points); + g_free (polygon->normals); + g_free (polygon); +} - memset (model, 0, sizeof *model); +static void +free_offset (Offset *offset, void *data) +{ + g_free (offset->objects); + g_free (offset); +} + +void +model_fini (Model *model) +{ + list_for_each (&model->object_list, free_element, NULL); + list_for_each (&model->spacer_list, free_element, NULL); + list_for_each (&model->string_list, free_element, NULL); + list_for_each (&model->stick_list, free_element, NULL); + list_for_each (&model->spring_list, free_element, NULL); + list_for_each (&model->anchor_list, free_element, NULL); + model_for_each_polygon (model, free_polygon, NULL); + model_for_each_offset (model, free_offset, NULL); + list_for_each (&model->offset_spring_list, free_element, NULL); } static void @@ -363,9 +451,8 @@ object_accumulate_forces (Object *object, void *data) } static void -spring_accumulate_forces (void *element, void *data) +spring_accumulate_forces (Spring *spring, void *data) { - Spring *spring = element; Model *model = data; double x, y, dx, dy, distance, displacement; Vector u; @@ -384,36 +471,32 @@ spring_accumulate_forces (void *element, void *data) spring->b->force.y -= u.y * model->k * displacement; } -static void -model_accumulate_forces (Model *model) +void +offset_spring_accumulate_forces (OffsetSpring *spring, void *data) { - int i; - double x, y, dx, dy; + Model *model = data; + double dx, dy; Point middle; - model_for_each_object (model, object_accumulate_forces, model); - - list_for_each (&model->spring_list, spring_accumulate_forces, model); + middle.x = (spring->a->position.x + spring->b->position.x) / 2; + middle.y = (spring->a->position.y + spring->b->position.y) / 2; - for (i = 0; i < model->num_offset_springs; i++) { - middle.x = - (model->offset_springs[i].a->position.x + - model->offset_springs[i].b->position.x) / 2; - middle.y = - (model->offset_springs[i].a->position.y + - model->offset_springs[i].b->position.y) / 2; + dx = (middle.x - spring->dx / 2) - spring->a->position.x; + dy = (middle.y - spring->dy / 2) - spring->a->position.y; - x = middle.x - model->offset_springs[i].dx / 2; - y = middle.y - model->offset_springs[i].dy / 2; - - dx = x - model->offset_springs[i].a->position.x; - dy = y - model->offset_springs[i].a->position.y; + spring->a->force.x += dx * model->k; + spring->a->force.y += dy * model->k; + spring->b->force.x -= dx * model->k; + spring->b->force.y -= dy * model->k; +} - model->offset_springs[i].a->force.x += dx * model->k; - model->offset_springs[i].a->force.y += dy * model->k; - model->offset_springs[i].b->force.x -= dx * model->k; - model->offset_springs[i].b->force.y -= dy * model->k; - } +static void +model_accumulate_forces (Model *model) +{ + model_for_each_object (model, object_accumulate_forces, model); + model_for_each_spring (model, spring_accumulate_forces, model); + model_for_each_offset_spring (model, + offset_spring_accumulate_forces, model); } static void @@ -437,7 +520,7 @@ object_integrate (Object *object, void *data) /* The square root in the distance computation for the string and * stick constraints can be aproximated using Newton: * - * distance = + * distance = * (model->sticks[i].length + * (dx * dx + dy * dy) / model->sticks[i].length) / 2; * @@ -520,20 +603,18 @@ object_constrain_polygon (Object *object, void *data) } static void -model_constrain_polygon (void *element, void *data) +model_constrain_polygon (Polygon *polygon, void *data) { ObjectConstrainPolygonClosure closure; - closure.polygon = element; + closure.polygon = polygon; closure.model = data; model_for_each_object (closure.model, object_constrain_polygon, &closure); } static void -model_constrain_anchor (void *element, void *data) +model_constrain_anchor (Anchor *anchor, void *data) { - Anchor *anchor = element; - if (anchor->object == NULL) return; @@ -542,32 +623,32 @@ model_constrain_anchor (void *element, void *data) } static void -model_constrain_offset (void *element, void *data) +model_constrain_offset (Offset *offset, void *data) { - Offset *offset = element; 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; - } + 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; - } + 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_string (void *element, void *data) +model_constrain_string (String *string, void *data) { - String *string = element; double x, y, dx, dy, distance, fraction; x = string->a->position.x; @@ -588,9 +669,8 @@ model_constrain_string (void *element, void *data) static void -model_constrain_spacer (void *element, void *data) +model_constrain_spacer (Spacer *spacer, void *data) { - Spacer *spacer = element; double x, y, dx, dy, distance, fraction; x = spacer->a->position.x; @@ -610,9 +690,8 @@ model_constrain_spacer (void *element, void *data) } static void -model_constrain_stick (void *element, void *data) +model_constrain_stick (Stick *stick, void *data) { - Stick *stick = element; double x, y, dx, dy, distance, fraction; x = stick->a->position.x; @@ -632,12 +711,12 @@ model_constrain_stick (void *element, void *data) static void model_constrain (Model *model) { - list_for_each (&model->anchor_list, model_constrain_anchor, model); - list_for_each (&model->string_list, model_constrain_string, model); - list_for_each (&model->spacer_list, model_constrain_spacer, model); - list_for_each (&model->stick_list, model_constrain_stick, model); - list_for_each (&model->offset_list, model_constrain_offset, model); - list_for_each (&model->polygon_list, model_constrain_polygon, model); + model_for_each_anchor (model, model_constrain_anchor, model); + model_for_each_string (model, model_constrain_string, model); + model_for_each_spacer (model, model_constrain_spacer, model); + model_for_each_stick (model, model_constrain_stick, model); + model_for_each_offset (model, model_constrain_offset, model); + model_for_each_polygon (model, model_constrain_polygon, model); } void @@ -78,6 +78,7 @@ struct _Spring { struct _OffsetSpring { Object *a, *b; int dx, dy; + Link link; }; struct _Spacer { @@ -109,25 +110,7 @@ struct _Model { List anchor_list; List polygon_list; List offset_list; - - int num_objects; - Object *objects; - int num_sticks; - Stick *sticks; - int num_strings; - String *strings; - int num_offsets; - Offset *offsets; - int num_springs; - Spring *springs; - int num_offset_springs; - OffsetSpring *offset_springs; - int num_spacers; - Spacer *spacers; - int num_anchors; - Anchor *anchors; - int num_polygons; - Polygon *polygons; + List offset_spring_list; double k; double friction; @@ -138,7 +121,7 @@ struct _Model { double theta; }; -typedef void (*ObjectFunc) (Object *element, void *data); +typedef void (*ObjectFunc) (Object *object, void *data); void object_init (Object *object, double x, double y, double mass); void offset_spring_init (OffsetSpring *spring, @@ -162,14 +145,46 @@ void model_fini (Model *model); Object *model_add_object (Model *model, double x, double y, double mass, void *data); void model_for_each_object (Model *model, ObjectFunc func, void *data); +typedef void (*SpacerFunc) (Spacer *spacer, void *data); Spacer *model_add_spacer (Model *model, Object *a, Object *b, double length); +void model_for_each_spacer (Model *model, SpacerFunc func, void *data); + +typedef void (*SpringFunc) (Spring *spring, void *data); Spring *model_add_spring (Model *model, Object *a, Object *b, double length); +void model_for_each_spring (Model *model, SpringFunc func, void *data); + +typedef void (*StickFunc) (Stick *stick, void *data); Stick *model_add_stick (Model *model, Object *a, Object *b, double length); +void model_for_each_stick (Model *model, StickFunc func, void *data); + +typedef void (*StringFunc) (String *string, void *data); String *model_add_string (Model *model, Object *a, Object *b, double length); +void model_for_each_string (Model *model, StringFunc func, void *data); + +typedef void (*AnchorFunc) (Anchor *anchor, void *data); Anchor *model_add_anchor (Model *model, Object *object, double x, double y); +void model_delete_anchor (Model *model, Anchor *anchor); +void model_for_each_anchor (Model *model, AnchorFunc func, void *data); + +typedef void (*PolygonFunc) (Polygon *polygon, void *data); Polygon *model_add_polygon (Model *model, int enclosing, int num_points, ...); +Polygon *model_add_diamond (Model *model, double x, double y); +Polygon *model_add_rectangle (Model *model, double x0, double y0, + double x1, double y1); Polygon *model_add_enclosing_rectangle (Model *model, double x0, double y0, double x1, double y1); +void model_for_each_polygon (Model *model, PolygonFunc func, void *data); + +typedef void (*OffsetSpringFunc) (OffsetSpring *spring, void *data); +OffsetSpring *model_add_offset_spring (Model *model, Object *a, Object *b, + double dx, double dy); +void model_for_each_offset_spring (Model *model, + OffsetSpringFunc func, void *data); + +typedef void (*OffsetFunc) (Offset *offset, void *data); +Offset *model_add_offset (Model *model, + int num_objects, double dx, double dy); +void model_for_each_offset (Model *model, OffsetFunc func, void *data); void model_step (Model *model, double delta_t); @@ -20,61 +20,50 @@ static void model_init_constants (Model *model) { model->elasticity = 0.7; - model->friction = 8; + model->friction = 10; model->gravity.x = 0; - model->gravity.y = 50; - model->k = 0.1; - model->constrain_iterations = 20; + model->gravity.y = 80; + model->k = 10; + model->constrain_iterations = 10; } static void model_init_polygons (Model *model) { - const int num_polygons = 5; const double ground_level = 500; - model->polygons = g_new (Polygon, num_polygons); - polygon_init_diamond (&model->polygons[0], 250, 300); - polygon_init_diamond (&model->polygons[1], 400, 150); - polygon_init_rectangle (&model->polygons[2], -100, 200, 200, 250); - polygon_init_rectangle (&model->polygons[3], -200, ground_level, - 1200, ground_level + 400); - - polygon_init_rectangle (&model->polygons[4], 300, 320, 400, 350); - - model->num_polygons = num_polygons; + model_add_diamond (model, 250, 300); + model_add_diamond (model, 400, 150); + model_add_rectangle (model, -100, 200, 200, 250); + model_add_rectangle (model, -200, ground_level, 1200, ground_level + 400); + model_add_rectangle (model, 300, 320, 400, 350); } static void model_init_snake (Model *model) { const int num_objects = 20; - const int num_sticks = num_objects * 2 - 3; + Object *object, *prev, *pprev; int i; - memset (model, 0, sizeof *model); - model->objects = g_new (Object, num_objects); - model->num_objects = num_objects; - model->sticks = g_new (Stick, num_sticks); - model->num_sticks = num_sticks; - + model_init (model); model_init_constants (model); model_init_polygons (model); + prev = NULL; + pprev = NULL; for (i = 0; i < num_objects; i++) { - object_init (&model->objects[i], - random() % 200 + 20, random() % 200 + 20, 1); + object = model_add_object (model, + g_random_int_range (100, 300), + g_random_int_range (100, 300), 1, NULL); - if (i + 1 < num_objects) { - model->sticks[i * 2].a = &model->objects[i]; - model->sticks[i * 2].b = &model->objects[i + 1]; - model->sticks[i * 2].length = random() % 20 + 20; - } - if (i + 2 < num_objects) { - model->sticks[i * 2 + 1].a = &model->objects[i]; - model->sticks[i * 2 + 1].b = &model->objects[i + 2]; - model->sticks[i * 2 + 1].length = random() % 20 + 20; - } + if (pprev != NULL) + model_add_stick (model, object, pprev, g_random_int_range (20, 40)); + if (prev != NULL) + model_add_stick (model, object, prev, g_random_int_range (20, 40)); + + pprev = prev; + prev = object; } } @@ -102,126 +91,98 @@ model_init_curtain (Model *model) { const int num_ropes = 5; const int num_rope_objects = 15; - const int num_objects = num_ropes * num_rope_objects; - const int num_sticks = num_ropes * (num_rope_objects - 1); const int stick_length = 10; const int rope_offset = 30; + Offset *offset; + Object *prev, *object; double x, y; - int i, j, index, stick_index; + int i, j; model_init (model); - model->objects = g_new (Object, num_objects); - model->num_objects = num_objects; - model->sticks = g_new (Stick, num_sticks); - model->num_sticks = num_sticks; - model->offsets = g_new (Offset, 1); - model->num_offsets = 1; - model_init_constants (model); 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; - y = 40 + j * stick_length; - index = i * num_rope_objects + j; - object_init (&model->objects[index], x, y, 1); - - if (j + 1 < num_rope_objects) { - stick_index = i * (num_rope_objects - 1) + j; - model->sticks[stick_index].a = &model->objects[index]; - model->sticks[stick_index].b = &model->objects[index + 1]; - model->sticks[stick_index].length = stick_length; - } + offset = model_add_offset (model, num_ropes, rope_offset, 0); + + for (i = 0; i < num_ropes; i++) + { + prev = NULL; + for (j = 0; j < num_rope_objects; j++) + { + x = 200 + i * rope_offset; + y = 40 + j * stick_length; + object = model_add_object (model, x, y, 1, NULL); + if (j == 0) + offset->objects[i] = object; + else + model_add_stick (model, prev, object, stick_length); + prev = object; + } } - - model->offsets[0].objects[i] = &model->objects[i * num_rope_objects]; - } } static void model_init_grid (Model *model) { - const int num_ropes = 8; - const int num_rope_objects = 8; - const int num_objects = num_ropes * num_rope_objects; - const int num_strings = num_ropes * (num_rope_objects - 1) + - (num_ropes - 1) * num_rope_objects; - const int string_length = 20; - const int rope_offset = 20; - Object *object; - String *string; + const int width = 8, height = 8; + const int distance = 20; + Offset *offset; + Object *last_column[height], *object; int i, j; - memset (model, 0, sizeof *model); - model->objects = g_new (Object, num_objects); - model->num_objects = num_objects; - model->strings = g_new (String, num_strings); - model->num_strings = num_strings; - model->offsets = g_new (Offset, 1); - model->num_offsets = 1; - + model_init (model); model_init_constants (model); 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; - - object = model->objects; - string = model->strings; - for (i = 0; i < num_ropes; i++) { - for (j = 0; j < num_rope_objects; j++) { - object_init (object, 200 + i * rope_offset, 40 + j * string_length, 1); - - if (i + 1 < num_ropes) - string_init (string++, - object, object + num_rope_objects, string_length); - if (j + 1 < num_rope_objects) - string_init (string++, object, object + 1, string_length); - object++; + offset = model_add_offset (model, width, distance, 0); + + for (i = 0; i < width; i++) + { + for (j = 0; j < height; j++) + { + object = model_add_object (model, + 200 + i * distance, + 40 + j * distance, 1, NULL); + + if (i > 0) + model_add_string (model, + last_column[j], object, distance); + if (j == 0) + offset->objects[i] = object; + else + model_add_string (model, + last_column[j - 1], object, distance); + last_column[j] = object; + } } - - model->offsets[0].objects[i] = &model->objects[i * num_rope_objects]; - } } static void model_init_molecule (Model *model) { const int num_objects = 8; - const int num_springs = num_objects * 2; const int spring_length = 50; + Object *objects[num_objects]; int i; - Spring *spring; - - memset (model, 0, sizeof *model); - model->objects = g_new (Object, num_objects); - model->num_objects = num_objects; - model->springs = g_new (Spring, num_springs); - model->num_springs = num_springs; - model->k = 2; + model_init (model); model_init_constants (model); for (i = 0; i < num_objects; i++) - object_init (&model->objects[i], 200 + i * 20, 200, 0); + objects[i] = model_add_object (model, + g_random_int_range (200, 400), + g_random_int_range (200, 400), + 0, NULL); - spring = model->springs; - for (i = 0; i < num_objects; i++) { - spring_init (spring++, &model->objects[i], - &model->objects[(i + 1) % num_objects], - spring_length); - spring_init (spring++, &model->objects[i], - &model->objects[(i + 2) % num_objects], - spring_length); - } + for (i = 0; i < num_objects; i++) + { + model_add_spring (model, + objects[i], objects[(i + 1) % num_objects], + spring_length); + model_add_spring (model, + objects[i], objects[(i + 2) % num_objects], + spring_length); + } } @@ -229,249 +190,141 @@ static void model_init_wobbly (Model *model) { const int width = 8, height = 8; - const int num_objects = width * height; - const int num_offset_springs = (width - 1) * height + width * (height - 1); const int distance = 30; double x, y; int i, j; - Object *object; - OffsetSpring *spring; - - memset (model, 0, sizeof *model); - model->objects = g_new (Object, num_objects); - model->num_objects = num_objects; - model->offset_springs = g_new (OffsetSpring, num_offset_springs); - model->num_offset_springs = num_offset_springs; - model->k = 4.5; + Object *object, *last_column[height]; + model_init (model); model_init_constants (model); model_init_polygons (model); - object = model->objects; - spring = model->offset_springs; - for (i = 0; i < width; i++) { - for (j = 0; j < height; j++) { - x = 200 + i * distance; - y = 40 + j * distance; - object_init (object, x, y, 0); - - if (i + 1 < width) - offset_spring_init (spring++, object, object + height, distance, 0); - - if (j + 1 < height) - offset_spring_init (spring++, object, object + 1, 0, distance); - - object++; - } + for (i = 0; i < width; i++) + { + for (j = 0; j < height; j++) + { + x = 200 + i * distance; + y = 40 + j * distance; + object = model_add_object (model, x, y, 0, NULL); + if (i > 0) + model_add_offset_spring (model, last_column[j], object, + distance, 0); + if (j > 0) + model_add_offset_spring (model, last_column[j - 1], object, + 0, distance); + last_column[j] = object; + } } } +typedef struct { + Model *model; + Object *current; + Object *anchor; + int distance; +} DockInitClosure; + static void -model_init_dock (Model *model) +dock_add_spacer (Object *object, void *data) { - const int num_objects = 8; - const int num_spacers = (num_objects - 1) * (num_objects - 2) / 2; - const int num_springs = num_objects - 1; - const int distance = 30; - double x, y; - int i, j; - Object *object; - Spring *spring; - Spacer *spacer; - - memset (model, 0, sizeof *model); - model->objects = g_new (Object, num_objects); - model->num_objects = num_objects; - model->springs = g_new (Spring, num_springs); - model->num_springs = num_springs; - model->spacers = g_new (Spacer, num_spacers); - model->num_spacers = num_spacers; - model->anchors = g_new (Anchor, 1); - model->num_anchors = 1; - model->k = 0.1; + DockInitClosure *closure = data; - model_init_constants (model); - model->polygons = g_new (Polygon, 1); - model->num_polygons = 1; - polygon_init_enclosing_rectangle (&model->polygons[0], 10, 10, 700, 500); - - model->anchors[0].x = 300; - model->anchors[0].y = 300; - model->anchors[0].object = &model->objects[0]; - - object = model->objects; - spring = model->springs; - spacer = model->spacers; - for (i = 0; i < num_objects; i++, object++) { - x = 200 + i * distance / 3; - y = 40; - object_init (object, x, y, 1); - if (i == 0) - continue; - spring_init (spring++, - &model->objects[0], - &model->objects[i], - distance); - for (j = 1; j < num_objects - i; j++) { - spacer_init (spacer++, object, object + j, distance); - } - } + /* Skip the anchor object. */ + if (object != closure->anchor && object != closure->current) + model_add_spacer (closure->model, + object, closure->current, closure->distance); } -typedef struct _Color Color; -struct _Color { - double red, green, blue; -}; - static void -draw_sticks (cairo_t *cr, - Model *model, - Color *color) +model_init_dock (Model *model) { + const int num_objects = 8; + const int distance = 30; + DockInitClosure closure; int i; - cairo_set_source_rgba (cr, color->red, color->green, color->blue, 1); - cairo_new_path (cr); - cairo_set_line_width (cr, 2); - cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND); - cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND); + model_init (model); + model_init_constants (model); + model_add_enclosing_rectangle (model, 10, 10, 700, 500); - for (i = 0; i < model->num_sticks; i++) { - cairo_move_to (cr, - model->sticks[i].a->position.x, - model->sticks[i].a->position.y); - cairo_line_to (cr, - model->sticks[i].b->position.x, - model->sticks[i].b->position.y); - } + closure.anchor = model_add_object (model, 0, 0, 0, NULL); + model_add_anchor (model, closure.anchor, 300, 300); - cairo_stroke (cr); + closure.model = model; + closure.distance = distance; + for (i = 0; i < num_objects; i++) { + closure.current = + model_add_object (model, 200 + i * distance / 3, 40, 2, NULL); + model_add_spring (model, closure.anchor, closure.current, distance); + model_for_each_object (model, dock_add_spacer, &closure); + } } static void -draw_strings (cairo_t *cr, - Model *model, - Color *color) +draw_stick (Stick *stick, void *data) { - int i; - - cairo_set_source_rgba (cr, color->red, color->green, color->blue, 1); - cairo_new_path (cr); - cairo_set_line_width (cr, 1); - cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND); - cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND); - - for (i = 0; i < model->num_strings; i++) { - cairo_move_to (cr, - model->strings[i].a->position.x, - model->strings[i].a->position.y); - cairo_line_to (cr, - model->strings[i].b->position.x, - model->strings[i].b->position.y); - } + cairo_t *cr = data; - cairo_stroke (cr); + cairo_move_to (cr, stick->a->position.x, stick->a->position.y); + cairo_line_to (cr, stick->b->position.x, stick->b->position.y); } static void -draw_offsets (cairo_t *cr, - Model *model, - Color *color) +draw_string (String *string, void *data) { - int i, j; - - cairo_set_source_rgba (cr, color->red, color->green, color->blue, 0.5); - cairo_new_path (cr); - cairo_set_line_width (cr, 4); - cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND); - cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND); - - for (i = 0; i < model->num_offsets; i++) { - 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_t *cr = data; + cairo_move_to (cr, string->a->position.x, string->a->position.y); + cairo_line_to (cr, string->b->position.x, string->b->position.y); } static void -draw_springs (cairo_t *cr, - Model *model, - Color *color) +draw_offset (Offset *offset, void *data) { + cairo_t *cr = data; int i; - cairo_set_source_rgba (cr, color->red, color->green, color->blue, 0.4); - cairo_new_path (cr); - cairo_set_line_width (cr, 2); - cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND); - cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND); - - for (i = 0; i < model->num_springs; i++) { - cairo_move_to (cr, - model->springs[i].a->position.x, - model->springs[i].a->position.y); + cairo_move_to (cr, + offset->objects[0]->position.x, + offset->objects[0]->position.y); + for (i = 1; i < offset->num_objects; i++) cairo_line_to (cr, - model->springs[i].b->position.x, - model->springs[i].b->position.y); - } - - cairo_stroke (cr); + offset->objects[i]->position.x, + offset->objects[i]->position.y); } static void -draw_offset_springs (cairo_t *cr, - Model *model, - Color *color) +draw_spring (Spring *spring, void *data) { - int i; - - cairo_set_source_rgba (cr, color->red, color->green, color->blue, 0.4); - cairo_new_path (cr); - cairo_set_line_width (cr, 2); - cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND); - cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND); - - for (i = 0; i < model->num_offset_springs; i++) { - cairo_move_to (cr, - model->offset_springs[i].a->position.x, - model->offset_springs[i].a->position.y); - cairo_line_to (cr, - model->offset_springs[i].b->position.x, - model->offset_springs[i].b->position.y); - } + cairo_t *cr = data; - cairo_stroke (cr); + cairo_move_to (cr, spring->a->position.x, spring->a->position.y); + cairo_line_to (cr, spring->b->position.x, spring->b->position.y); } static void -draw_polygons (cairo_t *cr, Model *model, Color *color) +draw_offset_spring (OffsetSpring *spring, void *data) { - Polygon *p; - int i, j; + cairo_t *cr = data; - for (i = 0; i < model->num_polygons; i++) { - p = &model->polygons[i]; - - for (j = 0; j < p->num_points; j++) - cairo_line_to (cr, p->points[j].x, p->points[j].y); - cairo_close_path (cr); + cairo_move_to (cr, spring->a->position.x, spring->a->position.y); + cairo_line_to (cr, spring->b->position.x, spring->b->position.y); +} - if (p->enclosing) { - cairo_set_source_rgba (cr, color->red, color->green, color->blue, 0.1); - cairo_fill_preserve (cr); - } +static void +draw_polygon (Polygon *polygon, void *data) +{ + cairo_t *cr = data; + int i; - cairo_set_source_rgba (cr, color->red, color->green, color->blue, 0.4); - if (p->enclosing) - cairo_stroke (cr); - else - cairo_fill (cr); - } + for (i = 0; i < polygon->num_points; i++) + cairo_line_to (cr, polygon->points[i].x, polygon->points[i].y); + cairo_close_path (cr); + if (polygon->enclosing) + cairo_stroke (cr); + else + cairo_fill (cr); } static void @@ -479,15 +332,11 @@ draw_object (Object *object, void *data) { cairo_t *cr = data; - cairo_arc (cr, object->position.x, object->position.y, 3, 0, 2 * M_PI); + cairo_arc (cr, object->position.x, object->position.y, + 3, 0, 2 * M_PI); cairo_fill (cr); } -static Color blue = { 0, 0, 1 }; -static Color green = { 0, 1, 0 }; -static Color red = { 1, 0, 0 }; -static Color black = { 0, 0, 0 }; - typedef struct _Closure Closure; struct _Closure { GtkWidget *drawing_area; @@ -509,12 +358,34 @@ draw_model (GtkWidget *widget, Model *model) cairo_set_source_rgb (cr, 1, 1, 1); cairo_paint (cr); - draw_polygons (cr, model, &blue); - draw_sticks (cr, model, &black); - draw_strings (cr, model, &green); - draw_springs (cr, model, &black); - draw_offsets (cr, model, &blue); - draw_offset_springs (cr, model, &blue); + cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND); + cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND); + + cairo_set_line_width (cr, 1); + cairo_set_source_rgba (cr, 0, 0, 0.5, 1); + model_for_each_polygon (model, draw_polygon, cr); + + cairo_set_source_rgba (cr, 0, 1, 0, 1); + model_for_each_string (model, draw_string, cr); + cairo_stroke (cr); + + cairo_set_source_rgba (cr, 0, 0, 0, 0.8); + model_for_each_spring (model, draw_spring, cr); + cairo_stroke (cr); + + cairo_set_line_width (cr, 4); + cairo_set_source_rgba (cr, 0, 0, 0.5, 0.5); + model_for_each_offset (model, draw_offset, cr); + cairo_stroke (cr); + + cairo_set_line_width (cr, 2); + cairo_set_source_rgba (cr, 0, 0, 0, 1); + model_for_each_stick (model, draw_stick, cr); + cairo_stroke (cr); + + cairo_set_source_rgba (cr, 1, 0, 1, 0.4); + model_for_each_offset_spring (model, draw_offset_spring, cr); + cairo_stroke (cr); cairo_set_source_rgba (cr, 1, 0, 0, 0.4); model_for_each_object (model, draw_object, cr); @@ -540,14 +411,14 @@ button_press_event (GtkWidget *widget, gpointer data) { Closure *closure = data; + Object *object; if (event->button != 1) return TRUE; - closure->mouse_anchor->x = event->x; - closure->mouse_anchor->y = event->y; - closure->mouse_anchor->object = - model_find_nearest (closure->model, event->x, event->y); + object = model_find_nearest (closure->model, event->x, event->y); + closure->mouse_anchor = + model_add_anchor (closure->model, object, event->x, event->y); return TRUE; } @@ -562,7 +433,8 @@ button_release_event (GtkWidget *widget, if ((event->state & GDK_BUTTON1_MASK) == 0) return TRUE; - closure->mouse_anchor->object = NULL; + model_delete_anchor (closure->model, closure->mouse_anchor); + closure->mouse_anchor = NULL; return TRUE; } @@ -578,8 +450,11 @@ motion_notify_event (GtkWidget *widget, gdk_window_get_pointer (event->window, &x, &y, &state); - closure->mouse_anchor->x = x + 0.5; - closure->mouse_anchor->y = y + 0.5; + if (closure->mouse_anchor != NULL) + { + closure->mouse_anchor->x = x + 0.5; + closure->mouse_anchor->y = y + 0.5; + } return TRUE; } @@ -791,7 +666,7 @@ main (int argc, char *argv[]) create_window (&closure); closure.i = 0; closure.model = &model; - closure.mouse_anchor = model_add_anchor (&model, NULL, 0, 0); + closure.mouse_anchor = NULL; closure.frame_count = 0; gettimeofday (&closure.start, NULL); g_timeout_add (40, timeout_callback, &closure); |