AILib.ts 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. /** @format */
  2. const Vec3 = cc.Vec3
  3. const Quat = cc.Quat
  4. const localP = {x: 0, y: 0, z: 0}
  5. const maxDist = {x: 0, y: 0, z: 0}
  6. const localCenter = {x: 0, y: 0, z: 0}
  7. const obbToLocal = {x: 0, y: 0, z: 0, w: 1.0}
  8. // 计算球体到 AABB 的 SDF 距离
  9. export function sphereAABBDistance(center: any, radius: any, size: any): boolean {
  10. // 计算离包围盒最近的点
  11. maxDist.x = Math.max(-size.x, Math.min(center.x, size.x))
  12. maxDist.y = Math.max(-size.y, Math.min(center.y, size.y))
  13. maxDist.z = Math.max(-size.z, Math.min(center.z, size.z))
  14. Vec3.subtract(maxDist, maxDist, center)
  15. const distSqr = Vec3.dot(maxDist, maxDist)
  16. return distSqr <= radius * radius
  17. }
  18. // 计算球体到 OBB 的 SDF 距离
  19. export function sphereOBBDistance(
  20. sphereCenter: cc.Vec3, // 球体中心点坐标
  21. radius: number, // 球体半径
  22. obbCenter: cc.Vec3, // OBB 中心点坐标
  23. obbQuaternion: cc.Quat, // OBB 旋转四元数
  24. obbHalfExtents: cc.Vec3, // OBB 半扩展尺寸
  25. ): boolean {
  26. Vec3.subtract(localCenter, sphereCenter, obbCenter)
  27. Quat.conjugate(obbToLocal, obbQuaternion)
  28. Vec3.transformQuat(localP, localCenter, obbToLocal)
  29. return sphereAABBDistance(localP, radius, obbHalfExtents)
  30. }
  31. export const obbIntersect = function (centerA: any, halfA: any, rotA: any, centerB: any, halfB: any, rotB: any) {
  32. let ae0 = halfA.x,
  33. ae1 = halfA.y,
  34. ae2 = halfA.z,
  35. ma = rotA.m,
  36. au00 = ma[0],
  37. au01 = ma[1],
  38. au02 = ma[2],
  39. au10 = ma[3],
  40. au11 = ma[4],
  41. au12 = ma[5],
  42. au20 = ma[6],
  43. au21 = ma[7],
  44. au22 = ma[8]
  45. let be0 = halfB.x,
  46. be1 = halfB.y,
  47. be2 = halfB.z,
  48. mb = rotB.m,
  49. bu00 = mb[0],
  50. bu01 = mb[1],
  51. bu02 = mb[2],
  52. bu10 = mb[3],
  53. bu11 = mb[4],
  54. bu12 = mb[5],
  55. bu20 = mb[6],
  56. bu21 = mb[7],
  57. bu22 = mb[8]
  58. let R00 = au00 * bu00 + au01 * bu01 + au02 * bu02
  59. let R01 = au00 * bu10 + au01 * bu11 + au02 * bu12
  60. let R02 = au00 * bu20 + au01 * bu21 + au02 * bu22
  61. let R10 = au10 * bu00 + au11 * bu01 + au12 * bu02
  62. let R11 = au10 * bu10 + au11 * bu11 + au12 * bu12
  63. let R12 = au10 * bu20 + au11 * bu21 + au12 * bu22
  64. let R20 = au20 * bu00 + au21 * bu01 + au22 * bu02
  65. let R21 = au20 * bu10 + au21 * bu11 + au22 * bu12
  66. let R22 = au20 * bu20 + au21 * bu21 + au22 * bu22
  67. let v0 = centerB.x - centerA.x,
  68. v1 = centerB.y - centerA.y,
  69. v2 = centerB.z - centerA.z
  70. let t0 = v0 * au00 + v1 * au01 + v2 * au02
  71. let t1 = v0 * au10 + v1 * au11 + v2 * au12
  72. let t2 = v0 * au20 + v1 * au21 + v2 * au22
  73. let ra, rb, abs
  74. let epsilon = Number.EPSILON
  75. let A00 = (R00 >= 0 ? R00 : -R00) + epsilon,
  76. A01 = (R01 >= 0 ? R01 : -R01) + epsilon,
  77. A02 = (R02 >= 0 ? R02 : -R02) + epsilon
  78. let A10 = (R10 >= 0 ? R10 : -R10) + epsilon,
  79. A11 = (R11 >= 0 ? R11 : -R11) + epsilon,
  80. A12 = (R12 >= 0 ? R12 : -R12) + epsilon
  81. let A20 = (R20 >= 0 ? R20 : -R20) + epsilon,
  82. A21 = (R21 >= 0 ? R21 : -R21) + epsilon,
  83. A22 = (R22 >= 0 ? R22 : -R22) + epsilon
  84. ra = ae0
  85. rb = be0 * A00 + be1 * A01 + be2 * A02
  86. if ((t0 >= 0 ? t0 : -t0) > ra + rb) return false
  87. ra = ae1
  88. rb = be0 * A10 + be1 * A11 + be2 * A12
  89. if ((t1 >= 0 ? t1 : -t1) > ra + rb) return false
  90. ra = ae2
  91. rb = be0 * A20 + be1 * A21 + be2 * A22
  92. if ((t2 >= 0 ? t2 : -t2) > ra + rb) return false
  93. rb = be0
  94. ra = ae0 * A00 + ae1 * A10 + ae2 * A20
  95. abs = t0 * R00 + t1 * R10 + t2 * R20
  96. if ((abs >= 0 ? abs : -abs) > ra + rb) return false
  97. rb = be1
  98. ra = ae0 * A01 + ae1 * A11 + ae2 * A21
  99. abs = t0 * R01 + t1 * R11 + t2 * R21
  100. if ((abs >= 0 ? abs : -abs) > ra + rb) return false
  101. rb = be2
  102. ra = ae0 * A02 + ae1 * A12 + ae2 * A22
  103. abs = t0 * R02 + t1 * R12 + t2 * R22
  104. if ((abs >= 0 ? abs : -abs) > ra + rb) return false
  105. // test axis L = A0 x B0
  106. ra = ae1 * A20 + ae2 * A10
  107. rb = be1 * A02 + be2 * A01
  108. abs = t2 * R10 - t1 * R20
  109. if ((abs >= 0 ? abs : -abs) > ra + rb) return false
  110. // test axis L = A0 x B1
  111. ra = ae1 * A21 + ae2 * A11
  112. rb = be0 * A02 + be2 * A00
  113. abs = t2 * R11 - t1 * R21
  114. if ((abs >= 0 ? abs : -abs) > ra + rb) return false
  115. // test axis L = A0 x B2
  116. ra = ae1 * A22 + ae2 * A12
  117. rb = be0 * A01 + be1 * A00
  118. abs = t2 * R12 - t1 * R22
  119. if ((abs >= 0 ? abs : -abs) > ra + rb) return false
  120. // test axis L = A1 x B0
  121. ra = ae0 * A20 + ae2 * A00
  122. rb = be1 * A12 + be2 * A11
  123. abs = t0 * R20 - t2 * R00
  124. if ((abs >= 0 ? abs : -abs) > ra + rb) return false
  125. // test axis L = A1 x B1
  126. ra = ae0 * A21 + ae2 * A01
  127. rb = be0 * A12 + be2 * A10
  128. abs = t0 * R21 - t2 * R01
  129. if ((abs >= 0 ? abs : -abs) > ra + rb) return false
  130. // test axis L = A1 x B2
  131. ra = ae0 * A22 + ae2 * A02
  132. rb = be0 * A11 + be1 * A10
  133. abs = t0 * R22 - t2 * R02
  134. if ((abs >= 0 ? abs : -abs) > ra + rb) return false
  135. // test axis L = A2 x B0
  136. ra = ae0 * A10 + ae1 * A00
  137. rb = be1 * A22 + be2 * A21
  138. abs = t1 * R00 - t0 * R10
  139. if ((abs >= 0 ? abs : -abs) > ra + rb) return false
  140. // test axis L = A2 x B1
  141. ra = ae0 * A11 + ae1 * A01
  142. rb = be0 * A22 + be2 * A20
  143. abs = t1 * R01 - t0 * R11
  144. if ((abs >= 0 ? abs : -abs) > ra + rb) return false
  145. // test axis L = A2 x B2
  146. ra = ae0 * A12 + ae1 * A02
  147. rb = be0 * A21 + be1 * A20
  148. abs = t1 * R02 - t0 * R12
  149. if ((abs >= 0 ? abs : -abs) > ra + rb) return false
  150. return true
  151. }