mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-03-26 22:49:01 +08:00
Finished "applied transform" for arbitrary constraint order.
This commit is contained in:
parent
438f0028b2
commit
217aa60c4f
@ -45,7 +45,7 @@ public class Bone implements Updatable {
|
|||||||
final Array<Bone> children = new Array();
|
final Array<Bone> children = new Array();
|
||||||
float x, y, rotation, scaleX, scaleY, shearX, shearY;
|
float x, y, rotation, scaleX, scaleY, shearX, shearY;
|
||||||
float ax, ay, arotation, ascaleX, ascaleY, ashearX, ashearY;
|
float ax, ay, arotation, ascaleX, ascaleY, ashearX, ashearY;
|
||||||
boolean appliedValid; // BOZO! - Use everywhere.
|
boolean appliedValid;
|
||||||
|
|
||||||
float a, b, worldX;
|
float a, b, worldX;
|
||||||
float c, d, worldY;
|
float c, d, worldY;
|
||||||
@ -99,6 +99,7 @@ public class Bone implements Updatable {
|
|||||||
ascaleY = scaleY;
|
ascaleY = scaleY;
|
||||||
ashearX = shearX;
|
ashearX = shearX;
|
||||||
ashearY = shearY;
|
ashearY = shearY;
|
||||||
|
appliedValid = true;
|
||||||
|
|
||||||
float rotationY = rotation + 90 + shearY;
|
float rotationY = rotation + 90 + shearY;
|
||||||
float la = cosDeg(rotation + shearX) * scaleX, lb = cosDeg(rotationY) * scaleY;
|
float la = cosDeg(rotation + shearX) * scaleX, lb = cosDeg(rotationY) * scaleY;
|
||||||
@ -162,71 +163,71 @@ public class Bone implements Updatable {
|
|||||||
b = cos(r) * s;
|
b = cos(r) * s;
|
||||||
d = sin(r) * s;
|
d = sin(r) * s;
|
||||||
} else if (data.inheritScale) { // No rotation inheritance.
|
} else if (data.inheritScale) { // No rotation inheritance.
|
||||||
float psx = (float)Math.sqrt(pa * pa + pc * pc), psy, pr;
|
// float psx = (float)Math.sqrt(pa * pa + pc * pc), psy, pr;
|
||||||
if (psx > 0.0001f) {
|
// if (psx > 0.0001f) {
|
||||||
float det = pa * pd - pb * pc;
|
// float det = pa * pd - pb * pc;
|
||||||
psy = det / psx;
|
// psy = det / psx;
|
||||||
rotationY = atan2(pa * pb + pc * pd, det) * radDeg + 90;
|
// rotationY = atan2(pa * pb + pc * pd, det) * radDeg + 90;
|
||||||
pr = atan2(pc, pa) * radDeg;
|
// pr = atan2(pc, pa) * radDeg;
|
||||||
} else {
|
// } else {
|
||||||
psx = 0;
|
// psx = 0;
|
||||||
psy = (float)Math.sqrt(pb * pb + pd * pd);
|
// psy = (float)Math.sqrt(pb * pb + pd * pd);
|
||||||
rotationY = 90;
|
// rotationY = 90;
|
||||||
pr = 90 - atan2(pd, pb) * radDeg;
|
// pr = 90 - atan2(pd, pb) * radDeg;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
|
// float blend;
|
||||||
|
// if (pr < -90)
|
||||||
|
// blend = 1 + (pr + 90) / 90;
|
||||||
|
// else if (pr < 0)
|
||||||
|
// blend = -pr / 90;
|
||||||
|
// else if (pr < 90)
|
||||||
|
// blend = pr / 90;
|
||||||
|
// else
|
||||||
|
// blend = 1f - (pr - 90) / 90;
|
||||||
|
//
|
||||||
|
// pa = lerp(psx, Math.abs(psy) * Math.signum(psx), blend);
|
||||||
|
// psy = lerp(psy, Math.abs(psx) * Math.signum(psy), blend);
|
||||||
|
// pb = cosDeg(rotationY) * psy;
|
||||||
|
// pc = 0;
|
||||||
|
// pd = sinDeg(rotationY) * psy;
|
||||||
|
//
|
||||||
|
// a = pa * la + pb * lc;
|
||||||
|
// b = pa * lb + pb * ld;
|
||||||
|
// c = pc * la + pd * lc;
|
||||||
|
// d = pc * lb + pd * ld;
|
||||||
|
|
||||||
float blend;
|
pa = 1;
|
||||||
if (pr < -90)
|
pb = 0;
|
||||||
blend = 1 + (pr + 90) / 90;
|
|
||||||
else if (pr < 0)
|
|
||||||
blend = -pr / 90;
|
|
||||||
else if (pr < 90)
|
|
||||||
blend = pr / 90;
|
|
||||||
else
|
|
||||||
blend = 1f - (pr - 90) / 90;
|
|
||||||
|
|
||||||
pa = lerp(psx, Math.abs(psy) * Math.signum(psx), blend);
|
|
||||||
psy = lerp(psy, Math.abs(psx) * Math.signum(psy), blend);
|
|
||||||
pb = cosDeg(rotationY) * psy;
|
|
||||||
pc = 0;
|
pc = 0;
|
||||||
pd = sinDeg(rotationY) * psy;
|
pd = 1;
|
||||||
|
do {
|
||||||
|
float cos = cosDeg(parent.arotation), sin = sinDeg(parent.arotation);
|
||||||
|
float psx = parent.ascaleX, psy = parent.ascaleY;
|
||||||
|
float za = cos * psx, zb = sin * psy, zc = sin * psx, zd = cos * psy;
|
||||||
|
float temp = pa * za + pb * zc;
|
||||||
|
pb = pb * zd - pa * zb;
|
||||||
|
pa = temp;
|
||||||
|
temp = pc * za + pd * zc;
|
||||||
|
pd = pd * zd - pc * zb;
|
||||||
|
pc = temp;
|
||||||
|
|
||||||
|
if (psx >= 0) // BOZO! - Why? Should always do this? Fix in new code?
|
||||||
|
sin = -sin;
|
||||||
|
temp = pa * cos + pb * sin;
|
||||||
|
pb = pb * cos - pa * sin;
|
||||||
|
pa = temp;
|
||||||
|
temp = pc * cos + pd * sin;
|
||||||
|
pd = pd * cos - pc * sin;
|
||||||
|
pc = temp;
|
||||||
|
|
||||||
|
if (!parent.data.inheritScale) break;
|
||||||
|
parent = parent.parent;
|
||||||
|
} while (parent != null);
|
||||||
a = pa * la + pb * lc;
|
a = pa * la + pb * lc;
|
||||||
b = pa * lb + pb * ld;
|
b = pa * lb + pb * ld;
|
||||||
c = pc * la + pd * lc;
|
c = pc * la + pd * lc;
|
||||||
d = pc * lb + pd * ld;
|
d = pc * lb + pd * ld;
|
||||||
|
|
||||||
// pa = 1;
|
|
||||||
// pb = 0;
|
|
||||||
// pc = 0;
|
|
||||||
// pd = 1;
|
|
||||||
// do {
|
|
||||||
// float cos = cosDeg(parent.arotation), sin = sinDeg(parent.arotation);
|
|
||||||
// float psx = parent.ascaleX, psy = parent.ascaleY;
|
|
||||||
// float za = cos * psx, zb = sin * psy, zc = sin * psx, zd = cos * psy;
|
|
||||||
// float temp = pa * za + pb * zc;
|
|
||||||
// pb = pb * zd - pa * zb;
|
|
||||||
// pa = temp;
|
|
||||||
// temp = pc * za + pd * zc;
|
|
||||||
// pd = pd * zd - pc * zb;
|
|
||||||
// pc = temp;
|
|
||||||
//
|
|
||||||
// if (psx >= 0) // BOZO! - Why? Should always do this? Fix in new code?
|
|
||||||
// sin = -sin;
|
|
||||||
// temp = pa * cos + pb * sin;
|
|
||||||
// pb = pb * cos - pa * sin;
|
|
||||||
// pa = temp;
|
|
||||||
// temp = pc * cos + pd * sin;
|
|
||||||
// pd = pd * cos - pc * sin;
|
|
||||||
// pc = temp;
|
|
||||||
//
|
|
||||||
// if (!parent.data.inheritScale) break;
|
|
||||||
// parent = parent.parent;
|
|
||||||
// } while (parent != null);
|
|
||||||
// a = pa * la + pb * lc;
|
|
||||||
// b = pa * lb + pb * ld;
|
|
||||||
// c = pc * la + pd * lc;
|
|
||||||
// d = pc * lb + pd * ld;
|
|
||||||
} else {
|
} else {
|
||||||
a = la;
|
a = la;
|
||||||
b = lb;
|
b = lb;
|
||||||
@ -411,6 +412,7 @@ public class Bone implements Updatable {
|
|||||||
this.b = cos * b - sin * d;
|
this.b = cos * b - sin * d;
|
||||||
this.c = sin * a + cos * c;
|
this.c = sin * a + cos * c;
|
||||||
this.d = sin * b + cos * d;
|
this.d = sin * b + cos * d;
|
||||||
|
appliedValid = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Computes the individual applied transform values from the world transform. This can be useful to perform processing using
|
/** Computes the individual applied transform values from the world transform. This can be useful to perform processing using
|
||||||
@ -418,6 +420,7 @@ public class Bone implements Updatable {
|
|||||||
* <p>
|
* <p>
|
||||||
* Some information is ambiguous in the world transform, such as -1,-1 scale versus 180 rotation. */
|
* Some information is ambiguous in the world transform, such as -1,-1 scale versus 180 rotation. */
|
||||||
public void updateAppliedTransform () {
|
public void updateAppliedTransform () {
|
||||||
|
appliedValid = true;
|
||||||
Bone parent = this.parent;
|
Bone parent = this.parent;
|
||||||
if (parent == null) {
|
if (parent == null) {
|
||||||
ax = worldX;
|
ax = worldX;
|
||||||
|
|||||||
@ -128,6 +128,7 @@ public class IkConstraint implements Constraint {
|
|||||||
/** Adjusts the bone rotation so the tip is as close to the target position as possible. The target is specified in the world
|
/** Adjusts the bone rotation so the tip is as close to the target position as possible. The target is specified in the world
|
||||||
* coordinate system. */
|
* coordinate system. */
|
||||||
static public void apply (Bone bone, float targetX, float targetY, float alpha) {
|
static public void apply (Bone bone, float targetX, float targetY, float alpha) {
|
||||||
|
if (!bone.appliedValid) bone.updateAppliedTransform();
|
||||||
Bone p = bone.parent;
|
Bone p = bone.parent;
|
||||||
float id = 1 / (p.a * p.d - p.b * p.c);
|
float id = 1 / (p.a * p.d - p.b * p.c);
|
||||||
float x = targetX - p.worldX, y = targetY - p.worldY;
|
float x = targetX - p.worldX, y = targetY - p.worldY;
|
||||||
@ -149,11 +150,8 @@ public class IkConstraint implements Constraint {
|
|||||||
child.updateWorldTransform();
|
child.updateWorldTransform();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (!parent.appliedValid) parent.updateAppliedTransform();
|
||||||
// BOZO! - Only when each bone needs it.
|
if (!child.appliedValid) child.updateAppliedTransform();
|
||||||
// child.updateLocalTransform();
|
|
||||||
// parent.updateLocalTransform();
|
|
||||||
|
|
||||||
float px = parent.ax, py = parent.ay, psx = parent.ascaleX, psy = parent.ascaleY, csx = child.ascaleX;
|
float px = parent.ax, py = parent.ay, psx = parent.ascaleX, psy = parent.ascaleY, csx = child.ascaleX;
|
||||||
int os1, os2, s2;
|
int os1, os2, s2;
|
||||||
if (psx < 0) {
|
if (psx < 0) {
|
||||||
|
|||||||
@ -137,6 +137,7 @@ public class PathConstraint implements Constraint {
|
|||||||
bone.c = sin * a + cos * c;
|
bone.c = sin * a + cos * c;
|
||||||
bone.d = sin * b + cos * d;
|
bone.d = sin * b + cos * d;
|
||||||
}
|
}
|
||||||
|
bone.appliedValid = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -60,7 +60,10 @@ public class Skeleton {
|
|||||||
float x, y;
|
float x, y;
|
||||||
|
|
||||||
final Comparator<Constraint> constraintComparator = new Comparator<Constraint>() {
|
final Comparator<Constraint> constraintComparator = new Comparator<Constraint>() {
|
||||||
public int compare (Constraint o1,Constraint o2){return o1.getOrder()-o2.getOrder();}};
|
public int compare (Constraint o1, Constraint o2) {
|
||||||
|
return o1.getOrder() - o2.getOrder();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
public Skeleton (SkeletonData data) {
|
public Skeleton (SkeletonData data) {
|
||||||
if (data == null) throw new IllegalArgumentException("data cannot be null.");
|
if (data == null) throw new IllegalArgumentException("data cannot be null.");
|
||||||
@ -175,6 +178,13 @@ public class Skeleton {
|
|||||||
|
|
||||||
for (int i = 0, n = bones.size; i < n; i++)
|
for (int i = 0, n = bones.size; i < n; i++)
|
||||||
sortBone(bones.get(i));
|
sortBone(bones.get(i));
|
||||||
|
|
||||||
|
// BOZO
|
||||||
|
// for (int i = 0, n = updateCache.size; i < n; i++) {
|
||||||
|
// Updatable item = updateCache.get(i);
|
||||||
|
// if (item instanceof Constraint) System.out.print(item + ", ");
|
||||||
|
// }
|
||||||
|
// System.out.println();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sortIkConstraint (IkConstraint constraint) {
|
private void sortIkConstraint (IkConstraint constraint) {
|
||||||
|
|||||||
@ -53,6 +53,7 @@ public class TransformConstraint implements Constraint {
|
|||||||
Array<Bone> bones = this.bones;
|
Array<Bone> bones = this.bones;
|
||||||
for (int i = 0, n = bones.size; i < n; i++) {
|
for (int i = 0, n = bones.size; i < n; i++) {
|
||||||
Bone bone = bones.get(i);
|
Bone bone = bones.get(i);
|
||||||
|
boolean modified = false;
|
||||||
|
|
||||||
if (rotateMix != 0) {
|
if (rotateMix != 0) {
|
||||||
float a = bone.a, b = bone.b, c = bone.c, d = bone.d;
|
float a = bone.a, b = bone.b, c = bone.c, d = bone.d;
|
||||||
@ -66,6 +67,7 @@ public class TransformConstraint implements Constraint {
|
|||||||
bone.b = cos * b - sin * d;
|
bone.b = cos * b - sin * d;
|
||||||
bone.c = sin * a + cos * c;
|
bone.c = sin * a + cos * c;
|
||||||
bone.d = sin * b + cos * d;
|
bone.d = sin * b + cos * d;
|
||||||
|
modified = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (translateMix != 0) {
|
if (translateMix != 0) {
|
||||||
@ -73,6 +75,7 @@ public class TransformConstraint implements Constraint {
|
|||||||
target.localToWorld(temp.set(data.offsetX, data.offsetY));
|
target.localToWorld(temp.set(data.offsetX, data.offsetY));
|
||||||
bone.worldX += (temp.x - bone.worldX) * translateMix;
|
bone.worldX += (temp.x - bone.worldX) * translateMix;
|
||||||
bone.worldY += (temp.y - bone.worldY) * translateMix;
|
bone.worldY += (temp.y - bone.worldY) * translateMix;
|
||||||
|
modified = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (scaleMix > 0) {
|
if (scaleMix > 0) {
|
||||||
@ -86,6 +89,7 @@ public class TransformConstraint implements Constraint {
|
|||||||
s = bs > 0.00001f ? (bs + (ts - bs + data.offsetScaleY) * scaleMix) / bs : 0;
|
s = bs > 0.00001f ? (bs + (ts - bs + data.offsetScaleY) * scaleMix) / bs : 0;
|
||||||
bone.b *= s;
|
bone.b *= s;
|
||||||
bone.d *= s;
|
bone.d *= s;
|
||||||
|
modified = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shearMix > 0) {
|
if (shearMix > 0) {
|
||||||
@ -99,7 +103,10 @@ public class TransformConstraint implements Constraint {
|
|||||||
float s = (float)Math.sqrt(b * b + d * d);
|
float s = (float)Math.sqrt(b * b + d * d);
|
||||||
bone.b = cos(r) * s;
|
bone.b = cos(r) * s;
|
||||||
bone.d = sin(r) * s;
|
bone.d = sin(r) * s;
|
||||||
|
modified = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (modified) bone.appliedValid = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user