Physics not working in pg

Hi!

I am trying to have collision between a mesh and a BABYLON mesh, but I get an error.

https://playground.babylonjs.com/#LJ4W85#2
This playground uses Cannon. Error “cannot read property clone, undefined”.

Next up, Oimo:
https://playground.babylonjs.com/#LJ4W85#3
I get the error “e.object.getAbsolutePivotPoint is not a function”.

Ammo:
https://playground.babylonjs.com/#LJ4W85#4
Cannot read property “x”, undefined

This is slightly annoying, but I’m not sure if it is because of my colossal mesh or the engine.

UPDATE:

With commenting out the line where the city gets it’s physics impostor, everything works, but I want to try and have the city to have collision.

2 Likes

Not sure about cannon… But Ammo.js has to use Ammo.then() to kinda bootstrap the physics engine loading. This is how i bootstrap ammo.js:


        // This initializes bullet physics (non-mesh)
        const wnd:any = window;
        if (!wnd.ammoLoaded) {
            wnd.Ammo().then(function(){ 
                wnd.ammoLoaded = true;
                Playground.LoadScene(scene);
            });
        } else {
            Playground.LoadScene(scene);
        }

Take a look at one of my Need For Speed style racing playgrounds. I use tons of physics including collisions and ray casting and obviously Driving Mechanics

https://www.babylonjs-playground.com/#GGCXPU#14

Hope that helps get you going :slight_smile:

Your playground has a broken github link and only shows a white screen. Sounds interesting, but basically you stop the scene from loading until the physics engine is loaded?

Thats weird… I just tried on both my browsers : Safari and Chrome

https://www.babylonjs-playground.com/#GGCXPU#14

Try one of the lower numbers like 11 for example:

https://www.babylonjs-playground.com/#GGCXPU#11

Technically you dont have to stop the scene.

The main thing is to load the Ammo.js library properly on the page before your scene loads that uses any physics.

Now in my real projects i simply make sure ammo is loaded before calling the defaultSceneLoader function (which actually creates the BABYLON.Engine and loads the BABYLON.Scene) for my index.html:

        // ************************************************************************ //
        // DEFAULT LOADER - Initialize Default Scene Loading                        //
        // ************************************************************************ //
        window.addEventListener("DOMContentLoaded", function() {
            if (enablephysics === true && window.Ammo !== undefined) {
                Ammo().then(function() { defaultSceneLoader(scenepath, scenename); });
            } else {
                defaultSceneLoader(scenepath, scenename);
            }
        });

that way ammo.js lib is already loaded and ready on the page before i even try load any scenes that may have physics enabled.

The playground is is bit different… We wont have access to the host page of the playground. So i wrote that little bootstrapper code just for playground workaround

Just in case you cant see playground code… Here is code to bootstrap Ammo.js on the playground:

class Playground { 
    public static async CreateScene(engine: BABYLON.Engine, canvas: HTMLCanvasElement): Promise<BABYLON.Scene> {
        // This creates a basic scene object (non-mesh)
        var scene = new BABYLON.Scene(engine);

        // This initializes bullet physics (non-mesh)
        const wnd:any = window;
        if (!wnd.ammoLoaded) {
            wnd.Ammo().then(function(){ 
                wnd.ammoLoaded = true;
                Playground.LoadScene(scene);
            });
        } else {
            Playground.LoadScene(scene);
        }

        // This save current scene for debugging
        (<any>window).scene = scene;
        return scene;
    }

    public static async LoadScene(scene:BABYLON.Scene):Promise<void> {
        let rootUrl:string = "https://mackeyk24.github.io/racing/test3/";
        
        // Load Project Script Bundle (Authored With Babylon Toolkit Editor)
        await BABYLON.Tools.LoadScriptAsync(rootUrl + "project.js");

        // Load Authored Sample Race Track Scene (SceneManager Will Parse Unity Metadata)
        await BABYLON.SceneLoader.AppendAsync(rootUrl, "SampleScene.gltf", scene);
        
        // Get Mustang Car Transform Node From Authored Scene Content
        const mustangTransform:BABYLON.TransformNode = BABYLON.SceneManager.GetTransformNode(scene, "Tester Car 1");
        if (mustangTransform) {

            // Get Reference To Project Standard Car Controller
            const standardCarController:PROJECT.StandardCarController = BABYLON.SceneManager.FindScriptComponent(mustangTransform, "PROJECT.StandardCarController");
            if (standardCarController != null) {
                standardCarController.baseEnginePower = 3000;
                standardCarController.burnoutCoefficient = 5.55;
                standardCarController.burnoutDonutBoost = 9.25;

                // Wheel Fountain Local Positions
                const frontLeftPosition:BABYLON.Vector3 = BABYLON.Vector3.Zero();
                const frontRightPosition:BABYLON.Vector3 = BABYLON.Vector3.Zero();
                const backLeftPosition:BABYLON.Vector3 = BABYLON.Vector3.Zero();
                const backRightPosition:BABYLON.Vector3 = BABYLON.Vector3.Zero();

                // Wheel Hub Transform Nodes
                let frontLeftWheelHub:BABYLON.TransformNode = null;
                let frontRightWheelHub:BABYLON.TransformNode = null;
                let backLeftWheelHub:BABYLON.TransformNode = null;
                let backRightWheelHub:BABYLON.TransformNode = null;
         

                ////////////////////////////////////////////////////
                // TODO: Setup GPU Particle Systems For Wheel Smoke
                ////////////////////////////////////////////////////

                let backRigghtWheelEmitter:BABYLON.AbstractMesh = new BABYLON.AbstractMesh("backRigghtWheelEmitter");
                //let psbr = new BABYLON.GPUParticleSystem("psbr",{capacity:30000}, scene);
                let psbr = new BABYLON.ParticleSystem("psbr", 10000, scene);
                psbr.particleTexture = new BABYLON.Texture("https://raw.githubusercontent.com/PatrickRyanMS/BabylonJStextures/master/forum/correctedSmoke.png", scene);                
                psbr.minAngularSpeed = -1.5;
                psbr.maxAngularSpeed = 1.5;
                psbr.minSize = 0.2;
                psbr.maxSize = 1.3;

                // changed lifetime to control shape of the cloud in conjunction with velocity gradient
                psbr.minLifeTime = 3.0;
                psbr.maxLifeTime = 5.0;

                // adding velocity over time to prevent large bloom of particles by launching them fast and then slowing them down GPU particles don't take a gradient on velocity, but the reduction in velocity over time is worth the trade off for less randomization
                // psbr.minEmitPower = 0.3;
                // psbr.maxEmitPower = 0.7;
                psbr.addVelocityGradient(0, 1);
                psbr.addVelocityGradient(0.1, 0.7);
                psbr.addVelocityGradient(0.7, 0.2);
                psbr.addVelocityGradient(1.0, 0.05);

                psbr.emitter = backRigghtWheelEmitter;

                // reduced the emit rate to reduce bloom of particles in the center of mass
                psbr.gravity = new BABYLON.Vector3(0, -0.1, 0);
                psbr.minEmitBox = new BABYLON.Vector3(0, -0.25, 0);
                psbr.maxEmitBox = new BABYLON.Vector3(0, -0.25, 0);
                psbr.direction1 = new BABYLON.Vector3(-1, -1, -1);
                psbr.direction2 = new BABYLON.Vector3(1, 1, 1);

                // The color1, color2, colorDead pattern is overridden by color gradient so is unnecessary
                psbr.color1 = new BABYLON.Color4(1.0, 1.0, 1.0, 0.1);
                psbr.color2 = new BABYLON.Color4(1.0, 1.0, 1.0, 0.05);
                psbr.colorDead = new BABYLON.Color4(1.0, 1.0, 1.0, 0.0);
                
                // Changed the color gradient to add a second value for randomization and ramped the color down further to create more texture with alpha blending
                //psbr.addColorGradient(0.0, new BABYLON.Color4(1, 1, 1, 0.0), new BABYLON.Color4(0.7, 0.7, 0.7, 0.0));
                //psbr.addColorGradient(0.2, new BABYLON.Color4(0.7, 0.7, 0.7, 0.2), new BABYLON.Color4(0.6, 0.6, 0.6, 0.2));
                //psbr.addColorGradient(0.6, new BABYLON.Color4(0.6, 0.6, 0.6, 0.1),new BABYLON.Color4(0.4, 0.4, 0.4, 0.1));
                //psbr.addColorGradient(1.0, new BABYLON.Color4(0.3, 0.3, 0.3, 0.0),new BABYLON.Color4(0.1, 0.1, 0.1, 0.0));
                
                psbr.blendMode = BABYLON.ParticleSystem.BLENDMODE_STANDARD;

                let backLeftWheelEmitter:BABYLON.AbstractMesh = new BABYLON.AbstractMesh("backLeftWheelEmitter");
                let psbl = psbr.clone("psbl", null);
                psbl.emitter = backLeftWheelEmitter;

                standardCarController.onUpdateVehicleInformation = (skid_FL:number, skid_FR:number, skid_RL:number, skid_RR:number) => {

                    //////////////////////////////////////////////////
                    // Validate Wheel Hub Transform Nodes Setup
                    //////////////////////////////////////////////////

                    if (frontLeftWheelHub == null) {
                        frontLeftWheelHub = standardCarController.getFrontLeftWheelNode();
                        if (frontLeftWheelHub != null) frontLeftPosition.copyFrom(frontLeftWheelHub.position);

                        // TODO: Create Front Left Fountion Mesh At Local Position - ???
                    }
                    if (frontRightWheelHub == null) {
                        frontRightWheelHub = standardCarController.getFrontRightWheelNode();
                        if (frontRightWheelHub != null) frontRightPosition.copyFrom(frontRightWheelHub.position);

                        // TODO: Create Front Right Fountion Mesh At Local Position - ???
                    }
                    if (backLeftWheelHub == null) {
                        backLeftWheelHub = standardCarController.getBackLeftWheelNode();
                        if (backLeftWheelHub != null){
                             backLeftPosition.copyFrom(backLeftWheelHub.position);
                            backLeftWheelEmitter.position = standardCarController.getBackLeftWheelNode().absolutePosition;
                        }

                        // TODO: Create Back Left Fountion Mesh At Local Position - ???
                    }
                    if (backRightWheelHub == null) {
                        backRightWheelHub = standardCarController.getBackRightWheelNode();
                        if (backRightWheelHub != null){ 
                            backRightPosition.copyFrom(backRightWheelHub.position);
                            backRigghtWheelEmitter.position = standardCarController.getBackRightWheelNode().absolutePosition;
                            }

                        // TODO: Create Back Right Fountion Mesh At Local Position - ???
                    }

                    //////////////////////////////////////////////////
                    // TODO: Emit Wheel Smoke Based On Skid Intenisty
                    //////////////////////////////////////////////////

                    if (frontLeftWheelHub != null) {
                        // Emit Front Left Wheel Smoke If Needed
                    }

                    if (frontRightWheelHub != null) {
                        // Emit Front Right Wheel Smoke If Needed
                    }

                    if (backLeftWheelHub != null) {
                        if(!psbl.isStarted()){
                            psbl.start()                            
                        }
                        let skid = skid_RL*skid_RL;
                        psbl.emitRate = 300 * skid;
                        psbl.minSize = 0.2 * skid + 0.2;
                        psbl.maxSize = 1.5 * skid + 1.5;
                    }

                    if (backRightWheelHub != null) {                        
                        if(!psbr.isStarted()){
                            psbr.start()                            
                        }
                        let skid = skid_RR*skid_RR;
                        psbr.emitRate = 300 * skid;
                        psbr.minSize = 0.2 * skid + 0.2;
                        psbr.maxSize = 1.5 * skid + 1.5;
                        
                    }
                };
            }
        } else {
            console.warn("No Mustang Car Transform Found.");
        }
    }
}

Nope, still a white screen. I’m using a chromebook, so that could explain why. Thanks for the great explanation, I should be able to test it out and see if it works.

Is chrome book not a full fledged PC ???

Dunno… I never used a chrome book before… I’m basically all Apple :apple:

1 Like

Heh. A chromebook is basically google chrome, and nothing else. They have Linux features, but they don’t really help because I can’t use them. (My chromebook is given to everyone at my school.) I have a custom desktop at home, and I’m basically the opposite of you; anti-apple. But, chrome is chrome, firefox is firefox, and IDEs are similar.

Oh, and a chromebook can’t run exe’s, or in your case, dmg’s

Hold up @Wingnut! I have a solution. Using some code from when I was messing around a long while back, giv0.gitlab.io/fpsg, I had some code for boxes I made. The code is below, but adapted for this case. All meshes have a mesh impostor, because I figured out that the mesh is a lot of sub-meshes and that by impostoring the sub meshes the mesh would be impostored. I tried Box impostors for some performance gainz, but only the load times were shorted with the change, but the collision was off.

https://playground.babylonjs.com/#LJ4W85#8

BABYLON.SceneLoader.ImportMesh("", "https://raw.githubusercontent.com/Giv0/PhaserGameAssets/master/", "center-city-sci-fi.babylon", scene, function(newMeshes) {
                let cparent = new BABYLON.TransformNode();

                for (var index = 0; index < newMeshes.length; index++) {
                    let city1 = newMeshes[index];

                    city1.physicsImpostor = new BABYLON.PhysicsImpostor(city1, BABYLON.PhysicsImpostor.MeshImpostor, { mass: 0, friction: 0, restitution: 0}, scene);

                    city1.parent = cparent;
                }

                
    });

Ok g-man, I’m over here, now, working on https://playground.babylonjs.com/#LJ4W85#7

CannonJS (ps. Oimo has no meshImpostor. Ammo probably does, though)

Ok, ya got a big fat 15-mesh model coming in, and you tried to flop a meshImpostor onto it… without waiting for the callback function to run. Ya had no callback func attached. So, I put one onto the importMesh call… so we could wait for it to finish loading… and then… attack the other problems.

I hope you didn’t think that one Cannon meshImpostor would handle 15 separate and likely childed/parented mesh.

So, ya gotta merge 'em all… into one big city mesh.

I try it in line 48… and city2 is not existing after the merge. SO, I suspect the merge is failing.

Can you make city be one big mesh… before you import? That might work. But still, ya gotta wait for load to finish and then add impostor in the callback. Callback function is sort of an onSuccess area.

Ok, that’s all I got so far. Failing merge. Might have some geometry-less mesh in the pile of imported pieces. Earler, I bypassed the import and tested a torus knot with a meshImpostor… dropping the sphere on it. It worked good… so physics engine is active and operating.

I also tried a “box” ground… with a meshImpostor, and I dropped the torus knot with meshImpostor… onto the ground. It fell right thru. A couple months ago, I found a playground where two meshImpostors collided with each other fine. But, those were both “ovals”. The meshImpostor on the box… might be failing. I HAVE seen two meshImpostors collide with each other fine. Here.

Pretty model!

1 Like

Wow, thanks for the cannon solution. (I can’t use the chrome inspector tools, because of everything being locked down, but on my main pc I can) I just downloaded this model from clara.io, a free 3d modeling website that can export to .babylon! It’s kinda my go-to. I made a little box with clara.io a while back, and remembered about it and the code needed to add impostors to the sub-meshes. More loading, but no merging. I was trying to add collision to the city so I can add a CS, CS:S, or CS:GO bhop map into my current NYNS bhop playground to try it out. (CS -> Counter strike, CS:S -> Counter Strike: Source, CS:GO -> Counter Strike: Global Offensive)

I’m trying to switch over to ammo.js because of the mesh collisions, because IDK why cannon feels like only having meshes collide with spheres and planes. Maybe the Convex Hull might be useful sometime. I’m not sure if ammo has the linear damping option with physics impostors, but right now NYNS switches between 0 and 0.9999 when moving. I’m gonna convert everything to like how the bhop works with set linear velocity so then the movement speed can be controller easier.

Thanks for the help! (I marked you as a solution because you have a solution. I don’t wanna be a scumbag who ignored other solutions :upside_down_face:)

Wait, the sphere falls right through the mesh for me on #7. That’s odd if it works for you. As of the individual impostors,

https://playground.babylonjs.com/#LJ4W85#9

this works.

Yeah, it DIDN’T work for me. I failed to merge evertthing into city2.

But you got it working, well done.

And you never need to worry about linear damping… because you can always use @RaananW’s leather boot method. This is where you stick your work-boot against the mesh to bring it to a stop. :slight_smile:

var brakes = 1; // When brakes = 1… no changes in LV. Brakes = .99 and below… brakes ON. Also works for angularVelocity.

scene.onBeforeRenderObservable.add(function(){
var addition = mesh.physicsImpostor.setLinearVelocity(mesh.physicsImpostor.getLinearVelocity().scale(brakes));
});

As needed, you can do scene.onBeforeRenderObservable.remove(addition); Its good to be able to add/remove your damper from the renderLoop… to keep performance hopping. Adding/removing observers takes a little practice. :slight_smile: The leather boot method MUST be hung on the renderLoop… cuz… we are continuously bleeding-off just a tiny bit of LV…each frame… something that needs to be done repeatedly. A bit difficult to know WHEN it’s time to shut it off/remove it, though.

Might require:
var testLV = mesh.physicsImpostor.getLinearVelocity();
if (testLV.x <.01 && testLV.y <.01 && testLV.z <.01) then remove damping.

If you know how to check for physics .isSleeping, that might work, too. :slight_smile:

It might be nice to have a vec3 all-components tester:

IF (testLV.allLessThan(.01)) { kill the damper } You might wish to code your own allLessThan(someVec3, .01); Checks all three axes… x/y/z, and if all are < .01, returns true. :slight_smile:

2 Likes

pikachu%20oh
thanks for the tip!

1 Like