MaterialState colors unrelated Geometries

Root problem seems to be that MaterialStates with FrontAndBack mat facings affect the back face of unrelated Geometries in the scene.  It colors the back of all (non-culled, of course) back faces which have not been materialized.  This includes both non-colored Geometries (with and without texcoords) and textured Geometries.



The following code snippet shows that the two triangles are sibling children of rootNode, and therefore should not share any render states assigned to one or to the other.  The TriMesh to the right ("colorlessTri") should have no color, because none is assigned.



rootNode.attachChild(coloredTri);
...
rootNode.attachChild(colorlessTri);



Here is the screen shot followed by the complete test case class.




import com.jme.math.FastMath;
import com.jme.bounding.BoundingBox;
import com.jme.scene.TriMesh;
import com.jme.app.SimpleGame;
import com.jme.input.MouseInput;
import com.jme.input.FirstPersonHandler;
import com.jme.system.DisplaySystem;
import com.jme.renderer.ColorRGBA;
import com.jme.util.geom.BufferUtils;
import com.jme.scene.state.MaterialState;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;

/**
 * Exemplifies jME problem where a Material colors unrelated Spatials in the
 * same scene.
 * In this case, 'coloredTri' affects 'colorlessTri'.
 *
 * @author Blaine Simpson (blaine dot simpson at admc dot com)
 * @see #main(String[])
 */
public class InvasiveMat extends SimpleGame {
    static public void main(String[] args) {
        InvasiveMat app = new InvasiveMat();
        if (args.length > 0 && args[0].equals("-r"))
            app.setConfigShowMode(ConfigShowMode.AlwaysShow);
        app.start();
    }

    protected void simpleInitGame() {
        try {
            MouseInput.get().setCursorVisible(true);
            ((FirstPersonHandler) input).setButtonPressRequired(true);
            // Windowed mode is extremely irritating without these two settings.

            MaterialState offendingMatState = DisplaySystem
                    .getDisplaySystem().getRenderer().createMaterialState();
            offendingMatState.setDiffuse(ColorRGBA.blue);
            offendingMatState.setMaterialFace(
                    MaterialState.MaterialFace.FrontAndBack);

            TriMesh coloredTri = mkTrivialTri("coloredTri");
            TriMesh colorlessTri = mkTrivialTri("colorlessTri");
            coloredTri.getLocalTranslation().setX(-2f);
            colorlessTri.getLocalTranslation().setX(+2f);
            // colored to the Left, colorless to the Right.
            coloredTri.setModelBound(new BoundingBox());
            rootNode.attachChild(coloredTri);
            coloredTri.getLocalRotation().fromAngles(0, FastMath.PI, 0);
            colorlessTri.getLocalRotation().fromAngles(0, FastMath.PI, 0);
            // Rotate the back sides towards the camera, because that is the
            // side which exhibits the problem.
            coloredTri.updateModelBound();
            colorlessTri.setModelBound(new BoundingBox());
            rootNode.attachChild(colorlessTri);
            colorlessTri.updateModelBound();
            rootNode.updateRenderState();

            coloredTri.setRenderState(offendingMatState);
        } catch (Exception e) {
            // Programs should not just continue obliviously when exceptions
            // are thrown.  Since we aren't handling them, we exit gracefully.
            e.printStackTrace();
            finish();
        }
    }

    public TriMesh mkTrivialTri(String newName) {
        TriMesh newTri = new TriMesh(newName);
        FloatBuffer vBuffer = BufferUtils.createFloatBuffer(3 * 3);
        // x+y+z coords for 3 points

        vBuffer.put(-.5f); vBuffer.put(-.5f); vBuffer.put(0f);
        vBuffer.put(+.5f); vBuffer.put(-.5f); vBuffer.put(0f);
        vBuffer.put(0f); vBuffer.put(+.5f); vBuffer.put(0f);
        vBuffer.flip();
        newTri.setVertexBuffer(vBuffer);

        FloatBuffer nBuffer = BufferUtils.createFloatBuffer(3 * 3);
        while (nBuffer.hasRemaining()) {
            nBuffer.put(0f);
            nBuffer.put(0f);
            nBuffer.put(1f);
        }
        nBuffer.flip();
        newTri.setNormalBuffer(nBuffer);

        IntBuffer iBuffer = BufferUtils.createIntBuffer(3);
        iBuffer.put(0); iBuffer.put(1); iBuffer.put(2);
        iBuffer.flip();
        newTri.setIndexBuffer(iBuffer);
        return newTri;
    }
}

Hi,



i had a look at it and i think this behaviour is because the defaultMaterialState has as defaultMaterialFace = FRONT. In your example, only the front is blue and the back is gray (the default materialstate defaultDiffuse).



    /** Default material face for all material states. */
    public static final MaterialFace defaultMaterialFace = MaterialFace.Front;



If i change this to FrontAndBack the behaviour is as expected. (The complete Triangle is gray)

Regards,

snare