|
@@ -122,14 +122,16 @@ public class IkConstraint implements Updatable {
|
|
|
/** Adjusts the bone rotation so the tip is as close to the target position as possible. The target is specified in the world
|
|
|
* coordinate system. */
|
|
|
static public void apply (Bone bone, float targetX, float targetY, float alpha) {
|
|
|
- float parentRotation = bone.parent == null ? 0 : bone.parent.getWorldRotationX();
|
|
|
- float rotation = bone.rotation;
|
|
|
- float rotationIK = atan2(targetY - bone.worldY, targetX - bone.worldX) * radDeg - parentRotation;
|
|
|
- if ((bone.worldSignX != bone.worldSignY) != (bone.skeleton.flipX != bone.skeleton.flipY)) rotationIK = 360 - rotationIK;
|
|
|
+ Bone pp = bone.parent;
|
|
|
+ float id = 1 / (pp.a * pp.d - pp.b * pp.c);
|
|
|
+ float x = targetX - pp.worldX, y = targetY - pp.worldY;
|
|
|
+ float tx = (x * pp.d - y * pp.b) * id - bone.x, ty = (y * pp.a - x * pp.c) * id - bone.y;
|
|
|
+ float rotationIK = atan2(ty, tx) * radDeg - bone.shearX;
|
|
|
+ if (bone.scaleX < 0) rotationIK += 180;
|
|
|
if (rotationIK > 180)
|
|
|
rotationIK -= 360;
|
|
|
else if (rotationIK < -180) rotationIK += 360;
|
|
|
- bone.updateWorldTransform(bone.x, bone.y, rotation + (rotationIK - rotation) * alpha, bone.appliedScaleX,
|
|
|
+ bone.updateWorldTransform(bone.x, bone.y, bone.rotation + (rotationIK - bone.rotation) * alpha, bone.appliedScaleX,
|
|
|
bone.appliedScaleY, bone.shearX, bone.shearY);
|
|
|
}
|
|
|
|
|
@@ -165,22 +167,12 @@ public class IkConstraint implements Updatable {
|
|
|
} else
|
|
|
os2 = 0;
|
|
|
Bone pp = parent.parent;
|
|
|
- float tx, ty, dx, dy;
|
|
|
- if (pp == null) {
|
|
|
- tx = targetX - px;
|
|
|
- ty = targetY - py;
|
|
|
- dx = child.worldX - px;
|
|
|
- dy = child.worldY - py;
|
|
|
- } else {
|
|
|
- float a = pp.a, b = pp.b, c = pp.c, d = pp.d, invDet = 1 / (a * d - b * c);
|
|
|
- float wx = pp.worldX, wy = pp.worldY, x = targetX - wx, y = targetY - wy;
|
|
|
- tx = (x * d - y * b) * invDet - px;
|
|
|
- ty = (y * a - x * c) * invDet - py;
|
|
|
- x = child.worldX - wx;
|
|
|
- y = child.worldY - wy;
|
|
|
- dx = (x * d - y * b) * invDet - px;
|
|
|
- dy = (y * a - x * c) * invDet - py;
|
|
|
- }
|
|
|
+ float ppa = pp.a, ppb = pp.b, ppc = pp.c, ppd = pp.d, id = 1 / (ppa * ppd - ppb * ppc);
|
|
|
+ float x = targetX - pp.worldX, y = targetY - pp.worldY;
|
|
|
+ float tx = (x * ppd - y * ppb) * id - px, ty = (y * ppa - x * ppc) * id - py;
|
|
|
+ x = child.worldX - pp.worldX;
|
|
|
+ y = child.worldY - pp.worldY;
|
|
|
+ float dx = (x * ppd - y * ppb) * id - px, dy = (y * ppa - x * ppc) * id - py;
|
|
|
float l1 = (float)Math.sqrt(dx * dx + dy * dy), l2 = child.data.length * csx, a1, a2;
|
|
|
outer:
|
|
|
if (u) {
|
|
@@ -204,7 +196,7 @@ public class IkConstraint implements Updatable {
|
|
|
float r0 = q / c2, r1 = c0 / q;
|
|
|
float r = Math.abs(r0) < Math.abs(r1) ? r0 : r1;
|
|
|
if (r * r <= dd) {
|
|
|
- float y = (float)Math.sqrt(dd - r * r) * bendDir;
|
|
|
+ y = (float)Math.sqrt(dd - r * r) * bendDir;
|
|
|
a1 = ta - atan2(y, r);
|
|
|
a2 = atan2(y / psy, (r - l1) / psx);
|
|
|
break outer;
|
|
@@ -212,32 +204,33 @@ public class IkConstraint implements Updatable {
|
|
|
}
|
|
|
float minAngle = 0, minDist = Float.MAX_VALUE, minX = 0, minY = 0;
|
|
|
float maxAngle = 0, maxDist = 0, maxX = 0, maxY = 0;
|
|
|
- float x = l1 + a, dist = x * x;
|
|
|
- if (dist > maxDist) {
|
|
|
+ x = l1 + a;
|
|
|
+ d = x * x;
|
|
|
+ if (d > maxDist) {
|
|
|
maxAngle = 0;
|
|
|
- maxDist = dist;
|
|
|
+ maxDist = d;
|
|
|
maxX = x;
|
|
|
}
|
|
|
x = l1 - a;
|
|
|
- dist = x * x;
|
|
|
- if (dist < minDist) {
|
|
|
+ d = x * x;
|
|
|
+ if (d < minDist) {
|
|
|
minAngle = PI;
|
|
|
- minDist = dist;
|
|
|
+ minDist = d;
|
|
|
minX = x;
|
|
|
}
|
|
|
float angle = (float)Math.acos(-a * l1 / (aa - bb));
|
|
|
x = a * cos(angle) + l1;
|
|
|
- float y = b * sin(angle);
|
|
|
- dist = x * x + y * y;
|
|
|
- if (dist < minDist) {
|
|
|
+ y = b * sin(angle);
|
|
|
+ d = x * x + y * y;
|
|
|
+ if (d < minDist) {
|
|
|
minAngle = angle;
|
|
|
- minDist = dist;
|
|
|
+ minDist = d;
|
|
|
minX = x;
|
|
|
minY = y;
|
|
|
}
|
|
|
- if (dist > maxDist) {
|
|
|
+ if (d > maxDist) {
|
|
|
maxAngle = angle;
|
|
|
- maxDist = dist;
|
|
|
+ maxDist = d;
|
|
|
maxX = x;
|
|
|
maxY = y;
|
|
|
}
|
|
@@ -251,7 +244,7 @@ public class IkConstraint implements Updatable {
|
|
|
}
|
|
|
float os = atan2(cy, cx) * s2;
|
|
|
a1 = (a1 - os) * radDeg + os1;
|
|
|
- a2 = (a2 + os) * radDeg * s2 + os2;
|
|
|
+ a2 = ((a2 + os) * radDeg - child.shearX) * s2 + os2;
|
|
|
if (a1 > 180)
|
|
|
a1 -= 360;
|
|
|
else if (a1 < -180) a1 += 360;
|
|
@@ -259,8 +252,7 @@ public class IkConstraint implements Updatable {
|
|
|
a2 -= 360;
|
|
|
else if (a2 < -180) a2 += 360;
|
|
|
float rotation = parent.rotation;
|
|
|
- parent.updateWorldTransform(px, py, rotation + (a1 - rotation) * alpha, parent.appliedScaleX, parent.appliedScaleY,
|
|
|
- parent.shearX, parent.shearY);
|
|
|
+ parent.updateWorldTransform(px, py, rotation + (a1 - rotation) * alpha, parent.appliedScaleX, parent.appliedScaleY, 0, 0);
|
|
|
rotation = child.rotation;
|
|
|
child.updateWorldTransform(cx, cy, rotation + (a2 - rotation) * alpha, child.appliedScaleX, child.appliedScaleY,
|
|
|
child.shearX, child.shearY);
|