ColliderExtrusionConstraint.cs 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  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. /// </summary>
  13. public class ColliderExtrusionConstraint : PhysicsManagerConstraint
  14. {
  15. public override void Create()
  16. {
  17. }
  18. public override void RemoveTeam(int teamId)
  19. {
  20. }
  21. // public void ChangeParam(int teamId, bool useCollision)
  22. // {
  23. // Manager.Team.SetFlag(teamId, PhysicsManagerTeamData.Flag_Collision, useCollision);
  24. // }
  25. public override void Release()
  26. {
  27. }
  28. //=========================================================================================
  29. public override JobHandle SolverConstraint(int runCount, float dtime, float updatePower, int iteration, JobHandle jobHandle)
  30. {
  31. if (Manager.Particle.ColliderCount <= 0)
  32. return jobHandle;
  33. #if true
  34. // コリジョン押し出し拘束
  35. var job1 = new CollisionExtrusionJob()
  36. {
  37. runCount = runCount,
  38. flagList = Manager.Particle.flagList.ToJobArray(),
  39. teamIdList = Manager.Particle.teamIdList.ToJobArray(),
  40. nextPosList = Manager.Particle.InNextPosList.ToJobArray(),
  41. nextRotList = Manager.Particle.InNextRotList.ToJobArray(),
  42. collisionLinkIdList = Manager.Particle.collisionLinkIdList.ToJobArray(),
  43. posList = Manager.Particle.posList.ToJobArray(),
  44. rotList = Manager.Particle.rotList.ToJobArray(),
  45. frictionList = Manager.Particle.frictionList.ToJobArray(),
  46. collisionNormalList = Manager.Particle.collisionNormalList.ToJobArray(),
  47. teamDataList = Manager.Team.teamDataList.ToJobArray(),
  48. };
  49. jobHandle = job1.Schedule(Manager.Particle.Length, 64, jobHandle);
  50. #endif
  51. return jobHandle;
  52. }
  53. //=========================================================================================
  54. /// <summary>
  55. /// コリジョン押し出し拘束ジョブ
  56. /// 移動パーティクルごとに計算
  57. /// </summary>
  58. [BurstCompile]
  59. struct CollisionExtrusionJob : IJobParallelFor
  60. {
  61. public int runCount;
  62. [Unity.Collections.ReadOnly]
  63. public NativeArray<PhysicsManagerParticleData.ParticleFlag> flagList;
  64. [Unity.Collections.ReadOnly]
  65. public NativeArray<int> teamIdList;
  66. [NativeDisableParallelForRestriction]
  67. public NativeArray<float3> nextPosList;
  68. [Unity.Collections.ReadOnly]
  69. public NativeArray<quaternion> nextRotList;
  70. public NativeArray<int> collisionLinkIdList;
  71. [NativeDisableParallelForRestriction]
  72. public NativeArray<float3> posList;
  73. [Unity.Collections.ReadOnly]
  74. public NativeArray<quaternion> rotList;
  75. [Unity.Collections.ReadOnly]
  76. public NativeArray<float> frictionList;
  77. [Unity.Collections.ReadOnly]
  78. public NativeArray<float3> collisionNormalList;
  79. [Unity.Collections.ReadOnly]
  80. public NativeArray<PhysicsManagerTeamData.TeamData> teamDataList;
  81. // パーティクルごと
  82. public void Execute(int index)
  83. {
  84. var flag = flagList[index];
  85. if (flag.IsValid() == false || flag.IsFixed() || flag.IsCollider())
  86. return;
  87. // チーム
  88. var team = teamIdList[index];
  89. var teamData = teamDataList[team];
  90. if (teamData.IsActive() == false)
  91. return;
  92. if (teamData.IsFlag(PhysicsManagerTeamData.Flag_Collision) == false)
  93. return;
  94. // 更新確認
  95. if (teamData.IsUpdate(runCount) == false)
  96. return;
  97. // 接続コライダー
  98. int cindex = collisionLinkIdList[index];
  99. collisionLinkIdList[index] = 0; // リセット
  100. if (cindex <= 0)
  101. return;
  102. var cflag = flagList[cindex];
  103. if (cflag.IsValid() == false || cflag.IsCollider() == false)
  104. return;
  105. var friction = frictionList[index];
  106. if (friction < Define.Compute.Epsilon)
  107. return;
  108. float3 nextpos = nextPosList[index];
  109. //int vindex = index - teamData.particleChunk.startIndex;
  110. //Debug.Log($"vindex:{vindex}");
  111. // 移動前コライダー姿勢
  112. var oldcpos = posList[cindex];
  113. var oldcrot = rotList[cindex];
  114. var v = nextpos - oldcpos; // nextposでないとダメ(oldPosList[index]ではまずい)
  115. var ioldcrot = math.inverse(oldcrot);
  116. var lpos = math.mul(ioldcrot, v);
  117. // 移動後コライダー姿勢
  118. var cpos = nextPosList[cindex];
  119. var crot = nextRotList[cindex];
  120. var fpos = math.mul(crot, lpos) + cpos;
  121. // 押し出しベクトル
  122. var ev = fpos - nextpos;
  123. var elen = math.length(ev);
  124. if (elen < 1e-06f)
  125. {
  126. // コライダーが動いていない
  127. return;
  128. }
  129. // アルゴリズム変更(v1.9.2)
  130. // 衝突面法線と押し出しベクトルの角度に応じて強さを変更
  131. var cn = collisionNormalList[index];
  132. var dot = math.dot(cn, ev / elen);
  133. dot = math.pow(dot, 0.5f); // 角度(内積)に対して押し出し力を強めにする
  134. float d = math.max(dot, 0.0f);
  135. // 摩擦係数に応じて強さを変更
  136. d *= math.saturate(friction);
  137. // 押し出し
  138. var opos = nextpos;
  139. nextpos = math.lerp(nextpos, fpos, d);
  140. nextPosList[index] = nextpos;
  141. // 速度影響
  142. var av = (nextpos - opos) * (1.0f - Define.Compute.ColliderExtrusionVelocityInfluence); // 跳ねを抑えるため少し抑える(※抑えすぎると突き抜けやすくなるので注意)
  143. posList[index] = posList[index] + av;
  144. }
  145. }
  146. }
  147. }