TwistConstraint.cs 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492
  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 TwistConstraint : PhysicsManagerConstraint
  14. {
  15. /// <summary>
  16. /// 拘束データ
  17. /// </summary>
  18. [System.Serializable]
  19. public struct TwistData
  20. {
  21. /// <summary>
  22. /// 計算頂点インデックス
  23. /// </summary>
  24. public ushort vertexIndex0;
  25. public ushort vertexIndex1;
  26. /// <summary>
  27. /// データが有効か判定する
  28. /// </summary>
  29. /// <returns></returns>
  30. public bool IsValid()
  31. {
  32. return vertexIndex0 > 0 || vertexIndex1 > 0;
  33. }
  34. }
  35. FixedChunkNativeArray<TwistData> dataList;
  36. /// <summary>
  37. /// 頂点インデックスごとのデータ参照
  38. /// </summary>
  39. FixedChunkNativeArray<ReferenceDataIndex> refDataList;
  40. /// <summary>
  41. /// データ参照ごとのグループインデックス
  42. /// </summary>
  43. //FixedChunkNativeArray<short> groupIndexList;
  44. /// <summary>
  45. /// グループごとの拘束データ
  46. /// </summary>
  47. public struct GroupData
  48. {
  49. public int teamId;
  50. public int active;
  51. public float recoveryPower;
  52. public ChunkData dataChunk;
  53. public ChunkData refChunk;
  54. }
  55. public FixedNativeList<GroupData> groupList;
  56. //=========================================================================================
  57. public override void Create()
  58. {
  59. dataList = new FixedChunkNativeArray<TwistData>();
  60. //groupIndexList = new FixedChunkNativeArray<short>();
  61. refDataList = new FixedChunkNativeArray<ReferenceDataIndex>();
  62. groupList = new FixedNativeList<GroupData>();
  63. }
  64. public override void Release()
  65. {
  66. dataList.Dispose();
  67. //groupIndexList.Dispose();
  68. refDataList.Dispose();
  69. groupList.Dispose();
  70. }
  71. //=========================================================================================
  72. public int AddGroup(int teamId, bool active, float recoveryPower, TwistData[] dataArray, ReferenceDataIndex[] refArray)
  73. {
  74. if (dataArray == null || dataArray.Length == 0)
  75. return -1;
  76. var gdata = new GroupData();
  77. gdata.teamId = teamId;
  78. gdata.active = active ? 1 : 0;
  79. gdata.recoveryPower = recoveryPower;
  80. gdata.dataChunk = dataList.AddChunk(dataArray.Length);
  81. gdata.refChunk = refDataList.AddChunk(refArray.Length);
  82. //groupIndexList.AddChunk(refArray.Length);
  83. // チャンクデータコピー
  84. dataList.ToJobArray().CopyFromFast(gdata.dataChunk.startIndex, dataArray);
  85. refDataList.ToJobArray().CopyFromFast(gdata.refChunk.startIndex, refArray);
  86. int group = groupList.Add(gdata);
  87. // データ参照ごとのグループインデックス
  88. //groupIndexList.Fill(gdata.refChunk, (short)group);
  89. return group;
  90. }
  91. public override void RemoveTeam(int teamId)
  92. {
  93. var teamData = MagicaPhysicsManager.Instance.Team.teamDataList[teamId];
  94. int group = teamData.twistGroupIndex;
  95. if (group < 0)
  96. return;
  97. var cdata = groupList[group];
  98. // チャンクデータ削除
  99. dataList.RemoveChunk(cdata.dataChunk);
  100. //groupIndexList.RemoveChunk(cdata.refChunk);
  101. refDataList.RemoveChunk(cdata.refChunk);
  102. // データ削除
  103. groupList.Remove(group);
  104. }
  105. public void ChangeParam(int teamId, bool active, float recoveryPower)
  106. {
  107. var teamData = MagicaPhysicsManager.Instance.Team.teamDataList[teamId];
  108. int group = teamData.twistGroupIndex;
  109. if (group < 0)
  110. return;
  111. var gdata = groupList[group];
  112. gdata.active = active ? 1 : 0;
  113. gdata.recoveryPower = recoveryPower;
  114. groupList[group] = gdata;
  115. }
  116. //=========================================================================================
  117. /// <summary>
  118. /// 拘束の解決
  119. /// </summary>
  120. /// <param name="dtime"></param>
  121. /// <param name="jobHandle"></param>
  122. /// <returns></returns>
  123. public override JobHandle SolverConstraint(int runCount, float dtime, float updatePower, int iteration, JobHandle jobHandle)
  124. {
  125. if (groupList.Count == 0)
  126. return jobHandle;
  127. #if false
  128. // ねじれ拘束
  129. var job1 = new TwistJob()
  130. {
  131. runCount = runCount,
  132. dataList = dataList.ToJobArray(),
  133. groupIndexList = groupIndexList.ToJobArray(),
  134. groupList = groupList.ToJobArray(),
  135. teamDataList = Manager.Team.teamDataList.ToJobArray(),
  136. //depthList = Manager.Particle.depthList.ToJobArray(),
  137. //flagList = Manager.Particle.flagList.ToJobArray(),
  138. basePosList = Manager.Particle.basePosList.ToJobArray(),
  139. frictionList = Manager.Particle.frictionList.ToJobArray(),
  140. nextPosList = Manager.Particle.InNextPosList.ToJobArray(),
  141. posList = Manager.Particle.posList.ToJobArray(),
  142. };
  143. jobHandle = job1.Schedule(dataList.Length, 2, jobHandle); // 数は多くないので2
  144. #endif
  145. // ねじれ拘束
  146. var job = new TwistJob2()
  147. {
  148. runCount = runCount,
  149. updatePower = updatePower,
  150. dataList = dataList.ToJobArray(),
  151. refDataList = refDataList.ToJobArray(),
  152. groupList = groupList.ToJobArray(),
  153. teamDataList = Manager.Team.teamDataList.ToJobArray(),
  154. teamIdList = Manager.Particle.teamIdList.ToJobArray(),
  155. flagList = Manager.Particle.flagList.ToJobArray(),
  156. basePosList = Manager.Particle.basePosList.ToJobArray(),
  157. nextPosList = Manager.Particle.InNextPosList.ToJobArray(),
  158. frictionList = Manager.Particle.frictionList.ToJobArray(),
  159. outNextPosList = Manager.Particle.OutNextPosList.ToJobArray(),
  160. posList = Manager.Particle.posList.ToJobArray(),
  161. };
  162. jobHandle = job.Schedule(Manager.Particle.Length, 64, jobHandle);
  163. Manager.Particle.SwitchingNextPosList();
  164. return jobHandle;
  165. }
  166. [BurstCompile]
  167. struct TwistJob2 : IJobParallelFor
  168. {
  169. public int runCount;
  170. public float updatePower;
  171. [Unity.Collections.ReadOnly]
  172. public NativeArray<TwistData> dataList;
  173. [Unity.Collections.ReadOnly]
  174. public NativeArray<ReferenceDataIndex> refDataList;
  175. [Unity.Collections.ReadOnly]
  176. public NativeArray<GroupData> groupList;
  177. // team
  178. [Unity.Collections.ReadOnly]
  179. public NativeArray<PhysicsManagerTeamData.TeamData> teamDataList;
  180. [Unity.Collections.ReadOnly]
  181. public NativeArray<int> teamIdList;
  182. // particle
  183. [Unity.Collections.ReadOnly]
  184. public NativeArray<PhysicsManagerParticleData.ParticleFlag> flagList;
  185. [Unity.Collections.ReadOnly]
  186. public NativeArray<float3> basePosList;
  187. [Unity.Collections.ReadOnly]
  188. public NativeArray<float3> nextPosList;
  189. [Unity.Collections.ReadOnly]
  190. public NativeArray<float> frictionList;
  191. [Unity.Collections.WriteOnly]
  192. public NativeArray<float3> outNextPosList;
  193. public NativeArray<float3> posList;
  194. // パーティクルごと
  195. public void Execute(int index)
  196. {
  197. // 初期化コピー
  198. var nextpos0 = nextPosList[index];
  199. outNextPosList[index] = nextpos0;
  200. var flag = flagList[index];
  201. if (flag.IsValid() == false || flag.IsFixed())
  202. return;
  203. var team = teamDataList[teamIdList[index]];
  204. if (team.twistGroupIndex < 0)
  205. return;
  206. // 更新確認
  207. if (team.IsUpdate(runCount) == false)
  208. return;
  209. // グループ
  210. var gdata = groupList[team.twistGroupIndex];
  211. if (gdata.active == 0)
  212. return;
  213. int pstart = team.particleChunk.startIndex;
  214. int vindex = index - pstart;
  215. // 参照情報
  216. var refdata = refDataList[gdata.refChunk.startIndex + vindex];
  217. if (refdata.count == 0)
  218. return;
  219. // 自身の情報
  220. var basepos0 = basePosList[index];
  221. var friction0 = frictionList[index];
  222. float moveratio = math.saturate(1.0f - friction0 * Define.Compute.FrictionMoveRatio);
  223. // 剛性
  224. float stiffness = math.saturate(gdata.recoveryPower * updatePower);
  225. // データ処理
  226. float3 addpos = 0;
  227. int addcnt = 0;
  228. int dataIndex = gdata.dataChunk.startIndex + refdata.startIndex;
  229. for (int i = 0; i < refdata.count; i++, dataIndex++)
  230. {
  231. var data = dataList[dataIndex];
  232. if (data.IsValid() == false)
  233. continue;
  234. // ターゲットの情報
  235. int tindex = pstart + data.vertexIndex1;
  236. var nextpos1 = nextPosList[tindex];
  237. var basepos1 = basePosList[tindex];
  238. #if false
  239. // 平面押出方式
  240. var v = basepos1 - basepos0;
  241. float len = math.length(v);
  242. float3 n = math.normalize(v);
  243. // 中央から各頂点への中間点
  244. float3 cen = (nextpos0 + nextpos1) * 0.5f;
  245. float3 cen0 = cen - n * (len * 0.25f);
  246. float3 cen1 = cen + n * (len * 0.25f);
  247. // 面に対してそれぞれの頂点を初期方向に押し出す
  248. float3 outPos0;
  249. MathUtility.IntersectPointPlane(cen0, -n, nextpos0, out outPos0);
  250. //float3 outPos1;
  251. //MathUtility.IntersectPointPlane(cen1, n, nextpos1, out outPos1);
  252. // 剛性
  253. // 基本最大にしておく
  254. float stiffness0 = 1.0f;
  255. //float stiffness1 = 1.0f;
  256. // 最終移動量
  257. float3 addPos0 = (outPos0 - nextpos0) * stiffness0;
  258. //float3 addPos1 = (outPos1 - nextpos1) * stiffness1;
  259. // 摩擦影響
  260. addPos0 *= moveratio;
  261. //addPos1 *= moveratio1;
  262. float3 add = addPos0;
  263. #else
  264. // 方向ベクトル補間方式
  265. // こちらのほうが安定していると思われる
  266. // 本来のベクトル
  267. float3 tv = basepos1 - basepos0;
  268. // 現在のベクトル
  269. float3 v = nextpos1 - nextpos0;
  270. float3 cen = nextpos0 + v * 0.5f;
  271. // 角度復元
  272. var q = MathUtility.FromToRotation(v, tv, stiffness);
  273. v = math.mul(q, v);
  274. float3 fpos = cen - v * 0.5f;
  275. float3 add = fpos - nextpos0;
  276. add *= moveratio; // 摩擦影響
  277. #endif
  278. // 移動加算
  279. addpos += add;
  280. addcnt++;
  281. }
  282. // 書き出し
  283. if (addcnt > 0)
  284. {
  285. addpos /= addcnt;
  286. outNextPosList[index] = nextpos0 + addpos;
  287. // 速度影響
  288. const float influence = 0.1f; // とりあえず固定
  289. posList[index] = posList[index] + (addpos * (1.0f - influence));
  290. }
  291. }
  292. }
  293. #if false
  294. /// <summary>
  295. /// ねじれ拘束ジョブ
  296. /// </summary>
  297. [BurstCompile]
  298. struct TwistJob : IJobParallelFor
  299. {
  300. public int runCount;
  301. [Unity.Collections.ReadOnly]
  302. public NativeArray<TwistData> dataList;
  303. [Unity.Collections.ReadOnly]
  304. public NativeArray<short> groupIndexList;
  305. [Unity.Collections.ReadOnly]
  306. public NativeArray<GroupData> groupList;
  307. // チーム
  308. [Unity.Collections.ReadOnly]
  309. public NativeArray<PhysicsManagerTeamData.TeamData> teamDataList;
  310. //[Unity.Collections.ReadOnly]
  311. //public NativeArray<float> depthList;
  312. //[Unity.Collections.ReadOnly]
  313. //public NativeArray<PhysicsManagerParticleData.ParticleFlag> flagList;
  314. [Unity.Collections.ReadOnly]
  315. public NativeArray<float3> basePosList;
  316. [Unity.Collections.ReadOnly]
  317. public NativeArray<float> frictionList;
  318. [NativeDisableParallelForRestriction]
  319. public NativeArray<float3> nextPosList;
  320. [NativeDisableParallelForRestriction]
  321. public NativeArray<float3> posList;
  322. // 拘束データごと
  323. public void Execute(int dataIndex)
  324. {
  325. var data = dataList[dataIndex];
  326. if (data.IsValid() == false)
  327. return;
  328. // group
  329. int groupIndex = groupIndexList[dataIndex];
  330. var gdata = groupList[groupIndex];
  331. if (gdata.active == 0)
  332. return;
  333. // team
  334. int teamIndex = gdata.teamId;
  335. var team = teamDataList[teamIndex];
  336. if (team.IsActive() == false || team.twistGroupIndex < 0)
  337. return;
  338. // 更新確認
  339. if (team.IsUpdate(runCount) == false)
  340. return;
  341. // particle
  342. int pstart = team.particleChunk.startIndex;
  343. int pindex0 = data.vertexIndex0 + pstart;
  344. int pindex1 = data.vertexIndex1 + pstart;
  345. float3 basePos0 = basePosList[pindex0];
  346. float3 basePos1 = basePosList[pindex1];
  347. float3 nextPos0 = nextPosList[pindex0];
  348. float3 nextPos1 = nextPosList[pindex1];
  349. // 面法線
  350. //var v = basePos1 - basePos0;
  351. //float len = math.length(v);
  352. //float3 n = math.normalize(v);
  353. var bv = basePos1 - basePos0;
  354. bv = math.normalize(bv);
  355. // 押出平面位置
  356. // 中央から各頂点への中間点
  357. float3 cen = (nextPos0 + nextPos1) * 0.5f;
  358. //float3 cen0 = cen - n * (len * 0.25f);
  359. //float3 cen1 = cen + n * (len * 0.25f);
  360. var v = nextPos1 - nextPos0;
  361. //v = math.normalize(v);
  362. // 剛性
  363. // 基本最大にしておく
  364. //float stiffness0 = 1.0f;
  365. //float stiffness1 = 1.0f;
  366. float stiffness = 0.5f;
  367. // 面に対してそれぞれの頂点を初期方向に押し出す
  368. //float3 outPos0;
  369. //MathUtility.IntersectPointPlane(cen0, -n, nextPos0, out outPos0);
  370. //float3 outPos1;
  371. //MathUtility.IntersectPointPlane(cen1, n, nextPos1, out outPos1);
  372. var q = MathUtility.FromToRotation(v, bv, stiffness);
  373. var rv = math.mul(q, v);
  374. // 最終移動量
  375. //float3 addPos0 = (outPos0 - nextPos0) * stiffness0;
  376. //float3 addPos1 = (outPos1 - nextPos1) * stiffness1;
  377. float3 fpos0 = cen - rv * 0.5f;
  378. float3 fpos1 = cen + rv * 0.5f;
  379. float3 addPos0 = fpos0 - nextPos0;
  380. float3 addPos1 = fpos1 - nextPos1;
  381. // 摩擦
  382. float friction0 = frictionList[pindex0];
  383. float friction1 = frictionList[pindex1];
  384. float moveratio0 = math.saturate(1.0f - friction0 * Define.Compute.FrictionMoveRatio);
  385. float moveratio1 = math.saturate(1.0f - friction1 * Define.Compute.FrictionMoveRatio);
  386. //stiffness0 *= moveratio0;
  387. //stiffness1 *= moveratio1;
  388. addPos0 *= moveratio0;
  389. addPos1 *= moveratio1;
  390. // 書き込み
  391. nextPos0 += addPos0;
  392. nextPos1 += addPos1;
  393. nextPosList[pindex0] = nextPos0;
  394. nextPosList[pindex1] = nextPos1;
  395. // 速度影響
  396. const float influence = 0.5f; // 低く抑える(0.1)
  397. posList[pindex0] = posList[pindex0] + addPos0 * (1.0f - influence);
  398. posList[pindex1] = posList[pindex1] + addPos1 * (1.0f - influence);
  399. }
  400. }
  401. #endif
  402. }
  403. }