UNPKG

@vladkrutenyuk/cannon-es-debugger-pro

Version:

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

321 lines (227 loc) β€’ 10 kB
# @vladkrutenyuk/cannon-es-debugger-pro This is improved pro debugger for [cannon-es](https://github.com/pmndrs/cannon-es) with [three](https://github.com/pmndrs/cannon-es) to visualize all bodies and its shapes of physics world. It was based on [cannon-es-debugger](https://www.npmjs.com/package/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](https://i.imgur.com/Tet6Pun.png) - 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 πŸ€“ ```bash 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. ```bash pnpm add three cannon-es # or via 'npm i ...', 'yarn add ...' and so on ``` ## Usage 🧐 #### Initialization ```ts 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. ```ts 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](https://www.npmjs.com/package/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`. ```ts 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. ```ts // 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` ```typescript 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` ```typescript 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` ```typescript // 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` ```typescript // 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.** ```ts 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 πŸ’ƒπŸ’… - [Telegram (@vladkrutenyuk)](https://t.me/vladkrutenyuk) - [Instagram (@vlad_krutenyuk)](https://instagram.com/vlad_krutenyuk) - [Twitter/X (@vladkrutenyuk)](https://x.com/vladkrutenyuk) - [Twitch (vladdyusha)](https://twitch.tv/vladdyusha) - [kvy-4Β° (My funny telegram channel)](https://t.me/kvvy4) - [https://kvy.world](https://kvy.world) --- _meow :3_