RobotWebTools / ros3djs

3D Visualization Library for use with the ROS JavaScript Libraries
https://robotwebtools.github.io/ros3djs
Other
368 stars 216 forks source link

Issue using GLTFLoader and multiple THREE instances #314

Open KhaledSharif opened 4 years ago

KhaledSharif commented 4 years ago

I'm facing an issue with rendering a scene that has a mix of URDF (Collada) that was loaded in using ROS3D's ColladaLoader, and GLTF that was loaded in using version r89 of GLTFLoader found here.

This is the console error that occurs when viewing a mixed object scene.

ros3d.js:16779 Uncaught TypeError: Cannot read property 'type' of undefined
    at WebGLIndexedBufferRenderer.setIndex (ros3d.js:16779)
    at WebGLRenderer.renderBufferDirect (ros3d.js:21901)
    at renderObject (ros3d.js:22619)
    at renderObjects (ros3d.js:22590)
    at WebGLRenderer.render (ros3d.js:22354)
    at Viewer.draw (ros3d.js:55821)

The issue might be linked to having multiple instances of THREE loaded in the browser that are fighting over the same resources (see this related issue).

Is there a way of loading GLTF files using the same THREE instance that ros3djs is using?

For reference, here is how I am loading the JS files.

<script src="https://static.robotwebtools.org/threejs/r89/three.js"></script>
<script src="https://static.robotwebtools.org/threejs/r89/ColladaLoader.js"></script>
<script src="https://static.robotwebtools.org/EventEmitter2/0.4.14/eventemitter2.js"></script>
<script src="https://static.robotwebtools.org/roslibjs/0.20.0/roslib.js"></script>
<script src="http://static.robotwebtools.org/ros3djs/current/ros3d.js"></script>

<script src="https://rawcdn.githack.com/mrdoob/three.js/r89/examples/js/loaders/GLTFLoader.js"></script>
yepw commented 3 years ago

I was having the same problem. It seems it happens because of multiple instances of THREE, so I made the following changes to make GLTFLoader work. (It's not a good solution, but it works for me.)

  1. Replace all THREE$1 to THREE in build/ros3d.js (assuming you are importing this file)
  2. Remove var THREE = Object.freeze(...) and var THREE = Object.assign({}, THREE)
KhaledSharif commented 3 years ago

@trusktr what do you think?

trusktr commented 3 years ago

Hey, sorry I just saw this. @KhaledSharif I believe in our project we already eliminated duplicate THREE libraries (notice I deleted the prebuilt/three.js file in the ES Module refactor). If the issue still persists, it may be something else.

trusktr commented 3 years ago

At the time I responded this in my last comment @KhaledSharif, we'd already unduplicated Three libraries, but I think what you described back in 2020 was most likely true.

@yepw My work in #438 exposes THREE as a non-frozen global so that it can be worked with, rather than it being hidden inside the lexical scope ROS3D creates. This allows someone to, for example, load the three/examples/js/loaders/GLTFLoader.js file and it will attach itself to the same THREE instance that ROS3D uses.

When we update to the latest Three.js at some point, we will want to change how we do this: we'll want to instead allow the user to pass THREE in when using global vars, and specify a Three as a peer dependency so that they can install custom versions of three in other cases, plus we should also have a build that includes THREE to make things still easy for some people. Note that with more recent versions of Three.js, their code is 100% compatible with native browser ESM, which makes things easier.