summaryrefslogtreecommitdiff
path: root/src/solve.c
diff options
context:
space:
mode:
authorJesper Jensen <jesper@jnsn.dev>2026-03-31 08:12:21 +0200
committerJesper Jensen <jesper@jnsn.dev>2026-03-31 08:12:21 +0200
commit9686666268442e7058620b6193adf6f5c1b0b4d5 (patch)
tree865e377586316b81ff1627e6ab84d09382864cda /src/solve.c
parente49c0ac340da53f3460a2aa02b514340ab0866e0 (diff)
Begin solving other meta constraints
Diffstat (limited to 'src/solve.c')
-rw-r--r--src/solve.c65
1 files changed, 58 insertions, 7 deletions
diff --git a/src/solve.c b/src/solve.c
index 66cbb7f..e3c456b 100644
--- a/src/solve.c
+++ b/src/solve.c
@@ -806,18 +806,68 @@ constraint_matches_j:
;
constraint = c;
+ goto constraint_found;
}
+ continue;
+constraint_found:
+ ;
// Here we have two assemblies, one fixed and the other not,
// that share a single point and each one other point that
// share a constraint. Try place the rigid body based on that
// information
- float theta = atan2(constraint->c1->e->line.norm[1], constraint->c1->e->line.norm[0]) - atan2(constraint->c2->e->line.norm[1], constraint->c2->e->line.norm[0]);
- theta = forward ? -theta : theta;
-
- constraint->used = true;
- theta += constraint->forward ? constraint->v : -constraint->v;
+ float theta;
+ if(constraint->type == CT_LINE_LINE_ANGLE) {
+ assert(constraint->c1->e->type == ETYPE_LINE);
+ assert(constraint->c2->e->type == ETYPE_LINE);
+
+ // Align the two lines
+ theta = atan2(constraint->c1->e->line.norm[1], constraint->c1->e->line.norm[0]) - atan2(constraint->c2->e->line.norm[1], constraint->c2->e->line.norm[0]);
+ theta = forward ? -theta : theta;
+
+ // Then rotate by whatever the constraint says
+ theta += constraint->forward ? constraint->v : -constraint->v;
+ } else if(constraint->type == CT_POINT_LINE_DISTANCE) {
+ assert(constraint->c1->e->type == ETYPE_POINT);
+ assert(constraint->c2->e->type == ETYPE_LINE);
+
+ struct line line = constraint->c2->e->line;
+ float norm_len = glm_vec2_norm(line.norm);
+ float beta = atan2(line.norm[1], line.norm[0]);
+ float v_signed = constraint->forward ? constraint->v : -constraint->v;
+
+ if(forward) {
+ // Point (c1) is in assembly i (unfixed), line (c2) is in assembly j (fixed)
+ vec2 v_src;
+ glm_vec2_sub(constraint->c1->e->point.pos, assemblies[i].articulation_position[articulation_i]->point.pos, v_src);
+ float r = glm_vec2_norm(v_src);
+ float alpha = atan2(v_src[1], v_src[0]);
+
+ float d_pivot = (glm_vec2_dot(line.norm, assemblies[j].articulation_position[articulation_j]->point.pos) + line.C) / norm_len;
+ float cos_val = (v_signed - d_pivot) / r;
+ if(cos_val > 1.0f) cos_val = 1.0f;
+ if(cos_val < -1.0f) cos_val = -1.0f;
+
+ theta = beta - alpha + acos(cos_val);
+ } else {
+ // Line (c2) is in assembly i (unfixed), point (c1) is in assembly j (fixed)
+ vec2 v_ext;
+ glm_vec2_sub(constraint->c1->e->point.pos, assemblies[j].articulation_position[articulation_j]->point.pos, v_ext);
+ float r = glm_vec2_norm(v_ext);
+ float alpha_ext = atan2(v_ext[1], v_ext[0]);
+
+ float d_pivot_i = (glm_vec2_dot(line.norm, assemblies[i].articulation_position[articulation_i]->point.pos) + line.C) / norm_len;
+ float cos_val = (v_signed - d_pivot_i) / r;
+ if(cos_val > 1.0f) cos_val = 1.0f;
+ if(cos_val < -1.0f) cos_val = -1.0f;
+
+ theta = alpha_ext - beta + acos(cos_val);
+ }
+ } else {
+ abort();
+ }
+ constraint->used = i+1;
assert(assemblies[i].articulation_position[articulation_i]->type == ETYPE_POINT);
assert(assemblies[j].articulation_position[articulation_j]->type == ETYPE_POINT);
@@ -825,13 +875,13 @@ constraint_matches_j:
mat3 transform;
glm_mat3_identity(transform);
- glm_translate2d(transform, assemblies[i].articulation_position[articulation_i]->point.pos);
+ glm_translate2d(transform, assemblies[j].articulation_position[articulation_j]->point.pos);
glm_rotate2d(transform, theta);
{
vec2 negative_translate;
- glm_vec2_negate_to(assemblies[j].articulation_position[articulation_j]->point.pos, negative_translate);
+ glm_vec2_negate_to(assemblies[i].articulation_position[articulation_i]->point.pos, negative_translate);
glm_translate2d(transform, negative_translate);
}
@@ -888,6 +938,7 @@ constraint_matches_j:
abort();
}
}
+ assemblies[i].fixed = true;
}
}
break;