Noob: jme import -> everything black and white

I'm still a JME noob (after several weeks of trying) and could REALLY use some help getting my head wrapped around all this.



The basic problem is that my scene graphs all display white objects on a black background. I suspect the problem is that the jme loader doesn't maintain material information, but I'm too new at this to be sure.



My objects originate in SketchUp, which exports them as .obj files; one file per object, with material files (.mtl), all in the same directory. I use a simple wrapper around ObjToJme to convert them to .jme files in the same directory. Reduced to essentials, the wrapper just does



ObjToJme main = new ObjToJme();

main.setProperty("mtldir", dir);

main.setProperty("texdir", dir);

String[] fileArray = dirFile.list();

for (int i = 0; i < fileArray.length; i++)

{

String s = fileArray;

if (s.endsWith(INPUT_SUFFIX))

{

String o = s.substring(0, s.lastIndexOf(INPUT_SUFFIX))+OUTPUT_SUFFIX;

File inFile = new File(dirFile, s);

File outFile = new File(dirFile, o);

String[] argArray = new String[] {inFile.getCanonicalPath(), outFile.getCanonicalPath()};

main.attemptFileConvert(argArray);

}

}



To eliminate the likelihood I'm just doing something wrong, I moved Maggie.obj and Maggie.mtl into my .obj directory, and used BinaryToXML to print the resulting Maggie.jme as XML, shown below. For brevity I've replaced all but the first and last two numbers in each XML element with …



<scene >

<mesh name="temp0" >

<vertex data="6.21503 0.84252 … 57.05824 73.99062" >

</vertex>

<normal data="-0.577201 0.816591 … 0.16023 0.549042 0.820292" >

</normal>

<color >

</color>

<texturecoords data="0.0 0.0 …  0.0 0.0" >

</texturecoords>

<index data="0 1 … 642 543" >

</index>

<materialstate diffuse="0.8 0.8 0.8 1.0" color="0" ambient="0.2 0.2 0.2 1.0" emissive="0.0 0.0 0.0 1.0" specular="1.0 1.0 1.0 1.0" face="0" shiny="0.0" >

</materialstate>

<texturestate >

</texturestate>

</mesh>

</scene>



My questions:


  1. Is JME format supposed to maintain material information? From the above, it appears that it doesn't.
  2. If not, how should I iniclude it?
  3. I'm using SimpleCanvasImpl to get a Swing/AWT canvas. Might this be the problem?
  4. Are there other causes for white/black output I should consider? Here's my setup;

    I've tried all permutations of USE_TEXTURE_STATES, etc; they have no visible effect.



    public void simpleSetup()

    {

    cameraAxisVector.normalizeLocal();

        cam.setParallelProjection(false);

        cam.update();

       

        if (USE_TEXTURE_STATES)

        {

        TextureState ts = renderer.createTextureState();

        URL monkeyLoc = HelloStates.class.getClassLoader().getResource("jmetest/data/images/Monkey.tga");

        Texture t = TextureManager.loadTexture(monkeyLoc, Texture.MM_LINEAR, Texture.FM_LINEAR);

        ts.setTexture(t);

        // rootNode.setTextureCombineMode();

        }

        if (USE_LIGHT_STATES)

        {

        LightState state = renderer.createLightState();

    DirectionalLight directionalLight = new NagumoDirectionalLight();

    SpotLight spotlight = new NagumoSpotLight();

    state.setEnabled(true);

    state.attach(directionalLight);

    state.attach(spotlight);

    rootNode.setRenderState(state);

    }

        if (USE_MATERIAL_STATES)

    {

    MaterialState ms = renderer.createMaterialState();

    ms.setAmbient(new ColorRGBA(0.5f, 0.5f, 0.5f, 0.5f));

    // ms.setEmissive(new ColorRGBA(0,0.75f,0,0.5f));

    ms.setDiffuse(new ColorRGBA(0, 1, 0, 0.5f));

    ms.setSpecular(new ColorRGBA(1, 0, 0, 0.5f));

    ms.setShininess(100);

    rootNode.setRenderState(ms);

    }

        setBackground(ColorRGBA.lightGray);

       

        this.world = controller.buildWorld();

        rootNode.attachChild(world.getNode());

    //rootNode.setLightCombineMode(LightState.OFF);

    rootNode.updateRenderState();

       

    addBox(new Vector3f(000,000,000));

        addBox(new Vector3f(100,000,000));

        addBox(new Vector3f(000,100,000));

        addBox(new Vector3f(100,100,000));



        startTime = System.currentTimeMillis() + 5000;

        controller.activate();

    }







Typically white objects indicate that your lights are off (which means materials are ignored by opengl) and there are no vertex colors assigned to your mesh data.  You might try using setSolidColor(ColorRGBA.red) on one of your meshes for example, if it turns red, lighting is off - or you think a light is assigned to an object but it isn't.

Sorry, that makes sense but I lose it on the details. I'm using jbr.loadBinaryFormat(node, is) to load nodes. But nodes don't recognize setSolidColor, so I suspect you mean a TriMesh. Not sure how to get at those since I'm using nodes as a black box. Or do you mean editing a .obj file somehow.



Noob: needing precise instructions. 

Question…  Have you tried simply enabling your lights?  I'm not sure what code you might have put into NagumoDirectionalLight for example, but I assume it extends DirectionalLight.  Try calling .setEnabled(true) on your two lights to start off with.

I'd moved the fiddley bits into their own class (below). Both do enable lights.



On closer inspection of the running app, the displayed objects aren't dead white; there's a rapid flicker of color, so fast I didn't notice before. I take this to mean that the lights are on but something is interfering somehow. Sorry to be so vague but I'm pretty much running out of ideas here.



These are internal classes to NagumoCanvas shown previously.





class NagumoSpotLight extends SpotLight

{

final Vector3f spotlightDirection = new Vector3f(0, 0, 1); // 0, 0, 1

final ColorRGBA diffuseSpotlightSettings = new ColorRGBA(1.0f, 1.0f, 1.0f, 1.0f); // 1.0f, 1.0f, 1.0f, 1.0f

final ColorRGBA ambientSpotlightSettings = new ColorRGBA(0.75f, 0.75f, 0.75f, 1.0f); // 0.75f, 0.75f, 0.75f, 1.0f

final Vector3f spotlightLocation = new Vector3f(0, 0, 0); // 0, 0, 0

final int spotlightAngle = 25;



NagumoSpotLight()

{

    setDiffuse(diffuseSpotlightSettings);

    setAmbient(ambientSpotlightSettings);

    setDirection(spotlightDirection);

    setLocation(spotlightLocation);

    setAngle(spotlightAngle);

    setEnabled(true);

}



}

class NagumoDirectionalLight extends DirectionalLight

{

final ColorRGBA diffuseLightSettings = new ColorRGBA(0.0f, 1.0f, 1.0f, 1.0f); // 0.0f, 1.0f, 0.0f, 1.0f

final ColorRGBA ambientLightSettings = new ColorRGBA(0.5f, 0.5f, 0.5f, 1.0f); // 0.5f, 0.5f, 0.5f, 1.0f

final Vector3f directionalLightDirection = new Vector3f(1, 1, 0); // 1, 0, 0



NagumoDirectionalLight()

{

    setDiffuse(diffuseLightSettings);

    setAmbient(ambientLightSettings);

    setDirection(directionalLightDirection);

    setEnabled(true);

}

}

Try setting your ambient values to .2, .2, .2, 1  and diffuse to 1, 1, 1, 1.  Leave out the spot light for now and set the directional light's direction to something like:  new Vector3f(1,1,-.5f).normalizeLocal()

That had a major affect; the rendering is much more pleasant now but still like a black and white snapshot. No colors, just grey scale.



BTW: I'd changed the background to ColorRGB.lightGray, so my objects now appear as mixed white and black against a light gray background. No colors; no obvious textures.



I've uploaded a screenshot to http://virtualschool.edu/nagumo.png if that will help. Pardon the swing stuff on the left; seriously under construction.



PS: The image is supposed to be an airport, with planes, torpedos, bombs, hangars, crew quarters. Their positions are scrambled because positioning and rotations aren't working right either (another likely question once this is resolved).



The previous version (Sketchup + Ruby) is partially described at http://virtualschool.edu/animation/index.html I'm simply converting that from ruby to java.


Hmm, that is really bizarre.  It's almost as if the bpp was set ridiculously low or something…  What are your machine specs, btw?



Also, could you try moving to using SimpleGame instead just to see if it is Swing throwing a wrench in the works?

I'm on a Mac OSX G5. The demos seem look fine there. So does the Bang beta, insofar as I've tested it.



I had a bad experience with subclassing SimpleGame and am reluctant to go back. One of the demos didn't enable the keyboard so I had to power cycle to get the cursor back. Major disk crash followed. Can't afford that again.



Are there specific reasons to suspect the Swing stuff? It seems to work as I'd expect. But most of all, switching to SimpleGame would mean a major overhaul.

The only reason I have for suspecting swing is that it adds an extra level of image painting fun which in previous swing implementations (prior to lwjgl releasing AWTGLCanvas) caused problems with colors.



Another sanity check approach would be to comment out your setup code and try throwing in a box with a colored texture…  Basically when I run across a strange issue like this, I take the approach of either removing stuff from my code until I get expected behavior or removing everything and adding stuff back in one at a time.  Since the tests work fine on your machine, starting off with your existing init code and setupcode containing something simple like a box with colored verts or a box with a color texture seems like a logical next step.

Still researching the original problem. No solution yet. Just documentiing what I've tried so far.



Eclipse shows DisplaySystem.bpp is indeed 0 (but depthBits=8). This code in my Swing

Frame constructor class creates it



DisplaySystem displaySystem = DisplaySystem.getDisplaySystem("lwjgl");

this.canvas = displaySystem.createCanvas(width, height);

this.nagumoCanvas = new NagumoCanvas(width, height, controller);

((JMECanvas) canvas).setImplementor(nagumoCanvas);

this.canvas.setBounds(0, 0, width, height);

    this.canvas.addComponentListener(this);



I noticed there's a new LWJGL release. Installed that, which triggered a different problem (NPE during camera positioning), so I'll need to revert out of that.



Stilll intend to try the suggested fix; building on SimpleGame instead of Frame. I've been trying other paths first because that has major impacts on my app.



It would help if I had a better understanding of the maturity of the AWT/Swing/SWT desktops compared to the SimpleGame stuff. If I'm really the only one using this, it would be worth backing out. Should I ask the developer? Does someone have Slack's email?

Heh, Joshua Slack is me.  :slight_smile:



We use the Swing stuff at work here to make tools and they run well on Linux, Windows and MacOSX.  Try running jmetest.effects.RenParticleEditor.  If you can run RenParticleEditor and it shows color, then it's something wrong with how you have things setup in your code.  (What that is would be good to know so we can document things better.)

Thanks! Glad to meet you Joshua!



RenParticleEditor does show color particles against a black background. But FYI there's an EXTREMELY harsh flicker in that background and several of the NPE's I described elsewhere appear in the logs. I understand the NPE's. Any ideas about the flicker? I'm seeing that too in my app. This is with lwjgl-1.0b



Haven't yet figured out how to apply this to my app because the "input" argument doesn't exist. What is the input arg for a JFrame?



Re: documentation, I'll exercise a noob's inalienable right to tell experts how to improve things  :slight_smile: Seems to me I've been following the path other noobs might; starting with images built elsewhere and importing them into your environment.



The documentation would be most helpful if it supported this directly; explaining how to import existing models (explaining mtllib and texlib settings EXPLICITLY; took me weeks to discover those) into a stable and usable environment that provides viable controls for exploring the users model in whatever state it arrives (likely broken), with camera movement, coloring controls, all ready to use in viewing the model from all perspectives. Most of my problems have been just getting to this point, before I'm even confident that my models are importing correctly.



In particular, I'm still not sure that I'm handling positions correctly (are they relative to parent or to self?), or how to handle  the fact that y is up in my coordinate system while y is documented as up for the camera).



A well-documented and feature-rich exploratorium would have collasped weeks of pointless huffing into days.



By contrast, LWJGL's documents start way too low (from noob's viewpoint), with polygons, not models. And JME's documents focus too high, explaining how the environment works (expert view), when the noob's attention is focused on modeling basicis.



Just thought I should capture that perspective before I start moving up the learning curve. Hope it helps.

Cool, thanks for the perspective on docs.  I can't promise that will change anytime soon with the copious free-time none of us seem to have, but at least it is here for us to keep in mind.  :confused:



lwjgl's 1.0b build has swing issues.  They gave us a custom lwjgl.jar file (in our cvs under jme/lib) that fixed the flicker issue though.  Windows tells me the file size is: 393 KB (403,308 bytes)  The older 1.0b jar was about 200 bytes smaller iirc.

On your advice, I wedged my model into JMESwingTest, making no nonessential changes except those shown below:



public void simpleSetup()

{

// Normal Scene setup stuff…

rotQuat = new Quaternion();

axis = new Vector3f(1, 1, 0.5f);

axis.normalizeLocal();

Vector3f max = new Vector3f(5, 5, 5);

Vector3f min = new Vector3f(-5, -5, -5);



box = new Box("Box", min, max);

box.setModelBound(new BoundingBox());

box.updateModelBound();

box.setLocalTranslation(new Vector3f(0, 0, -10));

box.setRenderQueueMode(Renderer.QUEUE_SKIP);

rootNode.attachChild(box);

box.setRandomColors();



this.world = buildWorld();

    world.node.setLocalTranslation(new Vector3f(-10, -10, -10));

world.node.setLocalScale(.5f);

world.node.setRenderQueueMode(Renderer.QUEUE_SKIP);

    rootNode.attachChild(world.getNode());



where world.node is the model I've been using all along. I also added a world.node.setLocalRotation(rotQuat); in the update loop.



Net result is exactly what I've been dealing with all along; a solid, untextured, almost pure white world revolving alongside your nicely colored and textured cube/box.



I eliminated CVS imponderables (I'm more familiar with Subversion than CVS) by erasing the JME I'd been using and downloading a completely new one, so I'm sure I'm using the latest JME and LWJGL now.



Any further suggestions? I'm about at the end of my rope.

Well, that's actually a good thing.  It narrows things down to a model problem.  Do you see any textures on your world?  Maybe textures are not being found.  Or does your model use vertex coloring?  Try disabling the lightstate to see if colors suddenly come in for your model.

There's no LightState in HelloJmeDesktop. I made no non-essential changes except the code I showed.



No textures are apparent but I've not ruled out that they are there. I did have to battle ObjToJme which was complaining about not being able to find them until I defined texurl (or similar).



I have a utility that uses BinaryToXML to print jme files. But I can't make sense of the output. Here's what it produces for Deck.jme; one of my files (with elipsis … replacing reptitive info).



Converting obj-xyz/Deck.jme

<scene >

<mesh name="temp0" >

<vertex data="400.0 … 0.0" >

</vertex>

<normal data="0.0 … 1.0" >

</normal>

<color >

</color>

<texturecoords data="606.197 … 200.0" >

</texturecoords>

<index data="0 … 182" >

</index>

<materialstate diffuse="0.8 0.8 0.8 1.0" color="0" ambient="0.2 0.2 0.2 1.0" emissive="0.0 0.0 0.0 1.0" specular="1.0 1.0 1.0 1.0" face="0" shiny="0.0" >

</materialstate>

<texturestate >

</texturestate>

</mesh>

</scene>



I think this is saying textures are in fact being stored in the .jme files. And presumably being loaded into the Nodes. Right?

So I did the converse by adding the LightState code from my original app to HelloJmeWorld… below



    if (USE_LIGHT_STATE)

    {

    LightState lightState = renderer.createLightState();

DirectionalLight directionalLight = new NagumoDirectionalLight();

// SpotLight spotlight = new NagumoSpotLight();

lightState.attach(directionalLight);

// lightState.attach(spotlight);

lightState.setEnabled(true);

rootNode.setRenderState(lightState);

    }



Result is much the same; rotating cube with colored monkey face (now rendered with shadows), plus my rotating model, dead white, when it emerges from shadow. Here's NagumoDirectionalLight again.



class NagumoDirectionalLight extends DirectionalLight

{

final ColorRGBA diffuseLightSettings = new ColorRGBA(1f, 1f, 1f, 1f); // 0.0f, 1.0f, 0.0f, 1.0f

final ColorRGBA ambientLightSettings = new ColorRGBA(.2f, .2f, .2f, 1f); // 0.5f, 0.5f, 0.5f, 1.0f

final Vector3f directionalLightDirection = new Vector3f(1,1,-.5f).normalizeLocal(); // 1, 0, 0



NagumoDirectionalLight()

{

    setDiffuse(diffuseLightSettings);

    setAmbient(ambientLightSettings);

    setDirection(directionalLightDirection);

    setEnabled(true);

}

}

Hmm, it appears your specular and shiny are set such that the specular highlight would overpower the color of the model.  Try setting the specular color to black.  Of course you said you were getting the issue with no lighting, but I would say it's worth a shot.  Your xml shows texturestate with no arguments, so my guess is that the texture is still not being loaded properly by the loader.  Another thing to try would be to apply one of our textures in a new texturestate at the top of your model.  Finally, your texture coords are really high, does the model have some highly repeating texture on it or something?

I assume you're referring to specular/shiny in the xml output since its not mentioned in the source. In that case, I've no way to "set the specular color to black" since the .jme file I'm using originate in a black box (SketchUp) and these pass through two more black boxes (ObjToJme and JmeToXML) before they appear on the screen. The .obj and .mtl files are available for inspection, but provide no obvious way of editing specular color. For example; here's the .mtl file in question:



#

Alias OBJ Material File

Exported from SketchUp, © 2000-2005 @Last Software, Inc.


newmtl FrontColor
Ka 0.000000 0.000000 0.000000
Kd 0.882353 0.882353 0.784314
Ks 0.330000 0.330000 0.330000

newmtl BackColor
Ka 0.000000 0.000000 0.000000
Kd 0.501961 0.501961 0.784314
Ks 0.330000 0.330000 0.330000

newmtl Seashell
Ka 0.000000 0.000000 0.000000
Kd 1.000000 0.960784 0.933333
Ks 0.330000 0.330000 0.330000

newmtl Concrete_rough
Ka 0.000000 0.000000 0.000000
Kd 0.658824 0.662745 0.643137
Ks 0.330000 0.330000 0.330000
map_Kd Deck/Concrete_rough.png

newmtl Concrete_rough_02_
Ka 0.000000 0.000000 0.000000
Kd 0.690196 0.666667 0.470588
Ks 0.330000 0.330000 0.330000
map_Kd Deck/Concrete_rough_02_.png

Re texture coordinates, the Deck model is nothing more than a 3D box with a few thin 3D boxes down the middle to represent landing stripes. These were textured with SketchUp's "Rough concrete" texture right out of the box.

SketchUp is even more of a black box than JME; even more so because the source isn't available. The .obj and .mtl files are one of the only ways to peek inside. Sketchup is documented for architects, not programmers, and no source is available. I do know the Ruby interface having worked with it extensively, but nothing inside the Sketchup box is accessible, let alone documented. That's precisely the reason I gave up on doing the whole simulation in Sketchup and returned to JME; availability of source somewhat compensates for JME's lack of documentation.

To add to my troubles, model loading broke for most (not all) of my components, presumably during the CVS update so I'm unable to repeat experiments right now.

IOException: unable to load obj-xzy/Tower.jme
java.io.IOException: Binary Header doesn't match.  Maybe wrong file?
at com.jmex.model.XMLparser.JmeBinaryReader.readHeader(JmeBinaryReader.java:1272)
at com.jmex.model.XMLparser.JmeBinaryReader.loadBinaryFormat(JmeBinaryReader.java:156)
at com.binary.nagumo.models.AbstractObject.loadNode(AbstractObject.java:115)
at com.binary.nagumo.models.AbstractObject.<init>(AbstractObject.java:43)
at com.binary.nagumo.models.Tower.<init>(Tower.java:9)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
at java.lang.reflect.Constructor.newInstance(Constructor.java:494)
at com.binary.nagumo.models.AbstractObject.<init>(AbstractObject.java:54)
at com.binary.nagumo.models.World.<init>(World.java:31)
at com.binary.nagumo.views.Controller.buildWorld(Controller.java:53)
at com.binary.nagumo.views.NagumoCanvas.simpleSetup(NagumoCanvas.java:51)

What a mess ;-(