cannon-es-control
Version:
A lightweight 3D physics engine written in JavaScript with control system tools
225 lines (175 loc) • 5.89 kB
text/typescript
import type { Shape } from '../shapes/Shape'
import { Vec3 } from '../math/Vec3'
import { Box } from '../shapes/Box'
import { Sphere } from '../shapes/Sphere'
import { Body } from '../objects/Body'
import { World } from '../world/World'
import { ArrayCollisionMatrix } from '../collision/ArrayCollisionMatrix'
import { ObjectCollisionMatrix } from '../collision/ObjectCollisionMatrix'
import { RaycastResult } from '../collision/RaycastResult'
import { testCollisionMatrix } from '../../test/helpers'
describe('World', () => {
test('clearForces', () => {
const world = new World()
const body = new Body()
world.addBody(body)
body.force.set(1, 2, 3)
body.torque.set(4, 5, 6)
world.clearForces()
expect(body.force.almostEquals(new Vec3(0, 0, 0))).toBe(true)
expect(body.torque.almostEquals(new Vec3(0, 0, 0))).toBe(true)
})
test('rayTestBox', () => {
const world = new World()
const body = new Body()
body.addShape(new Box(new Vec3(1, 1, 1)))
world.addBody(body)
const from = new Vec3(-10, 0, 0)
const to = new Vec3(10, 0, 0)
const result = new RaycastResult()
world.rayTest(from, to, result)
expect(result.hasHit).toBe(true)
})
test('rayTestSphere', () => {
const world = new World()
const body = new Body()
body.addShape(new Sphere(1))
world.addBody(body)
const from = new Vec3(-10, 0, 0)
const to = new Vec3(10, 0, 0)
const result = new RaycastResult()
world.rayTest(from, to, result)
expect(result.hasHit).toBe(true)
})
test('raycastClosest: single', () => {
const world = new World()
const body = new Body({
shape: new Sphere(1),
})
world.addBody(body)
const from = new Vec3(-10, 0, 0)
const to = new Vec3(10, 0, 0)
const result = new RaycastResult()
world.raycastClosest(from, to, {}, result)
expect(result.hasHit).toBe(true)
expect(result.body).toEqual(body)
expect(result.shape).toBe(body.shapes[0])
})
test('raycastClosest: order', () => {
const world = new World()
const bodyA = new Body({ shape: new Sphere(1), position: new Vec3(-1, 0, 0) })
const bodyB = new Body({ shape: new Sphere(1), position: new Vec3(1, 0, 0) })
world.addBody(bodyA)
world.addBody(bodyB)
const from = new Vec3(-10, 0, 0)
const to = new Vec3(10, 0, 0)
let result = new RaycastResult()
world.raycastClosest(from, to, {}, result)
expect(result.hasHit).toBe(true)
expect(result.body).toBe(bodyA)
expect(result.shape).toBe(bodyA.shapes[0])
from.set(10, 0, 0)
to.set(-10, 0, 0)
result = new RaycastResult()
world.raycastClosest(from, to, {}, result)
expect(result.hasHit).toBe(true)
expect(result.body).toBe(bodyB)
expect(result.shape).toBe(bodyB.shapes[0])
})
test('raycastAll: simple', () => {
const world = new World()
const body = new Body({ shape: new Sphere(1) })
world.addBody(body)
const from = new Vec3(-10, 0, 0)
const to = new Vec3(10, 0, 0)
let numResults = 0
const returnVal = world.raycastAll(from, to, {}, function (result) {
expect(result.hasHit).toBe(true)
expect(result.body).toBe(body)
expect(result.shape).toBe(result.body?.shapes[0])
numResults++
})
expect(numResults).toBe(2)
expect(returnVal).toBe(true)
})
test('raycastAll: two spheres', () => {
const world = new World()
const body = new Body({ shape: new Sphere(1) })
world.addBody(body)
const body2 = new Body({ shape: new Sphere(1) })
world.addBody(body2)
const from = new Vec3(-10, 0, 0)
const to = new Vec3(10, 0, 0)
let hasHit = false
let numResults = 0
world.raycastAll(from, to, {}, function (result) {
hasHit = result.hasHit
numResults++
})
expect(hasHit).toBe(true)
expect(numResults).toBe(4)
})
test('raycastAll: skipBackfaces', () => {
const world = new World()
const body = new Body({ shape: new Sphere(1) })
world.addBody(body)
let numResults = 0
world.raycastAll(new Vec3(-10, 0, 0), new Vec3(10, 0, 0), { skipBackfaces: true }, function (result) {
expect(result.hasHit).toBe(true)
expect(result.body).toBe(body)
expect(result.shape).toBe(result.body?.shapes[0])
numResults++
})
expect(numResults).toBe(1)
})
test('raycastAll: collisionFilters', () => {
const world = new World()
const body = new Body({
shape: new Sphere(1),
})
world.addBody(body)
body.collisionFilterGroup = 2
body.collisionFilterMask = 2
let numResults = 0
world.raycastAll(
new Vec3(-10, 0, 0),
new Vec3(10, 0, 0),
{
collisionFilterGroup: 2,
collisionFilterMask: 2,
},
function () {
numResults++
}
)
expect(numResults).toBe(2)
numResults = 0
world.raycastAll(
new Vec3(-10, 0, 0),
new Vec3(10, 0, 0),
{
collisionFilterGroup: 1,
collisionFilterMask: 1,
},
function () {
numResults++
}
)
expect(numResults).toBe(0) // should use collision groups!
})
test('raycastAny', () => {
const world = new World()
world.addBody(new Body({ shape: new Sphere(1) }))
const from = new Vec3(-10, 0, 0)
const to = new Vec3(10, 0, 0)
const result = new RaycastResult()
world.raycastAny(from, to, {}, result)
expect(result.hasHit).toBe(true)
})
test('using ArrayCollisionMatrix', () => {
testCollisionMatrix(ArrayCollisionMatrix)
})
test('using ObjectCollisionMatrix', () => {
testCollisionMatrix(ObjectCollisionMatrix)
})
})