[libgdx] Allow uniform for two bone IK.

This commit is contained in:
Nathan Sweet 2021-04-01 00:47:09 +02:00
parent aa46f411ab
commit 33bce01fee
2 changed files with 37 additions and 22 deletions

View File

@ -89,7 +89,7 @@ public class IkConstraint implements Updatable {
apply((Bone)bones[0], target.worldX, target.worldY, compress, stretch, data.uniform, mix); apply((Bone)bones[0], target.worldX, target.worldY, compress, stretch, data.uniform, mix);
break; break;
case 2: case 2:
apply((Bone)bones[0], (Bone)bones[1], target.worldX, target.worldY, bendDirection, stretch, softness, mix); apply((Bone)bones[0], (Bone)bones[1], target.worldX, target.worldY, bendDirection, stretch, data.uniform, softness, mix);
break; break;
} }
} }
@ -109,7 +109,9 @@ public class IkConstraint implements Updatable {
this.target = target; this.target = target;
} }
/** A percentage (0-1) that controls the mix between the constrained and unconstrained rotation. */ /** A percentage (0-1) that controls the mix between the constrained and unconstrained rotation.
* <p>
* For two bone IK: if the parent bone has local nonuniform scale, the child bone's local Y translation is set to 0. */
public float getMix () { public float getMix () {
return mix; return mix;
} }
@ -118,7 +120,8 @@ public class IkConstraint implements Updatable {
this.mix = mix; this.mix = mix;
} }
/** For two bone IK, the distance from the maximum reach of the bones that rotation will slow. */ /** For two bone IK, the target bone's distance from the maximum reach of the bones where rotation begins to slow. The bones
* will not straighten completely until the target is this far out of range. */
public float getSoftness () { public float getSoftness () {
return softness; return softness;
} }
@ -127,7 +130,7 @@ public class IkConstraint implements Updatable {
this.softness = softness; this.softness = softness;
} }
/** Controls the bend direction of the IK bones, either 1 or -1. */ /** For two bone IK, controls the bend direction of the IK bones, either 1 or -1. */
public int getBendDirection () { public int getBendDirection () {
return bendDirection; return bendDirection;
} }
@ -136,7 +139,7 @@ public class IkConstraint implements Updatable {
this.bendDirection = bendDirection; this.bendDirection = bendDirection;
} }
/** When true and only a single bone is being constrained, if the target is too close, the bone is scaled to reach it. */ /** For one bone IK, when true and the target is too close, the bone is scaled to reach it. */
public boolean getCompress () { public boolean getCompress () {
return compress; return compress;
} }
@ -145,8 +148,10 @@ public class IkConstraint implements Updatable {
this.compress = compress; this.compress = compress;
} }
/** When true, if the target is out of range, the parent bone is scaled to reach it. If more than one bone is being constrained /** When true and the target is out of range, the parent bone is scaled to reach it.
* and the parent bone has local nonuniform scale, stretch is not applied. */ * <p>
* For two bone IK: 1) the child bone's local Y translation is set to 0, 2) stretch is not applied if {@link #getSoftness()} is
* > 0, and 3) if the parent bone has local nonuniform scale, stretch is not applied. */
public boolean getStretch () { public boolean getStretch () {
return stretch; return stretch;
} }
@ -221,13 +226,13 @@ public class IkConstraint implements Updatable {
/** Applies 2 bone IK. The target is specified in the world coordinate system. /** Applies 2 bone IK. The target is specified in the world coordinate system.
* @param child A direct descendant of the parent bone. */ * @param child A direct descendant of the parent bone. */
static public void apply (Bone parent, Bone child, float targetX, float targetY, int bendDir, boolean stretch, float softness, static public void apply (Bone parent, Bone child, float targetX, float targetY, int bendDir, boolean stretch, boolean uniform,
float alpha) { float softness, float alpha) {
if (parent == null) throw new IllegalArgumentException("parent cannot be null."); if (parent == null) throw new IllegalArgumentException("parent cannot be null.");
if (child == null) throw new IllegalArgumentException("child cannot be null."); if (child == null) throw new IllegalArgumentException("child cannot be null.");
if (!parent.appliedValid) parent.updateAppliedTransform(); if (!parent.appliedValid) parent.updateAppliedTransform();
if (!child.appliedValid) child.updateAppliedTransform(); if (!child.appliedValid) child.updateAppliedTransform();
float px = parent.ax, py = parent.ay, psx = parent.ascaleX, sx = psx, psy = parent.ascaleY, csx = child.ascaleX; float px = parent.ax, py = parent.ay, psx = parent.ascaleX, psy = parent.ascaleY, sx = psx, sy = psy, csx = child.ascaleX;
int os1, os2, s2; int os1, os2, s2;
if (psx < 0) { if (psx < 0) {
psx = -psx; psx = -psx;
@ -295,7 +300,11 @@ public class IkConstraint implements Updatable {
} else if (cos > 1) { } else if (cos > 1) {
cos = 1; cos = 1;
a2 = 0; a2 = 0;
if (stretch) sx *= ((float)Math.sqrt(dd) / (l1 + l2) - 1) * alpha + 1; if (stretch) {
a = ((float)Math.sqrt(dd) / (l1 + l2) - 1) * alpha + 1;
sx *= a;
if (uniform) sy *= a;
}
} else } else
a2 = (float)Math.acos(cos) * bendDir; a2 = (float)Math.acos(cos) * bendDir;
a = l1 + l2 * cos; a = l1 + l2 * cos;
@ -355,13 +364,15 @@ public class IkConstraint implements Updatable {
a1 = (a1 - os) * radDeg + os1 - rotation; a1 = (a1 - os) * radDeg + os1 - rotation;
if (a1 > 180) if (a1 > 180)
a1 -= 360; a1 -= 360;
else if (a1 < -180) a1 += 360; else if (a1 < -180) //
parent.updateWorldTransform(px, py, rotation + a1 * alpha, sx, parent.ascaleY, 0, 0); a1 += 360;
parent.updateWorldTransform(px, py, rotation + a1 * alpha, sx, sy, 0, 0);
rotation = child.arotation; rotation = child.arotation;
a2 = ((a2 + os) * radDeg - child.ashearX) * s2 + os2 - rotation; a2 = ((a2 + os) * radDeg - child.ashearX) * s2 + os2 - rotation;
if (a2 > 180) if (a2 > 180)
a2 -= 360; a2 -= 360;
else if (a2 < -180) a2 += 360; else if (a2 < -180) //
a2 += 360;
child.updateWorldTransform(cx, cy, rotation + a2 * alpha, child.ascaleX, child.ascaleY, child.ashearX, child.ashearY); child.updateWorldTransform(cx, cy, rotation + a2 * alpha, child.ascaleX, child.ascaleY, child.ashearX, child.ashearY);
} }
} }

View File

@ -60,7 +60,9 @@ public class IkConstraintData extends ConstraintData {
this.target = target; this.target = target;
} }
/** A percentage (0-1) that controls the mix between the constrained and unconstrained rotation. */ /** A percentage (0-1) that controls the mix between the constrained and unconstrained rotation.
* <p>
* For two bone IK: if the parent bone has local nonuniform scale, the child bone's local Y translation is set to 0. */
public float getMix () { public float getMix () {
return mix; return mix;
} }
@ -69,7 +71,8 @@ public class IkConstraintData extends ConstraintData {
this.mix = mix; this.mix = mix;
} }
/** For two bone IK, the distance from the maximum reach of the bones that rotation will slow. */ /** For two bone IK, the target bone's distance from the maximum reach of the bones where rotation begins to slow. The bones
* will not straighten completely until the target is this far out of range. */
public float getSoftness () { public float getSoftness () {
return softness; return softness;
} }
@ -78,7 +81,7 @@ public class IkConstraintData extends ConstraintData {
this.softness = softness; this.softness = softness;
} }
/** Controls the bend direction of the IK bones, either 1 or -1. */ /** For two bone IK, controls the bend direction of the IK bones, either 1 or -1. */
public int getBendDirection () { public int getBendDirection () {
return bendDirection; return bendDirection;
} }
@ -87,7 +90,7 @@ public class IkConstraintData extends ConstraintData {
this.bendDirection = bendDirection; this.bendDirection = bendDirection;
} }
/** When true and only a single bone is being constrained, if the target is too close, the bone is scaled to reach it. */ /** For one bone IK, when true and the target is too close, the bone is scaled to reach it. */
public boolean getCompress () { public boolean getCompress () {
return compress; return compress;
} }
@ -96,8 +99,10 @@ public class IkConstraintData extends ConstraintData {
this.compress = compress; this.compress = compress;
} }
/** When true, if the target is out of range, the parent bone is scaled to reach it. If more than one bone is being constrained /** When true and the target is out of range, the parent bone is scaled to reach it.
* and the parent bone has local nonuniform scale, stretch is not applied. */ * <p>
* For two bone IK: 1) the child bone's local Y translation is set to 0, 2) stretch is not applied if {@link #getSoftness()} is
* > 0, and 3) if the parent bone has local nonuniform scale, stretch is not applied. */
public boolean getStretch () { public boolean getStretch () {
return stretch; return stretch;
} }
@ -106,8 +111,7 @@ public class IkConstraintData extends ConstraintData {
this.stretch = stretch; this.stretch = stretch;
} }
/** When true, only a single bone is being constrained, and {@link #getCompress()} or {@link #getStretch()} is used, the bone /** When true and {@link #getCompress()} or {@link #getStretch()} is used, the bone is scaled on both the X and Y axes. */
* is scaled on both the X and Y axes. */
public boolean getUniform () { public boolean getUniform () {
return uniform; return uniform;
} }