mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-02-06 07:14:55 +08:00
[unity] Spine.BoneMatrix struct.
This commit is contained in:
parent
f3bb19a339
commit
1c3f6b1b32
@ -283,8 +283,150 @@ namespace Spine.Unity {
|
||||
}
|
||||
|
||||
namespace Spine {
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
public struct BoneMatrix {
|
||||
public float a, b, c, d, x, y;
|
||||
|
||||
/// <summary>Recursively calculates a worldspace bone matrix based on BoneData.</summary>
|
||||
public static BoneMatrix CalculateSetupWorld (BoneData boneData) {
|
||||
if (boneData == null)
|
||||
return default(BoneMatrix);
|
||||
|
||||
// End condition: isRootBone
|
||||
if (boneData.parent == null)
|
||||
return GetInheritedInternal(boneData, default(BoneMatrix));
|
||||
|
||||
BoneMatrix result = CalculateSetupWorld(boneData.parent);
|
||||
return GetInheritedInternal(boneData, result);
|
||||
}
|
||||
|
||||
static BoneMatrix GetInheritedInternal (BoneData boneData, BoneMatrix parentMatrix) {
|
||||
var parent = boneData.parent;
|
||||
if (parent == null) return new BoneMatrix(boneData); // isRootBone
|
||||
|
||||
float pa = parentMatrix.a, pb = parentMatrix.b, pc = parentMatrix.c, pd = parentMatrix.d;
|
||||
BoneMatrix result = default(BoneMatrix);
|
||||
result.x = pa * boneData.x + pb * boneData.y + parentMatrix.x;
|
||||
result.y = pc * boneData.x + pd * boneData.y + parentMatrix.y;
|
||||
|
||||
switch (boneData.transformMode) {
|
||||
case TransformMode.Normal: {
|
||||
float rotationY = boneData.rotation + 90 + boneData.shearY;
|
||||
float la = MathUtils.CosDeg(boneData.rotation + boneData.shearX) * boneData.scaleX;
|
||||
float lb = MathUtils.CosDeg(rotationY) * boneData.scaleY;
|
||||
float lc = MathUtils.SinDeg(boneData.rotation + boneData.shearX) * boneData.scaleX;
|
||||
float ld = MathUtils.SinDeg(rotationY) * boneData.scaleY;
|
||||
result.a = pa * la + pb * lc;
|
||||
result.b = pa * lb + pb * ld;
|
||||
result.c = pc * la + pd * lc;
|
||||
result.d = pc * lb + pd * ld;
|
||||
break;
|
||||
}
|
||||
case TransformMode.OnlyTranslation: {
|
||||
float rotationY = boneData.rotation + 90 + boneData.shearY;
|
||||
result.a = MathUtils.CosDeg(boneData.rotation + boneData.shearX) * boneData.scaleX;
|
||||
result.b = MathUtils.CosDeg(rotationY) * boneData.scaleY;
|
||||
result.c = MathUtils.SinDeg(boneData.rotation + boneData.shearX) * boneData.scaleX;
|
||||
result.d = MathUtils.SinDeg(rotationY) * boneData.scaleY;
|
||||
break;
|
||||
}
|
||||
case TransformMode.NoRotationOrReflection: {
|
||||
float s = pa * pa + pc * pc, prx;
|
||||
if (s > 0.0001f) {
|
||||
s = Math.Abs(pa * pd - pb * pc) / s;
|
||||
pb = pc * s;
|
||||
pd = pa * s;
|
||||
prx = MathUtils.Atan2(pc, pa) * MathUtils.RadDeg;
|
||||
} else {
|
||||
pa = 0;
|
||||
pc = 0;
|
||||
prx = 90 - MathUtils.Atan2(pd, pb) * MathUtils.RadDeg;
|
||||
}
|
||||
float rx = boneData.rotation + boneData.shearX - prx;
|
||||
float ry = boneData.rotation + boneData.shearY - prx + 90;
|
||||
float la = MathUtils.CosDeg(rx) * boneData.scaleX;
|
||||
float lb = MathUtils.CosDeg(ry) * boneData.scaleY;
|
||||
float lc = MathUtils.SinDeg(rx) * boneData.scaleX;
|
||||
float ld = MathUtils.SinDeg(ry) * boneData.scaleY;
|
||||
result.a = pa * la - pb * lc;
|
||||
result.b = pa * lb - pb * ld;
|
||||
result.c = pc * la + pd * lc;
|
||||
result.d = pc * lb + pd * ld;
|
||||
break;
|
||||
}
|
||||
case TransformMode.NoScale:
|
||||
case TransformMode.NoScaleOrReflection: {
|
||||
float cos = MathUtils.CosDeg(boneData.rotation), sin = MathUtils.SinDeg(boneData.rotation);
|
||||
float za = pa * cos + pb * sin;
|
||||
float zc = pc * cos + pd * sin;
|
||||
float s = (float)Math.Sqrt(za * za + zc * zc);
|
||||
if (s > 0.00001f)
|
||||
s = 1 / s;
|
||||
za *= s;
|
||||
zc *= s;
|
||||
s = (float)Math.Sqrt(za * za + zc * zc);
|
||||
float r = MathUtils.PI / 2 + MathUtils.Atan2(zc, za);
|
||||
float zb = MathUtils.Cos(r) * s;
|
||||
float zd = MathUtils.Sin(r) * s;
|
||||
float la = MathUtils.CosDeg(boneData.shearX) * boneData.scaleX;
|
||||
float lb = MathUtils.CosDeg(90 + boneData.shearY) * boneData.scaleY;
|
||||
float lc = MathUtils.SinDeg(boneData.shearX) * boneData.scaleX;
|
||||
float ld = MathUtils.SinDeg(90 + boneData.shearY) * boneData.scaleY;
|
||||
if (boneData.transformMode != TransformMode.NoScaleOrReflection ? pa * pd - pb * pc < 0 : false) {
|
||||
zb = -zb;
|
||||
zd = -zd;
|
||||
}
|
||||
result.a = za * la + zb * lc;
|
||||
result.b = za * lb + zb * ld;
|
||||
result.c = zc * la + zd * lc;
|
||||
result.d = zc * lb + zd * ld;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>Constructor for a local bone matrix based on Setup Pose BoneData.</summary>
|
||||
public BoneMatrix (BoneData boneData) {
|
||||
float rotationY = boneData.rotation + 90 + boneData.shearY;
|
||||
float rotationX = boneData.rotation + boneData.shearX;
|
||||
|
||||
a = MathUtils.CosDeg(rotationX) * boneData.scaleX;
|
||||
c = MathUtils.SinDeg(rotationX) * boneData.scaleX;
|
||||
b = MathUtils.CosDeg(rotationY) * boneData.scaleY;
|
||||
d = MathUtils.SinDeg(rotationY) * boneData.scaleY;
|
||||
x = boneData.x;
|
||||
y = boneData.y;
|
||||
}
|
||||
|
||||
/// <summary>Constructor for a local bone matrix based on a bone instance's current pose.</summary>
|
||||
public BoneMatrix (Bone bone) {
|
||||
float rotationY = bone.rotation + 90 + bone.shearY;
|
||||
float rotationX = bone.rotation + bone.shearX;
|
||||
|
||||
a = MathUtils.CosDeg(rotationX) * bone.scaleX;
|
||||
c = MathUtils.SinDeg(rotationX) * bone.scaleX;
|
||||
b = MathUtils.CosDeg(rotationY) * bone.scaleY;
|
||||
d = MathUtils.SinDeg(rotationY) * bone.scaleY;
|
||||
x = bone.x;
|
||||
y = bone.y;
|
||||
}
|
||||
|
||||
public BoneMatrix TransformMatrix (BoneMatrix local) {
|
||||
return new BoneMatrix {
|
||||
a = this.a * local.a + this.b * local.c,
|
||||
b = this.a * local.b + this.b * local.d,
|
||||
c = this.c * local.a + this.d * local.c,
|
||||
d = this.c * local.b + this.d * local.d,
|
||||
x = this.a * local.x + this.b * local.y + this.x,
|
||||
y = this.c * local.x + this.d * local.y + this.y
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public static class SkeletonExtensions {
|
||||
public static bool IsWeighted (this VertexAttachment va) {
|
||||
return va.bones != null && va.bones.Length > 0;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user