Good day everyone. I’m currently facing a problem with saving a meshes as a babylon file.
Right now, I have done the following:
- I have a model of a lion with panels, the panels are detachable from the lion’s body and can be designed with flowers (which are really planes with materials/ diffuse texture set on it). What I do is I clone the flower on the book when it is clicked using mesh.clone(cloneName) method. See image below:
- What I do is after placement of flower on the panel, the user can choose to save his current progress. There is no problem with I place unique flowers on each panel like the image below:
With the above sample, I encounter no problem when saving it and importing it to the scene on reload.
- I only encounter the error when I design a panel with duplicated of one type of flower clicked like in the image below:
This is how I save the designed panel / serialize the meshes:
function save_designed_panels(filename) {
designCamera.detachControl(canvas);
var serializedMesh;
//the mapping of the panel:flowers will be saved here
let savedFlowersList = {};
//mapping of the serialized mesh will be saved here
var meshes_to_save = {
"materials": [],
"geometries": {
"boxes":[],
"spheres":[],
"cylinders":[],
"toruses":[],
"grounds":[],
"planes":[],
"torusKnots":[],
"vertexData":[]
},
"meshes": []
};
if(objectUrl) {
window.URL.revokeObjectURL(objectUrl);
}
//for each flower mesh placed in each panel taken from the flowerspanelsmap, serialize each mesh
for (const [panel,val] of flowersPanelsMap.entries()) {
if(val.size>0){
serializedMesh = BABYLON.SceneSerializer.SerializeMesh(panel,false,true);
for (let i=0;i<serializedMesh["meshes"].length;i++) {
meshes_to_save["materials"].push(serializedMesh["materials"][i]);
meshes_to_save["geometries"]["vertexData"].push(serializedMesh["geometries"]["vertexData"][i]);
meshes_to_save["meshes"].push(serializedMesh["meshes"][i]);
}
}
}
//for each flower mesh placed in each panel taken from the flowerspanelsmap, serialize each mesh
//the modified_panels_list contains the panels:flowers mapping taken from the database, only update the flowers in the db with updated flowers
for (const [panel,val] of flowersPanelsMap.entries()) {
if(modified_panels_list.has(panel.name)){
let temp = [];
for(const a of val.values()){
temp.push(a.name);
}
if(temp.length == 0) temp = "0";
savedFlowersList[panel.name] = temp;
}
}
//convert the meshes to blob format and save as babylon file
var strMesh = JSON.stringify(meshes_to_save);
var blob = new Blob ( [ strMesh ], { type : "octet/stream" } );
if (filename.toLowerCase().lastIndexOf(".babylon") !== filename.length - 8 || filename.length < 9){
filename += ".babylon";
}
//post to backend to save the user's progress
if(blob){
$.ajax({
type: "POST",
url:urlDesignPanel,
data:{
uid: userId,
designPath:userId+"_designedPanel.babylon",
babylonFile:strMesh,
flowersList:savedFlowersList,
_token:token
},
success: function(result){
Swal.fire({
width: '10vw',
padding: '3em',
background: 'rgba(8, 64, 147, 0.6) url(front/images3D/designScene/trevorSaved.png)',
title: '\n\n\n\nYour progress has been saved.',
showConfirmButton: false,
position: 'top-end',
timer: 3000,
customClass: {
popup: 'trevor-popup-class',
}
});
designCamera.attachControl(canvas,true);
savedFlowersList = {};
is_design_saved = true;
},
error: function(result){
Swal.fire({
width: '10vw',
padding: '3em',
background: 'rgba(8, 64, 147, 0.6) url(front/images3D/designScene/trevorSaved.png) ',
title: '\n\n\n\nOops...something went wrong. Your progress was not saved.',
showConfirmButton: false,
position: 'top-end',
timer: 3000,
customClass: {
title: 'error-title-class',
popup: 'trevor-popup-class',
},
});
}
});
}
}
And this is how I import the panels on page access:
function load_saved_game(){
Promise.all([
BABYLON.SceneLoader.ImportMeshAsync(null, "storage/saveState/designPanel/", load_filename, designScene).then(function (result) {
result.meshes.forEach(function(m){
if(mbayePanelsMap.has(m.name)){
m.setParent(mbayeDesign_object);
//mbayePanelsMap is a fresh mapping of the panels:flowers loaded from the database when the page is loaded
if(mbayePanelsMap.get(m.name) !== null) mbayePanelsMap.get(m.name).dispose();
m.isPickable = true;
m.material.emissiveColor = new BABYLON.Color3(0,0,0);
mbayePanelsMap.set(m.name, m);
let children = set_panel_children(m._children);
flowersPanelsMap.set(m, children);
}
});
}),
]).then(() => {
isProgressLoaded = true;
});
}
And this is the error I am getting when I load the page when I have previously designed a panel with flowers of the same type.
I am not sure why I am getting this error and I also tried loading the exported babylon file in sandbox and it throws me error that id is null. Please guide me where I am doing wrong. Thank you.
Page load error:
Sandbox error:
For reference, this is how I clone the black flower from the book. onPointerDown, I call this function:
function create_black_flower_copy(theFlower){
//create a clone of the flower clicked
let theFlowerCopy = theFlower.clone(theFlower.name);
theFlowerCopy.material = theFlower.material.clone(theFlower.name+flowerCtr+“Matl”);
theFlowerCopy.material.id = theFlowerCopy.material.name;
//i have also tried createInstance but it behaves differently
// let theFlowerCopy = theFlower.createInstance(theFlower.name + flowerCtr);
// theFlowerCopy.setParent(theFlowerCopy.parent)
flowerCtr++;
let flowerHasParent = false;
theFlowerCopy.id = theFlowerCopy.id + "_"+theFlowerCopy.uniqueId;
;
//if the active camera is panel camera or focus camera
if(designScene.activeCamera === panelCamera ){
if(theFlower.parent === bookLeftPages) flowerHasParent = true;
}else{
if(theFlower.parent === bookLeftPages) flowerHasParent = true;
}
//if the clone has a parent, set position x and y depending if the camera is panel or focus
if(flowerHasParent){ //if focus camera
theFlowerCopy.position.y += 50;
theFlowerCopy.position.x -= 50;
theFlowerCopy.rotation = new BABYLON.Vector3(BABYLON.Tools.ToRadians(155),BABYLON.Tools.ToRadians(0),BABYLON.Tools.ToRadians(0));
theFlowerCopy.setParent(null);
}else{
theFlowerCopy.position.y += 2.5;
theFlowerCopy.position.x += 0.1;
}
//increment the current flower selection count
flowerSelectionCount++;
if(theCurrentFlower.obj) theCurrentFlower.obj.showBoundingBox = false;
//attach the position gizmo to the flower clone
designGizmoManager.positionGizmoEnabled = true;
designGizmoManager.attachToMesh(theFlowerCopy);
//set the clone as the current flower and show bounding box
theCurrentFlower.obj = theFlowerCopy;
theCurrentFlower.obj.showBoundingBox = true;
//add the flower to the selected flowers map
selectedFlowersMap.set(theFlowerCopy.uniqueId, theFlowerCopy);
set_gizmo_style("#positionGizmo");
$("#gizmoToolsDiv").css('display','flex');
designGizmoManager.positionGizmoEnabled = true;
designGizmoManager.attachToMesh(theFlowerCopy);
}