Material applied itself to a different entity!

This is quite funny, but I can’t understand it. I am messing with glbs to replace all the old fbx/JSON stuff. I finally sort of got textures to apply to an untextured (but properly unwrapped) glb model. I made sure this model and unwrapping is valid by exporting it with UVW and textures included.

So now I re-exported it and removed the export with texture option so I can dynamically change the texture in game. After some trial and error it worked, but it also applied the texture to a totally unrelated plane! I verified that my other models don’t seem to be affected. I verified this by first loading my other models and then the new glb model, and also by loading the glb model and then my other models (just to see if it was messing with all models).

So how can this be? When I set my glbs models material, it updates a totally unrelated pc.Entity('plane') !

Here is relevant code. Note my app ref is called this.engine

Create the plane

this.background = new pc.Entity('plane');
this.background.addComponent('model', {type: 'plane'});
this.background.setLocalScale(25, 25, 25);
this.engine.root.addChild(this.background);

Load the glb and apply the texture/material

// Load assets (this has been working for ~ 1 year with no side effects)
loadAsset(url, type){
    return new Promise((resolve, reject) => {
        this.engine.assets.loadFromUrl(url, type, (err, asset) => {
            if(err){
                reject(err);
            }
            else {
                resolve(asset)
            }
        });
    });
}

// Load glbs
loadGlbContainerFromUrl(url, options, assetName, callback) {
    var filename = assetName + '.glb';
    var file = {url, filename};    
    var asset = new pc.Asset(filename, 'container', file, null, options);
    asset.once('load', function (containerAsset) {
        if (callback) {
            callback(null, containerAsset);
        }
    });

    this.engine.assets.add(asset);
    this.engine.assets.load(asset);
    return asset;
}

// Test
let url = "/test.glb"
this.loadGlbContainerFromUrl(url, null, 'test', async (err, asset) => {
    let entity = new pc.Entity();
    entity.addComponent('model');
    entity.model.asset = asset.resource.model;
    entity.setPosition(2,2,2);
    this.pc_entity.addChild(entity);

    const texture = await this.loadAsset("/test.jpg", 'texture');    
    entity.model.material.diffuseMap = texture.resource;
    entity.model.material.update();
});

Without a reproducible, my best guess is that both the GLB model and plane model are using the same default material.

Therefore, when you modify it, it affects the appearance of both.

That makes sense. I was trying this but it never seems to update the material. Am I missing something?

        const texture = await this.loadAsset("/test.jpg", 'texture');    
        const material = new pc.StandardMaterial();
        material.diffuseMap = texture.resource;
        material.update();
        entity.model.material = material;

Hm. Ok. I did this and it worked. I don’t really understand it, but… ok!

entity.model.meshInstances[0].material = material;

entity.model.asset does not apply to model components that use type ‘asset’ which is the case here. https://developer.playcanvas.com/en/api/pc.ModelComponent.html#material

You would need to apply the material to the mesh instances directly.

1 Like

Thanks! I wonder what your opinion on this is: Would it be better to export a GLB model with many (diffuse) textures and toggle them (if that’s even possible) or continue the approach I am taking of loading textures separately and creating/applying materials to an untextured model dynamically.

If the former is even possible I think it would be a better idea, I would have less assets to manage, etc. I was reading through this post


and I thought it mentioned something like that.

I’m not familiar with the export process in tools to GLB. If you can export more materials than what the model is using then yes, it’s a viable solution. ‘Better’ depends on your workflow. If you are using the engine only then it allows you to set the material properties in the 3D modelling tool rather than by code.