From dffd590966c08aa22e8a7568b67349c5e0d9d1c1 Mon Sep 17 00:00:00 2001 From: Nathan Sweet Date: Tue, 18 Oct 2022 16:32:48 -0400 Subject: [PATCH] [libgdx] Physics progress, springs have a bone for rotate/scale. --- .../spine/PhysicsConstraint.java | 78 ++++++++++++------- .../spine/PhysicsConstraintData.java | 3 +- .../com/esotericsoftware/spine/Skeleton.java | 15 +++- 3 files changed, 63 insertions(+), 33 deletions(-) diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PhysicsConstraint.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PhysicsConstraint.java index cddd40793..9e675a540 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PhysicsConstraint.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PhysicsConstraint.java @@ -42,6 +42,8 @@ import com.esotericsoftware.spine.PhysicsConstraintData.SpringData; *

* See Physics constraints in the Spine User Guide. */ public class PhysicsConstraint implements Updatable { + static final Vector2 temp = new Vector2(); + final PhysicsConstraintData data; final Array nodes; final Array springs; @@ -51,7 +53,6 @@ public class PhysicsConstraint implements Updatable { final Skeleton skeleton; float remaining, lastTime; - final Vector2 temp = new Vector2(); public PhysicsConstraint (PhysicsConstraintData data, Skeleton skeleton) { if (data == null) throw new IllegalArgumentException("data cannot be null."); @@ -123,9 +124,11 @@ public class PhysicsConstraint implements Updatable { /** Applies the constraint to the constrained bones. */ public void update () { + if (mix == 0) return; + Object[] nodes = this.nodes.items; int nodeCount = this.nodes.size; - Vector2 temp = this.temp; + Vector2 temp = PhysicsConstraint.temp; for (int i = 0; i < nodeCount; i++) { Node node = (Node)nodes[i]; if (node.parentBone == null) continue; @@ -142,26 +145,29 @@ public class PhysicsConstraint implements Updatable { while (remaining >= 0.016f) { remaining -= 0.016f; for (int i = 0; i < springCount; i++) - ((Spring)springs[i]).update(); + ((Spring)springs[i]).step(); for (int i = 0; i < nodeCount; i++) - ((Node)nodes[i]).update(this); + ((Node)nodes[i]).step(this); } - for (int i = 0; i < nodeCount; i++) { - Node node = (Node)nodes[i]; - Object[] bones = node.bones; - int ii = 0, nn = bones.length; - if (mix == 1) { - for (; ii < nn; ii++) { + if (mix == 1) { + for (int i = 0; i < nodeCount; i++) { + Node node = (Node)nodes[i]; + Object[] bones = node.bones; + for (int ii = 0, nn = bones.length; ii < nn; ii++) { Bone bone = (Bone)bones[ii]; bone.worldX = node.x; bone.worldY = node.y; - bone.worldToLocal(temp.set(bone.worldX, bone.worldY)); + bone.parent.worldToLocal(temp.set(node.x, node.y)); bone.ax = temp.x; bone.ay = temp.y; } - } else { - for (; ii < nn; ii++) { + } + } else { + for (int i = 0; i < nodeCount; i++) { + Node node = (Node)nodes[i]; + Object[] bones = node.bones; + for (int ii = 0, nn = bones.length; ii < nn; ii++) { Bone bone = (Bone)bones[ii]; bone.worldX = bone.worldX + (node.x - bone.worldX) * mix; bone.worldY = bone.worldY + (node.y - bone.worldY) * mix; @@ -295,12 +301,8 @@ public class PhysicsConstraint implements Updatable { vy = 0; } - public void update (PhysicsConstraint constraint) { - if (parentBone != null) { - vx = 0; - vy = 0; - return; - } + public void step (PhysicsConstraint constraint) { + if (parentBone != null) return; x += vx; y += vy; vx = vx * constraint.friction + constraint.wind; @@ -308,35 +310,36 @@ public class PhysicsConstraint implements Updatable { } } - static public class Spring { + static public class Spring implements Updatable { public final SpringData data; + public final PhysicsConstraint constraint; public Node node1, node2; - public Bone[] bones; + public Bone bone; public float length, stiffness, damping; - Spring (SpringData data) { // Editor. + Spring (SpringData data, PhysicsConstraint constraint) { // Editor. this.data = data; + this.constraint = constraint; } public Spring (SpringData data, PhysicsConstraint constraint, Skeleton skeleton) { this.data = data; + this.constraint = constraint; node1 = constraint.nodes.get(data.node1); node2 = constraint.nodes.get(data.node2); - bones = new Bone[data.bones.length]; - for (int i = 0, n = bones.length; i < n; i++) - bones[i] = skeleton.bones.get(data.bones[i]); + bone = skeleton.bones.get(data.bone); setToSetupPose(); } public Spring (Spring spring, PhysicsConstraint constraint) { this.data = spring.data; + this.constraint = constraint; node1 = constraint.nodes.get(data.node1); node2 = constraint.nodes.get(data.node2); - bones = new Bone[spring.bones.length]; - arraycopy(spring.bones, 0, bones, 0, bones.length); + bone = spring.bone; length = spring.length; stiffness = spring.stiffness; damping = spring.damping; @@ -348,9 +351,10 @@ public class PhysicsConstraint implements Updatable { damping = data.damping; } - public void update () { - float x = node2.x - node1.x, y = node2.y - node1.y, d = (float)Math.sqrt(Math.max(x * x + y * y, 0.00001f)); + public void step () { + float x = node2.x - node1.x, y = node2.y - node1.y, d = x * x + y * y; if (data.rope && d <= length) return; + d = (float)Math.sqrt(Math.max(d, 0.00001f)); x /= d; y /= d; float m1 = node1.massInverse, m2 = node2.massInverse; @@ -362,5 +366,21 @@ public class PhysicsConstraint implements Updatable { node2.vx -= x * m2; node2.vy -= y * m2; } + + public void update () { + float dx = node2.x - node1.x, dy = node2.y - node1.y; + float s = (float)Math.sqrt(dx * dx + dy * dy) / length, r = atan2(dy, dx), sin = sin(r), cos = cos(r); + if (constraint.mix == 1) { + bone.updateWorldTransform(bone.ax, bone.ay, + atan2(bone.a * sin - bone.c * cos, bone.d * cos - bone.b * sin) * radDeg + bone.arotation - bone.ashearX, + bone.ascaleX * s, bone.ascaleY, bone.ashearX, bone.ashearY); + } else { + // BOZO + } + } + + public boolean isActive () { + return constraint.active; + } } } diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PhysicsConstraintData.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PhysicsConstraintData.java index f2e55eb12..cd7b5ff76 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PhysicsConstraintData.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/PhysicsConstraintData.java @@ -115,8 +115,7 @@ public class PhysicsConstraintData extends ConstraintData { } static public class SpringData { - public int node1, node2; - public int[] bones; + public int node1, node2, bone; public float length, stiffness, damping; public boolean rope; } diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Skeleton.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Skeleton.java index 6a16d416a..150b2d7ee 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Skeleton.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Skeleton.java @@ -38,6 +38,7 @@ import com.badlogic.gdx.utils.FloatArray; import com.badlogic.gdx.utils.Null; import com.esotericsoftware.spine.PhysicsConstraint.Node; +import com.esotericsoftware.spine.PhysicsConstraint.Spring; import com.esotericsoftware.spine.Skin.SkinEntry; import com.esotericsoftware.spine.attachments.Attachment; import com.esotericsoftware.spine.attachments.MeshAttachment; @@ -355,16 +356,26 @@ public class Skeleton { for (int i = 0; i < nodeCount; i++) { Node node = (Node)nodes[i]; - if (node.parentBone != null) sortReset(node.parentBone.children); for (Bone bone : node.bones) sortReset(bone.children); } for (int i = 0; i < nodeCount; i++) { Node node = (Node)nodes[i]; - if (node.parentBone != null) node.parentBone.sorted = true; for (Bone bone : node.bones) bone.sorted = true; } + + Object[] springs = constraint.springs.items; + for (int i = 0, n = constraint.springs.size; i < n; i++) { + Spring spring = (Spring)springs[i]; + if (spring.bone == null) continue; + sortBone(spring.bone); + updateCache.add(spring); + sortReset(spring.bone.children); + spring.bone.sorted = true; + for (Bone child : spring.bone.children) + sortBone(child); + } } private void sortBone (Bone bone) {