typedef struct _Object Object;
typedef struct _Stick Stick;
+typedef struct _String String;
typedef struct _Offset Offset;
typedef struct _Model Model;
int length;
};
+struct _String {
+ Object *a, *b;
+ int length;
+};
+
struct _Offset {
Object *a, *b;
int dx, dy;
Object *objects;
int num_sticks;
Stick *sticks;
+ int num_strings;
+ String *strings;
int num_offsets;
Offset *offsets;
double k;
model->num_objects = num_objects;
model->sticks = g_new (Stick, num_sticks);
model->num_sticks = num_sticks;
+ model->strings = NULL;
+ model->num_strings = 0;
+ model->offsets = NULL;
model->num_offsets = 0;
for (i = 0; i < num_objects; i++) {
{
const int num_objects = 20;
const int num_sticks = num_objects - 1;
- const int stick_length = 20;
+ const int stick_length = 5;
int i;
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->strings = NULL;
+ model->num_strings = 0;
+ model->offsets = NULL;
+ model->num_offsets = 0;
for (i = 0; i < num_objects; i++) {
model->objects[i].position.x = 200;
model->num_objects = num_objects;
model->sticks = g_new (Stick, num_sticks);
model->num_sticks = num_sticks;
+ model->strings = NULL;
+ model->num_strings = 0;
model->offsets = g_new (Offset, num_ropes - 1);
model->num_offsets = num_ropes - 1;
model->anchor_object = NULL;
}
+static void
+model_init_grid (Model *model)
+{
+ const int num_ropes = 4;
+ const int num_rope_objects = 4;
+ 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 = 30;
+ const int rope_offset = 30;
+ double x, y;
+ int i, j, index, string_index;
+
+ model->objects = g_new (Object, num_objects);
+ model->num_objects = num_objects;
+ model->sticks = NULL;
+ model->num_sticks = 0;
+ model->strings = g_new (String, num_strings);
+ model->num_strings = num_strings;
+ model->offsets = g_new (Offset, num_ropes - 1);
+ model->num_offsets = num_ropes - 1;
+
+ for (i = 0; i < num_ropes; i++) {
+ for (j = 0; j < num_rope_objects; j++) {
+ x = 200 + i * rope_offset;
+ y = 40 + j * string_length;
+ index = i * num_rope_objects + j;
+ model->objects[index].position.x = x;
+ model->objects[index].position.y = y;
+ model->objects[index].previous_position.x = x;
+ model->objects[index].previous_position.y = y;
+
+ if (i + 1 < num_ropes) {
+ string_index = i * num_rope_objects + j;
+ model->strings[string_index].a = &model->objects[index];
+ model->strings[string_index].b = &model->objects[index + num_rope_objects];
+ model->strings[string_index].length = string_length;
+ }
+
+ if (j + 1 < num_rope_objects) {
+ string_index =
+ (num_ropes - 1) * num_rope_objects + i * (num_rope_objects - 1) + j;
+ model->strings[string_index].a = &model->objects[index];
+ model->strings[string_index].b = &model->objects[index + 1];
+ model->strings[string_index].length = string_length;
+ }
+ }
+
+ if (i + 1 < num_ropes) {
+ model->offsets[i].a = &model->objects[i * num_rope_objects];
+ model->offsets[i].b = &model->objects[(i + 1) * num_rope_objects];
+ model->offsets[i].dx = rope_offset;
+ model->offsets[i].dy = 0;
+ }
+ }
+
+ model->anchor_object = NULL;
+}
+
static void
model_fini (Model *model)
{
g_free (model->sticks);
model->sticks = NULL;
model->sticks = 0;
+ g_free (model->strings);
+ model->strings = NULL;
+ model->strings = 0;
g_free (model->offsets);
model->offsets = NULL;
model->num_offsets = 0;
model->offsets[i].b->position.y = y + model->offsets[i].dy / 2;
}
+ /* String constraints. */
+ for (i = 0; i < model->num_strings; i++) {
+ x = model->strings[i].a->position.x;
+ y = model->strings[i].a->position.y;
+ dx = model->strings[i].b->position.x - x;
+ dy = model->strings[i].b->position.y - y;
+ distance = sqrt (dx * dx + dy * dy);
+ if (distance < model->strings[i].length)
+ continue;
+ fraction = (distance - model->strings[i].length) / distance / 2;
+ model->strings[i].a->position.x = x + dx * fraction;
+ model->strings[i].a->position.y = y + dy * fraction;
+ model->strings[i].b->position.x = x + dx * (1 - fraction);
+ model->strings[i].b->position.y = y + dy * (1 - fraction);
+ }
+
#if 1
/* Stick constraints. */
for (i = 0; i < model->num_sticks; i++) {
model_accumulate_forces (model);
model_integrate (model, delta_t);
- for (i = 0; i < 5; i++)
+ for (i = 0; i < 35; i++)
model_constrain (model, delta_t);
model->theta += delta_t;
cairo_stroke (cr);
}
+static void
+draw_strings (cairo_t *cr,
+ Model *model,
+ Color *color)
+{
+ 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_stroke (cr);
+}
+
static void
draw_offsets (cairo_t *cr,
Model *model,
}
static Color blue = { 0, 0, 1 };
+static Color green = { 0, 1, 0 };
static Color red = { 1, 0, 0 };
static Color black = { 0, 0, 0 };
static Color white = { 1, 1, 1 };
draw_constraints (cr, model, &red);
draw_sticks (cr, model, &black);
+ draw_strings (cr, model, &green);
draw_offsets (cr, model, &blue);
draw_objects (cr, model, &white);
} models[] = {
{ "Rope", model_init_rope },
{ "Snake", model_init_snake },
- { "Curtain", model_init_curtain }
+ { "Curtain", model_init_curtain },
+ { "Grid", model_init_grid }
};
GtkTreeIter iter;