X-Git-Url: https://git.cworth.org/git?a=blobdiff_plain;f=akamaru.c;h=c667c371fade45e09ca49cdd274e177723dc9e1d;hb=5443c3705048a110ece3acd77d0ecb1b5bf3619d;hp=8dc477cc0f2ee4b7c10edb92f2828ef2102a2333;hpb=9bdb07522bfbb2611a7e70f1204d96b98bc0e615;p=akamaru diff --git a/akamaru.c b/akamaru.c index 8dc477c..c667c37 100644 --- a/akamaru.c +++ b/akamaru.c @@ -12,21 +12,80 @@ * corrections at the end instead of meaning as it goes. */ -#include -#include -#include -#include +#include #include #include -#include +#include #include #include "akamaru.h" const double elasticity = 0.7; +const double friction = 4; +const double gravity = 50; void -polygon_init (Polygon *p, int num_points, ...) +object_init (Object *object, double x, double y, double mass) +{ + object->position.x = x; + object->position.y = y; + object->previous_position.x = x; + object->previous_position.y = y; + object->mass = mass; +} + +void +spring_init (Spring *spring, Object *a, Object *b, double length) +{ + spring->a = a; + spring->b = b; + spring->length = length; +} + +void +stick_init (Stick *stick, Object *a, Object *b, double length) +{ + stick->a = a; + stick->b = b; + stick->length = length; +} + +void +string_init (String *string, Object *a, Object *b, double length) +{ + string->a = a; + string->b = b; + string->length = length; +} + +void +offset_spring_init (OffsetSpring *spring, Object *a, Object *b, + double dx, double dy) +{ + spring->a = a; + spring->b = b; + spring->dx = dx; + spring->dy = dy; +} + +void +spacer_init (Spacer *spacer, Object *a, Object *b, double length) +{ + spacer->a = a; + spacer->b = b; + spacer->length = length; +} + +void +anchor_init (Anchor *anchor, Object *object, double x, double y) +{ + anchor->object = object; + anchor->x = x; + anchor->y = y; +} + +void +polygon_init (Polygon *p, int enclosing, int num_points, ...) { double dx, dy, length; int i, j; @@ -38,6 +97,7 @@ polygon_init (Polygon *p, int num_points, ...) va_start (ap, num_points); p->num_points = num_points; p->points = g_new (Point, num_points); + p->enclosing = enclosing; for (i = 0; i < num_points; i++) { p->points[i].x = va_arg (ap, double); @@ -48,7 +108,7 @@ polygon_init (Polygon *p, int num_points, ...) p->normals = g_new (Vector, p->num_points); /* Compute outward pointing normals. p->normals[i] is the normal * for the edged between p->points[i] and p->points[i + 1]. */ - for (i = 0; i < p->num_points; i++) { + for (i = 0; i < p->num_points; i++) { j = (i + 1) % p->num_points; dx = p->points[j].x - p->points[i].x; dy = p->points[j].y - p->points[i].y; @@ -61,7 +121,7 @@ polygon_init (Polygon *p, int num_points, ...) void polygon_init_diamond (Polygon *polygon, double x, double y) { - return polygon_init (polygon, 5, + return polygon_init (polygon, FALSE, 5, x, y, x + 10, y + 40, x + 90, y + 40, @@ -73,7 +133,14 @@ void polygon_init_rectangle (Polygon *polygon, double x0, double y0, double x1, double y1) { - return polygon_init (polygon, 4, x0, y0, x0, y1, x1, y1, x1, y0); + return polygon_init (polygon, FALSE, 4, x0, y0, x0, y1, x1, y1, x1, y0); +} + +void +polygon_init_enclosing_rectangle (Polygon *polygon, double x0, double y0, + double x1, double y1) +{ + return polygon_init (polygon, TRUE, 4, x0, y0, x0, y1, x1, y1, x1, y0); } void @@ -88,6 +155,7 @@ model_fini (Model *model) 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); @@ -101,11 +169,18 @@ model_accumulate_forces (Model *model) int i; double x, y, dx, dy, distance, displacement; Point middle; - Vector u; + Vector u, v; for (i = 0; i < model->num_objects; i++) { + /* Gravity */ model->objects[i].force.x = 0; - model->objects[i].force.y = 3 * model->objects[i].mass; + model->objects[i].force.y = 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 * friction; + model->objects[i].force.y -= v.y * friction; } for (i = 0; i < model->num_springs; i++) { @@ -142,6 +217,15 @@ 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 @@ -157,9 +241,9 @@ model_integrate (Model *model, double step) y = o->position.y; o->position.x = - x + 0.9 * (x - o->previous_position.x) + o->force.x * step * step; + x + (x - o->previous_position.x) + o->force.x * step * step; o->position.y = - y + 0.9 * (y - o->previous_position.y) + o->force.y * step * step; + y + (y - o->previous_position.y) + o->force.y * step * step; o->previous_position.x = x; o->previous_position.y = y; @@ -200,10 +284,10 @@ polygon_contains_point (Polygon *polygon, Point *point) dy = point->y - polygon->points[i].y; if (polygon->normals[i].x * dx + polygon->normals[i].y * dy >= 0) - return FALSE; + return polygon->enclosing; } - return TRUE; + return !polygon->enclosing; } static void @@ -221,7 +305,6 @@ polygon_reflect_object (Polygon *polygon, Object *object) if (d > distance) { distance = d; edge = i; - polygon->edge = i; n = &polygon->normals[i]; } } @@ -248,6 +331,15 @@ model_constrain_polygon (Model *model, Polygon *polygon) } } +static void +model_constrain_anchor (Model *model, Anchor *anchor) +{ + anchor->object->position.x = anchor->x; + anchor->object->position.y = anchor->y; + anchor->object->previous_position.x = anchor->x; + anchor->object->previous_position.y = anchor->y; +} + static void model_constrain_offset (Model *model, Offset *offset) { @@ -276,13 +368,10 @@ model_constrain (Model *model) double dx, dy, x, y, distance, fraction; int i; - /* Anchor object constraint. */ - if (model->anchor_object != NULL) { - model->anchor_object->position.x = model->anchor_position.x; - model->anchor_object->position.y = model->anchor_position.y; - model->anchor_object->previous_position.x = model->anchor_position.x; - model->anchor_object->previous_position.y = model->anchor_position.y; - } + if (model->mouse_anchor.object != NULL) + model_constrain_anchor (model, &model->mouse_anchor); + for (i = 0; i < model->num_anchors; i++) + model_constrain_anchor (model, &model->anchors[i]); /* String constraints. */ for (i = 0; i < model->num_strings; i++) { @@ -300,6 +389,22 @@ model_constrain (Model *model) model->strings[i].b->position.y = y + dy * (1 - fraction); } + /* 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); + } + /* Stick constraints. */ for (i = 0; i < model->num_sticks; i++) { x = model->sticks[i].a->position.x; @@ -330,8 +435,7 @@ model_step (Model *model, double delta_t) model_accumulate_forces (model); model_integrate (model, delta_t); - - for (i = 0; i < 50; i++) + for (i = 0; i < 20; i++) model_constrain (model); model->theta += delta_t;