Extending material for easier use

Ok, for last project I was doing with JME3, I found out that its really useful for me to extend Material with some other functions, to make its use easier. This is because I mostly like to play with dynamic materials and change material properties in code. Also I like to abstract all the stuff that can change in the future of the engine, so I have only one place to change this (was useful for example when you omitted m_ prefix before shader variables). So here are my helper classes, which I used, don’t know if they should be included in the engine or not, its just my proposition to make use of the materials easier. These classes aren’t complete in any way!! Lots of other functions could be added, but probably they should be added to base Material class or to subclasses of it, like LightingMaterial and UnshadedMaterial, which are imho most commonly used materials.

The code:

[java]

package net.marbley.data.material;



import com.jme3.asset.AssetManager;

import com.jme3.material.Material;

import com.jme3.material.RenderState.BlendMode;

import com.jme3.material.RenderState.FaceCullMode;

import com.jme3.texture.Texture;

import com.jme3.texture.Texture.WrapMode;



public abstract class AbstractMaterialExt extends Material

{

private static AssetManager ASSET_MANAGER;



public AbstractMaterialExt(String materialPath)

{

super(ASSET_MANAGER, materialPath);

}



/**

  • This function must be called before using any subclasses of this abstract
  • class!

    *
  • @param assetManager

    */

    public static void setAssetManager(AssetManager assetManager)

    {

    ASSET_MANAGER = assetManager;

    }



    public void enableAlphaBlendMode()

    {

    getAdditionalRenderState().setBlendMode(BlendMode.Alpha);

    }



    public void disableBackFaceCulling()

    {

    getAdditionalRenderState().setFaceCullMode(FaceCullMode.Off);

    }



    protected Texture loadTexture(String texName)

    {

    Texture tex = ASSET_MANAGER.loadTexture(texName);

    tex.setWrap(WrapMode.Repeat);

    return tex;

    }

    }

    [/java]



    [java]

    package net.marbley.data.material;



    import com.jme3.math.ColorRGBA;



    public final class LightingMaterial extends AbstractMaterialExt

    {

    private static final String matPath = "Common/MatDefs/Light/Lighting.j3md";



    public LightingMaterial()

    {

    super(matPath);



    setBoolean("UseMaterialColors", true);

    setBoolean("UseAlpha", true);

    }



    public void setLowQuality(boolean lQuality)

    {

    setBoolean("LowQuality", lQuality);

    }



    public void setHighQuality(boolean hQuality)

    {

    setBoolean("HighQuality", hQuality);

    }



    public void setAmbientColor(ColorRGBA color)

    {

    setColor("Ambient", color);

    }



    public void setDiffuseColor(ColorRGBA color)

    {

    setColor("Diffuse", color);

    }



    public void setSpecularColor(ColorRGBA color)

    {

    setColor("Specular", color);

    }



    public void setShininess(float shininess)

    {

    setFloat("Shininess", shininess);

    }



    public void setGlowColor(ColorRGBA color)

    {

    setColor("GlowColor", color);

    }



    public void setDiffuseMap(String texName)

    {

    setTexture("DiffuseMap", loadTexture(texName));

    }



    public void setNormalMap(String texName)

    {

    setTexture("NormalMap", loadTexture(texName));

    }



    public void setSpecularMap(String texName)

    {

    setTexture("SpecularMap", loadTexture(texName));

    }



    public void setParallaxMap(String texName)

    {

    setTexture("ParallaxMap", loadTexture(texName));

    }



    public void setGlowMap(String texName)

    {

    setTexture("GlowMap", loadTexture(texName));

    }

    }

    [/java]



    [java]

    package net.marbley.data.material;



    import com.jme3.math.ColorRGBA;

    import com.jme3.texture.Texture;



    public final class UnshadedMaterial extends AbstractMaterialExt

    {

    private static final String matPath = "Common/MatDefs/Misc/Unshaded.j3md";



    public UnshadedMaterial()

    {

    super(matPath);

    }



    public void setColor(ColorRGBA color)

    {

    setColor("Color", color);

    }



    public void setColorMap(String texName)

    {

    setTexture("ColorMap", loadTexture(texName));

    }



    public void setColorMap(Texture texture)

    {

    setTexture("ColorMap", texture);

    }



    public void setLightMap(String texName)

    {

    setTexture("LightMap", loadTexture(texName));

    }



    public void setGlowMap(String texName)

    {

    setTexture("GlowMap", loadTexture(texName));

    }



    public void setGlowColor(ColorRGBA color)

    {

    setColor("GlowColor", color);

    }

    }

    [/java]



    Again, these classes are in no way complete, but I would really appreciate your opinion on this matter, and if such classes would be considered for including in the engine, I would be more than happy to enrich them and make them complete…

Another thing I forgot in previous post: setting asset manager to the material was mostly useful for me, because I find it cumbersome to pass assetManager from SimpleApplication to all the other classes and subclasses, where I instantiate my game object and actually use assetManager. I don’t really know what is the best solution for this, but I kinda miss some static public getter for assetManager in Application or something. :slight_smile:

No, this is definitely not something we want to add to the classes. Giving every object you might use a link to the assetManager is pretty much a bad hack, your game system should provide you with the assetmanager in the right places when you need it. Also having a Material object that is fixed to one base material is not very good, this is one of the big problems with extending, you cannot e.g. change a Lighting material to an unshaded one w/o replacing the object.

I’m using a singleton class for that purpose (AssetManager).



In the Object i store every relevant references to important objects and stuff… Dont know if this is the best way to handle things but i kinda like it. ^^"

I use this procedure because I use pythonscripts in my application and i can access everything through this beautifull little class… :smiley:

Yeah, basically if you extend some jME class you probably do it wrong.

Ok which classes are meant to be extended except for SimpleApplication and AbstractControl or smth? :slight_smile:

Application and Abstract classes

I think what we will do for the core, is have some material builder class like



[java]LightingMaterialBuilder lmb = new LightingMaterialBuilder();

lmb.setDiffuseMap("Textures/Blah.png");

lmb.setShininess(16);

lmb.setSpecularColor(ColorRGBA.Red);

// …

myModel.setMaterial(lmb.getMaterial());[/java]

3 Likes

@ Kirill nice idea

@Momoko_Fan: It’s a really good and useful idea… Basic function of a material builder may be copy, clone, extend or reference one to other material … And extra function is build up the handy material from some model like .mesh model (which reusable with some default value) , example :



I want to copy the fur of a tiger except its color … or I want to make my armor metal look but with default shine and bright value…



The extra-function I mention is the system which can produce the necessary custom file for a new material (.matc) which save such as Yellow /Black fur for a tiger and White/ Black fur for a cat. ← There’s a reason we don’t want to make another .mat and change only a few thing in it!

I’m sure I’m missing something but that sounds exactly the kind of thing that the existing j3md and j3m files are for. You can define defaults in the definition and then override them in the material.



…what did I miss?

@pspeed : So we can use j3md for definition and j3m for the custom things … But is it possible to change all the parameter (especially the render technique) in the j3m file , or just the Uniform … If it’s possible can you tell me how can we override to use other render techniques?

Usually you don’t need to override the render technique, those are generally used by filters if anything.

The uniforms are actually material parameters, so when you change a material param you’re actually changing a uniform. And that’s exactly the point of J3M files