MegaNearestPoint.cs 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. using UnityEngine;
  2. using System.Collections;
  3. public class MegaNearestPointTest
  4. {
  5. public static Vector3 NearestPointOnMesh1(Vector3 pt, Vector3[] verts, int[] tri, ref int index, ref Vector3 bary)
  6. {
  7. float nearestSqDist = float.MaxValue;
  8. Vector3 nearestPt = Vector3.zero;
  9. nearestSqDist = float.MaxValue;
  10. for ( int i = 0; i < tri.Length; i += 3 )
  11. {
  12. Vector3 a = verts[tri[i]];
  13. Vector3 b = verts[tri[i + 1]];
  14. Vector3 c = verts[tri[i + 2]];
  15. float dist = DistPoint3Triangle3Dbl(pt, a, b, c);
  16. float possNearestSqDist = dist;
  17. if ( possNearestSqDist < nearestSqDist )
  18. {
  19. index = i;
  20. bary = mTriangleBary;
  21. nearestPt = mClosestPoint1;
  22. nearestSqDist = possNearestSqDist;
  23. }
  24. }
  25. return nearestPt;
  26. }
  27. public static Vector3 NearestPointOnMesh2(Vector3 pt, Vector3[] verts, int[] tri, ref int index, ref Vector3 bary)
  28. {
  29. float nearestSqDist = float.MaxValue;
  30. Vector3 nearestPt = Vector3.zero;
  31. nearestSqDist = float.MaxValue;
  32. for ( int i = 0; i < tri.Length; i += 3 )
  33. {
  34. Vector3 a = verts[tri[i]];
  35. Vector3 b = verts[tri[i + 1]];
  36. Vector3 c = verts[tri[i + 2]];
  37. float dist = DistPoint3Triangle3Dbl(pt, a, b, c);
  38. float possNearestSqDist = dist;
  39. if ( possNearestSqDist < nearestSqDist )
  40. {
  41. index = i;
  42. bary = mTriangleBary;
  43. nearestPt = mClosestPoint1;
  44. nearestSqDist = possNearestSqDist;
  45. }
  46. }
  47. return nearestPt;
  48. }
  49. public static float DistPoint3Triangle3Dbl(Vector3 mPoint, Vector3 v0, Vector3 v1, Vector3 v2)
  50. {
  51. Vector3 diff = v0 - mPoint;
  52. Vector3 edge0 = v1 - v0;
  53. Vector3 edge1 = v2 - v0;
  54. double a00 = edge0.sqrMagnitude; //.SquaredLength();
  55. double a01 = Vector3.Dot(edge1, edge0);
  56. double a11 = edge1.sqrMagnitude;
  57. double b0 = Vector3.Dot(edge0, diff);
  58. double b1 = Vector3.Dot(edge1, diff);
  59. double c = diff.sqrMagnitude;
  60. double det = Mathf.Abs((float)a00 * (float)a11 - (float)a01 * (float)a01);
  61. double s = a01 * b1 - a11 * b0;
  62. double t = a01 * b0 - a00 * b1;
  63. double sqrDistance;
  64. if ( s + t <= det )
  65. {
  66. if ( s < (double)0.0 )
  67. {
  68. if ( t < (double)0 ) // region 4
  69. {
  70. if ( b0 < (double)0 )
  71. {
  72. t = (double)0;
  73. if ( -b0 >= a00 )
  74. {
  75. s = (double)1;
  76. sqrDistance = a00 + ((double)2) * b0 + c;
  77. }
  78. else
  79. {
  80. s = -b0 / a00;
  81. sqrDistance = b0 * s + c;
  82. }
  83. }
  84. else
  85. {
  86. s = (double)0;
  87. if ( b1 >= (double)0 )
  88. {
  89. t = (double)0;
  90. sqrDistance = c;
  91. }
  92. else if ( -b1 >= a11 )
  93. {
  94. t = (double)1;
  95. sqrDistance = a11 + ((double)2) * b1 + c;
  96. }
  97. else
  98. {
  99. t = -b1 / a11;
  100. sqrDistance = b1 * t + c;
  101. }
  102. }
  103. }
  104. else // region 3
  105. {
  106. s = (double)0;
  107. if ( b1 >= (double)0 )
  108. {
  109. t = (double)0;
  110. sqrDistance = c;
  111. }
  112. else if ( -b1 >= a11 )
  113. {
  114. t = (double)1;
  115. sqrDistance = a11 + ((double)2) * b1 + c;
  116. }
  117. else
  118. {
  119. t = -b1 / a11;
  120. sqrDistance = b1 * t + c;
  121. }
  122. }
  123. }
  124. else if ( t < (double)0 ) // region 5
  125. {
  126. t = (double)0;
  127. if ( b0 >= (double)0 )
  128. {
  129. s = (double)0;
  130. sqrDistance = c;
  131. }
  132. else if ( -b0 >= a00 )
  133. {
  134. s = (double)1;
  135. sqrDistance = a00 + ((double)2) * b0 + c;
  136. }
  137. else
  138. {
  139. s = -b0 / a00;
  140. sqrDistance = b0 * s + c;
  141. }
  142. }
  143. else // region 0
  144. {
  145. // minimum at interior point
  146. double invDet = ((double)1) / det;
  147. s *= invDet;
  148. t *= invDet;
  149. sqrDistance = s * (a00 * s + a01 * t + ((double)2) * b0) +
  150. t * (a01 * s + a11 * t + ((double)2) * b1) + c;
  151. }
  152. }
  153. else
  154. {
  155. double tmp0, tmp1, numer, denom;
  156. if ( s < (double)0 ) // region 2
  157. {
  158. tmp0 = a01 + b0;
  159. tmp1 = a11 + b1;
  160. if ( tmp1 > tmp0 )
  161. {
  162. numer = tmp1 - tmp0;
  163. denom = a00 - ((double)2) * a01 + a11;
  164. if ( numer >= denom )
  165. {
  166. s = (double)1;
  167. t = (double)0;
  168. sqrDistance = a00 + ((double)2) * b0 + c;
  169. }
  170. else
  171. {
  172. s = numer / denom;
  173. t = (double)1 - s;
  174. sqrDistance = s * (a00 * s + a01 * t + ((double)2) * b0) +
  175. t * (a01 * s + a11 * t + ((double)2) * b1) + c;
  176. }
  177. }
  178. else
  179. {
  180. s = (double)0;
  181. if ( tmp1 <= (double)0 )
  182. {
  183. t = (double)1;
  184. sqrDistance = a11 + ((double)2) * b1 + c;
  185. }
  186. else if ( b1 >= (double)0 )
  187. {
  188. t = (double)0;
  189. sqrDistance = c;
  190. }
  191. else
  192. {
  193. t = -b1 / a11;
  194. sqrDistance = b1 * t + c;
  195. }
  196. }
  197. }
  198. else if ( t < (double)0 ) // region 6
  199. {
  200. tmp0 = a01 + b1;
  201. tmp1 = a00 + b0;
  202. if ( tmp1 > tmp0 )
  203. {
  204. numer = tmp1 - tmp0;
  205. denom = a00 - ((double)2) * a01 + a11;
  206. if ( numer >= denom )
  207. {
  208. t = (double)1;
  209. s = (double)0;
  210. sqrDistance = a11 + ((double)2) * b1 + c;
  211. }
  212. else
  213. {
  214. t = numer / denom;
  215. s = (double)1 - t;
  216. sqrDistance = s * (a00 * s + a01 * t + ((double)2) * b0) +
  217. t * (a01 * s + a11 * t + ((double)2) * b1) + c;
  218. }
  219. }
  220. else
  221. {
  222. t = (double)0;
  223. if ( tmp1 <= (double)0 )
  224. {
  225. s = (double)1;
  226. sqrDistance = a00 + ((double)2) * b0 + c;
  227. }
  228. else if ( b0 >= (double)0 )
  229. {
  230. s = (double)0;
  231. sqrDistance = c;
  232. }
  233. else
  234. {
  235. s = -b0 / a00;
  236. sqrDistance = b0 * s + c;
  237. }
  238. }
  239. }
  240. else // region 1
  241. {
  242. numer = a11 + b1 - a01 - b0;
  243. if ( numer <= (double)0 )
  244. {
  245. s = (double)0;
  246. t = (double)1;
  247. sqrDistance = a11 + ((double)2) * b1 + c;
  248. }
  249. else
  250. {
  251. denom = a00 - ((double)2) * a01 + a11;
  252. if ( numer >= denom )
  253. {
  254. s = (double)1;
  255. t = (double)0;
  256. sqrDistance = a00 + ((double)2) * b0 + c;
  257. }
  258. else
  259. {
  260. s = numer / denom;
  261. t = (double)1 - s;
  262. sqrDistance = s * (a00 * s + a01 * t + ((double)2) * b0) +
  263. t * (a01 * s + a11 * t + ((double)2) * b1) + c;
  264. }
  265. }
  266. }
  267. }
  268. // Account for numerical round-off error.
  269. if ( sqrDistance < (double)0 )
  270. sqrDistance = (double)0;
  271. mClosestPoint1.x = v0.x + (float)(s * edge0.x + t * edge1.x);
  272. mClosestPoint1.y = v0.y + (float)(s * edge0.y + t * edge1.y);
  273. mClosestPoint1.z = v0.z + (float)(s * edge0.z + t * edge1.z);
  274. mTriangleBary[1] = (float)s;
  275. mTriangleBary[2] = (float)t;
  276. mTriangleBary[0] = (float)((double)1 - s - t);
  277. return (float)sqrDistance;
  278. }
  279. static Vector3 mTriangleBary = Vector3.zero;
  280. static Vector3 mClosestPoint1 = Vector3.zero;
  281. }