[SOLVED] Multiple materials on same meshinstance - Looking to change an assetreg material

I want to control the different materials of a meshinstance. At top and initialize I declare:

Raycast.attributes.add("materials", {type: "asset", assetType: "material", array: true, title: "Materials"});

// initialize code called once per entity
Raycast.prototype.initialize = function() {
     this.materialIndex = 0;
  • and at doRaycast I seek to change the material on my model’s shoulder, by altering the asset material:
Raycast.prototype.doRaycast = function (screenX, screenY) { 
     this.materialIndex = (this.materialIndex + 1) % this.materials.length;
    var materialAtList = this.materials[this.materialIndex]; 
    // The pc.Vec3 to raycast from (the position of the camera)
    var from = this.entity.getPosition();

    // The pc.Vec3 to raycast to (the click position projected onto the camera's far clip plane)
    var to = this.entity.camera.screenToWorld(screenX, screenY, this.entity.camera.farClip);

    // Raycast between the two points and return the closest hit result
    var result = this.app.systems.rigidbody.raycastFirst(from, to); try{ console.log('RC DRC:'+result.name);}catch(err){}
    // If there was a hit, store the entity
    if (result) {
        var hitEntity = result.entity; 
        if(hitEntity.name === "Capsule_UpperRightShoulder") { 
          var materialSta = new pc.StandardMaterial(); materialSta = pc.app.assets.get(38251253);
           this.entityKvindeOAMAT =materialSta; console.log("this.entityKvinde: "+ this.entityKvindeOAMAT);
           this.entityKvindeOAMAT.material = materialAtList.resource; this.entityKvindeOAMAT.material.update();

The console.log at ‘this.entityKvindeOAMAT’, does provide me with an [Object object], but the material does not ‘update’?

Several issues and questions here.

var materialSta = new pc.StandardMaterial();

This line is irrelevant as you assign materialSta to a material asset on the very next line.

materialSta = pc.app.assets.get(38251253);

There’s no such property material on an asset. You probably meant resource here:

this.entityKvindeOAMAT.material = materialAtList.resource;

Changing the value of the an asset resource to another asset resource is dangerous as you now have two assets handling the same resource.

It would be easier to go through the mesh instances of Entity, find the meshes with the material that you would like to replace and replace them.

Yes, I know I got colorblind after a lot of forum researching already.
But it is also important to stress that, I am not trying to run through the meshinstances of the model.
I want to run through the ‘Asset materials’ of one of the model’s meshinstances only:

Title: “Multiple materials on same meshinstance …”

Above are the imported materials that came along with the FBX model. Many of them are put on the bodyskin-meshinstance only (where as the rest are put on eyes, eyelashes etc … but those meshinstances are irrelevant - I am only interested in changing bodyskin materials … if I had to cut up the bodyskin’s vertices the model will crack open at slices while animating :-/ )

At this illustration, my approach should be more accessible - cf blue markers:

Top left: by collision/rigibody raycast I want to click a green capsule (later with invisible material), in order to change various body parts on the skin (the body meshinstance). In this case the stomach/breast is to be changed to a grey (as shown).
Bottom left: The two top used registry assets. But actually one/you should notice all the bottom assets ‘MBLab_skin2_ …’, being the materials at stake. All of those are from the skin (the body meshinstance).
Top right: Here it says ‘Meshinstances[19]’, as if they are to be accessed ‘over there’ (by script).
Bottom left: The index of [13], is where I have manually changed the stomach/breast - I need to do this by script.

I actually came upon an old post, where I used nodes (as shown by you) in relation to an gtlf-file that had multiple meshes.
Here I am wondering if nodes are relevant, while accessing the same-mesh materials?

As far as I can tell from the screenshots, is that you are trying to change one material of a single mesh instance. In this case, [13]. Is that correct?

The model instance in Blender;

Both part of the same instance. I want to access and alter these two materials;

  • of which (after export and import) lays in the asset registry.
    Yes, I understand you concern about that kind of change, but the surface rendering should only get pink/NaN temporarely, in case I get to a workaround place >> where a new material can be set on the slot … I would hope.

Are those two materials listed in this screenshot?

Yes, 4th from the bottom and 8th from the bottom :slight_smile:


  • in asset view to the left

I rephrase, are those materials listed in the meshinstance list on the right?

  • the scroll was out of space vertically

Cool, as they are in that list, that means you can access the meshinstance and change that material via the model component.

There’s one material to one meshinstance. AFAIK, you can’t have multiple materials on a single mesh instance.

Basically, we are back to this solution.

->> hmm … how do you explain ‘the editor screendump’ where I made the front; dark grey then? (there are only 10 meshes, but slots from 11 to 19 as well)

Will try a little further myself, but thanks anyway :slight_smile:

In PlayCanvas, there is a mesh instance per material. As you have 20 materials, you have 20 meshinstances on this mesh.

 var entityK = this.app.root.findByName("LightCookie_VersAfKvinde__FullBody");
 var meshInstances = entityK.model.meshInstances; console.log('length:'+meshInstances.length);

equals this in console


How about that. Not sure what to tell you here as the code in the engine shows that a mesh instance only has one material: https://github.com/playcanvas/engine/blob/master/src/scene/mesh-instance.js#L80

Is it possible to share that model? I would like take a peek at it?

I can do that ( - made it now, but will send it later)

Otherwise I am just trying to access very simply, like accessing the arm or stomach material like this:
pc.app.assets.find(38251248).diffuse = new pc.Color(1,0,1);
or …
this.app.assets.find(38251248).diffuse = new pc.Color(1,0,1);

As long as you know what materials they are, you can do that. The example that was posted above seemed to be about swapping materials rather than modifying an existing one which is harder as you need to assign the material back to the meshinstance.

Lays beneath ‘Models’:

pc.app.assets.find(‘38251248’).diffuse = new pc.Color(1,0,1);

ends out with:

[raycast.js?id=38253976&branchId=062396da-e562-458c-8459-ba900f1730e8:83]: Uncaught TypeError: Cannot set property ‘diffuse’ of undefined

Check the API.

find expects the name of the asset, not the id.

You want https://developer.playcanvas.com/en/api/pc.AssetRegistry.html#get
Which takes a number, not a string.

The example scene you sent me has 4 meshinstances which is inline with one meshinstance for one material