Documentation

Getting Started

The project enable3d offers 4 different ways. As a Standalone 3D Framework, a Physics Plugin for three.js, as a 3D Objects and Physics extension for Phaser or as a library to run Ammo.js on Node.js

In this guide, you will learn how to use the Standalone 3D Framework. Most of what you learn, will be applicable to all packages. Just take a look at the examples to see what Enable3d can do and how to use the different packages.

Note: Not everything is documented yet, the examples page helps a lot!

Basic Setup

// import the UMD bundle enable3d.framework.min.js
// or from npm enable3d
import { Project, Scene3D, PhysicsLoader } from 'enable3d'

class MainScene extends Scene3D {
  constructor() {
    super('MainScene')
  }

  async init() {
    this.renderer.setPixelRatio(1)
    this.renderer.setSize(window.innerWidth, window.innerHeight)
  }

  async preload() {
    // preload your assets here
  }

  async create() {
    // set up scene (light, ground, grid, sky, orbitControls)
    this.warpSpeed()

    // enable physics debug
    this.physics.debug.enable()

    // position camera
    this.camera.position.set(10, 10, 20)

    // blue box (without physics)
    this.add.box({ y: 2 }, { lambert: { color: 'deepskyblue' } })

    // pink box (with physics)
    this.physics.add.box({ y: 10 }, { lambert: { color: 'hotpink' } })
  }

  update() {
    this.box.rotation.x += 0.01
    this.box.rotation.y += 0.01
  }
}

// set your project configs
const config = { scenes: [MainScene] }

// load the ammo.js file from the /lib folder and start the project
PhysicsLoader('/lib', () => new Project(config))

Native Three.js Objects

You can use native Three.js objects if you include THREE

import { THREE } from 'enable3d'

// green sphere
const geometry = new THREE.SphereGeometry(0.8, 16, 16)
const material = new THREE.MeshLambertMaterial({ color: 0x00ff00 })
const cube = new THREE.Mesh(geometry, material)
cube.position.set(0.2, 3, 0)
this.scene.add(cube)
// add physics to an existing object
this.physics.add.existing(cube)

Extended Three.js Objects

To have more functionalities and a better compatibility, use new ExtendedMesh() and new ExtendedObject3D() instead of new THREE.Mesh() and new THREE.Object3D()

import { THREE, ExtendedMesh, ExtendedObject3D } from 'enable3d'

const cube = new THREE.Mesh(geometry, material)
// instead of
const cube = new ExtendedMesh(geometry, material)

const object = new ExtendedObject3D()
// instead of
const object = new THREE.Object3D()

Warp Speed

Not documented yet.

Factory

Enable3d provides a simple factory for creating physical objects.

// will add a 5x3x1 red box
const box = physics.add.box(
  { x: 1, y: 2, z: 10, width: 5, height: 3, depth: 1, mass: 2, collisionFlags: 0 },
  { lambert: { color: 'red', transparent: true, opacity: 0.5 } }
)

If you want to use the factory without adding physics to the object, extract the factory from physics.

// get the objects factory
const { factory } = physics

// add the same box as above, but without physics
const box = factory.add.box({ x: 1, y: 2, z: 10, width: 5, height: 3, depth: 1 }, { lambert: { color: 'red', transparent: true, opacity: 0.5 } })

// you can later add physics to it
physics.add.existing(box, { mass: 2, collisionFlags: 0 })

You can also add custom materials like so:

physics.add.box({}, { custom: THREE.MeshLambertMaterial({ color: 0x2194ce }) })

Basic Shapes

Enable3d supports these shapes:

  • Plane
  • Box
  • Sphere
  • Cylinder
  • Cone
  • Capsule
  • Compound
  • Hull
  • HACD (Hierarchical Approximate Convex Decomposition)
  • ConvexMesh
  • ConcaveMesh
  • Heightfield (not yet)

Enable3d does automatically recognize the shape of simple three.js object when adding it via physics.add.existing(object). But you can also change the shape like so physics.add.existing(object, { shape: 'hacd' })

Take a look at the compare-physics-body-shapes and the play-with-physics-bodies examples to see creating & adding shapes in action.

Compound shapes

There are 3 ways to use compound shapes. Automatically generated (child or group) and manually generated. The automatically generated follow three.js objects structure. To manually generate a compound shape, simply add multiple shapes to the second parameter of physics.add.existing()

Automatically

// example: https://enable3d.io/examples/play-with-physics-bodies.html

// compound shape (child based)
// (the center of mass is the center of the box)
let box1 = this.add.box({ x: 0, y: 2 })
let sphere3 = this.add.sphere({ radius: 0.5, x: 0.25, y: 0.5 }) // relative position to box1
box1.add(sphere3)
this.physics.add.existing(box1)

// compound shape (group based)
// (the center of mass is 0,0,0)
let group = new THREE.Group()
const body = this.add.box({ height: 0.8, y: 1, width: 0.4, depth: 0.4 }, { lambert: { color: 0xffff00 } })
const head = this.add.sphere({ radius: 0.25, y: 1.7, z: 0.05 }, { lambert: { color: 0xffff00 } })
group.add(body, head)
group.position.setX(3)
this.add.existing(group)
this.physics.add.existing(group)

Manually

// example: https://enable3d.io/examples/play-with-physics-bodies.html

// custom compound shape
const box = this.add.box({ x: 9 })
const compound = [
  { shape: 'box', width: 0.5, height: 1, depth: 0.4, y: -0.5, z: 0.5 },
  { shape: 'box', width: 2.4, height: 0.6, depth: 0.4, z: -0.4, y: 0.2 },
  { shape: 'sphere', radius: 0.65, z: -0.25, y: 0.35 },
  { shape: 'box', width: 1.5, height: 0.8, depth: 1, y: 0.2, z: 0.2 }
]
this.physics.add.existing(box, { compound })

Physics Body

Body Types

There are 4 different body types you can choose from by setting object.body.setCollisionFlags(number) accordingly.

  • 0 - Dynamic
  • 1 - Static
  • 2 - Kinematic
  • 4 - Ghost (aka Sensor or NO_CONTACT_RESPONSE).

Dynamic

The dynamic bodies react to force and gravity and you can apply velocity and torque to them.

// example: https://enable3d.io/examples/first-phaser-game-3d-version.html

jump() {
  dynamicObject.body.applyForceY(16)
}

Static

These object are just there but do not move at all.

Kinematic

These bodies do NOT react to force or gravity. You can only move them by adjusting its position or rotation.

// example: https://enable3d.io/examples/kinematic-body-orbiting-around-sun.html

update() {
  kinematicObject.position.set(0,5,0)
  kinematicObject.rotation.x =+ 0.01
  // set needUpdate to true, every time you want
  // to adjust the position or rotation of a kinematic body
  kinematicObject.body.needUpdate = true
}

Ghost

These bodies do never interact with other bodies. But they fire collision events. Use them as sensory in your game. Ghost can be dynamic (4), static (5) or kinematic (6), by settings the collisionFlags accordingly.

Body Methods

You can use a lot of method on the body (object.body.something()). It does not make send listing them all here.

Just take a look the the physicsBody.ts source code.

Physics Configuration

When we add Enable3d to the scene, there are a few choices we can make.

new Project({ gravity: { x: 0, y: -9.81, z: 0 }, maxSubSteps: 4, fixedTimeStep: 1 / 60 })
  • gravity default { x: 0, y: -9.81, z: 0 } Sets the amount and direction of gravitational forces

  • maxSubSteps default 2 Set the max sub steps allowed.

  • fixedTimeStep default 1 / 60 This number determines how much time one simulation step is to simulate. The smaller the number, the more accurate (and slower) the simulation.

You must always satisfy the equation timeStep(fps) < maxSubSteps * fixedTimeStep

Position, Rotation and Scale

Position

You can only set the position (and rotation) at any moment if it the body is of type kinematic. See Body Types. For all other types, you have to set the position and the rotation before you add a physics body to it.

Example of a non kinematic box:

const { factory } = physics

// add a box without physics
const box = factory.add.box()
// set position and rotation
box.position.set(10, 10, 0)
box.rotation.set(0, Math.PI / 2, 0)
// add physics to the box
physics.add.existing(box)

But if you really need to set a new position or rotation to any other type than kinematic, see the Teleport Example.

Rotation

Same as Position.

Scale

You can't scale a physics body after added to the world. But you can scale your object before adding physics to it or remove the physics body and add a new one.

Example of a Torus:

const { factory } = physics

// add torus (without physics)
let torus = factory.add.torus()
// scale the torus
torus.scale.set(2, 2, 2)
// add a rigid body to it
physics.add.existing(torus, { shape: 'hacd' })

// add torus (with physics)
let torus = physics.add.torus()
// remove the rigid body
physics.destroy(torus.body)
// scale the torus
torus.scale.set(2, 2, 2)
// add a new rigid body to it
physics.add.existing(torus, { shape: 'hacd' })

Collisions

You can check all collisions on a single body or check for collision between 2 specific bodies. The event will be start, colliding or end.

// all collision for blueBox
blueBox.body.on.collision((otherObject, event) => {
  if (otherObject.name !== 'ground') {
    console.log('blueBox collided with another object than the ground')
  }
})
// collision between blueBox and redBox
physics.add.collider(blueBox, redBox, event => {
  console.log(`blueBox and redBox: ${event}`)
})

See the collisions example for details on implementing and using this event.

Motion Clamping

When an object has a high velocity, collisions can be missed if it moves through and past other objects between simulation steps. To fix this, enable CCD motion clamping. For a cube of size 1 try:

// Enable CCD if the object moves more than 1 meter in one simulation frame
object.body.setCcdMotionThreshold(1)

// Set the radius of the embedded sphere such that it is smaller than the object
object.body.setCcdSweptSphereRadius(0.2)

Constraints

The following constraints are available, but I have not yet written the documentation.

  • Lock
  • Fixed
  • Spring
  • Slider
  • Hinge
  • Cone Twist
  • Point To Point

You will find an example of all constraints here.

Lights

Not documented yet.

Loaders

Not documented yet.

Tweens

Want to use Tweens? Checkout https://github.com/tweenjs/tween.js

Controls

Not documented yet.

JoyStick

FirstPersonControls

ThirdPersonControls

PointerDrag

PointerLock

Raycasting

Not documented yet.

Objects Raycasting

Physics Raycasting

WebXR

Not documented yet.

Virtual Reality

Augmented Reality

Misc

Not documented yet.

Water