Sounds nice
It means you have something wrong somewhere in the ImportMesh callback. Unfortunately I cannot help you without the complete code. Do some debugging, try removing some parts of the code and check if it works without. If it does, than it somewhere inside that part of code, if it still doesn’t then it’s somewhere else. You need to narrow down where the issue is.
This is an example of the whole code. I’ve been removing parts to see if it works but no luck so far. So I don’t know if you have any ideas @nogalo?
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html" charset="utf-8"/>
<style>
html, body {
overflow: hidden;
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
#renderCanvas {
width: 100%;
height: 100%;
touch-action: none;
}
</style>
<script src="https://cdn.jsdelivr.net/npm/babylonjs@4.0.3/babylon.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/babylonjs-loaders@4.0.3/babylonjs.loaders.min.js"></script>
<!-- For pointer events on tab/mob -->
<script src="https://code.jquery.com/pep/0.4.3/pep.js"></script>
</head>
<body>
<canvas id="renderCanvas" touch-action="none"></canvas>
<script>
var canvas = document.getElementById("renderCanvas"); // Get the canvas element
var engine = new BABYLON.Engine(canvas, true, { preserveDrawingBuffer: true, stencil: true }); // Generate the BABYLON 3D engine
/******* Add the create scene function ******/
var createScene = function () {
// Create the scene space
var scene = new BABYLON.Scene(engine);
scene.ambientColor = new BABYLON.Color3(.1, .1, .1);
/********** ARC ROTATE CAMERA **************************/
// Creates, angles, distances and targets the camera
var camera = new BABYLON.ArcRotateCamera("Camera", 0, 0, 10, new BABYLON.Vector3(0, 0, 0), scene);
// This positions the camera
camera.setPosition(new BABYLON.Vector3(-2, 2, -7));
// This attaches the camera to the canvas
camera.attachControl(canvas, true);
camera.lowerRadiusLimit = camera.upperRadiusLimit = camera.radius;
/*******************************************************/
// Add Light
var light = new BABYLON.HemisphericLight("HemiLight", new BABYLON.Vector3(0, 1, 0), scene);
light.intensity = .8;
light.specular = new BABYLON.Color3(0,0,0);
// Import meshes
BABYLON.SceneLoader.ImportMesh(["Cube", "Cylinder", "Cylinder.001", "Cylinder.002", "Cylinder.003"],
"https://raw.githubusercontent.com/ryannewelluk/3dcar/master/", "basic-redcar.glb", scene, function (meshes) {
var car = meshes[0];
car.scaling = new BABYLON.Vector3(0.25, 0.25, 0.25);
var block = meshes[1];
var frontWheel = meshes[2];
frontWheel.position.x = 5;
var frontWheel2 = meshes[3];
// GUI
var advancedTexture = BABYLON.GUI.AdvancedDynamicTexture.CreateFullscreenUI("UI");
advancedTexture.useInvalidateRectOptimization = false;
let actionManager = new BABYLON.ActionManager(scene);
block.actionManager = actionManager;
frontWheel.actionManager = actionManager;
frontWheel2.actionManager = actionManager;
//creat stack panel add it as root element to advancedTexture and scale it to 0
let panel = new BABYLON.GUI.StackPanel();
advancedTexture.addControl(panel);
panel.transformCenterY = 0;
panel.scaleX = 0;
panel.scaleY = 0;
//now add options (rect1, rect2) -> those are now children of the panel element, you can create these as many as you want and add it to panel
let rect1 = new BABYLON.GUI.Rectangle();
panel.addControl(rect1)
let text1 = new BABYLON.GUI.TextBlock();
rect1.addControl(text1);
let rect2 = new BABYLON.GUI.Button.CreateSimpleButton("but1", "Option1");
panel.addControl(rect2)
let rect3 = new BABYLON.GUI.Button.CreateSimpleButton("but2", "Option2");
panel.addControl(rect3)
let rect4 = new BABYLON.GUI.Button.CreateSimpleButton("but3", "Option3");
panel.addControl(rect4)
let rect5 = new BABYLON.GUI.Button.CreateSimpleButton("but4", "Option4");
panel.addControl(rect5)
//to avoid writing same code for every option in the stackPanel (because they use basically same properties, we can do something like this
//itarate through every child of panel element and set properties accordingly
for (let i = 0; i < panel.children.length; i++) {
let element = panel.children[i];
element.width = "160px";
element.height ="30px";
element.thickness = 0.2;
element.background = "grey";
element.alpha = 0.9;
element.fontSize = "16px";
element.color = "white";
}
text1.color = "black";
text1.fontSize = "24px"
let scaleXAnimation = new BABYLON.Animation("myAnimation", "scaleX", 60, BABYLON.Animation.ANIMATIONTYPE_FLOAT, BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT);
let scaleYAnimation = new BABYLON.Animation("myAnimation", "scaleY", 60, BABYLON.Animation.ANIMATIONTYPE_FLOAT, BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT);
var keys = [];
keys.push({
frame: 0,
value: 0
});
keys.push({
frame: 10,
value: 1
});
scaleXAnimation.setKeys(keys);
scaleYAnimation.setKeys(keys);
//panel is root element so need to switch this lines from rect1 to panel
panel.animations = [];
panel.animations.push(scaleXAnimation);
panel.animations.push(scaleYAnimation);
//create boolean switcher that controls the state of the gui element, is it shown or not, it's important to know if we are already in the menu or not
let isOpen = false;
//variable that stores current mesh that we clicked on
let currentMesh;
// red mat
let redMat = scene.getMaterialByName("Material.004");
// blue mat
let blueMat = new BABYLON.StandardMaterial("blueMat", scene);
blueMat.diffuseColor = new BABYLON.Color3.FromHexString("#7fcdff");
// orange mat
let orangeMat = new BABYLON.StandardMaterial("orangeMat", scene);
orangeMat.diffuseColor = new BABYLON.Color3.FromHexString("#FF4500");
// purple mat
let purpMat = new BABYLON.StandardMaterial("purpMat", scene);
purpMat.diffuseColor = new BABYLON.Color3.FromHexString("#800080");
actionManager.registerAction(
new BABYLON.ExecuteCodeAction(BABYLON.ActionManager.OnLeftPickTrigger, function(ev){
//if gui IS NOT open -> open it and enable selecting an option
if (!isOpen) {
//panel is root element so need to switch this line from rect1 to panel
panel.linkWithMesh(ev.meshUnderPointer);
text1.text = ev.meshUnderPointer.name;
//as before, show the gui element -> panel
scene.beginAnimation(panel, 0, 10, false)
//take the current mesh so you can apply functions to that exact mesh
currentMesh = ev.meshUnderPointer;
}
//when options from the panel are clicked do something
rect2.onPointerClickObservable.add(function() {
//example -> when first option is clicked call buttonOne function;
buttonOne(currentMesh, redMat);
});
rect3.onPointerClickObservable.add(function() {
//example -> when first option is clicked call buttonTwo function;
buttonTwo(currentMesh, blueMat);
});
rect4.onPointerClickObservable.add(function() {
//example -> when first option is clicked call buttonThree function;
buttonThree(currentMesh, orangeMat);
});
rect5.onPointerClickObservable.add(function() {
//example -> when first option is clicked call buttonFour function;
buttonFour(currentMesh, purpMat);
});
//set switcher to true
isOpen = true;
}));
actionManager.registerAction(
new BABYLON.ExecuteCodeAction(BABYLON.ActionManager.OnPointerOutTrigger, function(ev) {
//if gui IS open -> close it
if (isOpen) {
//close the panel
scene.beginAnimation(panel, 10, 0, false);
text1.text = "";
}
//set switcher to false
isOpen = false;
}));
});
//simple functions for options on panel
function buttonOne(mesh, material) {
console.log("button one is clicked");
mesh.material = material;
}
function buttonTwo(mesh, material) {
console.log("button two is clicked");
mesh.material = material;
}
function buttonThree(mesh, material) {
console.log("button three is clicked");
mesh.material = material;
}
function buttonFour(mesh, material) {
console.log("button four is clicked");
mesh.material = material;
}
return scene;
};
/******* End of the create scene function ******/
var scene = createScene(); //Call the createScene function
// Register a render loop to repeatedly render the scene
engine.runRenderLoop(function () {
scene.render();
});
// Watch for browser/canvas resize events
window.addEventListener("resize", function () {
engine.resize();
});
</script>
</body>
</html>
Well. ImportMesh method works properly in the playground. What I can say from the first look is that your render loop and resize function are outside of the createScene function. So move those into the createScene function. So somewhere after actionManager.registerAction() for example.
Also, as your error says that it cannot import meshes. Maybe you didn’t import babylon-loaders?
I was going by this tutorial which suggests having the render loop and resize function after the create scene function. I tried to move them but that gives me a blank page
Are you using npm modules ?
I haven’t but I could give it a go.
I tried swapping the babylonjs.loader.min.js for a local file and that just gave me a blank page
Okay. I might find a problem. Did you import babylonjs gui package?
I replicated your project. But I used npm packages. But I think it could be the same issue.
I imported GUI module like this
import * as GUI from ‘babylonjs-gui’;
And in your code GUI is created like this
var advancedTexture = BABYLON.GUI.AdvancedDynamicTexture.CreateFullscreenUI(“UI”);
And I got the same error message as you did. So Because I imported GUI as GUI as shown above, I don’t need the BABYLON part. So the working code is this.
var advancedTexture = GUI.AdvancedDynamicTexture.CreateFullscreenUI(“UI”);
And the error is gone (of course I needed to remove BABYLON. from every place I have GUI element).
Now, my guess is that you don’t need to remove BABYLON part if you imported gui package via CDN link. But if you haven’t do that, try to import it. And if it still doesn’t work try removing BABYLON part.
Before that, you can test if your scene is working when you completely remove GUI parts. So remove every part that contains BABYLON.GUI. And if it works we found the problem
Did the interactions start working with your version using npm packages?
I removed all the BABYLON.GUI sections but still got the unable to import meshes error.
I’ll try the import method next. Thanks again for all the help Sherlock Holmes
Everything is working properly on my end. Beside that GUI thing everything is working.
I am not sure what is going on on your end. I imported babylonjs, babylon-loaders and babylon-gui dependencies, and that’s it.
I didn’t have much luck with npm modules but I added this link and now the GUI loads:
Only difference seems to be some unwanted transparency on the materials.
yourMaterial.backFaceCulling = false
ah yes, thanks again
Hi @nogalo,
I don’t suppose you have any tips on how to close the GUI panel when one of the options is clicked?
Thank you!
https://www.babylonjs-playground.com/#YIU90M#118
Maybe something like this. Maybe not that elegant, but that’s the concept. I’ve expanded the button functions, and again with controlling switcher you control open/close animation of the GUI. .
Perfect! Thanks again @nogalo for helping me out