Kaynağa Gözat

Refactoring bone transforms.

NathanSweet 9 yıl önce
ebeveyn
işleme
dfe8e3b826

+ 2 - 0
.gitignore

@@ -102,3 +102,5 @@ spine-starling/spine-starling-example/lib/.spine-starling.swc.stamp
 spine-turbulenz/spine-js/spine.js
 
 spine-threejs/spine-js/spine.js
+
+spine-ts/.vscode/*

+ 2 - 1
spine-libgdx/spine-libgdx/.settings/org.eclipse.jdt.core.prefs

@@ -33,7 +33,7 @@ org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
 org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
 org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled
 org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
-org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning
+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore
 org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
 org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
 org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
@@ -84,6 +84,7 @@ org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore
 org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
 org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
 org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=enabled
+org.eclipse.jdt.core.compiler.problem.unusedExceptionParameter=ignore
 org.eclipse.jdt.core.compiler.problem.unusedImport=warning
 org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
 org.eclipse.jdt.core.compiler.problem.unusedLocal=warning

+ 19 - 19
spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Animation.java

@@ -721,35 +721,33 @@ public class Animation {
 
 			// BOZO - Test.
 			if (alpha == 1) {
-				// Absolute.
+				// Vertex positions or deform offsets, no alpha.
 				for (int i = 0; i < vertexCount; i++) {
 					float prev = prevVertices[i];
 					vertices[i] = prev + (nextVertices[i] - prev) * percent;
 				}
-			} else {
-				if (setupPose) {
-					VertexAttachment vertexAttachment = (VertexAttachment)slotAttachment;
-					if (vertexAttachment.getBones() == null) {
-						// Vertex positions.
-						float[] setupVertices = vertexAttachment.getVertices();
-						for (int i = 0; i < vertexCount; i++) {
-							float prev = prevVertices[i], setup = setupVertices[i];
-							vertices[i] = setup + (prev + (nextVertices[i] - prev) * percent - setup) * alpha;
-						}
-					} else {
-						// Deform offsets.
-						for (int i = 0; i < vertexCount; i++) {
-							float prev = prevVertices[i];
-							vertices[i] = (prev + (nextVertices[i] - prev) * percent) * alpha;
-						}
+			} else if (setupPose) {
+				VertexAttachment vertexAttachment = (VertexAttachment)slotAttachment;
+				if (vertexAttachment.getBones() == null) {
+					// Unweighted vertex positions, with alpha.
+					float[] setupVertices = vertexAttachment.getVertices();
+					for (int i = 0; i < vertexCount; i++) {
+						float prev = prevVertices[i], setup = setupVertices[i];
+						vertices[i] = setup + (prev + (nextVertices[i] - prev) * percent - setup) * alpha;
 					}
 				} else {
-					// Additive.
+					// Weighted deform offsets, with alpha.
 					for (int i = 0; i < vertexCount; i++) {
 						float prev = prevVertices[i];
-						vertices[i] += (prev + (nextVertices[i] - prev) * percent - vertices[i]) * alpha;
+						vertices[i] = (prev + (nextVertices[i] - prev) * percent) * alpha;
 					}
 				}
+			} else {
+				// Vertex positions or deform offsets, with alpha.
+				for (int i = 0; i < vertexCount; i++) {
+					float prev = prevVertices[i];
+					vertices[i] += (prev + (nextVertices[i] - prev) * percent - vertices[i]) * alpha;
+				}
 			}
 		}
 	}
@@ -918,6 +916,8 @@ public class Animation {
 			float[] frames = this.frames;
 			if (time < frames[0]) return; // Time is before first frame.
 
+			// BOZO - Finish timelines handling setupPose and mixingOut from here down.
+			
 			IkConstraint constraint = skeleton.ikConstraints.get(ikConstraintIndex);
 
 			if (time >= frames[frames.length - ENTRIES]) { // Time is after last frame.

+ 137 - 31
spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Bone.java

@@ -37,6 +37,7 @@ import static com.badlogic.gdx.math.Matrix3.*;
 import com.badlogic.gdx.math.Matrix3;
 import com.badlogic.gdx.math.Vector2;
 import com.badlogic.gdx.utils.Array;
+import com.esotericsoftware.spine.BoneData.TransformMode;
 
 public class Bone implements Updatable {
 	final BoneData data;
@@ -100,12 +101,13 @@ public class Bone implements Updatable {
 		ashearY = shearY;
 		appliedValid = true;
 
-		float rotationY = rotation + 90 + shearY;
-		float la = cosDeg(rotation + shearX) * scaleX, lb = cosDeg(rotationY) * scaleY;
-		float lc = sinDeg(rotation + shearX) * scaleX, ld = sinDeg(rotationY) * scaleY;
-
 		Bone parent = this.parent;
 		if (parent == null) { // Root bone.
+			float rotationY = rotation + 90 + shearY;
+			float la = cosDeg(rotation + shearX) * scaleX;
+			float lb = cosDeg(rotationY) * scaleY;
+			float lc = sinDeg(rotation + shearX) * scaleX;
+			float ld = sinDeg(rotationY) * scaleY;
 			Skeleton skeleton = this.skeleton;
 			if (skeleton.flipX) {
 				x = -x;
@@ -130,28 +132,99 @@ public class Bone implements Updatable {
 		worldX = pa * x + pb * y + parent.worldX;
 		worldY = pc * x + pd * y + parent.worldY;
 
-		if (data.inheritRotation && data.inheritScale) {
+		switch (data.transformMode) {
+		case normal: {
+			float rotationY = rotation + 90 + shearY;
+			float la = cosDeg(rotation + shearX) * scaleX;
+			float lb = cosDeg(rotationY) * scaleY;
+			float lc = sinDeg(rotation + shearX) * scaleX;
+			float ld = sinDeg(rotationY) * scaleY;
 			a = pa * la + pb * lc;
 			b = pa * lb + pb * ld;
 			c = pc * la + pd * lc;
 			d = pc * lb + pd * ld;
-		} else {
-			if (data.inheritRotation) { // No scale inheritance.
-				float psx = (float)Math.sqrt(pa * pa + pc * pc);
-				float psy = (float)Math.sqrt(pb * pb + pd * pd);
-				if (psx > 0.0001f) {
-					pa /= psx;
-					pc /= psx;
-				}
-				if (psy > 0.0001f) {
-					pb /= psy;
-					pd /= psy;
+			return;
+		}
+		case onlyTranslation: {
+			float rotationY = rotation + 90 + shearY;
+			a = cosDeg(rotation + shearX) * scaleX;
+			b = cosDeg(rotationY) * scaleY;
+			c = sinDeg(rotation + shearX) * scaleX;
+			d = sinDeg(rotationY) * scaleY;
+			break;
+		}
+		case noRotation: {
+			if (false) {
+				// Summing parent rotations.
+				// 1) Negative parent scale causes bone to rotate.
+				float sum = 0;
+				Bone current = parent;
+				while (current != null) {
+					sum += current.arotation;
+					current = current.parent;
 				}
+				rotation -= sum;
+				float rotationY = rotation + 90 + shearY;
+				float la = cosDeg(rotation + shearX) * scaleX;
+				float lb = cosDeg(rotationY) * scaleY;
+				float lc = sinDeg(rotation + shearX) * scaleX;
+				float ld = sinDeg(rotationY) * scaleY;
+				a = pa * la + pb * lc;
+				b = pa * lb + pb * ld;
+				c = pc * la + pd * lc;
+				d = pc * lb + pd * ld;
+			} else if (true) {
+				// Old way.
+				// 1) Immediate parent scale is applied in wrong direction.
+				// 2) Negative parent scale causes bone to rotate.
+				pa = 1;
+				pb = 0;
+				pc = 0;
+				pd = 1;
+				float rotationY, la, lb, lc, ld;
+				outer:
+				do {
+					if (!parent.appliedValid) parent.updateAppliedTransform();
+					float pr = parent.arotation, psx = parent.ascaleX;
+					rotationY = pr + 90 + parent.ashearY;
+					la = cosDeg(pr + parent.shearX);
+					lb = cosDeg(rotationY);
+					lc = sinDeg(pr + parent.shearX);
+					ld = sinDeg(rotationY);
+					float temp = (pa * la + pb * lc) * psx;
+					pb = (pb * ld + pa * lb) * parent.ascaleY;
+					pa = temp;
+					temp = (pc * la + pd * lc) * psx;
+					pd = (pd * ld + pc * lb) * parent.ascaleY;
+					pc = temp;
+
+					if (psx < 0) lc = -lc;
+					temp = pa * la - pb * lc;
+					pb = pb * ld - pa * lb;
+					pa = temp;
+					temp = pc * la - pd * lc;
+					pd = pd * ld - pc * lb;
+					pc = temp;
+
+					switch (parent.data.transformMode) {
+					case noScale:
+					case noScaleOrReflection:
+						break outer;
+					}
+					parent = parent.parent;
+				} while (parent != null);
+				rotationY = rotation + 90 + shearY;
+				la = cosDeg(rotation + shearX) * scaleX;
+				lb = cosDeg(rotationY) * scaleY;
+				lc = sinDeg(rotation + shearX) * scaleX;
+				ld = sinDeg(rotationY) * scaleY;
 				a = pa * la + pb * lc;
 				b = pa * lb + pb * ld;
 				c = pc * la + pd * lc;
 				d = pc * lb + pd * ld;
-			} else if (data.inheritScale) { // No rotation inheritance.
+			} else {
+				// New way.
+				// 1) Negative scale can cause bone to flip.
 				float psx = (float)Math.sqrt(pa * pa + pc * pc), psy, pr;
 				if (psx > 0.0001f) {
 					float det = pa * pd - pb * pc;
@@ -173,24 +246,57 @@ public class Bone implements Updatable {
 					blend = 1 - (pr - 90) / 90;
 				pa = psx + (Math.abs(psy) * Math.signum(psx) - psx) * blend;
 				pd = psy + (Math.abs(psx) * Math.signum(psy) - psy) * blend;
-				a = pa * la;
-				b = pa * lb;
-				c = pd * lc;
-				d = pd * ld;
-			} else {
-				a = la;
-				b = lb;
-				c = lc;
-				d = ld;
+				float rotationY = rotation + 90 + shearY;
+				a = pa * cosDeg(rotation + shearX) * scaleX;
+				b = pa * cosDeg(rotationY) * scaleY;
+				c = pd * sinDeg(rotation + shearX) * scaleX;
+				d = pd * sinDeg(rotationY) * scaleY;
 			}
-			if (skeleton.flipX) {
-				a = -a;
+			break;
+		}
+		case noScale:
+		case noScaleOrReflection: {
+			float cos = cosDeg(rotation), sin = sinDeg(rotation);
+			float za = pa * cos + pb * sin, zb = za;
+			float zc = pc * cos + pd * sin, zd = zc;
+			float s = (float)Math.sqrt(za * za + zc * zc);
+			if (s > 0.00001f) s = 1 / s;
+			za *= s;
+			zc *= s;
+			s = (float)Math.sqrt(zb * zb + zd * zd);
+			if (s > 0.00001f) s = 1 / s;
+			zb *= s;
+			zd *= s;
+			float by = atan2(zd, zb), r = PI / 2 - (by - atan2(zc, za));
+			if (r > PI)
+				r -= PI2;
+			else if (r < -PI) r += PI2;
+			r += by;
+			s = (float)Math.sqrt(zb * zb + zd * zd);
+			zb = cos(r) * s;
+			zd = sin(r) * s;
+			float la = cosDeg(shearX) * scaleX;
+			float lb = cosDeg(90 + shearY) * scaleY;
+			float lc = sinDeg(shearX) * scaleX;
+			float ld = sinDeg(90 + shearY) * scaleY;
+			a = za * la + zb * lc;
+			b = za * lb + zb * ld;
+			c = zc * la + zd * lc;
+			d = zc * lb + zd * ld;
+			if (data.transformMode != TransformMode.noScaleOrReflection ? pa * pd - pb * pc < 0 : skeleton.flipX != skeleton.flipY) {
 				b = -b;
-			}
-			if (skeleton.flipY) {
-				c = -c;
 				d = -d;
 			}
+			return;
+		}
+		}
+		if (skeleton.flipX) {
+			a = -a;
+			b = -b;
+		}
+		if (skeleton.flipY) {
+			c = -c;
+			d = -d;
 		}
 	}
 

+ 11 - 13
spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/BoneData.java

@@ -39,7 +39,7 @@ public class BoneData {
 	final BoneData parent;
 	float length;
 	float x, y, rotation, scaleX = 1, scaleY = 1, shearX, shearY;
-	boolean inheritRotation = true, inheritScale = true;
+	TransformMode transformMode = TransformMode.normal;
 
 	// Nonessential.
 	final Color color = new Color(0.61f, 0.61f, 0.61f, 1);
@@ -157,20 +157,12 @@ public class BoneData {
 		this.shearY = shearY;
 	}
 
-	public boolean getInheritRotation () {
-		return inheritRotation;
+	public TransformMode getTransformMode () {
+		return transformMode;
 	}
 
-	public void setInheritRotation (boolean inheritRotation) {
-		this.inheritRotation = inheritRotation;
-	}
-
-	public boolean getInheritScale () {
-		return inheritScale;
-	}
-
-	public void setInheritScale (boolean inheritScale) {
-		this.inheritScale = inheritScale;
+	public void setTransformMode (TransformMode transformMode) {
+		this.transformMode = transformMode;
 	}
 
 	public Color getColor () {
@@ -180,4 +172,10 @@ public class BoneData {
 	public String toString () {
 		return name;
 	}
+
+	static public enum TransformMode {
+		normal, onlyTranslation, noRotation, noScale, noScaleOrReflection;
+
+		static public final TransformMode[] values = TransformMode.values();
+	}
 }

+ 2 - 2
spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonBinary.java

@@ -58,6 +58,7 @@ import com.esotericsoftware.spine.Animation.ShearTimeline;
 import com.esotericsoftware.spine.Animation.Timeline;
 import com.esotericsoftware.spine.Animation.TransformConstraintTimeline;
 import com.esotericsoftware.spine.Animation.TranslateTimeline;
+import com.esotericsoftware.spine.BoneData.TransformMode;
 import com.esotericsoftware.spine.PathConstraintData.PositionMode;
 import com.esotericsoftware.spine.PathConstraintData.RotateMode;
 import com.esotericsoftware.spine.PathConstraintData.SpacingMode;
@@ -186,8 +187,7 @@ public class SkeletonBinary {
 				data.shearX = input.readFloat();
 				data.shearY = input.readFloat();
 				data.length = input.readFloat() * scale;
-				data.inheritRotation = input.readBoolean();
-				data.inheritScale = input.readBoolean();
+				data.transformMode = TransformMode.values[input.readInt(true)];
 				if (nonessential) Color.rgba8888ToColor(data.color, input.readInt());
 				skeletonData.bones.add(data);
 			}

+ 2 - 2
spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonJson.java

@@ -56,6 +56,7 @@ import com.esotericsoftware.spine.Animation.ShearTimeline;
 import com.esotericsoftware.spine.Animation.Timeline;
 import com.esotericsoftware.spine.Animation.TransformConstraintTimeline;
 import com.esotericsoftware.spine.Animation.TranslateTimeline;
+import com.esotericsoftware.spine.BoneData.TransformMode;
 import com.esotericsoftware.spine.PathConstraintData.PositionMode;
 import com.esotericsoftware.spine.PathConstraintData.RotateMode;
 import com.esotericsoftware.spine.PathConstraintData.SpacingMode;
@@ -129,8 +130,7 @@ public class SkeletonJson {
 			data.scaleY = boneMap.getFloat("scaleY", 1);
 			data.shearX = boneMap.getFloat("shearX", 0);
 			data.shearY = boneMap.getFloat("shearY", 0);
-			data.inheritRotation = boneMap.getBoolean("inheritRotation", true);
-			data.inheritScale = boneMap.getBoolean("inheritScale", true);
+			data.transformMode = TransformMode.valueOf(boneMap.getString("transform", TransformMode.normal.name()));
 
 			String color = boneMap.getString("color", null);
 			if (color != null) data.getColor().set(Color.valueOf(color));

+ 4 - 4
spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/TransformConstraint.java

@@ -79,14 +79,14 @@ public class TransformConstraint implements Constraint {
 			}
 
 			if (scaleMix > 0) {
-				float bs = (float)Math.sqrt(bone.a * bone.a + bone.c * bone.c);
+				float s = (float)Math.sqrt(bone.a * bone.a + bone.c * bone.c);
 				float ts = (float)Math.sqrt(ta * ta + tc * tc);
-				float s = bs > 0.00001f ? (bs + (ts - bs + data.offsetScaleX) * scaleMix) / bs : 0;
+				if (s > 0.00001f) s = (s + (ts - s + data.offsetScaleX) * scaleMix) / s;
 				bone.a *= s;
 				bone.c *= s;
-				bs = (float)Math.sqrt(bone.b * bone.b + bone.d * bone.d);
+				s = (float)Math.sqrt(bone.b * bone.b + bone.d * bone.d);
 				ts = (float)Math.sqrt(tb * tb + td * td);
-				s = bs > 0.00001f ? (bs + (ts - bs + data.offsetScaleY) * scaleMix) / bs : 0;
+				if (s > 0.00001f) s = (s + (ts - s + data.offsetScaleY) * scaleMix) / s;
 				bone.b *= s;
 				bone.d *= s;
 				modified = true;