MagicaMeshSpring.cs 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649
  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-mesh-spring/")]
  16. [AddComponentMenu("MagicaCloth/MagicaMeshSpring", 100)]
  17. public class MagicaMeshSpring : 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. // 対象仮想メッシュデフォーマー
  28. [SerializeField]
  29. private MagicaVirtualDeformer virtualDeformer = null;
  30. [SerializeField]
  31. private int virtualDeformerHash;
  32. [SerializeField]
  33. private int virtualDeformerVersion;
  34. // センタートランスフォーム
  35. [SerializeField]
  36. private Transform centerTransform = null;
  37. public enum Axis
  38. {
  39. X,
  40. Y,
  41. Z,
  42. InverseX,
  43. InverseY,
  44. InverseZ,
  45. }
  46. [SerializeField]
  47. private Axis directionAxis;
  48. [SerializeField]
  49. private SpringData springData = null;
  50. [SerializeField]
  51. private int springDataHash;
  52. [SerializeField]
  53. private int springDataVersion;
  54. //=========================================================================================
  55. public override ComponentType GetComponentType()
  56. {
  57. return ComponentType.MeshSpring;
  58. }
  59. //=========================================================================================
  60. public override int GetDataHash()
  61. {
  62. int hash = base.GetDataHash();
  63. hash += virtualDeformer.GetDataHash();
  64. hash += centerTransform.GetDataHash();
  65. hash += SpringData.GetDataHash();
  66. return hash;
  67. }
  68. //=========================================================================================
  69. public VirtualMeshDeformer Deformer
  70. {
  71. get
  72. {
  73. if (virtualDeformer != null)
  74. return virtualDeformer.Deformer;
  75. return null;
  76. }
  77. }
  78. public SpringData SpringData
  79. {
  80. get
  81. {
  82. #if UNITY_EDITOR
  83. if (Application.isPlaying)
  84. return springData;
  85. else
  86. {
  87. // unity2019.3で参照がnullとなる不具合の対処(臨時)
  88. var so = new SerializedObject(this);
  89. return so.FindProperty("springData").objectReferenceValue as SpringData;
  90. }
  91. #else
  92. return springData;
  93. #endif
  94. }
  95. }
  96. public int UseVertexCount
  97. {
  98. get
  99. {
  100. if (SpringData == null)
  101. return 0;
  102. else
  103. return SpringData.UseVertexCount;
  104. }
  105. }
  106. public Transform CenterTransform
  107. {
  108. get
  109. {
  110. return centerTransform;
  111. }
  112. set
  113. {
  114. centerTransform = value;
  115. }
  116. }
  117. public Axis DirectionAxis
  118. {
  119. get
  120. {
  121. return directionAxis;
  122. }
  123. set
  124. {
  125. directionAxis = value;
  126. }
  127. }
  128. public Vector3 CenterTransformDirection
  129. {
  130. get
  131. {
  132. Vector3 dir = Vector3.forward;
  133. if (centerTransform)
  134. {
  135. switch (directionAxis)
  136. {
  137. case Axis.X:
  138. dir = centerTransform.right;
  139. break;
  140. case Axis.Y:
  141. dir = centerTransform.up;
  142. break;
  143. case Axis.Z:
  144. dir = centerTransform.forward;
  145. break;
  146. case Axis.InverseX:
  147. dir = -centerTransform.right;
  148. break;
  149. case Axis.InverseY:
  150. dir = -centerTransform.up;
  151. break;
  152. case Axis.InverseZ:
  153. dir = -centerTransform.forward;
  154. break;
  155. }
  156. }
  157. return dir;
  158. }
  159. }
  160. public SpringData.DeformerData GetDeformerData()
  161. {
  162. return SpringData.deformerData;
  163. }
  164. //=========================================================================================
  165. protected override void Reset()
  166. {
  167. base.Reset();
  168. ResetParams();
  169. }
  170. protected override void OnValidate()
  171. {
  172. base.OnValidate();
  173. }
  174. //=========================================================================================
  175. /// <summary>
  176. /// クロス初期化
  177. /// </summary>
  178. protected override void ClothInit()
  179. {
  180. // 中央トランスフォームに移動パーティクルを1つ設定する(これが揺れる)
  181. // クロスデータはこの場で作成する
  182. ClothData cdata = ShareDataObject.CreateShareData<ClothData>("ClothData_work");
  183. cdata.selectionData.Add(SelectionData.Move);
  184. cdata.vertexFlagLevelList.Add(0);
  185. cdata.vertexDepthList.Add(0);
  186. cdata.rootList.Add(0);
  187. cdata.useVertexList.Add(0);
  188. cdata.initScale = SpringData.initScale;
  189. cdata.SaveDataHash = 1;
  190. cdata.SaveDataVersion = cdata.GetVersion();
  191. cdata.clampRotationAlgorithm = ClothParams.Algorithm.Algorithm_2;
  192. cdata.restoreRotationAlgorithm = ClothParams.Algorithm.Algorithm_2;
  193. cdata.triangleBendAlgorithm = ClothParams.Algorithm.Algorithm_2;
  194. ClothData = cdata;
  195. // エラーが出ないように
  196. clothDataHash = cdata.SaveDataHash;
  197. clothDataVersion = cdata.SaveDataVersion;
  198. // クロス初期化
  199. base.ClothInit();
  200. // スプリングではClampPositonの速度制限は無視する
  201. MagicaPhysicsManager.Instance.Team.SetFlag(TeamId, PhysicsManagerTeamData.Flag_IgnoreClampPositionVelocity, true);
  202. }
  203. protected override void ClothActive()
  204. {
  205. base.ClothActive();
  206. }
  207. /// <summary>
  208. /// 頂点ごとのパーティクルフラグ設定(不要な場合は0)
  209. /// </summary>
  210. /// <param name="vindex"></param>
  211. /// <returns></returns>
  212. protected override uint UserFlag(int index)
  213. {
  214. uint flag = 0;
  215. flag |= PhysicsManagerParticleData.Flag_Transform_Read_Base; // トランスフォームをbasePos/baseRotに読み込み
  216. flag |= PhysicsManagerParticleData.Flag_Transform_Read_Rot; // トランスフォームをrotに読み込む
  217. return flag;
  218. }
  219. /// <summary>
  220. /// 頂点ごとの連動トランスフォーム設定(不要な場合はnull)
  221. /// </summary>
  222. /// <param name="vindex"></param>
  223. /// <returns></returns>
  224. protected override Transform UserTransform(int index)
  225. {
  226. return CenterTransform;
  227. }
  228. /// <summary>
  229. /// 頂点ごとの連動トランスフォームのLocalPositionを返す(不要な場合は0)
  230. /// </summary>
  231. /// <param name="vindex"></param>
  232. /// <returns></returns>
  233. protected override float3 UserTransformLocalPosition(int vindex)
  234. {
  235. return CenterTransform.localPosition;
  236. }
  237. /// <summary>
  238. /// 頂点ごとの連動トランスフォームのLocalRotationを返す(不要な場合はquaternion.identity)
  239. /// </summary>
  240. /// <param name="vindex"></param>
  241. /// <returns></returns>
  242. protected override quaternion UserTransformLocalRotation(int vindex)
  243. {
  244. return CenterTransform.localRotation;
  245. }
  246. /// <summary>
  247. /// デフォーマーが必須か返す
  248. /// </summary>
  249. /// <returns></returns>
  250. public override bool IsRequiresDeformer()
  251. {
  252. return true;
  253. }
  254. /// <summary>
  255. /// デフォーマーを返す
  256. /// </summary>
  257. /// <param name="index"></param>
  258. /// <returns></returns>
  259. public override BaseMeshDeformer GetDeformer()
  260. {
  261. if (virtualDeformer)
  262. {
  263. return virtualDeformer.Deformer;
  264. }
  265. return null;
  266. }
  267. /// <summary>
  268. /// クロス初期化時に必要なMeshDataを返す(不要ならnull)
  269. /// </summary>
  270. /// <returns></returns>
  271. protected override MeshData GetMeshData()
  272. {
  273. // MeshSpringeには不要
  274. return null;
  275. }
  276. /// <summary>
  277. /// クロス初期化の主にワーカーへの登録
  278. /// </summary>
  279. protected override void WorkerInit()
  280. {
  281. // センターパーティクル
  282. int pindex = ParticleChunk.startIndex;
  283. // デフォーマーごとの設定
  284. SpringMeshWorker worker = MagicaPhysicsManager.Instance.Compute.SpringMeshWorker;
  285. {
  286. // デフォーマー取得
  287. var deformer = GetDeformer();
  288. Debug.Assert(deformer != null);
  289. deformer.Init();
  290. // スプリングデータ取得
  291. var data = GetDeformerData();
  292. Debug.Assert(data != null);
  293. // スプリングワーカー設定
  294. var minfo = MagicaPhysicsManager.Instance.Mesh.GetVirtualMeshInfo(deformer.MeshIndex);
  295. for (int j = 0; j < data.UseVertexCount; j++)
  296. {
  297. int vindex = data.useVertexIndexList[j];
  298. worker.Add(TeamId, minfo.vertexChunk.startIndex + vindex, pindex, data.weightList[j]);
  299. }
  300. }
  301. }
  302. /// <summary>
  303. /// デフォーマーごとの使用頂点設定
  304. /// 使用頂点に対して AddUseVertex() / RemoveUseVertex() を実行する
  305. /// </summary>
  306. /// <param name="sw"></param>
  307. /// <param name="deformer"></param>
  308. protected override void SetDeformerUseVertex(bool sw, BaseMeshDeformer deformer)
  309. {
  310. var data = GetDeformerData();
  311. int vcnt = data.UseVertexCount;
  312. for (int j = 0; j < vcnt; j++)
  313. {
  314. int vindex = data.useVertexIndexList[j];
  315. if (sw)
  316. deformer.AddUseVertex(vindex, false);
  317. else
  318. deformer.RemoveUseVertex(vindex, false);
  319. }
  320. }
  321. /// <summary>
  322. /// UnityPhyiscsでの更新の変更
  323. /// 継承クラスは自身の使用するボーンの状態更新などを記述する
  324. /// </summary>
  325. /// <param name="sw"></param>
  326. protected override void ChangeUseUnityPhysics(bool sw)
  327. {
  328. base.ChangeUseUnityPhysics(sw);
  329. // デフォーマに伝達
  330. virtualDeformer?.SetUseUnityPhysics(sw);
  331. }
  332. protected override void OnChangeCalculation()
  333. {
  334. base.OnChangeCalculation();
  335. if (IsCalculate)
  336. {
  337. if (MagicaPhysicsManager.Instance.IsDelay)
  338. {
  339. // 読み込みボーンの未来予測をリセットする
  340. MagicaPhysicsManager.Instance.Particle.ResetFuturePredictionTransform(particleChunk);
  341. }
  342. }
  343. }
  344. //=========================================================================================
  345. public override int GetVersion()
  346. {
  347. return DATA_VERSION;
  348. }
  349. /// <summary>
  350. /// エラーとするデータバージョンを取得する
  351. /// </summary>
  352. /// <returns></returns>
  353. public override int GetErrorVersion()
  354. {
  355. return ERR_DATA_VERSION;
  356. }
  357. /// <summary>
  358. /// データを検証して結果を格納する
  359. /// </summary>
  360. /// <returns></returns>
  361. public override void CreateVerifyData()
  362. {
  363. base.CreateVerifyData();
  364. virtualDeformerHash = virtualDeformer.SaveDataHash;
  365. virtualDeformerVersion = virtualDeformer.SaveDataVersion;
  366. springDataHash = SpringData.SaveDataHash;
  367. springDataVersion = SpringData.SaveDataVersion;
  368. }
  369. /// <summary>
  370. /// 現在のデータが正常(実行できる状態)か返す
  371. /// </summary>
  372. /// <returns></returns>
  373. public override Define.Error VerifyData()
  374. {
  375. var baseError = base.VerifyData();
  376. if (baseError != Define.Error.None)
  377. return baseError;
  378. if (virtualDeformer == null)
  379. return Define.Error.DeformerNull;
  380. var vdeformerError = virtualDeformer.VerifyData();
  381. if (vdeformerError != Define.Error.None)
  382. return vdeformerError;
  383. if (virtualDeformerHash != virtualDeformer.SaveDataHash)
  384. return Define.Error.DeformerHashMismatch;
  385. if (virtualDeformerVersion != virtualDeformer.SaveDataVersion)
  386. return Define.Error.DeformerVersionMismatch;
  387. if (centerTransform == null)
  388. return Define.Error.CenterTransformNull;
  389. var sdata = SpringData;
  390. if (sdata == null)
  391. return Define.Error.SpringDataNull;
  392. var sdataError = sdata.VerifyData();
  393. if (sdataError != Define.Error.None)
  394. return sdataError;
  395. if (springDataHash != sdata.SaveDataHash)
  396. return Define.Error.SpringDataHashMismatch;
  397. if (springDataVersion != sdata.SaveDataVersion)
  398. return Define.Error.SpringDataVersionMismatch;
  399. return Define.Error.None;
  400. }
  401. public override string GetInformation()
  402. {
  403. StaticStringBuilder.Clear();
  404. var err = VerifyData();
  405. if (err == Define.Error.None)
  406. {
  407. // OK
  408. StaticStringBuilder.AppendLine("Active: ", Status.IsActive);
  409. StaticStringBuilder.AppendLine($"Visible: {IsVisible}");
  410. StaticStringBuilder.AppendLine($"Calculation:{IsCalculate}");
  411. StaticStringBuilder.Append("Use Deformer Vertex: ", UseVertexCount);
  412. }
  413. else if (err == Define.Error.EmptyData)
  414. {
  415. StaticStringBuilder.Append(Define.GetErrorMessage(err));
  416. }
  417. else
  418. {
  419. // エラー
  420. StaticStringBuilder.AppendLine("This mesh spring is in a state error!");
  421. if (Application.isPlaying)
  422. {
  423. StaticStringBuilder.AppendLine("Execution stopped.");
  424. }
  425. else
  426. {
  427. StaticStringBuilder.AppendLine("Please recreate the mesh spring data.");
  428. }
  429. StaticStringBuilder.Append(Define.GetErrorMessage(err));
  430. }
  431. return StaticStringBuilder.ToString();
  432. }
  433. /// <summary>
  434. /// デフォーマーの検証
  435. /// </summary>
  436. public void VerifyDeformer()
  437. {
  438. }
  439. //=========================================================================================
  440. /// <summary>
  441. /// ボーンを置換する
  442. /// </summary>
  443. /// <param name="boneReplaceDict"></param>
  444. public override void ReplaceBone<T>(Dictionary<T, Transform> boneReplaceDict)
  445. {
  446. if (centerTransform)
  447. {
  448. centerTransform = MeshUtility.GetReplaceBone(centerTransform, boneReplaceDict);
  449. }
  450. }
  451. /// <summary>
  452. /// 現在使用しているボーンを格納して返す
  453. /// </summary>
  454. /// <returns></returns>
  455. public override HashSet<Transform> GetUsedBones()
  456. {
  457. var bones = base.GetUsedBones();
  458. bones.Add(centerTransform);
  459. return bones;
  460. }
  461. //=========================================================================================
  462. /// <summary>
  463. /// メッシュのワールド座標/法線/接線を返す(エディタ用)
  464. /// </summary>
  465. /// <param name="wposList"></param>
  466. /// <param name="wnorList"></param>
  467. /// <param name="wtanList"></param>
  468. /// <returns>頂点数</returns>
  469. public override int GetEditorPositionNormalTangent(out List<Vector3> wposList, out List<Vector3> wnorList, out List<Vector3> wtanList)
  470. {
  471. wposList = new List<Vector3>();
  472. wnorList = new List<Vector3>();
  473. wtanList = new List<Vector3>();
  474. var t = CenterTransform;
  475. if (t == null)
  476. return 0;
  477. wposList.Add(t.position);
  478. wnorList.Add(t.forward);
  479. var up = t.up;
  480. wtanList.Add(up);
  481. return 1;
  482. }
  483. /// <summary>
  484. /// メッシュのトライアングルリストを返す(エディタ用)
  485. /// </summary>
  486. /// <returns></returns>
  487. public override List<int> GetEditorTriangleList()
  488. {
  489. return null;
  490. }
  491. /// <summary>
  492. /// メッシュのラインリストを返す(エディタ用)
  493. /// </summary>
  494. /// <returns></returns>
  495. public override List<int> GetEditorLineList()
  496. {
  497. return null;
  498. }
  499. //=========================================================================================
  500. /// <summary>
  501. /// 頂点の選択状態をリストにして返す(エディタ用)
  502. /// 選択状態は ClothSelection.Invalid / ClothSelection.Fixed / ClothSelection.Move
  503. /// すべてがInvalidならばnullを返す
  504. /// </summary>
  505. /// <returns></returns>
  506. public override List<int> GetSelectionList()
  507. {
  508. return null;
  509. }
  510. /// <summary>
  511. /// 頂点の使用状態をリストにして返す(エディタ用)
  512. /// 数値が1以上ならば使用中とみなす
  513. /// すべて使用状態ならばnullを返す
  514. /// </summary>
  515. /// <returns></returns>
  516. public override List<int> GetUseList()
  517. {
  518. return null;
  519. }
  520. //=========================================================================================
  521. /// <summary>
  522. /// 共有データオブジェクト収集
  523. /// </summary>
  524. /// <returns></returns>
  525. public override List<ShareDataObject> GetAllShareDataObject()
  526. {
  527. var sdata = base.GetAllShareDataObject();
  528. sdata.Add(SpringData);
  529. return sdata;
  530. }
  531. /// <summary>
  532. /// sourceの共有データを複製して再セットする
  533. /// 再セットした共有データを返す
  534. /// </summary>
  535. /// <param name="source"></param>
  536. /// <returns></returns>
  537. public override ShareDataObject DuplicateShareDataObject(ShareDataObject source)
  538. {
  539. var sdata = base.DuplicateShareDataObject(source);
  540. if (sdata != null)
  541. return sdata;
  542. if (SpringData == source)
  543. {
  544. //springData = Instantiate(SpringData);
  545. springData = ShareDataObject.Clone(SpringData);
  546. return springData;
  547. }
  548. return null;
  549. }
  550. //=========================================================================================
  551. /// <summary>
  552. /// パラメータ初期化
  553. /// </summary>
  554. void ResetParams()
  555. {
  556. clothParams.AlgorithmType = ClothParams.Algorithm.Algorithm_2;
  557. clothParams.SetRadius(0.05f, 0.05f);
  558. clothParams.SetMass(1.0f, 1.0f, false);
  559. clothParams.SetGravity(false, -5.0f, -5.0f);
  560. clothParams.SetDrag(true, 0.01f, 0.01f);
  561. clothParams.SetMaxVelocity(true, 3.0f, 3.0f);
  562. clothParams.SetWorldInfluence(2.0f, 0.5f, 1.0f);
  563. clothParams.SetTeleport(false);
  564. clothParams.SetClampDistanceRatio(false);
  565. clothParams.SetClampPositionLength(true, 0.1f, 0.1f, 1.0f, 1.0f, 1.0f, 0.2f);
  566. clothParams.SetClampRotationAngle(false);
  567. clothParams.SetRestoreDistance(1.0f);
  568. clothParams.SetRestoreRotation(false);
  569. clothParams.SetSpring(true, 0.02f, 0.14f, 1.0f, 1.0f, 1.0f, 1.0f);
  570. clothParams.SetSpringDirectionAtten(1.0f, 0.0f, 0.6f);
  571. clothParams.SetSpringDistanceAtten(1.0f, 0.0f, 0.4f);
  572. clothParams.SetAdjustRotation(ClothParams.AdjustMode.Fixed, 5.0f);
  573. clothParams.SetTriangleBend(false);
  574. clothParams.SetVolume(false);
  575. clothParams.SetCollision(false, 0.1f);
  576. clothParams.SetExternalForce(0.2f, 0.0f, 0.0f, 1.0f);
  577. }
  578. }
  579. }