Shape.ts 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. /** @format */
  2. import {obbIntersect, sphereAABBDistance, sphereOBBDistance} from './AILib'
  3. import {cBody} from './Body'
  4. const Vec3 = cc.Vec3
  5. export enum ShapeType {
  6. Box = 1,
  7. Sphere = 2,
  8. Capsule = 4, //AI TODO
  9. }
  10. export abstract class cShape {
  11. radius = 0
  12. height = 0
  13. type = ShapeType.Box
  14. size = {x: 0, y: 0, z: 0}
  15. // scale = { x: 1, y: 1, z: 1 };
  16. center = {x: 0, y: 0, z: 0}
  17. // halfSize = { x: 0, y: 0, z: 0 };
  18. aabb: Array<number> = [0, 0, 0, 0, 0, 0]
  19. constructor(center: cc.Vec3, type: ShapeType) {
  20. this.type = type
  21. //this.isDirty = true;
  22. this.center.x = center.x
  23. this.center.y = center.y
  24. this.center.z = center.z
  25. }
  26. updateAABB(scale: cc.Vec3, world: cc.Mat3, isIdentity: boolean = true) {
  27. const size = this.size
  28. const center = this.center
  29. const sx = scale.x,
  30. sy = scale.y,
  31. sz = scale.z
  32. const cx = center.x,
  33. cy = center.y,
  34. cz = center.z
  35. let x = size.x * 0.5,
  36. y = size.y * 0.5,
  37. z = size.z * 0.5
  38. const aabb = this.aabb
  39. if (!isIdentity) {
  40. const m = world.m
  41. const uX = m[0] * sx,
  42. uY = m[1] * sx,
  43. uZ = m[2] * sx
  44. const vX = m[3] * sy,
  45. vY = m[4] * sy,
  46. vZ = m[5] * sy
  47. const wX = m[6] * sz,
  48. wY = m[7] * sz,
  49. wZ = m[8] * sz
  50. const cX = uX * cx + vX * cy + wX * cz
  51. const cY = uY * cx + vY * cy + wY * cz
  52. const cZ = uZ * cx + vZ * cy + wZ * cz
  53. const absU = Math.abs(uX) * x + Math.abs(vX) * y + Math.abs(wX) * z
  54. const absV = Math.abs(uY) * x + Math.abs(vY) * y + Math.abs(wY) * z
  55. const absW = Math.abs(uZ) * x + Math.abs(vZ) * y + Math.abs(wZ) * z
  56. ;(aabb[0] = cX - absU), (aabb[1] = cY - absV), (aabb[2] = cZ - absW)
  57. ;(aabb[3] = cX + absU), (aabb[4] = cY + absV), (aabb[5] = cZ + absW)
  58. } else {
  59. x = Math.abs(x * sx)
  60. y = Math.abs(y * sy)
  61. z = Math.abs(z * sz)
  62. aabb[0] = cx * sx - x
  63. aabb[1] = cy * sy - y
  64. aabb[2] = cz * sz - z
  65. aabb[3] = cx * sx + x
  66. aabb[4] = cy * sy + y
  67. aabb[5] = cz * sz + z
  68. }
  69. return aabb
  70. }
  71. }
  72. export class cBox extends cShape {
  73. constructor(center: cc.Vec3, size: cc.Vec3) {
  74. super(center, ShapeType.Box)
  75. this.size.x = size.x
  76. this.size.y = size.y
  77. this.size.z = size.z
  78. }
  79. }
  80. export class cSphere extends cShape {
  81. constructor(center: cc.Vec3, radius: number) {
  82. super(center, ShapeType.Sphere)
  83. this.radius = radius
  84. this.size.x = radius * 2
  85. this.size.y = radius * 2
  86. this.size.z = radius * 2
  87. }
  88. }
  89. //默认y轴竖向
  90. export class cCapsule extends cShape {
  91. constructor(center: cc.Vec3, radius: number, height: number) {
  92. super(center, ShapeType.Capsule)
  93. this.radius = radius
  94. this.height = height
  95. this.size.x = radius * 2
  96. this.size.y = height * 2
  97. this.size.z = radius * 2
  98. }
  99. }
  100. const center = new cc.Vec3()
  101. export const ShapeSupport: Array<(a: cBody, b: cBody) => boolean> = []
  102. ShapeSupport[ShapeType.Box | ShapeType.Box] = function (a: cBody, b: cBody) {
  103. //a,b 没有旋转,已进行AABB处理 , 直接返回 true
  104. if (a.isIdentity && b.isIdentity) return true
  105. return obbIntersect(a.getCenter(), a.getHalfSize(), a.getRotMat3(), b.getCenter(), b.getHalfSize(), b.getRotMat3())
  106. }
  107. ShapeSupport[ShapeType.Box | ShapeType.Sphere] = function (a: cBody, b: cBody) {
  108. //a没有旋转当AABB处理
  109. if (a.isIdentity) {
  110. // 转换到 aabb 坐标系下
  111. Vec3.subtract(center, b.getCenter(), a.getCenter())
  112. return sphereAABBDistance(center, b.getRaidus(), a.getHalfSize())
  113. }
  114. return sphereOBBDistance(b.getCenter(), b.getRaidus(), a.getCenter(), a.getRotation(), a.getHalfSize())
  115. }
  116. ShapeSupport[ShapeType.Sphere | ShapeType.Sphere] = function (a: cBody, b: cBody) {
  117. let ca = a.getCenter()
  118. let cb = b.getCenter()
  119. Vec3.subtract(center, ca, cb)
  120. let lengthSqr = center.lengthSqr()
  121. let radii = a.getRaidus() + b.getRaidus()
  122. return lengthSqr <= radii * radii
  123. }
  124. ShapeSupport[ShapeType.Box | ShapeType.Capsule] = function (a: cBody, b: cBody) {
  125. //AI TODO
  126. return true
  127. }
  128. ShapeSupport[ShapeType.Sphere | ShapeType.Capsule] = function (a: cBody, b: cBody) {
  129. //AI TODO
  130. return true
  131. }
  132. ShapeSupport[ShapeType.Capsule | ShapeType.Capsule] = function (a: cBody, b: cBody) {
  133. //AI TODO
  134. return true
  135. }