Material equality crash

Hello, I’ve recently updated JME, and calls to GeometryBatchFactory.optimize() started crashing on Matrial equality testing



[java]java.lang.NullPointerException

at com.jme3.material.Material.contentEquals(Material.java:257)

at jme3tools.optimize.GeometryBatchFactory.makeBatches(GeometryBatchFactory.java:294)

at jme3tools.optimize.GeometryBatchFactory.optimize(GeometryBatchFactory.java:362)

at jme3tools.optimize.GeometryBatchFactory.optimize(GeometryBatchFactory.java:346)[/java]



I’ve checked the Material.java source code and it crashes on this equal check. (I assume both techniques are null)



[java]

String thisDefName = this.technique != null ? this.technique.getDef().getName() : null;

String otherDefName = other.technique != null ? other.technique.getDef().getName() : null;

if (!thisDefName.equals(otherDefName)) {

return false;

}[/java]



I see what’s the prolem, so I’d like to ask, if that’s a bug or there’s some way how I could make the GeometryBatchFactory work again. (how to set the technique to something not null ?).



I use a standart Common/MatDefs/Misc/Unshaded.j3md material with a texture and BlendMode.Alpha set.



Edit:

I’ve managed to subclass Material and it works if I override the parent method like this:

[java] public boolean contentEquals(Object otherObj) {

if (!(otherObj instanceof Material)) {

return false;

}

Material other = (Material) otherObj;

if (getActiveTechnique() == null && other.getActiveTechnique() != null) {

return false;

}

return super.contentEquals(otherObj);

}[/java]

But still, seems like a bug to me

1 Like

propably because you haven’t specified the material.

null is an illegal value, and you use null as a material = your bug.

There’s no way it would crash there if material would be null…

If the first material is null, it wouldn’t even manage to invoke contentEquals, if the argument is null, it would return in the beginning.

See the original method:

[java]

public boolean contentEquals(Object otherObj) {

if (!(otherObj instanceof Material)) {

return false;

}

…etc

[/java]



I’ve managed to create a test case:



[java]import com.jme3.app.SimpleApplication;

import com.jme3.material.Material;

import com.jme3.math.ColorRGBA;

import com.jme3.scene.Geometry;

import com.jme3.scene.shape.Quad;



import java.util.logging.Level;



public class MaterialDemo extends SimpleApplication {



Material mat1;



public static void main(String… args) {

java.util.logging.Logger.getLogger("").setLevel(Level.SEVERE);

new MaterialDemo().start();

}



@Override

public void simpleInitApp() {

Quad q = new Quad(1, 1);

Geometry g = new Geometry("", q);

mat1 = new Material(assetManager, “Common/MatDefs/Misc/Unshaded.j3md”);

mat1.setColor(“ColorMap”, ColorRGBA.Black);

g.setMaterial(mat1);

rootNode.attachChild(g);

}



@Override

public void simpleUpdate(float tpf) {

super.simpleUpdate(tpf);

Material mat2 = mat1.clone();

System.out.println(mat2.contentEquals(mat1));

}

}

[/java]

It crashes the second time it executes update.



[java]true

7.6.2012 22:42:23 com.jme3.app.Application handleError

SEVERE: Uncaught exception thrown in Thread[LWJGL Renderer Thread,5,main]

java.lang.NullPointerException

at com.jme3.material.Material.contentEquals(Material.java:257)

at MaterialDemo.simpleUpdate(MaterialDemo.java:32)

at com.jme3.app.SimpleApplication.update(SimpleApplication.java:244)

at com.jme3.system.lwjgl.LwjglAbstractDisplay.runLoop(LwjglAbstractDisplay.java:149)

at com.jme3.system.lwjgl.LwjglDisplay.runLoop(LwjglDisplay.java:182)

at com.jme3.system.lwjgl.LwjglAbstractDisplay.run(LwjglAbstractDisplay.java:223)

at java.lang.Thread.run(Thread.java:619)

[/java]

1 Like

It will clearly fail if ‘this’ technique is null, and that should be fixed. But I’m not sure if cloning the material should not copy over the technique, there might be a bug there too…

this is a bug indeed.



It should be fixed in last SVN.

@Sploreg said:
It will clearly fail if 'this' technique is null, and that should be fixed. But I'm not sure if cloning the material should not copy over the technique, there might be a bug there too...

The technique is selected at render time, a newly created material has no technique...i replaced the null with "" to avoid the crash but I'm wondering if correct value shouldn't be "Default" as it's gonna be selected in the first render loop if nothing else is set.

Edit : a quick talk with Kirill confirmed this. So "Default" it is.