Babylon and Barba JS - Update new mesh

Hi there,

I’m not sure if anyone is sort of familiar with Barba JS. Each page has a canvas and the idea is to load a different scene on every page (same one at the moment). This is the function to load the scene:

var canvas;
var engine = null,
    scene = null;

function preloadEvents(container) {
	var canvas = container.querySelector("#canvas_place");
	var createDefaultEngine = function() { return new BABYLON.Engine(canvas, true, { preserveDrawingBuffer: true, stencil: true }); };
	var createScene = function () {
	    var scene = new BABYLON.Scene(engine);
	    
	    scene.clearColor = new BABYLON.Color4(0, 0, 0, 0);
	    var spot = new BABYLON.HemisphericLight("spot", new BABYLON.Vector3(-0.3, 2.4, -2), scene);
	    spot.intensity = 1;
	    spot.diffuse = new BABYLON.Color3(1, 1, 1);
	    spot.specular = new BABYLON.Color3(0, 0, 0);

	    function createSidesForGroundMesh(ground, bottomY) {}

	    var assetsManager = new BABYLON.AssetsManager(scene);

	    babylonJsAssetsToLoad.forEach((obj) => {});

	    var camera = new BABYLON.ArcRotateCamera("Camera", -40, 1.2, 140, BABYLON.Vector3.Zero(), scene);
	    camera.setTarget(new BABYLON.Vector3(0, -15, 0));
	    camera.attachControl(canvas, true);

	    var groundMaterial = new BABYLON.StandardMaterial("ground", scene);
	    groundMaterial.diffuseTexture = new BABYLON.Texture("xxxxx.jpg", scene);
	    var ground = BABYLON.Mesh.CreateGroundFromHeightMap("ground", "xxxx.png", 100, 70, 250, 0, 5, scene, true, successCallback);
	    function successCallback() {}

	    assetsManager.onFinish = function (tasks) {
	      engine.runRenderLoop(function () {
	          if (scene) {
	              scene.render();
	          }
	      });
	    };

	    assetsManager.load();

	    return scene;
	}
	engine = createDefaultEngine();
	scene = createScene();

	engine.runRenderLoop(function () {
	    if (scene) {
	        scene.render();
	    }
	});
	window.addEventListener("resize", function () { engine.resize(); });	
}

And this is the Barba function that deals with all the calls:

barba.init({
	debug: true,
	transitions: [{
		once(data) {
	    	preloadEvents(data.next.container);
	    },
		leave({current}) {
			current.container.remove();
		},
		beforeEnter(data) {
			scene.dispose();
			canvas = null;
			delete canvas;
			preloadEvents(data.next.container);
		}
	}]
});

I’m not sure if this is the right way to update scenes on Babylon so any help would be much appreciated

Thanks

Hey! This seems cool but can you be more precise with your question?

It could look really cool yeah!! BarbaJS allows you to transition between pages without having to reload the page. It’s a great library. Every JS stuff (Babylon, carousel, functions, etc) required on a page needs to be declared so it loads on the upcoming page.

If it was a “static” site I could just call preloadEvents on page load and it will load a Babylon scene in the canvas.

In order to get Babylon working with Barba, everytime a page gets loaded I have to reinitialise Babylon. With certain libraries you have to kill the library first then call it again but I don’t know if that’s the case with Babylon.

I’m not sure if I’m explaining it properly or if I’m making it even more complicated haha :grimacing:

Nope all good :slight_smile: the only thing you have to do is dispose the current engine and create a new one for the given canvas. THen all good :smiley:

So I dispose the current scene with scene.dispose(); but how would I initialise the new one?

well the same way you created the first one :smiley:

Ah okay so this would be the right call, wouldn’t it?

scene.dispose();
canvas = null;
delete canvas;
preloadEvents(data.next.container);

Quick question, do I still need to kill the variable canvas? Or is there really no point?

You do not even need to delete the canvas. IF the canvas was attached to the engine you can reuse the same engine and create a new scene

You’re right. I’ve kept it as you said:

scene.dispose();
preloadEvents(data.next.container);

and it loads a different scene when I go to a another page :smiley:

Although, I’m having a small issue. I implemented the functionality from this post to move the camera (Best method for moving camera to target object - Questions - Babylon.js). It does work wonders on the first page but once I load a different page it doesn’t animate anymore. Here are the functions I took from the example. I also had to add my own ones to adjust it to my needs

var animateCameraTargetToPosition = function(cam, speed, frameCount, newPos) {
    var ease = new BABYLON.CubicEase();
    ease.setEasingMode(BABYLON.EasingFunction.EASINGMODE_EASEINOUT);
    var animCam1 = BABYLON.Animation.CreateAndStartAnimation('at1', cam, 'target', speed, frameCount, cam.target, newPos, 0, ease);
    animCam1.disposeOnEnd = true;
}
var animateCameraToPosition = function(cam, speed, frameCount, newPos) {
    var ease = new BABYLON.CubicEase();
    ease.setEasingMode(BABYLON.EasingFunction.EASINGMODE_EASEINOUT);
    var animCam2 = BABYLON.Animation.CreateAndStartAnimation('at2', cam, 'position', speed, frameCount, cam.position, newPos, 0, ease);
    animCam2.disposeOnEnd = true;
}
var speed = 60;
var frameCount = 200;
var setCamDefault = function() {
    animateCameraTargetToPosition(camera, speed, frameCount, new BABYLON.Vector3(0, -15, 0));
    animateCameraToPosition(camera, speed, frameCount, new BABYLON.Vector3(-40, 15, -45));
};
var setCamZoomedIn = function() {
    animateCameraTargetToPosition(camera, speed, frameCount, new BABYLON.Vector3(35, -30, 80));
    animateCameraToPosition(camera, speed, frameCount, new BABYLON.Vector3(-10, 10, -25));
};

function funcZoomIn() {
	setCamZoomedIn();
	jsBody.addClass("zoomedin");
}
function funcZoomOut() {
	setCamDefault();
	jsBody.removeClass("zoomedin");
}

ScrollTrigger.create({
	trigger: ".hero_section",
	start: "top center",
	end: "bottom center",
	markers: false,
	onEnter: () => { funcZoomOut(); }, 
	onLeave: () => { funcZoomIn(); },
	onEnterBack: () => { funcZoomOut(); }
});

I added values in the console to all the above functions and they all get triggered perfectly fine so I don’t know what on earth is going on :pensive:

I would say that one potential culprit would be the fact that you are not sharing the correct camera?

I thought I was :S
The camera is set when I first load the scene here:

var createScene = function () {
    var camera = new BABYLON.ArcRotateCamera("Camera", -40, 1.2, 140, BABYLON.Vector3.Zero(), scene);
}

Then I assume that the camera is still the same but it only changes position here:

var setCamDefault = function() {
    animateCameraTargetToPosition(camera, speed, frameCount, new BABYLON.Vector3(0, -15, 0));
    animateCameraToPosition(camera, speed, frameCount, new BABYLON.Vector3(-40, 15, -45));
};
var setCamZoomedIn = function() {
    animateCameraTargetToPosition(camera, speed, frameCount, new BABYLON.Vector3(35, -30, 80));
    animateCameraToPosition(camera, speed, frameCount, new BABYLON.Vector3(-10, 10, -25));
};

Sorry to be this ignorant but I can’t figure out at what point the camera changes :thinking:

You are using “var camera” in your createScene so it is a local variable

How would you make var camera a global variable? I tried declaring the variable at the beginning of the file by
var camera;

I have also tried this but it throws me an error
var camera = new BABYLON.ArcRotateCamera("Camera", -40, 1.2, 140, BABYLON.Vector3.Zero(), scene);

well this is more a javascript question but if you can repro in the playground or in jsfiddle we can certainly help

I honestly can’t believe this. It was working all along. I was setting up a project on Codepen and I decided to use the latest version of GSAP…and it bloody worked!!

After all this blood and tears you deserve to see it working haha

I’ve noticed that sometimes it doesn’t render the textures but I don’t get that issue. It might be because I had to host the images on another site :S

You can probably tell what kind of “developer” I am by looking at the code but with regard to Babylon, is there anything I can do to improve performance, rendering, etc?? It might be because my laptop needs retiring but every time the page is fully loaded and I can interact with the map there’s this really loud noise like the laptop is about to take off to space.

Please let me know if there’s anything I can do :smiley:

The laptop fan noise will be a consequence of using your GPU :slight_smile: so not much we can do about it
What you can do about it is to not render the scene when it is not necessary.

Like if user is not interacting with the mouse you should not call scene.render

okay noted :wink: Thanks for your help and sorry about the whole thing with GSAP. The version I was using before wasn’t even that old but who knows

1 Like