0

While testing the import/export between Rhino and Three, I have encountered some problems while visualising a fairly complicated obj file. I exported the obj from Rhino after triangulating the Mesh.

The problem shows indipendently from the material: with no material, with a material or/and with a texture applied within Three.

Jpeg of the geometry I try to import from Rhino vs the result on Three.js: http://goo.gl/1WMGSu

As you can see, there are some weird depth problems, especially depending on the camera position. I made a long research on the topic without finding a solution. I'll append some other topics on StackOverflow that I already have followed.

On my own, I tried also to check and flip the normals within Rhino, with no success.

My script (updated with Gaitat advice):

<!DOCTYPE html>
<html lang="en">
    <head>
        <title>three.js webgl - loaders - OBJ loader</title>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
        <style>
            body {
                font-family: Monospace;
                background-color: #000;
                color: #fff;
                margin: 0px;
                overflow: hidden;
            }
            #info {
                color: #fff;
                position: absolute;
                top: 10px;
                width: 100%;
                text-align: center;
                z-index: 100;
                display:block;
            }
            #info a, .button { color: #f00; font-weight: bold; text-decoration: underline; cursor: pointer }
        </style>
    </head>

    <body>
        <div id="info">
        <a href="http://threejs.org" target="_blank">three.js</a> - OBJLoader test
        </div>

        <script src="../build/three.min.js"></script>
        <script src="js/loaders/OBJLoader.js"></script>

        <script>

            var container;

            var camera, scene, renderer;

            var mouseX = 0, mouseY = 0;

            var windowHalfX = window.innerWidth / 2;
            var windowHalfY = window.innerHeight / 2;


            init();
            animate();


            function init() {

                container = document.createElement( 'div' );
                document.body.appendChild( container );

                camera = new THREE.PerspectiveCamera( 55, window.innerWidth / window.innerHeight, 1, 2500 );
                camera.position.z = 50;

                // scene

                scene = new THREE.Scene();

                var ambient = new THREE.AmbientLight( 0x101030 );
                scene.add( ambient );

                var directionalLight = new THREE.DirectionalLight( 0xffeedd );
                directionalLight.position.set( 0, 0, 1 );
                scene.add( directionalLight );

                // texture

                var manager = new THREE.LoadingManager();
                manager.onProgress = function ( item, loaded, total ) {

                    console.log( item, loaded, total );

                };

                var texture = new THREE.Texture();

                var onProgress = function ( xhr ) {
                    if ( xhr.lengthComputable ) {
                        var percentComplete = xhr.loaded / xhr.total * 100;
                        console.log( Math.round(percentComplete, 2) + '% downloaded' );
                    }
                };

                var onError = function ( xhr ) {
                };


                var loader = new THREE.ImageLoader( manager );
                loader.load( 'textures/UV_Grid_Sm.jpg', function ( image ) {

                    texture.image = image;
                    texture.needsUpdate = true;

                } );

                // model

                loader = new THREE.OBJLoader( manager );
                loader.load( 'obj/RU_obj/testTriangulated_again.obj', function ( object ) {

                    object.traverse( function ( child ) {

                        if ( child instanceof THREE.Mesh ) {

                            child.material.map = texture;

                        }

                    } );

                    object.position.y = - 30;
                    object.scale.x = 0.5;
                    object.scale.y = 0.5;
                    object.scale.z = 0.5;

                    scene.add( object );

                }, onProgress, onError );

                //

                renderer = new THREE.WebGLRenderer();
                renderer.setPixelRatio( window.devicePixelRatio );
                renderer.setSize( window.innerWidth, window.innerHeight );
                container.appendChild( renderer.domElement );

                document.addEventListener( 'mousemove', onDocumentMouseMove, false );

                //

                window.addEventListener( 'resize', onWindowResize, false );

            }

            function onWindowResize() {

                windowHalfX = window.innerWidth / 2;
                windowHalfY = window.innerHeight / 2;

                camera.aspect = window.innerWidth / window.innerHeight;
                camera.updateProjectionMatrix();

                renderer.setSize( window.innerWidth, window.innerHeight );

            }

            function onDocumentMouseMove( event ) {

                mouseX = ( event.clientX - windowHalfX ) / 2;
                mouseY = ( event.clientY - windowHalfY ) / 2;

            }

            //

            function animate() {

                requestAnimationFrame( animate );
                render();

            }

            function render() {

                camera.position.x += ( mouseX - camera.position.x ) * .05;
                camera.position.y += ( - mouseY - camera.position.y ) * .05;
                camera.lookAt( scene.position );

                renderer.render( scene, camera );

            }

        </script>

    </body>
</html>

And here it is my obj file: http://goo.gl/hTD43D.

Thanks in advance.

alelom
  • 2,130
  • 3
  • 26
  • 38
  • I also checked the following, with no results: http://stackoverflow.com/questions/21080619/three-js-webgl-large-spheres-appear-broken-at-intersection – alelom Feb 24 '15 at 19:57
  • They may talk about a similar problem here, I'm not sure: http://stackoverflow.com/questions/16110716/occluded-object-with-three-js-behaving-strangely – alelom Feb 24 '15 at 19:59

1 Answers1

0

Replace this code:

loader.load('obj/RU_obj/testTriangulated.obj', function(geometry) {
    var material =  new THREE.MeshPhongMaterial( { color: 0x00ff00 } );
    geometry.position.y = 0;
    geometry.material = material;
    scene.add(geometry);
});

with

var material = new THREE.MeshPhongMaterial( { color: 0x00ff00 } );
loader.load('obj/RU_obj/testTriangulated.obj', function(object) {
    scene.add( new THREE.Mesh (object.geometry, material) );
});

You cannot assign the material as you did. What I am doing is using the geometry of the loaded object and creating a new mesh which I then add to the scene.

Update

Your object is actually inside out so what you are seeing is the inside of it. So in Rhino you have to change the normals or change the orientation of your polygons. The fix here is to use double sided material. This code has the fix:

<body>
    <div id="info">
    <a href="http://threejs.org" target="_blank">three.js</a> - OBJLoader test
    </div>

    <script src="../build/three.min.js"></script>
    <script src="js/loaders/OBJLoader.js"></script>
    <script src="js/controls/TrackballControls.js"></script>

    <script>

        var container;
        var camera, scene, renderer, controls;
        var mouseX = 0, mouseY = 0;

        init();
        animate();

        function init()
        {
            container = document.createElement( 'div' );
            document.body.appendChild( container );

            camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 2000 );
            camera.position.z = 100;

            // scene

            scene = new THREE.Scene();

            // lights

            var ambient = new THREE.AmbientLight( 0x101030 );
            scene.add( ambient );

            var directionalLight = new THREE.DirectionalLight( 0xffeedd );
            directionalLight.position.set( 0, 0, 1 );
            scene.add( directionalLight );

            // texture

            var manager = new THREE.LoadingManager();
            manager.onProgress = function ( item, loaded, total ) { };

            var texture = new THREE.Texture();

            var loader = new THREE.ImageLoader( manager );
            loader.load( 'textures/UV_Grid_Sm.jpg', function ( image )
            {
                texture.image = image;
                texture.needsUpdate = true;
            } );

            // model

            var loader = new THREE.OBJLoader( manager );
            loader.load( 'testTriangulated.obj', function ( object )
            {
                object.traverse( function ( child )
                {
                    if ( child instanceof THREE.Mesh )
                    {
                        child.material.map = texture;
                        child.material.side = THREE.DoubleSide;
                    }
                } );

                scene.add( object );
            } );

            //

            renderer = new THREE.WebGLRenderer();
            renderer.setPixelRatio( window.devicePixelRatio );
            renderer.setSize( window.innerWidth, window.innerHeight );
            container.appendChild( renderer.domElement );

            // controls
            controls = new THREE.TrackballControls (camera, renderer.domElement);
            controls.rotateSpeed = 1.0;
            controls.zoomSpeed = 1.2;

            window.addEventListener( 'resize', onWindowResize, false );
        }

        function onWindowResize()
        {

            camera.aspect = window.innerWidth / window.innerHeight;
            camera.updateProjectionMatrix();

            renderer.setSize( window.innerWidth, window.innerHeight );
        }

        function animate()
        {
            requestAnimationFrame( animate );
            controls.update();
            renderer.render( scene, camera );
        }

    </script>

</body>
gaitat
  • 12,449
  • 4
  • 52
  • 76
  • Thanks for your answer, I did what you said. Nothing shows up anymore, and the Renderer viewport is reduced to a little rectangle on the upper-left corner of the window. – alelom Feb 25 '15 at 10:35
  • Also, I made some tests with textures, as shown in the jpeg in the provided link. Even with the texture correctly applied (carefully following the example that comes with Three.js, Webgl_loader_mtl) the problem shows up. – alelom Feb 25 '15 at 10:42
  • next time please do not change your original post/code. just add to it. this morning I could not figure out / remember what we were trying to fix. And your edits to the code were not what I suggested. – gaitat Feb 25 '15 at 14:39
  • I'm really sorry - first post, first big mistake. I will never change my first code again. Thank you for your help, I'm gonna try right now. Actually, the first thing I considered was the direction of the normals, so I flipped them in Rhino and tried again with no results. I'll check this double sided material, thanks. – alelom Feb 25 '15 at 15:22
  • fyi: generally it is not a very good idea to use double sided material because you are rendering everything twice and you don't allow webgl to cull triangles based on their normals direction. So fix the model normals or triangle face orientation. – gaitat Feb 25 '15 at 15:38
  • Yes, I know this well from 3Ds Max+Vray. As I said, the first thing I tried was to flip the normal within Rhino, and that didn't work, probably I confused the imported file or whatever. In fact, I was concerned about the behaviour of Three related to the scale of the object, thought it was some more serious problem with the depth buffer or similar. I'll try to fix this issue without having to double side the material in Three. Thanks again. – alelom Feb 25 '15 at 15:57