I am starting to work on some scene material optimization. To start I wanted to search through existing materials in scene when loading a new model, and if identical material name existed then instance the existing scene material and dispose of the freshly loaded one to save memory. However I can’t get materials to display their names with “.name”.
When importing meshes through assetManager, you can easily console out the entire material as exampled in the playground below with mesh.material(look in console)
However if you only want to output the name (or use it) it refuses to ever return the name when you mesh.material.name. This is the commented out line in the same playground.
Why does returning the name not work in this case?
Not entirely sure why or how but I think it is because of how the material is defined in whatever app the object was created in. If you look at the properties of mesh material (done for mesh[1] lines 21 to 23) in https://www.babylonjs-playground.com/#ZJYNY#233name does not appear.
It must appear in a property that is an object since the playground inspector can obtain it.
mesh[0] is a transformNode, so logically it has no material. That part makes sense to me and I can easily walk through my mesh tree and filter out transformNodes using getClassName().
The question is why the .name property won’t return a material name when doing a mesh[x].material.name - or for that matter .id also does the same thing, no display of the set property if using mesh[x].material.id.
Seems strange you can set something that you can not use, so I just must not be using it correctly. This is further evidenced by the playground (and debug layer) somehow reading it and if you know the name you can getMaterialByName().
It would appear the forEach loop silently breaks when trying to reach a property within a property which doesn’t exist.
(e.g. material.name on TransformNode (thus nothing is logged at all) )
Seems related to the playground, rather than BabylonJs directly,
I believe the playground use try…catch, but fails to report this error.
See this fiddle; https://jsfiddle.net/68to4kpj/
It logs “a”, “null”, then nothing.
unless you check for mesh.material, then it’ll log “d” aswell.
So TL;DR:
For some reason, the playground’s “handleException” function does not run.
The tasks in AssetsManager eats all the errors with a try/catch and manage the errors via Task.onError. You can either use Task.onError directly or use AssetsManager.onTaskError.
bghgary, JohnK, Calsa, and wulf11 were all right but I wasn’t able to synthesize their answers until I dug into it myself. Hopefully this helps people in the future!
Basically, the task.loadedMeshes[0].material is null. As Calsa noted, it is a transformNode so it has no material. Therefore when you try and console.log task.loadedMeshes[0].material.name, it is going to error out. As bghgary noted, the tasks are wrapped in a try catch so once the first console.log of material.name fails, it bails out and doesnt print out the of the mesh materials in task.loadedMeshes.
It still prints out all of the mesh.materials but if you notice, the first material printed is null.
@Calsa, you can see the names of the nodes in this playground. All i did was skip the first node.