Pārlūkot izejas kodu

[c][cpp] Port IK constraint changes

See

https://github.com/EsotericSoftware/spine-runtimes/commit/33bce01feed1debd9cde6b7747a1aa2d07e00b02
https://github.com/EsotericSoftware/spine-runtimes/commit/f9862b10b373b8347c2b249d1086ef4049263153
badlogic 4 gadi atpakaļ
vecāks
revīzija
07d3633881

+ 1 - 1
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
 }

+ 27 - 17
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);
 	}
 }

+ 1 - 1
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);

+ 22 - 14
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;