PhysicsManagerBoneData.cs 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056
  1. // Magica Cloth.
  2. // Copyright (c) MagicaSoft, 2020-2022.
  3. // https://magicasoft.jp
  4. using System.Collections.Generic;
  5. using Unity.Burst;
  6. using Unity.Collections;
  7. using Unity.Jobs;
  8. using Unity.Mathematics;
  9. using UnityEngine;
  10. using UnityEngine.Jobs;
  11. using UnityEngine.Profiling;
  12. namespace MagicaCloth
  13. {
  14. /// <summary>
  15. /// ボーンデータ
  16. /// </summary>
  17. public class PhysicsManagerBoneData : PhysicsManagerAccess
  18. {
  19. //=========================================================================================
  20. /// <summary>
  21. /// ボーン制御フラグ
  22. /// </summary>
  23. public const byte Flag_Reset = 0x01; // リセット
  24. public const byte Flag_Restore = 0x10; // 復元許可フラグ
  25. public const byte Flag_Write = 0x20; // 書き込み許可フラグ
  26. /// <summary>
  27. /// 管理ボーンリスト
  28. /// </summary>
  29. public FixedTransformAccessArray boneList;
  30. /// <summary>
  31. /// ボーンフラグリスト
  32. /// </summary>
  33. public FixedNativeList<byte> boneFlagList;
  34. /// <summary>
  35. /// ボーンワールド位置リスト(※未来予測により補正される場合あり)
  36. /// </summary>
  37. public FixedNativeList<float3> bonePosList;
  38. /// <summary>
  39. /// ボーンワールド回転リスト(※未来予測により補正される場合あり)
  40. /// </summary>
  41. public FixedNativeList<quaternion> boneRotList;
  42. /// <summary>
  43. /// ボーンワールドスケールリスト(現在は初期化時に設定のみ不変)
  44. /// </summary>
  45. public FixedNativeList<float3> boneSclList;
  46. /// <summary>
  47. /// 親ボーンへのインデックス(-1=なし)
  48. /// </summary>
  49. public FixedNativeList<int> boneParentIndexList;
  50. /// <summary>
  51. /// ボーンワールド位置リスト(オリジナル)
  52. /// </summary>
  53. public FixedNativeList<float3> basePosList;
  54. /// <summary>
  55. /// ボーンワールド回転リスト(オリジナル)
  56. /// </summary>
  57. public FixedNativeList<quaternion> baseRotList;
  58. /// <summary>
  59. /// ボーンがUnityPhysicsで動作するかの参照カウンタ(1以上で動作)
  60. /// </summary>
  61. public FixedNativeList<short> boneUnityPhysicsList;
  62. /// <summary>
  63. /// ボーン未来予測位置リスト
  64. /// </summary>
  65. public FixedNativeList<float3> futurePosList;
  66. /// <summary>
  67. /// ボーン未来予測回転リスト
  68. /// </summary>
  69. public FixedNativeList<quaternion> futureRotList;
  70. //=========================================================================================
  71. /// <summary>
  72. /// 復元ボーンリスト
  73. /// </summary>
  74. public FixedTransformAccessArray restoreBoneList;
  75. /// <summary>
  76. /// 復元ボーンの復元ローカル座標リスト
  77. /// </summary>
  78. public FixedNativeList<float3> restoreBoneLocalPosList;
  79. /// <summary>
  80. /// 復元ボーンの復元ローカル回転リスト
  81. /// </summary>
  82. public FixedNativeList<quaternion> restoreBoneLocalRotList;
  83. /// <summary>
  84. /// 復元ボーンの参照ボーンインデックス
  85. /// </summary>
  86. public FixedNativeList<int> restoreBoneIndexList;
  87. //=========================================================================================
  88. // ここはライトボーンごと
  89. /// <summary>
  90. /// 書き込みボーンリスト
  91. /// </summary>
  92. public FixedTransformAccessArray writeBoneList;
  93. /// <summary>
  94. /// 書き込みボーンの参照ボーン姿勢インデックス(+1が入るので注意!)
  95. /// </summary>
  96. public FixedNativeList<int> writeBoneIndexList;
  97. /// <summary>
  98. /// 書き込みボーンの対応するパーティクルインデックス
  99. /// </summary>
  100. public ExNativeMultiHashMap<int, int> writeBoneParticleIndexMap;
  101. /// <summary>
  102. /// 読み込みボーンに対応する書き込みボーンのインデックス辞書
  103. /// </summary>
  104. Dictionary<int, int> boneToWriteIndexDict = new Dictionary<int, int>();
  105. /// <summary>
  106. /// 書き込みボーンの確定位置
  107. /// 親がいる場合はローカル、いない場合はワールド格納
  108. /// </summary>
  109. public FixedNativeList<float3> writeBonePosList;
  110. /// <summary>
  111. /// 書き込みボーンの確定回転
  112. /// 親がいる場合はローカル、いない場合はワールド格納
  113. /// </summary>
  114. public FixedNativeList<quaternion> writeBoneRotList;
  115. //=========================================================================================
  116. /// <summary>
  117. /// ボーンリストに変化が合った場合にtrue
  118. /// </summary>
  119. public bool hasBoneChanged { get; private set; }
  120. /// <summary>
  121. /// プロファイラ用
  122. /// </summary>
  123. private CustomSampler SamplerReadBoneScale { get; set; }
  124. //=========================================================================================
  125. /// <summary>
  126. /// 初期設定
  127. /// </summary>
  128. public override void Create()
  129. {
  130. boneList = new FixedTransformAccessArray();
  131. boneFlagList = new FixedNativeList<byte>();
  132. bonePosList = new FixedNativeList<float3>();
  133. boneRotList = new FixedNativeList<quaternion>();
  134. boneSclList = new FixedNativeList<float3>();
  135. boneParentIndexList = new FixedNativeList<int>();
  136. basePosList = new FixedNativeList<float3>();
  137. baseRotList = new FixedNativeList<quaternion>();
  138. boneUnityPhysicsList = new FixedNativeList<short>();
  139. futurePosList = new FixedNativeList<float3>();
  140. futureRotList = new FixedNativeList<quaternion>();
  141. restoreBoneList = new FixedTransformAccessArray();
  142. restoreBoneLocalPosList = new FixedNativeList<float3>();
  143. restoreBoneLocalRotList = new FixedNativeList<quaternion>();
  144. restoreBoneIndexList = new FixedNativeList<int>();
  145. writeBoneList = new FixedTransformAccessArray();
  146. writeBoneIndexList = new FixedNativeList<int>();
  147. writeBoneParticleIndexMap = new ExNativeMultiHashMap<int, int>();
  148. writeBonePosList = new FixedNativeList<float3>();
  149. writeBoneRotList = new FixedNativeList<quaternion>();
  150. // プロファイラ用
  151. SamplerReadBoneScale = CustomSampler.Create("ReadBoneScale");
  152. }
  153. /// <summary>
  154. /// 破棄
  155. /// </summary>
  156. public override void Dispose()
  157. {
  158. if (boneList == null)
  159. return;
  160. boneList.Dispose();
  161. boneFlagList.Dispose();
  162. bonePosList.Dispose();
  163. boneRotList.Dispose();
  164. boneSclList.Dispose();
  165. boneParentIndexList.Dispose();
  166. basePosList.Dispose();
  167. baseRotList.Dispose();
  168. boneUnityPhysicsList.Dispose();
  169. futurePosList.Dispose();
  170. futureRotList.Dispose();
  171. restoreBoneList.Dispose();
  172. restoreBoneLocalPosList.Dispose();
  173. restoreBoneLocalRotList.Dispose();
  174. restoreBoneIndexList.Dispose();
  175. writeBoneList.Dispose();
  176. writeBoneIndexList.Dispose();
  177. writeBoneParticleIndexMap.Dispose();
  178. writeBonePosList.Dispose();
  179. writeBoneRotList.Dispose();
  180. }
  181. //=========================================================================================
  182. /// <summary>
  183. /// 復元ボーン登録
  184. /// </summary>
  185. /// <param name="target"></param>
  186. /// <param name="lpos"></param>
  187. /// <param name="lrot"></param>
  188. /// <returns></returns>
  189. public int AddRestoreBone(Transform target, float3 lpos, quaternion lrot, int boneIndex)
  190. {
  191. int restoreBoneIndex;
  192. if (restoreBoneList.Exist(target))
  193. {
  194. // 参照カウンタ+
  195. restoreBoneIndex = restoreBoneList.Add(target);
  196. }
  197. else
  198. {
  199. // 復元ローカル姿勢も登録
  200. restoreBoneIndex = restoreBoneList.Add(target);
  201. restoreBoneLocalPosList.Add(lpos);
  202. restoreBoneLocalRotList.Add(lrot);
  203. restoreBoneIndexList.Add(boneIndex);
  204. hasBoneChanged = true;
  205. }
  206. return restoreBoneIndex;
  207. }
  208. /// <summary>
  209. /// 復元ボーン削除
  210. /// </summary>
  211. /// <param name="restoreBoneIndex"></param>
  212. public void RemoveRestoreBone(int restoreBoneIndex)
  213. {
  214. restoreBoneList.Remove(restoreBoneIndex);
  215. if (restoreBoneList.Exist(restoreBoneIndex) == false)
  216. {
  217. // データも削除
  218. restoreBoneLocalPosList.Remove(restoreBoneIndex);
  219. restoreBoneLocalRotList.Remove(restoreBoneIndex);
  220. restoreBoneIndexList.Remove(restoreBoneIndex);
  221. hasBoneChanged = true;
  222. }
  223. }
  224. /// <summary>
  225. /// ボーンの復元カウントを返す
  226. /// </summary>
  227. public int RestoreBoneCount
  228. {
  229. get
  230. {
  231. return restoreBoneList.Count;
  232. }
  233. }
  234. //=========================================================================================
  235. /// <summary>
  236. /// 利用ボーン登録
  237. /// </summary>
  238. /// <param name="target"></param>
  239. /// <param name="pindex"></param>
  240. /// <param name="addParent">親ボーンのインデックス保持の有無</param>
  241. /// <returns></returns>
  242. public int AddBone(Transform target, int pindex = -1, bool addParent = false)
  243. {
  244. int boneIndex;
  245. if (boneList.Exist(target))
  246. {
  247. // 参照カウンタ+
  248. boneIndex = boneList.Add(target);
  249. // 親ボーンは後登録優先の上書き方式にする(v1.10.2)
  250. if (addParent)
  251. {
  252. boneParentIndexList[boneIndex] = boneList.GetIndex(target.parent);
  253. }
  254. boneFlagList.Add(Flag_Reset); // 姿勢リセット
  255. }
  256. else
  257. {
  258. // 新規
  259. var pos = float3.zero;
  260. var rot = quaternion.identity;
  261. boneIndex = boneList.Add(target);
  262. boneFlagList.Add(Flag_Reset); // 姿勢リセット
  263. bonePosList.Add(pos);
  264. boneRotList.Add(rot);
  265. boneSclList.Add(float3.zero);
  266. if (addParent)
  267. boneParentIndexList.Add(boneList.GetIndex(target.parent));
  268. else
  269. boneParentIndexList.Add(-1);
  270. basePosList.Add(pos);
  271. baseRotList.Add(rot);
  272. boneUnityPhysicsList.Add(0);
  273. futurePosList.Add(pos);
  274. futureRotList.Add(rot);
  275. hasBoneChanged = true;
  276. }
  277. //Debug.Log("AddBone:" + target.name + " index:" + boneIndex + " parent?:" + boneParentIndexList[boneIndex]);
  278. // 書き込み設定
  279. if (pindex >= 0)
  280. {
  281. if (boneToWriteIndexDict.ContainsKey(boneIndex))
  282. {
  283. Debug.LogWarning($"[{target.name}] is already registered as a write bone.");
  284. }
  285. else
  286. {
  287. //Debug.Log("AddWriteBone:" + target.name + " index:" + boneIndex + " parent?:" + boneParentIndexList[boneIndex]);
  288. if (writeBoneList.Exist(target))
  289. {
  290. // 参照カウンタ+
  291. writeBoneList.Add(target);
  292. }
  293. else
  294. {
  295. // 新規
  296. writeBoneList.Add(target);
  297. //Debug.Log("write bone index:" + boneIndex);
  298. writeBoneIndexList.Add(boneIndex + 1); // +1を入れるので注意!
  299. writeBonePosList.Add(float3.zero);
  300. writeBoneRotList.Add(quaternion.identity);
  301. hasBoneChanged = true;
  302. }
  303. int writeIndex = writeBoneList.GetIndex(target);
  304. boneToWriteIndexDict.Add(boneIndex, writeIndex);
  305. // 書き込み姿勢参照パーティクルインデックス登録
  306. writeBoneParticleIndexMap.Add(writeIndex, pindex);
  307. }
  308. }
  309. return boneIndex;
  310. }
  311. /// <summary>
  312. /// 利用ボーン解除
  313. /// </summary>
  314. /// <param name="boneIndex"></param>
  315. /// <param name="pindex"></param>
  316. /// <returns></returns>
  317. public bool RemoveBone(int boneIndex, int pindex = -1)
  318. {
  319. //Debug.Log("RemoveBone: index:" + boneIndex + " parent?:" + boneParentIndexList[boneIndex]);
  320. bool del = false;
  321. boneList.Remove(boneIndex);
  322. if (boneList.Exist(boneIndex) == false)
  323. {
  324. // データも削除
  325. boneFlagList.Remove(boneIndex);
  326. bonePosList.Remove(boneIndex);
  327. boneRotList.Remove(boneIndex);
  328. boneSclList.Remove(boneIndex);
  329. boneParentIndexList.Remove(boneIndex);
  330. basePosList.Remove(boneIndex);
  331. baseRotList.Remove(boneIndex);
  332. boneUnityPhysicsList.Remove(boneIndex);
  333. futurePosList.Remove(boneIndex);
  334. futureRotList.Remove(boneIndex);
  335. hasBoneChanged = true;
  336. del = true;
  337. }
  338. // 書き込み設定から削除
  339. if (pindex >= 0 && boneToWriteIndexDict.ContainsKey(boneIndex))
  340. {
  341. int writeIndex = boneToWriteIndexDict[boneIndex];
  342. writeBoneList.Remove(writeIndex);
  343. writeBoneIndexList.Remove(writeIndex);
  344. writeBoneParticleIndexMap.Remove(writeIndex, pindex);
  345. writeBonePosList.Remove(writeIndex);
  346. writeBoneRotList.Remove(writeIndex);
  347. hasBoneChanged = true;
  348. if (writeBoneList.Exist(writeIndex) == false)
  349. {
  350. boneToWriteIndexDict.Remove(boneIndex);
  351. //Debug.Log("RemoveWriteBone: index:" + boneIndex);
  352. }
  353. }
  354. return del;
  355. }
  356. /// <summary>
  357. /// ボーンのUnityPhysics利用カウンタを増減させる
  358. /// </summary>
  359. /// <param name="boneIndex"></param>
  360. /// <param name="sw"></param>
  361. public void ChangeUnityPhysicsCount(int boneIndex, bool sw)
  362. {
  363. //Debug.Log($"Change Bone Physics Count [{boneIndex}]->{sw}");
  364. boneUnityPhysicsList[boneIndex] += (short)(sw ? 1 : -1);
  365. Debug.Assert(boneUnityPhysicsList[boneIndex] >= 0);
  366. }
  367. /// <summary>
  368. /// 未来予測をリセットする
  369. /// </summary>
  370. /// <param name="boneIndex"></param>
  371. public void ResetFuturePrediction(int boneIndex)
  372. {
  373. //Debug.Log($"ResetFuturePrediction:{boneIndex} F:{Time.frameCount}");
  374. var flag = boneFlagList[boneIndex];
  375. flag |= Flag_Reset;
  376. boneFlagList[boneIndex] = flag;
  377. }
  378. /// <summary>
  379. /// 読み込みボーン数を返す
  380. /// </summary>
  381. public int ReadBoneCount
  382. {
  383. get
  384. {
  385. return boneList.Count;
  386. }
  387. }
  388. /// <summary>
  389. /// 書き込みボーン数を返す
  390. /// </summary>
  391. public int WriteBoneCount
  392. {
  393. get
  394. {
  395. return writeBoneList.Count;
  396. }
  397. }
  398. //=========================================================================================
  399. /// <summary>
  400. /// ボーン情報のリセット
  401. /// </summary>
  402. public void ResetBoneFromTransform(bool fixedUpdate)
  403. {
  404. // ボーン姿勢リセット
  405. if (RestoreBoneCount > 0)
  406. {
  407. var job = new RestoreBoneJob()
  408. {
  409. fixedUpdate = fixedUpdate,
  410. boneUnityPhysicsList = boneUnityPhysicsList.ToJobArray(),
  411. boneFlagList = boneFlagList.ToJobArray(),
  412. restoreBoneLocalPosList = restoreBoneLocalPosList.ToJobArray(),
  413. restoreBoneLocalRotList = restoreBoneLocalRotList.ToJobArray(),
  414. restoreBoneIndexList = restoreBoneIndexList.ToJobArray(),
  415. };
  416. Compute.MasterJob = job.Schedule(restoreBoneList.GetTransformAccessArray(), Compute.MasterJob);
  417. }
  418. }
  419. /// <summary>
  420. /// ボーン姿勢の復元
  421. /// </summary>
  422. [BurstCompile]
  423. struct RestoreBoneJob : IJobParallelForTransform
  424. {
  425. public bool fixedUpdate;
  426. [Unity.Collections.ReadOnly]
  427. public NativeArray<short> boneUnityPhysicsList;
  428. [Unity.Collections.ReadOnly]
  429. public NativeArray<byte> boneFlagList;
  430. [Unity.Collections.ReadOnly]
  431. public NativeArray<float3> restoreBoneLocalPosList;
  432. [Unity.Collections.ReadOnly]
  433. public NativeArray<quaternion> restoreBoneLocalRotList;
  434. [Unity.Collections.ReadOnly]
  435. public NativeArray<int> restoreBoneIndexList;
  436. // 復元ボーンごと
  437. public void Execute(int index, TransformAccess transform)
  438. {
  439. var bindex = restoreBoneIndexList[index];
  440. bool isUnityPhysics = boneUnityPhysicsList[bindex] > 0;
  441. if (isUnityPhysics == fixedUpdate)
  442. {
  443. var flag = boneFlagList[bindex];
  444. if ((flag & Flag_Restore) == 0)
  445. return;
  446. transform.localPosition = restoreBoneLocalPosList[index];
  447. transform.localRotation = restoreBoneLocalRotList[index];
  448. }
  449. }
  450. }
  451. //=========================================================================================
  452. /// <summary>
  453. /// ボーン情報の読み込み
  454. /// </summary>
  455. public void ReadBoneFromTransform()
  456. {
  457. // ボーン姿勢読み込み
  458. if (ReadBoneCount > 0)
  459. {
  460. var updateTime = manager.UpdateTime;
  461. // 未来予測補間率
  462. float futureRate = updateTime.IsDelay ? updateTime.FuturePredictionRate : 0.0f;
  463. // 未来予測が不要ならば従来どおり
  464. if (futureRate < 0.01f)
  465. {
  466. // ボーンから姿勢読み込み(ルートが別れていないとジョブが並列化できないので注意!)
  467. var job = new ReadBoneJob0()
  468. {
  469. fixedUpdateCount = updateTime.FixedUpdateCount,
  470. bonePosList = bonePosList.ToJobArray(),
  471. boneRotList = boneRotList.ToJobArray(),
  472. boneSclList = boneSclList.ToJobArray(),
  473. basePosList = basePosList.ToJobArray(),
  474. baseRotList = baseRotList.ToJobArray(),
  475. futurePosList = futurePosList.ToJobArray(),
  476. futureRotList = futureRotList.ToJobArray(),
  477. boneUnityPhysicsList = boneUnityPhysicsList.ToJobArray(),
  478. boneFlagList = boneFlagList.ToJobArray(),
  479. };
  480. Compute.MasterJob = job.Schedule(boneList.GetTransformAccessArray(), Compute.MasterJob);
  481. }
  482. else
  483. {
  484. // 未来予測あり
  485. // Update更新での未来予測補間率を求める
  486. float normalFutureRatio = updateTime.DeltaTime > Define.Compute.Epsilon ?
  487. math.clamp((updateTime.AverageDeltaTime / updateTime.DeltaTime) * futureRate, 0.0f, 2.0f) : 0.0f;
  488. // FixedUpdate更新での未来予測補間率を求める
  489. float fixedFutureRatio = updateTime.FixedUpdateCount > 0 ? (1.0f / updateTime.FixedUpdateCount) * futureRate : 0.0f;
  490. #if true
  491. // 次に予想されるフレーム時間を加算することにより実行されるFixedUpdateの回数を予測する
  492. float fixedNextTime = Time.time + Time.smoothDeltaTime;
  493. float fixedInterval = fixedNextTime - Time.fixedTime;
  494. int nextFixedCount = math.max((int)(fixedInterval / Time.fixedDeltaTime), 1);
  495. fixedFutureRatio *= nextFixedCount;
  496. #endif
  497. //Debug.Log($"normalFutureRatio = {normalFutureRatio}");
  498. // ボーンから姿勢読み込み(ルートが別れていないとジョブが並列化できないので注意!)
  499. var job = new ReadBoneJob1()
  500. {
  501. fixedUpdateCount = updateTime.FixedUpdateCount,
  502. normalFutureRatio = normalFutureRatio,
  503. fixedFutureRatio = fixedFutureRatio,
  504. normalDeltaTime = Time.smoothDeltaTime,
  505. fixedDeltaTime = Time.fixedDeltaTime,
  506. bonePosList = bonePosList.ToJobArray(),
  507. boneRotList = boneRotList.ToJobArray(),
  508. boneSclList = boneSclList.ToJobArray(),
  509. basePosList = basePosList.ToJobArray(),
  510. baseRotList = baseRotList.ToJobArray(),
  511. boneUnityPhysicsList = boneUnityPhysicsList.ToJobArray(),
  512. futurePosList = futurePosList.ToJobArray(),
  513. futureRotList = futureRotList.ToJobArray(),
  514. boneFlagList = boneFlagList.ToJobArray(),
  515. };
  516. Compute.MasterJob = job.Schedule(boneList.GetTransformAccessArray(), Compute.MasterJob);
  517. }
  518. }
  519. }
  520. /// <summary>
  521. /// ボーン姿勢の読込み(未来予測なし)
  522. /// </summary>
  523. [BurstCompile]
  524. struct ReadBoneJob0 : IJobParallelForTransform
  525. {
  526. public int fixedUpdateCount;
  527. [Unity.Collections.WriteOnly]
  528. public NativeArray<float3> bonePosList;
  529. [Unity.Collections.WriteOnly]
  530. public NativeArray<quaternion> boneRotList;
  531. [Unity.Collections.WriteOnly]
  532. public NativeArray<float3> boneSclList;
  533. //[Unity.Collections.WriteOnly]
  534. public NativeArray<float3> basePosList;
  535. //[Unity.Collections.WriteOnly]
  536. public NativeArray<quaternion> baseRotList;
  537. [Unity.Collections.WriteOnly]
  538. public NativeArray<float3> futurePosList;
  539. [Unity.Collections.WriteOnly]
  540. public NativeArray<quaternion> futureRotList;
  541. [Unity.Collections.ReadOnly]
  542. public NativeArray<short> boneUnityPhysicsList;
  543. public NativeArray<byte> boneFlagList;
  544. // 読み込みボーンごと
  545. public void Execute(int index, TransformAccess transform)
  546. {
  547. // UnityPhysicsモードで今回更新が無い場合は前回のTransfrom姿勢をボーン姿勢に設定して終了する
  548. bool unityPhysics = boneUnityPhysicsList[index] > 0;
  549. var flag = boneFlagList[index];
  550. bool reset = (flag & Flag_Reset) != 0;
  551. if (unityPhysics == false || fixedUpdateCount > 0 || reset)
  552. {
  553. // 通常更新
  554. // UnityPhysics更新かつフレーム更新ありの場合
  555. // ボーンリセット時
  556. float3 pos = transform.position;
  557. quaternion rot = transform.rotation;
  558. bonePosList[index] = pos;
  559. boneRotList[index] = rot;
  560. basePosList[index] = pos;
  561. baseRotList[index] = rot;
  562. futurePosList[index] = pos;
  563. futureRotList[index] = rot;
  564. // lossyScale取得(現在はUnity2019.2.14以上のみ)
  565. // マトリックスから正確なスケール値を算出する(これはTransform.lossyScaleと等価)
  566. float4x4 m = transform.localToWorldMatrix;
  567. var irot = math.inverse(rot);
  568. var m2 = math.mul(new float4x4(irot, float3.zero), m);
  569. var scl = new float3(m2.c0.x, m2.c1.y, m2.c2.z);
  570. boneSclList[index] = scl;
  571. }
  572. else
  573. {
  574. // UnityPhysics更新かつフレーム更新なしの場合
  575. bonePosList[index] = basePosList[index];
  576. boneRotList[index] = baseRotList[index];
  577. }
  578. // リセットフラグクリア
  579. if (reset && (unityPhysics == false || fixedUpdateCount > 0))
  580. {
  581. flag = (byte)(flag & ~Flag_Reset);
  582. boneFlagList[index] = flag;
  583. }
  584. }
  585. }
  586. /// <summary>
  587. /// ボーン姿勢の読込み(未来予測あり)
  588. /// </summary>
  589. [BurstCompile]
  590. struct ReadBoneJob1 : IJobParallelForTransform
  591. {
  592. public int fixedUpdateCount;
  593. public float normalFutureRatio;
  594. public float fixedFutureRatio;
  595. public float normalDeltaTime;
  596. public float fixedDeltaTime;
  597. [Unity.Collections.WriteOnly]
  598. public NativeArray<float3> bonePosList;
  599. [Unity.Collections.WriteOnly]
  600. public NativeArray<quaternion> boneRotList;
  601. [Unity.Collections.WriteOnly]
  602. public NativeArray<float3> boneSclList;
  603. public NativeArray<float3> basePosList;
  604. public NativeArray<quaternion> baseRotList;
  605. [Unity.Collections.ReadOnly]
  606. public NativeArray<short> boneUnityPhysicsList;
  607. public NativeArray<float3> futurePosList;
  608. public NativeArray<quaternion> futureRotList;
  609. public NativeArray<byte> boneFlagList;
  610. // 読み込みボーンごと
  611. public void Execute(int index, TransformAccess transform)
  612. {
  613. bool unityPhysics = boneUnityPhysicsList[index] > 0;
  614. var flag = boneFlagList[index];
  615. bool reset = (flag & Flag_Reset) != 0;
  616. if (unityPhysics == false || fixedUpdateCount > 0 || reset)
  617. {
  618. // 通常更新
  619. // UnityPhysics更新かつフレーム更新ありの場合
  620. // ボーンリセット時
  621. float3 pos = transform.position;
  622. quaternion rot = transform.rotation;
  623. if (reset)
  624. {
  625. // リセット
  626. //Debug.Log($"reset bone :{index}");
  627. basePosList[index] = pos;
  628. baseRotList[index] = rot;
  629. bonePosList[index] = pos;
  630. boneRotList[index] = rot;
  631. futurePosList[index] = pos;
  632. futureRotList[index] = rot;
  633. }
  634. else
  635. {
  636. // 更新:未来予測
  637. //Debug.Log($"read bone :{index}");
  638. var oldPos = basePosList[index];
  639. var oldRot = baseRotList[index];
  640. basePosList[index] = pos;
  641. baseRotList[index] = rot;
  642. // 速度制限(v1.11.1)
  643. float moveRatio = 0;
  644. float angRatio = 0;
  645. float deltaLength = math.distance(oldPos, pos);
  646. float deltaAngle = math.degrees(math.abs(MathUtility.Angle(oldRot, rot)));
  647. float dtime = unityPhysics ? fixedDeltaTime : normalDeltaTime;
  648. if (dtime > Define.Compute.Epsilon)
  649. {
  650. float moveSpeed = deltaLength / dtime;
  651. float angSpeed = deltaAngle / dtime;
  652. //if (deltaLength > 1e-06f)
  653. // Debug.Log($"read bone :{index}, movesp:{moveSpeed}, angsp:{angSpeed}");
  654. const float maxMoveSpeed = 1.0f;
  655. moveRatio = moveSpeed > maxMoveSpeed ? maxMoveSpeed / moveSpeed : 1.0f;
  656. const float maxAngleSpeed = 360.0f; // deg
  657. angRatio = angSpeed > maxAngleSpeed ? maxAngleSpeed / angSpeed : 1.0f;
  658. }
  659. // 未来予測
  660. float ratio = unityPhysics ? fixedFutureRatio : normalFutureRatio; // ボーンの更新モードにより変化
  661. pos = math.lerp(oldPos, pos, 1.0f + ratio * moveRatio);
  662. rot = math.slerp(oldRot, rot, 1.0f + ratio * angRatio);
  663. rot = math.normalize(rot);
  664. bonePosList[index] = pos;
  665. boneRotList[index] = rot;
  666. // 未来予測姿勢を記録しておく
  667. futurePosList[index] = pos;
  668. futureRotList[index] = rot;
  669. }
  670. // lossyScale取得(現在はUnity2019.2.14以上のみ)
  671. // マトリックスから正確なスケール値を算出する(これはTransform.lossyScaleと等価)
  672. float4x4 m = transform.localToWorldMatrix;
  673. var irot = math.inverse(rot);
  674. var m2 = math.mul(new float4x4(irot, float3.zero), m);
  675. var scl = new float3(m2.c0.x, m2.c1.y, m2.c2.z);
  676. boneSclList[index] = scl;
  677. }
  678. else
  679. {
  680. // UnityPhysics更新かつフレーム更新なしの場合
  681. // 前回計算した未来予測姿勢を返す
  682. bonePosList[index] = futurePosList[index];
  683. boneRotList[index] = futureRotList[index];
  684. }
  685. // リセットフラグクリア
  686. if (reset && (unityPhysics == false || fixedUpdateCount > 0))
  687. {
  688. flag = (byte)(flag & ~Flag_Reset);
  689. boneFlagList[index] = flag;
  690. }
  691. }
  692. }
  693. //=========================================================================================
  694. /// <summary>
  695. /// 書き込みボーン姿勢をローカル姿勢に変換する
  696. /// </summary>
  697. public void ConvertWorldToLocal()
  698. {
  699. if (WriteBoneCount > 0)
  700. {
  701. var job = new ConvertWorldToLocalJob()
  702. {
  703. writeBoneIndexList = writeBoneIndexList.ToJobArray(),
  704. boneFlagList = boneFlagList.ToJobArray(),
  705. bonePosList = bonePosList.ToJobArray(),
  706. boneRotList = boneRotList.ToJobArray(),
  707. boneSclList = boneSclList.ToJobArray(),
  708. boneParentIndexList = boneParentIndexList.ToJobArray(),
  709. writeBonePosList = writeBonePosList.ToJobArray(),
  710. writeBoneRotList = writeBoneRotList.ToJobArray(),
  711. };
  712. Compute.MasterJob = job.Schedule(writeBoneIndexList.Length, 16, Compute.MasterJob);
  713. }
  714. }
  715. /// <summary>
  716. /// ボーン姿勢をローカル姿勢に変換する
  717. /// </summary>
  718. [BurstCompile]
  719. struct ConvertWorldToLocalJob : IJobParallelFor
  720. {
  721. [Unity.Collections.ReadOnly]
  722. public NativeArray<int> writeBoneIndexList;
  723. [Unity.Collections.ReadOnly]
  724. public NativeArray<byte> boneFlagList;
  725. [Unity.Collections.ReadOnly]
  726. public NativeArray<float3> bonePosList;
  727. [Unity.Collections.ReadOnly]
  728. public NativeArray<quaternion> boneRotList;
  729. [Unity.Collections.ReadOnly]
  730. public NativeArray<float3> boneSclList;
  731. [Unity.Collections.ReadOnly]
  732. public NativeArray<int> boneParentIndexList;
  733. [Unity.Collections.WriteOnly]
  734. public NativeArray<float3> writeBonePosList;
  735. [Unity.Collections.WriteOnly]
  736. public NativeArray<quaternion> writeBoneRotList;
  737. // 書き込みボーンごと
  738. public void Execute(int index)
  739. {
  740. int bindex = writeBoneIndexList[index];
  741. if (bindex == 0)
  742. return;
  743. bindex--; // +1が入っているので-1する
  744. // 書き込みフラグチェック
  745. var flag = boneFlagList[bindex];
  746. if ((flag & Flag_Write) == 0)
  747. return;
  748. var pos = bonePosList[bindex];
  749. var rot = boneRotList[bindex];
  750. int parentIndex = boneParentIndexList[bindex];
  751. if (parentIndex >= 0)
  752. {
  753. // 親がいる場合はローカル座標で書き込む
  754. var ppos = bonePosList[parentIndex];
  755. var prot = boneRotList[parentIndex];
  756. var pscl = boneSclList[parentIndex];
  757. var iprot = math.inverse(prot);
  758. var v = pos - ppos;
  759. var lpos = math.mul(iprot, v);
  760. lpos /= pscl;
  761. var lrot = math.mul(iprot, rot);
  762. // マイナススケール対応
  763. if (pscl.x < 0 || pscl.y < 0 || pscl.z < 0)
  764. lrot = new quaternion(lrot.value * new float4(-math.sign(pscl), 1));
  765. writeBonePosList[index] = lpos;
  766. writeBoneRotList[index] = lrot;
  767. }
  768. else
  769. {
  770. // 親がいない場合はワールド座標で書き込む
  771. writeBonePosList[index] = pos;
  772. writeBoneRotList[index] = rot;
  773. }
  774. }
  775. }
  776. //=========================================================================================
  777. /// <summary>
  778. /// ボーン姿勢をトランスフォームに書き込む
  779. /// </summary>
  780. public void WriteBoneToTransform(int bufferIndex)
  781. {
  782. if (WriteBoneCount > 0)
  783. {
  784. var job = new WriteBontToTransformJob2()
  785. {
  786. fixedUpdateCount = manager.UpdateTime.FixedUpdateCount,
  787. boneFlagList = boneFlagList.ToJobArray(bufferIndex),
  788. writeBoneIndexList = writeBoneIndexList.ToJobArray(bufferIndex),
  789. boneParentIndexList = boneParentIndexList.ToJobArray(),
  790. writeBonePosList = writeBonePosList.ToJobArray(bufferIndex),
  791. writeBoneRotList = writeBoneRotList.ToJobArray(bufferIndex),
  792. boneUnityPhysicsList = boneUnityPhysicsList.ToJobArray(),
  793. };
  794. Compute.MasterJob = job.Schedule(writeBoneList.GetTransformAccessArray(), Compute.MasterJob);
  795. }
  796. }
  797. /// <summary>
  798. /// ボーン姿勢をトランスフォームに書き込む
  799. /// </summary>
  800. [BurstCompile]
  801. struct WriteBontToTransformJob2 : IJobParallelForTransform
  802. {
  803. public int fixedUpdateCount;
  804. [Unity.Collections.ReadOnly]
  805. public NativeArray<byte> boneFlagList;
  806. [Unity.Collections.ReadOnly]
  807. public NativeArray<int> writeBoneIndexList;
  808. [Unity.Collections.ReadOnly]
  809. public NativeArray<int> boneParentIndexList;
  810. [Unity.Collections.ReadOnly]
  811. public NativeArray<float3> writeBonePosList;
  812. [Unity.Collections.ReadOnly]
  813. public NativeArray<quaternion> writeBoneRotList;
  814. [Unity.Collections.ReadOnly]
  815. public NativeArray<short> boneUnityPhysicsList;
  816. // 書き込みトランスフォームごと
  817. public void Execute(int index, TransformAccess transform)
  818. {
  819. if (index >= writeBoneIndexList.Length)
  820. return;
  821. int bindex = writeBoneIndexList[index];
  822. if (bindex == 0)
  823. return;
  824. bindex--; // +1が入っているので-1する
  825. // 書き込みフラグチェック
  826. var flag = boneFlagList[bindex];
  827. if ((flag & Flag_Write) == 0)
  828. return;
  829. bool unityPhysics = boneUnityPhysicsList[bindex] > 0;
  830. if (unityPhysics == false || fixedUpdateCount > 0)
  831. {
  832. var pos = writeBonePosList[index];
  833. var rot = writeBoneRotList[index];
  834. int parentIndex = boneParentIndexList[bindex];
  835. //Debug.Log($"Write Bone:{bindex} Parent:{parentIndex} Pos:{pos}");
  836. if (parentIndex >= 0)
  837. {
  838. // 親を参照する場合はローカル座標で書き込む
  839. transform.localPosition = pos;
  840. transform.localRotation = rot;
  841. }
  842. else
  843. {
  844. // 親がいない場合はワールドで書き込む
  845. transform.position = pos;
  846. transform.rotation = rot;
  847. }
  848. }
  849. }
  850. }
  851. //=========================================================================================
  852. /// <summary>
  853. /// ボーン情報を書き込みバッファにコピーする
  854. /// これは遅延実行時のみ
  855. /// </summary>
  856. public void CopyBoneBuffer()
  857. {
  858. var job0 = new CopyBoneJob0()
  859. {
  860. bonePosList = writeBonePosList.ToJobArray(),
  861. boneRotList = writeBoneRotList.ToJobArray(),
  862. backBonePosList = writeBonePosList.ToJobArray(1),
  863. backBoneRotList = writeBoneRotList.ToJobArray(1),
  864. };
  865. var jobHandle0 = job0.Schedule(writeBonePosList.Length, 16);
  866. var job1 = new CopyBoneJob1()
  867. {
  868. writeBoneIndexList = writeBoneIndexList.ToJobArray(),
  869. backWriteBoneIndexList = writeBoneIndexList.ToJobArray(1),
  870. };
  871. var jobHandle1 = job1.Schedule(writeBoneIndexList.Length, 16);
  872. var job2 = new CopyBoneJob2()
  873. {
  874. boneFlagList = boneFlagList.ToJobArray(),
  875. backBoneFlagList = boneFlagList.ToJobArray(1),
  876. };
  877. var jobHandle2 = job2.Schedule(boneFlagList.Length, 16);
  878. Compute.MasterJob = JobHandle.CombineDependencies(jobHandle0, jobHandle1, jobHandle2);
  879. }
  880. [BurstCompile]
  881. struct CopyBoneJob0 : IJobParallelFor
  882. {
  883. [Unity.Collections.ReadOnly]
  884. public NativeArray<float3> bonePosList;
  885. [Unity.Collections.ReadOnly]
  886. public NativeArray<quaternion> boneRotList;
  887. [Unity.Collections.WriteOnly]
  888. public NativeArray<float3> backBonePosList;
  889. [Unity.Collections.WriteOnly]
  890. public NativeArray<quaternion> backBoneRotList;
  891. public void Execute(int index)
  892. {
  893. backBonePosList[index] = bonePosList[index];
  894. backBoneRotList[index] = boneRotList[index];
  895. }
  896. }
  897. [BurstCompile]
  898. struct CopyBoneJob1 : IJobParallelFor
  899. {
  900. [Unity.Collections.ReadOnly]
  901. public NativeArray<int> writeBoneIndexList;
  902. [Unity.Collections.WriteOnly]
  903. public NativeArray<int> backWriteBoneIndexList;
  904. public void Execute(int index)
  905. {
  906. backWriteBoneIndexList[index] = writeBoneIndexList[index];
  907. }
  908. }
  909. [BurstCompile]
  910. struct CopyBoneJob2 : IJobParallelFor
  911. {
  912. [Unity.Collections.ReadOnly]
  913. public NativeArray<byte> boneFlagList;
  914. [Unity.Collections.WriteOnly]
  915. public NativeArray<byte> backBoneFlagList;
  916. public void Execute(int index)
  917. {
  918. backBoneFlagList[index] = boneFlagList[index];
  919. }
  920. }
  921. }
  922. }