0

Here's a VRML file that I'm trying to display with three.js. When I preview that file in a standalone viewer like view3dscene, it looks correct:

3D rendering of a bolt

However, in Three.js using the example VRMLLoader, the insides of the faces are colored instead of the outsides:

Rendering of the same bolt, but the outside is transparent, revealing the concave back side

Looks clear to me that three.js is reading the correct color information, just applying it to the faces incorrectly. But I'm very new to working with 3D, so I'm not sure where the discrepancy lies or what I can do to fix it.

I'm not doing anything fancy with loading the file; it's just as in the example code:

loader.load('https://75thtrombone.com/links/stack-exchange/2016-09/' + model, function(geometry) {
    scene.add(geometry);
});

Here's a fiddle with my code and a view of the problem. (Zoom in with the mouse wheel, drag to rotate.) Any help, insight, direction towards something to read to learn more, or any other clues at all would be wonderful.

75th Trombone
  • 1,364
  • 15
  • 28
  • Possible duplicate of [Faces invisible from one side using Three.js](http://stackoverflow.com/questions/23640056/faces-invisible-from-one-side-using-three-js) – 75th Trombone Sep 15 '16 at 16:11
  • 1
    looks like you found the answer, I was adjusting the fiddle anyways.... https://jsfiddle.net/z92bx5ay/ The problem is due to winding order of faces in webGL which determines the direction of the face. VRML assumes all faces are solid unless otherwise specified. WebGL makes no such assumption. – Radio Sep 15 '16 at 16:27
  • Thanks! I knew about winding numbers in 2D vector graphics, didn't know that 3D graphics were analogous in that way. – 75th Trombone Sep 15 '16 at 17:15

1 Answers1

2

@Radio is correct. Your winding order is backwards, which causes the faces to point in the wrong direction. It only appears that some of the faces are correct because of the threading on the object.

Here is a fiddle (code below) demonstrating one way to correct the winding order without altering your original object: https://jsfiddle.net/TheJim01/3nr7rakk/

I merely add a function which recurses the object returned by the loader, and forces all materials to draw the back-side of the triangle, rather than the front-side. This only happens once, so it may be good enough in cases of small geometry, but you'll see this slow down as you use larger geometry sets, and complex objects may throw stack errors if they're large enough.

One thing I did not do (as an exercise for the asker) was test this with the latest THREE.js. JSFiddle uses a very old version of THREE.js (JSFiddle uses r54, the current is r80). I recommend either configuring the fiddle to use the latest version and try again, or host the code locally with the latest version. There may be fixes to the VRML loader which resolve the issue you're seeing.

You can use this page as an example of how to link JSFiddle to the latest THREE.js: http://jsfiddle.net/TheJim01/kb7e88vr/ Feel free to fork and modify it.

Updated code: My code is the same as @75th Trombone's except I added/changed the following:

function sideReplacer(obj){
    if(obj.material){
        obj.material.side = THREE.DoubleSide;
    }
    if(obj.children && obj.children.length > 0){
        for(var i in obj.children){
            sideReplacer(obj.children[i]);
        }
    }
}

loader.load('https://75thtrombone.com/links/stack-exchange/2016-09/' + model, function(geometry) {
    sideReplacer(geometry);
    scene.add(geometry);
});
TheJim01
  • 8,411
  • 1
  • 30
  • 54
  • Thanks! My fiddle links three.js externally anyway, so everything here should apply to the latest version. – 75th Trombone Sep 15 '16 at 17:16
  • 1
    @TheJim01 check out the traverse function in Three.js. It works on scenes as well as objects. check out line 48: https://jsfiddle.net/z92bx5ay/ I've just noticed we've used the var name "geometry" which in this case is a misnomer as it does not represent a Three.js Geometry class object, but is an Object3d type. I would change the var name for clarity. – Radio Sep 15 '16 at 17:46