@vladkrutenyuk/cannon-es-debugger-pro
TypeScript icon, indicating that this package has built-in type declarations

0.2.4 • Public • Published

@vladkrutenyuk/cannon-es-debugger-pro

This is improved pro debugger for cannon-es with three to visualize all bodies and its shapes of physics world.

It was based on cannon-es-debugger. I wasn't completely satisfied with it so I decided to create a new fixed and improved version based on it.

Demo screenshot of @vladkrutenyuk/cannon-es-debugger-pro and comparing with @cannon-es-debugger

  • New pretty and clean appearance to make scene more readable.

    • Reworked debug graphics objects and its geoemtries.
    • New offset parameter to prevent overlapping instead of scale.
  • True memory management

    • Prevent memory leaking and disposing custom geometries created for complex shapes.
    • Ability to destroy debugger instance if its no longer used.
    • New methods - clean and destroy.
  • Better types and implementation

    • Class instead of function
    • Events instead of callback args.
    • Parameters changing after initialization - setColor, setOffset, setVisible.

Read section "Why use this instead of existed old one?" below after 'Usage' section.

Installation 🤓

pnpm add @vladkrutenyuk/cannon-es-debugger-pro
# or via 'npm i ...', 'yarn add ...' and so on

⚠️ Make sure you also have three and cannon-es as dependencies.

pnpm add three cannon-es
# or via 'npm i ...', 'yarn add ...' and so on

Usage 🧐

Initialization

import * as THREE from 'three'
import * as CANNON from 'cannon-es'
import { CannonEsDebuggerPro } from '@vladkrutenyuk/cannon-es-debugger-pro'

const world = new CANNON.World()
const scene = new THREE.Scene()
const root = new THREE.Group() // or any another THREE.Object3D like
scene.add(root)

// optional, default is 0x00ff00
const color = 0xe60c0c // or 'rgb(228, 14, 88)', '#e60c0c', 'red'
// optional, defailt is 0.005
const offset = 0.009

const cannonDebugger = new CannonEsDebuggerPro(root, world, color, offset)

Update

The update() method needs to be called after cannon physics world's step and before three.js render to update its state.

const animate = () => {
  requestAnimationFrame(animate)

  world.step(timeStep) // Update cannon-es physics
  cannonDebugger.update() // Update the CannonEsDebuggerPro
  renderer.render(scene, camera) // Render the three.js scene
}
animate()

Why use this instead of existed old one? What improvements? 🤩😍

"...existed old one" means cannon-es-debugger package.

1. Pretty and clean appearance

Make scene where a lot of objects and bodies readable and clean again.
See comparison image in the top of the page.

Reworked debug graphics objects and its geoemtreis

  • Sphere
    Custom shematic visualization of sphere shape instead of mesh with default icosahedron geometry.
    Geometry is built for THREE.LineSegments way.
    Thus, now it's combination of 3 perpendicular to each other edge-circles for each dimension. Looks like sphere colliders in Unity.

  • Box
    Only quad faces without diagonales of trianguilation (grid-like style).
    Geometry is built for THREE.LineSegments way.

  • ConvexPolyhedron
    This shape debug graphic geometry is built for THREE.LineSegments way. Thus, ConvexPolyhedron is displayed as it is, even if its faces contain more then 3 verticies (polygonal), for example Cylinder shape.

  • Plane
    Only quad faces without diagonales of trianguilation (grid-like style).
    Geometry is built for THREE.LineSegments way.
    Also it has bigger size (100x100 instead of 10x10) because physical plane is infinite.

  • Heightfield
    Only quad faces without diagonales of trianguilation (grid-like style).
    Geometry is built for THREE.LineSegments way.

Geometry offset

There is new parameter offset instead of old scale.
It's float value in meters to push up geometries vertices along its normals of debug graphics objects to prevent overlapping with source scene objects.

Recommended range of hundredths ~0.01 or thousandths ~0.001. Default is 0.005.

The method setOffset() is used to change it.

2. Solved memory issues

Original cannon-es-debugger doesn't clear scene from created meshes and doesn't dispose created geometry for complex shape after its removing.

This version does disposing for complex geometry when its body shape removed. Also it happens on new clear(), destroy() methods (read below in the next point).

3. Destroying, disposing and clearing

The method destroy() is called to remove all created debug 3d objects and dispose all created geometries for complex shapes and shared materials of this instance.

After calling destroy() the method update() won't work anymore and property (read-only) isDestroyed will become true.

cannonDebugger.update() // update happened

cannonDebugger.isDestroyed // > false
cannonDebugger.destroy() // remove all debug 3d objects and dispose its geometries, materials
cannonDebugger.isDestroyed // > true

cannonDebugger.update() // and now it does nothing

If you need just clear scene from debugs but you still need this cannon debugger instance then you are able to use clear() method. It does the same but shared materials won't be disposed and the update() method will be still working.

But oftenly, it's necessary to hide and show back debugs. In this case the better way is to use the setVisible() method. It doesn't remove and dispose anything.

// hide
cannonDebugger.setVisible(false)

// show back
cannonDebugger.setVisible(true)

4. Events

CannonEsDebuggerPro class extends THREE.EventDispatcher and uses it to dispatch update, init events. Old version's callbacks (onInit, onUpdate) are not longer used anymore.

Comparing:

🔞 in cannon-es-debugger

cannonDebugger = new CannonDebugger(scene, world, {
    onInit: (body, obj3d, shape) => {
        console.log('inited')
    },
    onUpdate: (body, obj3d, shape) => {
        console.log('updated')
    }   
})

😎👍 now in @vladkrutenyuk/cannon-es-debugger-pro

cannonDebugger = new CannonEsDebuggerPro(root, world)

cannonDebugger.addEventListener('init', (event) => {
    const { body, obj3d, shape } = event
    console.log(`inited obj-${obj3d.id} body-${body.id} shape-${shape.id}`)
})

cannonDebugger.addEventListener('update', (event) => {
    const { body, obj3d, shape } = event
    console.log(`updated obj-${obj3d.id} body-${body.id} shape-${shape.id}`)
})

5. Typing and implementation

Changes:

  • This version is implemented via class and instance just has its type CannonEsDebuggerPro instead of old implemention via function where instance can be typed only as ReturnType<...>.

  • THREE.Object3D root instead of THREE.Scene scene argument.

Comparing:

🔞 in cannon-es-debugger

// implementation
function CannonDebugger(scene: THREE.Scene, ...) { ... }

// thus, we need this to create typed variable:
cannonDebugger: ReturnType<typeof CannonDebugger>

this.cannonDebugger = new CannonDebugger(...)

// also, it provides only THREE.Scene as root:
const root = new THREE.Group()
new CannonDebugger(root, ...) //! TypeError

😎👍 now in @vladkrutenyuk/cannon-es-debugger-pro

// implementation
class CannonEsDebuggerPro { 
    constructor(root: THREE.Object3D, ...) { ... }
    ...
}

// thus
class AnyYourClass {
    cannonDebuggerPro: CannonEsDebuggerPro

    constructor() {
        // able to use any THREE.Object3D
        const root = new THREE.Group()
        this.cannonDebuggerPro = new CannonEsDebuggerPro(root, ...)
    }
}

Types 🧑‍🏫

Kind of API.

import * as THREE from 'three'
import * as CANNON from 'cannon-es'

// Helper types for THREE.EventDispatcher
export type CannonEsDebuggerProEventMap = {
	init: {
		body: CANNON.Body
		obj3d: THREE.Object3D
		shape: CANNON.Shape
	}
	update: {
		body: CANNON.Body
		obj3d: THREE.Object3D
		shape: CANNON.Shape
	}
}
type CannonEsDebuggerProEventType = Extract<keyof CannonEsDebuggerProEventMap, string>

export class CannonEsDebuggerPro extends THREE.EventDispatcher<CannonEsDebuggerProEventMap> {
    constructor(
        root: THREE.Object3D, 
        world: CANNON.World,
        color: THREE.ColorRepresentation = 0x00ff00,
        offset: number = 0.005
    ): void

    // Accessors
    get color(): THREE.ColorRepresentation
    get offset(): number
    get isVisible(): boolean
    get isDestroyed(): boolean

    // Main methods
    update(): void
    clear(): void
    destroy(): void

    // Customization methods
    setVisible(isVisible: boolean): this
    setColor(color: THREE.ColorRepresentation): this
    setOffset(offset: number): this

    // THREE.EventDispatcher methods
    addEventListener<T extends CannonEsDebuggerProEventType>(
        type: T,
        listener: THREE.EventListener<CannonEsDebuggerProEventMap[T], T, this>,
    ): void
    hasEventListener<T extends CannonEsDebuggerProEventType>(
        type: T,
        listener: THREE.EventListener<CannonEsDebuggerProEventMap[T], T, this>,
    ): boolean
    removeEventListener<T extends CannonEsDebuggerProEventType>(
        type: T,
        listener: THREE.EventListener<CannonEsDebuggerProEventMap[T], T, this>,
    ): void
}

Donate 🥺🙏

🌐 ERC-20 wallet (USDC / USDT / ETH):
0xF348AB28dB048CbFF18095b428ac9Da4f1A7a90e

Social media / links 💃💅


meow :3

Package Sidebar

Install

npm i @vladkrutenyuk/cannon-es-debugger-pro

Weekly Downloads

3

Version

0.2.4

License

MIT

Unpacked Size

153 kB

Total Files

9

Last publish

Collaborators

  • vladkrutenyuk