summaryrefslogtreecommitdiff
path: root/akamaru.c
diff options
context:
space:
mode:
authorKristian Høgsberg <krh@redhat.com>2006-07-05 03:19:32 -0400
committerKristian Høgsberg <krh@redhat.com>2006-07-05 03:19:32 -0400
commit9ad6f0b348f59520b427fa383aa85f42a430a11b (patch)
tree83b567794f85f719c98645a9f1fb42e45b99a6d3 /akamaru.c
parent395c1747a3e3133808b565942f15570c731c54d6 (diff)
First steps towards making the akamaru model dynamic.
Diffstat (limited to 'akamaru.c')
-rw-r--r--akamaru.c291
1 files changed, 213 insertions, 78 deletions
diff --git a/akamaru.c b/akamaru.c
index 9e5f8b8..c75a110 100644
--- a/akamaru.c
+++ b/akamaru.c
@@ -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);