[SOLVED] BinaryExporter and materials

Getting away from SDK reveals so many problems with how things work. Theres so many problems since oracle fragged java its sickening. It has pretty much made the SDK useless. People must not realize it yet or no ones using it anyway.

Anyhow.

So you can use BinaryExporter to convert a model and if you load that model into the game right after conversion, you have a fully textured model in game.

If you load that same model again, from the same folder as the material, which is also the same folder the model was converted to j3o from, no textures.

The j3o is supposed to be relative paths but I guess its not.

After reading everything I can, it comes down to making a j3m file right?

And there is no easy method I can find to do it like there is for binary export. If there is can someone point it out?

Seems like there would be material.write thast would do this since j3m is the standard but the one that exists is binary and not the right way to do this.

I read the code in the SDK for doing this and its a nightmare.

No easy way to do this then?

Writing j3m’s by hand is pretty simple
https://wiki.jmonkeyengine.org/jme3/advanced/j3m_material_files.html

But also see J3MExporter in Package com.jme3.material.plugin.export.material

Coder here, not a writer…

Let me rephrase because that reply seems terse.

I am not certain if what you show is correct since it looks to me its writing a binary file.

I am not certain because I can open any already buildt j3m as text.

I will see what happens tomorrow writing it out with the exporter, just that what I read said not the way to do it.

Afaik SDK also uses the J3MExporter for exporting materials, and afaik the exported material using J3MExporter should be editable in a text editor (Have not test it myself, I might be wrong so).

j3o’s have never had relative paths. The AssetManager doesn’t generally support relative paths.

…it’s always bugged me.

im not sure if i understand this topic correctly, but i understand there is some problem with BinaryExporter (j3o having material after export as i understand).

True, i use SDK to export to j3o, and i dont know why it is useless now since it work on both linux(openJDK) and windows(oracle), so someone might explain to me what is wrong. Also true we use prebuild SDK. but even if build SDK itself using oracle make a problem, why not just openJDK.

Anyway i dont see problem just creating material file like text file:

Material My Material : Common/MatDefs/Light/PBRLighting.j3md {
     MaterialParameters {
        BaseColorMap : Repeat Models/.../.../someFile.png
        Metallic : 0.3
        Roughness : 0.8
     }
    AdditionalRenderState {
    }
}

and then use

geom.setMaterial(assetManager.loadMaterial("/Materials/…/someMaterialFile.j3m"));

I think he’s trying to convert assets in code. Can you imagine trying to convert a bunch of assets if for every one you had to hand write a j3m? Seems unreasonable to me.

That being said, I’ve never had a problem writing a j3o in code, either… as long as you keep everything exactly where it was when you wrote it out.

1 Like

thanks for explain.

myself first, i wanted to just use imported material, .gltf to j3o exporter made it fine, but anyway for some of reasons i ended writing this “each j3m for each asset” that i dont like. i dont see nice solution to easly modify materials without it.

i just “sorted” them a way i will know that will never change. Found a lot of problems for asset managing, even using SDK. it was funny for me when i needed to update material textures, because it had different location for j3m, so when tried via SDK, each time needed to re-enter folders to select each single damn texture, instead of just remember last location that would help. so i just ended editing them as txt and auto-replace some parts with manual correction too.

but fact, now if i would need to change location for textures or materials, it would “break a system”.

i just hope i will never need move any folder to different location, because it will be a pain…

Spent about 4 hrs on this and still get same results. No texture.

@QSDragon was exactly right on using the j3mExporter.

                final J3MExporter j3mExporter = new J3MExporter(); 
                modelToImport.depthFirstTraversal(new SceneGraphVisitorAdapter() {
                    @Override
                    public void visit(Geometry geom) {
                        Material material = geom.getMaterial();
                        String name;
                        if (inputFile.getName().indexOf(".") > 0) {
                            name = inputFile.getName().substring(0, inputFile.getName().lastIndexOf(".")) + "-" + material.getName() + ".j3m";
                        } else {
                            name = inputFile.getName() + "-" + material.getName() + ".j3m";
                        } 
                        try {
                            File matFile = new File(outputFile.getParent(), name);
                            j3mExporter.save(material, matFile);

                            assetManager.registerLocator(matFile.getParent(), FileLocator.class);
                            Material loadMaterial = assetManager.loadMaterial(matFile.getName());
                            geom.setMaterial(loadMaterial);
                        } catch (IOException ex) {
                            Logger.getLogger(ModelConverter.class.getName())
                                    .log(Level.SEVERE, null, ex);
                        } 
                    }
                });

What I am doing is reading in the geometry existing geometry material.

Material material = geom.getMaterial();

Creating and assigning a name to the j3m file.

File matFile = new File(outputFile.getParent(), name);

Saving the file.

j3mExporter.save(material, matFile);

Loading the file back in, setting it to the geometry.

assetManager.registerLocator(matFile.getParent(), FileLocator.class);
Material loadMaterial = assetManager.loadMaterial(matFile.getName());
geom.setMaterial(loadMaterial);

Lastly, I write it to a new j3o but when loading it back in still no textures so evidently I am missing a step.

When you load it back in, have you still registered the material files parent with the asset manager?

No. After converting, which exits when done, I start a new app and run the game loading the j3o with assetManager.loadModel().

        Spatial loadModel = this.assetManager.loadModel("Textures/gltf/schoolpbr.j3o");
        rootNode.attachChild(loadModel);  

So you saves the j3m into a place that loading the asset will not find… because that location is not registered anymore?

You have a path problem, I think… else you wouldn’t need to register a special locator just to load the material. The asset key used to load it is what will be saved when you save the j3o.

I removed it. No different. If I convert the j3o and put it right back into the same folder the original model is in, using the exact same path, expected use would be that the materials would load. At leat thats what I feel and from the forum posts I am not alone.

They work just fine if you load the unconverted model into the engine.

Seems this is a common problem that always comes back to not finding the correct path but why its not has never been addressed by any form post. From what I can tell people just move on.

I use a prototype app to convert my gltf models to j3o… it has j3m support, texture support, etc… Nehon wrote this code.

Here is how it saves the scene as a j3o:

As long as I keep the asset/-relative paths the same, I can move these models into any project seemingly without issue.

Lot of good stuff in there.

I ran some printfs again,

   inputFile path: C:\xxx\assets\Textures\gltf\schoolpbr.gltf
  outputFile path: C:\xxx\assets\Textures\gltf\schoolpbr.j3o
materialFile path: C:\xxx\assets\Textures\gltf\schoolpbr-Concrete_Brown.j3m
    relative path: ..\schoolpbr.j3o

Relative is j3m to j3o and showing one folder above where it should be, ie the Textures folder.

System.out.println("   inputFile path: " + inputFile.getAbsolutePath());
                            
Path outFile = Paths.get(outputFile.getAbsolutePath());
System.out.println("  outputFile path: " + outFile);
                            
Path materialOut = Paths.get(matFile.getAbsolutePath());
System.out.println("materialFile path: " + materialOut);

Path relativize = materialOut.relativize(outFile);
System.out.println("    relative path: " + relativize);

Still fighting this.

There is no reason for this to not be loading the texture.

 The texture Roman_Brick_Long_A_R_M.png has linear color space, but the material parameter LightMap specifies no color space requirement, this may lead to unexpected behavior.

Ignore the content of the error message, I know why its doing that, intentional.

I print out the material and textures and they are set to correct path.

I know its finding the texture, warning proves it.

I know the code writing the j3o works, its same as everyone else uses.

I know the j3m is correct, I used sdk to build j3o and j3m and they are identical.

I know I can load the model without converting to j3o and it works.

Yet loading the converted j3o always fails to display the textures.

Let’s tease out what this means. Object is black? Object is colored? Object shows the “No Texture found” error texture?

1 Like

Yes, all the textures show the default image missing texture.

I am starting to suspect it has something to do with how in netbeans there is assets/Textures/etc and when loading things we use Textures/etc. The SDK took care of this I think somehow, not sure.

The “assets” directory should be on the classpath.

Edit: I think maybe there is some information I’m missing about your process/environment based on other posts. Are you trying to do this with gradle from the command line or something?