vasturiano/3d-force-graph-vr

`Entity.setObject3D` was called with an object that was not an instance of THREE.Object3D.

Opened this issue · 5 comments

I am trying to provide the user in Meteor/Vue with a choice between a 3D and VR presentation of the same graph. Switching from 3D to VR view gives the above error.
I have set up a Vue-Sandbox at https://codesandbox.io/s/flamboyant-bohr-6ek32?file=/src/Graph.js
I do not expect the VR to open in the sandbox, but I expect to see the VR button without error - which it does, if 'VR' is the preselected choice.
I am aware that this may be a duplicate of vasturiano/3d-force-graph#77 - it would be great if my sandbox could help provide the code example requested for solving that as well.

@ingodahn thanks for reaching out.

I see that you're providing the exact same data object to both of the components. This may be the reason behind the issue, as some conflicts arise due to the same internal Three objects being shared between two different scenes (and using different renderers, webgl and VR).

Could you try the same example but with completely separate dedicated data objects for each. You could try deep cloning one object from the other, or simply re-generate a data object from scratch at import time.

Let me know if that leads to a different result.

@ingodahn ok thanks for making that new example. 👍

I think I found the resolution to this issue, and it's a weird one. You just need to swap the order of the component imports, so that the import of 3d-force-graph-vr happens before 3d-force-graph.

So simply replace this:

import Component1 from "./Component1.vue";
import Component2 from "./Component2.vue";

with this

import Component2 from "./Component2.vue";
import Component1 from "./Component1.vue";

The explanation behind why this works has to do with the way three declares itself as a global in the system. And to prevent having multiple instances of three being consumed when importing modules that require it, they first verify if there isn't already one defined in the module, before defining a new one. So, whichever import happens first is essentially defining the version of three that will be consumed by the other packages in the application.
Then the other element of this is how the VR module actually imports a customly modified/augmented version of three as it's required by the underlying dependency aframe. This augmented version has methods which are not present in the vanilla version of three consumed by 3d-force-graph. So basically the version imported by 3d-force-graph-vr can satisfy the requirements of 3d-force-graph, but not vice-versa. That's why the import of 3d-force-graph-vr needs to occur first.

@ingodahn the only part that makes a difference is that the module that imports aframe, f.e. 3d-force-graph-vr must always come first.