summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKristian Høgsberg <krh@redhat.com>2006-07-12 15:36:55 -0400
committerKristian Høgsberg <krh@redhat.com>2006-07-12 15:36:55 -0400
commit1df47d291542a5afd474a31e7df2066cfd92b08d (patch)
tree7fd52c7cfed8a375d460bc05f92431a239af2ab3
parent6fc8f83a50b04d40ebd38e79f1954b8f05889255 (diff)
Finish dynamic model rewrite, port all of main.c over.
-rw-r--r--akamaru.c261
-rw-r--r--akamaru.h55
-rw-r--r--main.c541
3 files changed, 413 insertions, 444 deletions
diff --git a/akamaru.c b/akamaru.c
index f8c7cbb..3222c08 100644
--- a/akamaru.c
+++ b/akamaru.c
@@ -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
diff --git a/akamaru.h b/akamaru.h
index 219bd70..2f478a0 100644
--- a/akamaru.h
+++ b/akamaru.h
@@ -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);
diff --git a/main.c b/main.c
index e971805..8d41fdb 100644
--- a/main.c
+++ b/main.c
@@ -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);