/// <summary>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.</summary> static public void Apply(Bone bone, float targetX, float targetY, float alpha) { if (!bone.appliedValid) { bone.UpdateAppliedTransform(); } Bone p = bone.parent; float id = 1 / (p.a * p.d - p.b * p.c); float x = targetX - p.worldX, y = targetY - p.worldY; float tx = (x * p.d - y * p.b) * id - bone.ax, ty = (y * p.a - x * p.c) * id - bone.ay; float rotationIK = (float)Math.Atan2(ty, tx) * MathUtils.RadDeg - bone.ashearX - bone.arotation; if (bone.ascaleX < 0) { rotationIK += 180; } if (rotationIK > 180) { rotationIK -= 360; } else if (rotationIK < -180) { rotationIK += 360; } bone.UpdateWorldTransform(bone.ax, bone.ay, bone.arotation + rotationIK * alpha, bone.ascaleX, bone.ascaleY, bone.ashearX, bone.ashearY); }
public static void Apply(Bone bone, float targetX, float targetY, float alpha) { if (!bone.appliedValid) { bone.UpdateAppliedTransform(); } Bone parent = bone.parent; float num = 1f / ((parent.a * parent.d) - (parent.b * parent.c)); float num2 = targetX - parent.worldX; float num3 = targetY - parent.worldY; float num4 = (((num2 * parent.d) - (num3 * parent.b)) * num) - bone.ax; float num5 = (((num3 * parent.a) - (num2 * parent.c)) * num) - bone.ay; float num6 = ((((float)Math.Atan2((double)num5, (double)num4)) * 57.29578f) - bone.ashearX) - bone.arotation; if (bone.ascaleX < 0f) { num6 += 180f; } if (num6 > 180f) { num6 -= 360f; } else if (num6 < -180f) { num6 += 360f; } bone.UpdateWorldTransform(bone.ax, bone.ay, bone.arotation + (num6 * alpha), bone.ascaleX, bone.ascaleY, bone.ashearX, bone.ashearY); }
public static void Apply(Bone bone, float targetX, float targetY, float alpha) { if (!bone.appliedValid) { bone.UpdateAppliedTransform(); } Bone parent = bone.parent; float num = 1f / (parent.a * parent.d - parent.b * parent.c); float num2 = targetX - parent.worldX; float num3 = targetY - parent.worldY; float num4 = (num2 * parent.d - num3 * parent.b) * num - bone.ax; float num5 = (num3 * parent.a - num2 * parent.c) * num - bone.ay; float num6 = (float)Math.Atan2(num5, num4) * (180f / (float)Math.PI) - bone.ashearX - bone.arotation; if (bone.ascaleX < 0f) { num6 += 180f; } if (num6 > 180f) { num6 -= 360f; } else if (num6 < -180f) { num6 += 360f; } bone.UpdateWorldTransform(bone.ax, bone.ay, bone.arotation + num6 * alpha, bone.ascaleX, bone.ascaleY, bone.ashearX, bone.ashearY); }
private void ApplyAbsoluteLocal() { float num = rotateMix; float num2 = translateMix; float num3 = scaleMix; float num4 = shearMix; Bone bone = target; if (!bone.appliedValid) { bone.UpdateAppliedTransform(); } Bone[] items = bones.Items; int i = 0; for (int count = bones.Count; i < count; i++) { Bone bone2 = items[i]; if (!bone2.appliedValid) { bone2.UpdateAppliedTransform(); } float num5 = bone2.arotation; if (num != 0f) { float num6 = bone.arotation - num5 + data.offsetRotation; num6 -= (float)((16384 - (int)(16384.499999999996 - (double)(num6 / 360f))) * 360); num5 += num6 * num; } float num7 = bone2.ax; float num8 = bone2.ay; if (num2 != 0f) { num7 += (bone.ax - num7 + data.offsetX) * num2; num8 += (bone.ay - num8 + data.offsetY) * num2; } float num9 = bone2.ascaleX; float num10 = bone2.ascaleY; if (num3 > 0f) { if (num9 > 1E-05f) { num9 = (num9 + (bone.ascaleX - num9 + data.offsetScaleX) * num3) / num9; } if (num10 > 1E-05f) { num10 = (num10 + (bone.ascaleY - num10 + data.offsetScaleY) * num3) / num10; } } float ashearY = bone2.ashearY; if (num4 > 0f) { float num11 = bone.ashearY - ashearY + data.offsetShearY; num11 -= (float)((16384 - (int)(16384.499999999996 - (double)(num11 / 360f))) * 360); bone2.shearY += num11 * num4; } bone2.UpdateWorldTransform(num7, num8, num5, num9, num10, bone2.ashearX, ashearY); } }
void ApplyAbsoluteLocal() { float rotateMix = this.rotateMix, translateMix = this.translateMix, scaleMix = this.scaleMix, shearMix = this.shearMix; Bone target = this.target; if (!target.appliedValid) { target.UpdateAppliedTransform(); } var bonesItems = this.bones.Items; for (int i = 0, n = this.bones.Count; i < n; i++) { Bone bone = bonesItems[i]; if (!bone.appliedValid) { bone.UpdateAppliedTransform(); } float rotation = bone.arotation; if (rotateMix != 0) { float r = target.arotation - rotation + data.offsetRotation; r -= (16384 - (int)(16384.499999999996 - r / 360)) * 360; rotation += r * rotateMix; } float x = bone.ax, y = bone.ay; if (translateMix != 0) { x += (target.ax - x + data.offsetX) * translateMix; y += (target.ay - y + data.offsetY) * translateMix; } float scaleX = bone.ascaleX, scaleY = bone.ascaleY; if (scaleMix != 0) { if (scaleX != 0) { scaleX = (scaleX + (target.ascaleX - scaleX + data.offsetScaleX) * scaleMix) / scaleX; } if (scaleY != 0) { scaleY = (scaleY + (target.ascaleY - scaleY + data.offsetScaleY) * scaleMix) / scaleY; } } float shearY = bone.ashearY; if (shearMix != 0) { float r = target.ashearY - shearY + data.offsetShearY; r -= (16384 - (int)(16384.499999999996 - r / 360)) * 360; shearY += r * shearMix; } bone.UpdateWorldTransform(x, y, rotation, scaleX, scaleY, bone.ashearX, shearY); } }
private void ApplyRelativeLocal() { float rotateMix = this.rotateMix; float translateMix = this.translateMix; float scaleMix = this.scaleMix; float shearMix = this.shearMix; Bone target = this.target; if (!target.appliedValid) { target.UpdateAppliedTransform(); } Bone[] items = this.bones.Items; int index = 0; int count = this.bones.Count; while (index < count) { Bone bone2 = items[index]; if (!bone2.appliedValid) { bone2.UpdateAppliedTransform(); } float arotation = bone2.arotation; if (rotateMix != 0f) { arotation += (target.arotation + this.data.offsetRotation) * rotateMix; } float ax = bone2.ax; float ay = bone2.ay; if (translateMix != 0f) { ax += (target.ax + this.data.offsetX) * translateMix; ay += (target.ay + this.data.offsetY) * translateMix; } float ascaleX = bone2.ascaleX; float ascaleY = bone2.ascaleY; if (scaleMix > 0f) { if (ascaleX > 1E-05f) { ascaleX *= (((target.ascaleX - 1f) + this.data.offsetScaleX) * scaleMix) + 1f; } if (ascaleY > 1E-05f) { ascaleY *= (((target.ascaleY - 1f) + this.data.offsetScaleY) * scaleMix) + 1f; } } float ashearY = bone2.ashearY; if (shearMix > 0f) { ashearY += (target.ashearY + this.data.offsetShearY) * shearMix; } bone2.UpdateWorldTransform(ax, ay, arotation, ascaleX, ascaleY, bone2.ashearX, ashearY); index++; } }
private void ApplyRelativeLocal() { float num = rotateMix; float num2 = translateMix; float num3 = scaleMix; float num4 = shearMix; Bone bone = target; if (!bone.appliedValid) { bone.UpdateAppliedTransform(); } Bone[] items = bones.Items; int i = 0; for (int count = bones.Count; i < count; i++) { Bone bone2 = items[i]; if (!bone2.appliedValid) { bone2.UpdateAppliedTransform(); } float num5 = bone2.arotation; if (num != 0f) { num5 += (bone.arotation + data.offsetRotation) * num; } float num6 = bone2.ax; float num7 = bone2.ay; if (num2 != 0f) { num6 += (bone.ax + data.offsetX) * num2; num7 += (bone.ay + data.offsetY) * num2; } float num8 = bone2.ascaleX; float num9 = bone2.ascaleY; if (num3 > 0f) { if (num8 > 1E-05f) { num8 *= (bone.ascaleX - 1f + data.offsetScaleX) * num3 + 1f; } if (num9 > 1E-05f) { num9 *= (bone.ascaleY - 1f + data.offsetScaleY) * num3 + 1f; } } float num10 = bone2.ashearY; if (num4 > 0f) { num10 += (bone.ashearY + data.offsetShearY) * num4; } bone2.UpdateWorldTransform(num6, num7, num5, num8, num9, bone2.ashearX, num10); } }
void ApplyRelativeLocal() { float rotateMix = this.rotateMix, translateMix = this.translateMix, scaleMix = this.scaleMix, shearMix = this.shearMix; Bone target = this.target; if (!target.appliedValid) { target.UpdateAppliedTransform(); } var bonesItems = this.bones.Items; for (int i = 0, n = this.bones.Count; i < n; i++) { Bone bone = bonesItems[i]; if (!bone.appliedValid) { bone.UpdateAppliedTransform(); } float rotation = bone.arotation; if (rotateMix != 0) { rotation += (target.arotation + data.offsetRotation) * rotateMix; } float x = bone.ax, y = bone.ay; if (translateMix != 0) { x += (target.ax + data.offsetX) * translateMix; y += (target.ay + data.offsetY) * translateMix; } float scaleX = bone.ascaleX, scaleY = bone.ascaleY; if (scaleMix != 0) { if (scaleX > 0.00001f) { scaleX *= ((target.ascaleX - 1 + data.offsetScaleX) * scaleMix) + 1; } if (scaleY > 0.00001f) { scaleY *= ((target.ascaleY - 1 + data.offsetScaleY) * scaleMix) + 1; } } float shearY = bone.ashearY; if (shearMix != 0) { shearY += (target.ashearY + data.offsetShearY) * shearMix; } bone.UpdateWorldTransform(x, y, rotation, scaleX, scaleY, bone.ashearX, shearY); } }
void ApplyAbsoluteLocal() { float mixRotate = this.mixRotate, mixX = this.mixX, mixY = this.mixY, mixScaleX = this.mixScaleX, mixScaleY = this.mixScaleY, mixShearY = this.mixShearY; Bone target = this.target; var bones = this.bones.Items; for (int i = 0, n = this.bones.Count; i < n; i++) { Bone bone = bones[i]; float rotation = bone.arotation; if (mixRotate != 0) { float r = target.arotation - rotation + data.offsetRotation; r -= (16384 - (int)(16384.499999999996 - r / 360)) * 360; rotation += r * mixRotate; } float x = bone.ax, y = bone.ay; x += (target.ax - x + data.offsetX) * mixX; y += (target.ay - y + data.offsetY) * mixY; float scaleX = bone.ascaleX, scaleY = bone.ascaleY; if (mixScaleX != 0 && scaleX != 0) { scaleX = (scaleX + (target.ascaleX - scaleX + data.offsetScaleX) * mixScaleX) / scaleX; } if (mixScaleY != 0 && scaleY != 0) { scaleY = (scaleY + (target.ascaleY - scaleY + data.offsetScaleY) * mixScaleY) / scaleY; } float shearY = bone.ashearY; if (mixShearY != 0) { float r = target.ashearY - shearY + data.offsetShearY; r -= (16384 - (int)(16384.499999999996 - r / 360)) * 360; shearY += r * mixShearY; } bone.UpdateWorldTransform(x, y, rotation, scaleX, scaleY, bone.ashearX, shearY); } }
/// <summary>Applies 1 bone IK. The target is specified in the world coordinate system.</summary> static public void Apply(Bone bone, float targetX, float targetY, bool compress, bool stretch, bool uniform, float alpha) { if (!bone.appliedValid) { bone.UpdateAppliedTransform(); } Bone p = bone.parent; float id = 1 / (p.a * p.d - p.b * p.c); float x = targetX - p.worldX, y = targetY - p.worldY; float tx = (x * p.d - y * p.b) * id - bone.ax, ty = (y * p.a - x * p.c) * id - bone.ay; float rotationIK = (float)Math.Atan2(ty, tx) * MathUtils.RadDeg - bone.ashearX - bone.arotation; if (bone.ascaleX < 0) { rotationIK += 180; } if (rotationIK > 180) { rotationIK -= 360; } else if (rotationIK < -180) // { rotationIK += 360; } float sx = bone.ascaleX, sy = bone.ascaleY; if (compress || stretch) { float b = bone.data.length * sx, dd = (float)Math.Sqrt(tx * tx + ty * ty); if ((compress && dd < b) || (stretch && dd > b) && b > 0.0001f) { float s = (dd / b - 1) * alpha + 1; sx *= s; if (uniform) { sy *= s; } } } bone.UpdateWorldTransform(bone.ax, bone.ay, bone.arotation + rotationIK * alpha, sx, sy, bone.ashearX, bone.ashearY); }
/// <summary>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.</summary> static public void Apply(Bone bone, float targetX, float targetY, float alpha) { float parentRotation = bone.parent == null ? 0 : bone.parent.WorldRotationX; float rotation = bone.rotation; float rotationIK = MathUtils.Atan2(targetY - bone.worldY, targetX - bone.worldX) * MathUtils.radDeg - parentRotation; if ((bone.worldSignX != bone.worldSignY) != (bone.skeleton.flipX != (bone.skeleton.flipY != Bone.yDown))) { rotationIK = 360 - rotationIK; } if (rotationIK > 180) { rotationIK -= 360; } else if (rotationIK < -180) { rotationIK += 360; } bone.UpdateWorldTransform(bone.x, bone.y, rotation + (rotationIK - rotation) * alpha, bone.appliedScaleX, bone.appliedScaleY); }
/// <summary>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.</summary> static public void Apply(Bone bone, float targetX, float targetY, float alpha) { 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 = MathUtils.Atan2(ty, tx) * MathUtils.radDeg - bone.shearX - bone.rotation; if (bone.scaleX < 0) { rotationIK += 180; } if (rotationIK > 180) { rotationIK -= 360; } else if (rotationIK < -180) { rotationIK += 360; } bone.UpdateWorldTransform(bone.x, bone.y, bone.rotation + rotationIK * alpha, bone.scaleX, bone.scaleY, bone.shearX, bone.shearY); }
void ApplyRelativeLocal() { float mixRotate = this.mixRotate, mixX = this.mixX, mixY = this.mixY, mixScaleX = this.mixScaleX, mixScaleY = this.mixScaleY, mixShearY = this.mixShearY; Bone target = this.target; var bones = this.bones.Items; for (int i = 0, n = this.bones.Count; i < n; i++) { Bone bone = bones[i]; float rotation = bone.arotation + (target.arotation + data.offsetRotation) * mixRotate; float x = bone.ax + (target.ax + data.offsetX) * mixX; float y = bone.ay + (target.ay + data.offsetY) * mixY; float scaleX = bone.ascaleX * (((target.ascaleX - 1 + data.offsetScaleX) * mixScaleX) + 1); float scaleY = bone.ascaleY * (((target.ascaleY - 1 + data.offsetScaleY) * mixScaleY) + 1); float shearY = bone.ashearY + (target.ashearY + data.offsetShearY) * mixShearY; bone.UpdateWorldTransform(x, y, rotation, scaleX, scaleY, bone.ashearX, shearY); } }
public static void Apply(Bone bone, float targetX, float targetY, float alpha) { Bone parent = bone.parent; float num = 1f / (parent.a * parent.d - parent.b * parent.c); float num2 = targetX - parent.worldX; float num3 = targetY - parent.worldY; float x = (num2 * parent.d - num3 * parent.b) * num - bone.x; float y = (num3 * parent.a - num2 * parent.c) * num - bone.y; float num4 = MathUtils.Atan2(y, x) * 57.2957764f - bone.shearX - bone.rotation; if (bone.scaleX < 0f) { num4 += 180f; } if (num4 > 180f) { num4 -= 360f; } else if (num4 < -180f) { num4 += 360f; } bone.UpdateWorldTransform(bone.x, bone.y, bone.rotation + num4 * alpha, bone.scaleX, bone.scaleY, bone.shearX, bone.shearY); }
/// <summary>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.</summary> static public void Apply (Bone bone, float targetX, float targetY, float alpha) { float parentRotation = bone.parent == null ? 0 : bone.parent.WorldRotationX; float rotation = bone.rotation; float rotationIK = MathUtils.Atan2(targetY - bone.worldY, targetX - bone.worldX) * MathUtils.radDeg - parentRotation; if ((bone.worldSignX != bone.worldSignY) != (bone.skeleton.flipX != (bone.skeleton.flipY != Bone.yDown))) rotationIK = 360 - rotationIK; if (rotationIK > 180) rotationIK -= 360; else if (rotationIK < -180) rotationIK += 360; bone.UpdateWorldTransform(bone.x, bone.y, rotation + (rotationIK - rotation) * alpha, bone.scaleX, bone.scaleY); }
public static void Apply(Bone parent, Bone child, float targetX, float targetY, int bendDir, float alpha) { if (alpha == 0f) { child.UpdateWorldTransform(); return; } if (!parent.appliedValid) { parent.UpdateAppliedTransform(); } if (!child.appliedValid) { child.UpdateAppliedTransform(); } float ax = parent.ax; float ay = parent.ay; float num = parent.ascaleX; float num2 = parent.ascaleY; float num3 = child.ascaleX; int num4; int num5; if (num < 0f) { num = 0f - num; num4 = 180; num5 = -1; } else { num4 = 0; num5 = 1; } if (num2 < 0f) { num2 = 0f - num2; num5 = -num5; } int num6; if (num3 < 0f) { num3 = 0f - num3; num6 = 180; } else { num6 = 0; } float ax2 = child.ax; float a = parent.a; float b = parent.b; float c = parent.c; float d = parent.d; bool flag = Math.Abs(num - num2) <= 0.0001f; float num7; float num8; float num9; if (!flag) { num7 = 0f; num8 = a * ax2 + parent.worldX; num9 = c * ax2 + parent.worldY; } else { num7 = child.ay; num8 = a * ax2 + b * num7 + parent.worldX; num9 = c * ax2 + d * num7 + parent.worldY; } Bone parent2 = parent.parent; a = parent2.a; b = parent2.b; c = parent2.c; d = parent2.d; float num10 = 1f / (a * d - b * c); float num11 = targetX - parent2.worldX; float num12 = targetY - parent2.worldY; float num13 = (num11 * d - num12 * b) * num10 - ax; float num14 = (num12 * a - num11 * c) * num10 - ay; num11 = num8 - parent2.worldX; num12 = num9 - parent2.worldY; float num15 = (num11 * d - num12 * b) * num10 - ax; float num16 = (num12 * a - num11 * c) * num10 - ay; float num17 = (float)Math.Sqrt(num15 * num15 + num16 * num16); float num18 = child.data.length * num3; float num21; float num20; if (flag) { num18 *= num; float num19 = (num13 * num13 + num14 * num14 - num17 * num17 - num18 * num18) / (2f * num17 * num18); if (num19 < -1f) { num19 = -1f; } else if (num19 > 1f) { num19 = 1f; } num20 = (float)Math.Acos(num19) * (float)bendDir; a = num17 + num18 * num19; b = num18 * (float)Math.Sin(num20); num21 = (float)Math.Atan2(num14 * a - num13 * b, num13 * a + num14 * b); } else { a = num * num18; b = num2 * num18; float num22 = a * a; float num23 = b * b; float num24 = num13 * num13 + num14 * num14; float num25 = (float)Math.Atan2(num14, num13); c = num23 * num17 * num17 + num22 * num24 - num22 * num23; float num26 = -2f * num23 * num17; float num27 = num23 - num22; d = num26 * num26 - 4f * num27 * c; if (d >= 0f) { float num28 = (float)Math.Sqrt(d); if (num26 < 0f) { num28 = 0f - num28; } num28 = (0f - (num26 + num28)) / 2f; float num29 = num28 / num27; float num30 = c / num28; float num31 = (!(Math.Abs(num29) < Math.Abs(num30))) ? num30 : num29; if (num31 * num31 <= num24) { num12 = (float)Math.Sqrt(num24 - num31 * num31) * (float)bendDir; num21 = num25 - (float)Math.Atan2(num12, num31); num20 = (float)Math.Atan2(num12 / num2, (num31 - num17) / num); goto IL_0504; } } float num32 = (float)Math.PI; float num33 = num17 - a; float num34 = num33 * num33; float num35 = 0f; float num36 = 0f; float num37 = num17 + a; float num38 = num37 * num37; float num39 = 0f; c = (0f - a) * num17 / (num22 - num23); if (c >= -1f && c <= 1f) { c = (float)Math.Acos(c); num11 = a * (float)Math.Cos(c) + num17; num12 = b * (float)Math.Sin(c); d = num11 * num11 + num12 * num12; if (d < num34) { num32 = c; num34 = d; num33 = num11; num35 = num12; } if (d > num38) { num36 = c; num38 = d; num37 = num11; num39 = num12; } } if (num24 <= (num34 + num38) / 2f) { num21 = num25 - (float)Math.Atan2(num35 * (float)bendDir, num33); num20 = num32 * (float)bendDir; } else { num21 = num25 - (float)Math.Atan2(num39 * (float)bendDir, num37); num20 = num36 * (float)bendDir; } } goto IL_0504; IL_0504: float num40 = (float)Math.Atan2(num7, ax2) * (float)num5; float arotation = parent.arotation; num21 = (num21 - num40) * (180f / (float)Math.PI) + (float)num4 - arotation; if (num21 > 180f) { num21 -= 360f; } else if (num21 < -180f) { num21 += 360f; } parent.UpdateWorldTransform(ax, ay, arotation + num21 * alpha, parent.scaleX, parent.ascaleY, 0f, 0f); arotation = child.arotation; num20 = ((num20 + num40) * (180f / (float)Math.PI) - child.ashearX) * (float)num5 + (float)num6 - arotation; if (num20 > 180f) { num20 -= 360f; } else if (num20 < -180f) { num20 += 360f; } child.UpdateWorldTransform(ax2, num7, arotation + num20 * alpha, child.ascaleX, child.ascaleY, child.ashearX, child.ashearY); }
/// <summary>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.</summary> /// <param name="child">A direct descendant of the parent bone.</param> static public void Apply(Bone parent, Bone child, float targetX, float targetY, int bendDir, float alpha) { if (alpha == 0) { return; } float px = parent.x, py = parent.y, psx = parent.appliedScaleX, psy = parent.appliedScaleY; int os1, os2, s2; if (psx < 0) { psx = -psx; os1 = 180; s2 = -1; } else { os1 = 0; s2 = 1; } if (psy < 0) { psy = -psy; s2 = -s2; } float cx = child.x, cy = child.y, csx = child.appliedScaleX; bool u = Math.Abs(psx - psy) <= 0.0001f; if (!u && cy != 0) { child.worldX = parent.a * cx + parent.worldX; child.worldY = parent.c * cx + parent.worldY; cy = 0; } if (csx < 0) { csx = -csx; os2 = 180; } 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 l1 = (float)Math.Sqrt(dx * dx + dy * dy), l2 = child.data.length * csx, a1, a2; if (u) { l2 *= psx; float cos = (tx * tx + ty * ty - l1 * l1 - l2 * l2) / (2 * l1 * l2); if (cos < -1) { cos = -1; } else if (cos > 1) { cos = 1; } a2 = (float)Math.Acos(cos) * bendDir; float a = l1 + l2 * cos, o = l2 * MathUtils.Sin(a2); a1 = MathUtils.Atan2(ty * a - tx * o, tx * a + ty * o); } else { float a = psx * l2, b = psy * l2, ta = MathUtils.Atan2(ty, tx); float aa = a * a, bb = b * b, ll = l1 * l1, dd = tx * tx + ty * ty; float c0 = bb * ll + aa * dd - aa * bb, c1 = -2 * bb * l1, c2 = bb - aa; float d = c1 * c1 - 4 * c2 * c0; if (d >= 0) { float q = (float)Math.Sqrt(d); if (c1 < 0) { q = -q; } q = -(c1 + q) / 2; float r0 = q / c2, r1 = c0 / q; float r = Math.Abs(r0) < Math.Abs(r1) ? r0 : r1; if (r * r <= dd) { float y1 = (float)Math.Sqrt(dd - r * r) * bendDir; a1 = ta - MathUtils.Atan2(y1, r); a2 = MathUtils.Atan2(y1 / psy, (r - l1) / psx); goto outer; } } float minAngle = 0, minDist = float.MaxValue, minX = 0, minY = 0; float maxAngle = 0, maxDist = 0, maxX = 0, maxY = 0; float x = l1 + a, dist = x * x; if (dist > maxDist) { maxAngle = 0; maxDist = dist; maxX = x; } x = l1 - a; dist = x * x; if (dist < minDist) { minAngle = MathUtils.PI; minDist = dist; minX = x; } float angle = (float)Math.Acos(-a * l1 / (aa - bb)); x = a * MathUtils.Cos(angle) + l1; float y = b * MathUtils.Sin(angle); dist = x * x + y * y; if (dist < minDist) { minAngle = angle; minDist = dist; minX = x; minY = y; } if (dist > maxDist) { maxAngle = angle; maxDist = dist; maxX = x; maxY = y; } if (dd <= (minDist + maxDist) / 2) { a1 = ta - MathUtils.Atan2(minY * bendDir, minX); a2 = minAngle * bendDir; } else { a1 = ta - MathUtils.Atan2(maxY * bendDir, maxX); a2 = maxAngle * bendDir; } } outer: float os = MathUtils.Atan2(cy, cx) * s2; a1 = (a1 - os) * MathUtils.radDeg + os1; a2 = (a2 + os) * MathUtils.radDeg * s2 + os2; if (a1 > 180) { a1 -= 360; } else if (a1 < -180) { a1 += 360; } if (a2 > 180) { a2 -= 360; } else if (a2 < -180) { a2 += 360; } float rotation = parent.rotation; parent.UpdateWorldTransform(px, py, rotation + (a1 - rotation) * alpha, parent.appliedScaleX, parent.appliedScaleY); rotation = child.rotation; child.UpdateWorldTransform(cx, cy, rotation + (a2 - rotation) * alpha, child.appliedScaleX, child.appliedScaleY); }
public static void Apply(Bone parent, Bone child, float targetX, float targetY, int bendDir, float alpha) { int num6; int num7; int num8; float num10; float num11; float num12; float num26; float num27; float num47; if (alpha == 0f) { child.UpdateWorldTransform(); return; } if (!parent.appliedValid) { parent.UpdateAppliedTransform(); } if (!child.appliedValid) { child.UpdateAppliedTransform(); } float ax = parent.ax; float ay = parent.ay; float ascaleX = parent.ascaleX; float ascaleY = parent.ascaleY; float num5 = child.ascaleX; if (ascaleX < 0f) { ascaleX = -ascaleX; num6 = 180; num8 = -1; } else { num6 = 0; num8 = 1; } if (ascaleY < 0f) { ascaleY = -ascaleY; num8 = -num8; } if (num5 < 0f) { num5 = -num5; num7 = 180; } else { num7 = 0; } float x = child.ax; float a = parent.a; float b = parent.b; float c = parent.c; float d = parent.d; bool flag = Math.Abs((float)(ascaleX - ascaleY)) <= 0.0001f; if (!flag) { num10 = 0f; num11 = (a * x) + parent.worldX; num12 = (c * x) + parent.worldY; } else { num10 = child.ay; num11 = ((a * x) + (b * num10)) + parent.worldX; num12 = ((c * x) + (d * num10)) + parent.worldY; } Bone bone = parent.parent; a = bone.a; b = bone.b; c = bone.c; d = bone.d; float num17 = 1f / ((a * d) - (b * c)); float num18 = targetX - bone.worldX; float num19 = targetY - bone.worldY; float num20 = (((num18 * d) - (num19 * b)) * num17) - ax; float num21 = (((num19 * a) - (num18 * c)) * num17) - ay; num18 = num11 - bone.worldX; num19 = num12 - bone.worldY; float num22 = (((num18 * d) - (num19 * b)) * num17) - ax; float num23 = (((num19 * a) - (num18 * c)) * num17) - ay; float num24 = (float)Math.Sqrt((double)((num22 * num22) + (num23 * num23))); float num25 = child.data.length * num5; if (flag) { num25 *= ascaleX; float num28 = ((((num20 * num20) + (num21 * num21)) - (num24 * num24)) - (num25 * num25)) / ((2f * num24) * num25); if (num28 < -1f) { num28 = -1f; } else if (num28 > 1f) { num28 = 1f; } num27 = ((float)Math.Acos((double)num28)) * bendDir; a = num24 + (num25 * num28); b = num25 * ((float)Math.Sin((double)num27)); num26 = (float)Math.Atan2((double)((num21 * a) - (num20 * b)), (double)((num20 * a) + (num21 * b))); } else { a = ascaleX * num25; b = ascaleY * num25; float num29 = a * a; float num30 = b * b; float num31 = (num20 * num20) + (num21 * num21); float num32 = (float)Math.Atan2((double)num21, (double)num20); c = (((num30 * num24) * num24) + (num29 * num31)) - (num29 * num30); float num33 = (-2f * num30) * num24; float num34 = num30 - num29; d = (num33 * num33) - ((4f * num34) * c); if (d >= 0f) { float num35 = (float)Math.Sqrt((double)d); if (num33 < 0f) { num35 = -num35; } num35 = -(num33 + num35) / 2f; float num36 = num35 / num34; float num37 = c / num35; float num38 = (Math.Abs(num36) >= Math.Abs(num37)) ? num37 : num36; if ((num38 * num38) <= num31) { num19 = ((float)Math.Sqrt((double)(num31 - (num38 * num38)))) * bendDir; num26 = num32 - ((float)Math.Atan2((double)num19, (double)num38)); num27 = (float)Math.Atan2((double)(num19 / ascaleY), (double)((num38 - num24) / ascaleX)); goto Label_0504; } } float num39 = 3.141593f; float num40 = num24 - a; float num41 = num40 * num40; float num42 = 0f; float num43 = 0f; float num44 = num24 + a; float num45 = num44 * num44; float num46 = 0f; c = (-a * num24) / (num29 - num30); if ((c >= -1f) && (c <= 1f)) { c = (float)Math.Acos((double)c); num18 = (a * ((float)Math.Cos((double)c))) + num24; num19 = b * ((float)Math.Sin((double)c)); d = (num18 * num18) + (num19 * num19); if (d < num41) { num39 = c; num41 = d; num40 = num18; num42 = num19; } if (d > num45) { num43 = c; num45 = d; num44 = num18; num46 = num19; } } if (num31 <= ((num41 + num45) / 2f)) { num26 = num32 - ((float)Math.Atan2((double)(num42 * bendDir), (double)num40)); num27 = num39 * bendDir; } else { num26 = num32 - ((float)Math.Atan2((double)(num46 * bendDir), (double)num44)); num27 = num43 * bendDir; } } Label_0504: num47 = ((float)Math.Atan2((double)num10, (double)x)) * num8; float arotation = parent.arotation; num26 = (((num26 - num47) * 57.29578f) + num6) - arotation; if (num26 > 180f) { num26 -= 360f; } else if (num26 < -180f) { num26 += 360f; } parent.UpdateWorldTransform(ax, ay, arotation + (num26 * alpha), parent.scaleX, parent.ascaleY, 0f, 0f); arotation = child.arotation; num27 = (((((num27 + num47) * 57.29578f) - child.ashearX) * num8) + num7) - arotation; if (num27 > 180f) { num27 -= 360f; } else if (num27 < -180f) { num27 += 360f; } child.UpdateWorldTransform(x, num10, arotation + (num27 * alpha), child.ascaleX, child.ascaleY, child.ashearX, child.ashearY); }
/// <summary>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.</summary> /// <param name="child">A direct descendant of the parent bone.</param> static public void Apply(Bone parent, Bone child, float targetX, float targetY, int bendDir, float alpha) { if (alpha == 0) { child.UpdateWorldTransform(); return; } //float px = parent.x, py = parent.y, psx = parent.scaleX, psy = parent.scaleY, csx = child.scaleX; if (!parent.appliedValid) { parent.UpdateAppliedTransform(); } if (!child.appliedValid) { child.UpdateAppliedTransform(); } float px = parent.ax, py = parent.ay, psx = parent.ascaleX, psy = parent.ascaleY, csx = child.ascaleX; int os1, os2, s2; if (psx < 0) { psx = -psx; os1 = 180; s2 = -1; } else { os1 = 0; s2 = 1; } if (psy < 0) { psy = -psy; s2 = -s2; } if (csx < 0) { csx = -csx; os2 = 180; } else { os2 = 0; } float cx = child.ax, cy, cwx, cwy, a = parent.a, b = parent.b, c = parent.c, d = parent.d; bool u = Math.Abs(psx - psy) <= 0.0001f; if (!u) { cy = 0; cwx = a * cx + parent.worldX; cwy = c * cx + parent.worldY; } else { cy = child.ay; cwx = a * cx + b * cy + parent.worldX; cwy = c * cx + d * cy + parent.worldY; } Bone pp = parent.parent; a = pp.a; b = pp.b; c = pp.c; d = pp.d; float id = 1 / (a * d - b * c), x = targetX - pp.worldX, y = targetY - pp.worldY; float tx = (x * d - y * b) * id - px, ty = (y * a - x * c) * id - py; x = cwx - pp.worldX; y = cwy - pp.worldY; float dx = (x * d - y * b) * id - px, dy = (y * a - x * c) * id - py; float l1 = (float)Math.Sqrt(dx * dx + dy * dy), l2 = child.data.length * csx, a1, a2; if (u) { l2 *= psx; float cos = (tx * tx + ty * ty - l1 * l1 - l2 * l2) / (2 * l1 * l2); if (cos < -1) { cos = -1; } else if (cos > 1) { cos = 1; } a2 = (float)Math.Acos(cos) * bendDir; a = l1 + l2 * cos; b = l2 * (float)Math.Sin(a2); a1 = (float)Math.Atan2(ty * a - tx * b, tx * a + ty * b); } else { a = psx * l2; b = psy * l2; float aa = a * a, bb = b * b, dd = tx * tx + ty * ty, ta = (float)Math.Atan2(ty, tx); c = bb * l1 * l1 + aa * dd - aa * bb; float c1 = -2 * bb * l1, c2 = bb - aa; d = c1 * c1 - 4 * c2 * c; if (d >= 0) { float q = (float)Math.Sqrt(d); if (c1 < 0) { q = -q; } q = -(c1 + q) / 2; float r0 = q / c2, r1 = c / q; float r = Math.Abs(r0) < Math.Abs(r1) ? r0 : r1; if (r * r <= dd) { y = (float)Math.Sqrt(dd - r * r) * bendDir; a1 = ta - (float)Math.Atan2(y, r); a2 = (float)Math.Atan2(y / psy, (r - l1) / psx); goto break_outer; // break outer; } } float minAngle = MathUtils.PI, minX = l1 - a, minDist = minX * minX, minY = 0; float maxAngle = 0, maxX = l1 + a, maxDist = maxX * maxX, maxY = 0; c = -a * l1 / (aa - bb); if (c >= -1 && c <= 1) { c = (float)Math.Acos(c); x = a * (float)Math.Cos(c) + l1; y = b * (float)Math.Sin(c); d = x * x + y * y; if (d < minDist) { minAngle = c; minDist = d; minX = x; minY = y; } if (d > maxDist) { maxAngle = c; maxDist = d; maxX = x; maxY = y; } } if (dd <= (minDist + maxDist) / 2) { a1 = ta - (float)Math.Atan2(minY * bendDir, minX); a2 = minAngle * bendDir; } else { a1 = ta - (float)Math.Atan2(maxY * bendDir, maxX); a2 = maxAngle * bendDir; } } break_outer: float os = (float)Math.Atan2(cy, cx) * s2; float rotation = parent.arotation; a1 = (a1 - os) * MathUtils.RadDeg + os1 - rotation; if (a1 > 180) { a1 -= 360; } else if (a1 < -180) { a1 += 360; } parent.UpdateWorldTransform(px, py, rotation + a1 * alpha, parent.scaleX, parent.ascaleY, 0, 0); rotation = child.arotation; a2 = ((a2 + os) * MathUtils.RadDeg - child.ashearX) * s2 + os2 - rotation; 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); }
/// <summary>Applies 1 bone IK. The target is specified in the world coordinate system.</summary> static public void Apply(Bone bone, float targetX, float targetY, bool compress, bool stretch, bool uniform, float alpha) { if (!bone.appliedValid) { bone.UpdateAppliedTransform(); } Bone p = bone.parent; float pa = p.a, pb = p.b, pc = p.c, pd = p.d; float rotationIK = -bone.ashearX - bone.arotation; float tx = 0, ty = 0; switch (bone.data.transformMode) { case TransformMode.OnlyTranslation: tx = targetX - bone.worldX; ty = targetY - bone.worldY; break; case TransformMode.NoRotationOrReflection: { rotationIK += (float)Math.Atan2(pc, pa) * MathUtils.RadDeg; float ps = Math.Abs(pa * pd - pb * pc) / (pa * pa + pc * pc); pb = -pc * ps; pd = pa * ps; float x = targetX - p.worldX, y = targetY - p.worldY; float d = pa * pd - pb * pc; tx = (x * pd - y * pb) / d - bone.ax; ty = (y * pa - x * pc) / d - bone.ay; break; } default: { float x = targetX - p.worldX, y = targetY - p.worldY; float d = pa * pd - pb * pc; tx = (x * pd - y * pb) / d - bone.ax; ty = (y * pa - x * pc) / d - bone.ay; break; } } rotationIK += (float)Math.Atan2(ty, tx) * MathUtils.RadDeg; if (bone.ascaleX < 0) { rotationIK += 180; } if (rotationIK > 180) { rotationIK -= 360; } else if (rotationIK < -180) // { rotationIK += 360; } float sx = bone.ascaleX, sy = bone.ascaleY; if (compress || stretch) { switch (bone.data.transformMode) { case TransformMode.NoScale: tx = targetX - bone.worldX; ty = targetY - bone.worldY; break; case TransformMode.NoScaleOrReflection: tx = targetX - bone.worldX; ty = targetY - bone.worldY; break; } float b = bone.data.length * sx, dd = (float)Math.Sqrt(tx * tx + ty * ty); if ((compress && dd < b) || (stretch && dd > b) && b > 0.0001f) { float s = (dd / b - 1) * alpha + 1; sx *= s; if (uniform) { sy *= s; } } } bone.UpdateWorldTransform(bone.ax, bone.ay, bone.arotation + rotationIK * alpha, sx, sy, bone.ashearX, bone.ashearY); }
static Bone GetExtractionBone () { if (extractionBone != null) return extractionBone; SkeletonData skelData = new SkeletonData(); BoneData data = new BoneData("temp", null); data.ScaleX = 1; data.ScaleY = 1; data.Length = 100; skelData.Bones.Add(data); Skeleton skeleton = new Skeleton(skelData); Bone bone = new Bone(data, skeleton, null); bone.UpdateWorldTransform(); extractionBone = bone; return extractionBone; }
/// <summary>Applies 2 bone IK. The target is specified in the world coordinate system.</summary> /// <param name="child">A direct descendant of the parent bone.</param> static public void Apply(Bone parent, Bone child, float targetX, float targetY, int bendDir, bool stretch, bool uniform, float softness, float alpha) { if (parent == null) { throw new ArgumentNullException("parent", "parent cannot be null."); } if (child == null) { throw new ArgumentNullException("child", "child cannot be null."); } float px = parent.ax, py = parent.ay, psx = parent.ascaleX, psy = parent.ascaleY, sx = psx, sy = psy, csx = child.ascaleX; int os1, os2, s2; if (psx < 0) { psx = -psx; os1 = 180; s2 = -1; } else { os1 = 0; s2 = 1; } if (psy < 0) { psy = -psy; s2 = -s2; } if (csx < 0) { csx = -csx; os2 = 180; } else { os2 = 0; } float cx = child.ax, cy, cwx, cwy, a = parent.a, b = parent.b, c = parent.c, d = parent.d; bool u = Math.Abs(psx - psy) <= 0.0001f; if (!u || stretch) { cy = 0; cwx = a * cx + parent.worldX; cwy = c * cx + parent.worldY; } else { cy = child.ay; cwx = a * cx + b * cy + parent.worldX; cwy = c * cx + d * cy + parent.worldY; } Bone pp = parent.parent; a = pp.a; b = pp.b; c = pp.c; d = pp.d; float id = 1 / (a * d - b * c), x = cwx - pp.worldX, y = cwy - pp.worldY; float dx = (x * d - y * b) * id - px, dy = (y * a - x * c) * id - py; float l1 = (float)Math.Sqrt(dx * dx + dy * dy), l2 = child.data.length * csx, a1, a2; if (l1 < 0.0001f) { Apply(parent, targetX, targetY, false, stretch, false, alpha); child.UpdateWorldTransform(cx, cy, 0, child.ascaleX, child.ascaleY, child.ashearX, child.ashearY); return; } x = targetX - pp.worldX; y = targetY - pp.worldY; float tx = (x * d - y * b) * id - px, ty = (y * a - x * c) * id - py; float dd = tx * tx + ty * ty; if (softness != 0) { softness *= psx * (csx + 1) * 0.5f; float td = (float)Math.Sqrt(dd), sd = td - l1 - l2 * psx + softness; if (sd > 0) { float p = Math.Min(1, sd / (softness * 2)) - 1; p = (sd - softness * (1 - p * p)) / td; tx -= p * tx; ty -= p * ty; dd = tx * tx + ty * ty; } } if (u) { l2 *= psx; float cos = (dd - l1 * l1 - l2 * l2) / (2 * l1 * l2); if (cos < -1) { cos = -1; a2 = MathUtils.PI * bendDir; } else if (cos > 1) { cos = 1; a2 = 0; if (stretch) { a = ((float)Math.Sqrt(dd) / (l1 + l2) - 1) * alpha + 1; sx *= a; if (uniform) { sy *= a; } } } else { a2 = (float)Math.Acos(cos) * bendDir; } a = l1 + l2 * cos; b = l2 * (float)Math.Sin(a2); a1 = (float)Math.Atan2(ty * a - tx * b, tx * a + ty * b); } else { a = psx * l2; b = psy * l2; float aa = a * a, bb = b * b, ta = (float)Math.Atan2(ty, tx); c = bb * l1 * l1 + aa * dd - aa * bb; float c1 = -2 * bb * l1, c2 = bb - aa; d = c1 * c1 - 4 * c2 * c; if (d >= 0) { float q = (float)Math.Sqrt(d); if (c1 < 0) { q = -q; } q = -(c1 + q) * 0.5f; float r0 = q / c2, r1 = c / q; float r = Math.Abs(r0) < Math.Abs(r1) ? r0 : r1; if (r * r <= dd) { y = (float)Math.Sqrt(dd - r * r) * bendDir; a1 = ta - (float)Math.Atan2(y, r); a2 = (float)Math.Atan2(y / psy, (r - l1) / psx); goto break_outer; // break outer; } } float minAngle = MathUtils.PI, minX = l1 - a, minDist = minX * minX, minY = 0; float maxAngle = 0, maxX = l1 + a, maxDist = maxX * maxX, maxY = 0; c = -a * l1 / (aa - bb); if (c >= -1 && c <= 1) { c = (float)Math.Acos(c); x = a * (float)Math.Cos(c) + l1; y = b * (float)Math.Sin(c); d = x * x + y * y; if (d < minDist) { minAngle = c; minDist = d; minX = x; minY = y; } if (d > maxDist) { maxAngle = c; maxDist = d; maxX = x; maxY = y; } } if (dd <= (minDist + maxDist) * 0.5f) { a1 = ta - (float)Math.Atan2(minY * bendDir, minX); a2 = minAngle * bendDir; } else { a1 = ta - (float)Math.Atan2(maxY * bendDir, maxX); a2 = maxAngle * bendDir; } } break_outer: float os = (float)Math.Atan2(cy, cx) * s2; float rotation = parent.arotation; a1 = (a1 - os) * MathUtils.RadDeg + os1 - rotation; if (a1 > 180) { a1 -= 360; } else if (a1 < -180) { a1 += 360; } parent.UpdateWorldTransform(px, py, rotation + a1 * alpha, sx, sy, 0, 0); rotation = child.arotation; a2 = ((a2 + os) * MathUtils.RadDeg - child.ashearX) * s2 + os2 - rotation; 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); }
/// <summary>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.</summary> /// <param name="child">A direct descendant of the parent bone.</param> static public void Apply (Bone parent, Bone child, float targetX, float targetY, int bendDir, float alpha) { if (alpha == 0) { child.UpdateWorldTransform (); return; } float px = parent.x, py = parent.y, psx = parent.scaleX, psy = parent.scaleY, csx = child.scaleX; int os1, os2, s2; if (psx < 0) { psx = -psx; os1 = 180; s2 = -1; } else { os1 = 0; s2 = 1; } if (psy < 0) { psy = -psy; s2 = -s2; } if (csx < 0) { csx = -csx; os2 = 180; } else os2 = 0; float cx = child.x, cy, cwx, cwy, a = parent.a, b = parent.b, c = parent.c, d = parent.d; bool u = Math.Abs(psx - psy) <= 0.0001f; if (!u) { cy = 0; cwx = a * cx + parent.worldX; cwy = c * cx + parent.worldY; } else { cy = child.y; cwx = a * cx + b * cy + parent.worldX; cwy = c * cx + d * cy + parent.worldY; } Bone pp = parent.parent; a = pp.a; b = pp.b; c = pp.c; d = pp.d; float id = 1 / (a * d - b * c), x = targetX - pp.worldX, y = targetY - pp.worldY; float tx = (x * d - y * b) * id - px, ty = (y * a - x * c) * id - py; x = cwx - pp.worldX; y = cwy - pp.worldY; float dx = (x * d - y * b) * id - px, dy = (y * a - x * c) * id - py; float l1 = (float)Math.Sqrt(dx * dx + dy * dy), l2 = child.data.length * csx, a1, a2; if (u) { l2 *= psx; float cos = (tx * tx + ty * ty - l1 * l1 - l2 * l2) / (2 * l1 * l2); if (cos < -1) cos = -1; else if (cos > 1) cos = 1; a2 = (float)Math.Acos(cos) * bendDir; a = l1 + l2 * cos; b = l2 * MathUtils.Sin(a2); a1 = MathUtils.Atan2(ty * a - tx * b, tx * a + ty * b); } else { a = psx * l2; b = psy * l2; float aa = a * a, bb = b * b, dd = tx * tx + ty * ty, ta = MathUtils.Atan2(ty, tx); c = bb * l1 * l1 + aa * dd - aa * bb; float c1 = -2 * bb * l1, c2 = bb - aa; d = c1 * c1 - 4 * c2 * c; if (d >= 0) { float q = (float)Math.Sqrt(d); if (c1 < 0) q = -q; q = -(c1 + q) / 2; float r0 = q / c2, r1 = c / q; float r = Math.Abs(r0) < Math.Abs(r1) ? r0 : r1; if (r * r <= dd) { y = (float)Math.Sqrt(dd - r * r) * bendDir; a1 = ta - MathUtils.Atan2(y, r); a2 = MathUtils.Atan2(y / psy, (r - l1) / psx); goto outer; } } float minAngle = 0, minDist = float.MaxValue, minX = 0, minY = 0; float maxAngle = 0, maxDist = 0, maxX = 0, maxY = 0; x = l1 + a; d = x * x; if (d > maxDist) { maxAngle = 0; maxDist = d; maxX = x; } x = l1 - a; d = x * x; if (d < minDist) { minAngle = MathUtils.PI; minDist = d; minX = x; } float angle = (float)Math.Acos(-a * l1 / (aa - bb)); x = a * MathUtils.Cos(angle) + l1; y = b * MathUtils.Sin(angle); d = x * x + y * y; if (d < minDist) { minAngle = angle; minDist = d; minX = x; minY = y; } if (d > maxDist) { maxAngle = angle; maxDist = d; maxX = x; maxY = y; } if (dd <= (minDist + maxDist) / 2) { a1 = ta - MathUtils.Atan2(minY * bendDir, minX); a2 = minAngle * bendDir; } else { a1 = ta - MathUtils.Atan2(maxY * bendDir, maxX); a2 = maxAngle * bendDir; } } outer: float os = MathUtils.Atan2(cy, cx) * s2; float rotation = parent.rotation; a1 = (a1 - os) * MathUtils.radDeg + os1 - rotation; if (a1 > 180) a1 -= 360; else if (a1 < -180) a1 += 360; parent.UpdateWorldTransform(px, py, rotation + a1 * alpha, parent.scaleX, parent.scaleY, 0, 0); rotation = child.rotation; a2 = ((a2 + os) * MathUtils.radDeg - child.shearX) * s2 + os2 - rotation; if (a2 > 180) a2 -= 360; else if (a2 < -180) a2 += 360; child.UpdateWorldTransform(cx, cy, rotation + a2 * alpha, child.scaleX, child.scaleY, child.shearX, child.shearY); }
/// <summary>Applies 1 bone IK. The target is specified in the world coordinate system.</summary> static public void Apply(Bone bone, float targetX, float targetY, bool compress, bool stretch, bool uniform, float alpha) { if (bone == null) { throw new ArgumentNullException("bone", "bone cannot be null."); } Bone p = bone.parent; float pa = p.a, pb = p.b, pc = p.c, pd = p.d; float rotationIK = -bone.ashearX - bone.arotation; float tx = 0, ty = 0; switch (bone.data.transformMode) { case TransformMode.OnlyTranslation: tx = targetX - bone.worldX; ty = targetY - bone.worldY; break; case TransformMode.NoRotationOrReflection: { float s = Math.Abs(pa * pd - pb * pc) / (pa * pa + pc * pc); float sa = pa / bone.skeleton.ScaleX; float sc = pc / bone.skeleton.ScaleY; pb = -sc * s * bone.skeleton.ScaleX; pd = sa * s * bone.skeleton.ScaleY; rotationIK += (float)Math.Atan2(sc, sa) * MathUtils.RadDeg; goto default; // Fall through. } default: { float x = targetX - p.worldX, y = targetY - p.worldY; float d = pa * pd - pb * pc; tx = (x * pd - y * pb) / d - bone.ax; ty = (y * pa - x * pc) / d - bone.ay; break; } } rotationIK += (float)Math.Atan2(ty, tx) * MathUtils.RadDeg; if (bone.ascaleX < 0) { rotationIK += 180; } if (rotationIK > 180) { rotationIK -= 360; } else if (rotationIK < -180) // { rotationIK += 360; } float sx = bone.ascaleX, sy = bone.ascaleY; if (compress || stretch) { switch (bone.data.transformMode) { case TransformMode.NoScale: case TransformMode.NoScaleOrReflection: tx = targetX - bone.worldX; ty = targetY - bone.worldY; break; } float b = bone.data.length * sx, dd = (float)Math.Sqrt(tx * tx + ty * ty); if ((compress && dd < b) || (stretch && dd > b) && b > 0.0001f) { float s = (dd / b - 1) * alpha + 1; sx *= s; if (uniform) { sy *= s; } } } bone.UpdateWorldTransform(bone.ax, bone.ay, bone.arotation + rotationIK * alpha, sx, sy, bone.ashearX, bone.ashearY); }
private void ApplyAbsoluteLocal() { float rotateMix = this.rotateMix; float translateMix = this.translateMix; float scaleMix = this.scaleMix; float shearMix = this.shearMix; Bone target = this.target; if (!target.appliedValid) { target.UpdateAppliedTransform(); } Bone[] items = this.bones.Items; int index = 0; int count = this.bones.Count; while (index < count) { Bone bone2 = items[index]; if (!bone2.appliedValid) { bone2.UpdateAppliedTransform(); } float arotation = bone2.arotation; if (rotateMix != 0f) { float num8 = (target.arotation - arotation) + this.data.offsetRotation; num8 -= (0x4000 - ((int)(16384.499999999996 - (num8 / 360f)))) * 360; arotation += num8 * rotateMix; } float ax = bone2.ax; float ay = bone2.ay; if (translateMix != 0f) { ax += ((target.ax - ax) + this.data.offsetX) * translateMix; ay += ((target.ay - ay) + this.data.offsetY) * translateMix; } float ascaleX = bone2.ascaleX; float ascaleY = bone2.ascaleY; if (scaleMix > 0f) { if (ascaleX > 1E-05f) { ascaleX = (ascaleX + (((target.ascaleX - ascaleX) + this.data.offsetScaleX) * scaleMix)) / ascaleX; } if (ascaleY > 1E-05f) { ascaleY = (ascaleY + (((target.ascaleY - ascaleY) + this.data.offsetScaleY) * scaleMix)) / ascaleY; } } float ashearY = bone2.ashearY; if (shearMix > 0f) { float num14 = (target.ashearY - ashearY) + this.data.offsetShearY; num14 -= (0x4000 - ((int)(16384.499999999996 - (num14 / 360f)))) * 360; bone2.shearY += num14 * shearMix; } bone2.UpdateWorldTransform(ax, ay, arotation, ascaleX, ascaleY, bone2.ashearX, ashearY); index++; } }
/// <summary>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.</summary> static public void Apply (Bone bone, float targetX, float targetY, float alpha) { 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 = MathUtils.Atan2(ty, tx) * MathUtils.radDeg - bone.shearX - bone.rotation; if (bone.scaleX < 0) rotationIK += 180; if (rotationIK > 180) rotationIK -= 360; else if (rotationIK < -180) rotationIK += 360; bone.UpdateWorldTransform(bone.x, bone.y, bone.rotation + rotationIK * alpha, bone.scaleX, bone.scaleY, bone.shearX, bone.shearY); }
/// <summary>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.</summary> /// <param name="child">A direct descendant of the parent bone.</param> static public void Apply (Bone parent, Bone child, float targetX, float targetY, int bendDir, float alpha) { if (alpha == 0) return; float px = parent.x, py = parent.y, psx = parent.scaleX, psy = parent.scaleY, csx = child.scaleX, cy = child.y; int offset1, offset2, sign2; if (psx < 0) { psx = -psx; offset1 = 180; sign2 = -1; } else { offset1 = 0; sign2 = 1; } if (psy < 0) { psy = -psy; sign2 = -sign2; } if (csx < 0) { csx = -csx; offset2 = 180; } else offset2 = 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 l1 = (float)Math.Sqrt(dx * dx + dy * dy), l2 = child.data.length * csx, a1, a2; if (Math.Abs(psx - psy) <= 0.0001f) { l2 *= psx; float cos = (tx * tx + ty * ty - l1 * l1 - l2 * l2) / (2 * l1 * l2); if (cos < -1) cos = -1; else if (cos > 1) cos = 1; a2 = (float)Math.Acos(cos) * bendDir; float a = l1 + l2 * cos, o = l2 * MathUtils.Sin(a2); a1 = MathUtils.Atan2(ty * a - tx * o, tx * a + ty * o); } else { cy = 0; float a = psx * l2, b = psy * l2, ta = MathUtils.Atan2(ty, tx); float aa = a * a, bb = b * b, ll = l1 * l1, dd = tx * tx + ty * ty; float c0 = bb * ll + aa * dd - aa * bb, c1 = -2 * bb * l1, c2 = bb - aa; float d = c1 * c1 - 4 * c2 * c0; if (d >= 0) { float q = (float)Math.Sqrt(d); if (c1 < 0) q = -q; q = -(c1 + q) / 2; float r0 = q / c2, r1 = c0 / q; float r = Math.Abs(r0) < Math.Abs(r1) ? r0 : r1; if (r * r <= dd) { float y1 = (float)Math.Sqrt(dd - r * r) * bendDir; a1 = ta - MathUtils.Atan2(y1, r); a2 = MathUtils.Atan2(y1 / psy, (r - l1) / psx); goto outer; } } float minAngle = 0, minDist = float.MaxValue, minX = 0, minY = 0; float maxAngle = 0, maxDist = 0, maxX = 0, maxY = 0; float x = l1 + a, dist = x * x; if (dist > maxDist) { maxAngle = 0; maxDist = dist; maxX = x; } x = l1 - a; dist = x * x; if (dist < minDist) { minAngle = MathUtils.PI; minDist = dist; minX = x; } float angle = (float)Math.Acos(-a * l1 / (aa - bb)); x = a * MathUtils.Cos(angle) + l1; float y = b * MathUtils.Sin(angle); dist = x * x + y * y; if (dist < minDist) { minAngle = angle; minDist = dist; minX = x; minY = y; } if (dist > maxDist) { maxAngle = angle; maxDist = dist; maxX = x; maxY = y; } if (dd <= (minDist + maxDist) / 2) { a1 = ta - MathUtils.Atan2(minY * bendDir, minX); a2 = minAngle * bendDir; } else { a1 = ta - MathUtils.Atan2(maxY * bendDir, maxX); a2 = maxAngle * bendDir; } } outer: float offset = MathUtils.Atan2(cy, child.x) * sign2; a1 = (a1 - offset) * MathUtils.radDeg + offset1; a2 = (a2 + offset) * MathUtils.radDeg * sign2 + offset2; if (a1 > 180) a1 -= 360; else if (a1 < -180) a1 += 360; if (a2 > 180) a2 -= 360; else if (a2 < -180) a2 += 360; float rotation = parent.rotation; parent.UpdateWorldTransform(parent.x, parent.y, rotation + (a1 - rotation) * alpha, parent.scaleX, parent.scaleY); rotation = child.rotation; child.UpdateWorldTransform(child.x, cy, rotation + (a2 - rotation) * alpha, child.scaleX, child.scaleY); }
public static void Apply(Bone parent, Bone child, float targetX, float targetY, int bendDir, float alpha) { if (alpha == 0f) { child.UpdateWorldTransform(); return; } float x = parent.x; float y = parent.y; float num = parent.scaleX; float num2 = parent.scaleY; float num3 = child.scaleX; int num4; int num5; if (num < 0f) { num = -num; num4 = 180; num5 = -1; } else { num4 = 0; num5 = 1; } if (num2 < 0f) { num2 = -num2; num5 = -num5; } int num6; if (num3 < 0f) { num3 = -num3; num6 = 180; } else { num6 = 0; } float x2 = child.x; float num7 = parent.a; float num8 = parent.b; float num9 = parent.c; float num10 = parent.d; bool flag = Math.Abs(num - num2) <= 0.0001f; float num11; float num12; float num13; if (!flag) { num11 = 0f; num12 = num7 * x2 + parent.worldX; num13 = num9 * x2 + parent.worldY; } else { num11 = child.y; num12 = num7 * x2 + num8 * num11 + parent.worldX; num13 = num9 * x2 + num10 * num11 + parent.worldY; } Bone parent2 = parent.parent; num7 = parent2.a; num8 = parent2.b; num9 = parent2.c; num10 = parent2.d; float num14 = 1f / (num7 * num10 - num8 * num9); float num15 = targetX - parent2.worldX; float num16 = targetY - parent2.worldY; float num17 = (num15 * num10 - num16 * num8) * num14 - x; float num18 = (num16 * num7 - num15 * num9) * num14 - y; num15 = num12 - parent2.worldX; num16 = num13 - parent2.worldY; float num19 = (num15 * num10 - num16 * num8) * num14 - x; float num20 = (num16 * num7 - num15 * num9) * num14 - y; float num21 = (float)Math.Sqrt((double)(num19 * num19 + num20 * num20)); float num22 = child.data.length * num3; float num24; float num25; if (flag) { num22 *= num; float num23 = (num17 * num17 + num18 * num18 - num21 * num21 - num22 * num22) / (2f * num21 * num22); if (num23 < -1f) { num23 = -1f; } else if (num23 > 1f) { num23 = 1f; } num24 = (float)Math.Acos((double)num23) * (float)bendDir; num7 = num21 + num22 * num23; num8 = num22 * MathUtils.Sin(num24); num25 = MathUtils.Atan2(num18 * num7 - num17 * num8, num17 * num7 + num18 * num8); } else { num7 = num * num22; num8 = num2 * num22; float num26 = num7 * num7; float num27 = num8 * num8; float num28 = num17 * num17 + num18 * num18; float num29 = MathUtils.Atan2(num18, num17); num9 = num27 * num21 * num21 + num26 * num28 - num26 * num27; float num30 = -2f * num27 * num21; float num31 = num27 - num26; num10 = num30 * num30 - 4f * num31 * num9; if (num10 >= 0f) { float num32 = (float)Math.Sqrt((double)num10); if (num30 < 0f) { num32 = -num32; } num32 = -(num30 + num32) / 2f; float num33 = num32 / num31; float num34 = num9 / num32; float num35 = (Math.Abs(num33) >= Math.Abs(num34)) ? num34 : num33; if (num35 * num35 <= num28) { num16 = (float)Math.Sqrt((double)(num28 - num35 * num35)) * (float)bendDir; num25 = num29 - MathUtils.Atan2(num16, num35); num24 = MathUtils.Atan2(num16 / num2, (num35 - num21) / num); goto IL_4FA; } } float num36 = 0f; float num37 = float.MaxValue; float x3 = 0f; float num38 = 0f; float num39 = 0f; float num40 = 0f; float x4 = 0f; float num41 = 0f; num15 = num21 + num7; num10 = num15 * num15; if (num10 > num40) { num39 = 0f; num40 = num10; x4 = num15; } num15 = num21 - num7; num10 = num15 * num15; if (num10 < num37) { num36 = 3.14159274f; num37 = num10; x3 = num15; } float num42 = (float)Math.Acos((double)(-(double)num7 * num21 / (num26 - num27))); num15 = num7 * MathUtils.Cos(num42) + num21; num16 = num8 * MathUtils.Sin(num42); num10 = num15 * num15 + num16 * num16; if (num10 < num37) { num36 = num42; num37 = num10; x3 = num15; num38 = num16; } if (num10 > num40) { num39 = num42; num40 = num10; x4 = num15; num41 = num16; } if (num28 <= (num37 + num40) / 2f) { num25 = num29 - MathUtils.Atan2(num38 * (float)bendDir, x3); num24 = num36 * (float)bendDir; } else { num25 = num29 - MathUtils.Atan2(num41 * (float)bendDir, x4); num24 = num39 * (float)bendDir; } } IL_4FA: float num43 = MathUtils.Atan2(num11, x2) * (float)num5; float rotation = parent.rotation; num25 = (num25 - num43) * 57.2957764f + (float)num4 - rotation; if (num25 > 180f) { num25 -= 360f; } else if (num25 < -180f) { num25 += 360f; } parent.UpdateWorldTransform(x, y, rotation + num25 * alpha, parent.scaleX, parent.scaleY, 0f, 0f); rotation = child.rotation; num24 = ((num24 + num43) * 57.2957764f - child.shearX) * (float)num5 + (float)num6 - rotation; if (num24 > 180f) { num24 -= 360f; } else if (num24 < -180f) { num24 += 360f; } child.UpdateWorldTransform(x2, num11, rotation + num24 * alpha, child.scaleX, child.scaleY, child.shearX, child.shearY); }