viromedia / virocore

ViroCore cross-platform AR/VR renderer
MIT License
370 stars 108 forks source link

GLB / GLTF Load model error #303

Closed fzaiatz closed 5 years ago

fzaiatz commented 5 years ago

Environment

Please provide the following information about your environment:

  1. OS: Mac
  2. Version: ViroCore 1.16.0
  3. Device(s): Samsung Galaxy S8

Description

When I try to load a GLB / GLTF model, it's really difficult to understand how it needs to be done properly in order to it to work. Some models work fine, but some other don't. There are 2 different errors:

  1. For some models (like ModelA.glb.zip), the AsyncObject3DListener won't call any callback when I call Object3D.loadModel
  2. For some other models, the onObject3DFailed callback is called with a generic error

If it helps, I'm also attaching a working model named ModelB.glb.zip.

Reproducible Demo

Object3D obj = new Object3D();
obj.loadModel(viroContext, modelUri, Object3D.Type.GLB, new AsyncObject3DListener() {
    public void onObject3DFailed(String error) { }
    public void onObject3DLoaded(Object3D object, Object3D.Type type) { }
});
fzaiatz commented 5 years ago

If it helps, some models from https://github.com/KhronosGroup/glTF-Sample-Models/tree/master/2.0 are having the same issue. I've tested with Damaged Helmet and Boom Box.

My models are being exported from Blender 2.8

dthian commented 5 years ago

Hey @fzaiatz, I've verified that both the ModelA and BoomBox Sample model loads up in ViroCore. I've also verified that the callbacks are triggered as expected.

1) From the sample code above, it looks like you aren't doing anything to verify if the object was loaded or not. How are you making the determination that callbacks aren't getting called when you call Object3D.loadmodel?

2) From the sample code above, it looks like you aren't properly placing / scaling the objects in world space - and as such the models could be literally on top of the camera (and thus you wouldn't see it). Try setting the positions and scales properly in reference to the model's size. You can also always know the size of the model by determining it's bounding box size:

object.getBoundingBox()

Finally, if the issue still persists, could you also try keeping a private member reference to the Object3D within your class (so that we can make a determination to see if it's GC-related.

Hope that helps!

fzaiatz commented 5 years ago

Hi @dthian, thanks for your quick reply. Quick replies from above:

  1. I've removed the code inside each callback method. I'm debugging inside each method to check.
  2. I am, but not from that part of the code. That happens after the Object3D is build, which is my main issue here (I do scale, position and rotate each object after it has been built).

Should I call loadModel from main/background thread? Could it be that the viroContext has a wrong internal state?

Thanks again, F

fzaiatz commented 5 years ago

Also, neither nodeDidFinishCreation nor nodeDidFailOBJLoad seem to be getting called, inside Object3D class.

dthian commented 5 years ago

That's interesting, I've tested # 2 where i perform the scale, position and rotation after the Object3D is built, and still do not see the issue.

1 - Are you loading the 3d models when the View renderer has initialized via onSuccess()? 2 - Are you loading the model on the main thread, if not can you do so? 3 - As i'm not sure what additional variability your debugging techniques may introduce, can you try just printing out logs in the callback and see if they are printed in logcat, instead of verifying through debugging?

fzaiatz commented 5 years ago

Hi again, I think I might be missing something here. Please take a look at the code below:

public class TestActivity extends AppCompatActivity {
    private ViroViewScene mViroView;
    private Scene mScene;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mViroView = new ViroViewScene(this, new ViroViewScene.StartupListener() {
            @Override
            public void onSuccess() {
                displayScene();
            }

            @Override
            public void onFailure(ViroViewScene.StartupError error, String errorMessage) { }
        });
        setContentView(mViroView);
    }

    private void displayScene() {
        mScene = new Scene();

        Object3D obj = new Object3D();
        obj.loadModel(mViroView.getViroContext(), Uri.parse("file:///android_asset/ModelA.glb"), Object3D.Type.GLB, new AsyncObject3DListener() {
            public void onObject3DFailed(String error) {
                Log.d("ViroCore", "Model load error: "+error);
            }
            public void onObject3DLoaded(Object3D object, Object3D.Type type) {
                Log.d("ViroCore", "Model loaded ok");
                mScene.getRootNode().addChildNode(object);
            }
        });

        mViroView.setScene(mScene);
    }

    @Override
    protected void onStart() {
        super.onStart();
        mViroView.onActivityStarted(this);
    }

    @Override
    protected void onResume() {
        super.onResume();
        mViroView.onActivityResumed(this);
    }

    @Override
    protected void onPause(){
        super.onPause();
        mViroView.onActivityPaused(this);
    }

    @Override
    protected void onStop() {
        super.onStop();
        mViroView.onActivityStopped(this);
    }

    @Override
    protected void onDestroy(){
        super.onDestroy();
        mViroView.onActivityDestroyed(this);
    }
}

This is not loading the model. None callback is called. The model is the one I've attached before. Any ideas?

Thanks

fzaiatz commented 5 years ago

Just found out where the issue was: I was adding the Object3D after the model has been built, but it has to be done before calling the loadModel method:

Object3D obj = new Object3D();
mScene.getRootNode().addChildNode(object);
obj.loadModel(mViroView.getViroContext(), Uri.parse("file:///android_asset/ModelA.glb"), Object3D.Type.GLB, new AsyncObject3DListener() {
    public void onObject3DFailed(String error) {
        Log.d("ViroCore", "Model load error: "+error);
    }
    public void onObject3DLoaded(Object3D object, Object3D.Type type) {
        Log.d("ViroCore", "Model loaded ok");
    }
});