ClampPositionConstraint.cs 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. // Magica Cloth.
  2. // Copyright (c) MagicaSoft, 2020-2022.
  3. // https://magicasoft.jp
  4. using Unity.Burst;
  5. using Unity.Collections;
  6. using Unity.Jobs;
  7. using Unity.Mathematics;
  8. namespace MagicaCloth
  9. {
  10. /// <summary>
  11. /// 移動範囲制限距離拘束
  12. /// nextposおよびposを原点からの距離制限する
  13. /// </summary>
  14. public class ClampPositionConstraint : PhysicsManagerConstraint
  15. {
  16. /// <summary>
  17. /// グループごとの拘束データ
  18. /// </summary>
  19. public struct GroupData
  20. {
  21. public int teamId;
  22. public int active;
  23. public CurveParam limitLength;
  24. /// <summary>
  25. /// 軸ごとの移動制限割合(0.0-1.0)
  26. /// </summary>
  27. public float3 axisRatio;
  28. /// <summary>
  29. /// 速度影響
  30. /// </summary>
  31. public float velocityInfluence;
  32. /// <summary>
  33. /// データが軸ごとの制限を行うか判定する
  34. /// </summary>
  35. /// <returns></returns>
  36. public bool IsAxisCheck()
  37. {
  38. return axisRatio.x < 0.999f || axisRatio.y < 0.999f || axisRatio.z < 0.999f;
  39. }
  40. }
  41. public FixedNativeList<GroupData> groupList;
  42. //=========================================================================================
  43. public override void Create()
  44. {
  45. groupList = new FixedNativeList<GroupData>();
  46. }
  47. public override void Release()
  48. {
  49. groupList.Dispose();
  50. }
  51. //=========================================================================================
  52. public int AddGroup(int teamId, bool active, BezierParam limitLength, float3 axisRatio, float velocityInfluence)
  53. {
  54. var teamData = MagicaPhysicsManager.Instance.Team.teamDataList[teamId];
  55. var gdata = new GroupData();
  56. gdata.teamId = teamId;
  57. gdata.active = active ? 1 : 0;
  58. gdata.limitLength.Setup(limitLength);
  59. gdata.axisRatio = axisRatio;
  60. gdata.velocityInfluence = velocityInfluence;
  61. int group = groupList.Add(gdata);
  62. return group;
  63. }
  64. public override void RemoveTeam(int teamId)
  65. {
  66. var teamData = MagicaPhysicsManager.Instance.Team.teamDataList[teamId];
  67. int group = teamData.clampPositionGroupIndex;
  68. if (group < 0)
  69. return;
  70. // データ削除
  71. groupList.Remove(group);
  72. }
  73. public void ChangeParam(int teamId, bool active, BezierParam limitLength, float3 axisRatio, float velocityInfluence)
  74. {
  75. var teamData = MagicaPhysicsManager.Instance.Team.teamDataList[teamId];
  76. int group = teamData.clampPositionGroupIndex;
  77. if (group < 0)
  78. return;
  79. var gdata = groupList[group];
  80. gdata.active = active ? 1 : 0;
  81. gdata.limitLength.Setup(limitLength);
  82. gdata.axisRatio = axisRatio;
  83. gdata.velocityInfluence = velocityInfluence;
  84. groupList[group] = gdata;
  85. }
  86. //=========================================================================================
  87. /// <summary>
  88. /// 拘束の解決
  89. /// </summary>
  90. /// <param name="dtime"></param>
  91. /// <param name="jobHandle"></param>
  92. /// <returns></returns>
  93. public override JobHandle SolverConstraint(int runCount, float dtime, float updatePower, int iteration, JobHandle jobHandle)
  94. {
  95. if (groupList.Count == 0)
  96. return jobHandle;
  97. // 移動範囲制限拘束(パーティクルごとに実行する)
  98. var job1 = new ClampPositionJob()
  99. {
  100. runCount = runCount,
  101. maxMoveLength = dtime * Define.Compute.ClampPositionMaxVelocity, // 最大1.0m/s
  102. clampPositionGroupList = groupList.ToJobArray(),
  103. teamDataList = Manager.Team.teamDataList.ToJobArray(),
  104. teamIdList = Manager.Particle.teamIdList.ToJobArray(),
  105. flagList = Manager.Particle.flagList.ToJobArray(),
  106. depthList = Manager.Particle.depthList.ToJobArray(),
  107. basePosList = Manager.Particle.basePosList.ToJobArray(),
  108. baseRotList = Manager.Particle.baseRotList.ToJobArray(),
  109. frictionList = Manager.Particle.frictionList.ToJobArray(),
  110. nextPosList = Manager.Particle.InNextPosList.ToJobArray(),
  111. posList = Manager.Particle.posList.ToJobArray(),
  112. };
  113. jobHandle = job1.Schedule(Manager.Particle.Length, 64, jobHandle);
  114. return jobHandle;
  115. }
  116. /// <summary>
  117. /// 移動範囲制限拘束ジョブ
  118. /// パーティクルごとに計算
  119. /// </summary>
  120. [BurstCompile]
  121. struct ClampPositionJob : IJobParallelFor
  122. {
  123. public int runCount;
  124. // 最大移動距離
  125. public float maxMoveLength;
  126. [Unity.Collections.ReadOnly]
  127. public NativeArray<GroupData> clampPositionGroupList;
  128. [Unity.Collections.ReadOnly]
  129. public NativeArray<PhysicsManagerTeamData.TeamData> teamDataList;
  130. [Unity.Collections.ReadOnly]
  131. public NativeArray<int> teamIdList;
  132. [Unity.Collections.ReadOnly]
  133. public NativeArray<PhysicsManagerParticleData.ParticleFlag> flagList;
  134. [Unity.Collections.ReadOnly]
  135. public NativeArray<float> depthList;
  136. [Unity.Collections.ReadOnly]
  137. public NativeArray<float3> basePosList;
  138. [Unity.Collections.ReadOnly]
  139. public NativeArray<quaternion> baseRotList;
  140. [Unity.Collections.ReadOnly]
  141. public NativeArray<float> frictionList;
  142. public NativeArray<float3> nextPosList;
  143. public NativeArray<float3> posList;
  144. // パーティクルごと
  145. public void Execute(int index)
  146. {
  147. var flag = flagList[index];
  148. if (flag.IsValid() == false || flag.IsFixed())
  149. return;
  150. var team = teamDataList[teamIdList[index]];
  151. if (team.IsActive() == false)
  152. return;
  153. if (team.clampPositionGroupIndex < 0)
  154. return;
  155. // 更新確認
  156. if (team.IsUpdate(runCount) == false)
  157. return;
  158. // グループデータ
  159. var gdata = clampPositionGroupList[team.clampPositionGroupIndex];
  160. if (gdata.active == 0)
  161. return;
  162. var nextpos = nextPosList[index];
  163. var depth = depthList[index];
  164. var limitLength = gdata.limitLength.Evaluate(depth);
  165. // チームスケール倍率
  166. limitLength *= team.scaleRatio;
  167. // baseposからの最大移動距離制限
  168. var basepos = basePosList[index];
  169. var v = nextpos - basepos; // nextpos
  170. // 摩擦係数から移動率を算出
  171. var friction = frictionList[index];
  172. float moveratio = math.saturate(1.0f - friction * Define.Compute.FrictionMoveRatio);
  173. if (gdata.IsAxisCheck())
  174. {
  175. // 楕円体判定
  176. float3 axisRatio = gdata.axisRatio;
  177. // 基準軸のワールド回転
  178. quaternion rot = baseRotList[index];
  179. // 基準軸のローカルベクトルへ変換
  180. quaternion irot = math.inverse(rot);
  181. float3 lv = math.mul(irot, v);
  182. // Boxクランプ
  183. float3 axisRatio1 = axisRatio * limitLength;
  184. lv = math.clamp(lv, -axisRatio1, axisRatio1);
  185. // 基準軸のワールドベクトルへ変換
  186. // 最終的に(v)が楕円体でクランプされた移動制限ベクトルとなる
  187. v = math.mul(rot, lv);
  188. }
  189. // nextposの制限
  190. v = MathUtility.ClampVector(v, 0.0f, limitLength);
  191. // 最大速度クランプ
  192. v = (basepos + v) - nextpos;
  193. // 移動位置
  194. var opos = nextpos;
  195. var fpos = opos + v;
  196. // 摩擦係数による移動制限(衝突しているパーティクルは動きづらい)
  197. nextpos = math.lerp(opos, fpos, moveratio);
  198. // 書き込み
  199. nextPosList[index] = nextpos;
  200. // 速度影響
  201. var av = (nextpos - opos) * (1.0f - gdata.velocityInfluence);
  202. posList[index] = posList[index] + av;
  203. }
  204. }
  205. }
  206. }