Giter VIP home page Giter VIP logo

cannon-es-debugger's People

Contributors

codynova avatar dependabot[bot] avatar drcmda avatar krispya avatar marcofugaro avatar stockhuman avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

cannon-es-debugger's Issues

Incorrect Cylinder shape

As of new version of cannon-es Cylinder.type is equal to Shape.types.CYLINDER (as it should be).

But so far the debug-renderer handled Cylinders as ConvexPolyhedrons and now every cylinder is represented as the default "CylinderGeometry(0.5, 0.5, 1, 32)"

I'm not sure about the proper fix, but removing the body of "case CYLINDER" in "function createMesh()" leaving as
case CYLINDER: \n case CONVEXPOLYHEDRON: ...
solves the issue,
(the "function typeMatch()" also has not prepared to handle cylinders)

cannon-es_debug-renderer_cylinder_issue

Is scaleMesh on every update appropriate?

This may be an issue on my side, not grasping the complete concept of the debugger: What's the concept behind updateMesh calling scaleMesh every time - I'd rather expect scaleMesh to be called only on mesh intialization?

Feature request: Be able to toggle debug mode on or off

Hey thanks for this library, its awesome and makes it easy to visualize the collision bodies. I was trying to enable a way to for this mode to be turned on and off but noticed that I would have to find the objects in the scene and manually remove them. When you stop calling update() the objects remain in their old position.

I whipped something up will submit a PR if you are willing to consider it. Cheers.

PERFORMANCE WARNING!!! After migrated from cannon.js to cannon-es-debugger.

Cannon.js' CannonDebugRenderer.js require user to write cannonDebugRenderer.update().

But cannon-es-debugger.js has autoUpdate parameter and default set to true, so will use inner requestAnimationFrame to call update().

After migrated from cannon.js to cannon-es-debugger, be careful to set autoUpdate to false, or delete the old cannonDebugRenderer.update() in own code.

calling update does not update the debug visualization

cannon-es-debugger v: 1.0.0
cannon-es v: 0.18.0
threejs v: 0.136.0

when I update the data in a heightfield and call update on it and then call the debugger update, the visualization does not update.
I think this is the issue:

if (!typeMatch(mesh, shape)) {

The !typeMatch(mesh, shape) expression only evaluates to true at initialization, after that it always returns false so nothing is updated.
the shape.geometryId is undefined
my issue is with a heightfield but it also evaluates to false for sphere and and boxes.

Expose function to detach/disable debugger

When conditionally rendering the debugger it would be useful to be able to detach/disable it after it has been enabled, without having to reload the entire page. E.g. when used with dat.gui etc.

Currently there is no way to do this afaict. What would you think about adding a detach function that removes all meshes from the scene?

let enabled = true
const debugger = cannonDebugger(scene, world.bodies, { autoUpdate: false })

requestAnimationFrame(() => {
  if (enabled) {
    debugger.update()
  }
})

// This would be in an event listener in a real world scenario
enabled = false
debugger.detatch()

Cannon ES Debugger. WARNING: Multiple instances of Three.js being imported

This warning appears when I add cannon-es-debugger:

image

index.html

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="utf-8">
    <title>Example</title>
    <style>
        body {
            margin: 0;
        }
    </style>
</head>

<body>
    <!-- Since import maps are not yet supported by all browsers, it is
        necessary to add the polyfill es-module-shims.js -->
    <script async src="https://unpkg.com/[email protected]/dist/es-module-shims.js"></script>

    <script type="importmap">
        {
            "imports": {
                "three": "https://unpkg.com/[email protected]/build/three.module.min.js",
                "orbit-controls": "https://unpkg.com/[email protected]/examples/jsm/controls/OrbitControls.js",
                "cannon-es": "https://cdn.jsdelivr.net/npm/[email protected]/+esm",
                "cannon-es-debugger": "https://cdn.jsdelivr.net/npm/[email protected]/+esm"
            }
        }
    </script>

    <script type="module" src="./js/index.js"></script>
</body>

</html>

index.js

import * as THREE from "three";
import { OrbitControls } from "orbit-controls";
import * as CANNON from "cannon-es";
import CannonDebugger from "cannon-es-debugger";

async function init() {
    const scene = new THREE.Scene();

    const camera = new THREE.PerspectiveCamera(50,
        window.innerWidth / window.innerHeight, 0.1, 500);
    const renderer = new THREE.WebGLRenderer({ antialias: true });
    renderer.setClearColor(0x079bb0, 1);
    renderer.setSize(window.innerWidth, window.innerHeight);
    document.body.appendChild(renderer.domElement);

    const orbitControls = new OrbitControls(camera, renderer.domElement);
    orbitControls.target = new THREE.Vector3(0, 0, 0);

    const world = new CANNON.World({ gravity: new CANNON.Vec3(0, 0, 0) });
    const cannonDebugger = new CannonDebugger(scene, world);

    let dt;
    const clock = new THREE.Clock();

    window.onresize = () => {
        camera.aspect = window.innerWidth / window.innerHeight;
        camera.updateProjectionMatrix();
        renderer.setSize(window.innerWidth, window.innerHeight);
    };

    function render() {
        requestAnimationFrame(render);
        orbitControls.update();
        dt = clock.getDelta();
        world.step(dt);
        cannonDebugger.update();
        renderer.render(scene, camera);
    }
    render();
}

init();

Question: where is the example?

Truly wonderful library (Cannon-es)
But I'm having a hard time seeing how to implement the debugger version.
Is there an example html file anywhere, that I can run?

ReferenceError: three is not defined

Hi guys.
recently I use cannon-es-debugger with svelte(v.3.0.0)

but it said that "ReferenceError: three is not defined "

I don't know what it happened.

i just know it happened when imported cannon-es-debugger.

import as jsm

Hi! Is there a way we could make this module usable as a jsm module. Could we assume that the peer dependancies will be relative to this module? Or maybe pass three/cannon into the debugger?

I have been using the debugger like this as a jsm module:

// ./node_modules/cannon-es-debugger-jsm/index.js

import * as THREE from '../three/build/three.module.js'
import * as CANNON from '../cannon-es/dist/cannon-es.js'

// Cannon Debugger
export class CannonDebugRenderer {
   constructor(scene, world, options) {
      options = options || {};

      this.scene = scene;
      this.world = world;

      this._meshes = [];

      this._material = new THREE.MeshBasicMaterial({ color: 0x00ff00, wireframe: true });
      this._sphereGeometry = new THREE.SphereGeometry(1);
      this._boxGeometry = new THREE.BoxGeometry(1, 1, 1);
      this._planeGeometry = new THREE.PlaneGeometry( 10, 10, 10, 10 );
      this._cylinderGeometry = new THREE.CylinderGeometry( 1, 1, 10, 10 );
      
      this.tmpVec0 = new CANNON.Vec3();
      this.tmpVec1 = new CANNON.Vec3();
      this.tmpVec2 = new CANNON.Vec3();
      this.tmpQuat0 = new CANNON.Vec3();
   }

    update(bodies){

        // var bodies = this.world.bodies;
        var meshes = this._meshes;
        var shapeWorldPosition = this.tmpVec0;
        var shapeWorldQuaternion = this.tmpQuat0;

        var meshIndex = 0;

        for (var i = 0; i !== bodies.length; i++) {
            var body = bodies[i];

            for (var j = 0; j !== body.shapes.length; j++) {
                var shape = body.shapes[j];

                this._updateMesh(meshIndex, body, shape);

                var mesh = meshes[meshIndex];

                if(mesh){

                    // Get world position
                    body.quaternion.vmult(body.shapeOffsets[j], shapeWorldPosition);
                    body.position.vadd(shapeWorldPosition, shapeWorldPosition);

                    // Get world quaternion
                    body.quaternion.mult(body.shapeOrientations[j], shapeWorldQuaternion);

                    // Copy to meshes
                    mesh.position.copy(shapeWorldPosition);
                    mesh.quaternion.copy(shapeWorldQuaternion);
                }

                meshIndex++;
            }
        }

        for(var i = meshIndex; i < meshes.length; i++){
            var mesh = meshes[i];
            if(mesh){
                this.scene.remove(mesh);
            }
        }

        meshes.length = meshIndex;
    }

    _updateMesh(index, body, shape){
        var mesh = this._meshes[index];
        if(!this._typeMatch(mesh, shape)){
            if(mesh){
                this.scene.remove(mesh);
            }
            mesh = this._meshes[index] = this._createMesh(shape);
        }
        this._scaleMesh(mesh, shape);
    }

    _typeMatch(mesh, shape){
        if(!mesh){
            return false;
        }
        var geo = mesh.geometry;
        return (
            (geo instanceof THREE.SphereGeometry && shape instanceof CANNON.Sphere) ||
            (geo instanceof THREE.BoxGeometry && shape instanceof CANNON.Box) ||
            (geo instanceof THREE.PlaneGeometry && shape instanceof CANNON.Plane) ||
            (geo.id === shape.geometryId && shape instanceof CANNON.ConvexPolyhedron) ||
            (geo.id === shape.geometryId && shape instanceof CANNON.Trimesh) ||
            (geo.id === shape.geometryId && shape instanceof CANNON.Heightfield)
        );
    }

    _createMesh(shape){
        var mesh;
        var material = this._material;

        switch(shape.type){

        case CANNON.Shape.types.SPHERE:
            mesh = new THREE.Mesh(this._sphereGeometry, material);
            break;

        case CANNON.Shape.types.BOX:
            mesh = new THREE.Mesh(this._boxGeometry, material);
            break;

        case CANNON.Shape.types.PLANE:
            mesh = new THREE.Mesh(this._planeGeometry, material);
            break;

        case CANNON.Shape.types.CONVEXPOLYHEDRON:
            // Create mesh
            var geo = new THREE.Geometry();

            // Add vertices
            for (var i = 0; i < shape.vertices.length; i++) {
                var v = shape.vertices[i];
                geo.vertices.push(new THREE.Vector3(v.x, v.y, v.z));
            }

            for(var i=0; i < shape.faces.length; i++){
                var face = shape.faces[i];

                // add triangles
                var a = face[0];
                for (var j = 1; j < face.length - 1; j++) {
                    var b = face[j];
                    var c = face[j + 1];
                    geo.faces.push(new THREE.Face3(a, b, c));
                }
            }
            geo.computeBoundingSphere();
            geo.computeFaceNormals();

            mesh = new THREE.Mesh(geo, material);
            shape.geometryId = geo.id;
            break;

        case CANNON.Shape.types.TRIMESH:
            var geometry = new THREE.Geometry();
            var v0 = this.tmpVec0;
            var v1 = this.tmpVec1;
            var v2 = this.tmpVec2;
            for (var i = 0; i < shape.indices.length / 3; i++) {
                shape.getTriangleVertices(i, v0, v1, v2);
                geometry.vertices.push(
                    new THREE.Vector3(v0.x, v0.y, v0.z),
                    new THREE.Vector3(v1.x, v1.y, v1.z),
                    new THREE.Vector3(v2.x, v2.y, v2.z)
                );
                var j = geometry.vertices.length - 3;
                geometry.faces.push(new THREE.Face3(j, j+1, j+2));
            }
            geometry.computeBoundingSphere();
            geometry.computeFaceNormals();
            mesh = new THREE.Mesh(geometry, material);
            shape.geometryId = geometry.id;
            break;

        case CANNON.Shape.types.HEIGHTFIELD:
            var geometry = new THREE.Geometry();

            var v0 = this.tmpVec0;
            var v1 = this.tmpVec1;
            var v2 = this.tmpVec2;
            for (var xi = 0; xi < shape.data.length - 1; xi++) {
                for (var yi = 0; yi < shape.data[xi].length - 1; yi++) {
                    for (var k = 0; k < 2; k++) {
                        shape.getConvexTrianglePillar(xi, yi, k===0);
                        v0.copy(shape.pillarConvex.vertices[0]);
                        v1.copy(shape.pillarConvex.vertices[1]);
                        v2.copy(shape.pillarConvex.vertices[2]);
                        v0.vadd(shape.pillarOffset, v0);
                        v1.vadd(shape.pillarOffset, v1);
                        v2.vadd(shape.pillarOffset, v2);
                        geometry.vertices.push(
                            new THREE.Vector3(v0.x, v0.y, v0.z),
                            new THREE.Vector3(v1.x, v1.y, v1.z),
                            new THREE.Vector3(v2.x, v2.y, v2.z)
                        );
                        var i = geometry.vertices.length - 3;
                        geometry.faces.push(new THREE.Face3(i, i+1, i+2));
                    }
                }
            }
            geometry.computeBoundingSphere();
            geometry.computeFaceNormals();
            mesh = new THREE.Mesh(geometry, material);
            shape.geometryId = geometry.id;
            break;
        }

        if(mesh){
            this.scene.add(mesh);
        }

        return mesh;
    }

    _scaleMesh(mesh, shape){
        switch(shape.type){

        case CANNON.Shape.types.SPHERE:
            var radius = shape.radius;
            mesh.scale.set(radius, radius, radius);
            break;

        case CANNON.Shape.types.BOX:
            mesh.scale.copy(shape.halfExtents);
            mesh.scale.multiplyScalar(2);
            break;

        case CANNON.Shape.types.CONVEXPOLYHEDRON:
            mesh.scale.set(1,1,1);
            break;

        case CANNON.Shape.types.TRIMESH:
            mesh.scale.copy(shape.scale);
            break;

        case CANNON.Shape.types.HEIGHTFIELD:
            mesh.scale.set(1,1,1);
            break;

        }
    }
};

Internal requestAnimationFrame out of sync with main requestAnimationFrame

I have a requestAnimationFrame in my project where I do the three.js rendering and the cannon-es physics stepping. However when setting up cannon-es-debugger, this happens:

ball.mov

I keep the mesh in sync with the body, however the wireframes are just 1 step behind.

To fix this, we should provide an autoUpdate which the user can turn off if he needs to and then expose an update() method.

ContactMaterial Class

This had worked fine when using non-ES official cannon.js

var physicsMaterial = new CANNON.Material("slipperyMaterial");
var physicsContactMaterial = new CANNON.ContactMaterial(physicsMaterial, physicsMaterial, 0.0, 0.3);
world.addContactMaterial(physicsContactMaterial);
var groundShape = new CANNON.Plane();
var groundBody = new CANNON.Body({ mass: 0}), material: physicsMaterial });
groundBody.addShape(groundShape);
groundBody.quaternion.setFromAxisAngle(new CANNON.Vec3(1,0,0),-Math.PI/2 - .30);
groundBody.position.set(0,0,0);
world.addBody(groundBody);

Now I am getting this error

Uncaught TypeError: Cannot use 'in' operator to search for 'friction' in 0
at Function.defaults (main.js:2)
at new Ac (main.js:2)
at main.js:2
at main.js:2
defaults @ main.js:2
Ac @ main.js:2
(anonymous) @ main.js:2
(anonymous) @ main.js:2

Perhaps I was looking at outdated docs or examples when I pulled this in. Any ideas?

Scaling should affect Plane and position

Would you please

add mesh.scale.set(1 * scale, 1 * scale, 1 * scale) after line 188

and

change line 260 from mesh.position.copy(shapeWorldPosition as unknown as ThreeVector3) to
mesh.position.copy(shapeWorldPosition.clone().multiplyScalar(scale) as unknown as ThreeVector3) (or something more elegant, sorry I don't code in TypeScript)

Cheers
Rai

Usage section is outdated - TypeScript does not allow to use new keyword with function

Problem

The usage page uses the example where the CannonDebugger is a class, which is not right because right now what is exported from this package is a function. In TypeScript it's not possible to call it with new keyword, because it will throw an error as follows:

new CannonDebugger(scene, world); 
// 'new' expression, whose target lacks a construct signature, implicitly has an 'any' type.ts(7009)

In order to make it work in TypeScript, it would have to be called like a regular function

 CannonDebugger(scene, world); // does not throw an error

What is more the types from the declaration files seem to be outdated too. When I checked the dist/cannon-es-debugger.d.ts, it also points that the CannonDebugger is no more a class.

declare module "cannon-es-debugger" {
    import { Shape } from 'cannon-es';
    import { Mesh } from 'three';
    import type { Body, World } from 'cannon-es';
    import type { Scene, Color } from 'three';
    export type DebugOptions = {
        color?: string | number | Color;
        scale?: number;
        onInit?: (body: Body, mesh: Mesh, shape: Shape) => void;
        onUpdate?: (body: Body, mesh: Mesh, shape: Shape) => void;
    };
    export default function CannonDebugger(scene: Scene, world: World, { color, scale, onInit, onUpdate }?: DebugOptions): {
        update: () => void;
    };
}

Proposed Solution

The solution would be:

  • Update the usage section
  • Change the name of the function from CannonDebugger to createCannonDebugger and use named exports so that it is not confusing anymore that whether it's a class or function.

If you agree with this I can prepare a PR for that

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.