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

Fix SkeletonDebugger deserializing #2228

Merged
merged 2 commits into from
Mar 30, 2024

Conversation

tonihele
Copy link
Contributor

@tonihele tonihele commented Mar 17, 2024

Resolves #2226

Prevents NPE after deserializing SkeletonDebugger. The solution is not that pretty. But it works. The children are written/read properly, this just then finds them by the fixed names set.

@tonihele
Copy link
Contributor Author

Here is the code I used to test this. The model is here https://sketchfab.com/3d-models/silver-dragonkin-mir4-89ead4e87cdc4b70840f748383f0998f, get it as FBX:

package jme3test.scene;

import com.jme3.app.SimpleApplication;
import com.jme3.asset.plugins.FileLocator;
import com.jme3.asset.plugins.HttpZipLocator;
import com.jme3.asset.plugins.ZipLocator;
import com.jme3.export.binary.BinaryExporter;
import com.jme3.light.AmbientLight;
import com.jme3.light.DirectionalLight;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
import com.jme3.scene.Spatial;
import com.jme3.scene.shape.Sphere;
import com.jme3.util.SkyFactory;
import java.io.File;
import java.io.IOException;

public class TestSceneLoading extends SimpleApplication {

    final private Sphere sphereMesh = new Sphere(32, 32, 10, false, true);
    final private Geometry sphere = new Geometry("Sky", sphereMesh);
    private static boolean useHttp = false;

    public static void main(String[] args) {
     
        TestSceneLoading app = new TestSceneLoading();
        app.start();
    }

    @Override
    public void simpleUpdate(float tpf){
        sphere.setLocalTranslation(cam.getLocation());
    }

    @Override
    public void simpleInitApp() {
        File file = new File("wildhouse.zip");
        if (!file.exists()) {
            useHttp = true;
        }

        assetManager.registerLocator("C:\\temp\\dragon\\source", FileLocator.class);
        
        this.flyCam.setMoveSpeed(10);

        // load sky
        rootNode.attachChild(SkyFactory.createSky(assetManager, 
                "Textures/Sky/Bright/BrightSky.dds", 
                SkyFactory.EnvMapType.CubeMap));
        
        // create the geometry and attach it
        // load the level from zip or http zip
/*        if (useHttp) {
            assetManager.registerLocator("https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/jmonkeyengine/wildhouse.zip", HttpZipLocator.class);
        } else {
            assetManager.registerLocator("wildhouse.zip", ZipLocator.class);
        }*/
        Spatial scene = assetManager.loadModel("Mon_BlackDragon31_Skeleton.FBX");
        BinaryExporter exporter = BinaryExporter.getInstance();
        File f = new File("C:\\temp\\dragon\\source\\MyModel.j3o");
        try {
            exporter.save(scene, f);
        } catch (IOException ex) {

        }

        scene = assetManager.loadModel("MyModel.j3o");

        AmbientLight al = new AmbientLight();
        scene.addLight(al);

        DirectionalLight sun = new DirectionalLight();
        sun.setDirection(new Vector3f(0.69077975f, -0.6277887f, -0.35875428f).normalizeLocal());
        sun.setColor(ColorRGBA.White.clone().multLocal(2));
        scene.addLight(sun);

        rootNode.attachChild(scene);
    }
}

@capdevon
Copy link
Contributor

capdevon commented Mar 25, 2024

Hi @tonihele ,
you are right, I downloaded the dragon model and ran your code on my local pc getting the following error.

java.lang.NullPointerException
	at com.jme3.scene.debug.SkeletonDebugger.updateLogicalState(SkeletonDebugger.java:99)
	at com.jme3.scene.Node.updateLogicalState(Node.java:239)
	at com.jme3.app.SimpleApplication.update(SimpleApplication.java:268)
	at com.jme3.system.lwjgl.LwjglWindow.runLoop(LwjglWindow.java:631)
	at com.jme3.system.lwjgl.LwjglWindow.run(LwjglWindow.java:721)
	at java.base/java.lang.Thread.run(Thread.java:834)

Effectively jme's stock FBXLoader still uses the old animation system. The strange thing is that it adds the SkeletonDebugger to the model after loading it.

https://github.com/jMonkeyEngine/jmonkeyengine/blob/master/jme3-plugins/src/fbx/java/com/jme3/scene/plugins/fbx/node/FbxNode.java#L525

...
        if (fbxNode.skeleton != null) { 
            jmeSpatial.addControl(new AnimControl(fbxNode.skeleton));
            jmeSpatial.addControl(new SkeletonControl(fbxNode.skeleton));
            
// comment out this code
            /*SkeletonDebugger sd = new SkeletonDebugger("debug", fbxNode.skeleton);
            Material mat = new Material(fbxNode.assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
            mat.getAdditionalRenderState().setWireframe(true);
            mat.getAdditionalRenderState().setDepthTest(false);
            mat.setColor("Color", ColorRGBA.Green);
            sd.setMaterial(mat);
            
            ((Node)jmeSpatial).attachChild(sd);*/
        }

I don't know if the SkeletonDebugger is meant to be serialized or to be used for debugging purposes only in test applications. The solutions could be either to comment out the SkeletonDebugger from the FBXLoader or to fix the SkeletonDebugger as you did.

@tonihele
Copy link
Contributor Author

I don't know if the SkeletonDebugger is meant to be serialized or to be used for debugging purposes only in test applications. The solutions could be either to comment out the SkeletonDebugger from the FBXLoader or to fix the SkeletonDebugger as you did.

SkeletonDebugger is serializable. So IMO it should work, regardless what FBXLoader or anyone else thinks of it. We have no way of deducting how it will be used but it should work flawlessly as it promises to.

FBXLoader is another issue. Yes, it feels that it should not be in the master branch yet since it seems to use some debug data. It should not probably use this SkeletonDebugger. There is also another issue about the FBXLoader using the old animation system.

@capdevon
Copy link
Contributor

capdevon commented Mar 25, 2024

SkeletonDebugger is serializable. So IMO it should work, regardless what FBXLoader or anyone else thinks of it. We have no way of deducting how it will be used but it should work flawlessly as it promises to.

I agree with you.

@scenemax3d scenemax3d added this to the v3.7.0 milestone Mar 30, 2024
@scenemax3d scenemax3d merged commit 1332547 into jMonkeyEngine:master Mar 30, 2024
14 checks passed
scenemax3d pushed a commit that referenced this pull request Mar 30, 2024
Fix SkeletonDebugger deserializing
@tonihele tonihele deleted the bugfix/issue-2226 branch April 2, 2024 15:03
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 this pull request may close these issues.

SkeletonDebugger isn't really savable
3 participants