diff --git a/examples/impulses.html b/examples/impulses.html
index b53f6da13..4b8cc62a6 100644
--- a/examples/impulses.html
+++ b/examples/impulses.html
@@ -30,20 +30,15 @@
const world = setupWorld(demo)
const shape = new CANNON.Sphere(radius)
- const body = new CANNON.Body({
- mass,
- position: new CANNON.Vec3(0, 1, 0),
- })
+ const body = new CANNON.Body({ mass })
body.addShape(shape)
body.linearDamping = damping
body.angularDamping = damping
world.addBody(body)
demo.addVisual(body)
- // Add an impulse to the center
- const worldPoint = new CANNON.Vec3(0, 0, 0)
const impulse = new CANNON.Vec3(-strength * dt, 0, 0)
- body.applyImpulse(impulse, worldPoint)
+ body.applyImpulse(impulse)
})
// Add impulse to the top of the sphere
@@ -51,20 +46,17 @@
const world = setupWorld(demo)
const shape = new CANNON.Sphere(radius)
- const body = new CANNON.Body({
- mass,
- position: new CANNON.Vec3(0, 1, 0),
- })
+ const body = new CANNON.Body({ mass })
body.addShape(shape)
body.linearDamping = damping
body.angularDamping = damping
world.addBody(body)
demo.addVisual(body)
- // Add an impulse to the center
- const worldPoint = new CANNON.Vec3(0, radius, 0)
+ // The top of the sphere, relative to the sphere center
+ const topPoint = new CANNON.Vec3(0, radius / 2, 0)
const impulse = new CANNON.Vec3(-strength * dt, 0, 0)
- body.applyImpulse(impulse, worldPoint)
+ body.applyImpulse(impulse, topPoint)
})
// Add force to the body center
@@ -72,20 +64,15 @@
const world = setupWorld(demo)
const shape = new CANNON.Sphere(radius)
- const body = new CANNON.Body({
- mass,
- position: new CANNON.Vec3(0, 1, 0),
- })
+ const body = new CANNON.Body({ mass })
body.addShape(shape)
body.linearDamping = damping
body.angularDamping = damping
world.addBody(body)
demo.addVisual(body)
- // Add an force to the center
- const worldPoint = new CANNON.Vec3(0, 0, 0)
const force = new CANNON.Vec3(-strength, 0, 0)
- body.applyForce(force, worldPoint)
+ body.applyForce(force)
})
// Add force to the top of the sphere
@@ -93,20 +80,37 @@
const world = setupWorld(demo)
const shape = new CANNON.Sphere(radius)
- const body = new CANNON.Body({
- mass,
- position: new CANNON.Vec3(0, 1, 0),
- })
+ const body = new CANNON.Body({ mass })
body.addShape(shape)
body.linearDamping = damping
body.angularDamping = damping
world.addBody(body)
demo.addVisual(body)
- // Add an force to the center
- const worldPoint = new CANNON.Vec3(0, radius, 0)
+ // The top of the sphere, relative to the sphere center
+ const topPoint = new CANNON.Vec3(0, radius / 2, 0)
const force = new CANNON.Vec3(-strength, 0, 0)
- body.applyForce(force, worldPoint)
+ body.applyForce(force, topPoint)
+ })
+
+ // Apply a force in the local space
+ demo.addScene('Local force', () => {
+ const world = setupWorld(demo)
+
+ const shape = new CANNON.Sphere(radius)
+ const body = new CANNON.Body({ mass })
+ body.addShape(shape)
+ body.linearDamping = damping
+ body.angularDamping = damping
+ body.quaternion.setFromEuler(0, 0, Math.PI)
+ world.addBody(body)
+ demo.addVisual(body)
+
+ // it's the top point, but since the sphere is rotated
+ // by 180 degrees, it is the bottom point to the right
+ const topPoint = new CANNON.Vec3(0, radius / 2, 0)
+ const force = new CANNON.Vec3(-strength, 0, 0)
+ body.applyLocalForce(force, topPoint)
})
demo.start()
diff --git a/examples/sleep.html b/examples/sleep.html
index 96e09173d..944f39a60 100644
--- a/examples/sleep.html
+++ b/examples/sleep.html
@@ -49,7 +49,7 @@
})
// Wake up demo
- demo.addScene('Wake up', () => {
+ demo.addScene('Wake up when hit', () => {
const world = setupWorld(demo)
// Create sphere
@@ -89,6 +89,41 @@
})
})
+ // Wake up demo
+ demo.addScene('Wake up with impulse', () => {
+ const world = setupWorld(demo)
+
+ // Create sphere
+ const size = 2
+ const sphere = new CANNON.Sphere(size)
+ const sphereBody = new CANNON.Body({ mass: 1 })
+ sphereBody.addShape(sphere)
+ sphereBody.position.set(0, size, 0)
+ world.addBody(sphereBody)
+ demo.addVisual(sphereBody)
+
+ // Force it to sleep
+ sphereBody.sleep()
+
+ // Allow sleeping
+ world.allowSleep = true
+ sphereBody.allowSleep = true
+
+ // Sleep parameters
+ sphereBody.sleepSpeedLimit = 0.5
+ sphereBody.sleepTimeLimit = 1
+
+ // Apply an impulse after a bit
+ setTimeout(() => {
+ sphereBody.applyLocalImpulse(new CANNON.Vec3(5, 0, 0), new CANNON.Vec3())
+ }, 1000)
+
+ // The body wakes up when it gets a new contact
+ sphereBody.addEventListener('wakeup', (event) => {
+ console.log('The sphere woke up!')
+ })
+ })
+
demo.start()
function setupWorld(demo) {
diff --git a/readme.md b/readme.md
index 0a129d46b..0f52c8a03 100644
--- a/readme.md
+++ b/readme.md
@@ -11,6 +11,7 @@ These minor changes and improvements were also made:
- The `Cylinder` is now oriented on the Y axis. [#30](https://github.com/pmndrs/cannon-es/pull/30)
- The `type` property of the `Cylinder` is now equal to `Shape.types.CYLINDER`. [#59](https://github.com/pmndrs/cannon-es/pull/59)
- `Body.applyImpulse()` and `Body.applyForce()` are now relative to the center of the body instead of the center of the world [86b0444](https://github.com/schteppe/cannon.js/commit/86b0444c93356aeaa25dd1af795fa162574c6f4b)
+- Sleeping bodies now wake up if a force or an impulse is applied to them [#61](https://github.com/pmndrs/cannon-es/pull/61)
- 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).
diff --git a/src/objects/Body.ts b/src/objects/Body.ts
index 521e54011..5b1f1cd58 100644
--- a/src/objects/Body.ts
+++ b/src/objects/Body.ts
@@ -484,12 +484,23 @@ export class Body extends EventTarget {
}
}
- applyForce(force: Vec3, relativePoint: Vec3): void {
+ /**
+ * Apply force to a point of the body. This could for example be a point on the Body surface.
+ * Applying force this way will add to Body.force and Body.torque.
+ * @method applyForce
+ * @param {Vec3} force The amount of force to add.
+ * @param {Vec3} [relativePoint] A point relative to the center of mass to apply the force on.
+ */
+ applyForce(force: Vec3, relativePoint: Vec3 = new Vec3()): void {
+ // Needed?
if (this.type !== Body.DYNAMIC) {
- // Needed?
return
}
+ if (this.sleepState === Body.SLEEPING) {
+ this.wakeUp()
+ }
+
// Compute produced rotational force
const rotForce = Body_applyForce_rotForce
relativePoint.cross(force, rotForce)
@@ -501,7 +512,13 @@ export class Body extends EventTarget {
this.torque.vadd(rotForce, this.torque)
}
- applyLocalForce(localForce: Vec3, localPoint: Vec3): void {
+ /**
+ * Apply force to a local point in the body.
+ * @method applyLocalForce
+ * @param {Vec3} force The force vector to apply, defined locally in the body frame.
+ * @param {Vec3} [localPoint] A local point in the body to apply the force on.
+ */
+ applyLocalForce(localForce: Vec3, localPoint: Vec3 = new Vec3()): void {
if (this.type !== Body.DYNAMIC) {
return
}
@@ -516,11 +533,23 @@ export class Body extends EventTarget {
this.applyForce(worldForce, relativePointWorld)
}
- applyImpulse(impulse: Vec3, relativePoint: Vec3): void {
+ /**
+ * Apply impulse to a point of the body. This could for example be a point on the Body surface.
+ * An impulse is a force added to a body during a short period of time (impulse = force * time).
+ * Impulses will be added to Body.velocity and Body.angularVelocity.
+ * @method applyImpulse
+ * @param {Vec3} impulse The amount of impulse to add.
+ * @param {Vec3} relativePoint A point relative to the center of mass to apply the force on.
+ */
+ applyImpulse(impulse: Vec3, relativePoint: Vec3 = new Vec3()): void {
if (this.type !== Body.DYNAMIC) {
return
}
+ if (this.sleepState === Body.SLEEPING) {
+ this.wakeUp()
+ }
+
// Compute point position relative to the body center
const r = relativePoint
@@ -547,7 +576,13 @@ export class Body extends EventTarget {
this.angularVelocity.vadd(rotVelo, this.angularVelocity)
}
- applyLocalImpulse(localImpulse: Vec3, localPoint: Vec3): void {
+ /**
+ * Apply locally-defined impulse to a local point in the body.
+ * @method applyLocalImpulse
+ * @param {Vec3} force The force vector to apply, defined locally in the body frame.
+ * @param {Vec3} localPoint A local point in the body to apply the force on.
+ */
+ applyLocalImpulse(localImpulse: Vec3, localPoint: Vec3 = new Vec3()): void {
if (this.type !== Body.DYNAMIC) {
return
}
@@ -738,38 +773,14 @@ const uiw_m1 = new Mat3()
const uiw_m2 = new Mat3()
const uiw_m3 = new Mat3()
-/**
- * Apply force to a world point. This could for example be a point on the Body surface. Applying force this way will add to Body.force and Body.torque.
- * @method applyForce
- * @param {Vec3} force The amount of force to add.
- * @param {Vec3} relativePoint A point relative to the center of mass to apply the force on.
- */
const Body_applyForce_rotForce = new Vec3()
-/**
- * Apply force to a local point in the body.
- * @method applyLocalForce
- * @param {Vec3} force The force vector to apply, defined locally in the body frame.
- * @param {Vec3} localPoint A local point in the body to apply the force on.
- */
const Body_applyLocalForce_worldForce = new Vec3()
const Body_applyLocalForce_relativePointWorld = new Vec3()
-/**
- * Apply impulse to a world point. This could for example be a point on the Body surface. An impulse is a force added to a body during a short period of time (impulse = force * time). Impulses will be added to Body.velocity and Body.angularVelocity.
- * @method applyImpulse
- * @param {Vec3} impulse The amount of impulse to add.
- * @param {Vec3} relativePoint A point relative to the center of mass to apply the force on.
- */
const Body_applyImpulse_velo = new Vec3()
const Body_applyImpulse_rotVelo = new Vec3()
-/**
- * Apply locally-defined impulse to a local point in the body.
- * @method applyLocalImpulse
- * @param {Vec3} force The force vector to apply, defined locally in the body frame.
- * @param {Vec3} localPoint A local point in the body to apply the force on.
- */
const Body_applyLocalImpulse_worldImpulse = new Vec3()
const Body_applyLocalImpulse_relativePoint = new Vec3()