diff options
author | Kristian Høgsberg <krh@redhat.com> | 2006-07-05 03:19:32 -0400 |
---|---|---|
committer | Kristian Høgsberg <krh@redhat.com> | 2006-07-05 03:19:32 -0400 |
commit | 9ad6f0b348f59520b427fa383aa85f42a430a11b (patch) | |
tree | 83b567794f85f719c98645a9f1fb42e45b99a6d3 /akamaru.c | |
parent | 395c1747a3e3133808b565942f15570c731c54d6 (diff) |
First steps towards making the akamaru model dynamic.
Diffstat (limited to 'akamaru.c')
-rw-r--r-- | akamaru.c | 291 |
1 files changed, 213 insertions, 78 deletions
@@ -21,6 +21,54 @@ #include "akamaru.h" +static void +link_init (Link *link) +{ + link->prev = link; + link->next = link; +} + +static void +link_insert_before (Link *link, Link *anchor) +{ + link->prev = anchor->prev; + link->next = anchor; + link->prev->next = link; + link->next->prev = link; +} + +static void +link_remove (Link *link) +{ + link->prev->next = link->next; + link->next->prev = link->prev; +} + +static void +list_init (List *list, size_t offset) +{ + link_init (&list->head); + list->offset = offset; +} + +static void +list_for_each (List *list, ListFunc func, void *data) +{ + Link *l; + + for (l = list->head.next; l != &list->head; l = l->next) + func ((char *) l - list->offset, data); +} + +static void +list_append (List *list, void *element) +{ + Link *link; + + link = (Link *) ((char *) element + list->offset); + link_insert_before (link, &list->head); +} + void object_init (Object *object, double x, double y, double mass) { @@ -39,6 +87,20 @@ spring_init (Spring *spring, Object *a, Object *b, double length) spring->length = length; } +Spring * +model_add_spring (Model *model, Object *a, Object *b, double length) +{ + Spring *spring; + + spring = g_new (Spring, 1); + spring->a = a; + spring->b = b; + spring->length = length; + list_append (&model->spring_list, spring); + + return spring; +} + void stick_init (Stick *stick, Object *a, Object *b, double length) { @@ -73,6 +135,20 @@ spacer_init (Spacer *spacer, Object *a, Object *b, double length) spacer->length = length; } +Spacer * +model_add_spacer (Model *model, Object *a, Object *b, double length) +{ + Spacer *spacer; + + spacer = g_new (Spacer, 1); + spacer->a = a; + spacer->b = b; + spacer->length = length; + list_append (&model->spacer_list, spacer); + + return spacer; +} + void anchor_init (Anchor *anchor, Object *object, double x, double y) { @@ -141,6 +217,38 @@ polygon_init_enclosing_rectangle (Polygon *polygon, double x0, double y0, } 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)); +} + +Object * +model_add_object (Model *model, double x, double y, double mass, void *data) +{ + Object *object; + + object = g_new (Object, 1); + object->position.x = x; + object->position.y = y; + object->previous_position.x = x; + object->previous_position.y = y; + object->mass = mass; + list_append (&model->object_list, object); + object->data = data; + + return object; +} + +void +model_for_each_object (Model *model, ObjectFunc func, void *data) +{ + list_for_each (&model->object_list, (ListFunc) func, data); +} + +void model_fini (Model *model) { int i; @@ -161,46 +269,61 @@ model_fini (Model *model) } static void +object_accumulate_forces (Object *object, void *data) +{ + Model *model = data; + Vector v; + + /* Gravity */ + object->force.x = 0; + object->force.y = model->gravity * object->mass; + + /* Friction */ + v.x = object->position.x - object->previous_position.x; + v.y = object->position.y - object->previous_position.y; + object->force.x -= v.x * model->friction; + object->force.y -= v.y * model->friction; +} + +static void +spring_accumulate_forces (void *element, void *data) +{ + Spring *spring = element; + Model *model = data; + double x, y, dx, dy, distance, displacement; + Vector u; + + x = spring->a->position.x; + y = spring->a->position.y; + dx = spring->b->position.x - x; + dy = spring->b->position.y - y; + distance = sqrt (dx * dx + dy * dy); + u.x = dx / distance; + u.y = dy / distance; + displacement = distance - spring->length; + spring->a->force.x += u.x * model->k * displacement; + spring->a->force.y += u.y * model->k * displacement; + spring->b->force.x -= u.x * model->k * displacement; + spring->b->force.y -= u.y * model->k * displacement; +} + +static void model_accumulate_forces (Model *model) { int i; - double x, y, dx, dy, distance, displacement; + double x, y, dx, dy; Point middle; - Vector u, v; - for (i = 0; i < model->num_objects; i++) { - /* Gravity */ - model->objects[i].force.x = 0; - model->objects[i].force.y = model->gravity * model->objects[i].mass; - - /* Friction */ - v.x = model->objects[i].position.x - model->objects[i].previous_position.x; - v.y = model->objects[i].position.y - model->objects[i].previous_position.y; - model->objects[i].force.x -= v.x * model->friction; - model->objects[i].force.y -= v.y * model->friction; - } + model_for_each_object (model, object_accumulate_forces, model); - for (i = 0; i < model->num_springs; i++) { - x = model->springs[i].a->position.x; - y = model->springs[i].a->position.y; - dx = model->springs[i].b->position.x - x; - dy = model->springs[i].b->position.y - y; - distance = sqrt (dx * dx + dy * dy); - u.x = dx / distance; - u.y = dy / distance; - displacement = distance - model->springs[i].length; - model->springs[i].a->force.x += u.x * model->k * displacement; - model->springs[i].a->force.y += u.y * model->k * displacement; - model->springs[i].b->force.x -= u.x * model->k * displacement; - model->springs[i].b->force.y -= u.y * model->k * displacement; - } + list_for_each (&model->spring_list, spring_accumulate_forces, model); for (i = 0; i < model->num_offset_springs; i++) { - middle.x = - (model->offset_springs[i].a->position.x + + 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 + + middle.y = + (model->offset_springs[i].a->position.y + model->offset_springs[i].b->position.y) / 2; x = middle.x - model->offset_springs[i].dx / 2; @@ -214,37 +337,24 @@ model_accumulate_forces (Model *model) model->offset_springs[i].b->force.x -= dx * model->k; model->offset_springs[i].b->force.y -= dy * model->k; } - - for (i = 0; i < model->num_objects; i++) { - double f = - model->objects[i].force.x * model->objects[i].force.x + - model->objects[i].force.y * model->objects[i].force.y; - - if (f > 100000000) - abort(); - } } static void -model_integrate (Model *model, double step) +object_integrate (Object *object, void *data) { - double x, y; - Object *o; - int i; + double x, y, step; - for (i = 0; i < model->num_objects; i++) { - o = &model->objects[i]; - x = o->position.x; - y = o->position.y; - - o->position.x = - x + (x - o->previous_position.x) + o->force.x * step * step; - o->position.y = - y + (y - o->previous_position.y) + o->force.y * step * step; - - o->previous_position.x = x; - o->previous_position.y = y; - } + step = * (double *) data; + x = object->position.x; + y = object->position.y; + + object->position.x = + x + (x - object->previous_position.x) + object->force.x * step * step; + object->position.y = + y + (y - object->previous_position.y) + object->force.y * step * step; + + object->previous_position.x = x; + object->previous_position.y = y; } /* The square root in the distance computation for the string and @@ -317,15 +427,30 @@ polygon_reflect_object (Polygon *polygon, Object *object, double elasticity) object->previous_position.y -= (1 + elasticity) * distance * n->y; } +typedef struct _ObjectConstrainPolygonClosure { + Model *model; + Polygon *polygon; +} ObjectConstrainPolygonClosure; + +static void +object_constrain_polygon (Object *object, void *data) +{ + ObjectConstrainPolygonClosure *closure = data; + + if (polygon_contains_point (closure->polygon, &object->position)) + polygon_reflect_object (closure->polygon, object, + closure->model->elasticity); +} + static void model_constrain_polygon (Model *model, Polygon *polygon) { - int i; + ObjectConstrainPolygonClosure closure; - for (i = 0; i < model->num_objects; i++) { - if (polygon_contains_point (polygon, &model->objects[i].position)) - polygon_reflect_object (polygon, &model->objects[i], model->elasticity); - } + closure.model = model; + closure.polygon = polygon; + + model_for_each_object (model, object_constrain_polygon, &closure); } static void @@ -352,7 +477,7 @@ model_constrain_offset (Model *model, Offset *offset) 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; @@ -360,6 +485,29 @@ model_constrain_offset (Model *model, Offset *offset) } static void +model_constrain_spacer (void *element, void *data) +{ + Spacer *spacer = element; + double x, y, dx, dy, distance, fraction; + + x = spacer->a->position.x; + y = spacer->a->position.y; + dx = spacer->b->position.x - x; + dy = spacer->b->position.y - y; + + distance = estimate_distance (dx, dy, spacer->length); + if (distance > spacer->length) + return; + + fraction = (distance - spacer->length) / distance / 2; + spacer->a->position.x = x + dx * fraction; + spacer->a->position.y = y + dy * fraction; + spacer->b->position.x = x + dx * (1 - fraction); + spacer->b->position.y = y + dy * (1 - fraction); +} + + +static void model_constrain (Model *model) { double dx, dy, x, y, distance, fraction; @@ -387,20 +535,7 @@ model_constrain (Model *model) } /* Spacer constraints. */ - for (i = 0; i < model->num_spacers; i++) { - x = model->spacers[i].a->position.x; - y = model->spacers[i].a->position.y; - dx = model->spacers[i].b->position.x - x; - dy = model->spacers[i].b->position.y - y; - distance = estimate_distance (dx, dy, model->spacers[i].length); - if (distance > model->spacers[i].length) - continue; - fraction = (distance - model->spacers[i].length) / distance / 2; - model->spacers[i].a->position.x = x + dx * fraction; - model->spacers[i].a->position.y = y + dy * fraction; - model->spacers[i].b->position.x = x + dx * (1 - fraction); - model->spacers[i].b->position.y = y + dy * (1 - fraction); - } + list_for_each (&model->spacer_list, model_constrain_spacer, model); /* Stick constraints. */ for (i = 0; i < model->num_sticks; i++) { @@ -431,7 +566,7 @@ model_step (Model *model, double delta_t) int i; model_accumulate_forces (model); - model_integrate (model, delta_t); + model_for_each_object (model, object_integrate, &delta_t); for (i = 0; i < model->constrain_iterations; i++) model_constrain (model); |