mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-03-26 22:49:01 +08:00
Single bone IK.
This commit is contained in:
parent
6444e8e934
commit
62560444cf
@ -1,7 +1,8 @@
|
|||||||
|
|
||||||
package com.esotericsoftware.spine;
|
package com.esotericsoftware.spine;
|
||||||
|
|
||||||
import com.badlogic.gdx.math.MathUtils;
|
import static com.badlogic.gdx.math.MathUtils.*;
|
||||||
|
|
||||||
import com.badlogic.gdx.math.Vector2;
|
import com.badlogic.gdx.math.Vector2;
|
||||||
import com.badlogic.gdx.utils.Array;
|
import com.badlogic.gdx.utils.Array;
|
||||||
|
|
||||||
@ -39,7 +40,14 @@ public class IkConstraint {
|
|||||||
public void apply () {
|
public void apply () {
|
||||||
Bone target = this.target;
|
Bone target = this.target;
|
||||||
Array<Bone> bones = this.bones;
|
Array<Bone> bones = this.bones;
|
||||||
|
switch (bones.size) {
|
||||||
|
case 1:
|
||||||
|
apply(bones.first(), target.worldX, target.worldY, mix);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
apply(bones.first(), bones.get(1), target.worldX, target.worldY, bendDirection, mix);
|
apply(bones.first(), bones.get(1), target.worldX, target.worldY, bendDirection, mix);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Array<Bone> getBones () {
|
public Array<Bone> getBones () {
|
||||||
@ -78,6 +86,15 @@ public class IkConstraint {
|
|||||||
return data.name;
|
return data.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 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.worldRotation;
|
||||||
|
float rotation = bone.rotation;
|
||||||
|
float rotationIK = (float)Math.atan2(targetY - bone.getWorldY(), targetX - bone.getWorldX()) * radDeg - parentRotation;
|
||||||
|
bone.rotationIK = rotation + (rotationIK - rotation) * alpha;
|
||||||
|
}
|
||||||
|
|
||||||
/** Adjusts the parent and child bone rotations so the tip of the child is as close to the target position as possible. The
|
/** Adjusts the parent and child bone rotations so the tip of the child is as close to the target position as possible. The
|
||||||
* target is specified in the world coordinate system.
|
* target is specified in the world coordinate system.
|
||||||
* @param child Any descendant bone of the parent. */
|
* @param child Any descendant bone of the parent. */
|
||||||
@ -108,21 +125,21 @@ public class IkConstraint {
|
|||||||
// Based on code by Ryan Juckett with permission: Copyright (c) 2008-2009 Ryan Juckett, http://www.ryanjuckett.com/
|
// Based on code by Ryan Juckett with permission: Copyright (c) 2008-2009 Ryan Juckett, http://www.ryanjuckett.com/
|
||||||
float cosDenom = 2 * len1 * len2;
|
float cosDenom = 2 * len1 * len2;
|
||||||
if (cosDenom < 0.0001f) {
|
if (cosDenom < 0.0001f) {
|
||||||
child.rotationIK = childRotation
|
child.rotationIK = childRotation + ((float)Math.atan2(targetY, targetX) * radDeg - parentRotation - childRotation)
|
||||||
+ ((float)Math.atan2(targetY, targetX) * MathUtils.radDeg - parentRotation - childRotation) * alpha;
|
* alpha;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
float cos = MathUtils.clamp((targetX * targetX + targetY * targetY - len1 * len1 - len2 * len2) / cosDenom, -1, 1);
|
float cos = clamp((targetX * targetX + targetY * targetY - len1 * len1 - len2 * len2) / cosDenom, -1, 1);
|
||||||
float childAngle = (float)Math.acos(cos) * bendDirection;
|
float childAngle = (float)Math.acos(cos) * bendDirection;
|
||||||
float adjacent = len1 + len2 * cos, opposite = len2 * MathUtils.sin(childAngle);
|
float adjacent = len1 + len2 * cos, opposite = len2 * sin(childAngle);
|
||||||
float parentAngle = (float)Math.atan2(targetY * adjacent - targetX * opposite, targetX * adjacent + targetY * opposite);
|
float parentAngle = (float)Math.atan2(targetY * adjacent - targetX * opposite, targetX * adjacent + targetY * opposite);
|
||||||
float rotation = (parentAngle - offset) * MathUtils.radDeg - parentRotation;
|
float rotation = (parentAngle - offset) * radDeg - parentRotation;
|
||||||
if (rotation > 180)
|
if (rotation > 180)
|
||||||
rotation -= 360;
|
rotation -= 360;
|
||||||
else if (rotation < -180) //
|
else if (rotation < -180) //
|
||||||
rotation += 360;
|
rotation += 360;
|
||||||
parent.rotationIK = parentRotation + rotation * alpha;
|
parent.rotationIK = parentRotation + rotation * alpha;
|
||||||
rotation = (childAngle + offset) * MathUtils.radDeg - childRotation;
|
rotation = (childAngle + offset) * radDeg - childRotation;
|
||||||
if (rotation > 180)
|
if (rotation > 180)
|
||||||
rotation -= 360;
|
rotation -= 360;
|
||||||
else if (rotation < -180) //
|
else if (rotation < -180) //
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user