Hi.
As the title say.
I’m haveing a mesh with some matedata properties in scene, and I export it as glb, unfortunatelly on import glb file that metadata is missing.
I read somewhere that by default is not possible to add these meta to glb, but I saw that glb/gltf has some ‘extras’ property.
My question is: On exporting as gltf/glb if exported meshes contain metadata, can I in someway to add them to gltf/glb nodes as extras or something like this?
One more question, related to this exporter.
Can we add draco compression on it or not?
We can…the question is when
On exporting as gltf/glb if exported meshes contain metadata, can I in someway to add them to gltf/glb nodes as extras or something like this?
Not currently. It will be tricky to implement since Babylon objects don’t match 1:1 to glTF objects. Do you have a specific scenario?
Good question as well
Yes, unfortunatelly I think is pretty particular.
I allow the user to upload different types of meshes, like obj, stl, babylon or gltf put them together and export as new mesh.
For this new mesh I want to add few flags as meta, like, if it can be rotate in a specific axis, and more. So on import into second scene, simply check meta to know which functions are alowed.
Sounds reasonable. Can you file a feature request on GitHub?
If i can chime in here… Yes you can add metadata to your GLTF JSON in extras or your can create a real GLTF Extension and add your metadata there. @bghgary made excellent GLTF parsing hooks that you can use in your custom Babylon GLTF Importer Extension. This is the heart and soul of how the Babylon Toolkit - 2019 Edition is working. I serialize Unity data as extra metadata using my CVTOOLS_unity_metadata extension.
Then in Babylon i created a GLTF Importer Extension to properly parse all that gltf extra metadata:
this is what my extension looks like so far:
const CVTOOLS_NAME = "CVTOOLS_unity_metadata";
/**
* Babylon canvas tools loader class
* @class CVTOOLS_unity_metadata
* [Specification](https://github.com/MackeyK24/glTF/tree/master/extensions/2.0/Vendor/CVTOOLS_unity_metadata)
*/
class CVTOOLS_unity_metadata implements BABYLON.GLTF2.IGLTFLoaderExtension {
/** The name of this extension. */
public readonly name = CVTOOLS_NAME;
/** Defines whether this extension is enabled. */
public enabled = true;
private _loader: BABYLON.GLTF2.GLTFLoader;
/** @hidden */
constructor(loader: BABYLON.GLTF2.GLTFLoader) {
this._loader = loader;
}
/** @hidden */
public dispose() {
delete this._loader;
}
/** @hidden */
public onLoading(): void {
//console.log("CVTOOLS - Loading Scene");
}
/** @hidden */
public onReady(): void {
//console.log("CVTOOLS - Scene Ready");
}
/** @hidden */
public loadSceneAsync(context: string, scene: BABYLON.GLTF2.Loader.IScene): BABYLON.Nullable<Promise<void>> {
if (scene.extras != null && (<any>scene.extras).metadata != null) {
const metadata:any = (<any>scene.extras).metadata;
// ..
// console.log("CVTOOLS - Parsing Scene Properties: " + scene.name);
// console.log(metadata);
// ..
// Setup Scene Clear Coloring
// ..
this._loader.babylonScene.autoClear = true;
this._loader.babylonScene.ambientColor = BABYLON.Color3.Black();
if (metadata.hasOwnProperty("clearcolor")) {
this._loader.babylonScene.clearColor = BABYLON.Utilities.ParseColor4(metadata.clearcolor);
}
// ..
// Setup Scene Fog Information
// ..
if (metadata.hasOwnProperty("fogmode")) {
let fogmode:number = metadata.fogmode;
if (fogmode > 0) {
this._loader.babylonScene.fogMode = fogmode;
this._loader.babylonScene.fogEnabled = true;
if (metadata.hasOwnProperty("fogdensity")) {
this._loader.babylonScene.fogDensity = metadata.fogdensity;
}
if (metadata.hasOwnProperty("fogstart")) {
this._loader.babylonScene.fogStart = metadata.fogstart;
}
if (metadata.hasOwnProperty("fogend")) {
this._loader.babylonScene.fogEnd = metadata.fogend;
}
if (metadata.hasOwnProperty("fogcolor")) {
this._loader.babylonScene.fogColor = BABYLON.Utilities.ParseColor3(metadata.fogcolor);
}
}
}
// ..
// Setup Scene Ambient Lighting
// ..
if (metadata.hasOwnProperty("ambientlighting")) {
let ambientlighting:boolean = metadata.ambientlighting;
if (ambientlighting === true) {
if (metadata.hasOwnProperty("ambientskycolor")) {
const lightname:string = "Ambient Light";
let ambientlight:BABYLON.HemisphericLight = this._loader.babylonScene.getLightByName(lightname) as BABYLON.HemisphericLight;
if (ambientlight == null) {
ambientlight = new BABYLON.HemisphericLight(lightname, new BABYLON.Vector3(0, 1, 0), this._loader.babylonScene);
}
ambientlight.diffuse = BABYLON.Utilities.ParseColor3(metadata.ambientskycolor);
if (metadata.hasOwnProperty("ambientlightintensity")) {
ambientlight.intensity = metadata.ambientlightintensity;
}
if (metadata.hasOwnProperty("ambientspecularcolor")) {
ambientlight.specular = BABYLON.Utilities.ParseColor3(metadata.ambientspecularcolor);
}
if (metadata.hasOwnProperty("ambientgroundcolor")) {
ambientlight.groundColor = BABYLON.Utilities.ParseColor3(metadata.ambientgroundcolor);
}
}
}
}
// ..
// Setup Scene Physics Engine Library
// ..
if (metadata.hasOwnProperty("enablephysics")) {
let enablephysics:boolean = metadata.enablephysics;
if (enablephysics === true) {
// TODO: Setup Physics And Gravity
// console.log("CVTOOLS - Parse Physics Engine Properties");
}
}
// ..
// TODO: Load Six-Sided Skybox Textures
// ..
// TODO: Load HDR-DDS Environment Texture
// ..
// TODO: Load Navigation Mesh Interfaces
}
// ..
return this._loader.loadSceneAsync(context, scene);
}
/** @hidden */
public loadNodeAsync(context: string, node: BABYLON.GLTF2.Loader.INode, assign: (babylonMesh: BABYLON.Mesh) => void): BABYLON.Nullable<Promise<BABYLON.Mesh>> {
return this._loader.loadNodeAsync(context, node, (mesh: BABYLON.Mesh) => {
if (node.extras != null && (<any>node.extras).metadata != null) {
const metadata:any = (<any>node.extras).metadata;
// ..
// console.log("CVTOOLS - Parsing Mesh Node: " + mesh.name);
// console.log(metadata);
// ..
if (mesh.name == null || mesh.name === "") {
mesh.name = "Mesh." + mesh.id;
}
mesh.metadata = metadata;
if (metadata.components != null) {
const components:any[] = metadata.components;
// ..
// Parse Node Components
// ..
if (components != null && components.length > 0) {
let scripts:any[] = [];
components.forEach((component:any) => {
if (component != null) {
switch (component.alias) {
case "script":
scripts.push(component);
break;
case "camera":
CVTOOLS_unity_metadata.SetupCameraComponent(mesh, component, this._loader.babylonScene);
break;
case "light":
CVTOOLS_unity_metadata.SetupLightComponent(mesh, component, this._loader.babylonScene);
break;
}
}
});
// ..
// TODO: Store In Global List Then After All Nodes Process Add Script Components in Script Executtion Order
// ..
if (scripts.length > 0) {
//scripts.forEach((script) => { CanvasTools.ParseScriptNode(app, entity, data, resources, script); });
}
}
}
}
// ..
assign(mesh);
});
}
/** @hidden */
public loadMaterialPropertiesAsync(context: string, material: BABYLON.GLTF2.Loader.IMaterial, babylonMaterial: BABYLON.Material): BABYLON.Nullable<Promise<void>> {
const promises = new Array<Promise<any>>();
promises.push(this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial));
// ..
// console.log("CVTOOLS - Parsing Material Info: " + material.name);
// console.log(material);
// ..
// Parse Material Lightmap Textures
// ..
const materialJson:any = material;
const commonConstant:any = (materialJson.hasOwnProperty("commonConstant")) ? materialJson.commonConstant : null;
if (commonConstant != null) {
if (commonConstant.lightmapTexture) {
promises.push(this._loader.loadTextureInfoAsync(`${context}/lightmapTexture`, commonConstant.lightmapTexture, (texture) => {
if (babylonMaterial instanceof BABYLON.PBRMaterial) {
let pbrMaterial:BABYLON.PBRMaterial = babylonMaterial as BABYLON.PBRMaterial;
pbrMaterial.lightmapTexture = texture;
pbrMaterial.useLightmapAsShadowmap = true;
} else if (babylonMaterial instanceof BABYLON.StandardMaterial) {
let stdMaterial:BABYLON.StandardMaterial = babylonMaterial as BABYLON.StandardMaterial;
stdMaterial.lightmapTexture = texture;
stdMaterial.useLightmapAsShadowmap = true;
}
}));
}
}
// ..
// TODO: Parse Terrrain Splatmap Textures
// ..
return Promise.all(promises).then(() => { });
}
//////////////////////////////////////////////////////////////////////////////////////////////////////
// Canvas Tools Private Parsing Worker Functions
//////////////////////////////////////////////////////////////////////////////////////////////////////
private static SetupCameraComponent(mesh:BABYLON.Mesh, component:any, scene:BABYLON.Scene):void {
let label:string = mesh.name + ".Rig";
let camera:BABYLON.UniversalCamera = new BABYLON.UniversalCamera(label, BABYLON.Vector3.Zero(), scene);
camera.parent = mesh;
camera.rotation = new BABYLON.Vector3(0, Math.PI, 0);
camera.checkCollisions = false;
let cameratype:number = component.hasOwnProperty("projection") ? component.projection : 0;
switch (cameratype) {
case 0: { // PERSPECTIVE
camera.mode = BABYLON.Camera.PERSPECTIVE_CAMERA;
if (component.hasOwnProperty("perspectiveyfov")) {
camera.fov = component.perspectiveyfov;
}
if (component.hasOwnProperty("perspectiveznear")) {
camera.minZ = component.perspectiveznear;
}
if (component.hasOwnProperty("perspectivezfar")) {
camera.maxZ = component.perspectivezfar;
}
break;
}
case 1: { // ORTHOGRAPHIC:
camera.mode = BABYLON.Camera.ORTHOGRAPHIC_CAMERA;
if (component.hasOwnProperty("orthoxmag")) {
camera.orthoLeft = -component.orthoxmag;
camera.orthoRight = component.orthoxmag;
}
if (component.hasOwnProperty("orthoymag")) {
camera.orthoBottom = -component.orthoymag;
camera.orthoTop = component.orthoymag;
}
if (component.hasOwnProperty("orthoznear")) {
camera.minZ = component.orthoznear;
}
if (component.hasOwnProperty("orthozfar")) {
camera.maxZ = component.orthozfar;
}
break;
}
}
// ..
// Attach Camera Rig To Mesh
// ..
(<any>mesh).cameraRig = camera;
}
private static SetupLightComponent(mesh:BABYLON.Mesh, component:any, scene:BABYLON.Scene):void {
console.log("===> TODO: Create Node Light Rig: " + mesh.name);
}
}
BABYLON.GLTF2.GLTFLoader.RegisterExtension(CVTOOLS_NAME, (loader) => new CVTOOLS_unity_metadata(loader));
If that helps in any way to get your stuff going
This can be done by adding an issue on github, right?
Thanks @MackeyK24. I’ll try this understand your class and adapt to my requirements.
Yes, open an issue here: Issues · BabylonJS/Babylon.js · GitHub