[SOLVED] Blender Custom Properties and JME User Data

I can’t seem to get custom properties from Blender 2.8 to make it into JME. I’m exporting as glTF 2.0. I’ve tried loading the scene as a glTF and j3o.

        String sceneName = "Scenes/testRoom.j3o";
        AssetManager assetManager = app.getAssetManager();
        Node scene = (Node) assetManager.loadModel(sceneName);
        rootNode.attachChild(scene);
        //produces [ORIGINAL_NAME, ORIGINAL_PATH]
        System.out.println(scene.getUserDataKeys());
        //produces [ORIGINAL_NAME, ORIGINAL_PATH] for each spatial
        scene.getChildren().stream().forEach((q) -> System.out.println(""+q.getUserDataKeys()));
        //produces null
        System.out.println("" + scene.getChild("cylinder").getUserData("prop"));

Capture3

JME’s gltf load doesn’t shuffle “extras” into user data by default. You have to add an extras loader.

…or you can convert your model with JmeConverter which does it automatically.

Really, sometime that extras-handling code should probably be included in JME.

In the end, there are still advantages to using JMEC to create a repeatable pipeline for getting your model into JME. It can run custom scripts and so on that can tweak the model during the conversion process (for example to normalize size, etc.) that can be repeated each time you need to reconvert the model.

3 Likes

Thank you! I’m having a little trouble getting it working but I’m probably using it incorrectly. Given the input:

jmec -sourceRoot "C:\Users\PC\Documents\Blender Files\testRoom" -targetRoot "C:\Users\PC\Documents\conversion" -targetPath testRoom "C:\Users\PC\Documents\Blender Files\testRoom\testRoom.gltf"

I get:

21:04:04,685 INFO  [Convert] Max memory:4096.00 mb
21:04:04,687 INFO  [AssetReader] Using source asset root:C:\Users\PC\Documents\Blender Files\testRoom
21:04:04,688 INFO  [AssetReader] Found assetConfig:jar:file:/C:/Users/PC/Documents/jMonkey%20Projects/Robot%20Game%20Proxy/jmec-1.1.0/lib/jme3-core-3.2.3-stable.jar!/com/jme3/asset/Desktop.cfg
21:04:04,725 WARN  [AssetConfig] Cannot find loader com.jme3.audio.plugins.OGGLoader
21:04:04,728 INFO  [Convert] Convert:C:\Users\PC\Documents\Blender Files\testRoom\testRoom.gltf
21:04:04,729 INFO  [AssetReader] Loading asset:testRoom.gltf
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by com.jme3.util.ReflectionAllocator (file:/C:/Users/PC/Documents/jMonkey%20Projects/Robot%20Game%20Proxy/jmec-1.1.0/lib/jme3-core-3.2.3-stable.jar) to method sun.nio.ch.DirectBuffer.cleaner()
WARNING: Please consider reporting this to the maintainers of com.jme3.util.ReflectionAllocator
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
Exception in thread "main" java.lang.NoClassDefFoundError: javax/xml/bind/DatatypeConverter
        at com.jme3.scene.plugins.gltf.GltfLoader.getBytes(GltfLoader.java:527)
        at com.jme3.scene.plugins.gltf.GltfLoader.readData(GltfLoader.java:513)
        at com.jme3.scene.plugins.gltf.GltfLoader.readBuffer(GltfLoader.java:484)
        at com.jme3.scene.plugins.gltf.GltfLoader$VertexBufferPopulator.populate(GltfLoader.java:1350)
        at com.jme3.scene.plugins.gltf.GltfLoader$VertexBufferPopulator.populate(GltfLoader.java:1318)
        at com.jme3.scene.plugins.gltf.GltfLoader.readAccessorData(GltfLoader.java:465)
        at com.jme3.scene.plugins.gltf.GltfLoader.readMeshPrimitives(GltfLoader.java:356)
        at com.jme3.scene.plugins.gltf.GltfLoader.readNode(GltfLoader.java:217)
        at com.jme3.scene.plugins.gltf.GltfLoader.readChild(GltfLoader.java:266)
        at com.jme3.scene.plugins.gltf.GltfLoader.readScenes(GltfLoader.java:183)
        at com.jme3.scene.plugins.gltf.GltfLoader.loadFromStream(GltfLoader.java:127)
        at com.jme3.scene.plugins.gltf.GltfLoader.load(GltfLoader.java:78)
        at com.jme3.asset.DesktopAssetManager.loadLocatedAsset(DesktopAssetManager.java:259)
        at com.jme3.asset.DesktopAssetManager.loadAsset(DesktopAssetManager.java:373)
        at com.jme3.asset.DesktopAssetManager.loadModel(DesktopAssetManager.java:416)
        at com.simsilica.jmec.AssetReader.loadModel(AssetReader.java:106)
        at com.simsilica.jmec.Convert.convert(Convert.java:255)
        at com.simsilica.jmec.Convert.main(Convert.java:317)
Caused by: java.lang.ClassNotFoundException: javax.xml.bind.DatatypeConverter
        at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:583)
        at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
        at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
        ... 18 more

Weird that it’s missing jaxb. What version of java are you using?

1.8.0_212 currently

So, java -version from the same command line you run jmec says 1.8?

That’s weird because I also run 1.8 and mine isn’t missing JAXB.

1 Like

I’ll switch to the proper version in a sec

Oh, We’re running the same version? That is odd then, I’ll try doing a clean install of java and get back to you.

Alright, good and bad news. I resolved the missing dependencies by switching to a JDK version of java 8 (was using a JRE version for reasons). However:

input:

jmec -sourceRoot "C:\Users\PC\Documents\Blender Files\testRoom" -targetRoot "C:\Users\PC\Documents\conversion" -targetPath testRoom "C:\Users\PC\Documents\Blender Files\testRoom\testRoom.gltf"

produces:

12:51:14,641 INFO  [Convert] Max memory:3641.00 mb
12:51:14,643 INFO  [AssetReader] Using source asset root:C:\Users\PC\Documents\Blender Files\testRoom
12:51:14,643 INFO  [AssetReader] Found assetConfig:jar:file:/C:/jmec-1.1.0/lib/jme3-core-3.2.3-stable.jar!/com/jme3/asset/Desktop.cfg
12:51:14,680 WARN  [AssetConfig] Cannot find loader com.jme3.audio.plugins.OGGLoader
12:51:14,682 INFO  [Convert] Convert:C:\Users\PC\Documents\Blender Files\testRoom\testRoom.gltf
12:51:14,683 INFO  [AssetReader] Loading asset:testRoom.gltf
Exception in thread "main" com.jme3.asset.AssetLoadException: An error occurred loading testRoom.gltf
        at com.jme3.scene.plugins.gltf.GltfLoader.loadFromStream(GltfLoader.java:150)
        at com.jme3.scene.plugins.gltf.GltfLoader.load(GltfLoader.java:78)
        at com.jme3.asset.DesktopAssetManager.loadLocatedAsset(DesktopAssetManager.java:259)
        at com.jme3.asset.DesktopAssetManager.loadAsset(DesktopAssetManager.java:373)
        at com.jme3.asset.DesktopAssetManager.loadModel(DesktopAssetManager.java:416)
        at com.simsilica.jmec.AssetReader.loadModel(AssetReader.java:106)
        at com.simsilica.jmec.Convert.convert(Convert.java:255)
        at com.simsilica.jmec.Convert.main(Convert.java:317)
Caused by: java.lang.IllegalArgumentException: Unsupported type: com.google.gson.internal.LazilyParsedNumber
        at com.jme3.scene.UserData.getObjectType(UserData.java:124)
        at com.jme3.scene.Spatial.setUserData(Spatial.java:1539)
        at com.simsilica.jmec.gltf.GltfExtrasLoader.applyToSpatial(GltfExtrasLoader.java:114)
        at com.simsilica.jmec.gltf.GltfExtrasLoader.apply(GltfExtrasLoader.java:95)
        at com.simsilica.jmec.gltf.GltfExtrasLoader.handleExtras(GltfExtrasLoader.java:84)
        at com.jme3.scene.plugins.gltf.CustomContentManager.readExtras(CustomContentManager.java:111)
        at com.jme3.scene.plugins.gltf.CustomContentManager.readExtensionAndExtras(CustomContentManager.java:62)
        at com.jme3.scene.plugins.gltf.GltfLoader.readNode(GltfLoader.java:259)
        at com.jme3.scene.plugins.gltf.GltfLoader.readChild(GltfLoader.java:266)
        at com.jme3.scene.plugins.gltf.GltfLoader.readScenes(GltfLoader.java:183)
        at com.jme3.scene.plugins.gltf.GltfLoader.loadFromStream(GltfLoader.java:127)
        ... 7 more

[Edit] moved converter folder to C:\

Hmmm… that’s weird.

I assume you are using the prebuilt zip and you didn’t build jmec locally yourself?

Right. I’m using release 1.1.0 from the extracted zip on the C:\ root for no access privilege problems.

I’ve built the program using the release jar’s. Running the program within the SDK produces the same results.

Using a gltf embedded file containing a cube with no material or custom properties produces a slightly different error:

Exception in thread "main" java.lang.UnsupportedOperationException: Unsupported type stored in the list: class com.google.gson.internal.LazilyParsedNumber
	at com.jme3.scene.UserData.writeList(UserData.java:259)
	at com.jme3.scene.UserData.write(UserData.java:163)
	at com.jme3.export.binary.BinaryExporter.processBinarySavable(BinaryExporter.java:401)
	at com.jme3.export.binary.BinaryOutputCapsule.write(BinaryOutputCapsule.java:720)
	at com.jme3.export.binary.BinaryOutputCapsule.write(BinaryOutputCapsule.java:733)
	at com.jme3.export.binary.BinaryOutputCapsule.writeStringSavableMap(BinaryOutputCapsule.java:813)
	at com.jme3.export.binary.BinaryOutputCapsule.writeStringSavableMap(BinaryOutputCapsule.java:379)
	at com.jme3.scene.Spatial.write(Spatial.java:1609)
	at com.jme3.scene.Node.write(Node.java:734)
	at com.jme3.export.binary.BinaryExporter.processBinarySavable(BinaryExporter.java:401)
	at com.jme3.export.binary.BinaryExporter.save(BinaryExporter.java:210)
	at com.jme3.export.binary.BinaryExporter.save(BinaryExporter.java:360)
	at com.simsilica.jmec.AssetWriter.write(AssetWriter.java:139)
	at com.simsilica.jmec.AssetWriter.apply(AssetWriter.java:88)
	at com.simsilica.jmec.Convert.runProcessors(Convert.java:255)
	at com.simsilica.jmec.Convert.convert(Convert.java:245)
	at com.simsilica.jmec.Convert.main(Convert.java:298)

Note that the line numbers are no longer accurate due to IDE formatting.

[Edit] sorry I mixed up the outputs between the command line and SDK console.

jmec is not failing in this way for my models here.

Is it possible to provide a link to one that fails?

Have you tried downloading some gltf from sketchfab to see if they also fail to load?

1 Like

I downloaded a gltf sample which converts without error. I then downloaded Blender 2.79b and the legacy exporter - https://github.com/KhronosGroup/glTF-Blender-Exporter. A file produced from this setup also converted properly.

Seems that either Blender 2.8 or the new version of the exporter (https://github.com/KhronosGroup/glTF-Blender-IO) is to blame for the exception.

I use blender 2.80 for all of my gltf models, and have had no issues. I will investigate a bit when I get home. I am very familiar with jme’s gltf importer.
What setting in blender are you using for the export?

EDIT: Which version of JME are you using. There have been a lot of changes to the gltf importer this year.

You use @pspeed’s converter on models produced from blender 2.8? Just to be clear, it is the converter tool provided separately from JME’s converter that I was having issues with. I can use JME’s converter fine with 2.8 although the extra data blocks I need don’t survive the conversion from gltf.

I am using JME 3.2.4.

jmec uses JME’s code to do the import. The only added part is the user data that JME’s importer doesn’t support.

I guess the format of the numbers is something that the existing code doesn’t like.

I’d need a gltf file that fails in order for me to track the issue further.

http://www.mediafire.com/file/6nxrkcqj4zkvyww/cube.gltf/file

I believe I’ve found the problem and a partial solution. I was able to get a model to fail even when using 2.79 blender and the old exporter.

To recreate faulty file in 2.79: create an object property and leave it with its default values

To fix the error: click the edit button on the property, set the value to anything non-numeric, press ok, then change the value back to a number in the field box (next to edit button).

It seems any custom property with a numerically interpreted value will fail conversion. Each time the ok button is pressed from the edit dialogue the property value is decided whether to be interpreted as a string or a numerical type.

In 2.8 a model fails even with no custom properties added, which makes me think some implicit data values may be present.

Update: It looks like this trick works even with 2.8. The file won’t work without custom properties but will when a string-valued property is added.

Ok… so it’s a real issue and most people must have used non-numbers so far.

I’ll take a look at your sample model soon and see if I can fix the issue if no one submits a patch before then.