PolygonLinkReduction.cs 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. // Magica Cloth.
  2. // Copyright (c) MagicaSoft, 2020-2022.
  3. // https://magicasoft.jp
  4. using System.Collections.Generic;
  5. using UnityEngine;
  6. namespace MagicaReductionMesh
  7. {
  8. /// <summary>
  9. /// ポリゴンの接続に沿ったリダクション
  10. /// </summary>
  11. public class PolygonLinkReduction
  12. {
  13. protected MeshData meshData;
  14. private float reductionLength;
  15. /// <summary>
  16. /// 頂点データ
  17. /// </summary>
  18. public class Point
  19. {
  20. public MeshData.ShareVertex shareVertex;
  21. /// <summary>
  22. /// 現在の最近点のポイント(null=なし)
  23. /// </summary>
  24. public Point nearPoint;
  25. /// <summary>
  26. /// 現在の最近点ポイントまでの距離
  27. /// </summary>
  28. public float nearDist;
  29. }
  30. /// <summary>
  31. /// 頂点データリスト
  32. /// </summary>
  33. List<Point> pointList = new List<Point>();
  34. /// <summary>
  35. /// 共有頂点からの逆引き辞書
  36. /// </summary>
  37. Dictionary<MeshData.ShareVertex, Point> pointDict = new Dictionary<MeshData.ShareVertex, Point>();
  38. //=========================================================================================
  39. public PolygonLinkReduction(float length)
  40. {
  41. reductionLength = length;
  42. }
  43. public int PointCount
  44. {
  45. get
  46. {
  47. return pointList.Count;
  48. }
  49. }
  50. //=========================================================================================
  51. /// <summary>
  52. /// リダクションデータをメッシュデータから構築する
  53. /// </summary>
  54. /// <param name="meshData"></param>
  55. public void Create(MeshData meshData)
  56. {
  57. this.meshData = meshData;
  58. foreach (var sv in meshData.shareVertexList)
  59. {
  60. AddPoint(sv);
  61. }
  62. // すべてのの最近点を求める
  63. SearchNearPointAll();
  64. }
  65. /// <summary>
  66. /// リダクション実行
  67. /// </summary>
  68. public void Reduction()
  69. {
  70. Point p0 = null;
  71. var nlist = new List<Point>();
  72. while ((p0 = GetNearPointPair()) != null)
  73. {
  74. // p0にp1をマージする
  75. var p1 = p0.nearPoint;
  76. Debug.Assert(p1 != null);
  77. var sv0 = p0.shareVertex;
  78. var sv1 = p1.shareVertex;
  79. // この2つの頂点を最近点として参照しているリスト
  80. nlist.Clear();
  81. foreach (var sv in sv0.linkShareVertexSet)
  82. nlist.Add(pointDict[sv]);
  83. foreach (var sv in sv1.linkShareVertexSet)
  84. nlist.Add(pointDict[sv]);
  85. nlist.Add(p0); // p0も追加する
  86. // 最近点の参照を切る
  87. foreach (var np in nlist)
  88. {
  89. np.nearPoint = null;
  90. np.nearDist = 100000;
  91. }
  92. // p1を削除
  93. Remove(p1);
  94. p1 = null;
  95. // sv1にsv2をマージ
  96. meshData.CombineVertex(sv0, sv1);
  97. // p0/p1を指していたポイントに対して最近点を再計算する
  98. foreach (var np in nlist)
  99. {
  100. SearchNearPoint(np);
  101. }
  102. }
  103. }
  104. //=========================================================================================
  105. void AddPoint(MeshData.ShareVertex sv)
  106. {
  107. var p = new Point();
  108. p.shareVertex = sv;
  109. pointList.Add(p);
  110. pointDict.Add(sv, p);
  111. }
  112. Point GetPoint(MeshData.ShareVertex sv)
  113. {
  114. if (pointDict.ContainsKey(sv))
  115. return pointDict[sv];
  116. return null;
  117. }
  118. /// <summary>
  119. /// 頂点をグリッドから削除する
  120. /// </summary>
  121. /// <param name="p"></param>
  122. void Remove(Point p)
  123. {
  124. // データ削除
  125. pointDict.Remove(p.shareVertex);
  126. pointList.Remove(p);
  127. }
  128. //=========================================================================================
  129. /// <summary>
  130. /// すべての共有頂点の最近接続頂点を調べる
  131. /// </summary>
  132. void SearchNearPointAll()
  133. {
  134. foreach (var p in pointList)
  135. {
  136. SearchNearPoint(p);
  137. }
  138. }
  139. /// <summary>
  140. /// 指定頂点の最近接続頂点を調べる
  141. /// </summary>
  142. /// <param name="p"></param>
  143. void SearchNearPoint(Point p)
  144. {
  145. p.nearPoint = null;
  146. p.nearDist = 100000;
  147. var wpos = p.shareVertex.wpos;
  148. foreach (var sv in p.shareVertex.linkShareVertexSet)
  149. {
  150. var dist = Vector3.Distance(wpos, sv.wpos);
  151. if (dist < p.nearDist && dist <= reductionLength)
  152. {
  153. p.nearDist = dist;
  154. p.nearPoint = pointDict[sv];
  155. }
  156. }
  157. }
  158. /// <summary>
  159. /// 現時点で最も距離が近いポイントペアを返す
  160. /// </summary>
  161. /// <returns></returns>
  162. Point GetNearPointPair()
  163. {
  164. float nearDist = 10000;
  165. Point nearPoint = null;
  166. // ※全検索
  167. foreach (var p in pointList)
  168. {
  169. if (p.nearPoint != null && p.nearDist < nearDist)
  170. {
  171. nearDist = p.nearDist;
  172. nearPoint = p;
  173. }
  174. }
  175. return nearPoint;
  176. }
  177. }
  178. }