Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(body): add isTrigger option #79

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions examples/js/Demo.js
Original file line number Diff line number Diff line change
Expand Up @@ -547,6 +547,7 @@ class Demo extends CANNON.EventTarget {
this.currentMaterial = this.solidMaterial
const contactDotMaterial = new THREE.MeshBasicMaterial({ color: 0xffffff })
this.particleMaterial = new THREE.MeshLambertMaterial({ color: 0xff0000 })
this.triggerMaterial = new THREE.MeshBasicMaterial({ color: 0x00ff00, wireframe: true })

const contactPointGeometry = new THREE.SphereGeometry(0.1, 6, 6)
this.contactMeshCache = new GeometryCache(this.scene, () => {
Expand Down Expand Up @@ -894,10 +895,9 @@ class Demo extends CANNON.EventTarget {
throw new Error('The argument passed to addVisual() is not a body')
}

// if it's a particle paint it red, otherwise just gray
const material = body.shapes.every((s) => s instanceof CANNON.Particle)
? this.particleMaterial
: this.currentMaterial
// if it's a particle paint it red, if it's a trigger paint it as green, otherwise just gray
const isParticule = body.shapes.every((s) => s instanceof CANNON.Particle)
const material = isParticule ? this.particleMaterial : body.isTrigger ? this.triggerMaterial : this.currentMaterial

// get the correspondant three.js mesh
const mesh = bodyToMesh(body, material)
Expand Down
68 changes: 68 additions & 0 deletions examples/trigger.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>cannon.js - trigger demo</title>
<link rel="stylesheet" href="css/style.css" type="text/css" />
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0" />
</head>
<body>
<script type="module">
import * as CANNON from '../dist/cannon-es.js'
import { Demo } from './js/Demo.js'

/**
* Demonstrates how to make use of trigger to allow others body to pass through them, yet still emit collision events
*/
const demo = new Demo()

demo.addScene('Trigger', () => {
const world = setupWorld(demo)

const boxShape = new CANNON.Box(new CANNON.Vec3(1, 1, 1))
const sphereShape = new CANNON.Sphere(1)

// Trigger body
const triggerBox = new CANNON.Body({ isTrigger: true })
triggerBox.addShape(boxShape)
triggerBox.position.set(-5, 0, 0)
world.addBody(triggerBox)
demo.addVisual(triggerBox)

// Sphere
const movingSphere = new CANNON.Body({ mass: 5 })
movingSphere.addShape(sphereShape)
movingSphere.position.set(5, 0, 0)
movingSphere.velocity.set(-5, 0, 0)
movingSphere.linearDamping = 0
world.addBody(movingSphere)
demo.addVisual(movingSphere)

// When a body collides with another body, they both dispatch the "collide" event.
triggerBox.addEventListener('collide', (event) => {
console.log('The box trigger was collided!', event)
})
movingSphere.addEventListener('collide', (event) => {
console.log('The sphere was collided!', event)
})

// When two bodies collide they also emit contact events
world.addEventListener('endContact', (event) => {
console.log('World end contact event', event)
})
world.addEventListener('beginContact', (event) => {
console.log('World begin contact event', event)
})
})

demo.start()

function setupWorld(demo) {
const world = demo.getWorld()
world.gravity.set(0, 0, 0) // no gravity

return world
}
</script>
</body>
</html>
1 change: 1 addition & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@
'spring',
'stacks',
'tear',
'trigger',
'trimesh',
'tween',
]
Expand Down
1 change: 1 addition & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ These minor changes and improvements were also made:
- Added a property `World.hasActiveBodies: boolean` which will be false when all physics bodies are sleeping. This allows for invalidating frames when physics aren't active for increased performance.
- Deprecated properties and methods have been removed.
- The [original cannon.js debugger](https://github.com/schteppe/cannon.js/blob/master/tools/threejs/CannonDebugRenderer.js), which shows the wireframes of each body, has been moved to its own repo [cannon-es-debugger](https://github.com/pmndrs/cannon-es-debugger).
- Added a property `Body.isTrigger : boolean` which, when true allows for the body to trigger collision events without interacting physically with the other colliding bodies.

If instead you're using three.js in a **React** environment with [react-three-fiber](https://github.com/pmndrs/react-three-fiber), check out [use-cannon](https://github.com/pmndrs/use-cannon)! It's a wrapper around cannon-es.

Expand Down
Binary file added screenshots/trigger.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
19 changes: 11 additions & 8 deletions src/objects/Body.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,18 @@ import type { Material } from '../material/Material'
import type { World } from '../world/World'

export const BODY_TYPES = {
DYNAMIC: 1 as const,
STATIC: 2 as const,
KINEMATIC: 4 as const,
}
DYNAMIC: 1,
STATIC: 2,
KINEMATIC: 4,
} as const

export type BodyType = typeof BODY_TYPES[keyof typeof BODY_TYPES]

export const BODY_SLEEP_STATES = {
AWAKE: 0 as const,
SLEEPY: 1 as const,
SLEEPING: 2 as const,
}
AWAKE: 0,
SLEEPY: 1,
SLEEPING: 2,
} as const

export type BodySleepState = typeof BODY_SLEEP_STATES[keyof typeof BODY_SLEEP_STATES]

Expand All @@ -44,6 +44,7 @@ export type BodyOptions = {
linearFactor?: Vec3
angularFactor?: Vec3
shape?: Shape
isTrigger?: boolean
}

/**
Expand Down Expand Up @@ -130,6 +131,7 @@ export class Body extends EventTarget {
aabbNeedsUpdate: boolean // Indicates if the AABB needs to be updated before use.
boundingRadius: number // Total bounding radius of the Body including its shapes, relative to body.position.
wlambda: Vec3
isTrigger: boolean // When true "collide" events are still triggered but bodies do not interact.

static idCounter: number
static COLLIDE_EVENT_NAME: 'collide'
Expand Down Expand Up @@ -246,6 +248,7 @@ export class Body extends EventTarget {
this.aabbNeedsUpdate = true
this.boundingRadius = 0
this.wlambda = new Vec3()
this.isTrigger = Boolean(options.isTrigger)

if (options.shape) {
this.addShape(options.shape)
Expand Down
2 changes: 1 addition & 1 deletion src/solver/Solver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export class Solver {
* @param {Equation} eq
*/
addEquation(eq: Equation): void {
if (eq.enabled) {
if (eq.enabled && !eq.bi.isTrigger && !eq.bj.isTrigger) {
this.equations.push(eq)
}
}
Expand Down