schteppe / cannon.js

A lightweight 3D physics engine written in JavaScript.
http://schteppe.github.com/cannon.js
MIT License
4.69k stars 712 forks source link

Errors in cannon.demo.js for the constraint visualization #213

Open KillerGoldFisch opened 9 years ago

KillerGoldFisch commented 9 years ago

Hi, I stumbled across some errors while playing with the demos. To reproduce this Errors, go to the constraints demo and activate the option Rendering -> constraints. The scene will immediately freeze with errors like Uncaught TypeError: Cannot read property 'bi' of undefined.

Here my (quick) solutions for the file cannon.demo.js (v0.6.2):

Line Code Issue Solution
315 var nc = c.equations.normal; CANNON.DistanceConstraint.equations is an Array
an got no property .normals
var nc = c.equations[0];
341 var n = c.equations.normal; CANNON.PointToPointConstraint.equations is an Array
an got no property .normals
var n = c.equations[0];
347 diffLine.scale.set( -n.penetrationVec.x, -n.penetrationVec.y, -n.penetrationVec.z ); ContactEquation got no property .penetrationVec Delete line

I hope this helps.

By the way, thanks for this awesome library! :thumbsup:

kungfooman commented 6 days ago

Rendering the penetration vector can be quite useful, but then you first have to enable it again in the ContactEquation:

- penetrationVec = ContactEquation_computeB_temp3,
+ penetrationVec = this.penetrationVec,

And add it back in the constructor:

- this.ni = new Vec3();
+ this.ni = new Vec3();
+ this.penetrationVec = new Vec3();

Then you can rewrite the rendering code like this:

            // Lines for distance constraints
            for (let ci = 0; ci < world.constraints.length; ci++) {
                const c = world.constraints[ci];
                if (!(c instanceof CANNON.PointToPointConstraint)) {
                    continue;
                }
                for (const equation of c.equations) {
                    const {bi, bj, ri, rj} = equation;
                    const relLine1 = p2pConstraintMeshCache.request();
                    const relLine2 = p2pConstraintMeshCache.request();
                    const diffLine = p2pConstraintMeshCache.request();
                    if (equation instanceof CANNON.ContactEquation) {
                        const {penetrationVec} = equation;
                        relLine1.scale.copy(ri);
                        relLine2.scale.copy(rj);
                        const s = 1 / penetrationVec.length();
                        diffLine.scale.set(-penetrationVec.x * s, -penetrationVec.y * s, -penetrationVec.z * s);
                        makeSureNotZero(relLine1.scale);
                        makeSureNotZero(relLine2.scale);
                        makeSureNotZero(diffLine.scale);
                        relLine1.position.copy(bi.position);
                        relLine2.position.copy(bj.position);
                        bj.position.vadd(rj, diffLine.position);
                    }
                }
            }

I figured that the length of the penetration vector is usually very low (e.g. 1/50), that's why I scale it to 1 for rendering it.

This is how it looks:

image

The reason it was removed was to not allocated a Vec3 for every equation. Hence usually you would simply calculate when needed, for example in Unity you have a special function for it: https://docs.unity3d.com/ScriptReference/Physics.ComputePenetration.html