MagicaBoneSpring.cs 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612
  1. // Magica Cloth.
  2. // Copyright (c) MagicaSoft, 2020-2022.
  3. // https://magicasoft.jp
  4. using System.Collections.Generic;
  5. using Unity.Mathematics;
  6. using UnityEngine;
  7. #if UNITY_EDITOR
  8. using UnityEditor;
  9. #endif
  10. namespace MagicaCloth
  11. {
  12. /// <summary>
  13. /// ボーンスプリング
  14. /// </summary>
  15. [HelpURL("https://magicasoft.jp/magica-cloth-bone-spring/")]
  16. [AddComponentMenu("MagicaCloth/MagicaBoneSpring")]
  17. public class MagicaBoneSpring : BaseCloth
  18. {
  19. /// <summary>
  20. /// データバージョン
  21. /// </summary>
  22. private const int DATA_VERSION = 7;
  23. /// <summary>
  24. /// エラーデータバージョン
  25. /// </summary>
  26. private const int ERR_DATA_VERSION = 3;
  27. /// <summary>
  28. /// メッシュデータ
  29. /// </summary>
  30. [SerializeField]
  31. private MeshData meshData = null;
  32. [SerializeField]
  33. private int meshDataHash;
  34. [SerializeField]
  35. private int meshDataVersion;
  36. /// <summary>
  37. /// 使用ルートトランスフォーム情報
  38. /// </summary>
  39. [SerializeField]
  40. private BoneClothTarget clothTarget = new BoneClothTarget();
  41. /// <summary>
  42. /// 最終的に使用されるすべてのトランスフォーム情報
  43. /// </summary>
  44. [SerializeField]
  45. private List<Transform> useTransformList = new List<Transform>();
  46. [SerializeField]
  47. private List<Vector3> useTransformPositionList = new List<Vector3>();
  48. [SerializeField]
  49. private List<Quaternion> useTransformRotationList = new List<Quaternion>();
  50. [SerializeField]
  51. private List<Vector3> useTransformScaleList = new List<Vector3>();
  52. //=========================================================================================
  53. public override ComponentType GetComponentType()
  54. {
  55. return ComponentType.BoneSpring;
  56. }
  57. //=========================================================================================
  58. /// <summary>
  59. /// データハッシュを求める
  60. /// </summary>
  61. /// <returns></returns>
  62. public override int GetDataHash()
  63. {
  64. int hash = base.GetDataHash();
  65. hash += MeshData.GetDataHash();
  66. hash += clothTarget.GetDataHash();
  67. hash += useTransformList.GetDataHash();
  68. hash += useTransformPositionList.GetDataHash();
  69. hash += useTransformRotationList.GetDataHash();
  70. hash += useTransformScaleList.GetDataHash();
  71. return hash;
  72. }
  73. //=========================================================================================
  74. public BoneClothTarget ClothTarget
  75. {
  76. get
  77. {
  78. return clothTarget;
  79. }
  80. }
  81. public MeshData MeshData
  82. {
  83. get
  84. {
  85. #if UNITY_EDITOR
  86. if (Application.isPlaying)
  87. return meshData;
  88. else
  89. {
  90. // unity2019.3で参照がnullとなる不具合の対処(臨時)
  91. var so = new SerializedObject(this);
  92. return so.FindProperty("meshData").objectReferenceValue as MeshData;
  93. }
  94. #else
  95. return meshData;
  96. #endif
  97. }
  98. }
  99. //=========================================================================================
  100. protected override void Reset()
  101. {
  102. base.Reset();
  103. ResetParams();
  104. }
  105. protected override void OnValidate()
  106. {
  107. base.OnValidate();
  108. }
  109. protected override void ClothInit()
  110. {
  111. // ルートトランスフォームの親をすべて登録する
  112. ClothTarget.AddParentTransform();
  113. base.ClothInit();
  114. // スプリングではClampPositonの速度制限は無視する
  115. MagicaPhysicsManager.Instance.Team.SetFlag(TeamId, PhysicsManagerTeamData.Flag_IgnoreClampPositionVelocity, true);
  116. }
  117. protected override void ClothDispose()
  118. {
  119. // ルートトランスフォームの親をすべて解除する
  120. ClothTarget.RemoveParentTransform();
  121. base.ClothDispose();
  122. }
  123. protected override void ClothActive()
  124. {
  125. base.ClothActive();
  126. }
  127. /// <summary>
  128. /// 頂点ごとのパーティクルフラグ設定
  129. /// </summary>
  130. /// <param name="vindex"></param>
  131. /// <returns></returns>
  132. protected override uint UserFlag(int index)
  133. {
  134. uint flag = 0;
  135. bool isFix = ClothData.IsFixedVertex(index);
  136. flag |= PhysicsManagerParticleData.Flag_Transform_Restore; // 実行前にlocalPos/localRot復元
  137. flag |= isFix ? (PhysicsManagerParticleData.Flag_Transform_Read_Pos | PhysicsManagerParticleData.Flag_Transform_Read_Rot) : 0; // トランスフォームをpos/rotに読み込み(固定のみ)
  138. flag |= PhysicsManagerParticleData.Flag_Transform_Read_Base; // トランスフォームをbasePos/baseRotに読み込み
  139. flag |= PhysicsManagerParticleData.Flag_Transform_Write; // 最後にトランスフォームへ座標書き込み
  140. flag |= PhysicsManagerParticleData.Flag_Transform_Parent; // 親トランスフォームを参照する
  141. return flag;
  142. }
  143. /// <summary>
  144. /// 頂点ごとの連動トランスフォーム設定
  145. /// </summary>
  146. /// <param name="vindex"></param>
  147. /// <returns></returns>
  148. protected override Transform UserTransform(int index)
  149. {
  150. return GetUseTransform(index);
  151. }
  152. /// <summary>
  153. /// 頂点ごとの連動トランスフォームのLocalPositionを返す(不要な場合は0)
  154. /// </summary>
  155. /// <param name="vindex"></param>
  156. /// <returns></returns>
  157. protected override float3 UserTransformLocalPosition(int vindex)
  158. {
  159. int index = ClothData.useVertexList[vindex];
  160. return useTransformPositionList[index];
  161. }
  162. /// <summary>
  163. /// 頂点ごとの連動トランスフォームのLocalRotationを返す(不要な場合はquaternion.identity)
  164. /// </summary>
  165. /// <param name="vindex"></param>
  166. /// <returns></returns>
  167. protected override quaternion UserTransformLocalRotation(int vindex)
  168. {
  169. int index = ClothData.useVertexList[vindex];
  170. return useTransformRotationList[index];
  171. }
  172. /// <summary>
  173. /// デフォーマーが必須か返す
  174. /// </summary>
  175. /// <returns></returns>
  176. public override bool IsRequiresDeformer()
  177. {
  178. // BoneClothには不要
  179. return false;
  180. }
  181. /// <summary>
  182. /// デフォーマーを返す
  183. /// </summary>
  184. /// <param name="index"></param>
  185. /// <returns></returns>
  186. public override BaseMeshDeformer GetDeformer()
  187. {
  188. // BoneClothには不要
  189. return null;
  190. }
  191. /// <summary>
  192. /// クロス初期化時に必要なMeshDataを返す(不要ならnull)
  193. /// </summary>
  194. /// <returns></returns>
  195. protected override MeshData GetMeshData()
  196. {
  197. return MeshData;
  198. }
  199. /// <summary>
  200. /// クロス初期化の主にワーカーへの登録
  201. /// </summary>
  202. protected override void WorkerInit()
  203. {
  204. // BoneClothには不要
  205. }
  206. /// <summary>
  207. /// デフォーマーごとの使用頂点設定
  208. /// 使用頂点に対して AddUseVertex() / RemoveUseVertex() を実行する
  209. /// </summary>
  210. /// <param name="sw"></param>
  211. /// <param name="deformer"></param>
  212. protected override void SetDeformerUseVertex(bool sw, BaseMeshDeformer deformer)
  213. {
  214. // BoneClothには不要
  215. }
  216. /// <summary>
  217. /// UnityPhyiscsでの更新の変更
  218. /// 継承クラスは自身の使用するボーンの状態更新などを記述する
  219. /// </summary>
  220. /// <param name="sw"></param>
  221. protected override void ChangeUseUnityPhysics(bool sw)
  222. {
  223. base.ChangeUseUnityPhysics(sw);
  224. if (teamId <= 0)
  225. return;
  226. ClothTarget.ChangeUnityPhysicsCount(sw);
  227. }
  228. protected override void OnChangeCalculation()
  229. {
  230. base.OnChangeCalculation();
  231. if (IsCalculate)
  232. {
  233. // ルートトランスフォームの親の未来予測をリセットする
  234. // 遅延実行+再アクティブ時のみ
  235. //if (MagicaPhysicsManager.Instance.IsDelay && ActiveCount > 1)
  236. if (MagicaPhysicsManager.Instance.IsDelay)
  237. {
  238. ClothTarget.ResetFuturePredictionParentTransform();
  239. // 読み込みボーンの未来予測をリセットする
  240. MagicaPhysicsManager.Instance.Particle.ResetFuturePredictionTransform(particleChunk);
  241. }
  242. }
  243. // 書き込みボーンのフラグ設定
  244. if (MagicaPhysicsManager.IsInstance())
  245. {
  246. //Debug.Log($"ChangeWriteBoneFlag:[{this.name}] Write:{IsCalculate} F:{Time.frameCount}");
  247. MagicaPhysicsManager.Instance.Team.ChangeBoneFlag(TeamId, CullingMode, IsCalculate);
  248. }
  249. }
  250. //=========================================================================================
  251. /// <summary>
  252. /// 使用するトランスフォームをリストにして返す
  253. /// </summary>
  254. /// <returns></returns>
  255. public List<Transform> GetTransformList()
  256. {
  257. List<Transform> transformList = new List<Transform>();
  258. int cnt = clothTarget.RootCount;
  259. for (int i = 0; i < cnt; i++)
  260. {
  261. var root = clothTarget.GetRoot(i);
  262. if (root != null)
  263. {
  264. transformList.Add(root);
  265. }
  266. }
  267. return transformList;
  268. }
  269. Transform GetUseTransform(int index)
  270. {
  271. int vindex = ClothData.useVertexList[index];
  272. return useTransformList[vindex];
  273. }
  274. int UseTransformCount
  275. {
  276. get
  277. {
  278. return useTransformList.Count;
  279. }
  280. }
  281. //=========================================================================================
  282. public override int GetVersion()
  283. {
  284. return DATA_VERSION;
  285. }
  286. /// <summary>
  287. /// エラーとするデータバージョンを取得する
  288. /// </summary>
  289. /// <returns></returns>
  290. public override int GetErrorVersion()
  291. {
  292. return ERR_DATA_VERSION;
  293. }
  294. /// <summary>
  295. /// データを検証して結果を格納する
  296. /// </summary>
  297. /// <returns></returns>
  298. public override void CreateVerifyData()
  299. {
  300. base.CreateVerifyData();
  301. meshDataHash = MeshData.SaveDataHash;
  302. meshDataVersion = MeshData.SaveDataVersion;
  303. }
  304. /// <summary>
  305. /// 現在のデータが正常(実行できる状態)か返す
  306. /// </summary>
  307. /// <returns></returns>
  308. public override Define.Error VerifyData()
  309. {
  310. var baseError = base.VerifyData();
  311. if (baseError != Define.Error.None)
  312. return baseError;
  313. var mdata = MeshData;
  314. if (mdata == null)
  315. return Define.Error.MeshDataNull;
  316. var mdataError = mdata.VerifyData();
  317. if (mdataError != Define.Error.None)
  318. return mdataError;
  319. if (meshDataHash != mdata.SaveDataHash)
  320. return Define.Error.MeshDataHashMismatch;
  321. if (meshDataVersion != mdata.SaveDataVersion)
  322. return Define.Error.MeshDataVersionMismatch;
  323. if (useTransformList.Count == 0)
  324. return Define.Error.UseTransformCountZero;
  325. if (UseTransformCount != mdata.VertexCount)
  326. return Define.Error.UseTransformCountMismatch;
  327. if (clothTarget.RootCount != mdata.VertexCount)
  328. return Define.Error.ClothTargetRootCountMismatch;
  329. if (useTransformPositionList.Count != useTransformList.Count)
  330. return Define.Error.UseTransformCountMismatch;
  331. if (useTransformRotationList.Count != useTransformList.Count)
  332. return Define.Error.UseTransformCountMismatch;
  333. if (useTransformScaleList.Count != useTransformList.Count)
  334. return Define.Error.UseTransformCountMismatch;
  335. foreach (var t in useTransformList)
  336. if (t == null)
  337. return Define.Error.UseTransformNull;
  338. return Define.Error.None;
  339. }
  340. /// <summary>
  341. /// データ検証の結果テキストを取得する
  342. /// </summary>
  343. /// <returns></returns>
  344. public override string GetInformation()
  345. {
  346. StaticStringBuilder.Clear();
  347. var err = VerifyData();
  348. if (err == Define.Error.None)
  349. {
  350. // OK
  351. var cdata = ClothData;
  352. StaticStringBuilder.AppendLine("Active: ", Status.IsActive);
  353. StaticStringBuilder.AppendLine($"Visible: {IsVisible}");
  354. StaticStringBuilder.AppendLine($"Calculation:{IsCalculate}");
  355. StaticStringBuilder.AppendLine("Transform: ", MeshData.VertexCount);
  356. StaticStringBuilder.AppendLine("Clamp Position: ", clothParams.UseClampPositionLength ? cdata.VertexUseCount : 0);
  357. StaticStringBuilder.AppendLine("Spring: ", clothParams.UseSpring ? cdata.VertexUseCount : 0);
  358. StaticStringBuilder.Append("Adjust Rotation: ", cdata.VertexUseCount);
  359. }
  360. else if (err == Define.Error.EmptyData)
  361. {
  362. StaticStringBuilder.Append(Define.GetErrorMessage(err));
  363. }
  364. else
  365. {
  366. // エラー
  367. StaticStringBuilder.AppendLine("This bone spring is in a state error!");
  368. if (Application.isPlaying)
  369. {
  370. StaticStringBuilder.AppendLine("Execution stopped.");
  371. }
  372. else
  373. {
  374. StaticStringBuilder.AppendLine("Please recreate the bone spring data.");
  375. }
  376. StaticStringBuilder.Append(Define.GetErrorMessage(err));
  377. }
  378. return StaticStringBuilder.ToString();
  379. }
  380. //=========================================================================================
  381. /// <summary>
  382. /// ボーンを置換する
  383. /// </summary>
  384. /// <param name="boneReplaceDict"></param>
  385. public override void ReplaceBone<T>(Dictionary<T, Transform> boneReplaceDict)
  386. {
  387. base.ReplaceBone(boneReplaceDict);
  388. for (int i = 0; i < useTransformList.Count; i++)
  389. {
  390. useTransformList[i] = MeshUtility.GetReplaceBone(useTransformList[i], boneReplaceDict);
  391. }
  392. clothTarget.ReplaceBone(boneReplaceDict);
  393. }
  394. /// <summary>
  395. /// 現在使用しているボーンを格納して返す
  396. /// </summary>
  397. /// <returns></returns>
  398. public override HashSet<Transform> GetUsedBones()
  399. {
  400. var bones = base.GetUsedBones();
  401. bones.UnionWith(useTransformList);
  402. bones.UnionWith(clothTarget.GetUsedBones());
  403. return bones;
  404. }
  405. //=========================================================================================
  406. /// <summary>
  407. /// メッシュのワールド座標/法線/接線を返す(エディタ用)
  408. /// </summary>
  409. /// <param name="wposList"></param>
  410. /// <param name="wnorList"></param>
  411. /// <param name="wtanList"></param>
  412. /// <returns>頂点数</returns>
  413. public override int GetEditorPositionNormalTangent(out List<Vector3> wposList, out List<Vector3> wnorList, out List<Vector3> wtanList)
  414. {
  415. wposList = new List<Vector3>();
  416. wnorList = new List<Vector3>();
  417. wtanList = new List<Vector3>();
  418. var tlist = GetTransformList();
  419. foreach (var t in tlist)
  420. {
  421. wposList.Add(t.position);
  422. wnorList.Add(t.TransformDirection(Vector3.forward));
  423. var up = t.TransformDirection(Vector3.up);
  424. wtanList.Add(up);
  425. }
  426. return wposList.Count;
  427. }
  428. /// <summary>
  429. /// メッシュのトライアングルリストを返す(エディタ用)
  430. /// </summary>
  431. /// <returns></returns>
  432. public override List<int> GetEditorTriangleList()
  433. {
  434. List<int> triangles = new List<int>();
  435. var mdata = MeshData;
  436. if (mdata != null && mdata.triangleList != null)
  437. triangles = new List<int>(mdata.triangleList);
  438. return triangles;
  439. }
  440. /// <summary>
  441. /// メッシュのラインリストを返す(エディタ用)
  442. /// </summary>
  443. /// <returns></returns>
  444. public override List<int> GetEditorLineList()
  445. {
  446. List<int> lines = new List<int>();
  447. var mdata = MeshData;
  448. if (mdata != null && mdata.lineList != null)
  449. lines = new List<int>(mdata.lineList);
  450. return lines;
  451. }
  452. //=========================================================================================
  453. /// <summary>
  454. /// 頂点の選択状態をリストにして返す(エディタ用)
  455. /// 選択状態は ClothSelection.Invalid / ClothSelection.Fixed / ClothSelection.Move
  456. /// すべてがInvalidならばnullを返す
  457. /// </summary>
  458. /// <returns></returns>
  459. public override List<int> GetSelectionList()
  460. {
  461. if (ClothSelection != null && MeshData != null)
  462. return ClothSelection.GetSelectionData(MeshData, null);
  463. else
  464. return null;
  465. }
  466. /// <summary>
  467. /// 頂点の使用状態をリストにして返す(エディタ用)
  468. /// 数値が1以上ならば使用中とみなす
  469. /// すべて使用状態ならばnullを返す
  470. /// </summary>
  471. /// <returns></returns>
  472. public override List<int> GetUseList()
  473. {
  474. if (Application.isPlaying)
  475. {
  476. if (ClothData != null)
  477. {
  478. var useList = new List<int>();
  479. foreach (var sel in ClothData.selectionData)
  480. useList.Add(sel != SelectionData.Invalid ? 1 : 0);
  481. return useList;
  482. }
  483. }
  484. return null;
  485. }
  486. //=========================================================================================
  487. /// <summary>
  488. /// 共有データオブジェクト収集
  489. /// </summary>
  490. /// <returns></returns>
  491. public override List<ShareDataObject> GetAllShareDataObject()
  492. {
  493. var sdata = base.GetAllShareDataObject();
  494. sdata.Add(MeshData);
  495. return sdata;
  496. }
  497. /// <summary>
  498. /// sourceの共有データを複製して再セットする
  499. /// 再セットした共有データを返す
  500. /// </summary>
  501. /// <param name="source"></param>
  502. /// <returns></returns>
  503. public override ShareDataObject DuplicateShareDataObject(ShareDataObject source)
  504. {
  505. var sdata = base.DuplicateShareDataObject(source);
  506. if (sdata != null)
  507. return sdata;
  508. if (MeshData == source)
  509. {
  510. //meshData = Instantiate(MeshData);
  511. meshData = ShareDataObject.Clone(MeshData);
  512. return meshData;
  513. }
  514. return null;
  515. }
  516. //=========================================================================================
  517. /// <summary>
  518. /// パラメータ初期化
  519. /// </summary>
  520. void ResetParams()
  521. {
  522. clothParams.AlgorithmType = ClothParams.Algorithm.Algorithm_2;
  523. clothParams.SetRadius(0.05f, 0.05f);
  524. clothParams.SetMass(1.0f, 1.0f, false);
  525. clothParams.SetGravity(false, -5.0f, -5.0f);
  526. clothParams.SetDrag(true, 0.03f, 0.03f);
  527. clothParams.SetMaxVelocity(true, 3.0f, 3.0f);
  528. clothParams.SetWorldInfluence(2.0f, 0.5f, 1.0f);
  529. clothParams.SetTeleport(false);
  530. clothParams.SetClampDistanceRatio(false);
  531. clothParams.SetClampPositionLength(true, 0.2f, 0.2f, 1.0f, 1.0f, 1.0f, 1.0f);
  532. clothParams.SetClampRotationAngle(false);
  533. clothParams.SetRestoreDistance(1.0f);
  534. clothParams.SetRestoreRotation(false);
  535. clothParams.SetSpring(true, 0.02f, 0.1f, 1.0f, 1.0f, 1.0f, 1.0f);
  536. clothParams.SetAdjustRotation(ClothParams.AdjustMode.Fixed, 3.0f);
  537. clothParams.SetTriangleBend(false);
  538. clothParams.SetVolume(false);
  539. clothParams.SetCollision(false, 0.1f);
  540. clothParams.SetExternalForce(0.2f, 0.0f, 0.0f, 1.0f);
  541. }
  542. }
  543. }