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

Wakeup a body if a force is applied to it #61

Merged
merged 1 commit into from
Dec 24, 2020
Merged
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
60 changes: 32 additions & 28 deletions examples/impulses.html
Original file line number Diff line number Diff line change
Expand Up @@ -30,83 +30,87 @@
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
demo.addScene('Top impulse', () => {
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
demo.addScene('Center force', () => {
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
demo.addScene('Top force', () => {
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()
Expand Down
37 changes: 36 additions & 1 deletion examples/sleep.html
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
})

// Wake up demo
demo.addScene('Wake up', () => {
demo.addScene('Wake up when hit', () => {
const world = setupWorld(demo)

// Create sphere
Expand Down Expand Up @@ -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) {
Expand Down
1 change: 1 addition & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -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).
Expand Down
69 changes: 40 additions & 29 deletions src/objects/Body.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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
}
Expand All @@ -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

Expand All @@ -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
}
Expand Down Expand Up @@ -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()

Expand Down