IkConstraint.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  1. /******************************************************************************
  2. * Spine Runtimes License Agreement
  3. * Last updated January 1, 2020. Replaces all prior versions.
  4. *
  5. * Copyright (c) 2013-2020, Esoteric Software LLC
  6. *
  7. * Integration of the Spine Runtimes into software or otherwise creating
  8. * derivative works of the Spine Runtimes is permitted under the terms and
  9. * conditions of Section 2 of the Spine Editor License Agreement:
  10. * http://esotericsoftware.com/spine-editor-license
  11. *
  12. * Otherwise, it is permitted to integrate the Spine Runtimes into software
  13. * or otherwise create derivative works of the Spine Runtimes (collectively,
  14. * "Products"), provided that each user of the Products must obtain their own
  15. * Spine Editor license and redistribution of the Products in any form must
  16. * include this license and copyright notice.
  17. *
  18. * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
  19. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  20. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  21. * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
  22. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  23. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
  24. * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
  25. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  26. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  27. * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  28. *****************************************************************************/
  29. #ifdef SPINE_UE4
  30. #include "SpinePluginPrivatePCH.h"
  31. #endif
  32. #include <spine/IkConstraint.h>
  33. #include <spine/IkConstraintData.h>
  34. #include <spine/Skeleton.h>
  35. #include <spine/Bone.h>
  36. #include <spine/BoneData.h>
  37. using namespace spine;
  38. RTTI_IMPL(IkConstraint, Updatable)
  39. void IkConstraint::apply(Bone &bone, float targetX, float targetY, bool compress, bool stretch, bool uniform, float alpha) {
  40. Bone *p = bone.getParent();
  41. float pa = p->_a, pb = p->_b, pc = p->_c, pd = p->_d;
  42. float rotationIK = -bone._ashearX - bone._arotation;
  43. float tx = 0, ty = 0;
  44. if (!bone._appliedValid) bone.updateAppliedTransform();
  45. switch(bone._data.getTransformMode()) {
  46. case TransformMode_OnlyTranslation:
  47. tx = targetX - bone._worldX;
  48. ty = targetY - bone._worldY;
  49. break;
  50. case TransformMode_NoRotationOrReflection: {
  51. rotationIK += MathUtil::atan2(pc, pa) * MathUtil::Rad_Deg;
  52. float ps = MathUtil::abs(pa * pd - pb * pc) / (pa * pa + pc * pc);
  53. pb = -pc * ps;
  54. pd = pa * ps;
  55. }
  56. default:
  57. float x = targetX - p->_worldX, y = targetY - p->_worldY;
  58. float d = pa * pd - pb * pc;
  59. tx = (x * pd - y * pb) / d - bone._ax;
  60. ty = (y * pa - x * pc) / d - bone._ay;
  61. }
  62. rotationIK += MathUtil::atan2(ty, tx) * MathUtil::Rad_Deg;
  63. if (bone._ascaleX < 0) rotationIK += 180;
  64. if (rotationIK > 180) rotationIK -= 360;
  65. else if (rotationIK < -180) rotationIK += 360;
  66. float sx = bone._ascaleX;
  67. float sy = bone._ascaleY;
  68. if (compress || stretch) {
  69. switch(bone._data.getTransformMode()) {
  70. case TransformMode_NoScale:
  71. case TransformMode_NoScaleOrReflection:
  72. tx = targetX - bone._worldX;
  73. ty = targetY - bone._worldY;
  74. default: ;
  75. }
  76. float b = bone._data.getLength() * sx, dd = MathUtil::sqrt(tx * tx + ty * ty);
  77. if (((compress && dd < b) || (stretch && dd > b)) && (b > 0.0001f)) {
  78. float s = (dd / b - 1) * alpha + 1;
  79. sx *= s;
  80. if (uniform) sy *= s;
  81. }
  82. }
  83. bone.updateWorldTransform(bone._ax, bone._ay, bone._arotation + rotationIK * alpha, sx, sy, bone._ashearX, bone._ashearY);
  84. }
  85. void IkConstraint::apply(Bone &parent, Bone &child, float targetX, float targetY, int bendDir, bool stretch, float softness, float alpha) {
  86. float a, b, c, d;
  87. float px, py, psx, sx, psy;
  88. float cx, cy, csx, cwx, cwy;
  89. int o1, o2, s2, u;
  90. Bone *pp = parent.getParent();
  91. float tx, ty, dx, dy, dd, l1, l2, a1, a2, r, td, sd, p;
  92. float id, x, y;
  93. if (alpha == 0) {
  94. child.updateWorldTransform();
  95. return;
  96. }
  97. if (!parent._appliedValid) parent.updateAppliedTransform();
  98. if (!child._appliedValid) child.updateAppliedTransform();
  99. px = parent._ax;
  100. py = parent._ay;
  101. psx = parent._ascaleX;
  102. sx = psx;
  103. psy = parent._ascaleY;
  104. csx = child._ascaleX;
  105. if (psx < 0) {
  106. psx = -psx;
  107. o1 = 180;
  108. s2 = -1;
  109. } else {
  110. o1 = 0;
  111. s2 = 1;
  112. }
  113. if (psy < 0) {
  114. psy = -psy;
  115. s2 = -s2;
  116. }
  117. if (csx < 0) {
  118. csx = -csx;
  119. o2 = 180;
  120. } else
  121. o2 = 0;
  122. r = psx - psy;
  123. cx = child._ax;
  124. u = (r < 0 ? -r : r) <= 0.0001f;
  125. if (!u) {
  126. cy = 0;
  127. cwx = parent._a * cx + parent._worldX;
  128. cwy = parent._c * cx + parent._worldY;
  129. } else {
  130. cy = child._ay;
  131. cwx = parent._a * cx + parent._b * cy + parent._worldX;
  132. cwy = parent._c * cx + parent._d * cy + parent._worldY;
  133. }
  134. a = pp->_a;
  135. b = pp->_b;
  136. c = pp->_c;
  137. d = pp->_d;
  138. id = 1 / (a * d - b * c);
  139. x = cwx - pp->_worldX;
  140. y = cwy - pp->_worldY;
  141. dx = (x * d - y * b) * id - px;
  142. dy = (y * a - x * c) * id - py;
  143. l1 = MathUtil::sqrt(dx * dx + dy * dy);
  144. l2 = child._data.getLength() * csx;
  145. if (l1 < 0.0001) {
  146. apply(parent, targetX, targetY, false, stretch, false, alpha);
  147. child.updateWorldTransform(cx, cy, 0, child._ascaleX, child._ascaleY, child._ashearX, child._ashearY);
  148. return;
  149. }
  150. x = targetX - pp->_worldX;
  151. y = targetY - pp->_worldY;
  152. tx = (x * d - y * b) * id - px, ty = (y * a - x * c) * id - py;
  153. dd = tx * tx + ty * ty;
  154. if (softness != 0) {
  155. softness *= psx * (csx + 1) / 2;
  156. td = MathUtil::sqrt(dd), sd = td - l1 - l2 * psx + softness;
  157. if (sd > 0) {
  158. p = MathUtil::min(1.0f, sd / (softness * 2)) - 1;
  159. p = (sd - softness * (1 - p * p)) / td;
  160. tx -= p * tx;
  161. ty -= p * ty;
  162. dd = tx * tx + ty * ty;
  163. }
  164. }
  165. if (u) {
  166. float cosine;
  167. l2 *= psx;
  168. cosine = (dd - l1 * l1 - l2 * l2) / (2 * l1 * l2);
  169. if (cosine < -1) cosine = -1;
  170. else if (cosine > 1) {
  171. cosine = 1;
  172. if (stretch) sx *= (MathUtil::sqrt(dd) / (l1 + l2) - 1) * alpha + 1;
  173. }
  174. a2 = MathUtil::acos(cosine) * bendDir;
  175. a = l1 + l2 * cosine;
  176. b = l2 * MathUtil::sin(a2);
  177. a1 = MathUtil::atan2(ty * a - tx * b, tx * a + ty * b);
  178. } else {
  179. a = psx * l2, b = psy * l2;
  180. float aa = a * a, bb = b * b, ll = l1 * l1, ta = MathUtil::atan2(ty, tx);
  181. float c0 = bb * ll + aa * dd - aa * bb, c1 = -2 * bb * l1, c2 = bb - aa;
  182. d = c1 * c1 - 4 * c2 * c0;
  183. if (d >= 0) {
  184. float q = MathUtil::sqrt(d), r0, r1;
  185. if (c1 < 0) q = -q;
  186. q = -(c1 + q) / 2;
  187. r0 = q / c2;
  188. r1 = c0 / q;
  189. r = MathUtil::abs(r0) < MathUtil::abs(r1) ? r0 : r1;
  190. if (r * r <= dd) {
  191. y = MathUtil::sqrt(dd - r * r) * bendDir;
  192. a1 = ta - MathUtil::atan2(y, r);
  193. a2 = MathUtil::atan2(y / psy, (r - l1) / psx);
  194. goto break_outer;
  195. }
  196. }
  197. {
  198. float minAngle = MathUtil::Pi, minX = l1 - a, minDist = minX * minX, minY = 0;
  199. float maxAngle = 0, maxX = l1 + a, maxDist = maxX * maxX, maxY = 0;
  200. c0 = -a * l1 / (aa - bb);
  201. if (c0 >= -1 && c0 <= 1) {
  202. c0 = MathUtil::acos(c0);
  203. x = a * MathUtil::cos(c0) + l1;
  204. y = b * MathUtil::sin(c0);
  205. d = x * x + y * y;
  206. if (d < minDist) {
  207. minAngle = c0;
  208. minDist = d;
  209. minX = x;
  210. minY = y;
  211. }
  212. if (d > maxDist) {
  213. maxAngle = c0;
  214. maxDist = d;
  215. maxX = x;
  216. maxY = y;
  217. }
  218. }
  219. if (dd <= (minDist + maxDist) / 2) {
  220. a1 = ta - MathUtil::atan2(minY * bendDir, minX);
  221. a2 = minAngle * bendDir;
  222. } else {
  223. a1 = ta - MathUtil::atan2(maxY * bendDir, maxX);
  224. a2 = maxAngle * bendDir;
  225. }
  226. }
  227. }
  228. break_outer:
  229. {
  230. float os = MathUtil::atan2(cy, cx) * s2;
  231. a1 = (a1 - os) * MathUtil::Rad_Deg + o1 - parent._arotation;
  232. if (a1 > 180) a1 -= 360;
  233. else if (a1 < -180) a1 += 360;
  234. parent.updateWorldTransform(px, py, parent._rotation + a1 * alpha, sx, parent._ascaleY, 0, 0);
  235. a2 = ((a2 + os) * MathUtil::Rad_Deg - child._ashearX) * s2 + o2 - child._arotation;
  236. if (a2 > 180) a2 -= 360;
  237. else if (a2 < -180) a2 += 360;
  238. child.updateWorldTransform(cx, cy, child._arotation + a2 * alpha, child._ascaleX, child._ascaleY, child._ashearX, child._ashearY);
  239. }
  240. }
  241. IkConstraint::IkConstraint(IkConstraintData &data, Skeleton &skeleton) : Updatable(),
  242. _data(data),
  243. _bendDirection(data.getBendDirection()),
  244. _compress(data.getCompress()),
  245. _stretch(data.getStretch()),
  246. _mix(data.getMix()),
  247. _softness(data.getSoftness()),
  248. _target(skeleton.findBone(
  249. data.getTarget()->getName())),
  250. _active(false)
  251. {
  252. _bones.ensureCapacity(_data.getBones().size());
  253. for (size_t i = 0; i < _data.getBones().size(); i++) {
  254. BoneData *boneData = _data.getBones()[i];
  255. _bones.add(skeleton.findBone(boneData->getName()));
  256. }
  257. }
  258. /// Applies the constraint to the constrained bones.
  259. void IkConstraint::apply() {
  260. update();
  261. }
  262. void IkConstraint::update() {
  263. switch (_bones.size()) {
  264. case 1: {
  265. Bone *bone0 = _bones[0];
  266. apply(*bone0, _target->getWorldX(), _target->getWorldY(), _compress, _stretch, _data._uniform, _mix);
  267. }
  268. break;
  269. case 2: {
  270. Bone *bone0 = _bones[0];
  271. Bone *bone1 = _bones[1];
  272. apply(*bone0, *bone1, _target->getWorldX(), _target->getWorldY(), _bendDirection, _stretch, _softness, _mix);
  273. }
  274. break;
  275. }
  276. }
  277. int IkConstraint::getOrder() {
  278. return _data.getOrder();
  279. }
  280. IkConstraintData &IkConstraint::getData() {
  281. return _data;
  282. }
  283. Vector<Bone *> &IkConstraint::getBones() {
  284. return _bones;
  285. }
  286. Bone *IkConstraint::getTarget() {
  287. return _target;
  288. }
  289. void IkConstraint::setTarget(Bone *inValue) {
  290. _target = inValue;
  291. }
  292. int IkConstraint::getBendDirection() {
  293. return _bendDirection;
  294. }
  295. void IkConstraint::setBendDirection(int inValue) {
  296. _bendDirection = inValue;
  297. }
  298. float IkConstraint::getMix() {
  299. return _mix;
  300. }
  301. void IkConstraint::setMix(float inValue) {
  302. _mix = inValue;
  303. }
  304. bool IkConstraint::getStretch() {
  305. return _stretch;
  306. }
  307. void IkConstraint::setStretch(bool inValue) {
  308. _stretch = inValue;
  309. }
  310. bool IkConstraint::getCompress() {
  311. return _compress;
  312. }
  313. void IkConstraint::setCompress(bool inValue) {
  314. _compress = inValue;
  315. }
  316. bool IkConstraint::isActive() {
  317. return _active;
  318. }
  319. void IkConstraint::setActive(bool inValue) {
  320. _active = inValue;
  321. }
  322. float IkConstraint::getSoftness() {
  323. return _softness;
  324. }
  325. void IkConstraint::setSoftness(float inValue) {
  326. _softness = inValue;
  327. }