/** @format */ import {obbIntersect, sphereAABBDistance, sphereOBBDistance} from './AILib' import {cBody} from './Body' const Vec3 = cc.Vec3 export enum ShapeType { Box = 1, Sphere = 2, Capsule = 4, //AI TODO } export abstract class cShape { radius = 0 height = 0 type = ShapeType.Box size = {x: 0, y: 0, z: 0} // scale = { x: 1, y: 1, z: 1 }; center = {x: 0, y: 0, z: 0} // halfSize = { x: 0, y: 0, z: 0 }; aabb: Array = [0, 0, 0, 0, 0, 0] constructor(center: cc.Vec3, type: ShapeType) { this.type = type //this.isDirty = true; this.center.x = center.x this.center.y = center.y this.center.z = center.z } updateAABB(scale: cc.Vec3, world: cc.Mat3, isIdentity: boolean = true) { const size = this.size const center = this.center const sx = scale.x, sy = scale.y, sz = scale.z const cx = center.x, cy = center.y, cz = center.z let x = size.x * 0.5, y = size.y * 0.5, z = size.z * 0.5 const aabb = this.aabb if (!isIdentity) { const m = world.m const uX = m[0] * sx, uY = m[1] * sx, uZ = m[2] * sx const vX = m[3] * sy, vY = m[4] * sy, vZ = m[5] * sy const wX = m[6] * sz, wY = m[7] * sz, wZ = m[8] * sz const cX = uX * cx + vX * cy + wX * cz const cY = uY * cx + vY * cy + wY * cz const cZ = uZ * cx + vZ * cy + wZ * cz const absU = Math.abs(uX) * x + Math.abs(vX) * y + Math.abs(wX) * z const absV = Math.abs(uY) * x + Math.abs(vY) * y + Math.abs(wY) * z const absW = Math.abs(uZ) * x + Math.abs(vZ) * y + Math.abs(wZ) * z ;(aabb[0] = cX - absU), (aabb[1] = cY - absV), (aabb[2] = cZ - absW) ;(aabb[3] = cX + absU), (aabb[4] = cY + absV), (aabb[5] = cZ + absW) } else { x = Math.abs(x * sx) y = Math.abs(y * sy) z = Math.abs(z * sz) aabb[0] = cx * sx - x aabb[1] = cy * sy - y aabb[2] = cz * sz - z aabb[3] = cx * sx + x aabb[4] = cy * sy + y aabb[5] = cz * sz + z } return aabb } } export class cBox extends cShape { constructor(center: cc.Vec3, size: cc.Vec3) { super(center, ShapeType.Box) this.size.x = size.x this.size.y = size.y this.size.z = size.z } } export class cSphere extends cShape { constructor(center: cc.Vec3, radius: number) { super(center, ShapeType.Sphere) this.radius = radius this.size.x = radius * 2 this.size.y = radius * 2 this.size.z = radius * 2 } } //默认y轴竖向 export class cCapsule extends cShape { constructor(center: cc.Vec3, radius: number, height: number) { super(center, ShapeType.Capsule) this.radius = radius this.height = height this.size.x = radius * 2 this.size.y = height * 2 this.size.z = radius * 2 } } const center = new cc.Vec3() export const ShapeSupport: Array<(a: cBody, b: cBody) => boolean> = [] ShapeSupport[ShapeType.Box | ShapeType.Box] = function (a: cBody, b: cBody) { //a,b 没有旋转,已进行AABB处理 , 直接返回 true if (a.isIdentity && b.isIdentity) return true return obbIntersect(a.getCenter(), a.getHalfSize(), a.getRotMat3(), b.getCenter(), b.getHalfSize(), b.getRotMat3()) } ShapeSupport[ShapeType.Box | ShapeType.Sphere] = function (a: cBody, b: cBody) { //a没有旋转当AABB处理 if (a.isIdentity) { // 转换到 aabb 坐标系下 Vec3.subtract(center, b.getCenter(), a.getCenter()) return sphereAABBDistance(center, b.getRaidus(), a.getHalfSize()) } return sphereOBBDistance(b.getCenter(), b.getRaidus(), a.getCenter(), a.getRotation(), a.getHalfSize()) } ShapeSupport[ShapeType.Sphere | ShapeType.Sphere] = function (a: cBody, b: cBody) { let ca = a.getCenter() let cb = b.getCenter() Vec3.subtract(center, ca, cb) let lengthSqr = center.lengthSqr() let radii = a.getRaidus() + b.getRaidus() return lengthSqr <= radii * radii } ShapeSupport[ShapeType.Box | ShapeType.Capsule] = function (a: cBody, b: cBody) { //AI TODO return true } ShapeSupport[ShapeType.Sphere | ShapeType.Capsule] = function (a: cBody, b: cBody) { //AI TODO return true } ShapeSupport[ShapeType.Capsule | ShapeType.Capsule] = function (a: cBody, b: cBody) { //AI TODO return true }