Question regarding AssetLinkedNode and cloning

Hi

When we clone a spatial directly using clone( boolean cloneMaterial ), it adds an IdentityCloneFunction<Material> in the cloner to prevent materials being cloned. But when loading via asset manager it calls clone() methods which internally calls clone(true);

So suppose I have a .j3o binary file which has 10 children (of type AssetLinkedNode) and all of them have same ModelKey.
Now when I load that j3o file with asset manager, it will clone the material for all of them.

How I can change this behavior, so based on my ModelKey I can tell asset manager to clone or not clone Material ? (without needing to override clone() method)

Thanks

Why don’t you want the materials cloned?

For sake of performance !! :relaxed:

So first let me ask it this way,

Will it have any significant impact on performance or memory ?
I mean I thought if we share same material between all clones (Non animated models of course), it will be performance wise ? Otherwise I do not care about it if get cloned or not.

As long as you don’t set the defines different on some of the materials (in which case cloning would have been bad anyway) then they will share the same compiled shader, get sorted together in the opaque bucket, etc. just like if they had the same material.

Yes, there might be a little extra memory used for the material parameters. You’d probably have to have many thousands of objects before that would matter much and then likely the thousands of objects are overshadowing that anyway (and then why not batch?).

So you might be attempting to needlessly micro-optimize. And if that’s the case, and you still care, it would be pretty trivial to write a scene graph visitor that visits every Geometry and replaces its material with a common one.

http://javadoc.jmonkeyengine.org/com/jme3/scene/SceneGraphVisitorAdapter.html

Something like:

class MungeMaterialsVisitor extends SceneGraphVisitorAdapter {
    Map<Material, Material> index = new HashMap<>();

    public void visit( Geometry geom ) {
        Material m = geom.getMaterial();
        if( index.containsKey(m) ) {
            geom.setMaterial(index.get(m));
        } else {
            index.put(m, m);
        }
    }
}

If Material.equals() works like that… else you might have to use the asset key as the map key.

1 Like

Cool
Thank you very much for explaining.
Then it will be fine, because they use same material definition, so I will let them being cloned for now.

If any time I needed to care about micro-optimization, then I will use the scene graph visitor for switching materials.:slight_smile:

I use a similar visitor for a lot of my own stuff because I swap some existing materials with my own or in some cases force certain parameters on common materials and stuff. (Some of that can be more easily done with material overrides.)

The most common case is when I go and replace the regular lighting shader with my scattered lighting shader from SimFX and then apply all of the atmospheric parameters (which I suppose I could now do through material overrides… hmm…)

1 Like