MegaBezFloatKeyControl.cs 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. 
  2. using UnityEngine;
  3. using System.IO;
  4. [System.Serializable]
  5. public class MegaBezFloatKey
  6. {
  7. public float val;
  8. public float intan;
  9. public float outtan;
  10. public float intanx;
  11. public float outtanx;
  12. public float coef0;
  13. public float coef1;
  14. public float coef2;
  15. public float coef3;
  16. }
  17. [System.Serializable]
  18. public class MegaBezFloatKeyControl : MegaControl
  19. {
  20. public MegaBezFloatKey[] Keys;
  21. private const float SCALE = 4800.0f;
  22. public float f;
  23. //public float[] Times;
  24. //[HideInInspector]
  25. //public int lastkey = 0;
  26. //[HideInInspector]
  27. //public float lasttime = 0.0f;
  28. //public virtual float GetFloat(float time) { return 0.0f; }
  29. #if false
  30. int BinSearch(float t, int low, int high)
  31. {
  32. int probe = 0;
  33. while ( high - low > 1 )
  34. {
  35. probe = (high + low) / 2;
  36. if ( t < Times[probe] )
  37. high = probe;
  38. else
  39. {
  40. if ( t > Times[probe + 1] )
  41. low = probe;
  42. else
  43. break; // found
  44. }
  45. }
  46. return probe;
  47. }
  48. // get index
  49. // do a range check, anim code should keep the t in range
  50. public int GetKey(float t)
  51. {
  52. if ( t <= Times[1] )
  53. return 0;
  54. if ( t >= Times[Times.Length - 1] )
  55. return Times.Length - 2;
  56. // Cache result and then do a bin search
  57. int key = lastkey;
  58. if ( t >= Times[key] && t < Times[key + 1] )
  59. return key; // we get past this if out of time range of whole anim
  60. return BinSearch(t, -1, Times.Length - 1);
  61. }
  62. #endif
  63. public void InitKeys()
  64. {
  65. for ( int i = 0; i < Keys.Length - 1; i++ )
  66. {
  67. float dt = Times[i + 1] - Times[i];
  68. float hout = Keys[i].val + (Keys[i].outtan * SCALE) * (dt / 3.0f);
  69. float hin = Keys[i + 1].val + (Keys[i + 1].intan * SCALE) * (dt / 3.0f);
  70. Keys[i].coef1 = Keys[i + 1].val + 3.0f * (hout - hin) - Keys[i].val;
  71. Keys[i].coef2 = 3.0f * (hin - 2.0f * hout + Keys[i].val);
  72. Keys[i].coef3 = 3.0f * (hout - Keys[i].val);
  73. }
  74. }
  75. public void InitKeys(float scale)
  76. {
  77. for ( int i = 0; i < Keys.Length - 1; i++ )
  78. {
  79. float dt = Times[i + 1] - Times[i];
  80. float hout = Keys[i].val + (Keys[i].outtan * scale) * (dt / 3.0f);
  81. float hin = Keys[i + 1].val + (Keys[i + 1].intan * scale) * (dt / 3.0f);
  82. Keys[i].coef1 = Keys[i + 1].val + 3.0f * (hout - hin) - Keys[i].val;
  83. Keys[i].coef2 = 3.0f * (hin - 2.0f * hout + Keys[i].val);
  84. Keys[i].coef3 = 3.0f * (hout - Keys[i].val);
  85. }
  86. }
  87. public void InitKeysMaya()
  88. {
  89. for ( int i = 0; i < Keys.Length - 1; i++ )
  90. {
  91. float x0 = Times[i];
  92. float x1 = Times[i] + Keys[i].outtanx;
  93. float x2 = Times[i + 1] - Keys[i + 1].intanx;
  94. float x3 = Times[i + 1];
  95. float y0 = Keys[i].val;
  96. float y1 = Keys[i].val + Keys[i].outtan;
  97. float y2 = Keys[i + 1].val - Keys[i + 1].intan;
  98. float y3 = Keys[i + 1].val;
  99. float dx = x3 - x0;
  100. float dy = y3 - y0;
  101. float tan_x = x1 - x0;
  102. float m1 = 0.0f;
  103. float m2 = 0.0f;
  104. if ( tan_x != 0.0f )
  105. m1 = (y1 - y0) / tan_x;
  106. tan_x = x3 - x2;
  107. if ( tan_x != 0.0f )
  108. m2 = (y3 - y2) / tan_x;
  109. float length = 1.0f / (dx * dx);
  110. float d1 = dx * m1;
  111. float d2 = dx * m2;
  112. Keys[i].coef0 = (d1 + d2 - dy - dy) * length / dx;
  113. Keys[i].coef1 = (dy + dy + dy - d1 - d1 - d2) * length;
  114. Keys[i].coef2 = m1;
  115. Keys[i].coef3 = y0;
  116. }
  117. }
  118. public float GetHermiteFloat(float tt)
  119. {
  120. if ( Times.Length == 1 )
  121. return Keys[0].val;
  122. int key = GetKey(tt);
  123. float t = Mathf.Clamp01((tt - Times[key]) / (Times[key + 1] - Times[key]));
  124. t = Mathf.Lerp(Times[key], Times[key + 1], t) - Times[key];
  125. return (t * (t * (t * Keys[key].coef0 + Keys[key].coef1) + Keys[key].coef2) + Keys[key].coef3);
  126. }
  127. public void MakeKey(MegaBezFloatKey key, Vector2 pco, Vector2 pleft, Vector2 pright, Vector2 co, Vector2 left, Vector2 right)
  128. {
  129. float f1 = pco.y * 100.0f;
  130. float f2 = pright.y * 100.0f;
  131. float f3 = left.y * 100.0f;
  132. float f4 = co.y * 100.0f;
  133. key.val = f1;
  134. key.coef3 = 3.0f * (f2 - f1);
  135. key.coef2 = 3.0f * (f1 - 2.0f * f2 + f3);
  136. key.coef1 = f4 - f1 + 3.0f * (f2 - f3);
  137. }
  138. #if false
  139. public bool Parse(BinaryReader br, string id)
  140. {
  141. switch ( id )
  142. {
  143. case "Num":
  144. int num = br.ReadInt32();
  145. Keys = new MegaBezFloatKey[num];
  146. Times = new float[num];
  147. break;
  148. case "Keys":
  149. for ( int i = 0; i < Keys.Length; i++ )
  150. {
  151. Keys[i] = new MegaBezFloatKey();
  152. Keys[i].val = br.ReadSingle();
  153. Keys[i].intan = br.ReadSingle();
  154. Keys[i].outtan = br.ReadSingle();
  155. Times[i] = br.ReadSingle();
  156. }
  157. InitKeys();
  158. break;
  159. case "BKeys": // Blender keys
  160. Vector2 co = Vector2.zero;
  161. Vector2 left = Vector2.zero;
  162. Vector3 right = Vector2.zero;
  163. Vector2 pco = Vector2.zero;
  164. Vector2 pleft = Vector2.zero;
  165. Vector3 pright = Vector2.zero;
  166. for ( int i = 0; i < Keys.Length; i++ )
  167. {
  168. Keys[i] = new MegaBezFloatKey();
  169. co.x = br.ReadSingle();
  170. co.y = br.ReadSingle();
  171. left.x = br.ReadSingle();
  172. left.y = br.ReadSingle();
  173. right.x = br.ReadSingle();
  174. right.y = br.ReadSingle();
  175. if ( i > 0 )
  176. MakeKey(Keys[i - 1], pco, pleft, pright, co, left, right);
  177. pco = co;
  178. pleft = left;
  179. pright = right;
  180. Times[i] = co.x / 30.0f;
  181. }
  182. break;
  183. }
  184. return true;
  185. }
  186. #endif
  187. //public override void Interp(float alpha, int key)
  188. public void Interp(float alpha, int key)
  189. {
  190. if ( alpha == 0.0f )
  191. f = Keys[key].val;
  192. else
  193. {
  194. if ( alpha == 1.0f )
  195. f = Keys[key + 1].val;
  196. else
  197. {
  198. float tp2 = alpha * alpha;
  199. float tp3 = tp2 * alpha;
  200. f = Keys[key].coef1 * tp3 + Keys[key].coef2 * tp2 + Keys[key].coef3 * alpha + Keys[key].val;
  201. }
  202. }
  203. }
  204. public override float GetFloat(float t)
  205. {
  206. if ( Times.Length == 1 )
  207. {
  208. return Keys[0].val;
  209. }
  210. int key = GetKey(t);
  211. float alpha = (t - Times[key]) / (Times[key + 1] - Times[key]);
  212. if ( alpha < 0.0f )
  213. alpha = 0.0f;
  214. else
  215. {
  216. if ( alpha > 1.0f )
  217. alpha = 1.0f;
  218. }
  219. // Do ease and hermite here maybe
  220. Interp(alpha, key);
  221. lastkey = key;
  222. lasttime = t;
  223. return f;
  224. }
  225. }