-
Notifications
You must be signed in to change notification settings - Fork 38
/
Copy pathChain.pde
64 lines (56 loc) · 2.06 KB
/
Chain.pde
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
class Chain {
ArrayList<PVector> joints;
int linkSize; // Space between joints
// Only used in non-FABRIK resolution
ArrayList<Float> angles;
float angleConstraint; // Max angle diff between two adjacent joints, higher = loose, lower = rigid
Chain(PVector origin, int jointCount, int linkSize) {
this(origin, jointCount, linkSize, TWO_PI);
}
Chain(PVector origin, int jointCount, int linkSize, float angleConstraint) {
this.linkSize = linkSize;
this.angleConstraint = angleConstraint;
joints = new ArrayList<>(); // Assumed to be >= 2, otherwise it wouldn't be much of a chain
angles = new ArrayList<>();
joints.add(origin.copy());
angles.add(0f);
for (int i = 1; i < jointCount; i++) {
joints.add(PVector.add(joints.get(i - 1), new PVector(0, this.linkSize)));
angles.add(0f);
}
}
void resolve(PVector pos) {
angles.set(0, PVector.sub(pos, joints.get(0)).heading());
joints.set(0, pos);
for (int i = 1; i < joints.size(); i++) {
float curAngle = PVector.sub(joints.get(i - 1), joints.get(i)).heading();
angles.set(i, constrainAngle(curAngle, angles.get(i - 1), angleConstraint));
joints.set(i, PVector.sub(joints.get(i - 1), PVector.fromAngle(angles.get(i)).setMag(linkSize)));
}
}
void fabrikResolve(PVector pos, PVector anchor) {
// Forward pass
joints.set(0, pos);
for (int i = 1; i < joints.size(); i++) {
joints.set(i, constrainDistance(joints.get(i), joints.get(i-1), linkSize));
}
// Backward pass
joints.set(joints.size() - 1, anchor);
for (int i = joints.size() - 2; i >= 0; i--) {
joints.set(i, constrainDistance(joints.get(i), joints.get(i+1), linkSize));
}
}
void display() {
strokeWeight(8);
stroke(255);
for (int i = 0; i < joints.size() - 1; i++) {
PVector startJoint = joints.get(i);
PVector endJoint = joints.get(i + 1);
line(startJoint.x, startJoint.y, endJoint.x, endJoint.y);
}
fill(42, 44, 53);
for (PVector joint : joints) {
ellipse(joint.x, joint.y, 32, 32);
}
}
}