From 07d3633881471b4bf22fd6b016d71fe4cf2a5740 Mon Sep 17 00:00:00 2001 From: badlogic Date: Wed, 9 Jun 2021 14:44:24 +0200 Subject: [PATCH] [c][cpp] Port IK constraint changes See https://github.com/EsotericSoftware/spine-runtimes/commit/33bce01feed1debd9cde6b7747a1aa2d07e00b02 https://github.com/EsotericSoftware/spine-runtimes/commit/f9862b10b373b8347c2b249d1086ef4049263153 --- spine-c/spine-c/include/spine/IkConstraint.h | 2 +- spine-c/spine-c/src/spine/IkConstraint.c | 44 ++++++++++++------- .../spine-cpp/include/spine/IkConstraint.h | 2 +- .../spine-cpp/src/spine/IkConstraint.cpp | 36 +++++++++------ 4 files changed, 51 insertions(+), 33 deletions(-) diff --git a/spine-c/spine-c/include/spine/IkConstraint.h b/spine-c/spine-c/include/spine/IkConstraint.h index eb657a926..83518697b 100644 --- a/spine-c/spine-c/include/spine/IkConstraint.h +++ b/spine-c/spine-c/include/spine/IkConstraint.h @@ -67,7 +67,7 @@ spIkConstraint_apply1(spBone *bone, float targetX, float targetY, int /*boolean* int /*boolean*/ uniform, float alpha); SP_API void spIkConstraint_apply2(spBone *parent, spBone *child, float targetX, float targetY, int bendDirection, - int /*boolean*/ stretch, float softness, float alpha); + int /*boolean*/ stretch, int /*boolean*/ uniform, float softness, float alpha); #ifdef __cplusplus } diff --git a/spine-c/spine-c/src/spine/IkConstraint.c b/spine-c/spine-c/src/spine/IkConstraint.c index 92b977e8e..176018839 100644 --- a/spine-c/spine-c/src/spine/IkConstraint.c +++ b/spine-c/spine-c/src/spine/IkConstraint.c @@ -66,7 +66,7 @@ void spIkConstraint_update(spIkConstraint *self) { break; case 2: spIkConstraint_apply2(self->bones[0], self->bones[1], self->target->worldX, self->target->worldY, - self->bendDirection, self->stretch, self->softness, self->mix); + self->bendDirection, self->stretch, self->data->uniform, self->softness, self->mix); break; } } @@ -128,9 +128,9 @@ spIkConstraint_apply1(spBone *bone, float targetX, float targetY, int /*boolean* void spIkConstraint_apply2(spBone *parent, spBone *child, float targetX, float targetY, int bendDir, int /*boolean*/ stretch, - float softness, float alpha) { + int /*boolean*/ uniform, float softness, float alpha) { float a, b, c, d; - float px, py, psx, sx, psy; + float px, py, psx, psy, sx, sy; float cx, cy, csx, cwx, cwy; int o1, o2, s2, u; spBone *pp = parent->parent; @@ -141,8 +141,9 @@ spIkConstraint_apply2(spBone *parent, spBone *child, float targetX, float target px = parent->ax; py = parent->ay; psx = parent->ascaleX; - sx = psx; psy = parent->ascaleY; + sx = psx; + sy = psy; csx = child->ascaleX; if (psx < 0) { psx = -psx; @@ -164,7 +165,7 @@ spIkConstraint_apply2(spBone *parent, spBone *child, float targetX, float target r = psx - psy; cx = child->ax; u = (r < 0 ? -r : r) <= 0.0001f; - if (!u) { + if (!u || stretch) { cy = 0; cwx = parent->a * cx + parent->worldX; cwy = parent->c * cx + parent->worldY; @@ -196,7 +197,7 @@ spIkConstraint_apply2(spBone *parent, spBone *child, float targetX, float target ty = (y * a - x * c) * id - py; dd = tx * tx + ty * ty; if (softness != 0) { - softness *= psx * (csx + 1) / 2; + softness *= psx * (csx + 1) * 0.5f; td = SQRT(dd); sd = td - l1 - l2 * psx + softness; if (sd > 0) { @@ -211,12 +212,19 @@ spIkConstraint_apply2(spBone *parent, spBone *child, float targetX, float target float cosine; l2 *= psx; cosine = (dd - l1 * l1 - l2 * l2) / (2 * l1 * l2); - if (cosine < -1) cosine = -1; - else if (cosine > 1) { + if (cosine < -1) { + cosine = -1; + a2 = PI * bendDir; + } else if (cosine > 1) { cosine = 1; - if (stretch) sx *= (SQRT(dd) / (l1 + l2) - 1) * alpha + 1; - } - a2 = ACOS(cosine) * bendDir; + a2 = 0; + if (stretch) { + a = (SQRT(dd) / (l1 + l2) - 1) * alpha + 1; + sx *= a; + if (uniform) sy *= a; + } + } else + a2 = ACOS(cosine) * bendDir; a = l1 + l2 * cosine; b = l2 * SIN(a2); a1 = ATAN2(ty * a - tx * b, tx * a + ty * b); @@ -229,7 +237,7 @@ spIkConstraint_apply2(spBone *parent, spBone *child, float targetX, float target if (d >= 0) { float q = SQRT(d), r0, r1; if (c1 < 0) q = -q; - q = -(c1 + q) / 2; + q = -(c1 + q) * 0.5f; r0 = q / c2; r1 = c0 / q; r = ABS(r0) < ABS(r1) ? r0 : r1; @@ -262,7 +270,7 @@ spIkConstraint_apply2(spBone *parent, spBone *child, float targetX, float target maxY = y; } } - if (dd <= (minDist + maxDist) / 2) { + if (dd <= (minDist + maxDist) * 0.5f) { a1 = ta - ATAN2(minY * bendDir, minX); a2 = minAngle * bendDir; } else { @@ -274,14 +282,16 @@ spIkConstraint_apply2(spBone *parent, spBone *child, float targetX, float target break_outer: { float os = ATAN2(cy, cx) * s2; - a1 = (a1 - os) * RAD_DEG + o1 - parent->arotation; + float rotation = parent->arotation; + a1 = (a1 - os) * RAD_DEG + o1 -rotation; if (a1 > 180) a1 -= 360; else if (a1 < -180) a1 += 360; - spBone_updateWorldTransformWith(parent, px, py, parent->arotation + a1 * alpha, sx, parent->ascaleY, 0, 0); - a2 = ((a2 + os) * RAD_DEG - child->ashearX) * s2 + o2 - child->arotation; + spBone_updateWorldTransformWith(parent, px, py, rotation + a1 * alpha, sx, sy, 0, 0); + rotation = child->arotation; + a2 = ((a2 + os) * RAD_DEG - child->ashearX) * s2 + o2 - rotation; if (a2 > 180) a2 -= 360; else if (a2 < -180) a2 += 360; - spBone_updateWorldTransformWith(child, cx, cy, child->arotation + a2 * alpha, child->ascaleX, child->ascaleY, + spBone_updateWorldTransformWith(child, cx, cy, rotation + a2 * alpha, child->ascaleX, child->ascaleY, child->ashearX, child->ashearY); } } diff --git a/spine-cpp/spine-cpp/include/spine/IkConstraint.h b/spine-cpp/spine-cpp/include/spine/IkConstraint.h index 8207bc63b..3e44b6377 100644 --- a/spine-cpp/spine-cpp/include/spine/IkConstraint.h +++ b/spine-cpp/spine-cpp/include/spine/IkConstraint.h @@ -58,7 +58,7 @@ namespace spine { /// possible. The target is specified in the world coordinate system. /// @param child A direct descendant of the parent bone. static void - apply(Bone &parent, Bone &child, float targetX, float targetY, int bendDir, bool stretch, float softness, + apply(Bone &parent, Bone &child, float targetX, float targetY, int bendDir, bool stretch, bool uniform, float softness, float alpha); IkConstraint(IkConstraintData &data, Skeleton &skeleton); diff --git a/spine-cpp/spine-cpp/src/spine/IkConstraint.cpp b/spine-cpp/spine-cpp/src/spine/IkConstraint.cpp index de9113eed..1bd752d6e 100644 --- a/spine-cpp/spine-cpp/src/spine/IkConstraint.cpp +++ b/spine-cpp/spine-cpp/src/spine/IkConstraint.cpp @@ -95,10 +95,10 @@ IkConstraint::apply(Bone &bone, float targetX, float targetY, bool compress, boo } void -IkConstraint::apply(Bone &parent, Bone &child, float targetX, float targetY, int bendDir, bool stretch, float softness, +IkConstraint::apply(Bone &parent, Bone &child, float targetX, float targetY, int bendDir, bool stretch, bool uniform, float softness, float alpha) { float a, b, c, d; - float px, py, psx, sx, psy; + float px, py, psx, psy, sx, sy; float cx, cy, csx, cwx, cwy; int o1, o2, s2, u; Bone *pp = parent.getParent(); @@ -107,8 +107,9 @@ IkConstraint::apply(Bone &parent, Bone &child, float targetX, float targetY, int px = parent._ax; py = parent._ay; psx = parent._ascaleX; - sx = psx; psy = parent._ascaleY; + sx = psx; + sy = psy; csx = child._ascaleX; if (psx < 0) { psx = -psx; @@ -130,7 +131,7 @@ IkConstraint::apply(Bone &parent, Bone &child, float targetX, float targetY, int r = psx - psy; cx = child._ax; u = (r < 0 ? -r : r) <= 0.0001f; - if (!u) { + if (!u || stretch) { cy = 0; cwx = parent._a * cx + parent._worldX; cwy = parent._c * cx + parent._worldY; @@ -160,7 +161,7 @@ IkConstraint::apply(Bone &parent, Bone &child, float targetX, float targetY, int tx = (x * d - y * b) * id - px, ty = (y * a - x * c) * id - py; dd = tx * tx + ty * ty; if (softness != 0) { - softness *= psx * (csx + 1) / 2; + softness *= psx * (csx + 1) * 0.5f; td = MathUtil::sqrt(dd), sd = td - l1 - l2 * psx + softness; if (sd > 0) { p = MathUtil::min(1.0f, sd / (softness * 2)) - 1; @@ -174,12 +175,19 @@ IkConstraint::apply(Bone &parent, Bone &child, float targetX, float targetY, int float cosine; l2 *= psx; cosine = (dd - l1 * l1 - l2 * l2) / (2 * l1 * l2); - if (cosine < -1) cosine = -1; - else if (cosine > 1) { + if (cosine < -1) { + cosine = -1; + a2 = MathUtil::Pi * bendDir; + } else if (cosine > 1) { cosine = 1; - if (stretch) sx *= (MathUtil::sqrt(dd) / (l1 + l2) - 1) * alpha + 1; - } - a2 = MathUtil::acos(cosine) * bendDir; + a2 = 0; + if (stretch) { + a = (MathUtil::sqrt(dd) / (l1 + l2) - 1) * alpha + 1; + sx *= a; + if (uniform) sy *= a; + } + } else + a2 = MathUtil::acos(cosine) * bendDir; a = l1 + l2 * cosine; b = l2 * MathUtil::sin(a2); a1 = MathUtil::atan2(ty * a - tx * b, tx * a + ty * b); @@ -191,7 +199,7 @@ IkConstraint::apply(Bone &parent, Bone &child, float targetX, float targetY, int if (d >= 0) { float q = MathUtil::sqrt(d), r0, r1; if (c1 < 0) q = -q; - q = -(c1 + q) / 2; + q = -(c1 + q) * 0.5f; r0 = q / c2; r1 = c0 / q; r = MathUtil::abs(r0) < MathUtil::abs(r1) ? r0 : r1; @@ -224,7 +232,7 @@ IkConstraint::apply(Bone &parent, Bone &child, float targetX, float targetY, int maxY = y; } } - if (dd <= (minDist + maxDist) / 2) { + if (dd <= (minDist + maxDist) * 0.5f) { a1 = ta - MathUtil::atan2(minY * bendDir, minX); a2 = minAngle * bendDir; } else { @@ -239,7 +247,7 @@ IkConstraint::apply(Bone &parent, Bone &child, float targetX, float targetY, int a1 = (a1 - os) * MathUtil::Rad_Deg + o1 - parent._arotation; if (a1 > 180) a1 -= 360; else if (a1 < -180) a1 += 360; - parent.updateWorldTransform(px, py, parent._arotation + a1 * alpha, sx, parent._ascaleY, 0, 0); + parent.updateWorldTransform(px, py, parent._arotation + a1 * alpha, sx, sy, 0, 0); a2 = ((a2 + os) * MathUtil::Rad_Deg - child._ashearX) * s2 + o2 - child._arotation; if (a2 > 180) a2 -= 360; else if (a2 < -180) a2 += 360; @@ -276,7 +284,7 @@ void IkConstraint::update() { case 2: { Bone *bone0 = _bones[0]; Bone *bone1 = _bones[1]; - apply(*bone0, *bone1, _target->getWorldX(), _target->getWorldY(), _bendDirection, _stretch, _softness, + apply(*bone0, *bone1, _target->getWorldX(), _target->getWorldY(), _bendDirection, _stretch, _data._uniform, _softness, _mix); } break;