[c][cpp] Port IK constraint changes

See

33bce01fee
f9862b10b3
This commit is contained in:
badlogic 2021-06-09 14:44:24 +02:00
parent 0544e14102
commit 07d3633881
4 changed files with 51 additions and 33 deletions

View File

@ -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
}

View File

@ -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);
}
}

View File

@ -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);

View File

@ -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;