Model loading without rendering

Hi folks,



I noticed a misbehavior in the model conversion code. It is not possible to convert a stored model (in my case an .obj file model) without having the GL display created.

The following class will fail with a NullPointerException even if the URL stuff is set up correctly:

import com.jme.math.Vector3f;
import com.jme.scene.Node;
import com.jme.scene.Spatial;
import com.jme.util.export.binary.BinaryImporter;
import com.jmex.model.converters.ObjToJme;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.net.URL;

public class FailedGeomLoad {

    public FailedGeomLoad() {
        loadGeom();
    }
   
    public static void main(String[] args){
        FailedGeomLoad l = new FailedGeomLoad();
    }

    public void loadGeom() {
        ObjToJme conv = new ObjToJme();
        conv.setProperty("mtllib", GeomLoad.class.getClassLoader().getResource("loadtest/"));

        ByteArrayOutputStream bout = new ByteArrayOutputStream();
        URL url = GeomLoad.class.getClassLoader().getResource("loadtest/ear1.obj");
        Node loadedNode = new Node();
        loadedNode.setLocalTranslation(new Vector3f(2, 0, 0));

        InputStream is = null;
        try {
            is = url.openStream();
        } catch (Exception err) {
            System.out.println("Could not open Model file: " + err);
        }

        try {

            // Converts the file into a jme usable file
            conv.convert(is, bout);

            // Used to convert the jme usable file to a TriMesh
            BinaryImporter binaryImporter = new BinaryImporter();
            ByteArrayInputStream in = new ByteArrayInputStream(bout.toByteArray());

            //importer returns a Loadable, cast to Node
            Spatial geom = (Spatial) binaryImporter.load(in);

        } catch (Exception err) {
            System.out.println("Error loading obj model:" + err);
            err.printStackTrace();
        }
    }
}





If you put the identical code in a subclass of SimpleGame it will work:

public class GeomLoad extends SimpleGame{

    public static void main(String[] args) {
        GeomLoad l = new GeomLoad();
        l.setDialogBehaviour(ALWAYS_SHOW_PROPS_DIALOG);
        l.start();
    }

    public void loadGeom() {
        ObjToJme conv = new ObjToJme();
        conv.setProperty("mtllib", GeomLoad.class.getClassLoader().getResource("loadtest/"));
       
        ByteArrayOutputStream bout = new ByteArrayOutputStream();
        URL url = GeomLoad.class.getClassLoader().getResource("loadtest/ear1.obj");
        Node loadedNode = new Node();
        loadedNode.setLocalTranslation(new Vector3f(2,0,0));
       
        InputStream is = null;
        try {
            is = url.openStream();
        } catch (Exception err) {
            System.out.println("Could not open Model file: " + err);
        }

        try {

            // Converts the file into a jme usable file
            conv.convert(is, bout);

            // Used to convert the jme usable file to a TriMesh
            BinaryImporter binaryImporter = new BinaryImporter();
            ByteArrayInputStream in = new ByteArrayInputStream(bout.toByteArray());

            //importer returns a Loadable, cast to Node
            Spatial geom = (Spatial) binaryImporter.load(in);
            loadedNode.attachChild(geom);
            rootNode.attachChild(loadedNode);
           
        } catch (Exception err) {
            System.out.println("Error loading obj model:" + err);
            err.printStackTrace();
        }

    }
 
    @Override
    protected void simpleInitGame() {
         loadGeom();
       
}



Notice that this class will convert the wavefront model without problems. For my case this is a highly inconvenient behavior, because my application does not all the time keeps open the rendering window.
Is there a way to load the spatial prior to opening the rendering window?

Greetings,
Marcus

You can use a DummyDisplaySystem instead.  I know that will work fine for loading most models without a display.  I've never tried switching back and forth though, so not sure how well that will work.

Thanks,

could you give a short code snippet, how to "use" the DummyDisplaySystem? Because the display system stuff seems to be done in the model conversion classes. Is there a way to tell them to use the DummyDisplaySystem?

You can just create the DummyDisplaySystem before using them…  see the main method in most of the FormatConverter classes.

Thanks, this works.

But one drawback of this approach is, that if you later render the models loaded via DummyDisplaySystem, they will not have any color / material settings. I guess this is because DummyDisplaySystem somehow overrides the RenderingStates during the import process.

Personally I can live with this behavior, but one should eventually think about if this is a bug or a feature?



Thanks again,

Marcus