Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NPE while loading glTF model "Hover bike - The Rocket" #1612

Closed
stephengold opened this issue Sep 30, 2021 · 3 comments · Fixed by #1639
Closed

NPE while loading glTF model "Hover bike - The Rocket" #1612

stephengold opened this issue Sep 30, 2021 · 3 comments · Fixed by #1639
Assignees
Milestone

Comments

@stephengold
Copy link
Member

To reproduce the issue;

  1. download the Autoconverted format glTF from https://sketchfab.com/3d-models/hover-bike-the-rocket-8b2e5bfca78e41c791b4e5b5e8c04512
  2. unzip the files into "jme3-examples/src/main/resources"
  3. add assetManager.loadModel("scene.gltf"); to the example app of your choice

Typical stack trace:

com.jme3.asset.AssetLoadException: An error occurred loading scene.gltf
	at com.jme3.scene.plugins.gltf.GltfLoader.loadFromStream(GltfLoader.java:181)
	at com.jme3.scene.plugins.gltf.GltfLoader.load(GltfLoader.java:106)
	at com.jme3.asset.DesktopAssetManager.loadLocatedAsset(DesktopAssetManager.java:272)
	at com.jme3.asset.DesktopAssetManager.loadAsset(DesktopAssetManager.java:388)
	at com.jme3.asset.DesktopAssetManager.loadModel(DesktopAssetManager.java:439)
	at com.jme3.asset.DesktopAssetManager.loadModel(DesktopAssetManager.java:444)
...
Caused by: java.lang.NullPointerException
	at com.jme3.anim.SkinningControl.getAttachmentsNode(SkinningControl.java:403)
	at com.jme3.scene.plugins.gltf.GltfLoader.setupControls(GltfLoader.java:1151)
	at com.jme3.scene.plugins.gltf.GltfLoader.loadFromStream(GltfLoader.java:166)
	... 10 more

No matter how corrupt the model is, the loader shouldn't throw an NPE!

Forum discussion at https://hub.jmonkeyengine.org/t/how-to-load-gltf-model-correctly/44946

For reasons I don't yet understand, the loader isn't finding anywhere to add the SkinningControl. The following workaround allows the model to load, but probably isn't the best solution:

# This patch file was generated by NetBeans IDE
# It uses platform neutral UTF-8 encoding and \n newlines.
--- a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfLoader.java
+++ b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfLoader.java
@@ -1148,7 +1148,11 @@
                 continue;
             }
             SkinData skinData = fetchFromCache("skins", bw.skinIndex, SkinData.class);
-            skinData.skinningControl.getAttachmentsNode(bw.joint.getName()).attachChild(bw.attachedSpatial);
+            SkinningControl control = skinData.skinningControl;
+            if (control.getSpatial() == null) {
+               rootNode.addControl(control);
+            }
+            control.getAttachmentsNode(bw.joint.getName()).attachChild(bw.attachedSpatial);
         }
     }
@stephengold stephengold added this to the Future Release milestone Sep 30, 2021
@stephengold stephengold changed the title NPE while loading glTF model "Hover bike - "The Rocket" NPE while loading glTF model "Hover bike - The Rocket" Sep 30, 2021
@stephengold stephengold modified the milestones: Future Release, v3.5.0 Oct 24, 2021
@stephengold
Copy link
Member Author

The SkinningControl wasn't added to a Spatial because the if (spatials.isEmpty()) branch was taken in setupControls().

@stephengold
Copy link
Member Author

I found 2 places where spatials could be added:

  • one in readAnimation() if !spatials.isEmpty()
  • and one in readNode() if skinIndex != null.

Both methods are invoked, but the relevant conditions are never satisfied:

  • In readAnimation() the node fetched from the cache is always a JointWrapper, never a Spatial.
  • In readNode() the skinIndex is always null because nodeData never has any member named "skin".

@stephengold
Copy link
Member Author

The NPE also occurs while loading the model in "v3.4" branch, so the issue isn't a recent regression.

Downloaded the original model from Sketchfab in FBX format, imported it into Blender v2.93.3, exported it in GLB format, and was able to load the GLB file into JMonkeyEngine. This suggests a flaw in Sketchfab's (automated) conversion of the model.

Downloaded v2.0.0-dev.3.5 of the Khronos validator from https://github.com/KhronosGroup/glTF-Validator/releases, ran it, and got the following report:

Errors: 1, Warnings: 0, Infos: 2, Hints: 0
Time: 57ms

	Errors:
		/skins/0/inverseBindMatrices: bufferView.byteStride must not be defined for buffer views used by inverse bind matrices accessors.

	Infos:
		/nodes/6: Empty node encountered.
		/skins/0: This object may be unused.

The evidence indicates an invalid "scene.gltf" file, so consider how best to diagnose the issue and/or avoid crashing. If we skip getAttachmentsNode() entirely, then the loaded model won't have any geometries. Better to fall back on the model's root node (as proposed in September). But the loader shouldn't do this silently; it should also log a warning.

I'll submit a PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant