Mesh.material.name wont display name?

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?

See example:
https://www.babylonjs-playground.com/#ZJYNY#232

For some reason you have to start on loadedMeshes[1] !
The first item at index 0 return null !

EDIT the following is WRONG as can be seen using https://www.babylonjs-playground.com/#ZJYNY#236. Reply left in so other comments make sense, otherwise IGNORE

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#233 name does not appear.

It must appear in a property that is an object since the playground inspector can obtain it.

You should be able to discover how by doing

console.log(task.loadedMeshes[1].material)

and examining the properties displayed.

2 Likes

mesh[0] is the root parent node for all the other meshes

1 Like

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().

Strange this works https://www.babylonjs-playground.com/#ZJYNY#235

but un-comment line 14 and it doesn’t.

Currently have no idea why!!!

Also this works https://www.babylonjs-playground.com/#ZJYNY#237 but un-comment line 31 and it doesn’t

Using a for…next loop https://www.babylonjs-playground.com/#ZJYNY#238 it works, so something strange about for…each???

Needs somebody more knowledgeable than me to solve it - possibly not a BJS problem.

Also note that the following is not really needed in a PG

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

@JohnK & @Calsa

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.

2 Likes

It’s doing the same thing on my local build, which is checked out latest stable, so may not be an issue confined to the playground.

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.

See Task state and error handling which could perhaps use a bit more info.

3 Likes

That would explain it :slight_smile:

Hello,

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.

1 Like