CubismPhysicsSubRig.cs 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. /**
  2. * Copyright(c) Live2D Inc. All rights reserved.
  3. *
  4. * Use of this source code is governed by the Live2D Open Software license
  5. * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html.
  6. */
  7. using Live2D.Cubism.Core;
  8. using System;
  9. using UnityEngine;
  10. namespace Live2D.Cubism.Framework.Physics
  11. {
  12. /// <summary>
  13. /// Children of rig.
  14. /// </summary>
  15. [Serializable]
  16. public class CubismPhysicsSubRig
  17. {
  18. /// <summary>
  19. /// Input.
  20. /// </summary>
  21. [SerializeField]
  22. public CubismPhysicsInput[] Input;
  23. /// <summary>
  24. /// Output.
  25. /// </summary>
  26. [SerializeField]
  27. public CubismPhysicsOutput[] Output;
  28. /// <summary>
  29. /// Particles.
  30. /// </summary>
  31. [SerializeField]
  32. public CubismPhysicsParticle[] Particles;
  33. /// <summary>
  34. /// Normalization.
  35. /// </summary>
  36. [SerializeField]
  37. public CubismPhysicsNormalization Normalization;
  38. /// <summary>
  39. /// Rig.
  40. /// </summary>
  41. public CubismPhysicsRig Rig
  42. {
  43. get { return _rig; }
  44. set { _rig = value; }
  45. }
  46. [NonSerialized]
  47. private CubismPhysicsRig _rig;
  48. /// <summary>
  49. /// Updates parameter from output value.
  50. /// </summary>
  51. /// <param name="parameter">Target parameter.</param>
  52. /// <param name="translation">Translation.</param>
  53. /// <param name="output">Output value.</param>
  54. private void UpdateOutputParameterValue(CubismParameter parameter, float translation, CubismPhysicsOutput output)
  55. {
  56. var outputScale = 1.0f;
  57. outputScale = output.GetScale();
  58. var value = translation * outputScale;
  59. if (value < parameter.MinimumValue)
  60. {
  61. if (value < output.ValueBelowMinimum)
  62. {
  63. output.ValueBelowMinimum = value;
  64. }
  65. value = parameter.MinimumValue;
  66. }
  67. else if (value > parameter.MaximumValue)
  68. {
  69. if (value > output.ValueExceededMaximum)
  70. {
  71. output.ValueExceededMaximum = value;
  72. }
  73. value = parameter.MaximumValue;
  74. }
  75. var weight = (output.Weight / CubismPhysics.MaximumWeight);
  76. if (weight >= 1.0f)
  77. {
  78. parameter.Value = value;
  79. }
  80. else
  81. {
  82. value = (parameter.Value * (1.0f - weight)) + (value * weight);
  83. parameter.Value = value;
  84. }
  85. }
  86. /// <summary>
  87. /// Updates particles in every frame.
  88. /// </summary>
  89. /// <param name="strand">Particles.</param>
  90. /// <param name="totalTranslation">Total translation.</param>
  91. /// <param name="totalAngle">Total angle.</param>
  92. /// <param name="wind">Direction of wind.</param>
  93. /// <param name="thresholdValue">Value of threshold.</param>
  94. /// <param name="deltaTime">Time of delta.</param>
  95. private void UpdateParticles(
  96. CubismPhysicsParticle[] strand,
  97. Vector2 totalTranslation,
  98. float totalAngle,
  99. Vector2 wind,
  100. float thresholdValue,
  101. float deltaTime
  102. )
  103. {
  104. strand[0].Position = totalTranslation;
  105. var totalRadian = CubismPhysicsMath.DegreesToRadian(totalAngle);
  106. var currentGravity = CubismPhysicsMath.RadianToDirection(totalRadian);
  107. currentGravity.Normalize();
  108. for (var i = 1; i < strand.Length; ++i)
  109. {
  110. strand[i].Force = (currentGravity * strand[i].Acceleration) + wind;
  111. strand[i].LastPosition = strand[i].Position;
  112. // The Cubism Editor expects 30 FPS so we scale here by 30...
  113. var delay = strand[i].Delay * deltaTime * 30.0f;
  114. var direction = strand[i].Position - strand[i - 1].Position;
  115. var radian = CubismPhysicsMath.DirectionToRadian(strand[i].LastGravity, currentGravity) / CubismPhysics.AirResistance;
  116. direction.x = ((Mathf.Cos(radian) * direction.x) - (direction.y * Mathf.Sin(radian)));
  117. direction.y = ((Mathf.Sin(radian) * direction.x) + (direction.y * Mathf.Cos(radian)));
  118. strand[i].Position = strand[i - 1].Position + direction;
  119. var velocity = strand[i].Velocity * delay;
  120. var force = strand[i].Force * delay * delay;
  121. strand[i].Position = strand[i].Position + velocity + force;
  122. var newDirection = strand[i].Position - strand[i - 1].Position;
  123. newDirection.Normalize();
  124. strand[i].Position = strand[i - 1].Position + newDirection * strand[i].Radius;
  125. if (Mathf.Abs(strand[i].Position.x) < thresholdValue)
  126. {
  127. strand[i].Position.x = 0.0f;
  128. }
  129. if (delay != 0.0f)
  130. {
  131. strand[i].Velocity =
  132. ((strand[i].Position - strand[i].LastPosition) / delay) * strand[i].Mobility;
  133. }
  134. strand[i].Force = Vector2.zero;
  135. strand[i].LastGravity = currentGravity;
  136. }
  137. }
  138. /// <summary>
  139. /// Initializes <see langword="this"/>.
  140. /// </summary>
  141. public void Initialize()
  142. {
  143. var strand = Particles;
  144. // Initialize the top of particle.
  145. strand[0].InitialPosition = Vector2.zero;
  146. strand[0].LastPosition = strand[0].InitialPosition;
  147. strand[0].LastGravity = Rig.Gravity;
  148. strand[0].LastGravity.y *= -1.0f;
  149. // Initialize particles.
  150. for (var i = 1; i < strand.Length; ++i)
  151. {
  152. var radius = Vector2.zero;
  153. radius.y = strand[i].Radius;
  154. strand[i].InitialPosition = strand[i - 1].InitialPosition + radius;
  155. strand[i].Position = strand[i].InitialPosition;
  156. strand[i].LastPosition = strand[i].InitialPosition;
  157. strand[i].LastGravity = Rig.Gravity;
  158. strand[i].LastGravity.y *= -1.0f;
  159. }
  160. // Initialize inputs.
  161. for (var i = 0; i < Input.Length; ++i)
  162. {
  163. Input[i].InitializeGetter();
  164. }
  165. // Initialize outputs.
  166. for (var i = 0; i < Output.Length; ++i)
  167. {
  168. Output[i].InitializeGetter();
  169. }
  170. }
  171. /// <summary>
  172. /// Evaluate rig in every frame.
  173. /// </summary>
  174. /// <param name="deltaTime"></param>
  175. public void Evaluate(float deltaTime)
  176. {
  177. var totalAngle = 0.0f;
  178. var totalTranslation = Vector2.zero;
  179. for (var i = 0; i < Input.Length; ++i)
  180. {
  181. var weight = Input[i].Weight / CubismPhysics.MaximumWeight;
  182. if (Input[i].Source == null)
  183. {
  184. Input[i].Source = Rig.Controller.Parameters.FindById(Input[i].SourceId);
  185. }
  186. var parameter = Input[i].Source;
  187. Input[i].GetNormalizedParameterValue(
  188. ref totalTranslation,
  189. ref totalAngle,
  190. parameter,
  191. Normalization,
  192. weight
  193. );
  194. }
  195. var radAngle = CubismPhysicsMath.DegreesToRadian(-totalAngle);
  196. totalTranslation.x = (totalTranslation.x * Mathf.Cos(radAngle) - totalTranslation.y * Mathf.Sin(radAngle));
  197. totalTranslation.y = (totalTranslation.x * Mathf.Sin(radAngle) + totalTranslation.y * Mathf.Cos(radAngle));
  198. UpdateParticles(
  199. Particles,
  200. totalTranslation,
  201. totalAngle,
  202. Rig.Wind,
  203. CubismPhysics.MovementThreshold * Normalization.Position.Maximum,
  204. deltaTime
  205. );
  206. for (var i = 0; i < Output.Length; ++i)
  207. {
  208. var particleIndex = Output[i].ParticleIndex;
  209. if (particleIndex < 1 || particleIndex >= Particles.Length)
  210. {
  211. break;
  212. }
  213. if (Output[i].Destination == null)
  214. {
  215. Output[i].Destination = Rig.Controller.Parameters.FindById(Output[i].DestinationId);
  216. }
  217. var parameter = Output[i].Destination;
  218. var translation = Particles[particleIndex].Position -
  219. Particles[particleIndex - 1].Position;
  220. var outputValue = Output[i].GetValue(
  221. translation,
  222. parameter,
  223. Particles,
  224. particleIndex,
  225. Rig.Gravity
  226. );
  227. UpdateOutputParameterValue(parameter, outputValue, Output[i]);
  228. }
  229. }
  230. }
  231. }