cannon-es-control
Version:
A lightweight 3D physics engine written in JavaScript with control system tools
247 lines (210 loc) • 6.39 kB
text/typescript
import { AABB } from './AABB'
import { Ray } from './Ray'
import { Vec3 } from '../math/Vec3'
import { Quaternion } from '../math/Quaternion'
import { Transform } from '../math/Transform'
describe('AABB', () => {
test('construct', () => {
const a = new AABB()
expect(a).toBeDefined()
})
test('setFromPoints', () => {
const a = new AABB()
const points = [
new Vec3(7, 0, 1),
new Vec3(2, -1, 5),
new Vec3(-1, -7, 0),
new Vec3(4, 5, -9),
new Vec3(-5, 8, 2),
new Vec3(-3, -2, -1),
new Vec3(5, 3, 6),
]
expect(a.setFromPoints(points)).toBe(a)
expect(a).toMatchObject(
new AABB({
lowerBound: new Vec3(-5, -7, -9),
upperBound: new Vec3(7, 8, 6),
})
)
const position = new Vec3(1, 2, 3)
a.setFromPoints(points, position)
expect(a).toMatchObject(
new AABB({
lowerBound: new Vec3(-4, -5, -6),
upperBound: new Vec3(8, 10, 9),
})
)
const quaternion = new Quaternion().setFromAxisAngle(new Vec3(1, 0, 0), Math.PI)
a.setFromPoints(points, position, quaternion)
expect(a).toMatchObject(
new AABB({
lowerBound: new Vec3(-4, -6, -3),
upperBound: new Vec3(8, 9, 12),
})
)
const skinSize = 1
a.setFromPoints(points, position, quaternion, skinSize)
expect(a).toMatchObject(
new AABB({
lowerBound: new Vec3(-5, -7, -4),
upperBound: new Vec3(9, 10, 13),
})
)
})
test('copy', () => {
const a = new AABB()
const b = new AABB()
a.upperBound.set(1, 2, 3)
a.lowerBound.set(4, 5, 6)
expect(b.copy(a)).toBe(b)
expect(b).toMatchObject(a)
expect(b).not.toBe(a)
})
test('clone', () => {
const a = new AABB({
lowerBound: new Vec3(-1, -2, -3),
upperBound: new Vec3(1, 2, 3),
})
const b = a.clone()
expect(a).not.toBe(b)
expect(b).toMatchObject(a)
})
test('extend', () => {
const a = new AABB({
lowerBound: new Vec3(-1, -1, -1),
upperBound: new Vec3(1, 1, 1),
})
const b = new AABB({
lowerBound: new Vec3(-2, -2, -2),
upperBound: new Vec3(2, 2, 2),
})
a.extend(b)
expect(a).toMatchObject(b)
const c = new AABB({
lowerBound: new Vec3(-1, -1, -1),
upperBound: new Vec3(1, 1, 1),
})
const d = new AABB({
lowerBound: new Vec3(-2, -2, -2),
upperBound: new Vec3(2, 2, 2),
})
d.extend(c)
expect(d.lowerBound).toMatchObject(new Vec3(-2, -2, -2))
expect(d.upperBound).toMatchObject(new Vec3(2, 2, 2))
const e = new AABB({
lowerBound: new Vec3(-2, -1, -1),
upperBound: new Vec3(2, 1, 1),
})
const f = new AABB({
lowerBound: new Vec3(-1, -1, -1),
upperBound: new Vec3(1, 1, 1),
})
f.extend(e)
expect(e.lowerBound).toMatchObject(new Vec3(-2, -1, -1))
expect(e.upperBound).toMatchObject(new Vec3(2, 1, 1))
const g = new AABB({
lowerBound: new Vec3(-5, -3, -2),
upperBound: new Vec3(-3, -1, -1),
})
const h = new AABB({
lowerBound: new Vec3(-2, -5, -1.5),
upperBound: new Vec3(2, -2, 5),
})
g.extend(h)
expect(g.lowerBound).toMatchObject(new Vec3(-5, -5, -2))
expect(g.upperBound).toMatchObject(new Vec3(2, -1, 5))
})
test('overlaps', () => {
const a = new AABB()
const b = new AABB()
//Same aabb
a.lowerBound.set(-1, -1, 0)
a.upperBound.set(1, 1, 0)
b.lowerBound.set(-1, -1, 0)
b.upperBound.set(1, 1, 0)
expect(a.overlaps(b)).toBe(true)
//Corner overlaps
b.lowerBound.set(1, 1, 0)
b.upperBound.set(2, 2, 0)
expect(a.overlaps(b)).toBe(true)
//Separate
b.lowerBound.set(1.1, 1.1, 0)
expect(a.overlaps(b)).toBe(false)
//fully inside
b.lowerBound.set(-0.5, -0.5, 0)
b.upperBound.set(0.5, 0.5, 0)
expect(a.overlaps(b)).toBe(true)
b.lowerBound.set(-1.5, -1.5, 0)
b.upperBound.set(1.5, 1.5, 0)
expect(a.overlaps(b)).toBe(true)
//Translated
b.lowerBound.set(-3, -0.5, 0)
b.upperBound.set(-2, 0.5, 0)
expect(a.overlaps(b)).toBe(false)
})
test('volume', () => {
const a = new AABB({
lowerBound: new Vec3(-1, -2, -3),
upperBound: new Vec3(1, 2, 3),
})
expect(a.volume()).toBe(2 * 4 * 6)
})
test('contains', () => {
const a = new AABB()
const b = new AABB()
a.lowerBound.set(-1, -1, -1)
a.upperBound.set(1, 1, 1)
b.lowerBound.set(-1, -1, -1)
b.upperBound.set(1, 1, 1)
expect(a.contains(b)).toBe(true)
a.lowerBound.set(-2, -2, -2)
a.upperBound.set(2, 2, 2)
expect(a.contains(b)).toBe(true)
b.lowerBound.set(-3, -3, -3)
b.upperBound.set(3, 3, 3)
expect(a.contains(b)).toBe(false)
a.lowerBound.set(0, 0, 0)
a.upperBound.set(2, 2, 2)
b.lowerBound.set(-1, -1, -1)
b.upperBound.set(1, 1, 1)
expect(a.contains(b)).toBe(false)
})
test('toLocalFrame', () => {
const worldAABB = new AABB()
const localAABB = new AABB()
const frame = new Transform()
worldAABB.lowerBound.set(-1, -1, -1)
worldAABB.upperBound.set(1, 1, 1)
//No transform - should stay the same
worldAABB.toLocalFrame(frame, localAABB)
expect(localAABB).toMatchObject(worldAABB)
//Some translation
frame.position.set(-1, 0, 0)
worldAABB.toLocalFrame(frame, localAABB)
expect(localAABB).toMatchObject(
new AABB({
lowerBound: new Vec3(0, -1, -1),
upperBound: new Vec3(2, 1, 1),
})
)
})
test('toWorldFrame', () => {
const localAABB = new AABB()
const worldAABB = new AABB()
const frame = new Transform()
localAABB.lowerBound.set(-1, -1, -1)
localAABB.upperBound.set(1, 1, 1)
//No transform - should stay the same
localAABB.toLocalFrame(frame, worldAABB)
expect(localAABB).toMatchObject(worldAABB)
//Some translation on the frame
frame.position.set(1, 0, 0)
localAABB.toWorldFrame(frame, worldAABB)
expect(worldAABB).toMatchObject(
new AABB({
lowerBound: new Vec3(0, -1, -1),
upperBound: new Vec3(2, 1, 1),
})
)
})
})